From 1f1e7911fe85d640cb95fd107753a50d5ad6b1f3 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 4 Mar 2008 20:01:31 -0500 Subject: [PATCH] use the list for holding all the managed screens in the display. limit the number of redraws to 60/second, but it's not working right atm, the select goes forever sometimes --- dcompmgr.c | 64 +++++++++++++++++++++++++++++++++---------- display.c | 50 +++++++++++++++------------------- display.h | 6 ++-- list.c | 16 +++++++++++ list.h | 1 + render.c | 2 +- screen.c | 80 +++++++++++++++++++++++++++++++++++++----------------- screen.h | 12 ++++++-- time.c | 22 +++++++++++++-- time.h | 1 + 10 files changed, 178 insertions(+), 76 deletions(-) diff --git a/dcompmgr.c b/dcompmgr.c index 2145dcb..f441f8a 100644 --- a/dcompmgr.c +++ b/dcompmgr.c @@ -1,5 +1,6 @@ #include "screen.h" #include "window.h" +#include "list.h" #include "display.h" #include "gettext.h" #include "time.h" @@ -33,7 +34,7 @@ event(d_display_t *dpy) if (!ev->response_type) { display_error(dpy, (xcb_generic_error_t*)ev); free(ev); - return; + continue; } switch (ev->response_type) { @@ -60,6 +61,8 @@ event(d_display_t *dpy) w = screen_find_window(sc, dev->window); sc->window_hide(w); screen_remove_window(sc, w); + printf("** refresh needed **\n"); + screen_refresh(sc); break; } case XCB_REPARENT_NOTIFY: @@ -116,13 +119,13 @@ event(d_display_t *dpy) static void paint(d_display_t *dpy) { - int i; + d_list_it_t *it; struct timeval now; gettimeofday(&now, NULL); - for (i = 0; i < dpy->nscreens; ++i) { - d_screen_t *sc = display_screen_n(dpy, i); + for (it = list_top(dpy->screens); it; it = it->next) { + d_screen_t *sc = it->data; if (time_compare(&sc->next_repaint, &now) <= 0) sc->screen_paint(sc); @@ -144,18 +147,51 @@ run(d_display_t *dpy) quit = FALSE; while (!quit) { - int r; + struct timeval next, now, *wait; + int r, npaint; + d_list_it_t *it; + + npaint = 0; + for (it = list_top(dpy->screens); it; it = it->next) { + d_screen_t *sc = it->data; + if (sc->need_repaint && + (!npaint || time_compare(&sc->next_repaint, &next) < 0)) + { + next = sc->next_repaint; + ++npaint; + } + } + + gettimeofday(&now, 0); - r = select(max+1, &fds, NULL, NULL, NULL); + printf("* loop paint %d *\n", npaint); + + if (!npaint) + /* wait forever, there is nothing that needs drawing */ + wait = NULL; + else if (time_compare(&next, &now) > 0) { + /* wait until the next allowed redraw time */ + time_difference(&next, &now, &next); + wait = &next; + } + else { + /* don't wait cuz a redraw is due now already */ + next.tv_sec = 0; + next.tv_usec = 1; + wait = &next; + } + + r = select(max+1, &fds, NULL, NULL, wait); if (r < 0) printf("select error\n"); - else if (r == 0) + else if (r == 0) { printf("select timeout\n"); + paint(dpy); + } else { printf("select data\n"); /*if (FD_ISSET(dpy->fd, &fds))*/ { event(dpy); - paint(dpy); } } @@ -167,10 +203,10 @@ run(d_display_t *dpy) static void setup_functions(d_display_t *dpy) { - int i; + d_list_it_t *it; - for (i = 0; i < dpy->nscreens; ++i) { - d_screen_t *sc = display_screen_n(dpy, i); + for (it = list_top(dpy->screens); it; it = it->next) { + d_screen_t *sc = it->data; screen_setup_default_functions(sc); /* these can be plugins.. */ @@ -181,10 +217,10 @@ setup_functions(d_display_t *dpy) static void cleanup_functions(d_display_t *dpy) { - int i; + d_list_it_t *it; - for (i = 0; i < dpy->nscreens; ++i) { - d_screen_t *sc = display_screen_n(dpy, i); + for (it = list_top(dpy->screens); it; it = it->next) { + d_screen_t *sc = it->data; /* these can be plugins.. */ render_free(sc); diff --git a/display.c b/display.c index a03e7ab..ef2ba70 100644 --- a/display.c +++ b/display.c @@ -1,5 +1,6 @@ #include "display.h" #include "screen.h" +#include "list.h" #include "gettext.h" #include #include @@ -175,8 +176,7 @@ display_open(const char *name) dpy->conn = conn; dpy->ref = 1; dpy->fd = xcb_get_file_descriptor(conn); - dpy->screens = NULL; - dpy->nscreens = 0; + dpy->screens = list_new(); query_statics(dpy); } @@ -193,12 +193,13 @@ void display_unref(d_display_t *dpy) { if (dpy && --dpy->ref == 0) { - int i; + d_list_it_t *it; + xcb_disconnect(dpy->conn); - for (i = 0; i < dpy->nscreens; ++i) - screen_free(&dpy->screens[i]); - free(dpy->screens); + for (it = list_top(dpy->screens); it; it = it->next) + screen_unref(it->data); + list_unref(dpy->screens); free(dpy); } } @@ -284,40 +285,33 @@ display_claim_screens(d_display_t *dpy) static const xcb_setup_t *setup; xcb_screen_iterator_t it; int i; - d_screen_t sc; + d_screen_t *sc; setup = xcb_get_setup(dpy->conn); i = 0; for (it = xcb_setup_roots_iterator(setup); it.rem; xcb_screen_next(&it)) { - sc.super = *it.data; - sc.dpy = dpy; - sc.num = i++; - if (screen_register(dpy, i, &sc)) { - ++dpy->nscreens; - dpy->screens = realloc(dpy->screens, - sizeof(d_screen_t)*dpy->nscreens); - dpy->screens[dpy->nscreens-1] = sc; - printf(_("managing screen %d\n"), sc.num); + sc = screen_new(dpy, i++, it.data); + if (screen_register(sc)) { + list_append(dpy->screens, sc); + printf(_("managing screen %d\n"), sc->num); } + else + screen_unref(sc); } - return dpy->nscreens; + return list_length(dpy->screens); } d_screen_t* display_screen_from_root(d_display_t *dpy, xcb_window_t root) { - int i; - for (i = 0; i < dpy->nscreens; ++i) - if (dpy->screens[i].super.root == root) - return &dpy->screens[i]; + d_list_it_t *it; + + for (it = list_top(dpy->screens); it; it = it->next) { + d_screen_t *sc = it->data; + if (sc->super.root == root) + return sc; + } assert(0); return NULL; } - -struct d_screen* -display_screen_n(d_display_t *dpy, int n) -{ - assert(n >= 0 && n < dpy->nscreens); - return &dpy->screens[n]; -} diff --git a/display.h b/display.h index ab40200..00bb8b1 100644 --- a/display.h +++ b/display.h @@ -5,6 +5,8 @@ #include +struct d_list; + typedef struct d_display_ext { gboolean present; int error; @@ -18,8 +20,7 @@ typedef struct d_display { xcb_connection_t *conn; int ref; int fd; - struct d_screen *screens; - int nscreens; + struct d_list *screens; d_display_ext_t xfixes; d_display_ext_t render; @@ -60,7 +61,6 @@ void display_unref(d_display_t *dpy); int display_claim_screens(d_display_t *dpy); struct d_screen* display_screen_from_root(d_display_t *dpy, xcb_window_t root); -struct d_screen* display_screen_n(d_display_t *dpy, int n); void display_error(d_display_t *dpy, xcb_generic_error_t *ev); diff --git a/list.c b/list.c index 2557bc9..49a9f78 100644 --- a/list.c +++ b/list.c @@ -57,6 +57,22 @@ list_prepend(d_list_t *list, void *data) return n; } +d_list_it_t* +list_append(d_list_t *list, void *data) +{ + d_list_it_t *n = malloc(sizeof(d_list_it_t)); + n->data = data; + + n->prev = list->bottom; + n->next = NULL; + if (n->prev) n->prev->next = n; + + list->bottom = n; + if (!list->top) list->top = n; + ++list->len; + return n; +} + void list_delete_link(d_list_t *list, d_list_it_t *pos) { diff --git a/list.h b/list.h index 737f68d..d96c37e 100644 --- a/list.h +++ b/list.h @@ -19,6 +19,7 @@ void list_ref(d_list_t *list); void list_unref(d_list_t *list); d_list_it_t* list_prepend(d_list_t *list, void *data); +d_list_it_t* list_append(d_list_t *list, void *data); void list_delete_link(d_list_t *list, d_list_it_t *pos); void list_move_before(d_list_t *list, d_list_it_t *move, d_list_it_t *before); void list_remove(d_list_t *list, void *data); diff --git a/render.c b/render.c index f25ddc0..1843cc4 100644 --- a/render.c +++ b/render.c @@ -34,7 +34,7 @@ render_paint_screen(d_screen_t *sc) { data_t *d = screen_find_plugin_data(sc, PLUGIN_NAME); - printf("painting\n"); + printf("-- painting --\n"); /* call the function we replaced in the chain */ d->screen_paint(sc); diff --git a/screen.c b/screen.c index 55ee082..f86f719 100644 --- a/screen.c +++ b/screen.c @@ -20,8 +20,56 @@ static xcb_timestamp_t screen_timestamp(d_screen_t *sc); static void screen_add_existing_windows(d_screen_t *sc); static void screen_set_next_repaint(d_screen_t *sc); +static guint +xcb_window_hash(xcb_window_t *w) { return *w; } + +static gboolean +xcb_window_equal(xcb_window_t *w1, xcb_window_t *w2) { return *w1 == *w2; } + + +d_screen_t* +screen_new(struct d_display *dpy, int num, xcb_screen_t *xcb) +{ + d_screen_t *sc; + + sc = malloc(sizeof(d_screen_t)); + sc->super = *xcb; + sc->ref = 1; + sc->dpy = dpy; + sc->num = num; + + gettimeofday(&sc->next_repaint, NULL); + sc->need_repaint = TRUE; + + sc->winhash = g_hash_table_new((GHashFunc)xcb_window_hash, + (GEqualFunc)xcb_window_equal); + sc->stacking = list_new(); + sc->plugin_data = g_hash_table_new_full((GHashFunc)g_str_hash, + (GEqualFunc)g_str_equal, + g_free, NULL); + + return sc; +} + +void +screen_ref(d_screen_t *sc) +{ + ++sc->ref; +} + +void +screen_unref(d_screen_t *sc) +{ + if (sc && --sc->ref == 0) { + g_hash_table_unref(sc->winhash); + list_unref(sc->stacking); + g_hash_table_unref(sc->plugin_data); + free(sc); + } +} + gboolean -screen_register(struct d_display *dpy, int num, d_screen_t *sc) +screen_register(d_screen_t *sc) { char *name; xcb_window_t w; @@ -32,8 +80,6 @@ screen_register(struct d_display *dpy, int num, d_screen_t *sc) uint32_t event_mask; gboolean taken, ret; - sc->dpy = dpy; - sc->num = num; w = xcb_generate_id(sc->dpy->conn); event_mask = SELECTION_MASK; xcb_create_window(sc->dpy->conn, XCB_COPY_FROM_PARENT, w, sc->super.root, @@ -83,12 +129,6 @@ screen_register(struct d_display *dpy, int num, d_screen_t *sc) return ret; } -static guint -xcb_window_hash(xcb_window_t *w) { return *w; } - -static gboolean -xcb_window_equal(xcb_window_t *w1, xcb_window_t *w2) { return *w1 == *w2; } - static gboolean screen_init(d_screen_t *sc) { @@ -133,25 +173,9 @@ screen_init(d_screen_t *sc) xcb_change_window_attributes(sc->dpy->conn, sc->super.root, XCB_CW_EVENT_MASK, &mask); - gettimeofday(&sc->next_repaint, NULL); - - sc->winhash = g_hash_table_new((GHashFunc)xcb_window_hash, - (GEqualFunc)xcb_window_equal); - sc->stacking = list_new(); - sc->plugin_data = g_hash_table_new_full((GHashFunc)g_str_hash, - (GEqualFunc)g_str_equal, - g_free, NULL); - return TRUE; } -void screen_free(d_screen_t *sc) -{ - g_hash_table_unref(sc->winhash); - list_unref(sc->stacking); - g_hash_table_unref(sc->plugin_data); -} - void screen_add_window(d_screen_t *sc, xcb_window_t wid) { @@ -256,6 +280,7 @@ screen_set_next_repaint(d_screen_t *sc) gettimeofday(&sc->next_repaint, NULL); /* add time for the refresh rate (60 hz) */ time_add(&sc->next_repaint, 1000000/60); + sc->need_repaint = FALSE; } void @@ -286,3 +311,8 @@ screen_remove_plugin_data(d_screen_t *sc, const char *key) { g_hash_table_remove(sc->plugin_data, key); } + +void screen_refresh(d_screen_t *sc) +{ + sc->need_repaint = TRUE; +} diff --git a/screen.h b/screen.h index 2af3c98..e0f6508 100644 --- a/screen.h +++ b/screen.h @@ -12,6 +12,7 @@ struct d_list; /* inherits from xcb_screen_t */ typedef struct d_screen { xcb_screen_t super; + int ref; struct d_display *dpy; int num; @@ -21,6 +22,7 @@ typedef struct d_screen { xcb_window_t overlay; struct timeval next_repaint; + gboolean need_repaint; GHashTable *winhash; struct d_list *stacking; @@ -32,11 +34,15 @@ typedef struct d_screen { void (*window_become_zombie)(struct d_window *w); } d_screen_t; +d_screen_t* screen_new(struct d_display *dpy, int num, xcb_screen_t *xcb); + +void screen_ref(d_screen_t *sc); +void screen_unref(d_screen_t *sc); + /*! Tries to register on the screen given by @sc. If it succeeds, it fills in @sc and returns TRUE, otherwise it returns FALSE. */ -gboolean screen_register(struct d_display *dpy, int num, d_screen_t *sc); -void screen_free(d_screen_t *sc); +gboolean screen_register(d_screen_t *sc); void screen_add_window(d_screen_t *sc, xcb_window_t wid); void screen_remove_window(d_screen_t *sc, struct d_window *w); @@ -52,4 +58,6 @@ void screen_add_plugin_data(d_screen_t *sc, const char *key, void *data); void* screen_find_plugin_data(d_screen_t *sc, const char *key); void screen_remove_plugin_data(d_screen_t *sc, const char *key); +void screen_refresh(d_screen_t *sc); + #endif diff --git a/time.c b/time.c index 38b60b2..a90b1cd 100644 --- a/time.c +++ b/time.c @@ -1,9 +1,8 @@ #include "time.h" -void -time_add(struct timeval *tv, long microseconds) +static inline void +time_fix(struct timeval *tv) { - tv->tv_usec += microseconds; while (tv->tv_usec >= 1000000) { tv->tv_usec -= 1000000; ++tv->tv_sec; @@ -14,6 +13,13 @@ time_add(struct timeval *tv, long microseconds) } } +void +time_add(struct timeval *tv, long microseconds) +{ + tv->tv_usec += microseconds; + time_fix(tv); +} + long time_compare(struct timeval *a, struct timeval *b) { @@ -21,3 +27,13 @@ time_compare(struct timeval *a, struct timeval *b) if ((r = a->tv_sec - b->tv_sec)) return r; return a->tv_usec - b->tv_usec; } + +void +time_difference(struct timeval *a, struct timeval *b, struct timeval *r) +{ + struct timeval v; + v.tv_sec = a->tv_sec - b->tv_sec; + v.tv_usec = a->tv_usec - b->tv_usec; + time_fix(&v); + *r = v; +} diff --git a/time.h b/time.h index d8ac405..24cd3f0 100644 --- a/time.h +++ b/time.h @@ -5,5 +5,6 @@ void time_add(struct timeval *tv, long microseconds); long time_compare(struct timeval *a, struct timeval *b); +void time_difference(struct timeval *a, struct timeval *b, struct timeval *r); #endif -- 2.34.1