696 lines
18 KiB
C
696 lines
18 KiB
C
/* Copyright 1989 GROUPE BULL -- See license conditions in file COPYRIGHT
|
|
* Copyright 1989 Massachusetts Institute of Technology
|
|
*/
|
|
/***********************************************\
|
|
* *
|
|
* GWM: icccm.c *
|
|
* Miscellaneous utilities to enforce the ICCCM *
|
|
* *
|
|
\***********************************************/
|
|
|
|
#include "EXTERN.h"
|
|
#include <stdio.h>
|
|
#include "wool.h"
|
|
#include "wl_atom.h"
|
|
#include "wl_list.h"
|
|
#include "wl_string.h"
|
|
#include "gwm.h"
|
|
#include <X11/Xatom.h>
|
|
#include <X11/Xutil.h>
|
|
#include "wl_number.h"
|
|
|
|
extern XError(), NoXError();
|
|
DECLARE_strchr;
|
|
|
|
/* Used to tell a client that it has been moved
|
|
*/
|
|
|
|
SendSyntheticMoveEvent(cw)
|
|
ClientWindow cw;
|
|
{
|
|
XConfigureEvent event;
|
|
|
|
if(cw -> client_wob) /* do not send to ourselves */
|
|
return;
|
|
event.type = ConfigureNotify;
|
|
event.display = dpy;
|
|
event.event = cw -> client;
|
|
event.window = cw -> client;
|
|
event.x = cw -> inner_x + cw ->box.x + cw -> box.borderwidth;
|
|
event.y = cw -> inner_y + cw ->box.y + cw -> box.borderwidth;
|
|
event.width = cw -> inner_width;
|
|
event.height = cw -> inner_height;
|
|
event.border_width = cw -> inner_borderwidth;
|
|
event.above = cw -> hook;
|
|
event.override_redirect = False;
|
|
Trace('e', ("SendSyntheticMoveEvent: event 0x%x window 0x%x x %d y %d w %d h %d bw %d above 0x%x\n", event.event, event.window, event.x, event.y, event.width, event.height, event.border_width, event.above));
|
|
XSendEvent(dpy, cw -> client, False, StructureNotifyMask,
|
|
(XEvent *) &event);
|
|
}
|
|
|
|
/* for defining another icon for WM_STATE property
|
|
*/
|
|
|
|
WOOL_OBJECT
|
|
wool_wm_state_user_icon_get()
|
|
{
|
|
if (TargetWindow -> cached_props -> user_icon)
|
|
return (WOOL_OBJECT)
|
|
WLNumber_make(TargetWindow -> cached_props -> user_icon);
|
|
else
|
|
return NIL;
|
|
}
|
|
|
|
WOOL_OBJECT
|
|
wool_wm_state_user_icon_set(number)
|
|
WOOL_Number number;
|
|
{
|
|
must_be_number(number, 0);
|
|
TargetWindow -> cached_props -> user_icon = (ClientWindow)
|
|
number -> number;
|
|
Update_XA_WM_STATE(TargetWindow);
|
|
return (WOOL_OBJECT) number;
|
|
}
|
|
|
|
/* updating this window's WM_STATE once another icon is defined
|
|
*/
|
|
|
|
WOOL_OBJECT
|
|
wool_wm_state_update(argc, argv)
|
|
int argc;
|
|
WOOL_Atom argv[];
|
|
{
|
|
int state = -1;
|
|
if (argc) {
|
|
if (argv[0] == WA_window)
|
|
state = WM_STATE_Normal;
|
|
else if (argv[0] == WA_icon)
|
|
state = WM_STATE_Iconified;
|
|
else if ((WOOL_OBJECT) argv[0] == NIL)
|
|
state = WM_STATE_Withdrawn;
|
|
}
|
|
if (!TargetWindow -> window -> client_wob)
|
|
Set_XA_WM_STATE(TargetWindow -> window, state);
|
|
return NIL;
|
|
}
|
|
|
|
/*&WN window-wm-state
|
|
* getting this window's WM_STATE once another icon is defined
|
|
*/
|
|
|
|
WOOL_OBJECT
|
|
wool_wm_state_get(argc, argv)
|
|
int argc;
|
|
WOOL_Number argv[];
|
|
{
|
|
ClientWindow cw = TargetWindow;
|
|
Atom actualtype;
|
|
int actualformat;
|
|
unsigned long nitems;
|
|
unsigned long bytesafter;
|
|
WM_STATE_PROP wm_state;
|
|
|
|
if (argc) {
|
|
must_be_number(argv[0], 0);
|
|
cw = (ClientWindow) argv[0] -> number;
|
|
}
|
|
cw = cw -> window;
|
|
if ((Success == XGetWindowProperty(dpy, cw -> client, XA_WM_STATE, 0,
|
|
WM_STATE_PROP_Length, False, XA_WM_STATE, &actualtype,
|
|
&actualformat, &nitems, &bytesafter,
|
|
(unsigned char **) &wm_state))
|
|
&& nitems && wm_state) {
|
|
switch (wm_state -> state) {
|
|
case WM_STATE_Iconified:
|
|
XFree(wm_state);
|
|
return (WOOL_OBJECT) WA_icon;
|
|
case WM_STATE_Normal:
|
|
XFree(wm_state);
|
|
return (WOOL_OBJECT) WA_window;
|
|
default:
|
|
XFree(wm_state);
|
|
}
|
|
}
|
|
return NIL;
|
|
}
|
|
|
|
/* Colormaps
|
|
* colormap focus management:
|
|
*/
|
|
|
|
WOOL_OBJECT
|
|
wool_set_colormap_focus(argc, argv)
|
|
int argc;
|
|
WOOL_Number argv[];
|
|
{
|
|
ClientWindow cw = TargetWindow;
|
|
|
|
if (argc) {
|
|
if (argv[0] == (WOOL_Number) NIL) {
|
|
GWM_set_default_colormap();
|
|
Context -> InstalledColormapCW = Context -> rootWob;
|
|
return NIL;
|
|
}
|
|
must_be_number(argv[0], 0);
|
|
cw = (ClientWindow) argv[0] -> number;
|
|
}
|
|
if (cw -> colormap) {
|
|
if (cw != Context -> InstalledColormapCW &&
|
|
(!Context -> InstalledColormapCW ||
|
|
cw -> colormap != Context -> InstalledColormapCW -> colormap))
|
|
XInstallColormap(dpy, cw -> colormap);
|
|
if (cw -> cached_props -> colormap_windows)
|
|
cw -> cached_props -> colormap_windows_index = 0;
|
|
} else {
|
|
GWM_set_default_colormap();
|
|
}
|
|
Context -> InstalledColormapCW = cw;
|
|
return NIL;
|
|
}
|
|
|
|
GWM_set_default_colormap()
|
|
{
|
|
if (Context -> InstalledColormapCW != Context -> rootWob &&
|
|
(!Context -> InstalledColormapCW ||
|
|
(Context -> InstalledColormapCW -> colormap &&
|
|
Context -> InstalledColormapCW -> colormap
|
|
!= Context -> rootWob -> colormap))) {
|
|
XInstallColormap(dpy, Context -> rootWob -> colormap);
|
|
Context -> InstalledColormapCW = Context -> rootWob;
|
|
}
|
|
}
|
|
|
|
/* Sub windows colormaps
|
|
* colormap focus management:
|
|
*/
|
|
|
|
WOOL_OBJECT
|
|
wool_set_subwindow_colormap_focus(argc, argv)
|
|
int argc;
|
|
WOOL_Number argv[];
|
|
{
|
|
ClientWindow cw = TargetWindow;
|
|
int index;
|
|
XWindowAttributes wa;
|
|
Colormap current_colormap;
|
|
|
|
if (argc) {
|
|
must_be_number(argv[0], 0);
|
|
index = argv[0] -> number;
|
|
}
|
|
if (cw == Context -> InstalledColormapCW &&
|
|
cw -> cached_props -> colormap_windows) {
|
|
if (argc) { /* absolute index */
|
|
cw -> cached_props -> colormap_windows_index =
|
|
index % cw -> cached_props -> colormap_windows_size;
|
|
XGetWindowAttributes(dpy,
|
|
cw -> cached_props -> colormap_windows[
|
|
cw -> cached_props -> colormap_windows_index], &wa);
|
|
if (wa.colormap)
|
|
XInstallColormap(dpy, wa.colormap);
|
|
} else { /* increment index */
|
|
XGetWindowAttributes(dpy,
|
|
cw -> cached_props -> colormap_windows[
|
|
cw -> cached_props -> colormap_windows_index], &wa);
|
|
current_colormap = wa.colormap;
|
|
for (index = cw -> cached_props -> colormap_windows_index + 1;
|
|
index % cw -> cached_props -> colormap_windows_size !=
|
|
cw -> cached_props -> colormap_windows_index;
|
|
index++) {
|
|
index = index % cw -> cached_props -> colormap_windows_size;
|
|
XGetWindowAttributes(dpy,
|
|
cw -> cached_props -> colormap_windows[index], &wa);
|
|
if (wa.colormap != current_colormap) {
|
|
cw -> cached_props -> colormap_windows_index = index;
|
|
XInstallColormap(dpy, wa.colormap);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NIL;
|
|
}
|
|
|
|
|
|
/* updating a colormap for a watched window in a WM_COLORMAP_WINDOWS list
|
|
*/
|
|
|
|
Update_colormap_in_colormap_windows_list(evt)
|
|
XColormapEvent *evt;
|
|
{
|
|
ClientWindow cw;
|
|
|
|
if (ContextOfXWindow(evt -> window))
|
|
return; /* if no more window, returns */
|
|
cw = Context -> InstalledColormapCW;
|
|
if (cw && cw -> cached_props -> colormap_windows_index &&
|
|
evt -> window == cw -> cached_props -> colormap_windows[
|
|
cw -> cached_props -> colormap_windows_index]
|
|
&& evt -> new)
|
|
if (evt -> colormap)
|
|
XInstallColormap(dpy, evt -> colormap);
|
|
else
|
|
XInstallColormap(dpy, Context->rootWob -> colormap);
|
|
}
|
|
|
|
/* declare accepted icons sizes for future clients
|
|
*/
|
|
|
|
WOOL_OBJECT
|
|
wool_set_wm_icon_sizes(argc, argv)
|
|
int argc;
|
|
WOOL_Number argv[];
|
|
{
|
|
int i;
|
|
XIconSize icon_sizes;
|
|
|
|
if(argc != 6)
|
|
return wool_error(BAD_NUMBER_OF_ARGS, argc);
|
|
for(i=0;i<6;i++){
|
|
must_be_number(argv[i], i);
|
|
}
|
|
icon_sizes.min_width = argv[0] -> number;
|
|
icon_sizes.min_height = argv[1] -> number;
|
|
icon_sizes.max_width = argv[2] -> number;
|
|
icon_sizes.max_height = argv[3] -> number;
|
|
icon_sizes.width_inc = argv[4] -> number;
|
|
icon_sizes.height_inc = argv[5] -> number;
|
|
XSetIconSizes(dpy, Context->root, &icon_sizes, 6);
|
|
return NIL;
|
|
}
|
|
|
|
/* get WM_COMMAND
|
|
*/
|
|
|
|
WOOL_OBJECT
|
|
wool_get_wm_command()
|
|
{
|
|
Atom actual_type;
|
|
int actual_format = 0;
|
|
unsigned long nitems = 0L, leftover = 0L;
|
|
unsigned char *prop = NULL;
|
|
WOOL_List list;
|
|
int i, nstrings = 0, n;
|
|
unsigned char *p;
|
|
|
|
if (XGetWindowProperty (dpy, TargetWindow -> client, XA_WM_COMMAND,
|
|
0L, 1000000L, False,
|
|
AnyPropertyType, &actual_type, &actual_format,
|
|
&nitems, &leftover, &prop) == Success &&
|
|
actual_type != None && prop && nitems) {
|
|
for (i = 0; i < nitems; i++)
|
|
if (prop[i] == '\0')
|
|
nstrings ++;
|
|
list = wool_list_make(nstrings);
|
|
p = prop;
|
|
for (n = 0; n < nstrings; n++) {
|
|
increase_reference(list -> list[n] =
|
|
(WOOL_OBJECT) WLString_make(p));
|
|
while(*p++);
|
|
}
|
|
XFree(prop);
|
|
return (WOOL_OBJECT) list;
|
|
}
|
|
|
|
return NIL;
|
|
|
|
}
|
|
|
|
/* When not-yet mapped configures its window, we must execute the
|
|
* configure request!
|
|
*/
|
|
|
|
ConfigureUnmappedWindow(evt)
|
|
XConfigureRequestEvent *evt;
|
|
{
|
|
XWindowChanges window_changes;
|
|
|
|
window_changes.x = evt -> x;
|
|
window_changes.y = evt -> y;
|
|
window_changes.width = evt -> width;
|
|
window_changes.height = evt -> height;
|
|
window_changes.border_width = evt -> border_width;
|
|
window_changes.sibling = evt -> above;
|
|
window_changes.stack_mode = evt -> detail;
|
|
|
|
TrapXErrors(XConfigureWindow(dpy,
|
|
evt -> window, evt -> value_mask,
|
|
&window_changes));
|
|
}
|
|
|
|
/* PROTOCOLS communication via user events
|
|
*/
|
|
|
|
send_protocol_message(window, protocol, timestamp, data_size, data)
|
|
Window window;
|
|
Atom protocol;
|
|
Time timestamp; /* 0 for CurrentTime */
|
|
int data_size; /* 0 to 3 32-bit quantities */
|
|
Card32 *data;
|
|
{
|
|
XClientMessageEvent event;
|
|
|
|
event.type = ClientMessage;
|
|
event.window = window;
|
|
event.message_type = XA_WM_PROTOCOLS;
|
|
event.format = 32;
|
|
event.data.l[0] = (long) protocol;
|
|
if (timestamp)
|
|
event.data.l[1] = (long) timestamp;
|
|
else
|
|
event.data.l[1] = (long) CurrentTime;
|
|
data_size = Min(3, data_size);
|
|
if (data_size)
|
|
bcopy(data, &(event.data.l[2]), data_size * 4);
|
|
if (data_size < 3)
|
|
bzero(&(event.data.l[2 + data_size]), (3 - data_size) * 4);
|
|
|
|
TrapXErrors(XSendEvent(dpy, window, False, 0, (XEvent *) &event));
|
|
}
|
|
|
|
/* WM_DELETE_WINDOW
|
|
* if window participate in protocol, sends message and returns TRUE
|
|
* else unmaps it and its associated icon (go to withdrawn) and returns NIL
|
|
*/
|
|
|
|
WOOL_OBJECT
|
|
wool_delete_window(argc, argv)
|
|
int argc;
|
|
WOOL_Number *argv;
|
|
{
|
|
ClientWindow cw = TargetWindow -> window;
|
|
|
|
if (argc) {
|
|
must_be_number(argv[0], 0);
|
|
cw = ((ClientWindow) argv[0] -> number) -> window;
|
|
}
|
|
if (cw -> client
|
|
&& cw -> cached_props -> wm_delete_window) {
|
|
send_protocol_message(cw -> client, XA_WM_DELETE_WINDOW,
|
|
GWMTime, 0, 0);
|
|
return TRU;
|
|
} else {
|
|
return NIL;
|
|
}
|
|
}
|
|
|
|
/* WM_SAVE_YOURSELF
|
|
* if window participate in protocol, sends message and returns TRUE
|
|
* else returns NIL
|
|
*/
|
|
|
|
WOOL_OBJECT
|
|
wool_save_yourself(argc, argv)
|
|
int argc;
|
|
WOOL_Number *argv;
|
|
{
|
|
ClientWindow cw = TargetWindow -> window;
|
|
|
|
if (argc) {
|
|
must_be_number(argv[0], 0);
|
|
cw = ((ClientWindow) argv[0] -> number) -> window;
|
|
}
|
|
if (cw -> client && !cw -> client_wob
|
|
&& cw -> cached_props -> wm_save_yourself) {
|
|
send_protocol_message(cw -> client, XA_WM_SAVE_YOURSELF,
|
|
GWMTime, 0, 0);
|
|
return TRU;
|
|
} else {
|
|
return NIL;
|
|
}
|
|
}
|
|
|
|
/* Gravity: 123
|
|
* 456
|
|
* 789
|
|
* (Gravity - 1) % 3: x: 0 1 2
|
|
* (Gravity - 1) / 3: y: 0 1 2
|
|
* 1 is center, -1 is just client mustn't move
|
|
*/
|
|
|
|
GetWinGravityHint(cw, xgrav, ygrav)
|
|
ClientWindow cw;
|
|
int *xgrav, *ygrav;
|
|
{
|
|
#ifdef NOBASEDIMS
|
|
*xgrav = *ygrav = -1;
|
|
#else /* NOBASEDIMS */
|
|
int grav = cw -> cached_props -> normal_hints.win_gravity;
|
|
if (cw -> cached_props -> normal_hints.flags & PWinGravity) {
|
|
if ((grav <= ForgetGravity) || (grav >= StaticGravity))
|
|
*xgrav = *ygrav = -1;
|
|
else {
|
|
*xgrav = (grav - 1) % 3;
|
|
*ygrav = (grav - 1) / 3;
|
|
}
|
|
} else {
|
|
*xgrav = *ygrav = 0; /* NorthWest is default */
|
|
}
|
|
#endif /* NOBASEDIMS */
|
|
}
|
|
|
|
|
|
/* obeys the Window Gravity hints
|
|
* direction is 1 on decoration, 0 on un-decoration
|
|
* adjusts in place the cw->box.x/y dims
|
|
*/
|
|
|
|
ObeyWinGravityHint(cw, direction)
|
|
ClientWindow cw;
|
|
int direction;
|
|
{
|
|
int x_gravity, y_gravity;
|
|
int x_offset, y_offset;
|
|
|
|
#ifdef NOBASEDIMS /* old pre -R4 code */
|
|
if (!GWM_ProcessingExistingWindows
|
|
&& !cw -> cached_props -> new_normal_hints) {
|
|
if (cw -> cached_props -> normal_hints.flags & USPosition) {
|
|
cw -> box.x = cw -> cached_props -> normal_hints.x;
|
|
cw -> box.y = cw -> cached_props -> normal_hints.y;
|
|
} else if (cw -> cached_props -> normal_hints.flags & PPosition) {
|
|
cw -> box.x = cw -> cached_props -> normal_hints.x;
|
|
cw -> box.y = cw -> cached_props -> normal_hints.y;
|
|
}
|
|
}
|
|
#endif /* NOBASEDIMS */
|
|
|
|
GetWinGravityHint(cw, &x_gravity, &y_gravity);
|
|
|
|
switch(x_gravity) {
|
|
case 0: /* west */
|
|
x_offset = 0;
|
|
break;
|
|
/* I dont beleive in this. I think 1 means that it shouldn't move in */
|
|
/* this direction, like the default below. / aho@nada.kth.se 950302 */
|
|
/* case 1: */ /* center */
|
|
/* x_offset = cw -> old_inner_borderwidth - cw -> box.borderwidth */
|
|
/* + (cw -> inner_width - cw -> box.width)/2; */
|
|
/* break; */
|
|
case 2: /* east */
|
|
x_offset = cw -> inner_width - cw -> box.width
|
|
+ 2 * (cw -> old_inner_borderwidth - cw -> box.borderwidth);
|
|
break;
|
|
default: /* client don't move */
|
|
x_offset = cw -> old_inner_borderwidth - cw -> inner_borderwidth
|
|
- cw -> inner_x - cw -> box.borderwidth;
|
|
}
|
|
|
|
switch(y_gravity) {
|
|
case 0: /* north */
|
|
y_offset = 0;
|
|
break;
|
|
/* I dont beleive in this. I think 1 means that it shouldn't move in */
|
|
/* this direction, like the default below. / aho@nada.kth.se 950302 */
|
|
/* case 1: */ /* center */
|
|
/* y_offset = cw -> old_inner_borderwidth - cw -> box.borderwidth */
|
|
/* + (cw -> inner_height - cw -> box.height)/2; */
|
|
/* break; */
|
|
case 2: /* south */
|
|
y_offset = cw -> inner_height - cw -> box.height
|
|
+ 2 * (cw -> old_inner_borderwidth - cw -> box.borderwidth);
|
|
break;
|
|
default: /* client don't move */
|
|
y_offset = cw -> old_inner_borderwidth - cw -> inner_borderwidth
|
|
- cw -> inner_y - cw -> box.borderwidth;
|
|
}
|
|
trace1(6, "window 0x%x:" , cw->client);
|
|
trace2(6, "at %d, %d, offseted by:" , cw->box.x, cw->box.y);
|
|
trace2(6, " %d, %d\n" , x_offset, y_offset);
|
|
cw->box.x += (direction ? x_offset : - x_offset);
|
|
cw->box.y += (direction ? y_offset : - y_offset);
|
|
}
|
|
|
|
|
|
|
|
/* misc utilities */
|
|
|
|
/* replaces ., blanks, and * by _ for using as class in Xrm
|
|
* returns arg if not changed, new string if changed so as not to modify
|
|
* the original string
|
|
*/
|
|
|
|
WOOL_OBJECT
|
|
MakeResourceIdentifier(string)
|
|
WOOL_String string;
|
|
{
|
|
char *p;
|
|
WOOL_String new_string = 0;
|
|
|
|
must_be_string(string, 1);
|
|
for (p = string->string; *p; p++)
|
|
if (*p == '.' || *p == '*' || *p == ' ' || *p == '\t') {
|
|
if (!new_string)
|
|
new_string = WLString_make(string->string);
|
|
new_string->string[p - string->string] = '_';
|
|
}
|
|
|
|
if (new_string)
|
|
return (WOOL_OBJECT) new_string;
|
|
else
|
|
return (WOOL_OBJECT) string;
|
|
}
|
|
|
|
/* create an unmapped window whose ID is stored on the root window of each
|
|
* managed screen in the GWM_RUNNING property
|
|
* current screen is given in the context
|
|
*/
|
|
|
|
CreateGwmLabelWindow()
|
|
{
|
|
XSetWindowAttributes wa;
|
|
|
|
|
|
wa.override_redirect = True;
|
|
Context->GwmWindow = XCreateWindow (dpy, Context->root,
|
|
-100, -100, 10, 10, 0, 0,
|
|
InputOnly, CopyFromParent,
|
|
CWOverrideRedirect,
|
|
&wa);
|
|
XChangeProperty(dpy, Context->root, XA_GWM_RUNNING, XA_GWM_RUNNING,
|
|
32, PropModeReplace, (unsigned char *) &(Context->GwmWindow), 1);
|
|
XChangeProperty(dpy, Context->GwmWindow, XA_GWM_RUNNING, XA_GWM_RUNNING,
|
|
32, PropModeReplace, (unsigned char *) &(Context->GwmWindow), 1);
|
|
}
|
|
|
|
/* FindToplevelWindow
|
|
* given a window, move back in hierarchy to return the toplevel one
|
|
* If given root, returns 0
|
|
*/
|
|
|
|
Window
|
|
FindToplevelWindow(w)
|
|
Window w;
|
|
{
|
|
Window parent = 0;
|
|
Window *children; /* list of root sons */
|
|
unsigned int nchildren; /* number of children */
|
|
Window root;
|
|
|
|
if (w == Context->root) {
|
|
return 0;
|
|
}
|
|
|
|
for (;;) {
|
|
if(!XQueryTree(dpy, w, &root, &parent, &children, &nchildren)) {
|
|
return 0; /* failed */
|
|
}
|
|
XFreeN(children);
|
|
if (parent == Context->root) {
|
|
return w;
|
|
}
|
|
w = parent;
|
|
}
|
|
}
|
|
|
|
/* IsAToplevelWindow
|
|
* Examine a non-gwm decorated window to see if it is legal to decorate it
|
|
*/
|
|
|
|
int
|
|
IsAToplevelWindow(w)
|
|
Window w;
|
|
{
|
|
Window dummywin, parent; /* dummy parent */
|
|
Window *children; /* list of root sons */
|
|
unsigned int nchildren; /* number of children */
|
|
|
|
if (XQueryTree(dpy, w, &dummywin, &parent, &children, &nchildren)) {
|
|
XFreeN(children);
|
|
if (parent == Context -> root) { /* w is son of root, OK */
|
|
return 1;
|
|
}
|
|
} /* then not valid! */
|
|
return 0;
|
|
}
|
|
|
|
/* ClientWindowAncestorOfWindow
|
|
* looks into all the ancestors to eventually find a ClientWindow, which would
|
|
* be returned, or 0
|
|
*/
|
|
|
|
ClientWindow
|
|
ClientWindowAncestorOfWindow(w)
|
|
Window w;
|
|
{
|
|
Window toplevel = FindToplevelWindow(w);
|
|
ClientWindow cw;
|
|
if (toplevel
|
|
&& (cw = (ClientWindow) LookUpWob(toplevel))
|
|
&& (cw -> status & ClientWindowStatus)) {
|
|
return cw;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* DecoratedWindow
|
|
* given a X window, returns the GWM window associated to, decorating it in
|
|
* the process if needed.
|
|
* used to look for window group leaders and transient_for masters
|
|
* returns 0 if failed
|
|
*/
|
|
|
|
ClientWindow
|
|
DecoratedWindow(w)
|
|
Window w;
|
|
{
|
|
ClientWindow tw;
|
|
ClientWindow cw = (ClientWindow) LookUpClient(w);
|
|
if (cw) {
|
|
return cw;
|
|
} else {
|
|
cw = (ClientWindow) LookUpWob(w);
|
|
if (cw) {
|
|
if (cw->status | ClientWindowStatus) {
|
|
return 0;
|
|
} else {
|
|
Window win = FindToplevelWindow(w);
|
|
|
|
if (win) {
|
|
ClientWindow old_windec = GWM_window_being_decorated;
|
|
int old_reenter = GWM_reenter_on_opens;
|
|
GWM_reenter_on_opens = 0;
|
|
cw = (ClientWindow) DecorateWindow(win, Context->rootWob, 1, 0);
|
|
GWM_reenter_on_opens = old_reenter;
|
|
GWM_window_being_decorated = old_windec;
|
|
return cw;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
} else if (tw = ClientWindowAncestorOfWindow(w)) {
|
|
return tw;
|
|
} else if (IsAToplevelWindow(w)) {
|
|
ClientWindow old_windec = GWM_window_being_decorated;
|
|
int old_reenter = GWM_reenter_on_opens;
|
|
GWM_reenter_on_opens = 0;
|
|
cw = (ClientWindow) DecorateWindow(w, Context->rootWob, 1, 0);
|
|
GWM_reenter_on_opens = old_reenter;
|
|
GWM_window_being_decorated = old_windec;
|
|
return cw;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|