Skip to content

Commit 6623016

Browse files
author
Stan Janssen
committed
Correct accelerator arrow keys for RTL languages
This corrects accelerators that include a Left or Right arrow key when using a Right-to-Left (RTL) language, where UI elements are draw from right to left. This includes switching focus to the sidebar, which is on the right side in an RTL situation, as well as the 'drill down' and 'drill up' keys when navigating in list or Miller views, and the arrow keys for selecting the previous and next icon in icon view (the icons are also drawn right to left, with the 'next' icon being on the left of the 'previous' icon in an RTL situation. This also matches the directions of the arrow buttons in the tool bar.
1 parent a72202d commit 6623016

4 files changed

Lines changed: 104 additions & 76 deletions

File tree

src/View/IconView.vala

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,21 @@ public class Files.IconView : Files.AbstractDirectoryView {
243243

244244
/* Override native Gtk.IconView cursor handling */
245245
protected override bool move_cursor (uint keyval, bool only_shift_pressed, bool control_pressed) {
246+
uint prev_key;
247+
uint next_key;
248+
if (Gtk.StateFlags.DIR_RTL in get_style_context ().get_state ()) {
249+
prev_key = Gdk.Key.Right;
250+
next_key = Gdk.Key.Left;
251+
} else {
252+
prev_key = Gdk.Key.Left;
253+
next_key = Gdk.Key.Right;
254+
}
255+
246256
Gtk.TreePath? path = get_path_at_cursor ();
247257
if (path != null) {
248-
if (keyval == Gdk.Key.Right) {
258+
if (keyval == next_key) {
249259
path.next (); /* Does not check if path is valid */
250-
} else if (keyval == Gdk.Key.Left) {
260+
} else if (keyval == prev_key) {
251261
path.prev ();
252262
} else if (keyval == Gdk.Key.Up) {
253263
path = up (path);

src/View/ListView.vala

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -160,36 +160,41 @@ namespace Files {
160160
}
161161

162162
protected override bool on_view_key_press_event (uint keyval, uint keycode, Gdk.ModifierType state) {
163+
uint up_key;
164+
uint down_key;
165+
if (Gtk.StateFlags.DIR_RTL in get_style_context ().get_state ()) {
166+
up_key = Gdk.Key.Right;
167+
down_key = Gdk.Key.Left;
168+
} else {
169+
up_key = Gdk.Key.Left;
170+
down_key = Gdk.Key.Right;
171+
}
172+
163173
bool control_pressed = ((state & Gdk.ModifierType.CONTROL_MASK) != 0);
164174
bool shift_pressed = ((state & Gdk.ModifierType.SHIFT_MASK) != 0);
165175
if (!control_pressed && !shift_pressed) {
166-
switch (keyval) {
167-
case Gdk.Key.Right:
168-
Gtk.TreePath? path = null;
169-
tree.get_cursor (out path, null);
170-
171-
if (path != null) {
172-
tree.expand_row (path, false);
173-
}
174-
175-
return true;
176+
if (keyval == down_key) {
177+
Gtk.TreePath? path = null;
178+
tree.get_cursor (out path, null);
176179

177-
case Gdk.Key.Left:
178-
Gtk.TreePath? path = null;
179-
tree.get_cursor (out path, null);
180+
if (path != null) {
181+
tree.expand_row (path, false);
182+
}
180183

181-
if (path != null) {
182-
if (tree.is_row_expanded (path)) {
183-
tree.collapse_row (path);
184-
} else if (path.up ()) {
185-
tree.collapse_row (path);
186-
}
184+
return true;
185+
} else if (keyval == up_key) {
186+
Gtk.TreePath? path = null;
187+
tree.get_cursor (out path, null);
188+
189+
if (path != null) {
190+
if (tree.is_row_expanded (path)) {
191+
tree.collapse_row (path);
192+
} else if (path.up ()) {
193+
tree.collapse_row (path);
187194
}
195+
}
188196

189-
return true;
190-
191-
default:
192-
break;
197+
return true;
193198
}
194199
}
195200

src/View/Miller.vala

Lines changed: 45 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -424,59 +424,61 @@ namespace Files.View {
424424

425425
View.Slot? to_activate = null;
426426
var prefs = Files.Preferences.get_default ();
427-
switch (keyval) {
428-
case Gdk.Key.Left:
429-
if (current_position > 0) {
430-
if (prefs.show_file_preview) {
431-
clear_file_details ();
432-
}
433-
434-
to_activate = slot_list.nth_data (current_position - 1);
435-
}
436-
437-
break;
438427

439-
case Gdk.Key.Right:
440-
if (current_slot.get_selected_files () == null) {
441-
return true;
442-
}
428+
uint up_key;
429+
uint down_key;
443430

444-
Files.File? selected_file = current_slot.get_selected_files ().data;
445-
if (selected_file == null) {
446-
return true;
447-
}
431+
// Determine which key is the "drill down" key based on the layout direction
432+
if (Gtk.StateFlags.DIR_RTL in scrolled_window.get_style_context ().get_state ()) {
433+
up_key = Gdk.Key.Right;
434+
down_key = Gdk.Key.Left;
435+
} else {
436+
up_key = Gdk.Key.Left;
437+
down_key = Gdk.Key.Right;
438+
}
448439

449-
GLib.File current_location = selected_file.location;
450-
GLib.File? next_location = null;
451-
if (current_position < slot_list.length () - 1) { //Can be assumed to limited in length
452-
next_location = slot_list.nth_data (current_position + 1).location;
440+
if (keyval == up_key) {
441+
if (current_position > 0) {
442+
if (prefs.show_file_preview) {
443+
clear_file_details ();
453444
}
454445

455-
if (next_location != null && next_location.equal (current_location)) {
456-
to_activate = slot_list.nth_data (current_position + 1);
457-
} else if (selected_file.is_folder ()) {
458-
add_location (current_location, current_slot);
459-
return true;
460-
}
446+
to_activate = slot_list.nth_data (current_position - 1);
447+
}
461448

462-
break;
449+
} else if (keyval == down_key) {
450+
if (current_slot.get_selected_files () == null) {
451+
return true;
452+
}
463453

464-
case Gdk.Key.BackSpace:
465-
if (current_position > 0) {
466-
truncate_list_after_slot (slot_list.nth_data (current_position - 1));
467-
} else {
468-
ctab.go_up ();
469-
return true;
470-
}
454+
Files.File? selected_file = current_slot.get_selected_files ().data;
455+
if (selected_file == null) {
456+
return true;
457+
}
471458

472-
if (prefs.show_file_preview) {
473-
clear_file_details ();
474-
}
459+
GLib.File current_location = selected_file.location;
460+
GLib.File? next_location = null;
461+
if (current_position < slot_list.length () - 1) { //Can be assumed to limited in length
462+
next_location = slot_list.nth_data (current_position + 1).location;
463+
}
475464

476-
break;
465+
if (next_location != null && next_location.equal (current_location)) {
466+
to_activate = slot_list.nth_data (current_position + 1);
467+
} else if (selected_file.is_folder ()) {
468+
add_location (current_location, current_slot);
469+
return true;
470+
}
471+
} else if (keyval == Gdk.Key.BackSpace) {
472+
if (current_position > 0) {
473+
truncate_list_after_slot (slot_list.nth_data (current_position - 1));
474+
} else {
475+
ctab.go_up ();
476+
return true;
477+
}
477478

478-
default:
479-
break;
479+
if (prefs.show_file_preview) {
480+
clear_file_details ();
481+
}
480482
}
481483

482484
if (to_activate != null) {

src/View/Window.vala

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,19 @@ public class Files.View.Window : Hdy.ApplicationWindow {
158158
marlin_app.set_accels_for_action ("win.go-to::NETWORK", {"<Alt>N"});
159159
marlin_app.set_accels_for_action ("win.go-to::SERVER", {"<Alt>C"});
160160
marlin_app.set_accels_for_action ("win.go-to::UP", {"<Alt>Up"});
161-
marlin_app.set_accels_for_action ("win.forward(1)", {"<Alt>Right", "XF86Forward"});
162-
marlin_app.set_accels_for_action ("win.back(1)", {"<Alt>Left", "XF86Back"});
163161
marlin_app.set_accels_for_action ("win.tab::TAB", {"<Shift><Ctrl>K"});
164162
marlin_app.set_accels_for_action ("win.tab::WINDOW", {"<Ctrl><Alt>N"});
165-
marlin_app.set_accels_for_action ("win.focus-sidebar", {"<Ctrl><Alt>Left"});
166-
marlin_app.set_accels_for_action ("win.focus-current-container", {"<Ctrl><Alt>Right"});
163+
164+
// Make sure Left and Right arrow keys are mapped logically based on layout direction
165+
if (Gtk.StateFlags.DIR_RTL in get_style_context ().get_state ()) {
166+
marlin_app.set_accels_for_action ("win.focus-sidebar", {"<Ctrl><Alt>Right"});
167+
marlin_app.set_accels_for_action ("win.focus-current-container", {"<Ctrl><Alt>Left"});
168+
marlin_app.set_accels_for_action ("win.forward(1)", {"<Alt>Right", "XF86Forward"});
169+
} else {
170+
marlin_app.set_accels_for_action ("win.focus-sidebar", {"<Ctrl><Alt>Left"});
171+
marlin_app.set_accels_for_action ("win.focus-current-container", {"<Ctrl><Alt>Right"});
172+
marlin_app.set_accels_for_action ("win.back(1)", {"<Alt>Left", "XF86Back"});
173+
}
167174
}
168175

169176
build_window ();
@@ -190,15 +197,19 @@ public class Files.View.Window : Hdy.ApplicationWindow {
190197

191198
private void build_window () {
192199
button_back = new View.Chrome.ButtonWithMenu ("go-previous-symbolic");
193-
194-
button_back.tooltip_markup = Granite.markup_accel_tooltip ({"<Alt>Left"}, _("Previous"));
195200
button_back.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
196201

197202
button_forward = new View.Chrome.ButtonWithMenu ("go-next-symbolic");
198-
199-
button_forward.tooltip_markup = Granite.markup_accel_tooltip ({"<Alt>Right"}, _("Next"));
200203
button_forward.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
201204

205+
if (Gtk.StateFlags.DIR_RTL in get_style_context ().get_state ()) {
206+
button_back.tooltip_markup = Granite.markup_accel_tooltip ({"<Alt>Right"}, _("Previous"));
207+
button_forward.tooltip_markup = Granite.markup_accel_tooltip ({"<Alt>Left"}, _("Next"));
208+
} else {
209+
button_back.tooltip_markup = Granite.markup_accel_tooltip ({"<Alt>Left"}, _("Previous"));
210+
button_forward.tooltip_markup = Granite.markup_accel_tooltip ({"<Alt>Right"}, _("Next"));
211+
}
212+
202213
view_switcher = new Chrome.ViewSwitcher ((SimpleAction)lookup_action ("view-mode")) {
203214
margin_end = 20
204215
};

0 commit comments

Comments
 (0)