use the list for holding all the managed screens in the display. limit the number...
authorDana Jansens <danakj@orodu.net>
Wed, 5 Mar 2008 01:01:31 +0000 (20:01 -0500)
committerDana Jansens <danakj@orodu.net>
Wed, 5 Mar 2008 01:01:31 +0000 (20:01 -0500)
dcompmgr.c
display.c
display.h
list.c
list.h
render.c
screen.c
screen.h
time.c
time.h

index 2145dcb..f441f8a 100644 (file)
@@ -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);
index a03e7ab..ef2ba70 100644 (file)
--- a/display.c
+++ b/display.c
@@ -1,5 +1,6 @@
 #include "display.h"
 #include "screen.h"
+#include "list.h"
 #include "gettext.h"
 #include <stdlib.h>
 #include <assert.h>
@@ -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];
-}
index ab40200..00bb8b1 100644 (file)
--- a/display.h
+++ b/display.h
@@ -5,6 +5,8 @@
 
 #include <glib.h>
 
+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 (file)
--- 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 (file)
--- 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);
index f25ddc0..1843cc4 100644 (file)
--- 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);
index 55ee082..f86f719 100644 (file)
--- 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;
+}
index 2af3c98..e0f6508 100644 (file)
--- 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 (file)
--- 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 (file)
--- 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