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");
139 void Property::set(Window win
, Atom atom
, Atom type
, unsigned char* data
,
140 int size
, int nelements
, bool append
)
142 assert(win
!= None
); assert(atom
!= None
); assert(type
!= None
);
143 assert(nelements
== 0 || (nelements
> 0 && data
!= (unsigned char *) 0));
144 assert(size
== 8 || size
== 16 || size
== 32);
145 XChangeProperty(**display
, win
, atom
, type
, size
,
146 (append
? PropModeAppend
: PropModeReplace
),
150 void Property::set(Window win
, Atom atom
, Atom type
, unsigned long value
)
152 set(win
, atom
, type
, (unsigned char*) &value
, 32, 1, false);
155 void Property::set(Window win
, Atom atom
, Atom type
, unsigned long value
[],
158 set(win
, atom
, type
, (unsigned char*) value
, 32, elements
, false);
161 void Property::set(Window win
, Atom atom
, StringType type
,
162 const ustring
&value
)
166 case ascii
: t
= atoms
.string
; assert(!value
.utf8()); break;
167 case utf8
: t
= atoms
.utf8
; assert(value
.utf8()); break;
168 default: assert(false); return; // unhandled StringType
171 // add 1 to the size to include the trailing null
172 set(win
, atom
, t
, (unsigned char*) value
.c_str(), 8, value
.bytes() + 1,
176 void Property::set(Window win
, Atom atom
, StringType type
,
177 const StringVect
&strings
)
180 bool u
; // utf8 encoded?
182 case ascii
: t
= atoms
.string
; u
= false; break;
183 case utf8
: t
= atoms
.utf8
; u
= true; break;
184 default: assert(false); return; // unhandled StringType
189 StringVect::const_iterator it
= strings
.begin();
190 const StringVect::const_iterator end
= strings
.end();
191 for (; it
!= end
; ++it
) {
192 assert(it
->utf8() == u
); // the ustring is encoded correctly?
197 // add 1 to the size to include the trailing null
198 set(win
, atom
, t
, (unsigned char*)value
.c_str(), 8,
199 value
.bytes() + 1, false);
202 bool Property::get(Window win
, Atom atom
, Atom type
, unsigned long *nelements
,
203 unsigned char **value
, int size
)
205 assert(win
!= None
); assert(atom
!= None
); assert(type
!= None
);
206 assert(size
== 8 || size
== 16 || size
== 32);
207 assert(*nelements
> 0);
208 unsigned char *c_val
= 0; // value alloc'd in Xlib, must be XFree()d
211 unsigned long ret_bytes
;
213 unsigned long maxread
= *nelements
;
216 // try get the first element
217 result
= XGetWindowProperty(**display
, win
, atom
, 0l, 1l,
218 false, AnyPropertyType
, &ret_type
, &ret_size
,
219 nelements
, &ret_bytes
, &c_val
);
220 ret
= (result
== Success
&& ret_type
== type
&& ret_size
== size
&&
223 if (ret_bytes
== 0 || maxread
<= *nelements
) {
224 // we got the whole property's value
225 *value
= new unsigned char[*nelements
* size
/8 + 1];
226 memcpy(*value
, c_val
, *nelements
* size
/8 + 1);
228 // get the entire property since it is larger than one long
230 // the number of longs that need to be retreived to get the property's
231 // entire value. The last + 1 is the first long that we retrieved above.
232 int remain
= (ret_bytes
- 1)/sizeof(long) + 1 + 1;
233 if (remain
> size
/8 * (signed)maxread
) // dont get more than the max
234 remain
= size
/8 * (signed)maxread
;
235 result
= XGetWindowProperty(**display
, win
, atom
, 0l,
236 remain
, false, type
, &ret_type
, &ret_size
,
237 nelements
, &ret_bytes
, &c_val
);
238 ret
= (result
== Success
&& ret_type
== type
&& ret_size
== size
&&
241 If the property has changed type/size, or has grown since our first
242 read of it, then stop here and try again. If it shrank, then this will
246 return get(win
, atom
, type
, &maxread
, value
, size
);
248 *value
= new unsigned char[*nelements
* size
/8 + 1];
249 memcpy(*value
, c_val
, *nelements
* size
/8 + 1);
252 if (c_val
) XFree(c_val
);
256 bool Property::get(Window win
, Atom atom
, Atom type
, unsigned long *nelements
,
257 unsigned long **value
)
259 return get(win
, atom
, type
, nelements
, (unsigned char**) value
, 32);
262 bool Property::get(Window win
, Atom atom
, Atom type
, unsigned long *value
)
265 unsigned long num
= 1;
266 if (! get(win
, atom
, type
, &num
, (unsigned char **) &temp
, 32))
273 bool Property::get(Window win
, Atom atom
, StringType type
, ustring
*value
)
278 if (get(win
, atom
, type
, &n
, &s
)) {
285 bool Property::get(Window win
, Atom atom
, StringType type
,
286 unsigned long *nelements
, StringVect
*strings
)
288 assert(*nelements
> 0);
291 bool u
; // utf8 encoded?
293 case ascii
: t
= atoms
.string
; u
= false; break;
294 case utf8
: t
= atoms
.utf8
; u
= true; break;
295 default: assert(false); return false; // unhandled StringType
298 unsigned char *value
;
299 unsigned long elements
= (unsigned) -1;
300 if (!get(win
, atom
, t
, &elements
, &value
, 8) || elements
< 1)
303 std::string
s((char*)value
, elements
);
306 std::string::const_iterator it
= s
.begin(), end
= s
.end();
307 unsigned long num
= 0;
308 while(num
< *nelements
) {
309 std::string::const_iterator tmp
= it
; // current string.begin()
310 it
= std::find(tmp
, end
, '\0'); // look for null between tmp and end
311 strings
->push_back(std::string(tmp
, it
)); // s[tmp:it)
312 strings
->back().setUtf8(u
);
314 if (it
== end
) break;
316 if (it
== end
) break;
326 * Removes a property entirely from a window.
328 void Property::erase(Window win
, Atom atom
)
330 XDeleteProperty(**display
, win
, atom
);