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
This commit is contained in:
Lucas de Sena
2026-02-21 03:27:29 +00:00
parent 0c75c83e3b
commit 9354a98208
5 changed files with 147 additions and 120 deletions

159
frame.c
View File

@@ -511,51 +511,6 @@ void redrawclient(Client *c)
redraw(c, c->resize); 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) static Client *topmostmappedclient(Window *children, unsigned int nchildren)
{ {
int n; int n;
@@ -726,37 +681,93 @@ raisebottommostclient(Scrn *scr)
XFree(children); 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 *); if (w == 0 || h == 0)
Window w; return True; /* caller do not care about where click got released */
scr=c->scr; return x >= x0 && y >= y0 && x < x0 + w && y < y0 + h;
if((w=c->clicked)) { }
c->clicked=None;
redraw(c, w); enum click {
if(w==c->close) { CLICK_OUT = 0, /* click failed or released outside button */
if((c->proto & Pdelete)&&!(e->xbutton.state&ShiftMask)) CLICK_IN = 1, /* click released inside button */
sendcmessage(c->window, ATOMS[WM_PROTOCOLS], ATOMS[WM_DELETE_WINDOW]); CLICK_ALT = 2, /* click released inside button, while Shift pressed */
else };
XKillClient(dpy, c->window);
} else if(w==c->depth) /* check if Button1 is pressed AND released with cursor inside window */
raiselowerclient(c, -1); static enum click got_clicked(Client *c, Window w, Cursor curs, Time time)
else if(w==c->zoom) { {
XWindowAttributes xwa; XWindowAttributes xwa;
XGetWindowAttributes(dpy, c->parent, &xwa); int status;
XMoveWindow(dpy, c->parent, c->x=c->zoomx, c->y=c->zoomy);
resizeclientwindow(c, c->zoomw+c->framewidth, c->zoomh+c->frameheight); XSync(dpy, False);
c->zoomx=xwa.x; if (!XGetWindowAttributes(dpy, w, &xwa))
c->zoomy=xwa.y; return CLICK_OUT;
c->zoomw=xwa.width-c->framewidth; status = XGrabPointer(dpy, w, True, ButtonPressMask|ButtonReleaseMask,
c->zoomh=xwa.height-c->frameheight; GrabModeAsync, GrabModeAsync, False, curs, time);
/* XWarpPointer(dpy, None, c->zoom, 0, 0, 0, 0, 23/2, scr->h5); */ if (status != AlreadyGrabbed && status != GrabSuccess)
sendconfig(c); return CLICK_OUT;
} else if(w==c->iconify) { c->clicked = w;
iconify(c); 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);
}
} }

62
main.c
View File

@@ -72,8 +72,7 @@ typedef struct _DragIcon {
} DragIcon; } DragIcon;
Display *dpy = NULL; Display *dpy = NULL;
Client *activeclient=NULL, *clickclient=NULL; Client *activeclient=NULL;
Window clickwindow=None;
Scrn *menuactive=NULL; Scrn *menuactive=NULL;
Bool shape_extn=False; Bool shape_extn=False;
char *x_server=NULL; char *x_server=NULL;
@@ -97,18 +96,15 @@ static unsigned int meta_mask, switch_mask;
static char **main_argv; static char **main_argv;
extern Scrn *mbdclick, *mbdscr;
extern void reparent(Client *); extern void reparent(Client *);
extern void redraw(Client *, Window); extern void redraw(Client *, Window);
extern void redrawclient(Client *); extern void redrawclient(Client *);
extern void redrawmenubar(Scrn *, Window); extern void redrawmenubar(Scrn *, Window);
extern void resizeclientwindow(Client *c, int, int); extern void resizeclientwindow(Client *c, int, int);
extern void gadgetclicked(Client *c, Window w, XEvent *e); extern void click_close(Client *c, Time time);
extern void gadgetunclicked(Client *c, XEvent *e); extern void click_iconify(Client *c, Time time);
extern void gadgetaborted(Client *c); extern void click_zoom(Client *c, Time time);
extern void clickenter(void); extern void click_depth(Client *c, Time time);
extern void clickleave(void);
extern void menu_on(void); extern void menu_on(void);
extern void menu_off(void); extern void menu_off(void);
extern void menubar_enter(Window); 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; return False;
} }
static void get_drag_event(XEvent *event) void get_drag_event(XEvent *event)
{ {
static const unsigned int DRAG_MASK = ButtonPressMask|ButtonReleaseMask|Button1MotionMask; static const unsigned int DRAG_MASK = ButtonPressMask|ButtonReleaseMask|Button1MotionMask;
@@ -1368,9 +1364,7 @@ int main(int argc, char *argv[])
if(menuactive) { if(menuactive) {
scr=menuactive; scr=menuactive;
menubar_enter(event.xcrossing.window); menubar_enter(event.xcrossing.window);
} else if(clickwindow && event.xcrossing.window == clickwindow) } else if(c) {
clickenter();
else if(c) {
if((!c->active) && (c->state==NormalState) && if((!c->active) && (c->state==NormalState) &&
prefs.focus!=FOC_CLICKTOTYPE) { prefs.focus!=FOC_CLICKTOTYPE) {
if(activeclient) { if(activeclient) {
@@ -1392,9 +1386,7 @@ int main(int argc, char *argv[])
if(menuactive) { if(menuactive) {
scr=menuactive; scr=menuactive;
menubar_leave(event.xcrossing.window); menubar_leave(event.xcrossing.window);
} else if(clickwindow && event.xcrossing.window == clickwindow) } else if(c) {
clickleave();
else if(c) {
if(c->active && event.xcrossing.window==c->parent && if(c->active && event.xcrossing.window==c->parent &&
event.xcrossing.detail!=NotifyInferior && event.xcrossing.detail!=NotifyInferior &&
prefs.focus == FOC_FOLLOWMOUSE) { prefs.focus == FOC_FOLLOWMOUSE) {
@@ -1411,7 +1403,7 @@ int main(int argc, char *argv[])
} }
break; break;
case ButtonPress: case ButtonPress:
if(clickwindow==None && event.xbutton.button==Button1 && !menuactive) { if(event.xbutton.button==Button1 && !menuactive) {
if(c) { if(c) {
if((!c->active) && prefs.focus==FOC_CLICKTOTYPE && if((!c->active) && prefs.focus==FOC_CLICKTOTYPE &&
(c->state==NormalState)) { (c->state==NormalState)) {
@@ -1449,8 +1441,15 @@ int main(int argc, char *argv[])
else if(event.xbutton.window==c->window || else if(event.xbutton.window==c->window ||
event.xbutton.window==c->parent) event.xbutton.window==c->parent)
; ;
else else if (event.xbutton.window == c->close) {
gadgetclicked(c, event.xbutton.window, &event); 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) { } else if(i && event.xbutton.window==i->window) {
abortfocus(); abortfocus();
if(i->selected && (event.xbutton.time-last_icon_click)<dblClickTime) { if(i->selected && (event.xbutton.time-last_icon_click)<dblClickTime) {
@@ -1463,9 +1462,7 @@ int main(int argc, char *argv[])
drag_icon(i->scr, event.xbutton.time, event.xbutton.x_root, event.xbutton.y_root); drag_icon(i->scr, event.xbutton.time, event.xbutton.x_root, event.xbutton.y_root);
} }
} else if(scr&&event.xbutton.window==scr->menubardepth) { } else if(scr&&event.xbutton.window==scr->menubardepth) {
clickwindow=scr->menubardepth; click_screendepth(scr, event.xbutton.time);
mbdclick=mbdscr=scr;
redrawmenubar(scr, scr->menubardepth);
} else if(scr&&event.xbutton.window==scr->menubar && } else if(scr&&event.xbutton.window==scr->menubar &&
scr->back!=scr->root) { scr->back!=scr->root) {
drag_screen(scr, event.xbutton.time, event.xbutton.x_root, event.xbutton.y_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); event.xbutton.x, event.xbutton.y);
} else ; } else ;
} else if(event.xbutton.button==3) { } else if(event.xbutton.button==3) {
if(scr&&(scr==mbdscr)&&clickwindow==scr->menubardepth) { if(scr&&!menuactive) {
mbdclick=NULL;
clickwindow=None;
redrawmenubar(scr, scr->menubardepth);
} else if(clickclient) {
gadgetaborted(clickclient);
} else if(scr&&!menuactive) {
menu_on(); menu_on();
menuactive=scr; menuactive=scr;
} }
@@ -1494,18 +1485,7 @@ int main(int argc, char *argv[])
} }
break; break;
case ButtonRelease: case ButtonRelease:
if(event.xbutton.button==Button1) { if(event.xbutton.button==Button3 && (scr=menuactive)) {
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)) {
menu_off(); menu_off();
menuactive=NULL; menuactive=NULL;
} }

10
menu.c
View File

@@ -50,7 +50,7 @@ extern void setfocus(Window);
extern void flushmodules(); extern void flushmodules();
extern void wberror(Scrn *, char *); extern void wberror(Scrn *, char *);
Scrn *mbdclick=NULL, *mbdscr=NULL; Scrn *mbdclick=NULL;
static struct ToolItem { static struct ToolItem {
struct ToolItem *next; struct ToolItem *next;
@@ -594,7 +594,7 @@ void redrawmenubar(Scrn *scr, Window w)
} }
} else if(w==scr->menubardepth) { } else if(w==scr->menubardepth) {
/* Menubar depth widget */ /* Menubar depth widget */
if(!mbdclick) { if(mbdclick != scr) {
XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[SHADOWPEN]); XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[SHADOWPEN]);
XDrawRectangle(dpy, w, scr->menubargc, 4, scr->h2, 10, scr->h6-scr->h2); 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); XFillRectangle(dpy, w, scr->menubargc, 8, scr->h4, 10, scr->h8-scr->h4);
XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[SHADOWPEN]); XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[SHADOWPEN]);
XDrawRectangle(dpy, w, scr->menubargc, 8, scr->h4, 10, scr->h8-scr->h4); 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); 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, 22, 0);
XDrawLine(dpy, w, scr->menubargc, 0, 0, 0, scr->bh-2); 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, 0, scr->bh-1, 22, scr->bh-1);
XDrawLine(dpy, w, scr->menubargc, 22, 0, 22, scr->bh-1); XDrawLine(dpy, w, scr->menubargc, 22, 0, 22, scr->bh-1);
} else { } else {

View File

@@ -418,3 +418,38 @@ Scrn *getscreenbyroot(Window w)
{ {
return getscreenbyrootext(w, 0); 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;
}
}
}

View File

@@ -46,6 +46,7 @@ extern void closescreen();
extern Scrn * openscreen(char *, Window); extern Scrn * openscreen(char *, Window);
extern void realizescreens(); extern void realizescreens();
extern void screentoback(); extern void screentoback();
extern void click_screendepth(Scrn *s, Time time);
void closescreen(); void closescreen();
Scrn *openscreen(char *deftitle, Window root); Scrn *openscreen(char *deftitle, Window root);