mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
374 lines
9.4 KiB
C++
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
|