xwm: check to see if a LuccaWindow already exists for a window before creating a...
[luccawm.git] / xwm / lucca-window.c
blob810a0b8de56e945944043de07775abc14b6671e0
1 /* Copyright (c) 2008 Vincent Povirk
3 Permission is hereby granted, free of charge, to any person
4 obtaining a copy of this software and associated documentation
5 files (the "Software"), to deal in the Software without
6 restriction, including without limitation the rights to use,
7 copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following
10 conditions:
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 OTHER DEALINGS IN THE SOFTWARE.
25 #include "lucca-display-private.h"
27 /* Implementation of LuccaWindow */
29 static GObjectClass* parent_class = NULL;
31 static GData* state_atom_constants;
33 /* property id's */
34 enum {
35 PROP_VALID=1,
36 PROP_REQUESTED_TITLE,
37 PROP_WINDOW,
40 static void lucca_window_init(GTypeInstance* instance, gpointer g_class) {
41 LuccaWindow* window = LUCCA_WINDOW(instance);
43 window->valid = FALSE;
45 window->dispose_has_run = FALSE;
47 window->display = NULL;
48 window->window = NULL;
49 window->xwindow = 0;
50 window->xwmhints = NULL;
51 window->properties_set = NULL;
52 window->window_parent = NULL;
53 window->requested_title = NULL;
54 window->owner_callback = NULL;
55 window->bin = NULL;
58 static void lucca_window_dispose(GObject* obj) {
59 LuccaWindow* window = LUCCA_WINDOW(obj);
61 if (window->dispose_has_run) {
62 return;
64 window->dispose_has_run = TRUE;
66 window->valid = FALSE;
68 g_object_unref(window->display);
69 window->display = NULL;
71 g_object_unref(window->window);
72 window->window = NULL;
74 if (window->bin)
75 g_object_unref(window->bin);
76 window->bin = NULL;
78 window->xwindow = 0;
80 if (window->xwmhints) {
81 XFree(window->xwmhints);
84 g_datalist_clear(&window->properties_set);
86 g_object_unref(window->window_parent);
87 window->window_parent = NULL;
89 g_free(window->requested_title);
90 window->requested_title = NULL;
92 G_OBJECT_CLASS(parent_class)->dispose(obj);
95 static void lucca_window_get_property(GObject* object, guint property_id, GValue* value, GParamSpec* pspec) {
96 LuccaWindow* window = LUCCA_WINDOW(object);
98 switch (property_id) {
99 case PROP_VALID:
100 g_value_set_boolean(value, window->valid);
101 break;
102 case PROP_REQUESTED_TITLE:
103 g_value_set_string(value, window->requested_title);
104 break;
105 case PROP_WINDOW:
106 g_value_set_object(value, window->bin);
107 break;
108 default:
109 G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec);
110 break;
114 static void lucca_window_class_init(gpointer g_class, gpointer class_data) {
115 LuccaWindowClass* klass = (LuccaWindowClass*)g_class;
116 GObjectClass* gobclass = G_OBJECT_CLASS(g_class);
117 GParamSpec *pspec;
119 /* method overrides */
120 gobclass->dispose = lucca_window_dispose;
121 gobclass->get_property = lucca_window_get_property;
123 /* properties */
124 pspec = g_param_spec_boolean(
125 "valid",
126 "valid",
127 "TRUE if this manages a display's windows",
128 0, /* default value */
129 G_PARAM_READABLE);
130 g_object_class_install_property(gobclass, PROP_VALID, pspec);
132 pspec = g_param_spec_string(
133 "requested-title",
134 "requested title",
135 "The title the application requested for this window",
136 "", /* default value */
137 G_PARAM_READABLE);
138 g_object_class_install_property(gobclass, PROP_REQUESTED_TITLE, pspec);
140 pspec = g_param_spec_object(
141 "window",
142 "window",
143 "The GTK window for an internal LuccaWindow",
144 GTK_TYPE_WINDOW,
145 G_PARAM_READABLE);
146 g_object_class_install_property(gobclass, PROP_WINDOW, pspec);
148 /* signals */
150 klass->withdraw_signal_id = g_signal_new(
151 "withdraw",
152 G_TYPE_FROM_CLASS(g_class),
153 G_SIGNAL_RUN_LAST,
154 0, /* class_offset */
155 NULL, /* accumulator */
156 NULL, /* accu_data */
157 g_cclosure_marshal_VOID__VOID,
158 G_TYPE_NONE,
159 0 /* n_params */
162 parent_class = g_type_class_peek_parent(klass);
164 g_datalist_init(&state_atom_constants);
165 g_datalist_set_data(&state_atom_constants, "_NET_WM_STATE_MODAL", GINT_TO_POINTER(LUCCA_STATE_MODAL));
166 g_datalist_set_data(&state_atom_constants, "_NET_WM_STATE_STICKY", GINT_TO_POINTER(LUCCA_STATE_STICKY));
167 g_datalist_set_data(&state_atom_constants, "_NET_WM_STATE_MAXIMIZED_VIRT", GINT_TO_POINTER(LUCCA_STATE_MAXIMIZED_VIRT));
168 g_datalist_set_data(&state_atom_constants, "_NET_WM_STATE_MAXIMIZED_HORZ", GINT_TO_POINTER(LUCCA_STATE_MAXIMIZED_HORZ));
169 g_datalist_set_data(&state_atom_constants, "_NET_WM_STATE_SHADED", GINT_TO_POINTER(LUCCA_STATE_SHADED));
170 g_datalist_set_data(&state_atom_constants, "_NET_WM_STATE_SKIP_TASKBAR", GINT_TO_POINTER(LUCCA_STATE_SKIP_TASKBAR));
171 g_datalist_set_data(&state_atom_constants, "_NET_WM_STATE_SKIP_PAGER", GINT_TO_POINTER(LUCCA_STATE_SKIP_PAGER));
172 g_datalist_set_data(&state_atom_constants, "_NET_WM_STATE_HIDDEN", GINT_TO_POINTER(LUCCA_STATE_HIDDEN));
173 g_datalist_set_data(&state_atom_constants, "_NET_WM_STATE_FULLSCREEN", GINT_TO_POINTER(LUCCA_STATE_FULLSCREEN));
174 g_datalist_set_data(&state_atom_constants, "_NET_WM_STATE_ABOVE", GINT_TO_POINTER(LUCCA_STATE_ABOVE));
175 g_datalist_set_data(&state_atom_constants, "_NET_WM_STATE_BELOW", GINT_TO_POINTER(LUCCA_STATE_BELOW));
176 g_datalist_set_data(&state_atom_constants, "_NET_WM_STATE_DEMANDS_ATTENTION", GINT_TO_POINTER(LUCCA_STATE_DEMANDS_ATTENTION));
179 GType lucca_window_get_type() {
180 static GType type = 0;
181 if (type == 0) {
182 static const GTypeInfo info = {
183 sizeof (LuccaWindowClass),
184 NULL, /* base_init */
185 NULL, /* base_finalize */
186 lucca_window_class_init,
187 NULL, /* class_finalize */
188 NULL, /* class_data */
189 sizeof (LuccaWindow),
190 0, /* n_preallocs */
191 lucca_window_init
193 type = g_type_register_static (G_TYPE_OBJECT, "LuccaWindowType", &info, 0);
195 return type;
198 /* Method definitions */
200 /* retrieves a window's title from the X server; the result should be freed with g_free() */
201 static gchar* _get_requested_title(LuccaWindow* window) {
202 gchar* result;
204 result = lucca_window_get_utf8(window, "_NET_WM_NAME");
206 if (result == NULL) {
207 result = lucca_window_get_utf8(window, "WM_NAME");
210 return result;
213 static XWMHints* _get_wm_hints(LuccaWindow* window) {
214 XWMHints* result;
216 if (window->badwindow || !g_datalist_get_data(&window->properties_set, "WM_HINTS")) {
217 return NULL;
220 gdk_error_trap_push();
221 result = XGetWMHints(window->display->xdisplay, window->xwindow);
222 gdk_flush();
223 if (gdk_error_trap_pop() == BadWindow) {
224 window->badwindow = TRUE;
228 return result;
231 static void _update_normal_hints(LuccaWindow* window) {
232 Status status;
234 if (window->badwindow || !g_datalist_get_data(&window->properties_set, "WM_NORMAL_HINTS")) {
235 window->xsizehints_supplied = 0;
236 return;
239 gdk_error_trap_push();
240 status = XGetWMNormalHints(window->display->xdisplay, window->xwindow, &window->xsizehints, &window->xsizehints_supplied);
241 gdk_flush();
242 if (gdk_error_trap_pop() == BadWindow) {
243 window->badwindow = TRUE;
244 window->xsizehints_supplied = 0;
248 LuccaWindow* lucca_window_new(Window xwindow, LuccaScreen* screen, gboolean existing, gboolean internal) {
249 XWindowAttributes xattr;
250 LuccaWindow* result;
251 GData* properties_set;
252 Atom* property_atoms;
253 int property_count;
254 int i;
255 Status status;
256 GdkWindow* gdkwindow;
258 gdkwindow = gdk_window_foreign_new_for_display(screen->display->display, xwindow);
259 if (g_hash_table_lookup(screen->display->valid_windows, gdkwindow)) {
260 return NULL;
263 /* make sure it wants to be managed */
264 gdk_error_trap_push();
265 status = XGetWindowAttributes(screen->display->xdisplay, xwindow, &xattr);
266 gdk_flush();
267 if (gdk_error_trap_pop()) {
268 /* the window doesn't exist anymore */
269 return NULL;
271 if ((existing && xattr.map_state != IsViewable) || (xattr.override_redirect && !internal)) {
272 /* this is either an existing unmapped window or a non-internal override_redirect window; ignore it */
273 return NULL;
276 /* get a list of properties for the window; knowing if a property exists makes requesting various information faster later */
277 g_datalist_init(&properties_set);
278 gdk_error_trap_push();
279 property_atoms = XListProperties(screen->display->xdisplay, xwindow, &property_count);
280 gdk_flush();
281 if (gdk_error_trap_pop()) {
282 /* the window doesn't exist anymore */
283 g_datalist_clear(&properties_set);
284 return NULL;
286 for (i=0; i<property_count; i++) {
287 g_datalist_set_data(&properties_set, XGetAtomName(screen->display->xdisplay, property_atoms[i]), GINT_TO_POINTER(1));
289 XFree(property_atoms);
291 result = g_object_new(LUCCA_TYPE_WINDOW, NULL);
293 result->valid = TRUE;
294 result->badwindow = FALSE;
295 result->internal = internal;
296 result->window = gdkwindow;
297 result->xwindow = xwindow;
298 result->xattr = xattr;
299 result->display = g_object_ref(screen->display);
300 result->properties_set = properties_set;
302 if (xattr.map_state == IsViewable) {
303 result->icccm_state = NormalState;
305 else {
306 result->icccm_state = WithdrawnState;
309 /* get other information about the window from the server */
310 result->requested_title = _get_requested_title(result);
311 result->xwmhints = _get_wm_hints(result);
312 _update_normal_hints(result);
313 result->window_parent = g_object_ref(screen->root);
315 g_hash_table_insert(screen->display->valid_windows, result->window, result);
317 if (!xattr.override_redirect) {
318 g_signal_emit(screen->display, LUCCA_DISPLAY_GET_CLASS(screen->display)->new_window_signal_id, 0, result);
321 return result;
324 LuccaWindow* lucca_window_new_internal(LuccaBin* bin, LuccaScreen* screen) {
325 GdkWindow *window;
326 Window xwindow;
327 XWindowAttributes xattr;
328 LuccaWindow* result;
329 Window* hash_key;
330 GData* properties_set;
331 Atom* property_atoms;
332 int property_count;
333 int i;
335 window = g_object_ref(GTK_WIDGET(bin)->window);
336 xwindow = GDK_WINDOW_XWINDOW(window);
338 XGetWindowAttributes(screen->display->xdisplay, xwindow, &xattr);
340 /* get a list of properties for the window; knowing if a property exists makes requesting various information faster later */
341 g_datalist_init(&properties_set);
342 gdk_error_trap_push();
343 property_atoms = XListProperties(screen->display->xdisplay, xwindow, &property_count);
344 gdk_flush();
345 if (gdk_error_trap_pop()) {
346 /* the window doesn't exist anymore */
347 g_datalist_clear(&properties_set);
348 return NULL;
350 for (i=0; i<property_count; i++) {
351 g_datalist_set_data(&properties_set, XGetAtomName(screen->display->xdisplay, property_atoms[i]), GINT_TO_POINTER(1));
353 XFree(property_atoms);
355 result = g_object_new(LUCCA_TYPE_WINDOW, NULL);
357 result->valid = TRUE;
358 result->badwindow = FALSE;
359 result->internal = TRUE;
360 result->xattr = xattr;
361 result->window = window;
362 result->xwindow = xwindow;
363 result->bin = bin;
364 result->display = g_object_ref(screen->display);
365 result->properties_set = properties_set;
366 result->icccm_state = WithdrawnState;
368 /* get other information about the window from the server */
369 result->requested_title = _get_requested_title(result);
370 result->xwmhints = _get_wm_hints(result);
371 _update_normal_hints(result);
372 result->window_parent = g_object_ref(screen->root);
374 hash_key = g_malloc(sizeof(Window));
375 *hash_key = xwindow;
376 g_hash_table_insert(screen->display->valid_windows, hash_key, result);
378 if (!xattr.override_redirect) {
379 g_signal_emit(screen->display, LUCCA_DISPLAY_GET_CLASS(screen->display)->new_window_signal_id, 0, result);
382 return result;
385 gchar* lucca_window_get_utf8(LuccaWindow* window, gchar* property) {
386 int status;
387 Atom prop;
388 Atom xactual_type;
389 int actual_format;
390 unsigned long nitems;
391 unsigned long length;
392 unsigned long bytes_after;
393 unsigned char* data=NULL;
394 gchar* value=NULL;
395 gchar** list=NULL;
397 /* if the property isn't set, return no strings */
398 if (window->badwindow || !g_datalist_get_data(&window->properties_set, property)) {
399 return NULL;
402 prop = XInternAtom(window->display->xdisplay, property, True);
404 gdk_error_trap_push();
405 status = XGetWindowProperty(
406 window->display->xdisplay, /* display */
407 window->xwindow, /* window */
408 prop, /* property */
409 0, /* long_offset */
410 0, /* long_length */
411 False, /* delete */
412 AnyPropertyType, /* req_type */
413 &xactual_type, /* actual_type_return */
414 &actual_format, /* actual_format_return */
415 &nitems, /* nitems_return */
416 &length, /* bytes_after_return */
417 &data /* prop_return */
419 if (data != NULL) {
420 XFree(data);
423 if (status == Success) {
424 status = XGetWindowProperty(
425 window->display->xdisplay, /* display */
426 window->xwindow, /* window */
427 prop, /* property */
428 0, /* long_offset */
429 (length+3)/4, /* long_length */
430 False, /* delete */
431 AnyPropertyType, /* req_type */
432 &xactual_type, /* actual_type_return */
433 &actual_format, /* actual_format_return */
434 &nitems, /* nitems_return */
435 &bytes_after, /* bytes_after_return */
436 &data /* prop_return */
439 if (status == Success) {
440 nitems = gdk_text_property_to_utf8_list_for_display(
441 window->display->display, /* display */
442 gdk_atom_intern(XGetAtomName(window->display->xdisplay, xactual_type), FALSE), /* encoding */
443 actual_format, /* format */
444 data, /* text */
445 length, /* length */
446 &list /* list */
448 if (nitems >= 1) {
449 value = g_strdup(list[0]);
451 g_strfreev(list);
452 XFree(data);
456 gdk_flush();
457 if (gdk_error_trap_pop() == BadWindow) {
458 window->badwindow = TRUE;
461 return value;
464 /* lucca_window_get_atoms: get a list of atoms in a window property, to be freed with XFree() */
465 Atom* lucca_window_get_atoms(LuccaWindow* window, gchar* property, guint* length) {
466 int status;
467 Atom prop;
468 Atom xactual_type;
469 int actual_format;
470 unsigned long nitems;
471 unsigned long size;
472 unsigned long bytes_after;
473 unsigned char* data=NULL;
475 *length = 0;
477 /* if the property isn't set, return no strings */
478 if (window->badwindow || !g_datalist_get_data(&window->properties_set, property)) {
479 return NULL;
482 prop = XInternAtom(window->display->xdisplay, property, True);
484 gdk_error_trap_push();
485 status = XGetWindowProperty(
486 window->display->xdisplay, /* display */
487 window->xwindow, /* window */
488 prop, /* property */
489 0, /* long_offset */
490 0, /* long_length */
491 False, /* delete */
492 window->display->xatom_atom, /* req_type */
493 &xactual_type, /* actual_type_return */
494 &actual_format, /* actual_format_return */
495 &nitems, /* nitems_return */
496 &size, /* bytes_after_return */
497 &data /* prop_return */
499 if (data != NULL) {
500 XFree(data);
503 if (status == Success) {
504 status = XGetWindowProperty(
505 window->display->xdisplay, /* display */
506 window->xwindow, /* window */
507 prop, /* property */
508 0, /* long_offset */
509 (size+3)/4, /* long_length */
510 False, /* delete */
511 window->display->xatom_atom, /* req_type */
512 &xactual_type, /* actual_type_return */
513 &actual_format, /* actual_format_return */
514 &nitems, /* nitems_return */
515 &bytes_after, /* bytes_after_return */
516 &data /* prop_return */
519 if (status == Success) {
520 *length = size/sizeof(Atom);
524 gdk_flush();
525 if (gdk_error_trap_pop() == BadWindow) {
526 window->badwindow = TRUE;
529 return (Atom*)data;
532 void lucca_window_get_geometry_hints(LuccaWindow* window, GdkGeometry* geometry, GdkWindowHints* geom_mask) {
533 g_assert(window->valid);
535 if (window->xwmhints == NULL) {
536 *geom_mask = 0;
537 return;
540 if (window->xsizehints_supplied & USPosition) {
541 *geom_mask |= GDK_HINT_USER_POS;
544 if (window->xsizehints_supplied & USSize) {
545 *geom_mask |= GDK_HINT_USER_SIZE;
548 if (window->xsizehints_supplied & PPosition) {
549 *geom_mask |= GDK_HINT_POS;
552 /* if (window->xsizehints_supplied & PSize) ... no field in GdkWindowHints corresponds to this */
554 if (window->xsizehints_supplied & PMinSize) {
555 *geom_mask |= GDK_HINT_MIN_SIZE;
556 geometry->min_width = window->xsizehints.min_width;
557 geometry->min_height = window->xsizehints.min_height;
560 if (window->xsizehints_supplied & PMaxSize) {
561 *geom_mask |= GDK_HINT_MAX_SIZE;
562 geometry->max_width = window->xsizehints.max_width;
563 geometry->max_height = window->xsizehints.max_height;
566 if (window->xsizehints_supplied & PResizeInc) {
567 *geom_mask |= GDK_HINT_RESIZE_INC;
568 geometry->width_inc = window->xsizehints.width_inc;
569 geometry->height_inc = window->xsizehints.height_inc;
572 if (window->xsizehints_supplied & PAspect) {
573 *geom_mask |= GDK_HINT_ASPECT;
574 geometry->min_aspect = (gdouble)window->xsizehints.min_aspect.x / (gdouble)window->xsizehints.min_aspect.y;
575 geometry->max_aspect = (gdouble)window->xsizehints.max_aspect.x / (gdouble)window->xsizehints.max_aspect.y;
578 if (window->xsizehints_supplied & PBaseSize) {
579 *geom_mask |= GDK_HINT_BASE_SIZE;
580 geometry->base_width = window->xsizehints.base_width;
581 geometry->base_height = window->xsizehints.base_height;
584 if (window->xsizehints_supplied & PWinGravity) {
585 *geom_mask |= GDK_HINT_WIN_GRAVITY;
586 geometry->win_gravity = (GdkGravity)window->xsizehints.win_gravity;
590 void lucca_window_get_requested_states(LuccaWindow* window, LuccaState** states, guint* statecount) {
591 Atom* state_atoms;
592 guint state_atom_count;
593 guint i, j;
595 g_assert(window->valid);
597 state_atoms = lucca_window_get_atoms(window, "_NET_WM_STATE", &state_atom_count);
599 if (state_atoms == NULL) {
600 /* no _NET_WM_STATE, fall back on WM_HINTS */
601 if ((window->xwmhints->flags & StateHint) && (window->xwmhints->initial_state == IconicState)) {
602 *statecount = 1;
603 *states = g_malloc(sizeof(LuccaState));
604 *states[0] = LUCCA_STATE_HIDDEN;
606 else {
607 *statecount = 0;
608 *states = NULL;
611 else {
612 *states = g_malloc(sizeof(LuccaState) * state_atom_count);
613 j=0;
614 for (i=0; i<state_atom_count; i++) {
615 LuccaState state = GPOINTER_TO_INT(g_datalist_get_data(&state_atom_constants, XGetAtomName(window->display->xdisplay, state_atoms[i])));
616 if (state != 0) {
617 *states[j++] = state;
620 *statecount = j;
621 XFree(state_atoms);
625 void lucca_window_configure(LuccaWindow* window, GdkWindow* parent, gint x, gint y, gint width, gint height, gboolean visible) {
626 ICCCM_STATE new_icccm_state;
627 gboolean window_is_mapped;
628 gint error;
630 g_assert(window->valid);
632 if (visible) {
633 new_icccm_state = NormalState;
635 else {
636 new_icccm_state = IconicState;
639 if (window->badwindow) {
640 /* the window doesn't exist anymore; pretend everything worked */
641 if (parent != window->window_parent) {
642 g_object_unref(window->window_parent);
643 window->window_parent = g_object_ref(parent);
645 window->icccm_state = new_icccm_state;
646 window->xattr.x = x;
647 window->xattr.y = y;
648 window->xattr.width = width;
649 window->xattr.height = height;
651 else {
652 gdk_error_trap_push();
654 /* if the window is being reparented, we want to unmap, reparent, resize, and then remap it so that we don't end up with an intermediate step where the window is reparented with the wrong size; also, unmap it if we're asked to make it not visible */
655 if (((parent != window->window_parent) && (window->icccm_state == NormalState)) || !visible) {
656 if (window->internal) {
657 gtk_widget_hide(GTK_WIDGET(window->bin));
659 else {
660 XUnmapWindow(window->display->xdisplay, window->xwindow);
662 window_is_mapped = FALSE;
664 else if (window->icccm_state == NormalState) {
665 window_is_mapped = TRUE;
667 else {
668 window_is_mapped = FALSE;
671 if ((new_icccm_state != window->icccm_state) && (!window->internal)) {
672 ICCCM_WM_STATE new_wm_state;
673 GdkAtom wm_state_atom = gdk_atom_intern("WM_STATE", TRUE);
674 new_wm_state.state = new_icccm_state;
675 new_wm_state.icon = None;
677 gdk_property_change(
678 window->window, /* window */
679 wm_state_atom, /* property */
680 wm_state_atom, /* type */
681 32, /* format */
682 GDK_PROP_MODE_REPLACE, /* mode */
683 (guchar*)&new_wm_state, /* data */
684 2 /* nelements */
686 window->icccm_state = new_icccm_state;
689 if (parent != window->window_parent) {
690 if (window->internal) {
691 lucca_bin_set_parent(window->bin, parent);
693 else {
694 XReparentWindow(window->display->xdisplay, window->xwindow, GDK_WINDOW_XWINDOW(parent), x, y);
696 g_object_unref(window->window_parent);
697 window->window_parent = g_object_ref(parent);
700 if (window->internal) {
701 lucca_bin_move_resize(window->bin, x, y, width, height);
703 else {
704 XMoveResizeWindow(window->display->xdisplay, window->xwindow, x, y, (unsigned)width, (unsigned)height);
707 if (visible && !window_is_mapped) {
708 if (window->internal) {
709 gtk_widget_show(GTK_WIDGET(window->bin));
711 else {
712 XMapWindow(window->display->xdisplay, window->xwindow);
716 gdk_flush();
718 error = gdk_error_trap_pop();
719 if (error == BadWindow) {
720 window->badwindow = TRUE;
722 else if (error != 0) {
723 g_error("Unexpected X error: %i\n", error);
728 void lucca_window_change_owner(LuccaWindow* window, GClosure* callback) {
729 if (window->owner_callback != NULL) {
730 GValue value={0,};
732 g_value_init(&value, LUCCA_TYPE_WINDOW);
734 g_value_set_object(&value, window);
736 g_closure_invoke(window->owner_callback,
737 NULL,
739 &value,
740 NULL);
742 g_closure_unref(window->owner_callback);
744 g_value_unset(&value);
747 window->owner_callback = callback;
749 if (callback != NULL) {
750 g_closure_ref(callback);
751 g_closure_sink(callback);
755 void lucca_window_withdraw_finish(LuccaWindow* window) {
756 if (!window->badwindow) {
757 GdkAtom wmstate;
758 gint error;
760 wmstate = gdk_atom_intern("WM_STATE", FALSE);
762 gdk_error_trap_push();
764 gdk_property_delete(window->window, wmstate);
766 gdk_flush();
768 error = gdk_error_trap_pop();
769 if (error == BadWindow) {
770 window->badwindow = TRUE;
772 else if (error != 0) {
773 g_error("Unexpected X error: %i\n", error);
777 lucca_window_change_owner(window, NULL);
779 window->badwindow = TRUE;
780 window->valid = FALSE;
782 g_signal_emit(window, LUCCA_WINDOW_GET_CLASS(window)->withdraw_signal_id, 0);