From 9354a98208c64b8440429e1ba710164ccb80e4dd Mon Sep 17 00:00:00 2001 From: Lucas de Sena Date: Sat, 21 Feb 2026 03:27:29 +0000 Subject: [PATCH] localize button click routines Keep state local into click_*() for routines relating to button clicks than in global variables around frame.c and main.c --- frame.c | 159 +++++++++++++++++++++++++++++-------------------------- main.c | 62 ++++++++-------------- menu.c | 10 ++-- screen.c | 35 ++++++++++++ screen.h | 1 + 5 files changed, 147 insertions(+), 120 deletions(-) diff --git a/frame.c b/frame.c index 98330c6..191dddf 100644 --- a/frame.c +++ b/frame.c @@ -511,51 +511,6 @@ void redrawclient(Client *c) redraw(c, c->resize); } -extern Client *clickclient; -extern Window clickwindow; -extern Scrn *mbdclick, *mbdscr; - -void clickenter() -{ - if((scr=mbdscr)&& clickwindow == scr->menubardepth) { - mbdclick = scr; - redrawmenubar(scr, scr->menubardepth); - } else { - scr = clickclient->scr; - redraw(clickclient, clickclient->clicked=clickwindow); - } -} - -void clickleave() -{ - if((scr=mbdscr)&& clickwindow == scr->menubardepth) { - mbdclick = NULL; - redrawmenubar(scr, scr->menubardepth); - } else { - scr = clickclient->scr; - clickclient->clicked=None; - redraw(clickclient, clickwindow); - } -} - -void gadgetclicked(Client *c, Window w, XEvent *e) -{ - scr=c->scr; - redraw(c, clickwindow=(clickclient=c)->clicked=w); -} - -void gadgetaborted(Client *c) -{ - Window w; - scr=c->scr; - if((w=c->clicked)) { - c->clicked=None; - redraw(c, w); - } - clickwindow=None; - clickclient=NULL; -} - static Client *topmostmappedclient(Window *children, unsigned int nchildren) { int n; @@ -726,37 +681,93 @@ raisebottommostclient(Scrn *scr) XFree(children); } +extern void get_drag_event(XEvent *event); -void gadgetunclicked(Client *c, XEvent *e) +static Bool is_inside(int x0, int y0, int w, int h, int x, int y) { - extern void adjusticon(Icon *); - Window w; - scr=c->scr; - if((w=c->clicked)) { - c->clicked=None; - redraw(c, w); - if(w==c->close) { - if((c->proto & Pdelete)&&!(e->xbutton.state&ShiftMask)) - sendcmessage(c->window, ATOMS[WM_PROTOCOLS], ATOMS[WM_DELETE_WINDOW]); - else - XKillClient(dpy, c->window); - } else if(w==c->depth) - raiselowerclient(c, -1); - else if(w==c->zoom) { - XWindowAttributes xwa; - XGetWindowAttributes(dpy, c->parent, &xwa); - XMoveWindow(dpy, c->parent, c->x=c->zoomx, c->y=c->zoomy); - resizeclientwindow(c, c->zoomw+c->framewidth, c->zoomh+c->frameheight); - c->zoomx=xwa.x; - c->zoomy=xwa.y; - c->zoomw=xwa.width-c->framewidth; - c->zoomh=xwa.height-c->frameheight; -/* XWarpPointer(dpy, None, c->zoom, 0, 0, 0, 0, 23/2, scr->h5); */ - sendconfig(c); - } else if(w==c->iconify) { - iconify(c); + if (w == 0 || h == 0) + return True; /* caller do not care about where click got released */ + return x >= x0 && y >= y0 && x < x0 + w && y < y0 + h; +} + +enum click { + CLICK_OUT = 0, /* click failed or released outside button */ + CLICK_IN = 1, /* click released inside button */ + CLICK_ALT = 2, /* click released inside button, while Shift pressed */ +}; + +/* check if Button1 is pressed AND released with cursor inside window */ +static enum click got_clicked(Client *c, Window w, Cursor curs, Time time) +{ + XWindowAttributes xwa; + int status; + + XSync(dpy, False); + if (!XGetWindowAttributes(dpy, w, &xwa)) + return CLICK_OUT; + status = XGrabPointer(dpy, w, True, ButtonPressMask|ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, False, curs, time); + if (status != AlreadyGrabbed && status != GrabSuccess) + return CLICK_OUT; + c->clicked = w; + redraw(c, w); + for (;;) { + XEvent event; + + get_drag_event(&event); + if (event.type == ButtonRelease || event.type == ButtonPress) { + c->clicked = None; + redraw(c, w); + XUngrabPointer(dpy, event.xbutton.time); + if (event.type == ButtonPress) + return CLICK_OUT; + if (event.xbutton.button != Button1) + return CLICK_OUT; + if (!is_inside(0, 0, xwa.width, xwa.height, event.xbutton.x, event.xbutton.y)) + return CLICK_OUT; + if (event.xbutton.button & ShiftMask) + return CLICK_ALT; + return CLICK_IN; } } - clickwindow=None; - clickclient=NULL; +} + +void click_close(Client *c, Time time) +{ + enum click click = got_clicked(c, c->close, None, time); + if (click == CLICK_OUT) + return; + else if ((c->proto & Pdelete) && click != CLICK_ALT) + sendcmessage(c->window, ATOMS[WM_PROTOCOLS], ATOMS[WM_DELETE_WINDOW]); + else + XKillClient(dpy, c->window); +} + +void click_depth(Client *c, Time time) +{ + if (got_clicked(c, c->depth, None, time)) { + raiselowerclient(c, -1); + } +} + +void click_zoom(Client *c, Time time) +{ + if (got_clicked(c, c->zoom, None, time)) { + XWindowAttributes xwa; + XGetWindowAttributes(dpy, c->parent, &xwa); + XMoveWindow(dpy, c->parent, c->x=c->zoomx, c->y=c->zoomy); + resizeclientwindow(c, c->zoomw+c->framewidth, c->zoomh+c->frameheight); + c->zoomx=xwa.x; + c->zoomy=xwa.y; + c->zoomw=xwa.width-c->framewidth; + c->zoomh=xwa.height-c->frameheight; + sendconfig(c); + } +} + +void click_iconify(Client *c, Time time) +{ + if (got_clicked(c, c->iconify, None, time)) { + iconify(c); + } } diff --git a/main.c b/main.c index 937ede7..c2a93ea 100644 --- a/main.c +++ b/main.c @@ -72,8 +72,7 @@ typedef struct _DragIcon { } DragIcon; Display *dpy = NULL; -Client *activeclient=NULL, *clickclient=NULL; -Window clickwindow=None; +Client *activeclient=NULL; Scrn *menuactive=NULL; Bool shape_extn=False; char *x_server=NULL; @@ -97,18 +96,15 @@ static unsigned int meta_mask, switch_mask; static char **main_argv; -extern Scrn *mbdclick, *mbdscr; - extern void reparent(Client *); extern void redraw(Client *, Window); extern void redrawclient(Client *); extern void redrawmenubar(Scrn *, Window); extern void resizeclientwindow(Client *c, int, int); -extern void gadgetclicked(Client *c, Window w, XEvent *e); -extern void gadgetunclicked(Client *c, XEvent *e); -extern void gadgetaborted(Client *c); -extern void clickenter(void); -extern void clickleave(void); +extern void click_close(Client *c, Time time); +extern void click_iconify(Client *c, Time time); +extern void click_zoom(Client *c, Time time); +extern void click_depth(Client *c, Time time); extern void menu_on(void); extern void menu_off(void); extern void menubar_enter(Window); @@ -381,7 +377,7 @@ static Bool grab_for_motion(Window w, Window confine, Cursor curs, Time time, in return False; } -static void get_drag_event(XEvent *event) +void get_drag_event(XEvent *event) { static const unsigned int DRAG_MASK = ButtonPressMask|ButtonReleaseMask|Button1MotionMask; @@ -1368,9 +1364,7 @@ int main(int argc, char *argv[]) if(menuactive) { scr=menuactive; menubar_enter(event.xcrossing.window); - } else if(clickwindow && event.xcrossing.window == clickwindow) - clickenter(); - else if(c) { + } else if(c) { if((!c->active) && (c->state==NormalState) && prefs.focus!=FOC_CLICKTOTYPE) { if(activeclient) { @@ -1392,9 +1386,7 @@ int main(int argc, char *argv[]) if(menuactive) { scr=menuactive; menubar_leave(event.xcrossing.window); - } else if(clickwindow && event.xcrossing.window == clickwindow) - clickleave(); - else if(c) { + } else if(c) { if(c->active && event.xcrossing.window==c->parent && event.xcrossing.detail!=NotifyInferior && prefs.focus == FOC_FOLLOWMOUSE) { @@ -1411,7 +1403,7 @@ int main(int argc, char *argv[]) } break; case ButtonPress: - if(clickwindow==None && event.xbutton.button==Button1 && !menuactive) { + if(event.xbutton.button==Button1 && !menuactive) { if(c) { if((!c->active) && prefs.focus==FOC_CLICKTOTYPE && (c->state==NormalState)) { @@ -1449,8 +1441,15 @@ int main(int argc, char *argv[]) else if(event.xbutton.window==c->window || event.xbutton.window==c->parent) ; - else - gadgetclicked(c, event.xbutton.window, &event); + else if (event.xbutton.window == c->close) { + click_close(c, event.xbutton.time); + } else if (event.xbutton.window == c->iconify) { + click_iconify(c, event.xbutton.time); + } else if (event.xbutton.window == c->depth) { + click_depth(c, event.xbutton.time); + } else if (event.xbutton.window == c->zoom) { + click_zoom(c, event.xbutton.time); + } } else if(i && event.xbutton.window==i->window) { abortfocus(); if(i->selected && (event.xbutton.time-last_icon_click)scr, event.xbutton.time, event.xbutton.x_root, event.xbutton.y_root); } } else if(scr&&event.xbutton.window==scr->menubardepth) { - clickwindow=scr->menubardepth; - mbdclick=mbdscr=scr; - redrawmenubar(scr, scr->menubardepth); + click_screendepth(scr, event.xbutton.time); } else if(scr&&event.xbutton.window==scr->menubar && scr->back!=scr->root) { drag_screen(scr, event.xbutton.time, event.xbutton.x_root, event.xbutton.y_root); @@ -1476,13 +1473,7 @@ int main(int argc, char *argv[]) event.xbutton.x, event.xbutton.y); } else ; } else if(event.xbutton.button==3) { - if(scr&&(scr==mbdscr)&&clickwindow==scr->menubardepth) { - mbdclick=NULL; - clickwindow=None; - redrawmenubar(scr, scr->menubardepth); - } else if(clickclient) { - gadgetaborted(clickclient); - } else if(scr&&!menuactive) { + if(scr&&!menuactive) { menu_on(); menuactive=scr; } @@ -1494,18 +1485,7 @@ int main(int argc, char *argv[]) } break; case ButtonRelease: - if(event.xbutton.button==Button1) { - if(clickclient) - gadgetunclicked(clickclient, &event); - else if((scr=mbdscr)&& clickwindow==scr->menubardepth) { - if(mbdclick) { - mbdclick=NULL; - redrawmenubar(scr, scr->menubardepth); - screentoback(); - } - clickwindow=None; - } - } else if(event.xbutton.button==Button3 && (scr=menuactive)) { + if(event.xbutton.button==Button3 && (scr=menuactive)) { menu_off(); menuactive=NULL; } diff --git a/menu.c b/menu.c index 81830db..4b8ccda 100644 --- a/menu.c +++ b/menu.c @@ -50,7 +50,7 @@ extern void setfocus(Window); extern void flushmodules(); extern void wberror(Scrn *, char *); -Scrn *mbdclick=NULL, *mbdscr=NULL; +Scrn *mbdclick=NULL; static struct ToolItem { struct ToolItem *next; @@ -594,7 +594,7 @@ void redrawmenubar(Scrn *scr, Window w) } } else if(w==scr->menubardepth) { /* Menubar depth widget */ - if(!mbdclick) { + if(mbdclick != scr) { XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[SHADOWPEN]); XDrawRectangle(dpy, w, scr->menubargc, 4, scr->h2, 10, scr->h6-scr->h2); } @@ -602,12 +602,12 @@ void redrawmenubar(Scrn *scr, Window w) XFillRectangle(dpy, w, scr->menubargc, 8, scr->h4, 10, scr->h8-scr->h4); XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[SHADOWPEN]); XDrawRectangle(dpy, w, scr->menubargc, 8, scr->h4, 10, scr->h8-scr->h4); - if(mbdclick) + if(mbdclick == scr) XDrawRectangle(dpy, w, scr->menubargc, 4, scr->h2, 10, scr->h6-scr->h2); - XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[mbdclick?SHADOWPEN:SHINEPEN]); + XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[mbdclick==scr?SHADOWPEN:SHINEPEN]); XDrawLine(dpy, w, scr->menubargc, 0, 0, 22, 0); XDrawLine(dpy, w, scr->menubargc, 0, 0, 0, scr->bh-2); - XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[mbdclick?SHINEPEN:SHADOWPEN]); + XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[mbdclick==scr?SHINEPEN:SHADOWPEN]); XDrawLine(dpy, w, scr->menubargc, 0, scr->bh-1, 22, scr->bh-1); XDrawLine(dpy, w, scr->menubargc, 22, 0, 22, scr->bh-1); } else { diff --git a/screen.c b/screen.c index c17a251..49acf41 100644 --- a/screen.c +++ b/screen.c @@ -418,3 +418,38 @@ Scrn *getscreenbyroot(Window w) { return getscreenbyrootext(w, 0); } + +void click_screendepth(Scrn *s, Time time) +{ + extern void redrawmenubar(Scrn *, Window); + extern void get_drag_event(XEvent *event); + extern Scrn *mbdclick; + int status; + + XSync(dpy, False); + status = XGrabPointer(dpy, s->menubardepth, True, ButtonPressMask|ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, False, None, time); + if (status != AlreadyGrabbed && status != GrabSuccess) + return; + mbdclick = s; + redrawmenubar(s, s->menubardepth); + for (;;) { + XEvent event; + + get_drag_event(&event); + if (event.type == ButtonRelease || event.type == ButtonPress) { + mbdclick = NULL; + redrawmenubar(s, s->menubardepth); + XUngrabPointer(dpy, event.xbutton.time); + if (event.type == ButtonPress) + return; + if (event.xbutton.x < 0 || event.xbutton.y < 0) + return; /* pointer to left/top of button */ + if (event.xbutton.x >= 23 || event.xbutton.y >= s->bh) + return; /* pointer to right/bottom of button */ + if(event.xbutton.window == s->menubardepth) + screentoback(); + return; + } + } +} diff --git a/screen.h b/screen.h index 26fef64..4235550 100644 --- a/screen.h +++ b/screen.h @@ -46,6 +46,7 @@ extern void closescreen(); extern Scrn * openscreen(char *, Window); extern void realizescreens(); extern void screentoback(); +extern void click_screendepth(Scrn *s, Time time); void closescreen(); Scrn *openscreen(char *deftitle, Window root);