gint dx;
gint dy;
guint dragged : 1;
+ guint mode_visible : 1;
+ guint user_visible : 1;
+ guint has_point : 1;
};
struct _GtkTextHandlePrivate
cairo_set_source_rgba (cr, 0, 0, 0, 0);
cairo_paint (cr);
+ if (pos == GTK_TEXT_HANDLE_POSITION_SELECTION_END)
+ cairo_translate (cr, 0, priv->windows[pos].pointing_to.height);
+
gtk_style_context_save (priv->style_context);
gtk_style_context_add_class (priv->style_context,
GTK_STYLE_CLASS_CURSOR_HANDLE);
GtkTextHandlePosition pos)
{
GtkTextHandlePrivate *priv;
+ cairo_rectangle_int_t rect;
cairo_surface_t *surface;
cairo_region_t *region;
cairo_t *cr;
else
gdk_window_shape_combine_region (window, region, 0, 0);
+ cairo_region_get_extents (region, &rect);
+ cairo_region_destroy (region);
+
+ /* Preserve x/width, but extend input shape
+ * vertically to all window height */
+ rect.y = 0;
+ rect.height = gdk_window_get_height (window);
+ region = cairo_region_create_rectangle (&rect);
+
gdk_window_input_shape_combine_region (window, region, 0, 0);
cairo_surface_destroy (surface);
window = gdk_window_new (gtk_widget_get_root_window (priv->parent),
&attributes, mask);
- gdk_window_set_user_data (window, priv->parent);
+ gtk_widget_register_window (priv->parent, window);
gdk_window_set_background_rgba (window, &bg);
_gtk_text_handle_update_shape (handle, window, pos);
{
GtkTextHandlePrivate *priv;
GtkTextHandlePosition pos;
+ HandleWindow *handle_window;
priv = handle->priv;
else
return FALSE;
- _gtk_text_handle_draw (handle, cr, pos);
- return TRUE;
+ handle_window = &priv->windows[pos];
+ if (gdk_window_is_visible (handle_window->window))
+ _gtk_text_handle_draw (handle, cr, pos);
+
+ return FALSE;
}
static gboolean
if (pos == GTK_TEXT_HANDLE_POSITION_SELECTION_START)
y += height;
+ y += priv->windows[pos].pointing_to.height / 2;
+
g_signal_emit (handle, signals[HANDLE_DRAGGED], 0, pos, x, y);
}
}
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];
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;
- _gtk_text_handle_get_size (handle, &width, NULL);
- gdk_window_get_root_coords (handle_window->window,
- width / 2, 0, &x, &y);
+ x = handle_window->pointing_to.x;
+ y = handle_window->pointing_to.y;
+ _gtk_text_handle_get_size (handle, &width, &height);
+
+ if (pos != GTK_TEXT_HANDLE_POSITION_CURSOR)
+ y -= height;
+
+ height += handle_window->pointing_to.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);
+}
- 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 (!handle_window->window)
+ return;
- if (visible)
+ 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
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
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",
g_object_unref (priv->relative_to);
if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window)
- gdk_window_destroy (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
+ {
+ gtk_widget_unregister_window (priv->parent,
+ priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
+ gdk_window_destroy (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
+ }
if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window)
- gdk_window_destroy (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
+ {
+ gtk_widget_unregister_window (priv->parent,
+ priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
+ gdk_window_destroy (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
+ }
if (g_signal_handler_is_connected (priv->parent, priv->draw_signal_id))
g_signal_handler_disconnect (priv->parent, priv->draw_signal_id);
if (priv->relative_to)
{
+ gtk_widget_unregister_window (priv->parent,
+ priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
gdk_window_destroy (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
+ gtk_widget_unregister_window (priv->parent,
+ priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
gdk_window_destroy (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
g_object_unref (priv->relative_to);
}
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_shape (handle,
+ priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window,
+ GTK_TEXT_HANDLE_POSITION_SELECTION_START);
+
+ _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
GdkRectangle *rect)
{
GtkTextHandlePrivate *priv;
- gint x, y, width, height;
HandleWindow *handle_window;
+ gboolean size_changed;
g_return_if_fail (GTK_IS_TEXT_HANDLE (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;
pos != GTK_TEXT_HANDLE_POSITION_CURSOR))
return;
+ size_changed = (rect->width != handle_window->pointing_to.width ||
+ rect->height != handle_window->pointing_to.height);
+
+ 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;
+ &handle_window->pointing_to.x,
+ &handle_window->pointing_to.y);
- x -= width / 2;
+ _gtk_text_handle_update_window_state (handle, pos);
- gdk_window_move (handle_window->window, x, y);
- handle_window->pointing_to = *rect;
+ if (size_changed)
+ _gtk_text_handle_update_shape (handle, handle_window->window, pos);
}
void
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))
+ _gtk_text_handle_update_shape (handle, window, pos);
- 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