Add new infrastructure for notifications of failed keyboard navigation and
2006-11-16 Michael Natterer <mitch@imendio.com> Add new infrastructure for notifications of failed keyboard navigation and navigation with restricted set of keys. The patch handles configurable beeping, navigating the GUI with cursor keys only (as in phone environments), and configurable wrap-around. Fixes bugs #322640, #70986, #318827, #334726, #334742 and #309291. * gtk/gtksettings.c: added properties gtk-keynav-cursor-only, gtk-keynav-wrap-around and gtk-error-bell. * gtk/gtkwidget.[ch]: added new signal "keynav-failed" and public API to emit it. Added New function gtk_widget_error_bell() which looks at the gtk-error-bell setting and calls gdk_window_beep() accordingly. * gtk/gtk.symbols: add the new widget symbols. * gtk/gtkcellrendereraccel.c * gtk/gtkimcontextsimple.c * gtk/gtkmenu.c * gtk/gtknotebook.c: use gtk_widget_error_bell() or look at the gtk-error-bell setting instead of calling gdk_display_beep() unconditionally. * gtk/gtkcombobox.c * gtk/gtkentry.c * gtk/gtkiconview.c * gtk/gtklabel.c * gtk/gtkmenushell.c * gtk/gtkspinbutton.c * gtk/gtktextview.c * gtk/gtktreeview.c: call gtk_widget_error_bell() on failed keynav. * gtk/gtkentry.c * gtk/gtklabel.c * gtk/gtkrange.c * gtk/gtktextview.c: consult gtk_widget_keynav_failed() on failed cursor navigation and leave the widget if it returns FALSE. * gtk/gtkmenushell.c * gtk/gtknotebook.c: only wrap around if gtk-keynav-wrap-around is TRUE. * gtk/gtkradiobutton.c: ask gtk_widget_keynav_failed() to decide whether to to wrap-around, and don't select active items on cursor navigation if gtk-keynav-cursor-only is TRUE. Should look at gtk-keynav-wrap-around too, will look into that.
This commit is contained in:
parent
af6b361d6b
commit
7f374a74ba
51
ChangeLog
51
ChangeLog
@ -1,3 +1,54 @@
|
||||
2006-11-16 Michael Natterer <mitch@imendio.com>
|
||||
|
||||
Add new infrastructure for notifications of failed keyboard
|
||||
navigation and navigation with restricted set of keys.
|
||||
|
||||
The patch handles configurable beeping, navigating the GUI with
|
||||
cursor keys only (as in phone environments), and configurable
|
||||
wrap-around. Fixes bugs #322640, #70986, #318827, #334726, #334742
|
||||
and #309291.
|
||||
|
||||
* gtk/gtksettings.c: added properties gtk-keynav-cursor-only,
|
||||
gtk-keynav-wrap-around and gtk-error-bell.
|
||||
|
||||
* gtk/gtkwidget.[ch]: added new signal "keynav-failed" and public
|
||||
API to emit it. Added New function gtk_widget_error_bell() which
|
||||
looks at the gtk-error-bell setting and calls gdk_window_beep()
|
||||
accordingly.
|
||||
|
||||
* gtk/gtk.symbols: add the new widget symbols.
|
||||
|
||||
* gtk/gtkcellrendereraccel.c
|
||||
* gtk/gtkimcontextsimple.c
|
||||
* gtk/gtkmenu.c
|
||||
* gtk/gtknotebook.c: use gtk_widget_error_bell() or look at the
|
||||
gtk-error-bell setting instead of calling gdk_display_beep()
|
||||
unconditionally.
|
||||
|
||||
* gtk/gtkcombobox.c
|
||||
* gtk/gtkentry.c
|
||||
* gtk/gtkiconview.c
|
||||
* gtk/gtklabel.c
|
||||
* gtk/gtkmenushell.c
|
||||
* gtk/gtkspinbutton.c
|
||||
* gtk/gtktextview.c
|
||||
* gtk/gtktreeview.c: call gtk_widget_error_bell() on failed keynav.
|
||||
|
||||
* gtk/gtkentry.c
|
||||
* gtk/gtklabel.c
|
||||
* gtk/gtkrange.c
|
||||
* gtk/gtktextview.c: consult gtk_widget_keynav_failed() on failed
|
||||
cursor navigation and leave the widget if it returns FALSE.
|
||||
|
||||
* gtk/gtkmenushell.c
|
||||
* gtk/gtknotebook.c: only wrap around if gtk-keynav-wrap-around
|
||||
is TRUE.
|
||||
|
||||
* gtk/gtkradiobutton.c: ask gtk_widget_keynav_failed() to decide
|
||||
whether to to wrap-around, and don't select active items on cursor
|
||||
navigation if gtk-keynav-cursor-only is TRUE. Should look at
|
||||
gtk-keynav-wrap-around too, will look into that.
|
||||
|
||||
2006-11-16 Emmanuele Bassi <ebassi@gnome.org>
|
||||
|
||||
* gtk/gtkrecentmanager.c:
|
||||
|
@ -4470,6 +4470,7 @@ gtk_widget_create_pango_layout
|
||||
gtk_widget_destroy
|
||||
gtk_widget_destroyed
|
||||
gtk_widget_ensure_style
|
||||
gtk_widget_error_bell
|
||||
gtk_widget_event
|
||||
gtk_widget_freeze_child_notify
|
||||
gtk_widget_get_accessible
|
||||
@ -4511,6 +4512,7 @@ gtk_widget_hide_on_delete
|
||||
gtk_widget_intersect
|
||||
gtk_widget_is_ancestor
|
||||
gtk_widget_is_focus
|
||||
gtk_widget_keynav_failed
|
||||
gtk_widget_list_accel_closures
|
||||
gtk_widget_list_mnemonic_labels
|
||||
gtk_widget_map
|
||||
|
@ -456,7 +456,7 @@ grab_key_callback (GtkWidget *widget,
|
||||
{
|
||||
if (!gtk_accelerator_valid (accel_key, accel_mods))
|
||||
{
|
||||
gdk_display_beep (display);
|
||||
gtk_widget_error_bell (widget);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -4978,7 +4978,10 @@ gtk_combo_box_real_move_active (GtkComboBox *combo_box,
|
||||
gboolean found;
|
||||
|
||||
if (!combo_box->priv->model)
|
||||
return;
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (combo_box));
|
||||
return;
|
||||
}
|
||||
|
||||
active_iter = gtk_combo_box_get_active_iter (combo_box, &iter);
|
||||
|
||||
@ -5024,28 +5027,28 @@ gtk_combo_box_real_move_active (GtkComboBox *combo_box,
|
||||
return;
|
||||
}
|
||||
|
||||
if (found && active_iter)
|
||||
{
|
||||
GtkTreePath *old_path;
|
||||
GtkTreePath *new_path;
|
||||
|
||||
old_path = gtk_tree_model_get_path (combo_box->priv->model, &iter);
|
||||
new_path = gtk_tree_model_get_path (combo_box->priv->model, &new_iter);
|
||||
|
||||
if (gtk_tree_path_compare (old_path, new_path) == 0)
|
||||
found = FALSE;
|
||||
|
||||
gtk_tree_path_free (old_path);
|
||||
gtk_tree_path_free (new_path);
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
if (active_iter)
|
||||
{
|
||||
GtkTreePath *old_path;
|
||||
GtkTreePath *new_path;
|
||||
|
||||
old_path = gtk_tree_model_get_path (combo_box->priv->model, &iter);
|
||||
new_path = gtk_tree_model_get_path (combo_box->priv->model, &new_iter);
|
||||
|
||||
if (gtk_tree_path_compare (old_path, new_path) == 0)
|
||||
found = FALSE;
|
||||
|
||||
gtk_tree_path_free (old_path);
|
||||
gtk_tree_path_free (new_path);
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
gtk_combo_box_set_active_iter (combo_box, &new_iter);
|
||||
return;
|
||||
}
|
||||
gtk_combo_box_set_active_iter (combo_box, &new_iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (combo_box));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1709,12 +1709,18 @@ gtk_entry_button_press (GtkWidget *widget,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->button == 2 && event->type == GDK_BUTTON_PRESS && entry->editable)
|
||||
else if (event->button == 2 && event->type == GDK_BUTTON_PRESS)
|
||||
{
|
||||
priv->insert_pos = tmp_pos;
|
||||
gtk_entry_paste (entry, GDK_SELECTION_PRIMARY);
|
||||
|
||||
return TRUE;
|
||||
if (entry->editable)
|
||||
{
|
||||
priv->insert_pos = tmp_pos;
|
||||
gtk_entry_paste (entry, GDK_SELECTION_PRIMARY);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_error_bell (widget);
|
||||
}
|
||||
}
|
||||
else if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
|
||||
{
|
||||
@ -1976,6 +1982,9 @@ gtk_entry_key_press (GtkWidget *widget,
|
||||
*/
|
||||
return TRUE;
|
||||
|
||||
if (!entry->editable && event->length)
|
||||
gtk_widget_error_bell (widget);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -2329,7 +2338,7 @@ gtk_entry_real_insert_text (GtkEditable *editable,
|
||||
n_chars = g_utf8_strlen (new_text, new_text_length);
|
||||
if (entry->text_max_length > 0 && n_chars + entry->text_length > entry->text_max_length)
|
||||
{
|
||||
gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (entry)));
|
||||
gtk_widget_error_bell (GTK_WIDGET (entry));
|
||||
n_chars = entry->text_max_length - entry->text_length;
|
||||
new_text_length = g_utf8_offset_to_pointer (new_text, n_chars) - new_text;
|
||||
}
|
||||
@ -2535,7 +2544,6 @@ gtk_entry_move_cursor (GtkEntry *entry,
|
||||
new_pos = current_x < bound_x ? entry->current_pos : entry->selection_bound;
|
||||
else
|
||||
new_pos = current_x > bound_x ? entry->current_pos : entry->selection_bound;
|
||||
|
||||
break;
|
||||
}
|
||||
case GTK_MOVEMENT_LOGICAL_POSITIONS:
|
||||
@ -2566,6 +2574,27 @@ gtk_entry_move_cursor (GtkEntry *entry,
|
||||
break;
|
||||
case GTK_MOVEMENT_VISUAL_POSITIONS:
|
||||
new_pos = gtk_entry_move_visually (entry, new_pos, count);
|
||||
if (entry->current_pos == new_pos)
|
||||
{
|
||||
if (!extend_selection)
|
||||
{
|
||||
if (!gtk_widget_keynav_failed (GTK_WIDGET (entry),
|
||||
count > 0 ?
|
||||
GTK_DIR_RIGHT : GTK_DIR_LEFT))
|
||||
{
|
||||
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (entry));
|
||||
|
||||
if (toplevel)
|
||||
gtk_widget_child_focus (toplevel,
|
||||
count > 0 ?
|
||||
GTK_DIR_RIGHT : GTK_DIR_LEFT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (entry));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GTK_MOVEMENT_WORDS:
|
||||
while (count > 0)
|
||||
@ -2578,11 +2607,15 @@ gtk_entry_move_cursor (GtkEntry *entry,
|
||||
new_pos = gtk_entry_move_backward_word (entry, new_pos, FALSE);
|
||||
count++;
|
||||
}
|
||||
if (entry->current_pos == new_pos)
|
||||
gtk_widget_error_bell (GTK_WIDGET (entry));
|
||||
break;
|
||||
case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
|
||||
case GTK_MOVEMENT_PARAGRAPH_ENDS:
|
||||
case GTK_MOVEMENT_BUFFER_ENDS:
|
||||
new_pos = count < 0 ? 0 : entry->text_length;
|
||||
if (entry->current_pos == new_pos)
|
||||
gtk_widget_error_bell (GTK_WIDGET (entry));
|
||||
break;
|
||||
case GTK_MOVEMENT_DISPLAY_LINES:
|
||||
case GTK_MOVEMENT_PARAGRAPHS:
|
||||
@ -2624,11 +2657,15 @@ gtk_entry_delete_from_cursor (GtkEntry *entry,
|
||||
GtkEditable *editable = GTK_EDITABLE (entry);
|
||||
gint start_pos = entry->current_pos;
|
||||
gint end_pos = entry->current_pos;
|
||||
gint old_n_bytes = entry->n_bytes;
|
||||
|
||||
_gtk_entry_reset_im_context (entry);
|
||||
|
||||
if (!entry->editable)
|
||||
return;
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (entry));
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry->selection_bound != entry->current_pos)
|
||||
{
|
||||
@ -2685,7 +2722,10 @@ gtk_entry_delete_from_cursor (GtkEntry *entry,
|
||||
gtk_entry_delete_whitespace (entry);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (entry->n_bytes == old_n_bytes)
|
||||
gtk_widget_error_bell (GTK_WIDGET (entry));
|
||||
|
||||
gtk_entry_pend_cursor_blink (entry);
|
||||
}
|
||||
|
||||
@ -2698,7 +2738,10 @@ gtk_entry_backspace (GtkEntry *entry)
|
||||
_gtk_entry_reset_im_context (entry);
|
||||
|
||||
if (!entry->editable || !entry->text)
|
||||
return;
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (entry));
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry->selection_bound != entry->current_pos)
|
||||
{
|
||||
@ -2751,6 +2794,10 @@ gtk_entry_backspace (GtkEntry *entry)
|
||||
|
||||
g_free (log_attrs);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (entry));
|
||||
}
|
||||
|
||||
gtk_entry_pend_cursor_blink (entry);
|
||||
}
|
||||
@ -2784,6 +2831,10 @@ gtk_entry_cut_clipboard (GtkEntry *entry)
|
||||
if (gtk_editable_get_selection_bounds (editable, &start, &end))
|
||||
gtk_editable_delete_text (editable, start, end);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (entry));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2791,6 +2842,8 @@ gtk_entry_paste_clipboard (GtkEntry *entry)
|
||||
{
|
||||
if (entry->editable)
|
||||
gtk_entry_paste (entry, GDK_NONE);
|
||||
else
|
||||
gtk_widget_error_bell (GTK_WIDGET (entry));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -3796,7 +3796,10 @@ gtk_icon_view_move_cursor_up_down (GtkIconView *icon_view,
|
||||
}
|
||||
|
||||
if (!item)
|
||||
return;
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (icon_view));
|
||||
return;
|
||||
}
|
||||
|
||||
if (icon_view->priv->ctrl_pressed ||
|
||||
!icon_view->priv->shift_pressed ||
|
||||
@ -3847,6 +3850,9 @@ gtk_icon_view_move_cursor_page_up_down (GtkIconView *icon_view,
|
||||
icon_view->priv->cursor_item,
|
||||
count);
|
||||
|
||||
if (item == icon_view->priv->cursor_item)
|
||||
gtk_widget_error_bell (GTK_WIDGET (icon_view));
|
||||
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
@ -3915,7 +3921,10 @@ gtk_icon_view_move_cursor_left_right (GtkIconView *icon_view,
|
||||
}
|
||||
|
||||
if (!item)
|
||||
return;
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (icon_view));
|
||||
return;
|
||||
}
|
||||
|
||||
if (icon_view->priv->ctrl_pressed ||
|
||||
!icon_view->priv->shift_pressed ||
|
||||
@ -3958,6 +3967,9 @@ gtk_icon_view_move_cursor_start_end (GtkIconView *icon_view,
|
||||
|
||||
item = list ? list->data : NULL;
|
||||
|
||||
if (item == icon_view->priv->cursor_item)
|
||||
gtk_widget_error_bell (GTK_WIDGET (icon_view));
|
||||
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include "gtkaccelgroup.h"
|
||||
#include "gtkimcontextsimple.h"
|
||||
#include "gtksettings.h"
|
||||
#include "gtkwidget.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkalias.h"
|
||||
|
||||
@ -1175,6 +1177,31 @@ check_hex (GtkIMContextSimple *context_simple,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
beep_window (GdkWindow *window)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
gdk_window_get_user_data (window, &widget);
|
||||
|
||||
if (GTK_IS_WIDGET (widget))
|
||||
{
|
||||
gtk_widget_error_bell (widget);
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkScreen *screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
|
||||
gboolean beep;
|
||||
|
||||
g_object_get (gtk_settings_get_for_screen (screen),
|
||||
"gtk-error-bell", &beep,
|
||||
NULL);
|
||||
|
||||
if (beep)
|
||||
gdk_window_beep (window);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
no_sequence_matches (GtkIMContextSimple *context_simple,
|
||||
gint n_compose,
|
||||
@ -1212,7 +1239,7 @@ no_sequence_matches (GtkIMContextSimple *context_simple,
|
||||
context_simple->compose_buffer[0] = 0;
|
||||
if (n_compose > 1) /* Invalid sequence */
|
||||
{
|
||||
gdk_display_beep (gdk_drawable_get_display (event->window));
|
||||
beep_window (event->window);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1317,7 +1344,7 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
|
||||
else
|
||||
{
|
||||
/* invalid hex sequence */
|
||||
gdk_display_beep (gdk_drawable_get_display (event->window));
|
||||
beep_window (event->window);
|
||||
|
||||
context_simple->tentative_match = 0;
|
||||
context_simple->in_hex_sequence = FALSE;
|
||||
@ -1403,7 +1430,7 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
|
||||
{
|
||||
/* invalid hex sequence */
|
||||
if (n_compose > 0)
|
||||
gdk_display_beep (gdk_drawable_get_display (event->window));
|
||||
beep_window (event->window);
|
||||
|
||||
context_simple->tentative_match = 0;
|
||||
context_simple->in_hex_sequence = FALSE;
|
||||
@ -1438,7 +1465,7 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
|
||||
else if (!is_hex_end)
|
||||
{
|
||||
/* non-hex character in hex sequence */
|
||||
gdk_display_beep (gdk_drawable_get_display (event->window));
|
||||
beep_window (event->window);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -1465,7 +1492,7 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
|
||||
else
|
||||
{
|
||||
/* invalid hex sequence */
|
||||
gdk_display_beep (gdk_drawable_get_display (event->window));
|
||||
beep_window (event->window);
|
||||
|
||||
context_simple->tentative_match = 0;
|
||||
context_simple->in_hex_sequence = FALSE;
|
||||
@ -1473,7 +1500,7 @@ gtk_im_context_simple_filter_keypress (GtkIMContext *context,
|
||||
}
|
||||
}
|
||||
else if (!check_hex (context_simple, n_compose))
|
||||
gdk_display_beep (gdk_drawable_get_display (event->window));
|
||||
beep_window (event->window);
|
||||
|
||||
g_signal_emit_by_name (context_simple, "preedit_changed");
|
||||
|
||||
|
@ -891,8 +891,8 @@ gtk_label_mnemonic_activate (GtkWidget *widget,
|
||||
|
||||
/* barf if there was nothing to activate */
|
||||
g_warning ("Couldn't find a target for a mnemonic activation.");
|
||||
gdk_display_beep (gtk_widget_get_display (widget));
|
||||
|
||||
gtk_widget_error_bell (widget);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -3871,12 +3871,13 @@ gtk_label_move_cursor (GtkLabel *label,
|
||||
gint count,
|
||||
gboolean extend_selection)
|
||||
{
|
||||
gint old_pos;
|
||||
gint new_pos;
|
||||
|
||||
if (label->select_info == NULL)
|
||||
return;
|
||||
|
||||
new_pos = label->select_info->selection_end;
|
||||
|
||||
old_pos = new_pos = label->select_info->selection_end;
|
||||
|
||||
if (label->select_info->selection_end != label->select_info->selection_anchor &&
|
||||
!extend_selection)
|
||||
@ -3901,7 +3902,6 @@ gtk_label_move_cursor (GtkLabel *label,
|
||||
new_pos = end_is_left ? label->select_info->selection_end : label->select_info->selection_anchor;
|
||||
else
|
||||
new_pos = !end_is_left ? label->select_info->selection_end : label->select_info->selection_anchor;
|
||||
|
||||
break;
|
||||
}
|
||||
case GTK_MOVEMENT_LOGICAL_POSITIONS:
|
||||
@ -3933,6 +3933,27 @@ gtk_label_move_cursor (GtkLabel *label,
|
||||
break;
|
||||
case GTK_MOVEMENT_VISUAL_POSITIONS:
|
||||
new_pos = gtk_label_move_visually (label, new_pos, count);
|
||||
if (new_pos == old_pos)
|
||||
{
|
||||
if (!extend_selection)
|
||||
{
|
||||
if (!gtk_widget_keynav_failed (GTK_WIDGET (label),
|
||||
count > 0 ?
|
||||
GTK_DIR_RIGHT : GTK_DIR_LEFT))
|
||||
{
|
||||
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (label));
|
||||
|
||||
if (toplevel)
|
||||
gtk_widget_child_focus (toplevel,
|
||||
count > 0 ?
|
||||
GTK_DIR_RIGHT : GTK_DIR_LEFT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (label));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GTK_MOVEMENT_WORDS:
|
||||
while (count > 0)
|
||||
@ -3945,12 +3966,16 @@ gtk_label_move_cursor (GtkLabel *label,
|
||||
new_pos = gtk_label_move_backward_word (label, new_pos);
|
||||
count++;
|
||||
}
|
||||
if (new_pos == old_pos)
|
||||
gtk_widget_error_bell (GTK_WIDGET (label));
|
||||
break;
|
||||
case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
|
||||
case GTK_MOVEMENT_PARAGRAPH_ENDS:
|
||||
case GTK_MOVEMENT_BUFFER_ENDS:
|
||||
/* FIXME: Can do better here */
|
||||
new_pos = count < 0 ? 0 : strlen (label->text);
|
||||
if (new_pos == old_pos)
|
||||
gtk_widget_error_bell (GTK_WIDGET (label));
|
||||
break;
|
||||
case GTK_MOVEMENT_DISPLAY_LINES:
|
||||
case GTK_MOVEMENT_PARAGRAPHS:
|
||||
|
@ -2756,7 +2756,7 @@ gtk_menu_key_press (GtkWidget *widget,
|
||||
* (basically, those items are accelerator-locked).
|
||||
*/
|
||||
/* g_print("item has no path or is locked, menu prefix: %s\n", menu->accel_path); */
|
||||
gdk_display_beep (display);
|
||||
gtk_widget_error_bell (widget);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2785,7 +2785,7 @@ gtk_menu_key_press (GtkWidget *widget,
|
||||
* locked already
|
||||
*/
|
||||
/* g_print("failed to change\n"); */
|
||||
gdk_display_beep (display);
|
||||
gtk_widget_error_bell (widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1044,17 +1044,27 @@ gtk_menu_shell_move_selected (GtkMenuShell *menu_shell,
|
||||
GList *node = g_list_find (menu_shell->children,
|
||||
menu_shell->active_menu_item);
|
||||
GList *start_node = node;
|
||||
|
||||
gboolean wrap_around;
|
||||
|
||||
g_object_get (gtk_widget_get_settings (GTK_WIDGET (menu_shell)),
|
||||
"gtk-keynav-wrap-around", &wrap_around,
|
||||
NULL);
|
||||
|
||||
if (distance > 0)
|
||||
{
|
||||
node = node->next;
|
||||
while (node != start_node &&
|
||||
(!node || !_gtk_menu_item_is_selectable (node->data)))
|
||||
{
|
||||
if (!node)
|
||||
node = menu_shell->children;
|
||||
else
|
||||
if (node)
|
||||
node = node->next;
|
||||
else if (wrap_around)
|
||||
node = menu_shell->children;
|
||||
else
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (menu_shell));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1063,10 +1073,15 @@ gtk_menu_shell_move_selected (GtkMenuShell *menu_shell,
|
||||
while (node != start_node &&
|
||||
(!node || !_gtk_menu_item_is_selectable (node->data)))
|
||||
{
|
||||
if (!node)
|
||||
node = g_list_last (menu_shell->children);
|
||||
else
|
||||
if (node)
|
||||
node = node->prev;
|
||||
else if (wrap_around)
|
||||
node = g_list_last (menu_shell->children);
|
||||
else
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (menu_shell));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1066,14 +1066,33 @@ gtk_notebook_change_current_page (GtkNotebook *notebook,
|
||||
|
||||
while (offset != 0)
|
||||
{
|
||||
current = gtk_notebook_search_page (notebook, current, offset < 0 ? STEP_PREV : STEP_NEXT, TRUE);
|
||||
current = gtk_notebook_search_page (notebook, current,
|
||||
offset < 0 ? STEP_PREV : STEP_NEXT,
|
||||
TRUE);
|
||||
|
||||
if (!current)
|
||||
{
|
||||
gboolean wrap_around;
|
||||
|
||||
g_object_get (gtk_widget_get_settings (GTK_WIDGET (notebook)),
|
||||
"gtk-keynav-wrap-around", &wrap_around,
|
||||
NULL);
|
||||
|
||||
if (wrap_around)
|
||||
current = gtk_notebook_search_page (notebook, NULL,
|
||||
offset < 0 ? STEP_PREV : STEP_NEXT,
|
||||
TRUE);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
offset += offset < 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
if (current)
|
||||
gtk_notebook_switch_page (notebook, current->data, -1);
|
||||
else
|
||||
gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
|
||||
gtk_widget_error_bell (GTK_WIDGET (notebook));
|
||||
}
|
||||
|
||||
static GtkDirectionType
|
||||
@ -3589,11 +3608,24 @@ focus_tabs_move (GtkNotebook *notebook,
|
||||
|
||||
new_page = gtk_notebook_search_page (notebook, notebook->focus_tab,
|
||||
search_direction, TRUE);
|
||||
if (!new_page)
|
||||
{
|
||||
gboolean wrap_around;
|
||||
|
||||
g_object_get (gtk_widget_get_settings (GTK_WIDGET (notebook)),
|
||||
"gtk-keynav-wrap-around", &wrap_around,
|
||||
NULL);
|
||||
|
||||
if (wrap_around)
|
||||
new_page = gtk_notebook_search_page (notebook, NULL,
|
||||
search_direction, TRUE);
|
||||
}
|
||||
|
||||
if (new_page)
|
||||
gtk_notebook_switch_focus_tab (notebook, new_page);
|
||||
else
|
||||
gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (notebook)));
|
||||
|
||||
gtk_widget_error_bell (GTK_WIDGET (notebook));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -491,6 +491,12 @@ gtk_radio_button_focus (GtkWidget *widget,
|
||||
|
||||
if (!new_focus)
|
||||
{
|
||||
if (!gtk_widget_keynav_failed (widget, direction))
|
||||
{
|
||||
g_slist_free (focus_list);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
tmp_list = focus_list;
|
||||
|
||||
while (tmp_list)
|
||||
@ -511,8 +517,17 @@ gtk_radio_button_focus (GtkWidget *widget,
|
||||
|
||||
if (new_focus)
|
||||
{
|
||||
GtkSettings *settings = gtk_widget_get_settings (widget);
|
||||
gboolean cursor_only;
|
||||
|
||||
g_object_get (settings,
|
||||
"gtk-keynav-cursor-only", &cursor_only,
|
||||
NULL);
|
||||
|
||||
gtk_widget_grab_focus (new_focus);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (new_focus), TRUE);
|
||||
|
||||
if (!cursor_only)
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (new_focus), TRUE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -2457,6 +2457,42 @@ static void
|
||||
gtk_range_move_slider (GtkRange *range,
|
||||
GtkScrollType scroll)
|
||||
{
|
||||
gboolean cursor_only;
|
||||
|
||||
g_object_get (gtk_widget_get_settings (GTK_WIDGET (range)),
|
||||
"gtk-keynav-cursor-only", &cursor_only,
|
||||
NULL);
|
||||
|
||||
if (cursor_only)
|
||||
{
|
||||
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (range));
|
||||
|
||||
if (range->orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
if (scroll == GTK_SCROLL_STEP_UP ||
|
||||
scroll == GTK_SCROLL_STEP_DOWN)
|
||||
{
|
||||
if (toplevel)
|
||||
gtk_widget_child_focus (toplevel,
|
||||
scroll == GTK_SCROLL_STEP_UP ?
|
||||
GTK_DIR_UP : GTK_DIR_DOWN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scroll == GTK_SCROLL_STEP_LEFT ||
|
||||
scroll == GTK_SCROLL_STEP_RIGHT)
|
||||
{
|
||||
if (toplevel)
|
||||
gtk_widget_child_focus (toplevel,
|
||||
scroll == GTK_SCROLL_STEP_LEFT ?
|
||||
GTK_DIR_LEFT : GTK_DIR_RIGHT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gtk_range_scroll (range, scroll);
|
||||
|
||||
/* Policy DELAYED makes sense with key events,
|
||||
|
@ -93,6 +93,9 @@ enum {
|
||||
PROP_COLOR_SCHEME,
|
||||
PROP_ENABLE_ANIMATIONS,
|
||||
PROP_TOUCHSCREEN_MODE,
|
||||
PROP_KEYNAV_CURSOR_ONLY,
|
||||
PROP_KEYNAV_WRAP_AROUND,
|
||||
PROP_ERROR_BELL,
|
||||
PROP_COLOR_HASH
|
||||
};
|
||||
|
||||
@ -507,7 +510,7 @@ gtk_settings_class_init (GtkSettingsClass *class)
|
||||
/**
|
||||
* GtkSettings:gtk-touchscreen-mode:
|
||||
*
|
||||
* When TRUE, there are no motion notify events delivered on this screen,
|
||||
* When %TRUE, there are no motion notify events delivered on this screen,
|
||||
* and widgets can't use the pointer hovering them for any essential
|
||||
* functionality.
|
||||
*
|
||||
@ -523,6 +526,64 @@ gtk_settings_class_init (GtkSettingsClass *class)
|
||||
|
||||
g_assert (result == PROP_TOUCHSCREEN_MODE);
|
||||
|
||||
/**
|
||||
* GtkSettings:gtk-keynav-cursor-only:
|
||||
*
|
||||
* When %TRUE, keyboard navigation should be able to reach all widgets
|
||||
* by using the cursor keys only. Tab, Shift etc. keys can't be expected
|
||||
* to be present on the used input device.
|
||||
*
|
||||
* Since: 2.12
|
||||
*/
|
||||
result = settings_install_property_parser (class,
|
||||
g_param_spec_boolean ("gtk-keynav-cursor-only",
|
||||
P_("Keynav Cursor Only"),
|
||||
P_("When TRUE, there are only cursor keys available to navigate widgets"),
|
||||
FALSE,
|
||||
GTK_PARAM_READWRITE),
|
||||
NULL);
|
||||
|
||||
g_assert (result == PROP_KEYNAV_CURSOR_ONLY);
|
||||
|
||||
/**
|
||||
* GtkSettings:gtk-keynav-wrap-around:
|
||||
*
|
||||
* When %TRUE, some widgets will wrap around when doing keyboard
|
||||
* navigation, such as menus, menubars and notebooks.
|
||||
*
|
||||
* Since: 2.12
|
||||
*/
|
||||
result = settings_install_property_parser (class,
|
||||
g_param_spec_boolean ("gtk-keynav-wrap-around",
|
||||
P_("Keynav Wrap Around"),
|
||||
P_("Whether to wrap around when keyboard-navigating widgets"),
|
||||
TRUE,
|
||||
GTK_PARAM_READWRITE),
|
||||
NULL);
|
||||
|
||||
g_assert (result == PROP_KEYNAV_WRAP_AROUND);
|
||||
|
||||
/**
|
||||
* GtkSettings:gtk-error-bell:
|
||||
*
|
||||
* When %TRUE, keyboard navigation and other input-related errors
|
||||
* will cause a beep. Since the error bell is implemented using
|
||||
* gdk_window_beep(), the windowing system may offer ways to
|
||||
* configure the error bell in many ways, such as flashing the
|
||||
* window or similar visual effects.
|
||||
*
|
||||
* Since: 2.12
|
||||
*/
|
||||
result = settings_install_property_parser (class,
|
||||
g_param_spec_boolean ("gtk-error-bell",
|
||||
P_("Error Bell"),
|
||||
P_("When TRUE, keyboard navigation and other errors will cause a beep"),
|
||||
TRUE,
|
||||
GTK_PARAM_READWRITE),
|
||||
NULL);
|
||||
|
||||
g_assert (result == PROP_ERROR_BELL);
|
||||
|
||||
/**
|
||||
* GtkSettings:color-hash:
|
||||
*
|
||||
|
@ -1243,6 +1243,8 @@ static void
|
||||
gtk_spin_button_real_change_value (GtkSpinButton *spin,
|
||||
GtkScrollType scroll)
|
||||
{
|
||||
gdouble old_value = spin->adjustment->value;
|
||||
|
||||
/* We don't test whether the entry is editable, since
|
||||
* this key binding conceptually corresponds to changing
|
||||
* the value with the buttons using the mouse, which
|
||||
@ -1320,6 +1322,9 @@ gtk_spin_button_real_change_value (GtkSpinButton *spin,
|
||||
}
|
||||
|
||||
gtk_spin_button_update (spin);
|
||||
|
||||
if (spin->adjustment->value == old_value)
|
||||
gtk_widget_error_bell (GTK_WIDGET (spin));
|
||||
}
|
||||
|
||||
static gint
|
||||
|
@ -260,10 +260,10 @@ 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_scroll_pages (GtkTextView *text_view,
|
||||
static gboolean gtk_text_view_scroll_pages (GtkTextView *text_view,
|
||||
gint count,
|
||||
gboolean extend_selection);
|
||||
static void gtk_text_view_scroll_hpages (GtkTextView *text_view,
|
||||
static gboolean gtk_text_view_scroll_hpages(GtkTextView *text_view,
|
||||
gint count,
|
||||
gboolean extend_selection);
|
||||
static void gtk_text_view_insert_at_cursor (GtkTextView *text_view,
|
||||
@ -3922,6 +3922,9 @@ gtk_text_view_key_press_event (GtkWidget *widget, GdkEventKey *event)
|
||||
gtk_text_view_reset_blink_time (text_view);
|
||||
gtk_text_view_pend_cursor_blink (text_view);
|
||||
|
||||
if (!retval && event->length)
|
||||
gtk_widget_error_bell (widget);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -4688,8 +4691,8 @@ gtk_text_view_move_cursor_internal (GtkTextView *text_view,
|
||||
{
|
||||
GtkTextIter insert;
|
||||
GtkTextIter newplace;
|
||||
|
||||
gint cursor_x_pos = 0;
|
||||
GtkDirectionType leave_direction = -1;
|
||||
|
||||
if (!text_view->cursor_visible)
|
||||
{
|
||||
@ -4733,14 +4736,18 @@ gtk_text_view_move_cursor_internal (GtkTextView *text_view,
|
||||
|
||||
if (step == GTK_MOVEMENT_PAGES)
|
||||
{
|
||||
gtk_text_view_scroll_pages (text_view, count, extend_selection);
|
||||
if (!gtk_text_view_scroll_pages (text_view, count, extend_selection))
|
||||
gtk_widget_error_bell (GTK_WIDGET (text_view));
|
||||
|
||||
gtk_text_view_check_cursor_blink (text_view);
|
||||
gtk_text_view_pend_cursor_blink (text_view);
|
||||
return;
|
||||
}
|
||||
else if (step == GTK_MOVEMENT_HORIZONTAL_PAGES)
|
||||
{
|
||||
gtk_text_view_scroll_hpages (text_view, count, extend_selection);
|
||||
if (!gtk_text_view_scroll_hpages (text_view, count, extend_selection))
|
||||
gtk_widget_error_bell (GTK_WIDGET (text_view));
|
||||
|
||||
gtk_text_view_check_cursor_blink (text_view);
|
||||
gtk_text_view_pend_cursor_blink (text_view);
|
||||
return;
|
||||
@ -4777,19 +4784,23 @@ gtk_text_view_move_cursor_internal (GtkTextView *text_view,
|
||||
|
||||
case GTK_MOVEMENT_DISPLAY_LINES:
|
||||
if (count < 0)
|
||||
{
|
||||
if (gtk_text_view_move_iter_by_lines (text_view, &newplace, count))
|
||||
gtk_text_layout_move_iter_to_x (text_view->layout, &newplace, cursor_x_pos);
|
||||
else
|
||||
gtk_text_iter_set_line_offset (&newplace, 0);
|
||||
}
|
||||
{
|
||||
leave_direction = GTK_DIR_UP;
|
||||
|
||||
if (gtk_text_view_move_iter_by_lines (text_view, &newplace, count))
|
||||
gtk_text_layout_move_iter_to_x (text_view->layout, &newplace, cursor_x_pos);
|
||||
else
|
||||
gtk_text_iter_set_line_offset (&newplace, 0);
|
||||
}
|
||||
if (count > 0)
|
||||
{
|
||||
if (gtk_text_view_move_iter_by_lines (text_view, &newplace, count))
|
||||
gtk_text_layout_move_iter_to_x (text_view->layout, &newplace, cursor_x_pos);
|
||||
else
|
||||
gtk_text_iter_forward_to_line_end (&newplace);
|
||||
}
|
||||
{
|
||||
leave_direction = GTK_DIR_DOWN;
|
||||
|
||||
if (gtk_text_view_move_iter_by_lines (text_view, &newplace, count))
|
||||
gtk_text_layout_move_iter_to_x (text_view->layout, &newplace, cursor_x_pos);
|
||||
else
|
||||
gtk_text_iter_forward_to_line_end (&newplace);
|
||||
}
|
||||
break;
|
||||
|
||||
case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
|
||||
@ -4860,6 +4871,18 @@ gtk_text_view_move_cursor_internal (GtkTextView *text_view,
|
||||
if (step == GTK_MOVEMENT_DISPLAY_LINES)
|
||||
gtk_text_view_set_virtual_cursor_pos (text_view, cursor_x_pos, -1);
|
||||
}
|
||||
else if (leave_direction != -1)
|
||||
{
|
||||
if (!gtk_widget_keynav_failed (GTK_WIDGET (text_view),
|
||||
leave_direction))
|
||||
{
|
||||
gtk_text_view_move_focus (text_view, leave_direction);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (text_view));
|
||||
}
|
||||
|
||||
gtk_text_view_check_cursor_blink (text_view);
|
||||
gtk_text_view_pend_cursor_blink (text_view);
|
||||
@ -4943,7 +4966,7 @@ gtk_text_view_set_anchor (GtkTextView *text_view)
|
||||
gtk_text_buffer_create_mark (get_buffer (text_view), "anchor", &insert, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
gtk_text_view_scroll_pages (GtkTextView *text_view,
|
||||
gint count,
|
||||
gboolean extend_selection)
|
||||
@ -4952,11 +4975,12 @@ gtk_text_view_scroll_pages (GtkTextView *text_view,
|
||||
gdouble oldval;
|
||||
GtkAdjustment *adj;
|
||||
gint cursor_x_pos, cursor_y_pos;
|
||||
GtkTextIter old_insert;
|
||||
GtkTextIter new_insert;
|
||||
GtkTextIter anchor;
|
||||
gint y0, y1;
|
||||
|
||||
g_return_if_fail (text_view->vadjustment != NULL);
|
||||
g_return_val_if_fail (text_view->vadjustment != NULL, FALSE);
|
||||
|
||||
adj = text_view->vadjustment;
|
||||
|
||||
@ -4970,9 +4994,13 @@ gtk_text_view_scroll_pages (GtkTextView *text_view,
|
||||
gtk_text_view_scroll_mark_onscreen (text_view,
|
||||
gtk_text_buffer_get_mark (get_buffer (text_view),
|
||||
"insert"));
|
||||
|
||||
/* Validate the region that will be brought into view by the cursor motion
|
||||
|
||||
/* Validate the region that will be brought into view by the cursor motion
|
||||
*/
|
||||
gtk_text_buffer_get_iter_at_mark (get_buffer (text_view),
|
||||
&old_insert,
|
||||
gtk_text_buffer_get_mark (get_buffer (text_view), "insert"));
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
gtk_text_view_get_first_para_iter (text_view, &anchor);
|
||||
@ -4989,6 +5017,8 @@ gtk_text_view_scroll_pages (GtkTextView *text_view,
|
||||
gtk_text_layout_validate_yrange (text_view->layout, &anchor, y0, y1);
|
||||
/* FIXME do we need to update the adjustment ranges here? */
|
||||
|
||||
new_insert = old_insert;
|
||||
|
||||
if (count < 0 && adj->value <= (adj->lower + 1e-12))
|
||||
{
|
||||
/* already at top, just be sure we are at offset 0 */
|
||||
@ -5005,9 +5035,9 @@ gtk_text_view_scroll_pages (GtkTextView *text_view,
|
||||
{
|
||||
gtk_text_view_get_virtual_cursor_pos (text_view, &cursor_x_pos, &cursor_y_pos);
|
||||
|
||||
newval = adj->value;
|
||||
oldval = adj->value;
|
||||
|
||||
newval = adj->value;
|
||||
|
||||
newval += count * adj->page_increment;
|
||||
|
||||
set_adjustment_clamped (adj, newval);
|
||||
@ -5027,9 +5057,11 @@ gtk_text_view_scroll_pages (GtkTextView *text_view,
|
||||
gtk_text_view_scroll_mark_onscreen (text_view,
|
||||
gtk_text_buffer_get_mark (get_buffer (text_view),
|
||||
"insert"));
|
||||
|
||||
return !gtk_text_iter_equal (&old_insert, &new_insert);
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
gtk_text_view_scroll_hpages (GtkTextView *text_view,
|
||||
gint count,
|
||||
gboolean extend_selection)
|
||||
@ -5038,10 +5070,11 @@ gtk_text_view_scroll_hpages (GtkTextView *text_view,
|
||||
gdouble oldval;
|
||||
GtkAdjustment *adj;
|
||||
gint cursor_x_pos, cursor_y_pos;
|
||||
GtkTextIter old_insert;
|
||||
GtkTextIter new_insert;
|
||||
gint y, height;
|
||||
|
||||
g_return_if_fail (text_view->hadjustment != NULL);
|
||||
g_return_val_if_fail (text_view->hadjustment != NULL, FALSE);
|
||||
|
||||
adj = text_view->hadjustment;
|
||||
|
||||
@ -5055,16 +5088,18 @@ gtk_text_view_scroll_hpages (GtkTextView *text_view,
|
||||
gtk_text_view_scroll_mark_onscreen (text_view,
|
||||
gtk_text_buffer_get_mark (get_buffer (text_view),
|
||||
"insert"));
|
||||
|
||||
|
||||
/* Validate the line that we're moving within.
|
||||
*/
|
||||
gtk_text_buffer_get_iter_at_mark (get_buffer (text_view),
|
||||
&new_insert,
|
||||
&old_insert,
|
||||
gtk_text_buffer_get_mark (get_buffer (text_view), "insert"));
|
||||
gtk_text_layout_get_line_yrange (text_view->layout, &new_insert, &y, &height);
|
||||
gtk_text_layout_validate_yrange (text_view->layout, &new_insert, y, y + height);
|
||||
/* FIXME do we need to update the adjustment ranges here? */
|
||||
|
||||
|
||||
new_insert = old_insert;
|
||||
|
||||
if (count < 0 && adj->value <= (adj->lower + 1e-12))
|
||||
{
|
||||
/* already at far left, just be sure we are at offset 0 */
|
||||
@ -5082,9 +5117,9 @@ gtk_text_view_scroll_hpages (GtkTextView *text_view,
|
||||
{
|
||||
gtk_text_view_get_virtual_cursor_pos (text_view, &cursor_x_pos, &cursor_y_pos);
|
||||
|
||||
newval = adj->value;
|
||||
oldval = adj->value;
|
||||
|
||||
newval = adj->value;
|
||||
|
||||
newval += count * adj->page_increment;
|
||||
|
||||
set_adjustment_clamped (adj, newval);
|
||||
@ -5110,6 +5145,8 @@ gtk_text_view_scroll_hpages (GtkTextView *text_view,
|
||||
gtk_text_view_scroll_mark_onscreen (text_view,
|
||||
gtk_text_buffer_get_mark (get_buffer (text_view),
|
||||
"insert"));
|
||||
|
||||
return !gtk_text_iter_equal (&old_insert, &new_insert);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -5143,8 +5180,11 @@ static void
|
||||
gtk_text_view_insert_at_cursor (GtkTextView *text_view,
|
||||
const gchar *str)
|
||||
{
|
||||
gtk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), str, -1,
|
||||
text_view->editable);
|
||||
if (!gtk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), str, -1,
|
||||
text_view->editable))
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (text_view));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -5261,6 +5301,10 @@ gtk_text_view_delete_from_cursor (GtkTextView *text_view,
|
||||
" ", 1,
|
||||
text_view->editable);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (text_view));
|
||||
}
|
||||
|
||||
gtk_text_buffer_end_user_action (get_buffer (text_view));
|
||||
gtk_text_view_set_virtual_cursor_pos (text_view, -1, -1);
|
||||
@ -5269,6 +5313,10 @@ gtk_text_view_delete_from_cursor (GtkTextView *text_view,
|
||||
gtk_text_view_scroll_mark_onscreen (text_view,
|
||||
gtk_text_buffer_get_mark (get_buffer (text_view), "insert"));
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (text_view));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -5295,6 +5343,10 @@ gtk_text_view_backspace (GtkTextView *text_view)
|
||||
gtk_text_view_scroll_mark_onscreen (text_view,
|
||||
gtk_text_buffer_get_insert (get_buffer (text_view)));
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (text_view));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -6337,9 +6389,13 @@ insert_text_data (GtkTextView *text_view,
|
||||
|
||||
if (str)
|
||||
{
|
||||
gtk_text_buffer_insert_interactive (get_buffer (text_view),
|
||||
drop_point, (gchar *) str, -1,
|
||||
text_view->editable);
|
||||
if (!gtk_text_buffer_insert_interactive (get_buffer (text_view),
|
||||
drop_point, (gchar *) str, -1,
|
||||
text_view->editable))
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (text_view));
|
||||
}
|
||||
|
||||
g_free (str);
|
||||
}
|
||||
}
|
||||
@ -6804,8 +6860,11 @@ gtk_text_view_commit_text (GtkTextView *text_view,
|
||||
|
||||
if (!strcmp (str, "\n"))
|
||||
{
|
||||
gtk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), "\n", 1,
|
||||
text_view->editable);
|
||||
if (!gtk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), "\n", 1,
|
||||
text_view->editable))
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (text_view));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -6820,8 +6879,12 @@ gtk_text_view_commit_text (GtkTextView *text_view,
|
||||
if (!gtk_text_iter_ends_line (&insert))
|
||||
gtk_text_view_delete_from_cursor (text_view, GTK_DELETE_CHARS, 1);
|
||||
}
|
||||
gtk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), str, -1,
|
||||
text_view->editable);
|
||||
|
||||
if (!gtk_text_buffer_insert_interactive_at_cursor (get_buffer (text_view), str, -1,
|
||||
text_view->editable))
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (text_view));
|
||||
}
|
||||
}
|
||||
|
||||
gtk_text_buffer_end_user_action (get_buffer (text_view));
|
||||
|
@ -413,7 +413,7 @@ static gboolean gtk_tree_view_search_scroll_event (GtkWidget *entry
|
||||
static gboolean gtk_tree_view_search_key_press_event (GtkWidget *entry,
|
||||
GdkEventKey *event,
|
||||
GtkTreeView *tree_view);
|
||||
static void gtk_tree_view_search_move (GtkWidget *window,
|
||||
static gboolean gtk_tree_view_search_move (GtkWidget *window,
|
||||
GtkTreeView *tree_view,
|
||||
gboolean up);
|
||||
static gboolean gtk_tree_view_search_equal_func (GtkTreeModel *model,
|
||||
@ -5115,11 +5115,16 @@ gtk_tree_view_key_press (GtkWidget *widget,
|
||||
GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (focus_column->data);
|
||||
|
||||
if (!column->resizable)
|
||||
return TRUE;
|
||||
{
|
||||
gtk_widget_error_bell (widget);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (event->keyval == (rtl ? GDK_Right : GDK_Left)
|
||||
|| event->keyval == (rtl ? GDK_KP_Right : GDK_KP_Left))
|
||||
{
|
||||
gint old_width = column->resized_width;
|
||||
|
||||
column->resized_width = MAX (column->resized_width,
|
||||
column->width);
|
||||
column->resized_width -= 2;
|
||||
@ -5138,11 +5143,17 @@ gtk_tree_view_key_press (GtkWidget *widget,
|
||||
column->max_width);
|
||||
|
||||
column->use_resized_width = TRUE;
|
||||
gtk_widget_queue_resize (widget);
|
||||
|
||||
if (column->resized_width != old_width)
|
||||
gtk_widget_queue_resize (widget);
|
||||
else
|
||||
gtk_widget_error_bell (widget);
|
||||
}
|
||||
else if (event->keyval == (rtl ? GDK_Left : GDK_Right)
|
||||
|| event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right))
|
||||
{
|
||||
gint old_width = column->resized_width;
|
||||
|
||||
column->resized_width = MAX (column->resized_width,
|
||||
column->width);
|
||||
column->resized_width += 2;
|
||||
@ -5152,7 +5163,11 @@ gtk_tree_view_key_press (GtkWidget *widget,
|
||||
column->max_width);
|
||||
|
||||
column->use_resized_width = TRUE;
|
||||
gtk_widget_queue_resize (widget);
|
||||
|
||||
if (column->resized_width != old_width)
|
||||
gtk_widget_queue_resize (widget);
|
||||
else
|
||||
gtk_widget_error_bell (widget);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -5174,6 +5189,8 @@ gtk_tree_view_key_press (GtkWidget *widget,
|
||||
col = gtk_tree_view_get_drop_column (tree_view, column, DROP_LEFT);
|
||||
if (col != (GtkTreeViewColumn *)0x1)
|
||||
gtk_tree_view_move_column_after (tree_view, column, col);
|
||||
else
|
||||
gtk_widget_error_bell (widget);
|
||||
}
|
||||
else if (event->keyval == (rtl ? GDK_Left : GDK_Right)
|
||||
|| event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right))
|
||||
@ -5182,6 +5199,8 @@ gtk_tree_view_key_press (GtkWidget *widget,
|
||||
col = gtk_tree_view_get_drop_column (tree_view, column, DROP_RIGHT);
|
||||
if (col != (GtkTreeViewColumn *)0x1)
|
||||
gtk_tree_view_move_column_after (tree_view, column, col);
|
||||
else
|
||||
gtk_widget_error_bell (widget);
|
||||
}
|
||||
else if (event->keyval == GDK_Home || event->keyval == GDK_KP_Home)
|
||||
{
|
||||
@ -5189,6 +5208,8 @@ gtk_tree_view_key_press (GtkWidget *widget,
|
||||
col = gtk_tree_view_get_drop_column (tree_view, column, DROP_HOME);
|
||||
if (col != (GtkTreeViewColumn *)0x1)
|
||||
gtk_tree_view_move_column_after (tree_view, column, col);
|
||||
else
|
||||
gtk_widget_error_bell (widget);
|
||||
}
|
||||
else if (event->keyval == GDK_End || event->keyval == GDK_KP_End)
|
||||
{
|
||||
@ -5196,6 +5217,8 @@ gtk_tree_view_key_press (GtkWidget *widget,
|
||||
col = gtk_tree_view_get_drop_column (tree_view, column, DROP_END);
|
||||
if (col != (GtkTreeViewColumn *)0x1)
|
||||
gtk_tree_view_move_column_after (tree_view, column, col);
|
||||
else
|
||||
gtk_widget_error_bell (widget);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -5206,8 +5229,7 @@ gtk_tree_view_key_press (GtkWidget *widget,
|
||||
|| event->keyval == GDK_Right || event->keyval == GDK_KP_Right))
|
||||
{
|
||||
if ((event->keyval == (rtl ? GDK_Right : GDK_Left)
|
||||
|| event->keyval == (rtl ? GDK_KP_Right : GDK_KP_Left))
|
||||
&& focus_column->prev)
|
||||
|| event->keyval == (rtl ? GDK_KP_Right : GDK_KP_Left)))
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
@ -5216,7 +5238,10 @@ gtk_tree_view_key_press (GtkWidget *widget,
|
||||
break;
|
||||
|
||||
if (!tmp)
|
||||
return FALSE;
|
||||
{
|
||||
gtk_widget_error_bell (widget);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp->data);
|
||||
gtk_widget_grab_focus (tree_view->priv->focus_column->button);
|
||||
@ -5227,8 +5252,7 @@ gtk_tree_view_key_press (GtkWidget *widget,
|
||||
tree_view->priv->hadjustment->upper - tree_view->priv->hadjustment->page_size));
|
||||
}
|
||||
else if ((event->keyval == (rtl ? GDK_Left : GDK_Right)
|
||||
|| event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right))
|
||||
&& focus_column->next)
|
||||
|| event->keyval == (rtl ? GDK_KP_Left : GDK_KP_Right)))
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
@ -5237,7 +5261,10 @@ gtk_tree_view_key_press (GtkWidget *widget,
|
||||
break;
|
||||
|
||||
if (!tmp)
|
||||
return FALSE;
|
||||
{
|
||||
gtk_widget_error_bell (widget);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp->data);
|
||||
|
||||
@ -9558,6 +9585,7 @@ gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
|
||||
else
|
||||
{
|
||||
gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
|
||||
gtk_widget_error_bell (GTK_WIDGET (tree_view));
|
||||
}
|
||||
|
||||
gtk_widget_grab_focus (GTK_WIDGET (tree_view));
|
||||
@ -9569,6 +9597,7 @@ gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
|
||||
{
|
||||
GtkRBTree *cursor_tree = NULL;
|
||||
GtkRBNode *cursor_node = NULL;
|
||||
GtkTreePath *old_cursor_path = NULL;
|
||||
GtkTreePath *cursor_path = NULL;
|
||||
gint y;
|
||||
gint window_y;
|
||||
@ -9578,20 +9607,21 @@ gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
|
||||
return;
|
||||
|
||||
if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
|
||||
cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
|
||||
old_cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
|
||||
else
|
||||
/* This is sorta weird. Focus in should give us a cursor */
|
||||
return;
|
||||
|
||||
gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical-separator", &vertical_separator, NULL);
|
||||
_gtk_tree_view_find_node (tree_view, cursor_path,
|
||||
_gtk_tree_view_find_node (tree_view, old_cursor_path,
|
||||
&cursor_tree, &cursor_node);
|
||||
|
||||
gtk_tree_path_free (cursor_path);
|
||||
|
||||
if (cursor_tree == NULL)
|
||||
/* FIXME: we lost the cursor. Should we try to get one? */
|
||||
return;
|
||||
{
|
||||
/* FIXME: we lost the cursor. Should we try to get one? */
|
||||
gtk_tree_path_free (old_cursor_path);
|
||||
return;
|
||||
}
|
||||
g_return_if_fail (cursor_node != NULL);
|
||||
|
||||
y = _gtk_rbtree_node_find_offset (cursor_tree, cursor_node);
|
||||
@ -9606,11 +9636,16 @@ gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
|
||||
cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
|
||||
g_return_if_fail (cursor_path != NULL);
|
||||
gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE, FALSE);
|
||||
gtk_tree_path_free (cursor_path);
|
||||
|
||||
y -= window_y;
|
||||
gtk_tree_view_scroll_to_point (tree_view, -1, y);
|
||||
_gtk_tree_view_queue_draw_node (tree_view, cursor_tree, cursor_node, NULL);
|
||||
|
||||
if (!gtk_tree_path_compare (old_cursor_path, cursor_path))
|
||||
gtk_widget_error_bell (GTK_WIDGET (tree_view));
|
||||
|
||||
gtk_tree_path_free (old_cursor_path);
|
||||
gtk_tree_path_free (cursor_path);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -9703,6 +9738,11 @@ gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
|
||||
NULL);
|
||||
g_signal_emit (tree_view, tree_view_signals[CURSOR_CHANGED], 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (tree_view));
|
||||
}
|
||||
|
||||
gtk_tree_view_clamp_column_visible (tree_view, tree_view->priv->focus_column);
|
||||
}
|
||||
|
||||
@ -9713,23 +9753,25 @@ gtk_tree_view_move_cursor_start_end (GtkTreeView *tree_view,
|
||||
GtkRBTree *cursor_tree;
|
||||
GtkRBNode *cursor_node;
|
||||
GtkTreePath *path;
|
||||
GtkTreePath *old_path;
|
||||
|
||||
if (! GTK_WIDGET_HAS_FOCUS (tree_view))
|
||||
return;
|
||||
|
||||
g_return_if_fail (tree_view->priv->tree != NULL);
|
||||
|
||||
gtk_tree_view_get_cursor (tree_view, &old_path, NULL);
|
||||
|
||||
cursor_tree = tree_view->priv->tree;
|
||||
cursor_node = cursor_tree->root;
|
||||
|
||||
if (count == -1)
|
||||
{
|
||||
cursor_tree = tree_view->priv->tree;
|
||||
cursor_node = cursor_tree->root;
|
||||
while (cursor_node && cursor_node->left != cursor_tree->nil)
|
||||
cursor_node = cursor_node->left;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor_tree = tree_view->priv->tree;
|
||||
cursor_node = cursor_tree->root;
|
||||
do
|
||||
{
|
||||
while (cursor_node && cursor_node->right != cursor_tree->nil)
|
||||
@ -9744,7 +9786,17 @@ gtk_tree_view_move_cursor_start_end (GtkTreeView *tree_view,
|
||||
}
|
||||
|
||||
path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
|
||||
gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
|
||||
|
||||
if (gtk_tree_path_compare (old_path, path))
|
||||
{
|
||||
gtk_tree_view_real_set_cursor (tree_view, path, TRUE, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (tree_view));
|
||||
}
|
||||
|
||||
gtk_tree_path_free (old_path);
|
||||
gtk_tree_path_free (path);
|
||||
}
|
||||
|
||||
@ -13888,28 +13940,36 @@ gtk_tree_view_search_key_press_event (GtkWidget *widget,
|
||||
/* select previous matching iter */
|
||||
if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up)
|
||||
{
|
||||
gtk_tree_view_search_move (widget, tree_view, TRUE);
|
||||
if (!gtk_tree_view_search_move (widget, tree_view, TRUE))
|
||||
gtk_widget_error_bell (widget);
|
||||
|
||||
retval = TRUE;
|
||||
}
|
||||
|
||||
if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == (GDK_CONTROL_MASK | GDK_SHIFT_MASK))
|
||||
&& (event->keyval == GDK_g || event->keyval == GDK_G))
|
||||
{
|
||||
gtk_tree_view_search_move (widget, tree_view, TRUE);
|
||||
if (!gtk_tree_view_search_move (widget, tree_view, TRUE))
|
||||
gtk_widget_error_bell (widget);
|
||||
|
||||
retval = TRUE;
|
||||
}
|
||||
|
||||
/* select next matching iter */
|
||||
if (event->keyval == GDK_Down || event->keyval == GDK_KP_Down)
|
||||
{
|
||||
gtk_tree_view_search_move (widget, tree_view, FALSE);
|
||||
if (!gtk_tree_view_search_move (widget, tree_view, FALSE))
|
||||
gtk_widget_error_bell (widget);
|
||||
|
||||
retval = TRUE;
|
||||
}
|
||||
|
||||
if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
|
||||
&& (event->keyval == GDK_g || event->keyval == GDK_G))
|
||||
{
|
||||
gtk_tree_view_search_move (widget, tree_view, FALSE);
|
||||
if (!gtk_tree_view_search_move (widget, tree_view, FALSE))
|
||||
gtk_widget_error_bell (widget);
|
||||
|
||||
retval = TRUE;
|
||||
}
|
||||
|
||||
@ -13927,7 +13987,10 @@ gtk_tree_view_search_key_press_event (GtkWidget *widget,
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
/* this function returns FALSE if there is a search string but
|
||||
* nothing was found, and TRUE otherwise.
|
||||
*/
|
||||
static gboolean
|
||||
gtk_tree_view_search_move (GtkWidget *window,
|
||||
GtkTreeView *tree_view,
|
||||
gboolean up)
|
||||
@ -13942,15 +14005,17 @@ gtk_tree_view_search_move (GtkWidget *window,
|
||||
|
||||
text = gtk_entry_get_text (GTK_ENTRY (tree_view->priv->search_entry));
|
||||
|
||||
g_return_if_fail (text != NULL);
|
||||
g_return_val_if_fail (text != NULL, FALSE);
|
||||
|
||||
len = strlen (text);
|
||||
|
||||
if (up && tree_view->priv->selected_iter == 1)
|
||||
return;
|
||||
return strlen (text) < 1;
|
||||
|
||||
len = strlen (text);
|
||||
|
||||
if (len < 1)
|
||||
return;
|
||||
return TRUE;
|
||||
|
||||
model = gtk_tree_view_get_model (tree_view);
|
||||
selection = gtk_tree_view_get_selection (tree_view);
|
||||
@ -13958,7 +14023,7 @@ gtk_tree_view_search_move (GtkWidget *window,
|
||||
/* search */
|
||||
gtk_tree_selection_unselect_all (selection);
|
||||
if (!gtk_tree_model_get_iter_first (model, &iter))
|
||||
return;
|
||||
return TRUE;
|
||||
|
||||
ret = gtk_tree_view_search_iter (model, selection, &iter, text,
|
||||
&count, up?((tree_view->priv->selected_iter) - 1):((tree_view->priv->selected_iter + 1)));
|
||||
@ -13967,6 +14032,7 @@ gtk_tree_view_search_move (GtkWidget *window,
|
||||
{
|
||||
/* found */
|
||||
tree_view->priv->selected_iter += up?(-1):(1);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -13976,6 +14042,7 @@ gtk_tree_view_search_move (GtkWidget *window,
|
||||
gtk_tree_view_search_iter (model, selection,
|
||||
&iter, text,
|
||||
&count, tree_view->priv->selected_iter);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
143
gtk/gtkwidget.c
143
gtk/gtkwidget.c
@ -121,6 +121,7 @@ enum {
|
||||
CAN_ACTIVATE_ACCEL,
|
||||
GRAB_BROKEN,
|
||||
COMPOSITED_CHANGED,
|
||||
KEYNAV_FAILED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
@ -204,6 +205,8 @@ static gboolean gtk_widget_real_focus_out_event (GtkWidget *widget,
|
||||
GdkEventFocus *event);
|
||||
static gboolean gtk_widget_real_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static gboolean gtk_widget_real_keynav_failed (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
static PangoContext* gtk_widget_peek_pango_context (GtkWidget *widget);
|
||||
static void gtk_widget_update_pango_context (GtkWidget *widget);
|
||||
static void gtk_widget_propagate_state (GtkWidget *widget,
|
||||
@ -807,6 +810,29 @@ gtk_widget_class_init (GtkWidgetClass *klass)
|
||||
_gtk_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
/**
|
||||
* GtkWidget::keynav-failed:
|
||||
* @widget: the object which received the signal.
|
||||
* @direction: the direction of movement
|
||||
*
|
||||
* See gtk_widget_keynav_failed() for details.
|
||||
*
|
||||
* Returns: %TRUE if stopping keyboard navigation is fine, %FALSE
|
||||
* if the emitting widget should try to handle the keyboard
|
||||
* navigation attempt in its parent container(s).
|
||||
*
|
||||
* Since: 2.12
|
||||
**/
|
||||
widget_signals[KEYNAV_FAILED] =
|
||||
_gtk_binding_signal_new (I_("keynav-failed"),
|
||||
G_TYPE_FROM_CLASS (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_CALLBACK (gtk_widget_real_keynav_failed),
|
||||
_gtk_boolean_handled_accumulator, NULL,
|
||||
_gtk_marshal_BOOLEAN__ENUM,
|
||||
G_TYPE_BOOLEAN, 1,
|
||||
GTK_TYPE_DIRECTION_TYPE);
|
||||
|
||||
/**
|
||||
* GtkWidget::delete-event:
|
||||
* @widget: the object which received the signal.
|
||||
@ -3642,7 +3668,7 @@ gtk_widget_real_mnemonic_activate (GtkWidget *widget,
|
||||
{
|
||||
g_warning ("widget `%s' isn't suitable for mnemonic activation",
|
||||
G_OBJECT_TYPE_NAME (widget));
|
||||
gdk_display_beep (gtk_widget_get_display (widget));
|
||||
gtk_widget_error_bell (widget);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@ -4326,6 +4352,35 @@ gtk_widget_real_focus (GtkWidget *widget,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_widget_real_keynav_failed (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
gboolean cursor_only;
|
||||
|
||||
switch (direction)
|
||||
{
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
return FALSE;
|
||||
|
||||
case GTK_DIR_UP:
|
||||
case GTK_DIR_DOWN:
|
||||
case GTK_DIR_LEFT:
|
||||
case GTK_DIR_RIGHT:
|
||||
g_object_get (gtk_widget_get_settings (widget),
|
||||
"gtk-keynav-cursor-only", &cursor_only,
|
||||
NULL);
|
||||
if (cursor_only)
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
gtk_widget_error_bell (widget);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_is_focus:
|
||||
* @widget: a #GtkWidget
|
||||
@ -5899,6 +5954,92 @@ gtk_widget_child_focus (GtkWidget *widget,
|
||||
return return_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_keynav_failed:
|
||||
* @widget: a #GtkWidget
|
||||
* @direction: direction of focus movement
|
||||
*
|
||||
* This function should be called whenever keyboard navigation within
|
||||
* a single widget hits a boundary. The function emits the
|
||||
* "keynav-changed" signal on the widget and its return value should
|
||||
* be interpreted in a way similar to the return value of
|
||||
* gtk_widget_child_focus():
|
||||
*
|
||||
* When %TRUE is returned, stay in the widget, the failed keyboard
|
||||
* navigation is Ok and/or there is nowhere we can/should move the
|
||||
* focus to.
|
||||
*
|
||||
* When %FALSE is returned, the caller should continue with keyboard
|
||||
* navigation outside the widget, e.g. by calling
|
||||
* gtk_widget_child_focus() on the widget's toplevel.
|
||||
*
|
||||
* The default implementation for the "keynav-failed" signal is to
|
||||
* return %TRUE for %GTK_DIR_TAB_FORWARD and
|
||||
* %GTK_DIR_TAB_BACKWARD. For the other values of #GtkDirectionType,
|
||||
* it looks at the "gtk-keynav-cursor-only" settings property and
|
||||
* returns %FALSE if the setting is %TRUE. This way the entire GUI
|
||||
* becomes cursor-navigatable on input devices such as mobile phones
|
||||
* which only have cursor keys but no tab key.
|
||||
*
|
||||
* Whenever the default implementation returns %TRUE, it also calls
|
||||
* gtk_widget_error_bell() to notify the user of the failed keyboard
|
||||
* navigation.
|
||||
*
|
||||
* A use case for providing an own implementation of keynav-failed (by
|
||||
* either connecting to it or by overriding it) would be a row of
|
||||
* #GtkEntry widgets where the user should be able to navigate the
|
||||
* entire row with the cursor keys, as e.g. known from GUIs that
|
||||
* require entering license keys.
|
||||
*
|
||||
* Return value: %TRUE if stopping keyboard navigation is fine, %FALSE
|
||||
* if the emitting widget should try to handle the keyboard
|
||||
* navigation attempt in its parent container(s).
|
||||
*
|
||||
* Since: 2.12
|
||||
**/
|
||||
gboolean
|
||||
gtk_widget_keynav_failed (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
gboolean return_val;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
|
||||
g_signal_emit (widget, widget_signals[KEYNAV_FAILED], 0,
|
||||
direction, &return_val);
|
||||
|
||||
return return_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_error_bell:
|
||||
* @widget: a #GtkWidget
|
||||
*
|
||||
* Notifies the user about an input-related error on this widget. If
|
||||
* the gtk-error-bell settings property is %TRUE, it calls
|
||||
* gdk_window_beep(), otherwise it does nothing.
|
||||
*
|
||||
* Note that the effect of gdk_window_beep() can be configured in many
|
||||
* ways, depending on the windowing backend and the desktop environment
|
||||
* or window manager that is used.
|
||||
*
|
||||
* Since: 2.12
|
||||
**/
|
||||
void
|
||||
gtk_widget_error_bell (GtkWidget *widget)
|
||||
{
|
||||
gboolean beep;
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
|
||||
g_object_get (gtk_widget_get_settings (widget),
|
||||
"gtk-error-bell", &beep,
|
||||
NULL);
|
||||
|
||||
if (beep && widget->window)
|
||||
gdk_window_beep (widget->window);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_set_uposition:
|
||||
* @widget: a #GtkWidget
|
||||
|
@ -408,7 +408,7 @@ struct _GtkWidgetClass
|
||||
GdkEventGrabBroken *event);
|
||||
|
||||
void (* composited_changed) (GtkWidget *widget);
|
||||
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gtk_reserved4) (void);
|
||||
void (*_gtk_reserved5) (void);
|
||||
@ -563,6 +563,9 @@ GdkWindow *gtk_widget_get_parent_window (GtkWidget *widget);
|
||||
|
||||
gboolean gtk_widget_child_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
gboolean gtk_widget_keynav_failed (GtkWidget *widget,
|
||||
GtkDirectionType direction);
|
||||
void gtk_widget_error_bell (GtkWidget *widget);
|
||||
|
||||
void gtk_widget_set_size_request (GtkWidget *widget,
|
||||
gint width,
|
||||
|
Loading…
Reference in New Issue
Block a user