forked from AuroraMiddleware/gtk
8a599b2582
This changes allocation of the widget trees to happen as a side effect to the GdkSurface::layout signal, which first passes the GtkNative instance where it is then forwarded to the implementations of the GtkNative interface. The implementations of GtkNative are the ones doing the actual gtk_widget_allocate(), and they do so in their GtkNativeClass::layout function.
582 lines
18 KiB
C
582 lines
18 KiB
C
/* GTK - The GIMP Toolkit
|
|
* Copyright © 2012 Carlos Garnacho <carlosg@gnome.org>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "gtkcssnumbervalueprivate.h"
|
|
#include "gtkprivatetypebuiltins.h"
|
|
#include "gtktexthandleprivate.h"
|
|
#include "gtkmarshalers.h"
|
|
#include "gtkprivate.h"
|
|
#include "gtkwindowprivate.h"
|
|
#include "gtkwidgetprivate.h"
|
|
#include "gtkrendericonprivate.h"
|
|
#include "gtkcssboxesimplprivate.h"
|
|
#include "gtkcssnumbervalueprivate.h"
|
|
#include "gtkstylecontextprivate.h"
|
|
#include "gtknativeprivate.h"
|
|
#include "gtkintl.h"
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
enum {
|
|
DRAG_STARTED,
|
|
HANDLE_DRAGGED,
|
|
DRAG_FINISHED,
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
struct _GtkTextHandle
|
|
{
|
|
GtkWidget parent_instance;
|
|
|
|
GdkSurface *surface;
|
|
GskRenderer *renderer;
|
|
GtkEventController *controller;
|
|
GtkWidget *controller_widget;
|
|
|
|
GdkRectangle pointing_to;
|
|
GtkBorder border;
|
|
int dx;
|
|
int dy;
|
|
guint role : 2;
|
|
guint dragged : 1;
|
|
guint mode_visible : 1;
|
|
guint user_visible : 1;
|
|
guint has_point : 1;
|
|
};
|
|
|
|
static void gtk_text_handle_native_interface_init (GtkNativeInterface *iface);
|
|
|
|
static void handle_drag_begin (GtkGestureDrag *gesture,
|
|
double x,
|
|
double y,
|
|
GtkTextHandle *handle);
|
|
static void handle_drag_update (GtkGestureDrag *gesture,
|
|
double offset_x,
|
|
double offset_y,
|
|
GtkWidget *widget);
|
|
static void handle_drag_end (GtkGestureDrag *gesture,
|
|
double offset_x,
|
|
double offset_y,
|
|
GtkTextHandle *handle);
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (GtkTextHandle, gtk_text_handle, GTK_TYPE_WIDGET,
|
|
G_IMPLEMENT_INTERFACE (GTK_TYPE_NATIVE,
|
|
gtk_text_handle_native_interface_init))
|
|
|
|
static guint signals[LAST_SIGNAL] = { 0 };
|
|
|
|
static GdkSurface *
|
|
gtk_text_handle_native_get_surface (GtkNative *native)
|
|
{
|
|
return GTK_TEXT_HANDLE (native)->surface;
|
|
}
|
|
|
|
static GskRenderer *
|
|
gtk_text_handle_native_get_renderer (GtkNative *native)
|
|
{
|
|
return GTK_TEXT_HANDLE (native)->renderer;
|
|
}
|
|
|
|
static void
|
|
gtk_text_handle_native_get_surface_transform (GtkNative *native,
|
|
double *x,
|
|
double *y)
|
|
{
|
|
GtkCssBoxes css_boxes;
|
|
const graphene_rect_t *margin_rect;
|
|
|
|
gtk_css_boxes_init (&css_boxes, GTK_WIDGET (native));
|
|
margin_rect = gtk_css_boxes_get_margin_rect (&css_boxes);
|
|
|
|
*x = - margin_rect->origin.x;
|
|
*y = - margin_rect->origin.y;
|
|
}
|
|
|
|
static void
|
|
gtk_text_handle_get_padding (GtkTextHandle *handle,
|
|
GtkBorder *border)
|
|
{
|
|
GtkWidget *widget = GTK_WIDGET (handle);
|
|
GtkStyleContext *context;
|
|
|
|
context = gtk_widget_get_style_context (widget);
|
|
|
|
border->left = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_PADDING_LEFT), 100);
|
|
border->right = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_PADDING_RIGHT), 100);
|
|
border->top = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_PADDING_TOP), 100);
|
|
border->bottom = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_PADDING_BOTTOM), 100);
|
|
}
|
|
|
|
static void
|
|
gtk_text_handle_present_surface (GtkTextHandle *handle)
|
|
{
|
|
GtkWidget *widget = GTK_WIDGET (handle);
|
|
GdkPopupLayout *layout;
|
|
GdkRectangle rect;
|
|
GtkRequisition req;
|
|
GtkWidget *parent;
|
|
|
|
gtk_widget_get_preferred_size (widget, NULL, &req);
|
|
gtk_text_handle_get_padding (handle, &handle->border);
|
|
|
|
parent = gtk_widget_get_parent (widget);
|
|
gtk_widget_get_surface_allocation (parent, &rect);
|
|
|
|
rect.x += handle->pointing_to.x;
|
|
rect.y += handle->pointing_to.y + handle->pointing_to.height - handle->border.top;
|
|
rect.width = req.width - handle->border.left - handle->border.right;
|
|
rect.height = 1;
|
|
|
|
if (handle->role == GTK_TEXT_HANDLE_ROLE_CURSOR)
|
|
rect.x -= rect.width / 2;
|
|
else if ((handle->role == GTK_TEXT_HANDLE_ROLE_SELECTION_END &&
|
|
gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ||
|
|
(handle->role == GTK_TEXT_HANDLE_ROLE_SELECTION_START &&
|
|
gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL))
|
|
rect.x -= rect.width;
|
|
|
|
layout = gdk_popup_layout_new (&rect,
|
|
GDK_GRAVITY_SOUTH,
|
|
GDK_GRAVITY_NORTH);
|
|
gdk_popup_layout_set_anchor_hints (layout,
|
|
GDK_ANCHOR_FLIP_Y | GDK_ANCHOR_SLIDE_X);
|
|
|
|
gdk_popup_present (GDK_POPUP (handle->surface),
|
|
MAX (req.width, 1),
|
|
MAX (req.height, 1),
|
|
layout);
|
|
gdk_popup_layout_unref (layout);
|
|
}
|
|
|
|
static void
|
|
gtk_text_handle_native_check_resize (GtkNative *native)
|
|
{
|
|
GtkTextHandle *handle = GTK_TEXT_HANDLE (native);
|
|
GtkWidget *widget = GTK_WIDGET (native);
|
|
|
|
if (!_gtk_widget_get_alloc_needed (widget))
|
|
gtk_widget_ensure_allocate (widget);
|
|
else if (gtk_widget_get_visible (widget))
|
|
gtk_text_handle_present_surface (handle);
|
|
}
|
|
|
|
static void
|
|
gtk_text_handle_native_layout (GtkNative *native,
|
|
int width,
|
|
int height)
|
|
{
|
|
GtkWidget *widget = GTK_WIDGET (native);
|
|
|
|
if (_gtk_widget_get_alloc_needed (widget))
|
|
gtk_widget_allocate (widget, width, height, -1, NULL);
|
|
else
|
|
gtk_widget_ensure_allocate (widget);
|
|
}
|
|
|
|
static void
|
|
gtk_text_handle_native_interface_init (GtkNativeInterface *iface)
|
|
{
|
|
iface->get_surface = gtk_text_handle_native_get_surface;
|
|
iface->get_renderer = gtk_text_handle_native_get_renderer;
|
|
iface->get_surface_transform = gtk_text_handle_native_get_surface_transform;
|
|
iface->check_resize = gtk_text_handle_native_check_resize;
|
|
iface->layout = gtk_text_handle_native_layout;
|
|
}
|
|
|
|
static gboolean
|
|
surface_render (GdkSurface *surface,
|
|
cairo_region_t *region,
|
|
GtkTextHandle *handle)
|
|
{
|
|
gtk_widget_render (GTK_WIDGET (handle), surface, region);
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
surface_mapped_changed (GtkWidget *widget)
|
|
{
|
|
GtkTextHandle *handle = GTK_TEXT_HANDLE (widget);
|
|
|
|
gtk_widget_set_visible (widget, gdk_surface_get_mapped (handle->surface));
|
|
}
|
|
|
|
static void
|
|
gtk_text_handle_snapshot (GtkWidget *widget,
|
|
GtkSnapshot *snapshot)
|
|
{
|
|
GtkCssStyle *style = gtk_css_node_get_style (gtk_widget_get_css_node (widget));
|
|
|
|
gtk_css_style_snapshot_icon (style,
|
|
snapshot,
|
|
gtk_widget_get_width (widget),
|
|
gtk_widget_get_height (widget));
|
|
}
|
|
|
|
static void
|
|
gtk_text_handle_realize (GtkWidget *widget)
|
|
{
|
|
GtkTextHandle *handle = GTK_TEXT_HANDLE (widget);
|
|
GdkSurface *parent_surface;
|
|
GtkWidget *parent;
|
|
|
|
parent = gtk_widget_get_parent (widget);
|
|
parent_surface = gtk_native_get_surface (gtk_widget_get_native (parent));
|
|
|
|
handle->surface = gdk_surface_new_popup (parent_surface, FALSE);
|
|
gdk_surface_set_widget (handle->surface, widget);
|
|
gdk_surface_set_input_region (handle->surface, cairo_region_create ());
|
|
|
|
g_signal_connect_swapped (handle->surface, "notify::mapped",
|
|
G_CALLBACK (surface_mapped_changed), widget);
|
|
g_signal_connect (handle->surface, "render", G_CALLBACK (surface_render), widget);
|
|
|
|
GTK_WIDGET_CLASS (gtk_text_handle_parent_class)->realize (widget);
|
|
|
|
handle->renderer = gsk_renderer_new_for_surface (handle->surface);
|
|
|
|
gtk_native_realize (GTK_NATIVE (handle));
|
|
}
|
|
|
|
static void
|
|
gtk_text_handle_unrealize (GtkWidget *widget)
|
|
{
|
|
GtkTextHandle *handle = GTK_TEXT_HANDLE (widget);
|
|
|
|
gtk_native_unrealize (GTK_NATIVE (handle));
|
|
|
|
GTK_WIDGET_CLASS (gtk_text_handle_parent_class)->unrealize (widget);
|
|
|
|
gsk_renderer_unrealize (handle->renderer);
|
|
g_clear_object (&handle->renderer);
|
|
|
|
g_signal_handlers_disconnect_by_func (handle->surface, surface_render, widget);
|
|
g_signal_handlers_disconnect_by_func (handle->surface, surface_mapped_changed, widget);
|
|
|
|
gdk_surface_set_widget (handle->surface, NULL);
|
|
gdk_surface_destroy (handle->surface);
|
|
g_clear_object (&handle->surface);
|
|
}
|
|
|
|
static void
|
|
text_handle_set_up_gesture (GtkTextHandle *handle)
|
|
{
|
|
GtkNative *native;
|
|
|
|
/* The drag gesture is hooked on the parent native */
|
|
native = gtk_widget_get_native (gtk_widget_get_parent (GTK_WIDGET (handle)));
|
|
handle->controller_widget = GTK_WIDGET (native);
|
|
|
|
handle->controller = GTK_EVENT_CONTROLLER (gtk_gesture_drag_new ());
|
|
gtk_event_controller_set_propagation_phase (handle->controller,
|
|
GTK_PHASE_CAPTURE);
|
|
g_signal_connect (handle->controller, "drag-begin",
|
|
G_CALLBACK (handle_drag_begin), handle);
|
|
g_signal_connect (handle->controller, "drag-update",
|
|
G_CALLBACK (handle_drag_update), handle);
|
|
g_signal_connect (handle->controller, "drag-end",
|
|
G_CALLBACK (handle_drag_end), handle);
|
|
|
|
gtk_widget_add_controller (handle->controller_widget, handle->controller);
|
|
}
|
|
|
|
static void
|
|
gtk_text_handle_map (GtkWidget *widget)
|
|
{
|
|
GtkTextHandle *handle = GTK_TEXT_HANDLE (widget);
|
|
|
|
GTK_WIDGET_CLASS (gtk_text_handle_parent_class)->map (widget);
|
|
|
|
if (handle->has_point)
|
|
{
|
|
gtk_text_handle_present_surface (handle);
|
|
text_handle_set_up_gesture (handle);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gtk_text_handle_unmap (GtkWidget *widget)
|
|
{
|
|
GtkTextHandle *handle = GTK_TEXT_HANDLE (widget);
|
|
|
|
GTK_WIDGET_CLASS (gtk_text_handle_parent_class)->unmap (widget);
|
|
gdk_surface_hide (handle->surface);
|
|
|
|
if (handle->controller_widget)
|
|
{
|
|
gtk_widget_remove_controller (handle->controller_widget,
|
|
handle->controller);
|
|
handle->controller_widget = NULL;
|
|
handle->controller = NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gtk_text_handle_measure (GtkWidget *widget,
|
|
GtkOrientation orientation,
|
|
int for_size,
|
|
int *minimum,
|
|
int *natural,
|
|
int *minimum_baseline,
|
|
int *natural_baseline)
|
|
{
|
|
*natural = 0;
|
|
*minimum = 0;
|
|
*minimum_baseline = -1;
|
|
*natural_baseline = -1;
|
|
}
|
|
|
|
static void
|
|
gtk_text_handle_class_init (GtkTextHandleClass *klass)
|
|
{
|
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
widget_class->snapshot = gtk_text_handle_snapshot;
|
|
widget_class->realize = gtk_text_handle_realize;
|
|
widget_class->unrealize = gtk_text_handle_unrealize;
|
|
widget_class->map = gtk_text_handle_map;
|
|
widget_class->unmap = gtk_text_handle_unmap;
|
|
widget_class->measure = gtk_text_handle_measure;
|
|
|
|
signals[HANDLE_DRAGGED] =
|
|
g_signal_new (I_("handle-dragged"),
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
G_SIGNAL_RUN_LAST, 0,
|
|
NULL, NULL,
|
|
_gtk_marshal_VOID__INT_INT,
|
|
G_TYPE_NONE, 2,
|
|
G_TYPE_INT, G_TYPE_INT);
|
|
signals[DRAG_STARTED] =
|
|
g_signal_new (I_("drag-started"),
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
G_SIGNAL_RUN_LAST, 0,
|
|
NULL, NULL,
|
|
NULL,
|
|
G_TYPE_NONE, 0, G_TYPE_NONE);
|
|
signals[DRAG_FINISHED] =
|
|
g_signal_new (I_("drag-finished"),
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
G_SIGNAL_RUN_LAST, 0,
|
|
NULL, NULL,
|
|
NULL,
|
|
G_TYPE_NONE, 0, G_TYPE_NONE);
|
|
|
|
gtk_widget_class_set_css_name (widget_class, I_("cursor-handle"));
|
|
}
|
|
|
|
/* Relative to pointing_to x/y */
|
|
static void
|
|
handle_get_input_extents (GtkTextHandle *handle,
|
|
GtkBorder *border)
|
|
{
|
|
GtkWidget *widget = GTK_WIDGET (handle);
|
|
|
|
if (handle->role == GTK_TEXT_HANDLE_ROLE_CURSOR)
|
|
{
|
|
border->left = (-gtk_widget_get_width (widget) / 2) - handle->border.left;
|
|
border->right = (gtk_widget_get_width (widget) / 2) + handle->border.right;
|
|
}
|
|
else if ((handle->role == GTK_TEXT_HANDLE_ROLE_SELECTION_END &&
|
|
gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ||
|
|
(handle->role == GTK_TEXT_HANDLE_ROLE_SELECTION_START &&
|
|
gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL))
|
|
{
|
|
border->left = -gtk_widget_get_width (widget) - handle->border.left;
|
|
border->right = handle->border.right;
|
|
}
|
|
else
|
|
{
|
|
border->left = -handle->border.left;
|
|
border->right = gtk_widget_get_width (widget) + handle->border.right;
|
|
}
|
|
|
|
border->top = - handle->border.top;
|
|
border->bottom = gtk_widget_get_height (widget) + handle->border.bottom;
|
|
}
|
|
|
|
static void
|
|
handle_drag_begin (GtkGestureDrag *gesture,
|
|
double x,
|
|
double y,
|
|
GtkTextHandle *handle)
|
|
{
|
|
GtkBorder input_extents;
|
|
double widget_x, widget_y;
|
|
|
|
x -= handle->pointing_to.x;
|
|
y -= handle->pointing_to.y;
|
|
|
|
/* Figure out if the coordinates fall into the handle input area, coordinates
|
|
* are relative to the parent widget.
|
|
*/
|
|
handle_get_input_extents (handle, &input_extents);
|
|
gtk_widget_translate_coordinates (handle->controller_widget,
|
|
gtk_widget_get_parent (GTK_WIDGET (handle)),
|
|
x, y, &widget_x, &widget_y);
|
|
|
|
if (widget_x < input_extents.left || widget_x >= input_extents.right ||
|
|
widget_y < input_extents.top || widget_y >= input_extents.bottom)
|
|
{
|
|
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
|
|
return;
|
|
}
|
|
|
|
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
|
|
/* Store untranslated coordinates here, so ::update does not need
|
|
* an extra translation
|
|
*/
|
|
handle->dx = x;
|
|
handle->dy = y;
|
|
handle->dragged = TRUE;
|
|
g_signal_emit (handle, signals[DRAG_STARTED], 0);
|
|
}
|
|
|
|
static void
|
|
handle_drag_update (GtkGestureDrag *gesture,
|
|
double offset_x,
|
|
double offset_y,
|
|
GtkWidget *widget)
|
|
{
|
|
GtkTextHandle *handle = GTK_TEXT_HANDLE (widget);
|
|
double start_x, start_y;
|
|
int x, y;
|
|
|
|
gtk_gesture_drag_get_start_point (gesture, &start_x, &start_y);
|
|
|
|
x = start_x + offset_x - handle->dx;
|
|
y = start_y + offset_y - handle->dy + (handle->pointing_to.height / 2);
|
|
g_signal_emit (widget, signals[HANDLE_DRAGGED], 0, x, y);
|
|
}
|
|
|
|
static void
|
|
handle_drag_end (GtkGestureDrag *gesture,
|
|
double offset_x,
|
|
double offset_y,
|
|
GtkTextHandle *handle)
|
|
{
|
|
GdkEventSequence *sequence;
|
|
GtkEventSequenceState state;
|
|
|
|
sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
|
|
state = gtk_gesture_get_sequence_state (GTK_GESTURE (gesture), sequence);
|
|
|
|
if (state == GTK_EVENT_SEQUENCE_CLAIMED)
|
|
g_signal_emit (handle, signals[DRAG_FINISHED], 0);
|
|
|
|
handle->dragged = FALSE;
|
|
}
|
|
|
|
static void
|
|
gtk_text_handle_update_for_role (GtkTextHandle *handle)
|
|
{
|
|
GtkWidget *widget = GTK_WIDGET (handle);
|
|
|
|
if (handle->role == GTK_TEXT_HANDLE_ROLE_CURSOR)
|
|
{
|
|
gtk_widget_remove_css_class (widget, "top");
|
|
gtk_widget_add_css_class (widget, "bottom");
|
|
gtk_widget_add_css_class (widget, "insertion-cursor");
|
|
}
|
|
else if (handle->role == GTK_TEXT_HANDLE_ROLE_SELECTION_END)
|
|
{
|
|
gtk_widget_remove_css_class (widget, "top");
|
|
gtk_widget_add_css_class (widget, "bottom");
|
|
gtk_widget_remove_css_class (widget, "insertion-cursor");
|
|
}
|
|
else if (handle->role == GTK_TEXT_HANDLE_ROLE_SELECTION_START)
|
|
{
|
|
gtk_widget_add_css_class (widget, "top");
|
|
gtk_widget_remove_css_class (widget, "bottom");
|
|
gtk_widget_remove_css_class (widget, "insertion-cursor");
|
|
}
|
|
|
|
gtk_widget_queue_draw (widget);
|
|
}
|
|
|
|
static void
|
|
gtk_text_handle_init (GtkTextHandle *handle)
|
|
{
|
|
gtk_text_handle_update_for_role (handle);
|
|
}
|
|
|
|
GtkTextHandle *
|
|
gtk_text_handle_new (GtkWidget *parent)
|
|
{
|
|
GtkTextHandle *handle;
|
|
|
|
handle = g_object_new (GTK_TYPE_TEXT_HANDLE, NULL);
|
|
gtk_widget_set_parent (GTK_WIDGET (handle), parent);
|
|
|
|
return handle;
|
|
}
|
|
|
|
void
|
|
gtk_text_handle_set_role (GtkTextHandle *handle,
|
|
GtkTextHandleRole role)
|
|
{
|
|
g_return_if_fail (GTK_IS_TEXT_HANDLE (handle));
|
|
|
|
if (handle->role == role)
|
|
return;
|
|
|
|
handle->role = role;
|
|
gtk_text_handle_update_for_role (handle);
|
|
|
|
if (gtk_widget_get_visible (GTK_WIDGET (handle)))
|
|
{
|
|
if (handle->has_point)
|
|
gtk_text_handle_present_surface (handle);
|
|
}
|
|
}
|
|
|
|
GtkTextHandleRole
|
|
gtk_text_handle_get_role (GtkTextHandle *handle)
|
|
{
|
|
g_return_val_if_fail (GTK_IS_TEXT_HANDLE (handle), GTK_TEXT_HANDLE_ROLE_CURSOR);
|
|
|
|
return handle->role;
|
|
}
|
|
|
|
void
|
|
gtk_text_handle_set_position (GtkTextHandle *handle,
|
|
const GdkRectangle *rect)
|
|
{
|
|
g_return_if_fail (GTK_IS_TEXT_HANDLE (handle));
|
|
|
|
if (handle->pointing_to.x == rect->x &&
|
|
handle->pointing_to.y == rect->y &&
|
|
handle->pointing_to.width == rect->width &&
|
|
handle->pointing_to.height == rect->height)
|
|
return;
|
|
|
|
handle->pointing_to = *rect;
|
|
handle->has_point = TRUE;
|
|
|
|
if (gtk_widget_is_visible (GTK_WIDGET (handle)))
|
|
gtk_text_handle_present_surface (handle);
|
|
}
|
|
|
|
gboolean
|
|
gtk_text_handle_get_is_dragged (GtkTextHandle *handle)
|
|
{
|
|
g_return_val_if_fail (GTK_IS_TEXT_HANDLE (handle), FALSE);
|
|
|
|
return handle->dragged;
|
|
}
|