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