[gtk+] texthandles: Keep state internally to avoid X overhead



commit d97861bd8b338c3d25d7ffb5496edee9eee9bfbb
Author: Carlos Garnacho <carlos lanedo com>
Date:   Wed Nov 7 14:23:04 2012 +0100

    texthandles: Keep state internally to avoid X overhead
    
    Handles now do sync X calls less often. As visibility state
    is kept, it now can move+resize+show handles at once instead
    of in separated steps.

 gtk/gtktexthandle.c |  131 ++++++++++++++++++++++++++++-----------------------
 1 files changed, 72 insertions(+), 59 deletions(-)
---
diff --git a/gtk/gtktexthandle.c b/gtk/gtktexthandle.c
index 8298cdf..fd1d966 100644
--- a/gtk/gtktexthandle.c
+++ b/gtk/gtktexthandle.c
@@ -46,6 +46,9 @@ struct _HandleWindow
   gint dx;
   gint dy;
   guint dragged : 1;
+  guint mode_visible : 1;
+  guint user_visible : 1;
+  guint has_point : 1;
 };
 
 struct _GtkTextHandlePrivate
@@ -282,13 +285,11 @@ gtk_text_handle_widget_event (GtkWidget     *widget,
 }
 
 static void
-_gtk_text_handle_update_window (GtkTextHandle         *handle,
-                                GtkTextHandlePosition  pos)
+_gtk_text_handle_update_window_state (GtkTextHandle         *handle,
+                                      GtkTextHandlePosition  pos)
 {
   GtkTextHandlePrivate *priv;
   HandleWindow *handle_window;
-  gboolean visible;
-  gint x, y;
 
   priv = handle->priv;
   handle_window = &priv->windows[pos];
@@ -296,30 +297,51 @@ _gtk_text_handle_update_window (GtkTextHandle         *handle,
   if (!handle_window->window)
     return;
 
-  /* Get current state and destroy */
-  visible = gdk_window_is_visible (handle_window->window);
-
-  if (visible)
+  if (handle_window->has_point &&
+      handle_window->mode_visible && handle_window->user_visible)
     {
-      gint width;
+      gint x, y, width, height;
+
+      x = handle_window->pointing_to.x;
+      y = handle_window->pointing_to.y;
+      _gtk_text_handle_get_size (handle, &width, &height);
 
-      _gtk_text_handle_get_size (handle, &width, NULL);
-      gdk_window_get_root_coords (handle_window->window,
-                                  width / 2, 0, &x, &y);
+      if (pos == GTK_TEXT_HANDLE_POSITION_CURSOR)
+        y += handle_window->pointing_to.height;
+      else
+        y -= height;
+
+      x -= width / 2;
+
+      gdk_window_move_resize (handle_window->window, x, y, width, height);
+      gdk_window_show (handle_window->window);
     }
+  else
+    gdk_window_hide (handle_window->window);
+}
 
-  gtk_widget_unregister_window (priv->parent, handle_window->window);
-  gdk_window_destroy (handle_window->window);
+static void
+_gtk_text_handle_update_window (GtkTextHandle         *handle,
+                                GtkTextHandlePosition  pos,
+                                gboolean               recreate)
+{
+  GtkTextHandlePrivate *priv;
+  HandleWindow *handle_window;
 
-  /* Create new window and apply old state */
-  handle_window->window = _gtk_text_handle_create_window (handle, pos);
+  priv = handle->priv;
+  handle_window = &priv->windows[pos];
 
-  if (visible)
+  if (!handle_window->window)
+    return;
+
+  if (recreate)
     {
-      gdk_window_show (handle_window->window);
-      _gtk_text_handle_set_position (handle, pos,
-                                     &handle_window->pointing_to);
+      gtk_widget_unregister_window (priv->parent, handle_window->window);
+      gdk_window_destroy (handle_window->window);
+      handle_window->window = _gtk_text_handle_create_window (handle, pos);
     }
+
+  _gtk_text_handle_update_window_state (handle, pos);
 }
 
 static void
@@ -328,8 +350,15 @@ _gtk_text_handle_update_windows (GtkTextHandle *handle)
   GtkTextHandlePrivate *priv = handle->priv;
 
   gtk_style_context_invalidate (priv->style_context);
-  _gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START);
-  _gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END);
+  _gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START, FALSE);
+  _gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END, FALSE);
+}
+
+static void
+_gtk_text_handle_composited_changed (GtkTextHandle *handle)
+{
+  _gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START, TRUE);
+  _gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END, TRUE);
 }
 
 static void
@@ -350,7 +379,7 @@ gtk_text_handle_constructed (GObject *object)
                       object);
   priv->composited_changed_id =
     g_signal_connect_swapped (priv->parent, "composited-changed",
-                              G_CALLBACK (_gtk_text_handle_update_windows),
+                              G_CALLBACK (_gtk_text_handle_composited_changed),
                               object);
   priv->style_updated_id =
     g_signal_connect_swapped (priv->parent, "style-updated",
@@ -577,30 +606,31 @@ _gtk_text_handle_set_mode (GtkTextHandle     *handle,
   if (priv->mode == mode)
     return;
 
+  priv->mode = mode;
+
   switch (mode)
     {
     case GTK_TEXT_HANDLE_MODE_CURSOR:
-      /* Only display one handle */
-      gdk_window_show (priv->windows[GTK_TEXT_HANDLE_POSITION_CURSOR].window);
-      gdk_window_hide (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
+      priv->windows[GTK_TEXT_HANDLE_POSITION_CURSOR].mode_visible = TRUE;
+      priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].mode_visible = FALSE;
       break;
-      case GTK_TEXT_HANDLE_MODE_SELECTION:
-        /* Display both handles */
-      gdk_window_show (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
-      gdk_window_show (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
+    case GTK_TEXT_HANDLE_MODE_SELECTION:
+      priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].mode_visible = TRUE;
+      priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].mode_visible = TRUE;
       break;
     case GTK_TEXT_HANDLE_MODE_NONE:
     default:
-      gdk_window_hide (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
-      gdk_window_hide (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
+      priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].mode_visible = FALSE;
+      priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].mode_visible = FALSE;
       break;
     }
 
-  priv->mode = mode;
-
   _gtk_text_handle_update_shape (handle,
                                  priv->windows[GTK_TEXT_HANDLE_POSITION_CURSOR].window,
                                  GTK_TEXT_HANDLE_POSITION_CURSOR);
+
+  _gtk_text_handle_update_window_state (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START);
+  _gtk_text_handle_update_window_state (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END);
 }
 
 GtkTextHandleMode
@@ -620,7 +650,6 @@ _gtk_text_handle_set_position (GtkTextHandle         *handle,
                                GdkRectangle          *rect)
 {
   GtkTextHandlePrivate *priv;
-  gint x, y, width, height;
   HandleWindow *handle_window;
 
   g_return_if_fail (GTK_IS_TEXT_HANDLE (handle));
@@ -628,6 +657,7 @@ _gtk_text_handle_set_position (GtkTextHandle         *handle,
   priv = handle->priv;
   pos = CLAMP (pos, GTK_TEXT_HANDLE_POSITION_CURSOR,
                GTK_TEXT_HANDLE_POSITION_SELECTION_START);
+  handle_window = &priv->windows[pos];
 
   if (!priv->realized)
     return;
@@ -637,21 +667,14 @@ _gtk_text_handle_set_position (GtkTextHandle         *handle,
        pos != GTK_TEXT_HANDLE_POSITION_CURSOR))
     return;
 
+  handle_window->pointing_to = *rect;
+  handle_window->has_point = TRUE;
   gdk_window_get_root_coords (priv->relative_to,
                               rect->x, rect->y,
-                              &x, &y);
-  _gtk_text_handle_get_size (handle, &width, &height);
-  handle_window = &priv->windows[pos];
-
-  if (pos == GTK_TEXT_HANDLE_POSITION_CURSOR)
-    y += rect->height;
-  else
-    y -= height;
-
-  x -= width / 2;
+                              &handle_window->pointing_to.x,
+                              &handle_window->pointing_to.y);
 
-  gdk_window_move (handle_window->window, x, y);
-  handle_window->pointing_to = *rect;
+  _gtk_text_handle_update_window_state (handle, pos);
 }
 
 void
@@ -676,18 +699,8 @@ _gtk_text_handle_set_visible (GtkTextHandle         *handle,
   if (!window)
     return;
 
-  if (!visible)
-    gdk_window_hide (window);
-  else
-    {
-      if (priv->mode == GTK_TEXT_HANDLE_MODE_NONE ||
-          (priv->mode == GTK_TEXT_HANDLE_MODE_CURSOR &&
-           pos != GTK_TEXT_HANDLE_POSITION_CURSOR))
-        return;
-
-      if (!gdk_window_is_visible (window))
-        gdk_window_show (window);
-    }
+  priv->windows[pos].user_visible = visible;
+  _gtk_text_handle_update_window_state (handle, pos);
 }
 
 gboolean


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]