mirror of
https://github.com/Stichting-MINIX-Research-Foundation/xsrc.git
synced 2025-09-24 04:03:13 -04:00
3642 lines
105 KiB
C
3642 lines
105 KiB
C
/*
|
|
* [ 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 ]
|
|
*/
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include "twm.h"
|
|
#include "util.h"
|
|
#include "parse.h"
|
|
#include "screen.h"
|
|
#include "icons.h"
|
|
#include "resize.h"
|
|
#include "add_window.h"
|
|
#include "events.h"
|
|
#include "clicktofocus.h"
|
|
#include "cursor.h"
|
|
#include "list.h"
|
|
#include "workmgr.h"
|
|
#ifdef VMS
|
|
#include <string.h>
|
|
#include <decw$include/Xos.h>
|
|
#include <decw$include/Xatom.h>
|
|
#include <X11Xmu/CharSet.h>
|
|
#include <decw$include/Xresource.h>
|
|
#else
|
|
#include <X11/Xos.h>
|
|
#include <X11/Xatom.h>
|
|
#include <X11/Xmu/CharSet.h>
|
|
#include <X11/Xresource.h>
|
|
#endif
|
|
#ifdef macII
|
|
int strcmp(); /* missing from string.h in AUX 2.0 */
|
|
#endif
|
|
#ifdef BUGGY_HP700_SERVER
|
|
static void fakeRaiseLower ();
|
|
#endif
|
|
|
|
#ifdef GNOME
|
|
# include "gnomewindefs.h" /* include GNOME hints definitions */
|
|
extern Atom _XA_WIN_WORKSPACE;
|
|
extern Atom _XA_WIN_STATE;
|
|
#endif /* GNOME */
|
|
|
|
extern void twmrc_error_prefix (void); /* in gram.c */
|
|
extern char *captivename;
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Procedure:
|
|
* CreateWorkSpaceManager - create the workspace manager window
|
|
* for this screen.
|
|
*
|
|
* Returned Value:
|
|
* none
|
|
*
|
|
* Inputs:
|
|
* none
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
#define WSPCWINDOW 0
|
|
#define OCCUPYWINDOW 1
|
|
#define OCCUPYBUTTON 2
|
|
|
|
static void Vanish (virtualScreen *vs,
|
|
TwmWindow *tmp_win);
|
|
static void DisplayWin (virtualScreen *vs,
|
|
TwmWindow *tmp_win);
|
|
static void CreateWorkSpaceManagerWindow (virtualScreen *vs);
|
|
static void CreateOccupyWindow (void);
|
|
static unsigned int GetMaskFromResource (TwmWindow *win, char *res);
|
|
static int GetPropertyFromMask (unsigned int mask, char *prop,
|
|
long *gwkspc);
|
|
static void PaintWorkSpaceManagerBorder (virtualScreen *vs);
|
|
static void PaintButton (int which,
|
|
virtualScreen *vs, Window w,
|
|
char *label,
|
|
ColorPair cp, int state);
|
|
static void WMapRemoveFromList (TwmWindow *win, WorkSpace *ws);
|
|
static int WMapWindowMayBeAdded (TwmWindow *win);
|
|
static void WMapAddToList (TwmWindow *win, WorkSpace *ws);
|
|
static void ResizeWorkSpaceManager (virtualScreen *vs, TwmWindow *win);
|
|
static void ResizeOccupyWindow (TwmWindow *win);
|
|
static WorkSpace *GetWorkspace (char *wname);
|
|
static void WMapRedrawWindow (Window window, int width, int height,
|
|
ColorPair cp, char *label);
|
|
static int CanChangeOccupation (TwmWindow **twm_winp);
|
|
void safecopy (char *dest, char *src, int size);
|
|
|
|
Atom _XA_WM_OCCUPATION;
|
|
Atom _XA_WM_CURRENTWORKSPACE;
|
|
Atom _XA_WM_WORKSPACESLIST;
|
|
Atom _XA_WM_CTWMSLIST;
|
|
Atom _XA_WM_CTWM_VSCREENMAP;
|
|
Atom _OL_WIN_ATTR;
|
|
|
|
int fullOccupation = 0;
|
|
int useBackgroundInfo = False;
|
|
XContext MapWListContext = (XContext) 0;
|
|
static Cursor handCursor = (Cursor) 0;
|
|
static Bool DontRedirect (Window window);
|
|
|
|
extern Bool donttoggleworkspacemanagerstate;
|
|
extern Bool MaybeAnimate;
|
|
extern FILE *tracefile;
|
|
|
|
void InitWorkSpaceManager (void)
|
|
{
|
|
Scr->workSpaceMgr.count = 0;
|
|
Scr->workSpaceMgr.workSpaceList = NULL;
|
|
Scr->workSpaceMgr.initialstate = BUTTONSSTATE;
|
|
Scr->workSpaceMgr.geometry = NULL;
|
|
Scr->workSpaceMgr.buttonStyle = STYLE_NORMAL;
|
|
Scr->workSpaceMgr.windowcp.back = Scr->White;
|
|
Scr->workSpaceMgr.windowcp.fore = Scr->Black;
|
|
Scr->workSpaceMgr.windowcpgiven = False;
|
|
|
|
Scr->workSpaceMgr.occupyWindow = calloc(1, sizeof (OccupyWindow));
|
|
Scr->workSpaceMgr.occupyWindow->name = "Occupy Window";
|
|
Scr->workSpaceMgr.occupyWindow->icon_name = "Occupy Window Icon";
|
|
Scr->workSpaceMgr.occupyWindow->geometry = NULL;
|
|
Scr->workSpaceMgr.occupyWindow->columns = 0;
|
|
Scr->workSpaceMgr.occupyWindow->twm_win = (TwmWindow*) 0;
|
|
Scr->workSpaceMgr.occupyWindow->vspace = Scr->WMgrVertButtonIndent;
|
|
Scr->workSpaceMgr.occupyWindow->hspace = Scr->WMgrHorizButtonIndent;
|
|
|
|
Scr->workSpaceMgr.curColors.back = Scr->Black;
|
|
Scr->workSpaceMgr.curColors.fore = Scr->White;
|
|
Scr->workSpaceMgr.defColors.back = Scr->White;
|
|
Scr->workSpaceMgr.defColors.fore = Scr->Black;
|
|
Scr->workSpaceMgr.curImage = None;
|
|
Scr->workSpaceMgr.curPaint = False;
|
|
Scr->workSpaceMgr.defImage = None;
|
|
Scr->workSpaceMgr.vspace = Scr->WMgrVertButtonIndent;
|
|
Scr->workSpaceMgr.hspace = Scr->WMgrHorizButtonIndent;
|
|
Scr->workSpaceMgr.name = "WorkSpaceManager";
|
|
Scr->workSpaceMgr.icon_name = "WorkSpaceManager Icon";
|
|
|
|
Scr->workSpaceMgr.windowFont.basename =
|
|
"-adobe-courier-medium-r-normal--10-100-75-75-m-60-iso8859-1";
|
|
/*"-adobe-courier-bold-r-normal--8-80-75-75-m-50-iso8859-1";*/
|
|
|
|
XrmInitialize ();
|
|
if (MapWListContext == (XContext) 0) MapWListContext = XUniqueContext ();
|
|
}
|
|
|
|
void ConfigureWorkSpaceManager (void) {
|
|
virtualScreen *vs;
|
|
|
|
for (vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
|
|
/*
|
|
* Make sure this is all properly initialized to nothing. Otherwise
|
|
* bad and undefined behavior can show up in certain cases (e.g.,
|
|
* with no Workspaces {} defined in .ctwmrc, the only defined
|
|
* workspace will be random memory bytes, which can causes crashes on
|
|
* e.g. f.menu "TwmWindows".)
|
|
*/
|
|
WorkSpaceWindow *wsw = (WorkSpaceWindow*) calloc (1, sizeof (WorkSpaceWindow));
|
|
wsw->state = Scr->workSpaceMgr.initialstate; /* BUTTONSSTATE */
|
|
vs->wsw = wsw;
|
|
}
|
|
}
|
|
|
|
void CreateWorkSpaceManager (void)
|
|
{
|
|
char wrkSpcList [512];
|
|
char vsmapbuf [1024], *vsmap;
|
|
virtualScreen *vs;
|
|
WorkSpace *ws, *fws;
|
|
int len, vsmaplen;
|
|
long junk;
|
|
|
|
if (! Scr->workSpaceManagerActive) return;
|
|
|
|
Scr->workSpaceMgr.windowFont.basename =
|
|
"-adobe-courier-medium-r-normal--10-100-75-75-m-60-iso8859-1";
|
|
Scr->workSpaceMgr.buttonFont = Scr->IconManagerFont;
|
|
Scr->workSpaceMgr.cp = Scr->IconManagerC;
|
|
if (!Scr->BeNiceToColormap) GetShadeColors (&Scr->workSpaceMgr.cp);
|
|
|
|
_XA_WM_OCCUPATION = XInternAtom (dpy, "WM_OCCUPATION", False);
|
|
_XA_WM_CURRENTWORKSPACE = XInternAtom (dpy, "WM_CURRENTWORKSPACE", False);
|
|
_XA_WM_CTWM_VSCREENMAP = XInternAtom (dpy, "WM_CTWM_VSCREENMAP", False);
|
|
#ifdef GNOME
|
|
_XA_WM_WORKSPACESLIST = XInternAtom (dpy, "_WIN_WORKSPACE_NAMES", False);
|
|
#else /* GNOME */
|
|
_XA_WM_WORKSPACESLIST = XInternAtom (dpy, "WM_WORKSPACESLIST", False);
|
|
#endif /* GNOME */
|
|
_OL_WIN_ATTR = XInternAtom (dpy, "_OL_WIN_ATTR", False);
|
|
|
|
NewFontCursor (&handCursor, "top_left_arrow");
|
|
|
|
vsmaplen = sizeof(vsmapbuf);
|
|
if(CtwmGetVScreenMap(dpy, Scr->Root, vsmapbuf, &vsmaplen) == True)
|
|
vsmap = strtok(vsmapbuf, ",");
|
|
else
|
|
vsmap = NULL;
|
|
|
|
/*
|
|
* weird things can happen if the config file is changed or the atom
|
|
* returned above is messed with. Sometimes windows may disappear in
|
|
* that case depending on what's changed. (depending on where they were
|
|
* on the actual screen.
|
|
*/
|
|
ws = Scr->workSpaceMgr.workSpaceList;
|
|
for (vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
|
|
WorkSpaceWindow *wsw = vs->wsw;
|
|
if(vsmap)
|
|
fws = GetWorkspace(vsmap);
|
|
else
|
|
fws = NULL;
|
|
if(fws) {
|
|
wsw->currentwspc = fws;
|
|
vsmap = strtok(NULL, ",");
|
|
} else {
|
|
wsw->currentwspc = ws;
|
|
ws = ws->next;
|
|
}
|
|
CreateWorkSpaceManagerWindow (vs);
|
|
}
|
|
CreateOccupyWindow ();
|
|
|
|
for (vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
|
|
WorkSpaceWindow *wsw = vs->wsw;
|
|
WorkSpace *ws2 = wsw->currentwspc;
|
|
MapSubwindow *msw = wsw->mswl [ws2->number];
|
|
if (Scr->workSpaceMgr.curImage == None) {
|
|
if (Scr->workSpaceMgr.curPaint) {
|
|
XSetWindowBackground (dpy, msw->w, Scr->workSpaceMgr.curColors.back);
|
|
}
|
|
} else {
|
|
XSetWindowBackgroundPixmap (dpy, msw->w, Scr->workSpaceMgr.curImage->pixmap);
|
|
}
|
|
XSetWindowBorder (dpy, msw->w, Scr->workSpaceMgr.curBorderColor);
|
|
XClearWindow (dpy, msw->w);
|
|
|
|
if (useBackgroundInfo && ! Scr->DontPaintRootWindow) {
|
|
if (ws2->image == None)
|
|
XSetWindowBackground (dpy, vs->window, ws2->backcp.back);
|
|
else
|
|
XSetWindowBackgroundPixmap (dpy, vs->window, ws2->image->pixmap);
|
|
XClearWindow (dpy, vs->window);
|
|
}
|
|
}
|
|
len = GetPropertyFromMask (0xFFFFFFFFu, wrkSpcList, &junk);
|
|
XChangeProperty (dpy, Scr->Root, _XA_WM_WORKSPACESLIST, XA_STRING, 8,
|
|
PropModeReplace, (unsigned char *) wrkSpcList, len);
|
|
}
|
|
|
|
void GotoWorkSpaceByName (virtualScreen *vs, char *wname)
|
|
{
|
|
WorkSpace *ws;
|
|
|
|
if (! Scr->workSpaceManagerActive) return;
|
|
if (!vs) return;
|
|
ws = GetWorkspace(wname);
|
|
if (ws == NULL) return;
|
|
GotoWorkSpace (vs, ws);
|
|
}
|
|
|
|
/* 6/19/1999 nhd for GNOME compliance */
|
|
void GotoWorkSpaceByNumber(virtualScreen *vs, int workspacenum)
|
|
{
|
|
WorkSpace *ws;
|
|
if(! Scr->workSpaceManagerActive) return;
|
|
if (!vs) return;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (ws->number == workspacenum) break;
|
|
}
|
|
if (ws == NULL) return;
|
|
GotoWorkSpace (vs, ws);
|
|
}
|
|
/* */
|
|
|
|
void GotoPrevWorkSpace (virtualScreen *vs)
|
|
{
|
|
WorkSpace *ws1, *ws2;
|
|
|
|
if (! Scr->workSpaceManagerActive) return;
|
|
if (!vs) return;
|
|
ws1 = Scr->workSpaceMgr.workSpaceList;
|
|
if (ws1 == NULL) return;
|
|
ws2 = ws1->next;
|
|
|
|
while ((ws2 != vs->wsw->currentwspc) && (ws2 != NULL)) {
|
|
ws1 = ws2;
|
|
ws2 = ws2->next;
|
|
}
|
|
GotoWorkSpace (vs, ws1);
|
|
}
|
|
|
|
void GotoNextWorkSpace (virtualScreen *vs)
|
|
{
|
|
WorkSpace *ws;
|
|
if (! Scr->workSpaceManagerActive) return;
|
|
if (!vs) return;
|
|
|
|
ws = vs->wsw->currentwspc;
|
|
ws = (ws->next != NULL) ? ws->next : Scr->workSpaceMgr.workSpaceList;
|
|
GotoWorkSpace (vs, ws);
|
|
}
|
|
|
|
void GotoRightWorkSpace (virtualScreen *vs)
|
|
{
|
|
WorkSpace *ws;
|
|
int number, columns, count;
|
|
|
|
if (!Scr->workSpaceManagerActive)
|
|
return;
|
|
if (!vs)
|
|
return;
|
|
|
|
ws = vs->wsw->currentwspc;
|
|
number = ws->number;
|
|
columns = Scr->workSpaceMgr.columns;
|
|
count = Scr->workSpaceMgr.count;
|
|
number++;
|
|
if ((number % columns) == 0)
|
|
number -= columns;
|
|
else if (number >= count)
|
|
number = (number / columns) * columns;
|
|
|
|
GotoWorkSpaceByNumber(vs, number);
|
|
}
|
|
|
|
void GotoLeftWorkSpace (virtualScreen *vs)
|
|
{
|
|
WorkSpace *ws;
|
|
int number, columns, count;
|
|
|
|
if (!Scr->workSpaceManagerActive)
|
|
return;
|
|
if (!vs)
|
|
return;
|
|
|
|
ws = vs->wsw->currentwspc;
|
|
number = ws->number;
|
|
columns = Scr->workSpaceMgr.columns;
|
|
count = Scr->workSpaceMgr.count;
|
|
number += (number % columns) ? -1 : (columns - 1);
|
|
if (number >= count)
|
|
number = count - 1;
|
|
GotoWorkSpaceByNumber(vs, number);
|
|
}
|
|
|
|
void GotoUpWorkSpace (virtualScreen *vs)
|
|
{
|
|
WorkSpace *ws;
|
|
int number, lines, columns, count;
|
|
|
|
if (!Scr->workSpaceManagerActive)
|
|
return;
|
|
if (!vs)
|
|
return;
|
|
|
|
ws = vs->wsw->currentwspc;
|
|
number = ws->number;
|
|
lines = Scr->workSpaceMgr.lines;
|
|
columns = Scr->workSpaceMgr.columns;
|
|
count = Scr->workSpaceMgr.count;
|
|
number -= columns;
|
|
if (number < 0) {
|
|
number += lines * columns;
|
|
/* If the number of workspaces is not a multiple of nr of columns */
|
|
if (number >= count)
|
|
number -= columns;
|
|
}
|
|
GotoWorkSpaceByNumber(vs, number);
|
|
}
|
|
|
|
void GotoDownWorkSpace (virtualScreen *vs)
|
|
{
|
|
WorkSpace *ws;
|
|
int number, columns, count;
|
|
|
|
if (!Scr->workSpaceManagerActive)
|
|
return;
|
|
if (!vs)
|
|
return;
|
|
|
|
ws = vs->wsw->currentwspc;
|
|
number = ws->number;
|
|
columns = Scr->workSpaceMgr.columns;
|
|
count = Scr->workSpaceMgr.count;
|
|
number += columns;
|
|
if (number >= count) {
|
|
number %= columns;
|
|
}
|
|
GotoWorkSpaceByNumber(vs, number);
|
|
}
|
|
|
|
void ShowBackground (virtualScreen *vs)
|
|
{
|
|
static int state = 0;
|
|
TwmWindow *twmWin;
|
|
|
|
if (state) {
|
|
for (twmWin = Scr->FirstWindow; twmWin != NULL; twmWin = twmWin->next) {
|
|
if (twmWin->savevs == vs) {
|
|
DisplayWin (vs, twmWin);
|
|
}
|
|
twmWin->savevs = NULL;
|
|
}
|
|
state = 0;
|
|
} else {
|
|
for (twmWin = Scr->FirstWindow; twmWin != NULL; twmWin = twmWin->next) {
|
|
if (twmWin->vs == vs) {
|
|
twmWin->savevs = twmWin->vs;
|
|
Vanish (vs, twmWin);
|
|
}
|
|
}
|
|
state = 1;
|
|
}
|
|
}
|
|
|
|
void GotoWorkSpace (virtualScreen *vs, WorkSpace *ws)
|
|
{
|
|
TwmWindow *twmWin;
|
|
WorkSpace *oldws, *newws;
|
|
WList *wl, *wl1;
|
|
WinList winl;
|
|
XSetWindowAttributes attr;
|
|
XWindowAttributes winattrs;
|
|
unsigned long eventMask;
|
|
IconMgr *iconmgr;
|
|
Window oldw;
|
|
Window neww;
|
|
TwmWindow *focuswindow;
|
|
TwmWindow *last_twmWin = NULL;
|
|
virtualScreen *tmpvs;
|
|
|
|
if (! Scr->workSpaceManagerActive) return;
|
|
for (tmpvs = Scr->vScreenList; tmpvs != NULL; tmpvs = tmpvs->next) {
|
|
if (ws == tmpvs->wsw->currentwspc) {
|
|
XBell (dpy, 0);
|
|
return;
|
|
}
|
|
}
|
|
oldws = vs->wsw->currentwspc;
|
|
newws = ws;
|
|
if (oldws == newws) return;
|
|
|
|
attr.backing_store = NotUseful;
|
|
attr.save_under = False;
|
|
|
|
if (useBackgroundInfo && ! Scr->DontPaintRootWindow) {
|
|
if (newws->image == None)
|
|
XSetWindowBackground (dpy, vs->window, newws->backcp.back);
|
|
else
|
|
XSetWindowBackgroundPixmap (dpy, vs->window, newws->image->pixmap);
|
|
XClearWindow (dpy, vs->window);
|
|
}
|
|
|
|
/* If SaveWorkspaceFocus is on, save the focus of the last window. */
|
|
if ( Scr->SaveWorkspaceFocus ) {
|
|
oldws->save_focus = Scr->Focus;
|
|
}
|
|
|
|
focuswindow = (TwmWindow *)NULL;
|
|
for (twmWin = Scr->FirstWindow; twmWin != NULL; twmWin = twmWin->next) {
|
|
if (twmWin->vs == vs) {
|
|
if (!OCCUPY (twmWin, newws)) {
|
|
virtualScreen *tvs;
|
|
Vanish (vs, twmWin);
|
|
for (tvs = Scr->vScreenList; tvs != NULL; tvs = tvs->next) {
|
|
if (tvs == vs) continue;
|
|
if (OCCUPY (twmWin, tvs->wsw->currentwspc)) {
|
|
DisplayWin (tvs, twmWin);
|
|
break;
|
|
}
|
|
}
|
|
} else if (twmWin->hasfocusvisible) {
|
|
focuswindow = twmWin;
|
|
SetFocusVisualAttributes (focuswindow, False);
|
|
}
|
|
}
|
|
}
|
|
/* Move to the end of the twmWin list */
|
|
for (twmWin = Scr->FirstWindow; twmWin != NULL; twmWin = twmWin->next) {
|
|
last_twmWin = twmWin;
|
|
}
|
|
/* Iconise in reverse order */
|
|
for (twmWin = last_twmWin; twmWin != NULL; twmWin = twmWin->prev) {
|
|
if (OCCUPY (twmWin, newws) && !twmWin->vs) DisplayWin (vs, twmWin);
|
|
}
|
|
/*
|
|
Reorganize icon manager window lists
|
|
*/
|
|
for (twmWin = Scr->FirstWindow; twmWin != NULL; twmWin = twmWin->next) {
|
|
wl = twmWin->iconmanagerlist;
|
|
if (wl == NULL) continue;
|
|
if (OCCUPY (wl->iconmgr->twm_win, newws)) continue;
|
|
wl1 = wl;
|
|
wl = wl->nextv;
|
|
while (wl != NULL) {
|
|
if (OCCUPY (wl->iconmgr->twm_win, newws)) break;
|
|
wl1 = wl;
|
|
wl = wl->nextv;
|
|
}
|
|
if (wl != NULL) {
|
|
wl1->nextv = wl->nextv;
|
|
wl->nextv = twmWin->iconmanagerlist;
|
|
twmWin->iconmanagerlist = wl;
|
|
}
|
|
}
|
|
wl = (WList*)0;
|
|
for (iconmgr = newws->iconmgr; iconmgr; iconmgr = iconmgr->next) {
|
|
if (iconmgr->first) {
|
|
wl = iconmgr->first;
|
|
break;
|
|
}
|
|
}
|
|
CurrentIconManagerEntry (wl);
|
|
if (focuswindow) {
|
|
SetFocusVisualAttributes (focuswindow, True);
|
|
}
|
|
vs->wsw->currentwspc = newws;
|
|
if (Scr->ReverseCurrentWorkspace && vs->wsw->state == MAPSTATE) {
|
|
MapSubwindow *msw = vs->wsw->mswl [oldws->number];
|
|
for (winl = msw->wl; winl != NULL; winl = winl->next) {
|
|
WMapRedrawName (vs, winl);
|
|
}
|
|
msw = vs->wsw->mswl [newws->number];
|
|
for (winl = msw->wl; winl != NULL; winl = winl->next) {
|
|
WMapRedrawName (vs, winl);
|
|
}
|
|
} else
|
|
if (vs->wsw->state == BUTTONSSTATE) {
|
|
ButtonSubwindow *bsw = vs->wsw->bswl [oldws->number];
|
|
PaintButton (WSPCWINDOW, vs, bsw->w, oldws->label, oldws->cp, off);
|
|
bsw = vs->wsw->bswl [newws->number];
|
|
PaintButton (WSPCWINDOW, vs, bsw->w, newws->label, newws->cp, on);
|
|
}
|
|
oldws->iconmgr = Scr->iconmgr;
|
|
Scr->iconmgr = newws->iconmgr;
|
|
|
|
oldw = vs->wsw->mswl [oldws->number]->w;
|
|
neww = vs->wsw->mswl [newws->number]->w;
|
|
if (useBackgroundInfo) {
|
|
if (oldws->image == None || Scr->NoImagesInWorkSpaceManager)
|
|
XSetWindowBackground (dpy, oldw, oldws->backcp.back);
|
|
else
|
|
XSetWindowBackgroundPixmap (dpy, oldw, oldws->image->pixmap);
|
|
}
|
|
else {
|
|
if (Scr->workSpaceMgr.defImage == None || Scr->NoImagesInWorkSpaceManager)
|
|
XSetWindowBackground (dpy, oldw, Scr->workSpaceMgr.defColors.back);
|
|
else
|
|
XSetWindowBackgroundPixmap (dpy, oldw, Scr->workSpaceMgr.defImage->pixmap);
|
|
}
|
|
attr.border_pixel = Scr->workSpaceMgr.defBorderColor;
|
|
XChangeWindowAttributes (dpy, oldw, CWBorderPixel, &attr);
|
|
|
|
if (Scr->workSpaceMgr.curImage == None) {
|
|
if (Scr->workSpaceMgr.curPaint) XSetWindowBackground (dpy, neww, Scr->workSpaceMgr.curColors.back);
|
|
}
|
|
else {
|
|
XSetWindowBackgroundPixmap (dpy, neww, Scr->workSpaceMgr.curImage->pixmap);
|
|
}
|
|
attr.border_pixel = Scr->workSpaceMgr.curBorderColor;
|
|
XChangeWindowAttributes (dpy, neww, CWBorderPixel, &attr);
|
|
|
|
XClearWindow (dpy, oldw);
|
|
XClearWindow (dpy, neww);
|
|
|
|
XGetWindowAttributes(dpy, Scr->Root, &winattrs);
|
|
eventMask = winattrs.your_event_mask;
|
|
XSelectInput(dpy, Scr->Root, eventMask & ~PropertyChangeMask);
|
|
|
|
XChangeProperty (dpy, Scr->Root, _XA_WM_CURRENTWORKSPACE, XA_STRING, 8,
|
|
PropModeReplace, (unsigned char *) newws->name, strlen (newws->name));
|
|
#ifdef GNOME
|
|
/* nhd 6/19/1999 for GNOME compliance
|
|
* Publish which workspace the root window shows/contains.
|
|
* Olaf Rhialto Seibert: However, don't do it when the root window is
|
|
* captive, since it will be moved itself: for non-root windows this
|
|
* property is used to indicate in which workspace it is contained.
|
|
*/
|
|
|
|
if (!Scr->CaptiveRoot)
|
|
XChangeProperty (dpy, Scr->Root, _XA_WIN_WORKSPACE, XA_CARDINAL, 32,
|
|
PropModeReplace, (unsigned char *) &(newws->number), 1);
|
|
#endif /* GNOME */
|
|
XSelectInput(dpy, Scr->Root, eventMask);
|
|
|
|
/* XDestroyWindow (dpy, cachew);*/
|
|
if (Scr->ChangeWorkspaceFunction.func != 0) {
|
|
char *action;
|
|
XEvent event;
|
|
|
|
action = Scr->ChangeWorkspaceFunction.item ?
|
|
Scr->ChangeWorkspaceFunction.item->action : NULL;
|
|
ExecuteFunction (Scr->ChangeWorkspaceFunction.func, action,
|
|
(Window) 0, (TwmWindow*) 0, &event, C_ROOT, FALSE);
|
|
}
|
|
|
|
/* If SaveWorkspaceFocus is on, try to restore the focus to the last
|
|
window which was focused when we left this workspace. */
|
|
if (Scr->SaveWorkspaceFocus && newws->save_focus) {
|
|
twmWin = newws->save_focus;
|
|
if (OCCUPY(twmWin, newws)) { /* check should not even be needed anymore */
|
|
WarpToWindow(twmWin, 0);
|
|
} else {
|
|
newws->save_focus = NULL;
|
|
}
|
|
}
|
|
|
|
/* keep track of the order of the workspaces across restarts */
|
|
CtwmSetVScreenMap(dpy, Scr->Root, Scr->vScreenList);
|
|
|
|
XSync (dpy, 0);
|
|
if (Scr->ClickToFocus || Scr->SloppyFocus) set_last_window (newws);
|
|
MaybeAnimate = True;
|
|
}
|
|
|
|
char *GetCurrentWorkSpaceName (virtualScreen *vs)
|
|
{
|
|
if (! Scr->workSpaceManagerActive) return (NULL);
|
|
if (!vs) vs = Scr->vScreenList;
|
|
return vs->wsw->currentwspc->name;
|
|
}
|
|
|
|
void AddWorkSpace (char *name, char *background, char *foreground,
|
|
char *backback, char *backfore, char *backpix)
|
|
{
|
|
WorkSpace *ws;
|
|
int wsnum;
|
|
Image *image;
|
|
|
|
wsnum = Scr->workSpaceMgr.count;
|
|
if (wsnum == MAXWORKSPACE) return;
|
|
|
|
fullOccupation |= (1 << wsnum);
|
|
ws = (WorkSpace*) malloc (sizeof (WorkSpace));
|
|
ws->FirstWindowRegion = NULL;
|
|
#if 0 /* def VMS */
|
|
{
|
|
char *ftemp;
|
|
ftemp = (char *) malloc((strlen(name)+1)*sizeof(char));
|
|
ws->name = strcpy (ftemp,name);
|
|
ftemp = (char *) malloc((strlen(name)+1)*sizeof(char));
|
|
ws->label = strcpy (ftemp,name);
|
|
}
|
|
#else
|
|
ws->name = (char*) strdup (name);
|
|
ws->label = (char*) strdup (name);
|
|
#endif
|
|
ws->clientlist = NULL;
|
|
ws->save_focus = NULL;
|
|
|
|
if (background == NULL)
|
|
ws->cp.back = Scr->IconManagerC.back;
|
|
else
|
|
GetColor (Scr->Monochrome, &(ws->cp.back), background);
|
|
|
|
if (foreground == NULL)
|
|
ws->cp.fore = Scr->IconManagerC.fore;
|
|
else
|
|
GetColor (Scr->Monochrome, &(ws->cp.fore), foreground);
|
|
|
|
#ifdef COLOR_BLIND_USER
|
|
ws->cp.shadc = Scr->White;
|
|
ws->cp.shadd = Scr->Black;
|
|
#else
|
|
if (!Scr->BeNiceToColormap) GetShadeColors (&ws->cp);
|
|
#endif
|
|
|
|
if (backback == NULL)
|
|
GetColor (Scr->Monochrome, &(ws->backcp.back), "Black");
|
|
else {
|
|
GetColor (Scr->Monochrome, &(ws->backcp.back), backback);
|
|
useBackgroundInfo = True;
|
|
}
|
|
|
|
if (backfore == NULL)
|
|
GetColor (Scr->Monochrome, &(ws->backcp.fore), "White");
|
|
else {
|
|
GetColor (Scr->Monochrome, &(ws->backcp.fore), backfore);
|
|
useBackgroundInfo = True;
|
|
}
|
|
if ((image = GetImage (backpix, ws->backcp)) != None) {
|
|
ws->image = image;
|
|
useBackgroundInfo = True;
|
|
}
|
|
else {
|
|
ws->image = None;
|
|
}
|
|
ws->next = NULL;
|
|
ws->number = wsnum;
|
|
Scr->workSpaceMgr.count++;
|
|
|
|
if (Scr->workSpaceMgr.workSpaceList == NULL) {
|
|
Scr->workSpaceMgr.workSpaceList = ws;
|
|
}
|
|
else {
|
|
WorkSpace *wstmp = Scr->workSpaceMgr.workSpaceList;
|
|
while (wstmp->next != NULL) { wstmp = wstmp->next; }
|
|
wstmp->next = ws;
|
|
}
|
|
Scr->workSpaceManagerActive = 1;
|
|
}
|
|
|
|
static XrmOptionDescRec table [] = {
|
|
{"-xrm", NULL, XrmoptionResArg, (XPointer) NULL},
|
|
};
|
|
|
|
void SetupOccupation (TwmWindow *twm_win,
|
|
int occupation_hint) /* <== [ Matthew McNeill Feb 1997 ] == */
|
|
{
|
|
TwmWindow *t;
|
|
unsigned char *prop;
|
|
unsigned long nitems, bytesafter;
|
|
Atom actual_type;
|
|
int actual_format;
|
|
int state;
|
|
Window icon;
|
|
char **cliargv = NULL;
|
|
int cliargc;
|
|
Bool status;
|
|
char *str_type;
|
|
XrmValue value;
|
|
char wrkSpcList [512];
|
|
int len;
|
|
WorkSpace *ws;
|
|
XWindowAttributes winattrs;
|
|
unsigned long eventMask;
|
|
XrmDatabase db = NULL;
|
|
virtualScreen *vs;
|
|
long gwkspc = 0; /* for GNOME - which workspace we occupy */
|
|
|
|
if (! Scr->workSpaceManagerActive) {
|
|
twm_win->occupation = 1 << 0; /* occupy workspace #0 */
|
|
/*
|
|
* Choose some valid virtual screen.
|
|
* InitVirtualScreens() always seems to set this to non-NULL.
|
|
*/
|
|
twm_win->vs = Scr->vScreenList; /* only one virtual screen */
|
|
/* more?... */
|
|
|
|
return;
|
|
}
|
|
if (twm_win->wspmgr) return;
|
|
|
|
/*twm_win->occupation = twm_win->iswinbox ? fullOccupation : 0;*/
|
|
twm_win->occupation = 0;
|
|
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (LookInList (ws->clientlist, twm_win->full_name, &twm_win->class)) {
|
|
twm_win->occupation |= 1 << ws->number;
|
|
}
|
|
}
|
|
|
|
if (LookInList (Scr->OccupyAll, twm_win->full_name, &twm_win->class)) {
|
|
twm_win->occupation = fullOccupation;
|
|
}
|
|
|
|
if (XGetCommand (dpy, twm_win->w, &cliargv, &cliargc)) {
|
|
XrmParseCommand (&db, table, 1, "ctwm", &cliargc, cliargv);
|
|
status = XrmGetResource (db, "ctwm.workspace", "Ctwm.Workspace", &str_type, &value);
|
|
if ((status == True) && (value.size != 0)) {
|
|
strncpy (wrkSpcList, value.addr, value.size);
|
|
twm_win->occupation = GetMaskFromResource (twm_win, wrkSpcList);
|
|
}
|
|
XrmDestroyDatabase (db);
|
|
XFreeStringList (cliargv);
|
|
}
|
|
|
|
if (RestartPreviousState) {
|
|
if (XGetWindowProperty (dpy, twm_win->w, _XA_WM_OCCUPATION, 0L, 2500, False,
|
|
XA_STRING, &actual_type, &actual_format, &nitems,
|
|
&bytesafter, &prop) == Success) {
|
|
if (nitems != 0) {
|
|
twm_win->occupation = GetMaskFromProperty (prop, nitems);
|
|
XFree ((char *) prop);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (twm_win->iconmgr) return; /* someone tried to modify occupation of icon managers */
|
|
|
|
if (! Scr->TransientHasOccupation) {
|
|
if (twm_win->transient) {
|
|
t = GetTwmWindow(twm_win->transientfor);
|
|
if (t != NULL) twm_win->occupation = t->occupation;
|
|
}
|
|
else
|
|
if (twm_win->group != 0) {
|
|
t = GetTwmWindow(twm_win->group);
|
|
if (t != NULL) twm_win->occupation = t->occupation;
|
|
}
|
|
}
|
|
|
|
/*============[ Matthew McNeill Feb 1997 ]========================*
|
|
* added in functionality of specific occupation state. The value
|
|
* should be a valid occupation bit-field or 0 for the default action
|
|
*/
|
|
|
|
if (occupation_hint != 0)
|
|
twm_win->occupation = occupation_hint;
|
|
|
|
/*================================================================*/
|
|
|
|
if ((twm_win->occupation & fullOccupation) == 0) {
|
|
vs = Scr->currentvs;
|
|
if (vs && vs->wsw->currentwspc)
|
|
twm_win->occupation = 1 << vs->wsw->currentwspc->number;
|
|
else {
|
|
twm_win->occupation = 1;
|
|
}
|
|
}
|
|
twm_win->vs = NULL;
|
|
for (vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
|
|
if (OCCUPY (twm_win, vs->wsw->currentwspc)) {
|
|
twm_win->vs = vs;
|
|
break;
|
|
}
|
|
}
|
|
|
|
len = GetPropertyFromMask (twm_win->occupation, wrkSpcList, &gwkspc);
|
|
|
|
if (!XGetWindowAttributes(dpy, twm_win->w, &winattrs)) return;
|
|
eventMask = winattrs.your_event_mask;
|
|
XSelectInput(dpy, twm_win->w, eventMask & ~PropertyChangeMask);
|
|
|
|
XChangeProperty (dpy, twm_win->w, _XA_WM_OCCUPATION, XA_STRING, 8,
|
|
PropModeReplace, (unsigned char *) wrkSpcList, len);
|
|
#ifdef GNOME
|
|
XChangeProperty (dpy, twm_win->w, _XA_WIN_WORKSPACE, XA_CARDINAL, 32,
|
|
PropModeReplace, (unsigned char *)(&gwkspc), 1);
|
|
if (XGetWindowProperty (dpy, twm_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);
|
|
}
|
|
if (twm_win->occupation == fullOccupation)
|
|
gwkspc |= WIN_STATE_STICKY;
|
|
else
|
|
gwkspc &= ~WIN_STATE_STICKY;
|
|
XChangeProperty (dpy, twm_win->w, _XA_WIN_STATE, XA_CARDINAL, 32,
|
|
PropModeReplace, (unsigned char *)&gwkspc, 1);
|
|
#endif /* GNOME */
|
|
XSelectInput (dpy, twm_win->w, eventMask);
|
|
|
|
/* kludge */
|
|
state = NormalState;
|
|
if (!(RestartPreviousState && GetWMState (twm_win->w, &state, &icon) &&
|
|
(state == NormalState || state == IconicState || state == InactiveState))) {
|
|
if (twm_win->wmhints && (twm_win->wmhints->flags & StateHint))
|
|
state = twm_win->wmhints->initial_state;
|
|
}
|
|
if (visible (twm_win)) {
|
|
if (state == InactiveState) SetMapStateProp (twm_win, NormalState);
|
|
} else {
|
|
if (state == NormalState) SetMapStateProp (twm_win, InactiveState);
|
|
}
|
|
}
|
|
|
|
void safecopy(char *dest, char *src, int size)
|
|
{
|
|
strncpy(dest, src, size - 1);
|
|
dest[size - 1] = '\0';
|
|
}
|
|
|
|
Bool RedirectToCaptive (Window window)
|
|
{
|
|
unsigned long nitems, bytesafter;
|
|
Atom actual_type;
|
|
int actual_format;
|
|
char **cliargv = NULL;
|
|
int cliargc;
|
|
Bool status;
|
|
char *str_type;
|
|
XrmValue value;
|
|
int ret;
|
|
Atom _XA_WM_CTWM_ROOT;
|
|
char *atomname;
|
|
Window newroot;
|
|
XWindowAttributes wa;
|
|
XrmDatabase db = NULL;
|
|
|
|
if (DontRedirect (window)) return (False);
|
|
if (!XGetCommand (dpy, window, &cliargv, &cliargc)) return (False);
|
|
XrmParseCommand (&db, table, 1, "ctwm", &cliargc, cliargv);
|
|
if (db == NULL) {
|
|
if (cliargv) XFreeStringList (cliargv);
|
|
return False;
|
|
}
|
|
ret = False;
|
|
status = XrmGetResource (db, "ctwm.redirect", "Ctwm.Redirect", &str_type, &value);
|
|
if ((status == True) && (value.size != 0)) {
|
|
char cctwm [64];
|
|
Window *prop;
|
|
|
|
safecopy (cctwm, value.addr, sizeof(cctwm));
|
|
atomname = (char*) malloc (strlen ("WM_CTWM_ROOT_") + strlen (cctwm) + 1);
|
|
sprintf (atomname, "WM_CTWM_ROOT_%s", cctwm);
|
|
_XA_WM_CTWM_ROOT = XInternAtom (dpy, atomname, False);
|
|
|
|
if (XGetWindowProperty (dpy, Scr->Root, _XA_WM_CTWM_ROOT,
|
|
0L, 1L, False, AnyPropertyType, &actual_type, &actual_format,
|
|
&nitems, &bytesafter, (unsigned char **)&prop) == Success) {
|
|
if (actual_type == XA_WINDOW && actual_format == 32 &&
|
|
nitems == 1 /*&& bytesafter == 0*/) {
|
|
newroot = *prop;
|
|
if (XGetWindowAttributes (dpy, newroot, &wa)) {
|
|
XReparentWindow (dpy, window, newroot, 0, 0);
|
|
XMapWindow (dpy, window);
|
|
ret = True;
|
|
}
|
|
}
|
|
XFree ((char *)prop);
|
|
}
|
|
}
|
|
status = XrmGetResource (db, "ctwm.rootWindow", "Ctwm.RootWindow", &str_type, &value);
|
|
if ((status == True) && (value.size != 0)) {
|
|
char rootw [32];
|
|
unsigned int scanned;
|
|
|
|
safecopy (rootw, value.addr, sizeof(rootw));
|
|
if (sscanf (rootw, "%x", &scanned) == 1) {
|
|
newroot = scanned;
|
|
if (XGetWindowAttributes (dpy, newroot, &wa)) {
|
|
XReparentWindow (dpy, window, newroot, 0, 0);
|
|
XMapWindow (dpy, window);
|
|
ret = True;
|
|
}
|
|
}
|
|
}
|
|
XrmDestroyDatabase (db);
|
|
XFreeStringList (cliargv);
|
|
return (ret);
|
|
}
|
|
|
|
/*
|
|
* The window whose occupation is being manipulated.
|
|
*/
|
|
static TwmWindow *occupyWin = (TwmWindow*) 0;
|
|
|
|
static int CanChangeOccupation(TwmWindow **twm_winp)
|
|
{
|
|
TwmWindow *twm_win;
|
|
|
|
if (!Scr->workSpaceManagerActive)
|
|
return 0;
|
|
if (occupyWin != NULL)
|
|
return 0;
|
|
twm_win = *twm_winp;
|
|
if (twm_win->iconmgr)
|
|
return 0;
|
|
if (!Scr->TransientHasOccupation) {
|
|
if (twm_win->transient)
|
|
return 0;
|
|
if (twm_win->group != (Window) 0 && twm_win->group != twm_win->w) {
|
|
/*
|
|
* When trying to modify a group member window,
|
|
* operate on the group leader instead
|
|
* (and thereby on all group member windows as well).
|
|
* If we can't find the group leader, pretend it isn't set.
|
|
*/
|
|
twm_win = GetTwmWindow(twm_win->group);
|
|
if (!twm_win)
|
|
return 1;
|
|
*twm_winp = twm_win;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void Occupy (TwmWindow *twm_win)
|
|
{
|
|
int x, y, junkX, junkY;
|
|
unsigned int junkB, junkD;
|
|
unsigned int width, height;
|
|
int xoffset, yoffset;
|
|
Window junkW, w;
|
|
unsigned int junkK;
|
|
struct OccupyWindow *occupyWindow;
|
|
|
|
if (!CanChangeOccupation(&twm_win))
|
|
return;
|
|
|
|
occupyWindow = Scr->workSpaceMgr.occupyWindow;
|
|
occupyWindow->tmpOccupation = twm_win->occupation;
|
|
w = occupyWindow->w;
|
|
XGetGeometry (dpy, w, &junkW, &junkX, &junkY, &width, &height, &junkB, &junkD);
|
|
XQueryPointer (dpy, Scr->Root, &junkW, &junkW, &junkX, &junkY, &x, &y, &junkK);
|
|
x -= (width / 2);
|
|
y -= (height / 2);
|
|
if (x < 0) x = 0;
|
|
if (y < 0) y = 0;
|
|
xoffset = width + 2 * Scr->BorderWidth;
|
|
yoffset = height + 2 * Scr->BorderWidth + Scr->TitleHeight;
|
|
if ((x + xoffset) > Scr->rootw) x = Scr->rootw - xoffset;
|
|
if ((y + yoffset) > Scr->rooth) y = Scr->rooth - yoffset;
|
|
|
|
occupyWindow->twm_win->occupation = twm_win->occupation;
|
|
if (occupyWindow->twm_win->vs != Scr->currentvs) {
|
|
XReparentWindow(dpy, occupyWindow->twm_win->frame, Scr->Root, x, y);
|
|
occupyWindow->twm_win->vs = Scr->currentvs;
|
|
} else
|
|
XMoveWindow(dpy, occupyWindow->twm_win->frame, x, y);
|
|
|
|
SetMapStateProp (occupyWindow->twm_win, NormalState);
|
|
XMapWindow (dpy, occupyWindow->w);
|
|
XMapRaised (dpy, occupyWindow->twm_win->frame);
|
|
occupyWindow->twm_win->mapped = TRUE;
|
|
occupyWin = twm_win;
|
|
}
|
|
|
|
void OccupyHandleButtonEvent (XEvent *event)
|
|
{
|
|
WorkSpace *ws;
|
|
OccupyWindow *occupyW;
|
|
Window buttonW;
|
|
|
|
if (! Scr->workSpaceManagerActive) return;
|
|
if (occupyWin == (TwmWindow*) 0) return;
|
|
|
|
buttonW = event->xbutton.window;
|
|
if (buttonW == 0) return; /* icon */
|
|
|
|
XGrabPointer (dpy, Scr->Root, True,
|
|
ButtonPressMask | ButtonReleaseMask,
|
|
GrabModeAsync, GrabModeAsync,
|
|
Scr->Root, None, CurrentTime);
|
|
|
|
occupyW = Scr->workSpaceMgr.occupyWindow;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (occupyW->obuttonw [ws->number] == buttonW) break;
|
|
}
|
|
if (ws != NULL) {
|
|
int mask = 1 << ws->number;
|
|
if ((occupyW->tmpOccupation & mask) == 0) {
|
|
PaintButton (OCCUPYWINDOW, NULL, occupyW->obuttonw [ws->number],
|
|
ws->label, ws->cp, on);
|
|
} else {
|
|
PaintButton (OCCUPYWINDOW, NULL, occupyW->obuttonw [ws->number],
|
|
ws->label, ws->cp, off);
|
|
}
|
|
occupyW->tmpOccupation ^= mask;
|
|
}
|
|
else
|
|
if (buttonW == occupyW->OK) {
|
|
if (occupyW->tmpOccupation == 0) return;
|
|
ChangeOccupation (occupyWin, occupyW->tmpOccupation);
|
|
XUnmapWindow (dpy, occupyW->twm_win->frame);
|
|
occupyW->twm_win->mapped = FALSE;
|
|
occupyW->twm_win->occupation = 0;
|
|
occupyWin = (TwmWindow*) 0;
|
|
XSync (dpy, 0);
|
|
}
|
|
else
|
|
if (buttonW == occupyW->cancel) {
|
|
XUnmapWindow (dpy, occupyW->twm_win->frame);
|
|
occupyW->twm_win->mapped = FALSE;
|
|
occupyW->twm_win->occupation = 0;
|
|
occupyWin = (TwmWindow*) 0;
|
|
XSync (dpy, 0);
|
|
}
|
|
else
|
|
if (buttonW == occupyW->allworkspc) {
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
PaintButton (OCCUPYWINDOW, NULL, occupyW->obuttonw [ws->number],
|
|
ws->label, ws->cp, on);
|
|
}
|
|
occupyW->tmpOccupation = fullOccupation;
|
|
}
|
|
if (ButtonPressed == -1) XUngrabPointer (dpy, CurrentTime);
|
|
}
|
|
|
|
void OccupyAll (TwmWindow *twm_win)
|
|
{
|
|
IconMgr *save;
|
|
|
|
if (!CanChangeOccupation(&twm_win))
|
|
return;
|
|
save = Scr->iconmgr;
|
|
Scr->iconmgr = Scr->workSpaceMgr.workSpaceList->iconmgr;
|
|
ChangeOccupation (twm_win, fullOccupation);
|
|
Scr->iconmgr = save;
|
|
}
|
|
|
|
void AddToWorkSpace (char *wname, TwmWindow *twm_win)
|
|
{
|
|
WorkSpace *ws;
|
|
int newoccupation;
|
|
|
|
if (!CanChangeOccupation(&twm_win))
|
|
return;
|
|
ws = GetWorkspace (wname);
|
|
if (!ws)
|
|
return;
|
|
|
|
if (twm_win->occupation & (1 << ws->number))
|
|
return;
|
|
newoccupation = twm_win->occupation | (1 << ws->number);
|
|
ChangeOccupation (twm_win, newoccupation);
|
|
}
|
|
|
|
void RemoveFromWorkSpace (char *wname, TwmWindow *twm_win)
|
|
{
|
|
WorkSpace *ws;
|
|
int newoccupation;
|
|
|
|
if (!CanChangeOccupation(&twm_win))
|
|
return;
|
|
ws = GetWorkspace (wname);
|
|
if (!ws)
|
|
return;
|
|
|
|
newoccupation = twm_win->occupation & ~(1 << ws->number);
|
|
if (!newoccupation) return;
|
|
ChangeOccupation (twm_win, newoccupation);
|
|
}
|
|
|
|
void ToggleOccupation (char *wname, TwmWindow *twm_win)
|
|
{
|
|
WorkSpace *ws;
|
|
int newoccupation;
|
|
|
|
if (!CanChangeOccupation(&twm_win))
|
|
return;
|
|
ws = GetWorkspace (wname);
|
|
if (!ws) return;
|
|
|
|
newoccupation = twm_win->occupation ^ (1 << ws->number);
|
|
if (!newoccupation) return;
|
|
ChangeOccupation (twm_win, newoccupation);
|
|
}
|
|
|
|
void MoveToNextWorkSpace (virtualScreen *vs, TwmWindow *twm_win)
|
|
{
|
|
WorkSpace *wlist1, *wlist2;
|
|
int newoccupation;
|
|
|
|
if (!CanChangeOccupation(&twm_win))
|
|
return;
|
|
|
|
wlist1 = vs->wsw->currentwspc;
|
|
wlist2 = wlist1->next;
|
|
wlist2 = wlist2 ? wlist2 : Scr->workSpaceMgr.workSpaceList;
|
|
|
|
newoccupation = (twm_win->occupation ^ (1 << wlist1->number))
|
|
| (1 << wlist2->number);
|
|
ChangeOccupation (twm_win, newoccupation);
|
|
}
|
|
|
|
|
|
void MoveToNextWorkSpaceAndFollow (virtualScreen *vs, TwmWindow *twm_win)
|
|
{
|
|
if (!CanChangeOccupation(&twm_win))
|
|
return;
|
|
|
|
MoveToNextWorkSpace(vs, twm_win);
|
|
GotoNextWorkSpace(vs);
|
|
#if 0
|
|
RaiseWindow(twm_win); /* XXX really do this? */
|
|
#endif
|
|
}
|
|
|
|
|
|
void MoveToPrevWorkSpace (virtualScreen *vs, TwmWindow *twm_win)
|
|
{
|
|
WorkSpace *wlist1, *wlist2;
|
|
int newoccupation;
|
|
|
|
if (!CanChangeOccupation(&twm_win))
|
|
return;
|
|
|
|
wlist1 = Scr->workSpaceMgr.workSpaceList;
|
|
wlist2 = vs->wsw->currentwspc;
|
|
if (wlist1 == NULL) return;
|
|
|
|
while (wlist1->next != wlist2 && wlist1->next != NULL) {
|
|
wlist1 = wlist1->next;
|
|
}
|
|
|
|
newoccupation = (twm_win->occupation ^ (1 << wlist2->number))
|
|
| (1 << wlist1->number);
|
|
ChangeOccupation (twm_win, newoccupation);
|
|
}
|
|
|
|
void MoveToPrevWorkSpaceAndFollow (virtualScreen *vs, TwmWindow *twm_win)
|
|
{
|
|
if (!CanChangeOccupation(&twm_win))
|
|
return;
|
|
|
|
MoveToPrevWorkSpace(vs, twm_win);
|
|
GotoPrevWorkSpace(vs);
|
|
#if 0
|
|
RaiseWindow(twm_win); /* XXX really do this? */
|
|
#endif
|
|
}
|
|
|
|
static WorkSpace *GetWorkspace (char *wname)
|
|
{
|
|
WorkSpace *ws;
|
|
|
|
if (!wname) return (NULL);
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (strcmp (ws->label, wname) == 0) break;
|
|
}
|
|
if (ws == NULL) {
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (strcmp (ws->name, wname) == 0) break;
|
|
}
|
|
}
|
|
return (ws);
|
|
}
|
|
|
|
void AllocateOthersIconManagers (void)
|
|
{
|
|
IconMgr *p = NULL, *ip, *oldp, *oldv;
|
|
WorkSpace *ws;
|
|
|
|
if (! Scr->workSpaceManagerActive) return;
|
|
|
|
oldp = Scr->iconmgr;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList->next; ws != NULL; ws = ws->next) {
|
|
ws->iconmgr = (IconMgr *) malloc (sizeof (IconMgr));
|
|
*ws->iconmgr = *oldp;
|
|
oldv = ws->iconmgr;
|
|
oldp->nextv = ws->iconmgr;
|
|
oldv->nextv = NULL;
|
|
|
|
for (ip = oldp->next; ip != NULL; ip = ip->next) {
|
|
p = (IconMgr *) malloc (sizeof (IconMgr));
|
|
*p = *ip;
|
|
ip->nextv = p;
|
|
p->next = NULL;
|
|
p->prev = oldv;
|
|
p->nextv = NULL;
|
|
oldv->next = p;
|
|
oldv = p;
|
|
}
|
|
for (ip = ws->iconmgr; ip != NULL; ip = ip->next) {
|
|
ip->lasti = p;
|
|
}
|
|
oldp = ws->iconmgr;
|
|
}
|
|
Scr->workSpaceMgr.workSpaceList->iconmgr = Scr->iconmgr;
|
|
}
|
|
|
|
static void Vanish (virtualScreen *vs, TwmWindow *tmp_win)
|
|
{
|
|
XWindowAttributes winattrs;
|
|
unsigned long eventMask;
|
|
|
|
if (vs && tmp_win->vs && tmp_win->vs != vs)
|
|
return;
|
|
if (tmp_win->UnmapByMovingFarAway) {
|
|
XMoveWindow (dpy, tmp_win->frame, Scr->rootw + 1, Scr->rooth + 1);
|
|
} else if (tmp_win->mapped) {
|
|
XGetWindowAttributes(dpy, tmp_win->w, &winattrs);
|
|
eventMask = winattrs.your_event_mask;
|
|
XSelectInput (dpy, tmp_win->w, eventMask & ~StructureNotifyMask);
|
|
XUnmapWindow (dpy, tmp_win->w);
|
|
XUnmapWindow (dpy, tmp_win->frame);
|
|
XSelectInput (dpy, tmp_win->w, eventMask);
|
|
|
|
if (!tmp_win->DontSetInactive)
|
|
SetMapStateProp (tmp_win, InactiveState);
|
|
} else if (tmp_win->icon_on && tmp_win->icon && tmp_win->icon->w) {
|
|
XUnmapWindow (dpy, tmp_win->icon->w);
|
|
IconDown (tmp_win);
|
|
}
|
|
|
|
/*
|
|
* XXX - this may need to be tweaked to find the real window at 0x0.
|
|
* Most people will setup virtualscreens left to right, but some
|
|
* may not. The purpose of this is in the event of a ctwm death/restart,
|
|
* geometries of windows that were on unmapped workspaces will show
|
|
* up where they belong.
|
|
* XXX - XReparentWindow() messes up the stacking order of windows.
|
|
* It should be avoided as much as possible. This already affects
|
|
* switching away from and back to a workspace. Therefore do this only
|
|
* if there are at least 2 virtual screens AND the new one (firstvs)
|
|
* differs from where the window currently is. (Olaf Seibert).
|
|
*/
|
|
|
|
if (Scr->vScreenList && Scr->vScreenList->next) {
|
|
int x, y;
|
|
unsigned int junk;
|
|
Window junkW, w = tmp_win->frame;
|
|
virtualScreen *firstvs = NULL;
|
|
|
|
for (firstvs = Scr->vScreenList; firstvs; firstvs = firstvs->next)
|
|
if (firstvs->x == 0 && firstvs->y == 0)
|
|
break;
|
|
if (firstvs && firstvs != vs) {
|
|
XGetGeometry (dpy, w, &junkW, &x, &y, &junk, &junk, &junk, &junk);
|
|
XReparentWindow(dpy, w, firstvs->window, x, y);
|
|
tmp_win->vs = firstvs;
|
|
}
|
|
}
|
|
|
|
tmp_win->old_parent_vs = tmp_win->vs;
|
|
tmp_win->vs = NULL;
|
|
}
|
|
|
|
static void DisplayWin (virtualScreen *vs, TwmWindow *tmp_win)
|
|
{
|
|
XWindowAttributes winattrs;
|
|
unsigned long eventMask;
|
|
|
|
/*
|
|
* A window cannot be shown in multiple virtual screens, even if
|
|
* it occupies both corresponding workspaces.
|
|
*/
|
|
if (vs && tmp_win->vs)
|
|
return;
|
|
tmp_win->vs = vs;
|
|
|
|
if (!tmp_win->mapped) {
|
|
if (tmp_win->isicon) {
|
|
if (tmp_win->icon_on) {
|
|
if (tmp_win->icon && tmp_win->icon->w) {
|
|
if (vs && vs != tmp_win->old_parent_vs) {
|
|
int x, y;
|
|
unsigned int junk;
|
|
Window junkW, w = tmp_win->icon->w;
|
|
XGetGeometry (dpy, w, &junkW, &x, &y, &junk, &junk, &junk, &junk);
|
|
XReparentWindow (dpy, w, vs->window, x, y);
|
|
}
|
|
|
|
IconUp (tmp_win);
|
|
XMapWindow (dpy, tmp_win->icon->w);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
if (tmp_win->UnmapByMovingFarAway) {
|
|
if (vs) /* XXX I don't believe the handling of UnmapByMovingFarAway is quite correct */
|
|
XReparentWindow (dpy, tmp_win->frame, vs->window,
|
|
tmp_win->frame_x, tmp_win->frame_y);
|
|
else
|
|
XMoveWindow (dpy, tmp_win->frame, tmp_win->frame_x, tmp_win->frame_y);
|
|
} else {
|
|
if (!tmp_win->squeezed) {
|
|
XGetWindowAttributes(dpy, tmp_win->w, &winattrs);
|
|
eventMask = winattrs.your_event_mask;
|
|
XSelectInput (dpy, tmp_win->w, eventMask & ~StructureNotifyMask);
|
|
XMapWindow (dpy, tmp_win->w);
|
|
XSelectInput (dpy, tmp_win->w, eventMask);
|
|
}
|
|
if (vs && vs != tmp_win->old_parent_vs) {
|
|
XReparentWindow (dpy, tmp_win->frame, vs->window, tmp_win->frame_x, tmp_win->frame_y);
|
|
}
|
|
XMapWindow (dpy, tmp_win->frame);
|
|
SetMapStateProp (tmp_win, NormalState);
|
|
}
|
|
}
|
|
|
|
void ChangeOccupation (TwmWindow *tmp_win, int newoccupation)
|
|
{
|
|
TwmWindow *t;
|
|
virtualScreen *vs;
|
|
WorkSpace *ws;
|
|
int oldoccupation;
|
|
char namelist [512];
|
|
int len;
|
|
int final_x, final_y;
|
|
XWindowAttributes winattrs;
|
|
unsigned long eventMask;
|
|
long gwkspc = 0; /* for gnome - the workspace of this window */
|
|
int changedoccupation;
|
|
#ifdef GNOME
|
|
unsigned char *prop;
|
|
unsigned long bytesafter, numitems;
|
|
Atom actual_type;
|
|
int actual_format;
|
|
#endif /* GNOME */
|
|
|
|
if ((newoccupation == 0) || /* in case the property has been broken by another client */
|
|
(newoccupation == tmp_win->occupation)) {
|
|
len = GetPropertyFromMask (tmp_win->occupation, namelist, &gwkspc);
|
|
XGetWindowAttributes(dpy, tmp_win->w, &winattrs);
|
|
eventMask = winattrs.your_event_mask;
|
|
XSelectInput(dpy, tmp_win->w, eventMask & ~PropertyChangeMask);
|
|
|
|
XChangeProperty (dpy, tmp_win->w, _XA_WM_OCCUPATION, XA_STRING, 8,
|
|
PropModeReplace, (unsigned char *) namelist, len);
|
|
#ifdef GNOME
|
|
XChangeProperty (dpy, tmp_win->w, _XA_WIN_WORKSPACE, XA_CARDINAL, 32,
|
|
PropModeReplace, (unsigned char *)(&gwkspc), 1);
|
|
if (XGetWindowProperty(dpy, tmp_win->w, _XA_WIN_STATE, 0L, 32, False,
|
|
XA_CARDINAL, &actual_type, &actual_format, &numitems,
|
|
&bytesafter, &prop)
|
|
!= Success || numitems == 0) {
|
|
gwkspc = 0;
|
|
} else {
|
|
gwkspc = (int)*prop;
|
|
XFree((char *)prop);
|
|
}
|
|
if (tmp_win->occupation == fullOccupation)
|
|
gwkspc |= WIN_STATE_STICKY;
|
|
else
|
|
gwkspc &= ~WIN_STATE_STICKY;
|
|
XChangeProperty (dpy, tmp_win->w, _XA_WIN_STATE, XA_CARDINAL, 32,
|
|
PropModeReplace, (unsigned char *)&gwkspc, 1);
|
|
#endif /* GNOME */
|
|
XSelectInput (dpy, tmp_win->w, eventMask);
|
|
return;
|
|
}
|
|
oldoccupation = tmp_win->occupation;
|
|
tmp_win->occupation = newoccupation & ~oldoccupation;
|
|
AddIconManager (tmp_win);
|
|
tmp_win->occupation = newoccupation;
|
|
RemoveIconManager (tmp_win);
|
|
|
|
if (tmp_win->vs && !OCCUPY (tmp_win, tmp_win->vs->wsw->currentwspc)) {
|
|
Vanish (tmp_win->vs, tmp_win);
|
|
}
|
|
/*
|
|
* If a window occupies multiple workspaces, try to find another workspace
|
|
* which is currently in another virtual screen, so that the window
|
|
* can be shown there now.
|
|
*/
|
|
if (!tmp_win->vs) {
|
|
for (vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
|
|
if (OCCUPY (tmp_win, vs->wsw->currentwspc)) {
|
|
DisplayWin (vs, tmp_win);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
int mask = 1 << ws->number;
|
|
if (oldoccupation & mask) {
|
|
if (!(newoccupation & mask)) {
|
|
RemoveWindowFromRegion (tmp_win);
|
|
if (PlaceWindowInRegion (tmp_win, &final_x, &final_y))
|
|
XMoveWindow (dpy, tmp_win->frame, final_x, final_y);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
len = GetPropertyFromMask (newoccupation, namelist, &gwkspc);
|
|
XGetWindowAttributes(dpy, tmp_win->w, &winattrs);
|
|
eventMask = winattrs.your_event_mask;
|
|
XSelectInput(dpy, tmp_win->w, eventMask & ~PropertyChangeMask);
|
|
|
|
XChangeProperty (dpy, tmp_win->w, _XA_WM_OCCUPATION, XA_STRING, 8,
|
|
PropModeReplace, (unsigned char *) namelist, len);
|
|
|
|
#ifdef GNOME
|
|
/* Tell GNOME where this window lives */
|
|
XChangeProperty (dpy, tmp_win->w, _XA_WIN_WORKSPACE, XA_CARDINAL, 32,
|
|
PropModeReplace, (unsigned char *)(&gwkspc), 1);
|
|
if (XGetWindowProperty (dpy, tmp_win->w, _XA_WIN_STATE, 0L, 32, False,
|
|
XA_CARDINAL, &actual_type, &actual_format, &numitems,
|
|
&bytesafter, &prop)
|
|
!= Success || numitems == 0) {
|
|
gwkspc = 0;
|
|
} else {
|
|
gwkspc = (int)*prop;
|
|
XFree ((char *)prop);
|
|
}
|
|
if (tmp_win->occupation == fullOccupation)
|
|
gwkspc |= WIN_STATE_STICKY;
|
|
else
|
|
gwkspc &= ~WIN_STATE_STICKY;
|
|
XChangeProperty (dpy, tmp_win->w, _XA_WIN_STATE, XA_CARDINAL, 32,
|
|
PropModeReplace, (unsigned char *)&gwkspc, 1);
|
|
#endif /* GNOME */
|
|
XSelectInput(dpy, tmp_win->w, eventMask);
|
|
|
|
if (!WMapWindowMayBeAdded(tmp_win)) {
|
|
newoccupation = 0;
|
|
}
|
|
if (Scr->workSpaceMgr.noshowoccupyall) {
|
|
/* We can safely change new/oldoccupation here, it's only used
|
|
* for WMapAddToList()/WMapRemoveFromList() from here on.
|
|
*/
|
|
/* if (newoccupation == fullOccupation)
|
|
newoccupation = 0; */
|
|
if (oldoccupation == fullOccupation)
|
|
oldoccupation = 0;
|
|
}
|
|
changedoccupation = oldoccupation ^ newoccupation;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
int mask = 1 << ws->number;
|
|
if (changedoccupation & mask) {
|
|
if (newoccupation & mask) {
|
|
WMapAddToList (tmp_win, ws);
|
|
} else {
|
|
WMapRemoveFromList (tmp_win, ws);
|
|
if (Scr->SaveWorkspaceFocus && ws->save_focus == tmp_win) {
|
|
ws->save_focus = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (! Scr->TransientHasOccupation) {
|
|
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)) {
|
|
ChangeOccupation (t, tmp_win->occupation);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void WmgrRedoOccupation (TwmWindow *win)
|
|
{
|
|
WorkSpace *ws;
|
|
int newoccupation;
|
|
|
|
if (LookInList (Scr->OccupyAll, win->full_name, &win->class)) {
|
|
newoccupation = fullOccupation;
|
|
}
|
|
else {
|
|
newoccupation = 0;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (LookInList (ws->clientlist, win->full_name, &win->class)) {
|
|
newoccupation |= 1 << ws->number;
|
|
}
|
|
}
|
|
}
|
|
if (newoccupation != 0) ChangeOccupation (win, newoccupation);
|
|
}
|
|
|
|
void WMgrRemoveFromCurrentWorkSpace (virtualScreen *vs, TwmWindow *win)
|
|
{
|
|
WorkSpace *ws;
|
|
int newoccupation;
|
|
|
|
ws = vs->wsw->currentwspc;
|
|
if (! OCCUPY (win, ws)) return;
|
|
|
|
newoccupation = win->occupation & ~(1 << ws->number);
|
|
if (newoccupation == 0) return;
|
|
|
|
ChangeOccupation (win, newoccupation);
|
|
}
|
|
|
|
void WMgrAddToCurrentWorkSpaceAndWarp (virtualScreen *vs, char *winname)
|
|
{
|
|
TwmWindow *tw;
|
|
int newoccupation;
|
|
|
|
for (tw = Scr->FirstWindow; tw != NULL; tw = tw->next) {
|
|
if (match (winname, tw->full_name)) break;
|
|
}
|
|
if (!tw) {
|
|
for (tw = Scr->FirstWindow; tw != NULL; tw = tw->next) {
|
|
if (match (winname, tw->class.res_name)) break;
|
|
}
|
|
if (!tw) {
|
|
for (tw = Scr->FirstWindow; tw != NULL; tw = tw->next) {
|
|
if (match (winname, tw->class.res_class)) break;
|
|
}
|
|
}
|
|
}
|
|
if (!tw) {
|
|
XBell (dpy, 0);
|
|
return;
|
|
}
|
|
if ((! Scr->WarpUnmapped) && (! tw->mapped)) {
|
|
XBell (dpy, 0);
|
|
return;
|
|
}
|
|
if (! OCCUPY (tw, vs->wsw->currentwspc)) {
|
|
newoccupation = tw->occupation | (1 << vs->wsw->currentwspc->number);
|
|
ChangeOccupation (tw, newoccupation);
|
|
}
|
|
|
|
if (! tw->mapped) DeIconify (tw);
|
|
WarpToWindow (tw, Scr->RaiseOnWarp);
|
|
}
|
|
|
|
static void CreateWorkSpaceManagerWindow (virtualScreen *vs)
|
|
{
|
|
int mask;
|
|
int lines, vspace, hspace, count, columns;
|
|
unsigned int width, height, bwidth, bheight;
|
|
char *name, *icon_name, *geometry;
|
|
int i, j;
|
|
ColorPair cp;
|
|
MyFont font;
|
|
WorkSpace *ws;
|
|
int x, y, strWid, wid;
|
|
unsigned long border;
|
|
TwmWindow *tmp_win;
|
|
XSetWindowAttributes attr;
|
|
XWindowAttributes wattr;
|
|
unsigned long attrmask;
|
|
XSizeHints sizehints;
|
|
XWMHints wmhints;
|
|
int gravity;
|
|
XRectangle inc_rect;
|
|
XRectangle logical_rect;
|
|
|
|
name = Scr->workSpaceMgr.name;
|
|
icon_name = Scr->workSpaceMgr.icon_name;
|
|
geometry = Scr->workSpaceMgr.geometry;
|
|
columns = Scr->workSpaceMgr.columns;
|
|
vspace = Scr->workSpaceMgr.vspace;
|
|
hspace = Scr->workSpaceMgr.hspace;
|
|
font = Scr->workSpaceMgr.buttonFont;
|
|
cp = Scr->workSpaceMgr.cp;
|
|
border = Scr->workSpaceMgr.defBorderColor;
|
|
|
|
count = 0;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) count++;
|
|
Scr->workSpaceMgr.count = count;
|
|
|
|
if (columns == 0) {
|
|
lines = 2;
|
|
columns = ((count - 1) / lines) + 1;
|
|
}
|
|
else {
|
|
lines = ((count - 1) / columns) + 1;
|
|
}
|
|
Scr->workSpaceMgr.lines = lines;
|
|
Scr->workSpaceMgr.columns = columns;
|
|
|
|
strWid = 0;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
XmbTextExtents(font.font_set, ws->label, strlen (ws->label),
|
|
&inc_rect, &logical_rect);
|
|
wid = logical_rect.width;
|
|
if (wid > strWid) strWid = wid;
|
|
}
|
|
if (geometry != NULL) {
|
|
mask = XParseGeometry (geometry, &x, &y, &width, &height);
|
|
bwidth = (mask & WidthValue) ? ((width - (columns * hspace)) / columns) : strWid + 10;
|
|
bheight = (mask & HeightValue) ? ((height - (lines * vspace)) / lines) : 22;
|
|
width = columns * (bwidth + hspace);
|
|
height = lines * (bheight + vspace);
|
|
|
|
if (! (mask & YValue)) {
|
|
y = 0;
|
|
mask |= YNegative;
|
|
}
|
|
if (mask & XValue) {
|
|
if (mask & XNegative) {
|
|
x += vs->w - width;
|
|
gravity = (mask & YNegative) ? SouthEastGravity : NorthEastGravity;
|
|
}
|
|
else {
|
|
gravity = (mask & YNegative) ? SouthWestGravity : NorthWestGravity;
|
|
}
|
|
}
|
|
else {
|
|
x = (vs->w - width) / 2;
|
|
gravity = (mask & YValue) ? ((mask & YNegative) ?
|
|
SouthGravity : NorthGravity) : SouthGravity;
|
|
}
|
|
if (mask & YNegative) y += vs->h - height;
|
|
}
|
|
else {
|
|
bwidth = strWid + 2 * Scr->WMgrButtonShadowDepth + 6;
|
|
bheight = 22;
|
|
width = columns * (bwidth + hspace);
|
|
height = lines * (bheight + vspace);
|
|
x = (vs->w - width) / 2;
|
|
y = vs->h - height;
|
|
gravity = NorthWestGravity;
|
|
}
|
|
|
|
#define Dummy 1
|
|
|
|
vs->wsw->width = Dummy;
|
|
vs->wsw->height = Dummy;
|
|
vs->wsw->bswl = (ButtonSubwindow**)
|
|
malloc (Scr->workSpaceMgr.count * sizeof (ButtonSubwindow*));
|
|
vs->wsw->mswl = (MapSubwindow**)
|
|
malloc (Scr->workSpaceMgr.count * sizeof (MapSubwindow*));
|
|
|
|
vs->wsw->w = XCreateSimpleWindow (dpy, Scr->Root, x, y, width, height, 0,
|
|
Scr->Black, cp.back);
|
|
i = 0; j = 0;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
Window mapsw, butsw;
|
|
MapSubwindow *msw;
|
|
ButtonSubwindow *bsw;
|
|
|
|
vs->wsw->bswl [ws->number] = bsw =
|
|
(ButtonSubwindow*) malloc (sizeof (ButtonSubwindow));
|
|
vs->wsw->mswl [ws->number] = msw =
|
|
(MapSubwindow*) malloc (sizeof (MapSubwindow));
|
|
|
|
butsw = bsw->w =
|
|
XCreateSimpleWindow (dpy, vs->wsw->w,
|
|
Dummy /* x */, Dummy /* y */,
|
|
Dummy /* width */, Dummy /* height */,
|
|
0, Scr->Black, ws->cp.back);
|
|
|
|
mapsw = msw->w =
|
|
XCreateSimpleWindow (dpy, vs->wsw->w,
|
|
Dummy /* x */, Dummy /* y */,
|
|
Dummy /* width */, Dummy /* height */,
|
|
1, border, ws->cp.back);
|
|
|
|
if (vs->wsw->state == BUTTONSSTATE)
|
|
XMapWindow (dpy, butsw);
|
|
else
|
|
XMapWindow (dpy, mapsw);
|
|
|
|
vs->wsw->mswl [ws->number]->wl = NULL;
|
|
if (useBackgroundInfo) {
|
|
if (ws->image == None || Scr->NoImagesInWorkSpaceManager)
|
|
XSetWindowBackground (dpy, mapsw, ws->backcp.back);
|
|
else
|
|
XSetWindowBackgroundPixmap (dpy, mapsw, ws->image->pixmap);
|
|
}
|
|
else {
|
|
if (Scr->workSpaceMgr.defImage == None || Scr->NoImagesInWorkSpaceManager)
|
|
XSetWindowBackground (dpy, mapsw, Scr->workSpaceMgr.defColors.back);
|
|
else
|
|
XSetWindowBackgroundPixmap (dpy, mapsw, Scr->workSpaceMgr.defImage->pixmap);
|
|
}
|
|
XClearWindow (dpy, butsw);
|
|
i++;
|
|
if (i == columns) {i = 0; j++;};
|
|
}
|
|
|
|
sizehints.flags = USPosition | PBaseSize | PMinSize | PResizeInc | PWinGravity;
|
|
sizehints.x = x;
|
|
sizehints.y = y;
|
|
sizehints.base_width = columns * hspace;
|
|
sizehints.base_height = lines * vspace;
|
|
sizehints.width_inc = columns;
|
|
sizehints.height_inc = lines;
|
|
sizehints.min_width = columns * (hspace + 2);
|
|
sizehints.min_height = lines * (vspace + 2);
|
|
sizehints.win_gravity = gravity;
|
|
|
|
XSetStandardProperties (dpy, vs->wsw->w,
|
|
name, icon_name, None, NULL, 0, NULL);
|
|
XSetWMSizeHints (dpy, vs->wsw->w, &sizehints, XA_WM_NORMAL_HINTS);
|
|
|
|
wmhints.flags = InputHint | StateHint;
|
|
wmhints.input = True;
|
|
wmhints.initial_state = NormalState;
|
|
XSetWMHints (dpy, vs->wsw->w, &wmhints);
|
|
XSaveContext (dpy, vs->wsw->w, VirtScreenContext, (XPointer) vs);
|
|
tmp_win = AddWindow (vs->wsw->w, 3, Scr->iconmgr);
|
|
if (! tmp_win) {
|
|
fprintf (stderr, "cannot create workspace manager window, exiting...\n");
|
|
exit (1);
|
|
}
|
|
tmp_win->occupation = fullOccupation;
|
|
tmp_win->vs = vs;
|
|
tmp_win->attr.width = width;
|
|
tmp_win->attr.height = height;
|
|
ResizeWorkSpaceManager(vs, tmp_win);
|
|
|
|
attrmask = 0;
|
|
attr.cursor = Scr->ButtonCursor;
|
|
attrmask |= CWCursor;
|
|
attr.win_gravity = gravity;
|
|
attrmask |= CWWinGravity;
|
|
XChangeWindowAttributes (dpy, vs->wsw->w, attrmask, &attr);
|
|
|
|
XGetWindowAttributes (dpy, vs->wsw->w, &wattr);
|
|
attrmask = wattr.your_event_mask | KeyPressMask | KeyReleaseMask | ExposureMask;
|
|
XSelectInput (dpy, vs->wsw->w, attrmask);
|
|
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
Window buttonw = vs->wsw->bswl [ws->number]->w;
|
|
Window mapsubw = vs->wsw->mswl [ws->number]->w;
|
|
XSelectInput (dpy, buttonw, ButtonPressMask | ButtonReleaseMask | ExposureMask);
|
|
XSaveContext (dpy, buttonw, TwmContext, (XPointer) tmp_win);
|
|
XSaveContext (dpy, buttonw, ScreenContext, (XPointer) Scr);
|
|
|
|
XSelectInput (dpy, mapsubw, ButtonPressMask | ButtonReleaseMask);
|
|
XSaveContext (dpy, mapsubw, TwmContext, (XPointer) tmp_win);
|
|
XSaveContext (dpy, mapsubw, ScreenContext, (XPointer) Scr);
|
|
}
|
|
SetMapStateProp (tmp_win, WithdrawnState);
|
|
vs->wsw->twm_win = tmp_win;
|
|
|
|
ws = Scr->workSpaceMgr.workSpaceList;
|
|
if (useBackgroundInfo && ! Scr->DontPaintRootWindow) {
|
|
if (ws->image == None)
|
|
XSetWindowBackground (dpy, Scr->Root, ws->backcp.back);
|
|
else
|
|
XSetWindowBackgroundPixmap (dpy, Scr->Root, ws->image->pixmap);
|
|
XClearWindow (dpy, Scr->Root);
|
|
}
|
|
PaintWorkSpaceManager (vs);
|
|
}
|
|
|
|
void WMgrHandleExposeEvent (virtualScreen *vs, XEvent *event)
|
|
{
|
|
WorkSpace *ws;
|
|
Window buttonw;
|
|
|
|
if (vs->wsw->state == BUTTONSSTATE) {
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
buttonw = vs->wsw->bswl [ws->number]->w;
|
|
if (event->xexpose.window == buttonw) break;
|
|
}
|
|
if (ws == NULL) {
|
|
PaintWorkSpaceManagerBorder (vs);
|
|
}
|
|
else
|
|
if (ws == vs->wsw->currentwspc)
|
|
PaintButton (WSPCWINDOW, vs, buttonw, ws->label, ws->cp, on);
|
|
else
|
|
PaintButton (WSPCWINDOW, vs, buttonw, ws->label, ws->cp, off);
|
|
}
|
|
else {
|
|
WinList wl;
|
|
|
|
if (XFindContext (dpy, event->xexpose.window, MapWListContext,
|
|
(XPointer *) &wl) == XCNOENT) return;
|
|
if (wl && wl->twm_win && wl->twm_win->mapped) {
|
|
WMapRedrawName (vs, wl);
|
|
}
|
|
}
|
|
}
|
|
|
|
void PaintWorkSpaceManager (virtualScreen *vs)
|
|
{
|
|
WorkSpace *ws;
|
|
|
|
PaintWorkSpaceManagerBorder (vs);
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
Window buttonw = vs->wsw->bswl [ws->number]->w;
|
|
if (ws == vs->wsw->currentwspc)
|
|
PaintButton (WSPCWINDOW, vs, buttonw, ws->label, ws->cp, on);
|
|
else
|
|
PaintButton (WSPCWINDOW, vs, buttonw, ws->label, ws->cp, off);
|
|
}
|
|
}
|
|
|
|
static void PaintWorkSpaceManagerBorder (virtualScreen *vs)
|
|
{
|
|
int width, height;
|
|
|
|
width = vs->wsw->width;
|
|
height = vs->wsw->height;
|
|
Draw3DBorder (vs->wsw->w, 0, 0, width, height, 2, Scr->workSpaceMgr.cp, off, True, False);
|
|
}
|
|
|
|
ColorPair occupyButtoncp;
|
|
|
|
char *ok_string = "OK",
|
|
*cancel_string = "Cancel",
|
|
*everywhere_string = "All";
|
|
|
|
/*
|
|
* Create the Occupy window. Do not do the layout of the parts, only
|
|
* calculate the inial total size. For the layout, call ResizeOccupyWindow()
|
|
* at the end.
|
|
* There is only one Occupy window (per Screen), it is reparented to each
|
|
* virtual screen as needed.
|
|
*/
|
|
static void CreateOccupyWindow (void) {
|
|
int width, height, lines, columns;
|
|
int bwidth, bheight, owidth, oheight, hspace, vspace;
|
|
int min_bwidth, min_width;
|
|
int i, j;
|
|
Window w, OK, cancel, allworkspc;
|
|
char *name, *icon_name;
|
|
ColorPair cp;
|
|
TwmWindow *tmp_win;
|
|
WorkSpace *ws;
|
|
XSizeHints sizehints;
|
|
XWMHints wmhints;
|
|
MyFont font;
|
|
XSetWindowAttributes attr;
|
|
XWindowAttributes wattr;
|
|
unsigned long attrmask;
|
|
OccupyWindow *occwin;
|
|
virtualScreen *vs;
|
|
XRectangle inc_rect;
|
|
XRectangle logical_rect;
|
|
|
|
occwin = Scr->workSpaceMgr.occupyWindow;
|
|
occwin->font = Scr->IconManagerFont;
|
|
occwin->cp = Scr->IconManagerC;
|
|
#ifdef COLOR_BLIND_USER
|
|
occwin->cp.shadc = Scr->White;
|
|
occwin->cp.shadd = Scr->Black;
|
|
#else
|
|
if (!Scr->BeNiceToColormap) GetShadeColors (&occwin->cp);
|
|
#endif
|
|
vs = Scr->vScreenList;
|
|
name = occwin->name;
|
|
icon_name = occwin->icon_name;
|
|
lines = Scr->workSpaceMgr.lines;
|
|
columns = Scr->workSpaceMgr.columns;
|
|
bwidth = vs->wsw->bwidth;
|
|
bheight = vs->wsw->bheight;
|
|
oheight = bheight;
|
|
vspace = occwin->vspace;
|
|
hspace = occwin->hspace;
|
|
cp = occwin->cp;
|
|
height = ((bheight + vspace) * lines) + oheight + (2 * vspace);
|
|
font = occwin->font;
|
|
XmbTextExtents(font.font_set, ok_string, strlen(ok_string),
|
|
&inc_rect, &logical_rect);
|
|
min_bwidth = logical_rect.width;
|
|
XmbTextExtents(font.font_set, cancel_string, strlen (cancel_string),
|
|
&inc_rect, &logical_rect);
|
|
i = logical_rect.width;
|
|
if (i > min_bwidth) min_bwidth = i;
|
|
XmbTextExtents(font.font_set,everywhere_string, strlen (everywhere_string),
|
|
&inc_rect, &logical_rect);
|
|
i = logical_rect.width;
|
|
if (i > min_bwidth) min_bwidth = i;
|
|
min_bwidth = (min_bwidth + hspace); /* normal width calculation */
|
|
width = columns * (bwidth + hspace);
|
|
min_width = 3 * (min_bwidth + hspace); /* width by text width */
|
|
|
|
if (columns < 3) {
|
|
owidth = min_bwidth + 2 * Scr->WMgrButtonShadowDepth + 2;
|
|
if (width < min_width) width = min_width;
|
|
bwidth = (width - columns * hspace) / columns;
|
|
}
|
|
else {
|
|
owidth = min_bwidth + 2 * Scr->WMgrButtonShadowDepth + 2;
|
|
width = columns * (bwidth + hspace);
|
|
}
|
|
occwin->lines = lines;
|
|
occwin->columns = columns;
|
|
occwin->owidth = owidth;
|
|
|
|
w = occwin->w = XCreateSimpleWindow (dpy, Scr->Root, 0, 0, width, height,
|
|
1, Scr->Black, cp.back);
|
|
occwin->obuttonw = (Window*) malloc (Scr->workSpaceMgr.count * sizeof (Window));
|
|
i = 0; j = 0;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
Window bw =
|
|
occwin->obuttonw [j * columns + i] =
|
|
XCreateSimpleWindow(dpy, w,
|
|
Dummy /* x */,
|
|
Dummy /* y */,
|
|
Dummy /* width */,
|
|
Dummy /* height */,
|
|
0, Scr->Black, ws->cp.back);
|
|
XMapWindow (dpy, bw);
|
|
i++;
|
|
if (i == columns) {i = 0; j++;}
|
|
}
|
|
GetColor (Scr->Monochrome, &(occupyButtoncp.back), "gray50");
|
|
occupyButtoncp.fore = Scr->White;
|
|
if (!Scr->BeNiceToColormap) GetShadeColors (&occupyButtoncp);
|
|
|
|
OK = XCreateSimpleWindow (dpy, w, Dummy, Dummy, Dummy, Dummy, 0,
|
|
Scr->Black, occupyButtoncp.back);
|
|
XMapWindow (dpy, OK);
|
|
cancel = XCreateSimpleWindow (dpy, w, Dummy, Dummy, Dummy, Dummy, 0,
|
|
Scr->Black, occupyButtoncp.back);
|
|
XMapWindow (dpy, cancel);
|
|
allworkspc = XCreateSimpleWindow (dpy, w, Dummy, Dummy, Dummy, Dummy, 0,
|
|
Scr->Black, occupyButtoncp.back);
|
|
XMapWindow (dpy, allworkspc);
|
|
|
|
occwin->OK = OK;
|
|
occwin->cancel = cancel;
|
|
occwin->allworkspc = allworkspc;
|
|
|
|
sizehints.flags = PBaseSize | PMinSize | PResizeInc;
|
|
sizehints.base_width = columns;
|
|
sizehints.base_height = lines;
|
|
sizehints.width_inc = columns;
|
|
sizehints.height_inc = lines;
|
|
sizehints.min_width = 2 * columns;
|
|
sizehints.min_height = 2 * lines;
|
|
XSetStandardProperties (dpy, w, name, icon_name, None, NULL, 0, &sizehints);
|
|
|
|
wmhints.flags = InputHint | StateHint;
|
|
wmhints.input = True;
|
|
wmhints.initial_state = NormalState;
|
|
XSetWMHints (dpy, w, &wmhints);
|
|
tmp_win = AddWindow (w, FALSE, Scr->iconmgr);
|
|
if (! tmp_win) {
|
|
fprintf (stderr, "cannot create occupy window, exiting...\n");
|
|
exit (1);
|
|
}
|
|
tmp_win->vs = None;
|
|
tmp_win->occupation = 0;
|
|
|
|
attrmask = 0;
|
|
attr.cursor = Scr->ButtonCursor;
|
|
attrmask |= CWCursor;
|
|
XChangeWindowAttributes (dpy, w, attrmask, &attr);
|
|
|
|
XGetWindowAttributes (dpy, w, &wattr);
|
|
attrmask = wattr.your_event_mask | KeyPressMask | KeyReleaseMask | ExposureMask;
|
|
XSelectInput (dpy, w, attrmask);
|
|
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
Window bw = occwin->obuttonw [ws->number];
|
|
XSelectInput (dpy, bw, ButtonPressMask | ButtonReleaseMask | ExposureMask);
|
|
XSaveContext (dpy, bw, TwmContext, (XPointer) tmp_win);
|
|
XSaveContext (dpy, bw, ScreenContext, (XPointer) Scr);
|
|
}
|
|
XSelectInput (dpy, occwin->OK, ButtonPressMask | ButtonReleaseMask | ExposureMask);
|
|
XSaveContext (dpy, occwin->OK, TwmContext, (XPointer) tmp_win);
|
|
XSaveContext (dpy, occwin->OK, ScreenContext, (XPointer) Scr);
|
|
XSelectInput (dpy, occwin->cancel, ButtonPressMask | ButtonReleaseMask | ExposureMask);
|
|
XSaveContext (dpy, occwin->cancel, TwmContext, (XPointer) tmp_win);
|
|
XSaveContext (dpy, occwin->cancel, ScreenContext, (XPointer) Scr);
|
|
XSelectInput (dpy, occwin->allworkspc, ButtonPressMask | ButtonReleaseMask | ExposureMask);
|
|
XSaveContext (dpy, occwin->allworkspc, TwmContext, (XPointer) tmp_win);
|
|
XSaveContext (dpy, occwin->allworkspc, ScreenContext, (XPointer) Scr);
|
|
|
|
SetMapStateProp (tmp_win, WithdrawnState);
|
|
occwin->twm_win = tmp_win;
|
|
Scr->workSpaceMgr.occupyWindow = occwin;
|
|
|
|
tmp_win->attr.width = width;
|
|
tmp_win->attr.height = height;
|
|
ResizeOccupyWindow(tmp_win); /* place all parts in the right place */
|
|
}
|
|
|
|
void PaintOccupyWindow (void)
|
|
{
|
|
WorkSpace *ws;
|
|
OccupyWindow *occwin;
|
|
int width, height;
|
|
|
|
occwin = Scr->workSpaceMgr.occupyWindow;
|
|
width = occwin->width;
|
|
height = occwin->height;
|
|
|
|
Draw3DBorder (occwin->w, 0, 0, width, height, 2, occwin->cp, off, True, False);
|
|
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
Window bw = occwin->obuttonw [ws->number];
|
|
if (occwin->tmpOccupation & (1 << ws->number))
|
|
PaintButton (OCCUPYWINDOW, NULL, bw, ws->label, ws->cp, on);
|
|
else
|
|
PaintButton (OCCUPYWINDOW, NULL, bw, ws->label, ws->cp, off);
|
|
}
|
|
PaintButton (OCCUPYBUTTON, NULL, occwin->OK, ok_string, occupyButtoncp, off);
|
|
PaintButton (OCCUPYBUTTON, NULL, occwin->cancel, cancel_string, occupyButtoncp, off);
|
|
PaintButton (OCCUPYBUTTON, NULL, occwin->allworkspc, everywhere_string, occupyButtoncp, off);
|
|
}
|
|
|
|
static void PaintButton (int which,
|
|
virtualScreen *vs, Window w,
|
|
char *label,
|
|
ColorPair cp, int state)
|
|
{
|
|
OccupyWindow *occwin;
|
|
int bwidth, bheight;
|
|
MyFont font;
|
|
int strWid, strHei, hspace, vspace;
|
|
XRectangle inc_rect;
|
|
XRectangle logical_rect;
|
|
|
|
occwin = Scr->workSpaceMgr.occupyWindow;
|
|
if (which == WSPCWINDOW) {
|
|
bwidth = vs->wsw->bwidth;
|
|
bheight = vs->wsw->bheight;
|
|
font = Scr->workSpaceMgr.buttonFont;
|
|
}
|
|
else
|
|
if (which == OCCUPYWINDOW) {
|
|
bwidth = occwin->bwidth;
|
|
bheight = occwin->bheight;
|
|
font = occwin->font;
|
|
}
|
|
else
|
|
if (which == OCCUPYBUTTON) {
|
|
bwidth = occwin->owidth;
|
|
bheight = occwin->bheight;
|
|
font = occwin->font;
|
|
}
|
|
else return;
|
|
|
|
XmbTextExtents(font.font_set, label, strlen (label), &inc_rect, &logical_rect);
|
|
strHei = logical_rect.height;
|
|
vspace = ((bheight + strHei - font.descent) / 2);
|
|
strWid = logical_rect.width;
|
|
hspace = (bwidth - strWid) / 2;
|
|
if (hspace < (Scr->WMgrButtonShadowDepth + 1)) hspace = Scr->WMgrButtonShadowDepth + 1;
|
|
XClearWindow (dpy, w);
|
|
|
|
if (Scr->Monochrome == COLOR) {
|
|
Draw3DBorder (w, 0, 0, bwidth, bheight, Scr->WMgrButtonShadowDepth,
|
|
cp, state, True, False);
|
|
|
|
switch (Scr->workSpaceMgr.buttonStyle) {
|
|
case STYLE_NORMAL :
|
|
break;
|
|
|
|
case STYLE_STYLE1 :
|
|
Draw3DBorder (w,
|
|
Scr->WMgrButtonShadowDepth - 1,
|
|
Scr->WMgrButtonShadowDepth - 1,
|
|
bwidth - 2 * Scr->WMgrButtonShadowDepth + 2,
|
|
bheight - 2 * Scr->WMgrButtonShadowDepth + 2,
|
|
1, cp, (state == on) ? off : on, True, False);
|
|
break;
|
|
|
|
case STYLE_STYLE2 :
|
|
Draw3DBorder (w,
|
|
Scr->WMgrButtonShadowDepth / 2,
|
|
Scr->WMgrButtonShadowDepth / 2,
|
|
bwidth - Scr->WMgrButtonShadowDepth,
|
|
bheight - Scr->WMgrButtonShadowDepth,
|
|
1, cp, (state == on) ? off : on, True, False);
|
|
break;
|
|
|
|
case STYLE_STYLE3 :
|
|
Draw3DBorder (w,
|
|
1,
|
|
1,
|
|
bwidth - 2,
|
|
bheight - 2,
|
|
1, cp, (state == on) ? off : on, True, False);
|
|
break;
|
|
}
|
|
FB (cp.fore, cp.back);
|
|
XmbDrawString (dpy, w, font.font_set, Scr->NormalGC, hspace, vspace,
|
|
label, strlen (label));
|
|
}
|
|
else {
|
|
Draw3DBorder (w, 0, 0, bwidth, bheight, Scr->WMgrButtonShadowDepth,
|
|
cp, state, True, False);
|
|
if (state == on) {
|
|
FB (cp.fore, cp.back);
|
|
XmbDrawImageString (dpy, w, font.font_set, Scr->NormalGC, hspace, vspace,
|
|
label, strlen (label));
|
|
}
|
|
else {
|
|
FB (cp.back, cp.fore);
|
|
XmbDrawImageString (dpy, w, font.font_set, Scr->NormalGC, hspace, vspace,
|
|
label, strlen (label));
|
|
}
|
|
}
|
|
}
|
|
|
|
static unsigned int GetMaskFromResource (TwmWindow *win, char *res)
|
|
{
|
|
char *name;
|
|
char wrkSpcName [64];
|
|
WorkSpace *ws;
|
|
int mask, num, mode;
|
|
|
|
mode = 0;
|
|
if (*res == '+') {
|
|
mode = 1;
|
|
res++;
|
|
}
|
|
else
|
|
if (*res == '-') {
|
|
mode = 2;
|
|
res++;
|
|
}
|
|
mask = 0;
|
|
while (*res != '\0') {
|
|
while (*res == ' ') res++;
|
|
if (*res == '\0') break;
|
|
name = wrkSpcName;
|
|
while ((*res != '\0') && (*res != ' ')) {
|
|
if (*res == '\\') res++;
|
|
*name = *res;
|
|
name++; res++;
|
|
}
|
|
*name = '\0';
|
|
if (strcmp (wrkSpcName, "all") == 0) {
|
|
mask = fullOccupation;
|
|
break;
|
|
}
|
|
if (strcmp (wrkSpcName, "current") == 0) {
|
|
virtualScreen *vs = Scr->currentvs;
|
|
if (vs) mask |= (1 << vs->wsw->currentwspc->number);
|
|
continue;
|
|
}
|
|
num = 0;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (strcmp (wrkSpcName, ws->label) == 0) break;
|
|
num++;
|
|
}
|
|
if (ws != NULL) mask |= (1 << num);
|
|
else {
|
|
twmrc_error_prefix ();
|
|
fprintf (stderr, "unknown workspace : %s\n", wrkSpcName);
|
|
}
|
|
}
|
|
switch (mode) {
|
|
case 0 :
|
|
return (mask);
|
|
case 1 :
|
|
return (mask | win->occupation);
|
|
case 2 :
|
|
return (win->occupation & ~mask);
|
|
}
|
|
return (0); /* Never supposed to reach here, but just
|
|
in case... */
|
|
}
|
|
|
|
unsigned int GetMaskFromProperty (unsigned char *prop, unsigned long len)
|
|
{
|
|
char wrkSpcName [256];
|
|
WorkSpace *ws;
|
|
unsigned int mask;
|
|
int num, l;
|
|
|
|
mask = 0;
|
|
l = 0;
|
|
while (l < len) {
|
|
strcpy (wrkSpcName, (char *)prop);
|
|
l += strlen ((char *)prop) + 1;
|
|
prop += strlen ((char *)prop) + 1;
|
|
if (strcmp (wrkSpcName, "all") == 0) {
|
|
mask = fullOccupation;
|
|
break;
|
|
}
|
|
num = 0;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (strcmp (wrkSpcName, ws->label) == 0) break;
|
|
num++;
|
|
}
|
|
if (ws == NULL) {
|
|
fprintf (stderr, "unknown workspace : %s\n", wrkSpcName);
|
|
}
|
|
else {
|
|
mask |= (1 << num);
|
|
}
|
|
}
|
|
return (mask);
|
|
}
|
|
|
|
static int GetPropertyFromMask (unsigned int mask, char *prop, long *gwkspc)
|
|
{
|
|
WorkSpace *ws;
|
|
int len;
|
|
char *p;
|
|
|
|
if (mask == fullOccupation) {
|
|
strcpy (prop, "all");
|
|
return (3);
|
|
}
|
|
len = 0;
|
|
p = prop;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (mask & (1 << ws->number)) {
|
|
strcpy (p, ws->label);
|
|
p += strlen (ws->label) + 1;
|
|
len += strlen (ws->label) + 1;
|
|
*gwkspc = ws->number;
|
|
}
|
|
}
|
|
return (len);
|
|
}
|
|
|
|
void AddToClientsList (char *workspace, char *client)
|
|
{
|
|
WorkSpace *ws;
|
|
|
|
if (strcmp (workspace, "all") == 0) {
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
AddToList (&ws->clientlist, client, "");
|
|
}
|
|
return;
|
|
}
|
|
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (strcmp (ws->label, workspace) == 0) break;
|
|
}
|
|
if (ws == NULL) return;
|
|
AddToList (&ws->clientlist, client, "");
|
|
}
|
|
|
|
void WMapToggleState (virtualScreen *vs)
|
|
{
|
|
if (vs->wsw->state == BUTTONSSTATE) {
|
|
WMapSetMapState (vs);
|
|
} else {
|
|
WMapSetButtonsState (vs);
|
|
}
|
|
}
|
|
|
|
void WMapSetMapState (virtualScreen *vs)
|
|
{
|
|
WorkSpace *ws;
|
|
|
|
if (vs->wsw->state == MAPSTATE) return;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
XUnmapWindow (dpy, vs->wsw->bswl [ws->number]->w);
|
|
XMapWindow (dpy, vs->wsw->mswl [ws->number]->w);
|
|
}
|
|
vs->wsw->state = MAPSTATE;
|
|
MaybeAnimate = True;
|
|
}
|
|
|
|
void WMapSetButtonsState (virtualScreen *vs)
|
|
{
|
|
WorkSpace *ws;
|
|
|
|
if (vs->wsw->state == BUTTONSSTATE) return;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
XUnmapWindow (dpy, vs->wsw->mswl [ws->number]->w);
|
|
XMapWindow (dpy, vs->wsw->bswl [ws->number]->w);
|
|
}
|
|
vs->wsw->state = BUTTONSSTATE;
|
|
}
|
|
|
|
/*
|
|
* Verify if a window may be added to the workspace map.
|
|
* This is not allowed for
|
|
* - icon managers
|
|
* - the occupy window
|
|
* - workspace manager windows
|
|
* - or, optionally, windows with full occupation.
|
|
*/
|
|
int WMapWindowMayBeAdded(TwmWindow *win)
|
|
{
|
|
if (win->iconmgr)
|
|
return 0;
|
|
if (win == Scr->workSpaceMgr.occupyWindow->twm_win)
|
|
return 0;
|
|
if (win->wspmgr)
|
|
return 0;
|
|
if (Scr->workSpaceMgr.noshowoccupyall &&
|
|
win->occupation == fullOccupation)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
void WMapAddWindow (TwmWindow *win)
|
|
{
|
|
WorkSpace *ws;
|
|
|
|
if (!WMapWindowMayBeAdded(win))
|
|
return;
|
|
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (OCCUPY (win, ws)) WMapAddToList (win, ws);
|
|
}
|
|
}
|
|
|
|
void WMapDestroyWindow (TwmWindow *win)
|
|
{
|
|
WorkSpace *ws;
|
|
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (OCCUPY (win, ws)) WMapRemoveFromList (win, ws);
|
|
}
|
|
if (win == occupyWin) {
|
|
OccupyWindow *occwin = Scr->workSpaceMgr.occupyWindow;
|
|
XUnmapWindow (dpy, occwin->twm_win->frame);
|
|
occwin->twm_win->mapped = FALSE;
|
|
occwin->twm_win->occupation = 0;
|
|
occupyWin = (TwmWindow*) 0;
|
|
}
|
|
}
|
|
|
|
void WMapMapWindow (TwmWindow *win)
|
|
{
|
|
virtualScreen *vs;
|
|
WorkSpace *ws;
|
|
WinList wl;
|
|
|
|
for (vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
for (wl = vs->wsw->mswl [ws->number]->wl; wl != NULL; wl = wl->next) {
|
|
if (wl->twm_win == win) {
|
|
XMapWindow (dpy, wl->w);
|
|
WMapRedrawName (vs, wl);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void WMapSetupWindow (TwmWindow *win, int x, int y, int w, int h)
|
|
{
|
|
virtualScreen *vs;
|
|
WorkSpace *ws;
|
|
WinList wl;
|
|
float wf, hf;
|
|
|
|
if (win->iconmgr) return;
|
|
if (!win->vs) return;
|
|
|
|
if (win->wspmgr) {
|
|
if (w == -1) return;
|
|
ResizeWorkSpaceManager (win->vs, win);
|
|
return;
|
|
}
|
|
if (win == Scr->workSpaceMgr.occupyWindow->twm_win) {
|
|
if (w == -1) return;
|
|
ResizeOccupyWindow (win);
|
|
return;
|
|
}
|
|
for (vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
|
|
WorkSpaceWindow *wsw = vs->wsw;
|
|
wf = (float) (wsw->wwidth - 2) / (float) vs->w;
|
|
hf = (float) (wsw->wheight - 2) / (float) vs->h;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
for (wl = wsw->mswl [ws->number]->wl; wl != NULL; wl = wl->next) {
|
|
if (win == wl->twm_win) {
|
|
wl->x = (int) (x * wf);
|
|
wl->y = (int) (y * hf);
|
|
if (w == -1) {
|
|
XMoveWindow (dpy, wl->w, wl->x, wl->y);
|
|
}
|
|
else {
|
|
wl->width = (unsigned int) ((w * wf) + 0.5);
|
|
wl->height = (unsigned int) ((h * hf) + 0.5);
|
|
if (!Scr->use3Dwmap) {
|
|
wl->width -= 2;
|
|
wl->height -= 2;
|
|
}
|
|
if (wl->width < 1) wl->width = 1;
|
|
if (wl->height < 1) wl->height = 1;
|
|
XMoveResizeWindow (dpy, wl->w, wl->x, wl->y, wl->width, wl->height);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void WMapIconify (TwmWindow *win)
|
|
{
|
|
WorkSpace *ws;
|
|
WinList wl;
|
|
|
|
if (!win->vs) return;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
for (wl = win->vs->wsw->mswl [ws->number]->wl; wl != NULL; wl = wl->next) {
|
|
if (win == wl->twm_win) {
|
|
XUnmapWindow (dpy, wl->w);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void WMapDeIconify (TwmWindow *win)
|
|
{
|
|
WorkSpace *ws;
|
|
WinList wl;
|
|
|
|
if (!win->vs) return;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
for (wl = win->vs->wsw->mswl [ws->number]->wl; wl != NULL; wl = wl->next) {
|
|
if (win == wl->twm_win) {
|
|
if (Scr->NoRaiseDeicon)
|
|
XMapWindow (dpy, wl->w);
|
|
else
|
|
XMapRaised (dpy, wl->w);
|
|
WMapRedrawName (win->vs, wl);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void WMapRaiseLower (TwmWindow *win)
|
|
{
|
|
WorkSpace *ws;
|
|
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (OCCUPY (win, ws)) WMapRestack (ws);
|
|
}
|
|
}
|
|
|
|
void WMapLower (TwmWindow *win)
|
|
{
|
|
WorkSpace *ws;
|
|
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (OCCUPY (win, ws)) WMapRestack (ws);
|
|
}
|
|
}
|
|
|
|
void WMapRaise (TwmWindow *win)
|
|
{
|
|
WorkSpace *ws;
|
|
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (OCCUPY (win, ws)) WMapRestack (ws);
|
|
}
|
|
}
|
|
|
|
void WMapRestack (WorkSpace *ws)
|
|
{
|
|
virtualScreen *vs;
|
|
TwmWindow *win;
|
|
WinList wl;
|
|
Window root;
|
|
Window parent;
|
|
Window *children, *smallws;
|
|
unsigned int number;
|
|
int i, j;
|
|
|
|
number = 0;
|
|
XQueryTree (dpy, Scr->Root, &root, &parent, &children, &number);
|
|
smallws = (Window*) malloc (number * sizeof (Window));
|
|
|
|
for (vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
|
|
j = 0;
|
|
for (i = number - 1; i >= 0; i--) {
|
|
if (!(win = GetTwmWindow(children [i]))) {
|
|
continue;
|
|
}
|
|
if (win->frame != children [i]) continue; /* skip icons */
|
|
if (! OCCUPY (win, ws)) continue;
|
|
if (tracefile) {
|
|
fprintf (tracefile, "WMapRestack : w = %lx, win = %p\n", children [i], (void *)win);
|
|
fflush (tracefile);
|
|
}
|
|
for (wl = vs->wsw->mswl [ws->number]->wl; wl != NULL; wl = wl->next) {
|
|
if (tracefile) {
|
|
fprintf (tracefile, "WMapRestack : wl = %p, twm_win = %p\n", (void *)wl, (void *)wl->twm_win);
|
|
fflush (tracefile);
|
|
}
|
|
if (win == wl->twm_win) {
|
|
smallws [j++] = wl->w;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
XRestackWindows (dpy, smallws, j);
|
|
}
|
|
XFree ((char *) children);
|
|
free (smallws);
|
|
return;
|
|
}
|
|
|
|
void WMapUpdateIconName (TwmWindow *win)
|
|
{
|
|
virtualScreen *vs;
|
|
WorkSpace *ws;
|
|
WinList wl;
|
|
|
|
for (vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
for (wl = vs->wsw->mswl [ws->number]->wl; wl != NULL; wl = wl->next) {
|
|
if (win == wl->twm_win) {
|
|
WMapRedrawName (vs, wl);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void WMgrHandleKeyReleaseEvent (virtualScreen *vs, XEvent *event)
|
|
{
|
|
char *keyname;
|
|
KeySym keysym;
|
|
|
|
keysym = XLookupKeysym ((XKeyEvent*) event, 0);
|
|
if (! keysym) return;
|
|
keyname = XKeysymToString (keysym);
|
|
if (! keyname) return;
|
|
if ((strcmp (keyname, "Control_R") == 0) ||
|
|
(strcmp (keyname, "Control_L") == 0))
|
|
{
|
|
/* DontToggleWorkSpaceManagerState added 20040607 by dl*/
|
|
if (!donttoggleworkspacemanagerstate)
|
|
{
|
|
WMapToggleState (vs);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
void WMgrHandleKeyPressEvent (virtualScreen *vs, XEvent *event)
|
|
{
|
|
WorkSpace *ws;
|
|
int len, i, lname;
|
|
char key [16];
|
|
unsigned char k;
|
|
char name [128];
|
|
char *keyname;
|
|
KeySym keysym;
|
|
|
|
keysym = XLookupKeysym ((XKeyEvent*) event, 0);
|
|
if (! keysym) return;
|
|
keyname = XKeysymToString (keysym);
|
|
if (! keyname) return;
|
|
if ((strcmp (keyname, "Control_R") == 0) ||
|
|
(strcmp (keyname, "Control_L") == 0))
|
|
{
|
|
/* DontToggleWorkSpaceManagerState added 20040607 by dl*/
|
|
if (!donttoggleworkspacemanagerstate)
|
|
{
|
|
WMapToggleState (vs);
|
|
}
|
|
return;
|
|
}
|
|
if (vs->wsw->state == MAPSTATE) return;
|
|
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (vs->wsw->bswl [ws->number]->w == event->xkey.subwindow) break;
|
|
}
|
|
if (ws == NULL) return;
|
|
|
|
strcpy (name, ws->label);
|
|
lname = strlen (name);
|
|
len = XLookupString (&(event->xkey), key, 16, NULL, NULL);
|
|
for (i = 0; i < len; i++) {
|
|
k = key [i];
|
|
if (isprint (k)) {
|
|
name [lname++] = k;
|
|
}
|
|
else
|
|
if ((k == 127) || (k == 8)) {
|
|
if (lname != 0) lname--;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
name [lname] = '\0';
|
|
ws->label = realloc (ws->label, (strlen (name) + 1));
|
|
strcpy (ws->label, name);
|
|
if (ws == vs->wsw->currentwspc)
|
|
PaintButton (WSPCWINDOW, vs, vs->wsw->bswl [ws->number]->w, ws->label, ws->cp, on);
|
|
else
|
|
PaintButton (WSPCWINDOW, vs, vs->wsw->bswl [ws->number]->w, ws->label, ws->cp, off);
|
|
}
|
|
|
|
void WMgrHandleButtonEvent (virtualScreen *vs, XEvent *event)
|
|
{
|
|
WorkSpaceWindow *mw;
|
|
WorkSpace *ws, *oldws, *newws, *cws;
|
|
WinList wl;
|
|
TwmWindow *win;
|
|
int occupation;
|
|
unsigned int W0, H0, bw;
|
|
int cont;
|
|
XEvent ev;
|
|
Window w, sw, parent;
|
|
int X0, Y0, X1, Y1, XW, YW, XSW, YSW;
|
|
Position newX = 0, newY = 0, winX = 0, winY = 0;
|
|
Window junkW;
|
|
unsigned int junk;
|
|
unsigned int button;
|
|
unsigned int modifier;
|
|
XSetWindowAttributes attrs;
|
|
float wf, hf;
|
|
Boolean alreadyvivible, realmovemode, startincurrent;
|
|
Time etime;
|
|
|
|
parent = event->xbutton.window;
|
|
sw = event->xbutton.subwindow;
|
|
mw = vs->wsw;
|
|
button = event->xbutton.button;
|
|
modifier = event->xbutton.state;
|
|
etime = event->xbutton.time;
|
|
|
|
if (vs->wsw->state == BUTTONSSTATE) {
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (vs->wsw->bswl [ws->number]->w == parent) break;
|
|
}
|
|
if (ws == NULL) return;
|
|
GotoWorkSpace (vs, ws);
|
|
return;
|
|
}
|
|
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
if (vs->wsw->mswl [ws->number]->w == parent) break;
|
|
}
|
|
if (ws == NULL) return;
|
|
if (sw == (Window) 0) {
|
|
GotoWorkSpace (vs, ws);
|
|
return;
|
|
}
|
|
oldws = ws;
|
|
|
|
if (XFindContext (dpy, sw, MapWListContext, (XPointer *) &wl) == XCNOENT) return;
|
|
win = wl->twm_win;
|
|
if ((! Scr->TransientHasOccupation) && win->transient) return;
|
|
|
|
XTranslateCoordinates (dpy, Scr->Root, sw, event->xbutton.x_root, event->xbutton.y_root,
|
|
&XW, &YW, &junkW);
|
|
realmovemode = ( Scr->ReallyMoveInWorkspaceManager && !(modifier & ShiftMask)) ||
|
|
(!Scr->ReallyMoveInWorkspaceManager && (modifier & ShiftMask));
|
|
startincurrent = (oldws == vs->wsw->currentwspc);
|
|
if (win->OpaqueMove) {
|
|
int sw2, ss;
|
|
|
|
sw2 = win->frame_width * win->frame_height;
|
|
ss = vs->w * vs->h;
|
|
if (sw2 > ((ss * Scr->OpaqueMoveThreshold) / 100))
|
|
Scr->OpaqueMove = FALSE;
|
|
else
|
|
Scr->OpaqueMove = TRUE;
|
|
} else {
|
|
Scr->OpaqueMove = FALSE;
|
|
}
|
|
switch (button) {
|
|
case 1 :
|
|
XUnmapWindow (dpy, sw);
|
|
break;
|
|
case 2 :
|
|
XGetGeometry (dpy, sw, &junkW, &X0, &Y0, &W0, &H0, &bw, &junk);
|
|
XTranslateCoordinates (dpy, vs->wsw->mswl [oldws->number]->w,
|
|
mw->w, X0, Y0, &X1, &Y1, &junkW);
|
|
|
|
attrs.event_mask = ExposureMask;
|
|
attrs.background_pixel = wl->cp.back;
|
|
attrs.border_pixel = wl->cp.back;
|
|
w = XCreateWindow (dpy, mw->w, X1, Y1, W0, H0, bw,
|
|
CopyFromParent,
|
|
(unsigned int) CopyFromParent,
|
|
(Visual *) CopyFromParent,
|
|
CWEventMask | CWBackPixel | CWBorderPixel, &attrs);
|
|
|
|
XMapRaised (dpy, w);
|
|
WMapRedrawWindow (w, W0, H0, wl->cp, wl->twm_win->icon_name);
|
|
if (realmovemode && Scr->ShowWinWhenMovingInWmgr) {
|
|
if (Scr->OpaqueMove) {
|
|
DisplayWin (vs, win);
|
|
} else {
|
|
MoveOutline (Scr->Root,
|
|
win->frame_x - win->frame_bw,
|
|
win->frame_y - win->frame_bw,
|
|
win->frame_width + 2 * win->frame_bw,
|
|
win->frame_height + 2 * win->frame_bw,
|
|
win->frame_bw,
|
|
win->title_height + win->frame_bw3D);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 3 :
|
|
occupation = win->occupation & ~(1 << oldws->number);
|
|
ChangeOccupation (win, occupation);
|
|
return;
|
|
default :
|
|
return;
|
|
}
|
|
|
|
wf = (float) (mw->wwidth - 1) / (float) vs->w;
|
|
hf = (float) (mw->wheight - 1) / (float) vs->h;
|
|
XGrabPointer (dpy, mw->w, False, ButtonPressMask | ButtonMotionMask | ButtonReleaseMask,
|
|
GrabModeAsync, GrabModeAsync, mw->w, Scr->MoveCursor, CurrentTime);
|
|
|
|
alreadyvivible = False;
|
|
cont = TRUE;
|
|
while (cont) {
|
|
MapSubwindow *msw;
|
|
XMaskEvent (dpy, ButtonPressMask | ButtonMotionMask |
|
|
ButtonReleaseMask | ExposureMask, &ev);
|
|
switch (ev.xany.type) {
|
|
case ButtonPress :
|
|
case ButtonRelease :
|
|
if (ev.xbutton.button != button) break;
|
|
cont = FALSE;
|
|
newX = ev.xbutton.x;
|
|
newY = ev.xbutton.y;
|
|
|
|
case MotionNotify :
|
|
if (cont) {
|
|
newX = ev.xmotion.x;
|
|
newY = ev.xmotion.y;
|
|
}
|
|
if (realmovemode) {
|
|
for (cws = Scr->workSpaceMgr.workSpaceList;
|
|
cws != NULL;
|
|
cws = cws->next) {
|
|
msw = vs->wsw->mswl [cws->number];
|
|
if ((newX >= msw->x) && (newX < msw->x + mw->wwidth) &&
|
|
(newY >= msw->y) && (newY < msw->y + mw->wheight)) {
|
|
break;
|
|
}
|
|
}
|
|
if (!cws) break;
|
|
winX = newX - XW;
|
|
winY = newY - YW;
|
|
msw = vs->wsw->mswl [cws->number];
|
|
XTranslateCoordinates (dpy, mw->w, msw->w,
|
|
winX, winY, &XSW, &YSW, &junkW);
|
|
winX = (int) (XSW / wf);
|
|
winY = (int) (YSW / hf);
|
|
if (Scr->DontMoveOff) {
|
|
int width = win->frame_width;
|
|
int height = win->frame_height;
|
|
|
|
if ((winX < Scr->BorderLeft) && ((Scr->MoveOffResistance < 0) ||
|
|
(winX > Scr->BorderLeft - Scr->MoveOffResistance))) {
|
|
winX = Scr->BorderLeft;
|
|
newX = msw->x + XW + Scr->BorderLeft * mw->wwidth / vs->w;
|
|
}
|
|
if (((winX + width) > vs->w - Scr->BorderRight) &&
|
|
((Scr->MoveOffResistance < 0) ||
|
|
((winX + width) < vs->w - Scr->BorderRight + Scr->MoveOffResistance))) {
|
|
winX = vs->w - Scr->BorderRight - width;
|
|
newX = msw->x + mw->wwidth *
|
|
(1 - Scr->BorderRight / (double) vs->w) - wl->width + XW - 2;
|
|
}
|
|
if ((winY < Scr->BorderTop) && ((Scr->MoveOffResistance < 0) ||
|
|
(winY > Scr->BorderTop - Scr->MoveOffResistance))) {
|
|
winY = Scr->BorderTop;
|
|
newY = msw->y + YW + Scr->BorderTop * mw->height / vs->h;
|
|
}
|
|
if (((winY + height) > vs->h - Scr->BorderBottom) &&
|
|
((Scr->MoveOffResistance < 0) ||
|
|
((winY + height) < vs->h - Scr->BorderBottom + Scr->MoveOffResistance))) {
|
|
winY = vs->h - Scr->BorderBottom - height;
|
|
newY = msw->y + mw->wheight *
|
|
(1 - Scr->BorderBottom / (double) vs->h) - wl->height + YW - 2;
|
|
}
|
|
}
|
|
WMapSetupWindow (win, winX, winY, -1, -1);
|
|
if (Scr->ShowWinWhenMovingInWmgr) goto movewin;
|
|
if (cws == vs->wsw->currentwspc) {
|
|
if (alreadyvivible) goto movewin;
|
|
if (Scr->OpaqueMove) {
|
|
XMoveWindow (dpy, win->frame, winX, winY);
|
|
DisplayWin (vs, win);
|
|
} else {
|
|
MoveOutline (Scr->Root,
|
|
winX - win->frame_bw, winY - win->frame_bw,
|
|
win->frame_width + 2 * win->frame_bw,
|
|
win->frame_height + 2 * win->frame_bw,
|
|
win->frame_bw,
|
|
win->title_height + win->frame_bw3D);
|
|
}
|
|
alreadyvivible = True;
|
|
goto move;
|
|
}
|
|
if (!alreadyvivible) goto move;
|
|
if (!OCCUPY (win, vs->wsw->currentwspc) ||
|
|
(startincurrent && (button == 1))) {
|
|
if (Scr->OpaqueMove) {
|
|
Vanish (vs, win);
|
|
XMoveWindow (dpy, win->frame, winX, winY);
|
|
} else {
|
|
MoveOutline (Scr->Root, 0, 0, 0, 0, 0, 0);
|
|
}
|
|
alreadyvivible = False;
|
|
goto move;
|
|
}
|
|
movewin: if (Scr->OpaqueMove) {
|
|
XMoveWindow (dpy, win->frame, winX, winY);
|
|
} else {
|
|
MoveOutline (Scr->Root,
|
|
winX - win->frame_bw, winY - win->frame_bw,
|
|
win->frame_width + 2 * win->frame_bw,
|
|
win->frame_height + 2 * win->frame_bw,
|
|
win->frame_bw,
|
|
win->title_height + win->frame_bw3D);
|
|
}
|
|
}
|
|
move: XMoveWindow (dpy, w, newX - XW, newY - YW);
|
|
break;
|
|
case Expose :
|
|
if (ev.xexpose.window == w) {
|
|
WMapRedrawWindow (w, W0, H0, wl->cp, wl->twm_win->icon_name);
|
|
break;
|
|
}
|
|
Event = ev;
|
|
DispatchEvent ();
|
|
break;
|
|
}
|
|
}
|
|
if (realmovemode) {
|
|
if (Scr->ShowWinWhenMovingInWmgr || alreadyvivible) {
|
|
if (Scr->OpaqueMove && !OCCUPY (win, vs->wsw->currentwspc)) {
|
|
Vanish (vs, win);
|
|
}
|
|
if (!Scr->OpaqueMove) {
|
|
MoveOutline (Scr->Root, 0, 0, 0, 0, 0, 0);
|
|
WMapRedrawName (vs, wl);
|
|
}
|
|
}
|
|
SetupWindow (win, winX, winY, win->frame_width, win->frame_height, -1);
|
|
}
|
|
ev.xbutton.subwindow = (Window) 0;
|
|
ev.xbutton.window = parent;
|
|
XPutBackEvent (dpy, &ev);
|
|
XUngrabPointer (dpy, CurrentTime);
|
|
|
|
if ((ev.xbutton.time - etime) < 250) {
|
|
KeyCode control_L_code, control_R_code;
|
|
KeySym control_L_sym, control_R_sym;
|
|
char keys [32];
|
|
|
|
XMapWindow (dpy, sw);
|
|
XDestroyWindow (dpy, w);
|
|
GotoWorkSpace (vs, ws);
|
|
if (!Scr->DontWarpCursorInWMap) WarpToWindow (win, Scr->RaiseOnWarp);
|
|
control_L_sym = XStringToKeysym ("Control_L");
|
|
control_R_sym = XStringToKeysym ("Control_R");
|
|
control_L_code = XKeysymToKeycode (dpy, control_L_sym);
|
|
control_R_code = XKeysymToKeycode (dpy, control_R_sym);
|
|
XQueryKeymap (dpy, keys);
|
|
if ((keys [control_L_code / 8] & ((char) 0x80 >> (control_L_code % 8))) ||
|
|
keys [control_R_code / 8] & ((char) 0x80 >> (control_R_code % 8))) {
|
|
WMapToggleState (vs);
|
|
}
|
|
return;
|
|
}
|
|
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
MapSubwindow *msw = vs->wsw->mswl [ws->number];
|
|
if ((newX >= msw->x) && (newX < msw->x + mw->wwidth) &&
|
|
(newY >= msw->y) && (newY < msw->y + mw->wheight)) {
|
|
break;
|
|
}
|
|
}
|
|
newws = ws;
|
|
switch (button) {
|
|
case 1 :
|
|
if ((newws == NULL) || (newws == oldws) || OCCUPY (wl->twm_win, newws)) {
|
|
XMapWindow (dpy, sw);
|
|
break;
|
|
}
|
|
occupation = (win->occupation | (1 << newws->number)) & ~(1 << oldws->number);
|
|
ChangeOccupation (win, occupation);
|
|
if (newws == vs->wsw->currentwspc) {
|
|
RaiseWindow (win);
|
|
WMapRaise (win);
|
|
}
|
|
else WMapRestack (newws);
|
|
break;
|
|
|
|
case 2 :
|
|
if ((newws == NULL) || (newws == oldws) ||
|
|
OCCUPY (wl->twm_win, newws)) break;
|
|
|
|
occupation = win->occupation | (1 << newws->number);
|
|
ChangeOccupation (win, occupation);
|
|
if (newws == vs->wsw->currentwspc) {
|
|
RaiseWindow (win);
|
|
WMapRaise (win);
|
|
}
|
|
else WMapRestack (newws);
|
|
break;
|
|
|
|
default :
|
|
return;
|
|
}
|
|
XDestroyWindow (dpy, w);
|
|
}
|
|
|
|
void InvertColorPair (ColorPair *cp)
|
|
{
|
|
Pixel save;
|
|
|
|
save = cp->fore;
|
|
cp->fore = cp->back;
|
|
cp->back = save;
|
|
save = cp->shadc;
|
|
cp->shadc = cp->shadd;
|
|
cp->shadd = save;
|
|
}
|
|
|
|
void WMapRedrawName (virtualScreen *vs, WinList wl)
|
|
{
|
|
int w = wl->width;
|
|
int h = wl->height;
|
|
ColorPair cp;
|
|
char *label;
|
|
|
|
label = wl->twm_win->icon_name;
|
|
cp = wl->cp;
|
|
|
|
if (Scr->ReverseCurrentWorkspace && wl->wlist == vs->wsw->currentwspc) {
|
|
InvertColorPair (&cp);
|
|
}
|
|
WMapRedrawWindow (wl->w, w, h, cp, label);
|
|
}
|
|
|
|
static void WMapRedrawWindow (Window window, int width, int height,
|
|
ColorPair cp, char *label)
|
|
{
|
|
int x, y, strhei, strwid;
|
|
MyFont font;
|
|
XFontSetExtents *font_extents;
|
|
XRectangle inc_rect;
|
|
XRectangle logical_rect;
|
|
XFontStruct **xfonts;
|
|
char **font_names;
|
|
register int i;
|
|
int descent;
|
|
int fnum;
|
|
|
|
XClearWindow (dpy, window);
|
|
font = Scr->workSpaceMgr.windowFont;
|
|
|
|
font_extents = XExtentsOfFontSet(font.font_set);
|
|
strhei = font_extents->max_logical_extent.height;
|
|
|
|
if (strhei > height) return;
|
|
|
|
XmbTextExtents(font.font_set, label, strlen (label),
|
|
&inc_rect, &logical_rect);
|
|
strwid = logical_rect.width;
|
|
x = (width - strwid) / 2;
|
|
if (x < 1) x = 1;
|
|
|
|
fnum = XFontsOfFontSet(font.font_set, &xfonts, &font_names);
|
|
for( i = 0, descent = 0; i < fnum; i++){
|
|
/* xf = xfonts[i]; */
|
|
descent = ((descent < (xfonts[i]->max_bounds.descent)) ? (xfonts[i]->max_bounds.descent): descent);
|
|
}
|
|
|
|
y = ((height + strhei) / 2) - descent;
|
|
|
|
if (Scr->use3Dwmap) {
|
|
Draw3DBorder (window, 0, 0, width, height, 1, cp, off, True, False);
|
|
FB(cp.fore, cp.back);
|
|
} else {
|
|
FB (cp.back, cp.fore);
|
|
XFillRectangle (dpy, window, Scr->NormalGC, 0, 0, width, height);
|
|
FB (cp.fore, cp.back);
|
|
}
|
|
if (Scr->Monochrome != COLOR) {
|
|
XmbDrawImageString (dpy, window, font.font_set, Scr->NormalGC, x, y, label, strlen (label));
|
|
} else {
|
|
XmbDrawString (dpy, window, font.font_set,Scr->NormalGC, x, y, label, strlen (label));
|
|
}
|
|
}
|
|
|
|
static void WMapAddToList (TwmWindow *win, WorkSpace *ws)
|
|
{
|
|
virtualScreen *vs;
|
|
WinList wl;
|
|
float wf, hf;
|
|
ColorPair cp;
|
|
XSetWindowAttributes attr;
|
|
unsigned long attrmask;
|
|
unsigned int bw;
|
|
|
|
cp.back = win->title.back;
|
|
cp.fore = win->title.fore;
|
|
if (Scr->workSpaceMgr.windowcpgiven) {
|
|
cp.back = Scr->workSpaceMgr.windowcp.back;
|
|
GetColorFromList (Scr->workSpaceMgr.windowBackgroundL,
|
|
win->full_name, &win->class, &cp.back);
|
|
cp.fore = Scr->workSpaceMgr.windowcp.fore;
|
|
GetColorFromList (Scr->workSpaceMgr.windowForegroundL,
|
|
win->full_name, &win->class, &cp.fore);
|
|
}
|
|
if (Scr->use3Dwmap && !Scr->BeNiceToColormap) {
|
|
GetShadeColors (&cp);
|
|
}
|
|
for (vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
|
|
wf = (float) (vs->wsw->wwidth - 2) / (float) vs->w;
|
|
hf = (float) (vs->wsw->wheight - 2) / (float) vs->h;
|
|
wl = (WinList) malloc (sizeof (struct winList));
|
|
wl->wlist = ws;
|
|
wl->x = (int) (win->frame_x * wf);
|
|
wl->y = (int) (win->frame_y * hf);
|
|
wl->width = (unsigned int) ((win->frame_width * wf) + 0.5);
|
|
wl->height = (unsigned int) ((win->frame_height * hf) + 0.5);
|
|
bw = 0;
|
|
if (!Scr->use3Dwmap) {
|
|
bw = 1;
|
|
wl->width -= 2;
|
|
wl->height -= 2;
|
|
}
|
|
if (wl->width < 1) wl->width = 1;
|
|
if (wl->height < 1) wl->height = 1;
|
|
wl->w = XCreateSimpleWindow (dpy, vs->wsw->mswl [ws->number]->w, wl->x, wl->y,
|
|
wl->width, wl->height, bw, Scr->Black, cp.back);
|
|
attrmask = 0;
|
|
if (Scr->BackingStore) {
|
|
attr.backing_store = WhenMapped;
|
|
attrmask |= CWBackingStore;
|
|
}
|
|
attr.cursor = handCursor;
|
|
attrmask |= CWCursor;
|
|
XChangeWindowAttributes (dpy, wl->w, attrmask, &attr);
|
|
XSelectInput (dpy, wl->w, ExposureMask);
|
|
XSaveContext (dpy, wl->w, TwmContext, (XPointer) vs->wsw->twm_win);
|
|
XSaveContext (dpy, wl->w, ScreenContext, (XPointer) Scr);
|
|
XSaveContext (dpy, wl->w, MapWListContext, (XPointer) wl);
|
|
wl->twm_win = win;
|
|
wl->cp = cp;
|
|
wl->next = vs->wsw->mswl [ws->number]->wl;
|
|
vs->wsw->mswl [ws->number]->wl = wl;
|
|
if (win->mapped) XMapWindow (dpy, wl->w);
|
|
}
|
|
}
|
|
|
|
static void WMapRemoveFromList (TwmWindow *win, WorkSpace *ws)
|
|
{
|
|
virtualScreen *vs;
|
|
WinList wl, *prev;
|
|
|
|
for (vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
|
|
prev = &vs->wsw->mswl [ws->number]->wl;
|
|
wl = *prev;
|
|
while (wl != NULL) {
|
|
if (win == wl->twm_win) {
|
|
*prev = wl->next;
|
|
XDeleteContext (dpy, wl->w, TwmContext);
|
|
XDeleteContext (dpy, wl->w, ScreenContext);
|
|
XDeleteContext (dpy, wl->w, MapWListContext);
|
|
XDestroyWindow (dpy, wl->w);
|
|
free (wl);
|
|
break;
|
|
}
|
|
prev = &wl->next;
|
|
wl = *prev;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void ResizeWorkSpaceManager (virtualScreen *vs, TwmWindow *win)
|
|
{
|
|
int bwidth, bheight;
|
|
int wwidth, wheight;
|
|
int hspace, vspace;
|
|
int lines, columns;
|
|
int neww, newh;
|
|
WorkSpace *ws;
|
|
TwmWindow *tmp_win;
|
|
WinList wl;
|
|
int i, j;
|
|
float wf, hf;
|
|
|
|
neww = win->attr.width;
|
|
newh = win->attr.height;
|
|
if (neww == vs->wsw->width && newh == vs->wsw->height)
|
|
return;
|
|
|
|
hspace = Scr->workSpaceMgr.hspace;
|
|
vspace = Scr->workSpaceMgr.vspace;
|
|
lines = Scr->workSpaceMgr.lines;
|
|
columns = Scr->workSpaceMgr.columns;
|
|
bwidth = (neww - (columns * hspace)) / columns;
|
|
bheight = (newh - (lines * vspace)) / lines;
|
|
wwidth = neww / columns;
|
|
wheight = newh / lines;
|
|
wf = (float) (wwidth - 2) / (float) vs->w;
|
|
hf = (float) (wheight - 2) / (float) vs->h;
|
|
|
|
i = 0;
|
|
j = 0;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
MapSubwindow *msw = vs->wsw->mswl [ws->number];
|
|
XMoveResizeWindow (dpy, vs->wsw->bswl [ws->number]->w,
|
|
i * (bwidth + hspace) + (hspace / 2),
|
|
j * (bheight + vspace) + (vspace / 2),
|
|
bwidth, bheight);
|
|
msw->x = i * wwidth;
|
|
msw->y = j * wheight;
|
|
XMoveResizeWindow (dpy, msw->w, msw->x, msw->y, wwidth - 2, wheight - 2);
|
|
for (wl = msw->wl; wl != NULL; wl = wl->next) {
|
|
tmp_win = wl->twm_win;
|
|
wl->x = (int) (tmp_win->frame_x * wf);
|
|
wl->y = (int) (tmp_win->frame_y * hf);
|
|
wl->width = (unsigned int) ((tmp_win->frame_width * wf) + 0.5);
|
|
wl->height = (unsigned int) ((tmp_win->frame_height * hf) + 0.5);
|
|
XMoveResizeWindow (dpy, wl->w, wl->x, wl->y, wl->width, wl->height);
|
|
}
|
|
i++;
|
|
if (i == columns) {i = 0; j++;};
|
|
}
|
|
vs->wsw->bwidth = bwidth;
|
|
vs->wsw->bheight = bheight;
|
|
vs->wsw->width = neww;
|
|
vs->wsw->height = newh;
|
|
vs->wsw->wwidth = wwidth;
|
|
vs->wsw->wheight = wheight;
|
|
PaintWorkSpaceManager (vs);
|
|
}
|
|
|
|
static void ResizeOccupyWindow (TwmWindow *win)
|
|
{
|
|
int bwidth, bheight, owidth, oheight;
|
|
int hspace, vspace;
|
|
int lines, columns;
|
|
int neww, newh;
|
|
WorkSpace *ws;
|
|
int i, j, x, y;
|
|
OccupyWindow *occwin = Scr->workSpaceMgr.occupyWindow;
|
|
|
|
neww = win->attr.width;
|
|
newh = win->attr.height;
|
|
if (occwin->width == neww && occwin->height == newh)
|
|
return;
|
|
|
|
hspace = occwin->hspace;
|
|
vspace = occwin->vspace;
|
|
lines = Scr->workSpaceMgr.lines;
|
|
columns = Scr->workSpaceMgr.columns;
|
|
bwidth = (neww - columns * hspace) / columns;
|
|
bheight = (newh - (lines + 2) * vspace) / (lines + 1);
|
|
owidth = occwin->owidth;
|
|
oheight = bheight;
|
|
|
|
i = 0;
|
|
j = 0;
|
|
for (ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
XMoveResizeWindow (dpy, occwin->obuttonw [j * columns + i],
|
|
i * (bwidth + hspace) + (hspace / 2),
|
|
j * (bheight + vspace) + (vspace / 2),
|
|
bwidth, bheight);
|
|
i++;
|
|
if (i == columns) {i = 0; j++;}
|
|
}
|
|
hspace = (neww - 3 * owidth) / 4;
|
|
x = hspace;
|
|
y = ((bheight + vspace) * lines) + ((3 * vspace) / 2);
|
|
XMoveResizeWindow (dpy, occwin->OK, x, y, owidth, oheight);
|
|
x += owidth + hspace;
|
|
XMoveResizeWindow (dpy, occwin->cancel, x, y, owidth, oheight);
|
|
x += owidth + hspace;
|
|
XMoveResizeWindow (dpy, occwin->allworkspc, x, y, owidth, oheight);
|
|
|
|
occwin->width = neww;
|
|
occwin->height = newh;
|
|
occwin->bwidth = bwidth;
|
|
occwin->bheight = bheight;
|
|
occwin->owidth = owidth;
|
|
PaintOccupyWindow ();
|
|
}
|
|
|
|
void WMapCreateCurrentBackGround (char *border,
|
|
char *background, char *foreground,
|
|
char *pixmap)
|
|
{
|
|
Image *image;
|
|
WorkSpaceMgr *ws = &Scr->workSpaceMgr;
|
|
|
|
ws->curBorderColor = Scr->Black;
|
|
ws->curColors.back = Scr->White;
|
|
ws->curColors.fore = Scr->Black;
|
|
ws->curImage = None;
|
|
|
|
if (border == NULL)
|
|
return;
|
|
GetColor (Scr->Monochrome, &ws->curBorderColor, border);
|
|
if (background == NULL)
|
|
return;
|
|
ws->curPaint = True;
|
|
GetColor (Scr->Monochrome, &ws->curColors.back, background);
|
|
if (foreground == NULL)
|
|
return;
|
|
GetColor (Scr->Monochrome, &ws->curColors.fore, foreground);
|
|
|
|
if (pixmap == NULL)
|
|
return;
|
|
if ((image = GetImage (pixmap, Scr->workSpaceMgr.curColors)) == None) {
|
|
fprintf (stderr, "Can't find pixmap %s\n", pixmap);
|
|
return;
|
|
}
|
|
ws->curImage = image;
|
|
}
|
|
|
|
void WMapCreateDefaultBackGround (char *border,
|
|
char *background, char *foreground,
|
|
char *pixmap)
|
|
{
|
|
Image *image;
|
|
WorkSpaceMgr *ws = &Scr->workSpaceMgr;
|
|
|
|
ws->defBorderColor = Scr->Black;
|
|
ws->defColors.back = Scr->White;
|
|
ws->defColors.fore = Scr->Black;
|
|
ws->defImage = None;
|
|
|
|
if (border == NULL)
|
|
return;
|
|
GetColor (Scr->Monochrome, &ws->defBorderColor, border);
|
|
if (background == NULL)
|
|
return;
|
|
GetColor (Scr->Monochrome, &ws->defColors.back, background);
|
|
if (foreground == NULL)
|
|
return;
|
|
GetColor (Scr->Monochrome, &ws->defColors.fore, foreground);
|
|
if (pixmap == NULL)
|
|
return;
|
|
if ((image = GetImage (pixmap, ws->defColors)) == None)
|
|
return;
|
|
ws->defImage = image;
|
|
}
|
|
|
|
Bool AnimateRoot (void)
|
|
{
|
|
virtualScreen *vs;
|
|
ScreenInfo *scr;
|
|
int scrnum;
|
|
Image *image;
|
|
WorkSpace *ws;
|
|
Bool maybeanimate;
|
|
|
|
maybeanimate = False;
|
|
for (scrnum = 0; scrnum < NumScreens; scrnum++) {
|
|
if ((scr = ScreenList [scrnum]) == NULL) continue;
|
|
if (! scr->workSpaceManagerActive) continue;
|
|
|
|
for (vs = scr->vScreenList; vs != NULL; vs = vs->next) {
|
|
if (! vs->wsw->currentwspc) continue;
|
|
image = vs->wsw->currentwspc->image;
|
|
if ((image == None) || (image->next == None)) continue;
|
|
if (scr->DontPaintRootWindow) continue;
|
|
|
|
XSetWindowBackgroundPixmap (dpy, vs->window, image->pixmap);
|
|
XClearWindow (dpy, scr->Root);
|
|
vs->wsw->currentwspc->image = image->next;
|
|
maybeanimate = True;
|
|
}
|
|
}
|
|
for (scrnum = 0; scrnum < NumScreens; scrnum++) {
|
|
if ((scr = ScreenList [scrnum]) == NULL) continue;
|
|
|
|
for (vs = scr->vScreenList; vs != NULL; vs = vs->next) {
|
|
if (vs->wsw->state == BUTTONSSTATE) continue;
|
|
for (ws = scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
|
|
image = ws->image;
|
|
|
|
if ((image == None) || (image->next == None)) continue;
|
|
if (ws == vs->wsw->currentwspc) continue;
|
|
XSetWindowBackgroundPixmap (dpy, vs->wsw->mswl [ws->number]->w, image->pixmap);
|
|
XClearWindow (dpy, vs->wsw->mswl [ws->number]->w);
|
|
ws->image = image->next;
|
|
maybeanimate = True;
|
|
}
|
|
}
|
|
}
|
|
return (maybeanimate);
|
|
}
|
|
|
|
static char **GetCaptivesList (int scrnum)
|
|
{
|
|
unsigned char *prop, *p;
|
|
unsigned long bytesafter;
|
|
unsigned long len;
|
|
Atom actual_type;
|
|
int actual_format;
|
|
char **ret;
|
|
int count;
|
|
int i, l;
|
|
Window root;
|
|
|
|
_XA_WM_CTWMSLIST = XInternAtom (dpy, "WM_CTWMSLIST", True);
|
|
if (_XA_WM_CTWMSLIST == None) return ((char**)0);
|
|
|
|
root = RootWindow (dpy, scrnum);
|
|
if (XGetWindowProperty (dpy, root, _XA_WM_CTWMSLIST, 0L, 512,
|
|
False, XA_STRING, &actual_type, &actual_format, &len,
|
|
&bytesafter, &prop) != Success) return ((char**) 0);
|
|
if (len == 0) return ((char**) 0);
|
|
|
|
count = 0;
|
|
p = prop;
|
|
l = 0;
|
|
while (l < len) {
|
|
l += strlen ((char*)p) + 1;
|
|
p += strlen ((char*)p) + 1;
|
|
count++;
|
|
}
|
|
ret = (char**) malloc ((count + 1) * sizeof (char*));
|
|
|
|
p = prop;
|
|
l = 0;
|
|
i = 0;
|
|
while (l < len) {
|
|
ret [i++] = (char*) strdup ((char*) p);
|
|
l += strlen ((char*)p) + 1;
|
|
p += strlen ((char*)p) + 1;
|
|
}
|
|
ret [i] = (char*) 0;
|
|
XFree ((char *)prop);
|
|
|
|
return (ret);
|
|
}
|
|
|
|
static void SetCaptivesList (int scrnum, char **clist)
|
|
{
|
|
unsigned long len;
|
|
char **cl;
|
|
char *s, *slist;
|
|
Window root = RootWindow (dpy, scrnum);
|
|
|
|
_XA_WM_CTWMSLIST = XInternAtom (dpy, "WM_CTWMSLIST", False);
|
|
cl = clist; len = 0;
|
|
while (*cl) { len += strlen (*cl++) + 1; }
|
|
if (len == 0) {
|
|
XDeleteProperty (dpy, root, _XA_WM_CTWMSLIST);
|
|
return;
|
|
}
|
|
slist = (char*) malloc (len * sizeof (char));
|
|
cl = clist; s = slist;
|
|
while (*cl) {
|
|
strcpy (s, *cl);
|
|
s += strlen (*cl);
|
|
*s++ = '\0';
|
|
cl++;
|
|
}
|
|
XChangeProperty (dpy, root, _XA_WM_CTWMSLIST, XA_STRING, 8,
|
|
PropModeReplace, (unsigned char *) slist, len);
|
|
}
|
|
|
|
static void freeCaptiveList (char **clist)
|
|
{
|
|
while (clist && *clist) { free (*clist++); }
|
|
}
|
|
|
|
void AddToCaptiveList (void)
|
|
{
|
|
int i, count;
|
|
char **clist, **cl, **newclist;
|
|
int busy [32];
|
|
Atom _XA_WM_CTWM_ROOT;
|
|
char *atomname;
|
|
int scrnum = Scr->screen;
|
|
Window croot = Scr->Root;
|
|
Window root = RootWindow (dpy, scrnum);
|
|
|
|
for (i = 0; i < 32; i++) { busy [i] = 0; }
|
|
clist = GetCaptivesList (scrnum);
|
|
cl = clist;
|
|
count = 0;
|
|
while (cl && *cl) {
|
|
count++;
|
|
if (!captivename) {
|
|
if (!strncmp (*cl, "ctwm-", 5)) {
|
|
int r, n;
|
|
r = sscanf (*cl, "ctwm-%d", &n);
|
|
cl++;
|
|
if (r != 1) continue;
|
|
if ((n < 0) || (n > 31)) continue;
|
|
busy [n] = 1;
|
|
} else cl++;
|
|
continue;
|
|
}
|
|
if (!strcmp (*cl, captivename)) {
|
|
fprintf (stderr, "A captive ctwm with name %s is already running\n", captivename);
|
|
exit (1);
|
|
}
|
|
cl++;
|
|
}
|
|
if (!captivename) {
|
|
for (i = 0; i < 32; i++) {
|
|
if (!busy [i]) break;
|
|
}
|
|
if (i == 32) { /* no one can tell we didn't try hard */
|
|
fprintf (stderr, "Cannot find a suitable name for captive ctwm\n");
|
|
exit (1);
|
|
}
|
|
captivename = (char*) malloc (8);
|
|
sprintf (captivename, "ctwm-%d", i);
|
|
}
|
|
newclist = (char**) malloc ((count + 2) * sizeof (char*));
|
|
for (i = 0; i < count; i++) {
|
|
newclist [i] = (char*) strdup (clist [i]);
|
|
}
|
|
newclist [count] = (char*) strdup (captivename);
|
|
newclist [count + 1] = (char*) 0;
|
|
SetCaptivesList (scrnum, newclist);
|
|
freeCaptiveList (clist);
|
|
freeCaptiveList (newclist);
|
|
free (clist); free (newclist);
|
|
|
|
root = RootWindow (dpy, scrnum);
|
|
atomname = (char*) malloc (strlen ("WM_CTWM_ROOT_") + strlen (captivename) +1);
|
|
sprintf (atomname, "WM_CTWM_ROOT_%s", captivename);
|
|
_XA_WM_CTWM_ROOT = XInternAtom (dpy, atomname, False);
|
|
XChangeProperty (dpy, root, _XA_WM_CTWM_ROOT, XA_WINDOW, 32,
|
|
PropModeReplace, (unsigned char *) &croot, 4);
|
|
}
|
|
|
|
void RemoveFromCaptiveList (void)
|
|
{
|
|
int count;
|
|
char **clist, **cl, **newclist;
|
|
Atom _XA_WM_CTWM_ROOT;
|
|
char *atomname;
|
|
int scrnum = Scr->screen;
|
|
Window root = RootWindow (dpy, scrnum);
|
|
|
|
if (!captivename) return;
|
|
clist = GetCaptivesList (scrnum);
|
|
cl = clist; count = 0;
|
|
while (*cl) {
|
|
count++;
|
|
cl++;
|
|
}
|
|
newclist = (char**) malloc (count * sizeof (char*));
|
|
cl = clist; count = 0;
|
|
while (*cl) {
|
|
if (!strcmp (*cl, captivename)) { cl++; continue; }
|
|
newclist [count++] = *cl;
|
|
cl++;
|
|
}
|
|
newclist [count] = (char*) 0;
|
|
SetCaptivesList (scrnum, newclist);
|
|
freeCaptiveList (clist);
|
|
free (clist); free (newclist);
|
|
|
|
atomname = (char*) malloc (strlen ("WM_CTWM_ROOT_") + strlen (captivename) +1);
|
|
sprintf (atomname, "WM_CTWM_ROOT_%s", captivename);
|
|
_XA_WM_CTWM_ROOT = XInternAtom (dpy, atomname, True);
|
|
if (_XA_WM_CTWM_ROOT == None) return;
|
|
XDeleteProperty (dpy, root, _XA_WM_CTWM_ROOT);
|
|
}
|
|
|
|
void SetPropsIfCaptiveCtwm (TwmWindow *win)
|
|
{
|
|
Window window = win->w;
|
|
Window frame = win->frame;
|
|
Atom _XA_WM_CTWM_ROOT;
|
|
|
|
if (!CaptiveCtwmRootWindow (window)) return;
|
|
_XA_WM_CTWM_ROOT = XInternAtom (dpy, "WM_CTWM_ROOT", True);
|
|
if (_XA_WM_CTWM_ROOT == None) return;
|
|
|
|
XChangeProperty (dpy, frame, _XA_WM_CTWM_ROOT, XA_WINDOW, 32,
|
|
PropModeReplace, (unsigned char *) &window, 4);
|
|
}
|
|
|
|
Window CaptiveCtwmRootWindow (Window window)
|
|
{
|
|
Window *prop;
|
|
Window w;
|
|
unsigned long bytesafter;
|
|
unsigned long len;
|
|
Atom actual_type;
|
|
int actual_format;
|
|
Atom _XA_WM_CTWM_ROOT;
|
|
|
|
_XA_WM_CTWM_ROOT = XInternAtom (dpy, "WM_CTWM_ROOT", True);
|
|
if (_XA_WM_CTWM_ROOT == None) return ((Window)0);
|
|
|
|
if (XGetWindowProperty (dpy, window, _XA_WM_CTWM_ROOT, 0L, 1L,
|
|
False, XA_WINDOW, &actual_type, &actual_format, &len,
|
|
&bytesafter, (unsigned char **)&prop) != Success)
|
|
return ((Window)0);
|
|
if (len == 0) return ((Window)0);
|
|
w = *prop;
|
|
XFree ((char *)prop);
|
|
return w;
|
|
}
|
|
|
|
CaptiveCTWM GetCaptiveCTWMUnderPointer (void)
|
|
{
|
|
int scrnum = Scr->screen;
|
|
Window root;
|
|
Window child, croot;
|
|
CaptiveCTWM cctwm;
|
|
|
|
root = RootWindow (dpy, scrnum);
|
|
while (1) {
|
|
XQueryPointer (dpy, root, &JunkRoot, &child,
|
|
&JunkX, &JunkY, &JunkX, &JunkY, &JunkMask);
|
|
if (child && (croot = CaptiveCtwmRootWindow (child))) {
|
|
root = croot;
|
|
continue;
|
|
}
|
|
cctwm.root = root;
|
|
XFetchName (dpy, root, &cctwm.name);
|
|
if (!cctwm.name) cctwm.name = (char*) strdup ("Root");
|
|
return (cctwm);
|
|
}
|
|
}
|
|
|
|
void SetNoRedirect (Window window)
|
|
{
|
|
Atom _XA_WM_NOREDIRECT;
|
|
|
|
_XA_WM_NOREDIRECT = XInternAtom (dpy, "WM_NOREDIRECT", False);
|
|
if (_XA_WM_NOREDIRECT == None) return;
|
|
|
|
XChangeProperty (dpy, window, _XA_WM_NOREDIRECT, XA_STRING, 8,
|
|
PropModeReplace, (unsigned char *) "Yes", 4);
|
|
}
|
|
|
|
static Bool DontRedirect (Window window)
|
|
{
|
|
unsigned char *prop;
|
|
unsigned long bytesafter;
|
|
unsigned long len;
|
|
Atom actual_type;
|
|
int actual_format;
|
|
Atom _XA_WM_NOREDIRECT;
|
|
|
|
_XA_WM_NOREDIRECT = XInternAtom (dpy, "WM_NOREDIRECT", True);
|
|
if (_XA_WM_NOREDIRECT == None) return (False);
|
|
|
|
if (XGetWindowProperty (dpy, window, _XA_WM_NOREDIRECT, 0L, 1L,
|
|
False, XA_STRING, &actual_type, &actual_format, &len,
|
|
&bytesafter, &prop) != Success) return (False);
|
|
if (len == 0) return (False);
|
|
XFree ((char *)prop);
|
|
return (True);
|
|
}
|
|
|
|
Bool visible (TwmWindow *tmp_win)
|
|
{
|
|
return (tmp_win->vs != NULL);
|
|
}
|
|
|
|
#ifdef BUGGY_HP700_SERVER
|
|
static void fakeRaiseLower (display, window)
|
|
Display *display;
|
|
Window window;
|
|
{
|
|
Window root;
|
|
Window parent;
|
|
Window grandparent;
|
|
Window *children;
|
|
unsigned int number;
|
|
XWindowChanges changes;
|
|
|
|
number = 0;
|
|
XQueryTree (display, window, &root, &parent, &children, &number);
|
|
XFree ((char *) children);
|
|
XQueryTree (display, parent, &root, &grandparent, &children, &number);
|
|
|
|
changes.stack_mode = (children [number-1] == window) ? Below : Above;
|
|
XFree ((char *) children);
|
|
XConfigureWindow (display, window, CWStackMode, &changes);
|
|
}
|
|
#endif
|
|
|
|
|
|
|