#include "screen.h"
#include "window.h"
+#include "display.h"
#include "gettext.h"
#include <glib.h>
#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);
}
return count;
}
-d_screen_t*
+static d_screen_t*
screen_from_root(d_screen_t *list, int n, xcb_window_t root)
{
int i;
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;
}
}
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;
}
--- /dev/null
+#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();
+}
--- /dev/null
+#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
+++ /dev/null
-#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();
-}
+++ /dev/null
-#ifndef dc__error_h
-#define dc__error_h
-
-#include <xcb/xcb.h>
-
-void error(xcb_connection_t *conn, xcb_generic_error_t *ev);
-
-#endif
#include "screen.h"
-#include "error.h"
+#include "display.h"
#include "window.h"
#include "gettext.h"
#include <string.h>
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) {
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;
}
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);
}
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);
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);
/* 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;
}
#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 */
#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;
}
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;
}
#define dc__window_h
#include <xcb/xcb.h>
+#include <glib.h>
struct d_screen;
int ref;
struct d_screen *sc;
+ gboolean mapped;
+
void (*show)(struct d_window *w);
void (*hide)(struct d_window *w);
} d_window_t;
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