mirror of
https://github.com/Stichting-MINIX-Research-Foundation/xsrc.git
synced 2025-09-22 11:07:46 -04:00
5598 lines
148 KiB
C
5598 lines
148 KiB
C
/*****************************************************************************/
|
||
/** 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. **/
|
||
/*****************************************************************************/
|
||
/*
|
||
* [ ctwm ]
|
||
*
|
||
* Copyright 1992 Claude Lecommandeur.
|
||
*
|
||
* Permission to use, copy, modify and distribute this software [ctwm] and
|
||
* its documentation for any purpose is hereby granted without fee, provided
|
||
* that the above copyright notice appear in all copies and that both that
|
||
* copyright notice and this permission notice appear in supporting documen-
|
||
* tation, and that the name of Claude Lecommandeur not be used in adverti-
|
||
* sing or publicity pertaining to distribution of the software without
|
||
* specific, written prior permission. Claude Lecommandeur make no represen-
|
||
* tations about the suitability of this software for any purpose. It is
|
||
* provided "as is" without express or implied warranty.
|
||
*
|
||
* Claude Lecommandeur DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||
* EVENT SHALL Claude Lecommandeur BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||
* CONSEQUENTIAL DAMAGES 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.
|
||
*
|
||
* Author: Claude Lecommandeur [ lecom@sic.epfl.ch ][ April 1992 ]
|
||
*/
|
||
|
||
|
||
/***********************************************************************
|
||
*
|
||
* $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
|
||
*
|
||
* Do the necessary modification to be integrated in ctwm.
|
||
* Can no longer be used for the standard twm.
|
||
*
|
||
* 22-April-92 Claude Lecommandeur.
|
||
*
|
||
*
|
||
***********************************************************************/
|
||
|
||
#if defined(USE_SIGNALS) && defined(__sgi)
|
||
# define _BSD_SIGNALS
|
||
#endif
|
||
|
||
#include <stdio.h>
|
||
#include <signal.h>
|
||
|
||
#ifdef VMS
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <unixio.h>
|
||
#include <file.h>
|
||
#include <decw$include/Xos.h>
|
||
#include <decw$include/Xatom.h>
|
||
#else
|
||
#include <X11/Xos.h>
|
||
#include <X11/Xatom.h>
|
||
#endif
|
||
#include "twm.h"
|
||
#include "ctwm.h"
|
||
#include "gc.h"
|
||
#include "menus.h"
|
||
#include "resize.h"
|
||
#include "events.h"
|
||
#include "list.h"
|
||
#include "util.h"
|
||
#include "parse.h"
|
||
#include "screen.h"
|
||
#include "icons.h"
|
||
#include "add_window.h"
|
||
#include "windowbox.h"
|
||
#include "workmgr.h"
|
||
#include "cursor.h"
|
||
#include "gnomewindefs.h"
|
||
#ifdef SOUNDS
|
||
# include "sound.h"
|
||
#endif
|
||
#ifdef VMS
|
||
# include <X11Xmu/CharSet.h>
|
||
# include <decw$bitmaps/menu12.xbm>
|
||
# include <X11SM/SMlib.h>
|
||
# include "vms_cmd_services.h"
|
||
# include <lib$routines.h>
|
||
#else
|
||
# include <X11/Xmu/CharSet.h>
|
||
# include <X11/SM/SMlib.h>
|
||
#endif
|
||
#include "version.h"
|
||
|
||
#if defined(MACH) || defined(__MACH__) || defined(sony_news) || defined(NeXT)
|
||
#define lrand48 random
|
||
#endif
|
||
#if defined(VMS) || defined(__DARWIN__)
|
||
#define lrand48 rand
|
||
#endif
|
||
|
||
#ifndef VMS
|
||
#define MAX(x,y) ((x)>(y)?(x):(y))
|
||
#define MIN(x,y) ((x)<(y)?(x):(y))
|
||
#endif
|
||
#define ABS(x) ((x)<0?-(x):(x))
|
||
|
||
int RootFunction = 0;
|
||
MenuRoot *ActiveMenu = NULL; /* the active menu */
|
||
MenuItem *ActiveItem = NULL; /* the active menu item */
|
||
int MoveFunction; /* either F_MOVE or F_FORCEMOVE */
|
||
int WindowMoved = FALSE;
|
||
int menuFromFrameOrWindowOrTitlebar = FALSE;
|
||
char *CurrentSelectedWorkspace;
|
||
int AlternateKeymap;
|
||
Bool AlternateContext;
|
||
|
||
extern char *captivename;
|
||
|
||
int ConstMove = FALSE; /* constrained move variables */
|
||
int ConstMoveDir;
|
||
int ConstMoveX;
|
||
int ConstMoveY;
|
||
int ConstMoveXL;
|
||
int ConstMoveXR;
|
||
int ConstMoveYT;
|
||
int ConstMoveYB;
|
||
|
||
/* Globals used to keep track of whether the mouse has moved during
|
||
a resize function. */
|
||
int ResizeOrigX;
|
||
int ResizeOrigY;
|
||
|
||
int MenuDepth = 0; /* number of menus up */
|
||
static struct {
|
||
int x;
|
||
int y;
|
||
} MenuOrigins[MAXMENUDEPTH];
|
||
static Cursor LastCursor;
|
||
static Bool addingdefaults = False;
|
||
|
||
void jump (TwmWindow *tmp_win, int direction, char *action);
|
||
void waitamoment (float timeout);
|
||
|
||
extern char *Action;
|
||
extern int Context;
|
||
extern TwmWindow *ButtonWindow, *Tmp_win;
|
||
extern XEvent ButtonEvent;
|
||
extern char *InitFile;
|
||
extern int ConstrainedMoveTime;
|
||
static void Identify (TwmWindow *t);
|
||
|
||
#define SHADOWWIDTH 5 /* in pixels */
|
||
|
||
#ifdef GNOME
|
||
extern Atom _XA_WIN_STATE;
|
||
#endif /* GNOME */
|
||
|
||
|
||
|
||
/***********************************************************************
|
||
*
|
||
* Procedure:
|
||
* InitMenus - initialize menu roots
|
||
*
|
||
***********************************************************************
|
||
*/
|
||
|
||
void InitMenus(void)
|
||
{
|
||
Scr->DefaultFunction.func = 0;
|
||
Scr->WindowFunction.func = 0;
|
||
Scr->ChangeWorkspaceFunction.func = 0;
|
||
Scr->DeIconifyFunction.func = 0;
|
||
Scr->IconifyFunction.func = 0;
|
||
|
||
Scr->FuncKeyRoot.next = NULL;
|
||
Scr->FuncButtonRoot.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 (char *name, int cont, int mods, int func,
|
||
MenuRoot *menu, 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 && addingdefaults) return (True);
|
||
|
||
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->menu = menu;
|
||
tmp->win_name = win_name;
|
||
tmp->action = action;
|
||
|
||
return True;
|
||
}
|
||
|
||
/***********************************************************************
|
||
*
|
||
* Procedure:
|
||
* AddFuncButton - add a function button to the list
|
||
*
|
||
* Inputs:
|
||
* num - the num of the button
|
||
* cont - the context to look for the key press in
|
||
* mods - modifier keys that need to be pressed
|
||
* func - the function to perform
|
||
* menu - the menu (if any)
|
||
* item - the menu item (if any)
|
||
*
|
||
***********************************************************************
|
||
*/
|
||
|
||
Bool AddFuncButton (int num, int cont, int mods, int func,
|
||
MenuRoot *menu, MenuItem *item)
|
||
{
|
||
FuncButton *tmp;
|
||
|
||
/* see if there already is a key defined for this context */
|
||
for (tmp = Scr->FuncButtonRoot.next; tmp != NULL; tmp = tmp->next) {
|
||
if ((tmp->num == num) && (tmp->cont == cont) && (tmp->mods == mods))
|
||
break;
|
||
}
|
||
if (tmp && addingdefaults) return (True);
|
||
|
||
if (tmp == NULL) {
|
||
tmp = (FuncButton*) malloc (sizeof (FuncButton));
|
||
tmp->next = Scr->FuncButtonRoot.next;
|
||
Scr->FuncButtonRoot.next = tmp;
|
||
}
|
||
|
||
tmp->num = num;
|
||
tmp->cont = cont;
|
||
tmp->mods = mods;
|
||
tmp->func = func;
|
||
tmp->menu = menu;
|
||
tmp->item = item;
|
||
|
||
return True;
|
||
}
|
||
|
||
|
||
|
||
static TitleButton *cur_tb = NULL;
|
||
|
||
void ModifyCurrentTB(int button, int mods, int func, char *action,
|
||
MenuRoot *menuroot)
|
||
{
|
||
TitleButtonFunc *tbf;
|
||
|
||
if (!cur_tb) {
|
||
fprintf (stderr, "%s: can't find titlebutton\n", ProgramName);
|
||
return;
|
||
}
|
||
for (tbf = cur_tb->funs; tbf; tbf = tbf->next) {
|
||
if (tbf->num == button && tbf->mods == mods)
|
||
break;
|
||
}
|
||
if (!tbf) {
|
||
tbf = (TitleButtonFunc *)malloc(sizeof(TitleButtonFunc));
|
||
if (!tbf) {
|
||
fprintf (stderr, "%s: out of memory\n", ProgramName);
|
||
return;
|
||
}
|
||
tbf->next = cur_tb->funs;
|
||
cur_tb->funs = tbf;
|
||
}
|
||
tbf->num = button;
|
||
tbf->mods = mods;
|
||
tbf->func = func;
|
||
tbf->action = action;
|
||
tbf->menuroot = menuroot;
|
||
}
|
||
|
||
int CreateTitleButton (char *name, int func, char *action, MenuRoot *menuroot,
|
||
Bool rightside, Bool append)
|
||
{
|
||
int button;
|
||
cur_tb = (TitleButton *) malloc (sizeof(TitleButton));
|
||
|
||
if (!cur_tb) {
|
||
fprintf (stderr,
|
||
"%s: unable to allocate %lu bytes for title button\n",
|
||
ProgramName, (unsigned long) sizeof(TitleButton));
|
||
return 0;
|
||
}
|
||
|
||
cur_tb->next = NULL;
|
||
cur_tb->name = name; /* note that we are not copying */
|
||
cur_tb->image = None; /* WARNING, values not set yet */
|
||
cur_tb->width = 0; /* see InitTitlebarButtons */
|
||
cur_tb->height = 0; /* ditto */
|
||
cur_tb->rightside = rightside;
|
||
cur_tb->funs = NULL;
|
||
if (rightside) {
|
||
Scr->TBInfo.nright++;
|
||
} else {
|
||
Scr->TBInfo.nleft++;
|
||
}
|
||
|
||
for(button = 0; button < MAX_BUTTONS; button++){
|
||
ModifyCurrentTB(button + 1, 0, func, action, menuroot);
|
||
}
|
||
|
||
/*
|
||
* 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 */
|
||
cur_tb->next = Scr->TBInfo.head;
|
||
Scr->TBInfo.head = cur_tb;
|
||
} else if (append && rightside) { /* 3 */
|
||
register TitleButton *t;
|
||
for /* SUPPRESS 530 */
|
||
(t = Scr->TBInfo.head; t->next; t = t->next);
|
||
t->next = cur_tb;
|
||
cur_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) {
|
||
cur_tb->next = prev->next;
|
||
prev->next = cur_tb;
|
||
} else {
|
||
cur_tb->next = Scr->TBInfo.head;
|
||
Scr->TBInfo.head = cur_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.
|
||
*/
|
||
void InitTitlebarButtons (void)
|
||
{
|
||
TitleButton *tb;
|
||
int h;
|
||
|
||
/*
|
||
* initialize dimensions
|
||
*/
|
||
Scr->TBInfo.width = (Scr->TitleHeight -
|
||
2 * (Scr->FramePadding + Scr->ButtonIndent));
|
||
if (Scr->use3Dtitles)
|
||
Scr->TBInfo.pad = ((Scr->TitlePadding > 1)
|
||
? ((Scr->TitlePadding + 1) / 2) : 0);
|
||
else
|
||
Scr->TBInfo.pad = ((Scr->TitlePadding > 1)
|
||
? ((Scr->TitlePadding + 1) / 2) : 1);
|
||
h = Scr->TBInfo.width - 2 * Scr->TBInfo.border;
|
||
|
||
/*
|
||
* add in some useful buttons and bindings so that novices can still
|
||
* use the system.
|
||
*/
|
||
if (!Scr->NoDefaults) {
|
||
/* insert extra buttons */
|
||
if (Scr->use3Dtitles) {
|
||
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);
|
||
}
|
||
}
|
||
addingdefaults = True;
|
||
AddDefaultBindings ();
|
||
addingdefaults = False;
|
||
}
|
||
ComputeCommonTitleOffsets ();
|
||
|
||
/*
|
||
* load in images and do appropriate centering
|
||
*/
|
||
|
||
for (tb = Scr->TBInfo.head; tb; tb = tb->next) {
|
||
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);
|
||
continue;
|
||
}
|
||
}
|
||
tb->width = tb->image->width;
|
||
tb->height = tb->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;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
void PaintEntry(MenuRoot *mr, MenuItem *mi, int exposure)
|
||
{
|
||
if (Scr->use3Dmenus)
|
||
Paint3DEntry (mr, mi, exposure);
|
||
else
|
||
PaintNormalEntry (mr, mi, exposure);
|
||
if (mi->state) mr->lastactive = mi;
|
||
}
|
||
|
||
void Paint3DEntry(MenuRoot *mr, MenuItem *mi, int exposure)
|
||
{
|
||
int y_offset;
|
||
int text_y;
|
||
GC gc;
|
||
|
||
y_offset = mi->item_num * Scr->EntryHeight + Scr->MenuShadowDepth;
|
||
text_y = y_offset + Scr->MenuFont.y + 2;
|
||
|
||
if (mi->func != F_TITLE) {
|
||
int x, y;
|
||
|
||
gc = Scr->NormalGC;
|
||
if (mi->state) {
|
||
Draw3DBorder (mr->w, Scr->MenuShadowDepth, y_offset,
|
||
mr->width - 2 * Scr->MenuShadowDepth, Scr->EntryHeight, 1,
|
||
mi->highlight, off, True, False);
|
||
FB(mi->highlight.fore, mi->highlight.back);
|
||
XmbDrawImageString(dpy, mr->w, Scr->MenuFont.font_set, gc,
|
||
mi->x + Scr->MenuShadowDepth, text_y, mi->item, mi->strlen);
|
||
}
|
||
else {
|
||
if (mi->user_colors || !exposure) {
|
||
XSetForeground (dpy, gc, mi->normal.back);
|
||
XFillRectangle (dpy, mr->w, gc,
|
||
Scr->MenuShadowDepth, y_offset,
|
||
mr->width - 2 * Scr->MenuShadowDepth, Scr->EntryHeight);
|
||
FB (mi->normal.fore, mi->normal.back);
|
||
}
|
||
else {
|
||
gc = Scr->MenuGC;
|
||
}
|
||
XmbDrawImageString (dpy, mr->w, Scr->MenuFont.font_set, gc,
|
||
mi->x + Scr->MenuShadowDepth, text_y,
|
||
mi->item, mi->strlen);
|
||
if (mi->separated) {
|
||
FB (Scr->MenuC.shadd, Scr->MenuC.shadc);
|
||
XDrawLine (dpy, mr->w, Scr->NormalGC,
|
||
Scr->MenuShadowDepth,
|
||
y_offset + Scr->EntryHeight - 2,
|
||
mr->width - Scr->MenuShadowDepth,
|
||
y_offset + Scr->EntryHeight - 2);
|
||
FB (Scr->MenuC.shadc, Scr->MenuC.shadd);
|
||
XDrawLine (dpy, mr->w, Scr->NormalGC,
|
||
Scr->MenuShadowDepth,
|
||
y_offset + Scr->EntryHeight - 1,
|
||
mr->width - Scr->MenuShadowDepth,
|
||
y_offset + Scr->EntryHeight - 1);
|
||
}
|
||
}
|
||
|
||
if (mi->func == F_MENU) {
|
||
/* create the pull right pixmap if needed */
|
||
if (Scr->pullPm == None)
|
||
{
|
||
Scr->pullPm = Create3DMenuIcon (Scr->MenuFont.height, &Scr->pullW,
|
||
&Scr->pullH, Scr->MenuC);
|
||
}
|
||
x = mr->width - Scr->pullW - Scr->MenuShadowDepth - 2;
|
||
y = y_offset + ((Scr->MenuFont.height - Scr->pullH) / 2) + 2;
|
||
XCopyArea (dpy, Scr->pullPm, mr->w, gc, 0, 0, Scr->pullW, Scr->pullH, x, y);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Draw3DBorder (mr->w, Scr->MenuShadowDepth, y_offset,
|
||
mr->width - 2 * Scr->MenuShadowDepth, Scr->EntryHeight, 1,
|
||
mi->normal, off, True, False);
|
||
FB (mi->normal.fore, mi->normal.back);
|
||
XmbDrawImageString(dpy, mr->w, Scr->MenuFont.font_set, Scr->NormalGC,
|
||
mi->x + 2, text_y, mi->item, mi->strlen);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
void PaintNormalEntry(MenuRoot *mr, MenuItem *mi, int exposure)
|
||
{
|
||
int y_offset;
|
||
int text_y;
|
||
GC gc;
|
||
|
||
y_offset = mi->item_num * Scr->EntryHeight;
|
||
text_y = y_offset + 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);
|
||
FB(mi->highlight.fore, mi->highlight.back);
|
||
XmbDrawString(dpy, mr->w, Scr->MenuFont.font_set, 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);
|
||
|
||
FB(mi->normal.fore, mi->normal.back);
|
||
gc = Scr->NormalGC;
|
||
}
|
||
else {
|
||
gc = Scr->MenuGC;
|
||
}
|
||
XmbDrawString(dpy, mr->w, Scr->MenuFont.font_set, gc, mi->x,
|
||
text_y, mi->item, mi->strlen);
|
||
if (mi->separated)
|
||
XDrawLine (dpy, mr->w, gc, 0, y_offset + Scr->EntryHeight - 1,
|
||
mr->width, y_offset + Scr->EntryHeight - 1);
|
||
}
|
||
|
||
if (mi->func == F_MENU)
|
||
{
|
||
/* create the pull right pixmap if needed */
|
||
if (Scr->pullPm == None)
|
||
{
|
||
Scr->pullPm = CreateMenuIcon (Scr->MenuFont.height,
|
||
&Scr->pullW, &Scr->pullH);
|
||
}
|
||
x = mr->width - Scr->pullW - 5;
|
||
y = y_offset + ((Scr->MenuFont.height - Scr->pullH) / 2);
|
||
XCopyPlane(dpy, Scr->pullPm, mr->w, gc, 0, 0,
|
||
Scr->pullW, Scr->pullH, x, y, 1);
|
||
}
|
||
}
|
||
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);
|
||
}
|
||
|
||
FB(mi->normal.fore, mi->normal.back);
|
||
/* finally render the title */
|
||
XmbDrawString(dpy, mr->w, Scr->MenuFont.font_set, Scr->NormalGC, mi->x,
|
||
text_y, mi->item, mi->strlen);
|
||
}
|
||
}
|
||
|
||
void PaintMenu(MenuRoot *mr, XEvent *e)
|
||
{
|
||
MenuItem *mi;
|
||
|
||
if (Scr->use3Dmenus) {
|
||
Draw3DBorder (mr->w, 0, 0, mr->width, mr->height,
|
||
Scr->MenuShadowDepth, Scr->MenuC, off, False, False);
|
||
}
|
||
for (mi = mr->first; mi != NULL; mi = mi->next)
|
||
{
|
||
int y_offset = mi->item_num * Scr->EntryHeight;
|
||
|
||
/* be smart about handling the expose, redraw only the entries
|
||
* that we need to
|
||
*/
|
||
if (e->xexpose.y <= (y_offset + Scr->EntryHeight) &&
|
||
(e->xexpose.y + e->xexpose.height) >= y_offset)
|
||
{
|
||
PaintEntry(mr, mi, True);
|
||
}
|
||
}
|
||
XSync(dpy, 0);
|
||
}
|
||
|
||
|
||
|
||
void MakeWorkspacesMenu (void)
|
||
{
|
||
static char **actions = NULL;
|
||
WorkSpace *wlist;
|
||
char **act;
|
||
|
||
if (! Scr->Workspaces) return;
|
||
AddToMenu (Scr->Workspaces, "TWM Workspaces", NULLSTR, NULL, F_TITLE, NULLSTR, NULLSTR);
|
||
if (! actions) {
|
||
int count = 0;
|
||
|
||
for (wlist = Scr->workSpaceMgr.workSpaceList; wlist != NULL; wlist = wlist->next) {
|
||
count++;
|
||
}
|
||
count++;
|
||
actions = (char**) malloc (count * sizeof (char*));
|
||
act = actions;
|
||
for (wlist = Scr->workSpaceMgr.workSpaceList; wlist != NULL; wlist = wlist->next) {
|
||
*act = (char*) malloc (strlen ("WGOTO : ") + strlen (wlist->name) + 1);
|
||
sprintf (*act, "WGOTO : %s", wlist->name);
|
||
act++;
|
||
}
|
||
*act = NULL;
|
||
}
|
||
act = actions;
|
||
for (wlist = Scr->workSpaceMgr.workSpaceList; wlist != NULL; wlist = wlist->next) {
|
||
AddToMenu (Scr->Workspaces, wlist->name, *act, Scr->Windows, F_MENU, NULL, NULL);
|
||
act++;
|
||
}
|
||
Scr->Workspaces->pinned = False;
|
||
MakeMenu (Scr->Workspaces);
|
||
}
|
||
|
||
static Bool fromMenu;
|
||
|
||
int UpdateMenu(void)
|
||
{
|
||
MenuItem *mi;
|
||
int i, x, y, x_root, y_root, entry;
|
||
int done;
|
||
MenuItem *badItem = NULL;
|
||
|
||
fromMenu = TRUE;
|
||
|
||
while (TRUE)
|
||
{
|
||
/* block until there is an event */
|
||
if (!menuFromFrameOrWindowOrTitlebar) {
|
||
XMaskEvent(dpy,
|
||
ButtonPressMask | ButtonReleaseMask |
|
||
KeyPressMask | KeyReleaseMask |
|
||
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;
|
||
}
|
||
|
||
if (!DispatchEvent ())
|
||
continue;
|
||
|
||
if ((! ActiveMenu) || Cancel) {
|
||
menuFromFrameOrWindowOrTitlebar = FALSE;
|
||
fromMenu = FALSE;
|
||
return (0);
|
||
}
|
||
|
||
if (Event.type != MotionNotify)
|
||
continue;
|
||
|
||
done = FALSE;
|
||
XQueryPointer( dpy, ActiveMenu->w, &JunkRoot, &JunkChild,
|
||
&x_root, &y_root, &x, &y, &JunkMask);
|
||
|
||
/* if we haven't recieved the enter notify yet, wait */
|
||
if (ActiveMenu && !ActiveMenu->entered)
|
||
continue;
|
||
|
||
if (XFindContext(dpy, ActiveMenu->w, ScreenContext, (XPointer *)&Scr)
|
||
!= XCSUCCESS)
|
||
continue;
|
||
|
||
if (x < 0 || y < 0 ||
|
||
x >= ActiveMenu->width || y >= ActiveMenu->height)
|
||
{
|
||
if (ActiveItem && ActiveItem->func != F_TITLE)
|
||
{
|
||
ActiveItem->state = 0;
|
||
PaintEntry(ActiveMenu, ActiveItem, False);
|
||
}
|
||
ActiveItem = NULL;
|
||
continue;
|
||
}
|
||
|
||
/* look for the entry that the mouse is in */
|
||
entry = y / Scr->EntryHeight;
|
||
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);
|
||
}
|
||
}
|
||
|
||
/* if we weren't on the active item, change the active item and turn
|
||
* it on
|
||
*/
|
||
if (!done)
|
||
{
|
||
ActiveItem = mi;
|
||
if (ActiveItem && ActiveItem->func != F_TITLE && !ActiveItem->state)
|
||
{
|
||
ActiveItem->state = 1;
|
||
PaintEntry(ActiveMenu, ActiveItem, False);
|
||
}
|
||
}
|
||
|
||
/* now check to see if we were over the arrow of a pull right entry */
|
||
if (ActiveItem && ActiveItem->func == F_MENU &&
|
||
((ActiveMenu->width - x) < (ActiveMenu->width / 3)))
|
||
{
|
||
MenuRoot *save = ActiveMenu;
|
||
int savex = MenuOrigins[MenuDepth - 1].x;
|
||
int savey = MenuOrigins[MenuDepth - 1].y;
|
||
|
||
if (MenuDepth < MAXMENUDEPTH) {
|
||
if (ActiveMenu == Scr->Workspaces)
|
||
CurrentSelectedWorkspace = ActiveItem->item;
|
||
PopUpMenu (ActiveItem->sub,
|
||
(savex + (((2 * ActiveMenu->width) / 3) - 1)),
|
||
(savey + ActiveItem->item_num * Scr->EntryHeight)
|
||
/*(savey + ActiveItem->item_num * Scr->EntryHeight +
|
||
(Scr->EntryHeight >> 1))*/, False);
|
||
CurrentSelectedWorkspace = NULL;
|
||
} else if (!badItem) {
|
||
XBell (dpy, 0);
|
||
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(char *name)
|
||
{
|
||
MenuRoot *tmp;
|
||
|
||
#define UNUSED_PIXEL ((unsigned long) (~0)) /* more than 24 bits */
|
||
|
||
tmp = (MenuRoot *) malloc(sizeof(MenuRoot));
|
||
tmp->highlight.fore = UNUSED_PIXEL;
|
||
tmp->highlight.back = UNUSED_PIXEL;
|
||
tmp->name = name;
|
||
tmp->prev = NULL;
|
||
tmp->first = NULL;
|
||
tmp->last = NULL;
|
||
tmp->defaultitem = NULL;
|
||
tmp->items = 0;
|
||
tmp->width = 0;
|
||
tmp->mapped = NEVER_MAPPED;
|
||
tmp->pull = FALSE;
|
||
tmp->w = None;
|
||
tmp->shadow = None;
|
||
tmp->real_menu = FALSE;
|
||
|
||
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;
|
||
}
|
||
|
||
if (strcmp(name, TWM_WINDOWS) == 0)
|
||
Scr->Windows = tmp;
|
||
|
||
if (strcmp(name, TWM_ICONS) == 0)
|
||
Scr->Icons = tmp;
|
||
|
||
if (strcmp(name, TWM_WORKSPACES) == 0) {
|
||
Scr->Workspaces = tmp;
|
||
if (!Scr->Windows) NewMenuRoot (TWM_WINDOWS);
|
||
}
|
||
if (strcmp(name, TWM_ALLWINDOWS) == 0)
|
||
Scr->AllWindows = tmp;
|
||
|
||
/* Added by dl 2004 */
|
||
if (strcmp(name, TWM_ALLICONS) == 0)
|
||
Scr->AllIcons = tmp;
|
||
|
||
/* Added by Dan Lilliehorn (dl@dl.nu) 2000-02-29 */
|
||
if (strcmp(name, TWM_KEYS) == 0)
|
||
Scr->Keys = tmp;
|
||
|
||
if (strcmp(name, TWM_VISIBLE) == 0)
|
||
Scr->Visible = tmp;
|
||
|
||
/* End addition */
|
||
|
||
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(MenuRoot *menu, char *item, char *action,
|
||
MenuRoot *sub, int func, char *fore, char *back)
|
||
{
|
||
MenuItem *tmp;
|
||
int width;
|
||
char *itemname;
|
||
XRectangle ink_rect;
|
||
XRectangle logical_rect;
|
||
|
||
#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;
|
||
|
||
if ((menu == Scr->Workspaces) ||
|
||
(menu == Scr->Windows) ||
|
||
(menu == Scr->Icons) ||
|
||
(menu == Scr->AllWindows) ||
|
||
|
||
/* Added by dl 2004 */
|
||
(menu == Scr->AllIcons) ||
|
||
|
||
/* Added by Dan Lillehorn (dl@dl.nu) 2000-02-29 */
|
||
(menu == Scr->Keys) ||
|
||
(menu == Scr->Visible)) {
|
||
|
||
itemname = item;
|
||
} else
|
||
if (*item == '*') {
|
||
itemname = item + 1;
|
||
menu->defaultitem = tmp;
|
||
}
|
||
else {
|
||
itemname = item;
|
||
}
|
||
|
||
tmp->item = itemname;
|
||
tmp->strlen = strlen(itemname);
|
||
tmp->action = action;
|
||
tmp->next = NULL;
|
||
tmp->sub = NULL;
|
||
tmp->state = 0;
|
||
tmp->func = func;
|
||
tmp->separated = 0;
|
||
|
||
if (!Scr->HaveFonts) CreateFonts();
|
||
|
||
XmbTextExtents(Scr->MenuFont.font_set,
|
||
itemname, tmp->strlen,
|
||
&ink_rect, &logical_rect);
|
||
width = logical_rect.width;
|
||
|
||
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;
|
||
GetColor(COLOR, &tmp->normal.fore, fore);
|
||
GetColor(COLOR, &tmp->normal.back, back);
|
||
if (Scr->use3Dmenus && !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(void)
|
||
{
|
||
MenuRoot *mr;
|
||
|
||
for (mr = Scr->MenuList; mr != NULL; mr = mr->next)
|
||
{
|
||
if (mr->real_menu == FALSE)
|
||
continue;
|
||
|
||
mr->pinned = False;
|
||
MakeMenu(mr);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
int MakeMenu(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, borderwidth;
|
||
unsigned long valuemask;
|
||
XSetWindowAttributes attributes;
|
||
Colormap cmap = Scr->RootColormaps.cwins[0]->colormap->c;
|
||
XRectangle ink_rect;
|
||
XRectangle logical_rect;
|
||
|
||
Scr->EntryHeight = Scr->MenuFont.height + 4;
|
||
|
||
/* lets first size the window accordingly */
|
||
if (mr->mapped == NEVER_MAPPED)
|
||
{
|
||
if (mr->pull == TRUE) {
|
||
mr->width += 16 + 10;
|
||
}
|
||
width = mr->width + 10;
|
||
for (cur = mr->first; cur != NULL; cur = cur->next) {
|
||
if (cur->func != F_TITLE)
|
||
cur->x = 5;
|
||
else {
|
||
XmbTextExtents(Scr->MenuFont.font_set, cur->item, cur->strlen,
|
||
&ink_rect, &logical_rect);
|
||
cur->x = width - logical_rect.width;
|
||
cur->x /= 2;
|
||
}
|
||
}
|
||
mr->height = mr->items * Scr->EntryHeight;
|
||
mr->width += 10;
|
||
if (Scr->use3Dmenus) {
|
||
mr->width += 2 * Scr->MenuShadowDepth;
|
||
mr->height += 2 * Scr->MenuShadowDepth;
|
||
}
|
||
if (Scr->Shadow && ! mr->pinned)
|
||
{
|
||
/*
|
||
* 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;
|
||
if (mr->pinned) {
|
||
attributes.event_mask = (ExposureMask | EnterWindowMask
|
||
| LeaveWindowMask | ButtonPressMask
|
||
| ButtonReleaseMask | PointerMotionMask
|
||
| ButtonMotionMask
|
||
);
|
||
attributes.cursor = Scr->MenuCursor;
|
||
valuemask |= CWCursor;
|
||
}
|
||
else
|
||
attributes.event_mask = (ExposureMask | EnterWindowMask);
|
||
|
||
if (Scr->SaveUnder && ! mr->pinned) {
|
||
valuemask |= CWSaveUnder;
|
||
attributes.save_under = True;
|
||
}
|
||
if (Scr->BackingStore) {
|
||
valuemask |= CWBackingStore;
|
||
attributes.backing_store = Always;
|
||
}
|
||
borderwidth = Scr->use3Dmenus ? 0 : 1;
|
||
mr->w = XCreateWindow (dpy, Scr->Root, 0, 0, (unsigned int) mr->width,
|
||
(unsigned int) mr->height, (unsigned int) borderwidth,
|
||
CopyFromParent, (unsigned int) CopyFromParent,
|
||
(Visual *) CopyFromParent,
|
||
valuemask, &attributes);
|
||
|
||
|
||
XSaveContext(dpy, mr->w, MenuContext, (XPointer)mr);
|
||
XSaveContext(dpy, mr->w, ScreenContext, (XPointer)Scr);
|
||
|
||
mr->mapped = UNMAPPED;
|
||
}
|
||
|
||
if (Scr->use3Dmenus && (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 * ((int)xcol.red / 6),
|
||
5 * ((int)xcol.green / 6),
|
||
5 * ((int)xcol.blue / 6));
|
||
save = Scr->FirstTime;
|
||
Scr->FirstTime = True;
|
||
GetColor (Scr->Monochrome, &mr->highlight.back, colname);
|
||
Scr->FirstTime = save;
|
||
}
|
||
|
||
if (Scr->use3Dmenus && (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 * ((int)xcol.red / 6),
|
||
5 * ((int)xcol.green / 6),
|
||
5 * ((int)xcol.blue / 6));
|
||
save = Scr->FirstTime;
|
||
Scr->FirstTime = True;
|
||
GetColor (Scr->Monochrome, &mr->highlight.fore, colname);
|
||
Scr->FirstTime = save;
|
||
}
|
||
if (Scr->use3Dmenus && !Scr->BeNiceToColormap) GetShadeColors (&mr->highlight);
|
||
|
||
/* get the default colors into the menus */
|
||
for (tmp = mr->first; tmp != NULL; tmp = tmp->next)
|
||
{
|
||
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;
|
||
}
|
||
if (Scr->use3Dmenus && !Scr->BeNiceToColormap) {
|
||
if (tmp->func != F_TITLE)
|
||
GetShadeColors (&tmp->highlight);
|
||
else
|
||
GetShadeColors (&tmp->normal);
|
||
}
|
||
}
|
||
mr->pmenu = NULL;
|
||
|
||
if (Scr->Monochrome == MONOCHROME || !Scr->InterpolateMenuColors)
|
||
return 0;
|
||
|
||
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;
|
||
|
||
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;
|
||
|
||
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;
|
||
|
||
XAllocColor(dpy, cmap, &f3);
|
||
XAllocColor(dpy, cmap, &b3);
|
||
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;
|
||
start->highlight.back = start->normal.fore;
|
||
start->highlight.fore = start->normal.back;
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
|
||
|
||
/***********************************************************************
|
||
*
|
||
* 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 (MenuRoot *menu, int x, int y, Bool center)
|
||
{
|
||
int WindowNameCount;
|
||
TwmWindow **WindowNames;
|
||
TwmWindow *tmp_win2,*tmp_win3;
|
||
int i;
|
||
int xl, yt;
|
||
Bool clipped;
|
||
#ifdef CLAUDE
|
||
char tmpname3 [256], tmpname4 [256];
|
||
int hasmoz = 0;
|
||
#endif
|
||
if (!menu) return False;
|
||
|
||
InstallRootColormap();
|
||
|
||
if ((menu == Scr->Windows) ||
|
||
(menu == Scr->Icons) ||
|
||
(menu == Scr->AllWindows) ||
|
||
/* Added by Dan 'dl' Lilliehorn 040607 */
|
||
(menu == Scr->AllIcons) ||
|
||
/* Added by Dan Lilliehorn (dl@dl.nu) 2000-02-29 */
|
||
(menu == Scr->Visible))
|
||
{
|
||
TwmWindow *tmp_win;
|
||
WorkSpace *ws;
|
||
Boolean all, icons, visible_, allicons; /* visible, allicons:
|
||
Added by dl */
|
||
int func;
|
||
|
||
/* this is the twm windows menu, let's go ahead and build it */
|
||
|
||
all = (menu == Scr->AllWindows);
|
||
icons = (menu == Scr->Icons);
|
||
visible_ = (menu == Scr->Visible); /* Added by dl */
|
||
allicons = (menu == Scr->AllIcons);
|
||
DestroyMenu (menu);
|
||
|
||
menu->first = NULL;
|
||
menu->last = NULL;
|
||
menu->items = 0;
|
||
menu->width = 0;
|
||
menu->mapped = NEVER_MAPPED;
|
||
menu->highlight.fore = UNUSED_PIXEL;
|
||
menu->highlight.back = UNUSED_PIXEL;
|
||
if (menu == Scr->Windows)
|
||
AddToMenu(menu, "TWM Windows", NULLSTR, NULL, F_TITLE,NULLSTR,NULLSTR);
|
||
else
|
||
if (menu == Scr->Icons)
|
||
AddToMenu(menu, "TWM Icons", NULLSTR, NULL, F_TITLE, NULLSTR, NULLSTR);
|
||
else
|
||
if (menu == Scr->Visible) /* Added by dl 2000 */
|
||
AddToMenu(menu, "TWM Visible", NULLSTR, NULL, F_TITLE, NULLSTR, NULLSTR);
|
||
else
|
||
if (menu == Scr->AllIcons) /* Added by dl 2004 */
|
||
AddToMenu(menu, "TWM All Icons", NULLSTR, NULL, F_TITLE, NULLSTR, NULLSTR);
|
||
else
|
||
AddToMenu(menu, "TWM All Windows", NULLSTR, NULL, F_TITLE,NULLSTR,NULLSTR);
|
||
|
||
ws = NULL;
|
||
|
||
if (! (all || allicons)
|
||
&& CurrentSelectedWorkspace && Scr->workSpaceManagerActive) {
|
||
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
||
if (strcmp (ws->name, CurrentSelectedWorkspace) == 0) break;
|
||
}
|
||
}
|
||
if (!Scr->currentvs) return False;
|
||
if (!ws) ws = Scr->currentvs->wsw->currentwspc;
|
||
|
||
for (tmp_win = Scr->FirstWindow, WindowNameCount = 0;
|
||
tmp_win != NULL;
|
||
tmp_win = tmp_win->next) {
|
||
if (tmp_win == Scr->workSpaceMgr.occupyWindow->twm_win) continue;
|
||
if (Scr->ShortAllWindowsMenus && (tmp_win->wspmgr || tmp_win->iconmgr)) continue;
|
||
|
||
if (!(all || allicons) && !OCCUPY (tmp_win, ws)) continue;
|
||
if (allicons && !tmp_win->isicon) continue;
|
||
if (icons && !tmp_win->isicon) continue;
|
||
if (visible_ && tmp_win->isicon) continue; /* added by dl */
|
||
WindowNameCount++;
|
||
}
|
||
WindowNames = (TwmWindow **)malloc(sizeof(TwmWindow *)*WindowNameCount);
|
||
WindowNameCount = 0;
|
||
for (tmp_win = Scr->FirstWindow;
|
||
tmp_win != NULL;
|
||
tmp_win = tmp_win->next)
|
||
{
|
||
if (LookInList (Scr->IconMenuDontShow, tmp_win->full_name, &tmp_win->class)) continue;
|
||
|
||
if (tmp_win == Scr->workSpaceMgr.occupyWindow->twm_win) continue;
|
||
if (Scr->ShortAllWindowsMenus &&
|
||
tmp_win == Scr->currentvs->wsw->twm_win) continue;
|
||
if (Scr->ShortAllWindowsMenus && tmp_win->iconmgr) continue;
|
||
|
||
if (!(all || allicons)&& ! OCCUPY (tmp_win, ws)) continue;
|
||
if (allicons && !tmp_win->isicon) continue;
|
||
if (icons && !tmp_win->isicon) continue;
|
||
if (visible_ && tmp_win->isicon) continue; /* added by dl */
|
||
tmp_win2 = tmp_win;
|
||
|
||
for (i = 0; i < WindowNameCount; i++) {
|
||
int compresult;
|
||
char *tmpname1, *tmpname2;
|
||
tmpname1 = tmp_win2->name;
|
||
tmpname2 = WindowNames[i]->name;
|
||
#ifdef CLAUDE
|
||
if (strlen (tmpname1) == 1) tmpname1 = " No title";
|
||
if (strlen (tmpname2) == 1) tmpname2 = " No title";
|
||
|
||
if (!strncasecmp (tmp_win2->class.res_class, "navigator", 9) ||
|
||
!strncasecmp (tmp_win2->class.res_class, "mozilla", 7)) {
|
||
tmpname3 [0] = ' '; tmpname3 [1] = '\0';
|
||
strcat (tmpname3, tmpname1);
|
||
} else {
|
||
strcpy (tmpname3, tmpname1);
|
||
}
|
||
if (!strncasecmp (WindowNames[i]->class.res_class, "navigator", 9) ||
|
||
!strncasecmp (WindowNames[i]->class.res_class, "mozilla", 7)) {
|
||
tmpname4 [0] = ' '; tmpname4 [1] = '\0';
|
||
strcat (tmpname4, tmpname2);
|
||
} else {
|
||
strcpy (tmpname4, tmpname2);
|
||
}
|
||
tmpname1 = tmpname3;
|
||
tmpname2 = tmpname4;
|
||
#endif
|
||
if (Scr->CaseSensitive)
|
||
compresult = strcmp(tmpname1,tmpname2);
|
||
else
|
||
compresult = XmuCompareISOLatin1(tmpname1,tmpname2);
|
||
if (compresult < 0) {
|
||
tmp_win3 = tmp_win2;
|
||
tmp_win2 = WindowNames[i];
|
||
WindowNames[i] = tmp_win3;
|
||
}
|
||
}
|
||
WindowNames[WindowNameCount] = tmp_win2;
|
||
WindowNameCount++;
|
||
}
|
||
func = (all || allicons || CurrentSelectedWorkspace) ? F_WINWARP :
|
||
F_POPUP;
|
||
for (i = 0; i < WindowNameCount; i++)
|
||
{
|
||
char *tmpname;
|
||
tmpname = WindowNames[i]->name;
|
||
#ifdef CLAUDE
|
||
if (!strncasecmp (WindowNames[i]->class.res_class, "navigator", 9) ||
|
||
!strncasecmp (WindowNames[i]->class.res_class, "mozilla", 7) ||
|
||
!strncasecmp (WindowNames[i]->class.res_class, "netscape", 8) ||
|
||
!strncasecmp (WindowNames[i]->class.res_class, "konqueror", 9)) {
|
||
hasmoz = 1;
|
||
}
|
||
if (hasmoz && strncasecmp (WindowNames[i]->class.res_class, "navigator", 9) &&
|
||
strncasecmp (WindowNames[i]->class.res_class, "mozilla", 7) &&
|
||
strncasecmp (WindowNames[i]->class.res_class, "netscape", 8) &&
|
||
strncasecmp (WindowNames[i]->class.res_class, "konqueror", 9)) {
|
||
menu->last->separated = 1;
|
||
hasmoz = 0;
|
||
}
|
||
#endif
|
||
AddToMenu(menu, tmpname, (char *)WindowNames[i],
|
||
NULL, func,NULL,NULL);
|
||
}
|
||
free(WindowNames);
|
||
|
||
menu->pinned = False;
|
||
MakeMenu(menu);
|
||
}
|
||
|
||
/* Keys added by dl */
|
||
|
||
if (menu == Scr->Keys) {
|
||
FuncKey *tmpKey;
|
||
char *tmpStr, *tmpStr2;
|
||
char modStr[5];
|
||
char *oldact = 0;
|
||
int oldmod = 0;
|
||
int tmpLen;
|
||
|
||
DestroyMenu (menu);
|
||
|
||
menu->first = NULL;
|
||
menu->last = NULL;
|
||
menu->items = 0;
|
||
menu->width = 0;
|
||
menu->mapped = NEVER_MAPPED;
|
||
menu->highlight.fore = UNUSED_PIXEL;
|
||
menu->highlight.back = UNUSED_PIXEL;
|
||
|
||
AddToMenu(menu, "Twm Keys", NULLSTR, NULL, F_TITLE, NULLSTR, NULLSTR);
|
||
|
||
for (tmpKey = Scr->FuncKeyRoot.next; tmpKey != NULL; tmpKey = tmpKey->next) {
|
||
if (tmpKey->func != F_EXEC) continue;
|
||
if ((tmpKey->action == oldact) && (tmpKey->mods == oldmod)) continue;
|
||
strcpy (modStr, "");
|
||
switch (tmpKey->mods) {
|
||
case 1: strcpy (modStr, "S"); break;
|
||
case 4: strcpy (modStr, "C"); break;
|
||
case 5: strcpy (modStr, "S + C"); break;
|
||
case 8: strcpy (modStr, "M"); break;
|
||
case 9: strcpy (modStr, "S + M"); break;
|
||
case 12: strcpy (modStr, "C + M"); break;
|
||
default: break;
|
||
}
|
||
tmpLen = (strlen (tmpKey->name) + strlen (modStr) + 5);
|
||
tmpStr = malloc (sizeof(char) * tmpLen);
|
||
sprintf (tmpStr,"[%s + %s]", tmpKey->name, modStr);
|
||
tmpStr2 = malloc (sizeof(char) * (strlen (tmpKey->action) + tmpLen + 2));
|
||
sprintf (tmpStr2, "%s %s", tmpStr, tmpKey->action);
|
||
|
||
AddToMenu (menu, tmpStr2, tmpKey->action, NULL, tmpKey->func, NULLSTR, NULLSTR);
|
||
oldact = tmpKey->action;
|
||
oldmod = tmpKey->mods;
|
||
}
|
||
menu->pinned = False;
|
||
MakeMenu(menu);
|
||
}
|
||
if (menu->w == None || menu->items == 0) return False;
|
||
|
||
/* Prevent recursively bringing up menus. */
|
||
if ((!menu->pinned) && (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;
|
||
|
||
if (menu->pinned) {
|
||
ActiveMenu = menu;
|
||
menu->mapped = MAPPED;
|
||
menu->entered = TRUE;
|
||
MenuOrigins [MenuDepth].x = menu->x;
|
||
MenuOrigins [MenuDepth].y = menu->y;
|
||
MenuDepth++;
|
||
|
||
XRaiseWindow (dpy, menu->w);
|
||
return (True);
|
||
}
|
||
|
||
XGrabPointer(dpy, Scr->Root, True,
|
||
ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
|
||
ButtonMotionMask | PointerMotionHintMask,
|
||
GrabModeAsync, GrabModeAsync,
|
||
Scr->Root,
|
||
Scr->MenuCursor, CurrentTime);
|
||
|
||
XGrabKeyboard (dpy, Scr->Root, True, GrabModeAsync, GrabModeAsync, 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
|
||
*/
|
||
clipped = FALSE;
|
||
if (x + menu->width > Scr->rootw) {
|
||
x = Scr->rootw - menu->width;
|
||
clipped = TRUE;
|
||
}
|
||
if (x < 0) {
|
||
x = 0;
|
||
clipped = TRUE;
|
||
}
|
||
if (y + menu->height > Scr->rooth) {
|
||
y = Scr->rooth - menu->height;
|
||
clipped = TRUE;
|
||
}
|
||
if (y < 0) {
|
||
y = 0;
|
||
clipped = TRUE;
|
||
}
|
||
MenuOrigins[MenuDepth].x = x;
|
||
MenuOrigins[MenuDepth].y = y;
|
||
MenuDepth++;
|
||
|
||
if (Scr->Root != Scr->CaptiveRoot) {
|
||
XReparentWindow (dpy, menu->shadow, Scr->Root, x, y);
|
||
XReparentWindow (dpy, menu->w, Scr->Root, x, y);
|
||
} else
|
||
XMoveWindow (dpy, menu->w, x, y);
|
||
if (Scr->Shadow) {
|
||
XMoveWindow (dpy, menu->shadow, x + SHADOWWIDTH, y + SHADOWWIDTH);
|
||
XRaiseWindow (dpy, menu->shadow);
|
||
}
|
||
XMapRaised(dpy, menu->w);
|
||
if (!Scr->NoWarpToMenuTitle && clipped && center) {
|
||
xl = x + (menu->width / 2);
|
||
yt = y + (Scr->EntryHeight / 2);
|
||
XWarpPointer (dpy, Scr->Root, Scr->Root, x, y, menu->width, menu->height, xl, yt);
|
||
}
|
||
if (Scr->Shadow) XMapWindow (dpy, menu->shadow);
|
||
XSync(dpy, 0);
|
||
return True;
|
||
}
|
||
|
||
|
||
|
||
/***********************************************************************
|
||
*
|
||
* Procedure:
|
||
* PopDownMenu - unhighlight the current menu selection and
|
||
* take down the menus
|
||
*
|
||
***********************************************************************
|
||
*/
|
||
|
||
int PopDownMenu(void)
|
||
{
|
||
MenuRoot *tmp;
|
||
|
||
if (ActiveMenu == NULL)
|
||
return (1);
|
||
|
||
if (ActiveItem)
|
||
{
|
||
ActiveItem->state = 0;
|
||
PaintEntry(ActiveMenu, ActiveItem, False);
|
||
}
|
||
|
||
for (tmp = ActiveMenu; tmp != NULL; tmp = tmp->prev)
|
||
{
|
||
if (! tmp->pinned) HideMenu (tmp);
|
||
UninstallRootColormap();
|
||
}
|
||
|
||
XFlush(dpy);
|
||
ActiveMenu = NULL;
|
||
ActiveItem = NULL;
|
||
MenuDepth = 0;
|
||
XUngrabKeyboard (dpy, CurrentTime);
|
||
if (Context == C_WINDOW || Context == C_FRAME || Context == C_TITLE || Context == C_ICON)
|
||
menuFromFrameOrWindowOrTitlebar = TRUE;
|
||
|
||
return 1;
|
||
}
|
||
|
||
|
||
|
||
Bool HideMenu (MenuRoot *menu)
|
||
{
|
||
if (!menu) return False;
|
||
|
||
if (Scr->Shadow) {
|
||
XUnmapWindow (dpy, menu->shadow);
|
||
}
|
||
XUnmapWindow (dpy, menu->w);
|
||
menu->mapped = UNMAPPED;
|
||
|
||
return 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(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 (register TwmWindow *t, register Window w)
|
||
{
|
||
if (!t) return False;
|
||
|
||
if (w == t->frame || w == t->title_w || w == t->hilite_wl || w == t->hilite_wr ||
|
||
(t->icon && (w == t->icon->w || w == t->icon->bm_w))) return True;
|
||
|
||
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;
|
||
}
|
||
|
||
|
||
|
||
|
||
/***********************************************************************
|
||
*
|
||
* Procedure:
|
||
* resizeFromCenter -
|
||
*
|
||
***********************************************************************
|
||
*/
|
||
|
||
void resizeFromCenter(Window w, TwmWindow *tmp_win)
|
||
{
|
||
int lastx, lasty, bw2;
|
||
int namelen;
|
||
XRectangle inc_rect;
|
||
XRectangle logical_rect;
|
||
|
||
namelen = strlen (tmp_win->name);
|
||
bw2 = tmp_win->frame_bw * 2;
|
||
AddingW = tmp_win->attr.width + bw2 + 2 * tmp_win->frame_bw3D;
|
||
AddingH = tmp_win->attr.height + tmp_win->title_height + bw2 + 2 * tmp_win->frame_bw3D;
|
||
|
||
XmbTextExtents(Scr->SizeFont.font_set, tmp_win->name, namelen,
|
||
&inc_rect, &logical_rect);
|
||
|
||
XGetGeometry(dpy, w, &JunkRoot, &origDragX, &origDragY,
|
||
&DragWidth, &DragHeight,
|
||
&JunkBW, &JunkDepth);
|
||
|
||
XWarpPointer(dpy, None, w,
|
||
0, 0, 0, 0, DragWidth/2, DragHeight/2);
|
||
XQueryPointer (dpy, Scr->Root, &JunkRoot,
|
||
&JunkChild, &JunkX, &JunkY,
|
||
&AddingX, &AddingY, &JunkMask);
|
||
|
||
lastx = -10000;
|
||
lasty = -10000;
|
||
|
||
MenuStartResize(tmp_win, origDragX, origDragY, DragWidth, DragHeight);
|
||
while (TRUE)
|
||
{
|
||
XMaskEvent(dpy,
|
||
ButtonPressMask | PointerMotionMask | ExposureMask, &Event);
|
||
|
||
if (Event.type == MotionNotify) {
|
||
/* discard any extra motion events before a release */
|
||
while(XCheckMaskEvent(dpy,
|
||
ButtonMotionMask | ButtonPressMask, &Event))
|
||
if (Event.type == ButtonPress)
|
||
break;
|
||
}
|
||
|
||
if (Event.type == ButtonPress)
|
||
{
|
||
MenuEndResize(tmp_win);
|
||
XMoveResizeWindow(dpy, w, AddingX, AddingY, AddingW, AddingH);
|
||
break;
|
||
}
|
||
|
||
if (Event.type != MotionNotify) {
|
||
(void)DispatchEvent2 ();
|
||
continue;
|
||
}
|
||
|
||
/*
|
||
* XXX - if we are going to do a loop, we ought to consider
|
||
* using multiple GXxor lines so that we don't need to
|
||
* grab the server.
|
||
*/
|
||
XQueryPointer(dpy, Scr->Root, &JunkRoot, &JunkChild,
|
||
&JunkX, &JunkY, &AddingX, &AddingY, &JunkMask);
|
||
|
||
if (lastx != AddingX || lasty != AddingY)
|
||
{
|
||
MenuDoResize(AddingX, AddingY, tmp_win);
|
||
|
||
lastx = AddingX;
|
||
lasty = AddingY;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/***********************************************************************
|
||
*
|
||
* 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
|
||
*
|
||
***********************************************************************
|
||
*/
|
||
|
||
int ExecuteFunction(int func, void *action, Window w, TwmWindow *tmp_win,
|
||
XEvent *eventp, int context, int pulldown)
|
||
{
|
||
static Time last_time = 0;
|
||
char tmp[200];
|
||
char *ptr;
|
||
char buff[MAX_FILE_SIZE];
|
||
int count, fd;
|
||
Window rootw;
|
||
int origX, origY;
|
||
int do_next_action = TRUE;
|
||
int moving_icon = FALSE;
|
||
Bool fromtitlebar = False;
|
||
Bool from3dborder = False;
|
||
TwmWindow *t;
|
||
|
||
RootFunction = 0;
|
||
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_WARPTOSCREEN:
|
||
case F_WARPTO:
|
||
case F_WARPRING:
|
||
case F_WARPTOICONMGR:
|
||
case F_COLORMAP:
|
||
case F_ALTKEYMAP:
|
||
case F_ALTCONTEXT:
|
||
break;
|
||
|
||
default:
|
||
XGrabPointer(dpy, Scr->Root, True,
|
||
ButtonPressMask | ButtonReleaseMask,
|
||
GrabModeAsync, GrabModeAsync,
|
||
Scr->Root, Scr->WaitCursor, CurrentTime);
|
||
break;
|
||
}
|
||
|
||
switch (func)
|
||
{
|
||
#ifdef SOUNDS
|
||
case F_TOGGLESOUND:
|
||
toggle_sound();
|
||
break;
|
||
case F_REREADSOUNDS:
|
||
reread_sounds();
|
||
break;
|
||
#endif
|
||
case F_NOP:
|
||
case F_TITLE:
|
||
break;
|
||
|
||
case F_DELTASTOP:
|
||
if (WindowMoved) do_next_action = FALSE;
|
||
break;
|
||
|
||
case F_RESTART: {
|
||
DoRestart(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_FORWMAPICONMGR:
|
||
case F_BACKMAPICONMGR:
|
||
MoveMappedIconManager(func);
|
||
break;
|
||
|
||
case F_NEXTICONMGR:
|
||
case F_PREVICONMGR:
|
||
JumpIconManager(func);
|
||
break;
|
||
|
||
case F_SHOWLIST:
|
||
if (Scr->NoIconManagers) break;
|
||
ShowIconManager ();
|
||
break;
|
||
|
||
case F_STARTANIMATION :
|
||
StartAnimation ();
|
||
break;
|
||
|
||
case F_STOPANIMATION :
|
||
StopAnimation ();
|
||
break;
|
||
|
||
case F_SPEEDUPANIMATION :
|
||
ModifyAnimationSpeed (1);
|
||
break;
|
||
|
||
case F_SLOWDOWNANIMATION :
|
||
ModifyAnimationSpeed (-1);
|
||
break;
|
||
|
||
case F_HIDELIST:
|
||
if (Scr->NoIconManagers) break;
|
||
HideIconManager ();
|
||
break;
|
||
|
||
case F_SHOWWORKMGR:
|
||
if (! Scr->workSpaceManagerActive) break;
|
||
DeIconify (Scr->currentvs->wsw->twm_win);
|
||
RaiseWindow(Scr->currentvs->wsw->twm_win);
|
||
break;
|
||
|
||
case F_HIDEWORKMGR:
|
||
if (! Scr->workSpaceManagerActive) break;
|
||
Iconify (Scr->currentvs->wsw->twm_win, eventp->xbutton.x_root - 5,
|
||
eventp->xbutton.y_root - 5);
|
||
break;
|
||
|
||
case F_TOGGLEWORKMGR:
|
||
if (! Scr->workSpaceManagerActive) break;
|
||
if (Scr->currentvs->wsw->twm_win->mapped)
|
||
Iconify (Scr->currentvs->wsw->twm_win, eventp->xbutton.x_root - 5,
|
||
eventp->xbutton.y_root - 5);
|
||
else {
|
||
DeIconify (Scr->currentvs->wsw->twm_win);
|
||
RaiseWindow(Scr->currentvs->wsw->twm_win);
|
||
}
|
||
break;
|
||
|
||
case F_TOGGLESTATE :
|
||
WMapToggleState (Scr->currentvs);
|
||
break;
|
||
|
||
case F_SETBUTTONSTATE :
|
||
WMapSetButtonsState (Scr->currentvs);
|
||
break;
|
||
|
||
case F_SETMAPSTATE :
|
||
WMapSetMapState (Scr->currentvs);
|
||
break;
|
||
|
||
case F_PIN :
|
||
if (! ActiveMenu) break;
|
||
if (ActiveMenu->pinned) {
|
||
XUnmapWindow (dpy, ActiveMenu->w);
|
||
ActiveMenu->mapped = UNMAPPED;
|
||
}
|
||
else {
|
||
XWindowAttributes attr;
|
||
MenuRoot *menu;
|
||
|
||
if (ActiveMenu->pmenu == NULL) {
|
||
menu = (MenuRoot*) malloc (sizeof (struct MenuRoot));
|
||
*menu = *ActiveMenu;
|
||
menu->pinned = True;
|
||
menu->mapped = NEVER_MAPPED;
|
||
menu->width -= 10;
|
||
if (menu->pull) menu->width -= 16 + 10;
|
||
MakeMenu (menu);
|
||
ActiveMenu->pmenu = menu;
|
||
}
|
||
else menu = ActiveMenu->pmenu;
|
||
if (menu->mapped == MAPPED) break;
|
||
XGetWindowAttributes (dpy, ActiveMenu->w, &attr);
|
||
menu->x = attr.x;
|
||
menu->y = attr.y;
|
||
XMoveWindow (dpy, menu->w, menu->x, menu->y);
|
||
XMapRaised (dpy, menu->w);
|
||
menu->mapped = MAPPED;
|
||
}
|
||
PopDownMenu();
|
||
break;
|
||
|
||
case F_MOVEMENU:
|
||
break;
|
||
|
||
case F_FITTOCONTENT :
|
||
if (DeferExecution (context, func, Scr->SelectCursor)) return TRUE;
|
||
if (!tmp_win->iswinbox) {
|
||
XBell (dpy, 0);
|
||
break;
|
||
}
|
||
fittocontent (tmp_win);
|
||
break;
|
||
|
||
case F_VANISH:
|
||
if (DeferExecution (context, func, Scr->SelectCursor)) return TRUE;
|
||
|
||
WMgrRemoveFromCurrentWorkSpace (Scr->currentvs, tmp_win);
|
||
break;
|
||
|
||
case F_WARPHERE:
|
||
WMgrAddToCurrentWorkSpaceAndWarp (Scr->currentvs, action);
|
||
break;
|
||
|
||
case F_ADDTOWORKSPACE:
|
||
if (DeferExecution (context, func, Scr->SelectCursor)) return TRUE;
|
||
AddToWorkSpace (action, tmp_win);
|
||
break;
|
||
|
||
case F_REMOVEFROMWORKSPACE:
|
||
if (DeferExecution (context, func, Scr->SelectCursor)) return TRUE;
|
||
RemoveFromWorkSpace (action, tmp_win);
|
||
break;
|
||
|
||
case F_TOGGLEOCCUPATION:
|
||
if (DeferExecution (context, func, Scr->SelectCursor)) return TRUE;
|
||
ToggleOccupation (action, tmp_win);
|
||
break;
|
||
|
||
case F_MOVETONEXTWORKSPACE:
|
||
if (DeferExecution (context, func, Scr->SelectCursor)) return TRUE;
|
||
MoveToNextWorkSpace(Scr->currentvs,tmp_win);
|
||
break;
|
||
|
||
case F_MOVETOPREVWORKSPACE:
|
||
if (DeferExecution (context, func, Scr->SelectCursor)) return TRUE;
|
||
MoveToPrevWorkSpace(Scr->currentvs,tmp_win);
|
||
break;
|
||
|
||
case F_MOVETONEXTWORKSPACEANDFOLLOW:
|
||
if (DeferExecution (context, func, Scr->SelectCursor)) return TRUE;
|
||
MoveToNextWorkSpaceAndFollow(Scr->currentvs,tmp_win);
|
||
break;
|
||
|
||
case F_MOVETOPREVWORKSPACEANDFOLLOW:
|
||
if (DeferExecution (context, func, Scr->SelectCursor)) return TRUE;
|
||
MoveToPrevWorkSpaceAndFollow(Scr->currentvs,tmp_win);
|
||
break;
|
||
|
||
case F_SORTICONMGR:
|
||
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
|
||
XBell(dpy, 0);
|
||
|
||
Scr->SortIconMgr = save_sort;
|
||
}
|
||
break;
|
||
|
||
case F_ALTKEYMAP: {
|
||
int alt, stat_;
|
||
|
||
if (! action) return TRUE;
|
||
stat_ = sscanf (action, "%d", &alt);
|
||
if (stat_ != 1) return TRUE;
|
||
if ((alt < 1) || (alt > 5)) return TRUE;
|
||
AlternateKeymap = Alt1Mask << (alt - 1);
|
||
XGrabPointer (dpy, Scr->Root, True, ButtonPressMask | ButtonReleaseMask,
|
||
GrabModeAsync, GrabModeAsync,
|
||
Scr->Root, Scr->AlterCursor, CurrentTime);
|
||
XGrabKeyboard (dpy, Scr->Root, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||
return TRUE;
|
||
}
|
||
|
||
case F_ALTCONTEXT: {
|
||
AlternateContext = True;
|
||
XGrabPointer (dpy, Scr->Root, False, ButtonPressMask | ButtonReleaseMask,
|
||
GrabModeAsync, GrabModeAsync,
|
||
Scr->Root, Scr->AlterCursor, CurrentTime);
|
||
XGrabKeyboard (dpy, Scr->Root, False, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||
return TRUE;
|
||
}
|
||
case F_IDENTIFY:
|
||
if (DeferExecution(context, func, Scr->SelectCursor))
|
||
return TRUE;
|
||
|
||
Identify(tmp_win);
|
||
break;
|
||
|
||
case F_INITSIZE: {
|
||
int grav, x, y;
|
||
unsigned int width, height, swidth, sheight;
|
||
|
||
if (DeferExecution (context, func, Scr->SelectCursor)) return TRUE;
|
||
grav = ((tmp_win->hints.flags & PWinGravity)
|
||
? tmp_win->hints.win_gravity : NorthWestGravity);
|
||
|
||
if (!(tmp_win->hints.flags & USSize) && !(tmp_win->hints.flags & PSize)) break;
|
||
|
||
width = tmp_win->hints.width + 2 * tmp_win->frame_bw3D;
|
||
height = tmp_win->hints.height + 2 * tmp_win->frame_bw3D + tmp_win->title_height;
|
||
ConstrainSize (tmp_win, &width, &height);
|
||
|
||
x = tmp_win->frame_x;
|
||
y = tmp_win->frame_y;
|
||
swidth = tmp_win->frame_width;
|
||
sheight = tmp_win->frame_height;
|
||
switch (grav) {
|
||
case ForgetGravity :
|
||
case StaticGravity :
|
||
case NorthWestGravity :
|
||
case NorthGravity :
|
||
case WestGravity :
|
||
case CenterGravity :
|
||
break;
|
||
|
||
case NorthEastGravity :
|
||
case EastGravity :
|
||
x += swidth - width;
|
||
break;
|
||
|
||
case SouthWestGravity :
|
||
case SouthGravity :
|
||
y += sheight - height;
|
||
break;
|
||
|
||
case SouthEastGravity :
|
||
x += swidth - width;
|
||
y += sheight - height;
|
||
break;
|
||
}
|
||
SetupWindow (tmp_win, x, y, width, height, -1);
|
||
break;
|
||
}
|
||
|
||
case F_MOVERESIZE: {
|
||
int x, y, mask;
|
||
unsigned int width, height;
|
||
int px = 20, py = 30;
|
||
|
||
if (DeferExecution (context, func, Scr->SelectCursor)) return TRUE;
|
||
mask = XParseGeometry (action, &x, &y, &width, &height);
|
||
if (!(mask & WidthValue)) width = tmp_win->frame_width;
|
||
else width += 2 * tmp_win->frame_bw3D;
|
||
if (!(mask & HeightValue)) height = tmp_win->frame_height;
|
||
else height += 2 * tmp_win->frame_bw3D + tmp_win->title_height;
|
||
ConstrainSize (tmp_win, &width, &height);
|
||
if (mask & XValue) {
|
||
if (mask & XNegative) x += Scr->rootw - width;
|
||
} else x = tmp_win->frame_x;
|
||
if (mask & YValue) {
|
||
if (mask & YNegative) y += Scr->rooth - height;
|
||
} else y = tmp_win->frame_y;
|
||
|
||
{
|
||
int junkX, junkY;
|
||
unsigned int junkK;
|
||
Window junkW;
|
||
XQueryPointer (dpy, Scr->Root, &junkW, &junkW, &junkX, &junkY, &px, &py, &junkK);
|
||
}
|
||
px -= tmp_win->frame_x; if (px > width) px = width / 2;
|
||
py -= tmp_win->frame_y; if (py > height) px = height / 2;
|
||
SetupWindow (tmp_win, x, y, width, height, -1);
|
||
XWarpPointer (dpy, Scr->Root, Scr->Root, 0, 0, 0, 0, x + px, y + py);
|
||
break;
|
||
}
|
||
|
||
case F_VERSION:
|
||
Identify ((TwmWindow *) NULL);
|
||
break;
|
||
|
||
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_AUTOLOWER:
|
||
if (DeferExecution(context, func, Scr->SelectCursor))
|
||
return TRUE;
|
||
|
||
tmp_win->auto_lower = !tmp_win->auto_lower;
|
||
if (tmp_win->auto_lower) ++(Scr->NumAutoLowers);
|
||
else --(Scr->NumAutoLowers);
|
||
break;
|
||
|
||
case F_BEEP:
|
||
XBell(dpy, 0);
|
||
break;
|
||
|
||
case F_POPUP:
|
||
tmp_win = (TwmWindow *)action;
|
||
if (! tmp_win) break;
|
||
if (Scr->WindowFunction.func != 0)
|
||
{
|
||
ExecuteFunction(Scr->WindowFunction.func,
|
||
Scr->WindowFunction.item->action,
|
||
w, tmp_win, eventp, C_FRAME, FALSE);
|
||
}
|
||
else
|
||
{
|
||
DeIconify(tmp_win);
|
||
RaiseWindow (tmp_win);
|
||
}
|
||
break;
|
||
|
||
case F_WINWARP:
|
||
tmp_win = (TwmWindow *)action;
|
||
|
||
if (! tmp_win) break;
|
||
if (Scr->WarpUnmapped || tmp_win->mapped) {
|
||
if (!tmp_win->mapped) DeIconify (tmp_win);
|
||
WarpToWindow (tmp_win, Scr->RaiseOnWarp);
|
||
}
|
||
break;
|
||
|
||
case F_RESIZE:
|
||
EventHandler[EnterNotify] = HandleUnknown;
|
||
EventHandler[LeaveNotify] = HandleUnknown;
|
||
if (DeferExecution(context, func, Scr->MoveCursor))
|
||
return TRUE;
|
||
|
||
PopDownMenu();
|
||
if (tmp_win->squeezed) {
|
||
XBell (dpy, 0);
|
||
break;
|
||
}
|
||
if (tmp_win->OpaqueResize) {
|
||
/*
|
||
* OpaqueResize defaults to a thousand. Assume that any number
|
||
* >= 1000 is "infinity" and don't bother calculating.
|
||
*/
|
||
if (Scr->OpaqueResizeThreshold >= 1000)
|
||
Scr->OpaqueResize = TRUE;
|
||
else {
|
||
/*
|
||
* scrsz will hold the number of pixels in your resolution,
|
||
* which can get big. [signed] int may not cut it.
|
||
*/
|
||
unsigned long winsz, scrsz;
|
||
winsz = tmp_win->frame_width * tmp_win->frame_height;
|
||
scrsz = Scr->rootw * Scr->rooth;
|
||
if (winsz > (scrsz * (Scr->OpaqueResizeThreshold / 100.0)))
|
||
Scr->OpaqueResize = FALSE;
|
||
else
|
||
Scr->OpaqueResize = TRUE;
|
||
}
|
||
}
|
||
else
|
||
Scr->OpaqueResize = FALSE;
|
||
|
||
if (pulldown)
|
||
XWarpPointer(dpy, None, Scr->Root,
|
||
0, 0, 0, 0, eventp->xbutton.x_root, eventp->xbutton.y_root);
|
||
|
||
if (!tmp_win->icon || (w != tmp_win->icon->w)) { /* can't resize icons */
|
||
|
||
/* fromMenu = False; ????? */
|
||
if ((Context == C_FRAME || Context == C_WINDOW || Context == C_TITLE)
|
||
&& fromMenu)
|
||
resizeFromCenter(w, tmp_win);
|
||
else {
|
||
/*
|
||
* see if this is being done from the titlebar
|
||
*/
|
||
from3dborder = (eventp->xbutton.window == tmp_win->frame);
|
||
fromtitlebar = !from3dborder &&
|
||
belongs_to_twm_window (tmp_win, eventp->xbutton.window);
|
||
|
||
/* Save pointer position so we can tell if it was moved or
|
||
not during the resize. */
|
||
ResizeOrigX = eventp->xbutton.x_root;
|
||
ResizeOrigY = eventp->xbutton.y_root;
|
||
|
||
StartResize (eventp, tmp_win, fromtitlebar, from3dborder);
|
||
|
||
do {
|
||
XMaskEvent(dpy,
|
||
ButtonPressMask | ButtonReleaseMask |
|
||
EnterWindowMask | LeaveWindowMask |
|
||
ButtonMotionMask | VisibilityChangeMask | ExposureMask, &Event);
|
||
|
||
if (fromtitlebar && Event.type == ButtonPress) {
|
||
fromtitlebar = False;
|
||
continue;
|
||
}
|
||
|
||
if (Event.type == MotionNotify) {
|
||
/* discard any extra motion events before a release */
|
||
while
|
||
(XCheckMaskEvent
|
||
(dpy, ButtonMotionMask | ButtonReleaseMask, &Event))
|
||
if (Event.type == ButtonRelease)
|
||
break;
|
||
}
|
||
|
||
if (!DispatchEvent2 ()) continue;
|
||
|
||
} while (!(Event.type == ButtonRelease || Cancel));
|
||
return TRUE;
|
||
}
|
||
}
|
||
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;
|
||
if (tmp_win->squeezed) {
|
||
XBell(dpy, 0);
|
||
break;
|
||
}
|
||
fullzoom(tmp_win, func);
|
||
break;
|
||
|
||
case F_PACK:
|
||
if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE;
|
||
if (tmp_win->squeezed) { XBell(dpy, 0); break; }
|
||
packwindow (tmp_win, action);
|
||
break;
|
||
|
||
case F_FILL:
|
||
if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE;
|
||
if (tmp_win->squeezed) { XBell(dpy, 0); break; }
|
||
fillwindow (tmp_win, action);
|
||
break;
|
||
|
||
case F_JUMPLEFT:
|
||
if (DeferExecution(context, func, Scr->MoveCursor)) return TRUE;
|
||
if (tmp_win->squeezed) { XBell(dpy, 0); break; }
|
||
jump (tmp_win, J_LEFT, action);
|
||
break;
|
||
case F_JUMPRIGHT:
|
||
if (DeferExecution(context, func, Scr->MoveCursor)) return TRUE;
|
||
if (tmp_win->squeezed) { XBell(dpy, 0); break; }
|
||
jump (tmp_win, J_RIGHT, action);
|
||
break;
|
||
case F_JUMPDOWN:
|
||
if (DeferExecution(context, func, Scr->MoveCursor)) return TRUE;
|
||
if (tmp_win->squeezed) { XBell(dpy, 0); break; }
|
||
jump (tmp_win, J_BOTTOM, action);
|
||
break;
|
||
case F_JUMPUP:
|
||
if (DeferExecution(context, func, Scr->MoveCursor)) return TRUE;
|
||
if (tmp_win->squeezed) { XBell(dpy, 0); break; }
|
||
jump (tmp_win, J_TOP, action);
|
||
break;
|
||
|
||
case F_SAVEGEOMETRY:
|
||
if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE;
|
||
savegeometry (tmp_win);
|
||
break;
|
||
|
||
case F_RESTOREGEOMETRY:
|
||
if (DeferExecution(context, func, Scr->SelectCursor)) return TRUE;
|
||
restoregeometry (tmp_win);
|
||
break;
|
||
|
||
case F_HYPERMOVE: {
|
||
Bool cont = True;
|
||
Window root = RootWindow (dpy, Scr->screen);
|
||
Cursor cursor;
|
||
CaptiveCTWM cctwm0, cctwm;
|
||
|
||
if (DeferExecution(context, func, Scr->MoveCursor)) return TRUE;
|
||
|
||
if (tmp_win->iswinbox || tmp_win->wspmgr) {
|
||
XBell (dpy, 0);
|
||
break;
|
||
}
|
||
cctwm0 = GetCaptiveCTWMUnderPointer ();
|
||
cursor = MakeStringCursor (cctwm0.name);
|
||
free (cctwm0.name);
|
||
if (DeferExecution (context, func, Scr->MoveCursor)) return TRUE;
|
||
|
||
XGrabPointer (dpy, root, True,
|
||
ButtonPressMask | ButtonMotionMask | ButtonReleaseMask,
|
||
GrabModeAsync, GrabModeAsync, root, cursor, CurrentTime);
|
||
while (cont) {
|
||
XMaskEvent (dpy, ButtonPressMask | ButtonMotionMask |
|
||
ButtonReleaseMask, &Event);
|
||
switch (Event.xany.type) {
|
||
case ButtonPress :
|
||
cont = False;
|
||
break;
|
||
|
||
case ButtonRelease :
|
||
cont = False;
|
||
cctwm = GetCaptiveCTWMUnderPointer ();
|
||
free (cctwm.name);
|
||
if (cctwm.root == Scr->Root) break;
|
||
SetNoRedirect (tmp_win->w);
|
||
XUngrabButton (dpy, AnyButton, AnyModifier, tmp_win->w);
|
||
XReparentWindow (dpy, tmp_win->w, cctwm.root, 0, 0);
|
||
XMapWindow (dpy, tmp_win->w);
|
||
break;
|
||
|
||
case MotionNotify :
|
||
cctwm = GetCaptiveCTWMUnderPointer ();
|
||
if (cctwm.root != cctwm0.root) {
|
||
XFreeCursor (dpy, cursor);
|
||
cursor = MakeStringCursor (cctwm.name);
|
||
cctwm0 = cctwm;
|
||
XChangeActivePointerGrab (dpy,
|
||
ButtonPressMask | ButtonMotionMask | ButtonReleaseMask,
|
||
cursor, CurrentTime);
|
||
}
|
||
free (cctwm.name);
|
||
break;
|
||
}
|
||
}
|
||
ButtonPressed = -1;
|
||
XUngrabPointer (dpy, CurrentTime);
|
||
XFreeCursor (dpy, cursor);
|
||
break;
|
||
}
|
||
|
||
case F_MOVE:
|
||
case F_FORCEMOVE:
|
||
case F_MOVEPACK:
|
||
case F_MOVEPUSH: {
|
||
Window grabwin, dragroot;
|
||
|
||
if (DeferExecution(context, func, Scr->MoveCursor))
|
||
return TRUE;
|
||
|
||
PopDownMenu();
|
||
if (tmp_win->OpaqueMove) {
|
||
int sw, ss;
|
||
float sf;
|
||
|
||
sw = tmp_win->frame_width * tmp_win->frame_height;
|
||
ss = Scr->rootw * Scr->rooth;
|
||
sf = Scr->OpaqueMoveThreshold / 100.0;
|
||
if (sw > (ss * sf))
|
||
Scr->OpaqueMove = FALSE;
|
||
else
|
||
Scr->OpaqueMove = TRUE;
|
||
}
|
||
else
|
||
Scr->OpaqueMove = FALSE;
|
||
|
||
dragroot = Scr->XineramaRoot;
|
||
|
||
if (tmp_win->winbox) {
|
||
XTranslateCoordinates (dpy, dragroot, tmp_win->winbox->window,
|
||
eventp->xbutton.x_root, eventp->xbutton.y_root,
|
||
&(eventp->xbutton.x_root), &(eventp->xbutton.y_root), &JunkChild);
|
||
}
|
||
rootw = eventp->xbutton.root;
|
||
MoveFunction = func;
|
||
|
||
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;
|
||
|
||
if (!Scr->NoGrabServer || !Scr->OpaqueMove) {
|
||
XGrabServer(dpy);
|
||
}
|
||
|
||
Scr->SizeStringOffset = SIZE_HINDENT;
|
||
XResizeWindow (dpy, Scr->SizeWindow,
|
||
Scr->SizeStringWidth + SIZE_HINDENT * 2,
|
||
Scr->SizeFont.height + SIZE_VINDENT * 2);
|
||
XMapRaised (dpy, Scr->SizeWindow);
|
||
|
||
grabwin = Scr->XineramaRoot;
|
||
if (tmp_win->winbox) grabwin = tmp_win->winbox->window;
|
||
XGrabPointer(dpy, grabwin, True,
|
||
ButtonPressMask | ButtonReleaseMask |
|
||
ButtonMotionMask | PointerMotionMask, /* PointerMotionHintMask */
|
||
GrabModeAsync, GrabModeAsync, grabwin, Scr->MoveCursor, CurrentTime);
|
||
|
||
if (context == C_ICON && tmp_win->icon && tmp_win->icon->w)
|
||
{
|
||
w = tmp_win->icon->w;
|
||
DragX = eventp->xbutton.x;
|
||
DragY = eventp->xbutton.y;
|
||
moving_icon = TRUE;
|
||
if (tmp_win->OpaqueMove) Scr->OpaqueMove = TRUE;
|
||
}
|
||
|
||
else if (! tmp_win->icon || w != tmp_win->icon->w)
|
||
{
|
||
XTranslateCoordinates(dpy, w, tmp_win->frame,
|
||
eventp->xbutton.x,
|
||
eventp->xbutton.y,
|
||
&DragX, &DragY, &JunkChild);
|
||
|
||
w = tmp_win->frame;
|
||
}
|
||
|
||
DragWindow = None;
|
||
|
||
/* Get x/y relative to parent window, i.e. the virtual screen, Root.
|
||
* XMoveWindow() moves are relative to this.
|
||
* MoveOutline()s however are drawn from the XineramaRoot since they
|
||
* may cross virtual screens.
|
||
*/
|
||
XGetGeometry(dpy, w, &JunkRoot, &origDragX, &origDragY,
|
||
&DragWidth, &DragHeight, &DragBW,
|
||
&JunkDepth);
|
||
|
||
JunkBW = DragBW;
|
||
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;
|
||
|
||
if (!Scr->OpaqueMove)
|
||
{
|
||
InstallRootColormap();
|
||
if (!Scr->MoveDelta)
|
||
{
|
||
/*
|
||
* 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(dragroot,
|
||
origDragX - JunkBW + Scr->currentvs->x,
|
||
origDragY - JunkBW + Scr->currentvs->y,
|
||
DragWidth + 2 * JunkBW, DragHeight + 2 * JunkBW,
|
||
tmp_win->frame_bw,
|
||
moving_icon ? 0 : tmp_win->title_height + tmp_win->frame_bw3D);
|
||
/*
|
||
* This next line causes HandleReleaseNotify 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).
|
||
*/
|
||
DragWindow = w;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* see if this is being done from the titlebar
|
||
*/
|
||
fromtitlebar = belongs_to_twm_window (tmp_win, eventp->xbutton.window);
|
||
|
||
if (menuFromFrameOrWindowOrTitlebar) {
|
||
/* warp the pointer to the middle of the window */
|
||
XWarpPointer(dpy, None, Scr->Root, 0, 0, 0, 0,
|
||
origDragX + DragWidth / 2,
|
||
origDragY + DragHeight / 2);
|
||
XFlush(dpy);
|
||
}
|
||
|
||
DisplayPosition (tmp_win, CurrentDragX, CurrentDragY);
|
||
while (TRUE)
|
||
{
|
||
long releaseEvent = menuFromFrameOrWindowOrTitlebar ?
|
||
ButtonPress : ButtonRelease;
|
||
long movementMask = menuFromFrameOrWindowOrTitlebar ?
|
||
PointerMotionMask : ButtonMotionMask;
|
||
|
||
/* block until there is an interesting event */
|
||
XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask |
|
||
EnterWindowMask | LeaveWindowMask |
|
||
ExposureMask | movementMask |
|
||
VisibilityChangeMask, &Event);
|
||
|
||
/* throw away enter and leave events until release */
|
||
if (Event.xany.type == EnterNotify ||
|
||
Event.xany.type == LeaveNotify) continue;
|
||
|
||
if (Event.type == MotionNotify) {
|
||
/* discard any extra motion events before a logical release */
|
||
while(XCheckMaskEvent(dpy,
|
||
movementMask | releaseEvent, &Event))
|
||
if (Event.type == releaseEvent) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* test to see if we have a second button press to abort move */
|
||
if (!menuFromFrameOrWindowOrTitlebar)
|
||
if (Event.type == ButtonPress && DragWindow != None) {
|
||
Cursor cur;
|
||
if (Scr->OpaqueMove) {
|
||
XMoveWindow (dpy, DragWindow, origDragX, origDragY);
|
||
} else {
|
||
MoveOutline(dragroot, 0, 0, 0, 0, 0, 0);
|
||
}
|
||
DragWindow = None;
|
||
|
||
XUnmapWindow (dpy, Scr->SizeWindow);
|
||
cur = LeftButt;
|
||
if (Event.xbutton.button == Button2)
|
||
cur = MiddleButt;
|
||
else if (Event.xbutton.button >= Button3)
|
||
cur = RightButt;
|
||
|
||
XGrabPointer (dpy, Scr->Root, True,
|
||
ButtonReleaseMask | ButtonPressMask,
|
||
GrabModeAsync, GrabModeAsync,
|
||
Scr->Root, cur, CurrentTime);
|
||
return TRUE;
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
if (!DispatchEvent2 ()) continue;
|
||
|
||
if (Cancel)
|
||
{
|
||
WindowMoved = FALSE;
|
||
if (!Scr->OpaqueMove)
|
||
UninstallRootColormap();
|
||
return TRUE; /* XXX should this be FALSE? */
|
||
}
|
||
if (Event.type == releaseEvent)
|
||
{
|
||
MoveOutline(dragroot, 0, 0, 0, 0, 0, 0);
|
||
if (moving_icon &&
|
||
((CurrentDragX != origDragX ||
|
||
CurrentDragY != origDragY)))
|
||
tmp_win->icon_moved = TRUE;
|
||
if (!Scr->OpaqueMove && menuFromFrameOrWindowOrTitlebar) {
|
||
int xl = Event.xbutton.x_root - (DragWidth / 2),
|
||
yt = Event.xbutton.y_root - (DragHeight / 2);
|
||
if (!moving_icon &&
|
||
(MoveFunction == F_MOVEPACK || MoveFunction == F_MOVEPUSH))
|
||
TryToPack (tmp_win, &xl, &yt);
|
||
XMoveWindow(dpy, DragWindow, xl, yt);
|
||
}
|
||
if (menuFromFrameOrWindowOrTitlebar) DragWindow = None;
|
||
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);
|
||
|
||
FixRootEvent (eventp);
|
||
if (tmp_win->winbox) {
|
||
XTranslateCoordinates (dpy, dragroot, tmp_win->winbox->window,
|
||
eventp->xmotion.x_root, eventp->xmotion.y_root,
|
||
&(eventp->xmotion.x_root), &(eventp->xmotion.y_root), &JunkChild);
|
||
}
|
||
if (DragWindow == None &&
|
||
abs(eventp->xmotion.x_root - origX) < Scr->MoveDelta &&
|
||
abs(eventp->xmotion.y_root - origY) < Scr->MoveDelta)
|
||
continue;
|
||
|
||
DragWindow = w;
|
||
|
||
if (!Scr->NoRaiseMove && Scr->OpaqueMove && !WindowMoved)
|
||
RaiseFrame(DragWindow);
|
||
|
||
WindowMoved = TRUE;
|
||
|
||
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;
|
||
}
|
||
|
||
if (ConstMoveDir != MOVE_NONE)
|
||
{
|
||
int xl, yt, width, height;
|
||
|
||
xl = ConstMoveX;
|
||
yt = ConstMoveY;
|
||
width = DragWidth + 2 * JunkBW;
|
||
height = DragHeight + 2 * JunkBW;
|
||
|
||
if (Scr->DontMoveOff && MoveFunction != F_FORCEMOVE)
|
||
TryToGrid (tmp_win, &xl, &yt);
|
||
if (!moving_icon && MoveFunction == F_MOVEPUSH && Scr->OpaqueMove)
|
||
TryToPush (tmp_win, xl, yt, 0);
|
||
|
||
if (!moving_icon &&
|
||
(MoveFunction == F_MOVEPACK || MoveFunction == F_MOVEPUSH))
|
||
TryToPack (tmp_win, &xl, &yt);
|
||
|
||
if (Scr->DontMoveOff && MoveFunction != F_FORCEMOVE)
|
||
{
|
||
ConstrainByBorders (tmp_win, &xl, width, &yt, height);
|
||
}
|
||
CurrentDragX = xl;
|
||
CurrentDragY = yt;
|
||
if (Scr->OpaqueMove) {
|
||
if (MoveFunction == F_MOVEPUSH && !moving_icon) {
|
||
SetupWindow (tmp_win, xl, yt,
|
||
tmp_win->frame_width, tmp_win->frame_height, -1);
|
||
} else {
|
||
XMoveWindow(dpy, DragWindow, xl, yt);
|
||
}
|
||
WMapSetupWindow (tmp_win, xl, yt, -1, -1);
|
||
}
|
||
else {
|
||
MoveOutline(dragroot, xl + Scr->currentvs->x,
|
||
yt + Scr->currentvs->y, width, height,
|
||
tmp_win->frame_bw,
|
||
moving_icon ? 0 : tmp_win->title_height + tmp_win->frame_bw3D);
|
||
}
|
||
}
|
||
}
|
||
else if (DragWindow != None)
|
||
{
|
||
int xroot, yroot;
|
||
int xl, yt, width, height;
|
||
|
||
|
||
/*
|
||
* this is split out for virtual screens. In that case, it's
|
||
* possible to drag windows from one workspace to another, and
|
||
* as such, these need to be adjusted to the root, rather
|
||
* than this virtual screen...
|
||
*/
|
||
xroot = eventp->xmotion.x_root;
|
||
yroot = eventp->xmotion.y_root;
|
||
|
||
if (!menuFromFrameOrWindowOrTitlebar) {
|
||
xl = xroot - DragX - JunkBW;
|
||
yt = yroot - DragY - JunkBW;
|
||
}
|
||
else {
|
||
xl = xroot - (DragWidth / 2);
|
||
yt = yroot - (DragHeight / 2);
|
||
}
|
||
width = DragWidth + 2 * JunkBW;
|
||
height = DragHeight + 2 * JunkBW;
|
||
|
||
if (Scr->DontMoveOff && MoveFunction != F_FORCEMOVE)
|
||
TryToGrid (tmp_win, &xl, &yt);
|
||
if (!moving_icon && MoveFunction == F_MOVEPUSH && Scr->OpaqueMove)
|
||
TryToPush (tmp_win, xl, yt, 0);
|
||
|
||
if (!moving_icon &&
|
||
(MoveFunction == F_MOVEPACK || MoveFunction == F_MOVEPUSH))
|
||
TryToPack (tmp_win, &xl, &yt);
|
||
|
||
if (Scr->DontMoveOff && MoveFunction != F_FORCEMOVE)
|
||
{
|
||
ConstrainByBorders (tmp_win, &xl, width, &yt, height);
|
||
}
|
||
|
||
CurrentDragX = xl;
|
||
CurrentDragY = yt;
|
||
if (Scr->OpaqueMove) {
|
||
if (MoveFunction == F_MOVEPUSH && !moving_icon) {
|
||
SetupWindow (tmp_win, xl, yt,
|
||
tmp_win->frame_width, tmp_win->frame_height, -1);
|
||
} else {
|
||
XMoveWindow(dpy, DragWindow, xl, yt);
|
||
}
|
||
if (! moving_icon) WMapSetupWindow (tmp_win, xl, yt, -1, -1);
|
||
}
|
||
else {
|
||
MoveOutline(dragroot, xl + Scr->currentvs->x,
|
||
yt + Scr->currentvs->y, width, height,
|
||
tmp_win->frame_bw,
|
||
moving_icon ? 0 : tmp_win->title_height + tmp_win->frame_bw3D);
|
||
}
|
||
}
|
||
DisplayPosition (tmp_win, CurrentDragX, CurrentDragY);
|
||
}
|
||
XUnmapWindow (dpy, Scr->SizeWindow);
|
||
|
||
if (!Scr->OpaqueMove && DragWindow == None)
|
||
UninstallRootColormap();
|
||
break;
|
||
}
|
||
case F_MOVETITLEBAR:
|
||
{
|
||
Window grabwin;
|
||
int deltax = 0, newx = 0;
|
||
int origNum;
|
||
SqueezeInfo *si;
|
||
|
||
if (DeferExecution(context, func, Scr->MoveCursor))
|
||
return TRUE;
|
||
|
||
PopDownMenu();
|
||
if (tmp_win->squeezed ||
|
||
!tmp_win->squeeze_info ||
|
||
!tmp_win->title_w ||
|
||
context == C_ICON ) {
|
||
XBell (dpy, 0);
|
||
break;
|
||
}
|
||
|
||
/* If the SqueezeInfo isn't copied yet, do it now */
|
||
if (!tmp_win->squeeze_info_copied) {
|
||
SqueezeInfo *s = malloc(sizeof(SqueezeInfo));
|
||
if (!s)
|
||
break;
|
||
*s = *tmp_win->squeeze_info;
|
||
tmp_win->squeeze_info = s;
|
||
tmp_win->squeeze_info_copied = 1;
|
||
}
|
||
si = tmp_win->squeeze_info;
|
||
|
||
if (si->denom != 0) {
|
||
int target_denom = tmp_win->frame_width;
|
||
/*
|
||
* If not pixel based, scale the denominator to equal the
|
||
* window width, so the numerator equals pixels.
|
||
* That way we can just modify it by pixel units, just
|
||
* like the other case.
|
||
*/
|
||
|
||
if (si->denom != target_denom) {
|
||
float scale = (float)target_denom / si->denom;
|
||
si->num *= scale;
|
||
si->denom = target_denom; /* s->denom *= scale; */
|
||
}
|
||
}
|
||
|
||
/* now move the mouse */
|
||
if (tmp_win->winbox) {
|
||
XTranslateCoordinates (dpy, Scr->Root, tmp_win->winbox->window,
|
||
eventp->xbutton.x_root, eventp->xbutton.y_root,
|
||
&eventp->xbutton.x_root, &eventp->xbutton.y_root, &JunkChild);
|
||
}
|
||
/*
|
||
* the event is always a button event, since key events
|
||
* are "weeded out" - although incompletely only
|
||
* F_MOVE and F_RESIZE - in HandleKeyPress().
|
||
*/
|
||
rootw = eventp->xbutton.root;
|
||
|
||
EventHandler[EnterNotify] = HandleUnknown;
|
||
EventHandler[LeaveNotify] = HandleUnknown;
|
||
|
||
if (!Scr->NoGrabServer) {
|
||
XGrabServer(dpy);
|
||
}
|
||
|
||
grabwin = Scr->Root;
|
||
if (tmp_win->winbox) grabwin = tmp_win->winbox->window;
|
||
XGrabPointer(dpy, grabwin, True,
|
||
ButtonPressMask | ButtonReleaseMask |
|
||
ButtonMotionMask | PointerMotionMask, /* PointerMotionHintMask */
|
||
GrabModeAsync, GrabModeAsync, grabwin, Scr->MoveCursor, CurrentTime);
|
||
|
||
#if 0 /* what's this for ? */
|
||
if (! tmp_win->icon || w != tmp_win->icon->w)
|
||
{
|
||
XTranslateCoordinates(dpy, w, tmp_win->frame,
|
||
eventp->xbutton.x,
|
||
eventp->xbutton.y,
|
||
&DragX, &DragY, &JunkChild);
|
||
|
||
w = tmp_win->frame;
|
||
}
|
||
#endif
|
||
|
||
DragWindow = None;
|
||
|
||
XGetGeometry(dpy, tmp_win->title_w, &JunkRoot, &origDragX, &origDragY,
|
||
&DragWidth, &DragHeight, &DragBW,
|
||
&JunkDepth);
|
||
|
||
origX = eventp->xbutton.x_root;
|
||
origNum = si->num;
|
||
|
||
if (menuFromFrameOrWindowOrTitlebar) {
|
||
/* warp the pointer to the middle of the window */
|
||
XWarpPointer(dpy, None, Scr->Root, 0, 0, 0, 0,
|
||
origDragX + DragWidth / 2,
|
||
origDragY + DragHeight / 2);
|
||
XFlush(dpy);
|
||
}
|
||
|
||
while (TRUE)
|
||
{
|
||
long releaseEvent = menuFromFrameOrWindowOrTitlebar ?
|
||
ButtonPress : ButtonRelease;
|
||
long movementMask = menuFromFrameOrWindowOrTitlebar ?
|
||
PointerMotionMask : ButtonMotionMask;
|
||
|
||
/* block until there is an interesting event */
|
||
XMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask |
|
||
EnterWindowMask | LeaveWindowMask |
|
||
ExposureMask | movementMask |
|
||
VisibilityChangeMask, &Event);
|
||
|
||
/* throw away enter and leave events until release */
|
||
if (Event.xany.type == EnterNotify ||
|
||
Event.xany.type == LeaveNotify) continue;
|
||
|
||
if (Event.type == MotionNotify) {
|
||
/* discard any extra motion events before a logical release */
|
||
while (XCheckMaskEvent(dpy,
|
||
movementMask | releaseEvent, &Event)) {
|
||
if (Event.type == releaseEvent) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!DispatchEvent2())
|
||
continue;
|
||
|
||
if (Event.type == releaseEvent)
|
||
break;
|
||
|
||
/* something left to do only if the pointer moved */
|
||
if (Event.type != MotionNotify)
|
||
continue;
|
||
|
||
/* get current pointer pos, useful when there is lag */
|
||
XQueryPointer(dpy, rootw, &eventp->xmotion.root, &JunkChild,
|
||
&eventp->xmotion.x_root, &eventp->xmotion.y_root,
|
||
&JunkX, &JunkY, &JunkMask);
|
||
|
||
FixRootEvent(eventp);
|
||
if (tmp_win->winbox) {
|
||
XTranslateCoordinates(dpy, Scr->Root, tmp_win->winbox->window,
|
||
eventp->xmotion.x_root, eventp->xmotion.y_root,
|
||
&eventp->xmotion.x_root, &eventp->xmotion.y_root, &JunkChild);
|
||
}
|
||
|
||
if (!Scr->NoRaiseMove && Scr->OpaqueMove && !WindowMoved)
|
||
RaiseFrame(w);
|
||
|
||
deltax = eventp->xmotion.x_root - origX;
|
||
newx = origNum + deltax;
|
||
|
||
/*
|
||
* Clamp to left and right.
|
||
* If we're in pixel size, keep within [ 0, frame_width >.
|
||
* If we're proportional, don't cross the 0.
|
||
* Also don't let the nominator get bigger than the denominator.
|
||
* Keep within [ -denom, -1] or [ 0, denom >.
|
||
*/
|
||
{
|
||
int wtmp = tmp_win->frame_width; /* or si->denom; if it were != 0 */
|
||
if (origNum < 0) {
|
||
if (newx >= 0)
|
||
newx = -1;
|
||
else if (newx < -wtmp)
|
||
newx = -wtmp;
|
||
} else if (origNum >= 0) {
|
||
if (newx < 0)
|
||
newx = 0;
|
||
else if (newx >= wtmp)
|
||
newx = wtmp - 1;
|
||
}
|
||
}
|
||
|
||
si->num = newx;
|
||
/* This, finally, actually moves the title bar */
|
||
/* XXX pressing a second button should cancel and undo this */
|
||
SetFrameShape(tmp_win);
|
||
}
|
||
break;
|
||
}
|
||
case F_FUNCTION:
|
||
{
|
||
MenuRoot *mroot;
|
||
MenuItem *mitem;
|
||
|
||
if ((mroot = FindMenuRoot(action)) == NULL)
|
||
{
|
||
if (!action) action = "undef";
|
||
fprintf (stderr, "%s: couldn't find function \"%s\"\n",
|
||
ProgramName, (char *)action);
|
||
return TRUE;
|
||
}
|
||
|
||
if (NeedToDefer(mroot) && DeferExecution(context, func, Scr->SelectCursor))
|
||
return TRUE;
|
||
else
|
||
{
|
||
for (mitem = mroot->first; mitem != NULL; mitem = mitem->next)
|
||
{
|
||
if (!ExecuteFunction (mitem->func, mitem->action, w,
|
||
tmp_win, eventp, context, pulldown))
|
||
/* pebl FIXME: the focus should be updated here,
|
||
or the function would operate on the same window */
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
case F_DEICONIFY:
|
||
case F_ICONIFY:
|
||
if (DeferExecution(context, func, Scr->SelectCursor))
|
||
return TRUE;
|
||
|
||
if (tmp_win->isicon)
|
||
{
|
||
DeIconify(tmp_win);
|
||
}
|
||
else if (func == F_ICONIFY)
|
||
{
|
||
Iconify (tmp_win, eventp->xbutton.x_root - 5,
|
||
eventp->xbutton.y_root - 5);
|
||
}
|
||
break;
|
||
|
||
case F_SQUEEZE:
|
||
if (DeferExecution(context, func, Scr->SelectCursor))
|
||
return TRUE;
|
||
|
||
Squeeze (tmp_win);
|
||
break;
|
||
|
||
case F_SHOWBGRD:
|
||
ShowBackground (Scr->currentvs);
|
||
break;
|
||
|
||
case F_RAISELOWER:
|
||
if (DeferExecution(context, func, Scr->SelectCursor))
|
||
return TRUE;
|
||
|
||
if (!WindowMoved) {
|
||
if (tmp_win->icon && w == tmp_win->icon->w) {
|
||
RaiseLowerFrame(w, ONTOP_DEFAULT);
|
||
} else {
|
||
RaiseLower(tmp_win);
|
||
WMapRaiseLower (tmp_win);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case F_RAISE:
|
||
if (DeferExecution(context, func, Scr->SelectCursor))
|
||
return TRUE;
|
||
|
||
/* check to make sure raise is not from the WindowFunction */
|
||
if (tmp_win->icon && (w == tmp_win->icon->w) && Context != C_ROOT)
|
||
XRaiseWindow(dpy, tmp_win->icon->w);
|
||
else {
|
||
RaiseWindow (tmp_win);
|
||
WMapRaise (tmp_win);
|
||
}
|
||
break;
|
||
|
||
case F_LOWER:
|
||
if (DeferExecution(context, func, Scr->SelectCursor))
|
||
return TRUE;
|
||
|
||
if (tmp_win->icon && (w == tmp_win->icon->w))
|
||
XLowerWindow(dpy, tmp_win->icon->w);
|
||
else {
|
||
LowerWindow(tmp_win);
|
||
WMapLower (tmp_win);
|
||
}
|
||
break;
|
||
|
||
case F_RAISEICONS:
|
||
for (t = Scr->FirstWindow; t != NULL; t = t->next) {
|
||
if (t->icon && t->icon->w) {
|
||
XRaiseWindow (dpy, t->icon->w);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case F_FOCUS:
|
||
if (DeferExecution(context, func, Scr->SelectCursor))
|
||
return TRUE;
|
||
|
||
if (tmp_win->isicon == FALSE)
|
||
{
|
||
if (!Scr->FocusRoot && Scr->Focus == tmp_win)
|
||
{
|
||
FocusOnRoot();
|
||
}
|
||
else
|
||
{
|
||
InstallWindowColormaps (0, tmp_win);
|
||
SetFocus (tmp_win, eventp->xbutton.time);
|
||
Scr->FocusRoot = FALSE;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case F_DESTROY:
|
||
if (DeferExecution(context, func, Scr->DestroyCursor))
|
||
return TRUE;
|
||
|
||
if (tmp_win->iconmgr || tmp_win->iswinbox || tmp_win->wspmgr
|
||
|| (Scr->workSpaceMgr.occupyWindow
|
||
&& tmp_win == Scr->workSpaceMgr.occupyWindow->twm_win)) {
|
||
XBell(dpy, 0);
|
||
break;
|
||
}
|
||
XKillClient(dpy, tmp_win->w);
|
||
if (ButtonPressed != -1) {
|
||
XEvent kev;
|
||
|
||
XMaskEvent (dpy, ButtonReleaseMask, &kev);
|
||
if (kev.xbutton.window == tmp_win->w) kev.xbutton.window = Scr->Root;
|
||
XPutBackEvent (dpy, &kev);
|
||
}
|
||
break;
|
||
|
||
case F_DELETE:
|
||
if (DeferExecution(context, func, Scr->DestroyCursor))
|
||
return TRUE;
|
||
|
||
if (tmp_win->iconmgr) { /* don't send ourself a message */
|
||
HideIconManager ();
|
||
break;
|
||
}
|
||
if (tmp_win->iswinbox || tmp_win->wspmgr
|
||
|| (Scr->workSpaceMgr.occupyWindow
|
||
&& tmp_win == Scr->workSpaceMgr.occupyWindow->twm_win)) {
|
||
XBell (dpy, 0);
|
||
break;
|
||
}
|
||
if (tmp_win->protocols & DoesWmDeleteWindow) {
|
||
SendDeleteWindowMessage (tmp_win, LastTimestamp());
|
||
if (ButtonPressed != -1) {
|
||
XEvent kev;
|
||
|
||
XMaskEvent (dpy, ButtonReleaseMask, &kev);
|
||
if (kev.xbutton.window == tmp_win->w) kev.xbutton.window = Scr->Root;
|
||
XPutBackEvent (dpy, &kev);
|
||
}
|
||
break;
|
||
}
|
||
XBell (dpy, 0);
|
||
break;
|
||
|
||
case F_DELETEORDESTROY:
|
||
if (DeferExecution(context, func, Scr->DestroyCursor)) return TRUE;
|
||
|
||
if (tmp_win->iconmgr) {
|
||
HideIconManager ();
|
||
break;
|
||
}
|
||
if (tmp_win->iswinbox || tmp_win->wspmgr
|
||
|| (Scr->workSpaceMgr.occupyWindow
|
||
&& tmp_win == Scr->workSpaceMgr.occupyWindow->twm_win)) {
|
||
XBell (dpy, 0);
|
||
break;
|
||
}
|
||
if (tmp_win->protocols & DoesWmDeleteWindow) {
|
||
SendDeleteWindowMessage (tmp_win, LastTimestamp());
|
||
} else {
|
||
XKillClient(dpy, tmp_win->w);
|
||
}
|
||
if (ButtonPressed != -1) {
|
||
XEvent kev;
|
||
|
||
XMaskEvent (dpy, ButtonReleaseMask, &kev);
|
||
if (kev.xbutton.window == tmp_win->w) kev.xbutton.window = Scr->Root;
|
||
XPutBackEvent (dpy, &kev);
|
||
}
|
||
break;
|
||
|
||
case F_SAVEYOURSELF:
|
||
if (DeferExecution (context, func, Scr->SelectCursor))
|
||
return TRUE;
|
||
|
||
if (tmp_win->protocols & DoesWmSaveYourself)
|
||
SendSaveYourselfMessage (tmp_win, LastTimestamp());
|
||
else
|
||
XBell (dpy, 0);
|
||
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);
|
||
}
|
||
XUngrabPointer (dpy, CurrentTime);
|
||
XSync (dpy, 0);
|
||
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) {
|
||
#ifdef VMS
|
||
fd = open (ptr, O_RDONLY, 0);
|
||
#else
|
||
fd = open (ptr, 0);
|
||
#endif
|
||
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_WARPTO:
|
||
{
|
||
register TwmWindow *tw;
|
||
int len;
|
||
|
||
len = strlen(action);
|
||
|
||
#ifdef WARPTO_FROM_ICONMGR
|
||
if (len == 0 && tmp_win && tmp_win->iconmgr)
|
||
{
|
||
printf ("curren iconmgr entry: %s", tmp_win->iconmgr->Current);
|
||
}
|
||
#endif /* #ifdef WARPTO_FROM_ICONMGR */
|
||
for (tw = Scr->FirstWindow; tw != NULL; tw = tw->next) {
|
||
if (!strncmp(action, tw->full_name, len)) break;
|
||
if (match (action, tw->full_name)) break;
|
||
}
|
||
if (!tw) {
|
||
for (tw = Scr->FirstWindow; tw != NULL; tw = tw->next) {
|
||
if (!strncmp(action, tw->class.res_name, len)) break;
|
||
if (match (action, tw->class.res_name)) break;
|
||
}
|
||
if (!tw) {
|
||
for (tw = Scr->FirstWindow; tw != NULL; tw = tw->next) {
|
||
if (!strncmp(action, tw->class.res_class, len)) break;
|
||
if (match (action, tw->class.res_class)) break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (tw) {
|
||
if (Scr->WarpUnmapped || tw->mapped) {
|
||
if (!tw->mapped) DeIconify (tw);
|
||
WarpToWindow (tw, Scr->RaiseOnWarp);
|
||
}
|
||
} else {
|
||
XBell (dpy, 0);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case F_WARPTOICONMGR:
|
||
{
|
||
TwmWindow *tw;
|
||
int len;
|
||
Window raisewin = None, iconwin = None;
|
||
|
||
len = strlen(action);
|
||
if (len == 0) {
|
||
if (tmp_win && tmp_win->iconmanagerlist) {
|
||
raisewin = tmp_win->iconmanagerlist->iconmgr->twm_win->frame;
|
||
iconwin = tmp_win->iconmanagerlist->icon;
|
||
} else if (Scr->iconmgr->active) {
|
||
raisewin = Scr->iconmgr->twm_win->frame;
|
||
iconwin = Scr->iconmgr->active->w;
|
||
}
|
||
} else {
|
||
for (tw = Scr->FirstWindow; tw != NULL; tw = tw->next) {
|
||
if (strncmp (action, tw->icon_name, len) == 0) {
|
||
if (tw->iconmanagerlist &&
|
||
tw->iconmanagerlist->iconmgr->twm_win->mapped) {
|
||
raisewin = tw->iconmanagerlist->iconmgr->twm_win->frame;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (raisewin) {
|
||
RaiseFrame(raisewin);
|
||
XWarpPointer (dpy, None, iconwin, 0,0,0,0, 5, 5);
|
||
} else {
|
||
XBell (dpy, 0);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case F_RING: /* Taken from vtwm version 5.3 */
|
||
if (DeferExecution (context, func, Scr->SelectCursor)) return TRUE;
|
||
if ( tmp_win->ring.next || tmp_win->ring.prev ) {
|
||
/* It's in the ring, let's take it out. */
|
||
TwmWindow *prev = tmp_win->ring.prev, *next = tmp_win->ring.next;
|
||
|
||
/*
|
||
* 1. Unlink window
|
||
* 2. If window was only thing in ring, null out ring
|
||
* 3. If window was ring leader, set to next (or null)
|
||
*/
|
||
if (prev) prev->ring.next = next;
|
||
if (next) next->ring.prev = prev;
|
||
if (Scr->Ring == tmp_win)
|
||
Scr->Ring = (next != tmp_win ? next : (TwmWindow *) NULL);
|
||
|
||
if (!Scr->Ring || Scr->RingLeader == tmp_win)
|
||
Scr->RingLeader = Scr->Ring;
|
||
tmp_win->ring.next = tmp_win->ring.prev = NULL;
|
||
} else {
|
||
/* Not in the ring, so put it in. */
|
||
if (Scr->Ring) {
|
||
tmp_win->ring.next = Scr->Ring->ring.next;
|
||
if (Scr->Ring->ring.next->ring.prev)
|
||
Scr->Ring->ring.next->ring.prev = tmp_win;
|
||
Scr->Ring->ring.next = tmp_win;
|
||
tmp_win->ring.prev = Scr->Ring;
|
||
} else {
|
||
tmp_win->ring.next = tmp_win->ring.prev = Scr->Ring = tmp_win;
|
||
}
|
||
}
|
||
/*tmp_win->ring.cursor_valid = False;*/
|
||
break;
|
||
|
||
case F_WARPRING:
|
||
switch (((char *)action)[0]) {
|
||
case 'n':
|
||
WarpAlongRing (&eventp->xbutton, True);
|
||
break;
|
||
case 'p':
|
||
WarpAlongRing (&eventp->xbutton, False);
|
||
break;
|
||
default:
|
||
XBell (dpy, 0);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case F_FILE:
|
||
action = ExpandFilename(action);
|
||
#ifdef VMS
|
||
fd = open (action, O_RDONLY, 0);
|
||
#else
|
||
fd = open(action, 0);
|
||
#endif
|
||
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, (char *)action);
|
||
}
|
||
free(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->rootw,
|
||
(unsigned int) Scr->rooth,
|
||
(unsigned int) 0,
|
||
CopyFromParent, (unsigned int) CopyFromParent,
|
||
(Visual *) CopyFromParent, valuemask,
|
||
&attributes);
|
||
XMapWindow (dpy, w);
|
||
XDestroyWindow (dpy, w);
|
||
XFlush (dpy);
|
||
}
|
||
break;
|
||
|
||
case F_OCCUPY:
|
||
if (DeferExecution(context, func, Scr->SelectCursor))
|
||
return TRUE;
|
||
Occupy (tmp_win);
|
||
break;
|
||
|
||
case F_OCCUPYALL:
|
||
if (DeferExecution(context, func, Scr->SelectCursor))
|
||
return TRUE;
|
||
OccupyAll (tmp_win);
|
||
break;
|
||
|
||
case F_GOTOWORKSPACE:
|
||
GotoWorkSpaceByName (Scr->currentvs, action);
|
||
break;
|
||
|
||
case F_PREVWORKSPACE:
|
||
GotoPrevWorkSpace (Scr->currentvs);
|
||
break;
|
||
|
||
case F_NEXTWORKSPACE:
|
||
GotoNextWorkSpace (Scr->currentvs);
|
||
break;
|
||
|
||
case F_RIGHTWORKSPACE:
|
||
GotoRightWorkSpace (Scr->currentvs);
|
||
break;
|
||
|
||
case F_LEFTWORKSPACE:
|
||
GotoLeftWorkSpace (Scr->currentvs);
|
||
break;
|
||
|
||
case F_UPWORKSPACE:
|
||
GotoUpWorkSpace (Scr->currentvs);
|
||
break;
|
||
|
||
case F_DOWNWORKSPACE:
|
||
GotoDownWorkSpace (Scr->currentvs);
|
||
break;
|
||
|
||
case F_MENU:
|
||
if (action && ! strncmp (action, "WGOTO : ", 8)) {
|
||
GotoWorkSpaceByName (/* XXXXX */ Scr->currentvs,
|
||
((char *)action) + 8);
|
||
}
|
||
else {
|
||
MenuItem *item;
|
||
|
||
item = ActiveItem;
|
||
while (item && item->sub) {
|
||
if (!item->sub->defaultitem) break;
|
||
if (item->sub->defaultitem->func != F_MENU) break;
|
||
item = item->sub->defaultitem;
|
||
}
|
||
if (item && item->sub && item->sub->defaultitem) {
|
||
ExecuteFunction (item->sub->defaultitem->func,
|
||
item->sub->defaultitem->action,
|
||
w, tmp_win, eventp, context, pulldown);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case F_WINREFRESH:
|
||
if (DeferExecution(context, func, Scr->SelectCursor))
|
||
return TRUE;
|
||
|
||
if (context == C_ICON && tmp_win->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_ADOPTWINDOW:
|
||
adoptWindow ();
|
||
break;
|
||
|
||
case F_TRACE:
|
||
DebugTrace (action);
|
||
break;
|
||
|
||
case F_CHANGESIZE:
|
||
ChangeSize (action, tmp_win);
|
||
break;
|
||
|
||
case F_QUIT:
|
||
Done(0);
|
||
break;
|
||
}
|
||
|
||
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(int context, int func, Cursor cursor)
|
||
{
|
||
if ((context == C_ROOT) || (context == C_ALTERNATE))
|
||
{
|
||
LastCursor = cursor;
|
||
if (func == F_ADOPTWINDOW) {
|
||
XGrabPointer(dpy, Scr->Root, True,
|
||
ButtonPressMask | ButtonReleaseMask,
|
||
GrabModeAsync, GrabModeAsync,
|
||
None, cursor, CurrentTime);
|
||
} else {
|
||
XGrabPointer(dpy, Scr->Root, True,
|
||
ButtonPressMask | ButtonReleaseMask,
|
||
GrabModeAsync, GrabModeAsync,
|
||
Scr->Root, cursor, CurrentTime);
|
||
}
|
||
RootFunction = func;
|
||
|
||
return (TRUE);
|
||
}
|
||
|
||
return (FALSE);
|
||
}
|
||
|
||
|
||
|
||
/***********************************************************************
|
||
*
|
||
* Procedure:
|
||
* ReGrab - regrab the pointer with the LastCursor;
|
||
*
|
||
***********************************************************************
|
||
*/
|
||
|
||
void ReGrab(void)
|
||
{
|
||
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
|
||
*
|
||
***********************************************************************
|
||
*/
|
||
|
||
int NeedToDefer(MenuRoot *root)
|
||
{
|
||
MenuItem *mitem;
|
||
|
||
for (mitem = root->first; mitem != NULL; mitem = mitem->next)
|
||
{
|
||
switch (mitem->func)
|
||
{
|
||
case F_IDENTIFY:
|
||
case F_RESIZE:
|
||
case F_MOVE:
|
||
case F_FORCEMOVE:
|
||
case F_DEICONIFY:
|
||
case F_ICONIFY:
|
||
case F_RAISELOWER:
|
||
case F_RAISE:
|
||
case F_LOWER:
|
||
case F_FOCUS:
|
||
case F_DESTROY:
|
||
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_SQUEEZE:
|
||
case F_AUTORAISE:
|
||
case F_AUTOLOWER:
|
||
return TRUE;
|
||
}
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
|
||
/***********************************************************************
|
||
*
|
||
* Procedure:
|
||
* Execute - execute the string by /bin/sh
|
||
*
|
||
* Inputs:
|
||
* s - the string containing the command
|
||
*
|
||
***********************************************************************
|
||
*/
|
||
|
||
void Execute(char *s)
|
||
{
|
||
#ifdef VMS
|
||
createProcess(s);
|
||
#else
|
||
static char buf[256];
|
||
char *ds = DisplayString (dpy);
|
||
char *colon, *dot1;
|
||
char oldDisplay[256];
|
||
char *doisplay;
|
||
int restorevar = 0;
|
||
Bool replace;
|
||
char *subs, *name, *news;
|
||
int len;
|
||
|
||
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 = strrchr (ds, ':');
|
||
if (colon) { /* if host[:]:dpy */
|
||
strcpy (buf, "DISPLAY=");
|
||
strcat (buf, ds);
|
||
colon = buf + 8 + (colon - ds); /* use version in buf */
|
||
dot1 = strchr (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;
|
||
}
|
||
replace = False;
|
||
subs = strstr (s, "$currentworkspace");
|
||
name = GetCurrentWorkSpaceName (Scr->currentvs);
|
||
if (subs && name) {
|
||
len = strlen (s) - strlen ("$currentworkspace") + strlen (name);
|
||
news = (char*) malloc (len + 1);
|
||
*subs = '\0';
|
||
strcpy (news, s);
|
||
*subs = '$';
|
||
strcat (news, name);
|
||
subs += strlen ("$currentworkspace");
|
||
strcat (news, subs);
|
||
s = news;
|
||
replace = True;
|
||
}
|
||
subs = strstr (s, "$redirect");
|
||
if (subs) {
|
||
if (captive) {
|
||
name = (char*) malloc (21 + strlen (captivename) + 1);
|
||
sprintf (name, "-xrm 'ctwm.redirect:%s'", captivename);
|
||
} else {
|
||
name = (char*) malloc (1);
|
||
*name = '\0';
|
||
}
|
||
len = strlen (s) - strlen ("$redirect") + strlen (name);
|
||
news = (char*) malloc (len + 1);
|
||
*subs = '\0';
|
||
strcpy (news, s);
|
||
*subs = '$';
|
||
strcat (news, name);
|
||
subs += strlen ("$redirect");
|
||
strcat (news, subs);
|
||
s = news;
|
||
free (name);
|
||
replace = True;
|
||
}
|
||
#ifdef USE_SIGNALS
|
||
{
|
||
SigProc sig;
|
||
|
||
sig = signal (SIGALRM, SIG_IGN);
|
||
(void) system (s);
|
||
signal (SIGALRM, sig);
|
||
}
|
||
#else /* USE_SIGNALS */
|
||
(void) system (s);
|
||
#endif /* USE_SIGNALS */
|
||
|
||
if (restorevar) { /* why bother? */
|
||
(void) sprintf (buf, "DISPLAY=%s", oldDisplay);
|
||
putenv (buf);
|
||
}
|
||
if (replace) free (s);
|
||
#endif
|
||
}
|
||
|
||
|
||
|
||
Window lowerontop = -1;
|
||
|
||
void PlaceTransients (TwmWindow *tmp_win, int where)
|
||
{
|
||
int sp, sc;
|
||
TwmWindow *t;
|
||
XWindowChanges xwc;
|
||
xwc.stack_mode = where;
|
||
|
||
sp = tmp_win->frame_width * tmp_win->frame_height;
|
||
for (t = Scr->FirstWindow; t != NULL; t = t->next) {
|
||
if (t != tmp_win &&
|
||
((t->transient && t->transientfor == tmp_win->w) ||
|
||
t->group == tmp_win->w)) {
|
||
if (t->frame) {
|
||
sc = t->frame_width * t->frame_height;
|
||
if (sc < ((sp * Scr->TransientOnTop) / 100)) {
|
||
xwc.sibling = tmp_win->frame;
|
||
XConfigureWindow(dpy, t->frame, CWSibling | CWStackMode, &xwc);
|
||
if (lowerontop == t->frame) {
|
||
lowerontop = (Window)-1;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
#include <assert.h>
|
||
|
||
void PlaceOntop (int ontop, int where)
|
||
{
|
||
TwmWindow *t;
|
||
XWindowChanges xwc;
|
||
xwc.stack_mode = where;
|
||
|
||
lowerontop = (Window)-1;
|
||
|
||
for (t = Scr->FirstWindow; t != NULL; t = t->next) {
|
||
if (t->ontoppriority > ontop) {
|
||
XConfigureWindow(dpy, t->frame, CWStackMode, &xwc);
|
||
PlaceTransients(t, Above);
|
||
if (lowerontop == (Window)-1) {
|
||
lowerontop = t->frame;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void MapRaised (TwmWindow *tmp_win)
|
||
{
|
||
XMapWindow(dpy, tmp_win->frame);
|
||
RaiseWindow(tmp_win);
|
||
}
|
||
|
||
void RaiseWindow (TwmWindow *tmp_win)
|
||
{
|
||
XWindowChanges xwc;
|
||
int xwcm;
|
||
|
||
if (tmp_win->ontoppriority == ONTOP_MAX) {
|
||
XRaiseWindow(dpy, tmp_win->frame);
|
||
if (lowerontop == (Window)-1) {
|
||
lowerontop = tmp_win->frame;
|
||
} else if (lowerontop == tmp_win->frame) {
|
||
lowerontop = (Window)-1;
|
||
}
|
||
} else {
|
||
if (lowerontop == (Window)-1) {
|
||
PlaceOntop(tmp_win->ontoppriority, Above);
|
||
}
|
||
xwcm = CWStackMode;
|
||
if (lowerontop != (Window)-1) {
|
||
xwc.stack_mode = Below;
|
||
xwc.sibling = lowerontop;
|
||
xwcm |= CWSibling;
|
||
} else {
|
||
xwc.stack_mode = Above;
|
||
}
|
||
XConfigureWindow(dpy, tmp_win->frame, xwcm, &xwc);
|
||
}
|
||
PlaceTransients(tmp_win, Above);
|
||
}
|
||
|
||
void RaiseLower (TwmWindow *tmp_win)
|
||
{
|
||
XWindowChanges xwc;
|
||
|
||
PlaceOntop(tmp_win->ontoppriority, Below);
|
||
PlaceTransients(tmp_win, Below);
|
||
lowerontop = (Window)-1;
|
||
xwc.stack_mode = Opposite;
|
||
XConfigureWindow(dpy, tmp_win->frame, CWStackMode, &xwc);
|
||
PlaceOntop(tmp_win->ontoppriority, Above);
|
||
PlaceTransients(tmp_win, Above);
|
||
}
|
||
|
||
void RaiseLowerFrame (Window frame, int ontop)
|
||
{
|
||
XWindowChanges xwc;
|
||
|
||
PlaceOntop(ontop, Below);
|
||
lowerontop = (Window)-1;
|
||
xwc.stack_mode = Opposite;
|
||
XConfigureWindow(dpy, frame, CWStackMode, &xwc);
|
||
PlaceOntop(ontop, Above);
|
||
}
|
||
|
||
void LowerWindow (TwmWindow *tmp_win)
|
||
{
|
||
XLowerWindow(dpy, tmp_win->frame);
|
||
if (tmp_win->frame == lowerontop) {
|
||
lowerontop = (Window)-1;
|
||
}
|
||
PlaceTransients(tmp_win, Above);
|
||
}
|
||
|
||
void RaiseFrame (Window frame)
|
||
{
|
||
TwmWindow *tmp_win;
|
||
|
||
tmp_win = GetTwmWindow(frame);
|
||
|
||
if (tmp_win != NULL) {
|
||
RaiseWindow(tmp_win);
|
||
} else {
|
||
XRaiseWindow(dpy, frame);
|
||
}
|
||
}
|
||
|
||
/***********************************************************************
|
||
*
|
||
* Procedure:
|
||
* FocusOnRoot - put input focus on the root window
|
||
*
|
||
***********************************************************************
|
||
*/
|
||
|
||
void FocusOnRoot(void)
|
||
{
|
||
SetFocus ((TwmWindow *) NULL, LastTimestamp());
|
||
InstallColormaps(0, &Scr->RootColormaps);
|
||
if (! Scr->ClickToFocus) Scr->FocusRoot = TRUE;
|
||
}
|
||
|
||
static void ReMapOne(TwmWindow *t, TwmWindow *leader)
|
||
{
|
||
if (t->icon_on)
|
||
Zoom(t->icon->w, t->frame);
|
||
else if (leader->icon)
|
||
Zoom(leader->icon->w, t->frame);
|
||
|
||
if (!t->squeezed)
|
||
XMapWindow(dpy, t->w);
|
||
t->mapped = TRUE;
|
||
if (Scr->Root != Scr->CaptiveRoot) /* XXX dubious test */
|
||
XReparentWindow (dpy, t->frame, Scr->Root, t->frame_x, t->frame_y);
|
||
if (Scr->NoRaiseDeicon)
|
||
XMapWindow(dpy, t->frame);
|
||
else
|
||
MapRaised(t);
|
||
SetMapStateProp(t, NormalState);
|
||
|
||
if (t->icon && t->icon->w) {
|
||
XUnmapWindow(dpy, t->icon->w);
|
||
IconDown(t);
|
||
if (Scr->ShrinkIconTitles)
|
||
t->icon->title_shrunk = True;
|
||
}
|
||
if (t->iconmanagerlist) {
|
||
WList *wl;
|
||
|
||
for (wl = t->iconmanagerlist; wl != NULL; wl = wl->nextv)
|
||
XUnmapWindow(dpy, wl->icon);
|
||
}
|
||
t->isicon = FALSE;
|
||
t->icon_on = FALSE;
|
||
WMapDeIconify(t);
|
||
}
|
||
|
||
static void ReMapTransients(TwmWindow *tmp_win)
|
||
{
|
||
TwmWindow *t;
|
||
|
||
/* find t such that it is a transient or group member window */
|
||
for (t = Scr->FirstWindow; t != NULL; t = t->next) {
|
||
if (t != tmp_win &&
|
||
((t->transient && t->transientfor == tmp_win->w) ||
|
||
(t->group == tmp_win->w && t->isicon))) {
|
||
ReMapOne(t, tmp_win);
|
||
}
|
||
}
|
||
}
|
||
|
||
void DeIconify(TwmWindow *tmp_win)
|
||
{
|
||
TwmWindow *t = tmp_win;
|
||
int isicon = FALSE;
|
||
|
||
/* de-iconify the main window */
|
||
if (Scr->WindowMask)
|
||
XRaiseWindow (dpy, Scr->WindowMask);
|
||
if (tmp_win && tmp_win->isicon)
|
||
{
|
||
isicon = TRUE;
|
||
if (tmp_win->icon_on && tmp_win->icon && tmp_win->icon->w)
|
||
Zoom(tmp_win->icon->w, tmp_win->frame);
|
||
else if (tmp_win->group != (Window) 0)
|
||
{
|
||
t = GetTwmWindow(tmp_win->group);
|
||
if (t && t->icon_on && t->icon && t->icon->w)
|
||
{
|
||
Zoom(t->icon->w, tmp_win->frame);
|
||
}
|
||
}
|
||
}
|
||
|
||
ReMapOne(tmp_win, t);
|
||
|
||
if (isicon &&
|
||
(Scr->WarpCursor ||
|
||
LookInList(Scr->WarpCursorL, tmp_win->full_name, &tmp_win->class)))
|
||
WarpToWindow (tmp_win, 0);
|
||
|
||
/* now de-iconify and window group transients */
|
||
ReMapTransients(tmp_win);
|
||
|
||
if (! Scr->WindowMask && Scr->DeIconifyFunction.func != 0) {
|
||
char *action;
|
||
XEvent event;
|
||
|
||
action = Scr->DeIconifyFunction.item ?
|
||
Scr->DeIconifyFunction.item->action : NULL;
|
||
ExecuteFunction (Scr->DeIconifyFunction.func, action,
|
||
(Window) 0, tmp_win, &event, C_ROOT, FALSE);
|
||
}
|
||
XSync (dpy, 0);
|
||
}
|
||
|
||
|
||
static void UnmapTransients(TwmWindow *tmp_win, int iconify, unsigned long eventMask)
|
||
{
|
||
TwmWindow *t;
|
||
|
||
for (t = Scr->FirstWindow; t != NULL; t = t->next) {
|
||
if (t != tmp_win &&
|
||
((t->transient && t->transientfor == tmp_win->w) ||
|
||
t->group == tmp_win->w)) {
|
||
if (iconify && tmp_win->icon) {
|
||
if (t->icon_on)
|
||
Zoom(t->icon->w, tmp_win->icon->w);
|
||
else
|
||
Zoom(t->frame, tmp_win->icon->w);
|
||
}
|
||
|
||
/*
|
||
* 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);
|
||
XUnmapWindow(dpy, t->frame);
|
||
XSelectInput(dpy, t->w, eventMask);
|
||
if (t->icon && t->icon->w) XUnmapWindow(dpy, t->icon->w);
|
||
SetMapStateProp(t, IconicState);
|
||
if (t == Scr->Focus) {
|
||
SetFocus ((TwmWindow *) NULL, LastTimestamp());
|
||
if (! Scr->ClickToFocus) Scr->FocusRoot = TRUE;
|
||
}
|
||
if (t->iconmanagerlist)
|
||
XMapWindow(dpy, t->iconmanagerlist->icon);
|
||
t->isicon = TRUE;
|
||
t->icon_on = FALSE;
|
||
WMapIconify (t);
|
||
}
|
||
}
|
||
}
|
||
|
||
void Iconify(TwmWindow *tmp_win, int def_x, int def_y)
|
||
{
|
||
TwmWindow *t;
|
||
int iconify;
|
||
XWindowAttributes winattrs;
|
||
unsigned long eventMask;
|
||
WList *wl;
|
||
Window leader = (Window)-1;
|
||
Window blanket = (Window)-1;
|
||
|
||
iconify = (!tmp_win->iconify_by_unmapping);
|
||
t = (TwmWindow*) 0;
|
||
if (tmp_win->transient) {
|
||
leader = tmp_win->transientfor;
|
||
t = GetTwmWindow(leader);
|
||
}
|
||
else
|
||
if ((leader = tmp_win->group) != 0 && leader != tmp_win->w) {
|
||
t = GetTwmWindow(leader);
|
||
}
|
||
if (t && t->icon_on) iconify = False;
|
||
if (iconify)
|
||
{
|
||
if (!tmp_win->icon || !tmp_win->icon->w)
|
||
CreateIconWindow(tmp_win, def_x, def_y);
|
||
else
|
||
IconUp(tmp_win);
|
||
if (visible (tmp_win)) {
|
||
if (Scr->WindowMask) {
|
||
XRaiseWindow (dpy, Scr->WindowMask);
|
||
XMapWindow(dpy, tmp_win->icon->w);
|
||
}
|
||
else
|
||
XMapRaised(dpy, tmp_win->icon->w);
|
||
}
|
||
}
|
||
if (tmp_win->iconmanagerlist) {
|
||
for (wl = tmp_win->iconmanagerlist; wl != NULL; wl = wl->nextv) {
|
||
XMapWindow(dpy, wl->icon);
|
||
}
|
||
}
|
||
|
||
XGetWindowAttributes(dpy, tmp_win->w, &winattrs);
|
||
eventMask = winattrs.your_event_mask;
|
||
|
||
/* iconify transients and window group first */
|
||
UnmapTransients(tmp_win, iconify, eventMask);
|
||
|
||
if (iconify) Zoom(tmp_win->frame, tmp_win->icon->w);
|
||
|
||
/*
|
||
* Prevent the receipt of an UnmapNotify, since that would
|
||
* cause a transition to the Withdrawn state.
|
||
*/
|
||
tmp_win->mapped = FALSE;
|
||
|
||
if ((Scr->IconifyStyle != ICONIFY_NORMAL) && !Scr->WindowMask) {
|
||
XSetWindowAttributes attr;
|
||
XGetWindowAttributes(dpy, tmp_win->frame, &winattrs);
|
||
attr.backing_store = NotUseful;
|
||
attr.save_under = False;
|
||
blanket = XCreateWindow (dpy, Scr->Root, winattrs.x, winattrs.y,
|
||
winattrs.width, winattrs.height, (unsigned int) 0,
|
||
CopyFromParent, (unsigned int) CopyFromParent,
|
||
(Visual *) CopyFromParent, CWBackingStore | CWSaveUnder, &attr);
|
||
XMapWindow (dpy, blanket);
|
||
}
|
||
XSelectInput(dpy, tmp_win->w, eventMask & ~StructureNotifyMask);
|
||
XUnmapWindow(dpy, tmp_win->w);
|
||
XUnmapWindow(dpy, tmp_win->frame);
|
||
XSelectInput(dpy, tmp_win->w, eventMask);
|
||
SetMapStateProp(tmp_win, IconicState);
|
||
|
||
if ((Scr->IconifyStyle != ICONIFY_NORMAL) && !Scr->WindowMask) {
|
||
switch (Scr->IconifyStyle) {
|
||
case ICONIFY_MOSAIC: MosaicFade (tmp_win, blanket); break;
|
||
case ICONIFY_ZOOMIN: ZoomInWindow (tmp_win, blanket); break;
|
||
case ICONIFY_ZOOMOUT: ZoomOutWindow (tmp_win, blanket); break;
|
||
case ICONIFY_SWEEP: SweepWindow (tmp_win, blanket); break;
|
||
}
|
||
XDestroyWindow (dpy, blanket);
|
||
}
|
||
if (tmp_win == Scr->Focus) {
|
||
SetFocus ((TwmWindow *) NULL, LastTimestamp());
|
||
if (! Scr->ClickToFocus) Scr->FocusRoot = TRUE;
|
||
}
|
||
tmp_win->isicon = TRUE;
|
||
tmp_win->icon_on = iconify ? TRUE : FALSE;
|
||
WMapIconify (tmp_win);
|
||
if (! Scr->WindowMask && Scr->IconifyFunction.func != 0) {
|
||
char *action;
|
||
XEvent event;
|
||
|
||
action = Scr->IconifyFunction.item ? Scr->IconifyFunction.item->action : NULL;
|
||
ExecuteFunction (Scr->IconifyFunction.func, action,
|
||
(Window) 0, tmp_win, &event, C_ROOT, FALSE);
|
||
}
|
||
XSync (dpy, 0);
|
||
}
|
||
|
||
void AutoSqueeze (TwmWindow *tmp_win)
|
||
{
|
||
if (tmp_win->iconmgr) return;
|
||
if (Scr->RaiseWhenAutoUnSqueeze && tmp_win->squeezed) XRaiseWindow (dpy, tmp_win->frame);
|
||
Squeeze (tmp_win);
|
||
}
|
||
|
||
void Squeeze (TwmWindow *tmp_win)
|
||
{
|
||
long fx, fy, savex, savey;
|
||
int neww, newh, south;
|
||
int grav = ((tmp_win->hints.flags & PWinGravity)
|
||
? tmp_win->hints.win_gravity : NorthWestGravity);
|
||
XWindowAttributes winattrs;
|
||
unsigned long eventMask;
|
||
#ifdef GNOME
|
||
unsigned char *prop;
|
||
unsigned long nitems, bytesafter;
|
||
Atom actual_type;
|
||
int actual_format;
|
||
long gwkspc;
|
||
#endif /* GNOME */
|
||
if (tmp_win->squeezed) {
|
||
tmp_win->squeezed = False;
|
||
#ifdef GNOME
|
||
XGetWindowAttributes (dpy, tmp_win->w, &winattrs);
|
||
eventMask = winattrs.your_event_mask;
|
||
XSelectInput (dpy, tmp_win->w, eventMask & ~PropertyChangeMask);
|
||
if (XGetWindowProperty (dpy, tmp_win->w, _XA_WIN_STATE, 0L, 32, False,
|
||
XA_CARDINAL, &actual_type, &actual_format,
|
||
&nitems, &bytesafter, &prop)
|
||
!= Success || nitems == 0) {
|
||
gwkspc = 0;
|
||
} else {
|
||
gwkspc = (int)*prop;
|
||
XFree ((char *)prop);
|
||
}
|
||
gwkspc &= ~WIN_STATE_SHADED;
|
||
XChangeProperty (dpy, tmp_win->w, _XA_WIN_STATE, XA_CARDINAL, 32,
|
||
PropModeReplace, (unsigned char *)&gwkspc, 1);
|
||
XSelectInput(dpy, tmp_win->w, eventMask);
|
||
#endif /* GNOME */
|
||
if (!tmp_win->isicon) XMapWindow (dpy, tmp_win->w);
|
||
SetupWindow (tmp_win, tmp_win->actual_frame_x, tmp_win->actual_frame_y,
|
||
tmp_win->actual_frame_width, tmp_win->actual_frame_height, -1);
|
||
ReMapTransients(tmp_win);
|
||
return;
|
||
}
|
||
|
||
newh = tmp_win->title_height + 2 * tmp_win->frame_bw3D;
|
||
if (newh < 3) { XBell (dpy, 0); return; }
|
||
switch (grav) {
|
||
case SouthWestGravity :
|
||
case SouthGravity :
|
||
case SouthEastGravity :
|
||
south = True; break;
|
||
default :
|
||
south = False; break;
|
||
}
|
||
if (tmp_win->title_height && !tmp_win->AlwaysSqueezeToGravity) south = False;
|
||
|
||
tmp_win->squeezed = True;
|
||
tmp_win->actual_frame_width = tmp_win->frame_width;
|
||
tmp_win->actual_frame_height = tmp_win->frame_height;
|
||
savex = fx = tmp_win->frame_x;
|
||
savey = fy = tmp_win->frame_y;
|
||
neww = tmp_win->actual_frame_width;
|
||
if (south) fy += tmp_win->frame_height - newh;
|
||
if (tmp_win->squeeze_info) {
|
||
fx += tmp_win->title_x - tmp_win->frame_bw3D;
|
||
neww = tmp_win->title_width + 2 * (tmp_win->frame_bw + tmp_win->frame_bw3D);
|
||
}
|
||
XGetWindowAttributes(dpy, tmp_win->w, &winattrs);
|
||
eventMask = winattrs.your_event_mask;
|
||
#ifdef GNOME
|
||
XSelectInput (dpy, tmp_win->w, eventMask & ~(StructureNotifyMask | PropertyChangeMask));
|
||
if (XGetWindowProperty (dpy, tmp_win->w, _XA_WIN_STATE, 0L, 32, False,
|
||
XA_CARDINAL, &actual_type, &actual_format, &nitems,
|
||
&bytesafter, &prop)
|
||
!= Success || nitems == 0) {
|
||
gwkspc = 0;
|
||
} else {
|
||
gwkspc = (int)*prop;
|
||
XFree ((char *)prop);
|
||
}
|
||
gwkspc |= WIN_STATE_SHADED;
|
||
XChangeProperty (dpy, tmp_win->w, _XA_WIN_STATE, XA_CARDINAL, 32,
|
||
PropModeReplace, (unsigned char *)&gwkspc, 1);
|
||
#else
|
||
XSelectInput (dpy, tmp_win->w, eventMask & ~StructureNotifyMask);
|
||
#endif /* GNOME */
|
||
XUnmapWindow(dpy, tmp_win->w);
|
||
XSelectInput(dpy, tmp_win->w, eventMask);
|
||
|
||
if (fx + neww >= Scr->rootw - Scr->BorderRight)
|
||
fx = Scr->rootw - Scr->BorderRight - neww;
|
||
if (fy + newh >= Scr->rooth - Scr->BorderBottom)
|
||
fy = Scr->rooth - Scr->BorderBottom - newh;
|
||
SetupWindow (tmp_win, fx, fy, neww, newh, -1);
|
||
tmp_win->actual_frame_x = savex;
|
||
tmp_win->actual_frame_y = savey;
|
||
|
||
/* Now make the group members disappear */
|
||
UnmapTransients(tmp_win, 0, eventMask);
|
||
}
|
||
|
||
static void Identify (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;
|
||
unsigned char *prop;
|
||
unsigned long nitems, bytesafter;
|
||
Atom actual_type;
|
||
int actual_format;
|
||
XRectangle inc_rect;
|
||
XRectangle logical_rect;
|
||
Bool first = True;
|
||
|
||
n = 0;
|
||
(void) sprintf(Info[n++], "Twm version: %s", Version);
|
||
(void) sprintf(Info[n], "Compile time options :");
|
||
#ifdef XPM
|
||
(void) strcat (Info[n], " XPM");
|
||
first = False;
|
||
#endif
|
||
#ifdef IMCONV
|
||
if (!first) (void) strcat(Info[n], ", ");
|
||
(void) strcat (Info[n], "IMCONV");
|
||
first = False;
|
||
#endif
|
||
#ifdef USEM4
|
||
if (!first) (void) strcat(Info[n], ", ");
|
||
(void) strcat (Info[n], "USEM4");
|
||
first = False;
|
||
#endif
|
||
#ifdef GNOME
|
||
if (!first) (void) strcat(Info[n], ", ");
|
||
(void) strcat (Info[n], "GNOME");
|
||
first = False;
|
||
#endif
|
||
#ifdef SOUNDS
|
||
if (!first) (void) strcat(Info[n], ", ");
|
||
(void) strcat (Info[n], "SOUNDS");
|
||
first = False;
|
||
#endif
|
||
#ifdef DEBUG
|
||
if (!first) (void) strcat(Info[n], ", ");
|
||
(void) strcat (Info[n], "debug");
|
||
first = False;
|
||
#endif
|
||
if (!first) (void) strcat(Info[n], ", ");
|
||
(void) strcat (Info[n], "I18N");
|
||
first = False;
|
||
n++;
|
||
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);
|
||
(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 (UL) = %dx%d+%d+%d (Inner: %dx%d+%d+%d)",
|
||
wwidth + 2 * (bw + t->frame_bw3D),
|
||
wheight + 2 * (bw + t->frame_bw3D) + t->title_height,
|
||
x - (bw + t->frame_bw3D),
|
||
y - (bw + t->frame_bw3D + t->title_height),
|
||
wwidth, wheight, x, y);
|
||
(void) sprintf(Info[n++], "Geometry/root (LR) = %dx%d-%d-%d (Inner: %dx%d-%d-%d)",
|
||
wwidth + 2 * (bw + t->frame_bw3D),
|
||
wheight + 2 * (bw + t->frame_bw3D) + t->title_height,
|
||
Scr->rootw - (x + wwidth + bw + t->frame_bw3D),
|
||
Scr->rooth - (y + wheight + bw + t->frame_bw3D),
|
||
wwidth, wheight,
|
||
Scr->rootw - (x + wwidth), Scr->rooth - (y + wheight));
|
||
(void) sprintf(Info[n++], "Border width = %d", bw);
|
||
(void) sprintf(Info[n++], "3D border width = %d", t->frame_bw3D);
|
||
(void) sprintf(Info[n++], "Depth = %d", depth);
|
||
|
||
if (XGetWindowProperty (dpy, t->w, _XA_WM_CLIENT_MACHINE, 0L, 64, False,
|
||
XA_STRING, &actual_type, &actual_format, &nitems,
|
||
&bytesafter, &prop) == Success) {
|
||
if (nitems && prop) {
|
||
(void) sprintf(Info[n++], "Client machine = %s", (char*)prop);
|
||
XFree ((char *) prop);
|
||
}
|
||
}
|
||
Info[n++][0] = '\0';
|
||
}
|
||
|
||
(void) sprintf(Info[n++], "Click to dismiss....");
|
||
|
||
/* figure out the width and height of the info window */
|
||
height = n * (Scr->DefaultFont.height+2);
|
||
width = 1;
|
||
for (i = 0; i < n; i++)
|
||
{
|
||
XmbTextExtents(Scr->DefaultFont.font_set, Info[i],
|
||
strlen(Info[i]), &inc_rect, &logical_rect);
|
||
|
||
twidth = logical_rect.width;
|
||
if (twidth > width)
|
||
width = twidth;
|
||
}
|
||
if (InfoLines) XUnmapWindow(dpy, Scr->InfoWindow);
|
||
|
||
width += 10; /* some padding */
|
||
height += 10; /* some padding */
|
||
if (XQueryPointer (dpy, Scr->Root, &JunkRoot, &JunkChild,
|
||
&dummy, &dummy, &px, &py, &udummy)) {
|
||
px -= (width / 2);
|
||
py -= (height / 3);
|
||
if (px + width + BW2 >= Scr->rootw)
|
||
px = Scr->rootw - width - BW2;
|
||
if (py + height + BW2 >= Scr->rooth)
|
||
py = Scr->rooth - height - BW2;
|
||
if (px < 0) px = 0;
|
||
if (py < 0) py = 0;
|
||
} else {
|
||
px = py = 0;
|
||
}
|
||
XMoveResizeWindow(dpy, Scr->InfoWindow, px, py, width, height);
|
||
XMapRaised(dpy, Scr->InfoWindow);
|
||
InfoLines = n;
|
||
InfoWidth = width;
|
||
InfoHeight = height;
|
||
}
|
||
|
||
|
||
|
||
void SetMapStateProp(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 ? tmp_win->icon->w : None));
|
||
|
||
XChangeProperty (dpy, tmp_win->w, _XA_WM_STATE, _XA_WM_STATE, 32,
|
||
PropModeReplace, (unsigned char *) data, 2);
|
||
}
|
||
|
||
|
||
|
||
Bool GetWMState (Window w, int *statep, Window *iwp)
|
||
{
|
||
Atom actual_type;
|
||
int actual_format;
|
||
unsigned long nitems, bytesafter;
|
||
unsigned long *datap = NULL;
|
||
Bool retval = False;
|
||
|
||
if (XGetWindowProperty (dpy, w, _XA_WM_STATE, 0L, 2L, False, _XA_WM_STATE,
|
||
&actual_type, &actual_format, &nitems, &bytesafter,
|
||
(unsigned char **) &datap) != Success || !datap)
|
||
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;
|
||
}
|
||
|
||
|
||
|
||
int WarpToScreen (int n, int 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);
|
||
XBell (dpy, 0);
|
||
return (1);
|
||
}
|
||
}
|
||
|
||
if (Scr->screen == n) return (0); /* already on that screen */
|
||
|
||
PreviousScreen = Scr->screen;
|
||
XQueryPointer (dpy, Scr->Root, &dumwin, &dumwin, &x, &y,
|
||
&dumint, &dumint, &dummask);
|
||
|
||
XWarpPointer (dpy, None, newscr->Root, 0, 0, 0, 0, x, y);
|
||
Scr = newscr;
|
||
return (0);
|
||
}
|
||
|
||
|
||
|
||
|
||
/*
|
||
* BumpWindowColormap - rotate our internal copy of WM_COLORMAP_WINDOWS
|
||
*/
|
||
|
||
int BumpWindowColormap (TwmWindow *tmp, int inc)
|
||
{
|
||
int i, j, previously_installed;
|
||
ColormapWindow **cwins;
|
||
|
||
if (!tmp) return (1);
|
||
|
||
if (inc && tmp->cmaps.number_cwins > 0) {
|
||
cwins = (ColormapWindow **) malloc(sizeof(ColormapWindow *)*
|
||
tmp->cmaps.number_cwins);
|
||
if (cwins) {
|
||
if ((previously_installed =
|
||
/* SUPPRESS 560 */(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) {
|
||
InstallColormaps(PropertyNotify, NULL);
|
||
}
|
||
}
|
||
} else
|
||
FetchWmColormapWindows (tmp);
|
||
return (1);
|
||
}
|
||
|
||
|
||
|
||
void ShowIconManager (void)
|
||
{
|
||
IconMgr *i;
|
||
WorkSpace *wl;
|
||
|
||
if (! Scr->workSpaceManagerActive) return;
|
||
|
||
if (Scr->NoIconManagers) return;
|
||
for (wl = Scr->workSpaceMgr.workSpaceList; wl != NULL; wl = wl->next) {
|
||
for (i = wl->iconmgr; i != NULL; i = i->next) {
|
||
if (i->count == 0) continue;
|
||
if (visible (i->twm_win)) {
|
||
SetMapStateProp (i->twm_win, NormalState);
|
||
XMapWindow (dpy, i->twm_win->w);
|
||
MapRaised (i->twm_win);
|
||
if (i->twm_win->icon && i->twm_win->icon->w)
|
||
XUnmapWindow (dpy, i->twm_win->icon->w);
|
||
}
|
||
i->twm_win->mapped = TRUE;
|
||
i->twm_win->isicon = FALSE;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
void HideIconManager (void)
|
||
{
|
||
IconMgr *i;
|
||
WorkSpace *wl;
|
||
|
||
if (Scr->NoIconManagers) return;
|
||
for (wl = Scr->workSpaceMgr.workSpaceList; wl != NULL; wl = wl->next) {
|
||
for (i = wl->iconmgr; i != NULL; i = i->next) {
|
||
SetMapStateProp (i->twm_win, WithdrawnState);
|
||
XUnmapWindow(dpy, i->twm_win->frame);
|
||
if (i->twm_win->icon && i->twm_win->icon->w) XUnmapWindow (dpy, i->twm_win->icon->w);
|
||
i->twm_win->mapped = FALSE;
|
||
i->twm_win->isicon = TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
void DestroyMenu (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
|
||
*/
|
||
|
||
void WarpAlongRing (XButtonEvent *ev, Bool forward)
|
||
{
|
||
TwmWindow *r, *head;
|
||
|
||
if (Scr->RingLeader)
|
||
head = Scr->RingLeader;
|
||
else if (!(head = Scr->Ring))
|
||
return;
|
||
|
||
if (forward) {
|
||
for (r = head->ring.next; r != head; r = r->ring.next) {
|
||
if (!r) break;
|
||
if (r->mapped && (Scr->WarpRingAnyWhere || visible (r))) break;
|
||
}
|
||
} else {
|
||
for (r = head->ring.prev; r != head; r = r->ring.prev) {
|
||
if (!r) break;
|
||
if (r->mapped && (Scr->WarpRingAnyWhere || visible (r))) break;
|
||
}
|
||
}
|
||
|
||
/* Note: (Scr->Focus != r) is necessary when we move to a workspace that
|
||
has a single window and we want warping to warp to it. */
|
||
if (r && (r != head || Scr->Focus != r)) {
|
||
TwmWindow *p = Scr->RingLeader, *t;
|
||
|
||
Scr->RingLeader = r;
|
||
WarpToWindow (r, 1);
|
||
|
||
if (p && p->mapped &&
|
||
(t = GetTwmWindow(ev->window)) &&
|
||
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;
|
||
#ifdef DEBUG
|
||
fprintf(stderr, "WarpAlongRing: cursor_valid := True; x := %d (%d-%d), y := %d (%d-%d)\n", Tmp_win->ring.curs_x, ev->x_root, t->frame_x, Tmp_win->ring.curs_y, ev->y_root, t->frame_y);
|
||
#endif
|
||
/*
|
||
* The check if the cursor position is inside the window is now
|
||
* done in WarpToWindow().
|
||
*/
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
void WarpToWindow (TwmWindow *t, int must_raise)
|
||
{
|
||
int x, y;
|
||
|
||
if (t->ring.cursor_valid) {
|
||
x = t->ring.curs_x;
|
||
y = t->ring.curs_y;
|
||
#ifdef DEBUG
|
||
fprintf(stderr, "WarpToWindow: cursor_valid; x == %d, y == %d\n", x, y);
|
||
#endif
|
||
|
||
/*
|
||
* XXX is this correct with 3D borders? Easier check possible?
|
||
* frame_bw is for the left border.
|
||
*/
|
||
if (x < t->frame_bw)
|
||
x = t->frame_bw;
|
||
if (x >= t->frame_width + t->frame_bw)
|
||
x = t->frame_width + t->frame_bw - 1;
|
||
if (y < t->title_height + t->frame_bw)
|
||
y = t->title_height + t->frame_bw;
|
||
if (y >= t->frame_height + t->frame_bw)
|
||
y = t->frame_height + t->frame_bw - 1;
|
||
#ifdef DEBUG
|
||
fprintf(stderr, "WarpToWindow: adjusted ; x := %d, y := %d\n", x, y);
|
||
#endif
|
||
} else {
|
||
x = t->frame_width / 2;
|
||
y = t->frame_height / 2;
|
||
#ifdef DEBUG
|
||
fprintf(stderr, "WarpToWindow: middle; x := %d, y := %d\n", x, y);
|
||
#endif
|
||
}
|
||
#if 0
|
||
int dest_x, dest_y;
|
||
Window child;
|
||
|
||
/*
|
||
* Check if the proposed position actually is visible. If not, raise the window.
|
||
* "If the coordinates are contained in a mapped
|
||
* child of dest_w, that child is returned to child_return."
|
||
* We'll need to check for the right child window; the frame probably.
|
||
* (What about XXX window boxes?)
|
||
*
|
||
* Alternatively, use XQueryPointer() which returns the root window
|
||
* the pointer is in, but XXX that won't work for VirtualScreens.
|
||
*/
|
||
if (XTranslateCoordinates(dpy, t->frame, Scr->Root, x, y, &dest_x, &dest_y, &child)) {
|
||
if (child != t->frame)
|
||
must_raise = 1;
|
||
}
|
||
#endif
|
||
if (t->auto_raise || must_raise) AutoRaiseWindow (t);
|
||
if (! visible (t)) {
|
||
WorkSpace *wlist;
|
||
|
||
for (wlist = Scr->workSpaceMgr.workSpaceList; wlist != NULL; wlist = wlist->next) {
|
||
if (OCCUPY (t, wlist)) break;
|
||
}
|
||
if (wlist != NULL) GotoWorkSpace (Scr->currentvs, wlist);
|
||
}
|
||
XWarpPointer (dpy, None, Scr->Root, 0, 0, 0, 0, x + t->frame_x, y + t->frame_y);
|
||
#ifdef DEBUG
|
||
{
|
||
Window root_return;
|
||
Window child_return;
|
||
int root_x_return;
|
||
int root_y_return;
|
||
int win_x_return;
|
||
int win_y_return;
|
||
unsigned int mask_return;
|
||
|
||
if (XQueryPointer(dpy, t->frame, &root_return, &child_return, &root_x_return, &root_y_return, &win_x_return, &win_y_return, &mask_return)) {
|
||
fprintf(stderr, "XQueryPointer: root_return=%x, child_return=%x, root_x_return=%d, root_y_return=%d, win_x_return=%d, win_y_return=%d\n", root_return, child_return, root_x_return, root_y_return, win_x_return, win_y_return);
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
|
||
|
||
|
||
|
||
/*
|
||
* 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 (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 (TwmWindow *tmp, Time timestamp)
|
||
{
|
||
send_clientmessage (tmp->w, _XA_WM_DELETE_WINDOW, timestamp);
|
||
}
|
||
|
||
void SendSaveYourselfMessage (TwmWindow *tmp, Time timestamp)
|
||
{
|
||
send_clientmessage (tmp->w, _XA_WM_SAVE_YOURSELF, timestamp);
|
||
}
|
||
|
||
|
||
void SendTakeFocusMessage (TwmWindow *tmp, Time timestamp)
|
||
{
|
||
send_clientmessage (tmp->w, _XA_WM_TAKE_FOCUS, timestamp);
|
||
}
|
||
|
||
int MoveMenu (XEvent *eventp)
|
||
{
|
||
int XW, YW, newX, newY, cont;
|
||
Bool newev;
|
||
unsigned long event_mask;
|
||
XEvent ev;
|
||
|
||
if (! ActiveMenu) return (1);
|
||
if (! ActiveMenu->pinned) return (1);
|
||
|
||
XW = eventp->xbutton.x_root - ActiveMenu->x;
|
||
YW = eventp->xbutton.y_root - ActiveMenu->y;
|
||
XGrabPointer (dpy, ActiveMenu->w, True,
|
||
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
|
||
GrabModeAsync, GrabModeAsync,
|
||
None, Scr->MoveCursor, CurrentTime);
|
||
|
||
newX = ActiveMenu->x;
|
||
newY = ActiveMenu->y;
|
||
cont = TRUE;
|
||
event_mask = ButtonPressMask | ButtonMotionMask | ButtonReleaseMask | ExposureMask;
|
||
XMaskEvent (dpy, event_mask, &ev);
|
||
while (cont) {
|
||
ev.xbutton.x_root -= Scr->rootx;
|
||
ev.xbutton.y_root -= Scr->rooty;
|
||
switch (ev.xany.type) {
|
||
case ButtonRelease :
|
||
cont = FALSE;
|
||
case MotionNotify :
|
||
if (!cont) {
|
||
newev = False;
|
||
while (XCheckMaskEvent (dpy, ButtonMotionMask | ButtonReleaseMask, &ev)) {
|
||
newev = True;
|
||
if (ev.type == ButtonRelease) break;
|
||
}
|
||
if (ev.type == ButtonRelease) continue;
|
||
if (newev) {
|
||
ev.xbutton.x_root -= Scr->rootx;
|
||
ev.xbutton.y_root -= Scr->rooty;
|
||
}
|
||
}
|
||
newX = ev.xbutton.x_root - XW;
|
||
newY = ev.xbutton.y_root - YW;
|
||
if (Scr->DontMoveOff)
|
||
{
|
||
ConstrainByBorders1 (&newX, ActiveMenu->width,
|
||
&newY, ActiveMenu->height);
|
||
}
|
||
XMoveWindow (dpy, ActiveMenu->w, newX, newY);
|
||
XMaskEvent (dpy, event_mask, &ev);
|
||
break;
|
||
case ButtonPress :
|
||
cont = FALSE;
|
||
newX = ActiveMenu->x;
|
||
newY = ActiveMenu->y;
|
||
break;
|
||
case Expose:
|
||
case NoExpose:
|
||
Event = ev;
|
||
DispatchEvent ();
|
||
XMaskEvent (dpy, event_mask, &ev);
|
||
break;
|
||
}
|
||
}
|
||
XUngrabPointer (dpy, CurrentTime);
|
||
if (ev.xany.type == ButtonRelease) ButtonPressed = -1;
|
||
/*XPutBackEvent (dpy, &ev);*/
|
||
XMoveWindow (dpy, ActiveMenu->w, newX, newY);
|
||
ActiveMenu->x = newX;
|
||
ActiveMenu->y = newY;
|
||
MenuOrigins [MenuDepth - 1].x = newX;
|
||
MenuOrigins [MenuDepth - 1].y = newY;
|
||
|
||
return (1);
|
||
}
|
||
|
||
/***********************************************************************
|
||
*
|
||
* Procedure:
|
||
* DisplayPosition - display the position in the dimensions window
|
||
*
|
||
* Inputs:
|
||
* tmp_win - the current twm window
|
||
* x, y - position of the window
|
||
*
|
||
***********************************************************************
|
||
*/
|
||
|
||
void DisplayPosition (TwmWindow *tmp_win, int x, int y)
|
||
{
|
||
char str [100];
|
||
char signx = '+';
|
||
char signy = '+';
|
||
|
||
if (x < 0) {
|
||
x = -x;
|
||
signx = '-';
|
||
}
|
||
if (y < 0) {
|
||
y = -y;
|
||
signy = '-';
|
||
}
|
||
(void) sprintf (str, " %c%-4d %c%-4d ", signx, x, signy, y);
|
||
XRaiseWindow (dpy, Scr->SizeWindow);
|
||
|
||
Draw3DBorder (Scr->SizeWindow, 0, 0,
|
||
Scr->SizeStringOffset + Scr->SizeStringWidth + SIZE_HINDENT,
|
||
Scr->SizeFont.height + SIZE_VINDENT * 2,
|
||
2, Scr->DefaultC, off, False, False);
|
||
|
||
FB(Scr->DefaultC.fore, Scr->DefaultC.back);
|
||
XmbDrawImageString (dpy, Scr->SizeWindow, Scr->SizeFont.font_set,
|
||
Scr->NormalGC, Scr->SizeStringOffset,
|
||
Scr->SizeFont.ascent + SIZE_VINDENT , str, 13);
|
||
}
|
||
|
||
void MosaicFade (TwmWindow *tmp_win, Window blanket)
|
||
{
|
||
int srect;
|
||
int i, j, nrects;
|
||
Pixmap mask;
|
||
GC gc;
|
||
XGCValues gcv;
|
||
XRectangle *rectangles;
|
||
int width = tmp_win->frame_width;
|
||
int height = tmp_win->frame_height;
|
||
|
||
srect = (width < height) ? (width / 20) : (height / 20);
|
||
mask = XCreatePixmap (dpy, blanket, width, height, 1);
|
||
|
||
gcv.foreground = 1;
|
||
gc = XCreateGC (dpy, mask, GCForeground, &gcv);
|
||
XFillRectangle (dpy, mask, gc, 0, 0, width, height);
|
||
gcv.function = GXclear;
|
||
XChangeGC (dpy, gc, GCFunction, &gcv);
|
||
|
||
nrects = ((width * height) / (srect * srect)) / 10;
|
||
rectangles = (XRectangle*) malloc (nrects * sizeof (XRectangle));
|
||
for (j = 0; j < nrects; j++) {
|
||
rectangles [j].width = srect;
|
||
rectangles [j].height = srect;
|
||
}
|
||
for (i = 0; i < 10; i++) {
|
||
for (j = 0; j < nrects; j++) {
|
||
/* coverity[dc.weak_crypto] */
|
||
rectangles [j].x = ((lrand48 () % width) / srect) * srect;
|
||
/* coverity[dc.weak_crypto] */
|
||
rectangles [j].y = ((lrand48 () % height) / srect) * srect;
|
||
}
|
||
XFillRectangles (dpy, mask, gc, rectangles, nrects);
|
||
XShapeCombineMask (dpy, blanket, ShapeBounding, 0, 0, mask, ShapeSet);
|
||
XFlush (dpy);
|
||
waitamoment (0.020);
|
||
}
|
||
XFreePixmap (dpy, mask);
|
||
XFreeGC (dpy, gc);
|
||
free (rectangles);
|
||
}
|
||
|
||
void ZoomInWindow (TwmWindow *tmp_win, Window blanket)
|
||
{
|
||
Pixmap mask;
|
||
GC gc, gcn;
|
||
XGCValues gcv;
|
||
|
||
int i, nsteps = 20;
|
||
int w = tmp_win->frame_width;
|
||
int h = tmp_win->frame_height;
|
||
int step = (MAX (w, h)) / (2.0 * nsteps);
|
||
|
||
mask = XCreatePixmap (dpy, blanket, w, h, 1);
|
||
gcv.foreground = 1;
|
||
gc = XCreateGC (dpy, mask, GCForeground, &gcv);
|
||
gcv.function = GXclear;
|
||
gcn = XCreateGC (dpy, mask, GCForeground | GCFunction, &gcv);
|
||
|
||
for (i = 0; i < nsteps; i++) {
|
||
XFillRectangle (dpy, mask, gcn, 0, 0, w, h);
|
||
XFillArc (dpy, mask, gc, (w / 2) - ((nsteps - i) * step),
|
||
(h / 2) - ((nsteps - i) * step),
|
||
2 * (nsteps - i) * step,
|
||
2 * (nsteps - i) * step,
|
||
0, 360*64);
|
||
XShapeCombineMask (dpy, blanket, ShapeBounding, 0, 0, mask, ShapeSet);
|
||
XFlush (dpy);
|
||
waitamoment (0.020);
|
||
}
|
||
}
|
||
|
||
void ZoomOutWindow (TwmWindow *tmp_win, Window blanket)
|
||
{
|
||
Pixmap mask;
|
||
GC gc;
|
||
XGCValues gcv;
|
||
|
||
int i, nsteps = 20;
|
||
int w = tmp_win->frame_width;
|
||
int h = tmp_win->frame_height;
|
||
int step = (MAX (w, h)) / (2.0 * nsteps);
|
||
|
||
mask = XCreatePixmap (dpy, blanket, w, h, 1);
|
||
gcv.foreground = 1;
|
||
gc = XCreateGC (dpy, mask, GCForeground, &gcv);
|
||
XFillRectangle (dpy, mask, gc, 0, 0, w, h);
|
||
gcv.function = GXclear;
|
||
XChangeGC (dpy, gc, GCFunction, &gcv);
|
||
|
||
for (i = 0; i < nsteps; i++) {
|
||
XFillArc (dpy, mask, gc, (w / 2) - (i * step),
|
||
(h / 2) - (i * step),
|
||
2 * i * step,
|
||
2 * i * step,
|
||
0, 360*64);
|
||
XShapeCombineMask (dpy, blanket, ShapeBounding, 0, 0, mask, ShapeSet);
|
||
XFlush (dpy);
|
||
waitamoment (0.020);
|
||
}
|
||
}
|
||
|
||
void FadeWindow (TwmWindow *tmp_win, Window blanket)
|
||
{
|
||
Pixmap mask, stipple;
|
||
GC gc;
|
||
XGCValues gcv;
|
||
static unsigned char stipple_bits[] = { 0x0F, 0x0F,
|
||
0xF0, 0xF0,
|
||
0x0F, 0x0F,
|
||
0xF0, 0xF0,
|
||
0x0F, 0x0F,
|
||
0xF0, 0xF0,
|
||
0x0F, 0x0F,
|
||
0xF0, 0xF0,
|
||
};
|
||
int w = tmp_win->frame_width;
|
||
int h = tmp_win->frame_height;
|
||
|
||
stipple = XCreateBitmapFromData (dpy, blanket, (char *)stipple_bits, 8, 8);
|
||
mask = XCreatePixmap (dpy, blanket, w, h, 1);
|
||
gcv.background = 0;
|
||
gcv.foreground = 1;
|
||
gcv.stipple = stipple;
|
||
gcv.fill_style = FillOpaqueStippled;
|
||
gc = XCreateGC (dpy, mask, GCBackground | GCForeground | GCFillStyle | GCStipple, &gcv);
|
||
XFillRectangle (dpy, mask, gc, 0, 0, w, h);
|
||
|
||
XShapeCombineMask (dpy, blanket, ShapeBounding, 0, 0, mask, ShapeSet);
|
||
XFlush (dpy);
|
||
waitamoment (10.0);
|
||
XFreePixmap (dpy, stipple);
|
||
}
|
||
|
||
void SweepWindow (TwmWindow *tmp_win, Window blanket)
|
||
{
|
||
float step = 0.0;
|
||
int i, nsteps = 20;
|
||
int dir = 0, dist = tmp_win->frame_x, dist1;
|
||
|
||
dist1 = tmp_win->frame_y;
|
||
if (dist1 < dist) { dir = 1; dist = dist1; }
|
||
dist1 = tmp_win->vs->w - (tmp_win->frame_x + tmp_win->frame_width);
|
||
if (dist1 < dist) { dir = 2; dist = dist1; }
|
||
dist1 = tmp_win->vs->h - (tmp_win->frame_y + tmp_win->frame_height);
|
||
if (dist1 < dist) { dir = 3; dist = dist1; }
|
||
|
||
switch (dir) {
|
||
case 0: step = tmp_win->frame_x + tmp_win->frame_width; break;
|
||
case 1: step = tmp_win->frame_y + tmp_win->frame_height; break;
|
||
case 2: step = tmp_win->vs->w - tmp_win->frame_x; break;
|
||
case 3: step = tmp_win->vs->h - tmp_win->frame_y; break;
|
||
}
|
||
step /= (float) nsteps;
|
||
step /= (float) nsteps;
|
||
for (i = 0; i < 20; i++) {
|
||
int x = tmp_win->frame_x;
|
||
int y = tmp_win->frame_y;
|
||
switch (dir) {
|
||
case 0: x -= i * i * step; break;
|
||
case 1: y -= i * i * step; break;
|
||
case 2: x += i * i * step; break;
|
||
case 3: y += i * i * step; break;
|
||
}
|
||
XMoveWindow (dpy, blanket, x, y);
|
||
XFlush (dpy);
|
||
waitamoment (0.020);
|
||
}
|
||
}
|
||
|
||
void waitamoment (float timeout)
|
||
{
|
||
#ifdef VMS
|
||
lib$wait (&timeout);
|
||
#else
|
||
struct timeval timeoutstruct;
|
||
int usec = timeout * 1000000;
|
||
timeoutstruct.tv_usec = usec % (unsigned long) 1000000;
|
||
timeoutstruct.tv_sec = usec / (unsigned long) 1000000;
|
||
select (0, (void *) 0, (void *) 0, (void *) 0, &timeoutstruct);
|
||
#endif
|
||
}
|
||
|
||
void packwindow (TwmWindow *tmp_win, char *direction)
|
||
{
|
||
int cons, newx, newy;
|
||
int x, y, px, py, junkX, junkY;
|
||
unsigned int junkK;
|
||
Window junkW;
|
||
|
||
if (!strcmp (direction, "left")) {
|
||
cons = FindConstraint (tmp_win, J_LEFT);
|
||
if (cons == -1) return;
|
||
newx = cons;
|
||
newy = tmp_win->frame_y;
|
||
} else
|
||
if (!strcmp (direction, "right")) {
|
||
cons = FindConstraint (tmp_win, J_RIGHT);
|
||
if (cons == -1) return;
|
||
newx = cons;
|
||
newx -= tmp_win->frame_width + 2 * tmp_win->frame_bw;
|
||
newy = tmp_win->frame_y;
|
||
} else
|
||
if (!strcmp (direction, "top")) {
|
||
cons = FindConstraint (tmp_win, J_TOP);
|
||
if (cons == -1) return;
|
||
newx = tmp_win->frame_x;
|
||
newy = cons;
|
||
} else
|
||
if (!strcmp (direction, "bottom")) {
|
||
cons = FindConstraint (tmp_win, J_BOTTOM);
|
||
if (cons == -1) return;
|
||
newx = tmp_win->frame_x;
|
||
newy = cons;
|
||
newy -= tmp_win->frame_height + 2 * tmp_win->frame_bw;
|
||
} else return;
|
||
|
||
XQueryPointer (dpy, Scr->Root, &junkW, &junkW, &junkX, &junkY, &x, &y, &junkK);
|
||
px = x - tmp_win->frame_x + newx;
|
||
py = y - tmp_win->frame_y + newy;
|
||
XWarpPointer (dpy, Scr->Root, Scr->Root, 0, 0, 0, 0, px, py);
|
||
XRaiseWindow(dpy, tmp_win->frame);
|
||
XMoveWindow (dpy, tmp_win->frame, newx, newy);
|
||
SetupWindow (tmp_win, newx, newy, tmp_win->frame_width, tmp_win->frame_height, -1);
|
||
}
|
||
|
||
void fillwindow (TwmWindow *tmp_win, char *direction)
|
||
{
|
||
int cons, newx, newy, save;
|
||
unsigned int neww, newh;
|
||
int i;
|
||
int winx = tmp_win->frame_x;
|
||
int winy = tmp_win->frame_y;
|
||
int winw = tmp_win->frame_width + 2 * tmp_win->frame_bw;
|
||
int winh = tmp_win->frame_height + 2 * tmp_win->frame_bw;
|
||
|
||
if (!strcmp (direction, "left")) {
|
||
cons = FindConstraint (tmp_win, J_LEFT);
|
||
if (cons == -1) return;
|
||
newx = cons;
|
||
newy = tmp_win->frame_y;
|
||
neww = winw + winx - newx;
|
||
newh = winh;
|
||
neww -= 2 * tmp_win->frame_bw;
|
||
newh -= 2 * tmp_win->frame_bw;
|
||
ConstrainSize (tmp_win, &neww, &newh);
|
||
} else
|
||
if (!strcmp (direction, "right")) {
|
||
for (i = 0; i < 2; i++) {
|
||
cons = FindConstraint (tmp_win, J_RIGHT);
|
||
if (cons == -1) return;
|
||
newx = tmp_win->frame_x;
|
||
newy = tmp_win->frame_y;
|
||
neww = cons - winx;
|
||
newh = winh;
|
||
save = neww;
|
||
neww -= 2 * tmp_win->frame_bw;
|
||
newh -= 2 * tmp_win->frame_bw;
|
||
ConstrainSize (tmp_win, &neww, &newh);
|
||
if ((neww != winw) || (newh != winh) ||
|
||
(cons == Scr->rootw - Scr->BorderRight))
|
||
break;
|
||
neww = save;
|
||
SetupWindow (tmp_win, newx, newy, neww, newh, -1);
|
||
}
|
||
} else
|
||
if (!strcmp (direction, "top")) {
|
||
cons = FindConstraint (tmp_win, J_TOP);
|
||
if (cons == -1) return;
|
||
newx = tmp_win->frame_x;
|
||
newy = cons;
|
||
neww = winw;
|
||
newh = winh + winy - newy;
|
||
neww -= 2 * tmp_win->frame_bw;
|
||
newh -= 2 * tmp_win->frame_bw;
|
||
ConstrainSize (tmp_win, &neww, &newh);
|
||
} else
|
||
if (!strcmp (direction, "bottom")) {
|
||
for (i = 0; i < 2; i++) {
|
||
cons = FindConstraint (tmp_win, J_BOTTOM);
|
||
if (cons == -1) return;
|
||
newx = tmp_win->frame_x;
|
||
newy = tmp_win->frame_y;
|
||
neww = winw;
|
||
newh = cons - winy;
|
||
save = newh;
|
||
neww -= 2 * tmp_win->frame_bw;
|
||
newh -= 2 * tmp_win->frame_bw;
|
||
ConstrainSize (tmp_win, &neww, &newh);
|
||
if ((neww != winw) || (newh != winh) ||
|
||
(cons == Scr->rooth - Scr->BorderBottom))
|
||
break;
|
||
newh = save;
|
||
SetupWindow (tmp_win, newx, newy, neww, newh, -1);
|
||
}
|
||
}
|
||
else if (!strcmp (direction, "vertical"))
|
||
{
|
||
if (tmp_win->zoomed == ZOOM_NONE)
|
||
{
|
||
tmp_win->save_frame_height = tmp_win->frame_height;
|
||
tmp_win->save_frame_width = tmp_win->frame_width;
|
||
tmp_win->save_frame_y = tmp_win->frame_y;
|
||
tmp_win->save_frame_x = tmp_win->frame_x;
|
||
|
||
tmp_win->frame_y++;
|
||
newy = FindConstraint (tmp_win, J_TOP);
|
||
tmp_win->frame_y--;
|
||
newh = FindConstraint (tmp_win, J_BOTTOM) - newy;
|
||
newh -= 2 * tmp_win->frame_bw;
|
||
|
||
newx = tmp_win->frame_x;
|
||
neww = tmp_win->frame_width;
|
||
|
||
ConstrainSize (tmp_win, &neww, &newh);
|
||
|
||
/* if the bottom of the window has moved up
|
||
* it will be pushed down */
|
||
if (newy + newh <
|
||
tmp_win->save_frame_y + tmp_win->save_frame_height)
|
||
newy = tmp_win->save_frame_y +
|
||
tmp_win->save_frame_height - newh;
|
||
tmp_win->zoomed = F_ZOOM;
|
||
SetupWindow (tmp_win, newx, newy, neww, newh, -1);
|
||
}
|
||
else
|
||
{
|
||
fullzoom (tmp_win, tmp_win->zoomed);
|
||
}
|
||
return;
|
||
}
|
||
else return;
|
||
SetupWindow (tmp_win, newx, newy, neww, newh, -1);
|
||
}
|
||
|
||
void jump (TwmWindow *tmp_win, int direction, char *action)
|
||
{
|
||
int fx, fy, px, py, step, status, cons;
|
||
int fwidth, fheight;
|
||
int junkX, junkY;
|
||
unsigned int junkK;
|
||
Window junkW;
|
||
|
||
if (! action) return;
|
||
status = sscanf (action, "%d", &step);
|
||
if (status != 1) return;
|
||
if (step < 1) return;
|
||
|
||
fx = tmp_win->frame_x;
|
||
fy = tmp_win->frame_y;
|
||
XQueryPointer (dpy, Scr->Root, &junkW, &junkW, &junkX, &junkY, &px, &py, &junkK);
|
||
px -= fx; py -= fy;
|
||
|
||
fwidth = tmp_win->frame_width + 2 * tmp_win->frame_bw;
|
||
fheight = tmp_win->frame_height + 2 * tmp_win->frame_bw;
|
||
switch (direction) {
|
||
case J_LEFT :
|
||
cons = FindConstraint (tmp_win, J_LEFT);
|
||
if (cons == -1) return;
|
||
fx -= step * Scr->XMoveGrid;
|
||
if (fx < cons) fx = cons;
|
||
break;
|
||
case J_RIGHT :
|
||
cons = FindConstraint (tmp_win, J_RIGHT);
|
||
if (cons == -1) return;
|
||
fx += step * Scr->XMoveGrid;
|
||
if (fx + fwidth > cons) fx = cons - fwidth;
|
||
break;
|
||
case J_TOP :
|
||
cons = FindConstraint (tmp_win, J_TOP);
|
||
if (cons == -1) return;
|
||
fy -= step * Scr->YMoveGrid;
|
||
if (fy < cons) fy = cons;
|
||
break;
|
||
case J_BOTTOM :
|
||
cons = FindConstraint (tmp_win, J_BOTTOM);
|
||
if (cons == -1) return;
|
||
fy += step * Scr->YMoveGrid;
|
||
if (fy + fheight > cons) fy = cons - fheight;
|
||
break;
|
||
}
|
||
/* Pebl Fixme: don't warp if jump happens through iconmgr */
|
||
XWarpPointer (dpy, Scr->Root, Scr->Root, 0, 0, 0, 0, fx + px, fy + py);
|
||
if (!Scr->NoRaiseMove)
|
||
XRaiseWindow (dpy, tmp_win->frame);
|
||
SetupWindow (tmp_win, fx, fy, tmp_win->frame_width, tmp_win->frame_height, -1);
|
||
}
|
||
|
||
int FindConstraint (TwmWindow *tmp_win, int direction)
|
||
{
|
||
TwmWindow *t;
|
||
int w, h;
|
||
int winx = tmp_win->frame_x;
|
||
int winy = tmp_win->frame_y;
|
||
int winw = tmp_win->frame_width + 2 * tmp_win->frame_bw;
|
||
int winh = tmp_win->frame_height + 2 * tmp_win->frame_bw;
|
||
int ret;
|
||
|
||
switch (direction) {
|
||
case J_LEFT : if (winx < Scr->BorderLeft) return -1;
|
||
ret = Scr->BorderLeft; break;
|
||
case J_RIGHT : if (winx + winw > Scr->rootw - Scr->BorderRight) return -1;
|
||
ret = Scr->rootw - Scr->BorderRight; break;
|
||
case J_TOP : if (winy < Scr->BorderTop) return -1;
|
||
ret = Scr->BorderTop; break;
|
||
case J_BOTTOM : if (winy + winh > Scr->rooth - Scr->BorderBottom) return -1;
|
||
ret = Scr->rooth - Scr->BorderBottom; break;
|
||
default : return -1;
|
||
}
|
||
for (t = Scr->FirstWindow; t != NULL; t = t->next) {
|
||
if (t == tmp_win) continue;
|
||
if (!visible (t)) continue;
|
||
if (!t->mapped) continue;
|
||
w = t->frame_width + 2 * t->frame_bw;
|
||
h = t->frame_height + 2 * t->frame_bw;
|
||
|
||
switch (direction) {
|
||
case J_LEFT :
|
||
if (winx <= t->frame_x + w) continue;
|
||
if (winy >= t->frame_y + h) continue;
|
||
if (winy + winh <= t->frame_y ) continue;
|
||
ret = MAX (ret, t->frame_x + w);
|
||
break;
|
||
case J_RIGHT :
|
||
if (winx + winw >= t->frame_x ) continue;
|
||
if (winy >= t->frame_y + h) continue;
|
||
if (winy + winh <= t->frame_y ) continue;
|
||
ret = MIN (ret, t->frame_x);
|
||
break;
|
||
case J_TOP :
|
||
if (winy <= t->frame_y + h) continue;
|
||
if (winx >= t->frame_x + w) continue;
|
||
if (winx + winw <= t->frame_x ) continue;
|
||
ret = MAX (ret, t->frame_y + h);
|
||
break;
|
||
case J_BOTTOM :
|
||
if (winy + winh >= t->frame_y ) continue;
|
||
if (winx >= t->frame_x + w) continue;
|
||
if (winx + winw <= t->frame_x ) continue;
|
||
ret = MIN (ret, t->frame_y);
|
||
break;
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
void TryToPack (TwmWindow *tmp_win, int *x, int *y)
|
||
{
|
||
TwmWindow *t;
|
||
int newx, newy;
|
||
int w, h;
|
||
int winw = tmp_win->frame_width + 2 * tmp_win->frame_bw;
|
||
int winh = tmp_win->frame_height + 2 * tmp_win->frame_bw;
|
||
|
||
newx = *x;
|
||
newy = *y;
|
||
for (t = Scr->FirstWindow; t != NULL; t = t->next) {
|
||
if (t == tmp_win) continue;
|
||
if (t->winbox != tmp_win->winbox) continue;
|
||
if (t->vs != tmp_win->vs) continue;
|
||
if (!t->mapped) continue;
|
||
|
||
w = t->frame_width + 2 * t->frame_bw;
|
||
h = t->frame_height + 2 * t->frame_bw;
|
||
if (newx >= t->frame_x + w) continue;
|
||
if (newy >= t->frame_y + h) continue;
|
||
if (newx + winw <= t->frame_x) continue;
|
||
if (newy + winh <= t->frame_y) continue;
|
||
|
||
if (newx + Scr->MovePackResistance > t->frame_x + w) { /* left */
|
||
newx = MAX (newx, t->frame_x + w);
|
||
continue;
|
||
}
|
||
if (newx + winw < t->frame_x + Scr->MovePackResistance) { /* right */
|
||
newx = MIN (newx, t->frame_x - winw);
|
||
continue;
|
||
}
|
||
if (newy + Scr->MovePackResistance > t->frame_y + h) { /* top */
|
||
newy = MAX (newy, t->frame_y + h);
|
||
continue;
|
||
}
|
||
if (newy + winh < t->frame_y + Scr->MovePackResistance) { /* bottom */
|
||
newy = MIN (newy, t->frame_y - winh);
|
||
continue;
|
||
}
|
||
}
|
||
*x = newx;
|
||
*y = newy;
|
||
}
|
||
|
||
void TryToPush (TwmWindow *tmp_win, int x, int y, int dir)
|
||
{
|
||
TwmWindow *t;
|
||
int newx, newy, ndir;
|
||
Boolean move;
|
||
int w, h;
|
||
int winw = tmp_win->frame_width + 2 * tmp_win->frame_bw;
|
||
int winh = tmp_win->frame_height + 2 * tmp_win->frame_bw;
|
||
|
||
for (t = Scr->FirstWindow; t != NULL; t = t->next) {
|
||
if (t == tmp_win) continue;
|
||
if (t->winbox != tmp_win->winbox) continue;
|
||
if (t->vs != tmp_win->vs) continue;
|
||
if (!t->mapped) continue;
|
||
|
||
w = t->frame_width + 2 * t->frame_bw;
|
||
h = t->frame_height + 2 * t->frame_bw;
|
||
if (x >= t->frame_x + w) continue;
|
||
if (y >= t->frame_y + h) continue;
|
||
if (x + winw <= t->frame_x) continue;
|
||
if (y + winh <= t->frame_y) continue;
|
||
|
||
move = False;
|
||
if ((dir == 0 || dir == J_LEFT) &&
|
||
(x + Scr->MovePackResistance > t->frame_x + w)) {
|
||
newx = x - w;
|
||
newy = t->frame_y;
|
||
ndir = J_LEFT;
|
||
move = True;
|
||
}
|
||
else
|
||
if ((dir == 0 || dir == J_RIGHT) &&
|
||
(x + winw < t->frame_x + Scr->MovePackResistance)) {
|
||
newx = x + winw;
|
||
newy = t->frame_y;
|
||
ndir = J_RIGHT;
|
||
move = True;
|
||
}
|
||
else
|
||
if ((dir == 0 || dir == J_TOP) &&
|
||
(y + Scr->MovePackResistance > t->frame_y + h)) {
|
||
newx = t->frame_x;
|
||
newy = y - h;
|
||
ndir = J_TOP;
|
||
move = True;
|
||
}
|
||
else
|
||
if ((dir == 0 || dir == J_BOTTOM) &&
|
||
(y + winh < t->frame_y + Scr->MovePackResistance)) {
|
||
newx = t->frame_x;
|
||
newy = y + winh;
|
||
ndir = J_BOTTOM;
|
||
move = True;
|
||
}
|
||
if (move) {
|
||
TryToPush (t, newx, newy, ndir);
|
||
TryToPack (t, &newx, &newy);
|
||
ConstrainByBorders (tmp_win,
|
||
&newx, t->frame_width + 2 * t->frame_bw,
|
||
&newy, t->frame_height + 2 * t->frame_bw);
|
||
SetupWindow (t, newx, newy, t->frame_width, t->frame_height, -1);
|
||
}
|
||
}
|
||
}
|
||
|
||
void TryToGrid (TwmWindow *tmp_win, int *x, int *y)
|
||
{
|
||
int w = tmp_win->frame_width + 2 * tmp_win->frame_bw;
|
||
int h = tmp_win->frame_height + 2 * tmp_win->frame_bw;
|
||
int grav = ((tmp_win->hints.flags & PWinGravity)
|
||
? tmp_win->hints.win_gravity : NorthWestGravity);
|
||
|
||
switch (grav) {
|
||
case ForgetGravity :
|
||
case StaticGravity :
|
||
case NorthWestGravity :
|
||
case NorthGravity :
|
||
case WestGravity :
|
||
case CenterGravity :
|
||
*x = ((*x - Scr->BorderLeft) / Scr->XMoveGrid) * Scr->XMoveGrid
|
||
+ Scr->BorderLeft;
|
||
*y = ((*y - Scr->BorderTop) / Scr->YMoveGrid) * Scr->YMoveGrid
|
||
+ Scr->BorderTop;
|
||
break;
|
||
case NorthEastGravity :
|
||
case EastGravity :
|
||
*x = (((*x + w - Scr->BorderLeft) / Scr->XMoveGrid) *
|
||
Scr->XMoveGrid) - w + Scr->BorderLeft;
|
||
*y = ((*y - Scr->BorderTop) / Scr->YMoveGrid) *
|
||
Scr->YMoveGrid + Scr->BorderTop;
|
||
break;
|
||
case SouthWestGravity :
|
||
case SouthGravity :
|
||
*x = ((*x - Scr->BorderLeft) / Scr->XMoveGrid) * Scr->XMoveGrid
|
||
+ Scr->BorderLeft;
|
||
*y = (((*y + h - Scr->BorderTop) / Scr->YMoveGrid) * Scr->YMoveGrid)
|
||
- h + Scr->BorderTop;
|
||
break;
|
||
case SouthEastGravity :
|
||
*x = (((*x + w - Scr->BorderLeft) / Scr->XMoveGrid) *
|
||
Scr->XMoveGrid) - w + Scr->BorderLeft;
|
||
*y = (((*y + h - Scr->BorderTop) / Scr->YMoveGrid) *
|
||
Scr->YMoveGrid) - h + Scr->BorderTop;
|
||
break;
|
||
}
|
||
}
|
||
|
||
int WarpCursorToDefaultEntry (MenuRoot *menu)
|
||
{
|
||
MenuItem *item;
|
||
Window root;
|
||
int i, x, y, xl, yt;
|
||
unsigned int w, h, bw, d;
|
||
|
||
for (i = 0, item = menu->first; item != menu->last; item = item->next) {
|
||
if (item == menu->defaultitem) break;
|
||
i++;
|
||
}
|
||
if (!XGetGeometry (dpy, menu->w, &root, &x, &y, &w, &h, &bw, &d)) return 0;
|
||
xl = x + (menu->width / 2);
|
||
yt = y + (i + 0.5) * Scr->EntryHeight;
|
||
|
||
XWarpPointer (dpy, Scr->Root, Scr->Root,
|
||
Event.xbutton.x_root, Event.xbutton.y_root,
|
||
menu->width, menu->height, xl, yt);
|
||
return 1;
|
||
}
|
||
|