Newer
Older
Olivier Fourdan
committed
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.
Olivier Fourdan
committed
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.
Olivier Fourdan
committed
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <glib.h>
Olivier Fourdan
committed
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#include <libxfce4util/libxfce4util.h>
Olivier Fourdan
committed
#include <libxfcegui4/libxfcegui4.h>
#include "display.h"
#include "screen.h"
Olivier Fourdan
committed
#include "netwm.h"
#include "misc.h"
#include "client.h"
#include "frame.h"
#include "hints.h"
#include "workspaces.h"
#include "transients.h"
#include "stacking.h"
void
clientSetNetState (Client * c)
{
ScreenInfo *screen_info = NULL;
DisplayInfo *display_info = NULL;
Olivier Fourdan
committed
Atom data[16];
Olivier Fourdan
committed
g_return_if_fail (c != NULL);
TRACE ("entering clientSetNetState");
TRACE ("client \"%s\" (0x%lx)", c->name, c->window);
screen_info = c->screen_info;
display_info = screen_info->display_info;
Olivier Fourdan
committed
i = 0;
if (FLAG_TEST (c->flags, CLIENT_FLAG_SHADED))
{
TRACE ("clientSetNetState : shaded");
data[i++] = display_info->atoms[NET_WM_STATE_SHADED];
Olivier Fourdan
committed
}
if (FLAG_TEST (c->flags, CLIENT_FLAG_STICKY))
{
TRACE ("clientSetNetState : sticky");
data[i++] = display_info->atoms[NET_WM_STATE_STICKY];
Olivier Fourdan
committed
}
if (FLAG_TEST (c->flags, CLIENT_FLAG_STATE_MODAL))
{
TRACE ("clientSetNetState : modal");
data[i++] = display_info->atoms[NET_WM_STATE_MODAL];
Olivier Fourdan
committed
}
if (FLAG_TEST (c->flags, CLIENT_FLAG_SKIP_PAGER))
{
TRACE ("clientSetNetState : skip_pager");
data[i++] = display_info->atoms[NET_WM_STATE_SKIP_PAGER];
Olivier Fourdan
committed
}
if (FLAG_TEST (c->flags, CLIENT_FLAG_SKIP_TASKBAR))
{
TRACE ("clientSetNetState : skip_taskbar");
data[i++] = display_info->atoms[NET_WM_STATE_SKIP_TASKBAR];
Olivier Fourdan
committed
}
if (FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED))
{
TRACE ("clientSetNetState : maximize vert + horiz");
data[i++] = display_info->atoms[NET_WM_STATE_MAXIMIZED_HORZ];
data[i++] = display_info->atoms[NET_WM_STATE_MAXIMIZED_VERT];
Olivier Fourdan
committed
}
else if (FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_HORIZ))
{
TRACE ("clientSetNetState : maximize horiz");
data[i++] = display_info->atoms[NET_WM_STATE_MAXIMIZED_HORZ];
Olivier Fourdan
committed
}
else if (FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_VERT))
{
TRACE ("clientSetNetState : vert");
data[i++] = display_info->atoms[NET_WM_STATE_MAXIMIZED_VERT];
Olivier Fourdan
committed
}
if (FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN))
{
TRACE ("clientSetNetState : fullscreen");
data[i++] = display_info->atoms[NET_WM_STATE_FULLSCREEN];
Olivier Fourdan
committed
}
else if (FLAG_TEST (c->flags, CLIENT_FLAG_ABOVE))
{
TRACE ("clientSetNetState : above");
data[i++] = display_info->atoms[NET_WM_STATE_ABOVE];
Olivier Fourdan
committed
}
else if (FLAG_TEST (c->flags, CLIENT_FLAG_BELOW))
{
TRACE ("clientSetNetState : below");
data[i++] = display_info->atoms[NET_WM_STATE_BELOW];
Olivier Fourdan
committed
}
if (FLAG_TEST (c->flags, CLIENT_FLAG_ICONIFIED))
Olivier Fourdan
committed
{
TRACE ("clientSetNetState : hidden");
data[i++] = display_info->atoms[NET_WM_STATE_HIDDEN];
Olivier Fourdan
committed
}
if (FLAG_TEST (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION))
{
TRACE ("clientSetNetState : demands_attention");
data[i++] = display_info->atoms[NET_WM_STATE_DEMANDS_ATTENTION];
XChangeProperty (display_info->dpy, c->window,
display_info->atoms[NET_WM_STATE], XA_ATOM, 32,
PropModeReplace, (unsigned char *) data, i);
Olivier Fourdan
committed
/*
We also set GNOME hint here for consistency and convenience,
although the meaning of net_wm_state and win_state aren't the same.
*/
setHint (display_info, c->window, WIN_STATE, c->win_state);
Olivier Fourdan
committed
}
void
clientGetNetState (Client * c)
{
ScreenInfo *screen_info = NULL;
DisplayInfo *display_info = NULL;
Olivier Fourdan
committed
int n_atoms = 0;
Atom *atoms = NULL;
g_return_if_fail (c != NULL);
TRACE ("entering clientGetNetState");
TRACE ("client \"%s\" (0x%lx)", c->name, c->window);
screen_info = c->screen_info;
display_info = screen_info->display_info;
if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_SESSION_MANAGED))
{
if (FLAG_TEST (c->flags, CLIENT_FLAG_SHADED))
TRACE ("clientGetNetState : shaded from session management");
c->win_state |= WIN_STATE_SHADED;
FLAG_SET (c->flags, CLIENT_FLAG_SHADED);
if (FLAG_TEST (c->flags, CLIENT_FLAG_STICKY))
TRACE ("clientGetNetState : sticky from session management");
c->win_state |= WIN_STATE_STICKY;
FLAG_SET (c->flags, CLIENT_FLAG_STICKY);
if (FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_HORIZ))
TRACE ("clientGetNetState : maximized horiz from session management");
c->win_state |= WIN_STATE_MAXIMIZED_HORIZ;
FLAG_SET (c->flags, CLIENT_FLAG_MAXIMIZED_HORIZ);
if (FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_VERT))
TRACE ("clientGetNetState : maximized vert from session management");
c->win_state |= WIN_STATE_MAXIMIZED_VERT;
FLAG_SET (c->flags, CLIENT_FLAG_MAXIMIZED_VERT);
if (getAtomList (display_info, c->window, NET_WM_STATE, &atoms, &n_atoms))
Olivier Fourdan
committed
{
int i;
TRACE ("clientGetNetState: %i atoms detected", n_atoms);
i = 0;
while (i < n_atoms)
{
if ((atoms[i] == display_info->atoms[NET_WM_STATE_SHADED]))
Olivier Fourdan
committed
{
TRACE ("clientGetNetState : shaded");
c->win_state |= WIN_STATE_SHADED;
FLAG_SET (c->flags, CLIENT_FLAG_SHADED);
}
else if ((atoms[i] == display_info->atoms[NET_WM_STATE_STICKY]))
Olivier Fourdan
committed
{
TRACE ("clientGetNetState : sticky");
c->win_state |= WIN_STATE_STICKY;
FLAG_SET (c->flags, CLIENT_FLAG_STICKY);
}
else if ((atoms[i] == display_info->atoms[NET_WM_STATE_MAXIMIZED_HORZ]))
Olivier Fourdan
committed
{
TRACE ("clientGetNetState : maximized horiz");
c->win_state |= WIN_STATE_MAXIMIZED_HORIZ;
FLAG_SET (c->flags, CLIENT_FLAG_MAXIMIZED_HORIZ);
}
else if ((atoms[i] == display_info->atoms[NET_WM_STATE_MAXIMIZED_VERT]))
Olivier Fourdan
committed
{
TRACE ("clientGetNetState : maximized vert");
c->win_state |= WIN_STATE_MAXIMIZED_VERT;
FLAG_SET (c->flags, CLIENT_FLAG_MAXIMIZED_VERT);
}
else if ((atoms[i] == display_info->atoms[NET_WM_STATE_FULLSCREEN]))
Olivier Fourdan
committed
{
if (!FLAG_TEST_ALL (c->flags, CLIENT_FLAG_ABOVE | CLIENT_FLAG_BELOW))
{
TRACE ("clientGetNetState : fullscreen");
FLAG_SET (c->flags, CLIENT_FLAG_FULLSCREEN);
}
else if ((atoms[i] == display_info->atoms[NET_WM_STATE_ABOVE]))
Olivier Fourdan
committed
{
if (!FLAG_TEST_ALL (c->flags, CLIENT_FLAG_FULLSCREEN | CLIENT_FLAG_BELOW))
{
TRACE ("clientGetNetState : above");
FLAG_SET (c->flags, CLIENT_FLAG_ABOVE);
Olivier Fourdan
committed
}
else if ((atoms[i] == display_info->atoms[NET_WM_STATE_BELOW]))
Olivier Fourdan
committed
{
if (!FLAG_TEST_ALL (c->flags, CLIENT_FLAG_ABOVE | CLIENT_FLAG_FULLSCREEN))
{
TRACE ("clientGetNetState : below");
FLAG_SET (c->flags, CLIENT_FLAG_BELOW);
Olivier Fourdan
committed
}
else if (atoms[i] == display_info->atoms[NET_WM_STATE_MODAL])
Olivier Fourdan
committed
{
TRACE ("clientGetNetState : modal");
FLAG_SET (c->flags, CLIENT_FLAG_STATE_MODAL);
}
else if (atoms[i] == display_info->atoms[NET_WM_STATE_SKIP_PAGER])
Olivier Fourdan
committed
{
TRACE ("clientGetNetState : skip_pager");
FLAG_SET (c->flags, CLIENT_FLAG_SKIP_PAGER);
}
else if (atoms[i] == display_info->atoms[NET_WM_STATE_SKIP_TASKBAR])
Olivier Fourdan
committed
{
TRACE ("clientGetNetState : skip_taskbar");
FLAG_SET (c->flags, CLIENT_FLAG_SKIP_TASKBAR);
}
else if (atoms[i] == display_info->atoms[NET_WM_STATE_HIDDEN])
{
TRACE ("clientGetNetState : state_hidden");
FLAG_SET (c->flags, CLIENT_FLAG_ICONIFIED);
}
else if (atoms[i] == display_info->atoms[NET_WM_STATE_DEMANDS_ATTENTION])
{
TRACE ("clientGetNetState : demands_attention");
FLAG_SET (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION);
}
Olivier Fourdan
committed
else
{
g_warning ("Unmanaged net_wm_state (window 0x%lx)", c->window);
Olivier Fourdan
committed
}
++i;
}
if (atoms)
{
XFree (atoms);
}
}
}
void
clientUpdateNetState (Client * c, XClientMessageEvent * ev)
{
ScreenInfo *screen_info = NULL;
DisplayInfo *display_info = NULL;
Olivier Fourdan
committed
unsigned long action;
Atom first;
Atom second;
g_return_if_fail (c != NULL);
TRACE ("entering clientUpdateNetState");
TRACE ("client \"%s\" (0x%lx)", c->name, c->window);
screen_info = c->screen_info;
display_info = screen_info->display_info;
Olivier Fourdan
committed
action = ((XEvent *) ev)->xclient.data.l[0];
first = ((XEvent *) ev)->xclient.data.l[1];
Olivier Fourdan
committed
second = ((XEvent *) ev)->xclient.data.l[2];
if ((first == display_info->atoms[NET_WM_STATE_SHADED]) ||
(second == display_info->atoms[NET_WM_STATE_SHADED]))
Olivier Fourdan
committed
{
if ((action == NET_WM_STATE_ADD) && !FLAG_TEST (c->flags, CLIENT_FLAG_SHADED))
Olivier Fourdan
committed
{
clientShade (c);
}
else if ((action == NET_WM_STATE_REMOVE) && FLAG_TEST (c->flags, CLIENT_FLAG_SHADED))
Olivier Fourdan
committed
{
clientUnshade (c);
}
else if (action == NET_WM_STATE_TOGGLE)
{
clientToggleShaded (c);
}
}
if ((first == display_info->atoms[NET_WM_STATE_STICKY]) ||
(second == display_info->atoms[NET_WM_STATE_STICKY]))
Olivier Fourdan
committed
{
Olivier Fourdan
committed
if (!clientIsValidTransientOrModal (c) && FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_STICK))
Olivier Fourdan
committed
{
if ((action == NET_WM_STATE_ADD) && !FLAG_TEST (c->flags, CLIENT_FLAG_STICKY))
Olivier Fourdan
committed
{
clientStick (c, TRUE);
}
else if ((action == NET_WM_STATE_REMOVE) && FLAG_TEST (c->flags, CLIENT_FLAG_STICKY))
Olivier Fourdan
committed
{
clientUnstick (c, TRUE);
}
else if (action == NET_WM_STATE_TOGGLE)
{
clientToggleSticky (c, TRUE);
}
frameDraw (c, FALSE, FALSE);
}
}
if ((first == display_info->atoms[NET_WM_STATE_DEMANDS_ATTENTION]) ||
(second == display_info->atoms[NET_WM_STATE_DEMANDS_ATTENTION]))
{
if (action == NET_WM_STATE_ADD)
{
FLAG_SET (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION);
}
else if (action == NET_WM_STATE_REMOVE)
{
FLAG_UNSET (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION);
}
else if (action == NET_WM_STATE_TOGGLE)
{
FLAG_TOGGLE (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION);
}
}
if ((first == display_info->atoms[NET_WM_STATE_MAXIMIZED_HORZ]) ||
(second == display_info->atoms[NET_WM_STATE_MAXIMIZED_HORZ]) ||
(first == display_info->atoms[NET_WM_STATE_MAXIMIZED_VERT]) ||
(second == display_info->atoms[NET_WM_STATE_MAXIMIZED_VERT]))
Olivier Fourdan
committed
{
if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_MAXIMIZE))
Olivier Fourdan
committed
{
if ((action == NET_WM_STATE_ADD) && !FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED))
Olivier Fourdan
committed
{
unsigned long mode = 0;
if ((first == display_info->atoms[NET_WM_STATE_MAXIMIZED_HORZ]) ||
(second == display_info->atoms[NET_WM_STATE_MAXIMIZED_HORZ]))
Olivier Fourdan
committed
{
mode |= !FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_HORIZ) ? WIN_STATE_MAXIMIZED_HORIZ : 0;
Olivier Fourdan
committed
}
if ((first == display_info->atoms[NET_WM_STATE_MAXIMIZED_VERT]) ||
(second == display_info->atoms[NET_WM_STATE_MAXIMIZED_VERT]))
Olivier Fourdan
committed
{
mode |= !FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_VERT) ? WIN_STATE_MAXIMIZED_VERT : 0;
Olivier Fourdan
committed
}
Olivier Fourdan
committed
clientToggleMaximized (c, mode, TRUE);
Olivier Fourdan
committed
}
else if ((action == NET_WM_STATE_REMOVE) && FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED))
Olivier Fourdan
committed
{
unsigned long mode = 0;
if ((first == display_info->atoms[NET_WM_STATE_MAXIMIZED_HORZ]) ||
(second == display_info->atoms[NET_WM_STATE_MAXIMIZED_HORZ]))
Olivier Fourdan
committed
{
mode |= FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_HORIZ) ? WIN_STATE_MAXIMIZED_HORIZ : 0;
Olivier Fourdan
committed
}
if ((first == display_info->atoms[NET_WM_STATE_MAXIMIZED_VERT]) ||
(second == display_info->atoms[NET_WM_STATE_MAXIMIZED_VERT]))
Olivier Fourdan
committed
{
mode |= FLAG_TEST (c->flags, CLIENT_FLAG_MAXIMIZED_VERT) ? WIN_STATE_MAXIMIZED_VERT : 0;
Olivier Fourdan
committed
}
Olivier Fourdan
committed
clientToggleMaximized (c, mode, TRUE);
Olivier Fourdan
committed
}
else if (action == NET_WM_STATE_TOGGLE)
{
unsigned long mode = 0;
if ((first == display_info->atoms[NET_WM_STATE_MAXIMIZED_HORZ]) ||
(second == display_info->atoms[NET_WM_STATE_MAXIMIZED_HORZ]))
Olivier Fourdan
committed
{
mode |= WIN_STATE_MAXIMIZED_HORIZ;
}
if ((first == display_info->atoms[NET_WM_STATE_MAXIMIZED_VERT]) ||
(second == display_info->atoms[NET_WM_STATE_MAXIMIZED_VERT]))
Olivier Fourdan
committed
{
mode |= WIN_STATE_MAXIMIZED_VERT;
}
Olivier Fourdan
committed
clientToggleMaximized (c, mode, TRUE);
Olivier Fourdan
committed
}
}
}
if ((first == display_info->atoms[NET_WM_STATE_MODAL]) ||
(second == display_info->atoms[NET_WM_STATE_MODAL]))
Olivier Fourdan
committed
{
if ((action == NET_WM_STATE_ADD) && !FLAG_TEST (c->flags, CLIENT_FLAG_STATE_MODAL))
Olivier Fourdan
committed
{
FLAG_SET (c->flags, CLIENT_FLAG_STATE_MODAL);
clientSetNetState (c);
clientWindowType (c);
}
else if ((action == NET_WM_STATE_REMOVE) && FLAG_TEST (c->flags, CLIENT_FLAG_STATE_MODAL))
Olivier Fourdan
committed
{
FLAG_UNSET (c->flags, CLIENT_FLAG_STATE_MODAL);
clientSetNetState (c);
clientWindowType (c);
}
else if (action == NET_WM_STATE_TOGGLE)
{
FLAG_TOGGLE (c->flags, CLIENT_FLAG_STATE_MODAL);
clientSetNetState (c);
clientWindowType (c);
}
frameDraw (c, TRUE, FALSE);
Olivier Fourdan
committed
}
if ((first == display_info->atoms[NET_WM_STATE_FULLSCREEN]) ||
(second == display_info->atoms[NET_WM_STATE_FULLSCREEN]))
Olivier Fourdan
committed
{
Olivier Fourdan
committed
if (!clientIsValidTransientOrModal (c))
Olivier Fourdan
committed
{
if ((action == NET_WM_STATE_ADD) && !FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN))
Olivier Fourdan
committed
{
FLAG_SET (c->flags, CLIENT_FLAG_FULLSCREEN);
Olivier Fourdan
committed
}
else if ((action == NET_WM_STATE_REMOVE) && FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN))
Olivier Fourdan
committed
{
FLAG_UNSET (c->flags, CLIENT_FLAG_FULLSCREEN);
Olivier Fourdan
committed
}
else if (action == NET_WM_STATE_TOGGLE)
{
FLAG_TOGGLE (c->flags, CLIENT_FLAG_FULLSCREEN);
Olivier Fourdan
committed
}
}
}
if ((first == display_info->atoms[NET_WM_STATE_ABOVE]) ||
(second == display_info->atoms[NET_WM_STATE_ABOVE]))
Olivier Fourdan
committed
{
Olivier Fourdan
committed
if (!clientIsValidTransientOrModal (c) && !FLAG_TEST (c->flags, CLIENT_FLAG_BELOW))
Olivier Fourdan
committed
{
if ((action == NET_WM_STATE_ADD) && !FLAG_TEST (c->flags, CLIENT_FLAG_ABOVE))
Olivier Fourdan
committed
{
FLAG_SET (c->flags, CLIENT_FLAG_ABOVE);
Olivier Fourdan
committed
}
else if ((action == NET_WM_STATE_REMOVE) && FLAG_TEST (c->flags, CLIENT_FLAG_ABOVE))
Olivier Fourdan
committed
{
FLAG_UNSET (c->flags, CLIENT_FLAG_ABOVE);
Olivier Fourdan
committed
}
else if (action == NET_WM_STATE_TOGGLE)
{
FLAG_TOGGLE (c->flags, CLIENT_FLAG_ABOVE);
Olivier Fourdan
committed
}
}
}
if ((first == display_info->atoms[NET_WM_STATE_BELOW]) ||
(second == display_info->atoms[NET_WM_STATE_BELOW]))
Olivier Fourdan
committed
{
Olivier Fourdan
committed
if (!clientIsValidTransientOrModal (c) && !FLAG_TEST (c->flags, CLIENT_FLAG_ABOVE))
Olivier Fourdan
committed
{
if ((action == NET_WM_STATE_ADD) && !FLAG_TEST (c->flags, CLIENT_FLAG_BELOW))
Olivier Fourdan
committed
{
FLAG_SET (c->flags, CLIENT_FLAG_BELOW);
Olivier Fourdan
committed
}
else if ((action == NET_WM_STATE_REMOVE) && FLAG_TEST (c->flags, CLIENT_FLAG_BELOW))
Olivier Fourdan
committed
{
FLAG_UNSET (c->flags, CLIENT_FLAG_BELOW);
Olivier Fourdan
committed
}
else if (action == NET_WM_STATE_TOGGLE)
{
FLAG_TOGGLE (c->flags, CLIENT_FLAG_BELOW);
Olivier Fourdan
committed
}
}
}
if ((first == display_info->atoms[NET_WM_STATE_SKIP_PAGER]) ||
(second == display_info->atoms[NET_WM_STATE_SKIP_PAGER]))
Olivier Fourdan
committed
{
if ((action == NET_WM_STATE_ADD) && !FLAG_TEST (c->flags, CLIENT_FLAG_SKIP_PAGER))
Olivier Fourdan
committed
{
FLAG_SET (c->flags, CLIENT_FLAG_SKIP_PAGER);
clientSetNetState (c);
}
else if ((action == NET_WM_STATE_REMOVE) && FLAG_TEST (c->flags, CLIENT_FLAG_SKIP_PAGER))
Olivier Fourdan
committed
{
FLAG_UNSET (c->flags, CLIENT_FLAG_SKIP_PAGER);
clientSetNetState (c);
}
else if (action == NET_WM_STATE_TOGGLE)
{
FLAG_TOGGLE (c->flags, CLIENT_FLAG_SKIP_PAGER);
clientSetNetState (c);
}
}
if ((first == display_info->atoms[NET_WM_STATE_SKIP_TASKBAR]) ||
(second == display_info->atoms[NET_WM_STATE_SKIP_TASKBAR]))
Olivier Fourdan
committed
{
if ((action == NET_WM_STATE_ADD) && !FLAG_TEST (c->flags, CLIENT_FLAG_SKIP_TASKBAR))
Olivier Fourdan
committed
{
FLAG_SET (c->flags, CLIENT_FLAG_SKIP_TASKBAR);
clientSetNetState (c);
}
else if ((action == NET_WM_STATE_REMOVE) && FLAG_TEST (c->flags, CLIENT_FLAG_SKIP_TASKBAR))
Olivier Fourdan
committed
{
FLAG_UNSET (c->flags, CLIENT_FLAG_SKIP_TASKBAR);
clientSetNetState (c);
}
else if (action == NET_WM_STATE_TOGGLE)
{
FLAG_TOGGLE (c->flags, CLIENT_FLAG_SKIP_TASKBAR);
clientSetNetState (c);
}
Olivier Fourdan
committed
frameDraw (c, TRUE, FALSE);
Olivier Fourdan
committed
}
}
void
clientUpdateFullscreenState (Client * c)
{
XWindowChanges wc;
int layer;
g_return_if_fail (c != NULL);
TRACE ("entering clientUpdateFullscreenState");
TRACE ("Update fullscreen state for client \"%s\" (0x%lx)", c->name, c->window);
if (FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN))
{
Olivier Fourdan
committed
GdkRectangle rect;
gint monitor_nbr;
Olivier Fourdan
committed
int cx, cy;
cx = frameX (c) + (frameWidth (c) / 2);
cy = frameY (c) + (frameHeight (c) / 2);
monitor_nbr = find_monitor_at_point (c->screen_info->gscr, cx, cy);
gdk_screen_get_monitor_geometry (c->screen_info->gscr, monitor_nbr, &rect);
Olivier Fourdan
committed
Olivier Fourdan
committed
c->fullscreen_old_x = c->x;
c->fullscreen_old_y = c->y;
c->fullscreen_old_width = c->width;
c->fullscreen_old_height = c->height;
c->fullscreen_old_layer = c->win_layer;
Olivier Fourdan
committed
wc.x = rect.x;
wc.y = rect.y;
wc.width = rect.width;
wc.height = rect.height;
Olivier Fourdan
committed
layer = WIN_LAYER_ABOVE_DOCK;
}
else
{
wc.x = c->fullscreen_old_x;
wc.y = c->fullscreen_old_y;
wc.width = c->fullscreen_old_width;
wc.height = c->fullscreen_old_height;
layer = c->fullscreen_old_layer;
}
clientSetNetState (c);
if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_MANAGED))
Olivier Fourdan
committed
{
/*
For some reason, the configure can generate EnterNotify events
on lower windows, causing a nasty race cond with apps trying to
grab focus in focus follow mouse mode. Grab the pointer to
avoid these effects
*/
myScreenGrabPointer (c->screen_info, EnterWindowMask, None, CurrentTime);
Olivier Fourdan
committed
clientConfigure (c, &wc, CWX | CWY | CWWidth | CWHeight, CFG_FORCE_REDRAW);
myScreenUngrabPointer (c->screen_info, CurrentTime);
Olivier Fourdan
committed
}
else
{
c->x = wc.x;
c->y = wc.y;
c->height = wc.height;
c->width = wc.width;
}
clientSetLayer (c, layer);
}
void
clientGetNetWmType (Client * c)
{
ScreenInfo *screen_info = NULL;
DisplayInfo *display_info = NULL;
Olivier Fourdan
committed
int n_atoms = 0;
Atom *atoms = NULL;
int i;
g_return_if_fail (c != NULL);
TRACE ("entering clientGetNetWmType");
TRACE ("client \"%s\" (0x%lx)", c->name, c->window);
screen_info = c->screen_info;
display_info = screen_info->display_info;
Olivier Fourdan
committed
n_atoms = 0;
atoms = NULL;
if (!getAtomList (display_info, c->window, NET_WM_WINDOW_TYPE, &atoms, &n_atoms))
Olivier Fourdan
committed
{
switch (c->win_layer)
{
case WIN_LAYER_DESKTOP:
c->type_atom = display_info->atoms[NET_WM_WINDOW_TYPE_DESKTOP];
Olivier Fourdan
committed
break;
case WIN_LAYER_DOCK:
c->type_atom = display_info->atoms[NET_WM_WINDOW_TYPE_DOCK];
Olivier Fourdan
committed
break;
case WIN_LAYER_NORMAL:
c->type_atom = display_info->atoms[NET_WM_WINDOW_TYPE_NORMAL];
Olivier Fourdan
committed
break;
default:
c->type_atom = None;
break;
}
}
else
{
i = 0;
while (i < n_atoms)
{
if ((atoms[i] == display_info->atoms[NET_WM_WINDOW_TYPE_DESKTOP]) ||
(atoms[i] == display_info->atoms[NET_WM_WINDOW_TYPE_DOCK]) ||
(atoms[i] == display_info->atoms[NET_WM_WINDOW_TYPE_TOOLBAR]) ||
(atoms[i] == display_info->atoms[NET_WM_WINDOW_TYPE_MENU]) ||
(atoms[i] == display_info->atoms[NET_WM_WINDOW_TYPE_DIALOG]) ||
(atoms[i] == display_info->atoms[NET_WM_WINDOW_TYPE_NORMAL]) ||
(atoms[i] == display_info->atoms[NET_WM_WINDOW_TYPE_UTILITY]) ||
(atoms[i] == display_info->atoms[NET_WM_WINDOW_TYPE_SPLASH]))
Olivier Fourdan
committed
{
c->type_atom = atoms[i];
break;
}
++i;
}
if (atoms)
{
XFree (atoms);
}
}
clientWindowType (c);
}
void
clientGetInitialNetWmDesktop (Client * c)
{
ScreenInfo *screen_info = NULL;
DisplayInfo *display_info = NULL;
Olivier Fourdan
committed
Client *c2 = NULL;
long val = 0;
g_return_if_fail (c != NULL);
TRACE ("entering clientGetInitialNetWmDesktop");
TRACE ("client \"%s\" (0x%lx)", c->name, c->window);
screen_info = c->screen_info;
display_info = screen_info->display_info;
Olivier Fourdan
committed
/* This is to make sure that transient are shown with their "ancestor" window */
c2 = clientGetTransient (c);
if (c2)
{
FLAG_SET (c->xfwm_flags, XFWM_FLAG_WORKSPACE_SET);
Olivier Fourdan
committed
c->win_workspace = c2->win_workspace;
if (FLAG_TEST (c2->flags, CLIENT_FLAG_STICKY))
{
FLAG_SET (c->flags, CLIENT_FLAG_STICKY);
c->win_state |= WIN_STATE_STICKY;
}
}
else
{
if (!FLAG_TEST (c->xfwm_flags, XFWM_FLAG_SESSION_MANAGED)
&& !FLAG_TEST (c->xfwm_flags, XFWM_FLAG_WORKSPACE_SET))
Olivier Fourdan
committed
{
FLAG_SET (c->xfwm_flags, XFWM_FLAG_WORKSPACE_SET);
c->win_workspace = c->screen_info->current_ws;
Olivier Fourdan
committed
}
if (getHint (display_info, c->window, NET_WM_DESKTOP, &val))
Olivier Fourdan
committed
{
TRACE ("atom net_wm_desktop detected");
if (val == (int) ALL_WORKSPACES)
{
if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_STICK) && !FLAG_TEST (c->flags, CLIENT_FLAG_STICKY))
Olivier Fourdan
committed
{
TRACE ("atom net_wm_desktop specifies window \"%s\" is sticky", c->name);
Olivier Fourdan
committed
FLAG_SET (c->flags, CLIENT_FLAG_STICKY);
c->win_state |= WIN_STATE_STICKY;
}
c->win_workspace = c->screen_info->current_ws;
Olivier Fourdan
committed
}
else
{
TRACE ("atom net_wm_desktop specifies window \"%s\" is on desk %i", c->name, (int) val);
Olivier Fourdan
committed
c->win_workspace = (int) val;
}
FLAG_SET (c->xfwm_flags, XFWM_FLAG_WORKSPACE_SET);
Olivier Fourdan
committed
}
else if (getHint (display_info, c->window, WIN_WORKSPACE, &val))
Olivier Fourdan
committed
{
TRACE ("atom win_workspace specifies window \"%s\" is on desk %i", c->name, (int) val);
Olivier Fourdan
committed
c->win_workspace = (int) val;
FLAG_SET (c->xfwm_flags, XFWM_FLAG_WORKSPACE_SET);
Olivier Fourdan
committed
}
}
TRACE ("initial desktop for window \"%s\" is %i", c->name, c->win_workspace);
if (c->win_workspace > c->screen_info->workspace_count - 1)
Olivier Fourdan
committed
{
TRACE ("value off limits, using %i instead", c->screen_info->workspace_count - 1);
c->win_workspace = c->screen_info->workspace_count - 1;
FLAG_SET (c->xfwm_flags, XFWM_FLAG_WORKSPACE_SET);
Olivier Fourdan
committed
}
TRACE ("initial desktop for window \"%s\" is %i", c->name, c->win_workspace);
setHint (display_info, c->window, WIN_WORKSPACE, c->win_workspace);
Olivier Fourdan
committed
if (FLAG_TEST (c->flags, CLIENT_FLAG_STICKY))
{
setHint (display_info, c->window, NET_WM_DESKTOP, (unsigned long) ALL_WORKSPACES);
Olivier Fourdan
committed
}
else
{
setHint (display_info, c->window, NET_WM_DESKTOP, (unsigned long) c->win_workspace);
Olivier Fourdan
committed
}
}
void
clientSetNetClientList (ScreenInfo * screen_info, Atom a, GList * list)
Olivier Fourdan
committed
{
Window *listw;
Window *index_dest;
GList *index_src;
gint size, i;
TRACE ("entering clientSetNetClientList");
size = g_list_length (list);
if (size < 1)
{
XDeleteProperty (myScreenGetXDisplay (screen_info), screen_info->xroot, a);
Olivier Fourdan
committed
}
else if ((listw = (Window *) malloc ((size + 1) * sizeof (Window))))
{
TRACE ("%i windows in list for %i clients", size, screen_info->client_count);
Olivier Fourdan
committed
for (i = 0, index_dest = listw, index_src = list; i < size;
i++, index_dest++, index_src = g_list_next (index_src))
{
Client *c = (Client *) index_src->data;
*index_dest = c->window;
}
XChangeProperty (myScreenGetXDisplay (screen_info), screen_info->xroot, a, XA_WINDOW, 32, PropModeReplace,
Olivier Fourdan
committed
(unsigned char *) listw, size);
free (listw);
}
}
void
clientGetNetStruts (Client * c)
{
ScreenInfo *screen_info = NULL;
DisplayInfo *display_info = NULL;
Olivier Fourdan
committed
gulong *struts = NULL;
int nitems;
int i;
g_return_if_fail (c != NULL);
TRACE ("entering clientGetNetStruts for \"%s\" (0x%lx)", c->name, c->window);
screen_info = c->screen_info;
display_info = screen_info->display_info;
Olivier Fourdan
committed
for (i = 0; i < 12; i++)
{
c->struts[i] = 0;
}
FLAG_UNSET (c->flags, CLIENT_FLAG_HAS_STRUT);
FLAG_UNSET (c->flags, CLIENT_FLAG_HAS_STRUT_PARTIAL);
if (getCardinalList (display_info, c->window, NET_WM_STRUT_PARTIAL, &struts, &nitems))
Olivier Fourdan
committed
{
if (nitems != 12)
{
Olivier Fourdan
committed
return;
}
FLAG_SET (c->flags, CLIENT_FLAG_HAS_STRUT);
FLAG_SET (c->flags, CLIENT_FLAG_HAS_STRUT_PARTIAL);
for (i = 0; i < 12; i++)
{
c->struts[i] = (int) struts[i];
}
XFree (struts);
Olivier Fourdan
committed
}
else if (getCardinalList (display_info, c->window, NET_WM_STRUT, &struts, &nitems))
Olivier Fourdan
committed
{
if (nitems != 4)
{
Olivier Fourdan
committed
return;
}
FLAG_SET (c->flags, CLIENT_FLAG_HAS_STRUT);
for (i = 0; i < 4; i++)
{
c->struts[i] = (int) struts[i];
}
Olivier Fourdan
committed
for (i = 4; i < 12; i++)
{
Olivier Fourdan
committed
c->struts[i] = 0;
Olivier Fourdan
committed
}
/* Fill(in values as for partial struts */
Olivier Fourdan
committed
c->struts[TOP_START_X] = c->struts[BOTTOM_START_X] = 0;
c->struts[TOP_END_X] = c->struts[BOTTOM_END_X] =
Olivier Fourdan
committed
c->struts[LEFT_START_Y] = c->struts[RIGHT_START_Y] = 0;
c->struts[LEFT_END_Y] = c->struts[RIGHT_END_Y] =
gdk_screen_get_height (c->screen_info->gscr);
Olivier Fourdan
committed
Olivier Fourdan
committed
XFree (struts);
Olivier Fourdan
committed
}
}
void
clientSetNetActions (Client * c)
{
ScreenInfo *screen_info = NULL;
DisplayInfo *display_info = NULL;
Olivier Fourdan
committed
Atom atoms[6];
int i = 0;
g_return_if_fail (c != NULL);
TRACE ("entering clientSetNetActions");
screen_info = c->screen_info;
display_info = screen_info->display_info;
atoms[i++] = display_info->atoms[NET_WM_ACTION_CLOSE];
Olivier Fourdan
committed
if (CLIENT_CAN_MAXIMIZE_WINDOW (c))
{
atoms[i++] = display_info->atoms[NET_WM_ACTION_MAXIMIZE_HORZ];
atoms[i++] = display_info->atoms[NET_WM_ACTION_MAXIMIZE_VERT];
Olivier Fourdan
committed
}
if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_STICK))
Olivier Fourdan
committed
{
atoms[i++] = display_info->atoms[NET_WM_ACTION_CHANGE_DESKTOP];
atoms[i++] = display_info->atoms[NET_WM_ACTION_STICK];
Olivier Fourdan
committed
}
if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_BORDER))
Olivier Fourdan
committed
{
atoms[i++] = display_info->atoms[NET_WM_ACTION_SHADE];
Olivier Fourdan
committed
}
XChangeProperty (clientGetXDisplay (c), c->window, display_info->atoms[NET_WM_ALLOWED_ACTIONS],
XA_ATOM, 32, PropModeReplace, (unsigned char *) atoms, i);
Olivier Fourdan
committed
}
void
clientWindowType (Client * c)
{
ScreenInfo *screen_info = NULL;
DisplayInfo *display_info = NULL;
Olivier Fourdan
committed
g_return_if_fail (c != NULL);
TRACE ("entering clientWindowType");
TRACE ("type for client \"%s\" (0x%lx)", c->name, c->window);
screen_info = c->screen_info;
display_info = screen_info->display_info;
Olivier Fourdan
committed
old_type = c->type;
c->initial_layer = c->win_layer;
if (c->type_atom != None)
{
if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_DESKTOP])
Olivier Fourdan
committed
{
TRACE ("atom net_wm_window_type_desktop detected");
c->type = WINDOW_DESKTOP;
c->initial_layer = WIN_LAYER_DESKTOP;
c->win_state |= WIN_STATE_STICKY;
FLAG_SET (c->flags,
CLIENT_FLAG_SKIP_PAGER | CLIENT_FLAG_STICKY |
CLIENT_FLAG_SKIP_TASKBAR);
FLAG_UNSET (c->xfwm_flags,
XFWM_FLAG_HAS_RESIZE | XFWM_FLAG_HAS_MOVE |
XFWM_FLAG_HAS_HIDE | XFWM_FLAG_HAS_MAXIMIZE |
XFWM_FLAG_HAS_MENU | XFWM_FLAG_HAS_STICK |
XFWM_FLAG_HAS_BORDER);
Olivier Fourdan
committed
}
else if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_DOCK])
Olivier Fourdan
committed
{
TRACE ("atom net_wm_window_type_dock detected");
c->type = WINDOW_DOCK;
c->initial_layer = WIN_LAYER_DOCK;
FLAG_UNSET (c->xfwm_flags,
XFWM_FLAG_HAS_BORDER | XFWM_FLAG_HAS_MOVE |
XFWM_FLAG_HAS_HIDE | XFWM_FLAG_HAS_MAXIMIZE |
XFWM_FLAG_HAS_MENU | XFWM_FLAG_HAS_STICK);
Olivier Fourdan
committed
}
else if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_TOOLBAR])
Olivier Fourdan
committed
{
TRACE ("atom net_wm_window_type_toolbar detected");
c->type = WINDOW_TOOLBAR;
c->initial_layer = WIN_LAYER_NORMAL;
FLAG_UNSET (c->xfwm_flags,
XFWM_FLAG_HAS_HIDE | XFWM_FLAG_HAS_MAXIMIZE |
XFWM_FLAG_HAS_STICK);
Olivier Fourdan
committed
}
else if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_MENU])
Olivier Fourdan
committed
{
TRACE ("atom net_wm_window_type_menu detected");
c->type = WINDOW_MENU;
c->initial_layer = WIN_LAYER_NORMAL;
/* The policy here is unclear :
http://mail.gnome.org/archives/wm-spec-list/2002-May/msg00001.html
As it seems, GNOME and KDE don't treat menu the same way...
*/
FLAG_SET (c->flags,
CLIENT_FLAG_SKIP_PAGER | CLIENT_FLAG_SKIP_TASKBAR);
FLAG_UNSET (c->xfwm_flags,
XFWM_FLAG_HAS_HIDE | XFWM_FLAG_HAS_MAXIMIZE |
XFWM_FLAG_HAS_STICK);
Olivier Fourdan
committed
}
else if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_DIALOG])
Olivier Fourdan
committed
{
TRACE ("atom net_wm_window_type_dialog detected");
c->type = WINDOW_DIALOG;
c->initial_layer = WIN_LAYER_NORMAL;
}
else if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_NORMAL])
Olivier Fourdan
committed
{
TRACE ("atom net_wm_window_type_normal detected");
c->type = WINDOW_NORMAL;
c->initial_layer = WIN_LAYER_NORMAL;
}
else if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_UTILITY])
Olivier Fourdan
committed
{
TRACE ("atom net_wm_window_type_utility detected");
c->type = WINDOW_UTILITY;
c->initial_layer = WIN_LAYER_NORMAL;
}
else if (c->type_atom == display_info->atoms[NET_WM_WINDOW_TYPE_SPLASH])
Olivier Fourdan
committed
{
TRACE ("atom net_wm_window_type_splash detected");
Olivier Fourdan
committed
c->type = WINDOW_SPLASHSCREEN;
c->initial_layer = WIN_LAYER_ABOVE_DOCK;
FLAG_UNSET (c->xfwm_flags,
XFWM_FLAG_HAS_BORDER | XFWM_FLAG_HAS_HIDE |
XFWM_FLAG_HAS_MENU | XFWM_FLAG_HAS_MOVE |
XFWM_FLAG_HAS_RESIZE | XFWM_FLAG_HAS_STICK);
Olivier Fourdan
committed
}
}
else
{
TRACE ("no \"net\" atom detected");
c->type = UNSET;
c->initial_layer = c->win_layer;
}
Olivier Fourdan
committed
if (clientIsValidTransientOrModal (c))
Olivier Fourdan
committed
{
Client *c2;
TRACE ("Window \"%s\" is a transient or a modal", c->name);
c2 = clientGetHighestTransientOrModalFor (c);
if (c2)