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
This commit adds more trace logging around selection
related events.
That tracing uncovered a situation, when multiple wezterm windows within
the same process were involved, where one window didn't receive a
selection-clear event notification.
Since Window::get_clipboard trusted our local understand of the
clipboard contents, it would return those until the selection was
changed in that window.
This commit changes that code to always ask the X server for the
selection. It makes pasting slightly slower, but should always produce
consistent results.
refs: https://github.com/wez/wezterm/issues/2110
deadkeys that are triggered through shift (eg: backtick on a German
layout) weren't working because we were trying to lookup in our maps
using `SHIFT | LEFT_SHIFT` when the map data was keyed only by `SHIFT`.
This commit removes the positional modifier flags from the modifier
keys and restores the correct behavior.
refs: https://github.com/wez/wezterm/issues/2102
This does two things:
* Sets the event queue owner explicitly to xcb
* Adopts a dri2 resize related workaround from the rust-xcb opengl
example
I think the latter is probably a NOP, but the former sounds like
something important.
refs: #1992
Adds a configuration option, `focus_change_repaint_delay` to allow customisation of the delay added in 9b6329b454.
The default delay remains 100ms, and can be disabled by setting it to `0`, if the workaround is not required on the user's system.
refs: #2063
refs: #1992
The hope here is that the nvidia-specific resize issue might have
a workaround if it is emitting some other events that we were
previously not listening for.
This commit optionally enables the Present extension and listens
for its version of CONFIGURE_NOTIFY, routing it through the same
logic as the base CONFIGURE_NOTIFY event.
On my AMD hardware under Gnome, I see something like:
```
18:04:26.476 TRACE window::os::x11::window > Present::ConfigureNotify: width 1168 -> 1180, height 858 -> 873, dpi 124.7998046875 -> 124.7998046875
18:04:26.478 TRACE window::os::x11::window > Ignoring X::ConfigureNotify (1180x873 dpi=124.7998046875) because width,height,dpi are unchanged
```
with the Present event firing before the X event.
Let's see how this goes.
refs: #2063
refs: #1992
Main idea here is to add expose events to the trace so that we
can get a sense of whether those are emitted when a WM isn't delivering
CONFIGURE_NOTIFY consistently.
If the exposed area is bigger than what we think the window is,
then we mark geometry as unsure.
I'm considering always marking as unsure for an expose event,
or at least, adding a config option to enable that, as a way
to workaround this situation.
refs: https://github.com/wez/wezterm/issues/2063
refs: https://github.com/wez/wezterm/issues/1992
This commit:
* Logs atom names in property change events (makes it easier to
understand user's logs)
* Sets flags in cases where property changes might imply that a
configure or focus event should have or should be sent
* Adjusts the "unsure about state" logic so that it doesn't just
trigger on the initial paint, but also on those flags being set
refs: https://github.com/wez/wezterm/issues/1992
I think this might only be a thing on Windows.
This commit speculatively (I'm on a mac at the moment!) allows tracking
the left/right control/shift modifier flags and passing that through
to the win32 input mode logic.
refs: https://github.com/wez/wezterm/issues/2009
Mutter recently started to enforce a protocol error that enforces
the ordering of buffer updates and that is flushing out some
bugs in various places; here's a related issue that I stumbled
into when I set my scaling to 300% and got stuck:
https://gitlab.gnome.org/GNOME/mutter/-/issues/2083
What that means to us is that we have to be careful when updating
the buffer scaling properties on our EGL surface.
We don't actually own the underlying buffer or the underlying
buffer commits, so we have to be a little indirect: what
we do here is detach the EGL managed buffer when we notice
that scaling has changed, and that appears to satisfy the
compositor.
refs: https://github.com/wez/wezterm/issues/1727
The rust xcb bindings seem to have gotten more strict in 1.x;
previously we might generate two DestroyWindow calls for the same
window when closing one and things were fine, but now the second
call generates a protocol error which has the effect of terminating
the program.
This commit ensures that we only generate a single DestroyWindow
call by zeroing out the saved window_id after we emit it.
refs: #1974
* Add support for drag and drop files in Windows
* Add two drag and drop filename quoting patterns (mainly) for Windows, change doc examples.
* Code style cleanup
* Improve Windows quoting pattern and rename DoubleQuoteAlways to WindowsAlwaysQuoted
* Improve special char finding for DroppedFileQuoting::Windows and fix doc.
This cleans up the `cargo audit` output on linux because the `clipboard`
crate (which hasn't been updated in 3 years) depends on xcb=0.8.2
which is flagged by cargo audit.
We don't use `clipboard` on any platform except macos
This commit switches to the `clipboard_macos` crate; that appears to
use a copy and paste of the macos specific code from the `clipboard`
crate, so this shouldn't have any change in functionality.
refs: https://github.com/wez/wezterm/issues/1952
The upgrade to a newer mio version caused the poll method
to report EINTR in some cases.
We don't need to terminate for those, so suppress it.
refs: https://github.com/wez/wezterm/issues/1955
a redo of 81d08325c1, which was a bit
more nuanced. Partially revert the logic from that commit and rephrase
it as factoring out the condition to make that part clearer, but restore
the original action, which is important in order to propagate the
modifiers through.
refs: https://github.com/wez/wezterm/issues/1907#issuecomment-1108797343
I think I'd like to make a config option for this, but for the moment,
this first pass unconditionally updates the base environment with
data from the registry.
refs: https://github.com/wez/wezterm/issues/1848
Looking closer, I think I'd misread the key event generated by
perform_key_equivalent for the ctrl-escape case as a key down.
Fixing this is fairly straightforward: when we return YES from
perform_key_equivalent we synthesize a key_down event.
macos will follow up with the key up.
We can fold two cases together in there and remove the horrible
hack style fix I just added in a4b68247bb
refs: https://github.com/wez/wezterm/issues/1877
We want to avoid normalizing control key presses; there were
two places where it was happening; one in our own code and
the other was in the xkeyboard mapping stuff itself.
refs: https://github.com/wez/wezterm/issues/1851
There are certain key combinations that macOS prefers to handle
without giving the application much opportunity to process them.
CTRL-ESC and CMD-. both cause doCommandBySelector(cancel:) to be
called. The former we had already special cased but since we
can't disambiguate the two things, we need a better way.
performKeyEquivalent: is a method we can implement to have an
opportunity to "do something" and prevent the default macOS behavior.
So we implement that. What's interesting is that saying that we handled
CMD-. results in no further processing at all by macOS, whereas saying
that we handled CTRL-ESC results in macOS doing the normal key event
dispatch. So we need to route that event for ourselves in that one
case.
Doesn't feel great!
refs: https://github.com/wez/wezterm/issues/1867
Go directly to the underlying env_logger crate, as pretty_env_logger
hasn't been updated in some time, and I'd like to be able to redirect
the log output to a file more directly, and that feature is in a newer
version of the env logger than pretty_env_logger was pulling in.
For reasons that I cannot remember, I made
`send_composed_key_when_left_alt_is_pressed` and
`send_composed_key_when_right_alt_is_pressed` only take effect if only
the ALT modifiers were pressed. If SHIFT or CTRL were pressed, then
the purpose of `send_composed_key_when_left_alt_is_pressed` was
bypassed.
This commit scopes this back to the alt mods - other kinds of mods
don't affect this functionality any more.
refs: https://github.com/wez/wezterm/issues/1826
We were pinned on the revision where I had added dual source blending,
because I wanted that feature ahead of the crate being published.
Since then a couple of releases have been made so we can unpin.
On Windows 11, we had a report of glium complaining about the opengl
version. I can't find that error message string in the current version
of the code so it's possible that that situation has been resolved.
refs: https://github.com/wez/wezterm/issues/1813
This is mostly a refactoring: pulling out the discrete width/height from
the `new_window` method and preparing to pass down x/y coords as well.
The types are expressed as Dimension so that screen relative sizes could
be expressed in the future... once we know how to obtain that
information on each platform.
refs: https://github.com/wez/wezterm/issues/1794
- Simplify scroll thumb calculations
- Correct thumb position when dragging with mouse
- Support border OS parameters
- Use usize for OS borders, to explicitly only accept positive integers
- Get correct tab height when using fancy tab bar
- Correctly draw depending on tab bar position
- Adjust minimum thumb size to be 1/2 of a cell height, so it has consistent size across platforms and screen densities
Fixes#1525
We don't assume that we start up focused, and some WM don't tell
us our focus state, so prior to painting, if we don't know the
focus state, explicitly query it and synthesize a focus change event.
refs: https://github.com/wez/wezterm/issues/1757
Flesh out the get_os_parameters impl for macOS. When running on a
system that provides `NSScreen::safeAreaInsets`, use that to determine
the border required to avoid the "notch" on certain models of mac.
In the GUI layer: when the os parameters include a border, adjust
the render position to account for it.
This is a bit of a speculative change, as I don't have a mac with
a notch.
refs: https://github.com/wez/wezterm/issues/1737
If the WM has never confirmed our size and we're about to paint,
explicitly query it and generate a resize event so that we stand
a better chance of showing the right stuff.
refs: https://github.com/wez/wezterm/issues/1710
When the user switches to another virtual console and then back into a
Wayland session, a number of seat updates are received by the listener
installed by `Environment::listen_for_seats()`. These updates
essentially flip the keyboard and pointer flags off and then back on in
the seat data, which indicates that new handlers need to be assigned to
the keyboard and pointer objects.
However, because one update is received for _each_ flag being toggled,
this means that the listener is fired twice with `has_keyboard` set to
true, which means that two keyboard handlers end up being installed.
Users then experience each keypress being delivered twice to the
terminal.
This commit adds a map to track the keyboard object that has been
assigned on each seat, thereby preventing duplicate assignments and (by
extension) duplicate keypresses being registered. This logic is
essentially the same as what's used in the `kbd_input` example in SCTK,
which doesn't have this issue.
Something similar is required for pointer handling, which also breaks
after switching to another virtual console and back into Wayland, but I
was scared off by the TODO in the `listen_for_seats` callback and didn't
investigate this further.
On Windows in FRA layout, `^^SPACE` results in `^^SPACE`, whereas
on Linux it results in `^SPACE`. We were doing the latter instead
of the former.
Let's just be consistent with other windows apps.
closes: #1729closes: #1730