menus.c revision c2535118
13e747e6dSmrg/*****************************************************************************/ 23e747e6dSmrg/* 33e747e6dSmrg 43e747e6dSmrgCopyright 1989, 1998 The Open Group 53e747e6dSmrg 63e747e6dSmrgPermission to use, copy, modify, distribute, and sell this software and its 73e747e6dSmrgdocumentation for any purpose is hereby granted without fee, provided that 83e747e6dSmrgthe above copyright notice appear in all copies and that both that 93e747e6dSmrgcopyright notice and this permission notice appear in supporting 103e747e6dSmrgdocumentation. 113e747e6dSmrg 123e747e6dSmrgThe above copyright notice and this permission notice shall be included in 133e747e6dSmrgall copies or substantial portions of the Software. 143e747e6dSmrg 153e747e6dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 163e747e6dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 173e747e6dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 183e747e6dSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 193e747e6dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 203e747e6dSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 213e747e6dSmrg 223e747e6dSmrgExcept as contained in this notice, the name of The Open Group shall not be 233e747e6dSmrgused in advertising or otherwise to promote the sale, use or other dealings 243e747e6dSmrgin this Software without prior written authorization from The Open Group. 253e747e6dSmrg 263e747e6dSmrg*/ 273e747e6dSmrg/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ 283e747e6dSmrg/** Salt Lake City, Utah **/ 293e747e6dSmrg/** Cambridge, Massachusetts **/ 303e747e6dSmrg/** **/ 313e747e6dSmrg/** All Rights Reserved **/ 323e747e6dSmrg/** **/ 333e747e6dSmrg/** Permission to use, copy, modify, and distribute this software and **/ 343e747e6dSmrg/** its documentation for any purpose and without fee is hereby **/ 353e747e6dSmrg/** granted, provided that the above copyright notice appear in all **/ 363e747e6dSmrg/** copies and that both that copyright notice and this permis- **/ 373e747e6dSmrg/** sion notice appear in supporting documentation, and that the **/ 383e747e6dSmrg/** name of Evans & Sutherland not be used in advertising **/ 393e747e6dSmrg/** in publicity pertaining to distribution of the software without **/ 403e747e6dSmrg/** specific, written prior permission. **/ 413e747e6dSmrg/** **/ 423e747e6dSmrg/** EVANS & SUTHERLAND DISCLAIMs ALL WARRANTIES WITH REGARD **/ 433e747e6dSmrg/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ 443e747e6dSmrg/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND **/ 453e747e6dSmrg/** BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ 463e747e6dSmrg/** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ 473e747e6dSmrg/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ 483e747e6dSmrg/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ 493e747e6dSmrg/** OR PERFORMANCE OF THIS SOFTWARE. **/ 503e747e6dSmrg/*****************************************************************************/ 513e747e6dSmrg 523e747e6dSmrg 533e747e6dSmrg/*********************************************************************** 543e747e6dSmrg * 553e747e6dSmrg * twm menu code 563e747e6dSmrg * 573e747e6dSmrg * 17-Nov-87 Thomas E. LaStrange File created 583e747e6dSmrg * 593e747e6dSmrg ***********************************************************************/ 603e747e6dSmrg 61ffd25bcaSmrg#ifdef HAVE_CONFIG_H 62ffd25bcaSmrg# include "config.h" 63ffd25bcaSmrg#endif 64ffd25bcaSmrg 653e747e6dSmrg#include <stdio.h> 663e747e6dSmrg#include <X11/Xos.h> 673e747e6dSmrg#include "twm.h" 683e747e6dSmrg#include "gc.h" 693e747e6dSmrg#include "menus.h" 703e747e6dSmrg#include "resize.h" 713e747e6dSmrg#include "events.h" 723e747e6dSmrg#include "util.h" 733e747e6dSmrg#include "parse.h" 743e747e6dSmrg#include "gram.h" 753e747e6dSmrg#include "screen.h" 763e747e6dSmrg#include "menus.h" 773e747e6dSmrg#include "iconmgr.h" 783e747e6dSmrg#include "add_window.h" 793e747e6dSmrg#include "icons.h" 803e747e6dSmrg#include "session.h" 813e747e6dSmrg#include <X11/Xmu/CharSet.h> 823e747e6dSmrg#include "version.h" 833e747e6dSmrg#include <X11/extensions/sync.h> 843e747e6dSmrg#include <X11/SM/SMlib.h> 853e747e6dSmrg 863e747e6dSmrgint RootFunction = 0; 873e747e6dSmrgMenuRoot *ActiveMenu = NULL; /**< the active menu */ 883e747e6dSmrgMenuItem *ActiveItem = NULL; /**< the active menu item */ 893e747e6dSmrgint MoveFunction; /**< either F_MOVE or F_FORCEMOVE */ 903e747e6dSmrgint WindowMoved = FALSE; 913e747e6dSmrgint menuFromFrameOrWindowOrTitlebar = FALSE; 923e747e6dSmrg 933e747e6dSmrgint ConstMove = FALSE; /**< constrained move variables */ 943e747e6dSmrgint ConstMoveDir; 953e747e6dSmrgint ConstMoveX; 963e747e6dSmrgint ConstMoveY; 973e747e6dSmrgint ConstMoveXL; 983e747e6dSmrgint ConstMoveXR; 993e747e6dSmrgint ConstMoveYT; 1003e747e6dSmrgint ConstMoveYB; 101ffd25bcaSmrg 1023e747e6dSmrg/* Globals used to keep track of whether the mouse has moved during 1033e747e6dSmrg a resize function. */ 1043e747e6dSmrgint ResizeOrigX; 1053e747e6dSmrgint ResizeOrigY; 1063e747e6dSmrg 1073e747e6dSmrgint MenuDepth = 0; /**< number of menus up */ 1083e747e6dSmrgstatic struct { 1093e747e6dSmrg int x; 1103e747e6dSmrg int y; 1113e747e6dSmrg} MenuOrigins[MAXMENUDEPTH]; 1123e747e6dSmrgstatic Cursor LastCursor; 1133e747e6dSmrg 1143e747e6dSmrgstatic Bool belongs_to_twm_window ( TwmWindow *t, Window w ); 1153e747e6dSmrgstatic void Identify ( TwmWindow *t ); 1163e747e6dSmrgstatic void send_clientmessage ( Window w, Atom a, Time timestamp ); 117c2535118Smrgstatic void BumpWindowColormap ( TwmWindow *tmp, int inc ); 118c2535118Smrgstatic int DeferExecution ( int context, int func, Cursor cursor ); 119c2535118Smrgstatic Bool NeedToDefer ( MenuRoot *root ); 120c2535118Smrgstatic void DestroyMenu ( MenuRoot *menu ); 121c2535118Smrgstatic void MakeMenu ( MenuRoot *mr ); 122c2535118Smrgstatic void Execute ( const char *s ); 123c2535118Smrgstatic void HideIconManager ( void ); 124c2535118Smrgstatic void WarpAlongRing ( XButtonEvent *ev, Bool forward ); 125c2535118Smrgstatic int WarpThere ( TwmWindow * t ); 126c2535118Smrgstatic void WarpToWindow ( TwmWindow *t ); 1273e747e6dSmrg 1283e747e6dSmrg#define SHADOWWIDTH 5 /* in pixels */ 1293e747e6dSmrg 1303e747e6dSmrg 1313e747e6dSmrg 1323e747e6dSmrg 1333e747e6dSmrg/** 1343e747e6dSmrg * initialize menu roots 1353e747e6dSmrg */ 1363e747e6dSmrgvoid 137c2535118SmrgInitMenus(void) 1383e747e6dSmrg{ 1393e747e6dSmrg int i, j, k; 1403e747e6dSmrg FuncKey *key, *tmp; 1413e747e6dSmrg 1423e747e6dSmrg for (i = 0; i < MAX_BUTTONS+1; i++) 1433e747e6dSmrg for (j = 0; j < NUM_CONTEXTS; j++) 1443e747e6dSmrg for (k = 0; k < MOD_SIZE; k++) 1453e747e6dSmrg { 1463e747e6dSmrg Scr->Mouse[i][j][k].func = 0; 1473e747e6dSmrg Scr->Mouse[i][j][k].item = NULL; 1483e747e6dSmrg } 1493e747e6dSmrg 1503e747e6dSmrg Scr->DefaultFunction.func = 0; 1513e747e6dSmrg Scr->WindowFunction.func = 0; 1523e747e6dSmrg 1533e747e6dSmrg if (FirstScreen) 1543e747e6dSmrg { 1553e747e6dSmrg for (key = Scr->FuncKeyRoot.next; key != NULL;) 1563e747e6dSmrg { 1573e747e6dSmrg free(key->name); 1583e747e6dSmrg tmp = key; 1593e747e6dSmrg key = key->next; 160c2535118Smrg free(tmp); 1613e747e6dSmrg } 1623e747e6dSmrg Scr->FuncKeyRoot.next = NULL; 1633e747e6dSmrg } 1643e747e6dSmrg 1653e747e6dSmrg} 1663e747e6dSmrg 1673e747e6dSmrg 1683e747e6dSmrg 1693e747e6dSmrg/** 1703e747e6dSmrg * add a function key to the list 1713e747e6dSmrg * 1723e747e6dSmrg * \param name the name of the key 1733e747e6dSmrg * \param cont the context to look for the key press in 1743e747e6dSmrg * \param mods modifier keys that need to be pressed 1753e747e6dSmrg * \param func the function to perform 1763e747e6dSmrg * \param win_name the window name (if any) 1773e747e6dSmrg * \param action the action string associated with the function (if any) 1783e747e6dSmrg */ 179ffd25bcaSmrgBool AddFuncKey (char *name, int cont, int mods, int func, char *win_name, 1803e747e6dSmrg char *action) 1813e747e6dSmrg{ 1823e747e6dSmrg FuncKey *tmp; 1833e747e6dSmrg KeySym keysym; 1843e747e6dSmrg KeyCode keycode; 1853e747e6dSmrg 1863e747e6dSmrg /* 1873e747e6dSmrg * Don't let a 0 keycode go through, since that means AnyKey to the 1883e747e6dSmrg * XGrabKey call in GrabKeys(). 1893e747e6dSmrg */ 1903e747e6dSmrg if ((keysym = XStringToKeysym(name)) == NoSymbol || 1913e747e6dSmrg (keycode = XKeysymToKeycode(dpy, keysym)) == 0) 1923e747e6dSmrg { 1933e747e6dSmrg return False; 1943e747e6dSmrg } 1953e747e6dSmrg 1963e747e6dSmrg /* see if there already is a key defined for this context */ 1973e747e6dSmrg for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next) 1983e747e6dSmrg { 1993e747e6dSmrg if (tmp->keysym == keysym && 2003e747e6dSmrg tmp->cont == cont && 2013e747e6dSmrg tmp->mods == mods) 2023e747e6dSmrg break; 2033e747e6dSmrg } 2043e747e6dSmrg 2053e747e6dSmrg if (tmp == NULL) 2063e747e6dSmrg { 207c2535118Smrg tmp = malloc(sizeof(FuncKey)); 2083e747e6dSmrg tmp->next = Scr->FuncKeyRoot.next; 2093e747e6dSmrg Scr->FuncKeyRoot.next = tmp; 2103e747e6dSmrg } 2113e747e6dSmrg 2123e747e6dSmrg tmp->name = name; 2133e747e6dSmrg tmp->keysym = keysym; 2143e747e6dSmrg tmp->keycode = keycode; 2153e747e6dSmrg tmp->cont = cont; 2163e747e6dSmrg tmp->mods = mods; 2173e747e6dSmrg tmp->func = func; 2183e747e6dSmrg tmp->win_name = win_name; 2193e747e6dSmrg tmp->action = action; 2203e747e6dSmrg 2213e747e6dSmrg return True; 2223e747e6dSmrg} 2233e747e6dSmrg 2243e747e6dSmrg 2253e747e6dSmrg 226c2535118Smrgint CreateTitleButton (const char *name, int func, const char *action, 227c2535118Smrg MenuRoot *menuroot, Bool rightside, Bool append) 2283e747e6dSmrg{ 229c2535118Smrg TitleButton *tb = malloc (sizeof(TitleButton)); 2303e747e6dSmrg 2313e747e6dSmrg if (!tb) { 2323e747e6dSmrg fprintf (stderr, 2333e747e6dSmrg "%s: unable to allocate %ld bytes for title button\n", 2343e747e6dSmrg ProgramName, (unsigned long)sizeof(TitleButton)); 2353e747e6dSmrg return 0; 2363e747e6dSmrg } 2373e747e6dSmrg 2383e747e6dSmrg tb->next = NULL; 2393e747e6dSmrg tb->name = name; /* note that we are not copying */ 2403e747e6dSmrg tb->bitmap = None; /* WARNING, values not set yet */ 2413e747e6dSmrg tb->width = 0; /* see InitTitlebarButtons */ 2423e747e6dSmrg tb->height = 0; /* ditto */ 2433e747e6dSmrg tb->func = func; 2443e747e6dSmrg tb->action = action; 2453e747e6dSmrg tb->menuroot = menuroot; 2463e747e6dSmrg tb->rightside = rightside; 2473e747e6dSmrg if (rightside) { 2483e747e6dSmrg Scr->TBInfo.nright++; 2493e747e6dSmrg } else { 2503e747e6dSmrg Scr->TBInfo.nleft++; 2513e747e6dSmrg } 2523e747e6dSmrg 2533e747e6dSmrg /* 2543e747e6dSmrg * Cases for list: 255ffd25bcaSmrg * 2563e747e6dSmrg * 1. empty list, prepend left put at head of list 2573e747e6dSmrg * 2. append left, prepend right put in between left and right 2583e747e6dSmrg * 3. append right put at tail of list 2593e747e6dSmrg * 2603e747e6dSmrg * Do not refer to widths and heights yet since buttons not created 2613e747e6dSmrg * (since fonts not loaded and heights not known). 2623e747e6dSmrg */ 2633e747e6dSmrg if ((!Scr->TBInfo.head) || ((!append) && (!rightside))) { /* 1 */ 2643e747e6dSmrg tb->next = Scr->TBInfo.head; 2653e747e6dSmrg Scr->TBInfo.head = tb; 2663e747e6dSmrg } else if (append && rightside) { /* 3 */ 2673e747e6dSmrg register TitleButton *t; 2683e747e6dSmrg for /* SUPPRESS 530 */ 2693e747e6dSmrg (t = Scr->TBInfo.head; t->next; t = t->next); 2703e747e6dSmrg t->next = tb; 2713e747e6dSmrg tb->next = NULL; 2723e747e6dSmrg } else { /* 2 */ 2733e747e6dSmrg register TitleButton *t, *prev = NULL; 2743e747e6dSmrg for (t = Scr->TBInfo.head; t && !t->rightside; t = t->next) { 2753e747e6dSmrg prev = t; 2763e747e6dSmrg } 2773e747e6dSmrg if (prev) { 2783e747e6dSmrg tb->next = prev->next; 2793e747e6dSmrg prev->next = tb; 2803e747e6dSmrg } else { 2813e747e6dSmrg tb->next = Scr->TBInfo.head; 2823e747e6dSmrg Scr->TBInfo.head = tb; 2833e747e6dSmrg } 2843e747e6dSmrg } 2853e747e6dSmrg 2863e747e6dSmrg return 1; 2873e747e6dSmrg} 2883e747e6dSmrg 2893e747e6dSmrg 2903e747e6dSmrg 2913e747e6dSmrg/** 292ffd25bcaSmrg * Do all the necessary stuff to load in a titlebar button. If we can't find 293ffd25bcaSmrg * the button, then put in a question; if we can't find the question mark, 2943e747e6dSmrg * something is wrong and we are probably going to be in trouble later on. 2953e747e6dSmrg */ 296c2535118Smrgvoid InitTitlebarButtons (void) 2973e747e6dSmrg{ 2983e747e6dSmrg TitleButton *tb; 2993e747e6dSmrg int h; 3003e747e6dSmrg 3013e747e6dSmrg /* 3023e747e6dSmrg * initialize dimensions 3033e747e6dSmrg */ 3043e747e6dSmrg Scr->TBInfo.width = (Scr->TitleHeight - 3053e747e6dSmrg 2 * (Scr->FramePadding + Scr->ButtonIndent)); 3063e747e6dSmrg Scr->TBInfo.pad = ((Scr->TitlePadding > 1) 3073e747e6dSmrg ? ((Scr->TitlePadding + 1) / 2) : 1); 3083e747e6dSmrg h = Scr->TBInfo.width - 2 * Scr->TBInfo.border; 3093e747e6dSmrg 3103e747e6dSmrg /* 3113e747e6dSmrg * add in some useful buttons and bindings so that novices can still 3123e747e6dSmrg * use the system. 3133e747e6dSmrg */ 3143e747e6dSmrg if (!Scr->NoDefaults) { 3153e747e6dSmrg /* insert extra buttons */ 3163e747e6dSmrg if (!CreateTitleButton (TBPM_ICONIFY, F_ICONIFY, "", (MenuRoot *) NULL, 3173e747e6dSmrg False, False)) { 3183e747e6dSmrg fprintf (stderr, "%s: unable to add iconify button\n", 3193e747e6dSmrg ProgramName); 3203e747e6dSmrg } 3213e747e6dSmrg if (!CreateTitleButton (TBPM_RESIZE, F_RESIZE, "", (MenuRoot *) NULL, 3223e747e6dSmrg True, True)) { 3233e747e6dSmrg fprintf (stderr, "%s: unable to add resize button\n", 3243e747e6dSmrg ProgramName); 3253e747e6dSmrg } 3263e747e6dSmrg AddDefaultBindings (); 3273e747e6dSmrg } 3283e747e6dSmrg ComputeCommonTitleOffsets (); 3293e747e6dSmrg 3303e747e6dSmrg /* 3313e747e6dSmrg * load in images and do appropriate centering 3323e747e6dSmrg */ 3333e747e6dSmrg 3343e747e6dSmrg for (tb = Scr->TBInfo.head; tb; tb = tb->next) { 3353e747e6dSmrg tb->bitmap = FindBitmap (tb->name, &tb->width, &tb->height); 3363e747e6dSmrg if (!tb->bitmap) { 3373e747e6dSmrg tb->bitmap = FindBitmap (TBPM_QUESTION, &tb->width, &tb->height); 3383e747e6dSmrg if (!tb->bitmap) { /* cannot happen (see util.c) */ 3393e747e6dSmrg fprintf (stderr, 3403e747e6dSmrg "%s: unable to add titlebar button \"%s\"\n", 3413e747e6dSmrg ProgramName, tb->name); 3423e747e6dSmrg } 3433e747e6dSmrg } 3443e747e6dSmrg 3453e747e6dSmrg tb->dstx = (h - tb->width + 1) / 2; 3463e747e6dSmrg if (tb->dstx < 0) { /* clip to minimize copying */ 3473e747e6dSmrg tb->srcx = -(tb->dstx); 3483e747e6dSmrg tb->width = h; 3493e747e6dSmrg tb->dstx = 0; 3503e747e6dSmrg } else { 3513e747e6dSmrg tb->srcx = 0; 3523e747e6dSmrg } 3533e747e6dSmrg tb->dsty = (h - tb->height + 1) / 2; 3543e747e6dSmrg if (tb->dsty < 0) { 3553e747e6dSmrg tb->srcy = -(tb->dsty); 3563e747e6dSmrg tb->height = h; 3573e747e6dSmrg tb->dsty = 0; 3583e747e6dSmrg } else { 3593e747e6dSmrg tb->srcy = 0; 3603e747e6dSmrg } 3613e747e6dSmrg } 3623e747e6dSmrg} 3633e747e6dSmrg 3643e747e6dSmrg 3653e747e6dSmrg 3663e747e6dSmrgvoid 3673e747e6dSmrgPaintEntry(MenuRoot *mr, MenuItem *mi, int exposure) 3683e747e6dSmrg{ 3693e747e6dSmrg int y_offset; 3703e747e6dSmrg int text_y; 3713e747e6dSmrg GC gc; 3723e747e6dSmrg 3733e747e6dSmrg#ifdef DEBUG_MENUS 3743e747e6dSmrg fprintf(stderr, "Paint entry\n"); 3753e747e6dSmrg#endif 3763e747e6dSmrg y_offset = mi->item_num * Scr->EntryHeight; 3773e747e6dSmrg text_y = y_offset + Scr->MenuFont.y; 3783e747e6dSmrg 3793e747e6dSmrg if (mi->func != F_TITLE) 3803e747e6dSmrg { 3813e747e6dSmrg int x, y; 3823e747e6dSmrg 3833e747e6dSmrg if (mi->state) 3843e747e6dSmrg { 3853e747e6dSmrg XSetForeground(dpy, Scr->NormalGC, mi->hi_back); 3863e747e6dSmrg 3873e747e6dSmrg XFillRectangle(dpy, mr->w, Scr->NormalGC, 0, y_offset, 3883e747e6dSmrg mr->width, Scr->EntryHeight); 3893e747e6dSmrg 3903e747e6dSmrg MyFont_ChangeGC(mi->hi_fore, mi->hi_back, &Scr->MenuFont); 3913e747e6dSmrg 3923e747e6dSmrg MyFont_DrawString(dpy, mr->w, &Scr->MenuFont, Scr->NormalGC, mi->x, 3933e747e6dSmrg text_y, mi->item, mi->strlen); 3943e747e6dSmrg 3953e747e6dSmrg gc = Scr->NormalGC; 3963e747e6dSmrg } 3973e747e6dSmrg else 3983e747e6dSmrg { 3993e747e6dSmrg if (mi->user_colors || !exposure) 4003e747e6dSmrg { 4013e747e6dSmrg XSetForeground(dpy, Scr->NormalGC, mi->back); 4023e747e6dSmrg 4033e747e6dSmrg XFillRectangle(dpy, mr->w, Scr->NormalGC, 0, y_offset, 4043e747e6dSmrg mr->width, Scr->EntryHeight); 4053e747e6dSmrg 4063e747e6dSmrg MyFont_ChangeGC(mi->fore, mi->back, &Scr->MenuFont); 4073e747e6dSmrg gc = Scr->NormalGC; 4083e747e6dSmrg } 4093e747e6dSmrg else 4103e747e6dSmrg gc = Scr->MenuGC; 4113e747e6dSmrg 412ffd25bcaSmrg MyFont_DrawString(dpy, mr->w, &Scr->MenuFont, gc, 4133e747e6dSmrg mi->x, text_y, mi->item, mi->strlen); 4143e747e6dSmrg 4153e747e6dSmrg } 4163e747e6dSmrg 4173e747e6dSmrg if (mi->func == F_MENU) 4183e747e6dSmrg { 4193e747e6dSmrg /* create the pull right pixmap if needed */ 4203e747e6dSmrg if (Scr->pullPm == None) 4213e747e6dSmrg { 4223e747e6dSmrg Scr->pullPm = CreateMenuIcon (Scr->MenuFont.height, 4233e747e6dSmrg &Scr->pullW, &Scr->pullH); 4243e747e6dSmrg } 4253e747e6dSmrg x = mr->width - Scr->pullW - 5; 4263e747e6dSmrg y = y_offset + ((Scr->MenuFont.height - Scr->pullH) / 2); 4273e747e6dSmrg XCopyPlane(dpy, Scr->pullPm, mr->w, gc, 0, 0, 4283e747e6dSmrg Scr->pullW, Scr->pullH, x, y, 1); 4293e747e6dSmrg } 4303e747e6dSmrg } 4313e747e6dSmrg else 4323e747e6dSmrg { 4333e747e6dSmrg int y; 4343e747e6dSmrg 4353e747e6dSmrg XSetForeground(dpy, Scr->NormalGC, mi->back); 4363e747e6dSmrg 4373e747e6dSmrg /* fill the rectangle with the title background color */ 4383e747e6dSmrg XFillRectangle(dpy, mr->w, Scr->NormalGC, 0, y_offset, 4393e747e6dSmrg mr->width, Scr->EntryHeight); 4403e747e6dSmrg 4413e747e6dSmrg { 4423e747e6dSmrg XSetForeground(dpy, Scr->NormalGC, mi->fore); 4433e747e6dSmrg /* now draw the dividing lines */ 4443e747e6dSmrg if (y_offset) 4453e747e6dSmrg XDrawLine (dpy, mr->w, Scr->NormalGC, 0, y_offset, 4463e747e6dSmrg mr->width, y_offset); 4473e747e6dSmrg y = ((mi->item_num+1) * Scr->EntryHeight)-1; 4483e747e6dSmrg XDrawLine(dpy, mr->w, Scr->NormalGC, 0, y, mr->width, y); 4493e747e6dSmrg } 4503e747e6dSmrg 4513e747e6dSmrg MyFont_ChangeGC(mi->fore, mi->back, &Scr->MenuFont); 4523e747e6dSmrg /* finally render the title */ 4533e747e6dSmrg MyFont_DrawString(dpy, mr->w, &Scr->MenuFont, Scr->NormalGC, mi->x, 4543e747e6dSmrg text_y, mi->item, mi->strlen); 4553e747e6dSmrg } 4563e747e6dSmrg} 457ffd25bcaSmrg 4583e747e6dSmrg 4593e747e6dSmrgvoid 4603e747e6dSmrgPaintMenu(MenuRoot *mr, XEvent *e) 4613e747e6dSmrg{ 4623e747e6dSmrg MenuItem *mi; 4633e747e6dSmrg 4643e747e6dSmrg for (mi = mr->first; mi != NULL; mi = mi->next) 4653e747e6dSmrg { 4663e747e6dSmrg int y_offset = mi->item_num * Scr->EntryHeight; 4673e747e6dSmrg 4683e747e6dSmrg /* be smart about handling the expose, redraw only the entries 4693e747e6dSmrg * that we need to 4703e747e6dSmrg */ 4713e747e6dSmrg if (e->xexpose.y < (y_offset + Scr->EntryHeight) && 4723e747e6dSmrg (e->xexpose.y + e->xexpose.height) > y_offset) 4733e747e6dSmrg { 4743e747e6dSmrg PaintEntry(mr, mi, True); 4753e747e6dSmrg } 4763e747e6dSmrg } 4773e747e6dSmrg XSync(dpy, 0); 4783e747e6dSmrg} 4793e747e6dSmrg 4803e747e6dSmrg 4813e747e6dSmrg 4823e747e6dSmrgstatic Bool fromMenu; 4833e747e6dSmrg 4843e747e6dSmrgvoid 485c2535118SmrgUpdateMenu(void) 4863e747e6dSmrg{ 4873e747e6dSmrg MenuItem *mi; 4883e747e6dSmrg int i, x, y, x_root, y_root, entry; 4893e747e6dSmrg int done; 4903e747e6dSmrg MenuItem *badItem = NULL; 491ffd25bcaSmrg XPointer context_data; 4923e747e6dSmrg 4933e747e6dSmrg fromMenu = TRUE; 4943e747e6dSmrg 4953e747e6dSmrg while (TRUE) 4963e747e6dSmrg { 4973e747e6dSmrg /* block until there is an event */ 4983e747e6dSmrg if (!menuFromFrameOrWindowOrTitlebar) { 4993e747e6dSmrg XMaskEvent(dpy, 5003e747e6dSmrg ButtonPressMask | ButtonReleaseMask | 5013e747e6dSmrg EnterWindowMask | ExposureMask | 5023e747e6dSmrg VisibilityChangeMask | LeaveWindowMask | 5033e747e6dSmrg ButtonMotionMask, &Event); 5043e747e6dSmrg } 5053e747e6dSmrg if (Event.type == MotionNotify) { 5063e747e6dSmrg /* discard any extra motion events before a release */ 5073e747e6dSmrg while(XCheckMaskEvent(dpy, 5083e747e6dSmrg ButtonMotionMask | ButtonReleaseMask, &Event)) 5093e747e6dSmrg if (Event.type == ButtonRelease) 5103e747e6dSmrg break; 5113e747e6dSmrg } 5123e747e6dSmrg 5133e747e6dSmrg if (!DispatchEvent ()) 5143e747e6dSmrg continue; 5153e747e6dSmrg 5163e747e6dSmrg if (Event.type == ButtonRelease || Cancel) { 5173e747e6dSmrg menuFromFrameOrWindowOrTitlebar = FALSE; 5183e747e6dSmrg fromMenu = FALSE; 5193e747e6dSmrg return; 5203e747e6dSmrg } 5213e747e6dSmrg 5223e747e6dSmrg if (Event.type != MotionNotify) 5233e747e6dSmrg continue; 5243e747e6dSmrg 525ffd25bcaSmrg if (!ActiveMenu) 526ffd25bcaSmrg continue; 527ffd25bcaSmrg 5283e747e6dSmrg done = FALSE; 5293e747e6dSmrg XQueryPointer( dpy, ActiveMenu->w, &JunkRoot, &JunkChild, 5303e747e6dSmrg &x_root, &y_root, &x, &y, &JunkMask); 5313e747e6dSmrg 5323e747e6dSmrg /* if we haven't recieved the enter notify yet, wait */ 533ffd25bcaSmrg if (!ActiveMenu->entered) 5343e747e6dSmrg continue; 5353e747e6dSmrg 536ffd25bcaSmrg if (XFindContext(dpy, ActiveMenu->w, ScreenContext, &context_data) == 0) 537ffd25bcaSmrg Scr = (struct ScreenInfo *) context_data; 5383e747e6dSmrg 5393e747e6dSmrg if (x < 0 || y < 0 || 5403e747e6dSmrg x >= ActiveMenu->width || y >= ActiveMenu->height) 5413e747e6dSmrg { 5423e747e6dSmrg if (ActiveItem && ActiveItem->func != F_TITLE) 5433e747e6dSmrg { 5443e747e6dSmrg ActiveItem->state = 0; 5453e747e6dSmrg PaintEntry(ActiveMenu, ActiveItem, False); 5463e747e6dSmrg } 5473e747e6dSmrg ActiveItem = NULL; 5483e747e6dSmrg continue; 5493e747e6dSmrg } 5503e747e6dSmrg 5513e747e6dSmrg /* look for the entry that the mouse is in */ 5523e747e6dSmrg entry = y / Scr->EntryHeight; 5533e747e6dSmrg for (i = 0, mi = ActiveMenu->first; mi != NULL; i++, mi=mi->next) 5543e747e6dSmrg { 5553e747e6dSmrg if (i == entry) 5563e747e6dSmrg break; 5573e747e6dSmrg } 5583e747e6dSmrg 5593e747e6dSmrg /* if there is an active item, we might have to turn it off */ 5603e747e6dSmrg if (ActiveItem) 5613e747e6dSmrg { 5623e747e6dSmrg /* is the active item the one we are on ? */ 5633e747e6dSmrg if (ActiveItem->item_num == entry && ActiveItem->state) 5643e747e6dSmrg done = TRUE; 5653e747e6dSmrg 5663e747e6dSmrg /* if we weren't on the active entry, let's turn the old 567ffd25bcaSmrg * active one off 5683e747e6dSmrg */ 5693e747e6dSmrg if (!done && ActiveItem->func != F_TITLE) 5703e747e6dSmrg { 5713e747e6dSmrg ActiveItem->state = 0; 5723e747e6dSmrg PaintEntry(ActiveMenu, ActiveItem, False); 5733e747e6dSmrg } 5743e747e6dSmrg } 5753e747e6dSmrg 5763e747e6dSmrg /* if we weren't on the active item, change the active item and turn 577ffd25bcaSmrg * it on 5783e747e6dSmrg */ 5793e747e6dSmrg if (!done) 5803e747e6dSmrg { 5813e747e6dSmrg ActiveItem = mi; 582ffd25bcaSmrg if (ActiveItem && ActiveItem->func != F_TITLE && !ActiveItem->state) 5833e747e6dSmrg { 5843e747e6dSmrg ActiveItem->state = 1; 5853e747e6dSmrg PaintEntry(ActiveMenu, ActiveItem, False); 5863e747e6dSmrg } 5873e747e6dSmrg } 5883e747e6dSmrg 5893e747e6dSmrg /* now check to see if we were over the arrow of a pull right entry */ 590ffd25bcaSmrg if (ActiveItem && ActiveItem->func == F_MENU && 5913e747e6dSmrg ((ActiveMenu->width - x) < (ActiveMenu->width >> 1))) 5923e747e6dSmrg { 5933e747e6dSmrg MenuRoot *save = ActiveMenu; 594ffd25bcaSmrg int savex = MenuOrigins[MenuDepth - 1].x; 5953e747e6dSmrg int savey = MenuOrigins[MenuDepth - 1].y; 5963e747e6dSmrg 5973e747e6dSmrg if (MenuDepth < MAXMENUDEPTH) { 598ffd25bcaSmrg PopUpMenu (ActiveItem->sub, 599ffd25bcaSmrg (savex + (ActiveMenu->width >> 1)), 6003e747e6dSmrg (savey + ActiveItem->item_num * Scr->EntryHeight) 6013e747e6dSmrg /*(savey + ActiveItem->item_num * Scr->EntryHeight + 6023e747e6dSmrg (Scr->EntryHeight >> 1))*/, False); 6033e747e6dSmrg } else if (!badItem) { 6043e747e6dSmrg Bell(XkbBI_MinorError,0,None); 6053e747e6dSmrg badItem = ActiveItem; 6063e747e6dSmrg } 6073e747e6dSmrg 6083e747e6dSmrg /* if the menu did get popped up, unhighlight the active item */ 6093e747e6dSmrg if (save != ActiveMenu && ActiveItem->state) 6103e747e6dSmrg { 6113e747e6dSmrg ActiveItem->state = 0; 6123e747e6dSmrg PaintEntry(save, ActiveItem, False); 6133e747e6dSmrg ActiveItem = NULL; 6143e747e6dSmrg } 6153e747e6dSmrg } 6163e747e6dSmrg if (badItem != ActiveItem) badItem = NULL; 6173e747e6dSmrg XFlush(dpy); 6183e747e6dSmrg } 6193e747e6dSmrg 6203e747e6dSmrg} 6213e747e6dSmrg 6223e747e6dSmrg 6233e747e6dSmrg 6243e747e6dSmrg/** 6253e747e6dSmrg * create a new menu root 6263e747e6dSmrg * 6273e747e6dSmrg * \param name the name of the menu root 6283e747e6dSmrg */ 6293e747e6dSmrgMenuRoot * 630c2535118SmrgNewMenuRoot(const char *name) 6313e747e6dSmrg{ 6323e747e6dSmrg MenuRoot *tmp; 6333e747e6dSmrg 6343e747e6dSmrg#define UNUSED_PIXEL ((unsigned long) (~0)) /* more than 24 bits */ 6353e747e6dSmrg 636c2535118Smrg tmp = malloc(sizeof(MenuRoot)); 6373e747e6dSmrg tmp->hi_fore = UNUSED_PIXEL; 6383e747e6dSmrg tmp->hi_back = UNUSED_PIXEL; 6393e747e6dSmrg tmp->name = name; 6403e747e6dSmrg tmp->prev = NULL; 6413e747e6dSmrg tmp->first = NULL; 6423e747e6dSmrg tmp->last = NULL; 6433e747e6dSmrg tmp->items = 0; 6443e747e6dSmrg tmp->width = 0; 6453e747e6dSmrg tmp->mapped = NEVER_MAPPED; 6463e747e6dSmrg tmp->pull = FALSE; 6473e747e6dSmrg tmp->w = None; 6483e747e6dSmrg tmp->shadow = None; 6493e747e6dSmrg tmp->real_menu = FALSE; 6503e747e6dSmrg 6513e747e6dSmrg if (Scr->MenuList == NULL) 6523e747e6dSmrg { 6533e747e6dSmrg Scr->MenuList = tmp; 6543e747e6dSmrg Scr->MenuList->next = NULL; 6553e747e6dSmrg } 6563e747e6dSmrg 6573e747e6dSmrg if (Scr->LastMenu == NULL) 6583e747e6dSmrg { 6593e747e6dSmrg Scr->LastMenu = tmp; 6603e747e6dSmrg Scr->LastMenu->next = NULL; 6613e747e6dSmrg } 6623e747e6dSmrg else 6633e747e6dSmrg { 6643e747e6dSmrg Scr->LastMenu->next = tmp; 6653e747e6dSmrg Scr->LastMenu = tmp; 6663e747e6dSmrg Scr->LastMenu->next = NULL; 6673e747e6dSmrg } 6683e747e6dSmrg 6693e747e6dSmrg if (strcmp(name, TWM_WINDOWS) == 0) 6703e747e6dSmrg Scr->Windows = tmp; 6713e747e6dSmrg 6723e747e6dSmrg return (tmp); 6733e747e6dSmrg} 6743e747e6dSmrg 6753e747e6dSmrg 6763e747e6dSmrg 6773e747e6dSmrg/** 6783e747e6dSmrg * add an item to a root menu 6793e747e6dSmrg * 6803e747e6dSmrg * \param menu pointer to the root menu to add the item 6813e747e6dSmrg * \param item the text to appear in the menu 6823e747e6dSmrg * \param action the string to possibly execute 6833e747e6dSmrg * \param sub the menu root if it is a pull-right entry 6843e747e6dSmrg * \param func the numeric function 6853e747e6dSmrg * \param fore foreground color string 6863e747e6dSmrg * \param back background color string 6873e747e6dSmrg */ 6883e747e6dSmrgMenuItem * 689c2535118SmrgAddToMenu(MenuRoot *menu, const char *item, const char *action, 690c2535118Smrg MenuRoot *sub, int func, const char *fore, const char *back) 6913e747e6dSmrg{ 6923e747e6dSmrg MenuItem *tmp; 6933e747e6dSmrg int width; 6943e747e6dSmrg 6953e747e6dSmrg#ifdef DEBUG_MENUS 6963e747e6dSmrg fprintf(stderr, "adding menu item=\"%s\", action=%s, sub=%d, f=%d\n", 6973e747e6dSmrg item, action, sub, func); 6983e747e6dSmrg#endif 6993e747e6dSmrg 700c2535118Smrg tmp = malloc(sizeof(MenuItem)); 7013e747e6dSmrg tmp->root = menu; 7023e747e6dSmrg 7033e747e6dSmrg if (menu->first == NULL) 7043e747e6dSmrg { 7053e747e6dSmrg menu->first = tmp; 7063e747e6dSmrg tmp->prev = NULL; 7073e747e6dSmrg } 7083e747e6dSmrg else 7093e747e6dSmrg { 7103e747e6dSmrg menu->last->next = tmp; 7113e747e6dSmrg tmp->prev = menu->last; 7123e747e6dSmrg } 7133e747e6dSmrg menu->last = tmp; 7143e747e6dSmrg 7153e747e6dSmrg tmp->item = item; 7163e747e6dSmrg tmp->strlen = strlen(item); 7173e747e6dSmrg tmp->action = action; 7183e747e6dSmrg tmp->next = NULL; 7193e747e6dSmrg tmp->sub = NULL; 7203e747e6dSmrg tmp->state = 0; 7213e747e6dSmrg tmp->func = func; 7223e747e6dSmrg 7233e747e6dSmrg if (!Scr->HaveFonts) CreateFonts(); 7243e747e6dSmrg width = MyFont_TextWidth(&Scr->MenuFont, item, tmp->strlen); 7253e747e6dSmrg if (width <= 0) 7263e747e6dSmrg width = 1; 7273e747e6dSmrg if (width > menu->width) 7283e747e6dSmrg menu->width = width; 7293e747e6dSmrg 7303e747e6dSmrg tmp->user_colors = FALSE; 7313e747e6dSmrg if (Scr->Monochrome == COLOR && fore != NULL) 7323e747e6dSmrg { 7333e747e6dSmrg int save; 7343e747e6dSmrg 7353e747e6dSmrg save = Scr->FirstTime; 7363e747e6dSmrg Scr->FirstTime = TRUE; 7373e747e6dSmrg GetColor(COLOR, &tmp->fore, fore); 7383e747e6dSmrg GetColor(COLOR, &tmp->back, back); 7393e747e6dSmrg Scr->FirstTime = save; 7403e747e6dSmrg tmp->user_colors = TRUE; 7413e747e6dSmrg } 7423e747e6dSmrg if (sub != NULL) 7433e747e6dSmrg { 7443e747e6dSmrg tmp->sub = sub; 7453e747e6dSmrg menu->pull = TRUE; 7463e747e6dSmrg } 7473e747e6dSmrg tmp->item_num = menu->items++; 7483e747e6dSmrg 7493e747e6dSmrg return (tmp); 7503e747e6dSmrg} 7513e747e6dSmrg 7523e747e6dSmrg 7533e747e6dSmrgvoid 754c2535118SmrgMakeMenus(void) 7553e747e6dSmrg{ 7563e747e6dSmrg MenuRoot *mr; 7573e747e6dSmrg 7583e747e6dSmrg for (mr = Scr->MenuList; mr != NULL; mr = mr->next) 7593e747e6dSmrg { 7603e747e6dSmrg if (mr->real_menu == FALSE) 7613e747e6dSmrg continue; 7623e747e6dSmrg 7633e747e6dSmrg MakeMenu(mr); 7643e747e6dSmrg } 7653e747e6dSmrg} 7663e747e6dSmrg 7673e747e6dSmrg 768c2535118Smrgstatic void 7693e747e6dSmrgMakeMenu(MenuRoot *mr) 7703e747e6dSmrg{ 7713e747e6dSmrg MenuItem *start, *end, *cur, *tmp; 7723e747e6dSmrg XColor f1, f2, f3; 7733e747e6dSmrg XColor b1, b2, b3; 7743e747e6dSmrg XColor save_fore, save_back; 7753e747e6dSmrg int num, i; 7763e747e6dSmrg int fred, fgreen, fblue; 7773e747e6dSmrg int bred, bgreen, bblue; 7783e747e6dSmrg int width; 7793e747e6dSmrg unsigned long valuemask; 7803e747e6dSmrg XSetWindowAttributes attributes; 7813e747e6dSmrg Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c; 7823e747e6dSmrg 7833e747e6dSmrg Scr->EntryHeight = Scr->MenuFont.height + 4; 7843e747e6dSmrg 7853e747e6dSmrg /* lets first size the window accordingly */ 7863e747e6dSmrg if (mr->mapped == NEVER_MAPPED) 7873e747e6dSmrg { 7883e747e6dSmrg if (mr->pull == TRUE) 7893e747e6dSmrg { 7903e747e6dSmrg mr->width += 16 + 10; 7913e747e6dSmrg } 7923e747e6dSmrg 7933e747e6dSmrg width = mr->width + 10; 7943e747e6dSmrg 7953e747e6dSmrg for (cur = mr->first; cur != NULL; cur = cur->next) 7963e747e6dSmrg { 7973e747e6dSmrg if (cur->func != F_TITLE) 7983e747e6dSmrg cur->x = 5; 7993e747e6dSmrg else 8003e747e6dSmrg { 8013e747e6dSmrg cur->x = width - MyFont_TextWidth(&Scr->MenuFont, cur->item, 8023e747e6dSmrg cur->strlen); 8033e747e6dSmrg cur->x /= 2; 8043e747e6dSmrg } 8053e747e6dSmrg } 8063e747e6dSmrg mr->height = mr->items * Scr->EntryHeight; 8073e747e6dSmrg mr->width += 10; 8083e747e6dSmrg 8093e747e6dSmrg if (Scr->Shadow) 8103e747e6dSmrg { 8113e747e6dSmrg /* 8123e747e6dSmrg * Make sure that you don't draw into the shadow window or else 8133e747e6dSmrg * the background bits there will get saved 8143e747e6dSmrg */ 8153e747e6dSmrg valuemask = (CWBackPixel | CWBorderPixel); 8163e747e6dSmrg attributes.background_pixel = Scr->MenuShadowColor; 8173e747e6dSmrg attributes.border_pixel = Scr->MenuShadowColor; 8183e747e6dSmrg if (Scr->SaveUnder) { 8193e747e6dSmrg valuemask |= CWSaveUnder; 8203e747e6dSmrg attributes.save_under = True; 8213e747e6dSmrg } 8223e747e6dSmrg mr->shadow = XCreateWindow (dpy, Scr->Root, 0, 0, 823ffd25bcaSmrg (unsigned int) mr->width, 8243e747e6dSmrg (unsigned int) mr->height, 8253e747e6dSmrg (unsigned int)0, 826ffd25bcaSmrg CopyFromParent, 8273e747e6dSmrg (unsigned int) CopyFromParent, 8283e747e6dSmrg (Visual *) CopyFromParent, 8293e747e6dSmrg valuemask, &attributes); 8303e747e6dSmrg } 8313e747e6dSmrg 8323e747e6dSmrg valuemask = (CWBackPixel | CWBorderPixel | CWEventMask); 8333e747e6dSmrg attributes.background_pixel = Scr->MenuC.back; 8343e747e6dSmrg attributes.border_pixel = Scr->MenuBorderColor; 8353e747e6dSmrg attributes.event_mask = (ExposureMask | EnterWindowMask); 8363e747e6dSmrg if (Scr->SaveUnder) { 8373e747e6dSmrg valuemask |= CWSaveUnder; 8383e747e6dSmrg attributes.save_under = True; 8393e747e6dSmrg } 8403e747e6dSmrg if (Scr->BackingStore) { 8413e747e6dSmrg valuemask |= CWBackingStore; 8423e747e6dSmrg attributes.backing_store = Always; 8433e747e6dSmrg } 8443e747e6dSmrg mr->w = XCreateWindow (dpy, Scr->Root, 0, 0, (unsigned int) mr->width, 8453e747e6dSmrg (unsigned int) mr->height, 8463e747e6dSmrg (unsigned int) Scr->MenuBorderWidth, 8473e747e6dSmrg CopyFromParent, (unsigned int) CopyFromParent, 8483e747e6dSmrg (Visual *) CopyFromParent, 8493e747e6dSmrg valuemask, &attributes); 8503e747e6dSmrg 8513e747e6dSmrg 8523e747e6dSmrg XSaveContext(dpy, mr->w, MenuContext, (caddr_t)mr); 8533e747e6dSmrg XSaveContext(dpy, mr->w, ScreenContext, (caddr_t)Scr); 8543e747e6dSmrg 8553e747e6dSmrg mr->mapped = UNMAPPED; 8563e747e6dSmrg } 8573e747e6dSmrg 8583e747e6dSmrg /* get the default colors into the menus */ 8593e747e6dSmrg for (tmp = mr->first; tmp != NULL; tmp = tmp->next) 8603e747e6dSmrg { 8613e747e6dSmrg if (!tmp->user_colors) { 8623e747e6dSmrg if (tmp->func != F_TITLE) { 8633e747e6dSmrg tmp->fore = Scr->MenuC.fore; 8643e747e6dSmrg tmp->back = Scr->MenuC.back; 8653e747e6dSmrg } else { 8663e747e6dSmrg tmp->fore = Scr->MenuTitleC.fore; 8673e747e6dSmrg tmp->back = Scr->MenuTitleC.back; 8683e747e6dSmrg } 8693e747e6dSmrg } 8703e747e6dSmrg 8713e747e6dSmrg if (mr->hi_fore != UNUSED_PIXEL) 8723e747e6dSmrg { 8733e747e6dSmrg tmp->hi_fore = mr->hi_fore; 8743e747e6dSmrg tmp->hi_back = mr->hi_back; 8753e747e6dSmrg } 8763e747e6dSmrg else 8773e747e6dSmrg { 8783e747e6dSmrg tmp->hi_fore = tmp->back; 8793e747e6dSmrg tmp->hi_back = tmp->fore; 8803e747e6dSmrg } 8813e747e6dSmrg } 8823e747e6dSmrg 8833e747e6dSmrg if (Scr->Monochrome == MONOCHROME || !Scr->InterpolateMenuColors) 8843e747e6dSmrg return; 8853e747e6dSmrg 8863e747e6dSmrg start = mr->first; 8873e747e6dSmrg while (TRUE) 8883e747e6dSmrg { 8893e747e6dSmrg for (; start != NULL; start = start->next) 8903e747e6dSmrg { 8913e747e6dSmrg if (start->user_colors) 8923e747e6dSmrg break; 8933e747e6dSmrg } 8943e747e6dSmrg if (start == NULL) 8953e747e6dSmrg break; 8963e747e6dSmrg 8973e747e6dSmrg for (end = start->next; end != NULL; end = end->next) 8983e747e6dSmrg { 8993e747e6dSmrg if (end->user_colors) 9003e747e6dSmrg break; 9013e747e6dSmrg } 9023e747e6dSmrg if (end == NULL) 9033e747e6dSmrg break; 9043e747e6dSmrg 9053e747e6dSmrg /* we have a start and end to interpolate between */ 9063e747e6dSmrg num = end->item_num - start->item_num; 9073e747e6dSmrg 9083e747e6dSmrg f1.pixel = start->fore; 9093e747e6dSmrg XQueryColor(dpy, cmap, &f1); 9103e747e6dSmrg f2.pixel = end->fore; 9113e747e6dSmrg XQueryColor(dpy, cmap, &f2); 9123e747e6dSmrg 9133e747e6dSmrg b1.pixel = start->back; 9143e747e6dSmrg XQueryColor(dpy, cmap, &b1); 9153e747e6dSmrg b2.pixel = end->back; 9163e747e6dSmrg XQueryColor(dpy, cmap, &b2); 9173e747e6dSmrg 9183e747e6dSmrg fred = ((int)f2.red - (int)f1.red) / num; 9193e747e6dSmrg fgreen = ((int)f2.green - (int)f1.green) / num; 9203e747e6dSmrg fblue = ((int)f2.blue - (int)f1.blue) / num; 9213e747e6dSmrg 9223e747e6dSmrg bred = ((int)b2.red - (int)b1.red) / num; 9233e747e6dSmrg bgreen = ((int)b2.green - (int)b1.green) / num; 9243e747e6dSmrg bblue = ((int)b2.blue - (int)b1.blue) / num; 9253e747e6dSmrg 9263e747e6dSmrg f3 = f1; 9273e747e6dSmrg f3.flags = DoRed | DoGreen | DoBlue; 9283e747e6dSmrg 9293e747e6dSmrg b3 = b1; 9303e747e6dSmrg b3.flags = DoRed | DoGreen | DoBlue; 9313e747e6dSmrg 9323e747e6dSmrg num -= 1; 933ffd25bcaSmrg for (i = 0, cur = start->next; i < num && cur; i++, cur = cur->next) 9343e747e6dSmrg { 9353e747e6dSmrg f3.red += fred; 9363e747e6dSmrg f3.green += fgreen; 9373e747e6dSmrg f3.blue += fblue; 9383e747e6dSmrg save_fore = f3; 9393e747e6dSmrg 9403e747e6dSmrg b3.red += bred; 9413e747e6dSmrg b3.green += bgreen; 9423e747e6dSmrg b3.blue += bblue; 9433e747e6dSmrg save_back = b3; 9443e747e6dSmrg 9453e747e6dSmrg XAllocColor(dpy, cmap, &f3); 9463e747e6dSmrg XAllocColor(dpy, cmap, &b3); 9473e747e6dSmrg cur->hi_back = cur->fore = f3.pixel; 9483e747e6dSmrg cur->hi_fore = cur->back = b3.pixel; 9493e747e6dSmrg cur->user_colors = True; 9503e747e6dSmrg 9513e747e6dSmrg f3 = save_fore; 9523e747e6dSmrg b3 = save_back; 9533e747e6dSmrg } 9543e747e6dSmrg start = end; 9553e747e6dSmrg } 9563e747e6dSmrg} 9573e747e6dSmrg 9583e747e6dSmrg 9593e747e6dSmrg 9603e747e6dSmrg/** 9613e747e6dSmrg * pop up a pull down menu. 9623e747e6dSmrg * 9633e747e6dSmrg * \param menu the root pointer of the menu to pop up 9643e747e6dSmrg * \param x,y location of upper left of menu 9653e747e6dSmrg * \param center whether or not to center horizontally over position 9663e747e6dSmrg */ 967ffd25bcaSmrgBool 9683e747e6dSmrgPopUpMenu (MenuRoot *menu, int x, int y, Bool center) 9693e747e6dSmrg{ 9703e747e6dSmrg int WindowNameCount; 9713e747e6dSmrg TwmWindow **WindowNames; 9723e747e6dSmrg TwmWindow *tmp_win2,*tmp_win3; 9733e747e6dSmrg int i; 974ffd25bcaSmrg int (*compar)(const char *, const char *) = 9753e747e6dSmrg (Scr->CaseSensitive ? strcmp : XmuCompareISOLatin1); 9763e747e6dSmrg 9773e747e6dSmrg if (!menu) return False; 9783e747e6dSmrg 9793e747e6dSmrg InstallRootColormap(); 9803e747e6dSmrg 9813e747e6dSmrg if (menu == Scr->Windows) 9823e747e6dSmrg { 9833e747e6dSmrg TwmWindow *tmp_win; 9843e747e6dSmrg 9853e747e6dSmrg /* this is the twm windows menu, let's go ahead and build it */ 9863e747e6dSmrg 9873e747e6dSmrg DestroyMenu (menu); 9883e747e6dSmrg 9893e747e6dSmrg menu->first = NULL; 9903e747e6dSmrg menu->last = NULL; 9913e747e6dSmrg menu->items = 0; 9923e747e6dSmrg menu->width = 0; 9933e747e6dSmrg menu->mapped = NEVER_MAPPED; 9943e747e6dSmrg AddToMenu(menu, "TWM Windows", NULLSTR, NULL, F_TITLE,NULLSTR,NULLSTR); 995ffd25bcaSmrg 9963e747e6dSmrg for(tmp_win = Scr->TwmRoot.next , WindowNameCount=0; 9973e747e6dSmrg tmp_win != NULL; 9983e747e6dSmrg tmp_win = tmp_win->next) 9993e747e6dSmrg WindowNameCount++; 10003e747e6dSmrg if (WindowNameCount != 0) 10013e747e6dSmrg { 1002c2535118Smrg WindowNames = malloc(sizeof(TwmWindow *) * WindowNameCount); 10033e747e6dSmrg WindowNames[0] = Scr->TwmRoot.next; 10043e747e6dSmrg for(tmp_win = Scr->TwmRoot.next->next , WindowNameCount=1; 10053e747e6dSmrg tmp_win != NULL; 10063e747e6dSmrg tmp_win = tmp_win->next,WindowNameCount++) 10073e747e6dSmrg { 10083e747e6dSmrg tmp_win2 = tmp_win; 10093e747e6dSmrg for (i=0;i<WindowNameCount;i++) 10103e747e6dSmrg { 10113e747e6dSmrg if ((*compar)(tmp_win2->name,WindowNames[i]->name) < 0) 10123e747e6dSmrg { 10133e747e6dSmrg tmp_win3 = tmp_win2; 10143e747e6dSmrg tmp_win2 = WindowNames[i]; 10153e747e6dSmrg WindowNames[i] = tmp_win3; 10163e747e6dSmrg } 10173e747e6dSmrg } 10183e747e6dSmrg WindowNames[WindowNameCount] = tmp_win2; 10193e747e6dSmrg } 10203e747e6dSmrg for (i=0; i<WindowNameCount; i++) 10213e747e6dSmrg { 10223e747e6dSmrg AddToMenu(menu, WindowNames[i]->name, (char *)WindowNames[i], 10233e747e6dSmrg NULL, F_POPUP,NULL,NULL); 10243e747e6dSmrg } 10253e747e6dSmrg free(WindowNames); 10263e747e6dSmrg } 10273e747e6dSmrg 10283e747e6dSmrg MakeMenu(menu); 10293e747e6dSmrg } 10303e747e6dSmrg 10313e747e6dSmrg if (menu->w == None || menu->items == 0) return False; 10323e747e6dSmrg 10333e747e6dSmrg /* Prevent recursively bringing up menus. */ 10343e747e6dSmrg if (menu->mapped == MAPPED) return False; 10353e747e6dSmrg 10363e747e6dSmrg /* 10373e747e6dSmrg * Dynamically set the parent; this allows pull-ups to also be main 10383e747e6dSmrg * menus, or to be brought up from more than one place. 10393e747e6dSmrg */ 10403e747e6dSmrg menu->prev = ActiveMenu; 10413e747e6dSmrg 10423e747e6dSmrg XGrabPointer(dpy, Scr->Root, True, 10433e747e6dSmrg ButtonPressMask | ButtonReleaseMask | 10443e747e6dSmrg ButtonMotionMask | PointerMotionHintMask, 10453e747e6dSmrg GrabModeAsync, GrabModeAsync, 10463e747e6dSmrg Scr->Root, Scr->MenuCursor, CurrentTime); 10473e747e6dSmrg 10483e747e6dSmrg ActiveMenu = menu; 10493e747e6dSmrg menu->mapped = MAPPED; 10503e747e6dSmrg menu->entered = FALSE; 10513e747e6dSmrg 10523e747e6dSmrg if (center) { 10533e747e6dSmrg x -= (menu->width / 2); 10543e747e6dSmrg y -= (Scr->EntryHeight / 2); /* sticky menus would be nice here */ 10553e747e6dSmrg } 10563e747e6dSmrg 10573e747e6dSmrg /* 10583e747e6dSmrg * clip to screen 10593e747e6dSmrg */ 10603e747e6dSmrg if (x + menu->width > Scr->MyDisplayWidth) { 10613e747e6dSmrg x = Scr->MyDisplayWidth - menu->width; 10623e747e6dSmrg } 10633e747e6dSmrg if (x < 0) x = 0; 10643e747e6dSmrg if (y + menu->height > Scr->MyDisplayHeight) { 10653e747e6dSmrg y = Scr->MyDisplayHeight - menu->height; 10663e747e6dSmrg } 10673e747e6dSmrg if (y < 0) y = 0; 10683e747e6dSmrg 10693e747e6dSmrg MenuOrigins[MenuDepth].x = x; 10703e747e6dSmrg MenuOrigins[MenuDepth].y = y; 10713e747e6dSmrg MenuDepth++; 10723e747e6dSmrg 10733e747e6dSmrg XMoveWindow(dpy, menu->w, x, y); 10743e747e6dSmrg if (Scr->Shadow) { 10753e747e6dSmrg XMoveWindow (dpy, menu->shadow, x + SHADOWWIDTH, y + SHADOWWIDTH); 10763e747e6dSmrg } 10773e747e6dSmrg if (Scr->Shadow) { 10783e747e6dSmrg XRaiseWindow (dpy, menu->shadow); 10793e747e6dSmrg } 10803e747e6dSmrg XMapRaised(dpy, menu->w); 10813e747e6dSmrg if (Scr->Shadow) { 10823e747e6dSmrg XMapWindow (dpy, menu->shadow); 10833e747e6dSmrg } 10843e747e6dSmrg XSync(dpy, 0); 10853e747e6dSmrg return True; 10863e747e6dSmrg} 10873e747e6dSmrg 10883e747e6dSmrg 10893e747e6dSmrg 10903e747e6dSmrg/** 10913e747e6dSmrg * unhighlight the current menu selection and take down the menus 10923e747e6dSmrg */ 10933e747e6dSmrgvoid 1094c2535118SmrgPopDownMenu(void) 10953e747e6dSmrg{ 10963e747e6dSmrg MenuRoot *tmp; 10973e747e6dSmrg 10983e747e6dSmrg if (ActiveMenu == NULL) 10993e747e6dSmrg return; 11003e747e6dSmrg 11013e747e6dSmrg if (ActiveItem) 11023e747e6dSmrg { 11033e747e6dSmrg ActiveItem->state = 0; 11043e747e6dSmrg PaintEntry(ActiveMenu, ActiveItem, False); 11053e747e6dSmrg } 11063e747e6dSmrg 11073e747e6dSmrg for (tmp = ActiveMenu; tmp != NULL; tmp = tmp->prev) 11083e747e6dSmrg { 11093e747e6dSmrg if (Scr->Shadow) { 11103e747e6dSmrg XUnmapWindow (dpy, tmp->shadow); 11113e747e6dSmrg } 11123e747e6dSmrg XUnmapWindow(dpy, tmp->w); 11133e747e6dSmrg tmp->mapped = UNMAPPED; 11143e747e6dSmrg UninstallRootColormap(); 11153e747e6dSmrg } 11163e747e6dSmrg 11173e747e6dSmrg XFlush(dpy); 11183e747e6dSmrg ActiveMenu = NULL; 11193e747e6dSmrg ActiveItem = NULL; 11203e747e6dSmrg MenuDepth = 0; 11213e747e6dSmrg if (Context == C_WINDOW || Context == C_FRAME || Context == C_TITLE) 11223e747e6dSmrg menuFromFrameOrWindowOrTitlebar = TRUE; 11233e747e6dSmrg} 11243e747e6dSmrg 11253e747e6dSmrg 11263e747e6dSmrg 11273e747e6dSmrg/** 11283e747e6dSmrg * look for a menu root 11293e747e6dSmrg * 11303e747e6dSmrg * \return a pointer to the menu root structure 11313e747e6dSmrg * 11323e747e6dSmrg * \param name the name of the menu root 11333e747e6dSmrg */ 11343e747e6dSmrgMenuRoot * 1135c2535118SmrgFindMenuRoot(const char *name) 11363e747e6dSmrg{ 11373e747e6dSmrg MenuRoot *tmp; 11383e747e6dSmrg 11393e747e6dSmrg for (tmp = Scr->MenuList; tmp != NULL; tmp = tmp->next) 11403e747e6dSmrg { 11413e747e6dSmrg if (strcmp(name, tmp->name) == 0) 11423e747e6dSmrg return (tmp); 11433e747e6dSmrg } 11443e747e6dSmrg return NULL; 11453e747e6dSmrg} 11463e747e6dSmrg 11473e747e6dSmrg 11483e747e6dSmrg 1149ffd25bcaSmrgstatic Bool 11503e747e6dSmrgbelongs_to_twm_window (TwmWindow *t, Window w) 11513e747e6dSmrg{ 11523e747e6dSmrg if (!t) return False; 11533e747e6dSmrg 11543e747e6dSmrg if (w == t->frame || w == t->title_w || w == t->hilite_w || 11553e747e6dSmrg w == t->icon_w || w == t->icon_bm_w) return True; 1156ffd25bcaSmrg 11573e747e6dSmrg if (t && t->titlebuttons) { 11583e747e6dSmrg register TBWindow *tbw; 11593e747e6dSmrg register int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright; 11603e747e6dSmrg for (tbw = t->titlebuttons; nb > 0; tbw++, nb--) { 11613e747e6dSmrg if (tbw->window == w) return True; 11623e747e6dSmrg } 11633e747e6dSmrg } 11643e747e6dSmrg return False; 11653e747e6dSmrg} 11663e747e6dSmrg 11673e747e6dSmrg 11683e747e6dSmrg 1169c2535118Smrgstatic void 11703e747e6dSmrgresizeFromCenter(Window w, TwmWindow *tmp_win) 11713e747e6dSmrg{ 11723e747e6dSmrg int lastx, lasty, bw2; 11733e747e6dSmrg XEvent event; 11743e747e6dSmrg#if 0 11753e747e6dSmrg int namelen; 11763e747e6dSmrg int width, height; 11773e747e6dSmrg 11783e747e6dSmrg namelen = strlen (tmp_win->name); 11793e747e6dSmrg#endif 11803e747e6dSmrg bw2 = tmp_win->frame_bw * 2; 11813e747e6dSmrg AddingW = tmp_win->attr.width + bw2; 11823e747e6dSmrg AddingH = tmp_win->attr.height + tmp_win->title_height + bw2; 11833e747e6dSmrg#if 0 11843e747e6dSmrg width = (SIZE_HINDENT + MyFont_TextWidth (&Scr->SizeFont, 11853e747e6dSmrg tmp_win->name, namelen)); 11863e747e6dSmrg height = Scr->SizeFont.height + SIZE_VINDENT * 2; 11873e747e6dSmrg#endif 11883e747e6dSmrg XGetGeometry(dpy, w, &JunkRoot, &origDragX, &origDragY, 1189ffd25bcaSmrg (unsigned int *)&DragWidth, (unsigned int *)&DragHeight, 11903e747e6dSmrg &JunkBW, &JunkDepth); 11913e747e6dSmrg XWarpPointer(dpy, None, w, 1192ffd25bcaSmrg 0, 0, 0, 0, DragWidth/2, DragHeight/2); 1193ffd25bcaSmrg XQueryPointer (dpy, Scr->Root, &JunkRoot, 11943e747e6dSmrg &JunkChild, &JunkX, &JunkY, 11953e747e6dSmrg &AddingX, &AddingY, &JunkMask); 11963e747e6dSmrg#if 0 11973e747e6dSmrg Scr->SizeStringOffset = width + 11983e747e6dSmrg MyFont_TextWidth(&Scr->SizeFont, ": ", 2); 11993e747e6dSmrg XResizeWindow (dpy, Scr->SizeWindow, Scr->SizeStringOffset + 12003e747e6dSmrg Scr->SizeStringWidth, height); 12013e747e6dSmrg MyFont_DrawImageString (dpy, Scr->SizeWindow, &Scr->SizeFont, Scr->NormalGC, 12023e747e6dSmrg width, SIZE_VINDENT + Scr->SizeFont.ascent, 12033e747e6dSmrg ": ", 2); 12043e747e6dSmrg#endif 12053e747e6dSmrg lastx = -10000; 12063e747e6dSmrg lasty = -10000; 12073e747e6dSmrg#if 0 12083e747e6dSmrg MoveOutline(Scr->Root, 12093e747e6dSmrg origDragX - JunkBW, origDragY - JunkBW, 12103e747e6dSmrg DragWidth * JunkBW, DragHeight * JunkBW, 12113e747e6dSmrg tmp_win->frame_bw, 12123e747e6dSmrg tmp_win->title_height); 12133e747e6dSmrg#endif 12143e747e6dSmrg MenuStartResize(tmp_win, origDragX, origDragY, DragWidth, DragHeight); 12153e747e6dSmrg while (TRUE) 12163e747e6dSmrg { 12173e747e6dSmrg XMaskEvent(dpy, 12183e747e6dSmrg ButtonPressMask | PointerMotionMask, &event); 1219ffd25bcaSmrg 12203e747e6dSmrg if (event.type == MotionNotify) { 12213e747e6dSmrg /* discard any extra motion events before a release */ 12223e747e6dSmrg while(XCheckMaskEvent(dpy, 12233e747e6dSmrg ButtonMotionMask | ButtonPressMask, &event)) 12243e747e6dSmrg if (event.type == ButtonPress) 12253e747e6dSmrg break; 12263e747e6dSmrg } 1227ffd25bcaSmrg 12283e747e6dSmrg if (event.type == ButtonPress) 12293e747e6dSmrg { 12303e747e6dSmrg MenuEndResize(tmp_win); 12313e747e6dSmrg XMoveResizeWindow(dpy, w, AddingX, AddingY, AddingW, AddingH); 12323e747e6dSmrg break; 12333e747e6dSmrg } 1234ffd25bcaSmrg 12353e747e6dSmrg/* if (!DispatchEvent ()) continue; */ 12363e747e6dSmrg 12373e747e6dSmrg if (event.type != MotionNotify) { 12383e747e6dSmrg continue; 12393e747e6dSmrg } 1240ffd25bcaSmrg 12413e747e6dSmrg /* 12423e747e6dSmrg * XXX - if we are going to do a loop, we ought to consider 1243ffd25bcaSmrg * using multiple GXxor lines so that we don't need to 12443e747e6dSmrg * grab the server. 12453e747e6dSmrg */ 12463e747e6dSmrg XQueryPointer(dpy, Scr->Root, &JunkRoot, &JunkChild, 12473e747e6dSmrg &JunkX, &JunkY, &AddingX, &AddingY, &JunkMask); 1248ffd25bcaSmrg 12493e747e6dSmrg if (lastx != AddingX || lasty != AddingY) 12503e747e6dSmrg { 12513e747e6dSmrg MenuDoResize(AddingX, AddingY, tmp_win); 1252ffd25bcaSmrg 12533e747e6dSmrg lastx = AddingX; 12543e747e6dSmrg lasty = AddingY; 12553e747e6dSmrg } 1256ffd25bcaSmrg 12573e747e6dSmrg } 1258ffd25bcaSmrg} 12593e747e6dSmrg 12603e747e6dSmrg 12613e747e6dSmrg 12623e747e6dSmrg/** \fn ExecuteFunction 12633e747e6dSmrg * execute a twm root function. 12643e747e6dSmrg * 12653e747e6dSmrg * \param func the function to execute 1266ffd25bcaSmrg * \param action the menu action to execute 12673e747e6dSmrg * \param w the window to execute this function on 12683e747e6dSmrg * \param tmp_win the twm window structure 12693e747e6dSmrg * \param event the event that caused the function 12703e747e6dSmrg * \param context the context in which the button was pressed 12713e747e6dSmrg * \param pulldown flag indicating execution from pull down menu 12723e747e6dSmrg * 1273ffd25bcaSmrg * \return TRUE if should continue with remaining actions, 12743e747e6dSmrg * else FALSE to abort 12753e747e6dSmrg */ 12763e747e6dSmrg 1277c2535118Smrgstatic int 1278ffd25bcaSmrgWarpThere(TwmWindow *t) 12793e747e6dSmrg{ 12803e747e6dSmrg if (Scr->WarpUnmapped || t->mapped) { 12813e747e6dSmrg if (!t->mapped) DeIconify (t); 12823e747e6dSmrg if (!Scr->NoRaiseWarp) XRaiseWindow (dpy, t->frame); 1283ffd25bcaSmrg WarpToWindow (t); 1284ffd25bcaSmrg return 1; 1285ffd25bcaSmrg } 12863e747e6dSmrg return 0; 12873e747e6dSmrg} 12883e747e6dSmrg 12893e747e6dSmrg 12903e747e6dSmrgint 1291c2535118SmrgExecuteFunction(int func, const char *action, Window w, TwmWindow *tmp_win, 12923e747e6dSmrg XEvent *eventp, int context, int pulldown) 12933e747e6dSmrg{ 12943e747e6dSmrg static Time last_time = 0; 12953e747e6dSmrg char tmp[200]; 12963e747e6dSmrg char *ptr; 12973e747e6dSmrg char buff[MAX_FILE_SIZE]; 12983e747e6dSmrg int count, fd; 12993e747e6dSmrg Window rootw; 13003e747e6dSmrg int origX, origY; 13013e747e6dSmrg int do_next_action = TRUE; 13023e747e6dSmrg int moving_icon = FALSE; 13033e747e6dSmrg Bool fromtitlebar = False; 13043e747e6dSmrg 13053e747e6dSmrg RootFunction = 0; 13063e747e6dSmrg if (Cancel) 13073e747e6dSmrg return TRUE; /* XXX should this be FALSE? */ 13083e747e6dSmrg 13093e747e6dSmrg switch (func) 13103e747e6dSmrg { 13113e747e6dSmrg case F_UPICONMGR: 13123e747e6dSmrg case F_LEFTICONMGR: 13133e747e6dSmrg case F_RIGHTICONMGR: 13143e747e6dSmrg case F_DOWNICONMGR: 13153e747e6dSmrg case F_FORWICONMGR: 13163e747e6dSmrg case F_BACKICONMGR: 13173e747e6dSmrg case F_NEXTICONMGR: 13183e747e6dSmrg case F_PREVICONMGR: 13193e747e6dSmrg case F_NOP: 13203e747e6dSmrg case F_TITLE: 13213e747e6dSmrg case F_DELTASTOP: 13223e747e6dSmrg case F_RAISELOWER: 13233e747e6dSmrg case F_WARPTOSCREEN: 13243e747e6dSmrg case F_WARPTO: 13253e747e6dSmrg case F_WARPRING: 13263e747e6dSmrg case F_WARPTOICONMGR: 13273e747e6dSmrg case F_WARPNEXT: 13283e747e6dSmrg case F_WARPPREV: 13293e747e6dSmrg case F_COLORMAP: 13303e747e6dSmrg break; 13313e747e6dSmrg default: 13323e747e6dSmrg XGrabPointer(dpy, Scr->Root, True, 13333e747e6dSmrg ButtonPressMask | ButtonReleaseMask, 13343e747e6dSmrg GrabModeAsync, GrabModeAsync, 13353e747e6dSmrg Scr->Root, Scr->WaitCursor, CurrentTime); 13363e747e6dSmrg break; 13373e747e6dSmrg } 13383e747e6dSmrg 13393e747e6dSmrg switch (func) 13403e747e6dSmrg { 13413e747e6dSmrg case F_NOP: 13423e747e6dSmrg case F_TITLE: 13433e747e6dSmrg break; 13443e747e6dSmrg 13453e747e6dSmrg case F_DELTASTOP: 13463e747e6dSmrg if (WindowMoved) do_next_action = FALSE; 13473e747e6dSmrg break; 13483e747e6dSmrg 13493e747e6dSmrg case F_RESTART: 13503e747e6dSmrg { 13513e747e6dSmrg XSync (dpy, 0); 13523e747e6dSmrg Reborder (eventp->xbutton.time); 13533e747e6dSmrg XSync (dpy, 0); 13543e747e6dSmrg if (smcConn) 13553e747e6dSmrg SmcCloseConnection (smcConn, 0, NULL); 13563e747e6dSmrg execvp(*Argv, Argv); 13573e747e6dSmrg fprintf (stderr, "%s: unable to restart: %s\n", ProgramName, *Argv); 13583e747e6dSmrg break; 13593e747e6dSmrg } 13603e747e6dSmrg 13613e747e6dSmrg case F_UPICONMGR: 13623e747e6dSmrg case F_DOWNICONMGR: 13633e747e6dSmrg case F_LEFTICONMGR: 13643e747e6dSmrg case F_RIGHTICONMGR: 13653e747e6dSmrg case F_FORWICONMGR: 13663e747e6dSmrg case F_BACKICONMGR: 13673e747e6dSmrg MoveIconManager(func); 13683e747e6dSmrg break; 13693e747e6dSmrg 13703e747e6dSmrg case F_NEXTICONMGR: 13713e747e6dSmrg case F_PREVICONMGR: 13723e747e6dSmrg JumpIconManager(func); 13733e747e6dSmrg break; 13743e747e6dSmrg 13753e747e6dSmrg case F_SHOWLIST: 13763e747e6dSmrg if (Scr->NoIconManagers) 13773e747e6dSmrg break; 13783e747e6dSmrg DeIconify(Scr->iconmgr.twm_win); 13793e747e6dSmrg XRaiseWindow(dpy, Scr->iconmgr.twm_win->frame); 13803e747e6dSmrg break; 13813e747e6dSmrg 13823e747e6dSmrg case F_HIDELIST: 13833e747e6dSmrg if (Scr->NoIconManagers) 13843e747e6dSmrg break; 13853e747e6dSmrg HideIconManager (); 13863e747e6dSmrg break; 13873e747e6dSmrg 13883e747e6dSmrg case F_SORTICONMGR: 13893e747e6dSmrg if (DeferExecution(context, func, Scr->SelectCursor)) 13903e747e6dSmrg return TRUE; 13913e747e6dSmrg 13923e747e6dSmrg { 13933e747e6dSmrg int save_sort; 13943e747e6dSmrg 13953e747e6dSmrg save_sort = Scr->SortIconMgr; 13963e747e6dSmrg Scr->SortIconMgr = TRUE; 13973e747e6dSmrg 13983e747e6dSmrg if (context == C_ICONMGR) 13993e747e6dSmrg SortIconManager((IconMgr *) NULL); 14003e747e6dSmrg else if (tmp_win->iconmgr) 14013e747e6dSmrg SortIconManager(tmp_win->iconmgrp); 1402ffd25bcaSmrg else 14033e747e6dSmrg Bell(XkbBI_Info,0,tmp_win->w); 14043e747e6dSmrg 14053e747e6dSmrg Scr->SortIconMgr = save_sort; 14063e747e6dSmrg } 14073e747e6dSmrg break; 14083e747e6dSmrg 14093e747e6dSmrg case F_IDENTIFY: 14103e747e6dSmrg if (DeferExecution(context, func, Scr->SelectCursor)) 14113e747e6dSmrg return TRUE; 14123e747e6dSmrg 14133e747e6dSmrg Identify(tmp_win); 14143e747e6dSmrg break; 14153e747e6dSmrg 14163e747e6dSmrg case F_VERSION: 14173e747e6dSmrg Identify ((TwmWindow *) NULL); 14183e747e6dSmrg break; 14193e747e6dSmrg 14203e747e6dSmrg case F_AUTORAISE: 14213e747e6dSmrg if (DeferExecution(context, func, Scr->SelectCursor)) 14223e747e6dSmrg return TRUE; 14233e747e6dSmrg 14243e747e6dSmrg tmp_win->auto_raise = !tmp_win->auto_raise; 14253e747e6dSmrg if (tmp_win->auto_raise) ++(Scr->NumAutoRaises); 14263e747e6dSmrg else --(Scr->NumAutoRaises); 14273e747e6dSmrg break; 14283e747e6dSmrg 14293e747e6dSmrg case F_BEEP: 14303e747e6dSmrg Bell(XkbBI_Info,0,None); 14313e747e6dSmrg break; 14323e747e6dSmrg 14333e747e6dSmrg case F_POPUP: 14343e747e6dSmrg tmp_win = (TwmWindow *)action; 14353e747e6dSmrg if (Scr->WindowFunction.func != 0) 14363e747e6dSmrg { 14373e747e6dSmrg ExecuteFunction(Scr->WindowFunction.func, 14383e747e6dSmrg Scr->WindowFunction.item->action, 14393e747e6dSmrg w, tmp_win, eventp, C_FRAME, FALSE); 14403e747e6dSmrg } 14413e747e6dSmrg else 14423e747e6dSmrg { 14433e747e6dSmrg DeIconify(tmp_win); 14443e747e6dSmrg XRaiseWindow (dpy, tmp_win->frame); 14453e747e6dSmrg } 14463e747e6dSmrg break; 14473e747e6dSmrg 14483e747e6dSmrg case F_RESIZE: 14493e747e6dSmrg EventHandler[EnterNotify] = HandleUnknown; 14503e747e6dSmrg EventHandler[LeaveNotify] = HandleUnknown; 14513e747e6dSmrg if (DeferExecution(context, func, Scr->MoveCursor)) 14523e747e6dSmrg return TRUE; 14533e747e6dSmrg 14543e747e6dSmrg PopDownMenu(); 14553e747e6dSmrg 14563e747e6dSmrg if (pulldown) 1457ffd25bcaSmrg XWarpPointer(dpy, None, Scr->Root, 14583e747e6dSmrg 0, 0, 0, 0, eventp->xbutton.x_root, eventp->xbutton.y_root); 14593e747e6dSmrg 14603e747e6dSmrg if (w != tmp_win->icon_w) { /* can't resize icons */ 14613e747e6dSmrg 14623e747e6dSmrg if ((Context == C_FRAME || Context == C_WINDOW || Context == C_TITLE) 1463ffd25bcaSmrg && fromMenu) 14643e747e6dSmrg resizeFromCenter(w, tmp_win); 14653e747e6dSmrg else { 14663e747e6dSmrg /* 14673e747e6dSmrg * see if this is being done from the titlebar 14683e747e6dSmrg */ 1469ffd25bcaSmrg fromtitlebar = 14703e747e6dSmrg belongs_to_twm_window (tmp_win, eventp->xbutton.window); 1471ffd25bcaSmrg 14723e747e6dSmrg /* Save pointer position so we can tell if it was moved or 14733e747e6dSmrg not during the resize. */ 14743e747e6dSmrg ResizeOrigX = eventp->xbutton.x_root; 14753e747e6dSmrg ResizeOrigY = eventp->xbutton.y_root; 1476ffd25bcaSmrg 14773e747e6dSmrg StartResize (eventp, tmp_win, fromtitlebar); 1478ffd25bcaSmrg 14793e747e6dSmrg do { 14803e747e6dSmrg XMaskEvent(dpy, 14813e747e6dSmrg ButtonPressMask | ButtonReleaseMask | 14823e747e6dSmrg EnterWindowMask | LeaveWindowMask | 14833e747e6dSmrg ButtonMotionMask, &Event); 1484ffd25bcaSmrg 14853e747e6dSmrg if (fromtitlebar && Event.type == ButtonPress) { 14863e747e6dSmrg fromtitlebar = False; 14873e747e6dSmrg continue; 14883e747e6dSmrg } 1489ffd25bcaSmrg 14903e747e6dSmrg if (Event.type == MotionNotify) { 14913e747e6dSmrg /* discard any extra motion events before a release */ 14923e747e6dSmrg while 14933e747e6dSmrg (XCheckMaskEvent 14943e747e6dSmrg (dpy, ButtonMotionMask | ButtonReleaseMask, &Event)) 14953e747e6dSmrg if (Event.type == ButtonRelease) 14963e747e6dSmrg break; 14973e747e6dSmrg } 1498ffd25bcaSmrg 14993e747e6dSmrg if (!DispatchEvent ()) continue; 1500ffd25bcaSmrg 15013e747e6dSmrg } while (!(Event.type == ButtonRelease || Cancel)); 15023e747e6dSmrg return TRUE; 15033e747e6dSmrg } 1504ffd25bcaSmrg } 15053e747e6dSmrg break; 15063e747e6dSmrg 15073e747e6dSmrg 15083e747e6dSmrg case F_ZOOM: 15093e747e6dSmrg case F_HORIZOOM: 15103e747e6dSmrg case F_FULLZOOM: 15113e747e6dSmrg case F_LEFTZOOM: 15123e747e6dSmrg case F_RIGHTZOOM: 15133e747e6dSmrg case F_TOPZOOM: 15143e747e6dSmrg case F_BOTTOMZOOM: 15153e747e6dSmrg if (DeferExecution(context, func, Scr->SelectCursor)) 15163e747e6dSmrg return TRUE; 15173e747e6dSmrg fullzoom(tmp_win, func); 15183e747e6dSmrg break; 15193e747e6dSmrg 15203e747e6dSmrg case F_MOVE: 15213e747e6dSmrg case F_FORCEMOVE: 15223e747e6dSmrg if (DeferExecution(context, func, Scr->MoveCursor)) 15233e747e6dSmrg return TRUE; 15243e747e6dSmrg 15253e747e6dSmrg PopDownMenu(); 15263e747e6dSmrg rootw = eventp->xbutton.root; 15273e747e6dSmrg MoveFunction = func; 15283e747e6dSmrg 15293e747e6dSmrg if (pulldown) 1530ffd25bcaSmrg XWarpPointer(dpy, None, Scr->Root, 15313e747e6dSmrg 0, 0, 0, 0, eventp->xbutton.x_root, eventp->xbutton.y_root); 15323e747e6dSmrg 15333e747e6dSmrg EventHandler[EnterNotify] = HandleUnknown; 15343e747e6dSmrg EventHandler[LeaveNotify] = HandleUnknown; 15353e747e6dSmrg 15363e747e6dSmrg if (!Scr->NoGrabServer || !Scr->OpaqueMove) { 15373e747e6dSmrg XGrabServer(dpy); 15383e747e6dSmrg } 15393e747e6dSmrg XGrabPointer(dpy, eventp->xbutton.root, True, 15403e747e6dSmrg ButtonPressMask | ButtonReleaseMask | 15413e747e6dSmrg ButtonMotionMask | PointerMotionMask, /* PointerMotionHintMask */ 15423e747e6dSmrg GrabModeAsync, GrabModeAsync, 15433e747e6dSmrg Scr->Root, Scr->MoveCursor, CurrentTime); 15443e747e6dSmrg 15453e747e6dSmrg if (context == C_ICON && tmp_win->icon_w) 15463e747e6dSmrg { 15473e747e6dSmrg w = tmp_win->icon_w; 15483e747e6dSmrg DragX = eventp->xbutton.x; 15493e747e6dSmrg DragY = eventp->xbutton.y; 15503e747e6dSmrg moving_icon = TRUE; 15513e747e6dSmrg } 15523e747e6dSmrg 15533e747e6dSmrg else if (w != tmp_win->icon_w) 15543e747e6dSmrg { 15553e747e6dSmrg XTranslateCoordinates(dpy, w, tmp_win->frame, 1556ffd25bcaSmrg eventp->xbutton.x, 1557ffd25bcaSmrg eventp->xbutton.y, 15583e747e6dSmrg &DragX, &DragY, &JunkChild); 15593e747e6dSmrg 15603e747e6dSmrg w = tmp_win->frame; 15613e747e6dSmrg } 15623e747e6dSmrg 15633e747e6dSmrg DragWindow = None; 15643e747e6dSmrg 15653e747e6dSmrg XGetGeometry(dpy, w, &JunkRoot, &origDragX, &origDragY, 15663e747e6dSmrg (unsigned int *)&DragWidth, (unsigned int *)&DragHeight, &JunkBW, 15673e747e6dSmrg &JunkDepth); 15683e747e6dSmrg 15693e747e6dSmrg origX = eventp->xbutton.x_root; 15703e747e6dSmrg origY = eventp->xbutton.y_root; 15713e747e6dSmrg CurrentDragX = origDragX; 15723e747e6dSmrg CurrentDragY = origDragY; 15733e747e6dSmrg 15743e747e6dSmrg /* 15753e747e6dSmrg * only do the constrained move if timer is set; need to check it 15763e747e6dSmrg * in case of stupid or wicked fast servers 15773e747e6dSmrg */ 1578ffd25bcaSmrg if (ConstrainedMoveTime && 15793e747e6dSmrg (eventp->xbutton.time - last_time) < ConstrainedMoveTime) 15803e747e6dSmrg { 15813e747e6dSmrg int width, height; 15823e747e6dSmrg 15833e747e6dSmrg ConstMove = TRUE; 15843e747e6dSmrg ConstMoveDir = MOVE_NONE; 15853e747e6dSmrg ConstMoveX = eventp->xbutton.x_root - DragX - JunkBW; 15863e747e6dSmrg ConstMoveY = eventp->xbutton.y_root - DragY - JunkBW; 15873e747e6dSmrg width = DragWidth + 2 * JunkBW; 15883e747e6dSmrg height = DragHeight + 2 * JunkBW; 15893e747e6dSmrg ConstMoveXL = ConstMoveX + width/3; 15903e747e6dSmrg ConstMoveXR = ConstMoveX + 2*(width/3); 15913e747e6dSmrg ConstMoveYT = ConstMoveY + height/3; 15923e747e6dSmrg ConstMoveYB = ConstMoveY + 2*(height/3); 15933e747e6dSmrg 15943e747e6dSmrg XWarpPointer(dpy, None, w, 15953e747e6dSmrg 0, 0, 0, 0, DragWidth/2, DragHeight/2); 15963e747e6dSmrg 15973e747e6dSmrg XQueryPointer(dpy, w, &JunkRoot, &JunkChild, 15983e747e6dSmrg &JunkX, &JunkY, &DragX, &DragY, &JunkMask); 15993e747e6dSmrg } 16003e747e6dSmrg last_time = eventp->xbutton.time; 16013e747e6dSmrg 16023e747e6dSmrg if (!Scr->OpaqueMove) 16033e747e6dSmrg { 16043e747e6dSmrg InstallRootColormap(); 16053e747e6dSmrg if (!Scr->MoveDelta) 16063e747e6dSmrg { 16073e747e6dSmrg /* 16083e747e6dSmrg * Draw initial outline. This was previously done the 16093e747e6dSmrg * first time though the outer loop by dropping out of 16103e747e6dSmrg * the XCheckMaskEvent inner loop down to one of the 16113e747e6dSmrg * MoveOutline's below. 16123e747e6dSmrg */ 16133e747e6dSmrg MoveOutline(rootw, 16143e747e6dSmrg origDragX - JunkBW, origDragY - JunkBW, 16153e747e6dSmrg DragWidth + 2 * JunkBW, DragHeight + 2 * JunkBW, 16163e747e6dSmrg tmp_win->frame_bw, 16173e747e6dSmrg moving_icon ? 0 : tmp_win->title_height); 16183e747e6dSmrg /* 16193e747e6dSmrg * This next line causes HandleReleaseNotify to call 16203e747e6dSmrg * XRaiseWindow(). This is solely to preserve the 16213e747e6dSmrg * previous behaviour that raises a window being moved 16223e747e6dSmrg * on button release even if you never actually moved 16233e747e6dSmrg * any distance (unless you move less than MoveDelta or 16243e747e6dSmrg * NoRaiseMove is set or OpaqueMove is set). 16253e747e6dSmrg */ 16263e747e6dSmrg DragWindow = w; 16273e747e6dSmrg } 16283e747e6dSmrg } 16293e747e6dSmrg 16303e747e6dSmrg /* 16313e747e6dSmrg * see if this is being done from the titlebar 16323e747e6dSmrg */ 16333e747e6dSmrg fromtitlebar = belongs_to_twm_window (tmp_win, eventp->xbutton.window); 16343e747e6dSmrg 16353e747e6dSmrg if (menuFromFrameOrWindowOrTitlebar) { 16363e747e6dSmrg /* warp the pointer to the middle of the window */ 1637ffd25bcaSmrg XWarpPointer(dpy, None, Scr->Root, 0, 0, 0, 0, 1638ffd25bcaSmrg origDragX + DragWidth / 2, 16393e747e6dSmrg origDragY + DragHeight / 2); 16403e747e6dSmrg XFlush(dpy); 16413e747e6dSmrg } 1642ffd25bcaSmrg 16433e747e6dSmrg while (TRUE) 16443e747e6dSmrg { 1645ffd25bcaSmrg long releaseEvent = menuFromFrameOrWindowOrTitlebar ? 16463e747e6dSmrg ButtonPress : ButtonRelease; 16473e747e6dSmrg long movementMask = menuFromFrameOrWindowOrTitlebar ? 16483e747e6dSmrg PointerMotionMask : ButtonMotionMask; 16493e747e6dSmrg 16503e747e6dSmrg /* block until there is an interesting event */ 16513e747e6dSmrg XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | 16523e747e6dSmrg EnterWindowMask | LeaveWindowMask | 16533e747e6dSmrg ExposureMask | movementMask | 16543e747e6dSmrg VisibilityChangeMask, &Event); 16553e747e6dSmrg 16563e747e6dSmrg /* throw away enter and leave events until release */ 16573e747e6dSmrg if (Event.xany.type == EnterNotify || 1658ffd25bcaSmrg Event.xany.type == LeaveNotify) continue; 16593e747e6dSmrg 16603e747e6dSmrg if (Event.type == MotionNotify) { 16613e747e6dSmrg /* discard any extra motion events before a logical release */ 16623e747e6dSmrg while(XCheckMaskEvent(dpy, 16633e747e6dSmrg movementMask | releaseEvent, &Event)) 16643e747e6dSmrg if (Event.type == releaseEvent) 16653e747e6dSmrg break; 16663e747e6dSmrg } 16673e747e6dSmrg 16683e747e6dSmrg /* test to see if we have a second button press to abort move */ 16693e747e6dSmrg if (!menuFromFrameOrWindowOrTitlebar && !MovedFromKeyPress) { 16703e747e6dSmrg if (Event.type == ButtonPress && DragWindow != None) { 16713e747e6dSmrg if (Scr->OpaqueMove) 16723e747e6dSmrg XMoveWindow (dpy, DragWindow, origDragX, origDragY); 16733e747e6dSmrg else 16743e747e6dSmrg MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0); 16753e747e6dSmrg DragWindow = None; 16763e747e6dSmrg } 16773e747e6dSmrg } 16783e747e6dSmrg if (fromtitlebar && Event.type == ButtonPress) { 16793e747e6dSmrg fromtitlebar = False; 16803e747e6dSmrg CurrentDragX = origX = Event.xbutton.x_root; 16813e747e6dSmrg CurrentDragY = origY = Event.xbutton.y_root; 16823e747e6dSmrg XTranslateCoordinates (dpy, rootw, tmp_win->frame, 16833e747e6dSmrg origX, origY, 16843e747e6dSmrg &DragX, &DragY, &JunkChild); 16853e747e6dSmrg continue; 16863e747e6dSmrg } 16873e747e6dSmrg 16883e747e6dSmrg if (!DispatchEvent2 ()) continue; 16893e747e6dSmrg 16903e747e6dSmrg if (Cancel) 16913e747e6dSmrg { 16923e747e6dSmrg WindowMoved = FALSE; 16933e747e6dSmrg if (!Scr->OpaqueMove) 16943e747e6dSmrg UninstallRootColormap(); 16953e747e6dSmrg return TRUE; /* XXX should this be FALSE? */ 16963e747e6dSmrg } 16973e747e6dSmrg if (Event.type == releaseEvent) 16983e747e6dSmrg { 16993e747e6dSmrg MoveOutline(rootw, 0, 0, 0, 0, 0, 0); 17003e747e6dSmrg if (moving_icon && 17013e747e6dSmrg ((CurrentDragX != origDragX || 17023e747e6dSmrg CurrentDragY != origDragY))) 17033e747e6dSmrg tmp_win->icon_moved = TRUE; 17043e747e6dSmrg if (!Scr->OpaqueMove && menuFromFrameOrWindowOrTitlebar) 1705ffd25bcaSmrg XMoveWindow(dpy, DragWindow, 17063e747e6dSmrg Event.xbutton.x_root - DragWidth / 2, 17073e747e6dSmrg Event.xbutton.y_root - DragHeight / 2); 17083e747e6dSmrg break; 17093e747e6dSmrg } 17103e747e6dSmrg 17113e747e6dSmrg /* something left to do only if the pointer moved */ 17123e747e6dSmrg if (Event.type != MotionNotify) 17133e747e6dSmrg continue; 17143e747e6dSmrg 17153e747e6dSmrg XQueryPointer(dpy, rootw, &(eventp->xmotion.root), &JunkChild, 17163e747e6dSmrg &(eventp->xmotion.x_root), &(eventp->xmotion.y_root), 17173e747e6dSmrg &JunkX, &JunkY, &JunkMask); 17183e747e6dSmrg 17193e747e6dSmrg if (DragWindow == None && 17203e747e6dSmrg abs(eventp->xmotion.x_root - origX) < Scr->MoveDelta && 17213e747e6dSmrg abs(eventp->xmotion.y_root - origY) < Scr->MoveDelta) 17223e747e6dSmrg continue; 17233e747e6dSmrg 17243e747e6dSmrg WindowMoved = TRUE; 17253e747e6dSmrg DragWindow = w; 17263e747e6dSmrg 17273e747e6dSmrg if (!Scr->NoRaiseMove && Scr->OpaqueMove) /* can't restore... */ 17283e747e6dSmrg XRaiseWindow(dpy, DragWindow); 17293e747e6dSmrg 17303e747e6dSmrg if (ConstMove) 17313e747e6dSmrg { 17323e747e6dSmrg switch (ConstMoveDir) 17333e747e6dSmrg { 17343e747e6dSmrg case MOVE_NONE: 17353e747e6dSmrg if (eventp->xmotion.x_root < ConstMoveXL || 17363e747e6dSmrg eventp->xmotion.x_root > ConstMoveXR) 17373e747e6dSmrg ConstMoveDir = MOVE_HORIZ; 17383e747e6dSmrg 17393e747e6dSmrg if (eventp->xmotion.y_root < ConstMoveYT || 17403e747e6dSmrg eventp->xmotion.y_root > ConstMoveYB) 17413e747e6dSmrg ConstMoveDir = MOVE_VERT; 17423e747e6dSmrg 17433e747e6dSmrg XQueryPointer(dpy, DragWindow, &JunkRoot, &JunkChild, 17443e747e6dSmrg &JunkX, &JunkY, &DragX, &DragY, &JunkMask); 17453e747e6dSmrg break; 17463e747e6dSmrg 17473e747e6dSmrg case MOVE_VERT: 17483e747e6dSmrg ConstMoveY = eventp->xmotion.y_root - DragY - JunkBW; 17493e747e6dSmrg break; 17503e747e6dSmrg 17513e747e6dSmrg case MOVE_HORIZ: 17523e747e6dSmrg ConstMoveX= eventp->xmotion.x_root - DragX - JunkBW; 17533e747e6dSmrg break; 17543e747e6dSmrg } 17553e747e6dSmrg 17563e747e6dSmrg if (ConstMoveDir != MOVE_NONE) 17573e747e6dSmrg { 17583e747e6dSmrg int xl, yt, xr, yb, w, h; 17593e747e6dSmrg 17603e747e6dSmrg xl = ConstMoveX; 17613e747e6dSmrg yt = ConstMoveY; 17623e747e6dSmrg w = DragWidth + 2 * JunkBW; 17633e747e6dSmrg h = DragHeight + 2 * JunkBW; 17643e747e6dSmrg 17653e747e6dSmrg if (Scr->DontMoveOff && MoveFunction != F_FORCEMOVE) 17663e747e6dSmrg { 17673e747e6dSmrg xr = xl + w; 17683e747e6dSmrg yb = yt + h; 17693e747e6dSmrg 17703e747e6dSmrg if (xl < 0) 17713e747e6dSmrg xl = 0; 17723e747e6dSmrg if (xr > Scr->MyDisplayWidth) 17733e747e6dSmrg xl = Scr->MyDisplayWidth - w; 17743e747e6dSmrg 17753e747e6dSmrg if (yt < 0) 17763e747e6dSmrg yt = 0; 17773e747e6dSmrg if (yb > Scr->MyDisplayHeight) 17783e747e6dSmrg yt = Scr->MyDisplayHeight - h; 17793e747e6dSmrg } 17803e747e6dSmrg CurrentDragX = xl; 17813e747e6dSmrg CurrentDragY = yt; 17823e747e6dSmrg if (Scr->OpaqueMove) 17833e747e6dSmrg XMoveWindow(dpy, DragWindow, xl, yt); 17843e747e6dSmrg else 17853e747e6dSmrg MoveOutline(eventp->xmotion.root, xl, yt, w, h, 1786ffd25bcaSmrg tmp_win->frame_bw, 17873e747e6dSmrg moving_icon ? 0 : tmp_win->title_height); 17883e747e6dSmrg } 17893e747e6dSmrg } 17903e747e6dSmrg else if (DragWindow != None) 17913e747e6dSmrg { 17923e747e6dSmrg int xl, yt, xr, yb, w, h; 17933e747e6dSmrg if (!menuFromFrameOrWindowOrTitlebar) { 17943e747e6dSmrg xl = eventp->xmotion.x_root - DragX - JunkBW; 17953e747e6dSmrg yt = eventp->xmotion.y_root - DragY - JunkBW; 17963e747e6dSmrg } 17973e747e6dSmrg else { 17983e747e6dSmrg xl = eventp->xmotion.x_root - (DragWidth / 2); 17993e747e6dSmrg yt = eventp->xmotion.y_root - (DragHeight / 2); 1800ffd25bcaSmrg } 18013e747e6dSmrg w = DragWidth + 2 * JunkBW; 18023e747e6dSmrg h = DragHeight + 2 * JunkBW; 18033e747e6dSmrg 18043e747e6dSmrg if (Scr->DontMoveOff && MoveFunction != F_FORCEMOVE) 18053e747e6dSmrg { 18063e747e6dSmrg xr = xl + w; 18073e747e6dSmrg yb = yt + h; 18083e747e6dSmrg 18093e747e6dSmrg if (xl < 0) 18103e747e6dSmrg xl = 0; 18113e747e6dSmrg if (xr > Scr->MyDisplayWidth) 18123e747e6dSmrg xl = Scr->MyDisplayWidth - w; 18133e747e6dSmrg 18143e747e6dSmrg if (yt < 0) 18153e747e6dSmrg yt = 0; 18163e747e6dSmrg if (yb > Scr->MyDisplayHeight) 18173e747e6dSmrg yt = Scr->MyDisplayHeight - h; 18183e747e6dSmrg } 18193e747e6dSmrg 18203e747e6dSmrg CurrentDragX = xl; 18213e747e6dSmrg CurrentDragY = yt; 18223e747e6dSmrg if (Scr->OpaqueMove) 18233e747e6dSmrg XMoveWindow(dpy, DragWindow, xl, yt); 18243e747e6dSmrg else 18253e747e6dSmrg MoveOutline(eventp->xmotion.root, xl, yt, w, h, 18263e747e6dSmrg tmp_win->frame_bw, 18273e747e6dSmrg moving_icon ? 0 : tmp_win->title_height); 18283e747e6dSmrg } 18293e747e6dSmrg 18303e747e6dSmrg } 18313e747e6dSmrg MovedFromKeyPress = False; 18323e747e6dSmrg 18333e747e6dSmrg 18343e747e6dSmrg if (!Scr->OpaqueMove && DragWindow == None) 18353e747e6dSmrg UninstallRootColormap(); 18363e747e6dSmrg 18373e747e6dSmrg break; 18383e747e6dSmrg 18393e747e6dSmrg case F_FUNCTION: 18403e747e6dSmrg { 18413e747e6dSmrg MenuRoot *mroot; 18423e747e6dSmrg MenuItem *mitem; 18433e747e6dSmrg 18443e747e6dSmrg if ((mroot = FindMenuRoot(action)) == NULL) 18453e747e6dSmrg { 1846ffd25bcaSmrg fprintf (stderr, "%s: couldn't find function \"%s\"\n", 18473e747e6dSmrg ProgramName, action); 18483e747e6dSmrg return TRUE; 18493e747e6dSmrg } 18503e747e6dSmrg 18513e747e6dSmrg if (NeedToDefer(mroot) && DeferExecution(context, func, Scr->SelectCursor)) 18523e747e6dSmrg return TRUE; 18533e747e6dSmrg else 18543e747e6dSmrg { 18553e747e6dSmrg for (mitem = mroot->first; mitem != NULL; mitem = mitem->next) 18563e747e6dSmrg { 18573e747e6dSmrg if (!ExecuteFunction (mitem->func, mitem->action, w, 18583e747e6dSmrg tmp_win, eventp, context, pulldown)) 18593e747e6dSmrg break; 18603e747e6dSmrg } 18613e747e6dSmrg } 18623e747e6dSmrg } 18633e747e6dSmrg break; 18643e747e6dSmrg 18653e747e6dSmrg case F_DEICONIFY: 18663e747e6dSmrg case F_ICONIFY: 18673e747e6dSmrg if (DeferExecution(context, func, Scr->SelectCursor)) 18683e747e6dSmrg return TRUE; 18693e747e6dSmrg 18703e747e6dSmrg if (tmp_win->icon) 18713e747e6dSmrg { 18723e747e6dSmrg DeIconify(tmp_win); 18733e747e6dSmrg } 18743e747e6dSmrg else if (func == F_ICONIFY) 18753e747e6dSmrg { 18763e747e6dSmrg Iconify (tmp_win, eventp->xbutton.x_root - 5, 18773e747e6dSmrg eventp->xbutton.y_root - 5); 18783e747e6dSmrg } 18793e747e6dSmrg break; 18803e747e6dSmrg 18813e747e6dSmrg case F_RAISELOWER: 18823e747e6dSmrg if (DeferExecution(context, func, Scr->SelectCursor)) 18833e747e6dSmrg return TRUE; 18843e747e6dSmrg 18853e747e6dSmrg if (!WindowMoved) { 18863e747e6dSmrg XWindowChanges xwc; 18873e747e6dSmrg 18883e747e6dSmrg xwc.stack_mode = Opposite; 18893e747e6dSmrg if (w != tmp_win->icon_w) 18903e747e6dSmrg w = tmp_win->frame; 18913e747e6dSmrg XConfigureWindow (dpy, w, CWStackMode, &xwc); 18923e747e6dSmrg } 18933e747e6dSmrg break; 1894ffd25bcaSmrg 18953e747e6dSmrg case F_RAISE: 18963e747e6dSmrg if (DeferExecution(context, func, Scr->SelectCursor)) 18973e747e6dSmrg return TRUE; 18983e747e6dSmrg 18993e747e6dSmrg /* check to make sure raise is not from the WindowFunction */ 1900ffd25bcaSmrg if (w == tmp_win->icon_w && Context != C_ROOT) 19013e747e6dSmrg XRaiseWindow(dpy, tmp_win->icon_w); 19023e747e6dSmrg else 19033e747e6dSmrg XRaiseWindow(dpy, tmp_win->frame); 19043e747e6dSmrg 19053e747e6dSmrg break; 19063e747e6dSmrg 19073e747e6dSmrg case F_LOWER: 19083e747e6dSmrg if (DeferExecution(context, func, Scr->SelectCursor)) 19093e747e6dSmrg return TRUE; 19103e747e6dSmrg 19113e747e6dSmrg if (w == tmp_win->icon_w) 19123e747e6dSmrg XLowerWindow(dpy, tmp_win->icon_w); 19133e747e6dSmrg else 19143e747e6dSmrg XLowerWindow(dpy, tmp_win->frame); 19153e747e6dSmrg 19163e747e6dSmrg break; 19173e747e6dSmrg 19183e747e6dSmrg case F_FOCUS: 19193e747e6dSmrg if (DeferExecution(context, func, Scr->SelectCursor)) 19203e747e6dSmrg return TRUE; 19213e747e6dSmrg 19223e747e6dSmrg if (tmp_win->icon == FALSE) 19233e747e6dSmrg { 19243e747e6dSmrg if (!Scr->FocusRoot && Scr->Focus == tmp_win) 19253e747e6dSmrg { 19263e747e6dSmrg FocusOnRoot(); 19273e747e6dSmrg } 19283e747e6dSmrg else 19293e747e6dSmrg { 19303e747e6dSmrg if (Scr->Focus != NULL) { 19313e747e6dSmrg SetBorder (Scr->Focus, False); 19323e747e6dSmrg if (Scr->Focus->hilite_w) 19333e747e6dSmrg XUnmapWindow (dpy, Scr->Focus->hilite_w); 19343e747e6dSmrg } 19353e747e6dSmrg 19363e747e6dSmrg InstallWindowColormaps (0, tmp_win); 19373e747e6dSmrg if (tmp_win->hilite_w) XMapWindow (dpy, tmp_win->hilite_w); 19383e747e6dSmrg SetBorder (tmp_win, True); 19393e747e6dSmrg if (!tmp_win->wmhints || tmp_win->wmhints->input) 19403e747e6dSmrg SetFocus (tmp_win, eventp->xbutton.time); 19413e747e6dSmrg Scr->FocusRoot = FALSE; 19423e747e6dSmrg Scr->Focus = tmp_win; 19433e747e6dSmrg } 19443e747e6dSmrg } 19453e747e6dSmrg break; 19463e747e6dSmrg 19473e747e6dSmrg case F_DESTROY: 19483e747e6dSmrg if (DeferExecution(context, func, Scr->DestroyCursor)) 19493e747e6dSmrg return TRUE; 19503e747e6dSmrg 19513e747e6dSmrg if (tmp_win->iconmgr) 19523e747e6dSmrg Bell(XkbBI_MinorError,0,tmp_win->w); 19533e747e6dSmrg else 19543e747e6dSmrg XKillClient(dpy, tmp_win->w); 19553e747e6dSmrg break; 19563e747e6dSmrg 19573e747e6dSmrg case F_DELETE: 19583e747e6dSmrg if (DeferExecution(context, func, Scr->DestroyCursor)) 19593e747e6dSmrg return TRUE; 19603e747e6dSmrg 19613e747e6dSmrg if (tmp_win->iconmgr) /* don't send ourself a message */ 19623e747e6dSmrg HideIconManager (); 19633e747e6dSmrg else if (tmp_win->protocols & DoesWmDeleteWindow) 19643e747e6dSmrg SendDeleteWindowMessage (tmp_win, LastTimestamp()); 19653e747e6dSmrg else 19663e747e6dSmrg Bell(XkbBI_MinorError,0,tmp_win->w); 19673e747e6dSmrg break; 19683e747e6dSmrg 19693e747e6dSmrg case F_SAVEYOURSELF: 19703e747e6dSmrg if (DeferExecution (context, func, Scr->SelectCursor)) 19713e747e6dSmrg return TRUE; 19723e747e6dSmrg 19733e747e6dSmrg if (tmp_win->protocols & DoesWmSaveYourself) 19743e747e6dSmrg SendSaveYourselfMessage (tmp_win, LastTimestamp()); 19753e747e6dSmrg else 19763e747e6dSmrg Bell(XkbBI_MinorError,0,tmp_win->w); 19773e747e6dSmrg break; 19783e747e6dSmrg 19793e747e6dSmrg case F_CIRCLEUP: 19803e747e6dSmrg XCirculateSubwindowsUp(dpy, Scr->Root); 19813e747e6dSmrg break; 19823e747e6dSmrg 19833e747e6dSmrg case F_CIRCLEDOWN: 19843e747e6dSmrg XCirculateSubwindowsDown(dpy, Scr->Root); 19853e747e6dSmrg break; 19863e747e6dSmrg 19873e747e6dSmrg case F_EXEC: 19883e747e6dSmrg PopDownMenu(); 19893e747e6dSmrg if (!Scr->NoGrabServer) { 19903e747e6dSmrg XUngrabServer (dpy); 19913e747e6dSmrg XSync (dpy, 0); 19923e747e6dSmrg } 19933e747e6dSmrg Execute(action); 19943e747e6dSmrg break; 19953e747e6dSmrg 19963e747e6dSmrg case F_UNFOCUS: 19973e747e6dSmrg FocusOnRoot(); 19983e747e6dSmrg break; 19993e747e6dSmrg 20003e747e6dSmrg case F_CUT: 20013e747e6dSmrg strcpy(tmp, action); 20023e747e6dSmrg strcat(tmp, "\n"); 20033e747e6dSmrg XStoreBytes(dpy, tmp, strlen(tmp)); 20043e747e6dSmrg break; 20053e747e6dSmrg 20063e747e6dSmrg case F_CUTFILE: 20073e747e6dSmrg ptr = XFetchBytes(dpy, &count); 20083e747e6dSmrg if (ptr) { 20093e747e6dSmrg if (sscanf (ptr, "%s", tmp) == 1) { 20103e747e6dSmrg XFree (ptr); 20113e747e6dSmrg ptr = ExpandFilename(tmp); 20123e747e6dSmrg if (ptr) { 20133e747e6dSmrg fd = open (ptr, O_RDONLY); 20143e747e6dSmrg if (fd >= 0) { 20153e747e6dSmrg count = read (fd, buff, MAX_FILE_SIZE - 1); 20163e747e6dSmrg if (count > 0) XStoreBytes (dpy, buff, count); 20173e747e6dSmrg close(fd); 20183e747e6dSmrg } else { 2019ffd25bcaSmrg fprintf (stderr, 2020ffd25bcaSmrg "%s: unable to open cut file \"%s\"\n", 20213e747e6dSmrg ProgramName, tmp); 20223e747e6dSmrg } 20233e747e6dSmrg if (ptr != tmp) free (ptr); 2024ffd25bcaSmrg } 20253e747e6dSmrg } else { 20263e747e6dSmrg XFree(ptr); 20273e747e6dSmrg } 20283e747e6dSmrg } else { 20293e747e6dSmrg fprintf(stderr, "%s: cut buffer is empty\n", ProgramName); 20303e747e6dSmrg } 20313e747e6dSmrg break; 20323e747e6dSmrg 20333e747e6dSmrg case F_WARPTOSCREEN: 20343e747e6dSmrg { 20353e747e6dSmrg if (strcmp (action, WARPSCREEN_NEXT) == 0) { 20363e747e6dSmrg WarpToScreen (Scr->screen + 1, 1); 20373e747e6dSmrg } else if (strcmp (action, WARPSCREEN_PREV) == 0) { 20383e747e6dSmrg WarpToScreen (Scr->screen - 1, -1); 20393e747e6dSmrg } else if (strcmp (action, WARPSCREEN_BACK) == 0) { 20403e747e6dSmrg WarpToScreen (PreviousScreen, 0); 20413e747e6dSmrg } else { 20423e747e6dSmrg WarpToScreen (atoi (action), 0); 20433e747e6dSmrg } 20443e747e6dSmrg } 20453e747e6dSmrg break; 20463e747e6dSmrg 20473e747e6dSmrg case F_COLORMAP: 20483e747e6dSmrg { 20493e747e6dSmrg if (strcmp (action, COLORMAP_NEXT) == 0) { 20503e747e6dSmrg BumpWindowColormap (tmp_win, 1); 20513e747e6dSmrg } else if (strcmp (action, COLORMAP_PREV) == 0) { 20523e747e6dSmrg BumpWindowColormap (tmp_win, -1); 20533e747e6dSmrg } else { 20543e747e6dSmrg BumpWindowColormap (tmp_win, 0); 20553e747e6dSmrg } 20563e747e6dSmrg } 20573e747e6dSmrg break; 20583e747e6dSmrg 20593e747e6dSmrg case F_WARPPREV: 20603e747e6dSmrg case F_WARPNEXT: 20613e747e6dSmrg { 20623e747e6dSmrg register TwmWindow *t; 20633e747e6dSmrg static TwmWindow *savedwarp = NULL; 20643e747e6dSmrg TwmWindow *of, *l, *n; 20653e747e6dSmrg int c=0; 20663e747e6dSmrg 20673e747e6dSmrg#define wseq(w) (func == F_WARPNEXT ? (w)->next : (w)->prev) 20683e747e6dSmrg#define nwin(w) ((w) && (n=wseq(w)) != NULL && n != &Scr->TwmRoot ? n : l) 20693e747e6dSmrg#define bwin(w) (!(w)||(w)->iconmgr||(w)==of||!(Scr->WarpUnmapped||(w)->mapped)) 20703e747e6dSmrg 20713e747e6dSmrg of=(Scr->Focus ? Scr->Focus : &Scr->TwmRoot); 20723e747e6dSmrg 20733e747e6dSmrg for(t=Scr->TwmRoot.next; t; t=t->next) if(!bwin(t)) break; 20743e747e6dSmrg if(!t) break; /* no windows we can use */ 20753e747e6dSmrg 20763e747e6dSmrg if(func == F_WARPPREV) for(l=of; l->next; l=l->next) ; 20773e747e6dSmrg else l = Scr->TwmRoot.next; 20783e747e6dSmrg 20793e747e6dSmrg for(t=of; bwin(t) && c < 2; t=nwin(t)) if(t == of) c++; 20803e747e6dSmrg 20813e747e6dSmrg if(bwin(t) || c >= 2) Bell(XkbBI_MinorError,0,None); 20823e747e6dSmrg else { 20833e747e6dSmrg if(of && of == savedwarp) { 20843e747e6dSmrg Iconify(of, 0, 0); 20853e747e6dSmrg savedwarp = NULL; 20863e747e6dSmrg } 20873e747e6dSmrg if(!t->mapped) savedwarp = t; else savedwarp = NULL; 20883e747e6dSmrg WarpThere(t); 20893e747e6dSmrg } 20903e747e6dSmrg break; 20913e747e6dSmrg } 20923e747e6dSmrg 20933e747e6dSmrg case F_WARPTO: 20943e747e6dSmrg { 20953e747e6dSmrg register TwmWindow *t; 20963e747e6dSmrg int len; 20973e747e6dSmrg 20983e747e6dSmrg len = strlen(action); 20993e747e6dSmrg 21003e747e6dSmrg for (t = Scr->TwmRoot.next; t != NULL; t = t->next) { 2101ffd25bcaSmrg if (!strncmp(action, t->name, len)) 21023e747e6dSmrg if (WarpThere(t)) break; 21033e747e6dSmrg } 21043e747e6dSmrg if (!t) { 21053e747e6dSmrg for (t = Scr->TwmRoot.next; t != NULL; t = t->next) { 2106ffd25bcaSmrg if (!strncmp(action, t->class.res_name, len)) 21073e747e6dSmrg if (WarpThere(t)) break; 21083e747e6dSmrg } 21093e747e6dSmrg if (!t) { 21103e747e6dSmrg for (t = Scr->TwmRoot.next; t != NULL; t = t->next) { 2111ffd25bcaSmrg if (!strncmp(action, t->class.res_class, len)) 21123e747e6dSmrg if (WarpThere(t)) break; 21133e747e6dSmrg } 21143e747e6dSmrg } 21153e747e6dSmrg } 21163e747e6dSmrg 2117ffd25bcaSmrg if (!t) 21183e747e6dSmrg Bell(XkbBI_MinorError,0,None); 21193e747e6dSmrg } 21203e747e6dSmrg break; 21213e747e6dSmrg 21223e747e6dSmrg case F_WARPTOICONMGR: 21233e747e6dSmrg { 21243e747e6dSmrg TwmWindow *t; 21253e747e6dSmrg int len; 21263e747e6dSmrg Window raisewin = None, iconwin = None; 21273e747e6dSmrg 21283e747e6dSmrg len = strlen(action); 21293e747e6dSmrg if (len == 0) { 21303e747e6dSmrg if (tmp_win && tmp_win->list) { 21313e747e6dSmrg raisewin = tmp_win->list->iconmgr->twm_win->frame; 21323e747e6dSmrg iconwin = tmp_win->list->icon; 21333e747e6dSmrg } else if (Scr->iconmgr.active) { 21343e747e6dSmrg raisewin = Scr->iconmgr.twm_win->frame; 21353e747e6dSmrg iconwin = Scr->iconmgr.active->w; 21363e747e6dSmrg } 21373e747e6dSmrg } else { 21383e747e6dSmrg for (t = Scr->TwmRoot.next; t != NULL; t = t->next) { 21393e747e6dSmrg if (strncmp (action, t->icon_name, len) == 0) { 21403e747e6dSmrg if (t->list && t->list->iconmgr->twm_win->mapped) { 21413e747e6dSmrg raisewin = t->list->iconmgr->twm_win->frame; 21423e747e6dSmrg iconwin = t->list->icon; 21433e747e6dSmrg break; 21443e747e6dSmrg } 21453e747e6dSmrg } 21463e747e6dSmrg } 21473e747e6dSmrg } 21483e747e6dSmrg 21493e747e6dSmrg if (raisewin) { 21503e747e6dSmrg XRaiseWindow (dpy, raisewin); 21513e747e6dSmrg XWarpPointer (dpy, None, iconwin, 0,0,0,0, 5, 5); 21523e747e6dSmrg } else { 21533e747e6dSmrg Bell(XkbBI_MinorError,0,None); 21543e747e6dSmrg } 21553e747e6dSmrg } 21563e747e6dSmrg break; 2157ffd25bcaSmrg 21583e747e6dSmrg case F_WARPRING: 21593e747e6dSmrg switch (action[0]) { 21603e747e6dSmrg case 'n': 21613e747e6dSmrg WarpAlongRing (&eventp->xbutton, True); 21623e747e6dSmrg break; 21633e747e6dSmrg case 'p': 21643e747e6dSmrg WarpAlongRing (&eventp->xbutton, False); 21653e747e6dSmrg break; 21663e747e6dSmrg default: 21673e747e6dSmrg Bell(XkbBI_MinorError,0,None); 21683e747e6dSmrg break; 21693e747e6dSmrg } 21703e747e6dSmrg break; 21713e747e6dSmrg 21723e747e6dSmrg case F_FILE: 21733e747e6dSmrg ptr = ExpandFilename(action); 21743e747e6dSmrg fd = open(ptr, O_RDONLY); 21753e747e6dSmrg if (fd >= 0) 21763e747e6dSmrg { 21773e747e6dSmrg count = read(fd, buff, MAX_FILE_SIZE - 1); 21783e747e6dSmrg if (count > 0) 21793e747e6dSmrg XStoreBytes(dpy, buff, count); 21803e747e6dSmrg 21813e747e6dSmrg close(fd); 21823e747e6dSmrg } 21833e747e6dSmrg else 21843e747e6dSmrg { 2185ffd25bcaSmrg fprintf (stderr, "%s: unable to open file \"%s\"\n", 21863e747e6dSmrg ProgramName, ptr); 21873e747e6dSmrg } 21883e747e6dSmrg if (ptr != action) free(ptr); 21893e747e6dSmrg break; 21903e747e6dSmrg 21913e747e6dSmrg case F_REFRESH: 21923e747e6dSmrg { 21933e747e6dSmrg XSetWindowAttributes attributes; 21943e747e6dSmrg unsigned long valuemask; 21953e747e6dSmrg 21963e747e6dSmrg valuemask = (CWBackPixel | CWBackingStore | CWSaveUnder); 21973e747e6dSmrg attributes.background_pixel = Scr->Black; 21983e747e6dSmrg attributes.backing_store = NotUseful; 21993e747e6dSmrg attributes.save_under = False; 22003e747e6dSmrg w = XCreateWindow (dpy, Scr->Root, 0, 0, 22013e747e6dSmrg (unsigned int) Scr->MyDisplayWidth, 22023e747e6dSmrg (unsigned int) Scr->MyDisplayHeight, 22033e747e6dSmrg (unsigned int) 0, 22043e747e6dSmrg CopyFromParent, (unsigned int) CopyFromParent, 22053e747e6dSmrg (Visual *) CopyFromParent, valuemask, 22063e747e6dSmrg &attributes); 22073e747e6dSmrg XMapWindow (dpy, w); 22083e747e6dSmrg XDestroyWindow (dpy, w); 22093e747e6dSmrg XFlush (dpy); 22103e747e6dSmrg } 22113e747e6dSmrg break; 22123e747e6dSmrg 22133e747e6dSmrg case F_WINREFRESH: 22143e747e6dSmrg if (DeferExecution(context, func, Scr->SelectCursor)) 22153e747e6dSmrg return TRUE; 22163e747e6dSmrg 22173e747e6dSmrg if (context == C_ICON && tmp_win->icon_w) 22183e747e6dSmrg w = XCreateSimpleWindow(dpy, tmp_win->icon_w, 22193e747e6dSmrg 0, 0, 9999, 9999, 0, Scr->Black, Scr->Black); 22203e747e6dSmrg else 22213e747e6dSmrg w = XCreateSimpleWindow(dpy, tmp_win->frame, 22223e747e6dSmrg 0, 0, 9999, 9999, 0, Scr->Black, Scr->Black); 22233e747e6dSmrg 22243e747e6dSmrg XMapWindow(dpy, w); 22253e747e6dSmrg XDestroyWindow(dpy, w); 22263e747e6dSmrg XFlush(dpy); 22273e747e6dSmrg break; 22283e747e6dSmrg 22293e747e6dSmrg case F_QUIT: 22303e747e6dSmrg Done(NULL, NULL); 22313e747e6dSmrg break; 22323e747e6dSmrg 22333e747e6dSmrg case F_PRIORITY: 22343e747e6dSmrg if (HasSync) 22353e747e6dSmrg { 22363e747e6dSmrg if (DeferExecution (context, func, Scr->SelectCursor)) 22373e747e6dSmrg return TRUE; 22383e747e6dSmrg (void)XSyncSetPriority(dpy, tmp_win->w, atoi(action)); 22393e747e6dSmrg } 22403e747e6dSmrg break; 22413e747e6dSmrg case F_STARTWM: 22423e747e6dSmrg execlp("/bin/sh", "sh", "-c", action, (void *)NULL); 22433e747e6dSmrg fprintf (stderr, "%s: unable to start: %s\n", ProgramName, *Argv); 22443e747e6dSmrg break; 22453e747e6dSmrg 22463e747e6dSmrg } 22473e747e6dSmrg 22483e747e6dSmrg if (ButtonPressed == -1) XUngrabPointer(dpy, CurrentTime); 22493e747e6dSmrg return do_next_action; 22503e747e6dSmrg} 22513e747e6dSmrg 22523e747e6dSmrg 22533e747e6dSmrg 22543e747e6dSmrg/** 2255ffd25bcaSmrg * defer the execution of a function to the next button press if the context 22563e747e6dSmrg * is C_ROOT 22573e747e6dSmrg * 22583e747e6dSmrg * \param context the context in which the mouse button was pressed 22593e747e6dSmrg * \param func the function to defer 22603e747e6dSmrg * \param cursor cursor the cursor to display while waiting 22613e747e6dSmrg */ 2262c2535118Smrgstatic int 22633e747e6dSmrgDeferExecution(int context, int func, Cursor cursor) 22643e747e6dSmrg{ 22653e747e6dSmrg if (context == C_ROOT) 22663e747e6dSmrg { 22673e747e6dSmrg LastCursor = cursor; 22683e747e6dSmrg XGrabPointer(dpy, Scr->Root, True, 22693e747e6dSmrg ButtonPressMask | ButtonReleaseMask, 22703e747e6dSmrg GrabModeAsync, GrabModeAsync, 22713e747e6dSmrg Scr->Root, cursor, CurrentTime); 22723e747e6dSmrg 22733e747e6dSmrg RootFunction = func; 22743e747e6dSmrg 22753e747e6dSmrg return (TRUE); 22763e747e6dSmrg } 2277ffd25bcaSmrg 22783e747e6dSmrg return (FALSE); 22793e747e6dSmrg} 22803e747e6dSmrg 22813e747e6dSmrg 22823e747e6dSmrg 22833e747e6dSmrg/** 22843e747e6dSmrg *regrab the pointer with the LastCursor; 22853e747e6dSmrg */ 22863e747e6dSmrgvoid 2287c2535118SmrgReGrab(void) 22883e747e6dSmrg{ 22893e747e6dSmrg XGrabPointer(dpy, Scr->Root, True, 22903e747e6dSmrg ButtonPressMask | ButtonReleaseMask, 22913e747e6dSmrg GrabModeAsync, GrabModeAsync, 22923e747e6dSmrg Scr->Root, LastCursor, CurrentTime); 22933e747e6dSmrg} 22943e747e6dSmrg 22953e747e6dSmrg 22963e747e6dSmrg 22973e747e6dSmrg/** 2298ffd25bcaSmrg * checks each function in the list to see if it is one that needs 22993e747e6dSmrg * to be deferred. 23003e747e6dSmrg * 23013e747e6dSmrg * \param root the menu root to check 23023e747e6dSmrg */ 2303c2535118Smrgstatic Bool 23043e747e6dSmrgNeedToDefer(MenuRoot *root) 23053e747e6dSmrg{ 23063e747e6dSmrg MenuItem *mitem; 23073e747e6dSmrg 23083e747e6dSmrg for (mitem = root->first; mitem != NULL; mitem = mitem->next) 23093e747e6dSmrg { 23103e747e6dSmrg switch (mitem->func) 23113e747e6dSmrg { 23123e747e6dSmrg case F_IDENTIFY: 23133e747e6dSmrg case F_RESIZE: 23143e747e6dSmrg case F_MOVE: 23153e747e6dSmrg case F_FORCEMOVE: 23163e747e6dSmrg case F_DEICONIFY: 23173e747e6dSmrg case F_ICONIFY: 23183e747e6dSmrg case F_RAISELOWER: 23193e747e6dSmrg case F_RAISE: 23203e747e6dSmrg case F_LOWER: 23213e747e6dSmrg case F_FOCUS: 23223e747e6dSmrg case F_DESTROY: 23233e747e6dSmrg case F_WINREFRESH: 23243e747e6dSmrg case F_ZOOM: 23253e747e6dSmrg case F_FULLZOOM: 23263e747e6dSmrg case F_HORIZOOM: 23273e747e6dSmrg case F_RIGHTZOOM: 23283e747e6dSmrg case F_LEFTZOOM: 23293e747e6dSmrg case F_TOPZOOM: 23303e747e6dSmrg case F_BOTTOMZOOM: 23313e747e6dSmrg case F_AUTORAISE: 23323e747e6dSmrg return TRUE; 23333e747e6dSmrg } 23343e747e6dSmrg } 23353e747e6dSmrg return FALSE; 23363e747e6dSmrg} 23373e747e6dSmrg 23383e747e6dSmrg 23393e747e6dSmrg 23403e747e6dSmrg#if defined(sun) && defined(SVR4) 23413e747e6dSmrg#include <sys/wait.h> 23423e747e6dSmrg 23433e747e6dSmrg/** 23443e747e6dSmrg * execute the string by /bin/sh 23453e747e6dSmrg * \param s the string containing the command 23463e747e6dSmrg */ 2347ffd25bcaSmrgstatic int 2348c2535118SmrgSystem (const char *s) 23493e747e6dSmrg{ 23503e747e6dSmrg int pid, status; 23513e747e6dSmrg if ((pid = fork ()) == 0) { 23523e747e6dSmrg (void) setpgrp(); 2353c2535118Smrg execl ("/bin/sh", "sh", "-c", s, NULL); 23543e747e6dSmrg } else 23553e747e6dSmrg waitpid (pid, &status, 0); 23563e747e6dSmrg return status; 23573e747e6dSmrg} 23583e747e6dSmrg#define system(s) System(s) 23593e747e6dSmrg 23603e747e6dSmrg#endif 23613e747e6dSmrg 2362c2535118Smrgstatic void 2363c2535118SmrgExecute(const char *s) 23643e747e6dSmrg{ 23653e747e6dSmrg /* FIXME: is all this stuff needed? There could be security problems here. */ 23663e747e6dSmrg static char buf[256]; 23673e747e6dSmrg char *ds = DisplayString (dpy); 23683e747e6dSmrg char *colon, *dot1; 23693e747e6dSmrg char oldDisplay[256]; 23703e747e6dSmrg char *doisplay; 23713e747e6dSmrg int restorevar = 0; 23723e747e6dSmrg 23733e747e6dSmrg oldDisplay[0] = '\0'; 23743e747e6dSmrg doisplay=getenv("DISPLAY"); 23753e747e6dSmrg if (doisplay) 23763e747e6dSmrg strcpy (oldDisplay, doisplay); 23773e747e6dSmrg 23783e747e6dSmrg /* 23793e747e6dSmrg * Build a display string using the current screen number, so that 23803e747e6dSmrg * X programs which get fired up from a menu come up on the screen 23813e747e6dSmrg * that they were invoked from, unless specifically overridden on 23823e747e6dSmrg * their command line. 23833e747e6dSmrg */ 23843e747e6dSmrg colon = strrchr (ds, ':'); 23853e747e6dSmrg if (colon) { /* if host[:]:dpy */ 23863e747e6dSmrg strcpy (buf, "DISPLAY="); 23873e747e6dSmrg strcat (buf, ds); 23883e747e6dSmrg colon = buf + 8 + (colon - ds); /* use version in buf */ 23893e747e6dSmrg dot1 = strchr (colon, '.'); /* first period after colon */ 23903e747e6dSmrg if (!dot1) dot1 = colon + strlen (colon); /* if not there, append */ 23913e747e6dSmrg (void) sprintf (dot1, ".%d", Scr->screen); 23923e747e6dSmrg putenv (buf); 23933e747e6dSmrg restorevar = 1; 23943e747e6dSmrg } 23953e747e6dSmrg 23963e747e6dSmrg (void) system (s); 23973e747e6dSmrg 23983e747e6dSmrg if (restorevar) { /* why bother? */ 2399ffd25bcaSmrg (void) snprintf (buf, sizeof(buf), "DISPLAY=%s", oldDisplay); 24003e747e6dSmrg putenv (buf); 24013e747e6dSmrg } 24023e747e6dSmrg} 24033e747e6dSmrg 24043e747e6dSmrg 24053e747e6dSmrg 24063e747e6dSmrg/** 24073e747e6dSmrg * put input focus on the root window. 24083e747e6dSmrg */ 24093e747e6dSmrgvoid 2410c2535118SmrgFocusOnRoot(void) 24113e747e6dSmrg{ 24123e747e6dSmrg SetFocus ((TwmWindow *) NULL, LastTimestamp()); 24133e747e6dSmrg if (Scr->Focus != NULL) 24143e747e6dSmrg { 24153e747e6dSmrg SetBorder (Scr->Focus, False); 24163e747e6dSmrg if (Scr->Focus->hilite_w) XUnmapWindow (dpy, Scr->Focus->hilite_w); 24173e747e6dSmrg } 24183e747e6dSmrg InstallWindowColormaps(0, &Scr->TwmRoot); 24193e747e6dSmrg Scr->Focus = NULL; 24203e747e6dSmrg Scr->FocusRoot = TRUE; 24213e747e6dSmrg} 24223e747e6dSmrg 24233e747e6dSmrgvoid 24243e747e6dSmrgDeIconify(TwmWindow *tmp_win) 24253e747e6dSmrg{ 24263e747e6dSmrg TwmWindow *t; 24273e747e6dSmrg 24283e747e6dSmrg /* de-iconify the main window */ 24293e747e6dSmrg if (tmp_win->icon) 24303e747e6dSmrg { 24313e747e6dSmrg if (tmp_win->icon_on) 24323e747e6dSmrg Zoom(tmp_win->icon_w, tmp_win->frame); 24333e747e6dSmrg else if (tmp_win->group != (Window) 0) 24343e747e6dSmrg { 24353e747e6dSmrg for (t = Scr->TwmRoot.next; t != NULL; t = t->next) 24363e747e6dSmrg { 24373e747e6dSmrg if (tmp_win->group == t->w && t->icon_on) 24383e747e6dSmrg { 24393e747e6dSmrg Zoom(t->icon_w, tmp_win->frame); 24403e747e6dSmrg break; 24413e747e6dSmrg } 24423e747e6dSmrg } 24433e747e6dSmrg } 24443e747e6dSmrg } 24453e747e6dSmrg 24463e747e6dSmrg XMapWindow(dpy, tmp_win->w); 24473e747e6dSmrg tmp_win->mapped = TRUE; 24483e747e6dSmrg if (Scr->NoRaiseDeicon) 24493e747e6dSmrg XMapWindow(dpy, tmp_win->frame); 24503e747e6dSmrg else 24513e747e6dSmrg XMapRaised(dpy, tmp_win->frame); 24523e747e6dSmrg SetMapStateProp(tmp_win, NormalState); 24533e747e6dSmrg 24543e747e6dSmrg if (tmp_win->icon_w) { 24553e747e6dSmrg XUnmapWindow(dpy, tmp_win->icon_w); 24563e747e6dSmrg IconDown (tmp_win); 24573e747e6dSmrg } 24583e747e6dSmrg if (tmp_win->list) 24593e747e6dSmrg XUnmapWindow(dpy, tmp_win->list->icon); 24603e747e6dSmrg if ((Scr->WarpCursor || 24613e747e6dSmrg LookInList(Scr->WarpCursorL, tmp_win->full_name, &tmp_win->class)) && 24623e747e6dSmrg tmp_win->icon) 24633e747e6dSmrg WarpToWindow (tmp_win); 24643e747e6dSmrg tmp_win->icon = FALSE; 24653e747e6dSmrg tmp_win->icon_on = FALSE; 24663e747e6dSmrg 24673e747e6dSmrg 24683e747e6dSmrg /* now de-iconify transients */ 24693e747e6dSmrg for (t = Scr->TwmRoot.next; t != NULL; t = t->next) 24703e747e6dSmrg { 24713e747e6dSmrg if (t->transient && t->transientfor == tmp_win->w) 24723e747e6dSmrg { 24733e747e6dSmrg if (t->icon_on) 24743e747e6dSmrg Zoom(t->icon_w, t->frame); 24753e747e6dSmrg else 24763e747e6dSmrg Zoom(tmp_win->icon_w, t->frame); 2477ffd25bcaSmrg 24783e747e6dSmrg XMapWindow(dpy, t->w); 24793e747e6dSmrg t->mapped = TRUE; 24803e747e6dSmrg if (Scr->NoRaiseDeicon) 24813e747e6dSmrg XMapWindow(dpy, t->frame); 24823e747e6dSmrg else 24833e747e6dSmrg XMapRaised(dpy, t->frame); 24843e747e6dSmrg SetMapStateProp(t, NormalState); 2485ffd25bcaSmrg 24863e747e6dSmrg if (t->icon_w) { 24873e747e6dSmrg XUnmapWindow(dpy, t->icon_w); 24883e747e6dSmrg IconDown (t); 24893e747e6dSmrg } 24903e747e6dSmrg if (t->list) XUnmapWindow(dpy, t->list->icon); 24913e747e6dSmrg t->icon = FALSE; 24923e747e6dSmrg t->icon_on = FALSE; 24933e747e6dSmrg } 24943e747e6dSmrg } 2495ffd25bcaSmrg 24963e747e6dSmrg XSync (dpy, 0); 24973e747e6dSmrg} 24983e747e6dSmrg 24993e747e6dSmrg 25003e747e6dSmrg 25013e747e6dSmrgvoid 25023e747e6dSmrgIconify(TwmWindow *tmp_win, int def_x, int def_y) 25033e747e6dSmrg{ 25043e747e6dSmrg TwmWindow *t; 25053e747e6dSmrg int iconify; 25063e747e6dSmrg XWindowAttributes winattrs; 25073e747e6dSmrg unsigned long eventMask; 25083e747e6dSmrg 25093e747e6dSmrg iconify = ((!tmp_win->iconify_by_unmapping) || tmp_win->transient); 25103e747e6dSmrg if (iconify) 25113e747e6dSmrg { 25123e747e6dSmrg if (tmp_win->icon_w == (Window) 0) 25133e747e6dSmrg CreateIconWindow(tmp_win, def_x, def_y); 25143e747e6dSmrg else 25153e747e6dSmrg IconUp(tmp_win); 25163e747e6dSmrg XMapRaised(dpy, tmp_win->icon_w); 25173e747e6dSmrg } 25183e747e6dSmrg if (tmp_win->list) 25193e747e6dSmrg XMapWindow(dpy, tmp_win->list->icon); 25203e747e6dSmrg 25213e747e6dSmrg XGetWindowAttributes(dpy, tmp_win->w, &winattrs); 25223e747e6dSmrg eventMask = winattrs.your_event_mask; 25233e747e6dSmrg 25243e747e6dSmrg /* iconify transients first */ 25253e747e6dSmrg for (t = Scr->TwmRoot.next; t != NULL; t = t->next) 25263e747e6dSmrg { 25273e747e6dSmrg if (t->transient && t->transientfor == tmp_win->w) 25283e747e6dSmrg { 25293e747e6dSmrg if (iconify) 25303e747e6dSmrg { 25313e747e6dSmrg if (t->icon_on) 25323e747e6dSmrg Zoom(t->icon_w, tmp_win->icon_w); 25333e747e6dSmrg else 25343e747e6dSmrg Zoom(t->frame, tmp_win->icon_w); 25353e747e6dSmrg } 2536ffd25bcaSmrg 25373e747e6dSmrg /* 25383e747e6dSmrg * Prevent the receipt of an UnmapNotify, since that would 25393e747e6dSmrg * cause a transition to the Withdrawn state. 25403e747e6dSmrg */ 25413e747e6dSmrg t->mapped = FALSE; 25423e747e6dSmrg XSelectInput(dpy, t->w, eventMask & ~StructureNotifyMask); 25433e747e6dSmrg XUnmapWindow(dpy, t->w); 25443e747e6dSmrg XSelectInput(dpy, t->w, eventMask); 25453e747e6dSmrg XUnmapWindow(dpy, t->frame); 25463e747e6dSmrg if (t->icon_w) 25473e747e6dSmrg XUnmapWindow(dpy, t->icon_w); 25483e747e6dSmrg SetMapStateProp(t, IconicState); 25493e747e6dSmrg SetBorder (t, False); 25503e747e6dSmrg if (t == Scr->Focus) 25513e747e6dSmrg { 25523e747e6dSmrg SetFocus ((TwmWindow *) NULL, LastTimestamp()); 25533e747e6dSmrg Scr->Focus = NULL; 25543e747e6dSmrg Scr->FocusRoot = TRUE; 25553e747e6dSmrg } 25563e747e6dSmrg if (t->list) XMapWindow(dpy, t->list->icon); 25573e747e6dSmrg t->icon = TRUE; 25583e747e6dSmrg t->icon_on = FALSE; 25593e747e6dSmrg } 2560ffd25bcaSmrg } 2561ffd25bcaSmrg 25623e747e6dSmrg if (iconify) 25633e747e6dSmrg Zoom(tmp_win->frame, tmp_win->icon_w); 25643e747e6dSmrg 25653e747e6dSmrg /* 25663e747e6dSmrg * Prevent the receipt of an UnmapNotify, since that would 25673e747e6dSmrg * cause a transition to the Withdrawn state. 25683e747e6dSmrg */ 25693e747e6dSmrg tmp_win->mapped = FALSE; 25703e747e6dSmrg XSelectInput(dpy, tmp_win->w, eventMask & ~StructureNotifyMask); 25713e747e6dSmrg XUnmapWindow(dpy, tmp_win->w); 25723e747e6dSmrg XSelectInput(dpy, tmp_win->w, eventMask); 25733e747e6dSmrg XUnmapWindow(dpy, tmp_win->frame); 25743e747e6dSmrg SetMapStateProp(tmp_win, IconicState); 25753e747e6dSmrg 25763e747e6dSmrg SetBorder (tmp_win, False); 25773e747e6dSmrg if (tmp_win == Scr->Focus) 25783e747e6dSmrg { 25793e747e6dSmrg SetFocus ((TwmWindow *) NULL, LastTimestamp()); 25803e747e6dSmrg Scr->Focus = NULL; 25813e747e6dSmrg Scr->FocusRoot = TRUE; 25823e747e6dSmrg } 25833e747e6dSmrg tmp_win->icon = TRUE; 25843e747e6dSmrg if (iconify) 25853e747e6dSmrg tmp_win->icon_on = TRUE; 25863e747e6dSmrg else 25873e747e6dSmrg tmp_win->icon_on = FALSE; 25883e747e6dSmrg XSync (dpy, 0); 25893e747e6dSmrg} 25903e747e6dSmrg 25913e747e6dSmrg 25923e747e6dSmrg 2593ffd25bcaSmrgstatic void 25943e747e6dSmrgIdentify (TwmWindow *t) 25953e747e6dSmrg{ 25963e747e6dSmrg int i, n, twidth, width, height; 25973e747e6dSmrg int x, y; 25983e747e6dSmrg unsigned int wwidth, wheight, bw, depth; 25993e747e6dSmrg Window junk; 26003e747e6dSmrg int px, py, dummy; 26013e747e6dSmrg unsigned udummy; 26023e747e6dSmrg 26033e747e6dSmrg n = 0; 2604ffd25bcaSmrg snprintf(Info[n++], INFO_SIZE, "Twm version: %s", Version); 26053e747e6dSmrg Info[n++][0] = '\0'; 26063e747e6dSmrg 26073e747e6dSmrg if (t) { 26083e747e6dSmrg XGetGeometry (dpy, t->w, &JunkRoot, &JunkX, &JunkY, 26093e747e6dSmrg &wwidth, &wheight, &bw, &depth); 26103e747e6dSmrg (void) XTranslateCoordinates (dpy, t->w, Scr->Root, 0, 0, 26113e747e6dSmrg &x, &y, &junk); 2612ffd25bcaSmrg snprintf(Info[n++], INFO_SIZE, 2613ffd25bcaSmrg "Name = \"%s\"", t->full_name); 2614ffd25bcaSmrg snprintf(Info[n++], INFO_SIZE, 2615ffd25bcaSmrg "Class.res_name = \"%s\"", t->class.res_name); 2616ffd25bcaSmrg snprintf(Info[n++], INFO_SIZE, 2617ffd25bcaSmrg "Class.res_class = \"%s\"", t->class.res_class); 26183e747e6dSmrg Info[n++][0] = '\0'; 2619ffd25bcaSmrg snprintf(Info[n++], INFO_SIZE, 2620ffd25bcaSmrg "Geometry/root = %dx%d+%d+%d", wwidth, wheight, x, y); 2621ffd25bcaSmrg snprintf(Info[n++], INFO_SIZE, "Border width = %d", bw); 2622ffd25bcaSmrg snprintf(Info[n++], INFO_SIZE, "Depth = %d", depth); 26233e747e6dSmrg if (HasSync) 26243e747e6dSmrg { 26253e747e6dSmrg int priority; 26263e747e6dSmrg (void)XSyncGetPriority(dpy, t->w, &priority); 2627ffd25bcaSmrg snprintf(Info[n++], INFO_SIZE, "Priority = %d", priority); 26283e747e6dSmrg } 26293e747e6dSmrg } 26303e747e6dSmrg 26313e747e6dSmrg Info[n++][0] = '\0'; 2632ffd25bcaSmrg snprintf(Info[n++], INFO_SIZE, "Click to dismiss...."); 26333e747e6dSmrg 26343e747e6dSmrg /* figure out the width and height of the info window */ 26353e747e6dSmrg height = n * (Scr->DefaultFont.height+2); 26363e747e6dSmrg width = 1; 26373e747e6dSmrg for (i = 0; i < n; i++) 26383e747e6dSmrg { 2639ffd25bcaSmrg twidth = MyFont_TextWidth(&Scr->DefaultFont, Info[i], 26403e747e6dSmrg strlen(Info[i])); 26413e747e6dSmrg if (twidth > width) 26423e747e6dSmrg width = twidth; 26433e747e6dSmrg } 26443e747e6dSmrg if (InfoLines) XUnmapWindow(dpy, Scr->InfoWindow); 26453e747e6dSmrg 26463e747e6dSmrg width += 10; /* some padding */ 26473e747e6dSmrg if (XQueryPointer (dpy, Scr->Root, &JunkRoot, &JunkChild, &px, &py, 26483e747e6dSmrg &dummy, &dummy, &udummy)) { 26493e747e6dSmrg px -= (width / 2); 26503e747e6dSmrg py -= (height / 3); 2651ffd25bcaSmrg if (px + width + BW2 >= Scr->MyDisplayWidth) 26523e747e6dSmrg px = Scr->MyDisplayWidth - width - BW2; 2653ffd25bcaSmrg if (py + height + BW2 >= Scr->MyDisplayHeight) 26543e747e6dSmrg py = Scr->MyDisplayHeight - height - BW2; 26553e747e6dSmrg if (px < 0) px = 0; 26563e747e6dSmrg if (py < 0) py = 0; 26573e747e6dSmrg } else { 26583e747e6dSmrg px = py = 0; 26593e747e6dSmrg } 26603e747e6dSmrg XMoveResizeWindow(dpy, Scr->InfoWindow, px, py, width, height); 2661ffd25bcaSmrg XMapRaised(dpy, Scr->InfoWindow); 26623e747e6dSmrg InfoLines = n; 26633e747e6dSmrg} 26643e747e6dSmrg 26653e747e6dSmrg 26663e747e6dSmrgvoid 26673e747e6dSmrgSetMapStateProp(TwmWindow *tmp_win, int state) 26683e747e6dSmrg{ 26693e747e6dSmrg unsigned long data[2]; /* "suggested" by ICCCM version 1 */ 2670ffd25bcaSmrg 26713e747e6dSmrg data[0] = (unsigned long) state; 2672ffd25bcaSmrg data[1] = (unsigned long) (tmp_win->iconify_by_unmapping ? None : 26733e747e6dSmrg tmp_win->icon_w); 26743e747e6dSmrg 2675ffd25bcaSmrg XChangeProperty (dpy, tmp_win->w, _XA_WM_STATE, _XA_WM_STATE, 32, 26763e747e6dSmrg PropModeReplace, (unsigned char *) data, 2); 26773e747e6dSmrg} 26783e747e6dSmrg 26793e747e6dSmrg 26803e747e6dSmrg 2681ffd25bcaSmrgBool 26823e747e6dSmrgGetWMState (Window w, int *statep, Window *iwp) 26833e747e6dSmrg{ 26843e747e6dSmrg Atom actual_type; 26853e747e6dSmrg int actual_format; 26863e747e6dSmrg unsigned long nitems, bytesafter; 2687ffd25bcaSmrg unsigned char *prop_return = NULL; 26883e747e6dSmrg Bool retval = False; 26893e747e6dSmrg 26903e747e6dSmrg if (XGetWindowProperty (dpy, w, _XA_WM_STATE, 0L, 2L, False, _XA_WM_STATE, 26913e747e6dSmrg &actual_type, &actual_format, &nitems, &bytesafter, 2692ffd25bcaSmrg &prop_return) != Success || !prop_return) 26933e747e6dSmrg return False; 26943e747e6dSmrg 26953e747e6dSmrg if (nitems <= 2) { /* "suggested" by ICCCM version 1 */ 2696ffd25bcaSmrg unsigned long *datap = (unsigned long *) prop_return; 26973e747e6dSmrg *statep = (int) datap[0]; 26983e747e6dSmrg *iwp = (Window) datap[1]; 26993e747e6dSmrg retval = True; 27003e747e6dSmrg } 27013e747e6dSmrg 2702ffd25bcaSmrg XFree (prop_return); 27033e747e6dSmrg return retval; 27043e747e6dSmrg} 27053e747e6dSmrg 27063e747e6dSmrg 27073e747e6dSmrgvoid 27083e747e6dSmrgWarpToScreen (int n, int inc) 27093e747e6dSmrg{ 27103e747e6dSmrg Window dumwin; 27113e747e6dSmrg int x, y, dumint; 27123e747e6dSmrg unsigned int dummask; 27133e747e6dSmrg ScreenInfo *newscr = NULL; 27143e747e6dSmrg 27153e747e6dSmrg while (!newscr) { 27163e747e6dSmrg /* wrap around */ 2717ffd25bcaSmrg if (n < 0) 27183e747e6dSmrg n = NumScreens - 1; 27193e747e6dSmrg else if (n >= NumScreens) 27203e747e6dSmrg n = 0; 27213e747e6dSmrg 27223e747e6dSmrg newscr = ScreenList[n]; 27233e747e6dSmrg if (!newscr) { /* make sure screen is managed */ 27243e747e6dSmrg if (inc) { /* walk around the list */ 27253e747e6dSmrg n += inc; 27263e747e6dSmrg continue; 27273e747e6dSmrg } 2728ffd25bcaSmrg fprintf (stderr, "%s: unable to warp to unmanaged screen %d\n", 27293e747e6dSmrg ProgramName, n); 27303e747e6dSmrg Bell(XkbBI_MinorError,0,None); 27313e747e6dSmrg return; 27323e747e6dSmrg } 27333e747e6dSmrg } 27343e747e6dSmrg 27353e747e6dSmrg if (Scr->screen == n) return; /* already on that screen */ 27363e747e6dSmrg 27373e747e6dSmrg PreviousScreen = Scr->screen; 27383e747e6dSmrg XQueryPointer (dpy, Scr->Root, &dumwin, &dumwin, &x, &y, 27393e747e6dSmrg &dumint, &dumint, &dummask); 27403e747e6dSmrg 27413e747e6dSmrg XWarpPointer (dpy, None, newscr->Root, 0, 0, 0, 0, x, y); 27423e747e6dSmrg return; 27433e747e6dSmrg} 27443e747e6dSmrg 27453e747e6dSmrg 27463e747e6dSmrg 27473e747e6dSmrg 27483e747e6dSmrg/** 27493e747e6dSmrg * rotate our internal copy of WM_COLORMAP_WINDOWS 27503e747e6dSmrg */ 2751c2535118Smrgstatic void 27523e747e6dSmrgBumpWindowColormap (TwmWindow *tmp, int inc) 27533e747e6dSmrg{ 27543e747e6dSmrg int i, j, previously_installed; 27553e747e6dSmrg ColormapWindow **cwins; 27563e747e6dSmrg 27573e747e6dSmrg if (!tmp) return; 27583e747e6dSmrg 27593e747e6dSmrg if (inc && tmp->cmaps.number_cwins > 0) { 2760c2535118Smrg cwins = malloc(sizeof(ColormapWindow *) * tmp->cmaps.number_cwins); 2761ffd25bcaSmrg if (cwins) { 27623e747e6dSmrg if ((previously_installed = 27633e747e6dSmrg /* SUPPRESS 560 */(Scr->cmapInfo.cmaps == &tmp->cmaps && 27643e747e6dSmrg tmp->cmaps.number_cwins))) { 27653e747e6dSmrg for (i = tmp->cmaps.number_cwins; i-- > 0; ) 27663e747e6dSmrg tmp->cmaps.cwins[i]->colormap->state = 0; 27673e747e6dSmrg } 27683e747e6dSmrg 27693e747e6dSmrg for (i = 0; i < tmp->cmaps.number_cwins; i++) { 27703e747e6dSmrg j = i - inc; 27713e747e6dSmrg if (j >= tmp->cmaps.number_cwins) 27723e747e6dSmrg j -= tmp->cmaps.number_cwins; 27733e747e6dSmrg else if (j < 0) 27743e747e6dSmrg j += tmp->cmaps.number_cwins; 27753e747e6dSmrg cwins[j] = tmp->cmaps.cwins[i]; 27763e747e6dSmrg } 27773e747e6dSmrg 2778c2535118Smrg free(tmp->cmaps.cwins); 27793e747e6dSmrg 27803e747e6dSmrg tmp->cmaps.cwins = cwins; 27813e747e6dSmrg 27823e747e6dSmrg if (tmp->cmaps.number_cwins > 1) 2783ffd25bcaSmrg bzero (tmp->cmaps.scoreboard, 27843e747e6dSmrg ColormapsScoreboardLength(&tmp->cmaps)); 27853e747e6dSmrg 27863e747e6dSmrg if (previously_installed) 27873e747e6dSmrg InstallWindowColormaps(PropertyNotify, (TwmWindow *) NULL); 27883e747e6dSmrg } 27893e747e6dSmrg } else 27903e747e6dSmrg FetchWmColormapWindows (tmp); 27913e747e6dSmrg} 27923e747e6dSmrg 27933e747e6dSmrg 2794c2535118Smrgstatic void 2795c2535118SmrgHideIconManager (void) 27963e747e6dSmrg{ 27973e747e6dSmrg SetMapStateProp (Scr->iconmgr.twm_win, WithdrawnState); 27983e747e6dSmrg XUnmapWindow(dpy, Scr->iconmgr.twm_win->frame); 27993e747e6dSmrg if (Scr->iconmgr.twm_win->icon_w) 28003e747e6dSmrg XUnmapWindow (dpy, Scr->iconmgr.twm_win->icon_w); 28013e747e6dSmrg Scr->iconmgr.twm_win->mapped = FALSE; 28023e747e6dSmrg Scr->iconmgr.twm_win->icon = TRUE; 28033e747e6dSmrg} 28043e747e6dSmrg 28053e747e6dSmrg 28063e747e6dSmrg 28073e747e6dSmrgvoid 28083e747e6dSmrgSetBorder (TwmWindow *tmp, Bool onoroff) 28093e747e6dSmrg{ 28103e747e6dSmrg if (tmp->highlight) { 28113e747e6dSmrg if (onoroff) { 28123e747e6dSmrg XSetWindowBorder (dpy, tmp->frame, tmp->border); 2813ffd25bcaSmrg if (tmp->title_w) 28143e747e6dSmrg XSetWindowBorder (dpy, tmp->title_w, tmp->border); 28153e747e6dSmrg } else { 28163e747e6dSmrg XSetWindowBorderPixmap (dpy, tmp->frame, tmp->gray); 2817ffd25bcaSmrg if (tmp->title_w) 28183e747e6dSmrg XSetWindowBorderPixmap (dpy, tmp->title_w, tmp->gray); 28193e747e6dSmrg } 28203e747e6dSmrg } 28213e747e6dSmrg} 28223e747e6dSmrg 28233e747e6dSmrg 2824c2535118Smrgstatic void 28253e747e6dSmrgDestroyMenu (MenuRoot *menu) 28263e747e6dSmrg{ 28273e747e6dSmrg MenuItem *item; 28283e747e6dSmrg 28293e747e6dSmrg if (menu->w) { 28303e747e6dSmrg XDeleteContext (dpy, menu->w, MenuContext); 28313e747e6dSmrg XDeleteContext (dpy, menu->w, ScreenContext); 28323e747e6dSmrg if (Scr->Shadow) XDestroyWindow (dpy, menu->shadow); 28333e747e6dSmrg XDestroyWindow(dpy, menu->w); 28343e747e6dSmrg } 28353e747e6dSmrg 28363e747e6dSmrg for (item = menu->first; item; ) { 28373e747e6dSmrg MenuItem *tmp = item; 28383e747e6dSmrg item = item->next; 2839c2535118Smrg free (tmp); 28403e747e6dSmrg } 28413e747e6dSmrg} 28423e747e6dSmrg 28433e747e6dSmrg 28443e747e6dSmrg 28453e747e6dSmrg/* 28463e747e6dSmrg * warping routines 28473e747e6dSmrg */ 28483e747e6dSmrg 2849c2535118Smrgstatic void 28503e747e6dSmrgWarpAlongRing (XButtonEvent *ev, Bool forward) 28513e747e6dSmrg{ 28523e747e6dSmrg TwmWindow *r, *head; 28533e747e6dSmrg 28543e747e6dSmrg if (Scr->RingLeader) 28553e747e6dSmrg head = Scr->RingLeader; 2856ffd25bcaSmrg else if (!(head = Scr->Ring)) 28573e747e6dSmrg return; 28583e747e6dSmrg 28593e747e6dSmrg if (forward) { 28603e747e6dSmrg for (r = head->ring.next; r != head; r = r->ring.next) { 28613e747e6dSmrg if (!r || r->mapped) break; 28623e747e6dSmrg } 28633e747e6dSmrg } else { 28643e747e6dSmrg for (r = head->ring.prev; r != head; r = r->ring.prev) { 28653e747e6dSmrg if (!r || r->mapped) break; 28663e747e6dSmrg } 28673e747e6dSmrg } 28683e747e6dSmrg 28693e747e6dSmrg if (r && r != head) { 28703e747e6dSmrg TwmWindow *p = Scr->RingLeader, *t; 2871ffd25bcaSmrg XPointer context_data; 28723e747e6dSmrg 28733e747e6dSmrg Scr->RingLeader = r; 28743e747e6dSmrg WarpToWindow (r); 28753e747e6dSmrg 2876ffd25bcaSmrg if (XFindContext (dpy, ev->window, TwmContext, &context_data) == 0) 2877ffd25bcaSmrg t = (TwmWindow *) context_data; 2878ffd25bcaSmrg else 2879ffd25bcaSmrg t = NULL; 2880ffd25bcaSmrg 2881ffd25bcaSmrg if (p && p->mapped && p == t) { 28823e747e6dSmrg p->ring.cursor_valid = True; 28833e747e6dSmrg p->ring.curs_x = ev->x_root - t->frame_x; 28843e747e6dSmrg p->ring.curs_y = ev->y_root - t->frame_y; 2885ffd25bcaSmrg if (p->ring.curs_x < -p->frame_bw || 28863e747e6dSmrg p->ring.curs_x >= p->frame_width + p->frame_bw || 2887ffd25bcaSmrg p->ring.curs_y < -p->frame_bw || 28883e747e6dSmrg p->ring.curs_y >= p->frame_height + p->frame_bw) { 28893e747e6dSmrg /* somehow out of window */ 28903e747e6dSmrg p->ring.curs_x = p->frame_width / 2; 28913e747e6dSmrg p->ring.curs_y = p->frame_height / 2; 28923e747e6dSmrg } 28933e747e6dSmrg } 28943e747e6dSmrg } 28953e747e6dSmrg} 28963e747e6dSmrg 28973e747e6dSmrg 28983e747e6dSmrg 2899c2535118Smrgstatic void 29003e747e6dSmrgWarpToWindow (TwmWindow *t) 29013e747e6dSmrg{ 29023e747e6dSmrg int x, y; 29033e747e6dSmrg 29043e747e6dSmrg if (t->auto_raise || !Scr->NoRaiseWarp) AutoRaiseWindow (t); 29053e747e6dSmrg if (t->ring.cursor_valid) { 29063e747e6dSmrg x = t->ring.curs_x; 29073e747e6dSmrg y = t->ring.curs_y; 29083e747e6dSmrg } else { 29093e747e6dSmrg x = t->frame_width / 2; 29103e747e6dSmrg y = t->frame_height / 2; 29113e747e6dSmrg } 29123e747e6dSmrg XWarpPointer (dpy, None, t->frame, 0, 0, 0, 0, x, y); 29133e747e6dSmrg} 29143e747e6dSmrg 29153e747e6dSmrg 29163e747e6dSmrg 29173e747e6dSmrg 29183e747e6dSmrg/* 29193e747e6dSmrg * ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all 29203e747e6dSmrg * client messages will have the following form: 29213e747e6dSmrg * 29223e747e6dSmrg * event type ClientMessage 29233e747e6dSmrg * message type _XA_WM_PROTOCOLS 29243e747e6dSmrg * window tmp->w 29253e747e6dSmrg * format 32 29263e747e6dSmrg * data[0] message atom 29273e747e6dSmrg * data[1] time stamp 29283e747e6dSmrg */ 2929ffd25bcaSmrgstatic void 29303e747e6dSmrgsend_clientmessage (Window w, Atom a, Time timestamp) 29313e747e6dSmrg{ 29323e747e6dSmrg XClientMessageEvent ev; 29333e747e6dSmrg 29343e747e6dSmrg ev.type = ClientMessage; 29353e747e6dSmrg ev.window = w; 29363e747e6dSmrg ev.message_type = _XA_WM_PROTOCOLS; 29373e747e6dSmrg ev.format = 32; 29383e747e6dSmrg ev.data.l[0] = a; 29393e747e6dSmrg ev.data.l[1] = timestamp; 29403e747e6dSmrg XSendEvent (dpy, w, False, 0L, (XEvent *) &ev); 29413e747e6dSmrg} 29423e747e6dSmrg 29433e747e6dSmrgvoid 29443e747e6dSmrgSendDeleteWindowMessage (TwmWindow *tmp, Time timestamp) 29453e747e6dSmrg{ 29463e747e6dSmrg send_clientmessage (tmp->w, _XA_WM_DELETE_WINDOW, timestamp); 29473e747e6dSmrg} 29483e747e6dSmrg 29493e747e6dSmrgvoid 29503e747e6dSmrgSendSaveYourselfMessage (TwmWindow *tmp, Time timestamp) 29513e747e6dSmrg{ 29523e747e6dSmrg send_clientmessage (tmp->w, _XA_WM_SAVE_YOURSELF, timestamp); 29533e747e6dSmrg} 29543e747e6dSmrg 29553e747e6dSmrgvoid 29563e747e6dSmrgSendTakeFocusMessage (TwmWindow *tmp, Time timestamp) 29573e747e6dSmrg{ 29583e747e6dSmrg send_clientmessage (tmp->w, _XA_WM_TAKE_FOCUS, timestamp); 29593e747e6dSmrg} 2960