was added in 2.8.
@GDK_DAMAGE: the content of the window has been changed. This event type
was added in 2.14.
+@GDK_EVENT_LAST:
<!-- ##### ENUM GdkEventMask ##### -->
<para>
@GDK_WINDOW_DIALOG: useless/deprecated compatibility type
@GDK_WINDOW_TEMP: override redirect temporary window (used to implement #GtkMenu)
@GDK_WINDOW_FOREIGN: foreign window (see gdk_window_foreign_new())
+@GDK_WINDOW_OFFSCREEN:
<!-- ##### ENUM GdkWindowClass ##### -->
<para>
gdkintl.h \
gdkkeys.c \
gdkkeyuni.c \
+ gdkoffscreenwindow.c \
gdkpango.c \
gdkpixbuf-drawable.c \
gdkpixbuf-render.c \
gdkincludedir = $(includedir)/gtk-2.0/gdk
gdkinclude_HEADERS = $(gdk_public_h_sources) $(gdk_built_public_sources)
-# gdkmarshalers.c is not here because it is currently an empty file
common_sources = \
$(gdk_c_sources) \
gdkenumtypes.c \
+ gdkmarshalers.c \
gdkmarshalers.h
libgdk_directfb_2_0_la_SOURCES = $(common_sources)
gdk_set_use_xshm
#endif
gdk_keyboard_grab
-gdk_keyboard_grab_info_libgtk_only
-gdk_pointer_grab
-gdk_pointer_grab_info_libgtk_only
#endif
#endif
gdk_pointer_ungrab
gdk_event_send_client_message
gdk_event_send_clientmessage_toall
+gdk_keyboard_grab_info_libgtk_only
+gdk_pointer_grab_info_libgtk_only
+gdk_display_pointer_is_grabbed
#endif
#endif
#endif
#endif
-#if IN_HEADER(__GDK_PIXMAP_H__)
-#if IN_FILE(__GDK_PIXMAP_X11_C__)
-gdk_bitmap_create_from_data
-#endif
-#endif
-
#if IN_HEADER(__GDK_FONT_H__)
#if IN_FILE(__GDK_FONT_C__)
#ifndef GDK_DISABLE_DEPRECATED
gdk_display_get_name
gdk_display_get_n_screens
gdk_display_get_screen
-gdk_display_pointer_is_grabbed
gdk_display_pointer_ungrab
gdk_display_keyboard_ungrab
gdk_display_open
gdk_window_set_cursor
gdk_window_get_geometry
gdk_window_get_origin
+gdk_window_get_deskrelative_origin
gdk_window_shape_combine_mask
gdk_window_shape_combine_region
gdk_window_set_child_shapes
gdk_window_merge_child_shapes
+gdk_window_input_shape_combine_mask
+gdk_window_input_shape_combine_region
+gdk_window_set_child_input_shapes
+gdk_window_merge_child_input_shapes
gdk_window_set_static_gravities
gdk_window_reparent
gdk_window_add_filter
gdk_window_thaw_toplevel_updates_libgtk_only
gdk_window_thaw_updates
gdk_window_set_composited
+gdk_pointer_grab
+gdk_window_beep
+#endif
+#endif
+
+#if IN_HEADER(__GDK_WINDOW_H__)
+#if IN_FILE(__GDK_OFFSCREEN_WINDOW_C__)
+gdk_window_get_offscreen_pixmap
#endif
#endif
gdk_window_lookup_for_display
#ifndef GDK_DISABLE_DEPRECATED
gdk_window_set_hints
-gdk_window_get_deskrelative_origin
#endif
gdk_window_get_type_hint
gdk_window_set_type_hint
gdk_window_set_transient_for
gdk_window_get_root_origin
gdk_window_get_frame_extents
-gdk_window_input_shape_combine_mask
-gdk_window_input_shape_combine_region
gdk_window_set_override_redirect
gdk_window_set_accept_focus
gdk_window_set_focus_on_map
gdk_window_set_icon_list
gdk_window_set_icon
gdk_window_set_icon_name
-gdk_window_beep
gdk_window_set_opacity
gdk_window_iconify
gdk_window_deiconify
gdk_window_get_decorations
gdk_window_set_decorations
gdk_window_set_functions
-gdk_window_set_child_input_shapes
-gdk_window_merge_child_input_shapes
gdk_window_begin_move_drag
gdk_window_begin_resize_drag
gdk_window_enable_synchronized_configure
#if IN_HEADER(__GDK_PIXMAP_H__)
#if IN_FILE(__GDK_PIXMAP_C__)
+gdk_bitmap_create_from_data
gdk_pixmap_colormap_create_from_xpm
+gdk_pixmap_create_from_data
gdk_pixmap_create_from_xpm
gdk_pixmap_colormap_create_from_xpm_d
gdk_pixmap_create_from_xpm_d
gdk_pixmap_get_type G_GNUC_CONST
+gdk_pixmap_new
#endif
#endif
#if IN_HEADER(__GDK_PIXMAP_H__)
#if IN_FILE(__GDK_PIXMAP_X11_C__)
-gdk_pixmap_create_from_data
gdk_pixmap_foreign_new
gdk_pixmap_foreign_new_for_display
gdk_pixmap_foreign_new_for_screen
gdk_pixmap_lookup
gdk_pixmap_lookup_for_display
-gdk_pixmap_new
#endif
#endif
surface = _gdk_drawable_ref_cairo_surface (drawable);
cr = cairo_create (surface);
+
+ if (GDK_DRAWABLE_GET_CLASS (drawable)->set_cairo_clip)
+ GDK_DRAWABLE_GET_CLASS (drawable)->set_cairo_clip (drawable, cr);
+
cairo_surface_destroy (surface);
return cr;
*/
#include "config.h"
+#include <math.h>
#include <glib.h>
#include "gdk.h" /* gdk_event_send_client_message() */
#include "gdkdisplay.h"
+#include "gdkwindowimpl.h"
#include "gdkinternals.h"
#include "gdkmarshalers.h"
#include "gdkscreen.h"
static GdkWindow* singlehead_default_window_at_pointer (GdkScreen *screen,
gint *win_x,
gint *win_y);
+static GdkWindow *gdk_window_real_window_get_pointer (GdkDisplay *display,
+ GdkWindow *window,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask);
+static GdkWindow *gdk_display_real_get_window_at_pointer (GdkDisplay *display,
+ gint *win_x,
+ gint *win_y);
static guint signals[LAST_SIGNAL] = { 0 };
static const GdkDisplayPointerHooks default_pointer_hooks = {
_gdk_windowing_get_pointer,
- _gdk_windowing_window_get_pointer,
- _gdk_windowing_window_at_pointer
+ gdk_window_real_window_get_pointer,
+ gdk_display_real_get_window_at_pointer
};
static const GdkDisplayPointerHooks singlehead_pointer_hooks = {
return gdk_sm_client_id;
}
+void
+_gdk_display_enable_motion_hints (GdkDisplay *display)
+{
+ gulong serial;
+
+ if (display->pointer_info.motion_hint_serial != 0)
+ {
+ serial = _gdk_windowing_window_get_next_serial (display);
+ /* We might not actually generate the next request, so
+ make sure this triggers always, this may cause it to
+ trigger slightly to early, but this is just a hint
+ anyway. */
+ if (serial > 0)
+ serial--;
+ if (serial < display->pointer_info.motion_hint_serial)
+ display->pointer_info.motion_hint_serial = serial;
+ }
+}
+
/**
* gdk_display_get_pointer:
* @display: a #GdkDisplay
*mask = tmp_mask;
}
+static GdkWindow *
+gdk_display_real_get_window_at_pointer (GdkDisplay *display,
+ gint *win_x,
+ gint *win_y)
+{
+ GdkWindow *window;
+ gint x, y;
+
+ window = _gdk_windowing_window_at_pointer (display, &x, &y, NULL);
+
+ /* This might need corrections, as the native window returned
+ may contain client side children */
+ if (window)
+ {
+ double xx, yy;
+
+ window = _gdk_window_find_descendant_at (window,
+ x, y,
+ &xx, &yy);
+ x = floor (xx + 0.5);
+ y = floor (yy + 0.5);
+ }
+
+ *win_x = x;
+ *win_y = y;
+
+ return window;
+}
+
+static GdkWindow *
+gdk_window_real_window_get_pointer (GdkDisplay *display,
+ GdkWindow *window,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask)
+{
+ GdkWindowObject *private;
+ gint tmpx, tmpy;
+ GdkModifierType tmp_mask;
+ gboolean normal_child;
+
+ private = (GdkWindowObject *) window;
+
+ normal_child = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_pointer (window,
+ &tmpx, &tmpy,
+ &tmp_mask);
+ /* We got the coords on the impl, conver to the window */
+ tmpx -= private->abs_x;
+ tmpy -= private->abs_y;
+
+ if (x)
+ *x = tmpx;
+ if (y)
+ *y = tmpy;
+ if (mask)
+ *mask = tmp_mask;
+
+ if (normal_child)
+ return _gdk_window_find_child_at (window, tmpx, tmpy);
+ return NULL;
+}
+
/**
* gdk_display_get_window_at_pointer:
* @display: a #GdkDisplay
gint *y,
GdkModifierType *mask)
{
- return _gdk_windowing_window_get_pointer (gdk_drawable_get_display (window),
- window, x, y, mask);
+ return gdk_window_real_window_get_pointer (gdk_drawable_get_display (window),
+ window, x, y, mask);
}
static GdkWindow*
gint *win_x,
gint *win_y)
{
- return _gdk_windowing_window_at_pointer (gdk_screen_get_display (screen),
- win_x, win_y);
+ return gdk_display_real_get_window_at_pointer (gdk_screen_get_display (screen),
+ win_x, win_y);
}
/**
return (GdkPointerHooks *)result;
}
+static void
+generate_grab_broken_event (GdkWindow *window,
+ gboolean keyboard,
+ gboolean implicit,
+ GdkWindow *grab_window)
+{
+ g_return_if_fail (window != NULL);
+
+ if (!GDK_WINDOW_DESTROYED (window))
+ {
+ GdkEvent event;
+ event.type = GDK_GRAB_BROKEN;
+ event.grab_broken.window = window;
+ event.grab_broken.send_event = 0;
+ event.grab_broken.keyboard = keyboard;
+ event.grab_broken.implicit = implicit;
+ event.grab_broken.grab_window = grab_window;
+ gdk_event_put (&event);
+ }
+}
+
+GdkPointerGrabInfo *
+_gdk_display_get_last_pointer_grab (GdkDisplay *display)
+{
+ GList *l;
+
+ l = display->pointer_grabs;
+
+ if (l == NULL)
+ return NULL;
+
+ while (l->next != NULL)
+ l = l->next;
+
+ return (GdkPointerGrabInfo *)l->data;
+}
+
+
+GdkPointerGrabInfo *
+_gdk_display_add_pointer_grab (GdkDisplay *display,
+ GdkWindow *window,
+ GdkWindow *native_window,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ unsigned long serial_start,
+ guint32 time,
+ gboolean implicit)
+{
+ GdkPointerGrabInfo *info, *other_info;
+ GList *l;
+
+ info = g_new0 (GdkPointerGrabInfo, 1);
+
+ info->window = g_object_ref (window);
+ info->native_window = g_object_ref (native_window);
+ info->serial_start = serial_start;
+ info->serial_end = G_MAXULONG;
+ info->owner_events = owner_events;
+ info->event_mask = event_mask;
+ info->time = time;
+ info->implicit = implicit;
+
+ /* Find the first grab that has a larger start time (if any) and insert
+ * before that. I.E we insert after already existing grabs with same
+ * start time */
+ for (l = display->pointer_grabs; l != NULL; l = l->next)
+ {
+ other_info = l->data;
+
+ if (info->serial_start < other_info->serial_start)
+ break;
+ }
+ display->pointer_grabs =
+ g_list_insert_before (display->pointer_grabs, l, info);
+
+ /* Make sure the new grab end before next grab */
+ if (l)
+ {
+ other_info = l->data;
+ info->serial_end = other_info->serial_start;
+ }
+
+ /* Find any previous grab and update its end time */
+ l = g_list_find (display->pointer_grabs, info);
+ l = l->prev;
+ if (l)
+ {
+ other_info = l->data;
+ other_info->serial_end = serial_start;
+ }
+
+ return info;
+}
+
+static void
+free_pointer_grab (GdkPointerGrabInfo *info)
+{
+ g_object_unref (info->window);
+ g_object_unref (info->native_window);
+ g_free (info);
+}
+
+/* _gdk_syntesize_crossing_events only works inside one toplevel.
+ This function splits things into two calls if needed, converting the
+ coordinates to the right toplevel */
+static void
+synthesize_crossing_events (GdkDisplay *display,
+ GdkWindow *src_window,
+ GdkWindow *dest_window,
+ GdkCrossingMode crossing_mode,
+ guint32 time,
+ gulong serial)
+{
+ GdkWindow *src_toplevel, *dest_toplevel;
+ GdkModifierType state;
+ int x, y;
+
+ if (src_window)
+ src_toplevel = gdk_window_get_toplevel (src_window);
+ else
+ src_toplevel = NULL;
+ if (dest_window)
+ dest_toplevel = gdk_window_get_toplevel (dest_window);
+ else
+ dest_toplevel = NULL;
+
+ if (src_toplevel == NULL && dest_toplevel == NULL)
+ return;
+
+ if (src_toplevel == NULL ||
+ src_toplevel == dest_toplevel)
+ {
+ /* Same toplevels */
+ gdk_window_get_pointer (dest_toplevel,
+ &x, &y, &state);
+ _gdk_syntesize_crossing_events (display,
+ src_window,
+ dest_window,
+ crossing_mode,
+ x, y, state,
+ time,
+ NULL,
+ serial);
+ }
+ else if (dest_toplevel == NULL)
+ {
+ gdk_window_get_pointer (src_toplevel,
+ &x, &y, &state);
+ _gdk_syntesize_crossing_events (display,
+ src_window,
+ NULL,
+ crossing_mode,
+ x, y, state,
+ time,
+ NULL,
+ serial);
+ }
+ else
+ {
+ /* Different toplevels */
+ gdk_window_get_pointer (src_toplevel,
+ &x, &y, &state);
+ _gdk_syntesize_crossing_events (display,
+ src_window,
+ NULL,
+ crossing_mode,
+ x, y, state,
+ time,
+ NULL,
+ serial);
+ gdk_window_get_pointer (dest_toplevel,
+ &x, &y, &state);
+ _gdk_syntesize_crossing_events (display,
+ NULL,
+ dest_window,
+ crossing_mode,
+ x, y, state,
+ time,
+ NULL,
+ serial);
+ }
+}
+
+static void
+switch_to_pointer_grab (GdkDisplay *display,
+ GdkPointerGrabInfo *grab,
+ GdkPointerGrabInfo *last_grab,
+ guint32 time,
+ gulong serial)
+{
+ GdkWindow *src_window, *pointer_window;
+ GdkWindowObject *w;
+ GList *old_grabs;
+ GdkModifierType state;
+ int x, y;
+
+ /* Temporarily unset pointer to make sure we send the crossing events below */
+ old_grabs = display->pointer_grabs;
+ display->pointer_grabs = NULL;
+
+ if (grab)
+ {
+ /* New grab is in effect */
+
+ /* We need to generate crossing events for the grab.
+ * However, there are never any crossing events for implicit grabs
+ * TODO: ... Actually, this could happen if the pointer window
+ * doesn't have button mask so a parent gets the event...
+ */
+ if (!grab->implicit)
+ {
+ /* We send GRAB crossing events from the window under the pointer to the
+ grab window. Except if there is an old grab then we start from that */
+ if (last_grab)
+ src_window = last_grab->window;
+ else
+ src_window = display->pointer_info.window_under_pointer;
+
+ if (src_window != grab->window)
+ {
+ synthesize_crossing_events (display,
+ src_window, grab->window,
+ GDK_CROSSING_GRAB, time, serial);
+ }
+
+ /* !owner_event Grabbing a window that we're not inside, current status is
+ now NULL (i.e. outside grabbed window) */
+ if (!grab->owner_events && display->pointer_info.window_under_pointer != grab->window)
+ _gdk_display_set_window_under_pointer (display, NULL);
+ }
+
+ grab->activated = TRUE;
+ }
+ else if (last_grab)
+ {
+ pointer_window = _gdk_windowing_window_at_pointer (display, &x, &y, &state);
+ if (pointer_window != NULL &&
+ (GDK_WINDOW_DESTROYED (pointer_window) ||
+ GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
+ GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
+ pointer_window = NULL;
+
+ /* We force checked what window we're in, so we need to
+ * update the toplevel_under_pointer info, as that won't get told of
+ * this change.
+ */
+ if (display->pointer_info.toplevel_under_pointer)
+ g_object_unref (display->pointer_info.toplevel_under_pointer);
+ display->pointer_info.toplevel_under_pointer = NULL;
+
+ if (pointer_window)
+ {
+ /* Convert to toplevel */
+ w = (GdkWindowObject *)pointer_window;
+ while (/*w->parent != NULL && */
+ w->parent->window_type != GDK_WINDOW_ROOT)
+ {
+ x += w->x;
+ y += w->y;
+ w = w->parent;
+ }
+
+ /* w is now toplevel and x,y in toplevel coords */
+ display->pointer_info.toplevel_under_pointer = g_object_ref (w);
+
+ /* Find (possibly virtual) child window */
+ pointer_window =
+ _gdk_window_find_descendant_at ((GdkWindow *)w,
+ x, y,
+ NULL, NULL);
+ }
+
+ if (pointer_window != last_grab->window)
+ synthesize_crossing_events (display,
+ last_grab->window, pointer_window,
+ GDK_CROSSING_UNGRAB, time, serial);
+
+ /* We're now ungrabbed, update the window_under_pointer */
+ _gdk_display_set_window_under_pointer (display, pointer_window);
+
+ if (last_grab->implicit_ungrab)
+ generate_grab_broken_event (last_grab->window,
+ FALSE, TRUE,
+ NULL);
+ }
+
+ display->pointer_grabs = old_grabs;
+
+}
+
+void
+_gdk_display_pointer_grab_update (GdkDisplay *display,
+ gulong current_serial)
+{
+ GdkPointerGrabInfo *current_grab, *next_grab;
+ guint32 time;
+
+ time = display->last_event_time;
+
+ while (display->pointer_grabs != NULL)
+ {
+ current_grab = display->pointer_grabs->data;
+
+ if (current_grab->serial_start > current_serial)
+ return; /* Hasn't started yet */
+
+ if (current_grab->serial_end > current_serial ||
+ (current_grab->serial_end == current_serial &&
+ current_grab->grab_one_pointer_release_event))
+ {
+ /* This one hasn't ended yet.
+ its the currently active one or scheduled to be active */
+
+ if (!current_grab->activated)
+ switch_to_pointer_grab (display, current_grab, NULL, time, current_serial);
+
+ break;
+ }
+
+
+ next_grab = NULL;
+ if (display->pointer_grabs->next)
+ {
+ /* This is the next active grab */
+ next_grab = display->pointer_grabs->next->data;
+
+ if (next_grab->serial_start > current_serial)
+ next_grab = NULL; /* Actually its not yet active */
+ }
+
+ if (next_grab == NULL ||
+ current_grab->window != next_grab->window)
+ generate_grab_broken_event (GDK_WINDOW (current_grab->window),
+ FALSE, current_grab->implicit,
+ next_grab? next_grab->window : NULL);
+
+
+ /* Remove old grab */
+ display->pointer_grabs =
+ g_list_delete_link (display->pointer_grabs,
+ display->pointer_grabs);
+
+ switch_to_pointer_grab (display,
+ next_grab, current_grab,
+ time, current_serial);
+
+ free_pointer_grab (current_grab);
+ }
+}
+
+static GdkWindow *
+gdk_window_get_offscreen_parent (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindow *res;
+
+ res = NULL;
+ g_signal_emit_by_name (private->impl_window,
+ "get-offscreen-parent",
+ &res);
+
+ return res;
+}
+
+/* Gets the toplevel for a window as used for events,
+ i.e. including offscreen parents */
+static GdkWindowObject *
+get_event_parent (GdkWindowObject *window)
+{
+ if (window->window_type ==GDK_WINDOW_OFFSCREEN)
+ return (GdkWindowObject *)gdk_window_get_offscreen_parent ((GdkWindow *)window);
+ else
+ return window->parent;
+}
+
+is_event_parent_of (GdkWindow *parent,
+ GdkWindow *child)
+{
+ GdkWindow *w;
+
+ w = child;
+ while (w != NULL)
+ {
+ if (w == parent)
+ return TRUE;
+
+ w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
+ }
+
+ return FALSE;
+}
+
+static GList *
+find_pointer_grab (GdkDisplay *display,
+ gulong serial)
+{
+ GdkPointerGrabInfo *grab;
+ GList *l;
+
+ for (l = display->pointer_grabs; l != NULL; l = l->next)
+ {
+ grab = l->data;
+
+ if (serial >= grab->serial_start && serial < grab->serial_end)
+ return l;
+ }
+
+ return NULL;
+}
+
+
+
+GdkPointerGrabInfo *
+_gdk_display_has_pointer_grab (GdkDisplay *display,
+ gulong serial)
+{
+ GList *l;
+
+ l = find_pointer_grab (display, serial);
+ if (l)
+ return l->data;
+
+ return NULL;
+}
+
+/* Returns true if last grab was ended */
+gboolean
+_gdk_display_end_pointer_grab (GdkDisplay *display,
+ gulong serial,
+ GdkWindow *if_child,
+ gboolean implicit)
+{
+ GdkPointerGrabInfo *grab;
+ GList *l;
+
+ l = find_pointer_grab (display, serial);
+
+ if (l == NULL)
+ return FALSE;
+
+ grab = l->data;
+ if (grab &&
+ (if_child == NULL ||
+ is_event_parent_of (grab->window, if_child)))
+ {
+ grab->serial_end = serial;
+ grab->implicit_ungrab = implicit;
+ return l->next == NULL;
+ }
+
+ return FALSE;
+}
+
+void
+_gdk_display_set_has_keyboard_grab (GdkDisplay *display,
+ GdkWindow *window,
+ GdkWindow *native_window,
+ gboolean owner_events,
+ unsigned long serial,
+ guint32 time)
+{
+ if (display->keyboard_grab.window != NULL &&
+ display->keyboard_grab.window != window)
+ generate_grab_broken_event (display->keyboard_grab.window,
+ TRUE, FALSE, window);
+
+ display->keyboard_grab.window = window;
+ display->keyboard_grab.native_window = native_window;
+ display->keyboard_grab.owner_events = owner_events;
+ display->keyboard_grab.serial = serial;
+ display->keyboard_grab.time = time;
+}
+
+void
+_gdk_display_unset_has_keyboard_grab (GdkDisplay *display,
+ gboolean implicit)
+{
+ if (implicit)
+ generate_grab_broken_event (display->keyboard_grab.window,
+ TRUE, FALSE, NULL);
+ display->keyboard_grab.window = NULL;
+}
+
+/**
+ * gdk_keyboard_grab_info_libgtk_only:
+ * @display: the display for which to get the grab information
+ * @grab_window: location to store current grab window
+ * @owner_events: location to store boolean indicating whether
+ * the @owner_events flag to gdk_keyboard_grab() was %TRUE.
+ *
+ * Determines information about the current keyboard grab.
+ * This is not public API and must not be used by applications.
+ *
+ * Return value: %TRUE if this application currently has the
+ * keyboard grabbed.
+ **/
+gboolean
+gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
+ GdkWindow **grab_window,
+ gboolean *owner_events)
+{
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+ if (display->keyboard_grab.window)
+ {
+ if (grab_window)
+ *grab_window = display->keyboard_grab.window;
+ if (owner_events)
+ *owner_events = display->keyboard_grab.owner_events;
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/**
+ * gdk_pointer_grab_info_libgtk_only:
+ * @display: the #GdkDisplay for which to get the grab information
+ * @grab_window: location to store current grab window
+ * @owner_events: location to store boolean indicating whether
+ * the @owner_events flag to gdk_pointer_grab() was %TRUE.
+ *
+ * Determines information about the current pointer grab.
+ * This is not public API and must not be used by applications.
+ *
+ * Return value: %TRUE if this application currently has the
+ * pointer grabbed.
+ **/
+gboolean
+gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
+ GdkWindow **grab_window,
+ gboolean *owner_events)
+{
+ GdkPointerGrabInfo *info;
+
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+ /* What we're interested in is the steady state (ie last grab),
+ because we're interested e.g. if we grabbed so that we
+ can ungrab, even if our grab is not active just yet. */
+ info = _gdk_display_get_last_pointer_grab (display);
+
+ if (info)
+ {
+ if (grab_window)
+ *grab_window = info->window;
+ if (owner_events)
+ *owner_events = info->owner_events;
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+
+/**
+ * gdk_display_pointer_is_grabbed:
+ * @display: a #GdkDisplay
+ *
+ * Test if the pointer is grabbed.
+ *
+ * Returns: %TRUE if an active X pointer grab is in effect
+ *
+ * Since: 2.2
+ */
+gboolean
+gdk_display_pointer_is_grabbed (GdkDisplay *display)
+{
+ GdkPointerGrabInfo *info;
+
+ g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
+
+ /* What we're interested in is the steady state (ie last grab),
+ because we're interested e.g. if we grabbed so that we
+ can ungrab, even if our grab is not active just yet. */
+ info = _gdk_display_get_last_pointer_grab (display);
+
+ return (info && !info->implicit);
+}
+
#define __GDK_DISPLAY_C__
#include "gdkaliasdef.c"
#define GDK_IS_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DISPLAY))
#define GDK_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DISPLAY, GdkDisplayClass))
+/* Tracks information about the keyboard grab on this display */
+typedef struct
+{
+ GdkWindow *window;
+ GdkWindow *native_window;
+ gulong serial;
+ gboolean owner_events;
+ guint32 time;
+} GdkKeyboardGrabInfo;
+
+/* Tracks information about which window and position the pointer last was in.
+ * This is useful when we need to synthesize events later.
+ * Note that we track toplevel_under_pointer using enter/leave events,
+ * so in the case of a grab, either with owner_events==FALSE or with the
+ * pointer in no clients window the x/y coordinates may actually be outside
+ * the window.
+ */
+typedef struct
+{
+ GdkWindow *toplevel_under_pointer; /* The toplevel window with mouse inside, tracked via native events */
+ GdkWindow *window_under_pointer; /* The window that last got sent a normal enter event */
+ gdouble toplevel_x, toplevel_y;
+ guint32 state;
+ guint32 button;
+ gulong motion_hint_serial; /* 0 == didn't deliver hinted motion event */
+} GdkPointerWindowInfo;
+
struct _GdkDisplay
{
GObject parent_instance;
const GdkDisplayPointerHooks *pointer_hooks; /* Current hooks for querying pointer */
guint closed : 1; /* Whether this display has been closed */
+ guint ignore_core_events : 1; /* Don't send core motion and button event */
guint double_click_distance; /* Maximum distance between clicks in pixels */
gint button_x[2]; /* The last 2 button click positions. */
gint button_y[2];
+
+ GList *pointer_grabs;
+ GdkKeyboardGrabInfo keyboard_grab;
+ GdkPointerWindowInfo pointer_info;
+
+ /* Last reported event time from server */
+ guint32 last_event_time;
};
struct _GdkDisplayClass
{
g_return_if_fail (GDK_IS_DRAWABLE (drawable));
- GDK_DRAWABLE_GET_CLASS (drawable)->get_size (drawable, width, height);
+ if (GDK_DRAWABLE_GET_CLASS (drawable)->get_size != NULL)
+ GDK_DRAWABLE_GET_CLASS (drawable)->get_size (drawable, width, height);
}
/**
gint width,
gint height)
{
- GdkDrawable *composite;
+ GdkDrawable *composite, *composite_impl;
gint composite_x_offset = 0;
gint composite_y_offset = 0;
&composite_x_offset,
&composite_y_offset);
-
- GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc, composite,
+ /* The draw_drawable call below is will recurse into gdk_draw_drawable again,
+ * specifying the right impl for the destination. This means the composite
+ * we got here will be fed to get_composite_drawable again, which is a problem
+ * for window as that causes double the composite offset. Avoid this by passing
+ * in the impl directly.
+ */
+ if (GDK_IS_WINDOW (composite))
+ composite_impl = GDK_WINDOW_OBJECT (src)->impl;
+ else
+ composite_impl = composite;
+
+ /* TODO: For non-native windows this may copy stuff from other overlapping
+ windows. We should clip that and (for windows with bg != None) clear that
+ area in the destination instead. */
+
+ GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc,
+ composite_impl, src,
xsrc - composite_x_offset,
ysrc - composite_y_offset,
xdest, ydest,
width, height);
-
+
g_object_unref (composite);
}
cairo_t *cr;
cr = gdk_cairo_create (drawable);
- _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE);
+ _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE, drawable);
if (matrix)
{
g_return_if_fail (n_trapezoids == 0 || trapezoids != NULL);
cr = gdk_cairo_create (drawable);
- _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE);
+ _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE, drawable);
for (i = 0; i < n_trapezoids; i++)
{
return gdk_drawable_copy_to_image (drawable, NULL, x, y, 0, 0, width, height);
}
-static GdkDrawable*
+static GdkDrawable *
gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
gint x,
gint y,
}
}
+/**
+ * _gdk_drawable_get_subwindow_scratch_gc:
+ * @drawable: A #GdkDrawable
+ *
+ * Returns a #GdkGC suitable for drawing on @drawable. The #GdkGC has
+ * the standard values for @drawable, except for the graphics_exposures
+ * field which is %TRUE and the subwindow mode which is %GDK_INCLUDE_INFERIORS.
+ *
+ * The foreground color of the returned #GdkGC is undefined. The #GdkGC
+ * must not be altered in any way, except to change its foreground color.
+ *
+ * Return value: A #GdkGC suitable for drawing on @drawable
+ *
+ * Since: 2.18
+ **/
+GdkGC *
+_gdk_drawable_get_subwindow_scratch_gc (GdkDrawable *drawable)
+{
+ GdkScreen *screen;
+ gint depth;
+
+ g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
+
+ screen = gdk_drawable_get_screen (drawable);
+
+ g_return_val_if_fail (!screen->closed, NULL);
+
+ depth = gdk_drawable_get_depth (drawable) - 1;
+
+ if (!screen->subwindow_gcs[depth])
+ {
+ GdkGCValues values;
+ GdkGCValuesMask mask;
+
+ values.graphics_exposures = TRUE;
+ values.subwindow_mode = GDK_INCLUDE_INFERIORS;
+ mask = GDK_GC_EXPOSURES | GDK_GC_SUBWINDOW;
+
+ screen->subwindow_gcs[depth] =
+ gdk_gc_new_with_values (drawable, &values, mask);
+ }
+
+ return screen->subwindow_gcs[depth];
+}
+
+
+/**
+ * _gdk_drawable_get_source_drawable:
+ * @drawable: a #GdkDrawable
+ *
+ * Returns a drawable for the passed @drawable that is guaranteed to be
+ * usable to create a pixmap (e.g.: not an offscreen window).
+ *
+ * Since: 2.16
+ */
+GdkDrawable *
+_gdk_drawable_get_source_drawable (GdkDrawable *drawable)
+{
+ g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
+
+ if (GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable)
+ return GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable (drawable);
+
+ return drawable;
+}
+
+cairo_surface_t *
+_gdk_drawable_create_cairo_surface (GdkDrawable *drawable,
+ int width,
+ int height)
+{
+ return GDK_DRAWABLE_GET_CLASS (drawable)->create_cairo_surface (drawable,
+ width, height);
+}
+
+
#define __GDK_DRAW_C__
#include "gdkaliasdef.c"
void (*draw_drawable) (GdkDrawable *drawable,
GdkGC *gc,
GdkDrawable *src,
+ GdkDrawable *original_src,
gint xsrc,
gint ysrc,
gint xdest,
cairo_surface_t *(*ref_cairo_surface) (GdkDrawable *drawable);
+ GdkDrawable *(*get_source_drawable) (GdkDrawable *drawable);
+
+ void (*set_cairo_clip) (GdkDrawable *drawable,
+ cairo_t *cr);
+
+ cairo_surface_t * (*create_cairo_surface) (GdkDrawable *drawable,
+ int width,
+ int height);
+
/* Padding for future expansion */
- void (*_gdk_reserved4) (void);
- void (*_gdk_reserved5) (void);
- void (*_gdk_reserved6) (void);
void (*_gdk_reserved7) (void);
void (*_gdk_reserved9) (void);
void (*_gdk_reserved10) (void);
return display->queued_tail;
}
+/**
+ * _gdk_event_queue_insert_after:
+ * @display: a #GdkDisplay
+ * @sibling: Append after this event.
+ * @event: Event to append.
+ *
+ * Appends an event after the specified event, or if it isn't in
+ * the queue, onto the tail of the event queue.
+ *
+ * Returns: the newly appended list node.
+ *
+ * Since: 2.16
+ */
+GList*
+_gdk_event_queue_insert_after (GdkDisplay *display,
+ GdkEvent *sibling,
+ GdkEvent *event)
+{
+ GList *prev = g_list_find (display->queued_events, sibling);
+ if (prev && prev->next)
+ {
+ display->queued_events = g_list_insert_before (display->queued_events, prev->next, event);
+ return prev->next;
+ }
+ else
+ return _gdk_event_queue_append (display, event);
+}
+
+/**
+ * _gdk_event_queue_insert_after:
+ * @display: a #GdkDisplay
+ * @sibling: Append after this event.
+ * @event: Event to append.
+ *
+ * Appends an event before the specified event, or if it isn't in
+ * the queue, onto the tail of the event queue.
+ *
+ * Returns: the newly appended list node.
+ *
+ * Since: 2.16
+ */
+GList*
+_gdk_event_queue_insert_before (GdkDisplay *display,
+ GdkEvent *sibling,
+ GdkEvent *event)
+{
+ GList *next = g_list_find (display->queued_events, sibling);
+ if (next)
+ {
+ display->queued_events = g_list_insert_before (display->queued_events, next, event);
+ return next->prev;
+ }
+ else
+ return _gdk_event_queue_append (display, event);
+}
+
+
/**
* _gdk_event_queue_remove_link:
* @display: a #GdkDisplay
case GDK_SETTING:
case GDK_OWNER_CHANGE:
case GDK_GRAB_BROKEN:
+ case GDK_EVENT_LAST:
/* return current time */
break;
}
case GDK_SETTING:
case GDK_OWNER_CHANGE:
case GDK_GRAB_BROKEN:
+ case GDK_EVENT_LAST:
/* no state field */
break;
}
void
gdk_event_request_motions (const GdkEventMotion *event)
{
+ GdkDisplay *display;
+
g_return_if_fail (event != NULL);
+
if (event->type == GDK_MOTION_NOTIFY && event->is_hint)
- gdk_device_get_state (event->device, event->window, NULL, NULL);
+ {
+ gdk_device_get_state (event->device, event->window, NULL, NULL);
+
+ display = gdk_drawable_get_display (event->window);
+ _gdk_display_enable_motion_hints (display);
+ }
}
/**
gint nclicks)
{
GdkEvent temp_event;
+ GdkEvent *event_copy;
+ GList *link;
g_return_if_fail (event != NULL);
temp_event = *event;
temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
-
- gdk_display_put_event (display, &temp_event);
+
+ event_copy = gdk_event_copy (&temp_event);
+ link = _gdk_event_queue_append (display, event_copy);
}
void
GDK_SETTING = 33,
GDK_OWNER_CHANGE = 34,
GDK_GRAB_BROKEN = 35,
- GDK_DAMAGE = 36
+ GDK_DAMAGE = 36,
+ GDK_EVENT_LAST /* helper variable for decls */
} GdkEventType;
/* Event masks. (Used to select what types of events a window
{
GdkRegion *clip_region;
- GdkFill fill;
+ guint32 region_tag_applied;
+ int region_tag_offset_x;
+ int region_tag_offset_y;
+
+ GdkRegion *old_clip_region;
+ GdkPixmap *old_clip_mask;
+
GdkBitmap *stipple;
GdkPixmap *tile;
-
+
+ GdkPixmap *clip_mask;
+
guint32 fg_pixel;
guint32 bg_pixel;
+
+ guint subwindow_mode : 1;
+ guint fill : 2;
+ guint exposures : 2;
};
#define GDK_GC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDK_TYPE_GC, GdkGCPrivate))
gc->clip_x_origin = values->clip_x_origin;
if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
gc->clip_y_origin = values->clip_y_origin;
+ if ((values_mask & GDK_GC_CLIP_MASK) && values->clip_mask)
+ priv->clip_mask = g_object_ref (values->clip_mask);
if (values_mask & GDK_GC_TS_X_ORIGIN)
gc->ts_x_origin = values->ts_x_origin;
if (values_mask & GDK_GC_TS_Y_ORIGIN)
priv->fg_pixel = values->foreground.pixel;
if (values_mask & GDK_GC_BACKGROUND)
priv->bg_pixel = values->background.pixel;
+ if (values_mask & GDK_GC_SUBWINDOW)
+ priv->subwindow_mode = values->subwindow_mode;
+ if (values_mask & GDK_GC_EXPOSURES)
+ priv->exposures = values->graphics_exposures;
+ else
+ priv->exposures = TRUE;
gc->colormap = gdk_drawable_get_colormap (drawable);
if (gc->colormap)
{
GdkGC *gc = GDK_GC (object);
GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
-
+
if (priv->clip_region)
gdk_region_destroy (priv->clip_region);
+ if (priv->old_clip_region)
+ gdk_region_destroy (priv->old_clip_region);
+ if (priv->clip_mask)
+ g_object_unref (priv->clip_mask);
+ if (priv->old_clip_mask)
+ g_object_unref (priv->old_clip_mask);
if (gc->colormap)
g_object_unref (gc->colormap);
if (priv->tile)
priv = GDK_GC_GET_PRIVATE (gc);
+ if ((values_mask & GDK_GC_CLIP_X_ORIGIN) ||
+ (values_mask & GDK_GC_CLIP_Y_ORIGIN) ||
+ (values_mask & GDK_GC_CLIP_MASK) ||
+ (values_mask & GDK_GC_SUBWINDOW))
+ _gdk_gc_remove_drawable_clip (gc);
+
if (values_mask & GDK_GC_CLIP_X_ORIGIN)
gc->clip_x_origin = values->clip_x_origin;
if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
gc->ts_y_origin = values->ts_y_origin;
if (values_mask & GDK_GC_CLIP_MASK)
{
+ if (priv->clip_mask)
+ {
+ g_object_unref (priv->clip_mask);
+ priv->clip_mask = NULL;
+ }
+ if (values->clip_mask)
+ priv->clip_mask = g_object_ref (values->clip_mask);
+
if (priv->clip_region)
{
gdk_region_destroy (priv->clip_region);
priv->fg_pixel = values->foreground.pixel;
if (values_mask & GDK_GC_BACKGROUND)
priv->bg_pixel = values->background.pixel;
+ if (values_mask & GDK_GC_SUBWINDOW)
+ priv->subwindow_mode = values->subwindow_mode;
+ if (values_mask & GDK_GC_EXPOSURES)
+ priv->exposures = values->graphics_exposures;
GDK_GC_GET_CLASS (gc)->set_values (gc, values, values_mask);
}
gdk_gc_set_values (gc, &values, GDK_GC_CLIP_MASK);
}
+/* Takes ownership of passed in region */
static void
-_gdk_gc_set_clip_region_internal (GdkGC *gc,
- GdkRegion *region)
+_gdk_gc_set_clip_region_real (GdkGC *gc,
+ GdkRegion *region,
+ gboolean reset_origin)
{
GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+ if (priv->clip_mask)
+ {
+ g_object_unref (priv->clip_mask);
+ priv->clip_mask = NULL;
+ }
+
if (priv->clip_region)
gdk_region_destroy (priv->clip_region);
priv->clip_region = region;
- _gdk_windowing_gc_set_clip_region (gc, region);
+ _gdk_windowing_gc_set_clip_region (gc, region, reset_origin);
+}
+
+/* Doesn't copy region, allows not to reset origin */
+void
+_gdk_gc_set_clip_region_internal (GdkGC *gc,
+ GdkRegion *region,
+ gboolean reset_origin)
+{
+ _gdk_gc_remove_drawable_clip (gc);
+ _gdk_gc_set_clip_region_real (gc, region, reset_origin);
+}
+
+
+/* returns old clip region */
+void
+_gdk_gc_add_drawable_clip (GdkGC *gc,
+ guint32 region_tag,
+ GdkRegion *region,
+ int offset_x,
+ int offset_y)
+{
+ GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+
+ if (priv->region_tag_applied == region_tag &&
+ offset_x == priv->region_tag_offset_x &&
+ offset_y == priv->region_tag_offset_y)
+ return; /* Already appied this drawable region */
+
+ if (priv->region_tag_applied)
+ _gdk_gc_remove_drawable_clip (gc);
+
+ region = gdk_region_copy (region);
+ if (offset_x != 0 || offset_y != 0)
+ gdk_region_offset (region, offset_x, offset_y);
+
+ if (priv->clip_mask)
+ {
+ int w, h;
+ GdkPixmap *new_mask;
+ GdkGC *tmp_gc;
+ GdkColor black = {0, 0, 0, 0};
+
+ priv->old_clip_mask = g_object_ref (priv->clip_mask);
+ gdk_drawable_get_size (priv->old_clip_mask, &w, &h);
+
+ new_mask = gdk_pixmap_new (priv->old_clip_mask, w, h, -1);
+ tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)new_mask, FALSE);
+
+ gdk_gc_set_foreground (tmp_gc, &black);
+ gdk_draw_rectangle (new_mask, tmp_gc, TRUE, 0, 0, -1, -1);
+ _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE); /* Takes ownership of region */
+ gdk_draw_drawable (new_mask,
+ tmp_gc,
+ priv->old_clip_mask,
+ 0, 0,
+ 0, 0,
+ -1, -1);
+ gdk_gc_set_clip_region (tmp_gc, NULL);
+ gdk_gc_set_clip_mask (gc, new_mask);
+ }
+ else
+ {
+ priv->old_clip_region = priv->clip_region;
+ priv->clip_region = region;
+ if (priv->old_clip_region)
+ gdk_region_intersect (region, priv->old_clip_region);
+
+ _gdk_windowing_gc_set_clip_region (gc, priv->clip_region, FALSE);
+ }
+
+ priv->region_tag_applied = region_tag;
+ priv->region_tag_offset_x = offset_x;
+ priv->region_tag_offset_y = offset_y;
+}
+
+void
+_gdk_gc_remove_drawable_clip (GdkGC *gc)
+{
+ GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+
+ if (priv->region_tag_applied)
+ {
+ priv->region_tag_applied = 0;
+ if (priv->old_clip_mask)
+ {
+ gdk_gc_set_clip_mask (gc, priv->old_clip_mask);
+ g_object_unref (priv->old_clip_mask);
+ priv->old_clip_mask = NULL;
+ }
+ else
+ {
+ _gdk_gc_set_clip_region_real (gc, priv->old_clip_region, FALSE);
+ priv->old_clip_region = NULL;
+ }
+ }
}
/**
g_return_if_fail (GDK_IS_GC (gc));
+ _gdk_gc_remove_drawable_clip (gc);
+
if (rectangle)
region = gdk_region_rectangle (rectangle);
else
region = NULL;
- _gdk_gc_set_clip_region_internal (gc, region);
+ _gdk_gc_set_clip_region_real (gc, region, TRUE);
}
/**
g_return_if_fail (GDK_IS_GC (gc));
+ _gdk_gc_remove_drawable_clip (gc);
+
if (region)
copy = gdk_region_copy (region);
else
copy = NULL;
- _gdk_gc_set_clip_region_internal (gc, copy);
+ _gdk_gc_set_clip_region_real (gc, copy, TRUE);
}
/**
return GDK_GC_GET_PRIVATE (gc)->fill;
}
+gboolean
+_gdk_gc_get_exposures (GdkGC *gc)
+{
+ g_return_val_if_fail (GDK_IS_GC (gc), FALSE);
+
+ return GDK_GC_GET_PRIVATE (gc)->exposures;
+}
+
/**
* _gdk_gc_get_tile:
* @gc: a #GdkGC
GdkSubwindowMode mode)
{
GdkGCValues values;
+ GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
g_return_if_fail (GDK_IS_GC (gc));
+ /* This could get called a lot to reset the subwindow mode in
+ the client side clipping, so bail out early */
+ if (priv->subwindow_mode == mode)
+ return;
+
values.subwindow_mode = mode;
gdk_gc_set_values (gc, &values, GDK_GC_SUBWINDOW);
}
+GdkSubwindowMode
+_gdk_gc_get_subwindow (GdkGC *gc)
+{
+ GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+
+ return priv->subwindow_mode;
+}
+
/**
* gdk_gc_set_exposures:
* @gc: a #GdkGC.
dst_priv->clip_region = gdk_region_copy (src_priv->clip_region);
else
dst_priv->clip_region = NULL;
+
+ dst_priv->region_tag_applied = src_priv->region_tag_applied;
+
+ if (dst_priv->old_clip_region)
+ gdk_region_destroy (dst_priv->old_clip_region);
+
+ if (src_priv->old_clip_region)
+ dst_priv->old_clip_region = gdk_region_copy (src_priv->old_clip_region);
+ else
+ dst_priv->old_clip_region = NULL;
+
+ if (src_priv->clip_mask)
+ dst_priv->clip_mask = g_object_ref (src_priv->clip_mask);
+ else
+ dst_priv->clip_mask = NULL;
+
+ if (src_priv->old_clip_mask)
+ dst_priv->old_clip_mask = g_object_ref (src_priv->old_clip_mask);
+ else
+ dst_priv->old_clip_mask = NULL;
dst_priv->fill = src_priv->fill;
dst_priv->fg_pixel = src_priv->fg_pixel;
dst_priv->bg_pixel = src_priv->bg_pixel;
+ dst_priv->subwindow_mode = src_priv->subwindow_mode;
+ dst_priv->exposures = src_priv->exposures;
}
/**
* the fill mode will be forced to %GDK_STIPPLED
* @gc_changed: pass %FALSE if the @gc has not changed since the
* last call to this function
+ * @target_drawable: The drawable you're drawing in. If passed in
+ * this is used for client side window clip emulation.
*
* Set the attributes of a cairo context to match those of a #GdkGC
* as far as possible. Some aspects of a #GdkGC, such as clip masks
cairo_t *cr,
const GdkColor *override_foreground,
GdkBitmap *override_stipple,
- gboolean gc_changed)
+ gboolean gc_changed,
+ GdkDrawable *target_drawable)
{
GdkGCPrivate *priv;
GdkFill fill;
cairo_clip (cr);
}
+
+ /* The reset above resets the window clip rect, so we want to re-set that */
+ if (target_drawable && GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip)
+ GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip (target_drawable, cr);
}
gpointer windowing_data;
};
+/* Tracks information about the pointer grab on this display */
+typedef struct
+{
+ GdkWindow *window;
+ GdkWindow *native_window;
+ gulong serial_start;
+ gulong serial_end; /* exclusive, i.e. not active on serial_end */
+ gboolean owner_events;
+ guint event_mask;
+ gboolean implicit;
+ guint32 time;
+
+ gboolean activated;
+ gboolean implicit_ungrab;
+ gboolean grab_one_pointer_release_event;
+} GdkPointerGrabInfo;
+
+typedef struct _GdkInputWindow GdkInputWindow;
+
+/* Private version of GdkWindowObject. The initial part of this strucuture
+ is public for historical reasons. Don't change that part */
+typedef struct _GdkWindowPaint GdkWindowPaint;
+
+struct _GdkWindowObject
+{
+ /* vvvvvvv THIS PART IS PUBLIC. DON'T CHANGE vvvvvvvvvvvvvv */
+ GdkDrawable parent_instance;
+
+ GdkDrawable *impl; /* window-system-specific delegate object */
+
+ GdkWindowObject *parent;
+
+ gpointer user_data;
+
+ gint x;
+ gint y;
+
+ gint extension_events;
+
+ GList *filters;
+ GList *children;
+
+ GdkColor bg_color;
+ GdkPixmap *bg_pixmap;
+
+ GSList *paint_stack;
+
+ GdkRegion *update_area;
+ guint update_freeze_count;
+
+ guint8 window_type;
+ guint8 depth;
+ guint8 resize_count;
+
+ GdkWindowState state;
+
+ guint guffaw_gravity : 1;
+ guint input_only : 1;
+ guint modal_hint : 1;
+ guint composited : 1;
+
+ guint destroyed : 2;
+
+ guint accept_focus : 1;
+ guint focus_on_map : 1;
+ guint shaped : 1;
+
+ GdkEventMask event_mask;
+
+ guint update_and_descendants_freeze_count;
+
+ GdkWindowRedirect *redirect;
+
+ /* ^^^^^^^^^^ THIS PART IS PUBLIC. DON'T CHANGE ^^^^^^^^^^ */
+
+ /* The GdkWindowObject that has the impl, ref:ed if another window.
+ * This ref is required to keep the wrapper of the impl window alive
+ * for as long as any GdkWindow references the impl. */
+ GdkWindowObject *impl_window;
+ int abs_x, abs_y; /* Absolute offset in impl */
+ gint width, height;
+ guint32 clip_tag;
+ GdkRegion *clip_region; /* Clip region (wrt toplevel) in window coords */
+ GdkRegion *clip_region_with_children; /* Clip region in window coords */
+ GdkCursor *cursor;
+ gint8 toplevel_window_type;
+ guint synthesize_crossing_event_queued : 1;
+ guint effective_visibility : 2;
+ guint visibility : 2; /* The visibility wrt the toplevel (i.e. based on clip_region) */
+ guint native_visibility : 2; /* the native visibility of a impl windows */
+ guint has_offscreen_children : 1;
+
+ GdkWindowPaint *implicit_paint;
+ GdkInputWindow *input_window; /* only set for impl windows */
+
+ GList *outstanding_moves;
+
+ GdkRegion *shape;
+ GdkRegion *input_shape;
+
+ cairo_surface_t *cairo_surface;
+};
+
+
extern GdkEventFunc _gdk_event_func; /* Callback for events */
extern gpointer _gdk_event_data;
extern GDestroyNotify _gdk_event_notify;
void _gdk_events_queue (GdkDisplay *display);
GdkEvent* _gdk_event_unqueue (GdkDisplay *display);
-GList* _gdk_event_queue_find_first (GdkDisplay *display);
-void _gdk_event_queue_remove_link (GdkDisplay *display,
- GList *node);
-GList* _gdk_event_queue_prepend (GdkDisplay *display,
- GdkEvent *event);
-GList* _gdk_event_queue_append (GdkDisplay *display,
- GdkEvent *event);
-void _gdk_event_button_generate (GdkDisplay *display,
- GdkEvent *event);
+GList* _gdk_event_queue_find_first (GdkDisplay *display);
+void _gdk_event_queue_remove_link (GdkDisplay *display,
+ GList *node);
+GList* _gdk_event_queue_prepend (GdkDisplay *display,
+ GdkEvent *event);
+GList* _gdk_event_queue_append (GdkDisplay *display,
+ GdkEvent *event);
+GList* _gdk_event_queue_insert_after (GdkDisplay *display,
+ GdkEvent *after_event,
+ GdkEvent *event);
+GList* _gdk_event_queue_insert_before(GdkDisplay *display,
+ GdkEvent *after_event,
+ GdkEvent *event);
+void _gdk_event_button_generate (GdkDisplay *display,
+ GdkEvent *event);
void _gdk_windowing_event_data_copy (const GdkEvent *src,
GdkEvent *dst);
cairo_surface_t *_gdk_drawable_ref_cairo_surface (GdkDrawable *drawable);
+GdkDrawable *_gdk_drawable_get_source_drawable (GdkDrawable *drawable);
+cairo_surface_t * _gdk_drawable_create_cairo_surface (GdkDrawable *drawable,
+ int width,
+ int height);
+
/* GC caching */
GdkGC *_gdk_drawable_get_scratch_gc (GdkDrawable *drawable,
gboolean graphics_exposures);
+GdkGC *_gdk_drawable_get_subwindow_scratch_gc (GdkDrawable *drawable);
void _gdk_gc_update_context (GdkGC *gc,
cairo_t *cr,
const GdkColor *override_foreground,
GdkBitmap *override_stipple,
- gboolean gc_changed);
+ gboolean gc_changed,
+ GdkDrawable *target_drawable);
/*************************************
* Interfaces used by windowing code *
*************************************/
-GdkWindow *_gdk_window_new (GdkWindow *window,
- GdkWindowAttr *attributes,
- gint attributes_mask);
-void _gdk_window_destroy (GdkWindow *window,
- gboolean foreign_destroy);
-void _gdk_window_clear_update_area (GdkWindow *window);
-
-void _gdk_screen_close (GdkScreen *screen);
+GdkPixmap *_gdk_pixmap_new (GdkDrawable *drawable,
+ gint width,
+ gint height,
+ gint depth);
+GdkPixmap *_gdk_pixmap_create_from_data (GdkDrawable *drawable,
+ const gchar *data,
+ gint width,
+ gint height,
+ gint depth,
+ const GdkColor *fg,
+ const GdkColor *bg);
+GdkPixmap *_gdk_bitmap_create_from_data (GdkDrawable *drawable,
+ const gchar *data,
+ gint width,
+ gint height);
+
+void _gdk_window_impl_new (GdkWindow *window,
+ GdkWindow *real_parent,
+ GdkScreen *screen,
+ GdkVisual *visual,
+ GdkEventMask event_mask,
+ GdkWindowAttr *attributes,
+ gint attributes_mask);
+void _gdk_window_destroy (GdkWindow *window,
+ gboolean foreign_destroy);
+void _gdk_window_clear_update_area (GdkWindow *window);
+void _gdk_window_update_size (GdkWindow *window);
+
+void _gdk_window_process_updates_recurse (GdkWindow *window,
+ GdkRegion *expose_region);
+
+void _gdk_screen_close (GdkScreen *screen);
const char *_gdk_get_sm_client_id (void);
GdkGCValuesMask values_mask);
GdkRegion *_gdk_gc_get_clip_region (GdkGC *gc);
+gboolean _gdk_gc_get_exposures (GdkGC *gc);
GdkFill _gdk_gc_get_fill (GdkGC *gc);
GdkPixmap *_gdk_gc_get_tile (GdkGC *gc);
GdkBitmap *_gdk_gc_get_stipple (GdkGC *gc);
guint32 _gdk_gc_get_fg_pixel (GdkGC *gc);
guint32 _gdk_gc_get_bg_pixel (GdkGC *gc);
+void _gdk_gc_add_drawable_clip (GdkGC *gc,
+ guint32 region_tag,
+ GdkRegion *region,
+ int offset_x,
+ int offset_y);
+void _gdk_gc_remove_drawable_clip (GdkGC *gc);
+void _gdk_gc_set_clip_region_internal (GdkGC *gc,
+ GdkRegion *region,
+ gboolean reset_origin);
+GdkSubwindowMode _gdk_gc_get_subwindow (GdkGC *gc);
/*****************************************
* Interfaces provided by windowing code *
gchar *_gdk_windowing_substitute_screen_number (const gchar *display_name,
gint screen_number);
+gulong _gdk_windowing_window_get_next_serial (GdkDisplay *display);
void _gdk_windowing_window_get_offsets (GdkWindow *window,
gint *x_offset,
gint *y_offset);
+GdkRegion *_gdk_windowing_window_get_shape (GdkWindow *window);
+GdkRegion *_gdk_windowing_window_get_input_shape(GdkWindow *window);
+GdkRegion *_gdk_windowing_get_shape_for_mask (GdkBitmap *mask);
+void _gdk_windowing_window_beep (GdkWindow *window);
+
void _gdk_windowing_get_pointer (GdkDisplay *display,
GdkScreen **screen,
gint *x,
gint *y,
GdkModifierType *mask);
-GdkWindow* _gdk_windowing_window_get_pointer (GdkDisplay *display,
- GdkWindow *window,
- gint *x,
- gint *y,
- GdkModifierType *mask);
GdkWindow* _gdk_windowing_window_at_pointer (GdkDisplay *display,
gint *win_x,
- gint *win_y);
+ gint *win_y,
+ GdkModifierType *mask);
+GdkGrabStatus _gdk_windowing_pointer_grab (GdkWindow *window,
+ GdkWindow *native,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ GdkWindow *confine_to,
+ GdkCursor *cursor,
+ guint32 time);
+void _gdk_windowing_got_event (GdkDisplay *display,
+ GList *event_link,
+ GdkEvent *event,
+ gulong serial);
+
+void _gdk_windowing_window_process_updates_recurse (GdkWindow *window,
+ GdkRegion *expose_region);
+void _gdk_windowing_before_process_all_updates (void);
+void _gdk_windowing_after_process_all_updates (void);
/* Return the number of bits-per-pixel for images of the specified depth. */
gint _gdk_windowing_get_bits_for_depth (GdkDisplay *display,
gint depth);
-void _gdk_window_reparent (GdkWindow *window,
- GdkWindow *new_parent,
- gint x,
- gint y);
#define GDK_WINDOW_IS_MAPPED(window) ((((GdkWindowObject*)window)->state & GDK_WINDOW_STATE_WITHDRAWN) == 0)
-/* Called before processing updates for a window. This gives the windowing
- * layer a chance to save the region for later use in avoiding duplicate
- * exposes. The return value indicates whether the function has a saved
- * the region; if the result is TRUE, then the windowing layer is responsible
- * for destroying the region later.
- */
-gboolean _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
- GdkRegion *area);
-
-/* Called to do the windowing system specific part of gdk_window_destroy(),
- *
- * window: The window being destroyed
- * recursing: If TRUE, then this is being called because a parent
- * was destroyed. This generally means that the call to the windowing system
- * to destroy the window can be omitted, since it will be destroyed as a result
- * of the parent being destroyed. Unless @foreign_destroy
- *
- * foreign_destroy: If TRUE, the window or a parent was destroyed by some external
- * agency. The window has already been destroyed and no windowing
- * system calls should be made. (This may never happen for some
- * windowing systems.)
- */
-void _gdk_windowing_window_destroy (GdkWindow *window,
- gboolean recursing,
- gboolean foreign_destroy);
/* Called when gdk_window_destroy() is called on a foreign window
* or an ancestor of the foreign window. It should generally reparent
GTypeInterface g_iface;
void (* begin_paint_region) (GdkPaintable *paintable,
+ GdkWindow *window,
const GdkRegion *region);
void (* end_paint) (GdkPaintable *paintable);
-
- void (* invalidate_maybe_recurse) (GdkPaintable *paintable,
- const GdkRegion *region,
- gboolean (*child_func) (GdkWindow *, gpointer),
- gpointer user_data);
- void (* process_updates) (GdkPaintable *paintable,
- gboolean update_children);
};
GType _gdk_paintable_get_type (void) G_GNUC_CONST;
* _gdk_windowing_gc_set_clip_region:
* @gc: a #GdkGC
* @region: the new clip region
+ * @reset_origin: if TRUE, reset the clip_x/y_origin values to 0
*
* Do any window-system specific processing necessary
* for a change in clip region. Since the clip origin
* will already return the new region.
**/
void _gdk_windowing_gc_set_clip_region (GdkGC *gc,
- const GdkRegion *region);
+ const GdkRegion *region,
+ gboolean reset_origin);
/**
* _gdk_windowing_gc_copy:
void _gdk_windowing_launch_failed (GAppLaunchContext *context,
const char *startup_notify_id);
+GdkPointerGrabInfo *_gdk_display_get_active_pointer_grab (GdkDisplay *display);
+void _gdk_display_pointer_grab_update (GdkDisplay *display,
+ gulong current_serial);
+GdkPointerGrabInfo *_gdk_display_get_last_pointer_grab (GdkDisplay *display);
+GdkPointerGrabInfo *_gdk_display_add_pointer_grab (GdkDisplay *display,
+ GdkWindow *window,
+ GdkWindow *native_window,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ unsigned long serial_start,
+ guint32 time,
+ gboolean implicit);
+GdkPointerGrabInfo * _gdk_display_has_pointer_grab (GdkDisplay *display,
+ gulong serial);
+gboolean _gdk_display_end_pointer_grab (GdkDisplay *display,
+ gulong serial,
+ GdkWindow *if_child,
+ gboolean implicit);
+void _gdk_display_set_has_keyboard_grab (GdkDisplay *display,
+ GdkWindow *window,
+ GdkWindow *native_window,
+ gboolean owner_events,
+ unsigned long serial,
+ guint32 time);
+void _gdk_display_unset_has_keyboard_grab (GdkDisplay *display,
+ gboolean implicit);
+void _gdk_display_enable_motion_hints (GdkDisplay *display);
+
+
+void _gdk_window_invalidate_for_expose (GdkWindow *window,
+ const GdkRegion *region);
+
+void _gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
+ int width,
+ int height);
+
+cairo_surface_t * _gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
+ int width,
+ int height);
+GdkWindow * _gdk_window_find_child_at (GdkWindow *window,
+ int x, int y);
+GdkWindow * _gdk_window_find_descendant_at (GdkWindow *toplevel,
+ double x, double y,
+ double *found_x,
+ double *found_y);
+
+void _gdk_window_add_damage (GdkWindow *toplevel,
+ GdkRegion *damaged_region);
+
+GdkEvent * _gdk_make_event (GdkWindow *window,
+ GdkEventType type,
+ GdkEvent *event_in_queue,
+ gboolean before_event);
+
+void _gdk_syntesize_crossing_events (GdkDisplay *display,
+ GdkWindow *src,
+ GdkWindow *dest,
+ GdkCrossingMode mode,
+ gint toplevel_x,
+ gint toplevel_y,
+ GdkModifierType mask,
+ guint32 time_,
+ GdkEvent *event_in_queue,
+ gulong serial);
+void _gdk_display_set_window_under_pointer (GdkDisplay *display,
+ GdkWindow *window);
+
+
+void _gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window);
+
+GdkRegion *_gdk_window_calculate_full_clip_region (GdkWindow *window,
+ GdkWindow *base_window,
+ gboolean do_children,
+ gint *base_x_offset,
+ gint *base_y_offset);
+gboolean _gdk_window_has_impl (GdkWindow *window);
+GdkWindow * _gdk_window_get_impl_window (GdkWindow *window);
+GdkWindow *_gdk_window_get_input_window_for_event (GdkWindow *native_window,
+ GdkEventType event_type,
+ int x, int y,
+ gulong serial);
+GdkRegion *_gdk_region_new_from_yxbanded_rects (GdkRectangle *rects, int n_rects);
+
+/*****************************
+ * offscreen window routines *
+ *****************************/
+GType gdk_offscreen_window_get_type (void);
+void _gdk_offscreen_window_new (GdkWindow *window,
+ GdkScreen *screen,
+ GdkVisual *visual,
+ GdkWindowAttr *attributes,
+ gint attributes_mask);
+
/************************************
* Initialization and exit routines *
VOID:OBJECT
VOID:BOOLEAN
+VOID:POINTER,POINTER,POINTER
+OBJECT:VOID
+OBJECT:DOUBLE,DOUBLE
+VOID:DOUBLE,DOUBLE,POINTER,POINTER
--- /dev/null
+/* 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 Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2005. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include <config.h>
+#include <math.h>
+#include "gdk.h"
+#include "gdkwindow.h"
+#include "gdkinternals.h"
+#include "gdkwindowimpl.h"
+#include "gdkpixmap.h"
+#include "gdkdrawable.h"
+#include "gdktypes.h"
+#include "gdkscreen.h"
+#include "gdkgc.h"
+#include "gdkcolor.h"
+#include "gdkcursor.h"
+#include "gdkalias.h"
+
+/* LIMITATIONS:
+ *
+ * Offscreen windows can't be the child of a foreign window,
+ * nor contain foreign windows
+ *Â GDK_POINTER_MOTION_HINT_MASK isn't effective
+ */
+
+typedef struct _GdkOffscreenWindow GdkOffscreenWindow;
+typedef struct _GdkOffscreenWindowClass GdkOffscreenWindowClass;
+
+struct _GdkOffscreenWindow
+{
+ GdkDrawable parent_instance;
+
+ GdkWindow *wrapper;
+ GdkCursor *cursor;
+ GdkColormap *colormap;
+ GdkScreen *screen;
+
+ GdkPixmap *pixmap;
+};
+
+struct _GdkOffscreenWindowClass
+{
+ GdkDrawableClass parent_class;
+};
+
+#define GDK_TYPE_OFFSCREEN_WINDOW (gdk_offscreen_window_get_type())
+#define GDK_OFFSCREEN_WINDOW(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindow))
+#define GDK_IS_OFFSCREEN_WINDOW(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_OFFSCREEN_WINDOW))
+#define GDK_OFFSCREEN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
+#define GDK_IS_OFFSCREEN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_OFFSCREEN_WINDOW))
+#define GDK_OFFSCREEN_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
+
+static void gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface);
+static void gdk_offscreen_window_hide (GdkWindow *window);
+
+G_DEFINE_TYPE_WITH_CODE (GdkOffscreenWindow,
+ gdk_offscreen_window,
+ GDK_TYPE_DRAWABLE,
+ G_IMPLEMENT_INTERFACE (GDK_TYPE_WINDOW_IMPL,
+ gdk_offscreen_window_impl_iface_init));
+
+
+static void
+gdk_offscreen_window_finalize (GObject *object)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (object);
+
+ if (offscreen->cursor)
+ gdk_cursor_unref (offscreen->cursor);
+
+ offscreen->cursor = NULL;
+
+ gdk_pixmap_unref (offscreen->pixmap);
+
+ G_OBJECT_CLASS (gdk_offscreen_window_parent_class)->finalize (object);
+}
+
+static void
+gdk_offscreen_window_init (GdkOffscreenWindow *window)
+{
+}
+
+static void
+gdk_offscreen_window_destroy (GdkWindow *window,
+ gboolean recursing,
+ gboolean foreign_destroy)
+{
+ GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
+ GdkOffscreenWindow *offscreen;
+
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+ if (!recursing)
+ gdk_offscreen_window_hide (window);
+
+ g_object_unref (offscreen->colormap);
+ offscreen->colormap = NULL;
+}
+
+static gboolean
+is_parent_of (GdkWindow *parent,
+ GdkWindow *child)
+{
+ GdkWindow *w;
+
+ w = child;
+ while (w != NULL)
+ {
+ if (w == parent)
+ return TRUE;
+
+ w = gdk_window_get_parent (w);
+ }
+
+ return FALSE;
+}
+
+static GdkGC *
+gdk_offscreen_window_create_gc (GdkDrawable *drawable,
+ GdkGCValues *values,
+ GdkGCValuesMask values_mask)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return gdk_gc_new_with_values (offscreen->pixmap, values, values_mask);
+}
+
+static GdkImage*
+gdk_offscreen_window_copy_to_image (GdkDrawable *drawable,
+ GdkImage *image,
+ gint src_x,
+ gint src_y,
+ gint dest_x,
+ gint dest_y,
+ gint width,
+ gint height)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return gdk_drawable_copy_to_image (offscreen->pixmap,
+ image,
+ src_x,
+ src_y,
+ dest_x, dest_y,
+ width, height);
+}
+
+static cairo_surface_t *
+gdk_offscreen_window_ref_cairo_surface (GdkDrawable *drawable)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return _gdk_drawable_ref_cairo_surface (offscreen->pixmap);
+}
+
+static GdkColormap*
+gdk_offscreen_window_get_colormap (GdkDrawable *drawable)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return offscreen->colormap;
+}
+
+static void
+gdk_offscreen_window_set_colormap (GdkDrawable *drawable,
+ GdkColormap*colormap)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ if (colormap && GDK_WINDOW_DESTROYED (offscreen->wrapper))
+ return;
+
+ if (offscreen->colormap == colormap)
+ return;
+
+ if (offscreen->colormap)
+ g_object_unref (offscreen->colormap);
+
+ offscreen->colormap = colormap;
+ if (offscreen->colormap)
+ g_object_ref (offscreen->colormap);
+}
+
+
+static gint
+gdk_offscreen_window_get_depth (GdkDrawable *drawable)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return gdk_drawable_get_depth (offscreen->wrapper);
+}
+
+static GdkDrawable *
+gdk_offscreen_window_get_source_drawable (GdkDrawable *drawable)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return _gdk_drawable_get_source_drawable (offscreen->pixmap);
+}
+
+static GdkDrawable *
+gdk_offscreen_window_get_composite_drawable (GdkDrawable *drawable,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gint *composite_x_offset,
+ gint *composite_y_offset)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return g_object_ref (offscreen->pixmap);
+}
+
+static GdkScreen*
+gdk_offscreen_window_get_screen (GdkDrawable *drawable)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return offscreen->screen;
+}
+
+static GdkVisual*
+gdk_offscreen_window_get_visual (GdkDrawable *drawable)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+ return gdk_drawable_get_visual (offscreen->wrapper);
+}
+
+static void
+add_damage (GdkOffscreenWindow *offscreen,
+ int x, int y,
+ int w, int h)
+{
+ GdkRectangle rect;
+ GdkRegion *damage;
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = w;
+ rect.height = h;
+
+ damage = gdk_region_rectangle (&rect);
+ _gdk_window_add_damage (offscreen->wrapper, damage);
+ gdk_region_destroy (damage);
+}
+
+static GdkDrawable *
+get_real_drawable (GdkOffscreenWindow *offscreen)
+{
+ GdkPixmapObject *pixmap;
+ pixmap = (GdkPixmapObject *) offscreen->pixmap;
+ return GDK_DRAWABLE (pixmap->impl);
+}
+
+static void
+gdk_offscreen_window_draw_drawable (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPixmap *src,
+ GdkDrawable *original_src,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+ gdk_draw_drawable (real_drawable, gc,
+ src, xsrc, ysrc,
+ xdest, ydest,
+ width, height);
+
+ add_damage (offscreen, xdest, ydest, width, height);
+}
+
+static void
+gdk_offscreen_window_draw_rectangle (GdkDrawable *drawable,
+ GdkGC *gc,
+ gboolean filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+ gdk_draw_rectangle (real_drawable,
+ gc, filled, x, y, width, height);
+
+ add_damage (offscreen, x, y, width, height);
+
+}
+
+static void
+gdk_offscreen_window_draw_arc (GdkDrawable *drawable,
+ GdkGC *gc,
+ gboolean filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gint angle1,
+ gint angle2)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+ gdk_draw_arc (real_drawable,
+ gc,
+ filled,
+ x,
+ y,
+ width,
+ height,
+ angle1,
+ angle2);
+ add_damage (offscreen, x, y, width, height);
+}
+
+static void
+gdk_offscreen_window_draw_polygon (GdkDrawable *drawable,
+ GdkGC *gc,
+ gboolean filled,
+ GdkPoint *points,
+ gint npoints)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+ gdk_draw_polygon (real_drawable,
+ gc,
+ filled,
+ points,
+ npoints);
+
+ if (npoints > 0)
+ {
+ int min_x, min_y, max_x, max_y, i;
+
+ min_x = max_x = points[0].x;
+ min_y = max_y = points[0].y;
+
+ for (i = 1; i < npoints; i++)
+ {
+ min_x = MIN (min_x, points[i].x);
+ max_x = MAX (max_x, points[i].x);
+ min_y = MIN (min_y, points[i].y);
+ max_y = MAX (max_y, points[i].y);
+ }
+
+ add_damage (offscreen, min_x, min_y,
+ max_x - min_x,
+ max_y - min_y);
+ }
+}
+
+static void
+gdk_offscreen_window_draw_text (GdkDrawable *drawable,
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const gchar *text,
+ gint text_length)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = get_real_drawable (offscreen);
+ GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+ gdk_draw_text (real_drawable,
+ font,
+ gc,
+ x,
+ y,
+ text,
+ text_length);
+
+ /* Hard to compute the minimal size, not that often used anyway. */
+ add_damage (offscreen, 0, 0, private->width, private->height);
+}
+
+static void
+gdk_offscreen_window_draw_text_wc (GdkDrawable *drawable,
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const GdkWChar *text,
+ gint text_length)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = get_real_drawable (offscreen);
+ GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+ gdk_draw_text_wc (real_drawable,
+ font,
+ gc,
+ x,
+ y,
+ text,
+ text_length);
+
+ /* Hard to compute the minimal size, not that often used anyway. */
+ add_damage (offscreen, 0, 0, private->width, private->height);
+}
+
+static void
+gdk_offscreen_window_draw_points (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPoint *points,
+ gint npoints)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+ gdk_draw_points (real_drawable,
+ gc,
+ points,
+ npoints);
+
+
+ if (npoints > 0)
+ {
+ int min_x, min_y, max_x, max_y, i;
+
+ min_x = max_x = points[0].x;
+ min_y = max_y = points[0].y;
+
+ for (i = 1; i < npoints; i++)
+ {
+ min_x = MIN (min_x, points[i].x);
+ max_x = MAX (max_x, points[i].x);
+ min_y = MIN (min_y, points[i].y);
+ max_y = MAX (max_y, points[i].y);
+ }
+
+ add_damage (offscreen, min_x, min_y,
+ max_x - min_x,
+ max_y - min_y);
+ }
+}
+
+static void
+gdk_offscreen_window_draw_segments (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkSegment *segs,
+ gint nsegs)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+ gdk_draw_segments (real_drawable,
+ gc,
+ segs,
+ nsegs);
+
+ if (nsegs > 0)
+ {
+ int min_x, min_y, max_x, max_y, i;
+
+ min_x = max_x = segs[0].x1;
+ min_y = max_y = segs[0].y1;
+
+ for (i = 1; i < nsegs; i++)
+ {
+ min_x = MIN (min_x, segs[i].x1);
+ max_x = MAX (max_x, segs[i].x1);
+ min_x = MIN (min_x, segs[i].x2);
+ max_x = MAX (max_x, segs[i].x2);
+ min_y = MIN (min_y, segs[i].y1);
+ max_y = MAX (max_y, segs[i].y1);
+ min_y = MIN (min_y, segs[i].y2);
+ max_y = MAX (max_y, segs[i].y2);
+ }
+
+ add_damage (offscreen, min_x, min_y,
+ max_x - min_x,
+ max_y - min_y);
+ }
+
+}
+
+static void
+gdk_offscreen_window_draw_lines (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPoint *points,
+ gint npoints)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = get_real_drawable (offscreen);
+ GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+ gdk_draw_lines (real_drawable,
+ gc,
+ points,
+ npoints);
+
+ /* Hard to compute the minimal size, as we don't know the line
+ width, and since joins are hard to calculate.
+ Its not that often used anyway, damage it all */
+ add_damage (offscreen, 0, 0, private->width, private->height);
+}
+
+static void
+gdk_offscreen_window_draw_image (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+ gdk_draw_image (real_drawable,
+ gc,
+ image,
+ xsrc,
+ ysrc,
+ xdest,
+ ydest,
+ width,
+ height);
+
+ add_damage (offscreen, xdest, ydest, width, height);
+}
+
+
+static void
+gdk_offscreen_window_draw_pixbuf (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPixbuf *pixbuf,
+ gint src_x,
+ gint src_y,
+ gint dest_x,
+ gint dest_y,
+ gint width,
+ gint height,
+ GdkRgbDither dither,
+ gint x_dither,
+ gint y_dither)
+{
+ GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+ GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+ gdk_draw_pixbuf (real_drawable,
+ gc,
+ pixbuf,
+ src_x,
+ src_y,
+ dest_x,
+ dest_y,
+ width,
+ height,
+ dither,
+ x_dither,
+ y_dither);
+
+ add_damage (offscreen, dest_x, dest_y, width, height);
+
+}
+
+void
+_gdk_offscreen_window_new (GdkWindow *window,
+ GdkScreen *screen,
+ GdkVisual *visual,
+ GdkWindowAttr *attributes,
+ gint attributes_mask)
+{
+ GdkWindowObject *parent_private;
+ GdkWindowObject *private;
+ GdkOffscreenWindow *offscreen;
+
+ g_return_if_fail (attributes != NULL);
+
+ if (attributes->wclass != GDK_INPUT_OUTPUT)
+ return; /* Can't support input only offscreens */
+
+ private = (GdkWindowObject *)window;
+
+ if (private->parent != NULL && GDK_WINDOW_DESTROYED (private->parent))
+ return;
+
+ parent_private = (GdkWindowObject*) private->parent;
+ private->impl = g_object_new (GDK_TYPE_OFFSCREEN_WINDOW, NULL);
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+ offscreen->wrapper = window;
+
+ offscreen->screen = screen;
+
+ if (attributes_mask & GDK_WA_COLORMAP)
+ offscreen->colormap = g_object_ref (attributes->colormap);
+ else
+ {
+ if (gdk_screen_get_system_visual (screen) == visual)
+ {
+ offscreen->colormap = gdk_screen_get_system_colormap (screen);
+ g_object_ref (offscreen->colormap);
+ }
+ else
+ offscreen->colormap = gdk_colormap_new (visual, FALSE);
+ }
+
+ offscreen->pixmap = gdk_pixmap_new ((GdkDrawable *)private->parent,
+ private->width,
+ private->height,
+ private->depth);
+}
+
+static gboolean
+gdk_offscreen_window_reparent (GdkWindow *window,
+ GdkWindow *new_parent,
+ gint x,
+ gint y)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *new_parent_private = (GdkWindowObject *)new_parent;
+ GdkWindowObject *old_parent;
+ GdkOffscreenWindow *offscreen;
+ gboolean was_mapped;
+
+ if (new_parent)
+ {
+ /* No input-output children of input-only windows */
+ if (new_parent_private->input_only && !private->input_only)
+ return FALSE;
+
+ /* Don't create loops in hierarchy */
+ if (is_parent_of (window, new_parent))
+ return FALSE;
+ }
+
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+ was_mapped = GDK_WINDOW_IS_MAPPED (window);
+
+ gdk_window_hide (window);
+
+ if (private->parent)
+ private->parent->children = g_list_remove (private->parent->children, window);
+
+ old_parent = private->parent;
+ private->parent = new_parent_private;
+ private->x = x;
+ private->y = y;
+
+ if (new_parent_private)
+ private->parent->children = g_list_prepend (private->parent->children, window);
+
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+ if (old_parent)
+ _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (old_parent));
+
+ return was_mapped;
+}
+
+
+static GdkWindow *
+get_offscreen_parent (GdkWindow *window)
+{
+ GdkWindowObject *private;
+ GdkWindow *res;
+
+ private = (GdkWindowObject *)window;
+
+ res = NULL;
+ g_signal_emit_by_name (private->impl_window,
+ "get-offscreen-parent",
+ &res);
+
+ return res;
+}
+
+static void
+from_parent (GdkWindow *window,
+ double parent_x, double parent_y,
+ double *offscreen_x, double *offscreen_y)
+{
+ GdkWindowObject *private;
+
+ private = (GdkWindowObject *)window;
+
+ g_signal_emit_by_name (private->impl_window,
+ "from_parent",
+ parent_x, parent_y,
+ offscreen_x, offscreen_y,
+ NULL);
+}
+
+static void
+to_parent (GdkWindow *window,
+ double offscreen_x, double offscreen_y,
+ double *parent_x, double *parent_y)
+{
+ GdkWindowObject *private;
+
+ private = (GdkWindowObject *)window;
+
+ g_signal_emit_by_name (private->impl_window,
+ "to_parent",
+ offscreen_x, offscreen_y,
+ parent_x, parent_y,
+ NULL);
+}
+
+static gint
+gdk_offscreen_window_get_root_coords (GdkWindow *window,
+ gint x,
+ gint y,
+ gint *root_x,
+ gint *root_y)
+{
+ GdkWindow *parent;
+ int tmpx, tmpy;
+
+ tmpx = x;
+ tmpy = y;
+
+ parent = get_offscreen_parent (window);
+ if (parent)
+ {
+ double dx, dy;
+ to_parent (window,
+ x, y,
+ &dx, &dy);
+ tmpx = floor (dx + 0.5);
+ tmpy = floor (dy + 0.5);
+ gdk_window_get_root_coords (parent,
+ tmpx, tmpy,
+ &tmpx, &tmpy);
+
+ }
+
+ if (root_x)
+ *root_x = tmpx;
+ if (root_y)
+ *root_y = tmpy;
+
+ return TRUE;
+}
+
+static gint
+gdk_offscreen_window_get_deskrelative_origin (GdkWindow *window,
+ gint *x,
+ gint *y)
+{
+ GdkWindow *parent;
+ int tmpx, tmpy;
+
+ tmpx = 0;
+ tmpy = 0;
+
+ parent = get_offscreen_parent (window);
+ if (parent)
+ {
+ double dx, dy;
+ gdk_window_get_deskrelative_origin (parent,
+ &tmpx, &tmpy);
+
+ to_parent (window,
+ 0, 0,
+ &dx, &dy);
+ tmpx = floor (tmpx + dx + 0.5);
+ tmpy = floor (tmpy + dy + 0.5);
+ }
+
+
+ if (x)
+ *x = tmpx;
+ if (y)
+ *y = tmpy;
+
+ return TRUE;
+}
+
+static gboolean
+gdk_offscreen_window_get_pointer (GdkWindow *window,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask)
+{
+ int tmpx, tmpy;
+ double dtmpx, dtmpy;
+ GdkModifierType tmpmask;
+ GdkWindow *parent;
+
+ tmpx = 0;
+ tmpy = 0;
+ tmpmask = 0;
+
+ parent = get_offscreen_parent (window);
+ if (parent != NULL)
+ {
+ gdk_window_get_pointer (parent, &tmpx, &tmpy, &tmpmask);
+ from_parent (window,
+ tmpx, tmpy,
+ &dtmpx, &dtmpy);
+ tmpx = floor (dtmpx + 0.5);
+ tmpy = floor (dtmpy + 0.5);
+ }
+
+ if (x)
+ *x = tmpx;
+ if (y)
+ *y = tmpy;
+ if (mask)
+ *mask = tmpmask;
+ return TRUE;
+}
+
+/**
+ * gdk_window_get_offscreen_pixmap:
+ * @window: a #GdkWindow
+ *
+ * Gets the offscreen pixmap that an offscreen window renders into. If
+ * you need to keep this around over window resizes, you need to add a
+ * reference to it.
+ *
+ * Returns: The offscreen pixmap, or NULL if not offscreen
+ **/
+GdkPixmap *
+gdk_window_get_offscreen_pixmap (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkOffscreenWindow *offscreen;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+ if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
+ return NULL;
+
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+ return offscreen->pixmap;
+}
+
+static void
+gdk_offscreen_window_raise (GdkWindow *window)
+{
+ /* gdk_window_raise already changed the stacking order */
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+gdk_offscreen_window_lower (GdkWindow *window)
+{
+ /* gdk_window_lower already changed the stacking order */
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+gdk_offscreen_window_move_resize_internal (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gboolean send_expose_events)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkOffscreenWindow *offscreen;
+ gint dx, dy, dw, dh;
+ GdkGC *gc;
+ GdkPixmap *old_pixmap;
+
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+ if (width < 1)
+ width = 1;
+ if (height < 1)
+ height = 1;
+
+ if (private->destroyed)
+ return;
+
+ dx = x - private->x;
+ dy = y - private->y;
+ dw = width - private->width;
+ dh = height - private->height;
+
+ private->x = x;
+ private->y = y;
+
+ if (private->width != width ||
+ private->height != height)
+ {
+ private->width = width;
+ private->height = height;
+
+ old_pixmap = offscreen->pixmap;
+ offscreen->pixmap = gdk_pixmap_new (GDK_DRAWABLE (old_pixmap),
+ width,
+ height,
+ private->depth);
+
+ gc = _gdk_drawable_get_scratch_gc (offscreen->pixmap, FALSE);
+ gdk_draw_drawable (offscreen->pixmap,
+ gc,
+ old_pixmap,
+ 0,0, 0, 0,
+ -1, -1);
+ g_object_unref (old_pixmap);
+ }
+
+ if (GDK_WINDOW_IS_MAPPED (private))
+ {
+ // TODO: Only invalidate new area, i.e. for larger windows
+ gdk_window_invalidate_rect (window, NULL, TRUE);
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+ }
+}
+
+static void
+gdk_offscreen_window_move_resize (GdkWindow *window,
+ gboolean with_move,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkOffscreenWindow *offscreen;
+
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+ if (!with_move)
+ {
+ x = private->x;
+ y = private->y;
+ }
+
+ if (width < 0)
+ width = private->width;
+
+ if (height < 0)
+ height = private->height;
+
+ gdk_offscreen_window_move_resize_internal (window, x, y,
+ width, height,
+ TRUE);
+}
+
+static void
+gdk_offscreen_window_show (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ gdk_window_clear_area_e (window, 0, 0,
+ private->width, private->height);
+}
+
+
+static void
+gdk_offscreen_window_hide (GdkWindow *window)
+{
+ GdkWindowObject *private;
+ GdkOffscreenWindow *offscreen;
+ GdkDisplay *display;
+
+ g_return_if_fail (window != NULL);
+
+ private = (GdkWindowObject*) window;
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+ /* May need to break grabs on children */
+ display = gdk_drawable_get_display (window);
+
+ /* TODO: This needs updating to the new grab world */
+#if 0
+ if (display->pointer_grab.window != NULL)
+ {
+ if (is_parent_of (window, display->pointer_grab.window))
+ {
+ /* Call this ourselves, even though gdk_display_pointer_ungrab
+ does so too, since we want to pass implicit == TRUE so the
+ broken grab event is generated */
+ _gdk_display_unset_has_pointer_grab (display,
+ TRUE,
+ FALSE,
+ GDK_CURRENT_TIME);
+ gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+ }
+ }
+#endif
+}
+
+static void
+gdk_offscreen_window_withdraw (GdkWindow *window)
+{
+}
+
+static GdkEventMask
+gdk_offscreen_window_get_events (GdkWindow *window)
+{
+ return 0;
+}
+
+static void
+gdk_offscreen_window_set_events (GdkWindow *window,
+ GdkEventMask event_mask)
+{
+}
+
+static void
+gdk_offscreen_window_set_background (GdkWindow *window,
+ const GdkColor *color)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkColormap *colormap = gdk_drawable_get_colormap (window);
+
+ private->bg_color = *color;
+ gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
+
+ if (private->bg_pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG)
+ g_object_unref (private->bg_pixmap);
+
+ private->bg_pixmap = NULL;
+}
+
+static void
+gdk_offscreen_window_set_back_pixmap (GdkWindow *window,
+ GdkPixmap *pixmap)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ if (pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG &&
+ !gdk_drawable_get_colormap (pixmap))
+ {
+ g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
+ return;
+ }
+
+ if (private->bg_pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG)
+ g_object_unref (private->bg_pixmap);
+
+ private->bg_pixmap = pixmap;
+
+ if (pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG)
+ g_object_ref (pixmap);
+}
+
+static void
+gdk_offscreen_window_shape_combine_region (GdkWindow *window,
+ const GdkRegion *shape_region,
+ gint offset_x,
+ gint offset_y)
+{
+}
+
+static void
+gdk_offscreen_window_input_shape_combine_region (GdkWindow *window,
+ const GdkRegion *shape_region,
+ gint offset_x,
+ gint offset_y)
+{
+}
+
+static gboolean
+gdk_offscreen_window_set_static_gravities (GdkWindow *window,
+ gboolean use_static)
+{
+ return TRUE;
+}
+
+static void
+gdk_offscreen_window_set_cursor (GdkWindow *window,
+ GdkCursor *cursor)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkOffscreenWindow *offscreen;
+
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+ if (offscreen->cursor)
+ {
+ gdk_cursor_unref (offscreen->cursor);
+ offscreen->cursor = NULL;
+ }
+
+ if (cursor)
+ offscreen->cursor = gdk_cursor_ref (cursor);
+
+ /* TODO: The cursor is never actually used... */
+}
+
+static void
+gdk_offscreen_window_get_geometry (GdkWindow *window,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ gint *depth)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkOffscreenWindow *offscreen;
+
+ offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+ g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
+
+ if (!GDK_WINDOW_DESTROYED (window))
+ {
+ if (x)
+ *x = private->x;
+ if (y)
+ *y = private->y;
+ if (width)
+ *width = private->width;
+ if (height)
+ *height = private->height;
+ if (depth)
+ *depth = private->depth;
+ }
+}
+
+static gboolean
+gdk_offscreen_window_queue_antiexpose (GdkWindow *window,
+ GdkRegion *area)
+{
+ return FALSE;
+}
+
+static void
+gdk_offscreen_window_queue_translation (GdkWindow *window,
+ GdkRegion *area,
+ gint dx,
+ gint dy)
+{
+}
+
+
+static void
+gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass)
+{
+ GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gdk_offscreen_window_finalize;
+
+ drawable_class->create_gc = gdk_offscreen_window_create_gc;
+ drawable_class->_copy_to_image = gdk_offscreen_window_copy_to_image;
+ drawable_class->ref_cairo_surface = gdk_offscreen_window_ref_cairo_surface;
+ drawable_class->set_colormap = gdk_offscreen_window_set_colormap;
+ drawable_class->get_colormap = gdk_offscreen_window_get_colormap;
+ drawable_class->get_depth = gdk_offscreen_window_get_depth;
+ drawable_class->get_screen = gdk_offscreen_window_get_screen;
+ drawable_class->get_visual = gdk_offscreen_window_get_visual;
+ drawable_class->get_source_drawable = gdk_offscreen_window_get_source_drawable;
+ drawable_class->get_composite_drawable = gdk_offscreen_window_get_composite_drawable;
+
+ drawable_class->draw_rectangle = gdk_offscreen_window_draw_rectangle;
+ drawable_class->draw_arc = gdk_offscreen_window_draw_arc;
+ drawable_class->draw_polygon = gdk_offscreen_window_draw_polygon;
+ drawable_class->draw_text = gdk_offscreen_window_draw_text;
+ drawable_class->draw_text_wc = gdk_offscreen_window_draw_text_wc;
+ drawable_class->draw_drawable = gdk_offscreen_window_draw_drawable;
+ drawable_class->draw_points = gdk_offscreen_window_draw_points;
+ drawable_class->draw_segments = gdk_offscreen_window_draw_segments;
+ drawable_class->draw_lines = gdk_offscreen_window_draw_lines;
+ drawable_class->draw_image = gdk_offscreen_window_draw_image;
+ drawable_class->draw_pixbuf = gdk_offscreen_window_draw_pixbuf;
+}
+
+static void
+gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface)
+{
+ iface->show = gdk_offscreen_window_show;
+ iface->hide = gdk_offscreen_window_hide;
+ iface->withdraw = gdk_offscreen_window_withdraw;
+ iface->raise = gdk_offscreen_window_raise;
+ iface->lower = gdk_offscreen_window_lower;
+ iface->move_resize = gdk_offscreen_window_move_resize;
+ iface->set_background = gdk_offscreen_window_set_background;
+ iface->set_back_pixmap = gdk_offscreen_window_set_back_pixmap;
+ iface->get_events = gdk_offscreen_window_get_events;
+ iface->set_events = gdk_offscreen_window_set_events;
+ iface->reparent = gdk_offscreen_window_reparent;
+ iface->set_cursor = gdk_offscreen_window_set_cursor;
+ iface->get_geometry = gdk_offscreen_window_get_geometry;
+ iface->shape_combine_region = gdk_offscreen_window_shape_combine_region;
+ iface->input_shape_combine_region = gdk_offscreen_window_input_shape_combine_region;
+ iface->set_static_gravities = gdk_offscreen_window_set_static_gravities;
+ iface->queue_antiexpose = gdk_offscreen_window_queue_antiexpose;
+ iface->queue_translation = gdk_offscreen_window_queue_translation;
+ iface->get_root_coords = gdk_offscreen_window_get_root_coords;
+ iface->get_deskrelative_origin = gdk_offscreen_window_get_deskrelative_origin;
+ iface->get_pointer = gdk_offscreen_window_get_pointer;
+ iface->destroy = gdk_offscreen_window_destroy;
+}
+
+#define __GDK_OFFSCREEN_WINDOW_C__
+#include "gdkaliasdef.c"
priv->cr,
color,
priv->stipple[part],
- priv->gc_changed);
+ priv->gc_changed,
+ priv->drawable);
}
priv->last_part = part;
static void gdk_pixmap_draw_drawable (GdkDrawable *drawable,
GdkGC *gc,
GdkPixmap *src,
+ GdkPixmap *original_src,
gint xsrc,
gint ysrc,
gint xdest,
gint height);
static cairo_surface_t *gdk_pixmap_ref_cairo_surface (GdkDrawable *drawable);
+static cairo_surface_t *gdk_pixmap_create_cairo_surface (GdkDrawable *drawable,
+ int width,
+ int height);
static GdkVisual* gdk_pixmap_real_get_visual (GdkDrawable *drawable);
static gint gdk_pixmap_real_get_depth (GdkDrawable *drawable);
drawable_class->get_visual = gdk_pixmap_real_get_visual;
drawable_class->_copy_to_image = gdk_pixmap_copy_to_image;
drawable_class->ref_cairo_surface = gdk_pixmap_ref_cairo_surface;
+ drawable_class->create_cairo_surface = gdk_pixmap_create_cairo_surface;
}
static void
G_OBJECT_CLASS (parent_class)->finalize (object);
}
+GdkPixmap *
+gdk_pixmap_new (GdkDrawable *drawable,
+ gint width,
+ gint height,
+ gint depth)
+{
+ GdkDrawable *source_drawable;
+
+ if (drawable)
+ source_drawable = _gdk_drawable_get_source_drawable (drawable);
+ else
+ source_drawable = NULL;
+ return _gdk_pixmap_new (source_drawable, width, height, depth);
+}
+
+GdkPixmap *
+gdk_bitmap_create_from_data (GdkDrawable *drawable,
+ const gchar *data,
+ gint width,
+ gint height)
+{
+ GdkDrawable *source_drawable;
+
+ if (drawable)
+ source_drawable = _gdk_drawable_get_source_drawable (drawable);
+ else
+ source_drawable = NULL;
+ return _gdk_bitmap_create_from_data (source_drawable, data, width, height);
+}
+
+GdkPixmap*
+gdk_pixmap_create_from_data (GdkDrawable *drawable,
+ const gchar *data,
+ gint width,
+ gint height,
+ gint depth,
+ const GdkColor *fg,
+ const GdkColor *bg)
+{
+ GdkDrawable *source_drawable;
+
+ source_drawable = _gdk_drawable_get_source_drawable (drawable);
+ return _gdk_pixmap_create_from_data (source_drawable,
+ data, width, height,
+ depth, fg,bg);
+}
+
+
static GdkGC *
gdk_pixmap_create_gc (GdkDrawable *drawable,
GdkGCValues *values,
{
GdkPixmapObject *private = (GdkPixmapObject *)drawable;
+ _gdk_gc_remove_drawable_clip (gc);
gdk_draw_rectangle (private->impl, gc, filled,
x, y, width, height);
}
{
GdkPixmapObject *private = (GdkPixmapObject *)drawable;
+ _gdk_gc_remove_drawable_clip (gc);
gdk_draw_arc (private->impl, gc, filled,
x, y,
width, height, angle1, angle2);
{
GdkPixmapObject *private = (GdkPixmapObject *)drawable;
+ _gdk_gc_remove_drawable_clip (gc);
gdk_draw_polygon (private->impl, gc, filled, points, npoints);
}
{
GdkPixmapObject *private = (GdkPixmapObject *)drawable;
+ _gdk_gc_remove_drawable_clip (gc);
gdk_draw_text (private->impl, font, gc,
x, y, text, text_length);
}
{
GdkPixmapObject *private = (GdkPixmapObject *)drawable;
+ _gdk_gc_remove_drawable_clip (gc);
gdk_draw_text_wc (private->impl, font, gc,
x, y, text, text_length);
}
gdk_pixmap_draw_drawable (GdkDrawable *drawable,
GdkGC *gc,
GdkPixmap *src,
+ GdkPixmap *original_src,
gint xsrc,
gint ysrc,
gint xdest,
{
GdkPixmapObject *private = (GdkPixmapObject *)drawable;
+ _gdk_gc_remove_drawable_clip (gc);
gdk_draw_drawable (private->impl, gc, src, xsrc, ysrc,
xdest, ydest,
width, height);
{
GdkPixmapObject *private = (GdkPixmapObject *)drawable;
+ _gdk_gc_remove_drawable_clip (gc);
gdk_draw_points (private->impl, gc, points, npoints);
}
{
GdkPixmapObject *private = (GdkPixmapObject *)drawable;
+ _gdk_gc_remove_drawable_clip (gc);
gdk_draw_segments (private->impl, gc, segs, nsegs);
}
{
GdkPixmapObject *private = (GdkPixmapObject *)drawable;
+ _gdk_gc_remove_drawable_clip (gc);
gdk_draw_lines (private->impl, gc, points, npoints);
}
{
GdkPixmapObject *private = (GdkPixmapObject *)drawable;
+ _gdk_gc_remove_drawable_clip (gc);
gdk_draw_glyphs (private->impl, gc, font, x, y, glyphs);
}
{
GdkPixmapObject *private = (GdkPixmapObject *)drawable;
+ _gdk_gc_remove_drawable_clip (gc);
gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
}
{
GdkPixmapObject *private = (GdkPixmapObject *)drawable;
+ _gdk_gc_remove_drawable_clip (gc);
gdk_draw_image (private->impl, gc, image, xsrc, ysrc, xdest, ydest,
width, height);
}
{
GdkPixmapObject *private = (GdkPixmapObject *)drawable;
+ if (gc)
+ _gdk_gc_remove_drawable_clip (gc);
gdk_draw_pixbuf (private->impl, gc, pixbuf,
src_x, src_y, dest_x, dest_y, width, height,
dither, x_dither, y_dither);
{
GdkPixmapObject *private = (GdkPixmapObject *)drawable;
+ _gdk_gc_remove_drawable_clip (gc);
gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
}
return _gdk_drawable_ref_cairo_surface (((GdkPixmapObject*)drawable)->impl);
}
+static cairo_surface_t *
+gdk_pixmap_create_cairo_surface (GdkDrawable *drawable,
+ int width,
+ int height)
+{
+ return _gdk_windowing_create_cairo_surface (GDK_PIXMAP_OBJECT(drawable)->impl,
+ width, height);
+}
+
+
+
static GdkBitmap *
make_solid_mask (GdkScreen *screen, gint width, gint height)
{
overlapFunc overlapFn,
nonOverlapFunc nonOverlap1Fn,
nonOverlapFunc nonOverlap2Fn);
+static void miSetExtents (GdkRegion *pReg);
/**
* gdk_region_new:
return temp;
}
+GdkRegion *
+_gdk_region_new_from_yxbanded_rects (GdkRectangle *rects,
+ int num_rects)
+{
+ GdkRegion *temp;
+ int i;
+
+ temp = g_slice_new (GdkRegion);
+
+ temp->rects = g_new (GdkRegionBox, num_rects);
+ temp->size = num_rects;
+ temp->numRects = num_rects;
+ for (i = 0; i < num_rects; i++)
+ {
+ temp->rects[i].x1 = rects[i].x;
+ temp->rects[i].y1 = rects[i].y;
+ temp->rects[i].x2 = rects[i].x + rects[i].width;
+ temp->rects[i].y2 = rects[i].y + rects[i].height;
+ }
+ miSetExtents (temp);
+
+ return temp;
+}
+
+
/**
* gdk_region_rectangle:
* @rectangle: a #GdkRectangle
return TRUE;
}
+/**
+ * gdk_region_rect_equal:
+ * @region: a #GdkRegion
+ * @rectangle: a #GdkRectangle
+ *
+ * Finds out if a regions is the same as a rectangle.
+ *
+ * Returns: %TRUE if @region and @rectangle are equal.
+ *
+ * Since: 2.18
+ */
+gboolean
+gdk_region_rect_equal (const GdkRegion *region,
+ const GdkRectangle *rectangle)
+{
+ g_return_val_if_fail (region != NULL, FALSE);
+ g_return_val_if_fail (rectangle != NULL, FALSE);
+
+ if (region->numRects != 1) return FALSE;
+ else if (region->extents.x1 != rectangle->x) return FALSE;
+ else if (region->extents.y1 != rectangle->y) return FALSE;
+ else if (region->extents.x2 != rectangle->x + rectangle->width) return FALSE;
+ else if (region->extents.y2 != rectangle->y + rectangle->height) return FALSE;
+ return TRUE;
+}
+
/**
* gdk_region_point_in:
* @region: a #GdkRegion
gboolean gdk_region_empty (const GdkRegion *region);
gboolean gdk_region_equal (const GdkRegion *region1,
const GdkRegion *region2);
+gboolean gdk_region_rect_equal (const GdkRegion *region1,
+ const GdkRectangle *rectangle);
gboolean gdk_region_point_in (const GdkRegion *region,
int x,
int y);
GdkGC *normal_gcs[32];
GdkGC *exposure_gcs[32];
+ GdkGC *subwindow_gcs[32];
cairo_font_options_t *font_options;
double resolution; /* pixels/points scale factor for fonts */
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
#include "gdkpixmap.h"
#include "gdkdrawable.h"
#include "gdkscreen.h"
+#include "gdkmarshalers.h"
#include "gdkalias.h"
+#undef DEBUG_WINDOW_PRINTING
+
+#ifdef GDK_WINDOWING_X11
+#include "x11/gdkx.h" /* For workaround */
+#endif
+
+#include "math.h"
+
+/* Historically a GdkWindow always matches a platform native window,
+ * be it a toplevel window or a child window. In this setup the
+ * GdkWindow (and other GdkDrawables) were platform independent classes,
+ * and the actual platform specific implementation was in a delegate
+ * object availible as "impl" in the window object.
+ *
+ * With the addition of client side windows and offscreen windows this
+ * changes a bit. The application-visible GdkWindow object behaves as
+ * it did before, but not all such windows now have a corresponding native
+ * window. Instead windows that are "client side" are emulated by the gdk
+ * code such that clipping, drawing, moving, events etc work as expected.
+ *
+ * For GdkWindows that have a native window the "impl" object is the
+ * same as before. However, for all client side windows the impl object
+ * is shared with its parent (i.e. all client windows descendants of one
+ * native window has the same impl.
+ *
+ * Additionally there is a new type of platform independent impl object,
+ * GdkOffscreenWindow. All windows of type GDK_WINDOW_OFFSCREEN get an impl
+ * of this type (while their children are generally GDK_WINDOW_CHILD virtual
+ * windows). Such windows work by allocating a GdkPixmap as the backing store
+ * for drawing operations, which is resized with the window.
+ *
+ * GdkWindows have a pointer to the "impl window" they are in, i.e.
+ * the topmost GdkWindow which have the same "impl" value. This is stored
+ * in impl_window, which is different from the window itself only for client
+ * side windows.
+ * All GdkWindows (native or not) track the position of the window in the parent
+ * (x, y), the size of the window (width, height), the position of the window
+ * with respect to the impl window (abs_x, abs_y). We also track the clip
+ * region of the window wrt parent windows and siblings, in window-relative
+ * coordinates with and without child windows included (clip_region,
+ * clip_region_with_children).
+ *
+ * All toplevel windows are native windows, but also child windows can be
+ * native (although not children of offscreens). We always listen to
+ * a basic set of events (see get_native_event_mask) for these windows
+ * so that we can emulate events for any client side children.
+ *
+ * For native windows we apply the calculated clip region as a window shape
+ * so that eg. client side siblings that overlap the native child properly
+ * draws over the native child window.
+ *
+ * In order to minimize flicker and for performance we use a couple of cacheing
+ * tricks. First of all, every time we do a window to window copy area, for instance
+ * when moving a client side window or when scrolling/moving a region in a window
+ * we store this in outstanding_moves instead of applying immediately. We then
+ * delay this move until we really need it (because something depends on being
+ * able to read it), or until we're handing a redraw from an expose/invalidation
+ * (actually we delay it past redraw, but before blitting the double buffer pixmap
+ * to the window). This gives us two advantages. First of all it minimizes the time
+ * from the window is moved to the exposes related to that move, secondly it allows
+ * us to be smart about how to do the copy. We combine multiple moves into one (when
+ * possible) and we don't actually do copies to anything that is or will be
+ * invalidated and exposed anyway.
+ *
+ * Secondly, we use something called a "implicit paint" during repaint handling.
+ * An implicit paint is similar to a regular paint for the paint stack, but it is
+ * not put on the stack. Instead, it is set on the impl window, and later when
+ * regular gdk_window_begin_paint_region() happen on a window of this impl window
+ * we reuse the pixmap from the implicit paint. During repaint we create and at the
+ * end flush an implicit paint, which means we can collect all the paints on
+ * multiple client side windows in the same backing store pixmap.
+ *
+ * All drawing to windows are wrapped with macros that set up the GC such that
+ * the offsets and clip region is right for drawing to the paint object or
+ * directly to the emulated window. It also automatically handles any flushing
+ * needed when drawing directly to a window. Adding window/paint clipping is
+ * done using _gdk_gc_add_drawable_clip which lets us efficiently add and then
+ * remove a custom clip region.
+ */
+
#define USE_BACKING_STORE /* Appears to work on Win32, too, now. */
-typedef struct _GdkWindowPaint GdkWindowPaint;
+/* This adds a local value to the GdkVisibilityState enum */
+#define GDK_VISIBILITY_NOT_VIEWABLE 3
+
+enum {
+ GET_OFFSCREEN_PARENT,
+ PICK_OFFSCREEN_CHILD, /* only called if has_offscreen_children */
+ TO_PARENT,
+ FROM_PARENT,
+ LAST_SIGNAL
+};
struct _GdkWindowPaint
{
gint x_offset;
gint y_offset;
cairo_surface_t *surface;
+ guint uses_implicit : 1;
+ guint32 region_tag;
};
typedef struct {
- GdkRegion *old_region;
- gint old_clip_x_origin;
- gint old_clip_y_origin;
- gint x_offset;
- gint y_offset;
-} GdkWindowClipData;
-
-struct _GdkWindowRedirect
-{
- GdkWindowObject *redirected;
- GdkDrawable *pixmap;
- gint src_x;
- gint src_y;
- gint dest_x;
- gint dest_y;
- gint width;
- gint height;
-};
+ GdkRegion *dest_region; /* The destination region */
+ int dx, dy; /* The amount that the source was moved to reach dest_region */
+} GdkWindowRegionMove;
+
+
+/* Global info */
static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
- GdkGCValues *values,
- GdkGCValuesMask mask);
+ GdkGCValues *values,
+ GdkGCValuesMask mask);
static void gdk_window_draw_rectangle (GdkDrawable *drawable,
- GdkGC *gc,
- gboolean filled,
- gint x,
- gint y,
- gint width,
- gint height);
+ GdkGC *gc,
+ gboolean filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
static void gdk_window_draw_arc (GdkDrawable *drawable,
- GdkGC *gc,
- gboolean filled,
- gint x,
- gint y,
- gint width,
- gint height,
- gint angle1,
- gint angle2);
+ GdkGC *gc,
+ gboolean filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gint angle1,
+ gint angle2);
static void gdk_window_draw_polygon (GdkDrawable *drawable,
- GdkGC *gc,
- gboolean filled,
- GdkPoint *points,
- gint npoints);
+ GdkGC *gc,
+ gboolean filled,
+ GdkPoint *points,
+ gint npoints);
static void gdk_window_draw_text (GdkDrawable *drawable,
- GdkFont *font,
- GdkGC *gc,
- gint x,
- gint y,
- const gchar *text,
- gint text_length);
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const gchar *text,
+ gint text_length);
static void gdk_window_draw_text_wc (GdkDrawable *drawable,
- GdkFont *font,
- GdkGC *gc,
- gint x,
- gint y,
- const GdkWChar *text,
- gint text_length);
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const GdkWChar *text,
+ gint text_length);
static void gdk_window_draw_drawable (GdkDrawable *drawable,
- GdkGC *gc,
- GdkPixmap *src,
- gint xsrc,
- gint ysrc,
- gint xdest,
- gint ydest,
- gint width,
- gint height);
+ GdkGC *gc,
+ GdkPixmap *src,
+ GdkDrawable *original_src,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
static void gdk_window_draw_points (GdkDrawable *drawable,
- GdkGC *gc,
- GdkPoint *points,
- gint npoints);
+ GdkGC *gc,
+ GdkPoint *points,
+ gint npoints);
static void gdk_window_draw_segments (GdkDrawable *drawable,
- GdkGC *gc,
- GdkSegment *segs,
- gint nsegs);
+ GdkGC *gc,
+ GdkSegment *segs,
+ gint nsegs);
static void gdk_window_draw_lines (GdkDrawable *drawable,
GdkGC *gc,
GdkPoint *points,
PangoGlyphString *glyphs);
static void gdk_window_draw_image (GdkDrawable *drawable,
- GdkGC *gc,
- GdkImage *image,
- gint xsrc,
- gint ysrc,
- gint xdest,
- gint ydest,
- gint width,
- gint height);
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height);
static void gdk_window_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
gint height);
static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
+static cairo_surface_t *gdk_window_create_cairo_surface (GdkDrawable *drawable,
+ int width,
+ int height);
+static void gdk_window_set_cairo_clip (GdkDrawable *drawable,
+ cairo_t *cr);
static void gdk_window_real_get_size (GdkDrawable *drawable,
- gint *width,
- gint *height);
+ gint *width,
+ gint *height);
static GdkVisual* gdk_window_real_get_visual (GdkDrawable *drawable);
static gint gdk_window_real_get_depth (GdkDrawable *drawable);
GdkColormap *cmap);
static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
+static GdkDrawable* gdk_window_get_source_drawable (GdkDrawable *drawable);
static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
gint x,
gint y,
static void gdk_window_init (GdkWindowObject *window);
static void gdk_window_class_init (GdkWindowObjectClass *klass);
static void gdk_window_finalize (GObject *object);
-static void gdk_window_clear_backing_rect (GdkWindow *window,
- gint x,
- gint y,
- gint width,
- gint height);
-static void setup_redirect_clip (GdkWindow *window,
- GdkGC *gc,
- GdkWindowClipData *data);
-static void reset_redirect_clip (GdkWindow *offscreen,
- GdkGC *gc,
- GdkWindowClipData *data);
+static void gdk_window_clear_backing_region (GdkWindow *window,
+ GdkRegion *region);
static void gdk_window_redirect_free (GdkWindowRedirect *redirect);
static void apply_redirect_to_children (GdkWindowObject *private,
GdkWindowRedirect *redirect);
static void remove_redirect_from_children (GdkWindowObject *private,
GdkWindowRedirect *redirect);
-static GdkRegion *_gdk_window_calculate_full_clip_region (GdkWindow *window,
- GdkWindow *base_window,
- GdkGC *gc,
- gboolean do_children,
- gint *base_x_offset,
- gint *base_y_offset);
+
+static void recompute_visible_regions (GdkWindowObject *private,
+ gboolean recalculate_siblings,
+ gboolean recalculate_children);
+static void gdk_window_flush_outstanding_moves (GdkWindow *window);
+static void gdk_window_flush (GdkWindow *window);
+static void gdk_window_flush_recursive (GdkWindowObject *window);
+static void do_move_region_bits_on_impl (GdkWindowObject *private,
+ GdkRegion *region, /* In impl window coords */
+ int dx, int dy);
+static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
+static GdkWindow *gdk_window_get_offscreen_parent (GdkWindow *window);
+static void move_native_children (GdkWindowObject *private);
+static void update_cursor (GdkDisplay *display);
+static gboolean is_event_parent_of (GdkWindow *parent,
+ GdkWindow *child);
+
+static guint signals[LAST_SIGNAL] = { 0 };
static gpointer parent_class = NULL;
+static const cairo_user_data_key_t gdk_window_cairo_key;
+
+static guint32
+new_region_tag (void)
+{
+ static guint32 tag = 0;
+
+ return ++tag;
+}
+
GType
gdk_window_object_get_type (void)
{
sizeof (GdkWindowObject),
(GInstanceInitFunc) gdk_window_init,
0);
-
+
return object_type;
}
window->window_type = GDK_WINDOW_CHILD;
window->state = GDK_WINDOW_STATE_WITHDRAWN;
+ window->width = 1;
+ window->height = 1;
+ window->toplevel_window_type = -1;
+ /* starts hidden */
+ window->effective_visibility = GDK_VISIBILITY_NOT_VIEWABLE;
+ window->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
+ /* Default to unobscured since some backends don't send visibility events */
+ window->native_visibility = GDK_VISIBILITY_UNOBSCURED;
+}
+
+/* Stop and return on the first non-NULL parent */
+static gboolean
+accumulate_get_parent (GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ const GValue *handler_return,
+ gpointer data)
+{
+ g_value_copy (handler_return, return_accu);
+ /* Continue while returning NULL */
+ return g_value_get_object (handler_return) == NULL;
}
static GQuark quark_pointer_window = 0;
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
-
+
parent_class = g_type_class_peek_parent (klass);
object_class->finalize = gdk_window_finalize;
drawable_class->get_visual = gdk_window_real_get_visual;
drawable_class->_copy_to_image = gdk_window_copy_to_image;
drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
+ drawable_class->create_cairo_surface = gdk_window_create_cairo_surface;
+ drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
drawable_class->get_clip_region = gdk_window_get_clip_region;
drawable_class->get_visible_region = gdk_window_get_visible_region;
drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
+ drawable_class->get_source_drawable = gdk_window_get_source_drawable;
quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
+
+
+ signals[GET_OFFSCREEN_PARENT] =
+ g_signal_new (g_intern_static_string ("get-offscreen-parent"),
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ accumulate_get_parent, NULL,
+ gdk_marshal_OBJECT__VOID,
+ GDK_TYPE_WINDOW,
+ 0);
+ signals[PICK_OFFSCREEN_CHILD] =
+ g_signal_new (g_intern_static_string ("pick-offscreen-child"),
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ accumulate_get_parent, NULL,
+ gdk_marshal_OBJECT__DOUBLE_DOUBLE,
+ GDK_TYPE_WINDOW,
+ 2,
+ G_TYPE_DOUBLE,
+ G_TYPE_DOUBLE);
+ signals[TO_PARENT] =
+ g_signal_new (g_intern_static_string ("to-parent"),
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
+ G_TYPE_NONE,
+ 4,
+ G_TYPE_DOUBLE,
+ G_TYPE_DOUBLE,
+ G_TYPE_POINTER,
+ G_TYPE_POINTER);
+ signals[FROM_PARENT] =
+ g_signal_new (g_intern_static_string ("from-parent"),
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
+ G_TYPE_NONE,
+ 4,
+ G_TYPE_DOUBLE,
+ G_TYPE_DOUBLE,
+ G_TYPE_POINTER,
+ G_TYPE_POINTER);
}
static void
{
GdkWindow *window = GDK_WINDOW (object);
GdkWindowObject *obj = (GdkWindowObject *) object;
-
+
if (!GDK_WINDOW_DESTROYED (window))
{
if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
_gdk_window_destroy (window, TRUE);
}
- g_object_unref (obj->impl);
- obj->impl = NULL;
-
+ if (obj->impl)
+ {
+ g_object_unref (obj->impl);
+ obj->impl = NULL;
+ }
+
+ if (obj->impl_window != obj)
+ {
+ g_object_unref (obj->impl_window);
+ obj->impl_window = NULL;
+ }
+
+ if (obj->shape)
+ gdk_region_destroy (obj->shape);
+
+ if (obj->input_shape)
+ gdk_region_destroy (obj->input_shape);
+
+ if (obj->cursor)
+ gdk_cursor_unref (obj->cursor);
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
-/**
- * gdk_window_new:
- * @parent: a #GdkWindow, or %NULL to create the window as a child of
- * the default root window for the default display.
- * @attributes: attributes of the new window
- * @attributes_mask: mask indicating which fields in @attributes are valid
- *
- * Creates a new #GdkWindow using the attributes from
- * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
- * more details. Note: to use this on displays other than the default
- * display, @parent must be specified.
- *
- * Return value: the new #GdkWindow
- **/
-GdkWindow*
-gdk_window_new (GdkWindow *parent,
- GdkWindowAttr *attributes,
- gint attributes_mask)
+static gboolean
+gdk_window_is_offscreen (GdkWindowObject *window)
{
- GdkWindow *window;
- GdkWindowObject *private, *parent_private;
+ return GDK_WINDOW_TYPE (window) == GDK_WINDOW_OFFSCREEN;
+}
- g_return_val_if_fail (parent == NULL || GDK_IS_WINDOW (parent), NULL);
- g_return_val_if_fail (attributes != NULL, NULL);
+static GdkWindowObject *
+gdk_window_get_impl_window (GdkWindowObject *window)
+{
+ return window->impl_window;
+}
- window = _gdk_window_new (parent, attributes, attributes_mask);
- g_return_val_if_fail (window != NULL, window);
+GdkWindow *
+_gdk_window_get_impl_window (GdkWindow *window)
+{
+ return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
+}
- /* Inherit redirection from parent */
- if (parent != NULL)
- {
- parent_private = GDK_WINDOW_OBJECT (parent);
- private = GDK_WINDOW_OBJECT (window);
- private->redirect = parent_private->redirect;
- }
-
- return window;
+static gboolean
+gdk_window_has_impl (GdkWindowObject *window)
+{
+ return window->impl_window == window;
}
-/**
- * gdk_window_reparent:
- * @window: a #GdkWindow
- * @new_parent: new parent to move @window into
- * @x: X location inside the new parent
- * @y: Y location inside the new parent
- *
- * Reparents @window into the given @new_parent. The window being
- * reparented will be unmapped as a side effect.
- *
- **/
-void
-gdk_window_reparent (GdkWindow *window,
- GdkWindow *new_parent,
- gint x,
- gint y)
+gboolean
+_gdk_window_has_impl (GdkWindow *window)
{
- GdkWindowObject *private;
- gboolean show;
+ return gdk_window_has_impl ((GdkWindowObject *)window);
+}
- g_return_if_fail (GDK_IS_WINDOW (window));
- g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
- g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
+static gboolean
+gdk_window_has_no_impl (GdkWindowObject *window)
+{
+ return window->impl_window != window;
+}
- if (GDK_WINDOW_DESTROYED (window) ||
- (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
+static void
+remove_child_area (GdkWindowObject *private,
+ GdkWindowObject *until,
+ gboolean for_input,
+ GdkRegion *region)
+{
+ GdkWindowObject *child;
+ GdkRegion *child_region;
+ GdkRectangle r;
+ GList *l;
+ GdkRegion *shape;
+
+ for (l = private->children; l; l = l->next)
{
- return;
- }
+ child = l->data;
- private = (GdkWindowObject *) window;
+ if (child == until)
+ break;
+
+ if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
+ continue;
+
+ /* Ignore offscreen children, as they don't draw in their parent and
+ * don't take part in the clipping */
+ if (gdk_window_is_offscreen (child))
+ continue;
+
+ r.x = child->x;
+ r.y = child->y;
+ r.width = child->width;
+ r.height = child->height;
+
+ child_region = gdk_region_rectangle (&r);
+
+ if (child->shape)
+ gdk_region_intersect (child_region, child->shape);
+ else if (private->window_type == GDK_WINDOW_FOREIGN)
+ {
+ shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
+ if (shape)
+ {
+ gdk_region_intersect (child_region, shape);
+ gdk_region_destroy (shape);
+ }
+ }
+
+ if (for_input)
+ {
+ if (child->input_shape)
+ gdk_region_intersect (child_region, child->input_shape);
+ else if (private->window_type == GDK_WINDOW_FOREIGN)
+ {
+ shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
+ if (shape)
+ {
+ gdk_region_intersect (child_region, shape);
+ gdk_region_destroy (shape);
+ }
+ }
+ }
+
+ gdk_region_subtract (region, child_region);
+ gdk_region_destroy (child_region);
- /* Break up redirection if inherited */
- if (private->redirect && private->redirect->redirected != private)
- {
- remove_redirect_from_children (private, private->redirect);
- private->redirect = NULL;
}
-
- show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
+}
- /* Inherit parent redirect if we don't have our own */
- if (private->parent && private->redirect == NULL)
+static GdkVisibilityState
+effective_visibility (GdkWindowObject *private)
+{
+ GdkVisibilityState native;
+
+ if (!gdk_window_is_viewable ((GdkWindow *)private))
+ return GDK_VISIBILITY_NOT_VIEWABLE;
+
+ native = private->impl_window->native_visibility;
+
+ if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
+ private->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
+ return GDK_VISIBILITY_FULLY_OBSCURED;
+ else if (native == GDK_VISIBILITY_UNOBSCURED)
+ return private->visibility;
+ else /* native PARTIAL, private partial or unobscured */
+ return GDK_VISIBILITY_PARTIAL;
+}
+
+static void
+gdk_window_update_visibility (GdkWindowObject *private)
+{
+ GdkVisibilityState new_visibility;
+ GdkEvent *event;
+
+ new_visibility = effective_visibility (private);
+
+ if (new_visibility != private->effective_visibility)
{
- private->redirect = private->parent->redirect;
- apply_redirect_to_children (private, private->redirect);
- }
+ private->effective_visibility = new_visibility;
- if (show)
- gdk_window_show (window);
+ if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
+ private->event_mask & GDK_VISIBILITY_NOTIFY)
+ {
+ event = _gdk_make_event ((GdkWindow *)private, GDK_VISIBILITY_NOTIFY,
+ NULL, FALSE);
+ event->visibility.state = new_visibility;
+ }
+ }
}
static void
-window_remove_filters (GdkWindow *window)
+gdk_window_update_visibility_recursively (GdkWindowObject *private,
+ GdkWindowObject *only_for_impl)
{
- GdkWindowObject *obj = (GdkWindowObject*) window;
+ GdkWindowObject *child;
+ GList *l;
- if (obj->filters)
+ gdk_window_update_visibility (private);
+ for (l = private->children; l != NULL; l = l->next)
{
- GList *tmp_list;
-
- for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
- g_free (tmp_list->data);
-
- g_list_free (obj->filters);
- obj->filters = NULL;
+ child = l->data;
+ if ((only_for_impl == NULL) ||
+ (only_for_impl == child->impl_window))
+ gdk_window_update_visibility_recursively (child, only_for_impl);
}
}
-/**
- * _gdk_window_destroy_hierarchy:
- * @window: a #GdkWindow
- * @recursing: If TRUE, then this is being called because a parent
- * was destroyed. This generally means that the call to the
- * windowing system to destroy the window can be omitted, since
- * it will be destroyed as a result of the parent being destroyed.
- * Unless @foreign_destroy.
- * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
- * external agency. The window has already been destroyed and no
- * windowing system calls should be made. (This may never happen
- * for some windowing systems.)
- *
- * Internal function to destroy a window. Like gdk_window_destroy(),
- * but does not drop the reference count created by gdk_window_new().
- **/
static void
-_gdk_window_destroy_hierarchy (GdkWindow *window,
- gboolean recursing,
- gboolean foreign_destroy)
+recompute_visible_regions_internal (GdkWindowObject *private,
+ gboolean recalculate_clip,
+ gboolean recalculate_siblings,
+ gboolean recalculate_children)
{
- GdkWindowObject *private;
- GdkWindowObject *temp_private;
- GdkWindow *temp_window;
- GdkScreen *screen;
- GList *children;
- GList *tmp;
+ GdkRectangle r;
+ GList *l;
+ GdkWindowObject *child;
+ GdkRegion *new_clip, *old_clip_region_with_children;
+ gboolean clip_region_changed;
+ gboolean abs_pos_changed;
+ int old_abs_x, old_abs_y;
- g_return_if_fail (GDK_IS_WINDOW (window));
+ old_abs_x = private->abs_x;
+ old_abs_y = private->abs_y;
- private = (GdkWindowObject*) window;
-
- if (GDK_WINDOW_DESTROYED (window))
- return;
-
- screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
- temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
- if (temp_window == window)
- g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
+ /* Update absolute position */
+ if (gdk_window_has_impl (private))
+ {
+ /* Native window starts here */
+ private->abs_x = 0;
+ private->abs_y = 0;
+ }
+ else
+ {
+ private->abs_x = private->parent->abs_x + private->x;
+ private->abs_y = private->parent->abs_y + private->y;
+ }
- switch (GDK_WINDOW_TYPE (window))
+ abs_pos_changed =
+ private->abs_x != old_abs_x ||
+ private->abs_y != old_abs_y;
+
+ /* Update clip region based on:
+ * parent clip
+ * window size
+ * siblings in parents above window
+ */
+ clip_region_changed = FALSE;
+ if (recalculate_clip)
{
- case GDK_WINDOW_ROOT:
- if (!screen->closed)
- {
- g_error ("attempted to destroy root window");
- break;
- }
- /* else fall thru */
- case GDK_WINDOW_TOPLEVEL:
- case GDK_WINDOW_CHILD:
- case GDK_WINDOW_DIALOG:
- case GDK_WINDOW_TEMP:
- case GDK_WINDOW_FOREIGN:
- if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
+ /* Calculate visible region (sans children) in parent window coords */
+ r.x = private->x;
+ r.y = private->y;
+ r.width = private->width;
+ r.height = private->height;
+ new_clip = gdk_region_rectangle (&r);
+
+ if (private->parent != NULL && GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
{
- /* Logically, it probably makes more sense to send
- * a "destroy yourself" message to the foreign window
- * whether or not it's in our hierarchy; but for historical
- * reasons, we only send "destroy yourself" messages to
- * foreign windows in our hierarchy.
- */
- if (private->parent)
- _gdk_windowing_window_destroy_foreign (window);
+ gdk_region_intersect (new_clip, private->parent->clip_region);
- /* Also for historical reasons, we remove any filters
- * on a foreign window when it or a parent is destroyed;
- * this likely causes problems if two separate portions
- * of code are maintaining filter lists on a foreign window.
- */
- window_remove_filters (window);
+ /* Remove all overlapping children from parent */
+ remove_child_area (private->parent, private, FALSE, new_clip);
}
- else
- {
- private->state |= GDK_WINDOW_STATE_WITHDRAWN;
-
- if (private->parent)
- {
- GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
- if (parent_private->children)
- parent_private->children = g_list_remove (parent_private->children, window);
- }
- _gdk_window_clear_update_area (window);
- gdk_window_free_paint_stack (window);
-
- if (private->bg_pixmap &&
- private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
- private->bg_pixmap != GDK_NO_BG)
- {
- g_object_unref (private->bg_pixmap);
- private->bg_pixmap = NULL;
- }
-
- if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN)
- g_assert (private->children == NULL);
- else
- {
- children = tmp = private->children;
- private->children = NULL;
-
- while (tmp)
- {
- temp_window = tmp->data;
- tmp = tmp->next;
-
- temp_private = (GdkWindowObject*) temp_window;
- if (temp_private)
- _gdk_window_destroy_hierarchy (temp_window,
- TRUE, foreign_destroy);
- }
-
- g_list_free (children);
- }
-
- _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
- private->parent = NULL;
- private->destroyed = TRUE;
+ /* Convert from parent coords to window coords */
+ gdk_region_offset (new_clip, -private->x, -private->y);
- window_remove_filters (window);
+ if (private->shape)
+ gdk_region_intersect (new_clip, private->shape);
- gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
+ if (private->clip_region == NULL ||
+ !gdk_region_equal (private->clip_region, new_clip))
+ clip_region_changed = TRUE;
- /* If we own the redirect, free it */
- if (private->redirect && private->redirect->redirected == private)
- gdk_window_redirect_free (private->redirect);
+ if (private->clip_region)
+ gdk_region_destroy (private->clip_region);
+ private->clip_region = new_clip;
- private->redirect = NULL;
+ old_clip_region_with_children = private->clip_region_with_children;
+ private->clip_region_with_children = gdk_region_copy (private->clip_region);
+ remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
+
+ if (clip_region_changed ||
+ !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
+ private->clip_tag = new_region_tag ();
+
+ if (old_clip_region_with_children)
+ gdk_region_destroy (old_clip_region_with_children);
+ }
+
+ if (clip_region_changed)
+ {
+ GdkVisibilityState visibility;
+ gboolean fully_visible;
+
+ if (gdk_region_empty (private->clip_region))
+ visibility = GDK_VISIBILITY_FULLY_OBSCURED;
+ else {
+ if (private->shape)
+ fully_visible = gdk_region_equal (private->clip_region,
+ private->shape);
+ else
+ {
+ r.x = 0;
+ r.y = 0;
+ r.width = private->width;
+ r.height = private->height;
+ fully_visible = gdk_region_rect_equal (private->clip_region, &r);
+ }
+
+ if (fully_visible)
+ visibility = GDK_VISIBILITY_UNOBSCURED;
+ else
+ visibility = GDK_VISIBILITY_PARTIAL;
+ }
+
+ if (private->visibility != visibility)
+ {
+ private->visibility = visibility;
+ gdk_window_update_visibility (private);
}
- break;
}
-}
-/**
- * _gdk_window_destroy:
- * @window: a #GdkWindow
- * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
- * external agency. The window has already been destroyed and no
- * windowing system calls should be made. (This may never happen
- * for some windowing systems.)
- *
- * Internal function to destroy a window. Like gdk_window_destroy(),
- * but does not drop the reference count created by gdk_window_new().
- **/
-void
-_gdk_window_destroy (GdkWindow *window,
- gboolean foreign_destroy)
-{
- _gdk_window_destroy_hierarchy (window, FALSE, foreign_destroy);
+ /* Update all children, recursively. */
+ if (abs_pos_changed || clip_region_changed || recalculate_children)
+ {
+ for (l = private->children; l; l = l->next)
+ {
+ child = l->data;
+ /* Only recalculate clip if the the clip region changed, otherwise
+ * there is no way the child clip region could change (its has not e.g. moved)
+ * Except if recalculate_children is set to force child updates
+ */
+ recompute_visible_regions_internal (child, recalculate_clip && (clip_region_changed || recalculate_children), FALSE, FALSE);
+ }
+ }
+
+ if (clip_region_changed &&
+ gdk_window_has_impl (private) &&
+ /* Not for offscreens */
+ private->window_type != GDK_WINDOW_OFFSCREEN &&
+ /* or for non-shaped toplevels */
+ (private->shaped ||
+ (private->parent != NULL &&
+ GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)) &&
+ /* or for foreign windows */
+ GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN
+ )
+ {
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
+ }
+
+ if (recalculate_siblings &&
+ private->parent != NULL &&
+ GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+ {
+ /* If we moved a child window in parent or changed the stacking order, then we
+ * need to recompute the visible area of all the other children in the parent
+ */
+ for (l = private->parent->children; l; l = l->next)
+ {
+ child = l->data;
+
+ if (child != private)
+ recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
+ }
+
+ /* We also need to recompute the _with_children clip for the parent */
+ recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
+ }
+
+ if (private->cairo_surface)
+ {
+ int width, height;
+
+ /* It would be nice if we had some cairo support here so we
+ could set the clip rect on the cairo surface */
+ width = private->abs_x + private->width;
+ height = private->abs_y + private->height;
+
+ _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
+ width, height);
+ cairo_surface_set_device_offset (private->cairo_surface,
+ private->abs_x,
+ private->abs_y);
+ }
}
-/**
- * gdk_window_destroy:
- * @window: a #GdkWindow
+/* Call this when private has changed in one or more of these ways:
+ * size changed
+ * window moved
+ * new window added
+ * stacking order of window changed
+ * child deleted
*
- * Destroys the window system resources associated with @window and decrements @window's
- * reference count. The window system resources for all children of @window are also
- * destroyed, but the children's reference counts are not decremented.
+ * It will recalculate abs_x/y and the clip regions
*
- * Note that a window will not be destroyed automatically when its reference count
- * reaches zero. You must call this function yourself before that happens.
+ * Unless the window didn't change stacking order or size/pos, pass in TRUE
+ * for recalculate_siblings. (Mostly used internally for the recursion)
*
- **/
-void
-gdk_window_destroy (GdkWindow *window)
+ * If a child window was removed (and you can't use that child for
+ * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
+ */
+static void
+recompute_visible_regions (GdkWindowObject *private,
+ gboolean recalculate_siblings,
+ gboolean recalculate_children)
{
- _gdk_window_destroy_hierarchy (window, FALSE, FALSE);
- g_object_unref (window);
+ recompute_visible_regions_internal (private,
+ TRUE,
+ recalculate_siblings,
+ recalculate_children);
}
-/**
- * gdk_window_set_user_data:
- * @window: a #GdkWindow
- * @user_data: user data
- *
- * For most purposes this function is deprecated in favor of
- * g_object_set_data(). However, for historical reasons GTK+ stores
- * the #GtkWidget that owns a #GdkWindow as user data on the
- * #GdkWindow. So, custom widget implementations should use
- * this function for that. If GTK+ receives an event for a #GdkWindow,
- * and the user data for the window is non-%NULL, GTK+ will assume the
- * user data is a #GtkWidget, and forward the event to that widget.
- *
- **/
void
-gdk_window_set_user_data (GdkWindow *window,
- gpointer user_data)
+_gdk_window_update_size (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- ((GdkWindowObject*)window)->user_data = user_data;
+ recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
}
-/**
- * gdk_window_get_user_data:
- * @window: a #GdkWindow
- * @data: return location for user data
- *
- * Retrieves the user data for @window, which is normally the widget
- * that @window belongs to. See gdk_window_set_user_data().
- *
- **/
-void
-gdk_window_get_user_data (GdkWindow *window,
- gpointer *data)
+/* Find the native window that would be just above "child"
+ * in the native stacking order if "child" was a native window
+ * (it doesn't have to be native). If there is no such native
+ * window inside this native parent then NULL is returned.
+ * If child is NULL, find lowest native window in parent.
+ */
+static GdkWindowObject *
+find_native_sibling_above_helper (GdkWindowObject *parent,
+ GdkWindowObject *child)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
+ GdkWindowObject *w;
+ GList *l;
- *data = ((GdkWindowObject*)window)->user_data;
-}
+ if (child)
+ {
+ l = g_list_find (parent->children, child);
+ g_assert (l != NULL); /* Better be a child of its parent... */
+ l = l->prev; /* Start looking at the one above the child */
+ }
+ else
+ l = g_list_last (parent->children);
-/**
- * gdk_window_get_window_type:
- * @window: a #GdkWindow
- *
- * Gets the type of the window. See #GdkWindowType.
- *
- * Return value: type of window
- **/
-GdkWindowType
-gdk_window_get_window_type (GdkWindow *window)
-{
- g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
-
- return GDK_WINDOW_TYPE (window);
+ for (; l != NULL; l = l->prev)
+ {
+ w = l->data;
+
+ if (gdk_window_has_impl (w))
+ return w;
+
+ g_assert (parent != w);
+ w = find_native_sibling_above_helper (w, NULL);
+ if (w)
+ return w;
+ }
+
+ return NULL;
}
-/**
- * gdk_window_get_position:
- * @window: a #GdkWindow
- * @x: X coordinate of window
- * @y: Y coordinate of window
- *
- * Obtains the position of the window as reported in the
- * most-recently-processed #GdkEventConfigure. Contrast with
- * gdk_window_get_geometry() which queries the X server for the
- * current window position, regardless of which events have been
- * received or processed.
- *
- * The position coordinates are relative to the window's parent window.
- *
- **/
-void
-gdk_window_get_position (GdkWindow *window,
- gint *x,
- gint *y)
+
+static GdkWindowObject *
+find_native_sibling_above (GdkWindowObject *parent,
+ GdkWindowObject *child)
{
- GdkWindowObject *obj;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- obj = (GdkWindowObject*) window;
-
- if (x)
- *x = obj->x;
- if (y)
- *y = obj->y;
+ GdkWindowObject *w;
+
+ w = find_native_sibling_above_helper (parent, child);
+ if (w)
+ return w;
+
+ if (gdk_window_has_impl (parent))
+ return NULL;
+ else
+ return find_native_sibling_above (parent->parent, parent);
}
-/**
- * gdk_window_get_parent:
- * @window: a #GdkWindow
- *
- * Obtains the parent of @window, as known to GDK. Does not query the
- * X server; thus this returns the parent as passed to gdk_window_new(),
- * not the actual parent. This should never matter unless you're using
- * Xlib calls mixed with GDK calls on the X11 platform. It may also
- * matter for toplevel windows, because the window manager may choose
- * to reparent them.
- *
- * Return value: parent of @window
- **/
-GdkWindow*
-gdk_window_get_parent (GdkWindow *window)
+static GdkEventMask
+get_native_event_mask (GdkWindowObject *private)
{
- g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
-
- return (GdkWindow*) ((GdkWindowObject*) window)->parent;
+ if (private->window_type != GDK_WINDOW_ROOT &&
+ private->window_type != GDK_WINDOW_FOREIGN)
+ {
+ return
+ /* We need thse for all native window so we can emulate
+ events on children: */
+ GDK_EXPOSURE_MASK |
+ GDK_VISIBILITY_NOTIFY_MASK |
+ GDK_POINTER_MOTION_MASK |
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+ GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
+ GDK_SCROLL_MASK |
+ /* Then do whatever the app asks to, since the app
+ * may be asking for weird things for native windows,
+ * but filter out things that override the above
+ * requests somehow. */
+ (private->event_mask &
+ ~(GDK_POINTER_MOTION_HINT_MASK |
+ GDK_BUTTON_MOTION_MASK |
+ GDK_BUTTON1_MOTION_MASK |
+ GDK_BUTTON2_MOTION_MASK |
+ GDK_BUTTON3_MOTION_MASK));
+ }
+ else
+ return private->event_mask;
}
/**
- * gdk_window_get_toplevel:
- * @window: a #GdkWindow
- *
- * Gets the toplevel window that's an ancestor of @window.
- *
- * Return value: the toplevel window containing @window
+ * gdk_window_new:
+ * @parent: a #GdkWindow, or %NULL to create the window as a child of
+ * the default root window for the default display.
+ * @attributes: attributes of the new window
+ * @attributes_mask: mask indicating which fields in @attributes are valid
+ *
+ * Creates a new #GdkWindow using the attributes from
+ * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
+ * more details. Note: to use this on displays other than the default
+ * display, @parent must be specified.
+ *
+ * Return value: the new #GdkWindow
**/
GdkWindow*
-gdk_window_get_toplevel (GdkWindow *window)
+gdk_window_new (GdkWindow *parent,
+ GdkWindowAttr *attributes,
+ gint attributes_mask)
{
- GdkWindowObject *obj;
-
- g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+ GdkWindow *window;
+ GdkWindowObject *private;
+ GdkScreen *screen;
+ GdkVisual *visual;
+ int x, y;
+ gboolean native;
+ GdkEventMask event_mask;
+ GdkWindow *real_parent;
- obj = (GdkWindowObject *)window;
- while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
- obj = (GdkWindowObject *)obj->parent;
-
- return GDK_WINDOW (obj);
-}
+ g_return_val_if_fail (attributes != NULL, NULL);
-/**
- * gdk_window_get_children:
- * @window: a #GdkWindow
- *
- * Gets the list of children of @window known to GDK.
- * This function only returns children created via GDK,
- * so for example it's useless when used with the root window;
- * it only returns windows an application created itself.
- *
- * The returned list must be freed, but the elements in the
- * list need not be.
- *
- * Return value: list of child windows inside @window
- **/
-GList*
-gdk_window_get_children (GdkWindow *window)
-{
- g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+ if (!parent)
+ {
+ GDK_NOTE (MULTIHEAD,
+ g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
- if (GDK_WINDOW_DESTROYED (window))
- return NULL;
+ screen = gdk_screen_get_default ();
+ parent = gdk_screen_get_root_window (screen);
+ }
+ else
+ screen = gdk_drawable_get_screen (parent);
- return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
-}
+ g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
-/**
- * gdk_window_peek_children:
- * @window: a #GdkWindow
- *
- * Like gdk_window_get_children(), but does not copy the list of
- * children, so the list does not need to be freed.
- *
- * Return value: a reference to the list of child windows in @window
- **/
-GList *
-gdk_window_peek_children (GdkWindow *window)
-{
- g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+ if (GDK_WINDOW_DESTROYED (parent))
+ return NULL;
- if (GDK_WINDOW_DESTROYED (window))
- return NULL;
+ window = g_object_new (GDK_TYPE_WINDOW, NULL);
+ private = (GdkWindowObject *) window;
- return GDK_WINDOW_OBJECT (window)->children;
-}
+ /* Windows with a foreign parent are treated as if they are children
+ * of the root window, except for actual creation.
+ */
+ real_parent = parent;
+ if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
+ parent = gdk_screen_get_root_window (screen);
-/**
- * gdk_window_add_filter:
- * @window: a #GdkWindow
- * @function: filter callback
- * @data: data to pass to filter callback
- *
- * Adds an event filter to @window, allowing you to intercept events
- * before they reach GDK. This is a low-level operation and makes it
- * easy to break GDK and/or GTK+, so you have to know what you're
- * doing. Pass %NULL for @window to get all events for all windows,
- * instead of events for a specific window.
- *
- * See gdk_display_add_client_message_filter() if you are interested
- * in X ClientMessage events.
- **/
-void
-gdk_window_add_filter (GdkWindow *window,
- GdkFilterFunc function,
- gpointer data)
-{
- GdkWindowObject *private;
- GList *tmp_list;
- GdkEventFilter *filter;
-
- g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
+ private->parent = (GdkWindowObject *)parent;
- private = (GdkWindowObject*) window;
- if (private && GDK_WINDOW_DESTROYED (window))
- return;
-
- if (private)
- tmp_list = private->filters;
+ private->accept_focus = TRUE;
+ private->focus_on_map = TRUE;
+
+ if (attributes_mask & GDK_WA_X)
+ x = attributes->x;
else
- tmp_list = _gdk_default_filters;
-
- while (tmp_list)
+ 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);
+
+#ifdef GDK_WINDOWING_X11
+ /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
+ * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
+ */
+ if (attributes->wclass == GDK_INPUT_ONLY &&
+ GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT &&
+ !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
{
- filter = (GdkEventFilter *)tmp_list->data;
- if ((filter->function == function) && (filter->data == data))
- return;
- tmp_list = tmp_list->next;
+ g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
+ attributes->wclass = GDK_INPUT_OUTPUT;
+ }
+#endif
+
+ if (attributes->wclass == GDK_INPUT_ONLY)
+ {
+ /* Backwards compatiblity - we've always ignored
+ * attributes->window_type for input-only windows
+ * before
+ */
+ if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
+ private->window_type = GDK_WINDOW_TEMP;
+ else
+ private->window_type = GDK_WINDOW_CHILD;
}
-
- filter = g_new (GdkEventFilter, 1);
- filter->function = function;
- filter->data = data;
-
- if (private)
- private->filters = g_list_append (private->filters, filter);
else
- _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
-}
+ private->window_type = attributes->window_type;
-/**
- * gdk_window_remove_filter:
- * @window: a #GdkWindow
- * @function: previously-added filter function
- * @data: user data for previously-added filter function
- *
- * Remove a filter previously added with gdk_window_add_filter().
- *
- **/
-void
-gdk_window_remove_filter (GdkWindow *window,
- GdkFilterFunc function,
- gpointer data)
-{
- GdkWindowObject *private;
- GList *tmp_list, *node;
- GdkEventFilter *filter;
-
- g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
+ /* Sanity checks */
+ switch (private->window_type)
+ {
+ case GDK_WINDOW_TOPLEVEL:
+ case GDK_WINDOW_DIALOG:
+ case GDK_WINDOW_TEMP:
+ case GDK_WINDOW_OFFSCREEN:
+ if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
+ g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
+ "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
+ case GDK_WINDOW_CHILD:
+ break;
+ break;
+ default:
+ g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
+ return NULL;
+ }
- private = (GdkWindowObject*) window;
-
- if (private)
- tmp_list = private->filters;
+ if (attributes_mask & GDK_WA_VISUAL)
+ visual = attributes->visual;
else
- tmp_list = _gdk_default_filters;
-
- while (tmp_list)
+ visual = gdk_screen_get_system_visual (screen);
+
+ private->event_mask = attributes->event_mask;
+
+ if (attributes->wclass == GDK_INPUT_OUTPUT)
{
- filter = (GdkEventFilter *)tmp_list->data;
- node = tmp_list;
- tmp_list = tmp_list->next;
-
- if ((filter->function == function) && (filter->data == data))
+ private->input_only = FALSE;
+ private->depth = visual->depth;
+
+ private->bg_color.pixel = 0; // TODO: BlackPixel (xdisplay, screen_x11->screen_num);
+ private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
+
+ private->bg_pixmap = NULL;
+ }
+ else
+ {
+ private->depth = 0;
+ private->input_only = TRUE;
+ }
+
+ if (private->parent)
+ private->parent->children = g_list_prepend (private->parent->children, window);
+
+ native = FALSE; /* Default */
+ if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+ native = TRUE; /* Always use native windows for toplevels */
+ else if (!private->input_only &&
+ ((attributes_mask & GDK_WA_COLORMAP &&
+ attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
+ (attributes_mask & GDK_WA_VISUAL &&
+ attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
+ native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
+
+ if (private->window_type == GDK_WINDOW_OFFSCREEN)
+ {
+ _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
+ private->impl_window = private;
+ }
+ else if (native)
+ {
+ GdkWindowObject *above;
+ GList listhead = {0};
+
+ event_mask = get_native_event_mask (private);
+
+ /* Create the impl */
+ _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
+ private->impl_window = private;
+
+ /* This will put the native window topmost in the native parent, which may
+ * be wrong wrt other native windows in the non-native hierarchy, so restack */
+ above = find_native_sibling_above (private->parent, private);
+ if (above)
{
- if (private)
- private->filters = g_list_remove_link (private->filters, node);
- else
- _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
- g_list_free_1 (node);
- g_free (filter);
-
- return;
+ listhead.data = window;
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+ &listhead);
}
+
+ }
+ else
+ {
+ private->impl_window = g_object_ref (private->parent->impl_window);
+ private->impl = g_object_ref (private->impl_window->impl);
}
-}
-/**
- * gdk_screen_get_toplevel_windows:
- * @screen: The #GdkScreen where the toplevels are located.
- *
- * Obtains a list of all toplevel windows known to GDK on the screen @screen.
- * A toplevel window is a child of the root window (see
- * gdk_get_default_root_window()).
- *
- * The returned list should be freed with g_list_free(), but
- * its elements need not be freed.
- *
- * Return value: list of toplevel windows, free with g_list_free()
- *
- * Since: 2.2
- **/
-GList *
-gdk_screen_get_toplevel_windows (GdkScreen *screen)
-{
- GdkWindow * root_window;
- GList *new_list = NULL;
- GList *tmp_list;
-
- g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
-
- root_window = gdk_screen_get_root_window (screen);
+ recompute_visible_regions (private, TRUE, FALSE);
- tmp_list = ((GdkWindowObject *)root_window)->children;
- while (tmp_list)
+ if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
{
- if (GDK_WINDOW_TYPE (tmp_list->data) != GDK_WINDOW_FOREIGN)
- new_list = g_list_prepend (new_list, tmp_list->data);
- tmp_list = tmp_list->next;
+ /* Inherit redirection from parent */
+ private->redirect = private->parent->redirect;
}
-
- return new_list;
-}
-/**
- * gdk_window_get_toplevels:
- *
- * Obtains a list of all toplevel windows known to GDK on the default
- * screen (see gdk_screen_get_toplevel_windows()).
- * A toplevel window is a child of the root window (see
- * gdk_get_default_root_window()).
- *
- * The returned list should be freed with g_list_free(), but
- * its elements need not be freed.
- *
- * Return value: list of toplevel windows, free with g_list_free()
- *
- * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
- **/
-GList *
-gdk_window_get_toplevels (void)
-{
- return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
+ gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
+ (attributes->cursor) :
+ NULL));
+
+ return window;
}
-/**
- * gdk_window_is_visible:
- * @window: a #GdkWindow
- *
- * Checks whether the window has been mapped (with gdk_window_show() or
- * gdk_window_show_unraised()).
- *
- * Return value: %TRUE if the window is mapped
- **/
-gboolean
-gdk_window_is_visible (GdkWindow *window)
+static gboolean
+is_parent_of (GdkWindow *parent,
+ GdkWindow *child)
{
- g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-
- return GDK_WINDOW_IS_MAPPED (window);
+ GdkWindow *w;
+
+ w = child;
+ while (w != NULL)
+ {
+ if (w == parent)
+ return TRUE;
+
+ w = gdk_window_get_parent (w);
+ }
+
+ return FALSE;
}
-/**
- * gdk_window_is_viewable:
- * @window: a #GdkWindow
- *
- * 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.)
- *
- * Return value: %TRUE if the window is viewable
- **/
-gboolean
-gdk_window_is_viewable (GdkWindow *window)
+static void
+change_impl (GdkWindowObject *private,
+ GdkWindowObject *impl_window,
+ GdkDrawable *new)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkScreen *screen;
- GdkWindow *root_window;
+ GList *l;
+ GdkWindowObject *child;
+ GdkDrawable *old_impl;
+ GdkWindowObject *old_impl_window;
- g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+ old_impl = private->impl;
+ old_impl_window = private->impl_window;
+ if (private != impl_window)
+ private->impl_window = g_object_ref (impl_window);
+ else
+ private->impl_window = private;
+ private->impl = g_object_ref (new);
+ if (old_impl_window != private)
+ g_object_unref (old_impl_window);
+ g_object_unref (old_impl);
- screen = gdk_drawable_get_screen (window);
- root_window = gdk_screen_get_root_window (screen);
-
- while (private &&
- (private != (GdkWindowObject *)root_window) &&
- (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
+ for (l = private->children; l != NULL; l = l->next)
{
- if (GDK_WINDOW_DESTROYED (private) || !GDK_WINDOW_IS_MAPPED (private))
- return FALSE;
-
- private = (GdkWindowObject *)private->parent;
+ child = l->data;
+
+ if (child->impl == old_impl)
+ change_impl (child, impl_window, new);
}
-
- return TRUE;
}
-/**
- * gdk_window_get_state:
- * @window: a #GdkWindow
- *
- * Gets the bitwise OR of the currently active window state flags,
- * from the #GdkWindowState enumeration.
- *
- * Return value: window state bitfield
- **/
-GdkWindowState
-gdk_window_get_state (GdkWindow *window)
+static void
+reparent_to_impl (GdkWindowObject *private)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
-
- g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-
- return private->state;
+ GList *l;
+ GdkWindowObject *child;
+ gboolean show;
+
+ /* Enumerate in reverse order so we get the right order for the native
+ windows (first in childrens list is topmost, and reparent places on top) */
+ for (l = g_list_last (private->children); l != NULL; l = l->prev)
+ {
+ child = l->data;
+
+ if (child->impl == private->impl)
+ reparent_to_impl (child);
+ else
+ {
+ show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent ((GdkWindow *)child,
+ (GdkWindow *)private,
+ child->x, child->y);
+ if (show)
+ gdk_window_show_unraised ((GdkWindow *)child);
+ }
+ }
}
+
/**
- * gdk_window_begin_paint_rect:
+ * gdk_window_reparent:
* @window: a #GdkWindow
- * @rectangle: rectangle you intend to draw to
+ * @new_parent: new parent to move @window into
+ * @x: X location inside the new parent
+ * @y: Y location inside the new parent
+ *
+ * Reparents @window into the given @new_parent. The window being
+ * reparented will be unmapped as a side effect.
*
- * A convenience wrapper around gdk_window_begin_paint_region() which
- * creates a rectangular region for you. See
- * gdk_window_begin_paint_region() for details.
- *
**/
void
-gdk_window_begin_paint_rect (GdkWindow *window,
- const GdkRectangle *rectangle)
-{
- GdkRegion *region;
+gdk_window_reparent (GdkWindow *window,
+ GdkWindow *new_parent,
+ gint x,
+ gint y)
+{
+ GdkWindowObject *private;
+ GdkWindowObject *new_parent_private;
+ GdkWindowObject *old_parent;
+ gboolean show, was_toplevel, was_mapped;
+ gboolean do_reparent_to_impl;
g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
+ g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
- region = gdk_region_rectangle (rectangle);
- gdk_window_begin_paint_region (window, region);
- gdk_region_destroy (region);
-}
+ if (GDK_WINDOW_DESTROYED (window) ||
+ (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
+ return;
-#ifdef GDK_WINDOWING_X11
-#include "x11/gdkx.h"
-#endif
+ if (!new_parent)
+ new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
-/**
- * gdk_window_begin_paint_region:
- * @window: a #GdkWindow
- * @region: region you intend to draw to
- *
- * Indicates that you are beginning the process of redrawing @region.
- * A backing store (offscreen buffer) large enough to contain @region
- * will be created. The backing store will be initialized with the
- * background color or background pixmap for @window. Then, all
- * drawing operations performed on @window will be diverted to the
- * backing store. When you call gdk_window_end_paint(), the backing
- * store will be copied to @window, making it visible onscreen. Only
- * the part of @window contained in @region will be modified; that is,
- * drawing operations are clipped to @region.
- *
- * The net result of all this is to remove flicker, because the user
- * sees the finished product appear all at once when you call
- * gdk_window_end_paint(). If you draw to @window directly without
- * calling gdk_window_begin_paint_region(), the user may see flicker
- * as individual drawing operations are performed in sequence. The
- * clipping and background-initializing features of
- * gdk_window_begin_paint_region() are conveniences for the
- * programmer, so you can avoid doing that work yourself.
- *
- * When using GTK+, the widget system automatically places calls to
- * gdk_window_begin_paint_region() and gdk_window_end_paint() around
- * emissions of the expose_event signal. That is, if you're writing an
- * expose event handler, you can assume that the exposed area in
- * #GdkEventExpose has already been cleared to the window background,
- * is already set as the clip region, and already has a backing store.
- * Therefore in most cases, application code need not call
- * gdk_window_begin_paint_region(). (You can disable the automatic
- * calls around expose events on a widget-by-widget basis by calling
- * gtk_widget_set_double_buffered().)
- *
- * If you call this function multiple times before calling the
- * matching gdk_window_end_paint(), the backing stores are pushed onto
- * a stack. gdk_window_end_paint() copies the topmost backing store
- * onscreen, subtracts the topmost region from all other regions in
- * the stack, and pops the stack. All drawing operations affect only
- * the topmost backing store in the stack. One matching call to
- * gdk_window_end_paint() is required for each call to
- * gdk_window_begin_paint_region().
- *
- **/
-void
-gdk_window_begin_paint_region (GdkWindow *window,
- const GdkRegion *region)
-{
-#ifdef USE_BACKING_STORE
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkRectangle clip_box;
- GdkWindowPaint *paint;
- GSList *list;
+ private = (GdkWindowObject *) window;
+ new_parent_private = (GdkWindowObject *)new_parent;
- g_return_if_fail (GDK_IS_WINDOW (window));
+ /* No input-output children of input-only windows */
+ if (new_parent_private->input_only && !private->input_only)
+ return;
- if (GDK_WINDOW_DESTROYED (window))
+ /* Don't create loops in hierarchy */
+ if (is_parent_of (window, new_parent))
return;
- if (GDK_IS_PAINTABLE (private->impl))
+ if (private->cairo_surface)
{
- GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
+ /* This might be wrong in the new parent, e.g. for non-native surfaces.
+ To make sure we're ok, just wipe it. */
+ cairo_surface_finish (private->cairo_surface);
+ cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+ NULL, NULL);
+ }
- if (iface->begin_paint_region)
- iface->begin_paint_region ((GdkPaintable*)private->impl, region);
+ old_parent = private->parent;
- return;
+ /* Break up redirection if inherited */
+ if (private->redirect && private->redirect->redirected != private)
+ {
+ remove_redirect_from_children (private, private->redirect);
+ private->redirect = NULL;
}
- gdk_region_get_clipbox (region, &clip_box);
+ was_toplevel = private->parent == NULL;
+ was_mapped = GDK_WINDOW_IS_MAPPED (window);
+ show = FALSE;
- paint = g_new (GdkWindowPaint, 1);
- paint->region = gdk_region_copy (region);
- paint->x_offset = clip_box.x;
- paint->y_offset = clip_box.y;
- paint->pixmap =
- gdk_pixmap_new (window,
- MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
+ /* Reparenting to toplevel. Ensure we have a native window so this can work */
+ if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
+ new_parent_private->window_type == GDK_WINDOW_FOREIGN)
+ gdk_window_ensure_native (window);
- paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
- cairo_surface_set_device_offset (paint->surface,
- - paint->x_offset, - paint->y_offset);
-
- for (list = private->paint_stack; list != NULL; list = list->next)
+ do_reparent_to_impl = FALSE;
+ if (gdk_window_has_impl (private))
{
- GdkWindowPaint *tmp_paint = list->data;
+ /* Native window */
+ show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
+ }
+ else
+ {
+ /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
+ g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
+ new_parent_private->window_type != GDK_WINDOW_FOREIGN);
- gdk_region_subtract (tmp_paint->region, paint->region);
+ show = was_mapped;
+ gdk_window_hide (window);
+
+ do_reparent_to_impl = TRUE;
+ change_impl (private,
+ new_parent_private->impl_window,
+ new_parent_private->impl);
}
-
- private->paint_stack = g_slist_prepend (private->paint_stack, paint);
- if (!gdk_region_empty (region))
+ /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
+ * the root window
+ */
+ if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
{
- gdk_window_clear_backing_rect (window,
- clip_box.x, clip_box.y,
- clip_box.width, clip_box.height);
+ new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
+ new_parent_private = (GdkWindowObject *)new_parent;
}
-#endif /* USE_BACKING_STORE */
-}
-/**
- * gdk_window_end_paint:
- * @window: a #GdkWindow
- *
- * Indicates that the backing store created by the most recent call to
- * gdk_window_begin_paint_region() should be copied onscreen and
- * deleted, leaving the next-most-recent backing store or no backing
- * store at all as the active paint region. See
- * gdk_window_begin_paint_region() for full details. It is an error to
- * call this function without a matching
- * gdk_window_begin_paint_region() first.
- *
- **/
-void
-gdk_window_end_paint (GdkWindow *window)
-{
-#ifdef USE_BACKING_STORE
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkWindowObject *composited;
- GdkWindowPaint *paint;
- GdkGC *tmp_gc;
- GdkRectangle clip_box;
- gint x_offset, y_offset;
+ if (old_parent)
+ old_parent->children = g_list_remove (old_parent->children, window);
- g_return_if_fail (GDK_IS_WINDOW (window));
+ private->parent = new_parent_private;
+ private->x = x;
+ private->y = y;
- if (GDK_WINDOW_DESTROYED (window))
- return;
+ new_parent_private->children = g_list_prepend (new_parent_private->children, window);
- if (GDK_IS_PAINTABLE (private->impl))
+ /* Switch the window type as appropriate */
+
+ switch (GDK_WINDOW_TYPE (new_parent))
{
- GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
+ case GDK_WINDOW_ROOT:
+ case GDK_WINDOW_FOREIGN:
+ if (private->toplevel_window_type != -1)
+ GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
+ else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+ GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+ break;
+ case GDK_WINDOW_OFFSCREEN:
+ case GDK_WINDOW_TOPLEVEL:
+ case GDK_WINDOW_CHILD:
+ case GDK_WINDOW_DIALOG:
+ case GDK_WINDOW_TEMP:
+ if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
+ GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+ {
+ /* Save the original window type so we can restore it if the
+ * window is reparented back to be a toplevel
+ */
+ private->toplevel_window_type = GDK_WINDOW_TYPE (window);
+ GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
+ }
+ }
- if (iface->end_paint)
- iface->end_paint ((GdkPaintable*)private->impl);
- return;
+ /* We might have changed window type for a native windows, so we
+ need to change the event mask too. */
+ if (gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, get_native_event_mask (private));
+
+ /* Inherit parent redirect if we don't have our own */
+ if (private->parent && private->redirect == NULL)
+ {
+ private->redirect = private->parent->redirect;
+ apply_redirect_to_children (private, private->redirect);
}
- if (private->paint_stack == NULL)
+ recompute_visible_regions (private, TRUE, FALSE);
+ if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
+ recompute_visible_regions (old_parent, FALSE, TRUE);
+
+ if (do_reparent_to_impl)
+ reparent_to_impl (private);
+ else
{
- g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
- return;
+ GdkWindowObject *above;
+ GList listhead = {0};
+
+ /* The reparent will have put the native window topmost in the native parent,
+ * which may be wrong wrt other native windows in the non-native hierarchy,
+ * so restack */
+ above = find_native_sibling_above (private->parent, private);
+ if (above)
+ {
+ listhead.data = window;
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+ &listhead);
+ }
}
- paint = private->paint_stack->data;
- private->paint_stack = g_slist_delete_link (private->paint_stack,
- private->paint_stack);
+ if (show)
+ gdk_window_show_unraised (window);
+ else
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
- gdk_region_get_clipbox (paint->region, &clip_box);
+/**
+ * gdk_window_ensure_native:
+ * @window: a #GdkWindow
+ *
+ * Tries to ensure that there is a window-system native window for this
+ * GdkWindow. This may fail in some situations, returning %FALSE.
+ *
+ * Offscreen window and children of them can never have native windows.
+ *
+ * Some backends may not support native child windows.
+ *
+ * Returns: %TRUE if the window has a native window, %FALSE otherwise
+ *
+ * Since: 2.18
+ **/
+gboolean
+gdk_window_ensure_native (GdkWindow *window)
+{
+ GdkWindowObject *private;
+ GdkWindowObject *impl_window;
+ GdkDrawable *new_impl, *old_impl;
+ GdkScreen *screen;
+ GdkVisual *visual;
+ GdkWindowAttr attributes;
+ GdkWindowObject *above;
+ GList listhead;
- tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
+ g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, &x_offset, &y_offset);
+ if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
+ GDK_WINDOW_DESTROYED (window))
+ return FALSE;
- gdk_gc_set_clip_region (tmp_gc, paint->region);
- gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
+ private = (GdkWindowObject *) window;
- gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
- clip_box.x - paint->x_offset,
- clip_box.y - paint->y_offset,
- clip_box.x - x_offset, clip_box.y - y_offset,
- clip_box.width, clip_box.height);
+ impl_window = gdk_window_get_impl_window (private);
- if (private->redirect)
- {
- GdkWindowClipData data;
-
- setup_redirect_clip (window, tmp_gc, &data);
- gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
- clip_box.x - paint->x_offset,
- clip_box.y - paint->y_offset,
- clip_box.x + data.x_offset,
- clip_box.y + data.y_offset,
- clip_box.width, clip_box.height);
- reset_redirect_clip (window, tmp_gc, &data);
- }
-
- /* Reset clip region of the cached GdkGC */
- gdk_gc_set_clip_region (tmp_gc, NULL);
+ if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
+ return FALSE; /* native in offscreens not supported */
- cairo_surface_destroy (paint->surface);
- g_object_unref (paint->pixmap);
- gdk_region_destroy (paint->region);
- g_free (paint);
+ if (impl_window == private)
+ /* Already has an impl, and its not offscreen . */
+ return TRUE;
- /* find a composited window in our hierarchy to signal its
- * parent to redraw, calculating the clip box as we go...
- *
- * stop if parent becomes NULL since then we'd have nowhere
- * to draw (ie: 'composited' will always be non-NULL here).
- */
- for (composited = private;
- composited->parent;
- composited = composited->parent)
- {
- int width, height;
+ /* Need to create a native window */
- gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
- &width, &height);
+ screen = gdk_drawable_get_screen (window);
+ visual = gdk_drawable_get_visual (window);
- clip_box.x += composited->x;
- clip_box.y += composited->y;
- clip_box.width = MIN (clip_box.width, width - clip_box.x);
- clip_box.height = MIN (clip_box.height, height - clip_box.y);
+ attributes.colormap = gdk_drawable_get_colormap (window);
- if (composited->composited)
- {
- gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
- &clip_box, FALSE);
- break;
- }
- }
-#endif /* USE_BACKING_STORE */
-}
+ old_impl = private->impl;
+ _gdk_window_impl_new (window, (GdkWindow *)private->parent, screen, visual,
+ get_native_event_mask (private), &attributes, GDK_WA_COLORMAP);
+ new_impl = private->impl;
-static void
-gdk_window_free_paint_stack (GdkWindow *window)
-{
- GdkWindowObject *private = (GdkWindowObject *)window;
-
- if (private->paint_stack)
+ private->impl = old_impl;
+ change_impl (private, private, new_impl);
+
+ /* Native window creation will put the native window topmost in the
+ * native parent, which may be wrong wrt other native windows in the
+ * non-native hierarchy, so restack */
+ above = find_native_sibling_above (private->parent, private);
+ if (above)
{
- GSList *tmp_list = private->paint_stack;
+ listhead.data = window;
+ listhead.prev = NULL;
+ listhead.next = NULL;
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+ &listhead);
+ }
- while (tmp_list)
- {
- GdkWindowPaint *paint = tmp_list->data;
+ recompute_visible_regions (private, FALSE, FALSE);
- if (tmp_list == private->paint_stack)
- g_object_unref (paint->pixmap);
-
- gdk_region_destroy (paint->region);
- g_free (paint);
+ /* The shape may not have been set, as the clip region doesn't actually
+ change, so do it here manually */
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
- tmp_list = tmp_list->next;
- }
+ reparent_to_impl (private);
- g_slist_free (private->paint_stack);
- private->paint_stack = NULL;
+ if (!private->input_only)
+ {
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
+ if (private->bg_pixmap != NULL)
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
}
+
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
+
+ if (gdk_window_is_viewable (window))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, FALSE);
+
+ return TRUE;
}
static void
-gdk_window_get_offsets (GdkWindow *window,
- gint *x_offset,
- gint *y_offset)
+window_remove_filters (GdkWindow *window)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *obj = (GdkWindowObject*) window;
- if (private->paint_stack)
+ if (obj->filters)
{
- GdkWindowPaint *paint = private->paint_stack->data;
- *x_offset = paint->x_offset;
- *y_offset = paint->y_offset;
+ GList *tmp_list;
+
+ for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
+ g_free (tmp_list->data);
+
+ g_list_free (obj->filters);
+ obj->filters = NULL;
}
- else
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, x_offset, y_offset);
}
/**
- * gdk_window_get_internal_paint_info:
+ * _gdk_window_destroy_hierarchy:
* @window: a #GdkWindow
- * @real_drawable: location to store the drawable to which drawing should be
- * done.
- * @x_offset: location to store the X offset between coordinates in @window,
- * and the underlying window system primitive coordinates for
- * *@real_drawable.
- * @y_offset: location to store the Y offset between coordinates in @window,
- * and the underlying window system primitive coordinates for
- * *@real_drawable.
- *
- * If you bypass the GDK layer and use windowing system primitives to
- * draw directly onto a #GdkWindow, then you need to deal with two
- * details: there may be an offset between GDK coordinates and windowing
- * system coordinates, and GDK may have redirected drawing to a offscreen
- * pixmap as the result of a gdk_window_begin_paint_region() calls.
- * This function allows retrieving the information you need to compensate
- * for these effects.
+ * @recursing: If TRUE, then this is being called because a parent
+ * was destroyed.
+ * @recursing_native: If TRUE, then this is being called because a native parent
+ * was destroyed. This generally means that the call to the
+ * windowing system to destroy the window can be omitted, since
+ * it will be destroyed as a result of the parent being destroyed.
+ * Unless @foreign_destroy.
+ * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
+ * external agency. The window has already been destroyed and no
+ * windowing system calls should be made. (This may never happen
+ * for some windowing systems.)
*
- * This function exposes details of the GDK implementation, and is thus
- * likely to change in future releases of GDK.
+ * Internal function to destroy a window. Like gdk_window_destroy(),
+ * but does not drop the reference count created by gdk_window_new().
**/
-void
-gdk_window_get_internal_paint_info (GdkWindow *window,
- GdkDrawable **real_drawable,
- gint *x_offset,
- gint *y_offset)
+static void
+_gdk_window_destroy_hierarchy (GdkWindow *window,
+ gboolean recursing,
+ gboolean recursing_native,
+ gboolean foreign_destroy)
{
- gint x_off, y_off;
-
GdkWindowObject *private;
+ GdkWindowObject *temp_private;
+ GdkWindow *temp_window;
+ GdkScreen *screen;
+ GdkDisplay *display;
+ GList *children;
+ GList *tmp;
g_return_if_fail (GDK_IS_WINDOW (window));
- private = (GdkWindowObject *)window;
+ private = (GdkWindowObject*) window;
- if (real_drawable)
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ display = gdk_drawable_get_display (GDK_DRAWABLE (window));
+ screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
+ temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
+ if (temp_window == window)
+ g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
+
+
+ switch (GDK_WINDOW_TYPE (window))
{
- if (private->paint_stack)
+ case GDK_WINDOW_ROOT:
+ if (!screen->closed)
{
- GdkWindowPaint *paint = private->paint_stack->data;
- *real_drawable = paint->pixmap;
+ g_error ("attempted to destroy root window");
+ break;
+ }
+ /* else fall thru */
+ case GDK_WINDOW_TOPLEVEL:
+ case GDK_WINDOW_CHILD:
+ case GDK_WINDOW_DIALOG:
+ case GDK_WINDOW_TEMP:
+ case GDK_WINDOW_FOREIGN:
+ case GDK_WINDOW_OFFSCREEN:
+ if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
+ {
+ /* Logically, it probably makes more sense to send
+ * a "destroy yourself" message to the foreign window
+ * whether or not it's in our hierarchy; but for historical
+ * reasons, we only send "destroy yourself" messages to
+ * foreign windows in our hierarchy.
+ */
+ if (private->parent)
+ _gdk_windowing_window_destroy_foreign (window);
+
+ /* Also for historical reasons, we remove any filters
+ * on a foreign window when it or a parent is destroyed;
+ * this likely causes problems if two separate portions
+ * of code are maintaining filter lists on a foreign window.
+ */
+ window_remove_filters (window);
}
else
- *real_drawable = window;
- }
+ {
+ if (private->parent)
+ {
+ GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
- gdk_window_get_offsets (window, &x_off, &y_off);
+ if (parent_private->children)
+ parent_private->children = g_list_remove (parent_private->children, window);
- if (x_offset)
- *x_offset = x_off;
- if (y_offset)
- *y_offset = y_off;
-}
+ if (!recursing &&
+ GDK_WINDOW_IS_MAPPED (window))
+ {
+ recompute_visible_regions (private, TRUE, FALSE);
+ gdk_window_invalidate_in_parent (private);
+ }
+ }
-#define OFFSET_GC(gc) \
- gint x_offset, y_offset; \
- gint old_clip_x = gc->clip_x_origin; \
- gint old_clip_y = gc->clip_y_origin; \
- gint old_ts_x = gc->ts_x_origin; \
- gint old_ts_y = gc->ts_y_origin; \
- gdk_window_get_offsets (drawable, &x_offset, &y_offset); \
- if (x_offset != 0 || y_offset != 0) \
- { \
- gdk_gc_set_clip_origin (gc, old_clip_x - x_offset, \
- old_clip_y - y_offset); \
- gdk_gc_set_ts_origin (gc, old_ts_x - x_offset, \
- old_ts_y - y_offset); \
- }
-
-#define RESTORE_GC(gc) \
- if (x_offset != 0 || y_offset != 0) \
- { \
- gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
- gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
- }
+ gdk_window_free_paint_stack (window);
-static GdkGC *
-gdk_window_create_gc (GdkDrawable *drawable,
- GdkGCValues *values,
- GdkGCValuesMask mask)
-{
- g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
-
- if (GDK_WINDOW_DESTROYED (drawable))
- return NULL;
+ if (private->bg_pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG)
+ {
+ g_object_unref (private->bg_pixmap);
+ private->bg_pixmap = NULL;
+ }
- return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
- values, mask);
-}
+ if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN)
+ g_assert (private->children == NULL);
+ else
+ {
+ children = tmp = private->children;
+ private->children = NULL;
-static void
-gdk_window_draw_rectangle (GdkDrawable *drawable,
- GdkGC *gc,
- gboolean filled,
- gint x,
- gint y,
- gint width,
- gint height)
-{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
- OFFSET_GC (gc);
+ while (tmp)
+ {
+ temp_window = tmp->data;
+ tmp = tmp->next;
- if (GDK_WINDOW_DESTROYED (drawable))
- return;
-
- if (private->paint_stack)
- {
- GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_rectangle (paint->pixmap, gc, filled,
- x - x_offset, y - y_offset, width, height);
- }
- else
- gdk_draw_rectangle (private->impl, gc, filled,
- x - x_offset, y - y_offset, width, height);
+ temp_private = (GdkWindowObject*) temp_window;
+ if (temp_private)
+ _gdk_window_destroy_hierarchy (temp_window,
+ TRUE,
+ recursing_native || gdk_window_has_impl (private),
+ foreign_destroy);
+ }
- RESTORE_GC (gc);
-}
+ g_list_free (children);
+ }
-static void
-gdk_window_draw_arc (GdkDrawable *drawable,
- GdkGC *gc,
- gboolean filled,
- gint x,
- gint y,
- gint width,
- gint height,
- gint angle1,
- gint angle2)
-{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
- OFFSET_GC (gc);
+ _gdk_window_clear_update_area (window);
- if (GDK_WINDOW_DESTROYED (drawable))
- return;
-
- if (private->paint_stack)
- {
- GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_arc (paint->pixmap, gc, filled,
- x - x_offset, y - y_offset,
- width, height, angle1, angle2);
- }
- else
- gdk_draw_arc (private->impl, gc, filled,
- x - x_offset, y - y_offset,
- width, height, angle1, angle2);
- RESTORE_GC (gc);
-}
+ if (private->cairo_surface)
+ {
+ cairo_surface_finish (private->cairo_surface);
+ cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+ NULL, NULL);
+ }
-static void
-gdk_window_draw_polygon (GdkDrawable *drawable,
- GdkGC *gc,
- gboolean filled,
- GdkPoint *points,
- gint npoints)
-{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
- GdkPoint *new_points;
-
- OFFSET_GC (gc);
- if (GDK_WINDOW_DESTROYED (drawable))
- return;
-
- if (x_offset != 0 || y_offset != 0)
- {
- int i;
-
- new_points = g_new (GdkPoint, npoints);
- for (i=0; i<npoints; i++)
- {
- new_points[i].x = points[i].x - x_offset;
- new_points[i].y = points[i].y - y_offset;
- }
- }
- else
- new_points = points;
+ if (private->extension_events)
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_window_destroy (window);
- if (private->paint_stack)
- {
- GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_polygon (paint->pixmap, gc, filled, new_points, npoints);
+ if (gdk_window_has_impl (private))
+ {
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->destroy (window, recursing_native, foreign_destroy);
+ }
+ else
+ {
+ /* hide to make sure we repaint and break grabs */
+ gdk_window_hide (window);
+ }
- }
- else
- gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
-
- if (new_points != points)
- g_free (new_points);
+ private->state |= GDK_WINDOW_STATE_WITHDRAWN;
+ private->parent = NULL;
+ private->destroyed = TRUE;
- RESTORE_GC (gc);
-}
+ window_remove_filters (window);
-static void
-gdk_window_draw_text (GdkDrawable *drawable,
- GdkFont *font,
- GdkGC *gc,
- gint x,
- gint y,
- const gchar *text,
- gint text_length)
-{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
- OFFSET_GC (gc);
+ gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
- if (GDK_WINDOW_DESTROYED (drawable))
- return;
-
- if (private->paint_stack)
- {
- GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_text (paint->pixmap, font, gc,
- x - x_offset, y - y_offset, text, text_length);
+ /* If we own the redirect, free it */
+ if (private->redirect && private->redirect->redirected == private)
+ gdk_window_redirect_free (private->redirect);
- }
- else
- gdk_draw_text (private->impl, font, gc,
- x - x_offset, y - y_offset, text, text_length);
+ private->redirect = NULL;
- RESTORE_GC (gc);
+ if (display->pointer_info.toplevel_under_pointer == window)
+ {
+ g_object_unref (display->pointer_info.toplevel_under_pointer);
+ display->pointer_info.toplevel_under_pointer = NULL;
+ }
+ }
+ break;
+ }
}
-static void
-gdk_window_draw_text_wc (GdkDrawable *drawable,
- GdkFont *font,
- GdkGC *gc,
- gint x,
- gint y,
- const GdkWChar *text,
- gint text_length)
-{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
- OFFSET_GC (gc);
-
- if (GDK_WINDOW_DESTROYED (drawable))
- return;
-
+/**
+ * _gdk_window_destroy:
+ * @window: a #GdkWindow
+ * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
+ * external agency. The window has already been destroyed and no
+ * windowing system calls should be made. (This may never happen
+ * for some windowing systems.)
+ *
+ * Internal function to destroy a window. Like gdk_window_destroy(),
+ * but does not drop the reference count created by gdk_window_new().
+ **/
+void
+_gdk_window_destroy (GdkWindow *window,
+ gboolean foreign_destroy)
+{
+ _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
+}
+
+/**
+ * gdk_window_destroy:
+ * @window: a #GdkWindow
+ *
+ * Destroys the window system resources associated with @window and decrements @window's
+ * reference count. The window system resources for all children of @window are also
+ * destroyed, but the children's reference counts are not decremented.
+ *
+ * Note that a window will not be destroyed automatically when its reference count
+ * reaches zero. You must call this function yourself before that happens.
+ *
+ **/
+void
+gdk_window_destroy (GdkWindow *window)
+{
+ _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
+ g_object_unref (window);
+}
+
+/**
+ * gdk_window_set_user_data:
+ * @window: a #GdkWindow
+ * @user_data: user data
+ *
+ * For most purposes this function is deprecated in favor of
+ * g_object_set_data(). However, for historical reasons GTK+ stores
+ * the #GtkWidget that owns a #GdkWindow as user data on the
+ * #GdkWindow. So, custom widget implementations should use
+ * this function for that. If GTK+ receives an event for a #GdkWindow,
+ * and the user data for the window is non-%NULL, GTK+ will assume the
+ * user data is a #GtkWidget, and forward the event to that widget.
+ *
+ **/
+void
+gdk_window_set_user_data (GdkWindow *window,
+ gpointer user_data)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ ((GdkWindowObject*)window)->user_data = user_data;
+}
+
+/**
+ * gdk_window_get_user_data:
+ * @window: a #GdkWindow
+ * @data: return location for user data
+ *
+ * Retrieves the user data for @window, which is normally the widget
+ * that @window belongs to. See gdk_window_set_user_data().
+ *
+ **/
+void
+gdk_window_get_user_data (GdkWindow *window,
+ gpointer *data)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ *data = ((GdkWindowObject*)window)->user_data;
+}
+
+/**
+ * gdk_window_get_window_type:
+ * @window: a #GdkWindow
+ *
+ * Gets the type of the window. See #GdkWindowType.
+ *
+ * Return value: type of window
+ **/
+GdkWindowType
+gdk_window_get_window_type (GdkWindow *window)
+{
+ g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
+
+ return GDK_WINDOW_TYPE (window);
+}
+
+/**
+ * gdk_window_get_position:
+ * @window: a #GdkWindow
+ * @x: X coordinate of window
+ * @y: Y coordinate of window
+ *
+ * Obtains the position of the window as reported in the
+ * most-recently-processed #GdkEventConfigure. Contrast with
+ * gdk_window_get_geometry() which queries the X server for the
+ * current window position, regardless of which events have been
+ * received or processed.
+ *
+ * The position coordinates are relative to the window's parent window.
+ *
+ **/
+void
+gdk_window_get_position (GdkWindow *window,
+ gint *x,
+ gint *y)
+{
+ GdkWindowObject *obj;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ obj = (GdkWindowObject*) window;
+
+ if (x)
+ *x = obj->x;
+ if (y)
+ *y = obj->y;
+}
+
+/**
+ * gdk_window_get_parent:
+ * @window: a #GdkWindow
+ *
+ * Obtains the parent of @window, as known to GDK. Does not query the
+ * X server; thus this returns the parent as passed to gdk_window_new(),
+ * not the actual parent. This should never matter unless you're using
+ * Xlib calls mixed with GDK calls on the X11 platform. It may also
+ * matter for toplevel windows, because the window manager may choose
+ * to reparent them.
+ *
+ * Return value: parent of @window
+ **/
+GdkWindow*
+gdk_window_get_parent (GdkWindow *window)
+{
+ g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+ return (GdkWindow*) ((GdkWindowObject*) window)->parent;
+}
+
+/**
+ * gdk_window_get_toplevel:
+ * @window: a #GdkWindow
+ *
+ * Gets the toplevel window that's an ancestor of @window.
+ *
+ * Any window type but %GDK_WINDOW_CHILD is considered a
+ * toplevel window, as is a %GDK_WINDOW_CHILD window that
+ * has a root window as parent.
+ *
+ * Return value: the toplevel window containing @window
+ **/
+GdkWindow*
+gdk_window_get_toplevel (GdkWindow *window)
+{
+ GdkWindowObject *obj;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+ obj = (GdkWindowObject *)window;
+
+ while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
+ {
+ if (obj->parent == NULL ||
+ GDK_WINDOW_TYPE (obj->parent) == GDK_WINDOW_ROOT)
+ break;
+ obj = obj->parent;
+ }
+
+ return GDK_WINDOW (obj);
+}
+
+/**
+ * gdk_window_get_children:
+ * @window: a #GdkWindow
+ *
+ * Gets the list of children of @window known to GDK.
+ * This function only returns children created via GDK,
+ * so for example it's useless when used with the root window;
+ * it only returns windows an application created itself.
+ *
+ * The returned list must be freed, but the elements in the
+ * list need not be.
+ *
+ * Return value: list of child windows inside @window
+ **/
+GList*
+gdk_window_get_children (GdkWindow *window)
+{
+ g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return NULL;
+
+ return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
+}
+
+/**
+ * gdk_window_peek_children:
+ * @window: a #GdkWindow
+ *
+ * Like gdk_window_get_children(), but does not copy the list of
+ * children, so the list does not need to be freed.
+ *
+ * Return value: a reference to the list of child windows in @window
+ **/
+GList *
+gdk_window_peek_children (GdkWindow *window)
+{
+ g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return NULL;
+
+ return GDK_WINDOW_OBJECT (window)->children;
+}
+
+/**
+ * gdk_window_add_filter:
+ * @window: a #GdkWindow
+ * @function: filter callback
+ * @data: data to pass to filter callback
+ *
+ * Adds an event filter to @window, allowing you to intercept events
+ * before they reach GDK. This is a low-level operation and makes it
+ * easy to break GDK and/or GTK+, so you have to know what you're
+ * doing. Pass %NULL for @window to get all events for all windows,
+ * instead of events for a specific window.
+ *
+ * See gdk_display_add_client_message_filter() if you are interested
+ * in X ClientMessage events.
+ **/
+void
+gdk_window_add_filter (GdkWindow *window,
+ GdkFilterFunc function,
+ gpointer data)
+{
+ GdkWindowObject *private;
+ GList *tmp_list;
+ GdkEventFilter *filter;
+
+ g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject*) window;
+ if (private && GDK_WINDOW_DESTROYED (window))
+ return;
+
+ /* Filters are for the native events on the native window, so
+ ensure there is a native window. */
+ if (window)
+ gdk_window_ensure_native (window);
+
+ if (private)
+ tmp_list = private->filters;
+ else
+ tmp_list = _gdk_default_filters;
+
+ while (tmp_list)
+ {
+ filter = (GdkEventFilter *)tmp_list->data;
+ if ((filter->function == function) && (filter->data == data))
+ return;
+ tmp_list = tmp_list->next;
+ }
+
+ filter = g_new (GdkEventFilter, 1);
+ filter->function = function;
+ filter->data = data;
+
+ if (private)
+ private->filters = g_list_append (private->filters, filter);
+ else
+ _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
+}
+
+/**
+ * gdk_window_remove_filter:
+ * @window: a #GdkWindow
+ * @function: previously-added filter function
+ * @data: user data for previously-added filter function
+ *
+ * Remove a filter previously added with gdk_window_add_filter().
+ *
+ **/
+void
+gdk_window_remove_filter (GdkWindow *window,
+ GdkFilterFunc function,
+ gpointer data)
+{
+ GdkWindowObject *private;
+ GList *tmp_list, *node;
+ GdkEventFilter *filter;
+
+ g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject*) window;
+
+ if (private)
+ tmp_list = private->filters;
+ else
+ tmp_list = _gdk_default_filters;
+
+ 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, node);
+ else
+ _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
+ g_list_free_1 (node);
+ g_free (filter);
+
+ return;
+ }
+ }
+}
+
+/**
+ * gdk_screen_get_toplevel_windows:
+ * @screen: The #GdkScreen where the toplevels are located.
+ *
+ * Obtains a list of all toplevel windows known to GDK on the screen @screen.
+ * A toplevel window is a child of the root window (see
+ * gdk_get_default_root_window()).
+ *
+ * The returned list should be freed with g_list_free(), but
+ * its elements need not be freed.
+ *
+ * Return value: list of toplevel windows, free with g_list_free()
+ *
+ * Since: 2.2
+ **/
+GList *
+gdk_screen_get_toplevel_windows (GdkScreen *screen)
+{
+ GdkWindow * root_window;
+ GList *new_list = NULL;
+ GList *tmp_list;
+
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ root_window = gdk_screen_get_root_window (screen);
+
+ tmp_list = ((GdkWindowObject *)root_window)->children;
+ while (tmp_list)
+ {
+ if (GDK_WINDOW_TYPE (tmp_list->data) != GDK_WINDOW_FOREIGN)
+ new_list = g_list_prepend (new_list, tmp_list->data);
+ tmp_list = tmp_list->next;
+ }
+
+ return new_list;
+}
+
+/**
+ * gdk_window_get_toplevels:
+ *
+ * Obtains a list of all toplevel windows known to GDK on the default
+ * screen (see gdk_screen_get_toplevel_windows()).
+ * A toplevel window is a child of the root window (see
+ * gdk_get_default_root_window()).
+ *
+ * The returned list should be freed with g_list_free(), but
+ * its elements need not be freed.
+ *
+ * Return value: list of toplevel windows, free with g_list_free()
+ *
+ * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
+ **/
+GList *
+gdk_window_get_toplevels (void)
+{
+ return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
+}
+
+/**
+ * gdk_window_is_visible:
+ * @window: a #GdkWindow
+ *
+ * Checks whether the window has been mapped (with gdk_window_show() or
+ * gdk_window_show_unraised()).
+ *
+ * Return value: %TRUE if the window is mapped
+ **/
+gboolean
+gdk_window_is_visible (GdkWindow *window)
+{
+ g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+ return GDK_WINDOW_IS_MAPPED (window);
+}
+
+/**
+ * gdk_window_is_viewable:
+ * @window: a #GdkWindow
+ *
+ * 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.)
+ *
+ * Return value: %TRUE if the window is viewable
+ **/
+gboolean
+gdk_window_is_viewable (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkScreen *screen;
+ GdkWindow *root_window;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+ screen = gdk_drawable_get_screen (window);
+ root_window = gdk_screen_get_root_window (screen);
+
+ while (private &&
+ (private != (GdkWindowObject *)root_window) &&
+ (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
+ {
+ if (GDK_WINDOW_DESTROYED (private) || !GDK_WINDOW_IS_MAPPED (private))
+ return FALSE;
+
+ private = (GdkWindowObject *)private->parent;
+ }
+
+ return TRUE;
+}
+
+/**
+ * gdk_window_get_state:
+ * @window: a #GdkWindow
+ *
+ * Gets the bitwise OR of the currently active window state flags,
+ * from the #GdkWindowState enumeration.
+ *
+ * Return value: window state bitfield
+ **/
+GdkWindowState
+gdk_window_get_state (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+ return private->state;
+}
+
+
+/* This creates an empty "implicit" paint region for the impl window.
+ * By itself this does nothing, but real paints to this window
+ * or children of it can use this pixmap as backing to avoid allocating
+ * multiple pixmaps for subwindow rendering. When doing so they
+ * add to the region of the implicit paint region, which will be
+ * pushed to the window when the implicit paint region is ended.
+ * Such paints should not copy anything to the window on paint end, but
+ * should rely on the implicit paint end.
+ * The implicit paint will be automatically ended if someone draws
+ * directly to the window or a child window.
+ */
+static gboolean
+gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowPaint *paint;
+
+ g_assert (gdk_window_has_impl (private));
+
+ if (GDK_IS_PAINTABLE (private->impl))
+ return FALSE; /* Implementation does double buffering */
+
+ if (private->paint_stack != NULL ||
+ private->implicit_paint != NULL)
+ return FALSE; /* Don't stack implicit paints */
+
+ paint = g_new (GdkWindowPaint, 1);
+ paint->region = gdk_region_new (); /* Empty */
+ paint->x_offset = rect->x;
+ paint->y_offset = rect->y;
+ paint->uses_implicit = FALSE;
+ paint->surface = NULL;
+ paint->pixmap =
+ gdk_pixmap_new (window,
+ MAX (rect->width, 1), MAX (rect->height, 1), -1);
+
+ private->implicit_paint = paint;
+
+ return TRUE;
+}
+
+/* Ensure that all content related to this (sub)window is pushed to the
+ native region. If there is an active paint then that area is not
+ pushed, in order to not show partially finished double buffers. */
+static void
+gdk_window_flush_implicit_paint (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
+ GdkWindowPaint *paint;
+ GdkRegion *region;
+ GdkGC *tmp_gc;
+ GSList *list;
+
+ impl_window = gdk_window_get_impl_window (private);
+ if (impl_window->implicit_paint == NULL)
+ return;
+
+ paint = impl_window->implicit_paint;
+ region = gdk_region_copy (private->clip_region_with_children);
+
+ /* Don't flush active double buffers, as that may show partially done
+ * rendering */
+ for (list = private->paint_stack; list != NULL; list = list->next)
+ {
+ GdkWindowPaint *tmp_paint = list->data;
+
+ gdk_region_subtract (region, tmp_paint->region);
+ }
+
+ gdk_region_offset (region, private->abs_x, private->abs_y);
+ gdk_region_intersect (region, paint->region);
+
+ if (!gdk_region_empty (region))
+ {
+ /* Some regions are valid, push these to window now */
+ tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
+ _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
+ gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+ 0, 0, paint->x_offset, paint->y_offset, -1, -1);
+ /* Reset clip region of the cached GdkGC */
+ gdk_gc_set_clip_region (tmp_gc, NULL);
+
+ /* Remove flushed region from the implicit paint */
+ gdk_region_subtract (paint->region, region);
+ }
+ else
+ gdk_region_destroy (region);
+}
+
+/* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
+static void
+gdk_window_end_implicit_paint (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowPaint *paint;
+ GdkGC *tmp_gc;
+
+ g_assert (gdk_window_has_impl (private));
+
+ g_assert (private->implicit_paint != NULL);
+
+ paint = private->implicit_paint;
+
+ private->implicit_paint = NULL;
+
+ if (!gdk_region_empty (paint->region))
+ {
+ /* Some regions are valid, push these to window now */
+ tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
+ _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
+ gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+ 0, 0, paint->x_offset, paint->y_offset, -1, -1);
+ /* Reset clip region of the cached GdkGC */
+ gdk_gc_set_clip_region (tmp_gc, NULL);
+ }
+
+ g_object_unref (paint->pixmap);
+ g_free (paint);
+}
+
+/**
+ * gdk_window_begin_paint_rect:
+ * @window: a #GdkWindow
+ * @rectangle: rectangle you intend to draw to
+ *
+ * A convenience wrapper around gdk_window_begin_paint_region() which
+ * creates a rectangular region for you. See
+ * gdk_window_begin_paint_region() for details.
+ *
+ **/
+void
+gdk_window_begin_paint_rect (GdkWindow *window,
+ const GdkRectangle *rectangle)
+{
+ GdkRegion *region;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ region = gdk_region_rectangle (rectangle);
+ gdk_window_begin_paint_region (window, region);
+ gdk_region_destroy (region);
+}
+
+#ifdef GDK_WINDOWING_X11
+#include "x11/gdkx.h"
+#endif
+
+/**
+ * gdk_window_begin_paint_region:
+ * @window: a #GdkWindow
+ * @region: region you intend to draw to
+ *
+ * Indicates that you are beginning the process of redrawing @region.
+ * A backing store (offscreen buffer) large enough to contain @region
+ * will be created. The backing store will be initialized with the
+ * background color or background pixmap for @window. Then, all
+ * drawing operations performed on @window will be diverted to the
+ * backing store. When you call gdk_window_end_paint(), the backing
+ * store will be copied to @window, making it visible onscreen. Only
+ * the part of @window contained in @region will be modified; that is,
+ * drawing operations are clipped to @region.
+ *
+ * The net result of all this is to remove flicker, because the user
+ * sees the finished product appear all at once when you call
+ * gdk_window_end_paint(). If you draw to @window directly without
+ * calling gdk_window_begin_paint_region(), the user may see flicker
+ * as individual drawing operations are performed in sequence. The
+ * clipping and background-initializing features of
+ * gdk_window_begin_paint_region() are conveniences for the
+ * programmer, so you can avoid doing that work yourself.
+ *
+ * When using GTK+, the widget system automatically places calls to
+ * gdk_window_begin_paint_region() and gdk_window_end_paint() around
+ * emissions of the expose_event signal. That is, if you're writing an
+ * expose event handler, you can assume that the exposed area in
+ * #GdkEventExpose has already been cleared to the window background,
+ * is already set as the clip region, and already has a backing store.
+ * Therefore in most cases, application code need not call
+ * gdk_window_begin_paint_region(). (You can disable the automatic
+ * calls around expose events on a widget-by-widget basis by calling
+ * gtk_widget_set_double_buffered().)
+ *
+ * If you call this function multiple times before calling the
+ * matching gdk_window_end_paint(), the backing stores are pushed onto
+ * a stack. gdk_window_end_paint() copies the topmost backing store
+ * onscreen, subtracts the topmost region from all other regions in
+ * the stack, and pops the stack. All drawing operations affect only
+ * the topmost backing store in the stack. One matching call to
+ * gdk_window_end_paint() is required for each call to
+ * gdk_window_begin_paint_region().
+ *
+ **/
+void
+gdk_window_begin_paint_region (GdkWindow *window,
+ const GdkRegion *region)
+{
+#ifdef USE_BACKING_STORE
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkRectangle clip_box;
+ GdkWindowPaint *paint, *implicit_paint;
+ GdkWindowObject *impl_window;
+ GSList *list;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (GDK_IS_PAINTABLE (private->impl))
+ {
+ GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
+
+ if (iface->begin_paint_region)
+ iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
+
+ return;
+ }
+
+ impl_window = gdk_window_get_impl_window (private);
+ implicit_paint = impl_window->implicit_paint;
+
+ paint = g_new (GdkWindowPaint, 1);
+ paint->region = gdk_region_copy (region);
+ paint->region_tag = new_region_tag ();
+
+ gdk_region_intersect (paint->region, private->clip_region_with_children);
+ gdk_region_get_clipbox (paint->region, &clip_box);
+
+ /* Convert to impl coords */
+ gdk_region_offset (paint->region, private->abs_x, private->abs_y);
+
+ /* Mark the region as valid on the implicit paint */
+
+ if (implicit_paint)
+ gdk_region_union (implicit_paint->region, paint->region);
+
+ /* Convert back to normal coords */
+ gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
+
+ if (implicit_paint)
+ {
+ int width, height;
+
+ paint->uses_implicit = TRUE;
+ paint->pixmap = g_object_ref (implicit_paint->pixmap);
+ paint->x_offset = -private->abs_x + implicit_paint->x_offset;
+ paint->y_offset = -private->abs_y + implicit_paint->y_offset;
+
+ /* It would be nice if we had some cairo support here so we
+ could set the clip rect on the cairo surface */
+ width = private->abs_x + private->width;
+ height = private->abs_y + private->height;
+
+ paint->surface = _gdk_drawable_create_cairo_surface (paint->pixmap, width, height);
+
+ }
+ else
+ {
+ paint->uses_implicit = FALSE;
+ paint->x_offset = clip_box.x;
+ paint->y_offset = clip_box.y;
+ paint->pixmap =
+ gdk_pixmap_new (window,
+ MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
+ paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
+ }
+
+ if (paint->surface)
+ cairo_surface_set_device_offset (paint->surface,
+ -paint->x_offset, -paint->y_offset);
+
+ for (list = private->paint_stack; list != NULL; list = list->next)
+ {
+ GdkWindowPaint *tmp_paint = list->data;
+
+ gdk_region_subtract (tmp_paint->region, paint->region);
+ }
+
+ private->paint_stack = g_slist_prepend (private->paint_stack, paint);
+
+ if (!gdk_region_empty (paint->region))
+ {
+ gdk_window_clear_backing_region (window,
+ paint->region);
+ }
+
+#endif /* USE_BACKING_STORE */
+}
+
+static void
+setup_redirect_clip (GdkWindow *window,
+ GdkGC *gc,
+ int *x_offset_out,
+ int *y_offset_out)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkRegion *visible_region;
+ GdkRectangle dest_rect;
+ GdkRegion *tmpreg;
+ GdkWindow *toplevel;
+ int x_offset, y_offset;
+
+ toplevel = GDK_WINDOW (private->redirect->redirected);
+
+ /* Get the clip region for gc clip rect + window hierarchy in
+ window relative coords */
+ visible_region =
+ _gdk_window_calculate_full_clip_region (window, toplevel,
+ TRUE,
+ &x_offset,
+ &y_offset);
+
+ /* Compensate for the source pos/size */
+ x_offset -= private->redirect->src_x;
+ y_offset -= private->redirect->src_y;
+ dest_rect.x = -x_offset;
+ dest_rect.y = -y_offset;
+ dest_rect.width = private->redirect->width;
+ dest_rect.height = private->redirect->height;
+ tmpreg = gdk_region_rectangle (&dest_rect);
+ gdk_region_intersect (visible_region, tmpreg);
+ gdk_region_destroy (tmpreg);
+
+ /* Compensate for the dest pos */
+ x_offset += private->redirect->dest_x;
+ y_offset += private->redirect->dest_y;
+
+ gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
+
+ /* offset clip and tiles from window coords to pixmaps coords */
+ gdk_gc_offset (gc, -x_offset, -y_offset);
+
+ gdk_region_destroy (visible_region);
+
+ *x_offset_out = x_offset;
+ *y_offset_out = y_offset;
+}
+
+/**
+ * gdk_window_end_paint:
+ * @window: a #GdkWindow
+ *
+ * Indicates that the backing store created by the most recent call to
+ * gdk_window_begin_paint_region() should be copied onscreen and
+ * deleted, leaving the next-most-recent backing store or no backing
+ * store at all as the active paint region. See
+ * gdk_window_begin_paint_region() for full details. It is an error to
+ * call this function without a matching
+ * gdk_window_begin_paint_region() first.
+ *
+ **/
+void
+gdk_window_end_paint (GdkWindow *window)
+{
+#ifdef USE_BACKING_STORE
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *composited;
+ GdkWindowPaint *paint;
+ GdkGC *tmp_gc;
+ GdkRectangle clip_box;
+ gint x_offset, y_offset;
+ GdkRegion *full_clip;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (GDK_IS_PAINTABLE (private->impl))
+ {
+ GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
+
+ if (iface->end_paint)
+ iface->end_paint ((GdkPaintable*)private->impl);
+ return;
+ }
+
+ if (private->paint_stack == NULL)
+ {
+ g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
+ return;
+ }
+
+ paint = private->paint_stack->data;
+
+ private->paint_stack = g_slist_delete_link (private->paint_stack,
+ private->paint_stack);
+
+ gdk_region_get_clipbox (paint->region, &clip_box);
+
+ tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
+
+ x_offset = -private->abs_x;
+ y_offset = -private->abs_y;
+
+ if (!paint->uses_implicit)
+ {
+ gdk_window_flush_outstanding_moves (window);
+
+ full_clip = gdk_region_copy (private->clip_region_with_children);
+ gdk_region_intersect (full_clip, paint->region);
+ _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
+ gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
+ gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+ clip_box.x - paint->x_offset,
+ clip_box.y - paint->y_offset,
+ clip_box.x - x_offset, clip_box.y - y_offset,
+ clip_box.width, clip_box.height);
+ }
+
+ if (private->redirect)
+ {
+ int x_offset, y_offset;
+
+ /* TODO: Should also use paint->region for clipping */
+ setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
+ gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
+ clip_box.x - paint->x_offset,
+ clip_box.y - paint->y_offset,
+ clip_box.x + x_offset,
+ clip_box.y + y_offset,
+ clip_box.width, clip_box.height);
+ }
+
+ /* Reset clip region of the cached GdkGC */
+ gdk_gc_set_clip_region (tmp_gc, NULL);
+
+ cairo_surface_destroy (paint->surface);
+ g_object_unref (paint->pixmap);
+ gdk_region_destroy (paint->region);
+ g_free (paint);
+
+ /* find a composited window in our hierarchy to signal its
+ * parent to redraw, calculating the clip box as we go...
+ *
+ * stop if parent becomes NULL since then we'd have nowhere
+ * to draw (ie: 'composited' will always be non-NULL here).
+ */
+ for (composited = private;
+ composited->parent;
+ composited = composited->parent)
+ {
+ int width, height;
+
+ gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
+ &width, &height);
+
+ clip_box.x += composited->x;
+ clip_box.y += composited->y;
+ clip_box.width = MIN (clip_box.width, width - clip_box.x);
+ clip_box.height = MIN (clip_box.height, height - clip_box.y);
+
+ if (composited->composited)
+ {
+ gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
+ &clip_box, FALSE);
+ break;
+ }
+ }
+#endif /* USE_BACKING_STORE */
+}
+
+static void
+gdk_window_free_paint_stack (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ if (private->paint_stack)
+ {
+ GSList *tmp_list = private->paint_stack;
+
+ while (tmp_list)
+ {
+ GdkWindowPaint *paint = tmp_list->data;
+
+ if (tmp_list == private->paint_stack)
+ g_object_unref (paint->pixmap);
+
+ gdk_region_destroy (paint->region);
+ g_free (paint);
+
+ tmp_list = tmp_list->next;
+ }
+
+ g_slist_free (private->paint_stack);
+ private->paint_stack = NULL;
+ }
+}
+
+static void
+do_move_region_bits_on_impl (GdkWindowObject *impl_window,
+ GdkRegion *dest_region, /* In impl window coords */
+ int dx, int dy)
+{
+ GdkGC *tmp_gc;
+ GdkRectangle copy_rect;
+ GdkWindowObject *private;
+
+ /* We need to get data from subwindows here, because we might have
+ * shaped a native window over the moving region (with bg none,
+ * so the pixels are still there). In fact we might need to get data
+ * from overlapping native window that are not children of this window,
+ * so we copy from the toplevel with INCLUDE_INFERIORS.
+ */
+ private = impl_window;
+ while (private->parent != NULL &&
+ GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+ {
+ dx -= private->parent->abs_x + private->x;
+ dy -= private->parent->abs_y + private->y;
+ private = gdk_window_get_impl_window (private->parent);
+ }
+ tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private);
+
+ /* The region area is moved and we queue translations for all expose events
+ to the source area that were sent prior to the copy */
+ gdk_region_offset (dest_region, -dx, -dy); /* Temporarily move to source area */
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_translation ((GdkWindow *)impl_window,
+ dest_region, dx, dy);
+ gdk_region_offset (dest_region, dx, dy); /* back to dest area */
+
+ gdk_region_get_clipbox (dest_region, ©_rect);
+
+ gdk_gc_set_clip_region (tmp_gc, dest_region);
+ gdk_draw_drawable (impl_window->impl,
+ tmp_gc,
+ private->impl,
+ copy_rect.x-dx, copy_rect.y-dy,
+ copy_rect.x, copy_rect.y,
+ copy_rect.width, copy_rect.height);
+ gdk_gc_set_clip_region (tmp_gc, NULL);
+}
+
+static GdkWindowRegionMove *
+gdk_window_region_move_new (GdkRegion *region,
+ int dx, int dy)
+{
+ GdkWindowRegionMove *move;
+
+ move = g_slice_new (GdkWindowRegionMove);
+ move->dest_region = gdk_region_copy (region);
+ move->dx = dx;
+ move->dy = dy;
+
+ return move;
+}
+
+static void
+gdk_window_region_move_free (GdkWindowRegionMove *move)
+{
+ gdk_region_destroy (move->dest_region);
+ g_slice_free (GdkWindowRegionMove, move);
+}
+
+static void
+append_move_region (GdkWindowObject *impl_window,
+ GdkRegion *new_dest_region,
+ int dx, int dy)
+{
+ GdkWindowRegionMove *move, *old_move;
+ GdkRegion *new_total_region, *old_total_region;
+ GdkRegion *source_overlaps_destination;
+ GdkRegion *non_overwritten;
+ gboolean added_move;
+ GList *l, *prev;
+
+ if (gdk_region_empty (new_dest_region))
+ return;
+
+ /* In principle this could just append the move to the list of outstanding
+ moves that will be replayed before drawing anything when we're handling
+ exposes. However, we'd like to do a bit better since its commonly the case
+ that we get multiple copies where A is copied to B and then B is copied
+ to C, and we'd like to express this as a simple copy A to C operation. */
+
+ /* We approach this by taking the new move and pushing it ahead of moves
+ starting at the end of the list and stopping when its not safe to do so.
+ Its not safe to push past a move is either the source of the new move
+ is in the destination of the old move, or if the destination of the new
+ move is in the source of the new move, or if the destination of the new
+ move overlaps the destination of the old move. We simplify this by
+ just comparing the total regions (src + dest) */
+ new_total_region = gdk_region_copy (new_dest_region);
+ gdk_region_offset (new_total_region, -dx, -dy);
+ gdk_region_union (new_total_region, new_dest_region);
+
+ added_move = FALSE;
+ for (l = g_list_last (impl_window->outstanding_moves); l != NULL; l = prev)
+ {
+ prev = l->prev;
+ old_move = l->data;
+
+ old_total_region = gdk_region_copy (old_move->dest_region);
+ gdk_region_offset (old_total_region, -old_move->dx, -old_move->dy);
+ gdk_region_union (old_total_region, old_move->dest_region);
+
+ gdk_region_intersect (old_total_region, new_total_region);
+ /* If these regions intersect then its not safe to push the
+ new region before the old one */
+ if (!gdk_region_empty (old_total_region))
+ {
+ /* The area where the new moves source overlaps the old ones
+ destination */
+ source_overlaps_destination = gdk_region_copy (new_dest_region);
+ gdk_region_offset (source_overlaps_destination, -dx, -dy);
+ gdk_region_intersect (source_overlaps_destination, old_move->dest_region);
+ gdk_region_offset (source_overlaps_destination, dx, dy);
+
+ /* We can do all sort of optimizations here, but to do things safely it becomes
+ quite complicated. However, a very common case is that you copy something first,
+ then copy all that or a subset of it to a new location (i.e. if you scroll twice
+ in the same direction). We'd like to detect this case and optimize it to one
+ copy. */
+ if (gdk_region_equal (source_overlaps_destination, new_dest_region))
+ {
+ /* This means we might be able to replace the old move and the new one
+ with the new one read from the old ones source, and a second copy of
+ the non-overwritten parts of the old move. However, such a split
+ is only valid if the source in the old move isn't overwritten
+ by the destination of the new one */
+
+ /* the new destination of old move if split is ok: */
+ non_overwritten = gdk_region_copy (old_move->dest_region);
+ gdk_region_subtract (non_overwritten, new_dest_region);
+ /* move to source region */
+ gdk_region_offset (non_overwritten, -old_move->dx, -old_move->dy);
+
+ gdk_region_intersect (non_overwritten, new_dest_region);
+ if (gdk_region_empty (non_overwritten))
+ {
+ added_move = TRUE;
+ move = gdk_window_region_move_new (new_dest_region,
+ dx + old_move->dx,
+ dy + old_move->dy);
+
+ impl_window->outstanding_moves =
+ g_list_insert_before (impl_window->outstanding_moves,
+ l, move);
+ gdk_region_subtract (old_move->dest_region, new_dest_region);
+ }
+ gdk_region_destroy (non_overwritten);
+ }
+
+ gdk_region_destroy (source_overlaps_destination);
+ gdk_region_destroy (old_total_region);
+ break;
+ }
+ gdk_region_destroy (old_total_region);
+ }
+
+ gdk_region_destroy (new_total_region);
+
+ if (!added_move)
+ {
+ move = gdk_window_region_move_new (new_dest_region, dx, dy);
+
+ if (l == NULL)
+ impl_window->outstanding_moves =
+ g_list_prepend (impl_window->outstanding_moves,
+ move);
+ else
+ impl_window->outstanding_moves =
+ g_list_insert_before (impl_window->outstanding_moves,
+ l->next, move);
+ }
+}
+
+/* Moves bits and update area by dx/dy in impl window,
+ takes ownership of region */
+static void
+move_region_on_impl (GdkWindowObject *private,
+ GdkRegion *region, /* In impl window coords */
+ int dx, int dy)
+{
+ GdkWindowObject *impl_window;
+
+ if ((dx == 0 && dy == 0) ||
+ gdk_region_empty (region))
+ {
+ gdk_region_destroy (region);
+ return;
+ }
+
+ impl_window = gdk_window_get_impl_window (private);
+
+ /* Move any old invalid regions in the copy source area by dx/dy */
+ if (impl_window->update_area)
+ {
+ GdkRegion *update_area;
+ update_area = gdk_region_copy (region);
+
+ /* Convert from target to source */
+ gdk_region_offset (update_area, -dx, -dy);
+ gdk_region_intersect (update_area, impl_window->update_area);
+ gdk_region_subtract (impl_window->update_area, update_area);
+
+ /* Convert back */
+ gdk_region_offset (update_area, dx, dy);
+ gdk_region_union (impl_window->update_area, update_area);
+
+ /* This area of the destination is now invalid,
+ so no need to copy to it. */
+ gdk_region_subtract (region, update_area);
+
+ gdk_region_destroy (update_area);
+ }
+
+ if (1) /* Enable flicker free handling of moves. */
+ append_move_region (impl_window, region, dx, dy);
+ else
+ do_move_region_bits_on_impl (impl_window,
+ region, dx, dy);
+
+ gdk_region_destroy (region);
+}
+
+/* Flushes all outstanding changes to the window, call this
+ * before drawing directly to the window (i.e. outside a begin/end_paint pair).
+ */
+static void
+gdk_window_flush_outstanding_moves (GdkWindow *window)
+{
+ GdkWindowObject *private;
+ GdkWindowObject *impl_window;
+ GList *l;
+ GdkWindowRegionMove *move;
+
+ private = (GdkWindowObject *) window;
+
+ impl_window = gdk_window_get_impl_window (private);
+
+ for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
+ {
+ move = l->data;
+
+ do_move_region_bits_on_impl (impl_window,
+ move->dest_region, move->dx, move->dy);
+
+ gdk_window_region_move_free (move);
+ }
+
+ g_list_free (impl_window->outstanding_moves);
+ impl_window->outstanding_moves = NULL;
+}
+
+static void
+gdk_window_flush (GdkWindow *window)
+{
+ gdk_window_flush_outstanding_moves (window);
+ gdk_window_flush_implicit_paint (window);
+}
+
+static void
+gdk_window_flush_recursive_helper (GdkWindowObject *window,
+ GdkWindow *impl)
+{
+ GdkWindowObject *child;
+ GList *l;
+
+ for (l = window->children; l != NULL; l = l->next)
+ {
+ child = l->data;
+
+ if (child->impl == impl)
+ /* Same impl, ignore */
+ gdk_window_flush_recursive_helper (child, impl);
+ else
+ gdk_window_flush_recursive (child);
+ }
+}
+
+static void
+gdk_window_flush_recursive (GdkWindowObject *window)
+{
+ gdk_window_flush ((GdkWindow *)window);
+ gdk_window_flush_recursive_helper (window, window->impl);
+}
+
+static void
+gdk_window_get_offsets (GdkWindow *window,
+ gint *x_offset,
+ gint *y_offset)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ if (private->paint_stack)
+ {
+ GdkWindowPaint *paint = private->paint_stack->data;
+ *x_offset = paint->x_offset;
+ *y_offset = paint->y_offset;
+ }
+ else
+ {
+ *x_offset = -private->abs_x;
+ *y_offset = -private->abs_y;
+ }
+}
+
+/**
+ * gdk_window_get_internal_paint_info:
+ * @window: a #GdkWindow
+ * @real_drawable: location to store the drawable to which drawing should be
+ * done.
+ * @x_offset: location to store the X offset between coordinates in @window,
+ * and the underlying window system primitive coordinates for
+ * *@real_drawable.
+ * @y_offset: location to store the Y offset between coordinates in @window,
+ * and the underlying window system primitive coordinates for
+ * *@real_drawable.
+ *
+ * If you bypass the GDK layer and use windowing system primitives to
+ * draw directly onto a #GdkWindow, then you need to deal with two
+ * details: there may be an offset between GDK coordinates and windowing
+ * system coordinates, and GDK may have redirected drawing to a offscreen
+ * pixmap as the result of a gdk_window_begin_paint_region() calls.
+ * This function allows retrieving the information you need to compensate
+ * for these effects.
+ *
+ * This function exposes details of the GDK implementation, and is thus
+ * likely to change in future releases of GDK.
+ **/
+void
+gdk_window_get_internal_paint_info (GdkWindow *window,
+ GdkDrawable **real_drawable,
+ gint *x_offset,
+ gint *y_offset)
+{
+ gint x_off, y_off;
+
+ GdkWindowObject *private;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject *)window;
+
+ if (real_drawable)
+ {
+ if (private->paint_stack)
+ {
+ GdkWindowPaint *paint = private->paint_stack->data;
+ *real_drawable = paint->pixmap;
+ }
+ else
+ {
+ /* This means you're probably gonna be doing some weird shit
+ directly to the window, so we flush all outstanding stuff */
+ gdk_window_flush (window);
+ *real_drawable = window;
+ }
+ }
+
+ gdk_window_get_offsets (window, &x_off, &y_off);
+
+ if (x_offset)
+ *x_offset = x_off;
+ if (y_offset)
+ *y_offset = y_off;
+}
+
+static GdkDrawable *
+start_draw_helper (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint *x_offset_out,
+ gint *y_offset_out)
+{
+ GdkWindowObject *private = (GdkWindowObject *)drawable;
+ gint x_offset, y_offset;
+ GdkDrawable *impl;
+ gint old_clip_x = gc->clip_x_origin;
+ gint old_clip_y = gc->clip_y_origin;
+ GdkRegion *clip;
+ guint32 clip_region_tag;
+ GdkWindowPaint *paint;
+
+ paint = NULL;
+ if (private->paint_stack)
+ paint = private->paint_stack->data;
+
+ if (paint)
+ {
+ x_offset = paint->x_offset;
+ y_offset = paint->y_offset;
+ }
+ else
+ {
+ x_offset = -private->abs_x;
+ y_offset = -private->abs_y;
+ }
+
+ if (x_offset != 0 || y_offset != 0)
+ {
+ gdk_gc_set_clip_origin (gc,
+ old_clip_x - x_offset,
+ old_clip_y - y_offset);
+ gdk_gc_set_ts_origin (gc,
+ gc->ts_x_origin - x_offset,
+ gc->ts_y_origin - y_offset);
+ }
+
+ *x_offset_out = x_offset;
+ *y_offset_out = y_offset;
+
+ /* Add client side window clip region to gc */
+ clip = NULL;
+ if (paint)
+ {
+ /* Only need clipping if using implicit paint, otherwise
+ the pixmap is clipped when copying to the window in end_paint */
+ if (paint->uses_implicit)
+ {
+ /* This includes the window clip */
+ clip = paint->region;
+ }
+ clip_region_tag = paint->region_tag;
+
+ /* After having set up the drawable clip rect on a GC we need to make sure
+ * that we draw to th the impl, otherwise the pixmap code will reset the
+ * drawable clip. */
+ impl = ((GdkPixmapObject *)(paint->pixmap))->impl;
+ }
+ else
+ {
+ /* Drawing directly to the window, flush anything outstanding to
+ guarantee ordering. */
+ gdk_window_flush ((GdkWindow *)drawable);
+
+ /* Don't clip when drawing to root */
+ if (private->window_type != GDK_WINDOW_ROOT)
+ {
+ if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
+ clip = private->clip_region_with_children;
+ else
+ clip = private->clip_region;
+ }
+ clip_region_tag = private->clip_tag;
+ impl = private->impl;
+ }
+
+ if (clip)
+ _gdk_gc_add_drawable_clip (gc,
+ clip_region_tag, clip,
+ /* If there was a clip origin set appart from the
+ * window offset, need to take that into
+ * consideration */
+ -old_clip_x, -old_clip_y);
+
+ return impl;
+}
+
+#define BEGIN_DRAW \
+ { \
+ GdkDrawable *impl; \
+ gint x_offset, y_offset; \
+ gint old_clip_x = gc->clip_x_origin; \
+ gint old_clip_y = gc->clip_y_origin; \
+ gint old_ts_x = gc->ts_x_origin; \
+ gint old_ts_y = gc->ts_y_origin; \
+ impl = start_draw_helper (drawable, gc, \
+ &x_offset, &y_offset);
+
+#define END_DRAW \
+ if (x_offset != 0 || y_offset != 0) \
+ { \
+ gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
+ gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
+ } \
+ }
+
+static GdkGC *
+gdk_window_create_gc (GdkDrawable *drawable,
+ GdkGCValues *values,
+ GdkGCValuesMask mask)
+{
+ g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
+
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return NULL;
+
+ return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
+ values, mask);
+}
+
+static void
+gdk_window_draw_rectangle (GdkDrawable *drawable,
+ GdkGC *gc,
+ gboolean filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ BEGIN_DRAW;
+ gdk_draw_rectangle (impl, gc, filled,
+ x - x_offset, y - y_offset, width, height);
+ END_DRAW;
+}
+
+static void
+gdk_window_draw_arc (GdkDrawable *drawable,
+ GdkGC *gc,
+ gboolean filled,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gint angle1,
+ gint angle2)
+{
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ BEGIN_DRAW;
+ gdk_draw_arc (impl, gc, filled,
+ x - x_offset, y - y_offset,
+ width, height, angle1, angle2);
+ END_DRAW;
+}
+
+static void
+gdk_window_draw_polygon (GdkDrawable *drawable,
+ GdkGC *gc,
+ gboolean filled,
+ GdkPoint *points,
+ gint npoints)
+{
+ GdkPoint *new_points;
+
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ BEGIN_DRAW;
+
+ if (x_offset != 0 || y_offset != 0)
+ {
+ int i;
+
+ new_points = g_new (GdkPoint, npoints);
+ for (i=0; i<npoints; i++)
+ {
+ new_points[i].x = points[i].x - x_offset;
+ new_points[i].y = points[i].y - y_offset;
+ }
+ }
+ else
+ new_points = points;
+
+ gdk_draw_polygon (impl, gc, filled, new_points, npoints);
+
+ if (new_points != points)
+ g_free (new_points);
+
+ END_DRAW;
+}
+
+static void
+gdk_window_draw_text (GdkDrawable *drawable,
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const gchar *text,
+ gint text_length)
+{
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ BEGIN_DRAW;
+ gdk_draw_text (impl, font, gc,
+ x - x_offset, y - y_offset, text, text_length);
+ END_DRAW;
+}
+
+static void
+gdk_window_draw_text_wc (GdkDrawable *drawable,
+ GdkFont *font,
+ GdkGC *gc,
+ gint x,
+ gint y,
+ const GdkWChar *text,
+ gint text_length)
+{
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ BEGIN_DRAW;
+ gdk_draw_text_wc (impl, font, gc,
+ x - x_offset, y - y_offset, text, text_length);
+ END_DRAW;
+}
+
+static GdkDrawable *
+gdk_window_get_source_drawable (GdkDrawable *drawable)
+{
+ GdkWindow *window = GDK_WINDOW (drawable);
+ GdkWindowObject *private;
+
+ private = (GdkWindowObject *) window;
+ if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
+ return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
+
+ return drawable;
+}
+
+static GdkDrawable *
+gdk_window_get_composite_drawable (GdkDrawable *drawable,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gint *composite_x_offset,
+ gint *composite_y_offset)
+{
+ GdkWindowObject *private = (GdkWindowObject *)drawable;
+ GSList *list;
+ GdkPixmap *tmp_pixmap;
+ GdkRectangle rect;
+ GdkGC *tmp_gc;
+ gboolean overlap_buffer;
+ GdkDrawable *source;
+ GdkWindowObject *impl_window;
+ GdkWindowPaint *implicit_paint;
+
+ *composite_x_offset = -private->abs_x;
+ *composite_y_offset = -private->abs_y;
+
+ if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
+ return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
+
+ /* See if any buffered part is overlapping the part we want
+ * to get
+ */
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+
+ overlap_buffer = FALSE;
+
+ for (list = private->paint_stack; list != NULL; list = list->next)
+ {
+ GdkWindowPaint *paint = list->data;
+ GdkOverlapType overlap;
+
+ overlap = gdk_region_rect_in (paint->region, &rect);
+
+ if (overlap == GDK_OVERLAP_RECTANGLE_IN)
+ {
+ *composite_x_offset = paint->x_offset;
+ *composite_y_offset = paint->y_offset;
+
+ return g_object_ref (paint->pixmap);
+ }
+ else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
+ {
+ overlap_buffer = TRUE;
+ break;
+ }
+ }
+
+ impl_window = gdk_window_get_impl_window (private);
+ implicit_paint = impl_window->implicit_paint;
+ if (implicit_paint)
+ {
+ GdkOverlapType overlap;
+
+ rect.x += private->abs_x;
+ rect.y += private->abs_y;
+
+ overlap = gdk_region_rect_in (implicit_paint->region, &rect);
+ if (overlap == GDK_OVERLAP_RECTANGLE_IN)
+ {
+ *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
+ *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
+
+ return g_object_ref (implicit_paint->pixmap);
+ }
+ else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
+ overlap_buffer = TRUE;
+ }
+
+ if (!overlap_buffer)
+ return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
+
+ tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
+ tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
+
+ source = _gdk_drawable_get_source_drawable (drawable);
+
+ /* Copy the current window contents */
+ gdk_draw_drawable (tmp_pixmap,
+ tmp_gc,
+ GDK_WINDOW_OBJECT (source)->impl,
+ x - *composite_x_offset,
+ y - *composite_y_offset,
+ 0, 0,
+ width, height);
+
+ /* paint the backing stores */
+ if (implicit_paint)
+ {
+ GdkWindowPaint *paint = list->data;
+
+ gdk_gc_set_clip_region (tmp_gc, paint->region);
+ gdk_gc_set_clip_origin (tmp_gc, -x - paint->x_offset, -y - paint->y_offset);
+
+ gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
+ x - paint->x_offset,
+ y - paint->y_offset,
+ 0, 0, width, height);
+ }
+
+ for (list = private->paint_stack; list != NULL; list = list->next)
+ {
+ GdkWindowPaint *paint = list->data;
+
+ if (paint->uses_implicit)
+ continue; /* We already copied this above */
+
+ gdk_gc_set_clip_region (tmp_gc, paint->region);
+ gdk_gc_set_clip_origin (tmp_gc, -x, -y);
+
+ gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
+ x - paint->x_offset,
+ y - paint->y_offset,
+ 0, 0, width, height);
+ }
+
+ /* Reset clip region of the cached GdkGC */
+ gdk_gc_set_clip_region (tmp_gc, NULL);
+
+ /* Set these to location of tmp_pixmap within the window */
+ *composite_x_offset = x;
+ *composite_y_offset = y;
+
+ return tmp_pixmap;
+}
+
+static GdkRegion*
+gdk_window_get_clip_region (GdkDrawable *drawable)
+{
+ GdkWindowObject *private = (GdkWindowObject *)drawable;
+ GdkRegion *result;
+
+ result = gdk_region_copy (private->clip_region);
+
+ if (private->paint_stack)
+ {
+ GdkRegion *paint_region = gdk_region_new ();
+ GSList *tmp_list = private->paint_stack;
+
+ while (tmp_list)
+ {
+ GdkWindowPaint *paint = tmp_list->data;
+
+ gdk_region_union (paint_region, paint->region);
+
+ tmp_list = tmp_list->next;
+ }
+
+ gdk_region_intersect (result, paint_region);
+ gdk_region_destroy (paint_region);
+ }
+
+ return result;
+}
+
+static GdkRegion*
+gdk_window_get_visible_region (GdkDrawable *drawable)
+{
+ GdkWindowObject *private = (GdkWindowObject*) drawable;
+
+ return gdk_region_copy (private->clip_region);
+}
+
+static void
+gdk_window_draw_drawable (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPixmap *src,
+ GdkDrawable *original_src,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+ GdkWindowObject *private = (GdkWindowObject *)drawable;
+
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ BEGIN_DRAW;
+
+ gdk_draw_drawable (impl, gc, src, xsrc, ysrc,
+ xdest - x_offset, ydest - y_offset, width, height);
+
+ if (!private->paint_stack)
+ {
+ /* We might have drawn from an obscured part of a client
+ side window, if so we need to send graphics exposures */
+ if (_gdk_gc_get_exposures (gc) &&
+ GDK_IS_WINDOW (original_src))
+ {
+ GdkRegion *exposure_region;
+ GdkRegion *clip;
+ GdkRectangle r;
+
+ r.x = xdest;
+ r.y = ydest;
+ r.width = width;
+ r.height = height;
+ exposure_region = gdk_region_rectangle (&r);
+
+ if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
+ clip = private->clip_region_with_children;
+ else
+ clip = private->clip_region;
+ gdk_region_intersect (exposure_region, clip);
+
+ clip = _gdk_gc_get_clip_region (gc);
+ if (clip)
+ {
+ gdk_region_offset (exposure_region,
+ old_clip_x,
+ old_clip_y);
+ gdk_region_intersect (exposure_region, clip);
+ gdk_region_offset (exposure_region,
+ -old_clip_x,
+ -old_clip_y);
+ }
+
+ /* Note: We don't clip by the clip mask if set, so this
+ may invalidate to much */
+
+ /* Remove the area that is correctly copied from the src.
+ * Note that xsrc/ysrc has been corrected for abs_x/y offsets already,
+ * which need to be undone */
+ clip = gdk_drawable_get_visible_region (original_src);
+ gdk_region_offset (clip,
+ xdest - (xsrc - GDK_WINDOW_OBJECT (original_src)->abs_x),
+ ydest - (ysrc - GDK_WINDOW_OBJECT (original_src)->abs_y));
+ gdk_region_subtract (exposure_region, clip);
+ gdk_region_destroy (clip);
+
+ gdk_window_invalidate_region (GDK_WINDOW (private),
+ exposure_region,
+ _gdk_gc_get_subwindow (gc) == GDK_INCLUDE_INFERIORS);
+
+ gdk_region_destroy (exposure_region);
+ }
+ }
+
+ END_DRAW;
+}
+
+static void
+gdk_window_draw_points (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPoint *points,
+ gint npoints)
+{
+ GdkPoint *new_points;
+
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ BEGIN_DRAW;
+
+ if (x_offset != 0 || y_offset != 0)
+ {
+ gint i;
+
+ new_points = g_new (GdkPoint, npoints);
+ for (i=0; i<npoints; i++)
+ {
+ new_points[i].x = points[i].x - x_offset;
+ new_points[i].y = points[i].y - y_offset;
+ }
+ }
+ else
+ new_points = points;
+
+ gdk_draw_points (impl, gc, new_points, npoints);
+
+ if (new_points != points)
+ g_free (new_points);
+
+ END_DRAW;
+}
+
+static void
+gdk_window_draw_segments (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkSegment *segs,
+ gint nsegs)
+{
+ GdkSegment *new_segs;
+
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ BEGIN_DRAW;
+
+ if (x_offset != 0 || y_offset != 0)
+ {
+ gint i;
+
+ new_segs = g_new (GdkSegment, nsegs);
+ for (i=0; i<nsegs; i++)
+ {
+ new_segs[i].x1 = segs[i].x1 - x_offset;
+ new_segs[i].y1 = segs[i].y1 - y_offset;
+ new_segs[i].x2 = segs[i].x2 - x_offset;
+ new_segs[i].y2 = segs[i].y2 - y_offset;
+ }
+ }
+ else
+ new_segs = segs;
+
+ gdk_draw_segments (impl, gc, new_segs, nsegs);
+
+ if (new_segs != segs)
+ g_free (new_segs);
+
+ END_DRAW;
+}
+
+static void
+gdk_window_draw_lines (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPoint *points,
+ gint npoints)
+{
+ GdkPoint *new_points;
+
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ BEGIN_DRAW;
+
+ if (x_offset != 0 || y_offset != 0)
+ {
+ gint i;
+
+ new_points = g_new (GdkPoint, npoints);
+ for (i=0; i<npoints; i++)
+ {
+ new_points[i].x = points[i].x - x_offset;
+ new_points[i].y = points[i].y - y_offset;
+ }
+ }
+ else
+ new_points = points;
+
+ gdk_draw_lines (impl, gc, new_points, npoints);
+
+ if (new_points != points)
+ g_free (new_points);
+
+ END_DRAW;
+}
+
+static void
+gdk_window_draw_glyphs (GdkDrawable *drawable,
+ GdkGC *gc,
+ PangoFont *font,
+ gint x,
+ gint y,
+ PangoGlyphString *glyphs)
+{
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ BEGIN_DRAW;
+ gdk_draw_glyphs (impl, gc, font,
+ x - x_offset, y - y_offset, glyphs);
+ END_DRAW;
+}
+
+static void
+gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
+ GdkGC *gc,
+ PangoMatrix *matrix,
+ PangoFont *font,
+ gint x,
+ gint y,
+ PangoGlyphString *glyphs)
+{
+ PangoMatrix tmp_matrix;
+
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ BEGIN_DRAW;
+
+ if (x_offset != 0 || y_offset != 0)
+ {
+ if (matrix)
+ {
+ tmp_matrix = *matrix;
+ tmp_matrix.x0 -= x_offset;
+ tmp_matrix.y0 -= y_offset;
+ matrix = &tmp_matrix;
+ }
+ else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
+ {
+ PangoMatrix identity = PANGO_MATRIX_INIT;
+
+ tmp_matrix = identity;
+ tmp_matrix.x0 -= x_offset;
+ tmp_matrix.y0 -= y_offset;
+ matrix = &tmp_matrix;
+ }
+ else
+ {
+ x -= x_offset * PANGO_SCALE;
+ y -= y_offset * PANGO_SCALE;
+ }
+ }
+
+ gdk_draw_glyphs_transformed (impl, gc, matrix, font, x, y, glyphs);
+
+ END_DRAW;
+}
+
+typedef struct {
+ cairo_t *cr; /* if non-null, it means use this cairo context */
+ GdkGC *gc; /* if non-null, it means use this GC instead */
+} BackingRectMethod;
+
+static void
+setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
+ {
+ GdkWindowPaint tmp_paint;
+
+ tmp_paint = *paint;
+ tmp_paint.x_offset += private->x;
+ tmp_paint.y_offset += private->y;
+
+ x_offset_cairo += private->x;
+ y_offset_cairo += private->y;
+
+ setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
+ }
+ else if (private->bg_pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG)
+ {
+/* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
+ * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
+ * pixmap destination surface, can be very slow (on the order of seconds for a
+ * whole-screen copy). The workaround is to use pretty much the same code that
+ * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
+ * a tiled GC XFillRectangle().
+ */
+
+/* Actually computing this flag is left as an exercise for the reader */
+#if defined (G_OS_UNIX)
+# define GDK_CAIRO_REPEAT_IS_FAST 0
+#else
+# define GDK_CAIRO_REPEAT_IS_FAST 1
+#endif
+
+#if GDK_CAIRO_REPEAT_IS_FAST
+ cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
+ cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
+ cairo_surface_destroy (surface);
+
+ if (x_offset_cairo != 0 || y_offset_cairo != 0)
+ {
+ cairo_matrix_t matrix;
+ cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
+ cairo_pattern_set_matrix (pattern, &matrix);
+ }
+
+ cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+
+ method->cr = cairo_create (paint->surface);
+ method->gc = NULL;
+
+ cairo_set_source (method->cr, pattern);
+ cairo_pattern_destroy (pattern);
+#else
+ guint gc_mask;
+ GdkGCValues gc_values;
+
+ gc_values.fill = GDK_TILED;
+ gc_values.tile = private->bg_pixmap;
+ gc_values.ts_x_origin = -x_offset_cairo;
+ gc_values.ts_y_origin = -y_offset_cairo;
+
+ gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
+
+ method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
+#endif
+ }
+ else
+ {
+ method->cr = cairo_create (paint->surface);
+
+ gdk_cairo_set_source_color (method->cr, &private->bg_color);
+ }
+}
+
+static void
+gdk_window_clear_backing_region (GdkWindow *window,
+ GdkRegion *region)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowPaint *paint = private->paint_stack->data;
+ BackingRectMethod method;
+ GdkRegion *clip;
+ GdkRectangle clipbox;
+#if 0
+ GTimer *timer;
+ double elapsed;
+#endif
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+#if 0
+ timer = g_timer_new ();
+#endif
+
+ method.cr = NULL;
+ method.gc = NULL;
+ setup_backing_rect_method (&method, window, paint, 0, 0);
+
+ clip = gdk_region_copy (paint->region);
+ gdk_region_intersect (clip, region);
+ gdk_region_get_clipbox (clip, &clipbox);
+
+
+ if (method.cr)
+ {
+ g_assert (method.gc == NULL);
+
+ gdk_cairo_region (method.cr, clip);
+ cairo_fill (method.cr);
+
+ cairo_destroy (method.cr);
+#if 0
+ elapsed = g_timer_elapsed (timer, NULL);
+ g_print ("Draw the background with Cairo: %fs\n", elapsed);
+#endif
+ }
+ else
+ {
+ g_assert (method.gc != NULL);
+
+ gdk_gc_set_clip_region (method.gc, clip);
+ gdk_draw_rectangle (window, method.gc, TRUE,
+ clipbox.x, clipbox.y,
+ clipbox.width, clipbox.height);
+ g_object_unref (method.gc);
+
+#if 0
+ elapsed = g_timer_elapsed (timer, NULL);
+ g_print ("Draw the background with GDK: %fs\n", elapsed);
+#endif
+ }
+
+ gdk_region_destroy (clip);
+
+#if 0
+ g_timer_destroy (timer);
+#endif
+}
+
+static void
+gdk_window_clear_backing_region_redirect (GdkWindow *window,
+ GdkRegion *region)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowRedirect *redirect = private->redirect;
+ GdkRegion *clip_region;
+ GdkRectangle clipbox;
+ gint x_offset, y_offset;
+ BackingRectMethod method;
+ GdkWindowPaint paint;
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ clip_region = _gdk_window_calculate_full_clip_region (window,
+ GDK_WINDOW (redirect->redirected),
+ TRUE,
+ &x_offset, &y_offset);
+ gdk_region_intersect (clip_region, region);
+
+ /* offset is from redirected window origin to window origin, convert to
+ the offset from the redirected pixmap origin to the window origin */
+ x_offset += redirect->dest_x - redirect->src_x;
+ y_offset += redirect->dest_y - redirect->src_y;
+
+ /* Convert region to pixmap coords */
+ gdk_region_offset (clip_region, x_offset, y_offset);
+
+ paint.x_offset = 0;
+ paint.y_offset = 0;
+ paint.pixmap = redirect->pixmap;
+ paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
+
+ method.cr = NULL;
+ method.gc = NULL;
+ setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
+
+ if (method.cr)
+ {
+ g_assert (method.gc == NULL);
+
+ gdk_cairo_region (method.cr, clip_region);
+ cairo_fill (method.cr);
+
+ cairo_destroy (method.cr);
+ }
+ else
+ {
+ g_assert (method.gc != NULL);
+
+ gdk_region_get_clipbox (clip_region, &clipbox);
+ gdk_gc_set_clip_region (method.gc, clip_region);
+ gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
+ clipbox.x, clipbox.y,
+ clipbox.width, clipbox.height);
+ g_object_unref (method.gc);
+
+ }
+
+ gdk_region_destroy (clip_region);
+ cairo_surface_destroy (paint.surface);
+}
+
+static void
+gdk_window_clear_backing_region_direct (GdkWindow *window,
+ GdkRegion *region)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ BackingRectMethod method;
+ GdkWindowPaint paint;
+ GdkRegion *clip;
+ GdkRectangle clipbox;
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ paint.x_offset = 0;
+ paint.y_offset = 0;
+ paint.pixmap = window;
+ paint.surface = _gdk_drawable_ref_cairo_surface (window);
+
+ method.cr = NULL;
+ method.gc = NULL;
+ setup_backing_rect_method (&method, window, &paint, 0, 0);
+
+ clip = gdk_region_copy (private->clip_region_with_children);
+ gdk_region_intersect (clip, region);
+ gdk_region_get_clipbox (clip, &clipbox);
+
+ if (method.cr)
+ {
+ g_assert (method.gc == NULL);
+
+ gdk_cairo_region (method.cr, clip);
+ cairo_fill (method.cr);
+
+ cairo_destroy (method.cr);
+ }
+ else
+ {
+ g_assert (method.gc != NULL);
+
+ gdk_gc_set_clip_region (method.gc, clip);
+ gdk_draw_rectangle (window, method.gc, TRUE,
+ clipbox.x, clipbox.y,
+ clipbox.width, clipbox.height);
+ g_object_unref (method.gc);
+
+ }
+
+ gdk_region_destroy (clip);
+ cairo_surface_destroy (paint.surface);
+}
+
+
+/**
+ * gdk_window_clear:
+ * @window: a #GdkWindow
+ *
+ * Clears an entire @window to the background color or background pixmap.
+ **/
+void
+gdk_window_clear (GdkWindow *window)
+{
+ gint width, height;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
+
+ gdk_window_clear_area (window, 0, 0,
+ width, height);
+}
+
+static void
+gdk_window_clear_region_internal (GdkWindow *window,
+ GdkRegion *region,
+ gboolean send_expose)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ if (private->paint_stack)
+ gdk_window_clear_backing_region (window, region);
+ else
+ {
+ if (private->redirect)
+ gdk_window_clear_backing_region_redirect (window, region);
+
+ gdk_window_clear_backing_region_direct (window, region);
+ if (send_expose)
+ gdk_window_invalidate_region (window, region, FALSE);
+ }
+}
+
+static void
+gdk_window_clear_area_internal (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ gboolean send_expose)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkRectangle rect;
+ GdkRegion *region;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ /* This is what XClearArea does, and e.g. GtkCList uses it,
+ so we need to duplicate that */
+ if (width == 0)
+ width = private->width - x;
+ if (height == 0)
+ height = private->height - y;
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+
+ region = gdk_region_rectangle (&rect);
+ gdk_window_clear_region_internal (window,
+ region,
+ FALSE);
+ gdk_region_destroy (region);
+
+}
+
+/**
+ * gdk_window_clear_area:
+ * @window: a #GdkWindow
+ * @x: x coordinate of rectangle to clear
+ * @y: y coordinate of rectangle to clear
+ * @width: width of rectangle to clear
+ * @height: height of rectangle to clear
+ *
+ * Clears an area of @window to the background color or background pixmap.
+ *
+ **/
+void
+gdk_window_clear_area (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ gdk_window_clear_area_internal (window,
+ x, y,
+ width, height,
+ FALSE);
+}
+
+/**
+ * gdk_window_clear_area_e:
+ * @window: a #GdkWindow
+ * @x: x coordinate of rectangle to clear
+ * @y: y coordinate of rectangle to clear
+ * @width: width of rectangle to clear
+ * @height: height of rectangle to clear
+ *
+ * Like gdk_window_clear_area(), but also generates an expose event for
+ * the cleared area.
+ *
+ * This function has a stupid name because it dates back to the mists
+ * time, pre-GDK-1.0.
+ *
+ **/
+void
+gdk_window_clear_area_e (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ gdk_window_clear_area_internal (window,
+ x, y,
+ width, height,
+ TRUE);
+}
+
+static void
+gdk_window_draw_image (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkImage *image,
+ gint xsrc,
+ gint ysrc,
+ gint xdest,
+ gint ydest,
+ gint width,
+ gint height)
+{
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ BEGIN_DRAW;
+ gdk_draw_image (impl, gc, image, xsrc, ysrc,
+ xdest - x_offset, ydest - y_offset,
+ width, height);
+ END_DRAW;
+}
+
+static void
+gdk_window_draw_pixbuf (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkPixbuf *pixbuf,
+ gint src_x,
+ gint src_y,
+ gint dest_x,
+ gint dest_y,
+ gint width,
+ gint height,
+ GdkRgbDither dither,
+ gint x_dither,
+ gint y_dither)
+{
+ GdkWindowObject *private = (GdkWindowObject *)drawable;
+
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ /* If no gc => no user clipping, but we need clipping
+ for window emulation, so use a scratch gc */
+ if (!gc)
+ gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
+
+ BEGIN_DRAW;
+ if (private->paint_stack)
+ gdk_draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
+ dest_x - x_offset, dest_y - y_offset,
+ width, height,
+ dither, x_dither - x_offset, y_dither - y_offset);
+ else
+ gdk_draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
+ dest_x - x_offset, dest_y - y_offset,
+ width, height,
+ dither, x_dither, y_dither);
+ END_DRAW;
+}
+
+static void
+gdk_window_draw_trapezoids (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkTrapezoid *trapezoids,
+ gint n_trapezoids)
+{
+ GdkTrapezoid *new_trapezoids = NULL;
+
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ BEGIN_DRAW;
+
+ if (x_offset != 0 || y_offset != 0)
+ {
+ gint i;
+
+ new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
+ for (i=0; i < n_trapezoids; i++)
+ {
+ new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
+ new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
+ new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
+ new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
+ new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
+ new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
+ }
+
+ trapezoids = new_trapezoids;
+ }
+
+ gdk_draw_trapezoids (impl, gc, trapezoids, n_trapezoids);
+
+ g_free (new_trapezoids);
+
+ END_DRAW;
+}
+
+static void
+gdk_window_real_get_size (GdkDrawable *drawable,
+ gint *width,
+ gint *height)
+{
+ GdkWindowObject *private = (GdkWindowObject *)drawable;
+
+ if (width)
+ *width = private->width;
+ if (height)
+ *height = private->height;
+}
+
+static GdkVisual*
+gdk_window_real_get_visual (GdkDrawable *drawable)
+{
+ GdkColormap *colormap;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
+
+ colormap = gdk_drawable_get_colormap (drawable);
+ return colormap ? gdk_colormap_get_visual (colormap) : NULL;
+}
+
+static gint
+gdk_window_real_get_depth (GdkDrawable *drawable)
+{
+ g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
+
+ return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
+}
+
+static GdkScreen*
+gdk_window_real_get_screen (GdkDrawable *drawable)
+{
+ return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
+}
+
+static void
+gdk_window_real_set_colormap (GdkDrawable *drawable,
+ GdkColormap *cmap)
+{
+ GdkWindowObject *private;
+
+ g_return_if_fail (GDK_IS_WINDOW (drawable));
+
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ private = (GdkWindowObject *)drawable;
+
+ /* different colormap than parent, requires native window */
+ if (!private->input_only &&
+ cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
+ gdk_window_ensure_native ((GdkWindow *)drawable);
+
+ gdk_drawable_set_colormap (private->impl, cmap);
+}
+
+static GdkColormap*
+gdk_window_real_get_colormap (GdkDrawable *drawable)
+{
+ g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
+
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return NULL;
+
+ return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
+}
+
+static GdkImage*
+gdk_window_copy_to_image (GdkDrawable *drawable,
+ GdkImage *image,
+ gint src_x,
+ gint src_y,
+ gint dest_x,
+ gint dest_y,
+ gint width,
+ gint height)
+{
+ GdkWindowObject *private = (GdkWindowObject *) drawable;
+ gint x_offset, y_offset;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
+
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return NULL;
+
+ /* If we're here, a composite image was not necessary, so
+ * we can ignore the paint stack.
+ */
+
+ /* TODO: Is this right? */
+ x_offset = 0;
+ y_offset = 0;
+
+ return gdk_drawable_copy_to_image (private->impl,
+ image,
+ src_x - x_offset,
+ src_y - y_offset,
+ dest_x, dest_y,
+ width, height);
+}
+
+static void
+gdk_window_cairo_surface_destroy (void *data)
+{
+ GdkWindowObject *private = (GdkWindowObject*) data;
+
+ private->cairo_surface = NULL;
+}
+
+static cairo_surface_t *
+gdk_window_create_cairo_surface (GdkDrawable *drawable,
+ int width,
+ int height)
+{
+ return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
+ width, height);
+}
+
+
+static cairo_surface_t *
+gdk_window_ref_cairo_surface (GdkDrawable *drawable)
+{
+ GdkWindowObject *private = (GdkWindowObject*) drawable;
+ cairo_surface_t *surface;
+
if (private->paint_stack)
{
- GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_text_wc (paint->pixmap, font, gc,
- x - x_offset, y - y_offset, text, text_length);
+ GdkWindowPaint *paint = private->paint_stack->data;
+
+ surface = paint->surface;
+ cairo_surface_reference (surface);
+ }
+ else
+ {
+
+ /* This will be drawing directly to the window, so flush implicit paint */
+ gdk_window_flush ((GdkWindow *)drawable);
+
+ if (!private->cairo_surface)
+ {
+ int width, height;
+ GdkDrawable *source;
+
+ /* It would be nice if we had some cairo support here so we
+ could set the clip rect on the cairo surface */
+ width = private->abs_x + private->width;
+ height = private->abs_y + private->height;
+
+ source = _gdk_drawable_get_source_drawable (drawable);
+
+ /* TODO: Avoid the typecheck crap by adding virtual call */
+ private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
+
+ if (private->cairo_surface)
+ {
+ cairo_surface_set_device_offset (private->cairo_surface,
+ private->abs_x,
+ private->abs_y);
+
+ cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+ drawable, gdk_window_cairo_surface_destroy);
+ }
+ }
+ else
+ cairo_surface_reference (private->cairo_surface);
+
+ surface = private->cairo_surface;
+ }
+
+ return surface;
+}
+
+static void
+gdk_window_set_cairo_clip (GdkDrawable *drawable,
+ cairo_t *cr)
+{
+ GdkWindowObject *private = (GdkWindowObject*) drawable;
+
+ if (!private->paint_stack)
+ {
+ cairo_save (cr);
+ cairo_identity_matrix (cr);
+
+ cairo_reset_clip (cr);
+
+ cairo_new_path (cr);
+ gdk_cairo_region (cr, private->clip_region);
+
+ cairo_restore (cr);
+ cairo_clip (cr);
+ }
+ else
+ {
+ GdkWindowPaint *paint = private->paint_stack->data;
+
+ /* Only needs to clip to region if piggybacking
+ on an implicit paint pixmap */
+ if (paint->uses_implicit)
+ {
+ cairo_save (cr);
+ cairo_identity_matrix (cr);
+
+ cairo_reset_clip (cr);
+
+ cairo_new_path (cr);
+ gdk_cairo_region (cr, paint->region);
+ cairo_restore (cr);
+
+ cairo_clip (cr);
+ }
+ }
+}
+
+/* Code for dirty-region queueing
+ */
+static GSList *update_windows = NULL;
+static guint update_idle = 0;
+static gboolean debug_updates = FALSE;
+
+static inline gboolean
+gdk_window_is_ancestor (GdkWindow *window,
+ GdkWindow *ancestor)
+{
+ while (window)
+ {
+ GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
+
+ if (parent == ancestor)
+ return TRUE;
+
+ window = parent;
+ }
+
+ return FALSE;
+}
+
+static void
+gdk_window_add_update_window (GdkWindow *window)
+{
+ GSList *tmp;
+ GSList *prev = NULL;
+ gboolean has_ancestor_in_list = FALSE;
+
+ for (tmp = update_windows; tmp; tmp = tmp->next)
+ {
+ GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
+
+ /* check if tmp is an ancestor of "window"; if it is, set a
+ * flag indicating that all following windows are either
+ * children of "window" or from a differen hierarchy
+ */
+ if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
+ has_ancestor_in_list = TRUE;
+
+ /* insert in reverse stacking order when adding around siblings,
+ * so processing updates properly paints over lower stacked windows
+ */
+ if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
+ {
+ gint index = g_list_index (parent->children, window);
+ for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
+ {
+ gint sibling_index = g_list_index (parent->children, tmp->data);
+ if (index > sibling_index)
+ break;
+ prev = tmp;
+ }
+ /* here, tmp got advanced past all lower stacked siblings */
+ tmp = g_slist_prepend (tmp, window);
+ if (prev)
+ prev->next = tmp;
+ else
+ update_windows = tmp;
+ return;
+ }
+
+ /* if "window" has an ancestor in the list and tmp is one of
+ * "window's" children, insert "window" before tmp
+ */
+ if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
+ {
+ tmp = g_slist_prepend (tmp, window);
+
+ if (prev)
+ prev->next = tmp;
+ else
+ update_windows = tmp;
+ return;
+ }
+
+ /* if we're at the end of the list and had an ancestor it it,
+ * append to the list
+ */
+ if (! tmp->next && has_ancestor_in_list)
+ {
+ tmp = g_slist_append (tmp, window);
+ return;
+ }
+
+ prev = tmp;
+ }
+
+ /* if all above checks failed ("window" is from a different
+ * hierarchy than what is already in the list) or the list is
+ * empty, prepend
+ */
+ update_windows = g_slist_prepend (update_windows, window);
+}
+
+static void
+gdk_window_remove_update_window (GdkWindow *window)
+{
+ update_windows = g_slist_remove (update_windows, window);
+}
+
+static gboolean
+gdk_window_update_idle (gpointer data)
+{
+ gdk_window_process_all_updates ();
+
+ return FALSE;
+}
+
+static gboolean
+gdk_window_is_toplevel_frozen (GdkWindow *window)
+{
+ GdkWindowObject *toplevel;
+
+ toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
+
+ return toplevel->update_and_descendants_freeze_count > 0;
+}
+
+static void
+gdk_window_schedule_update (GdkWindow *window)
+{
+ if (window &&
+ (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
+ gdk_window_is_toplevel_frozen (window)))
+ return;
+
+ if (!update_idle)
+ {
+ update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
+ gdk_window_update_idle, NULL, NULL);
+ }
+}
+
+void
+_gdk_window_process_updates_recurse (GdkWindow *window,
+ GdkRegion *expose_region)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *child;
+ GdkRegion *child_region;
+ GdkRectangle r;
+ GList *l;
+
+ if (gdk_region_empty (expose_region))
+ return;
+
+ /* Iterate over children, starting at topmost */
+ for (l = private->children; l != NULL; l = l->next)
+ {
+ child = l->data;
+
+ if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
+ continue;
+
+ /* Ignore offscreen children, as they don't draw in their parent and
+ * don't take part in the clipping */
+ if (gdk_window_is_offscreen (child))
+ continue;
+
+ r.x = child->x;
+ r.y = child->y;
+ r.width = child->width;
+ r.height = child->height;
+
+ child_region = gdk_region_rectangle (&r);
+ if (child->shape)
+ gdk_region_intersect (child_region, child->shape);
+
+ if (child->impl == private->impl)
+ {
+ /* Client side child, expose */
+ gdk_region_intersect (child_region, expose_region);
+ gdk_region_subtract (expose_region, child_region);
+ gdk_region_offset (child_region, -child->x, -child->y);
+ _gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
+ }
+ else
+ {
+ /* Native child, just remove area from expose region */
+ gdk_region_subtract (expose_region, child_region);
+ }
+ gdk_region_destroy (child_region);
+ }
+
+ if (!gdk_region_empty (expose_region))
+ {
+ if (private->event_mask & GDK_EXPOSURE_MASK)
+ {
+ GdkEvent event;
+
+ event.expose.type = GDK_EXPOSE;
+ event.expose.window = g_object_ref (window);
+ event.expose.send_event = FALSE;
+ event.expose.count = 0;
+ event.expose.region = expose_region;
+ gdk_region_get_clipbox (expose_region, &event.expose.area);
+
+ (*_gdk_event_func) (&event, _gdk_event_data);
+
+ g_object_unref (window);
+ }
+ else if (private->bg_pixmap != GDK_NO_BG)
+ {
+ /* No exposure mask set, so nothing will be drawn, the
+ * app relies on the background being what it specified
+ * for the window. So, we need to clear this manually.
+ *
+ * We use begin/end_paint around the clear so that we can
+ * piggyback on the implicit paint */
+
+ gdk_window_begin_paint_region (window, expose_region);
+ gdk_window_clear_region_internal (window, expose_region, FALSE);
+ gdk_window_end_paint (window);
+ }
+ }
+}
+
+static void
+gdk_window_process_updates_internal (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ gboolean save_region = FALSE;
+ GdkRectangle clip_box;
+
+ /* If an update got queued during update processing, we can get a
+ * window in the update queue that has an empty update_area.
+ * just ignore it.
+ */
+ if (private->update_area)
+ {
+ GdkRegion *update_area = private->update_area;
+ private->update_area = NULL;
+
+ if (_gdk_event_func && gdk_window_is_viewable (window) &&
+ private->window_type != GDK_WINDOW_FOREIGN)
+ {
+ GdkRectangle window_rect;
+ GdkRegion *expose_region;
+ GdkRegion *window_region;
+ gboolean end_implicit;
+
+ /* Clip to part visible in toplevel */
+ gdk_region_intersect (update_area, private->clip_region);
+
+ if (debug_updates)
+ {
+ /* Make sure we see the red invalid area before redrawing. */
+ gdk_display_sync (gdk_drawable_get_display (window));
+ g_usleep (70000);
+ }
+
+ save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
+ if (save_region)
+ expose_region = gdk_region_copy (update_area);
+ else
+ expose_region = update_area;
+
+ window_rect.x = 0;
+ window_rect.y = 0;
+ window_rect.width = private->width;
+ window_rect.height = private->height;
+
+ window_region = gdk_region_rectangle (&window_rect);
+ gdk_region_intersect (expose_region,
+ window_region);
+ gdk_region_destroy (window_region);
+
+
+ /* No need to do any moves that will end up over the update area */
+ if (private->outstanding_moves)
+ {
+ GdkWindowRegionMove *move;
+ GdkRegion *remove;
+ GList *l, *prev;
+
+ remove = gdk_region_copy (update_area);
+ for (l = g_list_last (private->outstanding_moves); l != NULL; l = prev)
+ {
+ prev = l->prev;
+ move = l->data;
+ /* Don't need this area */
+ gdk_region_subtract (move->dest_region, remove);
+
+ /* However if any of the destination we do need has a source
+ in the updated region we do need that as a destination for
+ the earlier moves */
+ gdk_region_offset (move->dest_region, -move->dx, -move->dy);
+ gdk_region_subtract (remove, move->dest_region);
+
+ if (gdk_region_empty (move->dest_region))
+ {
+ gdk_window_region_move_free (move);
+ private->outstanding_moves =
+ g_list_delete_link (private->outstanding_moves, l);
+ }
+ else
+ gdk_region_offset (move->dest_region, move->dx, move->dy);
+ }
+ gdk_region_destroy (remove);
+ }
+
+ gdk_region_get_clipbox (expose_region, &clip_box);
+ end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
+ if (end_implicit) /* rendering is not double buffered, do moves now */
+ gdk_window_flush_outstanding_moves (window);
+ _gdk_windowing_window_process_updates_recurse (window, expose_region);
+ if (end_implicit)
+ {
+ /* Do moves right before exposes are rendered */
+ gdk_window_flush_outstanding_moves (window);
+ gdk_window_end_implicit_paint (window);
+ }
+
+ if (expose_region != update_area)
+ gdk_region_destroy (expose_region);
+ }
+ if (!save_region)
+ gdk_region_destroy (update_area);
+ }
+
+ if (private->outstanding_moves)
+ {
+ /* Flush any outstanding moves, may happen if we moved a window but got
+ no actual invalid area */
+ gdk_window_flush_outstanding_moves (window);
+ }
+}
+
+static void
+flush_all_displays (void)
+{
+ GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
+ GSList *tmp_list;
+
+ for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
+ gdk_display_flush (tmp_list->data);
+
+ g_slist_free (displays);
+}
+
+/* Currently it is not possible to override
+ * gdk_window_process_all_updates in the same manner as
+ * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
+ * by implementing the GdkPaintable interface. If in the future a
+ * backend would need this, the right solution would be to add a
+ * method to GdkDisplay that can be optionally
+ * NULL. gdk_window_process_all_updates can then walk the list of open
+ * displays and call the mehod.
+ */
+
+/**
+ * gdk_window_process_all_updates:
+ *
+ * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
+ * in the application.
+ *
+ **/
+void
+gdk_window_process_all_updates (void)
+{
+ GSList *old_update_windows = update_windows;
+ GSList *tmp_list = update_windows;
+ static gboolean in_process_all_updates = FALSE;
+
+ if (in_process_all_updates)
+ return;
+
+ in_process_all_updates = TRUE;
+
+ if (update_idle)
+ g_source_remove (update_idle);
+
+ update_windows = NULL;
+ update_idle = 0;
+
+ _gdk_windowing_before_process_all_updates ();
+
+ g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
+
+ while (tmp_list)
+ {
+ GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
+
+ if (!GDK_WINDOW_DESTROYED (tmp_list->data))
+ {
+ if (private->update_freeze_count ||
+ gdk_window_is_toplevel_frozen (tmp_list->data))
+ gdk_window_add_update_window ((GdkWindow *) private);
+ else
+ gdk_window_process_updates_internal (tmp_list->data);
+ }
+
+ g_object_unref (tmp_list->data);
+ tmp_list = tmp_list->next;
+ }
+
+ g_slist_free (old_update_windows);
+
+ flush_all_displays ();
+
+ _gdk_windowing_after_process_all_updates ();
+
+ in_process_all_updates = FALSE;
+}
+
+/**
+ * gdk_window_process_updates:
+ * @window: a #GdkWindow
+ * @update_children: whether to also process updates for child windows
+ *
+ * Sends one or more expose events to @window. The areas in each
+ * expose event will cover the entire update area for the window (see
+ * gdk_window_invalidate_region() for details). Normally GDK calls
+ * gdk_window_process_all_updates() on your behalf, so there's no
+ * need to call this function unless you want to force expose events
+ * to be delivered immediately and synchronously (vs. the usual
+ * case, where GDK delivers them in an idle handler). Occasionally
+ * this is useful to produce nicer scrolling behavior, for example.
+ *
+ **/
+void
+gdk_window_process_updates (GdkWindow *window,
+ gboolean update_children)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ impl_window = gdk_window_get_impl_window (private);
+ if ((impl_window->update_area ||
+ impl_window->outstanding_moves) &&
+ !impl_window->update_freeze_count &&
+ !gdk_window_is_toplevel_frozen (window))
+ {
+ gdk_window_process_updates_internal ((GdkWindow *)impl_window);
+ gdk_window_remove_update_window ((GdkWindow *)impl_window);
+ }
+
+ if (update_children)
+ {
+ /* process updates in reverse stacking order so composition or
+ * painting over achieves the desired effect for offscreen windows
+ */
+ GList *node;
+ for (node = g_list_last (private->children); node; node = node->prev)
+ gdk_window_process_updates (node->data, TRUE);
+ }
+}
+
+/**
+ * gdk_window_invalidate_rect:
+ * @window: a #GdkWindow
+ * @rect: rectangle to invalidate or %NULL to invalidate the whole
+ * window
+ * @invalidate_children: whether to also invalidate child windows
+ *
+ * A convenience wrapper around gdk_window_invalidate_region() which
+ * invalidates a rectangular region. See
+ * gdk_window_invalidate_region() for details.
+ **/
+void
+gdk_window_invalidate_rect (GdkWindow *window,
+ const GdkRectangle *rect,
+ gboolean invalidate_children)
+{
+ GdkRectangle window_rect;
+ GdkRegion *region;
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
+ return;
+
+ if (!rect)
+ {
+ window_rect.x = 0;
+ window_rect.y = 0;
+ gdk_drawable_get_size (GDK_DRAWABLE (window),
+ &window_rect.width,
+ &window_rect.height);
+ rect = &window_rect;
+ }
+
+ region = gdk_region_rectangle (rect);
+ gdk_window_invalidate_region (window, region, invalidate_children);
+ gdk_region_destroy (region);
+}
+
+static void
+draw_ugly_color (GdkWindow *window,
+ const GdkRegion *region)
+{
+ /* Draw ugly color all over the newly-invalid region */
+ GdkColor ugly_color = { 0, 50000, 10000, 10000 };
+ GdkGC *ugly_gc;
+ GdkRectangle clipbox;
+
+ ugly_gc = gdk_gc_new (window);
+ gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
+ gdk_gc_set_clip_region (ugly_gc, region);
+
+ gdk_region_get_clipbox (region, &clipbox);
+
+ gdk_draw_rectangle (window,
+ ugly_gc,
+ TRUE,
+ clipbox.x, clipbox.y,
+ clipbox.width, clipbox.height);
+
+ g_object_unref (ugly_gc);
+}
+
+/**
+ * gdk_window_invalidate_maybe_recurse:
+ * @window: a #GdkWindow
+ * @region: a #GdkRegion
+ * @child_func: function to use to decide if to recurse to a child,
+ * %NULL means never recurse.
+ * @user_data: data passed to @child_func
+ *
+ * Adds @region to the update area for @window. The update area is the
+ * region that needs to be redrawn, or "dirty region." The call
+ * gdk_window_process_updates() sends one or more expose events to the
+ * window, which together cover the entire update area. An
+ * application would normally redraw the contents of @window in
+ * response to those expose events.
+ *
+ * GDK will call gdk_window_process_all_updates() on your behalf
+ * whenever your program returns to the main loop and becomes idle, so
+ * normally there's no need to do that manually, you just need to
+ * invalidate regions that you know should be redrawn.
+ *
+ * The @child_func parameter controls whether the region of
+ * each child window that intersects @region will also be invalidated.
+ * Only children for which @child_func returns TRUE will have the area
+ * invalidated.
+ **/
+void
+gdk_window_invalidate_maybe_recurse (GdkWindow *window,
+ const GdkRegion *region,
+ gboolean (*child_func) (GdkWindow *,
+ gpointer),
+ gpointer user_data)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
+ GdkRegion *visible_region;
+ GList *tmp_list;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (private->input_only ||
+ !GDK_WINDOW_IS_MAPPED (window) ||
+ gdk_region_empty (region))
+ return;
+
+ visible_region = gdk_drawable_get_visible_region (window);
+ gdk_region_intersect (visible_region, region);
+
+ tmp_list = private->children;
+ while (tmp_list)
+ {
+ GdkWindowObject *child = tmp_list->data;
+
+ if (!child->input_only)
+ {
+ GdkRegion *child_region;
+ GdkRectangle child_rect;
+
+ child_rect.x = child->x;
+ child_rect.y = child->y;
+ child_rect.width = child->width;
+ child_rect.height = child->height;
+ child_region = gdk_region_rectangle (&child_rect);
+
+ /* remove child area from the invalid area of the parent */
+ if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
+ !child->composited &&
+ !gdk_window_is_offscreen (child))
+ gdk_region_subtract (visible_region, child_region);
+
+ if (child_func && (*child_func) ((GdkWindow *)child, user_data))
+ {
+ GdkRegion *tmp = gdk_region_copy (region);
+
+ gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
+ gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
+ gdk_region_intersect (child_region, tmp);
+
+ gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
+ child_region, child_func, user_data);
+
+ gdk_region_destroy (tmp);
+ }
+
+ gdk_region_destroy (child_region);
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ impl_window = gdk_window_get_impl_window (private);
+
+ if (!gdk_region_empty (visible_region) ||
+ /* Even if we're not exposing anything, make sure we process
+ idles for windows with outstanding moves */
+ (impl_window->outstanding_moves != NULL &&
+ impl_window->update_area == NULL))
+ {
+ if (debug_updates)
+ draw_ugly_color (window, region);
+
+ /* Convert to impl coords */
+ gdk_region_offset (visible_region, private->abs_x, private->abs_y);
+ if (impl_window->update_area)
+ {
+ gdk_region_union (impl_window->update_area, visible_region);
+ }
+ else
+ {
+ gdk_window_add_update_window ((GdkWindow *)impl_window);
+ impl_window->update_area = gdk_region_copy (visible_region);
+
+ gdk_window_schedule_update ((GdkWindow *)impl_window);
+ }
+ }
+
+ gdk_region_destroy (visible_region);
+}
+
+static gboolean
+true_predicate (GdkWindow *window,
+ gpointer user_data)
+{
+ return TRUE;
+}
+
+/**
+ * gdk_window_invalidate_region:
+ * @window: a #GdkWindow
+ * @region: a #GdkRegion
+ * @invalidate_children: %TRUE to also invalidate child windows
+ *
+ * Adds @region to the update area for @window. The update area is the
+ * region that needs to be redrawn, or "dirty region." The call
+ * gdk_window_process_updates() sends one or more expose events to the
+ * window, which together cover the entire update area. An
+ * application would normally redraw the contents of @window in
+ * response to those expose events.
+ *
+ * GDK will call gdk_window_process_all_updates() on your behalf
+ * whenever your program returns to the main loop and becomes idle, so
+ * normally there's no need to do that manually, you just need to
+ * invalidate regions that you know should be redrawn.
+ *
+ * The @invalidate_children parameter controls whether the region of
+ * each child window that intersects @region will also be invalidated.
+ * If %FALSE, then the update area for child windows will remain
+ * unaffected. See gdk_window_invalidate_maybe_recurse if you need
+ * fine grained control over which children are invalidated.
+ **/
+void
+gdk_window_invalidate_region (GdkWindow *window,
+ const GdkRegion *region,
+ gboolean invalidate_children)
+{
+ gdk_window_invalidate_maybe_recurse (window, region,
+ invalidate_children ?
+ true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
+ NULL);
+}
+
+/**
+ * _gdk_window_invalidate_for_expose:
+ * @window: a #GdkWindow
+ * @region: a #GdkRegion
+ *
+ * Adds @region to the update area for @window. The update area is the
+ * region that needs to be redrawn, or "dirty region." The call
+ * gdk_window_process_updates() sends one or more expose events to the
+ * window, which together cover the entire update area. An
+ * application would normally redraw the contents of @window in
+ * response to those expose events.
+ *
+ * GDK will call gdk_window_process_all_updates() on your behalf
+ * whenever your program returns to the main loop and becomes idle, so
+ * normally there's no need to do that manually, you just need to
+ * invalidate regions that you know should be redrawn.
+ *
+ * This version of invalidation is used when you recieve expose events
+ * from the native window system. It exposes the native window, plus
+ * any non-native child windows (but not native child windows, as those would
+ * have gotten their own expose events).
+ **/
+void
+_gdk_window_invalidate_for_expose (GdkWindow *window,
+ const GdkRegion *region)
+{
+ gdk_window_invalidate_maybe_recurse (window, region,
+ (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
+ NULL);
+}
+
+
+/**
+ * gdk_window_get_update_area:
+ * @window: a #GdkWindow
+ *
+ * Transfers ownership of the update area from @window to the caller
+ * of the function. That is, after calling this function, @window will
+ * no longer have an invalid/dirty region; the update area is removed
+ * from @window and handed to you. If a window has no update area,
+ * gdk_window_get_update_area() returns %NULL. You are responsible for
+ * calling gdk_region_destroy() on the returned region if it's non-%NULL.
+ *
+ * Return value: the update area for @window
+ **/
+GdkRegion *
+gdk_window_get_update_area (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
+ GdkRegion *tmp_region;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+ impl_window = gdk_window_get_impl_window (private);
+
+ if (impl_window->update_area)
+ {
+ tmp_region = gdk_region_copy (private->clip_region_with_children);
+ /* Convert to impl coords */
+ gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
+ gdk_region_intersect (tmp_region, impl_window->update_area);
+
+ if (gdk_region_empty (tmp_region))
+ {
+ gdk_region_destroy (tmp_region);
+ return NULL;
+ }
+ else
+ {
+ gdk_region_subtract (impl_window->update_area, tmp_region);
+
+ if (gdk_region_empty (impl_window->update_area) &&
+ impl_window->outstanding_moves == NULL)
+ {
+ gdk_region_destroy (impl_window->update_area);
+ impl_window->update_area = NULL;
+
+ gdk_window_remove_update_window ((GdkWindow *)impl_window);
+ }
+
+ /* Convert from impl coords */
+ gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
+ return tmp_region;
+
+ }
+ }
+ else
+ return NULL;
+}
+
+/**
+ * _gdk_window_clear_update_area:
+ * @window: a #GdkWindow.
+ *
+ * Internal function to clear the update area for a window. This
+ * is called when the window is hidden or destroyed.
+ **/
+void
+_gdk_window_clear_update_area (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (private->update_area)
+ {
+ gdk_window_remove_update_window (window);
+
+ gdk_region_destroy (private->update_area);
+ private->update_area = NULL;
+ }
+}
+
+/**
+ * gdk_window_freeze_updates:
+ * @window: a #GdkWindow
+ *
+ * Temporarily freezes a window such that it won't receive expose
+ * events. The window will begin receiving expose events again when
+ * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
+ * has been called more than once, gdk_window_thaw_updates() must be called
+ * an equal number of times to begin processing exposes.
+ **/
+void
+gdk_window_freeze_updates (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ impl_window = gdk_window_get_impl_window (private);
+ impl_window->update_freeze_count++;
+}
+
+/**
+ * gdk_window_thaw_updates:
+ * @window: a #GdkWindow
+ *
+ * Thaws a window frozen with gdk_window_freeze_updates().
+ **/
+void
+gdk_window_thaw_updates (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ impl_window = gdk_window_get_impl_window (private);
+
+ g_return_if_fail (impl_window->update_freeze_count > 0);
+
+ if (--impl_window->update_freeze_count == 0)
+ gdk_window_schedule_update (GDK_WINDOW (impl_window));
+}
+
+/**
+ * gdk_window_freeze_toplevel_updates_libgtk_only:
+ * @window: a #GdkWindow
+ *
+ * Temporarily freezes a window and all its descendants such that it won't
+ * receive expose events. The window will begin receiving expose events
+ * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
+ * gdk_window_freeze_toplevel_updates_libgtk_only()
+ * has been called more than once,
+ * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
+ * an equal number of times to begin processing exposes.
+ *
+ * This function is not part of the GDK public API and is only
+ * for use by GTK+.
+ **/
+void
+gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
+
+ private->update_and_descendants_freeze_count++;
+}
+
+/**
+ * gdk_window_thaw_toplevel_updates_libgtk_only:
+ * @window: a #GdkWindow
+ *
+ * Thaws a window frozen with
+ * gdk_window_freeze_toplevel_updates_libgtk_only().
+ *
+ * This function is not part of the GDK public API and is only
+ * for use by GTK+.
+ **/
+void
+gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
+ g_return_if_fail (private->update_and_descendants_freeze_count > 0);
+
+ private->update_and_descendants_freeze_count--;
+
+ gdk_window_schedule_update (window);
+}
+
+/**
+ * gdk_window_set_debug_updates:
+ * @setting: %TRUE to turn on update debugging
+ *
+ * With update debugging enabled, calls to
+ * gdk_window_invalidate_region() clear the invalidated region of the
+ * screen to a noticeable color, and GDK pauses for a short time
+ * before sending exposes to windows during
+ * gdk_window_process_updates(). The net effect is that you can see
+ * the invalid region for each window and watch redraws as they
+ * occur. This allows you to diagnose inefficiencies in your application.
+ *
+ * In essence, because the GDK rendering model prevents all flicker,
+ * if you are redrawing the same region 400 times you may never
+ * notice, aside from noticing a speed problem. Enabling update
+ * debugging causes GTK to flicker slowly and noticeably, so you can
+ * see exactly what's being redrawn when, in what order.
+ *
+ * The --gtk-debug=updates command line option passed to GTK+ programs
+ * enables this debug option at application startup time. That's
+ * usually more useful than calling gdk_window_set_debug_updates()
+ * yourself, though you might want to use this function to enable
+ * updates sometime after application startup time.
+ *
+ **/
+void
+gdk_window_set_debug_updates (gboolean setting)
+{
+ debug_updates = setting;
+}
+
+/**
+ * gdk_window_constrain_size:
+ * @geometry: a #GdkGeometry structure
+ * @flags: a mask indicating what portions of @geometry are set
+ * @width: desired width of window
+ * @height: desired height of the window
+ * @new_width: location to store resulting width
+ * @new_height: location to store resulting height
+ *
+ * Constrains a desired width and height according to a
+ * set of geometry hints (such as minimum and maximum size).
+ */
+void
+gdk_window_constrain_size (GdkGeometry *geometry,
+ guint flags,
+ gint width,
+ gint height,
+ gint *new_width,
+ gint *new_height)
+{
+ /* This routine is partially borrowed from fvwm.
+ *
+ * Copyright 1993, Robert Nation
+ * You may use this code for any purpose, as long as the original
+ * copyright remains in the source code and all documentation
+ *
+ * which in turn borrows parts of the algorithm from uwm
+ */
+ gint min_width = 0;
+ gint min_height = 0;
+ gint base_width = 0;
+ gint base_height = 0;
+ gint xinc = 1;
+ gint yinc = 1;
+ gint max_width = G_MAXINT;
+ gint max_height = G_MAXINT;
+
+#define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
+
+ if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
+ {
+ base_width = geometry->base_width;
+ base_height = geometry->base_height;
+ min_width = geometry->min_width;
+ min_height = geometry->min_height;
+ }
+ else if (flags & GDK_HINT_BASE_SIZE)
+ {
+ base_width = geometry->base_width;
+ base_height = geometry->base_height;
+ min_width = geometry->base_width;
+ min_height = geometry->base_height;
+ }
+ else if (flags & GDK_HINT_MIN_SIZE)
+ {
+ base_width = geometry->min_width;
+ base_height = geometry->min_height;
+ min_width = geometry->min_width;
+ min_height = geometry->min_height;
+ }
+
+ if (flags & GDK_HINT_MAX_SIZE)
+ {
+ max_width = geometry->max_width ;
+ max_height = geometry->max_height;
+ }
+
+ if (flags & GDK_HINT_RESIZE_INC)
+ {
+ xinc = MAX (xinc, geometry->width_inc);
+ yinc = MAX (yinc, geometry->height_inc);
+ }
+
+ /* clamp width and height to min and max values
+ */
+ width = CLAMP (width, min_width, max_width);
+ height = CLAMP (height, min_height, max_height);
+
+ /* shrink to base + N * inc
+ */
+ width = base_width + FLOOR (width - base_width, xinc);
+ height = base_height + FLOOR (height - base_height, yinc);
+
+ /* constrain aspect ratio, according to:
+ *
+ * width
+ * min_aspect <= -------- <= max_aspect
+ * height
+ */
+
+ if (flags & GDK_HINT_ASPECT &&
+ geometry->min_aspect > 0 &&
+ geometry->max_aspect > 0)
+ {
+ gint delta;
+
+ if (geometry->min_aspect * height > width)
+ {
+ delta = FLOOR (height - width / geometry->min_aspect, yinc);
+ if (height - delta >= min_height)
+ height -= delta;
+ else
+ {
+ delta = FLOOR (height * geometry->min_aspect - width, xinc);
+ if (width + delta <= max_width)
+ width += delta;
+ }
+ }
+
+ if (geometry->max_aspect * height < width)
+ {
+ delta = FLOOR (width - height * geometry->max_aspect, xinc);
+ if (width - delta >= min_width)
+ width -= delta;
+ else
+ {
+ delta = FLOOR (width / geometry->max_aspect - height, yinc);
+ if (height + delta <= max_height)
+ height += delta;
+ }
+ }
+ }
+
+#undef FLOOR
+
+ *new_width = width;
+ *new_height = height;
+}
+
+/**
+ * gdk_window_get_pointer:
+ * @window: a #GdkWindow
+ * @x: return location for X coordinate of pointer or %NULL to not
+ * return the X coordinate
+ * @y: return location for Y coordinate of pointer or %NULL to not
+ * return the Y coordinate
+ * @mask: return location for modifier mask or %NULL to not return the
+ * modifier mask
+ *
+ * Obtains the current pointer position and modifier state.
+ * The position is given in coordinates relative to the upper left
+ * corner of @window.
+ *
+ * Return value: the window containing the pointer (as with
+ * gdk_window_at_pointer()), or %NULL if the window containing the
+ * pointer isn't known to GDK
+ **/
+GdkWindow*
+gdk_window_get_pointer (GdkWindow *window,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask)
+{
+ GdkDisplay *display;
+ gint tmp_x, tmp_y;
+ GdkModifierType tmp_mask;
+ GdkWindow *child;
+
+ g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
+
+ if (window)
+ {
+ display = gdk_drawable_get_display (window);
+ }
+ else
+ {
+ GdkScreen *screen = gdk_screen_get_default ();
+
+ display = gdk_screen_get_display (screen);
+ window = gdk_screen_get_root_window (screen);
+
+ GDK_NOTE (MULTIHEAD,
+ g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
+ "is not multihead safe"));
+ }
+
+ child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
+
+ if (x)
+ *x = tmp_x;
+ if (y)
+ *y = tmp_y;
+ if (mask)
+ *mask = tmp_mask;
+
+ _gdk_display_enable_motion_hints (display);
+
+ return child;
+}
+
+/**
+ * gdk_window_at_pointer:
+ * @win_x: return location for origin of the window under the pointer
+ * @win_y: return location for origin of the window under the pointer
+ *
+ * Obtains the window underneath the mouse pointer, returning the
+ * location of that window in @win_x, @win_y. Returns %NULL if the
+ * window under the mouse pointer is not known to GDK (if the window
+ * belongs to another application and a #GdkWindow hasn't been created
+ * for it with gdk_window_foreign_new())
+ *
+ * NOTE: For multihead-aware widgets or applications use
+ * gdk_display_get_window_at_pointer() instead.
+ *
+ * Return value: window under the mouse pointer
+ **/
+GdkWindow*
+gdk_window_at_pointer (gint *win_x,
+ gint *win_y)
+{
+ return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
+}
+
+/**
+ * gdk_get_default_root_window:
+ *
+ * Obtains the root window (parent all other windows are inside)
+ * for the default display and screen.
+ *
+ * Return value: the default root window
+ **/
+GdkWindow *
+gdk_get_default_root_window (void)
+{
+ return gdk_screen_get_root_window (gdk_screen_get_default ());
+}
+
+/**
+ * gdk_window_foreign_new:
+ * @anid: a native window handle.
+ *
+ * Wraps a native window for the default display in a #GdkWindow.
+ * This may fail if the window has been destroyed.
+ *
+ * For example in the X backend, a native window handle is an Xlib
+ * <type>XID</type>.
+ *
+ * Return value: the newly-created #GdkWindow wrapper for the
+ * native window or %NULL if the window has been destroyed.
+ **/
+GdkWindow *
+gdk_window_foreign_new (GdkNativeWindow anid)
+{
+ return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
+}
+
+static void
+get_all_native_children (GdkWindowObject *private,
+ GList **native)
+{
+ GdkWindowObject *child;
+ GList *l;
+
+ for (l = private->children; l != NULL; l = l->next)
+ {
+ child = l->data;
+
+ if (gdk_window_has_impl (child))
+ *native = g_list_prepend (*native, child);
+ else
+ get_all_native_children (child, native);
+ }
+}
+
+
+static inline void
+gdk_window_raise_internal (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *parent = private->parent;
+ GdkWindowObject *above;
+ GList *native_children;
+ GList *l, listhead;
+
+ if (parent)
+ {
+ parent->children = g_list_remove (parent->children, window);
+ parent->children = g_list_prepend (parent->children, window);
+ }
+
+ /* Just do native raise for toplevels */
+ if (private->parent == NULL ||
+ GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+ {
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
+ }
+ else if (gdk_window_has_impl (private))
+ {
+ above = find_native_sibling_above (parent, private);
+ if (above)
+ {
+ listhead.data = window;
+ listhead.next = NULL;
+ listhead.prev = NULL;
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+ &listhead);
+ }
+ else
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
+ }
+ else
+ {
+ native_children = NULL;
+ get_all_native_children (private, &native_children);
+ if (native_children != NULL)
+ {
+ above = find_native_sibling_above (parent, private);
+
+ if (above)
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+ native_children);
+ else
+ {
+ /* Right order, since native_chilren is bottom-opmost first */
+ for (l = native_children; l != NULL; l = l->next)
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
+ }
+
+ g_list_free (native_children);
+ }
+
+ }
+}
+
+static void
+show_all_visible_impls (GdkWindowObject *private, gboolean already_mapped)
+{
+ GdkWindowObject *child;
+ GList *l;
+
+ for (l = private->children; l != NULL; l = l->next)
+ {
+ child = l->data;
+ if (GDK_WINDOW_IS_MAPPED (child))
+ show_all_visible_impls (child, FALSE);
+ }
+
+ if (gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private, already_mapped);
+}
+
+static void
+gdk_window_show_internal (GdkWindow *window, gboolean raise)
+{
+ GdkWindowObject *private;
+ gboolean was_mapped;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject *) window;
+ if (private->destroyed)
+ return;
+
+ was_mapped = GDK_WINDOW_IS_MAPPED (window);
+
+ if (raise)
+ /* Keep children in (reverse) stacking order */
+ gdk_window_raise_internal (window);
+
+ if (gdk_window_has_impl (private))
+ {
+ if (!was_mapped)
+ gdk_synthesize_window_state (window,
+ GDK_WINDOW_STATE_WITHDRAWN,
+ 0);
+ }
+ else
+ {
+ private->state = 0;
+ }
+
+ if (gdk_window_is_viewable (window))
+ show_all_visible_impls (private, was_mapped);
+
+ if (!was_mapped)
+ {
+ if (private->event_mask & GDK_STRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+
+ if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+ }
+
+ if (!was_mapped || raise)
+ {
+ recompute_visible_regions (private, TRUE, FALSE);
+
+ /* If any decendants became visible we need to send visibility notify */
+ gdk_window_update_visibility_recursively (private, NULL);
+
+ if (gdk_window_is_viewable (window))
+ {
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+ gdk_window_invalidate_rect (window, NULL, TRUE);
+ }
+ }
+}
+
+/**
+ * gdk_window_show_unraised:
+ * @window: a #GdkWindow
+ *
+ * Shows a #GdkWindow onscreen, but does not modify its stacking
+ * order. In contrast, gdk_window_show() will raise the window
+ * to the top of the window stack.
+ *
+ * On the X11 platform, in Xlib terms, this function calls
+ * XMapWindow() (it also updates some internal GDK state, which means
+ * that you can't really use XMapWindow() directly on a GDK window).
+ */
+void
+gdk_window_show_unraised (GdkWindow *window)
+{
+ gdk_window_show_internal (window, FALSE);
+}
+
+/**
+ * gdk_window_raise:
+ * @window: a #GdkWindow
+ *
+ * Raises @window to the top of the Z-order (stacking order), so that
+ * other windows with the same parent window appear below @window.
+ * This is true whether or not the windows are visible.
+ *
+ * If @window is a toplevel, the window manager may choose to deny the
+ * request to move the window in the Z-order, gdk_window_raise() only
+ * requests the restack, does not guarantee it.
+ */
+void
+gdk_window_raise (GdkWindow *window)
+{
+ GdkWindowObject *private;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject *) window;
+ if (private->destroyed)
+ return;
+
+ /* Keep children in (reverse) stacking order */
+ gdk_window_raise_internal (window);
+
+ recompute_visible_regions (private, TRUE, FALSE);
+
+ gdk_window_invalidate_rect (window, NULL, TRUE);
+}
+
+static void
+gdk_window_lower_internal (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *parent = private->parent;
+ GdkWindowObject *above;
+ GList *native_children;
+ GList *l, listhead;
+
+ if (parent)
+ {
+ parent->children = g_list_remove (parent->children, window);
+ parent->children = g_list_append (parent->children, window);
+ }
+
+ /* Just do native lower for toplevels */
+ if (private->parent == NULL ||
+ GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+ {
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
+ }
+ else if (gdk_window_has_impl (private))
+ {
+ above = find_native_sibling_above (parent, private);
+ if (above)
+ {
+ listhead.data = window;
+ listhead.next = NULL;
+ listhead.prev = NULL;
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+ &listhead);
+ }
+ else
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
}
else
- gdk_draw_text_wc (private->impl, font, gc,
- x - x_offset, y - y_offset, text, text_length);
-
- RESTORE_GC (gc);
+ {
+ native_children = NULL;
+ get_all_native_children (private, &native_children);
+ if (native_children != NULL)
+ {
+ above = find_native_sibling_above (parent, private);
+
+ if (above)
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+ native_children);
+ else
+ {
+ /* Right order, since native_chilren is bottom-opmost first */
+ for (l = native_children; l != NULL; l = l->next)
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
+ }
+
+ g_list_free (native_children);
+ }
+
+ }
+}
+
+static void
+gdk_window_invalidate_in_parent (GdkWindowObject *private)
+{
+ GdkRectangle r, child;
+
+ if (private->parent == NULL ||
+ GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+ return;
+
+ /* get the visible rectangle of the parent */
+ r.x = r.y = 0;
+ r.width = private->parent->width;
+ r.height = private->parent->height;
+
+ child.x = private->x;
+ child.y = private->y;
+ child.width = private->width;
+ child.height = private->height;
+ gdk_rectangle_intersect (&r, &child, &r);
+
+ gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
+}
+
+
+/**
+ * gdk_window_lower:
+ * @window: a #GdkWindow
+ *
+ * Lowers @window to the bottom of the Z-order (stacking order), so that
+ * other windows with the same parent window appear above @window.
+ * This is true whether or not the other windows are visible.
+ *
+ * If @window is a toplevel, the window manager may choose to deny the
+ * request to move the window in the Z-order, gdk_window_lower() only
+ * requests the restack, does not guarantee it.
+ *
+ * Note that gdk_window_show() raises the window again, so don't call this
+ * function before gdk_window_show(). (Try gdk_window_show_unraised().)
+ */
+void
+gdk_window_lower (GdkWindow *window)
+{
+ GdkWindowObject *private;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject *) window;
+ if (private->destroyed)
+ return;
+
+ /* Keep children in (reverse) stacking order */
+ gdk_window_lower_internal (window);
+
+ recompute_visible_regions (private, TRUE, FALSE);
+
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+ gdk_window_invalidate_in_parent (private);
}
-static GdkDrawable*
-gdk_window_get_composite_drawable (GdkDrawable *drawable,
- gint x,
- gint y,
- gint width,
- gint height,
- gint *composite_x_offset,
- gint *composite_y_offset)
+/**
+ * gdk_window_show:
+ * @window: a #GdkWindow
+ *
+ * Like gdk_window_show_unraised(), but also raises the window to the
+ * top of the window stack (moves the window to the front of the
+ * Z-order).
+ *
+ * This function maps a window so it's visible onscreen. Its opposite
+ * is gdk_window_hide().
+ *
+ * When implementing a #GtkWidget, you should call this function on the widget's
+ * #GdkWindow as part of the "map" method.
+ */
+void
+gdk_window_show (GdkWindow *window)
{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
- GSList *list;
- GdkPixmap *tmp_pixmap;
- GdkRectangle rect;
- GdkGC *tmp_gc;
- gboolean overlap_buffer;
+ gdk_window_show_internal (window, TRUE);
+}
+
+static void
+hide_all_visible_impls (GdkWindowObject *private)
+{
+ GdkWindowObject *child;
+ GList *l;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (GDK_WINDOW (drawable),
- composite_x_offset,
- composite_y_offset);
-
- if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
- || private->paint_stack == NULL)
+ for (l = private->children; l != NULL; l = l->next)
{
- /* No backing store */
- return g_object_ref (drawable);
+ child = l->data;
+
+ if (GDK_WINDOW_IS_MAPPED (child))
+ hide_all_visible_impls (child);
}
- /* See if the buffered part is overlapping the part we want
- * to get
- */
- rect.x = x;
- rect.y = y;
- rect.width = width;
- rect.height = height;
+ if (gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
+}
- overlap_buffer = FALSE;
-
- for (list = private->paint_stack; list != NULL; list = list->next)
+
+/**
+ * gdk_window_hide:
+ * @window: a #GdkWindow
+ *
+ * For toplevel windows, withdraws them, so they will no longer be
+ * known to the window manager; for all windows, unmaps them, so
+ * they won't be displayed. Normally done automatically as
+ * part of gtk_widget_hide().
+ */
+void
+gdk_window_hide (GdkWindow *window)
+{
+ GdkWindowObject *private;
+ gboolean was_mapped, was_viewable;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject *) window;
+ if (private->destroyed)
+ return;
+
+ was_mapped = GDK_WINDOW_IS_MAPPED (private);
+ was_viewable = gdk_window_is_viewable (window);
+
+ if (gdk_window_has_impl (private))
{
- GdkWindowPaint *paint = list->data;
- GdkOverlapType overlap;
- overlap = gdk_region_rect_in (paint->region, &rect);
+ if (GDK_WINDOW_IS_MAPPED (window))
+ gdk_synthesize_window_state (window,
+ 0,
+ GDK_WINDOW_STATE_WITHDRAWN);
+ }
+ else if (was_mapped)
+ {
+ GdkDisplay *display;
- if (overlap == GDK_OVERLAP_RECTANGLE_IN)
- {
- *composite_x_offset = paint->x_offset;
- *composite_y_offset = paint->y_offset;
-
- return g_object_ref (paint->pixmap);
- }
- else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
+ /* May need to break grabs on children */
+ display = gdk_drawable_get_display (window);
+
+ if (_gdk_display_end_pointer_grab (display,
+ _gdk_windowing_window_get_next_serial (display),
+ window,
+ TRUE))
+ gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+
+ if (display->keyboard_grab.window != NULL)
{
- overlap_buffer = TRUE;
- break;
+ if (is_parent_of (window, display->keyboard_grab.window))
+ {
+ /* Call this ourselves, even though gdk_display_keyboard_ungrab
+ does so too, since we want to pass implicit == TRUE so the
+ broken grab event is generated */
+ _gdk_display_unset_has_keyboard_grab (display,
+ TRUE);
+ gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
+ }
}
+
+ private->state = GDK_WINDOW_STATE_WITHDRAWN;
}
- if (!overlap_buffer)
- return g_object_ref (drawable);
+ if (was_viewable)
+ hide_all_visible_impls (private);
- tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
- tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
+ recompute_visible_regions (private, TRUE, FALSE);
- /* Copy the current window contents */
- gdk_draw_drawable (tmp_pixmap,
- tmp_gc,
- private->impl,
- x - *composite_x_offset,
- y - *composite_y_offset,
- 0, 0,
- width, height);
+ /* all decendants became non-visible, we need to send visibility notify */
+ gdk_window_update_visibility_recursively (private, NULL);
- /* paint the backing stores */
- for (list = private->paint_stack; list != NULL; list = list->next)
+ if (was_mapped)
{
- GdkWindowPaint *paint = list->data;
-
- gdk_gc_set_clip_region (tmp_gc, paint->region);
- gdk_gc_set_clip_origin (tmp_gc, -x, -y);
-
- gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
- x - paint->x_offset,
- y - paint->y_offset,
- 0, 0, width, height);
- }
+ if (private->event_mask & GDK_STRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
- /* Reset clip region of the cached GdkGC */
- gdk_gc_set_clip_region (tmp_gc, NULL);
+ if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
- /* Set these to location of tmp_pixmap within the window */
- *composite_x_offset = x;
- *composite_y_offset = y;
+ _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
+ }
- return tmp_pixmap;
+ /* Invalidate the rect */
+ gdk_window_invalidate_in_parent (private);
}
-static GdkRegion*
-gdk_window_get_clip_region (GdkDrawable *drawable)
+/**
+ * gdk_window_withdraw:
+ * @window: a toplevel #GdkWindow
+ *
+ * Withdraws a window (unmaps it and asks the window manager to forget about it).
+ * This function is not really useful as gdk_window_hide() automatically
+ * withdraws toplevel windows before hiding them.
+ **/
+void
+gdk_window_withdraw (GdkWindow *window)
{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
- GdkRegion *result;
+ GdkWindowObject *private;
+ gboolean was_mapped;
- result = gdk_drawable_get_clip_region (private->impl);
+ g_return_if_fail (GDK_IS_WINDOW (window));
- if (private->paint_stack)
+ private = (GdkWindowObject *) window;
+ if (private->destroyed)
+ return;
+
+ was_mapped = GDK_WINDOW_IS_MAPPED (private);
+
+ if (gdk_window_has_impl (private))
{
- GdkRegion *paint_region = gdk_region_new ();
- GSList *tmp_list = private->paint_stack;
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
- while (tmp_list)
+ if (was_mapped)
{
- GdkWindowPaint *paint = tmp_list->data;
-
- gdk_region_union (paint_region, paint->region);
+ if (private->event_mask & GDK_STRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+
+ if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+ _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
- tmp_list = tmp_list->next;
+ _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
}
- gdk_region_intersect (result, paint_region);
- gdk_region_destroy (paint_region);
+ recompute_visible_regions (private, TRUE, FALSE);
}
-
- return result;
}
-static GdkRegion*
-gdk_window_get_visible_region (GdkDrawable *drawable)
+/**
+ * gdk_window_set_events:
+ * @window: a #GdkWindow
+ * @event_mask: event mask for @window
+ *
+ * The event mask for a window determines which events will be reported
+ * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
+ * means the window should report button press events. The event mask
+ * is the bitwise OR of values from the #GdkEventMask enumeration.
+ **/
+void
+gdk_window_set_events (GdkWindow *window,
+ GdkEventMask event_mask)
{
- GdkWindowObject *private = (GdkWindowObject*) drawable;
-
- return gdk_drawable_get_visible_region (private->impl);
+ GdkWindowObject *private;
+ GdkDisplay *display;
+
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject *) window;
+ if (private->destroyed)
+ return;
+
+ /* If motion hint is disabled, enable motion events again */
+ display = gdk_drawable_get_display (window);
+ if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
+ !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
+ _gdk_display_enable_motion_hints (display);
+
+ private->event_mask = event_mask;
+
+ if (gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window,
+ get_native_event_mask (private));
+
}
-static void
-gdk_window_draw_drawable (GdkDrawable *drawable,
- GdkGC *gc,
- GdkPixmap *src,
- gint xsrc,
- gint ysrc,
- gint xdest,
- gint ydest,
- gint width,
- gint height)
+/**
+ * gdk_window_get_events:
+ * @window: a #GdkWindow
+ *
+ * Gets the event mask for @window. See gdk_window_set_events().
+ *
+ * Return value: event mask for @window
+ **/
+GdkEventMask
+gdk_window_get_events (GdkWindow *window)
{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
- OFFSET_GC (gc);
-
- if (GDK_WINDOW_DESTROYED (drawable))
- return;
+ GdkWindowObject *private;
- /* If we have a backing pixmap draw to that */
- if (private->paint_stack)
- {
- GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_drawable (paint->pixmap, gc,
- src, xsrc, ysrc,
- xdest - x_offset, ydest - y_offset, width, height);
+ g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
- }
- else
- gdk_draw_drawable (private->impl, gc,
- src, xsrc, ysrc,
- xdest - x_offset, ydest - y_offset,
- width, height);
+ private = (GdkWindowObject *) window;
+ if (private->destroyed)
+ return 0;
- RESTORE_GC (gc);
+ return private->event_mask;
}
static void
-gdk_window_draw_points (GdkDrawable *drawable,
- GdkGC *gc,
- GdkPoint *points,
- gint npoints)
+gdk_window_move_resize_toplevel (GdkWindow *window,
+ gboolean with_move,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
- GdkPoint *new_points;
-
- OFFSET_GC (gc);
+ GdkWindowObject *private;
+ GdkRegion *old_region, *new_region;
+ GdkWindowObject *impl_window;
+ gboolean expose;
+ int old_x, old_y, old_abs_x, old_abs_y;
+ int dx, dy;
+ gboolean is_resize;
- if (GDK_WINDOW_DESTROYED (drawable))
- return;
-
- if (x_offset != 0 || y_offset != 0)
- {
- gint i;
+ private = (GdkWindowObject *) window;
- new_points = g_new (GdkPoint, npoints);
- for (i=0; i<npoints; i++)
- {
- new_points[i].x = points[i].x - x_offset;
- new_points[i].y = points[i].y - y_offset;
- }
+ expose = FALSE;
+ old_region = NULL;
+
+ impl_window = gdk_window_get_impl_window (private);
+
+ old_x = private->x;
+ old_y = private->y;
+
+ is_resize = (width != -1) || (height != -1);
+
+ if (GDK_WINDOW_IS_MAPPED (window) &&
+ !private->input_only)
+ {
+ expose = TRUE;
+ old_region = gdk_region_copy (private->clip_region);
}
- else
- new_points = points;
- if (private->paint_stack)
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
+
+ dx = private->x - old_x;
+ dy = private->y - old_y;
+
+ old_abs_x = private->abs_x;
+ old_abs_y = private->abs_y;
+
+ /* Avoid recomputing for pure toplevel moves, for performance reasons */
+ if (is_resize)
+ recompute_visible_regions (private, TRUE, FALSE);
+
+ if (expose)
{
- GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_points (paint->pixmap, gc, new_points, npoints);
+ new_region = gdk_region_copy (private->clip_region);
+
+ /* This is the newly exposed area (due to any resize),
+ * X will expose it, but lets do that without the
+ * roundtrip
+ */
+ gdk_region_subtract (new_region, old_region);
+ gdk_window_invalidate_region (window, new_region, TRUE);
+
+ gdk_region_destroy (old_region);
+ gdk_region_destroy (new_region);
}
- else
- gdk_draw_points (private->impl, gc, points, npoints);
- if (new_points != points)
- g_free (new_points);
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+
+static void
+move_native_children (GdkWindowObject *private)
+{
+ GList *l;
+ GdkWindowObject *child;
+
+ for (l = private->children; l; l = l->next)
+ {
+ child = l->data;
- RESTORE_GC (gc);
+ if (child->impl != private->impl)
+ GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
+ else
+ move_native_children (child);
+ }
}
-static void
-gdk_window_draw_segments (GdkDrawable *drawable,
- GdkGC *gc,
- GdkSegment *segs,
- gint nsegs)
+static gboolean
+collect_native_child_region_helper (GdkWindowObject *window,
+ GdkWindow *impl,
+ GdkRegion **region,
+ int x_offset,
+ int y_offset)
{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
- GdkSegment *new_segs;
-
- OFFSET_GC (gc);
+ GdkWindowObject *child;
+ GdkRegion *tmp;
+ GList *l;
- if (GDK_WINDOW_DESTROYED (drawable))
- return;
-
- if (x_offset != 0 || y_offset != 0)
+ for (l = window->children; l != NULL; l = l->next)
{
- gint i;
+ child = l->data;
- new_segs = g_new (GdkSegment, nsegs);
- for (i=0; i<nsegs; i++)
+ if (child->impl != impl)
{
- new_segs[i].x1 = segs[i].x1 - x_offset;
- new_segs[i].y1 = segs[i].y1 - y_offset;
- new_segs[i].x2 = segs[i].x2 - x_offset;
- new_segs[i].y2 = segs[i].y2 - y_offset;
+ tmp = gdk_region_copy (child->clip_region);
+ gdk_region_offset (tmp,
+ x_offset + child->x,
+ y_offset + child->y);
+ if (*region == NULL)
+ *region = tmp;
+ else
+ {
+ gdk_region_union (*region, tmp);
+ gdk_region_destroy (tmp);
+ }
}
+ else
+ collect_native_child_region_helper (child, impl, region,
+ x_offset + child->x,
+ y_offset + child->y);
}
- else
- new_segs = segs;
- if (private->paint_stack)
- {
- GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_segments (paint->pixmap, gc, new_segs, nsegs);
- }
- else
- gdk_draw_segments (private->impl, gc, new_segs, nsegs);
-
- if (new_segs != segs)
- g_free (new_segs);
+ return FALSE;
+}
+
+static GdkRegion *
+collect_native_child_region (GdkWindowObject *window,
+ gboolean include_this)
+{
+ GdkRegion *region;
+
+ if (include_this && gdk_window_has_impl (window))
+ return gdk_region_copy (window->clip_region);
+
+ region = NULL;
+
+ collect_native_child_region_helper (window, window->impl, ®ion, 0, 0);
- RESTORE_GC (gc);
+ return region;
}
+
static void
-gdk_window_draw_lines (GdkDrawable *drawable,
- GdkGC *gc,
- GdkPoint *points,
- gint npoints)
+gdk_window_move_resize_internal (GdkWindow *window,
+ gboolean with_move,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
- GdkPoint *new_points;
+ GdkWindowObject *private;
+ GdkRegion *old_region, *new_region, *copy_area;
+ GdkRegion *old_native_child_region, *new_native_child_region;
+ GdkWindowObject *impl_window;
+ gboolean expose;
+ int old_x, old_y, old_abs_x, old_abs_y;
+ int dx, dy;
- OFFSET_GC (gc);
+ g_return_if_fail (GDK_IS_WINDOW (window));
- if (GDK_WINDOW_DESTROYED (drawable))
+ private = (GdkWindowObject *) window;
+ if (private->destroyed)
return;
-
- if (x_offset != 0 || y_offset != 0)
- {
- gint i;
-
- new_points = g_new (GdkPoint, npoints);
- for (i=0; i<npoints; i++)
- {
- new_points[i].x = points[i].x - x_offset;
- new_points[i].y = points[i].y - y_offset;
- }
- }
- else
- new_points = points;
- if (private->paint_stack)
+ if (private->parent == NULL ||
+ GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
{
- GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_lines (paint->pixmap, gc, new_points, npoints);
+ gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
+ return;
}
- else
- gdk_draw_lines (private->impl, gc, new_points, npoints);
- if (new_points != points)
- g_free (new_points);
+ /* Handle child windows */
- RESTORE_GC (gc);
-}
+ expose = FALSE;
+ old_region = NULL;
-static void
-gdk_window_draw_glyphs (GdkDrawable *drawable,
- GdkGC *gc,
- PangoFont *font,
- gint x,
- gint y,
- PangoGlyphString *glyphs)
-{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
+ impl_window = gdk_window_get_impl_window (private);
- OFFSET_GC (gc);
+ old_x = private->x;
+ old_y = private->y;
- if (GDK_WINDOW_DESTROYED (drawable))
- return;
-
- if (private->paint_stack)
+ if (GDK_WINDOW_IS_MAPPED (window) &&
+ !private->input_only)
{
- GdkWindowPaint *paint = private->paint_stack->data;
+ expose = TRUE;
- gdk_draw_glyphs (paint->pixmap, gc, font, x - x_offset, y - y_offset, glyphs);
+ old_region = gdk_region_copy (private->clip_region);
+ /* Adjust region to parent window coords */
+ gdk_region_offset (old_region, private->x, private->y);
}
- else
- gdk_draw_glyphs (private->impl, gc, font,
- x - x_offset, y - y_offset, glyphs);
- RESTORE_GC (gc);
-}
+ old_native_child_region = collect_native_child_region (private, TRUE);
+ if (old_native_child_region)
+ {
+ /* Adjust region to parent window coords */
+ gdk_region_offset (old_native_child_region, private->x, private->y);
+
+ /* Any native window move will immediately copy stuff to the destination, which may overwrite a
+ * source or destination for a delayed GdkWindowRegionMove. So, we need
+ * to flush those here for the parent window and all overlapped subwindows
+ * of it. And we need to do this before setting the new clips as those will be
+ * affecting this.
+ */
+ gdk_window_flush_recursive (private->parent);
+ }
-static void
-gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
- GdkGC *gc,
- PangoMatrix *matrix,
- PangoFont *font,
- gint x,
- gint y,
- PangoGlyphString *glyphs)
-{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
- PangoMatrix tmp_matrix;
+ /* Set the new position and size */
+ if (with_move)
+ {
+ private->x = x;
+ private->y = y;
+ }
+ if (!(width < 0 && height < 0))
+ {
+ if (width < 1)
+ width = 1;
+ private->width = width;
+ if (height < 1)
+ height = 1;
+ private->height = height;
+ }
- OFFSET_GC (gc);
+ dx = private->x - old_x;
+ dy = private->y - old_y;
- if (GDK_WINDOW_DESTROYED (drawable))
- return;
+ old_abs_x = private->abs_x;
+ old_abs_y = private->abs_y;
- if (x_offset != 0 || y_offset != 0)
+ recompute_visible_regions (private, TRUE, FALSE);
+
+ new_native_child_region = NULL;
+ if (old_native_child_region)
{
- if (matrix)
- {
- tmp_matrix = *matrix;
- tmp_matrix.x0 -= x_offset;
- tmp_matrix.y0 -= y_offset;
- matrix = &tmp_matrix;
- }
- else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
+ new_native_child_region = collect_native_child_region (private, TRUE);
+ /* Adjust region to parent window coords */
+ gdk_region_offset (new_native_child_region, private->x, private->y);
+ }
+
+ if (gdk_window_has_impl (private))
+ {
+ /* Do the actual move after recomputing things, as this will have set the shape to
+ the now correct one, thus avoiding copying regions that should not be copied. */
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, private->x, private->y, private->width, private->height);
+ }
+ else if (old_abs_x != private->abs_x ||
+ old_abs_y != private->abs_y)
+ move_native_children (private);
+
+ if (expose)
+ {
+ new_region = gdk_region_copy (private->clip_region);
+ /* Adjust region to parent window coords */
+ gdk_region_offset (new_region, private->x, private->y);
+
+ /* copy_area:
+ * Part of the data at the new location can be copied from the
+ * old location, this area is the intersection of the old region
+ * moved as the copy will move it and then intersected with
+ * the new region.
+ *
+ * new_region:
+ * Everything in the old and new regions that is not copied must be
+ * invalidated (including children) as this is newly exposed
+ */
+ copy_area = gdk_region_copy (new_region);
+
+ gdk_region_union (new_region, old_region);
+
+ if (old_native_child_region)
{
- PangoMatrix identity = PANGO_MATRIX_INIT;
-
- tmp_matrix = identity;
- tmp_matrix.x0 -= x_offset;
- tmp_matrix.y0 -= y_offset;
- matrix = &tmp_matrix;
+ /* Don't copy from inside native children, as this is copied by
+ * the native window move.
+ */
+ gdk_region_subtract (old_region, old_native_child_region);
}
- else
+ gdk_region_offset (old_region, dx, dy);
+
+ gdk_region_intersect (copy_area, old_region);
+
+ if (new_native_child_region)
{
- x -= x_offset * PANGO_SCALE;
- y -= y_offset * PANGO_SCALE;
+ /* Don't copy any bits that would cause a read from the moved
+ native windows, as we can't read that data */
+ gdk_region_offset (new_native_child_region, dx, dy);
+ gdk_region_subtract (copy_area, new_native_child_region);
}
+
+ gdk_region_subtract (new_region, copy_area);
+
+ /* Convert old region to impl coords */
+ gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
+
+ /* convert from parent coords to impl */
+ gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
+
+ move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
+
+ /* Invalidate affected part in the parent window
+ * (no higher window should be affected)
+ * We also invalidate any children in that area, which could include
+ * this window if it still overlaps that area.
+ */
+ gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
+
+ gdk_region_destroy (old_region);
+ gdk_region_destroy (new_region);
}
-
- if (private->paint_stack)
- {
- GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_glyphs_transformed (paint->pixmap, gc, matrix, font, x, y, glyphs);
+ if (old_native_child_region)
+ {
+ gdk_region_destroy (old_native_child_region);
+ gdk_region_destroy (new_native_child_region);
}
- else
- gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
- RESTORE_GC (gc);
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
}
-typedef struct {
- cairo_t *cr; /* if non-null, it means use this cairo context */
- GdkGC *gc; /* if non-null, it means use this GC instead */
-} BackingRectMethod;
-static void
-setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
+
+/**
+ * gdk_window_move:
+ * @window: a #GdkWindow
+ * @x: X coordinate relative to window's parent
+ * @y: Y coordinate relative to window's parent
+ *
+ * Repositions a window relative to its parent window.
+ * For toplevel windows, window managers may ignore or modify the move;
+ * you should probably use gtk_window_move() on a #GtkWindow widget
+ * anyway, instead of using GDK functions. For child windows,
+ * the move will reliably succeed.
+ *
+ * If you're also planning to resize the window, use gdk_window_move_resize()
+ * to both move and resize simultaneously, for a nicer visual effect.
+ **/
+void
+gdk_window_move (GdkWindow *window,
+ gint x,
+ gint y)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
+ gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
+}
+
+/**
+ * gdk_window_resize:
+ * @window: a #GdkWindow
+ * @width: new width of the window
+ * @height: new height of the window
+ *
+ * Resizes @window; for toplevel windows, asks the window manager to resize
+ * the window. The window manager may not allow the resize. When using GTK+,
+ * use gtk_window_resize() instead of this low-level GDK function.
+ *
+ * Windows may not be resized below 1x1.
+ *
+ * If you're also planning to move the window, use gdk_window_move_resize()
+ * to both move and resize simultaneously, for a nicer visual effect.
+ **/
+void
+gdk_window_resize (GdkWindow *window,
+ gint width,
+ gint height)
+{
+ gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
+}
+
+
+/**
+ * gdk_window_move_resize:
+ * @window: a #GdkWindow
+ * @x: new X position relative to window's parent
+ * @y: new Y position relative to window's parent
+ * @width: new width
+ * @height: new height
+ *
+ * Equivalent to calling gdk_window_move() and gdk_window_resize(),
+ * except that both operations are performed at once, avoiding strange
+ * visual effects. (i.e. the user may be able to see the window first
+ * move, then resize, if you don't use gdk_window_move_resize().)
+ **/
+void
+gdk_window_move_resize (GdkWindow *window,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
+}
+
+
+/**
+ * gdk_window_scroll:
+ * @window: a #GdkWindow
+ * @dx: Amount to scroll in the X direction
+ * @dy: Amount to scroll in the Y direction
+ *
+ * Scroll the contents of @window, both pixels and children, by the
+ * given amount. @window itself does not move. Portions of the window
+ * that the scroll operation brings in from offscreen areas are
+ * invalidated. The invalidated region may be bigger than what would
+ * strictly be necessary.
+ *
+ * For X11, a minimum area will be invalidated if the window has no
+ * subwindows, or if the edges of the window's parent do not extend
+ * beyond the edges of the window. In other cases, a multi-step process
+ * is used to scroll the window which may produce temporary visual
+ * artifacts and unnecessary invalidations.
+ **/
+void
+gdk_window_scroll (GdkWindow *window,
+ gint dx,
+ gint dy)
+{
+ GdkWindowObject *private = (GdkWindowObject *) window;
+ GdkWindowObject *impl_window;
+ GdkRegion *copy_area, *noncopy_area;
+ GdkRegion *old_native_child_region, *new_native_child_region;
+ GList *tmp_list;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (dx == 0 && dy == 0)
+ return;
- if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
+ if (private->destroyed)
+ return;
+
+ old_native_child_region = collect_native_child_region (private, FALSE);
+ if (old_native_child_region)
{
- GdkWindowPaint tmp_paint;
+ /* Any native window move will immediately copy stuff to the destination, which may overwrite a
+ * source or destination for a delayed GdkWindowRegionMove. So, we need
+ * to flush those here for the window and all overlapped subwindows
+ * of it. And we need to do this before setting the new clips as those will be
+ * affecting this.
+ */
+ gdk_window_flush_recursive (private);
+ }
- tmp_paint = *paint;
- tmp_paint.x_offset += private->x;
- tmp_paint.y_offset += private->y;
- x_offset_cairo += private->x;
- y_offset_cairo += private->y;
+ /* First move all child windows, without causing invalidation */
- setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
- }
- else if (private->bg_pixmap &&
- private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
- private->bg_pixmap != GDK_NO_BG)
+ tmp_list = private->children;
+ while (tmp_list)
{
-/* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
- * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
- * pixmap destination surface, can be very slow (on the order of seconds for a
- * whole-screen copy). The workaround is to use pretty much the same code that
- * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
- * a tiled GC XFillRectangle().
- */
-
-/* Actually computing this flag is left as an exercise for the reader */
-#if defined (G_OS_UNIX)
-# define GDK_CAIRO_REPEAT_IS_FAST 0
-#else
-# define GDK_CAIRO_REPEAT_IS_FAST 1
-#endif
+ GdkWindow *child = GDK_WINDOW (tmp_list->data);
+ GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
-#if GDK_CAIRO_REPEAT_IS_FAST
- cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
- cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
- cairo_surface_destroy (surface);
+ /* Just update the positions, the bits will move with the copy */
+ child_obj->x += dx;
+ child_obj->y += dy;
- if (x_offset_cairo != 0 || y_offset_cairo != 0)
- {
- cairo_matrix_t matrix;
- cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
- cairo_pattern_set_matrix (pattern, &matrix);
- }
+ tmp_list = tmp_list->next;
+ }
- cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+ recompute_visible_regions (private, FALSE, TRUE);
- method->cr = cairo_create (paint->surface);
- method->gc = NULL;
+ new_native_child_region = NULL;
+ if (old_native_child_region)
+ new_native_child_region = collect_native_child_region (private, FALSE);
- cairo_set_source (method->cr, pattern);
- cairo_pattern_destroy (pattern);
-#else
- guint gc_mask;
- GdkGCValues gc_values;
+ move_native_children (private);
- gc_values.fill = GDK_TILED;
- gc_values.tile = private->bg_pixmap;
- gc_values.ts_x_origin = -x_offset_cairo;
- gc_values.ts_y_origin = -y_offset_cairo;
+ /* Then copy the actual bits of the window w/ child windows */
- gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
+ impl_window = gdk_window_get_impl_window (private);
- method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
-#endif
- }
- else
+ /* Calculate the area that can be gotten by copying the old area */
+ copy_area = gdk_region_copy (private->clip_region);
+ if (old_native_child_region)
{
- method->cr = cairo_create (paint->surface);
-
- gdk_cairo_set_source_color (method->cr, &private->bg_color);
+ /* Don't copy from inside native children, as this is copied by
+ * the native window move.
+ */
+ gdk_region_subtract (copy_area, old_native_child_region);
+
+ /* Don't copy any bits that would cause a read from the moved
+ native windows, as we can't read that data */
+ gdk_region_subtract (copy_area, new_native_child_region);
}
-}
-
-static void
-gdk_window_clear_backing_rect (GdkWindow *window,
- gint x,
- gint y,
- gint width,
- gint height)
-{
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkWindowPaint *paint = private->paint_stack->data;
- BackingRectMethod method;
-#if 0
- GTimer *timer;
- double elapsed;
-#endif
-
- if (GDK_WINDOW_DESTROYED (window))
- return;
+ gdk_region_offset (copy_area, dx, dy);
+ gdk_region_intersect (copy_area, private->clip_region);
-#if 0
- timer = g_timer_new ();
-#endif
+ /* And the rest need to be invalidated */
+ noncopy_area = gdk_region_copy (private->clip_region);
+ gdk_region_subtract (noncopy_area, copy_area);
- method.cr = NULL;
- method.gc = NULL;
- setup_backing_rect_method (&method, window, paint, 0, 0);
+ /* convert from window coords to impl */
+ gdk_region_offset (copy_area, private->abs_x, private->abs_y);
- if (method.cr)
- {
- g_assert (method.gc == NULL);
+ move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
- cairo_rectangle (method.cr, x, y, width, height);
- cairo_clip (method.cr);
+ /* Invalidate not copied regions */
+ gdk_window_invalidate_region (window, noncopy_area, TRUE);
- gdk_cairo_region (method.cr, paint->region);
- cairo_fill (method.cr);
+ gdk_region_destroy (noncopy_area);
- cairo_destroy (method.cr);
-#if 0
- elapsed = g_timer_elapsed (timer, NULL);
- g_print ("Draw the background with Cairo: %fs\n", elapsed);
-#endif
- }
- else
+ if (old_native_child_region)
{
- g_assert (method.gc != NULL);
-
- gdk_gc_set_clip_region (method.gc, paint->region);
- gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
- g_object_unref (method.gc);
-
-#if 0
- elapsed = g_timer_elapsed (timer, NULL);
- g_print ("Draw the background with GDK: %fs\n", elapsed);
-#endif
+ gdk_region_destroy (old_native_child_region);
+ gdk_region_destroy (new_native_child_region);
}
-#if 0
- g_timer_destroy (timer);
-#endif
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
}
-static void
-gdk_window_clear_backing_rect_redirect (GdkWindow *window,
- gint x,
- gint y,
- gint width,
- gint height)
+/**
+ * gdk_window_move_region:
+ * @window: a #GdkWindow
+ * @region: The #GdkRegion to move
+ * @dx: Amount to move in the X direction
+ * @dy: Amount to move in the Y direction
+ *
+ * Move the part of @window indicated by @region by @dy pixels in the Y
+ * direction and @dx pixels in the X direction. The portions of @region
+ * that not covered by the new position of @region are invalidated.
+ *
+ * Child windows are not moved.
+ *
+ * Since: 2.8
+ */
+void
+gdk_window_move_region (GdkWindow *window,
+ const GdkRegion *region,
+ gint dx,
+ gint dy)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkWindowRedirect *redirect = private->redirect;
- GdkRegion *clip_region;
- gint x_offset, y_offset;
- BackingRectMethod method;
- GdkWindowPaint paint;
-
- if (GDK_WINDOW_DESTROYED (window))
- return;
-
- paint.x_offset = 0;
- paint.y_offset = 0;
- paint.pixmap = redirect->pixmap;
- paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
-
- clip_region = _gdk_window_calculate_full_clip_region (window,
- GDK_WINDOW (redirect->redirected),
- NULL, TRUE,
- &x_offset, &y_offset);
- /* offset is from redirected window origin to window origin, convert to
- the offset from the redirected pixmap origin to the window origin */
- x_offset += redirect->dest_x - redirect->src_x;
- y_offset += redirect->dest_y - redirect->src_y;
+ GdkWindowObject *private = (GdkWindowObject *) window;
+ GdkWindowObject *impl_window;
+ GdkRegion *nocopy_area;
+ GdkRegion *copy_area;
- /* Convert region and rect to pixmap coords */
- gdk_region_offset (clip_region, x_offset, y_offset);
- x += x_offset;
- y += y_offset;
+ g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (region != NULL);
- method.cr = NULL;
- method.gc = NULL;
- setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
+ if (dx == 0 && dy == 0)
+ return;
- if (method.cr)
- {
- g_assert (method.gc == NULL);
+ if (private->destroyed)
+ return;
- cairo_rectangle (method.cr, x, y, width, height);
- cairo_clip (method.cr);
+ impl_window = gdk_window_get_impl_window (private);
- gdk_cairo_region (method.cr, clip_region);
- cairo_fill (method.cr);
+ /* compute source regions */
+ copy_area = gdk_region_copy (region);
+ gdk_region_intersect (copy_area, private->clip_region_with_children);
- cairo_destroy (method.cr);
- }
- else
- {
- g_assert (method.gc != NULL);
+ /* compute destination regions */
+ gdk_region_offset (copy_area, dx, dy);
+ gdk_region_intersect (copy_area, private->clip_region_with_children);
- gdk_gc_set_clip_region (method.gc, clip_region);
- gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE, x, y, width, height);
- g_object_unref (method.gc);
+ /* invalidate parts of the region not covered by the copy */
+ nocopy_area = gdk_region_copy (region);
+ gdk_region_offset (nocopy_area, dx, dy);
+ gdk_region_subtract (nocopy_area, copy_area);
+ gdk_window_invalidate_region (window, nocopy_area, FALSE);
+ gdk_region_destroy (nocopy_area);
- }
+ /* convert from window coords to impl */
+ gdk_region_offset (copy_area, private->abs_x, private->abs_y);
- gdk_region_destroy (clip_region);
- cairo_surface_destroy (paint.surface);
+ move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
}
-
/**
- * gdk_window_clear:
+ * gdk_window_set_background:
* @window: a #GdkWindow
- *
- * Clears an entire @window to the background color or background pixmap.
- **/
+ * @color: an allocated #GdkColor
+ *
+ * Sets the background color of @window. (However, when using GTK+,
+ * set the background of a widget with gtk_widget_modify_bg() - if
+ * you're an application - or gtk_style_set_background() - if you're
+ * implementing a custom widget.)
+ *
+ * The @color must be allocated; gdk_rgb_find_color() is the best way
+ * to allocate a color.
+ *
+ * See also gdk_window_set_back_pixmap().
+ */
void
-gdk_window_clear (GdkWindow *window)
+gdk_window_set_background (GdkWindow *window,
+ const GdkColor *color)
{
- gint width, height;
+ GdkWindowObject *private;
+ GdkColormap *colormap = gdk_drawable_get_colormap (window);
g_return_if_fail (GDK_IS_WINDOW (window));
- gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
-
- gdk_window_clear_area (window, 0, 0,
- width, height);
+ private = (GdkWindowObject *) window;
+
+ private->bg_color = *color;
+ gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
+
+ if (private->bg_pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG)
+ g_object_unref (private->bg_pixmap);
+
+ private->bg_pixmap = NULL;
+
+ if (!GDK_WINDOW_DESTROYED (window) &&
+ gdk_window_has_impl (private) &&
+ !private->input_only)
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
}
/**
- * gdk_window_clear_area:
+ * gdk_window_set_back_pixmap:
* @window: a #GdkWindow
- * @x: x coordinate of rectangle to clear
- * @y: y coordinate of rectangle to clear
- * @width: width of rectangle to clear
- * @height: height of rectangle to clear
+ * @pixmap: a #GdkPixmap, or %NULL
+ * @parent_relative: whether the tiling origin is at the origin of
+ * @window's parent
*
- * Clears an area of @window to the background color or background pixmap.
- *
- **/
+ * Sets the background pixmap of @window. May also be used to set a
+ * background of "None" on @window, by setting a background pixmap
+ * of %NULL.
+ *
+ * A background pixmap will be tiled, positioning the first tile at
+ * the origin of @window, or if @parent_relative is %TRUE, the tiling
+ * will be done based on the origin of the parent window (useful to
+ * align tiles in a parent with tiles in a child).
+ *
+ * A background pixmap of %NULL means that the window will have no
+ * background. A window with no background will never have its
+ * background filled by the windowing system, instead the window will
+ * contain whatever pixels were already in the corresponding area of
+ * the display.
+ *
+ * The windowing system will normally fill a window with its background
+ * when the window is obscured then exposed, and when you call
+ * gdk_window_clear().
+ */
void
-gdk_window_clear_area (GdkWindow *window,
- gint x,
- gint y,
- gint width,
- gint height)
+gdk_window_set_back_pixmap (GdkWindow *window,
+ GdkPixmap *pixmap,
+ gboolean parent_relative)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *private;
g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (pixmap == NULL || !parent_relative);
+ g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
- if (private->paint_stack)
- gdk_window_clear_backing_rect (window, x, y, width, height);
- else
+ private = (GdkWindowObject *) window;
+
+ if (pixmap && !gdk_drawable_get_colormap (pixmap))
{
- if (private->redirect)
- gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
+ g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
+ return;
+ }
+
+ if (private->bg_pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG)
+ g_object_unref (private->bg_pixmap);
+
+ if (parent_relative)
+ private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
+ else if (pixmap)
+ private->bg_pixmap = g_object_ref (pixmap);
+ else
+ private->bg_pixmap = GDK_NO_BG;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_area (window,
- x, y,
- width, height,
- FALSE);
- }
+ if (!GDK_WINDOW_DESTROYED (window) &&
+ gdk_window_has_impl (private) &&
+ !private->input_only)
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
}
/**
- * gdk_window_clear_area_e:
+ * gdk_window_set_cursor:
* @window: a #GdkWindow
- * @x: x coordinate of rectangle to clear
- * @y: y coordinate of rectangle to clear
- * @width: width of rectangle to clear
- * @height: height of rectangle to clear
- *
- * Like gdk_window_clear_area(), but also generates an expose event for
- * the cleared area.
+ * @cursor: a cursor
*
- * This function has a stupid name because it dates back to the mists
- * time, pre-GDK-1.0.
- *
- **/
+ * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
+ * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
+ * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
+ * to gdk_window_set_cursor() means that @window will use the cursor of its
+ * parent window. Most windows should use this default.
+ */
void
-gdk_window_clear_area_e (GdkWindow *window,
- gint x,
- gint y,
- gint width,
- gint height)
+gdk_window_set_cursor (GdkWindow *window,
+ GdkCursor *cursor)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *private;
+ GdkDisplay *display;
g_return_if_fail (GDK_IS_WINDOW (window));
- if (private->paint_stack)
- gdk_window_clear_backing_rect (window, x, y, width, height);
-
- if (private->redirect)
- gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_area (window,
- x, y,
- width, height,
- TRUE);
-}
-
-static void
-gdk_window_draw_image (GdkDrawable *drawable,
- GdkGC *gc,
- GdkImage *image,
- gint xsrc,
- gint ysrc,
- gint xdest,
- gint ydest,
- gint width,
- gint height)
-{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
+ private = (GdkWindowObject *) window;
+ display = gdk_drawable_get_display (window);
- OFFSET_GC (gc);
+ if (private->cursor)
+ {
+ gdk_cursor_unref (private->cursor);
+ private->cursor = NULL;
+ }
- if (GDK_WINDOW_DESTROYED (drawable))
- return;
-
- if (private->paint_stack)
+ if (!GDK_WINDOW_DESTROYED (window))
{
- GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_image (paint->pixmap, gc, image, xsrc, ysrc,
- xdest - x_offset, ydest - y_offset,
- width, height);
+ if (cursor)
+ private->cursor = gdk_cursor_ref (cursor);
+ if (is_event_parent_of (window, display->pointer_info.window_under_pointer))
+ update_cursor (display);
}
- else
- gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
- xdest - x_offset, ydest - y_offset,
- width, height);
-
- RESTORE_GC (gc);
}
-static void
-gdk_window_draw_pixbuf (GdkDrawable *drawable,
- GdkGC *gc,
- GdkPixbuf *pixbuf,
- gint src_x,
- gint src_y,
- gint dest_x,
- gint dest_y,
- gint width,
- gint height,
- GdkRgbDither dither,
- gint x_dither,
- gint y_dither)
+/**
+ * gdk_window_get_geometry:
+ * @window: a #GdkWindow
+ * @x: return location for X coordinate of window (relative to its parent)
+ * @y: return location for Y coordinate of window (relative to its parent)
+ * @width: return location for width of window
+ * @height: return location for height of window
+ * @depth: return location for bit depth of window
+ *
+ * Any of the return location arguments to this function may be %NULL,
+ * if you aren't interested in getting the value of that field.
+ *
+ * The X and Y coordinates returned are relative to the parent window
+ * of @window, which for toplevels usually means relative to the
+ * window decorations (titlebar, etc.) rather than relative to the
+ * root window (screen-size background window).
+ *
+ * On the X11 platform, the geometry is obtained from the X server,
+ * so reflects the latest position of @window; this may be out-of-sync
+ * with the position of @window delivered in the most-recently-processed
+ * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
+ * position from the most recent configure event.
+ *
+ * <note>
+ * If @window is not a toplevel, it is <emphasis>much</emphasis> better
+ * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
+ * because it avoids the roundtrip to the X server and because
+ * gdk_drawable_get_size() supports the full 32-bit coordinate space,
+ * whereas gdk_window_get_geometry() is restricted to the 16-bit
+ * coordinates of X11.
+ *</note>
+ **/
+void
+gdk_window_get_geometry (GdkWindow *window,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ gint *depth)
{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
+ GdkWindowObject *private;
- if (GDK_WINDOW_DESTROYED (drawable))
- return;
-
- if (gc)
- {
- OFFSET_GC (gc);
-
- if (private->paint_stack)
- {
- GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
- dest_x - x_offset, dest_y - y_offset,
- width, height,
- dither, x_dither - x_offset, y_dither - y_offset);
- }
- else
- gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
- dest_x - x_offset, dest_y - y_offset,
- width, height,
- dither, x_dither, y_dither);
-
- RESTORE_GC (gc);
- }
- else
+ if (!window)
{
- gint x_offset, y_offset;
- gdk_window_get_offsets (drawable, &x_offset, &y_offset);
-
- if (private->paint_stack)
- {
- GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
- dest_x - x_offset, dest_y - y_offset,
- width, height,
- dither, x_dither - x_offset, y_dither - y_offset);
- }
- else
- gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
- dest_x - x_offset, dest_y - y_offset,
- width, height,
- dither, x_dither, y_dither);
+ GDK_NOTE (MULTIHEAD,
+ g_message ("gdk_window_get_geometry(): Window needs "
+ "to be non-NULL to be multi head safe"));
+ window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
}
-}
-static void
-gdk_window_draw_trapezoids (GdkDrawable *drawable,
- GdkGC *gc,
- GdkTrapezoid *trapezoids,
- gint n_trapezoids)
-{
- GdkWindowObject *private = (GdkWindowObject *)drawable;
- GdkTrapezoid *new_trapezoids = NULL;
+ g_return_if_fail (GDK_IS_WINDOW (window));
- OFFSET_GC (gc);
+ private = (GdkWindowObject *) window;
- if (GDK_WINDOW_DESTROYED (drawable))
- return;
-
- if (x_offset != 0 || y_offset != 0)
+ if (!GDK_WINDOW_DESTROYED (window))
{
- gint i;
-
- new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
- for (i=0; i < n_trapezoids; i++)
+ if (gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
+ width, height,
+ depth);
+ else
{
- new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
- new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
- new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
- new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
- new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
- new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
+ if (x)
+ *x = private->x;
+ if (y)
+ *y = private->y;
+ if (width)
+ *width = private->width;
+ if (height)
+ *height = private->height;
+ if (depth)
+ *depth = private->depth;
}
-
- trapezoids = new_trapezoids;
- }
-
- if (private->paint_stack)
- {
- GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_trapezoids (paint->pixmap, gc, trapezoids, n_trapezoids);
}
- else
- gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
-
- g_free (new_trapezoids);
-
- RESTORE_GC (gc);
-}
-
-static void
-gdk_window_real_get_size (GdkDrawable *drawable,
- gint *width,
- gint *height)
-{
- g_return_if_fail (GDK_IS_WINDOW (drawable));
-
- gdk_drawable_get_size (GDK_WINDOW_OBJECT (drawable)->impl,
- width, height);
}
-static GdkVisual*
-gdk_window_real_get_visual (GdkDrawable *drawable)
+/**
+ * gdk_window_get_origin:
+ * @window: a #GdkWindow
+ * @x: return location for X coordinate
+ * @y: return location for Y coordinate
+ *
+ * Obtains the position of a window in root window coordinates.
+ * (Compare with gdk_window_get_position() and
+ * gdk_window_get_geometry() which return the position of a window
+ * relative to its parent window.)
+ *
+ * Return value: not meaningful, ignore
+ */
+gint
+gdk_window_get_origin (GdkWindow *window,
+ gint *x,
+ gint *y)
{
- GdkColormap *colormap;
+ GdkWindowObject *private;
- g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
+ g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
- colormap = gdk_drawable_get_colormap (drawable);
- return colormap ? gdk_colormap_get_visual (colormap) : NULL;
-}
+ private = (GdkWindowObject *) window;
-static gint
-gdk_window_real_get_depth (GdkDrawable *drawable)
-{
- g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
+ private->abs_x,
+ private->abs_y,
+ x, y);
- return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
+ return TRUE;
}
-static GdkScreen*
-gdk_window_real_get_screen (GdkDrawable *drawable)
+/**
+ * gdk_window_get_root_coords:
+ * @window: a #GdkWindow
+ * @x: X coordinate in window
+ * @y: Y coordinate in window
+ * @root_x: return location for X coordinate
+ * @root_y: return location for Y coordinate
+ *
+ * Obtains the position of a window position in root
+ * window coordinates. This is similar to
+ * gdk_window_get_origin() but allows you go pass
+ * in any position in the window, not just the origin.
+ *
+ * Return value: not meaningful, ignore
+ */
+gint
+gdk_window_get_root_coords (GdkWindow *window,
+ gint x,
+ gint y,
+ gint *root_x,
+ gint *root_y)
{
- return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
-}
+ GdkWindowObject *private;
-static void
-gdk_window_real_set_colormap (GdkDrawable *drawable,
- GdkColormap *cmap)
-{
- g_return_if_fail (GDK_IS_WINDOW (drawable));
+ g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
- if (GDK_WINDOW_DESTROYED (drawable))
- return;
-
- gdk_drawable_set_colormap (((GdkWindowObject*)drawable)->impl, cmap);
-}
+ private = (GdkWindowObject *) window;
-static GdkColormap*
-gdk_window_real_get_colormap (GdkDrawable *drawable)
-{
- g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
+ x + private->abs_x,
+ y + private->abs_y,
+ root_x, root_y);
- if (GDK_WINDOW_DESTROYED (drawable))
- return NULL;
-
- return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
+ return TRUE;
}
-
-static GdkImage*
-gdk_window_copy_to_image (GdkDrawable *drawable,
- GdkImage *image,
- gint src_x,
- gint src_y,
- gint dest_x,
- gint dest_y,
- gint width,
- gint height)
-{
- GdkWindowObject *private = (GdkWindowObject *) drawable;
- gint x_offset, y_offset;
-
- g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
-
- if (GDK_WINDOW_DESTROYED (drawable))
- return NULL;
- /* If we're here, a composite image was not necessary, so
- * we can ignore the paint stack.
- */
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (drawable,
- &x_offset, &y_offset);
-
- return gdk_drawable_copy_to_image (private->impl,
- image,
- src_x - x_offset,
- src_y - y_offset,
- dest_x, dest_y,
- width, height);
-}
-static cairo_surface_t *
-gdk_window_ref_cairo_surface (GdkDrawable *drawable)
+/**
+ * gdk_window_get_deskrelative_origin:
+ * @window: a toplevel #GdkWindow
+ * @x: return location for X coordinate
+ * @y: return location for Y coordinate
+ *
+ * This gets the origin of a #GdkWindow relative to
+ * an Enlightenment-window-manager desktop. As long as you don't
+ * assume that the user's desktop/workspace covers the entire
+ * root window (i.e. you don't assume that the desktop begins
+ * at root window coordinate 0,0) this function is not necessary.
+ * It's deprecated for that reason.
+ *
+ * Return value: not meaningful
+ **/
+gboolean
+gdk_window_get_deskrelative_origin (GdkWindow *window,
+ gint *x,
+ gint *y)
{
- GdkWindowObject *private = (GdkWindowObject*) drawable;
- cairo_surface_t *surface;
+ GdkWindowObject *private;
+ gboolean return_val = FALSE;
+ gint tx = 0;
+ gint ty = 0;
- if (private->paint_stack)
+ g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+ private = (GdkWindowObject *) window;
+
+ if (!GDK_WINDOW_DESTROYED (window))
{
- GdkWindowPaint *paint = private->paint_stack->data;
+ return_val = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_deskrelative_origin (window, &tx, &ty);
- surface = paint->surface;
- cairo_surface_reference (surface);
+ if (x)
+ *x = tx + private->abs_x;
+ if (y)
+ *y = ty + private->abs_y;
}
- else
- surface = _gdk_drawable_ref_cairo_surface (private->impl);
- return surface;
+ return return_val;
}
-/* Code for dirty-region queueing
+/**
+ * gdk_window_shape_combine_mask:
+ * @window: a #GdkWindow
+ * @mask: shape mask
+ * @x: X position of shape mask with respect to @window
+ * @y: Y position of shape mask with respect to @window
+ *
+ * Applies a shape mask to @window. Pixels in @window corresponding to
+ * set bits in the @mask will be visible; pixels in @window
+ * corresponding to unset bits in the @mask will be transparent. This
+ * gives a non-rectangular window.
+ *
+ * If @mask is %NULL, the shape mask will be unset, and the @x/@y
+ * parameters are not used.
+ *
+ * On the X11 platform, this uses an X server extension which is
+ * widely available on most common platforms, but not available on
+ * very old X servers, and occasionally the implementation will be
+ * buggy. On servers without the shape extension, this function
+ * will do nothing.
+ *
+ * This function works on both toplevel and child windows.
*/
-static GSList *update_windows = NULL;
-static guint update_idle = 0;
-static gboolean debug_updates = FALSE;
-
-static gboolean
-gdk_window_update_idle (gpointer data)
+void
+gdk_window_shape_combine_mask (GdkWindow *window,
+ GdkBitmap *mask,
+ gint x,
+ gint y)
{
- gdk_window_process_all_updates ();
-
- return FALSE;
-}
+ GdkWindowObject *private;
+ GdkRegion *region;
-static gboolean
-gdk_window_is_toplevel_frozen (GdkWindow *window)
-{
- GdkWindowObject *toplevel;
+ g_return_if_fail (GDK_IS_WINDOW (window));
- toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
+ private = (GdkWindowObject *) window;
- return toplevel->update_and_descendants_freeze_count > 0;
+ if (mask)
+ region = _gdk_windowing_get_shape_for_mask (mask);
+ else
+ region = NULL;
+
+ gdk_window_shape_combine_region (window,
+ region,
+ x, y);
+
+ if (region)
+ gdk_region_destroy (region);
}
-static void
-gdk_window_schedule_update (GdkWindow *window)
+/**
+ * gdk_window_shape_combine_region:
+ * @window: a #GdkWindow
+ * @shape_region: region of window to be non-transparent
+ * @offset_x: X position of @shape_region in @window coordinates
+ * @offset_y: Y position of @shape_region in @window coordinates
+ *
+ * Makes pixels in @window outside @shape_region be transparent,
+ * so that the window may be nonrectangular. See also
+ * gdk_window_shape_combine_mask() to use a bitmap as the mask.
+ *
+ * If @shape_region is %NULL, the shape will be unset, so the whole
+ * window will be opaque again. @offset_x and @offset_y are ignored
+ * if @shape_region is %NULL.
+ *
+ * On the X11 platform, this uses an X server extension which is
+ * widely available on most common platforms, but not available on
+ * very old X servers, and occasionally the implementation will be
+ * buggy. On servers without the shape extension, this function
+ * will do nothing.
+ *
+ * This function works on both toplevel and child windows.
+ */
+void
+gdk_window_shape_combine_region (GdkWindow *window,
+ const GdkRegion *shape_region,
+ gint offset_x,
+ gint offset_y)
{
- if (window &&
- (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
- gdk_window_is_toplevel_frozen (window)))
+ GdkWindowObject *private;
+ GdkRegion *old_region, *new_region, *diff;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject *) window;
+
+ if (GDK_WINDOW_DESTROYED (window))
return;
- if (!update_idle)
+ private->shaped = (shape_region != NULL);
+
+ if (private->shape)
+ gdk_region_destroy (private->shape);
+
+ old_region = NULL;
+ if (GDK_WINDOW_IS_MAPPED (window))
+ old_region = gdk_region_copy (private->clip_region);
+
+ if (shape_region)
{
- update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
- gdk_window_update_idle, NULL, NULL);
+ private->shape = gdk_region_copy (shape_region);
+ gdk_region_offset (private->shape, offset_x, offset_y);
}
-}
+ else
+ private->shape = NULL;
-static void
-gdk_window_process_updates_internal (GdkWindow *window)
-{
- GdkWindowObject *private = (GdkWindowObject *)window;
- gboolean save_region = FALSE;
+ recompute_visible_regions (private, TRUE, FALSE);
- /* If an update got queued during update processing, we can get a
- * window in the update queue that has an empty update_area.
- * just ignore it.
- */
- if (private->update_area)
+ if (old_region)
{
- GdkRegion *update_area = private->update_area;
- private->update_area = NULL;
-
- if (_gdk_event_func && gdk_window_is_viewable (window))
- {
- GdkRectangle window_rect;
- GdkRegion *expose_region;
- GdkRegion *window_region;
- gint width, height;
+ new_region = gdk_region_copy (private->clip_region);
- if (debug_updates)
- {
- /* Make sure we see the red invalid area before redrawing. */
- gdk_display_sync (gdk_drawable_get_display (window));
- g_usleep (70000);
- }
-
- save_region = _gdk_windowing_window_queue_antiexpose (window, update_area);
+ /* New area in the window, needs invalidation */
+ diff = gdk_region_copy (new_region);
+ gdk_region_subtract (diff, old_region);
- if (save_region)
- expose_region = gdk_region_copy (update_area);
- else
- expose_region = update_area;
-
- gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height);
+ gdk_window_invalidate_region (window, diff, TRUE);
- window_rect.x = 0;
- window_rect.y = 0;
- window_rect.width = width;
- window_rect.height = height;
+ gdk_region_destroy (diff);
- window_region = gdk_region_rectangle (&window_rect);
- gdk_region_intersect (expose_region,
- window_region);
- gdk_region_destroy (window_region);
-
- if (!gdk_region_empty (expose_region) &&
- (private->event_mask & GDK_EXPOSURE_MASK))
- {
- GdkEvent event;
-
- event.expose.type = GDK_EXPOSE;
- event.expose.window = g_object_ref (window);
- event.expose.send_event = FALSE;
- event.expose.count = 0;
- event.expose.region = expose_region;
- gdk_region_get_clipbox (expose_region, &event.expose.area);
-
- (*_gdk_event_func) (&event, _gdk_event_data);
-
- g_object_unref (window);
- }
+ if (private->parent != NULL &&
+ GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+ {
+ /* New area in the non-root parent window, needs invalidation */
+ diff = gdk_region_copy (old_region);
+ gdk_region_subtract (diff, new_region);
- if (expose_region != update_area)
- gdk_region_destroy (expose_region);
+ /* Adjust region to parent window coords */
+ gdk_region_offset (diff, private->x, private->y);
+
+ gdk_window_invalidate_region (GDK_WINDOW (private->parent), diff, TRUE);
+
+ gdk_region_destroy (diff);
}
- if (!save_region)
- gdk_region_destroy (update_area);
+
+ gdk_region_destroy (new_region);
+ gdk_region_destroy (old_region);
}
}
static void
-flush_all_displays (void)
+do_child_shapes (GdkWindow *window,
+ gboolean merge)
{
- GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
- GSList *tmp_list;
+ GdkWindowObject *private;
+ GdkRectangle r;
+ GdkRegion *region;
- for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
- gdk_display_flush (tmp_list->data);
+ private = (GdkWindowObject *) window;
- g_slist_free (displays);
-}
+ r.x = 0;
+ r.y = 0;
+ r.width = private->width;
+ r.height = private->height;
-/* Currently it is not possible to override
- * gdk_window_process_all_updates in the same manner as
- * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
- * by implementing the GdkPaintable interface. If in the future a
- * backend would need this, the right solution would be to add a
- * method to GdkDisplay that can be optionally
- * NULL. gdk_window_process_all_updates can then walk the list of open
- * displays and call the mehod.
- */
+ region = gdk_region_rectangle (&r);
+ remove_child_area (private, NULL, FALSE, region);
+
+ if (merge && private->shape)
+ gdk_region_subtract (region, private->shape);
+
+ gdk_window_shape_combine_region (window, region, 0, 0);
+}
/**
- * gdk_window_process_all_updates:
+ * gdk_window_set_child_shapes:
+ * @window: a #GdkWindow
*
- * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
- * in the application.
- *
+ * Sets the shape mask of @window to the union of shape masks
+ * for all children of @window, ignoring the shape mask of @window
+ * itself. Contrast with gdk_window_merge_child_shapes() which includes
+ * the shape mask of @window in the masks to be merged.
**/
void
-gdk_window_process_all_updates (void)
+gdk_window_set_child_shapes (GdkWindow *window)
{
- GSList *old_update_windows = update_windows;
- GSList *tmp_list = update_windows;
-
- if (update_idle)
- g_source_remove (update_idle);
-
- update_windows = NULL;
- update_idle = 0;
-
- g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
-
- while (tmp_list)
- {
- GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
-
- if (!GDK_WINDOW_DESTROYED (tmp_list->data))
- {
- if (private->update_freeze_count ||
- gdk_window_is_toplevel_frozen (tmp_list->data))
- update_windows = g_slist_prepend (update_windows, private);
- else
- gdk_window_process_updates_internal (tmp_list->data);
- }
-
- g_object_unref (tmp_list->data);
- tmp_list = tmp_list->next;
- }
-
- g_slist_free (old_update_windows);
+ g_return_if_fail (GDK_IS_WINDOW (window));
- flush_all_displays ();
+ do_child_shapes (window, FALSE);
}
/**
- * gdk_window_process_updates:
+ * gdk_window_merge_child_shapes:
* @window: a #GdkWindow
- * @update_children: whether to also process updates for child windows
*
- * Sends one or more expose events to @window. The areas in each
- * expose event will cover the entire update area for the window (see
- * gdk_window_invalidate_region() for details). Normally GDK calls
- * gdk_window_process_all_updates() on your behalf, so there's no
- * need to call this function unless you want to force expose events
- * to be delivered immediately and synchronously (vs. the usual
- * case, where GDK delivers them in an idle handler). Occasionally
- * this is useful to produce nicer scrolling behavior, for example.
- *
- **/
+ * Merges the shape masks for any child windows into the
+ * shape mask for @window. i.e. the union of all masks
+ * for @window and its children will become the new mask
+ * for @window. See gdk_window_shape_combine_mask().
+ *
+ * This function is distinct from gdk_window_set_child_shapes()
+ * because it includes @window's shape mask in the set of shapes to
+ * be merged.
+ */
void
-gdk_window_process_updates (GdkWindow *window,
- gboolean update_children)
+gdk_window_merge_child_shapes (GdkWindow *window)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
-
g_return_if_fail (GDK_IS_WINDOW (window));
- if (GDK_IS_PAINTABLE (private->impl))
- {
- GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
-
- if (iface->process_updates)
- iface->process_updates ((GdkPaintable*)private->impl, update_children);
-
- return;
- }
-
- if (private->update_area &&
- !private->update_freeze_count &&
- !gdk_window_is_toplevel_frozen (window))
- {
- gdk_window_process_updates_internal (window);
- update_windows = g_slist_remove (update_windows, window);
- }
-
- if (update_children)
- {
- GList *tmp_list = private->children;
- while (tmp_list)
- {
- gdk_window_process_updates (tmp_list->data, TRUE);
- tmp_list = tmp_list->next;
- }
- }
+ do_child_shapes (window, TRUE);
}
/**
- * gdk_window_invalidate_rect:
+ * gdk_window_input_shape_combine_mask:
* @window: a #GdkWindow
- * @rect: rectangle to invalidate or %NULL to invalidate the whole
- * window
- * @invalidate_children: whether to also invalidate child windows
+ * @mask: shape mask
+ * @x: X position of shape mask with respect to @window
+ * @y: Y position of shape mask with respect to @window
*
- * A convenience wrapper around gdk_window_invalidate_region() which
- * invalidates a rectangular region. See
- * gdk_window_invalidate_region() for details.
- **/
+ * Like gdk_window_shape_combine_mask(), but the shape applies
+ * only to event handling. Mouse events which happen while
+ * the pointer position corresponds to an unset bit in the
+ * mask will be passed on the window below @window.
+ *
+ * An input shape is typically used with RGBA windows.
+ * The alpha channel of the window defines which pixels are
+ * invisible and allows for nicely antialiased borders,
+ * and the input shape controls where the window is
+ * "clickable".
+ *
+ * On the X11 platform, this requires version 1.1 of the
+ * shape extension.
+ *
+ * On the Win32 platform, this functionality is not present and the
+ * function does nothing.
+ *
+ * Since: 2.10
+ */
void
-gdk_window_invalidate_rect (GdkWindow *window,
- const GdkRectangle *rect,
- gboolean invalidate_children)
+gdk_window_input_shape_combine_mask (GdkWindow *window,
+ GdkBitmap *mask,
+ gint x,
+ gint y)
{
- GdkRectangle window_rect;
+ GdkWindowObject *private;
GdkRegion *region;
- GdkWindowObject *private = (GdkWindowObject *)window;
g_return_if_fail (GDK_IS_WINDOW (window));
- if (GDK_WINDOW_DESTROYED (window))
- return;
-
- if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
- return;
-
- if (!rect)
- {
- window_rect.x = 0;
- window_rect.y = 0;
- gdk_drawable_get_size (GDK_DRAWABLE (window),
- &window_rect.width,
- &window_rect.height);
- rect = &window_rect;
- }
+ private = (GdkWindowObject *) window;
- region = gdk_region_rectangle (rect);
- gdk_window_invalidate_region (window, region, invalidate_children);
- gdk_region_destroy (region);
-}
+ if (mask)
+ region = _gdk_windowing_get_shape_for_mask (mask);
+ else
+ region = NULL;
-static void
-draw_ugly_color (GdkWindow *window,
- const GdkRegion *region)
-{
- /* Draw ugly color all over the newly-invalid region */
- GdkColor ugly_color = { 0, 50000, 10000, 10000 };
- GdkGC *ugly_gc;
- GdkRectangle clipbox;
-
- ugly_gc = gdk_gc_new (window);
- gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
- gdk_gc_set_clip_region (ugly_gc, region);
+ gdk_window_input_shape_combine_region (window,
+ region,
+ x, y);
- gdk_region_get_clipbox (region, &clipbox);
-
- gdk_draw_rectangle (window,
- ugly_gc,
- TRUE,
- clipbox.x, clipbox.y,
- clipbox.width, clipbox.height);
-
- g_object_unref (ugly_gc);
+ gdk_region_destroy (region);
}
/**
- * gdk_window_invalidate_maybe_recurse:
+ * gdk_window_input_shape_combine_region:
* @window: a #GdkWindow
- * @region: a #GdkRegion
- * @child_func: function to use to decide if to recurse to a child,
- * %NULL means never recurse.
- * @user_data: data passed to @child_func
+ * @shape_region: region of window to be non-transparent
+ * @offset_x: X position of @shape_region in @window coordinates
+ * @offset_y: Y position of @shape_region in @window coordinates
*
- * Adds @region to the update area for @window. The update area is the
- * region that needs to be redrawn, or "dirty region." The call
- * gdk_window_process_updates() sends one or more expose events to the
- * window, which together cover the entire update area. An
- * application would normally redraw the contents of @window in
- * response to those expose events.
+ * Like gdk_window_shape_combine_region(), but the shape applies
+ * only to event handling. Mouse events which happen while
+ * the pointer position corresponds to an unset bit in the
+ * mask will be passed on the window below @window.
*
- * GDK will call gdk_window_process_all_updates() on your behalf
- * whenever your program returns to the main loop and becomes idle, so
- * normally there's no need to do that manually, you just need to
- * invalidate regions that you know should be redrawn.
+ * An input shape is typically used with RGBA windows.
+ * The alpha channel of the window defines which pixels are
+ * invisible and allows for nicely antialiased borders,
+ * and the input shape controls where the window is
+ * "clickable".
*
- * The @child_func parameter controls whether the region of
- * each child window that intersects @region will also be invalidated.
- * Only children for which @child_func returns TRUE will have the area
- * invalidated.
- **/
+ * On the X11 platform, this requires version 1.1 of the
+ * shape extension.
+ *
+ * On the Win32 platform, this functionality is not present and the
+ * function does nothing.
+ *
+ * Since: 2.10
+ */
void
-gdk_window_invalidate_maybe_recurse (GdkWindow *window,
- const GdkRegion *region,
- gboolean (*child_func) (GdkWindow *,
- gpointer),
- gpointer user_data)
+gdk_window_input_shape_combine_region (GdkWindow *window,
+ const GdkRegion *shape_region,
+ gint offset_x,
+ gint offset_y)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkRegion *visible_region;
- GList *tmp_list;
+ GdkWindowObject *private;
g_return_if_fail (GDK_IS_WINDOW (window));
+ private = (GdkWindowObject *) window;
+
if (GDK_WINDOW_DESTROYED (window))
return;
-
- if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
- return;
-
- if (GDK_IS_PAINTABLE (private->impl))
- {
- GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
- if (iface->invalidate_maybe_recurse)
- iface->invalidate_maybe_recurse ((GdkPaintable*)private->impl,
- region, child_func, user_data);
- return;
- }
+ if (private->input_shape)
+ gdk_region_destroy (private->input_shape);
- /* windows that a redirection has ben setup for need to be considered
- * fully visible, in order to avoid missing redirected paint ops
- * anywhere in the window area.
- */
- if (private->redirect && private->redirect->redirected == private)
+ if (shape_region)
{
- GdkRectangle visible_rect = { 0, 0, 0, 0 };
- gdk_drawable_get_size (GDK_DRAWABLE (window), &visible_rect.width, &visible_rect.height);
- visible_region = gdk_region_rectangle (&visible_rect);
+ private->input_shape = gdk_region_copy (shape_region);
+ gdk_region_offset (private->input_shape, offset_x, offset_y);
}
else
- visible_region = gdk_drawable_get_visible_region (window);
- gdk_region_intersect (visible_region, region);
+ private->input_shape = NULL;
- tmp_list = private->children;
- while (tmp_list)
- {
- GdkWindowObject *child = tmp_list->data;
-
- if (!child->input_only)
- {
- GdkRegion *child_region;
- GdkRectangle child_rect;
-
- gdk_window_get_position ((GdkWindow *)child,
- &child_rect.x, &child_rect.y);
- gdk_drawable_get_size ((GdkDrawable *)child,
- &child_rect.width, &child_rect.height);
+ if (gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
- child_region = gdk_region_rectangle (&child_rect);
-
- /* remove child area from the invalid area of the parent */
- if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
- !child->composited)
- gdk_region_subtract (visible_region, child_region);
-
- if (child_func && (*child_func) ((GdkWindow *)child, user_data))
- {
- GdkRegion *tmp = gdk_region_copy (region);
+ /* Pointer may have e.g. moved outside window due to the input mask change */
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
- gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
- gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
- gdk_region_intersect (child_region, tmp);
-
- gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
- child_region, child_func, user_data);
-
- gdk_region_destroy (tmp);
- }
+static void
+do_child_input_shapes (GdkWindow *window,
+ gboolean merge)
+{
+ GdkWindowObject *private;
+ GdkRectangle r;
+ GdkRegion *region;
- gdk_region_destroy (child_region);
- }
+ private = (GdkWindowObject *) window;
- tmp_list = tmp_list->next;
- }
-
- if (!gdk_region_empty (visible_region))
- {
- if (debug_updates)
- draw_ugly_color (window, region);
+ r.x = 0;
+ r.y = 0;
+ r.width = private->width;
+ r.height = private->height;
- if (private->update_area)
- {
- gdk_region_union (private->update_area, visible_region);
- }
- else
- {
- update_windows = g_slist_prepend (update_windows, window);
- private->update_area = gdk_region_copy (visible_region);
-
- gdk_window_schedule_update (window);
- }
- }
-
- gdk_region_destroy (visible_region);
+ region = gdk_region_rectangle (&r);
+ remove_child_area (private, NULL, TRUE, region);
+
+ if (merge && private->shape)
+ gdk_region_subtract (region, private->shape);
+ if (merge && private->input_shape)
+ gdk_region_subtract (region, private->input_shape);
+
+ gdk_window_input_shape_combine_region (window, region, 0, 0);
}
-static gboolean
-true_predicate (GdkWindow *window,
- gpointer user_data)
+
+/**
+ * gdk_window_set_child_input_shapes:
+ * @window: a #GdkWindow
+ *
+ * Sets the input shape mask of @window to the union of input shape masks
+ * for all children of @window, ignoring the input shape mask of @window
+ * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
+ * the input shape mask of @window in the masks to be merged.
+ *
+ * Since: 2.10
+ **/
+void
+gdk_window_set_child_input_shapes (GdkWindow *window)
{
- return TRUE;
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ do_child_input_shapes (window, FALSE);
}
/**
- * gdk_window_invalidate_region:
+ * gdk_window_merge_child_input_shapes:
* @window: a #GdkWindow
- * @region: a #GdkRegion
- * @invalidate_children: %TRUE to also invalidate child windows
*
- * Adds @region to the update area for @window. The update area is the
- * region that needs to be redrawn, or "dirty region." The call
- * gdk_window_process_updates() sends one or more expose events to the
- * window, which together cover the entire update area. An
- * application would normally redraw the contents of @window in
- * response to those expose events.
+ * Merges the input shape masks for any child windows into the
+ * input shape mask for @window. i.e. the union of all input masks
+ * for @window and its children will become the new input mask
+ * for @window. See gdk_window_input_shape_combine_mask().
*
- * GDK will call gdk_window_process_all_updates() on your behalf
- * whenever your program returns to the main loop and becomes idle, so
- * normally there's no need to do that manually, you just need to
- * invalidate regions that you know should be redrawn.
+ * This function is distinct from gdk_window_set_child_input_shapes()
+ * because it includes @window's input shape mask in the set of
+ * shapes to be merged.
*
- * The @invalidate_children parameter controls whether the region of
- * each child window that intersects @region will also be invalidated.
- * If %FALSE, then the update area for child windows will remain
- * unaffected. See gdk_window_invalidate_maybe_recurse if you need
- * fine grained control over which children are invalidated.
+ * Since: 2.10
**/
void
-gdk_window_invalidate_region (GdkWindow *window,
- const GdkRegion *region,
- gboolean invalidate_children)
+gdk_window_merge_child_input_shapes (GdkWindow *window)
{
- gdk_window_invalidate_maybe_recurse (window, region,
- invalidate_children ?
- true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
- NULL);
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ do_child_input_shapes (window, TRUE);
}
+
/**
- * gdk_window_get_update_area:
+ * gdk_window_set_static_gravities:
* @window: a #GdkWindow
- *
- * Transfers ownership of the update area from @window to the caller
- * of the function. That is, after calling this function, @window will
- * no longer have an invalid/dirty region; the update area is removed
- * from @window and handed to you. If a window has no update area,
- * gdk_window_get_update_area() returns %NULL. You are responsible for
- * calling gdk_region_destroy() on the returned region if it's non-%NULL.
- *
- * Return value: the update area for @window
- **/
-GdkRegion *
-gdk_window_get_update_area (GdkWindow *window)
+ * @use_static: %TRUE to turn on static gravity
+ *
+ * Set the bit gravity of the given window to static, and flag it so
+ * all children get static subwindow gravity. This is used if you are
+ * implementing scary features that involve deep knowledge of the
+ * windowing system. Don't worry about it unless you have to.
+ *
+ * Return value: %TRUE if the server supports static gravity
+ */
+gboolean
+gdk_window_set_static_gravities (GdkWindow *window,
+ gboolean use_static)
+{
+ GdkWindowObject *private;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+ private = (GdkWindowObject *) window;
+
+ if (gdk_window_has_impl (private))
+ return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
+
+ return FALSE;
+}
+
+/**
+ * gdk_window_set_composited:
+ * @window: a #GdkWindow
+ * @composited: %TRUE to set the window as composited
+ *
+ * Sets a #GdkWindow as composited, or unsets it. Composited
+ * windows do not automatically have their contents drawn to
+ * the screen. Drawing is redirected to an offscreen buffer
+ * and an expose event is emitted on the parent of the composited
+ * window. It is the responsibility of the parent's expose handler
+ * to manually merge the off-screen content onto the screen in
+ * whatever way it sees fit. See <xref linkend="composited-window-example"/>
+ * for an example.
+ *
+ * It only makes sense for child windows to be composited; see
+ * gdk_window_set_opacity() if you need translucent toplevel
+ * windows.
+ *
+ * An additional effect of this call is that the area of this
+ * window is no longer clipped from regions marked for
+ * invalidation on its parent. Draws done on the parent
+ * window are also no longer clipped by the child.
+ *
+ * This call is only supported on some systems (currently,
+ * only X11 with new enough Xcomposite and Xdamage extensions).
+ * You must call gdk_display_supports_composite() to check if
+ * setting a window as composited is supported before
+ * attempting to do so.
+ *
+ * Since: 2.12
+ */
+void
+gdk_window_set_composited (GdkWindow *window,
+ gboolean composited)
{
GdkWindowObject *private = (GdkWindowObject *)window;
- GdkRegion *tmp_region;
+ GdkDisplay *display;
- g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+ g_return_if_fail (GDK_IS_WINDOW (window));
- if (private->update_area)
+ composited = composited != FALSE;
+
+ if (private->composited == composited)
+ return;
+
+ if (composited)
+ gdk_window_ensure_native (window);
+
+ display = gdk_drawable_get_display (GDK_DRAWABLE (window));
+
+ if (!gdk_display_supports_composite (display) && composited)
{
- tmp_region = private->update_area;
- private->update_area = NULL;
+ g_warning ("gdk_window_set_composited called but "
+ "compositing is not supported");
+ return;
+ }
+
+ _gdk_windowing_window_set_composited (window, composited);
+
+ recompute_visible_regions (private, TRUE, FALSE);
+
+ if (GDK_WINDOW_IS_MAPPED (window))
+ gdk_window_invalidate_in_parent (private);
- update_windows = g_slist_remove (update_windows, window);
-
- return tmp_region;
- }
- else
- return NULL;
+ private->composited = composited;
}
-/**
- * _gdk_window_clear_update_area:
- * @window: a #GdkWindow.
- *
- * Internal function to clear the update area for a window. This
- * is called when the window is hidden or destroyed.
- **/
-void
-_gdk_window_clear_update_area (GdkWindow *window)
-{
- GdkWindowObject *private = (GdkWindowObject *)window;
- g_return_if_fail (GDK_IS_WINDOW (window));
+static void
+remove_redirect_from_children (GdkWindowObject *private,
+ GdkWindowRedirect *redirect)
+{
+ GList *l;
+ GdkWindowObject *child;
- if (private->update_area)
+ for (l = private->children; l != NULL; l = l->next)
{
- update_windows = g_slist_remove (update_windows, window);
-
- gdk_region_destroy (private->update_area);
- private->update_area = NULL;
+ child = l->data;
+
+ /* Don't redirect this child if it already has another redirect */
+ if (child->redirect == redirect)
+ {
+ child->redirect = NULL;
+ remove_redirect_from_children (child, redirect);
+ }
}
}
/**
- * gdk_window_freeze_updates:
+ * gdk_window_remove_redirection:
* @window: a #GdkWindow
- *
- * Temporarily freezes a window such that it won't receive expose
- * events. The window will begin receiving expose events again when
- * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
- * has been called more than once, gdk_window_thaw_updates() must be called
- * an equal number of times to begin processing exposes.
+ *
+ * Removes any active redirection started by
+ * gdk_window_redirect_to_drawable().
+ *
+ * Since: 2.14
**/
void
-gdk_window_freeze_updates (GdkWindow *window)
+gdk_window_remove_redirection (GdkWindow *window)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *private;
g_return_if_fail (GDK_IS_WINDOW (window));
- private->update_freeze_count++;
+ private = (GdkWindowObject *) window;
+
+ if (private->redirect &&
+ private->redirect->redirected == private)
+ {
+ remove_redirect_from_children (private, private->redirect);
+ gdk_window_redirect_free (private->redirect);
+ private->redirect = NULL;
+ }
}
-/**
- * gdk_window_thaw_updates:
- * @window: a #GdkWindow
- *
- * Thaws a window frozen with gdk_window_freeze_updates().
- **/
-void
-gdk_window_thaw_updates (GdkWindow *window)
+static void
+apply_redirect_to_children (GdkWindowObject *private,
+ GdkWindowRedirect *redirect)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
+ GList *l;
+ GdkWindowObject *child;
- g_return_if_fail (GDK_IS_WINDOW (window));
- g_return_if_fail (private->update_freeze_count > 0);
+ for (l = private->children; l != NULL; l = l->next)
+ {
+ child = l->data;
- if (--private->update_freeze_count == 0)
- gdk_window_schedule_update (window);
+ /* Don't redirect this child if it already has another redirect */
+ if (!child->redirect)
+ {
+ child->redirect = redirect;
+ apply_redirect_to_children (child, redirect);
+ }
+ }
}
/**
- * gdk_window_freeze_toplevel_updates_libgtk_only:
+ * gdk_window_redirect_to_drawable:
* @window: a #GdkWindow
+ * @drawable: a #GdkDrawable
+ * @src_x: x position in @window
+ * @src_y: y position in @window
+ * @dest_x: x position in @drawable
+ * @dest_y: y position in @drawable
+ * @width: width of redirection
+ * @height: height of redirection
*
- * Temporarily freezes a window and all its descendants such that it won't
- * receive expose events. The window will begin receiving expose events
- * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
- * gdk_window_freeze_toplevel_updates_libgtk_only()
- * has been called more than once,
- * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
- * an equal number of times to begin processing exposes.
+ * Redirects drawing into @window so that drawing to the
+ * window in the rectangle specified by @src_x, @src_y,
+ * @width and @height is also drawn into @drawable at
+ * @dest_x, @dest_y.
*
- * This function is not part of the GDK public API and is only
- * for use by GTK+.
+ * Only drawing between gdk_window_begin_paint_region() or
+ * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
+ * redirected.
+ *
+ * Redirection is active until gdk_window_remove_redirection()
+ * is called.
+ *
+ * Since: 2.14
**/
void
-gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
+gdk_window_redirect_to_drawable (GdkWindow *window,
+ GdkDrawable *drawable,
+ gint src_x,
+ gint src_y,
+ gint dest_x,
+ gint dest_y,
+ gint width,
+ gint height)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *private;
g_return_if_fail (GDK_IS_WINDOW (window));
- g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
+ g_return_if_fail (GDK_IS_DRAWABLE (drawable));
+ g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
- private->update_and_descendants_freeze_count++;
-}
+ private = (GdkWindowObject *) window;
-/**
- * gdk_window_thaw_toplevel_updates_libgtk_only:
- * @window: a #GdkWindow
- *
- * Thaws a window frozen with
- * gdk_window_freeze_toplevel_updates_libgtk_only().
- *
- * This function is not part of the GDK public API and is only
- * for use by GTK+.
- **/
-void
-gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
-{
- GdkWindowObject *private = (GdkWindowObject *)window;
+ if (private->redirect)
+ gdk_window_remove_redirection (window);
- g_return_if_fail (GDK_IS_WINDOW (window));
- g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
- g_return_if_fail (private->update_and_descendants_freeze_count > 0);
+ if (width == -1 || height == -1)
+ {
+ gint w, h;
+ gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+ if (width == -1)
+ width = w;
+ if (height == -1)
+ height = h;
+ }
- private->update_and_descendants_freeze_count--;
+ private->redirect = g_new0 (GdkWindowRedirect, 1);
+ private->redirect->redirected = private;
+ private->redirect->pixmap = g_object_ref (drawable);
+ private->redirect->src_x = src_x;
+ private->redirect->src_y = src_y;
+ private->redirect->dest_x = dest_x;
+ private->redirect->dest_y = dest_y;
+ private->redirect->width = width;
+ private->redirect->height = height;
- gdk_window_schedule_update (window);
+ apply_redirect_to_children (private, private->redirect);
}
-/**
- * gdk_window_set_debug_updates:
- * @setting: %TRUE to turn on update debugging
- *
- * With update debugging enabled, calls to
- * gdk_window_invalidate_region() clear the invalidated region of the
- * screen to a noticeable color, and GDK pauses for a short time
- * before sending exposes to windows during
- * gdk_window_process_updates(). The net effect is that you can see
- * the invalid region for each window and watch redraws as they
- * occur. This allows you to diagnose inefficiencies in your application.
- *
- * In essence, because the GDK rendering model prevents all flicker,
- * if you are redrawing the same region 400 times you may never
- * notice, aside from noticing a speed problem. Enabling update
- * debugging causes GTK to flicker slowly and noticeably, so you can
- * see exactly what's being redrawn when, in what order.
- *
- * The --gtk-debug=updates command line option passed to GTK+ programs
- * enables this debug option at application startup time. That's
- * usually more useful than calling gdk_window_set_debug_updates()
- * yourself, though you might want to use this function to enable
- * updates sometime after application startup time.
- *
- **/
-void
-gdk_window_set_debug_updates (gboolean setting)
+static void
+window_get_size_rectangle (GdkWindow *window,
+ GdkRectangle *rect)
{
- debug_updates = setting;
+ GdkWindowObject *private = (GdkWindowObject *) window;
+
+ rect->x = rect->y = 0;
+ rect->width = private->width;
+ rect->height = private->height;
}
-/**
- * gdk_window_constrain_size:
- * @geometry: a #GdkGeometry structure
- * @flags: a mask indicating what portions of @geometry are set
- * @width: desired width of window
- * @height: desired height of the window
- * @new_width: location to store resulting width
- * @new_height: location to store resulting height
- *
- * Constrains a desired width and height according to a
- * set of geometry hints (such as minimum and maximum size).
+/* Calculates the real clipping region for a window, in window coordinates,
+ * taking into account other windows, gc clip region and gc clip mask.
*/
-void
-gdk_window_constrain_size (GdkGeometry *geometry,
- guint flags,
- gint width,
- gint height,
- gint *new_width,
- gint *new_height)
-{
- /* This routine is partially borrowed from fvwm.
- *
- * Copyright 1993, Robert Nation
- * You may use this code for any purpose, as long as the original
- * copyright remains in the source code and all documentation
- *
- * which in turn borrows parts of the algorithm from uwm
- */
- gint min_width = 0;
- gint min_height = 0;
- gint base_width = 0;
- gint base_height = 0;
- gint xinc = 1;
- gint yinc = 1;
- gint max_width = G_MAXINT;
- gint max_height = G_MAXINT;
-
-#define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
-
- if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
- {
- base_width = geometry->base_width;
- base_height = geometry->base_height;
- min_width = geometry->min_width;
- min_height = geometry->min_height;
- }
- else if (flags & GDK_HINT_BASE_SIZE)
- {
- base_width = geometry->base_width;
- base_height = geometry->base_height;
- min_width = geometry->base_width;
- min_height = geometry->base_height;
- }
- else if (flags & GDK_HINT_MIN_SIZE)
- {
- base_width = geometry->min_width;
- base_height = geometry->min_height;
- min_width = geometry->min_width;
- min_height = geometry->min_height;
- }
+GdkRegion *
+_gdk_window_calculate_full_clip_region (GdkWindow *window,
+ GdkWindow *base_window,
+ gboolean do_children,
+ gint *base_x_offset,
+ gint *base_y_offset)
+{
+ GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
+ GdkRectangle visible_rect;
+ GdkRegion *real_clip_region, *tmpreg;
+ gint x_offset, y_offset;
+ GdkWindowObject *parentwin, *lastwin;
- if (flags & GDK_HINT_MAX_SIZE)
- {
- max_width = geometry->max_width ;
- max_height = geometry->max_height;
- }
+ if (base_x_offset)
+ *base_x_offset = 0;
+ if (base_y_offset)
+ *base_y_offset = 0;
- if (flags & GDK_HINT_RESIZE_INC)
- {
- xinc = MAX (xinc, geometry->width_inc);
- yinc = MAX (yinc, geometry->height_inc);
- }
-
- /* clamp width and height to min and max values
- */
- width = CLAMP (width, min_width, max_width);
- height = CLAMP (height, min_height, max_height);
-
- /* shrink to base + N * inc
- */
- width = base_width + FLOOR (width - base_width, xinc);
- height = base_height + FLOOR (height - base_height, yinc);
+ if (!GDK_WINDOW_IS_MAPPED (window) || private->input_only)
+ return gdk_region_new ();
- /* constrain aspect ratio, according to:
- *
- * width
- * min_aspect <= -------- <= max_aspect
- * height
- */
-
- if (flags & GDK_HINT_ASPECT &&
- geometry->min_aspect > 0 &&
- geometry->max_aspect > 0)
+ window_get_size_rectangle (window, &visible_rect);
+
+ /* real_clip_region is in window coordinates */
+ real_clip_region = gdk_region_rectangle (&visible_rect);
+
+ x_offset = y_offset = 0;
+
+ lastwin = private;
+ if (do_children)
+ parentwin = lastwin;
+ else
+ parentwin = lastwin->parent;
+
+ /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
+ for (; parentwin != NULL &&
+ (parentwin == private || lastwin != (GdkWindowObject*) base_window);
+ lastwin = parentwin, parentwin = lastwin->parent)
{
- gint delta;
+ GList *cur;
+ GdkRectangle real_clip_rect;
+ gboolean is_offscreen;
- if (geometry->min_aspect * height > width)
+ if (parentwin != private)
{
- delta = FLOOR (height - width / geometry->min_aspect, yinc);
- if (height - delta >= min_height)
- height -= delta;
- else
- {
- delta = FLOOR (height * geometry->min_aspect - width, xinc);
- if (width + delta <= max_width)
- width += delta;
- }
+ x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
+ y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
}
-
- if (geometry->max_aspect * height < width)
+
+ is_offscreen = gdk_window_is_offscreen (parentwin);
+
+ /* children is ordered in reverse stack order */
+ for (cur = parentwin->children;
+ cur && cur->data != lastwin;
+ cur = cur->next)
{
- delta = FLOOR (width - height * geometry->max_aspect, xinc);
- if (width - delta >= min_width)
- width -= delta;
- else
- {
- delta = FLOOR (width / geometry->max_aspect - height, yinc);
- if (height + delta <= max_height)
- height += delta;
- }
- }
- }
+ GdkWindow *child = cur->data;
+ GdkWindowObject *child_private = (GdkWindowObject *)child;
-#undef FLOOR
-
- *new_width = width;
- *new_height = height;
-}
+ if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
+ continue;
-/**
- * gdk_window_get_pointer:
- * @window: a #GdkWindow
- * @x: return location for X coordinate of pointer or %NULL to not
- * return the X coordinate
- * @y: return location for Y coordinate of pointer or %NULL to not
- * return the Y coordinate
- * @mask: return location for modifier mask or %NULL to not return the
- * modifier mask
- *
- * Obtains the current pointer position and modifier state.
- * The position is given in coordinates relative to the upper left
- * corner of @window.
- *
- * Return value: the window containing the pointer (as with
- * gdk_window_at_pointer()), or %NULL if the window containing the
- * pointer isn't known to GDK
- **/
-GdkWindow*
-gdk_window_get_pointer (GdkWindow *window,
- gint *x,
- gint *y,
- GdkModifierType *mask)
-{
- GdkDisplay *display;
- gint tmp_x, tmp_y;
- GdkModifierType tmp_mask;
- GdkWindow *child;
-
- g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
+ /* Ignore offscreen children, as they don't draw in their parent and
+ * don't take part in the clipping */
+ if (gdk_window_is_offscreen (child_private))
+ continue;
- if (window)
- {
- display = gdk_drawable_get_display (window);
- }
- else
- {
- GdkScreen *screen = gdk_screen_get_default ();
+ window_get_size_rectangle (child, &visible_rect);
- display = gdk_screen_get_display (screen);
- window = gdk_screen_get_root_window (screen);
-
- GDK_NOTE (MULTIHEAD,
- g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
- "is not multihead safe"));
- }
+ /* Convert rect to "window" coords */
+ visible_rect.x += child_private->x - x_offset;
+ visible_rect.y += child_private->y - y_offset;
- child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
+ /* This shortcut is really necessary for performance when there are a lot of windows */
+ gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
+ if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
+ visible_rect.x + visible_rect.width <= real_clip_rect.x ||
+ visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
+ visible_rect.y + visible_rect.height <= real_clip_rect.y)
+ continue;
- if (x)
- *x = tmp_x;
- if (y)
- *y = tmp_y;
- if (mask)
- *mask = tmp_mask;
+ tmpreg = gdk_region_rectangle (&visible_rect);
+ gdk_region_subtract (real_clip_region, tmpreg);
+ gdk_region_destroy (tmpreg);
+ }
- return child;
-}
+ /* Clip to the parent */
+ window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
+ /* Convert rect to "window" coords */
+ visible_rect.x += - x_offset;
+ visible_rect.y += - y_offset;
-/**
- * gdk_window_at_pointer:
- * @win_x: return location for origin of the window under the pointer
- * @win_y: return location for origin of the window under the pointer
- *
- * Obtains the window underneath the mouse pointer, returning the
- * location of that window in @win_x, @win_y. Returns %NULL if the
- * window under the mouse pointer is not known to GDK (if the window
- * belongs to another application and a #GdkWindow hasn't been created
- * for it with gdk_window_foreign_new())
- *
- * NOTE: For multihead-aware widgets or applications use
- * gdk_display_get_window_at_pointer() instead.
- *
- * Return value: window under the mouse pointer
- **/
-GdkWindow*
-gdk_window_at_pointer (gint *win_x,
- gint *win_y)
-{
- return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
+ tmpreg = gdk_region_rectangle (&visible_rect);
+ gdk_region_intersect (real_clip_region, tmpreg);
+ gdk_region_destroy (tmpreg);
+ }
+
+ if (base_x_offset)
+ *base_x_offset = x_offset;
+ if (base_y_offset)
+ *base_y_offset = y_offset;
+
+ return real_clip_region;
}
-/**
- * gdk_get_default_root_window:
- *
- * Obtains the root window (parent all other windows are inside)
- * for the default display and screen.
- *
- * Return value: the default root window
- **/
-GdkWindow *
-gdk_get_default_root_window (void)
+void
+_gdk_window_add_damage (GdkWindow *toplevel,
+ GdkRegion *damaged_region)
{
- return gdk_screen_get_root_window (gdk_screen_get_default ());
+ GdkDisplay *display;
+ GdkEvent event = { 0, };
+ event.expose.type = GDK_DAMAGE;
+ event.expose.window = toplevel;
+ event.expose.send_event = FALSE;
+ event.expose.region = damaged_region;
+ gdk_region_get_clipbox (event.expose.region, &event.expose.area);
+ display = gdk_drawable_get_display (event.expose.window);
+ _gdk_event_queue_append (display, gdk_event_copy (&event));
}
-/**
- * gdk_window_foreign_new:
- * @anid: a native window handle.
- *
- * Wraps a native window for the default display in a #GdkWindow.
- * This may fail if the window has been destroyed.
- *
- * For example in the X backend, a native window handle is an Xlib
- * <type>XID</type>.
- *
- * Return value: the newly-created #GdkWindow wrapper for the
- * native window or %NULL if the window has been destroyed.
- **/
-GdkWindow *
-gdk_window_foreign_new (GdkNativeWindow anid)
+static void
+gdk_window_redirect_free (GdkWindowRedirect *redirect)
{
- return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
+ g_object_unref (redirect->pixmap);
+ g_free (redirect);
}
-/**
- * gdk_window_show_unraised:
- * @window: a #GdkWindow
- *
- * Shows a #GdkWindow onscreen, but does not modify its stacking
- * order. In contrast, gdk_window_show() will raise the window
- * to the top of the window stack.
- *
- * On the X11 platform, in Xlib terms, this function calls
- * XMapWindow() (it also updates some internal GDK state, which means
- * that you can't really use XMapWindow() directly on a GDK window).
- */
-void
-gdk_window_show_unraised (GdkWindow *window)
+/* Gets the toplevel for a window as used for events,
+ i.e. including offscreen parents */
+static GdkWindowObject *
+get_event_parent (GdkWindowObject *window)
{
- GdkWindowObject *private;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, FALSE);
+ if (window->window_type ==GDK_WINDOW_OFFSCREEN)
+ return (GdkWindowObject *)gdk_window_get_offscreen_parent ((GdkWindow *)window);
+ else
+ return window->parent;
}
-static inline void
-gdk_window_raise_internal (GdkWindow *window)
+/* Gets the toplevel for a window as used for events,
+ i.e. including offscreen parents going up to the native
+ toplevel */
+static GdkWindow *
+get_event_toplevel (GdkWindow *w)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkWindowObject *parent = private->parent;
+ GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
+ GdkWindowObject *parent;
- if (parent)
- {
- parent->children = g_list_remove (parent->children, window);
- parent->children = g_list_prepend (parent->children, window);
- }
+ while ((parent = get_event_parent (private)) != NULL &&
+ (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT))
+ private = parent;
+
+ return GDK_WINDOW (private);
}
-/**
- * gdk_window_raise:
- * @window: a #GdkWindow
- *
- * Raises @window to the top of the Z-order (stacking order), so that
- * other windows with the same parent window appear below @window.
- * This is true whether or not the windows are visible.
- *
- * If @window is a toplevel, the window manager may choose to deny the
- * request to move the window in the Z-order, gdk_window_raise() only
- * requests the restack, does not guarantee it.
- */
-void
-gdk_window_raise (GdkWindow *window)
+static gboolean
+is_event_parent_of (GdkWindow *parent,
+ GdkWindow *child)
{
- GdkWindowObject *private;
+ GdkWindow *w;
- g_return_if_fail (GDK_IS_WINDOW (window));
+ w = child;
+ while (w != NULL)
+ {
+ if (w == parent)
+ return TRUE;
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
+ w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
+ }
- /* Keep children in (reverse) stacking order */
- gdk_window_raise_internal (window);
+ return FALSE;
+}
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
+static void
+update_cursor (GdkDisplay *display)
+{
+ GdkWindowObject *pointer_window, *cursor_window, *parent, *toplevel;
+ GdkPointerGrabInfo *grab;
+
+ pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
+
+ cursor_window = pointer_window;
+ while (cursor_window->cursor == NULL &&
+ (parent = get_event_parent (cursor_window)) != NULL &&
+ parent->window_type != GDK_WINDOW_ROOT)
+ cursor_window = parent;
+
+ /* We ignore the serials here and just pick the last grab
+ we've sent, as that would shortly be used anyway. */
+ grab = _gdk_display_get_last_pointer_grab (display);
+ if (grab != NULL &&
+ !is_event_parent_of (grab->window, (GdkWindow *)cursor_window))
+ cursor_window = (GdkWindowObject *)grab->window;
+
+ /* Set all cursors on toplevel, otherwise its tricky to keep track of
+ * which native window has what cursor set. */
+ toplevel = (GdkWindowObject *)get_event_toplevel ((GdkWindow *)pointer_window);
+ GDK_WINDOW_IMPL_GET_IFACE (toplevel->impl)->set_cursor
+ ((GdkWindow *)toplevel, cursor_window->cursor);
}
static void
-gdk_window_lower_internal (GdkWindow *window)
+from_parent (GdkWindowObject *window,
+ double parent_x, double parent_y,
+ double *offscreen_x, double *offscreen_y)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkWindowObject *parent = private->parent;
+ g_signal_emit_by_name (window,
+ "from_parent",
+ parent_x, parent_y,
+ offscreen_x, offscreen_y,
+ NULL);
+}
- if (parent)
+static void
+convert_coords_to_child (GdkWindowObject *child,
+ double x, double y,
+ double *child_x, double *child_y)
+{
+ if (gdk_window_is_offscreen (child))
{
- parent->children = g_list_remove (parent->children, window);
- parent->children = g_list_append (parent->children, window);
+ from_parent (child, x, y,
+ child_x, child_y);
+ }
+ else
+ {
+ *child_x = x - child->x;
+ *child_y = y - child->y;
}
}
-/**
- * gdk_window_lower:
- * @window: a #GdkWindow
- *
- * Lowers @window to the bottom of the Z-order (stacking order), so that
- * other windows with the same parent window appear above @window.
- * This is true whether or not the other windows are visible.
- *
- * If @window is a toplevel, the window manager may choose to deny the
- * request to move the window in the Z-order, gdk_window_lower() only
- * requests the restack, does not guarantee it.
- *
- * Note that gdk_window_show() raises the window again, so don't call this
- * function before gdk_window_show(). (Try gdk_window_show_unraised().)
- */
-void
-gdk_window_lower (GdkWindow *window)
+static gboolean
+point_in_window (GdkWindowObject *window,
+ double x, double y)
{
- GdkWindowObject *private;
+ return
+ x >= 0 && x < window->width &&
+ y >= 0 && y < window->height &&
+ (window->shape == NULL ||
+ gdk_region_point_in (window->shape,
+ x, y)) &&
+ (window->input_shape == NULL ||
+ gdk_region_point_in (window->input_shape,
+ x, y));
+}
- g_return_if_fail (GDK_IS_WINDOW (window));
+static GdkWindow *
+convert_native_coords_to_toplevel (GdkWindow *window,
+ double child_x, double child_y,
+ double *toplevel_x, double *toplevel_y)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ gdouble x, y;
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
+ x = child_x;
+ y = child_y;
- /* Keep children in (reverse) stacking order */
- gdk_window_lower_internal (window);
+ while (private->parent != NULL &&
+ (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
+ {
+ x += private->x;
+ y += private->y;
+ private = private->parent;
+ }
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
+ *toplevel_x = x;
+ *toplevel_y = y;
+
+ return (GdkWindow *)private;
}
-/**
- * gdk_window_show:
- * @window: a #GdkWindow
- *
- * Like gdk_window_show_unraised(), but also raises the window to the
- * top of the window stack (moves the window to the front of the
- * Z-order).
- *
- * This function maps a window so it's visible onscreen. Its opposite
- * is gdk_window_hide().
- *
- * When implementing a #GtkWidget, you should call this function on the widget's
- * #GdkWindow as part of the "map" method.
- */
-void
-gdk_window_show (GdkWindow *window)
+static void
+convert_toplevel_coords_to_window (GdkWindow *window,
+ gdouble toplevel_x,
+ gdouble toplevel_y,
+ gdouble *window_x,
+ gdouble *window_y)
{
GdkWindowObject *private;
+ GdkWindowObject *parent;
+ gdouble x, y;
+ GList *children, *l;
- g_return_if_fail (GDK_IS_WINDOW (window));
+ private = GDK_WINDOW_OBJECT (window);
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
+ x = toplevel_x;
+ y = toplevel_y;
- /* Keep children in (reverse) stacking order */
- gdk_window_raise_internal (window);
+ children = NULL;
+ while ((parent = get_event_parent (private)) != NULL &&
+ (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT))
+ {
+ children = g_list_prepend (children, private);
+ private = parent;
+ }
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, TRUE);
+ for (l = children; l != NULL; l = l->next)
+ convert_coords_to_child (l->data, x, y, &x, &y);
+
+ g_list_free (children);
+
+ *window_x = x;
+ *window_y = y;
}
-/**
- * gdk_window_hide:
- * @window: a #GdkWindow
- *
- * For toplevel windows, withdraws them, so they will no longer be
- * known to the window manager; for all windows, unmaps them, so
- * they won't be displayed. Normally done automatically as
- * part of gtk_widget_hide().
- */
-void
-gdk_window_hide (GdkWindow *window)
+static GdkWindowObject *
+pick_offscreen_child (GdkWindowObject *window,
+ double x, double y)
{
- GdkWindowObject *private;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
+ GdkWindowObject *res;
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
+ res = NULL;
+ g_signal_emit_by_name (window,
+ "pick-offscreen-child",
+ x, y, &res);
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide (window);
+ return res;
}
-/**
- * gdk_window_withdraw:
- * @window: a toplevel #GdkWindow
- *
- * Withdraws a window (unmaps it and asks the window manager to forget about it).
- * This function is not really useful as gdk_window_hide() automatically
- * withdraws toplevel windows before hiding them.
- **/
-void
-gdk_window_withdraw (GdkWindow *window)
+GdkWindow *
+_gdk_window_find_child_at (GdkWindow *window,
+ int x, int y)
{
- GdkWindowObject *private;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
+ GdkWindowObject *private, *sub;
+ double child_x, child_y;
+ GList *l;
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
+ private = (GdkWindowObject *)window;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
-}
+ if (point_in_window (private, x, y))
+ {
+ /* Children is ordered in reverse stack order, i.e. first is topmost */
+ for (l = private->children; l != NULL; l = l->next)
+ {
+ sub = l->data;
-/**
- * gdk_window_set_events:
- * @window: a #GdkWindow
- * @event_mask: event mask for @window
- *
- * The event mask for a window determines which events will be reported
- * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
- * means the window should report button press events. The event mask
- * is the bitwise OR of values from the #GdkEventMask enumeration.
- **/
-void
-gdk_window_set_events (GdkWindow *window,
- GdkEventMask event_mask)
-{
- GdkWindowObject *private;
+ if (!GDK_WINDOW_IS_MAPPED (sub))
+ continue;
- g_return_if_fail (GDK_IS_WINDOW (window));
+ convert_coords_to_child (sub,
+ x, y,
+ &child_x, &child_y);
+ if (point_in_window (sub, child_x, child_y))
+ return (GdkWindow *)sub;
+ }
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
+ if (private->has_offscreen_children)
+ {
+ sub = pick_offscreen_child (private,
+ x, y);
+ if (sub)
+ return (GdkWindow *)sub;
+ }
+ }
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, event_mask);
+ return NULL;
}
-/**
- * gdk_window_get_events:
- * @window: a #GdkWindow
- *
- * Gets the event mask for @window. See gdk_window_set_events().
- *
- * Return value: event mask for @window
- **/
-GdkEventMask
-gdk_window_get_events (GdkWindow *window)
+GdkWindow *
+_gdk_window_find_descendant_at (GdkWindow *toplevel,
+ double x, double y,
+ double *found_x,
+ double *found_y)
{
- GdkWindowObject *private;
+ GdkWindowObject *private, *sub;
+ double child_x, child_y;
+ GList *l;
+ gboolean found;
- g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+ private = (GdkWindowObject *)toplevel;
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return 0;
+ if (point_in_window (private, x, y))
+ {
+ do
+ {
+ found = FALSE;
+ /* Children is ordered in reverse stack order, i.e. first is topmost */
+ for (l = private->children; l != NULL; l = l->next)
+ {
+ sub = l->data;
+
+ if (!GDK_WINDOW_IS_MAPPED (sub))
+ continue;
+
+ convert_coords_to_child (sub,
+ x, y,
+ &child_x, &child_y);
+ if (point_in_window (sub, child_x, child_y))
+ {
+ x = child_x;
+ y = child_y;
+ private = sub;
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found &&
+ private->has_offscreen_children)
+ {
+ sub = pick_offscreen_child (private,
+ x, y);
+ if (sub)
+ {
+ found = TRUE;
+ private = sub;
+ from_parent (sub, x, y, &x, &y);
+ }
+ }
+ }
+ while (found);
+ }
+ else
+ {
+ /* Not in window at all */
+ private = NULL;
+ }
+
+ if (found_x)
+ *found_x = x;
+ if (found_y)
+ *found_y = y;
- return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_events (window);
+ return (GdkWindow *)private;
}
/**
- * gdk_window_move:
- * @window: a #GdkWindow
- * @x: X coordinate relative to window's parent
- * @y: Y coordinate relative to window's parent
+ * gdk_window_beep:
+ * @window: a toplevel #GdkWindow
*
- * Repositions a window relative to its parent window.
- * For toplevel windows, window managers may ignore or modify the move;
- * you should probably use gtk_window_move() on a #GtkWindow widget
- * anyway, instead of using GDK functions. For child windows,
- * the move will reliably succeed.
+ * Emits a short beep associated to @window in the appropriate
+ * display, if supported. Otherwise, emits a short beep on
+ * the display just as gdk_display_beep().
*
- * If you're also planning to resize the window, use gdk_window_move_resize()
- * to both move and resize simultaneously, for a nicer visual effect.
+ * Since: 2.12
**/
void
-gdk_window_move (GdkWindow *window,
- gint x,
- gint y)
+gdk_window_beep (GdkWindow *window)
{
- GdkWindowObject *private;
+ GdkDisplay *display;
+ GdkWindow *toplevel;
g_return_if_fail (GDK_IS_WINDOW (window));
- private = (GdkWindowObject *) window;
- if (private->destroyed)
+ if (GDK_WINDOW_DESTROYED (window))
return;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, x, y, -1, -1);
+ toplevel = get_event_toplevel (window);
+ display = gdk_drawable_get_display (GDK_DRAWABLE (window));
+
+ if (toplevel && gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
+ _gdk_windowing_window_beep (toplevel);
+ else
+ gdk_display_beep (display);
}
-/**
- * gdk_window_resize:
- * @window: a #GdkWindow
- * @width: new width of the window
- * @height: new height of the window
- *
- * Resizes @window; for toplevel windows, asks the window manager to resize
- * the window. The window manager may not allow the resize. When using GTK+,
- * use gtk_window_resize() instead of this low-level GDK function.
- *
- * Windows may not be resized below 1x1.
- *
- * If you're also planning to move the window, use gdk_window_move_resize()
- * to both move and resize simultaneously, for a nicer visual effect.
- **/
-void
-gdk_window_resize (GdkWindow *window,
- gint width,
- gint height)
+static const guint type_masks[] = {
+ GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0 */
+ GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1 */
+ GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2 */
+ GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3 */
+ GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4 */
+ GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5 */
+ GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6 */
+ GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7 */
+ GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8 */
+ GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9 */
+ GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10 */
+ GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11 */
+ GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12 */
+ GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13 */
+ GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14 */
+ GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15 */
+ GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16 */
+ GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17 */
+ GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18 */
+ GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19 */
+ GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20 */
+ GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21 */
+ GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22 */
+ GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23 */
+ GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24 */
+ GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25 */
+ GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26 */
+ GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27 */
+ GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28 */
+ GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
+ GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30 */
+ GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
+ 0, /* GDK_WINDOW_STATE = 32 */
+ 0, /* GDK_SETTING = 33 */
+ 0, /* GDK_OWNER_CHANGE = 34 */
+ 0, /* GDK_GRAB_BROKEN = 35 */
+ 0, /* GDK_DAMAGE = 36 */
+};
+G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
+
+/* send motion events if the right buttons are down */
+static guint
+update_evmask_for_button_motion (guint evmask,
+ GdkModifierType mask)
{
- GdkWindowObject *private;
+ if (evmask & GDK_BUTTON_MOTION_MASK &&
+ mask & (GDK_BUTTON1_MASK |
+ GDK_BUTTON2_MASK |
+ GDK_BUTTON3_MASK |
+ GDK_BUTTON4_MASK |
+ GDK_BUTTON5_MASK))
+ evmask |= GDK_POINTER_MOTION_MASK;
+
+ if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
+ (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
+ (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
+ evmask |= GDK_POINTER_MOTION_MASK;
+
+ return evmask;
+}
+
+static gboolean
+is_button_type (GdkEventType type)
+{
+ return type == GDK_BUTTON_PRESS ||
+ type == GDK_2BUTTON_PRESS ||
+ type == GDK_3BUTTON_PRESS ||
+ type == GDK_BUTTON_RELEASE ||
+ type == GDK_SCROLL;
+}
+
+static gboolean
+is_motion_type (GdkEventType type)
+{
+ return type == GDK_MOTION_NOTIFY ||
+ type == GDK_ENTER_NOTIFY ||
+ type == GDK_LEAVE_NOTIFY;
+}
+
+static GdkWindowObject *
+find_common_ancestor (GdkWindowObject *win1,
+ GdkWindowObject *win2)
+{
+ GdkWindowObject *tmp;
+ GList *path1 = NULL, *path2 = NULL;
+ GList *list1, *list2;
+
+ tmp = win1;
+ while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
+ {
+ path1 = g_list_prepend (path1, tmp);
+ tmp = get_event_parent (tmp);
+ }
- g_return_if_fail (GDK_IS_WINDOW (window));
+ tmp = win2;
+ while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
+ {
+ path2 = g_list_prepend (path2, tmp);
+ tmp = get_event_parent (tmp);
+ }
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
+ list1 = path1;
+ list2 = path2;
+ tmp = NULL;
+ while (list1 && list2 && (list1->data == list2->data))
+ {
+ tmp = (GdkWindowObject *)list1->data;
+ list1 = g_list_next (list1);
+ list2 = g_list_next (list2);
+ }
+ g_list_free (path1);
+ g_list_free (path2);
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, FALSE, 0, 0, width, height);
+ return tmp;
}
-
-/**
- * gdk_window_move_resize:
- * @window: a #GdkWindow
- * @x: new X position relative to window's parent
- * @y: new Y position relative to window's parent
- * @width: new width
- * @height: new height
- *
- * Equivalent to calling gdk_window_move() and gdk_window_resize(),
- * except that both operations are performed at once, avoiding strange
- * visual effects. (i.e. the user may be able to see the window first
- * move, then resize, if you don't use gdk_window_move_resize().)
- **/
-void
-gdk_window_move_resize (GdkWindow *window,
- gint x,
- gint y,
- gint width,
- gint height)
+GdkEvent *
+_gdk_make_event (GdkWindow *window,
+ GdkEventType type,
+ GdkEvent *event_in_queue,
+ gboolean before_event)
{
- GdkWindowObject *private;
+ GdkEvent *event = gdk_event_new (type);
+ guint32 the_time;
+ GdkModifierType the_state;
- g_return_if_fail (GDK_IS_WINDOW (window));
+ the_time = gdk_event_get_time (event_in_queue);
+ gdk_event_get_state (event_in_queue, &the_state);
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
+ event->any.window = g_object_ref (window);
+ event->any.send_event = FALSE;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, x, y, width, height);
-}
+ switch (type)
+ {
+ case GDK_MOTION_NOTIFY:
+ event->motion.time = the_time;
+ event->motion.axes = NULL;
+ event->motion.state = the_state;
+ break;
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ event->button.time = the_time;
+ event->button.axes = NULL;
+ event->button.state = the_state;
+ break;
-/**
- * gdk_window_scroll:
- * @window: a #GdkWindow
- * @dx: Amount to scroll in the X direction
- * @dy: Amount to scroll in the Y direction
- *
- * Scroll the contents of @window, both pixels and children, by the
- * given amount. @window itself does not move. Portions of the window
- * that the scroll operation brings in from offscreen areas are
- * invalidated. The invalidated region may be bigger than what would
- * strictly be necessary.
- *
- * For X11, a minimum area will be invalidated if the window has no
- * subwindows, or if the edges of the window's parent do not extend
- * beyond the edges of the window. In other cases, a multi-step process
- * is used to scroll the window which may produce temporary visual
- * artifacts and unnecessary invalidations.
- **/
-void
-gdk_window_scroll (GdkWindow *window,
- gint dx,
- gint dy)
-{
- GdkWindowObject *private = (GdkWindowObject *) window;
+ case GDK_SCROLL:
+ event->scroll.time = the_time;
+ event->scroll.state = the_state;
+ break;
- g_return_if_fail (GDK_IS_WINDOW (window));
+ case GDK_KEY_PRESS:
+ case GDK_KEY_RELEASE:
+ event->key.time = the_time;
+ event->key.state = the_state;
+ break;
- if (dx == 0 && dy == 0)
- return;
+ case GDK_ENTER_NOTIFY:
+ case GDK_LEAVE_NOTIFY:
+ event->crossing.time = the_time;
+ event->crossing.state = the_state;
+ break;
- if (private->destroyed)
- return;
+ case GDK_PROPERTY_NOTIFY:
+ event->property.time = the_time;
+ event->property.state = the_state;
+ break;
+
+ case GDK_SELECTION_CLEAR:
+ case GDK_SELECTION_REQUEST:
+ case GDK_SELECTION_NOTIFY:
+ event->selection.time = the_time;
+ break;
+
+ case GDK_PROXIMITY_IN:
+ case GDK_PROXIMITY_OUT:
+ event->proximity.time = the_time;
+ break;
+
+ case GDK_DRAG_ENTER:
+ case GDK_DRAG_LEAVE:
+ case GDK_DRAG_MOTION:
+ case GDK_DRAG_STATUS:
+ case GDK_DROP_START:
+ case GDK_DROP_FINISHED:
+ event->dnd.time = the_time;
+ break;
+
+ case GDK_FOCUS_CHANGE:
+ case GDK_CONFIGURE:
+ case GDK_MAP:
+ case GDK_UNMAP:
+ case GDK_CLIENT_EVENT:
+ case GDK_VISIBILITY_NOTIFY:
+ case GDK_NO_EXPOSE:
+ case GDK_DELETE:
+ case GDK_DESTROY:
+ case GDK_EXPOSE:
+ default:
+ break;
+ }
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->scroll (window, dx, dy);
+ if (event_in_queue)
+ {
+ if (before_event)
+ _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
+ else
+ _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
+ }
+ else
+ _gdk_event_queue_append (gdk_drawable_get_display (window), event);
+
+ return event;
}
-/**
- * gdk_window_move_region:
- * @window: a #GdkWindow
- * @region: The #GdkRegion to move
- * @dx: Amount to move in the X direction
- * @dy: Amount to move in the Y direction
- *
- * Move the part of @window indicated by @region by @dy pixels in the Y
- * direction and @dx pixels in the X direction. The portions of @region
- * that not covered by the new position of @region are invalidated.
- *
- * Child windows are not moved.
- *
- * Since: 2.8
- */
-void
-gdk_window_move_region (GdkWindow *window,
- const GdkRegion *region,
- gint dx,
- gint dy)
+static void
+send_crossing_event (GdkDisplay *display,
+ GdkWindowObject *toplevel,
+ GdkWindowObject *window,
+ GdkEventType type,
+ GdkCrossingMode mode,
+ GdkNotifyType notify_type,
+ GdkWindow *subwindow,
+ gint toplevel_x,
+ gint toplevel_y,
+ GdkModifierType mask,
+ guint32 time_,
+ GdkEvent *event_in_queue,
+ gulong serial)
{
- GdkWindowObject *private = (GdkWindowObject *) window;
+ GdkEvent *event;
+ guint32 event_mask;
+ GdkPointerGrabInfo *grab;
- g_return_if_fail (GDK_IS_WINDOW (window));
- g_return_if_fail (region != NULL);
+ grab = _gdk_display_has_pointer_grab (display, serial);
- if (dx == 0 && dy == 0)
+ if (grab != NULL &&
+ !grab->owner_events &&
+ (GdkWindow *)window != grab->window)
return;
- if (private->destroyed)
- return;
+ if (type == GDK_LEAVE_NOTIFY)
+ event_mask = GDK_LEAVE_NOTIFY_MASK;
+ else
+ event_mask = GDK_ENTER_NOTIFY_MASK;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_region (window, region, dx, dy);
+ if (window->extension_events != 0)
+ GDK_WINDOW_IMPL_GET_IFACE (window->impl)->input_window_crossing ((GdkWindow *)window,
+ type == GDK_ENTER_NOTIFY);
+
+ if (window->event_mask & event_mask)
+ {
+ event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
+ event->crossing.time = time_;
+ event->crossing.subwindow = subwindow;
+ if (subwindow)
+ g_object_ref (subwindow);
+ convert_toplevel_coords_to_window ((GdkWindow *)window,
+ toplevel_x, toplevel_y,
+ &event->crossing.x, &event->crossing.y);
+ event->crossing.x_root = toplevel_x + toplevel->x;
+ event->crossing.y_root = toplevel_y + toplevel->y;
+ event->crossing.mode = mode;
+ event->crossing.detail = notify_type;
+ event->crossing.focus = FALSE;
+ event->crossing.state = mask;
+ }
}
-/**
- * gdk_window_set_background:
- * @window: a #GdkWindow
- * @color: an allocated #GdkColor
- *
- * Sets the background color of @window. (However, when using GTK+,
- * set the background of a widget with gtk_widget_modify_bg() - if
- * you're an application - or gtk_style_set_background() - if you're
- * implementing a custom widget.)
- *
- * The @color must be allocated; gdk_rgb_find_color() is the best way
- * to allocate a color.
- *
- * See also gdk_window_set_back_pixmap().
+
+/* The coordinates are in the toplevel window that src/dest are in.
+ * src and dest are always (if != NULL) in the same toplevel, as
+ * we get a leave-notify and set the window_under_pointer to null
+ * before crossing to another toplevel.
*/
void
-gdk_window_set_background (GdkWindow *window,
- const GdkColor *color)
+_gdk_syntesize_crossing_events (GdkDisplay *display,
+ GdkWindow *src,
+ GdkWindow *dest,
+ GdkCrossingMode mode,
+ gint toplevel_x,
+ gint toplevel_y,
+ GdkModifierType mask,
+ guint32 time_,
+ GdkEvent *event_in_queue,
+ gulong serial)
{
- GdkWindowObject *private;
+ GdkWindowObject *c;
+ GdkWindowObject *win, *last, *next;
+ GList *path, *list;
+ gboolean non_linear;
+ GdkWindowObject *a;
+ GdkWindowObject *b;
+ GdkWindowObject *toplevel;
+ GdkNotifyType notify_type;
- g_return_if_fail (GDK_IS_WINDOW (window));
+ /* TODO: Don't send events to toplevel, as we get those from the windowing system */
- private = (GdkWindowObject *) window;
+ a = (GdkWindowObject *)src;
+ b = (GdkWindowObject *)dest;
+ if (a == b)
+ return; /* No crossings generated between src and dest */
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, color);
-}
+ c = find_common_ancestor (a, b);
-/**
- * gdk_window_set_back_pixmap:
- * @window: a #GdkWindow
- * @pixmap: a #GdkPixmap, or %NULL
- * @parent_relative: whether the tiling origin is at the origin of
- * @window's parent
- *
- * Sets the background pixmap of @window. May also be used to set a
- * background of "None" on @window, by setting a background pixmap
- * of %NULL.
- *
- * A background pixmap will be tiled, positioning the first tile at
- * the origin of @window, or if @parent_relative is %TRUE, the tiling
- * will be done based on the origin of the parent window (useful to
- * align tiles in a parent with tiles in a child).
- *
- * A background pixmap of %NULL means that the window will have no
- * background. A window with no background will never have its
- * background filled by the windowing system, instead the window will
- * contain whatever pixels were already in the corresponding area of
- * the display.
- *
- * The windowing system will normally fill a window with its background
- * when the window is obscured then exposed, and when you call
- * gdk_window_clear().
- */
-void
-gdk_window_set_back_pixmap (GdkWindow *window,
- GdkPixmap *pixmap,
- gboolean parent_relative)
-{
- GdkWindowObject *private;
+ non_linear = (c != a) && (c != b);
- g_return_if_fail (GDK_IS_WINDOW (window));
- g_return_if_fail (pixmap == NULL || !parent_relative);
- g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
+ if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
+ {
+ toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
- private = (GdkWindowObject *) window;
+ /* Traverse up from a to (excluding) c sending leave events */
+ if (non_linear)
+ notify_type = GDK_NOTIFY_NONLINEAR;
+ else if (c == a)
+ notify_type = GDK_NOTIFY_INFERIOR;
+ else
+ notify_type = GDK_NOTIFY_ANCESTOR;
+ send_crossing_event (display, toplevel,
+ a, GDK_LEAVE_NOTIFY,
+ mode,
+ notify_type,
+ NULL,
+ toplevel_x, toplevel_y,
+ mask, time_,
+ event_in_queue,
+ serial);
+
+ if (c != a)
+ {
+ if (non_linear)
+ notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+ else
+ notify_type = GDK_NOTIFY_VIRTUAL;
+
+ last = a;
+ win = get_event_parent (a);
+ while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
+ {
+ send_crossing_event (display, toplevel,
+ win, GDK_LEAVE_NOTIFY,
+ mode,
+ notify_type,
+ (GdkWindow *)last,
+ toplevel_x, toplevel_y,
+ mask, time_,
+ event_in_queue,
+ serial);
+
+ last = win;
+ win = get_event_parent (win);
+ }
+ }
+ }
+
+ if (b) /* Might not be a dest, e.g. if we're moving out of the window */
+ {
+ toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
+
+ /* Traverse down from c to b */
+ if (c != b)
+ {
+ path = NULL;
+ win = get_event_parent (b);
+ while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
+ {
+ path = g_list_prepend (path, win);
+ win = get_event_parent (win);
+ }
+
+ if (non_linear)
+ notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+ else
+ notify_type = GDK_NOTIFY_VIRTUAL;
+
+ list = path;
+ while (list)
+ {
+ win = (GdkWindowObject *)list->data;
+ list = g_list_next (list);
+ if (list)
+ next = (GdkWindowObject *)list->data;
+ else
+ next = b;
+
+ send_crossing_event (display, toplevel,
+ win, GDK_ENTER_NOTIFY,
+ mode,
+ notify_type,
+ (GdkWindow *)next,
+ toplevel_x, toplevel_y,
+ mask, time_,
+ event_in_queue,
+ serial);
+ }
+ g_list_free (path);
+ }
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, pixmap, parent_relative);
+
+ if (non_linear)
+ notify_type = GDK_NOTIFY_NONLINEAR;
+ else if (c == a)
+ notify_type = GDK_NOTIFY_ANCESTOR;
+ else
+ notify_type = GDK_NOTIFY_INFERIOR;
+
+ send_crossing_event (display, toplevel,
+ b, GDK_ENTER_NOTIFY,
+ mode,
+ notify_type,
+ NULL,
+ toplevel_x, toplevel_y,
+ mask, time_,
+ event_in_queue,
+ serial);
+ }
}
-/**
- * gdk_window_set_cursor:
- * @window: a #GdkWindow
- * @cursor: a cursor
- *
- * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
- * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
- * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
- * to gdk_window_set_cursor() means that @window will use the cursor of its
- * parent window. Most windows should use this default.
+/* Returns the window inside the event window with the pointer in it
+ * at the specified coordinates, or NULL if its not in any child of
+ * the toplevel. It also takes into account !owner_events grabs.
*/
-void
-gdk_window_set_cursor (GdkWindow *window,
- GdkCursor *cursor)
+static GdkWindow *
+get_pointer_window (GdkDisplay *display,
+ GdkWindow *event_window,
+ gdouble toplevel_x,
+ gdouble toplevel_y,
+ gulong serial)
{
- GdkWindowObject *private;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
+ GdkWindow *pointer_window;
+ GdkPointerGrabInfo *grab;
+
+ if (event_window == display->pointer_info.toplevel_under_pointer)
+ pointer_window =
+ _gdk_window_find_descendant_at (event_window,
+ toplevel_x, toplevel_y,
+ NULL, NULL);
+ else
+ pointer_window = NULL;
- private = (GdkWindowObject *) window;
+ grab = _gdk_display_has_pointer_grab (display, serial);
+ if (grab != NULL &&
+ !grab->owner_events &&
+ pointer_window != grab->window)
+ pointer_window = NULL;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
+ return pointer_window;
}
-/**
- * gdk_window_get_geometry:
- * @window: a #GdkWindow
- * @x: return location for X coordinate of window (relative to its parent)
- * @y: return location for Y coordinate of window (relative to its parent)
- * @width: return location for width of window
- * @height: return location for height of window
- * @depth: return location for bit depth of window
- *
- * Any of the return location arguments to this function may be %NULL,
- * if you aren't interested in getting the value of that field.
- *
- * The X and Y coordinates returned are relative to the parent window
- * of @window, which for toplevels usually means relative to the
- * window decorations (titlebar, etc.) rather than relative to the
- * root window (screen-size background window).
- *
- * On the X11 platform, the geometry is obtained from the X server,
- * so reflects the latest position of @window; this may be out-of-sync
- * with the position of @window delivered in the most-recently-processed
- * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
- * position from the most recent configure event.
- *
- * <note>
- * If @window is not a toplevel, it is <emphasis>much</emphasis> better
- * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
- * because it avoids the roundtrip to the X server and because
- * gdk_drawable_get_size() supports the full 32-bit coordinate space,
- * whereas gdk_window_get_geometry() is restricted to the 16-bit
- * coordinates of X11.
- *</note>
- **/
void
-gdk_window_get_geometry (GdkWindow *window,
- gint *x,
- gint *y,
- gint *width,
- gint *height,
- gint *depth)
+_gdk_display_set_window_under_pointer (GdkDisplay *display,
+ GdkWindow *window)
{
GdkWindowObject *private;
- if (!window)
- {
- GDK_NOTE (MULTIHEAD,
- g_message ("gdk_window_get_geometry(): Window needs "
- "to be non-NULL to be multi head safe"));
- window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
- }
+ private = (GdkWindowObject *)window;
- g_return_if_fail (GDK_IS_WINDOW (window));
+ if (display->pointer_info.window_under_pointer)
+ g_object_unref (display->pointer_info.window_under_pointer);
+ display->pointer_info.window_under_pointer = window;
+ if (window)
+ g_object_ref (window);
- private = (GdkWindowObject *) window;
+ if (window)
+ update_cursor (display);
- if (!GDK_WINDOW_DESTROYED (window))
- {
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
- width, height,
- depth);
- }
+ _gdk_display_enable_motion_hints (display);
}
-/**
- * gdk_window_get_origin:
- * @window: a #GdkWindow
- * @x: return location for X coordinate
- * @y: return location for Y coordinate
- *
- * Obtains the position of a window in root window coordinates.
- * (Compare with gdk_window_get_position() and
- * gdk_window_get_geometry() which return the position of a window
- * relative to its parent window.)
- *
- * Return value: not meaningful, ignore
- */
-gint
-gdk_window_get_origin (GdkWindow *window,
- gint *x,
- gint *y)
+static GdkWindow *
+gdk_window_get_offscreen_parent (GdkWindow *window)
{
- GdkWindowObject *private;
-
- g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindow *res;
- private = (GdkWindowObject *) window;
+ res = NULL;
+ g_signal_emit_by_name (private->impl_window,
+ "get-offscreen-parent",
+ &res);
- return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
+ return res;
}
-/**
- * gdk_window_shape_combine_mask:
- * @window: a #GdkWindow
- * @mask: shape mask
- * @x: X position of shape mask with respect to @window
- * @y: Y position of shape mask with respect to @window
+/*
+ *--------------------------------------------------------------
+ * gdk_pointer_grab
*
- * Applies a shape mask to @window. Pixels in @window corresponding to
- * set bits in the @mask will be visible; pixels in @window
- * corresponding to unset bits in the @mask will be transparent. This
- * gives a non-rectangular window.
+ * Grabs the pointer to a specific window
*
- * If @mask is %NULL, the shape mask will be unset, and the @x/@y
- * parameters are not used.
+ * Arguments:
+ * "window" is the window which will receive the grab
+ * "owner_events" specifies whether events will be reported as is,
+ * or relative to "window"
+ * "event_mask" masks only interesting events
+ * "confine_to" limits the cursor movement to the specified window
+ * "cursor" changes the cursor for the duration of the grab
+ * "time" specifies the time
*
- * On the X11 platform, this uses an X server extension which is
- * widely available on most common platforms, but not available on
- * very old X servers, and occasionally the implementation will be
- * buggy. On servers without the shape extension, this function
- * will do nothing.
+ * Results:
*
- * This function works on both toplevel and child windows.
+ * Side effects:
+ * requires a corresponding call to gdk_pointer_ungrab
+ *
+ *--------------------------------------------------------------
*/
-void
-gdk_window_shape_combine_mask (GdkWindow *window,
- GdkBitmap *mask,
- gint x,
- gint y)
+GdkGrabStatus
+gdk_pointer_grab (GdkWindow * window,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ GdkWindow * confine_to,
+ GdkCursor * cursor,
+ guint32 time)
{
- GdkWindowObject *private;
+ GdkWindow *native;
+ GdkDisplay *display;
+ GdkGrabStatus res;
+ gulong serial;
- g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_val_if_fail (window != NULL, 0);
+ g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+ g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
- private = (GdkWindowObject *) window;
+ /* We need a native window for confine to to work, ensure we have one */
+ if (confine_to)
+ {
+ if (!gdk_window_ensure_native (confine_to))
+ {
+ g_warning ("Can't confine to grabbed window, not native");
+ confine_to = NULL;
+ }
+ }
+
+ /* Non-viewable client side window => fail */
+ if (!_gdk_window_has_impl (window) &&
+ !gdk_window_is_viewable (window))
+ return GDK_GRAB_NOT_VIEWABLE;
+
+ native = gdk_window_get_toplevel (window);
+ while (gdk_window_is_offscreen ((GdkWindowObject *)native))
+ {
+ native = gdk_window_get_offscreen_parent (native);
+
+ if (native == NULL ||
+ (!_gdk_window_has_impl (native) &&
+ !gdk_window_is_viewable (native)))
+ return GDK_GRAB_NOT_VIEWABLE;
+
+ native = gdk_window_get_toplevel (native);
+ }
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_mask (window, mask, x, y);
+ display = gdk_drawable_get_display (window);
+
+ serial = _gdk_windowing_window_get_next_serial (display);
+
+ res = _gdk_windowing_pointer_grab (window,
+ native,
+ owner_events,
+ event_mask,
+ confine_to,
+ cursor,
+ time);
+
+ if (res == GDK_GRAB_SUCCESS)
+ _gdk_display_add_pointer_grab (display,
+ window,
+ native,
+ owner_events,
+ event_mask,
+ serial,
+ time,
+ FALSE);
+
+ return res;
}
-/**
- * gdk_window_shape_combine_region:
- * @window: a #GdkWindow
- * @shape_region: region of window to be non-transparent
- * @offset_x: X position of @shape_region in @window coordinates
- * @offset_y: Y position of @shape_region in @window coordinates
- *
- * Makes pixels in @window outside @shape_region be transparent,
- * so that the window may be nonrectangular. See also
- * gdk_window_shape_combine_mask() to use a bitmap as the mask.
- *
- * If @shape_region is %NULL, the shape will be unset, so the whole
- * window will be opaque again. @offset_x and @offset_y are ignored
- * if @shape_region is %NULL.
- *
- * On the X11 platform, this uses an X server extension which is
- * widely available on most common platforms, but not available on
- * very old X servers, and occasionally the implementation will be
- * buggy. On servers without the shape extension, this function
- * will do nothing.
- *
- * This function works on both toplevel and child windows.
- */
void
-gdk_window_shape_combine_region (GdkWindow *window,
- const GdkRegion *shape_region,
- gint offset_x,
- gint offset_y)
+gdk_window_set_has_offscreen_children (GdkWindow *window,
+ gboolean has_offscreen_children)
{
- GdkWindowObject *private;
+ GdkWindowObject *private = (GdkWindowObject *)window;
- g_return_if_fail (GDK_IS_WINDOW (window));
+ private->has_offscreen_children = !!has_offscreen_children;
+}
- private = (GdkWindowObject *) window;
+gboolean
+gdk_window_get_has_offscreen_children (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region (window, shape_region, offset_x, offset_y);
+ return private->has_offscreen_children;
}
-/**
- * gdk_window_set_child_shapes:
- * @window: a #GdkWindow
- *
- * Sets the shape mask of @window to the union of shape masks
- * for all children of @window, ignoring the shape mask of @window
- * itself. Contrast with gdk_window_merge_child_shapes() which includes
- * the shape mask of @window in the masks to be merged.
- **/
void
-gdk_window_set_child_shapes (GdkWindow *window)
+gdk_window_offscreen_children_changed (GdkWindow *window)
{
- GdkWindowObject *private;
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
- g_return_if_fail (GDK_IS_WINDOW (window));
+static gboolean
+do_synthesize_crossing_event (gpointer data)
+{
+ GdkDisplay *display;
+ GdkWindow *changed_toplevel;
+ GdkWindowObject *changed_toplevel_priv;
+ GdkWindow *new_window_under_pointer;
+ gulong serial;
- private = (GdkWindowObject *) window;
+ changed_toplevel = data;
+ changed_toplevel_priv = (GdkWindowObject *)changed_toplevel;
+
+ changed_toplevel_priv->synthesize_crossing_event_queued = FALSE;
+
+ if (GDK_WINDOW_DESTROYED (changed_toplevel))
+ return FALSE;
+
+ display = gdk_drawable_get_display (changed_toplevel);
+ serial = _gdk_windowing_window_get_next_serial (display);
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_child_shapes (window);
+ if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
+ {
+ new_window_under_pointer =
+ get_pointer_window (display, changed_toplevel,
+ display->pointer_info.toplevel_x,
+ display->pointer_info.toplevel_y,
+ serial);
+ if (new_window_under_pointer !=
+ display->pointer_info.window_under_pointer)
+ {
+ _gdk_syntesize_crossing_events (display,
+ display->pointer_info.window_under_pointer,
+ new_window_under_pointer,
+ GDK_CROSSING_NORMAL,
+ display->pointer_info.toplevel_x,
+ display->pointer_info.toplevel_y,
+ display->pointer_info.state,
+ GDK_CURRENT_TIME,
+ NULL,
+ serial);
+ _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
+ }
+ }
+
+ return FALSE;
}
-/**
- * gdk_window_merge_child_shapes:
- * @window: a #GdkWindow
- *
- * Merges the shape masks for any child windows into the
- * shape mask for @window. i.e. the union of all masks
- * for @window and its children will become the new mask
- * for @window. See gdk_window_shape_combine_mask().
- *
- * This function is distinct from gdk_window_set_child_shapes()
- * because it includes @window's shape mask in the set of shapes to
- * be merged.
- */
void
-gdk_window_merge_child_shapes (GdkWindow *window)
+_gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
{
- GdkWindowObject *private;
+ GdkDisplay *display;
+ GdkWindow *toplevel;
+ GdkWindowObject *toplevel_priv;
- g_return_if_fail (GDK_IS_WINDOW (window));
+ display = gdk_drawable_get_display (changed_window);
- private = (GdkWindowObject *) window;
+ toplevel = get_event_toplevel (changed_window);
+ toplevel_priv = (GdkWindowObject *)toplevel;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->merge_child_shapes (window);
+ if (toplevel == display->pointer_info.toplevel_under_pointer &&
+ !toplevel_priv->synthesize_crossing_event_queued)
+ {
+ toplevel_priv->synthesize_crossing_event_queued = TRUE;
+ g_idle_add_full (GDK_PRIORITY_EVENTS - 1,
+ do_synthesize_crossing_event,
+ g_object_ref (toplevel),
+ g_object_unref);
+ }
}
-
-/**
- * gdk_window_set_static_gravities:
- * @window: a #GdkWindow
- * @use_static: %TRUE to turn on static gravity
- *
- * Set the bit gravity of the given window to static, and flag it so
- * all children get static subwindow gravity. This is used if you are
- * implementing scary features that involve deep knowledge of the
- * windowing system. Don't worry about it unless you have to.
- *
- * Return value: %TRUE if the server supports static gravity
- */
-gboolean
-gdk_window_set_static_gravities (GdkWindow *window,
- gboolean use_static)
+/* Don't use for crossing events */
+static GdkWindow *
+get_event_window (GdkDisplay *display,
+ GdkWindow *pointer_window,
+ GdkEventType type,
+ GdkModifierType mask,
+ guint *evmask_out,
+ gulong serial)
{
- GdkWindowObject *private;
+ guint evmask;
+ GdkWindow *grab_window;
+ GdkWindowObject *w;
+ GdkPointerGrabInfo *grab;
- g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+ grab = _gdk_display_has_pointer_grab (display, serial);
- private = (GdkWindowObject *) window;
+ if (grab != NULL && !grab->owner_events)
+ {
+ evmask = grab->event_mask;
+ evmask = update_evmask_for_button_motion (evmask, mask);
- return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
-}
+ grab_window = grab->window;
-/**
- * gdk_window_set_composited:
- * @window: a #GdkWindow
- * @composited: %TRUE to set the window as composited
- *
- * Sets a #GdkWindow as composited, or unsets it. Composited
- * windows do not automatically have their contents drawn to
- * the screen. Drawing is redirected to an offscreen buffer
- * and an expose event is emitted on the parent of the composited
- * window. It is the responsibility of the parent's expose handler
- * to manually merge the off-screen content onto the screen in
- * whatever way it sees fit. See <xref linkend="composited-window-example"/>
- * for an example.
- *
- * It only makes sense for child windows to be composited; see
- * gdk_window_set_opacity() if you need translucent toplevel
- * windows.
- *
- * An additional effect of this call is that the area of this
- * window is no longer clipped from regions marked for
- * invalidation on its parent. Draws done on the parent
- * window are also no longer clipped by the child.
- *
- * This call is only supported on some systems (currently,
- * only X11 with new enough Xcomposite and Xdamage extensions).
- * You must call gdk_display_supports_composite() to check if
- * setting a window as composited is supported before
- * attempting to do so.
- *
- * Since: 2.12
- */
-void
-gdk_window_set_composited (GdkWindow *window,
- gboolean composited)
-{
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkDisplay *display;
+ if (evmask & type_masks[type])
+ {
+ if (evmask_out)
+ *evmask_out = evmask;
+ return grab_window;
+ }
+ else
+ return NULL;
+ }
- g_return_if_fail (GDK_IS_WINDOW (window));
+ w = (GdkWindowObject *)pointer_window;
+ while (w != NULL)
+ {
+ evmask = w->event_mask;
+ evmask = update_evmask_for_button_motion (evmask, mask);
- composited = composited != FALSE;
+ if (evmask & type_masks[type])
+ {
+ if (evmask_out)
+ *evmask_out = evmask;
+ return (GdkWindow *)w;
+ }
- if (private->composited == composited)
- return;
+ w = get_event_parent (w);
+ }
- display = gdk_drawable_get_display (GDK_DRAWABLE (window));
+ if (grab != NULL &&
+ grab->owner_events)
+ {
+ evmask = grab->event_mask;
+ evmask = update_evmask_for_button_motion (evmask, mask);
- if (!gdk_display_supports_composite (display) && composited)
+ if (evmask & type_masks[type])
+ {
+ if (evmask_out)
+ *evmask_out = evmask;
+ return grab->window;
+ }
+ else
+ return NULL;
+ }
+
+ return NULL;
+}
+
+static gboolean
+proxy_pointer_event (GdkDisplay *display,
+ GdkEvent *source_event,
+ gulong serial)
+{
+ GdkWindow *toplevel_window, *event_window;
+ GdkWindow *pointer_window;
+ GdkEvent *event;
+ guint state;
+ gdouble toplevel_x, toplevel_y;
+ guint32 time_;
+
+ event_window = source_event->any.window;
+ gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
+ gdk_event_get_state (source_event, &state);
+ time_ = gdk_event_get_time (source_event);
+ toplevel_window = convert_native_coords_to_toplevel (event_window,
+ toplevel_x, toplevel_y,
+ &toplevel_x, &toplevel_y);
+
+
+ /* If we get crossing events with subwindow unexpectedly being NULL
+ that means there is a native subwindow that gdk doesn't know about.
+ We track these and forward them, with the correct virtual window
+ events inbetween.
+ This is important to get right, as metacity uses gdk for the frame
+ windows, but gdk doesn't know about the client windows reparented
+ into the frame. */
+ if (((source_event->type == GDK_LEAVE_NOTIFY &&
+ source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
+ (source_event->type == GDK_ENTER_NOTIFY &&
+ (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
+ source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
+ source_event->crossing.subwindow == NULL)
{
- g_warning ("gdk_window_set_composited called but "
- "compositing is not supported");
- return;
+ /* Left for an unknown (to gdk) subwindow */
+
+ /* Send leave events from window under pointer to event window
+ that will get the subwindow == NULL window */
+ _gdk_syntesize_crossing_events (display,
+ display->pointer_info.window_under_pointer,
+ event_window,
+ source_event->crossing.mode,
+ toplevel_x, toplevel_y,
+ state, time_,
+ source_event,
+ serial);
+
+ /* Send subwindow == NULL event */
+ send_crossing_event (display,
+ (GdkWindowObject *)toplevel_window,
+ (GdkWindowObject *)event_window,
+ source_event->type,
+ source_event->crossing.mode,
+ source_event->crossing.detail,
+ NULL,
+ toplevel_x, toplevel_y,
+ state, time_,
+ source_event,
+ serial);
+
+ _gdk_display_set_window_under_pointer (display, NULL);
+ return TRUE;
}
- _gdk_windowing_window_set_composited (window, composited);
+ pointer_window = get_pointer_window (display, toplevel_window,
+ toplevel_x, toplevel_y, serial);
- private->composited = composited;
+ if (((source_event->type == GDK_ENTER_NOTIFY &&
+ source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
+ (source_event->type == GDK_LEAVE_NOTIFY &&
+ (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
+ source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
+ source_event->crossing.subwindow == NULL)
+ {
+ /* Entered from an unknown (to gdk) subwindow */
+
+ /* Send subwindow == NULL event */
+ send_crossing_event (display,
+ (GdkWindowObject *)toplevel_window,
+ (GdkWindowObject *)event_window,
+ source_event->type,
+ source_event->crossing.mode,
+ source_event->crossing.detail,
+ NULL,
+ toplevel_x, toplevel_y,
+ state, time_,
+ source_event,
+ serial);
+
+ /* Send enter events from event window to pointer_window */
+ _gdk_syntesize_crossing_events (display,
+ event_window,
+ pointer_window,
+ source_event->crossing.mode,
+ toplevel_x, toplevel_y,
+ state, time_,
+ source_event,
+ serial);
+ _gdk_display_set_window_under_pointer (display, pointer_window);
+ return TRUE;
+ }
+
+ if (display->pointer_info.window_under_pointer != pointer_window)
+ {
+ /* Either a toplevel crossing notify that ended up inside a child window,
+ or a motion notify that got into another child window */
+
+ /* Different than last time, send crossing events */
+ _gdk_syntesize_crossing_events (display,
+ display->pointer_info.window_under_pointer,
+ pointer_window,
+ GDK_CROSSING_NORMAL,
+ toplevel_x, toplevel_y,
+ state, time_,
+ source_event,
+ serial);
+ _gdk_display_set_window_under_pointer (display, pointer_window);
+ }
+ else if (source_event->type == GDK_MOTION_NOTIFY)
+ {
+ GdkWindow *event_win;
+ guint evmask;
+ gboolean is_hint;
+
+ event_win = get_event_window (display,
+ pointer_window,
+ source_event->type,
+ state,
+ &evmask,
+ serial);
+
+ is_hint = FALSE;
+
+ if (event_win &&
+ (evmask & GDK_POINTER_MOTION_HINT_MASK))
+ {
+ if (display->pointer_info.motion_hint_serial != 0 &&
+ serial < display->pointer_info.motion_hint_serial)
+ event_win = NULL; /* Ignore event */
+ else
+ {
+ is_hint = TRUE;
+ display->pointer_info.motion_hint_serial = G_MAXULONG;
+ }
+ }
+
+ if (event_win && !display->ignore_core_events)
+ {
+ event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
+ event->motion.time = time_;
+ convert_toplevel_coords_to_window (event_win,
+ toplevel_x, toplevel_y,
+ &event->motion.x, &event->motion.y);
+ event->motion.x_root = source_event->motion.x_root;
+ event->motion.y_root = source_event->motion.y_root;;
+ event->motion.state = state;
+ event->motion.is_hint = is_hint;
+ event->motion.device = NULL;
+ event->motion.device = source_event->motion.device;
+ }
+ }
+
+ /* unlink all move events from queue.
+ We handle our own, including our emulated masks. */
+ return TRUE;
}
+#define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
+ GDK_BUTTON2_MASK | \
+ GDK_BUTTON3_MASK | \
+ GDK_BUTTON4_MASK | \
+ GDK_BUTTON5_MASK)
-static void
-remove_redirect_from_children (GdkWindowObject *private,
- GdkWindowRedirect *redirect)
+static gboolean
+proxy_button_event (GdkEvent *source_event,
+ gulong serial)
{
- GList *l;
- GdkWindowObject *child;
-
- for (l = private->children; l != NULL; l = l->next)
+ GdkWindow *toplevel_window, *event_window;
+ GdkWindow *event_win;
+ GdkWindow *pointer_window;
+ GdkWindowObject *parent;
+ GdkEvent *event;
+ guint state;
+ guint32 time_;
+ GdkEventType type;
+ gdouble toplevel_x, toplevel_y;
+ GdkDisplay *display;
+ GdkWindowObject *w;
+
+ type = source_event->any.type;
+ event_window = source_event->any.window;
+ gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
+ gdk_event_get_state (source_event, &state);
+ time_ = gdk_event_get_time (source_event);
+ display = gdk_drawable_get_display (source_event->any.window);
+ toplevel_window = convert_native_coords_to_toplevel (event_window,
+ toplevel_x, toplevel_y,
+ &toplevel_x, &toplevel_y);
+
+ if (type == GDK_BUTTON_PRESS &&
+ _gdk_display_has_pointer_grab (display, serial) == NULL)
{
- child = l->data;
-
- /* Don't redirect this child if it already has another redirect */
- if (child->redirect == redirect)
+ pointer_window =
+ _gdk_window_find_descendant_at (toplevel_window,
+ toplevel_x, toplevel_y,
+ NULL, NULL);
+
+ /* Find the event window, that gets the grab */
+ w = (GdkWindowObject *)pointer_window;
+ while (w != NULL &&
+ (parent = get_event_parent (w)) != NULL &&
+ parent->window_type != GDK_WINDOW_ROOT)
{
- child->redirect = NULL;
- remove_redirect_from_children (child, redirect);
+ if (w->event_mask & GDK_BUTTON_PRESS_MASK)
+ break;
+ w = parent;
}
+ pointer_window = (GdkWindow *)w;
+
+ _gdk_display_add_pointer_grab (display,
+ pointer_window,
+ toplevel_window,
+ FALSE,
+ gdk_window_get_events (pointer_window),
+ serial,
+ time_,
+ TRUE);
+ _gdk_display_pointer_grab_update (display, serial);
}
-}
-/**
- * gdk_window_remove_redirection:
- * @window: a #GdkWindow
- *
- * Removes any active redirection started by
- * gdk_window_redirect_to_drawable().
- *
- * Since: 2.14
- **/
-void
-gdk_window_remove_redirection (GdkWindow *window)
-{
- GdkWindowObject *private;
+ pointer_window = get_pointer_window (display, toplevel_window,
+ toplevel_x, toplevel_y,
+ serial);
- g_return_if_fail (GDK_IS_WINDOW (window));
+ event_win = get_event_window (display,
+ pointer_window,
+ type, state,
+ NULL, serial);
- private = (GdkWindowObject *) window;
+ if (event_win == NULL || display->ignore_core_events)
+ return TRUE;
- if (private->redirect &&
- private->redirect->redirected == private)
+ event = _gdk_make_event (event_win, type, source_event, FALSE);
+
+ switch (type)
{
- remove_redirect_from_children (private, private->redirect);
- gdk_window_redirect_free (private->redirect);
- private->redirect = NULL;
+ case GDK_BUTTON_PRESS:
+ case GDK_BUTTON_RELEASE:
+ event->button.button = source_event->button.button;
+ convert_toplevel_coords_to_window (event_win,
+ toplevel_x, toplevel_y,
+ &event->button.x, &event->button.y);
+ event->button.x_root = source_event->button.x_root;
+ event->button.y_root = source_event->button.y_root;
+ event->button.state = state;
+ event->button.device = source_event->button.device;
+
+ if (type == GDK_BUTTON_PRESS)
+ _gdk_event_button_generate (display, event);
+ return TRUE;
+
+ case GDK_SCROLL:
+ event->scroll.direction = source_event->scroll.direction;
+ convert_toplevel_coords_to_window (event_win,
+ toplevel_x, toplevel_y,
+ &event->scroll.x, &event->scroll.y);
+ event->scroll.x_root = source_event->scroll.x_root;
+ event->scroll.y_root = source_event->scroll.y_root;
+ event->scroll.state = state;
+ event->scroll.device = source_event->scroll.device;
+ return TRUE;
+
+ default:
+ return FALSE;
}
+
+ return TRUE; /* Always unlink original, we want to obey the emulated event mask */
}
+#ifdef DEBUG_WINDOW_PRINTING
static void
-apply_redirect_to_children (GdkWindowObject *private,
- GdkWindowRedirect *redirect)
+gdk_window_print (GdkWindowObject *window,
+ int indent)
{
- GList *l;
- GdkWindowObject *child;
+ GdkRectangle r;
- for (l = private->children; l != NULL; l = l->next)
- {
- child = l->data;
+ g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
+ window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
+ window->x, window->y,
+ window->width, window->height
+ );
- /* Don't redirect this child if it already has another redirect */
- if (!child->redirect)
- {
- child->redirect = redirect;
- apply_redirect_to_children (child, redirect);
- }
+ if (gdk_window_has_impl (window))
+ {
+#ifdef GDK_WINDOWING_X11
+ g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
+#endif
}
+
+ if (window->input_only)
+ g_print (" input-only");
+
+ if (!gdk_window_is_visible ((GdkWindow *)window))
+ g_print (" hidden");
+
+ g_print (" abs[%d,%d]",
+ window->abs_x, window->abs_y);
+
+ gdk_region_get_clipbox (window->clip_region, &r);
+ if (gdk_region_empty (window->clip_region))
+ g_print (" clipbox[empty]");
+ else
+ g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
+
+ g_print ("\n");
}
-/**
- * gdk_window_redirect_to_drawable:
- * @window: a #GdkWindow
- * @drawable: a #GdkDrawable
- * @src_x: x position in @window
- * @src_y: y position in @window
- * @dest_x: x position in @drawable
- * @dest_y: y position in @drawable
- * @width: width of redirection
- * @height: height of redirection
- *
- * Redirects drawing into @window so that drawing to the
- * window in the rectangle specified by @src_x, @src_y,
- * @width and @height is also drawn into @drawable at
- * @dest_x, @dest_y.
- *
- * Only drawing between gdk_window_begin_paint_region() or
- * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
- * redirected.
- *
- * Redirection is active until gdk_window_remove_redirection()
- * is called.
- *
- * Since: 2.14
- **/
-void
-gdk_window_redirect_to_drawable (GdkWindow *window,
- GdkDrawable *drawable,
- gint src_x,
- gint src_y,
- gint dest_x,
- gint dest_y,
- gint width,
- gint height)
+
+static void
+gdk_window_print_tree (GdkWindow *window,
+ int indent,
+ gboolean include_input_only)
{
GdkWindowObject *private;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
- g_return_if_fail (GDK_IS_DRAWABLE (drawable));
- g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
+ GList *l;
- private = (GdkWindowObject *) window;
+ private = (GdkWindowObject *)window;
- if (private->redirect)
- gdk_window_remove_redirection (window);
+ if (private->input_only && !include_input_only)
+ return;
- if (width == -1 || height == -1)
- {
- gint w, h;
- gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
- if (width == -1)
- width = w;
- if (height == -1)
- height = h;
- }
-
- private->redirect = g_new0 (GdkWindowRedirect, 1);
- private->redirect->redirected = private;
- private->redirect->pixmap = g_object_ref (drawable);
- private->redirect->src_x = src_x;
- private->redirect->src_y = src_y;
- private->redirect->dest_x = dest_x;
- private->redirect->dest_y = dest_y;
- private->redirect->width = width;
- private->redirect->height = height;
+ gdk_window_print (private, indent);
- apply_redirect_to_children (private, private->redirect);
+ for (l = private->children; l != NULL; l = l->next)
+ gdk_window_print_tree (l->data, indent + 4, include_input_only);
}
-static void
-window_get_size_rectangle (GdkWindow *window,
- GdkRectangle *rect)
+#endif /* DEBUG_WINDOW_PRINTING */
+
+static gboolean
+is_input_event (GdkDisplay *display,
+ GdkEvent *event)
{
- rect->x = rect->y = 0;
- gdk_drawable_get_size (GDK_DRAWABLE (window), &rect->width, &rect->height);
+ GdkDevice *core_pointer;
+
+ core_pointer = gdk_display_get_core_pointer (display);
+ if ((event->type == GDK_MOTION_NOTIFY &&
+ event->motion.device != core_pointer) ||
+ ((event->type == GDK_BUTTON_PRESS ||
+ event->type == GDK_BUTTON_RELEASE) &&
+ event->button.device != core_pointer))
+ return TRUE;
+ return FALSE;
}
-/* Calculates the real clipping region for a window, in window coordinates,
- * taking into account other windows, gc clip region and gc clip mask.
- */
-static GdkRegion *
-_gdk_window_calculate_full_clip_region (GdkWindow *window,
- GdkWindow *base_window,
- GdkGC *gc,
- gboolean do_children,
- gint *base_x_offset,
- gint *base_y_offset)
+void
+_gdk_windowing_got_event (GdkDisplay *display,
+ GList *event_link,
+ GdkEvent *event,
+ gulong serial)
{
- GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
- GdkRectangle visible_rect;
- GdkRegion *real_clip_region, *tmpreg;
- gint x_offset, y_offset;
- GdkWindowObject *parentwin, *lastwin;
+ GdkWindow *event_window;
+ GdkWindowObject *event_private;
+ gdouble x, y;
+ gboolean unlink_event;
+ guint old_state, old_button;
+ GdkPointerGrabInfo *button_release_grab;
+ gboolean is_toplevel;
+
+ if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
+ display->last_event_time = gdk_event_get_time (event);
+
+ _gdk_display_pointer_grab_update (display,
+ serial);
+
+ event_window = event->any.window;
+ if (!event_window)
+ return;
- if (base_x_offset)
- *base_x_offset = 0;
- if (base_y_offset)
- *base_y_offset = 0;
-
- if (!GDK_WINDOW_IS_MAPPED (window) || private->input_only)
- return gdk_region_new ();
+ event_private = GDK_WINDOW_OBJECT (event_window);
- window_get_size_rectangle (window, &visible_rect);
+#ifdef DEBUG_WINDOW_PRINTING
+ if (event->type == GDK_KEY_PRESS &&
+ (event->key.keyval == 0xa7 ||
+ event->key.keyval == 0xbd))
+ {
+ gdk_window_print_tree (event_window, 0,
+ event->key.keyval == 0xbd);
+ }
+#endif
- /* windows that a redirection has ben setup for need to be considered
- * fully visible, in order to avoid missing redirected paint ops
- * anywhere in the window area.
- */
- if (private->redirect && private->redirect->redirected == private)
- return gdk_region_rectangle (&visible_rect);
+ if (event->type == GDK_VISIBILITY_NOTIFY)
+ {
+ event_private->native_visibility = event->visibility.state;
+ gdk_window_update_visibility_recursively (event_private,
+ event_private);
+ return;
+ }
- /* real_clip_region is in window coordinates */
- real_clip_region = gdk_region_rectangle (&visible_rect);
+ if (is_input_event (display, event))
+ return;
- x_offset = y_offset = 0;
+ if (!(is_button_type (event->type) ||
+ is_motion_type (event->type)) ||
+ GDK_WINDOW_TYPE (event_private) == GDK_WINDOW_ROOT)
+ return;
- lastwin = private;
- if (do_children)
- parentwin = lastwin;
- else
- parentwin = lastwin->parent;
-
- /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
- for (; parentwin != NULL && (parentwin == private || lastwin != (GdkWindowObject *)base_window);
- lastwin = parentwin, parentwin = lastwin->parent)
+ is_toplevel =
+ event_private->parent == NULL ||
+ GDK_WINDOW_TYPE (event_private->parent) == GDK_WINDOW_ROOT;
+
+ if ((event->type == GDK_ENTER_NOTIFY ||
+ event->type == GDK_LEAVE_NOTIFY) &&
+ (event->crossing.mode == GDK_CROSSING_GRAB ||
+ event->crossing.mode == GDK_CROSSING_UNGRAB) &&
+ (_gdk_display_has_pointer_grab (display, serial) ||
+ event->crossing.detail == GDK_NOTIFY_INFERIOR))
{
- GList *cur;
- GdkRectangle real_clip_rect;
-
- if (parentwin != private)
+ /* We synthesize all crossing events due to grabs outselves,
+ * so we ignore the native ones caused by our native pointer_grab
+ * calls. Otherwise we would proxy these crossing event and cause
+ * multiple copies of crossing events for grabs.
+ *
+ * We do want to handle grabs from other clients though, as for
+ * instance alt-tab in metacity causes grabs like these and
+ * we want to handle those. Thus the has_pointer_grab check.
+ *
+ * Implicit grabs on child windows create some grabbing events
+ * that are sent before the button press. This means we can't
+ * detect these with the has_pointer_grab check (as the implicit
+ * grab is only noticed when we get button press event), so we
+ * detect these events by checking for INFERIOR enter or leave
+ * events. These should never be a problem to filter out.
+ */
+
+ /* We ended up in this window after some (perhaps other clients)
+ grab, so update the toplevel_under_window state */
+ if (is_toplevel &&
+ event->type == GDK_ENTER_NOTIFY &&
+ event->crossing.mode == GDK_CROSSING_UNGRAB)
{
- x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
- y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
+ if (display->pointer_info.toplevel_under_pointer)
+ g_object_unref (display->pointer_info.toplevel_under_pointer);
+ display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
}
-
- /* children is ordered in reverse stack order */
- for (cur = GDK_WINDOW_OBJECT (parentwin)->children; cur && cur->data != lastwin; cur = cur->next)
- {
- GdkWindow *child = cur->data;
- GdkWindowObject *child_private = (GdkWindowObject *)child;
-
- if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
- continue;
- window_get_size_rectangle (child, &visible_rect);
+ unlink_event = TRUE;
+ goto out;
+ }
- /* Convert rect to "window" coords */
- visible_rect.x += child_private->x - x_offset;
- visible_rect.y += child_private->y - y_offset;
-
- /* This shortcut is really necessary for performance when there are a lot of windows */
- gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
- if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
- visible_rect.x + visible_rect.width <= real_clip_rect.x ||
- visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
- visible_rect.y + visible_rect.height <= real_clip_rect.y)
- continue;
-
- tmpreg = gdk_region_rectangle (&visible_rect);
- gdk_region_subtract (real_clip_region, tmpreg);
- gdk_region_destroy (tmpreg);
+ /* Track toplevel_under_pointer */
+ if (is_toplevel)
+ {
+ if (event->type == GDK_ENTER_NOTIFY &&
+ event->crossing.detail != GDK_NOTIFY_INFERIOR)
+ {
+ if (display->pointer_info.toplevel_under_pointer)
+ g_object_unref (display->pointer_info.toplevel_under_pointer);
+ display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
+ }
+ else if (event->type == GDK_LEAVE_NOTIFY &&
+ event->crossing.detail != GDK_NOTIFY_INFERIOR &&
+ display->pointer_info.toplevel_under_pointer == event_window)
+ {
+ if (display->pointer_info.toplevel_under_pointer)
+ g_object_unref (display->pointer_info.toplevel_under_pointer);
+ display->pointer_info.toplevel_under_pointer = NULL;
}
-
- /* Clip to the parent */
- window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
- /* Convert rect to "window" coords */
- visible_rect.x += - x_offset;
- visible_rect.y += - y_offset;
-
- tmpreg = gdk_region_rectangle (&visible_rect);
- gdk_region_intersect (real_clip_region, tmpreg);
- gdk_region_destroy (tmpreg);
}
- if (gc)
+ /* Store last pointer window and position/state */
+ old_state = display->pointer_info.state;
+ old_button = display->pointer_info.button;
+
+ gdk_event_get_coords (event, &x, &y);
+ convert_native_coords_to_toplevel (event_window, x, y, &x, &y);
+ display->pointer_info.toplevel_x = x;
+ display->pointer_info.toplevel_y = y;
+ gdk_event_get_state (event, &display->pointer_info.state);
+ if (event->type == GDK_BUTTON_PRESS ||
+ event->type == GDK_BUTTON_RELEASE)
+ display->pointer_info.button = event->button.button;
+
+ if (display->pointer_info.state != old_state ||
+ display->pointer_info.button != old_button)
+ _gdk_display_enable_motion_hints (display);
+
+ unlink_event = FALSE;
+ if (is_motion_type (event->type))
+ unlink_event = proxy_pointer_event (display,
+ event,
+ serial);
+ else if (is_button_type (event->type))
+ unlink_event = proxy_button_event (event,
+ serial);
+
+ if (event->type == GDK_BUTTON_RELEASE)
{
- GdkRegion *clip_region = _gdk_gc_get_clip_region (gc);
-
- if (clip_region)
+ button_release_grab =
+ _gdk_display_has_pointer_grab (display, serial);
+ if (button_release_grab &&
+ button_release_grab->implicit &&
+ (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
{
- /* clip_region is relative to gc clip origin which is relative to the window */
- /* offset it to window relative: */
- tmpreg = gdk_region_copy (clip_region);
- gdk_region_offset (real_clip_region,
- gc->clip_x_origin,
- gc->clip_y_origin);
- /* Intersect it with window hierarchy cliprect: */
- gdk_region_intersect (real_clip_region, tmpreg);
- gdk_region_destroy (tmpreg);
+ button_release_grab->serial_end = serial;
+ button_release_grab->implicit_ungrab = TRUE;
+ _gdk_display_pointer_grab_update (display, serial);
}
}
- if (base_x_offset)
- *base_x_offset = x_offset;
- if (base_y_offset)
- *base_y_offset = y_offset;
-
- return real_clip_region;
+ out:
+ if (unlink_event)
+ {
+ _gdk_event_queue_remove_link (display, event_link);
+ g_list_free_1 (event_link);
+ gdk_event_free (event);
+ }
}
-static void
-gdk_window_add_damage (GdkWindow *toplevel,
- GdkRegion *damaged_region)
-{
- GdkDisplay *display;
- GdkEvent event = { 0, };
- event.expose.type = GDK_DAMAGE;
- event.expose.window = toplevel;
- event.expose.send_event = FALSE;
- event.expose.region = damaged_region;
- gdk_region_get_clipbox (event.expose.region, &event.expose.area);
- display = gdk_drawable_get_display (event.expose.window);
- _gdk_event_queue_append (display, gdk_event_copy (&event));
-}
-static void
-setup_redirect_clip (GdkWindow *window,
- GdkGC *gc,
- GdkWindowClipData *data)
+static GdkWindow *
+get_extension_event_window (GdkDisplay *display,
+ GdkWindow *pointer_window,
+ GdkEventType type,
+ gulong serial)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkRegion *visible_region;
- GdkRectangle dest_rect;
- GdkRegion *tmpreg;
- GdkWindow *toplevel;
+ guint evmask;
+ GdkWindow *grab_window;
+ GdkWindowObject *w;
+ GdkPointerGrabInfo *grab;
- data->old_region = _gdk_gc_get_clip_region (gc);
- if (data->old_region)
- data->old_region = gdk_region_copy (data->old_region);
+ grab = _gdk_display_has_pointer_grab (display, serial);
- data->old_clip_x_origin = gc->clip_x_origin;
- data->old_clip_y_origin = gc->clip_y_origin;
+ if (grab != NULL && !grab->owner_events)
+ {
+ evmask = grab->event_mask;
- toplevel = GDK_WINDOW (private->redirect->redirected);
-
- /* Get the clip region for gc clip rect + window hierarchy in
- window relative coords */
- visible_region =
- _gdk_window_calculate_full_clip_region (window, toplevel,
- gc, TRUE,
- &data->x_offset,
- &data->y_offset);
+ grab_window = grab->window;
- /* Compensate for the source pos/size */
- data->x_offset -= private->redirect->src_x;
- data->y_offset -= private->redirect->src_y;
- dest_rect.x = -data->x_offset;
- dest_rect.y = -data->y_offset;
- dest_rect.width = private->redirect->width;
- dest_rect.height = private->redirect->height;
- tmpreg = gdk_region_rectangle (&dest_rect);
- gdk_region_intersect (visible_region, tmpreg);
- gdk_region_destroy (tmpreg);
+ if (evmask & type_masks[type])
+ return grab_window;
+ else
+ return NULL;
+ }
- /* Compensate for the dest pos */
- data->x_offset += private->redirect->dest_x;
- data->y_offset += private->redirect->dest_y;
+ w = (GdkWindowObject *)pointer_window;
+ while (w != NULL)
+ {
+ evmask = w->extension_events;
- gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
+ if (evmask & type_masks[type])
+ return (GdkWindow *)w;
- /* offset clip and tiles from window coords to pixmaps coords */
- gdk_gc_offset (gc, -data->x_offset, -data->y_offset);
+ w = get_event_parent (w);
+ }
- /* Offset region to abs coords and add to damage */
- gdk_region_offset (visible_region, data->x_offset, data->y_offset);
- gdk_window_add_damage (toplevel, visible_region);
-
- gdk_region_destroy (visible_region);
-}
+ if (grab != NULL &&
+ grab->owner_events)
+ {
+ evmask = grab->event_mask;
-static void
-reset_redirect_clip (GdkWindow *offscreen,
- GdkGC *gc,
- GdkWindowClipData *data)
-{
- /* offset back */
- gdk_gc_offset (gc, data->x_offset, data->y_offset);
+ if (evmask & type_masks[type])
+ return grab->window;
+ else
+ return NULL;
+ }
- /* reset old clip */
- gdk_gc_set_clip_region (gc, data->old_region);
- if (data->old_region)
- gdk_region_destroy (data->old_region);
- gdk_gc_set_clip_origin (gc, data->old_clip_x_origin, data->old_clip_y_origin);
+ return NULL;
}
-static void
-gdk_window_redirect_free (GdkWindowRedirect *redirect)
+
+GdkWindow *
+_gdk_window_get_input_window_for_event (GdkWindow *native_window,
+ GdkEventType event_type,
+ int x, int y,
+ gulong serial)
{
- g_object_unref (redirect->pixmap);
- g_free (redirect);
+ GdkDisplay *display;
+ GdkWindow *toplevel_window;
+ GdkWindow *pointer_window;
+ GdkWindow *event_win;
+ gdouble toplevel_x, toplevel_y;
+
+ toplevel_x = x;
+ toplevel_y = y;
+
+ display = gdk_drawable_get_display (native_window);
+ toplevel_window = convert_native_coords_to_toplevel (native_window,
+ toplevel_x, toplevel_y,
+ &toplevel_x, &toplevel_y);
+ pointer_window = get_pointer_window (display, toplevel_window,
+ toplevel_x, toplevel_y, serial);
+ event_win = get_extension_event_window (display,
+ pointer_window,
+ event_type,
+ serial);
+
+ return event_win;
}
+
#define __GDK_WINDOW_C__
#include "gdkaliasdef.c"
G_BEGIN_DECLS
-typedef struct _GdkGeometry GdkGeometry;
-typedef struct _GdkWindowAttr GdkWindowAttr;
-typedef struct _GdkPointerHooks GdkPointerHooks;
-typedef struct _GdkWindowRedirect GdkWindowRedirect;
+typedef struct _GdkGeometry GdkGeometry;
+typedef struct _GdkWindowAttr GdkWindowAttr;
+typedef struct _GdkPointerHooks GdkPointerHooks;
+typedef struct _GdkWindowRedirect GdkWindowRedirect;
/* Classes of windows.
* InputOutput: Almost every window should be of this type. Such windows
GDK_WINDOW_CHILD,
GDK_WINDOW_DIALOG,
GDK_WINDOW_TEMP,
- GDK_WINDOW_FOREIGN
+ GDK_WINDOW_FOREIGN,
+ GDK_WINDOW_OFFSCREEN
} GdkWindowType;
/* Window attribute mask values.
#define GDK_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WINDOW, GdkWindowObjectClass))
#define GDK_WINDOW_OBJECT(object) ((GdkWindowObject *) GDK_WINDOW (object))
+#ifndef GDK_COMPILATION
+/* We used to export all of GdkWindowObject, but we don't want to keep doing so.
+ However, there are various parts of it accessed by macros and other code,
+ so we keep the old exported version public, but in reality it is larger. */
+
+/**** DON'T CHANGE THIS STRUCT, the real version is in gdkinternals.h ****/
struct _GdkWindowObject
{
GdkDrawable parent_instance;
GdkWindowRedirect *redirect;
};
+#endif
struct _GdkWindowObjectClass
{
const GdkRegion *region,
gint dx,
gint dy);
+gboolean gdk_window_ensure_native (GdkWindow *window);
/*
* This allows for making shaped (partially transparent) windows
gint gdk_window_get_origin (GdkWindow *window,
gint *x,
gint *y);
+gint gdk_window_get_root_coords (GdkWindow *window,
+ gint x,
+ gint y,
+ gint *root_x,
+ gint *root_y);
#if !defined (GDK_DISABLE_DEPRECATED) || defined (GTK_COMPILATION)
/* Used by gtk_handle_box_button_changed () */
GdkWindow *gdk_get_default_root_window (void);
-void gdk_window_redirect_to_drawable (GdkWindow *window,
- GdkDrawable *drawable,
- gint src_x, gint src_y,
- gint dest_x, gint dest_y,
- gint width, gint height);
-void gdk_window_remove_redirection (GdkWindow *window);
+/* Offscreen redirection */
+GdkPixmap *gdk_window_get_offscreen_pixmap (GdkWindow *window);
+void gdk_window_set_has_offscreen_children (GdkWindow *window,
+ gboolean has_offscreen_children);
+gboolean gdk_window_get_has_offscreen_children (GdkWindow *window);
+void gdk_window_offscreen_children_changed (GdkWindow *window);
+
+void gdk_window_redirect_to_drawable (GdkWindow *window,
+ GdkDrawable *drawable,
+ gint src_x,
+ gint src_y,
+ gint dest_x,
+ gint dest_y,
+ gint width,
+ gint height);
+void gdk_window_remove_redirection (GdkWindow *window);
#ifndef GDK_DISABLE_DEPRECATED
#define GDK_ROOT_PARENT() (gdk_get_default_root_window ())
GTypeInterface g_iface;
void (* show) (GdkWindow *window,
- gboolean raise);
+ gboolean already_mapped);
void (* hide) (GdkWindow *window);
void (* withdraw) (GdkWindow *window);
void (* raise) (GdkWindow *window);
void (* lower) (GdkWindow *window);
+ void (* restack_under) (GdkWindow *window,
+ GList *native_siblings);
void (* move_resize) (GdkWindow *window,
gboolean with_move,
gint y,
gint width,
gint height);
- void (* move_region) (GdkWindow *window,
- const GdkRegion *region,
- gint dx,
- gint dy);
- void (* scroll) (GdkWindow *window,
- gint dx,
- gint dy);
-
- void (* clear_area) (GdkWindow *window,
- gint x,
- gint y,
- gint width,
- gint height,
- gboolean send_expose);
void (* set_background) (GdkWindow *window,
const GdkColor *color);
void (* set_back_pixmap) (GdkWindow *window,
- GdkPixmap *pixmap,
- gboolean parent_relative);
+ GdkPixmap *pixmap);
GdkEventMask (* get_events) (GdkWindow *window);
void (* set_events) (GdkWindow *window,
gint *width,
gint *height,
gint *depth);
- gint (* get_origin) (GdkWindow *window,
+ gint (* get_root_coords) (GdkWindow *window,
+ gint x,
+ gint y,
+ gint *root_x,
+ gint *root_y);
+ gint (* get_deskrelative_origin) (GdkWindow *window,
gint *x,
gint *y);
- void (* get_offsets) (GdkWindow *window,
- gint *x_offset,
- gint *y_offset);
+ gboolean (* get_pointer) (GdkWindow *window,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask);
- void (* shape_combine_mask) (GdkWindow *window,
- GdkBitmap *mask,
- gint x,
- gint y);
void (* shape_combine_region) (GdkWindow *window,
const GdkRegion *shape_region,
gint offset_x,
gint offset_y);
- void (* set_child_shapes) (GdkWindow *window);
- void (* merge_child_shapes) (GdkWindow *window);
+ void (* input_shape_combine_region) (GdkWindow *window,
+ const GdkRegion *shape_region,
+ gint offset_x,
+ gint offset_y);
gboolean (* set_static_gravities) (GdkWindow *window,
gboolean use_static);
+
+ /* Called before processing updates for a window. This gives the windowing
+ * layer a chance to save the region for later use in avoiding duplicate
+ * exposes. The return value indicates whether the function has a saved
+ * the region; if the result is TRUE, then the windowing layer is responsible
+ * for destroying the region later.
+ */
+ gboolean (* queue_antiexpose) (GdkWindow *window,
+ GdkRegion *update_area);
+ void (* queue_translation) (GdkWindow *window,
+ GdkRegion *area,
+ gint dx,
+ gint dy);
+
+/* Called to do the windowing system specific part of gdk_window_destroy(),
+ *
+ * window: The window being destroyed
+ * recursing: If TRUE, then this is being called because a parent
+ * was destroyed. This generally means that the call to the windowing system
+ * to destroy the window can be omitted, since it will be destroyed as a result
+ * of the parent being destroyed. Unless @foreign_destroy
+ *
+ * foreign_destroy: If TRUE, the window or a parent was destroyed by some external
+ * agency. The window has already been destroyed and no windowing
+ * system calls should be made. (This may never happen for some
+ * windowing systems.)
+ */
+ void (* destroy) (GdkWindow *window,
+ gboolean recursing,
+ gboolean foreign_destroy);
+
+ void (* input_window_destroy) (GdkWindow *window);
+ void (* input_window_crossing)(GdkWindow *window,
+ gboolean enter);
};
/* Interface Functions */
GType gdk_window_impl_get_type (void) G_GNUC_CONST;
+/* private definitions from gdkwindow.h */
+
+struct _GdkWindowRedirect
+{
+ GdkWindowObject *redirected;
+ GdkDrawable *pixmap;
+
+ gint src_x;
+ gint src_y;
+ gint dest_x;
+ gint dest_y;
+ gint width;
+ gint height;
+
+ GdkRegion *damage;
+ guint damage_idle;
+};
+
G_END_DECLS
#endif /* __GDK_WINDOW_IMPL_H__ */
return gdk_window;
}
+-(NSTrackingRectTag)trackingRect
+{
+ return trackingRect;
+}
+
-(BOOL)isFlipped
{
return YES;
if (NSEqualRects (rect, NSZeroRect))
return;
- GDK_QUARTZ_ALLOC_POOL;
-
[self getRectsBeingDrawn:&drawn_rects count:&count];
- region = gdk_region_new ();
-
- for (i = 0; i < count; i++)
- {
- gdk_rect.x = drawn_rects[i].origin.x;
- gdk_rect.y = drawn_rects[i].origin.y;
- gdk_rect.width = drawn_rects[i].size.width;
- gdk_rect.height = drawn_rects[i].size.height;
-
- gdk_region_union_with_rect (region, &gdk_rect);
- }
-
- if (!gdk_region_empty (region))
+ /* Note: arbitrary limit here to not degrade performace too much. It would
+ * be better to optimize the construction of the region below, by using
+ * _gdk_region_new_from_yxbanded_rects.
+ */
+ if (count > 25)
{
- GdkEvent event;
-
gdk_rect.x = rect.origin.x;
gdk_rect.y = rect.origin.y;
gdk_rect.width = rect.size.width;
gdk_rect.height = rect.size.height;
-
- event.expose.type = GDK_EXPOSE;
- event.expose.window = g_object_ref (gdk_window);
- event.expose.send_event = FALSE;
- event.expose.count = 0;
- event.expose.region = region;
- event.expose.area = gdk_rect;
-
- impl->in_paint_rect_count++;
- (*_gdk_event_func) (&event, _gdk_event_data);
+ region = gdk_region_rectangle (&gdk_rect);
+ }
+ else
+ {
+ region = gdk_region_new ();
- impl->in_paint_rect_count--;
+ for (i = 0; i < count; i++)
+ {
+ gdk_rect.x = drawn_rects[i].origin.x;
+ gdk_rect.y = drawn_rects[i].origin.y;
+ gdk_rect.width = drawn_rects[i].size.width;
+ gdk_rect.height = drawn_rects[i].size.height;
- g_object_unref (gdk_window);
+ gdk_region_union_with_rect (region, &gdk_rect);
+ }
}
+ impl->in_paint_rect_count++;
+ _gdk_window_process_updates_recurse (gdk_window, region);
+ impl->in_paint_rect_count--;
+
gdk_region_destroy (region);
if (needsInvalidateShadow)
[[self window] invalidateShadow];
needsInvalidateShadow = NO;
}
-
- GDK_QUARTZ_RELEASE_POOL;
}
-(void)setNeedsInvalidateShadow:(BOOL)invalidate
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
NSRect rect;
+ if (!impl->toplevel)
+ return;
+
if (trackingRect)
{
[self removeTrackingRect:trackingRect];
-(void)setGdkWindow:(GdkWindow *)window;
-(GdkWindow *)gdkWindow;
+-(NSTrackingRectTag)trackingRect;
-(void)setNeedsInvalidateShadow:(BOOL)invalidate;
@end
NSRect content_rect = [self contentRectForFrameRect:[self frame]];
GdkWindow *window = [[self contentView] gdkWindow];
GdkWindowObject *private = (GdkWindowObject *)window;
- GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
GdkEvent *event;
- /* Ignore new position during showing/hiding the window, otherwise we
- * would get the off-screen position that is used for hidden windows to
- * get reliable MouseEntered events when showing them again. See comments
- * in show() and hide().
- */
- if (inShowOrHide)
- return;
-
private->x = content_rect.origin.x;
private->y = _gdk_quartz_window_get_inverted_screen_y (content_rect.origin.y + content_rect.size.height);
event->configure.window = g_object_ref (window);
event->configure.x = private->x;
event->configure.y = private->y;
- event->configure.width = impl->width;
- event->configure.height = impl->height;
+ event->configure.width = private->width;
+ event->configure.height = private->height;
_gdk_event_queue_append (gdk_display_get_default (), event);
}
NSRect content_rect = [self contentRectForFrameRect:[self frame]];
GdkWindow *window = [[self contentView] gdkWindow];
GdkWindowObject *private = (GdkWindowObject *)window;
- GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
GdkEvent *event;
- impl->width = content_rect.size.width;
- impl->height = content_rect.size.height;
+ private->width = content_rect.size.width;
+ private->height = content_rect.size.height;
+
+ [[self contentView] setFrame:NSMakeRect (0, 0, private->width, private->height)];
- [[self contentView] setFrame:NSMakeRect (0, 0, impl->width, impl->height)];
+ _gdk_window_update_size (window);
/* Synthesize a configure event */
event = gdk_event_new (GDK_CONFIGURE);
event->configure.window = g_object_ref (window);
event->configure.x = private->x;
event->configure.y = private->y;
- event->configure.width = impl->width;
- event->configure.height = impl->height;
+ event->configure.width = private->width;
+ event->configure.height = private->height;
_gdk_event_queue_append (gdk_display_get_default (), event);
}
GdkWindow *window = [[self contentView] gdkWindow];
GdkWindowObject *private = (GdkWindowObject *)window;
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
- gboolean was_hidden;
- int requested_x = 0, requested_y = 0;
inShowOrHide = YES;
- was_hidden = FALSE;
-
- if (!GDK_WINDOW_IS_MAPPED (window))
- {
- NSRect content_rect;
- NSRect frame_rect;
-
- was_hidden = TRUE;
-
- /* We move the window in place if it's not mapped. See comment in
- * hide().
- */
- content_rect =
- NSMakeRect (private->x,
- _gdk_quartz_window_get_inverted_screen_y (private->y) - impl->height,
- impl->width, impl->height);
- frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
- [impl->toplevel setFrame:frame_rect display:NO];
-
- requested_x = frame_rect.origin.x;
- requested_y = frame_rect.origin.y;
- }
if (makeKey)
[impl->toplevel makeKeyAndOrderFront:impl->toplevel];
[impl->toplevel orderFront:nil];
inShowOrHide = NO;
-
- /* When the window manager didn't allow our request, update the position
- * to what it really ended up as.
- */
- if (was_hidden)
- {
- NSRect frame_rect;
-
- frame_rect = [impl->toplevel frame];
- if (requested_x != frame_rect.origin.x || requested_y != frame_rect.origin.y)
- {
- [self windowDidMove:nil];
- }
- }
}
- (void)hide
GdkWindow *window = [[self contentView] gdkWindow];
GdkWindowObject *private = (GdkWindowObject *)window;
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
- NSRect content_rect;
- NSRect frame_rect;
inShowOrHide = YES;
-
- /* We move the window away when hiding, to make it possible to move it in
- * place when showing to get reliable tracking rect events (which are used
- * to generate crossing events). We have to do this, probably a bug in
- * quartz.
- */
- content_rect = NSMakeRect (-500 - impl->width, -500 - impl->height,
- impl->width, impl->height);
- frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
- [impl->toplevel setFrame:frame_rect display:NO];
-
[impl->toplevel orderOut:nil];
-
inShowOrHide = NO;
}
/* FIXME: Implement */
return FALSE;
}
+
+gulong
+_gdk_windowing_window_get_next_serial (GdkDisplay *display)
+{
+ return 0;
+}
*/
#include "config.h"
+#include <sys/time.h>
#include <cairo-quartz.h>
#include "gdkprivate-quartz.h"
CGContextRef cg_context;
} GdkQuartzCairoSurfaceData;
+void
+_gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
+ int width,
+ int height)
+{
+ /* This is not supported with quartz surfaces. */
+}
+
static void
gdk_quartz_cairo_surface_destroy (void *data)
{
GdkQuartzCairoSurfaceData *surface_data = data;
GdkDrawableImplQuartz *impl = GDK_DRAWABLE_IMPL_QUARTZ (surface_data->drawable);
- gdk_quartz_drawable_release_context (surface_data->drawable,
- surface_data->cg_context);
-
impl->cairo_surface = NULL;
+ gdk_quartz_drawable_release_context (surface_data->drawable,
+ surface_data->cg_context);
+
g_free (surface_data);
}
+cairo_surface_t *
+_gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
+ int width,
+ int height)
+{
+ CGContextRef cg_context;
+ GdkQuartzCairoSurfaceData *surface_data;
+ cairo_surface_t *surface;
+
+ cg_context = gdk_quartz_drawable_get_context (drawable, TRUE);
+
+ if (!cg_context)
+ return NULL;
+
+ surface_data = g_new (GdkQuartzCairoSurfaceData, 1);
+ surface_data->drawable = drawable;
+ surface_data->cg_context = cg_context;
+
+ surface = cairo_quartz_surface_create_for_cg_context (cg_context,
+ width, height);
+
+ cairo_surface_set_user_data (surface, &gdk_quartz_cairo_key,
+ surface_data,
+ gdk_quartz_cairo_surface_destroy);
+
+ return surface;
+}
+
static cairo_surface_t *
gdk_quartz_ref_cairo_surface (GdkDrawable *drawable)
{
if (!impl->cairo_surface)
{
- CGContextRef cg_context;
int width, height;
- GdkQuartzCairoSurfaceData *surface_data;
-
- cg_context = gdk_quartz_drawable_get_context (drawable, TRUE);
- if (!cg_context)
- return NULL;
gdk_drawable_get_size (drawable, &width, &height);
-
- impl->cairo_surface = cairo_quartz_surface_create_for_cg_context (cg_context, width, height);
-
- surface_data = g_new (GdkQuartzCairoSurfaceData, 1);
- surface_data->drawable = drawable;
- surface_data->cg_context = cg_context;
-
- cairo_surface_set_user_data (impl->cairo_surface, &gdk_quartz_cairo_key,
- surface_data, gdk_quartz_cairo_surface_destroy);
+ impl->cairo_surface = _gdk_windowing_create_cairo_surface (drawable,
+ width, height);
}
else
cairo_surface_reference (impl->cairo_surface);
GDK_QUARTZ_CONTEXT_FILL :
GDK_QUARTZ_CONTEXT_STROKE);
- CGContextSaveGState (context);
-
start_angle = angle1 * 2.0 * G_PI / 360.0 / 64.0;
end_angle = start_angle + angle2 * 2.0 * G_PI / 360.0 / 64.0;
CGContextStrokePath (context);
}
- CGContextRestoreGState (context);
-
gdk_quartz_drawable_release_context (drawable, context);
}
gdk_quartz_draw_drawable (GdkDrawable *drawable,
GdkGC *gc,
GdkPixmap *src,
+ GdkDrawable *original_src,
gint xsrc,
gint ysrc,
gint xdest,
int dest_depth = gdk_drawable_get_depth (drawable);
GdkDrawableImplQuartz *src_impl;
- if (GDK_IS_DRAWABLE_IMPL_QUARTZ (src))
+ if (GDK_IS_WINDOW_IMPL_QUARTZ (src))
+ {
+ GdkWindowImplQuartz *window_impl;
+
+ window_impl = GDK_WINDOW_IMPL_QUARTZ (src);
+
+ /* We do support moving areas on the same drawable, if it can be done
+ * by using a scroll. FIXME: We need to check that the params support
+ * this hack, and make sure it's done properly with any offsets etc?
+ */
+ if (drawable == (GdkDrawable *)window_impl)
+ {
+ [window_impl->view scrollRect:NSMakeRect (xsrc, ysrc, width, height)
+ by:NSMakeSize (xdest - xsrc, ydest - ysrc)];
+
+
+ }
+ else
+ g_warning ("Drawing with window source != dest is not supported");
+
+ return;
+ }
+ else if (GDK_IS_DRAWABLE_IMPL_QUARTZ (src))
src_impl = GDK_DRAWABLE_IMPL_QUARTZ (src);
else if (GDK_IS_PIXMAP (src))
src_impl = GDK_DRAWABLE_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (src)->impl);
- else if (GDK_IS_WINDOW (src))
+ else
{
- src_impl = GDK_DRAWABLE_IMPL_QUARTZ (GDK_WINDOW_OBJECT (src)->impl);
- /* FIXME: Implement drawing a window. */
+ g_warning ("Unsupported source %s", G_OBJECT_TYPE_NAME (src));
return;
}
- else
- g_assert_not_reached ();
-
+
+ /* Handle drawable and pixmap sources. */
if (src_depth == 1)
{
/* FIXME: src depth 1 is not supported yet */
+ g_warning ("Source with depth 1 unsupported");
}
else if (dest_depth != 0 && src_depth == dest_depth)
{
+ GdkPixmapImplQuartz *pixmap_impl = GDK_PIXMAP_IMPL_QUARTZ (src_impl);
CGContextRef context = gdk_quartz_drawable_get_context (drawable, FALSE);
if (!context)
- return;
+ return;
_gdk_quartz_gc_update_cg_context (gc, drawable, context,
- GDK_QUARTZ_CONTEXT_STROKE);
+ GDK_QUARTZ_CONTEXT_STROKE);
CGContextClipToRect (context, CGRectMake (xdest, ydest, width, height));
CGContextTranslateCTM (context, xdest - xsrc, ydest - ysrc +
- GDK_PIXMAP_IMPL_QUARTZ (src_impl)->height);
+ pixmap_impl->height);
CGContextScaleCTM (context, 1.0, -1.0);
- CGContextDrawImage (context,
- CGRectMake(0, 0,
- GDK_PIXMAP_IMPL_QUARTZ (src_impl)->width,
- GDK_PIXMAP_IMPL_QUARTZ (src_impl)->height),
- GDK_PIXMAP_IMPL_QUARTZ (src_impl)->image);
+ CGContextDrawImage (context,
+ CGRectMake (0, 0, pixmap_impl->width, pixmap_impl->height),
+ pixmap_impl->image);
gdk_quartz_drawable_release_context (drawable, context);
}
else
g_warning ("Attempt to draw a drawable with depth %d to a drawable with depth %d",
- src_depth, dest_depth);
+ src_depth, dest_depth);
}
static void
return GDK_DRAWABLE_IMPL_QUARTZ_GET_CLASS (drawable)->get_context (drawable, antialias);
}
+/* Help preventing "beam sync penalty" where CG makes all graphics code
+ * block until the next vsync if we try to flush (including call display on
+ * a view) too often. We do this by limiting the manual flushing done
+ * outside of expose calls to less than some frequency when measured over
+ * the last 4 flushes. This is a bit arbitray, but seems to make it possible
+ * for some quick manual flushes (such as gtkruler or gimp's marching ants)
+ * without hitting the max flush frequency.
+ *
+ * If drawable NULL, no flushing is done, only registering that a flush was
+ * done externally.
+ */
+void
+_gdk_quartz_drawable_flush (GdkDrawable *drawable)
+{
+ static struct timeval prev_tv;
+ static gint intervals[4];
+ static gint index;
+ struct timeval tv;
+ gint ms;
+
+ gettimeofday (&tv, NULL);
+ ms = (tv.tv_sec - prev_tv.tv_sec) * 1000 + (tv.tv_usec - prev_tv.tv_usec) / 1000;
+ intervals[index++ % 4] = ms;
+
+ if (drawable)
+ {
+ ms = intervals[0] + intervals[1] + intervals[2] + intervals[3];
+
+ /* ~25Hz on average. */
+ if (ms > 4*40)
+ {
+ if (GDK_IS_WINDOW_IMPL_QUARTZ (drawable))
+ {
+ GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (drawable);
+
+ [window_impl->toplevel flushWindow];
+ }
+
+ prev_tv = tv;
+ }
+ }
+ else
+ prev_tv = tv;
+}
+
void
gdk_quartz_drawable_release_context (GdkDrawable *drawable,
CGContextRef cg_context)
/* See comment in gdk_quartz_drawable_get_context(). */
if (window_impl->in_paint_rect_count == 0)
- [window_impl->view unlockFocus];
+ {
+ _gdk_quartz_drawable_flush (drawable);
+ [window_impl->view unlockFocus];
+ }
}
else if (GDK_IS_PIXMAP_IMPL_QUARTZ (drawable))
CGContextRelease (cg_context);
#include "gdkkeysyms.h"
#include "gdkprivate-quartz.h"
-/* This is the window the mouse is currently over */
-static GdkWindow *current_mouse_window;
-
/* This is the window corresponding to the key window */
static GdkWindow *current_keyboard_window;
-/* This is the pointer grab window */
-GdkWindow *_gdk_quartz_pointer_grab_window;
-static gboolean pointer_grab_owner_events;
-static GdkEventMask pointer_grab_event_mask;
-static gboolean pointer_grab_implicit;
-
-/* This is the keyboard grab window */
-GdkWindow * _gdk_quartz_keyboard_grab_window;
-static gboolean keyboard_grab_owner_events;
-
/* This is the event mask and button state from the last event */
static GdkEventMask current_event_mask;
static int current_button_state;
-static void get_child_coordinates_from_ancestor (GdkWindow *ancestor_window,
- gint ancestor_x,
- gint ancestor_y,
- GdkWindow *child_window,
- gint *child_x,
- gint *child_y);
-static void get_ancestor_coordinates_from_child (GdkWindow *child_window,
- gint child_x,
- gint child_y,
- GdkWindow *ancestor_window,
- gint *ancestor_x,
- gint *ancestor_y);
-static void get_converted_window_coordinates (GdkWindow *in_window,
- gint in_x,
- gint in_y,
- GdkWindow *out_window,
- gint *out_x,
- gint *out_y);
static void append_event (GdkEvent *event);
-static const gchar *
-which_window_is_this (GdkWindow *window)
-{
- static gchar buf[256];
- const gchar *name = NULL;
- gpointer widget;
-
- /* Get rid of compiler warning. */
- if (0) which_window_is_this (window);
-
- if (window == _gdk_root)
- name = "root";
- else if (window == NULL)
- name = "null";
-
- if (window)
- {
- gdk_window_get_user_data (window, &widget);
- if (widget)
- name = G_OBJECT_TYPE_NAME (widget);
- }
-
- if (!name)
- name = "unknown";
-
- snprintf (buf, 256, "<%s (%p)%s>",
- name, window,
- window == current_mouse_window ? ", is mouse" : "");
-
- return buf;
-}
-
NSEvent *
gdk_quartz_event_get_nsevent (GdkEvent *event)
{
return ((GdkEventPrivate *) event)->windowing_data;
}
-void
+void
_gdk_events_init (void)
{
_gdk_quartz_event_loop_init ();
- current_mouse_window = g_object_ref (_gdk_root);
current_keyboard_window = g_object_ref (_gdk_root);
}
return NULL;
}
-static void
-generate_grab_broken_event (GdkWindow *window,
- gboolean keyboard,
- gboolean implicit,
- GdkWindow *grab_window)
-{
- if (!GDK_WINDOW_DESTROYED (window))
- {
- GdkEvent *event = gdk_event_new (GDK_GRAB_BROKEN);
-
- event->grab_broken.window = window;
- event->grab_broken.send_event = 0;
- event->grab_broken.keyboard = keyboard;
- event->grab_broken.implicit = implicit;
- event->grab_broken.grab_window = grab_window;
-
- append_event (event);
- }
-}
-
GdkGrabStatus
gdk_keyboard_grab (GdkWindow *window,
gint owner_events,
guint32 time)
{
+ GdkDisplay *display;
+ GdkWindow *toplevel;
+
g_return_val_if_fail (window != NULL, 0);
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
- if (_gdk_quartz_keyboard_grab_window)
- {
- if (_gdk_quartz_keyboard_grab_window != window)
- generate_grab_broken_event (_gdk_quartz_keyboard_grab_window,
- TRUE, FALSE, window);
-
- g_object_unref (_gdk_quartz_keyboard_grab_window);
- }
+ display = gdk_drawable_get_display (window);
+ toplevel = gdk_window_get_toplevel (window);
- _gdk_quartz_keyboard_grab_window = g_object_ref (window);
- keyboard_grab_owner_events = owner_events;
+ _gdk_display_set_has_keyboard_grab (display,
+ window,
+ toplevel,
+ owner_events,
+ 0,
+ time);
return GDK_GRAB_SUCCESS;
}
gdk_display_keyboard_ungrab (GdkDisplay *display,
guint32 time)
{
- if (_gdk_quartz_keyboard_grab_window)
- g_object_unref (_gdk_quartz_keyboard_grab_window);
- _gdk_quartz_keyboard_grab_window = NULL;
-}
-
-gboolean
-gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
- GdkWindow **grab_window,
- gboolean *owner_events)
-{
- if (_gdk_quartz_keyboard_grab_window)
- {
- if (grab_window)
- *grab_window = _gdk_quartz_keyboard_grab_window;
- if (owner_events)
- *owner_events = keyboard_grab_owner_events;
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-pointer_ungrab_internal (gboolean only_if_implicit)
-{
- if (!_gdk_quartz_pointer_grab_window)
- return;
-
- if (only_if_implicit && !pointer_grab_implicit)
- return;
-
- g_object_unref (_gdk_quartz_pointer_grab_window);
- _gdk_quartz_pointer_grab_window = NULL;
-
- pointer_grab_owner_events = FALSE;
- pointer_grab_event_mask = 0;
- pointer_grab_implicit = FALSE;
-
- /* FIXME: Send crossing events */
-}
-
-gboolean
-gdk_display_pointer_is_grabbed (GdkDisplay *display)
-{
- return (_gdk_quartz_pointer_grab_window != NULL &&
- !pointer_grab_implicit);
-}
-
-gboolean
-gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
- GdkWindow **grab_window,
- gboolean *owner_events)
-{
- if (!_gdk_quartz_pointer_grab_window)
- return FALSE;
-
- if (grab_window)
- *grab_window = _gdk_quartz_pointer_grab_window;
-
- if (owner_events)
- *owner_events = pointer_grab_owner_events;
-
- return TRUE;
+ _gdk_display_unset_has_keyboard_grab (display, FALSE);
}
void
gdk_display_pointer_ungrab (GdkDisplay *display,
guint32 time)
{
- pointer_ungrab_internal (FALSE);
-}
+ GdkPointerGrabInfo *grab;
-static GdkGrabStatus
-pointer_grab_internal (GdkWindow *window,
- gboolean owner_events,
- GdkEventMask event_mask,
- GdkWindow *confine_to,
- GdkCursor *cursor,
- gboolean implicit)
-{
- /* FIXME: Send crossing events */
-
- _gdk_quartz_pointer_grab_window = g_object_ref (window);
- pointer_grab_owner_events = owner_events;
- pointer_grab_event_mask = event_mask;
- pointer_grab_implicit = implicit;
+ grab = _gdk_display_get_last_pointer_grab (display);
+ if (grab)
+ grab->serial_end = 0;
- return GDK_GRAB_SUCCESS;
+ _gdk_display_pointer_grab_update (display, 0);
}
GdkGrabStatus
GdkCursor *cursor,
guint32 time)
{
+ GdkWindow *native;
+
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
- if (_gdk_quartz_pointer_grab_window)
- {
- if (_gdk_quartz_pointer_grab_window != window)
- generate_grab_broken_event (_gdk_quartz_pointer_grab_window,
- FALSE, pointer_grab_implicit, window);
+ native = gdk_window_get_toplevel (window);
- pointer_ungrab_internal (FALSE);
- }
+ /* TODO: What do we do for offscreens and their children? We need to proxy the grab somehow */
+ if (!GDK_IS_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (native)->impl))
+ return GDK_GRAB_SUCCESS;
- return pointer_grab_internal (window, owner_events, event_mask,
- confine_to, cursor, FALSE);
+ if (!_gdk_window_has_impl (window) &&
+ !gdk_window_is_viewable (window))
+ return GDK_GRAB_NOT_VIEWABLE;
+
+ _gdk_display_add_pointer_grab (_gdk_display,
+ window,
+ native,
+ owner_events,
+ event_mask,
+ 0,
+ time,
+ FALSE);
+
+ return GDK_GRAB_SUCCESS;
}
-/* This is used to break any grabs in the case where we have to due to
- * the grab emulation. Instead of enforcing the desktop wide grab, we
- * break it when the app loses focus for example.
- */
static void
-break_all_grabs (void)
+break_all_grabs (guint32 time)
{
- if (_gdk_quartz_keyboard_grab_window)
- {
- generate_grab_broken_event (_gdk_quartz_keyboard_grab_window,
- TRUE, FALSE,
- NULL);
- g_object_unref (_gdk_quartz_keyboard_grab_window);
- _gdk_quartz_keyboard_grab_window = NULL;
- }
+ GdkPointerGrabInfo *grab;
+
+ if (_gdk_display->keyboard_grab.window)
+ _gdk_display_unset_has_keyboard_grab (_gdk_display, FALSE);
- if (_gdk_quartz_pointer_grab_window)
+ grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+ if (grab)
{
- generate_grab_broken_event (_gdk_quartz_pointer_grab_window,
- FALSE, pointer_grab_implicit,
- NULL);
- pointer_ungrab_internal (FALSE);
+ grab->serial_end = 0;
+ grab->implicit_ungrab = TRUE;
}
+
+ _gdk_display_pointer_grab_update (_gdk_display, 0);
}
static void
_gdk_event_queue_append (_gdk_display, event);
}
-static GdkFilterReturn
-apply_filters (GdkWindow *window,
- NSEvent *nsevent,
- GList *filters)
+static gint
+gdk_event_apply_filters (NSEvent *nsevent,
+ GdkEvent *event,
+ GList *filters)
{
- GdkFilterReturn result = GDK_FILTER_CONTINUE;
- GdkEvent *event;
- GList *node;
GList *tmp_list;
-
- event = gdk_event_new (GDK_NOTHING);
- if (window != NULL)
- event->any.window = g_object_ref (window);
- ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
-
- /* I think GdkFilterFunc semantics require the passed-in event
- * to already be in the queue. The filter func can generate
- * more events and append them after it if it likes.
- */
- node = _gdk_event_queue_append (_gdk_display, event);
+ GdkFilterReturn result;
tmp_list = filters;
+
while (tmp_list)
{
- GdkEventFilter *filter = (GdkEventFilter *) tmp_list->data;
+ GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data;
tmp_list = tmp_list->next;
result = filter->function (nsevent, event, filter->data);
- if (result != GDK_FILTER_CONTINUE)
- break;
- }
-
- if (result == GDK_FILTER_CONTINUE || result == GDK_FILTER_REMOVE)
- {
- _gdk_event_queue_remove_link (_gdk_display, node);
- g_list_free_1 (node);
- gdk_event_free (event);
- }
- else /* GDK_FILTER_TRANSLATE */
- {
- ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
- fixup_event (event);
- }
- return result;
-}
-
-/* Checks if the passed in window is interested in the event mask, and
- * if so, it's returned. If not, the event can be propagated through
- * its ancestors until one with the right event mask is found, up to
- * the nearest toplevel.
- */
-static GdkWindow *
-find_window_interested_in_event_mask (GdkWindow *window,
- GdkEventMask event_mask,
- gboolean propagate)
-{
- GdkWindowObject *private;
-
- private = GDK_WINDOW_OBJECT (window);
- while (private)
- {
- if (private->event_mask & event_mask)
- return (GdkWindow *)private;
-
- if (!propagate)
- return NULL;
-
- /* Don't traverse beyond toplevels. */
- if (GDK_WINDOW_TYPE (private) != GDK_WINDOW_CHILD)
- break;
-
- private = private->parent;
+ if (result != GDK_FILTER_CONTINUE)
+ return result;
}
- return NULL;
+ return GDK_FILTER_CONTINUE;
}
static guint32
g_assert_not_reached ();
}
}
+ break;
+
+ case NSMouseEntered:
+ return GDK_ENTER_NOTIFY_MASK;
+
+ case NSMouseExited:
+ return GDK_LEAVE_NOTIFY_MASK;
+
default:
g_assert_not_reached ();
}
if (got_focus)
{
if (current_keyboard_window)
- {
- event = create_focus_event (current_keyboard_window, FALSE);
- append_event (event);
- g_object_unref (current_keyboard_window);
- current_keyboard_window = NULL;
- }
-
- event = create_focus_event (window, TRUE);
- append_event (event);
- current_keyboard_window = g_object_ref (window);
- }
-}
-
-static void
-convert_window_coordinates_to_root (GdkWindow *window,
- gdouble x,
- gdouble y,
- gdouble *x_root,
- gdouble *y_root)
-{
- gint ox, oy;
-
- *x_root = x;
- *y_root = y;
-
- if (gdk_window_get_origin (window, &ox, &oy))
- {
- *x_root += ox;
- *y_root += oy;
- }
-}
-
-/* FIXME: Refactor and share with scroll event. */
-static GdkEvent *
-create_crossing_event (GdkWindow *window,
- NSEvent *nsevent,
- GdkEventType event_type,
- GdkCrossingMode mode,
- GdkNotifyType detail)
-{
- GdkEvent *event;
- gint x_tmp, y_tmp;
-
- event = gdk_event_new (event_type);
-
- event->crossing.window = window;
- event->crossing.subwindow = NULL; /* FIXME */
- event->crossing.time = get_time_from_ns_event (nsevent);
-
- /* Split out this block: */
- {
- NSWindow *nswindow;
- GdkWindow *toplevel;
- GdkWindowImplQuartz *impl;
- NSPoint point;
-
- nswindow = [nsevent window];
- point = [nsevent locationInWindow];
-
- toplevel = [(GdkQuartzView *)[nswindow contentView] gdkWindow];
-
- impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl);
-
- x_tmp = point.x;
- y_tmp = impl->height - point.y;
-
- get_converted_window_coordinates (toplevel,
- x_tmp, y_tmp,
- window,
- &x_tmp, &y_tmp);
- }
-
- event->crossing.x = x_tmp;
- event->crossing.y = y_tmp;
-
- convert_window_coordinates_to_root (window,
- event->crossing.x,
- event->crossing.y,
- &event->crossing.x_root,
- &event->crossing.y_root);
-
- event->crossing.mode = mode;
- event->crossing.detail = detail;
- event->crossing.state = get_keyboard_modifiers_from_ns_event (nsevent);
-
- /* FIXME: focus and button state */
-
- return event;
-}
-
-static void
-synthesize_enter_event (GdkWindow *window,
- NSEvent *nsevent,
- GdkCrossingMode mode,
- GdkNotifyType detail)
-{
- GdkEvent *event;
-
- if (_gdk_quartz_pointer_grab_window != NULL &&
- !pointer_grab_owner_events &&
- !(pointer_grab_event_mask & GDK_ENTER_NOTIFY_MASK))
- return;
-
- if (!(GDK_WINDOW_OBJECT (window)->event_mask & GDK_ENTER_NOTIFY_MASK))
- return;
-
- event = create_crossing_event (window, nsevent, GDK_ENTER_NOTIFY,
- mode, detail);
-
- append_event (event);
-}
-
-static void
-synthesize_enter_events (GdkWindow *from,
- GdkWindow *to,
- NSEvent *nsevent,
- GdkCrossingMode mode,
- GdkNotifyType detail)
-{
- GdkWindow *prev = gdk_window_get_parent (to);
-
- if (prev != from)
- synthesize_enter_events (from, prev, nsevent, mode, detail);
- synthesize_enter_event (to, nsevent, mode, detail);
-}
-
-static void
-synthesize_leave_event (GdkWindow *window,
- NSEvent *nsevent,
- GdkCrossingMode mode,
- GdkNotifyType detail)
-{
- GdkEvent *event;
-
- if (_gdk_quartz_pointer_grab_window != NULL &&
- !pointer_grab_owner_events &&
- !(pointer_grab_event_mask & GDK_LEAVE_NOTIFY_MASK))
- return;
-
- if (!(GDK_WINDOW_OBJECT (window)->event_mask & GDK_LEAVE_NOTIFY_MASK))
- return;
-
- event = create_crossing_event (window, nsevent, GDK_LEAVE_NOTIFY,
- mode, detail);
-
- append_event (event);
-}
-
-static void
-synthesize_leave_events (GdkWindow *from,
- GdkWindow *to,
- NSEvent *nsevent,
- GdkCrossingMode mode,
- GdkNotifyType detail)
-{
- GdkWindow *next = gdk_window_get_parent (from);
-
- synthesize_leave_event (from, nsevent, mode, detail);
- if (next != to)
- synthesize_leave_events (next, to, nsevent, mode, detail);
-}
-
-static void
-synthesize_crossing_events (GdkWindow *window,
- GdkCrossingMode mode,
- NSEvent *nsevent,
- gint x,
- gint y)
-{
- GdkWindow *intermediate, *tem, *common_ancestor;
-
- if (window == current_mouse_window)
- return;
-
- if (_gdk_quartz_window_is_ancestor (current_mouse_window, window))
- {
- /* Pointer has moved to an inferior window. */
- synthesize_leave_event (current_mouse_window, nsevent, mode, GDK_NOTIFY_INFERIOR);
-
- /* If there are intermediate windows, generate ENTER_NOTIFY
- * events for them
- */
- intermediate = gdk_window_get_parent (window);
-
- if (intermediate != current_mouse_window)
- {
- synthesize_enter_events (current_mouse_window, intermediate, nsevent, mode, GDK_NOTIFY_VIRTUAL);
- }
-
- synthesize_enter_event (window, nsevent, mode, GDK_NOTIFY_ANCESTOR);
- }
- else if (_gdk_quartz_window_is_ancestor (window, current_mouse_window))
- {
- /* Pointer has moved to an ancestor window. */
- synthesize_leave_event (current_mouse_window, nsevent, mode, GDK_NOTIFY_ANCESTOR);
-
- /* If there are intermediate windows, generate LEAVE_NOTIFY
- * events for them
- */
- intermediate = gdk_window_get_parent (current_mouse_window);
- if (intermediate != window)
- {
- synthesize_leave_events (intermediate, window, nsevent, mode, GDK_NOTIFY_VIRTUAL);
- }
-
- synthesize_enter_event (window, nsevent, mode, GDK_NOTIFY_INFERIOR);
- }
- else if (current_mouse_window)
- {
- /* Find least common ancestor of current_mouse_window and window */
- tem = current_mouse_window;
- do {
- common_ancestor = gdk_window_get_parent (tem);
- tem = common_ancestor;
- } while (common_ancestor &&
- !_gdk_quartz_window_is_ancestor (common_ancestor, window));
- if (common_ancestor)
- {
- synthesize_leave_event (current_mouse_window, nsevent, mode, GDK_NOTIFY_NONLINEAR);
- intermediate = gdk_window_get_parent (current_mouse_window);
- if (intermediate != common_ancestor)
- {
- synthesize_leave_events (intermediate, common_ancestor,
- nsevent, mode, GDK_NOTIFY_NONLINEAR_VIRTUAL);
- }
- intermediate = gdk_window_get_parent (window);
- if (intermediate != common_ancestor)
- {
- synthesize_enter_events (common_ancestor, intermediate,
- nsevent, mode, GDK_NOTIFY_NONLINEAR_VIRTUAL);
- }
- synthesize_enter_event (window, nsevent, mode, GDK_NOTIFY_NONLINEAR);
- }
- }
- else
- {
- /* This means we have no current_mouse_window, which probably
- * means that there is a bug somewhere, we should always have
- * the root in we don't have another window. Does this ever
- * happen?
- */
- g_warning ("Trying to create crossing event when current_mouse_window is NULL");
- }
-
- _gdk_quartz_events_update_mouse_window (window);
-
- /* FIXME: This does't work when someone calls gdk_window_set_cursor
- * during a grab. The right behavior is that the cursor doesn't
- * change when a grab is in effect, but in that case it does.
- */
- if (window && !_gdk_quartz_pointer_grab_window)
- _gdk_quartz_events_update_cursor (window);
-}
-
-void
-_gdk_quartz_events_send_map_events (GdkWindow *window)
-{
- GList *list;
- GdkWindow *interested_window;
- GdkWindowObject *private = (GdkWindowObject *)window;
-
- interested_window = find_window_interested_in_event_mask (window,
- GDK_STRUCTURE_MASK,
- TRUE);
-
- if (interested_window)
- {
- GdkEvent *event = gdk_event_new (GDK_MAP);
- event->any.window = interested_window;
- append_event (event);
- }
-
- for (list = private->children; list != NULL; list = list->next)
- _gdk_quartz_events_send_map_events ((GdkWindow *)list->data);
-}
-
-/* Get current mouse window */
-GdkWindow *
-_gdk_quartz_events_get_mouse_window (gboolean consider_grabs)
-{
- if (!consider_grabs)
- return current_mouse_window;
-
- if (_gdk_quartz_pointer_grab_window && !pointer_grab_owner_events)
- return _gdk_quartz_pointer_grab_window;
-
- return current_mouse_window;
-}
-
-/* Update mouse window */
-void
-_gdk_quartz_events_update_mouse_window (GdkWindow *window)
-{
- if (window == current_mouse_window)
- return;
-
-#ifdef G_ENABLE_DEBUG
- if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
- _gdk_quartz_window_debug_highlight (window, 0);
-#endif /* G_ENABLE_DEBUG */
-
- if (window)
- g_object_ref (window);
- if (current_mouse_window)
- g_object_unref (current_mouse_window);
-
- current_mouse_window = window;
-}
-
-/* Update current cursor */
-void
-_gdk_quartz_events_update_cursor (GdkWindow *window)
-{
- GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
- NSCursor *nscursor = nil;
-
- while (private)
- {
- GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
-
- nscursor = impl->nscursor;
- if (nscursor)
- break;
-
- private = private->parent;
- }
-
- GDK_QUARTZ_ALLOC_POOL;
-
- if (!nscursor)
- nscursor = [NSCursor arrowCursor];
-
- if ([NSCursor currentCursor] != nscursor)
- [nscursor set];
-
- GDK_QUARTZ_RELEASE_POOL;
-}
-
-/* Translates coordinates from an ancestor window + coords, to
- * coordinates that are relative the child window.
- */
-static void
-get_child_coordinates_from_ancestor (GdkWindow *ancestor_window,
- gint ancestor_x,
- gint ancestor_y,
- GdkWindow *child_window,
- gint *child_x,
- gint *child_y)
-{
- GdkWindowObject *ancestor_private = GDK_WINDOW_OBJECT (ancestor_window);
- GdkWindowObject *child_private = GDK_WINDOW_OBJECT (child_window);
-
- while (child_private != ancestor_private)
- {
- ancestor_x -= child_private->x;
- ancestor_y -= child_private->y;
-
- child_private = child_private->parent;
- }
-
- *child_x = ancestor_x;
- *child_y = ancestor_y;
-}
-
-/* Translates coordinates from a child window + coords, to
- * coordinates that are relative the ancestor window.
- */
-static void
-get_ancestor_coordinates_from_child (GdkWindow *child_window,
- gint child_x,
- gint child_y,
- GdkWindow *ancestor_window,
- gint *ancestor_x,
- gint *ancestor_y)
-{
- GdkWindowObject *child_private = GDK_WINDOW_OBJECT (child_window);
- GdkWindowObject *ancestor_private = GDK_WINDOW_OBJECT (ancestor_window);
-
- while (child_private != ancestor_private)
- {
- child_x += child_private->x;
- child_y += child_private->y;
-
- child_private = child_private->parent;
- }
-
- *ancestor_x = child_x;
- *ancestor_y = child_y;
-}
-
-/* Translates coordinates relative to one window (in_window) into
- * coordinates relative to another window (out_window).
- */
-static void
-get_converted_window_coordinates (GdkWindow *in_window,
- gint in_x,
- gint in_y,
- GdkWindow *out_window,
- gint *out_x,
- gint *out_y)
-{
- GdkWindow *in_toplevel;
- GdkWindow *out_toplevel;
- int in_origin_x, in_origin_y;
- int out_origin_x, out_origin_y;
-
- if (in_window == out_window)
- {
- *out_x = in_x;
- *out_y = in_y;
- return;
- }
-
- /* First translate to "in" toplevel coordinates, then on to "out"
- * toplevel coordinates, and finally to "out" child (the passed in
- * window) coordinates.
- */
-
- in_toplevel = gdk_window_get_toplevel (in_window);
- out_toplevel = gdk_window_get_toplevel (out_window);
-
- /* Translate in_x, in_y to "in" toplevel coordinates. */
- get_ancestor_coordinates_from_child (in_window, in_x, in_y,
- in_toplevel, &in_x, &in_y);
-
- gdk_window_get_origin (in_toplevel, &in_origin_x, &in_origin_y);
- gdk_window_get_origin (out_toplevel, &out_origin_x, &out_origin_y);
-
- /* Translate in_x, in_y to "out" toplevel coordinates. */
- in_x -= out_origin_x - in_origin_x;
- in_y -= out_origin_y - in_origin_y;
-
- get_child_coordinates_from_ancestor (out_toplevel,
- in_x, in_y,
- out_window,
- out_x, out_y);
-}
-
-/* Given a mouse NSEvent (must be a mouse event for a GDK window),
- * finds the subwindow over which the pointer is located. Returns
- * coordinates relative to the found window. If no window is found,
- * returns the root window, and root window coordinates.
- */
-static GdkWindow *
-find_mouse_window_for_ns_event (NSEvent *nsevent,
- gint *x_ret,
- gint *y_ret)
-{
- GdkWindow *event_toplevel;
- GdkWindowImplQuartz *impl;
- GdkWindow *mouse_toplevel;
- GdkWindow *mouse_window;
- NSPoint point;
- gint x_tmp, y_tmp;
-
- event_toplevel = [(GdkQuartzView *)[[nsevent window] contentView] gdkWindow];
- impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (event_toplevel)->impl);
- point = [nsevent locationInWindow];
-
- x_tmp = point.x;
- y_tmp = impl->height - point.y;
-
- mouse_toplevel = gdk_window_get_toplevel (current_mouse_window);
-
- get_converted_window_coordinates (event_toplevel,
- x_tmp, y_tmp,
- mouse_toplevel,
- &x_tmp, &y_tmp);
-
- mouse_window = _gdk_quartz_window_find_child (mouse_toplevel, x_tmp, y_tmp);
- if (mouse_window && mouse_window != mouse_toplevel)
- {
- get_child_coordinates_from_ancestor (mouse_toplevel,
- x_tmp, y_tmp,
- mouse_window,
- &x_tmp, &y_tmp);
- }
- else if (!mouse_window)
- {
- /* This happens for events on the window title buttons and the
- * desktop, treat those as being on the root window.
- */
- get_converted_window_coordinates (mouse_toplevel,
- x_tmp, y_tmp,
- _gdk_root,
- &x_tmp, &y_tmp);
- mouse_window = _gdk_root;
+ {
+ event = create_focus_event (current_keyboard_window, FALSE);
+ append_event (event);
+ g_object_unref (current_keyboard_window);
+ current_keyboard_window = NULL;
+ }
+
+ event = create_focus_event (window, TRUE);
+ append_event (event);
+ current_keyboard_window = g_object_ref (window);
}
-
- *x_ret = x_tmp;
- *y_ret = y_tmp;
-
- return mouse_window;
}
-/* Trigger crossing events if necessary. This is used when showing a new
- * window, since the tracking rect API doesn't work reliably when a window
- * shows up under the mouse cursor. It's done by finding the topmost window
- * under the mouse pointer and synthesizing crossing events into that
- * window.
- */
void
-_gdk_quartz_events_trigger_crossing_events (gboolean defer_to_mainloop)
+_gdk_quartz_events_send_map_event (GdkWindow *window)
{
- NSPoint point;
- gint x, y;
- gint x_toplevel, y_toplevel;
- GdkWindow *mouse_window;
- GdkWindow *toplevel;
- GdkWindowImplQuartz *impl;
- guint flags = 0;
- NSTimeInterval timestamp = 0;
- NSEvent *current_event;
- NSEvent *nsevent;
-
- if (defer_to_mainloop)
- {
- nsevent = [NSEvent otherEventWithType:NSApplicationDefined
- location:NSZeroPoint
- modifierFlags:0
- timestamp:0
- windowNumber:0
- context:nil
- subtype:GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING
- data1:0
- data2:0];
- [NSApp postEvent:nsevent atStart:NO];
- return;
- }
-
- point = [NSEvent mouseLocation];
- x = point.x;
- y = _gdk_quartz_window_get_inverted_screen_y (point.y);
-
- mouse_window = _gdk_quartz_window_find_child (_gdk_root, x, y);
- if (!mouse_window || mouse_window == _gdk_root)
- return;
-
- toplevel = gdk_window_get_toplevel (mouse_window);
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
- /* We ignore crossing within the same toplevel since that is already
- * handled elsewhere.
- */
- if (toplevel == gdk_window_get_toplevel (current_mouse_window))
+ if (!impl->toplevel)
return;
- get_converted_window_coordinates (_gdk_root,
- x, y,
- toplevel,
- &x_toplevel, &y_toplevel);
-
- get_converted_window_coordinates (_gdk_root,
- x, y,
- mouse_window,
- &x, &y);
-
- /* Fix up the event to be less fake if possible. */
- current_event = [NSApp currentEvent];
- if (current_event)
+ if (private->event_mask & GDK_STRUCTURE_MASK)
{
- flags = [current_event modifierFlags];
- timestamp = [current_event timestamp];
- }
+ GdkEvent event;
- if (timestamp == 0)
- timestamp = GetCurrentEventTime ();
-
- impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl);
- nsevent = [NSEvent otherEventWithType:NSApplicationDefined
- location:NSMakePoint (x_toplevel, impl->height - y_toplevel)
- modifierFlags:flags
- timestamp:timestamp
- windowNumber:[impl->toplevel windowNumber]
- context:nil
- subtype:GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING
- data1:0
- data2:0];
-
-#ifdef G_ENABLE_DEBUG
- /*_gdk_quartz_window_debug_highlight (mouse_window, 0);*/
-#endif
-
- synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, x, y);
+ event.any.type = GDK_MAP;
+ event.any.window = window;
+
+ gdk_event_put (&event);
+ }
}
-/* Synthesizes crossing events if necessary, based on the passed in
- * NSEvent. Uses NSMouseEntered and NSMouseExisted for toplevels and
- * the mouse moved/dragged events for child windows, to see if the
- * mouse window has changed.
- */
-static void
-synthesize_crossing_events_for_ns_event (NSEvent *nsevent)
+static GdkWindow *
+find_toplevel_under_pointer (GdkDisplay *display,
+ NSPoint screen_point,
+ gint *x,
+ gint *y)
{
- NSEventType event_type;
- GdkWindow *mouse_window;
- gint x;
- gint y;
-
- event_type = [nsevent type];
+ GdkWindow *toplevel;
- switch (event_type)
+ toplevel = display->pointer_info.toplevel_under_pointer;
+ if (toplevel)
{
- case NSMouseMoved:
- case NSLeftMouseDragged:
- case NSRightMouseDragged:
- case NSOtherMouseDragged:
- /* We only handle moving the pointer to another GDK window.
- * Leaving to a non-GDK toplevel window (or window title bar or
- * the desktop) is covered by NSMouseExited events.
- */
- mouse_window = find_mouse_window_for_ns_event (nsevent, &x, &y);
- if (mouse_window != _gdk_root)
- synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, x, y);
-
- break;
-
- case NSMouseEntered:
- {
- GdkWindow *event_toplevel;
- GdkWindowImplQuartz *impl;
- NSPoint point;
+ GdkWindowObject *private;
+ NSWindow *nswindow;
+ NSPoint point;
- /* This is the only case where we actually use the window from
- * the event since we need to know which toplevel we entered
- * so it can be tracked properly.
- */
- event_toplevel = [(GdkQuartzView *)[[nsevent window] contentView] gdkWindow];
- impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (event_toplevel)->impl);
+ private = (GdkWindowObject *)toplevel;
+ nswindow = ((GdkWindowImplQuartz *)private->impl)->toplevel;
- point = [nsevent locationInWindow];
+ point = [nswindow convertScreenToBase:screen_point];
- x = point.x;
- y = impl->height - point.y;
-
- mouse_window = _gdk_quartz_window_find_child (event_toplevel, x, y);
-
- /* Treat unknown windows (like the title bar buttons or
- * desktop) as the root window.
- */
- if (!mouse_window)
- mouse_window = _gdk_root;
-
- if (mouse_window != event_toplevel)
- get_converted_window_coordinates (event_toplevel,
- x, y,
- mouse_window,
- &x, &y);
-
- synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, x, y);
- }
- break;
-
- case NSMouseExited:
- {
- GdkWindow *event_toplevel;
- GdkWindowImplQuartz *impl;
- NSPoint point;
-
- /* We only use NSMouseExited when leaving to the root
- * window. The other cases are handled above by checking the
- * motion/button events, or getting a NSMouseEntered for
- * another GDK window. The reason we don't use NSMouseExited
- * for other windows is that quartz first delivers the entered
- * event and then the exited which is the opposite from what
- * we need.
- */
- event_toplevel = [(GdkQuartzView *)[[nsevent window] contentView] gdkWindow];
- impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (event_toplevel)->impl);
- point = [nsevent locationInWindow];
-
- x = point.x;
- y = impl->height - point.y;
-
- x += GDK_WINDOW_OBJECT (event_toplevel)->x;
- y += GDK_WINDOW_OBJECT (event_toplevel)->y;
-
- /* If there is a window other than the root window at this
- * position, it means we didn't exit to the root window and we
- * ignore the event. (Note that we can get NULL here when swithing
- * spaces for example.)
- *
- * FIXME: This is not enough, it doesn't catch the case where
- * we leave a GDK window to a non-GDK window that has GDK
- * windows below it.
- */
- mouse_window = _gdk_quartz_window_find_child (_gdk_root, x, y);
-
- if (!mouse_window ||
- gdk_window_get_toplevel (mouse_window) ==
- gdk_window_get_toplevel (current_mouse_window))
- {
- mouse_window = _gdk_root;
- }
-
- if (mouse_window == _gdk_root)
- synthesize_crossing_events (_gdk_root, GDK_CROSSING_NORMAL, nsevent, x, y);
- }
- break;
-
- default:
- break;
+ *x = point.x;
+ *y = private->height - point.y;
}
+
+ return toplevel;
}
/* This function finds the correct window to send an event to, taking
static GdkWindow *
find_window_for_ns_event (NSEvent *nsevent,
gint *x,
- gint *y)
+ gint *y,
+ gint *x_root,
+ gint *y_root)
{
+ GdkQuartzView *view;
+ GdkWindow *toplevel;
+ GdkWindowObject *private;
+ NSPoint point;
+ NSPoint screen_point;
NSEventType event_type;
+ view = (GdkQuartzView *)[[nsevent window] contentView];
+
+ toplevel = [view gdkWindow];
+ private = GDK_WINDOW_OBJECT (toplevel);
+
+ point = [nsevent locationInWindow];
+ screen_point = [[nsevent window] convertBaseToScreen:point];
+
+ *x = point.x;
+ *y = private->height - point.y;
+
+ *x_root = screen_point.x;
+ *y_root = _gdk_quartz_window_get_inverted_screen_y (screen_point.y);
+
event_type = [nsevent type];
switch (event_type)
case NSRightMouseDragged:
case NSOtherMouseDragged:
{
- GdkWindow *mouse_window;
- GdkEventMask event_mask;
- GdkWindow *real_window;
+ GdkDisplay *display;
+ GdkPointerGrabInfo *grab;
+
+ display = gdk_drawable_get_display (toplevel);
/* From the docs for XGrabPointer:
*
* the grab_window and is reported only if selected by
* event_mask. For either value of owner_events, unreported
* events are discarded.
- *
- * This means we first try the owner, then the grab window,
- * then give up.
*/
- if (_gdk_quartz_pointer_grab_window)
+ grab = _gdk_display_get_last_pointer_grab (display);
+ if (grab)
{
- if (pointer_grab_owner_events)
- {
- mouse_window = find_mouse_window_for_ns_event (nsevent, x, y);
- event_mask = get_event_mask_from_ns_event (nsevent);
- real_window = find_window_interested_in_event_mask (mouse_window, event_mask, TRUE);
-
- if (mouse_window && real_window && mouse_window != real_window)
- get_ancestor_coordinates_from_child (mouse_window,
- *x, *y,
- real_window,
- x, y);
-
- if (real_window)
- return real_window;
- }
-
- /* Finally check the grab window. */
- if (pointer_grab_event_mask & get_event_mask_from_ns_event (nsevent))
- {
- GdkWindow *event_toplevel;
+ if ((grab->event_mask & get_event_mask_from_ns_event (nsevent)) == 0)
+ return NULL;
+
+ if (grab->owner_events)
+ {
+ /* For owner events, we need to use the toplevel under the
+ * pointer, not the window from the NSEvent, since that is
+ * reported with respect to the key window, which could be
+ * wrong.
+ */
+ GdkWindow *toplevel_under_pointer;
+ gint x_tmp, y_tmp;
+
+ toplevel_under_pointer = find_toplevel_under_pointer (display,
+ screen_point,
+ &x_tmp, &y_tmp);
+ if (toplevel_under_pointer)
+ {
+ toplevel = toplevel_under_pointer;
+ *x = x_tmp;
+ *y = y_tmp;
+ }
+
+ return toplevel;
+ }
+ else
+ {
+ /* Finally check the grab window. */
GdkWindow *grab_toplevel;
- NSPoint point;
- int x_tmp, y_tmp;
+ GdkWindowObject *grab_private;
+ NSWindow *grab_nswindow;
- event_toplevel = [(GdkQuartzView *)[[nsevent window] contentView] gdkWindow];
- grab_toplevel = gdk_window_get_toplevel (_gdk_quartz_pointer_grab_window);
- point = [nsevent locationInWindow];
+ grab_toplevel = gdk_window_get_toplevel (grab->window);
+ grab_private = (GdkWindowObject *)grab_toplevel;
- x_tmp = point.x;
- y_tmp = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (grab_toplevel)->impl)->height - point.y;
+ grab_nswindow = ((GdkWindowImplQuartz *)grab_private->impl)->toplevel;
+ point = [grab_nswindow convertScreenToBase:screen_point];
- /* Translate the coordinates so they are relative to
- * the grab window instead of the event toplevel for
- * the cases where they are not the same.
- */
- get_converted_window_coordinates (event_toplevel,
- x_tmp, y_tmp,
- _gdk_quartz_pointer_grab_window,
- x, y);
+ /* Note: x_root and y_root are already right. */
+ *x = point.x;
+ *y = grab_private->height - point.y;
- return _gdk_quartz_pointer_grab_window;
+ return grab_toplevel;
}
return NULL;
else
{
/* The non-grabbed case. */
- mouse_window = find_mouse_window_for_ns_event (nsevent, x, y);
- event_mask = get_event_mask_from_ns_event (nsevent);
- real_window = find_window_interested_in_event_mask (mouse_window, event_mask, TRUE);
-
- /* We have to translate the coordinates if the actual
- * window is different from the mouse window.
- */
- if (mouse_window && real_window && mouse_window != real_window)
- get_ancestor_coordinates_from_child (mouse_window,
- *x, *y,
- real_window,
- x, y);
-
- return real_window;
+ GdkWindow *toplevel_under_pointer;
+ gint x_tmp, y_tmp;
+
+ /* Ignore all events but mouse moved that might be on the title
+ * bar (above the content view). The reason is that otherwise
+ * gdk gets confused about getting e.g. button presses with no
+ * window (the title bar is not known to it).
+ */
+ if (event_type != NSMouseMoved)
+ if (*y < 0)
+ return NULL;
+
+ /* FIXME: Also need to leave resize events to cocoa somehow? */
+
+ /* As for owner events, we need to use the toplevel under the
+ * pointer, not the window from the NSEvent.
+ */
+ toplevel_under_pointer = find_toplevel_under_pointer (display,
+ screen_point,
+ &x_tmp, &y_tmp);
+ if (toplevel_under_pointer)
+ {
+ toplevel = toplevel_under_pointer;
+ *x = x_tmp;
+ *y = y_tmp;
+ }
+
+ return toplevel;
}
}
break;
case NSMouseEntered:
case NSMouseExited:
- /* Already handled in synthesize_crossing_events_for_ns_event. */
- break;
+ /* Only handle our own entered/exited events, not the ones for the
+ * titlebar buttons.
+ */
+ if ([view trackingRect] == [nsevent trackingNumber])
+ return toplevel;
+ else
+ return NULL;
case NSKeyDown:
case NSKeyUp:
case NSFlagsChanged:
- {
- GdkEventMask event_mask;
+ if (_gdk_display->keyboard_grab.window && !_gdk_display->keyboard_grab.owner_events)
+ return gdk_window_get_toplevel (_gdk_display->keyboard_grab.window);
- if (_gdk_quartz_keyboard_grab_window && !keyboard_grab_owner_events)
- return _gdk_quartz_keyboard_grab_window;
-
- event_mask = get_event_mask_from_ns_event (nsevent);
- return find_window_interested_in_event_mask (current_keyboard_window, event_mask, TRUE);
- }
- break;
+ return toplevel;
default:
/* Ignore everything else. */
return NULL;
}
-static GdkEvent *
-create_button_event (GdkWindow *window,
- NSEvent *nsevent,
- gint x,
- gint y)
+static void
+fill_crossing_event (GdkWindow *toplevel,
+ GdkEvent *event,
+ NSEvent *nsevent,
+ gint x,
+ gint y,
+ gint x_root,
+ gint y_root,
+ GdkEventType event_type,
+ GdkCrossingMode mode,
+ GdkNotifyType detail)
+{
+ event->any.type = event_type;
+ event->crossing.window = toplevel;
+ event->crossing.subwindow = NULL;
+ event->crossing.time = get_time_from_ns_event (nsevent);
+ event->crossing.x = x;
+ event->crossing.y = y;
+ event->crossing.x_root = x_root;
+ event->crossing.y_root = y_root;
+ event->crossing.mode = mode;
+ event->crossing.detail = detail;
+ event->crossing.state = get_keyboard_modifiers_from_ns_event (nsevent);
+
+ /* FIXME: Focus and button state? */
+}
+
+static void
+fill_button_event (GdkWindow *window,
+ GdkEvent *event,
+ NSEvent *nsevent,
+ gint x,
+ gint y,
+ gint x_root,
+ gint y_root)
{
- GdkEvent *event;
GdkEventType type;
gint state;
gint button;
button = get_mouse_button_from_ns_event (nsevent);
- event = gdk_event_new (type);
+ event->any.type = type;
event->button.window = window;
event->button.time = get_time_from_ns_event (nsevent);
event->button.x = x;
event->button.y = y;
+ event->button.x_root = x_root;
+ event->button.y_root = y_root;
/* FIXME event->axes */
event->button.state = state;
event->button.button = button;
event->button.device = _gdk_display->core_pointer;
- convert_window_coordinates_to_root (window, x, y,
- &event->button.x_root,
- &event->button.y_root);
-
- return event;
}
-static GdkEvent *
-create_motion_event (GdkWindow *window,
- NSEvent *nsevent,
- gint x,
- gint y)
+static void
+fill_motion_event (GdkWindow *window,
+ GdkEvent *event,
+ NSEvent *nsevent,
+ gint x,
+ gint y,
+ gint x_root,
+ gint y_root)
{
- GdkEvent *event;
- GdkEventType type;
- GdkModifierType state = 0;
+ GdkModifierType state;
+
+ state = get_keyboard_modifiers_from_ns_event (nsevent);
switch ([nsevent type])
{
case NSLeftMouseDragged:
case NSRightMouseDragged:
case NSOtherMouseDragged:
- state = get_mouse_button_modifiers_from_ns_event (nsevent);
- /* Fall through */
+ state |= get_mouse_button_modifiers_from_ns_event (nsevent);
+ break;
+
case NSMouseMoved:
- type = GDK_MOTION_NOTIFY;
break;
- default:
- g_assert_not_reached ();
}
- state |= get_keyboard_modifiers_from_ns_event (nsevent);
-
- event = gdk_event_new (type);
+ event->any.type = GDK_MOTION_NOTIFY;
event->motion.window = window;
event->motion.time = get_time_from_ns_event (nsevent);
event->motion.x = x;
event->motion.y = y;
+ event->motion.x_root = x_root;
+ event->motion.y_root = y_root;
/* FIXME event->axes */
event->motion.state = state;
event->motion.is_hint = FALSE;
event->motion.device = _gdk_display->core_pointer;
- convert_window_coordinates_to_root (window, x, y,
- &event->motion.x_root, &event->motion.y_root);
-
- return event;
}
-static GdkEvent *
-create_scroll_event (GdkWindow *window,
- NSEvent *nsevent,
- GdkScrollDirection direction)
+static void
+fill_scroll_event (GdkWindow *window,
+ GdkEvent *event,
+ NSEvent *nsevent,
+ gint x,
+ gint y,
+ gint x_root,
+ gint y_root,
+ GdkScrollDirection direction)
{
- GdkEvent *event;
+ GdkWindowObject *private;
NSPoint point;
-
- event = gdk_event_new (GDK_SCROLL);
- event->scroll.window = window;
- event->scroll.time = get_time_from_ns_event (nsevent);
+
+ private = GDK_WINDOW_OBJECT (window);
point = [nsevent locationInWindow];
- event->scroll.x = point.x;
- event->scroll.y = point.y;
- event->scroll.state = get_keyboard_modifiers_from_ns_event (nsevent);
- convert_window_coordinates_to_root (window, event->scroll.x, event->scroll.y,
- &event->scroll.x_root,
- &event->scroll.y_root);
+ event->any.type = GDK_SCROLL;
+ event->scroll.window = window;
+ event->scroll.time = get_time_from_ns_event (nsevent);
+ event->scroll.x = x;
+ event->scroll.y = y;
+ event->scroll.x_root = x_root;
+ event->scroll.y_root = y_root;
+ event->scroll.state = get_keyboard_modifiers_from_ns_event (nsevent);
event->scroll.direction = direction;
event->scroll.device = _gdk_display->core_pointer;
-
- return event;
}
-static GdkEvent *
-create_key_event (GdkWindow *window,
- NSEvent *nsevent,
- GdkEventType type)
+static void
+fill_key_event (GdkWindow *window,
+ GdkEvent *event,
+ NSEvent *nsevent,
+ GdkEventType type)
{
- GdkEvent *event;
GdkEventPrivate *priv;
gchar buf[7];
gunichar c = 0;
- event = gdk_event_new (type);
-
priv = (GdkEventPrivate *) event;
priv->windowing_data = [nsevent retain];
+ event->any.type = type;
event->key.window = window;
event->key.time = get_time_from_ns_event (nsevent);
event->key.state = get_keyboard_modifiers_from_ns_event (nsevent);
event->key.hardware_keycode = [nsevent keyCode];
event->key.group = ([nsevent modifierFlags] & NSAlternateKeyMask) ? 1 : 0;
-
event->key.keyval = GDK_VoidSymbol;
gdk_keymap_translate_keyboard_state (NULL,
if (event->key.keyval != GDK_VoidSymbol)
c = gdk_keyval_to_unicode (event->key.keyval);
- if (c)
+ if (c)
{
gsize bytes_written;
gint len;
event->key.window,
event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
event->key.keyval));
- return event;
+}
+
+static gboolean
+synthesize_crossing_event (GdkWindow *window,
+ GdkEvent *event,
+ NSEvent *nsevent,
+ gint x,
+ gint y,
+ gint x_root,
+ gint y_root)
+{
+ GdkWindowObject *private;
+
+ private = GDK_WINDOW_OBJECT (window);
+
+ switch ([nsevent type])
+ {
+ case NSMouseEntered:
+ /* Enter events are considered always to be from the root window as we
+ * can't know for sure from what window we enter.
+ */
+ if (!(private->event_mask & GDK_ENTER_NOTIFY_MASK))
+ return FALSE;
+
+ fill_crossing_event (window, event, nsevent,
+ x, y,
+ x_root, y_root,
+ GDK_ENTER_NOTIFY,
+ GDK_CROSSING_NORMAL,
+ GDK_NOTIFY_ANCESTOR);
+ return TRUE;
+
+ case NSMouseExited:
+ /* Exited always is to the root window as far as we are concerned,
+ * since there is no way to reliably get information about what new
+ * window is entered when exiting one.
+ */
+ if (!(private->event_mask & GDK_LEAVE_NOTIFY_MASK))
+ return FALSE;
+
+ fill_crossing_event (window, event, nsevent,
+ x, y,
+ x_root, y_root,
+ GDK_LEAVE_NOTIFY,
+ GDK_CROSSING_NORMAL,
+ GDK_NOTIFY_ANCESTOR);
+ return TRUE;
+
+ default:
+ break;
+ }
+
+ return FALSE;
}
GdkEventMask
}
static gboolean
-gdk_event_translate (NSEvent *nsevent)
+gdk_event_translate (GdkEvent *event,
+ NSEvent *nsevent)
{
+ NSEventType event_type;
NSWindow *nswindow;
GdkWindow *window;
- GdkFilterReturn result;
- GdkEvent *event;
int x, y;
+ int x_root, y_root;
+ gboolean return_val;
/* There is no support for real desktop wide grabs, so we break
* grabs when the application loses focus (gets deactivated).
*/
- if ([nsevent type] == NSAppKitDefined)
+ event_type = [nsevent type];
+ if (event_type == NSAppKitDefined)
{
if ([nsevent subtype] == NSApplicationDeactivatedEventType)
- break_all_grabs ();
+ break_all_grabs (get_time_from_ns_event (nsevent));
/* This could potentially be used to break grabs when clicking
* on the title. The subtype 20 is undocumented so it's probably
* not a good idea: else if (subtype == 20) break_all_grabs ();
*/
- }
- /* Handle our generated "fake" crossing events. */
- if ([nsevent type] == NSApplicationDefined &&
- [nsevent subtype] == GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING)
- {
- _gdk_quartz_events_trigger_crossing_events (FALSE);
- return TRUE;
+ /* Leave all AppKit events to AppKit. */
+ return FALSE;
}
/* Keep track of button state, since we don't get that information
* for key events.
*/
- switch ([nsevent type])
+ switch (event_type)
{
case NSLeftMouseDown:
case NSRightMouseDown:
break;
}
- nswindow = [nsevent window];
-
- /* Apply any global filters. */
if (_gdk_default_filters)
{
- result = apply_filters (NULL, nsevent, _gdk_default_filters);
+ /* Apply global filters */
+ GdkFilterReturn result;
- /* If result is GDK_FILTER_CONTINUE, we continue as if nothing
- * happened. If it is GDK_FILTER_REMOVE,
- * we return TRUE and won't send the message to Quartz.
- */
- if (result == GDK_FILTER_REMOVE)
- return TRUE;
+ result = gdk_event_apply_filters (nsevent, event, _gdk_default_filters);
+ if (result != GDK_FILTER_CONTINUE)
+ {
+ return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+ goto done;
+ }
}
+ nswindow = [nsevent window];
+
/* Ignore events for no window or ones not created by GDK. */
if (!nswindow || ![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
return FALSE;
*/
if ([(GdkQuartzWindow *)nswindow isInMove])
{
- break_all_grabs ();
+ break_all_grabs (get_time_from_ns_event (nsevent));
return FALSE;
}
- /* Take care of NSMouseEntered/Exited events and mouse movements
- * events and emit the right GDK crossing events.
- */
- synthesize_crossing_events_for_ns_event (nsevent);
-
/* Find the right GDK window to send the event to, taking grabs and
* event masks into consideration.
*/
- window = find_window_for_ns_event (nsevent, &x, &y);
+ window = find_window_for_ns_event (nsevent, &x, &y, &x_root, &y_root);
if (!window)
return FALSE;
/* Apply any window filters. */
- result = apply_filters (window, nsevent, ((GdkWindowObject *) window)->filters);
- if (result == GDK_FILTER_REMOVE)
- return TRUE;
-
- /* We need the appliction to be activated on clicks so that popups
- * like context menus get events routed properly. This is handled
- * automatically for left mouse button presses but not other
- * buttons, so we do it here.
+ if (GDK_IS_WINDOW (window))
+ {
+ GdkWindowObject *filter_private = (GdkWindowObject *) window;
+ GdkFilterReturn result;
+
+ if (filter_private->filters)
+ {
+ g_object_ref (window);
+
+ result = gdk_event_apply_filters (nsevent, event, filter_private->filters);
+
+ g_object_unref (window);
+
+ if (result != GDK_FILTER_CONTINUE)
+ {
+ return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+ goto done;
+ }
+ }
+ }
+
+ /* If the app is not active leave the event to AppKit so the window gets
+ * focused correctly and don't do click-through (so we behave like most
+ * native apps). If the app is active, we focus the window and then handle
+ * the event, also to match native apps.
*/
- if ([nsevent type] == NSRightMouseDown || [nsevent type] == NSOtherMouseDown)
+ if ((event_type == NSRightMouseDown ||
+ event_type == NSOtherMouseDown ||
+ event_type == NSLeftMouseDown))
{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
+
if (![NSApp isActive])
- [NSApp activateIgnoringOtherApps:YES];
+ {
+ [NSApp activateIgnoringOtherApps:YES];
+ return FALSE;
+ }
+ else if (![impl->toplevel isKeyWindow])
+ {
+ GdkPointerGrabInfo *grab;
+
+ grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+ if (!grab)
+ [impl->toplevel makeKeyWindow];
+ }
}
current_event_mask = get_event_mask_from_ns_event (nsevent);
- switch ([nsevent type])
+ return_val = TRUE;
+
+ switch (event_type)
{
case NSLeftMouseDown:
case NSRightMouseDown:
case NSOtherMouseDown:
- {
- GdkEventMask event_mask;
-
- /* Emulate implicit grab, when the window has both PRESS and RELEASE
- * in its mask, like X.
- */
- event_mask = (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
- if (!_gdk_quartz_pointer_grab_window &&
- (GDK_WINDOW_OBJECT (window)->event_mask & event_mask) == event_mask)
- {
- pointer_grab_internal (window, FALSE,
- GDK_WINDOW_OBJECT (window)->event_mask,
- NULL, NULL, TRUE);
- }
- }
-
- event = create_button_event (window, nsevent, x, y);
- append_event (event);
-
- _gdk_event_button_generate (_gdk_display, event);
- break;
-
case NSLeftMouseUp:
case NSRightMouseUp:
case NSOtherMouseUp:
- event = create_button_event (window, nsevent, x, y);
- append_event (event);
-
- /* Ungrab implicit grab */
- if (_gdk_quartz_pointer_grab_window && pointer_grab_implicit)
- pointer_ungrab_internal (TRUE);
+ fill_button_event (window, event, nsevent, x, y, x_root, y_root);
break;
case NSLeftMouseDragged:
case NSRightMouseDragged:
case NSOtherMouseDragged:
case NSMouseMoved:
- event = create_motion_event (window, nsevent, x, y);
- append_event (event);
+ fill_motion_event (window, event, nsevent, x, y, x_root, y_root);
break;
case NSScrollWheel:
float dy = [nsevent deltaY];
GdkScrollDirection direction;
- /* The delta is how much the mouse wheel has moved. Since there's no such thing in GTK+
- * we accomodate by sending a different number of scroll wheel events.
- */
-
- /* First do y events */
- if (dy < 0.0)
- {
- dy = -dy;
- direction = GDK_SCROLL_DOWN;
- }
- else
- direction = GDK_SCROLL_UP;
-
- while (dy > 0.0)
- {
- event = create_scroll_event (window, nsevent, direction);
- append_event (event);
- dy--;
-
- /* Ignore the delta for now, things get too slow when the events queue up. */
- break;
- }
+ if (dy != 0)
+ {
+ if (dy < 0.0)
+ direction = GDK_SCROLL_DOWN;
+ else
+ direction = GDK_SCROLL_UP;
- /* Now do x events */
- if (dx < 0.0)
- {
- dx = -dx;
- direction = GDK_SCROLL_RIGHT;
- }
- else
- direction = GDK_SCROLL_LEFT;
+ fill_scroll_event (window, event, nsevent, x, y, x_root, y_root, direction);
+ }
- while (dx > 0.0)
- {
- event = create_scroll_event (window, nsevent, direction);
- append_event (event);
- dx--;
-
- /* Ignore the delta for now, things get too slow when the events queue up. */
- break;
- }
+ if (dx != 0)
+ {
+ if (dx < 0.0)
+ direction = GDK_SCROLL_RIGHT;
+ else
+ direction = GDK_SCROLL_LEFT;
+ fill_scroll_event (window, event, nsevent, x, y, x_root, y_root, direction);
+ }
}
break;
+ case NSMouseEntered:
+ case NSMouseExited:
+ return_val = synthesize_crossing_event (window, event, nsevent, x, y, x_root, y_root);
+ break;
+
case NSKeyDown:
case NSKeyUp:
case NSFlagsChanged:
type = _gdk_quartz_keys_event_type (nsevent);
if (type == GDK_NOTHING)
- return FALSE;
-
- event = create_key_event (window, nsevent, type);
- append_event (event);
- return TRUE;
+ return_val = FALSE;
+ else
+ fill_key_event (window, event, nsevent, type);
}
break;
default:
/* Ignore everything elsee. */
+ return_val = FALSE;
break;
}
- return FALSE;
+ done:
+ if (return_val)
+ {
+ if (event->any.window)
+ g_object_ref (event->any.window);
+ if (((event->any.type == GDK_ENTER_NOTIFY) ||
+ (event->any.type == GDK_LEAVE_NOTIFY)) &&
+ (event->crossing.subwindow != NULL))
+ g_object_ref (event->crossing.subwindow);
+ }
+ else
+ {
+ /* Mark this event as having no resources to be freed */
+ event->any.window = NULL;
+ event->any.type = GDK_NOTHING;
+ }
+
+ return return_val;
}
void
_gdk_events_queue (GdkDisplay *display)
{
- NSEvent *event;
+ NSEvent *nsevent;
- event = _gdk_quartz_event_loop_get_pending ();
- if (event)
+ nsevent = _gdk_quartz_event_loop_get_pending ();
+ if (nsevent)
{
- if (!gdk_event_translate (event))
+ GdkEvent *event;
+ GList *node;
+
+ event = gdk_event_new (GDK_NOTHING);
+
+ event->any.window = NULL;
+ event->any.send_event = FALSE;
+
+ ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
+
+ node = _gdk_event_queue_append (display, event);
+
+ if (gdk_event_translate (event, nsevent))
+ {
+ ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
+ _gdk_windowing_got_event (display, node, event, 0);
+ }
+ else
{
+ _gdk_event_queue_remove_link (display, node);
+ g_list_free_1 (node);
+ gdk_event_free (event);
+
GDK_THREADS_LEAVE ();
- [NSApp sendEvent:event];
+ [NSApp sendEvent:nsevent];
GDK_THREADS_ENTER ();
}
- _gdk_quartz_event_loop_release_event (event);
+ _gdk_quartz_event_loop_release_event (nsevent);
}
}
/* Not supported. */
}
-void
+void
gdk_display_add_client_message_filter (GdkDisplay *display,
GdkAtom message_type,
GdkFilterFunc func,
/* Not supported. */
}
-void
+void
gdk_add_client_message_filter (GdkAtom message_type,
GdkFilterFunc func,
gpointer data)
void
_gdk_windowing_gc_set_clip_region (GdkGC *gc,
- const GdkRegion *region)
+ const GdkRegion *region,
+ gboolean reset_origin)
{
GdkGCQuartz *private = GDK_GC_QUARTZ (gc);
private->have_clip_region = region != NULL;
- gc->clip_x_origin = 0;
- gc->clip_y_origin = 0;
+ if (reset_origin)
+ {
+ gc->clip_x_origin = 0;
+ gc->clip_y_origin = 0;
+ }
}
void
CGContextRef context)
{
GdkGC *gc = GDK_GC (info);
- GdkGCQuartz *private = GDK_GC_QUARTZ (gc);
CGImageRef pattern_image;
size_t width, height;
#include "gdkprivate-quartz.h"
void
-_gdk_quartz_window_scroll (GdkWindow *window,
- gint dx,
- gint dy)
+_gdk_quartz_window_queue_translation (GdkWindow *window,
+ GdkRegion *area,
+ gint dx,
+ gint dy)
{
- NSRect visible_nsrect;
- GdkRectangle visible_rect, scrolled_rect;
- GdkRegion *visible_region, *scrolled_region;
- GdkRectangle *rects;
- gint n_rects, i;
- GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
- GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
- GList *list;
-
- /* Move the current invalid region */
- if (private->update_area)
- gdk_region_offset (private->update_area, dx, dy);
-
- visible_nsrect = [impl->view visibleRect];
-
- visible_rect.x = visible_nsrect.origin.x;
- visible_rect.y = visible_nsrect.origin.y;
- visible_rect.width = visible_nsrect.size.width;
- visible_rect.height = visible_nsrect.size.height;
-
- scrolled_rect = visible_rect;
- scrolled_rect.x += dx;
- scrolled_rect.y += dy;
-
- gdk_rectangle_intersect (&visible_rect, &scrolled_rect, &scrolled_rect);
-
- visible_region = gdk_region_rectangle (&visible_rect);
- scrolled_region = gdk_region_rectangle (&scrolled_rect);
-
- gdk_region_subtract (visible_region, scrolled_region);
-
- [impl->view scrollRect:[impl->view bounds] by:NSMakeSize(dx, dy)];
-
- gdk_region_get_rectangles (visible_region, &rects, &n_rects);
- for (i = 0; i < n_rects; i++)
- [impl->view setNeedsDisplayInRect:NSMakeRect (rects[i].x, rects[i].y, rects[i].width, rects[i].height)];
-
- g_free (rects);
-
- gdk_region_destroy (visible_region);
- gdk_region_destroy (scrolled_region);
-
- /* Move child windows */
- for (list = private->children; list; list = list->next)
- {
- GdkWindowObject *child = GDK_WINDOW_OBJECT (list->data);
-
- gdk_window_move (list->data,
- child->x + dx,
- child->y + dy);
- }
}
-void
-_gdk_quartz_window_move_region (GdkWindow *window,
- const GdkRegion *region,
- gint dx,
- gint dy)
+gboolean
+_gdk_quartz_window_queue_antiexpose (GdkWindow *window,
+ GdkRegion *area)
{
- /* FIXME: Implement */
+ return FALSE;
}
gint *n_events)
{
g_return_val_if_fail (window != NULL, FALSE);
- g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+ g_return_val_if_fail (GDK_WINDOW_IS_QUARTZ (window), FALSE);
g_return_val_if_fail (events != NULL, FALSE);
g_return_val_if_fail (n_events != NULL, FALSE);
GdkInputWindow *iw;
g_return_if_fail (window != NULL);
- g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (GDK_WINDOW_IS_QUARTZ (window));
window_private = (GdkWindowObject*) window;
}
GdkPixmap*
-gdk_pixmap_new (GdkDrawable *drawable,
- gint width,
- gint height,
- gint depth)
+_gdk_pixmap_new (GdkDrawable *drawable,
+ gint width,
+ gint height,
+ gint depth)
{
GdkPixmap *pixmap;
GdkDrawableImplQuartz *draw_impl;
}
GdkPixmap *
-gdk_bitmap_create_from_data (GdkDrawable *window,
- const gchar *data,
- gint width,
- gint height)
+_gdk_bitmap_create_from_data (GdkDrawable *window,
+ const gchar *data,
+ gint width,
+ gint height)
{
GdkPixmap *pixmap;
GdkPixmapImplQuartz *impl;
}
GdkPixmap*
-gdk_pixmap_create_from_data (GdkDrawable *drawable,
- const gchar *data,
- gint width,
- gint height,
- gint depth,
- const GdkColor *fg,
- const GdkColor *bg)
+_gdk_pixmap_create_from_data (GdkDrawable *drawable,
+ const gchar *data,
+ gint width,
+ gint height,
+ gint depth,
+ const GdkColor *fg,
+ const GdkColor *bg)
{
/* FIXME: Implement */
return NULL;
extern GdkDragContext *_gdk_quartz_drag_source_context;
+#define GDK_WINDOW_IS_QUARTZ(win) (GDK_IS_WINDOW_IMPL_QUARTZ (((GdkWindowObject *)win)->impl))
+
/* Initialization */
void _gdk_windowing_window_init (void);
void _gdk_events_init (void);
/* Events */
typedef enum {
- GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP,
- GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING
+ GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP
} GdkQuartzEventSubType;
void _gdk_quartz_events_update_focus_window (GdkWindow *new_window,
gboolean got_focus);
-GdkWindow * _gdk_quartz_events_get_mouse_window (gboolean consider_grabs);
-void _gdk_quartz_events_update_mouse_window (GdkWindow *window);
-void _gdk_quartz_events_update_cursor (GdkWindow *window);
-void _gdk_quartz_events_send_map_events (GdkWindow *window);
+void _gdk_quartz_events_send_map_event (GdkWindow *window);
GdkEventMask _gdk_quartz_events_get_current_event_mask (void);
-void _gdk_quartz_events_trigger_crossing_events(gboolean defer_to_mainloop);
-
-extern GdkWindow *_gdk_quartz_keyboard_grab_window;
-extern GdkWindow *_gdk_quartz_pointer_grab_window;
/* Event loop */
gboolean _gdk_quartz_event_loop_check_pending (void);
/* Drawable */
void _gdk_quartz_drawable_finish (GdkDrawable *drawable);
+void _gdk_quartz_drawable_flush (GdkDrawable *drawable);
/* Geometry */
void _gdk_quartz_window_scroll (GdkWindow *window,
gint dx,
gint dy);
-void _gdk_quartz_window_move_region (GdkWindow *window,
- const GdkRegion *region,
- gint dx,
- gint dy);
+void _gdk_quartz_window_queue_translation (GdkWindow *window,
+ GdkRegion *area,
+ gint dx,
+ gint dy);
+gboolean _gdk_quartz_window_queue_antiexpose (GdkWindow *window,
+ GdkRegion *area);
#endif /* __GDK_PRIVATE_QUARTZ_H__ */
static gpointer parent_class;
-static GSList *update_windows;
-static guint update_idle;
+static GSList *update_nswindows;
+static gboolean in_process_all_updates = FALSE;
static GSList *main_window_stack;
static FullscreenSavedGeometry *get_fullscreen_geometry (GdkWindow *window);
-#define WINDOW_IS_TOPLEVEL(window) \
- (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
- GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+#define WINDOW_IS_TOPLEVEL(window) \
+ (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
+ GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
+ GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
static void gdk_window_impl_iface_init (GdkWindowImplIface *iface);
return ((GdkWindowImplQuartz *)private->impl)->toplevel;
}
-static void
-gdk_window_impl_quartz_get_size (GdkDrawable *drawable,
- gint *width,
- gint *height)
-{
- g_return_if_fail (GDK_IS_WINDOW_IMPL_QUARTZ (drawable));
-
- if (width)
- *width = GDK_WINDOW_IMPL_QUARTZ (drawable)->width;
- if (height)
- *height = GDK_WINDOW_IMPL_QUARTZ (drawable)->height;
-}
-
static CGContextRef
gdk_window_impl_quartz_get_context (GdkDrawable *drawable,
gboolean antialias)
* is needed when called from outside "real" expose events, for
* example for synthesized expose events when realizing windows
* and for widgets that send fake expose events like the arrow
- * buttons in spinbuttons.
+ * buttons in spinbuttons or the position marker in rulers.
*/
if (window_impl->in_paint_rect_count == 0)
{
return cg_context;
}
-static GdkRegion*
-gdk_window_impl_quartz_get_visible_region (GdkDrawable *drawable)
+static void
+check_grab_unmap (GdkWindow *window)
{
- GdkWindowObject *private = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_QUARTZ (drawable)->wrapper);
- GdkRectangle rect;
- GdkWindowImplQuartz *impl;
- GList *windows = NULL, *l;
+ GdkDisplay *display = gdk_drawable_get_display (window);
- /* FIXME: The clip rectangle should really be cached
- * and recalculated when the window rectangle changes.
- */
- while (private)
+ _gdk_display_end_pointer_grab (display, 0, window, TRUE);
+
+ if (display->keyboard_grab.window)
{
- windows = g_list_prepend (windows, private);
+ GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
+ GdkWindowObject *tmp = GDK_WINDOW_OBJECT (display->keyboard_grab.window);
- if (private->parent == GDK_WINDOW_OBJECT (_gdk_root))
- break;
+ while (tmp && tmp != private)
+ tmp = tmp->parent;
- private = private->parent;
+ if (tmp)
+ _gdk_display_unset_has_keyboard_grab (display, TRUE);
}
+}
- /* Get rectangle for toplevel window */
- private = GDK_WINDOW_OBJECT (windows->data);
- impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
-
- rect.x = 0;
- rect.y = 0;
- rect.width = impl->width;
- rect.height = impl->height;
+static void
+check_grab_destroy (GdkWindow *window)
+{
+ GdkDisplay *display = gdk_drawable_get_display (window);
+ GdkPointerGrabInfo *grab;
- /* Skip toplevel window since we have its rect */
- for (l = windows->next; l; l = l->next)
+ /* Make sure there is no lasting grab in this native window */
+ grab = _gdk_display_get_last_pointer_grab (display);
+ if (grab && grab->native_window == window)
{
- private = GDK_WINDOW_OBJECT (l->data);
- impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
- GdkRectangle tmp_rect;
-
- tmp_rect.x = -MIN (0, private->x - rect.x);
- tmp_rect.y = -MIN (0, private->y - rect.y);
- tmp_rect.width = MIN (rect.width, impl->width + private->x - rect.x) - MAX (0, private->x - rect.x);
- tmp_rect.height = MIN (rect.height, impl->height + private->y - rect.y) - MAX (0, private->y - rect.y);
-
- rect = tmp_rect;
+ /* Serials are always 0 in quartz, but for clarity: */
+ grab->serial_end = grab->serial_start;
+ grab->implicit_ungrab = TRUE;
}
-
- g_list_free (windows);
-
- return gdk_region_rectangle (&rect);
+
+ if (window == display->keyboard_grab.native_window &&
+ display->keyboard_grab.window != NULL)
+ _gdk_display_unset_has_keyboard_grab (display, TRUE);
}
static void
{
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (object);
- if (impl->nscursor)
- [impl->nscursor release];
+ check_grab_destroy (GDK_DRAWABLE_IMPL_QUARTZ (object)->wrapper);
if (impl->paint_clip_region)
gdk_region_destroy (impl->paint_clip_region);
static void
gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass)
{
- GdkDrawableImplQuartzClass *drawable_quartz_class = GDK_DRAWABLE_IMPL_QUARTZ_CLASS (klass);
- GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GdkDrawableImplQuartzClass *drawable_quartz_class = GDK_DRAWABLE_IMPL_QUARTZ_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
object_class->finalize = gdk_window_impl_quartz_finalize;
- drawable_class->get_size = gdk_window_impl_quartz_get_size;
-
drawable_quartz_class->get_context = gdk_window_impl_quartz_get_context;
-
- /* Visible and clip regions are the same */
- drawable_class->get_clip_region = gdk_window_impl_quartz_get_visible_region;
- drawable_class->get_visible_region = gdk_window_impl_quartz_get_visible_region;
}
static void
gdk_window_impl_quartz_init (GdkWindowImplQuartz *impl)
{
- impl->width = 1;
- impl->height = 1;
impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
}
static void
gdk_window_impl_quartz_begin_paint_region (GdkPaintable *paintable,
+ GdkWindow *window,
const GdkRegion *region)
{
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
- GdkDrawableImplQuartz *drawable_impl;
+ GdkWindowObject *private = (GdkWindowObject*)window;
int n_rects;
- GdkRectangle *rects;
+ GdkRectangle *rects = NULL;
GdkPixmap *bg_pixmap;
- GdkWindow *window;
+ GdkRegion *clipped_and_offset_region;
+ gboolean free_clipped_and_offset_region = TRUE;
+
+ bg_pixmap = private->bg_pixmap;
- drawable_impl = GDK_DRAWABLE_IMPL_QUARTZ (impl);
- bg_pixmap = GDK_WINDOW_OBJECT (drawable_impl->wrapper)->bg_pixmap;
+ clipped_and_offset_region = gdk_region_copy (region);
+
+ gdk_region_intersect (clipped_and_offset_region,
+ private->clip_region_with_children);
+ gdk_region_offset (clipped_and_offset_region,
+ private->abs_x, private->abs_y);
if (impl->begin_paint_count == 0)
- impl->paint_clip_region = gdk_region_copy (region);
+ {
+ impl->paint_clip_region = clipped_and_offset_region;
+ free_clipped_and_offset_region = FALSE;
+ }
else
- gdk_region_union (impl->paint_clip_region, region);
+ gdk_region_union (impl->paint_clip_region, clipped_and_offset_region);
impl->begin_paint_count++;
if (bg_pixmap == GDK_NO_BG)
- return;
+ goto done;
- gdk_region_get_rectangles (region, &rects, &n_rects);
+ gdk_region_get_rectangles (clipped_and_offset_region, &rects, &n_rects);
if (bg_pixmap == NULL)
{
gint i;
cg_context = gdk_quartz_drawable_get_context (GDK_DRAWABLE (impl), FALSE);
- _gdk_quartz_colormap_get_rgba_from_pixel (gdk_drawable_get_colormap (drawable_impl->wrapper),
- GDK_WINDOW_OBJECT (drawable_impl->wrapper)->bg_color.pixel,
- &r, &g, &b, &a);
+ _gdk_quartz_colormap_get_rgba_from_pixel (gdk_drawable_get_colormap (window),
+ private->bg_color.pixel,
+ &r, &g, &b, &a);
CGContextSetRGBFillColor (cg_context, r, g, b, a);
for (i = 0; i < n_rects; i++)
x_offset = y_offset = 0;
- window = GDK_WINDOW (drawable_impl->wrapper);
while (window && bg_pixmap == GDK_PARENT_RELATIVE_BG)
{
/* If this window should have the same background as the parent,
/* Parent relative background but the parent doesn't have a
* pixmap.
*/
- g_free (rects);
- return;
+ goto done;
}
/* Note: There should be a CG API to draw tiled images, we might
g_object_unref (gc);
}
+ done:
+ if (free_clipped_and_offset_region)
+ gdk_region_destroy (clipped_and_offset_region);
g_free (rects);
}
}
}
-static void
-gdk_window_quartz_process_updates_internal (GdkWindow *window)
-{
- GdkWindowObject *private = (GdkWindowObject *) window;
- GdkWindowImplQuartz *impl = (GdkWindowImplQuartz *) private->impl;
-
- if (private->update_area)
- {
- int i, n_rects;
- GdkRectangle *rects;
-
- gdk_region_get_rectangles (private->update_area, &rects, &n_rects);
-
- gdk_region_destroy (private->update_area);
- private->update_area = NULL;
-
- for (i = 0; i < n_rects; i++)
- {
- [impl->view setNeedsDisplayInRect:NSMakeRect (rects[i].x, rects[i].y,
- rects[i].width, rects[i].height)];
- }
-
- [impl->view displayIfNeeded];
-
- g_free (rects);
- }
-}
-
-static void
-gdk_window_quartz_process_all_updates (void)
+void
+_gdk_windowing_window_process_updates_recurse (GdkWindow *window,
+ GdkRegion *region)
{
- GSList *old_update_windows = update_windows;
- GSList *tmp_list = update_windows;
- GSList *nswindows;
-
- update_idle = 0;
- update_windows = NULL;
- nswindows = NULL;
-
- g_slist_foreach (old_update_windows, (GFunc) g_object_ref, NULL);
-
- GDK_QUARTZ_ALLOC_POOL;
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowImplQuartz *impl = (GdkWindowImplQuartz *)private->impl;
+ int i, n_rects;
+ GdkRectangle *rects;
- while (tmp_list)
+ /* Make sure to only flush each toplevel at most once if we're called
+ * from process_all_updates.
+ */
+ if (in_process_all_updates)
{
- GdkWindow *window = tmp_list->data;
GdkWindow *toplevel;
- /* Only flush each toplevel at most once. */
toplevel = gdk_window_get_toplevel (window);
if (toplevel)
{
- GdkWindowObject *private;
- GdkWindowImplQuartz *impl;
+ GdkWindowObject *toplevel_private;
+ GdkWindowImplQuartz *toplevel_impl;
NSWindow *nswindow;
- private = (GdkWindowObject *) toplevel;
- impl = (GdkWindowImplQuartz *) private->impl;
- nswindow = impl->toplevel;
+ toplevel_private = (GdkWindowObject *)toplevel;
+ toplevel_impl = (GdkWindowImplQuartz *)toplevel_private->impl;
+ nswindow = toplevel_impl->toplevel;
+ /* In theory, we could skip the flush disabling, since we only
+ * have one NSView.
+ */
if (nswindow && ![nswindow isFlushWindowDisabled])
{
+ [nswindow retain];
[nswindow disableFlushWindow];
- nswindows = g_slist_prepend (nswindows, nswindow);
+ update_nswindows = g_slist_prepend (update_nswindows, nswindow);
}
}
-
- gdk_window_quartz_process_updates_internal (tmp_list->data);
-
- g_object_unref (tmp_list->data);
- tmp_list = tmp_list->next;
}
- tmp_list = nswindows;
- while (tmp_list)
- {
- NSWindow *nswindow = tmp_list->data;
-
- [nswindow enableFlushWindow];
- [nswindow flushWindow];
+ gdk_region_get_rectangles (region, &rects, &n_rects);
- tmp_list = tmp_list->next;
+ for (i = 0; i < n_rects; i++)
+ {
+ [impl->view setNeedsDisplayInRect:NSMakeRect (rects[i].x, rects[i].y,
+ rects[i].width, rects[i].height)];
}
-
- GDK_QUARTZ_RELEASE_POOL;
- g_slist_free (old_update_windows);
- g_slist_free (nswindows);
+ g_free (rects);
+
+ /* NOTE: I'm not sure if we should displayIfNeeded here. It slows down a
+ * lot (since it triggers the beam syncing) and things seem to work
+ * without it.
+ */
}
-static gboolean
-gdk_window_quartz_update_idle (gpointer data)
+void
+_gdk_windowing_before_process_all_updates (void)
{
- gdk_window_quartz_process_all_updates ();
+ in_process_all_updates = TRUE;
- return FALSE;
+ NSDisableScreenUpdates ();
}
-static void
-gdk_window_impl_quartz_invalidate_maybe_recurse (GdkPaintable *paintable,
- const GdkRegion *region,
- gboolean (*child_func) (GdkWindow *, gpointer),
- gpointer user_data)
-{
- GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
- GdkDrawableImplQuartz *drawable_impl = (GdkDrawableImplQuartz *) window_impl;
- GdkWindow *window = (GdkWindow *) drawable_impl->wrapper;
- GdkWindowObject *private = (GdkWindowObject *) window;
- GdkRegion *visible_region;
+void
+_gdk_windowing_after_process_all_updates (void)
+{
+ GSList *old_update_nswindows = update_nswindows;
+ GSList *tmp_list = update_nswindows;
- visible_region = gdk_drawable_get_visible_region (window);
- gdk_region_intersect (visible_region, region);
+ update_nswindows = NULL;
- if (private->update_area)
- {
- gdk_region_union (private->update_area, visible_region);
- gdk_region_destroy (visible_region);
- }
- else
+ while (tmp_list)
{
- /* FIXME: When the update_window/update_area handling is abstracted in
- * some way, we can remove this check. Currently it might be cleared
- * in the generic code without us knowing, see bug #530801.
- */
- if (!g_slist_find (update_windows, window))
- update_windows = g_slist_prepend (update_windows, window);
- private->update_area = visible_region;
+ NSWindow *nswindow = tmp_list->data;
- if (update_idle == 0)
- update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
- gdk_window_quartz_update_idle, NULL, NULL);
- }
-}
+ [[nswindow contentView] displayIfNeeded];
-static void
-gdk_window_impl_quartz_process_updates (GdkPaintable *paintable,
- gboolean update_children)
-{
- GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
- GdkDrawableImplQuartz *drawable_impl = (GdkDrawableImplQuartz *) impl;
- GdkWindowObject *private = (GdkWindowObject *) drawable_impl->wrapper;
+ _gdk_quartz_drawable_flush (NULL);
- if (private->update_area)
- {
- GDK_QUARTZ_ALLOC_POOL;
- gdk_window_quartz_process_updates_internal ((GdkWindow *) private);
- update_windows = g_slist_remove (update_windows, private);
- GDK_QUARTZ_RELEASE_POOL;
+ [nswindow enableFlushWindow];
+ [nswindow flushWindow];
+ [nswindow release];
+
+ tmp_list = tmp_list->next;
}
+
+ g_slist_free (old_update_nswindows);
+
+ in_process_all_updates = FALSE;
+
+ NSEnableScreenUpdates ();
}
static void
{
iface->begin_paint_region = gdk_window_impl_quartz_begin_paint_region;
iface->end_paint = gdk_window_impl_quartz_end_paint;
-
- iface->invalidate_maybe_recurse = gdk_window_impl_quartz_invalidate_maybe_recurse;
- iface->process_updates = gdk_window_impl_quartz_process_updates;
}
GType
_gdk_quartz_window_debug_highlight (GdkWindow *window, gint number)
{
GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
- GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
gint x, y;
GdkWindow *toplevel;
gint tx, ty;
y += ty;
rect = NSMakeRect (x,
- _gdk_quartz_window_get_inverted_screen_y (y + impl->height),
- impl->width, impl->height);
+ _gdk_quartz_window_get_inverted_screen_y (y + private->height),
+ private->width, private->height);
if (debug_window[number] && NSEqualRects (rect, old_rect[number]))
return;
if (titlebar_height > 0 &&
x >= temp_x && y >= temp_y - titlebar_height &&
- x < temp_x + child_impl->width && y < temp_y)
+ x < temp_x + child_private->width && y < temp_y)
{
/* The root means "unknown" i.e. a window not managed by
* GDK.
}
if (x >= temp_x && y >= temp_y &&
- x < temp_x + child_impl->width && y < temp_y + child_impl->height)
+ x < temp_x + child_private->width && y < temp_y + child_private->height)
{
/* Look for child windows. */
return find_child_window_helper (l->data,
gint y)
{
GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
- GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
- if (x >= 0 && y >= 0 && x < impl->width && y < impl->height)
+ if (x >= 0 && y >= 0 && x < private->width && y < private->height)
return find_child_window_helper (window, x, y, 0, 0);
return NULL;
clear_toplevel_order ();
}
-GdkWindow *
-_gdk_window_new (GdkWindow *parent,
- GdkWindowAttr *attributes,
- gint attributes_mask)
+void
+_gdk_window_impl_new (GdkWindow *window,
+ GdkWindow *real_parent,
+ GdkScreen *screen,
+ GdkVisual *visual,
+ GdkEventMask event_mask,
+ GdkWindowAttr *attributes,
+ gint attributes_mask)
{
- GdkWindow *window;
GdkWindowObject *private;
GdkWindowImplQuartz *impl;
GdkDrawableImplQuartz *draw_impl;
- GdkVisual *visual;
GdkWindowImplQuartz *parent_impl;
- if (parent && GDK_WINDOW_DESTROYED (parent))
- return NULL;
-
GDK_QUARTZ_ALLOC_POOL;
- if (!parent)
- parent = _gdk_root;
-
- window = g_object_new (GDK_TYPE_WINDOW, NULL);
-
private = (GdkWindowObject *)window;
- private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
- impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
- draw_impl = GDK_DRAWABLE_IMPL_QUARTZ (private->impl);
+ impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+ private->impl = (GdkDrawable *)impl;
+ draw_impl = GDK_DRAWABLE_IMPL_QUARTZ (impl);
draw_impl->wrapper = GDK_DRAWABLE (window);
- private->parent = (GdkWindowObject *)parent;
parent_impl = GDK_WINDOW_IMPL_QUARTZ (private->parent->impl);
- private->accept_focus = TRUE;
- private->focus_on_map = TRUE;
-
- if (attributes_mask & GDK_WA_X)
- private->x = attributes->x;
- else
- private->x = 0;
-
- if (attributes_mask & GDK_WA_Y)
- private->y = attributes->y;
- else if (attributes_mask & GDK_WA_X)
- private->y = 100;
- else
- private->y = 0;
-
- private->event_mask = attributes->event_mask;
-
- impl->width = attributes->width > 1 ? attributes->width : 1;
- impl->height = attributes->height > 1 ? attributes->height : 1;
-
- if (attributes_mask & GDK_WA_VISUAL)
- visual = attributes->visual;
- else
- visual = gdk_screen_get_system_visual (_gdk_screen);
-
- if (attributes->wclass == GDK_INPUT_ONLY)
- {
- /* Backwards compatiblity - we've always ignored
- * attributes->window_type for input-only windows
- * before
- */
- if (parent == _gdk_root)
- private->window_type = GDK_WINDOW_TEMP;
- else
- private->window_type = GDK_WINDOW_CHILD;
- }
- else
- private->window_type = attributes->window_type;
-
- /* Sanity checks */
switch (private->window_type)
{
case GDK_WINDOW_TOPLEVEL:
case GDK_WINDOW_DIALOG:
case GDK_WINDOW_TEMP:
- if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
+ if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
{
- g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
- "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
+ /* The common code warns for this case */
+ parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (_gdk_root)->impl);
}
- case GDK_WINDOW_CHILD:
- break;
- default:
- g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
- GDK_QUARTZ_RELEASE_POOL;
- return NULL;
}
- if (attributes->wclass == GDK_INPUT_OUTPUT)
+ if (!private->input_only)
{
- private->input_only = FALSE;
- private->depth = visual->depth;
-
if (attributes_mask & GDK_WA_COLORMAP)
{
draw_impl->colormap = attributes->colormap;
draw_impl->colormap = gdk_colormap_new (visual, FALSE);
}
}
-
- private->bg_color.pixel = 0;
- private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
}
else
{
- private->depth = 0;
- private->input_only = TRUE;
draw_impl->colormap = gdk_screen_get_system_colormap (_gdk_screen);
g_object_ref (draw_impl->colormap);
}
- private->parent->children = g_list_prepend (private->parent->children, window);
-
/* Maintain the z-ordered list of children. */
- if (parent != _gdk_root)
+ if (private->parent != (GdkWindowObject *)_gdk_root)
parent_impl->sorted_children = g_list_prepend (parent_impl->sorted_children, window);
else
clear_toplevel_order ();
int style_mask;
const char *title;
- /* Big hack: We start out outside the screen and move the
- * window in before showing it. This makes the initial
- * MouseEntered event work if the window ends up right under
- * the mouse pointer, bad quartz.
- */
- content_rect = NSMakeRect (-500 - impl->width, -500 - impl->height,
- impl->width, impl->height);
+ content_rect = NSMakeRect (private->x,
+ _gdk_quartz_window_get_inverted_screen_y (private->y) - private->height,
+ private->width,
+ private->height);
if (attributes->window_type == GDK_WINDOW_TEMP ||
attributes->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN)
[impl->toplevel setBackgroundColor:[NSColor clearColor]];
}
+ content_rect.origin.x = 0;
+ content_rect.origin.y = 0;
+
impl->view = [[GdkQuartzView alloc] initWithFrame:content_rect];
[impl->view setGdkWindow:window];
[impl->toplevel setContentView:impl->view];
case GDK_WINDOW_CHILD:
{
- GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (parent)->impl);
+ GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (private->parent)->impl);
- if (attributes->wclass == GDK_INPUT_OUTPUT)
+ if (!private->input_only)
{
- NSRect frame_rect = NSMakeRect (private->x, private->y, impl->width, impl->height);
+ NSRect frame_rect = NSMakeRect (private->x + private->parent->abs_x,
+ private->y + private->parent->abs_y,
+ private->width,
+ private->height);
impl->view = [[GdkQuartzView alloc] initWithFrame:frame_rect];
if (attributes_mask & GDK_WA_TYPE_HINT)
gdk_window_set_type_hint (window, attributes->type_hint);
-
- return window;
}
void
private = (GdkWindowObject *)_gdk_root;
private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+ private->impl_window = private;
/* Note: This needs to be reworked for multi-screen support. */
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (_gdk_root)->impl);
rect = [[NSScreen mainScreen] frame];
- impl->width = rect.size.width;
- impl->height = rect.size.height;
+
+ private->x = 0;
+ private->y = 0;
+ private->abs_x = 0;
+ private->abs_y = 0;
+ private->width = rect.size.width;
+ private->height = rect.size.height;
private->state = 0; /* We don't want GDK_WINDOW_STATE_WITHDRAWN here */
private->window_type = GDK_WINDOW_ROOT;
g_object_ref (drawable_impl->colormap);
}
-void
-_gdk_windowing_window_destroy (GdkWindow *window,
- gboolean recursing,
- gboolean foreign_destroy)
+static void
+_gdk_quartz_window_destroy (GdkWindow *window,
+ gboolean recursing,
+ gboolean foreign_destroy)
{
GdkWindowObject *private;
GdkWindowImplQuartz *impl;
GdkWindowObject *parent;
- GdkWindow *mouse_window;
private = GDK_WINDOW_OBJECT (window);
impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
- update_windows = g_slist_remove (update_windows, window);
main_window_stack = g_slist_remove (main_window_stack, window);
g_list_free (impl->sorted_children);
parent_impl->sorted_children = g_list_remove (parent_impl->sorted_children, window);
}
- /* If the destroyed window was targeted for a pointer or keyboard
- * grab, release the grab.
- */
- if (window == _gdk_quartz_pointer_grab_window)
- gdk_pointer_ungrab (0);
-
- if (window == _gdk_quartz_keyboard_grab_window)
- gdk_keyboard_ungrab (0);
-
_gdk_quartz_drawable_finish (GDK_DRAWABLE (impl));
- mouse_window = _gdk_quartz_events_get_mouse_window (FALSE);
- if (window == mouse_window ||
- _gdk_quartz_window_is_ancestor (window, mouse_window))
- _gdk_quartz_events_update_mouse_window (_gdk_root);
-
if (!recursing && !foreign_destroy)
{
GDK_QUARTZ_ALLOC_POOL;
/* Foreign windows aren't supported in OSX. */
}
-static gboolean
-all_parents_shown (GdkWindowObject *private)
-{
- while (GDK_WINDOW_IS_MAPPED (private))
- {
- if (private->parent)
- private = (GdkWindowObject *)private->parent;
- else
- return TRUE;
- }
-
- return FALSE;
-}
-
-/* Note: the raise argument is not really used, it doesn't seem
- * possible to show a window without raising it?
- */
+/* FIXME: This might be possible to simplify with client-side windows. */
static void
-gdk_window_quartz_show (GdkWindow *window,
- gboolean raise)
+gdk_window_quartz_show (GdkWindow *window)
{
- GdkWindowObject *private;
- GdkWindowImplQuartz *impl;
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
gboolean focus_on_map;
- if (GDK_WINDOW_DESTROYED (window))
- return;
-
GDK_QUARTZ_ALLOC_POOL;
- private = (GdkWindowObject *)window;
- impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
-
if (!GDK_WINDOW_IS_MAPPED (window))
focus_on_map = private->focus_on_map;
else
{
gboolean make_key;
- /* Move the window into place, to guarantee that we get the
- * initial MouseEntered event.
- */
- make_key = (private->accept_focus && focus_on_map && raise &&
+ make_key = (private->accept_focus && focus_on_map &&
private->window_type != GDK_WINDOW_TEMP);
[(GdkQuartzWindow*)impl->toplevel showAndMakeKey:make_key];
clear_toplevel_order ();
+
+ _gdk_quartz_events_send_map_event (window);
}
else
{
[impl->view setNeedsDisplay:YES];
- if (all_parents_shown (private->parent))
- _gdk_quartz_events_send_map_events (window);
-
gdk_synthesize_window_state (window, GDK_WINDOW_STATE_WITHDRAWN, 0);
if (private->state & GDK_WINDOW_STATE_MAXIMIZED)
if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
_gdk_quartz_window_attach_to_parent (window);
- /* Create a crossing event for windows that pop up under the mouse. Part
- * of the workarounds for problems with the tracking rect API.
- */
- if (impl->toplevel)
- _gdk_quartz_events_trigger_crossing_events (TRUE);
-
GDK_QUARTZ_RELEASE_POOL;
}
{
GdkWindowObject *private = (GdkWindowObject *)window;
GdkWindowImplQuartz *impl;
- GdkWindow *mouse_window;
/* Make sure we're not stuck in fullscreen mode. */
if (get_fullscreen_geometry (window))
SetSystemUIMode (kUIModeNormal, 0);
- if (GDK_WINDOW_DESTROYED (window))
- return;
-
- mouse_window = _gdk_quartz_events_get_mouse_window (FALSE);
- if (window == mouse_window ||
- _gdk_quartz_window_is_ancestor (window, mouse_window))
- _gdk_quartz_events_update_mouse_window (_gdk_root);
-
- if (GDK_WINDOW_IS_MAPPED (window))
- gdk_synthesize_window_state (window,
- 0,
- GDK_WINDOW_STATE_WITHDRAWN);
+ check_grab_unmap (window);
_gdk_window_clear_update_area (window);
{
[impl->view setHidden:YES];
}
-
- if (window == _gdk_quartz_pointer_grab_window)
- gdk_pointer_ungrab (0);
-
- if (window == _gdk_quartz_keyboard_grab_window)
- gdk_keyboard_ungrab (0);
}
void
if ((x == -1 || (x == private->x)) &&
(y == -1 || (y == private->y)) &&
- (width == -1 || (width == impl->width)) &&
- (height == -1 || (height == impl->height)))
+ (width == -1 || (width == private->width)) &&
+ (height == -1 || (height == private->height)))
{
return;
}
}
if (width != -1)
- impl->width = width;
+ private->width = width;
if (height != -1)
- impl->height = height;
+ private->height = height;
GDK_QUARTZ_ALLOC_POOL;
NSRect content_rect;
NSRect frame_rect;
- /* We don't update the NSWindow while unmapped, since we move windows
- * off-screen when hiding in order for MouseEntered to be triggered
- * reliably when showing windows and they appear under the mouse.
- */
- if (GDK_WINDOW_IS_MAPPED (window))
- {
- content_rect = NSMakeRect (private->x,
- _gdk_quartz_window_get_inverted_screen_y (private->y + impl->height),
- impl->width, impl->height);
+ content_rect = NSMakeRect (private->x,
+ _gdk_quartz_window_get_inverted_screen_y (private->y + private->height),
+ private->width, private->height);
- frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
- [impl->toplevel setFrame:frame_rect display:YES];
- }
+ frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
+ [impl->toplevel setFrame:frame_rect display:YES];
}
else
{
{
NSRect nsrect;
- nsrect = NSMakeRect (private->x, private->y, impl->width, impl->height);
+ nsrect = NSMakeRect (private->x, private->y, private->width, private->height);
/* The newly visible area of this window in a coordinate
* system rooted at the origin of this window.
}
}
+/* FIXME: This might need fixing (reparenting didn't work before client-side
+ * windows either).
+ */
static gboolean
gdk_window_quartz_reparent (GdkWindow *window,
GdkWindow *new_parent,
GdkWindowImplQuartz *impl, *old_parent_impl, *new_parent_impl;
NSView *view, *new_parent_view;
- if (!new_parent || new_parent == _gdk_root)
+ if (new_parent == _gdk_root)
{
/* Could be added, just needs implementing. */
g_warning ("Reparenting to root window is not supported yet in the Mac OS X backend");
[view release];
- private->x = x;
- private->y = y;
- private->parent = (GdkWindowObject *)new_parent;
+ private->parent = new_parent_private;
if (old_parent_private)
{
- old_parent_private->children = g_list_remove (old_parent_private->children, window);
old_parent_impl->sorted_children = g_list_remove (old_parent_impl->sorted_children, window);
}
- new_parent_private->children = g_list_prepend (new_parent_private->children, window);
new_parent_impl->sorted_children = g_list_prepend (new_parent_impl->sorted_children, window);
- return TRUE;
-}
-
-static void
-gdk_window_quartz_clear_area (GdkWindow *window,
- gint x,
- gint y,
- gint width,
- gint height,
- gboolean send_expose)
-{
- /* FIXME: Implement */
+ return FALSE;
}
/* Get the toplevel ordering from NSApp and update our own list. We do
gdk_window_quartz_set_background (GdkWindow *window,
const GdkColor *color)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkWindowImplQuartz *impl;
-
- if (GDK_WINDOW_DESTROYED (window))
- return;
-
- impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
-
- private->bg_color = *color;
-
- if (private->bg_pixmap &&
- private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
- private->bg_pixmap != GDK_NO_BG)
- g_object_unref (private->bg_pixmap);
-
- private->bg_pixmap = NULL;
+ /* FIXME: We could theoretically set the background color for toplevels
+ * here. (Currently we draw the background before emitting expose events)
+ */
}
static void
gdk_window_quartz_set_back_pixmap (GdkWindow *window,
- GdkPixmap *pixmap,
- gboolean parent_relative)
+ GdkPixmap *pixmap)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
-
- if (GDK_WINDOW_DESTROYED (window))
- return;
-
- if (private->bg_pixmap &&
- private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
- private->bg_pixmap != GDK_NO_BG)
- g_object_unref (private->bg_pixmap);
-
- if (parent_relative)
- {
- private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
- GDK_NOTE (MISC, g_print (G_STRLOC ": setting background pixmap to parent_relative\n"));
- }
- else
- {
- if (pixmap)
- {
- g_object_ref (pixmap);
- private->bg_pixmap = pixmap;
- }
- else
- {
- private->bg_pixmap = GDK_NO_BG;
- }
- }
+ /* FIXME: Could theoretically set some background image here. (Currently
+ * the back pixmap is drawn before emitting expose events.
+ */
}
static void
gdk_window_quartz_set_cursor (GdkWindow *window,
GdkCursor *cursor)
{
- GdkWindowImplQuartz *impl;
GdkCursorPrivate *cursor_private;
NSCursor *nscursor;
- impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
cursor_private = (GdkCursorPrivate *)cursor;
if (GDK_WINDOW_DESTROYED (window))
return;
- GDK_QUARTZ_ALLOC_POOL;
-
if (!cursor)
- nscursor = NULL;
+ nscursor = [NSCursor arrowCursor];
else
- nscursor = [cursor_private->nscursor retain];
-
- if (impl->nscursor)
- [impl->nscursor release];
-
- impl->nscursor = nscursor;
+ nscursor = cursor_private->nscursor;
- GDK_QUARTZ_RELEASE_POOL;
-
- _gdk_quartz_events_update_cursor (_gdk_quartz_events_get_mouse_window (TRUE));
+ [nscursor set];
}
static void
gint *depth)
{
GdkWindowImplQuartz *impl;
+ GdkWindowObject *private;
NSRect ns_rect;
if (GDK_WINDOW_DESTROYED (window))
return;
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
+ private = GDK_WINDOW_OBJECT (window);
if (window == _gdk_root)
{
if (x)
*y = 0;
if (width)
- *width = impl->width;
+ *width = private->width;
if (height)
- *height = impl->height;
+ *height = private->height;
}
else if (WINDOW_IS_TOPLEVEL (window))
{
if (window == _gdk_root)
{
- *x = 0;
- *y = 0;
+ if (x)
+ *x = 0;
+ if (y)
+ *y = 0;
+
return 1;
}
while (private != GDK_WINDOW_OBJECT (toplevel))
{
- tmp_x += private->x;
- tmp_y += private->y;
+ if (_gdk_window_has_impl ((GdkWindow *)private))
+ {
+ tmp_x += private->x;
+ tmp_y += private->y;
+ }
private = private->parent;
}
return TRUE;
}
-gboolean
-gdk_window_get_deskrelative_origin (GdkWindow *window,
- gint *x,
- gint *y)
+static gboolean
+gdk_window_quartz_get_deskrelative_origin (GdkWindow *window,
+ gint *x,
+ gint *y)
{
- g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-
return gdk_window_get_origin (window, x, y);
}
{
GdkRectangle rect;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
rect.x = 0;
rect.y = 0;
gint x_tmp, y_tmp;
GdkWindow *found_window;
+ g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
+
if (GDK_WINDOW_DESTROYED (window))
{
*x = 0;
NSWindow *nswindow;
impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
+ private = GDK_WINDOW_OBJECT (toplevel);
nswindow = impl->toplevel;
point = [nswindow mouseLocationOutsideOfEventStream];
- x_tmp = point.x;
- y_tmp = impl->height - point.y;
- }
- /* The coords are relative to the toplevel of the passed in window
- * at this point, make them relative to the passed in window:
- */
- private = GDK_WINDOW_OBJECT (window);
- while (private != toplevel)
- {
- x_tmp -= private->x;
- y_tmp -= private->y;
+ x_tmp = point.x;
+ y_tmp = private->height - point.y;
- private = private->parent;
+ window = (GdkWindow *)toplevel;
}
found_window = _gdk_quartz_window_find_child (window, x_tmp, y_tmp);
/* Returns coordinates relative to the found window. */
GdkWindow *
-_gdk_windowing_window_at_pointer (GdkDisplay *display,
- gint *win_x,
- gint *win_y)
+_gdk_windowing_window_at_pointer (GdkDisplay *display,
+ gint *win_x,
+ gint *win_y,
+ GdkModifierType *mask)
{
- GdkModifierType mask;
GdkWindow *found_window;
gint x, y;
+ GdkModifierType tmp_mask = 0;
found_window = _gdk_windowing_window_get_pointer (display,
_gdk_root,
&x, &y,
- &mask);
+ &tmp_mask);
if (found_window)
{
GdkWindowObject *private;
*win_y = -1;
}
+ if (mask)
+ *mask = tmp_mask;
+
return found_window;
}
gdk_window_quartz_set_events (GdkWindow *window,
GdkEventMask event_mask)
{
- if (!GDK_WINDOW_DESTROYED (window))
- {
- GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
- }
+ /* The mask is set in the common code. */
}
void
gdk_window_set_urgency_hint (GdkWindow *window,
gboolean urgent)
{
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return;
+
/* FIXME: Implement */
}
{
GdkWindowImplQuartz *impl;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (geometry != NULL);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl);
{
GdkWindowImplQuartz *impl;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (title != NULL);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ WINDOW_IS_TOPLEVEL (window))
return;
impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *)window)->impl);
gdk_window_set_role (GdkWindow *window,
const gchar *role)
{
+ if (GDK_WINDOW_DESTROYED (window) ||
+ WINDOW_IS_TOPLEVEL (window))
+ return;
+
/* FIXME: Implement */
}
GdkWindowImplQuartz *window_impl;
GdkWindowImplQuartz *parent_impl;
- if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (parent))
+ if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
+ WINDOW_IS_TOPLEVEL (window))
return;
window_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
}
static void
-gdk_window_quartz_shape_combine_mask (GdkWindow *window,
- GdkBitmap *mask,
- gint x,
- gint y)
-{
- /* FIXME: Implement */
-}
-
-void
-gdk_window_input_shape_combine_mask (GdkWindow *window,
- GdkBitmap *mask,
- gint x,
- gint y)
+gdk_window_quartz_input_shape_combine_region (GdkWindow *window,
+ const GdkRegion *shape_region,
+ gint offset_x,
+ gint offset_y)
{
/* FIXME: Implement */
}
-void
-gdk_window_input_shape_combine_region (GdkWindow *window,
- const GdkRegion *shape_region,
- gint offset_x,
- gint offset_y)
-{
- /* FIXME: Implement */
-}
-
-void
-gdk_window_set_child_input_shapes (GdkWindow *window)
-{
- /* FIXME: IMplement */
-}
-
void
gdk_window_set_override_redirect (GdkWindow *window,
gboolean override_redirect)
{
GdkWindowObject *private;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
private = (GdkWindowObject *)window;
private->accept_focus = accept_focus != FALSE;
}
-static void
-gdk_window_quartz_set_child_shapes (GdkWindow *window)
-{
- /* FIXME: Implement */
-}
-
-static void
-gdk_window_quartz_merge_child_shapes (GdkWindow *window)
-{
- /* FIXME: Implement */
-}
-
-void
-gdk_window_merge_child_input_shapes (GdkWindow *window)
-{
- /* FIXME: Implement */
-}
-
static gboolean
gdk_window_quartz_set_static_gravities (GdkWindow *window,
gboolean use_static)
{
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return FALSE;
+
/* FIXME: Implement */
return FALSE;
}
{
GdkWindowObject *private;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
private = (GdkWindowObject *)window;
private->focus_on_map = focus_on_map != FALSE;
GdkPixmap *pixmap,
GdkBitmap *mask)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
/* FIXME: Implement */
}
gdk_window_set_icon_name (GdkWindow *window,
const gchar *name)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
/* FIXME: Implement */
}
GdkWindowObject *private;
GdkWindowImplQuartz *impl;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
private = (GdkWindowObject*) window;
impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
- if (impl->toplevel)
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return;
+
+ if (private->accept_focus && private->window_type != GDK_WINDOW_TEMP)
{
- if (private->accept_focus && private->window_type != GDK_WINDOW_TEMP)
- {
- GDK_QUARTZ_ALLOC_POOL;
- [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
- clear_toplevel_order ();
- GDK_QUARTZ_RELEASE_POOL;
- }
+ GDK_QUARTZ_ALLOC_POOL;
+ [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
+ clear_toplevel_order ();
+ GDK_QUARTZ_RELEASE_POOL;
}
}
{
GdkWindowImplQuartz *impl;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl);
GdkWindowTypeHint
gdk_window_get_type_hint (GdkWindow *window)
{
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return GDK_WINDOW_TYPE_HINT_NORMAL;
return GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl)->type_hint;
gdk_window_set_modal_hint (GdkWindow *window,
gboolean modal)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return;
/* FIXME: Implement */
}
gdk_window_set_skip_taskbar_hint (GdkWindow *window,
gboolean skips_taskbar)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return;
/* FIXME: Implement */
}
gdk_window_set_skip_pager_hint (GdkWindow *window,
gboolean skips_pager)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return;
/* FIXME: Implement */
}
GdkWindowObject *private;
GdkWindowImplQuartz *impl;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
private = GDK_WINDOW_OBJECT (window);
GdkWindowImplQuartz *impl;
NSRect ns_rect;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (rect != NULL);
private = GDK_WINDOW_OBJECT (window);
rect->width = 1;
rect->height = 1;
- if (GDK_WINDOW_DESTROYED (window))
- return;
-
toplevel = gdk_window_get_toplevel (window);
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl);
int old_mask, new_mask;
NSView *old_view;
- g_return_if_fail (GDK_IS_WINDOW (window));
- g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
{
GdkWindowImplQuartz *impl;
- g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
- g_return_val_if_fail (WINDOW_IS_TOPLEVEL (window), FALSE);
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return FALSE;
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
/* FIXME: Implement */
}
-static void
-gdk_window_quartz_get_offsets (GdkWindow *window,
- gint *x_offset,
- gint *y_offset)
-{
- *x_offset = *y_offset = 0;
-}
-
gboolean
_gdk_windowing_window_queue_antiexpose (GdkWindow *window,
GdkRegion *area)
void
gdk_window_stick (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return;
}
void
gdk_window_unstick (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return;
}
void
{
GdkWindowImplQuartz *impl;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
{
GdkWindowImplQuartz *impl;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
{
GdkWindowImplQuartz *impl;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
-
+
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
if (GDK_WINDOW_IS_MAPPED (window))
{
GdkWindowImplQuartz *impl;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
{
FullscreenSavedGeometry *geometry;
GdkWindowObject *private = (GdkWindowObject *) window;
- GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
NSRect frame;
- g_return_if_fail (GDK_IS_WINDOW (window));
- g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return;
geometry = get_fullscreen_geometry (window);
if (!geometry)
geometry->x = private->x;
geometry->y = private->y;
- geometry->width = impl->width;
- geometry->height = impl->height;
+ geometry->width = private->width;
+ geometry->height = private->height;
if (!gdk_window_get_decorations (window, &geometry->decor))
geometry->decor = GDK_DECOR_ALL;
{
FullscreenSavedGeometry *geometry;
- g_return_if_fail (GDK_IS_WINDOW (window));
- g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return;
geometry = get_fullscreen_geometry (window);
if (geometry)
gint level;
g_return_if_fail (GDK_IS_WINDOW (window));
- g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
level = window_type_hint_to_level (gdk_window_get_type_hint (window));
gint level;
g_return_if_fail (GDK_IS_WINDOW (window));
- g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
level = window_type_hint_to_level (gdk_window_get_type_hint (window));
GdkWindow *
gdk_window_get_group (GdkWindow *window)
{
- g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return NULL;
+
/* FIXME: Implement */
return NULL;
void
gdk_window_destroy_notify (GdkWindow *window)
{
+ check_grab_destroy (window);
}
void
gdk_window_beep (GdkWindow *window)
{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
gdk_display_beep (_gdk_display);
}
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (opacity < 0)
iface->withdraw = gdk_window_quartz_withdraw;
iface->set_events = gdk_window_quartz_set_events;
iface->get_events = gdk_window_quartz_get_events;
- iface->clear_area = gdk_window_quartz_clear_area;
iface->raise = gdk_window_quartz_raise;
iface->lower = gdk_window_quartz_lower;
iface->move_resize = gdk_window_quartz_move_resize;
- iface->scroll = _gdk_quartz_window_scroll;
- iface->move_region = _gdk_quartz_window_move_region;
iface->set_background = gdk_window_quartz_set_background;
iface->set_back_pixmap = gdk_window_quartz_set_back_pixmap;
iface->reparent = gdk_window_quartz_reparent;
iface->set_cursor = gdk_window_quartz_set_cursor;
iface->get_geometry = gdk_window_quartz_get_geometry;
iface->get_origin = gdk_window_quartz_get_origin;
- iface->shape_combine_mask = gdk_window_quartz_shape_combine_mask;
+ iface->get_deskrelative_origin = gdk_window_quartz_get_deskrelative_origin;
iface->shape_combine_region = gdk_window_quartz_shape_combine_region;
- iface->set_child_shapes = gdk_window_quartz_set_child_shapes;
- iface->merge_child_shapes = gdk_window_quartz_merge_child_shapes;
+ iface->input_shape_combine_region = gdk_window_quartz_input_shape_combine_region;
iface->set_static_gravities = gdk_window_quartz_set_static_gravities;
- iface->get_offsets = gdk_window_quartz_get_offsets;
+ iface->queue_antiexpose = _gdk_quartz_window_queue_antiexpose;
+ iface->queue_translation = _gdk_quartz_window_queue_translation;
+ iface->destroy = _gdk_quartz_window_destroy;
}
{
GdkDrawableImplQuartz parent_instance;
- gint width;
- gint height;
-
NSWindow *toplevel;
NSTrackingRectTag tracking_rect;
GdkQuartzView *view;
GdkWindowTypeHint type_hint;
- NSCursor *nscursor;
-
GdkRegion *paint_clip_region;
gint begin_paint_count;
gint in_paint_rect_count;
g_assert (display == NULL || _gdk_display == display);
}
+gulong
+_gdk_windowing_window_get_next_serial (GdkDisplay *display)
+{
+ return 0;
+}
+
#ifdef HAVE_MONITOR_INFO
static BOOL CALLBACK
count_monitor (HMONITOR hmonitor,
_gdk_visual_init ();
gdk_screen_set_default_colormap (_gdk_screen,
gdk_screen_get_system_colormap (_gdk_screen));
- _gdk_windowing_window_init ();
+ _gdk_windowing_window_init (_gdk_screen);
_gdk_windowing_image_init ();
_gdk_events_init ();
_gdk_input_init (_gdk_display);
static void gdk_win32_draw_drawable (GdkDrawable *drawable,
GdkGC *gc,
GdkPixmap *src,
+ GdkDrawable *original_src,
gint xsrc,
gint ysrc,
gint xdest,
gdk_win32_draw_drawable (GdkDrawable *drawable,
GdkGC *gc,
GdkPixmap *src,
+ GdkDrawable *original_src,
gint xsrc,
gint ysrc,
gint xdest,
else
g_assert_not_reached ();
+ if (GDK_IS_WINDOW_IMPL_WIN32 (draw_impl) &&
+ GDK_IS_PIXMAP_IMPL_WIN32 (src_impl))
+ {
+ GdkPixmapImplWin32 *src_pixmap = GDK_PIXMAP_IMPL_WIN32 (src_impl);
+
+ if (xsrc < 0)
+ {
+ width += xsrc;
+ xdest -= xsrc;
+ xsrc = 0;
+ }
+
+ if (ysrc < 0)
+ {
+ height += ysrc;
+ ydest -= ysrc;
+ ysrc = 0;
+ }
+
+ if (xsrc + width > src_pixmap->width)
+ width = src_pixmap->width - xsrc;
+ if (ysrc + height > src_pixmap->height)
+ height = src_pixmap->height - ysrc;
+ }
+
hdc = gdk_win32_hdc_get (&draw_impl->parent_instance, gc, GDK_GC_FOREGROUND);
gdk_drawable_get_size (src, &src_width, &src_height);
if ((src_rgn = CreateRectRgn (0, 0, src_width + 1, src_height + 1)) == NULL)
- WIN32_GDI_FAILED ("CreateRectRgn");
+ {
+ WIN32_GDI_FAILED ("CreateRectRgn");
+ }
else if ((draw_rgn = CreateRectRgn (xsrc, ysrc,
xsrc + width + 1,
ysrc + height + 1)) == NULL)
- WIN32_GDI_FAILED ("CreateRectRgn");
+ {
+ WIN32_GDI_FAILED ("CreateRectRgn");
+ }
else
{
if (GDK_IS_WINDOW_IMPL_WIN32 (draw_impl))
xsrc, ysrc, xdest, ydest, width, height);
else
blit_from_window (hdc, GDK_GC_WIN32 (gc), src_impl, xsrc, ysrc, xdest, ydest, width, height);
+
gdk_win32_hdc_release (&draw_impl->parent_instance, gc, GDK_GC_FOREGROUND);
}
return impl->hdc;
}
else
- return NULL;
+ {
+ return NULL;
+ }
}
/**
}
}
+cairo_surface_t *
+_gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
+ gint width,
+ gint height)
+{
+ GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
+ RECT rect;
+
+ HDC hdc = _gdk_win32_drawable_acquire_dc (drawable);
+ if (!hdc)
+ {
+ return NULL;
+ }
+
+ GetClipBox (hdc, &rect);
+ g_print ("create_cairo_surface(): [%d %d %d %d]\n",
+ rect.left, rect.top, rect.right, rect.bottom);
+
+ return cairo_win32_surface_create (hdc);
+}
+
static void
gdk_win32_cairo_surface_destroy (void *data)
{
if (!impl->cairo_surface)
{
- HDC hdc = _gdk_win32_drawable_acquire_dc (drawable);
- if (!hdc)
- return NULL;
-
- impl->cairo_surface = cairo_win32_surface_create (hdc);
+ // On Win32 cairo surface, width and height are determined from the DC
+ impl->cairo_surface = _gdk_windowing_create_cairo_surface (drawable, 0, 0);
cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
drawable, gdk_win32_cairo_surface_destroy);
}
else
- cairo_surface_reference (impl->cairo_surface);
+ {
+ cairo_surface_reference (impl->cairo_surface);
+ }
return impl->cairo_surface;
}
+void
+_gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
+ gint width,
+ gint height)
+{
+ // Do nothing. The surface size is determined by the DC
+ g_print ("*** set_cairo_surface_size()\n");
+}
+
static gint
gdk_win32_get_depth (GdkDrawable *drawable)
{
if (impl->cairo_surface)
{
cairo_surface_finish (impl->cairo_surface);
- cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
- NULL, NULL);
+ cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key, NULL, NULL);
}
+
+ g_print ("hdc_count == %d\n", impl->hdc_count);
- g_assert (impl->hdc_count == 0);
+ //g_assert (impl->hdc_count == 0);
}
struct _GdkDrawableImplWin32Class
{
GdkDrawableClass parent_class;
-
};
GType gdk_drawable_impl_win32_get_type (void);
/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Copyright (C) 1998-2002 Tor Lillqvist
- * Copyright (C) 2007-2008 Cody Russell
+ * Copyright (C) 2007-2009 Cody Russell
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
/* Private variable declarations
*/
+#if 0
static GdkWindow *p_grab_window = NULL; /* Window that currently holds
* the pointer grab
*/
static GdkWindow *k_grab_window = NULL; /* Window the holds the
* keyboard grab
*/
+#endif
static GList *client_filters; /* Filters for client messages */
GdkCursor *cursor,
guint32 time)
{
- HCURSOR hcursor;
- GdkCursorPrivate *cursor_private;
- gint return_val = GDK_GRAB_SUCCESS;
+ GdkWindow *native;
- g_return_val_if_fail (window != NULL, 0);
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
-
- cursor_private = (GdkCursorPrivate*) cursor;
-
- if (!cursor)
- hcursor = NULL;
- else if ((hcursor = CopyCursor (cursor_private->hcursor)) == NULL)
- WIN32_API_FAILED ("CopyCursor");
-
- return_val = _gdk_input_grab_pointer (window,
- owner_events,
- event_mask,
- confine_to,
- time);
-
- if (return_val == GDK_GRAB_SUCCESS)
- {
- if (!GDK_WINDOW_DESTROYED (window))
- {
- GDK_NOTE (EVENTS, g_print ("%sgdk_pointer_grab: %p %s %p %s%s",
- (debug_indent > 0 ? "\n" : ""),
- GDK_WINDOW_HWND (window),
- (owner_events ? "TRUE" : "FALSE"),
- hcursor,
- event_mask_string (event_mask),
- (debug_indent == 0 ? "\n" : "")));
-
- p_grab_mask = event_mask;
- p_grab_owner_events = owner_events;
- p_grab_automatic = FALSE;
-
- SetCapture (GDK_WINDOW_HWND (window));
- return_val = GDK_GRAB_SUCCESS;
- }
- else
- return_val = GDK_GRAB_ALREADY_GRABBED;
- }
-
- if (return_val == GDK_GRAB_SUCCESS)
- {
- GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl);
-
- if (p_grab_window != NULL && p_grab_window != window)
- generate_grab_broken_event (p_grab_window, FALSE, window);
-
- assign_object (&p_grab_window, window);
-
- if (p_grab_cursor != NULL)
- {
- if (GetCursor () == p_grab_cursor)
- SetCursor (NULL);
- DestroyCursor (p_grab_cursor);
- }
- p_grab_cursor = hcursor;
+ native = gdk_window_get_toplevel (window);
- if (p_grab_cursor != NULL)
- SetCursor (p_grab_cursor);
- else if (impl->hcursor != NULL)
- SetCursor (impl->hcursor);
- else
- SetCursor (LoadCursor (NULL, IDC_ARROW));
-
- if (confine_to != NULL)
- {
- gint x, y, width, height;
- RECT rect;
+ if (!GDK_IS_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (native)->impl))
+ return GDK_GRAB_SUCCESS;
- gdk_window_get_origin (confine_to, &x, &y);
- gdk_drawable_get_size (confine_to, &width, &height);
+ if (!_gdk_window_has_impl (window) &&
+ !gdk_window_is_viewable (window))
+ return GDK_GRAB_NOT_VIEWABLE;
- x -= _gdk_offset_x;
- y -= _gdk_offset_y;
-
- rect.left = x;
- rect.top = y;
- rect.right = x + width;
- rect.bottom = y + height;
- API_CALL (ClipCursor, (&rect));
- p_grab_confine_to = confine_to;
- }
+ _gdk_display_add_pointer_grab (_gdk_display,
+ window,
+ native,
+ owner_events,
+ event_mask,
+ 0,
+ time,
+ FALSE);
- /* FIXME: Generate GDK_CROSSING_GRAB events */
- }
-
- return return_val;
+ return GDK_GRAB_SUCCESS;
}
void
gdk_display_pointer_ungrab (GdkDisplay *display,
guint32 time)
{
- g_return_if_fail (display == _gdk_display);
-
- GDK_NOTE (EVENTS, g_print ("%sgdk_display_pointer_ungrab%s",
- (debug_indent > 0 ? "\n" : ""),
- (debug_indent == 0 ? "\n" : "")));
-
- _gdk_input_ungrab_pointer (time);
-
- if (GetCapture () != NULL)
- ReleaseCapture ();
+ GdkPointerGrabInfo *info;
- /* FIXME: Generate GDK_CROSSING_UNGRAB events */
-
- assign_object (&p_grab_window, NULL);
- if (p_grab_cursor != NULL)
- {
- if (GetCursor () == p_grab_cursor)
- SetCursor (NULL);
- DestroyCursor (p_grab_cursor);
- p_grab_cursor = NULL;
- }
+ info = _gdk_display_get_last_pointer_grab (display);
+ if (info)
+ info->serial_end = 0;
- if (p_grab_confine_to != NULL)
- {
- API_CALL (ClipCursor, (NULL));
- p_grab_confine_to = NULL;
- }
+ _gdk_display_pointer_grab_update (display, 0);
}
static GdkWindow *
GetClientRect (hwnd, &rect);
ScreenToClient (hwnd, &pt);
if (!PtInRect (&rect, pt))
- return _gdk_root;
+ {
+ g_print ("find_real_window_for_grabbed_mouse_event(), PtInRect() failed\n");
+ return _gdk_root;
+ }
other_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd);
}
if (other_window == NULL)
- return _gdk_root;
+ {
+ g_print ("find_real_window_for_grabbed_mouse_event(), other_window == NULL\n");
+ return _gdk_root;
+ }
return other_window;
}
find_window_for_mouse_event (GdkWindow* reported_window,
MSG* msg)
{
- if (p_grab_window == NULL || !p_grab_owner_events)
+ GdkPointerGrabInfo *info = _gdk_display_get_last_pointer_grab (_gdk_display);
+
+ if (!info || !info->window || !info->owner_events)
return reported_window;
else
return find_real_window_for_grabbed_mouse_event (reported_window, msg);
}
-gboolean
-gdk_display_pointer_is_grabbed (GdkDisplay *display)
-{
- g_return_val_if_fail (display == _gdk_display, FALSE);
- GDK_NOTE (EVENTS, g_print ("gdk_pointer_is_grabbed: %s\n",
- p_grab_window != NULL ? "TRUE" : "FALSE"));
- return p_grab_window != NULL;
-}
-
-gboolean
-gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
- GdkWindow **grab_window,
- gboolean *owner_events)
-{
- g_return_val_if_fail (display == _gdk_display, FALSE);
-
- if (p_grab_window != NULL)
- {
- if (grab_window)
- *grab_window = p_grab_window;
- if (owner_events)
- *owner_events = p_grab_owner_events;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
GdkGrabStatus
gdk_keyboard_grab (GdkWindow *window,
gboolean owner_events,
guint32 time)
{
- GdkWindow *real_focus_window, *grab_focus_window;
+ GdkDisplay *display;
+ GdkWindow *toplevel;
- gint return_val;
-
g_return_val_if_fail (window != NULL, 0);
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
GDK_NOTE (EVENTS, g_print ("gdk_keyboard_grab %p%s\n",
GDK_WINDOW_HWND (window), owner_events ? " OWNER_EVENTS" : ""));
- if (!GDK_WINDOW_DESTROYED (window))
- {
- k_grab_owner_events = owner_events;
- return_val = GDK_GRAB_SUCCESS;
- }
- else
- return_val = GDK_GRAB_ALREADY_GRABBED;
-
- if (return_val == GDK_GRAB_SUCCESS)
- {
- if (k_grab_window != NULL && k_grab_window != window)
- generate_grab_broken_event (k_grab_window, TRUE, window);
+ display = gdk_drawable_get_display (window);
+ toplevel = gdk_window_get_toplevel (window);
- assign_object (&k_grab_window, window);
+ _gdk_display_set_has_keyboard_grab (display,
+ window,
+ toplevel,
+ owner_events,
+ 0,
+ time);
- if (!k_grab_owner_events)
- {
- real_focus_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) GetFocus ());
- if (real_focus_window)
- real_focus_window = gdk_window_get_toplevel (real_focus_window);
- grab_focus_window = gdk_window_get_toplevel (k_grab_window);
- if (real_focus_window != grab_focus_window)
- {
- /* Generate events for focus change from the window that really
- * has focus to the grabber.
- */
- if (real_focus_window && !GDK_WINDOW_DESTROYED (real_focus_window)
- && (((GdkWindowObject *) real_focus_window)->event_mask
- & GDK_FOCUS_CHANGE_MASK))
- generate_focus_event (real_focus_window, FALSE);
-
- if (((GdkWindowObject *) grab_focus_window)->event_mask
- & GDK_FOCUS_CHANGE_MASK)
- generate_focus_event (grab_focus_window, TRUE);
- }
- }
- }
-
- return return_val;
+ return GDK_GRAB_SUCCESS;
}
void
gdk_display_keyboard_ungrab (GdkDisplay *display,
guint32 time)
{
- GdkWindow *real_focus_window, *grab_focus_window;
-
- g_return_if_fail (display == _gdk_display);
-
GDK_NOTE (EVENTS, g_print ("gdk_display_keyboard_ungrab\n"));
-
- if (k_grab_window && !k_grab_owner_events)
- {
- real_focus_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) GetFocus ());
- if (real_focus_window)
- real_focus_window = gdk_window_get_toplevel (real_focus_window);
- if (!GDK_WINDOW_DESTROYED (k_grab_window))
- grab_focus_window = gdk_window_get_toplevel (k_grab_window);
- else
- grab_focus_window = NULL;
- if (real_focus_window != grab_focus_window)
- {
- /* Generate events for focus change from grabber to the window that
- * really has focus. Important for example if a new window is created
- * while focus is grabbed.
- */
- if (grab_focus_window
- && (((GdkWindowObject *) grab_focus_window)->event_mask
- & GDK_FOCUS_CHANGE_MASK))
- generate_focus_event (grab_focus_window, FALSE);
-
- if (real_focus_window && !GDK_WINDOW_DESTROYED (real_focus_window)
- && (((GdkWindowObject *) real_focus_window)->event_mask
- & GDK_FOCUS_CHANGE_MASK))
- generate_focus_event (real_focus_window, TRUE);
- }
- }
-
- assign_object (&k_grab_window, NULL);
-}
-
-gboolean
-gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
- GdkWindow **grab_window,
- gboolean *owner_events)
-{
- g_return_val_if_fail (display == _gdk_display, FALSE);
-
- if (k_grab_window)
- {
- if (grab_window)
- *grab_window = k_grab_window;
- if (owner_events)
- *owner_events = k_grab_owner_events;
-
- return TRUE;
- }
- else
- return FALSE;
+ _gdk_display_unset_has_keyboard_grab (display, FALSE);
}
void
gdk_add_client_message_filter (message_type, func, data);
}
-void
+void
gdk_add_client_message_filter (GdkAtom message_type,
GdkFilterFunc func,
gpointer data)
gint y)
{
GdkEvent *event;
- gint xoffset, yoffset;
event = gdk_event_new (type);
event->crossing.window = window;
event->crossing.subwindow = NULL;
event->crossing.time = _gdk_win32_get_next_tick (msg->time);
- _gdk_win32_windowing_window_get_offsets (window, &xoffset, &yoffset);
- event->crossing.x = x + xoffset;
- event->crossing.y = y + yoffset;
+ event->crossing.x = x;
+ event->crossing.y = y;
event->crossing.x_root = msg->pt.x + _gdk_offset_x;
event->crossing.y_root = msg->pt.y + _gdk_offset_y;
event->crossing.mode = mode;
event->crossing.detail = detail;
event->crossing.focus = TRUE; /* FIXME: Set correctly */
event->crossing.state = 0; /* FIXME: Set correctly */
-
+
append_event (event);
if (type == GDK_ENTER_NOTIFY &&
GdkNotifyType detail)
{
POINT pt;
+ GdkPointerGrabInfo *grab;
+
+ grab = _gdk_display_get_last_pointer_grab (_gdk_display);
- if (p_grab_window != NULL && !p_grab_owner_events && !(p_grab_mask & GDK_LEAVE_NOTIFY_MASK))
+ if (grab && grab->window != NULL && !grab->owner_events && !(grab->event_mask & GDK_LEAVE_NOTIFY_MASK))
return;
if (!(((GdkWindowObject *) window)->event_mask & GDK_LEAVE_NOTIFY_MASK))
GdkNotifyType detail)
{
POINT pt;
+ GdkPointerGrabInfo *grab;
- if (p_grab_window != NULL && !p_grab_owner_events && !(p_grab_mask & GDK_ENTER_NOTIFY_MASK))
+ grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+
+ if (grab && grab->window != NULL && !grab->owner_events && !(grab->event_mask & GDK_ENTER_NOTIFY_MASK))
return;
if (!(((GdkWindowObject *) window)->event_mask & GDK_ENTER_NOTIFY_MASK))
if (prev != from)
synthesize_enter_events (from, prev, msg, mode, detail);
+
synthesize_enter_event (to, msg, mode, detail);
}
GdkWindow *next = gdk_window_get_parent (from);
synthesize_leave_event (from, msg, mode, detail);
+
if (next != to)
synthesize_leave_events (next, to, msg, mode, detail);
}
{
RECT client_rect;
POINT point;
+ GdkWindowObject *window_object;
GetClientRect (msg->hwnd, &client_rect);
point.x = client_rect.left; /* always 0 */
point.y = client_rect.top;
+
/* top level windows need screen coords */
if (gdk_window_get_parent (window) == _gdk_root)
{
point.y += _gdk_offset_y;
}
- GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->width = client_rect.right - client_rect.left;
- GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->height = client_rect.bottom - client_rect.top;
+ window_object = GDK_WINDOW_OBJECT (window);
+
+ window_object->width = client_rect.right - client_rect.left;
+ window_object->height = client_rect.bottom - client_rect.top;
- ((GdkWindowObject *) window)->x = point.x;
- ((GdkWindowObject *) window)->y = point.y;
+ window_object->x = point.x;
+ window_object->y = point.y;
+
+ _gdk_window_update_size (window);
- if (((GdkWindowObject *) window)->event_mask & GDK_STRUCTURE_MASK)
+ if (window_object->event_mask & GDK_STRUCTURE_MASK)
{
GdkEvent *event = gdk_event_new (GDK_CONFIGURE);
HDC hdc;
PAINTSTRUCT paintstruct;
GdkRegion *update_region;
- gint xoffset, yoffset;
if (GetUpdateRgn (msg->hwnd, hrgn, FALSE) == ERROR)
{
update_region = _gdk_win32_hrgn_to_region (hrgn);
- _gdk_win32_windowing_window_get_offsets (window, &xoffset, &yoffset);
- gdk_region_offset (update_region, xoffset, yoffset);
-
+
+ //_gdk_win32_windowing_window_get_offsets (window, &xoffset, &yoffset);
+ //gdk_region_offset (update_region, xoffset, yoffset);
+
_gdk_window_process_expose (window, update_region);
gdk_region_destroy (update_region);
MSG *msg)
{
GdkEvent *event = gdk_event_new (type);
- gint xoffset, yoffset;
event->button.window = window;
event->button.time = _gdk_win32_get_next_tick (msg->time);
translate_mouse_coords (orig_window, window, msg);
event->button.x = current_x = (gint16) GET_X_LPARAM (msg->lParam);
event->button.y = current_y = (gint16) GET_Y_LPARAM (msg->lParam);
- _gdk_win32_windowing_window_get_offsets (window, &xoffset, &yoffset);
- event->button.x += xoffset;
- event->button.y += yoffset;
event->button.x_root = msg->pt.x + _gdk_offset_x;
event->button.y_root = msg->pt.y + _gdk_offset_y;
event->button.axes = NULL;
GdkWindowImplWin32 *impl;
GdkWindow *orig_window, *new_window;
- gint xoffset, yoffset;
+
+ GdkPointerGrabInfo *grab = NULL;
+ GdkWindow *grab_window = NULL;
+ guint grab_mask = 0;
+ gboolean grab_owner_events = FALSE;
static gint update_colors_counter = 0;
gint button;
/* Let the system handle Alt-Tab, Alt-Space and Alt-F4 unless
* the keyboard is grabbed.
*/
- if (k_grab_window == NULL &&
+ if (_gdk_display->keyboard_grab.window == NULL &&
(msg->wParam == VK_TAB ||
msg->wParam == VK_SPACE ||
msg->wParam == VK_F4))
break;
if (!propagate (&window, msg,
- k_grab_window, k_grab_owner_events, GDK_ALL_EVENTS_MASK,
+ _gdk_display->keyboard_grab.window,
+ _gdk_display->keyboard_grab.owner_events,
+ GDK_ALL_EVENTS_MASK,
doesnt_want_key, FALSE))
break;
break;
if (!propagate (&window, msg,
- k_grab_window, k_grab_owner_events, GDK_ALL_EVENTS_MASK,
+ _gdk_display->keyboard_grab.window,
+ _gdk_display->keyboard_grab.owner_events,
+ GDK_ALL_EVENTS_MASK,
doesnt_want_char, FALSE))
break;
assign_object (&window, find_window_for_mouse_event (window, msg));
- if (p_grab_window != NULL)
+ grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+ if (grab)
+ {
+ grab_window = grab->window;
+ grab_mask = grab->event_mask;
+ grab_owner_events = grab->owner_events;
+ }
+
+ if (grab_window != NULL)
{
GdkWindow *real_window = find_real_window_for_grabbed_mouse_event (window, msg);
if (real_window != current_window)
- synthesize_crossing_events (real_window, GDK_CROSSING_NORMAL, msg);
+ {
+ synthesize_crossing_events (real_window, GDK_CROSSING_NORMAL, msg);
+ }
}
else
{
if (window != current_window)
- synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
+ {
+ synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
+ }
}
- if (!propagate (&window, msg,
- p_grab_window, p_grab_owner_events, p_grab_mask,
+ if (!propagate (&window, msg, grab_window, grab_owner_events, grab_mask,
doesnt_want_button_press, TRUE))
break;
break;
/* Emulate X11's automatic active grab */
- if (!p_grab_window)
+ /* XXX: Do we still want this with CSW? -- Cody */
+ if (!grab_window)
{
/* No explicit active grab, let's start one automatically */
GDK_NOTE (EVENTS, g_print (" (automatic grab)"));
p_grab_automatic = TRUE;
}
+ g_print ("generate_button_event()\n");
+
generate_button_event (GDK_BUTTON_PRESS, button,
window, orig_window, msg);
assign_object (&window, find_window_for_mouse_event (window, msg));
- if (p_grab_window != NULL)
+ grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+ if (grab != NULL)
+ {
+ grab_window = grab->window;
+ grab_owner_events = grab->owner_events;
+ grab_mask = grab->event_mask;
+ }
+
+ if (grab_window != NULL)
{
GdkWindow *real_window = find_real_window_for_grabbed_mouse_event (window, msg);
}
#endif
- if (!propagate (&window, msg,
- p_grab_window, p_grab_owner_events, p_grab_mask,
- doesnt_want_button_release, TRUE))
+ if (!propagate (&window, msg, grab_window, grab_owner_events,
+ grab_mask, doesnt_want_button_release, TRUE))
{
}
else if (!GDK_WINDOW_DESTROYED (window))
window, orig_window, msg);
}
- if (p_grab_window != NULL &&
- p_grab_automatic &&
- (msg->wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) == 0)
+ if (grab_window != NULL && p_grab_automatic &&
+ (msg->wParam && (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) == 0)
{
- /* Terminate automatic grab */
gdk_pointer_ungrab (0);
}
assign_object (&window, find_window_for_mouse_event (window, msg));
- if (p_grab_window != NULL)
+ if (window != current_window)
+ synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
+
+ GdkPointerGrabInfo *grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+ if (grab != NULL)
+ {
+ grab_window = grab->window;
+ grab_owner_events = grab->owner_events;
+ grab_mask = grab->event_mask;
+ }
+
+ if (grab_window != NULL)
{
GdkWindow *real_window = find_real_window_for_grabbed_mouse_event (window, msg);
if (real_window != current_window)
{
- if (p_grab_owner_events)
+ if (grab_owner_events)
{
synthesize_crossing_events (real_window, GDK_CROSSING_NORMAL, msg);
}
- else if (current_window == p_grab_window)
+ else if (current_window == grab_window)
{
- synthesize_leave_event (p_grab_window, msg, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR);
+ synthesize_leave_event (grab_window, msg, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR);
assign_object (¤t_window, _gdk_root);
}
- else if (real_window == p_grab_window)
+ else if (real_window == grab_window)
{
- synthesize_enter_event (p_grab_window, msg, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR);
- assign_object (¤t_window, p_grab_window);
+ synthesize_enter_event (grab_window, msg, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR);
+ assign_object (¤t_window, grab_window);
}
}
}
else
{
if (window != current_window)
- synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
+ {
+ synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
+ }
}
- if (!propagate (&window, msg,
- p_grab_window, p_grab_owner_events, p_grab_mask,
+#if 0 // XXX - this seems to always block us from creating motion notify events -- Cody
+ if (!propagate (&window, msg, grab_window, grab_owner_events, grab_mask,
doesnt_want_button_motion, TRUE))
- break;
+ {
+ break;
+ }
+#endif
if (GDK_WINDOW_DESTROYED (window))
break;
if (window != orig_window)
- translate_mouse_coords (orig_window, window, msg);
+ {
+ translate_mouse_coords (orig_window, window, msg);
+ }
event = gdk_event_new (GDK_MOTION_NOTIFY);
event->motion.window = window;
event->motion.time = _gdk_win32_get_next_tick (msg->time);
event->motion.x = current_x = (gint16) GET_X_LPARAM (msg->lParam);
event->motion.y = current_y = (gint16) GET_Y_LPARAM (msg->lParam);
- _gdk_win32_windowing_window_get_offsets (window, &xoffset, &yoffset);
- event->motion.x += xoffset;
- event->motion.y += yoffset;
event->motion.x_root = current_root_x;
event->motion.y_root = current_root_y;
event->motion.axes = NULL;
assign_object (&window, new_window);
}
- if (!propagate (&window, msg,
- p_grab_window, p_grab_owner_events, p_grab_mask,
- doesnt_want_scroll, TRUE))
+ grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+ if (grab != NULL)
+ {
+ grab_window = grab->window;
+ grab_mask = grab->event_mask;
+ grab_owner_events = grab->owner_events;
+ }
+
+ if (!propagate (&window, msg, grab_window,
+ grab_owner_events,
+ grab_mask,
+ doesnt_want_scroll,
+ TRUE))
break;
if (GDK_WINDOW_DESTROYED (window))
event->scroll.direction = (((short) HIWORD (msg->wParam)) > 0) ?
GDK_SCROLL_UP : GDK_SCROLL_DOWN;
event->scroll.time = _gdk_win32_get_next_tick (msg->time);
- _gdk_win32_windowing_window_get_offsets (window, &xoffset, &yoffset);
- event->scroll.x = (gint16) point.x + xoffset;
- event->scroll.y = (gint16) point.y + yoffset;
+ event->scroll.x = (gint16) point.x;
+ event->scroll.y = (gint16) point.y;
event->scroll.x_root = (gint16) GET_X_LPARAM (msg->lParam) + _gdk_offset_x;
event->scroll.y_root = (gint16) GET_Y_LPARAM (msg->lParam) + _gdk_offset_y;
event->scroll.state = build_pointer_event_state (msg);
break;
case WM_KILLFOCUS:
- if (p_grab_window != NULL && !GDK_WINDOW_DESTROYED (p_grab_window))
- generate_grab_broken_event (p_grab_window, FALSE, NULL);
-
- if (k_grab_window != NULL && !GDK_WINDOW_DESTROYED (k_grab_window)
- && k_grab_window != p_grab_window)
- generate_grab_broken_event (k_grab_window, TRUE, NULL);
+ if (_gdk_display->keyboard_grab.window != NULL &&
+ !GDK_WINDOW_DESTROYED (_gdk_display->keyboard_grab.window))
+ {
+ generate_grab_broken_event (_gdk_display->keyboard_grab.window, FALSE, NULL);
+ }
/* fallthrough */
case WM_SETFOCUS:
- if (k_grab_window != NULL && !k_grab_owner_events)
+ if (_gdk_display->keyboard_grab.window != NULL &&
+ !_gdk_display->keyboard_grab.owner_events)
break;
if (!(((GdkWindowObject *) window)->event_mask & GDK_FOCUS_CHANGE_MASK))
GDK_NOTE (EVENTS, g_print (" %#x %#x",
LOWORD (msg->lParam), HIWORD (msg->lParam)));
- if (p_grab_window == NULL && LOWORD (msg->lParam) != HTCLIENT)
+ grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+ if (grab != NULL)
+ {
+ grab_window = grab->window;
+ }
+
+ if (grab_window == NULL && LOWORD (msg->lParam) != HTCLIENT)
break;
- if (p_grab_window != NULL && p_grab_cursor != NULL)
+ if (grab_window != NULL && p_grab_cursor != NULL)
hcursor = p_grab_cursor;
else if (!GDK_WINDOW_DESTROYED (window))
hcursor = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->hcursor;
SetForegroundWindow (GDK_WINDOW_HWND (impl->transient_owner));
}
- if (p_grab_window == window)
+ grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+ if (grab != NULL)
{
- gdk_pointer_ungrab (msg->time);
+ if (grab->window == window)
+ gdk_pointer_ungrab (msg->time);
}
- if (k_grab_window == window)
- {
- gdk_keyboard_ungrab (msg->time);
- }
+ if (_gdk_display->keyboard_grab.window == window)
+ gdk_keyboard_ungrab (msg->time);
}
return_val = TRUE;
if (msg->wParam == SIZE_MINIMIZED)
{
/* Don't generate any GDK event. This is *not* an UNMAP. */
-
- if (p_grab_window == window)
- gdk_pointer_ungrab (msg->time);
-
- if (k_grab_window == window)
+ grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+ if (grab != NULL)
+ {
+ if (grab->window == window)
+ gdk_pointer_ungrab (msg->time);
+ }
+ if (_gdk_display->keyboard_grab.window == window)
gdk_keyboard_ungrab (msg->time);
gdk_synthesize_window_state (window,
if (window == current_window)
assign_object (¤t_window, _gdk_root);
- if (p_grab_window == window)
- gdk_pointer_ungrab (msg->time);
+ grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+ if (grab != NULL)
+ {
+ if (grab->window == window)
+ gdk_pointer_ungrab (msg->time);
+ }
- if (k_grab_window == window)
+ if (_gdk_display->keyboard_grab.window == window)
gdk_keyboard_ungrab (msg->time);
if ((window != NULL) && (msg->hwnd != GetDesktopWindow ()))
void
_gdk_windowing_gc_set_clip_region (GdkGC *gc,
- const GdkRegion *region)
+ const GdkRegion *region,
+ gboolean reset_origin)
{
GdkGCWin32 *win32_gc = GDK_GC_WIN32 (gc);
win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
}
- gc->clip_x_origin = 0;
- gc->clip_y_origin = 0;
-
+ if (reset_origin)
+ {
+ gc->clip_x_origin = 0;
+ gc->clip_y_origin = 0;
+ }
+
win32_gc->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
}
#include "gdk.h" /* For gdk_rectangle_intersect */
#include "gdkregion.h"
#include "gdkregion-generic.h"
+#include "gdkinternals.h"
#include "gdkprivate-win32.h"
#define SIZE_LIMIT 32767
typedef struct _GdkWindowParentPos GdkWindowParentPos;
-struct _GdkWindowParentPos
-{
- gint x;
- gint y;
- gint win32_x;
- gint win32_y;
- GdkRectangle clip_rect;
-};
-
-static void gdk_window_compute_position (GdkWindowImplWin32 *window,
- GdkWindowParentPos *parent_pos,
- GdkWin32PositionInfo *info);
-static void gdk_window_compute_parent_pos (GdkWindowImplWin32 *window,
- GdkWindowParentPos *parent_pos);
-
-static void gdk_window_postmove (GdkWindow *window,
- GdkWindowParentPos *parent_pos,
- gboolean anti_scroll);
-static void gdk_window_tmp_unset_bg (GdkWindow *window);
-static void gdk_window_tmp_reset_bg (GdkWindow *window);
-static GdkRegion *gdk_window_clip_changed (GdkWindow *window,
- GdkRectangle *old_clip,
- GdkRectangle *new_clip);
-static void gdk_window_post_scroll (GdkWindow *window,
- GdkRegion *new_clip_region);
-
-void
-_gdk_win32_windowing_window_get_offsets (GdkWindow *window,
- gint *x_offset,
- gint *y_offset)
-{
- GdkWindowImplWin32 *impl =
- GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
-
- *x_offset = impl->position_info.x_offset;
- *y_offset = impl->position_info.y_offset;
-}
-
-void
-_gdk_window_init_position (GdkWindow *window)
-{
- GdkWindowParentPos parent_pos;
- GdkWindowImplWin32 *impl;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
-
- gdk_window_compute_parent_pos (impl, &parent_pos);
- gdk_window_compute_position (impl, &parent_pos, &impl->position_info);
-}
-
-void
-_gdk_win32_window_scroll (GdkWindow *window,
- gint dx,
- gint dy)
-{
- GdkRegion *invalidate_region;
- GdkWindowImplWin32 *impl;
- GdkWindowObject *obj;
- GList *tmp_list;
- GdkWindowParentPos parent_pos;
- HRGN native_invalidate_region;
-
- GDK_NOTE (EVENTS, g_print ("gdk_window_scroll: %p %d,%d\n",
- GDK_WINDOW_HWND (window), dx, dy));
-
- obj = GDK_WINDOW_OBJECT (window);
- impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
-
- /* Move the current invalid region */
- if (obj->update_area)
- gdk_region_offset (obj->update_area, dx, dy);
-
- gdk_window_compute_parent_pos (impl, &parent_pos);
-
- parent_pos.x += obj->x;
- parent_pos.y += obj->y;
- parent_pos.win32_x += impl->position_info.x;
- parent_pos.win32_y += impl->position_info.y;
- parent_pos.clip_rect = impl->position_info.clip_rect;
-
- gdk_window_tmp_unset_bg (window);
-
- native_invalidate_region = CreateRectRgn (0, 0, 0, 0);
- if (native_invalidate_region == NULL)
- WIN32_API_FAILED ("CreateRectRgn");
-
- API_CALL (ScrollWindowEx, (GDK_WINDOW_HWND (window),
- dx, dy, NULL, NULL,
- native_invalidate_region, NULL, SW_SCROLLCHILDREN));
-
- if (impl->position_info.no_bg)
- gdk_window_tmp_reset_bg (window);
-
- tmp_list = obj->children;
- while (tmp_list)
- {
- GDK_WINDOW_OBJECT(tmp_list->data)->x += dx;
- GDK_WINDOW_OBJECT(tmp_list->data)->y += dy;
- gdk_window_postmove (tmp_list->data, &parent_pos, FALSE);
- tmp_list = tmp_list->next;
- }
-
- if (native_invalidate_region != NULL)
- {
- invalidate_region = _gdk_win32_hrgn_to_region (native_invalidate_region);
- gdk_region_offset (invalidate_region, impl->position_info.x_offset,
- impl->position_info.y_offset);
- gdk_window_invalidate_region (window, invalidate_region, TRUE);
- gdk_region_destroy (invalidate_region);
- GDI_CALL (DeleteObject, (native_invalidate_region));
- }
-}
-
-void
-_gdk_win32_window_move_region (GdkWindow *window,
- const GdkRegion *region,
- gint dx,
- gint dy)
-{
- GdkRegion *invalidate_region;
- GdkWindowImplWin32 *impl;
- GdkWindowObject *obj;
- GdkRectangle src_rect, dest_rect;
- HRGN hrgn;
- RECT clipRect, destRect;
-
- obj = GDK_WINDOW_OBJECT (window);
- impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
-
- /* Move the current invalid region */
- if (obj->update_area)
- gdk_region_offset (obj->update_area, dx, dy);
-
- /* impl->position_info.clip_rect isn't meaningful for toplevels */
- if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
- src_rect = impl->position_info.clip_rect;
- else
- {
- src_rect.x = 0;
- src_rect.y = 0;
- src_rect.width = impl->width;
- src_rect.height = impl->height;
- }
-
- invalidate_region = gdk_region_rectangle (&src_rect);
-
- dest_rect = src_rect;
- dest_rect.x += dx;
- dest_rect.y += dy;
- gdk_rectangle_intersect (&dest_rect, &src_rect, &dest_rect);
-
- if (dest_rect.width > 0 && dest_rect.height > 0)
- {
- GdkRegion *tmp_region;
-
- tmp_region = gdk_region_rectangle (&dest_rect);
- gdk_region_subtract (invalidate_region, tmp_region);
- gdk_region_destroy (tmp_region);
- }
-
- /* no guffaw scroll on win32 */
- hrgn = _gdk_win32_gdkregion_to_hrgn(invalidate_region, 0, 0);
- gdk_region_destroy (invalidate_region);
- destRect.left = dest_rect.y;
- destRect.top = dest_rect.x;
- destRect.right = dest_rect.x + dest_rect.width;
- destRect.bottom = dest_rect.y + dest_rect.height;
- clipRect.left = src_rect.y;
- clipRect.top = src_rect.x;
- clipRect.right = src_rect.x + src_rect.width;
- clipRect.bottom = src_rect.y + src_rect.height;
-
- g_print ("ScrollWindowEx(%d, %d, ...) - if you see this work, remove trace;)\n", dx, dy);
- API_CALL(ScrollWindowEx, (GDK_WINDOW_HWND (window),
- dx, dy, /* in: scroll offsets */
- NULL, /* in: scroll rect, NULL == entire client area */
- &clipRect, /* in: restrict to */
- hrgn, /* in: update region */
- NULL, /* out: update rect */
- SW_INVALIDATE));
- API_CALL(DeleteObject, (hrgn));
-}
+static void tmp_unset_bg (GdkWindow *window);
+static void tmp_reset_bg (GdkWindow *window);
void
_gdk_window_move_resize_child (GdkWindow *window,
{
GdkWindowImplWin32 *impl;
GdkWindowObject *obj;
- GdkWin32PositionInfo new_info;
- GdkWindowParentPos parent_pos;
- GList *tmp_list;
- gint d_xoffset, d_yoffset;
- gint dx, dy;
gboolean is_move;
gboolean is_resize;
- GdkRegion *new_clip_region;
-
+
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
obj = GDK_WINDOW_OBJECT (window);
impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
+
+ is_move = (x - obj->x != 0) && (y - obj->y != 0);
+ is_resize = obj->width != width && obj->height != height;
GDK_NOTE (MISC, g_print ("_gdk_window_move_resize_child: %s@%+d%+d %dx%d@%+d%+d\n",
_gdk_win32_drawable_description (window),
- obj->x, obj->y,
- width, height, x, y));
+ obj->x, obj->y, width, height, x, y));
- dx = x - obj->x;
- dy = y - obj->y;
+ if (width > 65535 || height > 65535)
+ {
+ g_warning ("Native children wider or taller than 65535 pixels are not supported.");
- is_move = dx != 0 || dy != 0;
- is_resize = impl->width != width || impl->height != height;
-
- if (!is_move && !is_resize)
- {
- GDK_NOTE (MISC, g_print ("... neither move or resize\n"));
- return;
- }
-
- GDK_NOTE (MISC, g_print ("... %s%s\n",
- is_move ? "is_move " : "",
- is_resize ? "is_resize" : ""));
+ if (width > 65535)
+ width = 65535;
+ if (height > 65535)
+ height = 65535;
+ }
obj->x = x;
obj->y = y;
- impl->width = width;
- impl->height = height;
-
- gdk_window_compute_parent_pos (impl, &parent_pos);
- gdk_window_compute_position (impl, &parent_pos, &new_info);
+ obj->width = width;
+ obj->height = height;
- new_clip_region =
- gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
-
- parent_pos.x += obj->x;
- parent_pos.y += obj->y;
- parent_pos.win32_x += new_info.x;
- parent_pos.win32_y += new_info.y;
- parent_pos.clip_rect = new_info.clip_rect;
-
- d_xoffset = new_info.x_offset - impl->position_info.x_offset;
- d_yoffset = new_info.y_offset - impl->position_info.y_offset;
+ _gdk_win32_window_tmp_unset_parent_bg (window);
+ _gdk_win32_window_tmp_unset_bg (window, TRUE);
- if (d_xoffset != 0 || d_yoffset != 0)
- {
- GDK_NOTE (MISC, g_print ("... d_offset=%+d%+d\n", d_xoffset, d_yoffset));
-
- if (!ScrollWindowEx (GDK_WINDOW_HWND (window),
- -d_xoffset, -d_yoffset, /* in: scroll offsets */
- NULL, /* in: scroll rect, NULL == entire client area */
- NULL, /* in: restrict to */
- NULL, /* in: update region */
- NULL, /* out: update rect */
- SW_SCROLLCHILDREN))
- WIN32_API_FAILED ("ScrollWindowEx");
-
- if (dx != d_xoffset || dy != d_yoffset || is_resize)
- {
- GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%d,%d,"
- "NOACTIVATE|NOZORDER%s%s)\n",
- GDK_WINDOW_HWND (window),
- new_info.x, new_info.y,
- new_info.width, new_info.height,
- (is_move ? "" : "|NOMOVE"),
- (is_resize ? "" : "|NOSIZE")));
-
- API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
- new_info.x, new_info.y,
- new_info.width, new_info.height,
- SWP_NOACTIVATE | SWP_NOZORDER |
- (is_move ? 0 : SWP_NOMOVE) |
- (is_resize ? 0 : SWP_NOSIZE)));
- }
-
- if (impl->position_info.no_bg)
- gdk_window_tmp_reset_bg (window);
-
- if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
- {
- GDK_NOTE (MISC, g_print ("... ShowWindow(%p, SW_SHOWNA)\n",
- GDK_WINDOW_HWND (window)));
- ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
- }
-
- impl->position_info = new_info;
-
- tmp_list = obj->children;
- while (tmp_list)
- {
- gdk_window_postmove (tmp_list->data, &parent_pos, FALSE);
- tmp_list = tmp_list->next;
- }
- }
- else
- {
- if (impl->position_info.mapped && !new_info.mapped)
- {
- GDK_NOTE (MISC, g_print ("... ShowWindow(%p, SW_HIDE)\n",
- GDK_WINDOW_HWND (window)));
- ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
- }
-
- GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%d,%d,"
- "NOACTIVATE|NOZORDER%s%s)\n",
- GDK_WINDOW_HWND (window),
- new_info.x, new_info.y,
- new_info.width, new_info.height,
- (is_move ? "" : "|NOMOVE"),
- (is_resize ? "" : "|NOSIZE")));
-
- API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
- new_info.x, new_info.y,
- new_info.width, new_info.height,
- SWP_NOACTIVATE | SWP_NOZORDER |
- (is_move ? 0 : SWP_NOMOVE) |
- (is_resize ? 0 : SWP_NOSIZE)));
-
- tmp_list = obj->children;
- while (tmp_list)
- {
- gdk_window_postmove (tmp_list->data, &parent_pos, FALSE);
- tmp_list = tmp_list->next;
- }
-
- if (impl->position_info.no_bg)
- gdk_window_tmp_reset_bg (window);
-
- if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
- {
- GDK_NOTE (MISC, g_print ("... ShowWindow(%p, SW_SHOWNA)\n",
- GDK_WINDOW_HWND (window)));
- ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
- }
-
- impl->position_info = new_info;
- }
- if (new_clip_region)
- gdk_window_post_scroll (window, new_clip_region);
+ GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%d,%d,"
+ "NOACTIVATE|NOZORDER%s%s)\n",
+ GDK_WINDOW_HWND (window),
+ obj->x + obj->parent->abs_x, obj->y + obj->parent->abs_y,
+ width, height,
+ (is_move ? "" : "|NOMOVE"),
+ (is_resize ? "" : "|NOSIZE")));
+
+ API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
+ obj->x + obj->parent->abs_x, obj->y + obj->parent->abs_y,
+ width, height,
+ SWP_NOACTIVATE | SWP_NOZORDER |
+ (is_move ? 0 : SWP_NOMOVE) |
+ (is_resize ? 0 : SWP_NOSIZE)));
+
+ //_gdk_win32_window_tmp_reset_parent_bg (window);
+ _gdk_win32_window_tmp_reset_bg (window, TRUE);
}
-static void
-gdk_window_compute_position (GdkWindowImplWin32 *window,
- GdkWindowParentPos *parent_pos,
- GdkWin32PositionInfo *info)
+void
+_gdk_window_process_expose (GdkWindow *window,
+ GdkRegion *invalidate_region)
{
- GdkWindowObject *wrapper;
- int parent_x_offset;
- int parent_y_offset;
-
- g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (window));
-
- wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_WIN32 (window)->wrapper);
-
- info->big = FALSE;
+ GdkWindowImplWin32 *impl;
+ //GdkRegion *clip_region;
+ impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
- if (window->width <= SIZE_LIMIT)
- {
- info->width = window->width;
- info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
- }
- else
- {
- info->big = TRUE;
- info->width = SIZE_LIMIT;
- if (parent_pos->x + wrapper->x < -(SIZE_LIMIT/2))
- {
- if (parent_pos->x + wrapper->x + window->width < (SIZE_LIMIT/2))
- info->x = parent_pos->x + wrapper->x + window->width - info->width - parent_pos->win32_x;
- else
- info->x = -(SIZE_LIMIT/2) - parent_pos->win32_x;
- }
- else
- info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
- }
+ GDK_NOTE (EVENTS, g_print ("_gdk_window_process_expose: %p %s\n",
+ GDK_WINDOW_HWND (window),
+ _gdk_win32_gdkregion_to_string (invalidate_region)));
- if (window->height <= SIZE_LIMIT)
- {
- info->height = window->height;
- info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
- }
+ if (!gdk_region_empty (invalidate_region))
+ _gdk_window_invalidate_for_expose (window, invalidate_region);
else
- {
- info->big = TRUE;
- info->height = SIZE_LIMIT;
- if (parent_pos->y + wrapper->y < -(SIZE_LIMIT/2))
- {
- if (parent_pos->y + wrapper->y + window->height < (SIZE_LIMIT/2))
- info->y = parent_pos->y + wrapper->y + window->height - info->height - parent_pos->win32_y;
- else
- info->y = -(SIZE_LIMIT/2) - parent_pos->win32_y;
- }
- else
- info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
- }
-
- parent_x_offset = parent_pos->win32_x - parent_pos->x;
- parent_y_offset = parent_pos->win32_y - parent_pos->y;
+ g_print ("process_expose(), empty region\n");
- info->x_offset = parent_x_offset + info->x - wrapper->x;
- info->y_offset = parent_y_offset + info->y - wrapper->y;
-
- /* We don't considering the clipping of toplevel windows and their immediate children
- * by their parents, and simply always map those windows.
- */
- if (parent_pos->clip_rect.width == G_MAXINT)
- info->mapped = TRUE;
- /* Check if the window would wrap around into the visible space in either direction */
- else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
- info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
- info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
- info->y + info->height + parent_y_offset > parent_pos->clip_rect.y + 65536)
- info->mapped = FALSE;
- else
- info->mapped = TRUE;
-
- info->no_bg = FALSE;
-
- if (GDK_WINDOW_TYPE (wrapper) == GDK_WINDOW_CHILD)
- {
- info->clip_rect.x = wrapper->x;
- info->clip_rect.y = wrapper->y;
- info->clip_rect.width = window->width;
- info->clip_rect.height = window->height;
-
- gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
-
- info->clip_rect.x -= wrapper->x;
- info->clip_rect.y -= wrapper->y;
- }
- else
- {
- info->clip_rect.x = 0;
- info->clip_rect.y = 0;
- info->clip_rect.width = G_MAXINT;
- info->clip_rect.height = G_MAXINT;
- }
+ //gdk_region_destroy (invalidate_region);
}
-static void
-gdk_window_compute_parent_pos (GdkWindowImplWin32 *window,
- GdkWindowParentPos *parent_pos)
+void
+_gdk_win32_window_tmp_unset_bg (GdkWindow *window,
+ gboolean recurse)
{
- GdkWindowObject *wrapper;
- GdkWindowObject *parent;
- GdkRectangle tmp_clip;
-
- int clip_xoffset = 0;
- int clip_yoffset = 0;
+ GdkWindowObject *private;
- g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (window));
+ g_return_if_fail (GDK_IS_WINDOW (window));
- wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_WIN32 (window)->wrapper);
-
- parent_pos->x = 0;
- parent_pos->y = 0;
- parent_pos->win32_x = 0;
- parent_pos->win32_y = 0;
-
- /* We take a simple approach here and simply consider toplevel
- * windows not to clip their children on the right/bottom, since the
- * size of toplevel windows is not directly under our
- * control. Clipping only really matters when scrolling and
- * generally we aren't going to be moving the immediate child of a
- * toplevel beyond the bounds of that toplevel.
- *
- * We could go ahead and recompute the clips of toplevel windows and
- * their descendents when we receive size notification, but it would
- * probably not be an improvement in most cases.
- */
- parent_pos->clip_rect.x = 0;
- parent_pos->clip_rect.y = 0;
- parent_pos->clip_rect.width = G_MAXINT;
- parent_pos->clip_rect.height = G_MAXINT;
+ private = (GdkWindowObject *)window;
- parent = (GdkWindowObject *)wrapper->parent;
- while (parent && parent->window_type == GDK_WINDOW_CHILD)
- {
- GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (parent->impl);
-
- tmp_clip.x = - clip_xoffset;
- tmp_clip.y = - clip_yoffset;
- tmp_clip.width = impl->width;
- tmp_clip.height = impl->height;
+ if (private->input_only || private->destroyed ||
+ (private->window_type != GDK_WINDOW_ROOT &&
+ !GDK_WINDOW_IS_MAPPED (window)))
+ return;
- gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
+ if (_gdk_window_has_impl (window) &&
+ GDK_WINDOW_IS_WIN32 (window) &&
+ private->window_type != GDK_WINDOW_ROOT &&
+ private->window_type != GDK_WINDOW_FOREIGN)
+ tmp_unset_bg (window);
- parent_pos->x += parent->x;
- parent_pos->y += parent->y;
- parent_pos->win32_x += impl->position_info.x;
- parent_pos->win32_y += impl->position_info.y;
-
- clip_xoffset += parent->x;
- clip_yoffset += parent->y;
+ if (recurse)
+ {
+ GList *l;
- parent = (GdkWindowObject *)parent->parent;
+ for (l = private->children; l != NULL; l = l->next)
+ _gdk_win32_window_tmp_unset_bg (l->data, TRUE);
}
}
static void
-gdk_window_postmove (GdkWindow *window,
- GdkWindowParentPos *parent_pos,
- gboolean anti_scroll)
+tmp_unset_bg (GdkWindow *window)
{
GdkWindowImplWin32 *impl;
GdkWindowObject *obj;
- GdkWin32PositionInfo new_info;
- GList *tmp_list;
- gint d_xoffset, d_yoffset;
- GdkWindowParentPos this_pos;
- GdkRegion *new_clip_region;
obj = (GdkWindowObject *) window;
impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
-
- gdk_window_compute_position (impl, parent_pos, &new_info);
-
- new_clip_region =
- gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
- this_pos.x = parent_pos->x + obj->x;
- this_pos.y = parent_pos->y + obj->y;
- this_pos.win32_x = parent_pos->win32_x + new_info.x;
- this_pos.win32_y = parent_pos->win32_y + new_info.y;
- this_pos.clip_rect = new_info.clip_rect;
+ impl->no_bg = TRUE;
- if (impl->position_info.mapped && !new_info.mapped)
- ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
-
- d_xoffset = new_info.x_offset - impl->position_info.x_offset;
- d_yoffset = new_info.y_offset - impl->position_info.y_offset;
-
- if (anti_scroll || (anti_scroll = d_xoffset != 0 || d_yoffset != 0))
+ /*
+ * The X version sets background = None to avoid updateing for a moment.
+ * Not sure if this could really emulate it.
+ */
+ if (obj->bg_pixmap != GDK_NO_BG)
{
- GDK_NOTE (MISC, g_print ("gdk_window_postmove: %s@%+d%+d\n"
- "... SetWindowPos(%p,NULL,%d,%d,0,0,"
- "NOREDRAW|NOZORDER|NOACTIVATE|NOSIZE)\n",
- _gdk_win32_drawable_description (window),
- obj->x, obj->y,
- GDK_WINDOW_HWND (window),
- new_info.x, new_info.y));
-
- API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
- new_info.x, new_info.y,
- 0, 0,
- SWP_NOREDRAW | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE));
- }
-
- if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
- ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
-
- if (impl->position_info.no_bg)
- gdk_window_tmp_reset_bg (window);
-
- impl->position_info = new_info;
+ ///* handled in WM_ERASEBKGRND proceesing */;
- if (new_clip_region)
- gdk_window_post_scroll (window, new_clip_region);
-
- tmp_list = obj->children;
- while (tmp_list)
- {
- gdk_window_postmove (tmp_list->data, &this_pos, anti_scroll);
- tmp_list = tmp_list->next;
+ //HDC hdc = GetDC (GDK_WINDOW_HWND (window));
+ //erase_background (window, hdc);
}
}
-gboolean
-_gdk_windowing_window_queue_antiexpose (GdkWindow *window,
- GdkRegion *area)
+static void
+tmp_reset_bg (GdkWindow *window)
{
- HRGN hrgn = _gdk_win32_gdkregion_to_hrgn (area, 0, 0);
-
- GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose: ValidateRgn %p %s\n",
- GDK_WINDOW_HWND (window),
- _gdk_win32_gdkregion_to_string (area)));
-
- ValidateRgn (GDK_WINDOW_HWND (window), hrgn);
+ GdkWindowObject *obj;
+ GdkWindowImplWin32 *impl;
- DeleteObject (hrgn);
+ obj = GDK_WINDOW_OBJECT (window);
+ impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
- return FALSE;
+ impl->no_bg = FALSE;
}
void
-_gdk_window_process_expose (GdkWindow *window,
- GdkRegion *invalidate_region)
+_gdk_win32_window_tmp_unset_parent_bg (GdkWindow *window)
{
- GdkWindowImplWin32 *impl;
- GdkRegion *clip_region;
- impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
-
- GDK_NOTE (EVENTS, g_print ("_gdk_window_process_expose: %p %s\n",
- GDK_WINDOW_HWND (window),
- _gdk_win32_gdkregion_to_string (invalidate_region)));
- clip_region = gdk_region_rectangle (&impl->position_info.clip_rect);
- gdk_region_intersect (invalidate_region, clip_region);
+ GdkWindowObject *private = (GdkWindowObject*)window;
- if (!gdk_region_empty (invalidate_region))
- gdk_window_invalidate_region (window, invalidate_region, FALSE);
-
- gdk_region_destroy (clip_region);
+ if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+ return;
+
+ window = _gdk_window_get_impl_window ((GdkWindow*)private->parent);
+ _gdk_win32_window_tmp_unset_bg (window, FALSE);
}
-static void
-gdk_window_tmp_unset_bg (GdkWindow *window)
+void
+_gdk_win32_window_tmp_reset_bg (GdkWindow *window,
+ gboolean recurse)
{
- GdkWindowImplWin32 *impl;
- GdkWindowObject *obj;
+ GdkWindowObject *private;
- obj = (GdkWindowObject *) window;
- impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
+ g_return_if_fail (GDK_IS_WINDOW (window));
- impl->position_info.no_bg = TRUE;
+ if (private->input_only || private->destroyed ||
+ (private->window_type != GDK_WINDOW_ROOT && !GDK_WINDOW_IS_MAPPED (window)))
+ return;
- /*
- * The X version sets background = None to avoid updateing for a moment.
- * Not sure if this could really emulate it.
- */
- if (obj->bg_pixmap != GDK_NO_BG)
- /* handled in WM_ERASEBKGRND proceesing */;
+ if (_gdk_window_has_impl (window) &&
+ GDK_WINDOW_IS_WIN32 (window) &&
+ private->window_type != GDK_WINDOW_ROOT &&
+ private->window_type != GDK_WINDOW_FOREIGN)
+ {
+ tmp_reset_bg (window);
+ }
+
+ if (recurse)
+ {
+ GList *l;
+
+ for (l = private->children; l != NULL; l = l->next)
+ _gdk_win32_window_tmp_reset_bg (l->data, TRUE);
+ }
}
-static void
-gdk_window_tmp_reset_bg (GdkWindow *window)
+/*
+void
+_gdk_win32_window_tmp_reset_bg (GdkWindow *window)
{
GdkWindowImplWin32 *impl;
GdkWindowObject *obj;
obj = (GdkWindowObject *) window;
impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
- impl->position_info.no_bg = FALSE;
+ impl->no_bg = FALSE;
}
+*/
+#if 0
static GdkRegion *
gdk_window_clip_changed (GdkWindow *window,
GdkRectangle *old_clip,
gdk_region_destroy (new_clip_region);
new_clip_region = NULL;
}
+
gdk_region_destroy (old_clip_region);
return new_clip_region;
}
+#endif
+#if 0
static void
gdk_window_post_scroll (GdkWindow *window,
GdkRegion *new_clip_region)
_gdk_win32_gdkregion_to_string (new_clip_region)));
gdk_window_invalidate_region (window, new_clip_region, FALSE);
+ g_print ("gdk_window_post_scroll\n");
gdk_region_destroy (new_clip_region);
}
+
+#endif
gdouble *x_out,
gdouble *y_out)
{
- GdkWindowImplWin32 *impl, *root_impl;
+ GdkWindowImplWin32 *root_impl;
+ GdkWindowObject *window_object;
int i;
int x_axis = 0;
double device_width, device_height;
double x_offset, y_offset, x_scale, y_scale;
- impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (input_window->window)->impl);
+ window_object = GDK_WINDOW_OBJECT (input_window);
for (i=0; i<gdkdev->info.num_axes; i++)
{
switch (gdkdev->info.axes[i].use)
- {
- case GDK_AXIS_X:
- x_axis = i;
- break;
- case GDK_AXIS_Y:
- y_axis = i;
- break;
- default:
- break;
- }
+ {
+ case GDK_AXIS_X:
+ x_axis = i;
+ break;
+ case GDK_AXIS_Y:
+ y_axis = i;
+ break;
+ default:
+ break;
+ }
}
- device_width = gdkdev->axes[x_axis].max_value -
- gdkdev->axes[x_axis].min_value;
- device_height = gdkdev->axes[y_axis].max_value -
- gdkdev->axes[y_axis].min_value;
+ device_width = gdkdev->axes[x_axis].max_value - gdkdev->axes[x_axis].min_value;
+ device_height = gdkdev->axes[y_axis].max_value - gdkdev->axes[y_axis].min_value;
if (gdkdev->info.mode == GDK_MODE_SCREEN)
{
root_impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (_gdk_root)->impl);
- x_scale = root_impl->width / device_width;
- y_scale = root_impl->height / device_height;
+ x_scale = GDK_WINDOW_OBJECT (_gdk_root)->width / device_width;
+ y_scale = GDK_WINDOW_OBJECT (_gdk_root)->height / device_height;
x_offset = - input_window->root_x;
y_offset = - input_window->root_y;
double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
(device_width*gdkdev->axes[x_axis].resolution);
- if (device_aspect * impl->width >= impl->height)
- {
- /* device taller than window */
- x_scale = impl->width / device_width;
- y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
- / gdkdev->axes[y_axis].resolution;
-
- x_offset = 0;
- y_offset = -(device_height * y_scale -
- impl->height)/2;
- }
+ if (device_aspect * window_object->width >= window_object->height)
+ {
+ /* device taller than window */
+ x_scale = window_object->width / device_width;
+ y_scale = (x_scale * gdkdev->axes[x_axis].resolution) / gdkdev->axes[y_axis].resolution;
+
+ x_offset = 0;
+ y_offset = -(device_height * y_scale - window_object->height) / 2;
+ }
else
- {
- /* window taller than device */
- y_scale = impl->height / device_height;
- x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
- / gdkdev->axes[x_axis].resolution;
+ {
+ /* window taller than device */
+ y_scale = window_object->height / device_height;
+ x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
+ / gdkdev->axes[x_axis].resolution;
- y_offset = 0;
- x_offset = - (device_width * x_scale - impl->width)/2;
- }
+ y_offset = 0;
+ x_offset = - (device_width * x_scale - window_object->width) / 2;
+ }
}
- for (i=0; i<gdkdev->info.num_axes; i++)
+ for (i = 0; i < gdkdev->info.num_axes; i++)
{
switch (gdkdev->info.axes[i].use)
- {
- case GDK_AXIS_X:
- axis_out[i] = x_offset + x_scale*axis_data[x_axis];
- if (x_out)
- *x_out = axis_out[i];
- break;
- case GDK_AXIS_Y:
- axis_out[i] = y_offset + y_scale*axis_data[y_axis];
- if (y_out)
- *y_out = axis_out[i];
- break;
- default:
- axis_out[i] =
- (gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) +
- gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) /
- (gdkdev->axes[i].max_value - gdkdev->axes[i].min_value);
- break;
- }
+ {
+ case GDK_AXIS_X:
+ axis_out[i] = x_offset + x_scale * axis_data[x_axis];
+ if (x_out)
+ *x_out = axis_out[i];
+ break;
+ case GDK_AXIS_Y:
+ axis_out[i] = y_offset + y_scale * axis_data[y_axis];
+ if (y_out)
+ *y_out = axis_out[i];
+ break;
+ default:
+ axis_out[i] =
+ (gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) +
+ gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) /
+ (gdkdev->axes[i].max_value - gdkdev->axes[i].min_value);
+ break;
+ }
}
}
gint
gdk_screen_get_width (GdkScreen *screen)
{
- return GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (_gdk_root)->impl)->width;
+ //return GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (_gdk_root)->impl)->width;
+ return GDK_WINDOW_OBJECT (_gdk_root)->width;
}
gint
gdk_screen_get_height (GdkScreen *screen)
{
- return GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (_gdk_root)->impl)->height;
+ //return GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (_gdk_root)->impl)->height;
+ return GDK_WINDOW_OBJECT (_gdk_root)->height;
}
gint
gdk_screen_get_width_mm (GdkScreen *screen)
{
gint width, height, depth;
+ g_return_val_if_fail (GDK_IS_DRAWABLE (d), NULL);
+
gdk_drawable_get_size (d, &width, &height);
depth = gdk_drawable_get_depth (d);
}
GdkPixmap*
-gdk_pixmap_new (GdkDrawable *drawable,
+_gdk_pixmap_new (GdkDrawable *drawable,
gint width,
gint height,
gint depth)
};
GdkPixmap *
-gdk_bitmap_create_from_data (GdkDrawable *drawable,
+_gdk_bitmap_create_from_data (GdkDrawable *drawable,
const gchar *data,
gint width,
gint height)
}
GdkPixmap*
-gdk_pixmap_create_from_data (GdkDrawable *drawable,
+_gdk_pixmap_create_from_data (GdkDrawable *drawable,
const gchar *data,
gint width,
gint height,
#define GDK_IS_GC_WIN32_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_GC_WIN32))
#define GDK_GC_WIN32_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_GC_WIN32, GdkGCWin32Class))
+//#define GDK_WINDOW_SCREEN(win) (_gdk_screen)
+GdkScreen *GDK_WINDOW_SCREEN(GObject *win);
+
+#define GDK_WINDOW_IS_WIN32(win) (GDK_IS_WINDOW_IMPL_WIN32 (((GdkWindowObject *)win)->impl))
+
typedef struct _GdkColormapPrivateWin32 GdkColormapPrivateWin32;
typedef struct _GdkCursorPrivate GdkCursorPrivate;
typedef struct _GdkWin32SingleFont GdkWin32SingleFont;
gboolean _gdk_win32_pixbuf_to_hicon_supports_alpha (void);
/* Initialization */
-void _gdk_windowing_window_init (void);
+void _gdk_windowing_window_init (GdkScreen *screen);
void _gdk_root_window_size_init (void);
void _gdk_monitor_init(void);
void _gdk_visual_init (void);
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Copyright (C) 1998-2004 Tor Lillqvist
* Copyright (C) 2001-2004 Hans Breuer
- * Copyright (C) 2007 Cody Russell
+ * Copyright (C) 2007-2009 Cody Russell
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
static GdkColormap* gdk_window_impl_win32_get_colormap (GdkDrawable *drawable);
static void gdk_window_impl_win32_set_colormap (GdkDrawable *drawable,
GdkColormap *cmap);
-static void gdk_window_impl_win32_get_size (GdkDrawable *drawable,
- gint *width,
- gint *height);
-static GdkRegion* gdk_window_impl_win32_get_visible_region (GdkDrawable *drawable);
static void gdk_window_impl_win32_init (GdkWindowImplWin32 *window);
static void gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass);
static void gdk_window_impl_win32_finalize (GObject *object);
#define WINDOW_IS_TOPLEVEL(window) \
(GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
- GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+ GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
+ GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
static void gdk_window_impl_iface_init (GdkWindowImplIface *iface);
+GdkScreen *
+GDK_WINDOW_SCREEN (GObject *win)
+{
+ return _gdk_screen;
+}
+
GType
_gdk_window_impl_win32_get_type (void)
{
static void
gdk_window_impl_win32_init (GdkWindowImplWin32 *impl)
{
- impl->width = 1;
- impl->height = 1;
impl->toplevel_window_type = -1;
impl->hcursor = NULL;
impl->hicon_big = NULL;
drawable_class->set_colormap = gdk_window_impl_win32_set_colormap;
drawable_class->get_colormap = gdk_window_impl_win32_get_colormap;
- drawable_class->get_size = gdk_window_impl_win32_get_size;
-
- /* Visible and clip regions are the same */
- drawable_class->get_clip_region = gdk_window_impl_win32_get_visible_region;
- drawable_class->get_visible_region = gdk_window_impl_win32_get_visible_region;
}
static void
}
}
-static void
-gdk_window_impl_win32_get_size (GdkDrawable *drawable,
- gint *width,
- gint *height)
-{
- g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (drawable));
-
- if (width)
- *width = GDK_WINDOW_IMPL_WIN32 (drawable)->width;
- if (height)
- *height = GDK_WINDOW_IMPL_WIN32 (drawable)->height;
-}
-
-static GdkRegion*
-gdk_window_impl_win32_get_visible_region (GdkDrawable *drawable)
-{
- GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (drawable);
- GdkRectangle result_rect;
-
- result_rect.x = 0;
- result_rect.y = 0;
- result_rect.width = impl->width;
- result_rect.height = impl->height;
-
- gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);
-
- return gdk_region_rectangle (&result_rect);
-}
-
void
_gdk_root_window_size_init (void)
{
- GdkWindowImplWin32 *impl;
+ GdkWindowObject *window_object;
+ //GdkWindowImplWin32 *impl;
GdkRectangle rect;
int i;
- impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) _gdk_root)->impl);
+ window_object = GDK_WINDOW_OBJECT (_gdk_root);
+ //impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) _gdk_root)->impl);
rect = _gdk_monitors[0].rect;
for (i = 1; i < _gdk_num_monitors; i++)
gdk_rectangle_union (&rect, &_gdk_monitors[i].rect, &rect);
- impl->width = rect.width;
- impl->height = rect.height;
+ window_object->width = rect.width;
+ window_object->height = rect.height;
+ //impl->width = rect.width;
+ //impl->height = rect.height;
}
void
-_gdk_windowing_window_init (void)
+_gdk_windowing_window_init (GdkScreen *screen)
{
GdkWindowObject *private;
GdkDrawableImplWin32 *draw_impl;
_gdk_root = g_object_new (GDK_TYPE_WINDOW, NULL);
private = (GdkWindowObject *)_gdk_root;
private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+ private->impl_window = private;
+
draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
draw_impl->handle = GetDesktopWindow ();
private->depth = gdk_visual_get_system ()->depth;
_gdk_root_window_size_init ();
-
- _gdk_window_init_position (GDK_WINDOW (private));
+
+ private->x = 0;
+ private->y = 0;
+ private->abs_x = 0;
+ private->abs_y = 0;
+ private->width = GetSystemMetrics (SM_CXSCREEN);
+ private->height = GetSystemMetrics (SM_CYSCREEN);
gdk_win32_handle_table_insert ((HANDLE *) &draw_impl->handle, _gdk_root);
return klass;
}
-static GdkWindow*
-gdk_window_new_internal (GdkWindow *parent,
- GdkWindowAttr *attributes,
- gint attributes_mask,
- gboolean from_set_skip_taskbar_hint)
+void
+_gdk_window_impl_new (GdkWindow *window,
+ GdkWindow *real_parent,
+ GdkScreen *screen,
+ GdkVisual *visual,
+ GdkEventMask event_mask,
+ GdkWindowAttr *attributes,
+ gint attributes_mask)
{
HWND hwndNew;
HANDLE hparent;
ATOM klass = 0;
DWORD dwStyle = 0, dwExStyle;
RECT rect;
- GdkWindow *window;
GdkWindow *orig_parent;
GdkWindowObject *private;
GdkWindowImplWin32 *impl;
GdkDrawableImplWin32 *draw_impl;
- GdkVisual *visual;
const gchar *title;
wchar_t *wtitle;
gint window_width, window_height;
gint offset_x = 0, offset_y = 0;
- g_return_val_if_fail (attributes != NULL, NULL);
+ private = (GdkWindowObject *)window;
- if (!parent)
- parent = _gdk_root;
-
- g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
-
- orig_parent = parent;
+ orig_parent = real_parent;
GDK_NOTE (MISC,
g_print ("gdk_window_new_internal: %s\n",
- (attributes->window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
- (attributes->window_type == GDK_WINDOW_CHILD ? "CHILD" :
- (attributes->window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
+ (attributes->window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
+ (attributes->window_type == GDK_WINDOW_CHILD ? "CHILD" :
+ (attributes->window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
(attributes->window_type == GDK_WINDOW_TEMP ? "TEMP" :
- "???"))))));
+ "???"))))));
- if (GDK_WINDOW_DESTROYED (parent))
- return NULL;
-
- hparent = GDK_WINDOW_HWND (parent);
+ hparent = GDK_WINDOW_HWND (real_parent);
- window = g_object_new (GDK_TYPE_WINDOW, NULL);
- private = (GdkWindowObject *)window;
- private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
- impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
- draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
+ impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+ private->impl = (GdkDrawable *)impl;
+ draw_impl = GDK_DRAWABLE_IMPL_WIN32 (impl);
draw_impl->wrapper = GDK_DRAWABLE (window);
- /* Windows with a foreign parent are treated as if they are children
- * of the root window, except for actual creation.
- */
- if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
- parent = _gdk_root;
-
- private->parent = (GdkWindowObject *)parent;
+ // XXX: xattributes_mask = 0
- private->accept_focus = TRUE;
- private->focus_on_map = TRUE;
-
- if (attributes_mask & GDK_WA_X)
- private->x = attributes->x;
- else
- private->x = 0;
-
- if (attributes_mask & GDK_WA_Y)
- private->y = attributes->y;
- else if (attributes_mask & GDK_WA_X)
- private->y = 100; /* ??? We must put it somewhere... */
- else
- private->y = 0;
-
+#if 0
if (attributes_mask & GDK_WA_VISUAL)
visual = attributes->visual;
else
visual = gdk_visual_get_system ();
+#endif
+#if 0
impl->width = (attributes->width > 1) ? (attributes->width) : (1);
impl->height = (attributes->height > 1) ? (attributes->height) : (1);
+#endif
impl->extension_events_selected = FALSE;
- if (attributes->wclass == GDK_INPUT_ONLY)
- {
- /* Backwards compatiblity - we've always ignored
- * attributes->window_type for input-only windows
- * before
- */
- if (parent == _gdk_root)
- private->window_type = GDK_WINDOW_TEMP;
- else
- private->window_type = GDK_WINDOW_CHILD;
- }
- else
- private->window_type = attributes->window_type;
+ // XXX ?
if (attributes->wclass == GDK_INPUT_OUTPUT)
{
dwExStyle = 0;
if (attributes_mask & GDK_WA_COLORMAP)
{
draw_impl->colormap = attributes->colormap;
- g_object_ref (attributes->colormap);
- }
+ g_object_ref (attributes->colormap);
+ }
else
{
draw_impl->colormap = gdk_screen_get_system_colormap (_gdk_screen);
{
case GDK_WINDOW_TOPLEVEL:
case GDK_WINDOW_DIALOG:
- if (parent != _gdk_root)
+ if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
{
- g_warning (G_STRLOC ": Toplevel windows must be created as children\n"
- "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
+ /* The common code warns for this case. */
hparent = GetDesktopWindow ();
}
/* Children of foreign windows aren't toplevel windows */
}
break;
+ /*
case GDK_WINDOW_CHILD:
dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
break;
+ */
case GDK_WINDOW_TEMP:
/* A temp window is not necessarily a top level window */
- dwStyle = (_gdk_root == parent ? WS_POPUP : WS_CHILDWINDOW);
+ dwStyle = (_gdk_root == real_parent ? WS_POPUP : WS_CHILDWINDOW);
dwStyle |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
dwExStyle |= WS_EX_TOOLWINDOW;
offset_x = _gdk_offset_x;
offset_y = _gdk_offset_y;
break;
- case GDK_WINDOW_ROOT:
- g_error ("cannot make windows of type GDK_WINDOW_ROOT");
- break;
-
default:
g_assert_not_reached ();
}
- _gdk_window_init_position (GDK_WINDOW (private));
+ //_gdk_window_init_position (GDK_WINDOW (private));
if (private->window_type != GDK_WINDOW_CHILD)
{
rect.left = rect.top = 0;
- rect.right = impl->position_info.width;
- rect.bottom = impl->position_info.height;
+ rect.right = private->width;
+ rect.bottom = private->height;
AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
}
else
{
- window_width = impl->position_info.width;
- window_height = impl->position_info.height;
+ window_width = private->width;
+ window_height = private->height;
}
if (attributes_mask & GDK_WA_TITLE)
wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
hwndNew = CreateWindowExW (dwExStyle,
- MAKEINTRESOURCEW (klass),
- wtitle,
- dwStyle,
- ((attributes_mask & GDK_WA_X) ?
- impl->position_info.x - offset_x : CW_USEDEFAULT),
- impl->position_info.y - offset_y,
- window_width, window_height,
- hparent,
- NULL,
- _gdk_app_hmodule,
- window);
+ MAKEINTRESOURCEW (klass),
+ wtitle,
+ dwStyle,
+ ((attributes_mask & GDK_WA_X) ?
+ private->x - offset_x : CW_USEDEFAULT),
+ private->y - offset_y,
+ window_width, window_height,
+ hparent,
+ NULL,
+ _gdk_app_hmodule,
+ window);
if (GDK_WINDOW_HWND (window) != hwndNew)
{
g_warning ("gdk_window_new: gdk_event_translate::WM_CREATE (%p, %p) HWND mismatch.",
title,
window_width, window_height,
((attributes_mask & GDK_WA_X) ?
- impl->position_info.x - offset_x: CW_USEDEFAULT),
- impl->position_info.y - offset_y,
+ private->x - offset_x: CW_USEDEFAULT),
+ private->y - offset_y,
hparent,
GDK_WINDOW_HWND (window)));
{
WIN32_API_FAILED ("CreateWindowExW");
g_object_unref (window);
- return NULL;
+ return;
}
- if (!from_set_skip_taskbar_hint && private->window_type == GDK_WINDOW_TEMP)
- gdk_window_set_skip_taskbar_hint (window, TRUE);
+// if (!from_set_skip_taskbar_hint && private->window_type == GDK_WINDOW_TEMP)
+// gdk_window_set_skip_taskbar_hint (window, TRUE);
gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
(attributes->cursor) :
NULL));
-
- return window;
-}
-
-GdkWindow*
-_gdk_window_new (GdkWindow *parent,
- GdkWindowAttr *attributes,
- gint attributes_mask)
-{
- return gdk_window_new_internal (parent, attributes, attributes_mask, FALSE);
}
GdkWindow *
ScreenToClient (parent, &point);
private->x = point.x;
private->y = point.y;
- impl->width = rect.right - rect.left;
- impl->height = rect.bottom - rect.top;
+ private->width = rect.right - rect.left;
+ private->height = rect.bottom - rect.top;
private->window_type = GDK_WINDOW_FOREIGN;
private->destroyed = FALSE;
private->event_mask = GDK_ALL_EVENTS_MASK; /* XXX */
private->depth = gdk_visual_get_system ()->depth;
- _gdk_window_init_position (GDK_WINDOW (private));
+ //_gdk_window_init_position (GDK_WINDOW (private));
g_object_ref (window);
gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
}
static void
-adjust_for_gravity_hints (GdkWindowImplWin32 *impl,
- RECT *outer_rect,
- gint *x,
- gint *y)
+adjust_for_gravity_hints (GdkWindow *window,
+ RECT *outer_rect,
+ gint *x,
+ gint *y)
{
+ GdkWindowObject *obj;
+ GdkWindowImplWin32 *impl;
+
+ obj = GDK_WINDOW_OBJECT (window);
+ impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
+
if (impl->hint_flags & GDK_HINT_WIN_GRAVITY)
{
gint orig_x = *x, orig_y = *y;
case GDK_GRAVITY_CENTER:
case GDK_GRAVITY_SOUTH:
*x -= (outer_rect->right - outer_rect->left) / 2;
- *x += impl->width / 2;
+ *x += obj->width / 2;
break;
case GDK_GRAVITY_SOUTH_EAST:
case GDK_GRAVITY_EAST:
case GDK_GRAVITY_NORTH_EAST:
*x -= outer_rect->right - outer_rect->left;
- *x += impl->width;
+ *x += obj->width;
break;
case GDK_GRAVITY_STATIC:
case GDK_GRAVITY_CENTER:
case GDK_GRAVITY_EAST:
*y -= (outer_rect->bottom - outer_rect->top) / 2;
- *y += impl->height / 2;
+ *y += obj->height / 2;
break;
case GDK_GRAVITY_SOUTH_WEST:
case GDK_GRAVITY_SOUTH:
case GDK_GRAVITY_SOUTH_EAST:
*y -= outer_rect->bottom - outer_rect->top;
- *y += impl->height;
+ *y += obj->height;
break;
case GDK_GRAVITY_STATIC:
GDK_NOTE (MISC, g_print ("show_window_internal: %p: %s%s%s\n",
GDK_WINDOW_HWND (window),
_gdk_win32_window_state_to_string (private->state),
- (raise ? " raise" : ""),
+ //(raise ? " raise" : ""),
(deiconify ? " deiconify" : "")));
/* If asked to show (not deiconify) an withdrawn and iconified
{
UINT flags = SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOSIZE;
- if (!raise)
- flags |= SWP_NOZORDER;
+ if (!raise)
+ flags |= SWP_NOZORDER;
if (!raise || GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || !focus_on_map)
- flags |= SWP_NOACTIVATE;
+ flags |= SWP_NOACTIVATE;
SetWindowPos (GDK_WINDOW_HWND (window), top, 0, 0, 0, 0, flags);
}
static void
-gdk_win32_window_show (GdkWindow *window, gboolean raise)
+gdk_win32_window_show (GdkWindow *window)
{
- show_window_internal (window, raise, FALSE);
+ show_window_internal (window, FALSE, FALSE);
}
static void
*/
if (GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) != GetDesktopWindow ())
{
- _gdk_window_move_resize_child (window, x, y, impl->width, impl->height);
+ _gdk_window_move_resize_child (window, x, y, private->width, private->height);
}
else
{
RECT outer_rect;
- get_outer_rect (window, impl->width, impl->height, &outer_rect);
+ get_outer_rect (window, private->width, private->height, &outer_rect);
- adjust_for_gravity_hints (impl, &outer_rect, &x, &y);
+ adjust_for_gravity_hints (window, &outer_rect, &x, &y);
GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,0,0,"
"NOACTIVATE|NOSIZE|NOZORDER)\n",
gint width,
gint height)
{
- GdkWindowObject *private = (GdkWindowObject*) window;
+ GdkWindowObject *private;
GdkWindowImplWin32 *impl;
g_return_if_fail (GDK_IS_WINDOW (window));
if (height < 1)
height = 1;
+ private = GDK_WINDOW_OBJECT (window);
impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
if (private->state & GDK_WINDOW_STATE_FULLSCREEN)
get_outer_rect (window, width, height, &outer_rect);
- adjust_for_gravity_hints (impl, &outer_rect, &x, &y);
+ adjust_for_gravity_hints (window, &outer_rect, &x, &y);
GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%ld,%ld,"
"NOACTIVATE|NOZORDER)\n",
GDK_WINDOW_HWND (new_parent)));
API_CALL (MoveWindow, (GDK_WINDOW_HWND (window),
- x, y, impl->width, impl->height, TRUE));
+ x, y, window_private->width, window_private->height, TRUE));
/* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
* the root window
g_list_remove (old_parent_private->children, window);
parent_private->children = g_list_prepend (parent_private->children, window);
- _gdk_window_init_position (GDK_WINDOW (window_private));
+ //_gdk_window_init_position (GDK_WINDOW (window_private));
return FALSE;
}
erase_background (GdkWindow *window,
HDC hdc)
{
+#if 0
HDC bgdc = NULL;
HBRUSH hbr = NULL;
HPALETTE holdpal = NULL;
if (((GdkWindowObject *) window)->input_only ||
((GdkWindowObject *) window)->bg_pixmap == GDK_NO_BG ||
- GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->position_info.no_bg)
+ GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->no_bg)
{
return;
}
window = GDK_WINDOW (((GdkWindowObject *) window)->parent);
}
- if (GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->position_info.no_bg)
+ if (GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->no_bg)
{
/* Improves scolling effect, e.g. main buttons of testgtk */
return;
DeleteDC (bgdc);
}
}
+#endif
}
static void
gboolean send_expose)
{
GdkWindowImplWin32 *impl;
+ GdkWindowObject *obj;
- impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
+ obj = GDK_WINDOW_OBJECT (window);
+ impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
if (!GDK_WINDOW_DESTROYED (window))
{
if (!send_expose)
{
if (width == 0)
- width = impl->width - x;
+ width = obj->width - x;
if (height == 0)
- height = impl->height - y;
+ height = obj->height - y;
GDK_NOTE (MISC, g_print ("_gdk_windowing_window_clear_area: %p: "
"%dx%d@%+d%+d\n",
GDK_WINDOW_HWND (window),
gdk_win32_window_set_background (GdkWindow *window,
const GdkColor *color)
{
+#if 0
GdkWindowObject *private = (GdkWindowObject *)window;
GDK_NOTE (MISC, g_print ("gdk_window_set_background: %p: %s\n",
g_object_unref (private->bg_pixmap);
private->bg_pixmap = NULL;
}
+#endif
}
static void
gdk_win32_window_set_back_pixmap (GdkWindow *window,
- GdkPixmap *pixmap,
- gint parent_relative)
+ GdkPixmap *pixmap)
{
GdkWindowObject *private = (GdkWindowObject *)window;
- if (pixmap && !gdk_drawable_get_colormap (pixmap))
- {
- g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
- return;
- }
-
if (private->bg_pixmap &&
private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
private->bg_pixmap != GDK_NO_BG)
g_object_unref (private->bg_pixmap);
- if (parent_relative)
+ if (pixmap == GDK_PARENT_RELATIVE_BG || pixmap == GDK_NO_BG)
{
- private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
- GDK_NOTE (MISC, g_print (G_STRLOC ": setting background pixmap to parent_relative\n"));
- }
- else
- {
- if (pixmap)
- {
- g_object_ref (pixmap);
- private->bg_pixmap = pixmap;
- }
- else
- {
- private->bg_pixmap = GDK_NO_BG;
- }
+ private->bg_pixmap = pixmap;
}
}
return return_val;
}
-gboolean
-gdk_window_get_deskrelative_origin (GdkWindow *window,
- gint *x,
- gint *y)
+static gboolean
+gdk_win32_window_get_deskrelative_origin (GdkWindow *window,
+ gint *x,
+ gint *y)
{
return gdk_window_get_origin (window, x, y);
}
+static void
+gdk_win32_window_restack_under (GdkWindow *window,
+ GList *native_siblings)
+{
+ // ### TODO
+}
+
void
gdk_window_get_root_origin (GdkWindow *window,
gint *x,
GdkWindow*
_gdk_windowing_window_at_pointer (GdkDisplay *display,
gint *win_x,
- gint *win_y)
+ gint *win_y,
+ GdkModifierType *mask)
{
GdkWindow *window;
POINT point, pointc;
}
}
-void
-gdk_window_input_shape_combine_mask (GdkWindow *window,
- GdkBitmap *mask,
- gint x,
- gint y)
-{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- /* Not yet implemented
- *
- * I don't think there is anything in the Win32 API to directly
- * support this. And anyway, as we don't currently support RGBA
- * windows, it doesn't really matter.
- *
- * When we do support RGBA, input shape functionality could probably
- * be implemented by saving the input shape region in the per-window
- * private data, and then simply checking before generating an input
- * event whether the event's coordinates are inside the region.
- */
-}
-
void
gdk_window_set_override_redirect (GdkWindow *window,
gboolean override_redirect)
gdk_propagate_shapes (GDK_WINDOW_HWND (window), TRUE);
}
+#if 0
void
gdk_window_set_child_input_shapes (GdkWindow *window)
{
* gdk_window_input_shape_combine_mask().
*/
}
+#endif
+#if 0
void
gdk_window_merge_child_input_shapes (GdkWindow *window)
{
* gdk_window_input_shape_combine_mask().
*/
}
+#endif
static gboolean
gdk_win32_window_set_static_gravities (GdkWindow *window,
gboolean skips_taskbar)
{
static GdkWindow *owner = NULL;
- GdkWindowAttr wa;
+ //GdkWindowAttr wa;
g_return_if_fail (GDK_IS_WINDOW (window));
if (skips_taskbar)
{
+#if 0
if (owner == NULL)
- {
- wa.window_type = GDK_WINDOW_TEMP;
- wa.wclass = GDK_INPUT_OUTPUT;
- wa.width = wa.height = 1;
- wa.event_mask = 0;
- owner = gdk_window_new_internal (NULL, &wa, 0, TRUE);
- }
+ {
+ wa.window_type = GDK_WINDOW_TEMP;
+ wa.wclass = GDK_INPUT_OUTPUT;
+ wa.width = wa.height = 1;
+ wa.event_mask = 0;
+ owner = gdk_window_new_internal (NULL, &wa, 0, TRUE);
+ }
+#endif
SetWindowLongPtr (GDK_WINDOW_HWND (window), GWLP_HWNDPARENT, (LONG_PTR) GDK_WINDOW_HWND (owner));
}
}
-void
-gdk_window_input_shape_combine_region (GdkWindow *window,
- const GdkRegion *shape_region,
- gint offset_x,
- gint offset_y)
-{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- /* Not yet implemented. See comment in
- * gdk_window_input_shape_combine_mask().
- */
-}
-
GdkWindow *
gdk_window_lookup_for_display (GdkDisplay *display,
GdkNativeWindow anid)
}
}
+GdkRegion *
+_gdk_windowing_get_shape_for_mask (GdkBitmap *mask)
+{
+ // XXX: TODO
+ return NULL;
+}
+
void
_gdk_windowing_window_set_composited (GdkWindow *window, gboolean composited)
{
}
+GdkRegion *
+_gdk_windowing_window_get_shape (GdkWindow *window)
+{
+ return NULL;
+}
+
+GdkRegion *
+_gdk_windowing_window_get_input_shape (GdkWindow *window)
+{
+ return NULL;
+}
+
+static void
+_gdk_win32_window_destroy (GdkWindow *window,
+ gboolean recursing,
+ gboolean foreign_destroy)
+{
+}
+
+static gboolean
+_gdk_win32_window_queue_antiexpose (GdkWindow *window,
+ GdkRegion *area)
+{
+ HRGN hrgn = _gdk_win32_gdkregion_to_hrgn (area, 0, 0);
+
+ GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose: ValidateRgn %p %s\n",
+ GDK_WINDOW_HWND (window),
+ _gdk_win32_gdkregion_to_string (area)));
+
+ ValidateRgn (GDK_WINDOW_HWND (window), hrgn);
+
+ DeleteObject (hrgn);
+
+ return FALSE;
+}
+
+static void
+_gdk_win32_window_queue_translation (GdkWindow *window,
+ GdkRegion *area,
+ gint dx,
+ gint dy)
+{
+ g_print ("queue_translation\n");
+}
+
+static void
+gdk_win32_input_shape_combine_region (GdkWindow *window,
+ const GdkRegion *shape_region,
+ gint offset_x,
+ gint offset_y)
+{
+}
+
+void
+_gdk_windowing_window_process_updates_recurse (GdkWindow *window,
+ GdkRegion *region)
+{
+ _gdk_window_process_updates_recurse (window, region);
+}
+
+void
+_gdk_windowing_before_process_all_updates (void)
+{
+}
+
+void
+_gdk_windowing_after_process_all_updates (void)
+{
+}
+
static void
gdk_window_impl_iface_init (GdkWindowImplIface *iface)
{
iface->withdraw = gdk_win32_window_withdraw;
iface->set_events = gdk_win32_window_set_events;
iface->get_events = gdk_win32_window_get_events;
- iface->clear_area = gdk_win32_window_clear_area;
iface->raise = gdk_win32_window_raise;
iface->lower = gdk_win32_window_lower;
+ iface->restack_under = gdk_win32_window_restack_under;
iface->move_resize = gdk_win32_window_move_resize;
- iface->scroll = _gdk_win32_window_scroll;
- iface->move_region = _gdk_win32_window_move_region;
iface->set_background = gdk_win32_window_set_background;
iface->set_back_pixmap = gdk_win32_window_set_back_pixmap;
iface->reparent = gdk_win32_window_reparent;
iface->set_cursor = gdk_win32_window_set_cursor;
iface->get_geometry = gdk_win32_window_get_geometry;
iface->get_origin = gdk_win32_window_get_origin;
- iface->shape_combine_mask = gdk_win32_window_shape_combine_mask;
iface->shape_combine_region = gdk_win32_window_shape_combine_region;
- iface->set_child_shapes = gdk_win32_window_set_child_shapes;
- iface->merge_child_shapes = gdk_win32_window_merge_child_shapes;
+ iface->input_shape_combine_region = gdk_win32_input_shape_combine_region;
+ iface->get_deskrelative_origin = gdk_win32_window_get_deskrelative_origin;
iface->set_static_gravities = gdk_win32_window_set_static_gravities;
- iface->get_offsets = _gdk_win32_windowing_window_get_offsets;
+ iface->queue_antiexpose = _gdk_win32_window_queue_antiexpose;
+ iface->queue_translation = _gdk_win32_window_queue_translation;
+ iface->destroy = _gdk_win32_window_destroy;
}
typedef struct _GdkWin32PositionInfo GdkWin32PositionInfo;
+#if 0
struct _GdkWin32PositionInfo
{
gint x;
*/
GdkRectangle clip_rect; /* visible rectangle of window */
};
+#endif
/* Window implementation for Win32
{
GdkDrawableImplWin32 parent_instance;
- gint width;
- gint height;
-
- GdkWin32PositionInfo position_info;
-
gint8 toplevel_window_type;
HCURSOR hcursor;
GSList *transient_children;
gint num_transients;
gboolean changing_state;
+
+ guint no_bg : 1;
};
struct _GdkWindowImplWin32Class
GType _gdk_window_impl_win32_get_type (void);
+void _gdk_win32_window_tmp_unset_bg (GdkWindow *window,
+ gboolean recurse);
+void _gdk_win32_window_tmp_reset_bg (GdkWindow *window,
+ gboolean recurse);
+
+void _gdk_win32_window_tmp_unset_parent_bg (GdkWindow *window);
+void _gdk_win32_window_tmp_reset_parent_bg (GdkWindow *window);
+
G_END_DECLS
#endif /* __GDK_WINDOW_WIN32_H__ */
typedef struct _ListChildrenState ListChildrenState;
typedef struct _SendEventState SendEventState;
typedef struct _SetInputFocusState SetInputFocusState;
+typedef struct _RoundtripState RoundtripState;
typedef enum {
CHILD_INFO_GET_PROPERTY,
gulong get_input_focus_req;
};
+struct _RoundtripState
+{
+ Display *dpy;
+ _XAsyncHandler async;
+ gulong get_input_focus_req;
+ GdkDisplay *display;
+ GdkRoundTripCallback callback;
+ gpointer data;
+};
+
static gboolean
callback_idle (gpointer data)
{
return !state.have_error;
}
+static gboolean
+roundtrip_callback_idle (gpointer data)
+{
+ RoundtripState *state = (RoundtripState *)data;
+
+ state->callback (state->display, state->data, state->get_input_focus_req);
+
+ g_free (state);
+
+ return FALSE;
+}
+
+static Bool
+roundtrip_handler (Display *dpy,
+ xReply *rep,
+ char *buf,
+ int len,
+ XPointer data)
+{
+ RoundtripState *state = (RoundtripState *)data;
+
+ if (dpy->last_request_read == state->get_input_focus_req)
+ {
+ xGetInputFocusReply replbuf;
+ xGetInputFocusReply *repl;
+
+ if (rep->generic.type != X_Error)
+ {
+ /* Actually does nothing, since there are no additional bytes
+ * to read, but maintain good form.
+ */
+ repl = (xGetInputFocusReply *)
+ _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
+ (sizeof(xGetInputFocusReply) - sizeof(xReply)) >> 2,
+ True);
+ }
+
+
+ if (state->callback)
+ gdk_threads_add_idle (roundtrip_callback_idle, state);
+
+ DeqAsyncHandler(state->dpy, &state->async);
+
+ return (rep->generic.type != X_Error);
+ }
+
+ return False;
+}
+
+void
+_gdk_x11_roundtrip_async (GdkDisplay *display,
+ GdkRoundTripCallback callback,
+ gpointer data)
+{
+ Display *dpy;
+ RoundtripState *state;
+
+ dpy = GDK_DISPLAY_XDISPLAY (display);
+
+ state = g_new (RoundtripState, 1);
+
+ state->display = display;
+ state->dpy = dpy;
+ state->callback = callback;
+ state->data = data;
+
+ LockDisplay(dpy);
+
+ state->async.next = dpy->async_handlers;
+ state->async.handler = roundtrip_handler;
+ state->async.data = (XPointer) state;
+ dpy->async_handlers = &state->async;
+
+ /*
+ * XSync (dpy, 0)
+ */
+ {
+ xReq *req;
+
+ GetEmptyReq(GetInputFocus, req);
+ state->get_input_focus_req = dpy->request;
+ }
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+}
+
#define __GDK_ASYNC_C__
#include "gdkaliasdef.c"
typedef void (*GdkSendXEventCallback) (Window window,
gboolean success,
gpointer data);
+typedef void (*GdkRoundTripCallback) (GdkDisplay *display,
+ gpointer data,
+ gulong serial);
struct _GdkChildInfoX11
{
GdkChildInfoX11 **children,
guint *nchildren);
+void _gdk_x11_roundtrip_async (GdkDisplay *display,
+ GdkRoundTripCallback callback,
+ gpointer data);
+
G_END_DECLS
#endif /* __GDK_ASYNC_H__ */
#include <glib.h>
#include "gdkx.h"
+#include "gdkasync.h"
#include "gdkdisplay.h"
#include "gdkdisplay-x11.h"
#include "gdkscreen.h"
return TRUE;
}
+gulong
+_gdk_windowing_window_get_next_serial (GdkDisplay *display)
+{
+ return NextRequest (GDK_DISPLAY_XDISPLAY (display));
+}
+
+
static GdkInternalConnection *
gdk_add_connection_handler (Display *display,
guint fd)
return FALSE;
}
+struct XPointerUngrabInfo {
+ GdkDisplay *display;
+ guint32 time;
+};
+
+static void
+pointer_ungrab_callback (GdkDisplay *display,
+ gpointer data,
+ gulong serial)
+{
+ _gdk_display_pointer_grab_update (display, serial);
+}
+
+
#define XSERVER_TIME_IS_LATER(time1, time2) \
( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) || \
(( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 )) \
*/
void
gdk_display_pointer_ungrab (GdkDisplay *display,
- guint32 time)
+ guint32 time_)
{
Display *xdisplay;
GdkDisplayX11 *display_x11;
+ GdkPointerGrabInfo *grab;
+ unsigned long serial;
g_return_if_fail (GDK_IS_DISPLAY (display));
display_x11 = GDK_DISPLAY_X11 (display);
xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+ serial = NextRequest (xdisplay);
- _gdk_input_ungrab_pointer (display, time);
- XUngrabPointer (xdisplay, time);
+ _gdk_input_ungrab_pointer (display, time_);
+ XUngrabPointer (xdisplay, time_);
XFlush (xdisplay);
- if (time == GDK_CURRENT_TIME ||
- display_x11->pointer_xgrab_time == GDK_CURRENT_TIME ||
- !XSERVER_TIME_IS_LATER (display_x11->pointer_xgrab_time, time))
- display_x11->pointer_xgrab_window = NULL;
-}
-
-/**
- * gdk_display_pointer_is_grabbed:
- * @display: a #GdkDisplay
- *
- * Test if the pointer is grabbed.
- *
- * Returns: %TRUE if an active X pointer grab is in effect
- *
- * Since: 2.2
- */
-gboolean
-gdk_display_pointer_is_grabbed (GdkDisplay *display)
-{
- g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
-
- return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL &&
- !GDK_DISPLAY_X11 (display)->pointer_xgrab_implicit);
+ grab = _gdk_display_get_last_pointer_grab (display);
+ if (grab &&
+ (time_ == GDK_CURRENT_TIME ||
+ grab->time == GDK_CURRENT_TIME ||
+ !XSERVER_TIME_IS_LATER (grab->time, time_)))
+ {
+ grab->serial_end = serial;
+ _gdk_x11_roundtrip_async (display,
+ pointer_ungrab_callback,
+ NULL);
+ }
}
/**
XFlush (xdisplay);
if (time == GDK_CURRENT_TIME ||
- display_x11->keyboard_xgrab_time == GDK_CURRENT_TIME ||
- !XSERVER_TIME_IS_LATER (display_x11->keyboard_xgrab_time, time))
- display_x11->keyboard_xgrab_window = NULL;
+ display->keyboard_grab.time == GDK_CURRENT_TIME ||
+ !XSERVER_TIME_IS_LATER (display->keyboard_grab.time, time))
+ _gdk_display_unset_has_keyboard_grab (display, FALSE);
}
/**
{
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
Atom clipboard_manager, save_targets;
-
+
+ g_return_if_fail (GDK_WINDOW_IS_X11 (clipboard_window));
+
clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
save_targets = gdk_x11_get_xatom_by_name_for_display (display, "SAVE_TARGETS");
#include <gdk/gdkdisplay.h>
#include <gdk/gdkkeys.h>
#include <gdk/gdkwindow.h>
+#include <gdk/gdkinternals.h>
#include <gdk/gdk.h> /* For gdk_get_program_class() */
G_BEGIN_DECLS
* (grabs, properties etc.) Otherwise always TRUE. */
gboolean trusted_client;
- /* Information about current pointer and keyboard grabs held by this
- * client. If gdk_pointer_xgrab_window or gdk_keyboard_xgrab_window
- * window is NULL, then the other associated fields are ignored
- */
- GdkWindowObject *pointer_xgrab_window;
- gulong pointer_xgrab_serial;
- gboolean pointer_xgrab_owner_events;
- gboolean pointer_xgrab_implicit;
- guint32 pointer_xgrab_time;
-
- GdkWindowObject *keyboard_xgrab_window;
- gulong keyboard_xgrab_serial;
- gboolean keyboard_xgrab_owner_events;
- guint32 keyboard_xgrab_time;
-
/* drag and drop information */
GdkDragContext *current_dest_drag;
/* input GdkWindow list */
GList *input_windows;
- gint input_ignore_core;
- /* information about network port and host for gxid daemon */
- gchar *input_gxid_host;
- gint input_gxid_port;
-
/* Startup notification */
gchar *startup_notification_id;
/* Alpha mask picture format */
XRenderPictFormat *mask_format;
+
+ /* The offscreen window that has the pointer in it (if any) */
+ GdkWindow *active_offscreen_window;
};
struct _GdkDisplayX11Class
GdkDragContext *new_context;
g_return_val_if_fail (window != NULL, NULL);
+ g_return_val_if_fail (GDK_WINDOW_IS_X11 (window), NULL);
new_context = gdk_drag_context_new ();
new_context->is_source = TRUE;
window_cache = drag_context_find_window_cache (context, screen);
dest = get_client_window_at_coords (window_cache,
- drag_window ?
+ drag_window && GDK_WINDOW_IS_X11 (drag_window) ?
GDK_DRAWABLE_XID (drag_window) : None,
x_root, y_root);
GdkDragContextPrivateX11 *private = PRIVATE_DATA (context);
g_return_val_if_fail (context != NULL, FALSE);
+ g_return_val_if_fail (dest_window == NULL || GDK_WINDOW_IS_X11 (dest_window), FALSE);
private->old_actions = context->actions;
context->actions = possible_actions;
static void gdk_x11_draw_drawable (GdkDrawable *drawable,
GdkGC *gc,
GdkPixmap *src,
+ GdkDrawable *original_src,
gint xsrc,
gint ysrc,
gint xdest,
gdk_x11_draw_drawable (GdkDrawable *drawable,
GdkGC *gc,
GdkPixmap *src,
+ GdkDrawable *original_src,
gint xsrc,
gint ysrc,
gint xdest,
if (GDK_IS_DRAWABLE_IMPL_X11 (src))
src_impl = GDK_DRAWABLE_IMPL_X11 (src);
+ else if (GDK_IS_WINDOW (src))
+ src_impl = GDK_DRAWABLE_IMPL_X11(((GdkWindowObject *)src)->impl);
else
- src_impl = NULL;
+ src_impl = GDK_DRAWABLE_IMPL_X11(((GdkPixmapObject *)src)->impl);
+
+ if (GDK_IS_WINDOW_IMPL_X11 (impl) &&
+ GDK_IS_PIXMAP_IMPL_X11 (src_impl))
+ {
+ GdkPixmapImplX11 *src_pixmap = GDK_PIXMAP_IMPL_X11 (src_impl);
+ /* Work around an Xserver bug where non-visible areas from
+ * a pixmap to a window will clear the window background
+ * in destination areas that are supposed to be clipped out.
+ * This is a problem with client side windows as this means
+ * things may draw outside the virtual windows. This could
+ * also happen for window to window copies, but I don't
+ * think we generate any calls like that.
+ *
+ * See:
+ * http://lists.freedesktop.org/archives/xorg/2009-February/043318.html
+ */
+ if (xsrc < 0)
+ {
+ width += xsrc;
+ xdest -= xsrc;
+ xsrc = 0;
+ }
+
+ if (ysrc < 0)
+ {
+ height += ysrc;
+ ydest -= ysrc;
+ ysrc = 0;
+ }
+
+ if (xsrc + width > src_pixmap->width)
+ width = src_pixmap->width - xsrc;
+ if (ysrc + height > src_pixmap->height)
+ height = src_pixmap->height - ysrc;
+ }
if (src_depth == 1)
{
XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
- src_impl ? src_impl->xid : GDK_DRAWABLE_XID (src),
+ src_impl->xid,
impl->xid,
GDK_GC_GET_XGC (gc),
xsrc, ysrc,
else if (dest_depth != 0 && src_depth == dest_depth)
{
XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
- src_impl ? src_impl->xid : GDK_DRAWABLE_XID (src),
+ src_impl->xid,
impl->xid,
GDK_GC_GET_XGC (gc),
xsrc, ysrc,
GdkDrawable *impl;
if (GDK_IS_WINDOW (drawable))
- impl = ((GdkPixmapObject *)drawable)->impl;
+ {
+ GdkWindow *window = (GdkWindow *)drawable;
+
+ /* Try to ensure the window has a native window */
+ if (!_gdk_window_has_impl (window))
+ {
+ gdk_window_ensure_native (window);
+
+ /* We sync here to ensure the window is created in the Xserver when
+ * this function returns. This is required because the returned XID
+ * for this window must be valid immediately, even with another
+ * connection to the Xserver */
+ gdk_display_sync (gdk_drawable_get_display (window));
+ }
+
+ if (!GDK_WINDOW_IS_X11 (window))
+ {
+ g_warning (G_STRLOC " drawable is not a native X11 window");
+ return None;
+ }
+
+ impl = ((GdkWindowObject *)drawable)->impl;
+ }
else if (GDK_IS_PIXMAP (drawable))
impl = ((GdkPixmapObject *)drawable)->impl;
else
impl->cairo_surface = NULL;
}
+void
+_gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
+ int width,
+ int height)
+{
+ cairo_xlib_surface_set_size (surface, width, height);
+}
+
+cairo_surface_t *
+_gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
+ int width,
+ int height)
+{
+ GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+ GdkVisual *visual;
+
+ visual = gdk_drawable_get_visual (drawable);
+ if (visual)
+ return cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
+ impl->xid,
+ GDK_VISUAL_XVISUAL (visual),
+ width, height);
+ else if (gdk_drawable_get_depth (drawable) == 1)
+ return cairo_xlib_surface_create_for_bitmap (GDK_SCREEN_XDISPLAY (impl->screen),
+ impl->xid,
+ GDK_SCREEN_XSCREEN (impl->screen),
+ width, height);
+ else
+ {
+ g_warning ("Using Cairo rendering requires the drawable argument to\n"
+ "have a specified colormap. All windows have a colormap,\n"
+ "however, pixmaps only have colormap by default if they\n"
+ "were created with a non-NULL window argument. Otherwise\n"
+ "a colormap must be set on them with gdk_drawable_set_colormap");
+ return NULL;
+ }
+
+}
+
static cairo_surface_t *
gdk_x11_ref_cairo_surface (GdkDrawable *drawable)
{
if (!impl->cairo_surface)
{
- GdkVisual *visual = NULL;
int width, height;
- visual = gdk_drawable_get_visual (drawable);
-
gdk_drawable_get_size (drawable, &width, &height);
- if (visual)
- impl->cairo_surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
- impl->xid,
- GDK_VISUAL_XVISUAL (visual),
- width, height);
- else if (gdk_drawable_get_depth (drawable) == 1)
- impl->cairo_surface = cairo_xlib_surface_create_for_bitmap (GDK_SCREEN_XDISPLAY (impl->screen),
- impl->xid,
- GDK_SCREEN_XSCREEN (impl->screen),
- width, height);
- else
- {
- g_warning ("Using Cairo rendering requires the drawable argument to\n"
- "have a specified colormap. All windows have a colormap,\n"
- "however, pixmaps only have colormap by default if they\n"
- "were created with a non-NULL window argument. Otherwise\n"
- "a colormap must be set on them with gdk_drawable_set_colormap");
- return NULL;
- }
-
- cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
- drawable, gdk_x11_cairo_surface_destroy);
+ impl->cairo_surface = _gdk_windowing_create_cairo_surface (drawable, width, height);
+
+ if (impl->cairo_surface)
+ cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
+ drawable, gdk_x11_cairo_surface_destroy);
}
else
cairo_surface_reference (impl->cairo_surface);
GdkEvent *event;
g_return_val_if_fail (window != NULL, NULL);
-
+
XIfEvent (GDK_WINDOW_XDISPLAY (window), &xevent,
graphics_expose_predicate, (XPointer) window);
gdk_event_get_time (event));
}
+static gboolean
+is_parent_of (GdkWindow *parent,
+ GdkWindow *child)
+{
+ GdkWindow *w;
+
+ w = child;
+ while (w != NULL)
+ {
+ if (w == parent)
+ return TRUE;
+
+ w = gdk_window_get_parent (w);
+ }
+
+ return FALSE;
+}
+
static gboolean
gdk_event_translate (GdkDisplay *display,
GdkEvent *event,
GdkWindow *filter_window;
GdkWindowImplX11 *window_impl = NULL;
gboolean return_val;
- gint xoffset, yoffset;
GdkScreen *screen = NULL;
GdkScreenX11 *screen_x11 = NULL;
GdkToplevelX11 *toplevel = NULL;
if (window != NULL)
{
+ /* Apply keyboard grabs to non-native windows */
+ if (/* Is key event */
+ (xevent->type == KeyPress || xevent->type == KeyRelease) &&
+ /* And we have a grab */
+ display->keyboard_grab.window != NULL &&
+ (
+ /* The window is not a descendant of the grabbed window */
+ !is_parent_of ((GdkWindow *)display->keyboard_grab.window, window) ||
+ /* Or owner event is false */
+ !display->keyboard_grab.owner_events
+ )
+ )
+ {
+ /* Report key event against grab window */
+ window = display->keyboard_grab.window;;
+ window_private = (GdkWindowObject *) window;
+ }
+
window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
/* Move key events on focus window to the real toplevel, and
return_val = TRUE;
- if (window)
- {
- _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
- }
- else
- {
- xoffset = 0;
- yoffset = 0;
- }
-
switch (xevent->type)
{
case KeyPress:
xevent->xbutton.x, xevent->xbutton.y,
xevent->xbutton.button));
- if (window_private == NULL ||
- ((window_private->extension_events != 0) &&
- display_x11->input_ignore_core))
+ if (window_private == NULL)
{
return_val = FALSE;
break;
event->scroll.window = window;
event->scroll.time = xevent->xbutton.time;
- event->scroll.x = xevent->xbutton.x + xoffset;
- event->scroll.y = xevent->xbutton.y + yoffset;
+ event->scroll.x = xevent->xbutton.x;
+ event->scroll.y = xevent->xbutton.y;
event->scroll.x_root = (gfloat)xevent->xbutton.x_root;
event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
event->scroll.state = (GdkModifierType) xevent->xbutton.state;
event->button.type = GDK_BUTTON_PRESS;
event->button.window = window;
event->button.time = xevent->xbutton.time;
- event->button.x = xevent->xbutton.x + xoffset;
- event->button.y = xevent->xbutton.y + yoffset;
+ event->button.x = xevent->xbutton.x;
+ event->button.y = xevent->xbutton.y;
event->button.x_root = (gfloat)xevent->xbutton.x_root;
event->button.y_root = (gfloat)xevent->xbutton.y_root;
event->button.axes = NULL;
return_val = FALSE;
break;
}
-
- _gdk_event_button_generate (display, event);
break;
}
set_user_time (window, event);
- _gdk_xgrab_check_button_event (window, xevent);
break;
case ButtonRelease:
xevent->xbutton.x, xevent->xbutton.y,
xevent->xbutton.button));
- if (window_private == NULL ||
- ((window_private->extension_events != 0) &&
- display_x11->input_ignore_core))
+ if (window_private == NULL)
{
return_val = FALSE;
break;
event->button.type = GDK_BUTTON_RELEASE;
event->button.window = window;
event->button.time = xevent->xbutton.time;
- event->button.x = xevent->xbutton.x + xoffset;
- event->button.y = xevent->xbutton.y + yoffset;
+ event->button.x = xevent->xbutton.x;
+ event->button.y = xevent->xbutton.y;
event->button.x_root = (gfloat)xevent->xbutton.x_root;
event->button.y_root = (gfloat)xevent->xbutton.y_root;
event->button.axes = NULL;
event->button.device = display->core_pointer;
if (!set_screen_from_root (display, event, xevent->xbutton.root))
- {
- return_val = FALSE;
- break;
- }
-
- _gdk_xgrab_check_button_event (window, xevent);
+ return_val = FALSE;
+
break;
case MotionNotify:
xevent->xmotion.x, xevent->xmotion.y,
(xevent->xmotion.is_hint) ? "true" : "false"));
- if (window_private == NULL ||
- ((window_private->extension_events != 0) &&
- display_x11->input_ignore_core))
+ if (window_private == NULL)
{
return_val = FALSE;
break;
event->motion.type = GDK_MOTION_NOTIFY;
event->motion.window = window;
event->motion.time = xevent->xmotion.time;
- event->motion.x = xevent->xmotion.x + xoffset;
- event->motion.y = xevent->xmotion.y + yoffset;
+ event->motion.x = xevent->xmotion.x;
+ event->motion.y = xevent->xmotion.y;
event->motion.x_root = (gfloat)xevent->xmotion.x_root;
event->motion.y_root = (gfloat)xevent->xmotion.y_root;
event->motion.axes = NULL;
}
}
- /* Tell XInput stuff about it if appropriate */
- if (window_private &&
- !GDK_WINDOW_DESTROYED (window) &&
- window_private->extension_events != 0)
- _gdk_input_enter_event (&xevent->xcrossing, window);
-
event->crossing.type = GDK_ENTER_NOTIFY;
event->crossing.window = window;
event->crossing.subwindow = NULL;
event->crossing.time = xevent->xcrossing.time;
- event->crossing.x = xevent->xcrossing.x + xoffset;
- event->crossing.y = xevent->xcrossing.y + yoffset;
+ event->crossing.x = xevent->xcrossing.x;
+ event->crossing.y = xevent->xcrossing.y;
event->crossing.x_root = xevent->xcrossing.x_root;
event->crossing.y_root = xevent->xcrossing.y_root;
event->crossing.subwindow = NULL;
event->crossing.time = xevent->xcrossing.time;
- event->crossing.x = xevent->xcrossing.x + xoffset;
- event->crossing.y = xevent->xcrossing.y + yoffset;
+ event->crossing.x = xevent->xcrossing.x;
+ event->crossing.y = xevent->xcrossing.y;
event->crossing.x_root = xevent->xcrossing.x_root;
event->crossing.y_root = xevent->xcrossing.y_root;
{
GdkRectangle expose_rect;
- expose_rect.x = xevent->xexpose.x + xoffset;
- expose_rect.y = xevent->xexpose.y + yoffset;
+ expose_rect.x = xevent->xexpose.x;
+ expose_rect.y = xevent->xexpose.y;
expose_rect.width = xevent->xexpose.width;
expose_rect.height = xevent->xexpose.height;
break;
}
- expose_rect.x = xevent->xgraphicsexpose.x + xoffset;
- expose_rect.y = xevent->xgraphicsexpose.y + yoffset;
+ expose_rect.x = xevent->xgraphicsexpose.x;
+ expose_rect.y = xevent->xgraphicsexpose.y;
expose_rect.width = xevent->xgraphicsexpose.width;
expose_rect.height = xevent->xgraphicsexpose.height;
: ""));
if (window && GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
{
- window_impl->width = xevent->xconfigure.width;
- window_impl->height = xevent->xconfigure.height;
-
+ window_private->width = xevent->xconfigure.width;
+ window_private->height = xevent->xconfigure.height;
+
_gdk_x11_drawable_update_size (window_private->impl);
_gdk_x11_screen_size_changed (screen, xevent);
}
if (window &&
xevent->xconfigure.event == xevent->xconfigure.window &&
!GDK_WINDOW_DESTROYED (window) &&
- (window_private->extension_events != 0))
+ window_private->input_window != NULL)
_gdk_input_configure_event (&xevent->xconfigure, window);
#ifdef HAVE_XSYNC
}
#endif
- if (!window ||
+ if (!window ||
xevent->xconfigure.event != xevent->xconfigure.window ||
GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
}
window_private->x = event->configure.x;
window_private->y = event->configure.y;
- window_impl->width = xevent->xconfigure.width;
- window_impl->height = xevent->xconfigure.height;
+ window_private->width = xevent->xconfigure.width;
+ window_private->height = xevent->xconfigure.height;
+ _gdk_window_update_size (window);
_gdk_x11_drawable_update_size (window_private->impl);
if (window_private->resize_count >= 1)
if (window_private &&
!GDK_WINDOW_DESTROYED (window_private) &&
- (window_private->extension_events != 0))
- return_val = _gdk_input_other_event(event, xevent, window);
+ window_private->input_window)
+ return_val = _gdk_input_other_event (event, xevent, window);
else
return_val = FALSE;
if (window)
g_object_unref (window);
-
+
return return_val;
}
if (gdk_event_translate (display, event, &xevent, FALSE))
{
((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
+ _gdk_windowing_got_event (display, node, event, xevent.xany.serial);
}
else
{
void
_gdk_windowing_gc_set_clip_region (GdkGC *gc,
- const GdkRegion *region)
+ const GdkRegion *region,
+ gboolean reset_origin)
{
GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
x11_gc->have_clip_region = region != NULL;
- gc->clip_x_origin = 0;
- gc->clip_y_origin = 0;
+ if (reset_origin)
+ {
+ gc->clip_x_origin = 0;
+ gc->clip_y_origin = 0;
+ }
x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
}
} u;
};
-struct _GdkWindowParentPos
-{
- gint x;
- gint y;
- gint x11_x;
- gint x11_y;
- GdkRectangle clip_rect;
-};
-
-static void gdk_window_compute_position (GdkWindowImplX11 *window,
- GdkWindowParentPos *parent_pos,
- GdkXPositionInfo *info);
-static void gdk_window_compute_parent_pos (GdkWindowImplX11 *window,
- GdkWindowParentPos *parent_pos);
-static void gdk_window_premove (GdkWindow *window,
- GdkWindowParentPos *parent_pos);
-static void gdk_window_postmove (GdkWindow *window,
- GdkWindowParentPos *parent_pos);
-static void gdk_window_queue_translation (GdkWindow *window,
- GdkRegion *area,
- gint dx,
- gint dy);
-static void gdk_window_clip_changed (GdkWindow *window,
- GdkRectangle *old_clip,
- GdkRectangle *new_clip);
-
-void
-_gdk_x11_window_get_offsets (GdkWindow *window,
- gint *x_offset,
- gint *y_offset)
-{
- GdkWindowImplX11 *impl =
- GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
-
- *x_offset = impl->position_info.x_offset;
- *y_offset = impl->position_info.y_offset;
-}
-
-void
-_gdk_window_init_position (GdkWindow *window)
-{
- GdkWindowParentPos parent_pos;
- GdkWindowImplX11 *impl;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- impl =
- GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
-
- gdk_window_compute_parent_pos (impl, &parent_pos);
- gdk_window_compute_position (impl, &parent_pos, &impl->position_info);
-}
-
-static void
-gdk_window_copy_area_scroll (GdkWindow *window,
- GdkRectangle *dest_rect,
- gint dx,
- gint dy)
-{
- GdkWindowObject *obj = GDK_WINDOW_OBJECT (window);
- GList *l;
-
- if (dest_rect->width > 0 && dest_rect->height > 0)
- {
- GdkGC *gc;
-
- gc = _gdk_drawable_get_scratch_gc (window, TRUE);
-
- gdk_window_queue_translation (window, NULL, dx, dy);
-
- XCopyArea (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- GDK_WINDOW_XID (window),
- gdk_x11_gc_get_xgc (gc),
- dest_rect->x - dx, dest_rect->y - dy,
- dest_rect->width, dest_rect->height,
- dest_rect->x, dest_rect->y);
- }
-
- for (l = obj->children; l; l = l->next)
- {
- GdkWindow *child = (GdkWindow*) l->data;
- GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
-
- gdk_window_move (child, child_obj->x + dx, child_obj->y + dy);
- }
-}
-
-static void
-compute_intermediate_position (GdkXPositionInfo *position_info,
- GdkXPositionInfo *new_info,
- gint d_xoffset,
- gint d_yoffset,
- GdkRectangle *new_position)
-{
- gint new_x0, new_x1, new_y0, new_y1;
-
- /* Wrap d_xoffset, d_yoffset into [-32768,32767] range. For the
- * purposes of subwindow movement, it doesn't matter if we are
- * off by a factor of 65536, and if we don't do this range
- * reduction, we'll end up with invalid widths.
- */
- d_xoffset = (gint16)d_xoffset;
- d_yoffset = (gint16)d_yoffset;
-
- if (d_xoffset < 0)
- {
- new_x0 = position_info->x + d_xoffset;
- new_x1 = position_info->x + position_info->width;
- }
- else
- {
- new_x0 = position_info->x;
- new_x1 = position_info->x + new_info->width + d_xoffset;
- }
-
- new_position->x = new_x0;
- new_position->width = new_x1 - new_x0;
-
- if (d_yoffset < 0)
- {
- new_y0 = position_info->y + d_yoffset;
- new_y1 = position_info->y + position_info->height;
- }
- else
- {
- new_y0 = position_info->y;
- new_y1 = position_info->y + new_info->height + d_yoffset;
- }
-
- new_position->y = new_y0;
- new_position->height = new_y1 - new_y0;
-}
-
-static void
-translate_pos (GdkWindowParentPos *dest, GdkWindowParentPos *src,
- GdkWindowObject *obj, GdkXPositionInfo *pos_info,
- gboolean set_clip)
-{
- dest->x = src->x + obj->x;
- dest->y = src->y + obj->y;
- dest->x11_x = src->x11_x + pos_info->x;
- dest->x11_y = src->x11_y + pos_info->y;
-
- if (set_clip)
- dest->clip_rect = pos_info->clip_rect;
-}
-
-static void
-move (GdkWindow *window, GdkXPositionInfo *pos)
-{
- XMoveWindow (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window), pos->x, pos->y);
-}
-
-static void
-move_relative (GdkWindow *window, GdkRectangle *rect,
- gint dx, gint dy)
-{
- XMoveWindow (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- rect->x + dx, rect->y + dy);
-}
-
-static void
-move_resize (GdkWindow *window, GdkRectangle *pos)
-{
- XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- pos->x, pos->y, pos->width, pos->height);
-}
-
-static void
-gdk_window_guffaw_scroll (GdkWindow *window,
- gint dx,
- gint dy)
-{
- GdkWindowObject *obj = GDK_WINDOW_OBJECT (window);
- GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
- gint d_xoffset = -dx;
- gint d_yoffset = -dy;
- GdkRectangle new_position;
- GdkXPositionInfo new_info;
- GdkWindowParentPos parent_pos;
- GList *l;
-
- gdk_window_compute_parent_pos (impl, &parent_pos);
- gdk_window_compute_position (impl, &parent_pos, &new_info);
-
- translate_pos (&parent_pos, &parent_pos, obj, &new_info, TRUE);
-
- _gdk_x11_window_tmp_unset_bg (window, FALSE);;
-
- if (dx > 0 || dy > 0)
- gdk_window_queue_translation (window, NULL, MAX (dx, 0), MAX (dy, 0));
-
- gdk_window_set_static_gravities (window, TRUE);
-
- compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
- &new_position);
-
- move_resize (window, &new_position);
-
- for (l = obj->children; l; l = l->next)
- {
- GdkWindow *child = (GdkWindow*) l->data;
- GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
-
- child_obj->x -= d_xoffset;
- child_obj->y -= d_yoffset;
-
- gdk_window_premove (child, &parent_pos);
- }
-
- move_relative (window, &new_position, -d_xoffset, -d_yoffset);
-
- if (dx < 0 || dy < 0)
- gdk_window_queue_translation (window, NULL, MIN (dx, 0), MIN (dy, 0));
-
- move_resize (window, (GdkRectangle *) &impl->position_info);
-
- if (impl->position_info.no_bg)
- _gdk_x11_window_tmp_reset_bg (window, FALSE);
-
- impl->position_info = new_info;
-
- g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &parent_pos);
-}
-
-void
-_gdk_x11_window_scroll (GdkWindow *window,
- gint dx,
- gint dy)
-{
- gboolean can_guffaw_scroll = FALSE;
- GdkRegion *invalidate_region;
- GdkWindowImplX11 *impl;
- GdkWindowObject *obj;
- GdkRectangle src_rect, dest_rect;
-
- obj = GDK_WINDOW_OBJECT (window);
- impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
- /* Move the current invalid region */
- if (obj->update_area)
- gdk_region_offset (obj->update_area, dx, dy);
-
- /* impl->position_info.clip_rect isn't meaningful for toplevels */
- if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
- src_rect = impl->position_info.clip_rect;
- else
- {
- src_rect.x = 0;
- src_rect.y = 0;
- src_rect.width = impl->width;
- src_rect.height = impl->height;
- }
-
- invalidate_region = gdk_region_rectangle (&src_rect);
-
- dest_rect = src_rect;
- dest_rect.x += dx;
- dest_rect.y += dy;
- gdk_rectangle_intersect (&dest_rect, &src_rect, &dest_rect);
-
- if (dest_rect.width > 0 && dest_rect.height > 0)
- {
- GdkRegion *tmp_region;
-
- tmp_region = gdk_region_rectangle (&dest_rect);
- gdk_region_subtract (invalidate_region, tmp_region);
- gdk_region_destroy (tmp_region);
- }
-
- gdk_window_invalidate_region (window, invalidate_region, TRUE);
- gdk_region_destroy (invalidate_region);
-
- /* We can guffaw scroll if we are a child window, and the parent
- * does not extend beyond our edges. Otherwise, we use XCopyArea, then
- * move any children later
- */
- if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
- {
- GdkWindowImplX11 *parent_impl = GDK_WINDOW_IMPL_X11 (obj->parent->impl);
- can_guffaw_scroll = ((dx == 0 || (obj->x <= 0 && obj->x + impl->width >= parent_impl->width)) &&
- (dy == 0 || (obj->y <= 0 && obj->y + impl->height >= parent_impl->height)));
- }
-
- if (!obj->children || !can_guffaw_scroll)
- gdk_window_copy_area_scroll (window, &dest_rect, dx, dy);
- else
- gdk_window_guffaw_scroll (window, dx, dy);
-}
-
-void
-_gdk_x11_window_move_region (GdkWindow *window,
- const GdkRegion *region,
- gint dx,
- gint dy)
-{
- GdkWindowImplX11 *impl;
- GdkWindowObject *private;
- GdkRegion *window_clip;
- GdkRegion *src_region;
- GdkRegion *brought_in;
- GdkRegion *dest_region;
- GdkRegion *moving_invalid_region;
- GdkRectangle dest_extents;
- GdkGC *gc;
-
- private = GDK_WINDOW_OBJECT (window);
- impl = GDK_WINDOW_IMPL_X11 (private->impl);
-
- window_clip = gdk_region_rectangle (&impl->position_info.clip_rect);
-
- /* compute source regions */
- src_region = gdk_region_copy (region);
- brought_in = gdk_region_copy (region);
- gdk_region_intersect (src_region, window_clip);
-
- gdk_region_subtract (brought_in, src_region);
- gdk_region_offset (brought_in, dx, dy);
-
- /* compute destination regions */
- dest_region = gdk_region_copy (src_region);
- gdk_region_offset (dest_region, dx, dy);
- gdk_region_intersect (dest_region, window_clip);
- gdk_region_get_clipbox (dest_region, &dest_extents);
-
- gdk_region_destroy (window_clip);
-
- /* calculating moving part of current invalid area */
- moving_invalid_region = NULL;
- if (private->update_area)
- {
- moving_invalid_region = gdk_region_copy (private->update_area);
- gdk_region_intersect (moving_invalid_region, src_region);
- gdk_region_offset (moving_invalid_region, dx, dy);
- }
-
- /* invalidate all of the src region */
- gdk_window_invalidate_region (window, src_region, FALSE);
-
- /* un-invalidate destination region */
- if (private->update_area)
- gdk_region_subtract (private->update_area, dest_region);
-
- /* invalidate moving parts of existing update area */
- if (moving_invalid_region)
- {
- gdk_window_invalidate_region (window, moving_invalid_region, FALSE);
- gdk_region_destroy (moving_invalid_region);
- }
-
- /* invalidate area brought in from off-screen */
- gdk_window_invalidate_region (window, brought_in, FALSE);
- gdk_region_destroy (brought_in);
-
- /* Actually do the moving */
- gdk_window_queue_translation (window, src_region, dx, dy);
-
- gc = _gdk_drawable_get_scratch_gc (window, TRUE);
- gdk_gc_set_clip_region (gc, dest_region);
-
- XCopyArea (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- GDK_WINDOW_XID (window),
- GDK_GC_XGC (gc),
- dest_extents.x - dx, dest_extents.y - dy,
- dest_extents.width, dest_extents.height,
- dest_extents.x, dest_extents.y);
-
- /* Unset clip region of cached GC */
- gdk_gc_set_clip_region (gc, NULL);
-
- gdk_region_destroy (src_region);
- gdk_region_destroy (dest_region);
-}
-
-static void
-reset_backgrounds (GdkWindow *window)
-{
- GdkWindowObject *obj = (GdkWindowObject *)window;
-
- _gdk_x11_window_tmp_reset_bg (window, FALSE);
-
- if (obj->parent)
- _gdk_x11_window_tmp_reset_bg ((GdkWindow *)obj->parent, FALSE);
-}
-
-static void
-map_if_needed (GdkWindow *window, GdkXPositionInfo *pos_info)
-{
- GdkWindowObject *obj = (GdkWindowObject *) window;
- GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
- if (!impl->position_info.mapped && pos_info->mapped && GDK_WINDOW_IS_MAPPED (obj))
- XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
-}
-
-static void
-unmap_if_needed (GdkWindow *window, GdkXPositionInfo *pos_info)
-{
- GdkWindowObject *obj = (GdkWindowObject *) window;
- GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
- if (impl->position_info.mapped && !pos_info->mapped)
- XUnmapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
-}
-
void
_gdk_window_move_resize_child (GdkWindow *window,
gint x,
{
GdkWindowImplX11 *impl;
GdkWindowObject *obj;
- GdkXPositionInfo new_info;
- GdkWindowParentPos parent_pos;
-
- gint d_xoffset, d_yoffset;
- gint dx, dy;
- gboolean is_move;
- gboolean is_resize;
-
- GdkRectangle old_pos;
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
impl = GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
obj = GDK_WINDOW_OBJECT (window);
- dx = x - obj->x;
- dy = y - obj->y;
-
- is_move = dx != 0 || dy != 0;
- is_resize = impl->width != width || impl->height != height;
-
- if (!is_move && !is_resize)
- return;
-
- old_pos.x = obj->x;
- old_pos.y = obj->y;
- old_pos.width = impl->width;
- old_pos.height = impl->height;
-
- obj->x = x;
- obj->y = y;
- impl->width = width;
- impl->height = height;
-
- gdk_window_compute_parent_pos (impl, &parent_pos);
- gdk_window_compute_position (impl, &parent_pos, &new_info);
-
- gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
-
- translate_pos (&parent_pos, &parent_pos, obj, &new_info, TRUE);
-
- d_xoffset = new_info.x_offset - impl->position_info.x_offset;
- d_yoffset = new_info.y_offset - impl->position_info.y_offset;
-
- if (d_xoffset != 0 || d_yoffset != 0)
+ if (width > 65535 ||
+ height > 65535)
{
- GdkRectangle new_position;
-
- gdk_window_set_static_gravities (window, TRUE);
-
- if (d_xoffset < 0 || d_yoffset < 0)
- gdk_window_queue_translation (window, NULL, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
-
- compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
- &new_position);
+ g_warning ("Native children wider or taller than 65535 pixels are not supported");
- move_resize (window, &new_position);
-
- g_list_foreach (obj->children, (GFunc) gdk_window_premove, &parent_pos);
-
- move_relative (window, &new_position, dx, dy);
-
- if (d_xoffset > 0 || d_yoffset > 0)
- gdk_window_queue_translation (window, NULL, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
-
- move_resize (window, (GdkRectangle *) &new_info);
-
- reset_backgrounds (window);
-
- map_if_needed (window, &new_info);
-
- impl->position_info = new_info;
-
- g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &parent_pos);
+ if (width > 65535)
+ width = 65535;
+ if (height > 65535)
+ height = 65535;
}
- else
- {
- if (is_move && is_resize)
- gdk_window_set_static_gravities (window, FALSE);
-
- unmap_if_needed (window, &new_info);
-
- g_list_foreach (obj->children, (GFunc) gdk_window_premove, &parent_pos);
-
- if (is_resize)
- move_resize (window, (GdkRectangle *) &new_info);
- else
- move (window, &new_info);
-
- g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &parent_pos);
-
- reset_backgrounds (window);
-
- map_if_needed (window, &new_info);
-
- impl->position_info = new_info;
- }
-
- if (GDK_WINDOW_IS_MAPPED (obj) && obj->parent && !obj->input_only)
- gdk_window_invalidate_rect ((GdkWindow *)obj->parent, &old_pos, FALSE);
-}
-
-static void
-gdk_window_compute_position (GdkWindowImplX11 *window,
- GdkWindowParentPos *parent_pos,
- GdkXPositionInfo *info)
-{
- GdkWindowObject *wrapper;
- int parent_x_offset;
- int parent_y_offset;
-
- g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (window));
-
- wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_X11 (window)->wrapper);
-
- info->big = FALSE;
-
- if (window->width <= 32767)
- {
- info->width = window->width;
- info->x = parent_pos->x + wrapper->x - parent_pos->x11_x;
- }
- else
- {
- info->big = TRUE;
- info->width = 32767;
- if (parent_pos->x + wrapper->x < -16384)
- {
- if (parent_pos->x + wrapper->x + window->width < 16384)
- info->x = parent_pos->x + wrapper->x + window->width - info->width - parent_pos->x11_x;
- else
- info->x = -16384 - parent_pos->x11_x;
- }
- else
- info->x = parent_pos->x + wrapper->x - parent_pos->x11_x;
- }
-
- if (window->height <= 32767)
- {
- info->height = window->height;
- info->y = parent_pos->y + wrapper->y - parent_pos->x11_y;
- }
- else
- {
- info->big = TRUE;
- info->height = 32767;
- if (parent_pos->y + wrapper->y < -16384)
- {
- if (parent_pos->y + wrapper->y + window->height < 16384)
- info->y = parent_pos->y + wrapper->y + window->height - info->height - parent_pos->x11_y;
- else
- info->y = -16384 - parent_pos->x11_y;
- }
- else
- info->y = parent_pos->y + wrapper->y - parent_pos->x11_y;
- }
-
- parent_x_offset = parent_pos->x11_x - parent_pos->x;
- parent_y_offset = parent_pos->x11_y - parent_pos->y;
- info->x_offset = parent_x_offset + info->x - wrapper->x;
- info->y_offset = parent_y_offset + info->y - wrapper->y;
-
- /* We don't considering the clipping of toplevel windows and their immediate children
- * by their parents, and simply always map those windows.
- */
- if (parent_pos->clip_rect.width == G_MAXINT)
- info->mapped = TRUE;
- /* Check if the window would wrap around into the visible space in either direction */
- else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
- info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
- info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
- info->y + info->height + parent_y_offset > parent_pos->clip_rect.y + 65536)
- info->mapped = FALSE;
- else
- info->mapped = TRUE;
-
- info->no_bg = FALSE;
-
- if (GDK_WINDOW_TYPE (wrapper) == GDK_WINDOW_CHILD)
- {
- info->clip_rect.x = wrapper->x;
- info->clip_rect.y = wrapper->y;
- info->clip_rect.width = window->width;
- info->clip_rect.height = window->height;
-
- gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
-
- info->clip_rect.x -= wrapper->x;
- info->clip_rect.y -= wrapper->y;
- }
- else
- {
- info->clip_rect.x = 0;
- info->clip_rect.y = 0;
- info->clip_rect.width = G_MAXINT;
- info->clip_rect.height = G_MAXINT;
- }
-}
-
-static void
-gdk_window_compute_parent_pos (GdkWindowImplX11 *window,
- GdkWindowParentPos *parent_pos)
-{
- GdkWindowObject *wrapper;
- GdkWindowObject *parent;
- GdkRectangle tmp_clip;
-
- int clip_xoffset = 0;
- int clip_yoffset = 0;
-
- g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (window));
-
- wrapper =
- GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_X11 (window)->wrapper);
-
- parent_pos->x = 0;
- parent_pos->y = 0;
- parent_pos->x11_x = 0;
- parent_pos->x11_y = 0;
-
- /* We take a simple approach here and simply consider toplevel
- * windows not to clip their children on the right/bottom, since the
- * size of toplevel windows is not directly under our
- * control. Clipping only really matters when scrolling and
- * generally we aren't going to be moving the immediate child of a
- * toplevel beyond the bounds of that toplevel.
- *
- * We could go ahead and recompute the clips of toplevel windows and
- * their descendents when we receive size notification, but it would
- * probably not be an improvement in most cases.
- */
- parent_pos->clip_rect.x = 0;
- parent_pos->clip_rect.y = 0;
- parent_pos->clip_rect.width = G_MAXINT;
- parent_pos->clip_rect.height = G_MAXINT;
-
- parent = (GdkWindowObject *)wrapper->parent;
- while (parent && parent->window_type == GDK_WINDOW_CHILD)
- {
- GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (parent->impl);
-
- tmp_clip.x = - clip_xoffset;
- tmp_clip.y = - clip_yoffset;
- tmp_clip.width = impl->width;
- tmp_clip.height = impl->height;
-
- gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
-
- translate_pos (parent_pos, parent_pos, parent,
- &impl->position_info, FALSE);
-
- clip_xoffset += parent->x;
- clip_yoffset += parent->y;
-
- parent = (GdkWindowObject *)parent->parent;
- }
-}
-
-static void
-gdk_window_premove (GdkWindow *window,
- GdkWindowParentPos *parent_pos)
-{
- GdkWindowImplX11 *impl;
- GdkWindowObject *obj;
- GdkXPositionInfo new_info;
- gint d_xoffset, d_yoffset;
- GdkWindowParentPos this_pos;
-
- obj = (GdkWindowObject *) window;
- impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
- gdk_window_compute_position (impl, parent_pos, &new_info);
-
- gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
-
- translate_pos (&this_pos, parent_pos, obj, &new_info, TRUE);
-
- unmap_if_needed (window, &new_info);
-
- d_xoffset = new_info.x_offset - impl->position_info.x_offset;
- d_yoffset = new_info.y_offset - impl->position_info.y_offset;
-
- if (d_xoffset != 0 || d_yoffset != 0)
- {
- GdkRectangle new_position;
-
- if (d_xoffset < 0 || d_yoffset < 0)
- gdk_window_queue_translation (window, NULL, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
-
- compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
- &new_position);
-
- move_resize (window, &new_position);
- }
-
- g_list_foreach (obj->children, (GFunc) gdk_window_premove, &this_pos);
-}
-
-static void
-gdk_window_postmove (GdkWindow *window,
- GdkWindowParentPos *parent_pos)
-{
- GdkWindowImplX11 *impl;
- GdkWindowObject *obj;
- GdkXPositionInfo new_info;
- gint d_xoffset, d_yoffset;
- GdkWindowParentPos this_pos;
-
- obj = (GdkWindowObject *) window;
- impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
- gdk_window_compute_position (impl, parent_pos, &new_info);
+ obj->x = x;
+ obj->y = y;
+ obj->width = width;
+ obj->height = height;
- translate_pos (&this_pos, parent_pos, obj, &new_info, TRUE);
+ /* We don't really care about origin overflow, because on overflow
+ the window won't be visible anyway and thus it will be shaped
+ to nothing */
- d_xoffset = new_info.x_offset - impl->position_info.x_offset;
- d_yoffset = new_info.y_offset - impl->position_info.y_offset;
- if (d_xoffset != 0 || d_yoffset != 0)
- {
- if (d_xoffset > 0 || d_yoffset > 0)
- gdk_window_queue_translation (window, NULL, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
-
- move_resize (window, (GdkRectangle *) &new_info);
- }
-
- map_if_needed (window, &new_info);
-
- reset_backgrounds (window);
-
- impl->position_info = new_info;
-
- g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &this_pos);
+ _gdk_x11_window_tmp_unset_parent_bg (window);
+ _gdk_x11_window_tmp_unset_bg (window, TRUE);
+ XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ obj->x + obj->parent->abs_x,
+ obj->y + obj->parent->abs_y,
+ width, height);
+ _gdk_x11_window_tmp_reset_parent_bg (window);
+ _gdk_x11_window_tmp_reset_bg (window, TRUE);
}
static Bool
g_queue_push_tail (display_x11->translate_queue, item);
}
-static void
-gdk_window_queue_translation (GdkWindow *window,
- GdkRegion *area,
- gint dx,
- gint dy)
+void
+_gdk_x11_window_queue_translation (GdkWindow *window,
+ GdkRegion *area,
+ gint dx,
+ gint dy)
{
GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
item->type = GDK_WINDOW_QUEUE_TRANSLATE;
}
gboolean
-_gdk_windowing_window_queue_antiexpose (GdkWindow *window,
- GdkRegion *area)
+_gdk_x11_window_queue_antiexpose (GdkWindow *window,
+ GdkRegion *area)
{
GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
item->type = GDK_WINDOW_QUEUE_ANTIEXPOSE;
{
GdkWindowImplX11 *impl;
GdkRegion *invalidate_region = gdk_region_rectangle (area);
- GdkRegion *clip_region;
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
impl = GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
}
}
- clip_region = gdk_region_rectangle (&impl->position_info.clip_rect);
- gdk_region_intersect (invalidate_region, clip_region);
-
if (!gdk_region_empty (invalidate_region))
- gdk_window_invalidate_region (window, invalidate_region, FALSE);
+ _gdk_window_invalidate_for_expose (window, invalidate_region);
gdk_region_destroy (invalidate_region);
- gdk_region_destroy (clip_region);
-}
-
-static void
-gdk_window_clip_changed (GdkWindow *window, GdkRectangle *old_clip, GdkRectangle *new_clip)
-{
- GdkWindowImplX11 *impl;
- GdkWindowObject *obj;
- GdkRegion *old_clip_region;
- GdkRegion *new_clip_region;
-
- if (((GdkWindowObject *)window)->input_only)
- return;
-
- obj = (GdkWindowObject *) window;
- impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
- old_clip_region = gdk_region_rectangle (old_clip);
- new_clip_region = gdk_region_rectangle (new_clip);
-
- /* We need to update this here because gdk_window_invalidate_region makes
- * use if it (through gdk_drawable_get_visible_region
- */
- impl->position_info.clip_rect = *new_clip;
-
- /* Trim invalid region of window to new clip rectangle
- */
- if (obj->update_area)
- gdk_region_intersect (obj->update_area, new_clip_region);
-
- /* Invalidate newly exposed portion of window
- */
- gdk_region_subtract (new_clip_region, old_clip_region);
- if (!gdk_region_empty (new_clip_region))
- {
- _gdk_x11_window_tmp_unset_bg (window, FALSE);;
- gdk_window_invalidate_region (window, new_clip_region, FALSE);
- }
-
- if (obj->parent)
- _gdk_x11_window_tmp_unset_bg ((GdkWindow *)obj->parent, FALSE);
-
- gdk_region_destroy (new_clip_region);
- gdk_region_destroy (old_clip_region);
}
#define __GDK_GEOMETRY_X11_C__
_gdk_init_input_core (display);
display_x11->input_devices = g_list_append (NULL, display->core_pointer);
- display_x11->input_ignore_core = FALSE;
+ display->ignore_core_events = FALSE;
}
void
return FALSE;
}
-gboolean
-_gdk_input_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
-{
- return TRUE;
-}
-
-gboolean
-_gdk_input_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+void
+_gdk_input_select_events (GdkWindow *impl_window,
+ GdkDevicePrivate *gdkdev)
{
- return TRUE;
}
gboolean
}
void
-_gdk_input_enter_event (XCrossingEvent *xevent,
- GdkWindow *window)
+_gdk_input_crossing_event (GdkWindow *window,
+ gboolean enter)
{
}
gint
_gdk_input_grab_pointer (GdkWindow * window,
+ GdkWindow *native_window,
gint owner_events,
GdkEventMask event_mask,
GdkWindow * confine_to,
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
XDeviceInfo *device,
gint include_core);
static void gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
- GdkInputWindow *input_window,
+ GdkWindow *window,
gint *axis_data,
gdouble *axis_out,
gdouble *x_out,
}
void
-_gdk_input_get_root_relative_geometry(Display *display, Window w, int *x_ret, int *y_ret,
- int *width_ret, int *height_ret)
+_gdk_input_get_root_relative_geometry (GdkWindow *window,
+ int *x_ret, int *y_ret)
{
- Window root, parent, child;
- Window *children;
- guint nchildren;
+ Window child;
gint x,y;
- guint width, height;
- guint border_widthc, depthc;
-
- XQueryTree (display, w, &root, &parent, &children, &nchildren);
- if (children)
- XFree(children);
-
- XGetGeometry (display, w, &root, &x, &y, &width, &height, &border_widthc, &depthc);
-
- XTranslateCoordinates (display, w, root, 0, 0, &x, &y, &child);
-
+
+ XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XWINDOW (window),
+ GDK_WINDOW_XROOTWIN (window),
+ 0, 0, &x, &y, &child);
+
if (x_ret)
*x_ret = x;
if (y_ret)
*y_ret = y;
- if (width_ret)
- *width_ret = width;
- if (height_ret)
- *height_ret = height;
}
static GdkDevicePrivate *
gdk_input_device_new (GdkDisplay *display,
- XDeviceInfo *device,
+ XDeviceInfo *device,
gint include_core)
{
GdkDevicePrivate *gdkdev;
for comparison purposes */
tmp_name = g_ascii_strdown (gdkdev->info.name, -1);
-
+
if (!strcmp (tmp_name, "pointer"))
gdkdev->info.source = GDK_SOURCE_MOUSE;
else if (!strcmp (tmp_name, "wacom") ||
gdkdev->button_state = 0;
class = device->inputclassinfo;
- for (i=0;i<device->num_classes;i++)
+ for (i=0;i<device->num_classes;i++)
{
switch (class->class) {
case ButtonClass:
{
XKeyInfo *xki = (XKeyInfo *)class;
/* Hack to catch XFree86 3.3.1 bug. Other devices better
- * not have exactly 25 keys...
+ * not have exactly 25 keys...
*/
if ((xki->min_keycode == 8) && (xki->max_keycode == 32))
{
gdkdev->info.axes = g_new0 (GdkDeviceAxis, xvi->num_axes);
for (j=0;j<xvi->num_axes;j++)
{
- gdkdev->axes[j].resolution =
+ gdkdev->axes[j].resolution =
gdkdev->axes[j].xresolution = xvi->axes[j].resolution;
gdkdev->axes[j].min_value =
gdkdev->axes[j].xmin_value = xvi->axes[j].min_value;
gdk_device_set_axis_use (&gdkdev->info, j++, GDK_AXIS_YTILT);
if (j<xvi->num_axes)
gdk_device_set_axis_use (&gdkdev->info, j++, GDK_AXIS_WHEEL);
-
+
break;
}
}
error:
g_object_unref (gdkdev);
-
+
return NULL;
}
void
-_gdk_input_common_find_events(GdkWindow *window,
- GdkDevicePrivate *gdkdev,
- gint mask,
- XEventClass *classes,
- int *num_classes)
+_gdk_input_common_find_events (GdkDevicePrivate *gdkdev,
+ gint mask,
+ XEventClass *classes,
+ int *num_classes)
{
gint i;
XEventClass class;
-
+
i = 0;
if (mask & GDK_BUTTON_PRESS_MASK)
{
}
void
-_gdk_input_common_select_events(GdkWindow *window,
- GdkDevicePrivate *gdkdev)
+_gdk_input_select_events (GdkWindow *impl_window,
+ GdkDevicePrivate *gdkdev)
{
XEventClass classes[GDK_MAX_DEVICE_CLASSES];
gint num_classes;
+ guint event_mask;
+ GdkWindowObject *w;
+ GdkInputWindow *iw;
+ GList *l;
- if (gdkdev->info.mode == GDK_MODE_DISABLED)
- _gdk_input_common_find_events(window, gdkdev, 0, classes, &num_classes);
- else
- _gdk_input_common_find_events(window, gdkdev,
- ((GdkWindowObject *)window)->extension_events,
- classes, &num_classes);
-
- XSelectExtensionEvent (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XWINDOW (window),
+ event_mask = 0;
+ iw = ((GdkWindowObject *)impl_window)->input_window;
+
+ if (gdkdev->info.mode != GDK_MODE_DISABLED &&
+ iw != NULL)
+ {
+ for (l = iw->windows; l != NULL; l = l->next)
+ {
+ w = l->data;
+ if (gdkdev->info.has_cursor || (w->extension_events & GDK_ALL_DEVICES_MASK))
+ event_mask |= w->extension_events;
+ }
+ }
+ event_mask &= ~GDK_ALL_DEVICES_MASK;
+
+ if (event_mask)
+ event_mask |= GDK_PROXIMITY_OUT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK;
+
+ _gdk_input_common_find_events (gdkdev, event_mask,
+ classes, &num_classes);
+ XSelectExtensionEvent (GDK_WINDOW_XDISPLAY (impl_window),
+ GDK_WINDOW_XWINDOW (impl_window),
classes, num_classes);
}
-gint
+gint
_gdk_input_common_init (GdkDisplay *display,
gint include_core)
{
event_base, 15 /* Number of events */);
devices = XListInputDevices(display_x11->xdisplay, &num_devices);
-
+
for(loop=0; loop<num_devices; loop++)
{
GdkDevicePrivate *gdkdev = gdk_input_device_new(display,
static void
gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
- GdkInputWindow *input_window,
+ GdkWindow *window,
gint *axis_data,
gdouble *axis_out,
gdouble *x_out,
gdouble *y_out)
{
- GdkWindowImplX11 *impl;
+ GdkWindowObject *priv, *impl_window;
+
int i;
int x_axis = 0;
int y_axis = 0;
double device_width, device_height;
double x_offset, y_offset, x_scale, y_scale;
- impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *) input_window->window)->impl);
+ priv = (GdkWindowObject *) window;
+ impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
for (i=0; i<gdkdev->info.num_axes; i++)
{
break;
}
}
-
- device_width = gdkdev->axes[x_axis].max_value -
- gdkdev->axes[x_axis].min_value;
- device_height = gdkdev->axes[y_axis].max_value -
- gdkdev->axes[y_axis].min_value;
- if (gdkdev->info.mode == GDK_MODE_SCREEN)
+ device_width = gdkdev->axes[x_axis].max_value - gdkdev->axes[x_axis].min_value;
+ device_height = gdkdev->axes[y_axis].max_value - gdkdev->axes[y_axis].min_value;
+
+ if (gdkdev->info.mode == GDK_MODE_SCREEN)
{
- x_scale = gdk_screen_get_width (gdk_drawable_get_screen (input_window->window)) / device_width;
- y_scale = gdk_screen_get_height (gdk_drawable_get_screen (input_window->window)) / device_height;
+ x_scale = gdk_screen_get_width (gdk_drawable_get_screen (window)) / device_width;
+ y_scale = gdk_screen_get_height (gdk_drawable_get_screen (window)) / device_height;
- x_offset = - input_window->root_x;
- y_offset = - input_window->root_y;
+ x_offset = - impl_window->input_window->root_x;
+ y_offset = - impl_window->input_window->root_y;
}
else /* GDK_MODE_WINDOW */
{
double x_resolution = gdkdev->axes[x_axis].resolution;
double y_resolution = gdkdev->axes[y_axis].resolution;
double device_aspect;
- /*
+ /*
* Some drivers incorrectly report the resolution of the device
* as zero (in partiular linuxwacom < 0.5.3 with usb tablets).
* This causes the device_aspect to become NaN and totally
y_resolution = 1;
}
device_aspect = (device_height*y_resolution) /
- (device_width*x_resolution);
- if (device_aspect * impl->width >= impl->height)
+ (device_width*x_resolution);
+ if (device_aspect * priv->width >= priv->height)
{
/* device taller than window */
- x_scale = impl->width / device_width;
- y_scale = (x_scale * x_resolution)
- / y_resolution;
+ x_scale = priv->width / device_width;
+ y_scale = (x_scale * x_resolution) / y_resolution;
x_offset = 0;
- y_offset = -(device_height * y_scale -
- impl->height)/2;
+ y_offset = -(device_height * y_scale - priv->height)/2;
}
else
{
/* window taller than device */
- y_scale = impl->height / device_height;
- x_scale = (y_scale * y_resolution)
- / x_resolution;
+ y_scale = priv->height / device_height;
+ x_scale = (y_scale * y_resolution) / x_resolution;
y_offset = 0;
- x_offset = - (device_width * x_scale - impl->width)/2;
+ x_offset = - (device_width * x_scale - priv->width)/2;
}
}
switch (gdkdev->info.axes[i].use)
{
case GDK_AXIS_X:
- axis_out[i] = x_offset + x_scale * (axis_data[x_axis] -
+ axis_out[i] = x_offset + x_scale * (axis_data[x_axis] -
gdkdev->axes[x_axis].min_value);
if (x_out)
*x_out = axis_out[i];
break;
case GDK_AXIS_Y:
- axis_out[i] = y_offset + y_scale * (axis_data[y_axis] -
+ axis_out[i] = y_offset + y_scale * (axis_data[y_axis] -
gdkdev->axes[y_axis].min_value);
if (y_out)
*y_out = axis_out[i];
gboolean
_gdk_input_common_other_event (GdkEvent *event,
XEvent *xevent,
- GdkInputWindow *input_window,
+ GdkWindow *window,
GdkDevicePrivate *gdkdev)
{
+ GdkWindowObject *priv, *impl_window;
+ GdkInputWindow *input_window;
+
+ priv = (GdkWindowObject *) window;
+ impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
+ input_window = impl_window->input_window;
+
if ((xevent->type == gdkdev->buttonpress_type) ||
- (xevent->type == gdkdev->buttonrelease_type))
+ (xevent->type == gdkdev->buttonrelease_type))
{
XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *)(xevent);
gdkdev->button_state &= ~(1 << xdbe->button);
}
event->button.device = &gdkdev->info;
- event->button.window = input_window->window;
+ event->button.window = window;
event->button.time = xdbe->time;
event->button.axes = g_new (gdouble, gdkdev->info.num_axes);
- gdk_input_translate_coordinates (gdkdev,input_window, xdbe->axis_data,
- event->button.axes,
- &event->button.x,&event->button.y);
- event->button.x_root = event->button.x + input_window->root_x;
- event->button.y_root = event->button.y + input_window->root_y;
- event->button.state = gdk_input_translate_state(xdbe->state,xdbe->device_state);
+ gdk_input_translate_coordinates (gdkdev, window, xdbe->axis_data,
+ event->button.axes,
+ &event->button.x, &event->button.y);
+ event->button.x_root = event->button.x + priv->abs_x + input_window->root_x;
+ event->button.y_root = event->button.y + priv->abs_y + input_window->root_y;
+ event->button.state = gdk_input_translate_state (xdbe->state,xdbe->device_state);
event->button.button = xdbe->button;
if (event->button.type == GDK_BUTTON_PRESS)
* a valid timestamp.
*/
if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
- gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
- gdk_event_get_time (event));
+ gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+ gdk_event_get_time (event));
return TRUE;
}
g_warning ("Invalid device key code received");
return FALSE;
}
-
+
event->key.keyval = gdkdev->info.keys[xdke->keycode - gdkdev->min_keycode].keyval;
- if (event->key.keyval == 0)
+ if (event->key.keyval == 0)
{
GDK_NOTE (EVENTS,
g_print ("\t\ttranslation - NONE\n"));
-
+
return FALSE;
}
event->key.type = (xdke->type == gdkdev->keypress_type) ?
GDK_KEY_PRESS : GDK_KEY_RELEASE;
- event->key.window = input_window->window;
+ event->key.window = window;
event->key.time = xdke->time;
event->key.state = gdk_input_translate_state(xdke->state, xdke->device_state)
* a valid timestamp.
*/
if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
- gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
- gdk_event_get_time (event));
+ gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+ gdk_event_get_time (event));
return TRUE;
}
- if (xevent->type == gdkdev->motionnotify_type)
+ if (xevent->type == gdkdev->motionnotify_type)
{
XDeviceMotionEvent *xdme = (XDeviceMotionEvent *)(xevent);
event->motion.device = &gdkdev->info;
-
+
event->motion.axes = g_new (gdouble, gdkdev->info.num_axes);
- gdk_input_translate_coordinates(gdkdev,input_window,xdme->axis_data,
+ gdk_input_translate_coordinates(gdkdev,window,xdme->axis_data,
event->motion.axes,
&event->motion.x,&event->motion.y);
- event->motion.x_root = event->motion.x + input_window->root_x;
- event->motion.y_root = event->motion.y + input_window->root_y;
+ event->motion.x_root = event->motion.x + priv->abs_x + input_window->root_x;
+ event->motion.y_root = event->motion.y + priv->abs_y + input_window->root_y;
event->motion.type = GDK_MOTION_NOTIFY;
- event->motion.window = input_window->window;
+ event->motion.window = window;
event->motion.time = xdme->time;
event->motion.state = gdk_input_translate_state(xdme->state,
xdme->device_state);
event->motion.x, event->motion.y,
event->motion.state,
(xdme->is_hint) ? "true" : "false"));
-
-
+
+
/* Update the timestamp of the latest user interaction, if the event has
* a valid timestamp.
*/
if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
- gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
- gdk_event_get_time (event));
+ gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+ gdk_event_get_time (event));
return TRUE;
}
event->proximity.device = &gdkdev->info;
event->proximity.type = (xevent->type == gdkdev->proximityin_type)?
- GDK_PROXIMITY_IN:GDK_PROXIMITY_OUT;
- event->proximity.window = input_window->window;
+ GDK_PROXIMITY_IN:GDK_PROXIMITY_OUT;
+ event->proximity.window = window;
event->proximity.time = xpne->time;
-
+
/* Update the timestamp of the latest user interaction, if the event has
* a valid timestamp.
*/
if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
- gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
- gdk_event_get_time (event));
+ gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+ gdk_event_get_time (event));
return TRUE;
}
{
GdkTimeCoord **coords;
XDeviceTimeCoord *device_coords;
- GdkInputWindow *input_window;
+ GdkWindow *impl_window;
GdkDevicePrivate *gdkdev;
gint mode_return;
gint axis_count_return;
gint i;
gdkdev = (GdkDevicePrivate *)device;
- input_window = _gdk_input_window_find (window);
- g_return_val_if_fail (input_window != NULL, FALSE);
+ impl_window = _gdk_window_get_impl_window (window);
- device_coords = XGetDeviceMotionEvents (GDK_WINDOW_XDISPLAY (window),
+ device_coords = XGetDeviceMotionEvents (GDK_WINDOW_XDISPLAY (impl_window),
gdkdev->xdevice,
start, stop,
n_events, &mode_return,
coords = _gdk_device_allocate_history (device, *n_events);
for (i = 0; i < *n_events; i++)
- {
- coords[i]->time = device_coords[i].time;
+ {
+ coords[i]->time = device_coords[i].time;
- gdk_input_translate_coordinates (gdkdev, input_window,
- device_coords[i].data,
- coords[i]->axes, NULL, NULL);
- }
+ gdk_input_translate_coordinates (gdkdev, window,
+ device_coords[i].data,
+ coords[i]->axes, NULL, NULL);
+ }
XFreeDeviceMotionEvents (device_coords);
return FALSE;
}
-void
+void
gdk_device_get_state (GdkDevice *device,
GdkWindow *window,
gdouble *axes,
if (GDK_IS_CORE (device))
{
gint x_int, y_int;
-
+
gdk_window_get_pointer (window, &x_int, &y_int, mask);
if (axes)
else
{
GdkDevicePrivate *gdkdev;
- GdkInputWindow *input_window;
XDeviceState *state;
XInputClass *input_class;
-
+
if (mask)
gdk_window_get_pointer (window, NULL, NULL, mask);
-
+
gdkdev = (GdkDevicePrivate *)device;
- input_window = _gdk_input_window_find (window);
- g_return_if_fail (input_window != NULL);
state = XQueryDeviceState (GDK_WINDOW_XDISPLAY (window),
gdkdev->xdevice);
{
case ValuatorClass:
if (axes)
- gdk_input_translate_coordinates (gdkdev, input_window,
+ gdk_input_translate_coordinates (gdkdev, window,
((XValuatorState *)input_class)->valuators,
axes, NULL, NULL);
break;
-
+
case ButtonClass:
if (mask)
{
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
/* forward declarations */
static void gdk_input_check_proximity (GdkDisplay *display);
-void
+void
_gdk_input_init(GdkDisplay *display)
{
_gdk_init_input_core (display);
- GDK_DISPLAY_X11 (display)->input_ignore_core = FALSE;
+ display->ignore_core_events = FALSE;
_gdk_input_common_init (display, FALSE);
}
{
GList *tmp_list;
GdkDevicePrivate *gdkdev;
- GdkInputMode old_mode;
GdkInputWindow *input_window;
GdkDisplayX11 *display_impl;
if (device->mode == mode)
return TRUE;
- old_mode = device->mode;
device->mode = mode;
- display_impl = GDK_DISPLAY_X11 (gdkdev->display);
-
if (mode == GDK_MODE_WINDOW)
- {
- device->has_cursor = FALSE;
- for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
- {
- input_window = (GdkInputWindow *)tmp_list->data;
- if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
- _gdk_input_enable_window (input_window->window, gdkdev);
- else
- if (old_mode != GDK_MODE_DISABLED)
- _gdk_input_disable_window (input_window->window, gdkdev);
- }
- }
+ device->has_cursor = FALSE;
else if (mode == GDK_MODE_SCREEN)
+ device->has_cursor = TRUE;
+
+ display_impl = GDK_DISPLAY_X11 (gdkdev->display);
+ for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
{
- device->has_cursor = TRUE;
- for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
- _gdk_input_enable_window (((GdkInputWindow *)tmp_list->data)->window,
- gdkdev);
- }
- else /* mode == GDK_MODE_DISABLED */
- {
- for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
- {
- input_window = (GdkInputWindow *)tmp_list->data;
- if (old_mode != GDK_MODE_WINDOW ||
- input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
- _gdk_input_disable_window (input_window->window, gdkdev);
- }
+ input_window = (GdkInputWindow *)tmp_list->data;
+ _gdk_input_select_events (input_window->impl_window, gdkdev);
}
return TRUE;
-
}
static void
gdk_input_check_proximity (GdkDisplay *display)
{
- gint new_proximity = 0;
GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
GList *tmp_list = display_impl->input_devices;
+ gint new_proximity = 0;
- while (tmp_list && !new_proximity)
+ while (tmp_list && !new_proximity)
{
GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
- if (gdkdev->info.mode != GDK_MODE_DISABLED
+ if (gdkdev->info.mode != GDK_MODE_DISABLED
&& !GDK_IS_CORE (gdkdev)
&& gdkdev->xdevice)
{
gdkdev->xdevice);
XInputClass *xic;
int i;
-
+
xic = state->data;
for (i=0; i<state->num_classes; i++)
{
}
XFreeDeviceState (state);
- }
+ }
tmp_list = tmp_list->next;
}
- display_impl->input_ignore_core = new_proximity;
+ display->ignore_core_events = new_proximity;
}
void
_gdk_input_configure_event (XConfigureEvent *xevent,
GdkWindow *window)
{
+ GdkWindowObject *priv = (GdkWindowObject *)window;
GdkInputWindow *input_window;
gint root_x, root_y;
- input_window = _gdk_input_window_find(window);
- g_return_if_fail (input_window != NULL);
-
- _gdk_input_get_root_relative_geometry(GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XWINDOW (window),
- &root_x, &root_y, NULL, NULL);
-
- input_window->root_x = root_x;
- input_window->root_y = root_y;
+ input_window = priv->input_window;
+ if (input_window != NULL)
+ {
+ _gdk_input_get_root_relative_geometry (window, &root_x, &root_y);
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+ }
}
-void
-_gdk_input_enter_event (XCrossingEvent *xevent,
- GdkWindow *window)
+void
+_gdk_input_crossing_event (GdkWindow *window,
+ gboolean enter)
{
+ GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+ GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
+ GdkWindowObject *priv = (GdkWindowObject *)window;
GdkInputWindow *input_window;
gint root_x, root_y;
- input_window = _gdk_input_window_find (window);
- g_return_if_fail (input_window != NULL);
+ if (enter)
+ {
+ gdk_input_check_proximity(display);
+
+ input_window = priv->input_window;
+ if (input_window != NULL)
+ {
+ _gdk_input_get_root_relative_geometry (window, &root_x, &root_y);
+ input_window->root_x = root_x;
+ input_window->root_y = root_y;
+ }
+ }
+ else
+ display->ignore_core_events = FALSE;
+}
+
+static GdkEventType
+get_input_event_type (GdkDevicePrivate *gdkdev,
+ XEvent *xevent,
+ int *core_x, int *core_y)
+{
+ if (xevent->type == gdkdev->buttonpress_type)
+ {
+ XDeviceButtonEvent *xie = (XDeviceButtonEvent *)(xevent);
+ *core_x = xie->x;
+ *core_y = xie->y;
+ return GDK_BUTTON_PRESS;
+ }
+
+ if (xevent->type == gdkdev->buttonrelease_type)
+ {
+ XDeviceButtonEvent *xie = (XDeviceButtonEvent *)(xevent);
+ *core_x = xie->x;
+ *core_y = xie->y;
+ return GDK_BUTTON_RELEASE;
+ }
+
+ if (xevent->type == gdkdev->keypress_type)
+ {
+ XDeviceKeyEvent *xie = (XDeviceKeyEvent *)(xevent);
+ *core_x = xie->x;
+ *core_y = xie->y;
+ return GDK_KEY_PRESS;
+ }
+
+ if (xevent->type == gdkdev->keyrelease_type)
+ {
+ XDeviceKeyEvent *xie = (XDeviceKeyEvent *)(xevent);
+ *core_x = xie->x;
+ *core_y = xie->y;
+ return GDK_KEY_RELEASE;
+ }
+
+ if (xevent->type == gdkdev->motionnotify_type)
+ {
+ XDeviceMotionEvent *xie = (XDeviceMotionEvent *)(xevent);
+ *core_x = xie->x;
+ *core_y = xie->y;
+ return GDK_MOTION_NOTIFY;
+ }
- gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window));
+ if (xevent->type == gdkdev->proximityin_type)
+ {
+ XProximityNotifyEvent *xie = (XProximityNotifyEvent *)(xevent);
+ *core_x = xie->x;
+ *core_y = xie->y;
+ return GDK_PROXIMITY_IN;
+ }
- _gdk_input_get_root_relative_geometry(GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XWINDOW(window),
- &root_x, &root_y, NULL, NULL);
+ if (xevent->type == gdkdev->proximityout_type)
+ {
+ XProximityNotifyEvent *xie = (XProximityNotifyEvent *)(xevent);
+ *core_x = xie->x;
+ *core_y = xie->y;
+ return GDK_PROXIMITY_OUT;
+ }
- input_window->root_x = root_x;
- input_window->root_y = root_y;
+ *core_x = 0;
+ *core_y = 0;
+ return GDK_NOTHING;
}
-gboolean
-_gdk_input_other_event (GdkEvent *event,
- XEvent *xevent,
- GdkWindow *window)
+
+gboolean
+_gdk_input_other_event (GdkEvent *event,
+ XEvent *xevent,
+ GdkWindow *event_window)
{
- GdkInputWindow *input_window;
-
+ GdkWindow *window;
+ GdkWindowObject *priv;
+ GdkInputWindow *iw;
GdkDevicePrivate *gdkdev;
gint return_val;
- GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
-
- input_window = _gdk_input_window_find(window);
- g_return_val_if_fail (input_window != NULL, FALSE);
+ GdkEventType event_type;
+ int x, y;
+ GdkDisplay *display = GDK_WINDOW_DISPLAY (event_window);
+ GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
/* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
but it's potentially faster than scanning through the types of
every device. If we were deceived, then it won't match any of
the types for the device anyways */
- gdkdev = _gdk_input_find_device (GDK_WINDOW_DISPLAY (window),
+ gdkdev = _gdk_input_find_device (display,
((XDeviceButtonEvent *)xevent)->deviceid);
if (!gdkdev)
return FALSE; /* we don't handle it - not an XInput event */
- /* FIXME: It would be nice if we could just get rid of the events
- entirely, instead of having to ignore them */
+ event_type = get_input_event_type (gdkdev, xevent, &x, &y);
+ if (event_type == GDK_NOTHING)
+ return FALSE;
+
+ window = _gdk_window_get_input_window_for_event (event_window,
+ event_type,
+ x, y,
+ xevent->xany.serial);
+ /* If we're not getting any event window its likely because we're outside the
+ window and there is no grab. We should still report according to the
+ implicit grab though. */
+ iw = ((GdkWindowObject *)event_window)->input_window;
+ if (window == NULL)
+ window = iw->button_down_window;
+
+ priv = (GdkWindowObject *)window;
+ if (window == NULL)
+ return FALSE;
+
if (gdkdev->info.mode == GDK_MODE_DISABLED ||
- (gdkdev->info.mode == GDK_MODE_WINDOW
- && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR))
+ !(gdkdev->info.has_cursor || (priv->extension_events & GDK_ALL_DEVICES_MASK)))
return FALSE;
-
- if (!display_impl->input_ignore_core)
- gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window));
- return_val = _gdk_input_common_other_event (event, xevent,
- input_window, gdkdev);
+ if (!display->ignore_core_events && priv->extension_events != 0)
+ gdk_input_check_proximity (GDK_WINDOW_DISPLAY (window));
- if (return_val && event->type == GDK_PROXIMITY_OUT &&
- display_impl->input_ignore_core)
- gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window));
+ return_val = _gdk_input_common_other_event (event, xevent, window, gdkdev);
- return return_val;
-}
+ if (return_val && event->type == GDK_BUTTON_PRESS)
+ iw->button_down_window = window;
+ if (return_val && event->type == GDK_BUTTON_RELEASE)
+ iw->button_down_window = NULL;
-gboolean
-_gdk_input_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
-{
- /* FIXME: watchout, gdkdev might be core pointer, never opened */
- _gdk_input_common_select_events (window, gdkdev);
- return TRUE;
-}
+ if (return_val && event->type == GDK_PROXIMITY_OUT &&
+ display->ignore_core_events)
+ gdk_input_check_proximity (GDK_WINDOW_DISPLAY (window));
-gboolean
-_gdk_input_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
-{
- _gdk_input_common_select_events (window, gdkdev);
- return TRUE;
+ return return_val;
}
-gint
-_gdk_input_grab_pointer (GdkWindow * window,
+gint
+_gdk_input_grab_pointer (GdkWindow *window,
+ GdkWindow *native_window, /* This is the toplevel */
gint owner_events,
GdkEventMask event_mask,
GdkWindow * confine_to,
guint32 time)
{
- GdkInputWindow *input_window, *new_window;
+ GdkInputWindow *input_window;
+ GdkWindowObject *priv, *impl_window;
gboolean need_ungrab;
GdkDevicePrivate *gdkdev;
GList *tmp_list;
GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
tmp_list = display_impl->input_windows;
- new_window = NULL;
need_ungrab = FALSE;
while (tmp_list)
{
input_window = (GdkInputWindow *)tmp_list->data;
- if (input_window->window == window)
- new_window = input_window;
- else if (input_window->grabbed)
+ if (input_window->grabbed)
{
input_window->grabbed = FALSE;
need_ungrab = TRUE;
+ break;
}
-
tmp_list = tmp_list->next;
}
- if (new_window)
+ priv = (GdkWindowObject *)window;
+ impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
+ input_window = impl_window->input_window;
+ if (priv->extension_events)
{
- new_window->grabbed = TRUE;
-
+ g_assert (input_window != NULL);
+ input_window->grabbed = TRUE;
+
tmp_list = display_impl->input_devices;
while (tmp_list)
{
gdkdev = (GdkDevicePrivate *)tmp_list->data;
if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
{
- _gdk_input_common_find_events (window, gdkdev,
- event_mask,
+ _gdk_input_common_find_events (gdkdev, event_mask,
event_classes, &num_classes);
#ifdef G_ENABLE_DEBUG
if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
else
#endif
result = XGrabDevice (display_impl->xdisplay, gdkdev->xdevice,
- GDK_WINDOW_XWINDOW (window),
+ GDK_WINDOW_XWINDOW (native_window),
owner_events, num_classes, event_classes,
GrabModeAsync, GrabModeAsync, time);
-
+
/* FIXME: if failure occurs on something other than the first
device, things will be badly inconsistent */
if (result != Success)
}
}
else
- {
+ {
tmp_list = display_impl->input_devices;
while (tmp_list)
{
XUngrabDevice (display_impl->xdisplay, gdkdev->xdevice, time);
gdkdev->button_state = 0;
}
-
+
tmp_list = tmp_list->next;
}
}
return Success;
-
}
-void
-_gdk_input_ungrab_pointer (GdkDisplay *display,
+void
+_gdk_input_ungrab_pointer (GdkDisplay *display,
guint32 time)
{
GdkInputWindow *input_window = NULL; /* Quiet GCC */
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "config.h"
_gdk_init_input_core (GdkDisplay *display)
{
GdkDevicePrivate *private;
-
+
display->core_pointer = g_object_new (GDK_TYPE_DEVICE, NULL);
private = (GdkDevicePrivate *)display->core_pointer;
-
+
display->core_pointer->name = "Core Pointer";
display->core_pointer->source = GDK_SOURCE_MOUSE;
display->core_pointer->mode = GDK_MODE_SCREEN;
0, /* n_preallocs */
(GInstanceInitFunc) NULL,
};
-
+
object_type = g_type_register_static (G_TYPE_OBJECT,
- g_intern_static_string ("GdkDevice"),
- &object_info, 0);
+ g_intern_static_string ("GdkDevice"),
+ &object_info, 0);
}
-
+
return object_type;
}
{
#ifndef XINPUT_NONE
if (gdkdev->xdevice)
- {
- XCloseDevice (GDK_DISPLAY_XDISPLAY (gdkdev->display), gdkdev->xdevice);
- gdkdev->xdevice = NULL;
- }
+ {
+ XCloseDevice (GDK_DISPLAY_XDISPLAY (gdkdev->display), gdkdev->xdevice);
+ gdkdev->xdevice = NULL;
+ }
g_free (gdkdev->axes);
gdkdev->axes = NULL;
#endif /* !XINPUT_NONE */
*
* Returns the list of available input devices for the default display.
* The list is statically allocated and should not be freed.
- *
+ *
* Return value: a list of #GdkDevice
**/
GList *
*
* Returns the list of available input devices attached to @display.
* The list is statically allocated and should not be freed.
- *
+ *
* Return value: a list of #GdkDevice
*
* Since: 2.2
**/
-GList *
+GList *
gdk_display_list_devices (GdkDisplay *display)
{
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-
+
return GDK_DISPLAY_X11 (display)->input_devices;
}
}
}
+static gboolean
+impl_coord_in_window (GdkWindow *window,
+ int impl_x,
+ int impl_y)
+{
+ GdkWindowObject *priv = (GdkWindowObject *)window;
+
+ if (impl_x < priv->abs_x ||
+ impl_x > priv->abs_x + priv->width)
+ return FALSE;
+ if (impl_y < priv->abs_y ||
+ impl_y > priv->abs_y + priv->height)
+ return FALSE;
+ return TRUE;
+}
+
/**
* gdk_device_get_history:
* @device: a #GdkDevice
* @stop: ending timestamp for the range of events to return
* @events: location to store a newly-allocated array of #GdkTimeCoord, or %NULL
* @n_events: location to store the length of @events, or %NULL
- *
+ *
* Obtains the motion history for a device; given a starting and
* ending timestamp, return all events in the motion history for
* the device in the given range of time. Some windowing systems
* do not support motion history, in which case, %FALSE will
* be returned. (This is not distinguishable from the case where
* motion history is supported and no events were found.)
- *
+ *
* Return value: %TRUE if the windowing system supports motion history and
* at least one event was found.
**/
gint *n_events)
{
GdkTimeCoord **coords = NULL;
+ GdkWindow *impl_window;
gboolean result = FALSE;
int tmp_n_events = 0;
- int i;
+ int i, j;
- g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+ g_return_val_if_fail (GDK_WINDOW_IS_X11 (window), FALSE);
+
+ impl_window = _gdk_window_get_impl_window (window);
if (GDK_WINDOW_DESTROYED (window))
/* Nothing */ ;
else if (GDK_IS_CORE (device))
{
XTimeCoord *xcoords;
-
+
xcoords = XGetMotionEvents (GDK_DRAWABLE_XDISPLAY (window),
- GDK_DRAWABLE_XID (window),
+ GDK_DRAWABLE_XID (impl_window),
start, stop, &tmp_n_events);
if (xcoords)
{
+ GdkWindowObject *priv = (GdkWindowObject *)window;
coords = _gdk_device_allocate_history (device, tmp_n_events);
+ j = 0;
for (i=0; i<tmp_n_events; i++)
{
- coords[i]->time = xcoords[i].time;
- coords[i]->axes[0] = xcoords[i].x;
- coords[i]->axes[1] = xcoords[i].y;
+ if (impl_coord_in_window (window, xcoords[i].x, xcoords[i].y))
+ {
+ coords[j]->time = xcoords[i].time;
+ coords[j]->axes[0] = xcoords[i].x - priv->abs_x;
+ coords[j]->axes[1] = xcoords[i].y - priv->abs_y;
+ j++;
+ }
}
XFree (xcoords);
return result;
}
-GdkTimeCoord **
+GdkTimeCoord **
_gdk_device_allocate_history (GdkDevice *device,
gint n_events)
{
return result;
}
-void
+void
gdk_device_free_history (GdkTimeCoord **events,
gint n_events)
{
gint i;
-
+
for (i=0; i<n_events; i++)
g_free (events[i]);
g_free (events);
}
-GdkInputWindow *
-_gdk_input_window_find(GdkWindow *window)
+static void
+unset_extension_events (GdkWindow *window)
{
- GList *tmp_list;
- GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
+ GdkWindowObject *window_private;
+ GdkWindowObject *impl_window;
+ GdkDisplayX11 *display_x11;
+ GdkInputWindow *iw;
- for (tmp_list=display_x11->input_windows; tmp_list; tmp_list=tmp_list->next)
- if (((GdkInputWindow *)(tmp_list->data))->window == window)
- return (GdkInputWindow *)(tmp_list->data);
+ window_private = (GdkWindowObject*) window;
+ impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
+ iw = impl_window->input_window;
- return NULL; /* Not found */
-}
+ display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
+
+ if (window_private->extension_events != 0)
+ {
+ g_assert (iw != NULL);
+ g_assert (g_list_find (iw->windows, window) != NULL);
-/* FIXME: this routine currently needs to be called between creation
- and the corresponding configure event (because it doesn't get the
- root_relative_geometry). This should work with
- gtk_window_set_extension_events, but will likely fail in other
- cases */
+ iw->windows = g_list_remove (iw->windows, window);
+ if (iw->windows == NULL)
+ {
+ impl_window->input_window = NULL;
+ display_x11->input_windows = g_list_remove (display_x11->input_windows, iw);
+ g_free (iw);
+ }
+ }
+
+ window_private->extension_events = 0;
+}
void
gdk_input_set_extension_events (GdkWindow *window, gint mask,
{
GdkWindowObject *window_private;
GList *tmp_list;
+ GdkWindowObject *impl_window;
GdkInputWindow *iw;
GdkDisplayX11 *display_x11;
g_return_if_fail (window != NULL);
- g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (GDK_WINDOW_IS_X11 (window));
window_private = (GdkWindowObject*) window;
display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
if (GDK_WINDOW_DESTROYED (window))
return;
+ impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
+
+ if (mode == GDK_EXTENSION_EVENTS_ALL && mask != 0)
+ mask |= GDK_ALL_DEVICES_MASK;
+
if (mode == GDK_EXTENSION_EVENTS_NONE)
mask = 0;
- iw = _gdk_input_window_find (window);
+ iw = impl_window->input_window;
if (mask != 0)
{
if (!iw)
- {
- iw = g_new(GdkInputWindow,1);
-
- iw->window = window;
- iw->mode = mode;
+ {
+ iw = g_new0 (GdkInputWindow,1);
- iw->obscuring = NULL;
- iw->num_obscuring = 0;
- iw->grabbed = FALSE;
+ iw->impl_window = (GdkWindow *)impl_window;
- display_x11->input_windows = g_list_append(display_x11->input_windows,iw);
- }
+ iw->windows = NULL;
+ iw->grabbed = FALSE;
- window_private->extension_events = mask;
+ display_x11->input_windows = g_list_append (display_x11->input_windows, iw);
#ifndef XINPUT_NONE
- /* Add enter window events to the event mask */
- /* this is not needed for XINPUT_NONE */
- gdk_window_set_events (window,
- gdk_window_get_events (window) |
- GDK_ENTER_NOTIFY_MASK);
-
- /* we might not receive ConfigureNotify so get the root_relative_geometry
- * now, just in case */
- _gdk_input_get_root_relative_geometry (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XWINDOW (window),
- &iw->root_x, &iw->root_y, NULL, NULL);
+ /* we might not receive ConfigureNotify so get the root_relative_geometry
+ * now, just in case */
+ _gdk_input_get_root_relative_geometry (window, &iw->root_x, &iw->root_y);
#endif /* !XINPUT_NONE */
+ impl_window->input_window = iw;
+ }
+
+ if (window_private->extension_events == 0)
+ iw->windows = g_list_append (iw->windows, window);
+ window_private->extension_events = mask;
}
else
{
- if (iw)
- {
- display_x11->input_windows = g_list_remove(display_x11->input_windows,iw);
- g_free(iw);
- }
-
- window_private->extension_events = 0;
+ unset_extension_events (window);
}
for (tmp_list = display_x11->input_devices; tmp_list; tmp_list = tmp_list->next)
GdkDevicePrivate *gdkdev = tmp_list->data;
if (!GDK_IS_CORE (gdkdev))
- {
- if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
- && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
- _gdk_input_enable_window (window,gdkdev);
- else
- _gdk_input_disable_window (window,gdkdev);
- }
+ _gdk_input_select_events ((GdkWindow *)impl_window, gdkdev);
}
}
void
_gdk_input_window_destroy (GdkWindow *window)
{
- GdkInputWindow *input_window;
- GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
-
- input_window = _gdk_input_window_find (window);
- g_return_if_fail (input_window != NULL);
-
- display_x11->input_windows = g_list_remove (display_x11->input_windows, input_window);
- g_free(input_window);
-}
-
-void
-_gdk_input_exit (void)
-{
- GList *tmp_list;
- GSList *display_list;
- GdkDevicePrivate *gdkdev;
-
- for (display_list = _gdk_displays ; display_list ; display_list = display_list->next)
- {
- GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display_list->data);
-
- for (tmp_list = display_x11->input_devices; tmp_list; tmp_list = tmp_list->next)
- {
- gdkdev = (GdkDevicePrivate *)(tmp_list->data);
- if (!GDK_IS_CORE (gdkdev))
- {
- gdk_device_set_mode (&gdkdev->info, GDK_MODE_DISABLED);
- g_object_unref(gdkdev);
- }
- }
-
- g_list_free(display_x11->input_devices);
-
- for (tmp_list = display_x11->input_windows; tmp_list; tmp_list = tmp_list->next)
- g_free(tmp_list->data);
-
- g_list_free(display_x11->input_windows);
- }
+ unset_extension_events (window);
}
/**
* @axes: pointer to an array of axes
* @use: the use to look for
* @value: location to store the found value.
- *
+ *
* Interprets an array of double as axis values for a given device,
* and locates the value in the array for a given axis use.
- *
+ *
* Return value: %TRUE if the given axis use was found, otherwise %FALSE
**/
gboolean
gdouble *value)
{
gint i;
-
+
g_return_val_if_fail (device != NULL, FALSE);
if (axes == NULL)
return FALSE;
-
+
for (i=0; i<device->num_axes; i++)
if (device->axes[i].use == use)
{
*value = axes[i];
return TRUE;
}
-
+
return FALSE;
}
typedef struct _GdkAxisInfo GdkAxisInfo;
typedef struct _GdkDevicePrivate GdkDevicePrivate;
-typedef struct _GdkInputWindow GdkInputWindow;
/* information about a device axis */
struct _GdkAxisInfo
GObjectClass parent_class;
};
+/* Addition used for extension_events mask */
+#define GDK_ALL_DEVICES_MASK (1<<30)
+
struct _GdkInputWindow
{
- /* gdk window */
- GdkWindow *window;
+ GList *windows; /* GdkWindow:s with extension_events set */
- /* Extension mode (GDK_EXTENSION_EVENTS_ALL/CURSOR) */
- GdkExtensionMode mode;
+ /* gdk window */
+ GdkWindow *impl_window; /* an impl window */
+ GdkWindow *button_down_window;
/* position relative to root window */
gint root_x;
gint root_y;
- /* rectangles relative to window of windows obscuring this one */
- GdkRectangle *obscuring;
- gint num_obscuring;
-
/* Is there a pointer grab for this window ? */
gint grabbed;
};
-
-
/* Global data */
#define GDK_IS_CORE(d) (((GdkDevice *)(d)) == ((GdkDevicePrivate *)(d))->display->core_pointer)
/* The following functions are provided by each implementation
* (xfree, gxi, and none)
*/
-gint _gdk_input_enable_window (GdkWindow *window,
- GdkDevicePrivate *gdkdev);
-gint _gdk_input_disable_window (GdkWindow *window,
- GdkDevicePrivate *gdkdev);
void _gdk_input_configure_event (XConfigureEvent *xevent,
GdkWindow *window);
-void _gdk_input_enter_event (XCrossingEvent *xevent,
- GdkWindow *window);
+void _gdk_input_crossing_event (GdkWindow *window,
+ gboolean enter);
gboolean _gdk_input_other_event (GdkEvent *event,
XEvent *xevent,
GdkWindow *window);
gint _gdk_input_grab_pointer (GdkWindow *window,
+ GdkWindow *native_window,
gint owner_events,
GdkEventMask event_mask,
GdkWindow *confine_to,
gint include_core);
GdkDevicePrivate * _gdk_input_find_device (GdkDisplay *display,
guint32 id);
-void _gdk_input_get_root_relative_geometry(Display *display,
- Window w,
+void _gdk_input_get_root_relative_geometry(GdkWindow *window,
int *x_ret,
- int *y_ret,
- int *width_ret,
- int *height_ret);
-void _gdk_input_common_find_events (GdkWindow *window,
- GdkDevicePrivate *gdkdev,
+ int *y_ret);
+void _gdk_input_common_find_events (GdkDevicePrivate *gdkdev,
gint mask,
XEventClass *classes,
int *num_classes);
-void _gdk_input_common_select_events (GdkWindow *window,
+void _gdk_input_select_events (GdkWindow *impl_window,
GdkDevicePrivate *gdkdev);
gint _gdk_input_common_other_event (GdkEvent *event,
XEvent *xevent,
- GdkInputWindow *input_window,
+ GdkWindow *window,
GdkDevicePrivate *gdkdev);
#endif /* !XINPUT_NONE */
#include "gdk.h"
#include "gdkx.h"
+#include "gdkasync.h"
#include "gdkdisplay-x11.h"
#include "gdkinternals.h"
#include "gdkintl.h"
}
static void
-generate_grab_broken_event (GdkWindow *window,
- gboolean keyboard,
- gboolean implicit,
- GdkWindow *grab_window)
+has_pointer_grab_callback (GdkDisplay *display,
+ gpointer data,
+ gulong serial)
{
- if (!GDK_WINDOW_DESTROYED (window))
- {
- GdkEvent event;
-
- event.type = GDK_GRAB_BROKEN;
- event.grab_broken.window = window;
- event.grab_broken.send_event = 0;
- event.grab_broken.keyboard = keyboard;
- event.grab_broken.implicit = implicit;
- event.grab_broken.grab_window = grab_window;
-
- gdk_event_put (&event);
- }
+ _gdk_display_pointer_grab_update (display, serial);
}
-/*
- *--------------------------------------------------------------
- * gdk_pointer_grab
- *
- * Grabs the pointer to a specific window
- *
- * Arguments:
- * "window" is the window which will receive the grab
- * "owner_events" specifies whether events will be reported as is,
- * or relative to "window"
- * "event_mask" masks only interesting events
- * "confine_to" limits the cursor movement to the specified window
- * "cursor" changes the cursor for the duration of the grab
- * "time" specifies the time
- *
- * Results:
- *
- * Side effects:
- * requires a corresponding call to gdk_pointer_ungrab
- *
- *--------------------------------------------------------------
- */
-
GdkGrabStatus
-gdk_pointer_grab (GdkWindow * window,
- gboolean owner_events,
- GdkEventMask event_mask,
- GdkWindow * confine_to,
- GdkCursor * cursor,
- guint32 time)
+_gdk_windowing_pointer_grab (GdkWindow *window,
+ GdkWindow *native,
+ gboolean owner_events,
+ GdkEventMask event_mask,
+ GdkWindow *confine_to,
+ GdkCursor *cursor,
+ guint32 time)
{
gint return_val;
GdkCursorPrivate *cursor_private;
Window xwindow;
Window xconfine_to;
Cursor xcursor;
- unsigned long serial;
int i;
-
- g_return_val_if_fail (window != NULL, 0);
- g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
- g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
-
- display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
+
+ if (confine_to)
+ confine_to = _gdk_window_get_impl_window (confine_to);
+
+ display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (native));
cursor_private = (GdkCursorPrivate*) cursor;
-
- xwindow = GDK_WINDOW_XID (window);
- serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
-
+
+ xwindow = GDK_WINDOW_XID (native);
+
if (!confine_to || GDK_WINDOW_DESTROYED (confine_to))
xconfine_to = None;
else
xconfine_to = GDK_WINDOW_XID (confine_to);
-
+
if (!cursor)
xcursor = None;
else
_gdk_x11_cursor_update_theme (cursor);
xcursor = cursor_private->xcursor;
}
-
+
xevent_mask = 0;
for (i = 0; i < _gdk_nenvent_masks; i++)
{
if (event_mask & (1 << (i + 1)))
xevent_mask |= _gdk_event_mask_table[i];
}
-
+
+ /* We don't want to set a native motion hint mask, as we're emulating motion
+ * hints. If we set a native one we just wouldn't get any events.
+ */
+ xevent_mask &= ~PointerMotionHintMask;
+
return_val = _gdk_input_grab_pointer (window,
+ native,
owner_events,
event_mask,
confine_to,
time);
- if (return_val == GrabSuccess ||
+ if (return_val == GrabSuccess ||
G_UNLIKELY (!display_x11->trusted_client && return_val == AlreadyGrabbed))
{
- if (!GDK_WINDOW_DESTROYED (window))
+ if (!GDK_WINDOW_DESTROYED (native))
{
#ifdef G_ENABLE_DEBUG
if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
return_val = GrabSuccess;
else
#endif
- return_val = XGrabPointer (GDK_WINDOW_XDISPLAY (window),
+ return_val = XGrabPointer (GDK_WINDOW_XDISPLAY (native),
xwindow,
owner_events,
xevent_mask,
else
return_val = AlreadyGrabbed;
}
-
+
if (return_val == GrabSuccess)
- {
- if (display_x11->pointer_xgrab_window != NULL &&
- display_x11->pointer_xgrab_window != (GdkWindowObject *)window)
- generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
- FALSE, display_x11->pointer_xgrab_implicit,
- window);
-
- display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
- display_x11->pointer_xgrab_serial = serial;
- display_x11->pointer_xgrab_owner_events = owner_events;
- display_x11->pointer_xgrab_time = time;
- display_x11->pointer_xgrab_implicit = FALSE;
- }
+ _gdk_x11_roundtrip_async (GDK_DISPLAY_OBJECT (display_x11),
+ has_pointer_grab_callback,
+ NULL);
return gdk_x11_convert_grab_status (return_val);
}
-/**
- * gdk_pointer_grab_info_libgtk_only:
- * @display: the #GdkDisplay for which to get the grab information
- * @grab_window: location to store current grab window
- * @owner_events: location to store boolean indicating whether
- * the @owner_events flag to gdk_pointer_grab() was %TRUE.
- *
- * Determines information about the current pointer grab.
- * This is not public API and must not be used by applications.
- *
- * Return value: %TRUE if this application currently has the
- * pointer grabbed.
- **/
-gboolean
-gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
- GdkWindow **grab_window,
- gboolean *owner_events)
-{
- GdkDisplayX11 *display_x11;
-
- g_return_val_if_fail (GDK_IS_DISPLAY (display), False);
-
- display_x11 = GDK_DISPLAY_X11 (display);
-
- if (display_x11->pointer_xgrab_window)
- {
- if (grab_window)
- *grab_window = (GdkWindow *)display_x11->pointer_xgrab_window;
- if (owner_events)
- *owner_events = display_x11->pointer_xgrab_owner_events;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
/*
*--------------------------------------------------------------
* gdk_keyboard_grab
{
gint return_val;
unsigned long serial;
+ GdkDisplay *display;
GdkDisplayX11 *display_x11;
-
+ GdkWindow *native;
+
g_return_val_if_fail (window != NULL, 0);
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
-
- display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
- serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
+ native = gdk_window_get_toplevel (window);
+
+ /* TODO: What do we do for offscreens and children? We need to proxy the grab somehow */
+ if (!GDK_IS_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (native)->impl))
+ return GDK_GRAB_SUCCESS;
+
+ display = GDK_WINDOW_DISPLAY (native);
+ display_x11 = GDK_DISPLAY_X11 (display);
+
+ serial = NextRequest (GDK_WINDOW_XDISPLAY (native));
- if (!GDK_WINDOW_DESTROYED (window))
+ if (!GDK_WINDOW_DESTROYED (native))
{
#ifdef G_ENABLE_DEBUG
if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
return_val = GrabSuccess;
else
#endif
- return_val = XGrabKeyboard (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
+ return_val = XGrabKeyboard (GDK_WINDOW_XDISPLAY (native),
+ GDK_WINDOW_XID (native),
owner_events,
GrabModeAsync, GrabModeAsync,
time);
return_val = AlreadyGrabbed;
if (return_val == GrabSuccess)
- {
- if (display_x11->keyboard_xgrab_window != NULL &&
- display_x11->keyboard_xgrab_window != (GdkWindowObject *)window)
- generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
- TRUE, FALSE, window);
-
- display_x11->keyboard_xgrab_window = (GdkWindowObject *)window;
- display_x11->keyboard_xgrab_serial = serial;
- display_x11->keyboard_xgrab_owner_events = owner_events;
- display_x11->keyboard_xgrab_time = time;
- }
+ _gdk_display_set_has_keyboard_grab (display,
+ window, native,
+ owner_events,
+ serial, time);
return gdk_x11_convert_grab_status (return_val);
}
-/**
- * gdk_keyboard_grab_info_libgtk_only:
- * @display: the display for which to get the grab information
- * @grab_window: location to store current grab window
- * @owner_events: location to store boolean indicating whether
- * the @owner_events flag to gdk_keyboard_grab() was %TRUE.
- *
- * Determines information about the current keyboard grab.
- * This is not public API and must not be used by applications.
- *
- * Return value: %TRUE if this application currently has the
- * keyboard grabbed.
- **/
-gboolean
-gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
- GdkWindow **grab_window,
- gboolean *owner_events)
-{
- GdkDisplayX11 *display_x11;
-
- g_return_val_if_fail (GDK_IS_DISPLAY (display), False);
-
- display_x11 = GDK_DISPLAY_X11 (display);
-
- if (display_x11->keyboard_xgrab_window)
- {
- if (grab_window)
- *grab_window = (GdkWindow *)display_x11->keyboard_xgrab_window;
- if (owner_events)
- *owner_events = display_x11->keyboard_xgrab_owner_events;
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
/**
* _gdk_xgrab_check_unmap:
* @window: a #GdkWindow
_gdk_xgrab_check_unmap (GdkWindow *window,
gulong serial)
{
- GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
-
- if (display_x11->pointer_xgrab_window &&
- serial >= display_x11->pointer_xgrab_serial)
- {
- GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
- GdkWindowObject *tmp = display_x11->pointer_xgrab_window;
+ GdkDisplay *display = gdk_drawable_get_display (window);
- while (tmp && tmp != private)
- tmp = tmp->parent;
+ _gdk_display_end_pointer_grab (display, serial, window, TRUE);
- if (tmp)
- {
- generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
- FALSE, display_x11->pointer_xgrab_implicit,
- NULL);
- display_x11->pointer_xgrab_window = NULL;
- }
- }
-
- if (display_x11->keyboard_xgrab_window &&
- serial >= display_x11->keyboard_xgrab_serial)
+ if (display->keyboard_grab.window &&
+ serial >= display->keyboard_grab.serial)
{
GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
- GdkWindowObject *tmp = display_x11->keyboard_xgrab_window;
-
+ GdkWindowObject *tmp = GDK_WINDOW_OBJECT (display->keyboard_grab.window);
while (tmp && tmp != private)
tmp = tmp->parent;
if (tmp)
- {
- generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
- TRUE, FALSE, NULL);
- display_x11->keyboard_xgrab_window = NULL;
- }
+ _gdk_display_unset_has_keyboard_grab (display, TRUE);
}
}
void
_gdk_xgrab_check_destroy (GdkWindow *window)
{
- GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
-
- if ((GdkWindowObject *)window == display_x11->pointer_xgrab_window)
- {
- generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
- FALSE, display_x11->pointer_xgrab_implicit,
- NULL);
- display_x11->pointer_xgrab_window = NULL;
- }
+ GdkDisplay *display = gdk_drawable_get_display (window);
+ GdkPointerGrabInfo *grab;
- if ((GdkWindowObject *)window == display_x11->keyboard_xgrab_window)
+ /* Make sure there is no lasting grab in this native
+ window */
+ grab = _gdk_display_get_last_pointer_grab (display);
+ if (grab && grab->native_window == window)
{
- generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
- TRUE, FALSE, NULL);
- display_x11->keyboard_xgrab_window = NULL;
+ /* We don't know the actual serial to end, but it
+ doesn't really matter as this only happens
+ after we get told of the destroy from the
+ server so we know its ended in the server,
+ just make sure its ended. */
+ grab->serial_end = grab->serial_start;
+ grab->implicit_ungrab = TRUE;
}
-}
-
-#define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
- GDK_BUTTON2_MASK | \
- GDK_BUTTON3_MASK | \
- GDK_BUTTON4_MASK | \
- GDK_BUTTON5_MASK)
-
-/**
- * _gdk_xgrab_check_button_event:
- * @window: a #GdkWindow
- * @event: an XEvent of type ButtonPress or ButtonRelease
- *
- * Checks to see if a button event starts or ends an implicit grab.
- **/
-void
-_gdk_xgrab_check_button_event (GdkWindow *window,
- XEvent *xevent)
-{
- GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
- /* track implicit grabs for button presses */
- switch (xevent->type)
- {
- case ButtonPress:
- if (!display_x11->pointer_xgrab_window)
- {
- display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
- display_x11->pointer_xgrab_serial = xevent->xany.serial;
- display_x11->pointer_xgrab_owner_events = FALSE;
- display_x11->pointer_xgrab_time = xevent->xbutton.time;
- display_x11->pointer_xgrab_implicit = TRUE;
- }
- break;
- case ButtonRelease:
- if (display_x11->pointer_xgrab_window &&
- display_x11->pointer_xgrab_implicit &&
- (xevent->xbutton.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (xevent->xbutton.button - 1))) == 0)
- {
- display_x11->pointer_xgrab_window = NULL;
- }
- break;
- default:
- g_assert_not_reached ();
- }
+ if (window == display->keyboard_grab.native_window &&
+ display->keyboard_grab.window != NULL)
+ _gdk_display_unset_has_keyboard_grab (display, TRUE);
}
void
}
GdkPixmap*
-gdk_pixmap_new (GdkDrawable *drawable,
- gint width,
- gint height,
- gint depth)
+_gdk_pixmap_new (GdkDrawable *drawable,
+ gint width,
+ gint height,
+ gint depth)
{
GdkPixmap *pixmap;
GdkDrawableImplX11 *draw_impl;
}
GdkPixmap *
-gdk_bitmap_create_from_data (GdkDrawable *drawable,
- const gchar *data,
- gint width,
- gint height)
+_gdk_bitmap_create_from_data (GdkDrawable *drawable,
+ const gchar *data,
+ gint width,
+ gint height)
{
GdkPixmap *pixmap;
GdkDrawableImplX11 *draw_impl;
}
GdkPixmap*
-gdk_pixmap_create_from_data (GdkDrawable *drawable,
- const gchar *data,
- gint width,
- gint height,
- gint depth,
- const GdkColor *fg,
- const GdkColor *bg)
+_gdk_pixmap_create_from_data (GdkDrawable *drawable,
+ const gchar *data,
+ gint width,
+ gint height,
+ gint depth,
+ const GdkColor *fg,
+ const GdkColor *bg)
{
GdkPixmap *pixmap;
GdkDrawableImplX11 *draw_impl;
Pixmap _gdk_x11_image_get_shm_pixmap (GdkImage *image);
/* Routines from gdkgeometry-x11.c */
-void _gdk_window_init_position (GdkWindow *window);
void _gdk_window_move_resize_child (GdkWindow *window,
gint x,
gint y,
gulong serial,
GdkRectangle *area);
-void _gdk_x11_window_scroll (GdkWindow *window,
- gint dx,
- gint dy);
-void _gdk_x11_window_move_region (GdkWindow *window,
- const GdkRegion *region,
- gint dx,
- gint dy);
+gboolean _gdk_x11_window_queue_antiexpose (GdkWindow *window,
+ GdkRegion *area);
+void _gdk_x11_window_queue_translation (GdkWindow *window,
+ GdkRegion *area,
+ gint dx,
+ gint dy);
void _gdk_selection_window_destroyed (GdkWindow *window);
gboolean _gdk_selection_filter_clear_event (XSelectionClearEvent *event);
void _gdk_xgrab_check_unmap (GdkWindow *window,
gulong serial);
void _gdk_xgrab_check_destroy (GdkWindow *window);
-void _gdk_xgrab_check_button_event (GdkWindow *window,
- XEvent *xevent);
gboolean _gdk_x11_display_is_root_window (GdkDisplay *display,
Window xroot_window);
#define GDK_WINDOW_DISPLAY(win) (GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (win))->display)
#define GDK_WINDOW_XROOTWIN(win) (GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (win))->xroot_window)
#define GDK_GC_DISPLAY(gc) (GDK_SCREEN_DISPLAY (GDK_GC_X11(gc)->screen))
+#define GDK_WINDOW_IS_X11(win) (GDK_IS_WINDOW_IMPL_X11 (((GdkWindowObject *)win)->impl))
#endif /* __GDK_PRIVATE_X11_H__ */
Atom xtype;
int res;
- g_return_val_if_fail (!window || GDK_IS_WINDOW (window), FALSE);
+ g_return_val_if_fail (!window || GDK_WINDOW_IS_X11 (window), FALSE);
if (!window)
{
GDK_NOTE (MULTIHEAD, g_message ("gdk_property_get(): window is NULL\n"));
}
+ else if (!GDK_WINDOW_IS_X11 (window))
+ return FALSE;
if (GDK_WINDOW_DESTROYED (window))
return FALSE;
Atom xproperty;
Atom xtype;
- g_return_if_fail (!window || GDK_IS_WINDOW (window));
+ g_return_if_fail (!window || GDK_WINDOW_IS_X11 (window));
if (!window)
{
GDK_NOTE (MULTIHEAD, g_message ("gdk_property_change(): window is NULL\n"));
}
-
+ else if (!GDK_WINDOW_IS_X11 (window))
+ return;
if (GDK_WINDOW_DESTROYED (window))
return;
gdk_property_delete (GdkWindow *window,
GdkAtom property)
{
- g_return_if_fail (!window || GDK_IS_WINDOW (window));
+ g_return_if_fail (!window || GDK_WINDOW_IS_X11 (window));
if (!window)
{
GDK_NOTE (MULTIHEAD,
g_message ("gdk_property_delete(): window is NULL\n"));
}
+ else if (!GDK_WINDOW_IS_X11 (window))
+ return;
if (GDK_WINDOW_DESTROYED (window))
return;
if (owner)
{
- if (GDK_WINDOW_DESTROYED (owner))
+ if (GDK_WINDOW_DESTROYED (owner) || !GDK_WINDOW_IS_X11 (owner))
return FALSE;
xdisplay = GDK_WINDOW_XDISPLAY (owner);
g_return_if_fail (selection != GDK_NONE);
- if (GDK_WINDOW_DESTROYED (requestor))
+ if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
return;
display = GDK_WINDOW_DISPLAY (requestor);
g_return_val_if_fail (requestor != NULL, 0);
g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
+ g_return_val_if_fail (GDK_WINDOW_IS_X11 (requestor), 0);
display = GDK_WINDOW_DISPLAY (requestor);
- if (GDK_WINDOW_DESTROYED (requestor))
+ if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
goto err;
t = NULL;
static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
static void gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
GdkColormap *cmap);
-static void gdk_window_impl_x11_get_size (GdkDrawable *drawable,
- gint *width,
- gint *height);
-static GdkRegion* gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable);
static void gdk_window_impl_x11_finalize (GObject *object);
static void gdk_window_impl_iface_init (GdkWindowImplIface *iface);
-#define WINDOW_IS_TOPLEVEL(window) \
- (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
- GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+#define WINDOW_IS_TOPLEVEL(window) \
+ (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
+ GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
+ GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
/* Return whether time1 is considered later than time2 as far as xserver
* time is concerned. Accounts for wraparound.
static void
gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
{
- impl->width = 1;
- impl->height = 1;
impl->toplevel_window_type = -1;
}
drawable_class->set_colormap = gdk_window_impl_x11_set_colormap;
drawable_class->get_colormap = gdk_window_impl_x11_get_colormap;
- drawable_class->get_size = gdk_window_impl_x11_get_size;
-
- /* Visible and clip regions are the same */
- drawable_class->get_clip_region = gdk_window_impl_x11_get_visible_region;
- drawable_class->get_visible_region = gdk_window_impl_x11_get_visible_region;
}
static void
obj = (GdkWindowObject *) window;
impl = GDK_WINDOW_IMPL_X11 (obj->impl);
- /* For windows without EXPOSURE_MASK, we can't do this
- * unsetting because such windows depend on the drawing
- * that the X server is going to do
- */
- if (!(obj->event_mask & GDK_EXPOSURE_MASK))
- return;
-
- impl->position_info.no_bg = TRUE;
+ impl->no_bg = TRUE;
if (obj->bg_pixmap != GDK_NO_BG)
XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
obj = (GdkWindowObject *) window;
impl = GDK_WINDOW_IMPL_X11 (obj->impl);
- if (!(obj->event_mask & GDK_EXPOSURE_MASK))
- return;
-
- impl->position_info.no_bg = FALSE;
+ impl->no_bg = FALSE;
if (obj->bg_pixmap == GDK_NO_BG)
return;
if (private->input_only || private->destroyed ||
(private->window_type != GDK_WINDOW_ROOT &&
!GDK_WINDOW_IS_MAPPED (window)))
- {
- return;
- }
-
- if (private->window_type != GDK_WINDOW_ROOT &&
+ return;
+
+ if (_gdk_window_has_impl (window) &&
+ GDK_WINDOW_IS_X11 (window) &&
+ private->window_type != GDK_WINDOW_ROOT &&
private->window_type != GDK_WINDOW_FOREIGN)
- {
- tmp_unset_bg (window);
- }
+ tmp_unset_bg (window);
if (recurse)
{
}
}
+void
+_gdk_x11_window_tmp_unset_parent_bg (GdkWindow *window)
+{
+ GdkWindowObject *private;
+ private = (GdkWindowObject*) window;
+
+ if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+ return;
+
+ window = _gdk_window_get_impl_window ((GdkWindow *)private->parent);
+ _gdk_x11_window_tmp_unset_bg (window, FALSE);
+}
+
void
_gdk_x11_window_tmp_reset_bg (GdkWindow *window,
gboolean recurse)
if (private->input_only || private->destroyed ||
(private->window_type != GDK_WINDOW_ROOT &&
!GDK_WINDOW_IS_MAPPED (window)))
- {
- return;
- }
+ return;
- if (private->window_type != GDK_WINDOW_ROOT &&
+
+ if (_gdk_window_has_impl (window) &&
+ GDK_WINDOW_IS_X11 (window) &&
+ private->window_type != GDK_WINDOW_ROOT &&
private->window_type != GDK_WINDOW_FOREIGN)
- {
- tmp_reset_bg (window);
- }
+ tmp_reset_bg (window);
if (recurse)
{
}
}
+void
+_gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window)
+{
+ GdkWindowObject *private;
+ private = (GdkWindowObject*) window;
+
+ if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+ return;
+
+ window = _gdk_window_get_impl_window ((GdkWindow *)private->parent);
+
+ _gdk_x11_window_tmp_reset_bg (window, FALSE);
+}
+
static GdkColormap*
gdk_window_impl_x11_get_colormap (GdkDrawable *drawable)
{
}
-static void
-gdk_window_impl_x11_get_size (GdkDrawable *drawable,
- gint *width,
- gint *height)
-{
- g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
-
- if (width)
- *width = GDK_WINDOW_IMPL_X11 (drawable)->width;
- if (height)
- *height = GDK_WINDOW_IMPL_X11 (drawable)->height;
-}
-
-static GdkRegion*
-gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable)
-{
- GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (drawable);
- GdkRectangle result_rect;
-
- result_rect.x = 0;
- result_rect.y = 0;
- result_rect.width = impl->width;
- result_rect.height = impl->height;
-
- gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);
-
- return gdk_region_rectangle (&result_rect);
-}
-
void
_gdk_windowing_window_init (GdkScreen * screen)
{
private = (GdkWindowObject *) screen_x11->root_window;
private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+ private->impl_window = private;
impl = GDK_WINDOW_IMPL_X11 (private->impl);
draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
private->window_type = GDK_WINDOW_ROOT;
private->depth = DefaultDepthOfScreen (screen_x11->xscreen);
-
- impl->width = WidthOfScreen (screen_x11->xscreen);
- impl->height = HeightOfScreen (screen_x11->xscreen);
-
- _gdk_window_init_position (GDK_WINDOW (private));
+ private->x = 0;
+ private->y = 0;
+ private->abs_x = 0;
+ private->abs_y = 0;
+ private->width = WidthOfScreen (screen_x11->xscreen);
+ private->height = HeightOfScreen (screen_x11->xscreen);
+
_gdk_xid_table_insert (screen_x11->display,
&screen_x11->xroot_window,
screen_x11->root_window);
{
GdkWindowObject *obj = (GdkWindowObject *)window;
GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
- GdkWindowImplX11 *impl = (GdkWindowImplX11 *)obj->impl;
Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
XID xid = GDK_WINDOW_XID (window);
XID xparent = GDK_WINDOW_XID (parent);
* correct value???
*/
size_hints.flags = PSize;
- size_hints.width = impl->width;
- size_hints.height = impl->height;
+ size_hints.width = obj->width;
+ size_hints.height = obj->height;
XSetWMNormalHints (xdisplay, xid, &size_hints);
ensure_sync_counter (window);
}
-GdkWindow *
-_gdk_window_new (GdkWindow *parent,
- GdkWindowAttr *attributes,
- gint attributes_mask)
+void
+_gdk_window_impl_new (GdkWindow *window,
+ GdkWindow *real_parent,
+ GdkScreen *screen,
+ GdkVisual *visual,
+ GdkEventMask event_mask,
+ GdkWindowAttr *attributes,
+ gint attributes_mask)
{
- GdkWindow *window;
GdkWindowObject *private;
GdkWindowImplX11 *impl;
GdkDrawableImplX11 *draw_impl;
GdkScreenX11 *screen_x11;
- GdkScreen *screen;
- GdkVisual *visual;
Window xparent;
Visual *xvisual;
Display *xdisplay;
XSetWindowAttributes xattributes;
long xattributes_mask;
XClassHint *class_hint;
- int x, y, depth;
unsigned int class;
const char *title;
int i;
- g_return_val_if_fail (attributes != NULL, NULL);
+ private = (GdkWindowObject *) window;
- if (!parent)
- {
- GDK_NOTE (MULTIHEAD,
- g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
-
- screen = gdk_screen_get_default ();
- parent = gdk_screen_get_root_window (screen);
- }
- else
- screen = gdk_drawable_get_screen (parent);
-
screen_x11 = GDK_SCREEN_X11 (screen);
-
- g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
-
- if (GDK_WINDOW_DESTROYED (parent))
- return NULL;
+ xparent = GDK_WINDOW_XID (real_parent);
- xparent = GDK_WINDOW_XID (parent);
-
- window = g_object_new (GDK_TYPE_WINDOW, NULL);
-
- private = (GdkWindowObject *) window;
- private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
-
- impl = GDK_WINDOW_IMPL_X11 (private->impl);
- draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
+ impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+ private->impl = (GdkDrawable *)impl;
+ draw_impl = GDK_DRAWABLE_IMPL_X11 (impl);
draw_impl->wrapper = GDK_DRAWABLE (window);
draw_impl->screen = screen;
xdisplay = screen_x11->xdisplay;
- /* Windows with a foreign parent are treated as if they are children
- * of the root window, except for actual creation.
- */
- if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
- parent = gdk_screen_get_root_window (screen);
-
- private->parent = (GdkWindowObject *)parent;
-
- private->accept_focus = TRUE;
- private->focus_on_map = TRUE;
-
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;
- impl->width = (attributes->width > 1) ? (attributes->width) : (1);
- impl->height = (attributes->height > 1) ? (attributes->height) : (1);
-
- if (attributes->wclass == GDK_INPUT_ONLY)
- {
- /* Backwards compatiblity - we've always ignored
- * attributes->window_type for input-only windows
- * before
- */
- if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
- private->window_type = GDK_WINDOW_TEMP;
- else
- private->window_type = GDK_WINDOW_CHILD;
- }
- else
- private->window_type = attributes->window_type;
-
- /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
- * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
- */
- if (attributes->wclass == GDK_INPUT_ONLY &&
- GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT &&
- !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
- {
- g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
- attributes->wclass = GDK_INPUT_OUTPUT;
- }
- _gdk_window_init_position (GDK_WINDOW (private));
- if (impl->position_info.big)
- private->guffaw_gravity = TRUE;
-
- if (attributes_mask & GDK_WA_VISUAL)
- visual = attributes->visual;
- else
- visual = gdk_screen_get_system_visual (screen);
xvisual = ((GdkVisualPrivate*) visual)->xvisual;
xattributes.event_mask = StructureNotifyMask | PropertyChangeMask;
for (i = 0; i < _gdk_nenvent_masks; i++)
{
- if (attributes->event_mask & (1 << (i + 1)))
+ if (event_mask & (1 << (i + 1)))
xattributes.event_mask |= _gdk_event_mask_table[i];
}
- private->event_mask = attributes->event_mask;
-
if (xattributes.event_mask)
xattributes_mask |= CWEventMask;
case GDK_WINDOW_TOPLEVEL:
case GDK_WINDOW_DIALOG:
case GDK_WINDOW_TEMP:
- if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
+ if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
{
- g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
- "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
+ /* The common code warns for this case */
xparent = GDK_SCREEN_XROOTWIN (screen);
}
- case GDK_WINDOW_CHILD:
- break;
- default:
- g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
- return NULL;
}
- if (attributes->wclass == GDK_INPUT_OUTPUT)
+ if (!private->input_only)
{
class = InputOutput;
- depth = visual->depth;
- private->input_only = FALSE;
- private->depth = depth;
-
if (attributes_mask & GDK_WA_COLORMAP)
{
draw_impl->colormap = attributes->colormap;
}
}
- private->bg_color.pixel = BlackPixel (xdisplay, screen_x11->screen_num);
- private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
xattributes.background_pixel = private->bg_color.pixel;
- private->bg_pixmap = NULL;
-
xattributes.border_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
xattributes_mask |= CWBorderPixel | CWBackPixel;
}
else
{
- depth = 0;
- private->depth = 0;
class = InputOnly;
- private->input_only = TRUE;
draw_impl->colormap = gdk_screen_get_system_colormap (screen);
g_object_ref (draw_impl->colormap);
}
+ if (private->width > 65535 ||
+ private->height > 65535)
+ {
+ g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
+
+ if (private->width > 65535)
+ private->width = 65535;
+ if (private->height > 65535)
+ private->height = 65535;
+ }
+
xid = draw_impl->xid = XCreateWindow (xdisplay, xparent,
- impl->position_info.x, impl->position_info.y,
- impl->position_info.width, impl->position_info.height,
- 0, depth, class, xvisual,
+ private->x + private->parent->abs_x,
+ private->y + private->parent->abs_y,
+ private->width, private->height,
+ 0, private->depth, class, xvisual,
xattributes_mask, &xattributes);
g_object_ref (window);
_gdk_xid_table_insert (screen_x11->display, &draw_impl->xid, window);
-
- gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
- (attributes->cursor) :
- NULL));
-
- if (private->parent)
- private->parent->children = g_list_prepend (private->parent->children, window);
-
+
switch (GDK_WINDOW_TYPE (private))
{
case GDK_WINDOW_DIALOG:
XFree (class_hint);
}
- setup_toplevel_window (window, parent);
+ setup_toplevel_window (window, (GdkWindow *)private->parent);
break;
case GDK_WINDOW_CHILD:
- if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
+ if (!private->input_only &&
(draw_impl->colormap != gdk_screen_get_system_colormap (screen)) &&
(draw_impl->colormap != gdk_drawable_get_colormap (gdk_window_get_toplevel (window))))
{
if (attributes_mask & GDK_WA_TYPE_HINT)
gdk_window_set_type_hint (window, attributes->type_hint);
-
- return window;
}
static GdkEventMask
private = (GdkWindowObject *) window;
private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+ private->impl_window = private;
impl = GDK_WINDOW_IMPL_X11 (private->impl);
draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
private->x = attrs.x;
private->y = attrs.y;
- impl->width = attrs.width;
- impl->height = attrs.height;
+ private->width = attrs.width;
+ private->height = attrs.height;
private->window_type = GDK_WINDOW_FOREIGN;
private->destroyed = FALSE;
private->depth = attrs.depth;
- _gdk_window_init_position (GDK_WINDOW (private));
-
g_object_ref (window);
_gdk_xid_table_insert (display, &GDK_WINDOW_XID (window), window);
+
+ /* Update the clip region, etc */
+ _gdk_window_update_size (window);
+
return window;
}
#endif
}
-void
-_gdk_windowing_window_destroy (GdkWindow *window,
- gboolean recursing,
- gboolean foreign_destroy)
+static void
+_gdk_x11_window_destroy (GdkWindow *window,
+ gboolean recursing,
+ gboolean foreign_destroy)
{
GdkWindowObject *private = (GdkWindowObject *)window;
GdkToplevelX11 *toplevel;
_gdk_selection_window_destroyed (window);
- if (private->extension_events != 0)
- _gdk_input_window_destroy (window);
-
toplevel = _gdk_x11_window_get_toplevel (window);
if (toplevel)
gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
{
GdkWindowImplX11 *window_impl;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
window_impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
if (!GDK_WINDOW_DESTROYED (window))
}
static void
-gdk_window_x11_show (GdkWindow *window,
- gboolean raise)
+gdk_window_x11_show (GdkWindow *window, gboolean already_mapped)
{
- GdkWindowObject *private;
+ GdkWindowObject *private = (GdkWindowObject*) window;
GdkDisplay *display;
GdkDisplayX11 *display_x11;
GdkToplevelX11 *toplevel;
-
- private = (GdkWindowObject*) window;
- if (!private->destroyed)
- {
- GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
- Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
- Window xwindow = GDK_WINDOW_XID (window);
-
- if (raise)
- XRaiseWindow (xdisplay, xwindow);
+ GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
+ Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
+ Window xwindow = GDK_WINDOW_XID (window);
+ gboolean unset_bg;
- if (!GDK_WINDOW_IS_MAPPED (window))
- {
- set_initial_hints (window);
-
- gdk_synthesize_window_state (window,
- GDK_WINDOW_STATE_WITHDRAWN,
- 0);
- }
+ if (!already_mapped)
+ set_initial_hints (window);
- g_assert (GDK_WINDOW_IS_MAPPED (window));
-
- if (WINDOW_IS_TOPLEVEL (window))
- {
- display = gdk_drawable_get_display (window);
- display_x11 = GDK_DISPLAY_X11 (display);
- toplevel = _gdk_x11_window_get_toplevel (window);
-
- if (toplevel->user_time != 0 &&
+ if (WINDOW_IS_TOPLEVEL (window))
+ {
+ display = gdk_drawable_get_display (window);
+ display_x11 = GDK_DISPLAY_X11 (display);
+ toplevel = _gdk_x11_window_get_toplevel (window);
+
+ if (toplevel->user_time != 0 &&
display_x11->user_time != 0 &&
- XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
- gdk_x11_window_set_user_time (window, display_x11->user_time);
- }
-
- if (impl->position_info.mapped)
- {
- gboolean unset_bg = !private->input_only &&
- (private->window_type == GDK_WINDOW_CHILD ||
- impl->override_redirect) &&
- gdk_window_is_viewable (window);
-
- if (unset_bg)
- _gdk_x11_window_tmp_unset_bg (window, TRUE);
-
- XMapWindow (xdisplay, xwindow);
-
- if (unset_bg)
- {
- _gdk_x11_window_tmp_reset_bg (window, TRUE);
- gdk_window_invalidate_rect (window, NULL, TRUE);
- }
- }
+ XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
+ gdk_x11_window_set_user_time (window, display_x11->user_time);
}
+
+ unset_bg = !private->input_only &&
+ (private->window_type == GDK_WINDOW_CHILD ||
+ impl->override_redirect) &&
+ gdk_window_is_viewable (window);
+
+ if (unset_bg)
+ _gdk_x11_window_tmp_unset_bg (window, TRUE);
+
+ XMapWindow (xdisplay, xwindow);
+
+ if (unset_bg)
+ _gdk_x11_window_tmp_reset_bg (window, TRUE);
}
static void
return;
if (private->window_type == GDK_WINDOW_CHILD)
- start_window = (GdkWindow *)private->parent;
+ start_window = _gdk_window_get_impl_window ((GdkWindow *)private->parent);
else if (private->window_type == GDK_WINDOW_TEMP)
start_window = get_root (window);
return;
if (private->window_type == GDK_WINDOW_CHILD)
- start_window = (GdkWindow *)private->parent;
+ start_window = _gdk_window_get_impl_window ((GdkWindow *)private->parent);
else if (private->window_type == GDK_WINDOW_TEMP)
start_window = get_root (window);
break;
}
- if (!private->destroyed)
- {
- if (GDK_WINDOW_IS_MAPPED (window))
- gdk_synthesize_window_state (window,
- 0,
- GDK_WINDOW_STATE_WITHDRAWN);
-
- g_assert (!GDK_WINDOW_IS_MAPPED (window));
-
- _gdk_window_clear_update_area (window);
-
- pre_unmap (window);
-
- XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window));
-
- post_unmap (window);
- }
+ _gdk_window_clear_update_area (window);
+
+ pre_unmap (window);
+ XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window));
+ post_unmap (window);
}
static void
{
_gdk_window_move_resize_child (window,
x, y,
- impl->width, impl->height);
+ private->width, private->height);
}
else
{
_gdk_window_move_resize_child (window,
private->x, private->y,
width, height);
- _gdk_x11_drawable_update_size (private->impl);
}
else
{
if (impl->override_redirect)
{
- impl->width = width;
- impl->height = height;
+ private->width = width;
+ private->height = height;
_gdk_x11_drawable_update_size (private->impl);
}
else
{
- if (width != impl->width || height != impl->height)
+ if (width != private->width || height != private->height)
private->resize_count += 1;
}
}
private->x = x;
private->y = y;
- impl->width = width;
- impl->height = height;
+ private->width = width;
+ private->height = height;
_gdk_x11_drawable_update_size (private->impl);
}
else
{
- if (width != impl->width || height != impl->height)
+ if (width != private->width || height != private->height)
private->resize_count += 1;
}
}
GdkWindowObject *parent_private;
GdkWindowObject *old_parent_private;
GdkWindowImplX11 *impl;
- gboolean was_toplevel;
-
- if (!new_parent)
- new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
window_private = (GdkWindowObject*) window;
old_parent_private = (GdkWindowObject*)window_private->parent;
parent_private = (GdkWindowObject*) new_parent;
impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
+ _gdk_x11_window_tmp_unset_bg (window, TRUE);
+ _gdk_x11_window_tmp_unset_parent_bg (window);
XReparentWindow (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
GDK_WINDOW_XID (new_parent),
- x, y);
+ parent_private->abs_x + x, parent_private->abs_y + y);
+ _gdk_x11_window_tmp_reset_parent_bg (window);
+ _gdk_x11_window_tmp_reset_bg (window, TRUE);
- window_private->x = x;
- window_private->y = y;
-
- /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
- * the root window
- */
if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
- window_private->parent = (GdkWindowObject *)new_parent;
+ window_private->parent = parent_private;
/* Switch the window type as appropriate */
{
case GDK_WINDOW_ROOT:
case GDK_WINDOW_FOREIGN:
- was_toplevel = WINDOW_IS_TOPLEVEL (window);
-
- if (impl->toplevel_window_type != -1)
- GDK_WINDOW_TYPE (window) = impl->toplevel_window_type;
- else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
- GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+ /* Reparenting to toplevel */
+
+ if (!WINDOW_IS_TOPLEVEL (window) &&
+ GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
+ {
+ /* This is also done in common code at a later stage, but we
+ need it in setup_toplevel, so do it here too */
+ if (window_private->toplevel_window_type != -1)
+ GDK_WINDOW_TYPE (window) = window_private->toplevel_window_type;
+ else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+ GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+
+ /* Wasn't a toplevel, set up */
+ setup_toplevel_window (window, new_parent);
+ }
- if (WINDOW_IS_TOPLEVEL (window) && !was_toplevel)
- setup_toplevel_window (window, new_parent);
break;
+
case GDK_WINDOW_TOPLEVEL:
case GDK_WINDOW_CHILD:
case GDK_WINDOW_DIALOG:
case GDK_WINDOW_TEMP:
- if (WINDOW_IS_TOPLEVEL (window))
+ if (WINDOW_IS_TOPLEVEL (window) &&
+ impl->toplevel)
{
- /* Save the original window type so we can restore it if the
- * window is reparented back to be a toplevel
- */
- impl->toplevel_window_type = GDK_WINDOW_TYPE (window);
- GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
- if (impl->toplevel)
+ if (impl->toplevel->focus_window)
{
- if (impl->toplevel->focus_window)
- {
- XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
- _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
- }
-
- gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window),
- impl->toplevel);
- g_free (impl->toplevel);
- impl->toplevel = NULL;
+ XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
+ _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
}
+
+ gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window),
+ impl->toplevel);
+ g_free (impl->toplevel);
+ impl->toplevel = NULL;
}
}
- if (old_parent_private)
- old_parent_private->children = g_list_remove (old_parent_private->children, window);
-
- if ((old_parent_private &&
- (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
- (!old_parent_private && parent_private->guffaw_gravity))
- gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
-
- parent_private->children = g_list_prepend (parent_private->children, window);
- _gdk_window_init_position (GDK_WINDOW (window_private));
-
return FALSE;
}
static void
-gdk_window_x11_clear_area (GdkWindow *window,
- gint x,
- gint y,
- gint width,
- gint height,
- gboolean send_expose)
+gdk_window_x11_raise (GdkWindow *window)
{
- if (!GDK_WINDOW_DESTROYED (window))
- XClearArea (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
- x, y, width, height,
- send_expose);
+ XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
}
static void
-gdk_window_x11_raise (GdkWindow *window)
+gdk_window_x11_restack_under (GdkWindow *window,
+ GList *native_siblings /* in requested order, first is bottom-most */)
{
- if (!GDK_WINDOW_DESTROYED (window))
- XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
+ Window *windows;
+ int n_windows, i;
+ GList *l;
+
+ n_windows = g_list_length (native_siblings) + 1;
+ windows = g_new (Window, n_windows);
+
+ windows[0] = GDK_WINDOW_XID (window);
+ /* Reverse order, as input order is bottom-most first */
+ i = n_windows - 1;
+ for (l = native_siblings; l != NULL; l = l->next)
+ windows[i--] = GDK_WINDOW_XID (l->data);
+
+ XRestackWindows (GDK_WINDOW_XDISPLAY (window), windows, n_windows);
+
+ g_free (windows);
}
static void
gdk_window_x11_lower (GdkWindow *window)
{
- if (!GDK_WINDOW_DESTROYED (window))
- XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
+ XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
}
/**
guint32 timestamp)
{
GdkDisplay *display;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
- if (GDK_WINDOW_DESTROYED (window))
+ g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
+
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
display = GDK_WINDOW_DISPLAY (window);
{
XSizeHints size_hints;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
size_hints.flags = 0;
GdkDisplay *display;
Atom atom;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
display = gdk_drawable_get_display (window);
g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return GDK_WINDOW_TYPE_HINT_NORMAL;
type = GDK_WINDOW_TYPE_HINT_NORMAL;
{
GdkWindowObject *private;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
private = (GdkWindowObject*) window;
{
GdkToplevelX11 *toplevel;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
toplevel = _gdk_x11_window_get_toplevel (window);
{
GdkToplevelX11 *toplevel;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
toplevel = _gdk_x11_window_get_toplevel (window);
{
GdkToplevelX11 *toplevel;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
toplevel = _gdk_x11_window_get_toplevel (window);
{
XSizeHints size_hints;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
size_hints.flags = 0;
*geom_mask = 0;
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
size_hints = XAllocSizeHints ();
Display *xdisplay;
Window xwindow;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (title != NULL);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
display = gdk_drawable_get_display (window);
{
GdkDisplay *display;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
display = gdk_drawable_get_display (window);
- if (!GDK_WINDOW_DESTROYED (window))
+ if (!GDK_WINDOW_DESTROYED (window) &&
+ WINDOW_IS_TOPLEVEL (window))
{
if (role)
XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
**/
void
gdk_window_set_startup_id (GdkWindow *window,
- const gchar *startup_id)
+ const gchar *startup_id)
{
GdkDisplay *display;
display = gdk_drawable_get_display (window);
- if (!GDK_WINDOW_DESTROYED (window))
+ if (!GDK_WINDOW_DESTROYED (window) &&
+ WINDOW_IS_TOPLEVEL (window))
{
if (startup_id)
XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
- PropModeReplace, startup_id, strlen (startup_id));
+ PropModeReplace, (unsigned char *)startup_id, strlen (startup_id));
else
XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"));
gdk_window_set_transient_for (GdkWindow *window,
GdkWindow *parent)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent))
+ if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
+ WINDOW_IS_TOPLEVEL (window))
XSetTransientForHint (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
GDK_WINDOW_XID (parent));
gdk_window_x11_set_background (GdkWindow *window,
const GdkColor *color)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkColormap *colormap = gdk_drawable_get_colormap (window);
-
- if (!GDK_WINDOW_DESTROYED (window))
- XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window), color->pixel);
-
- private->bg_color = *color;
- gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
-
- if (private->bg_pixmap &&
- private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
- private->bg_pixmap != GDK_NO_BG)
- g_object_unref (private->bg_pixmap);
-
- private->bg_pixmap = NULL;
+ XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window), color->pixel);
}
static void
gdk_window_x11_set_back_pixmap (GdkWindow *window,
- GdkPixmap *pixmap,
- gboolean parent_relative)
+ GdkPixmap *pixmap)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
Pixmap xpixmap;
- if (pixmap && !gdk_drawable_get_colormap (pixmap))
- {
- g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
- return;
- }
-
- if (private->bg_pixmap &&
- private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
- private->bg_pixmap != GDK_NO_BG)
- g_object_unref (private->bg_pixmap);
-
- if (parent_relative)
- {
- xpixmap = ParentRelative;
- private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
- }
+ if (pixmap == GDK_PARENT_RELATIVE_BG)
+ xpixmap = ParentRelative;
+ else if (pixmap == GDK_NO_BG)
+ xpixmap = None;
else
- {
- if (pixmap)
- {
- g_object_ref (pixmap);
- private->bg_pixmap = pixmap;
- xpixmap = GDK_PIXMAP_XID (pixmap);
- }
- else
- {
- xpixmap = None;
- private->bg_pixmap = GDK_NO_BG;
- }
- }
+ xpixmap = GDK_PIXMAP_XID (pixmap);
if (!GDK_WINDOW_DESTROYED (window))
XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
}
static gint
-gdk_window_x11_get_origin (GdkWindow *window,
- gint *x,
- gint *y)
+gdk_window_x11_get_root_coords (GdkWindow *window,
+ gint x,
+ gint y,
+ gint *root_x,
+ gint *root_y)
{
gint return_val;
Window child;
return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
GDK_WINDOW_XROOTWIN (window),
- 0, 0, &tx, &ty,
+ x, y, &tx, &ty,
&child);
}
else
return_val = 0;
- if (x)
- *x = tx;
- if (y)
- *y = ty;
+ if (root_x)
+ *root_x = tx;
+ if (root_y)
+ *root_y = ty;
return return_val;
}
-/**
- * gdk_window_get_deskrelative_origin:
- * @window: a toplevel #GdkWindow
- * @x: return location for X coordinate
- * @y: return location for Y coordinate
- *
- * This gets the origin of a #GdkWindow relative to
- * an Enlightenment-window-manager desktop. As long as you don't
- * assume that the user's desktop/workspace covers the entire
- * root window (i.e. you don't assume that the desktop begins
- * at root window coordinate 0,0) this function is not necessary.
- * It's deprecated for that reason.
- *
- * Return value: not meaningful
- **/
-gboolean
-gdk_window_get_deskrelative_origin (GdkWindow *window,
- gint *x,
- gint *y)
+static gboolean
+gdk_window_x11_get_deskrelative_origin (GdkWindow *window,
+ gint *x,
+ gint *y)
{
gboolean return_val = FALSE;
gint num_children, format_return;
Window win, *child, parent, root;
- gint tx = 0;
- gint ty = 0;
Atom type_return;
Atom atom;
gulong number_return, bytes_after_return;
guchar *data_return;
- g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+ atom = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+ "ENLIGHTENMENT_DESKTOP");
+ win = GDK_WINDOW_XID (window);
- if (!GDK_WINDOW_DESTROYED (window))
+ while (XQueryTree (GDK_WINDOW_XDISPLAY (window), win, &root, &parent,
+ &child, (unsigned int *)&num_children))
{
- atom = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
- "ENLIGHTENMENT_DESKTOP");
- win = GDK_WINDOW_XID (window);
+ if ((child) && (num_children > 0))
+ XFree (child);
+
+ if (!parent)
+ break;
+ else
+ win = parent;
+
+ if (win == root)
+ break;
- while (XQueryTree (GDK_WINDOW_XDISPLAY (window), win, &root, &parent,
- &child, (unsigned int *)&num_children))
+ data_return = NULL;
+ XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), win, atom, 0, 0,
+ False, XA_CARDINAL, &type_return, &format_return,
+ &number_return, &bytes_after_return, &data_return);
+
+ if (type_return == XA_CARDINAL)
{
- if ((child) && (num_children > 0))
- XFree (child);
-
- if (!parent)
- break;
- else
- win = parent;
-
- if (win == root)
- break;
-
- data_return = NULL;
- XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), 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;
- }
+ XFree (data_return);
+ break;
}
-
- return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- win,
- 0, 0, &tx, &ty,
- &root);
- if (x)
- *x = tx;
- if (y)
- *y = ty;
}
+ return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ win,
+ 0, 0, x, y,
+ &root);
return return_val;
}
{
GdkRectangle rect;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
gdk_window_get_frame_extents (window, &rect);
if (x)
gint wx, wy;
gboolean got_frame_extents = FALSE;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (rect != NULL);
private = (GdkWindowObject*) window;
rect->width = 1;
rect->height = 1;
- if (GDK_WINDOW_DESTROYED (window))
- return;
-
while (private->parent && ((GdkWindowObject*) private->parent)->parent)
private = (GdkWindowObject*) private->parent;
*mask = xmask;
}
-GdkWindow*
-_gdk_windowing_window_get_pointer (GdkDisplay *display,
- GdkWindow *window,
- gint *x,
- gint *y,
- GdkModifierType *mask)
+static gboolean
+gdk_window_x11_get_pointer (GdkWindow *window,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask)
{
- GdkWindow *return_val;
+ GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+ gboolean return_val;
Window root;
Window child;
int rootx, rooty;
int winx = 0;
int winy = 0;
unsigned int xmask = 0;
- gint xoffset, yoffset;
- g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
-
- _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
+ g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
- return_val = NULL;
- if (!GDK_WINDOW_DESTROYED (window))
+
+ return_val = TRUE;
+ if (!GDK_WINDOW_DESTROYED (window))
{
- if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
+ if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
{
if (XQueryPointer (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
&root, &child, &rootx, &rooty, &winx, &winy, &xmask))
{
if (child)
- return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child);
+ return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child) != NULL;
}
- }
- else
+ }
+ else
{
GdkScreen *screen;
int originx, originy;
- _gdk_windowing_get_pointer (gdk_drawable_get_display (window), &screen,
+ _gdk_windowing_get_pointer (gdk_drawable_get_display (window), &screen,
&rootx, &rooty, &xmask);
gdk_window_get_origin (window, &originx, &originy);
winx = rootx - originx;
winy = rooty - originy;
}
}
-
- *x = winx + xoffset;
- *y = winy + yoffset;
+
+ *x = winx;
+ *y = winy;
*mask = xmask;
-
+
return return_val;
}
GdkWindow*
_gdk_windowing_window_at_pointer (GdkDisplay *display,
gint *win_x,
- gint *win_y)
+ gint *win_y,
+ GdkModifierType *mask)
{
GdkWindow *window;
GdkScreen *screen;
window = gdk_window_lookup_for_display (display, xwindow_last);
*win_x = window ? winx : -1;
*win_y = window ? winy : -1;
-
+ if (mask)
+ *mask = xmask;
+
return window;
}
if (!GDK_WINDOW_DESTROYED (window))
{
- GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
xevent_mask = StructureNotifyMask | PropertyChangeMask;
for (i = 0; i < _gdk_nenvent_masks; i++)
XFree (old_windows);
}
-#define WARN_SHAPE_TOO_BIG() g_warning ("GdkWindow is too large to allow the use of shape masks or shape regions.")
-
-/*
- * This needs the X11 shape extension.
- * If not available, shaped windows will look
- * ugly, but programs still work. Stefan Wille
- */
-static inline void
-do_shape_combine_mask (GdkWindow *window,
- GdkBitmap *mask,
- gint x,
- gint y,
- gint shape)
-{
- GdkWindowObject *private = (GdkWindowObject *)window;
- Pixmap pixmap;
- gint xoffset, yoffset;
-
- if (GDK_WINDOW_DESTROYED (window))
- return;
-
- _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
- if (xoffset != 0 || yoffset != 0)
- {
- WARN_SHAPE_TOO_BIG ();
- return;
- }
-
- if (shape == ShapeBounding
- ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
- : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
- {
- if (mask)
- {
- pixmap = GDK_PIXMAP_XID (mask);
-
- private->shaped = (shape == ShapeBounding);
- }
- else
- {
- x = 0;
- y = 0;
- pixmap = None;
-
- private->shaped = FALSE;
- }
-
- XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- shape,
- x, y,
- pixmap,
- ShapeSet);
- }
-}
-
-static void
-gdk_window_x11_shape_combine_mask (GdkWindow *window,
- GdkBitmap *mask,
- gint x,
- gint y)
-{
- do_shape_combine_mask (window, mask, x, y, ShapeBounding);
-}
-
-/**
- * gdk_window_input_shape_combine_mask:
- * @window: a #GdkWindow
- * @mask: shape mask
- * @x: X position of shape mask with respect to @window
- * @y: Y position of shape mask with respect to @window
- *
- * Like gdk_window_shape_combine_mask(), but the shape applies
- * only to event handling. Mouse events which happen while
- * the pointer position corresponds to an unset bit in the
- * mask will be passed on the window below @window.
- *
- * An input shape is typically used with RGBA windows.
- * The alpha channel of the window defines which pixels are
- * invisible and allows for nicely antialiased borders,
- * and the input shape controls where the window is
- * "clickable".
- *
- * On the X11 platform, this requires version 1.1 of the
- * shape extension.
- *
- * On the Win32 platform, this functionality is not present and the
- * function does nothing.
- *
- * Since: 2.10
- */
-void
-gdk_window_input_shape_combine_mask (GdkWindow *window,
- GdkBitmap *mask,
- gint x,
- gint y)
-{
-#ifdef ShapeInput
- do_shape_combine_mask (window, mask, x, y, ShapeInput);
-#endif
-}
-
-
static inline void
do_shape_combine_region (GdkWindow *window,
const GdkRegion *shape_region,
gint shape)
{
GdkWindowObject *private = (GdkWindowObject *)window;
- gint xoffset, yoffset;
-
+
if (GDK_WINDOW_DESTROYED (window))
return;
- _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
- if (xoffset != 0 || yoffset != 0)
- {
- WARN_SHAPE_TOO_BIG ();
- return;
- }
-
if (shape_region == NULL)
{
/* Use NULL mask to unset the shape */
- gdk_window_shape_combine_mask (window, NULL, 0, 0);
+ if (shape == ShapeBounding
+ ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
+ : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
+ {
+ if (shape == ShapeBounding)
+ private->shaped = FALSE;
+
+ if (shape == ShapeBounding)
+ {
+ _gdk_x11_window_tmp_unset_parent_bg (window);
+ _gdk_x11_window_tmp_unset_bg (window, TRUE);
+ }
+ XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ shape,
+ 0, 0,
+ None,
+ ShapeSet);
+ if (shape == ShapeBounding)
+ {
+ _gdk_x11_window_tmp_reset_parent_bg (window);
+ _gdk_x11_window_tmp_reset_bg (window, TRUE);
+ }
+ }
return;
}
gint n_rects = 0;
XRectangle *xrects = NULL;
- private->shaped = shape == ShapeBounding;
+ if (shape == ShapeBounding)
+ private->shaped = TRUE;
_gdk_region_get_xrectangles (shape_region,
0, 0,
&xrects, &n_rects);
+ if (shape == ShapeBounding)
+ {
+ _gdk_x11_window_tmp_unset_parent_bg (window);
+ _gdk_x11_window_tmp_unset_bg (window, TRUE);
+ }
XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
shape,
ShapeSet,
YXBanded);
+ if (shape == ShapeBounding)
+ {
+ _gdk_x11_window_tmp_reset_parent_bg (window);
+ _gdk_x11_window_tmp_reset_bg (window, TRUE);
+ }
+
g_free (xrects);
}
}
do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
}
-/**
- * gdk_window_input_shape_combine_region:
- * @window: a #GdkWindow
- * @shape_region: region of window to be non-transparent
- * @offset_x: X position of @shape_region in @window coordinates
- * @offset_y: Y position of @shape_region in @window coordinates
- *
- * Like gdk_window_shape_combine_region(), but the shape applies
- * only to event handling. Mouse events which happen while
- * the pointer position corresponds to an unset bit in the
- * mask will be passed on the window below @window.
- *
- * An input shape is typically used with RGBA windows.
- * The alpha channel of the window defines which pixels are
- * invisible and allows for nicely antialiased borders,
- * and the input shape controls where the window is
- * "clickable".
- *
- * On the X11 platform, this requires version 1.1 of the
- * shape extension.
- *
- * On the Win32 platform, this functionality is not present and the
- * function does nothing.
- *
- * Since: 2.10
- */
-void
-gdk_window_input_shape_combine_region (GdkWindow *window,
- const GdkRegion *shape_region,
- gint offset_x,
- gint offset_y)
+static void
+gdk_window_x11_input_shape_combine_region (GdkWindow *window,
+ const GdkRegion *shape_region,
+ gint offset_x,
+ gint offset_y)
{
#ifdef ShapeInput
do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
{
XSetWindowAttributes attr;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (!GDK_WINDOW_DESTROYED (window))
+ if (!GDK_WINDOW_DESTROYED (window) &&
+ WINDOW_IS_TOPLEVEL (window))
{
GdkWindowObject *private = (GdkWindowObject *)window;
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
{
GdkWindowObject *private;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
private = (GdkWindowObject *)window;
accept_focus = accept_focus != FALSE;
{
private->accept_focus = accept_focus;
- if (!GDK_WINDOW_DESTROYED (window))
+ if (!GDK_WINDOW_DESTROYED (window) &&
+ WINDOW_IS_TOPLEVEL (window))
update_wm_hints (window, FALSE);
}
}
{
GdkWindowObject *private;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
private = (GdkWindowObject *)window;
focus_on_map = focus_on_map != FALSE;
if (private->focus_on_map != focus_on_map)
{
private->focus_on_map = focus_on_map;
-
- if ((!GDK_WINDOW_DESTROYED (window)) && (!private->focus_on_map))
+
+ if ((!GDK_WINDOW_DESTROYED (window)) &&
+ (!private->focus_on_map) &&
+ WINDOW_IS_TOPLEVEL (window))
gdk_x11_window_set_user_time (window, 0);
}
}
glong timestamp_long = (glong)timestamp;
Window xid;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
display = gdk_drawable_get_display (window);
GdkDisplay *display;
gint n;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
display = gdk_drawable_get_display (window);
{
GdkToplevelX11 *toplevel;
- g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
toplevel = _gdk_x11_window_get_toplevel (window);
{
GdkDisplay *display;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ WINDOW_IS_TOPLEVEL (window))
return;
display = gdk_drawable_get_display (window);
void
gdk_window_iconify (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
void
gdk_window_deiconify (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
void
gdk_window_stick (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
void
gdk_window_unstick (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
void
gdk_window_maximize (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
void
gdk_window_unmaximize (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
void
gdk_window_fullscreen (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
void
gdk_window_unfullscreen (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
{
g_return_if_fail (GDK_IS_WINDOW (window));
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
{
g_return_if_fail (GDK_IS_WINDOW (window));
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (GDK_WINDOW_IS_MAPPED (window))
{
GdkToplevelX11 *toplevel;
- g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return NULL;
toplevel = _gdk_x11_window_get_toplevel (window);
g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
- if (GDK_WINDOW_DESTROYED (window) || (leader != NULL && GDK_WINDOW_DESTROYED (leader)))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ (leader != NULL && GDK_WINDOW_DESTROYED (leader)) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
toplevel = _gdk_x11_window_get_toplevel (window);
GdkWMDecoration decorations)
{
MotifWmHints hints;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return;
/* initialize to zero to avoid writing uninitialized data to socket */
memset(&hints, 0, sizeof(hints));
MotifWmHints *hints;
gboolean result = FALSE;
- g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return FALSE;
+
hints = gdk_window_get_mwm_hints (window);
if (hints)
MotifWmHints hints;
g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
+ return;
/* initialize to zero to avoid writing uninitialized data to socket */
memset(&hints, 0, sizeof(hints));
gdk_window_set_mwm_hints (window, &hints);
}
-/*
- * 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
+static GdkRegion *
+xwindow_get_shape (Display *xdisplay,
+ Window window,
+ gint shape_type)
{
- gint start;
- gint end;
- struct _gdk_span *next;
-};
+ GdkRegion *shape;
+ GdkRectangle *rl;
+ XRectangle *xrl;
+ gint rn, ord, i;
-static void
-gdk_add_to_span (struct _gdk_span **s,
- gint x,
- gint 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));
+ shape = NULL;
+
+ xrl = XShapeGetRectangles (xdisplay,
+ window,
+ shape_type, &rn, &ord);
- if (noo)
+ if (rn == 0)
+ return gdk_region_new (); /* Empty */
+
+ if (ord != YXBanded)
{
- noo->start = x;
- noo->end = xx;
- if (ptr2)
- {
- noo->next = ptr2->next;
- ptr2->next = noo;
- }
- else
- {
- noo->next = NULL;
- *s = noo;
- }
+ /* This really shouldn't happen with any xserver, as they
+ generally convert regions to YXBanded internally */
+ g_warning ("non YXBanded shape masks not supported");
+ XFree (xrl);
+ return NULL;
}
- 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);
+ rl = g_new (GdkRectangle, rn);
+ for (i = 0; i < rn; i++)
+ {
+ rl[i].x = xrl[i].x;
+ rl[i].y = xrl[i].y;
+ rl[i].width = xrl[i].width;
+ rl[i].height = xrl[i].height;
}
+ XFree (xrl);
+
+ shape = _gdk_region_new_from_yxbanded_rects (rl, rn);
+ g_free (rl);
+
+ return shape;
}
-static void
-gdk_propagate_shapes (Display *disp,
- Window win,
- gboolean merge,
- int shape)
-{
- 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);
+
+GdkRegion *
+_gdk_windowing_get_shape_for_mask (GdkBitmap *mask)
+{
+ GdkDisplay *display;
+ Window window;
+ GdkRegion *region;
+
+ display = gdk_drawable_get_display (GDK_DRAWABLE (mask));
+
+ window = XCreateSimpleWindow (GDK_DISPLAY_XDISPLAY (display),
+ GDK_SCREEN_XROOTWIN (gdk_display_get_default_screen (display)),
+ -1, -1, 1, 1, 0,
+ 0, 0);
+ XShapeCombineMask (GDK_DISPLAY_XDISPLAY (display),
+ window,
+ ShapeBounding,
+ 0, 0,
+ GDK_PIXMAP_XID (mask),
+ ShapeSet);
- 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, shape, 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);
+ region = xwindow_get_shape (GDK_DISPLAY_XDISPLAY (display),
+ window, ShapeBounding);
+
+ XDestroyWindow (GDK_DISPLAY_XDISPLAY (display),
+ window);
+
+ return region;
}
-static inline void
-do_child_shapes (GdkWindow *window,
- gboolean merge)
+GdkRegion *
+_gdk_windowing_window_get_shape (GdkWindow *window)
{
if (!GDK_WINDOW_DESTROYED (window) &&
gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
- {
- gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- merge,
- ShapeBounding);
- }
-}
+ return xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window), ShapeBounding);
-static void
-gdk_window_x11_set_child_shapes (GdkWindow *window)
-{
- do_child_shapes (window, FALSE);
+ return NULL;
}
-static void
-gdk_window_x11_merge_child_shapes (GdkWindow *window)
-{
- do_child_shapes (window, TRUE);
-}
-
-static inline void
-do_child_input_shapes (GdkWindow *window,
- gboolean merge)
+GdkRegion *
+_gdk_windowing_window_get_input_shape (GdkWindow *window)
{
#if defined(ShapeInput)
if (!GDK_WINDOW_DESTROYED (window) &&
gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
- {
- gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- merge,
- ShapeInput);
- }
+ return xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ ShapeInput);
#endif
-}
-/**
- * gdk_window_set_child_input_shapes:
- * @window: a #GdkWindow
- *
- * Sets the input shape mask of @window to the union of input shape masks
- * for all children of @window, ignoring the input shape mask of @window
- * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
- * the input shape mask of @window in the masks to be merged.
- *
- * Since: 2.10
- **/
-void
-gdk_window_set_child_input_shapes (GdkWindow *window)
-{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- do_child_input_shapes (window, FALSE);
-}
-
-/**
- * gdk_window_merge_child_input_shapes:
- * @window: a #GdkWindow
- *
- * Merges the input shape masks for any child windows into the
- * input shape mask for @window. i.e. the union of all input masks
- * for @window and its children will become the new input mask
- * for @window. See gdk_window_input_shape_combine_mask().
- *
- * This function is distinct from gdk_window_set_child_input_shapes()
- * because it includes @window's input shape mask in the set of
- * shapes to be merged.
- *
- * Since: 2.10
- **/
-void
-gdk_window_merge_child_input_shapes (GdkWindow *window)
-{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- do_child_input_shapes (window, TRUE);
+ return NULL;
}
-
static void
gdk_window_set_static_bit_gravity (GdkWindow *window,
gboolean on)
gint root_y,
guint32 timestamp)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
gint root_y,
guint32 timestamp)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
GdkWindowObject *private = (GdkWindowObject *)window;
GdkWindowImplX11 *impl;
- g_return_if_fail (GDK_IS_WINDOW (window));
-
+ if (!GDK_IS_WINDOW_IMPL_X11 (private->impl))
+ return;
+
impl = GDK_WINDOW_IMPL_X11 (private->impl);
if (!impl->use_synchronized_configure)
{
+ /* This basically means you want to do fancy X specific stuff, so
+ ensure we have a native window */
+ gdk_window_ensure_native (window);
+
impl->use_synchronized_configure = TRUE;
ensure_sync_counter (window);
}
{
GdkWindowImplX11 *impl;
- g_return_if_fail (GDK_IS_WINDOW (window));
+ if (!WINDOW_IS_TOPLEVEL (window))
+ return;
impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
if (!impl->use_synchronized_configure)
#endif
}
-/**
- * gdk_window_beep:
- * @window: a toplevel #GdkWindow
- *
- * Emits a short beep associated to @window in the appropriate
- * display, if supported. Otherwise, emits a short beep on
- * the display just as gdk_display_beep().
- *
- * Since: 2.12
- **/
void
-gdk_window_beep (GdkWindow *window)
+_gdk_windowing_window_beep (GdkWindow *window)
{
GdkDisplay *display;
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
display = GDK_WINDOW_DISPLAY (window);
#ifdef HAVE_XKB
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
- if (GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL (window))
return;
display = gdk_drawable_get_display (window);
#endif
}
+void
+_gdk_windowing_window_process_updates_recurse (GdkWindow *window,
+ GdkRegion *region)
+{
+ _gdk_window_process_updates_recurse (window, region);
+}
+
+void
+_gdk_windowing_before_process_all_updates (void)
+{
+}
+
+void
+_gdk_windowing_after_process_all_updates (void)
+{
+}
+
static void
gdk_window_impl_iface_init (GdkWindowImplIface *iface)
{
iface->withdraw = gdk_window_x11_withdraw;
iface->set_events = gdk_window_x11_set_events;
iface->get_events = gdk_window_x11_get_events;
- iface->clear_area = gdk_window_x11_clear_area;
iface->raise = gdk_window_x11_raise;
iface->lower = gdk_window_x11_lower;
+ iface->restack_under = gdk_window_x11_restack_under;
iface->move_resize = gdk_window_x11_move_resize;
- iface->scroll = _gdk_x11_window_scroll;
- iface->move_region = _gdk_x11_window_move_region;
iface->set_background = gdk_window_x11_set_background;
iface->set_back_pixmap = gdk_window_x11_set_back_pixmap;
iface->reparent = gdk_window_x11_reparent;
iface->set_cursor = gdk_window_x11_set_cursor;
iface->get_geometry = gdk_window_x11_get_geometry;
- iface->get_origin = gdk_window_x11_get_origin;
- iface->shape_combine_mask = gdk_window_x11_shape_combine_mask;
+ iface->get_root_coords = gdk_window_x11_get_root_coords;
+ iface->get_pointer = gdk_window_x11_get_pointer;
+ iface->get_deskrelative_origin = gdk_window_x11_get_deskrelative_origin;
iface->shape_combine_region = gdk_window_x11_shape_combine_region;
- iface->set_child_shapes = gdk_window_x11_set_child_shapes;
- iface->merge_child_shapes = gdk_window_x11_merge_child_shapes;
+ iface->input_shape_combine_region = gdk_window_x11_input_shape_combine_region;
iface->set_static_gravities = gdk_window_x11_set_static_gravities;
- iface->get_offsets = _gdk_x11_window_get_offsets;
+ iface->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
+ iface->queue_translation = _gdk_x11_window_queue_translation;
+ iface->destroy = _gdk_x11_window_destroy;
+ iface->input_window_destroy = _gdk_input_window_destroy;
+ iface->input_window_crossing = _gdk_input_crossing_event;
}
#define __GDK_WINDOW_X11_C__
typedef struct _GdkWindowImplX11Class GdkWindowImplX11Class;
typedef struct _GdkXPositionInfo GdkXPositionInfo;
-struct _GdkXPositionInfo
-{
- gint x;
- gint y;
- gint width;
- gint height;
- gint x_offset; /* Offsets to add to X coordinates within window */
- gint y_offset; /* to get GDK coodinates within window */
- guint big : 1;
- guint mapped : 1;
- guint no_bg : 1; /* Set when the window background is temporarily
- * unset during resizing and scaling */
- GdkRectangle clip_rect; /* visible rectangle of window */
-};
-
-
/* Window implementation for X11
*/
{
GdkDrawableImplX11 parent_instance;
- gint width;
- gint height;
-
- GdkXPositionInfo position_info;
GdkToplevelX11 *toplevel; /* Toplevel-specific information */
GdkCursor *cursor;
gint8 toplevel_window_type;
+ guint no_bg : 1; /* Set when the window background is temporarily
+ * unset during resizing and scaling */
guint override_redirect : 1;
guint use_synchronized_configure : 1;
GType gdk_window_impl_x11_get_type (void);
-void gdk_x11_window_set_user_time (GdkWindow *window,
- guint32 timestamp);
-
-GdkToplevelX11 *_gdk_x11_window_get_toplevel (GdkWindow *window);
-void _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
- gboolean recurse);
-void _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
- gboolean recurse);
+void gdk_x11_window_set_user_time (GdkWindow *window,
+ guint32 timestamp);
+GdkToplevelX11 *_gdk_x11_window_get_toplevel (GdkWindow *window);
+void _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
+ gboolean recurse);
+void _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
+ gboolean recurse);
+void _gdk_x11_window_tmp_unset_parent_bg (GdkWindow *window);
+void _gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window);
GdkCursor *_gdk_x11_window_get_cursor (GdkWindow *window);
void _gdk_x11_window_get_offsets (GdkWindow *window,
/* FIXME: is using the size request here broken? */
child = GTK_BIN (combo_box)->child;
-
- gdk_window_get_origin (child->window, &sx, &sy);
-
+
+ sx = sy = 0;
+
if (GTK_WIDGET_NO_WINDOW (child))
{
sx += child->allocation.x;
sy += child->allocation.y;
}
+ gdk_window_get_root_coords (child->window, sx, sy, &sx, &sy);
+
if (GTK_SHADOW_NONE != combo_box->priv->shadow_type)
sx -= GTK_WIDGET (combo_box)->style->xthickness;
menu_width = requisition.width;
active = gtk_menu_get_active (GTK_MENU (combo_box->priv->popup_widget));
- gdk_window_get_origin (widget->window, &menu_xpos, &menu_ypos);
- menu_xpos += widget->allocation.x;
- menu_ypos += widget->allocation.y + widget->allocation.height / 2 - 2;
+ menu_xpos = widget->allocation.x;
+ menu_ypos = widget->allocation.y + widget->allocation.height / 2 - 2;
if (active != NULL)
{
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
menu_xpos = menu_xpos + widget->allocation.width - menu_width;
+ gdk_window_get_root_coords (widget->window, menu_xpos, menu_ypos,
+ &menu_xpos, &menu_ypos);
+
/* Clamp the position on screen */
screen_width = gdk_screen_get_width (gtk_widget_get_screen (widget));
see bug #340204 */
GtkWidget *sample = GTK_WIDGET (combo_box);
- gdk_window_get_origin (sample->window, x, y);
+ *x = *y = 0;
if (GTK_WIDGET_NO_WINDOW (sample))
{
*y += sample->allocation.y;
}
+ gdk_window_get_root_coords (sample->window, *x, *y, x, y);
+
*width = sample->allocation.width;
hpolicy = vpolicy = GTK_POLICY_NEVER;
noinst_PROGRAMS = $(TEST_PROGS) \
simple \
+ flicker \
print-editor \
testaccel \
testassistant \
testmultiscreen \
testnotebookdnd \
testnouiprint \
+ testoffscreen \
testorientable \
testprint \
testrgb \
testtreesort \
treestoretest \
testxinerama \
+ testwindows \
pixbuf-read \
pixbuf-lowmem \
pixbuf-randomly-modified \
endif
+flicker_DEPENDENCIES = $(TEST_DEPS)
simple_DEPENDENCIES = $(TEST_DEPS)
print_editor_DEPENDENCIES = $(TEST_DEPS)
testicontheme_DEPENDENCIES = $(TEST_DEPS)
testmultiscreen_DEPENDENCIES = $(TEST_DEPS)
testnotebookdnd_DEPENDENCIES = $(TEST_DEPS)
testnouiprint_DEPENDENCIES = $(TEST_DEPS)
+testoffscreen_DEPENDENCIES = $(TEST_DEPS)
testorientable_DEPENDENCIES = $(TEST_DEPS)
testprint_DEPENDENCIES = $(TEST_DEPS)
testrecentchooser_DEPENDENCIES = $(TEST_DEPS)
testgrouping_DEPENDENCIES = $(TEST_DEPS)
testtooltips_DEPENDENCIES = $(TEST_DEPS)
testvolumebutton_DEPENDENCIES = $(TEST_DEPS)
+testwindows_DEPENDENCIES = $(TEST_DEPS)
+flicker_LDADD = $(LDADDS)
simple_LDADD = $(LDADDS)
print_editor_LDADD = $(LDADDS)
testaccel_LDADD = $(LDADDS)
testmultiscreen_LDADD = $(LDADDS)
testnotebookdnd_LDADD = $(LDADDS)
testnouiprint_LDADD = $(LDADDS)
+testoffscreen_LDADD = $(LDADDS)
testorientable_LDADD = $(LDADDS)
testprint_LDADD = $(LDADDS)
testrecentchooser_LDADD = $(LDADDS)
testgrouping_LDADD = $(LDADDS)
testtooltips_LDADD = $(LDADDS)
testvolumebutton_LDADD = $(LDADDS)
+testwindows_LDADD = $(LDADDS)
testentrycompletion_SOURCES = \
testvolumebutton_SOURCES = \
testvolumebutton.c
+testoffscreen_SOURCES = \
+ gtkoffscreenbox.c \
+ gtkoffscreenbox.h \
+ testoffscreen.c
+
+testwindow_SOURCES = \
+ testwindows.c
+
EXTRA_DIST += \
prop-editor.h \
testgtk.1 \
--- /dev/null
+#include <gtk/gtk.h>
+
+GtkWidget*
+create_flicker (void)
+{
+ GtkWidget *window1;
+ GtkWidget *hpaned1;
+ GtkWidget *vpaned2;
+ GtkWidget *hbox2;
+ GtkObject *spinbutton7_adj;
+ GtkWidget *spinbutton7;
+ GtkObject *spinbutton8_adj;
+ GtkWidget *spinbutton8;
+ GtkWidget *vbox1;
+ GtkObject *spinbutton9_adj;
+ GtkWidget *spinbutton9;
+ GtkObject *spinbutton10_adj;
+ GtkWidget *spinbutton10;
+ GtkObject *spinbutton11_adj;
+ GtkWidget *spinbutton11;
+ GtkObject *spinbutton12_adj;
+ GtkWidget *spinbutton12;
+ GtkObject *spinbutton13_adj;
+ GtkWidget *spinbutton13;
+ GtkObject *spinbutton14_adj;
+ GtkWidget *spinbutton14;
+ GtkObject *spinbutton15_adj;
+ GtkWidget *spinbutton15;
+ GtkObject *spinbutton16_adj;
+ GtkWidget *spinbutton16;
+ GtkWidget *vpaned1;
+ GtkWidget *hbox1;
+ GtkObject *spinbutton17_adj;
+ GtkWidget *spinbutton17;
+ GtkObject *spinbutton18_adj;
+ GtkWidget *spinbutton18;
+ GtkObject *spinbutton19_adj;
+ GtkWidget *spinbutton19;
+ GtkWidget *vbox2;
+ GtkObject *spinbutton20_adj;
+ GtkWidget *spinbutton20;
+ GtkObject *spinbutton21_adj;
+ GtkWidget *spinbutton21;
+ GtkObject *spinbutton22_adj;
+ GtkWidget *spinbutton22;
+ GtkObject *spinbutton23_adj;
+ GtkWidget *spinbutton23;
+ GtkObject *spinbutton24_adj;
+ GtkWidget *spinbutton24;
+ GtkObject *spinbutton25_adj;
+ GtkWidget *spinbutton25;
+ GtkObject *spinbutton26_adj;
+ GtkWidget *spinbutton26;
+ GtkObject *spinbutton27_adj;
+ GtkWidget *spinbutton27;
+
+ window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size (GTK_WINDOW (window1), 500, 400);
+ gtk_window_set_title (GTK_WINDOW (window1), "window1");
+
+ hpaned1 = gtk_hpaned_new ();
+ gtk_widget_show (hpaned1);
+ gtk_container_add (GTK_CONTAINER (window1), hpaned1);
+ gtk_paned_set_position (GTK_PANED (hpaned1), 100);
+
+ vpaned2 = gtk_vpaned_new ();
+ gtk_widget_show (vpaned2);
+ gtk_paned_pack1 (GTK_PANED (hpaned1), vpaned2, FALSE, TRUE);
+ gtk_paned_set_position (GTK_PANED (vpaned2), 100);
+
+ hbox2 = gtk_hbox_new (FALSE, 0);
+ gtk_widget_show (hbox2);
+ gtk_paned_pack1 (GTK_PANED (vpaned2), hbox2, FALSE, TRUE);
+
+ spinbutton7_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton7 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton7_adj), 1, 0);
+ gtk_widget_show (spinbutton7);
+ gtk_box_pack_start (GTK_BOX (hbox2), spinbutton7, TRUE, TRUE, 0);
+
+ spinbutton8_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton8 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton8_adj), 1, 0);
+ gtk_widget_show (spinbutton8);
+ gtk_box_pack_start (GTK_BOX (hbox2), spinbutton8, TRUE, TRUE, 0);
+
+ vbox1 = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (vbox1);
+ gtk_paned_pack2 (GTK_PANED (vpaned2), vbox1, TRUE, TRUE);
+
+ spinbutton9_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton9 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton9_adj), 1, 0);
+ gtk_widget_show (spinbutton9);
+ gtk_box_pack_start (GTK_BOX (vbox1), spinbutton9, FALSE, FALSE, 0);
+
+ spinbutton10_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton10 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton10_adj), 1, 0);
+ gtk_widget_show (spinbutton10);
+ gtk_box_pack_start (GTK_BOX (vbox1), spinbutton10, FALSE, FALSE, 0);
+
+ spinbutton11_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton11 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton11_adj), 1, 0);
+ gtk_widget_show (spinbutton11);
+ gtk_box_pack_start (GTK_BOX (vbox1), spinbutton11, FALSE, FALSE, 0);
+
+ spinbutton12_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton12 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton12_adj), 1, 0);
+ gtk_widget_show (spinbutton12);
+ gtk_box_pack_start (GTK_BOX (vbox1), spinbutton12, FALSE, FALSE, 0);
+
+ spinbutton13_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton13 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton13_adj), 1, 0);
+ gtk_widget_show (spinbutton13);
+ gtk_box_pack_start (GTK_BOX (vbox1), spinbutton13, FALSE, FALSE, 0);
+
+ spinbutton14_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton14 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton14_adj), 1, 0);
+ gtk_widget_show (spinbutton14);
+ gtk_box_pack_start (GTK_BOX (vbox1), spinbutton14, FALSE, FALSE, 0);
+
+ spinbutton15_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton15 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton15_adj), 1, 0);
+ gtk_widget_show (spinbutton15);
+ gtk_box_pack_start (GTK_BOX (vbox1), spinbutton15, FALSE, FALSE, 0);
+
+ spinbutton16_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton16 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton16_adj), 1, 0);
+ gtk_widget_show (spinbutton16);
+ gtk_box_pack_start (GTK_BOX (vbox1), spinbutton16, FALSE, FALSE, 0);
+
+ vpaned1 = gtk_vpaned_new ();
+ gtk_widget_show (vpaned1);
+ gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
+ gtk_paned_set_position (GTK_PANED (vpaned1), 0);
+
+ hbox1 = gtk_hbox_new (FALSE, 0);
+ gtk_widget_show (hbox1);
+ gtk_paned_pack1 (GTK_PANED (vpaned1), hbox1, FALSE, TRUE);
+
+ spinbutton17_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton17 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton17_adj), 1, 0);
+ gtk_widget_show (spinbutton17);
+ gtk_box_pack_start (GTK_BOX (hbox1), spinbutton17, TRUE, TRUE, 0);
+
+ spinbutton18_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton18 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton18_adj), 1, 0);
+ gtk_widget_show (spinbutton18);
+ gtk_box_pack_start (GTK_BOX (hbox1), spinbutton18, TRUE, TRUE, 0);
+
+ spinbutton19_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton19 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton19_adj), 1, 0);
+ gtk_widget_show (spinbutton19);
+ gtk_box_pack_start (GTK_BOX (hbox1), spinbutton19, TRUE, TRUE, 0);
+
+ vbox2 = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (vbox2);
+ gtk_paned_pack2 (GTK_PANED (vpaned1), vbox2, FALSE, FALSE);
+
+ spinbutton20_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton20 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton20_adj), 1, 0);
+ gtk_widget_show (spinbutton20);
+ gtk_box_pack_start (GTK_BOX (vbox2), spinbutton20, FALSE, FALSE, 0);
+
+ spinbutton21_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton21 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton21_adj), 1, 0);
+ gtk_widget_show (spinbutton21);
+ gtk_box_pack_start (GTK_BOX (vbox2), spinbutton21, FALSE, FALSE, 0);
+
+ spinbutton22_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton22 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton22_adj), 1, 0);
+ gtk_widget_show (spinbutton22);
+ gtk_box_pack_start (GTK_BOX (vbox2), spinbutton22, FALSE, FALSE, 0);
+
+ spinbutton23_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton23 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton23_adj), 1, 0);
+ gtk_widget_show (spinbutton23);
+ gtk_box_pack_start (GTK_BOX (vbox2), spinbutton23, FALSE, FALSE, 0);
+
+ spinbutton24_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton24 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton24_adj), 1, 0);
+ gtk_widget_show (spinbutton24);
+ gtk_box_pack_start (GTK_BOX (vbox2), spinbutton24, FALSE, FALSE, 0);
+
+ spinbutton25_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton25 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton25_adj), 1, 0);
+ gtk_widget_show (spinbutton25);
+ gtk_box_pack_start (GTK_BOX (vbox2), spinbutton25, FALSE, FALSE, 0);
+
+ spinbutton26_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton26 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton26_adj), 1, 0);
+ gtk_widget_show (spinbutton26);
+ gtk_box_pack_start (GTK_BOX (vbox2), spinbutton26, TRUE, FALSE, 0);
+
+ spinbutton27_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+ spinbutton27 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton27_adj), 1, 0);
+ gtk_widget_show (spinbutton27);
+ gtk_box_pack_end (GTK_BOX (vbox2), spinbutton27, FALSE, FALSE, 0);
+
+
+ return window1;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window1;
+
+ gtk_set_locale ();
+ gtk_init (&argc, &argv);
+
+ window1 = create_flicker ();
+ gtk_widget_show (window1);
+
+ gtk_main ();
+ return 0;
+}
+
--- /dev/null
+/*
+ * gtkoffscreenbox.c
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <gtk/gtk.h>
+
+#include "gtkoffscreenbox.h"
+
+static void gtk_offscreen_box_realize (GtkWidget *widget);
+static void gtk_offscreen_box_unrealize (GtkWidget *widget);
+static void gtk_offscreen_box_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_offscreen_box_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gboolean gtk_offscreen_box_damage (GtkWidget *widget,
+ GdkEventExpose *event);
+static gboolean gtk_offscreen_box_expose (GtkWidget *widget,
+ GdkEventExpose *offscreen);
+
+static void gtk_offscreen_box_add (GtkContainer *container,
+ GtkWidget *child);
+static void gtk_offscreen_box_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_offscreen_box_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data);
+static GType gtk_offscreen_box_child_type (GtkContainer *container);
+
+#define CHILD1_SIZE_SCALE 1.0
+#define CHILD2_SIZE_SCALE 1.0
+
+G_DEFINE_TYPE (GtkOffscreenBox, gtk_offscreen_box, GTK_TYPE_CONTAINER);
+
+static void
+to_child_2 (GtkOffscreenBox *offscreen_box,
+ double widget_x, double widget_y,
+ double *x_out, double *y_out)
+{
+ GtkAllocation child_area;
+ double x, y, xr, yr;
+ double cos_angle, sin_angle;
+
+ x = widget_x;
+ y = widget_y;
+
+ if (offscreen_box->child1 && GTK_WIDGET_VISIBLE (offscreen_box->child1))
+ y -= offscreen_box->child1->allocation.height;
+
+ child_area = offscreen_box->child2->allocation;
+
+ x -= child_area.width / 2;
+ y -= child_area.height / 2;
+
+ cos_angle = cos (-offscreen_box->angle);
+ sin_angle = sin (-offscreen_box->angle);
+
+ xr = x * cos_angle - y * sin_angle;
+ yr = x * sin_angle + y * cos_angle;
+ x = xr;
+ y = yr;
+
+ x += child_area.width / 2;
+ y += child_area.height / 2;
+
+ *x_out = x;
+ *y_out = y;
+}
+
+static void
+to_parent_2 (GtkOffscreenBox *offscreen_box,
+ double offscreen_x, double offscreen_y,
+ double *x_out, double *y_out)
+{
+ GtkAllocation child_area;
+ double x, y, xr, yr;
+ double cos_angle, sin_angle;
+
+ child_area = offscreen_box->child2->allocation;
+
+ x = offscreen_x;
+ y = offscreen_y;
+
+ x -= child_area.width / 2;
+ y -= child_area.height / 2;
+
+ cos_angle = cos (offscreen_box->angle);
+ sin_angle = sin (offscreen_box->angle);
+
+ xr = x * cos_angle - y * sin_angle;
+ yr = x * sin_angle + y * cos_angle;
+ x = xr;
+ y = yr;
+
+ x += child_area.width / 2;
+ y += child_area.height / 2;
+
+ if (offscreen_box->child1 && GTK_WIDGET_VISIBLE (offscreen_box->child1))
+ y += offscreen_box->child1->allocation.height;
+
+ *x_out = x;
+ *y_out = y;
+}
+
+static void
+gtk_offscreen_box_class_init (GtkOffscreenBoxClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+
+ widget_class->realize = gtk_offscreen_box_realize;
+ widget_class->unrealize = gtk_offscreen_box_unrealize;
+ widget_class->size_request = gtk_offscreen_box_size_request;
+ widget_class->size_allocate = gtk_offscreen_box_size_allocate;
+ widget_class->expose_event = gtk_offscreen_box_expose;
+
+ g_signal_override_class_closure (g_signal_lookup ("damage-event", GTK_TYPE_WIDGET),
+ GTK_TYPE_OFFSCREEN_BOX,
+ g_cclosure_new (G_CALLBACK (gtk_offscreen_box_damage),
+ NULL, NULL));
+
+ container_class->add = gtk_offscreen_box_add;
+ container_class->remove = gtk_offscreen_box_remove;
+ container_class->forall = gtk_offscreen_box_forall;
+ container_class->child_type = gtk_offscreen_box_child_type;
+}
+
+static void
+gtk_offscreen_box_init (GtkOffscreenBox *offscreen_box)
+{
+ GTK_WIDGET_UNSET_FLAGS (offscreen_box, GTK_NO_WINDOW);
+}
+
+GtkWidget *
+gtk_offscreen_box_new (void)
+{
+ return g_object_new (GTK_TYPE_OFFSCREEN_BOX, NULL);
+}
+
+static GdkWindow *
+get_offscreen_parent (GdkWindow *offscreen_window,
+ GtkOffscreenBox *offscreen_box)
+{
+ return GTK_WIDGET (offscreen_box)->window;
+}
+
+static GdkWindow *
+pick_offscreen_child (GdkWindow *offscreen_window,
+ double widget_x, double widget_y,
+ GtkOffscreenBox *offscreen_box)
+{
+ GtkAllocation child_area;
+ double x, y;
+
+ /* First check for child 2 */
+ if (offscreen_box->child2 &&
+ GTK_WIDGET_VISIBLE (offscreen_box->child2))
+ {
+ to_child_2 (offscreen_box,
+ widget_x, widget_y,
+ &x, &y);
+
+ child_area = offscreen_box->child2->allocation;
+
+ if (x >= 0 && x < child_area.width &&
+ y >= 0 && y < child_area.height)
+ return offscreen_box->offscreen_window2;
+ }
+
+ if (offscreen_box->child1 && GTK_WIDGET_VISIBLE (offscreen_box->child1))
+ {
+ x = widget_x;
+ y = widget_y;
+
+ child_area = offscreen_box->child1->allocation;
+
+ if (x >= 0 && x < child_area.width &&
+ y >= 0 && y < child_area.height)
+ return offscreen_box->offscreen_window1;
+ }
+
+ return NULL;
+}
+
+static void
+offscreen_window_to_parent1 (GdkWindow *offscreen_window,
+ double offscreen_x,
+ double offscreen_y,
+ double *parent_x,
+ double *parent_y,
+ GtkOffscreenBox *offscreen_box)
+{
+ *parent_x = offscreen_x;
+ *parent_y = offscreen_y;
+}
+
+static void
+offscreen_window_from_parent1 (GdkWindow *window,
+ double parent_x,
+ double parent_y,
+ double *offscreen_x,
+ double *offscreen_y,
+ GtkOffscreenBox *offscreen_box)
+{
+ *offscreen_x = parent_x;
+ *offscreen_y = parent_y;
+}
+
+static void
+offscreen_window_to_parent2 (GdkWindow *offscreen_window,
+ double offscreen_x,
+ double offscreen_y,
+ double *parent_x,
+ double *parent_y,
+ GtkOffscreenBox *offscreen_box)
+{
+ to_parent_2 (offscreen_box,
+ offscreen_x, offscreen_y,
+ parent_x, parent_y);
+}
+
+static void
+offscreen_window_from_parent2 (GdkWindow *window,
+ double parent_x,
+ double parent_y,
+ double *offscreen_x,
+ double *offscreen_y,
+ GtkOffscreenBox *offscreen_box)
+{
+ to_child_2 (offscreen_box,
+ parent_x, parent_y,
+ offscreen_x, offscreen_y);
+}
+
+static void
+gtk_offscreen_box_realize (GtkWidget *widget)
+{
+ GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (widget);
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ gint border_width;
+ GtkRequisition child_requisition;
+ int start_y = 0;
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ border_width = GTK_CONTAINER (widget)->border_width;
+
+ attributes.x = widget->allocation.x + border_width;
+ attributes.y = widget->allocation.y + border_width;
+ attributes.width = widget->allocation.width - 2 * border_width;
+ attributes.height = widget->allocation.height - 2 * border_width;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.event_mask = gtk_widget_get_events (widget)
+ | GDK_EXPOSURE_MASK
+ | GDK_POINTER_MOTION_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK
+ | GDK_SCROLL_MASK
+ | GDK_ENTER_NOTIFY_MASK
+ | GDK_LEAVE_NOTIFY_MASK;
+
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.wclass = GDK_INPUT_OUTPUT;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, widget);
+
+ gdk_window_set_has_offscreen_children (widget->window, TRUE);
+ g_signal_connect (widget->window, "pick-offscreen-child",
+ G_CALLBACK (pick_offscreen_child), offscreen_box);
+
+ attributes.window_type = GDK_WINDOW_OFFSCREEN;
+
+ /* Child 1 */
+ attributes.x = attributes.y = 0;
+ if (offscreen_box->child1 && GTK_WIDGET_VISIBLE (offscreen_box->child1))
+ {
+ attributes.width = offscreen_box->child1->allocation.width;
+ attributes.height = offscreen_box->child1->allocation.height;
+ start_y += offscreen_box->child1->allocation.height;
+ }
+ offscreen_box->offscreen_window1 = gdk_window_new (gtk_widget_get_root_window (widget),
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (offscreen_box->offscreen_window1, widget);
+ if (offscreen_box->child1)
+ gtk_widget_set_parent_window (offscreen_box->child1, offscreen_box->offscreen_window1);
+
+ g_signal_connect (offscreen_box->offscreen_window1, "get-offscreen-parent",
+ G_CALLBACK (get_offscreen_parent), offscreen_box);
+ g_signal_connect (offscreen_box->offscreen_window1, "to_parent",
+ G_CALLBACK (offscreen_window_to_parent1), offscreen_box);
+ g_signal_connect (offscreen_box->offscreen_window1, "from_parent",
+ G_CALLBACK (offscreen_window_from_parent1), offscreen_box);
+
+ /* Child 2 */
+ attributes.y = start_y;
+ child_requisition.width = child_requisition.height = 0;
+ if (offscreen_box->child2 && GTK_WIDGET_VISIBLE (offscreen_box->child2))
+ {
+ attributes.width = offscreen_box->child2->allocation.width;
+ attributes.height = offscreen_box->child2->allocation.height;
+ }
+ offscreen_box->offscreen_window2 = gdk_window_new (gtk_widget_get_root_window (widget),
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (offscreen_box->offscreen_window2, widget);
+ if (offscreen_box->child2)
+ gtk_widget_set_parent_window (offscreen_box->child2, offscreen_box->offscreen_window2);
+ g_signal_connect (offscreen_box->offscreen_window2, "get-offscreen-parent",
+ G_CALLBACK (get_offscreen_parent), offscreen_box);
+ g_signal_connect (offscreen_box->offscreen_window2, "to_parent",
+ G_CALLBACK (offscreen_window_to_parent2), offscreen_box);
+ g_signal_connect (offscreen_box->offscreen_window2, "from_parent",
+ G_CALLBACK (offscreen_window_from_parent2), offscreen_box);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+ gtk_style_set_background (widget->style, offscreen_box->offscreen_window1, GTK_STATE_NORMAL);
+ gtk_style_set_background (widget->style, offscreen_box->offscreen_window2, GTK_STATE_NORMAL);
+
+ gdk_window_show (offscreen_box->offscreen_window1);
+ gdk_window_show (offscreen_box->offscreen_window2);
+}
+
+static void
+gtk_offscreen_box_unrealize (GtkWidget *widget)
+{
+ GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (widget);
+
+ gdk_window_set_user_data (offscreen_box->offscreen_window1, NULL);
+ gdk_window_destroy (offscreen_box->offscreen_window1);
+ offscreen_box->offscreen_window1 = NULL;
+
+ gdk_window_set_user_data (offscreen_box->offscreen_window2, NULL);
+ gdk_window_destroy (offscreen_box->offscreen_window2);
+ offscreen_box->offscreen_window2 = NULL;
+
+ GTK_WIDGET_CLASS (gtk_offscreen_box_parent_class)->unrealize (widget);
+}
+
+static GType
+gtk_offscreen_box_child_type (GtkContainer *container)
+{
+ GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (container);
+
+ if (offscreen_box->child1 && offscreen_box->child2)
+ return G_TYPE_NONE;
+
+ return GTK_TYPE_WIDGET;
+}
+
+static void
+gtk_offscreen_box_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (container);
+
+ if (!offscreen_box->child1)
+ gtk_offscreen_box_add1 (offscreen_box, widget);
+ else if (!offscreen_box->child2)
+ gtk_offscreen_box_add2 (offscreen_box, widget);
+ else
+ g_warning ("GtkOffscreenBox cannot have more than 2 children\n");
+}
+
+void
+gtk_offscreen_box_add1 (GtkOffscreenBox *offscreen_box,
+ GtkWidget *child)
+{
+ g_return_if_fail (GTK_IS_OFFSCREEN_BOX (offscreen_box));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+
+ if (offscreen_box->child1 == NULL)
+ {
+ gtk_widget_set_parent_window (child, offscreen_box->offscreen_window1);
+ gtk_widget_set_parent (child, GTK_WIDGET (offscreen_box));
+ offscreen_box->child1 = child;
+ }
+}
+
+void
+gtk_offscreen_box_add2 (GtkOffscreenBox *offscreen_box,
+ GtkWidget *child)
+{
+ g_return_if_fail (GTK_IS_OFFSCREEN_BOX (offscreen_box));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+
+ if (offscreen_box->child2 == NULL)
+ {
+ gtk_widget_set_parent_window (child, offscreen_box->offscreen_window2);
+ gtk_widget_set_parent (child, GTK_WIDGET (offscreen_box));
+ offscreen_box->child2 = child;
+ }
+}
+
+static void
+gtk_offscreen_box_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (container);
+ gboolean was_visible;
+
+ was_visible = GTK_WIDGET_VISIBLE (widget);
+
+ if (offscreen_box->child1 == widget)
+ {
+ gtk_widget_unparent (widget);
+
+ offscreen_box->child1 = NULL;
+
+ if (was_visible && GTK_WIDGET_VISIBLE (container))
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+ }
+ else if (offscreen_box->child2 == widget)
+ {
+ gtk_widget_unparent (widget);
+
+ offscreen_box->child2 = NULL;
+
+ if (was_visible && GTK_WIDGET_VISIBLE (container))
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+ }
+}
+
+static void
+gtk_offscreen_box_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (container);
+
+ g_return_if_fail (callback != NULL);
+
+ if (offscreen_box->child1)
+ (*callback) (offscreen_box->child1, callback_data);
+ if (offscreen_box->child2)
+ (*callback) (offscreen_box->child2, callback_data);
+}
+
+void
+gtk_offscreen_box_set_angle (GtkOffscreenBox *offscreen_box,
+ gdouble angle)
+{
+ g_return_if_fail (GTK_IS_OFFSCREEN_BOX (offscreen_box));
+
+ offscreen_box->angle = angle;
+ gtk_widget_queue_draw (GTK_WIDGET (offscreen_box));
+
+ /* TODO: Really needs to resent pointer events if over the rotated window */
+}
+
+
+static void
+gtk_offscreen_box_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (widget);
+ int w, h;
+
+ w = 0;
+ h = 0;
+
+ if (offscreen_box->child1 && GTK_WIDGET_VISIBLE (offscreen_box->child1))
+ {
+ GtkRequisition child_requisition;
+
+ gtk_widget_size_request (offscreen_box->child1, &child_requisition);
+
+ w = MAX (w, CHILD1_SIZE_SCALE * child_requisition.width);
+ h += CHILD1_SIZE_SCALE * child_requisition.height;
+ }
+
+ if (offscreen_box->child2 && GTK_WIDGET_VISIBLE (offscreen_box->child2))
+ {
+ GtkRequisition child_requisition;
+
+ gtk_widget_size_request (offscreen_box->child2, &child_requisition);
+
+ w = MAX (w, CHILD2_SIZE_SCALE * child_requisition.width);
+ h += CHILD2_SIZE_SCALE * child_requisition.height;
+ }
+
+ requisition->width = GTK_CONTAINER (widget)->border_width * 2 + w;
+ requisition->height = GTK_CONTAINER (widget)->border_width * 2 + h;
+}
+
+static void
+gtk_offscreen_box_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkOffscreenBox *offscreen_box;
+ gint border_width;
+ gint start_y;
+
+ widget->allocation = *allocation;
+ offscreen_box = GTK_OFFSCREEN_BOX (widget);
+
+ border_width = GTK_CONTAINER (widget)->border_width;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (widget->window,
+ allocation->x + border_width,
+ allocation->y + border_width,
+ allocation->width - border_width * 2,
+ allocation->height - border_width * 2);
+
+ start_y = 0;
+
+ if (offscreen_box->child1 && GTK_WIDGET_VISIBLE (offscreen_box->child1))
+ {
+ GtkRequisition child_requisition;
+ GtkAllocation child_allocation;
+
+ gtk_widget_get_child_requisition (offscreen_box->child1, &child_requisition);
+ child_allocation.x = child_requisition.width * (CHILD1_SIZE_SCALE - 1.0) / 2;
+ child_allocation.y = start_y + child_requisition.height * (CHILD1_SIZE_SCALE - 1.0) / 2;
+ child_allocation.width = MAX (1, (gint) widget->allocation.width - 2 * border_width);
+ child_allocation.height = child_requisition.height;
+
+ start_y += CHILD1_SIZE_SCALE * child_requisition.height;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (offscreen_box->offscreen_window1,
+ child_allocation.x,
+ child_allocation.y,
+ child_allocation.width,
+ child_allocation.height);
+
+ child_allocation.x = child_allocation.y = 0;
+ gtk_widget_size_allocate (offscreen_box->child1, &child_allocation);
+ }
+
+ if (offscreen_box->child2 && GTK_WIDGET_VISIBLE (offscreen_box->child2))
+ {
+ GtkRequisition child_requisition;
+ GtkAllocation child_allocation;
+
+ gtk_widget_get_child_requisition (offscreen_box->child2, &child_requisition);
+ child_allocation.x = child_requisition.width * (CHILD2_SIZE_SCALE - 1.0) / 2;
+ child_allocation.y = start_y + child_requisition.height * (CHILD2_SIZE_SCALE - 1.0) / 2;
+ child_allocation.width = MAX (1, (gint) widget->allocation.width - 2 * border_width);
+ child_allocation.height = child_requisition.height;
+
+ start_y += CHILD2_SIZE_SCALE * child_requisition.height;
+
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (offscreen_box->offscreen_window2,
+ child_allocation.x,
+ child_allocation.y,
+ child_allocation.width,
+ child_allocation.height);
+
+ child_allocation.x = child_allocation.y = 0;
+ gtk_widget_size_allocate (offscreen_box->child2, &child_allocation);
+ }
+}
+
+static gboolean
+gtk_offscreen_box_damage (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ gdk_window_invalidate_rect (widget->window, NULL, FALSE);
+
+ return TRUE;
+}
+
+static gboolean
+gtk_offscreen_box_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (widget);
+
+ if (GTK_WIDGET_DRAWABLE (widget))
+ {
+ if (event->window == widget->window)
+ {
+ GdkPixmap *pixmap;
+ GtkAllocation child_area;
+ cairo_t *cr;
+ int start_y = 0;
+
+ if (offscreen_box->child1 && GTK_WIDGET_VISIBLE (offscreen_box->child1))
+ {
+ pixmap = gdk_window_get_offscreen_pixmap (offscreen_box->offscreen_window1);
+ child_area = offscreen_box->child1->allocation;
+
+ cr = gdk_cairo_create (widget->window);
+
+ gdk_cairo_set_source_pixmap (cr, pixmap, 0, 0);
+ cairo_paint (cr);
+
+ cairo_destroy (cr);
+
+ start_y += child_area.height;
+ }
+
+ if (offscreen_box->child2 && GTK_WIDGET_VISIBLE (offscreen_box->child2))
+ {
+ gint w, h;
+
+ pixmap = gdk_window_get_offscreen_pixmap (offscreen_box->offscreen_window2);
+ child_area = offscreen_box->child2->allocation;
+
+ cr = gdk_cairo_create (widget->window);
+
+ /* transform */
+ cairo_translate (cr, 0, start_y);
+ cairo_translate (cr, child_area.width / 2, child_area.height / 2);
+ cairo_rotate (cr, offscreen_box->angle);
+ cairo_translate (cr, -child_area.width / 2, -child_area.height / 2);
+
+ /* clip */
+ gdk_drawable_get_size (pixmap, &w, &h);
+ cairo_rectangle (cr, 0, 0, w, h);
+ cairo_clip (cr);
+
+ /* paint */
+ gdk_cairo_set_source_pixmap (cr, pixmap, 0, 0);
+ cairo_paint (cr);
+
+ cairo_destroy (cr);
+ }
+ }
+ else if (event->window == offscreen_box->offscreen_window1)
+ {
+ gtk_paint_flat_box (widget->style, event->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_NONE,
+ &event->area, widget, "blah",
+ 0, 0, -1, -1);
+
+ if (offscreen_box->child1)
+ gtk_container_propagate_expose (GTK_CONTAINER (widget),
+ offscreen_box->child1,
+ event);
+ }
+ else if (event->window == offscreen_box->offscreen_window2)
+ {
+ gtk_paint_flat_box (widget->style, event->window,
+ GTK_STATE_NORMAL, GTK_SHADOW_NONE,
+ &event->area, widget, "blah",
+ 0, 0, -1, -1);
+
+ if (offscreen_box->child2)
+ gtk_container_propagate_expose (GTK_CONTAINER (widget),
+ offscreen_box->child2,
+ event);
+ }
+ }
+
+ return FALSE;
+}
--- /dev/null
+#ifndef __GTK_OFFSCREEN_BOX_H__
+#define __GTK_OFFSCREEN_BOX_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_OFFSCREEN_BOX (gtk_offscreen_box_get_type ())
+#define GTK_OFFSCREEN_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_OFFSCREEN_BOX, GtkOffscreenBox))
+#define GTK_OFFSCREEN_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_OFFSCREEN_BOX, GtkOffscreenBoxClass))
+#define GTK_IS_OFFSCREEN_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_OFFSCREEN_BOX))
+#define GTK_IS_OFFSCREEN_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_OFFSCREEN_BOX))
+#define GTK_OFFSCREEN_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_OFFSCREEN_BOX, GtkOffscreenBoxClass))
+
+typedef struct _GtkOffscreenBox GtkOffscreenBox;
+typedef struct _GtkOffscreenBoxClass GtkOffscreenBoxClass;
+
+struct _GtkOffscreenBox
+{
+ GtkContainer container;
+
+ GtkWidget *child1;
+ GtkWidget *child2;
+
+ GdkWindow *offscreen_window1;
+ GdkWindow *offscreen_window2;
+
+ gdouble angle;
+};
+
+struct _GtkOffscreenBoxClass
+{
+ GtkBinClass parent_class;
+};
+
+GType gtk_offscreen_box_get_type (void) G_GNUC_CONST;
+GtkWidget* gtk_offscreen_box_new (void);
+void gtk_offscreen_box_add1 (GtkOffscreenBox *offscreen,
+ GtkWidget *child);
+void gtk_offscreen_box_add2 (GtkOffscreenBox *offscreen,
+ GtkWidget *child);
+void gtk_offscreen_box_set_angle (GtkOffscreenBox *offscreen,
+ double angle);
+
+
+
+G_END_DECLS
+
+#endif /* __GTK_OFFSCREEN_BOX_H__ */
-/* testclientmessage.c\r
- * Copyright (C) 2008 Novell, Inc.\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Library General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- * Library General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Library General Public\r
- * License along with this library; if not, write to the\r
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,\r
- * Boston, MA 02111-1307, USA.\r
- */\r
-\r
-#include <gtk/gtk.h>\r
-\r
-static GdkAtom my_type;\r
-static GdkAtom random_type;\r
-\r
-static void\r
-send_known (void)\r
-{\r
- GdkEvent *event = gdk_event_new (GDK_CLIENT_EVENT);\r
- static int counter = 42;\r
- int i;\r
- \r
- event->client.window = NULL;\r
- event->client.message_type = my_type;\r
- event->client.data_format = 32;\r
- event->client.data.l[0] = counter++;\r
- for (i = 1; i < 5; i++)\r
- event->client.data.l[i] = 0;\r
-\r
- gdk_screen_broadcast_client_message (gdk_display_get_default_screen (gdk_display_get_default ()), event);\r
- \r
- gdk_event_free (event);\r
-}\r
-\r
-void\r
-send_random (void)\r
-{\r
- GdkEvent *event = gdk_event_new (GDK_CLIENT_EVENT);\r
- static int counter = 1;\r
- int i;\r
- \r
- event->client.window = NULL;\r
- event->client.message_type = random_type;\r
- event->client.data_format = 32;\r
- event->client.data.l[0] = counter++;\r
- for (i = 1; i < 5; i++)\r
- event->client.data.l[i] = 0;\r
-\r
- gdk_screen_broadcast_client_message (gdk_display_get_default_screen (gdk_display_get_default ()), event);\r
- \r
- gdk_event_free (event);\r
-}\r
-\r
-static GdkFilterReturn\r
-filter_func (GdkXEvent *xevent,\r
- GdkEvent *event,\r
- gpointer data)\r
-{\r
- g_print ("Got matching client message!\n");\r
- return GDK_FILTER_REMOVE;\r
-}\r
-\r
-int\r
-main (int argc, char **argv)\r
-{\r
- GtkWidget *window;\r
- GtkWidget *vbox;\r
- GtkWidget *button;\r
-\r
- gtk_init (&argc, &argv);\r
-\r
- my_type = gdk_atom_intern ("GtkTestClientMessage", FALSE);\r
- random_type = gdk_atom_intern (g_strdup_printf ("GtkTestClientMessage-%d",\r
- g_rand_int_range (g_rand_new (), 1, 99)),\r
- FALSE);\r
-\r
- g_print ("using random client message type %s\n", gdk_atom_name (random_type));\r
-\r
- window = g_object_connect (g_object_new (gtk_window_get_type (),\r
- "type", GTK_WINDOW_TOPLEVEL,\r
- "title", "testclientmessage",\r
- "border_width", 10,\r
- NULL),\r
- "signal::destroy", gtk_main_quit, NULL,\r
- NULL);\r
- vbox = g_object_new (gtk_vbox_get_type (),\r
- "GtkWidget::parent", window,\r
- "GtkWidget::visible", TRUE,\r
- NULL);\r
- button = g_object_connect (g_object_new (gtk_button_get_type (),\r
- "GtkButton::label", "send known client message",\r
- "GtkWidget::parent", vbox,\r
- "GtkWidget::visible", TRUE,\r
- NULL),\r
- "signal::clicked", send_known, NULL,\r
- NULL);\r
- button = g_object_connect (g_object_new (gtk_button_get_type (),\r
- "GtkButton::label", "send random client message",\r
- "GtkWidget::parent", vbox,\r
- "GtkWidget::visible", TRUE,\r
- NULL),\r
- "signal::clicked", send_random, NULL,\r
- NULL);\r
- gdk_display_add_client_message_filter (gdk_display_get_default (),\r
- my_type,\r
- filter_func,\r
- NULL);\r
- gtk_widget_show (window);\r
-\r
- gtk_main ();\r
-\r
- return 0;\r
-}\r
+/* testclientmessage.c
+ * Copyright (C) 2008 Novell, Inc.
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gtk/gtk.h>
+
+static GdkAtom my_type;
+static GdkAtom random_type;
+
+static void
+send_known (void)
+{
+ GdkEvent *event = gdk_event_new (GDK_CLIENT_EVENT);
+ static int counter = 42;
+ int i;
+
+ event->client.window = NULL;
+ event->client.message_type = my_type;
+ event->client.data_format = 32;
+ event->client.data.l[0] = counter++;
+ for (i = 1; i < 5; i++)
+ event->client.data.l[i] = 0;
+
+ gdk_screen_broadcast_client_message (gdk_display_get_default_screen (gdk_display_get_default ()), event);
+
+ gdk_event_free (event);
+}
+
+void
+send_random (void)
+{
+ GdkEvent *event = gdk_event_new (GDK_CLIENT_EVENT);
+ static int counter = 1;
+ int i;
+
+ event->client.window = NULL;
+ event->client.message_type = random_type;
+ event->client.data_format = 32;
+ event->client.data.l[0] = counter++;
+ for (i = 1; i < 5; i++)
+ event->client.data.l[i] = 0;
+
+ gdk_screen_broadcast_client_message (gdk_display_get_default_screen (gdk_display_get_default ()), event);
+
+ gdk_event_free (event);
+}
+
+static GdkFilterReturn
+filter_func (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data)
+{
+ g_print ("Got matching client message!\n");
+ return GDK_FILTER_REMOVE;
+}
+
+int
+main (int argc, char **argv)
+{
+ GtkWidget *window;
+ GtkWidget *vbox;
+ GtkWidget *button;
+
+ gtk_init (&argc, &argv);
+
+ my_type = gdk_atom_intern ("GtkTestClientMessage", FALSE);
+ random_type = gdk_atom_intern (g_strdup_printf ("GtkTestClientMessage-%d",
+ g_rand_int_range (g_rand_new (), 1, 99)),
+ FALSE);
+
+ g_print ("using random client message type %s\n", gdk_atom_name (random_type));
+
+ window = g_object_connect (g_object_new (gtk_window_get_type (),
+ "type", GTK_WINDOW_TOPLEVEL,
+ "title", "testclientmessage",
+ "border_width", 10,
+ NULL),
+ "signal::destroy", gtk_main_quit, NULL,
+ NULL);
+ vbox = g_object_new (gtk_vbox_get_type (),
+ "GtkWidget::parent", window,
+ "GtkWidget::visible", TRUE,
+ NULL);
+ button = g_object_connect (g_object_new (gtk_button_get_type (),
+ "GtkButton::label", "send known client message",
+ "GtkWidget::parent", vbox,
+ "GtkWidget::visible", TRUE,
+ NULL),
+ "signal::clicked", send_known, NULL,
+ NULL);
+ button = g_object_connect (g_object_new (gtk_button_get_type (),
+ "GtkButton::label", "send random client message",
+ "GtkWidget::parent", vbox,
+ "GtkWidget::visible", TRUE,
+ NULL),
+ "signal::clicked", send_random, NULL,
+ NULL);
+ gdk_display_add_client_message_filter (gdk_display_get_default (),
+ my_type,
+ filter_func,
+ NULL);
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return 0;
+}
--- /dev/null
+/*
+ * testoffscreen.c
+ */
+
+#undef GTK_DISABLE_DEPRECATED
+
+#include <math.h>
+#include <gtk/gtk.h>
+#include "gtkoffscreenbox.h"
+
+
+static void
+combo_changed_cb (GtkWidget *combo,
+ gpointer data)
+{
+ GtkWidget *label = GTK_WIDGET (data);
+ gint active;
+
+ active = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+
+ gtk_label_set_ellipsize (GTK_LABEL (label), (PangoEllipsizeMode)active);
+}
+
+static gboolean
+layout_expose_handler (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkLayout *layout = GTK_LAYOUT (widget);
+
+ gint i,j;
+ gint imin, imax, jmin, jmax;
+
+ if (event->window != layout->bin_window)
+ return FALSE;
+
+ imin = (event->area.x) / 10;
+ imax = (event->area.x + event->area.width + 9) / 10;
+
+ jmin = (event->area.y) / 10;
+ jmax = (event->area.y + event->area.height + 9) / 10;
+
+ for (i = imin; i < imax; i++)
+ for (j = jmin; j < jmax; j++)
+ if ((i + j) % 2)
+ gdk_draw_rectangle (layout->bin_window,
+ widget->style->black_gc,
+ TRUE,
+ 10 * i, 10 * j,
+ 1 + i % 10, 1 + j % 10);
+
+ return FALSE;
+}
+
+static gboolean
+scroll_layout (gpointer data)
+{
+ GtkWidget *layout = data;
+ GtkAdjustment *adj;
+
+ adj = gtk_layout_get_hadjustment (GTK_LAYOUT (layout));
+ gtk_adjustment_set_value (adj,
+ gtk_adjustment_get_value (adj) + 5.0);
+ return TRUE;
+}
+
+static guint layout_timeout;
+
+static void
+create_layout (GtkWidget *vbox)
+{
+ GtkWidget *layout;
+ GtkWidget *scrolledwindow;
+ GtkWidget *button;
+ gchar buf[16];
+ gint i, j;
+
+ scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
+ GTK_SHADOW_IN);
+ gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
+ GTK_CORNER_TOP_RIGHT);
+
+ gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow, TRUE, TRUE, 0);
+
+ layout = gtk_layout_new (NULL, NULL);
+ gtk_container_add (GTK_CONTAINER (scrolledwindow), layout);
+
+ /* We set step sizes here since GtkLayout does not set
+ * them itself.
+ */
+ GTK_LAYOUT (layout)->hadjustment->step_increment = 10.0;
+ GTK_LAYOUT (layout)->vadjustment->step_increment = 10.0;
+
+ gtk_widget_set_events (layout, GDK_EXPOSURE_MASK);
+ g_signal_connect (layout, "expose_event",
+ G_CALLBACK (layout_expose_handler),
+ NULL);
+
+ gtk_layout_set_size (GTK_LAYOUT (layout), 1600, 128000);
+
+ for (i = 0 ; i < 16 ; i++)
+ for (j = 0 ; j < 16 ; j++)
+ {
+ g_snprintf (buf, sizeof (buf), "Button %d, %d", i, j);
+
+ if ((i + j) % 2)
+ button = gtk_button_new_with_label (buf);
+ else
+ button = gtk_label_new (buf);
+
+ gtk_layout_put (GTK_LAYOUT (layout), button,
+ j * 100, i * 100);
+ }
+
+ for (i = 16; i < 1280; i++)
+ {
+ g_snprintf (buf, sizeof (buf), "Button %d, %d", i, 0);
+
+ if (i % 2)
+ button = gtk_button_new_with_label (buf);
+ else
+ button = gtk_label_new (buf);
+
+ gtk_layout_put (GTK_LAYOUT (layout), button,
+ 0, i * 100);
+ }
+
+ layout_timeout = g_timeout_add (1000, scroll_layout, layout);
+}
+
+static void
+create_treeview (GtkWidget *vbox)
+{
+ GtkWidget *scrolledwindow;
+ GtkListStore *store;
+ GtkWidget *tree_view;
+ GSList *stock_ids;
+ GSList *list;
+
+ scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
+ GTK_SHADOW_IN);
+
+ gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow, TRUE, TRUE, 0);
+
+ store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+ tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+ g_object_unref (store);
+
+ gtk_container_add (GTK_CONTAINER (scrolledwindow), tree_view);
+
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view), -1,
+ "Icon",
+ gtk_cell_renderer_pixbuf_new (),
+ "stock-id", 0,
+ NULL);
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view), -1,
+ "Label",
+ gtk_cell_renderer_text_new (),
+ "text", 1,
+ NULL);
+
+ stock_ids = gtk_stock_list_ids ();
+
+ for (list = stock_ids; list; list = g_slist_next (list))
+ {
+ const gchar *stock_id = list->data;
+ GtkStockItem item;
+
+ if (gtk_stock_lookup (stock_id, &item))
+ {
+ gtk_list_store_insert_with_values (store, NULL, -1,
+ 0, item.stock_id,
+ 1, item.label,
+ -1);
+ }
+ }
+
+ g_slist_foreach (stock_ids, (GFunc) g_free, NULL);
+ g_slist_free (stock_ids);
+}
+
+static GtkWidget *
+create_widgets (void)
+{
+ GtkWidget *main_hbox, *main_vbox;
+ GtkWidget *vbox, *hbox, *label, *combo, *entry, *button, *cb;
+ GtkWidget *sw, *text_view;
+ GList *cbitems = NULL;
+
+ main_vbox = gtk_vbox_new (0, FALSE);
+
+ main_hbox = gtk_hbox_new (0, FALSE);
+ gtk_box_pack_start (GTK_BOX (main_vbox), main_hbox, TRUE, TRUE, 0);
+
+ vbox = gtk_vbox_new (0, FALSE);
+ gtk_box_pack_start (GTK_BOX (main_hbox), vbox, TRUE, TRUE, 0);
+
+ hbox = gtk_hbox_new (0, FALSE);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+ label = gtk_label_new ("This label may be ellipsized\nto make it fit.");
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+
+ combo = gtk_combo_box_new_text ();
+ gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "NONE");
+ gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "START");
+ gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "MIDDLE");
+ gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "END");
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
+ gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
+
+ g_signal_connect (combo, "changed",
+ G_CALLBACK (combo_changed_cb),
+ label);
+
+ entry = gtk_entry_new ();
+ gtk_entry_set_text (GTK_ENTRY (entry), "an entry - lots of text.... lots of text.... lots of text.... lots of text.... ");
+ gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
+
+ label = gtk_label_new ("Label after entry.");
+ gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+ gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
+
+ button = gtk_button_new_with_label ("Button");
+ gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
+
+ button = gtk_check_button_new_with_mnemonic ("_Check button");
+ gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+ cb = gtk_combo_new ();
+ cbitems = g_list_append (cbitems, "item0");
+ cbitems = g_list_append (cbitems, "item1 item1");
+ cbitems = g_list_append (cbitems, "item2 item2 item2");
+ gtk_combo_set_popdown_strings (GTK_COMBO (cb), cbitems);
+ gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (cb)->entry), "hello world ♥ foo");
+ gtk_editable_select_region (GTK_EDITABLE (GTK_COMBO (cb)->entry),
+ 0, -1);
+ gtk_box_pack_start (GTK_BOX (vbox), cb, TRUE, TRUE, 0);
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ text_view = gtk_text_view_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
+ gtk_container_add (GTK_CONTAINER (sw), text_view);
+
+ create_layout (vbox);
+
+ create_treeview (main_hbox);
+
+ return main_vbox;
+}
+
+
+static void
+scale_changed (GtkRange *range,
+ GtkOffscreenBox *offscreen_box)
+{
+ gtk_offscreen_box_set_angle (offscreen_box, gtk_range_get_value (range));
+}
+
+static GtkWidget *scale = NULL;
+
+static void
+remove_clicked (GtkButton *button,
+ GtkWidget *widget)
+{
+ gtk_widget_destroy (widget);
+ g_source_remove (layout_timeout);
+
+ gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
+ gtk_widget_set_sensitive (scale, FALSE);
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ GtkWidget *window, *widget, *vbox, *button;
+ GtkWidget *offscreen = NULL;
+ gboolean use_offscreen;
+
+ gtk_init (&argc, &argv);
+
+ use_offscreen = argc == 1;
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size (GTK_WINDOW (window), 300,300);
+
+ g_signal_connect (window, "destroy",
+ G_CALLBACK (gtk_main_quit),
+ NULL);
+
+ vbox = gtk_vbox_new (0, FALSE);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+
+ scale = gtk_hscale_new_with_range (0,
+ M_PI * 2,
+ 0.01);
+ gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
+
+ button = gtk_button_new_with_label ("Remove child 2");
+ gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+ if (use_offscreen)
+ {
+ offscreen = gtk_offscreen_box_new ();
+
+ g_signal_connect (scale, "value_changed",
+ G_CALLBACK (scale_changed),
+ offscreen);
+ }
+ else
+ {
+ offscreen = gtk_vpaned_new ();
+ }
+
+ gtk_box_pack_start (GTK_BOX (vbox), offscreen, TRUE, TRUE, 0);
+
+ widget = create_widgets ();
+ if (use_offscreen)
+ gtk_offscreen_box_add1 (GTK_OFFSCREEN_BOX (offscreen),
+ widget);
+ else
+ gtk_paned_add1 (GTK_PANED (offscreen), widget);
+
+ widget = create_widgets ();
+ if (1)
+ {
+ GtkWidget *widget2, *box2, *offscreen2;
+
+ offscreen2 = gtk_offscreen_box_new ();
+ gtk_box_pack_start (GTK_BOX (widget), offscreen2, FALSE, FALSE, 0);
+
+ g_signal_connect (scale, "value_changed",
+ G_CALLBACK (scale_changed),
+ offscreen2);
+
+ box2 = gtk_vbox_new (FALSE, 0);
+ gtk_offscreen_box_add2 (GTK_OFFSCREEN_BOX (offscreen2), box2);
+
+ widget2 = gtk_button_new_with_label ("Offscreen in offscreen");
+ gtk_box_pack_start (GTK_BOX (box2), widget2, FALSE, FALSE, 0);
+
+ widget2 = gtk_entry_new ();
+ gtk_entry_set_text (GTK_ENTRY (widget2), "Offscreen in offscreen");
+ gtk_box_pack_start (GTK_BOX (box2), widget2, FALSE, FALSE, 0);
+ }
+
+ if (use_offscreen)
+ gtk_offscreen_box_add2 (GTK_OFFSCREEN_BOX (offscreen), widget);
+ else
+ gtk_paned_add2 (GTK_PANED (offscreen), widget);
+
+ gtk_widget_show_all (window);
+
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (remove_clicked),
+ widget);
+
+ /* redirect */
+ if (0)
+ {
+ GtkWidget *redirect_win;
+
+ redirect_win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size (GTK_WINDOW (redirect_win), 400,400);
+ gtk_widget_show (redirect_win);
+ gtk_widget_realize (redirect_win);
+ gtk_widget_realize (window);
+ gdk_window_redirect_to_drawable (window->window,
+ GDK_DRAWABLE (redirect_win->window),
+ 0, 0, 0, 0, -1, -1);
+ }
+
+ gtk_main ();
+
+ return 0;
+}
--- /dev/null
+#include <gtk/gtk.h>
+#include <X11/Xlib.h>
+
+static GtkWidget *darea;
+static GtkTreeStore *window_store = NULL;
+static GtkWidget *treeview;
+
+static void update_store (void);
+
+static GtkWidget *main_window;
+
+static gboolean
+window_has_impl (GdkWindow *window)
+{
+ GdkWindowObject *w;
+ w = (GdkWindowObject *)window;
+ return w->parent == NULL || w->parent->impl != w->impl;
+}
+
+GdkWindow *
+create_window (GdkWindow *parent,
+ int x, int y, int w, int h,
+ GdkColor *color)
+{
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ GdkWindow *window;
+ GdkColor *bg;
+
+ attributes.x = x;
+ attributes.y = y;
+ attributes.width = w;
+ attributes.height = h;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.event_mask = GDK_STRUCTURE_MASK
+ | GDK_BUTTON_MOTION_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK
+ | GDK_EXPOSURE_MASK
+ | GDK_ENTER_NOTIFY_MASK
+ | GDK_LEAVE_NOTIFY_MASK;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y;
+
+ window = gdk_window_new (parent, &attributes, attributes_mask);
+ gdk_window_set_user_data (window, darea);
+
+ bg = g_new (GdkColor, 1);
+ if (color)
+ *bg = *color;
+ else
+ {
+ bg->red = g_random_int_range (0, 0xffff);
+ bg->blue = g_random_int_range (0, 0xffff);
+ bg->green = g_random_int_range (0, 0xffff);;
+ }
+
+ gdk_rgb_find_color (gtk_widget_get_colormap (darea), bg);
+ gdk_window_set_background (window, bg);
+ g_object_set_data_full (G_OBJECT (window), "color", bg, g_free);
+
+ gdk_window_show (window);
+
+ return window;
+}
+
+static void
+add_window_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ GList **selected = data;
+ GdkWindow *window;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (window_store),
+ iter,
+ 0, &window,
+ -1);
+
+ *selected = g_list_prepend (*selected, window);
+}
+
+static GList *
+get_selected_windows (void)
+{
+ GtkTreeSelection *sel;
+ GList *selected;
+
+ sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+ selected = NULL;
+ gtk_tree_selection_selected_foreach (sel, add_window_cb, &selected);
+
+ return selected;
+}
+
+static gboolean
+find_window_helper (GtkTreeModel *model,
+ GdkWindow *window,
+ GtkTreeIter *iter,
+ GtkTreeIter *selected_iter)
+{
+ GtkTreeIter child_iter;
+ GdkWindow *w;
+
+ do
+ {
+ gtk_tree_model_get (model, iter,
+ 0, &w,
+ -1);
+ if (w == window)
+ {
+ *selected_iter = *iter;
+ return TRUE;
+ }
+
+ if (gtk_tree_model_iter_children (model,
+ &child_iter,
+ iter))
+ {
+ if (find_window_helper (model, window, &child_iter, selected_iter))
+ return TRUE;
+ }
+ } while (gtk_tree_model_iter_next (model, iter));
+
+ return FALSE;
+}
+
+static gboolean
+find_window (GdkWindow *window,
+ GtkTreeIter *window_iter)
+{
+ GtkTreeIter iter;
+
+ if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (window_store), &iter))
+ return FALSE;
+
+ return find_window_helper (GTK_TREE_MODEL (window_store),
+ window,
+ &iter,
+ window_iter);
+}
+
+static void
+toggle_selection_window (GdkWindow *window)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+ if (window != NULL &&
+ find_window (window, &iter))
+ {
+ if (gtk_tree_selection_iter_is_selected (selection, &iter))
+ gtk_tree_selection_unselect_iter (selection, &iter);
+ else
+ gtk_tree_selection_select_iter (selection, &iter);
+ }
+}
+
+static void
+unselect_windows (void)
+{
+ GtkTreeSelection *selection;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+ gtk_tree_selection_unselect_all (selection);
+}
+
+
+static void
+select_window (GdkWindow *window)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+ if (window != NULL &&
+ find_window (window, &iter))
+ gtk_tree_selection_select_iter (selection, &iter);
+}
+
+static void
+select_windows (GList *windows)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ GList *l;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+ gtk_tree_selection_unselect_all (selection);
+
+ for (l = windows; l != NULL; l = l->next)
+ {
+ if (find_window (l->data, &iter))
+ gtk_tree_selection_select_iter (selection, &iter);
+ }
+}
+
+static void
+add_window_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GdkWindow *parent;
+ GList *l;
+
+ l = get_selected_windows ();
+ if (l != NULL)
+ parent = l->data;
+ else
+ parent = darea->window;
+
+ g_list_free (l);
+
+ create_window (parent, 10, 10, 100, 100, NULL);
+ update_store ();
+}
+
+static void
+draw_drawable_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GdkGC *gc;
+ gc = gdk_gc_new (darea->window);
+ gdk_draw_drawable (darea->window,
+ gc,
+ darea->window,
+ -15, -15,
+ 40, 70,
+ 100, 100);
+ g_object_unref (gc);
+}
+
+
+static void
+remove_window_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GList *l, *selected;
+
+ selected = get_selected_windows ();
+
+ for (l = selected; l != NULL; l = l->next)
+ gdk_window_destroy (l->data);
+
+ g_list_free (selected);
+
+ update_store ();
+}
+
+static void save_children (GString *s, GdkWindow *window);
+
+static void
+save_window (GString *s,
+ GdkWindow *window)
+{
+ gint x, y, w, h;
+ GdkColor *color;
+
+ gdk_window_get_position (window, &x, &y);
+ gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+ color = g_object_get_data (G_OBJECT (window), "color");
+
+ g_string_append_printf (s, "%d,%d %dx%d (%d,%d,%d) %d %d\n",
+ x, y, w, h,
+ color->red, color->green, color->blue,
+ window_has_impl (window),
+ g_list_length (gdk_window_peek_children (window)));
+
+ save_children (s, window);
+}
+
+
+static void
+save_children (GString *s,
+ GdkWindow *window)
+{
+ GList *l;
+ GdkWindow *child;
+
+ for (l = g_list_reverse (gdk_window_peek_children (window));
+ l != NULL;
+ l = l->next)
+ {
+ child = l->data;
+
+ save_window (s, child);
+ }
+}
+
+
+static void
+save_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GString *s;
+ GtkWidget *dialog;
+ GFile *file;
+
+ s = g_string_new ("");
+
+ save_children (s, darea->window);
+
+ dialog = gtk_file_chooser_dialog_new ("Filename for window data",
+ NULL,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ {
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+
+ g_file_replace_contents (file,
+ s->str, s->len,
+ NULL, FALSE,
+ 0, NULL, NULL, NULL);
+
+ g_object_unref (file);
+ }
+
+ gtk_widget_destroy (dialog);
+ g_string_free (s, TRUE);
+}
+
+static void
+destroy_children (GdkWindow *window)
+{
+ GList *l;
+ GdkWindow *child;
+
+ for (l = gdk_window_peek_children (window);
+ l != NULL;
+ l = l->next)
+ {
+ child = l->data;
+
+ destroy_children (child);
+ gdk_window_destroy (child);
+ }
+}
+
+static char **
+parse_window (GdkWindow *parent, char **lines)
+{
+ int x, y, w, h, r, g, b, native, n_children;
+ GdkWindow *window;
+ GdkColor color;
+ int i;
+
+ if (*lines == NULL)
+ return lines;
+
+ if (sscanf(*lines, "%d,%d %dx%d (%d,%d,%d) %d %d",
+ &x, &y, &w, &h, &r, &g, &b, &native, &n_children) == 9)
+ {
+ lines++;
+ color.red = r;
+ color.green = g;
+ color.blue = b;
+ window = create_window (parent, x, y, w, h, &color);
+ if (native)
+ gdk_window_ensure_native (window);
+
+ for (i = 0; i < n_children; i++)
+ lines = parse_window (window, lines);
+ }
+ else
+ lines++;
+
+ return lines;
+}
+
+static void
+load_file (GFile *file)
+{
+ char *data;
+ char **lines, **l;
+
+ if (g_file_load_contents (file, NULL, &data, NULL, NULL, NULL))
+ {
+ destroy_children (darea->window);
+
+ lines = g_strsplit (data, "\n", -1);
+
+ l = lines;
+ while (*l != NULL)
+ l = parse_window (darea->window, l);
+ }
+
+ update_store ();
+}
+
+static void
+move_window_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GdkWindow *window;
+ GtkDirectionType direction;
+ GList *selected, *l;
+ gint x, y;
+
+ direction = GPOINTER_TO_INT (data);
+
+ selected = get_selected_windows ();
+
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
+
+ gdk_window_get_position (window, &x, &y);
+
+ switch (direction) {
+ case GTK_DIR_UP:
+ y -= 10;
+ break;
+ case GTK_DIR_DOWN:
+ y += 10;
+ break;
+ case GTK_DIR_LEFT:
+ x -= 10;
+ break;
+ case GTK_DIR_RIGHT:
+ x += 10;
+ break;
+ default:
+ break;
+ }
+
+ gdk_window_move (window, x, y);
+ }
+
+ g_list_free (selected);
+}
+
+static void
+manual_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GdkWindow *window;
+ GList *selected, *l;
+ int x, y, w, h;
+ GtkWidget *dialog, *table, *label, *xspin, *yspin, *wspin, *hspin;
+
+
+ selected = get_selected_windows ();
+
+ if (selected == NULL)
+ return;
+
+ gdk_window_get_position (selected->data, &x, &y);
+ gdk_drawable_get_size (selected->data, &w, &h);
+
+ dialog = gtk_dialog_new_with_buttons ("Select new position and size",
+ GTK_WINDOW (main_window),
+ GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+
+
+ table = gtk_table_new (2, 4, TRUE);
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+ table,
+ FALSE, FALSE,
+ 2);
+
+
+ label = gtk_label_new ("x:");
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ label,
+ 0, 1,
+ 0, 1);
+ label = gtk_label_new ("y:");
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ label,
+ 0, 1,
+ 1, 2);
+ label = gtk_label_new ("width:");
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ label,
+ 0, 1,
+ 2, 3);
+ label = gtk_label_new ("height:");
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ label,
+ 0, 1,
+ 3, 4);
+
+ xspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (xspin), x);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ xspin,
+ 1, 2,
+ 0, 1);
+ yspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (yspin), y);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ yspin,
+ 1, 2,
+ 1, 2);
+ wspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (wspin), w);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ wspin,
+ 1, 2,
+ 2, 3);
+ hspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (hspin), h);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ hspin,
+ 1, 2,
+ 3, 4);
+
+ gtk_widget_show_all (dialog);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+
+ x = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (xspin));
+ y = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (yspin));
+ w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (wspin));
+ h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (hspin));
+
+ gtk_widget_destroy (dialog);
+
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
+
+ gdk_window_move_resize (window, x, y, w, h);
+ }
+
+ g_list_free (selected);
+}
+
+static void
+scroll_window_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GdkWindow *window;
+ GtkDirectionType direction;
+ GList *selected, *l;
+ gint dx, dy;
+
+ direction = GPOINTER_TO_INT (data);
+
+ selected = get_selected_windows ();
+
+ dx = 0; dy = 0;
+ switch (direction) {
+ case GTK_DIR_UP:
+ dy = 10;
+ break;
+ case GTK_DIR_DOWN:
+ dy = -10;
+ break;
+ case GTK_DIR_LEFT:
+ dx = 10;
+ break;
+ case GTK_DIR_RIGHT:
+ dx = -10;
+ break;
+ default:
+ break;
+ }
+
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
+
+ gdk_window_scroll (window, dx, dy);
+ }
+
+ g_list_free (selected);
+}
+
+
+static void
+raise_window_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GList *selected, *l;
+ GdkWindow *window;
+
+ selected = get_selected_windows ();
+
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
+
+ gdk_window_raise (window);
+ }
+
+ g_list_free (selected);
+
+ update_store ();
+}
+
+static void
+lower_window_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GList *selected, *l;
+ GdkWindow *window;
+
+ selected = get_selected_windows ();
+
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
+
+ gdk_window_lower (window);
+ }
+
+ g_list_free (selected);
+
+ update_store ();
+}
+
+
+static void
+smaller_window_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GList *selected, *l;
+ GdkWindow *window;
+ int w, h;
+
+ selected = get_selected_windows ();
+
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
+
+ gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+
+ w -= 10;
+ h -= 10;
+ if (w < 1)
+ w = 1;
+ if (h < 1)
+ h = 1;
+
+ gdk_window_resize (window, w, h);
+ }
+
+ g_list_free (selected);
+}
+
+static void
+larger_window_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GList *selected, *l;
+ GdkWindow *window;
+ int w, h;
+
+ selected = get_selected_windows ();
+
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
+
+ gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+
+ w += 10;
+ h += 10;
+
+ gdk_window_resize (window, w, h);
+ }
+
+ g_list_free (selected);
+}
+
+static void
+native_window_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GList *selected, *l;
+ GdkWindow *window;
+
+ selected = get_selected_windows ();
+
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
+
+ gdk_window_ensure_native (window);
+ }
+
+ g_list_free (selected);
+
+ update_store ();
+}
+
+static gboolean
+darea_button_release_event (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ if ((event->state & GDK_CONTROL_MASK) != 0)
+ {
+ toggle_selection_window (event->window);
+ }
+ else
+ {
+ unselect_windows ();
+ select_window (event->window);
+ }
+
+ return TRUE;
+}
+
+static void
+render_window_cell (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ GdkWindow *window;
+ char *name;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (window_store),
+ iter,
+ 0, &window,
+ -1);
+
+ if (window_has_impl (window))
+ name = g_strdup_printf ("%p (native)", window);
+ else
+ name = g_strdup_printf ("%p", window);
+ g_object_set (cell,
+ "text", name,
+ "background-gdk", &((GdkWindowObject *)window)->bg_color,
+ NULL);
+}
+
+static void
+add_children (GtkTreeStore *store,
+ GdkWindow *window,
+ GtkTreeIter *window_iter)
+{
+ GList *l;
+ GtkTreeIter child_iter;
+
+ for (l = gdk_window_peek_children (window);
+ l != NULL;
+ l = l->next)
+ {
+ gtk_tree_store_append (store, &child_iter, window_iter);
+ gtk_tree_store_set (store, &child_iter,
+ 0, l->data,
+ -1);
+
+ add_children (store, l->data, &child_iter);
+ }
+}
+
+static void
+update_store (void)
+{
+ GList *selected;
+
+ selected = get_selected_windows ();
+
+ gtk_tree_store_clear (window_store);
+
+ add_children (window_store, darea->window, NULL);
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (treeview));
+
+ select_windows (selected);
+ g_list_free (selected);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ GtkWidget *window, *vbox, *hbox, *frame;
+ GtkWidget *button, *scrolled, *table;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ GdkColor black = {0};
+ GFile *file;
+
+ gtk_init (&argc, &argv);
+
+ main_window = window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_container_set_border_width (GTK_CONTAINER (window), 0);
+
+ g_signal_connect (G_OBJECT (window), "delete-event", gtk_main_quit, NULL);
+
+ hbox = gtk_hbox_new (FALSE, 5);
+ gtk_container_add (GTK_CONTAINER (window), hbox);
+ gtk_widget_show (hbox);
+
+ frame = gtk_frame_new ("GdkWindows");
+ gtk_box_pack_start (GTK_BOX (hbox),
+ frame,
+ FALSE, FALSE,
+ 5);
+ gtk_widget_show (frame);
+
+ darea = gtk_drawing_area_new ();
+ /*gtk_widget_set_double_buffered (darea, FALSE);*/
+ gtk_widget_add_events (darea, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
+ gtk_widget_set_size_request (darea, 500, 500);
+ g_signal_connect (darea, "button_release_event",
+ G_CALLBACK (darea_button_release_event),
+ NULL);
+
+
+ gtk_container_add (GTK_CONTAINER (frame), darea);
+ gtk_widget_realize (darea);
+ gtk_widget_show (darea);
+ gtk_widget_modify_bg (darea, GTK_STATE_NORMAL,
+ &black);
+
+
+ vbox = gtk_vbox_new (FALSE, 5);
+ gtk_box_pack_start (GTK_BOX (hbox),
+ vbox,
+ FALSE, FALSE,
+ 5);
+ gtk_widget_show (vbox);
+
+ window_store = gtk_tree_store_new (1, GDK_TYPE_WINDOW);
+
+ treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (window_store));
+ gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
+ GTK_SELECTION_MULTIPLE);
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_title (column, "Window");
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_set_cell_data_func (column,
+ renderer,
+ render_window_cell,
+ NULL, NULL);
+
+ gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+
+ scrolled = gtk_scrolled_window_new (NULL, NULL);
+ gtk_widget_set_size_request (scrolled, 200, 400);
+ gtk_container_add (GTK_CONTAINER (scrolled), treeview);
+ gtk_box_pack_start (GTK_BOX (vbox),
+ scrolled,
+ FALSE, FALSE,
+ 5);
+ gtk_widget_show (scrolled);
+ gtk_widget_show (treeview);
+
+ table = gtk_table_new (4, 4, TRUE);
+ gtk_box_pack_start (GTK_BOX (vbox),
+ table,
+ FALSE, FALSE,
+ 2);
+ gtk_widget_show (table);
+
+ button = gtk_button_new ();
+ gtk_button_set_image (GTK_BUTTON (button),
+ gtk_image_new_from_stock (GTK_STOCK_GO_BACK,
+ GTK_ICON_SIZE_BUTTON));
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (move_window_clicked),
+ GINT_TO_POINTER (GTK_DIR_LEFT));
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 0, 1,
+ 1, 2);
+ gtk_widget_show (button);
+
+ button = gtk_button_new ();
+ gtk_button_set_image (GTK_BUTTON (button),
+ gtk_image_new_from_stock (GTK_STOCK_GO_UP,
+ GTK_ICON_SIZE_BUTTON));
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (move_window_clicked),
+ GINT_TO_POINTER (GTK_DIR_UP));
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 1, 2,
+ 0, 1);
+ gtk_widget_show (button);
+
+ button = gtk_button_new ();
+ gtk_button_set_image (GTK_BUTTON (button),
+ gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,
+ GTK_ICON_SIZE_BUTTON));
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (move_window_clicked),
+ GINT_TO_POINTER (GTK_DIR_RIGHT));
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 2, 3,
+ 1, 2);
+ gtk_widget_show (button);
+
+ button = gtk_button_new ();
+ gtk_button_set_image (GTK_BUTTON (button),
+ gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
+ GTK_ICON_SIZE_BUTTON));
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (move_window_clicked),
+ GINT_TO_POINTER (GTK_DIR_DOWN));
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 1, 2,
+ 2, 3);
+ gtk_widget_show (button);
+
+
+ button = gtk_button_new_with_label ("Raise");
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (raise_window_clicked),
+ NULL);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 0, 1,
+ 0, 1);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Lower");
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (lower_window_clicked),
+ NULL);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 0, 1,
+ 2, 3);
+ gtk_widget_show (button);
+
+
+ button = gtk_button_new_with_label ("Smaller");
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (smaller_window_clicked),
+ NULL);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 2, 3,
+ 0, 1);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Larger");
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (larger_window_clicked),
+ NULL);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 2, 3,
+ 2, 3);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Native");
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (native_window_clicked),
+ NULL);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 1, 2,
+ 1, 2);
+ gtk_widget_show (button);
+
+
+ button = gtk_button_new_with_label ("scroll");
+ gtk_button_set_image (GTK_BUTTON (button),
+ gtk_image_new_from_stock (GTK_STOCK_GO_UP,
+ GTK_ICON_SIZE_BUTTON));
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (scroll_window_clicked),
+ GINT_TO_POINTER (GTK_DIR_UP));
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 3, 4,
+ 0, 1);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("scroll");
+ gtk_button_set_image (GTK_BUTTON (button),
+ gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
+ GTK_ICON_SIZE_BUTTON));
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (scroll_window_clicked),
+ GINT_TO_POINTER (GTK_DIR_DOWN));
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 3, 4,
+ 1, 2);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Manual");
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (manual_clicked),
+ NULL);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 3, 4,
+ 2, 3);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("draw drawable");
+ gtk_box_pack_start (GTK_BOX (vbox),
+ button,
+ FALSE, FALSE,
+ 2);
+ gtk_widget_show (button);
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (draw_drawable_clicked),
+ NULL);
+
+ button = gtk_button_new_with_label ("Add window");
+ gtk_box_pack_start (GTK_BOX (vbox),
+ button,
+ FALSE, FALSE,
+ 2);
+ gtk_widget_show (button);
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (add_window_clicked),
+ NULL);
+
+ button = gtk_button_new_with_label ("Remove window");
+ gtk_box_pack_start (GTK_BOX (vbox),
+ button,
+ FALSE, FALSE,
+ 2);
+ gtk_widget_show (button);
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (remove_window_clicked),
+ NULL);
+
+ button = gtk_button_new_with_label ("Save");
+ gtk_box_pack_start (GTK_BOX (vbox),
+ button,
+ FALSE, FALSE,
+ 2);
+ gtk_widget_show (button);
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (save_clicked),
+ NULL);
+
+ gtk_widget_show (window);
+
+ if (argc == 2)
+ {
+ file = g_file_new_for_commandline_arg (argv[1]);
+ load_file (file);
+ g_object_unref (file);
+ }
+
+ gtk_main ();
+
+ return 0;
+}