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");
139 atoms
.openbox_active_window
= create("_OPENBOX_ACTIVE_WINDOW");
142 void Property::set(Window win
, Atom atom
, Atom type
, unsigned char* data
,
143 int size
, int nelements
, bool append
)
145 assert(win
!= None
); assert(atom
!= None
); assert(type
!= None
);
146 assert(nelements
== 0 || (nelements
> 0 && data
!= (unsigned char *) 0));
147 assert(size
== 8 || size
== 16 || size
== 32);
148 XChangeProperty(**display
, win
, atom
, type
, size
,
149 (append
? PropModeAppend
: PropModeReplace
),
153 void Property::set(Window win
, Atom atom
, Atom type
, unsigned long value
)
155 set(win
, atom
, type
, (unsigned char*) &value
, 32, 1, false);
158 void Property::set(Window win
, Atom atom
, Atom type
, unsigned long value
[],
161 set(win
, atom
, type
, (unsigned char*) value
, 32, elements
, false);
164 void Property::set(Window win
, Atom atom
, StringType type
,
165 const ustring
&value
)
169 case ascii
: t
= atoms
.string
; assert(!value
.utf8()); break;
170 case utf8
: t
= atoms
.utf8
; assert(value
.utf8()); break;
171 default: assert(false); return; // unhandled StringType
174 // add 1 to the size to include the trailing null
175 set(win
, atom
, t
, (unsigned char*) value
.c_str(), 8, value
.bytes() + 1,
179 void Property::set(Window win
, Atom atom
, StringType type
,
180 const StringVect
&strings
)
183 bool u
; // utf8 encoded?
185 case ascii
: t
= atoms
.string
; u
= false; break;
186 case utf8
: t
= atoms
.utf8
; u
= true; break;
187 default: assert(false); return; // unhandled StringType
192 StringVect::const_iterator it
= strings
.begin();
193 const StringVect::const_iterator end
= strings
.end();
194 for (; it
!= end
; ++it
) {
195 assert(it
->utf8() == u
); // the ustring is encoded correctly?
200 // add 1 to the size to include the trailing null
201 set(win
, atom
, t
, (unsigned char*)value
.c_str(), 8,
202 value
.bytes() + 1, false);
205 bool Property::get(Window win
, Atom atom
, Atom type
, unsigned long *nelements
,
206 unsigned char **value
, int size
)
208 assert(win
!= None
); assert(atom
!= None
); assert(type
!= None
);
209 assert(size
== 8 || size
== 16 || size
== 32);
210 assert(*nelements
> 0);
211 unsigned char *c_val
= 0; // value alloc'd in Xlib, must be XFree()d
214 unsigned long ret_bytes
;
216 unsigned long maxread
= *nelements
;
219 // try get the first element
220 result
= XGetWindowProperty(**display
, win
, atom
, 0l, 1l,
221 false, AnyPropertyType
, &ret_type
, &ret_size
,
222 nelements
, &ret_bytes
, &c_val
);
223 ret
= (result
== Success
&& ret_type
== type
&& ret_size
== size
&&
226 if (ret_bytes
== 0 || maxread
<= *nelements
) {
227 // we got the whole property's value
228 *value
= new unsigned char[*nelements
* size
/8 + 1];
229 memcpy(*value
, c_val
, *nelements
* size
/8 + 1);
231 // get the entire property since it is larger than one long
233 // the number of longs that need to be retreived to get the property's
234 // entire value. The last + 1 is the first long that we retrieved above.
235 int remain
= (ret_bytes
- 1)/sizeof(long) + 1 + 1;
236 if (remain
> size
/8 * (signed)maxread
) // dont get more than the max
237 remain
= size
/8 * (signed)maxread
;
238 result
= XGetWindowProperty(**display
, win
, atom
, 0l,
239 remain
, false, type
, &ret_type
, &ret_size
,
240 nelements
, &ret_bytes
, &c_val
);
241 ret
= (result
== Success
&& ret_type
== type
&& ret_size
== size
&&
244 If the property has changed type/size, or has grown since our first
245 read of it, then stop here and try again. If it shrank, then this will
249 return get(win
, atom
, type
, &maxread
, value
, size
);
251 *value
= new unsigned char[*nelements
* size
/8 + 1];
252 memcpy(*value
, c_val
, *nelements
* size
/8 + 1);
255 if (c_val
) XFree(c_val
);
259 bool Property::get(Window win
, Atom atom
, Atom type
, unsigned long *nelements
,
260 unsigned long **value
)
262 return get(win
, atom
, type
, nelements
, (unsigned char**) value
, 32);
265 bool Property::get(Window win
, Atom atom
, Atom type
, unsigned long *value
)
268 unsigned long num
= 1;
269 if (! get(win
, atom
, type
, &num
, (unsigned char **) &temp
, 32))
276 bool Property::get(Window win
, Atom atom
, StringType type
, ustring
*value
)
281 if (get(win
, atom
, type
, &n
, &s
)) {
288 bool Property::get(Window win
, Atom atom
, StringType type
,
289 unsigned long *nelements
, StringVect
*strings
)
291 assert(*nelements
> 0);
294 bool u
; // utf8 encoded?
296 case ascii
: t
= atoms
.string
; u
= false; break;
297 case utf8
: t
= atoms
.utf8
; u
= true; break;
298 default: assert(false); return false; // unhandled StringType
301 unsigned char *value
;
302 unsigned long elements
= (unsigned) -1;
303 if (!get(win
, atom
, t
, &elements
, &value
, 8) || elements
< 1)
306 std::string
s((char*)value
, elements
);
309 std::string::const_iterator it
= s
.begin(), end
= s
.end();
310 unsigned long num
= 0;
311 while(num
< *nelements
) {
312 std::string::const_iterator tmp
= it
; // current string.begin()
313 it
= std::find(tmp
, end
, '\0'); // look for null between tmp and end
314 strings
->push_back(std::string(tmp
, it
)); // s[tmp:it)
315 strings
->back().setUtf8(u
);
317 if (it
== end
) break;
319 if (it
== end
) break;
329 * Removes a property entirely from a window.
331 void Property::erase(Window win
, Atom atom
)
333 XDeleteProperty(**display
, win
, atom
);