This is a working tentative at fixing text expansion/injection done by
Espanso by default, where XKB doesn't seem to detect the pressed
modifiers `Ctrl+Shift` before pressing `v`.
refs: #3840
Weirdly, the rust compiler is suddenly complaining about this,
when this file hasn't changed.
```
error[E0283]: type annotations needed
--> window\src\os\windows\window.rs:2398:26
|
2398 | if vk <= u8::MAX.into() {
| -- ^^^^
| |
| type must be known at this point
|
= note: cannot satisfy `u32: PartialOrd<_>`
help: try using a fully qualified path to specify the expected types
|
2398 | if vk <= <u8 as Into<T>>::into(u8::MAX) {
| ++++++++++++++++++++++ ~
error[E0283]: type annotations needed
--> window\src\os\windows\window.rs:2415:32
|
2415 | if leader.1 <= u8::MAX.into() && key.1 <= u8::MAX.into() {
| -- ^^^^
| |
| type must be known at this point
|
= note: cannot satisfy `u32: PartialOrd<_>`
help: try using a fully qualified path to specify the expected types
|
2415 | if leader.1 <= <u8 as Into<T>>::into(u8::MAX) && key.1 <= u8::MAX.into() {
| ++++++++++++++++++++++ ~
```
Note that this also does not respect dpi_by_screen; this is for
consistency in behavior and reported values.
Once we can produce the correct overridden value in
dispatch_pending_event, we can update these functions to return
the same data.
refs: #4096
This is a baby step towards handling dpi_by_screen.
I don't want to do the actualy per-screen stuff here;
it touches stuff around the edges of SCTK and there is a pending,
significant, rewrite of that code needed to upgrade to a more
recent version of SCTK + wayland-protocols, and I don't want to waste
my effort on the intermediate state.
https://github.com/wez/wezterm/issues/3996#issuecomment-1636830740
refs: #4096
Maintain a cache of the positions of the various named screens,
and use that to resolve the screen of the current window, and
from there we can resolve the correct dpi_by_screen screen.
Make dpi and dpi_by_screen config changes generate a resize
event with the updated dpi.
refs: #4096
Allows specifying the precise dpi to use on a per-screen basis:
```lua
return {
dpi_by_screen = {
["Built-in Retina Display"] = 144,
},
}
```
The screen names are the same as those returned from
`wezterm.gui.screens()`.
Changing either `dpi` or `dpi_by_screen` in the config will now cause
the window to be immediately resized/adjusted to the changed dpi
override.
Ultimately, I'd like to deprecate `dpi` in favor of `dpi_by_screen`,
but can't do that until this functionality is ported to windows, x11
and wayland.
refs: #4096
This is fixing a regression introduced by the fix for #2845.
The resolution for this is relatively straightforward, but took a bit
of effort to plumb.
Previously:
* CTRL/ALT/SUPER-modified keys with no explicit expansion would end
up just taking the US layout version of the key. That worked well
for the intended problem with non-latin layouts, but for eg: German
layouts it caused expansion to totally the wrong thing
Now:
* CTRL/ALT/SUPER-modified keys which effectively expand to non-ascii
text (eg: cyrillic "Es") now take the equivalent key press from the
US layout (which would be "c" in the "Es" case). For European
layouts this heuristic seems to avoid unexpected effects, but could
do with some validation from native users.
To support this, the xkb code splits the `Keyboard` struct out from
some of the higher level logic and introduces a `KeyboardWithFallback`
struct that is built out of the user-selected keyboard layout, and
the fallback keyboard. Now the fallback keyboard is fed the same
key inputs as the selected keyboard to correctly model the key
combinations.
refs: #3610
refs: #3933
On Wayland, copy mode often doesn't actually update the clipboard.
Specifically, it only works one time after a pointer enter or pointer
button event, then doesn't work again until the next event.
This is because the Wayland protocol serial number in
CopyAndPaste::last_serial is only updated by pointer enter and pointer
button events. So, subsequent copies using only the keyboard reuse the
same serial number and get ignored. last_serial used to be updated for
keyboard events, too, but that was (accidentally?) dropped in commit
0a00ffe98b.
Commit 0a00ffe98b also added another
last_serial to WaylandConnection which is updated for keyboard events
but isn't used anywhere as far as I can tell.
So, to fix this bug, let's get rid of CopyAndPaste::last_serial and
replace it with WaylandConnection::last_serial, which is now updated for
pointer and keyboard events.
closes: #3843
Error message I've been seeing the past couple of days:
Unable to resolve appearance using xdg-desktop-portal: invalid value:
string "()", expected at least one field signature between `(` and `)`:
invalid value: string "()", expected at least one field signature
between `(` and `)`
When trying to display a 4k image there is a high chance that
we'll run out of texture space and then render with no images
displayed.
This commit changes the binary yes/no allow-images into a a series
of attempts: display at natural size, scale down by 2, 4, then 8,
then give up on images.
While looking at this, I noticed that we had a TOCTOU in the blob lease
stuff in the case where we might very quickly try the handle the same
image in succession, and end up deleting a file out from under a live
lease.
I've put in place a simple bandaid for that, but it's probably worth
revisiting the concurrency model for that.
Don't fallback to some other serial.
In a new version of SCTK, it looks like the serial we pass should
be the serial from the time we entered the surface, rather than
the latest serial that we have.
In practice, this commit uses None for the serial which seems to
have better results, but may come back to haunt us until we upgrade
to the latest SCTK.
refs: https://github.com/wez/wezterm/issues/3334#issuecomment-1515141539
This allows for potentially listing multiple candidate cursor names,
like we do for x11, but doesn't add any.
Attempt to load default if our desired cursor is not found.
refs: https://github.com/wez/wezterm/issues/3334
For eg: RU layout, CTRL-S shouldn't result in ы in the context
of a terminal.
The approach taken here is similar to kitty; when the key combination
doesn't produce a definitive composed output, and when any of
ctrl/alt/super are present, we treat the keypress as though it were
the same as the one from the system default keymap.
The result is that ctrl-c now works like ctrl-c and alt-b and alt-f work
like their latin counterparts.
Hopefully there are no downsides to this!
refs: https://github.com/wez/wezterm/issues/2845
refs: https://github.com/kovidgoyal/kitty/issues/606
The main part of the problem is that NSWindow::isZoomed lies to us
sometimes.
This is a relatively gross workaround.
Add missing invalidation after setting the content size; that prevents
janky when dragging the window between monitors.
Removed some redundant Dimensions computation from that method; nothing
ever read it.
refs: https://github.com/wez/wezterm/issues/3503
This pulls in almost all of the original PR in #2235.
I skipped a dead key case that I recall being tricky:
I didn't want to break the non win32-input mode version
of that.
I'd be happy to have that case re-evaluated in a smaller
PR where we can focus on its details.
Co-authored-by: Dominik Kreutzer <kreudom@gmail.com>
macos doesn't have a num lock concept, so there is no num lock state
reported in modifiers. wezterm doesn't emulate that state because it
cannot guarantee to observe all key presses and correctly track it.
We were missing encoding of these for the base xterm encoding
(I haven't daily driven a keyboard with a numpad in over 10 years!).
Improve mapping for the kitty protocol.
refs: https://github.com/wez/wezterm/issues/3478
This commit teaches the termwiz layer about positional modifiers,
and expands our modifier concept to also pass through led states
such as caps lock and num lock.
Those aren't actually keyboard modifiers, but the state is useful
to recognize.
Adjust the shift key normalization so that we don't uppercase
alpha characters when both SHIFT and CAPS_LOCK are held.
This processing will remove both SHIFT and CAPS_LOCK in that
situation.
Add a method to KeyEvent that will undo the OS keyboard layer
normalization of positional to generic modifier key presses.
eg: the OS may map LeftControl -> Control, but we actually
prefer to have LeftControl so if we can unambiguously reverse
that mapping, we do so.
refs: #3476
refs: #3475
For whatever reason, it appears as though the wayland
frame event stuff is unreliable when used with webgpu,
so we simply avoid using it.
refs: https://github.com/wez/wezterm/issues/3126
Remove an unsafe global variable and replace with a member variable
that works similarly to the drag tracking.
Doing this from a mac... may not compile on a windows box!
Weird behavior from macos; the command line:
`wezterm start vim hello`
would result in macos requesting `vim` and `hello` be opened
as "documents" which would route each of those to the .command
script handling flow and spawn a window for each; running:
`vim ; exit` in one
`hello ; exit` in another
in addition to the normal handling of that command line.
This commit resolves this by igoring document opening
requests until after the application is fully launched.
I tested this by trying to open a .command script with
this new build and verified that that continued to work.
refs: #3340
- Removes closures and function calls for types that implement default:
```rust
// Change
let _my_str = get_str().unwrap_or(String::new);
// To
let _my_str = get_str().unwrap_or_default();
```
- Uses the `.cloned()/.copied()` methods where possible
- Use function pointer instead of simple closure
May improve performace, as closures generate more code, and this might
unlock some inlining opportunities.
- Use `find` instead of `position(..).next()`
- Use `any` instead of `position(..).next().is_some()/.is_none()`
- Use `first/next` instead of `get(0)/nth(0)`
- Prefer `for` loops over `while let` loops on iterators
May improve performance.
A user reported this:
08:47:13.372 DEBUG window::os::x11::connection > Unable to
resolve appearance using xdg-desktop-portal: Read:
org.freedesktop.DBus.Error.TimedOut: Failed to activate service
'org.freedesktop.portal.Desktop': timed out
(service_start_timeout=120000ms)
which is an issue with their xdg-portal service.
Rather than have wezterm block for 2 minutes on startup, we give it
1 second, and log the issue as a warning.
If there are no windows, clicking on the dock icon will spawn a new
window.
Requires that `quit_when_all_windows_are_closed=false`
refs: https://github.com/wez/wezterm/issues/3057
The recently added app delegate was telling cocoa that we'd decide
to quit later in response to termination requests, blocking
shutdown/logout/restart.
This commit introduces a macos native modal alert to let the user
decide whether to quit or not.
While testing this, I noticed that in some cases, our internal choice
to quit had no effect. Reading the fine print of NSApp::stop, it sounds
like calling it from a modal context will only stop a modal rather then
exit out of NSApp::run, so we explicitly bounce through an event
callback to try to make it exit from the right place.
I'm not 100% convinced by this. I've left some debug prints in for
now to see if those give some insight in the future.
refs: https://github.com/wez/wezterm/issues/2944
This is moderately painful to do, because of some objc/cocoa lifetime
concern that causes a crash when attempting to simply replace the
entire menubar, so we try to find/update items instead.
refs: https://github.com/wez/wezterm/issues/1485
This commit safely registers key equivalents with the menubar. Safe in
this context means "doesn't override a key assignment from a key table".
For example, it would suck to define an application-wide key assignment
for a key combination that has a different assignment in a key table
that may be activated conditionally by some user-defined state/mode.
refs: https://github.com/wez/wezterm/issues/1485
This allows defining those help actions that open URLs in the main
commands list, and not just for the macOS Help menu.
refs: https://github.com/wez/wezterm/issues/1485
This took a decent amount of effort to thread through with context;
wrappers around NSMenu and NSMenuItem are added to reduce some of
the objc usability warts, and an additional NSObject wrapper is
added to help copy the KeyAssignment from the existing list
of command palette commands and associate it with the menu item.
When a menu item is selected, macOS will walk through the responder
chain and look for a responder that responds to the selector associated
with the menu item. In practice that means that our window/view class
will be tried first, and then later, our app delegate will be tried.
This commit implements routing from both of these: the window case
routes to the associated TermWindow and drops into the existing
perform_key_assignment method.
In case there is no window (not currently possible, but will be
in the future), the app delegate also has a placeholder for dispatching
key assignments, although it will only be able to perform a subset
of the possible actions.
A couple of things to note:
* Items aren't smart enough to disable themselves or adjust their
caption based on the context. To make that work, we either need
to recreate the entire menubar when any possible context changes
(doable, but feels heavy), or we need to assign a target to each
menu item and implement a validation handler on that target.
That seemed to mess with the responder chain when I briefly
experimented with it.
* There's some disabled code to add a Services menu. It is disabled
because when it is enabled, accessing either Services or Help
from the menu bar sends the process into a busy loop somewhere
in macOS's internals. It's unclear what it is unhappy with.
* No keyboard accelerators are associated with the menubar yet.
That needs some thought, as they would essentially become global
keyboard shortcuts and take precedence over the shortcuts defined
for other keys in the config. This feels like it should be something
that the user has control over, so there needs to be something to
allow that before we go ahead and wire those up.
refs: https://github.com/wez/wezterm/issues/162
refs: https://github.com/wez/wezterm/issues/1485
Implement an app delegate to receive a callback when the system
requests that we open `.command` files, and then ask the mux
layer to spawn a window for it and execute it via the shell.
Also allow handling `.sh`, `.zsh`, `.bash`, `.fish` and `.tool`,
per kitty.
refs: https://github.com/wez/wezterm/issues/2741
refs: https://github.com/wez/wezterm/issues/2871
https://github.com/wez/wezterm/pull/2435 proposed including
CTRL-modified keys, but I think that the state of the code now means
that we can simplify that area and adjust it so that we will default to
routing keys to the IME, but excluding them based on the
`send_composed_key_when_(left|right)_alt_is_pressed` configuration.
I've only very lightly tested this, but it seems ok with roman text and
me punching in random pinyin and then using CTRL-H or CTRL-M to delete
or enter.
refs: https://github.com/wez/wezterm/pull/2435
weirdly, BOOL is considered bool when I compile locally,
but in the CI:
```
error[E0308]: mismatched types
--> window/src/os/macos/connection.rs:170:22
|
170 | let max_fps = if has_max_fps {
| ^^^^^^^^^^^ expected `bool`, found `i8`
```
I can't explain the difference in behavior (feels like a compiler
bug?) but let's try comparing explicitly against YES
This slightly improves the startup time of wezterm.
Right now we query the portal appearance value again over dbus every
time that we access it, for example every time that the user calls
wezterm.gui.get_appearance() from the Lua interface.
Queries over dbus are slow, they usually take a few milliseconds to
complete, for example on my system a portal query over dbus takes around
2 milliseconds to complete.
Wezterm also automatically calls the portal during its own internal
x11/wayland connection initialization, thus right now wezterm queries
the appearance portal setting n+1 times on startup, where n is the
number of times that the user calls get_appearance() from the config.
To fix this problem, we simply cache the portal appearance.
Thus this patch decreases the startup time by 2ms for users that
configure wezterm to follow the global system theme and potentially by
more for users that call get_appearance() in inflational amounts.
With the naive implementation wezterm would be subject to the following
race condition:
1. wezterm calls get_appearance() and caches the value
2. System-wide dark mode changes
3. wezterm subscribes to portal notifications
In that scenario wezterm would miss the dark mode switch entirely and
would cache the wrong value until the dark mode switches again after
wezterm subscribed.
To fix this race condition we call read_setting() again **after** we
have subscribed just to be on the safe side.
Note that while this still introduces a second "redundant" dbus query
for the same value, this time it does not actually block start up since
it happens in another thread.
refs: #2258
Right now the initial x11 appearance retrieval uses the specific
connection interface, which completely circumvents the already existing
more complete implementation in x_and_wayland.rs.
The latter implementation is strictly better, because it first attempts
getting the appearance from the XDG desktop portal and then falls back
to the X11 interface.
Before this patch there was a very weird issue for folks using the OS
system dark mode with the following config snippet:
```
color_scheme = scheme_for_appearance(wezterm.gui.get_appearance())
```
The color_scheme on startup would be correct, but there would be a very
weird problem where sometimes wezterm ignores the first time that the
portal notifies about an appearance update.
The source of the bug was an inconsistent retrieval of the appearance
setting:
- The Lua API used the XDG desktop portal
- The internal appearance used the X11 specific connection at startup
For example due to this, the internal appearance variable could have
stored "Dark" from the X11 connection, but the actual appearance from
the XDG desktop portal was "Light".
If then the XDG desktop portal changes to "Dark", the
appearance_changed() method would dismiss the update because
self.appearance was already "Dark".
It is only after that, that the internal inconsistency would have been
solved and following appearance changes would succeed and update the
colorscheme correctly.
To fix this problem, we now use the portal directly in both the x11 and
wayland connections, which is consistent with the Lua
wezterm.gui.get_appearance() API.
refs: #2258
Querying the window can call into windowproc so we need to avoid
it when we hold `inner`. Adjust the flow so that we can get
the info about the window state purely from an HWND.
refs: #2257
Since applying the maximized state is async, we hadn't fully applied
it before we got to the startup logic that resizes the window to fit
the initial terminal size.
This adds a final check to see if we are resizable before we try
to apply that size, and skips it.
refs: #284
Hook it up for resolving geometry, but note that wayland doesn't
allow positioning and we don't expose a way to set width/height
based on screen right now.
On Windows, GDI returns unintuitive names like "\\.\DISPLAY6" that
may not start numbered at either 0 or 1.
This commit grubs through the various APIs so that we can produce more
meaningful names like "DISPLAY6: Gigabyte M32u on NVIDIA 2080 TI"
instead.
This commit also makes the lua wezterm.window.screens() function
consistent with the internal resolve_geom functions that each different
implementation had, so that we can eliminate those functions in
favor of this new one on the ConnectionOps trait.
Still need to do macOS and verify that this commit doesn't break X11.
Currently implemented on X11 only, this function returns information
about the geometry of the screen(s).
This is taken from the same source of information we use for the
`--position` CLI argument to `wezterm start`.
```
> wezterm.window.screens()
{
"by_name": {
"DisplayPort-1": {
"height": 2160,
"name": "DisplayPort-1",
"width": 3840,
"x": 0,
"y": 0,
},
},
"main": {
"height": 2160,
"name": "DisplayPort-1",
"width": 3840,
"x": 0,
"y": 0,
},
"origin_x": 0,
"origin_y": 0,
"virtual_height": 2160,
"virtual_width": 3840,
}
```
This is a bit of an unsatisfactory commit... the bulk of it is
augmenting our calls into XCB to ensure that we check the status of each
request; the idea was that doing so would highlight the source of the
bad drawable error that is being surfaced in #2198, but after doing
that, it still doesn't highlight the offending call.
My conclusion is that either something in MESA/EGL or the IME is
generating calls that we cannot see into and that one of those is
referencing the window id that we just destroyed.
The resolution then is a bit gross: instead of destroying the window
when we need to close it, we first unmap it to remove it from the
screen, then after 2 seconds we destroy it.
refs: https://github.com/wez/wezterm/issues/2198