summaryrefslogtreecommitdiff
path: root/gtk/gtktexthandle.c
diff options
context:
space:
mode:
authorCarlos Garnacho <carlos@lanedo.com>2012-11-07 14:23:04 +0100
committerMatthias Clasen <mclasen@redhat.com>2013-03-05 16:47:58 -0500
commitd97861bd8b338c3d25d7ffb5496edee9eee9bfbb (patch)
tree22387c4479285a1a0abd3a538fb295f4a07ff0d0 /gtk/gtktexthandle.c
parentbfbb96605fe52dd20e4ba9b89b8bcbe929d58b3c (diff)
downloadgtk+-d97861bd8b338c3d25d7ffb5496edee9eee9bfbb.tar.gz
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.
Diffstat (limited to 'gtk/gtktexthandle.c')
-rw-r--r--gtk/gtktexthandle.c131
1 files changed, 72 insertions, 59 deletions
diff --git a/gtk/gtktexthandle.c b/gtk/gtktexthandle.c
index 8298cdf941..fd1d966482 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