Newer
Older
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
xfwm4 - (c) 2002-2007 Olivier Fourdan
Olivier Fourdan
committed
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <libxfce4util/libxfce4util.h>
Olivier Fourdan
committed
#include "compositor.h"
#include "focus.h"
Olivier Fourdan
committed
#include "icons.h"
#include "misc.h"
Olivier Fourdan
committed
#include "netwm.h"
#include "placement.h"
Olivier Fourdan
committed
#include "poswin.h"
Olivier Fourdan
committed
#include "screen.h"
Olivier Fourdan
committed
#include "settings.h"
Olivier Fourdan
committed
#include "stacking.h"
#include "startup_notification.h"
Olivier Fourdan
committed
#include "tabwin.h"
#include "transients.h"
#include "wireframe.h"
#include "workspaces.h"
#include "event_filter.h"
Olivier Fourdan
committed
/* Event mask definition */
#define POINTER_EVENT_MASK \
ButtonPressMask|\
Olivier Fourdan
committed
ButtonReleaseMask
Olivier Fourdan
committed
#define FRAME_EVENT_MASK \
SubstructureNotifyMask|\
Olivier Fourdan
committed
SubstructureRedirectMask|\
Olivier Fourdan
committed
FocusChangeMask|\
Olivier Fourdan
committed
#define CLIENT_EVENT_MASK \
StructureNotifyMask|\
Olivier Fourdan
committed
PropertyChangeMask
Olivier Fourdan
committed
#define BUTTON_EVENT_MASK \
EnterWindowMask|\
LeaveWindowMask
Olivier Fourdan
committed
/* Useful macros */
Olivier Fourdan
committed
(c->wmhints->initial_state == IconicState) && \
Olivier Fourdan
committed
!clientIsValidTransientOrModal (c))
#define OPACITY_SET_STEP (guint) 0x16000000
#define OPACITY_SET_MIN (guint) 0x40000000
Olivier Fourdan
committed
typedef struct _MoveResizeData MoveResizeData;
struct _MoveResizeData
{
Olivier Fourdan
committed
gboolean use_keys;
gboolean grab;
gboolean is_transient;
Olivier Fourdan
committed
gboolean move_resized;
gboolean released;
int button;
int cancel_x, cancel_y; /* for cancellation (either position or size) */
int cancel_workspace;
Olivier Fourdan
committed
int mx, my;
int ox, oy;
int oldw, oldh;
int corner;
Olivier Fourdan
committed
Poswin *poswin;
Olivier Fourdan
committed
};
typedef struct _ClientCycleData ClientCycleData;
struct _ClientCycleData
{
Client *c;
Tabwin *tabwin;
Olivier Fourdan
committed
Window wireframe;
Olivier Fourdan
committed
int cycle_range;
};
typedef struct _ButtonPressData ButtonPressData;
struct _ButtonPressData
{
int b;
Client *c;
};
Olivier Fourdan
committed
/* Forward decl */
Olivier Fourdan
committed
clientUpdateIconPix (Client * c);
Display *
clientGetXDisplay (Client * c)
{
g_return_val_if_fail (c, NULL);
return myScreenGetXDisplay (c->screen_info);
void
clientInstallColormaps (Client * c)
{
XWindowAttributes attr;
Olivier Fourdan
committed
g_return_if_fail (c != NULL);
TRACE ("entering clientInstallColormaps");
for (i = c->ncmap - 1; i >= 0; i--)
{
XGetWindowAttributes (clientGetXDisplay (c), c->cmap_windows[i], &attr);
XInstallColormap (clientGetXDisplay (c), attr.colormap);
if (c->cmap_windows[i] == c->window)
{
installed = TRUE;
}
}
if ((!installed) && (c->cmap))
XInstallColormap (clientGetXDisplay (c), c->cmap);
void
clientUpdateColormaps (Client * c)
g_return_if_fail (c != NULL);
TRACE ("entering clientUpdateColormaps");
XFree (c->cmap_windows);
if (!XGetWMColormapWindows (clientGetXDisplay (c), c->window, &c->cmap_windows, &c->ncmap))
Olivier Fourdan
committed
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
void
clientUpdateName (Client * c)
{
ScreenInfo *screen_info;
DisplayInfo *display_info;
gchar *name;
g_return_if_fail (c != NULL);
TRACE ("entering clientUpdateName");
screen_info = c->screen_info;
display_info = screen_info->display_info;
getWindowName (display_info, c->window, &name);
if (name)
{
if (c->name)
{
if (strcmp (name, c->name))
{
g_free (c->name);
c->name = name;
FLAG_SET (c->flags, CLIENT_FLAG_NAME_CHANGED);
frameQueueDraw (c);
}
}
}
}
clientUpdateAllFrames (ScreenInfo *screen_info, int mask)
Olivier Fourdan
committed
{
Olivier Fourdan
committed
XWindowChanges wc;
Olivier Fourdan
committed
TRACE ("entering clientRedrawAllFrames");
Olivier Fourdan
committed
myScreenGrabPointer (screen_info, EnterWindowMask, None, myDisplayGetCurrentTime (screen_info->display_info));
for (c = screen_info->clients, i = 0; i < screen_info->client_count; c = c->next, i++)
Olivier Fourdan
committed
unsigned long configure_flags = 0L;
if (mask & UPDATE_BUTTON_GRABS)
{
clientUngrabButtons (c);
clientGrabButtons (c);
clientGrabMouseButton (c);
}
if (mask & UPDATE_CACHE)
{
Olivier Fourdan
committed
clientUpdateIconPix (c);
}
if (mask & UPDATE_GRAVITY)
{
clientGravitate (c, REMOVE);
clientGravitate (c, APPLY);
setNetFrameExtents (screen_info->display_info,
c->window,
Olivier Fourdan
committed
frameTop (c),
frameLeft (c),
frameRight (c),
frameBottom (c));
Olivier Fourdan
committed
configure_flags |= CFG_FORCE_REDRAW;
mask &= ~UPDATE_FRAME;
}
if (mask & UPDATE_MAXIMIZE)
{
unsigned long maximization_flags = 0L;
/* Recompute size and position of maximized windows */
if (FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_HORIZ | CLIENT_FLAG_MAXIMIZED_VERT))
{
Olivier Fourdan
committed
maximization_flags |= FLAG_TEST (c->flags,
CLIENT_FLAG_MAXIMIZED_HORIZ) ? WIN_STATE_MAXIMIZED_HORIZ : 0;
maximization_flags |= FLAG_TEST (c->flags,
CLIENT_FLAG_MAXIMIZED_VERT) ? WIN_STATE_MAXIMIZED_VERT : 0;
Olivier Fourdan
committed
Olivier Fourdan
committed
/* Force an update by clearing the internal flags */
FLAG_UNSET (c->flags, CLIENT_FLAG_MAXIMIZED_HORIZ | CLIENT_FLAG_MAXIMIZED_VERT);
clientToggleMaximized (c, maximization_flags, FALSE);
Olivier Fourdan
committed
Olivier Fourdan
committed
configure_flags |= CFG_FORCE_REDRAW;
mask &= ~UPDATE_FRAME;
Olivier Fourdan
committed
}
}
if (configure_flags != 0L)
{
Olivier Fourdan
committed
wc.x = c->x;
wc.y = c->y;
wc.width = c->width;
wc.height = c->height;
clientConfigure (c, &wc, CWX | CWY | CWWidth | CWHeight, configure_flags);
}
if (mask & UPDATE_FRAME)
{
Olivier Fourdan
committed
frameDraw (c, TRUE);
Olivier Fourdan
committed
Olivier Fourdan
committed
}
myScreenUngrabPointer (screen_info);
Olivier Fourdan
committed
}
Olivier Fourdan
committed
void
clientGrabButtons (Client * c)
{
Olivier Fourdan
committed
Olivier Fourdan
committed
g_return_if_fail (c != NULL);
TRACE ("entering clientGrabButtons");
TRACE ("grabbing buttons for client \"%s\" (0x%lx)", c->name, c->window);
Olivier Fourdan
committed
screen_info = c->screen_info;
if (screen_info->params->easy_click)
{
Olivier Fourdan
committed
grabButton(clientGetXDisplay (c), AnyButton, screen_info->params->easy_click, c->window);
Olivier Fourdan
committed
}
Olivier Fourdan
committed
}
void
clientUngrabButtons (Client * c)
{
g_return_if_fail (c != NULL);
TRACE ("entering clientUngrabButtons");
TRACE ("grabbing buttons for client \"%s\" (0x%lx)", c->name, c->window);
XUngrabButton (clientGetXDisplay (c), AnyButton, AnyModifier, c->window);
static gboolean
urgent_cb (gpointer data)
{
FLAG_TOGGLE (c->xfwm_flags, XFWM_FLAG_SEEN_ACTIVE);
Olivier Fourdan
committed
frameDraw (c, FALSE);
}
return (TRUE);
}
void
clientUpdateUrgency (Client *c)
{
g_return_if_fail (c != NULL);
TRACE ("entering clientUpdateUrgency");
FLAG_UNSET (c->xfwm_flags, XFWM_FLAG_SEEN_ACTIVE);
Olivier Fourdan
committed
frameDraw (c, FALSE);
c->blink_timeout_id = 0;
if ((c->wmhints) && (c->wmhints->flags & XUrgencyHint))
{
if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_VISIBLE))
{
g_timeout_add_full (G_PRIORITY_DEFAULT,
CLIENT_BLINK_TIMEOUT,
Olivier Fourdan
committed
(GtkFunction) urgent_cb,
(gpointer) c, NULL);
if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_SEEN_ACTIVE)
&& !FLAG_TEST (c->wm_flags, WM_FLAG_URGENT)
&& (c != clientGetFocus ()))
FLAG_UNSET (c->xfwm_flags, XFWM_FLAG_SEEN_ACTIVE);
Olivier Fourdan
committed
frameDraw (c, FALSE);
void
clientCoordGravitate (Client * c, int mode, int *x, int *y)
g_return_if_fail (c != NULL);
TRACE ("entering clientCoordGravitate");
c->gravity = c->size->flags & PWinGravity ? c->size->win_gravity : NorthWestGravity;
case CenterGravity:
dx = (c->border_width * 2) - ((frameLeft (c) +
frameRight (c)) / 2);
dy = (c->border_width * 2) - ((frameTop (c) +
frameBottom (c)) / 2);
break;
case NorthGravity:
dx = (c->border_width * 2) - ((frameLeft (c) +
frameRight (c)) / 2);
dy = frameTop (c);
break;
case SouthGravity:
dx = (c->border_width * 2) - ((frameLeft (c) +
frameRight (c)) / 2);
dy = (c->border_width * 2) - frameBottom (c);
break;
case EastGravity:
dx = (c->border_width * 2) - frameRight (c);
dy = (c->border_width * 2) - ((frameTop (c) +
frameBottom (c)) / 2);
break;
case WestGravity:
dx = frameLeft (c);
dy = (c->border_width * 2) - ((frameTop (c) +
frameBottom (c)) / 2);
break;
case NorthWestGravity:
dx = frameLeft (c);
dy = frameTop (c);
break;
case NorthEastGravity:
dx = (c->border_width * 2) - frameRight (c);
dy = frameTop (c);
break;
case SouthWestGravity:
dx = frameLeft (c);
dy = (c->border_width * 2) - frameBottom (c);
break;
case SouthEastGravity:
dx = (c->border_width * 2) - frameRight (c);
dy = (c->border_width * 2) - frameBottom (c);
break;
default:
dx = 0;
dy = 0;
break;
*x = *x + (dx * mode);
*y = *y + (dy * mode);
}
void
clientGravitate (Client * c, int mode)
g_return_if_fail (c != NULL);
TRACE ("entering clientGravitate");
clientCoordGravitate (c, mode, &x, &y);
clientComputeWidth (Client * c, int *w)
g_return_if_fail (c != NULL);
g_return_if_fail (w != NULL);
TRACE ("entering clientComputeWidth");
/* Bypass resize increment and max sizes for fullscreen */
if (!FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN)
&& !(FLAG_TEST_ALL (c->flags, CLIENT_FLAG_MAXIMIZED)
&& (c->screen_info->params->borderless_maximize)))
if ((c->size->flags & PResizeInc) && (c->size->width_inc))
w2 = (*w - c->size->min_width) / c->size->width_inc;
*w = c->size->min_width + (w2 * c->size->width_inc);
}
if (c->size->flags & PMaxSize)
{
if (*w > c->size->max_width)
{
*w = c->size->max_width;
}
if (c->size->flags & PMinSize)
if (*w < c->size->min_width)
*w = c->size->min_width;
if (*w < 1)
*w = 1;
clientSetWidth (Client * c, int w)
{
int temp;
g_return_if_fail (c != NULL);
TRACE ("entering clientSetWidth");
TRACE ("setting width %i for client \"%s\" (0x%lx)", w, c->name, c->window);
temp = w;
clientComputeWidth (c, &temp);
c->width = temp;
}
static void
clientComputeHeight (Client * c, int *h)
g_return_if_fail (c != NULL);
TRACE ("entering clientComputeHeight");
/* Bypass resize increment and max sizes for fullscreen */
if (!FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN)
&& !(FLAG_TEST_ALL (c->flags, CLIENT_FLAG_MAXIMIZED)
&& (c->screen_info->params->borderless_maximize)))
if ((c->size->flags & PResizeInc) && (c->size->height_inc))
Olivier Fourdan
committed
{
h2 = (*h - c->size->min_height) / c->size->height_inc;
*h = c->size->min_height + (h2 * c->size->height_inc);
}
if (c->size->flags & PMaxSize)
{
if (*h > c->size->max_height)
{
*h = c->size->max_height;
}
Olivier Fourdan
committed
if (c->size->flags & PMinSize)
if (*h < c->size->min_height)
*h = c->size->min_height;
if (*h < 1)
*h = 1;
static void
clientSetHeight (Client * c, int h)
{
int temp;
g_return_if_fail (c != NULL);
TRACE ("entering clientSetHeight");
TRACE ("setting height %i for client \"%s\" (0x%lx)", h, c->name, c->window);
temp = h;
clientComputeHeight (c, &temp);
c->height = temp;
}
/* clientConstrainRatio - adjust the given width and height to account for
the constraints imposed by size hints
The aspect ratio stuff, is borrowed from uwm's CheckConsistency routine.
*/
#define MAKE_MULT(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
clientConstrainRatio (Client * c, int *w, int *h, int corner)
{
g_return_if_fail (c != NULL);
TRACE ("entering clientConstrainRatio");
TRACE ("client \"%s\" (0x%lx)", c->name, c->window);
if (c->size->flags & PAspect)
{
int xinc, yinc, minx, miny, maxx, maxy, delta;
xinc = c->size->width_inc;
yinc = c->size->height_inc;
minx = c->size->min_aspect.x;
miny = c->size->min_aspect.y;
maxx = c->size->max_aspect.x;
maxy = c->size->max_aspect.y;
if ((minx * *h > miny * *w) && (miny) &&
((corner == CORNER_COUNT + SIDE_TOP) || (corner == CORNER_COUNT + SIDE_BOTTOM)))
delta = MAKE_MULT (minx * *h / miny - *w, xinc);
if (!(c->size->flags & PMaxSize) ||
(*w + delta <= c->size->max_width))
*w += delta;
if ((minx * *h > miny * *w) && (minx))
delta = MAKE_MULT (*h - *w * miny / minx, yinc);
if (!(c->size->flags & PMinSize) ||
(*h - delta >= c->size->min_height))
*h -= delta;
delta = MAKE_MULT (minx * *h / miny - *w, xinc);
Olivier Fourdan
committed
if (!(c->size->flags & PMaxSize) ||
(*w + delta <= c->size->max_width))
*w += delta;
if ((maxx * *h < maxy * *w) && (maxx) &&
((corner == CORNER_COUNT + SIDE_LEFT) || (corner == CORNER_COUNT + SIDE_RIGHT)))
delta = MAKE_MULT (*w * maxy / maxx - *h, yinc);
if (!(c->size->flags & PMaxSize) ||
(*h + delta <= c->size->max_height))
*h += delta;
if ((maxx * *h < maxy * *w) && (maxy))
delta = MAKE_MULT (*w - maxx * *h / maxy, xinc);
if (!(c->size->flags & PMinSize) ||
(*w - delta >= c->size->min_width))
Olivier Fourdan
committed
{
*w -= delta;
delta = MAKE_MULT (*w * maxy / maxx - *h, yinc);
Olivier Fourdan
committed
if (!(c->size->flags & PMaxSize) ||
(*h + delta <= c->size->max_height))
*h += delta;
#define WIN_MOVED (mask & (CWX | CWY))
#define WIN_RESIZED (mask & (CWWidth | CWHeight))
static void
clientConfigureWindows (Client * c, XWindowChanges * wc, unsigned long mask, unsigned short flags)
{
unsigned long change_mask;
XWindowChanges change_values;
Olivier Fourdan
committed
change_mask = (mask & (CWX | CWY | CWWidth | CWHeight));
if (flags & CFG_FORCE_REDRAW)
Olivier Fourdan
committed
change_mask |= (CWX | CWY);
Olivier Fourdan
committed
if (change_mask & (CWX | CWY | CWWidth | CWHeight))
{
change_values.x = frameX (c);
change_values.y = frameY (c);
change_values.width = frameWidth (c);
change_values.height = frameHeight (c);
XConfigureWindow (clientGetXDisplay (c), c->frame, change_mask, &change_values);
Olivier Fourdan
committed
if (WIN_RESIZED || (flags & CFG_FORCE_REDRAW))
{
frameDraw (c, (flags & CFG_FORCE_REDRAW));
}
Olivier Fourdan
committed
change_values.x = frameLeft (c);
change_values.y = frameTop (c);
change_values.width = c->width;
change_values.height = c->height;
XConfigureWindow (clientGetXDisplay (c), c->window, change_mask, &change_values);
Olivier Fourdan
committed
clientConfigure (Client * c, XWindowChanges * wc, unsigned long mask, unsigned short flags)
g_return_if_fail (c != NULL);
g_return_if_fail (c->window != None);
TRACE ("entering clientConfigure");
TRACE ("configuring client \"%s\" (0x%lx) %s, type %u", c->name,
c->window, flags & CFG_CONSTRAINED ? "constrained" : "not contrained", c->type);
Olivier Fourdan
committed
px = c->x;
py = c->y;
pwidth = c->width;
pheight = c->height;
if (mask & CWX)
if (!FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MOVING_RESIZING))
{
c->x = wc->x;
}
if (mask & CWY)
if (!FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MOVING_RESIZING))
{
c->y = wc->y;
}
if (mask & CWWidth)
clientSetWidth (c, wc->width);
if (mask & CWHeight)
clientSetHeight (c, wc->height);
if (mask & CWBorderWidth)
c->border_width = wc->border_width;
if (mask & CWStackMode)
switch (wc->stack_mode)
{
* Limitation: we don't support neither
* TopIf, BottomIf nor Opposite ...
case Above:
TRACE ("Above");
Olivier Fourdan
committed
if (mask & CWSibling)
{
clientRaise (c, wc->sibling);
}
else
{
clientRaise (c, None);
}
break;
case Below:
Olivier Fourdan
committed
TRACE ("Below");
if (mask & CWSibling)
{
clientLower (c, wc->sibling);
}
else
{
Olivier Fourdan
committed
clientLower (c, None);
}
Olivier Fourdan
committed
break;
case Opposite:
default:
break;
}
mask &= ~(CWStackMode | CWSibling);
/* Keep control over what the application does. However, some broken apps try
to achieve fullscreen by using static gravity and a (0,0) position, the
second part of the test is for this case.
*/
if (((flags & (CFG_CONSTRAINED | CFG_REQUEST)) == (CFG_CONSTRAINED | CFG_REQUEST))
&& CONSTRAINED_WINDOW (c)
&& !((c->gravity == StaticGravity) && (c->x == 0) && (c->y == 0)))
/* Keep fully visible only on resize */
clientConstrainPos (c, (mask & (CWWidth | CWHeight)));
if (c->x != px)
{
mask |= CWX;
}
Olivier Fourdan
committed
else
{
mask &= ~CWX;
}
if (c->y != py)
{
mask |= CWY;
}
Olivier Fourdan
committed
else
{
mask &= ~CWY;
}
if (c->width != pwidth)
{
mask |= CWWidth;
}
Olivier Fourdan
committed
else
{
mask &= ~CWWidth;
}
if (c->height != pheight)
{
mask |= CWHeight;
}
Olivier Fourdan
committed
else
{
mask &= ~CWHeight;
}
Olivier Fourdan
committed
clientConfigureWindows (c, wc, mask, flags);
Olivier Fourdan
committed
/*
Olivier Fourdan
committed
We reparent the client window. According to the ICCCM spec, the
Olivier Fourdan
committed
WM must send a senthetic event when the window is moved and not resized.
But, since we reparent the window, we must also send a synthetic
configure event when the window is moved and resized.
See this thread for the rational:
http://www.mail-archive.com/wm-spec-list@gnome.org/msg00379.html
And specifically this post from Carsten Haitzler:
http://www.mail-archive.com/wm-spec-list@gnome.org/msg00382.html
Olivier Fourdan
committed
*/
if ((WIN_MOVED) || (flags & CFG_NOTIFY) ||
((flags & CFG_REQUEST) && !(WIN_MOVED || WIN_RESIZED)))
DBG ("Sending ConfigureNotify");
ce.type = ConfigureNotify;
ce.event = c->window;
ce.window = c->window;
ce.x = c->x;
ce.y = c->y;
ce.width = c->width;
ce.height = c->height;
ce.border_width = 0;
ce.above = c->frame;
ce.override_redirect = FALSE;
XSendEvent (clientGetXDisplay (c), c->window, FALSE,
StructureNotifyMask, (XEvent *) & ce);
clientGetMWMHints (Client * c, gboolean update)
g_return_if_fail (c != NULL);
g_return_if_fail (c->window != None);
TRACE ("entering clientGetMWMHints client \"%s\" (0x%lx)", c->name,
screen_info = c->screen_info;
display_info = screen_info->display_info;
mwm_hints = getMotifHints (display_info, c->window);
if (mwm_hints)
{
Olivier Fourdan
committed
if ((mwm_hints->flags & MWM_HINTS_DECORATIONS))
Olivier Fourdan
committed
if (!FLAG_TEST (c->flags, CLIENT_FLAG_HAS_SHAPE))
Olivier Fourdan
committed
if (mwm_hints->decorations & MWM_DECOR_ALL)
{
FLAG_SET (c->xfwm_flags, XFWM_FLAG_HAS_BORDER | XFWM_FLAG_HAS_MENU);
}
else
{
FLAG_UNSET (c->xfwm_flags, XFWM_FLAG_HAS_BORDER | XFWM_FLAG_HAS_MENU);
FLAG_SET (c->xfwm_flags, (mwm_hints-> decorations & (MWM_DECOR_TITLE | MWM_DECOR_BORDER))
Olivier Fourdan
committed
? XFWM_FLAG_HAS_BORDER : 0);
FLAG_SET (c->xfwm_flags, (mwm_hints->decorations & (MWM_DECOR_MENU))
Olivier Fourdan
committed
? XFWM_FLAG_HAS_MENU : 0);
/*
FLAG_UNSET(c->xfwm_flags, XFWM_FLAG_HAS_HIDE);
FLAG_UNSET(c->xfwm_flags, XFWM_FLAG_HAS_MAXIMIZE);
FLAG_SET(c->xfwm_flags, (mwm_hints->decorations & (MWM_DECOR_MINIMIZE)) ? XFWM_FLAG_HAS_HIDE : 0);
FLAG_SET(c->xfwm_flags, (mwm_hints->decorations & (MWM_DECOR_MAXIMIZE)) ? XFWM_FLAG_HAS_MAXIMIZE : 0);
*/
}
}
}
/* The following is from Metacity : */
if (mwm_hints->flags & MWM_HINTS_FUNCTIONS)
{
if (!(mwm_hints->functions & MWM_FUNC_ALL))
{
FLAG_UNSET (c->xfwm_flags,
XFWM_FLAG_HAS_CLOSE | XFWM_FLAG_HAS_HIDE |
XFWM_FLAG_HAS_MAXIMIZE | XFWM_FLAG_HAS_MOVE |
XFWM_FLAG_HAS_RESIZE);
FLAG_SET (c->xfwm_flags,
XFWM_FLAG_HAS_CLOSE | XFWM_FLAG_HAS_HIDE |
XFWM_FLAG_HAS_MAXIMIZE | XFWM_FLAG_HAS_MOVE |
XFWM_FLAG_HAS_RESIZE);
}
if (mwm_hints->functions & MWM_FUNC_CLOSE)
{
FLAG_TOGGLE (c->xfwm_flags, XFWM_FLAG_HAS_CLOSE);
}
if (mwm_hints->functions & MWM_FUNC_MINIMIZE)
{
FLAG_TOGGLE (c->xfwm_flags, XFWM_FLAG_HAS_HIDE);
}
if (mwm_hints->functions & MWM_FUNC_MAXIMIZE)
{
FLAG_TOGGLE (c->xfwm_flags, XFWM_FLAG_HAS_MAXIMIZE);
}
if (mwm_hints->functions & MWM_FUNC_RESIZE)
{
FLAG_TOGGLE (c->xfwm_flags, XFWM_FLAG_HAS_RESIZE);
}
if (mwm_hints->functions & MWM_FUNC_MOVE)
{
FLAG_TOGGLE (c->xfwm_flags, XFWM_FLAG_HAS_MOVE);
Olivier Fourdan
committed
g_free (mwm_hints);
if (FLAG_TEST_ALL(c->xfwm_flags, XFWM_FLAG_HAS_BORDER | XFWM_FLAG_LEGACY_FULLSCREEN)
&& !FLAG_TEST(c->flags, CLIENT_FLAG_FULLSCREEN))
/* legacy app changed its decoration, put it back on regular layer */
FLAG_UNSET (c->xfwm_flags, XFWM_FLAG_LEGACY_FULLSCREEN);
clientSetLayer (c, WIN_LAYER_NORMAL);
}
wc.x = c->x;
wc.y = c->y;
wc.width = c->width;
wc.height = c->height;
clientConfigure (c, &wc, CWX | CWY | CWWidth | CWHeight, CFG_FORCE_REDRAW);
/* MWM hints can add or remove decorations, update NET_FRAME_EXTENTS accordingly */
setNetFrameExtents (display_info,
c->window,
frameTop (c),
frameLeft (c),
frameRight (c),
frameBottom (c));
}
}
void
clientGetWMNormalHints (Client * c, gboolean update)
{
XWindowChanges wc;
g_return_if_fail (c != NULL);
g_return_if_fail (c->window != None);
TRACE ("entering clientGetWMNormalHints client \"%s\" (0x%lx)", c->name,
c->window);
if (!c->size)
{
c->size = XAllocSizeHints ();
}
g_assert (c->size);
if (!XGetWMNormalHints (clientGetXDisplay (c), c->window, c->size, &dummy))
c->size->flags = 0;
previous_value = FLAG_TEST (c->xfwm_flags, XFWM_FLAG_IS_RESIZABLE);
FLAG_UNSET (c->xfwm_flags, XFWM_FLAG_IS_RESIZABLE);
wc.x = c->x;
wc.y = c->y;
wc.width = c->width;
wc.height = c->height;
if (!(c->size->flags & PMaxSize))
c->size->max_width = G_MAXINT;
c->size->max_height = G_MAXINT;
c->size->flags |= PMaxSize;
}
if (!(c->size->flags & PBaseSize))
{
c->size->base_width = 0;
c->size->base_height = 0;