2001-09-12 21:43:42 +00:00
/* wmspec.c-- support for the wm-spec Hints
2004-10-12 01:34:32 +00:00
*
2001-09-12 21:43:42 +00:00
* Window Maker window manager
2004-10-12 01:34:32 +00:00
*
2003-01-16 23:30:45 +00:00
* Copyright (c) 1998-2003 Alfredo K. Kojima
2004-10-12 01:34:32 +00:00
*
2001-09-12 21:43:42 +00:00
* 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 of the License, 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.
*
2010-10-08 01:32:11 +02:00
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2001-09-12 21:43:42 +00:00
*/
2005-01-08 22:53:39 +00:00
/*
* TODO
* ----
*
* This file needs to be checked for all calls to XGetWindowProperty() and
* proper checks need to be made on the returned values. Only checking for
* return to be Success is not enough. -Dan
*/
2001-09-12 21:43:42 +00:00
#include "wconfig.h"
#include <X11/Xlib.h>
#include <X11/Xatom.h>
2006-01-22 18:05:00 +00:00
#include <X11/Xarch.h>
2004-10-12 01:34:32 +00:00
#include <string.h>
2001-09-12 21:43:42 +00:00
#include "WindowMaker.h"
#include "window.h"
#include "screen.h"
2004-10-12 01:34:32 +00:00
#include "workspace.h"
2001-09-12 21:43:42 +00:00
#include "framewin.h"
#include "actions.h"
2004-10-12 01:34:32 +00:00
#include "client.h"
#include "wmspec.h"
#include "icon.h"
#include "stacking.h"
#include "xinerama.h"
2004-10-13 05:09:08 +00:00
#include "properties.h"
2001-09-12 21:43:42 +00:00
2004-10-12 01:34:32 +00:00
#ifdef DEBUG_WMSPEC
#include <stdio.h>
#endif
/* Global variables */
extern Atom _XA_WM_DELETE_WINDOW ;
extern Time LastTimestamp ;
extern WPreferences wPreferences ;
/* Root Window Properties */
2001-09-12 21:43:42 +00:00
static Atom net_supported ;
static Atom net_client_list ;
static Atom net_client_list_stacking ;
static Atom net_number_of_desktops ;
static Atom net_desktop_geometry ;
static Atom net_desktop_viewport ;
static Atom net_current_desktop ;
2004-10-12 01:34:32 +00:00
static Atom net_desktop_names ;
2001-09-12 21:43:42 +00:00
static Atom net_active_window ;
2009-08-20 00:59:40 +02:00
static Atom net_workarea ; /* XXX: not xinerama compatible */
2001-09-12 21:43:42 +00:00
static Atom net_supporting_wm_check ;
2009-08-20 00:59:40 +02:00
static Atom net_virtual_roots ; /* N/A */
static Atom net_desktop_layout ; /* XXX */
2004-10-12 01:34:32 +00:00
static Atom net_showing_desktop ;
/* Other Root Window Messages */
static Atom net_close_window ;
2009-08-20 00:59:40 +02:00
static Atom net_moveresize_window ; /* TODO */
static Atom net_wm_moveresize ; /* TODO */
2004-10-12 01:34:32 +00:00
/* Application Window Properties */
2004-10-16 22:05:04 +00:00
static Atom net_wm_name ;
2009-08-20 00:59:40 +02:00
static Atom net_wm_visible_name ; /* TODO (unnecessary?) */
2004-10-16 22:05:04 +00:00
static Atom net_wm_icon_name ;
2009-08-20 00:59:40 +02:00
static Atom net_wm_visible_icon_name ; /* TODO (unnecessary?) */
2001-09-12 21:43:42 +00:00
static Atom net_wm_desktop ;
2004-10-12 01:34:32 +00:00
static Atom net_wm_window_type ;
static Atom net_wm_window_type_desktop ;
static Atom net_wm_window_type_dock ;
static Atom net_wm_window_type_toolbar ;
static Atom net_wm_window_type_menu ;
static Atom net_wm_window_type_utility ;
static Atom net_wm_window_type_splash ;
static Atom net_wm_window_type_dialog ;
static Atom net_wm_window_type_normal ;
2001-09-12 21:43:42 +00:00
static Atom net_wm_state ;
2009-08-20 00:59:40 +02:00
static Atom net_wm_state_modal ; /* XXX: what is this?!? */
2001-09-12 21:43:42 +00:00
static Atom net_wm_state_sticky ;
static Atom net_wm_state_maximized_vert ;
static Atom net_wm_state_maximized_horz ;
static Atom net_wm_state_shaded ;
static Atom net_wm_state_skip_taskbar ;
static Atom net_wm_state_skip_pager ;
2004-10-12 01:34:32 +00:00
static Atom net_wm_state_hidden ;
static Atom net_wm_state_fullscreen ;
static Atom net_wm_state_above ;
static Atom net_wm_state_below ;
static Atom net_wm_allowed_actions ;
static Atom net_wm_action_move ;
static Atom net_wm_action_resize ;
static Atom net_wm_action_minimize ;
static Atom net_wm_action_shade ;
static Atom net_wm_action_stick ;
static Atom net_wm_action_maximize_horz ;
static Atom net_wm_action_maximize_vert ;
static Atom net_wm_action_fullscreen ;
static Atom net_wm_action_change_desktop ;
static Atom net_wm_action_close ;
2009-08-20 00:59:40 +02:00
static Atom net_wm_strut ; /* XXX: see net_workarea */
static Atom net_wm_strut_partial ; /* TODO: doesn't really fit into the current strut scheme */
static Atom net_wm_icon_geometry ; /* FIXME: should work together with net_wm_handled_icons, gnome-panel-2.2.0.1 doesn't use _NET_WM_HANDLED_ICONS, thus present situation. */
2004-10-12 01:34:32 +00:00
static Atom net_wm_icon ;
2009-08-20 00:59:40 +02:00
static Atom net_wm_pid ; /* TODO */
static Atom net_wm_handled_icons ; /* FIXME: see net_wm_icon_geometry */
2004-10-12 01:34:32 +00:00
/* Window Manager Protocols */
2009-08-20 00:59:40 +02:00
static Atom net_wm_ping ; /* TODO */
2004-10-12 01:34:32 +00:00
static Atom utf8_string ;
typedef struct {
2009-08-20 00:59:40 +02:00
char * name ;
Atom * atom ;
2004-10-12 01:34:32 +00:00
} atomitem_t ;
static atomitem_t atomNames [] = {
2009-08-20 00:59:40 +02:00
{ "_NET_SUPPORTED" , & net_supported },
{ "_NET_CLIENT_LIST" , & net_client_list },
{ "_NET_CLIENT_LIST_STACKING" , & net_client_list_stacking },
{ "_NET_NUMBER_OF_DESKTOPS" , & net_number_of_desktops },
{ "_NET_DESKTOP_GEOMETRY" , & net_desktop_geometry },
{ "_NET_DESKTOP_VIEWPORT" , & net_desktop_viewport },
{ "_NET_CURRENT_DESKTOP" , & net_current_desktop },
{ "_NET_DESKTOP_NAMES" , & net_desktop_names },
{ "_NET_ACTIVE_WINDOW" , & net_active_window },
{ "_NET_WORKAREA" , & net_workarea },
{ "_NET_SUPPORTING_WM_CHECK" , & net_supporting_wm_check },
{ "_NET_VIRTUAL_ROOTS" , & net_virtual_roots },
{ "_NET_DESKTOP_LAYOUT" , & net_desktop_layout },
{ "_NET_SHOWING_DESKTOP" , & net_showing_desktop },
{ "_NET_CLOSE_WINDOW" , & net_close_window },
{ "_NET_MOVERESIZE_WINDOW" , & net_moveresize_window },
{ "_NET_WM_MOVERESIZE" , & net_wm_moveresize },
{ "_NET_WM_NAME" , & net_wm_name },
{ "_NET_WM_VISIBLE_NAME" , & net_wm_visible_name },
{ "_NET_WM_ICON_NAME" , & net_wm_icon_name },
{ "_NET_WM_VISIBLE_ICON_NAME" , & net_wm_visible_icon_name },
{ "_NET_WM_DESKTOP" , & net_wm_desktop },
{ "_NET_WM_WINDOW_TYPE" , & net_wm_window_type },
{ "_NET_WM_WINDOW_TYPE_DESKTOP" , & net_wm_window_type_desktop },
{ "_NET_WM_WINDOW_TYPE_DOCK" , & net_wm_window_type_dock },
{ "_NET_WM_WINDOW_TYPE_TOOLBAR" , & net_wm_window_type_toolbar },
{ "_NET_WM_WINDOW_TYPE_MENU" , & net_wm_window_type_menu },
{ "_NET_WM_WINDOW_TYPE_UTILITY" , & net_wm_window_type_utility },
{ "_NET_WM_WINDOW_TYPE_SPLASH" , & net_wm_window_type_splash },
{ "_NET_WM_WINDOW_TYPE_DIALOG" , & net_wm_window_type_dialog },
{ "_NET_WM_WINDOW_TYPE_NORMAL" , & net_wm_window_type_normal },
{ "_NET_WM_STATE" , & net_wm_state },
{ "_NET_WM_STATE_MODAL" , & net_wm_state_modal },
{ "_NET_WM_STATE_STICKY" , & net_wm_state_sticky },
{ "_NET_WM_STATE_MAXIMIZED_VERT" , & net_wm_state_maximized_vert },
{ "_NET_WM_STATE_MAXIMIZED_HORZ" , & net_wm_state_maximized_horz },
{ "_NET_WM_STATE_SHADED" , & net_wm_state_shaded },
{ "_NET_WM_STATE_SKIP_TASKBAR" , & net_wm_state_skip_taskbar },
{ "_NET_WM_STATE_SKIP_PAGER" , & net_wm_state_skip_pager },
{ "_NET_WM_STATE_HIDDEN" , & net_wm_state_hidden },
{ "_NET_WM_STATE_FULLSCREEN" , & net_wm_state_fullscreen },
{ "_NET_WM_STATE_ABOVE" , & net_wm_state_above },
{ "_NET_WM_STATE_BELOW" , & net_wm_state_below },
{ "_NET_WM_ALLOWED_ACTIONS" , & net_wm_allowed_actions },
{ "_NET_WM_ACTION_MOVE" , & net_wm_action_move },
{ "_NET_WM_ACTION_RESIZE" , & net_wm_action_resize },
{ "_NET_WM_ACTION_MINIMIZE" , & net_wm_action_minimize },
{ "_NET_WM_ACTION_SHADE" , & net_wm_action_shade },
{ "_NET_WM_ACTION_STICK" , & net_wm_action_stick },
{ "_NET_WM_ACTION_MAXIMIZE_HORZ" , & net_wm_action_maximize_horz },
{ "_NET_WM_ACTION_MAXIMIZE_VERT" , & net_wm_action_maximize_vert },
{ "_NET_WM_ACTION_FULLSCREEN" , & net_wm_action_fullscreen },
{ "_NET_WM_ACTION_CHANGE_DESKTOP" , & net_wm_action_change_desktop },
{ "_NET_WM_ACTION_CLOSE" , & net_wm_action_close },
{ "_NET_WM_STRUT" , & net_wm_strut },
{ "_NET_WM_STRUT_PARTIAL" , & net_wm_strut_partial },
{ "_NET_WM_ICON_GEOMETRY" , & net_wm_icon_geometry },
{ "_NET_WM_ICON" , & net_wm_icon },
{ "_NET_WM_PID" , & net_wm_pid },
{ "_NET_WM_HANDLED_ICONS" , & net_wm_handled_icons },
{ "_NET_WM_PING" , & net_wm_ping },
{ "UTF8_STRING" , & utf8_string },
2004-10-12 01:34:32 +00:00
};
2001-09-12 21:43:42 +00:00
2004-10-12 01:34:32 +00:00
#define atomNr (sizeof(atomNames)/sizeof(atomitem_t))
2001-09-12 21:43:42 +00:00
2004-10-12 01:34:32 +00:00
#define _NET_WM_STATE_REMOVE 0
#define _NET_WM_STATE_ADD 1
#define _NET_WM_STATE_TOGGLE 2
2001-09-12 21:43:42 +00:00
2004-10-12 01:34:32 +00:00
#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
#define _NET_WM_MOVERESIZE_SIZE_TOP 1
#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
2009-08-20 00:59:40 +02:00
#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
2001-09-12 21:43:42 +00:00
2009-08-20 00:59:40 +02:00
static void observer ( void * self , WMNotification * notif );
static void wsobserver ( void * self , WMNotification * notif );
2001-09-12 21:43:42 +00:00
2009-08-20 00:59:40 +02:00
static void updateClientList ( WScreen * scr );
static void updateClientListStacking ( WScreen * scr , WWindow * );
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
static void updateWorkspaceNames ( WScreen * scr );
static void updateCurrentWorkspace ( WScreen * scr );
static void updateWorkspaceCount ( WScreen * scr );
2001-09-12 21:43:42 +00:00
typedef struct NetData {
2009-08-20 00:59:40 +02:00
WScreen * scr ;
WReservedArea * strut ;
WWindow ** show_desktop ;
2001-09-12 21:43:42 +00:00
} NetData ;
2009-08-20 00:59:40 +02:00
static void setSupportedHints ( WScreen * scr )
2001-09-12 21:43:42 +00:00
{
2009-08-20 00:59:40 +02:00
Atom atom [ atomNr ];
int i = 0 ;
/* set supported hints list */
/* XXX: extend this !!! */
atom [ i ++ ] = net_client_list ;
atom [ i ++ ] = net_client_list_stacking ;
atom [ i ++ ] = net_number_of_desktops ;
atom [ i ++ ] = net_desktop_geometry ;
atom [ i ++ ] = net_desktop_viewport ;
atom [ i ++ ] = net_current_desktop ;
atom [ i ++ ] = net_desktop_names ;
atom [ i ++ ] = net_active_window ;
atom [ i ++ ] = net_workarea ;
atom [ i ++ ] = net_supporting_wm_check ;
atom [ i ++ ] = net_showing_desktop ;
2004-10-12 01:34:32 +00:00
#if 0
2009-08-20 00:59:40 +02:00
atom[i++] = net_wm_moveresize;
2004-10-12 01:34:32 +00:00
#endif
2009-08-20 00:59:40 +02:00
atom [ i ++ ] = net_wm_desktop ;
atom [ i ++ ] = net_wm_window_type ;
atom [ i ++ ] = net_wm_window_type_desktop ;
atom [ i ++ ] = net_wm_window_type_dock ;
atom [ i ++ ] = net_wm_window_type_toolbar ;
atom [ i ++ ] = net_wm_window_type_menu ;
atom [ i ++ ] = net_wm_window_type_utility ;
atom [ i ++ ] = net_wm_window_type_splash ;
atom [ i ++ ] = net_wm_window_type_dialog ;
atom [ i ++ ] = net_wm_window_type_normal ;
atom [ i ++ ] = net_wm_state ;
/* atom[i++] = net_wm_state_modal; *//* XXX: not sure where/when to use it. */
atom [ i ++ ] = net_wm_state_sticky ;
atom [ i ++ ] = net_wm_state_shaded ;
atom [ i ++ ] = net_wm_state_maximized_horz ;
atom [ i ++ ] = net_wm_state_maximized_vert ;
atom [ i ++ ] = net_wm_state_skip_taskbar ;
atom [ i ++ ] = net_wm_state_skip_pager ;
atom [ i ++ ] = net_wm_state_hidden ;
atom [ i ++ ] = net_wm_state_fullscreen ;
atom [ i ++ ] = net_wm_state_above ;
atom [ i ++ ] = net_wm_state_below ;
atom [ i ++ ] = net_wm_allowed_actions ;
atom [ i ++ ] = net_wm_action_move ;
atom [ i ++ ] = net_wm_action_resize ;
atom [ i ++ ] = net_wm_action_minimize ;
atom [ i ++ ] = net_wm_action_shade ;
atom [ i ++ ] = net_wm_action_stick ;
atom [ i ++ ] = net_wm_action_maximize_horz ;
atom [ i ++ ] = net_wm_action_maximize_vert ;
atom [ i ++ ] = net_wm_action_fullscreen ;
atom [ i ++ ] = net_wm_action_change_desktop ;
atom [ i ++ ] = net_wm_action_close ;
atom [ i ++ ] = net_wm_strut ;
atom [ i ++ ] = net_wm_icon_geometry ;
atom [ i ++ ] = net_wm_icon ;
atom [ i ++ ] = net_wm_handled_icons ;
atom [ i ++ ] = net_wm_name ;
atom [ i ++ ] = net_wm_icon_name ;
XChangeProperty ( dpy , scr -> root_win , net_supported , XA_ATOM , 32 , PropModeReplace , ( unsigned char * ) atom , i );
/* set supporting wm hint */
XChangeProperty ( dpy , scr -> root_win , net_supporting_wm_check , XA_WINDOW , 32 ,
PropModeReplace , ( unsigned char * ) & scr -> info_window , 1 );
XChangeProperty ( dpy , scr -> info_window , net_supporting_wm_check , XA_WINDOW ,
32 , PropModeReplace , ( unsigned char * ) & scr -> info_window , 1 );
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
void wNETWMUpdateDesktop ( WScreen * scr )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
long * views , sizes [ 2 ];
int count , i ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
if ( scr -> workspace_count == 0 )
return ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
count = scr -> workspace_count * 2 ;
views = wmalloc ( sizeof ( long ) * count );
/*memset(views, 0, sizeof(long) * count); */
sizes [ 0 ] = scr -> scr_width ;
sizes [ 1 ] = scr -> scr_height ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
for ( i = 0 ; i < scr -> workspace_count ; i ++ ) {
views [ 2 * i + 0 ] = 0 ;
views [ 2 * i + 1 ] = 0 ;
}
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
XChangeProperty ( dpy , scr -> root_win , net_desktop_geometry , XA_CARDINAL , 32 ,
PropModeReplace , ( unsigned char * ) sizes , 2 );
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
XChangeProperty ( dpy , scr -> root_win , net_desktop_viewport , XA_CARDINAL , 32 ,
PropModeReplace , ( unsigned char * ) views , count );
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
wfree ( views );
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
int wNETWMGetCurrentDesktopFromHint ( WScreen * scr )
2004-10-13 05:09:08 +00:00
{
2009-08-20 00:59:40 +02:00
int count ;
unsigned char * prop ;
prop = PropGetCheckProperty ( scr -> root_win , net_current_desktop , XA_CARDINAL , 0 , 1 , & count );
if ( prop ) {
int desktop = * ( long * ) prop ;
XFree ( prop );
return desktop ;
}
return - 1 ;
2004-10-13 05:09:08 +00:00
}
2005-01-08 22:53:39 +00:00
/*
* Find the best icon to be used by Window Maker for appicon/miniwindows.
* Currently the algorithm is to take the image with the size closest
* to icon_size x icon_size, but never bigger than that.
*
* This algorithm is very poorly implemented and needs to be redone (it can
* easily select images with very large widths and very small heights over
* square images, if the area of the former is closer to the desired one).
*
* The logic can also be changed to accept bigger images and scale them down.
*/
2009-08-20 00:59:40 +02:00
static unsigned long * findBestIcon ( unsigned long * data , unsigned long items )
2005-01-08 22:53:39 +00:00
{
2009-08-20 00:59:40 +02:00
int size , wanted , d ;
unsigned long i , distance ;
unsigned long * icon ;
/* better use only 75% of icon_size. For 64x64 this means 48x48
* This leaves room around the icon for the miniwindow title and
* results in better overall aesthetics -Dan */
wanted = wPreferences . icon_size * wPreferences . icon_size ;
2009-08-21 01:49:24 +02:00
for ( icon = NULL , distance = wanted , i = 0L ; i < items - 1 ;) {
2009-08-20 00:59:40 +02:00
size = data [ i ] * data [ i + 1 ];
if ( size == 0 )
break ;
d = wanted - size ;
if ( d >= 0 && d <= distance && ( i + size + 2 ) <= items ) {
distance = d ;
icon = & data [ i ];
}
i += size + 2 ;
}
return icon ;
2005-01-08 22:53:39 +00:00
}
2009-08-20 00:59:40 +02:00
static RImage * makeRImageFromARGBData ( unsigned long * data )
2005-01-08 22:53:39 +00:00
{
2009-08-20 00:59:40 +02:00
int size , width , height , i ;
RImage * image ;
unsigned char * imgdata ;
unsigned long pixel ;
2005-01-08 22:53:39 +00:00
2009-08-20 00:59:40 +02:00
width = data [ 0 ];
height = data [ 1 ];
size = width * height ;
2005-01-08 22:53:39 +00:00
2009-08-20 00:59:40 +02:00
if ( size == 0 )
return NULL ;
2005-01-08 22:53:39 +00:00
2009-08-20 00:59:40 +02:00
image = RCreateImage ( width , height , True );
2005-01-08 22:53:39 +00:00
2009-08-20 00:59:40 +02:00
for ( imgdata = image -> data , i = 2 ; i < size + 2 ; i ++ , imgdata += 4 ) {
pixel = data [ i ];
2006-01-22 18:05:00 +00:00
#if BYTE_ORDER == BIG_ENDIAN
2009-08-20 00:59:40 +02:00
imgdata [ 2 ] = ( pixel >> 24 ) & 0xff ; /* A */
imgdata [ 1 ] = ( pixel >> 16 ) & 0xff ; /* R */
imgdata [ 0 ] = ( pixel >> 8 ) & 0xff ; /* G */
imgdata [ 3 ] = ( pixel >> 0 ) & 0xff ; /* B */
#else /* Little endian */
imgdata [ 3 ] = ( pixel >> 24 ) & 0xff ; /* A */
imgdata [ 0 ] = ( pixel >> 16 ) & 0xff ; /* R */
imgdata [ 1 ] = ( pixel >> 8 ) & 0xff ; /* G */
imgdata [ 2 ] = ( pixel >> 0 ) & 0xff ; /* B */
#endif /* endianness */
}
return image ;
2005-01-08 22:53:39 +00:00
}
2009-08-20 00:59:40 +02:00
static void updateIconImage ( WScreen * scr , WWindow * wwin )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
unsigned long * property , * data ;
unsigned long items , rest ;
Atom type ;
int format ;
RImage * image ;
if ( XGetWindowProperty ( dpy , wwin -> client_win , net_wm_icon , 0L , LONG_MAX ,
False , XA_CARDINAL , & type , & format , & items , & rest ,
( unsigned char ** ) & property ) != Success || ! property ) {
return ;
}
if ( type != XA_CARDINAL || format != 32 || items < 2 ) {
XFree ( property );
return ;
}
data = findBestIcon ( property , items );
if ( ! data ) {
XFree ( property );
return ;
}
image = makeRImageFromARGBData ( data );
if ( image ) {
if ( wwin -> net_icon_image )
RReleaseImage ( wwin -> net_icon_image );
wwin -> net_icon_image = image ;
}
XFree ( property );
2004-10-12 01:34:32 +00:00
}
2001-09-12 21:43:42 +00:00
2009-08-20 00:59:40 +02:00
static void updateShowDesktop ( WScreen * scr , Bool show )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
long foo ;
2001-09-12 21:43:42 +00:00
2009-08-20 00:59:40 +02:00
foo = ( show == True );
XChangeProperty ( dpy , scr -> root_win , net_showing_desktop , XA_CARDINAL , 32 ,
PropModeReplace , ( unsigned char * ) & foo , 1 );
2001-09-12 21:43:42 +00:00
}
2009-08-20 00:59:40 +02:00
void wNETWMShowingDesktop ( WScreen * scr , Bool show )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
if ( show && scr -> netdata -> show_desktop == NULL ) {
WWindow * tmp , ** wins ;
int i = 0 ;
wins = ( WWindow ** ) wmalloc ( sizeof ( WWindow * ) * ( scr -> window_count + 1 ));
tmp = scr -> focused_window ;
while ( tmp ) {
if ( ! tmp -> flags . hidden && ! tmp -> flags . miniaturized && ! WFLAGP ( tmp , skip_window_list )) {
wins [ i ++ ] = tmp ;
tmp -> flags . skip_next_animation = 1 ;
tmp -> flags . net_show_desktop = 1 ;
wIconifyWindow ( tmp );
}
tmp = tmp -> prev ;
}
wins [ i ++ ] = NULL ;
scr -> netdata -> show_desktop = wins ;
updateShowDesktop ( scr , True );
} else if ( scr -> netdata -> show_desktop != NULL ) {
/* FIXME: get rid of workspace flashing ! */
int ws = scr -> current_workspace ;
WWindow ** tmp ;
for ( tmp = scr -> netdata -> show_desktop ; * tmp ; ++ tmp ) {
wDeiconifyWindow ( * tmp );
( * tmp ) -> flags . net_show_desktop = 0 ;
}
if ( ws != scr -> current_workspace )
wWorkspaceChange ( scr , ws );
wfree ( scr -> netdata -> show_desktop );
scr -> netdata -> show_desktop = NULL ;
updateShowDesktop ( scr , False );
}
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
void wNETWMInitStuff ( WScreen * scr )
2001-09-12 21:43:42 +00:00
{
2009-08-20 00:59:40 +02:00
NetData * data ;
int i ;
2004-10-12 01:34:32 +00:00
#ifdef DEBUG_WMSPEC
2009-08-20 00:59:40 +02:00
printf ( "wNETWMInitStuff \n " );
2004-10-12 01:34:32 +00:00
#endif
2001-09-12 21:43:42 +00:00
#ifdef HAVE_XINTERNATOMS
2009-08-20 00:59:40 +02:00
{
Atom atoms [ atomNr ];
char * names [ atomNr ];
for ( i = 0 ; i < atomNr ; ++ i ) {
names [ i ] = atomNames [ i ]. name ;
}
XInternAtoms ( dpy , & names [ 0 ], atomNr , False , atoms );
for ( i = 0 ; i < atomNr ; ++ i ) {
* atomNames [ i ]. atom = atoms [ i ];
}
}
2004-10-12 01:34:32 +00:00
#else
2009-08-20 00:59:40 +02:00
for ( i = 0 ; i < atomNr ; i ++ ) {
* atomNames [ i ]. atom = XInternAtom ( dpy , atomNames [ i ]. name , False );
}
2001-09-12 21:43:42 +00:00
#endif
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
data = wmalloc ( sizeof ( NetData ));
data -> scr = scr ;
data -> strut = NULL ;
data -> show_desktop = NULL ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
scr -> netdata = data ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
setSupportedHints ( scr );
2001-09-12 21:43:42 +00:00
2009-08-20 00:59:40 +02:00
WMAddNotificationObserver ( observer , data , WMNManaged , NULL );
WMAddNotificationObserver ( observer , data , WMNUnmanaged , NULL );
WMAddNotificationObserver ( observer , data , WMNChangedWorkspace , NULL );
WMAddNotificationObserver ( observer , data , WMNChangedState , NULL );
WMAddNotificationObserver ( observer , data , WMNChangedFocus , NULL );
WMAddNotificationObserver ( observer , data , WMNChangedStacking , NULL );
WMAddNotificationObserver ( observer , data , WMNChangedName , NULL );
2001-09-12 21:43:42 +00:00
2009-08-20 00:59:40 +02:00
WMAddNotificationObserver ( wsobserver , data , WMNWorkspaceCreated , NULL );
WMAddNotificationObserver ( wsobserver , data , WMNWorkspaceDestroyed , NULL );
WMAddNotificationObserver ( wsobserver , data , WMNWorkspaceChanged , NULL );
WMAddNotificationObserver ( wsobserver , data , WMNWorkspaceNameChanged , NULL );
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
updateClientList ( scr );
updateClientListStacking ( scr , NULL );
updateWorkspaceCount ( scr );
updateWorkspaceNames ( scr );
updateShowDesktop ( scr , False );
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
wScreenUpdateUsableArea ( scr );
2001-09-12 21:43:42 +00:00
}
2009-08-20 00:59:40 +02:00
void wNETWMCleanup ( WScreen * scr )
2004-10-16 22:05:04 +00:00
{
2009-08-20 00:59:40 +02:00
int i ;
2004-10-16 22:05:04 +00:00
2009-08-20 00:59:40 +02:00
for ( i = 0 ; i < atomNr ; i ++ )
XDeleteProperty ( dpy , scr -> root_win , * atomNames [ i ]. atom );
2004-10-16 22:05:04 +00:00
}
2009-08-20 00:59:40 +02:00
void wNETWMUpdateActions ( WWindow * wwin , Bool del )
2001-09-12 21:43:42 +00:00
{
2009-08-20 00:59:40 +02:00
Atom action [ 10 ]; /* nr of actions atoms defined */
int i = 0 ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
if ( del ) {
XDeleteProperty ( dpy , wwin -> client_win , net_wm_allowed_actions );
return ;
}
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
if ( IS_MOVABLE ( wwin ))
action [ i ++ ] = net_wm_action_move ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
if ( IS_RESIZABLE ( wwin ))
action [ i ++ ] = net_wm_action_resize ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
if ( ! WFLAGP ( wwin , no_miniaturizable ))
action [ i ++ ] = net_wm_action_minimize ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
if ( ! WFLAGP ( wwin , no_shadeable ))
action [ i ++ ] = net_wm_action_shade ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
/* if (!WFLAGP(wwin, no_stickable)) */
action [ i ++ ] = net_wm_action_stick ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
/* if (!(WFLAGP(wwin, no_maximizeable) & MAX_HORIZONTAL)) */
if ( IS_RESIZABLE ( wwin ))
action [ i ++ ] = net_wm_action_maximize_horz ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
/* if (!(WFLAGP(wwin, no_maximizeable) & MAX_VERTICAL)) */
if ( IS_RESIZABLE ( wwin ))
action [ i ++ ] = net_wm_action_maximize_vert ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
/* if (!WFLAGP(wwin, no_fullscreen)) */
action [ i ++ ] = net_wm_action_fullscreen ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
/* if (!WFLAGP(wwin, no_change_desktop)) */
action [ i ++ ] = net_wm_action_change_desktop ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
if ( ! WFLAGP ( wwin , no_closable ))
action [ i ++ ] = net_wm_action_close ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
XChangeProperty ( dpy , wwin -> client_win , net_wm_allowed_actions ,
XA_ATOM , 32 , PropModeReplace , ( unsigned char * ) action , i );
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
void wNETWMUpdateWorkarea ( WScreen * scr , WArea usableArea )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
long * area ;
int count , i ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
/* XXX: not Xinerama compatible,
xinerama gets the largest available */
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
if ( ! scr -> netdata || scr -> workspace_count == 0 )
return ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
count = scr -> workspace_count * 4 ;
area = wmalloc ( sizeof ( long ) * count );
for ( i = 0 ; i < scr -> workspace_count ; i ++ ) {
area [ 4 * i + 0 ] = usableArea . x1 ;
area [ 4 * i + 1 ] = usableArea . y1 ;
area [ 4 * i + 2 ] = usableArea . x2 - usableArea . x1 ;
area [ 4 * i + 3 ] = usableArea . y2 - usableArea . y1 ;
}
2001-09-12 21:43:42 +00:00
2009-08-20 00:59:40 +02:00
XChangeProperty ( dpy , scr -> root_win , net_workarea , XA_CARDINAL , 32 ,
PropModeReplace , ( unsigned char * ) area , count );
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
wfree ( area );
2001-09-12 21:43:42 +00:00
}
2009-08-20 00:59:40 +02:00
Bool wNETWMGetUsableArea ( WScreen * scr , int head , WArea * area )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
WReservedArea * cur ;
WMRect rect ;
if ( ! scr -> netdata || ! scr -> netdata -> strut )
return False ;
area -> x1 = area -> y1 = area -> x2 = area -> y2 = 0 ;
for ( cur = scr -> netdata -> strut ; cur ; cur = cur -> next ) {
WWindow * wwin = wWindowFor ( cur -> window );
if ( wWindowTouchesHead ( wwin , head )) {
if ( cur -> area . x1 > area -> x1 )
area -> x1 = cur -> area . x1 ;
if ( cur -> area . y1 > area -> y1 )
area -> y1 = cur -> area . y1 ;
if ( cur -> area . x2 > area -> x2 )
area -> x2 = cur -> area . x2 ;
if ( cur -> area . y2 > area -> y2 )
area -> y2 = cur -> area . y2 ;
}
}
if ( area -> x1 == 0 && area -> x2 == 0 && area -> y1 == 0 && area -> y2 == 0 )
return False ;
rect = wGetRectForHead ( scr , head );
area -> x1 = rect . pos . x + area -> x1 ;
area -> x2 = rect . pos . x + rect . size . width - area -> x2 ;
area -> y1 = rect . pos . y + area -> y1 ;
area -> y2 = rect . pos . y + rect . size . height - area -> y2 ;
return True ;
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
static void updateClientList ( WScreen * scr )
2001-09-12 21:43:42 +00:00
{
2009-08-20 00:59:40 +02:00
WWindow * wwin ;
Window * windows ;
int count ;
windows = ( Window * ) wmalloc ( sizeof ( Window ) * ( scr -> window_count + 1 ));
count = 0 ;
wwin = scr -> focused_window ;
while ( wwin ) {
windows [ count ++ ] = wwin -> client_win ;
wwin = wwin -> prev ;
}
XChangeProperty ( dpy , scr -> root_win , net_client_list , XA_WINDOW , 32 ,
PropModeReplace , ( unsigned char * ) windows , count );
wfree ( windows );
XFlush ( dpy );
2001-09-12 21:43:42 +00:00
}
2009-08-20 00:59:40 +02:00
static void updateClientListStacking ( WScreen * scr , WWindow * wwin_excl )
2001-09-12 21:43:42 +00:00
{
2009-08-20 00:59:40 +02:00
WWindow * wwin ;
Window * client_list ;
Window * client_list_reverse ;
int client_count ;
WCoreWindow * tmp ;
WMBagIterator iter ;
int i ;
/* update client list */
i = scr -> window_count + 1 ;
client_list = ( Window * ) wmalloc ( sizeof ( Window ) * i );
client_list_reverse = ( Window * ) wmalloc ( sizeof ( Window ) * i );
client_count = 0 ;
WM_ETARETI_BAG ( scr -> stacking_list , tmp , iter ) {
while ( tmp ) {
wwin = wWindowFor ( tmp -> window );
/* wwin_excl is a window to exclude from the list
(e.g. it's now unmanaged) */
if ( wwin && ( wwin != wwin_excl ))
client_list [ client_count ++ ] = wwin -> client_win ;
tmp = tmp -> stacking -> under ;
}
}
for ( i = 0 ; i < client_count ; i ++ ) {
Window w = client_list [ client_count - i - 1 ];
client_list_reverse [ i ] = w ;
}
XChangeProperty ( dpy , scr -> root_win , net_client_list_stacking , XA_WINDOW , 32 ,
PropModeReplace , ( unsigned char * ) client_list_reverse , client_count );
wfree ( client_list );
wfree ( client_list_reverse );
XFlush ( dpy );
2001-09-12 21:43:42 +00:00
}
2009-08-20 00:59:40 +02:00
static void updateWorkspaceCount ( WScreen * scr )
{ /* changeable */
long count ;
2001-09-12 21:43:42 +00:00
2009-08-20 00:59:40 +02:00
count = scr -> workspace_count ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
XChangeProperty ( dpy , scr -> root_win , net_number_of_desktops , XA_CARDINAL ,
32 , PropModeReplace , ( unsigned char * ) & count , 1 );
2001-09-12 21:43:42 +00:00
}
2009-08-20 00:59:40 +02:00
static void updateCurrentWorkspace ( WScreen * scr )
{ /* changeable */
long count ;
2001-09-12 21:43:42 +00:00
2009-08-20 00:59:40 +02:00
count = scr -> current_workspace ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
XChangeProperty ( dpy , scr -> root_win , net_current_desktop , XA_CARDINAL , 32 ,
PropModeReplace , ( unsigned char * ) & count , 1 );
2001-09-12 21:43:42 +00:00
}
2009-08-20 00:59:40 +02:00
static void updateWorkspaceNames ( WScreen * scr )
2001-09-12 21:43:42 +00:00
{
2009-08-20 00:59:40 +02:00
char buf [ MAX_WORKSPACES * ( MAX_WORKSPACENAME_WIDTH + 1 )], * pos ;
unsigned int i , len , curr_size ;
pos = buf ;
len = 0 ;
for ( i = 0 ; i < scr -> workspace_count ; i ++ ) {
curr_size = strlen ( scr -> workspaces [ i ] -> name );
strcpy ( pos , scr -> workspaces [ i ] -> name );
pos += ( curr_size + 1 );
len += ( curr_size + 1 );
}
XChangeProperty ( dpy , scr -> root_win , net_desktop_names , utf8_string , 8 ,
PropModeReplace , ( unsigned char * ) buf , len );
2001-09-12 21:43:42 +00:00
}
2009-08-20 00:59:40 +02:00
static void updateFocusHint ( WScreen * scr , WWindow * wwin )
{ /* changeable */
Window window ;
2001-09-12 21:43:42 +00:00
2009-08-20 00:59:40 +02:00
if ( ! scr -> focused_window || ! scr -> focused_window -> flags . focused )
window = None ;
else
window = scr -> focused_window -> client_win ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
XChangeProperty ( dpy , scr -> root_win , net_active_window , XA_WINDOW , 32 ,
PropModeReplace , ( unsigned char * ) & window , 1 );
2001-09-12 21:43:42 +00:00
}
2009-08-20 00:59:40 +02:00
static void updateWorkspaceHint ( WWindow * wwin , Bool fake , Bool del )
2001-09-12 21:43:42 +00:00
{
2009-08-20 00:59:40 +02:00
long l ;
if ( del ) {
XDeleteProperty ( dpy , wwin -> client_win , net_wm_desktop );
} else {
l = (( fake || IS_OMNIPRESENT ( wwin )) ? - 1 : wwin -> frame -> workspace );
XChangeProperty ( dpy , wwin -> client_win , net_wm_desktop , XA_CARDINAL ,
32 , PropModeReplace , ( unsigned char * ) & l , 1 );
}
2001-09-12 21:43:42 +00:00
}
2009-08-20 00:59:40 +02:00
static void updateStateHint ( WWindow * wwin , Bool changedWorkspace , Bool del )
{ /* changeable */
if ( del ) {
if ( ! wwin -> flags . net_state_from_client ) {
XDeleteProperty ( dpy , wwin -> client_win , net_wm_state );
}
} else {
Atom state [ 15 ]; /* nr of defined state atoms */
int i = 0 ;
if ( changedWorkspace || ( wPreferences . sticky_icons && ! IS_OMNIPRESENT ( wwin )))
updateWorkspaceHint ( wwin , False , False );
if ( IS_OMNIPRESENT ( wwin ))
state [ i ++ ] = net_wm_state_sticky ;
if ( wwin -> flags . shaded )
state [ i ++ ] = net_wm_state_shaded ;
if ( wwin -> flags . maximized & MAX_HORIZONTAL )
state [ i ++ ] = net_wm_state_maximized_horz ;
if ( wwin -> flags . maximized & MAX_VERTICAL )
state [ i ++ ] = net_wm_state_maximized_vert ;
if ( WFLAGP ( wwin , skip_window_list ))
state [ i ++ ] = net_wm_state_skip_taskbar ;
if ( wwin -> flags . net_skip_pager )
state [ i ++ ] = net_wm_state_skip_pager ;
if (( wwin -> flags . hidden || wwin -> flags . miniaturized ) && ! wwin -> flags . net_show_desktop ) {
state [ i ++ ] = net_wm_state_hidden ;
state [ i ++ ] = net_wm_state_skip_pager ;
if ( wwin -> flags . miniaturized && wPreferences . sticky_icons ) {
if ( ! IS_OMNIPRESENT ( wwin ))
updateWorkspaceHint ( wwin , True , False );
state [ i ++ ] = net_wm_state_sticky ;
}
}
if ( WFLAGP ( wwin , sunken ))
state [ i ++ ] = net_wm_state_below ;
if ( WFLAGP ( wwin , floating ))
state [ i ++ ] = net_wm_state_above ;
if ( wwin -> flags . fullscreen )
state [ i ++ ] = net_wm_state_fullscreen ;
XChangeProperty ( dpy , wwin -> client_win , net_wm_state , XA_ATOM , 32 ,
PropModeReplace , ( unsigned char * ) state , i );
}
2001-09-12 21:43:42 +00:00
}
2009-08-20 00:59:40 +02:00
static Bool updateStrut ( WWindow * wwin , Bool adding )
2001-09-12 21:43:42 +00:00
{
2009-08-20 00:59:40 +02:00
WScreen * scr ;
WReservedArea * area ;
Bool hasState = False ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
scr = wwin -> screen_ptr ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
if ( adding ) {
Atom type_ret ;
int fmt_ret ;
unsigned long nitems_ret ;
unsigned long bytes_after_ret ;
2010-04-12 23:31:59 +02:00
long * data = NULL ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
if ( XGetWindowProperty ( dpy , wwin -> client_win , net_wm_strut , 0 , 4 , False ,
XA_CARDINAL , & type_ret , & fmt_ret , & nitems_ret ,
& bytes_after_ret , ( unsigned char ** ) & data ) == Success && data ) {
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
area = ( WReservedArea * ) wmalloc ( sizeof ( WReservedArea ));
area -> area . x1 = data [ 0 ];
area -> area . x2 = data [ 1 ];
area -> area . y1 = data [ 2 ];
area -> area . y2 = data [ 3 ];
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
area -> window = wwin -> client_win ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
area -> next = scr -> netdata -> strut ;
scr -> netdata -> strut = area ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
XFree ( data );
hasState = True ;
}
} else {
/* deleting */
area = scr -> netdata -> strut ;
if ( area ) {
if ( area -> window == wwin -> client_win ) {
scr -> netdata -> strut = area -> next ;
wfree ( area );
hasState = True ;
} else {
while ( area -> next && area -> next -> window != wwin -> client_win )
area = area -> next ;
if ( area -> next ) {
WReservedArea * next ;
next = area -> next -> next ;
wfree ( area -> next );
area -> next = next ;
hasState = True ;
}
}
}
}
return hasState ;
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
static int getWindowLayer ( WWindow * wwin )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
int layer = WMNormalLevel ;
if ( wwin -> type == net_wm_window_type_desktop ) {
layer = WMDesktopLevel ;
} else if ( wwin -> type == net_wm_window_type_dock ) {
layer = WMDockLevel ;
} else if ( wwin -> type == net_wm_window_type_toolbar ) {
layer = WMMainMenuLevel ;
} else if ( wwin -> type == net_wm_window_type_menu ) {
layer = WMSubmenuLevel ;
} else if ( wwin -> type == net_wm_window_type_utility ) {
} else if ( wwin -> type == net_wm_window_type_splash ) {
} else if ( wwin -> type == net_wm_window_type_dialog ) {
if ( wwin -> transient_for ) {
WWindow * parent = wWindowFor ( wwin -> transient_for );
if ( parent && parent -> flags . fullscreen ) {
layer = WMFullscreenLevel ;
}
}
/* //layer = WMPopUpLevel; // this seems a bad idea -Dan */
} else if ( wwin -> type == net_wm_window_type_normal ) {
}
if ( wwin -> client_flags . sunken && WMSunkenLevel < layer )
layer = WMSunkenLevel ;
if ( wwin -> client_flags . floating && WMFloatingLevel > layer )
layer = WMFloatingLevel ;
return layer ;
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
static void doStateAtom ( WWindow * wwin , Atom state , int set , Bool init )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
if ( state == net_wm_state_sticky ) {
if ( set == _NET_WM_STATE_TOGGLE ) {
set = ! IS_OMNIPRESENT ( wwin );
}
if ( set != wwin -> flags . omnipresent ) {
wWindowSetOmnipresent ( wwin , set );
}
} else if ( state == net_wm_state_shaded ) {
if ( set == _NET_WM_STATE_TOGGLE ) {
set = ! wwin -> flags . shaded ;
}
if ( init ) {
wwin -> flags . shaded = set ;
} else {
if ( set ) {
wShadeWindow ( wwin );
} else {
wUnshadeWindow ( wwin );
}
}
} else if ( state == net_wm_state_skip_taskbar ) {
if ( set == _NET_WM_STATE_TOGGLE ) {
set = ! wwin -> client_flags . skip_window_list ;
}
wwin -> client_flags . skip_window_list = set ;
} else if ( state == net_wm_state_skip_pager ) {
if ( set == _NET_WM_STATE_TOGGLE ) {
set = ! wwin -> flags . net_skip_pager ;
}
wwin -> flags . net_skip_pager = set ;
} else if ( state == net_wm_state_maximized_vert ) {
if ( set == _NET_WM_STATE_TOGGLE ) {
set = ! ( wwin -> flags . maximized & MAX_VERTICAL );
}
if ( init ) {
wwin -> flags . maximized |= ( set ? MAX_VERTICAL : 0 );
} else {
if ( set ) {
wMaximizeWindow ( wwin , wwin -> flags . maximized | MAX_VERTICAL );
} else {
wMaximizeWindow ( wwin , wwin -> flags . maximized & ~ MAX_VERTICAL );
}
}
} else if ( state == net_wm_state_maximized_horz ) {
if ( set == _NET_WM_STATE_TOGGLE ) {
set = ! ( wwin -> flags . maximized & MAX_HORIZONTAL );
}
if ( init ) {
wwin -> flags . maximized |= ( set ? MAX_HORIZONTAL : 0 );
} else {
if ( set ) {
wMaximizeWindow ( wwin , wwin -> flags . maximized | MAX_HORIZONTAL );
} else {
wMaximizeWindow ( wwin , wwin -> flags . maximized & ~ MAX_HORIZONTAL );
}
}
} else if ( state == net_wm_state_hidden ) {
if ( set == _NET_WM_STATE_TOGGLE ) {
set = ! ( wwin -> flags . miniaturized );
}
if ( init ) {
wwin -> flags . miniaturized = set ;
} else {
if ( set ) {
wIconifyWindow ( wwin );
} else {
wDeiconifyWindow ( wwin );
}
}
} else if ( state == net_wm_state_fullscreen ) {
if ( set == _NET_WM_STATE_TOGGLE ) {
set = ! ( wwin -> flags . fullscreen );
}
if ( init ) {
wwin -> flags . fullscreen = set ;
} else {
if ( set ) {
wFullscreenWindow ( wwin );
} else {
wUnfullscreenWindow ( wwin );
}
}
} else if ( state == net_wm_state_above ) {
if ( set == _NET_WM_STATE_TOGGLE ) {
set = ! ( wwin -> client_flags . floating );
}
if ( init ) {
wwin -> client_flags . floating = set ;
} else {
wwin -> client_flags . floating = set ;
ChangeStackingLevel ( wwin -> frame -> core , getWindowLayer ( wwin ));
}
} else if ( state == net_wm_state_below ) {
if ( set == _NET_WM_STATE_TOGGLE ) {
set = ! ( wwin -> client_flags . sunken );
}
if ( init ) {
wwin -> client_flags . sunken = set ;
} else {
wwin -> client_flags . sunken = set ;
ChangeStackingLevel ( wwin -> frame -> core , getWindowLayer ( wwin ));
}
} else {
2004-10-12 01:34:32 +00:00
#ifdef DEBUG_WMSPEC
2009-08-20 00:59:40 +02:00
printf ( "doStateAtom unknown atom %s set %d \n " , XGetAtomName ( dpy , state ), set );
2004-10-12 01:34:32 +00:00
#endif
2009-08-20 00:59:40 +02:00
}
2001-09-12 21:43:42 +00:00
}
2009-08-20 00:59:40 +02:00
static void removeIcon ( WWindow * wwin )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
if ( wwin -> icon == NULL )
return ;
if ( wwin -> flags . miniaturized && wwin -> icon -> mapped ) {
XUnmapWindow ( dpy , wwin -> icon -> core -> window );
RemoveFromStackList ( wwin -> icon -> core );
wIconDestroy ( wwin -> icon );
wwin -> icon = NULL ;
}
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
static Bool handleWindowType ( WWindow * wwin , Atom type , int * layer )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
Bool ret = True ;
if ( type == net_wm_window_type_desktop ) {
wwin -> client_flags . no_titlebar = 1 ;
wwin -> client_flags . no_resizable = 1 ;
wwin -> client_flags . no_miniaturizable = 1 ;
wwin -> client_flags . no_border = 1 ;
wwin -> client_flags . no_resizebar = 1 ;
wwin -> client_flags . no_shadeable = 1 ;
wwin -> client_flags . no_movable = 1 ;
wwin -> client_flags . omnipresent = 1 ;
wwin -> client_flags . skip_window_list = 1 ;
wwin -> client_flags . dont_move_off = 1 ;
wwin -> client_flags . no_appicon = 1 ;
wwin -> flags . net_skip_pager = 1 ;
wwin -> frame_x = 0 ;
wwin -> frame_y = 0 ;
} else if ( type == net_wm_window_type_dock ) {
wwin -> client_flags . no_titlebar = 1 ;
wwin -> client_flags . no_resizable = 1 ;
wwin -> client_flags . no_miniaturizable = 1 ;
wwin -> client_flags . no_border = 1 ; /* XXX: really not a single decoration. */
wwin -> client_flags . no_resizebar = 1 ;
wwin -> client_flags . no_shadeable = 1 ;
wwin -> client_flags . no_movable = 1 ;
wwin -> client_flags . omnipresent = 1 ;
wwin -> client_flags . skip_window_list = 1 ;
wwin -> client_flags . dont_move_off = 1 ;
wwin -> flags . net_skip_pager = 1 ;
} else if ( type == net_wm_window_type_toolbar ) {
wwin -> client_flags . no_titlebar = 1 ;
wwin -> client_flags . no_resizable = 1 ;
wwin -> client_flags . no_miniaturizable = 1 ;
wwin -> client_flags . no_resizebar = 1 ;
wwin -> client_flags . no_shadeable = 1 ;
wwin -> client_flags . skip_window_list = 1 ;
wwin -> client_flags . dont_move_off = 1 ;
wwin -> client_flags . no_appicon = 1 ;
} else if ( type == net_wm_window_type_menu ) {
wwin -> client_flags . no_titlebar = 1 ;
wwin -> client_flags . no_resizable = 1 ;
wwin -> client_flags . no_miniaturizable = 1 ;
wwin -> client_flags . no_resizebar = 1 ;
wwin -> client_flags . no_shadeable = 1 ;
wwin -> client_flags . skip_window_list = 1 ;
wwin -> client_flags . dont_move_off = 1 ;
wwin -> client_flags . no_appicon = 1 ;
} else if ( type == net_wm_window_type_utility ) {
wwin -> client_flags . no_appicon = 1 ;
} else if ( type == net_wm_window_type_splash ) {
wwin -> client_flags . no_titlebar = 1 ;
wwin -> client_flags . no_resizable = 1 ;
wwin -> client_flags . no_miniaturizable = 1 ;
wwin -> client_flags . no_resizebar = 1 ;
wwin -> client_flags . no_shadeable = 1 ;
wwin -> client_flags . no_movable = 1 ;
wwin -> client_flags . skip_window_list = 1 ;
wwin -> client_flags . dont_move_off = 1 ;
wwin -> client_flags . no_appicon = 1 ;
wwin -> flags . net_skip_pager = 1 ;
} else if ( type == net_wm_window_type_dialog ) {
/* These also seem a bad idea in our context -Dan
// wwin->client_flags.skip_window_list = 1;
// wwin->client_flags.no_appicon = 1;
*/
} else if ( type == net_wm_window_type_normal ) {
} else {
ret = False ;
}
wwin -> type = type ;
* layer = getWindowLayer ( wwin );
return ret ;
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
void wNETWMPositionSplash ( WWindow * wwin , int * x , int * y , int width , int height )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
if ( wwin -> type == net_wm_window_type_splash ) {
WScreen * scr = wwin -> screen_ptr ;
WMRect rect = wGetRectForHead ( scr , wGetHeadForPointerLocation ( scr ));
* x = rect . pos . x + ( rect . size . width - width ) / 2 ;
* y = rect . pos . y + ( rect . size . height - height ) / 2 ;
}
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
static void updateWindowType ( WWindow * wwin )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
Atom type_ret ;
int fmt_ret ;
unsigned long nitems_ret ;
unsigned long bytes_after_ret ;
2010-04-12 23:31:59 +02:00
long * data = NULL ;
2009-08-20 00:59:40 +02:00
int layer ;
if ( XGetWindowProperty ( dpy , wwin -> client_win , net_wm_window_type , 0 , 1 ,
False , XA_ATOM , & type_ret , & fmt_ret , & nitems_ret ,
& bytes_after_ret , ( unsigned char ** ) & data ) == Success && data ) {
int i ;
Atom * type = ( Atom * ) data ;
for ( i = 0 ; i < nitems_ret ; ++ i ) {
if ( handleWindowType ( wwin , type [ i ], & layer ))
break ;
}
XFree ( data );
}
2008-11-26 15:56:33 +01:00
if ( wwin -> frame != NULL ) {
ChangeStackingLevel ( wwin -> frame -> core , layer );
wwin -> frame -> flags . need_texture_change = 1 ;
wWindowConfigureBorders ( wwin );
wFrameWindowPaint ( wwin -> frame );
wNETWMUpdateActions ( wwin , False );
}
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
Bool wNETWMCheckClientHints ( WWindow * wwin , int * layer , int * workspace )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
Atom type_ret ;
int fmt_ret ;
unsigned long nitems_ret ;
unsigned long bytes_after_ret ;
2010-04-12 23:31:59 +02:00
long * data = NULL ;
2009-08-20 00:59:40 +02:00
Bool hasState = False ;
int i ;
if ( XGetWindowProperty ( dpy , wwin -> client_win , net_wm_desktop , 0 , 1 , False ,
XA_CARDINAL , & type_ret , & fmt_ret , & nitems_ret ,
& bytes_after_ret , ( unsigned char ** ) & data ) == Success && data ) {
long desktop = * data ;
XFree ( data );
if ( desktop == - 1 )
wwin -> client_flags . omnipresent = 1 ;
else
* workspace = desktop ;
hasState = True ;
}
if ( XGetWindowProperty ( dpy , wwin -> client_win , net_wm_state , 0 , 1 , False ,
XA_ATOM , & type_ret , & fmt_ret , & nitems_ret ,
& bytes_after_ret , ( unsigned char ** ) & data ) == Success && data ) {
Atom * state = ( Atom * ) data ;
for ( i = 0 ; i < nitems_ret ; ++ i ) {
doStateAtom ( wwin , state [ i ], _NET_WM_STATE_ADD , True );
}
XFree ( data );
hasState = True ;
}
if ( XGetWindowProperty ( dpy , wwin -> client_win , net_wm_window_type , 0 , 1 , False ,
XA_ATOM , & type_ret , & fmt_ret , & nitems_ret ,
& bytes_after_ret , ( unsigned char ** ) & data ) == Success && data ) {
Atom * type = ( Atom * ) data ;
for ( i = 0 ; i < nitems_ret ; ++ i ) {
if ( handleWindowType ( wwin , type [ i ], layer ))
break ;
}
XFree ( data );
hasState = True ;
}
wNETWMUpdateActions ( wwin , False );
updateStrut ( wwin , False );
if ( updateStrut ( wwin , True )) {
hasState = True ;
}
wScreenUpdateUsableArea ( wwin -> screen_ptr );
return hasState ;
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
static Bool updateNetIconInfo ( WWindow * wwin )
{
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
Atom type_ret ;
int fmt_ret ;
unsigned long nitems_ret ;
unsigned long bytes_after_ret ;
2010-04-12 23:31:59 +02:00
long * data = NULL ;
2009-08-20 00:59:40 +02:00
Bool hasState = False ;
Bool old_state = wwin -> flags . net_handle_icon ;
if ( XGetWindowProperty ( dpy , wwin -> client_win , net_wm_handled_icons , 0 , 1 , False ,
XA_CARDINAL , & type_ret , & fmt_ret , & nitems_ret ,
& bytes_after_ret , ( unsigned char ** ) & data ) == Success && data ) {
long handled = * data ;
wwin -> flags . net_handle_icon = ( handled != 0 );
XFree ( data );
hasState = True ;
} else
wwin -> flags . net_handle_icon = False ;
if ( XGetWindowProperty ( dpy , wwin -> client_win , net_wm_icon_geometry , 0 , 4 , False ,
XA_CARDINAL , & type_ret , & fmt_ret , & nitems_ret ,
& bytes_after_ret , ( unsigned char ** ) & data ) == Success && data ) {
2004-10-12 01:34:32 +00:00
#ifdef NETWM_PROPER
2009-08-20 00:59:40 +02:00
if ( wwin -> flags . net_handle_icon )
2004-10-12 01:34:32 +00:00
#else
2009-08-20 00:59:40 +02:00
wwin -> flags . net_handle_icon = True ;
2004-10-12 01:34:32 +00:00
#endif
2009-08-20 00:59:40 +02:00
{
wwin -> icon_x = data [ 0 ];
wwin -> icon_y = data [ 1 ];
wwin -> icon_w = data [ 2 ];
wwin -> icon_h = data [ 3 ];
}
XFree ( data );
hasState = True ;
} else
wwin -> flags . net_handle_icon = False ;
if ( wwin -> flags . miniaturized && old_state != wwin -> flags . net_handle_icon ) {
if ( wwin -> flags . net_handle_icon ) {
removeIcon ( wwin );
} else {
wwin -> flags . miniaturized = False ;
wwin -> flags . skip_next_animation = True ;
wIconifyWindow ( wwin );
}
}
return hasState ;
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
Bool wNETWMCheckInitialClientState ( WWindow * wwin )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
Bool hasState = False ;
2004-10-12 01:34:32 +00:00
#ifdef DEBUG_WMSPEC
2009-08-20 00:59:40 +02:00
printf ( "CheckInitialClientState \n " );
2004-10-12 01:34:32 +00:00
#endif
2009-08-20 00:59:40 +02:00
wNETWMShowingDesktop ( wwin -> screen_ptr , False );
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
hasState |= updateNetIconInfo ( wwin );
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
updateIconImage ( wwin -> screen_ptr , wwin );
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
return hasState ;
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
static void handleDesktopNames ( XClientMessageEvent * event , WScreen * scr )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
unsigned long nitems_ret , bytes_after_ret ;
char * data , * names [ 32 ];
int fmt_ret , i , n ;
Atom type_ret ;
if ( XGetWindowProperty ( dpy , scr -> root_win , net_desktop_names , 0 , 1 , False ,
utf8_string , & type_ret , & fmt_ret , & nitems_ret ,
& bytes_after_ret , ( unsigned char ** ) & data ) != Success ) {
return ;
}
2010-04-12 23:31:59 +02:00
if ( data == NULL )
2009-08-20 00:59:40 +02:00
return ;
if ( type_ret != utf8_string || fmt_ret != 8 )
return ;
n = 0 ;
names [ n ] = data ;
for ( i = 0 ; i < nitems_ret ; i ++ ) {
if ( data [ i ] == 0 ) {
n ++ ;
names [ n ] = & data [ i ];
} else if ( * names [ n ] == 0 ) {
names [ n ] = & data [ i ];
wWorkspaceRename ( scr , n , names [ n ]);
}
}
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
Bool wNETWMProcessClientMessage ( XClientMessageEvent * event )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
WScreen * scr ;
WWindow * wwin ;
Bool done = True ;
2004-10-12 01:34:32 +00:00
#ifdef DEBUG_WMSPEC
2009-08-20 00:59:40 +02:00
printf ( "processClientMessage type %s \n " , XGetAtomName ( dpy , event -> message_type ));
2004-10-12 01:34:32 +00:00
#endif
2009-08-20 00:59:40 +02:00
scr = wScreenForWindow ( event -> window );
if ( scr ) {
/* generic client messages */
if ( event -> message_type == net_current_desktop ) {
wWorkspaceChange ( scr , event -> data . l [ 0 ]);
} else if ( event -> message_type == net_number_of_desktops ) {
long value ;
value = event -> data . l [ 0 ];
if ( value > scr -> workspace_count ) {
wWorkspaceMake ( scr , value - scr -> workspace_count );
} else if ( value < scr -> workspace_count ) {
int i ;
Bool rebuild = False ;
for ( i = scr -> workspace_count - 1 ; i >= value ; i -- ) {
if ( ! wWorkspaceDelete ( scr , i )) {
rebuild = True ;
break ;
}
}
if ( rebuild ) {
updateWorkspaceCount ( scr );
}
}
} else if ( event -> message_type == net_showing_desktop ) {
wNETWMShowingDesktop ( scr , event -> data . l [ 0 ]);
} else if ( event -> message_type == net_desktop_names ) {
handleDesktopNames ( event , scr );
} else {
done = False ;
}
if ( done )
return True ;
}
/* window specific client messages */
wwin = wWindowFor ( event -> window );
if ( ! wwin )
return False ;
2009-08-25 21:15:35 +02:00
if ( event -> message_type == net_active_window ) {
/*
* Firefox sends aditional 'net_active_window' signals on startup if
* multiple tabs are open. That causes unnecessary workspace switching if
* those signals come from other workspaces. Therefore we also check if
* we should ignore these spurious focus across workspaces requests (but
* allow the switching if it comes from a pager).
*/
if ( wwin -> frame -> workspace == wwin -> screen_ptr -> current_workspace
|| ! WFLAGP ( wwin , dont_focus_across_wksp ) || event -> data . l [ 0 ] == 2 ) {
wNETWMShowingDesktop ( scr , False );
wMakeWindowVisible ( wwin );
}
2009-08-20 00:59:40 +02:00
} else if ( event -> message_type == net_close_window ) {
if ( ! WFLAGP ( wwin , no_closable )) {
if ( wwin -> protocols . DELETE_WINDOW )
wClientSendProtocol ( wwin , _XA_WM_DELETE_WINDOW , LastTimestamp );
}
} else if ( event -> message_type == net_wm_state ) {
int maximized = wwin -> flags . maximized ;
long set = event -> data . l [ 0 ];
2004-10-12 01:34:32 +00:00
#ifdef DEBUG_WMSPEC
2009-08-20 00:59:40 +02:00
printf ( "net_wm_state set %d a1 %s a2 %s \n " , set ,
XGetAtomName ( dpy , event -> data . l [ 1 ]), XGetAtomName ( dpy , event -> data . l [ 2 ]));
2004-10-12 01:34:32 +00:00
#endif
2009-08-20 00:59:40 +02:00
doStateAtom ( wwin , ( Atom ) event -> data . l [ 1 ], set , False );
if ( event -> data . l [ 2 ])
doStateAtom ( wwin , ( Atom ) event -> data . l [ 2 ], set , False );
if ( wwin -> flags . maximized != maximized ) {
if ( ! wwin -> flags . maximized ) {
wwin -> flags . maximized = maximized ;
wUnmaximizeWindow ( wwin );
} else {
wMaximizeWindow ( wwin , wwin -> flags . maximized );
}
}
updateStateHint ( wwin , False , False );
} else if ( event -> message_type == net_wm_handled_icons || event -> message_type == net_wm_icon_geometry ) {
updateNetIconInfo ( wwin );
} else if ( event -> message_type == net_wm_desktop ) {
long desktop = event -> data . l [ 0 ];
if ( desktop == - 1 ) {
wWindowSetOmnipresent ( wwin , True );
} else {
if ( IS_OMNIPRESENT ( wwin ))
wWindowSetOmnipresent ( wwin , False );
wWindowChangeWorkspace ( wwin , desktop );
}
} else if ( event -> message_type == net_wm_icon ) {
updateIconImage ( scr , wwin );
} else {
done = False ;
}
return done ;
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
Bool wNETWMCheckClientHintChange ( WWindow * wwin , XPropertyEvent * event )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
Bool ret = True ;
if ( event -> atom == net_wm_strut ) {
updateStrut ( wwin , False );
updateStrut ( wwin , True );
wScreenUpdateUsableArea ( wwin -> screen_ptr );
} else if ( event -> atom == net_wm_handled_icons || event -> atom == net_wm_icon_geometry ) {
updateNetIconInfo ( wwin );
} else if ( event -> atom == net_wm_window_type ) {
updateWindowType ( wwin );
} else if ( event -> atom == net_wm_name ) {
char * name = wNETWMGetWindowName ( wwin -> client_win );
wWindowUpdateName ( wwin , name );
if ( name )
wfree ( name );
} else if ( event -> atom == net_wm_icon_name ) {
if ( wwin -> icon ) {
char * name = wNETWMGetIconName ( wwin -> client_win );
wIconChangeTitle ( wwin -> icon , name );
}
} else {
ret = False ;
}
return ret ;
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
int wNETWMGetPidForWindow ( Window window )
2004-10-12 01:34:32 +00:00
{
2009-08-20 00:59:40 +02:00
Atom type_ret ;
int fmt_ret ;
unsigned long nitems_ret ;
unsigned long bytes_after_ret ;
2010-04-12 23:31:59 +02:00
long * data = NULL ;
2009-08-20 00:59:40 +02:00
int pid ;
if ( XGetWindowProperty ( dpy , window , net_wm_pid , 0 , 1 , False ,
XA_CARDINAL , & type_ret , & fmt_ret , & nitems_ret ,
& bytes_after_ret , ( unsigned char ** ) & data ) == Success && data ) {
pid = * data ;
XFree ( data );
} else {
pid = 0 ;
}
return pid ;
2004-10-12 01:34:32 +00:00
}
2009-08-20 00:59:40 +02:00
char * wNETWMGetWindowName ( Window window )
2004-10-16 22:05:04 +00:00
{
2009-08-20 00:59:40 +02:00
char * name ;
char * ret ;
int size ;
name = ( char * ) PropGetCheckProperty ( window , net_wm_name , utf8_string , 0 , 0 , & size );
if ( name ) {
ret = wstrndup ( name , size );
XFree ( name );
} else
ret = NULL ;
return ret ;
2004-10-16 22:05:04 +00:00
}
2009-08-20 00:59:40 +02:00
char * wNETWMGetIconName ( Window window )
2004-10-16 22:05:04 +00:00
{
2009-08-20 00:59:40 +02:00
char * name ;
char * ret ;
int size ;
name = ( char * ) PropGetCheckProperty ( window , net_wm_icon_name , utf8_string , 0 , 0 , & size );
if ( name ) {
ret = wstrndup ( name , size );
XFree ( name );
} else
ret = NULL ;
return ret ;
2004-10-16 22:05:04 +00:00
}
2009-08-20 00:59:40 +02:00
static void observer ( void * self , WMNotification * notif )
2001-09-12 21:43:42 +00:00
{
2009-08-20 00:59:40 +02:00
WWindow * wwin = ( WWindow * ) WMGetNotificationObject ( notif );
const char * name = WMGetNotificationName ( notif );
void * data = WMGetNotificationClientData ( notif );
NetData * ndata = ( NetData * ) self ;
if ( strcmp ( name , WMNManaged ) == 0 && wwin ) {
updateClientList ( wwin -> screen_ptr );
updateClientListStacking ( wwin -> screen_ptr , NULL );
updateStateHint ( wwin , True , False );
updateStrut ( wwin , False );
updateStrut ( wwin , True );
wScreenUpdateUsableArea ( wwin -> screen_ptr );
} else if ( strcmp ( name , WMNUnmanaged ) == 0 && wwin ) {
updateClientList ( wwin -> screen_ptr );
updateClientListStacking ( wwin -> screen_ptr , wwin );
updateWorkspaceHint ( wwin , False , True );
updateStateHint ( wwin , False , True );
wNETWMUpdateActions ( wwin , True );
updateStrut ( wwin , False );
wScreenUpdateUsableArea ( wwin -> screen_ptr );
} else if ( strcmp ( name , WMNResetStacking ) == 0 && wwin ) {
updateClientListStacking ( wwin -> screen_ptr , NULL );
updateStateHint ( wwin , False , False );
} else if ( strcmp ( name , WMNChangedStacking ) == 0 && wwin ) {
updateClientListStacking ( wwin -> screen_ptr , NULL );
updateStateHint ( wwin , False , False );
} else if ( strcmp ( name , WMNChangedFocus ) == 0 ) {
updateFocusHint ( ndata -> scr , wwin );
} else if ( strcmp ( name , WMNChangedWorkspace ) == 0 && wwin ) {
updateWorkspaceHint ( wwin , False , False );
updateStateHint ( wwin , True , False );
} else if ( strcmp ( name , WMNChangedState ) == 0 && wwin ) {
updateStateHint ( wwin , ! strcmp ( data , "omnipresent" ), False );
}
2001-09-12 21:43:42 +00:00
}
2009-08-20 00:59:40 +02:00
static void wsobserver ( void * self , WMNotification * notif )
2001-09-12 21:43:42 +00:00
{
2009-08-20 00:59:40 +02:00
WScreen * scr = ( WScreen * ) WMGetNotificationObject ( notif );
const char * name = WMGetNotificationName ( notif );
if ( strcmp ( name , WMNWorkspaceCreated ) == 0 ) {
updateWorkspaceCount ( scr );
updateWorkspaceNames ( scr );
} else if ( strcmp ( name , WMNWorkspaceDestroyed ) == 0 ) {
updateWorkspaceCount ( scr );
updateWorkspaceNames ( scr );
} else if ( strcmp ( name , WMNWorkspaceChanged ) == 0 ) {
updateCurrentWorkspace ( scr );
} else if ( strcmp ( name , WMNWorkspaceNameChanged ) == 0 ) {
updateWorkspaceNames ( scr );
}
2001-09-12 21:43:42 +00:00
}