From 6685043266583902b41fe0aa4ba38f3e4213fcdb Mon Sep 17 00:00:00 2001 From: Lucas de Sena Date: Wed, 4 Feb 2026 16:12:48 +0000 Subject: [PATCH] make dialog clients be iconified/re-screened with their respective leader client --- client.c | 12 +++++++++++- client.h | 1 + frame.c | 28 +++++++++++++--------------- icc.c | 9 +++++++++ icc.h | 1 + icon.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ icon.h | 2 ++ main.c | 23 ++--------------------- module.c | 1 - screen.c | 32 ++++++++++++++++++++------------ 10 files changed, 107 insertions(+), 50 deletions(-) diff --git a/client.c b/client.c index 4c21172..b152df1 100644 --- a/client.c +++ b/client.c @@ -153,6 +153,9 @@ void open_fscrn(Client *c) c->fsscr = scr = openscreen(NULL, scr->root); c->reparenting = 1; XReparentWindow(dpy, c->window, scr->back, 0, 0); + for (Client *dialog = clients; dialog != NULL; dialog = dialog->next) + if (dialog->leader == c) + reparent_client(c->fsscr, dialog); XResizeWindow(dpy, c->window, scr->width, scr->height); realizescreens(); scr = c->fsscr; @@ -177,6 +180,9 @@ void close_fscrn(Client *c, int state) scr = c->scr; if (state != IconicState) XMapWindow(dpy, c->parent); + for (Client *dialog = clients; dialog != NULL; dialog = dialog->next) + if (dialog->leader == c) + reparent_client(c->scr, dialog); } void setclientstate(Client *c, int state) @@ -348,6 +354,9 @@ void rmclient(Client *c) XDeleteContext(dpy, c->window, client_context); if (c->sizehints) XFree(c->sizehints); + for (Client *dialog = clients; dialog != NULL; dialog = dialog->next) + if (dialog->leader == c) + dialog->leader = NULL; free(c); } @@ -432,7 +441,8 @@ reparent_client(Scrn *s, Client *client) client->scr = s; if(client->parent != client->scr->root) XReparentWindow(dpy, client->parent, s->back, client->x, client->y); - setstringprop(client->window, amiwm_screen, s->deftitle); + if (s->deftitle != NULL) + setstringprop(client->window, amiwm_screen, s->deftitle); sendconfig(client); } diff --git a/client.h b/client.h index 86e989c..c0f6b0b 100644 --- a/client.h +++ b/client.h @@ -15,6 +15,7 @@ struct _Scrn; * @colormap: current colormap. */ typedef struct _Client { + struct _Client *leader; struct _Client *next; struct _Scrn *scr, *fsscr; struct _Icon *icon; diff --git a/frame.c b/frame.c index 61565fd..fd2a609 100644 --- a/frame.c +++ b/frame.c @@ -183,9 +183,14 @@ void reparent(Client *c) getwmstate(c); if(XGetTransientForHint(dpy, c->window, &leader) && - !XFindContext(dpy, leader, client_context, (XPointer *)&lc)) - c->scr = lc->scr; - else if(XGetTextProperty(dpy, c->window, &screen_prop, amiwm_screen)) { + !XFindContext(dpy, leader, client_context, (XPointer *)&lc) && + lc != NULL) { + c->leader = lc; + if (lc->fsscr != NULL) + c->scr = lc->fsscr; + else + c->scr = lc->scr; + } else if(XGetTextProperty(dpy, c->window, &screen_prop, amiwm_screen)) { do { if(s->root == scr->root && (!s->deftitle[screen_prop.nitems])&&!strncmp(s->deftitle, @@ -298,8 +303,9 @@ void reparent(Client *c) cb=(resizable(c->sizehints)? prefs.sizeborder:0); c->close=creategadget(c, c->parent, 0, 0, 19, scr->bh); c->drag=creategadget(c, c->parent, 19, 0, 1, 1); - if(c->wflags&WF_NOICONIFY) + if(c->wflags&WF_NOICONIFY || c->leader != NULL) { c->iconify=None; + } else c->iconify=creategadget(c, c->parent, 0, 0, 23, scr->bh); if(cb) @@ -322,7 +328,8 @@ void reparent(Client *c) #endif XMapSubwindows(dpy, c->parent); sendconfig(c); - setstringprop(c->window, amiwm_screen, scr->deftitle); + if (scr->deftitle != NULL) + setstringprop(c->window, amiwm_screen, scr->deftitle); if(prefs.focus == FOC_CLICKTOTYPE) XGrabButton(dpy, Button1, AnyModifier, c->parent, True, ButtonPressMask, GrabModeSync, GrabModeAsync, None, wm_curs); @@ -747,16 +754,7 @@ void gadgetunclicked(Client *c, XEvent *e) /* XWarpPointer(dpy, None, c->zoom, 0, 0, 0, 0, 23/2, scr->h5); */ sendconfig(c); } else if(w==c->iconify) { - if(!(c->icon)) - createicon(c); - XUnmapWindow(dpy, c->parent); - /* XUnmapWindow(dpy, c->window); */ - adjusticon(c->icon); - XMapWindow(dpy, c->icon->window); - if(c->icon->labelwidth) - XMapWindow(dpy, c->icon->labelwin); - c->icon->mapped=1; - setclientstate(c, IconicState); + iconify(c); } } clickwindow=None; diff --git a/icc.c b/icc.c index aeb739e..2d0ba4b 100644 --- a/icc.c +++ b/icc.c @@ -353,3 +353,12 @@ void handle_client_message(Client *c, XClientMessageEvent *xcme) } } } + +Window get_transient_for(Window w) +{ + Window transient_for = None; + + if (!XGetTransientForHint(dpy, w, &transient_for)) + return None; + return transient_for; +} diff --git a/icc.h b/icc.h index 227e4dc..0b7144f 100644 --- a/icc.h +++ b/icc.h @@ -15,6 +15,7 @@ extern void setstringprop(Window, Atom, char *); extern void propertychange(Client *, Atom); extern long _getprop(Window, Atom, Atom, long, char **); extern void getwflags(Client *); +extern Window get_transient_for(Window); extern Atom wm_state, wm_change_state, wm_protocols, wm_delete, wm_take_focus, wm_colormaps, wm_hints, amiwm_screen, swm_vroot; diff --git a/icon.c b/icon.c index b0fc083..f93ebc8 100644 --- a/icon.c +++ b/icon.c @@ -157,6 +157,11 @@ void reparenticon(Icon *i, Scrn *s, int x, int y) s->icons=i; if(i->client) { reparent_client(s, i->client); + for (Client *dialog = clients; dialog != NULL; dialog = dialog->next) { + if (dialog->leader == i->client) { + reparent_client(s, dialog); + } + } } if(os) selecticon(i); @@ -630,3 +635,46 @@ void free_icon_pms(struct IconPixmaps *pms) free_color_store(dpy, &pms->cs); free_color_store(dpy, &pms->cs2); } + +void iconify(Client *c) +{ + if(!(c->icon)) + createicon(c); + XUnmapWindow(dpy, c->parent); + adjusticon(c->icon); + XMapWindow(dpy, c->icon->window); + if(c->icon->labelwidth) + XMapWindow(dpy, c->icon->labelwin); + c->icon->mapped=1; + setclientstate(c, IconicState); + for (Client *dialog = clients; dialog != NULL; dialog = dialog->next) { + if (dialog->leader == c) { + XUnmapWindow(dpy, dialog->parent); + setclientstate(dialog, IconicState); + } + } +} + +void deiconify(Icon *i) +{ + Client *c = i->client; + + if(i->labelwin) + XUnmapWindow(dpy, i->labelwin); + if(i->window) + XUnmapWindow(dpy, i->window); + i->mapped=0; + deselecticon(i); + if (c != NULL) { + XMapWindow(dpy, c->window); + if(c->parent!=c->scr->root && !c->fullscreen) + XMapRaised(dpy, c->parent); + setclientstate(c, NormalState); + for (Client *dialog = clients; dialog != NULL; dialog = dialog->next) { + if (dialog->leader == c) { + XMapRaised(dpy, dialog->parent); + setclientstate(dialog, NormalState); + } + } + } +} diff --git a/icon.h b/icon.h index 9ca81f4..e9664d7 100644 --- a/icon.h +++ b/icon.h @@ -39,5 +39,7 @@ extern void adjusticon(Icon *); extern void selecticon(Icon *); extern void deselecticon(Icon *); extern void free_icon_pms(struct IconPixmaps *pms); +extern void iconify(Client *); +extern void deiconify(Icon *); #endif diff --git a/main.c b/main.c index 4777704..05c9ef0 100644 --- a/main.c +++ b/main.c @@ -730,7 +730,6 @@ void do_icon_double_click(Scrn *scr) { extern Atom amiwm_appiconmsg; Icon *i, *next; - Client *c; for(i=scr->firstselected; i; i=next) { next=i->nextselected; @@ -738,18 +737,7 @@ void do_icon_double_click(Scrn *scr) dispatch_event_to_broker(mkcmessage(i->window, amiwm_appiconmsg, 0), 0, i->module); } else { - if(i->labelwin) - XUnmapWindow(dpy, i->labelwin); - if(i->window) - XUnmapWindow(dpy, i->window); - i->mapped=0; - deselecticon(i); - if((c=(i->client))) { - XMapWindow(dpy, c->window); - if(c->parent!=c->scr->root && !c->fullscreen) - XMapRaised(dpy, c->parent); - setclientstate(c, NormalState); - } + deiconify(i); } } } @@ -1239,14 +1227,7 @@ int main(int argc, char *argv[]) case IconicState: if(c->parent == c->scr->root) reparent(c); - if(!(c->icon)) - createicon(c); - adjusticon(c->icon); - XMapWindow(dpy, c->icon->window); - if(c->icon->labelwidth) - XMapWindow(dpy, c->icon->labelwin); - c->icon->mapped=1; - setclientstate(c, IconicState); + iconify(c); break; } } diff --git a/module.c b/module.c index a3008e1..34d91d8 100644 --- a/module.c +++ b/module.c @@ -41,7 +41,6 @@ extern void remove_fd_from_set(int); extern void raiselowerclient(Client *, int); extern void wberror(Scrn *, char *); -extern void reparent(Client *); extern Icon *createappicon(struct module *, Window, char *, Pixmap, Pixmap, Pixmap, int, int); diff --git a/screen.c b/screen.c index ed02570..6d8933b 100644 --- a/screen.c +++ b/screen.c @@ -122,46 +122,54 @@ static void scanwins() unsigned int i, nwins; Client *c; Window dw1, dw2, *wins; - XWindowAttributes *pattr=NULL; XPointer dummy; Scrn *s=scr; + XGrabServer(dpy); XQueryTree(dpy, scr->root, &dw1, &dw2, &wins, &nwins); - if(nwins && (pattr=calloc(nwins, sizeof(XWindowAttributes)))) { - for (i = 0; i < nwins; i++) - XGetWindowAttributes(dpy, wins[i], pattr+i); + for (int scan_dialogs = 0; nwins > 0 && scan_dialogs <= 1; scan_dialogs++) { for (i = 0; i < nwins; i++) { + XWindowAttributes attr; + Window leader = None; + + XGetTransientForHint(dpy, wins[i], &leader); + if (!scan_dialogs && leader != None) + continue; /* first pass; skip dialogs */ + if (scan_dialogs && leader == None) + continue; /* second pass; skip leaders */ + XGetWindowAttributes(dpy, wins[i], &attr); if (!XFindContext(dpy, wins[i], client_context, &dummy)) continue; - if (pattr[i].override_redirect) { + if (attr.override_redirect) { if(scr->back!=scr->root && XFindContext(dpy, wins[i], screen_context, &dummy)) - assimilate(wins[i], pattr[i].x, pattr[i].y); + assimilate(wins[i], attr.x, attr.y); continue; } c = createclient(wins[i]); - if (c != 0 && c->window == wins[i]) { - if (pattr[i].map_state == IsViewable) { + if (c != NULL && c->window == wins[i]) { + if (attr.map_state == IsViewable) { c->state=NormalState; getstate(c); reparent(c); - if(c->state==IconicState) { + if(c->state==IconicState && c->leader == NULL) { createicon(c); adjusticon(c->icon); XMapWindow(dpy, c->icon->window); if(c->icon->labelwidth) XMapWindow(dpy, c->icon->labelwin); c->icon->mapped=1; - } else if(c->state==NormalState) + } else if(c->state==NormalState) { XMapRaised(dpy, c->parent); - else + } else { XRaiseWindow(dpy, c->parent); + } c->reparenting=1; scr=s; } } } - free(pattr); } + XUngrabServer(dpy); XFree((void *) wins); cleanupicons(); }