diff --git a/src/dorkbox/systemTray/MenuEntry.java b/src/dorkbox/systemTray/MenuEntry.java index 2b3e37e8..660bf03a 100644 --- a/src/dorkbox/systemTray/MenuEntry.java +++ b/src/dorkbox/systemTray/MenuEntry.java @@ -99,6 +99,16 @@ interface MenuEntry { */ void setCallback(SystemTrayMenuAction callback); + /** + * Sets a menu entry shortcut key (Mnemonic) so that menu entry can be "selected" via the keyboard while the menu is displayed. + * + * Mnemonics are case-insensitive, and if the character defined by the mnemonic is found within the text, the first occurrence + * of it will be underlined. + * + * @param key this is the key to set as the mnemonic + */ + void setShortcut(char key); + /** * Removes this menu entry from the menu and releases all system resources associated with this menu entry */ diff --git a/src/dorkbox/systemTray/linux/GtkEntry.java b/src/dorkbox/systemTray/linux/GtkEntry.java index 0e25a5b2..491f83ac 100644 --- a/src/dorkbox/systemTray/linux/GtkEntry.java +++ b/src/dorkbox/systemTray/linux/GtkEntry.java @@ -90,6 +90,11 @@ class GtkEntry implements MenuEntry { } } + @Override + public + void setShortcut(final char key) { + } + @Override public String getText() { diff --git a/src/dorkbox/systemTray/linux/GtkEntryItem.java b/src/dorkbox/systemTray/linux/GtkEntryItem.java index 8736388b..0c85dec1 100644 --- a/src/dorkbox/systemTray/linux/GtkEntryItem.java +++ b/src/dorkbox/systemTray/linux/GtkEntryItem.java @@ -39,12 +39,17 @@ class GtkEntryItem extends GtkEntry implements GCallback { // these are necessary BECAUSE GTK menus look funky as hell when there are some menu entries WITH icons and some WITHOUT private volatile boolean hasLegitIcon = true; + // The mnemonic will ONLY show-up once a menu entry is selected. IT WILL NOT show up before then! + // AppIndicators will only show if you use the keyboard to navigate + // GtkStatusIndicator will show on mouse+keyboard movement + private volatile char mnemonicKey = 0; + /** * called from inside dispatch thread. ONLY creates the menu item, but DOES NOT attach it! * this is a FLOATING reference. See: https://developer.gnome.org/gobject/stable/gobject-The-Base-Object-Type.html#floating-ref */ GtkEntryItem(final GtkMenu parent, final SystemTrayMenuAction callback) { - super(parent, Gtk.gtk_image_menu_item_new_with_label("")); + super(parent, Gtk.gtk_image_menu_item_new_with_mnemonic("")); this.callback = callback; @@ -62,6 +67,20 @@ class GtkEntryItem extends GtkEntry implements GCallback { } } + @Override + public + void setShortcut(final char key) { + this.mnemonicKey = Character.toLowerCase(key); + + Gtk.dispatch(new Runnable() { + @Override + public + void run() { + renderText(getText()); + } + }); + } + @Override public void setCallback(final SystemTrayMenuAction callback) { @@ -118,8 +137,19 @@ class GtkEntryItem extends GtkEntry implements GCallback { /** * must always be called in the GTK thread */ - void renderText(final String text) { + void renderText(String text) { + if (this.mnemonicKey != 0) { + // they are CASE INSENSITIVE! + int i = text.toLowerCase() + .indexOf(this.mnemonicKey); + + if (i >= 0) { + text = text.substring(0, i) + "_" + text.substring(i); + } + } + Gtk.gtk_menu_item_set_label(_native, text); + Gtk.gtk_widget_show_all(_native); } diff --git a/src/dorkbox/systemTray/linux/GtkMenu.java b/src/dorkbox/systemTray/linux/GtkMenu.java index 23a6d710..dc40c586 100644 --- a/src/dorkbox/systemTray/linux/GtkMenu.java +++ b/src/dorkbox/systemTray/linux/GtkMenu.java @@ -152,6 +152,12 @@ class GtkMenu extends Menu implements MenuEntry { }); } + @Override + public + void setShortcut(final char key) { + menuEntry.setShortcut(key); + } + @Override public String getText() { diff --git a/src/dorkbox/systemTray/linux/jna/Gtk.java b/src/dorkbox/systemTray/linux/jna/Gtk.java index 3284ee78..5dc29418 100644 --- a/src/dorkbox/systemTray/linux/jna/Gtk.java +++ b/src/dorkbox/systemTray/linux/jna/Gtk.java @@ -429,8 +429,8 @@ class Gtk { // to create a menu entry WITH an icon. public static native Pointer gtk_image_new_from_file(String iconPath); - - public static native Pointer gtk_image_menu_item_new_with_label(String label); + // uses '_' to define which key is the mnemonic + public static native Pointer gtk_image_menu_item_new_with_mnemonic(String label); public static native void gtk_image_menu_item_set_image(Pointer image_menu_item, Pointer image);