X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gdk%2Fx11%2Fgdkwindow-x11.c;h=56e8cdfb81c01f71f3c0388c69860f12b4f1d420;hb=2e99e7713dc73ea5b7a000ab03b4d64176b9ad40;hp=f5de78cc3f162026483fe05b5c4ac009de68a685;hpb=1c77b5f9269a9841b100664dae61a95e1810da38;p=~andy%2Fgtk diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index f5de78cc3..56e8cdfb8 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -12,25 +12,39 @@ * 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. + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. */ #include #include #include -#include #include #include "gdk.h" -#include "../config.h" +#include "config.h" #include "gdkinput.h" #include "gdkprivate.h" #include "MwmUtil.h" -#include -#include -int nevent_masks = 17; -int event_mask_table[19] = +#if HAVE_CONFIG_H +# include +# if STDC_HEADERS +# include +# include +# include +# endif +#else +# include +# include +#endif + + +#ifdef HAVE_SHAPE_EXT +#include +#endif + +const int gdk_event_mask_table[20] = { ExposureMask, PointerMotionMask, @@ -50,48 +64,65 @@ int event_mask_table[19] = PropertyChangeMask, VisibilityChangeMask, 0, /* PROXIMITY_IN */ - 0 /* PROXIMTY_OUT */ + 0, /* PROXIMTY_OUT */ + SubstructureNotifyMask }; +const int gdk_nevent_masks = sizeof(gdk_event_mask_table)/sizeof(int); +static gboolean gdk_window_have_shape_ext (void); /* internal function created for and used by gdk_window_xid_at_coords */ Window -gdk_window_xid_at(Window base, gint bx, gint by, gint x, gint y, - GList *excludes, gboolean excl_child) +gdk_window_xid_at (Window base, + gint bx, + gint by, + gint x, + gint y, + GList *excludes, + gboolean excl_child) { GdkWindow *window; GdkWindowPrivate *private; Display *disp; - Window *list=NULL; - Window child=0,parent_win=0,root_win=0; - int num,i,ww,wh,wb,wd; - int wx,wy; + Window *list = NULL; + Window child = 0, parent_win = 0, root_win = 0; + int i; + unsigned int ww, wh, wb, wd, num; + int wx, wy; - window=(GdkWindow*)&gdk_root_parent; - private=(GdkWindowPrivate*)window; - disp=private->xdisplay; - if (!XGetGeometry(disp,base,&root_win,&wx,&wy,&ww,&wh,&wb,&wd)) + window = (GdkWindow*) &gdk_root_parent; + private = (GdkWindowPrivate*) window; + disp = private->xdisplay; + if (!XGetGeometry (disp, base, &root_win, &wx, &wy, &ww, &wh, &wb, &wd)) return 0; - wx+=bx;wy+=by; - if (!((x>=wx)&&(y>=wy)&&(x<(wx+ww))&&(y<(wy+wh)))) + wx += bx; + wy += by; + + if (!((x >= wx) && + (y >= wy) && + (x < (int) (wx + ww)) && + (y < (int) (wy + wh)))) return 0; - if (!XQueryTree(disp,base,&root_win,&parent_win,&list,&num)) + + if (!XQueryTree (disp, base, &root_win, &parent_win, &list, &num)) return base; + if (list) { - for (i=num-1;;i--) + for (i = num - 1; ; i--) { - if ((!excl_child)||(!g_list_find(excludes,(gpointer *)list[i]))) + if ((!excl_child) || (!g_list_find (excludes, (gpointer *) list[i]))) { - if ((child=gdk_window_xid_at(list[i],wx,wy,x,y,excludes,excl_child))!=0) + if ((child = gdk_window_xid_at (list[i], wx, wy, x, y, excludes, excl_child)) != 0) { - XFree(list); + XFree (list); return child; } } - if (!i) break; + if (!i) + break; } - XFree(list); + XFree (list); } return base; } @@ -110,24 +141,31 @@ gdk_window_xid_at(Window base, gint bx, gint by, gint x, gint y, * those X,Y co-ordinates. */ Window -gdk_window_xid_at_coords(gint x, gint y, GList *excludes, gboolean excl_child) +gdk_window_xid_at_coords (gint x, + gint y, + GList *excludes, + gboolean excl_child) { GdkWindow *window; GdkWindowPrivate *private; Display *disp; - Window *list=NULL; - Window root,child=0,parent_win=0,root_win=0; + Window *list = NULL; + Window root, child = 0, parent_win = 0, root_win = 0; unsigned int num; int i; - window=(GdkWindow*)&gdk_root_parent; - private=(GdkWindowPrivate*)window; - disp=private->xdisplay; - root=private->xwindow; - XGrabServer(disp); - num=g_list_length(excludes); - if (!XQueryTree(disp,root,&root_win,&parent_win,&list,&num)) - return root; + window = (GdkWindow*) &gdk_root_parent; + private = (GdkWindowPrivate*) window; + disp = private->xdisplay; + root = private->xwindow; + num = g_list_length (excludes); + + XGrabServer (disp); + if (!XQueryTree (disp, root, &root_win, &parent_win, &list, &num)) + { + XUngrabServer(disp); + return root; + } if (list) { i = num - 1; @@ -140,7 +178,7 @@ gdk_window_xid_at_coords(gint x, gint y, GList *excludes, gboolean excl_child) if (xwa.map_state != IsViewable) continue; - if (excl_child && g_list_find(excludes,(gpointer *)list[i])) + if (excl_child && g_list_find (excludes, (gpointer *) list[i])) continue; if ((child = gdk_window_xid_at (list[i], 0, 0, x, y, excludes, excl_child)) == 0) @@ -148,28 +186,28 @@ gdk_window_xid_at_coords(gint x, gint y, GList *excludes, gboolean excl_child) if (excludes) { - if (!g_list_find(excludes,(gpointer *)child)) + if (!g_list_find (excludes, (gpointer *) child)) { - XFree(list); - XUngrabServer(disp); + XFree (list); + XUngrabServer (disp); return child; } } else { - XFree(list); - XUngrabServer(disp); + XFree (list); + XUngrabServer (disp); return child; } } while (--i > 0); - XFree(list); + XFree (list); } - XUngrabServer(disp); + XUngrabServer (disp); return root; } void -gdk_window_init () +gdk_window_init (void) { XWindowAttributes xattributes; unsigned int width; @@ -182,12 +220,17 @@ gdk_window_init () &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.xdisplay = gdk_display; gdk_root_parent.window_type = GDK_WINDOW_ROOT; gdk_root_parent.window.user_data = NULL; gdk_root_parent.width = width; gdk_root_parent.height = height; + gdk_root_parent.children = NULL; + gdk_root_parent.colormap = NULL; + gdk_root_parent.ref_count = 1; + + gdk_xid_table_insert (&gdk_root_window, &gdk_root_parent); } GdkWindow* @@ -199,7 +242,6 @@ gdk_window_new (GdkWindow *parent, GdkWindowPrivate *private; GdkWindowPrivate *parent_private; GdkVisual *visual; - GdkColormap *colormap; Display *parent_display; Window xparent; Visual *xvisual; @@ -229,8 +271,13 @@ gdk_window_new (GdkWindow *parent, window = (GdkWindow*) private; private->parent = parent; + + if (parent_private) + parent_private->children = g_list_prepend (parent_private->children, window); + private->xdisplay = parent_display; private->destroyed = FALSE; + private->mapped = FALSE; private->resize_count = 0; private->ref_count = 1; xattributes_mask = 0; @@ -251,16 +298,9 @@ gdk_window_new (GdkWindow *parent, 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; private->filters = NULL; + private->children = NULL; window->user_data = NULL; @@ -271,10 +311,10 @@ gdk_window_new (GdkWindow *parent, xvisual = ((GdkVisualPrivate*) visual)->xvisual; xattributes.event_mask = StructureNotifyMask; - for (i = 0; i < nevent_masks; i++) + for (i = 0; i < gdk_nevent_masks; i++) { if (attributes->event_mask & (1 << (i + 1))) - xattributes.event_mask |= event_mask_table[i]; + xattributes.event_mask |= gdk_event_mask_table[i]; } if (xattributes.event_mask) @@ -293,9 +333,14 @@ gdk_window_new (GdkWindow *parent, depth = visual->depth; if (attributes_mask & GDK_WA_COLORMAP) - colormap = attributes->colormap; + private->colormap = attributes->colormap; else - colormap = gdk_colormap_get_system (); + { + if ((((GdkVisualPrivate*)gdk_visual_get_system())->xvisual) == xvisual) + private->colormap = gdk_colormap_get_system (); + else + private->colormap = gdk_colormap_new (visual, False); + } xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen); xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen); @@ -304,26 +349,26 @@ gdk_window_new (GdkWindow *parent, switch (private->window_type) { case GDK_WINDOW_TOPLEVEL: - xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap; + xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap; xattributes_mask |= CWColormap; xparent = gdk_root_window; break; case GDK_WINDOW_CHILD: - xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap; + xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap; xattributes_mask |= CWColormap; break; case GDK_WINDOW_DIALOG: - xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap; + xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap; xattributes_mask |= CWColormap; xparent = gdk_root_window; break; case GDK_WINDOW_TEMP: - xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap; + xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap; xattributes_mask |= CWColormap; xparent = gdk_root_window; @@ -345,7 +390,7 @@ gdk_window_new (GdkWindow *parent, { depth = 0; class = InputOnly; - colormap = NULL; + private->colormap = NULL; } private->xwindow = XCreateWindow (private->xdisplay, xparent, @@ -355,6 +400,9 @@ gdk_window_new (GdkWindow *parent, gdk_window_ref (window); gdk_xid_table_insert (&private->xwindow, window); + if (private->colormap) + gdk_colormap_ref (private->colormap); + gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ? (attributes->cursor) : NULL)); @@ -369,10 +417,10 @@ gdk_window_new (GdkWindow *parent, 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)))) + (private->colormap != gdk_colormap_get_system ()) && + (private->colormap != gdk_window_get_colormap (gdk_window_get_toplevel (window)))) { - GDK_NOTE (MISC, g_print ("adding colormap window\n")); + GDK_NOTE (MISC, g_message ("adding colormap window\n")); gdk_window_add_colormap_windows (window); } @@ -402,7 +450,7 @@ gdk_window_new (GdkWindow *parent, if (attributes_mask & GDK_WA_TITLE) title = attributes->title; else - title = gdk_progname; + title = g_get_prgname (); XmbSetWMProperties (private->xdisplay, private->xwindow, title, title, @@ -427,22 +475,33 @@ gdk_window_foreign_new (guint32 anid) { GdkWindow *window; GdkWindowPrivate *private; + GdkWindowPrivate *parent_private; XWindowAttributes attrs; Window root, parent; - Window *children; + Window *children = NULL; guint nchildren; + if(!XGetWindowAttributes (gdk_display, anid, &attrs)) { + g_warning("XGetWindowAttributes failed on window ID %d\n", anid); + return NULL; + } + private = g_new (GdkWindowPrivate, 1); window = (GdkWindow*) private; - XGetWindowAttributes (gdk_display, anid, &attrs); - /* FIXME: This is pretty expensive. Maybe the caller should supply * the parent */ XQueryTree (gdk_display, anid, &root, &parent, &children, &nchildren); - XFree (children); + + if (children) + XFree (children); private->parent = gdk_xid_table_lookup (parent); + parent_private = (GdkWindowPrivate *)private->parent; + + if (parent_private) + parent_private->children = g_list_prepend (parent_private->children, window); + private->xwindow = anid; private->xdisplay = gdk_display; private->x = attrs.x; @@ -453,19 +512,13 @@ gdk_window_foreign_new (guint32 anid) private->ref_count = 1; private->window_type = GDK_WINDOW_FOREIGN; private->destroyed = FALSE; + private->mapped = (attrs.map_state != IsUnmapped); private->extension_events = 0; - - 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; + private->colormap = NULL; private->filters = NULL; + private->children = NULL; window->user_data = NULL; @@ -504,10 +557,17 @@ gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy, case GDK_WINDOW_FOREIGN: if (!private->destroyed) { + if (private->parent) + { + GdkWindowPrivate *parent_private = (GdkWindowPrivate *)private->parent; + if (parent_private->children) + parent_private->children = g_list_remove (parent_private->children, window); + } + if (private->window_type != GDK_WINDOW_FOREIGN) { - children = gdk_window_get_children (window); - tmp = children; + children = tmp = private->children; + private->children = NULL; while (tmp) { @@ -519,24 +579,13 @@ gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy, gdk_window_internal_destroy (temp_window, FALSE, our_destroy); } - + g_list_free (children); } if (private->extension_events != 0) gdk_input_window_destroy (window); - if(private->dnd_drag_data_numtypesavail > 0) - { - g_free (private->dnd_drag_data_typesavail); - private->dnd_drag_data_typesavail = NULL; - } - if(private->dnd_drop_data_numtypesavail > 0) - { - g_free (private->dnd_drop_data_typesavail); - private->dnd_drop_data_typesavail = NULL; - } - if (private->filters) { tmp = private->filters; @@ -578,6 +627,9 @@ gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy, else if (xdestroy) XDestroyWindow (private->xdisplay, private->xwindow); + if (private->colormap) + gdk_colormap_unref (private->colormap); + private->destroyed = TRUE; } break; @@ -645,7 +697,13 @@ gdk_window_unref (GdkWindow *window) if (private->ref_count == 0) { if (!private->destroyed) - g_warning ("losing last reference to undestroyed window\n"); + { + if (private->window_type == GDK_WINDOW_FOREIGN) + gdk_xid_table_remove (private->xwindow); + else + g_warning ("losing last reference to undestroyed window\n"); + } + g_dataset_destroy (window); g_free (window); } } @@ -660,6 +718,7 @@ gdk_window_show (GdkWindow *window) private = (GdkWindowPrivate*) window; if (!private->destroyed) { + private->mapped = TRUE; XRaiseWindow (private->xdisplay, private->xwindow); XMapWindow (private->xdisplay, private->xwindow); } @@ -674,7 +733,10 @@ gdk_window_hide (GdkWindow *window) private = (GdkWindowPrivate*) window; if (!private->destroyed) - XUnmapWindow (private->xdisplay, private->xwindow); + { + private->mapped = FALSE; + XUnmapWindow (private->xdisplay, private->xwindow); + } } void @@ -782,6 +844,7 @@ gdk_window_reparent (GdkWindow *window, { GdkWindowPrivate *window_private; GdkWindowPrivate *parent_private; + GdkWindowPrivate *old_parent_private; g_return_if_fail (window != NULL); @@ -789,6 +852,7 @@ gdk_window_reparent (GdkWindow *window, new_parent = (GdkWindow*) &gdk_root_parent; window_private = (GdkWindowPrivate*) window; + old_parent_private = (GdkWindowPrivate*)window_private->parent; parent_private = (GdkWindowPrivate*) new_parent; if (!window_private->destroyed && !parent_private->destroyed) @@ -796,6 +860,13 @@ gdk_window_reparent (GdkWindow *window, window_private->xwindow, parent_private->xwindow, x, y); + + window_private->parent = new_parent; + + if (old_parent_private) + old_parent_private->children = g_list_remove (old_parent_private->children, window); + parent_private->children = g_list_prepend (parent_private->children, window); + } void @@ -963,6 +1034,82 @@ gdk_window_set_hints (GdkWindow *window, XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints); } +void +gdk_window_set_geometry_hints (GdkWindow *window, + GdkGeometry *geometry, + GdkWindowHints geom_mask) +{ + GdkWindowPrivate *private; + XSizeHints size_hints; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + if (private->destroyed) + return; + + size_hints.flags = 0; + + if (geom_mask & GDK_HINT_POS) + size_hints.flags |= PPosition; + + if (geom_mask & GDK_HINT_MIN_SIZE) + { + size_hints.flags |= PMinSize; + size_hints.min_width = geometry->min_width; + size_hints.min_height = geometry->min_height; + } + + if (geom_mask & GDK_HINT_MAX_SIZE) + { + size_hints.flags |= PMaxSize; + size_hints.max_width = geometry->max_width; + size_hints.max_height = geometry->max_height; + } + + if (geom_mask & GDK_HINT_BASE_SIZE) + { + size_hints.flags |= PBaseSize; + size_hints.base_width = geometry->base_width; + size_hints.base_height = geometry->base_height; + } + + if (geom_mask & GDK_HINT_RESIZE_INC) + { + size_hints.flags |= PResizeInc; + size_hints.width_inc = geometry->width_inc; + size_hints.height_inc = geometry->height_inc; + } + + if (geom_mask & GDK_HINT_ASPECT) + { + size_hints.flags |= PAspect; + if (geometry->min_aspect <= 1) + { + size_hints.min_aspect.x = G_MAXINT * geometry->min_aspect; + size_hints.min_aspect.y = G_MAXINT; + } + else + { + size_hints.min_aspect.x = G_MAXINT; + size_hints.min_aspect.y = G_MAXINT / geometry->min_aspect;; + } + if (geometry->max_aspect <= 1) + { + size_hints.max_aspect.x = G_MAXINT * geometry->max_aspect; + size_hints.max_aspect.y = G_MAXINT; + } + else + { + size_hints.max_aspect.x = G_MAXINT; + size_hints.max_aspect.y = G_MAXINT / geometry->max_aspect;; + } + } + + if (geom_mask) + XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints); +} + void gdk_window_set_title (GdkWindow *window, const gchar *title) @@ -977,6 +1124,42 @@ gdk_window_set_title (GdkWindow *window, title, title, NULL, 0, NULL, NULL, NULL); } +void +gdk_window_set_role (GdkWindow *window, + const gchar *role) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + + if (role) + XChangeProperty (private->xdisplay, private->xwindow, + gdk_atom_intern ("WM_WINDOW_ROLE", FALSE), XA_STRING, + 8, PropModeReplace, role, strlen(role)); + else + XDeleteProperty (private->xdisplay, private->xwindow, + gdk_atom_intern ("WM_WINDOW_ROLE", FALSE)); +} + +void +gdk_window_set_transient_for (GdkWindow *window, + GdkWindow *parent) +{ + GdkWindowPrivate *private; + GdkWindowPrivate *parent_private; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + parent_private = (GdkWindowPrivate*) parent; + + if (!private->destroyed && !parent_private->destroyed) + XSetTransientForHint (private->xdisplay, + private->xwindow, parent_private->xwindow); +} + void gdk_window_set_background (GdkWindow *window, GdkColor *color) @@ -1056,6 +1239,11 @@ gdk_window_set_colormap (GdkWindow *window, XSetWindowColormap (window_private->xdisplay, window_private->xwindow, colormap_private->xcolormap); + + if (window_private->colormap) + gdk_colormap_unref (window_private->colormap); + window_private->colormap = colormap; + gdk_colormap_ref (window_private->colormap); if (window_private->window_type != GDK_WINDOW_TOPLEVEL) gdk_window_add_colormap_windows (window); @@ -1150,20 +1338,27 @@ gdk_window_get_visual (GdkWindow *window) { GdkWindowPrivate *window_private; XWindowAttributes window_attributes; - + g_return_val_if_fail (window != NULL, NULL); - + window_private = (GdkWindowPrivate*) window; + /* Huh? ->parent is never set for a pixmap. We should just return + * null immeditately + */ while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP)) window_private = (GdkWindowPrivate*) window_private->parent; if (window_private && !window_private->destroyed) { - XGetWindowAttributes (window_private->xdisplay, - window_private->xwindow, - &window_attributes); - - return gdk_visual_lookup (window_attributes.visual); + if (window_private->colormap == NULL) + { + XGetWindowAttributes (window_private->xdisplay, + window_private->xwindow, + &window_attributes); + return gdk_visual_lookup (window_attributes.visual); + } + else + return ((GdkColormapPrivate *)window_private->colormap)->visual; } return NULL; @@ -1176,16 +1371,20 @@ gdk_window_get_colormap (GdkWindow *window) XWindowAttributes window_attributes; g_return_val_if_fail (window != NULL, NULL); - window_private = (GdkWindowPrivate*) window; - + + g_return_val_if_fail (window_private->window_type != GDK_WINDOW_PIXMAP, NULL); if (!window_private->destroyed) { - XGetWindowAttributes (window_private->xdisplay, - window_private->xwindow, - &window_attributes); - - return gdk_colormap_lookup (window_attributes.colormap); + if (window_private->colormap == NULL) + { + XGetWindowAttributes (window_private->xdisplay, + window_private->xwindow, + &window_attributes); + return gdk_colormap_lookup (window_attributes.colormap); + } + else + return window_private->colormap; } return NULL; @@ -1210,7 +1409,8 @@ gdk_window_get_origin (GdkWindow *window, GdkWindowPrivate *private; gint return_val; Window child; - gint tx, ty; + gint tx = 0; + gint ty = 0; g_return_val_if_fail (window != NULL, 0); @@ -1224,17 +1424,140 @@ gdk_window_get_origin (GdkWindow *window, 0, 0, &tx, &ty, &child); + } + else + return_val = 0; + + if (x) + *x = tx; + if (y) + *y = ty; + + return return_val; +} + +gboolean +gdk_window_get_deskrelative_origin (GdkWindow *window, + gint *x, + gint *y) +{ + GdkWindowPrivate *private; + gboolean return_val = FALSE; + gint num_children, format_return; + Window win, *child, parent, root; + gint tx = 0; + gint ty = 0; + Atom type_return; + static Atom atom = 0; + gulong number_return, bytes_after_return; + guchar *data_return; + + g_return_val_if_fail (window != NULL, 0); + + private = (GdkWindowPrivate*) window; + + if (!private->destroyed) + { + if (!atom) + atom = XInternAtom(private->xdisplay, "ENLIGHTENMENT_DESKTOP", False); + win = private->xwindow; + + while (XQueryTree(private->xdisplay, win, &root, &parent, + &child, (unsigned int *)&num_children)) + { + if ((child) && (num_children > 0)) + XFree(child); + + if (!parent) + break; + else + win = parent; + + if (win == root) + break; + + data_return = NULL; + XGetWindowProperty(private->xdisplay, win, atom, 0, 0, + False, XA_CARDINAL, &type_return, &format_return, + &number_return, &bytes_after_return, &data_return); + if (type_return == XA_CARDINAL) + { + XFree(data_return); + break; + } + } + + return_val = XTranslateCoordinates (private->xdisplay, + private->xwindow, + win, + 0, 0, &tx, &ty, + &root); if (x) *x = tx; if (y) *y = ty; } - else - return_val = 0; + return return_val; } +void +gdk_window_get_root_origin (GdkWindow *window, + gint *x, + gint *y) +{ + GdkWindowPrivate *private; + Window xwindow; + Window xparent; + Window root; + Window *children; + unsigned int nchildren; + + g_return_if_fail (window != NULL); + + private = (GdkWindowPrivate*) window; + if (x) + *x = 0; + if (y) + *y = 0; + if (private->destroyed) + return; + + while (private->parent && ((GdkWindowPrivate*) private->parent)->parent) + private = (GdkWindowPrivate*) private->parent; + if (private->destroyed) + return; + + xparent = private->xwindow; + do + { + xwindow = xparent; + if (!XQueryTree (private->xdisplay, xwindow, + &root, &xparent, + &children, &nchildren)) + return; + + if (children) + XFree (children); + } + while (xparent != root); + + if (xparent == root) + { + unsigned int ww, wh, wb, wd; + int wx, wy; + + if (XGetGeometry (private->xdisplay, xwindow, &root, &wx, &wy, &ww, &wh, &wb, &wd)) + { + if (x) + *x = wx; + if (y) + *y = wy; + } + } +} + GdkWindow* gdk_window_get_pointer (GdkWindow *window, gint *x, @@ -1246,8 +1569,9 @@ gdk_window_get_pointer (GdkWindow *window, Window root; Window child; int rootx, rooty; - int winx, winy; - unsigned int xmask; + int winx = 0; + int winy = 0; + unsigned int xmask = 0; if (!window) window = (GdkWindow*) &gdk_root_parent; @@ -1259,17 +1583,60 @@ gdk_window_get_pointer (GdkWindow *window, 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); } + if (x) + *x = winx; + if (y) + *y = winy; + if (mask) + *mask = xmask; + return return_val; } +GdkWindow* +gdk_window_at_pointer (gint *win_x, + gint *win_y) +{ + GdkWindowPrivate *private; + GdkWindow *window; + Window root; + Window xwindow; + Window xwindow_last = 0; + int rootx = -1, rooty = -1; + int winx, winy; + unsigned int xmask; + + private = &gdk_root_parent; + + xwindow = private->xwindow; + + XGrabServer (private->xdisplay); + while (xwindow) + { + xwindow_last = xwindow; + XQueryPointer (private->xdisplay, + xwindow, + &root, &xwindow, + &rootx, &rooty, + &winx, &winy, + &xmask); + } + XUngrabServer (private->xdisplay); + + window = gdk_window_lookup (xwindow_last); + + if (win_x) + *win_x = window ? winx : -1; + if (win_y) + *win_y = window ? winy : -1; + + return window; +} + GdkWindow* gdk_window_get_parent (GdkWindow *window) { @@ -1328,7 +1695,8 @@ gdk_window_get_children (GdkWindow *window) children = g_list_prepend (children, child); } - XFree (xchildren); + if (xchildren) + XFree (xchildren); } return children; @@ -1352,9 +1720,9 @@ gdk_window_get_events (GdkWindow *window) &attrs); event_mask = 0; - for (i = 0; i < nevent_masks; i++) + for (i = 0; i < gdk_nevent_masks; i++) { - if (attrs.your_event_mask & event_mask_table[i]) + if (attrs.your_event_mask & gdk_event_mask_table[i]) event_mask |= 1 << (i + 1); } @@ -1376,10 +1744,10 @@ gdk_window_set_events (GdkWindow *window, return; xevent_mask = StructureNotifyMask; - for (i = 0; i < nevent_masks; i++) + for (i = 0; i < gdk_nevent_masks; i++) { if (event_mask & (1 << (i + 1))) - xevent_mask |= event_mask_table[i]; + xevent_mask |= gdk_event_mask_table[i]; } XSelectInput (gdk_display, private->xwindow, @@ -1404,17 +1772,20 @@ gdk_window_add_colormap_windows (GdkWindow *window) if (window_private->destroyed) return; + old_windows = NULL; 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; + { + XFree (old_windows); + return; + } new_windows = g_new (Window, count + 1); @@ -1431,10 +1802,27 @@ gdk_window_add_colormap_windows (GdkWindow *window) XFree (old_windows); } +static gboolean +gdk_window_have_shape_ext (void) +{ + enum { UNKNOWN, NO, YES }; + static gint have_shape = UNKNOWN; + + if (have_shape == UNKNOWN) + { + int ignore; + if (XQueryExtension(gdk_display, "SHAPE", &ignore, &ignore, &ignore)) + have_shape = YES; + else + have_shape = NO; + } + + return (have_shape == YES); +} + /* * This needs the X11 shape extension. - * If not available, simply remove the call to - * XShapeCombineMask. Shaped windows will look + * If not available, shaped windows will look * ugly, but programs still work. Stefan Wille */ void @@ -1447,216 +1835,35 @@ gdk_window_shape_combine_mask (GdkWindow *window, g_return_if_fail (window != NULL); - /* This is needed, according to raster */ - gdk_window_set_override_redirect(window, TRUE); - +#ifdef HAVE_SHAPE_EXT window_private = (GdkWindowPrivate*) window; if (window_private->destroyed) return; - if (mask) + if (gdk_window_have_shape_ext()) { - GdkWindowPrivate *pixmap_private; - - pixmap_private = (GdkWindowPrivate*) mask; - pixmap = (Pixmap) pixmap_private->xwindow; - } - else - { - x = 0; - y = 0; - pixmap = None; - } - - XShapeCombineMask (window_private->xdisplay, - window_private->xwindow, - ShapeBounding, - x, y, - pixmap, - ShapeSet); -} - -void -gdk_dnd_drag_addwindow (GdkWindow *window) -{ - GdkWindowPrivate *window_private; - - g_return_if_fail (window != NULL); - - window_private = (GdkWindowPrivate *) window; - if (window_private->destroyed) - return; - - 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; - if (window_private->destroyed) - return; - - 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++) + if (mask) { - /* 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; + GdkWindowPrivate *pixmap_private; + + pixmap_private = (GdkWindowPrivate*) mask; + pixmap = (Pixmap) pixmap_private->xwindow; + } + else + { + x = 0; + y = 0; + pixmap = 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 - { - g_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; - if (window_private->destroyed) - return; - - 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; + XShapeCombineMask (window_private->xdisplay, + window_private->xwindow, + ShapeBounding, + x, y, + pixmap, + ShapeSet); } -} - -/* - * 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); - - window_private = (GdkWindowPrivate *) window; - g_return_if_fail (window_private->dnd_drag_accepted != 0); - if (window_private->destroyed) - return; - - /* 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); -#ifdef DEBUG_DND - g_print("DnD type %s on window %ld\n", tmp, window_private->xwindow); -#endif - 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] = event->dragrequest.timestamp; - - if (!gdk_send_xevent (event->dragrequest.requestor, False, - StructureNotifyMask, &sev)) - GDK_NOTE (DND, g_print("Sending XdeDataAvailable to %#x failed\n", - event->dragrequest.requestor)); - +#endif /* HAVE_SHAPE_EXT */ } void @@ -1701,7 +1908,7 @@ gdk_window_remove_filter (GdkWindow *window, gpointer data) { GdkWindowPrivate *private; - GList *tmp_list; + GList *tmp_list, *node; GdkEventFilter *filter; private = (GdkWindowPrivate*) window; @@ -1714,15 +1921,16 @@ gdk_window_remove_filter (GdkWindow *window, while (tmp_list) { filter = (GdkEventFilter *)tmp_list->data; + node = tmp_list; tmp_list = tmp_list->next; if ((filter->function == function) && (filter->data == data)) { if(private) - private->filters = g_list_remove_link (private->filters, tmp_list); + private->filters = g_list_remove_link (private->filters, node); else gdk_default_filters = g_list_remove_link (gdk_default_filters, tmp_list); - g_list_free_1 (tmp_list); + g_list_free_1 (node); g_free (filter); return; @@ -1814,7 +2022,8 @@ gdk_window_set_icon_name (GdkWindow *window, XSetWMIconName (window_private->xdisplay, window_private->xwindow, &property); - XFree(property.value); + if (property.value) + XFree (property.value); } void @@ -1912,3 +2121,417 @@ gdk_window_set_functions (GdkWindow *window, gdk_window_set_mwm_hints (window, &hints); } + +GList * +gdk_window_get_toplevels (void) +{ + GList *new_list = NULL; + GList *tmp_list; + + tmp_list = gdk_root_parent.children; + while (tmp_list) + { + new_list = g_list_prepend (new_list, tmp_list->data); + tmp_list = tmp_list->next; + } + + return new_list; +} + +/* + * propagate the shapes from all child windows of a GDK window to the parent + * window. Shamelessly ripped from Enlightenment's code + * + * - Raster + */ + +struct _gdk_span +{ + gint start; + gint end; + struct _gdk_span *next; +}; + +static void +gdk_add_to_span(struct _gdk_span **s, int x, int xx) +{ + struct _gdk_span *ptr1, *ptr2, *noo, *ss; + gchar spanning; + + ptr2 = NULL; + ptr1 = *s; + spanning = 0; + ss = NULL; + /* scan the spans for this line */ + while (ptr1) + { + /* -- -> new span */ + /* == -> existing span */ + /* ## -> spans intersect */ + /* if we are in the middle of spanning the span into the line */ + if (spanning) + { + /* case: ---- ==== */ + if (xx < ptr1->start - 1) + { + /* ends before next span - extend to here */ + ss->end = xx; + return; + } + /* case: ----##=== */ + else if (xx <= ptr1->end) + { + /* crosses into next span - delete next span and append */ + ss->end = ptr1->end; + ss->next = ptr1->next; + g_free(ptr1); + return; + } + /* case: ---###--- */ + else + { + /* overlaps next span - delete and keep checking */ + ss->next = ptr1->next; + g_free(ptr1); + ptr1 = ss; + } + } + /* otherwise havent started spanning it in yet */ + else + { + /* case: ---- ==== */ + if (xx < ptr1->start - 1) + { + /* insert span here in list */ + noo = g_malloc(sizeof(struct _gdk_span)); + + if (noo) + { + noo->start = x; + noo->end = xx; + noo->next = ptr1; + if (ptr2) + ptr2->next = noo; + else + *s = noo; + } + return; + } + /* case: ----##=== */ + else if ((x < ptr1->start) && (xx <= ptr1->end)) + { + /* expand this span to the left point of the new one */ + ptr1->start = x; + return; + } + /* case: ===###=== */ + else if ((x >= ptr1->start) && (xx <= ptr1->end)) + { + /* throw the span away */ + return; + } + /* case: ---###--- */ + else if ((x < ptr1->start) && (xx > ptr1->end)) + { + ss = ptr1; + spanning = 1; + ptr1->start = x; + ptr1->end = xx; + } + /* case: ===##---- */ + else if ((x >= ptr1->start) && (x <= ptr1->end + 1) && (xx > ptr1->end)) + { + ss = ptr1; + spanning = 1; + ptr1->end = xx; + } + /* case: ==== ---- */ + /* case handled by next loop iteration - first case */ + } + ptr2 = ptr1; + ptr1 = ptr1->next; + } + /* it started in the middle but spans beyond your current list */ + if (spanning) + { + ptr2->end = xx; + return; + } + /* it does not start inside a span or in the middle, so add it to the end */ + noo = g_malloc(sizeof(struct _gdk_span)); + + if (noo) + { + noo->start = x; + noo->end = xx; + if (ptr2) + { + noo->next = ptr2->next; + ptr2->next = noo; + } + else + { + noo->next = NULL; + *s = noo; + } + } + return; +} + +static void +gdk_add_rectangles (Display *disp, Window win, struct _gdk_span **spans, + gint basew, gint baseh, gint x, gint y) +{ + gint a, k; + gint x1, y1, x2, y2; + gint rn, ord; + XRectangle *rl; + + rl = XShapeGetRectangles(disp, win, ShapeBounding, &rn, &ord); + if (rl) + { + /* go through all clip rects in this window's shape */ + for (k = 0; k < rn; k++) + { + /* for each clip rect, add it to each line's spans */ + x1 = x + rl[k].x; + x2 = x + rl[k].x + (rl[k].width - 1); + y1 = y + rl[k].y; + y2 = y + rl[k].y + (rl[k].height - 1); + if (x1 < 0) + x1 = 0; + if (y1 < 0) + y1 = 0; + if (x2 >= basew) + x2 = basew - 1; + if (y2 >= baseh) + y2 = baseh - 1; + for (a = y1; a <= y2; a++) + { + if ((x2 - x1) >= 0) + gdk_add_to_span(&spans[a], x1, x2); + } + } + XFree(rl); + } +} + +static void +gdk_propagate_shapes(Display *disp, Window win, gboolean merge) +{ + Window rt, par, *list = NULL; + gint i, j, num = 0, num_rects = 0; + gint x, y, contig; + guint w, h, d; + gint baseh, basew; + XRectangle *rects = NULL; + struct _gdk_span **spans = NULL, *ptr1, *ptr2, *ptr3; + XWindowAttributes xatt; + + XGetGeometry(disp, win, &rt, &x, &y, &w, &h, &d, &d); + if (h <= 0) + return; + basew = w; + baseh = h; + spans = g_malloc(sizeof(struct _gdk_span *) * h); + + for (i = 0; i < h; i++) + spans[i] = NULL; + XQueryTree(disp, win, &rt, &par, &list, (unsigned int *)&num); + if (list) + { + /* go through all child windows and create/insert spans */ + for (i = 0; i < num; i++) + { + if (XGetWindowAttributes(disp, list[i], &xatt) && (xatt.map_state != IsUnmapped)) + if (XGetGeometry(disp, list[i], &rt, &x, &y, &w, &h, &d, &d)) + gdk_add_rectangles (disp, list[i], spans, basew, baseh, x, y); + } + if (merge) + gdk_add_rectangles (disp, win, spans, basew, baseh, x, y); + + /* go through the spans list and build a list of rects */ + rects = g_malloc(sizeof(XRectangle) * 256); + num_rects = 0; + for (i = 0; i < baseh; i++) + { + ptr1 = spans[i]; + /* go through the line for all spans */ + while (ptr1) + { + rects[num_rects].x = ptr1->start; + rects[num_rects].y = i; + rects[num_rects].width = ptr1->end - ptr1->start + 1; + rects[num_rects].height = 1; + j = i + 1; + /* if there are more lines */ + contig = 1; + /* while contigous rects (same start/end coords) exist */ + while ((contig) && (j < baseh)) + { + /* search next line for spans matching this one */ + contig = 0; + ptr2 = spans[j]; + ptr3 = NULL; + while (ptr2) + { + /* if we have an exact span match set contig */ + if ((ptr2->start == ptr1->start) && + (ptr2->end == ptr1->end)) + { + contig = 1; + /* remove the span - not needed */ + if (ptr3) + { + ptr3->next = ptr2->next; + g_free(ptr2); + ptr2 = NULL; + } + else + { + spans[j] = ptr2->next; + g_free(ptr2); + ptr2 = NULL; + } + break; + } + /* gone past the span point no point looking */ + else if (ptr2->start < ptr1->start) + break; + if (ptr2) + { + ptr3 = ptr2; + ptr2 = ptr2->next; + } + } + /* if a contiguous span was found increase the rect h */ + if (contig) + { + rects[num_rects].height++; + j++; + } + } + /* up the rect count */ + num_rects++; + /* every 256 new rects increase the rect array */ + if ((num_rects % 256) == 0) + rects = g_realloc(rects, sizeof(XRectangle) * (num_rects + 256)); + ptr1 = ptr1->next; + } + } + /* set the rects as the shape mask */ + if (rects) + { + XShapeCombineRectangles(disp, win, ShapeBounding, 0, 0, rects, num_rects, + ShapeSet, YXSorted); + g_free(rects); + } + XFree(list); + } + /* free up all the spans we made */ + for (i = 0; i < baseh; i++) + { + ptr1 = spans[i]; + while (ptr1) + { + ptr2 = ptr1; + ptr1 = ptr1->next; + g_free(ptr2); + } + } + g_free(spans); +} + +void +gdk_window_set_child_shapes (GdkWindow *window) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + +#ifdef HAVE_SHAPE_EXT + private = (GdkWindowPrivate*) window; + if (private->destroyed) + return; + + if (gdk_window_have_shape_ext()) + gdk_propagate_shapes (private->xdisplay, private->xwindow, FALSE); +#endif +} + +void +gdk_window_merge_child_shapes (GdkWindow *window) +{ + GdkWindowPrivate *private; + + g_return_if_fail (window != NULL); + +#ifdef HAVE_SHAPE_EXT + private = (GdkWindowPrivate*) window; + if (private->destroyed) + return; + + if (gdk_window_have_shape_ext()) + gdk_propagate_shapes (private->xdisplay, private->xwindow, TRUE); +#endif +} + +/************************************************************* + * gdk_window_is_visible: + * Check if the given window is mapped. + * arguments: + * window: + * results: + * is the window mapped + *************************************************************/ + +gboolean +gdk_window_is_visible (GdkWindow *window) +{ + GdkWindowPrivate *private = (GdkWindowPrivate *)window; + + g_return_val_if_fail (window != NULL, FALSE); + + return private->mapped; +} + +/************************************************************* + * gdk_window_is_viewable: + * Check if the window and all ancestors of the window + * are mapped. (This is not necessarily "viewable" in + * the X sense, since we only check as far as we have + * GDK window parents, not to the root window) + * arguments: + * window: + * results: + * is the window viewable + *************************************************************/ + +gboolean +gdk_window_is_viewable (GdkWindow *window) +{ + GdkWindowPrivate *private = (GdkWindowPrivate *)window; + + g_return_val_if_fail (window != NULL, FALSE); + + while (private && (private != &gdk_root_parent)) + { + if (!private->mapped) + return FALSE; + + private = (GdkWindowPrivate *)private->parent; + } + + return TRUE; +} + +void +gdk_drawable_set_data (GdkDrawable *drawable, + const gchar *key, + gpointer data, + GDestroyNotify destroy_func) +{ + g_dataset_set_data_full (drawable, key, data, destroy_func); +} + +