Repository: wezterm/wezterm (language: rust)

Issue:
wayland: Pressing and holding a button is laggy when using the webgpu frontend
### What Operating System(s) are you seeing this problem on?

Linux Wayland

### Which Wayland compositor or X11 Window manager(s) are you using?

Mutter

### WezTerm version

20230407-221507-36d5307b

### Did you try the latest nightly build to see if the issue is better (or worse!) than your current version?

Yes, and I updated the version box above to show the version of the nightly that I tried

### Describe the bug

After the latest commit, the webgpu frontend has become usable on Linux.
But pressing and holding a key is really laggy now.
Whether its holding backspace to delete, a character to type, or even arrow keys to navigate.

This only happens in the wayland and not in the xwayland version 

### To Reproduce

Open wezterm and press and hold any key

### Configuration

local wezterm = require 'wezterm';
local act = wezterm.action

return {
  window_decorations = "INTEGRATED_BUTTONS|RESIZE",
  integrated_title_button_style = "Gnome",
  color_scheme = "Kasugano (terminal.sexy)",
  enable_wayland = true,
  hide_mouse_cursor_when_typing = false,
  front_end = 'WebGpu'
}


### Expected Behavior

The action happens continuously and smoothly instead of being laggy.

### Logs

```
wezterm version: 20230407-221507-36d5307b x86_64-unknown-linux-gnu
Window Environment: Wayland
OpenGL version: WebGPU: name=AMD Radeon Graphics (RADV RENOIR), device_type=IntegratedGpu, backend=Vulkan, driver=radv, driver_info=Mesa 23.0.1, vendor=4098, device=5688
```
Launching with `WAYLAND_DEBUG=1 wezterm` and holding a key gives the following loop:

```
[ 659559.337] wl_buffer@48.release()
[ 659574.863] wl_display@1.delete_id(78)
[ 659574.885] wl_callback@78.done(5654499)
[ 659574.899]  -> wl_surface@20.attach(wl_buffer@48, 0, 0)
[ 659574.918]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659574.931]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659574.943]  -> wl_surface@20.commit()
[ 659575.768] wl_buffer@69.release()
[ 659591.372] wl_display@1.delete_id(78)
[ 659591.400] wl_callback@78.done(5654516)
[ 659591.420]  -> wl_surface@20.attach(wl_buffer@69, 0, 0)
[ 659591.433]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659591.448]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659591.459]  -> wl_surface@20.commit()
[ 659592.027]  -> zwp_text_input_v3@14.set_cursor_rectangle(640, 63, 10, 20)
[ 659592.042]  -> zwp_text_input_v3@14.commit()
[ 659592.563] wl_buffer@48.release()
[ 659607.587] wl_display@1.delete_id(78)
[ 659607.611] wl_callback@78.done(5654532)
[ 659607.630]  -> wl_surface@20.attach(wl_buffer@48, 0, 0)
[ 659607.644]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659607.652]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659607.664]  -> wl_surface@20.commit()
[ 659608.452] zwp_text_input_v3@14.done(46)
[ 659609.699] wl_buffer@69.release()
[ 659624.235] wl_display@1.delete_id(78)
[ 659624.251] wl_callback@78.done(5654549)
[ 659624.258]  -> wl_surface@20.attach(wl_buffer@69, 0, 0)
[ 659624.269]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659624.275]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659624.279]  -> wl_surface@20.commit()
[ 659624.849] wl_buffer@48.release()
[ 659639.689] wl_display@1.delete_id(78)
[ 659639.698] wl_callback@78.done(5654564)
[ 659639.702]  -> wl_surface@20.attach(wl_buffer@48, 0, 0)
[ 659639.705]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659639.708]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659639.710]  -> wl_surface@20.commit()
[ 659640.055] wl_buffer@69.release()
[ 659658.082] wl_display@1.delete_id(78)
[ 659658.112] wl_callback@78.done(5654582)
[ 659658.123]  -> wl_surface@20.attach(wl_buffer@69, 0, 0)
[ 659658.132]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659658.139]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659658.145]  -> wl_surface@20.commit()
[ 659659.266] wl_buffer@48.release()
[ 659673.854] wl_display@1.delete_id(78)
[ 659673.879] wl_callback@78.done(5654598)
[ 659673.900]  -> wl_surface@20.attach(wl_buffer@48, 0, 0)
[ 659673.914]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659673.924]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659673.936]  -> wl_surface@20.commit()
[ 659674.837] wl_buffer@69.release()
[ 659690.713] wl_display@1.delete_id(78)
[ 659690.721] wl_callback@78.done(5654615)
[ 659690.725]  -> wl_surface@20.attach(wl_buffer@69, 0, 0)
[ 659690.729]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659690.733]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659690.735]  -> wl_surface@20.commit()
[ 659691.053] wl_buffer@48.release()
[ 659707.664] wl_display@1.delete_id(78)
[ 659707.689] wl_callback@78.done(5654632)
[ 659707.700]  -> wl_surface@20.attach(wl_buffer@48, 0, 0)
[ 659707.709]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659707.717]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659707.723]  -> wl_surface@20.commit()
[ 659708.797] wl_buffer@69.release()
[ 659724.595] wl_display@1.delete_id(78)
[ 659724.618] wl_callback@78.done(5654649)
[ 659724.636]  -> wl_surface@20.attach(wl_buffer@69, 0, 0)
[ 659724.650]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659724.660]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659724.671]  -> wl_surface@20.commit()
[ 659725.363]  -> zwp_text_input_v3@14.set_cursor_rectangle(650, 63, 10, 20)
[ 659725.382]  -> zwp_text_input_v3@14.commit()
````

### Anything else?

I don't have any knowledge about this, but for it to be smooth,
```
[ 659725.363]  -> zwp_text_input_v3@14.set_cursor_rectangle(650, 63, 10, 20)
[ 659725.382]  -> zwp_text_input_v3@14.commit()
```
Should be present in every loop?
wayland: Pressing and holding a button is laggy when using the webgpu frontend
### What Operating System(s) are you seeing this problem on?

Linux Wayland

### Which Wayland compositor or X11 Window manager(s) are you using?

Mutter

### WezTerm version

20230407-221507-36d5307b

### Did you try the latest nightly build to see if the issue is better (or worse!) than your current version?

Yes, and I updated the version box above to show the version of the nightly that I tried

### Describe the bug

After the latest commit, the webgpu frontend has become usable on Linux.
But pressing and holding a key is really laggy now.
Whether its holding backspace to delete, a character to type, or even arrow keys to navigate.

This only happens in the wayland and not in the xwayland version 

### To Reproduce

Open wezterm and press and hold any key

### Configuration

local wezterm = require 'wezterm';
local act = wezterm.action

return {
  window_decorations = "INTEGRATED_BUTTONS|RESIZE",
  integrated_title_button_style = "Gnome",
  color_scheme = "Kasugano (terminal.sexy)",
  enable_wayland = true,
  hide_mouse_cursor_when_typing = false,
  front_end = 'WebGpu'
}


### Expected Behavior

The action happens continuously and smoothly instead of being laggy.

### Logs

```
wezterm version: 20230407-221507-36d5307b x86_64-unknown-linux-gnu
Window Environment: Wayland
OpenGL version: WebGPU: name=AMD Radeon Graphics (RADV RENOIR), device_type=IntegratedGpu, backend=Vulkan, driver=radv, driver_info=Mesa 23.0.1, vendor=4098, device=5688
```
Launching with `WAYLAND_DEBUG=1 wezterm` and holding a key gives the following loop:

```
[ 659559.337] wl_buffer@48.release()
[ 659574.863] wl_display@1.delete_id(78)
[ 659574.885] wl_callback@78.done(5654499)
[ 659574.899]  -> wl_surface@20.attach(wl_buffer@48, 0, 0)
[ 659574.918]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659574.931]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659574.943]  -> wl_surface@20.commit()
[ 659575.768] wl_buffer@69.release()
[ 659591.372] wl_display@1.delete_id(78)
[ 659591.400] wl_callback@78.done(5654516)
[ 659591.420]  -> wl_surface@20.attach(wl_buffer@69, 0, 0)
[ 659591.433]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659591.448]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659591.459]  -> wl_surface@20.commit()
[ 659592.027]  -> zwp_text_input_v3@14.set_cursor_rectangle(640, 63, 10, 20)
[ 659592.042]  -> zwp_text_input_v3@14.commit()
[ 659592.563] wl_buffer@48.release()
[ 659607.587] wl_display@1.delete_id(78)
[ 659607.611] wl_callback@78.done(5654532)
[ 659607.630]  -> wl_surface@20.attach(wl_buffer@48, 0, 0)
[ 659607.644]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659607.652]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659607.664]  -> wl_surface@20.commit()
[ 659608.452] zwp_text_input_v3@14.done(46)
[ 659609.699] wl_buffer@69.release()
[ 659624.235] wl_display@1.delete_id(78)
[ 659624.251] wl_callback@78.done(5654549)
[ 659624.258]  -> wl_surface@20.attach(wl_buffer@69, 0, 0)
[ 659624.269]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659624.275]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659624.279]  -> wl_surface@20.commit()
[ 659624.849] wl_buffer@48.release()
[ 659639.689] wl_display@1.delete_id(78)
[ 659639.698] wl_callback@78.done(5654564)
[ 659639.702]  -> wl_surface@20.attach(wl_buffer@48, 0, 0)
[ 659639.705]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659639.708]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659639.710]  -> wl_surface@20.commit()
[ 659640.055] wl_buffer@69.release()
[ 659658.082] wl_display@1.delete_id(78)
[ 659658.112] wl_callback@78.done(5654582)
[ 659658.123]  -> wl_surface@20.attach(wl_buffer@69, 0, 0)
[ 659658.132]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659658.139]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659658.145]  -> wl_surface@20.commit()
[ 659659.266] wl_buffer@48.release()
[ 659673.854] wl_display@1.delete_id(78)
[ 659673.879] wl_callback@78.done(5654598)
[ 659673.900]  -> wl_surface@20.attach(wl_buffer@48, 0, 0)
[ 659673.914]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659673.924]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659673.936]  -> wl_surface@20.commit()
[ 659674.837] wl_buffer@69.release()
[ 659690.713] wl_display@1.delete_id(78)
[ 659690.721] wl_callback@78.done(5654615)
[ 659690.725]  -> wl_surface@20.attach(wl_buffer@69, 0, 0)
[ 659690.729]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659690.733]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659690.735]  -> wl_surface@20.commit()
[ 659691.053] wl_buffer@48.release()
[ 659707.664] wl_display@1.delete_id(78)
[ 659707.689] wl_callback@78.done(5654632)
[ 659707.700]  -> wl_surface@20.attach(wl_buffer@48, 0, 0)
[ 659707.709]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659707.717]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659707.723]  -> wl_surface@20.commit()
[ 659708.797] wl_buffer@69.release()
[ 659724.595] wl_display@1.delete_id(78)
[ 659724.618] wl_callback@78.done(5654649)
[ 659724.636]  -> wl_surface@20.attach(wl_buffer@69, 0, 0)
[ 659724.650]  -> wl_surface@20.damage(0, 0, 2147483647, 2147483647)
[ 659724.660]  -> wl_surface@20.frame(new id wl_callback@78)
[ 659724.671]  -> wl_surface@20.commit()
[ 659725.363]  -> zwp_text_input_v3@14.set_cursor_rectangle(650, 63, 10, 20)
[ 659725.382]  -> zwp_text_input_v3@14.commit()
````

### Anything else?

I don't have any knowledge about this, but for it to be smooth,
```
[ 659725.363]  -> zwp_text_input_v3@14.set_cursor_rectangle(650, 63, 10, 20)
[ 659725.382]  -> zwp_text_input_v3@14.commit()
```
Should be present in every loop?


Discussion / hints:
[Kooha-2023-04-08-20-16-32.webm](https://user-images.githubusercontent.com/479816/230715977-4ee043e4-c19f-4194-915f-09b3c30166e4.webm)

a few observations:

- at least on my system (Radeon 6800XT) and to my eyes, this doesn't seem laggy or choppy
- while the window is focused, the frame->commit->damage->commit loop is happening over and over
- when the window loses focus, the loop stops

I'm not sure if the that loop happening over and over is what is interfering with your frame rate, that loop might be expected, but it also could be part of the issue :shrug: 
@jokeyrhyme Can you compare it to the OpenGL backend?
Also, interestingly, its not that laggy when using with bash, still a lot compared to the OpenGL version, but the lag is definitely there when using it with nushell.
I guess this is just WebGpu frontend needing more time and maturity :confused: 
Let's record somewhere here that this might be related to the work done in https://github.com/wez/wezterm/commit/36d5307b801c4343065ad5e540ca420cc93d19e8 to solve https://github.com/wez/wezterm/issues/3126
When I run this in OpenGL mode, the performance/latency/smoothness is indistinguishable to my eye, and running `btm` inside the fresh build of `wezterm` doesn't show any weird lag, and also doesn't show significant difference in CPU usage

That said, I do have an integrated GPU (so far I've only tested on a discrete GPU), so I should switch to that and see if the performance is different
Okay, trying out WebGPU on my integrated GPU:

```
wezterm version: 20230408-112425-69ae8472 x86_64-unknown-linux-gnu
Window Environment: Wayland
OpenGL version: WebGPU: name=AMD Radeon Graphics (RADV GFX1036), device_type=IntegratedGpu, backend=Vulkan, driver=radv, driver_info=Mesa 23.0.2, vendor=4098, device=5710
```

Interestingly, when I exit, it logs:

```
warning: queue 0x55d5dd36c9e0 destroyed while proxies still attached:
  zwp_primary_selection_offer_v1@4278190091 still attached
  wl_data_offer@4278190081 still attached
  wl_data_offer@4278190088 still attached
  wl_data_offer@4278190082 still attached
  wl_data_offer@4278190087 still attached
  wl_data_source@54 still attached
  wl_data_offer@4278190083 still attached
  zwp_primary_selection_source_v1@56 still attached
  wl_data_source@58 still attached
  wl_buffer@43 still attached
  wl_buffer@46 still attached
  wl_shm_pool@48 still attached
  wl_buffer@50 still attached
  wl_shm_pool@51 still attached
  wl_data_offer@4278190084 still attached
  wl_data_offer@4278190080 still attached
  xdg_wm_base@22 still attached
  wl_surface@21 still attached
  wl_data_device@18 still attached
  wl_pointer@16 still attached
  zwp_text_input_v3@15 still attached
  wl_keyboard@14 still attached
  zwp_primary_selection_device_v1@13 still attached
  zwp_primary_selection_device_manager_v1@3 still attached
  wl_data_device@12 still attached
  wl_output@11 still attached
  wl_seat@10 still attached
  zwp_text_input_manager_v3@9 still attached
  zxdg_decoration_manager_v1@8 still attached
  wl_data_device_manager@7 still attached
  wl_subcompositor@6 still attached
  wl_compositor@5 still attached
  wl_shm@4 still attached
  wl_registry@2 still attached
```

Still seems pretty smooth though

And no change in performance when running via Xwayland on the integrated GPU:

```
wezterm version: 20230408-112425-69ae8472 x86_64-unknown-linux-gnu
Window Environment: X11 wlroots wm
OpenGL version: WebGPU: name=AMD Radeon Graphics (RADV GFX1036), device_type=IntegratedGpu, backend=Vulkan, driver=radv, driver_info=Mesa 23.0.2, vendor=4098, device=5710
```
Okay, I can reproduce this on a Dell Precision 5550 with an Intel integrated GPU
I've been thinking about the blocked frame queue from #3126 , and the new behaviour in https://github.com/wez/wezterm/commit/36d5307b801c4343065ad5e540ca420cc93d19e8 which is a firehose of frames

In the ideal case, we'd figure out why the compositor isn't asking for new frames and fix it there

I do have some work-around ideas in the meantime:
- implement `max_fps` ( https://wezfurlong.org/wezterm/config/lua/config/max_fps.html ) for wayland so that it isn't a an unrestricted firehose of frames
- revert https://github.com/wez/wezterm/commit/36d5307b801c4343065ad5e540ca420cc93d19e8 and instead have an expiry or timeout on waiting for the compositor to ask for a new frame, so we don't wait forever, perhaps as an internal (non-configurable for now) concept of "min_fps"
https://matrix.to/#/!FZyQrssSlHEZqrYcOb:matrix.org/$RCv9tY1ipZ-QoxPSwe9gY77FVKA8lt5kTfYsvkRge4Y?via=matrix.org&via=mozilla.org&via=kde.org

https://matrix.to/#/!FZyQrssSlHEZqrYcOb:matrix.org/$0JHPA3iCPWtALFRAXXB3eCR9vzUOLUdRiOlWNTzL2sE?via=matrix.org&via=mozilla.org&via=kde.org

> so the thing to try is reverting our workaround from yesterday, then moving the self.events.dispatch(WindowEvent::NeedRepaint); line after self.frame_callback.replace(callback);
[Kooha-2023-04-08-20-16-32.webm](https://user-images.githubusercontent.com/479816/230715977-4ee043e4-c19f-4194-915f-09b3c30166e4.webm)

a few observations:

- at least on my system (Radeon 6800XT) and to my eyes, this doesn't seem laggy or choppy
- while the window is focused, the frame->commit->damage->commit loop is happening over and over
- when the window loses focus, the loop stops

I'm not sure if the that loop happening over and over is what is interfering with your frame rate, that loop might be expected, but it also could be part of the issue :shrug: 
@jokeyrhyme Can you compare it to the OpenGL backend?
Also, interestingly, its not that laggy when using with bash, still a lot compared to the OpenGL version, but the lag is definitely there when using it with nushell.
I guess this is just WebGpu frontend needing more time and maturity :confused: 
Let's record somewhere here that this might be related to the work done in https://github.com/wez/wezterm/commit/36d5307b801c4343065ad5e540ca420cc93d19e8 to solve https://github.com/wez/wezterm/issues/3126
When I run this in OpenGL mode, the performance/latency/smoothness is indistinguishable to my eye, and running `btm` inside the fresh build of `wezterm` doesn't show any weird lag, and also doesn't show significant difference in CPU usage

That said, I do have an integrated GPU (so far I've only tested on a discrete GPU), so I should switch to that and see if the performance is different
Okay, trying out WebGPU on my integrated GPU:

```
wezterm version: 20230408-112425-69ae8472 x86_64-unknown-linux-gnu
Window Environment: Wayland
OpenGL version: WebGPU: name=AMD Radeon Graphics (RADV GFX1036), device_type=IntegratedGpu, backend=Vulkan, driver=radv, driver_info=Mesa 23.0.2, vendor=4098, device=5710
```

Interestingly, when I exit, it logs:

```
warning: queue 0x55d5dd36c9e0 destroyed while proxies still attached:
  zwp_primary_selection_offer_v1@4278190091 still attached
  wl_data_offer@4278190081 still attached
  wl_data_offer@4278190088 still attached
  wl_data_offer@4278190082 still attached
  wl_data_offer@4278190087 still attached
  wl_data_source@54 still attached
  wl_data_offer@4278190083 still attached
  zwp_primary_selection_source_v1@56 still attached
  wl_data_source@58 still attached
  wl_buffer@43 still attached
  wl_buffer@46 still attached
  wl_shm_pool@48 still attached
  wl_buffer@50 still attached
  wl_shm_pool@51 still attached
  wl_data_offer@4278190084 still attached
  wl_data_offer@4278190080 still attached
  xdg_wm_base@22 still attached
  wl_surface@21 still attached
  wl_data_device@18 still attached
  wl_pointer@16 still attached
  zwp_text_input_v3@15 still attached
  wl_keyboard@14 still attached
  zwp_primary_selection_device_v1@13 still attached
  zwp_primary_selection_device_manager_v1@3 still attached
  wl_data_device@12 still attached
  wl_output@11 still attached
  wl_seat@10 still attached
  zwp_text_input_manager_v3@9 still attached
  zxdg_decoration_manager_v1@8 still attached
  wl_data_device_manager@7 still attached
  wl_subcompositor@6 still attached
  wl_compositor@5 still attached
  wl_shm@4 still attached
  wl_registry@2 still attached
```

Still seems pretty smooth though

And no change in performance when running via Xwayland on the integrated GPU:

```
wezterm version: 20230408-112425-69ae8472 x86_64-unknown-linux-gnu
Window Environment: X11 wlroots wm
OpenGL version: WebGPU: name=AMD Radeon Graphics (RADV GFX1036), device_type=IntegratedGpu, backend=Vulkan, driver=radv, driver_info=Mesa 23.0.2, vendor=4098, device=5710
```
Okay, I can reproduce this on a Dell Precision 5550 with an Intel integrated GPU
I've been thinking about the blocked frame queue from #3126 , and the new behaviour in https://github.com/wez/wezterm/commit/36d5307b801c4343065ad5e540ca420cc93d19e8 which is a firehose of frames

In the ideal case, we'd figure out why the compositor isn't asking for new frames and fix it there

I do have some work-around ideas in the meantime:
- implement `max_fps` ( https://wezfurlong.org/wezterm/config/lua/config/max_fps.html ) for wayland so that it isn't a an unrestricted firehose of frames
- revert https://github.com/wez/wezterm/commit/36d5307b801c4343065ad5e540ca420cc93d19e8 and instead have an expiry or timeout on waiting for the compositor to ask for a new frame, so we don't wait forever, perhaps as an internal (non-configurable for now) concept of "min_fps"
https://matrix.to/#/!FZyQrssSlHEZqrYcOb:matrix.org/$RCv9tY1ipZ-QoxPSwe9gY77FVKA8lt5kTfYsvkRge4Y?via=matrix.org&via=mozilla.org&via=kde.org

https://matrix.to/#/!FZyQrssSlHEZqrYcOb:matrix.org/$0JHPA3iCPWtALFRAXXB3eCR9vzUOLUdRiOlWNTzL2sE?via=matrix.org&via=mozilla.org&via=kde.org

> so the thing to try is reverting our workaround from yesterday, then moving the self.events.dispatch(WindowEvent::NeedRepaint); line after self.frame_callback.replace(callback);

Fix patch:
diff --git a/window/src/os/wayland/window.rs b/window/src/os/wayland/window.rs
index 189d3b5ee86..db66d7d2613 100644
--- a/window/src/os/wayland/window.rs
+++ b/window/src/os/wayland/window.rs
@@ -801,27 +801,26 @@ impl WaylandWindowInner {
         }
 
         self.invalidated = false;
-        self.events.dispatch(WindowEvent::NeedRepaint);
 
-        if self.gl_state.is_some() {
-            // Ask the compositor to wake us up when it is time to paint
-            // the next frame.
-            // We don't do this when we're using WebGPU because we don't
-            // always get a timely wakeup. We configure wgpu to use a
-            // vsync-equivalent PresentMode so we should already be
-            // respecting the maximum frame rate, making it less critical
-            // to rely on Wayland's frame scheduling.
-            // <https://github.com/wez/wezterm/issues/3126>
-            let window_id = self.window_id;
-            let callback = self.surface.frame();
-            callback.quick_assign(move |_source, _event, _data| {
-                WaylandConnection::with_window_inner(window_id, |inner| {
-                    inner.next_frame_is_ready();
-                    Ok(())
-                });
+        // Ask the compositor to wake us up when its time to paint the next frame,
+        // note that this only happens _after_ the next commit
+        let window_id = self.window_id;
+        let callback = self.surface.frame();
+        callback.quick_assign(move |_source, _event, _data| {
+            WaylandConnection::with_window_inner(window_id, |inner| {
+                inner.next_frame_is_ready();
+                Ok(())
             });
-            self.frame_callback.replace(callback);
-        }
+        });
+        self.frame_callback.replace(callback);
+
+        // The repaint has the side of effect of committing the surface,
+        // which is necessary for the frame callback to get triggered.
+        // Ordering the repaint after requesting the callback ensures that
+        // we will get woken at the appropriate time.
+        // <https://github.com/wez/wezterm/issues/3468>
+        // <https://github.com/wez/wezterm/issues/3126>
+        self.events.dispatch(WindowEvent::NeedRepaint);
 
         Ok(())
     }


Test patch: