functions_win.c revision b18c2d1e
10bbfda8aSnia/* 20bbfda8aSnia * Functions related to manipulating windows. 30bbfda8aSnia * 40bbfda8aSnia * This doesn't include stuff related to changing their occupation (in 50bbfda8aSnia * functions_workspaces.c), or moving/resizing (in 60bbfda8aSnia * functions_win_moveresize.c), or a few other cases of things 70bbfda8aSnia * peripherally involving windows. 80bbfda8aSnia */ 90bbfda8aSnia 100bbfda8aSnia#include "ctwm.h" 110bbfda8aSnia 120bbfda8aSnia#include <stdlib.h> 130bbfda8aSnia 140bbfda8aSnia#include "colormaps.h" 150bbfda8aSnia#include "ctwm_atoms.h" 160bbfda8aSnia#include "events.h" 170bbfda8aSnia#include "event_handlers.h" 180bbfda8aSnia#include "functions.h" 190bbfda8aSnia#include "functions_defs.h" 200bbfda8aSnia#include "functions_internal.h" 210bbfda8aSnia#include "icons.h" 220bbfda8aSnia#include "occupation.h" 230bbfda8aSnia#include "otp.h" 240bbfda8aSnia#include "parse.h" 250bbfda8aSnia#include "screen.h" 260bbfda8aSnia#include "win_decorations.h" 270bbfda8aSnia#include "win_iconify.h" 280bbfda8aSnia#include "win_ops.h" 290bbfda8aSnia#include "win_utils.h" 300bbfda8aSnia#include "workspace_manager.h" 310bbfda8aSnia 320bbfda8aSnia 330bbfda8aSnia 340bbfda8aSnia/* 350bbfda8aSnia ************************************************************* 360bbfda8aSnia * 370bbfda8aSnia * Moving windows on/off the AutoRaise/AutoLower lists 380bbfda8aSnia * 390bbfda8aSnia ************************************************************* 400bbfda8aSnia */ 410bbfda8aSniaDFHANDLER(autoraise) 420bbfda8aSnia{ 430bbfda8aSnia tmp_win->auto_raise = !tmp_win->auto_raise; 440bbfda8aSnia if(tmp_win->auto_raise) { 450bbfda8aSnia ++(Scr->NumAutoRaises); 460bbfda8aSnia } 470bbfda8aSnia else { 480bbfda8aSnia --(Scr->NumAutoRaises); 490bbfda8aSnia } 500bbfda8aSnia} 510bbfda8aSnia 520bbfda8aSniaDFHANDLER(autolower) 530bbfda8aSnia{ 540bbfda8aSnia tmp_win->auto_lower = !tmp_win->auto_lower; 550bbfda8aSnia if(tmp_win->auto_lower) { 560bbfda8aSnia ++(Scr->NumAutoLowers); 570bbfda8aSnia } 580bbfda8aSnia else { 590bbfda8aSnia --(Scr->NumAutoLowers); 600bbfda8aSnia } 610bbfda8aSnia} 620bbfda8aSnia 630bbfda8aSnia 640bbfda8aSnia 650bbfda8aSnia 660bbfda8aSnia/* 670bbfda8aSnia ************************************************************* 680bbfda8aSnia * 690bbfda8aSnia * Raising and lowering 700bbfda8aSnia * 710bbfda8aSnia ************************************************************* 720bbfda8aSnia */ 730bbfda8aSnia 740bbfda8aSnia/* Separate function because raise and raiseorsqueeze can both need it */ 750bbfda8aSniastatic void 760bbfda8aSniaraise_handler(EF_FULLPROTO) 770bbfda8aSnia{ 780bbfda8aSnia /* check to make sure raise is not from the WindowFunction */ 790bbfda8aSnia if(tmp_win->icon && (w == tmp_win->icon->w) && Context != C_ROOT) { 800bbfda8aSnia OtpRaise(tmp_win, IconWin); 810bbfda8aSnia } 820bbfda8aSnia else { 830bbfda8aSnia OtpRaise(tmp_win, WinWin); 840bbfda8aSnia WMapRaise(tmp_win); 850bbfda8aSnia } 860bbfda8aSnia} 870bbfda8aSnia 880bbfda8aSniaDFHANDLER(raise) 890bbfda8aSnia{ 900bbfda8aSnia raise_handler(EF_ARGS); 910bbfda8aSnia} 920bbfda8aSnia 930bbfda8aSniaDFHANDLER(raiseorsqueeze) 940bbfda8aSnia{ 950bbfda8aSnia /* FIXME using the same double-click ConstrainedMoveTime here */ 960bbfda8aSnia if((eventp->xbutton.time - last_time) < ConstrainedMoveTime) { 970bbfda8aSnia Squeeze(tmp_win); 980bbfda8aSnia return; 990bbfda8aSnia } 1000bbfda8aSnia last_time = eventp->xbutton.time; 1010bbfda8aSnia 1020bbfda8aSnia /* intentional fall-thru into F_RAISE */ 1030bbfda8aSnia raise_handler(EF_ARGS); 1040bbfda8aSnia} 1050bbfda8aSnia 1060bbfda8aSniaDFHANDLER(lower) 1070bbfda8aSnia{ 1080bbfda8aSnia if(tmp_win->icon && (w == tmp_win->icon->w)) { 1090bbfda8aSnia OtpLower(tmp_win, IconWin); 1100bbfda8aSnia } 1110bbfda8aSnia else { 1120bbfda8aSnia OtpLower(tmp_win, WinWin); 1130bbfda8aSnia WMapLower(tmp_win); 1140bbfda8aSnia } 1150bbfda8aSnia} 1160bbfda8aSnia 1170bbfda8aSniaDFHANDLER(raiselower) 1180bbfda8aSnia{ 1190bbfda8aSnia if(!WindowMoved) { 1200bbfda8aSnia if(tmp_win->icon && w == tmp_win->icon->w) { 1210bbfda8aSnia OtpRaiseLower(tmp_win, IconWin); 1220bbfda8aSnia } 1230bbfda8aSnia else { 1240bbfda8aSnia OtpRaiseLower(tmp_win, WinWin); 1250bbfda8aSnia WMapRaiseLower(tmp_win); 1260bbfda8aSnia } 1270bbfda8aSnia } 1280bbfda8aSnia} 1290bbfda8aSnia 1300bbfda8aSnia 1310bbfda8aSnia/* 1320bbfda8aSnia * Smaller raise/lower 1330bbfda8aSnia */ 1340bbfda8aSniaDFHANDLER(tinyraise) 1350bbfda8aSnia{ 1360bbfda8aSnia /* check to make sure raise is not from the WindowFunction */ 1370bbfda8aSnia if(tmp_win->icon && (w == tmp_win->icon->w) && Context != C_ROOT) { 1380bbfda8aSnia OtpTinyRaise(tmp_win, IconWin); 1390bbfda8aSnia } 1400bbfda8aSnia else { 1410bbfda8aSnia OtpTinyRaise(tmp_win, WinWin); 1420bbfda8aSnia WMapRaise(tmp_win); 1430bbfda8aSnia } 1440bbfda8aSnia} 1450bbfda8aSnia 1460bbfda8aSniaDFHANDLER(tinylower) 1470bbfda8aSnia{ 1480bbfda8aSnia /* check to make sure raise is not from the WindowFunction */ 1490bbfda8aSnia if(tmp_win->icon && (w == tmp_win->icon->w) && Context != C_ROOT) { 1500bbfda8aSnia OtpTinyLower(tmp_win, IconWin); 1510bbfda8aSnia } 1520bbfda8aSnia else { 1530bbfda8aSnia OtpTinyLower(tmp_win, WinWin); 1540bbfda8aSnia WMapLower(tmp_win); 1550bbfda8aSnia } 1560bbfda8aSnia} 1570bbfda8aSnia 1580bbfda8aSnia 1590bbfda8aSnia/* 1600bbfda8aSnia * Raising/lowering a non-targetted window 1610bbfda8aSnia */ 1620bbfda8aSniaDFHANDLER(circleup) 1630bbfda8aSnia{ 1640bbfda8aSnia OtpCirculateSubwindows(Scr->currentvs, RaiseLowest); 1650bbfda8aSnia} 1660bbfda8aSnia 1670bbfda8aSniaDFHANDLER(circledown) 1680bbfda8aSnia{ 1690bbfda8aSnia OtpCirculateSubwindows(Scr->currentvs, LowerHighest); 1700bbfda8aSnia} 1710bbfda8aSnia 1720bbfda8aSnia 1730bbfda8aSnia 1740bbfda8aSnia 1750bbfda8aSnia/* 1760bbfda8aSnia ************************************************************* 1770bbfda8aSnia * 1780bbfda8aSnia * Iconification and its inverse. 1790bbfda8aSnia * 1800bbfda8aSnia ************************************************************* 1810bbfda8aSnia */ 1820bbfda8aSniastatic void 1830bbfda8aSniaiconify_handler(EF_FULLPROTO) 1840bbfda8aSnia{ 1850bbfda8aSnia if(tmp_win->isicon) { 1860bbfda8aSnia DeIconify(tmp_win); 1870bbfda8aSnia } 1880bbfda8aSnia else if(func == F_ICONIFY) { 1890bbfda8aSnia Iconify(tmp_win, eventp->xbutton.x_root - 5, 1900bbfda8aSnia eventp->xbutton.y_root - 5); 1910bbfda8aSnia } 1920bbfda8aSnia} 1930bbfda8aSnia 1940bbfda8aSniaDFHANDLER(deiconify) 1950bbfda8aSnia{ 1960bbfda8aSnia iconify_handler(EF_ARGS); 1970bbfda8aSnia} 1980bbfda8aSniaDFHANDLER(iconify) 1990bbfda8aSnia{ 2000bbfda8aSnia iconify_handler(EF_ARGS); 2010bbfda8aSnia} 2020bbfda8aSnia 2030bbfda8aSnia 2040bbfda8aSnia/* 2050bbfda8aSnia * This is a synthetic function; it only exists as an action in some 2060bbfda8aSnia * magic menus like TwmWindows (x-ref f.winwarp as well). It acts as a 2070bbfda8aSnia * sort of deiconify, so I've stuck it here. 2080bbfda8aSnia */ 2090bbfda8aSniaDFHANDLER(popup) 2100bbfda8aSnia{ 2110bbfda8aSnia /* 2120bbfda8aSnia * This is a synthetic function; it exists only to be called 2130bbfda8aSnia * internally from the various magic menus like TwmWindows 2140bbfda8aSnia * etc. 2150bbfda8aSnia */ 2160bbfda8aSnia tmp_win = (TwmWindow *)action; 2170bbfda8aSnia if(! tmp_win) { 2180bbfda8aSnia return; 2190bbfda8aSnia } 2200bbfda8aSnia if(Scr->WindowFunction.func != 0) { 2210bbfda8aSnia ExecuteFunction(Scr->WindowFunction.func, 2220bbfda8aSnia Scr->WindowFunction.item->action, 2230bbfda8aSnia w, tmp_win, eventp, C_FRAME, false); 2240bbfda8aSnia } 2250bbfda8aSnia else { 2260bbfda8aSnia DeIconify(tmp_win); 2270bbfda8aSnia OtpRaise(tmp_win, WinWin); 2280bbfda8aSnia } 2290bbfda8aSnia} 2300bbfda8aSnia 2310bbfda8aSnia 2320bbfda8aSnia 2330bbfda8aSnia 2340bbfda8aSnia/* 2350bbfda8aSnia ************************************************************* 2360bbfda8aSnia * 2370bbfda8aSnia * Focus locking 2380bbfda8aSnia * 2390bbfda8aSnia ************************************************************* 2400bbfda8aSnia */ 2410bbfda8aSniaDFHANDLER(focus) 2420bbfda8aSnia{ 2430bbfda8aSnia if(!tmp_win->isicon) { 2440bbfda8aSnia if(!Scr->FocusRoot && Scr->Focus == tmp_win) { 2450bbfda8aSnia FocusOnRoot(); 2460bbfda8aSnia } 2470bbfda8aSnia else { 2480bbfda8aSnia InstallWindowColormaps(0, tmp_win); 2490bbfda8aSnia SetFocus(tmp_win, eventp->xbutton.time); 2500bbfda8aSnia Scr->FocusRoot = false; 2510bbfda8aSnia } 2520bbfda8aSnia } 2530bbfda8aSnia} 2540bbfda8aSnia 2550bbfda8aSniaDFHANDLER(unfocus) 2560bbfda8aSnia{ 2570bbfda8aSnia FocusOnRoot(); 2580bbfda8aSnia} 2590bbfda8aSnia 2600bbfda8aSnia 2610bbfda8aSnia 2620bbfda8aSnia 2630bbfda8aSnia/* 2640bbfda8aSnia ************************************************************* 2650bbfda8aSnia * 2660bbfda8aSnia * Window destruction 2670bbfda8aSnia * 2680bbfda8aSnia ************************************************************* 2690bbfda8aSnia */ 2700bbfda8aSniastatic void 2710bbfda8aSniaSendDeleteWindowMessage(TwmWindow *tmp, Time timestamp) 2720bbfda8aSnia{ 2730bbfda8aSnia send_clientmessage(tmp->w, XA_WM_DELETE_WINDOW, timestamp); 2740bbfda8aSnia} 2750bbfda8aSnia 2760bbfda8aSniaDFHANDLER(delete) 2770bbfda8aSnia{ 2780bbfda8aSnia if(tmp_win->isiconmgr) { /* don't send ourself a message */ 2790bbfda8aSnia HideIconManager(); 2800bbfda8aSnia return; 2810bbfda8aSnia } 282b18c2d1eSnia if(tmp_win->iswspmgr 283b18c2d1eSnia#ifdef WINBOX 284b18c2d1eSnia || tmp_win->iswinbox 285b18c2d1eSnia#endif 2860bbfda8aSnia || (Scr->workSpaceMgr.occupyWindow 2870bbfda8aSnia && tmp_win == Scr->workSpaceMgr.occupyWindow->twm_win)) { 2880bbfda8aSnia XBell(dpy, 0); 2890bbfda8aSnia return; 2900bbfda8aSnia } 2910bbfda8aSnia if(tmp_win->protocols & DoesWmDeleteWindow) { 2920bbfda8aSnia SendDeleteWindowMessage(tmp_win, EventTime); 2930bbfda8aSnia if(ButtonPressed != -1) { 2940bbfda8aSnia XEvent kev; 2950bbfda8aSnia 2960bbfda8aSnia XMaskEvent(dpy, ButtonReleaseMask, &kev); 2970bbfda8aSnia if(kev.xbutton.window == tmp_win->w) { 2980bbfda8aSnia kev.xbutton.window = Scr->Root; 2990bbfda8aSnia } 3000bbfda8aSnia XPutBackEvent(dpy, &kev); 3010bbfda8aSnia } 3020bbfda8aSnia return; 3030bbfda8aSnia } 3040bbfda8aSnia XBell(dpy, 0); 3050bbfda8aSnia} 3060bbfda8aSnia 3070bbfda8aSniaDFHANDLER(destroy) 3080bbfda8aSnia{ 309b18c2d1eSnia if(tmp_win->isiconmgr || tmp_win->iswspmgr 310b18c2d1eSnia#ifdef WINBOX 311b18c2d1eSnia || tmp_win->iswinbox 312b18c2d1eSnia#endif 3130bbfda8aSnia || (Scr->workSpaceMgr.occupyWindow 3140bbfda8aSnia && tmp_win == Scr->workSpaceMgr.occupyWindow->twm_win)) { 3150bbfda8aSnia XBell(dpy, 0); 3160bbfda8aSnia return; 3170bbfda8aSnia } 3180bbfda8aSnia XKillClient(dpy, tmp_win->w); 3190bbfda8aSnia if(ButtonPressed != -1) { 3200bbfda8aSnia XEvent kev; 3210bbfda8aSnia 3220bbfda8aSnia XMaskEvent(dpy, ButtonReleaseMask, &kev); 3230bbfda8aSnia if(kev.xbutton.window == tmp_win->w) { 3240bbfda8aSnia kev.xbutton.window = Scr->Root; 3250bbfda8aSnia } 3260bbfda8aSnia XPutBackEvent(dpy, &kev); 3270bbfda8aSnia } 3280bbfda8aSnia} 3290bbfda8aSnia 3300bbfda8aSniaDFHANDLER(deleteordestroy) 3310bbfda8aSnia{ 3320bbfda8aSnia if(tmp_win->isiconmgr) { 3330bbfda8aSnia HideIconManager(); 3340bbfda8aSnia return; 3350bbfda8aSnia } 336b18c2d1eSnia if(tmp_win->iswspmgr 337b18c2d1eSnia#ifdef WINBOX 338b18c2d1eSnia || tmp_win->iswinbox 339b18c2d1eSnia#endif 3400bbfda8aSnia || (Scr->workSpaceMgr.occupyWindow 3410bbfda8aSnia && tmp_win == Scr->workSpaceMgr.occupyWindow->twm_win)) { 3420bbfda8aSnia XBell(dpy, 0); 3430bbfda8aSnia return; 3440bbfda8aSnia } 3450bbfda8aSnia if(tmp_win->protocols & DoesWmDeleteWindow) { 3460bbfda8aSnia SendDeleteWindowMessage(tmp_win, EventTime); 3470bbfda8aSnia } 3480bbfda8aSnia else { 3490bbfda8aSnia XKillClient(dpy, tmp_win->w); 3500bbfda8aSnia } 3510bbfda8aSnia if(ButtonPressed != -1) { 3520bbfda8aSnia XEvent kev; 3530bbfda8aSnia 3540bbfda8aSnia XMaskEvent(dpy, ButtonReleaseMask, &kev); 3550bbfda8aSnia if(kev.xbutton.window == tmp_win->w) { 3560bbfda8aSnia kev.xbutton.window = Scr->Root; 3570bbfda8aSnia } 3580bbfda8aSnia XPutBackEvent(dpy, &kev); 3590bbfda8aSnia } 3600bbfda8aSnia} 3610bbfda8aSnia 3620bbfda8aSnia 3630bbfda8aSnia 3640bbfda8aSnia 3650bbfda8aSnia/* 3660bbfda8aSnia ************************************************************* 3670bbfda8aSnia * 3680bbfda8aSnia * Messing with OnTopPriority bits 3690bbfda8aSnia * 3700bbfda8aSnia ************************************************************* 3710bbfda8aSnia */ 3720bbfda8aSniastatic void 3730bbfda8aSniaotp_priority_handler(EF_FULLPROTO) 3740bbfda8aSnia{ 3750bbfda8aSnia WinType wintype; 3760bbfda8aSnia int pri; 3770bbfda8aSnia char *endp; 3780bbfda8aSnia 3790bbfda8aSnia if(tmp_win->icon && w == tmp_win->icon->w) { 3800bbfda8aSnia wintype = IconWin; 3810bbfda8aSnia } 3820bbfda8aSnia else { 3830bbfda8aSnia wintype = WinWin; 3840bbfda8aSnia } 3850bbfda8aSnia switch(func) { 3860bbfda8aSnia case F_PRIORITYSWITCHING: 3870bbfda8aSnia OtpToggleSwitching(tmp_win, wintype); 3880bbfda8aSnia break; 3890bbfda8aSnia case F_SETPRIORITY: 3900bbfda8aSnia pri = (int)strtol(action, &endp, 10); 3910bbfda8aSnia OtpSetPriority(tmp_win, wintype, pri, 3920bbfda8aSnia (*endp == '<' || *endp == 'b') ? Below : Above); 3930bbfda8aSnia break; 3940bbfda8aSnia case F_CHANGEPRIORITY: 3950bbfda8aSnia OtpChangePriority(tmp_win, wintype, atoi(action)); 3960bbfda8aSnia break; 3970bbfda8aSnia case F_SWITCHPRIORITY: 3980bbfda8aSnia OtpSwitchPriority(tmp_win, wintype); 3990bbfda8aSnia break; 4000bbfda8aSnia } 4010bbfda8aSnia 4020bbfda8aSnia /* 4030bbfda8aSnia * Stash up our current flags if there aren't any set yet. This is 4040bbfda8aSnia * necessary because otherwise the EWMH prop we [may] stash below 4050bbfda8aSnia * would be taken as gospel on restart, when it shouldn't be. 4060bbfda8aSnia */ 4070bbfda8aSnia OtpStashAflagsFirstTime(tmp_win); 4080bbfda8aSnia 4090bbfda8aSnia#ifdef EWMH 4100bbfda8aSnia /* 4110bbfda8aSnia * We changed the priority somehow, so we may have changed where it 4120bbfda8aSnia * sits relative to the middle. So trigger rechecking/setting of the 4130bbfda8aSnia * _STATE_{ABOVE,BELOW}. (_ABOVE in changes arg covers both) 4140bbfda8aSnia */ 4150bbfda8aSnia EwmhSet_NET_WM_STATE(tmp_win, EWMH_STATE_ABOVE); 4160bbfda8aSnia#endif /* EWMH */ 4170bbfda8aSnia} 4180bbfda8aSniaDFHANDLER(priorityswitching) 4190bbfda8aSnia{ 4200bbfda8aSnia otp_priority_handler(EF_ARGS); 4210bbfda8aSnia} 4220bbfda8aSniaDFHANDLER(switchpriority) 4230bbfda8aSnia{ 4240bbfda8aSnia otp_priority_handler(EF_ARGS); 4250bbfda8aSnia} 4260bbfda8aSniaDFHANDLER(setpriority) 4270bbfda8aSnia{ 4280bbfda8aSnia otp_priority_handler(EF_ARGS); 4290bbfda8aSnia} 4300bbfda8aSniaDFHANDLER(changepriority) 4310bbfda8aSnia{ 4320bbfda8aSnia otp_priority_handler(EF_ARGS); 4330bbfda8aSnia} 4340bbfda8aSnia 4350bbfda8aSnia 4360bbfda8aSnia 4370bbfda8aSnia 4380bbfda8aSnia/* 4390bbfda8aSnia ************************************************************* 4400bbfda8aSnia * 4410bbfda8aSnia * Some misc utilities 4420bbfda8aSnia * 4430bbfda8aSnia ************************************************************* 4440bbfda8aSnia */ 4450bbfda8aSniaDFHANDLER(saveyourself) 4460bbfda8aSnia{ 4470bbfda8aSnia if(tmp_win->protocols & DoesWmSaveYourself) { 4480bbfda8aSnia send_clientmessage(tmp_win->w, XA_WM_SAVE_YOURSELF, EventTime); 4490bbfda8aSnia } 4500bbfda8aSnia else { 4510bbfda8aSnia XBell(dpy, 0); 4520bbfda8aSnia } 4530bbfda8aSnia} 4540bbfda8aSnia 4550bbfda8aSniaDFHANDLER(colormap) 4560bbfda8aSnia{ 4570bbfda8aSnia /* XXX Window targetting; should this be on the Defer list? */ 4580bbfda8aSnia if(strcmp(action, COLORMAP_NEXT) == 0) { 4590bbfda8aSnia BumpWindowColormap(tmp_win, 1); 4600bbfda8aSnia } 4610bbfda8aSnia else if(strcmp(action, COLORMAP_PREV) == 0) { 4620bbfda8aSnia BumpWindowColormap(tmp_win, -1); 4630bbfda8aSnia } 4640bbfda8aSnia else { 4650bbfda8aSnia BumpWindowColormap(tmp_win, 0); 4660bbfda8aSnia } 4670bbfda8aSnia} 4680bbfda8aSnia 4690bbfda8aSniaDFHANDLER(refresh) 4700bbfda8aSnia{ 4710bbfda8aSnia XSetWindowAttributes attributes; 4720bbfda8aSnia unsigned long valuemask; 4730bbfda8aSnia 4740bbfda8aSnia valuemask = CWBackPixel; 4750bbfda8aSnia attributes.background_pixel = Scr->Black; 4760bbfda8aSnia w = XCreateWindow(dpy, Scr->Root, 0, 0, 4770bbfda8aSnia Scr->rootw, 4780bbfda8aSnia Scr->rooth, 4790bbfda8aSnia 0, 4800bbfda8aSnia CopyFromParent, CopyFromParent, 4810bbfda8aSnia CopyFromParent, valuemask, 4820bbfda8aSnia &attributes); 4830bbfda8aSnia XMapWindow(dpy, w); 4840bbfda8aSnia XDestroyWindow(dpy, w); 4850bbfda8aSnia XFlush(dpy); 4860bbfda8aSnia 4870bbfda8aSnia} 4880bbfda8aSnia 4890bbfda8aSniaDFHANDLER(winrefresh) 4900bbfda8aSnia{ 4910bbfda8aSnia if(context == C_ICON && tmp_win->icon && tmp_win->icon->w) 4920bbfda8aSnia w = XCreateSimpleWindow(dpy, tmp_win->icon->w, 4930bbfda8aSnia 0, 0, 9999, 9999, 0, Scr->Black, Scr->Black); 4940bbfda8aSnia else 4950bbfda8aSnia w = XCreateSimpleWindow(dpy, tmp_win->frame, 4960bbfda8aSnia 0, 0, 9999, 9999, 0, Scr->Black, Scr->Black); 4970bbfda8aSnia 4980bbfda8aSnia XMapWindow(dpy, w); 4990bbfda8aSnia XDestroyWindow(dpy, w); 5000bbfda8aSnia XFlush(dpy); 5010bbfda8aSnia} 5020bbfda8aSnia 5030bbfda8aSnia 5040bbfda8aSnia 5050bbfda8aSnia 5060bbfda8aSnia/* 5070bbfda8aSnia ************************************************************* 5080bbfda8aSnia * 5090bbfda8aSnia * Window squeezing related bits 5100bbfda8aSnia * 5110bbfda8aSnia ************************************************************* 5120bbfda8aSnia */ 5130bbfda8aSniaDFHANDLER(squeeze) 5140bbfda8aSnia{ 5150bbfda8aSnia Squeeze(tmp_win); 5160bbfda8aSnia} 5170bbfda8aSnia 5180bbfda8aSniaDFHANDLER(unsqueeze) 5190bbfda8aSnia{ 5200bbfda8aSnia if(tmp_win->squeezed) { 5210bbfda8aSnia Squeeze(tmp_win); 5220bbfda8aSnia } 5230bbfda8aSnia} 5240bbfda8aSnia 5250bbfda8aSnia 5260bbfda8aSniaDFHANDLER(movetitlebar) 5270bbfda8aSnia{ 5280bbfda8aSnia Window grabwin; 5290bbfda8aSnia Window rootw; 5300bbfda8aSnia int deltax = 0, newx = 0; 5310bbfda8aSnia int origX; 5320bbfda8aSnia int origNum; 5330bbfda8aSnia SqueezeInfo *si; 5340bbfda8aSnia 5350bbfda8aSnia PopDownMenu(); 5360bbfda8aSnia if(tmp_win->squeezed || 5370bbfda8aSnia !tmp_win->squeeze_info || 5380bbfda8aSnia !tmp_win->title_w || 5390bbfda8aSnia context == C_ICON) { 5400bbfda8aSnia XBell(dpy, 0); 5410bbfda8aSnia return; 5420bbfda8aSnia } 5430bbfda8aSnia 5440bbfda8aSnia /* If the SqueezeInfo isn't copied yet, do it now */ 5450bbfda8aSnia if(!tmp_win->squeeze_info_copied) { 5460bbfda8aSnia SqueezeInfo *s = malloc(sizeof(SqueezeInfo)); 5470bbfda8aSnia if(!s) { 5480bbfda8aSnia return; 5490bbfda8aSnia } 5500bbfda8aSnia *s = *tmp_win->squeeze_info; 5510bbfda8aSnia tmp_win->squeeze_info = s; 5520bbfda8aSnia tmp_win->squeeze_info_copied = true; 5530bbfda8aSnia } 5540bbfda8aSnia si = tmp_win->squeeze_info; 5550bbfda8aSnia 5560bbfda8aSnia if(si->denom != 0) { 5570bbfda8aSnia int target_denom = tmp_win->frame_width; 5580bbfda8aSnia /* 5590bbfda8aSnia * If not pixel based, scale the denominator to equal the 5600bbfda8aSnia * window width, so the numerator equals pixels. 5610bbfda8aSnia * That way we can just modify it by pixel units, just 5620bbfda8aSnia * like the other case. 5630bbfda8aSnia */ 5640bbfda8aSnia 5650bbfda8aSnia if(si->denom != target_denom) { 5660bbfda8aSnia float scale = (float)target_denom / si->denom; 5670bbfda8aSnia si->num *= scale; 5680bbfda8aSnia si->denom = target_denom; /* s->denom *= scale; */ 5690bbfda8aSnia } 5700bbfda8aSnia } 5710bbfda8aSnia 5720bbfda8aSnia /* now move the mouse */ 573b18c2d1eSnia#ifdef WINBOX 5740bbfda8aSnia if(tmp_win->winbox) { 5750bbfda8aSnia XTranslateCoordinates(dpy, Scr->Root, tmp_win->winbox->window, 5760bbfda8aSnia eventp->xbutton.x_root, eventp->xbutton.y_root, 5770bbfda8aSnia &eventp->xbutton.x_root, &eventp->xbutton.y_root, &JunkChild); 5780bbfda8aSnia } 579b18c2d1eSnia#endif 5800bbfda8aSnia /* 5810bbfda8aSnia * the event is always a button event, since key events 5820bbfda8aSnia * are "weeded out" - although incompletely only 5830bbfda8aSnia * F_MOVE and F_RESIZE - in HandleKeyPress(). 5840bbfda8aSnia */ 5850bbfda8aSnia 5860bbfda8aSnia /* 5870bbfda8aSnia * XXX This var may be actually unnecessary; it's used only 5880bbfda8aSnia * once as an arg to a later X call, but during that time I 5890bbfda8aSnia * don't believe anything can mutate eventp or anything near 5900bbfda8aSnia * the root. However, due to the union nature of XEvent, 5910bbfda8aSnia * it's hard to be sure without more investigation, so I 5920bbfda8aSnia * leave the intermediate var for now. 5930bbfda8aSnia * 5940bbfda8aSnia * Note that we're looking inside the XButtonEvent member 5950bbfda8aSnia * here, but other bits of this code later look at the 5960bbfda8aSnia * XMotionEvent piece. This should be further investigated 5970bbfda8aSnia * and resolved; they can't both be right (though the 5980bbfda8aSnia * structure of the structs are such that almost all the 5990bbfda8aSnia * similar elements are in the same place, at least in 6000bbfda8aSnia * theory). 6010bbfda8aSnia */ 6020bbfda8aSnia rootw = eventp->xbutton.root; 6030bbfda8aSnia 6040bbfda8aSnia EventHandler[EnterNotify] = HandleUnknown; 6050bbfda8aSnia EventHandler[LeaveNotify] = HandleUnknown; 6060bbfda8aSnia 6070bbfda8aSnia if(!Scr->NoGrabServer) { 6080bbfda8aSnia XGrabServer(dpy); 6090bbfda8aSnia } 6100bbfda8aSnia 6110bbfda8aSnia grabwin = Scr->Root; 612b18c2d1eSnia#ifdef WINBOX 6130bbfda8aSnia if(tmp_win->winbox) { 6140bbfda8aSnia grabwin = tmp_win->winbox->window; 6150bbfda8aSnia } 616b18c2d1eSnia#endif 6170bbfda8aSnia XGrabPointer(dpy, grabwin, True, 6180bbfda8aSnia ButtonPressMask | ButtonReleaseMask | 6190bbfda8aSnia ButtonMotionMask | PointerMotionMask, /* PointerMotionHintMask */ 6200bbfda8aSnia GrabModeAsync, GrabModeAsync, grabwin, Scr->MoveCursor, CurrentTime); 6210bbfda8aSnia 6220bbfda8aSnia#if 0 /* what's this for ? */ 6230bbfda8aSnia if(! tmp_win->icon || w != tmp_win->icon->w) { 6240bbfda8aSnia XTranslateCoordinates(dpy, w, tmp_win->frame, 6250bbfda8aSnia eventp->xbutton.x, 6260bbfda8aSnia eventp->xbutton.y, 6270bbfda8aSnia &DragX, &DragY, &JunkChild); 6280bbfda8aSnia 6290bbfda8aSnia w = tmp_win->frame; 6300bbfda8aSnia } 6310bbfda8aSnia#endif 6320bbfda8aSnia 6330bbfda8aSnia DragWindow = None; 6340bbfda8aSnia 6350bbfda8aSnia XGetGeometry(dpy, tmp_win->title_w, &JunkRoot, &origDragX, &origDragY, 6360bbfda8aSnia &DragWidth, &DragHeight, &DragBW, 6370bbfda8aSnia &JunkDepth); 6380bbfda8aSnia 6390bbfda8aSnia origX = eventp->xbutton.x_root; 6400bbfda8aSnia origNum = si->num; 6410bbfda8aSnia 6420bbfda8aSnia if(menuFromFrameOrWindowOrTitlebar) { 6430bbfda8aSnia /* warp the pointer to the middle of the window */ 6440bbfda8aSnia XWarpPointer(dpy, None, Scr->Root, 0, 0, 0, 0, 6450bbfda8aSnia origDragX + DragWidth / 2, 6460bbfda8aSnia origDragY + DragHeight / 2); 6470bbfda8aSnia XFlush(dpy); 6480bbfda8aSnia } 6490bbfda8aSnia 6500bbfda8aSnia while(1) { 6510bbfda8aSnia long releaseEvent = menuFromFrameOrWindowOrTitlebar ? 6520bbfda8aSnia ButtonPress : ButtonRelease; 6530bbfda8aSnia long movementMask = menuFromFrameOrWindowOrTitlebar ? 6540bbfda8aSnia PointerMotionMask : ButtonMotionMask; 6550bbfda8aSnia 6560bbfda8aSnia /* block until there is an interesting event */ 6570bbfda8aSnia XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | 6580bbfda8aSnia EnterWindowMask | LeaveWindowMask | 6590bbfda8aSnia ExposureMask | movementMask | 6600bbfda8aSnia VisibilityChangeMask, &Event); 6610bbfda8aSnia 6620bbfda8aSnia /* throw away enter and leave events until release */ 6630bbfda8aSnia if(Event.xany.type == EnterNotify || 6640bbfda8aSnia Event.xany.type == LeaveNotify) { 6650bbfda8aSnia continue; 6660bbfda8aSnia } 6670bbfda8aSnia 6680bbfda8aSnia if(Event.type == MotionNotify) { 6690bbfda8aSnia /* discard any extra motion events before a logical release */ 6700bbfda8aSnia while(XCheckMaskEvent(dpy, 6710bbfda8aSnia movementMask | releaseEvent, &Event)) { 6720bbfda8aSnia if(Event.type == releaseEvent) { 6730bbfda8aSnia break; 6740bbfda8aSnia } 6750bbfda8aSnia } 6760bbfda8aSnia } 6770bbfda8aSnia 6780bbfda8aSnia if(!DispatchEvent2()) { 6790bbfda8aSnia continue; 6800bbfda8aSnia } 6810bbfda8aSnia 6820bbfda8aSnia if(Event.type == releaseEvent) { 6830bbfda8aSnia break; 6840bbfda8aSnia } 6850bbfda8aSnia 6860bbfda8aSnia /* something left to do only if the pointer moved */ 6870bbfda8aSnia if(Event.type != MotionNotify) { 6880bbfda8aSnia continue; 6890bbfda8aSnia } 6900bbfda8aSnia 6910bbfda8aSnia /* get current pointer pos, useful when there is lag */ 6920bbfda8aSnia XQueryPointer(dpy, rootw, &eventp->xmotion.root, &JunkChild, 6930bbfda8aSnia &eventp->xmotion.x_root, &eventp->xmotion.y_root, 6940bbfda8aSnia &JunkX, &JunkY, &JunkMask); 6950bbfda8aSnia 6960bbfda8aSnia FixRootEvent(eventp); 697b18c2d1eSnia#ifdef WINBOX 6980bbfda8aSnia if(tmp_win->winbox) { 6990bbfda8aSnia XTranslateCoordinates(dpy, Scr->Root, tmp_win->winbox->window, 7000bbfda8aSnia eventp->xmotion.x_root, eventp->xmotion.y_root, 7010bbfda8aSnia &eventp->xmotion.x_root, &eventp->xmotion.y_root, &JunkChild); 7020bbfda8aSnia } 703b18c2d1eSnia#endif 7040bbfda8aSnia 7050bbfda8aSnia if(!Scr->NoRaiseMove && Scr->OpaqueMove && !WindowMoved) { 7060bbfda8aSnia OtpRaise(tmp_win, WinWin); 7070bbfda8aSnia } 7080bbfda8aSnia 7090bbfda8aSnia deltax = eventp->xmotion.x_root - origX; 7100bbfda8aSnia newx = origNum + deltax; 7110bbfda8aSnia 7120bbfda8aSnia /* 7130bbfda8aSnia * Clamp to left and right. 7140bbfda8aSnia * If we're in pixel size, keep within [ 0, frame_width >. 7150bbfda8aSnia * If we're proportional, don't cross the 0. 7160bbfda8aSnia * Also don't let the nominator get bigger than the denominator. 7170bbfda8aSnia * Keep within [ -denom, -1] or [ 0, denom >. 7180bbfda8aSnia */ 7190bbfda8aSnia { 7200bbfda8aSnia int wtmp = tmp_win->frame_width; /* or si->denom; if it were != 0 */ 7210bbfda8aSnia if(origNum < 0) { 7220bbfda8aSnia if(newx >= 0) { 7230bbfda8aSnia newx = -1; 7240bbfda8aSnia } 7250bbfda8aSnia else if(newx < -wtmp) { 7260bbfda8aSnia newx = -wtmp; 7270bbfda8aSnia } 7280bbfda8aSnia } 7290bbfda8aSnia else if(origNum >= 0) { 7300bbfda8aSnia if(newx < 0) { 7310bbfda8aSnia newx = 0; 7320bbfda8aSnia } 7330bbfda8aSnia else if(newx >= wtmp) { 7340bbfda8aSnia newx = wtmp - 1; 7350bbfda8aSnia } 7360bbfda8aSnia } 7370bbfda8aSnia } 7380bbfda8aSnia 7390bbfda8aSnia si->num = newx; 7400bbfda8aSnia /* This, finally, actually moves the title bar */ 7410bbfda8aSnia /* XXX pressing a second button should cancel and undo this */ 7420bbfda8aSnia SetFrameShape(tmp_win); 7430bbfda8aSnia } 7440bbfda8aSnia 7450bbfda8aSnia /* 7460bbfda8aSnia * The ButtonRelease handler will have taken care of 7470bbfda8aSnia * ungrabbing our pointer. 7480bbfda8aSnia */ 7490bbfda8aSnia return; 7500bbfda8aSnia} 751