Jumping cursor patch
- From: Owen Taylor <otaylor redhat com>
- To: gtk-devel-list gnome org
- Cc: gtk-i18n-list gnome org
- Subject: Jumping cursor patch
- Date: 07 Jun 2001 15:22:32 -0400
I just implemented jumping cursors in GTK+ (that is, instead of
displaying two cursors, the cursor position depends on the
keyboard direction)
The following patches:
* Add an extra parameter pango_move_cursor_visually(), so it
can follow either the strong or weak cursor
* Add gdk_keymap_get_direction() and a ::direction_changed signal
to GdkKeymap.
When XKB is present, this direction is keyed off the name of
the current group - if the group name matches "arabic" "hebrew"
or "israelian", then it uses RTL for the direction, otherwise LTR.
* Add a global property "split-cursor" which determines whether
to use a double cursor, or a single jumping cursor.
* Make GtkEntry and GtkTextView obey this global property.
The main problem I notice testing it out is not really a new one -
if you are typing in the weak direction, then if you type
HEBREW<space>
It appears as:
WERBEH<space>|
Until you type another hebrew character, then jumps to
|M<space>WERBEH
Fixing this would somehow involve taking the cursor into account
in the bidi algorithm, probably by inserting a magic RTL mark
at the cursor location.
If anybody wants to review the patches or try them out; I'd appreciate
it. (You'll have to add 'gtk-split-cursor = 0' to your ~/.gtkrc-2.0 to
get the jumping cursor, since I left the split cursor as the default.)
I'll probably check them in sometime in the next day or two.
Regards,
Owen
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/pango/ChangeLog,v
retrieving revision 1.272
diff -u -r1.272 ChangeLog
--- ChangeLog 2001/06/07 16:40:01 1.272
+++ ChangeLog 2001/06/07 19:08:21
@@ -1,3 +1,9 @@
+Thu Jun 7 14:06:25 2001 Owen Taylor <otaylor redhat com>
+
+ * pango/pango-layout.c (pango_layout_move_cursor_visually):
+ Add a 'strong' parameter to allow moving either the strong
+ or the weak cursor visually, instead of the strong cursor.
+
2001-06-07 Havoc Pennington <hp redhat com>
* pango/Makefile.am: add libpango.la to _DEPENDENCIES for the
Index: docs/tmpl/layout.sgml
===================================================================
RCS file: /cvs/gnome/pango/docs/tmpl/layout.sgml,v
retrieving revision 1.16
diff -u -r1.16 layout.sgml
--- docs/tmpl/layout.sgml 2001/05/04 23:13:00 1.16
+++ docs/tmpl/layout.sgml 2001/06/07 19:08:21
@@ -385,6 +385,7 @@
</para>
@layout:
+ strong:
@old_index:
@old_trailing:
@direction:
Index: pango/pango-layout.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-layout.c,v
retrieving revision 1.64
diff -u -r1.64 pango-layout.c
--- pango/pango-layout.c 2001/05/31 23:52:46 1.64
+++ pango/pango-layout.c 2001/06/07 19:08:22
@@ -1135,6 +1135,9 @@
/**
* pango_layout_move_cursor_visually:
* @layout: a #PangoLayout.
+ * @strong: whether the moving cursor is the strong cursor or the
+ * weak cursor. The strong cursor is the cursor corresponding
+ * to text insertion in the base direction for the layout.
* @old_index: the byte index of the grapheme for the old index
* @old_trailing: if 0, the cursor was at the trailing edge of the
* grapheme indicated by @old_index, if > 0, the cursor
@@ -1171,6 +1174,7 @@
**/
void
pango_layout_move_cursor_visually (PangoLayout *layout,
+ gboolean strong,
int old_index,
int old_trailing,
int direction,
@@ -1228,7 +1232,7 @@
while (old_trailing--)
old_index = g_utf8_next_char (layout->text + old_index) - layout->text;
- log2vis_map = pango_layout_line_get_log2vis_map (line, TRUE);
+ log2vis_map = pango_layout_line_get_log2vis_map (line, strong);
n_vis = g_utf8_strlen (layout->text + line->start_index, line->length);
/* Clamp old_index to fit on the line */
@@ -1289,7 +1293,7 @@
vis_pos = 0;
}
- vis2log_map = pango_layout_line_get_vis2log_map (line, TRUE);
+ vis2log_map = pango_layout_line_get_vis2log_map (line, strong);
do
{
Index: pango/pango-layout.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-layout.h,v
retrieving revision 1.25
diff -u -r1.25 pango-layout.h
--- pango/pango-layout.h 2001/05/18 16:04:39 1.25
+++ pango/pango-layout.h 2001/06/07 19:08:22
@@ -142,6 +142,7 @@
PangoRectangle *strong_pos,
PangoRectangle *weak_pos);
void pango_layout_move_cursor_visually (PangoLayout *layout,
+ gboolean strong,
int old_index,
int old_trailing,
int direction,
Index: gdk/gdkkeys.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkkeys.c,v
retrieving revision 1.1
diff -u -r1.1 gdkkeys.c
--- gdk/gdkkeys.c 2000/12/06 05:31:25 1.1
+++ gdk/gdkkeys.c 2001/06/07 19:08:27
@@ -27,12 +27,19 @@
#include "gdkkeys.h"
#include <config.h>
+enum {
+ DIRECTION_CHANGED,
+ LAST_SIGNAL
+};
+
static void gdk_keymap_init (GdkKeymap *keymap);
static void gdk_keymap_class_init (GdkKeymapClass *klass);
static void gdk_keymap_finalize (GObject *object);
static gpointer parent_class = NULL;
+static guint signals[LAST_SIGNAL] = { 0 };
+
GType
gdk_keymap_get_type (void)
{
@@ -75,6 +82,16 @@
parent_class = g_type_class_peek_parent (klass);
object_class->finalize = gdk_keymap_finalize;
+
+ signals[DIRECTION_CHANGED] =
+ g_signal_newc ("direction_changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GdkKeymapClass, direction_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
}
static void
@@ -83,17 +100,6 @@
GdkKeymap *keymap = GDK_KEYMAP (object);
G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-GdkKeymap*
-gdk_keymap_get_default (void)
-{
- static GdkKeymap *keymap = NULL;
-
- if (keymap == NULL)
- keymap = g_object_new (gdk_keymap_get_type (), NULL);
-
- return keymap;
}
Index: gdk/gdkkeys.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkkeys.h,v
retrieving revision 1.1
diff -u -r1.1 gdkkeys.h
--- gdk/gdkkeys.h 2000/12/06 05:31:25 1.1
+++ gdk/gdkkeys.h 2001/06/07 19:08:27
@@ -70,6 +70,8 @@
struct _GdkKeymapClass
{
GObjectClass parent_class;
+
+ void (*direction_changed) (void);
};
GType gdk_keymap_get_type (void) G_GNUC_CONST;
@@ -77,25 +79,26 @@
GdkKeymap* gdk_keymap_get_default (void);
-guint gdk_keymap_lookup_key (GdkKeymap *keymap,
- const GdkKeymapKey *key);
-gboolean gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
- guint hardware_keycode,
- GdkModifierType state,
- gint group,
- guint *keyval,
- gint *effective_group,
- gint *level,
- GdkModifierType *unused_modifiers);
-gboolean gdk_keymap_get_entries_for_keyval (GdkKeymap *keymap,
- guint keyval,
- GdkKeymapKey **keys,
- gint *n_keys);
-gboolean gdk_keymap_get_entries_for_keycode (GdkKeymap *keymap,
- guint hardware_keycode,
- GdkKeymapKey **keys,
- guint **keyvals,
- gint *n_entries);
+guint gdk_keymap_lookup_key (GdkKeymap *keymap,
+ const GdkKeymapKey *key);
+gboolean gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
+ guint hardware_keycode,
+ GdkModifierType state,
+ gint group,
+ guint *keyval,
+ gint *effective_group,
+ gint *level,
+ GdkModifierType *unused_modifiers);
+gboolean gdk_keymap_get_entries_for_keyval (GdkKeymap *keymap,
+ guint keyval,
+ GdkKeymapKey **keys,
+ gint *n_keys);
+gboolean gdk_keymap_get_entries_for_keycode (GdkKeymap *keymap,
+ guint hardware_keycode,
+ GdkKeymapKey **keys,
+ guint **keyvals,
+ gint *n_entries);
+PangoDirection gdk_keymap_get_direction (GdkKeymap *keymap);
/* Key values
*/
Index: gdk/x11/gdkevents-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkevents-x11.c,v
retrieving revision 1.53
diff -u -r1.53 gdkevents-x11.c
--- gdk/x11/gdkevents-x11.c 2001/06/05 01:18:15 1.53
+++ gdk/x11/gdkevents-x11.c 2001/06/07 19:08:27
@@ -1428,24 +1428,38 @@
return_val = FALSE;
break;
-#ifdef HAVE_XKB
- case XkbMapNotify:
- ++_gdk_keymap_serial;
- return_val = FALSE;
- break;
-#endif
-
default:
- /* something else - (e.g., a Xinput event) */
-
- if (window_private &&
- !GDK_WINDOW_DESTROYED (window_private) &&
- (window_private->extension_events != 0))
- return_val = _gdk_input_other_event(event, xevent, window);
+#ifdef HAVE_XKB
+ if (xevent->type == _gdk_xkb_event_type)
+ {
+ XkbEvent *xkb_event = (XkbEvent *)xevent;
+
+ switch (xkb_event->any.xkb_type)
+ {
+ case XkbMapNotify:
+ ++_gdk_keymap_serial;
+ return_val = FALSE;
+ break;
+
+ case XkbStateNotify:
+ _gdk_keymap_state_changed ();
+ break;
+ }
+ }
else
- return_val = FALSE;
-
- break;
+#endif
+ {
+ /* something else - (e.g., a Xinput event) */
+
+ if (window_private &&
+ !GDK_WINDOW_DESTROYED (window_private) &&
+ (window_private->extension_events != 0))
+ return_val = _gdk_input_other_event(event, xevent, window);
+ else
+ return_val = FALSE;
+
+ break;
+ }
}
done:
Index: gdk/x11/gdkkeys-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkkeys-x11.c,v
retrieving revision 1.4
diff -u -r1.4 gdkkeys-x11.c
--- gdk/x11/gdkkeys-x11.c 2001/05/03 20:11:05 1.4
+++ gdk/x11/gdkkeys-x11.c 2001/06/07 19:08:27
@@ -56,6 +56,7 @@
#include <X11/XKBlib.h>
gboolean _gdk_use_xkb = FALSE;
+gint _gdk_xkb_event_type;
static XkbDescPtr xkb_desc = NULL;
static XkbDescPtr
@@ -70,10 +71,13 @@
xkb_desc = XkbGetMap (gdk_display, XkbKeySymsMask, XkbUseCoreKbd);
if (xkb_desc == NULL)
g_error ("Failed to get keymap");
+
+ XkbGetNames (gdk_display, XkbGroupNamesMask, xkb_desc);
}
else if (current_serial != _gdk_keymap_serial)
{
XkbGetUpdatedMap (gdk_display, XkbKeySymsMask, xkb_desc);
+ XkbGetNames (gdk_display, XkbGroupNamesMask, xkb_desc);
}
current_serial = _gdk_keymap_serial;
@@ -92,7 +96,19 @@
static gint keysyms_per_keycode = 0;
static XModifierKeymap* mod_keymap = NULL;
static GdkModifierType group_switch_mask = 0;
+static PangoDirection current_direction;
+static gboolean have_direction = FALSE;
+static GdkKeymap *default_keymap = NULL;
+
+GdkKeymap*
+gdk_keymap_get_default (void)
+{
+ if (default_keymap == NULL)
+ default_keymap = g_object_new (gdk_keymap_get_type (), NULL);
+ return default_keymap;
+}
+
static void
update_keymaps (void)
{
@@ -173,6 +189,60 @@
update_keymaps ();
return keymap;
+}
+
+#if HAVE_XKB
+
+PangoDirection
+get_direction (void)
+{
+ XkbDescRec *xkb = get_xkb ();
+ char *name;
+ XkbStateRec state_rec;
+ PangoDirection result;
+
+ XkbGetState (gdk_display, XkbUseCoreKbd, &state_rec);
+
+ name = gdk_atom_name (xkb->names->groups[state_rec.locked_group]);
+ if (g_strcasecmp (name, "arabic") == 0 ||
+ g_strcasecmp (name, "hebrew") == 0 ||
+ g_strcasecmp (name, "israelian") == 0)
+ result = PANGO_DIRECTION_RTL;
+ else
+ result = PANGO_DIRECTION_LTR;
+
+ g_free (name);
+
+ return result;
+}
+
+void
+_gdk_keymap_state_changed (void)
+{
+ if (default_keymap)
+ {
+ PangoDirection new_direction = get_direction ();
+
+ if (!have_direction || new_direction != current_direction)
+ {
+ have_direction = TRUE;
+ current_direction = new_direction;
+ g_signal_emit_by_name (G_OBJECT (default_keymap), "direction_changed");
+ }
+ }
+}
+#endif /* HAVE_XKB */
+
+PangoDirection
+gdk_keymap_get_direction (GdkKeymap *keymap)
+{
+ if (!have_direction)
+ {
+ current_direction = get_direction ();
+ have_direction = TRUE;
+ }
+
+ return current_direction;
}
/**
Index: gdk/x11/gdkmain-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkmain-x11.c,v
retrieving revision 1.130
diff -u -r1.130 gdkmain-x11.c
--- gdk/x11/gdkmain-x11.c 2001/05/20 22:48:40 1.130
+++ gdk/x11/gdkmain-x11.c 2001/06/07 19:08:27
@@ -170,21 +170,23 @@
{
gint xkb_major = XkbMajorVersion;
gint xkb_minor = XkbMinorVersion;
+ gint xkb_event_type;
if (XkbLibraryVersion (&xkb_major, &xkb_minor))
{
xkb_major = XkbMajorVersion;
xkb_minor = XkbMinorVersion;
- if (XkbQueryExtension (gdk_display, NULL, NULL, NULL,
+
+ if (XkbQueryExtension (gdk_display, NULL, &_gdk_xkb_event_type, NULL,
&xkb_major, &xkb_minor))
{
Bool detectable_autorepeat_supported;
-
+
_gdk_use_xkb = TRUE;
XkbSelectEvents (gdk_display,
XkbUseCoreKbd,
- XkbMapNotifyMask,
- XkbMapNotifyMask);
+ XkbMapNotifyMask | XkbStateNotifyMask,
+ XkbMapNotifyMask | XkbStateNotifyMask);
XkbSetDetectableAutoRepeat (gdk_display,
True,
Index: gdk/x11/gdkprivate-x11.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkprivate-x11.h,v
retrieving revision 1.12
diff -u -r1.12 gdkprivate-x11.h
--- gdk/x11/gdkprivate-x11.h 2001/03/29 21:17:44 1.12
+++ gdk/x11/gdkprivate-x11.h 2001/06/07 19:08:27
@@ -95,6 +95,8 @@
void _gdk_moveresize_handle_event (XEvent *event);
void _gdk_moveresize_configure_done (void);
+void _gdk_keymap_state_changed (void);
+
extern GdkDrawableClass _gdk_x11_drawable_class;
extern gboolean gdk_use_xshm;
extern Atom gdk_wm_delete_window;
@@ -115,6 +117,7 @@
#ifdef HAVE_XKB
extern gboolean _gdk_use_xkb;
extern gboolean _gdk_have_xkb_autorepeat;
+extern gint _gdk_xkb_event_type;
#endif
/* Whether we were able to turn on detectable-autorepeat using
Index: gtk/gtkentry.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkentry.c,v
retrieving revision 1.131
diff -u -r1.131 gtkentry.c
--- gtk/gtkentry.c 2001/06/01 19:26:00 1.131
+++ gtk/gtkentry.c 2001/06/07 19:08:27
@@ -211,6 +211,8 @@
static void gtk_entry_real_activate (GtkEntry *entry);
static void gtk_entry_popup_menu (GtkWidget *widget);
+static void gtk_entry_keymap_direction_changed (GdkKeymap *keymap,
+ GtkEntry *entry);
/* IM Context Callbacks
*/
static void gtk_entry_commit_cb (GtkIMContext *context,
@@ -1511,6 +1513,11 @@
entry->need_im_reset = TRUE;
gtk_im_context_focus_in (entry->im_context);
+ g_signal_connect_data (gdk_keymap_get_default (),
+ "direction_changed",
+ G_CALLBACK (gtk_entry_keymap_direction_changed), entry, NULL,
+ FALSE, FALSE);
+
gtk_entry_check_cursor_blink (entry);
return FALSE;
@@ -1530,6 +1537,10 @@
gtk_entry_check_cursor_blink (entry);
+ g_signal_disconnect_by_func (gdk_keymap_get_default (),
+ gtk_entry_keymap_direction_changed,
+ entry);
+
return FALSE;
}
@@ -2006,6 +2017,13 @@
}
}
+static void
+gtk_entry_keymap_direction_changed (GdkKeymap *keymap,
+ GtkEntry *entry)
+{
+ gtk_entry_queue_draw (entry);
+}
+
/* IM Context Callbacks
*/
@@ -2408,29 +2426,64 @@
gtk_entry_draw_cursor (GtkEntry *entry,
CursorType type)
{
+ GtkTextDirection keymap_direction =
+ (gdk_keymap_get_direction (gdk_keymap_get_default ()) == PANGO_DIRECTION_LTR) ?
+ GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
+ GtkTextDirection widget_direction = gtk_widget_get_direction (GTK_WIDGET (entry));
+
g_return_if_fail (entry != NULL);
g_return_if_fail (GTK_IS_ENTRY (entry));
if (GTK_WIDGET_DRAWABLE (entry))
{
GtkWidget *widget = GTK_WIDGET (entry);
+ gboolean split_cursor;
gint xoffset = INNER_BORDER - entry->scroll_offset;
gint strong_x, weak_x;
gint text_area_height;
+ GdkGC *gc1 = NULL;
+ GdkGC *gc2 = NULL;
+ gint x1 = 0;
+ gint x2 = 0;
gdk_window_get_size (entry->text_area, NULL, &text_area_height);
gtk_entry_get_cursor_locations (entry, type, &strong_x, &weak_x);
+
+ g_object_get (gtk_settings_get_global (),
+ "gtk-split-cursor", &split_cursor,
+ NULL);
+
+ if (split_cursor)
+ {
+ gc1 = entry->cursor_gc;
+ x1 = strong_x;
+
+ if (weak_x != strong_x)
+ {
+ gc2 = widget->style->text_gc[GTK_STATE_NORMAL];
+ x2 = weak_x;
+ }
+ }
+ else
+ {
+ gc1 = entry->cursor_gc;
+
+ if (keymap_direction == widget_direction)
+ x1 = strong_x;
+ else
+ x1 = weak_x;
+ }
+
+ gdk_draw_line (entry->text_area, gc1,
+ xoffset + x1, INNER_BORDER,
+ xoffset + x1, text_area_height - INNER_BORDER);
- gdk_draw_line (entry->text_area, entry->cursor_gc,
- xoffset + strong_x, INNER_BORDER,
- xoffset + strong_x, text_area_height - INNER_BORDER);
-
- if (weak_x != strong_x)
- gdk_draw_line (entry->text_area, widget->style->text_gc[GTK_STATE_NORMAL],
- xoffset + weak_x, INNER_BORDER,
- xoffset + weak_x, text_area_height - INNER_BORDER);
+ if (gc2)
+ gdk_draw_line (entry->text_area, gc2,
+ xoffset + x2, INNER_BORDER,
+ xoffset + x2, text_area_height - INNER_BORDER);
}
}
@@ -2624,15 +2677,32 @@
while (count != 0)
{
int new_index, new_trailing;
+ gboolean split_cursor;
+ gboolean strong;
+
+ g_object_get (gtk_settings_get_global (),
+ "gtk-split-cursor", &split_cursor,
+ NULL);
+
+ if (split_cursor)
+ {
+ GtkTextDirection keymap_direction =
+ (gdk_keymap_get_direction (gdk_keymap_get_default ()) == PANGO_DIRECTION_LTR) ?
+ GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
+
+ strong = keymap_direction == gtk_widget_get_direction (GTK_WIDGET (entry));
+ }
+ else
+ strong = TRUE;
if (count > 0)
{
- pango_layout_move_cursor_visually (layout, index, 0, 1, &new_index, &new_trailing);
+ pango_layout_move_cursor_visually (layout, index, strong, 0, 1, &new_index, &new_trailing);
count--;
}
else
{
- pango_layout_move_cursor_visually (layout, index, 0, -1, &new_index, &new_trailing);
+ pango_layout_move_cursor_visually (layout, index, strong, 0, -1, &new_index, &new_trailing);
count++;
}
@@ -3630,5 +3700,3 @@
show_cursor (entry);
}
}
-
-
Index: gtk/gtksettings.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtksettings.c,v
retrieving revision 1.11
diff -u -r1.11 gtksettings.c
--- gtk/gtksettings.c 2001/06/04 23:15:50 1.11
+++ gtk/gtksettings.c 2001/06/07 19:08:27
@@ -24,6 +24,7 @@
PROP_DOUBLE_CLICK_TIME,
PROP_CURSOR_BLINK,
PROP_CURSOR_BLINK_TIME,
+ PROP_SPLIT_CURSOR
};
@@ -151,6 +152,14 @@
G_PARAM_READWRITE),
NULL);
g_assert (result == PROP_CURSOR_BLINK_TIME);
+ result = settings_install_property_parser (class,
+ g_param_spec_boolean ("gtk-split-cursor",
+ _("Split Cursor"),
+ _("Whether two cursors should be displayed for mixed left-to-right and right-to-left text"),
+ TRUE,
+ G_PARAM_READWRITE),
+ NULL);
+ g_assert (result == PROP_SPLIT_CURSOR);
}
static void
Index: gtk/gtktextlayout.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktextlayout.c,v
retrieving revision 1.62
diff -u -r1.62 gtktextlayout.c
--- gtk/gtktextlayout.c 2001/05/21 05:35:03 1.62
+++ gtk/gtktextlayout.c 2001/06/07 19:08:27
@@ -94,14 +94,15 @@
static void gtk_text_layout_invalidated (GtkTextLayout *layout);
-static void gtk_text_layout_real_invalidate (GtkTextLayout *layout,
- const GtkTextIter *start,
- const GtkTextIter *end);
-static void gtk_text_layout_invalidate_cache (GtkTextLayout *layout,
- GtkTextLine *line);
-static void gtk_text_layout_real_free_line_data (GtkTextLayout *layout,
- GtkTextLine *line,
- GtkTextLineData *line_data);
+static void gtk_text_layout_real_invalidate (GtkTextLayout *layout,
+ const GtkTextIter *start,
+ const GtkTextIter *end);
+static void gtk_text_layout_invalidate_cache (GtkTextLayout *layout,
+ GtkTextLine *line);
+static void gtk_text_layout_invalidate_cursor_line (GtkTextLayout *layout);
+static void gtk_text_layout_real_free_line_data (GtkTextLayout *layout,
+ GtkTextLine *line,
+ GtkTextLineData *line_data);
static void gtk_text_layout_invalidate_all (GtkTextLayout *layout);
@@ -338,6 +339,30 @@
gtk_text_layout_invalidate_all (layout);
}
+/**
+ * gtk_text_layout_set_cursor_direction:
+ * @direction: the new direction(s) for which to draw cursors.
+ * %GTK_TEXT_DIR_NONE means draw cursors for both
+ * left-to-right insertion and right-to-left insertion.
+ * (The two cursors will be visually distinguished.)
+ *
+ * Sets which text directions (left-to-right and/or right-to-left) for
+ * which cursors will be drawn for the insertion point. The visual
+ * point at which new text is inserted depends on whether the new
+ * text is right-to-left or left-to-right, so it may be desired to
+ * make the drawn position of the cursor depend on the keyboard state.
+ **/
+void
+gtk_text_layout_set_cursor_direction (GtkTextLayout *layout,
+ GtkTextDirection direction)
+{
+ if (direction != layout->cursor_direction)
+ {
+ layout->cursor_direction = direction;
+ gtk_text_layout_invalidate_cursor_line (layout);
+ }
+}
+
void
gtk_text_layout_set_screen_width (GtkTextLayout *layout, gint width)
{
@@ -420,10 +445,6 @@
PangoAttrList *preedit_attrs,
gint cursor_pos)
{
- GtkTextIter iter;
- GtkTextLine *line;
- GtkTextLineData *line_data;
-
g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
g_return_if_fail (preedit_attrs != NULL || preedit_string == NULL);
@@ -451,19 +472,7 @@
layout->preedit_cursor = 0;
}
- /* Now invalidate the paragraph containing the cursor
- */
- gtk_text_buffer_get_iter_at_mark (layout->buffer, &iter,
- gtk_text_buffer_get_mark (layout->buffer, "insert"));
-
- line = _gtk_text_iter_get_text_line (&iter);
- line_data = _gtk_text_line_get_data (line, layout);
- if (line_data)
- {
- gtk_text_layout_invalidate_cache (layout, line);
- _gtk_text_line_invalidate_wrap (line, line_data);
- gtk_text_layout_invalidated (layout);
- }
+ gtk_text_layout_invalidate_cursor_line (layout);
}
void
@@ -647,7 +656,29 @@
}
}
+/* Now invalidate the paragraph containing the cursor
+ */
static void
+gtk_text_layout_invalidate_cursor_line (GtkTextLayout *layout)
+{
+ GtkTextIter iter;
+ GtkTextLine *line;
+ GtkTextLineData *line_data;
+
+ gtk_text_buffer_get_iter_at_mark (layout->buffer, &iter,
+ gtk_text_buffer_get_mark (layout->buffer, "insert"));
+
+ line = _gtk_text_iter_get_text_line (&iter);
+ line_data = _gtk_text_line_get_data (line, layout);
+ if (line_data)
+ {
+ gtk_text_layout_invalidate_cache (layout, line);
+ _gtk_text_line_invalidate_wrap (line, line_data);
+ gtk_text_layout_invalidated (layout);
+ }
+}
+
+static void
gtk_text_layout_real_invalidate (GtkTextLayout *layout,
const GtkTextIter *start,
const GtkTextIter *end)
@@ -1403,8 +1434,10 @@
gint start)
{
PangoRectangle strong_pos, weak_pos;
- GtkTextCursorDisplay *cursor;
-
+ GtkTextCursorDisplay *cursor = NULL; /* Quiet GCC */
+ gboolean add_weak = FALSE;
+ gboolean add_strong = FALSE;
+
/* Hide insertion cursor when we have a selection or the layout
* user has hidden the cursor.
*/
@@ -1415,30 +1448,45 @@
return;
pango_layout_get_cursor_pos (display->layout, start, &strong_pos, &weak_pos);
-
- cursor = g_new (GtkTextCursorDisplay, 1);
-
- cursor->x = PANGO_PIXELS (strong_pos.x);
- cursor->y = PANGO_PIXELS (strong_pos.y);
- cursor->height = PANGO_PIXELS (strong_pos.height);
- cursor->is_strong = TRUE;
- display->cursors = g_slist_prepend (display->cursors, cursor);
- if (weak_pos.x == strong_pos.x)
- cursor->is_weak = TRUE;
- else
+ if (layout->cursor_direction == GTK_TEXT_DIR_NONE)
{
- cursor->is_weak = FALSE;
+ add_strong = TRUE;
+ add_weak = TRUE;
+ }
+ else if (display->direction == layout->cursor_direction)
+ add_strong = TRUE;
+ else
+ add_weak = TRUE;
+ if (add_strong)
+ {
cursor = g_new (GtkTextCursorDisplay, 1);
- cursor->x = PANGO_PIXELS (weak_pos.x);
- cursor->y = PANGO_PIXELS (weak_pos.y);
- cursor->height = PANGO_PIXELS (weak_pos.height);
- cursor->is_strong = FALSE;
- cursor->is_weak = TRUE;
+ cursor->x = PANGO_PIXELS (strong_pos.x);
+ cursor->y = PANGO_PIXELS (strong_pos.y);
+ cursor->height = PANGO_PIXELS (strong_pos.height);
+ cursor->is_strong = TRUE;
+ cursor->is_weak = FALSE;
display->cursors = g_slist_prepend (display->cursors, cursor);
}
+
+ if (add_weak)
+ {
+ if (weak_pos.x == strong_pos.x && add_strong)
+ cursor->is_weak = TRUE;
+ else
+ {
+ cursor = g_new (GtkTextCursorDisplay, 1);
+
+ cursor->x = PANGO_PIXELS (weak_pos.x);
+ cursor->y = PANGO_PIXELS (weak_pos.y);
+ cursor->height = PANGO_PIXELS (weak_pos.height);
+ cursor->is_strong = FALSE;
+ cursor->is_weak = TRUE;
+ display->cursors = g_slist_prepend (display->cursors, cursor);
+ }
+ }
}
static gboolean
@@ -2838,25 +2886,31 @@
GtkTextLine *line = _gtk_text_iter_get_text_line (iter);
gint line_byte;
gint extra_back = 0;
+ gboolean strong;
int byte_count = _gtk_text_line_byte_count (line);
int new_index;
int new_trailing;
-
if (!display)
display = gtk_text_layout_get_line_display (layout, line, FALSE);
+
+ if (layout->cursor_direction == GTK_TEXT_DIR_NONE)
+ strong = TRUE;
+ else
+ strong = display->direction == layout->cursor_direction;
+
line_byte = line_display_iter_to_index (layout, display, iter);
if (count > 0)
{
- pango_layout_move_cursor_visually (display->layout, line_byte, 0, 1, &new_index, &new_trailing);
+ pango_layout_move_cursor_visually (display->layout, strong, line_byte, 0, 1, &new_index, &new_trailing);
count--;
}
else
{
- pango_layout_move_cursor_visually (display->layout, line_byte, 0, -1, &new_index, &new_trailing);
+ pango_layout_move_cursor_visually (display->layout, strong, line_byte, 0, -1, &new_index, &new_trailing);
count++;
}
Index: gtk/gtktextlayout.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktextlayout.h,v
retrieving revision 1.22
diff -u -r1.22 gtktextlayout.h
--- gtk/gtktextlayout.h 2001/01/04 17:48:43 1.22
+++ gtk/gtktextlayout.h 2001/06/07 19:08:27
@@ -157,6 +157,11 @@
/* Whether to show the insertion cursor */
guint cursor_visible : 1;
+ /* For what GtkTextDirection to draw cursor GTK_TEXT_DIR_NONE -
+ * means draw both cursors.
+ */
+ gint cursor_direction : 2;
+
/* The preedit string and attributes, if any */
gchar *preedit_string;
@@ -248,6 +253,8 @@
void gtk_text_layout_set_contexts (GtkTextLayout *layout,
PangoContext *ltr_context,
PangoContext *rtl_context);
+void gtk_text_layout_set_cursor_direction (GtkTextLayout *layout,
+ GtkTextDirection direction);
void gtk_text_layout_default_style_changed (GtkTextLayout *layout);
void gtk_text_layout_set_screen_width (GtkTextLayout *layout,
Index: gtk/gtktextview.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktextview.c,v
retrieving revision 1.90
diff -u -r1.90 gtktextview.c
--- gtk/gtktextview.c 2001/06/04 23:53:43 1.90
+++ gtk/gtktextview.c 2001/06/07 19:08:27
@@ -237,20 +237,21 @@
static void gtk_text_view_set_attributes_from_style (GtkTextView *text_view,
GtkTextAttributes *values,
GtkStyle *style);
-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_reset_im_context (GtkTextView *text_view);
-static void gtk_text_view_start_selection_drag (GtkTextView *text_view,
- const GtkTextIter *iter,
- GdkEventButton *event);
-static gboolean gtk_text_view_end_selection_drag (GtkTextView *text_view,
- GdkEventButton *event);
-static void gtk_text_view_start_selection_dnd (GtkTextView *text_view,
- const GtkTextIter *iter,
- GdkEventMotion *event);
-static void gtk_text_view_check_cursor_blink (GtkTextView *text_view);
-static void gtk_text_view_pend_cursor_blink (GtkTextView *text_view);
-static void gtk_text_view_stop_cursor_blink (GtkTextView *text_view);
+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_reset_im_context (GtkTextView *text_view);
+static void gtk_text_view_start_selection_drag (GtkTextView *text_view,
+ const GtkTextIter *iter,
+ GdkEventButton *event);
+static gboolean gtk_text_view_end_selection_drag (GtkTextView *text_view,
+ GdkEventButton *event);
+static void gtk_text_view_start_selection_dnd (GtkTextView *text_view,
+ const GtkTextIter *iter,
+ GdkEventMotion *event);
+static void gtk_text_view_check_cursor_blink (GtkTextView *text_view);
+static void gtk_text_view_pend_cursor_blink (GtkTextView *text_view);
+static void gtk_text_view_stop_cursor_blink (GtkTextView *text_view);
static void gtk_text_view_value_changed (GtkAdjustment *adj,
GtkTextView *view);
@@ -3344,6 +3345,13 @@
return FALSE;
}
+static void
+keymap_direction_changed (GdkKeymap *keymap,
+ GtkTextView *text_view)
+{
+ gtk_text_view_check_keymap_direction (text_view);
+}
+
static gint
gtk_text_view_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
{
@@ -3358,6 +3366,12 @@
gtk_text_view_check_cursor_blink (text_view);
}
+ g_signal_connect_data (gdk_keymap_get_default (),
+ "direction_changed",
+ G_CALLBACK (keymap_direction_changed), text_view, NULL,
+ FALSE, FALSE);
+ gtk_text_view_check_keymap_direction (text_view);
+
text_view->need_im_reset = TRUE;
gtk_im_context_focus_in (GTK_TEXT_VIEW (widget)->im_context);
@@ -3378,6 +3392,10 @@
gtk_text_view_check_cursor_blink (text_view);
}
+ g_signal_disconnect_by_func (gdk_keymap_get_default (),
+ keymap_direction_changed,
+ text_view);
+
text_view->need_im_reset = TRUE;
gtk_im_context_focus_out (GTK_TEXT_VIEW (widget)->im_context);
@@ -4275,6 +4293,28 @@
}
static void
+gtk_text_view_check_keymap_direction (GtkTextView *text_view)
+{
+ if (text_view->layout)
+ {
+ gboolean split_cursor;
+ GtkTextDirection new_dir;
+
+ g_object_get (gtk_settings_get_global (),
+ "gtk-split-cursor", &split_cursor,
+ NULL);
+ if (split_cursor)
+ new_dir = GTK_TEXT_DIR_NONE;
+ else
+ new_dir = (gdk_keymap_get_direction (gdk_keymap_get_default ()) == PANGO_DIRECTION_LTR) ?
+ GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
+
+ if (text_view->layout->cursor_direction != new_dir)
+ gtk_text_layout_set_cursor_direction (text_view->layout, new_dir);
+ }
+}
+
+static void
gtk_text_view_ensure_layout (GtkTextView *text_view)
{
GtkWidget *widget;
@@ -4326,6 +4366,8 @@
g_object_unref (G_OBJECT (ltr_context));
g_object_unref (G_OBJECT (rtl_context));
+
+ gtk_text_view_check_keymap_direction (text_view);
style = gtk_text_attributes_new ();
[Date Prev][
Date Next] [Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]