]> Pileus Git - wmpus/blobdiff - sys-x11.c
Try to improve focus speed
[wmpus] / sys-x11.c
index 3fc4ed7f7d7a02a7e6e935b49895b5000173a7a7..77555a9cb05a309ec3531f2d36a0bd48f5837fad 100644 (file)
--- a/sys-x11.c
+++ b/sys-x11.c
@@ -1,3 +1,19 @@
+/*
+ * Copyright (c) 2011, Andy Spencer <andy753421@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ */
+
+#define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
 #include <search.h>
 #include <X11/extensions/Xinerama.h>
 
 #include "util.h"
+#include "conf.h"
 #include "sys.h"
 #include "wm.h"
 
-#define BORDER 2
+/* Configuration */
+static int BORDER     = 2;
+static int NO_CAPTURE = 0;
 
 /* Internal structures */
 struct win_sys {
@@ -38,10 +57,12 @@ typedef enum {
 } color_t;
 
 /* Global data */
+static int   running;
 static void *cache;
 static Atom atoms[natoms];
 static int (*xerrorxlib)(Display *, XErrorEvent *);
 static unsigned long colors[ncolors];
+static list_t *screens;
 
 /* Conversion functions */
 static keymap_t key2sym[] = {
@@ -130,8 +151,25 @@ static Window getfocus(win_t *root, XEvent *event)
        return focus;
 }
 
-/* Helpers */
-static int add_strut(win_t *root, win_t *win)
+/* Strut functions
+ *   Struts are spaces at the edges of the screen that are used by
+ *   toolbars and statusbars such as dzen. */
+static int strut_copy(win_t *to, win_t *from, int scale)
+{
+       int left   = from->sys->strut.left;
+       int right  = from->sys->strut.right;
+       int top    = from->sys->strut.top;
+       int bottom = from->sys->strut.bottom;
+       if (left == 0 && right == 0 && top == 0 && bottom == 0)
+               return 0;
+       to->x += scale*(left      );
+       to->y += scale*(top       );
+       to->w -= scale*(left+right);
+       to->h -= scale*(top+bottom);
+       return 1;
+}
+
+static int strut_add(win_t *root, win_t *win)
 {
        /* Get X11 strut data */
        Atom ret_type;
@@ -144,38 +182,20 @@ static int add_strut(win_t *root, win_t *win)
        if (status != Success || ret_size != 32 || ret_items != 4)
                return 0;
 
-       int left   = ((int*)xdata)[0];
-       int right  = ((int*)xdata)[1];
-       int top    = ((int*)xdata)[2];
-       int bottom = ((int*)xdata)[3];
-       if (left == 0 && right == 0 && top == 0 && bottom == 0)
-               return 0;
-
-       win->sys->strut.left   = left;
-       win->sys->strut.right  = right;
-       win->sys->strut.top    = top;
-       win->sys->strut.bottom = bottom;
-       root->x += left;
-       root->y += top;
-       root->w -= left+right;
-       root->h -= top+bottom;
-       return 1;
+       win->sys->strut.left   = ((int*)xdata)[0];
+       win->sys->strut.right  = ((int*)xdata)[1];
+       win->sys->strut.top    = ((int*)xdata)[2];
+       win->sys->strut.bottom = ((int*)xdata)[3];
+       for (list_t *cur = screens; cur; cur = cur->next)
+               strut_copy(cur->data, win, 1);
+       return strut_copy(root, win, 1);
 }
 
-static int del_strut(win_t *root, win_t *win)
+static int strut_del(win_t *root, win_t *win)
 {
-       int left   = win->sys->strut.left;
-       int right  = win->sys->strut.right;
-       int top    = win->sys->strut.top;
-       int bottom = win->sys->strut.bottom;
-       if (left == 0 && right == 0 && top == 0 && bottom == 0)
-               return 0;
-
-       root->x -= left;
-       root->y -= top;
-       root->w += left+right;
-       root->h += top+bottom;
-       return 1;
+       for (list_t *cur = screens; cur; cur = cur->next)
+               strut_copy(cur->data, win, -1);
+       return strut_copy(root, win, -1);
 }
 
 /* Window functions */
@@ -224,13 +244,18 @@ static win_t *win_find(Display *dpy, Window xid, int create)
        return new;
 }
 
-static void win_remove(win_t *win)
+static void win_free(win_t *win)
 {
-       tdelete(win, &cache, win_cmp);
        free(win->sys);
        free(win);
 }
 
+static void win_remove(win_t *win)
+{
+       tdelete(win, &cache, win_cmp);
+       win_free(win);
+}
+
 static int win_viewable(win_t *win)
 {
        XWindowAttributes attr;
@@ -241,7 +266,7 @@ static int win_viewable(win_t *win)
 }
 
 /* Drawing functions */
-unsigned long get_color(Display *dpy, const char *name)
+static unsigned long get_color(Display *dpy, const char *name)
 {
        XColor color;
        int screen = DefaultScreen(dpy);
@@ -258,7 +283,7 @@ static void process_event(int type, XEvent *ev, win_t *root)
        //printf("event: %d\n", type);
 
        /* Common data for all these events ... */
-       ptr_t ptr; mod_t mod;
+       ptr_t ptr = {}; mod_t mod = {};
        if (type == KeyPress    || type == KeyRelease    ||
            type == ButtonPress || type == ButtonRelease ||
            type == MotionNotify) {
@@ -322,7 +347,7 @@ static void process_event(int type, XEvent *ev, win_t *root)
        else if (type == UnmapNotify) {
                if ((win = win_find(dpy,ev->xunmap.window,0)) &&
                     win->sys->state == st_show) {
-                       if (!del_strut(root, win))
+                       if (!strut_del(root, win))
                                wm_remove(win);
                        else
                                wm_update();
@@ -346,7 +371,7 @@ static void process_event(int type, XEvent *ev, win_t *root)
                        .height = cre->height,
                });
 
-               /* This seems necessasairy for, but causes flicker
+               /* This seems necessary for, but causes flicker
                 * there could be a better way to do this */
                if ((win = win_find(dpy,ev->xmaprequest.window,0)))
                        sys_move(win, win->x, win->y, win->w, win->h);
@@ -354,7 +379,7 @@ static void process_event(int type, XEvent *ev, win_t *root)
        else if (type == MapRequest) {
                printf("map_req: %d\n", type);
                if ((win = win_find(dpy,ev->xmaprequest.window,1))) {
-                       if (!add_strut(root, win))
+                       if (!strut_add(root, win))
                                wm_insert(win);
                        else
                                wm_update();
@@ -381,9 +406,9 @@ static int xerror(Display *dpy, XErrorEvent *err)
        return xerrorxlib(dpy, err);
 }
 
-/*****************
- * Sys functions *
- *****************/
+/********************
+ * System functions *
+ ********************/
 void sys_move(win_t *win, int x, int y, int w, int h)
 {
        //printf("sys_move: %p - %d,%d  %dx%d\n", win, x, y, w, h);
@@ -393,7 +418,7 @@ void sys_move(win_t *win, int x, int y, int w, int h)
        w      = MAX(w-b,1); h      = MAX(h-b,1);
        XMoveResizeWindow(win->sys->dpy, win->sys->xid, x, y, w, h);
 
-       /* Flush events, so moving window doesn't cuase re-focus
+       /* Flush events, so moving window doesn't cause re-focus
         * There's probably a better way to do this */
        XEvent ev;
        XSync(win->sys->dpy, False);
@@ -439,6 +464,7 @@ void sys_show(win_t *win, state_t state)
        case st_show:
                printf("sys_show: show\n");
                XMapWindow(win->sys->dpy, win->sys->xid);
+               XSync(win->sys->dpy, False);
                return;
        case st_full:
                printf("sys_show: full\n");
@@ -485,23 +511,27 @@ void sys_unwatch(win_t *win, Key_t key, mod_t mod)
 
 list_t *sys_info(win_t *win)
 {
-       int n;
-       XineramaScreenInfo *info = NULL;
-       if (XineramaIsActive(win->sys->dpy))
-               info = XineramaQueryScreens(win->sys->dpy, &n);
-       if (!info) {
-               win_t *screen = new0(win_t);
-               *screen = *win;
-               return list_insert(NULL, screen);
+       /* Use global copy of screens so we can add struts */
+       if (screens == NULL) {
+               /* Add Xinerama screens */
+               int n = 0;
+               XineramaScreenInfo *info = NULL;
+               if (XineramaIsActive(win->sys->dpy))
+                       info = XineramaQueryScreens(win->sys->dpy, &n);
+               for (int i = 0; i < n; i++) {
+                       win_t *screen = new0(win_t);
+                       screen->x = info[i].x_org;
+                       screen->y = info[i].y_org;
+                       screen->w = info[i].width;
+                       screen->h = info[i].height;
+                       screens = list_append(screens, screen);
+               }
        }
-       list_t *screens = NULL;
-       for (int i = 0; i < n; i++) {
+       if (screens == NULL) {
+               /* No xinerama support */
                win_t *screen = new0(win_t);
-               screen->x = info[i].x_org;
-               screen->y = info[i].y_org;
-               screen->w = info[i].width;
-               screen->h = info[i].height;
-               screens = list_append(screens, screen);
+               *screen = *win;
+               screens = list_insert(NULL, screen);
        }
        return screens;
 }
@@ -511,6 +541,10 @@ win_t *sys_init(void)
        Display *dpy;
        Window   xid;
 
+       /* Load configuration */
+       BORDER     = conf_get_int("main.border",     BORDER);
+       NO_CAPTURE = conf_get_int("main.no-capture", NO_CAPTURE);
+
        /* Open the display */
        if (!(dpy = XOpenDisplay(NULL)))
                error("Unable to get display");
@@ -527,9 +561,8 @@ win_t *sys_init(void)
        colors[clr_urgent]  = get_color(dpy, "#ff0000");
        printf("colors = #%06lx #%06lx #%06lx\n", colors[0], colors[1], colors[2]);
 
-       /* Selec Window Managmenet events */
+       /* Select window management events */
        XSelectInput(dpy, xid, SubstructureRedirectMask|SubstructureNotifyMask);
-       XSetInputFocus(dpy, None, RevertToNone, CurrentTime);
        xerrorxlib = XSetErrorHandler(xerror);
 
        return win_find(dpy, xid, 1);
@@ -538,22 +571,40 @@ win_t *sys_init(void)
 void sys_run(win_t *root)
 {
        /* Add each initial window */
-       unsigned int nkids;
-       Window par, xid, *kids = NULL;
-       if (XQueryTree(root->sys->dpy, root->sys->xid,
-                               &par, &xid, &kids, &nkids))
-               for(int i = 0; i < nkids; i++) {
-                       win_t *win = win_find(root->sys->dpy, kids[i], 1);
-                       if (win && win_viewable(win) && !add_strut(root,win))
-                               wm_insert(win);
+       if (!NO_CAPTURE) {
+               unsigned int nkids;
+               Window par, xid, *kids = NULL;
+               if (XQueryTree(root->sys->dpy, root->sys->xid,
+                                       &par, &xid, &kids, &nkids)) {
+                       for(int i = 0; i < nkids; i++) {
+                               win_t *win = win_find(root->sys->dpy, kids[i], 1);
+                               if (win && win_viewable(win) && !strut_add(root,win))
+                                       wm_insert(win);
+                       }
+                       XFree(kids);
                }
-       wm_update(); // For struts
+               wm_update(); // For struts
+       }
 
        /* Main loop */
-       for(;;)
+       running = 1;
+       while (running)
        {
                XEvent ev;
                XNextEvent(root->sys->dpy, &ev);
                process_event(ev.type, &ev, root);
        }
 }
+
+void sys_exit(void)
+{
+       running = 0;
+}
+
+void sys_free(win_t *root)
+{
+       XCloseDisplay(root->sys->dpy);
+       while (screens)
+               screens = list_remove(screens, screens, 1);
+       tdestroy(cache, (void(*)(void*))win_free);
+}