You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdelibs/tdecore/netwm.cpp

4646 lines
137 KiB

/*
Copyright (c) 2000 Troll Tech AS
Copyright (c) 2003 Lubos Lunak <l.lunak@kde.org>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
//#define NETWMDEBUG
#include <tqwidget.h>
#include <tqapplication.h>
#ifdef Q_WS_X11 //FIXME
#include "netwm.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <X11/Xmd.h>
#include "netwm_p.h"
// UTF-8 string
static Atom UTF8_STRING = 0;
// root window properties
static Atom net_supported = 0;
static Atom net_client_list = 0;
static Atom net_client_list_stacking = 0;
static Atom net_desktop_geometry = 0;
static Atom net_desktop_viewport = 0;
static Atom net_current_desktop = 0;
static Atom net_desktop_names = 0;
static Atom net_number_of_desktops = 0;
static Atom net_active_window = 0;
static Atom net_workarea = 0;
static Atom net_supporting_wm_check = 0;
static Atom net_virtual_roots = 0;
static Atom net_showing_desktop = 0;
static Atom net_desktop_layout = 0;
// root window messages
static Atom net_close_window = 0;
static Atom net_restack_window = 0;
static Atom net_wm_moveresize = 0;
static Atom net_moveresize_window = 0;
// application window properties
static Atom net_wm_name = 0;
static Atom net_wm_visible_name = 0;
static Atom net_wm_icon_name = 0;
static Atom net_wm_visible_icon_name = 0;
static Atom net_wm_desktop = 0;
static Atom net_wm_window_type = 0;
static Atom net_wm_state = 0;
static Atom net_wm_strut = 0;
static Atom net_wm_extended_strut = 0; // the atom is called _NET_WM_STRUT_PARTIAL
static Atom net_wm_icon_geometry = 0;
static Atom net_wm_icon = 0;
static Atom net_wm_pid = 0;
static Atom net_wm_user_time = 0;
static Atom net_wm_handled_icons = 0;
static Atom net_startup_id = 0;
static Atom net_wm_allowed_actions = 0;
static Atom wm_window_role = 0;
static Atom net_frame_extents = 0;
// KDE extensions
static Atom kde_net_system_tray_windows = 0;
static Atom kde_net_wm_system_tray_window_for = 0;
static Atom kde_net_wm_frame_strut = 0;
static Atom kde_net_wm_window_type_override = 0;
static Atom kde_net_wm_window_type_topmenu = 0;
static Atom kde_net_wm_temporary_rules = 0;
// application protocols
static Atom wm_protocols = 0;
static Atom net_wm_ping = 0;
static Atom net_wm_take_activity = 0;
// application window types
static Atom net_wm_window_type_normal = 0;
static Atom net_wm_window_type_desktop = 0;
static Atom net_wm_window_type_dock = 0;
static Atom net_wm_window_type_toolbar = 0;
static Atom net_wm_window_type_menu = 0;
static Atom net_wm_window_type_dialog = 0;
static Atom net_wm_window_type_utility = 0;
static Atom net_wm_window_type_splash = 0;
static Atom net_wm_window_type_dropdown_menu = 0;
static Atom net_wm_window_type_popup_menu = 0;
static Atom net_wm_window_type_tooltip = 0;
static Atom net_wm_window_type_notification = 0;
static Atom net_wm_window_type_combobox = 0;
static Atom net_wm_window_type_dnd = 0;
// application window state
static Atom net_wm_state_modal = 0;
static Atom net_wm_state_sticky = 0;
static Atom net_wm_state_max_vert = 0;
static Atom net_wm_state_max_horiz = 0;
static Atom net_wm_state_shaded = 0;
static Atom net_wm_state_skip_taskbar = 0;
static Atom net_wm_state_skip_pager = 0;
static Atom net_wm_state_hidden = 0;
static Atom net_wm_state_fullscreen = 0;
static Atom net_wm_state_above = 0;
static Atom net_wm_state_below = 0;
static Atom net_wm_state_demands_attention = 0;
// allowed actions
static Atom net_wm_action_move = 0;
static Atom net_wm_action_resize = 0;
static Atom net_wm_action_minimize = 0;
static Atom net_wm_action_shade = 0;
static Atom net_wm_action_stick = 0;
static Atom net_wm_action_max_vert = 0;
static Atom net_wm_action_max_horiz = 0;
static Atom net_wm_action_fullscreen = 0;
static Atom net_wm_action_change_desk = 0;
static Atom net_wm_action_close = 0;
// KDE extension that's not in the specs - Replaced by state_above now?
static Atom net_wm_state_stays_on_top = 0;
// used to determine whether application window is managed or not
static Atom xa_wm_state = 0;
// ability flags
static Atom net_wm_full_placement = 0;
static Bool netwm_atoms_created = False;
const unsigned long netwm_sendevent_mask = (SubstructureRedirectMask|
SubstructureNotifyMask);
const long MAX_PROP_SIZE = 100000;
static char *nstrdup(const char *s1) {
if (! s1) return (char *) 0;
int l = strlen(s1) + 1;
char *s2 = new char[l];
strncpy(s2, s1, l);
return s2;
}
static char *nstrndup(const char *s1, int l) {
if (! s1 || l == 0) return (char *) 0;
char *s2 = new char[l+1];
strncpy(s2, s1, l);
s2[l] = '\0';
return s2;
}
static Window *nwindup(Window *w1, int n) {
if (! w1 || n == 0) return (Window *) 0;
Window *w2 = new Window[n];
while (n--) w2[n] = w1[n];
return w2;
}
static void refdec_nri(NETRootInfoPrivate *p) {
#ifdef NETWMDEBUG
fprintf(stderr, "NET: decrementing NETRootInfoPrivate::ref (%d)\n", p->ref - 1);
#endif
if (! --p->ref) {
#ifdef NETWMDEBUG
fprintf(stderr, "NET: \tno more references, deleting\n");
#endif
delete [] p->name;
delete [] p->stacking;
delete [] p->clients;
delete [] p->virtual_roots;
delete [] p->kde_system_tray_windows;
int i;
for (i = 0; i < p->desktop_names.size(); i++)
delete [] p->desktop_names[i];
}
}
static void refdec_nwi(NETWinInfoPrivate *p) {
#ifdef NETWMDEBUG
fprintf(stderr, "NET: decrementing NETWinInfoPrivate::ref (%d)\n", p->ref - 1);
#endif
if (! --p->ref) {
#ifdef NETWMDEBUG
fprintf(stderr, "NET: \tno more references, deleting\n");
#endif
delete [] p->name;
delete [] p->visible_name;
delete [] p->icon_name;
delete [] p->visible_icon_name;
delete [] p->startup_id;
int i;
for (i = 0; i < p->icons.size(); i++)
delete [] p->icons[i].data;
}
}
static int wcmp(const void *a, const void *b) {
return *((Window *) a) - *((Window *) b);
}
static const int netAtomCount = 85;
static void create_atoms(Display *d) {
static const char * const names[netAtomCount] =
{
"UTF8_STRING",
"_NET_SUPPORTED",
"_NET_SUPPORTING_WM_CHECK",
"_NET_CLIENT_LIST",
"_NET_CLIENT_LIST_STACKING",
"_NET_NUMBER_OF_DESKTOPS",
"_NET_DESKTOP_GEOMETRY",
"_NET_DESKTOP_VIEWPORT",
"_NET_CURRENT_DESKTOP",
"_NET_DESKTOP_NAMES",
"_NET_ACTIVE_WINDOW",
"_NET_WORKAREA",
"_NET_VIRTUAL_ROOTS",
"_NET_DESKTOP_LAYOUT",
"_NET_SHOWING_DESKTOP",
"_NET_CLOSE_WINDOW",
"_NET_RESTACK_WINDOW",
"_NET_WM_MOVERESIZE",
"_NET_MOVERESIZE_WINDOW",
"_NET_WM_NAME",
"_NET_WM_VISIBLE_NAME",
"_NET_WM_ICON_NAME",
"_NET_WM_VISIBLE_ICON_NAME",
"_NET_WM_DESKTOP",
"_NET_WM_WINDOW_TYPE",
"_NET_WM_STATE",
"_NET_WM_STRUT",
"_NET_WM_STRUT_PARTIAL",
"_NET_WM_ICON_GEOMETRY",
"_NET_WM_ICON",
"_NET_WM_PID",
"_NET_WM_USER_TIME",
"_NET_WM_HANDLED_ICONS",
"_NET_STARTUP_ID",
"_NET_WM_ALLOWED_ACTIONS",
"_NET_WM_PING",
"_NET_WM_TAKE_ACTIVITY",
"WM_WINDOW_ROLE",
"_NET_FRAME_EXTENTS",
"_NET_WM_WINDOW_TYPE_NORMAL",
"_NET_WM_WINDOW_TYPE_DESKTOP",
"_NET_WM_WINDOW_TYPE_DOCK",
"_NET_WM_WINDOW_TYPE_TOOLBAR",
"_NET_WM_WINDOW_TYPE_MENU",
"_NET_WM_WINDOW_TYPE_DIALOG",
"_NET_WM_WINDOW_TYPE_UTILITY",
"_NET_WM_WINDOW_TYPE_SPLASH",
"_NET_WM_WINDOW_TYPE_DROPDOWN_MENU",
"_NET_WM_WINDOW_TYPE_POPUP_MENU",
"_NET_WM_WINDOW_TYPE_TOOLTIP",
"_NET_WM_WINDOW_TYPE_NOTIFICATION",
"_NET_WM_WINDOW_TYPE_COMBOBOX",
"_NET_WM_WINDOW_TYPE_DND",
"_NET_WM_STATE_MODAL",
"_NET_WM_STATE_STICKY",
"_NET_WM_STATE_MAXIMIZED_VERT",
"_NET_WM_STATE_MAXIMIZED_HORZ",
"_NET_WM_STATE_SHADED",
"_NET_WM_STATE_SKIP_TASKBAR",
"_NET_WM_STATE_SKIP_PAGER",
"_NET_WM_STATE_HIDDEN",
"_NET_WM_STATE_FULLSCREEN",
"_NET_WM_STATE_ABOVE",
"_NET_WM_STATE_BELOW",
"_NET_WM_STATE_DEMANDS_ATTENTION",
"_NET_WM_ACTION_MOVE",
"_NET_WM_ACTION_RESIZE",
"_NET_WM_ACTION_MINIMIZE",
"_NET_WM_ACTION_SHADE",
"_NET_WM_ACTION_STICK",
"_NET_WM_ACTION_MAXIMIZE_VERT",
"_NET_WM_ACTION_MAXIMIZE_HORZ",
"_NET_WM_ACTION_FULLSCREEN",
"_NET_WM_ACTION_CHANGE_DESKTOP",
"_NET_WM_ACTION_CLOSE",
"_NET_WM_STATE_STAYS_ON_TOP",
"_KDE_NET_SYSTEM_TRAY_WINDOWS",
"_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
"_KDE_NET_WM_FRAME_STRUT",
"_KDE_NET_WM_WINDOW_TYPE_OVERRIDE",
"_KDE_NET_WM_WINDOW_TYPE_TOPMENU",
"_KDE_NET_WM_TEMPORARY_RULES",
"WM_STATE",
"WM_PROTOCOLS",
"_NET_WM_FULL_PLACEMENT"
};
Atom atoms[netAtomCount], *atomsp[netAtomCount] =
{
&UTF8_STRING,
&net_supported,
&net_supporting_wm_check,
&net_client_list,
&net_client_list_stacking,
&net_number_of_desktops,
&net_desktop_geometry,
&net_desktop_viewport,
&net_current_desktop,
&net_desktop_names,
&net_active_window,
&net_workarea,
&net_virtual_roots,
&net_desktop_layout,
&net_showing_desktop,
&net_close_window,
&net_restack_window,
&net_wm_moveresize,
&net_moveresize_window,
&net_wm_name,
&net_wm_visible_name,
&net_wm_icon_name,
&net_wm_visible_icon_name,
&net_wm_desktop,
&net_wm_window_type,
&net_wm_state,
&net_wm_strut,
&net_wm_extended_strut,
&net_wm_icon_geometry,
&net_wm_icon,
&net_wm_pid,
&net_wm_user_time,
&net_wm_handled_icons,
&net_startup_id,
&net_wm_allowed_actions,
&net_wm_ping,
&net_wm_take_activity,
&wm_window_role,
&net_frame_extents,
&net_wm_window_type_normal,
&net_wm_window_type_desktop,
&net_wm_window_type_dock,
&net_wm_window_type_toolbar,
&net_wm_window_type_menu,
&net_wm_window_type_dialog,
&net_wm_window_type_utility,
&net_wm_window_type_splash,
&net_wm_window_type_dropdown_menu,
&net_wm_window_type_popup_menu,
&net_wm_window_type_tooltip,
&net_wm_window_type_notification,
&net_wm_window_type_combobox,
&net_wm_window_type_dnd,
&net_wm_state_modal,
&net_wm_state_sticky,
&net_wm_state_max_vert,
&net_wm_state_max_horiz,
&net_wm_state_shaded,
&net_wm_state_skip_taskbar,
&net_wm_state_skip_pager,
&net_wm_state_hidden,
&net_wm_state_fullscreen,
&net_wm_state_above,
&net_wm_state_below,
&net_wm_state_demands_attention,
&net_wm_action_move,
&net_wm_action_resize,
&net_wm_action_minimize,
&net_wm_action_shade,
&net_wm_action_stick,
&net_wm_action_max_vert,
&net_wm_action_max_horiz,
&net_wm_action_fullscreen,
&net_wm_action_change_desk,
&net_wm_action_close,
&net_wm_state_stays_on_top,
&kde_net_system_tray_windows,
&kde_net_wm_system_tray_window_for,
&kde_net_wm_frame_strut,
&kde_net_wm_window_type_override,
&kde_net_wm_window_type_topmenu,
&kde_net_wm_temporary_rules,
&xa_wm_state,
&wm_protocols,
&net_wm_full_placement
};
assert( !netwm_atoms_created );
int i = netAtomCount;
while (i--)
atoms[i] = 0;
XInternAtoms(d, (char **) names, netAtomCount, False, atoms);
i = netAtomCount;
while (i--)
*atomsp[i] = atoms[i];
netwm_atoms_created = True;
}
static void readIcon(Display* display, Window window, Atom property, NETRArray<NETIcon>& icons, int& icon_count) {
#ifdef NETWMDEBUG
fprintf(stderr, "NET: readIcon\n");
#endif
Atom type_ret;
int format_ret;
unsigned long nitems_ret = 0, after_ret = 0;
unsigned char *data_ret = 0;
// reset
for (int i = 0; i < icons.size(); i++)
delete [] icons[i].data;
icons.reset();
icon_count = 0;
// allocate buffers
unsigned char *buffer = 0;
unsigned long offset = 0;
unsigned long buffer_offset = 0;
unsigned long bufsize = 0;
// read data
do {
if (XGetWindowProperty(display, window, property, offset,
MAX_PROP_SIZE, False, XA_CARDINAL, &type_ret,
&format_ret, &nitems_ret, &after_ret, &data_ret)
== Success) {
if (!bufsize)
{
if (nitems_ret < 3 || type_ret != XA_CARDINAL ||
format_ret != 32) {
// either we didn't get the property, or the property has less than
// 3 elements in it
// NOTE: 3 is the ABSOLUTE minimum:
// width = 1, height = 1, length(data) = 1 (width * height)
if ( data_ret )
XFree(data_ret);
return;
}
bufsize = nitems_ret * sizeof(long) + after_ret;
buffer = (unsigned char *) malloc(bufsize);
}
else if (buffer_offset + nitems_ret*sizeof(long) > bufsize)
{
fprintf(stderr, "NETWM: Warning readIcon() needs buffer adjustment!\n");
bufsize = buffer_offset + nitems_ret * sizeof(long) + after_ret;
buffer = (unsigned char *) realloc(buffer, bufsize);
}
memcpy((buffer + buffer_offset), data_ret, nitems_ret * sizeof(long));
buffer_offset += nitems_ret * sizeof(long);
offset += nitems_ret;
if ( data_ret )
XFree(data_ret);
} else {
if (buffer)
free(buffer);
return; // Some error occurred cq. property didn't exist.
}
}
while (after_ret > 0);
CARD32 *data32;
unsigned long i, j, k, sz, s;
unsigned long *d = (unsigned long *) buffer;
for (i = 0, j = 0; i < bufsize;) {
icons[j].size.width = *d++;
i += sizeof(long);
icons[j].size.height = *d++;
i += sizeof(long);
sz = icons[j].size.width * icons[j].size.height;
s = sz * sizeof(long);
if ( i + s - 1 > bufsize || sz == 0 || sz > 1024 * 1024 ) {
break;
}
delete [] icons[j].data;
data32 = new CARD32[sz];
icons[j].data = (unsigned char *) data32;
for (k = 0; k < sz; k++, i += sizeof(long)) {
*data32++ = (CARD32) *d++;
}
j++;
icon_count++;
}
#ifdef NETWMDEBUG
fprintf(stderr, "NET: readIcon got %d icons\n", icon_count);
#endif
free(buffer);
}
template <class Z>
NETRArray<Z>::NETRArray()
: sz(0), capacity(2)
{
d = (Z*) calloc(capacity, sizeof(Z)); // allocate 2 elts and set to zero
}
template <class Z>
NETRArray<Z>::~NETRArray() {
free(d);
}
template <class Z>
void NETRArray<Z>::reset() {
sz = 0;
capacity = 2;
d = (Z*) realloc(d, sizeof(Z)*capacity);
memset( (void*) d, 0, sizeof(Z)*capacity );
}
template <class Z>
Z &NETRArray<Z>::operator[](int index) {
if (index >= capacity) {
// allocate space for the new data
// open table has amortized O(1) access time
// when N elements appended consecutively -- exa
int newcapacity = 2*capacity > index+1 ? 2*capacity : index+1; // max
// copy into new larger memory block using realloc
d = (Z*) realloc(d, sizeof(Z)*newcapacity);
memset( (void*) &d[capacity], 0, sizeof(Z)*(newcapacity-capacity) );
capacity = newcapacity;
}
if (index >= sz) // at this point capacity>index
sz = index + 1;
return d[index];
}
// Construct a new NETRootInfo object.
NETRootInfo::NETRootInfo(Display *display, Window supportWindow, const char *wmName,
const unsigned long properties[], int properties_size,
int screen, bool doActivate)
{
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::NETRootInfo: using window manager constructor\n");
#endif
p = new NETRootInfoPrivate;
p->ref = 1;
p->display = display;
p->name = nstrdup(wmName);
if (screen != -1) {
p->screen = screen;
} else {
p->screen = DefaultScreen(p->display);
}
p->root = RootWindow(p->display, p->screen);
p->supportwindow = supportWindow;
p->number_of_desktops = p->current_desktop = 0;
p->active = None;
p->clients = p->stacking = p->virtual_roots = (Window *) 0;
p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
p->kde_system_tray_windows = 0;
p->kde_system_tray_windows_count = 0;
p->showing_desktop = false;
p->desktop_layout_orientation = OrientationHorizontal;
p->desktop_layout_corner = DesktopLayoutCornerTopLeft;
p->desktop_layout_columns = p->desktop_layout_rows = 0;
setDefaultProperties();
if( properties_size > PROPERTIES_SIZE ) {
fprintf( stderr, "[netwm] NETRootInfo::NETRootInfo(): properties array too large\n");
properties_size = PROPERTIES_SIZE;
}
for( int i = 0; i < properties_size; ++i )
p->properties[ i ] = properties[ i ];
// force support for Supported and SupportingWMCheck for window managers
p->properties[ PROTOCOLS ] |= ( Supported | SupportingWMCheck );
p->client_properties[ PROTOCOLS ] = DesktopNames // the only thing that can be changed by clients
| WMPing; // or they can reply to this
p->client_properties[ PROTOCOLS2 ] = WM2TakeActivity | WM2DesktopLayout;
role = WindowManager;
if (! netwm_atoms_created) create_atoms(p->display);
if (doActivate) activate();
}
NETRootInfo::NETRootInfo(Display *display, Window supportWindow, const char *wmName,
unsigned long properties, int screen, bool doActivate)
{
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::NETRootInfo: using window manager constructor\n");
#endif
p = new NETRootInfoPrivate;
p->ref = 1;
p->display = display;
p->name = nstrdup(wmName);
if (screen != -1) {
p->screen = screen;
} else {
p->screen = DefaultScreen(p->display);
}
p->root = RootWindow(p->display, p->screen);
p->supportwindow = supportWindow;
p->number_of_desktops = p->current_desktop = 0;
p->active = None;
p->clients = p->stacking = p->virtual_roots = (Window *) 0;
p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
p->kde_system_tray_windows = 0;
p->kde_system_tray_windows_count = 0;
p->showing_desktop = false;
setDefaultProperties();
p->properties[ PROTOCOLS ] = properties;
// force support for Supported and SupportingWMCheck for window managers
p->properties[ PROTOCOLS ] |= ( Supported | SupportingWMCheck );
p->client_properties[ PROTOCOLS ] = DesktopNames // the only thing that can be changed by clients
| WMPing; // or they can reply to this
p->client_properties[ PROTOCOLS2 ] = WM2TakeActivity;
role = WindowManager;
if (! netwm_atoms_created) create_atoms(p->display);
if (doActivate) activate();
}
NETRootInfo::NETRootInfo(Display *display, const unsigned long properties[], int properties_size,
int screen, bool doActivate)
{
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::NETRootInfo: using Client constructor\n");
#endif
p = new NETRootInfoPrivate;
p->ref = 1;
p->name = 0;
p->display = display;
if (screen != -1) {
p->screen = screen;
} else {
p->screen = DefaultScreen(p->display);
}
p->root = RootWindow(p->display, p->screen);
p->rootSize.width = WidthOfScreen(ScreenOfDisplay(p->display, p->screen));
p->rootSize.height = HeightOfScreen(ScreenOfDisplay(p->display, p->screen));
p->supportwindow = None;
p->number_of_desktops = p->current_desktop = 0;
p->active = None;
p->clients = p->stacking = p->virtual_roots = (Window *) 0;
p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
p->kde_system_tray_windows = 0;
p->kde_system_tray_windows_count = 0;
p->showing_desktop = false;
p->desktop_layout_orientation = OrientationHorizontal;
p->desktop_layout_corner = DesktopLayoutCornerTopLeft;
p->desktop_layout_columns = p->desktop_layout_rows = 0;
setDefaultProperties();
if( properties_size > 2 ) {
fprintf( stderr, "[netwm] NETWinInfo::NETWinInfo(): properties array too large\n");
properties_size = 2;
}
for( int i = 0; i < properties_size; ++i )
// remap from [0]=NET::Property,[1]=NET::Property2
switch( i ) {
case 0:
p->client_properties[ PROTOCOLS ] = properties[ i ];
break;
case 1:
p->client_properties[ PROTOCOLS2 ] = properties[ i ];
break;
}
for( int i = 0; i < PROPERTIES_SIZE; ++i )
p->properties[ i ] = 0;
role = Client;
if (! netwm_atoms_created) create_atoms(p->display);
if (doActivate) activate();
}
NETRootInfo::NETRootInfo(Display *display, unsigned long properties, int screen,
bool doActivate)
{
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::NETRootInfo: using Client constructor\n");
#endif
p = new NETRootInfoPrivate;
p->ref = 1;
p->name = 0;
p->display = display;
if (screen != -1) {
p->screen = screen;
} else {
p->screen = DefaultScreen(p->display);
}
p->root = RootWindow(p->display, p->screen);
p->rootSize.width = WidthOfScreen(ScreenOfDisplay(p->display, p->screen));
p->rootSize.height = HeightOfScreen(ScreenOfDisplay(p->display, p->screen));
p->supportwindow = None;
p->number_of_desktops = p->current_desktop = 0;
p->active = None;
p->clients = p->stacking = p->virtual_roots = (Window *) 0;
p->clients_count = p->stacking_count = p->virtual_roots_count = 0;
p->kde_system_tray_windows = 0;
p->kde_system_tray_windows_count = 0;
p->showing_desktop = false;
p->desktop_layout_orientation = OrientationHorizontal;
p->desktop_layout_corner = DesktopLayoutCornerTopLeft;
p->desktop_layout_columns = p->desktop_layout_rows = 0;
setDefaultProperties();
p->client_properties[ PROTOCOLS ] = properties;
for( int i = 0; i < PROPERTIES_SIZE; ++i )
p->properties[ i ] = 0;
role = Client;
if (! netwm_atoms_created) create_atoms(p->display);
if (doActivate) activate();
}
NETRootInfo2::NETRootInfo2(Display *display, Window supportWindow, const char *wmName,
unsigned long properties[], int properties_size,
int screen, bool doActivate)
: NETRootInfo( display, supportWindow, wmName, properties, properties_size,
screen, doActivate )
{
}
NETRootInfo2::NETRootInfo2(Display *display, const unsigned long properties[], int properties_size,
int screen, bool doActivate)
: NETRootInfo( display, properties, properties_size, screen, doActivate )
{
}
NETRootInfo3::NETRootInfo3(Display *display, Window supportWindow, const char *wmName,
unsigned long properties[], int properties_size,
int screen, bool doActivate)
: NETRootInfo2( display, supportWindow, wmName, properties, properties_size,
screen, doActivate )
{
}
NETRootInfo3::NETRootInfo3(Display *display, const unsigned long properties[], int properties_size,
int screen, bool doActivate)
: NETRootInfo2( display, properties, properties_size, screen, doActivate )
{
}
NETRootInfo4::NETRootInfo4(Display *display, Window supportWindow, const char *wmName,
unsigned long properties[], int properties_size,
int screen, bool doActivate)
: NETRootInfo3( display, supportWindow, wmName, properties, properties_size,
screen, doActivate )
{
}
NETRootInfo4::NETRootInfo4(Display *display, const unsigned long properties[], int properties_size,
int screen, bool doActivate)
: NETRootInfo3( display, properties, properties_size, screen, doActivate )
{
}
// Copy an existing NETRootInfo object.
NETRootInfo::NETRootInfo(const NETRootInfo &rootinfo) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::NETRootInfo: using copy constructor\n");
#endif
p = rootinfo.p;
role = rootinfo.role;
p->ref++;
}
// Be gone with our NETRootInfo.
NETRootInfo::~NETRootInfo() {
refdec_nri(p);
if (! p->ref) delete p;
}
void NETRootInfo::setDefaultProperties()
{
p->properties[ PROTOCOLS ] = Supported | SupportingWMCheck;
p->properties[ WINDOW_TYPES ] = NormalMask | DesktopMask | DockMask
| ToolbarMask | MenuMask | DialogMask;
p->properties[ STATES ] = Modal | Sticky | MaxVert | MaxHoriz | Shaded
| SkipTaskbar | StaysOnTop;
p->properties[ PROTOCOLS2 ] = 0;
p->properties[ ACTIONS ] = 0;
p->client_properties[ PROTOCOLS ] = 0;
p->client_properties[ WINDOW_TYPES ] = 0; // these two actually don't
p->client_properties[ STATES ] = 0; // make sense in client_properties
p->client_properties[ PROTOCOLS2 ] = 0;
p->client_properties[ ACTIONS ] = 0;
}
void NETRootInfo::activate() {
if (role == WindowManager) {
#ifdef NETWMDEBUG
fprintf(stderr,
"NETRootInfo::activate: setting supported properties on root\n");
#endif
setSupported();
update(p->client_properties);
} else {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::activate: updating client information\n");
#endif
update(p->client_properties);
}
}
void NETRootInfo::setClientList(Window *windows, unsigned int count) {
if (role != WindowManager) return;
p->clients_count = count;
delete [] p->clients;
p->clients = nwindup(windows, count);
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::setClientList: setting list with %ld windows\n",
p->clients_count);
#endif
XChangeProperty(p->display, p->root, net_client_list, XA_WINDOW, 32,
PropModeReplace, (unsigned char *)p->clients,
p->clients_count);
}
void NETRootInfo::setClientListStacking(Window *windows, unsigned int count) {
if (role != WindowManager) return;
p->stacking_count = count;
delete [] p->stacking;
p->stacking = nwindup(windows, count);
#ifdef NETWMDEBUG
fprintf(stderr,
"NETRootInfo::setClientListStacking: setting list with %ld windows\n",
p->clients_count);
#endif
XChangeProperty(p->display, p->root, net_client_list_stacking, XA_WINDOW, 32,
PropModeReplace, (unsigned char *) p->stacking,
p->stacking_count);
}
void NETRootInfo::setKDESystemTrayWindows(Window *windows, unsigned int count) {
if (role != WindowManager) return;
p->kde_system_tray_windows_count = count;
delete [] p->kde_system_tray_windows;
p->kde_system_tray_windows = nwindup(windows, count);
#ifdef NETWMDEBUG
fprintf(stderr,
"NETRootInfo::setKDESystemTrayWindows: setting list with %ld windows\n",
p->kde_system_tray_windows_count);
#endif
XChangeProperty(p->display, p->root, kde_net_system_tray_windows, XA_WINDOW, 32,
PropModeReplace,
(unsigned char *) p->kde_system_tray_windows,
p->kde_system_tray_windows_count);
}
void NETRootInfo::setNumberOfDesktops(int numberOfDesktops) {
#ifdef NETWMDEBUG
fprintf(stderr,
"NETRootInfo::setNumberOfDesktops: setting desktop count to %d (%s)\n",
numberOfDesktops, (role == WindowManager) ? "WM" : "Client");
#endif
if (role == WindowManager) {
p->number_of_desktops = numberOfDesktops;
long d = numberOfDesktops;
XChangeProperty(p->display, p->root, net_number_of_desktops, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) &d, 1);
} else {
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.message_type = net_number_of_desktops;
e.xclient.display = p->display;
e.xclient.window = p->root;
e.xclient.format = 32;
e.xclient.data.l[0] = numberOfDesktops;
e.xclient.data.l[1] = 0l;
e.xclient.data.l[2] = 0l;
e.xclient.data.l[3] = 0l;
e.xclient.data.l[4] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
}
void NETRootInfo::setCurrentDesktop(int desktop) {
#ifdef NETWMDEBUG
fprintf(stderr,
"NETRootInfo::setCurrentDesktop: setting current desktop = %d (%s)\n",
desktop, (role == WindowManager) ? "WM" : "Client");
#endif
if (role == WindowManager) {
p->current_desktop = desktop;
long d = p->current_desktop - 1;
XChangeProperty(p->display, p->root, net_current_desktop, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) &d, 1);
} else {
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.message_type = net_current_desktop;
e.xclient.display = p->display;
e.xclient.window = p->root;
e.xclient.format = 32;
e.xclient.data.l[0] = desktop - 1;
e.xclient.data.l[1] = 0l;
e.xclient.data.l[2] = 0l;
e.xclient.data.l[3] = 0l;
e.xclient.data.l[4] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
}
void NETRootInfo::setDesktopName(int desktop, const char *desktopName) {
// allow setting desktop names even for non-existant desktops, see the spec, sect.3.7.
if (desktop < 1) return;
delete [] p->desktop_names[desktop - 1];
p->desktop_names[desktop - 1] = nstrdup(desktopName);
unsigned int i, proplen,
num = ((p->number_of_desktops > p->desktop_names.size()) ?
p->number_of_desktops : p->desktop_names.size());
for (i = 0, proplen = 0; i < num; i++)
proplen += (p->desktop_names[i] != 0 ? strlen(p->desktop_names[i])+1 : 1 );
char *prop = new char[proplen], *propp = prop;
for (i = 0; i < num; i++)
if (p->desktop_names[i]) {
strcpy(propp, p->desktop_names[i]);
propp += strlen(p->desktop_names[i]) + 1;
} else
*propp++ = '\0';
#ifdef NETWMDEBUG
fprintf(stderr,
"NETRootInfo::setDesktopName(%d, '%s')\n"
"NETRootInfo::setDesktopName: total property length = %d",
desktop, desktopName, proplen);
#endif
XChangeProperty(p->display, p->root, net_desktop_names, UTF8_STRING, 8,
PropModeReplace, (unsigned char *) prop, proplen);
delete [] prop;
}
void NETRootInfo::setDesktopGeometry(int , const NETSize &geometry) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::setDesktopGeometry( -- , { %d, %d }) (%s)\n",
geometry.width, geometry.height, (role == WindowManager) ? "WM" : "Client");
#endif
if (role == WindowManager) {
p->geometry = geometry;
long data[2];
data[0] = p->geometry.width;
data[1] = p->geometry.height;
XChangeProperty(p->display, p->root, net_desktop_geometry, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) data, 2);
} else {
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.message_type = net_desktop_geometry;
e.xclient.display = p->display;
e.xclient.window = p->root;
e.xclient.format = 32;
e.xclient.data.l[0] = geometry.width;
e.xclient.data.l[1] = geometry.height;
e.xclient.data.l[2] = 0l;
e.xclient.data.l[3] = 0l;
e.xclient.data.l[4] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
}
void NETRootInfo::setDesktopViewport(int desktop, const NETPoint &viewport) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::setDesktopViewport(%d, { %d, %d }) (%s)\n",
desktop, viewport.x, viewport.y, (role == WindowManager) ? "WM" : "Client");
#endif
if (desktop < 1) return;
if (role == WindowManager) {
p->viewport[desktop - 1] = viewport;
int d, i, l;
l = p->number_of_desktops * 2;
long *data = new long[l];
for (d = 0, i = 0; d < p->number_of_desktops; d++) {
data[i++] = p->viewport[d].x;
data[i++] = p->viewport[d].y;
}
XChangeProperty(p->display, p->root, net_desktop_viewport, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) data, l);
delete [] data;
} else {
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.message_type = net_desktop_viewport;
e.xclient.display = p->display;
e.xclient.window = p->root;
e.xclient.format = 32;
e.xclient.data.l[0] = viewport.x;
e.xclient.data.l[1] = viewport.y;
e.xclient.data.l[2] = 0l;
e.xclient.data.l[3] = 0l;
e.xclient.data.l[4] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
}
void NETRootInfo::setSupported() {
if (role != WindowManager) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::setSupported - role != WindowManager\n");
#endif
return;
}
Atom atoms[netAtomCount];
int pnum = 2;
// Root window properties/messages
atoms[0] = net_supported;
atoms[1] = net_supporting_wm_check;
if (p->properties[ PROTOCOLS ] & ClientList)
atoms[pnum++] = net_client_list;
if (p->properties[ PROTOCOLS ] & ClientListStacking)
atoms[pnum++] = net_client_list_stacking;
if (p->properties[ PROTOCOLS ] & NumberOfDesktops)
atoms[pnum++] = net_number_of_desktops;
if (p->properties[ PROTOCOLS ] & DesktopGeometry)
atoms[pnum++] = net_desktop_geometry;
if (p->properties[ PROTOCOLS ] & DesktopViewport)
atoms[pnum++] = net_desktop_viewport;
if (p->properties[ PROTOCOLS ] & CurrentDesktop)
atoms[pnum++] = net_current_desktop;
if (p->properties[ PROTOCOLS ] & DesktopNames)
atoms[pnum++] = net_desktop_names;
if (p->properties[ PROTOCOLS ] & ActiveWindow)
atoms[pnum++] = net_active_window;
if (p->properties[ PROTOCOLS ] & WorkArea)
atoms[pnum++] = net_workarea;
if (p->properties[ PROTOCOLS ] & VirtualRoots)
atoms[pnum++] = net_virtual_roots;
if (p->properties[ PROTOCOLS2 ] & WM2DesktopLayout)
atoms[pnum++] = net_desktop_layout;
if (p->properties[ PROTOCOLS ] & CloseWindow)
atoms[pnum++] = net_close_window;
if (p->properties[ PROTOCOLS2 ] & WM2RestackWindow)
atoms[pnum++] = net_restack_window;
if (p->properties[ PROTOCOLS2 ] & WM2ShowingDesktop)
atoms[pnum++] = net_showing_desktop;
// Application window properties/messages
if (p->properties[ PROTOCOLS ] & WMMoveResize)
atoms[pnum++] = net_wm_moveresize;
if (p->properties[ PROTOCOLS2 ] & WM2MoveResizeWindow)
atoms[pnum++] = net_moveresize_window;
if (p->properties[ PROTOCOLS ] & WMName)
atoms[pnum++] = net_wm_name;
if (p->properties[ PROTOCOLS ] & WMVisibleName)
atoms[pnum++] = net_wm_visible_name;
if (p->properties[ PROTOCOLS ] & WMIconName)
atoms[pnum++] = net_wm_icon_name;
if (p->properties[ PROTOCOLS ] & WMVisibleIconName)
atoms[pnum++] = net_wm_visible_icon_name;
if (p->properties[ PROTOCOLS ] & WMDesktop)
atoms[pnum++] = net_wm_desktop;
if (p->properties[ PROTOCOLS ] & WMWindowType) {
atoms[pnum++] = net_wm_window_type;
// Application window types
if (p->properties[ WINDOW_TYPES ] & NormalMask)
atoms[pnum++] = net_wm_window_type_normal;
if (p->properties[ WINDOW_TYPES ] & DesktopMask)
atoms[pnum++] = net_wm_window_type_desktop;
if (p->properties[ WINDOW_TYPES ] & DockMask)
atoms[pnum++] = net_wm_window_type_dock;
if (p->properties[ WINDOW_TYPES ] & ToolbarMask)
atoms[pnum++] = net_wm_window_type_toolbar;
if (p->properties[ WINDOW_TYPES ] & MenuMask)
atoms[pnum++] = net_wm_window_type_menu;
if (p->properties[ WINDOW_TYPES ] & DialogMask)
atoms[pnum++] = net_wm_window_type_dialog;
if (p->properties[ WINDOW_TYPES ] & UtilityMask)
atoms[pnum++] = net_wm_window_type_utility;
if (p->properties[ WINDOW_TYPES ] & SplashMask)
atoms[pnum++] = net_wm_window_type_splash;
if (p->properties[ WINDOW_TYPES ] & DropdownMenuMask)
atoms[pnum++] = net_wm_window_type_dropdown_menu;
if (p->properties[ WINDOW_TYPES ] & PopupMenuMask)
atoms[pnum++] = net_wm_window_type_popup_menu;
if (p->properties[ WINDOW_TYPES ] & TooltipMask)
atoms[pnum++] = net_wm_window_type_tooltip;
if (p->properties[ WINDOW_TYPES ] & NotificationMask)
atoms[pnum++] = net_wm_window_type_notification;
if (p->properties[ WINDOW_TYPES ] & ComboBoxMask)
atoms[pnum++] = net_wm_window_type_combobox;
if (p->properties[ WINDOW_TYPES ] & DNDIconMask)
atoms[pnum++] = net_wm_window_type_dnd;
// KDE extensions
if (p->properties[ WINDOW_TYPES ] & OverrideMask)
atoms[pnum++] = kde_net_wm_window_type_override;
if (p->properties[ WINDOW_TYPES ] & TopMenuMask)
atoms[pnum++] = kde_net_wm_window_type_topmenu;
}
if (p->properties[ PROTOCOLS ] & WMState) {
atoms[pnum++] = net_wm_state;
// Application window states
if (p->properties[ STATES ] & Modal)
atoms[pnum++] = net_wm_state_modal;
if (p->properties[ STATES ] & Sticky)
atoms[pnum++] = net_wm_state_sticky;
if (p->properties[ STATES ] & MaxVert)
atoms[pnum++] = net_wm_state_max_vert;
if (p->properties[ STATES ] & MaxHoriz)
atoms[pnum++] = net_wm_state_max_horiz;
if (p->properties[ STATES ] & Shaded)
atoms[pnum++] = net_wm_state_shaded;
if (p->properties[ STATES ] & SkipTaskbar)
atoms[pnum++] = net_wm_state_skip_taskbar;
if (p->properties[ STATES ] & SkipPager)
atoms[pnum++] = net_wm_state_skip_pager;
if (p->properties[ STATES ] & Hidden)
atoms[pnum++] = net_wm_state_hidden;
if (p->properties[ STATES ] & FullScreen)
atoms[pnum++] = net_wm_state_fullscreen;
if (p->properties[ STATES ] & KeepAbove)
atoms[pnum++] = net_wm_state_above;
if (p->properties[ STATES ] & KeepBelow)
atoms[pnum++] = net_wm_state_below;
if (p->properties[ STATES ] & DemandsAttention)
atoms[pnum++] = net_wm_state_demands_attention;
if (p->properties[ STATES ] & StaysOnTop)
atoms[pnum++] = net_wm_state_stays_on_top;
}
if (p->properties[ PROTOCOLS ] & WMStrut)
atoms[pnum++] = net_wm_strut;
if (p->properties[ PROTOCOLS2 ] & WM2ExtendedStrut)
atoms[pnum++] = net_wm_extended_strut;
if (p->properties[ PROTOCOLS ] & WMIconGeometry)
atoms[pnum++] = net_wm_icon_geometry;
if (p->properties[ PROTOCOLS ] & WMIcon)
atoms[pnum++] = net_wm_icon;
if (p->properties[ PROTOCOLS ] & WMPid)
atoms[pnum++] = net_wm_pid;
if (p->properties[ PROTOCOLS ] & WMHandledIcons)
atoms[pnum++] = net_wm_handled_icons;
if (p->properties[ PROTOCOLS ] & WMPing)
atoms[pnum++] = net_wm_ping;
if (p->properties[ PROTOCOLS2 ] & WM2TakeActivity)
atoms[pnum++] = net_wm_take_activity;
if (p->properties[ PROTOCOLS2 ] & WM2UserTime)
atoms[pnum++] = net_wm_user_time;
if (p->properties[ PROTOCOLS2 ] & WM2StartupId)
atoms[pnum++] = net_startup_id;
if (p->properties[ PROTOCOLS2 ] & WM2AllowedActions) {
atoms[pnum++] = net_wm_allowed_actions;
// Actions
if (p->properties[ ACTIONS ] & ActionMove)
atoms[pnum++] = net_wm_action_move;
if (p->properties[ ACTIONS ] & ActionResize)
atoms[pnum++] = net_wm_action_resize;
if (p->properties[ ACTIONS ] & ActionMinimize)
atoms[pnum++] = net_wm_action_minimize;
if (p->properties[ ACTIONS ] & ActionShade)
atoms[pnum++] = net_wm_action_shade;
if (p->properties[ ACTIONS ] & ActionStick)
atoms[pnum++] = net_wm_action_stick;
if (p->properties[ ACTIONS ] & ActionMaxVert)
atoms[pnum++] = net_wm_action_max_vert;
if (p->properties[ ACTIONS ] & ActionMaxHoriz)
atoms[pnum++] = net_wm_action_max_horiz;
if (p->properties[ ACTIONS ] & ActionFullScreen)
atoms[pnum++] = net_wm_action_fullscreen;
if (p->properties[ ACTIONS ] & ActionChangeDesktop)
atoms[pnum++] = net_wm_action_change_desk;
if (p->properties[ ACTIONS ] & ActionClose)
atoms[pnum++] = net_wm_action_close;
}
// KDE specific extensions
if (p->properties[ PROTOCOLS ] & KDESystemTrayWindows)
atoms[pnum++] = kde_net_system_tray_windows;
if (p->properties[ PROTOCOLS ] & WMKDESystemTrayWinFor)
atoms[pnum++] = kde_net_wm_system_tray_window_for;
if (p->properties[ PROTOCOLS ] & WMFrameExtents) {
atoms[pnum++] = net_frame_extents;
atoms[pnum++] = kde_net_wm_frame_strut;
}
if (p->properties[ PROTOCOLS2 ] & WM2KDETemporaryRules)
atoms[pnum++] = kde_net_wm_temporary_rules;
if (p->properties[ PROTOCOLS2 ] & WM2FullPlacement)
atoms[pnum++] = net_wm_full_placement;
XChangeProperty(p->display, p->root, net_supported, XA_ATOM, 32,
PropModeReplace, (unsigned char *) atoms, pnum);
XChangeProperty(p->display, p->root, net_supporting_wm_check, XA_WINDOW, 32,
PropModeReplace, (unsigned char *) &(p->supportwindow), 1);
#ifdef NETWMDEBUG
fprintf(stderr,
"NETRootInfo::setSupported: _NET_SUPPORTING_WM_CHECK = 0x%lx on 0x%lx\n"
" : _NET_WM_NAME = '%s' on 0x%lx\n",
p->supportwindow, p->supportwindow, p->name, p->supportwindow);
#endif
XChangeProperty(p->display, p->supportwindow, net_supporting_wm_check,
XA_WINDOW, 32, PropModeReplace,
(unsigned char *) &(p->supportwindow), 1);
XChangeProperty(p->display, p->supportwindow, net_wm_name, UTF8_STRING, 8,
PropModeReplace, (unsigned char *) p->name,
strlen(p->name));
}
void NETRootInfo::updateSupportedProperties( Atom atom )
{
if( atom == net_supported )
p->properties[ PROTOCOLS ] |= Supported;
else if( atom == net_supporting_wm_check )
p->properties[ PROTOCOLS ] |= SupportingWMCheck;
else if( atom == net_client_list )
p->properties[ PROTOCOLS ] |= ClientList;
else if( atom == net_client_list_stacking )
p->properties[ PROTOCOLS ] |= ClientListStacking;
else if( atom == net_number_of_desktops )
p->properties[ PROTOCOLS ] |= NumberOfDesktops;
else if( atom == net_desktop_geometry )
p->properties[ PROTOCOLS ] |= DesktopGeometry;
else if( atom == net_desktop_viewport )
p->properties[ PROTOCOLS ] |= DesktopViewport;
else if( atom == net_current_desktop )
p->properties[ PROTOCOLS ] |= CurrentDesktop;
else if( atom == net_desktop_names )
p->properties[ PROTOCOLS ] |= DesktopNames;
else if( atom == net_active_window )
p->properties[ PROTOCOLS ] |= ActiveWindow;
else if( atom == net_workarea )
p->properties[ PROTOCOLS ] |= WorkArea;
else if( atom == net_virtual_roots )
p->properties[ PROTOCOLS ] |= VirtualRoots;
else if( atom == net_desktop_layout )
p->properties[ PROTOCOLS2 ] |= WM2DesktopLayout;
else if( atom == net_close_window )
p->properties[ PROTOCOLS ] |= CloseWindow;
else if( atom == net_restack_window )
p->properties[ PROTOCOLS2 ] |= WM2RestackWindow;
else if( atom == net_showing_desktop )
p->properties[ PROTOCOLS2 ] |= WM2ShowingDesktop;
// Application window properties/messages
else if( atom == net_wm_moveresize )
p->properties[ PROTOCOLS ] |= WMMoveResize;
else if( atom == net_moveresize_window )
p->properties[ PROTOCOLS2 ] |= WM2MoveResizeWindow;
else if( atom == net_wm_name )
p->properties[ PROTOCOLS ] |= WMName;
else if( atom == net_wm_visible_name )
p->properties[ PROTOCOLS ] |= WMVisibleName;
else if( atom == net_wm_icon_name )
p->properties[ PROTOCOLS ] |= WMIconName;
else if( atom == net_wm_visible_icon_name )
p->properties[ PROTOCOLS ] |= WMVisibleIconName;
else if( atom == net_wm_desktop )
p->properties[ PROTOCOLS ] |= WMDesktop;
else if( atom == net_wm_window_type )
p->properties[ PROTOCOLS ] |= WMWindowType;
// Application window types
else if( atom == net_wm_window_type_normal )
p->properties[ WINDOW_TYPES ] |= NormalMask;
else if( atom == net_wm_window_type_desktop )
p->properties[ WINDOW_TYPES ] |= DesktopMask;
else if( atom == net_wm_window_type_dock )
p->properties[ WINDOW_TYPES ] |= DockMask;
else if( atom == net_wm_window_type_toolbar )
p->properties[ WINDOW_TYPES ] |= ToolbarMask;
else if( atom == net_wm_window_type_menu )
p->properties[ WINDOW_TYPES ] |= MenuMask;
else if( atom == net_wm_window_type_dialog )
p->properties[ WINDOW_TYPES ] |= DialogMask;
else if( atom == net_wm_window_type_utility )
p->properties[ WINDOW_TYPES ] |= UtilityMask;
else if( atom == net_wm_window_type_splash )
p->properties[ WINDOW_TYPES ] |= SplashMask;
else if( atom == net_wm_window_type_dropdown_menu )
p->properties[ WINDOW_TYPES ] |= DropdownMenuMask;
else if( atom == net_wm_window_type_popup_menu )
p->properties[ WINDOW_TYPES ] |= PopupMenuMask;
else if( atom == net_wm_window_type_tooltip )
p->properties[ WINDOW_TYPES ] |= TooltipMask;
else if( atom == net_wm_window_type_notification )
p->properties[ WINDOW_TYPES ] |= NotificationMask;
else if( atom == net_wm_window_type_combobox )
p->properties[ WINDOW_TYPES ] |= ComboBoxMask;
else if( atom == net_wm_window_type_dnd )
p->properties[ WINDOW_TYPES ] |= DNDIconMask;
// KDE extensions
else if( atom == kde_net_wm_window_type_override )
p->properties[ WINDOW_TYPES ] |= OverrideMask;
else if( atom == kde_net_wm_window_type_topmenu )
p->properties[ WINDOW_TYPES ] |= TopMenuMask;
else if( atom == net_wm_state )
p->properties[ PROTOCOLS ] |= WMState;
// Application window states
else if( atom == net_wm_state_modal )
p->properties[ STATES ] |= Modal;
else if( atom == net_wm_state_sticky )
p->properties[ STATES ] |= Sticky;
else if( atom == net_wm_state_max_vert )
p->properties[ STATES ] |= MaxVert;
else if( atom == net_wm_state_max_horiz )
p->properties[ STATES ] |= MaxHoriz;
else if( atom == net_wm_state_shaded )
p->properties[ STATES ] |= Shaded;
else if( atom == net_wm_state_skip_taskbar )
p->properties[ STATES ] |= SkipTaskbar;
else if( atom == net_wm_state_skip_pager )
p->properties[ STATES ] |= SkipPager;
else if( atom == net_wm_state_hidden )
p->properties[ STATES ] |= Hidden;
else if( atom == net_wm_state_fullscreen )
p->properties[ STATES ] |= FullScreen;
else if( atom == net_wm_state_above )
p->properties[ STATES ] |= KeepAbove;
else if( atom == net_wm_state_below )
p->properties[ STATES ] |= KeepBelow;
else if( atom == net_wm_state_demands_attention )
p->properties[ STATES ] |= DemandsAttention;
else if( atom == net_wm_state_stays_on_top )
p->properties[ STATES ] |= StaysOnTop;
else if( atom == net_wm_strut )
p->properties[ PROTOCOLS ] |= WMStrut;
else if( atom == net_wm_extended_strut )
p->properties[ PROTOCOLS2 ] |= WM2ExtendedStrut;
else if( atom == net_wm_icon_geometry )
p->properties[ PROTOCOLS ] |= WMIconGeometry;
else if( atom == net_wm_icon )
p->properties[ PROTOCOLS ] |= WMIcon;
else if( atom == net_wm_pid )
p->properties[ PROTOCOLS ] |= WMPid;
else if( atom == net_wm_handled_icons )
p->properties[ PROTOCOLS ] |= WMHandledIcons;
else if( atom == net_wm_ping )
p->properties[ PROTOCOLS ] |= WMPing;
else if( atom == net_wm_take_activity )
p->properties[ PROTOCOLS2 ] |= WM2TakeActivity;
else if( atom == net_wm_user_time )
p->properties[ PROTOCOLS2 ] |= WM2UserTime;
else if( atom == net_startup_id )
p->properties[ PROTOCOLS2 ] |= WM2StartupId;
else if( atom == net_wm_allowed_actions )
p->properties[ PROTOCOLS2 ] |= WM2AllowedActions;
// Actions
else if( atom == net_wm_action_move )
p->properties[ ACTIONS ] |= ActionMove;
else if( atom == net_wm_action_resize )
p->properties[ ACTIONS ] |= ActionResize;
else if( atom == net_wm_action_minimize )
p->properties[ ACTIONS ] |= ActionMinimize;
else if( atom == net_wm_action_shade )
p->properties[ ACTIONS ] |= ActionShade;
else if( atom == net_wm_action_stick )
p->properties[ ACTIONS ] |= ActionStick;
else if( atom == net_wm_action_max_vert )
p->properties[ ACTIONS ] |= ActionMaxVert;
else if( atom == net_wm_action_max_horiz )
p->properties[ ACTIONS ] |= ActionMaxHoriz;
else if( atom == net_wm_action_fullscreen )
p->properties[ ACTIONS ] |= ActionFullScreen;
else if( atom == net_wm_action_change_desk )
p->properties[ ACTIONS ] |= ActionChangeDesktop;
else if( atom == net_wm_action_close )
p->properties[ ACTIONS ] |= ActionClose;
// KDE specific extensions
else if( atom == kde_net_system_tray_windows )
p->properties[ PROTOCOLS ] |= KDESystemTrayWindows;
else if( atom == kde_net_wm_system_tray_window_for )
p->properties[ PROTOCOLS ] |= WMKDESystemTrayWinFor;
else if( atom == net_frame_extents )
p->properties[ PROTOCOLS ] |= WMFrameExtents;
else if( atom == kde_net_wm_frame_strut )
p->properties[ PROTOCOLS ] |= WMKDEFrameStrut;
else if( atom == kde_net_wm_temporary_rules )
p->properties[ PROTOCOLS2 ] |= WM2KDETemporaryRules;
else if( atom == net_wm_full_placement )
p->properties[ PROTOCOLS2 ] |= WM2FullPlacement;
}
void NETRootInfo::setActiveWindow(Window window) {
setActiveWindow( window, FromUnknown, GET_QT_X_USER_TIME(), None );
}
void NETRootInfo::setActiveWindow(Window window, NET::RequestSource src,
Time timestamp, Window active_window ) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::setActiveWindow(0x%lx) (%s)\n",
window, (role == WindowManager) ? "WM" : "Client");
#endif
if (role == WindowManager) {
p->active = window;
XChangeProperty(p->display, p->root, net_active_window, XA_WINDOW, 32,
PropModeReplace, (unsigned char *) &(p->active), 1);
} else {
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.message_type = net_active_window;
e.xclient.display = p->display;
e.xclient.window = window;
e.xclient.format = 32;
e.xclient.data.l[0] = src;
e.xclient.data.l[1] = timestamp;
e.xclient.data.l[2] = active_window;
e.xclient.data.l[3] = 0l;
e.xclient.data.l[4] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
}
void NETRootInfo::setWorkArea(int desktop, const NETRect &workarea) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::setWorkArea(%d, { %d, %d, %d, %d }) (%s)\n",
desktop, workarea.pos.x, workarea.pos.y, workarea.size.width, workarea.size.height,
(role == WindowManager) ? "WM" : "Client");
#endif
if (role != WindowManager || desktop < 1) return;
p->workarea[desktop - 1] = workarea;
long *wa = new long[p->number_of_desktops * 4];
int i, o;
for (i = 0, o = 0; i < p->number_of_desktops; i++) {
wa[o++] = p->workarea[i].pos.x;
wa[o++] = p->workarea[i].pos.y;
wa[o++] = p->workarea[i].size.width;
wa[o++] = p->workarea[i].size.height;
}
XChangeProperty(p->display, p->root, net_workarea, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) wa,
p->number_of_desktops * 4);
delete [] wa;
}
void NETRootInfo::setVirtualRoots(Window *windows, unsigned int count) {
if (role != WindowManager) return;
p->virtual_roots_count = count;
p->virtual_roots = windows;
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::setVirtualRoots: setting list with %ld windows\n",
p->virtual_roots_count);
#endif
XChangeProperty(p->display, p->root, net_virtual_roots, XA_WINDOW, 32,
PropModeReplace, (unsigned char *) p->virtual_roots,
p->virtual_roots_count);
}
void NETRootInfo::setDesktopLayout(NET::Orientation orientation, int columns, int rows,
NET::DesktopLayoutCorner corner)
{
p->desktop_layout_orientation = orientation;
p->desktop_layout_columns = columns;
p->desktop_layout_rows = rows;
p->desktop_layout_corner = corner;
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::setDesktopLayout: %d %d %d %d\n",
orientation, columns, rows, corner);
#endif
long data[ 4 ];
data[ 0 ] = orientation;
data[ 1 ] = columns;
data[ 2 ] = rows;
data[ 3 ] = corner;
XChangeProperty(p->display, p->root, net_desktop_layout, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) &data, 4);
}
void NETRootInfo::setShowingDesktop( bool showing ) {
if (role == WindowManager) {
long d = p->showing_desktop = showing;
XChangeProperty(p->display, p->root, net_showing_desktop, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) &d, 1);
} else {
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.message_type = net_showing_desktop;
e.xclient.display = p->display;
e.xclient.window = 0;
e.xclient.format = 32;
e.xclient.data.l[0] = showing ? 1 : 0;
e.xclient.data.l[1] = 0;
e.xclient.data.l[2] = 0;
e.xclient.data.l[3] = 0;
e.xclient.data.l[4] = 0;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
}
bool NETRootInfo::showingDesktop() const {
return p->showing_desktop;
}
void NETRootInfo::closeWindowRequest(Window window) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::closeWindowRequest: requesting close for 0x%lx\n",
window);
#endif
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.message_type = net_close_window;
e.xclient.display = p->display;
e.xclient.window = window;
e.xclient.format = 32;
e.xclient.data.l[0] = 0l;
e.xclient.data.l[1] = 0l;
e.xclient.data.l[2] = 0l;
e.xclient.data.l[3] = 0l;
e.xclient.data.l[4] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
void NETRootInfo::moveResizeRequest(Window window, int x_root, int y_root,
Direction direction)
{
#ifdef NETWMDEBUG
fprintf(stderr,
"NETRootInfo::moveResizeRequest: requesting resize/move for 0x%lx (%d, %d, %d)\n",
window, x_root, y_root, direction);
#endif
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.message_type = net_wm_moveresize;
e.xclient.display = p->display;
e.xclient.window = window,
e.xclient.format = 32;
e.xclient.data.l[0] = x_root;
e.xclient.data.l[1] = y_root;
e.xclient.data.l[2] = direction;
e.xclient.data.l[3] = 0l;
e.xclient.data.l[4] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
void NETRootInfo::moveResizeWindowRequest(Window window, int flags, int x, int y, int width, int height )
{
#ifdef NETWMDEBUG
fprintf(stderr,
"NETRootInfo::moveResizeWindowRequest: resizing/moving 0x%lx (%d, %d, %d, %d, %d)\n",
window, flags, x, y, width, height);
#endif
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.message_type = net_moveresize_window;
e.xclient.display = p->display;
e.xclient.window = window,
e.xclient.format = 32;
e.xclient.data.l[0] = flags;
e.xclient.data.l[1] = x;
e.xclient.data.l[2] = y;
e.xclient.data.l[3] = width;
e.xclient.data.l[4] = height;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
void NETRootInfo::restackRequest(Window window, Window above, int detail)
{
restackRequest( window, FromTool, above, detail, GET_QT_X_USER_TIME() );
}
void NETRootInfo::restackRequest(Window window, RequestSource src, Window above, int detail, Time timestamp )
{
#ifdef NETWMDEBUG
fprintf(stderr,
"NETRootInfo::restackRequest: requesting restack for 0x%lx (%lx, %d)\n",
window, above, detail);
#endif
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.message_type = net_restack_window;
e.xclient.display = p->display;
e.xclient.window = window,
e.xclient.format = 32;
e.xclient.data.l[0] = src;
e.xclient.data.l[1] = above;
e.xclient.data.l[2] = detail;
e.xclient.data.l[3] = timestamp;
e.xclient.data.l[4] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
void NETRootInfo2::sendPing( Window window, Time timestamp )
{
if (role != WindowManager) return;
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo2::setPing: window 0x%lx, timestamp %lu\n",
window, timestamp );
#endif
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.message_type = wm_protocols;
e.xclient.display = p->display;
e.xclient.window = window,
e.xclient.format = 32;
e.xclient.data.l[0] = net_wm_ping;
e.xclient.data.l[1] = timestamp;
e.xclient.data.l[2] = window;
e.xclient.data.l[3] = 0;
e.xclient.data.l[4] = 0;
XSendEvent(p->display, window, False, 0, &e);
}
void NETRootInfo3::takeActivity( Window window, Time timestamp, long flags )
{
if (role != WindowManager) return;
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo2::takeActivity: window 0x%lx, timestamp %lu, flags 0x%lx\n",
window, timestamp, flags );
#endif
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.message_type = wm_protocols;
e.xclient.display = p->display;
e.xclient.window = window,
e.xclient.format = 32;
e.xclient.data.l[0] = net_wm_take_activity;
e.xclient.data.l[1] = timestamp;
e.xclient.data.l[2] = window;
e.xclient.data.l[3] = flags;
e.xclient.data.l[4] = 0;
XSendEvent(p->display, window, False, 0, &e);
}
// assignment operator
const NETRootInfo &NETRootInfo::operator=(const NETRootInfo &rootinfo) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::operator=()\n");
#endif
if (p != rootinfo.p) {
refdec_nri(p);
if (! p->ref) delete p;
}
p = rootinfo.p;
role = rootinfo.role;
p->ref++;
return *this;
}
unsigned long NETRootInfo::event(XEvent *ev )
{
unsigned long props[ 1 ];
event( ev, props, 1 );
return props[ 0 ];
}
void NETRootInfo::event(XEvent *event, unsigned long* properties, int properties_size )
{
unsigned long props[ PROPERTIES_SIZE ] = { 0, 0, 0, 0, 0 };
assert( PROPERTIES_SIZE == 5 ); // add elements above
unsigned long& dirty = props[ PROTOCOLS ];
unsigned long& dirty2 = props[ PROTOCOLS2 ];
bool do_update = false;
// the window manager will be interested in client messages... no other
// client should get these messages
if (role == WindowManager && event->type == ClientMessage &&
event->xclient.format == 32) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::event: handling ClientMessage event\n");
#endif
if (event->xclient.message_type == net_number_of_desktops) {
dirty = NumberOfDesktops;
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::event: changeNumberOfDesktops(%ld)\n",
event->xclient.data.l[0]);
#endif
changeNumberOfDesktops(event->xclient.data.l[0]);
} else if (event->xclient.message_type == net_desktop_geometry) {
dirty = DesktopGeometry;
NETSize sz;
sz.width = event->xclient.data.l[0];
sz.height = event->xclient.data.l[1];
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::event: changeDesktopGeometry( -- , { %d, %d })\n",
sz.width, sz.height);
#endif
changeDesktopGeometry(~0, sz);
} else if (event->xclient.message_type == net_desktop_viewport) {
dirty = DesktopViewport;
NETPoint pt;
pt.x = event->xclient.data.l[0];
pt.y = event->xclient.data.l[1];
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::event: changeDesktopViewport(%d, { %d, %d })\n",
p->current_desktop, pt.x, pt.y);
#endif
changeDesktopViewport(p->current_desktop, pt);
} else if (event->xclient.message_type == net_current_desktop) {
dirty = CurrentDesktop;
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::event: changeCurrentDesktop(%ld)\n",
event->xclient.data.l[0] + 1);
#endif
changeCurrentDesktop(event->xclient.data.l[0] + 1);
} else if (event->xclient.message_type == net_active_window) {
dirty = ActiveWindow;
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::event: changeActiveWindow(0x%lx)\n",
event->xclient.window);
#endif
changeActiveWindow(event->xclient.window);
if( NETRootInfo2* this2 = dynamic_cast< NETRootInfo2* >( this ))
{
RequestSource src = FromUnknown;
Time timestamp = CurrentTime;
Window active_window = None;
// make sure there aren't unknown values
if( event->xclient.data.l[0] >= FromUnknown
&& event->xclient.data.l[0] <= FromTool )
{
src = static_cast< RequestSource >( event->xclient.data.l[0] );
timestamp = event->xclient.data.l[1];
active_window = event->xclient.data.l[2];
}
this2->changeActiveWindow( event->xclient.window, src, timestamp, active_window );
}
} else if (event->xclient.message_type == net_wm_moveresize) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::event: moveResize(%ld, %ld, %ld, %ld)\n",
event->xclient.window,
event->xclient.data.l[0],
event->xclient.data.l[1],
event->xclient.data.l[2]
);
#endif
moveResize(event->xclient.window,
event->xclient.data.l[0],
event->xclient.data.l[1],
event->xclient.data.l[2]);
} else if (event->xclient.message_type == net_moveresize_window) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::event: moveResizeWindow(%ld, %ld, %ld, %ld, %ld, %ld)\n",
event->xclient.window,
event->xclient.data.l[0],
event->xclient.data.l[1],
event->xclient.data.l[2],
event->xclient.data.l[3],
event->xclient.data.l[4]
);
#endif
if( NETRootInfo2* this2 = dynamic_cast< NETRootInfo2* >( this ))
this2->moveResizeWindow(event->xclient.window,
event->xclient.data.l[0],
event->xclient.data.l[1],
event->xclient.data.l[2],
event->xclient.data.l[3],
event->xclient.data.l[4]);
} else if (event->xclient.message_type == net_close_window) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::event: closeWindow(0x%lx)\n",
event->xclient.window);
#endif
closeWindow(event->xclient.window);
} else if (event->xclient.message_type == net_restack_window) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::event: restackWindow(0x%lx)\n",
event->xclient.window);
#endif
if( NETRootInfo3* this3 = dynamic_cast< NETRootInfo3* >( this ))
{
RequestSource src = FromUnknown;
Time timestamp = CurrentTime;
// make sure there aren't unknown values
if( event->xclient.data.l[0] >= FromUnknown
&& event->xclient.data.l[0] <= FromTool )
{
src = static_cast< RequestSource >( event->xclient.data.l[0] );
timestamp = event->xclient.data.l[3];
}
this3->restackWindow(event->xclient.window, src,
event->xclient.data.l[1], event->xclient.data.l[2], timestamp);
}
else if( NETRootInfo2* this2 = dynamic_cast< NETRootInfo2* >( this ))
this2->restackWindow(event->xclient.window,
event->xclient.data.l[1], event->xclient.data.l[2]);
} else if (event->xclient.message_type == wm_protocols
&& (Atom)event->xclient.data.l[ 0 ] == net_wm_ping) {
dirty = WMPing;
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo2::event: gotPing(0x%lx,%lu)\n",
event->xclient.window, event->xclient.data.l[1]);
#endif
if( NETRootInfo2* this2 = dynamic_cast< NETRootInfo2* >( this ))
this2->gotPing( event->xclient.data.l[2], event->xclient.data.l[1]);
} else if (event->xclient.message_type == wm_protocols
&& (Atom)event->xclient.data.l[ 0 ] == net_wm_take_activity) {
dirty2 = WM2TakeActivity;
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo2::event: gotTakeActivity(0x%lx,%lu,0x%lx)\n",
event->xclient.window, event->xclient.data.l[1], event->xclient.data.l[3]);
#endif
if( NETRootInfo3* this3 = dynamic_cast< NETRootInfo3* >( this ))
this3->gotTakeActivity( event->xclient.data.l[2], event->xclient.data.l[1],
event->xclient.data.l[3]);
} else if (event->xclient.message_type == net_showing_desktop) {
dirty2 = WM2ShowingDesktop;
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::event: changeShowingDesktop(%ld)\n",
event->xclient.data.l[0]);
#endif
if( NETRootInfo4* this4 = dynamic_cast< NETRootInfo4* >( this ))
this4->changeShowingDesktop(event->xclient.data.l[0]);
}
}
if (event->type == PropertyNotify) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::event: handling PropertyNotify event\n");
#endif
XEvent pe = *event;
Bool done = False;
Bool compaction = False;
while (! done) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::event: loop fire\n");
#endif
if (pe.xproperty.atom == net_client_list)
dirty |= ClientList;
else if (pe.xproperty.atom == net_client_list_stacking)
dirty |= ClientListStacking;
else if (pe.xproperty.atom == kde_net_system_tray_windows)
dirty |= KDESystemTrayWindows;
else if (pe.xproperty.atom == net_desktop_names)
dirty |= DesktopNames;
else if (pe.xproperty.atom == net_workarea)
dirty |= WorkArea;
else if (pe.xproperty.atom == net_number_of_desktops)
dirty |= NumberOfDesktops;
else if (pe.xproperty.atom == net_desktop_geometry)
dirty |= DesktopGeometry;
else if (pe.xproperty.atom == net_desktop_viewport)
dirty |= DesktopViewport;
else if (pe.xproperty.atom == net_current_desktop)
dirty |= CurrentDesktop;
else if (pe.xproperty.atom == net_active_window)
dirty |= ActiveWindow;
else if (pe.xproperty.atom == net_showing_desktop)
dirty2 |= WM2ShowingDesktop;
// else if (pe.xproperty.atom == net_supported )
// dirty |= Supported; // update here?
else if (pe.xproperty.atom == net_supporting_wm_check )
dirty |= SupportingWMCheck;
else if (pe.xproperty.atom == net_virtual_roots )
dirty |= VirtualRoots;
else if (pe.xproperty.atom == net_desktop_layout )
dirty2 |= WM2DesktopLayout;
else {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::event: putting back event and breaking\n");
#endif
if ( compaction )
XPutBackEvent(p->display, &pe);
break;
}
if (XCheckTypedWindowEvent(p->display, p->root, PropertyNotify, &pe) )
compaction = True;
else
break;
}
do_update = true;
}
if( do_update )
update( props );
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::event: handled events, returning dirty = 0x%lx, 0x%lx\n",
dirty, dirty2);
#endif
if( properties_size > PROPERTIES_SIZE )
properties_size = PROPERTIES_SIZE;
for( int i = 0;
i < properties_size;
++i )
properties[ i ] = props[ i ];
}
// private functions to update the data we keep
void NETRootInfo::update( const unsigned long dirty_props[] )
{
Atom type_ret;
int format_ret;
unsigned char *data_ret;
unsigned long nitems_ret, unused;
unsigned long props[ PROPERTIES_SIZE ];
for( int i = 0;
i < PROPERTIES_SIZE;
++i )
props[ i ] = dirty_props[ i ] & p->client_properties[ i ];
const unsigned long& dirty = props[ PROTOCOLS ];
const unsigned long& dirty2 = props[ PROTOCOLS2 ];
if (dirty & Supported ) {
// only in Client mode
for( int i = 0; i < PROPERTIES_SIZE; ++i )
p->properties[ i ] = 0;
if( XGetWindowProperty(p->display, p->root, net_supported,
0l, MAX_PROP_SIZE, False, XA_ATOM, &type_ret,
&format_ret, &nitems_ret, &unused, &data_ret)
== Success ) {
if( type_ret == XA_ATOM && format_ret == 32 ) {
Atom* atoms = (Atom*) data_ret;
for( unsigned int i = 0;
i < nitems_ret;
++i )
updateSupportedProperties( atoms[ i ] );
}
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & ClientList) {
bool read_ok = false;
if (XGetWindowProperty(p->display, p->root, net_client_list,
0l, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret,
&format_ret, &nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_WINDOW && format_ret == 32) {
Window *wins = (Window *) data_ret;
qsort(wins, nitems_ret, sizeof(Window), wcmp);
if (p->clients) {
if (role == Client) {
unsigned long new_index = 0, old_index = 0;
unsigned long new_count = nitems_ret,
old_count = p->clients_count;
while (old_index < old_count || new_index < new_count) {
if (old_index == old_count) {
addClient(wins[new_index++]);
} else if (new_index == new_count) {
removeClient(p->clients[old_index++]);
} else {
if (p->clients[old_index] <
wins[new_index]) {
removeClient(p->clients[old_index++]);
} else if (wins[new_index] <
p->clients[old_index]) {
addClient(wins[new_index++]);
} else {
new_index++;
old_index++;
}
}
}
}
delete [] p->clients;
} else {
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::update: client list null, creating\n");
#endif
unsigned long n;
for (n = 0; n < nitems_ret; n++) {
addClient(wins[n]);
}
}
p->clients_count = nitems_ret;
p->clients = nwindup(wins, p->clients_count);
read_ok = true;
}
if ( data_ret )
XFree(data_ret);
}
if( !read_ok ) {
for( unsigned int i = 0; i < p->clients_count; ++ i )
removeClient(p->clients[i]);
p->clients_count = 0;
delete[] p->clients;
p->clients = NULL;
}
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::update: client list updated (%ld clients)\n",
p->clients_count);
#endif
}
if (dirty & KDESystemTrayWindows) {
bool read_ok = false;
if (XGetWindowProperty(p->display, p->root, kde_net_system_tray_windows,
0l, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret,
&format_ret, &nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_WINDOW && format_ret == 32) {
Window *wins = (Window *) data_ret;
qsort(wins, nitems_ret, sizeof(Window), wcmp);
if (p->kde_system_tray_windows) {
if (role == Client) {
unsigned long new_index = 0, new_count = nitems_ret;
unsigned long old_index = 0,
old_count = p->kde_system_tray_windows_count;
while(old_index < old_count || new_index < new_count) {
if (old_index == old_count) {
addSystemTrayWin(wins[new_index++]);
} else if (new_index == new_count) {
removeSystemTrayWin(p->kde_system_tray_windows[old_index++]);
} else {
if (p->kde_system_tray_windows[old_index] <
wins[new_index]) {
removeSystemTrayWin(p->kde_system_tray_windows[old_index++]);
} else if (wins[new_index] <
p->kde_system_tray_windows[old_index]) {
addSystemTrayWin(wins[new_index++]);
} else {
new_index++;
old_index++;
}
}
}
}
} else {
unsigned long n;
for (n = 0; n < nitems_ret; n++) {
addSystemTrayWin(wins[n]);
}
}
p->kde_system_tray_windows_count = nitems_ret;
delete [] p->kde_system_tray_windows;
p->kde_system_tray_windows =
nwindup(wins, p->kde_system_tray_windows_count);
read_ok = true;
}
if ( data_ret )
XFree(data_ret);
}
if( !read_ok ) {
for( unsigned int i = 0; i < p->kde_system_tray_windows_count; ++i )
removeSystemTrayWin(p->kde_system_tray_windows[i]);
p->kde_system_tray_windows_count = 0;
delete [] p->kde_system_tray_windows;
p->kde_system_tray_windows = NULL;
}
}
if (dirty & ClientListStacking) {
p->stacking_count = 0;
delete[] p->stacking;
p->stacking = NULL;
if (XGetWindowProperty(p->display, p->root, net_client_list_stacking,
0, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret,
&format_ret, &nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_WINDOW && format_ret == 32) {
Window *wins = (Window *) data_ret;
p->stacking_count = nitems_ret;
p->stacking = nwindup(wins, p->stacking_count);
}
#ifdef NETWMDEBUG
fprintf(stderr,"NETRootInfo::update: client stacking updated (%ld clients)\n",
p->stacking_count);
#endif
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & NumberOfDesktops) {
p->number_of_desktops = 0;
if (XGetWindowProperty(p->display, p->root, net_number_of_desktops,
0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) {
p->number_of_desktops = *((long *) data_ret);
}
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::update: number of desktops = %d\n",
p->number_of_desktops);
#endif
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & DesktopGeometry) {
p->geometry = p->rootSize;
if (XGetWindowProperty(p->display, p->root, net_desktop_geometry,
0l, 2l, False, XA_CARDINAL, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_CARDINAL && format_ret == 32 &&
nitems_ret == 2) {
long *data = (long *) data_ret;
p->geometry.width = data[0];
p->geometry.height = data[1];
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::update: desktop geometry updated\n");
#endif
}
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & DesktopViewport) {
for (int i = 0; i < p->viewport.size(); i++)
p->viewport[i].x = p->viewport[i].y = 0;
if (XGetWindowProperty(p->display, p->root, net_desktop_viewport,
0l, 2l, False, XA_CARDINAL, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_CARDINAL && format_ret == 32 &&
nitems_ret == 2) {
long *data = (long *) data_ret;
int d, i, n;
n = nitems_ret / 2;
for (d = 0, i = 0; d < n; d++) {
p->viewport[d].x = data[i++];
p->viewport[d].y = data[i++];
}
#ifdef NETWMDEBUG
fprintf(stderr,
"NETRootInfo::update: desktop viewport array updated (%d entries)\n",
p->viewport.size());
if (nitems_ret % 2 != 0) {
fprintf(stderr,
"NETRootInfo::update(): desktop viewport array "
"size not a multiple of 2\n");
}
#endif
}
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & CurrentDesktop) {
p->current_desktop = 0;
if (XGetWindowProperty(p->display, p->root, net_current_desktop,
0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) {
p->current_desktop = *((long *) data_ret) + 1;
}
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::update: current desktop = %d\n",
p->current_desktop);
#endif
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & DesktopNames) {
for( int i = 0; i < p->desktop_names.size(); ++i )
delete[] p->desktop_names[ i ];
p->desktop_names.reset();
if (XGetWindowProperty(p->display, p->root, net_desktop_names,
0l, MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
&format_ret, &nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == UTF8_STRING && format_ret == 8) {
const char *d = (const char *) data_ret;
unsigned int s, n, index;
for (s = 0, n = 0, index = 0; n < nitems_ret; n++) {
if (d[n] == '\0') {
delete [] p->desktop_names[index];
p->desktop_names[index++] = nstrndup((d + s), n - s + 1);
s = n + 1;
}
}
}
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::update: desktop names array updated (%d entries)\n",
p->desktop_names.size());
#endif
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & ActiveWindow) {
p->active = None;
if (XGetWindowProperty(p->display, p->root, net_active_window, 0l, 1l,
False, XA_WINDOW, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_WINDOW && format_ret == 32 && nitems_ret == 1) {
p->active = *((Window *) data_ret);
}
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::update: active window = 0x%lx\n",
p->active);
#endif
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & WorkArea) {
p->workarea.reset();
if (XGetWindowProperty(p->display, p->root, net_workarea, 0l,
(p->number_of_desktops * 4), False, XA_CARDINAL,
&type_ret, &format_ret, &nitems_ret, &unused,
&data_ret)
== Success) {
if (type_ret == XA_CARDINAL && format_ret == 32 &&
nitems_ret == (unsigned) (p->number_of_desktops * 4)) {
long *d = (long *) data_ret;
int i, j;
for (i = 0, j = 0; i < p->number_of_desktops; i++) {
p->workarea[i].pos.x = d[j++];
p->workarea[i].pos.y = d[j++];
p->workarea[i].size.width = d[j++];
p->workarea[i].size.height = d[j++];
}
}
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::update: work area array updated (%d entries)\n",
p->workarea.size());
#endif
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & SupportingWMCheck) {
p->supportwindow = None;
delete[] p->name;
p->name = NULL;
if (XGetWindowProperty(p->display, p->root, net_supporting_wm_check,
0l, 1l, False, XA_WINDOW, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_WINDOW && format_ret == 32 && nitems_ret == 1) {
p->supportwindow = *((Window *) data_ret);
unsigned char *name_ret;
if (XGetWindowProperty(p->display, p->supportwindow,
net_wm_name, 0l, MAX_PROP_SIZE, False,
UTF8_STRING, &type_ret, &format_ret,
&nitems_ret, &unused, &name_ret)
== Success) {
if (type_ret == UTF8_STRING && format_ret == 8)
p->name = nstrndup((const char *) name_ret, nitems_ret);
if ( name_ret )
XFree(name_ret);
}
}
#ifdef NETWMDEBUG
fprintf(stderr,
"NETRootInfo::update: supporting window manager = '%s'\n",
p->name);
#endif
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & VirtualRoots) {
p->virtual_roots_count = 0;
delete[] p->virtual_roots;
p->virtual_roots = NULL;
if (XGetWindowProperty(p->display, p->root, net_virtual_roots,
0, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret,
&format_ret, &nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_WINDOW && format_ret == 32) {
Window *wins = (Window *) data_ret;
p->virtual_roots_count = nitems_ret;
p->virtual_roots = nwindup(wins, p->virtual_roots_count);
}
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::updated: virtual roots updated (%ld windows)\n",
p->virtual_roots_count);
#endif
if ( data_ret )
XFree(data_ret);
}
}
if (dirty2 & WM2DesktopLayout) {
p->desktop_layout_orientation = OrientationHorizontal;
p->desktop_layout_corner = DesktopLayoutCornerTopLeft;
p->desktop_layout_columns = p->desktop_layout_rows = 0;
if (XGetWindowProperty(p->display, p->root, net_desktop_layout,
0, MAX_PROP_SIZE, False, XA_CARDINAL, &type_ret,
&format_ret, &nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_CARDINAL && format_ret == 32) {
long* data = (long*) data_ret;
if( nitems_ret >= 4 && data[ 3 ] >= 0 && data[ 3 ] <= 3 )
p->desktop_layout_corner = (NET::DesktopLayoutCorner)data[ 3 ];
if( nitems_ret >= 3 ) {
if( data[ 0 ] >= 0 && data[ 0 ] <= 1 )
p->desktop_layout_orientation = (NET::Orientation)data[ 0 ];
p->desktop_layout_columns = data[ 1 ];
p->desktop_layout_rows = data[ 2 ];
}
}
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::updated: desktop layout updated (%d %d %d %d)\n",
p->desktop_layout_orientation, p->desktop_layout_columns,
p->desktop_layout_rows, p->desktop_layout_corner );
#endif
if ( data_ret )
XFree(data_ret);
}
}
if (dirty2 & WM2ShowingDesktop) {
p->showing_desktop = false;
if (XGetWindowProperty(p->display, p->root, net_showing_desktop,
0, MAX_PROP_SIZE, False, XA_CARDINAL, &type_ret,
&format_ret, &nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) {
p->showing_desktop = *((long *) data_ret);
}
#ifdef NETWMDEBUG
fprintf(stderr, "NETRootInfo::update: showing desktop = %d\n",
p->showing_desktop);
#endif
if ( data_ret )
XFree(data_ret);
}
}
}
Display *NETRootInfo::x11Display() const {
return p->display;
}
Window NETRootInfo::rootWindow() const {
return p->root;
}
Window NETRootInfo::supportWindow() const {
return p->supportwindow;
}
const char *NETRootInfo::wmName() const {
return p->name; }
int NETRootInfo::screenNumber() const {
return p->screen;
}
unsigned long NETRootInfo::supported() const {
return role == WindowManager
? p->properties[ PROTOCOLS ]
: p->client_properties[ PROTOCOLS ];
}
const unsigned long* NETRootInfo::supportedProperties() const {
return p->properties;
}
const unsigned long* NETRootInfo::passedProperties() const {
return role == WindowManager
? p->properties
: p->client_properties;
}
bool NETRootInfo::isSupported( NET::Property property ) const {
return p->properties[ PROTOCOLS ] & property;
}
bool NETRootInfo::isSupported( NET::Property2 property ) const {
return p->properties[ PROTOCOLS2 ] & property;
}
bool NETRootInfo::isSupported( NET::WindowType type ) const {
return p->properties[ WINDOW_TYPES ] & type;
}
bool NETRootInfo::isSupported( NET::State state ) const {
return p->properties[ STATES ] & state;
}
bool NETRootInfo::isSupported( NET::Action action ) const {
return p->properties[ ACTIONS ] & action;
}
const Window *NETRootInfo::clientList() const {
return p->clients;
}
int NETRootInfo::clientListCount() const {
return p->clients_count;
}
const Window *NETRootInfo::clientListStacking() const {
return p->stacking;
}
int NETRootInfo::clientListStackingCount() const {
return p->stacking_count;
}
const Window *NETRootInfo::kdeSystemTrayWindows() const {
return p->kde_system_tray_windows;
}
int NETRootInfo::kdeSystemTrayWindowsCount() const {
return p->kde_system_tray_windows_count;
}
NETSize NETRootInfo::desktopGeometry(int) const {
return p->geometry.width != 0 ? p->geometry : p->rootSize;
}
NETPoint NETRootInfo::desktopViewport(int desktop) const {
if (desktop < 1) {
NETPoint pt; // set to (0,0)
return pt;
}
return p->viewport[desktop - 1];
}
NETRect NETRootInfo::workArea(int desktop) const {
if (desktop < 1) {
NETRect rt;
return rt;
}
return p->workarea[desktop - 1];
}
const char *NETRootInfo::desktopName(int desktop) const {
if (desktop < 1) {
return 0;
}
return p->desktop_names[desktop - 1];
}
const Window *NETRootInfo::virtualRoots( ) const {
return p->virtual_roots;
}
int NETRootInfo::virtualRootsCount() const {
return p->virtual_roots_count;
}
NET::Orientation NETRootInfo::desktopLayoutOrientation() const {
return p->desktop_layout_orientation;
}
TQSize NETRootInfo::desktopLayoutColumnsRows() const {
return TQSize( p->desktop_layout_columns, p->desktop_layout_rows );
}
NET::DesktopLayoutCorner NETRootInfo::desktopLayoutCorner() const {
return p->desktop_layout_corner;
}
int NETRootInfo::numberOfDesktops() const {
return p->number_of_desktops == 0 ? 1 : p->number_of_desktops;
}
int NETRootInfo::currentDesktop() const {
return p->current_desktop == 0 ? 1 : p->current_desktop;
}
Window NETRootInfo::activeWindow() const {
return p->active;
}
// NETWinInfo stuffs
const int NETWinInfo::OnAllDesktops = NET::OnAllDesktops;
NETWinInfo::NETWinInfo(Display *display, Window window, Window rootWindow,
const unsigned long properties[], int properties_size,
Role role)
{
#ifdef NETWMDEBUG
fprintf(stderr, "NETWinInfo::NETWinInfo: constructing object with role '%s'\n",
(role == WindowManager) ? "WindowManager" : "Client");
#endif
p = new NETWinInfoPrivate;
p->ref = 1;
p->display = display;
p->window = window;
p->root = rootWindow;
p->mapping_state = Withdrawn;
p->mapping_state_dirty = True;
p->state = 0;
p->types[ 0 ] = Unknown;
p->name = (char *) 0;
p->visible_name = (char *) 0;
p->icon_name = (char *) 0;
p->visible_icon_name = (char *) 0;
p->desktop = p->pid = p->handled_icons = 0;
p->user_time = -1U;
p->startup_id = NULL;
p->transient_for = None;
p->window_group = None;
p->allowed_actions = 0;
p->has_net_support = false;
p->class_class = (char*) 0;
p->class_name = (char*) 0;
p->role = (char*) 0;
p->client_machine = (char*) 0;
// p->strut.left = p->strut.right = p->strut.top = p->strut.bottom = 0;
// p->frame_strut.left = p->frame_strut.right = p->frame_strut.top =
// p->frame_strut.bottom = 0;
p->kde_system_tray_win_for = 0;
for( int i = 0;
i < PROPERTIES_SIZE;
++i )
p->properties[ i ] = 0;
if( properties_size > PROPERTIES_SIZE )
properties_size = PROPERTIES_SIZE;
for( int i = 0;
i < properties_size;
++i )
p->properties[ i ] = properties[ i ];
p->icon_count = 0;
this->role = role;
if (! netwm_atoms_created) create_atoms(p->display);
update(p->properties);
}
NETWinInfo::NETWinInfo(Display *display, Window window, Window rootWindow,
unsigned long properties, Role role)
{
#ifdef NETWMDEBUG
fprintf(stderr, "NETWinInfo::NETWinInfo: constructing object with role '%s'\n",
(role == WindowManager) ? "WindowManager" : "Client");
#endif
p = new NETWinInfoPrivate;
p->ref = 1;
p->display = display;
p->window = window;
p->root = rootWindow;
p->mapping_state = Withdrawn;
p->mapping_state_dirty = True;
p->state = 0;
p->types[ 0 ] = Unknown;
p->name = (char *) 0;
p->visible_name = (char *) 0;
p->icon_name = (char *) 0;
p->visible_icon_name = (char *) 0;
p->desktop = p->pid = p->handled_icons = 0;
p->user_time = -1U;
p->startup_id = NULL;
p->transient_for = None;
p->window_group = None;
p->allowed_actions = 0;
p->has_net_support = false;
p->class_class = (char*) 0;
p->class_name = (char*) 0;
p->role = (char*) 0;
p->client_machine = (char*) 0;
// p->strut.left = p->strut.right = p->strut.top = p->strut.bottom = 0;
// p->frame_strut.left = p->frame_strut.right = p->frame_strut.top =
// p->frame_strut.bottom = 0;
p->kde_system_tray_win_for = 0;
for( int i = 0;
i < PROPERTIES_SIZE;
++i )
p->properties[ i ] = 0;
p->properties[ PROTOCOLS ] = properties;
p->icon_count = 0;
this->role = role;
if (! netwm_atoms_created) create_atoms(p->display);
update(p->properties);
}
NETWinInfo::NETWinInfo(const NETWinInfo &wininfo) {
p = wininfo.p;
p->ref++;
}
NETWinInfo::~NETWinInfo() {
refdec_nwi(p);
if (! p->ref) delete p;
}
// assignment operator
const NETWinInfo &NETWinInfo::operator=(const NETWinInfo &wininfo) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETWinInfo::operator=()\n");
#endif
if (p != wininfo.p) {
refdec_nwi(p);
if (! p->ref) delete p;
}
p = wininfo.p;
role = wininfo.role;
p->ref++;
return *this;
}
void NETWinInfo::setIcon(NETIcon icon, Bool replace) {
setIconInternal( p->icons, p->icon_count, net_wm_icon, icon, replace );
}
void NETWinInfo::setIconInternal(NETRArray<NETIcon>& icons, int& icon_count, Atom property, NETIcon icon, Bool replace) {
if (role != Client) return;
int proplen, i, sz, j;
if (replace) {
for (i = 0; i < icons.size(); i++) {
delete [] icons[i].data;
icons[i].data = 0;
icons[i].size.width = 0;
icons[i].size.height = 0;
}
icon_count = 0;
}
// assign icon
icons[icon_count] = icon;
icon_count++;
// do a deep copy, we want to own the data
NETIcon &ni = icons[icon_count - 1];
sz = ni.size.width * ni.size.height;
CARD32 *d = new CARD32[sz];
ni.data = (unsigned char *) d;
memcpy(d, icon.data, sz * sizeof(CARD32));
// compute property length
for (i = 0, proplen = 0; i < icon_count; i++) {
proplen += 2 + (icons[i].size.width *
icons[i].size.height);
}
CARD32 *d32;
long *prop = new long[proplen], *pprop = prop;
for (i = 0; i < icon_count; i++) {
// copy size into property
*pprop++ = icons[i].size.width;
*pprop++ = icons[i].size.height;
// copy data into property
sz = (icons[i].size.width * icons[i].size.height);
d32 = (CARD32 *) icons[i].data;
for (j = 0; j < sz; j++) *pprop++ = *d32++;
}
XChangeProperty(p->display, p->window, property, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) prop, proplen);
delete [] prop;
}
void NETWinInfo::setIconGeometry(NETRect geometry) {
if (role != Client) return;
p->icon_geom = geometry;
if( geometry.size.width == 0 ) // empty
XDeleteProperty(p->display, p->window, net_wm_icon_geometry);
else {
long data[4];
data[0] = geometry.pos.x;
data[1] = geometry.pos.y;
data[2] = geometry.size.width;
data[3] = geometry.size.height;
XChangeProperty(p->display, p->window, net_wm_icon_geometry, XA_CARDINAL,
32, PropModeReplace, (unsigned char *) data, 4);
}
}
void NETWinInfo::setExtendedStrut(const NETExtendedStrut& extended_strut ) {
if (role != Client) return;
p->extended_strut = extended_strut;
long data[12];
data[0] = extended_strut.left_width;
data[1] = extended_strut.right_width;
data[2] = extended_strut.top_width;
data[3] = extended_strut.bottom_width;
data[4] = extended_strut.left_start;
data[5] = extended_strut.left_end;
data[6] = extended_strut.right_start;
data[7] = extended_strut.right_end;
data[8] = extended_strut.top_start;
data[9] = extended_strut.top_end;
data[10] = extended_strut.bottom_start;
data[11] = extended_strut.bottom_end;
XChangeProperty(p->display, p->window, net_wm_extended_strut, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) data, 12);
}
void NETWinInfo::setStrut(NETStrut strut) {
if (role != Client) return;
p->strut = strut;
long data[4];
data[0] = strut.left;
data[1] = strut.right;
data[2] = strut.top;
data[3] = strut.bottom;
XChangeProperty(p->display, p->window, net_wm_strut, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) data, 4);
}
void NETWinInfo::setState(unsigned long state, unsigned long mask) {
if (p->mapping_state_dirty)
updateWMState();
// setState() needs to know the current state, so read it even if not requested
if( ( p->properties[ PROTOCOLS ] & WMState ) == 0 ) {
p->properties[ PROTOCOLS ] |= WMState;
unsigned long props[ PROPERTIES_SIZE ] = { WMState, 0 };
assert( PROPERTIES_SIZE == 2 ); // add elements above
update( props );
p->properties[ PROTOCOLS ] &= ~WMState;
}
if (role == Client && p->mapping_state != Withdrawn) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETWinInfo::setState (0x%lx, 0x%lx) (Client)\n",
state, mask);
#endif // NETWMDEBUG
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.message_type = net_wm_state;
e.xclient.display = p->display;
e.xclient.window = p->window;
e.xclient.format = 32;
e.xclient.data.l[3] = 0l;
e.xclient.data.l[4] = 0l;
if ((mask & Modal) && ((p->state & Modal) != (state & Modal))) {
e.xclient.data.l[0] = (state & Modal) ? 1 : 0;
e.xclient.data.l[1] = net_wm_state_modal;
e.xclient.data.l[2] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
if ((mask & Sticky) && ((p->state & Sticky) != (state & Sticky))) {
e.xclient.data.l[0] = (state & Sticky) ? 1 : 0;
e.xclient.data.l[1] = net_wm_state_sticky;
e.xclient.data.l[2] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
if ((mask & Max) && (( (p->state&mask) & Max) != (state & Max))) {
unsigned long wishstate = (p->state & ~mask) | (state & mask);
if ( ( (wishstate & MaxHoriz) != (p->state & MaxHoriz) )
&& ( (wishstate & MaxVert) != (p->state & MaxVert) ) ) {
if ( (wishstate & Max) == Max ) {
e.xclient.data.l[0] = 1;
e.xclient.data.l[1] = net_wm_state_max_horiz;
e.xclient.data.l[2] = net_wm_state_max_vert;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
} else if ( (wishstate & Max) == 0 ) {
e.xclient.data.l[0] = 0;
e.xclient.data.l[1] = net_wm_state_max_horiz;
e.xclient.data.l[2] = net_wm_state_max_vert;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
} else {
e.xclient.data.l[0] = ( wishstate & MaxHoriz ) ? 1 : 0;
e.xclient.data.l[1] = net_wm_state_max_horiz;
e.xclient.data.l[2] = 0;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
e.xclient.data.l[0] = ( wishstate & MaxVert ) ? 1 : 0;
e.xclient.data.l[1] = net_wm_state_max_vert;
e.xclient.data.l[2] = 0;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
} else if ( (wishstate & MaxVert) != (p->state & MaxVert) ) {
e.xclient.data.l[0] = ( wishstate & MaxVert ) ? 1 : 0;
e.xclient.data.l[1] = net_wm_state_max_vert;
e.xclient.data.l[2] = 0;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
} else if ( (wishstate & MaxHoriz) != (p->state & MaxHoriz) ) {
e.xclient.data.l[0] = ( wishstate & MaxHoriz ) ? 1 : 0;
e.xclient.data.l[1] = net_wm_state_max_horiz;
e.xclient.data.l[2] = 0;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
}
if ((mask & Shaded) && ((p->state & Shaded) != (state & Shaded))) {
e.xclient.data.l[0] = (state & Shaded) ? 1 : 0;
e.xclient.data.l[1] = net_wm_state_shaded;
e.xclient.data.l[2] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
if ((mask & SkipTaskbar) &&
((p->state & SkipTaskbar) != (state & SkipTaskbar))) {
e.xclient.data.l[0] = (state & SkipTaskbar) ? 1 : 0;
e.xclient.data.l[1] = net_wm_state_skip_taskbar;
e.xclient.data.l[2] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
if ((mask & SkipPager) &&
((p->state & SkipPager) != (state & SkipPager))) {
e.xclient.data.l[0] = (state & SkipPager) ? 1 : 0;
e.xclient.data.l[1] = net_wm_state_skip_pager;
e.xclient.data.l[2] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
if ((mask & Hidden) &&
((p->state & Hidden) != (state & Hidden))) {
e.xclient.data.l[0] = (state & Hidden) ? 1 : 0;
e.xclient.data.l[1] = net_wm_state_hidden;
e.xclient.data.l[2] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
if ((mask & FullScreen) &&
((p->state & FullScreen) != (state & FullScreen))) {
e.xclient.data.l[0] = (state & FullScreen) ? 1 : 0;
e.xclient.data.l[1] = net_wm_state_fullscreen;
e.xclient.data.l[2] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
if ((mask & KeepAbove) &&
((p->state & KeepAbove) != (state & KeepAbove))) {
e.xclient.data.l[0] = (state & KeepAbove) ? 1 : 0;
e.xclient.data.l[1] = net_wm_state_above;
e.xclient.data.l[2] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
if ((mask & KeepBelow) &&
((p->state & KeepBelow) != (state & KeepBelow))) {
e.xclient.data.l[0] = (state & KeepBelow) ? 1 : 0;
e.xclient.data.l[1] = net_wm_state_below;
e.xclient.data.l[2] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
if ((mask & StaysOnTop) && ((p->state & StaysOnTop) != (state & StaysOnTop))) {
e.xclient.data.l[0] = (state & StaysOnTop) ? 1 : 0;
e.xclient.data.l[1] = net_wm_state_stays_on_top;
e.xclient.data.l[2] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
if ((mask & DemandsAttention) &&
((p->state & DemandsAttention) != (state & DemandsAttention))) {
e.xclient.data.l[0] = (state & DemandsAttention) ? 1 : 0;
e.xclient.data.l[1] = net_wm_state_demands_attention;
e.xclient.data.l[2] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
}
} else {
p->state &= ~mask;
p->state |= state;
long data[50];
int count = 0;
// hints
if (p->state & Modal) data[count++] = net_wm_state_modal;
if (p->state & MaxVert) data[count++] = net_wm_state_max_vert;
if (p->state & MaxHoriz) data[count++] = net_wm_state_max_horiz;
if (p->state & Shaded) data[count++] = net_wm_state_shaded;
if (p->state & Hidden) data[count++] = net_wm_state_hidden;
if (p->state & FullScreen) data[count++] = net_wm_state_fullscreen;
if (p->state & DemandsAttention) data[count++] = net_wm_state_demands_attention;
// policy
if (p->state & KeepAbove) data[count++] = net_wm_state_above;
if (p->state & KeepBelow) data[count++] = net_wm_state_below;
if (p->state & StaysOnTop) data[count++] = net_wm_state_stays_on_top;
if (p->state & Sticky) data[count++] = net_wm_state_sticky;
if (p->state & SkipTaskbar) data[count++] = net_wm_state_skip_taskbar;
if (p->state & SkipPager) data[count++] = net_wm_state_skip_pager;
#ifdef NETWMDEBUG
fprintf(stderr, "NETWinInfo::setState: setting state property (%d)\n", count);
for (int i = 0; i < count; i++) {
char* data_ret = XGetAtomName(p->display, (Atom) data[i]);
fprintf(stderr, "NETWinInfo::setState: state %ld '%s'\n",
data[i], data_ret);
if ( data_ret )
XFree( data_ret );
}
#endif
XChangeProperty(p->display, p->window, net_wm_state, XA_ATOM, 32,
PropModeReplace, (unsigned char *) data, count);
}
}
void NETWinInfo::setWindowType(WindowType type) {
if (role != Client) return;
int len;
long data[2];
switch (type) {
case Override:
// spec extension: override window type. we must comply with the spec
// and provide a fall back (normal seems best)
data[0] = kde_net_wm_window_type_override;
data[1] = net_wm_window_type_normal;
len = 2;
break;
case Dialog:
data[0] = net_wm_window_type_dialog;
data[1] = None;
len = 1;
break;
case Menu:
data[0] = net_wm_window_type_menu;
data[1] = None;
len = 1;
break;
case TopMenu:
// spec extension: override window type. we must comply with the spec
// and provide a fall back (dock seems best)
data[0] = kde_net_wm_window_type_topmenu;
data[1] = net_wm_window_type_dock;
len = 2;
break;
case Tool:
data[0] = net_wm_window_type_toolbar;
data[1] = None;
len = 1;
break;
case Dock:
data[0] = net_wm_window_type_dock;
data[1] = None;
len = 1;
break;
case Desktop:
data[0] = net_wm_window_type_desktop;
data[1] = None;
len = 1;
break;
case Utility:
data[0] = net_wm_window_type_utility;
data[1] = net_wm_window_type_dialog; // fallback for old netwm version
len = 2;
break;
case Splash:
data[0] = net_wm_window_type_splash;
data[1] = net_wm_window_type_dock; // fallback (dock seems best)
len = 2;
break;
case DropdownMenu:
data[0] = net_wm_window_type_dropdown_menu;
data[1] = None;
len = 1;
break;
case PopupMenu:
data[0] = net_wm_window_type_popup_menu;
data[1] = None;
len = 1;
break;
case Tooltip:
data[0] = net_wm_window_type_tooltip;
data[1] = None;
len = 1;
break;
case Notification:
data[0] = net_wm_window_type_notification;
data[1] = None;
len = 1;
break;
case ComboBox:
data[0] = net_wm_window_type_combobox;
data[1] = None;
len = 1;
break;
case DNDIcon:
data[0] = net_wm_window_type_dnd;
data[1] = None;
len = 1;
break;
default:
case Normal:
data[0] = net_wm_window_type_normal;
data[1] = None;
len = 1;
break;
}
XChangeProperty(p->display, p->window, net_wm_window_type, XA_ATOM, 32,
PropModeReplace, (unsigned char *) &data, len);
}
void NETWinInfo::setName(const char *name) {
if (role != Client) return;
delete [] p->name;
p->name = nstrdup(name);
if( p->name[ 0 ] != '\0' )
XChangeProperty(p->display, p->window, net_wm_name, UTF8_STRING, 8,
PropModeReplace, (unsigned char *) p->name,
strlen(p->name));
else
XDeleteProperty(p->display, p->window, net_wm_name);
}
void NETWinInfo::setVisibleName(const char *visibleName) {
if (role != WindowManager) return;
delete [] p->visible_name;
p->visible_name = nstrdup(visibleName);
if( p->visible_name[ 0 ] != '\0' )
XChangeProperty(p->display, p->window, net_wm_visible_name, UTF8_STRING, 8,
PropModeReplace, (unsigned char *) p->visible_name,
strlen(p->visible_name));
else
XDeleteProperty(p->display, p->window, net_wm_visible_name);
}
void NETWinInfo::setIconName(const char *iconName) {
if (role != Client) return;
delete [] p->icon_name;
p->icon_name = nstrdup(iconName);
if( p->icon_name[ 0 ] != '\0' )
XChangeProperty(p->display, p->window, net_wm_icon_name, UTF8_STRING, 8,
PropModeReplace, (unsigned char *) p->icon_name,
strlen(p->icon_name));
else
XDeleteProperty(p->display, p->window, net_wm_icon_name);
}
void NETWinInfo::setVisibleIconName(const char *visibleIconName) {
if (role != WindowManager) return;
delete [] p->visible_icon_name;
p->visible_icon_name = nstrdup(visibleIconName);
if( p->visible_icon_name[ 0 ] != '\0' )
XChangeProperty(p->display, p->window, net_wm_visible_icon_name, UTF8_STRING, 8,
PropModeReplace, (unsigned char *) p->visible_icon_name,
strlen(p->visible_icon_name));
else
XDeleteProperty(p->display, p->window, net_wm_visible_icon_name);
}
void NETWinInfo::setDesktop(int desktop) {
if (p->mapping_state_dirty)
updateWMState();
if (role == Client && p->mapping_state != Withdrawn) {
// we only send a ClientMessage if we are 1) a client and 2) managed
if ( desktop == 0 )
return; // we can't do that while being managed
XEvent e;
e.xclient.type = ClientMessage;
e.xclient.message_type = net_wm_desktop;
e.xclient.display = p->display;
e.xclient.window = p->window;
e.xclient.format = 32;
e.xclient.data.l[0] = desktop == OnAllDesktops ? OnAllDesktops : desktop - 1;
e.xclient.data.l[1] = 0l;
e.xclient.data.l[2] = 0l;
e.xclient.data.l[3] = 0l;
e.xclient.data.l[4] = 0l;
XSendEvent(p->display, p->root, False, netwm_sendevent_mask, &e);
} else {
// otherwise we just set or remove the property directly
p->desktop = desktop;
long d = desktop;
if ( d != OnAllDesktops ) {
if ( d == 0 ) {
XDeleteProperty( p->display, p->window, net_wm_desktop );
return;
}
d -= 1;
}
XChangeProperty(p->display, p->window, net_wm_desktop, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) &d, 1);
}
}
void NETWinInfo::setPid(int pid) {
if (role != Client) return;
p->pid = pid;
long d = pid;
XChangeProperty(p->display, p->window, net_wm_pid, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) &d, 1);
}
void NETWinInfo::setHandledIcons(Bool handled) {
if (role != Client) return;
p->handled_icons = handled;
long d = handled;
XChangeProperty(p->display, p->window, net_wm_handled_icons, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) &d, 1);
}
void NETWinInfo::setStartupId(const char* id) {
if (role != Client) return;
delete[] p->startup_id;
p->startup_id = nstrdup(id);
XChangeProperty(p->display, p->window, net_startup_id, UTF8_STRING, 8,
PropModeReplace, reinterpret_cast< unsigned char* >( p->startup_id ),
strlen( p->startup_id ));
}
void NETWinInfo::setAllowedActions( unsigned long actions ) {
if( role != WindowManager )
return;
long data[50];
int count = 0;
p->allowed_actions = actions;
if (p->allowed_actions & ActionMove) data[count++] = net_wm_action_move;
if (p->allowed_actions & ActionResize) data[count++] = net_wm_action_resize;
if (p->allowed_actions & ActionMinimize) data[count++] = net_wm_action_minimize;
if (p->allowed_actions & ActionShade) data[count++] = net_wm_action_shade;
if (p->allowed_actions & ActionStick) data[count++] = net_wm_action_stick;
if (p->allowed_actions & ActionMaxVert) data[count++] = net_wm_action_max_vert;
if (p->allowed_actions & ActionMaxHoriz) data[count++] = net_wm_action_max_horiz;
if (p->allowed_actions & ActionFullScreen) data[count++] = net_wm_action_fullscreen;
if (p->allowed_actions & ActionChangeDesktop) data[count++] = net_wm_action_change_desk;
if (p->allowed_actions & ActionClose) data[count++] = net_wm_action_close;
#ifdef NETWMDEBUG
fprintf(stderr, "NETWinInfo::setAllowedActions: setting property (%d)\n", count);
for (int i = 0; i < count; i++) {
char* data_ret = XGetAtomName(p->display, (Atom) data[i]);
fprintf(stderr, "NETWinInfo::setAllowedActions: action %ld '%s'\n",
data[i], data_ret);
if ( data_ret )
XFree(data_ret);
}
#endif
XChangeProperty(p->display, p->window, net_wm_allowed_actions, XA_ATOM, 32,
PropModeReplace, (unsigned char *) data, count);
}
void NETWinInfo::setKDESystemTrayWinFor(Window window) {
if (role != Client) return;
p->kde_system_tray_win_for = window;
XChangeProperty(p->display, p->window, kde_net_wm_system_tray_window_for,
XA_WINDOW, 32, PropModeReplace,
(unsigned char *) &(p->kde_system_tray_win_for), 1);
}
void NETWinInfo::setKDEFrameStrut(NETStrut strut) {
setFrameExtents( strut );
}
void NETWinInfo::setFrameExtents(NETStrut strut) {
if (role != WindowManager) return;
p->frame_strut = strut;
long d[4];
d[0] = strut.left;
d[1] = strut.right;
d[2] = strut.top;
d[3] = strut.bottom;
XChangeProperty(p->display, p->window, net_frame_extents, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) d, 4);
XChangeProperty(p->display, p->window, kde_net_wm_frame_strut, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) d, 4);
}
void NETWinInfo::kdeGeometry(NETRect& frame, NETRect& window) {
if (p->win_geom.size.width == 0 || p->win_geom.size.height == 0) {
Window unused;
int x, y;
unsigned int w, h, junk;
XGetGeometry(p->display, p->window, &unused, &x, &y, &w, &h, &junk, &junk);
XTranslateCoordinates(p->display, p->window, p->root, 0, 0, &x, &y, &unused
);
p->win_geom.pos.x = x;
p->win_geom.pos.y = y;
p->win_geom.size.width = w;
p->win_geom.size.height = h;
}
// TODO try to work also without _KDE_NET_WM_FRAME_STRUT
window = p->win_geom;
frame.pos.x = window.pos.x - p->frame_strut.left;
frame.pos.y = window.pos.y - p->frame_strut.top;
frame.size.width = window.size.width + p->frame_strut.left + p->frame_strut.right;
frame.size.height = window.size.height + p->frame_strut.top + p->frame_strut.bottom;
}
NETIcon NETWinInfo::icon(int width, int height) const {
return iconInternal( p->icons, p->icon_count, width, height );
}
NETIcon NETWinInfo::iconInternal(NETRArray<NETIcon>& icons, int icon_count, int width, int height) const {
NETIcon result;
if ( !icon_count ) {
result.size.width = 0;
result.size.height = 0;
result.data = 0;
return result;
}
// find the largest icon
result = icons[0];
for (int i = 1; i < icons.size(); i++) {
if( icons[i].size.width >= result.size.width &&
icons[i].size.height >= result.size.height )
result = icons[i];
}
// return the largest icon if w and h are -1
if (width == -1 && height == -1) return result;
// find the icon that's closest in size to w x h...
for (int i = 0; i < icons.size(); i++) {
if ((icons[i].size.width >= width &&
icons[i].size.width < result.size.width) &&
(icons[i].size.height >= height &&
icons[i].size.height < result.size.height))
result = icons[i];
}
return result;
}
void NETWinInfo::setUserTime( Time time ) {
if (role != Client) return;
p->user_time = time;
long d = time;
XChangeProperty(p->display, p->window, net_wm_user_time, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) &d, 1);
}
unsigned long NETWinInfo::event(XEvent *ev )
{
unsigned long props[ 1 ];
event( ev, props, 1 );
return props[ 0 ];
}
void NETWinInfo::event(XEvent *event, unsigned long* properties, int properties_size ) {
unsigned long props[ PROPERTIES_SIZE ] = { 0, 0 };
assert( PROPERTIES_SIZE == 2 ); // add elements above
unsigned long& dirty = props[ PROTOCOLS ];
unsigned long& dirty2 = props[ PROTOCOLS2 ];
bool do_update = false;
if (role == WindowManager && event->type == ClientMessage &&
event->xclient.format == 32) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETWinInfo::event: handling ClientMessage event\n");
#endif // NETWMDEBUG
if (event->xclient.message_type == net_wm_state) {
dirty = WMState;
// we need to generate a change mask
#ifdef NETWMDEBUG
fprintf(stderr,
"NETWinInfo::event: state client message, getting new state/mask\n");
#endif
int i;
long state = 0, mask = 0;
for (i = 1; i < 3; i++) {
#ifdef NETWMDEBUG
char* debug_txt = XGetAtomName(p->display, (Atom) event->xclient.data.l[i]);
fprintf(stderr, "NETWinInfo::event: message %ld '%s'\n",
event->xclient.data.l[i], debug_txt );
if ( debug_txt )
XFree( debug_txt );
#endif
if ((Atom) event->xclient.data.l[i] == net_wm_state_modal)
mask |= Modal;
else if ((Atom) event->xclient.data.l[i] == net_wm_state_sticky)
mask |= Sticky;
else if ((Atom) event->xclient.data.l[i] == net_wm_state_max_vert)
mask |= MaxVert;
else if ((Atom) event->xclient.data.l[i] == net_wm_state_max_horiz)
mask |= MaxHoriz;
else if ((Atom) event->xclient.data.l[i] == net_wm_state_shaded)
mask |= Shaded;
else if ((Atom) event->xclient.data.l[i] == net_wm_state_skip_taskbar)
mask |= SkipTaskbar;
else if ((Atom) event->xclient.data.l[i] == net_wm_state_skip_pager)
mask |= SkipPager;
else if ((Atom) event->xclient.data.l[i] == net_wm_state_hidden)
mask |= Hidden;
else if ((Atom) event->xclient.data.l[i] == net_wm_state_fullscreen)
mask |= FullScreen;
else if ((Atom) event->xclient.data.l[i] == net_wm_state_above)
mask |= KeepAbove;
else if ((Atom) event->xclient.data.l[i] == net_wm_state_below)
mask |= KeepBelow;
else if ((Atom) event->xclient.data.l[i] == net_wm_state_demands_attention)
mask |= DemandsAttention;
else if ((Atom) event->xclient.data.l[i] == net_wm_state_stays_on_top)
mask |= StaysOnTop;
}
// when removing, we just leave newstate == 0
switch (event->xclient.data.l[0]) {
case 1: // set
// to set... the change state should be the same as the mask
state = mask;
break;
case 2: // toggle
// to toggle, we need to xor the current state with the new state
state = (p->state & mask) ^ mask;
break;
default:
// to clear state, the new state should stay zero
;
}
#ifdef NETWMDEBUG
fprintf(stderr, "NETWinInfo::event: calling changeState(%lx, %lx)\n",
state, mask);
#endif
changeState(state, mask);
} else if (event->xclient.message_type == net_wm_desktop) {
dirty = WMDesktop;
if( event->xclient.data.l[0] == OnAllDesktops )
changeDesktop( OnAllDesktops );
else
changeDesktop(event->xclient.data.l[0] + 1);
}
}
if (event->type == PropertyNotify) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETWinInfo::event: handling PropertyNotify event\n");
#endif
XEvent pe = *event;
Bool done = False;
Bool compaction = False;
while (! done) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETWinInfo::event: loop fire\n");
#endif
if (pe.xproperty.atom == net_wm_name)
dirty |= WMName;
else if (pe.xproperty.atom == net_wm_visible_name)
dirty |= WMVisibleName;
else if (pe.xproperty.atom == net_wm_desktop)
dirty |= WMDesktop;
else if (pe.xproperty.atom == net_wm_window_type)
dirty |=WMWindowType;
else if (pe.xproperty.atom == net_wm_state)
dirty |= WMState;
else if (pe.xproperty.atom == net_wm_strut)
dirty |= WMStrut;
else if (pe.xproperty.atom == net_wm_extended_strut)
dirty2 |= WM2ExtendedStrut;
else if (pe.xproperty.atom == net_wm_icon_geometry)
dirty |= WMIconGeometry;
else if (pe.xproperty.atom == net_wm_icon)
dirty |= WMIcon;
else if (pe.xproperty.atom == net_wm_pid)
dirty |= WMPid;
else if (pe.xproperty.atom == net_wm_handled_icons)
dirty |= WMHandledIcons;
else if (pe.xproperty.atom == net_startup_id)
dirty2 |= WM2StartupId;
else if (pe.xproperty.atom == net_wm_allowed_actions)
dirty2 |= WM2AllowedActions;
else if (pe.xproperty.atom == kde_net_wm_system_tray_window_for)
dirty |= WMKDESystemTrayWinFor;
else if (pe.xproperty.atom == xa_wm_state)
dirty |= XAWMState;
else if (pe.xproperty.atom == net_frame_extents)
dirty |= WMFrameExtents;
else if (pe.xproperty.atom == kde_net_wm_frame_strut)
dirty |= WMKDEFrameStrut;
else if (pe.xproperty.atom == net_wm_icon_name)
dirty |= WMIconName;
else if (pe.xproperty.atom == net_wm_visible_icon_name)
dirty |= WMVisibleIconName;
else if (pe.xproperty.atom == net_wm_user_time)
dirty2 |= WM2UserTime;
else if (pe.xproperty.atom == XA_WM_HINTS)
dirty2 |= WM2GroupLeader;
else if (pe.xproperty.atom == XA_WM_TRANSIENT_FOR)
dirty2 |= WM2TransientFor;
else if (pe.xproperty.atom == XA_WM_CLASS)
dirty2 |= WM2WindowClass;
else if (pe.xproperty.atom == wm_window_role)
dirty2 |= WM2WindowRole;
else if (pe.xproperty.atom == XA_WM_CLIENT_MACHINE)
dirty2 |= WM2ClientMachine;
else {
#ifdef NETWMDEBUG
fprintf(stderr, "NETWinInfo::event: putting back event and breaking\n");
#endif
if ( compaction )
XPutBackEvent(p->display, &pe);
break;
}
if (XCheckTypedWindowEvent(p->display, p->window, PropertyNotify, &pe) )
compaction = True;
else
break;
}
do_update = true;
} else if (event->type == ConfigureNotify) {
#ifdef NETWMDEBUG
fprintf(stderr, "NETWinInfo::event: handling ConfigureNotify event\n");
#endif
dirty |= WMGeometry;
// update window geometry
p->win_geom.pos.x = event->xconfigure.x;
p->win_geom.pos.y = event->xconfigure.y;
p->win_geom.size.width = event->xconfigure.width;
p->win_geom.size.height = event->xconfigure.height;
}
if( do_update )
update( props );
if( properties_size > PROPERTIES_SIZE )
properties_size = PROPERTIES_SIZE;
for( int i = 0;
i < properties_size;
++i )
properties[ i ] = props[ i ];
}
void NETWinInfo::updateWMState() {
unsigned long props[ PROPERTIES_SIZE ] = { XAWMState, 0 };
assert( PROPERTIES_SIZE == 2 ); // add elements above
update( props );
}
void NETWinInfo::update(const unsigned long dirty_props[]) {
Atom type_ret;
int format_ret;
unsigned long nitems_ret, unused;
unsigned char *data_ret;
unsigned long props[ PROPERTIES_SIZE ];
for( int i = 0;
i < PROPERTIES_SIZE;
++i )
props[ i ] = dirty_props[ i ] & p->properties[ i ];
const unsigned long& dirty = props[ PROTOCOLS ];
const unsigned long& dirty2 = props[ PROTOCOLS2 ];
// we *always* want to update WM_STATE if set in dirty_props
if( dirty_props[ PROTOCOLS ] & XAWMState )
props[ PROTOCOLS ] |= XAWMState;
if (dirty & XAWMState) {
p->mapping_state = Withdrawn;
if (XGetWindowProperty(p->display, p->window, xa_wm_state, 0l, 1l,
False, xa_wm_state, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == xa_wm_state && format_ret == 32 &&
nitems_ret == 1) {
long *state = (long *) data_ret;
switch(*state) {
case IconicState:
p->mapping_state = Iconic;
break;
case NormalState:
p->mapping_state = Visible;
break;
case WithdrawnState:
default:
p->mapping_state = Withdrawn;
break;
}
p->mapping_state_dirty = False;
}
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & WMState) {
p->state = 0;
if (XGetWindowProperty(p->display, p->window, net_wm_state, 0l, 2048l,
False, XA_ATOM, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
// determine window state
#ifdef NETWMDEBUG
fprintf(stderr, "NETWinInfo::update: updating window state (%ld)\n",
nitems_ret);
#endif
long *states = (long *) data_ret;
unsigned long count;
for (count = 0; count < nitems_ret; count++) {
#ifdef NETWMDEBUG
char* data_ret = XGetAtomName(p->display, (Atom) states[count]);
fprintf(stderr,
"NETWinInfo::update: adding window state %ld '%s'\n",
states[count], data_ret );
if ( data_ret )
XFree( data_ret );
#endif
if ((Atom) states[count] == net_wm_state_modal)
p->state |= Modal;
else if ((Atom) states[count] == net_wm_state_sticky)
p->state |= Sticky;
else if ((Atom) states[count] == net_wm_state_max_vert)
p->state |= MaxVert;
else if ((Atom) states[count] == net_wm_state_max_horiz)
p->state |= MaxHoriz;
else if ((Atom) states[count] == net_wm_state_shaded)
p->state |= Shaded;
else if ((Atom) states[count] == net_wm_state_skip_taskbar)
p->state |= SkipTaskbar;
else if ((Atom) states[count] == net_wm_state_skip_pager)
p->state |= SkipPager;
else if ((Atom) states[count] == net_wm_state_hidden)
p->state |= Hidden;
else if ((Atom) states[count] == net_wm_state_fullscreen)
p->state |= FullScreen;
else if ((Atom) states[count] == net_wm_state_above)
p->state |= KeepAbove;
else if ((Atom) states[count] == net_wm_state_below)
p->state |= KeepBelow;
else if ((Atom) states[count] == net_wm_state_demands_attention)
p->state |= DemandsAttention;
else if ((Atom) states[count] == net_wm_state_stays_on_top)
p->state |= StaysOnTop;
}
}
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & WMDesktop) {
p->desktop = 0;
if (XGetWindowProperty(p->display, p->window, net_wm_desktop, 0l, 1l,
False, XA_CARDINAL, &type_ret,
&format_ret, &nitems_ret,
&unused, &data_ret)
== Success) {
if (type_ret == XA_CARDINAL && format_ret == 32 &&
nitems_ret == 1) {
p->desktop = *((long *) data_ret);
if ((signed) p->desktop != OnAllDesktops)
p->desktop++;
if ( p->desktop == 0 )
p->desktop = OnAllDesktops;
}
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & WMName) {
delete[] p->name;
p->name = NULL;
if (XGetWindowProperty(p->display, p->window, net_wm_name, 0l,
MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
&format_ret, &nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
p->name = nstrndup((const char *) data_ret, nitems_ret);
}
if( data_ret )
XFree(data_ret);
}
}
if (dirty & WMVisibleName) {
delete[] p->visible_name;
p->visible_name = NULL;
if (XGetWindowProperty(p->display, p->window, net_wm_visible_name, 0l,
MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
&format_ret, &nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
p->visible_name = nstrndup((const char *) data_ret, nitems_ret);
}
if( data_ret )
XFree(data_ret);
}
}
if (dirty & WMIconName) {
delete[] p->icon_name;
p->icon_name = NULL;
if (XGetWindowProperty(p->display, p->window, net_wm_icon_name, 0l,
MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
&format_ret, &nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
p->icon_name = nstrndup((const char *) data_ret, nitems_ret);
}
if( data_ret )
XFree(data_ret);
}
}
if (dirty & WMVisibleIconName)
{
delete[] p->visible_icon_name;
p->visible_icon_name = NULL;
if (XGetWindowProperty(p->display, p->window, net_wm_visible_icon_name, 0l,
MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
&format_ret, &nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
p->visible_icon_name = nstrndup((const char *) data_ret, nitems_ret);
}
if( data_ret )
XFree(data_ret);
}
}
if (dirty & WMWindowType) {
p->types.reset();
p->types[ 0 ] = Unknown;
p->has_net_support = false;
if (XGetWindowProperty(p->display, p->window, net_wm_window_type, 0l, 2048l,
False, XA_ATOM, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
// determine the window type
#ifdef NETWMDEBUG
fprintf(stderr, "NETWinInfo::update: getting window type (%ld)\n",
nitems_ret);
#endif
p->has_net_support = true;
unsigned long count = 0;
long *types = (long *) data_ret;
int pos = 0;
while (count < nitems_ret) {
// remember all window types we know
#ifdef NETWMDEBUG
char* debug_type = XGetAtomName(p->display, (Atom) types[count]);
fprintf(stderr,
"NETWinInfo::update: examining window type %ld %s\n",
types[count], debug_type );
if ( debug_type )
XFree( debug_type );
#endif
if ((Atom) types[count] == net_wm_window_type_normal)
p->types[ pos++ ] = Normal;
else if ((Atom) types[count] == net_wm_window_type_desktop)
p->types[ pos++ ] = Desktop;
else if ((Atom) types[count] == net_wm_window_type_dock)
p->types[ pos++ ] = Dock;
else if ((Atom) types[count] == net_wm_window_type_toolbar)
p->types[ pos++ ] = Tool;
else if ((Atom) types[count] == net_wm_window_type_menu)
p->types[ pos++ ] = Menu;
else if ((Atom) types[count] == net_wm_window_type_dialog)
p->types[ pos++ ] = Dialog;
else if ((Atom) types[count] == net_wm_window_type_utility)
p->types[ pos++ ] = Utility;
else if ((Atom) types[count] == net_wm_window_type_splash)
p->types[ pos++ ] = Splash;
else if ((Atom) types[count] == net_wm_window_type_dropdown_menu)
p->types[ pos++ ] = DropdownMenu;
else if ((Atom) types[count] == net_wm_window_type_popup_menu)
p->types[ pos++ ] = PopupMenu;
else if ((Atom) types[count] == net_wm_window_type_tooltip)
p->types[ pos++ ] = Tooltip;
else if ((Atom) types[count] == net_wm_window_type_notification)
p->types[ pos++ ] = Notification;
else if ((Atom) types[count] == net_wm_window_type_combobox)
p->types[ pos++ ] = ComboBox;
else if ((Atom) types[count] == net_wm_window_type_dnd)
p->types[ pos++ ] = DNDIcon;
else if ((Atom) types[count] == kde_net_wm_window_type_override)
p->types[ pos++ ] = Override;
else if ((Atom) types[count] == kde_net_wm_window_type_topmenu)
p->types[ pos++ ] = TopMenu;
count++;
}
}
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & WMStrut) {
p->strut = NETStrut();
if (XGetWindowProperty(p->display, p->window, net_wm_strut, 0l, 4l,
False, XA_CARDINAL, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_CARDINAL && format_ret == 32 &&
nitems_ret == 4) {
long *d = (long *) data_ret;
p->strut.left = d[0];
p->strut.right = d[1];
p->strut.top = d[2];
p->strut.bottom = d[3];
}
if ( data_ret )
XFree(data_ret);
}
}
if (dirty2 & WM2ExtendedStrut) {
p->extended_strut = NETExtendedStrut();
if (XGetWindowProperty(p->display, p->window, net_wm_extended_strut, 0l, 12l,
False, XA_CARDINAL, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_CARDINAL && format_ret == 32 &&
nitems_ret == 12) {
long *d = (long *) data_ret;
p->extended_strut.left_width = d[0];
p->extended_strut.right_width = d[1];
p->extended_strut.top_width = d[2];
p->extended_strut.bottom_width = d[3];
p->extended_strut.left_start = d[4];
p->extended_strut.left_end = d[5];
p->extended_strut.right_start = d[6];
p->extended_strut.right_end = d[7];
p->extended_strut.top_start = d[8];
p->extended_strut.top_end = d[9];
p->extended_strut.bottom_start = d[10];
p->extended_strut.bottom_end = d[11];
}
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & WMIconGeometry) {
p->icon_geom = NETRect();
if (XGetWindowProperty(p->display, p->window, net_wm_icon_geometry, 0l, 4l,
False, XA_CARDINAL, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_CARDINAL && format_ret == 32 &&
nitems_ret == 4) {
long *d = (long *) data_ret;
p->icon_geom.pos.x = d[0];
p->icon_geom.pos.y = d[1];
p->icon_geom.size.width = d[2];
p->icon_geom.size.height = d[3];
}
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & WMIcon) {
readIcon(p->display,p->window,net_wm_icon,p->icons,p->icon_count);
}
if (dirty & WMKDESystemTrayWinFor) {
p->kde_system_tray_win_for = 0;
if (XGetWindowProperty(p->display, p->window, kde_net_wm_system_tray_window_for,
0l, 1l, False, XA_WINDOW, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_WINDOW && format_ret == 32 &&
nitems_ret == 1) {
p->kde_system_tray_win_for = *((Window *) data_ret);
if ( p->kde_system_tray_win_for == 0 )
p->kde_system_tray_win_for = p->root;
}
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & WMFrameExtents) {
p->frame_strut = NETStrut();
bool ok = false;
if (XGetWindowProperty(p->display, p->window, net_frame_extents,
0l, 4l, False, XA_CARDINAL, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret) == Success) {
if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 4) {
ok = true;
long *d = (long *) data_ret;
p->frame_strut.left = d[0];
p->frame_strut.right = d[1];
p->frame_strut.top = d[2];
p->frame_strut.bottom = d[3];
}
if ( data_ret )
XFree(data_ret);
}
if (!ok && XGetWindowProperty(p->display, p->window, kde_net_wm_frame_strut,
0l, 4l, False, XA_CARDINAL, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret) == Success) {
if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 4) {
ok = true;
long *d = (long *) data_ret;
p->frame_strut.left = d[0];
p->frame_strut.right = d[1];
p->frame_strut.top = d[2];
p->frame_strut.bottom = d[3];
}
if ( data_ret )
XFree(data_ret);
}
}
if (dirty & WMPid) {
p->pid = 0;
if (XGetWindowProperty(p->display, p->window, net_wm_pid, 0l, 1l,
False, XA_CARDINAL, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret) == Success) {
if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) {
p->pid = *((long *) data_ret);
}
if ( data_ret )
XFree(data_ret);
}
}
if (dirty2 & WM2StartupId)
{
delete[] p->startup_id;
p->startup_id = NULL;
if (XGetWindowProperty(p->display, p->window, net_startup_id, 0l,
MAX_PROP_SIZE, False, UTF8_STRING, &type_ret,
&format_ret, &nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == UTF8_STRING && format_ret == 8 && nitems_ret > 0) {
p->startup_id = nstrndup((const char *) data_ret, nitems_ret);
}
if( data_ret )
XFree(data_ret);
}
}
if( dirty2 & WM2AllowedActions ) {
p->allowed_actions = 0;
if (XGetWindowProperty(p->display, p->window, net_wm_allowed_actions, 0l, 2048l,
False, XA_ATOM, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_ATOM && format_ret == 32 && nitems_ret > 0) {
// determine actions
#ifdef NETWMDEBUG
fprintf(stderr, "NETWinInfo::update: updating allowed actions (%ld)\n",
nitems_ret);
#endif
long *actions = (long *) data_ret;
unsigned long count;
for (count = 0; count < nitems_ret; count++) {
#ifdef NETWMDEBUG
fprintf(stderr,
"NETWinInfo::update: adding allowed action %ld '%s'\n",
actions[count],
XGetAtomName(p->display, (Atom) actions[count]));
#endif
if ((Atom) actions[count] == net_wm_action_move)
p->allowed_actions |= ActionMove;
if ((Atom) actions[count] == net_wm_action_resize)
p->allowed_actions |= ActionResize;
if ((Atom) actions[count] == net_wm_action_minimize)
p->allowed_actions |= ActionMinimize;
if ((Atom) actions[count] == net_wm_action_shade)
p->allowed_actions |= ActionShade;
if ((Atom) actions[count] == net_wm_action_stick)
p->allowed_actions |= ActionStick;
if ((Atom) actions[count] == net_wm_action_max_vert)
p->allowed_actions |= ActionMaxVert;
if ((Atom) actions[count] == net_wm_action_max_horiz)
p->allowed_actions |= ActionMaxHoriz;
if ((Atom) actions[count] == net_wm_action_fullscreen)
p->allowed_actions |= ActionFullScreen;
if ((Atom) actions[count] == net_wm_action_change_desk)
p->allowed_actions |= ActionChangeDesktop;
if ((Atom) actions[count] == net_wm_action_close)
p->allowed_actions |= ActionClose;
}
}
if ( data_ret )
XFree(data_ret);
}
}
if (dirty2 & WM2UserTime) {
p->user_time = -1U;
if (XGetWindowProperty(p->display, p->window, net_wm_user_time, 0l, 1l,
False, XA_CARDINAL, &type_ret, &format_ret,
&nitems_ret, &unused, &data_ret) == Success) {
// don't do nitems_ret check - Qt does PropModeAppend to avoid API call for it
if (type_ret == XA_CARDINAL && format_ret == 32 /*&& nitems_ret == 1*/) {
p->user_time = *((long *) data_ret);
}
if ( data_ret )
XFree(data_ret);
}
}
if (dirty2 & WM2TransientFor) {
p->transient_for = None;
XGetTransientForHint(p->display, p->window, &p->transient_for);
}
if (dirty2 & WM2GroupLeader) {
XWMHints *hints = XGetWMHints(p->display, p->window);
p->window_group = None;
if ( hints )
{
if( hints->flags & WindowGroupHint )
p->window_group = hints->window_group;
XFree( reinterpret_cast< char* >( hints ));
}
}
if( dirty2 & WM2WindowClass ) {
delete[] p->class_class;
delete[] p->class_name;
p->class_class = NULL;
p->class_name = NULL;
XClassHint hint;
if( XGetClassHint( p->display, p->window, &hint )) {
p->class_class = strdup( hint.res_class );
p->class_name = strdup( hint.res_name );
XFree( hint.res_class );
XFree( hint.res_name );
}
}
if( dirty2 & WM2WindowRole ) {
delete[] p->role;
p->role = NULL;
if (XGetWindowProperty(p->display, p->window, wm_window_role, 0l,
MAX_PROP_SIZE, False, XA_STRING, &type_ret,
&format_ret, &nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_STRING && format_ret == 8 && nitems_ret > 0) {
p->role = nstrndup((const char *) data_ret, nitems_ret);
}
if( data_ret )
XFree(data_ret);
}
}
if( dirty2 & WM2ClientMachine ) {
delete[] p->client_machine;
p->client_machine = NULL;
if (XGetWindowProperty(p->display, p->window, XA_WM_CLIENT_MACHINE, 0l,
MAX_PROP_SIZE, False, XA_STRING, &type_ret,
&format_ret, &nitems_ret, &unused, &data_ret)
== Success) {
if (type_ret == XA_STRING && format_ret == 8 && nitems_ret > 0) {
p->client_machine = nstrndup((const char *) data_ret, nitems_ret);
}
if( data_ret )
XFree(data_ret);
}
}
}
NETRect NETWinInfo::iconGeometry() const {
return p->icon_geom;
}
unsigned long NETWinInfo::state() const {
return p->state;
}
NETStrut NETWinInfo::strut() const {
return p->strut;
}
NETExtendedStrut NETWinInfo::extendedStrut() const {
return p->extended_strut;
}
bool NET::typeMatchesMask( WindowType type, unsigned long mask ) {
switch( type ) {
#define CHECK_TYPE_MASK( type ) \
case type: \
if( mask & type##Mask ) \
return true; \
break;
CHECK_TYPE_MASK( Normal )
CHECK_TYPE_MASK( Desktop )
CHECK_TYPE_MASK( Dock )
CHECK_TYPE_MASK( Toolbar )
CHECK_TYPE_MASK( Menu )
CHECK_TYPE_MASK( Dialog )
CHECK_TYPE_MASK( Override )
CHECK_TYPE_MASK( TopMenu )
CHECK_TYPE_MASK( Utility )
CHECK_TYPE_MASK( Splash )
CHECK_TYPE_MASK( DropdownMenu )
CHECK_TYPE_MASK( PopupMenu )
CHECK_TYPE_MASK( Tooltip )
CHECK_TYPE_MASK( Notification )
CHECK_TYPE_MASK( ComboBox )
CHECK_TYPE_MASK( DNDIcon )
#undef CHECK_TYPE_MASK
default:
break;
}
return false;
}
NET::WindowType NETWinInfo::windowType( unsigned long supported_types ) const {
for( int i = 0;
i < p->types.size();
++i ) {
// return the type only if the application supports it
if( typeMatchesMask( p->types[ i ], supported_types ))
return p->types[ i ];
}
return Unknown;
}
NET::WindowType NETWinInfo::windowType() const {
return p->types[ 0 ];
}
const char *NETWinInfo::name() const {
return p->name;
}
const char *NETWinInfo::visibleName() const {
return p->visible_name;
}
const char *NETWinInfo::iconName() const {
return p->icon_name;
}
const char *NETWinInfo::visibleIconName() const {
return p->visible_icon_name;
}
int NETWinInfo::desktop() const {
return p->desktop;
}
int NETWinInfo::pid() const {
return p->pid;
}
Time NETWinInfo::userTime() const {
return p->user_time;
}
const char* NETWinInfo::startupId() const {
return p->startup_id;
}
unsigned long NETWinInfo::allowedActions() const {
return p->allowed_actions;
}
bool NETWinInfo::hasNETSupport() const {
return p->has_net_support;
}
Window NETWinInfo::transientFor() const {
return p->transient_for;
}
Window NETWinInfo::groupLeader() const {
return p->window_group;
}
const char* NETWinInfo::windowClassClass() const {
return p->class_class;
}
const char* NETWinInfo::windowClassName() const {
return p->class_name;
}
const char* NETWinInfo::windowRole() const {
return p->role;
}
const char* NETWinInfo::clientMachine() const {
return p->client_machine;
}
Bool NETWinInfo::handledIcons() const {
return p->handled_icons;
}
Window NETWinInfo::kdeSystemTrayWinFor() const {
return p->kde_system_tray_win_for;
}
const unsigned long* NETWinInfo::passedProperties() const {
return p->properties;
}
unsigned long NETWinInfo::properties() const {
return p->properties[ PROTOCOLS ];
}
NET::MappingState NETWinInfo::mappingState() const {
return p->mapping_state;
}
void NETRootInfo::virtual_hook( int, void* )
{ /*BASE::virtual_hook( id, data );*/ }
void NETWinInfo::virtual_hook( int, void* )
{ /*BASE::virtual_hook( id, data );*/ }
// Functions for X timestamp comparing. For Time being 32bit they're fairly simple
// (the #if 0 part), but on 64bit architectures Time is 64bit unsigned long,
// so there special care needs to be taken to always use only the lower 32bits.
#if 0
int NET::timestampCompare( Time time1, Time time2 ) // like strcmp()
{
if( time1 == time2 )
return 0;
return ( time1 - time2 ) < 0x7fffffffU ? 1 : -1; // time1 > time2 -> 1, handle wrapping
}
Time NET::timestampDiff( Time time1, Time time2 ) // returns time2 - time1
{ // no need to handle wrapping?
return time2 - time1;
}
#else
int NET::timestampCompare( unsigned long time1_, unsigned long time2_ ) // like strcmp()
{
TQ_UINT32 time1 = time1_;
TQ_UINT32 time2 = time2_;
if( time1 == time2 )
return 0;
return TQ_UINT32( time1 - time2 ) < 0x7fffffffU ? 1 : -1; // time1 > time2 -> 1, handle wrapping
}
int NET::timestampDiff( unsigned long time1_, unsigned long time2_ ) // returns time2 - time1
{ // no need to handle wrapping?
TQ_UINT32 time1 = time1_;
TQ_UINT32 time2 = time2_;
return TQ_UINT32( time2 - time1 );
}
#endif
#endif