diff --git a/Makefile.am b/Makefile.am index 9e8316f8..76f84542 100644 --- a/Makefile.am +++ b/Makefile.am @@ -137,6 +137,8 @@ obt_libobt_la_SOURCES = \ obt/display.c \ obt/mainloop.h \ obt/mainloop.c \ + obt/prop.h \ + obt/prop.c \ obt/util.h ## openbox ## diff --git a/obt/Makefile b/obt/Makefile new file mode 100644 index 00000000..b90edacf --- /dev/null +++ b/obt/Makefile @@ -0,0 +1,4 @@ +all clean install: + $(MAKE) -C .. -$(MAKEFLAGS) $@ + +.PHONY: all clean install diff --git a/obt/display.c b/obt/display.c index d9966780..6993addb 100644 --- a/obt/display.c +++ b/obt/display.c @@ -17,6 +17,7 @@ */ #include "obt/display.h" +#include "obt/prop.h" #ifdef HAVE_STRING_H # include @@ -28,6 +29,8 @@ # include #endif +Display* obt_display = NULL; + gboolean obt_display_error_occured = FALSE; gboolean obt_display_extension_xkb = FALSE; @@ -45,13 +48,13 @@ static gint xerror_handler(Display *d, XErrorEvent *e); static gboolean xerror_ignore = FALSE; -Display* obt_display_open(const char *display_name) +gboolean obt_display_open(const char *display_name) { gchar *n; Display *d = NULL; n = display_name ? g_strdup(display_name) : NULL; - d = XOpenDisplay(n); + obt_display = d = XOpenDisplay(n); if (d) { gint junk; (void)junk; @@ -103,15 +106,17 @@ Display* obt_display_open(const char *display_name) g_message("X Sync extension is not present on the server or is an " "incompatible version"); #endif + + obt_prop_startup(); } g_free(n); - return d; + return obt_display != NULL; } -void obt_display_close(Display *d) +void obt_display_close() { - if (d) XCloseDisplay(d); + if (obt_display) XCloseDisplay(obt_display); } static gint xerror_handler(Display *d, XErrorEvent *e) @@ -135,9 +140,9 @@ static gint xerror_handler(Display *d, XErrorEvent *e) return 0; } -void obt_display_ignore_errors(Display *d, gboolean ignore) +void obt_display_ignore_errors(gboolean ignore) { - XSync(d, FALSE); + XSync(obt_display, FALSE); xerror_ignore = ignore; if (ignore) obt_display_error_occured = FALSE; } diff --git a/obt/display.h b/obt/display.h index b4a13c7c..5626f268 100644 --- a/obt/display.h +++ b/obt/display.h @@ -54,10 +54,12 @@ extern gint obt_display_extension_randr_basep; extern gboolean obt_display_extension_sync; extern gint obt_display_extension_sync_basep; -Display* obt_display_open(const char *display_name); -void obt_display_close(Display *d); +extern Display* obt_display; -void obt_display_ignore_errors(Display *d, gboolean ignore); +gboolean obt_display_open(const char *display_name); +void obt_display_close(); + +void obt_display_ignore_errors(gboolean ignore); G_END_DECLS diff --git a/obt/prop.c b/obt/prop.c new file mode 100644 index 00000000..a7e598ff --- /dev/null +++ b/obt/prop.c @@ -0,0 +1,454 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + obt/prop.c for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#include "obt/prop.h" +#include "obt/display.h" + +#include +#ifdef HAVE_STRING_H +# include +#endif + +Atom prop_atoms[OBT_PROP_NUM_ATOMS]; +gboolean prop_started = FALSE; + +#define CREATE(var, name) (prop_atoms[OBT_PROP_##var] = \ + XInternAtom((obt_display), (name), FALSE)) + +void obt_prop_startup() +{ + if (prop_started) return; + prop_started = TRUE; + + g_assert(obt_display); + + CREATE(CARDINAL, "CARDINAL"); + CREATE(WINDOW, "WINDOW"); + CREATE(PIXMAP, "PIXMAP"); + CREATE(ATOM, "ATOM"); + CREATE(STRING, "STRING"); + CREATE(UTF8, "UTF8_STRING"); + + CREATE(MANAGER, "MANAGER"); + + CREATE(WM_COLORMAP_WINDOWS, "WM_COLORMAP_WINDOWS"); + CREATE(WM_PROTOCOLS, "WM_PROTOCOLS"); + CREATE(WM_STATE, "WM_STATE"); + CREATE(WM_CHANGE_STATE, "WM_CHANGE_STATE"); + CREATE(WM_DELETE_WINDOW, "WM_DELETE_WINDOW"); + CREATE(WM_TAKE_FOCUS, "WM_TAKE_FOCUS"); + CREATE(WM_NAME, "WM_NAME"); + CREATE(WM_ICON_NAME, "WM_ICON_NAME"); + CREATE(WM_CLASS, "WM_CLASS"); + CREATE(WM_WINDOW_ROLE, "WM_WINDOW_ROLE"); + CREATE(WM_CLIENT_MACHINE, "WM_CLIENT_MACHINE"); + CREATE(WM_COMMAND, "WM_COMMAND"); + CREATE(WM_CLIENT_LEADER, "WM_CLIENT_LEADER"); + CREATE(MOTIF_WM_HINTS, "_MOTIF_WM_HINTS"); + + CREATE(SM_CLIENT_ID, "SM_CLIENT_ID"); + + CREATE(NET_WM_FULL_PLACEMENT, "_NET_WM_FULL_PLACEMENT"); + + CREATE(NET_SUPPORTED, "_NET_SUPPORTED"); + CREATE(NET_CLIENT_LIST, "_NET_CLIENT_LIST"); + CREATE(NET_CLIENT_LIST_STACKING, "_NET_CLIENT_LIST_STACKING"); + CREATE(NET_NUMBER_OF_DESKTOPS, "_NET_NUMBER_OF_DESKTOPS"); + CREATE(NET_DESKTOP_GEOMETRY, "_NET_DESKTOP_GEOMETRY"); + CREATE(NET_DESKTOP_VIEWPORT, "_NET_DESKTOP_VIEWPORT"); + CREATE(NET_CURRENT_DESKTOP, "_NET_CURRENT_DESKTOP"); + CREATE(NET_DESKTOP_NAMES, "_NET_DESKTOP_NAMES"); + CREATE(NET_ACTIVE_WINDOW, "_NET_ACTIVE_WINDOW"); +/* CREATE(NET_RESTACK_WINDOW, "_NET_RESTACK_WINDOW");*/ + CREATE(NET_WORKAREA, "_NET_WORKAREA"); + CREATE(NET_SUPPORTING_WM_CHECK, "_NET_SUPPORTING_WM_CHECK"); + CREATE(NET_DESKTOP_LAYOUT, "_NET_DESKTOP_LAYOUT"); + CREATE(NET_SHOWING_DESKTOP, "_NET_SHOWING_DESKTOP"); + + CREATE(NET_CLOSE_WINDOW, "_NET_CLOSE_WINDOW"); + CREATE(NET_WM_MOVERESIZE, "_NET_WM_MOVERESIZE"); + CREATE(NET_MOVERESIZE_WINDOW, "_NET_MOVERESIZE_WINDOW"); + CREATE(NET_REQUEST_FRAME_EXTENTS, "_NET_REQUEST_FRAME_EXTENTS"); + CREATE(NET_RESTACK_WINDOW, "_NET_RESTACK_WINDOW"); + + CREATE(NET_STARTUP_ID, "_NET_STARTUP_ID"); + + CREATE(NET_WM_NAME, "_NET_WM_NAME"); + CREATE(NET_WM_VISIBLE_NAME, "_NET_WM_VISIBLE_NAME"); + CREATE(NET_WM_ICON_NAME, "_NET_WM_ICON_NAME"); + CREATE(NET_WM_VISIBLE_ICON_NAME, "_NET_WM_VISIBLE_ICON_NAME"); + CREATE(NET_WM_DESKTOP, "_NET_WM_DESKTOP"); + CREATE(NET_WM_WINDOW_TYPE, "_NET_WM_WINDOW_TYPE"); + CREATE(NET_WM_STATE, "_NET_WM_STATE"); + CREATE(NET_WM_STRUT, "_NET_WM_STRUT"); + CREATE(NET_WM_STRUT_PARTIAL, "_NET_WM_STRUT_PARTIAL"); + CREATE(NET_WM_ICON, "_NET_WM_ICON"); + CREATE(NET_WM_ICON_GEOMETRY, "_NET_WM_ICON_GEOMETRY"); +/* CREATE(NET_WM_PId, "_NET_WM_PID"); */ + CREATE(NET_WM_ALLOWED_ACTIONS, "_NET_WM_ALLOWED_ACTIONS"); + CREATE(NET_WM_USER_TIME, "_NET_WM_USER_TIME"); + CREATE(NET_WM_USER_TIME_WINDOW, "_NET_WM_USER_TIME_WINDOW"); + CREATE(KDE_NET_WM_FRAME_STRUT, "_KDE_NET_WM_FRAME_STRUT"); + CREATE(NET_FRAME_EXTENTS, "_NET_FRAME_EXTENTS"); + +/* CREATE(NET_WM_PING, "_NET_WM_PING"); */ +#ifdef SYNC + CREATE(NET_WM_SYNC_REQUEST, "_NET_WM_SYNC_REQUEST"); + CREATE(NET_WM_SYNC_REQUEST_COUNTER, "_NET_WM_SYNC_REQUEST_COUNTER"); +#endif + + CREATE(NET_WM_WINDOW_TYPE_DESKTOP, "_NET_WM_WINDOW_TYPE_DESKTOP"); + CREATE(NET_WM_WINDOW_TYPE_DOCK, "_NET_WM_WINDOW_TYPE_DOCK"); + CREATE(NET_WM_WINDOW_TYPE_TOOLBAR, "_NET_WM_WINDOW_TYPE_TOOLBAR"); + CREATE(NET_WM_WINDOW_TYPE_MENU, "_NET_WM_WINDOW_TYPE_MENU"); + CREATE(NET_WM_WINDOW_TYPE_UTILITY, "_NET_WM_WINDOW_TYPE_UTILITY"); + CREATE(NET_WM_WINDOW_TYPE_SPLASH, "_NET_WM_WINDOW_TYPE_SPLASH"); + CREATE(NET_WM_WINDOW_TYPE_DIALOG, "_NET_WM_WINDOW_TYPE_DIALOG"); + CREATE(NET_WM_WINDOW_TYPE_NORMAL, "_NET_WM_WINDOW_TYPE_NORMAL"); + + prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOPLEFT] = 0; + prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOP] = 1; + prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOPRIGHT] = 2; + prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_RIGHT] = 3; + prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT] = 4; + prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOM] = 5; + prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT] = 6; + prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_LEFT] = 7; + prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_MOVE] = 8; + prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_SIZE_KEYBOARD] = 9; + prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_MOVE_KEYBOARD] = 10; + prop_atoms[OBT_PROP_NET_WM_MOVERESIZE_CANCEL] = 11; + + CREATE(NET_WM_ACTION_MOVE, "_NET_WM_ACTION_MOVE"); + CREATE(NET_WM_ACTION_RESIZE, "_NET_WM_ACTION_RESIZE"); + CREATE(NET_WM_ACTION_MINIMIZE, "_NET_WM_ACTION_MINIMIZE"); + CREATE(NET_WM_ACTION_SHADE, "_NET_WM_ACTION_SHADE"); + CREATE(NET_WM_ACTION_MAXIMIZE_HORZ, "_NET_WM_ACTION_MAXIMIZE_HORZ"); + CREATE(NET_WM_ACTION_MAXIMIZE_VERT, "_NET_WM_ACTION_MAXIMIZE_VERT"); + CREATE(NET_WM_ACTION_FULLSCREEN, "_NET_WM_ACTION_FULLSCREEN"); + CREATE(NET_WM_ACTION_CHANGE_DESKTOP, "_NET_WM_ACTION_CHANGE_DESKTOP"); + CREATE(NET_WM_ACTION_CLOSE, "_NET_WM_ACTION_CLOSE"); + CREATE(NET_WM_ACTION_ABOVE, "_NET_WM_ACTION_ABOVE"); + CREATE(NET_WM_ACTION_BELOW, "_NET_WM_ACTION_BELOW"); + + CREATE(NET_WM_STATE_MODAL, "_NET_WM_STATE_MODAL"); +/* CREATE(NET_WM_STATE_STICKY, "_NET_WM_STATE_STICKY");*/ + CREATE(NET_WM_STATE_MAXIMIZED_VERT, "_NET_WM_STATE_MAXIMIZED_VERT"); + CREATE(NET_WM_STATE_MAXIMIZED_HORZ, "_NET_WM_STATE_MAXIMIZED_HORZ"); + CREATE(NET_WM_STATE_SHADED, "_NET_WM_STATE_SHADED"); + CREATE(NET_WM_STATE_SKIP_TASKBAR, "_NET_WM_STATE_SKIP_TASKBAR"); + CREATE(NET_WM_STATE_SKIP_PAGER, "_NET_WM_STATE_SKIP_PAGER"); + CREATE(NET_WM_STATE_HIDDEN, "_NET_WM_STATE_HIDDEN"); + CREATE(NET_WM_STATE_FULLSCREEN, "_NET_WM_STATE_FULLSCREEN"); + CREATE(NET_WM_STATE_ABOVE, "_NET_WM_STATE_ABOVE"); + CREATE(NET_WM_STATE_BELOW, "_NET_WM_STATE_BELOW"); + CREATE(NET_WM_STATE_DEMANDS_ATTENTION, "_NET_WM_STATE_DEMANDS_ATTENTION"); + + prop_atoms[OBT_PROP_NET_WM_STATE_ADD] = 1; + prop_atoms[OBT_PROP_NET_WM_STATE_REMOVE] = 0; + prop_atoms[OBT_PROP_NET_WM_STATE_TOGGLE] = 2; + + prop_atoms[OBT_PROP_NET_WM_ORIENTATION_HORZ] = 0; + prop_atoms[OBT_PROP_NET_WM_ORIENTATION_VERT] = 1; + prop_atoms[OBT_PROP_NET_WM_TOPLEFT] = 0; + prop_atoms[OBT_PROP_NET_WM_TOPRIGHT] = 1; + prop_atoms[OBT_PROP_NET_WM_BOTTOMRIGHT] = 2; + prop_atoms[OBT_PROP_NET_WM_BOTTOMLEFT] = 3; + + CREATE(KDE_WM_CHANGE_STATE, "_KDE_WM_CHANGE_STATE"); + CREATE(KDE_NET_WM_WINDOW_TYPE_OVERRIDE,"_KDE_NET_WM_WINDOW_TYPE_OVERRIDE"); + +/* + CREATE(ROOTPMAPId, "_XROOTPMAP_ID"); + CREATE(ESETROOTId, "ESETROOT_PMAP_ID"); +*/ + + CREATE(OPENBOX_PID, "_OPENBOX_PID"); + CREATE(OB_THEME, "_OB_THEME"); + CREATE(OB_WM_ACTION_UNDECORATE, "_OB_WM_ACTION_UNDECORATE"); + CREATE(OB_WM_STATE_UNDECORATED, "_OB_WM_STATE_UNDECORATED"); + CREATE(OB_CONTROL, "_OB_CONTROL"); +} + +Atom obt_prop_atom(ObtPropAtom a) +{ + g_assert(prop_started); + g_assert(a < OBT_PROP_NUM_ATOMS); + return prop_atoms[a]; +} + +static gboolean get_prealloc(Window win, Atom prop, Atom type, gint size, + guchar *data, gulong num) +{ + gboolean ret = FALSE; + gint res; + guchar *xdata = NULL; + Atom ret_type; + gint ret_size; + gulong ret_items, bytes_left; + glong num32 = 32 / size * num; /* num in 32-bit elements */ + + res = XGetWindowProperty(obt_display, win, prop, 0l, num32, + FALSE, type, &ret_type, &ret_size, + &ret_items, &bytes_left, &xdata); + if (res == Success && ret_items && xdata) { + if (ret_size == size && ret_items >= num) { + guint i; + for (i = 0; i < num; ++i) + switch (size) { + case 8: + data[i] = xdata[i]; + break; + case 16: + ((guint16*)data)[i] = ((gushort*)xdata)[i]; + break; + case 32: + ((guint32*)data)[i] = ((gulong*)xdata)[i]; + break; + default: + g_assert_not_reached(); /* unhandled size */ + } + ret = TRUE; + } + XFree(xdata); + } + return ret; +} + +static gboolean get_all(Window win, Atom prop, Atom type, gint size, + guchar **data, guint *num) +{ + gboolean ret = FALSE; + gint res; + guchar *xdata = NULL; + Atom ret_type; + gint ret_size; + gulong ret_items, bytes_left; + + res = XGetWindowProperty(obt_display, win, prop, 0l, G_MAXLONG, + FALSE, type, &ret_type, &ret_size, + &ret_items, &bytes_left, &xdata); + if (res == Success) { + if (ret_size == size && ret_items > 0) { + guint i; + + *data = g_malloc(ret_items * (size / 8)); + for (i = 0; i < ret_items; ++i) + switch (size) { + case 8: + (*data)[i] = xdata[i]; + break; + case 16: + ((guint16*)*data)[i] = ((gushort*)xdata)[i]; + break; + case 32: + ((guint32*)*data)[i] = ((gulong*)xdata)[i]; + break; + default: + g_assert_not_reached(); /* unhandled size */ + } + *num = ret_items; + ret = TRUE; + } + XFree(xdata); + } + return ret; +} + +static gboolean get_stringlist(Window win, Atom prop, gchar ***list, gint *nstr) +{ + XTextProperty tprop; + gboolean ret = FALSE; + + if (XGetTextProperty(obt_display, win, &tprop, prop) && tprop.nitems) { + if (XTextPropertyToStringList(&tprop, list, nstr)) + ret = TRUE; + XFree(tprop.value); + } + return ret; +} + +gboolean obt_prop_get32(Window win, Atom prop, Atom type, guint32 *ret) +{ + return get_prealloc(win, prop, type, 32, (guchar*)ret, 1); +} + +gboolean obt_prop_get_array32(Window win, Atom prop, Atom type, guint32 **ret, + guint *nret) +{ + return get_all(win, prop, type, 32, (guchar**)ret, nret); +} + +gboolean obt_prop_get_string_locale(Window win, Atom prop, gchar **ret) +{ + gchar **list; + gint nstr; + gchar *s; + + if (get_stringlist(win, prop, &list, &nstr) && nstr) { + s = g_locale_to_utf8(list[0], -1, NULL, NULL, NULL); + XFreeStringList(list); + if (s) { + *ret = s; + return TRUE; + } + } + return FALSE; +} + +gboolean obt_prop_get_strings_locale(Window win, Atom prop, gchar ***ret) +{ + GSList *strs = NULL, *it; + gchar *raw, *p; + guint num, i, count = 0; + + if (get_all(win, prop, obt_prop_atom(OBT_PROP_STRING), 8, + (guchar**)&raw, &num)) + { + p = raw; + while (p < raw + num) { + ++count; + strs = g_slist_append(strs, p); + p += strlen(p) + 1; /* next string */ + } + + *ret = g_new0(gchar*, count + 1); + (*ret)[count] = NULL; /* null terminated list */ + + for (i = 0, it = strs; it; ++i, it = g_slist_next(it)) { + (*ret)[i] = g_locale_to_utf8(it->data, -1, NULL, NULL, NULL); + /* make sure translation did not fail */ + if (!(*ret)[i]) + (*ret)[i] = g_strdup(""); + } + g_free(raw); + g_slist_free(strs); + return TRUE; + } + return FALSE; +} + +gboolean obt_prop_get_string_utf8(Window win, Atom prop, gchar **ret) +{ + gchar *raw; + gchar *str; + guint num; + + if (get_all(win, prop, obt_prop_atom(OBT_PROP_UTF8), 8, + (guchar**)&raw, &num)) + { + str = g_strndup(raw, num); /* grab the first string from the list */ + g_free(raw); + if (g_utf8_validate(str, -1, NULL)) { + *ret = str; + return TRUE; + } + g_free(str); + } + return FALSE; +} + +gboolean obt_prop_get_strings_utf8(Window win, Atom prop, gchar ***ret) +{ + GSList *strs = NULL, *it; + gchar *raw, *p; + guint num, i, count = 0; + + if (get_all(win, prop, obt_prop_atom(OBT_PROP_UTF8), 8, + (guchar**)&raw, &num)) + { + p = raw; + while (p < raw + num) { + ++count; + strs = g_slist_append(strs, p); + p += strlen(p) + 1; /* next string */ + } + + *ret = g_new0(gchar*, count + 1); + + for (i = 0, it = strs; it; ++i, it = g_slist_next(it)) { + if (g_utf8_validate(it->data, -1, NULL)) + (*ret)[i] = g_strdup(it->data); + else + (*ret)[i] = g_strdup(""); + } + g_free(raw); + g_slist_free(strs); + return TRUE; + } + return FALSE; +} + +void obt_prop_set32(Window win, Atom prop, Atom type, gulong val) +{ + XChangeProperty(obt_display, win, prop, type, 32, PropModeReplace, + (guchar*)&val, 1); +} + +void obt_prop_set_array32(Window win, Atom prop, Atom type, gulong *val, + guint num) +{ + XChangeProperty(obt_display, win, prop, type, 32, PropModeReplace, + (guchar*)val, num); +} + +void obt_prop_set_string_utf8(Window win, Atom prop, const gchar *val) +{ + XChangeProperty(obt_display, win, prop, obt_prop_atom(OBT_PROP_UTF8), 8, + PropModeReplace, (const guchar*)val, strlen(val)); +} + +void obt_prop_set_strings_utf8(Window win, Atom prop, gchar **strs) +{ + GString *str; + gchar **s; + + str = g_string_sized_new(0); + for (s = strs; *s; ++s) { + str = g_string_append(str, *s); + str = g_string_append_c(str, '\0'); + } + XChangeProperty(obt_display, win, prop, obt_prop_atom(OBT_PROP_UTF8), 8, + PropModeReplace, (guchar*)str->str, str->len); + g_string_free(str, TRUE); +} + +void obt_prop_erase(Window win, Atom prop) +{ + XDeleteProperty(obt_display, win, prop); +} + +void obt_prop_message(gint screen, Window about, Atom messagetype, + glong data0, glong data1, glong data2, glong data3, + glong data4, glong mask) +{ + XEvent ce; + ce.xclient.type = ClientMessage; + ce.xclient.message_type = messagetype; + ce.xclient.display = obt_display; + ce.xclient.window = about; + ce.xclient.format = 32; + ce.xclient.data.l[0] = data0; + ce.xclient.data.l[1] = data1; + ce.xclient.data.l[2] = data2; + ce.xclient.data.l[3] = data3; + ce.xclient.data.l[4] = data4; + XSendEvent(obt_display, RootWindow(obt_display, screen), FALSE, + mask, &ce); +} diff --git a/obt/prop.h b/obt/prop.h new file mode 100644 index 00000000..128f2dc1 --- /dev/null +++ b/obt/prop.h @@ -0,0 +1,256 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + obt/prop.h for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#ifndef __obt_prop_h +#define __obt_prop_h + +#include +#include + +G_BEGIN_DECLS + +typedef enum { + /* types */ + OBT_PROP_CARDINAL, /*!< The atom which represents the Cardinal data type */ + OBT_PROP_WINDOW, /*!< The atom which represents window ids */ + OBT_PROP_PIXMAP, /*!< The atom which represents pixmap ids */ + OBT_PROP_ATOM, /*!< The atom which represents atom values */ + OBT_PROP_STRING, /*!< The atom which represents ascii strings */ + OBT_PROP_UTF8, /*!< The atom which represents utf8-encoded strings */ + + /* selection stuff */ + OBT_PROP_MANAGER, + + /* window hints */ + OBT_PROP_WM_COLORMAP_WINDOWS, + OBT_PROP_WM_PROTOCOLS, + OBT_PROP_WM_STATE, + OBT_PROP_WM_DELETE_WINDOW, + OBT_PROP_WM_TAKE_FOCUS, + OBT_PROP_WM_CHANGE_STATE, + OBT_PROP_WM_NAME, + OBT_PROP_WM_ICON_NAME, + OBT_PROP_WM_CLASS, + OBT_PROP_WM_WINDOW_ROLE, + OBT_PROP_WM_CLIENT_MACHINE, + OBT_PROP_WM_COMMAND, + OBT_PROP_WM_CLIENT_LEADER, + OBT_PROP_MOTIF_WM_HINTS, + + /* SM atoms */ + OBT_PROP_SM_CLIENT_ID, + + /* NETWM atoms */ + + /* Atoms that are used inside messages - these don't go in net_supported */ + + OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOPLEFT, + OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOP, + OBT_PROP_NET_WM_MOVERESIZE_SIZE_TOPRIGHT, + OBT_PROP_NET_WM_MOVERESIZE_SIZE_RIGHT, + OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT, + OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOM, + OBT_PROP_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT, + OBT_PROP_NET_WM_MOVERESIZE_SIZE_LEFT, + OBT_PROP_NET_WM_MOVERESIZE_MOVE, + OBT_PROP_NET_WM_MOVERESIZE_SIZE_KEYBOARD, + OBT_PROP_NET_WM_MOVERESIZE_MOVE_KEYBOARD, + OBT_PROP_NET_WM_MOVERESIZE_CANCEL, + + OBT_PROP_NET_WM_STATE_ADD, + OBT_PROP_NET_WM_STATE_REMOVE, + OBT_PROP_NET_WM_STATE_TOGGLE, + + OBT_PROP_NET_WM_ORIENTATION_HORZ, + OBT_PROP_NET_WM_ORIENTATION_VERT, + OBT_PROP_NET_WM_TOPLEFT, + OBT_PROP_NET_WM_TOPRIGHT, + OBT_PROP_NET_WM_BOTTOMRIGHT, + OBT_PROP_NET_WM_BOTTOMLEFT, + + /* Everything below here must go in net_supported on the root window */ + + /* root window properties */ + OBT_PROP_NET_SUPPORTED, + OBT_PROP_NET_CLIENT_LIST, + OBT_PROP_NET_CLIENT_LIST_STACKING, + OBT_PROP_NET_NUMBER_OF_DESKTOPS, + OBT_PROP_NET_DESKTOP_GEOMETRY, + OBT_PROP_NET_DESKTOP_VIEWPORT, + OBT_PROP_NET_CURRENT_DESKTOP, + OBT_PROP_NET_DESKTOP_NAMES, + OBT_PROP_NET_ACTIVE_WINDOW, +/* Atom net_restack_window;*/ + OBT_PROP_NET_WORKAREA, + OBT_PROP_NET_SUPPORTING_WM_CHECK, + OBT_PROP_NET_DESKTOP_LAYOUT, + OBT_PROP_NET_SHOWING_DESKTOP, + + /* root window messages */ + OBT_PROP_NET_CLOSE_WINDOW, + OBT_PROP_NET_WM_MOVERESIZE, + OBT_PROP_NET_MOVERESIZE_WINDOW, + OBT_PROP_NET_REQUEST_FRAME_EXTENTS, + OBT_PROP_NET_RESTACK_WINDOW, + + /* helpful hints to apps that aren't used for anything */ + OBT_PROP_NET_WM_FULL_PLACEMENT, + + /* startup-notification extension */ + OBT_PROP_NET_STARTUP_ID, + + /* application window properties */ + OBT_PROP_NET_WM_NAME, + OBT_PROP_NET_WM_VISIBLE_NAME, + OBT_PROP_NET_WM_ICON_NAME, + OBT_PROP_NET_WM_VISIBLE_ICON_NAME, + OBT_PROP_NET_WM_DESKTOP, + OBT_PROP_NET_WM_WINDOW_TYPE, + OBT_PROP_NET_WM_STATE, + OBT_PROP_NET_WM_STRUT, + OBT_PROP_NET_WM_STRUT_PARTIAL, + OBT_PROP_NET_WM_ICON, + OBT_PROP_NET_WM_ICON_GEOMETRY, +/* OBT_PROP_NET_WM_PID, */ + OBT_PROP_NET_WM_ALLOWED_ACTIONS, + OBT_PROP_NET_WM_USER_TIME, + OBT_PROP_NET_WM_USER_TIME_WINDOW, + OBT_PROP_NET_FRAME_EXTENTS, + + /* application protocols */ +/* OBT_PROP_NET_WM_PING, */ +#ifdef SYNC + OBT_PROP_NET_WM_SYNC_REQUEST, + OBT_PROP_NET_WM_SYNC_REQUEST_COUNTER, +#endif + + OBT_PROP_NET_WM_WINDOW_TYPE_DESKTOP, + OBT_PROP_NET_WM_WINDOW_TYPE_DOCK, + OBT_PROP_NET_WM_WINDOW_TYPE_TOOLBAR, + OBT_PROP_NET_WM_WINDOW_TYPE_MENU, + OBT_PROP_NET_WM_WINDOW_TYPE_UTILITY, + OBT_PROP_NET_WM_WINDOW_TYPE_SPLASH, + OBT_PROP_NET_WM_WINDOW_TYPE_DIALOG, + OBT_PROP_NET_WM_WINDOW_TYPE_NORMAL, + + OBT_PROP_NET_WM_ACTION_MOVE, + OBT_PROP_NET_WM_ACTION_RESIZE, + OBT_PROP_NET_WM_ACTION_MINIMIZE, + OBT_PROP_NET_WM_ACTION_SHADE, +/* OBT_PROP_NET_WM_ACTION_STICK,*/ + OBT_PROP_NET_WM_ACTION_MAXIMIZE_HORZ, + OBT_PROP_NET_WM_ACTION_MAXIMIZE_VERT, + OBT_PROP_NET_WM_ACTION_FULLSCREEN, + OBT_PROP_NET_WM_ACTION_CHANGE_DESKTOP, + OBT_PROP_NET_WM_ACTION_CLOSE, + OBT_PROP_NET_WM_ACTION_ABOVE, + OBT_PROP_NET_WM_ACTION_BELOW, + + OBT_PROP_NET_WM_STATE_MODAL, +/* OBT_PROP_NET_WM_STATE_STICKY,*/ + OBT_PROP_NET_WM_STATE_MAXIMIZED_VERT, + OBT_PROP_NET_WM_STATE_MAXIMIZED_HORZ, + OBT_PROP_NET_WM_STATE_SHADED, + OBT_PROP_NET_WM_STATE_SKIP_TASKBAR, + OBT_PROP_NET_WM_STATE_SKIP_PAGER, + OBT_PROP_NET_WM_STATE_HIDDEN, + OBT_PROP_NET_WM_STATE_FULLSCREEN, + OBT_PROP_NET_WM_STATE_ABOVE, + OBT_PROP_NET_WM_STATE_BELOW, + OBT_PROP_NET_WM_STATE_DEMANDS_ATTENTION, + + /* KDE atoms */ + + OBT_PROP_KDE_WM_CHANGE_STATE, + OBT_PROP_KDE_NET_WM_FRAME_STRUT, + OBT_PROP_KDE_NET_WM_WINDOW_TYPE_OVERRIDE, + +/* + OBT_PROP_ROOTPMAPID, + OBT_PROP_ESETROOTID, +*/ + + /* Openbox specific atoms */ + + OBT_PROP_OB_WM_ACTION_UNDECORATE, + OBT_PROP_OB_WM_STATE_UNDECORATED, + OBT_PROP_OPENBOX_PID, /* this is depreecated in favour of ob_control */ + OBT_PROP_OB_THEME, + OBT_PROP_OB_CONTROL, + + OBT_PROP_NUM_ATOMS +} ObtPropAtom; + +#define OB_PROP_NUM_PUBLIC_ATOMS (OB_PROP_NUM_ATOMS - OB_PROP_NET_SUPPORTED) + +void obt_prop_startup(); + +Atom obt_prop_atom(ObtPropAtom a); + +gboolean obt_prop_get32(Window win, Atom prop, Atom type, guint32 *ret); +gboolean obt_prop_get_array32(Window win, Atom prop, Atom type, guint32 **ret, + guint *nret); +gboolean obt_prop_get_string_locale(Window win, Atom prop, gchar **ret); +gboolean obt_prop_get_string_utf8(Window win, Atom prop, gchar **ret); +gboolean obt_prop_get_strings_locale(Window win, Atom prop, gchar ***ret); +gboolean obt_prop_get_strings_utf8(Window win, Atom prop, gchar ***ret); + +void obt_prop_set32(Window win, Atom prop, Atom type, gulong val); +void obt_prop_set_array32(Window win, Atom prop, Atom type, gulong *val, + guint num); +void obt_prop_set_string_utf8(Window win, Atom prop, const gchar *val); +void obt_prop_set_strings_utf8(Window win, Atom prop, gchar **strs); + +void obt_prop_erase(Window win, Atom prop); + +void obt_prop_message(gint screen, Window about, Atom messagetype, + glong data0, glong data1, glong data2, glong data3, + glong data4, glong mask); + +#define PROP_GET32(win, prop, type, ret) \ + (prop_get32(win, obt_prop_atom(OB_PROP_##prop), prop_atoms.type, ret)) +#define PROP_GETA32(win, prop, type, ret, nret) \ + (prop_get_array32(win, obt_prop_atom(OB_PROP_##prop), prop_atoms.type, \ + ret, nret)) +#define PROP_GETS(win, prop, type, ret) \ + (prop_get_string_##type(win, obt_prop_atom(OB_PROP_##prop), ret)) +#define PROP_GETSS(win, prop, type, ret) \ + (prop_get_strings_##type(win, obt_prop_atom(OB_PROP_##prop), ret)) + +#define PROP_SET32(win, prop, type, val) \ + prop_set32(win, obt_prop_atom(OB_PROP_##prop), \ + obt_prop_atom(OB_PROP_##type), val) +#define PROP_SETA32(win, prop, type, val, num) \ + prop_set_array32(win, obt_prop_atom(OB_PROP_##prop), \ + obt_prop_atom(OB_PROP_##type), val, num) +#define PROP_SETS(win, prop, val) \ + prop_set_string_utf8(win, obt_prop_atom(OB_PROP_##prop), val) +#define PROP_SETSS(win, prop, strs) \ + prop_set_strings_utf8(win, obt_prop_atom(OB_PROP_##prop), strs) + +#define PROP_ERASE(win, prop) prop_erase(win, obt_prop_atom(OB_PROP_##prop)) + +#define PROP_MSG(screen, about, msgtype, data0, data1, data2, data3, data4) \ + (prop_message(screen, about, obt_prop_atom(OB_PROP_##msgtype), \ + data0, data1, data2, data3, data4, \ + SubstructureNotifyMask | SubstructureRedirectMask)) + +G_END_DECLS + +#endif /* __obt_prop_h */ diff --git a/openbox/client.c b/openbox/client.c index 20ccfe3d..3c295017 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -2123,7 +2123,7 @@ void client_update_icons(ObClient *self) if (hints->flags & IconPixmapHint) { self->nicons = 1; self->icons = g_new(ObClientIcon, self->nicons); - obt_display_ignore_errors(ob_display, TRUE); + obt_display_ignore_errors(TRUE); if (!RrPixmapToRGBA(ob_rr_inst, hints->icon_pixmap, (hints->flags & IconMaskHint ? @@ -2135,7 +2135,7 @@ void client_update_icons(ObClient *self) g_free(self->icons); self->nicons = 0; } - obt_display_ignore_errors(ob_display, FALSE); + obt_display_ignore_errors(FALSE); } XFree(hints); } @@ -3611,7 +3611,7 @@ gboolean client_focus(ObClient *self) */ event_cancel_all_key_grabs(); - obt_display_ignore_errors(ob_display, TRUE); + obt_display_ignore_errors(TRUE); if (self->can_focus) { /* This can cause a BadMatch error with CurrentTime, or if an app @@ -3635,7 +3635,7 @@ gboolean client_focus(ObClient *self) XSendEvent(ob_display, self->window, FALSE, NoEventMask, &ce); } - obt_display_ignore_errors(ob_display, FALSE); + obt_display_ignore_errors(FALSE); ob_debug_type(OB_DEBUG_FOCUS, "Error focusing? %d\n", obt_display_error_occured); diff --git a/openbox/event.c b/openbox/event.c index 63e27df6..7e4e25f3 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -595,7 +595,7 @@ static void event_process(const XEvent *ec, gpointer data) Window win, root; gint i; guint u; - obt_display_ignore_errors(ob_display, TRUE); + obt_display_ignore_errors(TRUE); if (XGetInputFocus(ob_display, &win, &i) != 0 && XGetGeometry(ob_display, win, &root, &i,&i,&u,&u,&u,&u) != 0 && root != RootWindow(ob_display, ob_screen)) @@ -607,7 +607,7 @@ static void event_process(const XEvent *ec, gpointer data) else ob_debug_type(OB_DEBUG_FOCUS, "Focus went to a black hole !\n"); - obt_display_ignore_errors(ob_display, FALSE); + obt_display_ignore_errors(FALSE); /* nothing is focused */ focus_set_client(NULL); } else { @@ -685,10 +685,10 @@ static void event_process(const XEvent *ec, gpointer data) /* we are not to be held responsible if someone sends us an invalid request! */ - obt_display_ignore_errors(ob_display, TRUE); + obt_display_ignore_errors(TRUE); XConfigureWindow(ob_display, window, e->xconfigurerequest.value_mask, &xwc); - obt_display_ignore_errors(ob_display, FALSE); + obt_display_ignore_errors(FALSE); } #ifdef SYNC else if (obt_display_extension_sync && diff --git a/openbox/grab.c b/openbox/grab.c index cfbbbe1a..fea2b62e 100644 --- a/openbox/grab.c +++ b/openbox/grab.c @@ -175,11 +175,11 @@ void grab_button_full(guint button, guint state, Window win, guint mask, guint i; /* can get BadAccess from these */ - obt_display_ignore_errors(ob_display, TRUE); + obt_display_ignore_errors(TRUE); for (i = 0; i < MASK_LIST_SIZE; ++i) XGrabButton(ob_display, button, state | mask_list[i], win, False, mask, pointer_mode, GrabModeAsync, None, ob_cursor(cur)); - obt_display_ignore_errors(ob_display, FALSE); + obt_display_ignore_errors(FALSE); if (obt_display_error_occured) ob_debug("Failed to grab button %d modifiers %d", button, state); } @@ -197,11 +197,11 @@ void grab_key(guint keycode, guint state, Window win, gint keyboard_mode) guint i; /* can get BadAccess' from these */ - obt_display_ignore_errors(ob_display, TRUE); + obt_display_ignore_errors(TRUE); for (i = 0; i < MASK_LIST_SIZE; ++i) XGrabKey(ob_display, keycode, state | mask_list[i], win, FALSE, GrabModeAsync, keyboard_mode); - obt_display_ignore_errors(ob_display, FALSE); + obt_display_ignore_errors(FALSE); if (obt_display_error_occured) ob_debug("Failed to grab keycode %d modifiers %d", keycode, state); } diff --git a/openbox/mouse.c b/openbox/mouse.c index 782ea62c..5a9fe170 100644 --- a/openbox/mouse.c +++ b/openbox/mouse.c @@ -257,10 +257,10 @@ void mouse_event(ObClient *client, XEvent *e) Window wjunk; guint ujunk, b, w, h; /* this can cause errors to occur when the window closes */ - obt_display_ignore_errors(ob_display, TRUE); + obt_display_ignore_errors(TRUE); junk1 = XGetGeometry(ob_display, e->xbutton.window, &wjunk, &junk1, &junk2, &w, &h, &b, &ujunk); - obt_display_ignore_errors(ob_display, FALSE); + obt_display_ignore_errors(FALSE); if (junk1) { if (e->xbutton.x >= (signed)-b && e->xbutton.y >= (signed)-b && diff --git a/openbox/openbox.c b/openbox/openbox.c index ec283d5c..79b30c0d 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -142,9 +142,9 @@ gint main(gint argc, gchar **argv) session_startup(argc, argv); } - ob_display = obt_display_open(NULL); - if (ob_display == NULL) + if (!obt_display_open(NULL)) ob_exit_with_error(_("Failed to open the display from the DISPLAY environment variable.")); + ob_display = obt_display; if (remote_control) { prop_startup(); diff --git a/openbox/screen.c b/openbox/screen.c index 0d891630..e8a175d1 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -102,13 +102,13 @@ static gboolean replace_wm(void) ob_screen); return FALSE; } - obt_display_ignore_errors(ob_display, TRUE); + obt_display_ignore_errors(TRUE); /* We want to find out when the current selection owner dies */ XSelectInput(ob_display, current_wm_sn_owner, StructureNotifyMask); XSync(ob_display, FALSE); - obt_display_ignore_errors(ob_display, FALSE); + obt_display_ignore_errors(FALSE); if (obt_display_error_occured) current_wm_sn_owner = None; } @@ -179,10 +179,10 @@ gboolean screen_annex(void) return FALSE; } - obt_display_ignore_errors(ob_display, TRUE); + obt_display_ignore_errors(TRUE); XSelectInput(ob_display, RootWindow(ob_display, ob_screen), ROOT_EVENTMASK); - obt_display_ignore_errors(ob_display, FALSE); + obt_display_ignore_errors(FALSE); if (obt_display_error_occured) { g_message(_("A window manager is already running on screen %d"), ob_screen); @@ -1239,16 +1239,16 @@ void screen_install_colormap(ObClient *client, gboolean install) { if (client == NULL || client->colormap == None) { if (install) - XInstallColormap(RrDisplay(ob_rr_inst), RrColormap(ob_rr_inst)); + XInstallColormap(ob_display, RrColormap(ob_rr_inst)); else - XUninstallColormap(RrDisplay(ob_rr_inst), RrColormap(ob_rr_inst)); + XUninstallColormap(ob_display, RrColormap(ob_rr_inst)); } else { - obt_display_ignore_errors(ob_display, TRUE); + obt_display_ignore_errors(TRUE); if (install) - XInstallColormap(RrDisplay(ob_rr_inst), client->colormap); + XInstallColormap(ob_display, client->colormap); else - XUninstallColormap(RrDisplay(ob_rr_inst), client->colormap); - obt_display_ignore_errors(ob_display, FALSE); + XUninstallColormap(ob_display, client->colormap); + obt_display_ignore_errors(FALSE); } }