/*****************************************************************************/ /** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ /** Salt Lake City, Utah **/ /** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ /** Cambridge, Massachusetts **/ /** **/ /** All Rights Reserved **/ /** **/ /** Permission to use, copy, modify, and distribute this software and **/ /** its documentation for any purpose and without fee is hereby **/ /** granted, provided that the above copyright notice appear in all **/ /** copies and that both that copyright notice and this permis- **/ /** sion notice appear in supporting documentation, and that the **/ /** names of Evans & Sutherland and M.I.T. not be used in advertising **/ /** in publicity pertaining to distribution of the software without **/ /** specific, written prior permission. **/ /** **/ /** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ /** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ /** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ /** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ /** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ /** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ /** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ /** OR PERFORMANCE OF THIS SOFTWARE. **/ /*****************************************************************************/ /*********************************************************************** * * $XConsortium: menus.c,v 1.186 91/07/17 13:58:00 dave Exp $ * * twm menu code * * 17-Nov-87 Thomas E. LaStrange File created * ***********************************************************************/ #include #include /* djhjr - 10/27/02 */ #ifndef NO_REGEX_SUPPORT #include #include #endif #include #include #include #include #include #ifdef NEED_PROCESS_H #include #endif #include /* DSE */ #include "twm.h" #include "gc.h" #include "menus.h" #include "resize.h" #include "events.h" #include "util.h" #include "parse.h" #include "gram.h" #include "screen.h" #include "doors.h" #include "desktop.h" #include "add_window.h" /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT #include "sound.h" #endif #include "version.h" #define strdup Strdup /* avoid conflict with system header files */ extern char *strdup(char *); extern void IconUp(), IconDown(), CreateIconWindow(); /* djhjr - 4/26/99 */ extern void AppletDown(); /* djhjr - 12/2/01 */ extern void delete_pidfile(); /* djhjr - 10/27/02 */ extern int MatchName(); extern void ResizeTwmWindowContents(); extern void SetRaiseWindow(); extern char *Action; extern int Context; extern int ConstrainedMoveTime; extern TwmWindow *ButtonWindow, *Tmp_win; extern XEvent Event, ButtonEvent; extern char *InitFile; int RootFunction = F_NOFUNCTION; MenuRoot *ActiveMenu = NULL; /* the active menu */ MenuItem *ActiveItem = NULL; /* the active menu item */ int MoveFunction = F_NOFUNCTION; /* or F_MOVE or F_FORCEMOVE */ int WindowMoved = FALSE; int menuFromFrameOrWindowOrTitlebar = FALSE; /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT int createSoundFromFunction = FALSE; int destroySoundFromFunction = FALSE; #endif void BumpWindowColormap(); void DestroyMenu(); void HideIconManager(); void MakeMenu(); void SendDeleteWindowMessage(); void SendSaveYourselfMessage(); void WarpClass(); void WarpToScreen(); void WarpScreenToWindow(); Cursor NeedToDefer(); /* was an 'int' - Submitted by Michel Eyckmans */ int ConstMove = FALSE; /* constrained move variables */ /* for comparison against MoveDelta - djhjr - 9/5/98 */ static int MenuOrigX, MenuOrigY; /* Globals used to keep track of whether the mouse has moved during a resize function. */ int ResizeOrigX; int ResizeOrigY; extern int origx, origy, origWidth, origHeight; int MenuDepth = 0; /* number of menus up */ static struct { int x; int y; } MenuOrigins[MAXMENUDEPTH]; static Cursor LastCursor; static char *actionHack = ""; /* Submitted by Michel Eyckmans */ /* * context bitmaps for TwmWindows menu, f.showdesktop and f.showiconmgr * djhjr - 9/10/99 */ static int have_twmwindows = -1; static int have_showdesktop = -1; static int have_showlist = -1; void WarpAlongRing(); /* djhjr - 4/18/96 */ void Paint3DEntry(); static void Identify(); void PaintNormalEntry(); /* djhjr - 5/13/98 */ static TwmWindow *next_by_class(); static int warp_if_warpunmapped(); /* djhjr - 7/31/98 */ static void setup_restart(); void RestartVtwm(); /* djhjr - 9/21/99 */ int FindMenuOrFuncInBindings(); int FindMenuOrFuncInWindows(); int FindMenuInMenus(); int FindFuncInMenus(); /* djhjr - 9/21/99 */ void HideIconMgr(); void ShowIconMgr(); /* djhjr - 9/17/02 */ static int do_squeezetitle(); /* djhjr */ #undef MAX /* DSE */ #define MAX(x,y) ((x)>(y)?(x):(y)) #define SHADOWWIDTH 5 /* in pixels */ #define EDGE_OFFSET 5 /* DSE */ /* djhjr - 5/5/98 #define PULLDOWNMENU_OFFSET ((Scr->RightHandSidePulldownMenus)?\ (ActiveMenu->width - EDGE_OFFSET * 2 - Scr->pullW):\ (ActiveMenu->width >> 1)) * DSE * */ #define PULLDOWNMENU_OFFSET ((Scr->RightHandSidePulldownMenus)?\ (JunkWidth - EDGE_OFFSET * 2 - Scr->pullW):\ (JunkWidth >> 1)) /*********************************************************************** * * Procedure: * InitMenus - initialize menu roots * *********************************************************************** */ void InitMenus() { int i, j, k; FuncKey *key, *tmp; for (i = 0; i < MAX_BUTTONS+1; i++) for (j = 0; j < NUM_CONTEXTS; j++) for (k = 0; k < MOD_SIZE; k++) { Scr->Mouse[i][j][k].func = F_NOFUNCTION; Scr->Mouse[i][j][k].item = NULL; } Scr->DefaultFunction.func = F_NOFUNCTION; Scr->WindowFunction.func = F_NOFUNCTION; if (FirstScreen) { for (key = Scr->FuncKeyRoot.next; key != NULL;) { free(key->name); tmp = key; key = key->next; free((char *) tmp); } Scr->FuncKeyRoot.next = NULL; } } /*********************************************************************** * * Procedure: * AddFuncKey - add a function key to the list * * Inputs: * name - the name of the key * cont - the context to look for the key press in * mods - modifier keys that need to be pressed * func - the function to perform * win_name- the window name (if any) * action - the action string associated with the function (if any) * *********************************************************************** */ Bool AddFuncKey (name, cont, mods, func, win_name, action) char *name; int cont, mods, func; char *win_name; char *action; { FuncKey *tmp; KeySym keysym; KeyCode keycode; /* * Don't let a 0 keycode go through, since that means AnyKey to the * XGrabKey call in GrabKeys(). */ if ((keysym = XStringToKeysym(name)) == NoSymbol || (keycode = XKeysymToKeycode(dpy, keysym)) == 0) { return False; } /* see if there already is a key defined for this context */ for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next) { if (tmp->keysym == keysym && tmp->cont == cont && tmp->mods == mods) break; } if (tmp == NULL) { tmp = (FuncKey *) malloc(sizeof(FuncKey)); tmp->next = Scr->FuncKeyRoot.next; Scr->FuncKeyRoot.next = tmp; } tmp->name = name; tmp->keysym = keysym; tmp->keycode = keycode; tmp->cont = cont; tmp->mods = mods; tmp->func = func; tmp->win_name = win_name; tmp->action = action; return True; } int CreateTitleButton (name, func, action, menuroot, rightside, append) char *name; int func; char *action; MenuRoot *menuroot; Bool rightside; Bool append; { TitleButton *tb = (TitleButton *) malloc (sizeof(TitleButton)); if (!tb) { fprintf (stderr, "%s: unable to allocate %d bytes for title button\n", ProgramName, sizeof(TitleButton)); return 0; } tb->next = NULL; tb->name = name; /* note that we are not copying */ /* djhjr - 10/30/02 * djhjr - 4/19/96 * tb->image = NULL; */ /* tb->bitmap = None;*/ /* WARNING, values not set yet */ tb->width = 0; /* see InitTitlebarButtons */ tb->height = 0; /* ditto */ tb->func = func; tb->action = action; tb->menuroot = menuroot; tb->rightside = rightside; if (rightside) { Scr->TBInfo.nright++; } else { Scr->TBInfo.nleft++; } /* * Cases for list: * * 1. empty list, prepend left put at head of list * 2. append left, prepend right put in between left and right * 3. append right put at tail of list * * Do not refer to widths and heights yet since buttons not created * (since fonts not loaded and heights not known). */ if ((!Scr->TBInfo.head) || ((!append) && (!rightside))) { /* 1 */ tb->next = Scr->TBInfo.head; Scr->TBInfo.head = tb; } else if (append && rightside) { /* 3 */ register TitleButton *t; for (t = Scr->TBInfo.head; t->next; t = t->next) ; /* SUPPRESS 530 */ t->next = tb; tb->next = NULL; } else { /* 2 */ register TitleButton *t, *prev = NULL; for (t = Scr->TBInfo.head; t && !t->rightside; t = t->next) prev = t; if (prev) { tb->next = prev->next; prev->next = tb; } else { tb->next = Scr->TBInfo.head; Scr->TBInfo.head = tb; } } return 1; } /* * InitTitlebarButtons - Do all the necessary stuff to load in a titlebar * button. If we can't find the button, then put in a question; if we can't * find the question mark, something is wrong and we are probably going to be * in trouble later on. */ /* was of type 'void', now returns button height - djhjr - 12/10/98 */ int InitTitlebarButtons () { Image *image; TitleButton *tb; int h, height; /* * initialize dimensions */ Scr->TBInfo.width = (Scr->TitleHeight - 2 * (Scr->FramePadding + Scr->ButtonIndent)); /* djhjr - 10/18/02 * djhjr - 4/19/96 * * was 'Scr->use3Dtitles' - djhjr - 8/11/98 * if (Scr->TitleBevelWidth > 0) Scr->TBInfo.pad = ((Scr->TitlePadding > 1) ? ((Scr->TitlePadding + 1) / 2) : 0); else Scr->TBInfo.pad = ((Scr->TitlePadding > 1) ? ((Scr->TitlePadding + 1) / 2) : 1); */ Scr->TBInfo.pad = Scr->TitlePadding; h = Scr->TBInfo.width - 2 * Scr->TBInfo.border; /* djhjr - 10/30/02 */ if (!(h & 1)) h--; height = h; /* * add in some useful buttons and bindings so that novices can still * use the system. -- modified by DSE */ if (!Scr->NoDefaultTitleButtons) /* DSE */ { /* insert extra buttons */ /* djhjr - 4/19/96 */ /* was 'Scr->use3Dtitles' - djhjr - 8/11/98 */ if (Scr->TitleBevelWidth > 0) { if (!CreateTitleButton (TBPM_3DDOT, F_ICONIFY, "", (MenuRoot *) NULL, False, False)) fprintf (stderr, "%s: unable to add iconify button\n", ProgramName); if (!CreateTitleButton (TBPM_3DRESIZE, F_RESIZE, "", (MenuRoot *) NULL, True, True)) fprintf (stderr, "%s: unable to add resize button\n", ProgramName); } else { if (!CreateTitleButton (TBPM_ICONIFY, F_ICONIFY, "", (MenuRoot *) NULL, False, False)) fprintf(stderr,"%s: unable to add iconify button\n",ProgramName); if (!CreateTitleButton (TBPM_RESIZE, F_RESIZE, "", (MenuRoot *) NULL, True, True)) fprintf(stderr,"%s: unable to add resize button\n",ProgramName); } } if (!Scr->NoDefaultMouseOrKeyboardBindings) /* DSE */ { AddDefaultBindings (); } ComputeCommonTitleOffsets (); /* djhjr - 6/15/98 - moved it back to here... */ /* djhjr - 9/14/96 - moved to CreateWindowTitlebarButtons()... */ /* * load in images and do appropriate centering */ for (tb = Scr->TBInfo.head; tb; tb = tb->next) { /* djhjr - 4/19/96 tb->bitmap = FindBitmap (tb->name, &tb->width, &tb->height); if (!tb->bitmap) { tb->bitmap = FindBitmap (TBPM_QUESTION, &tb->width, &tb->height); if (!tb->bitmap) { * cannot happen (see util.c) * fprintf (stderr, "%s: unable to add titlebar button \"%s\"\n", ProgramName, tb->name); } } */ /* djhjr - 9/21/96 tb->image = GetImage (tb->name, Scr->TitleC); if (!tb->image) { tb->image = GetImage (TBPM_QUESTION, Scr->TitleC); if (!tb->image) { * cannot happen (see util.c) * fprintf (stderr, "%s: unable to add titlebar button \"%s\"\n", ProgramName, tb->name); } } */ /* added width and height - 10/30/02 */ image = GetImage (tb->name, h, h, Scr->ButtonBevelWidth * 2, (Scr->ButtonColorIsFrame) ? Scr->BorderColorC : Scr->TitleC); tb->width = image->width; /* added 'height = ' - djhjr - 12/10/98 */ height = tb->height = image->height; tb->dstx = (h - tb->width + 1) / 2; if (tb->dstx < 0) { /* clip to minimize copying */ tb->srcx = -(tb->dstx); tb->width = h; tb->dstx = 0; } else { tb->srcx = 0; } tb->dsty = (h - tb->height + 1) / 2; if (tb->dsty < 0) { tb->srcy = -(tb->dsty); tb->height = h; tb->dsty = 0; } else { tb->srcy = 0; } } /* for(...) */ /* djhjr - 12/10/98 */ return (height > h) ? height : h; /* ...end of moved */ } /* djhjr - 10/30/02 */ void SetMenuIconPixmap(filename) char *filename; { Scr->menuIconName = filename; } void PaintEntry(mr, mi, exposure) MenuRoot *mr; MenuItem *mi; int exposure; { /* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */ if (Scr->MenuBevelWidth > 0) Paint3DEntry (mr, mi, exposure); /* djhjr - 4/22/96 */ else PaintNormalEntry (mr, mi, exposure); } void Paint3DEntry(mr, mi, exposure) MenuRoot *mr; MenuItem *mi; int exposure; { int y_offset; int text_y; GC gc; /* djhjr - 4/29/98 y_offset = mi->item_num * Scr->EntryHeight + 2; */ /* djhjr - 5/22/00 y_offset = mi->item_num * Scr->EntryHeight + Scr->MenuBevelWidth; */ y_offset = (mi->item_num - mr->top) * Scr->EntryHeight + Scr->MenuBevelWidth; /* djhjr - 9/25/96 text_y = y_offset + Scr->MenuFont.y + 2; */ text_y = y_offset + (((Scr->EntryHeight - Scr->MenuFont.height) / 2) + Scr->MenuFont.y); if (mi->func != F_TITLE) { int x, y; if (mi->state) { /* djhjr - 9/25/96 Draw3DBorder (mr->w, 2, y_offset, mr->width - 4, Scr->EntryHeight, 1, mi->highlight, off, True, False); */ /* djhjr - 4/29/98 Draw3DBorder (mr->w, 2, y_offset + 1, mr->width - 4, Scr->EntryHeight - 1, 1, mi->highlight, off, True, False); */ Draw3DBorder (mr->w, Scr->MenuBevelWidth, y_offset + 1, mr->width - 2 * Scr->MenuBevelWidth, Scr->EntryHeight - 1, 1, mi->highlight, off, True, False); /* font was font.font->fid - djhjr - 9/14/03 */ FBF(mi->highlight.fore, mi->highlight.back, Scr->MenuFont); /* djhjr - 4/29/98 XDrawImageString(dpy, mr->w, Scr->NormalGC, mi->x + 2, text_y, mi->item, mi->strlen); */ /* djhjr - 9/14/03 */ #ifndef NO_I18N_SUPPORT MyFont_DrawImageString(dpy, mr->w, &Scr->MenuFont, #else XDrawImageString(dpy, mr->w, #endif Scr->NormalGC, mi->x + Scr->MenuBevelWidth, text_y, mi->item, mi->strlen); gc = Scr->NormalGC; } else { if (mi->user_colors || !exposure) { XSetForeground (dpy, Scr->NormalGC, mi->normal.back); /* djhjr - 9/25/96 XFillRectangle (dpy, mr->w, Scr->NormalGC, 2, y_offset, mr->width - 4, Scr->EntryHeight); */ /* djhjr - 4/29/98 XFillRectangle (dpy, mr->w, Scr->NormalGC, 2, y_offset + 1, mr->width - 4, Scr->EntryHeight - 1); */ XFillRectangle (dpy, mr->w, Scr->NormalGC, Scr->MenuBevelWidth, y_offset + 1, mr->width - 2 * Scr->MenuBevelWidth, Scr->EntryHeight - 1); /* font was font.font->fid - djhjr - 9/14/03 */ FBF (mi->normal.fore, mi->normal.back, Scr->MenuFont); gc = Scr->NormalGC; } else { gc = Scr->MenuGC; } /* djhjr - 4/29/98 XDrawImageString (dpy, mr->w, gc, mi->x + 2, text_y, mi->item, mi->strlen); */ /* djhjr - 9/14/03 */ #ifndef NO_I18N_SUPPORT MyFont_DrawImageString (dpy, mr->w, &Scr->MenuFont, #else XDrawImageString (dpy, mr->w, #endif gc, mi->x + Scr->MenuBevelWidth, text_y, mi->item, mi->strlen); if (mi->separated) { /* this 'if (...)' - djhjr - 1/19/98 */ if (!Scr->BeNiceToColormap) { FB (Scr->MenuC.shadd, Scr->MenuC.shadc); /* djhjr - 9/25/96 XDrawLine (dpy, mr->w, Scr->NormalGC, 1, y_offset + Scr->MenuFont.y + 5, mr->width - 2, y_offset + Scr->MenuFont.y + 5); */ /* djhjr - 4/29/98 XDrawLine (dpy, mr->w, Scr->NormalGC, 1, y_offset + Scr->EntryHeight - 1, mr->width - 2, y_offset + Scr->EntryHeight - 1); */ XDrawLine (dpy, mr->w, Scr->NormalGC, Scr->MenuBevelWidth + 1, y_offset + Scr->EntryHeight - 1, mr->width - Scr->MenuBevelWidth - 3, y_offset + Scr->EntryHeight - 1); } FB (Scr->MenuC.shadc, Scr->MenuC.shadd); /* djhjr - 9/25/96 XDrawLine (dpy, mr->w, Scr->NormalGC, 2, y_offset + Scr->MenuFont.y + 6, mr->width - 3, y_offset + Scr->MenuFont.y + 6); */ /* djhjr - 4/29/98 XDrawLine (dpy, mr->w, Scr->NormalGC, 2, y_offset + Scr->EntryHeight, mr->width - 3, y_offset + Scr->EntryHeight); */ XDrawLine (dpy, mr->w, Scr->NormalGC, Scr->MenuBevelWidth + 2, y_offset + Scr->EntryHeight, mr->width - Scr->MenuBevelWidth - 2, y_offset + Scr->EntryHeight); } } if (mi->func == F_MENU) { /* djhjr - 10/30/02 * create the pull right pixmap if needed * if (Scr->pullPm == None) { Scr->pullPm = Create3DMenuIcon (Scr->MenuFont.height, &Scr->pullW, &Scr->pullH, Scr->MenuC); */ Image *image; Pixel back; back = Scr->MenuC.back; if (mi->state) Scr->MenuC.back = mi->highlight.back; else Scr->MenuC.back = mi->normal.back; Scr->pullW = Scr->pullH = Scr->MenuFont.height; image = GetImage(Scr->menuIconName, Scr->pullW, Scr->pullH, 0, Scr->MenuC); Scr->MenuC.back = back; /* djhjr - 10/30/02 } */ /* djhjr - 4/29/98 x = mr->width - Scr->pullW - 5; */ x = mr->width - Scr->pullW - Scr->MenuBevelWidth - EDGE_OFFSET; /* djhjr - 9/25/96 y = y_offset + ((Scr->MenuFont.height - Scr->pullH) / 2) + 2; */ y = y_offset + ((Scr->EntryHeight - Scr->pullH) / 2) + 1; XCopyArea (dpy, image->pixmap, mr->w, gc, 0, 0, Scr->pullW, Scr->pullH, x, y); } } else { /* djhjr - 4/29/96 Draw3DBorder (mr->w, 2, y_offset, mr->width - 4, Scr->EntryHeight, 1, mi->normal, off, True, False); */ /* djhjr - 4/29/98 Draw3DBorder (mr->w, 2, y_offset, mr->width - 4, Scr->EntryHeight + 1, 1, mi->normal, off, True, False); */ Draw3DBorder (mr->w, Scr->MenuBevelWidth, y_offset, mr->width - 2 * Scr->MenuBevelWidth, Scr->EntryHeight + 1, 1, mi->normal, off, True, False); /* djhjr - 4/29/96 FBF (mi->normal.fore, mi->normal.back, Scr->MenuFont.font->fid); */ /* font was font.font->fid - djhjr - 9/14/03 */ FBF (mi->normal.fore, mi->normal.back, Scr->MenuTitleFont); /* djhjr - 9/25/96 XDrawImageString (dpy, mr->w, Scr->NormalGC, mi->x + 2, text_y, mi->item, mi->strlen); */ /* djhjr - 9/14/03 */ #ifndef NO_I18N_SUPPORT MyFont_DrawImageString (dpy, mr->w, &Scr->MenuTitleFont, #else XDrawImageString (dpy, mr->w, #endif Scr->NormalGC, mi->x, text_y, mi->item, mi->strlen); } } void PaintNormalEntry(mr, mi, exposure) MenuRoot *mr; MenuItem *mi; int exposure; { int y_offset; int text_y; GC gc; /* djhjr - 5/22/00 y_offset = mi->item_num * Scr->EntryHeight; */ y_offset = (mi->item_num - mr->top) * Scr->EntryHeight; /* djhjr - 9/26/96 text_y = y_offset + Scr->MenuFont.y; */ text_y = y_offset + (((Scr->EntryHeight - Scr->MenuFont.height) / 2) + Scr->MenuFont.y); if (mi->func != F_TITLE) { int x, y; if (mi->state) { XSetForeground(dpy, Scr->NormalGC, mi->highlight.back); XFillRectangle(dpy, mr->w, Scr->NormalGC, 0, y_offset, mr->width, Scr->EntryHeight); /* font was font.font->fid - djhjr - 9/14/03 */ FBF(mi->highlight.fore, mi->highlight.back, Scr->MenuFont); /* djhjr - 9/14/03 */ #ifndef NO_I18N_SUPPORT MyFont_DrawString(dpy, mr->w, &Scr->MenuFont, #else XDrawString(dpy, mr->w, #endif Scr->NormalGC, mi->x, text_y, mi->item, mi->strlen); gc = Scr->NormalGC; } else { if (mi->user_colors || !exposure) { XSetForeground(dpy, Scr->NormalGC, mi->normal.back); XFillRectangle(dpy, mr->w, Scr->NormalGC, 0, y_offset, mr->width, Scr->EntryHeight); /* font was font.font->fid - djhjr - 9/14/03 */ FBF(mi->normal.fore, mi->normal.back, Scr->MenuFont); gc = Scr->NormalGC; } else { gc = Scr->MenuGC; } /* djhjr - 9/14/03 */ #ifndef NO_I18N_SUPPORT MyFont_DrawString(dpy, mr->w, &Scr->MenuFont, #else XDrawString(dpy, mr->w, #endif gc, mi->x, text_y, mi->item, mi->strlen); if (mi->separated) /* djhjr - 9/26/96 XDrawLine (dpy, mr->w, gc, 0, y_offset + Scr->MenuFont.y + 5, mr->width, y_offset + Scr->MenuFont.y + 5); */ XDrawLine (dpy, mr->w, gc, 0, y_offset + Scr->EntryHeight - 1, mr->width, y_offset + Scr->EntryHeight - 1); } if (mi->func == F_MENU) { /* djhjr - 10/30/02 * create the pull right pixmap if needed * if (Scr->pullPm == None) { Scr->pullPm = CreateMenuIcon (Scr->MenuFont.height, &Scr->pullW, &Scr->pullH); */ Image *image; ColorPair cp; cp.back = Scr->MenuC.back; if (strncmp(Scr->menuIconName, ":xpm:", 5) != 0) { cp.fore = Scr->MenuC.fore; Scr->MenuC.fore = (mi->state) ? mi->highlight.fore : mi->normal.fore; Scr->MenuC.back = (mi->state) ? mi->highlight.back : mi->normal.back; } else Scr->MenuC.back = (mi->state) ? mi->highlight.back : mi->normal.back; Scr->pullW = Scr->pullH = Scr->MenuFont.height; image = GetImage(Scr->menuIconName, Scr->pullW, Scr->pullH, 0, Scr->MenuC); Scr->MenuC.back = cp.back; if (strncmp(Scr->menuIconName, ":xpm:", 5) != 0) Scr->MenuC.fore = cp.fore; /* djhjr - 10/30/02 } */ x = mr->width - Scr->pullW - EDGE_OFFSET; /* djhjr - 9/26/96 y = y_offset + ((Scr->MenuFont.height - Scr->pullH) / 2); */ y = y_offset + ((Scr->EntryHeight - Scr->pullH) / 2); /* djhjr - 10/30/02 XCopyPlane(dpy, Scr->pullPm->pixmap, mr->w, gc, 0, 0, Scr->pullW, Scr->pullH, x, y, 1); */ XCopyArea (dpy, image->pixmap, mr->w, gc, 0, 0, Scr->pullW, Scr->pullH, x, y); } } else { int y; XSetForeground(dpy, Scr->NormalGC, mi->normal.back); /* fill the rectangle with the title background color */ XFillRectangle(dpy, mr->w, Scr->NormalGC, 0, y_offset, mr->width, Scr->EntryHeight); XSetForeground(dpy, Scr->NormalGC, mi->normal.fore); /* now draw the dividing lines */ if (y_offset) XDrawLine (dpy, mr->w, Scr->NormalGC, 0, y_offset, mr->width, y_offset); y = ((mi->item_num+1) * Scr->EntryHeight)-1; XDrawLine(dpy, mr->w, Scr->NormalGC, 0, y, mr->width, y); /* djhjr - 4/29/96 FBF(mi->normal.fore, mi->normal.back, Scr->MenuFont.font->fid); */ /* font was font.font->fid - djhjr - 9/14/03 */ FBF (mi->normal.fore, mi->normal.back, Scr->MenuTitleFont); /* finally render the title */ /* djhjr - 9/14/03 */ #ifndef NO_I18N_SUPPORT MyFont_DrawString(dpy, mr->w, &Scr->MenuTitleFont, #else XDrawString(dpy, mr->w, #endif Scr->NormalGC, mi->x, text_y, mi->item, mi->strlen); } } void PaintMenu(mr, e) MenuRoot *mr; XEvent *e; { MenuItem *mi; /* djhjr - 5/22/00 */ int y_offset; /* djhjr - 4/22/96 */ /* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */ if (Scr->MenuBevelWidth > 0) { /* djhjr - 4/29/98 Draw3DBorder (mr->w, 0, 0, mr->width, mr->height, 2, Scr->MenuC, off, False, False); */ Draw3DBorder (mr->w, 0, 0, mr->width, mr->height, Scr->MenuBevelWidth, Scr->MenuC, off, False, False); } for (mi = mr->first; mi != NULL; mi = mi->next) { /* djhjr - 5/22/00 */ if (mi->item_num < mr->top) continue; /* djhjr - 5/22/00 int y_offset = mi->item_num * Scr->EntryHeight; */ y_offset = (mi->item_num - mr->top) * Scr->EntryHeight; /* djhjr - 5/22/00 */ if (y_offset + Scr->EntryHeight > mr->height) break; /* some servers want the previous entry redrawn - djhjr - 10/24/00 */ if (Scr->MenuBevelWidth > 0) y_offset += Scr->EntryHeight; /* * Be smart about handling the expose, redraw only the entries * that we need to. */ /* those servers want the next entry redrawn, too - djhjr - 10/24/00 */ if (e->xexpose.y < (y_offset + Scr->EntryHeight) && (e->xexpose.y + e->xexpose.height) > y_offset - ((mr->shadow) ? Scr->EntryHeight : 0)) { PaintEntry(mr, mi, True); } } XSync(dpy, 0); } static Bool fromMenu; extern int GlobalFirstTime; /* for StayUpMenus -- PF */ void UpdateMenu() { MenuItem *mi; int i, x, y, x_root, y_root, entry; int done; MenuItem *badItem = NULL; static int firstTime = True; fromMenu = TRUE; while (TRUE) { /* block until there is an event */ #ifdef NEVER /* see the '#else' - Steve Ratcliffe */ #if 0 if (!menuFromFrameOrWindowOrTitlebar && ! Scr->StayUpMenus) { XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | EnterWindowMask | ExposureMask | VisibilityChangeMask | LeaveWindowMask | ButtonMotionMask, &Event); } if (Event.type == MotionNotify) { /* discard any extra motion events before a release */ while(XCheckMaskEvent(dpy, ButtonMotionMask | ButtonReleaseMask, &Event)) if (Event.type == ButtonRelease) break; } #else while (XCheckMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | EnterWindowMask | ExposureMask, &Event)) { /* taken from tvtwm */ #endif /* 0 */ #else /* Submitted by Steve Ratcliffe */ XNextEvent(dpy, &Event); #endif /* NEVER */ if (!DispatchEvent ()) continue; if (Event.type == ButtonRelease ) { if (Scr->StayUpMenus) { if (firstTime == True) { /* it was the first release of the button */ firstTime = False; } else { /* thats the second we need to return now */ firstTime = True; menuFromFrameOrWindowOrTitlebar = FALSE; fromMenu = FALSE; return; } } else { /* not stay-up */ menuFromFrameOrWindowOrTitlebar = FALSE; fromMenu = FALSE; return; } } if (Cancel) return; #ifdef NEVER /* see the above - Steve Ratcliffe */ } #endif /* re-instated - Steve Ratcliffe */ if (Event.type != MotionNotify) continue; /* if we haven't received the enter notify yet, wait */ if (!ActiveMenu || !ActiveMenu->entered) continue; done = FALSE; XQueryPointer( dpy, ActiveMenu->w, &JunkRoot, &JunkChild, &x_root, &y_root, &x, &y, &JunkMask); /* djhjr - 9/5/98 */ if (!ActiveItem) if (abs(x_root - MenuOrigX) < Scr->MoveDelta && abs(y_root - MenuOrigY) < Scr->MoveDelta) continue; #if 0 /* if we haven't recieved the enter notify yet, wait */ if (ActiveMenu && !ActiveMenu->entered) continue; #endif XFindContext(dpy, ActiveMenu->w, ScreenContext, (caddr_t *)&Scr); JunkWidth = ActiveMenu->width; JunkHeight = ActiveMenu->height; /* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */ if (Scr->MenuBevelWidth > 0) { x -= Scr->MenuBevelWidth; y -= Scr->MenuBevelWidth; JunkWidth -= 2 * Scr->MenuBevelWidth; JunkHeight -= Scr->MenuBevelWidth; } /* djhjr - 5/22/00 if (x < 0 || y < 0 || x >= JunkWidth || y >= JunkHeight) */ if ((x < 0 || y < 0 || x >= JunkWidth || y >= JunkHeight) || (ActiveMenu->too_tall && (y < Scr->MenuScrollBorderWidth || y > JunkHeight - Scr->MenuScrollBorderWidth))) { if (ActiveItem && ActiveItem->func != F_TITLE) { ActiveItem->state = 0; PaintEntry(ActiveMenu, ActiveItem, False); } ActiveItem = NULL; /* menu scrolling - djhjr - 5/22/00 */ if (ActiveMenu->too_tall && x >= 0 && x < JunkWidth) { short j = ActiveMenu->top; if (y < Scr->MenuScrollBorderWidth) { if (ActiveMenu->top - Scr->MenuScrollJump < 0) continue; else j -= Scr->MenuScrollJump; } else if (y > JunkHeight - Scr->MenuScrollBorderWidth) { int k = JunkHeight / Scr->EntryHeight; if (ActiveMenu->top + k >= ActiveMenu->items) continue; else j += Scr->MenuScrollJump; } if (ActiveMenu->top != j) { ActiveMenu->top = j; XClearArea(dpy, ActiveMenu->w, 0, 0, 0, 0, True); } } continue; } /* look for the entry that the mouse is in */ /* djhjr - 5/22/00 entry = y / Scr->EntryHeight; */ entry = (y / Scr->EntryHeight) + ActiveMenu->top; for (i = 0, mi = ActiveMenu->first; mi != NULL; i++, mi=mi->next) { if (i == entry) break; } /* if there is an active item, we might have to turn it off */ if (ActiveItem) { /* is the active item the one we are on ? */ if (ActiveItem->item_num == entry && ActiveItem->state) done = TRUE; /* if we weren't on the active entry, let's turn the old * active one off */ if (!done && ActiveItem->func != F_TITLE) { ActiveItem->state = 0; PaintEntry(ActiveMenu, ActiveItem, False); } } /* djhjr - 5/22/00 */ if (ActiveMenu->too_tall && y + Scr->EntryHeight > JunkHeight) continue; /* if we weren't on the active item, change the active item and turn * it on */ if (!done) { ActiveItem = mi; /* djhjr - 5/20/98 if (ActiveItem->func != F_TITLE && !ActiveItem->state) */ if (ActiveItem && ActiveItem->func != F_TITLE && !ActiveItem->state) { ActiveItem->state = 1; PaintEntry(ActiveMenu, ActiveItem, False); if (Scr->StayUpOptionalMenus) /* PF */ GlobalFirstTime = firstTime = False; /* PF */ } } /* now check to see if we were over the arrow of a pull right entry */ /* djhjr - 5/20/98 if (ActiveItem->func == F_MENU && */ if (ActiveItem && ActiveItem->func == F_MENU && /* ((ActiveMenu->width - x) < (ActiveMenu->width >> 1))) */ ( x > PULLDOWNMENU_OFFSET )) /* DSE */ { MenuRoot *save = ActiveMenu; int savex = MenuOrigins[MenuDepth - 1].x; int savey = MenuOrigins[MenuDepth - 1].y; if (MenuDepth < MAXMENUDEPTH) { PopUpMenu (ActiveItem->sub, (savex + PULLDOWNMENU_OFFSET), /* DSE */ (savey + ActiveItem->item_num * Scr->EntryHeight) /*(savey + ActiveItem->item_num * Scr->EntryHeight + (Scr->EntryHeight >> 1))*/, False); } else if (!badItem) { DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ badItem = ActiveItem; } /* if the menu did get popped up, unhighlight the active item */ if (save != ActiveMenu && ActiveItem->state) { ActiveItem->state = 0; PaintEntry(save, ActiveItem, False); ActiveItem = NULL; } } if (badItem != ActiveItem) badItem = NULL; XFlush(dpy); } } /*********************************************************************** * * Procedure: * NewMenuRoot - create a new menu root * * Returned Value: * (MenuRoot *) * * Inputs: * name - the name of the menu root * *********************************************************************** */ MenuRoot * NewMenuRoot(name) char *name; { MenuRoot *tmp; #define UNUSED_PIXEL ((unsigned long) (~0)) /* more than 24 bits */ tmp = (MenuRoot *) malloc(sizeof(MenuRoot)); /* djhjr - 5/22/96 tmp->hi_fore = UNUSED_PIXEL; tmp->hi_back = UNUSED_PIXEL; */ tmp->highlight.fore = UNUSED_PIXEL; tmp->highlight.back = UNUSED_PIXEL; tmp->name = name; tmp->prev = NULL; tmp->first = NULL; tmp->last = NULL; tmp->items = 0; tmp->width = 0; tmp->mapped = NEVER_MAPPED; tmp->pull = FALSE; tmp->w = None; tmp->shadow = None; tmp->real_menu = FALSE; /* djhjr - 5/22/00 */ tmp->too_tall = 0; tmp->top = 0; if (Scr->MenuList == NULL) { Scr->MenuList = tmp; Scr->MenuList->next = NULL; } if (Scr->LastMenu == NULL) { Scr->LastMenu = tmp; Scr->LastMenu->next = NULL; } else { Scr->LastMenu->next = tmp; Scr->LastMenu = tmp; Scr->LastMenu->next = NULL; } /* djhjr - 5/4/98 if (strcmp(name, TWM_WINDOWS) == 0) */ if (strcmp(name, TWM_WINDOWS) == 0 || strcmp(name, VTWM_WINDOWS) == 0) Scr->Windows = tmp; return (tmp); } /*********************************************************************** * * Procedure: * AddToMenu - add an item to a root menu * * Returned Value: * (MenuItem *) * * Inputs: * menu - pointer to the root menu to add the item * item - the text to appear in the menu * action - the string to possibly execute * sub - the menu root if it is a pull-right entry * func - the numeric function * fore - foreground color string * back - background color string * *********************************************************************** */ MenuItem * AddToMenu(menu, item, action, sub, func, fore, back) MenuRoot *menu; char *item, *action; MenuRoot *sub; int func; char *fore, *back; { MenuItem *tmp; int width; MyFont *font; /* DSE */ #ifdef DEBUG_MENUS fprintf(stderr, "adding menu item=\"%s\", action=%s, sub=%d, f=%d\n", item, action, sub, func); #endif tmp = (MenuItem *) malloc(sizeof(MenuItem)); tmp->root = menu; if (menu->first == NULL) { menu->first = tmp; tmp->prev = NULL; } else { menu->last->next = tmp; tmp->prev = menu->last; } menu->last = tmp; tmp->item = item; tmp->strlen = strlen(item); tmp->action = action; tmp->next = NULL; tmp->sub = NULL; tmp->state = 0; tmp->func = func; /* djhjr - 4/22/96 */ tmp->separated = 0; if ( func == F_TITLE && (Scr->MenuTitleFont.name != NULL) ) /* DSE */ font= &(Scr->MenuTitleFont); else font= &(Scr->MenuFont); if (!Scr->HaveFonts) CreateFonts(); /* djhjr - 9/14/03 */ #ifndef NO_I18N_SUPPORT width = MyFont_TextWidth(font, #else width = XTextWidth(font->font, #endif item, tmp->strlen); if (width <= 0) width = 1; if (width > menu->width) menu->width = width; tmp->user_colors = FALSE; if (Scr->Monochrome == COLOR && fore != NULL) { int save; save = Scr->FirstTime; Scr->FirstTime = TRUE; /* djhjr - 4/22/96 GetColor(COLOR, &tmp->fore, fore); GetColor(COLOR, &tmp->back, back); */ GetColor(COLOR, &tmp->normal.fore, fore); GetColor(COLOR, &tmp->normal.back, back); /* djhjr - 4/22/96 */ /* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */ /* rem'd 'Scr->MenuBevelWidth' djhjr - 10/30/02 */ if (/*Scr->MenuBevelWidth > 0 && */!Scr->BeNiceToColormap) GetShadeColors (&tmp->normal); Scr->FirstTime = save; tmp->user_colors = TRUE; } if (sub != NULL) { tmp->sub = sub; menu->pull = TRUE; } tmp->item_num = menu->items++; return (tmp); } void MakeMenus() { MenuRoot *mr; for (mr = Scr->MenuList; mr != NULL; mr = mr->next) { if (mr->real_menu == FALSE) continue; MakeMenu(mr); } } void MakeMenu(mr) MenuRoot *mr; { MenuItem *start, *end, *cur, *tmp; XColor f1, f2, f3; XColor b1, b2, b3; XColor save_fore, save_back; int num, i; int fred, fgreen, fblue; int bred, bgreen, bblue; int width; /* djhjr - 4/22/96 */ int borderwidth; unsigned long valuemask; XSetWindowAttributes attributes; Colormap cmap = Scr->TwmRoot.cmaps.cwins[0]->colormap->c; MyFont *titleFont; if ( Scr->MenuTitleFont.name != NULL ) /* DSE */ { Scr->EntryHeight = MAX(Scr->MenuFont.height, Scr->MenuTitleFont.height) + 4; titleFont = &(Scr->MenuTitleFont); } else { Scr->EntryHeight = Scr->MenuFont.height + 4; titleFont= &(Scr->MenuFont); } /* lets first size the window accordingly */ if (mr->mapped == NEVER_MAPPED) { if (mr->pull == TRUE) { mr->width += 16 + 2 * EDGE_OFFSET; /* DSE */ } /* djhjr - 4/29/98 * djhjr - 9/18/96 * if (Scr->use3Dmenus) mr->width += 4; */ /* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */ if (Scr->MenuBevelWidth > 0) mr->width += 2 * Scr->MenuBevelWidth; width = mr->width + 2 * EDGE_OFFSET; /* DSE */ for (cur = mr->first; cur != NULL; cur = cur->next) { if (cur->func != F_TITLE) cur->x = EDGE_OFFSET; /* DSE */ else { cur->x = width - /* djhjr - 9/14/03 */ #ifndef NO_I18N_SUPPORT MyFont_TextWidth(titleFont, #else XTextWidth(titleFont->font, #endif cur->item, cur->strlen); cur->x /= 2; } } mr->height = mr->items * Scr->EntryHeight; /* djhjr - 4/29/98 * djhjr - 4/22/96 * if (Scr->use3Dmenus) mr->height += 4; */ /* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */ if (Scr->MenuBevelWidth > 0) mr->height += 2 * Scr->MenuBevelWidth; /* djhjr - 4/22/96 */ /* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */ borderwidth = (Scr->MenuBevelWidth > 0) ? 0 : 1; /* djhjr - 5/22/00 */ if (mr->height > Scr->MyDisplayHeight) { mr->too_tall = 1; mr->height = Scr->MyDisplayHeight - borderwidth * 2; } /* added this 'if () ... else' - djhjr - 4/29/98 */ /* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */ if (Scr->MenuBevelWidth > 0) mr->width += 2 * Scr->MenuBevelWidth + 6; else mr->width += 10; if (Scr->Shadow) { /* * Make sure that you don't draw into the shadow window or else * the background bits there will get saved */ valuemask = (CWBackPixel | CWBorderPixel); attributes.background_pixel = Scr->MenuShadowColor; attributes.border_pixel = Scr->MenuShadowColor; if (Scr->SaveUnder) { valuemask |= CWSaveUnder; attributes.save_under = True; } mr->shadow = XCreateWindow (dpy, Scr->Root, 0, 0, (unsigned int) mr->width, (unsigned int) mr->height, (unsigned int)0, CopyFromParent, (unsigned int) CopyFromParent, (Visual *) CopyFromParent, valuemask, &attributes); } valuemask = (CWBackPixel | CWBorderPixel | CWEventMask); attributes.background_pixel = Scr->MenuC.back; attributes.border_pixel = Scr->MenuC.fore; attributes.event_mask = (ExposureMask | EnterWindowMask); if (Scr->SaveUnder) { valuemask |= CWSaveUnder; attributes.save_under = True; } if (Scr->BackingStore) { valuemask |= CWBackingStore; attributes.backing_store = Always; } mr->w = XCreateWindow (dpy, Scr->Root, 0, 0, (unsigned int) mr->width, /* djhjr - 4/22/96 (unsigned int) mr->height, (unsigned int) 1, */ (unsigned int) mr->height, (unsigned int) borderwidth, CopyFromParent, (unsigned int) CopyFromParent, (Visual *) CopyFromParent, valuemask, &attributes); XSaveContext(dpy, mr->w, MenuContext, (caddr_t)mr); XSaveContext(dpy, mr->w, ScreenContext, (caddr_t)Scr); mr->mapped = UNMAPPED; } /* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */ if (Scr->MenuBevelWidth > 0 && (Scr->Monochrome == COLOR) && (mr->highlight.back == UNUSED_PIXEL)) { XColor xcol; char colname [32]; short save; xcol.pixel = Scr->MenuC.back; XQueryColor (dpy, cmap, &xcol); sprintf (colname, "#%04x%04x%04x", 5 * (xcol.red / 6), 5 * (xcol.green / 6), 5 * (xcol.blue / 6)); save = Scr->FirstTime; Scr->FirstTime = True; GetColor (Scr->Monochrome, &mr->highlight.back, colname); Scr->FirstTime = save; } /* djhjr - 4/22/96 */ /* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */ if (Scr->MenuBevelWidth > 0 && (Scr->Monochrome == COLOR) && (mr->highlight.fore == UNUSED_PIXEL)) { XColor xcol; char colname [32]; short save; xcol.pixel = Scr->MenuC.fore; XQueryColor (dpy, cmap, &xcol); sprintf (colname, "#%04x%04x%04x", 5 * (xcol.red / 6), 5 * (xcol.green / 6), 5 * (xcol.blue / 6)); save = Scr->FirstTime; Scr->FirstTime = True; GetColor (Scr->Monochrome, &mr->highlight.fore, colname); Scr->FirstTime = save; } /* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */ if (Scr->MenuBevelWidth > 0 && !Scr->BeNiceToColormap) GetShadeColors (&mr->highlight); /* get the default colors into the menus */ for (tmp = mr->first; tmp != NULL; tmp = tmp->next) { /* djhjr - 4/22/96 if (!tmp->user_colors) { if (tmp->func != F_TITLE) { tmp->fore = Scr->MenuC.fore; tmp->back = Scr->MenuC.back; } else { tmp->fore = Scr->MenuTitleC.fore; tmp->back = Scr->MenuTitleC.back; } } if (mr->hi_fore != UNUSED_PIXEL) { tmp->hi_fore = mr->hi_fore; tmp->hi_back = mr->hi_back; } else { tmp->hi_fore = tmp->back; tmp->hi_back = tmp->fore; } */ if (!tmp->user_colors) { if (tmp->func != F_TITLE) { tmp->normal.fore = Scr->MenuC.fore; tmp->normal.back = Scr->MenuC.back; } else { tmp->normal.fore = Scr->MenuTitleC.fore; tmp->normal.back = Scr->MenuTitleC.back; } } if (mr->highlight.fore != UNUSED_PIXEL) { tmp->highlight.fore = mr->highlight.fore; tmp->highlight.back = mr->highlight.back; } else { tmp->highlight.fore = tmp->normal.back; tmp->highlight.back = tmp->normal.fore; } /* was 'Scr->use3Dmenus' - djhjr - 8/11/98 */ if (Scr->MenuBevelWidth > 0 && !Scr->BeNiceToColormap) { if (tmp->func != F_TITLE) GetShadeColors (&tmp->highlight); else GetShadeColors (&tmp->normal); } } /* end for(...) */ if (Scr->Monochrome == MONOCHROME || !Scr->InterpolateMenuColors) return; start = mr->first; while (TRUE) { for (; start != NULL; start = start->next) { if (start->user_colors) break; } if (start == NULL) break; for (end = start->next; end != NULL; end = end->next) { if (end->user_colors) break; } if (end == NULL) break; /* we have a start and end to interpolate between */ num = end->item_num - start->item_num; /* djhjr - 4/22/96 f1.pixel = start->fore; XQueryColor(dpy, cmap, &f1); f2.pixel = end->fore; XQueryColor(dpy, cmap, &f2); b1.pixel = start->back; XQueryColor(dpy, cmap, &b1); b2.pixel = end->back; XQueryColor(dpy, cmap, &b2); */ f1.pixel = start->normal.fore; XQueryColor(dpy, cmap, &f1); f2.pixel = end->normal.fore; XQueryColor(dpy, cmap, &f2); b1.pixel = start->normal.back; XQueryColor(dpy, cmap, &b1); b2.pixel = end->normal.back; XQueryColor(dpy, cmap, &b2); fred = ((int)f2.red - (int)f1.red) / num; fgreen = ((int)f2.green - (int)f1.green) / num; fblue = ((int)f2.blue - (int)f1.blue) / num; bred = ((int)b2.red - (int)b1.red) / num; bgreen = ((int)b2.green - (int)b1.green) / num; bblue = ((int)b2.blue - (int)b1.blue) / num; f3 = f1; f3.flags = DoRed | DoGreen | DoBlue; b3 = b1; b3.flags = DoRed | DoGreen | DoBlue; /* djhjr - 4/23/96 */ start->highlight.back = start->normal.fore; start->highlight.fore = start->normal.back; num -= 1; for (i = 0, cur = start->next; i < num; i++, cur = cur->next) { f3.red += fred; f3.green += fgreen; f3.blue += fblue; save_fore = f3; b3.red += bred; b3.green += bgreen; b3.blue += bblue; save_back = b3; if (Scr->DontInterpolateTitles && (cur->func == F_TITLE)) continue; /* DSE -- from tvtwm */ XAllocColor(dpy, cmap, &f3); XAllocColor(dpy, cmap, &b3); /* djhjr - 4/22/96 cur->hi_back = cur->fore = f3.pixel; cur->hi_fore = cur->back = b3.pixel; */ cur->highlight.back = cur->normal.fore = f3.pixel; cur->highlight.fore = cur->normal.back = b3.pixel; cur->user_colors = True; f3 = save_fore; b3 = save_back; } start = end; /* djhjr - 4/22/96 start->highlight.back = start->normal.fore; start->highlight.fore = start->normal.back; */ } } /*********************************************************************** * * Procedure: * PopUpMenu - pop up a pull down menu * * Inputs: * menu - the root pointer of the menu to pop up * x, y - location of upper left of menu * center - whether or not to center horizontally over position * *********************************************************************** */ Bool PopUpMenu (menu, x, y, center) MenuRoot *menu; int x, y; Bool center; { int WindowNameOffset, WindowNameCount; TwmWindow **WindowNames; TwmWindow *tmp_win2,*tmp_win3; int mask; int i; int (*compar)() = (Scr->CaseSensitive ? strcmp : XmuCompareISOLatin1); /* djhjr - 9/5/98 */ int x_root, y_root; if (!menu) return False; /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT if (!PlaySound(F_MENU)) PlaySound(S_MMAP); #endif /* djhjr - 5/22/00 */ menu->top = 0; if (menu->w) XClearArea(dpy, menu->w, 0, 0, 0, 0, True); InstallRootColormap(); if (menu == Scr->Windows) { TwmWindow *tmp_win; /* this is the twm windows menu, let's go ahead and build it */ DestroyMenu (menu); menu->first = NULL; menu->last = NULL; menu->items = 0; menu->width = 0; menu->mapped = NEVER_MAPPED; /* djhjr - 5/4/98 AddToMenu(menu, "TWM Windows", NULLSTR, (MenuRoot *)NULL, F_TITLE,NULLSTR,NULLSTR); */ AddToMenu(menu, "VTWM Windows", NULLSTR, (MenuRoot *)NULL, F_TITLE,NULLSTR,NULLSTR); WindowNameOffset=(char *)Scr->TwmRoot.next->name - (char *)Scr->TwmRoot.next; for(tmp_win = Scr->TwmRoot.next , WindowNameCount=0; tmp_win != NULL; tmp_win = tmp_win->next) WindowNameCount++; if (WindowNameCount != 0) /* Submitted by Jennifer Elaan */ { WindowNames = (TwmWindow **)malloc(sizeof(TwmWindow *)*WindowNameCount); WindowNames[0] = Scr->TwmRoot.next; for(tmp_win = Scr->TwmRoot.next->next , WindowNameCount=1; tmp_win != NULL; tmp_win = tmp_win->next,WindowNameCount++) { /* Submitted by Erik Agsjo */ if (LookInList(Scr->DontShowInTWMWindows, tmp_win->full_name, &tmp_win->class)) { WindowNameCount--; continue; } tmp_win2 = tmp_win; for (i=0;iname,WindowNames[i]->name) < 0) { tmp_win3 = tmp_win2; tmp_win2 = WindowNames[i]; WindowNames[i] = tmp_win3; } } WindowNames[WindowNameCount] = tmp_win2; } for (i=0; iname, (char *)WindowNames[i], (MenuRoot *)NULL, F_POPUP,NULLSTR,NULLSTR); if (!Scr->OldFashionedTwmWindowsMenu && Scr->Monochrome == COLOR)/*RFBCOLOR*/ {/*RFBCOLOR*/ menu->last->user_colors = TRUE;/*RFBCOLOR*/ /* djhjr - 4/22/96 menu->last->fore = WindowNames[i]->virtual.fore;*RFBCOLOR* */ /* djhjr - 5/4/98 menu->last->normal.fore = WindowNames[i]->virtual.fore;*RFBCOLOR* */ menu->last->normal.fore = Scr->MenuC.fore; /* djhjr - 4/22/96 menu->last->back = WindowNames[i]->virtual.back;*RFBCOLOR* */ menu->last->normal.back = WindowNames[i]->virtual.back; /**********************************************************/ /* */ /* Okay, okay, it's a bit of a kludge. */ /* */ /* On the other hand, it's nice to have the VTWM Windows */ /* menu come up with "the right colors". And the colors */ /* from the panner are not a bad choice... */ /* */ /**********************************************************/ }/*RFBCOLOR*/ } free(WindowNames); } MakeMenu(menu); } if (menu->w == None || menu->items == 0) return False; /* Prevent recursively bringing up menus. */ if (menu->mapped == MAPPED) return False; /* * Dynamically set the parent; this allows pull-ups to also be main * menus, or to be brought up from more than one place. */ menu->prev = ActiveMenu; /* * Submitted by Steve Ratcliffe */ mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PointerMotionHintMask; if (Scr->StayUpMenus) mask |= PointerMotionMask; XGrabPointer(dpy, Scr->Root, True, mask, GrabModeAsync, GrabModeAsync, Scr->Root, Scr->MenuCursor, CurrentTime); ActiveMenu = menu; menu->mapped = MAPPED; menu->entered = FALSE; if (center) { x -= (menu->width / 2); y -= (Scr->EntryHeight / 2); /* sticky menus would be nice here */ } /* * clip to screen */ /* next line and " - i" to "x = " and "y = " - djhjr - 5/22/00 */ i = (Scr->MenuBevelWidth > 0) ? 0 : 2; if (x + menu->width > Scr->MyDisplayWidth) { x = Scr->MyDisplayWidth - menu->width - i; } if (x < 0) x = 0; if (y + menu->height > Scr->MyDisplayHeight) { y = Scr->MyDisplayHeight - menu->height - i; } if (y < 0) y = 0; MenuOrigins[MenuDepth].x = x; MenuOrigins[MenuDepth].y = y; MenuDepth++; XMoveWindow(dpy, menu->w, x, y); if (Scr->Shadow) { XMoveWindow (dpy, menu->shadow, x + SHADOWWIDTH, y + SHADOWWIDTH); } if (Scr->Shadow) { XRaiseWindow (dpy, menu->shadow); } XMapRaised(dpy, menu->w); if (Scr->Shadow) { XMapWindow (dpy, menu->shadow); } XSync(dpy, 0); /* djhjr - 9/5/98 */ XQueryPointer(dpy, menu->w, &JunkRoot, &JunkChild, &x_root, &y_root, &JunkX, &JunkY, &JunkMask); MenuOrigX = x_root; MenuOrigY = y_root; return True; } /*********************************************************************** * * Procedure: * PopDownMenu - unhighlight the current menu selection and * take down the menus * *********************************************************************** */ void PopDownMenu() { MenuRoot *tmp; if (ActiveMenu == NULL) return; /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT PlaySound(S_MUNMAP); #endif if (ActiveItem) { ActiveItem->state = 0; PaintEntry(ActiveMenu, ActiveItem, False); } for (tmp = ActiveMenu; tmp != NULL; tmp = tmp->prev) { if (Scr->Shadow) { XUnmapWindow (dpy, tmp->shadow); } XUnmapWindow(dpy, tmp->w); tmp->mapped = UNMAPPED; UninstallRootColormap(); } XFlush(dpy); ActiveMenu = NULL; ActiveItem = NULL; MenuDepth = 0; if (Context == C_WINDOW || Context == C_FRAME || Context == C_TITLE) { menuFromFrameOrWindowOrTitlebar = TRUE; } } /*********************************************************************** * * Procedure: * FindMenuRoot - look for a menu root * * Returned Value: * (MenuRoot *) - a pointer to the menu root structure * * Inputs: * name - the name of the menu root * *********************************************************************** */ MenuRoot * FindMenuRoot(name) char *name; { MenuRoot *tmp; for (tmp = Scr->MenuList; tmp != NULL; tmp = tmp->next) { if (strcmp(name, tmp->name) == 0) return (tmp); } return NULL; } static Bool belongs_to_twm_window (t, w) register TwmWindow *t; register Window w; { if (!t) return False; #if 0 StayUpMenus if (w == t->frame || w == t->title_w || w == t->hilite_w || w == t->icon_w || w == t->icon_bm_w) return True; #endif if (t && t->titlebuttons) { register TBWindow *tbw; register int nb = Scr->TBInfo.nleft + Scr->TBInfo.nright; for (tbw = t->titlebuttons; nb > 0; tbw++, nb--) { if (tbw->window == w) return True; } } return False; } /* * Hack^H^H^H^HWrapper to moves for non-menu contexts. * * djhjr - 10/11/01 10/4/02 */ static void moveFromCenterWrapper(tmp_win) TwmWindow *tmp_win; { if (!tmp_win->opaque_move) XUngrabServer(dpy); WarpScreenToWindow(tmp_win); /* now here's a nice little kludge... */ { int hilite = tmp_win->highlight; tmp_win->highlight = True; SetBorder(tmp_win, (hilite) ? True : False); tmp_win->highlight = hilite; Scr->Focus = tmp_win; } if (!tmp_win->opaque_move) XGrabServer(dpy); } /* * Jason P. Venner jason@tfs.com * This function is used by F_WARPTO to match the action name * against window names. * Re-written to use list.c:MatchName(), allowing VTWM-style wilcards. * djhjr - 10/27/02 */ int MatchWinName(action, t) char *action; TwmWindow *t; { int matched = 0; #ifndef NO_REGEX_SUPPORT regex_t re; #else char re; #endif if (MatchName(t->full_name, action, &re, LTYPE_ANY_STRING)) if (MatchName(t->class.res_name, action, &re, LTYPE_ANY_STRING)) if (MatchName(t->class.res_class, action, &re, LTYPE_ANY_STRING)) matched = 1; return (matched); } /*********************************************************************** * * Procedure: * ExecuteFunction - execute a twm root function * * Inputs: * func - the function to execute * action - the menu action to execute * w - the window to execute this function on * tmp_win - the twm window structure * event - the event that caused the function * context - the context in which the button was pressed * pulldown- flag indicating execution from pull down menu * * Returns: * TRUE if should continue with remaining actions else FALSE to abort * *********************************************************************** */ extern int MovedFromKeyPress; int ExecuteFunction(func, action, w, tmp_win, eventp, context, pulldown) int func; char *action; Window w; TwmWindow *tmp_win; XEvent *eventp; int context; int pulldown; { char tmp[200]; char *ptr; char buff[MAX_FILE_SIZE]; int count, fd; int do_next_action = TRUE; actionHack = action; /* Submitted by Michel Eyckmans */ RootFunction = F_NOFUNCTION; if (Cancel) return TRUE; /* XXX should this be FALSE? */ switch (func) { case F_UPICONMGR: case F_LEFTICONMGR: case F_RIGHTICONMGR: case F_DOWNICONMGR: case F_FORWICONMGR: case F_BACKICONMGR: case F_NEXTICONMGR: case F_PREVICONMGR: case F_NOP: case F_TITLE: case F_DELTASTOP: case F_RAISELOWER: case F_WARP: /* PF */ case F_WARPCLASSNEXT: /* PF */ case F_WARPCLASSPREV: /* PF */ case F_WARPTOSCREEN: case F_WARPTO: case F_WARPRING: case F_WARPTOICONMGR: case F_COLORMAP: /* djhjr - 4/30/96 */ case F_SEPARATOR: /* djhjr - 12/14/98 */ case F_STATICICONPOSITIONS: /* djhjr - 5/30/00 */ case F_WARPSNUG: case F_WARPVISIBLE: /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT case F_SOUNDS: #endif /* djhjr - 10/2/01 */ case F_STRICTICONMGR: /* djhjr - 9/9/02 */ case F_BINDBUTTONS: case F_BINDKEYS: case F_UNBINDBUTTONS: case F_UNBINDKEYS: break; default: XGrabPointer(dpy, Scr->Root, True, ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, Scr->Root, Scr->WaitCursor, CurrentTime); break; } /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT switch (func) { case F_BEEP: case F_SQUEEZECENTER: case F_SQUEEZELEFT: case F_SQUEEZERIGHT: /* djhjr - 11/4/03 */ case F_MOVESCREEN: case F_FORCEMOVE: case F_MOVE: case F_RESIZE: case F_EXEC: case F_DELETE: case F_DELETEDOOR: case F_DESTROY: case F_DEICONIFY: case F_ICONIFY: case F_IDENTIFY: case F_VERSION: case F_QUIT: case F_WARP: case F_WARPCLASSNEXT: case F_WARPCLASSPREV: case F_WARPRING: case F_WARPTO: case F_WARPTOICONMGR: case F_WARPTONEWEST: case F_WARPTOSCREEN: /* handle uniquely */ break; case F_POPUP: /* ignore */ break; case F_LOWER: case F_RAISE: case F_RAISELOWER: case F_NAIL: case F_NAMEDOOR: case F_BOTTOMZOOM: case F_FULLZOOM: case F_HORIZOOM: case F_LEFTZOOM: case F_RIGHTZOOM: case F_TOPZOOM: case F_ZOOM: case F_BACKICONMGR: case F_DOWNICONMGR: case F_FORWICONMGR: case F_LEFTICONMGR: case F_RIGHTICONMGR: case F_UPICONMGR: case F_FOCUS: case F_SAVEYOURSELF: case F_STICKYABOVE: case F_RING: case F_WINREFRESH: /* djhjr - 9/9/02 */ case F_BINDBUTTONS: case F_BINDKEYS: case F_UNBINDBUTTONS: case F_UNBINDKEYS: /* ignore if from a root menu */ if (Context != C_ROOT && Context != C_NO_CONTEXT) PlaySound(func); break; default: /* unconditional */ PlaySound(func); break; } #endif switch (func) { case F_NOP: case F_TITLE: break; case F_DELTASTOP: if (WindowMoved) do_next_action = FALSE; break; case F_RESTART: /* added this 'case' and 'if () ... else ' - djhjr - 7/15/98 */ case F_STARTWM: if (func == F_STARTWM) { /* dynamic allocation of (char **)my_argv - djhjr - 9/26/02 */ char *p, *delims = " \t"; char *new_argv = NULL, **my_argv = NULL; int i = 0, j = 0; p = strtok(action, delims); while (p) { if (j >= i) { i += 5; new_argv = (char *)realloc((char *)my_argv, i * sizeof(char *)); if (new_argv == NULL) { fprintf(stderr, "%s: unable to allocate %d bytes for execvp()\n", ProgramName, i * sizeof(char *)); break; } else my_argv = (char **)new_argv; } my_argv[j++] = strdup(p); p = strtok(NULL, delims); } if (new_argv != NULL) { my_argv[j] = NULL; /* djhjr - 7/31/98 */ setup_restart(eventp->xbutton.time); execvp(*my_argv, my_argv); fprintf(stderr, "%s: unable to start \"%s\"\n", ProgramName, *my_argv); new_argv = NULL; } if (new_argv == NULL) { i = 0; while (i < j) free(my_argv[i++]); if (j) free((char *)my_argv); } } else /* djhjr - 7/31/98 */ RestartVtwm(eventp->xbutton.time); break; case F_UPICONMGR: case F_DOWNICONMGR: case F_LEFTICONMGR: case F_RIGHTICONMGR: case F_FORWICONMGR: case F_BACKICONMGR: MoveIconManager(func); break; case F_NEXTICONMGR: case F_PREVICONMGR: JumpIconManager(func); break; case F_SHOWLIST: /* added this 'if (...) else ...' - djhjr - 9/21/99 */ if (context == C_ROOT) { name_list *list; ShowIconMgr(&Scr->iconmgr); /* * New code in list.c necessitates 'next_entry()' and * 'contents_of_entry()' - djhjr - 10/20/01 */ for (list = Scr->IconMgrs; list != NULL; list = next_entry(list)) ShowIconMgr((IconMgr *)contents_of_entry(list)); } else { IconMgr *ip; if ((ip = (IconMgr *)LookInList(Scr->IconMgrs, tmp_win->full_name, &tmp_win->class)) == NULL) ip = &Scr->iconmgr; ShowIconMgr(ip); } RaiseStickyAbove(); /* DSE */ RaiseAutoPan(); break; case F_HIDELIST: if (Scr->NoIconManagers) break; /* added argument - djhjr - 9/21/99 */ HideIconManager((context == C_ROOT) ? NULL : tmp_win); break; case F_SORTICONMGR: /* djhjr - 6/10/98 */ if (Scr->NoIconManagers || Scr->iconmgr.count == 0) break; if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE; { int save_sort; save_sort = Scr->SortIconMgr; Scr->SortIconMgr = TRUE; if (context == C_ICONMGR) SortIconManager((IconMgr *) NULL); else if (tmp_win->iconmgr) SortIconManager(tmp_win->iconmgrp); else DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ Scr->SortIconMgr = save_sort; } break; case F_IDENTIFY: if (DeferExecution(context, func, Scr->SelectCursor)) { return TRUE; } Identify(tmp_win); break; case F_VERSION: Identify ((TwmWindow *) NULL); break; case F_ZOOMZOOM: /* RFB silly */ /* added args to iconmgrs - djhjr - 10/11/01 */ Zoom( None, NULL, None, NULL ); break; case F_AUTOPAN:/*RFB F_AUTOPAN*/ { /* toggle autopan *//*RFB F_AUTOPAN*/ static int saved;/*RFB F_AUTOPAN*/ if ( Scr->AutoPanX ) { saved = Scr->AutoPanX;/*RFB F_AUTOPAN*/ Scr->AutoPanX = 0;/*RFB F_AUTOPAN*/ } else { /*RFB F_AUTOPAN*/ Scr->AutoPanX = saved;/*RFB F_AUTOPAN*/ /* if restart with no autopan, we'll set the ** variable but we won't pan */ RaiseAutoPan(); /* DSE */ }/*RFB F_AUTOPAN*/ break;/*RFB F_AUTOPAN*/ }/*RFB F_AUTOPAN*/ case F_STICKYABOVE: /* DSE */ if (Scr->StickyAbove) { LowerSticky(); Scr->StickyAbove = FALSE; /* don't change the order of execution! */ } else { Scr->StickyAbove = TRUE; RaiseStickyAbove(); RaiseAutoPan(); /* don't change the order of execution! */ } return TRUE; /* break; *//* NOT REACHABLE */ case F_AUTORAISE: if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE; tmp_win->auto_raise = !tmp_win->auto_raise; if (tmp_win->auto_raise) ++(Scr->NumAutoRaises); else --(Scr->NumAutoRaises); break; case F_BEEP: /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT /* sound has priority over bell */ if (PlaySound(func)) break; #endif DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ break; case F_POPUP: tmp_win = (TwmWindow *)action; if (Scr->WindowFunction.func != F_NOFUNCTION) { ExecuteFunction(Scr->WindowFunction.func, Scr->WindowFunction.item->action, w, tmp_win, eventp, C_FRAME, FALSE); } else { DeIconify(tmp_win); XRaiseWindow (dpy, tmp_win->frame); XRaiseWindow (dpy, tmp_win->VirtualDesktopDisplayWindow); RaiseStickyAbove(); RaiseAutoPan(); } break; case F_RESIZE: { TwmWindow *focused = NULL; /* djhjr - 5/27/03 */ Bool fromtitlebar = False; long releaseEvent; long movementMask; int resizefromcenter = 0; /* djhjr - 10/2/02 */ /* djhjr - 10/6/02 */ #ifndef NO_SOUND_SUPPORT int did_playsound = FALSE; #endif if (DeferExecution(context, func, Scr->ResizeCursor)) return TRUE; PopDownMenu(); if (pulldown) XWarpPointer(dpy, None, Scr->Root, 0, 0, 0, 0, eventp->xbutton.x_root, eventp->xbutton.y_root); EventHandler[EnterNotify] = HandleUnknown; EventHandler[LeaveNotify] = HandleUnknown; /* allow the resizing of doors - djhjr - 2/22/99 if ((w != tmp_win->icon_w) && (context != C_DOOR)) */ if (context == C_ICON) /* can't resize icons */ { DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ break; } /* * Resizing from a titlebar menu was handled uniquely long * before I got here, and I added virtual windows and icon * managers on 9/15/99 and 10/11/01, leveraging that code. * It's all been integrated here. * djhjr - 10/3/02 */ if (Context & (C_FRAME_BIT | C_WINDOW_BIT | C_TITLE_BIT) && menuFromFrameOrWindowOrTitlebar) { XGetGeometry(dpy, w, &JunkRoot, &origDragX, &origDragY, (unsigned int *)&DragWidth, (unsigned int *)&DragHeight, &JunkBW, &JunkDepth); resizefromcenter = 2; } else if (Context == C_VIRTUAL_WIN) { TwmWindow *twin; if ((XFindContext(dpy, eventp->xbutton.subwindow, VirtualContext, (caddr_t *) &twin) == XCNOENT)) { DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ break; } context = C_WINDOW; tmp_win = twin; resizefromcenter = 1; } else if (Context == C_ICONMGR && tmp_win->list) { /* added the second argument - djhjr - 5/28/00 */ if (!warp_if_warpunmapped(tmp_win, F_NOFUNCTION)) { DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ break; } resizefromcenter = 1; } if (resizefromcenter) { WarpScreenToWindow(tmp_win); XWarpPointer(dpy, None, Scr->Root, 0, 0, 0, 0, tmp_win->frame_x + tmp_win->frame_width / 2, tmp_win->frame_y + tmp_win->frame_height / 2); /* grr - djhjr - 5/27/03 */ focused = Scr->Focus; Scr->Focus = tmp_win; SetBorder(Scr->Focus, True); /* save positions so we can tell if it was moved or not */ ResizeOrigX = tmp_win->frame_x + tmp_win->frame_width / 2; ResizeOrigY = tmp_win->frame_y + tmp_win->frame_height / 2; } else { /* save position so we can tell if it was moved or not */ ResizeOrigX = eventp->xbutton.x_root; ResizeOrigY = eventp->xbutton.y_root; } /* see if this is being done from the titlebar */ fromtitlebar = belongs_to_twm_window(tmp_win, eventp->xbutton.window); if (resizefromcenter == 2) { MenuStartResize(tmp_win, origDragX, origDragY, DragWidth, DragHeight, Context); releaseEvent = ButtonPress; movementMask = PointerMotionMask; } else { StartResize(eventp, tmp_win, fromtitlebar, context); fromtitlebar = False; releaseEvent = ButtonRelease; movementMask = ButtonMotionMask; } /* substantially re-worked - djhjr - 5/27/03 */ while (TRUE) { /* added exposure event masks - djhjr - 10/11/01 */ XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | ExposureMask | VisibilityChangeMask | movementMask, &Event); /* * See down below, after this loop - djhjr - 5/27/03 */ #if 0 /* discard crossing events before a release - djhjr - 10/11/01 */ if (Event.xany.type == EnterNotify || Event.xany.type == LeaveNotify) { /* this can't be the proper place - djhjr - 10/2/02 */ SetBorder(tmp_win, True); continue; } #endif /* * Don't discard exposure events before release * or window borders and/or their titles in the * virtual desktop won't get redrawn - djhjr */ /* discard any extra motion events before a release */ if (Event.type == MotionNotify) { /* was 'ButtonMotionMask' - djhjr - 10/11/01 */ while (XCheckMaskEvent(dpy, releaseEvent | movementMask, &Event)) { if (Event.type == releaseEvent) break; } } /* * See above, before this loop - djhjr - 5/27/03 */ #if 0 if (fromtitlebar && Event.type == ButtonPress) { fromtitlebar = False; continue; } #endif if (Event.type == releaseEvent) { if (Cancel) { if (tmp_win->opaque_resize) { ConstrainSize(tmp_win, &origWidth, &origHeight); SetupWindow(tmp_win, origx, origy, origWidth, origHeight, -1); ResizeTwmWindowContents(tmp_win, origWidth, origHeight); } else MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0); ResizeWindow = None; resizing_window = 0; do_next_action = FALSE; } else { if (resizefromcenter == 2) { /* added passing of 'Context' - djhjr - 9/30/02 */ MenuEndResize(tmp_win, Context); } else EndResize(); /* DispatchEvent2() is depreciated - djhjr - 10/6/02 */ DispatchEvent(); /* djhjr - 5/27/03 11/2/03 */ if (!Scr->NoRaiseResize && !Scr->RaiseOnStart && WindowMoved) { XRaiseWindow(dpy, tmp_win->frame); SetRaiseWindow(tmp_win); } } break; } /* DispatchEvent2() is depreciated - djhjr - 10/6/02 */ if (!DispatchEvent()) continue; if (Event.type != MotionNotify) continue; XQueryPointer(dpy, Scr->Root, &JunkRoot, &JunkChild, &JunkX, &JunkY, &AddingX, &AddingY, &JunkMask); if (!resizing_window && (abs(AddingX - ResizeOrigX) < Scr->MoveDelta && abs(AddingY - ResizeOrigY) < Scr->MoveDelta)) { continue; } resizing_window = 1; WindowMoved = TRUE; /* djhjr - 5/27/03 11/3/03 */ if ((!Scr->NoRaiseResize && Scr->RaiseOnStart) /* trap a Shape extention bug - djhjr - 5/27/03 */ || (tmp_win->opaque_resize && (HasShape && (tmp_win->wShaped || tmp_win->squeeze_info))) ) { XRaiseWindow(dpy, tmp_win->frame); SetRaiseWindow(tmp_win); if (Scr->Virtual && tmp_win->VirtualDesktopDisplayWindow) XRaiseWindow(dpy, tmp_win->VirtualDesktopDisplayWindow); } /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT if (did_playsound == FALSE) { PlaySound(func); did_playsound = TRUE; } #endif /* MenuDoResize() is depreciated - djhjr - 10/6/02 */ DoResize(AddingX, AddingY, tmp_win); } /* djhjr - 6/4/98 return TRUE; */ /* djhjr - 7/17/98 * djhjr - 4/7/98 * if (!Scr->NoGrabServer) XUngrabServer(dpy); */ if (!tmp_win->opaque_resize) XUngrabServer(dpy); /* * All this stuff from resize.c:EndResize() - djhjr - 10/6/02 */ if (!tmp_win->opaque_resize) UninstallRootColormap(); /* discard queued enter and leave events - djhjr - 5/27/03 */ while (XCheckMaskEvent(dpy, EnterWindowMask | LeaveWindowMask, &Event)) ; if (!Scr->NoRaiseResize) { RaiseStickyAbove (); /* DSE */ RaiseAutoPan(); } /* update virtual coords */ tmp_win->virtual_frame_x = Scr->VirtualDesktopX + tmp_win->frame_x; tmp_win->virtual_frame_y = Scr->VirtualDesktopY + tmp_win->frame_y; /* UpdateDesktop(tmp_win); Stig */ /* djhjr - 5/27/03 MoveResizeDesktop(tmp_win, Scr->NoRaiseResize); * Stig * */ MoveResizeDesktop(tmp_win, Cancel | Scr->NoRaiseResize); /* Stig */ /* djhjr - 9/30/02 10/6/02 */ if (Context == C_VIRTUAL_WIN) { /* * Mask a bug that calls MoveOutline(zeros) after the * border has been repainted, leaving artifacts. I think * I know what the bug is, but I can't seem to fix it. */ if (Scr->BorderBevelWidth > 0) PaintBorders(tmp_win, False); JunkX = tmp_win->virtual_frame_x + tmp_win->frame_width / 2; JunkY = tmp_win->virtual_frame_y + tmp_win->frame_height / 2; XWarpPointer(dpy, None, Scr->VirtualDesktopDisplayOuter, 0, 0, 0, 0, SCALE_D(JunkX), SCALE_D(JunkY)); /* grr - djhjr - 5/27/03 */ SetBorder(Scr->Focus, False); Scr->Focus = focused; } /* djhjr - 6/4/98 */ /* don't re-map if the window is the virtual desktop - djhjr - 2/28/99 */ if (Scr->VirtualReceivesMotionEvents && /* !tmp_win->opaque_resize && */ tmp_win->w != Scr->VirtualDesktopDisplayOuter) { XUnmapWindow(dpy, Scr->VirtualDesktopDisplay); XMapWindow(dpy, Scr->VirtualDesktopDisplay); } break; } case F_ZOOM: case F_HORIZOOM: case F_FULLZOOM: case F_LEFTZOOM: case F_RIGHTZOOM: case F_TOPZOOM: case F_BOTTOMZOOM: if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE; /* djhjr - 4/1/00 */ PopDownMenu(); fullzoom(tmp_win, func); /* UpdateDesktop(tmp_win); Stig */ MoveResizeDesktop(tmp_win, Scr->NoRaiseMove); /* Stig */ break; case F_MOVE: case F_FORCEMOVE: { static Time last_time = 0; Window rootw; Bool fromtitlebar = False; int moving_icon = FALSE; int constMoveDir, constMoveX, constMoveY; int constMoveXL, constMoveXR, constMoveYT, constMoveYB; int origX, origY; long releaseEvent; long movementMask; int xl, yt, xr, yb; int movefromcenter = 0; /* djhjr - 10/4/02 */ /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT int did_playsound = FALSE; #endif if (DeferExecution(context, func, Scr->MoveCursor)) return TRUE; PopDownMenu(); rootw = eventp->xbutton.root; if (pulldown) XWarpPointer(dpy, None, Scr->Root, 0, 0, 0, 0, eventp->xbutton.x_root, eventp->xbutton.y_root); EventHandler[EnterNotify] = HandleUnknown; EventHandler[LeaveNotify] = HandleUnknown; /* djhjr - 4/7/98 if (!Scr->NoGrabServer || !Scr->OpaqueMove) XGrabServer(dpy); */ /* djhjr - 7/17/98 if (!Scr->NoGrabServer) XGrabServer(dpy); */ if (!tmp_win->opaque_move) XGrabServer(dpy); /* use initialized size... djhjr - 5/9/96 * djhjr - 4/27/96 * Scr->SizeStringOffset = SIZE_HINDENT; XResizeWindow(dpy, Scr->SizeWindow, Scr->SizeStringWidth + SIZE_HINDENT * 2, Scr->SizeFont.height + SIZE_VINDENT * 2); */ XGrabPointer(dpy, eventp->xbutton.root, True, ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PointerMotionMask, /* PointerMotionHintMask */ GrabModeAsync, GrabModeAsync, Scr->Root, Scr->MoveCursor, CurrentTime); /* added this 'if (...) else' - djhjr - 10/11/01 */ if (context == C_VIRTUAL_WIN) { TwmWindow *twin; if ((XFindContext(dpy, eventp->xbutton.subwindow, VirtualContext, (caddr_t *) &twin) == XCNOENT)) { DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ break; } tmp_win = twin; moveFromCenterWrapper(tmp_win); /* these two - djhjr - 10/4/02 */ w = tmp_win->frame; movefromcenter = 1; } else /* added this 'if (...) else' - djhjr - 9/15/99 */ if (context == C_ICONMGR && tmp_win->list) { /* added the second argument - djhjr - 5/28/00 */ if (!warp_if_warpunmapped(tmp_win, F_NOFUNCTION)) { DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ break; } moveFromCenterWrapper(tmp_win); /* djhjr - 10/11/01 */ /* these two - djhjr - 10/4/02 */ w = tmp_win->frame; movefromcenter = 1; } else if (context == C_ICON && tmp_win->icon_w) { DragX = eventp->xbutton.x; DragY = eventp->xbutton.y; w = tmp_win->icon_w; moving_icon = TRUE; } else if (w != tmp_win->icon_w) { XTranslateCoordinates(dpy, w, tmp_win->frame, eventp->xbutton.x, eventp->xbutton.y, &DragX, &DragY, &JunkChild); w = tmp_win->frame; } XMapRaised (dpy, Scr->SizeWindow); DragWindow = None; MoveFunction = func; /* set for DispatchEvent() */ XGetGeometry(dpy, w, &JunkRoot, &origDragX, &origDragY, (unsigned int *)&DragWidth, (unsigned int *)&DragHeight, &JunkBW, &JunkDepth); /* added this 'if (...) else' - djhjr - 10/4/02 */ if (menuFromFrameOrWindowOrTitlebar || movefromcenter || (moving_icon && fromMenu)) { origX = DragX = origDragX + DragWidth / 2; origY = DragY = origDragY + DragHeight / 2; } else { origX = eventp->xbutton.x_root; origY = eventp->xbutton.y_root; } CurrentDragX = origDragX; CurrentDragY = origDragY; /* * Only do the constrained move if timer is set - * need to check it in case of stupid or wicked fast servers. */ if ( ConstrainedMoveTime && eventp->xbutton.time - last_time < ConstrainedMoveTime) { int width, height; ConstMove = TRUE; constMoveDir = MOVE_NONE; constMoveX = eventp->xbutton.x_root - DragX - JunkBW; constMoveY = eventp->xbutton.y_root - DragY - JunkBW; width = DragWidth + 2 * JunkBW; height = DragHeight + 2 * JunkBW; constMoveXL = constMoveX + width/3; constMoveXR = constMoveX + 2*(width/3); constMoveYT = constMoveY + height/3; constMoveYB = constMoveY + 2*(height/3); XWarpPointer(dpy, None, w, 0, 0, 0, 0, DragWidth/2, DragHeight/2); XQueryPointer(dpy, w, &JunkRoot, &JunkChild, &JunkX, &JunkY, &DragX, &DragY, &JunkMask); } last_time = eventp->xbutton.time; /* djhjr - 4/7/98 if (!Scr->OpaqueMove) */ if (!tmp_win->opaque_move) { InstallRootColormap(); /*if (!Scr->MoveDelta)*/ /* djhjr - 10/2/02 */ { /* * Draw initial outline. This was previously done the * first time though the outer loop by dropping out of * the XCheckMaskEvent inner loop down to one of the * MoveOutline's below. */ MoveOutline(rootw, origDragX - JunkBW, origDragY - JunkBW, DragWidth + 2 * JunkBW, DragHeight + 2 * JunkBW, tmp_win->frame_bw, /* djhjr - 4/22/96 moving_icon ? 0 : tmp_win->title_height); */ moving_icon ? 0 : tmp_win->title_height + tmp_win->frame_bw3D); /* * This next line causes HandleButtonRelease to call * XRaiseWindow(). This is solely to preserve the * previous behaviour that raises a window being moved * on button release even if you never actually moved * any distance (unless you move less than MoveDelta or * NoRaiseMove is set or OpaqueMove is set). * * It's set way down below; no need to force it here. * djhjr - 10/4/02 * * The code referred to above is 'if 0'd out now anyway. * djhjr - 10/6/02 */ /*DragWindow = w;*/ } } /* * see if this is being done from the titlebar */ fromtitlebar = belongs_to_twm_window(tmp_win, eventp->xbutton.window); /* added 'movefromcenter' and 'moving_icon' - djhjr - 10/4/02 */ if ((menuFromFrameOrWindowOrTitlebar && !fromtitlebar) || movefromcenter || (moving_icon && fromMenu)) { /* warp the pointer to the middle of the window */ XWarpPointer(dpy, None, Scr->Root, 0, 0, 0, 0, origDragX + DragWidth / 2, origDragY + DragHeight / 2); SetBorder(tmp_win, True); /* grr */ XFlush(dpy); } /* djhjr - 4/27/96 */ DisplayPosition(CurrentDragX, CurrentDragY); if (menuFromFrameOrWindowOrTitlebar) { releaseEvent = ButtonPress; movementMask = PointerMotionMask; } else { releaseEvent = ButtonRelease; movementMask = ButtonMotionMask; } while (TRUE) { /* block until there is an interesting event */ XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | ExposureMask | VisibilityChangeMask | movementMask, &Event); /* * See down below, after this loop - djhjr - 5/23/03 */ #if 0 /* throw away enter and leave events until release */ if (Event.xany.type == EnterNotify || Event.xany.type == LeaveNotify) { continue; } #endif /* * Don't discard exposure events before release * or window borders and/or their titles in the * virtual desktop won't get redrawn - djhjr */ /* discard any extra motion events before a release */ if (Event.type == MotionNotify) { while (XCheckMaskEvent(dpy, movementMask | releaseEvent, &Event)) { if (Event.type == releaseEvent) break; } } /* * There used to be a couple of routines that handled the * cancel functionality here, each doing a portion of the * job, then returning immediately. They became redundant * to just letting program execution fall through. So now, * the 'if (Event.type == releaseEvent) if (Cancel)' below * does just that, clearing a few flags first. * djhjr - 10/6/02 */ if (fromtitlebar && Event.type == ButtonPress) { fromtitlebar = False; CurrentDragX = origX = Event.xbutton.x_root; CurrentDragY = origY = Event.xbutton.y_root; XTranslateCoordinates(dpy, rootw, tmp_win->frame, origX, origY, &DragX, &DragY, &JunkChild); continue; } /* DispatchEvent2() is depreciated - djhjr - 10/6/02 */ if (!DispatchEvent()) continue; /* re-wrote this stuff - djhjr - 10/4/02 5/24/03 11/2/03 */ if (Event.type == releaseEvent) { MoveOutline(rootw, 0, 0, 0, 0, 0, 0); if (Cancel) { DragWindow = None; ConstMove = WindowMoved = do_next_action = FALSE; } else if (WindowMoved) { if (moving_icon) { tmp_win->icon_moved = TRUE; XMoveWindow(dpy, tmp_win->icon_w, CurrentDragX, CurrentDragY); if (!Scr->NoRaiseMove && !Scr->RaiseOnStart) { XRaiseWindow(dpy, tmp_win->icon_w); SetRaiseWindow(tmp_win->icon_w); } } else { if (movefromcenter) { tmp_win->frame_x = Event.xbutton.x_root - DragWidth / 2; tmp_win->frame_y = Event.xbutton.y_root - DragHeight / 2; } else { tmp_win->frame_x = CurrentDragX; tmp_win->frame_y = CurrentDragY; } XMoveWindow(dpy, tmp_win->frame, tmp_win->frame_x, tmp_win->frame_y); SendConfigureNotify(tmp_win, tmp_win->frame_x, tmp_win->frame_y); if (!Scr->NoRaiseMove && !Scr->RaiseOnStart) { XRaiseWindow(dpy, tmp_win->frame); SetRaiseWindow(tmp_win); } } } break; } /* something left to do only if the pointer moved */ if (Event.type != MotionNotify) continue; XQueryPointer(dpy, rootw, &(eventp->xmotion.root), &JunkChild, &(eventp->xmotion.x_root), &(eventp->xmotion.y_root), &JunkX, &JunkY, &JunkMask); if (DragWindow == None && abs(eventp->xmotion.x_root - origX) < Scr->MoveDelta && abs(eventp->xmotion.y_root - origY) < Scr->MoveDelta) { continue; } WindowMoved = TRUE; DragWindow = w; /* djhjr - 4/7/98 if (!Scr->NoRaiseMove && Scr->OpaqueMove) */ /* djhjr - 10/6/02 if (!Scr->NoRaiseMove && tmp_win->opaque_move) XRaiseWindow(dpy, DragWindow); */ /* djhjr - 5/24/03 11/3/03 */ if (!Scr->NoRaiseMove && Scr->RaiseOnStart) { if (moving_icon) { XRaiseWindow(dpy, tmp_win->icon_w); SetRaiseWindow(tmp_win->icon_w); } else { XRaiseWindow(dpy, tmp_win->frame); SetRaiseWindow(tmp_win); if (Scr->Virtual && tmp_win->VirtualDesktopDisplayWindow) XRaiseWindow(dpy, tmp_win->VirtualDesktopDisplayWindow); } } if (ConstMove) { switch (constMoveDir) { case MOVE_NONE: if (eventp->xmotion.x_root < constMoveXL || eventp->xmotion.x_root > constMoveXR) { constMoveDir = MOVE_HORIZ; } if (eventp->xmotion.y_root < constMoveYT || eventp->xmotion.y_root > constMoveYB) { constMoveDir = MOVE_VERT; } XQueryPointer(dpy, DragWindow, &JunkRoot, &JunkChild, &JunkX, &JunkY, &DragX, &DragY, &JunkMask); break; case MOVE_VERT: constMoveY = eventp->xmotion.y_root - DragY - JunkBW; break; case MOVE_HORIZ: constMoveX = eventp->xmotion.x_root - DragX - JunkBW; break; } xl = constMoveX; yt = constMoveY; } else if (DragWindow != None) { /* added 'movefromcenter' and 'moving_icon' - djhjr - 10/4/02 */ if (!menuFromFrameOrWindowOrTitlebar && !movefromcenter && !(moving_icon && fromMenu)) { xl = eventp->xmotion.x_root - DragX - JunkBW; yt = eventp->xmotion.y_root - DragY - JunkBW; } else { xl = eventp->xmotion.x_root - (DragWidth / 2); yt = eventp->xmotion.y_root - (DragHeight / 2); } } if ((ConstMove && constMoveDir != MOVE_NONE) || DragWindow != None) { int width = DragWidth + 2 * JunkBW; int height = DragHeight + 2 * JunkBW; if (Scr->DontMoveOff && MoveFunction != F_FORCEMOVE) { xr = xl + width; yb = yt + height; if (xl < 0) xl = 0; if (xr > Scr->MyDisplayWidth) xl = Scr->MyDisplayWidth - width; if (yt < 0) yt = 0; if (yb > Scr->MyDisplayHeight) yt = Scr->MyDisplayHeight - height; } CurrentDragX = xl; CurrentDragY = yt; /* djhjr - 6/22/01 10/6/02 */ #ifndef NO_SOUND_SUPPORT if ((!ConstMove || constMoveDir != MOVE_NONE) && did_playsound == FALSE) { PlaySound(func); did_playsound = TRUE; } #endif /* djhjr - 4/7/98 if (Scr->OpaqueMove) */ if (tmp_win->opaque_move) XMoveWindow(dpy, DragWindow, xl, yt); else MoveOutline(eventp->xmotion.root, xl, yt, width, height, tmp_win->frame_bw, /* djhjr - 4/22/96 moving_icon ? 0 : tmp_win->title_height); */ moving_icon ? 0 : tmp_win->title_height + tmp_win->frame_bw3D); /* djhjr - 4/17/98 * move the small representation window * this knows a bit much about the internals i guess * XMoveWindow(dpy, tmp_win->VirtualDesktopDisplayWindow, SCALE_D(xl), SCALE_D(yt)); */ if (Scr->VirtualReceivesMotionEvents) { tmp_win->virtual_frame_x = R_TO_V_X(xl); tmp_win->virtual_frame_y = R_TO_V_Y(yt); /* djhjr - 5/24/03 MoveResizeDesktop(tmp_win, Scr->NoRaiseMove); */ MoveResizeDesktop(tmp_win, TRUE); } /* djhjr - 4/27/96 */ DisplayPosition (xl, yt); } } /* djhjr - 7/17/98 * djhjr - 4/7/98 * if (!Scr->NoGrabServer) XUngrabServer(dpy); */ if (!tmp_win->opaque_move) XUngrabServer(dpy); /* djhjr - 4/27/96 */ XUnmapWindow (dpy, Scr->SizeWindow); MovedFromKeyPress = False; if (!tmp_win->opaque_move) UninstallRootColormap(); /* discard queued enter and leave events - djhjr - 5/23/03 */ while (XCheckMaskEvent(dpy, EnterWindowMask | LeaveWindowMask, &Event)) ; /* from events.c:HandleButtonRelease() - djhjr - 10/6/02 */ if (!Scr->NoRaiseMove) { RaiseStickyAbove(); /* DSE */ RaiseAutoPan(); } /* update virtual coords */ tmp_win->virtual_frame_x = Scr->VirtualDesktopX + tmp_win->frame_x; tmp_win->virtual_frame_y = Scr->VirtualDesktopY + tmp_win->frame_y; /* UpdateDesktop() hoses the stacking order - djhjr - 10/6/02 */ /* djhjr - 5/24/03 MoveResizeDesktop(tmp_win, Scr->NoRaiseMove); */ MoveResizeDesktop(tmp_win, Cancel | Scr->NoRaiseMove); /* djhjr - 10/4/02 10/6/02 */ if (Context == C_VIRTUAL_WIN) { /* * Mask a bug that calls MoveOutline(zeros) after the * border has been repainted, leaving artifacts. I think * I know what the bug is, but I can't seem to fix it. */ if (Scr->BorderBevelWidth > 0) PaintBorders(tmp_win, False); JunkX = tmp_win->virtual_frame_x + tmp_win->frame_width / 2; JunkY = tmp_win->virtual_frame_y + tmp_win->frame_height / 2; XWarpPointer(dpy, None, Scr->VirtualDesktopDisplayOuter, 0, 0, 0, 0, SCALE_D(JunkX), SCALE_D(JunkY)); } /* djhjr - 6/4/98 */ /* don't re-map if the window is the virtual desktop - djhjr - 2/28/99 */ if (Scr->VirtualReceivesMotionEvents && /* !tmp_win->opaque_move && */ tmp_win->w != Scr->VirtualDesktopDisplayOuter) { XUnmapWindow(dpy, Scr->VirtualDesktopDisplay); XMapWindow(dpy, Scr->VirtualDesktopDisplay); } MoveFunction = F_NOFUNCTION; /* clear for DispatchEvent() */ /* sanity check (also in events.c:HandleButtonRelease()) - djhjr - 10/6/02 */ DragWindow = None; ConstMove = FALSE; break; } case F_FUNCTION: { MenuRoot *mroot; MenuItem *mitem; Cursor cursor; if ((mroot = FindMenuRoot(action)) == NULL) { fprintf (stderr, "%s: couldn't find function \"%s\"\n", ProgramName, action); return TRUE; } /* * Changed this 'if ()' for deferred keyboard events (see also events.c) * Submitted by Michel Eyckmans * if (NeedToDefer(mroot) && DeferExecution(context, func, Scr->SelectCursor)) */ if ((cursor = NeedToDefer(mroot)) != None && DeferExecution(context, func, cursor)) return TRUE; else { for (mitem = mroot->first; mitem != NULL; mitem = mitem->next) { if (!ExecuteFunction (mitem->func, mitem->action, w, tmp_win, eventp, context, pulldown)) break; } } } break; case F_DEICONIFY: case F_ICONIFY: if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE; /* added '|| (...)' - djhjr - 6/3/03 */ if (tmp_win->icon || (func == F_DEICONIFY && tmp_win == tmp_win->list->twm)) { /* djhjr - 6/3/03 */ #ifndef NO_SOUND_SUPPORT PlaySound(func); #endif DeIconify(tmp_win); /* * now HERE's a fine bit of kludge! it's to mask a hole in the * code I can't find that messes up when trying to warp to the * de-iconified window not in the real screen when WarpWindows * isn't used. see also the change in DeIconify(). * djhjr - 1/24/98 */ if (!Scr->WarpWindows && (Scr->WarpCursor || LookInList(Scr->WarpCursorL, tmp_win->full_name, &tmp_win->class))) { RaiseStickyAbove(); /* DSE */ RaiseAutoPan(); WarpToWindow(tmp_win); /* PF */ } } else if (func == F_ICONIFY) { /* djhjr - 9/10/99 */ TwmDoor *d; TwmWindow *tmgr = NULL, *twin = NULL; MenuRoot *mr; /* sanity check for what's next - djhjr - 9/10/99 */ if (XFindContext(dpy, tmp_win->w, DoorContext, (caddr_t *)&d) != XCNOENT) { twin = tmp_win; tmp_win = d->twin; } /* * don't iconify if there's no way to get it back - not fool-proof * djhjr - 9/10/99 */ if (tmp_win->iconify_by_unmapping) { /* iconified by unmapping */ if (tmp_win->list) tmgr = tmp_win->list->iconmgr->twm_win; if ((tmgr && !tmgr->mapped && tmgr->iconify_by_unmapping) || ((Scr->IconManagerDontShow || LookInList(Scr->IconMgrNoShow, tmp_win->full_name, &tmp_win->class)) && LookInList(Scr->IconMgrShow, tmp_win->full_name, &tmp_win->class) == (char *)NULL)) { /* icon manager not mapped or not shown in one */ if (have_twmwindows == -1) { have_twmwindows = 0; /* better than two calls to FindMenuRoot() */ for (mr = Scr->MenuList; mr != NULL; mr = mr->next) if (strcmp(mr->name, TWM_WINDOWS) == 0 || strcmp(mr->name, VTWM_WINDOWS) == 0) { /* djhjr - 9/21/99 */ have_twmwindows = FindMenuOrFuncInBindings(C_ALL_BITS, mr, F_NOFUNCTION); break; } } /* djhjr - 9/21/99 */ if (have_showdesktop == -1) have_showdesktop = FindMenuOrFuncInBindings(C_ALL_BITS, NULL, F_SHOWDESKTOP); if (have_showlist == -1) have_showlist = FindMenuOrFuncInBindings(C_ALL_BITS, NULL, F_SHOWLIST); /* djhjr - 9/21/99 */ if (!FindMenuOrFuncInWindows(tmp_win, have_twmwindows, mr, F_NOFUNCTION) || LookInList(Scr->DontShowInTWMWindows, tmp_win->full_name, &tmp_win->class)) { /* no TwmWindows menu or not shown in it */ if (tmp_win->w == Scr->VirtualDesktopDisplayOuter && FindMenuOrFuncInWindows(tmp_win, have_showdesktop, NULL, F_SHOWDESKTOP)) ; else if (tmp_win->iconmgr && FindMenuOrFuncInWindows(tmp_win, have_showlist, NULL, F_SHOWLIST)) ; else if (tmgr && FindMenuOrFuncInWindows(tmgr, have_showlist, NULL, F_SHOWLIST)) ; else { /* no f.showdesktop or f.showiconmgr */ DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ if (twin) tmp_win = twin; break; } } } } if (twin) tmp_win = twin; if (tmp_win->list || !Scr->NoIconifyIconManagers) /* PF */ { /* djhjr - 6/3/03 */ #ifndef NO_SOUND_SUPPORT PlaySound(func); #endif Iconify (tmp_win, eventp->xbutton.x_root - EDGE_OFFSET, /* DSE */ eventp->xbutton.y_root - EDGE_OFFSET); /* DSE */ } } break; case F_RAISELOWER: if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE; if (!WindowMoved) { XWindowChanges xwc; xwc.stack_mode = Opposite; if (w != tmp_win->icon_w) w = tmp_win->frame; XConfigureWindow (dpy, w, CWStackMode, &xwc); XConfigureWindow (dpy, tmp_win->VirtualDesktopDisplayWindow, CWStackMode, &xwc); /* ug */ XLowerWindow(dpy, Scr->VirtualDesktopDScreen); } break; case F_RAISE: if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE; /* check to make sure raise is not from the WindowFunction */ if (w == tmp_win->icon_w && Context != C_ROOT) XRaiseWindow(dpy, tmp_win->icon_w); else { XRaiseWindow(dpy, tmp_win->frame); XRaiseWindow(dpy, tmp_win->VirtualDesktopDisplayWindow); } RaiseStickyAbove(); /* DSE */ RaiseAutoPan(); break; case F_LOWER: if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE; if (!(Scr->StickyAbove && tmp_win->nailed)) { /* DSE */ if (w == tmp_win->icon_w) XLowerWindow(dpy, tmp_win->icon_w); else { XLowerWindow(dpy, tmp_win->frame); XLowerWindow(dpy, tmp_win->VirtualDesktopDisplayWindow); XLowerWindow(dpy, Scr->VirtualDesktopDScreen); } } /* DSE */ break; case F_FOCUS: if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE; if (tmp_win->icon == FALSE) { if (!Scr->FocusRoot && Scr->Focus == tmp_win) { FocusOnRoot(); } else { if (Scr->Focus != NULL) { SetBorder (Scr->Focus, False); /* djhjr - 4/25/96 if (Scr->Focus->hilite_w) XUnmapWindow (dpy, Scr->Focus->hilite_w); */ PaintTitleHighlight(Scr->Focus, off); } InstallWindowColormaps (0, tmp_win); /* djhjr - 4/25/96 if (tmp_win->hilite_w) XMapWindow (dpy, tmp_win->hilite_w); */ PaintTitleHighlight(tmp_win, on); SetBorder (tmp_win, True); SetFocus (tmp_win, eventp->xbutton.time); Scr->FocusRoot = FALSE; Scr->Focus = tmp_win; } } break; case F_DESTROY: if (DeferExecution(context, func, Scr->DestroyCursor)) return TRUE; /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT /* flag for the handler */ if (PlaySound(func)) destroySoundFromFunction = TRUE; #endif /* djhjr - 9/10/96 */ if (tmp_win == Scr->VirtualDesktopDisplayTwin) { /* added this 'if (...) ...' and 'if (...) else' - djhjr - 9/21/99 */ if (have_showdesktop == -1) have_showdesktop = FindMenuOrFuncInBindings(C_ALL_BITS, NULL, F_SHOWDESKTOP); if (FindMenuOrFuncInWindows(tmp_win, have_showdesktop, NULL, F_SHOWDESKTOP)) XUnmapWindow(dpy, Scr->VirtualDesktopDisplayTwin->frame); else DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ break; } { TwmDoor *d; if (XFindContext(dpy, tmp_win->w, DoorContext, (caddr_t *) &d) != XCNOENT) { /* djhjr - 9/10/99 XBell(dpy, 0); */ /* for some reason, we don't get the button up event - djhjr - 9/10/99 */ ButtonPressed = -1; door_delete(tmp_win->w, d); break; } } if (tmp_win->iconmgr) /* don't send ourself a message */ { /* added this 'if (...) ...' and 'if (...) else ...' - djhjr - 9/21/99 */ if (have_showlist == -1) have_showlist = FindMenuOrFuncInBindings(C_ALL_BITS, NULL, F_SHOWLIST); if (FindMenuOrFuncInWindows(tmp_win, have_showlist, NULL, F_SHOWLIST)) /* added argument - djhjr - 9/21/99 */ HideIconManager(tmp_win); else DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ } else { /* djhjr - 4/26/99 */ AppletDown(tmp_win); XKillClient(dpy, tmp_win->w); } break; case F_DELETE: if (DeferExecution(context, func, Scr->DestroyCursor)) return TRUE; /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT /* flag for the handler */ if (PlaySound(func)) destroySoundFromFunction = TRUE; #endif /* djhjr - 9/21/99 */ if (tmp_win == Scr->VirtualDesktopDisplayTwin) { if (have_showdesktop == -1) have_showdesktop = FindMenuOrFuncInBindings(C_ALL_BITS, NULL, F_SHOWDESKTOP); if (FindMenuOrFuncInWindows(tmp_win, have_showdesktop, NULL, F_SHOWDESKTOP)) XUnmapWindow(dpy, Scr->VirtualDesktopDisplayTwin->frame); else DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ break; } /* djhjr - 9/10/99 */ { TwmDoor *d; if (XFindContext(dpy, tmp_win->w, DoorContext, (caddr_t *) &d) != XCNOENT) { /* for some reason, we don't get the button up event - djhjr - 9/10/99 */ ButtonPressed = -1; door_delete(tmp_win->w, d); break; } } if (tmp_win->iconmgr) /* don't send ourself a message */ { /* added this 'if (...) ...' and 'if (...) else ...' - djhjr - 9/21/99 */ if (have_showlist == -1) have_showlist = FindMenuOrFuncInBindings(C_ALL_BITS, NULL, F_SHOWLIST); if (FindMenuOrFuncInWindows(tmp_win, have_showlist, NULL, F_SHOWLIST)) /* added argument - djhjr - 9/21/99 */ HideIconManager(tmp_win); else DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ } else if (tmp_win->protocols & DoesWmDeleteWindow) { /* djhjr - 4/26/99 */ AppletDown(tmp_win); SendDeleteWindowMessage (tmp_win, LastTimestamp()); } else DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ break; case F_SAVEYOURSELF: if (DeferExecution (context, func, Scr->SelectCursor)) return TRUE; if (tmp_win->protocols & DoesWmSaveYourself) SendSaveYourselfMessage (tmp_win, LastTimestamp()); else DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ break; case F_CIRCLEUP: XCirculateSubwindowsUp(dpy, Scr->Root); break; case F_CIRCLEDOWN: XCirculateSubwindowsDown(dpy, Scr->Root); break; case F_EXEC: PopDownMenu(); if (!Scr->NoGrabServer) { XUngrabServer (dpy); XSync (dpy, 0); } /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT /* flag for the handler */ if (PlaySound(func)) createSoundFromFunction = TRUE; #endif Execute(action); break; case F_UNFOCUS: FocusOnRoot(); break; case F_CUT: strcpy(tmp, action); strcat(tmp, "\n"); XStoreBytes(dpy, tmp, strlen(tmp)); break; case F_CUTFILE: ptr = XFetchBytes(dpy, &count); if (ptr) { if (sscanf (ptr, "%s", tmp) == 1) { XFree (ptr); ptr = ExpandFilename(tmp); if (ptr) { fd = open (ptr, 0); if (fd >= 0) { count = read (fd, buff, MAX_FILE_SIZE - 1); if (count > 0) XStoreBytes (dpy, buff, count); close(fd); } else { fprintf (stderr, "%s: unable to open cut file \"%s\"\n", ProgramName, tmp); } if (ptr != tmp) free (ptr); } } else { XFree(ptr); } } else { fprintf(stderr, "%s: cut buffer is empty\n", ProgramName); } break; case F_WARPTOSCREEN: { if (strcmp (action, WARPSCREEN_NEXT) == 0) { WarpToScreen (Scr->screen + 1, 1); } else if (strcmp (action, WARPSCREEN_PREV) == 0) { WarpToScreen (Scr->screen - 1, -1); } else if (strcmp (action, WARPSCREEN_BACK) == 0) { WarpToScreen (PreviousScreen, 0); } else { WarpToScreen (atoi (action), 0); } } break; case F_COLORMAP: { if (strcmp (action, COLORMAP_NEXT) == 0) { BumpWindowColormap (tmp_win, 1); } else if (strcmp (action, COLORMAP_PREV) == 0) { BumpWindowColormap (tmp_win, -1); } else { BumpWindowColormap (tmp_win, 0); } } break; case F_WARPCLASSNEXT: /* PF */ case F_WARPCLASSPREV: /* PF */ WarpClass(func == F_WARPCLASSNEXT, tmp_win, action); break; case F_WARPTONEWEST: /* PF */ /* added '&& warp_if_warpunmapped()' - djhjr - 5/13/98 */ /* added the second argument - djhjr - 5/28/00 */ if (Scr->Newest && warp_if_warpunmapped(Scr->Newest, F_NOFUNCTION)) { RaiseStickyAbove(); RaiseAutoPan(); /* djhjr - 6/3/03 */ #ifndef NO_SOUND_SUPPORT PlaySound(func); #endif WarpToWindow(Scr->Newest); } else DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ break; case F_WARPTO: { register TwmWindow *t; /* djhjr - 6/3/03 */ int did_warpto = FALSE; for (t = Scr->TwmRoot.next; t != NULL; t = t->next) { /* * This used to fall through into F_WARP, but the * warp_if_warpunmapped() meant this loop couldn't * continue to look for a match in the window list. * djhjr - 10/27/02 */ /* jason@tfs.com */ if (MatchWinName(action, t) == 0 && warp_if_warpunmapped(t, func)) { tmp_win = t; /* PF */ RaiseStickyAbove(); /* DSE */ RaiseAutoPan(); /* djhjr - 6/3/03 */ #ifndef NO_SOUND_SUPPORT PlaySound(func); #endif did_warpto = TRUE; WarpToWindow(tmp_win); /* PF */ break; } } /* djhjr - 6/3/03 */ if (!did_warpto) DoAudible(); } break; case F_WARP: /* PF */ { /* PF */ /* added '&& warp_if_warpunmapped()' - djhjr - 5/13/98 */ /* added the second argument - djhjr - 5/28/00 */ if (tmp_win && warp_if_warpunmapped(tmp_win, F_NOFUNCTION)) /* PF */ { RaiseStickyAbove(); /* DSE */ RaiseAutoPan(); /* djhjr - 6/3/03 */ #ifndef NO_SOUND_SUPPORT PlaySound(func); #endif WarpToWindow(tmp_win); /* PF */ } else { DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ } } /* PF */ break; case F_WARPTOICONMGR: { TwmWindow *t; int len; /* djhjr - 5/13/98 Window raisewin = None, iconwin = None; */ /* * raisewin now points to the window's icon manager entry, and * iconwin now points to raisewin's icon manager - djhjr - 5/30/00 * TwmWindow *raisewin = None; Window iconwin = None; */ WList *raisewin = NULL; TwmWindow *iconwin = None; len = strlen(action); if (len == 0) { if (tmp_win && tmp_win->list) { /* djhjr - 5/13/98 raisewin = tmp_win->list->iconmgr->twm_win->frame; */ /* djhjr - 5/30/00 raisewin = tmp_win->list->iconmgr->twm_win; iconwin = tmp_win->list->icon; */ raisewin = tmp_win->list; } else if (Scr->iconmgr.active) { /* djhjr - 5/13/98 raisewin = Scr->iconmgr.twm_win->frame; */ /* djhjr - 5/30/00 raisewin = Scr->iconmgr.twm_win; iconwin = Scr->iconmgr.active->w; */ raisewin = Scr->iconmgr.active; } } else { for (t = Scr->TwmRoot.next; t != NULL; t = t->next) { if (strncmp (action, t->icon_name, len) == 0) { if (t->list && t->list->iconmgr->twm_win->mapped) { /* djhjr - 5/13/98 raisewin = t->list->iconmgr->twm_win->frame; */ /* djhjr - 5/30/00 raisewin = t->list->iconmgr->twm_win; iconwin = t->list->icon; */ raisewin = t->list; break; } } } } /* djhjr - 6/14/00 */ if (!raisewin) { DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ break; } /* djhjr - 5/30/00 */ iconwin = raisewin->iconmgr->twm_win; /* added '&& warp_if_warpunmapped()' - djhjr - 5/13/98 */ /* added the second argument - djhjr - 5/28/00 */ /* was 'raisewin' - djhjr - 5/30/00 */ if (iconwin && warp_if_warpunmapped(iconwin, F_NOFUNCTION)) { /* djhjr - 6/3/03 */ #ifndef NO_SOUND_SUPPORT PlaySound(func); #endif /* djhjr - 5/30/00 XWarpPointer (dpy, None, iconwin, 0, 0, 0, 0, EDGE_OFFSET, EDGE_OFFSET); * DSE * */ WarpInIconMgr(raisewin, iconwin); } else { DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ } } break; case F_SQUEEZELEFT:/*RFB*/ { static SqueezeInfo left_squeeze = { J_LEFT, 0, 0 }; /* too much dup'd code - djhjr - 9/17/02 */ if (do_squeezetitle(context, func, tmp_win, &left_squeeze)) return TRUE; /* deferred */ } break; case F_SQUEEZERIGHT:/*RFB*/ { static SqueezeInfo right_squeeze = { J_RIGHT, 0, 0 }; /* too much dup'd code - djhjr - 9/17/02 */ if (do_squeezetitle(context, func, tmp_win, &right_squeeze)) return TRUE; /* deferred */ } break; case F_SQUEEZECENTER:/*RFB*/ { static SqueezeInfo center_squeeze = { J_CENTER, 0, 0 }; /* too much dup'd code - djhjr - 9/17/02 */ if (do_squeezetitle(context, func, tmp_win, ¢er_squeeze)) return TRUE; /* deferred */ } break; case F_RING:/*RFB*/ if (DeferExecution (context, func, Scr->SelectCursor)) return TRUE; if ( tmp_win->ring.next || tmp_win->ring.prev ) RemoveWindowFromRing(tmp_win); else AddWindowToRing(tmp_win); #ifdef ORIGINAL_WARPRINGCOORDINATES /* djhjr - 5/11/98 */ tmp_win->ring.cursor_valid = False; #endif break; case F_WARPRING: switch (action[0]) { case 'n': WarpAlongRing (&eventp->xbutton, True); break; case 'p': WarpAlongRing (&eventp->xbutton, False); break; default: DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ break; } break; case F_FILE: action = ExpandFilename(action); fd = open(action, 0); if (fd >= 0) { count = read(fd, buff, MAX_FILE_SIZE - 1); if (count > 0) XStoreBytes(dpy, buff, count); close(fd); } else { fprintf (stderr, "%s: unable to open file \"%s\"\n", ProgramName, action); } break; case F_REFRESH: { XSetWindowAttributes attributes; unsigned long valuemask; valuemask = (CWBackPixel | CWBackingStore | CWSaveUnder); attributes.background_pixel = Scr->Black; attributes.backing_store = NotUseful; attributes.save_under = False; w = XCreateWindow (dpy, Scr->Root, 0, 0, (unsigned int) Scr->MyDisplayWidth, (unsigned int) Scr->MyDisplayHeight, (unsigned int) 0, CopyFromParent, (unsigned int) CopyFromParent, (Visual *) CopyFromParent, valuemask, &attributes); XMapWindow (dpy, w); XDestroyWindow (dpy, w); XFlush (dpy); } break; case F_WINREFRESH: if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE; if (context == C_ICON && tmp_win->icon_w) w = XCreateSimpleWindow(dpy, tmp_win->icon_w, 0, 0, 9999, 9999, 0, Scr->Black, Scr->Black); else w = XCreateSimpleWindow(dpy, tmp_win->frame, 0, 0, 9999, 9999, 0, Scr->Black, Scr->Black); XMapWindow(dpy, w); XDestroyWindow(dpy, w); XFlush(dpy); break; case F_NAIL: if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE; tmp_win->nailed = !tmp_win->nailed; /* update the vd display */ /* UpdateDesktop(tmp_win); Stig */ NailDesktop(tmp_win); /* Stig */ #ifdef DEBUG fprintf(stdout, "%s: nail state of %s is now %s\n", ProgramName, tmp_win->name, (tmp_win->nailed ? "nailed" : "free")); #endif /* DEBUG */ RaiseStickyAbove(); /* DSE */ RaiseAutoPan(); /* DSE */ break; /* * move a percentage in a particular direction */ case F_PANDOWN: PanRealScreen(0, (atoi(action) * Scr->MyDisplayHeight) / 100 /* DSE */ ,NULL,NULL); break; case F_PANLEFT: PanRealScreen(-((atoi(action) * Scr->MyDisplayWidth) / 100), 0 /* DSE */ ,NULL,NULL); break; case F_PANRIGHT: PanRealScreen((atoi(action) * Scr->MyDisplayWidth) / 100, 0 /* DSE */ ,NULL,NULL); break; case F_PANUP: PanRealScreen(0, -((atoi(action) * Scr->MyDisplayHeight) / 100) /* DSE */ ,NULL,NULL); break; case F_RESETDESKTOP: SetRealScreen(0, 0); break; /*SNUG*/ /* Robert Forsman added these two functions */ /*SNUG*/ { /*SNUG*/ TwmWindow *scan; /*SNUG*/ int right, left, up, down; /*SNUG*/ int inited; /*SNUG*/ case F_SNUGDESKTOP: /*SNUG*/ /*SNUG*/ inited = 0; /*SNUG*/ for (scan = Scr->TwmRoot.next; scan!=NULL; scan = scan->next) /*SNUG*/ { /*SNUG*/ if (scan->nailed) /*SNUG*/ continue; /*SNUG*/ if (scan->frame_x > Scr->MyDisplayWidth || /*SNUG*/ scan->frame_y > Scr->MyDisplayHeight) /*SNUG*/ continue; /*SNUG*/ if (scan->frame_x+scan->frame_width < 0 || /*SNUG*/ scan->frame_y+scan->frame_height < 0) /*SNUG*/ continue; /*SNUG*/ if ( inited==0 || scan->frame_xframe_x; /*SNUG*/ if ( inited==0 || scan->frame_yframe_y; /*SNUG*/ if ( inited==0 || scan->frame_x+scan->frame_width>left ) /*SNUG*/ left = scan->frame_x+scan->frame_width; /*SNUG*/ if ( inited==0 || scan->frame_y+scan->frame_height>down ) /*SNUG*/ down = scan->frame_y+scan->frame_height; /*SNUG*/ inited = 1; /*SNUG*/ } /*SNUG*/ if (inited) /*SNUG*/ { /*SNUG*/ int dx,dy; /*SNUG*/ if (left-right < Scr->MyDisplayWidth && (right<0 || left>Scr->MyDisplayWidth) ) /*SNUG*/ dx = right - ( Scr->MyDisplayWidth - (left-right) ) /2; /*SNUG*/ else /*SNUG*/ dx = 0; /*SNUG*/ if (down-up < Scr->MyDisplayHeight && (up<0 || down>Scr->MyDisplayHeight) ) /*SNUG*/ dy = up - (Scr->MyDisplayHeight - (down-up) ) /2; /*SNUG*/ else /*SNUG*/ dy = 0; /*SNUG*/ if (dx!=0 || dy!=0) /*SNUG*/ PanRealScreen(dx,dy,NULL,NULL); /*SNUG*/ /* DSE */ /*SNUG*/ else /*SNUG*/ DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ /*SNUG*/ } /*SNUG*/ else /*SNUG*/ DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ /*SNUG*/ break; /*SNUG*/ /*SNUG*/ case F_SNUGWINDOW: /*SNUG*/ if (DeferExecution(context, func, Scr->SelectCursor)) /*SNUG*/ return TRUE; /*SNUG*/ /*SNUG*/ inited = 0; /*SNUG*/ right = tmp_win->frame_x; /*SNUG*/ left = tmp_win->frame_x + tmp_win->frame_width; /*SNUG*/ up = tmp_win->frame_y; /*SNUG*/ down = tmp_win->frame_y + tmp_win->frame_height; /*SNUG*/ inited = 1; /*SNUG*/ if (inited) /*SNUG*/ { /*SNUG*/ int dx,dy; /*SNUG*/ dx = 0; /*SNUG*/ if (left-right < Scr->MyDisplayWidth) /*SNUG*/ { /*SNUG*/ if (right<0) /*SNUG*/ dx = right; /*SNUG*/ else if (left>Scr->MyDisplayWidth) /*SNUG*/ dx = left - Scr->MyDisplayWidth; /*SNUG*/ } /*SNUG*/ /*SNUG*/ dy = 0; /*SNUG*/ if (down-up < Scr->MyDisplayHeight) /*SNUG*/ { /*SNUG*/ if (up<0) /*SNUG*/ dy = up; /*SNUG*/ else if (down>Scr->MyDisplayHeight) /*SNUG*/ dy = down - Scr->MyDisplayHeight; /*SNUG*/ } /*SNUG*/ /*SNUG*/ if (dx!=0 || dy!=0) /*SNUG*/ PanRealScreen(dx,dy,NULL,NULL); /*SNUG*/ /* DSE */ /*SNUG*/ else /*SNUG*/ DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ /*SNUG*/ } /*SNUG*/ else /*SNUG*/ DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ /*SNUG*/ /*SNUG*/ break; /*SNUG*/ } /* Next four submitted by Seth Robertson - 9/9/02 */ case F_BINDBUTTONS: { int i, j; if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE; for (i = 0; i < MAX_BUTTONS+1; i++) for (j = 0; j < MOD_SIZE; j++) if (Scr->Mouse[i][C_WINDOW][j].func != F_NOFUNCTION) XGrabButton(dpy, i, j, tmp_win->frame, True, ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, None, Scr->FrameCursor); break; } case F_BINDKEYS: { FuncKey *tmp; if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE; for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next) if (tmp->cont == C_WINDOW) /* djhjr - 9/10/03 XGrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->w, True, GrabModeAsync, GrabModeAsync); */ GrabModKeys(tmp_win->w, tmp); break; } case F_UNBINDBUTTONS: { int i, j; if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE; for (i = 0; i < MAX_BUTTONS+1; i++) for (j = 0; j < MOD_SIZE; j++) if (Scr->Mouse[i][C_WINDOW][j].func != F_NOFUNCTION) XUngrabButton(dpy, i, j, tmp_win->frame); break; } case F_UNBINDKEYS: { FuncKey *tmp; if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE; for (tmp = Scr->FuncKeyRoot.next; tmp != NULL; tmp = tmp->next) if (tmp->cont == C_WINDOW) /* djhjr - 9/10/03 XUngrabKey(dpy, tmp->keycode, tmp->mods, tmp_win->w); */ UngrabModKeys(tmp_win->w, tmp); break; } case F_MOVESCREEN: /* * Breaks badly if not called by the default button press. */ { long releaseEvent = ButtonRelease; long movementMask = ButtonMotionMask; #ifndef NO_SOUND_SUPPORT int did_playsound = FALSE; #endif StartMoveWindowInDesktop(eventp->xmotion); while (TRUE) { /* added exposure event masks - djhjr - 10/11/01 */ XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | ExposureMask | VisibilityChangeMask | movementMask, &Event); /* * Don't discard exposure events before release * or window borders and/or their titles in the * virtual desktop won't get redrawn - djhjr */ /* discard any extra motion events before a release */ if (Event.type == MotionNotify) { /* was 'ButtonMotionMask' - djhjr - 10/11/01 */ while (XCheckMaskEvent(dpy, releaseEvent | movementMask, &Event)) { if (Event.type == releaseEvent) break; } } if (Event.type == releaseEvent) { EndMoveWindowOnDesktop(); break; } if (!DispatchEvent()) continue; if (Event.type != MotionNotify) continue; #ifndef NO_SOUND_SUPPORT if (did_playsound == FALSE) { PlaySound(func); did_playsound = TRUE; } #endif DoMoveWindowOnDesktop(Event.xmotion.x, Event.xmotion.y); } /* discard queued enter and leave events */ while (XCheckMaskEvent(dpy, EnterWindowMask | LeaveWindowMask, &Event)) ; /* will clear the XGrabPointer() in events.c:HandleButtonPress() */ ButtonPressed = -1; break; } case F_SNAP: SnapRealScreen(); /* and update the data structures */ SetRealScreen(Scr->VirtualDesktopX, Scr->VirtualDesktopY); break; case F_SNAPREALSCREEN: Scr->snapRealScreen = ! Scr->snapRealScreen; break; /* djhjr - 12/14/98 */ case F_STATICICONPOSITIONS: Scr->StaticIconPositions = ! Scr->StaticIconPositions; break; /* djhjr - 12/14/98 */ case F_STRICTICONMGR: { TwmWindow *t; Scr->StrictIconManager = ! Scr->StrictIconManager; if (Scr->StrictIconManager) { for (t = Scr->TwmRoot.next; t != NULL; t = t->next) if (!t->icon) RemoveIconManager(t); } else { for (t = Scr->TwmRoot.next; t != NULL; t = t->next) if (!t->list) AddIconManager(t); } break; } case F_SETREALSCREEN: { int newx = Scr->VirtualDesktopX; int newy = Scr->VirtualDesktopY; /* parse the geometry */ JunkMask = XParseGeometry (action, &JunkX, &JunkY, &JunkWidth, &JunkHeight); if (JunkMask & XValue) newx = JunkX; if (JunkMask & YValue) newy = JunkY; if (newx < 0) newx = Scr->VirtualDesktopWidth + newx; if (newy < 0) newy = Scr->VirtualDesktopHeight + newy; SetRealScreen(newx, newy); break; } case F_HIDEDESKTOP: if (Scr->Virtual) XUnmapWindow(dpy, Scr->VirtualDesktopDisplayTwin->frame); break; case F_SHOWDESKTOP: if (Scr->Virtual) { XMapWindow(dpy, Scr->VirtualDesktopDisplayTwin->frame); /* djhjr - 9/14/96 */ if (Scr->VirtualDesktopDisplayTwin->icon) DeIconify(Scr->VirtualDesktopDisplayTwin); } break; case F_ENTERDOOR: { TwmDoor *d; if (XFindContext(dpy, tmp_win->w, DoorContext, (caddr_t *) &d) != XCNOENT) door_enter(tmp_win->w, d); break; } case F_DELETEDOOR: { /*marcel@duteca.et.tudelft.nl*/ TwmDoor *d; if (DeferExecution(context, func, Scr->DestroyCursor)) return TRUE; /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT /* flag for the handler */ if (PlaySound(func)) destroySoundFromFunction = TRUE; #endif if (XFindContext(dpy, tmp_win->w, DoorContext, (caddr_t *) &d) != XCNOENT) { /* for some reason, we don't get the button up event - djhjr - 5/13/99 */ ButtonPressed = -1; door_delete(tmp_win->w, d); } break; } case F_NEWDOOR: PopDownMenu(); door_new(); break; /* djhjr - 4/20/98 */ case F_NAMEDOOR: { TwmDoor *d; if (XFindContext(dpy, tmp_win->w, DoorContext, (caddr_t *) &d) != XCNOENT) door_paste_name(tmp_win->w, d); break; } case F_QUIT: /* djhjr - 9/14/96 - it's in Done()... SetRealScreen(0,0); */ /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT if (PlaySound(func)) { /* allow time to emit */ if (Scr->PauseOnQuit) sleep(Scr->PauseOnQuit); } else PlaySoundDone(); #endif Done(); break; case F_VIRTUALGEOMETRIES: Scr->GeometriesAreVirtual = ! Scr->GeometriesAreVirtual; break; /* submitted by Ugen Antsilevitch - 5/28/00 */ case F_WARPVISIBLE: Scr->WarpVisible = ! Scr->WarpVisible; break; /* djhjr - 5/30/00 */ case F_WARPSNUG: Scr->WarpSnug = ! Scr->WarpSnug; break; /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT case F_SOUNDS: ToggleSounds(); break; /* djhjr - 11/15/02 */ case F_PLAYSOUND: PlaySoundAdhoc(action); break; #endif } if (ButtonPressed == -1) XUngrabPointer(dpy, CurrentTime); return do_next_action; } /*********************************************************************** * * Procedure: * DeferExecution - defer the execution of a function to the * next button press if the context is C_ROOT * * Inputs: * context - the context in which the mouse button was pressed * func - the function to defer * cursor - the cursor to display while waiting * *********************************************************************** */ int DeferExecution(context, func, cursor) int context, func; Cursor cursor; { if (context == C_ROOT) { LastCursor = cursor; XGrabPointer(dpy, Scr->Root, True, ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, Scr->Root, cursor, CurrentTime); RootFunction = func; Action = actionHack; /* Submitted by Michel Eyckmans */ return (TRUE); } return (FALSE); } /*********************************************************************** * * Procedure: * ReGrab - regrab the pointer with the LastCursor; * *********************************************************************** */ void ReGrab() { XGrabPointer(dpy, Scr->Root, True, ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, Scr->Root, LastCursor, CurrentTime); } /*********************************************************************** * * Procedure: * NeedToDefer - checks each function in the list to see if it * is one that needs to be defered. * * Inputs: * root - the menu root to check * *********************************************************************** */ /* was of type 'int' - Submitted by Michel Eyckmans */ Cursor NeedToDefer(root) MenuRoot *root; { MenuItem *mitem; for (mitem = root->first; mitem != NULL; mitem = mitem->next) { switch (mitem->func) { case F_RESIZE: return Scr->ResizeCursor; /* Submitted by Michel Eyckmans */ case F_MOVE: case F_FORCEMOVE: return Scr->MoveCursor; /* Submitted by Michel Eyckmans */ /* these next four - Submitted by Michel Eyckmans */ case F_DELETE: case F_DELETEDOOR: case F_DESTROY: return Scr->DestroyCursor; case F_IDENTIFY: /* was with 'F_RESIZE' - Submitted by Michel Eyckmans */ case F_DEICONIFY: case F_ICONIFY: case F_RAISELOWER: case F_RAISE: case F_LOWER: case F_FOCUS: case F_WINREFRESH: case F_ZOOM: case F_FULLZOOM: case F_HORIZOOM: case F_RIGHTZOOM: case F_LEFTZOOM: case F_TOPZOOM: case F_BOTTOMZOOM: case F_AUTORAISE: case F_NAIL: case F_SNUGWINDOW: return Scr->SelectCursor; } } return None; } void Execute(s) char *s; { static char buf[256]; char *ds = DisplayString (dpy); char *colon, *dot1; char oldDisplay[256]; char *doisplay; int restorevar = 0; char *append_this = " &"; char *es = (char *)malloc(strlen(s)+strlen(append_this)+1); sprintf(es,s); /* a new copy of s, with extra space incase -- DSE */ if (Scr->EnhancedExecResources) /* DSE */ { /* chop all space characters from the end of the string */ while ( isspace ( es[strlen(es)-1] ) ) { es[strlen(es)-1] = '\0'; } switch ( es[strlen(es)-1] ) /* last character */ { case ';': es[strlen(es)-1] = '\0'; /* remove the semicolon */ break; case '&': /* already there so do nothing */ break; default: strcat(es,append_this); /* don't block the window manager */ break; } } oldDisplay[0] = '\0'; doisplay=getenv("DISPLAY"); if (doisplay) strcpy (oldDisplay, doisplay); /* * Build a display string using the current screen number, so that * X programs which get fired up from a menu come up on the screen * that they were invoked from, unless specifically overridden on * their command line. */ colon = rindex (ds, ':'); if (colon) { /* if host[:]:dpy */ strcpy (buf, "DISPLAY="); strcat (buf, ds); colon = buf + 8 + (colon - ds); /* use version in buf */ dot1 = index (colon, '.'); /* first period after colon */ if (!dot1) dot1 = colon + strlen (colon); /* if not there, append */ (void) sprintf (dot1, ".%d", Scr->screen); putenv (buf); restorevar = 1; } (void) system (es); /* DSE */ free (es); /* DSE */ if (restorevar) { /* why bother? */ (void) sprintf (buf, "DISPLAY=%s", oldDisplay); putenv (buf); } } /*********************************************************************** * * Procedure: * FocusOnRoot - put input focus on the root window * *********************************************************************** */ void FocusOnRoot() { SetFocus ((TwmWindow *) NULL, LastTimestamp()); if (Scr->Focus != NULL) { SetBorder (Scr->Focus, False); /* djhjr - 4/25/96 if (Scr->Focus->hilite_w) XUnmapWindow (dpy, Scr->Focus->hilite_w); */ PaintTitleHighlight(Scr->Focus, off); } InstallWindowColormaps(0, &Scr->TwmRoot); Scr->Focus = NULL; Scr->FocusRoot = TRUE; } void DeIconify(tmp_win) TwmWindow *tmp_win; { TwmWindow *t; /* * De-iconify the main window first */ /* re-vamped the zoom stuff - djhjr - 10/11/01 */ if (Scr->DoZoom && Scr->ZoomCount > 0) { IconMgr *ipf = NULL; Window wt = None, wf = None; if (tmp_win->icon) { if (tmp_win->icon_on) { wf = tmp_win->icon_w; wt = tmp_win->frame; } else if (tmp_win->list) /* djhjr - 10/11/01 */ { wf = tmp_win->list->w; wt = tmp_win->frame; ipf = tmp_win->list->iconmgr; } else if (tmp_win->group != None) { for (t = Scr->TwmRoot.next; t != NULL; t = t->next) if (tmp_win->group == t->w) { if (t->icon_on) wf = t->icon_w; else if (t->list) /* djhjr - 10/11/01 */ { wf = t->list->w; ipf = t->list->iconmgr; } wt = tmp_win->frame; break; } } } /* added Zoom()s args to iconmgrs - djhjr - 10/11/01 */ if (Scr->ZoomZoom || (wf != None && wt != None)) Zoom(wf, ipf, wt, NULL); /* RFBZOOM */ } XMapWindow(dpy, tmp_win->w); tmp_win->mapped = TRUE; if (Scr->NoRaiseDeicon) XMapWindow(dpy, tmp_win->frame); else { XMapRaised(dpy, tmp_win->frame); XRaiseWindow(dpy, tmp_win->VirtualDesktopDisplayWindow); } SetMapStateProp(tmp_win, NormalState); if (tmp_win->icon_w) { XUnmapWindow(dpy, tmp_win->icon_w); IconDown (tmp_win); } tmp_win->icon = FALSE; tmp_win->icon_on = FALSE; if (tmp_win->list) XUnmapWindow(dpy, tmp_win->list->icon); /* * RemoveIconManager() done in events.c:HandleMapNotify() */ UpdateDesktop(tmp_win); /* * Now de-iconify transients */ for (t = Scr->TwmRoot.next; t != NULL; t = t->next) { if (t->transient && t->transientfor == tmp_win->w) { /* this 'if (...) else' (see also Iconify()) - djhjr - 6/22/99 */ if (Scr->DontDeiconifyTransients && t->icon_w && t->icon == TRUE && t->icon_on == FALSE) { IconUp(t); XMapRaised(dpy, t->icon_w); t->icon_on = TRUE; } else { /* added Zoom()s args to iconmgrs - djhjr - 10/11/01 */ if (t->icon_on) Zoom(t->icon_w, NULL, t->frame, NULL); else Zoom(tmp_win->icon_w, NULL, t->frame, NULL); XMapWindow(dpy, t->w); t->mapped = TRUE; if (Scr->NoRaiseDeicon) XMapWindow(dpy, t->frame); else { XMapRaised(dpy, t->frame); XRaiseWindow(dpy, t->VirtualDesktopDisplayWindow); } SetMapStateProp(t, NormalState); if (t->icon_w) { XUnmapWindow(dpy, t->icon_w); IconDown (t); } t->icon = FALSE; t->icon_on = FALSE; if (t->list) XUnmapWindow(dpy, t->list->icon); /* * RemoveIconManager() done in events.c:HandleMapNotify() */ UpdateDesktop(t); } } } RaiseStickyAbove(); /* DSE */ RaiseAutoPan(); /* * added '&& Scr->WarpWindows'. * see the kludge in ExecuteFunction(F_ICONIFY, ...). * djhjr - 1/24/98 */ if (((Scr->WarpCursor || LookInList(Scr->WarpCursorL, tmp_win->full_name, &tmp_win->class)) && tmp_win->icon) && Scr->WarpWindows) WarpToWindow (tmp_win); XSync (dpy, 0); } void Iconify(tmp_win, def_x, def_y) TwmWindow *tmp_win; int def_x, def_y; { TwmWindow *t; int iconify; XWindowAttributes winattrs; unsigned long eventMask; /* djhjr - 6/22/99 */ short fake_icon; iconify = ((!tmp_win->iconify_by_unmapping) || tmp_win->transient); if (iconify) { if (tmp_win->icon_w == None) CreateIconWindow(tmp_win, def_x, def_y); else IconUp(tmp_win); XMapRaised(dpy, tmp_win->icon_w); RaiseStickyAbove(); /* DSE */ RaiseAutoPan(); } XGetWindowAttributes(dpy, tmp_win->w, &winattrs); eventMask = winattrs.your_event_mask; /* * Iconify transients first */ for (t = Scr->TwmRoot.next; t != NULL; t = t->next) { if (t->transient && t->transientfor == tmp_win->w) { /* RemoveFromDesktop(t); Stig */ /* * Prevent the receipt of an UnmapNotify, since that would * cause a transition to the Withdrawn state. */ t->mapped = FALSE; XSelectInput(dpy, t->w, eventMask & ~StructureNotifyMask); XUnmapWindow(dpy, t->w); XSelectInput(dpy, t->w, eventMask); XUnmapWindow(dpy, t->frame); /* moved to make zooms more aesthetically pleasing -- DSE */ if (iconify) { /* added Zoom()s args to iconmgrs - djhjr - 10/11/01 */ if (t->icon_on) Zoom(t->icon_w, NULL, tmp_win->icon_w, NULL); else Zoom(t->frame, NULL, tmp_win->icon_w, NULL); } if (t->icon_w) XUnmapWindow(dpy, t->icon_w); SetMapStateProp(t, IconicState); SetBorder (t, False); if (t == Scr->Focus) { SetFocus ((TwmWindow *) NULL, LastTimestamp()); Scr->Focus = NULL; Scr->FocusRoot = TRUE; } /* * let current status ride, but "fake out" UpdateDesktop() * (see also DeIconify()) - djhjr - 6/22/99 */ fake_icon = t->icon; t->icon = TRUE; t->icon_on = FALSE; /* djhjr - 10/2/01 */ if (Scr->StrictIconManager) if (!t->list) AddIconManager(t); if (t->list) XMapWindow(dpy, t->list->icon); UpdateDesktop(t); /* restore icon status - djhjr - 6/22/99 */ t->icon = fake_icon; } } /* * Now iconify the main window */ /* if (iconify) RFBZOOM*/ /* RemoveFromDesktop(tmp_win); Stig */ /* * Prevent the receipt of an UnmapNotify, since that would * cause a transition to the Withdrawn state. */ tmp_win->mapped = FALSE; XSelectInput(dpy, tmp_win->w, eventMask & ~StructureNotifyMask); XUnmapWindow(dpy, tmp_win->w); XSelectInput(dpy, tmp_win->w, eventMask); XUnmapWindow(dpy, tmp_win->frame); SetMapStateProp(tmp_win, IconicState); SetBorder (tmp_win, False); if (tmp_win == Scr->Focus) { SetFocus ((TwmWindow *) NULL, LastTimestamp()); Scr->Focus = NULL; Scr->FocusRoot = TRUE; } tmp_win->icon = TRUE; if (iconify) tmp_win->icon_on = TRUE; else tmp_win->icon_on = FALSE; /* djhjr - 10/2/01 */ if (Scr->StrictIconManager) if (!tmp_win->list) AddIconManager(tmp_win); /* moved to make zooms more aesthetically pleasing -- DSE */ /* moved again to ensure an icon manager entry exists - djhjr - 10/11/01 */ /* added Zoom()s args to iconmgrs - djhjr - 10/11/01 */ if (iconify) Zoom(tmp_win->frame, NULL, tmp_win->icon_w, NULL); else if (tmp_win->list) /* djhjr - 10/11/01 */ Zoom(tmp_win->frame, NULL, tmp_win->list->w, tmp_win->list->iconmgr); if (tmp_win->list) XMapWindow(dpy, tmp_win->list->icon); UpdateDesktop(tmp_win); XSync (dpy, 0); } static void Identify (t) TwmWindow *t; { int i, n, twidth, width, height; int x, y; unsigned int wwidth, wheight, bw, depth; Window junk; int px, py, dummy; unsigned udummy; /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT PlaySound(F_IDENTIFY); #endif n = 0; (void) sprintf(Info[n++], "%s", Version); Info[n++][0] = '\0'; if (t) { XGetGeometry (dpy, t->w, &JunkRoot, &JunkX, &JunkY, &wwidth, &wheight, &bw, &depth); (void) XTranslateCoordinates (dpy, t->w, Scr->Root, 0, 0, &x, &y, &junk); /* looks bad with variable fonts... djhjr - 5/10/96 (void) sprintf(Info[n++], "Name = \"%s\"", t->full_name); (void) sprintf(Info[n++], "Class.res_name = \"%s\"", t->class.res_name); (void) sprintf(Info[n++], "Class.res_class = \"%s\"", t->class.res_class); Info[n++][0] = '\0'; (void) sprintf(Info[n++], "Geometry/root = %dx%d+%d+%d", wwidth, wheight, x, y); (void) sprintf(Info[n++], "Border width = %d", bw); (void) sprintf(Info[n++], "Depth = %d", depth); */ (void) sprintf(Info[n++], "Name: \"%s\"", t->full_name); (void) sprintf(Info[n++], "Class.res_name: \"%s\"", t->class.res_name); (void) sprintf(Info[n++], "Class.res_class: \"%s\"", t->class.res_class); Info[n++][0] = '\0'; (void) sprintf(Info[n++], "Geometry/root: %dx%d+%d+%d", wwidth, wheight, x, y); (void) sprintf(Info[n++], "Border width: %d", bw); (void) sprintf(Info[n++], "Depth: %d", depth); Info[n++][0] = '\0'; } /* djhjr - 9/19/96 */ #ifndef NO_BUILD_INFO else { char is_m4, is_xpm; char is_rplay; /* djhjr - 6/22/01 */ char is_regex; /* djhjr - 10/20/01 */ char is_i18n; /* djhjr - 10/20/01 */ /* djhjr - 6/22/99 */ #ifdef WE_REALLY_DO_WANT_TO_SEE_THIS (void) sprintf(Info[n++], "X Server: %s Version %d.%d Release %d", ServerVendor(dpy), ProtocolVersion(dpy), ProtocolRevision(dpy), VendorRelease(dpy)); #endif /* * Was a 'do ... while()' that accessed unallocated memory. * This and the change to Imakefile submitted by Takeharu Kato */ i = 0; while (lastmake[i][0] != '\0') (void) sprintf(Info[n++], "%s", lastmake[i++]); /* djhjr - 1/31/99 */ #ifdef NO_M4_SUPPORT is_m4 = '-'; #else is_m4 = '+'; #endif #ifdef NO_XPM_SUPPORT is_xpm = '-'; #else is_xpm = '+'; #endif /* djhjr - 6/22/01 */ #ifdef NO_SOUND_SUPPORT is_rplay = '-'; #else is_rplay = '+'; #endif /* djhjr - 6/22/01 */ #ifdef NO_REGEX_SUPPORT is_regex = '-'; #else is_regex = '+'; #endif /* djhjr - 9/14/03 */ #ifdef NO_I18N_SUPPORT is_i18n = '-'; #else is_i18n = '+'; #endif (void) sprintf(Info[n++], "Options: %ci18n %cm4 %cregex %crplay %cxpm", is_i18n, is_m4, is_regex, is_rplay, is_xpm); Info[n++][0] = '\0'; } #endif (void) sprintf(Info[n++], "Click to dismiss..."); /* figure out the width and height of the info window */ /* djhjr - 4/29/98 height = (n * (Scr->InfoFont.height+2)) + 10; * some padding * */ /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */ i = (Scr->InfoBevelWidth > 0) ? Scr->InfoBevelWidth + 8 : 10; height = (n * (Scr->InfoFont.height+2)) + i; /* some padding */ width = 1; for (i = 0; i < n; i++) { /* djhjr - 9/14/03 */ #ifndef NO_I18N_SUPPORT twidth = MyFont_TextWidth(&Scr->InfoFont, #else twidth = XTextWidth(Scr->InfoFont.font, #endif Info[i], strlen(Info[i])); if (twidth > width) width = twidth; } if (InfoLines) XUnmapWindow(dpy, Scr->InfoWindow); /* djhjr - 4/29/98 width += 20; * some padding * */ /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */ i = (Scr->InfoBevelWidth > 0) ? Scr->InfoBevelWidth + 18 : 20; width += i; /* some padding */ if (XQueryPointer (dpy, Scr->Root, &JunkRoot, &JunkChild, &px, &py, &dummy, &dummy, &udummy)) { px -= (width / 2); py -= (height / 3); /* added this 'if ()' - djhjr - 4/29/98 */ /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */ if (Scr->InfoBevelWidth > 0) { if (px + width + 2 * Scr->InfoBevelWidth >= Scr->MyDisplayWidth) px = Scr->MyDisplayWidth - width - 2 * Scr->InfoBevelWidth; if (py + height + 2 * Scr->InfoBevelWidth >= Scr->MyDisplayHeight) py = Scr->MyDisplayHeight - height - 2 * Scr->InfoBevelWidth; } else { if (px + width + BW2 >= Scr->MyDisplayWidth) px = Scr->MyDisplayWidth - width - BW2; if (py + height + BW2 >= Scr->MyDisplayHeight) py = Scr->MyDisplayHeight - height - BW2; } if (px < 0) px = 0; if (py < 0) py = 0; } else { px = py = 0; } XMoveResizeWindow(dpy, Scr->InfoWindow, px, py, width, height); /* done in HandleExpose() in events.c - djhjr - 4/30/98 */ #ifdef NEVER /* djhjr - 5/9/96 */ if (Scr->use3Dborders > 0) { XGetGeometry (dpy, Scr->InfoWindow, &JunkRoot, &JunkX, &JunkY, &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth); Draw3DBorder(Scr->InfoWindow, 0, 0, JunkWidth, JunkHeight, /* djhjr - 4/29/98 BW, Scr->DefaultC, off, False, False); */ Scr->InfoBevelWidth, Scr->DefaultC, off, False, False); } #endif XMapRaised(dpy, Scr->InfoWindow); InfoLines = n; } void SetMapStateProp(tmp_win, state) TwmWindow *tmp_win; int state; { unsigned long data[2]; /* "suggested" by ICCCM version 1 */ data[0] = (unsigned long) state; data[1] = (unsigned long) (tmp_win->iconify_by_unmapping ? None : tmp_win->icon_w); XChangeProperty (dpy, tmp_win->w, _XA_WM_STATE, _XA_WM_STATE, 32, PropModeReplace, (unsigned char *) data, 2); } Bool GetWMState (w, statep, iwp) Window w; int *statep; Window *iwp; { Atom actual_type; int actual_format; unsigned long nitems, bytesafter; unsigned long *datap = NULL; Bool retval = False; /* used to test for '!datap' - djhjr - 1/10/98 */ if (XGetWindowProperty (dpy, w, _XA_WM_STATE, 0L, 2L, False, _XA_WM_STATE, &actual_type, &actual_format, &nitems, &bytesafter, (unsigned char **) &datap) != Success || actual_type == None) return False; if (nitems <= 2) { /* "suggested" by ICCCM version 1 */ *statep = (int) datap[0]; *iwp = (Window) datap[1]; retval = True; } XFree ((char *) datap); return retval; } /* * BumpWindowColormap - rotate our internal copy of WM_COLORMAP_WINDOWS */ void BumpWindowColormap (tmp, inc) TwmWindow *tmp; int inc; { int i, j, previously_installed; ColormapWindow **cwins; if (!tmp) return; if (inc && tmp->cmaps.number_cwins > 0) { cwins = (ColormapWindow **) malloc(sizeof(ColormapWindow *)* tmp->cmaps.number_cwins); if (cwins) { if ((previously_installed = (Scr->cmapInfo.cmaps == &tmp->cmaps) && tmp->cmaps.number_cwins)) { for (i = tmp->cmaps.number_cwins; i-- > 0; ) tmp->cmaps.cwins[i]->colormap->state = 0; } for (i = 0; i < tmp->cmaps.number_cwins; i++) { j = i - inc; if (j >= tmp->cmaps.number_cwins) j -= tmp->cmaps.number_cwins; else if (j < 0) j += tmp->cmaps.number_cwins; cwins[j] = tmp->cmaps.cwins[i]; } free((char *) tmp->cmaps.cwins); tmp->cmaps.cwins = cwins; if (tmp->cmaps.number_cwins > 1) memset( tmp->cmaps.scoreboard, 0, ColormapsScoreboardLength(&tmp->cmaps)); if (previously_installed) InstallWindowColormaps(PropertyNotify, (TwmWindow *) NULL); } } else FetchWmColormapWindows (tmp); } void HideIconManager(tmp_win) TwmWindow *tmp_win; { /* added this 'if (...) else ...' - djhjr - 9/21/99 */ if (tmp_win == NULL) { name_list *list; HideIconMgr(&Scr->iconmgr); /* * New code in list.c necessitates 'next_entry()' and * 'contents_of_entry()' - djhjr - 10/20/01 */ for (list = Scr->IconMgrs; list != NULL; list = next_entry(list)) HideIconMgr((IconMgr *)contents_of_entry(list)); } else { IconMgr *ip; if ((ip = (IconMgr *)LookInList(Scr->IconMgrs, tmp_win->full_name, &tmp_win->class)) == NULL) ip = &Scr->iconmgr; HideIconMgr(ip); } } /* djhjr - 9/21/99 */ void HideIconMgr(ip) IconMgr *ip; { /* djhjr - 6/10/98 */ if (ip->count == 0) return; SetMapStateProp (ip->twm_win, WithdrawnState); XUnmapWindow(dpy, ip->twm_win->frame); if (ip->twm_win->icon_w) XUnmapWindow (dpy, ip->twm_win->icon_w); ip->twm_win->mapped = FALSE; ip->twm_win->icon = TRUE; } /* djhjr - 9/21/99 */ void ShowIconMgr(ip) IconMgr *ip; { /* added the second condition - djhjr - 6/10/98 */ if (Scr->NoIconManagers || ip->count == 0) return; DeIconify(ip->twm_win); XRaiseWindow(dpy, ip->twm_win->frame); XRaiseWindow(dpy, ip->twm_win->VirtualDesktopDisplayWindow); } void SetBorder (tmp, onoroff) TwmWindow *tmp; Bool onoroff; { if (tmp->highlight) { /* djhjr - 4/22/96 */ /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */ if (Scr->BorderBevelWidth > 0) PaintBorders (tmp, onoroff); else { if (onoroff) { /* djhjr - 4/24/96 XSetWindowBorder (dpy, tmp->frame, tmp->border); */ /* djhjr - 11/17/97 XSetWindowBorder (dpy, tmp->frame, tmp->border_tile.back); */ XSetWindowBorder (dpy, tmp->frame, tmp->border.back); if (tmp->title_w) /* djhjr - 4/24/96 XSetWindowBorder (dpy, tmp->title_w, tmp->border); */ /* djhjr - 11/17/97 XSetWindowBorder (dpy, tmp->title_w, tmp->border_tile.back); */ XSetWindowBorder (dpy, tmp->title_w, tmp->border.back); } else { XSetWindowBorderPixmap (dpy, tmp->frame, tmp->gray); if (tmp->title_w) XSetWindowBorderPixmap (dpy, tmp->title_w, tmp->gray); } } /* djhjr - 11/17/97 */ /* rem'd out test for button color - djhjr - 9/15/99 */ if (/*Scr->ButtonColorIsFrame && */tmp->titlebuttons) { int i, nb = Scr->TBInfo.nleft + Scr->TBInfo.nright; TBWindow *tbw; /* collapsed two functions - djhjr - 8/10/98 */ for (i = 0, tbw = tmp->titlebuttons; i < nb; i++, tbw++) PaintTitleButton(tmp, tbw, (onoroff) ? 2 : 1); } } } void DestroyMenu (menu) MenuRoot *menu; { MenuItem *item; if (menu->w) { XDeleteContext (dpy, menu->w, MenuContext); XDeleteContext (dpy, menu->w, ScreenContext); if (Scr->Shadow) XDestroyWindow (dpy, menu->shadow); XDestroyWindow(dpy, menu->w); } for (item = menu->first; item; ) { MenuItem *tmp = item; item = item->next; free ((char *) tmp); } } /* * warping routines */ /* for moves and resizes from center - djhjr - 10/4/02 */ void WarpScreenToWindow(t) TwmWindow *t; { int warpwin = Scr->WarpWindows; int warpsnug = Scr->WarpSnug; Scr->WarpWindows = Scr->WarpSnug = FALSE; WarpToWindow(t); Scr->WarpWindows = warpwin; Scr->WarpSnug = warpsnug; /* * This is an attempt to have windows redraw themselves, but * it doesn't always work (non-raising windows in particular). */ XSync(dpy, 0); } /* was in-lined in WarpToWindow() - djhjr - 5/30/00 */ void WarpWindowOrScreen(t) TwmWindow *t; { /* * we are either moving the window onto the screen, or the screen to the * window, the distances remain the same */ if ((t->frame_x < Scr->MyDisplayWidth) && (t->frame_y < Scr->MyDisplayHeight) && (t->frame_x + t->frame_width >= 0) && (t->frame_y + t->frame_height >= 0)) { /* * window is visible; you can simply * snug it if WarpSnug or WarpWindows is set -- DSE */ if (Scr->WarpSnug || Scr->WarpWindows) { int right,left,up,down,dx,dy; /* * Adjustment for border widths submitted by Steve Ratcliffe * Note: Do not include the 3D border width! */ right = t->frame_x; left = t->frame_x + t->frame_width + 2 * t->frame_bw; up = t->frame_y; down = t->frame_y + t->frame_height + 2 * t->frame_bw; dx = 0; if (left-right < Scr->MyDisplayWidth) { if (right<0) dx = right; else if (left>Scr->MyDisplayWidth) dx = left - Scr->MyDisplayWidth; } dy = 0; if (down-up < Scr->MyDisplayHeight) { if (up<0) dy = up; else if (down>Scr->MyDisplayHeight) dy = down - Scr->MyDisplayHeight; } if (dx!=0 || dy!=0) { /* added 'Scr->WarpSnug ||' - djhjr - 5/30/00 */ if (Scr->WarpSnug || Scr->WarpWindows) { /* move the window */ VirtualMoveWindow(t, t->virtual_frame_x - dx, t->virtual_frame_y - dy); } else { /* move the screen */ PanRealScreen(dx,dy,NULL,NULL); } } } } else { /* * Window is invisible; we need to move it or the screen. */ int xdiff, ydiff; xdiff = ((Scr->MyDisplayWidth - t->frame_width) / 2) - t->frame_x; ydiff = ((Scr->MyDisplayHeight - t->frame_height) / 2) - t->frame_y; /* added 'Scr->WarpSnug ||' - djhjr - 5/30/00 */ if (Scr->WarpSnug || Scr->WarpWindows) { /* move the window */ VirtualMoveWindow(t, t->virtual_frame_x + xdiff, t->virtual_frame_y + ydiff); } else { /* move the screen */ PanRealScreen(-xdiff, -ydiff,NULL,NULL); /* DSE */ } } if (t->auto_raise || !Scr->NoRaiseWarp) AutoRaiseWindow (t); } /* for icon manager management - djhjr - 5/30/00 */ void WarpInIconMgr(w, t) WList *w; TwmWindow *t; { int x, y, pan_margin = 0; /* djhjr - 9/9/02 */ int bw = t->frame_bw3D + t->frame_bw; RaiseStickyAbove(); RaiseAutoPan(); WarpWindowOrScreen(t); /* was 'Scr->BorderWidth' - djhjr - 9/9/02 */ x = w->x + bw + EDGE_OFFSET + 5; x += (Scr->IconMgrBevelWidth > 0) ? Scr->IconMgrBevelWidth : bw; y = w->y + bw + w->height / 2; y += (Scr->IconMgrBevelWidth > 0) ? Scr->IconMgrBevelWidth : bw; y += w->iconmgr->twm_win->title_height; /* * adjust the pointer for partially visible windows and the * AutoPan border width */ if (Scr->AutoPanX) pan_margin = Scr->AutoPanBorderWidth; if (x + t->frame_x >= Scr->MyDisplayWidth - pan_margin) x = Scr->MyDisplayWidth - t->frame_x - pan_margin - 2; if (x + t->frame_x <= pan_margin) x = -t->frame_x + pan_margin + 2; if (y + t->frame_y >= Scr->MyDisplayHeight - pan_margin) y = Scr->MyDisplayHeight - t->frame_y - pan_margin - 2; if (y + t->frame_y <= pan_margin) y = -t->frame_y + pan_margin + 2; XWarpPointer(dpy, None, t->frame, 0, 0, 0, 0, x, y); /* DSE */ } /* * substantially re-written and added passing 'next' to next_by_class() * * djhjr - 5/13/98 6/6/98 6/15/98 */ #ifdef ORIGINAL_WARPCLASS void WarpClass (next, t, class) int next; TwmWindow *t; char *class; { int len = strlen(class); if (!strncmp(class, t->class.res_class, len)) t = next_by_class(t, class); else t = next_by_class((TwmWindow *)NULL, class); if (t) { if (Scr->WarpUnmapped || t->mapped) { if (!t->mapped) DeIconify (t); if (!Scr->NoRaiseWarp) { XRaiseWindow (dpy, t->frame); } XRaiseWindow (dpy, t->VirtualDesktopDisplayWindow); RaiseStickyAbove(); /* DSE */ RaiseAutoPan(); WarpToWindow (t); } } } #else /* ORIGINAL_WARPCLASS */ void WarpClass(next, t, class) int next; TwmWindow *t; char *class; { TwmWindow *tt; XClassHint ch; int i; /* * if an empty class string * if a TwmWindow * class = the TwmWindow's class * else if a window with focus * if it's classed * class = the focused window's class * else * return * if still an empty class string * class = "VTWM" */ if (!strlen(class)) { if (t) class = t->class.res_class; else if (Scr->Focus) { i = XGetClassHint(dpy, Scr->Focus->w, &ch); if (i && !strncmp(class, ch.res_class, strlen(class))) class = ch.res_class; } /* djhjr - 6/21/00 */ else { DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ return; } } if (!strlen(class) || !strncmp(class, "VTWM", 4)) class = "VTWM"; /* djhjr - 8/3/98 if (!(tt = next_by_class(next, t, class))) if (t) tt = t; */ /* djhjr - 5/28/00 */ while (1) { tt = NULL; do { if ((tt = next_by_class(next, t, class))) { /* multiple icon managers: gotta test for those without entries */ if (tt->iconmgr && tt->iconmgrp->count == 0) { t = tt; tt = NULL; } } else if (t) tt = t; else break; } while (!tt); /* added the second argument - djhjr - 5/28/00 */ if (tt && warp_if_warpunmapped(tt, (next) ? F_WARPCLASSNEXT: F_WARPCLASSPREV)) { RaiseStickyAbove(); /* DSE */ RaiseAutoPan(); /* djhjr - 6/3/03 */ #ifndef NO_SOUND_SUPPORT PlaySound((next) ? F_WARPCLASSNEXT: F_WARPCLASSPREV); #endif WarpToWindow(tt); /* djhjr - 5/28/00 */ break; } /* djhjr - 5/28/00 else XBell(dpy, 0); */ t = tt; } /* while (1) */ } #endif /* ORIGINAL_WARPCLASS */ /* moved from add_window.c - djhjr - 10/27/02 */ void AddWindowToRing(tmp_win) TwmWindow *tmp_win; { if (Scr->Ring) { /* link window in after Scr->Ring */ tmp_win->ring.prev = Scr->Ring; tmp_win->ring.next = Scr->Ring->ring.next; /* Scr->Ring's next's prev points to this */ /*if (Scr->Ring->ring.next->ring.prev)*/ Scr->Ring->ring.next->ring.prev = tmp_win; /* Scr->Ring's next points to this */ Scr->Ring->ring.next = tmp_win; } else tmp_win->ring.next = tmp_win->ring.prev = Scr->Ring = tmp_win; } /* moved from events.c - djhjr - 10/27/02 */ void RemoveWindowFromRing(tmp_win) TwmWindow *tmp_win; { /* unlink window */ if (tmp_win->ring.prev) tmp_win->ring.prev->ring.next = tmp_win->ring.next; if (tmp_win->ring.next) tmp_win->ring.next->ring.prev = tmp_win->ring.prev; /* if window was only thing in ring, null out ring */ if (Scr->Ring == tmp_win) Scr->Ring = (tmp_win->ring.next != tmp_win) ? tmp_win->ring.next : (TwmWindow *)NULL; /* if window was ring leader, set to next (or null) */ if (!Scr->Ring || Scr->RingLeader == tmp_win) Scr->RingLeader = Scr->Ring; tmp_win->ring.next = tmp_win->ring.prev = NULL; } void WarpAlongRing (ev, forward) XButtonEvent *ev; Bool forward; { TwmWindow *r, *head; /* * Re-vamped much of this to properly handle icon managers, and * clean up dumb code I added some time back. * djhjr - 11/8/01 * Cleaned it up again. I musta been high. Twice. * djhjr - 10/27/02 */ if (!(head = (Scr->RingLeader) ? Scr->RingLeader : Scr->Ring)) { DoAudible(); return; } if (forward) r = head->ring.next; else r = head->ring.prev; while (r && r != head) { if (r->mapped || warp_if_warpunmapped(r, F_WARPRING)) break; r = (forward) ? r->ring.next : r->ring.prev; } if (r && r->mapped) { #ifdef ORIGINAL_WARPRINGCOORDINATES /* djhjr - 5/11/98 */ TwmWindow *p = Scr->RingLeader, *t; #endif /* done in WarpToWindow - djhjr - 10/27/02 Scr->RingLeader = r; */ RaiseStickyAbove(); RaiseAutoPan(); /* djhjr - 6/3/03 */ #ifndef NO_SOUND_SUPPORT PlaySound(F_WARPRING); #endif WarpToWindow (r); #ifdef ORIGINAL_WARPRINGCOORDINATES /* djhjr - 5/11/98 */ if (p && p->mapped && XFindContext (dpy, ev->window, TwmContext, (caddr_t *)&t) == XCSUCCESS && p == t) { p->ring.cursor_valid = True; p->ring.curs_x = ev->x_root - t->frame_x; p->ring.curs_y = ev->y_root - t->frame_y; if (p->ring.curs_x < -p->frame_bw || p->ring.curs_x >= p->frame_width + p->frame_bw || p->ring.curs_y < -p->frame_bw || p->ring.curs_y >= p->frame_height + p->frame_bw) { /* somehow out of window */ p->ring.curs_x = p->frame_width / 2; p->ring.curs_y = p->frame_height / 2; } } #endif } else DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ } void WarpToScreen (n, inc) int n, inc; { Window dumwin; int x, y, dumint; unsigned int dummask; ScreenInfo *newscr = NULL; while (!newscr) { /* wrap around */ if (n < 0) n = NumScreens - 1; else if (n >= NumScreens) n = 0; newscr = ScreenList[n]; if (!newscr) { /* make sure screen is managed */ if (inc) { /* walk around the list */ n += inc; continue; } fprintf (stderr, "%s: unable to warp to unmanaged screen %d\n", ProgramName, n); DoAudible(); /* was 'XBell()' - djhjr - 6/22/01 */ return; } } if (Scr->screen == n) return; /* already on that screen */ PreviousScreen = Scr->screen; XQueryPointer (dpy, Scr->Root, &dumwin, &dumwin, &x, &y, &dumint, &dumint, &dummask); /* djhjr - 6/3/03 */ #ifndef NO_SOUND_SUPPORT PlaySound(F_WARPTOSCREEN); #endif XWarpPointer (dpy, None, newscr->Root, 0, 0, 0, 0, x, y); return; } void WarpToWindow (t) TwmWindow *t; { int x, y; int pan_margin = 0; /* djhjr - 5/28/00 */ int bw = t->frame_bw3D + t->frame_bw; /* djhjr - 9/9/02 */ Window w = t->frame; /* djhjr - 5/30/00 */ WarpWindowOrScreen(t); /* djhjr - 5/30/00 */ #ifdef ORIGINAL_WARPRINGCOORDINATES /* djhjr - 5/11/98 */ if (t->ring.cursor_valid) { x = t->ring.curs_x; y = t->ring.curs_y; } else { x = t->frame_width / 2; y = t->frame_height / 2; } #else /* added this 'if (...) else' - djhjr - 6/10/98 */ if (t->iconmgr) { /* djhjr - 5/30/00 if (t->iconmgrp->count > 0) XWarpPointer(dpy, None, t->iconmgrp->first->icon, 0,0,0,0, EDGE_OFFSET, EDGE_OFFSET); return; */ if (t->iconmgrp->count > 0) { w = t->iconmgrp->twm_win->frame; /* was 'Scr->BorderWidth' - djhjr - 9/9/02 */ x = t->iconmgrp->x + bw + EDGE_OFFSET + 5; x += (Scr->IconMgrBevelWidth > 0) ? Scr->IconMgrBevelWidth : bw; y = t->iconmgrp->y + bw + t->iconmgrp->first->height / 2; y += (Scr->IconMgrBevelWidth > 0) ? Scr->IconMgrBevelWidth : bw; y += t->iconmgrp->twm_win->title_height; } } else if (!t->title_w) { /* added this 'if (...) else' - djhjr - 10/16/02 */ if (Scr->WarpCentered & WARPC_UNTITLED) { x = t->frame_width / 2; y = t->frame_height / 2; } else { x = t->frame_width / 2; y = (t->wShaped) ? bw : bw / 2; /* djhjr - 9/9/02 */ } } else { /* added this 'if (...) else' - djhjr - 10/16/02 */ if (Scr->WarpCentered & WARPC_TITLED) { x = t->frame_width / 2; y = t->frame_height / 2; } else { /* * Added 't->title_x + ' to handle titlebars that * aren't flush left. * Submitted by Steve Ratcliffe * was '(t->frame_bw3D + t->frame_bw)' - djhjr - 9/9/02 */ x = t->title_x + t->title_width / 2 + bw; y = t->title_height / 2 + bw; } } /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */ if (!Scr->BorderBevelWidth > 0) y -= t->frame_bw; #endif /* * adjust the pointer for partially visible windows and the * AutoPan border width - djhjr - 5/30/00 * was '(t->frame_bw3D + t->frame_bw)' - djhjr - 9/9/02 */ if (Scr->AutoPanX) pan_margin = Scr->AutoPanBorderWidth; if (x + t->frame_x >= Scr->MyDisplayWidth - pan_margin) x = Scr->MyDisplayWidth - t->frame_x - pan_margin - 2; if (x + t->frame_x <= pan_margin) { if (t->title_w) x = t->title_width - (t->frame_x + t->title_width) + pan_margin + 2; else x = -t->frame_x + pan_margin + 2; } /* added test for centered warps - djhjr - 10/16/02 */ if (t->title_w && !(Scr->WarpCentered & WARPC_TITLED) && (x < t->title_x || x > t->title_x + t->title_width)) { y = t->title_height + bw / 2; } if (y + t->frame_y >= Scr->MyDisplayHeight - pan_margin) { y = Scr->MyDisplayHeight - t->frame_y - pan_margin - 2; /* move centered warp to titlebar - djhjr - 10/16/02 */ if (y < t->title_y + t->title_height) x = t->title_x + t->title_width / 2 + bw; } if (y + t->frame_y <= pan_margin) y = -t->frame_y + pan_margin + 2; /* was 't->frame' - djhjr - 5/30/00 */ XWarpPointer (dpy, None, w, 0, 0, 0, 0, x, y); /* djhjr - 10/27/02 */ if (t->ring.next) Scr->RingLeader = t; } /* * substantially re-written and added receiving and using 'next' * * djhjr - 5/13/98 5/19/98 6/6/98 6/15/98 */ #ifdef ORIGINAL_WARPCLASS TwmWindow * next_by_class (t, class) TwmWindow *t; char *class; { TwmWindow *tt; int len = strlen(class); if (t) for (tt = t->next; tt != NULL; tt = tt->next) if (!strncmp(class, tt->class.res_class, len)) return tt; for (tt = Scr->TwmRoot.next; tt != NULL; tt = tt->next) if (!strncmp(class, tt->class.res_class, len)) return tt; return NULL; } #else /* ORIGINAL_WARPCLASS */ static TwmWindow * next_by_class (next, t, class) int next; TwmWindow *t; char *class; { static TwmWindow *tp = NULL; TwmWindow *tt, *tl; int i, len = strlen(class); XClassHint ch; #ifdef DEBUG_WARPCLASS fprintf(stderr, "class=\"%s\", next=%d, %s t, ", class, next, (t) ? "have" : "no"); #endif /* forward or backward from current */ tl = (next) ? ((tp) ? tp->next : Scr->TwmRoot.next) : ((tp) ? tp->prev : Scr->TwmRoot.prev); for (tt = (next) ? ((t) ? t->next : tl) : ((t) ? t->prev : tl); tt != NULL; tt = (next) ? tt->next : tt->prev) if (Scr->WarpUnmapped || tt->mapped) { i = XGetClassHint(dpy, tt->w, &ch); if (i && !strncmp(class, ch.res_class, len)) { #ifdef DEBUG_WARPCLASS fprintf(stderr, "matched \"%s\" \"%s\"\n", tt->class.res_class, tt->class.res_name); #endif tp = tt; return tp; } else { #ifdef DEBUG_WARPCLASS fprintf(stderr, "(1) skipping \"%s\"\n", (i) ? tt->class.res_class : "NO RES_CLASS!"); #endif if (i == 0) break; } } /* no match, wrap and retry */ tp = tl = NULL; for (tt = Scr->TwmRoot.next; tt != NULL; tt = tt->next) if (Scr->WarpUnmapped || tt->mapped) { i = XGetClassHint(dpy, tt->w, &ch); if (i && !strncmp(class, ch.res_class, len)) { if (next) { #ifdef DEBUG_WARPCLASS fprintf(stderr, "next wrapped to \"%s\ \"%s\"\n", tt->class.res_class, tt->class.res_name); #endif tp = tt; return tp; } else tl = tt; } #ifdef DEBUG_WARPCLASS else fprintf(stderr, "(2) skipping \"%s\"\n", (i) ? tt->class.res_class : "NO RES_CLASS!"); #endif } #ifdef DEBUG_WARPCLASS i = 0; if (tl) i = XGetClassHint(dpy, tl->w, &ch); fprintf(stderr, "prev wrapped to \"%s\ \"%s\"\n", (i) ? ch.res_class : "NO RES_CLASS!", (i) ? ch.res_name : "NO RES_CLASS!"); #endif tp = tl; return tp; } #endif /* ORIGINAL_WARPCLASS */ /* this was inlined in many places, and even more now - djhjr - 5/13/98 */ /* added the second argument - djhjr - 5/28/00 */ static int warp_if_warpunmapped(w, func) TwmWindow *w; int func; { /* skip empty icon managers - 10/27/02 */ if (w && (w->iconmgr && w->iconmgrp->count == 0)) return (0); if (Scr->WarpUnmapped || w->mapped) { /* submitted by Ugen Antsilevitch - 5/28/00 */ /* if F_NOFUNCTION, override WarpVisible - djhjr - 5/28/00 */ if (func != F_NOFUNCTION && Scr->WarpVisible) { int pan_margin = 0; if (Scr->AutoPanX) pan_margin = Scr->AutoPanBorderWidth; if (w->frame_x >= Scr->MyDisplayWidth - pan_margin || w->frame_y >= Scr->MyDisplayHeight - pan_margin || w->frame_x + w->frame_width <= pan_margin || w->frame_y + w->frame_height <= pan_margin) return 0; } if (!w->mapped) DeIconify(w); if (!Scr->NoRaiseWarp) XRaiseWindow(dpy, w->frame); XRaiseWindow(dpy, w->VirtualDesktopDisplayWindow); return (1); } return (0); } /* djhjr - 9/17/02 */ static int do_squeezetitle(context, func, tmp_win, squeeze) int context, func; TwmWindow *tmp_win; SqueezeInfo *squeeze; { if (DeferExecution (context, func, Scr->SelectCursor)) return TRUE; /* honor "Don't Squeeze" resources - djhjr - 9/17/02 */ if (Scr->SqueezeTitle && !LookInList(Scr->DontSqueezeTitleL, tmp_win->full_name, &tmp_win->class)) { if ( tmp_win->title_height ) /* Not for untitled windows! */ { PopDownMenu(); /* djhjr - 9/17/02 */ #ifndef NO_SOUND_SUPPORT PlaySound(func); #endif tmp_win->squeeze_info = squeeze; SetFrameShape( tmp_win ); /* Can't go in SetFrameShape()... - djhjr - 4/1/00 */ if (Scr->WarpCursor || LookInList(Scr->WarpCursorL, tmp_win->full_name, &tmp_win->class)) WarpToWindow(tmp_win); } } else DoAudible(); return FALSE; } /* * Two functions to handle a restart from a SIGUSR1 signal * (see also twm.c:Done() and twm.c:QueueRestartVtwm()) * * adapted from TVTWM-pl11 - djhjr - 7/31/98 */ static void setup_restart(time) Time time; { /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT CloseSound(); #endif SetRealScreen(0,0); XSync (dpy, 0); Reborder (time); XSync (dpy, 0); /* djhjr - 3/13/97 */ XCloseDisplay(dpy); /* djhjr - 12/2/01 */ delete_pidfile(); } void RestartVtwm(time) Time time; { setup_restart(time); execvp(*Argv, Argv); fprintf (stderr, "%s: unable to restart \"%s\"\n", ProgramName, *Argv); } /* * ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all * client messages will have the following form: * * event type ClientMessage * message type _XA_WM_PROTOCOLS * window tmp->w * format 32 * data[0] message atom * data[1] time stamp */ static void send_clientmessage (w, a, timestamp) Window w; Atom a; Time timestamp; { XClientMessageEvent ev; ev.type = ClientMessage; ev.window = w; ev.message_type = _XA_WM_PROTOCOLS; ev.format = 32; ev.data.l[0] = a; ev.data.l[1] = timestamp; XSendEvent (dpy, w, False, 0L, (XEvent *) &ev); } void SendDeleteWindowMessage (tmp, timestamp) TwmWindow *tmp; Time timestamp; { send_clientmessage (tmp->w, _XA_WM_DELETE_WINDOW, timestamp); } void SendSaveYourselfMessage (tmp, timestamp) TwmWindow *tmp; Time timestamp; { send_clientmessage (tmp->w, _XA_WM_SAVE_YOURSELF, timestamp); } void SendTakeFocusMessage (tmp, timestamp) TwmWindow *tmp; Time timestamp; { send_clientmessage (tmp->w, _XA_WM_TAKE_FOCUS, timestamp); } /* djhjr - 4/27/96 */ void DisplayPosition (x, y) int x, y; { char str [100]; int i; /* djhjr - 5/10/96 char signx = '+'; char signy = '+'; if (x < 0) { x = -x; signx = '-'; } if (y < 0) { y = -y; signy = '-'; } i = sprintf (str, " %c%-4d %c%-4d ", signx, x, signy, y); */ /* * Non-SysV systems - specifically, BSD-derived systems - return a * pointer to the string, not its length. Submitted by Goran Larsson i = sprintf (str, "%+6d %-+6d", x, y); */ sprintf (str, "%+6d %-+6d", x, y); i = strlen (str); XRaiseWindow (dpy, Scr->SizeWindow); /* font was font.font->fid - djhjr - 9/14/03 */ FBF (Scr->DefaultC.fore, Scr->DefaultC.back, Scr->SizeFont); /* djhjr - 9/14/03 */ #ifndef NO_I18N_SUPPORT MyFont_DrawImageString (dpy, Scr->SizeWindow, &Scr->SizeFont, #else XDrawImageString (dpy, Scr->SizeWindow, #endif Scr->NormalGC, /* djhjr - 5/9/96 Scr->SizeStringOffset, */ (Scr->SizeStringWidth - /* djhjr - 9/14/03 */ #ifndef NO_I18N_SUPPORT MyFont_TextWidth(&Scr->SizeFont, #else XTextWidth(Scr->SizeFont.font, #endif str, i)) / 2, /* djhjr - 4/29/98 Scr->SizeFont.font->ascent + SIZE_VINDENT, */ /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */ /* djhjr - 9/14/03 Scr->SizeFont.font->ascent + */ Scr->SizeFont.ascent + SIZE_VINDENT + ((Scr->InfoBevelWidth > 0) ? Scr->InfoBevelWidth : 0), str, i); /* I know, I know, but the above code overwrites it... djhjr - 5/9/96 */ /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */ if (Scr->InfoBevelWidth > 0) Draw3DBorder(Scr->SizeWindow, 0, 0, Scr->SizeStringWidth, /* djhjr - 4/29/98 (unsigned int) (Scr->SizeFont.height + SIZE_VINDENT*2), BW, Scr->DefaultC, off, False, False); */ /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */ (unsigned int) (Scr->SizeFont.height + SIZE_VINDENT*2) + ((Scr->InfoBevelWidth > 0) ? 2 * Scr->InfoBevelWidth : 0), Scr->InfoBevelWidth, Scr->DefaultC, off, False, False); } /* djhjr - 9/21/99 */ int FindMenuOrFuncInBindings(contexts, mr, func) int contexts; MenuRoot *mr; int func; { MenuRoot *start; FuncKey *key; int found = 0; /* context bitmap for menu or function */ int i, j, k, l, fallback = 0; if (mr) { if (Scr->DefaultFunction.func == F_MENU) if (FindMenuInMenus(Scr->DefaultFunction.menu, mr)) fallback = 1; } else { if (Scr->DefaultFunction.func == func) fallback = 1; else if (Scr->DefaultFunction.func == F_MENU) if (FindFuncInMenus(Scr->DefaultFunction.menu, func)) fallback = 1; } for (j = 0; j < NUM_CONTEXTS; j++) { if ((contexts & (1 << j)) == 0) continue; if (fallback) { found |= (1 << j); continue; } for (i = 0; i < MAX_BUTTONS + 1; i++) { l = 0; for (k = 0; k < MOD_SIZE; k++) { if (mr) { if (Scr->Mouse[i][j][k].func == F_MENU) l = FindMenuInMenus(Scr->Mouse[i][j][k].menu, mr); } else { if (Scr->Mouse[i][j][k].func == func) l = 1; else if (Scr->Mouse[i][j][k].func == F_MENU) l = FindFuncInMenus(Scr->Mouse[i][j][k].menu, func); } if (l) { found |= (1 << j); i = MAX_BUTTONS + 1; break; } } } l = 0; for (key = Scr->FuncKeyRoot.next; key != NULL; key = key->next) if (key->cont & (1 << j)) { if (mr) { if (key->func == F_MENU) for (start = Scr->MenuList; start != NULL; start = start->next) if (strcmp(start->name, key->action) == 0) { l = FindMenuInMenus(start, mr); break; } } else { if (key->func == func) l = 1; else if (key->func == F_MENU) for (start = Scr->MenuList; start != NULL; start = start->next) if (strcmp(start->name, key->action) == 0) { l = FindFuncInMenus(start, func); break; } } if (l) { found |= (1 << j); break; } } } return found; } /* djhjr - 9/21/99 */ int FindMenuOrFuncInWindows(tmp_win, contexts, mr, func) TwmWindow *tmp_win; int contexts; MenuRoot *mr; int func; { TwmWindow *twin; TwmDoor *d; TBWindow *tbw; int i, nb; if (contexts & C_ROOT_BIT) return 1; for (twin = Scr->TwmRoot.next; twin != NULL; twin = twin->next) if (twin != tmp_win) { /* * if this window is an icon manager, * skip the windows that aren't in it */ if (tmp_win->iconmgr && twin->list && tmp_win != twin->list->iconmgr->twm_win) continue; if (twin->mapped) { for (i = 1; i < C_ALL_BITS; i = (1 << i)) { if ((contexts & i) == 0) continue; switch (i) { case C_WINDOW_BIT: case C_FRAME_BIT: break; case C_TITLE_BIT: if (!twin->title_height) continue; break; case C_VIRTUAL_BIT: if (twin->w != Scr->VirtualDesktopDisplayOuter) continue; break; case C_DOOR_BIT: if (XFindContext(dpy, twin->w, DoorContext, (caddr_t *)&d) == XCNOENT) continue; break; default: continue; break; } return 1; } if (twin->titlebuttons) { nb = Scr->TBInfo.nleft + Scr->TBInfo.nright; for (tbw = twin->titlebuttons; nb > 0; tbw++, nb--) if (mr) { if (tbw->info->menuroot) if (FindMenuInMenus(tbw->info->menuroot, mr)) return 1; } else { if (tbw->info->func == func) return 1; else if (tbw->info->menuroot) if (FindFuncInMenus(tbw->info->menuroot, func)) return 1; } } } else if (!twin->iconify_by_unmapping) { /* not mapped and shows an icon */ if (contexts & C_ICON_BIT) return 1; } } return 0; } /* djhjr - 9/21/99 */ int FindMenuInMenus(start, sought) MenuRoot *start, *sought; { MenuItem *mi; if (!start) return 0; /* submitted by Jonathan Paisley - 11/11/02 */ if (start == sought) return 1; for (mi = start->first; mi != NULL; mi = mi->next) if (mi->sub) if (FindMenuInMenus(mi->sub, sought)) return 1; return 0; } /* djhjr - 9/21/99 */ int FindFuncInMenus(mr, func) MenuRoot *mr; int func; { MenuItem *mi; for (mi = mr->first; mi != NULL; mi = mi->next) if (mi->func == func) return 1; else if (mi->sub) if (FindFuncInMenus(mi->sub, func)) return 1; return 0; } /* djhjr - 6/22/01 */ void DoAudible() { #ifndef NO_SOUND_SUPPORT if (PlaySound(S_BELL)) return; #endif XBell(dpy, 0); }