From: Mike Lowis Date: Wed, 31 Jul 2024 20:31:16 +0000 (-0400) Subject: started revamping client handling from the ground up X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=bced2e934e598593cfa045f5d2de21383bb089c0;p=proto%2Fanvil.git started revamping client handling from the ground up --- diff --git a/anvil.c b/anvil.c index 93b4ada..435bd65 100644 --- a/anvil.c +++ b/anvil.c @@ -1,6 +1,72 @@ #include "anvil.h" #include +/* + + X11 Client Window State Management: + + CreateNotify ->Withdrawn: + Create window detached from any workspace (withdrawn list). + Place window in withdrawn list. + + MapRequest ->Normal: + Read the window properties + Reparent the window to a frame if applicable + Move window to current workspace tiled or floating + Send expose event to window + + UnmapNotify ->Withdrawn/Iconified: + if shaded -> Iconified + Keep window where it is, show only titlebar + else if unloaded + Keep window where it is but unmapped + else + Remove window from workspace. + Place window in withdrawn list. + + DestroyNotify ->Destroyed + Window is destroyed. Free all resources. + +*/ +static void xcreatenotify(XEvent* e) +{ + XCreateWindowEvent* ev = &(e->xcreatewindow); + printf("CREATE(w: 0x%lx)\n", ev->window); + + /* add the new window in the withdrawn state */ + Client_Create(ev->window); +} + +static void xmaprequest(XEvent* e) +{ + XMapRequestEvent* ev = &(e->xmaprequest); + printf("MAP(w: 0x%lx)\n", ev->window); + + /* window request to be shown, let's place it now */ + Client_Show(ev->window); +} + +static void xunmapnotify(XEvent* e) +{ + XUnmapEvent* ev = &(e->xunmap); + printf("UNMAP(e: 0x%lx w: 0x%lx %d)\n", ev->event, ev->window, ev->from_configure); + + /* hide or shade the window */ + Client_Hide(ev->window); +} + +static void xdestroynotify(XEvent* e) +{ + XDestroyWindowEvent* ev = &(e->xdestroywindow); + printf("DESTROY(w: 0x%lx)\n", ev->window); + + /* remove the client altogether */ + Client_Destroy(ev->window); +} + + + + XConf X = {0}; /* Anvil State */ @@ -117,61 +183,6 @@ static void xconfigrequest(XEvent* e) } } -static void xmaprequest(XEvent* e) -{ - XMapRequestEvent* ev = &(e->xmaprequest); - printf("MAP(w: 0x%lx)\n", ev->window); - XWindowAttributes attr; - Location loc = {0}; - if (!mons_find(ev->window, &loc)) - { - if (XGetWindowAttributes(X.disp, ev->window, &attr) && !attr.override_redirect) - { - (void)client_add(ev->window, &attr); - } - } -} - -static void xmapnotify(XEvent* e) -{ - XMapEvent* ev = &(e->xmap); - printf("MAP(e: 0x%lx w: 0x%lx)\n", ev->event, ev->window); - Location loc = {0}; - if (mons_find(ev->window, &loc))// && loc.client->win == ev->window) - { - client_draw(loc.client); - } -} - - -static void xunmapnotify(XEvent* e) -{ - XUnmapEvent* ev = &(e->xunmap); - printf("UNMAP(e: 0x%lx w: 0x%lx %d)\n", ev->event, ev->window, ev->from_configure); - Location loc = {0}; - if (mons_find(ev->window, &loc))// && loc.client->win == ev->window) - { - if (ev->event == X.root && ev->window == loc.client->win) - { - mons_delclient(&loc); - } - else if ( !(loc.client->flags & F_SHADED) ) - { - XUnmapWindow(X.disp, loc.client->frame); - } - } -} - -static void xdestroynotify(XEvent* e) -{ - XDestroyWindowEvent* ev = &(e->xdestroywindow); - printf("DESTROY(w: 0x%lx)\n", ev->window); - Location loc = {0}; - if (mons_find(ev->window, &loc)) - { - mons_delclient(&loc); - } -} static void xclientmsg(XEvent* e) { @@ -220,6 +231,19 @@ static void xexpose(XEvent* e) } } +static void xmapnotify(XEvent* e) +{ + XMapEvent* ev = &(e->xmap); + printf("MAP(e: 0x%lx w: 0x%lx)\n", ev->event, ev->window); + Location loc = {0}; + if (mons_find(ev->window, &loc))// && loc.client->win == ev->window) + { + client_draw(loc.client); + } +} + + + static void xkeypress(XEvent* e) { XKeyEvent* ev = &(e->xkey); @@ -296,16 +320,19 @@ int main(void) keys_init(); atoms_init(); - /* setup event handlers */ + /* setup window life-cycle management event handlers */ + X.eventfns[CreateNotify] = xcreatenotify; + X.eventfns[MapRequest] = xmaprequest; + X.eventfns[UnmapNotify] = xunmapnotify; + X.eventfns[DestroyNotify] = xdestroynotify; + + /* all other events */ + X.eventfns[MapNotify] = xmapnotify; X.eventfns[ButtonPress] = xbtnpress; X.eventfns[ButtonRelease] = xbtnrelease; X.eventfns[MotionNotify] = xbtnmotion; X.eventfns[KeyPress] = xkeypress; X.eventfns[ConfigureRequest] = xconfigrequest; - X.eventfns[MapRequest] = xmaprequest; - X.eventfns[MapNotify] = xmapnotify; - X.eventfns[UnmapNotify] = xunmapnotify; - X.eventfns[DestroyNotify] = xdestroynotify; X.eventfns[ClientMessage] = xclientmsg; X.eventfns[PropertyNotify] = xpropnotify; X.eventfns[EnterNotify] = xenternotify; diff --git a/anvil.h b/anvil.h index 73b5cbb..147a614 100644 --- a/anvil.h +++ b/anvil.h @@ -167,6 +167,11 @@ void mons_tilemove(Location* loc, int hdiff); void mons_activate(Window win); /* client.c */ +void Client_Create(Window win); +void Client_Destroy(Window win); +void Client_Show(Window win); +void Client_Hide(Window win); + void client_initall(void); Client* client_add(Window win, XWindowAttributes* attr); void client_draw(Client* c); diff --git a/client.c b/client.c index a443733..aabfef7 100644 --- a/client.c +++ b/client.c @@ -1,31 +1,106 @@ #include "anvil.h" -void client_initall(void) +void Client_Create(Window win) { - /* TODO: Find all top-level windows and register them correctly + (void)win; + XWindowAttributes attr; + if (XGetWindowAttributes(X.disp, win, &attr) && !attr.override_redirect) + { + /* we care about it, let's add it to withdrawn */ + Client* c = ecalloc(1, sizeof(Client)); + c->win = win; + c->x = attr.x; + c->y = attr.y; + c->w = attr.width + FRAME_WIDTH_SUM; + c->h = attr.height + FRAME_HEIGHT_SUM; + c->next = Withdrawn; + Withdrawn = c; + + /* Reparent the window if applicable */ + c->frame = XCreateSimpleWindow(X.disp, X.root, c->x, c->y, c->w, c->h, 1, X.clr_bdr, X.clr_bg); + XSelectInput(X.disp, c->frame, + ExposureMask | EnterWindowMask | + ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | + SubstructureRedirectMask | SubstructureNotifyMask + ); + XSetWindowAttributes wa; + wa.event_mask = EnterWindowMask | PropertyChangeMask | FocusChangeMask; + wa.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask; + XChangeWindowAttributes(X.disp, c->win, CWEventMask | CWDontPropagate, &wa); + XReparentWindow(X.disp, c->win, c->frame, BORDER_WIDTH, MIN_HEIGHT); + +// /* Map the window and draw the frame */ +// XAddToSaveSet(X.disp, c->win); +// client_readprops(c); +// mons_addclient(c); +// client_show(c, 1); +// client_draw(c); + } +} - * Find all root children with override_redirect set False - * Add them to withdrawn list if WM_STATE = withdrawn - * Add them as floating and unshaded if WM_STATE = Normal - * Add them as floating ad shaded if WM_STATE = Iconic +void Client_Destroy(Window win) +{ + (void)win; +} + +void Client_Show(Window win) +{ + (void)win; +} + +void Client_Hide(Window win) +{ + (void)win; + /* TODO: hiding is complicated... + if window == frame and client_window == unmapped + unmap frame + move to withdrawn list + else if shaded */ - unsigned int nwins; - Window d1, d2, *wins = NULL; - XWindowAttributes attr; - if (XQueryTree(X.disp, X.root, &d1, &d2, &wins, &nwins)) - { - for (unsigned int i = 0; i < nwins; i++) - { - if (XGetWindowAttributes(X.disp, wins[i], &attr) && (attr.override_redirect == False)) - { - Client* c = client_add(wins[i], &attr); - c->flags |= F_FLOATING; - } - } - xfree(wins); - } +// if (ev->event == X.root && ev->window == loc.client->win) +// { +//// mons_delclient(&loc); +// } +// else if ( !(loc.client->flags & F_SHADED) ) +// { +// Client_Shade(ev->window); +//// XUnmapWindow(X.disp, loc.client->frame); +// } + + +} + + + + +void client_initall(void) +{ +// /* TODO: Find all top-level windows and register them correctly +// +// * Find all root children with override_redirect set False +// * Add them to withdrawn list if WM_STATE = withdrawn +// * Add them as floating and unshaded if WM_STATE = Normal +// * Add them as floating ad shaded if WM_STATE = Iconic +// +// */ +// +// unsigned int nwins; +// Window d1, d2, *wins = NULL; +// XWindowAttributes attr; +// if (XQueryTree(X.disp, X.root, &d1, &d2, &wins, &nwins)) +// { +// for (unsigned int i = 0; i < nwins; i++) +// { +// if (XGetWindowAttributes(X.disp, wins[i], &attr) && (attr.override_redirect == False)) +// { +// Client* c = client_add(wins[i], &attr); +// c->flags |= F_FLOATING; +// } +// } +// xfree(wins); +// } } Client* client_add(Window win, XWindowAttributes* attr)