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).
Relates to #799.
Removes NRSIAllTags, alltags.txt, parser and utility units.
Also re-enables standardsdata.dpr unit test which needed some syntax
cleanup.
Fixes#3801.
Fixes#3802.
Fixes KEYMAN-WINDOWS-5M.
Fixes KEYMAN-WINDOWS-5N.
This is a two-part fix for Keyman Configuration where it appears there
was a race with creating a temporary file, and which caused a cascading
exception.
The first part resolves the race; the second part (in
UfrmInstallKeyboard.pas) adds a little extra robustness (probably not
totally necessary).
Fixes#3650.
This removes the bad call to `FreeLibrary` that was still present in
a callee of `DllMain` in keyman32. The refactor moves responsibility for
loading TSF to the `SelectKeyboard` functions and gets rid of the
associated thread globals.
The `TSFINTERFACES` struct is of course a future candidate for a class.
In the process I removed a lot of cruft from keyman32.cpp which was
either obsolete, irrelevant or just plain wrong. None of which had
material impact on the running code.
1. Remove unused variables
2. Remove invalid build configurations
3. Move hotkey checks before touch keyboard panel check, so hotkeys
still work when touch panel is active; the touch keyboard panel check
is there to disable serialised input which conflicts with it.
This is the first half of a two-part update to Keyman for Windows. There
are two significant changes here. These changes apply to
keyman32/keyman64, as well as kmtip/kmtip64, but will refer to the
32-bit equivalents for simplicity:
1. Instead of using `GetProcAddress` to connect to keyman32.dll, we
now have an import library connection. This removes one particularly
suspect piece of architecture for Keyman, as using `GetProcAddress`
could lead to a race condition, where keyman32.dll is unloaded after
that function is called but before we use the handle. This makes the
kmtip.dll build dependent on keyman32.dll; loading kmtip.dll (by
selecting a Keyman input method) also loads keyman32.dll.
2. It's not enough (yet) to load kmtip.dll. We also need to be running
keyman.exe itself, due to global hooks that we still require (it may
be possible, one day, to avoid these, but it doesn't look very
hopeful). To that end, kmtip calls new function `TIPIsKeymanRunning`
to check whether keyman32.dll is initialised (and hence keyman.exe
has initialised it). Then, if keyman.exe is not running, it issues an
event to the Windows Event Log, which we will pick up with a
scheduled task in the next PR.
The first part of this is an architectural change which may lead to some
change in behaviours, as keyman32.dll now may not be unloaded from a
process when keyman.exe exits, due to the lock that kmtip.dll now has on
it. It will be important to test this (@MakaraSok) by running through
various startup and shutdown scenarios. In my initial testing, I found
that there were some situations after restarting keyman.exe where I
needed to switch in and out of the Keyman TIP, but those were not all
critical.
This change also lays groundwork for an eventual ability to run the
Keyman input method without keyman.exe running, which will be helpful
e.g. on login screen, even if missing certain additional functionality
such as the serialised input queue.
Both the win32 and the win64 keyman engine libraries would receive a
refresh notification, and then they'd both broadcast the change. This
change limits the broadcast responsibility to the 32-bit engine.
Fixes#3518.
Changes in Keyman Configuration will now apply immediately. This removes
the OK and Cancel buttons from the dialog and means that all actions
are consistent in when they are applied, unlike previously. This also
matches the Windows 10 Settings metaphor and metaphors for most modern
apps and devices.
For now, I have placed a message where the OK and Buttons were
previously, to help existing users understand the change. In time, I
expect us to be able to remove that message entirely.
Fixes#3694.
The keyboard menu would sometimes scroll too far, which could be
confusing for the end user. This fix stops the scroll once the last
item is in view; it also tweaks the down arrow key handler to ensure
that the current item is correctly scrolled into view.
When loading transient language profiles, RefreshKeyboards would reset
the list of profiles (and in so doing, also leak memory). Instead, the
list should be cleared before the initial language profile list load.
While it might be nice to add the tag to versions in filenames, this
creates a lot of work on the website where we make some filename
assumptions. So, this PR winds that detail of filename changes back,
and renames copydev.in to download.in to make it consistent with the
other download.in files.
Release build executables should have 3 component version numbers with
the version tag appended, e.g. keymandesktop-14.0.155-alpha-local.exe.
Coming later, rename keymandesktop-version.exe to keyman-version.exe.
Fixes#3665.
On some systems, subkeys of HKCU\Software\Keyman could have incorrect
permissions and these would not be corrected with earlier fixes such as
in #2316. This fix resolves the problem by recursively correcting
permissions on all subkeys, rather than just the top two levels.
This issue caused Metro-style applications (Windows Store apps) to fail
to accept Keyman keyboard input.