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