]> Pileus Git - ~andy/gtk/blobdiff - gdk/gdkwindow.c
GdkWindow: remove reference to a long-removed example
[~andy/gtk] / gdk / gdkwindow.c
index 7a84aee90a2cf07010202befd39ca3eb4155a786..ae77620888496d11bdfcb217cc867b6563356f7b 100644 (file)
  * <firstterm>composited</firstterm> window it is the responsibility of the
  * application to render the window contents at the right spot.
  * </para>
- * <example id="composited-window-example">
- * <title>Composited windows</title>
- * <programlisting>
- * <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../examples/gdk/composited-window-example.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include>
- * </programlisting></example>
- * <para>
- * In the example <xref linkend="composited-window-example"/>, a button is
- * placed inside of an event box inside of a window. The event box is set as
- * composited and therefore is no longer automatically drawn to the screen.
- *
- * When the contents of the event box change, an expose event is generated on
- * its parent window (which, in this case, belongs to the toplevel #GtkWindow).
- * The expose handler for this widget is responsible for merging the changes
- * back on the screen in the way that it wishes.
- *
- * In our case, we merge the contents with a 50% transparency. We also set the
- * background colour of the window to red. The effect is that the background
- * shows through the button.
- * </para>
  * </refsect2>
  * <refsect2 id="OFFSCREEN-WINDOWS">
  * <title>Offscreen Windows</title>
  * be it a toplevel window or a child window. In this setup the
  * GdkWindow (and other GdkDrawables) were platform independent classes,
  * and the actual platform specific implementation was in a delegate
- * object availible as "impl" in the window object.
+ * object available as "impl" in the window object.
  *
  * With the addition of client side windows and offscreen windows this
  * changes a bit. The application-visible GdkWindow object behaves as
@@ -254,6 +235,7 @@ static void gdk_window_invalidate_rect_full (GdkWindow          *window,
                                             gboolean            invalidate_children,
                                             ClearBg             clear_bg);
 static void _gdk_window_propagate_has_alpha_background (GdkWindow *window);
+static cairo_surface_t *gdk_window_ref_impl_surface (GdkWindow *window);
 
 static guint signals[LAST_SIGNAL] = { 0 };
 
@@ -263,6 +245,42 @@ static const cairo_user_data_key_t gdk_window_cairo_key;
 
 G_DEFINE_ABSTRACT_TYPE (GdkWindow, gdk_window, G_TYPE_OBJECT)
 
+#ifdef DEBUG_WINDOW_PRINTING
+char *
+print_region (cairo_region_t *region)
+{
+  GString *s = g_string_new ("{");
+  if (cairo_region_is_empty (region))
+    {
+      g_string_append (s, "empty");
+    }
+  else
+    {
+      int num = cairo_region_num_rectangles (region);
+      cairo_rectangle_int_t r;
+
+      if (num == 1)
+       {
+         cairo_region_get_rectangle (region, 0, &r);
+         g_string_append_printf (s, "%dx%d @%d,%d", r.width, r.height, r.x, r.y);
+       }
+      else
+       {
+         cairo_region_get_extents (region, &r);
+         g_string_append_printf (s, "extent: %dx%d @%d,%d, details: ", r.width, r.height, r.x, r.y);
+         for (int i = 0; i < num; i++)
+           {
+             g_string_append_printf (s, "[%dx%d @%d,%d]", r.width, r.height, r.x, r.y);
+             if (i != num -1)
+               g_string_append (s, ", ");
+           }
+       }
+    }
+  g_string_append (s, "}");
+  return g_string_free (s, FALSE);
+}
+#endif
+
 GType
 _gdk_paintable_get_type (void)
 {
@@ -397,11 +415,11 @@ gdk_window_class_init (GdkWindowClass *klass)
   /**
    * GdkWindow::to-embedder:
    * @window: the offscreen window on which the signal is emitted
-   * @offscreen-x: x coordinate in the offscreen window
-   * @offscreen-y: y coordinate in the offscreen window
-   * @embedder-x: (out) (type double): return location for the x
+   * @offscreen_x: x coordinate in the offscreen window
+   * @offscreen_y: y coordinate in the offscreen window
+   * @embedder_x: (out) (type double): return location for the x
    *     coordinate in the embedder window
-   * @embedder-y: (out) (type double): return location for the y
+   * @embedder_y: (out) (type double): return location for the y
    *     coordinate in the embedder window
    *
    * The ::to-embedder signal is emitted to translate coordinates
@@ -428,11 +446,11 @@ gdk_window_class_init (GdkWindowClass *klass)
   /**
    * GdkWindow::from-embedder:
    * @window: the offscreen window on which the signal is emitted
-   * @embedder-x: x coordinate in the embedder window
-   * @embedder-y: y coordinate in the embedder window
-   * @offscreen-x: (out) (type double): return location for the x
+   * @embedder_x: x coordinate in the embedder window
+   * @embedder_y: y coordinate in the embedder window
+   * @offscreen_x: (out) (type double): return location for the x
    *     coordinate in the offscreen window
-   * @offscreen-y: (out) (type double): return location for the y
+   * @offscreen_y: (out) (type double): return location for the y
    *     coordinate in the offscreen window
    *
    * The ::from-embedder signal is emitted to translate coordinates
@@ -1300,7 +1318,8 @@ sync_native_window_stack_position (GdkWindow *window)
  * @parent: (allow-none): a #GdkWindow, or %NULL to create the window as a child of
  *   the default root window for the default display.
  * @attributes: attributes of the new window
- * @attributes_mask: mask indicating which fields in @attributes are valid
+ * @attributes_mask: (type GdkWindowAttributesType): mask indicating which
+ *   fields in @attributes are valid
  *
  * Creates a new #GdkWindow using the attributes from
  * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
@@ -2670,7 +2689,7 @@ gdk_window_get_content (GdkWindow *window)
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
-  surface = _gdk_window_ref_cairo_surface (window);
+  surface = gdk_window_ref_impl_surface (window);
   content = cairo_surface_get_content (surface);
   cairo_surface_destroy (surface);
 
@@ -2745,60 +2764,55 @@ gdk_cairo_create_for_impl (GdkWindow *window)
   return cr;
 }
 
-/* Ensure that all content related to this (sub)window is pushed to the
-   native region. If there is an active paint then that area is not
-   pushed, in order to not show partially finished double buffers. */
+/* This is called whenever something is drawing directly to the
+ * window, bypassing the double buffering. When this happens we
+ * need to mark any the currently drawn data in the double buffer
+ * as invalid to avoid later drawing it back over the directly
+ * rendered pixels. We also need to mark this region as "flushed"
+ * so that if we later try to paint on it double-buffered we need
+ * to read back the on-window pixels rather than relying on what
+ * is in the current double-buffer pixmap.
+ *
+ * Note that this doesn't correctly handle the case where the
+ * non-double buffered drawing uses transparency and relies on
+ * what the windows below it draws. A fix for that would require
+ * drawing the existing double-buffered background to the window,
+ * but that causes ugly flashes. Non-double buffered drawing is
+ * typically only used in old code or when the drawed widget
+ * already has a double-buffering layer, and in these cases the
+ * pixels are opaque anyway. If you need transparency, don't
+ * disable double buffering.
+ */
 static void
 gdk_window_flush_implicit_paint (GdkWindow *window)
 {
   GdkWindow *impl_window;
   GdkWindowPaint *paint;
   cairo_region_t *region;
-  GSList *list;
 
   impl_window = gdk_window_get_impl_window (window);
   if (impl_window->implicit_paint == NULL)
     return;
 
   paint = impl_window->implicit_paint;
-  region = cairo_region_copy (window->clip_region_with_children);
 
+  region = cairo_region_copy (window->clip_region_with_children);
   cairo_region_translate (region, window->abs_x, window->abs_y);
 
+  /* Anything in the whole flushed window that was drawn is now
+     considered unpainted, so that we don't push it back at the
+     end of the implicit paint overwriting the directly rendered
+     pixels. */
+  cairo_region_subtract (paint->region, region);
+
+  /* Save flushed area so we can read it back if we draw over it later */
   if (paint->flushed == NULL)
-    paint->flushed = cairo_region_copy (region);
+    paint->flushed = region;
   else
-    cairo_region_union (paint->flushed, region);
-
-  cairo_region_intersect (region, paint->region);
-
-  /* Don't flush active double buffers, as that may show partially done
-   * rendering */
-  for (list = window->paint_stack; list != NULL; list = list->next)
-    {
-      GdkWindowPaint *tmp_paint = list->data;
-
-      cairo_region_subtract (region, tmp_paint->region);
-    }
-
-  if (!GDK_WINDOW_DESTROYED (window) && !cairo_region_is_empty (region))
     {
-      cairo_t *cr;
-
-      /* Remove flushed region from the implicit paint */
-      cairo_region_subtract (paint->region, region);
-
-      /* Some regions are valid, push these to window now */
-      cr = gdk_cairo_create_for_impl (window);
-      gdk_cairo_region (cr, region);
-      cairo_clip (cr);
-      cairo_set_source_surface (cr, paint->surface, 0, 0);
-      cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-      cairo_paint (cr);
-      cairo_destroy (cr);
+      cairo_region_union (paint->flushed, region);
+      cairo_region_destroy (region);
     }
-
-  cairo_region_destroy (region);
 }
 
 /* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
@@ -3411,28 +3425,6 @@ gdk_window_flush (GdkWindow *window)
   gdk_window_flush_implicit_paint (window);
 }
 
-/* If we're about to move/resize or otherwise change the
- * hierarchy of a client side window in an impl and we're
- * called from an expose event handler then we need to
- * flush any already painted parts of the implicit paint
- * that are not part of the current paint, as these may
- * be used when scrolling or may overdraw the changes
- * caused by the hierarchy change.
- */
-static void
-gdk_window_flush_if_exposing (GdkWindow *window)
-{
-  GdkWindow *impl_window;
-
-  impl_window = gdk_window_get_impl_window (window);
-
-  /* If we're in an implicit paint (i.e. in an expose handler, flush
-     all the already finished exposes to get things to an uptodate state. */
-  if (impl_window->implicit_paint)
-    gdk_window_flush (window);
-}
-
-
 static void
 gdk_window_flush_recursive_helper (GdkWindow *window,
                                   GdkWindowImpl *impl)
@@ -5333,8 +5325,6 @@ gdk_window_raise (GdkWindow *window)
   if (window->destroyed)
     return;
 
-  gdk_window_flush_if_exposing (window);
-
   /* Keep children in (reverse) stacking order */
   gdk_window_raise_internal (window);
 
@@ -5455,8 +5445,6 @@ gdk_window_lower (GdkWindow *window)
   if (window->destroyed)
     return;
 
-  gdk_window_flush_if_exposing (window);
-
   /* Keep children in (reverse) stacking order */
   gdk_window_lower_internal (window);
 
@@ -5512,8 +5500,6 @@ gdk_window_restack (GdkWindow     *window,
       return;
     }
 
-  gdk_window_flush_if_exposing (window);
-
   if (gdk_window_is_toplevel (window))
     {
       g_return_if_fail (gdk_window_is_toplevel (sibling));
@@ -6069,8 +6055,6 @@ gdk_window_move_resize_internal (GdkWindow *window,
        window->y == y)))
     return;
 
-  gdk_window_flush_if_exposing (window);
-
   /* Handle child windows */
 
   expose = FALSE;
@@ -6355,8 +6339,6 @@ gdk_window_scroll (GdkWindow *window,
   if (window->destroyed)
     return;
 
-  gdk_window_flush_if_exposing (window);
-
   old_layered_area = cairo_region_copy (window->layered_region);
   old_native_child_region = collect_native_child_region (window, FALSE);
   if (old_native_child_region)
@@ -8116,7 +8098,7 @@ static const guint type_masks[] = {
   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 */
+  GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK,/* GDK_SCROLL= 31 */
   0, /* GDK_WINDOW_STATE = 32 */
   0, /* GDK_SETTING = 33 */
   0, /* GDK_OWNER_CHANGE = 34 */
@@ -9158,7 +9140,7 @@ get_event_window (GdkDisplay                 *display,
           emulated_mask |= GDK_BUTTON_PRESS_MASK;
           break;
         case GDK_TOUCH_UPDATE:
-          emulated_mask |= GDK_BUTTON_MOTION_MASK;
+          emulated_mask |= GDK_POINTER_MOTION_MASK;
           break;
         case GDK_TOUCH_END:
           emulated_mask |= GDK_BUTTON_RELEASE_MASK;
@@ -9271,7 +9253,6 @@ proxy_pointer_event (GdkDisplay                 *display,
 
   if (pointer_info->need_touch_press_enter &&
       gdk_device_get_source (pointer_info->last_slave) != GDK_SOURCE_TOUCHSCREEN &&
-      gdk_device_get_source (pointer_info->last_slave) != GDK_SOURCE_TOUCHPAD &&
       (source_event->type != GDK_TOUCH_UPDATE ||
        _gdk_event_get_pointer_emulated (source_event)))
     {
@@ -9470,55 +9451,53 @@ proxy_pointer_event (GdkDisplay                 *display,
       if (!event_win)
         return TRUE;
 
-      if (!display->ignore_core_events)
-        {
-          event = gdk_event_new (event_type);
-          event->any.window = g_object_ref (event_win);
-          event->any.send_event = source_event->any.send_event;
+      event = gdk_event_new (event_type);
+      event->any.window = g_object_ref (event_win);
+      event->any.send_event = source_event->any.send_event;
 
-          gdk_event_set_device (event, gdk_event_get_device (source_event));
-          gdk_event_set_source_device (event, source_device);
+      gdk_event_set_device (event, gdk_event_get_device (source_event));
+      gdk_event_set_source_device (event, source_device);
 
-          if (event_type == GDK_TOUCH_UPDATE)
-            {
-              event->touch.time = time_;
-              event->touch.state = state | GDK_BUTTON1_MASK;
-              event->touch.sequence = source_event->touch.sequence;
-              convert_toplevel_coords_to_window (event_win,
-                                                 toplevel_x, toplevel_y,
-                                                 &event->touch.x, &event->touch.y);
-              gdk_event_get_root_coords (source_event,
-                                         &event->touch.x_root,
-                                         &event->touch.y_root);
-
-              event->touch.axes = g_memdup (source_event->touch.axes,
-                                            sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
-            }
-          else
-            {
-              event->motion.time = time_;
-              event->motion.state = state;
-              event->motion.is_hint = is_hint;
-
-              convert_toplevel_coords_to_window (event_win,
-                                                 toplevel_x, toplevel_y,
-                                                 &event->motion.x, &event->motion.y);
-              gdk_event_get_root_coords (source_event,
-                                         &event->motion.x_root,
-                                         &event->motion.y_root);
-
-              if (is_touch_type (source_event->type))
-                event->motion.axes = g_memdup (source_event->touch.axes,
-                                               sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
-              else
-                event->motion.axes = g_memdup (source_event->motion.axes,
-                                               sizeof (gdouble) * gdk_device_get_n_axes (source_event->motion.device));
-            }
+      if (event_type == GDK_TOUCH_UPDATE)
+       {
+         event->touch.time = time_;
+         event->touch.state = state | GDK_BUTTON1_MASK;
+         event->touch.sequence = source_event->touch.sequence;
+         event->touch.emulating_pointer = source_event->touch.emulating_pointer;
+         convert_toplevel_coords_to_window (event_win,
+                                            toplevel_x, toplevel_y,
+                                            &event->touch.x, &event->touch.y);
+         gdk_event_get_root_coords (source_event,
+                                    &event->touch.x_root,
+                                    &event->touch.y_root);
+
+         event->touch.axes = g_memdup (source_event->touch.axes,
+                                       sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
+       }
+      else
+       {
+         event->motion.time = time_;
+         event->motion.state = state;
+         event->motion.is_hint = is_hint;
+
+         convert_toplevel_coords_to_window (event_win,
+                                            toplevel_x, toplevel_y,
+                                            &event->motion.x, &event->motion.y);
+         gdk_event_get_root_coords (source_event,
+                                    &event->motion.x_root,
+                                    &event->motion.y_root);
+
+         if (is_touch_type (source_event->type))
+           event->motion.axes = g_memdup (source_event->touch.axes,
+                                          sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
+         else
+           event->motion.axes = g_memdup (source_event->motion.axes,
+                                          sizeof (gdouble) * gdk_device_get_n_axes (source_event->motion.device));
+       }
 
-          /* Just insert the event */
-          _gdk_event_queue_insert_after (gdk_window_get_display (event_win),
-                                         source_event, event);
-        }
+      /* Just insert the event */
+      _gdk_event_queue_insert_after (gdk_window_get_display (event_win),
+                                    source_event, event);
     }
 
   /* unlink all move events from queue.
@@ -9663,7 +9642,7 @@ proxy_button_event (GdkEvent *source_event,
   if (source_event->type == GDK_TOUCH_END && !is_touch_type (type))
     state |= GDK_BUTTON1_MASK;
 
-  if (event_win == NULL || display->ignore_core_events)
+  if (event_win == NULL)
     return TRUE;
 
   if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER &&
@@ -9681,8 +9660,7 @@ proxy_button_event (GdkEvent *source_event,
        * which synthesized a leave notify event, so synthesize another enter
        * notify to tell the pointer is on the window.
        */
-      if (gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN ||
-          gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHPAD)
+      if (gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)
         mode = GDK_CROSSING_TOUCH_BEGIN;
       else
         mode = GDK_CROSSING_DEVICE_SWITCH;
@@ -9696,6 +9674,13 @@ proxy_button_event (GdkEvent *source_event,
                                        state, time_, source_event,
                                        serial, FALSE);
     }
+  else if (type == GDK_SCROLL &&
+           (((evmask & GDK_SMOOTH_SCROLL_MASK) == 0 &&
+             source_event->scroll.direction == GDK_SCROLL_SMOOTH) ||
+            ((evmask & GDK_SMOOTH_SCROLL_MASK) != 0 &&
+             source_event->scroll.direction != GDK_SCROLL_SMOOTH &&
+             _gdk_event_get_pointer_emulated (source_event))))
+    return FALSE;
 
   event = _gdk_make_event (event_win, type, source_event, FALSE);
 
@@ -9713,11 +9698,10 @@ proxy_button_event (GdkEvent *source_event,
       gdk_event_set_device (event, gdk_event_get_device (source_event));
       gdk_event_set_source_device (event, source_device);
 
-      if (type == GDK_BUTTON_RELEASE)
-       event->button.state |= GDK_BUTTON1_MASK;
-
       if (is_touch_type (source_event->type))
-       {
+        {
+          if (type == GDK_BUTTON_RELEASE)
+            event->button.state |= GDK_BUTTON1_MASK;
          event->button.button = 1;
          event->button.axes = g_memdup (source_event->touch.axes,
                                         sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
@@ -9735,8 +9719,7 @@ proxy_button_event (GdkEvent *source_event,
                 (type == GDK_TOUCH_END &&
                  _gdk_event_get_pointer_emulated (source_event))) &&
                pointer_window == pointer_info->window_under_pointer &&
-               (gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN ||
-                gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHPAD))
+               gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)
         {
           /* Synthesize a leave notify event
            * whenever a touch device is released
@@ -9765,14 +9748,14 @@ proxy_button_event (GdkEvent *source_event,
       event->touch.axes = g_memdup (source_event->touch.axes,
                                      sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
       event->touch.sequence = source_event->touch.sequence;
+      event->touch.emulating_pointer = source_event->touch.emulating_pointer;
 
       gdk_event_set_source_device (event, source_device);
 
       if ((type == GDK_TOUCH_END &&
            _gdk_event_get_pointer_emulated (source_event)) &&
            pointer_window == pointer_info->window_under_pointer &&
-           (gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN ||
-            gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHPAD))
+           gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)
         {
           /* Synthesize a leave notify event
            * whenever a touch device is released
@@ -9797,6 +9780,8 @@ proxy_button_event (GdkEvent *source_event,
       event->scroll.y_root = source_event->scroll.y_root;
       event->scroll.state = state;
       event->scroll.device = source_event->scroll.device;
+      event->scroll.delta_x = source_event->scroll.delta_x;
+      event->scroll.delta_y = source_event->scroll.delta_y;
       gdk_event_set_source_device (event, source_device);
       return TRUE;
 
@@ -9808,11 +9793,16 @@ proxy_button_event (GdkEvent *source_event,
 }
 
 #ifdef DEBUG_WINDOW_PRINTING
+
+#ifdef GDK_WINDOWING_X11
+#include "x11/gdkx.h"
+#endif
+
 static void
 gdk_window_print (GdkWindow *window,
                  int indent)
 {
-  GdkRectangle r;
+  char *s;
   const char *window_types[] = {
     "root",
     "toplevel",
@@ -9851,11 +9841,8 @@ gdk_window_print (GdkWindow *window,
   g_print (" abs[%d,%d]",
           window->abs_x, window->abs_y);
 
-  cairo_region_get_extents (window->clip_region, &r);
-  if (cairo_region_is_empty (window->clip_region))
-    g_print (" clipbox[empty]");
-  else
-    g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
+  s = print_region (window->clip_region);
+  g_print (" clipbox[%s]", s);
 
   g_print ("\n");
 }
@@ -10125,7 +10112,7 @@ gdk_window_create_similar_surface (GdkWindow *     window,
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
   
-  window_surface = _gdk_window_ref_cairo_surface (window);
+  window_surface = gdk_window_ref_impl_surface (window);
 
   switch (_gdk_rendering_mode)
   {
@@ -10425,7 +10412,7 @@ gdk_window_get_root_origin (GdkWindow *window,
 /**
  * gdk_window_get_frame_extents:
  * @window: a toplevel #GdkWindow
- * @rect: rectangle to fill with bounding box of the window frame
+ * @rect: (out): rectangle to fill with bounding box of the window frame
  *
  * Obtains the bounding box of the window, including window manager
  * titlebar/borders if any. The frame position is given in root window