X-Git-Url: http://pileus.org/git/?p=wmpus;a=blobdiff_plain;f=sys-x11.c;h=1a833da3b23a033e22d81ea767a8fb91a1f29dd0;hp=68baaee22cb16540683f1aedbc281e0d773ca140;hb=08a8a76218133e513d7804fcc3307c895f22956b;hpb=f4ecdada45354c19e46d860a4563305780060635 diff --git a/sys-x11.c b/sys-x11.c index 68baaee..1a833da 100644 --- a/sys-x11.c +++ b/sys-x11.c @@ -60,6 +60,8 @@ typedef enum { } color_t; /* Global data */ +static win_t *root; +static win_t *last; static int running; static void *cache; static Atom atoms[NATOMS]; @@ -68,6 +70,17 @@ static unsigned long colors[NCOLORS]; static list_t *screens; static list_t *struts; +/* Debug functions */ +static char *state_map[] = { + [ST_HIDE ] "hide ", + [ST_SHOW ] "show ", + [ST_FULL ] "full ", + [ST_MAX ] "max ", + [ST_SHADE] "shade", + [ST_ICON ] "icon ", + [ST_CLOSE] "close", +}; + /* Conversion functions */ static event_map_t ev2sym[] = { {EV_LEFT , XK_Left }, @@ -221,6 +234,7 @@ static win_t *win_new(Display *dpy, Window xid) if (XGetWindowAttributes(dpy, xid, &attr)) if (attr.override_redirect) return NULL; + win_t *win = new0(win_t); win->x = attr.x; win->y = attr.y; @@ -229,14 +243,33 @@ static win_t *win_new(Display *dpy, Window xid) win->sys = new0(win_sys_t); win->sys->dpy = dpy; win->sys->xid = xid; - if (win_prop(win, NET_TYPE) == atoms[NET_DIALOG]) - win->type = TYPE_DIALOG; - if (XGetTransientForHint(dpy, xid, &trans)) - win->parent = win_find(dpy, trans, 0); - printf("win_new: %p = %p, %d (%d,%d %dx%d) - %s\n", - win, dpy, (int)xid, + + if (root) { + if (strut_add(root, win)) + win->type = TYPE_TOOLBAR; + + if (win_prop(win, NET_TYPE) == atoms[NET_DIALOG]) + win->type = TYPE_DIALOG; + + if (win_prop(win, NET_STATE) == atoms[NET_FULL]) + win->state = ST_FULL; + + if (XGetTransientForHint(dpy, xid, &trans)) + win->parent = win_find(dpy, trans, 0); + + XSelectInput(dpy, xid, PropertyChangeMask); + } + + printf("win_new: win=%p x11=(%p,%d) state=%x pos=(%d,%d %dx%d) type=%s\n", + win, dpy, (int)xid, win->state, win->x, win->y, win->w, win->h, - win->type ? "dialog" : "normal"); + win->type == TYPE_NORMAL ? "normal" : + win->type == TYPE_DIALOG ? "dialog" : + win->type == TYPE_TOOLBAR ? "toolbar" : "unknown"); + + if (root) + wm_insert(win); + return win; } @@ -267,20 +300,26 @@ static win_t *win_find(Display *dpy, Window xid, int create) static void win_free(win_t *win) { + if (win == last) + last = NULL; free(win->sys); free(win); } static void win_remove(win_t *win) { + if (win != root) { + strut_del(root, win); + wm_remove(win); + } tdelete(win, &cache, win_cmp); win_free(win); } -static int win_viewable(win_t *win) +static int win_viewable(Display *dpy, Window xid) { XWindowAttributes attr; - if (XGetWindowAttributes(win->sys->dpy, win->sys->xid, &attr)) + if (XGetWindowAttributes(dpy, xid, &attr)) return attr.map_state == IsViewable; else return True; @@ -300,7 +339,7 @@ static int win_msg(win_t *win, atom_t msg) return 0; XSendEvent(win->sys->dpy, win->sys->xid, False, NoEventMask, &(XEvent){ - .type = ClientMessage, + .xclient.type = ClientMessage, .xclient.window = win->sys->xid, .xclient.message_type = atoms[WM_PROTO], .xclient.format = 32, @@ -358,7 +397,7 @@ static void process_event(int type, XEvent *xe, win_t *root) if (type == KeyPress) { while (XCheckTypedEvent(dpy, KeyPress, xe)); KeySym sym = XLookupKeysym(&xe->xkey, 0); - printf("got xe %c %hhx\n", xk2ev(sym), mod2int(mod)); + //printf("got xe %c %hhx\n", xk2ev(sym), mod2int(mod)); wm_handle_event(win, xk2ev(sym), mod, ptr); } else if (type == KeyRelease) { @@ -391,12 +430,12 @@ static void process_event(int type, XEvent *xe, win_t *root) } else if (type == FocusIn || type == FocusOut) { //printf("focus: %lx\n", xe->xfocus.window); - event_t ev = FocusIn ? EV_FOCUS : EV_UNFOCUS; + event_t ev = type == FocusIn ? EV_FOCUS : EV_UNFOCUS; if ((win = win_find(dpy,xe->xfocus.window,0))) wm_handle_event(win, ev, MOD(), PTR()); } else if (type == ConfigureNotify) { - printf("configure: %lx\n", xe->xconfigure.window); + //printf("configure: %lx\n", xe->xconfigure.window); } else if (type == MapNotify) { printf("map: %lx\n", xe->xmap.window); @@ -404,15 +443,13 @@ static void process_event(int type, XEvent *xe, win_t *root) else if (type == UnmapNotify) { if ((win = win_find(dpy,xe->xunmap.window,0)) && win->state != ST_HIDE) { - if (!strut_del(root, win)) - wm_remove(win); - else - wm_update(); + printf("unmap: %lx\n", xe->xunmap.window); + wm_handle_state(win, win->state, ST_HIDE); win->state = ST_HIDE; } } else if (type == DestroyNotify) { - //printf("destroy: %lx\n", xe->xdestroywindow.window); + printf("destroy: %lx\n", xe->xdestroywindow.window); if ((win = win_find(dpy,xe->xdestroywindow.window,0))) win_remove(win); } @@ -421,7 +458,7 @@ static void process_event(int type, XEvent *xe, win_t *root) printf("configure_req: %lx - (0x%lx) %dx%d @ %d,%d\n", cre->window, cre->value_mask, cre->height, cre->width, cre->x, cre->y); - if ((win = win_find(dpy,xe->xconfigurerequest.window,1))) { + if ((win = win_find(dpy,cre->window,1))) { XSendEvent(dpy, cre->window, False, StructureNotifyMask, &(XEvent){ .xconfigure.type = ConfigureNotify, .xconfigure.display = win->sys->dpy, @@ -438,16 +475,11 @@ static void process_event(int type, XEvent *xe, win_t *root) } else if (type == MapRequest) { printf("map_req: %lx\n", xe->xmaprequest.window); - if ((win = win_find(dpy,xe->xmaprequest.window,1)) && - win->state == ST_HIDE) { + win = win_find(dpy,xe->xmaprequest.window,1); + // fixme, for hide -> max, etc + if (win->state == ST_HIDE) { + wm_handle_state(win, win->state, ST_SHOW); win->state = ST_SHOW; - if (win_prop(win, NET_STATE) == atoms[NET_FULL]) - win->state = ST_FULL; - XSelectInput(win->sys->dpy, win->sys->xid, PropertyChangeMask); - if (!strut_add(root, win)) - wm_insert(win); - else - wm_update(); } sys_show(win, win->state); } @@ -469,7 +501,7 @@ static void process_event(int type, XEvent *xe, win_t *root) } } else if (type == PropertyNotify) { - printf("prop: %d\n", xe->xproperty.state); + printf("prop: %lx - %d\n", xe->xproperty.window, xe->xproperty.state); } else { printf("unknown event: %d\n", type); @@ -509,6 +541,8 @@ void sys_move(win_t *win, int x, int y, int w, int h) 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); + XConfigureWindow(win->sys->dpy, win->sys->xid, CWX|CWY|CWWidth|CWHeight, + &(XWindowChanges) { .x=x, .y=y, .width=w, .height=h }); XMoveResizeWindow(win->sys->dpy, win->sys->xid, x, y, w, h); /* Flush events, so moving window doesn't cause re-focus @@ -530,15 +564,14 @@ 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 actual focus */ XSetInputFocus(win->sys->dpy, win->sys->xid, RevertToPointerRoot, CurrentTime); - win_msg(win, WM_FOCUS); + //win_msg(win, WM_FOCUS); /* Set border on focused window */ - static win_t *last = NULL; if (last) XSetWindowBorder(last->sys->dpy, last->sys->xid, colors[CLR_UNFOCUS]); XSync(win->sys->dpy, False); @@ -548,52 +581,71 @@ void sys_focus(win_t *win) void sys_show(win_t *win, state_t state) { - switch (state) { - case ST_HIDE: - printf("sys_show: hide %p\n", win); - XUnmapWindow(win->sys->dpy, win->sys->xid); - break; - case ST_SHOW: - printf("sys_show: show %p\n", win); - if (win->state == ST_FULL) - sys_move(win, win->x, win->y, win->w, win->h); - XSetWindowBorderWidth(win->sys->dpy, win->sys->xid, border); - XMapWindow(win->sys->dpy, win->sys->xid); - XSync(win->sys->dpy, False); - break; - case ST_MAX: - printf("sys_show: max %p\n", win); - XMapWindow(win->sys->dpy, win->sys->xid); - break; - case ST_FULL: - printf("sys_show: full %p\n", win); - win_t *screen = NULL; + //if (win->state == state) + // return; + + /* Debug */ + printf("sys_show: %p: %s -> %s\n", win, + state_map[win->state], state_map[state]); + + /* Find screen */ + win_t *screen = NULL; + if (state == ST_FULL || state == ST_MAX) { for (list_t *cur = screens; cur; cur = cur->next) { screen = cur->data; if (win->x >= screen->x && win->x <= screen->x+screen->w && win->y >= screen->y && win->y <= screen->y+screen->h) break; } + } + + /* Update properties */ + if (state == ST_FULL) + XChangeProperty(win->sys->dpy, win->sys->xid, atoms[NET_STATE], XA_ATOM, 32, + PropModeReplace, (unsigned char*)&atoms[NET_FULL], 1); + else if (state != ST_FULL) + XChangeProperty(win->sys->dpy, win->sys->xid, atoms[NET_STATE], XA_ATOM, 32, + PropModeReplace, (unsigned char*)0, 0); + + /* Update border */ + if (state == ST_SHOW || state == ST_MAX || state == ST_SHADE) + XSetWindowBorderWidth(win->sys->dpy, win->sys->xid, border); + else if (state == ST_FULL) XSetWindowBorderWidth(win->sys->dpy, win->sys->xid, 0); + + /* Map/Unmap window */ + if (state == ST_SHOW || state == ST_FULL || state == ST_MAX || state == ST_SHADE) XMapWindow(win->sys->dpy, win->sys->xid); - XMoveResizeWindow(win->sys->dpy, win->sys->xid, - screen->x - screen->sys->strut.left, - screen->y - screen->sys->strut.top, - screen->w + screen->sys->strut.left + screen->sys->strut.right, - screen->h + screen->sys->strut.top + screen->sys->strut.bottom); - XRaiseWindow(win->sys->dpy, win->sys->xid); - break; - case ST_SHADE: - printf("sys_show: shade %p\n", win); + else if (state == ST_HIDE) + XUnmapWindow(win->sys->dpy, win->sys->xid); + + /* Resize windows */ + if (state == ST_SHOW) { + sys_move(win, win->x, win->y, win->w, win->h); + } else if (state == ST_MAX) { + sys_move(win, screen->x, screen->y, screen->w, screen->h); + } else if (state == ST_FULL) { + XWindowChanges wc = { + .x = screen->x - screen->sys->strut.left , + .y = screen->y - screen->sys->strut.top , + .width = screen->w + screen->sys->strut.left + screen->sys->strut.right, + .height = screen->h + screen->sys->strut.top + screen->sys->strut.bottom + }; + win->x = wc.x; win->y = wc.y; + win->w = wc.width; win->h = wc.height; + XConfigureWindow(win->sys->dpy, win->sys->xid, CWX|CWY|CWWidth|CWHeight, &wc); + XMoveResizeWindow(win->sys->dpy, win->sys->xid, wc.x, wc.y, wc.width, wc.height); + } else if (state == ST_SHADE) { XConfigureWindow(win->sys->dpy, win->sys->xid, CWHeight, - &(XWindowChanges){ .height = stack }); - XMapWindow(win->sys->dpy, win->sys->xid); - break; - case ST_ICON: - printf("sys_show: icon %p\n", win); - break; - case ST_CLOSE: - printf("sys_show: close %p\n", win); + &(XWindowChanges) { .height = stack }); + } + + /* Raise window */ + if (state == ST_FULL || state == ST_MAX) + XRaiseWindow(win->sys->dpy, win->sys->xid); + + /* Close windows */ + if (state == ST_CLOSE) { if (!win_msg(win, WM_DELETE)) { XGrabServer(win->sys->dpy); XSetErrorHandler(xnoerror); @@ -603,9 +655,9 @@ void sys_show(win_t *win, state_t state) XSetErrorHandler(xerror); XUngrabServer(win->sys->dpy); } - XDestroyWindow(win->sys->dpy, win->sys->xid); - break; } + + /* Update state */ win->state = state; } @@ -699,7 +751,7 @@ win_t *sys_init(void) XSelectInput(dpy, xid, SubstructureRedirectMask|SubstructureNotifyMask); xerrorxlib = XSetErrorHandler(xerror); - return win_find(dpy, xid, 1); + return root = win_find(dpy, xid, 1); } void sys_run(win_t *root) @@ -710,14 +762,11 @@ void sys_run(win_t *root) 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); - } + for(int i = 0; i < nkids; i++) + if (win_viewable(root->sys->dpy, kids[i])) + win_find(root->sys->dpy, kids[i], 1); XFree(kids); } - wm_update(); // For struts } /* Main loop */