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.
4646 lines
137 KiB
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 <qwidget.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, "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, "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;
|
|
}
|
|
|
|
extern Time qt_x_user_time;
|
|
void NETRootInfo::setActiveWindow(Window window) {
|
|
setActiveWindow( window, FromUnknown, 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, 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;
|
|
}
|
|
|
|
|
|
QSize NETRootInfo::desktopLayoutColumnsRows() const {
|
|
return QSize( 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()
|
|
{
|
|
Q_UINT32 time1 = time1_;
|
|
Q_UINT32 time2 = time2_;
|
|
if( time1 == time2 )
|
|
return 0;
|
|
return Q_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?
|
|
Q_UINT32 time1 = time1_;
|
|
Q_UINT32 time2 = time2_;
|
|
return Q_UINT32( time2 - time1 );
|
|
}
|
|
#endif
|
|
|
|
|
|
#endif
|