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
2011-04-18 21:00:49 +02:00
#include <WINGs/WUtil.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"
2010-10-08 15:08:33 -04:00
#include "appicon.h"
2004-10-12 01:34:32 +00:00
#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
/* 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 ;
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
2012-07-04 08:31:39 +01:00
static Atom net_frame_extents ;
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_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 },
2012-07-04 08:31:39 +01:00
{ "_NET_FRAME_EXTENTS" , & net_frame_extents },
2009-08-20 00:59:40 +02:00
{ "_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 _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
2012-10-23 23:59:51 +02:00
static void observer ( void * self , WMNotification * notif );
static void wsobserver ( void * self , WMNotification * notif );
2001-09-12 21:43:42 +00:00
2012-10-23 23:59:51 +02:00
static void updateClientList ( WScreen * scr );
static void updateClientListStacking ( WScreen * scr , WWindow * );
2004-10-12 01:34:32 +00:00
2012-10-23 23:59:51 +02:00
static void updateWorkspaceNames ( WScreen * scr );
static void updateCurrentWorkspace ( WScreen * scr );
static void updateWorkspaceCount ( WScreen * scr );
2012-10-23 23:59:46 +02:00
static void wNETWMShowingDesktop ( WScreen * scr , Bool show );
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 ;
2012-10-23 23:59:51 +02:00
static void setSupportedHints ( WScreen * scr )
2001-09-12 21:43:42 +00:00
{
2013-11-08 21:18:21 +01:00
Atom atom [ wlengthof ( atomNames )];
2009-08-20 00:59:40 +02:00
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_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 ;
2012-07-04 08:31:39 +01:00
atom [ i ++ ] = net_frame_extents ;
2009-08-20 00:59:40 +02:00
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
}
2012-10-23 23:59:51 +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
2013-10-08 00:56:30 +02:00
if ( w_global . workspace . count == 0 )
2009-08-20 00:59:40 +02:00
return ;
2004-10-12 01:34:32 +00:00
2013-10-08 00:56:30 +02:00
count = w_global . workspace . count * 2 ;
2009-08-20 00:59:40 +02:00
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
2013-10-08 00:56:30 +02:00
for ( i = 0 ; i < w_global . workspace . count ; i ++ ) {
2009-08-20 00:59:40 +02:00
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
}
2012-10-23 23:59:51 +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 ];
imgdata [ 3 ] = ( pixel >> 24 ) & 0xff ; /* A */
imgdata [ 0 ] = ( pixel >> 16 ) & 0xff ; /* R */
imgdata [ 1 ] = ( pixel >> 8 ) & 0xff ; /* G */
imgdata [ 2 ] = ( pixel >> 0 ) & 0xff ; /* B */
}
return image ;
2005-01-08 22:53:39 +00:00
}
2012-11-03 19:54:00 +01:00
RImage * get_window_image_from_x11 ( Window window )
2004-10-12 01:34:32 +00:00
{
2012-03-04 12:45:34 +01:00
RImage * image ;
2009-08-20 00:59:40 +02:00
Atom type ;
int format ;
2012-03-04 12:45:34 +01:00
unsigned long items , rest ;
unsigned long * property , * data ;
2010-10-08 15:08:31 -04:00
2012-03-04 12:45:34 +01:00
/* Get the icon from X11 Window */
2012-11-03 19:54:00 +01:00
if ( XGetWindowProperty ( dpy , window , net_wm_icon , 0L , LONG_MAX ,
2009-08-20 00:59:40 +02:00
False , XA_CARDINAL , & type , & format , & items , & rest ,
2012-03-04 12:26:33 +01:00
( unsigned char ** ) & property ) != Success || ! property )
2012-03-04 12:45:34 +01:00
return NULL ;
2009-08-20 00:59:40 +02:00
if ( type != XA_CARDINAL || format != 32 || items < 2 ) {
XFree ( property );
2012-03-04 12:45:34 +01:00
return NULL ;
2009-08-20 00:59:40 +02:00
}
2012-03-04 12:26:33 +01:00
/* Find the best icon */
2009-08-20 00:59:40 +02:00
data = findBestIcon ( property , items );
if ( ! data ) {
XFree ( property );
2012-03-04 12:45:34 +01:00
return NULL ;
2009-08-20 00:59:40 +02:00
}
2012-03-04 12:26:33 +01:00
/* Save the best icon in the X11 icon */
2012-03-04 12:45:34 +01:00
image = makeRImageFromARGBData ( data );
2009-08-20 00:59:40 +02:00
XFree ( property );
2012-07-15 21:31:14 +02:00
/* Resize the image to the correct value */
image = wIconValidateIconSize ( image , wPreferences . icon_size );
2012-03-04 12:45:34 +01:00
return image ;
}
static void updateIconImage ( WWindow * wwin )
{
/* Remove the icon image from X11 */
if ( wwin -> net_icon_image )
RReleaseImage ( wwin -> net_icon_image );
/* Save the icon in the X11 icon */
2012-11-03 19:54:00 +01:00
wwin -> net_icon_image = get_window_image_from_x11 ( wwin -> client_win );
2010-10-08 15:08:31 -04:00
2012-03-04 12:26:33 +01:00
/* Refresh the Window Icon */
if ( wwin -> icon )
2013-04-08 19:40:46 +02:00
wIconUpdate ( wwin -> icon );
2012-03-04 12:26:33 +01:00
/* Refresh the application icon */
2010-10-08 15:08:33 -04:00
WApplication * app = wApplicationOf ( wwin -> main_window );
2012-03-04 12:26:33 +01:00
if ( app && app -> app_icon ) {
2013-04-08 19:40:46 +02:00
wIconUpdate ( app -> app_icon -> icon );
2012-11-10 20:25:14 +01:00
wAppIconPaint ( app -> app_icon );
2010-10-08 15:08:33 -04:00
}
2004-10-12 01:34:32 +00:00
}
2001-09-12 21:43:42 +00:00
2012-10-23 23:59:51 +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
}
2012-10-23 23:59:46 +02:00
static 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 ! */
2013-10-08 00:56:32 +02:00
int ws = w_global . workspace . current ;
2009-08-20 00:59:40 +02:00
WWindow ** tmp ;
for ( tmp = scr -> netdata -> show_desktop ; * tmp ; ++ tmp ) {
wDeiconifyWindow ( * tmp );
( * tmp ) -> flags . net_show_desktop = 0 ;
}
2013-10-08 00:56:32 +02:00
if ( ws != w_global . workspace . current )
2009-08-20 00:59:40 +02:00
wWorkspaceChange ( scr , ws );
wfree ( scr -> netdata -> show_desktop );
scr -> netdata -> show_desktop = NULL ;
updateShowDesktop ( scr , False );
}
2004-10-12 01:34:32 +00:00
}
2012-10-23 23:59:51 +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
2012-10-23 23:58:56 +02:00
wmessage ( "wNETWMInitStuff" );
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
{
2013-11-08 21:18:21 +01:00
Atom atoms [ wlengthof ( atomNames )];
char * names [ wlengthof ( atomNames )];
2009-08-20 00:59:40 +02:00
2013-11-08 21:18:21 +01:00
for ( i = 0 ; i < wlengthof ( atomNames ); ++ i )
2009-08-20 00:59:40 +02:00
names [ i ] = atomNames [ i ]. name ;
2012-10-23 23:59:51 +02:00
2013-11-08 21:18:21 +01:00
XInternAtoms ( dpy , & names [ 0 ], wlengthof ( atomNames ), False , atoms );
for ( i = 0 ; i < wlengthof ( atomNames ); ++ i )
2009-08-20 00:59:40 +02:00
* atomNames [ i ]. atom = atoms [ i ];
2012-10-23 23:59:51 +02:00
2009-08-20 00:59:40 +02:00
}
2004-10-12 01:34:32 +00:00
#else
2013-11-08 21:18:21 +01:00
for ( i = 0 ; i < wlengthof ( atomNames ); i ++ )
2009-08-20 00:59:40 +02:00
* 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
}
2012-10-23 23:59:51 +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
2013-11-08 21:18:21 +01:00
for ( i = 0 ; i < wlengthof ( atomNames ); i ++ )
2009-08-20 00:59:40 +02:00
XDeleteProperty ( dpy , scr -> root_win , * atomNames [ i ]. atom );
2004-10-16 22:05:04 +00:00
}
2012-10-23 23:59:51 +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
}
2012-10-23 23:59:51 +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
}
2012-10-23 23:59:51 +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
}
2012-10-23 23:59:51 +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 ;
2012-10-23 23:59:51 +02:00
Window * client_list , * client_list_reverse ;
int client_count , i ;
2009-08-20 00:59:40 +02:00
WCoreWindow * tmp ;
WMBagIterator iter ;
/* 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
}
2012-10-23 23:59:51 +02:00
static void updateWorkspaceCount ( WScreen * scr )
2009-08-20 00:59:40 +02:00
{ /* changeable */
long count ;
2001-09-12 21:43:42 +00:00
2013-10-08 00:56:30 +02:00
count = w_global . 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
}
2012-10-23 23:59:51 +02:00
static void updateCurrentWorkspace ( WScreen * scr )
2009-08-20 00:59:40 +02:00
{ /* changeable */
long count ;
2001-09-12 21:43:42 +00:00
2013-10-08 00:56:32 +02:00
count = w_global . workspace . current ;
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
}
2012-10-23 23:59:51 +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 ;
2013-10-08 00:56:30 +02:00
for ( i = 0 ; i < w_global . workspace . count ; i ++ ) {
2013-10-08 00:56:33 +02:00
curr_size = strlen ( w_global . workspace . array [ i ] -> name );
strcpy ( pos , w_global . workspace . array [ i ] -> name );
2009-08-20 00:59:40 +02:00
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
}
2013-11-01 16:06:54 +01:00
static void updateFocusHint ( WScreen * scr )
2009-08-20 00:59:40 +02:00
{ /* 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
}
2012-10-23 23:59:51 +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
}
2012-10-23 23:59:51 +02:00
static void updateStateHint ( WWindow * wwin , Bool changedWorkspace , Bool del )
2009-08-20 00:59:40 +02:00
{ /* changeable */
if ( del ) {
2012-06-25 21:53:23 +02:00
XDeleteProperty ( dpy , wwin -> client_win , net_wm_state );
2009-08-20 00:59:40 +02:00
} 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
}
2012-10-29 15:49:43 -07:00
static Bool updateStrut ( WScreen * scr , Window w , Bool adding )
2001-09-12 21:43:42 +00:00
{
2009-08-20 00:59:40 +02:00
WReservedArea * area ;
Bool hasState = False ;
2004-10-12 01:34:32 +00:00
2009-08-20 00:59:40 +02:00
if ( adding ) {
Atom type_ret ;
int fmt_ret ;
2012-10-23 23:59:51 +02:00
unsigned long nitems_ret , bytes_after_ret ;
2010-04-12 23:31:59 +02:00
long * data = NULL ;
2004-10-12 01:34:32 +00:00
2012-10-29 15:49:43 -07:00
if (( XGetWindowProperty ( dpy , w , net_wm_strut , 0 , 4 , False ,
2009-08-20 00:59:40 +02:00
XA_CARDINAL , & type_ret , & fmt_ret , & nitems_ret ,
2012-10-26 11:40:55 -07:00
& bytes_after_ret , ( unsigned char ** ) & data ) == Success && data ) ||
2012-10-29 15:49:43 -07:00
(( XGetWindowProperty ( dpy , w , net_wm_strut_partial , 0 , 12 , False ,
2012-10-26 11:40:55 -07:00
XA_CARDINAL , & type_ret , & fmt_ret , & nitems_ret ,
& bytes_after_ret , ( unsigned char ** ) & data ) == Success && data ))) {
/* XXX: This is strictly incorrect in the case of net_wm_strut_partial...
* Discard the start and end properties from the partial strut and treat it as
* a (deprecated) strut.
* This means we are marking the whole width or height of the screen as
* reserved, which is not necessarily what the strut defines. However for the
* purposes of determining placement or maximization it's probably good enough.
*/
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
2012-10-29 15:49:43 -07:00
area -> window = w ;
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 ) {
2012-10-29 15:49:43 -07:00
if ( area -> window == w ) {
2009-08-20 00:59:40 +02:00
scr -> netdata -> strut = area -> next ;
wfree ( area );
hasState = True ;
} else {
2012-10-29 15:49:43 -07:00
while ( area -> next && area -> next -> window != w )
2009-08-20 00:59:40 +02:00
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
}
2012-10-23 23:59:51 +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 );
2012-10-23 23:59:51 +02:00
if ( parent && parent -> flags . fullscreen )
2013-11-04 22:07:54 +01:00
layer = WMNormalLevel ;
2009-08-20 00:59:40 +02:00
}
/* //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
}
2012-10-23 23:59:51 +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 ) {
2012-10-23 23:59:51 +02:00
if ( set == _NET_WM_STATE_TOGGLE )
2009-08-20 00:59:40 +02:00
set = ! IS_OMNIPRESENT ( wwin );
2012-10-23 23:59:51 +02:00
if ( set != wwin -> flags . omnipresent )
2009-08-20 00:59:40 +02:00
wWindowSetOmnipresent ( wwin , set );
2012-10-23 23:59:51 +02:00
2009-08-20 00:59:40 +02:00
} else if ( state == net_wm_state_shaded ) {
2012-10-23 23:59:51 +02:00
if ( set == _NET_WM_STATE_TOGGLE )
2009-08-20 00:59:40 +02:00
set = ! wwin -> flags . shaded ;
2012-10-23 23:59:51 +02:00
2009-08-20 00:59:40 +02:00
if ( init ) {
wwin -> flags . shaded = set ;
} else {
2012-10-23 23:59:51 +02:00
if ( set )
2009-08-20 00:59:40 +02:00
wShadeWindow ( wwin );
2012-10-23 23:59:51 +02:00
else
2009-08-20 00:59:40 +02:00
wUnshadeWindow ( wwin );
}
} else if ( state == net_wm_state_skip_taskbar ) {
2012-10-23 23:59:51 +02:00
if ( set == _NET_WM_STATE_TOGGLE )
2009-08-20 00:59:40 +02:00
set = ! wwin -> client_flags . skip_window_list ;
2012-10-23 23:59:51 +02:00
2009-08-20 00:59:40 +02:00
wwin -> client_flags . skip_window_list = set ;
} else if ( state == net_wm_state_skip_pager ) {
2012-10-23 23:59:51 +02:00
if ( set == _NET_WM_STATE_TOGGLE )
2009-08-20 00:59:40 +02:00
set = ! wwin -> flags . net_skip_pager ;
2012-10-23 23:59:51 +02:00
2009-08-20 00:59:40 +02:00
wwin -> flags . net_skip_pager = set ;
} else if ( state == net_wm_state_maximized_vert ) {
2012-10-23 23:59:51 +02:00
if ( set == _NET_WM_STATE_TOGGLE )
2009-08-20 00:59:40 +02:00
set = ! ( wwin -> flags . maximized & MAX_VERTICAL );
2012-10-23 23:59:51 +02:00
2009-08-20 00:59:40 +02:00
if ( init ) {
wwin -> flags . maximized |= ( set ? MAX_VERTICAL : 0 );
} else {
2012-10-23 23:59:51 +02:00
if ( set )
2009-08-20 00:59:40 +02:00
wMaximizeWindow ( wwin , wwin -> flags . maximized | MAX_VERTICAL );
2012-10-23 23:59:51 +02:00
else
2009-08-20 00:59:40 +02:00
wMaximizeWindow ( wwin , wwin -> flags . maximized & ~ MAX_VERTICAL );
}
} else if ( state == net_wm_state_maximized_horz ) {
2012-10-23 23:59:51 +02:00
if ( set == _NET_WM_STATE_TOGGLE )
2009-08-20 00:59:40 +02:00
set = ! ( wwin -> flags . maximized & MAX_HORIZONTAL );
2012-10-23 23:59:51 +02:00
2009-08-20 00:59:40 +02:00
if ( init ) {
wwin -> flags . maximized |= ( set ? MAX_HORIZONTAL : 0 );
} else {
2012-10-23 23:59:51 +02:00
if ( set )
2009-08-20 00:59:40 +02:00
wMaximizeWindow ( wwin , wwin -> flags . maximized | MAX_HORIZONTAL );
2012-10-23 23:59:51 +02:00
else
2009-08-20 00:59:40 +02:00
wMaximizeWindow ( wwin , wwin -> flags . maximized & ~ MAX_HORIZONTAL );
}
} else if ( state == net_wm_state_hidden ) {
2012-10-23 23:59:51 +02:00
if ( set == _NET_WM_STATE_TOGGLE )
2009-08-20 00:59:40 +02:00
set = ! ( wwin -> flags . miniaturized );
2012-10-23 23:59:51 +02:00
2009-08-20 00:59:40 +02:00
if ( init ) {
wwin -> flags . miniaturized = set ;
} else {
2012-10-23 23:59:51 +02:00
if ( set )
2009-08-20 00:59:40 +02:00
wIconifyWindow ( wwin );
2012-10-23 23:59:51 +02:00
else
2009-08-20 00:59:40 +02:00
wDeiconifyWindow ( wwin );
}
} else if ( state == net_wm_state_fullscreen ) {
2012-10-23 23:59:51 +02:00
if ( set == _NET_WM_STATE_TOGGLE )
2009-08-20 00:59:40 +02:00
set = ! ( wwin -> flags . fullscreen );
2012-10-23 23:59:51 +02:00
2009-08-20 00:59:40 +02:00
if ( init ) {
wwin -> flags . fullscreen = set ;
} else {
2012-10-23 23:59:51 +02:00
if ( set )
2009-08-20 00:59:40 +02:00
wFullscreenWindow ( wwin );
2012-10-23 23:59:51 +02:00
else
2009-08-20 00:59:40 +02:00
wUnfullscreenWindow ( wwin );
}
} else if ( state == net_wm_state_above ) {
2012-10-23 23:59:51 +02:00
if ( set == _NET_WM_STATE_TOGGLE )
2009-08-20 00:59:40 +02:00
set = ! ( wwin -> client_flags . floating );
2012-10-23 23:59:51 +02:00
2009-08-20 00:59:40 +02:00
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 ) {
2012-10-23 23:59:51 +02:00
if ( set == _NET_WM_STATE_TOGGLE )
2009-08-20 00:59:40 +02:00
set = ! ( wwin -> client_flags . sunken );
2012-10-23 23:59:51 +02:00
2009-08-20 00:59:40 +02:00
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
2011-04-18 21:00:49 +02:00
wmessage ( "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
}
2012-10-23 23:59:51 +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
}
2012-10-23 23:59:51 +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 ;
2011-02-17 14:56:36 -02:00
wwin -> client_flags . skip_switchpanel = 1 ;
2009-08-20 00:59:40 +02:00
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 ;
2011-02-17 14:56:36 -02:00
wwin -> client_flags . skip_switchpanel = 1 ;
2009-08-20 00:59:40 +02:00
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 ;
2011-02-17 14:56:36 -02:00
wwin -> client_flags . skip_switchpanel = 1 ;
2009-08-20 00:59:40 +02:00
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 ;
2011-02-17 14:56:36 -02:00
wwin -> client_flags . skip_switchpanel = 1 ;
2009-08-20 00:59:40 +02:00
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 ;
2011-02-17 14:56:36 -02:00
wwin -> client_flags . skip_switchpanel = 1 ;
2009-08-20 00:59:40 +02:00
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
}
2012-10-23 23:59:51 +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
}
2012-10-23 23:59:51 +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 ;
2012-10-23 23:59:51 +02:00
int fmt_ret , layer ;
unsigned long nitems_ret , bytes_after_ret ;
2010-04-12 23:31:59 +02:00
long * data = NULL ;
2012-10-23 23:59:51 +02:00
2009-08-20 00:59:40 +02:00
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
}
2012-10-23 23:59:49 +02:00
void 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 ;
2012-10-23 23:59:49 +02:00
int fmt_ret , i ;
unsigned long nitems_ret , bytes_after_ret ;
2010-04-12 23:31:59 +02:00
long * data = NULL ;
2009-08-20 00:59:40 +02:00
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 ;
}
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 ;
2012-10-23 23:59:49 +02:00
for ( i = 0 ; i < nitems_ret ; ++ i )
2009-08-20 00:59:40 +02:00
doStateAtom ( wwin , state [ i ], _NET_WM_STATE_ADD , True );
2012-10-23 23:59:49 +02:00
2009-08-20 00:59:40 +02:00
XFree ( data );
}
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 );
}
wNETWMUpdateActions ( wwin , False );
2012-10-29 15:49:43 -07:00
updateStrut ( wwin -> screen_ptr , wwin -> client_win , False );
updateStrut ( wwin -> screen_ptr , wwin -> client_win , True );
2009-08-20 00:59:40 +02:00
2012-10-23 23:59:49 +02:00
wScreenUpdateUsableArea ( wwin -> screen_ptr );
2004-10-12 01:34:32 +00:00
}
2012-10-23 23:59:51 +02:00
static Bool updateNetIconInfo ( WWindow * wwin )
2009-08-20 00:59:40 +02:00
{
Atom type_ret ;
int fmt_ret ;
2012-10-23 23:59:51 +02:00
unsigned long nitems_ret , 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 ;
2012-10-23 23:59:51 +02:00
} else {
2009-08-20 00:59:40 +02:00
wwin -> flags . net_handle_icon = False ;
2012-10-23 23:59:51 +02:00
}
2009-08-20 00:59:40 +02:00
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 ;
2012-10-23 23:59:51 +02:00
} else {
2009-08-20 00:59:40 +02:00
wwin -> flags . net_handle_icon = False ;
2012-10-23 23:59:51 +02:00
}
2009-08-20 00:59:40 +02:00
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
}
2012-10-23 23:59:47 +02:00
void wNETWMCheckInitialClientState ( WWindow * wwin )
2004-10-12 01:34:32 +00:00
{
#ifdef DEBUG_WMSPEC
2012-10-23 23:58:56 +02:00
wmessage ( "wNETWMCheckInitialClientState" );
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
2012-10-23 23:59:47 +02:00
updateNetIconInfo ( wwin );
2010-10-08 15:08:31 -04:00
updateIconImage ( wwin );
2004-10-12 01:34:32 +00:00
}
2013-11-01 16:06:54 +01:00
static void handleDesktopNames ( 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 ,
2012-10-23 23:59:51 +02:00
& bytes_after_ret , ( unsigned char ** ) & data ) != Success )
2009-08-20 00:59:40 +02:00
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
}
2012-10-23 23:59:51 +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
2011-04-18 21:00:49 +02:00
wmessage ( "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 ];
2013-10-08 00:56:30 +02:00
if ( value > w_global . workspace . count ) {
wWorkspaceMake ( scr , value - w_global . workspace . count );
} else if ( value < w_global . workspace . count ) {
2009-08-20 00:59:40 +02:00
int i ;
Bool rebuild = False ;
2013-10-08 00:56:30 +02:00
for ( i = w_global . workspace . count - 1 ; i >= value ; i -- ) {
2009-08-20 00:59:40 +02:00
if ( ! wWorkspaceDelete ( scr , i )) {
rebuild = True ;
break ;
}
}
2012-10-23 23:59:51 +02:00
if ( rebuild )
2009-08-20 00:59:40 +02:00
updateWorkspaceCount ( scr );
}
} else if ( event -> message_type == net_showing_desktop ) {
wNETWMShowingDesktop ( scr , event -> data . l [ 0 ]);
} else if ( event -> message_type == net_desktop_names ) {
2013-11-01 16:06:54 +01:00
handleDesktopNames ( scr );
2009-08-20 00:59:40 +02:00
} 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 ) {
/*
2011-04-18 21:00:49 +02:00
* Satisfy a client's focus request only if
* - request comes from a pager, or
* - it's explicitly allowed in Advanced Options, or
* - giving the client the focus does not cause a change in
* the active workspace (XXX: or the active head if Xinerama)
2009-08-25 21:15:35 +02:00
*/
2013-10-08 00:56:32 +02:00
if ( wwin -> frame -> workspace == w_global . workspace . current /* No workspace change */
2011-04-18 21:00:49 +02:00
|| event -> data . l [ 0 ] == 2 /* Requested by pager */
|| WFLAGP ( wwin , focus_across_wksp ) /* Explicitly allowed */ ) {
wNETWMShowingDesktop ( scr , False );
wMakeWindowVisible ( wwin );
2009-08-25 21:15:35 +02:00
}
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 )
2013-09-29 13:22:55 +02:00
wClientSendProtocol ( wwin , w_global . atom . wm . delete_window ,
w_global . timestamp . last_event );
2009-08-20 00:59:40 +02:00
}
} 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
2011-04-18 21:00:49 +02:00
wmessage ( "net_wm_state set %ld a1 %s a2 %s \n " , set ,
2009-08-20 00:59:40 +02:00
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 {
done = False ;
}
return done ;
2004-10-12 01:34:32 +00:00
}
2012-10-23 23:59:50 +02:00
void wNETWMCheckClientHintChange ( WWindow * wwin , XPropertyEvent * event )
2004-10-12 01:34:32 +00:00
{
2010-10-08 15:08:31 -04:00
#ifdef DEBUG_WMSPEC
2011-04-18 21:00:49 +02:00
wmessage ( "clientHintChange type %s \n " , XGetAtomName ( dpy , event -> atom ));
2010-10-08 15:08:31 -04:00
#endif
2012-10-26 11:40:55 -07:00
if ( event -> atom == net_wm_strut || event -> atom == net_wm_strut_partial ) {
2012-10-29 15:49:43 -07:00
updateStrut ( wwin -> screen_ptr , wwin -> client_win , False );
updateStrut ( wwin -> screen_ptr , wwin -> client_win , True );
2009-08-20 00:59:40 +02:00
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 ) {
2013-04-08 19:40:58 +02:00
wIconChangeTitle ( wwin -> icon , wwin );
wIconPaint ( wwin -> icon );
2009-08-20 00:59:40 +02:00
}
2010-10-08 15:08:31 -04:00
} else if ( event -> atom == net_wm_icon ) {
updateIconImage ( wwin );
2009-08-20 00:59:40 +02:00
}
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 ;
2012-10-23 23:59:51 +02:00
unsigned long nitems_ret , 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 );
2012-10-23 23:59:51 +02:00
} else {
2009-08-20 00:59:40 +02:00
ret = NULL ;
2012-10-23 23:59:51 +02:00
}
2009-08-20 00:59:40 +02:00
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 );
2012-10-23 23:59:51 +02:00
} else {
2009-08-20 00:59:40 +02:00
ret = NULL ;
2012-10-23 23:59:51 +02:00
}
2009-08-20 00:59:40 +02:00
return ret ;
2004-10-16 22:05:04 +00:00
}
2012-10-23 23:59:51 +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 );
2012-10-29 15:49:43 -07:00
updateStrut ( wwin -> screen_ptr , wwin -> client_win , False );
updateStrut ( wwin -> screen_ptr , wwin -> client_win , True );
2009-08-20 00:59:40 +02:00
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 );
2012-10-29 15:49:43 -07:00
updateStrut ( wwin -> screen_ptr , wwin -> client_win , False );
2009-08-20 00:59:40 +02:00
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 ) {
2013-11-01 16:06:54 +01:00
updateFocusHint ( ndata -> scr );
2009-08-20 00:59:40 +02:00
} 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
}
2012-10-23 23:59:51 +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 );
2013-10-13 22:44:08 +02:00
/* Parameter not used, but tell the compiler that it is ok */
( void ) self ;
2009-08-20 00:59:40 +02:00
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
}
2012-07-04 08:31:39 +01:00
void wNETFrameExtents ( WWindow * wwin )
{
long extents [ 4 ] = { 0 , 0 , 0 , 0 };
/* The extents array describes dimensions which are not
* part of the client window. In our case that means
* widths of the border and heights of the titlebar and resizebar.
*
* Index 0 = left
* 1 = right
* 2 = top
* 3 = bottom
*/
if ( wwin -> frame -> titlebar )
extents [ 2 ] = wwin -> frame -> titlebar -> height ;
if ( wwin -> frame -> resizebar )
extents [ 3 ] = wwin -> frame -> resizebar -> height ;
2012-08-24 17:59:30 +01:00
if ( HAS_BORDER ( wwin )) {
2013-03-26 07:01:08 +00:00
extents [ 0 ] += wwin -> screen_ptr -> frame_border_width ;
extents [ 1 ] += wwin -> screen_ptr -> frame_border_width ;
extents [ 2 ] += wwin -> screen_ptr -> frame_border_width ;
extents [ 3 ] += wwin -> screen_ptr -> frame_border_width ;
2012-08-24 17:59:30 +01:00
}
2012-07-04 08:31:39 +01:00
XChangeProperty ( dpy , wwin -> client_win , net_frame_extents , XA_CARDINAL , 32 , PropModeReplace , ( unsigned char * ) extents , 4 );
}
2012-09-14 15:31:14 +01:00
void wNETCleanupFrameExtents ( WWindow * wwin )
{
XDeleteProperty ( dpy , wwin -> client_win , net_frame_extents );
}