ede/pekwm/Atoms.cc

374 lines
9.4 KiB
C++

//
// Atoms.cc for pekwm
// Copyright © 2003-2009 Claes Nästén <me@pekdon.net>
//
// This program is licensed under the GNU GPL.
// See the LICENSE file for more information.
//
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H
#include "Atoms.hh"
#include "PScreen.hh"
#include "Util.hh"
extern "C" {
#include <X11/Xutil.h>
}
using std::string;
using std::map;
static const char *atomnames[] = {
// EWMH atoms
"_NET_SUPPORTED",
"_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_DESKTOP_LAYOUT", "_NET_SUPPORTING_WM_CHECK",
"_NET_CLOSE_WINDOW",
"_NET_WM_NAME", "_NET_WM_VISIBLE_NAME",
"_NET_WM_ICON_NAME", "_NET_WM_VISIBLE_ICON_NAME",
"_NET_WM_ICON", "_NET_WM_DESKTOP",
"_NET_WM_STRUT", "_NET_WM_PID",
"_NET_WM_WINDOW_OPACITY",
"_NET_WM_WINDOW_TYPE",
"_NET_WM_WINDOW_TYPE_DESKTOP", "_NET_WM_WINDOW_TYPE_DOCK",
"_NET_WM_WINDOW_TYPE_TOOLBAR", "_NET_WM_WINDOW_TYPE_MENU",
"_NET_WM_WINDOW_TYPE_UTILITY", "_NET_WM_WINDOW_TYPE_SPLASH",
"_NET_WM_WINDOW_TYPE_DIALOG", "_NET_WM_WINDOW_TYPE_NORMAL",
"_NET_WM_STATE",
"_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_ALLOWED_ACTIONS",
"_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",
"UTF8_STRING", // When adding an ewmh atom after this,
// fix setEwmhAtomsSupport(Window)
"STRING", "MANAGER",
// pekwm atoms
"_PEKWM_FRAME_ID",
"_PEKWM_FRAME_ORDER",
"_PEKWM_FRAME_ACTIVE",
"_PEKWM_FRAME_DECOR",
"_PEKWM_FRAME_SKIP",
"_PEKWM_TITLE",
// ICCCM atoms
"WM_NAME",
"WM_ICON_NAME",
"WM_CLASS",
"WM_STATE",
"WM_CHANGE_STATE",
"WM_PROTOCOLS",
"WM_DELETE_WINDOW",
"WM_COLORMAP_WINDOWS",
"WM_TAKE_FOCUS",
"WM_WINDOW_ROLE",
"WM_CLIENT_MACHINE",
// miscellaneous atoms
"_MOTIF_WM_HINTS"
};
//! @brief initialise the atoms mappings
void
Atoms::init(void)
{
const uint num = sizeof(atomnames) / sizeof(char*);
Atom *atoms = new Atom[num];
XInternAtoms(PScreen::instance()->getDpy(),
const_cast<char**>(atomnames), num, 0, atoms);
for (uint i = 0; i < num; ++i) {
_atoms[AtomName(i)] = atoms[i];
}
delete [] atoms;
}
//! @brief Builds a array of all atoms in the map.
void
Atoms::setEwmhAtomsSupport(Window win)
{
Atom *atoms = new Atom[UTF8_STRING+1];
for (uint i = 0; i <= UTF8_STRING; ++i) {
atoms[i] = _atoms[AtomName(i)];
}
AtomUtil::setAtoms(win, getAtom(NET_SUPPORTED), atoms, UTF8_STRING+1);
delete [] atoms;
}
std::map<AtomName, Atom> Atoms::_atoms;
namespace AtomUtil {
//! @brief Get unknown property
bool
getProperty(Window win, Atom atom, Atom type,
ulong expected, uchar** data, ulong *actual)
{
Atom r_type;
int r_format, status;
ulong read = 0, left = 0;
*data = 0;
do {
if (*data) {
XFree(*data);
*data = 0;
}
expected += left;
status =
XGetWindowProperty(PScreen::instance()->getDpy(), win, atom,
0L, expected, False, type,
&r_type, &r_format, &read, &left, data);
if (status != Success || type != r_type || read == 0) {
if (*data) {
XFree(*data);
*data = 0;
}
left = 0;
}
} while (left);
if (actual) {
*actual = read;
}
return (*data != 0);
}
//! @brief Set XA_ATOM, one value
void
setAtom(Window win, Atom atom, Atom value)
{
XChangeProperty(PScreen::instance()->getDpy(), win, atom, XA_ATOM, 32,
PropModeReplace, (uchar *) &value, 1);
}
//! @brief Set XA_ATOM, multiple values
void
setAtoms(Window win, Atom atom, Atom *values, int size)
{
XChangeProperty(PScreen::instance()->getDpy(), win, atom, XA_ATOM, 32,
PropModeReplace, (uchar *) values, size);
}
//! @brief Set XA_WINDOW, one value
void
setWindow(Window win, Atom atom, Window value)
{
XChangeProperty(PScreen::instance()->getDpy(), win, atom, XA_WINDOW, 32,
PropModeReplace, (uchar *) &value, 1);
}
//! @brief Set XA_WINDOW, multiple values
void
setWindows(Window win, Atom atom, Window *values, int size)
{
XChangeProperty(PScreen::instance()->getDpy(), win, atom, XA_WINDOW, 32,
PropModeReplace, (uchar *) values, size);
}
//! @brief Get XA_CARDINAL
bool
getLong(Window win, Atom atom, long &value)
{
long *data = 0;
uchar *udata = 0;
if (getProperty(win, atom, XA_CARDINAL, 1L, &udata, 0)) {
data = reinterpret_cast<long*>(udata);
value = *data;
XFree(udata);
return true;
}
return false;
}
//! @brief Set XA_CARDINAL
void
setLong(Window win, Atom atom, long value)
{
XChangeProperty(PScreen::instance()->getDpy(), win, atom, XA_CARDINAL, 32,
PropModeReplace, (uchar *) &value, 1);
}
/**
* Set array of longs as Cardinal/32.
*
* @param win Window to set longs on.
* @param atom Atom to set longs as.
* @param values Array of longs to set.
* @param size Number of elements in array.
*/
void
setLongs(Window win, Atom atom, long *values, int size)
{
XChangeProperty(PScreen::instance()->getDpy(), win, atom, XA_CARDINAL, 32,
PropModeReplace, reinterpret_cast<unsigned char*>(values), size);
}
//! @brief Get XA_STRING property
bool
getString(Window win, Atom atom, string &value)
{
uchar *data = 0;
if (getProperty(win, atom, XA_STRING, 64L, &data, 0)) {
value = string((const char*) data);
XFree(data);
return true;
}
return false;
}
//! @brief Get UTF-8 string.
bool
getUtf8String(Window win, Atom atom, std::wstring &value)
{
bool status = false;
unsigned char *data = 0;
if (getProperty(win, atom, Atoms::getAtom(UTF8_STRING),
32, &data, 0)) {
status = true;
string utf8_str(reinterpret_cast<char*>(data));
value = Util::from_utf8_str(utf8_str);
XFree(data);
}
return status;
}
//! @brief Set UTF-8 string.
void
setUtf8String(Window win, Atom atom, const std::wstring &value)
{
string utf8_string(Util::to_utf8_str(value));
XChangeProperty(PScreen::instance()->getDpy(), win, atom,
Atoms::getAtom(UTF8_STRING), 8,
PropModeReplace,
reinterpret_cast<const uchar*>(utf8_string.c_str()),
utf8_string.size());
}
/**
* Set array of UTF-8 strings.
*
* @param win Window to set string on.
* @param atom Atom to set array value.
* @param values Array of strings.
* @param length Number of elements in value.
*/
void
setUtf8StringArray(Window win, Atom atom, unsigned char *values, unsigned int length)
{
XChangeProperty(PScreen::instance()->getDpy(), win, atom, Atoms::getAtom(UTF8_STRING),
8, PropModeReplace, values, length);
}
//! @brief Set XA_STRING property
void
setString(Window win, Atom atom, const string &value)
{
XChangeProperty(PScreen::instance()->getDpy(), win, atom, XA_STRING, 8,
PropModeReplace, (uchar*) value.c_str(), value.size());
}
/**
* Read text property.
*
* @param win Window to get property from.
* @param atom Atom holding the property.
* @param value Return string.
* @return true if property was successfully read.
*/
bool
getTextProperty(Window win, Atom atom, std::string &value)
{
// Read text property, return if it fails.
XTextProperty text_property;
if (! XGetTextProperty(PScreen::instance()->getDpy(), win, &text_property, atom)
|| ! text_property.value || ! text_property.nitems) {
return false;
}
if (text_property.encoding == XA_STRING) {
value = reinterpret_cast<const char*>(text_property.value);
} else {
char **mb_list;
int num;
XmbTextPropertyToTextList(PScreen::instance()->getDpy(), &text_property, &mb_list, &num);
if (mb_list && num > 0) {
value = *mb_list;
XFreeStringList(mb_list);
}
}
XFree(text_property.value);
return true;
}
//! @brief
void*
getEwmhPropData(Window win, Atom prop, Atom type, int &num)
{
Atom type_ret;
int format_ret;
ulong items_ret, after_ret;
uchar *prop_data = 0;
XGetWindowProperty(PScreen::instance()->getDpy(), win, prop, 0, 0x7fffffff,
False, type, &type_ret, &format_ret, &items_ret,
&after_ret, &prop_data);
num = items_ret;
return prop_data;
}
/**
* Remove property from window.
*/
void
unsetProperty(Window win, Atom prop)
{
XDeleteProperty(PScreen::instance()->getDpy(), win, prop);
}
} // end namespace AtomUtil