diff --git a/client.c b/client.c index dbfbfe6..89b3bae 100644 --- a/client.c +++ b/client.c @@ -19,6 +19,7 @@ extern struct Library *XLibBase; extern Display *dpy; extern XContext client_context, screen_context; extern Client *activeclient; +extern Scrn *menuactive; extern void setfocus(Window); Client *clients=NULL; @@ -321,6 +322,8 @@ void rmclient(Client *c) closescreen(); scr = c->scr; if(c->active) { + if(!menuactive) + setfocus(None); c->active=False; activeclient = NULL; XInstallColormap(dpy, scr->cmap); diff --git a/frame.c b/frame.c index 191dddf..98330c6 100644 --- a/frame.c +++ b/frame.c @@ -511,6 +511,51 @@ 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; @@ -681,93 +726,37 @@ raisebottommostclient(Scrn *scr) XFree(children); } -extern void get_drag_event(XEvent *event); -static Bool is_inside(int x0, int y0, int w, int h, int x, int y) +void gadgetunclicked(Client *c, XEvent *e) { - 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; + 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); } } -} - -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); - } + clickwindow=None; + clickclient=NULL; } diff --git a/main.c b/main.c index a50aabe..937ede7 100644 --- a/main.c +++ b/main.c @@ -72,7 +72,9 @@ typedef struct _DragIcon { } DragIcon; Display *dpy = NULL; -Client *activeclient=NULL; +Client *activeclient=NULL, *clickclient=NULL; +Window clickwindow=None; +Scrn *menuactive=NULL; Bool shape_extn=False; char *x_server=NULL; char *free_screentitle=NULL; @@ -95,19 +97,24 @@ 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 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 drag_menu(Scrn *s); +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 menu_on(void); +extern void menu_off(void); extern void menubar_enter(Window); extern void menubar_leave(Window); extern void *getitembyhotkey(KeySym); +extern void menuaction(void *); extern Scrn *getscreenbyroot(Window); extern void assimilate(Window, int, int); extern void deselect_all_icons(Scrn *); @@ -374,10 +381,9 @@ static Bool grab_for_motion(Window w, Window confine, Cursor curs, Time time, in return False; } -void get_drag_event(XEvent *event) +static void get_drag_event(XEvent *event) { - static const unsigned int DRAG_MASK = - ButtonPressMask|ButtonReleaseMask|PointerMotionMask|EnterWindowMask|LeaveWindowMask; + static const unsigned int DRAG_MASK = ButtonPressMask|ButtonReleaseMask|Button1MotionMask; for (;;) { fd_set rfds = master_fd_set; @@ -1182,6 +1188,8 @@ int main(int argc, char *argv[]) XGrabButton(dpy, Button1, AnyModifier, c->parent, True, ButtonPressMask, GrabModeSync, GrabModeAsync, None, wm_curs); + if(!menuactive) + setfocus(None); } if(c && (event.xunmap.window==c->window)) { if((!c->reparenting) && c->parent != c->scr->root) { @@ -1357,7 +1365,12 @@ int main(int argc, char *argv[]) } break; case EnterNotify: - if(c) { + if(menuactive) { + scr=menuactive; + menubar_enter(event.xcrossing.window); + } else if(clickwindow && event.xcrossing.window == clickwindow) + clickenter(); + else if(c) { if((!c->active) && (c->state==NormalState) && prefs.focus!=FOC_CLICKTOTYPE) { if(activeclient) { @@ -1376,10 +1389,17 @@ int main(int argc, char *argv[]) } break; case LeaveNotify: - if(c) { + if(menuactive) { + scr=menuactive; + menubar_leave(event.xcrossing.window); + } else if(clickwindow && event.xcrossing.window == clickwindow) + clickleave(); + else if(c) { if(c->active && event.xcrossing.window==c->parent && event.xcrossing.detail!=NotifyInferior && prefs.focus == FOC_FOLLOWMOUSE) { + if(!menuactive) + setfocus(None); c->active=False; activeclient = NULL; instcmap(None); @@ -1391,7 +1411,7 @@ int main(int argc, char *argv[]) } break; case ButtonPress: - if(event.xbutton.button==Button1) { + if(clickwindow==None && event.xbutton.button==Button1 && !menuactive) { if(c) { if((!c->active) && prefs.focus==FOC_CLICKTOTYPE && (c->state==NormalState)) { @@ -1429,15 +1449,8 @@ int main(int argc, char *argv[]) else if(event.xbutton.window==c->window || event.xbutton.window==c->parent) ; - 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 + gadgetclicked(c, event.xbutton.window, &event); } 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) { - click_screendepth(scr, event.xbutton.time); + clickwindow=scr->menubardepth; + mbdclick=mbdscr=scr; + redrawmenubar(scr, scr->menubardepth); } 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); @@ -1461,17 +1476,39 @@ int main(int argc, char *argv[]) event.xbutton.x, event.xbutton.y); } else ; } else if(event.xbutton.button==3) { - if(c == NULL && scr != NULL) { - drag_menu(scr); + if(scr&&(scr==mbdscr)&&clickwindow==scr->menubardepth) { + mbdclick=NULL; + clickwindow=None; + redrawmenubar(scr, scr->menubardepth); + } else if(clickclient) { + gadgetaborted(clickclient); + } else if(scr&&!menuactive) { + menu_on(); + menuactive=scr; } } - if(prefs.focus == FOC_CLICKTOTYPE) { + if(prefs.focus == FOC_CLICKTOTYPE && !menuactive) { XSync(dpy,0); XAllowEvents(dpy,ReplayPointer,CurrentTime); XSync(dpy,0); } 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)) { + menu_off(); + menuactive=NULL; + } break; case MotionNotify: break; diff --git a/menu.c b/menu.c index f6c04a1..81830db 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; +Scrn *mbdclick=NULL, *mbdscr=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 != scr) { + if(!mbdclick) { 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 == scr) + if(mbdclick) XDrawRectangle(dpy, w, scr->menubargc, 4, scr->h2, 10, scr->h6-scr->h2); - XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[mbdclick==scr?SHADOWPEN:SHINEPEN]); + XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[mbdclick?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==scr?SHINEPEN:SHADOWPEN]); + XSetForeground(dpy, scr->menubargc, scr->dri.dri_Pens[mbdclick?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 { @@ -642,8 +642,6 @@ void redrawmenubar(Scrn *scr, Window w) static void leave_item(struct Item *i, Window w) { - if (i == NULL) - return; if(i==activesubitem) activesubitem=NULL; if(i==activeitem) { @@ -710,7 +708,7 @@ static void enter_menu(struct Menu *m, Window w) } } -static void menubar_enter(Window w) +void menubar_enter(Window w) { struct Menu *m; struct Item *i; @@ -734,7 +732,7 @@ static void menubar_enter(Window w) } } -static void menubar_leave(Window w) +void menubar_leave(Window w) { if(activesubitem && activesubitem->win==w) leave_item(activesubitem, w); @@ -742,6 +740,24 @@ static void menubar_leave(Window w) leave_item(activeitem, w); } +void menu_on() +{ + Window r, c; + int rx, ry, x, y; + unsigned int m; + + if(scr->menubarparent) { + XMapRaised(dpy, scr->menubarparent); + XRaiseWindow(dpy, scr->menubar); + XGrabPointer(dpy, scr->back, True, ButtonPressMask|ButtonReleaseMask| + EnterWindowMask|LeaveWindowMask, GrabModeAsync, GrabModeAsync, + scr->back, wm_curs, CurrentTime); + XSetInputFocus(dpy, scr->menubar, RevertToParent, CurrentTime); + if(XQueryPointer(dpy, scr->menubarparent, &r, &c, &rx, &ry, &x, &y, &m)) + menubar_enter(c); + } +} + void menuaction(struct Item *i, struct Item *si) { extern void restart_amiwm(void); @@ -871,6 +887,57 @@ void menuaction(struct Item *i, struct Item *si) } } +void menu_off() +{ + struct Menu *oa; + struct Item *oi, *osi; + + if(scr->menubarparent) { + Window r,p,*children; + unsigned int nchildren; + XUngrabPointer(dpy, CurrentTime); + setfocus((activeclient && activeclient->state==NormalState? + activeclient->window:None)); + XUnmapWindow(dpy, scr->menubarparent); + if(XQueryTree(dpy, scr->back, &r, &p, &children, &nchildren)) { + int n; + Client *c2; + for(n=0; nparent) + break; + if(nmenubar; + XRestackWindows(dpy, ws, 2); + } + if(children) XFree(children); + } + } + if((osi=activesubitem)) + leave_item(osi, osi->win); + if((oi=activeitem)) + leave_item(oi, oi->win); + if((oa=activesubmenu)) { + activesubmenu=NULL; + if(oa->parent) + XUnmapWindow(dpy, oa->parent); + } + if((oa=activemenu)) { + activemenu=NULL; + if(oa->parent) + XUnmapWindow(dpy, oa->parent); + XSetWindowBackground(dpy, oa->win, scr->dri.dri_Pens[BARBLOCKPEN]); + XClearWindow(dpy, oa->win); + redraw_menu(oa, oa->win); + } + if(oi) { + XSync(dpy, False); + menuaction(oi, osi); + } +} + struct Item *getitembyhotkey(KeySym key) { struct Menu *m; @@ -956,61 +1023,3 @@ struct Item *own_items(struct module *m, Scrn *s, endlink->next = c; return chain; } - -void drag_menu(Scrn *s) -{ - extern void get_drag_event(XEvent *event); - Window w; - struct Item *saved_item = NULL; - struct Item *saved_subitem = NULL; - - if (s->menubarparent == None) - return; - XMapRaised(dpy, s->menubarparent); - XRaiseWindow(dpy, s->menubar); - XGrabPointer(dpy, s->back, True, ButtonPressMask|ButtonReleaseMask| - EnterWindowMask|LeaveWindowMask, GrabModeAsync, GrabModeAsync, - s->back, wm_curs, CurrentTime); - if(XQueryPointer(dpy, s->menubarparent, &(Window){0}, &w, - &(int){0}, &(int){0}, &(int){0}, &(int){0}, &(unsigned){0})) - menubar_enter(w); - for (;;) { - XEvent event; - - get_drag_event(&event); - if (event.type == ButtonRelease && event.xbutton.button == Button3) { - XUngrabPointer(dpy, event.xbutton.time); - break; - } else if (event.type == EnterNotify) { - menubar_enter(event.xcrossing.window); - } else if (event.type == LeaveNotify) { - menubar_leave(event.xcrossing.window); - } - } - XUnmapWindow(dpy, s->menubarparent); - saved_item = activeitem; - saved_subitem = activesubitem; - if(activesubitem != NULL) - leave_item(activesubitem, activesubitem->win); - if(activeitem != NULL) - leave_item(activeitem, activeitem->win); - if(activesubmenu != NULL) { - if(activesubmenu->parent) - XUnmapWindow(dpy, activesubmenu->parent); - activesubmenu=NULL; - } - if(activemenu != NULL) { - struct Menu *saved_menu = activemenu; - activemenu=NULL; - if(saved_menu->parent) - XUnmapWindow(dpy, saved_menu->parent); - XSetWindowBackground(dpy, saved_menu->win, s->dri.dri_Pens[BARBLOCKPEN]); - XClearWindow(dpy, saved_menu->win); - redraw_menu(saved_menu, saved_menu->win); - } - if(saved_item != NULL) { - XSync(dpy, False); - menuaction(saved_item, saved_subitem); - } - XLowerWindow(dpy, s->menubar); -} diff --git a/screen.c b/screen.c index 49acf41..c17a251 100644 --- a/screen.c +++ b/screen.c @@ -418,38 +418,3 @@ 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 4235550..26fef64 100644 --- a/screen.h +++ b/screen.h @@ -46,7 +46,6 @@ 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);