X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=sys-x11.c;h=0d7644b859c3a67e575901802e5fc527f92d8b63;hb=bafa6f74e4a8112b650cb1aa2894bc5c0184fca5;hp=b8dbe02ce24d7d543ef0ac7cfab0593142c2baf3;hpb=e18a4741e8fa583e13554b5f6c4e59307ec1ac0e;p=wmpus diff --git a/sys-x11.c b/sys-x11.c index b8dbe02..0d7644b 100644 --- a/sys-x11.c +++ b/sys-x11.c @@ -40,7 +40,6 @@ struct win_sys { struct { int left, right, top, bottom; } strut; - state_t state; }; typedef struct { @@ -49,8 +48,9 @@ typedef struct { } event_map_t; typedef enum { - WM_PROTO, WM_FOCUS, + WM_PROTO, WM_FOCUS, WM_DELETE, NET_STATE, NET_FULL, NET_STRUT, + NET_TYPE, NET_DIALOG, NATOMS } atom_t; @@ -210,8 +210,12 @@ static int strut_del(win_t *root, win_t *win) } /* Window functions */ +static Atom win_prop(win_t *win, atom_t prop); +static win_t *win_find(Display *dpy, Window xid, int create); + static win_t *win_new(Display *dpy, Window xid) { + Window trans; XWindowAttributes attr; if (XGetWindowAttributes(dpy, xid, &attr)) if (attr.override_redirect) @@ -224,9 +228,14 @@ static win_t *win_new(Display *dpy, Window xid) win->sys = new0(win_sys_t); win->sys->dpy = dpy; win->sys->xid = xid; - printf("win_new: %p = %p, %d (%d,%d %dx%d)\n", + 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, - win->x, win->y, win->w, win->h); + win->x, win->y, win->w, win->h, + win->type ? "dialog" : "normal"); return win; } @@ -300,27 +309,19 @@ static int win_msg(win_t *win, atom_t msg) return 1; } -#if 0 -static int win_full(win_t *win) +static Atom win_prop(win_t *win, atom_t prop) { - Atom ret_type; - int ret_size; - unsigned long ret_items, bytes_left; - unsigned char *xdata; - int status = XGetWindowProperty(win->sys->dpy, win->sys->xid, - atoms[NET_FULL], 0L, 1L, False, XA_ATOM, - &ret_type, &ret_size, &ret_items, &bytes_left, &xdata); - printf("is_fullscreen:\n"); - printf("\t%d\n", status); - printf("\t%d\n", ret_size); - printf("\t%ld\n", ret_items); - printf("\t%p\n", xdata); - if (xdata) - printf("\t%d\n", xdata[0]); - return status == Success && ret_size == 32 && ret_items == 1 && - xdata[0] == atoms[NET_FULL]; -} -#endif + int format; + unsigned long nitems, bytes; + unsigned char *buf = NULL; + Atom atom, type = XA_ATOM; + if (XGetWindowProperty(win->sys->dpy, win->sys->xid, atoms[prop], + 0L, sizeof(Atom), False, type, &type, &format, &nitems, &bytes, &buf) || !buf) + return 0; + atom = *(Atom *)buf; + XFree(buf); + return atom; +} /* Drawing functions */ static unsigned long get_color(Display *dpy, const char *name) @@ -347,6 +348,7 @@ static void process_event(int type, XEvent *xe, win_t *root) Window xid = getfocus(root, xe); if (!(win = win_find(dpy,xid,0))) return; + //printf("button-press %p\n", win); ptr = x2ptr(xe); mod = x2mod(xe->xkey.state, type==KeyRelease||type==ButtonRelease); } @@ -362,11 +364,14 @@ static void process_event(int type, XEvent *xe, win_t *root) //printf("release: %d\n", type); } else if (type == ButtonPress) { - if (wm_handle_event(win, xb2ev(xe->xbutton.button), mod, ptr)) + if (wm_handle_event(win, xb2ev(xe->xbutton.button), mod, ptr)) { + //printf("grab pointer\n"); XGrabPointer(dpy, xe->xbutton.root, True, PointerMotionMask|ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); - else - XAllowEvents(win->sys->dpy, ReplayPointer, CurrentTime); + } else { + //printf("allow events\n"); + XAllowEvents(win->sys->dpy, ReplayPointer, xe->xbutton.time); + } } else if (type == ButtonRelease) { XUngrabPointer(dpy, CurrentTime); @@ -378,7 +383,7 @@ static void process_event(int type, XEvent *xe, win_t *root) } else if (type == EnterNotify || type == LeaveNotify) { printf("%s: %d\n", type==EnterNotify?"enter":"leave", type); - event_t ev = EnterNotify ? EV_ENTER : EV_LEAVE; + event_t ev = type == EnterNotify ? EV_ENTER : EV_LEAVE; if ((win = win_find(dpy,xe->xcrossing.window,0))) wm_handle_event(win, ev, MOD(), PTR()); } @@ -396,12 +401,12 @@ 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->sys->state != ST_HIDE) { + win->state != ST_HIDE) { if (!strut_del(root, win)) wm_remove(win); else wm_update(); - win->sys->state = ST_HIDE; + win->state = ST_HIDE; } } else if (type == DestroyNotify) { @@ -414,7 +419,7 @@ static void process_event(int type, XEvent *xe, win_t *root) printf("configure_req: %d - %x, (0x%lx) %dx%d @ %d,%d\n", type, (int)cre->window, cre->value_mask, cre->height, cre->width, cre->x, cre->y); - if ((win = win_find(dpy,xe->xmaprequest.window,1))) { + if ((win = win_find(dpy,xe->xconfigurerequest.window,1))) { XSendEvent(dpy, cre->window, False, StructureNotifyMask, &(XEvent){ .xconfigure.type = ConfigureNotify, .xconfigure.display = win->sys->dpy, @@ -431,32 +436,38 @@ static void process_event(int type, XEvent *xe, win_t *root) } else if (type == MapRequest) { printf("map_req: %d\n", type); - if ((win = win_find(dpy,xe->xmaprequest.window,1))) { + if ((win = win_find(dpy,xe->xmaprequest.window,1)) && + win->state == ST_HIDE) { + 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(); } - XMapWindow(dpy, xe->xmaprequest.window); + sys_show(win, win->state); } else if (type == ClientMessage) { - printf("msg: %d\n", type); XClientMessageEvent *cme = &xe->xclient; + printf("msg: %d - %ld %ld,%ld,%ld,%ld,%ld\n", + type, cme->message_type, + cme->data.l[0], cme->data.l[1], cme->data.l[2], + cme->data.l[3], cme->data.l[4]); if ((win = win_find(dpy,cme->window,0)) && (cme->message_type == atoms[NET_STATE]) && (cme->data.l[1] == atoms[NET_FULL] || cme->data.l[2] == atoms[NET_FULL])) { - if (cme->data.l[0] == 1 || /* _NET_WM_STATE_ADD */ - (cme->data.l[0] == 2 && /* _NET_WM_STATE_TOGGLE */ - win->sys->state != ST_FULL)) - sys_show(win, ST_FULL); - else - sys_show(win, ST_SHOW); + state_t next = (cme->data.l[0] == 1 || /* _NET_WM_STATE_ADD */ + (cme->data.l[0] == 2 && /* _NET_WM_STATE_TOGGLE */ + win->state != ST_FULL)) ? ST_FULL : ST_SHOW; + wm_handle_state(win, win->state, next); + sys_show(win, next); } } else if (type == PropertyNotify) { - printf("prop: %d\n", type); + printf("prop: %d - %d\n", type, xe->xproperty.state); } else { printf("unknown event: %d\n", type); @@ -480,6 +491,12 @@ static int xerror(Display *dpy, XErrorEvent *err) return xerrorxlib(dpy, err); } +static int xnoerror(Display *dpy, XErrorEvent *err) +{ + return 0; +} + + /******************** * System functions * ********************/ @@ -529,18 +546,25 @@ void sys_focus(win_t *win) void sys_show(win_t *win, state_t state) { - /* Restore from fullscreen */ 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\n"); - if (win->sys->state == ST_FULL) + 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\n"); + printf("sys_show: full %p\n", win); win_t *screen = NULL; for (list_t *cur = screens; cur; cur = cur->next) { screen = cur->data; @@ -558,22 +582,27 @@ void sys_show(win_t *win, state_t state) XRaiseWindow(win->sys->dpy, win->sys->xid); break; case ST_SHADE: - printf("sys_show: shade\n"); + printf("sys_show: shade %p\n", win); XMapWindow(win->sys->dpy, win->sys->xid); break; case ST_ICON: - printf("sys_show: icon\n"); - break; - case ST_HIDE: - printf("sys_show: hide\n"); - XUnmapWindow(win->sys->dpy, win->sys->xid); + printf("sys_show: icon %p\n", win); break; case ST_CLOSE: - printf("sys_show: close\n"); + printf("sys_show: close %p\n", win); + if (!win_msg(win, WM_DELETE)) { + XGrabServer(win->sys->dpy); + XSetErrorHandler(xnoerror); + XSetCloseDownMode(win->sys->dpy, DestroyAll); + XKillClient(win->sys->dpy, win->sys->xid); + XSync(win->sys->dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(win->sys->dpy); + } XDestroyWindow(win->sys->dpy, win->sys->xid); break; } - win->sys->state = state; + win->state = state; } void sys_watch(win_t *win, event_t ev, mod_t mod) @@ -647,11 +676,14 @@ win_t *sys_init(void) error("Unable to get root window"); /* Setup X11 data */ - atoms[WM_PROTO] = XInternAtom(dpy, "WM_PROTOCOLS", False); - atoms[WM_FOCUS] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); - atoms[NET_STATE] = XInternAtom(dpy, "_NET_WM_STATE", False); - atoms[NET_FULL] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); - atoms[NET_STRUT] = XInternAtom(dpy, "_NET_WM_STRUT", False); + atoms[WM_PROTO] = XInternAtom(dpy, "WM_PROTOCOLS", False); + atoms[WM_FOCUS] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + atoms[WM_DELETE] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + atoms[NET_STATE] = XInternAtom(dpy, "_NET_WM_STATE", False); + atoms[NET_FULL] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); + atoms[NET_STRUT] = XInternAtom(dpy, "_NET_WM_STRUT", False); + atoms[NET_TYPE] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + atoms[NET_DIALOG] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); colors[CLR_FOCUS] = get_color(dpy, "#a0a0ff"); colors[CLR_UNFOCUS] = get_color(dpy, "#101066");