gdkintl.h \
gdkkeys.c \
gdkkeyuni.c \
+ gdkoffscreenwindow.c \
gdkpango.c \
gdkpixbuf-drawable.c \
gdkpixbuf-render.c \
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
#endif
#endif
+#if IN_HEADER(__GDK_WINDOW_H__)
+#if IN_FILE(__GDK_OFFSCREEN_WINDOW_C__)
+gdk_window_get_offscreen_pixmap
+#endif
+#endif
+
#if IN_HEADER(__GDK_WINDOW_H__)
#if IN_FILE(__GDK_DND_X11_C__)
gdk_window_register_dnd
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_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;
+ GdkWindow *pointer_window;
+ gint tmpx, tmpy;
+ GdkModifierType tmp_mask;
+
+ private = (GdkWindowObject *) window;
+
+ pointer_window = _gdk_windowing_window_get_pointer (display,
+ window,
+ &tmpx, &tmpy,
+ 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;
+
+ /* We need to recalculate the true child window with the pointer in it
+ due to possible client side child windows */
+ if (pointer_window != NULL)
+ {
+ /* First get the pointer coords relative to pointer_window */
+ _gdk_windowing_window_get_pointer (display,
+ pointer_window,
+ &tmpx, &tmpy,
+ &tmp_mask);
+ /* Then convert that to a client side window */
+ pointer_window = _gdk_window_find_descendant_at (pointer_window,
+ tmpx, tmpy,
+ NULL, NULL);
+ }
+
+ return pointer_window;
+}
+
/**
* 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_windowing_window_get_pointer (display,
+ 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_windowing_window_get_pointer (display,
+ 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_windowing_window_get_pointer (display,
+ src_toplevel,
+ &x, &y, &state);
+ _gdk_syntesize_crossing_events (display,
+ src_window,
+ NULL,
+ crossing_mode,
+ x, y, state,
+ time,
+ NULL,
+ serial);
+ _gdk_windowing_window_get_pointer (display,
+ 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 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 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_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;
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);
+ /* 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 clear that area in the destination instead. */
- GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc, composite,
+ GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc, composite_impl,
xsrc - composite_x_offset,
ysrc - composite_y_offset,
xdest, ydest,
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"
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;
+ guint32 region_tag_applied;
+ int region_tag_offset_x;
+ int region_tag_offset_y;
+
+ GdkRegion *old_clip_region;
+ GdkPixmap *old_clip_mask;
+
+ GdkSubwindowMode subwindow_mode;
+
GdkFill fill;
GdkBitmap *stipple;
GdkPixmap *tile;
+
+ GdkPixmap *clip_mask;
guint32 fg_pixel;
guint32 bg_pixel;
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;
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;
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);
}
/**
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;
}
/**
* 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;
+
+
+/* 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;
+
+ GdkWindowPaint *implicit_paint;
+
+ 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);
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);
+ 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_get_pointer (GdkDisplay *display,
GdkScreen **screen,
GdkModifierType *mask);
GdkWindow* _gdk_windowing_window_at_pointer (GdkDisplay *display,
gint *win_x,
- gint *win_y);
+ gint *win_y,
+ GdkModifierType *mask);
+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_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);
+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 *
--- /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,
+ 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 gint
+gdk_offscreen_window_get_origin (GdkWindow *window,
+ gint *x,
+ gint *y)
+{
+ if (x)
+ *x = 0;
+ if (y)
+ *y = 0;
+
+ 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_origin = gdk_offscreen_window_get_origin;
+ 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;
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);
}
{
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
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 */
#include "gdkscreen.h"
#include "gdkalias.h"
-#define USE_BACKING_STORE /* Appears to work on Win32, too, now. */
+#undef DEBUG_WINDOW_PRINTING
+
+#ifdef GDK_WINDOWING_X11
+#include "x11/gdkx.h" /* For workaround */
+#endif
-typedef struct _GdkWindowPaint GdkWindowPaint;
+#include "math.h"
+
+/* Not all GdkWindows have a corresponding native window.
+ * Instead some draw into the nearest parent that has whatss
+ * called an "impl", i.e. the implementation window.
+ * For toplevel window system windows the impl is always native
+ * window, but child windows can also have native windows as
+ * this is sometimes necessary. Furthermore, offscreen windows
+ * (type GDK_WINDOW_OFFSCREEN) have an impl of type
+ * GdkOffscreenWindow rather than a backend implementation native
+ * window. Such windows draw into an offscreen pixmap instead
+ * of a window and collect damage that lets you paint it where
+ * you want.
+ *
+ * All GdkWindow track their position, size, clip region and
+ * absolute position in the impl window. For child window with
+ * native windows the clip region is set on the native window
+ * as a window shape to make it clip against other non-native windows.
+ */
+
+#define USE_BACKING_STORE /* Appears to work on Win32, too, now. */
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,
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,
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 void move_native_children (GdkWindowObject *private);
+
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)
{
window->window_type = GDK_WINDOW_CHILD;
window->state = GDK_WINDOW_STATE_WITHDRAWN;
+ window->width = 1;
+ window->height = 1;
+ window->toplevel_window_type = -1;
}
static GQuark quark_pointer_window = 0;
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");
}
_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);
}
+static gboolean
+gdk_window_is_offscreen (GdkWindowObject *window)
+{
+ return GDK_WINDOW_TYPE (window) == GDK_WINDOW_OFFSCREEN;
+}
+
+static GdkWindowObject *
+gdk_window_get_impl_window (GdkWindowObject *window)
+{
+ return window->impl_window;
+}
+
+GdkWindow *
+_gdk_window_get_impl_window (GdkWindow *window)
+{
+ return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
+}
+
+static gboolean
+gdk_window_has_impl (GdkWindowObject *window)
+{
+ return window->impl_window == window;
+}
+
+gboolean
+_gdk_window_has_impl (GdkWindow *window)
+{
+ return gdk_window_has_impl ((GdkWindowObject *)window);
+}
+
+static gboolean
+gdk_window_has_no_impl (GdkWindowObject *window)
+{
+ return window->impl_window != window;
+}
+
+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)
+ {
+ child = l->data;
+
+ 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);
+
+ }
+}
+
+static void
+recompute_visible_regions_internal (GdkWindowObject *private,
+ gboolean recalculate_clip,
+ gboolean recalculate_siblings,
+ gboolean recalculate_children)
+{
+ 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;
+
+ old_abs_x = private->abs_x;
+ old_abs_y = private->abs_y;
+
+ /* 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;
+ }
+
+ 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)
+ {
+ /* 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)
+ {
+ gdk_region_intersect (new_clip, private->parent->clip_region);
+
+ /* Remove all overlapping children from parent */
+ remove_child_area (private->parent, private, FALSE, new_clip);
+ }
+
+ /* Convert from parent coords to window coords */
+ gdk_region_offset (new_clip, -private->x, -private->y);
+
+ if (private->shape)
+ gdk_region_intersect (new_clip, private->shape);
+
+ if (private->clip_region == NULL ||
+ !gdk_region_equal (private->clip_region, new_clip))
+ clip_region_changed = TRUE;
+
+ if (private->clip_region)
+ gdk_region_destroy (private->clip_region);
+ private->clip_region = new_clip;
+
+ 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);
+ }
+
+ /* 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);
+ }
+}
+
+/* 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
+ *
+ * It will recalculate abs_x/y and the clip regions
+ *
+ * Unless the window didn't change stacking order or size/pos, pass in TRUE
+ * for recalculate_siblings. (Mostly used internally for the recursion)
+ *
+ * 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)
+{
+ recompute_visible_regions_internal (private,
+ TRUE,
+ recalculate_siblings,
+ recalculate_children);
+}
+
+void
+_gdk_window_update_size (GdkWindow *window)
+{
+ recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
+}
+
+/* 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)
+{
+ GdkWindowObject *w;
+ GList *l;
+
+ 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);
+
+ 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;
+}
+
+
+static GdkWindowObject *
+find_native_sibling_above (GdkWindowObject *parent,
+ GdkWindowObject *child)
+{
+ 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);
+}
+
+static GdkEventMask
+get_native_event_mask (GdkWindowObject *private)
+{
+ 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_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_new:
* @parent: a #GdkWindow, or %NULL to create the window as a child of
gint attributes_mask)
{
GdkWindow *window;
- GdkWindowObject *private, *parent_private;
-
- g_return_val_if_fail (parent == NULL || GDK_IS_WINDOW (parent), NULL);
+ GdkWindowObject *private;
+ GdkScreen *screen;
+ GdkVisual *visual;
+ int x, y;
+ gboolean native;
+ GdkEventMask event_mask;
+ GdkWindow *real_parent;
+
g_return_val_if_fail (attributes != NULL, NULL);
-
- window = _gdk_window_new (parent, attributes, attributes_mask);
- g_return_val_if_fail (window != NULL, window);
-
- /* Inherit redirection from parent */
- if (parent != NULL)
+
+ if (!parent)
{
- parent_private = GDK_WINDOW_OBJECT (parent);
- private = GDK_WINDOW_OBJECT (window);
- private->redirect = parent_private->redirect;
+ 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);
+
+ g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
- return window;
-}
+ if (GDK_WINDOW_DESTROYED (parent))
+ return NULL;
-/**
- * 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)
-{
- GdkWindowObject *private;
- gboolean show;
+ window = g_object_new (GDK_TYPE_WINDOW, NULL);
+ private = (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);
+ /* 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);
- if (GDK_WINDOW_DESTROYED (window) ||
- (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
- {
- return;
- }
+ private->parent = (GdkWindowObject *)parent;
- private = (GdkWindowObject *) window;
+ private->accept_focus = TRUE;
+ private->focus_on_map = TRUE;
- /* Break up redirection if inherited */
- if (private->redirect && private->redirect->redirected != private)
+ if (attributes_mask & GDK_WA_X)
+ x = attributes->x;
+ else
+ x = 0;
+
+ if (attributes_mask & GDK_WA_Y)
+ y = attributes->y;
+ else
+ y = 0;
+
+ private->x = x;
+ private->y = y;
+ private->width = (attributes->width > 1) ? (attributes->width) : (1);
+ private->height = (attributes->height > 1) ? (attributes->height) : (1);
+
+#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))
{
- remove_redirect_from_children (private, private->redirect);
- private->redirect = NULL;
+ 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
- show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
+ 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;
- /* Inherit parent redirect if we don't have our own */
- if (private->parent && private->redirect == NULL)
+ /* Sanity checks */
+ switch (private->window_type)
{
- private->redirect = private->parent->redirect;
- apply_redirect_to_children (private, private->redirect);
+ 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;
}
+
+ if (attributes_mask & GDK_WA_VISUAL)
+ visual = attributes->visual;
+ else
+ visual = gdk_screen_get_system_visual (screen);
- if (show)
- gdk_window_show (window);
-}
+ private->event_mask = attributes->event_mask;
-static void
-window_remove_filters (GdkWindow *window)
-{
- GdkWindowObject *obj = (GdkWindowObject*) window;
+ if (attributes->wclass == GDK_INPUT_OUTPUT)
+ {
+ 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;
- if (obj->filters)
+ private->bg_pixmap = NULL;
+ }
+ else
{
- 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;
+ private->depth = 0;
+ private->input_only = TRUE;
}
-}
-/**
- * _gdk_window_destroy_hierarchy:
- * @window: a #GdkWindow
- * @recursing: If TRUE, then this is being called because a parent
+ 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)
+ {
+ 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);
+ }
+
+ recompute_visible_regions (private, TRUE, FALSE);
+
+ if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+ {
+ /* Inherit redirection from parent */
+ private->redirect = private->parent->redirect;
+ }
+
+ gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
+ (attributes->cursor) :
+ NULL));
+
+ return window;
+}
+
+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 void
+change_impl (GdkWindowObject *private,
+ GdkWindowObject *impl_window,
+ GdkDrawable *new)
+{
+ GList *l;
+ GdkWindowObject *child;
+ GdkDrawable *old_impl;
+ GdkWindowObject *old_impl_window;
+
+ 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);
+
+ for (l = private->children; l != NULL; l = l->next)
+ {
+ child = l->data;
+
+ if (child->impl == old_impl)
+ change_impl (child, impl_window, new);
+ }
+}
+
+static void
+reparent_to_impl (GdkWindowObject *private)
+{
+ 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_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)
+{
+ 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);
+
+ if (GDK_WINDOW_DESTROYED (window) ||
+ (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
+ return;
+
+ if (!new_parent)
+ new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
+
+ private = (GdkWindowObject *) window;
+ new_parent_private = (GdkWindowObject *)new_parent;
+
+ /* No input-output children of input-only windows */
+ if (new_parent_private->input_only && !private->input_only)
+ return;
+
+ /* Don't create loops in hierarchy */
+ if (is_parent_of (window, new_parent))
+ return;
+
+ if (private->cairo_surface)
+ {
+ /* 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);
+ }
+
+ old_parent = private->parent;
+
+ /* Break up redirection if inherited */
+ if (private->redirect && private->redirect->redirected != private)
+ {
+ remove_redirect_from_children (private, private->redirect);
+ private->redirect = NULL;
+ }
+
+ was_toplevel = private->parent == NULL;
+ was_mapped = GDK_WINDOW_IS_MAPPED (window);
+ show = FALSE;
+
+ /* 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_set_has_native (window, TRUE);
+
+ do_reparent_to_impl = FALSE;
+ if (gdk_window_has_impl (private))
+ {
+ /* 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);
+
+ show = was_mapped;
+ gdk_window_hide (window);
+
+ do_reparent_to_impl = TRUE;
+ change_impl (private,
+ new_parent_private->impl_window,
+ new_parent_private->impl);
+ }
+
+ /* 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));
+ new_parent_private = (GdkWindowObject *)new_parent;
+ }
+
+ if (old_parent)
+ old_parent->children = g_list_remove (old_parent->children, window);
+
+ private->parent = new_parent_private;
+ private->x = x;
+ private->y = y;
+
+ new_parent_private->children = g_list_prepend (new_parent_private->children, window);
+
+ /* Switch the window type as appropriate */
+
+ switch (GDK_WINDOW_TYPE (new_parent))
+ {
+ 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;
+ }
+ }
+
+ /* 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);
+ }
+
+ 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
+ {
+ 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);
+ }
+ }
+
+ if (show)
+ gdk_window_show_unraised (window);
+ else
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+/**
+ * gdk_window_set_has_native:
+ * @window: a #GdkWindow
+ * @has_native: whethe the window should have a native window
+ *
+ * Tries to create or remove a window-system native window for this
+ * GdkWindow. This may fail in some situations. For instance:
+ *
+ * Toplevel and foreign windows must have a native window.
+ * Offscreen window and children of them can never have native windows.
+ * Some backends may not support native child windows.
+ *
+ **/
+void
+gdk_window_set_has_native (GdkWindow *window, gboolean has_native)
+{
+ GdkWindowObject *private;
+ GdkWindowObject *impl_window;
+ GdkDrawable *new_impl, *old_impl;
+ GdkScreen *screen;
+ GdkVisual *visual;
+ GdkWindowAttr attributes;
+ GdkWindowObject *above;
+ GList listhead;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
+ GDK_WINDOW_DESTROYED (window))
+ return;
+
+ private = (GdkWindowObject *) window;
+
+ if (has_native)
+ {
+ /* Create native window */
+
+ if (gdk_window_has_impl (private))
+ /* Already has an impl, either native (ok) or
+ offscreen (not supported). Bail. */
+ return;
+
+ impl_window = gdk_window_get_impl_window (private);
+ if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
+ return; /* native in offscreens not supported */
+
+ screen = gdk_drawable_get_screen (window);
+ visual = gdk_drawable_get_visual (window);
+
+ attributes.colormap = gdk_drawable_get_colormap (window);
+
+ 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;
+
+ 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)
+ {
+ listhead.data = window;
+ listhead.prev = NULL;
+ listhead.next = NULL;
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+ &listhead);
+ }
+
+ recompute_visible_regions (private, FALSE, FALSE);
+
+ /* 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);
+
+ reparent_to_impl (private);
+
+ 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);
+ }
+ else
+ {
+ /* Remove native window */
+
+ if (!gdk_window_has_impl (private))
+ return; /* Not native, can't remove */
+
+ if (private->window_type == GDK_WINDOW_OFFSCREEN)
+ return; /* Not native, can't remove */
+
+ if (private->parent == NULL ||
+ GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+ return; /* toplevel, must be native */
+
+ g_warning ("Tried to turn native window to client side window, this is not supported yet.");
+
+ /* TODO: remove native */
+ }
+}
+
+static void
+window_remove_filters (GdkWindow *window)
+{
+ GdkWindowObject *obj = (GdkWindowObject*) window;
+
+ if (obj->filters)
+ {
+ 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;
+ }
+}
+
+/**
+ * _gdk_window_destroy_hierarchy:
+ * @window: a #GdkWindow
+ * @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.
static void
_gdk_window_destroy_hierarchy (GdkWindow *window,
gboolean recursing,
+ gboolean recursing_native,
gboolean foreign_destroy)
{
GdkWindowObject *private;
GdkWindowObject *temp_private;
GdkWindow *temp_window;
GdkScreen *screen;
+ GdkDisplay *display;
GList *children;
GList *tmp;
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))
{
case GDK_WINDOW_ROOT:
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
}
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);
+
+ if (!recursing &&
+ GDK_WINDOW_IS_MAPPED (window))
+ {
+ recompute_visible_regions (private, TRUE, FALSE);
+ gdk_window_invalidate_in_parent (private);
+ }
}
- _gdk_window_clear_update_area (window);
gdk_window_free_paint_stack (window);
if (private->bg_pixmap &&
temp_private = (GdkWindowObject*) temp_window;
if (temp_private)
_gdk_window_destroy_hierarchy (temp_window,
- TRUE, foreign_destroy);
+ TRUE,
+ recursing_native || gdk_window_has_impl (private),
+ foreign_destroy);
}
g_list_free (children);
}
+
+ _gdk_window_clear_update_area (window);
- _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
+ if (private->cairo_surface)
+ {
+ cairo_surface_finish (private->cairo_surface);
+ cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+ NULL, NULL);
+ }
+
+ 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);
+ }
+
+ private->state |= GDK_WINDOW_STATE_WITHDRAWN;
private->parent = NULL;
private->destroyed = TRUE;
gdk_window_redirect_free (private->redirect);
private->redirect = NULL;
+
+ 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;
}
_gdk_window_destroy (GdkWindow *window,
gboolean foreign_destroy)
{
- _gdk_window_destroy_hierarchy (window, FALSE, foreign_destroy);
+ _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
}
/**
void
gdk_window_destroy (GdkWindow *window)
{
- _gdk_window_destroy_hierarchy (window, FALSE, FALSE);
+ _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
g_object_unref (window);
}
* @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
**/
g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
obj = (GdkWindowObject *)window;
+
while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
- obj = (GdkWindowObject *)obj->parent;
+ {
+ if (obj->parent == NULL ||
+ GDK_WINDOW_TYPE (obj->parent) == GDK_WINDOW_ROOT)
+ break;
+ obj = obj->parent;
+ }
return GDK_WINDOW (obj);
}
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_set_has_native (window, TRUE);
if (private)
tmp_list = private->filters;
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 */
+static void
+gdk_window_flush_implicit_paint (GdkWindow *window)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
+ GdkWindowPaint *paint;
+ GdkRegion *region;
+ GdkGC *tmp_gc;
+
+ /* Ensure that there is no explicit paint region. */
+ g_assert (private->paint_stack == NULL);
+
+ 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);
+ 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
#ifdef USE_BACKING_STORE
GdkWindowObject *private = (GdkWindowObject *)window;
GdkRectangle clip_box;
- GdkWindowPaint *paint;
+ GdkWindowPaint *paint, *implicit_paint;
+ GdkWindowObject *impl_window;
GSList *list;
g_return_if_fail (GDK_IS_WINDOW (window));
GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
if (iface->begin_paint_region)
- iface->begin_paint_region ((GdkPaintable*)private->impl, region);
-
+ iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
+
return;
}
- gdk_region_get_clipbox (region, &clip_box);
+ 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->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->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);
- paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
- cairo_surface_set_device_offset (paint->surface,
- - paint->x_offset, - paint->y_offset);
+ }
+ 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)
{
private->paint_stack = g_slist_prepend (private->paint_stack, paint);
- if (!gdk_region_empty (region))
+ if (!gdk_region_empty (paint->region))
{
- gdk_window_clear_backing_rect (window,
- clip_box.x, clip_box.y,
- clip_box.width, clip_box.height);
+ 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
GdkGC *tmp_gc;
GdkRectangle clip_box;
gint x_offset, y_offset;
+ GdkRegion *full_clip;
g_return_if_fail (GDK_IS_WINDOW (window));
}
paint = private->paint_stack->data;
+
private->paint_stack = g_slist_delete_link (private->paint_stack,
- private->paint_stack);
+ private->paint_stack);
gdk_region_get_clipbox (paint->region, &clip_box);
tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, &x_offset, &y_offset);
-
- gdk_gc_set_clip_region (tmp_gc, paint->region);
- gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
+ x_offset = -private->abs_x;
+ y_offset = -private->abs_y;
- 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)
+ if (!paint->uses_implicit)
{
- GdkWindowClipData data;
+ gdk_window_flush_outstanding_moves (window);
- setup_redirect_clip (window, tmp_gc, &data);
+ 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 + data.x_offset,
- clip_box.y + data.y_offset,
+ clip_box.x + x_offset,
+ clip_box.y + y_offset,
clip_box.width, clip_box.height);
- reset_redirect_clip (window, tmp_gc, &data);
}
/* Reset clip region of the cached GdkGC */
}
}
+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,
*y_offset = paint->y_offset;
}
else
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, x_offset, y_offset);
+ {
+ *x_offset = -private->abs_x;
+ *y_offset = -private->abs_y;
+ }
}
/**
*real_drawable = paint->pixmap;
}
else
- *real_drawable = window;
+ {
+ /* 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);
*y_offset = y_off;
}
+static void
+setup_clip_for_draw (GdkDrawable *drawable,
+ GdkGC *gc,
+ int old_clip_x, int old_clip_y)
+{
+ GdkWindowObject *private = (GdkWindowObject *)drawable;
+ GdkRegion *clip;
+
+ if (private->window_type == GDK_WINDOW_ROOT)
+ return;
+
+ if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
+ clip = private->clip_region_with_children;
+ else
+ clip = private->clip_region;
+
+ _gdk_gc_add_drawable_clip (gc,
+ private->clip_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);
+}
+
+static void
+setup_clip_for_paint (GdkDrawable *drawable,
+ GdkWindowPaint *paint,
+ GdkGC *gc,
+ int old_clip_x, int old_clip_y)
+{
+ _gdk_gc_add_drawable_clip (gc,
+ paint->region_tag,
+ /* This includes the window clip */
+ paint->region,
+ /* If there was a clip origin set appart from the
+ * window offset, need to take that into consideration */
+ -old_clip_x, -old_clip_y);
+}
+
+
#define OFFSET_GC(gc) \
gint x_offset, y_offset; \
gint old_clip_x = gc->clip_x_origin; \
gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
}
+#define SETUP_PAINT_GC_CLIP(gc) \
+ if (paint->uses_implicit) \
+ setup_clip_for_paint (drawable, paint, gc, old_clip_x, \
+ old_clip_y);
+
+#define RESTORE_PAINT_GC_CLIP(gc)
+
+
+#define SETUP_DIRECT_GC_CLIP(gc) \
+ gdk_window_flush ((GdkWindow *)drawable);\
+ setup_clip_for_draw (drawable, gc, old_clip_x, old_clip_y);
+
+#define RESTORE_DIRECT_GC_CLIP(gc)
+
static GdkGC *
gdk_window_create_gc (GdkDrawable *drawable,
GdkGCValues *values,
values, mask);
}
+/* After having set up the drawable clip rect on a GC we need
+ * to make sure that if we draw to a pixmap we draw to the impl,
+ * otherwise the pixmap code will reset the drawable clip.
+ */
+static GdkDrawable *
+pixmap_impl (GdkPixmap *pixmap)
+{
+ return ((GdkPixmapObject *)pixmap)->impl;
+}
+
static void
gdk_window_draw_rectangle (GdkDrawable *drawable,
GdkGC *gc,
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_rectangle (paint->pixmap, gc, filled,
+ SETUP_PAINT_GC_CLIP (gc);
+ gdk_draw_rectangle (pixmap_impl (paint->pixmap), gc, filled,
x - x_offset, y - y_offset, width, height);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_rectangle (private->impl, gc, filled,
- x - x_offset, y - y_offset, width, height);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_rectangle (private->impl, gc, filled,
+ x - x_offset, y - y_offset, width, height);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_arc (paint->pixmap, gc, filled,
+ SETUP_PAINT_GC_CLIP (gc);
+ gdk_draw_arc (pixmap_impl (paint->pixmap), gc, filled,
x - x_offset, y - y_offset,
width, height, angle1, angle2);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_arc (private->impl, gc, filled,
- x - x_offset, y - y_offset,
- width, height, angle1, angle2);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_arc (private->impl, gc, filled,
+ x - x_offset, y - y_offset,
+ width, height, angle1, angle2);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_polygon (paint->pixmap, gc, filled, new_points, npoints);
-
+ SETUP_PAINT_GC_CLIP (gc);
+ gdk_draw_polygon (pixmap_impl (paint->pixmap), gc, filled, new_points, npoints);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
if (new_points != points)
g_free (new_points);
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_text (paint->pixmap, font, gc,
+ SETUP_PAINT_GC_CLIP (gc);
+ gdk_draw_text (pixmap_impl (paint->pixmap), font, gc,
x - x_offset, y - y_offset, text, text_length);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_text (private->impl, font, gc,
- x - x_offset, y - y_offset, text, text_length);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_text (private->impl, font, gc,
+ x - x_offset, y - y_offset, text, text_length);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_text_wc (paint->pixmap, font, gc,
+ SETUP_PAINT_GC_CLIP (gc);
+ gdk_draw_text_wc (pixmap_impl (paint->pixmap), font, gc,
x - x_offset, y - y_offset, text, text_length);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_text_wc (private->impl, font, gc,
- x - x_offset, y - y_offset, text, text_length);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_text_wc (private->impl, font, gc,
+ x - x_offset, y - y_offset, text, text_length);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
-static GdkDrawable*
+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,
GdkRectangle rect;
GdkGC *tmp_gc;
gboolean overlap_buffer;
+ GdkDrawable *source;
+ GdkWindowObject *impl_window;
+ GdkWindowPaint *implicit_paint;
- 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)
- {
- /* No backing store */
- return g_object_ref (drawable);
- }
+ *composite_x_offset = -private->abs_x;
+ *composite_y_offset = -private->abs_y;
- /* See if the buffered part is overlapping the part we want
+ 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.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;
}
}
- if (!overlap_buffer)
- return g_object_ref (drawable);
+ 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,
- private->impl,
+ 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);
y - paint->y_offset,
0, 0, width, height);
}
-
+
/* Reset clip region of the cached GdkGC */
gdk_gc_set_clip_region (tmp_gc, NULL);
GdkWindowObject *private = (GdkWindowObject *)drawable;
GdkRegion *result;
- result = gdk_drawable_get_clip_region (private->impl);
+ result = gdk_region_copy (private->clip_region);
if (private->paint_stack)
{
gdk_window_get_visible_region (GdkDrawable *drawable)
{
GdkWindowObject *private = (GdkWindowObject*) drawable;
-
- return gdk_drawable_get_visible_region (private->impl);
+
+ return gdk_region_copy (private->clip_region);
}
static void
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_drawable (paint->pixmap, gc,
+ SETUP_PAINT_GC_CLIP (gc);
+ gdk_draw_drawable (pixmap_impl (paint->pixmap), gc,
src, xsrc, ysrc,
xdest - x_offset, ydest - y_offset, width, height);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_drawable (private->impl, gc,
- src, xsrc, ysrc,
- xdest - x_offset, ydest - y_offset,
- width, height);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_drawable (private->impl, gc,
+ src, xsrc, ysrc,
+ xdest - x_offset, ydest - y_offset,
+ width, height);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_points (paint->pixmap, gc, new_points, npoints);
+ SETUP_PAINT_GC_CLIP (gc);
+ gdk_draw_points (pixmap_impl (paint->pixmap), gc, new_points, npoints);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_points (private->impl, gc, points, npoints);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_points (private->impl, gc, new_points, npoints);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
if (new_points != points)
g_free (new_points);
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_segments (paint->pixmap, gc, new_segs, nsegs);
+ SETUP_PAINT_GC_CLIP (gc);
+ gdk_draw_segments (pixmap_impl (paint->pixmap), gc, new_segs, nsegs);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_segments (private->impl, gc, new_segs, nsegs);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_segments (private->impl, gc, new_segs, nsegs);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
if (new_segs != segs)
g_free (new_segs);
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_lines (paint->pixmap, gc, new_points, npoints);
+ SETUP_PAINT_GC_CLIP (gc);
+ gdk_draw_lines (pixmap_impl (paint->pixmap), gc, new_points, npoints);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_lines (private->impl, gc, new_points, npoints);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_lines (private->impl, gc, new_points, npoints);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
if (new_points != points)
g_free (new_points);
{
GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_glyphs (paint->pixmap, gc, font, x - x_offset, y - y_offset, glyphs);
+ SETUP_PAINT_GC_CLIP (gc);
+ gdk_draw_glyphs (pixmap_impl (paint->pixmap), gc, font, x - x_offset, y - y_offset, glyphs);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_glyphs (private->impl, gc, font,
- x - x_offset, y - y_offset, glyphs);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_glyphs (private->impl, gc, font,
+ x - x_offset, y - y_offset, glyphs);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
{
GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_glyphs_transformed (paint->pixmap, gc, matrix, font, x, y, glyphs);
+ SETUP_PAINT_GC_CLIP (gc);
+ gdk_draw_glyphs_transformed (pixmap_impl (paint->pixmap), gc, matrix, font, x, y, glyphs);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
}
static void
-gdk_window_clear_backing_rect (GdkWindow *window,
- gint x,
- gint y,
- gint width,
- gint height)
+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;
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);
- cairo_rectangle (method.cr, x, y, width, height);
- cairo_clip (method.cr);
-
- gdk_cairo_region (method.cr, paint->region);
+ gdk_cairo_region (method.cr, clip);
cairo_fill (method.cr);
cairo_destroy (method.cr);
{
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);
+ 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
#endif
}
+ gdk_region_destroy (clip);
+
#if 0
g_timer_destroy (timer);
#endif
}
static void
-gdk_window_clear_backing_rect_redirect (GdkWindow *window,
- gint x,
- gint y,
- gint width,
- gint height)
+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;
- 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,
+ 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 and rect to pixmap coords */
+ /* Convert region to pixmap coords */
gdk_region_offset (clip_region, x_offset, y_offset);
- x += x_offset;
- y += 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);
{
g_assert (method.gc == NULL);
- cairo_rectangle (method.cr, x, y, width, height);
- cairo_clip (method.cr);
-
gdk_cairo_region (method.cr, clip_region);
cairo_fill (method.cr);
{
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, x, y, width, height);
+ gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
+ clipbox.x, clipbox.y,
+ clipbox.width, clipbox.height);
g_object_unref (method.gc);
}
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:
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
gint width,
gint height)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- if (private->paint_stack)
- gdk_window_clear_backing_rect (window, x, y, width, height);
- else
- {
- 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,
- FALSE);
- }
+ gdk_window_clear_area_internal (window,
+ x, y,
+ width, height,
+ FALSE);
}
/**
gint width,
gint height)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
-
- 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);
+ gdk_window_clear_area_internal (window,
+ x, y,
+ width, height,
+ TRUE);
}
static void
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_image (paint->pixmap, gc, image, xsrc, ysrc,
+ SETUP_PAINT_GC_CLIP (gc);
+ gdk_draw_image (pixmap_impl (paint->pixmap), gc, image, xsrc, ysrc,
xdest - x_offset, ydest - y_offset,
width, height);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
- xdest - x_offset, ydest - y_offset,
- width, height);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
+ xdest - x_offset, ydest - y_offset,
+ width, height);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
RESTORE_GC (gc);
}
if (GDK_WINDOW_DESTROYED (drawable))
return;
-
- if (gc)
+
+ /* 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);
+
+ /* Need block to make OFFSET_GC macro to work */
{
OFFSET_GC (gc);
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
+ SETUP_PAINT_GC_CLIP (gc);
+ gdk_draw_pixbuf (pixmap_impl (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);
+ RESTORE_PAINT_GC_CLIP (gc);
}
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
- {
- 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,
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_pixbuf (private->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);
+ dither, x_dither, y_dither);
+ RESTORE_DIRECT_GC_CLIP(gc);
}
- 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);
}
}
if (private->paint_stack)
{
GdkWindowPaint *paint = private->paint_stack->data;
- gdk_draw_trapezoids (paint->pixmap, gc, trapezoids, n_trapezoids);
+ SETUP_PAINT_GC_CLIP (gc);
+ gdk_draw_trapezoids (pixmap_impl (paint->pixmap), gc, trapezoids, n_trapezoids);
+ RESTORE_PAINT_GC_CLIP (gc);
}
else
- gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
+ {
+ SETUP_DIRECT_GC_CLIP(gc);
+ gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
+ RESTORE_DIRECT_GC_CLIP(gc);
+ }
g_free (new_trapezoids);
gint *width,
gint *height)
{
- g_return_if_fail (GDK_IS_WINDOW (drawable));
+ GdkWindowObject *private = (GdkWindowObject *)drawable;
- gdk_drawable_get_size (GDK_WINDOW_OBJECT (drawable)->impl,
- width, height);
+ if (width)
+ *width = private->width;
+ if (height)
+ *height = private->height;
}
static GdkVisual*
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_set_has_native ((GdkWindow *)drawable, TRUE);
- gdk_drawable_set_colormap (((GdkWindowObject*)drawable)->impl, cmap);
+ gdk_drawable_set_colormap (private->impl, cmap);
}
static GdkColormap*
/* 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);
+
+ /* TODO: Is this right? */
+ x_offset = 0;
+ y_offset = 0;
return gdk_drawable_copy_to_image (private->impl,
image,
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)
{
cairo_surface_reference (surface);
}
else
- surface = _gdk_drawable_ref_cairo_surface (private->impl);
+ {
+
+ /* 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 gboolean
-gdk_window_update_idle (gpointer data)
+static inline gboolean
+gdk_window_is_ancestor (GdkWindow *window,
+ GdkWindow *ancestor)
{
- gdk_window_process_all_updates ();
-
+ while (window)
+ {
+ GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
+
+ if (parent == ancestor)
+ return TRUE;
+
+ window = parent;
+ }
+
return FALSE;
}
-static gboolean
-gdk_window_is_toplevel_frozen (GdkWindow *window)
+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;
}
}
+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.
GdkRegion *update_area = private->update_area;
private->update_area = NULL;
- if (_gdk_event_func && gdk_window_is_viewable (window))
+ if (_gdk_event_func && gdk_window_is_viewable (window) &&
+ private->window_type != GDK_WINDOW_FOREIGN)
{
GdkRectangle window_rect;
GdkRegion *expose_region;
GdkRegion *window_region;
- gint width, height;
+ 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_windowing_window_queue_antiexpose (window, update_area);
+ 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;
- gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height);
-
window_rect.x = 0;
window_rect.y = 0;
- window_rect.width = width;
- window_rect.height = height;
+ 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);
-
- if (!gdk_region_empty (expose_region) &&
- (private->event_mask & GDK_EXPOSURE_MASK))
+
+
+ /* No need to do any moves that will end up over the update area */
+ if (private->outstanding_moves)
{
- 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);
+ GdkWindowRegionMove *move;
+ GdkRegion *remove;
+ GList *l, *prev;
- (*_gdk_event_func) (&event, _gdk_event_data);
-
- g_object_unref (window);
+ 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
{
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)
{
if (private->update_freeze_count ||
gdk_window_is_toplevel_frozen (tmp_list->data))
- update_windows = g_slist_prepend (update_windows, private);
+ gdk_window_add_update_window ((GdkWindow *) private);
else
gdk_window_process_updates_internal (tmp_list->data);
}
g_slist_free (old_update_windows);
flush_all_displays ();
+
+ _gdk_windowing_after_process_all_updates ();
+
+ in_process_all_updates = FALSE;
}
/**
gboolean update_children)
{
GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_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 &&
+ 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 (window);
- update_windows = g_slist_remove (update_windows, window);
+ gdk_window_process_updates_internal ((GdkWindow *)impl_window);
+ gdk_window_remove_update_window ((GdkWindow *)impl_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;
- }
+ /* 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);
}
}
gpointer user_data)
{
GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
GdkRegion *visible_region;
GList *tmp_list;
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;
- }
-
- /* 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)
- {
- 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);
- }
- else
- visible_region = gdk_drawable_get_visible_region (window);
+ visible_region = gdk_drawable_get_visible_region (window);
gdk_region_intersect (visible_region, region);
tmp_list = private->children;
{
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);
+ 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)
+ !child->composited &&
+ !gdk_window_is_offscreen (child))
gdk_region_subtract (visible_region, child_region);
if (child_func && (*child_func) ((GdkWindow *)child, user_data))
tmp_list = tmp_list->next;
}
+
+ impl_window = gdk_window_get_impl_window (private);
- if (!gdk_region_empty (visible_region))
+ 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);
-
- if (private->update_area)
+
+ /* Convert to impl coords */
+ gdk_region_offset (visible_region, private->abs_x, private->abs_y);
+ if (impl_window->update_area)
{
- gdk_region_union (private->update_area, visible_region);
+ gdk_region_union (impl_window->update_area, visible_region);
}
else
{
- update_windows = g_slist_prepend (update_windows, window);
- private->update_area = gdk_region_copy (visible_region);
+ gdk_window_add_update_window ((GdkWindow *)impl_window);
+ impl_window->update_area = gdk_region_copy (visible_region);
- gdk_window_schedule_update (window);
+ gdk_window_schedule_update ((GdkWindow *)impl_window);
}
}
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
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);
- if (private->update_area)
+ impl_window = gdk_window_get_impl_window (private);
+
+ if (impl_window->update_area)
{
- tmp_region = private->update_area;
- private->update_area = NULL;
+ 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);
- update_windows = g_slist_remove (update_windows, window);
-
- return tmp_region;
+ 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;
if (private->update_area)
{
- update_windows = g_slist_remove (update_windows, window);
-
+ gdk_window_remove_update_window (window);
+
gdk_region_destroy (private->update_area);
private->update_area = NULL;
}
gdk_window_freeze_updates (GdkWindow *window)
{
GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
g_return_if_fail (GDK_IS_WINDOW (window));
- private->update_freeze_count++;
+ impl_window = gdk_window_get_impl_window (private);
+ impl_window->update_freeze_count++;
}
/**
gdk_window_thaw_updates (GdkWindow *window)
{
GdkWindowObject *private = (GdkWindowObject *)window;
+ GdkWindowObject *impl_window;
g_return_if_fail (GDK_IS_WINDOW (window));
- g_return_if_fail (private->update_freeze_count > 0);
- if (--private->update_freeze_count == 0)
- gdk_window_schedule_update (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));
}
/**
if (mask)
*mask = tmp_mask;
+ _gdk_display_enable_motion_hints (display);
+
return child;
}
return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
}
-/**
- * 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)
+static void
+get_all_native_children (GdkWindowObject *private,
+ GList **native)
{
- GdkWindowObject *private;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
+ GdkWindowObject *child;
+ GList *l;
+
+ for (l = private->children; l != NULL; l = l->next)
+ {
+ child = l->data;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, FALSE);
+ 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);
+ }
+
+ }
}
-/**
- * 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 void
+show_all_visible_impls (GdkWindowObject *private)
+{
+ 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);
+ }
+
+ if (gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private);
+}
+
+static void
+gdk_window_show_internal (GdkWindow *window, gboolean raise)
{
GdkWindowObject *private;
+ gboolean was_mapped;
g_return_if_fail (GDK_IS_WINDOW (window));
if (private->destroyed)
return;
- /* Keep children in (reverse) stacking order */
- gdk_window_raise_internal (window);
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
-}
-
-static void
-gdk_window_lower_internal (GdkWindow *window)
-{
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkWindowObject *parent = private->parent;
+ was_mapped = GDK_WINDOW_IS_MAPPED (window);
+
+ if (raise)
+ /* Keep children in (reverse) stacking order */
+ gdk_window_raise_internal (window);
- if (parent)
+ if (gdk_window_has_impl (private))
{
- parent->children = g_list_remove (parent->children, window);
- parent->children = g_list_append (parent->children, window);
+ if (!was_mapped)
+ gdk_synthesize_window_state (window,
+ GDK_WINDOW_STATE_WITHDRAWN,
+ 0);
+ }
+ else
+ {
+ private->state = 0;
}
-}
-/**
- * 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.
+ if (gdk_window_is_viewable (window))
+ show_all_visible_impls (private);
+
+ 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 (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
+ {
+ 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
/* Keep children in (reverse) stacking order */
gdk_window_lower_internal (window);
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
+ recompute_visible_regions (private, TRUE, FALSE);
+
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+ gdk_window_invalidate_in_parent (private);
}
/**
void
gdk_window_show (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);
+ gdk_window_show_internal (window, TRUE);
+}
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, TRUE);
+static void
+hide_all_visible_impls (GdkWindowObject *private)
+{
+ GdkWindowObject *child;
+ GList *l;
+
+ for (l = private->children; l != NULL; l = l->next)
+ {
+ child = l->data;
+
+ if (GDK_WINDOW_IS_MAPPED (child))
+ hide_all_visible_impls (child);
+ }
+
+ if (gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
}
+
/**
* gdk_window_hide:
* @window: a #GdkWindow
gdk_window_hide (GdkWindow *window)
{
GdkWindowObject *private;
+ gboolean was_mapped, was_viewable;
g_return_if_fail (GDK_IS_WINDOW (window));
if (private->destroyed)
return;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide (window);
+ was_mapped = GDK_WINDOW_IS_MAPPED (private);
+ was_viewable = gdk_window_is_viewable (window);
+
+ if (gdk_window_has_impl (private))
+ {
+
+ if (GDK_WINDOW_IS_MAPPED (window))
+ gdk_synthesize_window_state (window,
+ 0,
+ GDK_WINDOW_STATE_WITHDRAWN);
+ }
+ else if (was_mapped)
+ {
+ GdkDisplay *display;
+
+ /* 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)
+ {
+ 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 (was_viewable)
+ hide_all_visible_impls (private);
+
+ recompute_visible_regions (private, TRUE, FALSE);
+
+ if (was_mapped)
+ {
+ 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);
+
+ _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
+ }
+
+ /* Invalidate the rect */
+ gdk_window_invalidate_in_parent (private);
}
/**
gdk_window_withdraw (GdkWindow *window)
{
GdkWindowObject *private;
+ gboolean was_mapped;
g_return_if_fail (GDK_IS_WINDOW (window));
if (private->destroyed)
return;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
+ was_mapped = GDK_WINDOW_IS_MAPPED (private);
+
+ if (gdk_window_has_impl (private))
+ {
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
+
+ if (was_mapped)
+ {
+ 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);
+
+ _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
+ }
+
+ recompute_visible_regions (private, TRUE, FALSE);
+ }
}
/**
GdkEventMask event_mask)
{
GdkWindowObject *private;
+ GdkDisplay *display;
+
g_return_if_fail (GDK_IS_WINDOW (window));
if (private->destroyed)
return;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, event_mask);
+ /* 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));
+
}
/**
if (private->destroyed)
return 0;
- return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_events (window);
+ return private->event_mask;
}
-/**
- * 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)
+static void
+gdk_window_move_resize_toplevel (GdkWindow *window,
+ gboolean with_move,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
{
GdkWindowObject *private;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
+ 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;
private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (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)
-{
- GdkWindowObject *private;
-
- g_return_if_fail (GDK_IS_WINDOW (window));
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
+ expose = FALSE;
+ old_region = NULL;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, FALSE, 0, 0, width, height);
-}
+ impl_window = gdk_window_get_impl_window (private);
+ old_x = private->x;
+ old_y = private->y;
-/**
- * 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)
-{
- GdkWindowObject *private;
+ 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);
+ }
+
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
- g_return_if_fail (GDK_IS_WINDOW (window));
+ dx = private->x - old_x;
+ dy = private->y - old_y;
+
+ old_abs_x = private->abs_x;
+ old_abs_y = private->abs_y;
- private = (GdkWindowObject *) window;
- if (private->destroyed)
- return;
+ /* Avoid recomputing for pure toplevel moves, for performance reasons */
+ if (is_resize)
+ recompute_visible_regions (private, TRUE, FALSE);
+
+ if (expose)
+ {
+ 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);
+ }
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, x, y, width, height);
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
}
-/**
- * gdk_window_scroll:
+static void
+move_native_children (GdkWindowObject *private)
+{
+ GList *l;
+ GdkWindowObject *child;
+
+ for (l = private->children; l; l = l->next)
+ {
+ child = l->data;
+
+ 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 gboolean
+collect_native_child_region_helper (GdkWindowObject *window,
+ GdkWindow *impl,
+ GdkRegion **region,
+ int x_offset,
+ int y_offset)
+{
+ GdkWindowObject *child;
+ GdkRegion *tmp;
+ GList *l;
+
+ for (l = window->children; l != NULL; l = l->next)
+ {
+ child = l->data;
+
+ if (child->impl != impl)
+ {
+ 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);
+ }
+
+ 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);
+
+ return region;
+}
+
+
+static void
+gdk_window_move_resize_internal (GdkWindow *window,
+ gboolean with_move,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ 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;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject *) window;
+ if (private->destroyed)
+ return;
+
+ if (private->parent == NULL ||
+ GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+ {
+ gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
+ return;
+ }
+
+ /* Handle child windows */
+
+ expose = FALSE;
+ old_region = NULL;
+
+ impl_window = gdk_window_get_impl_window (private);
+
+ old_x = private->x;
+ old_y = private->y;
+
+ if (GDK_WINDOW_IS_MAPPED (window) &&
+ !private->input_only)
+ {
+ expose = TRUE;
+
+ old_region = gdk_region_copy (private->clip_region);
+ /* Adjust region to parent window coords */
+ gdk_region_offset (old_region, private->x, private->y);
+ }
+
+ 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);
+ }
+
+ /* 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;
+ }
+
+ dx = private->x - old_x;
+ dy = private->y - old_y;
+
+ old_abs_x = private->abs_x;
+ old_abs_y = private->abs_y;
+
+ recompute_visible_regions (private, TRUE, FALSE);
+
+ new_native_child_region = NULL;
+ if (old_native_child_region)
+ {
+ 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)
+ {
+ /* 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);
+ }
+ gdk_region_offset (old_region, dx, dy);
+
+ gdk_region_intersect (copy_area, old_region);
+
+ if (new_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_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 (old_native_child_region)
+ {
+ gdk_region_destroy (old_native_child_region);
+ gdk_region_destroy (new_native_child_region);
+ }
+
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+
+
+/**
+ * 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)
+{
+ 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
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 (private->destroyed)
return;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->scroll (window, dx, dy);
+ old_native_child_region = collect_native_child_region (private, FALSE);
+ if (old_native_child_region)
+ {
+ /* 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);
+ }
+
+
+ /* First move all child windows, without causing invalidation */
+
+ tmp_list = private->children;
+ while (tmp_list)
+ {
+ GdkWindow *child = GDK_WINDOW (tmp_list->data);
+ GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
+
+ /* Just update the positions, the bits will move with the copy */
+ child_obj->x += dx;
+ child_obj->y += dy;
+
+ tmp_list = tmp_list->next;
+ }
+
+ recompute_visible_regions (private, FALSE, TRUE);
+
+ new_native_child_region = NULL;
+ if (old_native_child_region)
+ new_native_child_region = collect_native_child_region (private, FALSE);
+
+ move_native_children (private);
+
+ /* Then copy the actual bits of the window w/ child windows */
+
+ impl_window = gdk_window_get_impl_window (private);
+
+ /* 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)
+ {
+ /* 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);
+ }
+ gdk_region_offset (copy_area, dx, dy);
+ gdk_region_intersect (copy_area, private->clip_region);
+
+ /* And the rest need to be invalidated */
+ noncopy_area = gdk_region_copy (private->clip_region);
+ gdk_region_subtract (noncopy_area, copy_area);
+
+ /* convert from window coords to impl */
+ gdk_region_offset (copy_area, private->abs_x, private->abs_y);
+
+ move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
+
+ /* Invalidate not copied regions */
+ gdk_window_invalidate_region (window, noncopy_area, TRUE);
+
+ gdk_region_destroy (noncopy_area);
+
+ if (old_native_child_region)
+ {
+ gdk_region_destroy (old_native_child_region);
+ gdk_region_destroy (new_native_child_region);
+ }
+
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
}
/**
gint dy)
{
GdkWindowObject *private = (GdkWindowObject *) window;
+ GdkWindowObject *impl_window;
+ GdkRegion *nocopy_area;
+ GdkRegion *copy_area;
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (region != NULL);
if (private->destroyed)
return;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_region (window, region, dx, dy);
+ impl_window = gdk_window_get_impl_window (private);
+
+ /* compute source regions */
+ copy_area = gdk_region_copy (region);
+ gdk_region_intersect (copy_area, private->clip_region_with_children);
+
+ /* compute destination regions */
+ gdk_region_offset (copy_area, dx, dy);
+ gdk_region_intersect (copy_area, private->clip_region_with_children);
+
+ /* 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);
+
+ move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
}
/**
const GdkColor *color)
{
GdkWindowObject *private;
+ GdkColormap *colormap = gdk_drawable_get_colormap (window);
g_return_if_fail (GDK_IS_WINDOW (window));
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;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, color);
+ 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);
}
/**
private = (GdkWindowObject *) window;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, pixmap, parent_relative);
+ 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)
+ private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
+ else if (pixmap)
+ private->bg_pixmap = g_object_ref (pixmap);
+ else
+ private->bg_pixmap = GDK_NO_BG;
+
+ 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);
+}
+
+static void
+update_cursor (GdkDisplay *display)
+{
+ GdkWindowObject *pointer_window, *cursor_window;
+ GdkPointerGrabInfo *grab;
+
+ pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
+
+ cursor_window = pointer_window;
+ while (cursor_window->cursor == NULL &&
+ cursor_window->parent != NULL &&
+ cursor_window->parent->window_type != GDK_WINDOW_ROOT)
+ cursor_window = 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_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. */
+ GDK_WINDOW_IMPL_GET_IFACE (pointer_window->impl)->set_cursor
+ (gdk_window_get_toplevel ((GdkWindow *)pointer_window),
+ cursor_window->cursor);
}
/**
GdkCursor *cursor)
{
GdkWindowObject *private;
+ GdkDisplay *display;
g_return_if_fail (GDK_IS_WINDOW (window));
private = (GdkWindowObject *) window;
+ display = gdk_drawable_get_display (window);
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
+ if (private->cursor)
+ {
+ gdk_cursor_unref (private->cursor);
+ private->cursor = NULL;
+ }
+
+ if (!GDK_WINDOW_DESTROYED (window))
+ {
+ if (cursor)
+ private->cursor = gdk_cursor_ref (cursor);
+
+ if (is_parent_of (window, display->pointer_info.window_under_pointer))
+ update_cursor (display);
+ }
}
/**
if (!GDK_WINDOW_DESTROYED (window))
{
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
- width, height,
- depth);
+ if (gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
+ width, height,
+ depth);
+ else
+ {
+ 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;
+ }
}
}
g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
private = (GdkWindowObject *) window;
+
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
- return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
+ if (x)
+ *x += private->abs_x;
+ if (y)
+ *y += private->abs_y;
+
+ return TRUE;
}
+
/**
- * 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
+ * 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;
+ gboolean return_val = FALSE;
+ gint tx = 0;
+ gint ty = 0;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+ private = (GdkWindowObject *) window;
+
+ if (!GDK_WINDOW_DESTROYED (window))
+ {
+ return_val = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_deskrelative_origin (window, &tx, &ty);
+
+ if (x)
+ *x = tx + private->abs_x;
+ if (y)
+ *y = ty + private->abs_y;
+ }
+
+ return return_val;
+}
+
+/**
+ * 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.
gint y)
{
GdkWindowObject *private;
+ GdkRegion *region;
g_return_if_fail (GDK_IS_WINDOW (window));
private = (GdkWindowObject *) window;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_mask (window, mask, x, y);
+ 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);
}
/**
gint offset_y)
{
GdkWindowObject *private;
+ GdkRegion *old_region, *new_region, *diff;
g_return_if_fail (GDK_IS_WINDOW (window));
private = (GdkWindowObject *) window;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region (window, shape_region, offset_x, offset_y);
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ 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)
+ {
+ private->shape = gdk_region_copy (shape_region);
+ gdk_region_offset (private->shape, offset_x, offset_y);
+ }
+ else
+ private->shape = NULL;
+
+ recompute_visible_regions (private, TRUE, FALSE);
+
+ if (old_region)
+ {
+ new_region = gdk_region_copy (private->clip_region);
+
+ /* New area in the window, needs invalidation */
+ diff = gdk_region_copy (new_region);
+ gdk_region_subtract (diff, old_region);
+
+ gdk_window_invalidate_region (window, diff, TRUE);
+
+ gdk_region_destroy (diff);
+
+ 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);
+
+ /* 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);
+ }
+
+ gdk_region_destroy (new_region);
+ gdk_region_destroy (old_region);
+ }
+}
+
+static void
+do_child_shapes (GdkWindow *window,
+ gboolean merge)
+{
+ GdkWindowObject *private;
+ GdkRectangle r;
+ GdkRegion *region;
+
+ private = (GdkWindowObject *) window;
+
+ r.x = 0;
+ r.y = 0;
+ r.width = private->width;
+ r.height = private->height;
+
+ 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);
}
/**
void
gdk_window_set_child_shapes (GdkWindow *window)
{
- GdkWindowObject *private;
-
g_return_if_fail (GDK_IS_WINDOW (window));
- private = (GdkWindowObject *) window;
-
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_child_shapes (window);
+ do_child_shapes (window, FALSE);
}
/**
*/
void
gdk_window_merge_child_shapes (GdkWindow *window)
+{
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ do_child_shapes (window, TRUE);
+}
+
+/**
+ * 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)
+{
+ GdkWindowObject *private;
+ GdkRegion *region;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ private = (GdkWindowObject *) window;
+
+ if (mask)
+ region = _gdk_windowing_get_shape_for_mask (mask);
+ else
+ region = NULL;
+
+ gdk_window_input_shape_combine_region (window,
+ region,
+ x, y);
+
+ gdk_region_destroy (region);
+}
+
+/**
+ * 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)
{
GdkWindowObject *private;
private = (GdkWindowObject *) window;
- GDK_WINDOW_IMPL_GET_IFACE (private->impl)->merge_child_shapes (window);
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
+ if (private->input_shape)
+ gdk_region_destroy (private->input_shape);
+
+ if (shape_region)
+ {
+ private->input_shape = gdk_region_copy (shape_region);
+ gdk_region_offset (private->input_shape, offset_x, offset_y);
+ }
+ else
+ private->input_shape = NULL;
+
+ if (gdk_window_has_impl (private))
+ GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
+
+ /* Pointer may have e.g. moved outside window due to the input mask change */
+ _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+do_child_input_shapes (GdkWindow *window,
+ gboolean merge)
+{
+ GdkWindowObject *private;
+ GdkRectangle r;
+ GdkRegion *region;
+
+ private = (GdkWindowObject *) window;
+
+ r.x = 0;
+ r.y = 0;
+ r.width = private->width;
+ r.height = private->height;
+
+ 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);
+}
+
+
+/**
+ * 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);
}
private = (GdkWindowObject *) window;
- return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
+ if (gdk_window_has_impl (private))
+ return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
+
+ return FALSE;
}
/**
if (private->composited == composited)
return;
+ if (composited)
+ gdk_window_set_has_native (window, TRUE);
+
display = gdk_drawable_get_display (GDK_DRAWABLE (window));
if (!gdk_display_supports_composite (display) && composited)
_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);
+
private->composited = composited;
}
gint height)
{
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);
window_get_size_rectangle (GdkWindow *window,
GdkRectangle *rect)
{
+ GdkWindowObject *private = (GdkWindowObject *) window;
+
rect->x = rect->y = 0;
- gdk_drawable_get_size (GDK_DRAWABLE (window), &rect->width, &rect->height);
+ rect->width = private->width;
+ rect->height = private->height;
}
/* 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 *
+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)
+ gboolean do_children,
+ gint *base_x_offset,
+ gint *base_y_offset)
{
GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
GdkRectangle visible_rect;
window_get_size_rectangle (window, &visible_rect);
- /* 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);
-
/* real_clip_region is in window coordinates */
real_clip_region = gdk_region_rectangle (&visible_rect);
parentwin = lastwin->parent;
/* Remove the areas of all overlapping windows above parentwin in the hiearachy */
- for (; parentwin != NULL && (parentwin == private || lastwin != (GdkWindowObject *)base_window);
+ for (; parentwin != NULL &&
+ (parentwin == private || lastwin != (GdkWindowObject*) base_window);
lastwin = parentwin, parentwin = lastwin->parent)
{
GList *cur;
GdkRectangle real_clip_rect;
-
+ gboolean is_offscreen;
+
if (parentwin != private)
{
x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
}
-
+
+ is_offscreen = gdk_window_is_offscreen (parentwin);
+
/* children is ordered in reverse stack order */
- for (cur = GDK_WINDOW_OBJECT (parentwin)->children; cur && cur->data != lastwin; cur = cur->next)
+ for (cur = 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;
+ /* 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;
+
window_get_size_rectangle (child, &visible_rect);
/* Convert rect to "window" coords */
gdk_region_destroy (tmpreg);
}
- if (gc)
- {
- GdkRegion *clip_region = _gdk_gc_get_clip_region (gc);
-
- if (clip_region)
- {
- /* 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);
- }
- }
-
if (base_x_offset)
*base_x_offset = x_offset;
if (base_y_offset)
return real_clip_region;
}
-static void
-gdk_window_add_damage (GdkWindow *toplevel,
- GdkRegion *damaged_region)
+void
+_gdk_window_add_damage (GdkWindow *toplevel,
+ GdkRegion *damaged_region)
{
GdkDisplay *display;
GdkEvent event = { 0, };
}
static void
-setup_redirect_clip (GdkWindow *window,
- GdkGC *gc,
- GdkWindowClipData *data)
+gdk_window_redirect_free (GdkWindowRedirect *redirect)
{
- GdkWindowObject *private = (GdkWindowObject *)window;
- GdkRegion *visible_region;
- GdkRectangle dest_rect;
- GdkRegion *tmpreg;
- GdkWindow *toplevel;
+ g_object_unref (redirect->pixmap);
+ g_free (redirect);
+}
+
+static void
+convert_coords_to_child (GdkWindowObject *child,
+ double x, double y,
+ double *child_x, double *child_y)
+{
+ *child_x = x - child->x;
+ *child_y = y - child->y;
+}
+
+static gboolean
+point_in_window (GdkWindowObject *window,
+ double x, double y)
+{
+ 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));
+}
- data->old_region = _gdk_gc_get_clip_region (gc);
- if (data->old_region)
- data->old_region = gdk_region_copy (data->old_region);
+static GdkWindow *
+convert_coords_to_toplevel (GdkWindow *window,
+ double child_x, double child_y,
+ double *toplevel_x, double *toplevel_y)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+ gdouble x, y;
- data->old_clip_x_origin = gc->clip_x_origin;
- data->old_clip_y_origin = gc->clip_y_origin;
+ x = child_x;
+ y = child_y;
- toplevel = GDK_WINDOW (private->redirect->redirected);
+ while (private->parent != NULL &&
+ (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
+ {
+ x += private->x;
+ y += private->y;
+ private = private->parent;
+ }
- /* 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);
+ *toplevel_x = x;
+ *toplevel_y = y;
+
+ return (GdkWindow *)private;
+}
- /* 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);
- /* Compensate for the dest pos */
- data->x_offset += private->redirect->dest_x;
- data->y_offset += private->redirect->dest_y;
+static void
+convert_toplevel_coords_to_window (GdkWindow *window,
+ gdouble toplevel_x,
+ gdouble toplevel_y,
+ gdouble *window_x,
+ gdouble *window_y)
+{
+ GdkWindowObject *private;
+ gdouble x, y;
+ GList *children, *l;
- gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
+ private = GDK_WINDOW_OBJECT (window);
+
+ x = toplevel_x;
+ y = toplevel_y;
- /* offset clip and tiles from window coords to pixmaps coords */
- gdk_gc_offset (gc, -data->x_offset, -data->y_offset);
+ children = NULL;
+ while (private->parent != NULL &&
+ (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
+ {
+ children = g_list_prepend (children, private);
+ private = private->parent;
+ }
- /* 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);
+ for (l = children; l != NULL; l = l->next)
+ convert_coords_to_child (l->data, x, y, &x, &y);
- gdk_region_destroy (visible_region);
+ g_list_free (children);
+
+ *window_x = x;
+ *window_y = y;
}
-static void
-reset_redirect_clip (GdkWindow *offscreen,
- GdkGC *gc,
- GdkWindowClipData *data)
+GdkWindow *
+_gdk_window_find_descendant_at (GdkWindow *toplevel,
+ double x, double y,
+ double *found_x,
+ double *found_y)
{
- /* offset back */
- gdk_gc_offset (gc, data->x_offset, data->y_offset);
+ GdkWindowObject *private, *sub;
+ double child_x, child_y;
+ GList *l;
- /* 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);
-}
+ private = (GdkWindowObject *)toplevel;
+
+ if (point_in_window (private, x, y))
+ {
+ do
+ {
+ /* Children is ordered in reverse stack order, i.e. first is topmost */
+ for (l = private->children; l != NULL; l = l->next)
+ {
+ sub = l->data;
-static void
-gdk_window_redirect_free (GdkWindowRedirect *redirect)
-{
- g_object_unref (redirect->pixmap);
- g_free (redirect);
+ 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;
+ break;
+ }
+ }
+ }
+ while (l != NULL);
+ }
+ else
+ {
+ /* Not in window at all */
+ private = NULL;
+ }
+
+ if (found_x)
+ *found_x = x;
+ if (found_y)
+ *found_y = y;
+
+ return (GdkWindow *)private;
+}
+
+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)
+{
+ 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 = tmp->parent;
+ }
+
+ tmp = win2;
+ while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
+ {
+ path2 = g_list_prepend (path2, tmp);
+ tmp = tmp->parent;
+ }
+
+ 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);
+
+ return tmp;
+}
+
+GdkEvent *
+_gdk_make_event (GdkWindow *window,
+ GdkEventType type,
+ GdkEvent *event_in_queue,
+ gboolean before_event)
+{
+ GdkEvent *event = gdk_event_new (type);
+ guint32 the_time;
+ GdkModifierType the_state;
+
+ the_time = gdk_event_get_time (event_in_queue);
+ gdk_event_get_state (event_in_queue, &the_state);
+
+ event->any.window = g_object_ref (window);
+ event->any.send_event = FALSE;
+
+ 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;
+
+ case GDK_SCROLL:
+ event->scroll.time = the_time;
+ event->scroll.state = the_state;
+ break;
+
+ case GDK_KEY_PRESS:
+ case GDK_KEY_RELEASE:
+ event->key.time = the_time;
+ event->key.state = the_state;
+ break;
+
+ case GDK_ENTER_NOTIFY:
+ case GDK_LEAVE_NOTIFY:
+ event->crossing.time = the_time;
+ event->crossing.state = the_state;
+ break;
+
+ 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;
+ }
+
+ 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;
+}
+
+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)
+{
+ GdkEvent *event;
+ guint32 event_mask;
+ GdkPointerGrabInfo *grab;
+
+ grab = _gdk_display_has_pointer_grab (display, serial);
+
+ if (grab != NULL &&
+ !grab->owner_events &&
+ (GdkWindow *)window != grab->window)
+ return;
+
+ if (type == GDK_LEAVE_NOTIFY)
+ event_mask = GDK_LEAVE_NOTIFY_MASK;
+ else
+ event_mask = GDK_ENTER_NOTIFY_MASK;
+
+ 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;
+ }
+}
+
+
+/* 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_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 *c;
+ GdkWindowObject *win, *last, *next;
+ GList *path, *list;
+ gboolean non_linear;
+ GdkWindowObject *a;
+ GdkWindowObject *b;
+ GdkWindowObject *toplevel;
+ GdkNotifyType notify_type;
+
+ /* TODO: Don't send events to toplevel, as we get those from the windowing system */
+
+ a = (GdkWindowObject *)src;
+ b = (GdkWindowObject *)dest;
+ if (a == b)
+ return; /* No crossings generated between src and dest */
+
+ c = find_common_ancestor (a, b);
+
+ non_linear = (c != a) && (c != b);
+
+ if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
+ {
+ toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
+
+ /* 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 = a->parent;
+ 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 = win->parent;
+ }
+ }
+ }
+
+ 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 = b->parent;
+ while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
+ {
+ path = g_list_prepend (path, win);
+ win = win->parent;
+ }
+
+ 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);
+ }
+
+
+ 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);
+ }
+}
+
+static GdkWindow *
+get_toplevel (GdkWindow *w)
+{
+ GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
+
+ while (private->parent != NULL &&
+ (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
+ private = private->parent;
+
+ return GDK_WINDOW (private);
+}
+
+/* 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.
+ */
+static GdkWindow *
+get_pointer_window (GdkDisplay *display,
+ GdkWindow *event_window,
+ gdouble toplevel_x,
+ gdouble toplevel_y,
+ gulong serial)
+{
+ 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;
+
+ grab = _gdk_display_has_pointer_grab (display, serial);
+ if (grab != NULL &&
+ !grab->owner_events &&
+ pointer_window != grab->window)
+ pointer_window = NULL;
+
+ return pointer_window;
+}
+
+void
+_gdk_display_set_window_under_pointer (GdkDisplay *display,
+ GdkWindow *window)
+{
+ GdkWindowObject *private;
+
+ private = (GdkWindowObject *)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);
+
+ if (window)
+ update_cursor (display);
+
+ _gdk_display_enable_motion_hints (display);
+}
+
+void
+_gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
+{
+ GdkDisplay *display;
+ GdkWindow *changed_toplevel;
+ GdkWindow *new_window_under_pointer;
+ gulong serial;
+
+ display = gdk_drawable_get_display (changed_window);
+
+ serial = _gdk_windowing_window_get_next_serial (display);
+ changed_toplevel = get_toplevel (changed_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);
+ }
+ }
+}
+
+/* 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)
+{
+ guint evmask;
+ GdkWindow *grab_window;
+ GdkWindowObject *w;
+ GdkPointerGrabInfo *grab;
+
+ grab = _gdk_display_has_pointer_grab (display, serial);
+
+ if (grab != NULL && !grab->owner_events)
+ {
+ evmask = grab->event_mask;
+ evmask = update_evmask_for_button_motion (evmask, mask);
+
+ grab_window = grab->window;
+
+ if (evmask & type_masks[type])
+ {
+ if (evmask_out)
+ *evmask_out = evmask;
+ return grab_window;
+ }
+ else
+ return NULL;
+ }
+
+ w = (GdkWindowObject *)pointer_window;
+ while (w != NULL)
+ {
+ evmask = w->event_mask;
+ evmask = update_evmask_for_button_motion (evmask, mask);
+
+ if (evmask & type_masks[type])
+ {
+ if (evmask_out)
+ *evmask_out = evmask;
+ return (GdkWindow *)w;
+ }
+
+ w = w->parent;
+ }
+
+ if (grab != NULL &&
+ grab->owner_events)
+ {
+ evmask = grab->event_mask;
+ evmask = update_evmask_for_button_motion (evmask, mask);
+
+ 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_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)
+ {
+ /* 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;
+ }
+
+ pointer_window = get_pointer_window (display, toplevel_window,
+ toplevel_x, toplevel_y, serial);
+
+ 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)
+ {
+ 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 gboolean
+proxy_button_event (GdkEvent *source_event,
+ gulong serial)
+{
+ GdkWindow *toplevel_window, *event_window;
+ GdkWindow *event_win;
+ GdkWindow *pointer_window;
+ 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_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)
+ {
+ 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 && w->parent->window_type != GDK_WINDOW_ROOT)
+ {
+ if (w->event_mask & GDK_BUTTON_PRESS_MASK)
+ break;
+ w = 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);
+ }
+
+ pointer_window = get_pointer_window (display, toplevel_window,
+ toplevel_x, toplevel_y,
+ serial);
+
+ event_win = get_event_window (display,
+ pointer_window,
+ type, state,
+ NULL, serial);
+
+ if (event_win == NULL)
+ return TRUE;
+
+ event = _gdk_make_event (event_win, type, source_event, FALSE);
+
+ switch (type)
+ {
+ 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
+gdk_window_print (GdkWindowObject *window,
+ int indent)
+{
+ GdkRectangle r;
+
+ 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
+ );
+
+ 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");
+}
+
+
+static void
+gdk_window_print_tree (GdkWindow *window,
+ int indent,
+ gboolean include_input_only)
+{
+ GdkWindowObject *private;
+ GList *l;
+
+ private = (GdkWindowObject *)window;
+
+ if (private->input_only && !include_input_only)
+ return;
+
+ gdk_window_print (private, indent);
+
+ for (l = private->children; l != NULL; l = l->next)
+ gdk_window_print_tree (l->data, indent + 4, include_input_only);
+}
+
+#endif /* DEBUG_WINDOW_PRINTING */
+
+void
+_gdk_windowing_got_event (GdkDisplay *display,
+ GList *event_link,
+ GdkEvent *event,
+ gulong serial)
+{
+ 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;
+
+ event_private = GDK_WINDOW_OBJECT (event_window);
+
+#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
+
+ if (!(is_button_type (event->type) ||
+ is_motion_type (event->type)) ||
+ GDK_WINDOW_TYPE (event_private) == GDK_WINDOW_ROOT)
+ return;
+
+ 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))
+ {
+ /* 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)
+ {
+ 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);
+ }
+
+ unlink_event = TRUE;
+ goto out;
+ }
+
+ /* 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;
+ }
+ }
+
+ /* 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_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)
+ {
+ 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)
+ {
+ button_release_grab->serial_end = serial;
+ button_release_grab->implicit_ungrab = TRUE;
+ _gdk_display_pointer_grab_update (display, serial);
+ }
+ }
+
+ out:
+ if (unlink_event)
+ {
+ _gdk_event_queue_remove_link (display, event_link);
+ g_list_free_1 (event_link);
+ gdk_event_free (event);
+ }
}
#define __GDK_WINDOW_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);
+void gdk_window_set_has_native (GdkWindow *window,
+ gboolean has_native);
/*
* This allows for making shaped (partially transparent) windows
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_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);
+ void (* show) (GdkWindow *window);
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 (* get_origin) (GdkWindow *window,
gint *x,
gint *y);
- void (* get_offsets) (GdkWindow *window,
- gint *x_offset,
- gint *y_offset);
+ gint (* get_deskrelative_origin) (GdkWindow *window,
+ gint *x,
+ gint *y);
- 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);
};
/* 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);
}
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);
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;
/* 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;
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_set_has_native (window, TRUE);
+
+ /* 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:
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:
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:
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;
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);
}
}
#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)
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__
gdouble *x_out,
gdouble *y_out)
{
- GdkWindowImplX11 *impl;
+ GdkWindowObject *window_private;
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);
+
+ window_private = (GdkWindowObject *) input_window->window;
for (i=0; i<gdkdev->info.num_axes; i++)
{
}
device_aspect = (device_height*y_resolution) /
(device_width*x_resolution);
- if (device_aspect * impl->width >= impl->height)
+ if (device_aspect * window_private->width >= window_private->height)
{
/* device taller than window */
- x_scale = impl->width / device_width;
+ x_scale = window_private->width / device_width;
y_scale = (x_scale * x_resolution)
/ y_resolution;
x_offset = 0;
y_offset = -(device_height * y_scale -
- impl->height)/2;
+ window_private->height)/2;
}
else
{
/* window taller than device */
- y_scale = impl->height / device_height;
+ y_scale = window_private->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 - window_private->width)/2;
}
}
int tmp_n_events = 0;
int i;
- g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+ g_return_val_if_fail (GDK_WINDOW_IS_X11 (window), FALSE);
if (GDK_WINDOW_DESTROYED (window))
/* Nothing */ ;
GList *tmp_list;
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
+ /* Ensure we have a native window, or the input stuff won't work.
+ Its possible we could emulate this also, but at least this should make
+ it work. */
+ gdk_window_set_has_native (window, TRUE);
+
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);
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));
#include "gdk.h"
#include "gdkx.h"
+#include "gdkasync.h"
#include "gdkdisplay-x11.h"
#include "gdkinternals.h"
#include "gdkintl.h"
return 0;
}
+struct XPointerGrabInfo {
+ GdkDisplay *display;
+ GdkWindow *window;
+ GdkWindow *native_window;
+ gboolean owner_events;
+ gulong serial;
+ guint event_mask;
+ guint32 time;
+};
+
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);
}
/*
{
gint return_val;
GdkCursorPrivate *cursor_private;
+ GdkWindow *native;
GdkDisplayX11 *display_x11;
guint xevent_mask;
Window xwindow;
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);
+
+ native = gdk_window_get_toplevel (window);
+
+ /* We need a native window for confine to to work, ensure we have one */
+ if (confine_to)
+ gdk_window_set_has_native (confine_to, TRUE);
+
+ /* TODO: What do we do for offscreens and their children? We need to proxy the grab somehow */
+ if (!GDK_IS_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (native)->impl))
+ return GDK_GRAB_SUCCESS;
+
+ if (!_gdk_window_has_impl (window) &&
+ !gdk_window_is_viewable (window))
+ return GDK_GRAB_NOT_VIEWABLE;
- 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);
+ serial = NextRequest (GDK_WINDOW_XDISPLAY (native));
if (!confine_to || GDK_WINDOW_DESTROYED (confine_to))
xconfine_to = None;
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,
+ return_val = _gdk_input_grab_pointer (native,
owner_events,
event_mask,
confine_to,
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,
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_display_add_pointer_grab (GDK_DISPLAY_OBJECT (display_x11),
+ window,
+ native,
+ owner_events,
+ event_mask,
+ serial,
+ time,
+ 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);
- if (!GDK_WINDOW_DESTROYED (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 (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;
{
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)
{
- 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);
+ GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
+ Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
+ Window xwindow = GDK_WINDOW_XID (window);
+ gboolean unset_bg;
- if (raise)
- XRaiseWindow (xdisplay, xwindow);
-
- if (!GDK_WINDOW_IS_MAPPED (window))
- {
- set_initial_hints (window);
-
- gdk_synthesize_window_state (window,
- GDK_WINDOW_STATE_WITHDRAWN,
- 0);
- }
+ 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);
-
- window_private->x = x;
- window_private->y = 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);
- /* 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),
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;
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);
-
return_val = NULL;
if (!GDK_WINDOW_DESTROYED (window))
{
}
}
- *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;
-
-#ifdef HAVE_SHAPE_EXT
- 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);
- }
-#endif /* HAVE_SHAPE_EXT */
-}
-
-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;
#ifdef HAVE_SHAPE_EXT
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);
}
#endif /* HAVE_SHAPE_EXT */
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);
}
-#ifdef HAVE_SHAPE_EXT
-
-/*
- * 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;
- if (noo)
- {
- noo->start = x;
- noo->end = xx;
- if (ptr2)
- {
- noo->next = ptr2->next;
- ptr2->next = noo;
- }
- else
- {
- noo->next = NULL;
- *s = noo;
- }
- }
- return;
-}
-
-static void
-gdk_add_rectangles (Display *disp,
- Window win,
- struct _gdk_span **spans,
- gint basew,
- gint baseh,
- gint x,
- gint y)
-{
- gint a, k;
- gint x1, y1, x2, y2;
- gint rn, ord;
- XRectangle *rl;
-
- rl = XShapeGetRectangles (disp, win, ShapeBounding, &rn, &ord);
- if (rl)
- {
- /* go through all clip rects in this window's shape */
- for (k = 0; k < rn; k++)
- {
- /* for each clip rect, add it to each line's spans */
- x1 = x + rl[k].x;
- x2 = x + rl[k].x + (rl[k].width - 1);
- y1 = y + rl[k].y;
- y2 = y + rl[k].y + (rl[k].height - 1);
- if (x1 < 0)
- x1 = 0;
- if (y1 < 0)
- y1 = 0;
- if (x2 >= basew)
- x2 = basew - 1;
- if (y2 >= baseh)
- y2 = baseh - 1;
- for (a = y1; a <= y2; a++)
- {
- if ((x2 - x1) >= 0)
- gdk_add_to_span (&spans[a], x1, x2);
- }
- }
- XFree (rl);
- }
-}
-
-static void
-gdk_propagate_shapes (Display *disp,
- Window win,
- gboolean merge,
- 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);
+#if defined(HAVE_SHAPE_EXT)
+ xrl = XShapeGetRectangles (xdisplay,
+ window,
+ shape_type, &rn, &ord);
- 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++)
+ if (rn == 0)
+ return gdk_region_new (); /* Empty */
+
+ if (ord != YXBanded)
{
- ptr1 = spans[i];
- while (ptr1)
- {
- ptr2 = ptr1;
- ptr1 = ptr1->next;
- g_free (ptr2);
- }
+ /* 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;
}
- g_free (spans);
-}
-#endif /* HAVE_SHAPE_EXT */
-
-static inline void
-do_child_shapes (GdkWindow *window,
- gboolean merge)
-{
-#ifdef HAVE_SHAPE_EXT
- if (!GDK_WINDOW_DESTROYED (window) &&
- gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
+ rl = g_new (GdkRectangle, rn);
+ for (i = 0; i < rn; i++)
{
- gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- merge,
- ShapeBounding);
+ 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);
#endif
+
+ return shape;
}
-static void
-gdk_window_x11_set_child_shapes (GdkWindow *window)
-{
- do_child_shapes (window, FALSE);
-}
-static void
-gdk_window_x11_merge_child_shapes (GdkWindow *window)
+GdkRegion *
+_gdk_windowing_get_shape_for_mask (GdkBitmap *mask)
{
- do_child_shapes (window, TRUE);
+ 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);
+
+ region = xwindow_get_shape (GDK_DISPLAY_XDISPLAY (display),
+ window, ShapeBounding);
+
+ XDestroyWindow (GDK_DISPLAY_XDISPLAY (display),
+ window);
+
+ return region;
}
-static inline void
-do_child_input_shapes (GdkWindow *window,
- gboolean merge)
+GdkRegion *
+_gdk_windowing_window_get_shape (GdkWindow *window)
{
-#if defined(HAVE_SHAPE_EXT) && defined(ShapeInput)
+#if defined(HAVE_SHAPE_EXT)
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), ShapeBounding);
#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);
+ return NULL;
}
-/**
- * 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)
+GdkRegion *
+_gdk_windowing_window_get_input_shape (GdkWindow *window)
{
- g_return_if_fail (GDK_IS_WINDOW (window));
-
- do_child_input_shapes (window, TRUE);
-}
+#if defined(HAVE_SHAPE_EXT)
+ if (!GDK_WINDOW_DESTROYED (window) &&
+ gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
+ return xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
+ GDK_WINDOW_XID (window),
+ ShapeInput);
+#endif
+ return NULL;
+}
static void
gdk_window_set_static_bit_gravity (GdkWindow *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),
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_set_has_native (window, TRUE);
+
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)
{
GdkDisplay *display;
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
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_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;
}
#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,
noinst_PROGRAMS = $(TEST_PROGS) \
simple \
+ flicker \
print-editor \
testaccel \
testassistant \
testmultiscreen \
testnotebookdnd \
testnouiprint \
+ testoffscreen \
testprint \
testrgb \
testrecentchooser \
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)
testprint_DEPENDENCIES = $(TEST_DEPS)
testrecentchooser_DEPENDENCIES = $(TEST_DEPS)
testrecentchoosermenu_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)
testprint_LDADD = $(LDADDS)
testrecentchooser_LDADD = $(LDADDS)
testrecentchoosermenu_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
+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 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);
+
+ 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 (NULL,
+ &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);
+
+ /* 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 (NULL,
+ &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);
+
+ 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
+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_set_has_native (window, TRUE);
+
+ 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_set_has_native (window, TRUE);
+ }
+
+ 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 ("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;
+}