diff options
Diffstat (limited to 'gdk/x11/gdkwindow-x11.c')
-rw-r--r-- | gdk/x11/gdkwindow-x11.c | 1358 |
1 files changed, 1358 insertions, 0 deletions
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c new file mode 100644 index 000000000..aef1367d9 --- /dev/null +++ b/gdk/x11/gdkwindow-x11.c @@ -0,0 +1,1358 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/extensions/shape.h> +#include <netinet/in.h> +#include "gdk.h" +#include "gdkinput.h" +#include "gdkprivate.h" +#include <stdlib.h> + +int nevent_masks = 16; +int event_mask_table[18] = +{ + ExposureMask, + PointerMotionMask, + PointerMotionHintMask, + ButtonMotionMask, + Button1MotionMask, + Button2MotionMask, + Button3MotionMask, + ButtonPressMask | OwnerGrabButtonMask, + ButtonReleaseMask | OwnerGrabButtonMask, + KeyPressMask, + KeyReleaseMask, + EnterWindowMask, + LeaveWindowMask, + FocusChangeMask, + StructureNotifyMask, + PropertyChangeMask, + 0, /* PROXIMITY_IN */ + 0 /* PROXIMTY_OUT */ +}; + + +void +gdk_window_init () +{ + XWindowAttributes xattributes; + unsigned int width; + unsigned int height; + unsigned int border_width; + unsigned int depth; + int x, y; + + XGetGeometry (gdk_display, gdk_root_window, &gdk_root_window, + &x, &y, &width, &height, &border_width, &depth); + XGetWindowAttributes (gdk_display, gdk_root_window, &xattributes); + + gdk_root_parent.xdisplay = gdk_display; + gdk_root_parent.xwindow = gdk_root_window; + gdk_root_parent.window_type = GDK_WINDOW_ROOT; + gdk_root_parent.window.user_data = NULL; +} + +GdkWindow* +gdk_window_new (GdkWindow *parent, + GdkWindowAttr *attributes, + gint attributes_mask) +{ + GdkWindow *window; + GdkWindowPrivate *private; + GdkWindowPrivate *parent_private; + GdkVisual *visual; + GdkColormap *colormap; + Display *parent_display; + Window xparent; + Visual *xvisual; + XSetWindowAttributes xattributes; + long xattributes_mask; + XSizeHints size_hints; + XWMHints wm_hints; + XTextProperty text_property; + XClassHint *class_hint; + int x, y, depth; + unsigned int class; + char *title; + int i; + + g_return_val_if_fail (attributes != NULL, NULL); + + if (!parent) + parent = (GdkWindow*) &gdk_root_parent; + + parent_private = (GdkWindowPrivate*) parent; + xparent = parent_private->xwindow; + parent_display = parent_private->xdisplay; + + private = g_new (GdkWindowPrivate, 1); + window = (GdkWindow*) private; + + private->parent = parent; + private->xdisplay = parent_display; + private->destroyed = FALSE; + private->resize_count = 0; + private->ref_count = 1; + xattributes_mask = 0; + + if (attributes_mask & GDK_WA_X) + x = attributes->x; + else + x = 0; + + if (attributes_mask & GDK_WA_Y) + y = attributes->y; + else + y = 0; + + private->x = x; + private->y = y; + private->width = (attributes->width > 1) ? (attributes->width) : (1); + private->height = (attributes->height > 1) ? (attributes->height) : (1); + private->window_type = attributes->window_type; + private->extension_events = FALSE; + private->dnd_drag_data_type = None; + private->dnd_drag_data_typesavail = + private->dnd_drop_data_typesavail = NULL; + private->dnd_drop_enabled = private->dnd_drag_enabled = + private->dnd_drag_accepted = private->dnd_drag_datashow = + private->dnd_drop_data_numtypesavail = + private->dnd_drag_data_numtypesavail = 0; + private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0; + + window->user_data = NULL; + + if (attributes_mask & GDK_WA_VISUAL) + visual = attributes->visual; + else + visual = gdk_visual_get_system (); + xvisual = ((GdkVisualPrivate*) visual)->xvisual; + + xattributes.event_mask = StructureNotifyMask; + for (i = 0; i < nevent_masks; i++) + { + if (attributes->event_mask & (1 << (i + 1))) + xattributes.event_mask |= event_mask_table[i]; + } + + if (xattributes.event_mask) + xattributes_mask |= CWEventMask; + + if (attributes->wclass == GDK_INPUT_OUTPUT) + { + class = InputOutput; + depth = visual->depth; + + if (attributes_mask & GDK_WA_COLORMAP) + colormap = attributes->colormap; + else + colormap = gdk_colormap_get_system (); + + xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen); + xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen); + xattributes_mask |= CWBorderPixel | CWBackPixel; + + switch (private->window_type) + { + case GDK_WINDOW_TOPLEVEL: + xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap; + xattributes_mask |= CWColormap; + + xparent = gdk_root_window; + break; + + case GDK_WINDOW_CHILD: + xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap; + xattributes_mask |= CWColormap; + break; + + case GDK_WINDOW_DIALOG: + xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap; + xattributes_mask |= CWColormap; + + xparent = gdk_root_window; + break; + + case GDK_WINDOW_TEMP: + xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap; + xattributes_mask |= CWColormap; + + xparent = gdk_root_window; + + xattributes.save_under = True; + xattributes.override_redirect = True; + xattributes.cursor = None; + xattributes_mask |= CWSaveUnder | CWOverrideRedirect; + break; + case GDK_WINDOW_ROOT: + g_error ("cannot make windows of type GDK_WINDOW_ROOT"); + break; + case GDK_WINDOW_PIXMAP: + g_error ("cannot make windows of type GDK_WINDOW_PIXMAP (use gdk_pixmap_new)"); + break; + } + } + else + { + depth = 1; + class = InputOnly; + colormap = NULL; + } + + private->xwindow = XCreateWindow (private->xdisplay, xparent, + x, y, private->width, private->height, + 0, depth, class, xvisual, + xattributes_mask, &xattributes); + gdk_xid_table_insert (&private->xwindow, window); + + switch (private->window_type) + { + case GDK_WINDOW_DIALOG: + XSetTransientForHint (private->xdisplay, private->xwindow, xparent); + case GDK_WINDOW_TOPLEVEL: + case GDK_WINDOW_TEMP: + XSetWMProtocols (private->xdisplay, private->xwindow, gdk_wm_window_protocols, 2); + break; + case GDK_WINDOW_CHILD: + if ((attributes->wclass == GDK_INPUT_OUTPUT) && + (colormap != gdk_colormap_get_system ()) && + (colormap != gdk_window_get_colormap (gdk_window_get_toplevel (window)))) + { + g_print ("adding colormap window\n"); + gdk_window_add_colormap_windows (window); + } + break; + default: + break; + } + + size_hints.flags = PSize | PBaseSize; + size_hints.width = private->width; + size_hints.height = private->height; + size_hints.base_width = private->width; + size_hints.base_height = private->height; + + wm_hints.flags = InputHint | StateHint | WindowGroupHint; + wm_hints.window_group = gdk_leader_window; + wm_hints.input = True; + wm_hints.initial_state = NormalState; + + XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints); + XSetWMHints (private->xdisplay, private->xwindow, &wm_hints); + + if (attributes_mask & GDK_WA_TITLE) + title = attributes->title; + else + title = gdk_progname; + + if (XStringListToTextProperty (&title, 1, &text_property)) + { + XSetWMName (private->xdisplay, private->xwindow, &text_property); + XSetWMIconName (private->xdisplay, private->xwindow, &text_property); + XFree (text_property.value); + } + + if (attributes_mask & GDK_WA_WMCLASS) + { + class_hint = XAllocClassHint (); + class_hint->res_name = attributes->wmclass_name; + class_hint->res_class = attributes->wmclass_class; + XSetClassHint (private->xdisplay, private->xwindow, class_hint); + XFree (class_hint); + } + + gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ? + (attributes->cursor) : + NULL)); + + return window; +} + +GdkWindow * +gdk_window_foreign_new (guint32 anid) +{ + GdkWindow *window; + GdkWindowPrivate *private; + XWindowAttributes attrs; + + private = g_new (GdkWindowPrivate, 1); + window = (GdkWindow*) private; + + XGetWindowAttributes (gdk_display, anid, &attrs); + + private->parent = NULL; + private->xwindow = anid; + private->xdisplay = gdk_display; + private->x = attrs.x; + private->y = attrs.y; + private->width = attrs.width; + private->height = attrs.height; + private->resize_count = 0; + private->ref_count = 1; + if (anid == attrs.root) + private->window_type = GDK_WINDOW_ROOT; + else + private->window_type = GDK_WINDOW_TOPLEVEL; + /* the above is probably wrong, but it may not be worth the extra + X call to get it right */ + + private->destroyed = FALSE; + private->extension_events = 0; + + window->user_data = NULL; + + gdk_xid_table_insert (&private->xwindow, window); + + return window; +} + +void +gdk_window_destroy (GdkWindow *window) +{ + GdkWindowPrivate *private; + GdkWindowPrivate *temp_private; + GdkWindow *temp_window; + GList *children; + GList *tmp; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + if(private->dnd_drag_data_numtypesavail > 0) + { + free(private->dnd_drag_data_typesavail); + private->dnd_drag_data_typesavail = NULL; + } + if(private->dnd_drop_data_numtypesavail > 0) + { + free(private->dnd_drop_data_typesavail); + private->dnd_drop_data_typesavail = NULL; + } + + switch (private->window_type) + { + case GDK_WINDOW_TOPLEVEL: + case GDK_WINDOW_CHILD: + case GDK_WINDOW_DIALOG: + case GDK_WINDOW_TEMP: + if (private->ref_count >= 1) + private->ref_count -= 1; + + if (!private->destroyed || (private->destroyed == 2)) + { + children = gdk_window_get_children (window); + tmp = children; + + while (tmp) + { + temp_window = tmp->data; + tmp = tmp->next; + + temp_private = (GdkWindowPrivate*) temp_window; + if (temp_private && !temp_private->destroyed) + /* Removes some nice coredumps... /David */ + { + temp_private->destroyed = 2; + temp_private->ref_count += 1; + gdk_window_destroy (temp_window); + } + } + + g_list_free (children); + + if (!private->destroyed) + XDestroyWindow (private->xdisplay, private->xwindow); + private->destroyed = TRUE; + } + break; + + case GDK_WINDOW_ROOT: + g_error ("attempted to destroy root window"); + break; + + case GDK_WINDOW_PIXMAP: + g_warning ("called gdk_window_destroy on a pixmap (use gdk_pixmap_destroy)"); + gdk_pixmap_destroy (window); + break; + } +} + +void +gdk_window_real_destroy (GdkWindow *window) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + + if (private->extension_events != 0) + gdk_input_window_destroy (window); + + if (private->ref_count == 0) + { + gdk_xid_table_remove (private->xwindow); + g_free (window); + } +} + +GdkWindow* +gdk_window_ref (GdkWindow *window) +{ + GdkWindowPrivate *private = (GdkWindowPrivate *)window; + g_return_if_fail (window != NULL); + + private->ref_count += 1; + return window; +} + +void +gdk_window_unref (GdkWindow *window) +{ + GdkWindowPrivate *private = (GdkWindowPrivate *)window; + g_return_if_fail (window != NULL); + + private->ref_count -= 1; + if (private->ref_count == 0) + gdk_window_real_destroy (window); +} + +void +gdk_window_show (GdkWindow *window) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + if (!private->destroyed) + { + XRaiseWindow (private->xdisplay, private->xwindow); + XMapWindow (private->xdisplay, private->xwindow); + } +} + +void +gdk_window_hide (GdkWindow *window) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + if (!private->destroyed) + XUnmapWindow (private->xdisplay, private->xwindow); +} + +void +gdk_window_move (GdkWindow *window, + gint x, + gint y) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + XMoveWindow (private->xdisplay, private->xwindow, x, y); + + if (private->window_type == GDK_WINDOW_CHILD) + { + private->x = x; + private->y = y; + } +} + +void +gdk_window_resize (GdkWindow *window, + gint width, + gint height) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + + if (width < 1) + width = 1; + if (height < 1) + height = 1; + + private = (GdkWindowPrivate*) window; + + if (!private->destroyed && + ((private->resize_count > 0) || + (private->width != (guint16) width) || + (private->height != (guint16) height))) + { + XResizeWindow (private->xdisplay, private->xwindow, width, height); + private->resize_count += 1; + + if (private->window_type == GDK_WINDOW_CHILD) + { + private->width = width; + private->height = height; + } + } +} + +void +gdk_window_move_resize (GdkWindow *window, + gint x, + gint y, + gint width, + gint height) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + + if (width < 1) + width = 1; + if (height < 1) + height = 1; + + private = (GdkWindowPrivate*) window; + XMoveResizeWindow (private->xdisplay, private->xwindow, x, y, width, height); + + if (!private->destroyed && + (private->window_type == GDK_WINDOW_CHILD)) + { + private->x = x; + private->y = y; + private->width = width; + private->height = height; + } +} + +void +gdk_window_reparent (GdkWindow *window, + GdkWindow *new_parent, + gint x, + gint y) +{ + GdkWindowPrivate *window_private; + GdkWindowPrivate *parent_private; + + g_return_if_fail (window != NULL); + + if (!new_parent) + new_parent = (GdkWindow*) &gdk_root_parent; + + window_private = (GdkWindowPrivate*) window; + parent_private = (GdkWindowPrivate*) new_parent; + + XReparentWindow (window_private->xdisplay, + window_private->xwindow, + parent_private->xwindow, + x, y); +} + +void +gdk_window_clear (GdkWindow *window) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + + XClearWindow (private->xdisplay, private->xwindow); +} + +void +gdk_window_clear_area (GdkWindow *window, + gint x, + gint y, + gint width, + gint height) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + + if (!private->destroyed) + XClearArea (private->xdisplay, private->xwindow, + x, y, width, height, False); +} + +void +gdk_window_clear_area_e (GdkWindow *window, + gint x, + gint y, + gint width, + gint height) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + + if (!private->destroyed) + XClearArea (private->xdisplay, private->xwindow, + x, y, width, height, True); +} + +void +gdk_window_copy_area (GdkWindow *window, + GdkGC *gc, + gint x, + gint y, + GdkWindow *source_window, + gint source_x, + gint source_y, + gint width, + gint height) +{ + GdkWindowPrivate *src_private; + GdkWindowPrivate *dest_private; + GdkGCPrivate *gc_private; + + g_return_if_fail (window != NULL); + g_return_if_fail (gc != NULL); + + if (source_window == NULL) + source_window = window; + + src_private = (GdkWindowPrivate*) source_window; + dest_private = (GdkWindowPrivate*) window; + gc_private = (GdkGCPrivate*) gc; + + if (!src_private->destroyed && !dest_private->destroyed) + { + XCopyArea (dest_private->xdisplay, src_private->xwindow, dest_private->xwindow, + gc_private->xgc, + source_x, source_y, + width, height, + x, y); + } +} + +void +gdk_window_raise (GdkWindow *window) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + + if (!private->destroyed) + XRaiseWindow (private->xdisplay, private->xwindow); +} + +void +gdk_window_lower (GdkWindow *window) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + + if (!private->destroyed) + XLowerWindow (private->xdisplay, private->xwindow); +} + +void +gdk_window_set_user_data (GdkWindow *window, + gpointer user_data) +{ + g_return_if_fail (window != NULL); + + window->user_data = user_data; +} + +void +gdk_window_set_hints (GdkWindow *window, + gint x, + gint y, + gint min_width, + gint min_height, + gint max_width, + gint max_height, + gint flags) +{ + GdkWindowPrivate *private; + XSizeHints size_hints; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + size_hints.flags = 0; + + if (flags & GDK_HINT_POS) + { + size_hints.flags |= PPosition; + size_hints.x = x; + size_hints.y = y; + } + + if (flags & GDK_HINT_MIN_SIZE) + { + size_hints.flags |= PMinSize; + size_hints.min_width = min_width; + size_hints.min_height = min_height; + } + + if (flags & GDK_HINT_MAX_SIZE) + { + size_hints.flags |= PMaxSize; + size_hints.max_width = max_width; + size_hints.max_height = max_height; + } + + if (flags) + XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints); +} + +void +gdk_window_set_title (GdkWindow *window, + const gchar *title) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + XStoreName (private->xdisplay, private->xwindow, title); + XSetIconName (private->xdisplay, private->xwindow, title); +} + +void +gdk_window_set_background (GdkWindow *window, + GdkColor *color) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + XSetWindowBackground (private->xdisplay, private->xwindow, color->pixel); +} + +void +gdk_window_set_back_pixmap (GdkWindow *window, + GdkPixmap *pixmap, + gint parent_relative) +{ + GdkWindowPrivate *window_private; + GdkPixmapPrivate *pixmap_private; + Pixmap xpixmap; + + g_return_if_fail (window != NULL); + + window_private = (GdkWindowPrivate*) window; + pixmap_private = (GdkPixmapPrivate*) pixmap; + + if (pixmap) + xpixmap = pixmap_private->xwindow; + else + xpixmap = None; + + if (parent_relative) + xpixmap = ParentRelative; + + XSetWindowBackgroundPixmap (window_private->xdisplay, window_private->xwindow, xpixmap); +} + +void +gdk_window_set_cursor (GdkWindow *window, + GdkCursor *cursor) +{ + GdkWindowPrivate *window_private; + GdkCursorPrivate *cursor_private; + Cursor xcursor; + + g_return_if_fail (window != NULL); + + window_private = (GdkWindowPrivate*) window; + cursor_private = (GdkCursorPrivate*) cursor; + + if (!cursor) + xcursor = None; + else + xcursor = cursor_private->xcursor; + + XDefineCursor (window_private->xdisplay, window_private->xwindow, xcursor); +} + +void +gdk_window_set_colormap (GdkWindow *window, + GdkColormap *colormap) +{ + GdkWindowPrivate *window_private; + GdkColormapPrivate *colormap_private; + + g_return_if_fail (window != NULL); + g_return_if_fail (colormap != NULL); + + window_private = (GdkWindowPrivate*) window; + colormap_private = (GdkColormapPrivate*) colormap; + + XSetWindowColormap (window_private->xdisplay, + window_private->xwindow, + colormap_private->xcolormap); + + if (window_private->window_type != GDK_WINDOW_TOPLEVEL) + gdk_window_add_colormap_windows (window); +} + +void +gdk_window_get_user_data (GdkWindow *window, + gpointer *data) +{ + g_return_if_fail (window != NULL); + + *data = window->user_data; +} + +void +gdk_window_get_geometry (GdkWindow *window, + gint *x, + gint *y, + gint *width, + gint *height, + gint *depth) +{ + GdkWindowPrivate *window_private; + Window root; + gint tx; + gint ty; + guint twidth; + guint theight; + guint tborder_width; + guint tdepth; + + if (!window) + window = (GdkWindow*) &gdk_root_parent; + + window_private = (GdkWindowPrivate*) window; + + XGetGeometry (window_private->xdisplay, window_private->xwindow, + &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth); + + if (x) + *x = tx; + if (y) + *y = ty; + if (width) + *width = twidth; + if (height) + *height = theight; + if (depth) + *depth = tdepth; +} + +void +gdk_window_get_position (GdkWindow *window, + gint *x, + gint *y) +{ + GdkWindowPrivate *window_private; + + g_return_if_fail (window != NULL); + + window_private = (GdkWindowPrivate*) window; + + if (x) + *x = window_private->x; + if (y) + *y = window_private->y; +} + +void +gdk_window_get_size (GdkWindow *window, + gint *width, + gint *height) +{ + GdkWindowPrivate *window_private; + + g_return_if_fail (window != NULL); + + window_private = (GdkWindowPrivate*) window; + + if (width) + *width = window_private->width; + if (height) + *height = window_private->height; +} + + +GdkVisual* +gdk_window_get_visual (GdkWindow *window) +{ + GdkWindowPrivate *window_private; + XWindowAttributes window_attributes; + + g_return_val_if_fail (window != NULL, NULL); + + window_private = (GdkWindowPrivate*) window; + while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP)) + window_private = (GdkWindowPrivate*) window_private->parent; + + if (window_private) + { + XGetWindowAttributes (window_private->xdisplay, + window_private->xwindow, + &window_attributes); + + return gdk_visual_lookup (window_attributes.visual); + } + + return NULL; +} + +GdkColormap* +gdk_window_get_colormap (GdkWindow *window) +{ + GdkWindowPrivate *window_private; + XWindowAttributes window_attributes; + + g_return_val_if_fail (window != NULL, NULL); + + window_private = (GdkWindowPrivate*) window; + + XGetWindowAttributes (window_private->xdisplay, + window_private->xwindow, + &window_attributes); + + return gdk_colormap_lookup (window_attributes.colormap); +} + +GdkWindowType +gdk_window_get_type (GdkWindow *window) +{ + GdkWindowPrivate *window_private; + + g_return_val_if_fail (window != NULL, (GdkWindowType) -1); + + window_private = (GdkWindowPrivate*) window; + return window_private->window_type; +} + +gint +gdk_window_get_origin (GdkWindow *window, + gint *x, + gint *y) +{ + GdkWindowPrivate *private; + gint return_val; + Window child; + gint tx, ty; + + g_return_val_if_fail (window != NULL, 0); + + private = (GdkWindowPrivate*) window; + + return_val = XTranslateCoordinates (private->xdisplay, + private->xwindow, + gdk_root_window, + 0, 0, &tx, &ty, + &child); + + if (x) + *x = tx; + if (y) + *y = ty; + + return return_val; +} + +GdkWindow* +gdk_window_get_pointer (GdkWindow *window, + gint *x, + gint *y, + GdkModifierType *mask) +{ + GdkWindowPrivate *private; + GdkWindow *return_val; + Window root; + Window child; + int rootx, rooty; + int winx, winy; + unsigned int xmask; + + if (!window) + window = (GdkWindow*) &gdk_root_parent; + + private = (GdkWindowPrivate*) window; + + return_val = NULL; + if (XQueryPointer (private->xdisplay, private->xwindow, &root, &child, + &rootx, &rooty, &winx, &winy, &xmask)) + { + if (x) *x = winx; + if (y) *y = winy; + if (mask) *mask = xmask; + + if (child) + return_val = gdk_window_lookup (child); + } + + return return_val; +} + +GdkWindow* +gdk_window_get_parent (GdkWindow *window) +{ + g_return_val_if_fail (window != NULL, NULL); + + return ((GdkWindowPrivate*) window)->parent; +} + +GdkWindow* +gdk_window_get_toplevel (GdkWindow *window) +{ + GdkWindowPrivate *private; + + g_return_val_if_fail (window != NULL, NULL); + + private = (GdkWindowPrivate*) window; + + while (private->window_type == GDK_WINDOW_CHILD) + { + window = ((GdkWindowPrivate*) window)->parent; + private = (GdkWindowPrivate*) window; + } + + return window; +} + +GList* +gdk_window_get_children (GdkWindow *window) +{ + GdkWindowPrivate *private; + GdkWindow *child; + GList *children; + Window root; + Window parent; + Window *xchildren; + unsigned int nchildren; + unsigned int i; + + g_return_val_if_fail (window != NULL, NULL); + + private = (GdkWindowPrivate*) window; + + XQueryTree (private->xdisplay, private->xwindow, + &root, &parent, &xchildren, &nchildren); + + children = NULL; + + if (nchildren > 0) + { + for (i = 0; i < nchildren; i++) + { + child = gdk_window_lookup (xchildren[i]); + if (child) + children = g_list_prepend (children, child); + } + + XFree (xchildren); + } + + return children; +} + +GdkEventMask +gdk_window_get_events (GdkWindow *window) +{ + XWindowAttributes attrs; + GdkEventMask event_mask; + int i; + + XGetWindowAttributes (gdk_display, ((GdkWindowPrivate *)window)->xwindow, + &attrs); + + event_mask = 0; + for (i = 0; i < nevent_masks; i++) + { + if (attrs.your_event_mask & event_mask_table[i]) + event_mask |= 1 << (i + 1); + } + + return event_mask; +} + +void +gdk_window_set_events (GdkWindow *window, + GdkEventMask event_mask) +{ + long xevent_mask; + int i; + + xevent_mask = StructureNotifyMask; + for (i = 0; i < nevent_masks; i++) + { + if (event_mask & (1 << (i + 1))) + xevent_mask |= event_mask_table[i]; + } + + XSelectInput (gdk_display, ((GdkWindowPrivate *)window)->xwindow, + xevent_mask); +} + +void +gdk_window_add_colormap_windows (GdkWindow *window) +{ + GdkWindow *toplevel; + GdkWindowPrivate *toplevel_private; + GdkWindowPrivate *window_private; + Window *old_windows; + Window *new_windows; + int i, count; + + g_return_if_fail (window != NULL); + + toplevel = gdk_window_get_toplevel (window); + toplevel_private = (GdkWindowPrivate*) toplevel; + window_private = (GdkWindowPrivate*) window; + + if (!XGetWMColormapWindows (toplevel_private->xdisplay, + toplevel_private->xwindow, + &old_windows, &count)) + { + old_windows = NULL; + count = 0; + } + + for (i = 0; i < count; i++) + if (old_windows[i] == window_private->xwindow) + return; + + new_windows = g_new (Window, count + 1); + + for (i = 0; i < count; i++) + new_windows[i] = old_windows[i]; + new_windows[count] = window_private->xwindow; + + XSetWMColormapWindows (toplevel_private->xdisplay, + toplevel_private->xwindow, + new_windows, count + 1); + + g_free (new_windows); + if (old_windows) + XFree (old_windows); +} + +/* + * This needs the X11 shape extension. + * If not available, simply remove the call to + * XShapeCombineMask. Shaped windows will look + * ugly, but programs still work. Stefan Wille + */ +void +gdk_window_shape_combine_mask (GdkWindow *window, + GdkBitmap *mask, + gint x, gint y) +{ + GdkWindowPrivate *window_private; + GdkWindowPrivate *pixmap_private; + + g_return_if_fail (window != NULL); + g_return_if_fail (mask != NULL); + + window_private = (GdkWindowPrivate*) window; + pixmap_private = (GdkWindowPrivate*) mask; + + XShapeCombineMask (window_private->xdisplay, + window_private->xwindow, + ShapeBounding, + x, y, /* offset */ + (Pixmap)pixmap_private->xwindow, + ShapeSet); +} + +void +gdk_dnd_drag_addwindow (GdkWindow *window) +{ + GdkWindowPrivate *window_private; + + g_return_if_fail (window != NULL); + + window_private = (GdkWindowPrivate *) window; + + if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0) + { + gdk_dnd.drag_numwindows++; + gdk_dnd.drag_startwindows = g_realloc (gdk_dnd.drag_startwindows, + gdk_dnd.drag_numwindows + * sizeof(GdkWindow *)); + gdk_dnd.drag_startwindows[gdk_dnd.drag_numwindows - 1] = window; + window_private->dnd_drag_accepted = 0; + } + else + g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n"); +} + +void +gdk_window_dnd_drag_set (GdkWindow *window, + guint8 drag_enable, + gchar **typelist, + guint numtypes) +{ + GdkWindowPrivate *window_private; + int i, wasset = 0; + + g_return_if_fail (window != NULL); + window_private = (GdkWindowPrivate *) window; + + window_private->dnd_drag_enabled = drag_enable ? 1 : 0; + + if (drag_enable) + { + g_return_if_fail(typelist != NULL); + + if (window_private->dnd_drag_data_numtypesavail > 3) + wasset = 1; + window_private->dnd_drag_data_numtypesavail = numtypes; + + window_private->dnd_drag_data_typesavail = + g_realloc (window_private->dnd_drag_data_typesavail, + (numtypes + 1) * sizeof (GdkAtom)); + + for (i = 0; i < numtypes; i++) + { + /* Allow blanket use of ALL to get anything... */ + if (strcmp (typelist[i], "ALL")) + window_private->dnd_drag_data_typesavail[i] = + gdk_atom_intern (typelist[i], FALSE); + else + window_private->dnd_drag_data_typesavail[i] = None; + } + + /* + * set our extended type list if we need to + */ + if (numtypes > 3) + gdk_property_change(window, gdk_dnd.gdk_XdeTypelist, + XA_PRIMARY, 32, GDK_PROP_MODE_REPLACE, + (guchar *)(window_private->dnd_drag_data_typesavail + + (sizeof(GdkAtom) * 3)), + (numtypes - 3) * sizeof(GdkAtom)); + else if (wasset) + gdk_property_delete (window, gdk_dnd.gdk_XdeTypelist); + } + else + { + free (window_private->dnd_drag_data_typesavail); + window_private->dnd_drag_data_typesavail = NULL; + window_private->dnd_drag_data_numtypesavail = 0; + } +} + +void +gdk_window_dnd_drop_set (GdkWindow *window, + guint8 drop_enable, + gchar **typelist, + guint numtypes, + guint8 destructive_op) +{ + GdkWindowPrivate *window_private; + int i; + + g_return_if_fail (window != NULL); + + window_private = (GdkWindowPrivate *) window; + + window_private->dnd_drop_enabled = drop_enable ? 1 : 0; + if (drop_enable) + { + g_return_if_fail(typelist != NULL); + + window_private->dnd_drop_data_numtypesavail = numtypes; + + window_private->dnd_drop_data_typesavail = + g_realloc (window_private->dnd_drop_data_typesavail, + (numtypes + 1) * sizeof (GdkAtom)); + + for (i = 0; i < numtypes; i++) + window_private->dnd_drop_data_typesavail[i] = + gdk_atom_intern (typelist[i], FALSE); + + window_private->dnd_drop_destructive_op = destructive_op; + } +} + +/* + * This is used to reply to a GDK_DRAG_REQUEST event + * (which may be generated by XdeRequest or a confirmed drop... + */ +void +gdk_window_dnd_data_set (GdkWindow *window, + GdkEvent *event, + gpointer data, + gulong data_numbytes) +{ + GdkWindowPrivate *window_private; + XEvent sev; + GdkEventDropDataAvailable tmp_ev; + gchar *tmp; + + g_return_if_fail (window != NULL); + g_return_if_fail (event != NULL); + g_return_if_fail (data != NULL); + g_return_if_fail (data_numbytes > 0); + g_return_if_fail (event->type == GDK_DRAG_REQUEST); + + g_free (event->dragrequest.data_type); + event->dragrequest.data_type = NULL; + + window_private = (GdkWindowPrivate *) window; + g_return_if_fail (window_private->dnd_drag_accepted != 0); + + /* We set the property on our window... */ + gdk_property_change (window, window_private->dnd_drag_data_type, + XA_PRIMARY, 8, GDK_PROP_MODE_REPLACE, data, + data_numbytes); + tmp = gdk_atom_name(window_private->dnd_drag_data_type); + g_print("DnD type %s on window %ld\n", tmp, window_private->xwindow); + g_free(tmp); + + /* + * Then we send the event to tell the receiving window that the + * drop has happened + */ + tmp_ev.u.allflags = 0; + tmp_ev.u.flags.protocol_version = DND_PROTOCOL_VERSION; + tmp_ev.u.flags.isdrop = event->dragrequest.isdrop; + + sev.xclient.type = ClientMessage; + sev.xclient.format = 32; + sev.xclient.window = event->dragrequest.requestor; + sev.xclient.message_type = gdk_dnd.gdk_XdeDataAvailable; + sev.xclient.data.l[0] = window_private->xwindow; + sev.xclient.data.l[1] = tmp_ev.u.allflags; + sev.xclient.data.l[2] = window_private->dnd_drag_data_type; + + if (event->dragrequest.isdrop) + sev.xclient.data.l[3] = event->dragrequest.drop_coords.x + + (event->dragrequest.drop_coords.y << 16); + else + sev.xclient.data.l[3] = 0; + + sev.xclient.data.l[4] = 0; + + XSendEvent (gdk_display, event->dragrequest.requestor, False, + NoEventMask, &sev); +} |