1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
4 # include "../config.h"
5 #endif // HAVE_CONFIG_H
11 #include <X11/Xatom.h>
20 Atoms
Property::atoms
;
22 static Atom
create(char *name
) { return XInternAtom(**display
, name
, false); }
24 void Property::initialize()
28 // make sure asserts fire if there is a problem
29 memset(&atoms
, 0, sizeof(Atoms
));
31 atoms
.cardinal
= XA_CARDINAL
;
32 atoms
.window
= XA_WINDOW
;
33 atoms
.pixmap
= XA_PIXMAP
;
35 atoms
.string
= XA_STRING
;
36 atoms
.utf8
= create("UTF8_STRING");
38 atoms
.openbox_pid
= create("_OPENBOX_PID");
40 atoms
.wm_colormap_windows
= create("WM_COLORMAP_WINDOWS");
41 atoms
.wm_protocols
= create("WM_PROTOCOLS");
42 atoms
.wm_state
= create("WM_STATE");
43 atoms
.wm_change_state
= create("WM_CHANGE_STATE");
44 atoms
.wm_delete_window
= create("WM_DELETE_WINDOW");
45 atoms
.wm_take_focus
= create("WM_TAKE_FOCUS");
46 atoms
.wm_name
= create("WM_NAME");
47 atoms
.wm_icon_name
= create("WM_ICON_NAME");
48 atoms
.wm_class
= create("WM_CLASS");
49 atoms
.wm_window_role
= create("WM_WINDOW_ROLE");
50 atoms
.motif_wm_hints
= create("_MOTIF_WM_HINTS");
52 atoms
.openbox_show_root_menu
= create("_OPENBOX_SHOW_ROOT_MENU");
53 atoms
.openbox_show_workspace_menu
= create("_OPENBOX_SHOW_WORKSPACE_MENU");
55 atoms
.net_supported
= create("_NET_SUPPORTED");
56 atoms
.net_client_list
= create("_NET_CLIENT_LIST");
57 atoms
.net_client_list_stacking
= create("_NET_CLIENT_LIST_STACKING");
58 atoms
.net_number_of_desktops
= create("_NET_NUMBER_OF_DESKTOPS");
59 atoms
.net_desktop_geometry
= create("_NET_DESKTOP_GEOMETRY");
60 atoms
.net_desktop_viewport
= create("_NET_DESKTOP_VIEWPORT");
61 atoms
.net_current_desktop
= create("_NET_CURRENT_DESKTOP");
62 atoms
.net_desktop_names
= create("_NET_DESKTOP_NAMES");
63 atoms
.net_active_window
= create("_NET_ACTIVE_WINDOW");
64 atoms
.net_workarea
= create("_NET_WORKAREA");
65 atoms
.net_supporting_wm_check
= create("_NET_SUPPORTING_WM_CHECK");
66 // atoms.net_virtual_roots = create("_NET_VIRTUAL_ROOTS");
68 atoms
.net_close_window
= create("_NET_CLOSE_WINDOW");
69 atoms
.net_wm_moveresize
= create("_NET_WM_MOVERESIZE");
71 // atoms.net_properties = create("_NET_PROPERTIES");
72 atoms
.net_wm_name
= create("_NET_WM_NAME");
73 atoms
.net_wm_visible_name
= create("_NET_WM_VISIBLE_NAME");
74 atoms
.net_wm_icon_name
= create("_NET_WM_ICON_NAME");
75 atoms
.net_wm_visible_icon_name
= create("_NET_WM_VISIBLE_ICON_NAME");
76 atoms
.net_wm_desktop
= create("_NET_WM_DESKTOP");
77 atoms
.net_wm_window_type
= create("_NET_WM_WINDOW_TYPE");
78 atoms
.net_wm_state
= create("_NET_WM_STATE");
79 atoms
.net_wm_strut
= create("_NET_WM_STRUT");
80 // atoms.net_wm_icon_geometry = create("_NET_WM_ICON_GEOMETRY");
81 // atoms.net_wm_icon = create("_NET_WM_ICON");
82 // atoms.net_wm_pid = create("_NET_WM_PID");
83 // atoms.net_wm_handled_icons = create("_NET_WM_HANDLED_ICONS");
84 atoms
.net_wm_allowed_actions
= create("_NET_WM_ALLOWED_ACTIONS");
86 // atoms.net_wm_ping = create("_NET_WM_PING");
88 atoms
.net_wm_window_type_desktop
= create("_NET_WM_WINDOW_TYPE_DESKTOP");
89 atoms
.net_wm_window_type_dock
= create("_NET_WM_WINDOW_TYPE_DOCK");
90 atoms
.net_wm_window_type_toolbar
= create("_NET_WM_WINDOW_TYPE_TOOLBAR");
91 atoms
.net_wm_window_type_menu
= create("_NET_WM_WINDOW_TYPE_MENU");
92 atoms
.net_wm_window_type_utility
= create("_NET_WM_WINDOW_TYPE_UTILITY");
93 atoms
.net_wm_window_type_splash
= create("_NET_WM_WINDOW_TYPE_SPLASH");
94 atoms
.net_wm_window_type_dialog
= create("_NET_WM_WINDOW_TYPE_DIALOG");
95 atoms
.net_wm_window_type_normal
= create("_NET_WM_WINDOW_TYPE_NORMAL");
97 atoms
.net_wm_moveresize_size_topleft
=
98 create("_NET_WM_MOVERESIZE_SIZE_TOPLEFT");
99 atoms
.net_wm_moveresize_size_topright
=
100 create("_NET_WM_MOVERESIZE_SIZE_TOPRIGHT");
101 atoms
.net_wm_moveresize_size_bottomleft
=
102 create("_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT");
103 atoms
.net_wm_moveresize_size_bottomright
=
104 create("_NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT");
105 atoms
.net_wm_moveresize_move
=
106 create("_NET_WM_MOVERESIZE_MOVE");
108 atoms
.net_wm_action_move
= create("_NET_WM_ACTION_MOVE");
109 atoms
.net_wm_action_resize
= create("_NET_WM_ACTION_RESIZE");
110 atoms
.net_wm_action_minimize
= create("_NET_WM_ACTION_MINIMIZE");
111 atoms
.net_wm_action_shade
= create("_NET_WM_ACTION_SHADE");
112 atoms
.net_wm_action_stick
= create("_NET_WM_ACTION_STICK");
113 atoms
.net_wm_action_maximize_horz
= create("_NET_WM_ACTION_MAXIMIZE_HORZ");
114 atoms
.net_wm_action_maximize_vert
= create("_NET_WM_ACTION_MAXIMIZE_VERT");
115 atoms
.net_wm_action_fullscreen
= create("_NET_WM_ACTION_FULLSCREEN");
116 atoms
.net_wm_action_change_desktop
=
117 create("_NET_WM_ACTION_CHANGE_DESKTOP");
118 atoms
.net_wm_action_close
= create("_NET_WM_ACTION_CLOSE");
120 atoms
.net_wm_state_modal
= create("_NET_WM_STATE_MODAL");
121 atoms
.net_wm_state_sticky
= create("_NET_WM_STATE_STICKY");
122 atoms
.net_wm_state_maximized_vert
= create("_NET_WM_STATE_MAXIMIZED_VERT");
123 atoms
.net_wm_state_maximized_horz
= create("_NET_WM_STATE_MAXIMIZED_HORZ");
124 atoms
.net_wm_state_shaded
= create("_NET_WM_STATE_SHADED");
125 atoms
.net_wm_state_skip_taskbar
= create("_NET_WM_STATE_SKIP_TASKBAR");
126 atoms
.net_wm_state_skip_pager
= create("_NET_WM_STATE_SKIP_PAGER");
127 atoms
.net_wm_state_hidden
= create("_NET_WM_STATE_HIDDEN");
128 atoms
.net_wm_state_fullscreen
= create("_NET_WM_STATE_FULLSCREEN");
129 atoms
.net_wm_state_above
= create("_NET_WM_STATE_ABOVE");
130 atoms
.net_wm_state_below
= create("_NET_WM_STATE_BELOW");
132 atoms
.kde_net_system_tray_windows
= create("_KDE_NET_SYSTEM_TRAY_WINDOWS");
133 atoms
.kde_net_wm_system_tray_window_for
=
134 create("_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR");
135 atoms
.kde_net_wm_window_type_override
=
136 create("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE");
138 atoms
.openbox_premax
= create("_OPENBOX_PREMAX");
141 void Property::set(Window win
, Atom atom
, Atom type
, unsigned char* data
,
142 int size
, int nelements
, bool append
)
144 assert(win
!= None
); assert(atom
!= None
); assert(type
!= None
);
145 assert(nelements
== 0 || (nelements
> 0 && data
!= (unsigned char *) 0));
146 assert(size
== 8 || size
== 16 || size
== 32);
147 XChangeProperty(**display
, win
, atom
, type
, size
,
148 (append
? PropModeAppend
: PropModeReplace
),
152 void Property::set(Window win
, Atom atom
, Atom type
, unsigned long value
)
154 set(win
, atom
, type
, (unsigned char*) &value
, 32, 1, false);
157 void Property::set(Window win
, Atom atom
, Atom type
, unsigned long value
[],
160 set(win
, atom
, type
, (unsigned char*) value
, 32, elements
, false);
163 void Property::set(Window win
, Atom atom
, StringType type
,
164 const ustring
&value
)
168 case ascii
: t
= atoms
.string
; assert(!value
.utf8()); break;
169 case utf8
: t
= atoms
.utf8
; assert(value
.utf8()); break;
170 default: assert(false); return; // unhandled StringType
173 // add 1 to the size to include the trailing null
174 set(win
, atom
, t
, (unsigned char*) value
.c_str(), 8, value
.bytes() + 1,
178 void Property::set(Window win
, Atom atom
, StringType type
,
179 const StringVect
&strings
)
182 bool u
; // utf8 encoded?
184 case ascii
: t
= atoms
.string
; u
= false; break;
185 case utf8
: t
= atoms
.utf8
; u
= true; break;
186 default: assert(false); return; // unhandled StringType
191 StringVect::const_iterator it
= strings
.begin();
192 const StringVect::const_iterator end
= strings
.end();
193 for (; it
!= end
; ++it
) {
194 assert(it
->utf8() == u
); // the ustring is encoded correctly?
199 // add 1 to the size to include the trailing null
200 set(win
, atom
, t
, (unsigned char*)value
.c_str(), 8,
201 value
.bytes() + 1, false);
204 bool Property::get(Window win
, Atom atom
, Atom type
, unsigned long *nelements
,
205 unsigned char **value
, int size
)
207 assert(win
!= None
); assert(atom
!= None
); assert(type
!= None
);
208 assert(size
== 8 || size
== 16 || size
== 32);
209 assert(*nelements
> 0);
210 unsigned char *c_val
= 0; // value alloc'd in Xlib, must be XFree()d
213 unsigned long ret_bytes
;
215 unsigned long maxread
= *nelements
;
218 // try get the first element
219 result
= XGetWindowProperty(**display
, win
, atom
, 0l, 1l,
220 false, AnyPropertyType
, &ret_type
, &ret_size
,
221 nelements
, &ret_bytes
, &c_val
);
222 ret
= (result
== Success
&& ret_type
== type
&& ret_size
== size
&&
225 if (ret_bytes
== 0 || maxread
<= *nelements
) {
226 // we got the whole property's value
227 *value
= new unsigned char[*nelements
* size
/8 + 1];
228 memcpy(*value
, c_val
, *nelements
* size
/8 + 1);
230 // get the entire property since it is larger than one long
232 // the number of longs that need to be retreived to get the property's
233 // entire value. The last + 1 is the first long that we retrieved above.
234 int remain
= (ret_bytes
- 1)/sizeof(long) + 1 + 1;
235 if (remain
> size
/8 * (signed)maxread
) // dont get more than the max
236 remain
= size
/8 * (signed)maxread
;
237 result
= XGetWindowProperty(**display
, win
, atom
, 0l,
238 remain
, false, type
, &ret_type
, &ret_size
,
239 nelements
, &ret_bytes
, &c_val
);
240 ret
= (result
== Success
&& ret_type
== type
&& ret_size
== size
&&
243 If the property has changed type/size, or has grown since our first
244 read of it, then stop here and try again. If it shrank, then this will
248 return get(win
, atom
, type
, &maxread
, value
, size
);
250 *value
= new unsigned char[*nelements
* size
/8 + 1];
251 memcpy(*value
, c_val
, *nelements
* size
/8 + 1);
254 if (c_val
) XFree(c_val
);
258 bool Property::get(Window win
, Atom atom
, Atom type
, unsigned long *nelements
,
259 unsigned long **value
)
261 return get(win
, atom
, type
, nelements
, (unsigned char**) value
, 32);
264 bool Property::get(Window win
, Atom atom
, Atom type
, unsigned long *value
)
267 unsigned long num
= 1;
268 if (! get(win
, atom
, type
, &num
, (unsigned char **) &temp
, 32))
275 bool Property::get(Window win
, Atom atom
, StringType type
, ustring
*value
)
280 if (get(win
, atom
, type
, &n
, &s
)) {
287 bool Property::get(Window win
, Atom atom
, StringType type
,
288 unsigned long *nelements
, StringVect
*strings
)
290 assert(*nelements
> 0);
293 bool u
; // utf8 encoded?
295 case ascii
: t
= atoms
.string
; u
= false; break;
296 case utf8
: t
= atoms
.utf8
; u
= true; break;
297 default: assert(false); return false; // unhandled StringType
300 unsigned char *value
;
301 unsigned long elements
= (unsigned) -1;
302 if (!get(win
, atom
, t
, &elements
, &value
, 8) || elements
< 1)
305 std::string
s((char*)value
, elements
);
308 std::string::const_iterator it
= s
.begin(), end
= s
.end();
309 unsigned long num
= 0;
310 while(num
< *nelements
) {
311 std::string::const_iterator tmp
= it
; // current string.begin()
312 it
= std::find(tmp
, end
, '\0'); // look for null between tmp and end
313 strings
->push_back(std::string(tmp
, it
)); // s[tmp:it)
314 strings
->back().setUtf8(u
);
316 if (it
== end
) break;
318 if (it
== end
) break;
328 * Removes a property entirely from a window.
330 void Property::erase(Window win
, Atom atom
)
332 XDeleteProperty(**display
, win
, atom
);