1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 #include <X11/Xutil.h>
22 #include <X11/Xatom.h>
23 #include <netinet/in.h>
25 #include "../config.h"
27 #include "gdkprivate.h"
33 #include <X11/extensions/shape.h>
36 int nevent_masks = 20;
37 int event_mask_table[20] =
41 PointerMotionHintMask,
46 ButtonPressMask | OwnerGrabButtonMask,
47 ButtonReleaseMask | OwnerGrabButtonMask,
58 SubstructureNotifyMask
61 static gboolean gdk_window_have_shape_ext (void);
63 /* internal function created for and used by gdk_window_xid_at_coords */
65 gdk_window_xid_at (Window base,
74 GdkWindowPrivate *private;
77 Window child = 0, parent_win = 0, root_win = 0;
79 unsigned int ww, wh, wb, wd, num;
82 window = (GdkWindow*) &gdk_root_parent;
83 private = (GdkWindowPrivate*) window;
84 disp = private->xdisplay;
85 if (!XGetGeometry (disp, base, &root_win, &wx, &wy, &ww, &wh, &wb, &wd))
92 (x < (int) (wx + ww)) &&
93 (y < (int) (wy + wh))))
96 if (!XQueryTree (disp, base, &root_win, &parent_win, &list, &num))
101 for (i = num - 1; ; i--)
103 if ((!excl_child) || (!g_list_find (excludes, (gpointer *) list[i])))
105 if ((child = gdk_window_xid_at (list[i], wx, wy, x, y, excludes, excl_child)) != 0)
120 * The following fucntion by The Rasterman <raster@redhat.com>
121 * This function returns the X Window ID in which the x y location is in
122 * (x and y being relative to the root window), excluding any windows listed
123 * in the GList excludes (this is a list of X Window ID's - gpointer being
126 * This is primarily designed for internal gdk use - for DND for example
127 * when using a shaped icon window as the drag object - you exclude the
128 * X Window ID of the "icon" (perhaps more if excludes may be needed) and
129 * You can get back an X Window ID as to what X Window ID is infact under
130 * those X,Y co-ordinates.
133 gdk_window_xid_at_coords (gint x,
139 GdkWindowPrivate *private;
142 Window root, child = 0, parent_win = 0, root_win = 0;
146 window = (GdkWindow*) &gdk_root_parent;
147 private = (GdkWindowPrivate*) window;
148 disp = private->xdisplay;
149 root = private->xwindow;
150 num = g_list_length (excludes);
153 if (!XQueryTree (disp, root, &root_win, &parent_win, &list, &num))
163 XWindowAttributes xwa;
165 XGetWindowAttributes (disp, list [i], &xwa);
167 if (xwa.map_state != IsViewable)
170 if (excl_child && g_list_find (excludes, (gpointer *) list[i]))
173 if ((child = gdk_window_xid_at (list[i], 0, 0, x, y, excludes, excl_child)) == 0)
178 if (!g_list_find (excludes, (gpointer *) child))
181 XUngrabServer (disp);
188 XUngrabServer (disp);
194 XUngrabServer (disp);
199 gdk_window_init (void)
201 XWindowAttributes xattributes;
204 unsigned int border_width;
208 XGetGeometry (gdk_display, gdk_root_window, &gdk_root_window,
209 &x, &y, &width, &height, &border_width, &depth);
210 XGetWindowAttributes (gdk_display, gdk_root_window, &xattributes);
212 gdk_root_parent.xwindow = gdk_root_window;
213 gdk_root_parent.xdisplay = gdk_display;
214 gdk_root_parent.window_type = GDK_WINDOW_ROOT;
215 gdk_root_parent.window.user_data = NULL;
216 gdk_root_parent.width = width;
217 gdk_root_parent.height = height;
218 gdk_root_parent.children = NULL;
219 gdk_root_parent.colormap = NULL;
220 gdk_root_parent.ref_count = 1;
222 gdk_xid_table_insert (&gdk_root_window, &gdk_root_parent);
226 gdk_window_new (GdkWindow *parent,
227 GdkWindowAttr *attributes,
228 gint attributes_mask)
231 GdkWindowPrivate *private;
232 GdkWindowPrivate *parent_private;
234 Display *parent_display;
237 XSetWindowAttributes xattributes;
238 long xattributes_mask;
239 XSizeHints size_hints;
241 XClassHint *class_hint;
247 g_return_val_if_fail (attributes != NULL, NULL);
250 parent = (GdkWindow*) &gdk_root_parent;
252 parent_private = (GdkWindowPrivate*) parent;
253 if (parent_private->destroyed)
256 xparent = parent_private->xwindow;
257 parent_display = parent_private->xdisplay;
259 private = g_new (GdkWindowPrivate, 1);
260 window = (GdkWindow*) private;
262 private->parent = parent;
265 parent_private->children = g_list_prepend (parent_private->children, window);
267 private->xdisplay = parent_display;
268 private->destroyed = FALSE;
269 private->resize_count = 0;
270 private->ref_count = 1;
271 xattributes_mask = 0;
273 if (attributes_mask & GDK_WA_X)
278 if (attributes_mask & GDK_WA_Y)
285 private->width = (attributes->width > 1) ? (attributes->width) : (1);
286 private->height = (attributes->height > 1) ? (attributes->height) : (1);
287 private->window_type = attributes->window_type;
288 private->extension_events = FALSE;
290 private->filters = NULL;
291 private->children = NULL;
293 window->user_data = NULL;
295 if (attributes_mask & GDK_WA_VISUAL)
296 visual = attributes->visual;
298 visual = gdk_visual_get_system ();
299 xvisual = ((GdkVisualPrivate*) visual)->xvisual;
301 xattributes.event_mask = StructureNotifyMask;
302 for (i = 0; i < nevent_masks; i++)
304 if (attributes->event_mask & (1 << (i + 1)))
305 xattributes.event_mask |= event_mask_table[i];
308 if (xattributes.event_mask)
309 xattributes_mask |= CWEventMask;
311 if(attributes_mask & GDK_WA_NOREDIR) {
312 xattributes.override_redirect =
313 (attributes->override_redirect == FALSE)?False:True;
314 xattributes_mask |= CWOverrideRedirect;
316 xattributes.override_redirect = False;
318 if (attributes->wclass == GDK_INPUT_OUTPUT)
321 depth = visual->depth;
323 if (attributes_mask & GDK_WA_COLORMAP)
324 private->colormap = attributes->colormap;
326 private->colormap = gdk_colormap_get_system ();
328 xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen);
329 xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen);
330 xattributes_mask |= CWBorderPixel | CWBackPixel;
332 switch (private->window_type)
334 case GDK_WINDOW_TOPLEVEL:
335 xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
336 xattributes_mask |= CWColormap;
338 xparent = gdk_root_window;
341 case GDK_WINDOW_CHILD:
342 xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
343 xattributes_mask |= CWColormap;
346 case GDK_WINDOW_DIALOG:
347 xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
348 xattributes_mask |= CWColormap;
350 xparent = gdk_root_window;
353 case GDK_WINDOW_TEMP:
354 xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
355 xattributes_mask |= CWColormap;
357 xparent = gdk_root_window;
359 xattributes.save_under = True;
360 xattributes.override_redirect = True;
361 xattributes.cursor = None;
362 xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
364 case GDK_WINDOW_ROOT:
365 g_error ("cannot make windows of type GDK_WINDOW_ROOT");
367 case GDK_WINDOW_PIXMAP:
368 g_error ("cannot make windows of type GDK_WINDOW_PIXMAP (use gdk_pixmap_new)");
376 private->colormap = NULL;
379 private->xwindow = XCreateWindow (private->xdisplay, xparent,
380 x, y, private->width, private->height,
381 0, depth, class, xvisual,
382 xattributes_mask, &xattributes);
383 gdk_window_ref (window);
384 gdk_xid_table_insert (&private->xwindow, window);
386 if (private->colormap)
387 gdk_colormap_ref (private->colormap);
389 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
390 (attributes->cursor) :
393 switch (private->window_type)
395 case GDK_WINDOW_DIALOG:
396 XSetTransientForHint (private->xdisplay, private->xwindow, xparent);
397 case GDK_WINDOW_TOPLEVEL:
398 case GDK_WINDOW_TEMP:
399 XSetWMProtocols (private->xdisplay, private->xwindow, gdk_wm_window_protocols, 2);
401 case GDK_WINDOW_CHILD:
402 if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
403 (private->colormap != gdk_colormap_get_system ()) &&
404 (private->colormap != gdk_window_get_colormap (gdk_window_get_toplevel (window))))
406 GDK_NOTE (MISC, g_message ("adding colormap window\n"));
407 gdk_window_add_colormap_windows (window);
416 size_hints.flags = PSize;
417 size_hints.width = private->width;
418 size_hints.height = private->height;
420 wm_hints.flags = InputHint | StateHint | WindowGroupHint;
421 wm_hints.window_group = gdk_leader_window;
422 wm_hints.input = True;
423 wm_hints.initial_state = NormalState;
425 /* FIXME: Is there any point in doing this? Do any WM's pay
426 * attention to PSize, and even if they do, is this the
429 XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
431 XSetWMHints (private->xdisplay, private->xwindow, &wm_hints);
433 if (attributes_mask & GDK_WA_TITLE)
434 title = attributes->title;
436 title = g_get_prgname ();
438 XmbSetWMProperties (private->xdisplay, private->xwindow,
443 if (attributes_mask & GDK_WA_WMCLASS)
445 class_hint = XAllocClassHint ();
446 class_hint->res_name = attributes->wmclass_name;
447 class_hint->res_class = attributes->wmclass_class;
448 XSetClassHint (private->xdisplay, private->xwindow, class_hint);
457 gdk_window_foreign_new (guint32 anid)
460 GdkWindowPrivate *private;
461 GdkWindowPrivate *parent_private;
462 XWindowAttributes attrs;
464 Window *children = NULL;
467 if(!XGetWindowAttributes (gdk_display, anid, &attrs)) {
468 g_warning("XGetWindowAttributes failed on window ID %d\n", anid);
472 private = g_new (GdkWindowPrivate, 1);
473 window = (GdkWindow*) private;
475 /* FIXME: This is pretty expensive. Maybe the caller should supply
477 XQueryTree (gdk_display, anid, &root, &parent, &children, &nchildren);
481 private->parent = gdk_xid_table_lookup (parent);
483 parent_private = (GdkWindowPrivate *)private->parent;
486 parent_private->children = g_list_prepend (parent_private->children, window);
488 private->xwindow = anid;
489 private->xdisplay = gdk_display;
490 private->x = attrs.x;
491 private->y = attrs.y;
492 private->width = attrs.width;
493 private->height = attrs.height;
494 private->resize_count = 0;
495 private->ref_count = 1;
496 private->window_type = GDK_WINDOW_FOREIGN;
497 private->destroyed = FALSE;
498 private->extension_events = 0;
500 private->colormap = NULL;
502 private->filters = NULL;
503 private->children = NULL;
505 window->user_data = NULL;
507 gdk_window_ref (window);
508 gdk_xid_table_insert (&private->xwindow, window);
513 /* Call this function when you want a window and all its children to
514 disappear. When xdestroy is true, a request to destroy the XWindow
515 is sent out. When it is false, it is assumed that the XWindow has
516 been or will be destroyed by destroying some ancestor of this
520 gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy,
521 gboolean our_destroy)
523 GdkWindowPrivate *private;
524 GdkWindowPrivate *temp_private;
525 GdkWindow *temp_window;
529 g_return_if_fail (window != NULL);
531 private = (GdkWindowPrivate*) window;
533 switch (private->window_type)
535 case GDK_WINDOW_TOPLEVEL:
536 case GDK_WINDOW_CHILD:
537 case GDK_WINDOW_DIALOG:
538 case GDK_WINDOW_TEMP:
539 case GDK_WINDOW_FOREIGN:
540 if (!private->destroyed)
544 GdkWindowPrivate *parent_private = (GdkWindowPrivate *)private->parent;
545 if (parent_private->children)
546 parent_private->children = g_list_remove (parent_private->children, window);
549 if (private->window_type != GDK_WINDOW_FOREIGN)
551 children = tmp = private->children;
552 private->children = NULL;
556 temp_window = tmp->data;
559 temp_private = (GdkWindowPrivate*) temp_window;
561 gdk_window_internal_destroy (temp_window, FALSE,
565 g_list_free (children);
568 if (private->extension_events != 0)
569 gdk_input_window_destroy (window);
571 if (private->filters)
573 tmp = private->filters;
581 g_list_free (private->filters);
582 private->filters = NULL;
585 if (private->window_type == GDK_WINDOW_FOREIGN)
587 if (our_destroy && (private->parent != NULL))
589 /* It's somebody elses window, but in our heirarchy,
590 * so reparent it to the root window, and then send
591 * it a delete event, as if we were a WM
593 XClientMessageEvent xevent;
595 gdk_window_hide (window);
596 gdk_window_reparent (window, NULL, 0, 0);
598 xevent.type = ClientMessage;
599 xevent.window = private->xwindow;
600 xevent.message_type = gdk_wm_protocols;
602 xevent.data.l[0] = gdk_wm_delete_window;
603 xevent.data.l[1] = CurrentTime;
605 XSendEvent (private->xdisplay, private->xwindow,
606 False, 0, (XEvent *)&xevent);
610 XDestroyWindow (private->xdisplay, private->xwindow);
612 if (private->colormap)
613 gdk_colormap_unref (private->colormap);
615 private->destroyed = TRUE;
619 case GDK_WINDOW_ROOT:
620 g_error ("attempted to destroy root window");
623 case GDK_WINDOW_PIXMAP:
624 g_error ("called gdk_window_destroy on a pixmap (use gdk_pixmap_unref)");
629 /* Like internal_destroy, but also destroys the reference created by
633 gdk_window_destroy (GdkWindow *window)
635 gdk_window_internal_destroy (window, TRUE, TRUE);
636 gdk_window_unref (window);
639 /* This function is called when the XWindow is really gone. */
642 gdk_window_destroy_notify (GdkWindow *window)
644 GdkWindowPrivate *private;
646 g_return_if_fail (window != NULL);
648 private = (GdkWindowPrivate*) window;
650 if (!private->destroyed)
652 if (private->window_type == GDK_WINDOW_FOREIGN)
653 gdk_window_internal_destroy (window, FALSE, FALSE);
655 g_warning ("GdkWindow %#lx unexpectedly destroyed", private->xwindow);
658 gdk_xid_table_remove (private->xwindow);
659 gdk_window_unref (window);
663 gdk_window_ref (GdkWindow *window)
665 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
666 g_return_val_if_fail (window != NULL, NULL);
668 private->ref_count += 1;
673 gdk_window_unref (GdkWindow *window)
675 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
676 g_return_if_fail (window != NULL);
678 private->ref_count -= 1;
679 if (private->ref_count == 0)
681 if (!private->destroyed)
683 if (private->window_type == GDK_WINDOW_FOREIGN)
684 gdk_xid_table_remove (private->xwindow);
686 g_warning ("losing last reference to undestroyed window\n");
688 g_dataset_destroy (window);
694 gdk_window_show (GdkWindow *window)
696 GdkWindowPrivate *private;
698 g_return_if_fail (window != NULL);
700 private = (GdkWindowPrivate*) window;
701 if (!private->destroyed)
703 XRaiseWindow (private->xdisplay, private->xwindow);
704 XMapWindow (private->xdisplay, private->xwindow);
709 gdk_window_hide (GdkWindow *window)
711 GdkWindowPrivate *private;
713 g_return_if_fail (window != NULL);
715 private = (GdkWindowPrivate*) window;
716 if (!private->destroyed)
717 XUnmapWindow (private->xdisplay, private->xwindow);
721 gdk_window_withdraw (GdkWindow *window)
723 GdkWindowPrivate *private;
725 g_return_if_fail (window != NULL);
727 private = (GdkWindowPrivate*) window;
728 if (!private->destroyed)
729 XWithdrawWindow (private->xdisplay, private->xwindow, 0);
733 gdk_window_move (GdkWindow *window,
737 GdkWindowPrivate *private;
739 g_return_if_fail (window != NULL);
741 private = (GdkWindowPrivate*) window;
742 if (!private->destroyed)
744 XMoveWindow (private->xdisplay, private->xwindow, x, y);
746 if (private->window_type == GDK_WINDOW_CHILD)
755 gdk_window_resize (GdkWindow *window,
759 GdkWindowPrivate *private;
761 g_return_if_fail (window != NULL);
768 private = (GdkWindowPrivate*) window;
770 if (!private->destroyed &&
771 ((private->resize_count > 0) ||
772 (private->width != (guint16) width) ||
773 (private->height != (guint16) height)))
775 XResizeWindow (private->xdisplay, private->xwindow, width, height);
776 private->resize_count += 1;
778 if (private->window_type == GDK_WINDOW_CHILD)
780 private->width = width;
781 private->height = height;
787 gdk_window_move_resize (GdkWindow *window,
793 GdkWindowPrivate *private;
795 g_return_if_fail (window != NULL);
802 private = (GdkWindowPrivate*) window;
803 if (!private->destroyed)
805 XMoveResizeWindow (private->xdisplay, private->xwindow, x, y, width, height);
807 if (private->window_type == GDK_WINDOW_CHILD)
811 private->width = width;
812 private->height = height;
818 gdk_window_reparent (GdkWindow *window,
819 GdkWindow *new_parent,
823 GdkWindowPrivate *window_private;
824 GdkWindowPrivate *parent_private;
825 GdkWindowPrivate *old_parent_private;
827 g_return_if_fail (window != NULL);
830 new_parent = (GdkWindow*) &gdk_root_parent;
832 window_private = (GdkWindowPrivate*) window;
833 old_parent_private = (GdkWindowPrivate*)window_private->parent;
834 parent_private = (GdkWindowPrivate*) new_parent;
836 if (!window_private->destroyed && !parent_private->destroyed)
837 XReparentWindow (window_private->xdisplay,
838 window_private->xwindow,
839 parent_private->xwindow,
842 window_private->parent = new_parent;
844 if (old_parent_private)
845 old_parent_private->children = g_list_remove (old_parent_private->children, window);
846 parent_private->children = g_list_prepend (parent_private->children, window);
851 gdk_window_clear (GdkWindow *window)
853 GdkWindowPrivate *private;
855 g_return_if_fail (window != NULL);
857 private = (GdkWindowPrivate*) window;
859 if (!private->destroyed)
860 XClearWindow (private->xdisplay, private->xwindow);
864 gdk_window_clear_area (GdkWindow *window,
870 GdkWindowPrivate *private;
872 g_return_if_fail (window != NULL);
874 private = (GdkWindowPrivate*) window;
876 if (!private->destroyed)
877 XClearArea (private->xdisplay, private->xwindow,
878 x, y, width, height, False);
882 gdk_window_clear_area_e (GdkWindow *window,
888 GdkWindowPrivate *private;
890 g_return_if_fail (window != NULL);
892 private = (GdkWindowPrivate*) window;
894 if (!private->destroyed)
895 XClearArea (private->xdisplay, private->xwindow,
896 x, y, width, height, True);
900 gdk_window_copy_area (GdkWindow *window,
904 GdkWindow *source_window,
910 GdkWindowPrivate *src_private;
911 GdkWindowPrivate *dest_private;
912 GdkGCPrivate *gc_private;
914 g_return_if_fail (window != NULL);
915 g_return_if_fail (gc != NULL);
917 if (source_window == NULL)
918 source_window = window;
920 src_private = (GdkWindowPrivate*) source_window;
921 dest_private = (GdkWindowPrivate*) window;
922 gc_private = (GdkGCPrivate*) gc;
924 if (!src_private->destroyed && !dest_private->destroyed)
926 XCopyArea (dest_private->xdisplay, src_private->xwindow, dest_private->xwindow,
935 gdk_window_raise (GdkWindow *window)
937 GdkWindowPrivate *private;
939 g_return_if_fail (window != NULL);
941 private = (GdkWindowPrivate*) window;
943 if (!private->destroyed)
944 XRaiseWindow (private->xdisplay, private->xwindow);
948 gdk_window_lower (GdkWindow *window)
950 GdkWindowPrivate *private;
952 g_return_if_fail (window != NULL);
954 private = (GdkWindowPrivate*) window;
956 if (!private->destroyed)
957 XLowerWindow (private->xdisplay, private->xwindow);
961 gdk_window_set_user_data (GdkWindow *window,
964 g_return_if_fail (window != NULL);
966 window->user_data = user_data;
970 gdk_window_set_hints (GdkWindow *window,
979 GdkWindowPrivate *private;
980 XSizeHints size_hints;
982 g_return_if_fail (window != NULL);
984 private = (GdkWindowPrivate*) window;
985 if (private->destroyed)
988 size_hints.flags = 0;
990 if (flags & GDK_HINT_POS)
992 size_hints.flags |= PPosition;
997 if (flags & GDK_HINT_MIN_SIZE)
999 size_hints.flags |= PMinSize;
1000 size_hints.min_width = min_width;
1001 size_hints.min_height = min_height;
1004 if (flags & GDK_HINT_MAX_SIZE)
1006 size_hints.flags |= PMaxSize;
1007 size_hints.max_width = max_width;
1008 size_hints.max_height = max_height;
1012 XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
1016 gdk_window_set_title (GdkWindow *window,
1019 GdkWindowPrivate *private;
1021 g_return_if_fail (window != NULL);
1023 private = (GdkWindowPrivate*) window;
1024 if (!private->destroyed)
1025 XmbSetWMProperties (private->xdisplay, private->xwindow,
1026 title, title, NULL, 0, NULL, NULL, NULL);
1030 gdk_window_set_background (GdkWindow *window,
1033 GdkWindowPrivate *private;
1035 g_return_if_fail (window != NULL);
1037 private = (GdkWindowPrivate*) window;
1038 if (!private->destroyed)
1039 XSetWindowBackground (private->xdisplay, private->xwindow, color->pixel);
1043 gdk_window_set_back_pixmap (GdkWindow *window,
1045 gint parent_relative)
1047 GdkWindowPrivate *window_private;
1048 GdkPixmapPrivate *pixmap_private;
1051 g_return_if_fail (window != NULL);
1053 window_private = (GdkWindowPrivate*) window;
1054 pixmap_private = (GdkPixmapPrivate*) pixmap;
1057 xpixmap = pixmap_private->xwindow;
1061 if (parent_relative)
1062 xpixmap = ParentRelative;
1064 if (!window_private->destroyed)
1065 XSetWindowBackgroundPixmap (window_private->xdisplay, window_private->xwindow, xpixmap);
1069 gdk_window_set_cursor (GdkWindow *window,
1072 GdkWindowPrivate *window_private;
1073 GdkCursorPrivate *cursor_private;
1076 g_return_if_fail (window != NULL);
1078 window_private = (GdkWindowPrivate*) window;
1079 cursor_private = (GdkCursorPrivate*) cursor;
1084 xcursor = cursor_private->xcursor;
1086 if (!window_private->destroyed)
1087 XDefineCursor (window_private->xdisplay, window_private->xwindow, xcursor);
1091 gdk_window_set_colormap (GdkWindow *window,
1092 GdkColormap *colormap)
1094 GdkWindowPrivate *window_private;
1095 GdkColormapPrivate *colormap_private;
1097 g_return_if_fail (window != NULL);
1098 g_return_if_fail (colormap != NULL);
1100 window_private = (GdkWindowPrivate*) window;
1101 colormap_private = (GdkColormapPrivate*) colormap;
1103 if (!window_private->destroyed)
1105 XSetWindowColormap (window_private->xdisplay,
1106 window_private->xwindow,
1107 colormap_private->xcolormap);
1109 if (window_private->colormap)
1110 gdk_colormap_unref (window_private->colormap);
1111 window_private->colormap = colormap;
1112 gdk_colormap_ref (window_private->colormap);
1114 if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
1115 gdk_window_add_colormap_windows (window);
1120 gdk_window_get_user_data (GdkWindow *window,
1123 g_return_if_fail (window != NULL);
1125 *data = window->user_data;
1129 gdk_window_get_geometry (GdkWindow *window,
1136 GdkWindowPrivate *window_private;
1142 guint tborder_width;
1146 window = (GdkWindow*) &gdk_root_parent;
1148 window_private = (GdkWindowPrivate*) window;
1150 if (!window_private->destroyed)
1152 XGetGeometry (window_private->xdisplay, window_private->xwindow,
1153 &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
1169 gdk_window_get_position (GdkWindow *window,
1173 GdkWindowPrivate *window_private;
1175 g_return_if_fail (window != NULL);
1177 window_private = (GdkWindowPrivate*) window;
1180 *x = window_private->x;
1182 *y = window_private->y;
1186 gdk_window_get_size (GdkWindow *window,
1190 GdkWindowPrivate *window_private;
1192 g_return_if_fail (window != NULL);
1194 window_private = (GdkWindowPrivate*) window;
1197 *width = window_private->width;
1199 *height = window_private->height;
1203 gdk_window_get_visual (GdkWindow *window)
1205 GdkWindowPrivate *window_private;
1206 XWindowAttributes window_attributes;
1208 g_return_val_if_fail (window != NULL, NULL);
1210 window_private = (GdkWindowPrivate*) window;
1211 /* Huh? ->parent is never set for a pixmap. We should just return
1214 while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP))
1215 window_private = (GdkWindowPrivate*) window_private->parent;
1217 if (window_private && !window_private->destroyed)
1219 if (window_private->colormap == NULL)
1221 XGetWindowAttributes (window_private->xdisplay,
1222 window_private->xwindow,
1223 &window_attributes);
1224 return gdk_visual_lookup (window_attributes.visual);
1227 return ((GdkColormapPrivate *)window_private->colormap)->visual;
1234 gdk_window_get_colormap (GdkWindow *window)
1236 GdkWindowPrivate *window_private;
1237 XWindowAttributes window_attributes;
1239 g_return_val_if_fail (window != NULL, NULL);
1240 window_private = (GdkWindowPrivate*) window;
1242 g_return_val_if_fail (window_private->window_type != GDK_WINDOW_PIXMAP, NULL);
1243 if (!window_private->destroyed)
1245 if (window_private->colormap == NULL)
1247 XGetWindowAttributes (window_private->xdisplay,
1248 window_private->xwindow,
1249 &window_attributes);
1250 return gdk_colormap_lookup (window_attributes.colormap);
1253 return window_private->colormap;
1260 gdk_window_get_type (GdkWindow *window)
1262 GdkWindowPrivate *window_private;
1264 g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
1266 window_private = (GdkWindowPrivate*) window;
1267 return window_private->window_type;
1271 gdk_window_get_origin (GdkWindow *window,
1275 GdkWindowPrivate *private;
1281 g_return_val_if_fail (window != NULL, 0);
1283 private = (GdkWindowPrivate*) window;
1285 if (!private->destroyed)
1287 return_val = XTranslateCoordinates (private->xdisplay,
1306 gdk_window_get_root_origin (GdkWindow *window,
1310 GdkWindowPrivate *private;
1315 unsigned int nchildren;
1317 g_return_if_fail (window != NULL);
1319 private = (GdkWindowPrivate*) window;
1324 if (private->destroyed)
1327 while (private->parent && ((GdkWindowPrivate*) private->parent)->parent)
1328 private = (GdkWindowPrivate*) private->parent;
1329 if (private->destroyed)
1332 xparent = private->xwindow;
1336 if (!XQueryTree (private->xdisplay, xwindow,
1338 &children, &nchildren))
1344 while (xparent != root);
1346 if (xparent == root)
1348 unsigned int ww, wh, wb, wd;
1351 if (XGetGeometry (private->xdisplay, xwindow, &root, &wx, &wy, &ww, &wh, &wb, &wd))
1362 gdk_window_get_pointer (GdkWindow *window,
1365 GdkModifierType *mask)
1367 GdkWindowPrivate *private;
1368 GdkWindow *return_val;
1374 unsigned int xmask = 0;
1377 window = (GdkWindow*) &gdk_root_parent;
1379 private = (GdkWindowPrivate*) window;
1382 if (!private->destroyed &&
1383 XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
1384 &rootx, &rooty, &winx, &winy, &xmask))
1387 return_val = gdk_window_lookup (child);
1401 gdk_window_at_pointer (gint *win_x,
1404 GdkWindowPrivate *private;
1408 Window xwindow_last = 0;
1409 int rootx = -1, rooty = -1;
1413 private = &gdk_root_parent;
1415 xwindow = private->xwindow;
1417 XGrabServer (private->xdisplay);
1420 xwindow_last = xwindow;
1421 XQueryPointer (private->xdisplay,
1428 XUngrabServer (private->xdisplay);
1430 window = gdk_window_lookup (xwindow_last);
1433 *win_x = window ? winx : -1;
1435 *win_y = window ? winy : -1;
1441 gdk_window_get_parent (GdkWindow *window)
1443 g_return_val_if_fail (window != NULL, NULL);
1445 return ((GdkWindowPrivate*) window)->parent;
1449 gdk_window_get_toplevel (GdkWindow *window)
1451 GdkWindowPrivate *private;
1453 g_return_val_if_fail (window != NULL, NULL);
1455 private = (GdkWindowPrivate*) window;
1457 while (private->window_type == GDK_WINDOW_CHILD)
1459 window = ((GdkWindowPrivate*) window)->parent;
1460 private = (GdkWindowPrivate*) window;
1467 gdk_window_get_children (GdkWindow *window)
1469 GdkWindowPrivate *private;
1475 unsigned int nchildren;
1478 g_return_val_if_fail (window != NULL, NULL);
1480 private = (GdkWindowPrivate*) window;
1481 if (private->destroyed)
1484 XQueryTree (private->xdisplay, private->xwindow,
1485 &root, &parent, &xchildren, &nchildren);
1491 for (i = 0; i < nchildren; i++)
1493 child = gdk_window_lookup (xchildren[i]);
1495 children = g_list_prepend (children, child);
1506 gdk_window_get_events (GdkWindow *window)
1508 GdkWindowPrivate *private;
1509 XWindowAttributes attrs;
1510 GdkEventMask event_mask;
1513 g_return_val_if_fail (window != NULL, 0);
1515 private = (GdkWindowPrivate*) window;
1516 if (private->destroyed)
1519 XGetWindowAttributes (gdk_display, private->xwindow,
1523 for (i = 0; i < nevent_masks; i++)
1525 if (attrs.your_event_mask & event_mask_table[i])
1526 event_mask |= 1 << (i + 1);
1533 gdk_window_set_events (GdkWindow *window,
1534 GdkEventMask event_mask)
1536 GdkWindowPrivate *private;
1540 g_return_if_fail (window != NULL);
1542 private = (GdkWindowPrivate*) window;
1543 if (private->destroyed)
1546 xevent_mask = StructureNotifyMask;
1547 for (i = 0; i < nevent_masks; i++)
1549 if (event_mask & (1 << (i + 1)))
1550 xevent_mask |= event_mask_table[i];
1553 XSelectInput (gdk_display, private->xwindow,
1558 gdk_window_add_colormap_windows (GdkWindow *window)
1560 GdkWindow *toplevel;
1561 GdkWindowPrivate *toplevel_private;
1562 GdkWindowPrivate *window_private;
1563 Window *old_windows;
1564 Window *new_windows;
1567 g_return_if_fail (window != NULL);
1569 toplevel = gdk_window_get_toplevel (window);
1570 toplevel_private = (GdkWindowPrivate*) toplevel;
1571 window_private = (GdkWindowPrivate*) window;
1572 if (window_private->destroyed)
1576 if (!XGetWMColormapWindows (toplevel_private->xdisplay,
1577 toplevel_private->xwindow,
1578 &old_windows, &count))
1583 for (i = 0; i < count; i++)
1584 if (old_windows[i] == window_private->xwindow)
1586 XFree (old_windows);
1590 new_windows = g_new (Window, count + 1);
1592 for (i = 0; i < count; i++)
1593 new_windows[i] = old_windows[i];
1594 new_windows[count] = window_private->xwindow;
1596 XSetWMColormapWindows (toplevel_private->xdisplay,
1597 toplevel_private->xwindow,
1598 new_windows, count + 1);
1600 g_free (new_windows);
1602 XFree (old_windows);
1606 gdk_window_have_shape_ext (void)
1608 enum { UNKNOWN, NO, YES };
1609 static gint have_shape = UNKNOWN;
1611 if (have_shape == UNKNOWN)
1614 if (XQueryExtension(gdk_display, "SHAPE", &ignore, &ignore, &ignore))
1620 return (have_shape == YES);
1624 * This needs the X11 shape extension.
1625 * If not available, shaped windows will look
1626 * ugly, but programs still work. Stefan Wille
1629 gdk_window_shape_combine_mask (GdkWindow *window,
1633 GdkWindowPrivate *window_private;
1636 g_return_if_fail (window != NULL);
1638 #ifdef HAVE_SHAPE_EXT
1639 window_private = (GdkWindowPrivate*) window;
1640 if (window_private->destroyed)
1643 if (gdk_window_have_shape_ext())
1647 GdkWindowPrivate *pixmap_private;
1649 pixmap_private = (GdkWindowPrivate*) mask;
1650 pixmap = (Pixmap) pixmap_private->xwindow;
1659 XShapeCombineMask (window_private->xdisplay,
1660 window_private->xwindow,
1666 #endif /* HAVE_SHAPE_EXT */
1670 gdk_window_add_filter (GdkWindow *window,
1671 GdkFilterFunc function,
1674 GdkWindowPrivate *private;
1676 GdkEventFilter *filter;
1678 private = (GdkWindowPrivate*) window;
1679 if (private && private->destroyed)
1683 tmp_list = private->filters;
1685 tmp_list = gdk_default_filters;
1689 filter = (GdkEventFilter *)tmp_list->data;
1690 if ((filter->function == function) && (filter->data == data))
1692 tmp_list = tmp_list->next;
1695 filter = g_new (GdkEventFilter, 1);
1696 filter->function = function;
1697 filter->data = data;
1700 private->filters = g_list_append (private->filters, filter);
1702 gdk_default_filters = g_list_append (gdk_default_filters, filter);
1706 gdk_window_remove_filter (GdkWindow *window,
1707 GdkFilterFunc function,
1710 GdkWindowPrivate *private;
1711 GList *tmp_list, *node;
1712 GdkEventFilter *filter;
1714 private = (GdkWindowPrivate*) window;
1717 tmp_list = private->filters;
1719 tmp_list = gdk_default_filters;
1723 filter = (GdkEventFilter *)tmp_list->data;
1725 tmp_list = tmp_list->next;
1727 if ((filter->function == function) && (filter->data == data))
1730 private->filters = g_list_remove_link (private->filters, node);
1732 gdk_default_filters = g_list_remove_link (gdk_default_filters, tmp_list);
1733 g_list_free_1 (node);
1742 gdk_window_set_override_redirect(GdkWindow *window,
1743 gboolean override_redirect)
1745 GdkWindowPrivate *private;
1746 XSetWindowAttributes attr;
1748 g_return_if_fail (window != NULL);
1749 private = (GdkWindowPrivate*) window;
1750 if (private->destroyed)
1753 attr.override_redirect = (override_redirect == FALSE)?False:True;
1754 XChangeWindowAttributes(gdk_display,
1755 ((GdkWindowPrivate *)window)->xwindow,
1761 gdk_window_set_icon (GdkWindow *window,
1762 GdkWindow *icon_window,
1767 GdkWindowPrivate *window_private;
1768 GdkWindowPrivate *private;
1770 g_return_if_fail (window != NULL);
1771 window_private = (GdkWindowPrivate*) window;
1772 if (window_private->destroyed)
1777 if (icon_window != NULL)
1779 private = (GdkWindowPrivate *)icon_window;
1780 wm_hints.flags |= IconWindowHint;
1781 wm_hints.icon_window = private->xwindow;
1786 private = (GdkWindowPrivate *)pixmap;
1787 wm_hints.flags |= IconPixmapHint;
1788 wm_hints.icon_pixmap = private->xwindow;
1793 private = (GdkWindowPrivate *)mask;
1794 wm_hints.flags |= IconMaskHint;
1795 wm_hints.icon_mask = private->xwindow;
1798 XSetWMHints (window_private->xdisplay, window_private->xwindow, &wm_hints);
1802 gdk_window_set_icon_name (GdkWindow *window,
1805 GdkWindowPrivate *window_private;
1806 XTextProperty property;
1809 g_return_if_fail (window != NULL);
1810 window_private = (GdkWindowPrivate*) window;
1811 if (window_private->destroyed)
1813 res = XmbTextListToTextProperty (window_private->xdisplay,
1814 &name, 1, XStdICCTextStyle,
1818 g_warning("Error converting icon name to text property: %d\n", res);
1822 XSetWMIconName (window_private->xdisplay, window_private->xwindow,
1826 XFree (property.value);
1830 gdk_window_set_group (GdkWindow *window,
1834 GdkWindowPrivate *window_private;
1835 GdkWindowPrivate *private;
1837 g_return_if_fail (window != NULL);
1838 g_return_if_fail (leader != NULL);
1839 window_private = (GdkWindowPrivate*) window;
1840 if (window_private->destroyed)
1843 private = (GdkWindowPrivate *)leader;
1844 wm_hints.flags = WindowGroupHint;
1845 wm_hints.window_group = private->xwindow;
1847 XSetWMHints (window_private->xdisplay, window_private->xwindow, &wm_hints);
1851 gdk_window_set_mwm_hints (GdkWindow *window,
1852 MotifWmHints *new_hints)
1854 static Atom hints_atom = None;
1855 MotifWmHints *hints;
1861 GdkWindowPrivate *window_private;
1863 g_return_if_fail (window != NULL);
1864 window_private = (GdkWindowPrivate*) window;
1865 if (window_private->destroyed)
1869 hints_atom = XInternAtom (window_private->xdisplay,
1870 _XA_MOTIF_WM_HINTS, FALSE);
1872 XGetWindowProperty (window_private->xdisplay, window_private->xwindow,
1873 hints_atom, 0, sizeof(MotifWmHints)/4,
1874 False, AnyPropertyType, &type, &format, &nitems,
1875 &bytes_after, (guchar **)&hints);
1881 if (new_hints->flags & MWM_HINTS_FUNCTIONS)
1883 hints->flags |= MWM_HINTS_FUNCTIONS;
1884 hints->functions = new_hints->functions;
1886 if (new_hints->flags & MWM_HINTS_DECORATIONS)
1888 hints->flags |= MWM_HINTS_DECORATIONS;
1889 hints->decorations = new_hints->decorations;
1893 XChangeProperty (window_private->xdisplay, window_private->xwindow,
1894 hints_atom, hints_atom, 32, PropModeReplace,
1895 (guchar *)hints, sizeof(MotifWmHints)/4);
1897 if (hints != new_hints)
1902 gdk_window_set_decorations (GdkWindow *window,
1903 GdkWMDecoration decorations)
1907 hints.flags = MWM_HINTS_DECORATIONS;
1908 hints.decorations = decorations;
1910 gdk_window_set_mwm_hints (window, &hints);
1914 gdk_window_set_functions (GdkWindow *window,
1915 GdkWMFunction functions)
1919 hints.flags = MWM_HINTS_FUNCTIONS;
1920 hints.functions = functions;
1922 gdk_window_set_mwm_hints (window, &hints);
1926 gdk_window_get_toplevels (void)
1928 GList *new_list = NULL;
1931 tmp_list = gdk_root_parent.children;
1934 new_list = g_list_prepend (new_list, tmp_list->data);
1935 tmp_list = tmp_list->next;
1942 * propagate the shapes from all child windows of a GDK window to the parent
1943 * window. Shamelessly ripped from Enlightenment's code
1952 struct _gdk_span *next;
1956 gdk_add_to_span(struct _gdk_span **s, int x, int xx)
1958 struct _gdk_span *ptr1, *ptr2, *noo, *ss;
1965 /* scan the spans for this line */
1968 /* -- -> new span */
1969 /* == -> existing span */
1970 /* ## -> spans intersect */
1971 /* if we are in the middle of spanning the span into the line */
1974 /* case: ---- ==== */
1975 if (xx < ptr1->start - 1)
1977 /* ends before next span - extend to here */
1981 /* case: ----##=== */
1982 else if (xx <= ptr1->end)
1984 /* crosses into next span - delete next span and append */
1985 ss->end = ptr1->end;
1986 ss->next = ptr1->next;
1990 /* case: ---###--- */
1993 /* overlaps next span - delete and keep checking */
1994 ss->next = ptr1->next;
1999 /* otherwise havent started spanning it in yet */
2002 /* case: ---- ==== */
2003 if (xx < ptr1->start - 1)
2005 /* insert span here in list */
2006 noo = g_malloc(sizeof(struct _gdk_span));
2020 /* case: ----##=== */
2021 else if ((x < ptr1->start) && (xx <= ptr1->end))
2023 /* expand this span to the left point of the new one */
2027 /* case: ===###=== */
2028 else if ((x >= ptr1->start) && (xx <= ptr1->end))
2030 /* throw the span away */
2033 /* case: ---###--- */
2034 else if ((x < ptr1->start) && (xx > ptr1->end))
2041 /* case: ===##---- */
2042 else if ((x >= ptr1->start) && (x <= ptr1->end + 1) && (xx > ptr1->end))
2048 /* case: ==== ---- */
2049 /* case handled by next loop iteration - first case */
2054 /* it started in the middle but spans beyond your current list */
2060 /* it does not start inside a span or in the middle, so add it to the end */
2061 noo = g_malloc(sizeof(struct _gdk_span));
2069 noo->next = ptr2->next;
2082 gdk_add_rectangles (Display *disp, Window win, struct _gdk_span **spans,
2083 gint basew, gint baseh, gint x, gint y)
2086 gint x1, y1, x2, y2;
2090 rl = XShapeGetRectangles(disp, win, ShapeBounding, &rn, &ord);
2093 /* go through all clip rects in this window's shape */
2094 for (k = 0; k < rn; k++)
2096 /* for each clip rect, add it to each line's spans */
2098 x2 = x + rl[k].x + (rl[k].width - 1);
2100 y2 = y + rl[k].y + (rl[k].height - 1);
2109 for (a = y1; a <= y2; a++)
2112 gdk_add_to_span(&spans[a], x1, x2);
2120 gdk_propagate_shapes(Display *disp, Window win, gboolean merge)
2122 Window rt, par, *list = NULL;
2123 gint i, j, num = 0, num_rects = 0;
2127 XRectangle *rects = NULL;
2128 struct _gdk_span **spans = NULL, *ptr1, *ptr2, *ptr3;
2129 XWindowAttributes xatt;
2131 XGetGeometry(disp, win, &rt, &x, &y, &w, &h, &d, &d);
2136 spans = g_malloc(sizeof(struct _gdk_span *) * h);
2138 for (i = 0; i < h; i++)
2140 XQueryTree(disp, win, &rt, &par, &list, (unsigned int *)&num);
2143 /* go through all child windows and create/insert spans */
2144 for (i = 0; i < num; i++)
2146 if (XGetWindowAttributes(disp, list[i], &xatt) && (xatt.map_state != IsUnmapped))
2147 if (XGetGeometry(disp, list[i], &rt, &x, &y, &w, &h, &d, &d))
2148 gdk_add_rectangles (disp, list[i], spans, basew, baseh, x, y);
2151 gdk_add_rectangles (disp, win, spans, basew, baseh, x, y);
2153 /* go through the spans list and build a list of rects */
2154 rects = g_malloc(sizeof(XRectangle) * 256);
2156 for (i = 0; i < baseh; i++)
2159 /* go through the line for all spans */
2162 rects[num_rects].x = ptr1->start;
2163 rects[num_rects].y = i;
2164 rects[num_rects].width = ptr1->end - ptr1->start + 1;
2165 rects[num_rects].height = 1;
2167 /* if there are more lines */
2169 /* while contigous rects (same start/end coords) exist */
2170 while ((contig) && (j < baseh))
2172 /* search next line for spans matching this one */
2178 /* if we have an exact span match set contig */
2179 if ((ptr2->start == ptr1->start) &&
2180 (ptr2->end == ptr1->end))
2183 /* remove the span - not needed */
2186 ptr3->next = ptr2->next;
2192 spans[j] = ptr2->next;
2198 /* gone past the span point no point looking */
2199 else if (ptr2->start < ptr1->start)
2207 /* if a contiguous span was found increase the rect h */
2210 rects[num_rects].height++;
2214 /* up the rect count */
2216 /* every 256 new rects increase the rect array */
2217 if ((num_rects % 256) == 0)
2218 rects = g_realloc(rects, sizeof(XRectangle) * (num_rects + 256));
2222 /* set the rects as the shape mask */
2225 XShapeCombineRectangles(disp, win, ShapeBounding, 0, 0, rects, num_rects,
2226 ShapeSet, YXSorted);
2231 /* free up all the spans we made */
2232 for (i = 0; i < baseh; i++)
2246 gdk_window_set_child_shapes (GdkWindow *window)
2248 GdkWindowPrivate *private;
2250 g_return_if_fail (window != NULL);
2252 #ifdef HAVE_SHAPE_EXT
2253 private = (GdkWindowPrivate*) window;
2254 if (private->destroyed)
2257 if (gdk_window_have_shape_ext())
2258 gdk_propagate_shapes (private->xdisplay, private->xwindow, FALSE);
2263 gdk_window_merge_child_shapes (GdkWindow *window)
2265 GdkWindowPrivate *private;
2267 g_return_if_fail (window != NULL);
2269 #ifdef HAVE_SHAPE_EXT
2270 private = (GdkWindowPrivate*) window;
2271 if (private->destroyed)
2274 if (gdk_window_have_shape_ext())
2275 gdk_propagate_shapes (private->xdisplay, private->xwindow, TRUE);
2280 gdk_drawable_set_data (GdkDrawable *drawable,
2283 GDestroyNotify destroy_func)
2285 g_dataset_set_data_full (drawable, key, data, destroy_func);