[Xposed Framework Modules] Roughy:
Exi for Swiftkey 2.6.8 release

2.6.8 [03.04.2020 ] - Toolbar/Number row toggle actions, bug fixes, behavioral changes ( Stable: 7.5.1.7 Beta: 7.5.2.4 )

Changes in 2.6.8

Fixed

- Emoji panel locking up Swiftkey ( Beta 7.5.2.4 )

- Quick-menu in sectioned layouts ( Chinese stroke etc )

- Long popup strings being inserted incorrectly in certain fields

Added

- Text action to toggle number row

- Text action to toggle toolbar

Changed

- Maximize predictions retains toolbar toggle button by default ( swipe gesture in settings )

- Made Swipe gesture to open toolbar less sensitive

The Xposed Installer app does not appear to be refreshing properly and may not list the latest version.

Please download it directly from the Xposed Repository below using a browser.

Download:

Exi for Swiftkey on Xposed module repository

My own mirror of all versions

Notes:

Toolbar toggle stuff [MENTION=433422]death_jax[/MENTION] [MENTION=6584717]mario0318[/MENTION]

Swiping the predictions to toggle the toolbar is now configurable, and disabled by default. The old button is used otherwise.

If you do choose to enable the swipe gesture, it now takes a bit more effort to trigger.

There is also an action you can configure to the quick-menu or hotkeys for toggling the toolbar now, if that's your cup of tea.

Number row toggle [MENTION=5044560]oroboros74[/MENTION]

Number row toggle added as an action for the time being, so quick-menu or hotkey.

Long popup strings ( and quick menu in some layouts ) [MENTION=5905138]aadi50[/MENTION]

If a popup key string is longer than 1 character it will now be intercepted and inserted into the field directly, instead of relying on Swiftkey to handle it.

This solves... whatever Swiftkey was doing with password fields.

This was supposed to be simple, but it turns out we were not already tracking Popup key instances.

When a key is created, Swiftkey first calls a method that lets us know the type of key and its contents.

A bit later it will the actual constructor of the key class several times, each resulting in a new key object.

Some of these represent the popup keys, some are phantom keys that do not seem to exist, and finally a single one of them will be the actual key.

All we know is that they're all related to the same key somehow.

With some observation you can tell that it creates the lower case popup keys, an empty key, the upper case popup keys, and then finally the actual key.

This all happens directly after we've inserted our custom popup keys, so we can use this information to figure out what the content of each popup key is, and finally use that to decide which keys we should intercept and handle ourselves.

Before discovering this I had been discarding keys that were obviously incorrect based on their area; the x/y left/top/right/bottom positions in the layout.

Keys never fill the entire height or width of the layout, so we obviously wouldn't care about those.

However, popup keys /do/ fill the popup window they appear in.

They were keys other than popup keys that had the same height-filling area though.

It turns out that, in some layouts, the keyboard is split into several different sections.

The spacebar row is its own little section, and the keys they go into it should fill the height of it.

This includes the spacebar in these layouts, which we would previously have treated as invalid and discarded, thus breaking the quick-menu.

The final piece of this puzzle was figuring out how to intercept the popup key.

When there is some kind of interaction with a key Swiftkey may call one of 4 different methods: Down, up, cancel, and one more unknown.

These methods are all identical and, once obfuscated, we cannot really tell them apart, so we've been hooking them all and just asking the layer that we use to handle swipe selection what the last motion event was. If it was down then the key event was probably also down.

Popup keys trigger on the UP event, so we need to identify that. Luckily the 4 methods always appear in the same order, so figuring out which is which and just hooking them in order works.

We wait for the UP event, check if the key is a popup, and then cancel it, right? Unfortunately this will never tell the popup key that the user is done with it, and it will remain visible.

In addition to cancelling the UP event, we also have to call the CANCEL event on the key to make it go away.

All that, to fix popups with long strings in password fields. At least we got the quick menu working in a few more layouts out of it too.

Emoji panel freeze

When we display the emoji variant indicator and the selection popup, we need to color a few elements accordingly.

In these panels Swiftkey uses either a light or dark theme so we don't have to worry about theme-specific weirdness, but we do need to know whether it's treating the current theme as a dark or a light theme.

Since the emoji would respond to this change I had previously looked up the ID of a resource the emoji would query when shown, and then check if it was using the light or dark variant.

Unfortunately they have removed this resource, so an exception is thrown when it cannot be found. Multiply this by a million emoji and you have a freeze on your hands.

I was hoping I could continue to use the same hook with a different resource, but unfortunately they've completely ditched that system and all the dark/light resources in that section of the code are irrelevant now.

After a bit of searching I realized the method we use to set and keep track of the current theme name returns an object that only has 2 methods, both of which return booleans.

Exactly what these booleans represent I do not know, but they seem to always be true with light themes, and false with dark themes.

I imagine in some themes they will not be matched, but they were for everything I tried so good enough.