Skip to content

Conversation

@bkueng
Copy link
Contributor

@bkueng bkueng commented Jan 25, 2025

When a monitor gets disconnected, the destroy event of all associated windows gets called, and the window gets removed.

This PR changes that behavior: the window is still closed but the configuration is kept using the existing reload mechanism. In addition, a callback is added to listen for new monitors, triggering a reload when a new monitor gets connected.

This logic also reloads already running windows, which has a positive and negative effect:

  • positive: if currently running e.g. on the second monitor specified in the list, the window can get moved to the first monitor
  • negative: if reloading starts it on the same monitor, it gets reset (e.g. graphs)

I also had to work around an issue: the monitor model is not yet available immediately when a new monitor callback triggers. Waiting in the callback does not help (I tried 10 seconds). However, waiting outside, it always became available after 10ms.

Tested with a dual monitor setup under KDE through a combinations of:

  • enabling/disabling individual monitors
  • switching between monitors
  • specifying a specific monitor in the yuck config
  • specifying a list of specific monitors in the yuck config

In all these cases the behavior is as expected, and the widget gets loaded on the first available monitor (or stays unloaded until one becomes available).
It also works when opening a window without any of the configured monitors being available.

There is one remaining error from GTK when closing the window: GLib-GObject-CRITICAL **: 20:06:05.912: ../gobject/gsignal.c:2684: instance '0x55a4ab4be2d0' has no handler with id '136'.
This comes from the self.gtk_window.disconnect(handler_id) call. To prevent that we'd have to reset destroy_event_handler_id.

I have not tested under X11, and I'm not sure if the behavior should be the same there.

Fixes #1158

Checklist

Please make sure you can check all the boxes that apply to this PR.

  • All widgets I've added are correctly documented.
  • I added my changes to CHANGELOG.md, if appropriate.
  • The documentation in the docs/content/main directory has been adjusted to reflect my changes.
  • I used cargo fmt to automatically format all code before committing

@elkowar
Copy link
Owner

elkowar commented Feb 5, 2025

I'm down to merge this once someone has tested if the behavior breaks anything under X11, once the conficts are resolved ^^

@bkueng bkueng force-pushed the improve_multi_monitor_wayland branch 2 times, most recently from 9aec9e9 to 6b0f42e Compare February 10, 2025 17:54
@bkueng
Copy link
Contributor Author

bkueng commented Feb 10, 2025

I still have an old system with X11 installed, and was able to test there. It works as well with 2 differences in behavior:

  • the 'on new monitor' callback gets called twice whenever a new monitor is connected
  • the window does not get distroyed when the underlying monitor is disconnected.

I also rebased and resolved the conflicts.

There was a regression in a recently added commit (29fa158) which I fixed in 6b0f42e.

@bkueng
Copy link
Contributor Author

bkueng commented Feb 24, 2025

@elkowar is there anything else I can or should do to get this merged?

@Flat
Copy link

Flat commented Mar 13, 2025

I've been using this branch for a few days now, and when I re-connect monitors it causes a SIGABRT. Backtrace attached. Very consistently happens every time.
gdb.txt

@bkueng
Copy link
Contributor Author

bkueng commented Mar 17, 2025

@Flat which Linux distribution and desktop environment / window manager do you use?
And could you provide the yuck config, maybe it helps to reproduce?

@Flat
Copy link

Flat commented Mar 17, 2025

@Flat which Linux distribution and desktop environment / window manager do you use? And could you provide the yuck config, maybe it helps to reproduce?

Arch Linux with Hyprland (From git master)

Attached is the yuck config as well.
eww.txt

From the crash dump, it appears to be coming from this https://github.com/elkowar/eww/pull/1276/files#diff-12f72e340b5f9de88e64ebfc3df46f5d14a2bc5b0b2221eadf43ba087765d762R157-R158 as it is the only closure in wait_for_monitor_model

I would assume it is hitting something on the monitors before they are fully initialized.

@cstruck
Copy link

cstruck commented Mar 18, 2025

It often works but sometimes eww crashes

 2025-03-18T21:52:10.131Z INFO  eww::server             > New monitor connected, reloading configuration
 2025-03-18T21:52:10.639Z WARN  eww::app                > Timed out waiting for monitor model to be set
 2025-03-18T21:52:10.640Z INFO  eww::app                > Reloading windows
 2025-03-18T21:52:10.758Z INFO  eww::app                > Opening window win0 as 'win0'
 2025-03-18T21:52:11.445Z INFO  eww::server             > New monitor connected, reloading configuration
 2025-03-18T21:52:11.446Z INFO  eww::app                > Opening window win1 as 'win1'
 2025-03-18T21:52:11.486Z INFO  eww::server             > Reloaded config successfully

thread 'main' panicked at /var/tmp/portage/gui-apps/eww-9999/work/cargo_home/gentoo/glib/src/main_context_futures.rs:238:56:
called `Result::unwrap()` on an `Err` value: EnterError
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'main' panicked at library/core/src/panicking.rs:218:5:
panic in a function that cannot unwind
stack backtrace:
   0:     0x55a4fdb5ceba - <unknown>
   1:     0x55a4fdb89ed3 - <unknown>
   2:     0x55a4fdb57dd3 - <unknown>
   3:     0x55a4fdb5cd02 - <unknown>
   4:     0x55a4fdb5deb0 - <unknown>
   5:     0x55a4fdb5dc90 - <unknown>
   6:     0x55a4fdb5e612 - <unknown>
   7:     0x55a4fdb5e386 - <unknown>
   8:     0x55a4fdb5d3b9 - <unknown>
   9:     0x55a4fdb5e04d - <unknown>
  10:     0x55a4fd03b36d - <unknown>
  11:     0x55a4fd03b402 - <unknown>
  12:     0x55a4fd03b526 - <unknown>
  13:     0x55a4fdb28127 - <unknown>
  14:     0x7fafa0810ae2 - <unknown>
  15:     0x7fafa0813f07 - <unknown>
  16:     0x7fafa08146b0 - g_main_context_iteration
  17:     0x7fafa0ff73f5 - gtk_main_iteration_do
  18:     0x55a4fdb202eb - <unknown>
  19:     0x55a4fd1a236b - <unknown>
  20:     0x55a4fd1a5a3d - <unknown>
  21:     0x55a4fd18e35e - <unknown>
  22:     0x55a4fdb27e18 - <unknown>
  23:     0x7fafa0810ae2 - <unknown>
  24:     0x7fafa0813f07 - <unknown>
  25:     0x7fafa081499f - g_main_loop_run
  26:     0x7fafa0ff72fd - gtk_main
  27:     0x55a4fd2443f9 - <unknown>
  28:     0x55a4fd24a09f - <unknown>
  29:     0x55a4fd1289d3 - <unknown>
  30:     0x55a4fd3178e9 - <unknown>
  31:     0x55a4fdb4db07 - <unknown>
  32:     0x55a4fd24ce05 - <unknown>
  33:     0x7fafa05201ee - <unknown>
  34:     0x7fafa05202a9 - __libc_start_main
  35:     0x55a4fd03ba35 - <unknown>
  36:                0x0 - <unknown>
thread caused non-unwinding panic. aborting.

this happens with wayland (hyprland)

@bkueng
Copy link
Contributor Author

bkueng commented Mar 20, 2025

Thanks for the data points. I was able to find the problem and pushed a fix.
Could you give it another try?

@Flat
Copy link

Flat commented Mar 20, 2025

Thanks for the data points. I was able to find the problem and pushed a fix. Could you give it another try?

So far looks like it is now working as intended!

@Philipp-M
Copy link

I've tested it on both X as well as wayland where the bug indeed seems to be fixed.
Thanks for fixing this!

@cstruck
Copy link

cstruck commented Mar 29, 2025

can confirm didn't happen since

@Sahnvour
Copy link

That would really help for my setup, using a kvm switch means I need to restart eww each time I switch video input.

@cstruck
Copy link

cstruck commented Apr 14, 2025

@elkowar anything you still need to get this merged?

@cstruck
Copy link

cstruck commented Jun 13, 2025

@elkowar I'm running this PR branch since the 20.03. without any problems can I somehow support to get this merged?

@elkowar
Copy link
Owner

elkowar commented Jun 13, 2025

@bkueng could you rebase this onto the latest master? I'm down to merge! Sorry for being gone for so long ^^'

bkueng added 2 commits June 16, 2025 20:50
When a monitor gets disconnected, the destroy event of all associated
windows gets called, and the window gets removed.

This patch changes that behavior: the window is still closed but the
configuration is kept using the existing reload mechanism.
In addition, a callback is added to listen for new monitors, triggering
a reload when a new monitor gets connected.

This logic also reloads already running windows, which has a positive and
negative effect:
- positive: if currently running e.g. on the second monitor specified in
  the list, the window can get moved to the first monitor
- negative: if reloading starts it on the same monitor, it gets reset
  (e.g. graphs)

I also had to work around an issue: the monitor model is not yet available
immediately when a new monitor callback triggers. Waiting in the callback
does not help (I tried 10 seconds). However, waiting outside, it always
became available after 10ms.

Tested with a dual monitor setup under KDE through a combinations of:
- enabling/disabling individual monitors
- switching between monitors
- specifying a specific monitor in the yuck config
- specifying a list of specific monitors in the yuck config

In all these cases the behavior is as expected, and the widget gets loaded
on the first available monitor (or stays unloaded until one becomes
available).
It also works when opening a window without any of the configured monitors
being available.

There is one remaining error from GTK when closing the window:
GLib-GObject-CRITICAL **: 20:06:05.912: ../gobject/gsignal.c:2684: instance '0x55a4ab4be2d0' has no handler with id '136'
This comes from the `self.gtk_window.disconnect(handler_id)` call. To
prevent that we'd have to reset `destroy_event_handler_id`.
Executors that poll a future cannot be called recursively (in this case
glib::main_context_futures::TaskSource::poll).
So we cannot call gtk::main_iteration_do here, which in some cases led to
the future being polled again, which raised a panic in the form of:
thread 'main' panicked at glib/src/main_context_futures.rs:238:56:
called `Result::unwrap()` on an `Err` value: EnterError

We can just remove it as tokio::time::sleep() ensures the main thread
continues to process (gtk) events during that time.
@bkueng bkueng force-pushed the improve_multi_monitor_wayland branch from b0bc461 to c85c8e8 Compare June 16, 2025 18:55
@bkueng
Copy link
Contributor Author

bkueng commented Jun 16, 2025

@elkowar I understand the problem of having little time but I do hope it's the last time I rebased. I also have 2 other PR's which have conflicts by now: #1267 and #1277

@elkowar elkowar merged commit 0e409d4 into elkowar:master Jun 17, 2025
1 check passed
@Sahnvour
Copy link

Hi @elkowar, sorry to ping you, but since this fix was quite wanted, would you consider doing a new release?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Crash when monitor turned off

6 participants