Open Bug 1794664 Opened 3 years ago Updated 11 days ago

Feature: Keyboard shortcuts

Categories

(Firefox for Android :: General, task, P2)

All
Android
task

Tracking

()

ASSIGNED

People

(Reporter: csadilek, Assigned: m_kato)

References

(Depends on 1 open bug, Blocks 3 open bugs)

Details

(Whiteboard: [fxdroid] [group4])

Attachments

(3 files)

From github: https://github.com/mozilla-mobile/android-components/issues/1978.

This came up for the reference browser here:
https://github.com/mozilla-mobile/reference-browser/issues/575

Since most of those shortcuts would probably invoke UseCases (or indirectly perform things on the SessionManager or Session).. maybe we could just wrap that in a component and with that provide those keyboard shortcuts to all our apps easily.

Related code in Fennec:
https://searchfox.org/mozilla-central/source/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java#471-567

https://searchfox.org/mozilla-esr68/rev/13df4aebd54ee9ba73924dd558af289ef515a490/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java#534


  • [ ] New tab
  • [ ] Navigate forward
  • [ ] Navigate back
  • [ ] Reload
  • [ ] Stop loading
  • [ ] Private tab
  • [ ] Close tab
  • [ ] Find in page

┆Issue is synchronized with this Jira Task

Change performed by the Move to Bugzilla add-on.

Would love to have this feature back.

The severity field is not set for this bug.
:cpeterson, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(cpeterson)

Some work was done on this, but needs help from a more experienced developer - see comments in:

Duplicate of this bug: 1787403
Severity: -- → N/A
Type: defect → task

Maybe we can have something like this (UML diagram attached)?
https://user-images.githubusercontent.com/58442255/224989808-3c256caf-8738-4e9d-808c-f728ff4981d0.png

From @gaul's code (attached GitHub issue), we can have a generic abstract DispatchKeyEvent (is that alr in Fenix?), that would be extended to implement a single shortcut for every subclass (for extensibility, if not all shortcut code must be added to only one file) - similar to what is done for Feature(I think?)
We can then have an ArrayList<DispatchKeyEvent> in the GeckoEngineView, then in the BaseBrowserFragment, or appropriate locations, we add the shortcuts one by one with addShortcut().

Also, if needed, I can also add a field for the name and description of the shortcut, so users can discover is more quickly. We should use the OS keyboard shortcuts menu to advertise available shortcuts, probably in HomeActivity. Although undocumented, it is a feature of AOSP since Android Nougat, and I've discovered how to do this and posted my answer here: https://stackoverflow.com/a/71062698/12204281.

How does this sound?
Thanks.

Flags: needinfo?(csadilek)

Reading the original discussion on Github, I agree that's roughly the right shape.

The missing piece here is the Feature class, which would allow registering specific shortcut handlers in applications e.g., Fenix. The feature class would be bound to the view (as most of our features), have access to an EngineView and listen for key events. It would then invoke the corresponding shortcut handler in response to those events.

Flags: needinfo?(csadilek)
Flags: needinfo?(cpeterson)

I think View.OnKeyListener and the corresponding setOnKeyListener should be more appropriate for this use case.

(In reply to czlucius from comment #8)

I think View.OnKeyListener and the corresponding setOnKeyListener should be more appropriate for this use case.
Seems to be what Fennec uses as well, although Fennec hard-codes it. I think a feature implementation will do well for this.

https://hg.mozilla.org/mozilla-central/file/add212ee1118aff550a5fc05420282556fb3ade9/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java#l573

Seems like onKeyDown, onKeyUp and onKeyPreIme is overriden in GeckoView.java, hence nothing is received with setOnKeyListener.
Thus, an override for dispatchKeyEvent is needed.

I've started working on this, got the reload shortcut to work with the suggested modular approach, implemented with a feature component.
Will push a PR when it is ready.

How are things going? I would very much enjoy to be able to use Firefox on the tablet.

Hello there,

Just want to add some extra context as reading here makes it look like a relativeky new problem, but this user request dates back 12 years now, if we count it all the way to the Fennec issue that was fixed shortly before the transition to Fenix, which still has the bug to this day:

https://bugzilla.mozilla.org/show_bug.cgi?id=726716

This was also discussed to some length in GitHub for over 4 years, before the repository was retired:

https://github.com/mozilla-mobile/fenix/issues/3729

That latter issue is linked from user comments all around the web, mainly as people find that they are stuck with other browsers whenever they want to use Android with a keyboard, which is more common nowadays as there are larger tablet screens.

It's great to see some action on this per earlier comments above, but considering it's been over 8 months now, hopefully this didn't get unintendedly missed again as other items moved up the list.

Thanks for the great work you all do.

(In reply to czlucius from comment #11)

Created attachment 9324679 [details]
photo_2023-03-23_22-05-56.jpg

I've started working on this, got the reload shortcut to work with the suggested modular approach, implemented with a feature component.
Will push a PR when it is ready.

Hi czlucius, your screenshot looks great! Did you have a chance to move this topic forward in the past few months?

The missing support for keyboard shortcuts on Android is a real annoyance. It often leads me to to go back to Chrome on my Samsung Tab S9 tablet with the keyboard cover.

Is there any hope that keyboard shortcuts will be implemented for Android Firefox?
Maybe someone with the required superpower can review Priority: Not set Severity: N/A.
Otherwise, this issue probably has the last place in the ranking.

See Also: → 1897673

@czlucius Have you made any progress with your work?

Flags: needinfo?(lucius)

Redirect a needinfo that is pending on an inactive user to the triage owner.
:boek, since the bug has recent activity, could you have a look please?

For more information, please visit BugBot documentation.

Flags: needinfo?(lucius) → needinfo?(jboek)

Hi there.
I have been quite busy the past year, but have found some time on this of late. .

From what I can see from the attempted PR and Fennec, they all handle dispatchKeyEvent, and I think the ideal place is in GeckoEngineView.
I have made slight progress in the keyboard feature in AC, to plug into a GeckoEngineView for capturing dispatched KeyEvents.
Some of the keyboard shortcuts can be written in AC in the Feature itself, but some (like new tab) have to be written in Fenix as it is very dependent on navigation.

But before this can be solved, there is 1 problem that will be blocking it (in which I can file another issue), if not even if keyboard shortcuts are implemented the experience would not be according to standard:
Some websites may call event.preventDefault() to capture the shortcut from the browser, and we should support this behaviour (see https://stackoverflow.com/a/3680946/12204281). It seems like for GeckoView's processing keyevent code which leads to GeckoEditable.java (in the fn processKey, around line 2551), just returns true (hence capturing the keyevent), for all valid keyboard shortcuts (see snippet below).
This means all keyevents including our keyboard shortcuts is captured by Gecko, and its either all (we capture all shortcuts and disallow any website-override), or nothing (the browser does not get any keyevent at all because it is captured by Gecko).

Hence I think we need to find a solution to get Gecko(View) to return us whether it has captured the keyevent (i.e. the website has overriden it), which will be the return value of processKey hence onKeyDown (in GeckoView.java, line 880). I don't have much experience with Gecko code, it seems like afterwards it is being passed to native code in C++ which I cannot trace. But the chain of functions all return void which is going to be a problem (in addition to the callback-based sendKeyEvent as seen below)? Maybe someone from the Fenix/GeckoView team can advice on how we can proceed with this.

Thanks!
Let me know if you need any clarification.

Snippet for processKey of GeckoEditable:

  private boolean processKey(
      final @Nullable View view,
      final int action,
      final int keyCode,
      final @NonNull KeyEvent event) {
    if (keyCode > KeyEvent.getMaxKeyCode() || !shouldProcessKey(keyCode, event)) {
      return false;
    }

    postToInputConnection(
        new Runnable() {
          @Override
          public void run() {
            sendKeyEvent(view, action, event);
          }
        });
    return true;
  }
Flags: needinfo?(csadilek)

I am very, very satisfied. After all these years, you have dealt with the subject seriously, so that I can have some hope again.

Depends on: 1921161
Flags: needinfo?(jboek)
Duplicate of this bug: 1918282
Duplicate of this bug: 1897673

Hey Makoto, is this something that needs to be done in GV layer?

Flags: needinfo?(m_kato)

(In reply to [:owlish] 🦉 PST from comment #25)

Hey Makoto, is this something that needs to be done in GV layer?

Although I am consider this implementation for 2 days, I think that new GeckoView API may be unnecessary. Actually, since GeckoView.onKey* calls super.onKey at first, we can override keyboard handling by View.setOnKeyListener.

I attach concept code / WIP as feature-keyboardshortcut to perform keyboard shortcut.

Flags: needinfo?(m_kato)

As shortcut, there is both browser level and content level. Browser level is handed by this, but I need to investigate content level.

(WIP is just imported from legacy Fennec code. It uses setOnKeyListener for View)

We don't want to block any events by UI thread, so onKey* should return immediately. If you handle content level shortcut, I guess that it is better to add an API such as GeckoSession.setPostOnKeyListerer(View.OnKeyListener)...

Thanks!
@m_kato I actually have some code that handles keyboard shortcuts also using Features, in a polymorphic approach. I've written a few subclasses to handle refresh, and some other commands.
Was waiting for the GV fix because if not the implementation wouldn't be good as websites won't be able to override the shortcuts.
How do I push this up as a draft as you did?
Thanks!

I'll go test this out.
@m_kato does the WIP code (i.e. session?.webView?.setOnKeyListener(listener) ) successfully prevent the browser from handling the shortcut if already handled by the webpage?
Thanks.

Assignee: nobody → m_kato
Flags: needinfo?(csadilek)
Priority: -- → P2
Whiteboard: [fxdroid] [group4]
Status: NEW → ASSIGNED

Please add this to the "See also" field (in order for you to remember to update Mozilla Connect when this feature is completed): https://connect.mozilla.org/t5/ideas/android-firefox-shortcuts-keys/idi-p/57847

(In reply to czlucius from comment #33)

I'll go test this out.
@m_kato does the WIP code (i.e. session?.webView?.setOnKeyListener(listener) ) successfully prevent the browser from handling the shortcut if already handled by the webpage?
Thanks.

We will add new GeckoView API (see Bug 1921161 Comment 12) to handle more key event things.

Blocks: 1894355

Hey Makoto, are there any updates on this feature? How much work is left and is it prioritized?

Flags: needinfo?(m_kato)

It will be ready for review next week.

GeckoView dispatches key event by 2 path. One is dispatched by parent process, and another is dispatched by content process via Binder. When editable element doesn't has focus, it is by parent. Child process case is most by IME related. Desktop version dispatch from parent only. (Unit tests might be able to dispatch from content process). I am re-thinking good way for 2 patterns.

Also, for media key support, GeckoEditable has internal listener, but this is broken now. So I also consider to fix it.

Wonderful, I'm really excited, and finally we turn into the home straight.

(In reply to Thomas.Heinrich.Schmidt from comment #40)

Wonderful, I'm really excited, and finally we turn into the home straight.

Yeah it's been one of the sore spots of attempting to use Firefox on a tablet for some time now.

(In reply to Makoto Kato [:m_kato] from comment #39)

GeckoView dispatches key event by 2 path. One is dispatched by parent process, and another is dispatched by content process via Binder. When editable element doesn't has focus, it is by parent. Child process case is most by IME related. Desktop version dispatch from parent only. (Unit tests might be able to dispatch from content process). I am re-thinking good way for 2 patterns.

Also, for media key support, GeckoEditable has internal listener, but this is broken now. So I also consider to fix it.

Are you considering unifying these paths, or perhaps refining the conditions under which each is used?

I will file some related bugs to add APIs.

Flags: needinfo?(m_kato)
Depends on: 1974148

Are we getting closer? Is someone working on the APIs?

🎉🎉🎉 we are indeed getting closer as dependent bug 1974148 has been fixed!

It's been three years. Is this going anywhere?

Everytime a new version comes out I test it. But still nothing after all this time.

Hey, is there any updates?

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: