* 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
*/
#include "config.h"
+
#include <string.h>
#define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
#include "gtkmenuitem.h"
#include "gtkseparatormenuitem.h"
#include "gtksettings.h"
+#include "gtkselectionprivate.h"
#include "gtkstock.h"
-#include "gtksizerequest.h"
#include "gtktextbufferrichtext.h"
#include "gtktextdisplay.h"
#include "gtktextview.h"
#include "gtkimmulticontext.h"
-#include "gdk/gdkkeysyms.h"
#include "gtkprivate.h"
#include "gtktextutil.h"
+#include "gtkwidgetprivate.h"
#include "gtkwindow.h"
+#include "gtkscrollable.h"
+#include "gtktypebuiltins.h"
+#include "gtktexthandleprivate.h"
+#include "gtkstylecontextprivate.h"
+#include "gtkcssstylepropertyprivate.h"
+
+#include "a11y/gtktextviewaccessibleprivate.h"
+
+/**
+ * SECTION:gtktextview
+ * @Short_description: Widget that displays a GtkTextBuffer
+ * @Title: GtkTextView
+ * @See_also: #GtkTextBuffer, #GtkTextIter
+ *
+ * You may wish to begin by reading the <link linkend="TextWidget">text widget
+ * conceptual overview</link> which gives an overview of all the objects and data
+ * types related to the text widget and how they work together.
+ */
/* How scrolling, validation, exposes, etc. work.
GdkDevice *grab_device;
GdkDevice *dnd_device;
- guint selection_drag_handler;
- guint scroll_timeout;
+ gulong selection_drag_handler;
+ GtkTextHandle *text_handle;
GtkTextWindow *text_window;
GtkTextWindow *left_window;
* FIXME: This could be done in a simpler way by
* consulting the above width/height of the buffer + some
* padding values, however all of this request code needs
- * to be changed to use GtkSizeRequestIface and deserves
+ * to be changed to use GtkWidget Iface and deserves
* more attention.
*/
GtkRequisition cached_size_request;
GtkTextMark *first_para_mark; /* Mark at the beginning of the first onscreen paragraph */
gint first_para_pixels; /* Offset of top of screen in the first onscreen paragraph */
- GtkTextMark *dnd_mark;
guint blink_timeout;
+ guint scroll_timeout;
guint first_validate_idle; /* Idle to revalidate onscreen portion, runs before resize */
guint incremental_validate_idle; /* Idle to revalidate offscreen portions, runs after redraw */
+ gint pending_place_cursor_button;
+
+ GtkTextMark *dnd_mark;
+
GtkIMContext *im_context;
GtkWidget *popup_menu;
GtkTextPendingScroll *pending_scroll;
- gint pending_place_cursor_button;
-
/* Default style settings */
gint pixels_above_lines;
gint pixels_below_lines;
guint overwrite_mode : 1;
guint cursor_visible : 1;
- /* if we have reset the IM since the last character entered */
+ /* if we have reset the IM since the last character entered */
guint need_im_reset : 1;
guint accepts_tab : 1;
guint mouse_cursor_obscured : 1;
guint scroll_after_paste : 1;
+
+ /* GtkScrollablePolicy needs to be checked when
+ * driving the scrollable adjustment values */
+ guint hscroll_policy : 1;
+ guint vscroll_policy : 1;
+ guint cursor_handle_dragged : 1;
+ guint selection_handle_dragged : 1;
};
struct _GtkTextPendingScroll
enum
{
- SET_SCROLL_ADJUSTMENTS,
POPULATE_POPUP,
MOVE_CURSOR,
PAGE_HORIZONTALLY,
PROP_BUFFER,
PROP_OVERWRITE,
PROP_ACCEPTS_TAB,
- PROP_IM_MODULE
+ PROP_IM_MODULE,
+ PROP_HADJUSTMENT,
+ PROP_VADJUSTMENT,
+ PROP_HSCROLL_POLICY,
+ PROP_VSCROLL_POLICY,
+ PROP_INPUT_PURPOSE,
+ PROP_INPUT_HINTS
};
-static void gtk_text_view_destroy (GtkObject *object);
static void gtk_text_view_finalize (GObject *object);
static void gtk_text_view_set_property (GObject *object,
guint prop_id,
guint prop_id,
GValue *value,
GParamSpec *pspec);
+static void gtk_text_view_destroy (GtkWidget *widget);
static void gtk_text_view_size_request (GtkWidget *widget,
GtkRequisition *requisition);
+static void gtk_text_view_get_preferred_width (GtkWidget *widget,
+ gint *minimum,
+ gint *natural);
+static void gtk_text_view_get_preferred_height (GtkWidget *widget,
+ gint *minimum,
+ gint *natural);
static void gtk_text_view_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static void gtk_text_view_realize (GtkWidget *widget);
static void gtk_text_view_unrealize (GtkWidget *widget);
-static void gtk_text_view_style_set (GtkWidget *widget,
- GtkStyle *previous_style);
+static void gtk_text_view_style_updated (GtkWidget *widget);
static void gtk_text_view_direction_changed (GtkWidget *widget,
GtkTextDirection previous_direction);
static void gtk_text_view_grab_notify (GtkWidget *widget,
gboolean was_grabbed);
-static void gtk_text_view_state_changed (GtkWidget *widget,
- GtkStateType previous_state);
+static void gtk_text_view_state_flags_changed (GtkWidget *widget,
+ GtkStateFlags previous_state);
static gint gtk_text_view_event (GtkWidget *widget,
GdkEvent *event);
GdkEventFocus *event);
static gint gtk_text_view_motion_event (GtkWidget *widget,
GdkEventMotion *event);
-static gint gtk_text_view_expose_event (GtkWidget *widget,
- GdkEventExpose *expose);
-static void gtk_text_view_draw_focus (GtkWidget *widget);
+static gint gtk_text_view_draw (GtkWidget *widget,
+ cairo_t *cr);
+static void gtk_text_view_draw_focus (GtkWidget *widget,
+ cairo_t *cr);
static gboolean gtk_text_view_focus (GtkWidget *widget,
GtkDirectionType direction);
-static void gtk_text_view_move_focus (GtkWidget *widget,
- GtkDirectionType direction_type);
static void gtk_text_view_select_all (GtkWidget *widget,
gboolean select);
-
+static gboolean get_middle_click_paste (GtkTextView *text_view);
/* Source side drag signals */
static void gtk_text_view_drag_begin (GtkWidget *widget,
guint info,
guint time);
-static void gtk_text_view_set_scroll_adjustments (GtkTextView *text_view,
- GtkAdjustment *hadj,
- GtkAdjustment *vadj);
static gboolean gtk_text_view_popup_menu (GtkWidget *widget);
static void gtk_text_view_move_cursor (GtkTextView *text_view,
GtkMovementStep step,
gint count,
gboolean extend_selection);
-static gboolean gtk_text_view_move_viewport (GtkTextView *text_view,
+static void gtk_text_view_move_viewport (GtkTextView *text_view,
GtkScrollStep step,
gint count);
static void gtk_text_view_set_anchor (GtkTextView *text_view);
static void gtk_text_view_paste_clipboard (GtkTextView *text_view);
static void gtk_text_view_toggle_overwrite (GtkTextView *text_view);
static void gtk_text_view_toggle_cursor_visible (GtkTextView *text_view);
-static void gtk_text_view_compat_move_focus(GtkTextView *text_view,
- GtkDirectionType direction_type);
+
static void gtk_text_view_unselect (GtkTextView *text_view);
static void gtk_text_view_validate_onscreen (GtkTextView *text_view);
GtkTextIter *iter);
static void gtk_text_view_update_layout_width (GtkTextView *text_view);
static void gtk_text_view_set_attributes_from_style (GtkTextView *text_view,
- GtkTextAttributes *values,
- GtkStyle *style);
+ GtkTextAttributes *values);
static void gtk_text_view_ensure_layout (GtkTextView *text_view);
static void gtk_text_view_destroy_layout (GtkTextView *text_view);
static void gtk_text_view_check_keymap_direction (GtkTextView *text_view);
static void gtk_text_view_stop_cursor_blink (GtkTextView *text_view);
static void gtk_text_view_reset_blink_time (GtkTextView *text_view);
-static void gtk_text_view_value_changed (GtkAdjustment *adj,
+static void gtk_text_view_value_changed (GtkAdjustment *adjustment,
GtkTextView *view);
static void gtk_text_view_commit_handler (GtkIMContext *context,
const gchar *str,
static void gtk_text_view_paste_done_handler (GtkTextBuffer *buffer,
GtkClipboard *clipboard,
gpointer data);
-static void gtk_text_view_get_cursor_location (GtkTextView *text_view,
- GdkRectangle *pos);
+static void gtk_text_view_buffer_changed_handler (GtkTextBuffer *buffer,
+ gpointer data);
static void gtk_text_view_get_virtual_cursor_pos (GtkTextView *text_view,
GtkTextIter *cursor,
gint *x,
gint x,
gint y);
-static GtkAdjustment* get_hadjustment (GtkTextView *text_view);
-static GtkAdjustment* get_vadjustment (GtkTextView *text_view);
-
static void gtk_text_view_do_popup (GtkTextView *text_view,
GdkEventButton *event);
static void gtk_text_view_invalidate (GtkTextView *text_view);
static void gtk_text_view_flush_first_validate (GtkTextView *text_view);
+static void gtk_text_view_set_hadjustment (GtkTextView *text_view,
+ GtkAdjustment *adjustment);
+static void gtk_text_view_set_vadjustment (GtkTextView *text_view,
+ GtkAdjustment *adjustment);
+static void gtk_text_view_set_hadjustment_values (GtkTextView *text_view);
+static void gtk_text_view_set_vadjustment_values (GtkTextView *text_view);
+
static void gtk_text_view_update_im_spot_location (GtkTextView *text_view);
/* Container methods */
GtkCallback callback,
gpointer callback_data);
+/* GtkTextHandle handlers */
+static void gtk_text_view_handle_dragged (GtkTextHandle *handle,
+ GtkTextHandlePosition pos,
+ gint x,
+ gint y,
+ GtkTextView *text_view);
+static void gtk_text_view_update_handles (GtkTextView *text_view,
+ GtkTextHandleMode mode);
+
/* FIXME probably need the focus methods. */
typedef struct _GtkTextViewChild GtkTextViewChild;
static guint signals[LAST_SIGNAL] = { 0 };
+static gboolean test_touchscreen = FALSE;
-G_DEFINE_TYPE (GtkTextView, gtk_text_view, GTK_TYPE_CONTAINER)
+G_DEFINE_TYPE_WITH_CODE (GtkTextView, gtk_text_view, GTK_TYPE_CONTAINER,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
static void
add_move_binding (GtkBindingSet *binding_set,
gtk_text_view_class_init (GtkTextViewClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
GtkBindingSet *binding_set;
*/
gobject_class->set_property = gtk_text_view_set_property;
gobject_class->get_property = gtk_text_view_get_property;
-
- object_class->destroy = gtk_text_view_destroy;
gobject_class->finalize = gtk_text_view_finalize;
+ widget_class->destroy = gtk_text_view_destroy;
widget_class->realize = gtk_text_view_realize;
widget_class->unrealize = gtk_text_view_unrealize;
- widget_class->style_set = gtk_text_view_style_set;
+ widget_class->style_updated = gtk_text_view_style_updated;
widget_class->direction_changed = gtk_text_view_direction_changed;
widget_class->grab_notify = gtk_text_view_grab_notify;
- widget_class->state_changed = gtk_text_view_state_changed;
- widget_class->size_request = gtk_text_view_size_request;
+ widget_class->state_flags_changed = gtk_text_view_state_flags_changed;
+ widget_class->get_preferred_width = gtk_text_view_get_preferred_width;
+ widget_class->get_preferred_height = gtk_text_view_get_preferred_height;
widget_class->size_allocate = gtk_text_view_size_allocate;
widget_class->event = gtk_text_view_event;
widget_class->key_press_event = gtk_text_view_key_press_event;
widget_class->focus_in_event = gtk_text_view_focus_in_event;
widget_class->focus_out_event = gtk_text_view_focus_out_event;
widget_class->motion_notify_event = gtk_text_view_motion_event;
- widget_class->expose_event = gtk_text_view_expose_event;
+ widget_class->draw = gtk_text_view_draw;
widget_class->focus = gtk_text_view_focus;
-
- /* need to override the base class function via override_class_handler,
- * because the signal slot is not available in GtkWidgetCLass
- */
- g_signal_override_class_handler ("move-focus",
- GTK_TYPE_TEXT_VIEW,
- G_CALLBACK (gtk_text_view_move_focus));
-
widget_class->drag_begin = gtk_text_view_drag_begin;
widget_class->drag_end = gtk_text_view_drag_end;
widget_class->drag_data_get = gtk_text_view_drag_data_get;
klass->copy_clipboard = gtk_text_view_copy_clipboard;
klass->paste_clipboard = gtk_text_view_paste_clipboard;
klass->toggle_overwrite = gtk_text_view_toggle_overwrite;
- klass->move_focus = gtk_text_view_compat_move_focus;
- klass->set_scroll_adjustments = gtk_text_view_set_scroll_adjustments;
/*
* Properties
/**
* GtkTextView:im-module:
*
- * Which IM (input method) module should be used for this entry.
+ * Which IM (input method) module should be used for this text_view.
* See #GtkIMContext.
*
* Setting this to a non-%NULL value overrides the
NULL,
GTK_PARAM_READWRITE));
+ /**
+ * GtkTextView:input-purpose:
+ *
+ * The purpose of this text field.
+ *
+ * This property can be used by on-screen keyboards and other input
+ * methods to adjust their behaviour.
+ *
+ * Since: 3.6
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_INPUT_PURPOSE,
+ g_param_spec_enum ("input-purpose",
+ P_("Purpose"),
+ P_("Purpose of the text field"),
+ GTK_TYPE_INPUT_PURPOSE,
+ GTK_INPUT_PURPOSE_FREE_FORM,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GtkTextView:input-hints:
+ *
+ * Additional hints (beyond #GtkTextView:input-purpose) that
+ * allow input methods to fine-tune their behaviour.
+ *
+ * Since: 3.6
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_INPUT_HINTS,
+ g_param_spec_flags ("input-hints",
+ P_("hints"),
+ P_("Hints for the text field behaviour"),
+ GTK_TYPE_INPUT_HINTS,
+ GTK_INPUT_HINT_NONE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /* GtkScrollable interface */
+ g_object_class_override_property (gobject_class, PROP_HADJUSTMENT, "hadjustment");
+ g_object_class_override_property (gobject_class, PROP_VADJUSTMENT, "vadjustment");
+ g_object_class_override_property (gobject_class, PROP_HSCROLL_POLICY, "hscroll-policy");
+ g_object_class_override_property (gobject_class, PROP_VSCROLL_POLICY, "vscroll-policy");
+
/*
* Style properties
*/
_gtk_marshal_VOID__VOID,
G_TYPE_NONE, 0);
- /**
- * GtkTextView::set-scroll-adjustments
- * @horizontal: the horizontal #GtkAdjustment
- * @vertical: the vertical #GtkAdjustment
- *
- * Set the scroll adjustments for the text view. Usually scrolled containers
- * like #GtkScrolledWindow will emit this signal to connect two instances
- * of #GtkScrollbar to the scroll directions of the #GtkTextView.
- */
- signals[SET_SCROLL_ADJUSTMENTS] =
- g_signal_new (I_("set-scroll-adjustments"),
- G_OBJECT_CLASS_TYPE (gobject_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GtkTextViewClass, set_scroll_adjustments),
- NULL, NULL,
- _gtk_marshal_VOID__OBJECT_OBJECT,
- G_TYPE_NONE, 2,
- GTK_TYPE_ADJUSTMENT,
- GTK_TYPE_ADJUSTMENT);
- widget_class->set_scroll_adjustments_signal = signals[SET_SCROLL_ADJUSTMENTS];
-
/**
* GtkTextView::populate-popup:
- * @entry: The text view on which the signal is emitted
+ * @text_view: The text view on which the signal is emitted
* @menu: the menu that is being populated
*
* The ::populate-popup signal gets emitted before showing the
*/
signals[SELECT_ALL] =
g_signal_new_class_handler (I_("select-all"),
- G_OBJECT_CLASS_TYPE (object_class),
+ G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_CALLBACK (gtk_text_view_select_all),
NULL, NULL,
*/
signals[TOGGLE_CURSOR_VISIBLE] =
g_signal_new_class_handler (I_("toggle-cursor-visible"),
- G_OBJECT_CLASS_TYPE (object_class),
+ G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_CALLBACK (gtk_text_view_toggle_cursor_visible),
NULL, NULL,
*/
signals[PREEDIT_CHANGED] =
g_signal_new_class_handler (I_("preedit-changed"),
- G_OBJECT_CLASS_TYPE (object_class),
+ G_OBJECT_CLASS_TYPE (gobject_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
NULL,
NULL, NULL,
GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
g_type_class_add_private (gobject_class, sizeof (GtkTextViewPrivate));
+
+ gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_TEXT_VIEW_ACCESSIBLE);
+ test_touchscreen = g_getenv ("GTK_TEST_TOUCHSCREEN") != NULL;
}
static void
/* We handle all our own redrawing */
gtk_widget_set_redraw_on_allocate (widget, FALSE);
+
+ priv->text_handle = _gtk_text_handle_new (widget);
+ g_signal_connect (priv->text_handle, "handle-dragged",
+ G_CALLBACK (gtk_text_view_handle_dragged), text_view);
}
/**
GtkTextBuffer *buffer)
{
GtkTextViewPrivate *priv;
+ GtkTextBuffer *old_buffer;
g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
g_return_if_fail (buffer == NULL || GTK_IS_TEXT_BUFFER (buffer));
if (priv->buffer == buffer)
return;
+ old_buffer = priv->buffer;
if (priv->buffer != NULL)
{
/* Destroy all anchored children */
g_signal_handlers_disconnect_by_func (priv->buffer,
gtk_text_view_paste_done_handler,
text_view);
+ g_signal_handlers_disconnect_by_func (priv->buffer,
+ gtk_text_view_buffer_changed_handler,
+ text_view);
if (gtk_widget_get_realized (GTK_WIDGET (text_view)))
{
if (priv->layout)
gtk_text_layout_set_buffer (priv->layout, NULL);
- g_object_unref (priv->buffer);
priv->dnd_mark = NULL;
priv->first_para_mark = NULL;
cancel_pending_scroll (text_view);
g_signal_connect (priv->buffer, "paste-done",
G_CALLBACK (gtk_text_view_paste_done_handler),
text_view);
+ g_signal_connect (priv->buffer, "changed",
+ G_CALLBACK (gtk_text_view_buffer_changed_handler),
+ text_view);
gtk_text_view_target_list_notify (priv->buffer, NULL, text_view);
GDK_SELECTION_PRIMARY);
gtk_text_buffer_add_selection_clipboard (priv->buffer, clipboard);
}
+
+ gtk_text_view_update_handles (text_view, GTK_TEXT_HANDLE_MODE_NONE);
}
+ _gtk_text_view_accessible_set_buffer (text_view, old_buffer);
+ if (old_buffer)
+ g_object_unref (old_buffer);
+
g_object_notify (G_OBJECT (text_view), "buffer");
if (gtk_widget_get_visible (GTK_WIDGET (text_view)))
return get_buffer (text_view);
}
+/**
+ * gtk_text_view_get_cursor_locations:
+ * @text_view: a #GtkTextView
+ * @iter: (allow-none): a #GtkTextIter
+ * @strong: (out) (allow-none): location to store the strong
+ * cursor position (may be %NULL)
+ * @weak: (out) (allow-none): location to store the weak
+ * cursor position (may be %NULL)
+ *
+ * Given an @iter within a text layout, determine the positions of the
+ * strong and weak cursors if the insertion point is at that
+ * iterator. The position of each cursor is stored as a zero-width
+ * rectangle. The strong cursor location is the location where
+ * characters of the directionality equal to the base direction of the
+ * paragraph are inserted. The weak cursor location is the location
+ * where characters of the directionality opposite to the base
+ * direction of the paragraph are inserted.
+ *
+ * If @iter is %NULL, the actual cursor position is used.
+ *
+ * Note that if @iter happens to be the actual cursor position, and
+ * there is currently an IM preedit sequence being entered, the
+ * returned locations will be adjusted to account for the preedit
+ * cursor's offset within the preedit sequence.
+ *
+ * The rectangle position is in buffer coordinates; use
+ * gtk_text_view_buffer_to_window_coords() to convert these
+ * coordinates to coordinates for one of the windows in the text view.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_text_view_get_cursor_locations (GtkTextView *text_view,
+ const GtkTextIter *iter,
+ GdkRectangle *strong,
+ GdkRectangle *weak)
+{
+ GtkTextIter insert;
+
+ g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
+ g_return_if_fail (iter == NULL ||
+ gtk_text_iter_get_buffer (iter) == get_buffer (text_view));
+
+ gtk_text_view_ensure_layout (text_view);
+
+ if (iter)
+ insert = *iter;
+ else
+ gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &insert,
+ gtk_text_buffer_get_insert (get_buffer (text_view)));
+
+ gtk_text_layout_get_cursor_locations (text_view->priv->layout, &insert,
+ strong, weak);
+}
+
/**
* gtk_text_view_get_iter_at_location:
* @text_view: a #GtkTextView
line_top);
}
-static gboolean
-set_adjustment_clamped (GtkAdjustment *adj, gdouble val)
-{
- DV (g_print (" Setting adj to raw value %g\n", val));
-
- /* We don't really want to clamp to upper; we want to clamp to
- upper - page_size which is the highest value the scrollbar
- will let us reach. */
- if (val > (adj->upper - adj->page_size))
- val = adj->upper - adj->page_size;
-
- if (val < adj->lower)
- val = adj->lower;
-
- if (val != adj->value)
- {
- DV (g_print (" Setting adj to clamped value %g\n", val));
- gtk_adjustment_set_value (adj, val);
- return TRUE;
- }
- else
- return FALSE;
-}
-
/**
* gtk_text_view_scroll_to_iter:
* @text_view: a #GtkTextView
if (scroll_inc != 0)
{
- retval = set_adjustment_clamped (get_vadjustment (text_view),
- current_y_scroll + scroll_inc);
+ gtk_adjustment_set_value (text_view->priv->vadjustment,
+ current_y_scroll + scroll_inc);
DV (g_print (" vert increment %d\n", scroll_inc));
}
if (scroll_inc != 0)
{
- retval = set_adjustment_clamped (get_hadjustment (text_view),
- current_x_scroll + scroll_inc);
+ gtk_adjustment_set_value (text_view->priv->hadjustment,
+ current_x_scroll + scroll_inc);
DV (g_print (" horiz increment %d\n", scroll_inc));
}
+ retval = (current_y_scroll != gtk_adjustment_get_value (text_view->priv->vadjustment))
+ || (current_x_scroll != gtk_adjustment_get_value (text_view->priv->hadjustment));
+
if (retval)
{
DV(g_print (">Actually scrolled ("G_STRLOC")\n"));
return retval;
}
-static void
-gtk_text_view_set_adjustment_upper (GtkAdjustment *adj, gdouble upper)
-{
- if (upper != adj->upper)
- {
- gdouble min = MAX (0.0, upper - adj->page_size);
- gboolean value_changed = FALSE;
-
- adj->upper = upper;
-
- if (adj->value > min)
- {
- adj->value = min;
- value_changed = TRUE;
- }
-
- gtk_adjustment_changed (adj);
- DV(g_print(">Changed adj upper to %g ("G_STRLOC")\n", upper));
-
- if (value_changed)
- {
- DV(g_print(">Changed adj value because upper decreased ("G_STRLOC")\n"));
- gtk_adjustment_value_changed (adj);
- }
- }
-}
-
static void
gtk_text_view_update_adjustments (GtkTextView *text_view)
{
priv->width = width;
priv->height = height;
- gtk_text_view_set_adjustment_upper (get_hadjustment (text_view),
- MAX (SCREEN_WIDTH (text_view), width));
- gtk_text_view_set_adjustment_upper (get_vadjustment (text_view),
- MAX (SCREEN_HEIGHT (text_view), height));
-
- /* hadj/vadj exist since we called get_hadjustment/get_vadjustment above */
-
- /* Set up the step sizes; we'll say that a page is
- our allocation minus one step, and a step is
- 1/10 of our allocation. */
- priv->hadjustment->step_increment =
- SCREEN_WIDTH (text_view) / 10.0;
- priv->hadjustment->page_increment =
- SCREEN_WIDTH (text_view) * 0.9;
-
- priv->vadjustment->step_increment =
- SCREEN_HEIGHT (text_view) / 10.0;
- priv->vadjustment->page_increment =
- SCREEN_HEIGHT (text_view) * 0.9;
-
- gtk_adjustment_changed (get_hadjustment (text_view));
- gtk_adjustment_changed (get_vadjustment (text_view));
+ gtk_text_view_set_hadjustment_values (text_view);
+ gtk_text_view_set_vadjustment_values (text_view);
}
}
if (text_view->priv->layout == NULL)
return;
- gtk_text_view_get_cursor_location (text_view, &area);
+ gtk_text_view_get_cursor_locations (text_view, NULL, &area, NULL);
area.x -= text_view->priv->xoffset;
area.y -= text_view->priv->yoffset;
/* Width returned by Pango indicates direction of cursor,
- * by it's sign more than the size of cursor.
+ * by its sign more than the size of cursor.
*/
area.width = 0;
/**
* gtk_text_view_get_visible_rect:
* @text_view: a #GtkTextView
- * @visible_rect: rectangle to fill
+ * @visible_rect: (out): rectangle to fill
*
* Fills @visible_rect with the currently-visible
* region of the buffer, in buffer coordinates. Convert to window coordinates
{
priv->wrap_mode = wrap_mode;
- if (priv->layout)
+ if (priv->layout && priv->layout->default_style)
{
priv->layout->default_style->wrap_mode = wrap_mode;
gtk_text_layout_default_style_changed (priv->layout);
if (setting && gtk_widget_has_focus (GTK_WIDGET (text_view)))
gtk_im_context_focus_in (priv->im_context);
- if (priv->layout)
+ if (priv->layout && priv->layout->default_style)
{
gtk_text_layout_set_overwrite_mode (priv->layout,
priv->overwrite_mode && priv->editable);
{
priv->pixels_above_lines = pixels_above_lines;
- if (priv->layout)
+ if (priv->layout && priv->layout->default_style)
{
priv->layout->default_style->pixels_above_lines = pixels_above_lines;
gtk_text_layout_default_style_changed (priv->layout);
{
priv->pixels_below_lines = pixels_below_lines;
- if (priv->layout)
+ if (priv->layout && priv->layout->default_style)
{
priv->layout->default_style->pixels_below_lines = pixels_below_lines;
gtk_text_layout_default_style_changed (priv->layout);
{
priv->pixels_inside_wrap = pixels_inside_wrap;
- if (priv->layout)
+ if (priv->layout && priv->layout->default_style)
{
priv->layout->default_style->pixels_inside_wrap = pixels_inside_wrap;
gtk_text_layout_default_style_changed (priv->layout);
{
priv->justify = justification;
- if (priv->layout)
+ if (priv->layout && priv->layout->default_style)
{
priv->layout->default_style->justification = justification;
gtk_text_layout_default_style_changed (priv->layout);
{
priv->left_margin = left_margin;
- if (priv->layout)
+ if (priv->layout && priv->layout->default_style)
{
priv->layout->default_style->left_margin = left_margin;
gtk_text_layout_default_style_changed (priv->layout);
{
priv->right_margin = right_margin;
- if (priv->layout)
+ if (priv->layout && priv->layout->default_style)
{
priv->layout->default_style->right_margin = right_margin;
gtk_text_layout_default_style_changed (priv->layout);
{
priv->indent = indent;
- if (priv->layout)
+ if (priv->layout && priv->layout->default_style)
{
priv->layout->default_style->indent = indent;
gtk_text_layout_default_style_changed (priv->layout);
priv->tabs = tabs ? pango_tab_array_copy (tabs) : NULL;
- if (priv->layout)
+ if (priv->layout && priv->layout->default_style)
{
/* some unkosher futzing in internal struct details... */
if (priv->layout->default_style->tabs)
}
static void
-gtk_text_view_destroy (GtkObject *object)
+gtk_text_view_destroy (GtkWidget *widget)
{
GtkTextView *text_view;
GtkTextViewPrivate *priv;
- text_view = GTK_TEXT_VIEW (object);
+ text_view = GTK_TEXT_VIEW (widget);
priv = text_view->priv;
gtk_text_view_remove_validate_idles (text_view);
priv->im_spot_idle = 0;
}
- GTK_OBJECT_CLASS (gtk_text_view_parent_class)->destroy (object);
+ GTK_WIDGET_CLASS (gtk_text_view_parent_class)->destroy (widget);
}
static void
text_view = GTK_TEXT_VIEW (object);
priv = text_view->priv;
- g_assert (priv->buffer == NULL);
-
gtk_text_view_destroy_layout (text_view);
gtk_text_view_set_buffer (text_view, NULL);
+
+ /* at this point, no "notify::buffer" handler should recreate the buffer. */
+ g_assert (priv->buffer == NULL);
cancel_pending_scroll (text_view);
if (priv->bottom_window)
text_window_free (priv->bottom_window);
+ g_object_unref (priv->text_handle);
g_object_unref (priv->im_context);
g_free (priv->im_module);
gtk_im_multicontext_set_context_id (GTK_IM_MULTICONTEXT (priv->im_context), priv->im_module);
break;
+ case PROP_HADJUSTMENT:
+ gtk_text_view_set_hadjustment (text_view, g_value_get_object (value));
+ break;
+
+ case PROP_VADJUSTMENT:
+ gtk_text_view_set_vadjustment (text_view, g_value_get_object (value));
+ break;
+
+ case PROP_HSCROLL_POLICY:
+ priv->hscroll_policy = g_value_get_enum (value);
+ gtk_widget_queue_resize (GTK_WIDGET (text_view));
+ break;
+
+ case PROP_VSCROLL_POLICY:
+ priv->vscroll_policy = g_value_get_enum (value);
+ gtk_widget_queue_resize (GTK_WIDGET (text_view));
+ break;
+
+ case PROP_INPUT_PURPOSE:
+ gtk_text_view_set_input_purpose (text_view, g_value_get_enum (value));
+ break;
+
+ case PROP_INPUT_HINTS:
+ gtk_text_view_set_input_hints (text_view, g_value_get_flags (value));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
g_value_set_string (value, priv->im_module);
break;
+ case PROP_HADJUSTMENT:
+ g_value_set_object (value, priv->hadjustment);
+ break;
+
+ case PROP_VADJUSTMENT:
+ g_value_set_object (value, priv->vadjustment);
+ break;
+
+ case PROP_HSCROLL_POLICY:
+ g_value_set_enum (value, priv->hscroll_policy);
+ break;
+
+ case PROP_VSCROLL_POLICY:
+ g_value_set_enum (value, priv->vscroll_policy);
+ break;
+
+ case PROP_INPUT_PURPOSE:
+ g_value_set_enum (value, gtk_text_view_get_input_purpose (text_view));
+ break;
+
+ case PROP_INPUT_HINTS:
+ g_value_set_flags (value, gtk_text_view_get_input_hints (text_view));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
GtkRequisition child_req;
GtkRequisition old_req;
- gtk_size_request_get_size (GTK_SIZE_REQUEST (child->widget),
- &old_req, NULL);
+ gtk_widget_get_preferred_size (child->widget, &old_req, NULL);
- gtk_size_request_get_size (GTK_SIZE_REQUEST (child->widget),
- &child_req, NULL);
+ gtk_widget_get_preferred_size (child->widget, &child_req, NULL);
/* Invalidate layout lines if required */
if (priv->layout &&
{
GtkRequisition child_req;
- gtk_size_request_get_size (GTK_SIZE_REQUEST (child->widget),
- &child_req, NULL);
+ gtk_widget_get_preferred_size (child->widget,
+ &child_req, NULL);
}
tmp_list = g_slist_next (tmp_list);
priv->cached_size_request = *requisition;
}
+static void
+gtk_text_view_get_preferred_width (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
+{
+ GtkRequisition requisition;
+
+ gtk_text_view_size_request (widget, &requisition);
+
+ *minimum = *natural = requisition.width;
+}
+
+static void
+gtk_text_view_get_preferred_height (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
+{
+ GtkRequisition requisition;
+
+ gtk_text_view_size_request (widget, &requisition);
+
+ *minimum = *natural = requisition.height;
+}
+
+
static void
gtk_text_view_compute_child_allocation (GtkTextView *text_view,
GtkTextViewChild *vc,
allocation->x = vc->from_left_of_buffer - text_view->priv->xoffset;
allocation->y = buffer_y - text_view->priv->yoffset;
- gtk_size_request_get_size (GTK_SIZE_REQUEST (vc->widget),
- &req, NULL);
+ gtk_widget_get_preferred_size (vc->widget, &req, NULL);
allocation->width = req.width;
allocation->height = req.height;
}
* get in the way. Invalidating the layout around the anchor
* achieves this.
*/
- if (GTK_WIDGET_ALLOC_NEEDED (child->widget))
+ if (_gtk_widget_get_alloc_needed (child->widget))
{
GtkTextIter end = child_loc;
gtk_text_iter_forward_char (&end);
allocation.x = child->x;
allocation.y = child->y;
- gtk_size_request_get_size (GTK_SIZE_REQUEST (child->widget),
- &child_req, NULL);
+ gtk_widget_get_preferred_size (child->widget, &child_req, NULL);
allocation.width = child_req.width;
allocation.height = child_req.height;
GtkAllocation widget_allocation;
GtkTextView *text_view;
GtkTextViewPrivate *priv;
- GtkTextIter first_para;
- gint y;
gint width, height;
GdkRectangle text_rect;
GdkRectangle left_rect;
/* Note that this will do some layout validation */
gtk_text_view_allocate_children (text_view);
- /* Ensure h/v adj exist */
- get_hadjustment (text_view);
- get_vadjustment (text_view);
-
- priv->hadjustment->page_size = SCREEN_WIDTH (text_view);
- priv->hadjustment->page_increment = SCREEN_WIDTH (text_view) * 0.9;
- priv->hadjustment->step_increment = SCREEN_WIDTH (text_view) * 0.1;
- priv->hadjustment->lower = 0;
- priv->hadjustment->upper = MAX (SCREEN_WIDTH (text_view),
- priv->width);
-
- if (priv->hadjustment->value > priv->hadjustment->upper - priv->hadjustment->page_size)
- gtk_adjustment_set_value (priv->hadjustment, MAX (0, priv->hadjustment->upper - priv->hadjustment->page_size));
-
- gtk_adjustment_changed (priv->hadjustment);
-
- priv->vadjustment->page_size = SCREEN_HEIGHT (text_view);
- priv->vadjustment->page_increment = SCREEN_HEIGHT (text_view) * 0.9;
- priv->vadjustment->step_increment = SCREEN_HEIGHT (text_view) * 0.1;
- priv->vadjustment->lower = 0;
- priv->vadjustment->upper = MAX (SCREEN_HEIGHT (text_view),
- priv->height);
-
- /* Now adjust the value of the adjustment to keep the cursor at the
- * same place in the buffer
- */
- gtk_text_view_get_first_para_iter (text_view, &first_para);
- gtk_text_layout_get_line_yrange (priv->layout, &first_para, &y, NULL);
-
- y += priv->first_para_pixels;
-
- if (y > priv->vadjustment->upper - priv->vadjustment->page_size)
- y = MAX (0, priv->vadjustment->upper - priv->vadjustment->page_size);
-
- if (y != priv->yoffset)
- gtk_adjustment_set_value (priv->vadjustment, y);
-
- gtk_adjustment_changed (priv->vadjustment);
+ /* Update adjustments */
+ gtk_text_view_set_hadjustment_values (text_view);
+ gtk_text_view_set_vadjustment_values (text_view);
/* The GTK resize loop processes all the pending exposes right
* after doing the resize stuff, so the idle sizer won't have a
if (old_height != new_height)
{
- gboolean yoffset_changed = FALSE;
GSList *tmp_list;
int new_first_para_top;
int old_first_para_top;
{
priv->yoffset += new_first_para_top - old_first_para_top;
- get_vadjustment (text_view)->value = priv->yoffset;
- yoffset_changed = TRUE;
- }
-
- if (yoffset_changed)
- {
- DV(g_print ("Changing scroll position (%s)\n", G_STRLOC));
- gtk_adjustment_value_changed (get_vadjustment (text_view));
+ gtk_adjustment_set_value (text_view->priv->vadjustment, priv->yoffset);
}
/* FIXME be smarter about which anchored widgets we update */
* to avoid the optimization which just returns widget->requisition
* if a resize hasn't been queued.
*/
- GTK_WIDGET_GET_CLASS (widget)->size_request (widget, &new_req);
+ gtk_text_view_size_request (widget, &new_req);
if (old_req.width != new_req.width ||
old_req.height != new_req.height)
GtkAllocation allocation;
GtkTextView *text_view;
GtkTextViewPrivate *priv;
+ GtkStyleContext *context;
GdkWindow *window;
GdkWindowAttr attributes;
gint attributes_mask;
GSList *tmp_list;
-
+
text_view = GTK_TEXT_VIEW (widget);
priv = text_view->priv;
window = gdk_window_new (gtk_widget_get_parent_window (widget),
&attributes, attributes_mask);
gtk_widget_set_window (widget, window);
- gdk_window_set_user_data (window, widget);
+ gtk_widget_register_window (widget, window);
- /* must come before text_window_realize calls */
- gtk_widget_style_attach (widget);
+ context = gtk_widget_get_style_context (widget);
- gdk_window_set_background (window,
- >k_widget_get_style (widget)->bg[gtk_widget_get_state (widget)]);
+ gtk_style_context_save (context);
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_VIEW);
+ gtk_style_context_set_background (context, window);
+ gtk_style_context_restore (context);
text_window_realize (priv->text_window, widget);
text_window_realize (priv->bottom_window, widget);
gtk_text_view_ensure_layout (text_view);
+ gtk_text_view_invalidate (text_view);
if (priv->buffer)
{
/* Ensure updating the spot location. */
gtk_text_view_update_im_spot_location (text_view);
+
+ _gtk_text_handle_set_relative_to (priv->text_handle, priv->text_window->window);
}
static void
if (priv->bottom_window)
text_window_unrealize (priv->bottom_window);
- gtk_text_view_destroy_layout (text_view);
+ _gtk_text_handle_set_relative_to (priv->text_handle, NULL);
GTK_WIDGET_CLASS (gtk_text_view_parent_class)->unrealize (widget);
}
static void
gtk_text_view_set_background (GtkTextView *text_view)
{
- GtkStyle *style;
- GtkStateType state;
+ GtkStyleContext *context;
+ GtkStateFlags state;
GtkWidget *widget;
GtkTextViewPrivate *priv;
+ GdkRGBA color;
widget = GTK_WIDGET (text_view);
priv = text_view->priv;
- style = gtk_widget_get_style (widget);
- state = gtk_widget_get_state (widget);
+ context = gtk_widget_get_style_context (widget);
+ state = gtk_widget_get_state_flags (widget);
+
+ /* Set bin window background */
+ gtk_style_context_save (context);
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_VIEW);
- gdk_window_set_background (gtk_widget_get_window (widget),
- &style->bg[state]);
+ gtk_style_context_set_background (context, priv->text_window->bin_window);
+ gtk_style_context_set_background (context, gtk_widget_get_window (widget));
- gdk_window_set_background (priv->text_window->bin_window,
- &style->base[state]);
+ gtk_style_context_restore (context);
+
+ /* Set lateral panes background */
+ gtk_style_context_get_background_color (context, state, &color);
if (priv->left_window)
- gdk_window_set_background (priv->left_window->bin_window,
- &style->bg[state]);
+ gdk_window_set_background_rgba (priv->left_window->bin_window, &color);
+
if (priv->right_window)
- gdk_window_set_background (priv->right_window->bin_window,
- &style->bg[state]);
+ gdk_window_set_background_rgba (priv->right_window->bin_window, &color);
if (priv->top_window)
- gdk_window_set_background (priv->top_window->bin_window,
- &style->bg[state]);
+ gdk_window_set_background_rgba (priv->top_window->bin_window, &color);
if (priv->bottom_window)
- gdk_window_set_background (priv->bottom_window->bin_window,
- &style->bg[state]);
+ gdk_window_set_background_rgba (priv->bottom_window->bin_window, &color);
}
static void
-gtk_text_view_style_set (GtkWidget *widget,
- GtkStyle *previous_style)
+gtk_text_view_style_updated (GtkWidget *widget)
{
GtkTextView *text_view;
GtkTextViewPrivate *priv;
PangoContext *ltr_context, *rtl_context;
+ GtkStyleContext *style_context;
+ const GtkBitmask *changes;
text_view = GTK_TEXT_VIEW (widget);
priv = text_view->priv;
+ GTK_WIDGET_CLASS (gtk_text_view_parent_class)->style_updated (widget);
+
if (gtk_widget_get_realized (widget))
{
gtk_text_view_set_background (text_view);
}
- if (priv->layout && previous_style)
+
+ style_context = gtk_widget_get_style_context (widget);
+ changes = _gtk_style_context_get_changes (style_context);
+ if ((changes == NULL || _gtk_css_style_property_changes_affect_font (changes)) &&
+ priv->layout && priv->layout->default_style)
{
gtk_text_view_set_attributes_from_style (text_view,
- priv->layout->default_style,
- gtk_widget_get_style (widget));
+ priv->layout->default_style);
ltr_context = gtk_widget_create_pango_context (widget);
pango_context_set_base_dir (ltr_context, PANGO_DIRECTION_LTR);
{
GtkTextViewPrivate *priv = GTK_TEXT_VIEW (widget)->priv;
- if (priv->layout)
+ if (priv->layout && priv->layout->default_style)
{
priv->layout->default_style->direction = gtk_widget_get_direction (widget);
}
static void
-gtk_text_view_state_changed (GtkWidget *widget,
- GtkStateType previous_state)
+gtk_text_view_state_flags_changed (GtkWidget *widget,
+ GtkStateFlags previous_state)
{
GtkTextView *text_view = GTK_TEXT_VIEW (widget);
GdkCursor *cursor;
gdk_window_set_cursor (text_view->priv->text_window->bin_window, cursor);
if (cursor)
- gdk_cursor_unref (cursor);
+ g_object_unref (cursor);
text_view->priv->mouse_cursor_obscured = FALSE;
}
GdkDisplay *display;
GdkCursor *cursor;
- display = gdk_drawable_get_display (window);
+ display = gdk_window_get_display (window);
cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR);
gdk_window_set_cursor (window, cursor);
- gdk_cursor_unref (cursor);
+ g_object_unref (cursor);
}
static void
cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (text_view)),
GDK_XTERM);
gdk_window_set_cursor (text_view->priv->text_window->bin_window, cursor);
- gdk_cursor_unref (cursor);
+ g_object_unref (cursor);
text_view->priv->mouse_cursor_obscured = FALSE;
}
}
if (priv->grab_device &&
gtk_widget_device_is_shadowed (widget, priv->grab_device))
{
+ if (priv->drag_start_x >= 0)
+ {
+ priv->drag_start_x = -1;
+ priv->drag_start_y = -1;
+ }
+
gtk_text_view_end_selection_drag (GTK_TEXT_VIEW (widget));
gtk_text_view_unobscure_mouse_cursor (GTK_TEXT_VIEW (widget));
+ priv->grab_device = NULL;
}
}
return retval;
}
+static void
+gtk_text_view_set_handle_position (GtkTextView *text_view,
+ GtkTextIter *iter,
+ GtkTextHandlePosition pos)
+{
+ GtkTextViewPrivate *priv;
+ GdkRectangle rect;
+ gint x, y;
+
+ priv = text_view->priv;
+ gtk_text_view_get_cursor_locations (text_view, iter, &rect, NULL);
+
+ x = rect.x - priv->xoffset;
+ y = rect.y - priv->yoffset;
+
+ if (!_gtk_text_handle_get_is_dragged (priv->text_handle, pos) &&
+ (x < 0 || x > SCREEN_WIDTH (text_view) ||
+ y < 0 || y > SCREEN_HEIGHT (text_view)))
+ {
+ /* Hide the handle if it's not being manipulated
+ * and fell outside of the visible text area.
+ */
+ _gtk_text_handle_set_visible (priv->text_handle, pos, FALSE);
+ }
+ else
+ {
+ _gtk_text_handle_set_visible (priv->text_handle, pos, TRUE);
+
+ rect.x = CLAMP (x, 0, SCREEN_WIDTH (text_view));
+ rect.y = CLAMP (y, 0, SCREEN_HEIGHT (text_view));
+ _gtk_text_handle_set_position (priv->text_handle, pos, &rect);
+ }
+}
+
+static void
+gtk_text_view_handle_dragged (GtkTextHandle *handle,
+ GtkTextHandlePosition pos,
+ gint x,
+ gint y,
+ GtkTextView *text_view)
+{
+ GtkTextViewPrivate *priv;
+ GtkTextIter old_cursor, old_bound;
+ GtkTextIter cursor, bound, iter;
+ GtkTextIter *min, *max;
+ GtkTextHandleMode mode;
+ GtkTextBuffer *buffer;
+ GtkTextHandlePosition cursor_pos;
+
+ priv = text_view->priv;
+ buffer = get_buffer (text_view);
+ mode = _gtk_text_handle_get_mode (handle);
+
+ gtk_text_layout_get_iter_at_pixel (priv->layout, &iter,
+ x + priv->xoffset,
+ y + priv->yoffset);
+ gtk_text_buffer_get_iter_at_mark (buffer, &old_cursor,
+ gtk_text_buffer_get_insert (buffer));
+ gtk_text_buffer_get_iter_at_mark (buffer, &old_bound,
+ gtk_text_buffer_get_selection_bound (buffer));
+ cursor = old_cursor;
+ bound = old_bound;
+
+ if (mode == GTK_TEXT_HANDLE_MODE_CURSOR ||
+ gtk_text_iter_compare (&cursor, &bound) >= 0)
+ {
+ cursor_pos = GTK_TEXT_HANDLE_POSITION_CURSOR;
+ max = &cursor;
+ min = &bound;
+ }
+ else
+ {
+ cursor_pos = GTK_TEXT_HANDLE_POSITION_SELECTION_START;
+ max = &bound;
+ min = &cursor;
+ }
+
+ if (pos == GTK_TEXT_HANDLE_POSITION_SELECTION_END)
+ {
+ if (mode == GTK_TEXT_HANDLE_MODE_SELECTION &&
+ gtk_text_iter_compare (&iter, min) <= 0)
+ {
+ iter = *min;
+ gtk_text_iter_forward_char (&iter);
+ }
+
+ *max = iter;
+ gtk_text_view_set_handle_position (text_view, &iter, pos);
+ }
+ else
+ {
+ if (mode == GTK_TEXT_HANDLE_MODE_SELECTION &&
+ gtk_text_iter_compare (&iter, max) >= 0)
+ {
+ iter = *max;
+ gtk_text_iter_backward_char (&iter);
+ }
+
+ *min = iter;
+ gtk_text_view_set_handle_position (text_view, &iter, pos);
+ }
+
+ if (gtk_text_iter_compare (&old_cursor, &cursor) != 0 ||
+ gtk_text_iter_compare (&old_bound, &bound) != 0)
+ {
+ if (mode == GTK_TEXT_HANDLE_MODE_CURSOR)
+ gtk_text_buffer_place_cursor (buffer, &cursor);
+ else
+ gtk_text_buffer_select_range (buffer, &cursor, &bound);
+
+ if (_gtk_text_handle_get_is_dragged (priv->text_handle, cursor_pos))
+ gtk_text_view_scroll_mark_onscreen (text_view,
+ gtk_text_buffer_get_insert (buffer));
+ else
+ gtk_text_view_scroll_mark_onscreen (text_view,
+ gtk_text_buffer_get_selection_bound (buffer));
+ }
+}
+
+static void
+gtk_text_view_update_handles (GtkTextView *text_view,
+ GtkTextHandleMode mode)
+{
+ GtkTextViewPrivate *priv = text_view->priv;
+ GtkTextIter cursor, bound, min, max;
+ GtkTextBuffer *buffer;
+
+ buffer = get_buffer (text_view);
+
+ gtk_text_buffer_get_iter_at_mark (buffer, &cursor,
+ gtk_text_buffer_get_insert (buffer));
+ gtk_text_buffer_get_iter_at_mark (buffer, &bound,
+ gtk_text_buffer_get_selection_bound (buffer));
+
+ if (mode == GTK_TEXT_HANDLE_MODE_SELECTION &&
+ gtk_text_iter_compare (&cursor, &bound) == 0)
+ {
+ mode = GTK_TEXT_HANDLE_MODE_CURSOR;
+ }
+
+ if (mode == GTK_TEXT_HANDLE_MODE_CURSOR &&
+ (!gtk_widget_is_sensitive (GTK_WIDGET (text_view)) || !priv->cursor_visible))
+ {
+ mode = GTK_TEXT_HANDLE_MODE_NONE;
+ }
+
+ _gtk_text_handle_set_mode (priv->text_handle, mode);
+
+ if (gtk_text_iter_compare (&cursor, &bound) >= 0)
+ {
+ min = bound;
+ max = cursor;
+ }
+ else
+ {
+ min = cursor;
+ max = bound;
+ }
+
+ if (mode != GTK_TEXT_HANDLE_MODE_NONE)
+ gtk_text_view_set_handle_position (text_view, &max,
+ GTK_TEXT_HANDLE_POSITION_SELECTION_END);
+
+ if (mode == GTK_TEXT_HANDLE_MODE_SELECTION)
+ gtk_text_view_set_handle_position (text_view, &min,
+ GTK_TEXT_HANDLE_POSITION_SELECTION_START);
+}
+
static gint
gtk_text_view_event (GtkWidget *widget, GdkEvent *event)
{
gtk_text_view_reset_blink_time (text_view);
gtk_text_view_pend_cursor_blink (text_view);
+ _gtk_text_handle_set_mode (priv->text_handle,
+ GTK_TEXT_HANDLE_MODE_NONE);
+
return retval;
}
{
GtkTextView *text_view;
GtkTextViewPrivate *priv;
+ GdkDevice *device;
+ gboolean is_touchscreen;
text_view = GTK_TEXT_VIEW (widget);
priv = text_view->priv;
#if 0
/* debug hack */
- if (event->button == 3 && (event->state & GDK_CONTROL_MASK) != 0)
+ if (event->button == GDK_BUTTON_SECONDARY && (event->state & GDK_CONTROL_MASK) != 0)
_gtk_text_buffer_spew (GTK_TEXT_VIEW (widget)->buffer);
- else if (event->button == 3)
+ else if (event->button == GDK_BUTTON_SECONDARY)
gtk_text_layout_spew (GTK_TEXT_VIEW (widget)->layout);
#endif
+ device = gdk_event_get_source_device ((GdkEvent *) event);
+ is_touchscreen = test_touchscreen ||
+ gdk_device_get_source (device) == GDK_SOURCE_TOUCHSCREEN;
+
if (event->type == GDK_BUTTON_PRESS)
{
gtk_text_view_reset_im_context (text_view);
- if (event->button == 1)
+ if (gdk_event_triggers_context_menu ((GdkEvent *) event))
+ {
+ gtk_text_view_do_popup (text_view, event);
+ return TRUE;
+ }
+ else if (event->button == GDK_BUTTON_PRIMARY)
{
/* If we're in the selection, start a drag copy/move of the
* selection; otherwise, start creating a new selection.
if (gtk_text_buffer_get_selection_bounds (get_buffer (text_view),
&start, &end) &&
gtk_text_iter_in_range (&iter, &start, &end) &&
- !(event->state & GDK_SHIFT_MASK))
+ !(event->state &
+ gtk_widget_get_modifier_mask (widget,
+ GDK_MODIFIER_INTENT_EXTEND_SELECTION)))
{
+ priv->grab_device = event->device;
priv->drag_start_x = event->x;
priv->drag_start_y = event->y;
priv->pending_place_cursor_button = event->button;
}
else
{
+ GtkTextHandleMode mode;
+
gtk_text_view_start_selection_drag (text_view, &iter, event);
+
+ if (gtk_widget_is_sensitive (widget) && is_touchscreen)
+ mode = GTK_TEXT_HANDLE_MODE_CURSOR;
+ else
+ mode = GTK_TEXT_HANDLE_MODE_NONE;
+
+ gtk_text_view_update_handles (text_view, mode);
}
return TRUE;
}
- else if (event->button == 2)
+ else if (event->button == GDK_BUTTON_MIDDLE &&
+ get_middle_click_paste (text_view))
{
GtkTextIter iter;
priv->editable);
return TRUE;
}
- else if (event->button == 3)
- {
- gtk_text_view_do_popup (text_view, event);
- return TRUE;
- }
}
else if ((event->type == GDK_2BUTTON_PRESS ||
event->type == GDK_3BUTTON_PRESS) &&
- event->button == 1)
+ event->button == GDK_BUTTON_PRIMARY)
{
GtkTextIter iter;
+ GtkTextHandleMode mode;
gtk_text_view_end_selection_drag (text_view);
&iter,
event->x + priv->xoffset,
event->y + priv->yoffset);
-
+
gtk_text_view_start_selection_drag (text_view, &iter, event);
+
+ if (gtk_widget_is_sensitive (widget) && is_touchscreen)
+ mode = GTK_TEXT_HANDLE_MODE_SELECTION;
+ else
+ mode = GTK_TEXT_HANDLE_MODE_NONE;
+
+ gtk_text_view_update_handles (text_view, mode);
return TRUE;
}
-
+
return FALSE;
}
if (event->window != priv->text_window->bin_window)
return FALSE;
- if (event->button == 1)
+ if (event->button == GDK_BUTTON_PRIMARY)
{
if (priv->drag_start_x >= 0)
{
return TRUE;
else if (priv->pending_place_cursor_button == event->button)
{
+ GtkTextHandleMode mode;
+ GdkDevice *device;
GtkTextIter iter;
/* Unselect everything; we clicked inside selection, but
gtk_text_buffer_place_cursor (get_buffer (text_view), &iter);
gtk_text_view_check_cursor_blink (text_view);
-
+
+ device = gdk_event_get_source_device ((GdkEvent *) event);
+
+ if (gtk_widget_is_sensitive (widget) &&
+ (test_touchscreen ||
+ gdk_device_get_source (device) == GDK_SOURCE_TOUCHSCREEN))
+ mode = GTK_TEXT_HANDLE_MODE_CURSOR;
+ else
+ mode = GTK_TEXT_HANDLE_MODE_NONE;
+
+ gtk_text_view_update_handles (text_view, mode);
priv->pending_place_cursor_button = 0;
-
+
return FALSE;
}
}
g_signal_handlers_disconnect_by_func (gdk_keymap_get_for_display (gtk_widget_get_display (widget)),
keymap_direction_changed,
text_view);
+ _gtk_text_handle_set_mode (priv->text_handle,
+ GTK_TEXT_HANDLE_MODE_NONE);
if (priv->editable)
{
static void
gtk_text_view_paint (GtkWidget *widget,
- GdkRectangle *area,
- GdkEventExpose *event)
+ cairo_t *cr)
{
GtkTextView *text_view;
GtkTextViewPrivate *priv;
- GList *child_exposes;
- GList *tmp_list;
- cairo_t *cr;
text_view = GTK_TEXT_VIEW (widget);
priv = text_view->priv;
area->width, area->height);
#endif
- child_exposes = NULL;
-
- cr = gdk_cairo_create (priv->text_window->bin_window);
-
- gdk_cairo_region (cr, event->region);
- cairo_clip (cr);
-
+ cairo_save (cr);
cairo_translate (cr, -priv->xoffset, -priv->yoffset);
gtk_text_layout_draw (priv->layout,
- widget,
- cr,
- &child_exposes);
-
- cairo_destroy (cr);
-
- tmp_list = child_exposes;
- while (tmp_list != NULL)
- {
- GtkWidget *child = tmp_list->data;
-
- gtk_container_propagate_expose (GTK_CONTAINER (text_view),
- child,
- event);
-
- g_object_unref (child);
-
- tmp_list = tmp_list->next;
- }
+ widget,
+ cr,
+ NULL);
- g_list_free (child_exposes);
+ cairo_restore (cr);
}
-static gint
-gtk_text_view_expose_event (GtkWidget *widget, GdkEventExpose *event)
+static gboolean
+gtk_text_view_draw (GtkWidget *widget,
+ cairo_t *cr)
{
GSList *tmp_list;
+ GdkWindow *window;
- if (event->window == gtk_text_view_get_window (GTK_TEXT_VIEW (widget),
- GTK_TEXT_WINDOW_TEXT))
+ if (gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)))
+ gtk_text_view_draw_focus (widget, cr);
+
+ window = gtk_text_view_get_window (GTK_TEXT_VIEW (widget),
+ GTK_TEXT_WINDOW_TEXT);
+ if (gtk_cairo_should_draw_window (cr, window))
{
DV(g_print (">Exposed ("G_STRLOC")\n"));
- gtk_text_view_paint (widget, &event->area, event);
+ cairo_save (cr);
+ gtk_cairo_transform_to_window (cr, widget, window);
+ gtk_text_view_paint (widget, cr);
+ cairo_restore (cr);
}
- if (event->window == gtk_widget_get_window (widget))
- gtk_text_view_draw_focus (widget);
-
/* Propagate exposes to all unanchored children.
* Anchored children are handled in gtk_text_view_paint().
*/
{
GtkTextViewChild *vc = tmp_list->data;
- /* propagate_expose checks that event->window matches
+ /* propagate_draw checks that event->window matches
* child->window
*/
- if (!vc->anchor)
- gtk_container_propagate_expose (GTK_CONTAINER (widget),
- vc->widget,
- event);
+ gtk_container_propagate_draw (GTK_CONTAINER (widget),
+ vc->widget,
+ cr);
tmp_list = tmp_list->next;
}
}
static void
-gtk_text_view_draw_focus (GtkWidget *widget)
+gtk_text_view_draw_focus (GtkWidget *widget,
+ cairo_t *cr)
{
- GtkAllocation allocation;
- GdkWindow *window;
gboolean interior_focus;
/* We clear the focus if we are in interior focus mode. */
"interior-focus", &interior_focus,
NULL);
- if (gtk_widget_is_drawable (widget))
+ if (gtk_widget_has_visible_focus (widget) && !interior_focus)
{
- window = gtk_widget_get_window (widget);
+ GtkStyleContext *context;
- if (gtk_widget_has_focus (widget) && !interior_focus)
- {
- gtk_widget_get_allocation (widget, &allocation);
- gtk_paint_focus (gtk_widget_get_style (widget),
- window,
- gtk_widget_get_state (widget),
- NULL, widget, "textview",
- 0, 0,
- allocation.width, allocation.height);
- }
- else
- {
- gdk_window_clear (window);
- }
+ context = gtk_widget_get_style_context (widget);
+
+ gtk_render_focus (context, cr, 0, 0,
+ gtk_widget_get_allocated_width (widget),
+ gtk_widget_get_allocated_height (widget));
}
}
{
GtkContainer *container;
gboolean result;
-
- container = GTK_CONTAINER (widget);
+
+ container = GTK_CONTAINER (widget);
if (!gtk_widget_is_focus (widget) &&
gtk_container_get_focus_child (container) == NULL)
{
- gtk_widget_grab_focus (widget);
- return TRUE;
+ if (gtk_widget_get_can_focus (widget))
+ {
+ gtk_widget_grab_focus (widget);
+ return TRUE;
+ }
+
+ return FALSE;
}
else
{
+ gboolean can_focus;
/*
* Unset CAN_FOCUS flag so that gtk_container_focus() allows
* children to get the focus
*/
+ can_focus = gtk_widget_get_can_focus (widget);
gtk_widget_set_can_focus (widget, FALSE);
result = GTK_WIDGET_CLASS (gtk_text_view_parent_class)->focus (widget, direction);
- gtk_widget_set_can_focus (widget, TRUE);
+ gtk_widget_set_can_focus (widget, can_focus);
return result;
}
}
-static void
-gtk_text_view_move_focus (GtkWidget *widget,
- GtkDirectionType direction_type)
-{
- GtkTextView *text_view = GTK_TEXT_VIEW (widget);
-
- if (GTK_TEXT_VIEW_GET_CLASS (text_view)->move_focus)
- GTK_TEXT_VIEW_GET_CLASS (text_view)->move_focus (text_view,
- direction_type);
-}
-
/*
* Container
*/
return FALSE;
}
+static gboolean
+get_middle_click_paste (GtkTextView *text_view)
+{
+ GtkSettings *settings;
+ gboolean paste;
+
+ settings = gtk_widget_get_settings (GTK_WIDGET (text_view));
+ g_object_get (settings, "gtk-enable-primary-paste", &paste, NULL);
+
+ return paste;
+}
+
static gint
get_cursor_time (GtkTextView *text_view)
{
if (!priv->cursor_visible)
{
GtkScrollStep scroll_step;
+ gdouble old_xpos, old_ypos;
switch (step)
{
break;
}
- if (!gtk_text_view_move_viewport (text_view, scroll_step, count))
+ old_xpos = priv->xoffset;
+ old_ypos = priv->yoffset;
+ gtk_text_view_move_viewport (text_view, scroll_step, count);
+ if ((old_xpos == priv->xoffset && old_ypos == priv->yoffset) &&
+ leave_direction != -1 &&
+ !gtk_widget_keynav_failed (GTK_WIDGET (text_view),
+ leave_direction))
{
- if (leave_direction != -1 &&
- !gtk_widget_keynav_failed (GTK_WIDGET (text_view),
- leave_direction))
- {
- g_signal_emit_by_name (text_view, "move-focus", leave_direction);
- }
+ g_signal_emit_by_name (text_view, "move-focus", leave_direction);
}
return;
gtk_text_view_move_cursor_internal (text_view, step, count, extend_selection);
}
-static gboolean
+static void
gtk_text_view_move_viewport (GtkTextView *text_view,
GtkScrollStep step,
gint count)
case GTK_SCROLL_STEPS:
case GTK_SCROLL_PAGES:
case GTK_SCROLL_ENDS:
- adjustment = get_vadjustment (text_view);
+ adjustment = text_view->priv->vadjustment;
break;
case GTK_SCROLL_HORIZONTAL_STEPS:
case GTK_SCROLL_HORIZONTAL_PAGES:
case GTK_SCROLL_HORIZONTAL_ENDS:
- adjustment = get_hadjustment (text_view);
+ adjustment = text_view->priv->hadjustment;
break;
default:
- adjustment = get_vadjustment (text_view);
+ adjustment = text_view->priv->vadjustment;
break;
}
{
case GTK_SCROLL_STEPS:
case GTK_SCROLL_HORIZONTAL_STEPS:
- increment = adjustment->step_increment;
+ increment = gtk_adjustment_get_step_increment (adjustment);
break;
case GTK_SCROLL_PAGES:
case GTK_SCROLL_HORIZONTAL_PAGES:
- increment = adjustment->page_increment;
+ increment = gtk_adjustment_get_page_increment (adjustment);
break;
case GTK_SCROLL_ENDS:
case GTK_SCROLL_HORIZONTAL_ENDS:
- increment = adjustment->upper - adjustment->lower;
+ increment = gtk_adjustment_get_upper (adjustment) - gtk_adjustment_get_lower (adjustment);
break;
default:
increment = 0.0;
break;
}
- return set_adjustment_clamped (adjustment, adjustment->value + count * increment);
+ gtk_adjustment_set_value (adjustment, gtk_adjustment_get_value (adjustment) + count * increment);
}
static void
gboolean extend_selection)
{
GtkTextViewPrivate *priv;
- GtkAdjustment *adj;
+ GtkAdjustment *adjustment;
gint cursor_x_pos, cursor_y_pos;
GtkTextMark *insert_mark;
GtkTextIter old_insert;
g_return_val_if_fail (priv->vadjustment != NULL, FALSE);
- adj = priv->vadjustment;
+ adjustment = priv->vadjustment;
insert_mark = gtk_text_buffer_get_insert (get_buffer (text_view));
if (count < 0)
{
gtk_text_view_get_first_para_iter (text_view, &anchor);
- y0 = adj->page_size;
- y1 = adj->page_size + count * adj->page_increment;
+ y0 = gtk_adjustment_get_page_size (adjustment);
+ y1 = gtk_adjustment_get_page_size (adjustment) + count * gtk_adjustment_get_page_increment (adjustment);
}
else
{
gtk_text_view_get_first_para_iter (text_view, &anchor);
- y0 = count * adj->page_increment + adj->page_size;
+ y0 = count * gtk_adjustment_get_page_increment (adjustment) + gtk_adjustment_get_page_size (adjustment);
y1 = 0;
}
new_insert = old_insert;
- if (count < 0 && adj->value <= (adj->lower + 1e-12))
+ if (count < 0 && gtk_adjustment_get_value (adjustment) <= (gtk_adjustment_get_lower (adjustment) + 1e-12))
{
/* already at top, just be sure we are at offset 0 */
gtk_text_buffer_get_start_iter (get_buffer (text_view), &new_insert);
move_cursor (text_view, &new_insert, extend_selection);
}
- else if (count > 0 && adj->value >= (adj->upper - adj->page_size - 1e-12))
+ else if (count > 0 && gtk_adjustment_get_value (adjustment) >= (gtk_adjustment_get_upper (adjustment) - gtk_adjustment_get_page_size (adjustment) - 1e-12))
{
/* already at bottom, just be sure we are at the end */
gtk_text_buffer_get_end_iter (get_buffer (text_view), &new_insert);
{
gtk_text_view_get_virtual_cursor_pos (text_view, NULL, &cursor_x_pos, &cursor_y_pos);
- oldval = adj->value;
- newval = adj->value;
+ oldval = gtk_adjustment_get_value (adjustment);
+ newval = gtk_adjustment_get_value (adjustment);
- newval += count * adj->page_increment;
+ newval += count * gtk_adjustment_get_page_increment (adjustment);
- set_adjustment_clamped (adj, newval);
- cursor_y_pos += adj->value - oldval;
+ gtk_adjustment_set_value (adjustment, newval);
+ cursor_y_pos += gtk_adjustment_get_value (adjustment) - oldval;
gtk_text_layout_get_iter_at_pixel (priv->layout, &new_insert, cursor_x_pos, cursor_y_pos);
clamp_iter_onscreen (text_view, &new_insert);
gboolean extend_selection)
{
GtkTextViewPrivate *priv;
- GtkAdjustment *adj;
+ GtkAdjustment *adjustment;
gint cursor_x_pos, cursor_y_pos;
GtkTextMark *insert_mark;
GtkTextIter old_insert;
g_return_val_if_fail (priv->hadjustment != NULL, FALSE);
- adj = priv->hadjustment;
+ adjustment = priv->hadjustment;
insert_mark = gtk_text_buffer_get_insert (get_buffer (text_view));
new_insert = old_insert;
- if (count < 0 && adj->value <= (adj->lower + 1e-12))
+ if (count < 0 && gtk_adjustment_get_value (adjustment) <= (gtk_adjustment_get_lower (adjustment) + 1e-12))
{
/* already at far left, just be sure we are at offset 0 */
gtk_text_iter_set_line_offset (&new_insert, 0);
move_cursor (text_view, &new_insert, extend_selection);
}
- else if (count > 0 && adj->value >= (adj->upper - adj->page_size - 1e-12))
+ else if (count > 0 && gtk_adjustment_get_value (adjustment) >= (gtk_adjustment_get_upper (adjustment) - gtk_adjustment_get_page_size (adjustment) - 1e-12))
{
/* already at far right, just be sure we are at the end */
if (!gtk_text_iter_ends_line (&new_insert))
{
gtk_text_view_get_virtual_cursor_pos (text_view, NULL, &cursor_x_pos, &cursor_y_pos);
- oldval = adj->value;
- newval = adj->value;
+ oldval = gtk_adjustment_get_value (adjustment);
+ newval = gtk_adjustment_get_value (adjustment);
- newval += count * adj->page_increment;
+ newval += count * gtk_adjustment_get_page_increment (adjustment);
- set_adjustment_clamped (adj, newval);
- cursor_x_pos += adj->value - oldval;
+ gtk_adjustment_set_value (adjustment, newval);
+ cursor_x_pos += gtk_adjustment_get_value (adjustment) - oldval;
gtk_text_layout_get_iter_at_pixel (priv->layout, &new_insert, cursor_x_pos, cursor_y_pos);
clamp_iter_onscreen (text_view, &new_insert);
priv->scroll_after_paste = TRUE;
}
+static void
+gtk_text_view_buffer_changed_handler (GtkTextBuffer *buffer,
+ gpointer data)
+{
+ GtkTextView *text_view = data;
+ gtk_text_view_update_handles (text_view, GTK_TEXT_HANDLE_MODE_NONE);
+}
+
static void
gtk_text_view_toggle_overwrite (GtkTextView *text_view)
{
return text_view->priv->accepts_tab;
}
-static void
-gtk_text_view_compat_move_focus (GtkTextView *text_view,
- GtkDirectionType direction_type)
-{
- GSignalInvocationHint *hint = g_signal_get_invocation_hint (text_view);
-
- /* as of GTK+ 2.12, the "move-focus" signal has been moved to GtkWidget,
- * the evil code below makes sure that both emitting the signal and
- * calling the virtual function directly continue to work as expetcted
- */
-
- if (hint->signal_id == g_signal_lookup ("move-focus", GTK_TYPE_WIDGET))
- {
- /* if this is a signal emission, chain up */
-
- gboolean retval;
-
- g_signal_chain_from_overridden_handler (text_view,
- direction_type, &retval);
- }
- else
- {
- /* otherwise emit the signal, since somebody called the virtual
- * function directly
- */
-
- g_signal_emit_by_name (text_view, "move-focus", direction_type);
- }
-}
-
/*
* Selections
*/
}
static void
-move_mark_to_pointer_and_scroll (GtkTextView *text_view,
- const gchar *mark_name,
- GdkDevice *device)
+move_mark_to_pointer_and_scroll (GtkTextView *text_view,
+ const gchar *mark_name,
+ GdkDevice *device,
+ GdkInputSource source)
{
GtkTextIter newplace;
+ GtkTextBuffer *buffer;
GtkTextMark *mark;
+ buffer = get_buffer (text_view);
get_iter_at_pointer (text_view, device, &newplace, NULL, NULL);
-
- mark = gtk_text_buffer_get_mark (get_buffer (text_view), mark_name);
-
+
+ mark = gtk_text_buffer_get_mark (buffer, mark_name);
+
/* This may invalidate the layout */
DV(g_print (G_STRLOC": move mark\n"));
-
- gtk_text_buffer_move_mark (get_buffer (text_view),
- mark,
- &newplace);
-
+
+ gtk_text_buffer_move_mark (buffer, mark, &newplace);
+
DV(g_print (G_STRLOC": scrolling onscreen\n"));
gtk_text_view_scroll_mark_onscreen (text_view, mark);
#define LOWER_OFFSET_ANCHOR 0.2
static gboolean
-check_scroll (gdouble offset, GtkAdjustment *adj)
+check_scroll (gdouble offset, GtkAdjustment *adjustment)
{
if ((offset > UPPER_OFFSET_ANCHOR &&
- adj->value + adj->page_size < adj->upper) ||
+ gtk_adjustment_get_value (adjustment) + gtk_adjustment_get_page_size (adjustment) < gtk_adjustment_get_upper (adjustment)) ||
(offset < LOWER_OFFSET_ANCHOR &&
- adj->value > adj->lower))
+ gtk_adjustment_get_value (adjustment) > gtk_adjustment_get_lower (adjustment)))
return TRUE;
return FALSE;
GtkTextView *text_view;
GtkTextViewPrivate *priv;
GtkTextIter newplace;
- gint x, y, width, height;
+ gint x, y;
gdouble pointer_xoffset, pointer_yoffset;
text_view = GTK_TEXT_VIEW (data);
priv = text_view->priv;
get_iter_at_pointer (text_view, priv->dnd_device, &newplace, &x, &y);
- gdk_drawable_get_size (priv->text_window->bin_window, &width, &height);
gtk_text_buffer_move_mark (get_buffer (text_view),
priv->dnd_mark,
&newplace);
- pointer_xoffset = (gdouble) x / width;
- pointer_yoffset = (gdouble) y / height;
+ pointer_xoffset = (gdouble) x / gdk_window_get_width (priv->text_window->bin_window);
+ pointer_yoffset = (gdouble) y / gdk_window_get_height (priv->text_window->bin_window);
if (check_scroll (pointer_xoffset, priv->hadjustment) ||
check_scroll (pointer_yoffset, priv->vadjustment))
SelectionData *data)
{
GtkTextViewPrivate *priv;
+ GdkInputSource input_source;
+ GdkDevice *device;
priv = text_view->priv;
gdk_event_request_motions (event);
+ device = gdk_event_get_source_device ((GdkEvent *) event);
+ input_source = gdk_device_get_source (device);
+
if (priv->grab_device != event->device)
return FALSE;
if (data->granularity == SELECT_CHARACTERS)
{
- move_mark_to_pointer_and_scroll (text_view, "insert", event->device);
+ move_mark_to_pointer_and_scroll (text_view, "insert",
+ event->device, input_source);
}
else
{
else
gtk_text_buffer_select_range (buffer, &end, &orig_start);
- gtk_text_view_scroll_mark_onscreen (text_view,
+ gtk_text_view_scroll_mark_onscreen (text_view,
gtk_text_buffer_get_insert (buffer));
}
text_view->priv->scroll_timeout =
gdk_threads_add_timeout (50, selection_scan_timeout, text_view);
+ if (test_touchscreen || input_source == GDK_SOURCE_TOUCHSCREEN)
+ gtk_text_view_update_handles (text_view, GTK_TEXT_HANDLE_MODE_SELECTION);
+
return TRUE;
}
orig_start = ins;
orig_end = bound;
- if (button->state & GDK_SHIFT_MASK)
+ if (button->state &
+ gtk_widget_get_modifier_mask (GTK_WIDGET (text_view),
+ GDK_MODIFIER_INTENT_EXTEND_SELECTION))
{
/* Extend selection */
GtkTextIter old_ins, old_bound;
static void
gtk_text_view_set_attributes_from_style (GtkTextView *text_view,
- GtkTextAttributes *values,
- GtkStyle *style)
+ GtkTextAttributes *values)
{
- values->appearance.bg_color = style->base[GTK_STATE_NORMAL];
- values->appearance.fg_color = style->text[GTK_STATE_NORMAL];
+ GtkStyleContext *context;
+ GdkRGBA bg_color, fg_color;
+ GtkStateFlags state;
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (text_view));
+ state = gtk_widget_get_state_flags (GTK_WIDGET (text_view));
+
+ gtk_style_context_save (context);
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_VIEW);
+
+ gtk_style_context_get_background_color (context, state, &bg_color);
+ gtk_style_context_get_color (context, state, &fg_color);
+
+ values->appearance.bg_color.red = CLAMP (bg_color.red * 65535. + 0.5, 0, 65535);
+ values->appearance.bg_color.green = CLAMP (bg_color.green * 65535. + 0.5, 0, 65535);
+ values->appearance.bg_color.blue = CLAMP (bg_color.blue * 65535. + 0.5, 0, 65535);
+
+ values->appearance.fg_color.red = CLAMP (fg_color.red * 65535. + 0.5, 0, 65535);
+ values->appearance.fg_color.green = CLAMP (fg_color.green * 65535. + 0.5, 0, 65535);
+ values->appearance.fg_color.blue = CLAMP (fg_color.blue * 65535. + 0.5, 0, 65535);
if (values->font)
pango_font_description_free (values->font);
- values->font = pango_font_description_copy (style->font_desc);
+ gtk_style_context_get (context, state, "font", &values->font, NULL);
+
+ gtk_style_context_restore (context);
}
static void
style = gtk_text_attributes_new ();
- gtk_widget_ensure_style (widget);
- gtk_text_view_set_attributes_from_style (text_view,
- style,
- gtk_widget_get_style (widget));
+ gtk_text_view_set_attributes_from_style (text_view, style);
style->pixels_above_lines = priv->pixels_above_lines;
style->pixels_below_lines = priv->pixels_below_lines;
tmp_list = g_slist_next (tmp_list);
}
-
- gtk_text_view_invalidate (text_view);
}
}
* gtk_foo_bar_key_press_event (GtkWidget *widget,
* GdkEventKey *event)
* {
- * if ((key->keyval == GDK_Return || key->keyval == GDK_KP_Enter))
+ * if ((key->keyval == GDK_KEY_Return || key->keyval == GDK_KEY_KP_Enter))
* {
* if (gtk_text_view_im_context_filter_keypress (GTK_TEXT_VIEW (view), event))
* return TRUE;
{
/* Extract the selected text */
str = gtk_text_buffer_serialize (buffer, buffer,
- selection_data->target,
+ gtk_selection_data_get_target (selection_data),
&start, &end,
&len);
}
if (str)
{
gtk_selection_data_set (selection_data,
- selection_data->target,
+ gtk_selection_data_get_target (selection_data),
8, /* bytes */
(guchar *) str, len);
g_free (str);
{
GtkWidget *source_widget;
- suggested_action = context->suggested_action;
+ suggested_action = gdk_drag_context_get_suggested_action (context);
source_widget = gtk_drag_get_source_widget (context);
/* Default to MOVE, unless the user has
* pressed ctrl or alt to affect available actions
*/
- if ((context->actions & GDK_ACTION_MOVE) != 0)
+ if ((gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE) != 0)
suggested_action = GDK_ACTION_MOVE;
}
}
GtkTextIter start, end;
gboolean copy_tags = TRUE;
- if (selection_data->length != sizeof (src_buffer))
+ if (gtk_selection_data_get_length (selection_data) != sizeof (src_buffer))
return;
- memcpy (&src_buffer, selection_data->data, sizeof (src_buffer));
+ memcpy (&src_buffer, gtk_selection_data_get_data (selection_data), sizeof (src_buffer));
if (src_buffer == NULL)
return;
atoms = gtk_text_buffer_get_deserialize_formats (buffer, &n_atoms);
- for (list = context->targets; list; list = g_list_next (list))
+ for (list = gdk_drag_context_list_targets (context); list; list = g_list_next (list))
{
gint i;
}
}
}
- else if (selection_data->length > 0 &&
+ else if (gtk_selection_data_get_length (selection_data) > 0 &&
info == GTK_TEXT_BUFFER_TARGET_INFO_RICH_TEXT)
{
gboolean retval;
GError *error = NULL;
retval = gtk_text_buffer_deserialize (buffer, buffer,
- selection_data->target,
+ gtk_selection_data_get_target (selection_data),
&drop_point,
- (guint8 *) selection_data->data,
- selection_data->length,
+ (guint8 *) gtk_selection_data_get_data (selection_data),
+ gtk_selection_data_get_length (selection_data),
&error);
if (!retval)
done:
gtk_drag_finish (context, success,
- success && context->action == GDK_ACTION_MOVE,
+ success && gdk_drag_context_get_selected_action (context) == GDK_ACTION_MOVE,
time);
if (success)
* Returns: (transfer none): pointer to the horizontal #GtkAdjustment
*
* Since: 2.22
+ *
+ * Deprecated: 3.0: Use gtk_scrollable_get_hadjustment()
**/
GtkAdjustment*
gtk_text_view_get_hadjustment (GtkTextView *text_view)
{
g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), NULL);
- return get_hadjustment (text_view);
+ return text_view->priv->hadjustment;
+}
+
+static void
+gtk_text_view_set_hadjustment (GtkTextView *text_view,
+ GtkAdjustment *adjustment)
+{
+ GtkTextViewPrivate *priv = text_view->priv;
+
+ if (adjustment && priv->hadjustment == adjustment)
+ return;
+
+ if (priv->hadjustment != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (priv->hadjustment,
+ gtk_text_view_value_changed,
+ text_view);
+ g_object_unref (priv->hadjustment);
+ }
+
+ if (adjustment == NULL)
+ adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+ g_signal_connect (adjustment, "value-changed",
+ G_CALLBACK (gtk_text_view_value_changed), text_view);
+ priv->hadjustment = g_object_ref_sink (adjustment);
+ gtk_text_view_set_hadjustment_values (text_view);
+
+ g_object_notify (G_OBJECT (text_view), "hadjustment");
}
/**
* Returns: (transfer none): pointer to the vertical #GtkAdjustment
*
* Since: 2.22
+ *
+ * Deprecated: 3.0: Use gtk_scrollable_get_vadjustment()
**/
GtkAdjustment*
gtk_text_view_get_vadjustment (GtkTextView *text_view)
{
g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), NULL);
- return get_vadjustment (text_view);
+ return text_view->priv->vadjustment;
}
-static GtkAdjustment*
-get_hadjustment (GtkTextView *text_view)
+static void
+gtk_text_view_set_vadjustment (GtkTextView *text_view,
+ GtkAdjustment *adjustment)
{
- if (text_view->priv->hadjustment == NULL)
- gtk_text_view_set_scroll_adjustments (text_view,
- NULL, /* forces creation */
- text_view->priv->vadjustment);
+ GtkTextViewPrivate *priv = text_view->priv;
- return text_view->priv->hadjustment;
+ if (adjustment && priv->vadjustment == adjustment)
+ return;
+
+ if (priv->vadjustment != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (priv->vadjustment,
+ gtk_text_view_value_changed,
+ text_view);
+ g_object_unref (priv->vadjustment);
+ }
+
+ if (adjustment == NULL)
+ adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+ g_signal_connect (adjustment, "value-changed",
+ G_CALLBACK (gtk_text_view_value_changed), text_view);
+ priv->vadjustment = g_object_ref_sink (adjustment);
+ gtk_text_view_set_vadjustment_values (text_view);
+
+ g_object_notify (G_OBJECT (text_view), "vadjustment");
}
-static GtkAdjustment*
-get_vadjustment (GtkTextView *text_view)
+static void
+gtk_text_view_set_hadjustment_values (GtkTextView *text_view)
{
- if (text_view->priv->vadjustment == NULL)
- gtk_text_view_set_scroll_adjustments (text_view,
- text_view->priv->hadjustment,
- NULL); /* forces creation */
- return text_view->priv->vadjustment;
-}
+ GtkTextViewPrivate *priv;
+ gint screen_width;
+ gdouble old_value;
+ gdouble new_value;
+ gdouble new_upper;
+
+ priv = text_view->priv;
+
+ screen_width = SCREEN_WIDTH (text_view);
+ old_value = gtk_adjustment_get_value (priv->hadjustment);
+ new_upper = MAX (screen_width, priv->width);
+ g_object_set (priv->hadjustment,
+ "lower", 0.0,
+ "upper", new_upper,
+ "page-size", (gdouble)screen_width,
+ "step-increment", screen_width * 0.1,
+ "page-increment", screen_width * 0.9,
+ NULL);
+
+ new_value = CLAMP (old_value, 0, new_upper - screen_width);
+ if (new_value != old_value)
+ gtk_adjustment_set_value (priv->hadjustment, new_value);
+}
static void
-gtk_text_view_set_scroll_adjustments (GtkTextView *text_view,
- GtkAdjustment *hadj,
- GtkAdjustment *vadj)
+gtk_text_view_set_vadjustment_values (GtkTextView *text_view)
{
- GtkTextViewPrivate *priv = text_view->priv;
- gboolean need_adjust = FALSE;
+ GtkTextViewPrivate *priv;
+ GtkTextIter first_para;
+ gint screen_height;
+ gint y;
+ gdouble old_value;
+ gdouble new_value;
+ gdouble new_upper;
- if (hadj)
- g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
- else
- hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
- if (vadj)
- g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
- else
- vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+ priv = text_view->priv;
- if (priv->hadjustment && (priv->hadjustment != hadj))
- {
- g_signal_handlers_disconnect_by_func (priv->hadjustment,
- gtk_text_view_value_changed,
- text_view);
- g_object_unref (priv->hadjustment);
- }
+ screen_height = SCREEN_HEIGHT (text_view);
+ old_value = gtk_adjustment_get_value (priv->vadjustment);
+ new_upper = MAX (screen_height, priv->height);
- if (priv->vadjustment && (priv->vadjustment != vadj))
- {
- g_signal_handlers_disconnect_by_func (priv->vadjustment,
- gtk_text_view_value_changed,
- text_view);
- g_object_unref (priv->vadjustment);
- }
+ g_object_set (priv->vadjustment,
+ "lower", 0.0,
+ "upper", new_upper,
+ "page-size", (gdouble)screen_height,
+ "step-increment", screen_height * 0.1,
+ "page-increment", screen_height * 0.9,
+ NULL);
- if (priv->hadjustment != hadj)
- {
- priv->hadjustment = hadj;
- g_object_ref_sink (priv->hadjustment);
-
- g_signal_connect (priv->hadjustment, "value-changed",
- G_CALLBACK (gtk_text_view_value_changed),
- text_view);
- need_adjust = TRUE;
- }
+ /* Now adjust the value of the adjustment to keep the cursor at the
+ * same place in the buffer */
+ gtk_text_view_ensure_layout (text_view);
+ gtk_text_view_get_first_para_iter (text_view, &first_para);
+ gtk_text_layout_get_line_yrange (priv->layout, &first_para, &y, NULL);
- if (priv->vadjustment != vadj)
- {
- priv->vadjustment = vadj;
- g_object_ref_sink (priv->vadjustment);
-
- g_signal_connect (priv->vadjustment, "value-changed",
- G_CALLBACK (gtk_text_view_value_changed),
- text_view);
- need_adjust = TRUE;
- }
+ y += priv->first_para_pixels;
+
+ new_value = CLAMP (y, 0, new_upper - screen_height);
+ if (new_value != old_value)
+ gtk_adjustment_set_value (priv->vadjustment, new_value);
+ }
- if (need_adjust)
- gtk_text_view_value_changed (NULL, text_view);
-}
/* FIXME this adjust_allocation is a big cut-and-paste from
* GtkCList, needs to be some "official" way to do this
* into widget->allocation if the widget is not realized.
* FIXME someone figure out why this was.
*/
+ gtk_widget_get_allocation (widget, &allocation);
+
if (!gtk_widget_get_realized (widget))
{
if (gtk_widget_get_visible (widget))
adjust_allocation_recurse (widget, &scroll_data);
}
-
+
static void
-gtk_text_view_value_changed (GtkAdjustment *adj,
+gtk_text_view_value_changed (GtkAdjustment *adjustment,
GtkTextView *text_view)
{
GtkTextViewPrivate *priv;
priv = text_view->priv;
- /* Note that we oddly call this function with adj == NULL
+ /* Note that we oddly call this function with adjustment == NULL
* sometimes
*/
priv->onscreen_validated = FALSE;
DV(g_print(">Scroll offset changed %s/%g, onscreen_validated = FALSE ("G_STRLOC")\n",
- adj == priv->hadjustment ? "hadj" : adj == priv->vadjustment ? "vadj" : "none",
- adj ? adj->value : 0.0));
+ adjustment == priv->hadjustment ? "hadjustment" : adjustment == priv->vadjustment ? "vadjustment" : "none",
+ adjustment ? gtk_adjustment_get_value (adjustment) : 0.0));
- if (adj == priv->hadjustment)
+ if (adjustment == priv->hadjustment)
{
- dx = priv->xoffset - (gint)adj->value;
- priv->xoffset = adj->value;
+ dx = priv->xoffset - (gint)gtk_adjustment_get_value (adjustment);
+ priv->xoffset = gtk_adjustment_get_value (adjustment);
/* If the change is due to a size change we need
* to invalidate the entire text window because there might be
priv->width_changed = FALSE;
}
}
- else if (adj == priv->vadjustment)
+ else if (adjustment == priv->vadjustment)
{
- dy = priv->yoffset - (gint)adj->value;
- priv->yoffset = adj->value;
+ dy = priv->yoffset - (gint)gtk_adjustment_get_value (adjustment);
+ priv->yoffset = gtk_adjustment_get_value (adjustment);
if (priv->layout)
{
- gtk_text_layout_get_line_at_y (priv->layout, &iter, adj->value, &line_top);
+ gtk_text_layout_get_line_at_y (priv->layout, &iter, gtk_adjustment_get_value (adjustment), &line_top);
gtk_text_buffer_move_mark (get_buffer (text_view), priv->first_para_mark, &iter);
- priv->first_para_pixels = adj->value - line_top;
+ priv->first_para_pixels = gtk_adjustment_get_value (adjustment) - line_top;
}
}
*/
gtk_text_view_validate_onscreen (text_view);
- /* process exposes */
- if (gtk_widget_get_realized (GTK_WIDGET (text_view)))
- {
- DV (g_print ("Processing updates (%s)\n", G_STRLOC));
-
- if (priv->left_window)
- gdk_window_process_updates (priv->left_window->bin_window, TRUE);
-
- if (priv->right_window)
- gdk_window_process_updates (priv->right_window->bin_window, TRUE);
-
- if (priv->top_window)
- gdk_window_process_updates (priv->top_window->bin_window, TRUE);
-
- if (priv->bottom_window)
- gdk_window_process_updates (priv->bottom_window->bin_window, TRUE);
-
- gdk_window_process_updates (priv->text_window->bin_window, TRUE);
- }
-
/* If this got installed, get rid of it, it's just a waste of time. */
if (priv->first_validate_idle != 0)
{
* changes made by the validation are pushed through.
*/
gtk_text_view_update_im_spot_location (text_view);
-
+
+ gtk_text_view_update_handles (text_view,
+ _gtk_text_handle_get_mode (priv->text_handle));
+
DV(g_print(">End scroll offset changed handler ("G_STRLOC")\n"));
}
}
if (need_reset)
- gtk_text_view_reset_im_context (text_view);
+ {
+ gtk_text_view_reset_im_context (text_view);
+ gtk_text_view_update_handles (text_view,
+ _gtk_text_handle_get_mode (text_view->priv->text_handle));
+ }
}
static void
gtk_target_list_unref (view_list);
}
-static void
-gtk_text_view_get_cursor_location (GtkTextView *text_view,
- GdkRectangle *pos)
-{
- GtkTextIter insert;
-
- gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &insert,
- gtk_text_buffer_get_insert (get_buffer (text_view)));
-
- gtk_text_layout_get_cursor_locations (text_view->priv->layout, &insert, pos, NULL);
-}
-
static void
gtk_text_view_get_virtual_cursor_pos (GtkTextView *text_view,
GtkTextIter *cursor,
return;
if (x == -1 || y == -1)
- gtk_text_view_get_cursor_location (text_view, &pos);
+ gtk_text_view_get_cursor_locations (text_view, NULL, &pos, NULL);
text_view->priv->virtual_cursor_x = (x == -1) ? pos.x : x;
text_view->priv->virtual_cursor_y = (y == -1) ? pos.y + pos.height / 2 : y;
gtk_text_view_get_visible_rect (text_view, &onscreen_rect);
- gtk_size_request_get_size (GTK_SIZE_REQUEST (text_view->priv->popup_menu),
- &req, NULL);
+ gtk_widget_get_preferred_size (text_view->priv->popup_menu,
+ &req, NULL);
gtk_widget_get_allocation (widget, &allocation);
monitor_num = gdk_screen_get_monitor_at_point (screen, *x, *y);
gtk_menu_set_monitor (menu, monitor_num);
- gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
+ gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor);
*x = CLAMP (*x, monitor.x, monitor.x + MAX (0, monitor.width - req.width));
*y = CLAMP (*y, monitor.y, monitor.y + MAX (0, monitor.height - req.height));
GtkTextView *text_view;
gint button;
guint time;
+ GdkDevice *device;
} PopupInfo;
static gboolean
gtk_menu_shell_append (GTK_MENU_SHELL (priv->popup_menu), menuitem);
menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_SELECT_ALL, NULL);
+ gtk_widget_set_sensitive (menuitem,
+ gtk_text_buffer_get_char_count (priv->buffer) > 0);
g_signal_connect (menuitem, "activate",
G_CALLBACK (select_all_cb), text_view);
gtk_widget_show (menuitem);
0,
priv->popup_menu);
- if (info->button)
- gtk_menu_popup (GTK_MENU (priv->popup_menu), NULL, NULL,
- NULL, NULL,
+ if (info->device)
+ gtk_menu_popup_for_device (GTK_MENU (priv->popup_menu),
+ info->device, NULL, NULL, NULL, NULL, NULL,
info->button, info->time);
else
{
{
info->button = event->button;
info->time = event->time;
+ info->device = event->device;
}
else
{
info->button = 0;
info->time = gtk_get_current_event_time ();
+ info->device = NULL;
}
gtk_clipboard_request_contents (gtk_widget_get_clipboard (GTK_WIDGET (text_view),
text_window_realize (GtkTextWindow *win,
GtkWidget *widget)
{
+ GtkStyleContext *context;
+ GtkStateFlags state;
GdkWindow *window;
GdkWindowAttr attributes;
gint attributes_mask;
GdkCursor *cursor;
+ GdkRGBA color;
attributes.window_type = GDK_WINDOW_CHILD;
attributes.x = win->allocation.x;
&attributes, attributes_mask);
gdk_window_show (win->window);
- gdk_window_set_user_data (win->window, win->widget);
+ gtk_widget_register_window (win->widget, win->window);
gdk_window_lower (win->window);
attributes.x = 0;
attributes.height = win->allocation.height;
attributes.event_mask = (GDK_EXPOSURE_MASK |
GDK_SCROLL_MASK |
+ GDK_SMOOTH_SCROLL_MASK |
GDK_KEY_PRESS_MASK |
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
attributes_mask);
gdk_window_show (win->bin_window);
- gdk_window_set_user_data (win->bin_window, win->widget);
+ gtk_widget_register_window (win->widget, win->bin_window);
+
+ context = gtk_widget_get_style_context (widget);
+ state = gtk_widget_get_state_flags (widget);
if (win->type == GTK_TEXT_WINDOW_TEXT)
{
if (gtk_widget_is_sensitive (widget))
{
/* I-beam cursor */
- cursor = gdk_cursor_new_for_display (gdk_drawable_get_display (window),
+ cursor = gdk_cursor_new_for_display (gdk_window_get_display (window),
GDK_XTERM);
gdk_window_set_cursor (win->bin_window, cursor);
- gdk_cursor_unref (cursor);
+ g_object_unref (cursor);
}
gtk_im_context_set_client_window (GTK_TEXT_VIEW (widget)->priv->im_context,
win->window);
+ gtk_style_context_save (context);
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_VIEW);
- gdk_window_set_background (win->bin_window,
- >k_widget_get_style (widget)->base[gtk_widget_get_state (widget)]);
+ gtk_style_context_get_background_color (context, state, &color);
+ gdk_window_set_background_rgba (win->bin_window, &color);
+
+ gtk_style_context_restore (context);
}
else
{
- gdk_window_set_background (win->bin_window,
- >k_widget_get_style (widget)->bg[gtk_widget_get_state (widget)]);
+ gtk_style_context_get_background_color (context, state, &color);
+ gdk_window_set_background_rgba (win->bin_window, &color);
}
g_object_set_qdata (G_OBJECT (win->window),
NULL);
}
- gdk_window_set_user_data (win->window, NULL);
- gdk_window_set_user_data (win->bin_window, NULL);
+ gtk_widget_unregister_window (win->widget, win->window);
+ gtk_widget_unregister_window (win->widget, win->bin_window);
gdk_window_destroy (win->bin_window);
gdk_window_destroy (win->window);
win->window = NULL;
gtk_text_layout_get_cursor_locations (priv->layout, &iter,
&strong, &weak);
- /* cursor width calculation as in gtkstyle.c:draw_insertion_cursor(),
+ /* cursor width calculation as in gtkstylecontext.c:draw_insertion_cursor(),
* ignoring the text direction be exposing both sides of the cursor
*/
* @ypos: Y position of child in window coordinates
*
* Adds a child at fixed coordinates in one of the text widget's
- * windows. The window must have nonzero size (see
+ * windows.
+ *
+ * The window must have nonzero size (see
* gtk_text_view_set_border_window_size()). Note that the child
* coordinates are given relative to the #GdkWindow in question, and
* that these coordinates have no sane relationship to scrolling. When
* text window), you'll need to compute the child's correct position
* in buffer coordinates any time scrolling occurs or buffer changes
* occur, and then call gtk_text_view_move_child() to update the
- * child's position. Unfortunately there's no good way to detect that
- * scrolling has occurred, using the current API; a possible hack
- * would be to update all child positions when the scroll adjustments
- * change or the text buffer changes. See bug 64518 on
- * bugzilla.gnome.org for status of fixing this issue.
- **/
+ * child's position.
+ */
void
gtk_text_view_add_child_in_window (GtkTextView *text_view,
GtkWidget *child,
return gtk_text_layout_move_iter_visually (text_view->priv->layout, iter, count);
}
+
+/**
+ * gtk_text_view_set_input_purpose:
+ * @text_view: a #GtkTextView
+ * @purpose: the purpose
+ *
+ * Sets the #GtkTextView:input-purpose property which
+ * can be used by on-screen keyboards and other input
+ * methods to adjust their behaviour.
+ *
+ * Since: 3.6
+ */
+
+void
+gtk_text_view_set_input_purpose (GtkTextView *text_view,
+ GtkInputPurpose purpose)
+
+{
+ g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
+
+ if (gtk_text_view_get_input_purpose (text_view) != purpose)
+ {
+ g_object_set (G_OBJECT (text_view->priv->im_context),
+ "input-purpose", purpose,
+ NULL);
+
+ g_object_notify (G_OBJECT (text_view), "input-purpose");
+ }
+}
+
+/**
+ * gtk_text_view_get_input_purpose:
+ * @text_view: a #GtkTextView
+ *
+ * Gets the value of the #GtkTextView:input-purpose property.
+ *
+ * Since: 3.6
+ */
+
+GtkInputPurpose
+gtk_text_view_get_input_purpose (GtkTextView *text_view)
+{
+ GtkInputPurpose purpose;
+
+ g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), GTK_INPUT_PURPOSE_FREE_FORM);
+
+ g_object_get (G_OBJECT (text_view->priv->im_context),
+ "input-purpose", &purpose,
+ NULL);
+
+ return purpose;
+}
+
+/**
+ * gtk_text_view_set_input_hints:
+ * @text_view: a #GtkTextView
+ * @hints: the hints
+ *
+ * Sets the #GtkTextView:input-hints property, which
+ * allows input methods to fine-tune their behaviour.
+ *
+ * Since: 3.6
+ */
+
+void
+gtk_text_view_set_input_hints (GtkTextView *text_view,
+ GtkInputHints hints)
+
+{
+ g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
+
+ if (gtk_text_view_get_input_hints (text_view) != hints)
+ {
+ g_object_set (G_OBJECT (text_view->priv->im_context),
+ "input-hints", hints,
+ NULL);
+
+ g_object_notify (G_OBJECT (text_view), "input-hints");
+ }
+}
+
+/**
+ * gtk_text_view_get_input_hints:
+ * @text_view: a #GtkTextView
+ *
+ * Gets the value of the #GtkTextView:input-hints property.
+ *
+ * Since: 3.6
+ */
+
+GtkInputHints
+gtk_text_view_get_input_hints (GtkTextView *text_view)
+{
+ GtkInputHints hints;
+
+ g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), GTK_INPUT_HINT_NONE);
+
+ g_object_get (G_OBJECT (text_view->priv->im_context),
+ "input-hints", &hints,
+ NULL);
+
+ return hints;
+}