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.
Olivier Fourdan
committed
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-2006 Olivier Fourdan
Olivier Fourdan
committed
*/
Olivier Fourdan
committed
#ifdef HAVE_CONFIG_H
Olivier Fourdan
committed
#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 "client.h"
Olivier Fourdan
committed
#include "compositor.h"
#include "display.h"
Olivier Fourdan
committed
#include "frame.h"
Olivier Fourdan
committed
#include "focus.h"
Olivier Fourdan
committed
#include "hints.h"
Olivier Fourdan
committed
#include "misc.h"
#include "netwm.h"
#include "screen.h"
Olivier Fourdan
committed
#include "stacking.h"
Olivier Fourdan
committed
#include "transients.h"
#include "workspaces.h"
Olivier Fourdan
committed
void
clientSetNetState (Client * c)
{
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
}
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,
Olivier Fourdan
committed
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;
DisplayInfo *display_info;
int n_atoms;
Atom *atoms;
Olivier Fourdan
committed
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;
DisplayInfo *display_info;
unsigned long action, mode;
Olivier Fourdan
committed
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;
action = ev->data.l[0];
first = ev->data.l[1];
second = ev->data.l[2];
Olivier Fourdan
committed
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);
}
Olivier Fourdan
committed
frameDraw (c, FALSE);
Olivier Fourdan
committed
}
}
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
{
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
{
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)
{
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);
}
Olivier Fourdan
committed
frameDraw (c, TRUE);
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 (!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 (!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
{
Olivier Fourdan
committed
compositorDamageWindow (display_info, c->frame);
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
{
Olivier Fourdan
committed
compositorDamageWindow (display_info, c->frame);
Olivier Fourdan
committed
FLAG_UNSET (c->flags, CLIENT_FLAG_BELOW);
Olivier Fourdan
committed
}
else if (action == NET_WM_STATE_TOGGLE)
{
Olivier Fourdan
committed
compositorDamageWindow (display_info, c->frame);
Olivier Fourdan
committed
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);
Olivier Fourdan
committed
}
Olivier Fourdan
committed
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_TEST (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION))
{
Olivier Fourdan
committed
/* Do not apply NET_WM_STATE_DEMANDS_ATTENTION if client is already focused */
if (c != clientGetFocusOrPending ())
{
FLAG_SET (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION);
clientSetNetState (c);
}
Olivier Fourdan
committed
}
else if ((action == NET_WM_STATE_REMOVE) && FLAG_TEST (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION))
{
FLAG_UNSET (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION);
clientSetNetState (c);
}
else if (action == NET_WM_STATE_TOGGLE)
{
Olivier Fourdan
committed
/* Do not apply NET_WM_STATE_DEMANDS_ATTENTION if client is already focused */
if (c != clientGetFocusOrPending () || !FLAG_TEST (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION))
{
FLAG_TOGGLE (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION);
clientSetNetState (c);
}
Olivier Fourdan
committed
}
}
Olivier Fourdan
committed
}
void
clientNetMoveResize (Client * c, XClientMessageEvent * ev)
{
ScreenInfo *screen_info;
DisplayInfo *display_info;
unsigned int button_mask;
int x_root, y_root, dx, dy, action, button;
int corner;
gboolean resize; /* true == resize, false == move */
g_return_if_fail (c != NULL);
TRACE ("entering clientNetMoveResize");
TRACE ("client \"%s\" (0x%lx)", c->name, c->window);
screen_info = c->screen_info;
display_info = screen_info->display_info;
x_root = (int) ev->data.l[0];
y_root = (int) ev->data.l[1];
action = (int) ev->data.l[2];
button = (int) ev->data.l[3];
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
if (button == 0)
{
button_mask = getMouseXY (screen_info, c->window, &dx, &dy);
if (button_mask & Button1Mask)
{
button = Button1;
}
else if (button_mask & Button2Mask)
{
button = Button2;
}
else if (button_mask & Button3Mask)
{
button = Button3;
}
else
{
g_warning ("Could not determine the mouse button used");
return;
}
}
corner = CORNER_BOTTOM_RIGHT;
resize = TRUE;
event->xbutton.button = button;
event->xbutton.x_root = event->xkey.x_root = x_root;
event->xbutton.y_root = event->xkey.y_root = y_root;
event->xbutton.time = event->xkey.time = myDisplayGetCurrentTime (display_info);
switch (action)
{
/* Keyboard */
case NET_WM_MOVERESIZE_SIZE_KEYBOARD:
corner = CORNER_BOTTOM_RIGHT;
resize = TRUE; /* Resize */
break;
case NET_WM_MOVERESIZE_MOVE_KEYBOARD:
resize = FALSE; /* Move */
break;
/* Sides */
case NET_WM_MOVERESIZE_SIZE_TOP:
corner = CORNER_COUNT + SIDE_TOP;
resize = TRUE; /* Resize */
break;
case NET_WM_MOVERESIZE_SIZE_BOTTOM:
corner = CORNER_COUNT + SIDE_BOTTOM;
resize = TRUE; /* Resize */
break;
case NET_WM_MOVERESIZE_SIZE_RIGHT:
corner = CORNER_COUNT + SIDE_RIGHT;
resize = TRUE; /* Resize */
break;
case NET_WM_MOVERESIZE_SIZE_LEFT:
corner = CORNER_COUNT + SIDE_LEFT;
resize = TRUE; /* Resize */
break;
/* Corners */
case NET_WM_MOVERESIZE_SIZE_TOPLEFT:
corner = CORNER_TOP_LEFT;
resize = TRUE; /* Resize */
break;
case NET_WM_MOVERESIZE_SIZE_TOPRIGHT:
corner = CORNER_TOP_RIGHT;
resize = TRUE; /* Resize */
break;
case NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT:
corner = CORNER_BOTTOM_LEFT;
resize = TRUE; /* Resize */
break;
case NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT:
corner = CORNER_BOTTOM_RIGHT;
resize = TRUE; /* Resize */
break;
case NET_WM_MOVERESIZE_MOVE:
default:
resize = FALSE; /* Move */
break;
}
if (!FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN))
{
if (resize && FLAG_TEST_ALL (c->xfwm_flags, XFWM_FLAG_HAS_RESIZE | XFWM_FLAG_IS_RESIZABLE))
{
}
else if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_MOVE))
{
Olivier Fourdan
committed
void
clientUpdateFullscreenState (Client * c)
{
Olivier Fourdan
committed
ScreenInfo *screen_info;
DisplayInfo *display_info;
Olivier Fourdan
committed
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);
Olivier Fourdan
committed
screen_info = c->screen_info;
display_info = screen_info->display_info;
Olivier Fourdan
committed
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
{
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
*/
Olivier Fourdan
committed
myScreenGrabPointer (c->screen_info, EnterWindowMask, None, myDisplayGetCurrentTime (display_info));
Olivier Fourdan
committed
clientConfigure (c, &wc, CWX | CWY | CWWidth | CWHeight, CFG_FORCE_REDRAW);
myScreenUngrabPointer (c->screen_info);
Olivier Fourdan
committed
}
else
{
c->x = wc.x;
c->y = wc.y;
c->height = wc.height;
c->width = wc.width;
}
clientSetLayer (c, layer);
/* Fullscreen has no decoration at all, update NET_FRAME_EXTENTS accordingly */
setNetFrameExtents (display_info,
c->window,
frameTop (c),
frameLeft (c),
frameRight (c),
frameBottom (c));
Olivier Fourdan
committed
}
void
clientGetNetWmType (Client * c)
{
ScreenInfo *screen_info;
DisplayInfo *display_info;
int n_atoms;
Atom *atoms;
Olivier Fourdan
committed
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;
DisplayInfo *display_info;
Client *c2;
long val;
Olivier Fourdan
committed
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
}
Olivier Fourdan
committed
{
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);
Olivier Fourdan
committed
}
}
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
gboolean
clientValidateNetStrut (Client * c)
{
ScreenInfo *screen_info;
gboolean valid;
int max_value;
int i;
g_return_val_if_fail (c != NULL, TRUE);
TRACE ("entering clientValidateNetStrut for \"%s\" (0x%lx)", c->name, c->window);
screen_info = c->screen_info;
max_value = MIN (screen_info->width, screen_info->height) / 4;
valid = TRUE;
for (i = 0; i < 4; i++)
{
if (c->struts[i] > max_value)
{
g_warning ("Strut value for application window 0x%lx changed from %d to %d", c->window, c->struts[i], max_value);
c->struts[i] = max_value;
valid = FALSE;
}
}
return valid;
}
gboolean
Olivier Fourdan
committed
clientGetNetStruts (Client * c)
{
unsigned long old_flags, new_flags;
int old_struts[STRUTS_SIZE];
Olivier Fourdan
committed
int nitems;
int i;
g_return_val_if_fail (c != NULL, FALSE);
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
/* Save old values */
old_flags = c->flags & (CLIENT_FLAG_HAS_STRUT | CLIENT_FLAG_HAS_STRUT_PARTIAL);
for (i = 0; i < STRUTS_SIZE; i++)
Olivier Fourdan
committed
{
old_struts[i] = c->struts[i];
Olivier Fourdan
committed
c->struts[i] = 0;
}
FLAG_UNSET (c->flags, CLIENT_FLAG_HAS_STRUT);
FLAG_UNSET (c->flags, CLIENT_FLAG_HAS_STRUT_PARTIAL);