Fixes#4525.
This is a regression from #4468, which inadvertently added modifier
checks for `VK_CAPITAL` and `VK_NUMLOCK`, when it should not have done
so, as the flag was then being reset when the key was released rather
than toggled.
`ProcessModifierChange` pretended that it could handle `VK_CAPITAL` and
`VK_NUMLOCK` but it would never have worked, and the other caller (the
GetMessage hook) never passed those key events through, only Shift, Ctrl
and Alt, so that's now what the TIP handler does as well.
This leaves the rest of the fix from #4468 in place as that appears
correct.
I took the opportunity to move a repeated function declaration into
keyman64.h.
Fixes#4369.
When Keyman is not handling a particular virtual key, it does not
preserve the virtual key (TSF terminology, essentially reserves that
virtual key + modifier for Keyman). In this situation, Keyman still
receives and processes the virtual key event, but the modifier state
is not passed through by kmtip to keyman32. This is normally okay,
because our `GetMessage` hook is responsible for tracking modifiers.
However, in UWP apps, our `GetMessage` hook does not get run, and so
we lose the modifier keys. Thus, this update ensures that the modifier
keys are processed when received by the TSF TIP.
It does not hurt to process modifier events twice.
We should uninstall transient languages before disabling them
because once we have disabled them, we lose the language
association and cannot find the entry to uninstall. catch-22.
Ensures we get a canonical tag per langtags.json as far as we possibly
can. This is a breaking change for the compiler as tags which were
formerly regarded as canonical are no longer regarded that way. This
mostly relates to script subtag but a secondary bug meant that some
other tags would have lost data in the canonicalization process
(because we did a lookup based only on the language subtag previously,
which is a no-no).
See keymanapp/keyboards#1452 for related work.
Two changes here:
1. Only post the refresh message to the master controller, so that we
get a single refresh regardless of how many controllers are
registered.
2. When Keyman is restarted, the global RefreshTag is reset to 0, so we
need to do a `!=` comparison rather than a `<` comparison to ensure
that apps with an existing keyman32.dll/keyman64.dll in memory get
refresh notifications (as their local `RefreshTag_Process` will
likely already be greater than `0`).
Also a small additional debug statement.
Fixes#4192.
If Keyman is already running, and the user attempts to start Keyman
again, a balloon will be shown to direct the user to the right place on
the screen.
Note: this worked in earlier versions of Keyman but stopped working due
to name changes for windows in the app.
I have also added a new string for balloon that will need translation.
Fixes#4343.
This patch makes all language codes from the langtags.json dataset
visible through the Add Language dialog. This avoids situations where
an incomplete code such as "cmo" can result in an error (a script is
required for "cmo" as it is written in either Latn or Khmr).
Fixes#4337.
The Sinhala language installation mitigation needed the BCP 47 code as
well as the language code with the new language installation process.
Fixes#4336.
Removes the "Show Keyboard Usage Page" hotkey entry as it has no effect,
and cleans up Keyboard Usage and OSK Hint strings from all the current
locales.
Fixes#4289.
Some settings changes would not apply immediately for 64-bit apps, as
the refresh was not being processed until keymanx64 received focus (i.e.
never, as keymanx64 does not have a visible window!)
In order for the BK_SURROGATE and BK_DEADKEY flags to be matched with
the correct xstring elements in the context, we need to delete the
elements from the buffer in reverse order.
decxstr would previously assert if attempting to move before start of
string. This is undesirable behaviour as it should instead return NULL
to indicate that we've finished the string.
I also corretected a buffer underrun which would be possible if
malformed data was in the xstring.
I checked all uses of decxstr to ensure that the NULL return value is
being tested correctly.
Fixes#4196.
When deleting characters in a TSF-aware app, we must delete both halves
of a surrogate pair. This behaviour differs from legacy apps, where a
single backspace is usually sufficient to delete both characters.
Truly ancient apps that do not know about Unicode surrogate pairs are
not going to delete both halves with a single backspace event.
Fortunately, these are few and far between; we would handle them on a
case-by-case basis if support questions for them arise.
When we come to integrating Keyman Core into Keyman for Windows, there
will need to be some careful checking of surrogate pair support, as it
is likely that the handling will need to change.
Fixes#4264.
The Android strings.xml format that we now use with Keyman Desktop has a
number of escapes that must be supported in order for text strings to be
rendered correctly, including: @, ?, ', ". Furthermore, positional
parameters have a slightly different format which we should transform on
load.
This change includes a unit test androidstringtokeymanlocalestring.
Fixes#2690.
Fixes#3082.
In the debugger, key events such as Enter, Ctrl+C, Ctrl+V were being
swallowed by the debug engine if they did not have rules within the
keyboard. This change emits the key events so the debug memo can
process them normally.
Fixes#4184.
If a package had a keyboard with language metadata, it would not
load that language data correctly, which then meant it would not
apply the mitigation correctly either, leading to a double elevation
dialog as Keyman tried to fallback to primary language.
Fixes#1285.
If running Windows 10 19597 or later, the underlying issue has
been addressed, so disable the mitigation for new installs of
the keyboard. Does not attempt to change the language code if
the keyboard is already installed.
The keyboard profile and registration strategy was not taking into
account the mitigation for Win10 1803 (#1285) and this meant that the
Amharic, Tigrigna and Sinhala keyboards would not install correctly.
Fixes#4013.
This turned out to be a lot more complicated than I expected, mostly due
to limitations in the Windows Shell API with regard to multiple monitors
and per-monitor DPI awareness (which we don't yet do in Keyman -- a
task for another day). Some of the Shell API functions are also
re-entrant, which is dangerous, so I avoided using those.
We now popup the menu relative to the Keyman icon far more precisely
which gives a much nicer feel to the menu interaction.
This change has three fixes to improve the reliability of notifying
Keyman Engine of updates to settings or keyboard installs:
1. It removes the closure pattern of the refresh thread, because that
was closing on a variable on a different thread (`RefreshHandle`) and
that could cause races and/or exceptions in the case of early free.
What's more, the closure was actually unnecessary as the variable was
really only used by the refresh thread!
2. It moves responsibility for setting the refresh token to the calling
thread so that the caller can depend on the token being the one that
is actually sent, removing a race.
3. Most important, the refresh thread now flushes all messages in its
queue, as there may be multiple messages relating to the window
construction that need to be processed before the wm_keyman_refresh
message can be handled. This greatly improves the chance of the
notification actually being sent!
Another thought: we could also try refreshing every 125msec for 5
seconds after the first change is detected. It's a bit yuck perf-wise
but would probably be pretty transparent to the user.
In testing, this looks good. It means the changes appear as soon as
ready, without substantial delays or performance issues. Polling this
makes me feel a bit dirty, but I'll just take a shower and be okay.
As Keyman now monitors the Windows keyboard list from Control Panel, it
is no longer sufficient to refresh the toolbar only when a Keyman
keyboard is updated, as at that point Windows has not refreshed its own
language list in the registry. Instead, we need to monitor changes to
the relevant registry key and then refresh when those changes are
'complete'.
There is a problem: there does not appear to be a good way to monitor
for changes to Windows language settings. WM_SETTINGCHANGE is sent when
a language is added by the user in Settings, but the actual change
happens asynchronously, and we are not notified when the changes are
complete.
We also do not get notifications when languages are added via APIs.
Given the async nature of the language profile changes, this leads to
race conditions when we try to refresh the OSK toolbar. My preferred
solution currently is to monitor the relevant key in a separate thread,
and wait 1 second post-changes to actually do the refresh.
Fixes#4006.
This fixes the list error exception which was masking the actual cause
of #4006, which is already fixed by #4164.
Related issue #4119 is also fixed by #4164.
When a keyboard is installed, Keyman will now only refresh its internal
state on a given thread when that thread receives focus and/or input,
rather than immediately. This will dramatically reduce the chatter
caused by Keyman Engine when a keyboard is installed or settings are
changed.
Fixes#4011.
Fixes#4039.
Fixes#4121.
This change completes the immediate-change model for Keyman
Configuration, by refactoring the refresh of settings out of the render
phase and more appropriately splitting applying and refreshing. It adds
a new message flag for wm_keyman_refresh, KR_SETTINGS_CHANGED, which
uses a random token approach broadcast to all applications on the
desktop to ensure that the refresh is received and multiple
notifications for the same event can be appropriately coalesced.
Most of the files touched are stripping out the refresh flags from the
render phase.
There is one small bug resolved at the same time with the options
properties, which were not reset to default if they had been deleted
from the registry prior to a refresh (see utilkeymanoption.pas).
Fixes#3749.
Fixes#3759.
Adds a warning dialog when user attempts to add a transient language to
a keyboard but the maximum number of transient languages is already
installed.
If this issue arises when a user is installing a keyboard for the first
time, Keyman instead installs the keyboard for the user's default
language. This may be a little confusing, but the error condition is
difficult to explain and non-technical users will probably be stuck
and need to install under their default language in any case. Happy to
receive any pushback on this decision.
Fixes#4012.
If the menu previously was scrollable, then it would potentially show
items at the wrong offset because the offsets were not reset when the
menu popup was called if no scroll was needed.
Fixes#4003.
This addresses the majority of locations where we use the name "Keyman
Desktop" in code. There will be some filenames and paths that do not
change at this point -- particularly at a source level. For now, the
focus is on the user interface changes.
While making these changes, I also made the VERSION and MANIFEST
resources more consistent.
We used the 'Started' event when testing Sentry integration. We no
longer need it, but I left it in as commented code so we can re-enable
if/when we do Sentry updates in the future and need to re-test.
Fixes#3831.
This fixes both issues reported in the bug (dproj changes ensure
separate .tds, and Makefile changes fix order of execution so that
dbg is generated after sentryprep's cleanup).