File: | plugins/xsettings/xsettings-manager.c |
Warning: | line 327, column 20 Out of bound memory access (access exceeds upper limit of memory block) |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright © 2001 Red Hat, Inc. | |||
3 | * | |||
4 | * Permission to use, copy, modify, distribute, and sell this software and its | |||
5 | * documentation for any purpose is hereby granted without fee, provided that | |||
6 | * the above copyright notice appear in all copies and that both that | |||
7 | * copyright notice and this permission notice appear in supporting | |||
8 | * documentation, and that the name of Red Hat not be used in advertising or | |||
9 | * publicity pertaining to distribution of the software without specific, | |||
10 | * written prior permission. Red Hat makes no representations about the | |||
11 | * suitability of this software for any purpose. It is provided "as is" | |||
12 | * without express or implied warranty. | |||
13 | * | |||
14 | * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL | |||
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT | |||
16 | * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | |||
18 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
19 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
20 | * | |||
21 | * Author: Owen Taylor, Red Hat, Inc. | |||
22 | */ | |||
23 | #include <stdio.h> | |||
24 | #include <stdlib.h> | |||
25 | #include <string.h> | |||
26 | ||||
27 | #include <X11/Xmd.h> /* For CARD16 */ | |||
28 | ||||
29 | #include "xsettings-manager.h" | |||
30 | ||||
31 | struct _XSettingsManager | |||
32 | { | |||
33 | Display *display; | |||
34 | int screen; | |||
35 | ||||
36 | Window window; | |||
37 | Atom manager_atom; | |||
38 | Atom selection_atom; | |||
39 | Atom xsettings_atom; | |||
40 | ||||
41 | XSettingsTerminateFunc terminate; | |||
42 | void *cb_data; | |||
43 | ||||
44 | XSettingsList *settings; | |||
45 | unsigned long serial; | |||
46 | }; | |||
47 | ||||
48 | static XSettingsList *settings; | |||
49 | ||||
50 | typedef struct | |||
51 | { | |||
52 | Window window; | |||
53 | Atom timestamp_prop_atom; | |||
54 | } TimeStampInfo; | |||
55 | ||||
56 | static Boolint | |||
57 | timestamp_predicate (Display *display, | |||
58 | XEvent *xevent, | |||
59 | XPointer arg) | |||
60 | { | |||
61 | TimeStampInfo *info = (TimeStampInfo *)arg; | |||
62 | ||||
63 | if (xevent->type == PropertyNotify28 && | |||
64 | xevent->xproperty.window == info->window && | |||
65 | xevent->xproperty.atom == info->timestamp_prop_atom) | |||
66 | return True1; | |||
67 | ||||
68 | return False0; | |||
69 | } | |||
70 | ||||
71 | /** | |||
72 | * get_server_time: | |||
73 | * @display: display from which to get the time | |||
74 | * @window: a #Window, used for communication with the server. | |||
75 | * The window must have PropertyChangeMask in its | |||
76 | * events mask or a hang will result. | |||
77 | * | |||
78 | * Routine to get the current X server time stamp. | |||
79 | * | |||
80 | * Return value: the time stamp. | |||
81 | **/ | |||
82 | static Time | |||
83 | get_server_time (Display *display, | |||
84 | Window window) | |||
85 | { | |||
86 | unsigned char c = 'a'; | |||
87 | XEvent xevent; | |||
88 | TimeStampInfo info; | |||
89 | ||||
90 | info.timestamp_prop_atom = XInternAtom (display, "_TIMESTAMP_PROP", False0); | |||
91 | info.window = window; | |||
92 | ||||
93 | XChangeProperty (display, window, | |||
94 | info.timestamp_prop_atom, info.timestamp_prop_atom, | |||
95 | 8, PropModeReplace0, &c, 1); | |||
96 | ||||
97 | XIfEvent (display, &xevent, | |||
98 | timestamp_predicate, (XPointer)&info); | |||
99 | ||||
100 | return xevent.xproperty.time; | |||
101 | } | |||
102 | ||||
103 | Boolint | |||
104 | xsettings_manager_check_running (Display *display, | |||
105 | int screen) | |||
106 | { | |||
107 | char buffer[256]; | |||
108 | Atom selection_atom; | |||
109 | ||||
110 | sprintf(buffer, "_XSETTINGS_S%d", screen); | |||
111 | selection_atom = XInternAtom (display, buffer, False0); | |||
112 | ||||
113 | if (XGetSelectionOwner (display, selection_atom)) | |||
114 | return True1; | |||
115 | else | |||
116 | return False0; | |||
117 | } | |||
118 | ||||
119 | XSettingsManager * | |||
120 | xsettings_manager_new (Display *display, | |||
121 | int screen, | |||
122 | XSettingsTerminateFunc terminate, | |||
123 | void *cb_data) | |||
124 | { | |||
125 | XSettingsManager *manager; | |||
126 | Time timestamp; | |||
127 | XClientMessageEvent xev; | |||
128 | ||||
129 | char buffer[256]; | |||
130 | ||||
131 | manager = malloc (sizeof *manager); | |||
132 | if (!manager) | |||
133 | return NULL((void*)0); | |||
134 | ||||
135 | manager->display = display; | |||
136 | manager->screen = screen; | |||
137 | ||||
138 | sprintf(buffer, "_XSETTINGS_S%d", screen); | |||
139 | manager->selection_atom = XInternAtom (display, buffer, False0); | |||
140 | manager->xsettings_atom = XInternAtom (display, "_XSETTINGS_SETTINGS", False0); | |||
141 | manager->manager_atom = XInternAtom (display, "MANAGER", False0); | |||
142 | ||||
143 | manager->terminate = terminate; | |||
144 | manager->cb_data = cb_data; | |||
145 | ||||
146 | manager->settings = NULL((void*)0); | |||
147 | manager->serial = 0; | |||
148 | ||||
149 | manager->window = XCreateSimpleWindow (display, | |||
150 | RootWindow (display, screen)((&((_XPrivDisplay)(display))->screens[screen])->root ), | |||
151 | 0, 0, 10, 10, 0, | |||
152 | WhitePixel (display, screen)((&((_XPrivDisplay)(display))->screens[screen])->white_pixel ), | |||
153 | WhitePixel (display, screen)((&((_XPrivDisplay)(display))->screens[screen])->white_pixel )); | |||
154 | ||||
155 | XSelectInput (display, manager->window, PropertyChangeMask(1L<<22)); | |||
156 | timestamp = get_server_time (display, manager->window); | |||
157 | ||||
158 | XSetSelectionOwner (display, manager->selection_atom, | |||
159 | manager->window, timestamp); | |||
160 | ||||
161 | /* Check to see if we managed to claim the selection. If not, | |||
162 | * we treat it as if we got it then immediately lost it | |||
163 | */ | |||
164 | ||||
165 | if (XGetSelectionOwner (display, manager->selection_atom) == | |||
166 | manager->window) | |||
167 | { | |||
168 | xev.type = ClientMessage33; | |||
169 | xev.window = RootWindow (display, screen)((&((_XPrivDisplay)(display))->screens[screen])->root ); | |||
170 | xev.message_type = manager->manager_atom; | |||
171 | xev.format = 32; | |||
172 | xev.data.l[0] = timestamp; | |||
173 | xev.data.l[1] = manager->selection_atom; | |||
174 | xev.data.l[2] = manager->window; | |||
175 | xev.data.l[3] = 0; /* manager specific data */ | |||
176 | xev.data.l[4] = 0; /* manager specific data */ | |||
177 | ||||
178 | XSendEvent (display, RootWindow (display, screen)((&((_XPrivDisplay)(display))->screens[screen])->root ), | |||
179 | False0, StructureNotifyMask(1L<<17), (XEvent *)&xev); | |||
180 | } | |||
181 | else | |||
182 | { | |||
183 | manager->terminate (manager->cb_data); | |||
184 | } | |||
185 | ||||
186 | return manager; | |||
187 | } | |||
188 | ||||
189 | void | |||
190 | xsettings_manager_destroy (XSettingsManager *manager) | |||
191 | { | |||
192 | XDestroyWindow (manager->display, manager->window); | |||
193 | ||||
194 | xsettings_list_free (manager->settings); | |||
195 | free (manager); | |||
196 | } | |||
197 | ||||
198 | Window | |||
199 | xsettings_manager_get_window (XSettingsManager *manager) | |||
200 | { | |||
201 | return manager->window; | |||
202 | } | |||
203 | ||||
204 | Boolint | |||
205 | xsettings_manager_process_event (XSettingsManager *manager, | |||
206 | XEvent *xev) | |||
207 | { | |||
208 | if (xev->xany.window == manager->window && | |||
209 | xev->xany.type == SelectionClear29 && | |||
210 | xev->xselectionclear.selection == manager->selection_atom) | |||
211 | { | |||
212 | manager->terminate (manager->cb_data); | |||
213 | return True1; | |||
214 | } | |||
215 | ||||
216 | return False0; | |||
217 | } | |||
218 | ||||
219 | XSettingsResult | |||
220 | xsettings_manager_delete_setting (XSettingsManager *manager, | |||
221 | const char *name) | |||
222 | { | |||
223 | return xsettings_list_delete (&settings, name); | |||
224 | } | |||
225 | ||||
226 | XSettingsResult | |||
227 | xsettings_manager_set_setting (XSettingsManager *manager, | |||
228 | XSettingsSetting *setting) | |||
229 | { | |||
230 | XSettingsSetting *old_setting = xsettings_list_lookup (settings, setting->name); | |||
231 | XSettingsSetting *new_setting; | |||
232 | XSettingsResult result; | |||
233 | ||||
234 | if (old_setting) | |||
235 | { | |||
236 | if (xsettings_setting_equal (old_setting, setting)) | |||
237 | return XSETTINGS_SUCCESS; | |||
238 | ||||
239 | xsettings_list_delete (&settings, setting->name); | |||
240 | } | |||
241 | ||||
242 | new_setting = xsettings_setting_copy (setting); | |||
243 | if (!new_setting) | |||
244 | return XSETTINGS_NO_MEM; | |||
245 | ||||
246 | new_setting->last_change_serial = manager->serial; | |||
247 | ||||
248 | result = xsettings_list_insert (&settings, new_setting); | |||
249 | ||||
250 | if (result != XSETTINGS_SUCCESS) | |||
251 | xsettings_setting_free (new_setting); | |||
252 | ||||
253 | return result; | |||
254 | } | |||
255 | ||||
256 | XSettingsResult | |||
257 | xsettings_manager_set_int (XSettingsManager *manager, | |||
258 | const char *name, | |||
259 | int value) | |||
260 | { | |||
261 | XSettingsSetting setting; | |||
262 | ||||
263 | setting.name = (char *)name; | |||
264 | setting.type = XSETTINGS_TYPE_INT; | |||
265 | setting.data.v_int = value; | |||
266 | ||||
267 | return xsettings_manager_set_setting (manager, &setting); | |||
268 | } | |||
269 | ||||
270 | XSettingsResult | |||
271 | xsettings_manager_set_string (XSettingsManager *manager, | |||
272 | const char *name, | |||
273 | const char *value) | |||
274 | { | |||
275 | XSettingsSetting setting; | |||
276 | ||||
277 | setting.name = (char *)name; | |||
278 | setting.type = XSETTINGS_TYPE_STRING; | |||
279 | setting.data.v_string = (char *)value; | |||
280 | ||||
281 | return xsettings_manager_set_setting (manager, &setting); | |||
282 | } | |||
283 | ||||
284 | XSettingsResult | |||
285 | xsettings_manager_set_color (XSettingsManager *manager, | |||
286 | const char *name, | |||
287 | XSettingsColor *value) | |||
288 | { | |||
289 | XSettingsSetting setting; | |||
290 | ||||
291 | setting.name = (char *)name; | |||
292 | setting.type = XSETTINGS_TYPE_COLOR; | |||
293 | setting.data.v_color = *value; | |||
294 | ||||
295 | return xsettings_manager_set_setting (manager, &setting); | |||
296 | } | |||
297 | ||||
298 | static size_t | |||
299 | setting_length (XSettingsSetting *setting) | |||
300 | { | |||
301 | size_t length = 8; /* type + pad + name-len + last-change-serial */ | |||
302 | length += XSETTINGS_PAD (strlen (setting->name), 4)((strlen (setting->name) + 4 - 1) & (~(4 -1))); | |||
303 | ||||
304 | switch (setting->type) | |||
305 | { | |||
306 | case XSETTINGS_TYPE_INT: | |||
307 | length += 4; | |||
308 | break; | |||
309 | case XSETTINGS_TYPE_STRING: | |||
310 | length += 4 + XSETTINGS_PAD (strlen (setting->data.v_string), 4)((strlen (setting->data.v_string) + 4 - 1) & (~(4 -1)) ); | |||
311 | break; | |||
312 | case XSETTINGS_TYPE_COLOR: | |||
313 | length += 8; | |||
314 | break; | |||
315 | } | |||
316 | ||||
317 | return length; | |||
318 | } | |||
319 | ||||
320 | static void | |||
321 | setting_store (XSettingsSetting *setting, | |||
322 | XSettingsBuffer *buffer) | |||
323 | { | |||
324 | size_t string_len; | |||
325 | size_t length; | |||
326 | ||||
327 | *(buffer->pos++) = setting->type; | |||
| ||||
328 | *(buffer->pos++) = 0; | |||
329 | ||||
330 | string_len = strlen (setting->name); | |||
331 | *(CARD16 *)(buffer->pos) = string_len; | |||
332 | buffer->pos += 2; | |||
333 | ||||
334 | length = XSETTINGS_PAD (string_len, 4)((string_len + 4 - 1) & (~(4 -1))); | |||
335 | memcpy (buffer->pos, setting->name, string_len); | |||
336 | length -= string_len; | |||
337 | buffer->pos += string_len; | |||
338 | ||||
339 | while (length > 0) | |||
340 | { | |||
341 | *(buffer->pos++) = 0; | |||
342 | length--; | |||
343 | } | |||
344 | ||||
345 | *(CARD32 *)(buffer->pos) = setting->last_change_serial; | |||
346 | buffer->pos += 4; | |||
347 | ||||
348 | switch (setting->type) | |||
349 | { | |||
350 | case XSETTINGS_TYPE_INT: | |||
351 | *(CARD32 *)(buffer->pos) = setting->data.v_int; | |||
352 | buffer->pos += 4; | |||
353 | break; | |||
354 | case XSETTINGS_TYPE_STRING: | |||
355 | string_len = strlen (setting->data.v_string); | |||
356 | *(CARD32 *)(buffer->pos) = string_len; | |||
357 | buffer->pos += 4; | |||
358 | ||||
359 | length = XSETTINGS_PAD (string_len, 4)((string_len + 4 - 1) & (~(4 -1))); | |||
360 | memcpy (buffer->pos, setting->data.v_string, string_len); | |||
361 | length -= string_len; | |||
362 | buffer->pos += string_len; | |||
363 | ||||
364 | while (length > 0) | |||
365 | { | |||
366 | *(buffer->pos++) = 0; | |||
367 | length--; | |||
368 | } | |||
369 | break; | |||
370 | case XSETTINGS_TYPE_COLOR: | |||
371 | *(CARD16 *)(buffer->pos) = setting->data.v_color.red; | |||
372 | *(CARD16 *)(buffer->pos + 2) = setting->data.v_color.green; | |||
373 | *(CARD16 *)(buffer->pos + 4) = setting->data.v_color.blue; | |||
374 | *(CARD16 *)(buffer->pos + 6) = setting->data.v_color.alpha; | |||
375 | buffer->pos += 8; | |||
376 | break; | |||
377 | } | |||
378 | } | |||
379 | ||||
380 | XSettingsResult | |||
381 | xsettings_manager_notify (XSettingsManager *manager) | |||
382 | { | |||
383 | XSettingsBuffer buffer; | |||
384 | XSettingsList *iter; | |||
385 | int n_settings = 0; | |||
386 | ||||
387 | buffer.len = 12; /* byte-order + pad + SERIAL + N_SETTINGS */ | |||
388 | ||||
389 | iter = settings; | |||
390 | while (iter) | |||
| ||||
391 | { | |||
392 | buffer.len += setting_length (iter->setting); | |||
393 | n_settings++; | |||
394 | iter = iter->next; | |||
395 | } | |||
396 | ||||
397 | buffer.data = buffer.pos = malloc (buffer.len); | |||
398 | if (!buffer.data) | |||
399 | return XSETTINGS_NO_MEM; | |||
400 | ||||
401 | *buffer.pos = xsettings_byte_order (); | |||
402 | ||||
403 | buffer.pos += 4; | |||
404 | *(CARD32 *)buffer.pos = manager->serial++; | |||
405 | buffer.pos += 4; | |||
406 | *(CARD32 *)buffer.pos = n_settings; | |||
407 | buffer.pos += 4; | |||
408 | ||||
409 | iter = settings; | |||
410 | while (iter) | |||
411 | { | |||
412 | setting_store (iter->setting, &buffer); | |||
413 | iter = iter->next; | |||
414 | } | |||
415 | ||||
416 | XChangeProperty (manager->display, manager->window, | |||
417 | manager->xsettings_atom, manager->xsettings_atom, | |||
418 | 8, PropModeReplace0, buffer.data, buffer.len); | |||
419 | ||||
420 | free (buffer.data); | |||
421 | ||||
422 | return XSETTINGS_SUCCESS; | |||
423 | } | |||
424 |