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