create a d_display_t type that encompasses a connection to a display
authorDana Jansens <danakj@orodu.net>
Tue, 4 Mar 2008 19:19:04 +0000 (14:19 -0500)
committerDana Jansens <danakj@orodu.net>
Tue, 4 Mar 2008 19:19:04 +0000 (14:19 -0500)
dcompmgr.c
display.c [new file with mode: 0644]
display.h [new file with mode: 0644]
error.c [deleted file]
error.h [deleted file]
screen.c
screen.h
window.c
window.h

index c024349..175b522 100644 (file)
@@ -1,5 +1,6 @@
 #include "screen.h"
 #include "window.h"
+#include "display.h"
 #include "gettext.h"
 
 #include <glib.h>
@@ -8,24 +9,28 @@
 #include <string.h>
 #include <xcb/xcb.h>
 
+typedef struct {
+    int foo;
+} d_options_t;
+
 static gint
-all_screens(xcb_connection_t *conn, d_screen_t **list)
+all_screens(d_display_t *dpy, d_screen_t **list)
 {
     static const xcb_setup_t *setup;
     xcb_screen_iterator_t it;
     int count, i;
     d_screen_t sc;
 
-    setup = xcb_get_setup(conn);
+    setup = xcb_get_setup(dpy->conn);
 
     count = i = 0;
     for (it = xcb_setup_roots_iterator(setup); it.rem; xcb_screen_next(&it)) {
         sc.super = *it.data;
-        sc.conn = conn;
+        sc.dpy = dpy;
         sc.num = i++;
         if (screen_register(&sc)) {
             ++count;
-            *list = g_renew(d_screen_t, *list, count);
+            *list = realloc(*list, sizeof(d_screen_t)*count);
             (*list)[count-1] = sc;
             printf(_("managing screen %d\n"), sc.num);
         }
@@ -33,7 +38,7 @@ all_screens(xcb_connection_t *conn, d_screen_t **list)
     return count;
 }
 
-d_screen_t*
+static d_screen_t*
 screen_from_root(d_screen_t *list, int n, xcb_window_t root)
 {
     int i;
@@ -43,32 +48,41 @@ screen_from_root(d_screen_t *list, int n, xcb_window_t root)
     return NULL;
 }
 
+static
+void read_options(int argc, char **argv, d_options_t *opts)
+{
+    opts->foo = argc && argv;
+}
+
 int
 main(int argc, char **argv)
 {
-    xcb_connection_t    *conn;
+    d_display_t         *dpy;
     d_screen_t          *screens = NULL;
     int                  nscreens;
     xcb_generic_event_t *ev;
+    d_options_t          opts;
+
+    read_options(argc, argv, &opts);
 
-    conn = xcb_connect(NULL, NULL);
-    if (!conn) {
+    dpy = display_open(NULL);
+    if (!dpy) {
         printf(_("Unable to connect to display\n"));
         return 1;
     }
 
-    nscreens = all_screens(conn, &screens);
+    nscreens = all_screens(dpy, &screens);
     if (nscreens < 1) {
         printf(_("found no screens to run on\n"));
-        xcb_disconnect(conn);
+        display_unref(dpy);
         return 0;
     }
 
-    while ((ev = xcb_wait_for_event(conn))) {
+    while ((ev = xcb_wait_for_event(dpy->conn))) {
         printf("event %d\n", ev->response_type);
 
         if (!ev->response_type) {
-            error(conn, (xcb_generic_error_t*)ev);
+            display_error(dpy, (xcb_generic_error_t*)ev);
             free(ev);
             continue;
         }
@@ -117,12 +131,38 @@ main(int argc, char **argv)
             }
             break;
         }
+        case XCB_MAP_NOTIFY:
+        {
+            xcb_map_notify_event_t *mev;
+            d_screen_t *sc;
+            d_window_t *w;
+
+            mev = (xcb_map_notify_event_t*)ev;
+            sc = screen_from_root(screens, nscreens, mev->event);
+            if (!sc) break;
+            w = screen_find_window(sc, mev->window);
+            window_show(w);
+            break;
+        }
+        case XCB_UNMAP_NOTIFY:
+        {
+            xcb_unmap_notify_event_t *mev;
+            d_screen_t *sc;
+            d_window_t *w;
+
+            mev = (xcb_unmap_notify_event_t*)ev;
+            sc = screen_from_root(screens, nscreens, mev->event);
+            if (!sc) break;
+            w = screen_find_window(sc, mev->window);
+            window_hide(w);
+            break;
+        }
         default:
             break;
         }
         free(ev);
     }
 
-    xcb_disconnect(conn);
+    display_unref(dpy);
     return 0;
 }
diff --git a/display.c b/display.c
new file mode 100644 (file)
index 0000000..ffca5e6
--- /dev/null
+++ b/display.c
@@ -0,0 +1,112 @@
+#include "display.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <xcb/render.h>
+#include <xcb/xfixes.h>
+#include <xcb/damage.h>
+
+d_display_t*
+display_open(const char *name)
+{
+    d_display_t *dpy = NULL;
+    xcb_connection_t *conn;
+
+    conn = xcb_connect(name, NULL);
+    if (conn) {
+        dpy = malloc(sizeof(d_display_t));
+        dpy->conn = conn;
+        dpy->ref = 1;
+    }
+    return dpy;
+}
+
+void
+display_ref(d_display_t *dpy)
+{
+    ++dpy->ref;
+}
+
+void
+display_unref(d_display_t *dpy)
+{
+    if (dpy && --dpy->ref == 0) {
+        xcb_disconnect(dpy->conn);
+        free(dpy);
+    }
+}
+
+void
+display_error(d_display_t *dpy, xcb_generic_error_t *ev)
+{
+    const int major_opcode = ((xcb_request_error_t*)ev)->major_opcode;
+    const int minor_opcode = ((xcb_request_error_t*)ev)->minor_opcode;
+    const char *name, *req;
+
+    /* XXX check if we should ignore it (ev->full_sequence) */
+
+    (void)dpy;
+
+    name = NULL;
+    switch (ev->error_code) {
+    case XCB_REQUEST:   name = "BadRequest";   break;
+    case XCB_VALUE:     name = "BadValue";     break;
+    case XCB_WINDOW:    name = "BadWindow";    break;
+    case XCB_PIXMAP:    name = "BadPixmap";    break;
+    case XCB_MATCH:     name = "BadMatch";     break;
+    case XCB_DRAWABLE:  name = "BadDrawable";  break;
+    case XCB_G_CONTEXT: name = "BadGC";        break;
+    default: break;
+    }
+    if (!name)
+        switch (ev->error_code - dpy->fixes_error) {
+        case XCB_XFIXES_BAD_REGION: name = "BadRegion"; break;
+        default: break;
+        }
+    if (!name)
+        switch (ev->error_code - dpy->damage_error) {
+        case XCB_DAMAGE_BAD_DAMAGE: name = "BadDamage"; break;
+        default: break;
+        }
+    if (!name)
+        switch (ev->error_code - dpy->render_error) {
+        case XCB_RENDER_PICT_FORMAT: name = "BadPictFormat"; break;
+        case XCB_RENDER_PICT_OP:     name = "BadPictOp"; break;
+        case XCB_RENDER_PICTURE:     name = "BadPicture"; break;
+        case XCB_RENDER_GLYPH_SET:   name = "BadGlyphSet"; break;
+        case XCB_RENDER_GLYPH:       name = "BadGlyph"; break;
+        default: break;
+        }
+
+    if (major_opcode <= 127)
+        switch (major_opcode) {
+        case 1:  req = "CreateWindow";           break;
+        case 2:  req = "ChangeWindowAttributes"; break;
+        case 3:  req = "GetWindowAttributes";    break;
+        case 14: req = "GetGeometry";            break;
+        case 15: req = "QueryTree";              break;
+        case 18: req = "ChangeProperty";         break;
+        case 20: req = "GetProperty";            break;
+        case 22: req = "SetSelectionOwner";      break;
+        case 23: req = "GetSelectionOwner";      break;
+        case 53: req = "CreatePixmap";           break;
+        case 54: req = "FreePixmap";             break;
+        case 55: req = "CreateGC";               break;
+        case 56: req = "ChangeGC";               break;
+        case 60: req = "FreeGC";                 break;
+        case 72: req = "PutImage";               break;
+        default: break; 
+        }
+
+    if (name && req)
+        printf("XError: %s %s!\n",
+               name, req);
+    else if (name)
+        printf("XError: %s major opcode %d minor opcode %d!\n",
+               name, major_opcode, minor_opcode);
+    else
+        printf("XError: code %d major opcode %d minor opcode %d!\n",
+               ev->error_code, major_opcode, minor_opcode);
+
+    abort();
+}
diff --git a/display.h b/display.h
new file mode 100644 (file)
index 0000000..f46ed46
--- /dev/null
+++ b/display.h
@@ -0,0 +1,22 @@
+#ifndef dc__display_h
+#define dc__display_h
+
+#include <xcb/xcb.h>
+
+typedef struct d_display {
+    xcb_connection_t *conn;
+    int               ref;
+
+    int fixes_error;
+    int damage_error;
+    int render_error;
+} d_display_t;
+
+d_display_t* display_open(const char *name);
+
+void display_ref(d_display_t *dpy);
+void display_unref(d_display_t *dpy);
+
+void display_error(d_display_t *dpy, xcb_generic_error_t *ev);
+
+#endif
diff --git a/error.c b/error.c
deleted file mode 100644 (file)
index 918f95d..0000000
--- a/error.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "error.h"
-#include <stdlib.h>
-#include <stdio.h>
-
-void
-error(xcb_connection_t *conn, xcb_generic_error_t *ev)
-{
-    (void)conn; (void)ev;
-    printf("error!\n");
-    abort();
-}
diff --git a/error.h b/error.h
deleted file mode 100644 (file)
index 3a8be4c..0000000
--- a/error.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef dc__error_h
-#define dc__error_h
-
-#include <xcb/xcb.h>
-
-void error(xcb_connection_t *conn, xcb_generic_error_t *ev);
-
-#endif
index 873e96f..533f07f 100644 (file)
--- a/screen.c
+++ b/screen.c
@@ -1,5 +1,5 @@
 #include "screen.h"
-#include "error.h"
+#include "display.h"
 #include "window.h"
 #include "gettext.h"
 #include <string.h>
@@ -28,19 +28,19 @@ screen_register(d_screen_t *sc)
     uint32_t event_mask;
     gboolean taken, ret;
 
-    w = xcb_generate_id(sc->conn);
+    w = xcb_generate_id(sc->dpy->conn);
     event_mask = SELECTION_MASK;
-    xcb_create_window(sc->conn, XCB_COPY_FROM_PARENT, w, sc->super.root,
+    xcb_create_window(sc->dpy->conn, XCB_COPY_FROM_PARENT, w, sc->super.root,
                       0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
                       sc->super.root_visual, XCB_CW_EVENT_MASK, &event_mask);
 
     name = g_strdup_printf("_NET_WM_CM_S%d", sc->num);
-    ack = xcb_intern_atom(sc->conn, FALSE, strlen(name), name);
-    arep = xcb_intern_atom_reply(sc->conn, ack, NULL);
+    ack = xcb_intern_atom(sc->dpy->conn, FALSE, strlen(name), name);
+    arep = xcb_intern_atom_reply(sc->dpy->conn, ack, NULL);
     g_free(name);
 
-    sck = xcb_get_selection_owner(sc->conn, arep->atom);
-    srep = xcb_get_selection_owner_reply(sc->conn, sck, NULL);
+    sck = xcb_get_selection_owner(sc->dpy->conn, arep->atom);
+    srep = xcb_get_selection_owner_reply(sc->dpy->conn, sck, NULL);
     taken = !!srep->owner;
     free(srep);
     if (taken) {
@@ -56,21 +56,21 @@ screen_register(d_screen_t *sc)
 
         time = screen_timestamp(sc);
 
-        xcb_grab_server(sc->conn);
-        xcb_set_selection_owner(sc->conn, w, arep->atom, time);
-        sck = xcb_get_selection_owner(sc->conn, arep->atom);
-        srep = xcb_get_selection_owner_reply(sc->conn, sck, NULL);
+        xcb_grab_server(sc->dpy->conn);
+        xcb_set_selection_owner(sc->dpy->conn, w, arep->atom, time);
+        sck = xcb_get_selection_owner(sc->dpy->conn, arep->atom);
+        srep = xcb_get_selection_owner_reply(sc->dpy->conn, sck, NULL);
         taken = srep->owner == w;
         if (taken) {
             screen_init(sc);
             ret = TRUE;
         }
         else {
-            xcb_destroy_window(sc->conn, w);
+            xcb_destroy_window(sc->dpy->conn, w);
             ret = FALSE;
         }
-        xcb_ungrab_server(sc->conn);
-        xcb_flush(sc->conn);
+        xcb_ungrab_server(sc->dpy->conn);
+        xcb_flush(sc->dpy->conn);
     }
     return ret;
 }
@@ -89,14 +89,14 @@ screen_init(d_screen_t *sc)
     sc->winhash = g_hash_table_new((GHashFunc)window_hash,
                                    (GCompareFunc)window_compare);
 
-//    xcb_composite_redirect_subwindows(sc->conn, sc->super.root,
+//    xcb_composite_redirect_subwindows(sc->dpy->conn, sc->super.root,
 //                                      XCB_COMPOSITE_REDIRECT_MANUAL);
 
     mask = SELECTION_MASK;
-    xcb_change_window_attributes(sc->conn, sc->selwin,
+    xcb_change_window_attributes(sc->dpy->conn, sc->selwin,
                                  XCB_CW_EVENT_MASK, &mask);
     mask = ROOT_MASK;
-    xcb_change_window_attributes(sc->conn, sc->super.root,
+    xcb_change_window_attributes(sc->dpy->conn, sc->super.root,
                                  XCB_CW_EVENT_MASK, &mask);
 }
 
@@ -110,13 +110,13 @@ screen_add_window(d_screen_t *sc, xcb_window_t wid)
     w = window_new(wid, sc);
     g_hash_table_insert(sc->winhash, &w->id, w);
 
-    printf("added window 0x%x\n", w->id);
+    printf("screen added window 0x%x\n", w->id);
 }
 
 void
 screen_remove_window(d_screen_t *sc, struct d_window *w)
 {
-    printf("removed window 0x%x\n", w->id);
+    printf("screen removed window 0x%x\n", w->id);
 
     g_hash_table_remove(sc->winhash, &w->id);
     window_unref(w);
@@ -134,13 +134,13 @@ screen_timestamp(d_screen_t *sc)
     xcb_void_cookie_t ck;
     xcb_timestamp_t   time;
 
-    ck = xcb_change_property(sc->conn, XCB_PROP_MODE_REPLACE, sc->selwin,
+    ck = xcb_change_property(sc->dpy->conn, XCB_PROP_MODE_REPLACE, sc->selwin,
                              sc->selatom, sc->selatom, 32, 0, NULL);
-    xcb_flush(sc->conn);
+    xcb_flush(sc->dpy->conn);
     while (1) {
         xcb_generic_event_t *ev;
 
-        ev = xcb_wait_for_event(sc->conn);
+        ev = xcb_wait_for_event(sc->dpy->conn);
         if (!ev) {
             printf(_("IO error\n"));
             exit(0);
@@ -148,7 +148,7 @@ screen_timestamp(d_screen_t *sc)
 
         /* expect errors.. */
         if (!ev->response_type) {
-            error(sc->conn, (xcb_generic_error_t*)ev);
+            display_error(sc->dpy, (xcb_generic_error_t*)ev);
             free(ev);
             continue;
         }
index 4abfcb7..96b1ab1 100644 (file)
--- a/screen.h
+++ b/screen.h
@@ -5,11 +5,12 @@
 #include <glib.h>
 
 struct d_window;
+struct d_display;
 
 /* inherits from xcb_screen_t */
 typedef struct d_screen {
     xcb_screen_t      super;
-    xcb_connection_t *conn;
+    struct d_display *dpy;
     int               num;
 
     xcb_window_t      selwin;  /* for the selection */
index 269b60d..4d9bb7b 100644 (file)
--- a/window.c
+++ b/window.c
@@ -1,23 +1,24 @@
 #include "window.h"
-#include <glib.h>
-
-static void window_show(d_window_t *w);
-static void window_hide(d_window_t *w);
+#include <stdlib.h>
+#include <stdio.h>
 
 d_window_t*
 window_new(xcb_window_t id, struct d_screen *sc)
 {
     d_window_t *w;
 
-    w = g_new(d_window_t, 1);
+    w = malloc(sizeof(d_window_t));
     w->id = id;
     w->ref = 1;
     w->sc = sc;
+    w->mapped = FALSE;
 
     /* default functions */
     w->show = window_show;
     w->hide = window_hide;
 
+    printf("new window 0x%x\n", w->id);
+
     return w;
 }
 
@@ -31,16 +32,26 @@ void
 window_unref(d_window_t *w)
 {
     if (w && --w->ref == 0) {
-        g_free(w);
+        free(w);
     }
 }
 
-static void
+void
 window_show(d_window_t *w)
 {
+    if (w->mapped) return;
+
+    printf("show window 0x%x\n", w->id);
+
+    w->mapped = TRUE;
 }
 
-static void
+void
 window_hide(d_window_t *w)
 {
+    if (!w->mapped) return;
+
+    printf("hide window 0x%x\n", w->id);
+
+    w->mapped = FALSE;
 }
index e03623b..211fd8e 100644 (file)
--- a/window.h
+++ b/window.h
@@ -2,6 +2,7 @@
 #define dc__window_h
 
 #include <xcb/xcb.h>
+#include <glib.h>
 
 struct d_screen;
 
@@ -10,6 +11,8 @@ typedef struct d_window {
     int              ref;
     struct d_screen *sc;
 
+    gboolean         mapped;
+
     void (*show)(struct d_window *w);
     void (*hide)(struct d_window *w);
 } d_window_t;
@@ -19,5 +22,7 @@ d_window_t* window_new(xcb_window_t id, struct d_screen *sc);
 void window_ref(d_window_t *w);
 void window_unref(d_window_t *w);
 
+void window_show(d_window_t *w);
+void window_hide(d_window_t *w);
 
 #endif