diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2011-02-25 12:20:48 -0500 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2011-02-25 12:20:48 -0500 |
commit | 31869cd166977c963b1a7b9eeb68b42e28613e67 (patch) | |
tree | 270c1776122dc68cc4d9dcfc78cfac4606255094 | |
parent | 2c37aa64b50d8c76fa96f92875a20de1d500f6fc (diff) |
window.c
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | main.c | 226 | ||||
-rw-r--r-- | ocm.h | 41 | ||||
-rw-r--r-- | utils.c | 29 | ||||
-rw-r--r-- | window.c | 18 |
5 files changed, 245 insertions, 71 deletions
@@ -1,7 +1,7 @@ EXTRA_CFLAGS = -g -Wall -fno-omit-frame-pointer `pkg-config --cflags x11 xrender xcomposite xdamage` EXTRA_LDFLAGS = `pkg-config --libs x11 xrender xcomposite xdamage` -sources := main.c utils.c ocm.h +sources := main.c utils.c window.c ocm.h %.o: %.c $(CC) -c $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ @@ -27,21 +27,147 @@ get_time (ocm_app_t *app) if (app->timestamp == CurrentTime) { XEvent event; - + /* Using the property XA_PRIMARY because it's safe; nothing * would use it as a property. The type doesn't matter. */ XChangeProperty (app->display, app->no_focus, XA_PRIMARY, XA_STRING, 8, PropModeAppend, NULL, 0); - + XWindowEvent (app->display, app->no_focus, PropertyChangeMask, &event); - + app->timestamp = event.xproperty.time; } - + return app->timestamp; } +static ocm_window_t * +app_find_xwindow (ocm_app_t *app, Window xwindow) +{ + ocm_window_t *window = app->windows; + + while (window) + { + if (window->xwindow == xwindow) + return window; + + window = window->next; + } +} + +static void +app_unmanage_xwindow (ocm_app_t *app, Window xwindow) +{ + ocm_window_t *prev, *window; + + prev = NULL; + window = app->windows; + while (window) + { + if (window->xwindow == xwindow) + { + if (prev) + prev->next = window->next; + else + app->windows = window->next; + + ocm_window_free (window); + return; + } + + prev = window; + window = window->next; + } +} + +static void +app_manage_window (ocm_app_t *app, Window window) +{ + XWindowAttributes attrs; + + XGrabServer (app->display); + + if (XGetWindowAttributes (app->display, window, &attrs)) + { + ocm_window_t *owindow = ocm_window_new (app, window); + + owindow->next = app->windows; + app->windows = owindow; + } + + XUngrabServer (app->display); +} + +static Window +create_offscreen_window (ocm_app_t *app) +{ + XSetWindowAttributes attrs; + + attrs.override_redirect = TRUE; + attrs.event_mask = NoEventMask; + + return XCreateWindow (app->display, + app->root, + -100, -100, 1, 1, + 0, + CopyFromParent, + CopyFromParent, + (Visual *)CopyFromParent, + CWOverrideRedirect | CWEventMask, + &attrs); + +} + +static void +acquire_manager_selection (ocm_app_t * app, + const char * selection, + Window new_owner, + bool replace) +{ + Atom atom = XInternAtom (app->display, selection, FALSE); + Window existing; + XSetWindowAttributes attr; + uint32_t managed_since; + XClientMessageEvent event; + + existing = XGetSelectionOwner (app->display, atom); + if (existing) + { + if (!replace) + ocm_error ("Could not acquire %s - try -r", selection); + + attr.event_mask = StructureNotifyMask; + XChangeWindowAttributes (app->display, existing, CWEventMask, &attr); + } + + managed_since = get_time (app); + + XSetSelectionOwner (app->display, atom, app->no_focus, managed_since); + + /* Announce ourself as the new owner */ + event.type = ClientMessage; + event.window = app->root; + event.message_type = XInternAtom (app->display, "MANAGER", FALSE); + event.format = 32; + event.data.l[0] = managed_since; + event.data.l[1] = atom; + + XSendEvent (app->display, app->root, FALSE, + StructureNotifyMask, (XEvent*)&event); + + if (existing) + { + XEvent event; + + do + { + XWindowEvent (app->display, existing, StructureNotifyMask, &event); + } + while (event.type != DestroyNotify); + } +} + static ocm_app_t * ocm_app_new (int argc, char **argv) { @@ -50,110 +176,78 @@ ocm_app_new (int argc, char **argv) int composite_major, composite_minor; int damage_event, damage_error; XSetWindowAttributes attr; - Window existing; - Atom wm_s0; - XClientMessageEvent event; - bool replace; - uint32_t managed_since; - int i; unsigned int n_children; Window *children, r, p; - + bool replace; + int i; + replace = FALSE; for (i = 0; i < argc; ++i) { char *arg = argv[i]; - + if (strcmp (arg, "-r") == 0) replace = TRUE; } app->display = XOpenDisplay (NULL); - + if (!app->display) ocm_error ("Could not open X display"); - + app->root = DefaultRootWindow (app->display); app->timestamp = CurrentTime; + app->error_handler = NULL; + app->error_nesting = 0; + app->windows = NULL; if (!XRenderQueryExtension ( app->display, &render_event, &render_error)) { ocm_error ("No Render extension"); } - + if (!XCompositeQueryVersion ( app->display, &composite_major, &composite_minor)) { ocm_error ("No Composite extension"); } - + if (composite_major == 0 && composite_minor < 2) ocm_error ("No NamePixmap\n"); - + if (!XDamageQueryExtension ( app->display, &damage_event, &damage_error)) { ocm_error ("No Damage extensions\n"); } - + attr.event_mask = - StructureNotifyMask | PropertyChangeMask | KeyPressMask | KeyReleaseMask; + StructureNotifyMask | PropertyChangeMask | + KeyPressMask | KeyReleaseMask; attr.override_redirect = TRUE; attr.background_pixmap = None; attr.border_pixel = 0x00000000; - app->no_focus = XCreateWindow (app->display, app->root, -10, -10, 10, 10, 0, CopyFromParent, + app->no_focus = XCreateWindow (app->display, app->root, + -10, -10, 10, 10, 0, CopyFromParent, InputOutput, CopyFromParent, - CWEventMask | CWOverrideRedirect | CWBackPixmap | CWBorderPixel, + CWEventMask | CWOverrideRedirect | + CWBackPixmap | CWBorderPixel, &attr); + app->wm_owner = create_offscreen_window (app); + app->cm_owner = create_offscreen_window (app); + acquire_manager_selection (app, "WM_S0", app->wm_owner, replace); + acquire_manager_selection (app, "WM_CM_S0", app->cm_owner, replace); - wm_s0 = XInternAtom (app->display, "WM_S0", FALSE); - existing = XGetSelectionOwner (app->display, wm_s0); - if (existing) - { - if (!replace) - ocm_error ("Another window manager is already running - try -r"); - - attr.event_mask = StructureNotifyMask; - XChangeWindowAttributes (app->display, existing, CWEventMask, &attr); - } - - managed_since = get_time (app); - - XSetSelectionOwner (app->display, wm_s0, app->no_focus, managed_since); - - /* Announce ourself as the new wm */ - event.type = ClientMessage; - event.window = app->root; - event.message_type = XInternAtom (app->display, "MANAGER", FALSE); - event.format = 32; - event.data.l[0] = managed_since; - event.data.l[1] = wm_s0; - - XSendEvent (app->display, app->root, FALSE, - StructureNotifyMask, (XEvent*)&event); - - if (existing) - { - XEvent event; - - do - { - XWindowEvent (app->display, existing, StructureNotifyMask, &event); - } - while (event.type != DestroyNotify); - } - /* Now manage all the windows */ if (!XQueryTree (app->display, app->root, &r, &p, &children, &n_children)) ocm_error ("XQueryTree() failed"); - + for (i = 0; i < n_children; ++i) - { - printf ("%lx\n", children[i]); - } + app_manage_window (app, children[i]); + if (children) XFree (children); @@ -168,10 +262,10 @@ ocm_app_run (ocm_app_t *app) XEvent event; XNextEvent (app->display, &event); - - + + } } @@ -180,8 +274,8 @@ int main (int argc, char **argv) { ocm_app_t *app = ocm_app_new (argc, argv); - + ocm_app_run (app); - + return 0; } @@ -19,17 +19,44 @@ /* Typedefs */ typedef int bool; +typedef int (* error_handler_t) (Display *dpy, XErrorEvent *event); typedef struct ocm_app_t ocm_app_t; +typedef struct ocm_window_t ocm_window_t; /* Data structures */ struct ocm_app_t { - Display * display; - Window root; - Window no_focus; - uint32_t timestamp; + Display * display; + Window root; + Window no_focus; + uint32_t timestamp; + + Window cm_owner; + Window wm_owner; + + error_handler_t error_handler; + int error_nesting; + + ocm_window_t * windows; + +}; + +struct ocm_window_t +{ + ocm_app_t * app; + + Window xwindow; + + ocm_window_t * next; }; +/* window.c */ +ocm_window_t * +ocm_window_new (ocm_app_t *app, Window xwindow); + +void +ocm_window_free (ocm_window_t *window); + /* utils.c */ void ocm_error (const char *fmt, ...); @@ -39,3 +66,9 @@ ocm_malloc (size_t n); void ocm_free (void *data); + +void +ocm_begin_ignore_errors (ocm_app_t *app); + +void +ocm_end_ignore_errors (ocm_app_t *app); @@ -27,3 +27,32 @@ ocm_malloc (size_t n) return 0; } + +static int +ignore_errors (Display *dpy, XErrorEvent *event) +{ + return 0; +} + +void +ocm_begin_ignore_errors (ocm_app_t *app) +{ + app->error_nesting++; + if (app->error_handler) + return; + + XSync (app->display, FALSE); + + app->error_handler = XSetErrorHandler (ignore_errors); +} + +void +ocm_end_ignore_errors (ocm_app_t *app) +{ + if (--app->error_nesting == 0) + { + XSync (app->display, FALSE); + + XSetErrorHandler (app->error_handler); + } +} diff --git a/window.c b/window.c new file mode 100644 index 0000000..0624489 --- /dev/null +++ b/window.c @@ -0,0 +1,18 @@ +#include "ocm.h" + +ocm_window_t * +ocm_window_new (ocm_app_t *app, Window xwindow) +{ + ocm_window_t *owindow = ocm_malloc (sizeof *owindow); + + owindow->app = app; + owindow->xwindow = xwindow; + + return owindow; +} + +void +ocm_window_free (ocm_window_t *window) +{ + +} |