/*********************************************************/
/* GNOME WM Compliance adapted for FVWM */
/* Properties set on the root window (or desktop window) */
/* */
/* Even though the rest of fvwm is GPL consider this file*/
/* Public Domain - use it however you see fit to make */
/* your WM GNOME compiant */
/* */
/* written by Raster */
/* adapted for FVWM by Jay Painter <jpaint@gnu.org> */
/*********************************************************/
#include "config.h"
#ifdef GNOME
#include <stdio.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include <X11/Xlib.h>
#include <X11/Xmd.h>
#include "libs/fvwmlib.h"
#include "fvwm.h"
#include "externs.h"
#include "cursor.h"
#include "functions.h"
#include "bindings.h"
#include "misc.h"
#include "screen.h"
#include "gnome.h"
#include "stack.h"
#include "update.h"
#include "style.h"
#include "virtual.h"
#include "window_flags.h"
#include "borders.h"
/*********************************************************/
/* Properties set on the root window (or desktop window) */
/*********************************************************/
/* WIN_AREA CARD32[2] contains the current desktop area X,Y */
#define XA_WIN_AREA "_WIN_AREA"
/* WIN_AREA CARD32[2] contains the current desktop area size WxH */
#define XA_WIN_AREA_COUNT "_WIN_AREA_COUNT"
/* array of atoms - atom being one of the following atoms */
#define XA_WIN_PROTOCOLS "_WIN_PROTOCOLS"
/* array of iocn in various sizes */
/* Type: array of CARD32 */
/* first item is icon count (n) */
/* second item is icon record length (in CARD32s) */
/* this is followed by (n) icon records as follows */
/* pixmap (XID) */
/* mask (XID) */
/* width (CARD32) */
/* height (CARD32) */
/* depth (of pixmap, mask is assumed to be of depth 1) (CARD32) */
/* drawable (screen root drawable of pixmap) (XID) */
/* ... additional fields can be added at the end of this list */
#define XA_WIN_ICONS "_WIN_ICONS"
/* WIN_WORKSPACE CARD32 contains the current desktop number */
#define XA_WIN_WORKSPACE "_WIN_WORKSPACE"
/* WIN_WORKSPACE_COUNT CARD32 contains the number of desktops */
#define XA_WIN_WORKSPACE_COUNT "_WIN_WORKSPACE_COUNT"
/* WIN_WORKSPACE_NAMES StringList (Text Property) of workspace names */
/* unused by enlightenment */
#define XA_WIN_WORKSPACE_NAMES "_WIN_WORKSPACE_NAMES"
/* ********** Don't use this.. iffy at best. *********** */
/* The available work area for client windows. The WM can set this and the WM */
/* and/or clients may change it at any time. If it is changed the WM and/or */
/* clients should honor the changes. If this property does not exist a client */
/* or WM can create it. */
/*
* CARD32 min_x;
* CARD32 min_y;
* CARD32 max_x;
* CARD32 max_y;
*/
#define XA_WIN_WORKAREA "_WIN_WORKAREA"
/* array of 4 CARD32's */
/* This is a list of window id's the WM is currently managing - primarily */
/* for being able to have external "tasklist" apps */
#define XA_WIN_CLIENT_LIST "_WIN_CLIENT_LIST"
/* array of N XID's */
/*********************************************************/
/* Properties on client windows */
/*********************************************************/
/* The layer the window exists in */
/* 0 = Desktop */
/* 1 = Below */
/* 2 = Normal (default app layer) */
/* 4 = OnTop */
/* 6 = Dock (always on top - for panel) */
/* The app sets this alone, not the WM. If this property changes the WM */
/* should comply and change the appearance/behavior of the Client window */
/* if this hint does not exist the WM Will create it on the Client window */
#define WIN_LAYER_DESKTOP 0
#define WIN_LAYER_BELOW 2
#define WIN_LAYER_NORMAL 4
#define WIN_LAYER_ONTOP 6
#define WIN_LAYER_DOCK 8
#define WIN_LAYER_ABOVE_DOCK 10
#define WIN_LAYER_MENU 12
#define XA_WIN_LAYER "_WIN_LAYER"
/* WIN_LAYER = CARD32 */
/* flags for the window's state. The WM will change these as needed when */
/* state changes. If the property contains info on client map, E will modify */
/* the windows state accordingly. if the Hint does not exist the WM will */
/* create it on the client window. 0 for the bit means off, 1 means on. */
/* unused (default) values are 0 */
/* removed Minimized - no explanation of what it really means - ambiguity */
/* should not be here if not clear */
#define WIN_STATE_STICKY (1<<0) /* everyone knows sticky */
#define WIN_STATE_RESERVED_BIT1 (1<<1) /* removed minimize here */
#define WIN_STATE_MAXIMIZED_VERT (1<<2) /* window in maximized V state */
#define WIN_STATE_MAXIMIZED_HORIZ (1<<3) /* window in maximized H state */
#define WIN_STATE_HIDDEN (1<<4) /* not on taskbar but window visible */
#define WIN_STATE_SHADED (1<<5) /* shaded (NeXT style) */
#define WIN_STATE_HID_WORKSPACE (1<<6) /* not on current desktop */
#define WIN_STATE_HID_TRANSIENT (1<<7) /* Owner of transient is hidden */
#define WIN_STATE_FIXED_POSITION (1<<8) /* window is fixed in position even */
#define WIN_STATE_ARRANGE_IGNORE (1<<9) /* ignore for auto arranging */
/* when scrolling about large */
/* virtual desktops ala fvwm */
#define XA_WIN_STATE "_WIN_STATE"
/* WIN_STATE = CARD32 */
/* Preferences for behavior for app */
/* ONLY the client sets this */
#define WIN_HINTS_SKIP_FOCUS (1<<0) /* "alt-tab" skips this win */
#define WIN_HINTS_SKIP_WINLIST (1<<1) /* not in win list */
#define WIN_HINTS_SKIP_TASKBAR (1<<2) /* not on taskbar */
#define WIN_HINTS_GROUP_TRANSIENT (1<<3) /* ??????? */
#define WIN_HINTS_FOCUS_ON_CLICK (1<<4) /* app only accepts focus when clicked */
#define XA_WIN_HINTS "_WIN_HINTS"
/* WIN_HINTS = CARD32 */
/* Application state - also "color reactiveness" - the app can keep changing */
/* this property when it changes its state and the WM or monitoring program */
/* will pick this up and dpylay somehting accordingly. ONLY the client sets */
/* this. */
#define WIN_APP_STATE_NONE 0
#define WIN_APP_STATE_ACTIVE1 1
#define WIN_APP_STATE_ACTIVE2 2
#define WIN_APP_STATE_ERROR1 3
#define WIN_APP_STATE_ERROR2 4
#define WIN_APP_STATE_FATAL_ERROR1 5
#define WIN_APP_STATE_FATAL_ERROR2 6
#define WIN_APP_STATE_IDLE1 7
#define WIN_APP_STATE_IDLE2 8
#define WIN_APP_STATE_WAITING1 9
#define WIN_APP_STATE_WAITING2 10
#define WIN_APP_STATE_WORKING1 11
#define WIN_APP_STATE_WORKING2 12
#define WIN_APP_STATE_NEED_USER_INPUT1 13
#define WIN_APP_STATE_NEED_USER_INPUT2 14
#define WIN_APP_STATE_STRUGGLING1 15
#define WIN_APP_STATE_STRUGGLING2 16
#define WIN_APP_STATE_DISK_TRAFFIC1 17
#define WIN_APP_STATE_DISK_TRAFFIC2 18
#define WIN_APP_STATE_NETWORK_TRAFFIC1 19
#define WIN_APP_STATE_NETWORK_TRAFFIC2 20
#define WIN_APP_STATE_OVERLOADED1 21
#define WIN_APP_STATE_OVERLOADED2 22
#define WIN_APP_STATE_PERCENT000_1 23
#define WIN_APP_STATE_PERCENT000_2 24
#define WIN_APP_STATE_PERCENT010_1 25
#define WIN_APP_STATE_PERCENT010_2 26
#define WIN_APP_STATE_PERCENT020_1 27
#define WIN_APP_STATE_PERCENT020_2 28
#define WIN_APP_STATE_PERCENT030_1 29
#define WIN_APP_STATE_PERCENT030_2 30
#define WIN_APP_STATE_PERCENT040_1 31
#define WIN_APP_STATE_PERCENT040_2 32
#define WIN_APP_STATE_PERCENT050_1 33
#define WIN_APP_STATE_PERCENT050_2 34
#define WIN_APP_STATE_PERCENT060_1 35
#define WIN_APP_STATE_PERCENT060_2 36
#define WIN_APP_STATE_PERCENT070_1 37
#define WIN_APP_STATE_PERCENT070_2 38
#define WIN_APP_STATE_PERCENT080_1 39
#define WIN_APP_STATE_PERCENT080_2 40
#define WIN_APP_STATE_PERCENT090_1 41
#define WIN_APP_STATE_PERCENT090_2 42
#define WIN_APP_STATE_PERCENT100_1 43
#define WIN_APP_STATE_PERCENT100_2 44
#define XA_WIN_APP_STATE "_WIN_APP_STATE"
/* WIN_APP_STATE = CARD32 */
/* Expanded space occupied - this is the area on screen the app's window */
/* will occupy when "expanded" - ie if you have a button on an app that */
/* "hides" it by reducing its size, this is the geometry of the expanded */
/* window - so the window manager can allow for this when doign auto */
/* positioing of client windows assuming the app can at any point use this */
/* this area and thus try and keep it clear. ONLY the client sets this */
/*
* CARD32 x;
* CARD32 y;
* CARD32 width;
* CARD32 height;
*/
#define XA_WIN_EXPANDED_SIZE "_WIN_EXPANDED_SIZE"
/* array of 4 CARD32's */
/* CARD32 that contians the desktop number the application is on If the */
/* application's state is "sticky" it is irrelevant. Only the WM should */
/* change this. */
#define XA_WIN_WORKSPACE "_WIN_WORKSPACE"
/* This atom is a 32-bit integer that is either 0 or 1 (currently). */
/* 0 denotes everything is as per usual but 1 denotes that ALL configure */
/* requests by the client on the client window with this property are */
/* not just a simple "moving" of the window, but the result of a user */
/* moving the window BUT the client handling that interaction by moving */
/* its own window. The window manager should respond accordingly by assuming */
/* any configure requests for this window whilst this atom is "active" in */
/* the "1" state are a client move and should handle flipping desktops if */
/* the window is being dragged "off screem" or across desktop boundaries */
/* etc. This atom is ONLY ever set by the client */
#define XA_WIN_CLIENT_MOVING "_WIN_CLIENT_MOVING"
/* WIN_CLIENT_MOVING = CARD32 */
/* Designed for checking if the WIN_ supporting WM is still there */
/* and kicking about - basically check this property - check the window */
/* ID it points to - then check that window Id has this property too */
/* if that is the case the WIN_ supporting WM is there and alive and the */
/* list of WIN_PROTOCOLS is valid */
#define XA_WIN_SUPPORTING_WM_CHECK "_WIN_SUPPORTING_WM_CHECK"
/* CARD32 */
/* for root window button clicks */
#define XA_WIN_DESKTOP_BUTTON_PROXY "_WIN_DESKTOP_BUTTON_PROXY"
/* CARD32 */
/* for the root window clicks */
static Window __button_proxy = 0;
/* how many desks does gnome know about */
static unsigned int gnome_max_desk = 1;
static void *
AtomGet(Window win, Atom to_get, Atom type, int *size)
{
unsigned char *retval;
Atom type_ret;
unsigned long bytes_after, num_ret;
int format_ret;
long length;
void *data;
retval = NULL;
length = 0x7fffffff;
XGetWindowProperty(dpy, win, to_get, 0,
length,
False, type,
&type_ret,
&format_ret,
&num_ret,
&bytes_after,
&retval);
if ((retval) && (num_ret > 0) && (format_ret > 0))
{
data = safemalloc(num_ret * (format_ret >> 3));
if (data)
memcpy(data, retval, num_ret * (format_ret >> 3));
XFree(retval);
*size = num_ret * (format_ret >> 3);
return data;
}
return NULL;
}
/*** GET WINDOW PROPERTIES ***/
#if 0
static void
GNOME_GetHintIcons(FvwmWindow *fwin)
{
Atom atom_get;
CARD32 *retval;
int size;
unsigned int i;
Pixmap pmap;
Pixmap mask;
atom_get = XInternAtom(dpy, XA_WIN_ICONS, False);
retval = AtomGet(fwin->w, atom_get, XA_PIXMAP, &size);
if (retval)
{
for (i = 0; i < (size / (sizeof(CARD32))); i += 2)
{
pmap = retval[i];
mask = retval[i + 1];
}
free(retval);
}
}
static void
GNOME_GetHintLayer(FvwmWindow *fwin)
{
Atom atom_get;
CARD32 *retval;
int size;
atom_get = XInternAtom(dpy, XA_WIN_LAYER, False);
retval = AtomGet(fwin->w, atom_get, XA_CARDINAL, &size);
if (retval)
{
set_layer(fwin, *retval);
free(retval);
}
}
static void
GNOME_GetHintState(FvwmWindow *fwin)
{
Atom atom_get;
CARD32 *retval;
int size;
atom_get = XInternAtom(dpy, XA_WIN_STATE, False);
retval = AtomGet(fwin->w, atom_get, XA_CARDINAL, &size);
if (retval)
{
if (*retval & WIN_STATE_STICKY)
SET_STICKY(fwin, 1);
if (*retval & WIN_STATE_SHADED)
SET_SHADED(fwin, 1);
if (*retval & WIN_STATE_FIXED_POSITION)
SET_FIXED(fwin, 1);
free(retval);
}
}
static void
GNOME_GetHintAppState(FvwmWindow *fwin)
{
Atom atom_get;
unsigned char *retval;
int size;
/* have nothing interesting to do with an app state (lamp) right now */
atom_get = XInternAtom(dpy, XA_WIN_APP_STATE, False);
retval = AtomGet(fwin->w, atom_get, XA_CARDINAL, &size);
if (retval)
{
free(retval);
}
}
static void
GNOME_GetHintDesktop(FvwmWindow *fwin)
{
Atom atom_get;
unsigned char *retval;
int size;
int *desk;
atom_get = XInternAtom(dpy, XA_WIN_WORKSPACE, False);
retval = AtomGet(fwin->w, atom_get, XA_CARDINAL, &size);
if (retval)
{
desk = (int *)retval;
fwin->Desk = *desk;
/* XXX: hide window if it's not on the current desktop! */
free(retval);
}
}
static void
GNOME_GetHint(FvwmWindow *fwin)
{
Atom atom_get;
int *retval;
int size;
atom_get = XInternAtom(dpy, XA_WIN_HINTS, False);
retval = AtomGet(fwin->w, atom_get, XA_CARDINAL, &size);
if (retval)
{
if (*retval & WIN_HINTS_SKIP_WINLIST)
SET_DO_SKIP_WINDOW_LIST(fwin, 1);
/* XXX: unimplimented */
if (*retval & WIN_HINTS_SKIP_TASKBAR)
;
if (*retval & WIN_HINTS_SKIP_FOCUS)
;
if (*retval & WIN_HINTS_FOCUS_ON_CLICK)
;
/* if (*retval & WIN_HINTS_DO_NOT_COVER);*/
free(retval);
}
}
static void
GNOME_GetExpandedSize(FvwmWindow *fwin)
{
Atom atom_get;
CARD32 *retval;
int size;
/* unimplimented */
int expanded_x, expanded_y, expanded_width, expanded_height;
atom_get = XInternAtom(dpy, XA_WIN_EXPANDED_SIZE, False);
retval = AtomGet(fwin->w, atom_get, XA_CARDINAL, &size);
if (retval)
{
expanded_x = retval[0];
expanded_y = retval[1];
expanded_width = retval[2];
expanded_height = retval[3];
free(retval);
}
}
void
GNOME_GetHints(FvwmWindow *fwin)
{
if (DO_IGNORE_GNOME_HINTS(fwin))
return;
GNOME_GetHintDesktop(fwin);
GNOME_GetHintIcons(fwin);
GNOME_GetHintLayer(fwin);
GNOME_GetHintState(fwin);
GNOME_GetHintAppState(fwin);
GNOME_GetHint(fwin);
GNOME_GetExpandedSize(fwin);
}
#endif
void
GNOME_SetHints(FvwmWindow *fwin)
{
Atom atom_set;
int val;
atom_set = XInternAtom(dpy, XA_WIN_STATE, False);
val = 0;
if (IS_STICKY(fwin))
val |= WIN_STATE_STICKY;
if (IS_SHADED(fwin))
val |= WIN_STATE_SHADED;
if (IS_FIXED(fwin))
val |= WIN_STATE_FIXED_POSITION;
XChangeProperty(dpy, fwin->w, atom_set, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *)&val, 1);
}
/* this duplicates most of the above... and it assumes
that style is inizialized to zero.
*/
void
GNOME_GetStyle (FvwmWindow *fwin, window_style *style)
{
Atom atom_get;
unsigned char *retval;
int size;
if (DO_IGNORE_GNOME_HINTS(fwin))
return;
/* Desktop */
atom_get = XInternAtom(dpy, XA_WIN_WORKSPACE, False);
retval = AtomGet(fwin->w, atom_get, XA_CARDINAL, &size);
if (retval)
{
SSET_START_DESK(*style, *(int*)retval);
/* Allow special case of -1 to work. */
if (SGET_START_DESK(*style) > -1)
SSET_START_DESK(*style, SGET_START_DESK(*style) + 1);
style->flags.use_start_on_desk = 1;
style->flag_mask.use_start_on_desk = 1;
free(retval);
}
/* Icons - not implemented */
/* Layer */
atom_get = XInternAtom(dpy, XA_WIN_LAYER, False);
retval = AtomGet(fwin->w, atom_get, XA_CARDINAL, &size);
if (retval)
{
SSET_LAYER(*style, *(int*)retval);
style->flags.use_layer = (SGET_LAYER(*style) >= 0) ? 1 : 0;
style->flag_mask.use_layer = 1;
free(retval);
}
/* State */
atom_get = XInternAtom(dpy, XA_WIN_STATE, False);
retval = AtomGet(fwin->w, atom_get, XA_CARDINAL, &size);
if (retval)
{
if (*(int*)retval & WIN_STATE_STICKY)
{
SFSET_IS_STICKY(*style, 1);
SMSET_IS_STICKY(*style, 1);
SCSET_IS_STICKY(*style, 1);
}
if (*(int*)retval & WIN_STATE_SHADED)
{
/* unimplemented, since we don't have a
start_shaded flag. SM code relies on a
separate do_shade flag, but that is ugly.
*/
}
if (*(int*)retval & WIN_STATE_FIXED_POSITION)
{
SFSET_IS_FIXED(*style, 1);
SMSET_IS_FIXED(*style, 1);
SCSET_IS_FIXED(*style, 1);
}
free(retval);
}
/* App state - not implemented */
/* Hints */
atom_get = XInternAtom(dpy, XA_WIN_HINTS, False);
retval = AtomGet(fwin->w, atom_get, XA_CARDINAL, &size);
if (retval)
{
if (*retval & WIN_HINTS_SKIP_WINLIST)
{
SFSET_DO_WINDOW_LIST_SKIP(*style, 1);
SMSET_DO_WINDOW_LIST_SKIP(*style, 1);
SCSET_DO_WINDOW_LIST_SKIP(*style, 1);
}
free(retval);
}
/* Expanded size - not implemented */
}
/*** SET WINDOW PROPERTIES ***/
void
GNOME_SetDesk(FvwmWindow *fwin)
{
Atom atom_set;
int val;
atom_set = XInternAtom(dpy, XA_WIN_WORKSPACE, False);
val = fwin->Desk;
if (val >= gnome_max_desk)
{
GNOME_SetDeskCount();
}
XChangeProperty(dpy, fwin->w, atom_set, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *)&val, 1);
}
void
GNOME_SetLayer(FvwmWindow *fwin)
{
Atom atom_set;
int val;
atom_set = XInternAtom(dpy, XA_WIN_LAYER, False);
val = get_layer(fwin);
XChangeProperty(dpy, fwin->w, atom_set, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *)&val, 1);
}
/*** INITALIZE GNOME WM SUPPORT ***/
/* sets the virtual desktop grid properties */
void
GNOME_SetAreaCount(void)
{
Atom atom_set;
CARD32 val[2];
atom_set = XInternAtom(dpy, XA_WIN_AREA_COUNT, False);
val[0] = (Scr.VxMax + Scr.MyDisplayWidth) / Scr.MyDisplayWidth;
val[1] = (Scr.VyMax + Scr.MyDisplayHeight) / Scr.MyDisplayHeight;
XChangeProperty(dpy, Scr.Root, atom_set, XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)val, 2);
}
/* sets the property indicating the current virtual desktop
* location
*/
void
GNOME_SetCurrentArea(void)
{
Atom atom_set;
CARD32 val[2];
atom_set = XInternAtom(dpy, XA_WIN_AREA, False);
val[0] = Scr.Vx / Scr.MyDisplayWidth;
val[1] = Scr.Vy / Scr.MyDisplayHeight;
XChangeProperty(dpy, Scr.Root, atom_set, XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)val, 2);
}
/* FIXME: what to do about negative desks ? */
/* ignore them! */
void
GNOME_SetDeskCount(void)
{
Atom atom_set;
CARD32 val;
FvwmWindow *t;
atom_set = XInternAtom(dpy, XA_WIN_WORKSPACE_COUNT, False);
val = 0;
if (Scr.CurrentDesk > 0)
val = Scr.CurrentDesk;
for (t = get_next_window_in_stack_ring(&Scr.FvwmRoot);
t != &Scr.FvwmRoot;
t = get_next_window_in_stack_ring(t))
{
if (t->Desk > val)
{
val = t->Desk;
}
}
val++;
if (gnome_max_desk > val)
{
val = gnome_max_desk;
}
XChangeProperty(dpy, Scr.Root, atom_set, XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)&val, 1);
}
/* XXX: this function is hard-coded to one! -JMP */
void
GNOME_SetCurrentDesk(void)
{
Atom atom_set;
CARD32 val;
atom_set = XInternAtom(dpy, XA_WIN_WORKSPACE, False);
val = (CARD32) Scr.CurrentDesk;
if (val >= gnome_max_desk)
{
GNOME_SetDeskCount();
}
XChangeProperty(dpy, Scr.Root, atom_set, XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)&val, 1);
GNOME_SetCurrentArea();
}
/* sets the names assigned to the desktops */
void
GNOME_SetDeskNames(void)
{
Atom atom_set;
XTextProperty text;
char *names[1];
atom_set = XInternAtom(dpy, XA_WIN_WORKSPACE_NAMES, False);
names[0] = "GNOME Desktop";
if (XStringListToTextProperty(names, 1, &text))
{
XSetTextProperty(dpy, Scr.Root, &text, atom_set);
XFree(text.value);
}
}
void
GNOME_SetClientList(void)
{
Atom atom_set;
Window *wl=NULL;
int displayed=0;
int i = 0;
FvwmWindow *t;
/* Find out how many window pointers we need to store, allocate
* the space and go through the list again to actually store them.
*/
for (t = Scr.FvwmRoot.next; t; t = t->next)
{
if (!DO_SKIP_WINDOW_LIST(t))
{
displayed++;
}
}
if(displayed)
{
wl=(Window*)safemalloc(sizeof(Window*)*displayed);
for (t = Scr.FvwmRoot.next; t; t = t->next)
{
if (!DO_SKIP_WINDOW_LIST(t))
{
wl[i++] = t->w;
}
}
}
/* Update X */
atom_set = XInternAtom(dpy, XA_WIN_CLIENT_LIST, False);
XChangeProperty(
dpy, Scr.Root, atom_set, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *)wl, i);
if(wl)
free(wl);
return;
}
void
GNOME_SetWinArea(FvwmWindow *w)
{
Atom atom_set;
CARD32 val[2];
atom_set = XInternAtom(dpy, XA_WIN_AREA, False);
if (!DO_SKIP_WINDOW_LIST(w))
{
if (IsRectangleOnThisPage(&(w->frame_g), w->Desk))
{
val[0] = Scr.Vx / Scr.MyDisplayWidth;
val[1] = Scr.Vy / Scr.MyDisplayHeight;
}
else
{
val[0] = (w->frame_g.x + Scr.Vx) / Scr.MyDisplayWidth;
if (val[0] < 0 && w->frame_g.x + Scr.Vx + w->frame_g.width > 0)
val[0] = 0;
val[1] = (w->frame_g.y + Scr.Vy) / Scr.MyDisplayHeight;
if (val[1] < 0 && w->frame_g.y + Scr.Vy + w->frame_g.height > 0)
val[1] = 0;
}
XChangeProperty(dpy, w->w, atom_set, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *)val, 2);
}
}
void
GNOME_Init(void)
{
int i;
Atom atom_set, list[11];
CARD32 val;
atom_set = XInternAtom(dpy, XA_WIN_PROTOCOLS, False);
/* these indicate what GNOME compliance properties have been implemented */
i = 0;
list[i++] = XInternAtom(dpy, XA_WIN_LAYER, False);
list[i++] = XInternAtom(dpy, XA_WIN_STATE, False);
list[i++] = XInternAtom(dpy, XA_WIN_HINTS, False);
/* list[i++] = XInternAtom(dpy, XA_WIN_APP_STATE, False); */
/* list[i++] = XInternAtom(dpy, XA_WIN_EXPANDED_SIZE, False); */
/* list[i++] = XInternAtom(dpy, XA_WIN_ICONS, False); */
list[i++] = XInternAtom(dpy, XA_WIN_WORKSPACE, False);
list[i++] = XInternAtom(dpy, XA_WIN_WORKSPACE_COUNT, False);
list[i++] = XInternAtom(dpy, XA_WIN_WORKSPACE_NAMES, False);
list[i++] = XInternAtom(dpy, XA_WIN_CLIENT_LIST, False);
list[i++] = XInternAtom(dpy, XA_WIN_DESKTOP_BUTTON_PROXY, False);
XChangeProperty(dpy, Scr.Root, atom_set, XA_ATOM, 32, PropModeReplace,
(unsigned char *)list, i);
/*-----------------------------------------------------------------------
why use two windows when one does just fine ?
-----------------------------------------------------------------------*/
/* create a window which is a child of the root window and set the
* XA_WIN_SUPPORTING_WM_CHECK property on it, and also set the
* same property on the root window with the window ID of of the
* window we just created
*/
__button_proxy = XCreateWindow(dpy, Scr.Root, -10, -10, 10, 10, 0, 0,
InputOnly, CopyFromParent, 0, NULL);
atom_set = XInternAtom(dpy, XA_WIN_SUPPORTING_WM_CHECK, False);
val = __button_proxy;
XChangeProperty(dpy, Scr.Root, atom_set, XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)&val, 1);
XChangeProperty(dpy, __button_proxy, atom_set, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *)&val, 1);
/* create a window which is the child of the root window for proxying
* root window clicks
*/
atom_set = XInternAtom(dpy, XA_WIN_DESKTOP_BUTTON_PROXY, False);
XChangeProperty(dpy, Scr.Root, atom_set, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *)&val, 1);
XChangeProperty(dpy, __button_proxy, atom_set, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *)&val, 1);
/* some inital settings */
GNOME_SetDeskCount();
GNOME_SetCurrentDesk();
GNOME_SetDeskNames();
GNOME_SetAreaCount();
GNOME_SetCurrentArea();
GNOME_SetClientList();
}
/*-----------------------------------------------------------------------
tell gnome how many desks to show
-----------------------------------------------------------------------*/
void
CMD_GnomeShowDesks(F_CMD_ARGS)
{
int n;
Atom atom_set;
CARD32 val[1];
atom_set = XInternAtom(dpy, XA_WIN_WORKSPACE_COUNT, False);
DBUG("GNOME_ShowDesks","Routine Entered");
n = GetIntegerArguments(action, NULL, (int *)val, 1);
if(n != 1)
{
fvwm_msg(ERR,"GnomeShowDesks","requires one argument");
return;
}
gnome_max_desk = val[0];
XChangeProperty(dpy, Scr.Root, atom_set, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *)(&val[0]), 1);
}
/*** RECIVING MESSAGES ***/
int
GNOME_ProcessClientMessage(FvwmWindow *fwin, XEvent *ev)
{
Atom a;
long p0 = 0;
long p1 = 0;
if (fwin != NULL && DO_IGNORE_GNOME_HINTS(fwin))
return 0;
a = XInternAtom(dpy, XA_WIN_AREA, False);
if (ev->xclient.message_type == a)
{
/* convert to integer grid */
p0 = ev->xclient.data.l[0] * Scr.MyDisplayWidth;
p1 = ev->xclient.data.l[1] * Scr.MyDisplayHeight;
if (p0 < 0 || p0 > 0x7fffffff || p1 < 0 || p1 > 0x7fffffff)
{
return 0;
}
MoveViewport(p0, p1, 1);
return 1;
}
a = XInternAtom(dpy, XA_WIN_WORKSPACE, False);
if (ev->xclient.message_type == a)
{
p0 = ev->xclient.data.l[0];
if (p0 < 0 || p0 > 0x7fffffff)
{
return 0;
}
goto_desk(p0);
return 1;
}
a = XInternAtom(dpy, XA_WIN_LAYER, False);
if (ev->xclient.message_type == a && fwin)
{
p0 = ev->xclient.data.l[0];
if (p0 < 0 || p0 > 0x7fffffff)
{
return 0;
}
new_layer(fwin, p0);
return 1;
}
a = XInternAtom(dpy, XA_WIN_STATE, False);
if (ev->xclient.message_type == a && fwin)
{
GNOME_HandlePropRequest(ev->xclient.data.l[0],
ev->xclient.data.l[1],
ev->xclient.window,
ev);
return 1;
}
return 0;
}
void GNOME_HandlePropRequest(unsigned int propm,
unsigned int prop,
Window win,
XEvent *ev)
{
Atom atype;
Atom a;
int aformat;
FvwmWindow *fwin;
unsigned char *indi;
unsigned long nitems, bytes_remain, oldprop;
indi = (unsigned char *)&oldprop;
DBUG("HandleGnomePropRequest","Routine Entered");
a = XInternAtom(dpy, XA_WIN_STATE, False);
for (fwin = Scr.FvwmRoot.next; fwin; fwin = fwin->next)
{
if (fwin->w == win)
break;
}
/*-----------------------------------------------------------------------
First change the props on the window so the gnome app knows we did
somthing.
-----------------------------------------------------------------------*/
#ifdef FVWM_DEBUG_MSGS
fvwm_msg(DBG, "HandleGnomePropRequest", "window is %d", fwin->w);
#endif
if (fwin == NULL)
return;
if (DO_IGNORE_GNOME_HINTS(fwin))
return;
#ifdef FVWM_DEBUG_MSGS
fvwm_msg(DBG, "HandleGnomePropRequest", "prop req is %d", prop);
fvwm_msg(DBG, "HandleGnomePropRequest", "propm req is %d", propm);
#endif
XGetWindowProperty(dpy, fwin->w, a, 0L, 3L, False, a,
&atype, &aformat, &nitems, &bytes_remain, &indi);
oldprop &= ~(propm);
oldprop |= (propm & prop);
#ifdef FVWM_DEBUG_MSGS
fvwm_msg(DBG, "HandleGnomePropRequest", "oldprop req is %d", oldprop);
#endif
XChangeProperty(dpy, fwin->w, a, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *)&oldprop, 1);
/*-----------------------------------------------------------------------
Then apply the requests
-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------
Sticky
-----------------------------------------------------------------------*/
if (propm & WIN_STATE_STICKY)
{
if (prop & WIN_STATE_STICKY)
{
SET_STICKY(fwin, 1);
}
else
{
SET_STICKY(fwin, 0);
}
DrawDecorations(fwin, DRAW_TITLE, (Scr.Hilite==fwin), True, None);
}
/*-----------------------------------------------------------------------
WindowShade
-----------------------------------------------------------------------*/
if (propm & WIN_STATE_SHADED)
{
if (prop & WIN_STATE_SHADED)
{
/* shade up */
old_execute_function(
"WindowShade True", fwin, ev, C_WINDOW, -1, 0, NULL);
}
else
{
/* shade down */
old_execute_function(
"WindowShade False", fwin, ev, C_WINDOW, -1, 0, NULL);
}
}
/*-----------------------------------------------------------------------
-----------------------------------------------------------------------*/
}
void
GNOME_ProxyButtonEvent(XEvent *ev)
{
switch (ev->type)
{
case ButtonPress:
XUngrabPointer(dpy, CurrentTime);
XSendEvent(dpy, __button_proxy, False, SubstructureNotifyMask, ev);
break;
case ButtonRelease:
XSendEvent(dpy, __button_proxy, False, SubstructureNotifyMask, ev);
break;
}
}
/* this is the function entered into FVWM's functions table */
void
CMD_GnomeButton(F_CMD_ARGS)
{
/* send off the button press event */
GNOME_ProxyButtonEvent(eventp);
}
#endif /* GNOME */
syntax highlighted by Code2HTML, v. 0.9.1