summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2011-02-25 12:20:48 -0500
committerSøren Sandmann Pedersen <ssp@redhat.com>2011-02-25 12:20:48 -0500
commit31869cd166977c963b1a7b9eeb68b42e28613e67 (patch)
tree270c1776122dc68cc4d9dcfc78cfac4606255094
parent2c37aa64b50d8c76fa96f92875a20de1d500f6fc (diff)
window.c
-rw-r--r--Makefile2
-rw-r--r--main.c226
-rw-r--r--ocm.h41
-rw-r--r--utils.c29
-rw-r--r--window.c18
5 files changed, 245 insertions, 71 deletions
diff --git a/Makefile b/Makefile
index 1cde8ea..3c483d9 100644
--- a/Makefile
+++ b/Makefile
@@ -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 $@
diff --git a/main.c b/main.c
index c8d12a2..15a631d 100644
--- a/main.c
+++ b/main.c
@@ -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;
}
diff --git a/ocm.h b/ocm.h
index 6096532..d601093 100644
--- a/ocm.h
+++ b/ocm.h
@@ -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);
diff --git a/utils.c b/utils.c
index 26d910e..99c375a 100644
--- a/utils.c
+++ b/utils.c
@@ -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)
+{
+
+}