Ticket #4135: 0001-texthandles-Keep-state-internally-to-avoid-X-overhea.patch

File 0001-texthandles-Keep-state-internally-to-avoid-X-overhea.patch, 8.2 KB (added by garnacho, 12 years ago)

Patch to fix the issue

  • gtk/gtktexthandle.c

    From 9bfc81a58c6ddde2d0e7c9c48f31dbe5354f0b64 Mon Sep 17 00:00:00 2001
    From: Carlos Garnacho <carlos@lanedo.com>
    Date: Wed, 7 Nov 2012 14:23:04 +0100
    Subject: [PATCH] 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 | 130 +++++++++++++++++++++++++++++-----------------------
     1 file changed, 73 insertions(+), 57 deletions(-)
    
    diff --git a/gtk/gtktexthandle.c b/gtk/gtktexthandle.c
    index 6c7033b..426fa3a 100644
    a b struct _HandleWindow 
    4646  gint dx;
    4747  gint dy;
    4848  guint dragged : 1;
     49  guint mode_visible : 1;
     50  guint user_visible : 1;
     51  guint has_point : 1;
    4952};
    5053
    5154struct _GtkTextHandlePrivate
    gtk_text_handle_widget_event (GtkWidget *widget, 
    278281}
    279282
    280283static void
    281 _gtk_text_handle_update_window (GtkTextHandle         *handle,
    282                                 GtkTextHandlePosition  pos)
     284_gtk_text_handle_update_window_state (GtkTextHandle         *handle,
     285                                      GtkTextHandlePosition  pos)
    283286{
    284287  GtkTextHandlePrivate *priv;
    285288  HandleWindow *handle_window;
    286   gboolean visible;
    287   gint x, y;
    288289
    289290  priv = handle->priv;
    290291  handle_window = &priv->windows[pos];
    _gtk_text_handle_update_window (GtkTextHandle *handle, 
    292293  if (!handle_window->window)
    293294    return;
    294295
    295   /* Get current state and destroy */
    296   visible = gdk_window_is_visible (handle_window->window);
    297 
    298   if (visible)
     296  if (handle_window->has_point &&
     297      handle_window->mode_visible && handle_window->user_visible)
    299298    {
    300       gint width;
     299      gint x, y, width, height;
    301300
    302       _gtk_text_handle_get_size (handle, &width, NULL);
    303       gdk_window_get_root_coords (handle_window->window,
    304                                   width / 2, 0, &x, &y);
     301      x = handle_window->pointing_to.x;
     302      y = handle_window->pointing_to.y;
     303      _gtk_text_handle_get_size (handle, &width, &height);
     304
     305      if (pos == GTK_TEXT_HANDLE_POSITION_CURSOR)
     306        y += handle_window->pointing_to.height;
     307      else
     308        y -= height;
     309
     310      x -= width / 2;
     311
     312      gdk_window_move_resize (handle_window->window, x, y, width, height);
     313      gdk_window_show (handle_window->window);
    305314    }
     315  else
     316    gdk_window_hide (handle_window->window);
     317}
    306318
    307   gdk_window_destroy (handle_window->window);
     319static void
     320_gtk_text_handle_update_window (GtkTextHandle         *handle,
     321                                GtkTextHandlePosition  pos,
     322                                gboolean               recreate)
     323{
     324  GtkTextHandlePrivate *priv;
     325  HandleWindow *handle_window;
     326  gboolean visible;
     327  gint x, y;
     328
     329  priv = handle->priv;
     330  handle_window = &priv->windows[pos];
    308331
    309   /* Create new window and apply old state */
    310   handle_window->window = _gtk_text_handle_create_window (handle, pos);
     332  if (!handle_window->window)
     333    return;
    311334
    312   if (visible)
     335  if (recreate)
    313336    {
    314       gdk_window_show (handle_window->window);
    315       _gtk_text_handle_set_position (handle, pos,
    316                                      &handle_window->pointing_to);
     337      gdk_window_destroy (handle_window->window);
     338      handle_window->window = _gtk_text_handle_create_window (handle, pos);
    317339    }
     340
     341  _gtk_text_handle_update_window_state (handle, pos);
    318342}
    319343
    320344static void
    _gtk_text_handle_update_windows (GtkTextHandle *handle) 
    323347  GtkTextHandlePrivate *priv = handle->priv;
    324348
    325349  gtk_style_context_invalidate (priv->style_context);
    326   _gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START);
    327   _gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END);
     350  _gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START, FALSE);
     351  _gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END, FALSE);
     352}
     353
     354static void
     355_gtk_text_handle_composited_changed (GtkTextHandle *handle)
     356{
     357  _gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START, TRUE);
     358  _gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END, TRUE);
    328359}
    329360
    330361static void
    gtk_text_handle_constructed (GObject *object) 
    345376                      object);
    346377  priv->composited_changed_id =
    347378    g_signal_connect_swapped (priv->parent, "composited-changed",
    348                               G_CALLBACK (_gtk_text_handle_update_windows),
     379                              G_CALLBACK (_gtk_text_handle_composited_changed),
    349380                              object);
    350381  priv->style_updated_id =
    351382    g_signal_connect_swapped (priv->parent, "style-updated",
    _gtk_text_handle_set_mode (GtkTextHandle *handle, 
    560591  if (priv->mode == mode)
    561592    return;
    562593
     594  priv->mode = mode;
     595
    563596  switch (mode)
    564597    {
    565598    case GTK_TEXT_HANDLE_MODE_CURSOR:
    566       /* Only display one handle */
    567       gdk_window_show (priv->windows[GTK_TEXT_HANDLE_POSITION_CURSOR].window);
    568       gdk_window_hide (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
     599      priv->windows[GTK_TEXT_HANDLE_POSITION_CURSOR].mode_visible = TRUE;
     600      priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].mode_visible = FALSE;
    569601      break;
    570       case GTK_TEXT_HANDLE_MODE_SELECTION:
    571         /* Display both handles */
    572       gdk_window_show (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
    573       gdk_window_show (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
     602    case GTK_TEXT_HANDLE_MODE_SELECTION:
     603      priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].mode_visible = TRUE;
     604      priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].mode_visible = TRUE;
    574605      break;
    575606    case GTK_TEXT_HANDLE_MODE_NONE:
    576607    default:
    577       gdk_window_hide (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
    578       gdk_window_hide (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
     608      priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].mode_visible = FALSE;
     609      priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].mode_visible = FALSE;
    579610      break;
    580611    }
    581612
    582   priv->mode = mode;
    583 
    584613  _gtk_text_handle_update_shape (handle,
    585614                                 priv->windows[GTK_TEXT_HANDLE_POSITION_CURSOR].window,
    586615                                 GTK_TEXT_HANDLE_POSITION_CURSOR);
     616
     617  _gtk_text_handle_update_window_state (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START);
     618  _gtk_text_handle_update_window_state (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END);
    587619}
    588620
    589621GtkTextHandleMode
    _gtk_text_handle_set_position (GtkTextHandle *handle, 
    611643  priv = handle->priv;
    612644  pos = CLAMP (pos, GTK_TEXT_HANDLE_POSITION_CURSOR,
    613645               GTK_TEXT_HANDLE_POSITION_SELECTION_START);
     646  handle_window = &priv->windows[pos];
    614647
    615648  if (!priv->realized)
    616649    return;
    _gtk_text_handle_set_position (GtkTextHandle *handle, 
    620653       pos != GTK_TEXT_HANDLE_POSITION_CURSOR))
    621654    return;
    622655
     656  handle_window->pointing_to = *rect;
     657  handle_window->has_point = TRUE;
    623658  gdk_window_get_root_coords (priv->relative_to,
    624659                              rect->x, rect->y,
    625                               &x, &y);
    626   _gtk_text_handle_get_size (handle, &width, &height);
    627   handle_window = &priv->windows[pos];
    628 
    629   if (pos == GTK_TEXT_HANDLE_POSITION_CURSOR)
    630     y += rect->height;
    631   else
    632     y -= height;
     660                              &handle_window->pointing_to.x,
     661                              &handle_window->pointing_to.y);
    633662
    634   x -= width / 2;
    635 
    636   gdk_window_move (handle_window->window, x, y);
    637   handle_window->pointing_to = *rect;
     663  _gtk_text_handle_update_window_state (handle, pos);
    638664}
    639665
    640666void
    _gtk_text_handle_set_visible (GtkTextHandle *handle, 
    659685  if (!window)
    660686    return;
    661687
    662   if (!visible)
    663     gdk_window_hide (window);
    664   else
    665     {
    666       if (priv->mode == GTK_TEXT_HANDLE_MODE_NONE ||
    667           (priv->mode == GTK_TEXT_HANDLE_MODE_CURSOR &&
    668            pos != GTK_TEXT_HANDLE_POSITION_CURSOR))
    669         return;
    670 
    671       if (!gdk_window_is_visible (window))
    672         gdk_window_show (window);
    673     }
     688  priv->windows[pos].user_visible = visible;
     689  _gtk_text_handle_update_window_state (handle, pos);
    674690}
    675691
    676692gboolean