X-Git-Url: http://pileus.org/git/?p=wmpus;a=blobdiff_plain;f=sys-x11.c;h=7222b462141d7f5eb5a38b22ca62ef6585bdeaff;hp=907cde7e86afb4e39bc58da0f54f13c98a5eeb35;hb=43cb9b7de22dac5864d73321ec974bb937a217ff;hpb=caa90c89a09fe03c144922d44e3137e4c1fe5d8e diff --git a/sys-x11.c b/sys-x11.c index 907cde7..7222b46 100644 --- a/sys-x11.c +++ b/sys-x11.c @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2011, Andy Spencer + * + * 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 + */ + #include #include #include @@ -12,7 +27,9 @@ #include "sys.h" #include "wm.h" +#ifndef BORDER #define BORDER 2 +#endif /* Internal structures */ struct win_sys { @@ -21,6 +38,7 @@ struct win_sys { struct { int left, right, top, bottom; } strut; + state_t state; }; typedef struct { @@ -37,10 +55,12 @@ typedef enum { } color_t; /* Global data */ -static void *win_cache; +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[] = { @@ -129,8 +149,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; @@ -143,38 +180,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 */ @@ -216,16 +235,16 @@ static win_t *win_find(Display *dpy, Window xid, int create) win_sys_t sys = {.dpy=dpy, .xid=xid}; win_t tmp = {.sys=&sys}; win_t **old = NULL, *new = NULL; - if ((old = tfind(&tmp, &win_cache, win_cmp))) + if ((old = tfind(&tmp, &cache, win_cmp))) return *old; if (create && (new = win_new(dpy,xid))) - tsearch(new, &win_cache, win_cmp); + tsearch(new, &cache, win_cmp); return new; } static void win_remove(win_t *win) { - tdelete(win, &win_cache, win_cmp); + tdelete(win, &cache, win_cmp); free(win->sys); free(win); } @@ -240,7 +259,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); @@ -254,10 +273,10 @@ static void process_event(int type, XEvent *ev, win_t *root) { Display *dpy = root->sys->dpy; win_t *win = NULL; - printf("event: %d\n", type); + //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) { @@ -272,6 +291,7 @@ static void process_event(int type, XEvent *ev, win_t *root) if (type == KeyPress) { while (XCheckTypedEvent(dpy, KeyPress, ev)); KeySym sym = XKeycodeToKeysym(dpy, ev->xkey.keycode, 0); + printf("got key %c %hhx\n", x2key(sym), mod2int(mod)); wm_handle_key(win, x2key(sym), mod, ptr); } else if (type == KeyRelease) { @@ -306,7 +326,7 @@ static void process_event(int type, XEvent *ev, win_t *root) wm_handle_key(win, key, MOD(), PTR()); } else if (type == FocusIn || type == FocusOut) { - printf("focus: %d\n", type); + //printf("focus: %d\n", type); key_t key = FocusIn ? key_focus : key_unfocus; if ((win = win_find(dpy,ev->xfocus.window,0))) wm_handle_key(win, key, MOD(), PTR()); @@ -318,15 +338,20 @@ static void process_event(int type, XEvent *ev, win_t *root) printf("map: %d\n", type); } else if (type == UnmapNotify) { - //printf("unmap: %d\n", type); - if ((win = win_find(dpy,ev->xunmap.window,0))) { - if (!del_strut(root, win)) + if ((win = win_find(dpy,ev->xunmap.window,0)) && + win->sys->state == st_show) { + if (!strut_del(root, win)) wm_remove(win); else wm_update(); - win_remove(win); + win->sys->state = st_hide; } } + else if (type == DestroyNotify) { + //printf("destroy: %d\n", type); + if ((win = win_find(dpy,ev->xdestroywindow.window,0))) + win_remove(win); + } else if (type == ConfigureRequest) { XConfigureRequestEvent *cre = &ev->xconfigurerequest; printf("configure_req: %d - %x, (0x%lx) %dx%d @ %d,%d\n", @@ -339,7 +364,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); @@ -347,7 +372,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(); @@ -374,19 +399,19 @@ 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); int b = 2*BORDER; - win->x = MAX(x,0); win->y = MAX(y,0); + win->x = x; win->y = y; win->w = MAX(w,1+b); win->h = MAX(h,1+b); 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); @@ -402,7 +427,7 @@ void sys_raise(win_t *win) void sys_focus(win_t *win) { - printf("sys_focus: %p\n", win); + //printf("sys_focus: %p\n", win); /* Set border on focused window */ static win_t *last = NULL; @@ -425,6 +450,30 @@ void sys_focus(win_t *win) }); } +void sys_show(win_t *win, state_t state) +{ + win->sys->state = state; + switch (state) { + case st_show: + printf("sys_show: show\n"); + XMapWindow(win->sys->dpy, win->sys->xid); + return; + case st_full: + printf("sys_show: full\n"); + return; + case st_shade: + printf("sys_show: shade\n"); + return; + case st_icon: + printf("sys_show: icon\n"); + return; + case st_hide: + printf("sys_show: hide\n"); + XUnmapWindow(win->sys->dpy, win->sys->xid); + return; + } +} + void sys_watch(win_t *win, Key_t key, mod_t mod) { //printf("sys_watch: %p - %x %hhx\n", win, key, mod); @@ -454,23 +503,25 @@ 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); - } - list_t *screens = NULL; - 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); + /* Use global copy of screens so we can add struts */ + if (screens == NULL) { + 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); + } + 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); + } } return screens; } @@ -496,7 +547,7 @@ 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); @@ -513,16 +564,22 @@ void sys_run(win_t *root) &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)) + if (win && win_viewable(win) && !strut_add(root,win)) wm_insert(win); } 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; +}