Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fl_Sys_Menu_Bar menu item shortcuts using Escape or Tab do not work properly on Mac #469

Closed
dannye opened this issue Jul 18, 2022 · 12 comments
Assignees
Labels
fixed The issue or PR was fixed.

Comments

@dannye
Copy link

dannye commented Jul 18, 2022

(most of this problem description is outdated -- please see comments for full context.)

The Problem

Fl_Sys_Menu_Bar menu item shortcuts using Escape or Tab do not work properly on Mac.
The shortcuts display incorrectly in the menu and the keyboard shortcuts do not invoke the callback.
This works correctly in Windows and Linux.

"Escape" is displayed in the menu as a semicolon (;) and "Tab" is displayed as a closing parenthesis ()).
Note that neither Escape/Tab nor semicolon/parenthesis invoke the callback.

It's possible that this is just user-error on my part but that seems unlikely.
I couldn't find any bug reports of a similar bug so I wanted to submit this and see if there is any known workaround.

Thanks!

Screenshots

Mac

mac1
mac2

Windows

windows1
windows2

Linux

linux1
linux2

The Code

Fl_Menu_Item menu_items[] = {
    ...
    OS_MENU_ITEM("&Stop", FL_Escape, (Fl_Callback *)stop_cb, this, FL_MENU_DIVIDER),
    ...
    OS_MENU_ITEM("&Next Channel", FL_Tab, (Fl_Callback *)next_channel_cb, this, 0),
    OS_MENU_ITEM("&Previous Channel", FL_SHIFT + FL_Tab, (Fl_Callback *)previous_channel_cb, this, 0),
    ...
};
_menu_bar->copy(menu_items);

where OS_MENU_ITEM is a convenience macro defined as:

#ifdef __APPLE__
#define OS_MENU_ITEM_PREFIX ""
#define OS_MENU_ITEM_SUFFIX ""
#else
#define OS_MENU_ITEM_PREFIX " "
#define OS_MENU_ITEM_SUFFIX "         "
#endif

#define OS_MENU_ITEM(l, s, c, d, f) {OS_MENU_ITEM_PREFIX l OS_MENU_ITEM_SUFFIX, s, c, d, f, FL_NORMAL_LABEL, OS_FONT, OS_FONT_SIZE, FL_FOREGROUND_COLOR}
@dannye
Copy link
Author

dannye commented Jul 18, 2022

It's also worth noting that if I change the Fl_Sys_Menu_Bar back into a Fl_Menu_Bar, the shortcuts are displayed correctly in the menu (except the "ESC" is hilariously tiny) and the callbacks are invoked correctly:
mac3
mac4

(also, are the menus supposed to be semitransparent here? 🤔 There is no transparency on Windows or Linux.)

@dannye
Copy link
Author

dannye commented Jul 18, 2022

Update:
It turns out that using NSTabCharacter and FL_SHIFT + NSTabCharacter (from here) fixes the display for Tab and Shift+Tab, and fixes the callback for Tab -- but unfortunately does not fix the callback for Shift+Tab.
image

I also tried using NSBackTabCharacter (⇤) with no luck. (It displays fine, but shift+tab does not trigger it. Not that I assumed it would, I'm just grasping at straws.)

I am also still searching for the correct way to display Mac's special "Escape" symbol (⎋) in the menu.
Edit: Apparently NSEscapeCharacter is equal to 27, although I've yet to find an "official" source on this. (unofficial source)
image
This fixed both the menu display and callback for Escape.

So, I apologize for my rambling, but now the only remaining mystery is how to get Shift+Tab to trigger the menu item callback.

@ManoloFLTK
Copy link
Contributor

I don't see how you can use either escape or tab as menu shortcuts under Linux or any other FLTK platform. The FLTK source code processes tab as a command to move to the next menu item, shift-tab to the previous one, and escape to close the menu. These keystrokes are not processed as candidates for menu item shortcuts.

@dannye
Copy link
Author

dannye commented Jul 26, 2022

I don't see how you can use either escape or tab as menu shortcuts under Linux or any other FLTK platform.

Hi, thanks for the reply. I'm not sure exactly what you mean by this. I had no speedbumps/roadblocks at all getting Escape or Tab to work under Linux or Windows.
The only uncooperative combination is Mac using Fl_Sys_Menu_Bar with Shift+Tab (Escape and Tab work fine, and all shortcuts work fine using Fl_Menu_Bar instead of Fl_Sys_Menu_Bar).

The FLTK source code processes tab as a command to move to the next menu item, shift-tab to the previous one, and escape to close the menu.

In my testing, this is only the case while the menu is open. With the menu closed, menu item shortcuts involving Escape or Tab work as expected, which luckily is the desired behavior for me.

@ManoloFLTK
Copy link
Contributor

OK. I was reasoning and experimenting with open menus.

With a closed menubar, I do see now escape recognized as an item shortcut. I keep failing to use tab as a shortcut, though. In my hands, FLTK processes tab and shift-tab keystrokes as navigation commands moving the focus to other widgets.

@ManoloFLTK ManoloFLTK self-assigned this Jul 26, 2022
@ManoloFLTK
Copy link
Contributor

Commit f582e06 (to 1.4) now allows to use FL_Escape and FL_Tab to define shortcuts under macOS just as under linux. In other words, it's no longer necessary to use NSTabCharacter and NSEscapeCharacter for the macOS platform instead of FL_Escape and FL_Tab.

But, while escape now works as a menu item shortcut also under macOS, tab remains recognized as a focus navigation command under all platforms.

@dannye
Copy link
Author

dannye commented Jul 26, 2022

Thanks!

Since Mac and Shift+Tab is the only thing not working right for me, my window's handle() has this snippet:

#ifdef __APPLE__
    case FL_KEYBOARD:
        if (Fl::event_key() == FL_Tab && Fl::event_shift()) {
            previous_channel_cb(nullptr, this);
            return 1;
        }
#endif

and this workaround works fine for me. The only (minor) downside is that the menu doesn't "flicker" in response to this shortcut (obviously).

Thanks again for your consideration on this.

@ManoloFLTK
Copy link
Contributor

ManoloFLTK commented Jul 26, 2022

OK. But I still don't understand how you get the tab keystroke recognized as a menu item shortcut, on any platform.

Please, close this issue since it seems no longer to be an issue for you.

@dannye
Copy link
Author

dannye commented Jul 26, 2022

OK. But I still don't understand how you get the tab keystroke recognized as a menu item shortcut, on any platform.

In my experience, getting Tab recognized as a menu item shortcut just works "out of the box".
My repo is private for a little while longer, but I based it off this public project where Tab is used as a menu item shortcut with no issues right here.

Please, close this issue since it seems no longer to be an issue for you.

It would still be nice to resolve the inconsistency with Fl_Sys_Menu_Bar and Shift+Tab, but I'll leave it to your discretion if that is worth looking into further.

@ManoloFLTK
Copy link
Contributor

Plain FLTK prevents Tab from being recognized as a menu item shortcut because the program flow goes to function nav_key() (in Fl_Group.cxx) which recognizes Tab and Shift-Tab keystrokes as focus navigation commands and prevents the same keystroke to be processed as an FL_SHORTCUT event where it could be recognized as a menu item shortcut.

If an app derives Fl_Window or Fl_Double_Window and overrides its handle(int) method as follows

class myWindow : public Fl_Double_Window {
  public:
  myWindow(int w, int h) : Fl_Double_Window(w,h) {}
  int handle(int event) {
    if (event == FL_KEYBOARD) {
      int retval = Fl_Double_Window::handle(FL_SHORTCUT);
      if (retval) return retval;
    }
    return Fl_Double_Window::handle(event);
  }
};

then Tab and shift-Tab are recognized as menu shortcuts by unchanged FLTK both under Linux and macOS (and, presumably, Windows too).

Does your application modify the windows' handle method similarly?
If yes, this would mean this issue could be closed considering the last changes committed to the main branch (FLTK 1.4).

@dannye
Copy link
Author

dannye commented Jul 27, 2022

Does your application modify the windows' handle method similarly?

No, my entire window's handle() is just:

int Main_Window::handle(int event) {
    switch (event) {
    case FL_FOCUS:
    case FL_UNFOCUS:
        return 1;
#ifdef __APPLE__
    case FL_KEYBOARD:
        if (Fl::event_key() == FL_Tab && Fl::event_shift()) {
            previous_channel_cb(nullptr, this);
            return 1;
        }
        break;
#endif
    }
    return Fl_Double_Window::handle(event);
}

This is with FLTK 1.3.8.

ManoloFLTK added a commit that referenced this issue Jul 28, 2022
@ManoloFLTK
Copy link
Contributor

OK. I understand now how you manage to process Tab as menu item shortcut. This results from

    switch (event) {
      case FL_FOCUS:
      case FL_UNFOCUS:
        return 1;

in your window's handle method. With that, the focus goes initially to the window object itself and Tab navigation is ineffective in that case, so the Tab keystroke is then analyzed as a candidate shortcut.

Source code changes for menu shortcuts to be displayed adequately under macOS (e.g., ⎋, ⌫, ⌦) and to be recognized correctly have been pushed to FLTK master and 1.3 branches. For your app to benefit from them, I'd advise to use the source code of the master branch which will soon become FLTK 1.4. It's likely there won't be another 1.3.x public release.

Please, close this issue if you agree it's fixed.

@ManoloFLTK ManoloFLTK added the fixed The issue or PR was fixed. label Jul 28, 2022
@dannye dannye closed this as completed Jul 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fixed The issue or PR was fixed.
Projects
None yet
Development

No branches or pull requests

2 participants