/**
* @file Net.cc
* @author David Reveman <david@waimea.org>
* @date 11-Oct-2001 22:36:12
*
* @brief Implementation of NetHandler class
*
* Functions for reading and writing window hints.
*
* Copyright (C) David Reveman. All rights reserved.
*
*/
#ifdef HAVE_CONFIG_H
# include "../config.h"
#endif // HAVE_CONFIG_H
extern "C" {
#include <X11/Xatom.h>
}
#include "Net.hh"
/**
* @fn NetHandler(Waimea *wa)
* @brief Constructor for NetHandler class
*
* Creates atom identifiers, allocates wm_hints and size_hints.
*
* @param wa Waimea object
*/
NetHandler::NetHandler(Waimea *wa) {
waimea = wa;
display = waimea->display;
wm_hints = XAllocWMHints();
size_hints = XAllocSizeHints();
utf8_string = XInternAtom(display, "UTF8_STRING", false);
mwm_hints_atom =
XInternAtom(display, "_MOTIF_WM_HINTS", false);
wm_state =
XInternAtom(display, "WM_STATE", false);
net_supported =
XInternAtom(display, "_NET_SUPPORTED", false);
net_supported_wm_check =
XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", false);
net_client_list =
XInternAtom(display, "_NET_CLIENT_LIST", false);
net_client_list_stacking =
XInternAtom(display, "_NET_CLIENT_LIST_STACKING", false);
net_active_window =
XInternAtom(display, "_NET_ACTIVE_WINDOW", false);
net_state =
XInternAtom(display, "_NET_WM_STATE", false);
net_state_sticky =
XInternAtom(display, "_NET_WM_STATE_STICKY", false);
net_state_shaded =
XInternAtom(display, "_NET_WM_STATE_SHADED", false);
net_maximized_vert =
XInternAtom(display, "_NET_WM_STATE_MAXIMIZED_VERT", false);
net_maximized_horz =
XInternAtom(display, "_NET_WM_STATE_MAXIMIZED_HORZ", false);
net_state_decor =
XInternAtom(display, "_NET_WM_STATE_DECOR", false);
net_state_decortitle =
XInternAtom(display, "_NET_WM_STATE_DECOR_TITLE", false);
net_state_decorhandle =
XInternAtom(display, "_NET_WM_STATE_DECOR_HANDLE", false);
net_state_decorborder =
XInternAtom(display, "_NET_WM_STATE_DECOR_BORDER", false);
net_state_aot =
XInternAtom(display, "_NET_WM_STATE_STAYS_ON_TOP", false);
net_state_aab =
XInternAtom(display, "_NET_WM_STATE_STAYS_AT_BOTTOM", false);
net_state_parentrelative_background =
XInternAtom(display, "_NET_WM_STATE_PARENTRELATIVE_BACKGROUND", false);
net_maximized_restore =
XInternAtom(display, "_NET_MAXIMIZED_RESTORE", false);
net_virtual_pos =
XInternAtom(display, "_NET_VIRTUAL_POS", false);
net_desktop_viewport =
XInternAtom(display, "_NET_DESKTOP_VIEWPORT", false);
net_desktop_geometry =
XInternAtom(display, "_NET_DESKTOP_GEOMETRY", false);
net_wm_strut =
XInternAtom(display, "_NET_WM_STRUT", false);
net_workarea =
XInternAtom(display, "_NET_WORKAREA", false);
net_wm_name =
XInternAtom(display, "_NET_WM_NAME", false);
net_wm_visible_name =
XInternAtom(display, "_NET_WM_VISIBLE_NAME", false);
net_restart =
XInternAtom(display, "_NET_RESTART", false);
net_shutdown =
XInternAtom(display, "_NET_SHUTDOWN", false);
net_wm_pid =
XInternAtom(display, "_NET_WM_PID", false);
net_wm_window_type =
XInternAtom(display, "_NET_WM_WINDOW_TYPE", false);
net_wm_window_type_desktop =
XInternAtom(display, "_NET_WM_WINDOW_TYPE_DESKTOP", false);
net_wm_window_type_dock =
XInternAtom(display, "_NET_WM_WINDOW_TYPE_DOCK", false);
net_wm_window_type_toolbar =
XInternAtom(display, "_NET_WM_WINDOW_TYPE_TOOLBAR", false);
net_wm_window_type_menu =
XInternAtom(display, "_NET_WM_WINDOW_TYPE_MENU", false);
net_wm_window_type_splash =
XInternAtom(display, "_NET_WM_WINDOW_TYPE_SPLASH", false);
net_wm_window_type_normal =
XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", false);
net_wm_window_type_dialog =
XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", false);
net_wm_window_type_utility =
XInternAtom(display, "_NET_WM_WINDOW_TYPE_UTILITY", false);
net_current_desktop =
XInternAtom(display, "_NET_CURRENT_DESKTOP", false);
net_number_of_desktops =
XInternAtom(display, "_NET_NUMBER_OF_DESKTOPS", false);
net_desktop_names =
XInternAtom(display, "_NET_DESKTOP_NAMES", false);
net_close_window =
XInternAtom(display, "_NET_CLOSE_WINDOW", false);
net_wm_desktop =
XInternAtom(display, "_NET_WM_DESKTOP", false);
net_wm_desktop_mask =
XInternAtom(display, "_NET_WM_DESKTOP_MASK", false);
kde_net_system_tray_windows =
XInternAtom(display, "_KDE_NET_SYSTEM_TRAY_WINDOWS", false);
kde_net_wm_system_tray_window_for =
XInternAtom(display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", false);
#ifdef RENDER
xrootpmap_id =
XInternAtom(display, "_XROOTPMAP_ID", false);
#endif // RENDER
xa_xdndaware = XInternAtom(display, "XdndAware", false);
xa_xdndenter = XInternAtom(display, "XdndEnter", false);
xa_xdndleave = XInternAtom(display, "XdndLeave", false);
event.type = ClientMessage;
event.xclient.display = display;
event.xclient.format = 32;
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] = 0l;
}
/**
* @fn ~NetHandler(void)
* @brief Destructor for NetHandler class
*
* Frees wm_hints and size_hints.
*/
NetHandler::~NetHandler(void) {
XFree(wm_hints);
XFree(size_hints);
}
/**
* @fn GetWMHints(WaWindow *ww)
* @brief Read WM hints
*
* Reads WaWindows WM hints.
*
* @param ww WaWindow object
*/
void NetHandler::GetWMHints(WaWindow *ww) {
XTextProperty text_prop;
char **list;
int num;
char *__m_wastrdup_tmp;
ww->state = NormalState;
XGrabServer(display);
if (validatedrawable(ww->id)) {
if ((wm_hints = XGetWMHints(display, ww->id)))
if (wm_hints->flags & StateHint)
ww->state = wm_hints->initial_state;
ww->classhint = XAllocClassHint();
XGetClassHint(ww->display, ww->id, ww->classhint);
if (XGetWMClientMachine(ww->display, ww->id, &text_prop)) {
if (XTextPropertyToStringList(&text_prop, &list, &num)) {
XFree(text_prop.value);
ww->host = __m_wastrdup(*list);
XFreeStringList(list);
}
}
} else ww->deleted = true;
XUngrabServer(display);
}
/**
* @fn GetMWMHints(WaWindow *ww)
* @brief Read MWM Hints
*
* Reads WaWindows MWM hints.
*
* @param ww WaWindow object
*/
void NetHandler::GetMWMHints(WaWindow *ww) {
Window trans;
int status;
ww->flags.title = ww->flags.border = ww->flags.handle = true;
XGrabServer(display);
if (validatedrawable(ww->id)) {
status = XGetWindowProperty(display, ww->id, mwm_hints_atom, 0L, 20L,
false, mwm_hints_atom, &real_type,
&real_format, &items_read, &items_left,
(unsigned char **) &mwm_hints);
} else WW_DELETED;
XUngrabServer(display);
if (status == Success && items_read >= PropMotifWmHintsElements) {
if (mwm_hints->flags & MwmHintsDecorations
&& !(mwm_hints->decorations & MwmDecorAll)) {
ww->flags.title =
(mwm_hints->decorations & MwmDecorTitle) ? true: false;
ww->flags.border =
(mwm_hints->decorations & MwmDecorBorder) ? true: false;
ww->flags.handle =
(mwm_hints->decorations & MwmDecorHandle) ? true: false;
}
}
if (ww->wascreen->config.transient_above) {
XGrabServer(display);
if (validatedrawable(ww->id)) {
status = XGetTransientForHint(display, ww->id, &trans);
} else WW_DELETED;
XUngrabServer(display);
if (status && trans && (trans != ww->id)) {
if (trans == ww->wascreen->id) {
list<WaWindow *>::iterator it =
ww->wascreen->wawindow_list.begin();
for (;it != ww->wascreen->wawindow_list.end(); ++it)
(*it)->transients.push_back(ww->id);
ww->want_focus = true;
} else {
map<Window, WindowObject *>::iterator it;
if ((it = waimea->window_table.find(trans)) !=
waimea->window_table.end()) {
if (((*it).second)->type == WindowType) {
ww->transient_for = trans;
((WaWindow *)
(*it).second)->transients.push_back(ww->id);
if (waimea->eh && trans == waimea->eh->focused)
ww->want_focus = true;
}
}
}
}
}
ww->flags.all = ww->flags.title && ww->flags.handle && ww->flags.border;
}
/**
* @fn GetWMNormalHints(WaWindow *ww)
* @brief Read size hints
*
* Reads WaWindows size hints.
*
* @param ww WaWindow object
*/
void NetHandler::GetWMNormalHints(WaWindow *ww) {
long dummy;
int status;
ww->size.max_width = ww->size.max_height = 65536;
ww->size.min_width = ww->size.min_height = ww->size.width_inc =
ww->size.height_inc = 1;
ww->size.base_width = ww->size.min_width;
ww->size.base_height = ww->size.min_height;
size_hints->flags = 0;
XGrabServer(display);
if (validatedrawable(ww->id))
status = XGetWMNormalHints(display, ww->id, size_hints, &dummy);
else WW_DELETED;
XUngrabServer(display);
if (status) {
if (size_hints->flags & PMaxSize) {
ww->size.max_width = size_hints->max_width;
ww->size.max_height = size_hints->max_height;
}
if (size_hints->flags & PMinSize) {
ww->size.min_width = size_hints->min_width;
ww->size.min_height = size_hints->min_height;
}
if (size_hints->flags & PResizeInc) {
ww->size.width_inc = size_hints->width_inc;
ww->size.height_inc = size_hints->height_inc;
}
if (size_hints->flags & PBaseSize) {
ww->size.base_width = size_hints->base_width;
ww->size.base_height = size_hints->base_height;
}
if (size_hints->flags & PWinGravity)
ww->size.win_gravity = size_hints->win_gravity;
if (ww->size.width_inc == 0) {
ww->size.base_width = 0;
ww->size.width_inc = 1;
}
if (ww->size.height_inc == 0) {
ww->size.base_height = 0;
ww->size.height_inc = 1;
}
}
if (ww->size.min_width < ((ww->title_w - 4) * 3 + 8))
ww->size.min_width = (ww->title_w - 4) * 3 + 8;
if (ww->size.min_width < (50 + ww->border_w))
ww->size.min_width = 50 + ww->border_w;
}
/**
* @fn GetState(WaWindow *ww)
* @brief Read state hint
*
* Reads WaWindows state hint.
*
* @param ww WaWindow object
*/
void NetHandler::GetState(WaWindow *ww) {
CARD32 *data;
ww->state = WithdrawnState;
XGrabServer(display);
if (validatedrawable(ww->id)) {
if (XGetWindowProperty(display, ww->id, wm_state, 0L, 1L, false,
wm_state, &real_type, &real_format, &items_read,
&items_left, (unsigned char **) &data) ==
Success && items_read) {
ww->state = *data;
XFree(data);
}
} else ww->deleted = true;
XUngrabServer(display);
}
/**
* @fn SetState(WaWindow *ww, int newstate)
* @brief Write state hint.
*
* Changes the state of the window and writes state hint.
*
* @param ww WaWindow object
* @param newstate State to change to
*/
void NetHandler::SetState(WaWindow *ww, int newstate) {
CARD32 data[2];
ww->state = newstate;
switch (ww->state) {
case IconicState:
case NormalState:
ww->MapWindow();
}
if (ww->want_focus && ww->mapped && !ww->hidden) {
XGrabServer(display);
if (validatedrawable(ww->id))
XSetInputFocus(display, ww->id, RevertToPointerRoot, CurrentTime);
else WW_DELETED;
XUngrabServer(display);
}
ww->want_focus = false;
data[0] = ww->state;
data[1] = None;
XGrabServer(display);
if (validatedrawable(ww->id))
XChangeProperty(display, ww->id, wm_state, wm_state,
32, PropModeReplace, (unsigned char *) data, 2);
else WW_DELETED;
XUngrabServer(display);
ww->SendConfig();
}
/**
* @fn GetWmState(WaWindow *ww)
* @brief Reads _NET_WM_STATE atom
*
* Reads _NET_WM_STATE atom to get the current state of the window.
*
* @param ww WaWindow object
*/
void NetHandler::GetWmState(WaWindow *ww) {
CARD32 *data;
bool vert = false, horz = false, shaded = false, title = false,
handle = false, border = false, decor = false;
unsigned int i;
int status;
XGrabServer(display);
if (validatedrawable(ww->id)) {
status = XGetWindowProperty(display, ww->id, net_state, 0L, 10L,
false, XA_ATOM, &real_type,
&real_format, &items_read, &items_left,
(unsigned char **) &data);
} else WW_DELETED;
XUngrabServer(display);
if (status == Success && items_read)
for (i = 0; i < items_read; i++) {
if (data[i] == net_state_sticky) ww->flags.sticky = true;
else if (data[i] == net_state_shaded) shaded = true;
else if (data[i] == net_maximized_vert) vert = true;
else if (data[i] == net_maximized_horz) horz = true;
else if (data[i] == net_state_decor) decor = true;
else if (data[i] == net_state_decortitle) title = true;
else if (data[i] == net_state_decorhandle) handle = true;
else if (data[i] == net_state_decorborder) border = true;
else if (data[i] == net_state_aot) {
ww->flags.alwaysontop = true;
ww->wascreen->wawindow_list_stacking_aot.push_back(ww);
ww->wascreen->WaRaiseWindow(0);
}
else if (data[i] == net_state_aab) {
ww->flags.alwaysatbottom = true;
ww->wascreen->wawindow_list_stacking_aab.push_back(ww);
ww->wascreen->WaLowerWindow(ww->frame->id);
}
}
if (decor) {
ww->flags.title = ww->flags.handle = ww->flags.border = false;
if (title) ww->flags.title = true;
if (handle) ww->flags.handle = true;
if (border) ww->flags.border = true;
ww->flags.all = ww->flags.title && ww->flags.handle &&
ww->flags.border;
}
XFree(data);
if (vert && horz) {
XGrabServer(display);
if (validatedrawable(ww->id)) {
status = XGetWindowProperty(display, ww->id, net_maximized_restore,
0L, 6L, false, XA_CARDINAL, &real_type,
&real_format, &items_read,
&items_left, (unsigned char **) &data);
} else WW_DELETED;
XUngrabServer(display);
if (status == Success && items_read >= 6) {
ww->_Maximize(data[4], data[5]);
ww->restore_max.x = data[0];
ww->restore_max.y = data[1];
ww->restore_max.width = data[2];
ww->restore_max.height = data[3];
XFree(data);
}
}
if (shaded) ww->flags.shaded = true;
}
/**
* @fn SetWmState(WaWindow *ww)
* @brief Sets _NET_WM_STATE atom
*
* Sets _NET_WM_STATE atom to the state of the window.
*
* @param ww WaWindow object
*/
void NetHandler::SetWmState(WaWindow *ww) {
int i = 0;
CARD32 data[10];
CARD32 data2[6];
XGrabServer(display);
if (validatedrawable(ww->id)) {
if (ww->flags.sticky) data[i++] = net_state_sticky;
if (ww->flags.shaded) data[i++] = net_state_shaded;
data[i++] = net_state_decor;
if (ww->flags.title) data[i++] = net_state_decortitle;
if (ww->flags.handle) data[i++] = net_state_decorhandle;
if (ww->flags.border) data[i++] = net_state_decorborder;
if (ww->flags.alwaysontop) data[i++] = net_state_aot;
if (ww->flags.alwaysatbottom) data[i++] = net_state_aab;
if (ww->flags.max) {
data[i++] = net_maximized_vert;
data[i++] = net_maximized_horz;
data2[0] = ww->restore_max.x;
data2[1] = ww->restore_max.y;
data2[2] = ww->restore_max.width;
data2[3] = ww->restore_max.height;
data2[4] = ww->restore_max.misc0;
data2[5] = ww->restore_max.misc1;
XChangeProperty(display, ww->id, net_maximized_restore,
XA_CARDINAL, 32, PropModeReplace,
(unsigned char *) data2, 6);
}
XChangeProperty(display, ww->id, net_state, XA_ATOM, 32,
PropModeReplace, (unsigned char *) data, i);
} else ww->deleted = true;
XUngrabServer(display);
}
/**
* @fn SetSupported(WaScreen *ws)
* @brief Writes _NET_SUPPORTED hint
*
* Sets _NET_SUPPORTED hint to the atoms Waimea supports.
*
* @param ws WaScreen object
*/
void NetHandler::SetSupported(WaScreen *ws) {
CARD32 data[43];
int i = 0;
data[i++] = net_supported;
data[i++] = net_supported_wm_check;
data[i++] = net_current_desktop;
data[i++] = net_number_of_desktops;
data[i++] = net_desktop_geometry;
data[i++] = net_desktop_viewport;
data[i++] = net_desktop_names;
data[i++] = net_active_window;
data[i++] = net_workarea;
data[i++] = net_client_list;
data[i++] = net_client_list_stacking;
data[i++] = net_wm_window_type;
data[i++] = net_wm_window_type_desktop;
data[i++] = net_wm_window_type_dock;
data[i++] = net_wm_window_type_toolbar;
data[i++] = net_wm_window_type_menu;
data[i++] = net_wm_window_type_splash;
data[i++] = net_wm_window_type_normal;
data[i++] = net_wm_window_type_dialog;
data[i++] = net_wm_window_type_utility;
data[i++] = net_state;
data[i++] = net_state_sticky;
data[i++] = net_state_shaded;
data[i++] = net_maximized_vert;
data[i++] = net_maximized_horz;
data[i++] = net_wm_strut;
data[i++] = net_wm_name;
data[i++] = net_wm_visible_name;
data[i++] = net_wm_desktop;
data[i++] = net_wm_desktop_mask;
data[i++] = net_state_decor;
data[i++] = net_state_decortitle;
data[i++] = net_state_decorhandle;
data[i++] = net_state_decorborder;
data[i++] = net_state_aot;
data[i++] = net_state_aab;
#ifdef RENDER
data[i++] = net_state_parentrelative_background;
#endif // RENDER
data[i++] = net_maximized_restore;
data[i++] = net_virtual_pos;
data[i++] = net_restart;
data[i++] = net_shutdown;
data[i++] = net_wm_pid;
XChangeProperty(display, ws->id, net_supported, XA_ATOM, 32,
PropModeReplace, (unsigned char *) data, i);
}
/**
* @fn SetSupportedCheck(WaScreen *ws, Window child)
* @brief Writes _NET_SUPPORTED_WM_CHECK hint
*
* Sets _NET_SUPPORTED_WM_CHECK to child window and sets child windows
* _NET_WM_NAME hint to the window manager name.
*
* @param ws WaScreen object
& @param child Window to use as child window
*/
void NetHandler::SetSupportedWMCheck(WaScreen *ws, Window child) {
XChangeProperty(display, ws->id, net_supported_wm_check, XA_WINDOW, 32,
PropModeReplace, (unsigned char *) &child, 1);
XChangeProperty(display, child, net_supported_wm_check, XA_WINDOW, 32,
PropModeReplace, (unsigned char *) &child, 1);
XChangeProperty(display, child, net_wm_name, utf8_string, 8,
PropModeReplace, (unsigned char *) PACKAGE,
strlen(PACKAGE));
}
/**
* @fn SetClientList(WaScreen *ws)
* @brief Writes _NET_CLIENT_LIST hint
*
* Updates _NET_CLIENT_LIST hint to the current window list.
*
* @param ws WaScreen object
*/
void NetHandler::SetClientList(WaScreen *ws) {
CARD32 *data;
int i = 0;
data = new CARD32[ws->wawindow_list_map_order.size() + 1];
list<WaWindow *>::iterator it =
ws->wawindow_list_map_order.begin();
for (; it != ws->wawindow_list_map_order.end(); ++it) {
if (! (*it)->flags.forcedatbottom)
data[i++] = (*it)->id;
}
if (i > 0)
XChangeProperty(display, ws->id, net_client_list, XA_WINDOW, 32,
PropModeReplace, (unsigned char *) data, i);
delete [] data;
}
/**
* @fn SetClientListStacking(WaScreen *ws)
* @brief Writes _NET_CLIENT_LIST_STACKING hint
*
* Updates _NET_CLIENT_LIST_STACKING hint to the current stacking order.
*
* @param ws WaScreen object
*/
void NetHandler::SetClientListStacking(WaScreen *ws) {
CARD32 *data;
list<WaWindow *>::reverse_iterator rit;
list<WindowObject *>::reverse_iterator writ;
list<WaWindow *>::iterator it;
int i = 0;
data = new CARD32[ws->wawindow_list.size() + 1];
it = ws->wawindow_list_stacking_aab.begin();
for (; it != ws->wawindow_list_stacking_aab.end(); ++it)
data[i++] = (*it)->id;
writ = ws->wa_list_stacking.rbegin();
for (; writ != ws->wa_list_stacking.rend(); ++writ) {
if ((*writ)->type == WindowType)
data[i++] = ((WaWindow *) (*writ))->id;
}
rit = ws->wawindow_list_stacking_aot.rbegin();
for (; rit != ws->wawindow_list_stacking_aot.rend(); ++rit)
data[i++] = (*rit)->id;
if (i > 0)
XChangeProperty(display, ws->id, net_client_list_stacking, XA_WINDOW,
32, PropModeReplace, (unsigned char *) data, i);
delete [] data;
}
/**
* @fn GetClientList(WaScreen *ws)
* @brief Reads _NET_CLIENT_LIST_STACKING hint
*
* Updates window stacking order to order in _NET_CLIENT_LIST_STACKING hint.
*
* @param ws WaScreen object
*/
void NetHandler::GetClientListStacking(WaScreen *ws) {
CARD32 *data;
WaWindow *ww;
unsigned int i;
if (XGetWindowProperty(display, ws->id, net_client_list_stacking,
0L, ws->wawindow_list.size(),
false, XA_WINDOW, &real_type,
&real_format, &items_read, &items_left,
(unsigned char **) &data) == Success &&
items_read) {
for (i = 0; i < items_read; i++) {
ww = (WaWindow *) waimea->FindWin(data[i], WindowType);
if (ww) {
if (ww->flags.alwaysontop) {
ws->wawindow_list_stacking_aot.remove(ww);
ws->wawindow_list_stacking_aot.push_front(ww);
}
else if (ww->flags.alwaysatbottom) {
ws->wawindow_list_stacking_aab.remove(ww);
ws->wawindow_list_stacking_aab.push_back(ww);
}
else if (! ww->flags.forcedatbottom) {
ws->wa_list_stacking.remove(ww);
ws->wa_list_stacking.push_front(ww);
}
}
}
ws->WaLowerWindow((Window) 0);
}
}
/**
* @fn SetActiveWindow(WaScreen *ws, WaWindow *ww)
* @brief Writes _NET_ACTIVE_CLIENT hint
*
* Updates _NET_ACTIVE_CLIENT hint to the current list of last active
* windows. The currently active window at the front.
*
* @param ws WaScreen object
* @param ww WaWindow that was set active or NULL if root window.
*/
void NetHandler::SetActiveWindow(WaScreen *ws, WaWindow *ww) {
CARD32 *data;
list<WaWindow *>::iterator it;
int i = 0;
data = new CARD32[ws->wawindow_list.size() + 1];
if (ww) {
ws->focus = false;
ws->wawindow_list.remove(ww);
ws->wawindow_list.push_front(ww);
} else {
ws->focus = true;
data[i++] = None;
}
it = ws->wawindow_list.begin();
for (; it != ws->wawindow_list.end(); ++it)
data[i++] = (*it)->id;
XChangeProperty(display, ws->id, net_active_window, XA_WINDOW, 32,
PropModeReplace, (unsigned char *) data, i);
delete [] data;
}
/**
* @fn GetActiveWindow(WaScreen *ws)
* @brief Reads _NET_ACTIVE_CLIENT hint
*
* Sorts active window list after _NET_ACTIVE_CLIENT hint and sets input
* focus to first window in _NET_ACTIVE_CLIENT list.
*
* @param ws WaScreen object
*/
void NetHandler::GetActiveWindow(WaScreen *ws) {
WaWindow *ww;
CARD32 *data;
int i;
if (XGetWindowProperty(display, ws->id, net_active_window, 0L,
ws->wawindow_list.size(),
false, XA_WINDOW, &real_type, &real_format,
&items_read, &items_left,
(unsigned char **) &data) == Success &&
items_read) {
for (i = items_read - 1; i >= 0; i--) {
if (i == 0 && data[0] == None) {
ws->Focus(NULL, NULL);
break;
}
ww = (WaWindow *) waimea->FindWin(data[i], WindowType);
if (ww) {
ws->wawindow_list.remove(ww);
ws->wawindow_list.push_front(ww);
if (i == 0)
ww->Focus(false);
}
}
XFree(data);
}
}
/**
* @fn GetVirtualPos(WaWindow *ww)
* @brief Reads virtual position hint
*
* Reads WaWindows virtual position hint.
*
* @param ww WaWindow object
*/
void NetHandler::GetVirtualPos(WaWindow *ww) {
int *data;
XGrabServer(display);
if (validatedrawable(ww->id)) {
if (XGetWindowProperty(display, ww->id, net_virtual_pos, 0L, 2L,
false, XA_INTEGER, &real_type, &real_format,
&items_read, &items_left,
(unsigned char **) &data) == Success &&
items_read >= 2) {
ww->attrib.x = data[0] - ww->wascreen->v_x;
ww->attrib.y = data[1] - ww->wascreen->v_y;
if (ww->flags.sticky) {
ww->attrib.x = ww->attrib.x % ww->wascreen->width;
ww->attrib.y = ww->attrib.y % ww->wascreen->height;
}
XFree(data);
}
} else ww->deleted = true;
XUngrabServer(display);
}
/**
* @fn GetXaName(WaWindow *ww)
* @brief Reads window title
*
* Reads WM_NAME hint and if hint exists the window title is set to this
* and _NET_WM_VISIBLE_HINT is updated.
*
* @param ww WaWindow object
*/
void NetHandler::GetXaName(WaWindow *ww) {
char *data = NULL;
int status;
char *__m_wastrdup_tmp;
XGrabServer(display);
if (validatedrawable(ww->id)) {
status = XFetchName(display, ww->id, &data);
} else ww->deleted = true;
XUngrabServer(display);
if (status && data) {
delete [] ww->name;
ww->name = __m_wastrdup(data);
XFree(data);
ww->SetActionLists();
}
XGrabServer(display);
if (validatedrawable(ww->id)) {
XChangeProperty(display, ww->id, net_wm_visible_name,
utf8_string, 8, PropModeReplace,
(unsigned char *) ww->name, strlen(ww->name));
} else ww->deleted = true;
XUngrabServer(display);
}
/**
* @fn GetNetName(WaWindow *ww)
* @brief Reads window title
*
* Reads _NET_WM_NAME hint and if hint exists the window title is set to this
* and _NET_WM_VISIBLE_HINT is updated.
*
* @param ww WaWindow object
*
* @return True if _NET_WM_NAME hint did exist otherwise false
*/
bool NetHandler::GetNetName(WaWindow *ww) {
char *data;
int status;
char *__m_wastrdup_tmp;
XGrabServer(display);
if (validatedrawable(ww->id)) {
status = XGetWindowProperty(display, ww->id, net_wm_name, 0L, 8192L,
false, utf8_string, &real_type,
&real_format, &items_read, &items_left,
(unsigned char **) &data);
} else ww->deleted = true;
XUngrabServer(display);
if (status == Success && items_read) {
delete [] ww->name;
ww->name = __m_wastrdup(data);
ww->SetActionLists();
XFree(data);
XGrabServer(display);
if (validatedrawable(ww->id)) {
XChangeProperty(display, ww->id, net_wm_visible_name,
utf8_string, 8, PropModeReplace,
(unsigned char *) ww->name, strlen(ww->name));
} else ww->deleted = true;
XUngrabServer(display);
return true;
}
return false;
}
/**
* @fn SetVirtualPos(WaWindow *ww)
* @brief Writes virtual position hint
*
* Writes WaWindows virtual position hint.
*
* @param ww WaWindow object
*/
void NetHandler::SetVirtualPos(WaWindow *ww) {
int data[2];
ww->Gravitate(RemoveGravity);
data[0] = ww->wascreen->v_x + ww->attrib.x;
data[1] = ww->wascreen->v_y + ww->attrib.y;
ww->Gravitate(ApplyGravity);
XGrabServer(display);
if (validatedrawable(ww->id))
XChangeProperty(display, ww->id, net_virtual_pos, XA_INTEGER, 32,
PropModeReplace, (unsigned char *) data, 2);
else ww->deleted = true;
XUngrabServer(display);
}
/**
* @fn GetWmStrut(WaWindow *ww)
* @brief Reads WM_STRUT hint
*
* Reads windows WM_STRUT hint, adds it to the strut list and updates
* workarea.
*
* @param ww WaWindow object
*/
void NetHandler::GetWmStrut(WaWindow *ww) {
CARD32 *data;
WMstrut *wm_strut;
bool found = false;
int status;
XGrabServer(display);
if (validatedrawable(ww->id)) {
status = XGetWindowProperty(display, ww->id, net_wm_strut, 0L, 4L,
false, XA_CARDINAL, &real_type,
&real_format, &items_read, &items_left,
(unsigned char **) &data);
} else WW_DELETED;
XUngrabServer(display);
if (status == Success && items_read >= 4) {
list<WMstrut *>::iterator it = ww->wascreen->strut_list.begin();
for (; it != ww->wascreen->strut_list.end(); ++it) {
if ((*it)->window == ww->id) {
(*it)->left = data[0];
(*it)->right = data[1];
(*it)->top = data[2];
(*it)->bottom = data[3];
found = true;
ww->wascreen->UpdateWorkarea();
}
}
if (! found) {
wm_strut = new WMstrut;
wm_strut->window = ww->id;
wm_strut->left = data[0];
wm_strut->right = data[1];
wm_strut->top = data[2];
wm_strut->bottom = data[3];
ww->wm_strut = wm_strut;
ww->wascreen->strut_list.push_back(wm_strut);
ww->wascreen->UpdateWorkarea();
}
XFree(data);
}
}
/**
* @fn GetWmPid(WaWindow *ww)
* @brief Reads _NET_WM_PID hint
*
* Reads windows _NET_WM_PID hint and stores it in WaWindows pid variable.
*
* @param ww WaWindow object
*/
void NetHandler::GetWmPid(WaWindow *ww) {
char tmp[32];
CARD32 *data;
XGrabServer(display);
if (validatedrawable(ww->id)) {
if (XGetWindowProperty(ww->display, ww->id, net_wm_pid, 0L, 1L,
false, XA_CARDINAL, &real_type,
&real_format, &items_read, &items_left,
(unsigned char **) &data) == Success &&
items_read) {
sprintf(tmp, "%d" , (unsigned int) *data);
ww->pid = new char[strlen(tmp) + 1];
sprintf(ww->pid, "%s" , tmp);
XFree(data);
}
} else ww->deleted = true;
XUngrabServer(display);
}
/**
* @fn GetDesktopViewPort(WaScreen *ws)
* @brief Reads viewport hint
*
* Reads WaScreens viewport hint.
*
* @param ws WaScreen object
*/
void NetHandler::GetDesktopViewPort(WaScreen *ws) {
CARD32 *data;
if (XGetWindowProperty(display, ws->id, net_desktop_viewport, 0L, 2L,
false, XA_CARDINAL, &real_type,
&real_format, &items_read, &items_left,
(unsigned char **) &data) == Success &&
items_read >= 2) {
ws->MoveViewportTo(data[0], data[1]);
XFree(data);
}
}
/**
* @fn SetDesktopViewPort(WaScreen *ws)
* @brief Writes viewport hint
*
* Writes WaScreens viewport hint.
*
* @param ws WaScreen object
*/
void NetHandler::SetDesktopViewPort(WaScreen *ws) {
CARD32 data[2];
data[0] = ws->v_x;
data[1] = ws->v_y;
XChangeProperty(display, ws->id, net_desktop_viewport, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) data, 2);
}
/**
* @fn SetDesktopGeometry(WaScreen *ws)
* @brief Writes desktop geometry hint
*
* Sets _NET_DESKTOP_GEOMETRY hint.
*
* @param ws WaScreen object
*/
void NetHandler::SetDesktopGeometry(WaScreen *ws) {
CARD32 data[2];
data[0] = ws->v_xmax + ws->width;
data[1] = ws->v_ymax + ws->height;
XChangeProperty(display, ws->id, net_desktop_geometry, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) data, 2);
}
/**
* @fn SetNumberOfDesktops(WaScreen *ws)
* @brief Writes number of desktops hint
*
* Sets _NET_NUMBER_OF_DESKTOPS hint.
*
* @param ws WaScreen object
*/
void NetHandler::SetNumberOfDesktops(WaScreen *ws) {
CARD32 data[1];
data[0] = ws->desktop_list.size();
XChangeProperty(display, ws->id, net_number_of_desktops, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) data, 1);
}
/**
* @fn SetCurrentDesktop(WaScreen *ws)
* @brief Writes current desktop hint
*
* Sets _NET_CURRENT_DESKTOP hint.
*
* @param ws WaScreen object
*/
void NetHandler::SetCurrentDesktop(WaScreen *ws) {
CARD32 data[1];
data[0] = ws->current_desktop->number;
XChangeProperty(display, ws->id, net_current_desktop, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) data, 1);
}
/**
* @fn GetCurrentDesktop(WaScreen *ws)
* @brief Reads current desktop hint
*
* Reads _NET_CURRENT_DESKTOP hint and sets desktop accordingly.
*
* @param ws WaScreen object
*/
void NetHandler::GetCurrentDesktop(WaScreen *ws) {
CARD32 *data;
if (XGetWindowProperty(display, ws->id, net_current_desktop, 0L, 1L,
false, XA_CARDINAL, &real_type, &real_format,
&items_read, &items_left,
(unsigned char **) &data) == Success &&
items_read) {
ws->GoToDesktop(data[0]);
XFree(data);
}
}
/**
* @fn SetDesktopNames(WaScreen *ws, char *names)
* @brief Writes desktop names hint
*
* Sets _NET_DESKTOP_NAMES.
*
* @param ws WaScreen object
* @param names String to parse desktop names from
*/
void NetHandler::SetDesktopNames(WaScreen *ws, char *names) {
int i;
for (i = 0; i < 8192; i++) {
if (names[i] == ',') names[i] = '\0';
else if (names[i] == '\0') break;
}
names[i] = '\0';
if (i)
XChangeProperty(display, ws->id, net_desktop_names, utf8_string, 8,
PropModeReplace, (unsigned char *) names, i + 1);
}
/**
* @fn SetWorkarea(WaScreen *ws)
* @brief Sets window manager workarea
*
* Sets the window manager workarea, used for placing icons and maximizing
* windows.
*
* @param ws WaScreen object
*/
void NetHandler::SetWorkarea(WaScreen *ws) {
CARD32 data[4 * 16];
int i = 0;
list<Desktop *>::iterator it = ws->desktop_list.begin();
for (; it != ws->desktop_list.end(); ++it) {
data[i++] = (*it)->workarea.x;
data[i++] = (*it)->workarea.y;
data[i++] = (*it)->workarea.width;
data[i++] = (*it)->workarea.height;
}
XChangeProperty(waimea->display, ws->id, net_workarea, XA_CARDINAL,
32, PropModeReplace, (unsigned char *) data, i);
}
/**
* @fn wXDNDMakeAwareness(Window window)
* @brief Make window DND aware
*
* Makes drag'n'drop awareness for window.
*
* @param window Window to make DND aware
*/
void NetHandler::wXDNDMakeAwareness(Window window) {
long int xdnd_version = 3;
XChangeProperty(waimea->display, window, xa_xdndaware, XA_ATOM,
32, PropModeReplace, (unsigned char *) &xdnd_version, 1);
}
/**
* @fn wXDNDClearAwareness(Window window)
* @brief Removes DND awareness from window
*
* Removes drag'n'drop awareness for window.
*
* @param window Window to remove DND awareness from
*/
void NetHandler::wXDNDClearAwareness(Window window) {
XDeleteProperty (waimea->display, window, xa_xdndaware);
}
/**
* @fn DeleteSupported(WaScreen *ws)
* @brief Deletes supported hints
*
* Deletes all hints set on the root window that we don't have any use
* of next time Waimea starts.
*
* @param ws WaScreen object
*/
void NetHandler::DeleteSupported(WaScreen *ws) {
XDeleteProperty(display, ws->id, net_desktop_geometry);
XDeleteProperty(display, ws->id, net_workarea);
XDeleteProperty(display, ws->id, net_supported_wm_check);
XDeleteProperty(display, ws->id, net_supported);
}
#ifdef RENDER
/**
* @fn GetXRootPMapId(WaScreen *ws)
* @brief Reads XROOTPMAPID hint
*
* Reads XROOTPMAPID hint, which if it exist is the pixmap ID for the root
* window.
*
* @param ws WaScreen object
*/
void NetHandler::GetXRootPMapId(WaScreen *ws) {
CARD32 *data;
XSync(ws->display, false);
if (XGetWindowProperty(ws->pdisplay, ws->id, xrootpmap_id, 0L, 1L,
false, XA_PIXMAP, &real_type,
&real_format, &items_read, &items_left,
(unsigned char **) &data) == Success &&
items_read) {
ws->xrootpmap_id = (Pixmap) (*data);
XFree(data);
}
else
ws->xrootpmap_id = (Pixmap) 0;
XSync(ws->display, false);
XSync(ws->pdisplay, false);
}
#endif // RENDER
/**
* @fn GetType(WaWindow *ww)
* @brief Read type hint
*
* Reads _NET_WM_WINDOW_TYPE hint and sets window properties accordingly.
*
* @param ww WaWindow object
*/
void NetHandler::GetWmType(WaWindow *ww) {
CARD32 *data;
int status;
XGrabServer(display);
if (validatedrawable(ww->id)) {
status = XGetWindowProperty(display, ww->id, net_wm_window_type,
0L, 8L, false, XA_ATOM,
&real_type, &real_format, &items_read,
&items_left, (unsigned char **) &data);
} else WW_DELETED;
XUngrabServer(display);
if (status == Success && items_read) {
for (unsigned int i = 0; i < items_read; ++i) {
if (data[i] == net_wm_window_type_desktop) {
ww->desktop_mask = (1L << 16) - 1;
ww->flags.tasklist = false;
ww->flags.sticky = true;
ww->flags.border = ww->flags.title = ww->flags.handle =
ww->flags.all = false;
ww->size.max_width = ww->wascreen->width;
ww->size.min_width = ww->wascreen->width;
ww->size.max_height = ww->wascreen->height;
ww->size.min_height = ww->wascreen->height;
ww->attrib.x = 0;
ww->attrib.y = 0;
if (ww->flags.alwaysontop)
ww->wascreen->wawindow_list_stacking_aot.remove(ww);
if (ww->flags.alwaysatbottom)
ww->wascreen->wawindow_list_stacking_aab.remove(ww);
ww->flags.alwaysatbottom = ww->flags.alwaysontop = false;
ww->flags.forcedatbottom = true;
ww->wascreen->always_at_bottom_list.push_back(ww->frame->id);
ww->wascreen->WaLowerWindow(ww->frame->id);
}
else if (data[i] == net_wm_window_type_toolbar ||
data[i] == net_wm_window_type_dock) {
ww->desktop_mask = (1L << 16) - 1;
ww->flags.tasklist = false;
ww->flags.sticky = true;
ww->flags.border = ww->flags.title = ww->flags.handle =
ww->flags.all = false;
if (ww->flags.alwaysontop)
ww->wascreen->wawindow_list_stacking_aot.remove(ww);
if (ww->flags.alwaysatbottom)
ww->wascreen->wawindow_list_stacking_aab.remove(ww);
ww->flags.alwaysontop = true;
ww->wascreen->wawindow_list_stacking_aot.push_front(ww);
ww->wascreen->WaRaiseWindow(0);
}
else if (data[i] == net_wm_window_type_splash ||
data[i] == net_wm_window_type_menu) {
ww->flags.tasklist = false;
ww->flags.border = ww->flags.title = ww->flags.handle =
ww->flags.all = false;
if (ww->flags.alwaysontop)
ww->wascreen->wawindow_list_stacking_aot.remove(ww);
if (ww->flags.alwaysatbottom)
ww->wascreen->wawindow_list_stacking_aab.remove(ww);
ww->flags.alwaysontop = true;
ww->wascreen->wawindow_list_stacking_aot.push_front(ww);
ww->wascreen->WaRaiseWindow(0);
}
else {
if (ww->attrib.x == 0) {
if (ww->wascreen->current_desktop->workarea.x >
ww->attrib.x)
ww->attrib.x =
ww->wascreen->current_desktop->workarea.x;
}
if (ww->attrib.y == 0) {
if (ww->wascreen->current_desktop->workarea.y >
ww->attrib.y)
ww->attrib.y =
ww->wascreen->current_desktop->workarea.y;
}
}
}
XFree(data);
} else {
if (ww->attrib.x == 0) {
if (ww->wascreen->current_desktop->workarea.x > ww->attrib.x)
ww->attrib.x = ww->wascreen->current_desktop->workarea.x;
}
if (ww->attrib.y == 0) {
if (ww->wascreen->current_desktop->workarea.y > ww->attrib.y)
ww->attrib.y = ww->wascreen->current_desktop->workarea.y;
}
}
}
/**
* @fn SetDesktop(WaWindow *ww)
* @brief Write net_wm_desktop hint
*
* Sets _NET_WM_DESKTOP hint to current desktop, if window is not a member
* of the current desktop then hint is set to the lowest desktop number that
* the window is a member of. If window is a member of all desktops then
* hint is set to 0xffffffff.
*
* @param ww WaWindow object
*/
void NetHandler::SetDesktop(WaWindow *ww) {
CARD32 data[1];
data[0] = 0;
if (ww->desktop_mask & (1L << ww->wascreen->current_desktop->number))
data[0] = ww->wascreen->current_desktop->number;
else {
int i;
for (i = 0; i < 16; i++)
if (ww->desktop_mask & (1L << i)) {
data[0] = i;
break;
}
}
if (ww->desktop_mask == ((1L << 16) - 1))
data[0] = 0xffffffff;
XGrabServer(display);
if (validatedrawable(ww->id)) {
XChangeProperty(display, ww->id, net_wm_desktop, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) data, 1);
} else ww->deleted = true;
XUngrabServer(display);
}
/**
* @fn SetDesktopMask(WaWindow *ww)
* @brief Write net_wm_desktop_mask hint
*
* Sets _NET_WM_DESKTOP_MASK hint to the current desktop mask of the window.
*
* @param ww WaWindow object
*/
void NetHandler::SetDesktopMask(WaWindow *ww) {
CARD32 data[1];
data[0] = ww->desktop_mask;
XGrabServer(display);
if (validatedrawable(ww->id)) {
XChangeProperty(display, ww->id, net_wm_desktop_mask, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) data, 1);
} else ww->deleted = true;
XUngrabServer(display);
}
/**
* @fn GetDesktop(WaWindow *ww)
* @brief Reads net_wm_desktop and net_desktop_mask hints
*
* Reads _NET_WM_DESKTOP and _NET_DESKTOP_MASK hints and sets desktop_mask
* for window accordingly.
*
* @param ww WaWindow object
*/
void NetHandler::GetDesktop(WaWindow *ww) {
CARD32 *data;
XGrabServer(display);
if (validatedrawable(ww->id)) {
if (XGetWindowProperty(display, ww->id, net_wm_desktop, 0L, 1L,
false, XA_CARDINAL, &real_type, &real_format,
&items_read, &items_left,
(unsigned char **) &data) == Success &&
items_read) {
if (data[0] == 0xffffffff || data[0] == 0xfffffffe)
ww->desktop_mask = ((1L << 16) - 1);
else if (data[0] < 15 && data[0] >= 0) {
ww->desktop_mask = (1L << data[0]);
}
XFree(data);
}
if (XGetWindowProperty(display, ww->id, net_wm_desktop_mask, 0L, 1L,
false, XA_CARDINAL, &real_type, &real_format,
&items_read, &items_left,
(unsigned char **) &data) == Success &&
items_read) {
ww->desktop_mask = data[0];
XFree(data);
}
} else ww->deleted = true;
XUngrabServer(display);
}
/**
* @fn IsSystrayWindow(Window w)
* @brief Checks if window is systray window
*
* Reads _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR hint to see if window is a systray
* window.
*
* @param w Window to check
*
* @return True if window is systray window, otherwise false
*/
bool NetHandler::IsSystrayWindow(Window w) {
CARD32 *data;
items_read = 0;
XGrabServer(display);
if (validatedrawable(w)) {
if (XGetWindowProperty(display, w, kde_net_wm_system_tray_window_for,
0L, 1L, false, XA_WINDOW, &real_type,
&real_format, &items_read, &items_left,
(unsigned char **) &data) != Success) {
items_read = 0;
}
}
XUngrabServer(display);
return ((items_read)? true: false);
}
/**
* @fn SetSystrayWindows(WaScreen *ws)
* @brief Write kde_net_system_tray_windows hint
*
* Sets _KDE_NET_SYSTEM_TRAY_WINDOWS hint to the current list of systray
* windows.
*
* @param ws WaScreen object
*/
void NetHandler::SetSystrayWindows(WaScreen *ws) {
CARD32 *data;
int i = 0;
data = new CARD32[ws->systray_window_list.size() + 1];
list<Window>::iterator it = ws->systray_window_list.begin();
for (; it != ws->systray_window_list.end(); it++)
data[i++] = *it;
XChangeProperty(display, ws->id, kde_net_system_tray_windows, XA_WINDOW,
32, PropModeReplace, (unsigned char *) data, i);
delete [] data;
}
syntax highlighted by Code2HTML, v. 0.9.1