diff --git a/include/client.h b/include/client.h index 34dabeb..8b81335 100644 --- a/include/client.h +++ b/include/client.h @@ -70,27 +70,28 @@ enum KillType }; /* Manage cookies */ -enum ManageCookies +/* Manage cookies */ +enum ManageClientProperties { - ManageCookieAttributes, - ManageCookieGeometry, - ManageCookieTransient, - ManageCookieWType, - ManageCookieWState, - ManageCookieSizeHint, - ManageCookieWMHints, - ManageCookieClass, - ManageCookieWMProtocol, - ManageCookieStrutP, - ManageCookieStrut, - ManageCookieNetWMName, - ManageCookieWMName, - ManageCookiePid, - ManageCookieIcon, - ManageCookieMotif, + ManageClientAttributes, + ManageClientGeometry, + ManageClientTransient, + ManageClientWType, + ManageClientWState, + ManageClientSizeHint, + ManageClientWMHints, + ManageClientClass, + ManageClientWMProtocol, + ManageClientStrutP, + ManageClientStrut, + ManageClientNetWMName, + ManageClientWMName, + ManageClientPid, + ManageClientIcon, + ManageClientMotif, - ManageCookieLAST + ManageClientLAST }; enum BarSides @@ -100,7 +101,6 @@ enum BarSides typedef struct Client Client; - /* extern structs */ struct Desktop; struct Monitor; @@ -174,7 +174,6 @@ struct Client XCBColormap colormap; /* Clients colormap */ }; - /* Applies the gravity shifts specified by the gravity onto the x and y coordinates. */ void applygravity(const enum XCBBitGravity gravity, int32_t *x, int32_t *y, const uint32_t width, const uint32_t height, const uint32_t border_width); @@ -252,14 +251,16 @@ Client *laststack(struct Desktop *desk); */ Client *lastrstack(struct Desktop *desk); /* requests for clients cookies. */ -void managerequest(XCBWindow win, XCBCookie requests[ManageCookieLAST]); +void managecleanup(void *replies[ManageClientLAST]); +void managerequest(XCBWindow win, XCBCookie requests[ManageClientLAST]); +void managereplies(XCBCookie requests[ManageClientLAST], void *replies[ManageClientLAST]); /* Part of main event loop "run()" * Manages AKA adds the window to our current or windows specified desktop. * Applies size checks, bounds, layout, etc... * RETURN: Client * on Success. * RETURN: NULL on Failure. */ -Client *managereply(XCBWindow window, XCBCookie requests[ManageCookieLAST]); +Client *manage(XCBWindow window, void *replies[ManageClientLAST]); /* Maximizes a client if unmaxed, Sets flag. */ void maximize(Client *c); diff --git a/include/getprop.h b/include/getprop.h index 796d71f..44db226 100644 --- a/include/getprop.h +++ b/include/getprop.h @@ -21,6 +21,8 @@ enum PropertyType PropPid, PropIcon, PropMotifHints, + PropManage, + PropUnmanage, /* special */ PropExitThread, diff --git a/src/client.c b/src/client.c index 752d0ab..3967344 100644 --- a/src/client.c +++ b/src/client.c @@ -854,105 +854,208 @@ lastrstack(Desktop *desk) return desk->rlast; } +void +managecleanup(void *replies[ManageClientLAST]) +{ + /* Remove *_reply from structures + * 'Wipe' + */ + if(replies[ManageClientClass]) + { XCBWipeGetWMClass(replies[ManageClientClass]); + } + if(replies[ManageClientWMProtocol]) + { XCBWipeGetWMProtocols(replies[ManageClientWMProtocol]); + } + + i32 i; + for(i = 0; i < ManageClientLAST; ++i) + { free(replies[i]); + } +} + void -managerequest(XCBWindow win, XCBCookie requests[ManageCookieLAST]) -{ - requests[ManageCookieAttributes] = XCBGetWindowAttributesCookie(_wm.dpy, win); - requests[ManageCookieGeometry] = XCBGetWindowGeometryCookie(_wm.dpy, win); - requests[ManageCookieTransient] = GetTransientCookie(_wm.dpy, win); - requests[ManageCookieWType] = GetWindowTypeCookie(_wm.dpy, win); - requests[ManageCookieWState] = GetWindowStateCookie(_wm.dpy, win); - requests[ManageCookieSizeHint] = GetSizeHintsCookie(_wm.dpy, win); - requests[ManageCookieWMHints] = GetWMHintsCookie(_wm.dpy, win); - requests[ManageCookieClass] = GetWMClassCookie(_wm.dpy, win); - requests[ManageCookieWMProtocol] = GetWMProtocolCookie(_wm.dpy, win); - requests[ManageCookieStrut] = GetStrutCookie(_wm.dpy, win); - requests[ManageCookieStrutP] = GetStrutpCookie(_wm.dpy, win); - requests[ManageCookieNetWMName] = GetNetWMNameCookie(_wm.dpy, win); - requests[ManageCookieWMName] = GetWMNameCookie(_wm.dpy, win); - requests[ManageCookiePid] = GetPidCookie(_wm.dpy, win); - requests[ManageCookieIcon] = GetIconCookie(_wm.dpy, win); - requests[ManageCookieMotif] = GetMotifHintsCookie(_wm.dpy, win); +managerequest(XCBWindow win, XCBCookie requests[ManageClientLAST]) +{ + requests[ManageClientAttributes] = XCBGetWindowAttributesCookie(_wm.dpy, win); + requests[ManageClientGeometry] = XCBGetWindowGeometryCookie(_wm.dpy, win); + requests[ManageClientTransient] = GetTransientCookie(_wm.dpy, win); + requests[ManageClientWType] = GetWindowTypeCookie(_wm.dpy, win); + requests[ManageClientWState] = GetWindowStateCookie(_wm.dpy, win); + requests[ManageClientSizeHint] = GetSizeHintsCookie(_wm.dpy, win); + requests[ManageClientWMHints] = GetWMHintsCookie(_wm.dpy, win); + requests[ManageClientClass] = GetWMClassCookie(_wm.dpy, win); + requests[ManageClientWMProtocol] = GetWMProtocolCookie(_wm.dpy, win); + requests[ManageClientStrut] = GetStrutCookie(_wm.dpy, win); + requests[ManageClientStrutP] = GetStrutpCookie(_wm.dpy, win); + requests[ManageClientNetWMName] = GetNetWMNameCookie(_wm.dpy, win); + requests[ManageClientWMName] = GetWMNameCookie(_wm.dpy, win); + requests[ManageClientPid] = GetPidCookie(_wm.dpy, win); + requests[ManageClientIcon] = GetIconCookie(_wm.dpy, win); + requests[ManageClientMotif] = GetMotifHintsCookie(_wm.dpy, win); } +void +managereplies(XCBCookie requests[ManageClientLAST], void *replies[ManageClientLAST]) +{ + XCBWindowGeometry *wg; + XCBGetWindowAttributes *waattributes; + XCBWindowProperty *wtypeunused; + XCBWindowProperty *stateunused; + XCBSizeHints hints; + u8 hintstatus = 0; + XCBWMHints *wmh; + XCBWMClass cls = { ._reply = NULL }; + u8 clsstatus = 0; + XCBWMProtocols wmprotocols = { ._reply = NULL, .atoms_len = 0 }; + u8 wmprotocolsstatus = 0; + XCBWindowProperty *strutpreply; + XCBWindowProperty *strutreply; + XCBWindowProperty *netwmnamereply; + XCBWindowProperty *wmnamereply; + XCBWindowProperty *iconreply; + pid_t pid = 0; + XCBWindowProperty *motifreply; + XCBWindow trans; + u8 transstatus; + + /* wait for replies */ + waattributes = XCBGetWindowAttributesReply(_wm.dpy, requests[ManageClientAttributes]); + wg = XCBGetWindowGeometryReply(_wm.dpy, requests[ManageClientGeometry]); + transstatus = XCBGetTransientForHintReply(_wm.dpy, requests[ManageClientTransient], &trans); + wtypeunused = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageClientWType]); + stateunused = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageClientWState]); + hintstatus = XCBGetWMNormalHintsReply(_wm.dpy, requests[ManageClientSizeHint], &hints); + wmh = XCBGetWMHintsReply(_wm.dpy, requests[ManageClientWMHints]); + clsstatus = XCBGetWMClassReply(_wm.dpy, requests[ManageClientClass], &cls); + wmprotocolsstatus = XCBGetWMProtocolsReply(_wm.dpy, requests[ManageClientWMProtocol], &wmprotocols); + strutreply = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageClientStrut]); + strutpreply = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageClientStrutP]); + netwmnamereply = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageClientNetWMName]); + wmnamereply = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageClientWMName]); + iconreply = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageClientIcon]); + pid = XCBGetPidReply(_wm.dpy, requests[ManageClientPid]); + motifreply = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageClientMotif]); + + + XCBWindow *transreply = NULL; + XCBSizeHints *sizehintsreply = NULL; + XCBWMClass *classreply = NULL; + XCBWMProtocols *wmprotocolsreply = NULL; + int32_t *pidreply = NULL; + + if(transstatus) + { + transreply = malloc(sizeof(XCBWindow )); + if(transreply) + { *transreply = trans; + } + } + if(hintstatus) + { + sizehintsreply = malloc(sizeof(XCBSizeHints )); + if(sizehintsreply) + { *sizehintsreply = hints; + } + } + if(clsstatus) + { + classreply = malloc(sizeof(XCBWMClass )); + if(classreply) + { *classreply = cls; + } + else + { XCBWipeGetWMClass(&cls); + } + } + if(wmprotocolsstatus) + { + wmprotocolsreply = malloc(sizeof(XCBWMProtocols )); + if(wmprotocolsreply) + { *wmprotocolsreply = wmprotocols; + } + else + { XCBWipeGetWMProtocols(&wmprotocols); + } + } + + const int PID_FAILURE = -1; + if(pid != PID_FAILURE) + { + pidreply = malloc(sizeof(pid_t )); + if(pidreply) + { *pidreply = pid; + } + } + + replies[ManageClientAttributes] = waattributes; + replies[ManageClientGeometry] = wg; + replies[ManageClientTransient] = transreply; + replies[ManageClientWType] = wtypeunused; + replies[ManageClientWState] = stateunused; + replies[ManageClientSizeHint] = sizehintsreply; + replies[ManageClientWMHints] = wmh; + replies[ManageClientClass] = classreply; + replies[ManageClientWMProtocol] = wmprotocolsreply; + replies[ManageClientStrut] = strutreply; + replies[ManageClientStrutP] = strutpreply; + replies[ManageClientNetWMName] = netwmnamereply; + replies[ManageClientWMName] = wmnamereply; + replies[ManageClientPid] = pidreply; + replies[ManageClientIcon] = iconreply; + replies[ManageClientMotif] = motifreply; +} + + Client * -managereply(XCBWindow win, XCBCookie requests[ManageCookieLAST]) +manage(XCBWindow win, void *replies[ManageClientLAST]) { + Monitor *m = NULL; + Client *c = NULL; /* checks */ if(win == _wm.root) { Debug("%s", "Cannot manage() root window."); - goto DISCARD; + goto FAILURE; } else if(wintoclient(win)) { Debug("Window already managed????: [%u]", win); - goto DISCARD; + goto FAILURE; } const u16 bw = 0; const u32 bcol = 0; const u8 showdecor = 1; - Monitor *m = NULL; - Client *c = NULL; - XCBWindow trans = 0; - u8 transstatus = 0; const u32 inputmask = XCB_EVENT_MASK_ENTER_WINDOW|XCB_EVENT_MASK_FOCUS_CHANGE|XCB_EVENT_MASK_PROPERTY_CHANGE|XCB_EVENT_MASK_STRUCTURE_NOTIFY; - XCBWindowGeometry *wg = NULL; - - XCBGetWindowAttributes *waattributes = NULL; - XCBWindowProperty *wtypeunused = NULL; - XCBWindowProperty *stateunused = NULL; - XCBSizeHints hints; - u8 hintstatus = 0; - XCBWMHints *wmh = NULL; - XCBWMClass cls = { ._reply = NULL }; - u8 clsstatus = 0; - XCBWMProtocols wmprotocols = { ._reply = NULL, .atoms_len = 0 }; - u8 wmprotocolsstatus = 0; - XCBWindowProperty *strutpreply = NULL; - XCBWindowProperty *strutreply = NULL; - u32 *strutp = NULL; - u32 *strut = NULL; - XCBWindowProperty *netwmnamereply = NULL; - XCBWindowProperty *wmnamereply = NULL; - char *netwmname = NULL; - char *wmname = NULL; - XCBWindowProperty *iconreply = NULL; - pid_t pid = 0; - XCBWindowProperty *motifreply = NULL; /* we do it here before, because we are waiting for replies and for more memory. */ c = createclient(); - /* wait for replies */ - waattributes = XCBGetWindowAttributesReply(_wm.dpy, requests[ManageCookieAttributes]); - wg = XCBGetWindowGeometryReply(_wm.dpy, requests[ManageCookieGeometry]); - transstatus = XCBGetTransientForHintReply(_wm.dpy, requests[ManageCookieTransient], &trans); trans *= !!transstatus; - wtypeunused = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageCookieWType]); - stateunused = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageCookieWState]); - hintstatus = XCBGetWMNormalHintsReply(_wm.dpy, requests[ManageCookieSizeHint], &hints); - wmh = XCBGetWMHintsReply(_wm.dpy, requests[ManageCookieWMHints]); - clsstatus = XCBGetWMClassReply(_wm.dpy, requests[ManageCookieClass], &cls); - wmprotocolsstatus = XCBGetWMProtocolsReply(_wm.dpy, requests[ManageCookieWMProtocol], &wmprotocols); - strutreply = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageCookieStrut]); - strutpreply = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageCookieStrutP]); - netwmnamereply = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageCookieNetWMName]); - wmnamereply = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageCookieWMName]); - iconreply = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageCookieIcon]); - pid = XCBGetPidReply(_wm.dpy, requests[ManageCookiePid]); - motifreply = XCBGetWindowPropertyReply(_wm.dpy, requests[ManageCookieMotif]); - - strutp = strutpreply ? XCBGetWindowPropertyValue(strutpreply) : NULL; - strut = strutreply ? XCBGetWindowPropertyValue(strutpreply) : NULL; + XCBWindowGeometry *wg = replies[ManageClientGeometry]; + XCBGetWindowAttributes *waattributes = replies[ManageClientAttributes]; + XCBWindowProperty *wtypeunused = replies[ManageClientWType]; + XCBWindowProperty *stateunused = replies[ManageClientWState]; + XCBSizeHints *hints = replies[ManageClientWState]; + XCBWMHints *wmh = replies[ManageClientWMHints]; + XCBWMClass *cls = replies[ManageClientClass]; + XCBWMProtocols *wmprotocols = replies[ManageClientWMProtocol]; + XCBWindowProperty *strutpreply = replies[ManageClientStrutP]; + XCBWindowProperty *strutreply = replies[ManageClientStrut]; + XCBWindowProperty *netwmnamereply = replies[ManageClientNetWMName]; + XCBWindowProperty *wmnamereply = replies[ManageClientWMName]; + XCBWindowProperty *iconreply = replies[ManageClientIcon]; + pid_t *pid = replies[ManageClientPid]; + XCBWindowProperty *motifreply = replies[ManageClientMotif]; + XCBWindow *trans = replies[ManageClientTransient]; + + u32 *strutp = strutp = strutpreply ? XCBGetWindowPropertyValue(strutpreply) : NULL; + u32 *strut = strut = strutreply ? XCBGetWindowPropertyValue(strutpreply) : NULL; + if(!c) { goto FAILURE; } c->win = win; - /* On Failure clear flag and ignore hints */ - hints.flags *= !!hintstatus; - if(waattributes && waattributes->override_redirect) { Debug("Override Redirect: [%d]", win); /* theoredically we could manage these but they are a hastle to deal with */ @@ -961,25 +1064,21 @@ managereply(XCBWindow win, XCBCookie requests[ManageCookieLAST]) /* this sets up the desktop which is quite important for some operations */ clientinitcolormap(c, waattributes); - clientinittrans(c, trans); + clientinittrans(c, trans ? *trans : 0); clientinitgeom(c, wg); clientinitwtype(c, wtypeunused); clientinitwstate(c, stateunused); - updatewindowprotocol(c, wmprotocolsstatus ? &wmprotocols : NULL); - netwmname = getnamefromreply(netwmnamereply); - wmname = getnamefromreply(wmnamereply); + updatewindowprotocol(c, wmprotocols); setfloating(c, !!trans); /* Custom stuff */ - setclientpid(c, pid); + setclientpid(c, pid ? *pid : 0); setborderwidth(c, bw); setbordercolor32(c, bcol); setshowdecor(c, showdecor); - updatetitle(c, netwmname, wmname); + updatetitle(c, getnamefromreply(netwmnamereply), getnamefromreply(wmnamereply)); updateborder(c); - updatesizehints(c, &hints); - if(clsstatus) - { updateclass(c, &cls); - } + updatesizehints(c, hints); + updateclass(c, cls); updatewmhints(c, wmh); updatemotifhints(c, motifreply); updateicon(c, iconreply); @@ -997,15 +1096,8 @@ managereply(XCBWindow win, XCBCookie requests[ManageCookieLAST]) updateclientlist(win, ClientListAdd); setclientstate(c, XCB_WINDOW_NORMAL_STATE); - /* add to hash */ addclienthash(c); - - /* inherit previous client state */ - if(c->desktop && c->desktop->sel) - { setfullscreen(c, ISFULLSCREEN(c->desktop->sel) || ISFULLSCREEN(c)); - } - /* propagates border_width, if size doesn't change */ configure(c); /* if its a new bar we dont want to return it as the monitor now manages it */ @@ -1016,28 +1108,9 @@ managereply(XCBWindow win, XCBCookie requests[ManageCookieLAST]) FAILURE: free(c); c = NULL; - goto CLEANUP; CLEANUP: - /* reply cleanup */ - free(waattributes); - free(wg); - free(wtypeunused); - free(stateunused); - free(wmh); - XCBWipeGetWMClass(&cls); - XCBWipeGetWMProtocols(&wmprotocols); - free(strutreply); - free(strutpreply); - free(netwmnamereply); - free(wmnamereply); - free(iconreply); - free(motifreply); + managecleanup(replies); return c; -DISCARD: - for(pid = 0; pid < ManageCookieLAST; ++pid) - { XCBDiscardReply(_wm.dpy, requests[pid]); - } - return NULL; } void diff --git a/src/events.c b/src/events.c index b7391b5..990e2f7 100644 --- a/src/events.c +++ b/src/events.c @@ -824,30 +824,11 @@ maprequest(XCBGenericEvent *event) (void)parent; u8 sync = 0; - Client *c = NULL; - if(!wintoclient(win)) - { - /* only sync if we successfully managed the window */ - XCBCookie cookies[ManageCookieLAST]; - managerequest(win, cookies); - c = managereply(win, cookies); - sync = 1; - } - /* map window before input focus is set cause we just get errors other wise. */ + /* map window first (illusion of responsiveness) */ XCBMapWindow(_wm.dpy, win); - if(c) - { - focus(c); - arrange(c->desktop); - } - /* check if we managed a new bar */ - else if(_wm.selmon->bar && _wm.selmon->bar->win == win) - { - focus(NULL); - arrange(_wm.selmon->desksel); - } - sync = 1; + PropListen(_wm.dpy, win, PropManage); + if(sync) { XCBFlush(_wm.dpy); } @@ -988,20 +969,10 @@ destroynotify(XCBGenericEvent *event) (void)eventwin; - Client *c = NULL; u8 sync = 0; - /* destroyed windows no longer need to be managed */ - if((c = wintoclient(win))) - { - Desktop *desk = c->desktop; - unmanage(c, 1); - if(desk->mon->desksel == desk) - { - focus(NULL); - arrange(desk); - } - sync = 1; - } + + PropListen(_wm.dpy, win, PropUnmanage); + if(sync) { XCBFlush(_wm.dpy); } @@ -1070,19 +1041,9 @@ unmapnotify(XCBGenericEvent *event) (void)eventwin; (void)isconfigure; - Client *c; u8 sync = 0; - if((c = wintoclient(win))) - { - Desktop *desk = c->desktop; - unmanage(c, 0); - if(desk->mon->desksel == desk) - { - focus(NULL); - arrange(desk); - } - sync = 1; - } + + PropListen(_wm.dpy, win, PropUnmanage); if(sync) { XCBFlush(_wm.dpy); diff --git a/src/getprop.c b/src/getprop.c index 0950d59..7afe05c 100644 --- a/src/getprop.c +++ b/src/getprop.c @@ -11,7 +11,7 @@ #include "getprop.h" #include "main.h" -#define QUEUE_SIZE 1024 +#define QUEUE_SIZE 256 /* realistically you wont ever need more than 64 as most of these threads are just waiting for data. */ #define MAX_THREADS 64 @@ -71,6 +71,8 @@ static void UpdateWMName(XCBDisplay *display, __Property__Cookie__ *cookie, XCBC static void UpdatePid(XCBDisplay *display, __Property__Cookie__ *cookie, XCBCookie _XCB_COOKIE); static void UpdateIcon(XCBDisplay *display, __Property__Cookie__ *cookie, XCBCookie _XCB_COOKIE); static void UpdateMotifHints(XCBDisplay *display, __Property__Cookie__ *cookie, XCBCookie _XCB_COOKIE); +static void UpdateManage(XCBDisplay *display, __Property__Cookie__ *cookie, XCBCookie _XCB_COOKIE); +static void UpdateUnmanage(XCBDisplay *display, __Property__Cookie__ *cookie, XCBCookie _XCB_COOKIE); enum PropMode { @@ -96,6 +98,9 @@ static PropHandler __prop_handler[PropLAST] = [PropPid] = { GetPidCookie, UpdatePid }, [PropIcon] = { GetIconCookie, UpdateIcon }, [PropMotifHints] = { GetMotifHintsCookie, UpdateMotifHints }, + [PropManage] = { GetInvalidCookie, UpdateManage }, + [PropUnmanage] = { GetInvalidCookie, UpdateUnmanage }, + [PropExitThread] = { GetInvalidCookie, UpdateInvalid }, }; @@ -366,6 +371,62 @@ UpdateMotifHints(XCBDisplay *display, __Property__Cookie__ *cookie, XCBCookie _X free(prop); } +static void +UpdateManage(XCBDisplay *display, __Property__Cookie__ *cookie, XCBCookie _XCB_COOKIE) +{ + const XCBWindow win = cookie->win; + Client *c; + XCBCookie requests[ManageClientLAST]; + void *replies[ManageClientLAST]; + + (void)_XCB_COOKIE; + + managerequest(win, requests); + managereplies(requests, replies); + + LockMainThread(); + + c = manage(win, replies); + if(c) + { + focus(c); + arrange(c->desktop); + } + else if(_wm.selmon->bar && _wm.selmon->bar->win == win) + { + focus(NULL); + arrange(_wm.selmon->desksel); + } + XCBFlush(_wm.dpy); + UnlockMainThread(); +} + +static void +UpdateUnmanage(XCBDisplay *display, __Property__Cookie__ *cookie, XCBCookie _XCB_COOKIE) +{ + XCBWindow win = cookie->win; + Client *c; + Desktop *desk; + (void)display; + (void)_XCB_COOKIE; + LockMainThread(); + + c = wintoclient(win); + if(c) + { + desk = c->desktop; + unmanage(c, 0); + if(desk->mon->desksel == desk) + { + focus(NULL); + arrange(desk); + } + XCBFlush(_wm.dpy); + } + + UnlockMainThread(); +} + static void UpdateProperty(XCBDisplay *display, __Property__Cookie__ *cookie) { @@ -532,9 +593,8 @@ PropListen(XCBDisplay *display, XCBWindow win, enum PropertyType type) if(usethreads && !full) { CQueueAdd(&__threads.queue, (void *)&cookie); } - /* single thread operation */ - if(!usethreads || full) - { + else + { /* single thread operation */ UpdateProperty(display, &cookie); Debug("Using single threads, full: %d", full); } diff --git a/src/main.c b/src/main.c index 58590d7..685ad59 100644 --- a/src/main.c +++ b/src/main.c @@ -757,9 +757,7 @@ restoremonsession(char *buff, u16 len) { XCBWindow win = pullm->bar->win; unmanage(pullm->bar, 0); - XCBCookie cookies[ManageCookieLAST]; - managerequest(win, cookies); - managereply(win, cookies); + PropListen(_wm.dpy, win, PropManage); } setupbar(pullm, b); } @@ -1019,21 +1017,24 @@ scan(void) if(wins) { const size_t countsz = sizeof(XCBCookie ) * num; - const size_t managecookiesz = sizeof(XCBCookie) * ManageCookieLAST; + const size_t managecookiesz = sizeof(XCBCookie) * ManageClientLAST; + const size_t managerepliesz = sizeof(void *) * ManageClientLAST; XCBCookie *wa = malloc(countsz); XCBCookie *wastates = malloc(countsz); XCBCookie *tfh = malloc(countsz); XCBCookie *managecookies = malloc(managecookiesz * num); + void **managereplys = malloc(managerepliesz * num); XCBGetWindowAttributes **replies = malloc(sizeof(XCBGetWindowAttributes *) * num); XCBGetWindowAttributes **replystates = malloc(sizeof(XCBGetWindowAttributes *) * num); XCBWindow *trans = malloc(sizeof(XCBWindow) * num); - if(!wa || !wastates || !tfh || !managecookies || !replies || !replystates || !trans) + if(!wa || !wastates || !tfh || !managecookies || !managereplys || !replies || !replystates || !trans) { free(wa); free(wastates); free(tfh); free(managecookies); + free(managereplys); free(replies); free(replystates); free(trans); @@ -1046,30 +1047,39 @@ scan(void) /* this specifically queries for the state which wa[i] might fail to provide */ wastates[i] = XCBGetWindowPropertyCookie(_wm.dpy, wins[i], wmatom[WMState], 0L, 2L, False, wmatom[WMState]); tfh[i] = XCBGetTransientForHintCookie(_wm.dpy, wins[i]); - managerequest(wins[i], &managecookies[i * ManageCookieLAST]); + managerequest(wins[i], &managecookies[i * ManageClientLAST]); } uint8_t hastrans = 0; + uint64_t index; /* get them replies back */ for(i = 0; i < num; ++i) { replies[i] = XCBGetWindowAttributesReply(_wm.dpy, wa[i]); replystates[i] = XCBGetWindowAttributesReply(_wm.dpy, wastates[i]); hastrans = XCBGetTransientForHintReply(_wm.dpy, tfh[i], &trans[i]); + index = ManageClientLAST * i; + managereplies(managecookies + index, managereplys + index); if(!hastrans) { trans[i] = 0; } + } + + /* Manage the Windows */ + for(i = 0; i < num; ++i) + { /* override_redirect only needed to be handled for old windows */ /* X auto redirects when running wm so no need to do anything else */ if(replies[i]->override_redirect || trans[i]) { continue; } + index = ManageClientLAST * i; if(replies[i] && replies[i]->map_state == XCB_MAP_STATE_VIEWABLE) - { managereply(wins[i], &managecookies[i * ManageCookieLAST]); + { manage(wins[i], managereplys + index); } else if(replystates[i] && replystates[i]->map_state == XCB_WINDOW_ICONIC_STATE) - { managereply(wins[i], &managecookies[i * ManageCookieLAST]); + { manage(wins[i], managereplys + index); } } @@ -1080,9 +1090,10 @@ scan(void) { if(replies[i]->map_state == XCB_MAP_STATE_VIEWABLE && replystates[i] && replystates[i]->map_state == XCB_WINDOW_ICONIC_STATE) { + index = ManageClientLAST * i; /* technically we shouldnt have to do this but just in case */ if(!wintoclient(wins[i])) - { managereply(wins[i], &managecookies[i * ManageCookieLAST]); + { manage(wins[i], managereplys + i); } } } @@ -1097,6 +1108,7 @@ scan(void) free(wastates); free(tfh); free(managecookies); + free(managereplys); free(replies); free(replystates); free(trans);