lxqt / lxqt-session

The LXQt session manager
https://lxqt.github.io
GNU Lesser General Public License v2.1
57 stars 52 forks source link

Autostart much delayed under wayland #460

Closed stefonarch closed 1 year ago

stefonarch commented 1 year ago

If lxqt-session is started under wayland all applications that use the notification are starting with a delay of ~30sec, but also others like firefox. This is true also for lxqt-modules like lxqt-powermanagement. This is very inconvenient as suddenly many windows open up at the same time after half a minute. For some reason this is true also for firefox.

To avoid this behavior lxqt-panel or waybar can be started some seconds before lxqt-session itself in the compositors autostart settings.

Expected Behavior

Autostart is fast

Current Behavior

It has huge delays for most apps if the notification area is not available.

Possible Solution

The check for systray available doesn't work under wayland? mTrayStarted = QSystemTrayIcon::isSystemTrayAvailable();

But this doesn't explain the delay of firefox while thunderbird starts just fine. More investigating is needed.

I've tested this script - inserted in autostart - which starts all the "delayed" apps and it works with lxqt module lxqt-panel checked (started by the session).

while true; do
  if dbus-send --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListNames | grep -q org.kde.StatusNotifierWatcher; then
    echo "StatusNotifierArea is available"
    # Start your commands here
    lxqt-powermanagement &
    lxqt-notificationd &
    dimmer &
    cmst&
    feathernotes &
    telegram-desktop &
    meteo-qt &
    exit 0
  else
    echo "StatusNotifierArea is not available, retrying in 2 seconds..."
    sleep 2
  fi

done

Context

Having lxqt-panel started outside of lxqt-session is not desirable, even if it works.

System Information
tsujan commented 1 year ago

There's a ~30-second~ 60-second blocking loop in the code for finding the tray if there are tray apps in the startup, but the code that checks the tray is excluded from Wayland. Therefore, 30 seconds should pass there.

The condition that excludes Wayland is here: https://github.com/lxqt/lxqt-session/blob/c630af9ae592d7a39882bd307b3feaab9fb75cd8/lxqt-session/src/lxqtmodman.cpp#L404-L405

I think it should be replaced by an appropriate condition under Wayland, but I don't know how.

Anyway, you could check this by removing tray apps from the startup.

EDIT: By "tray apps" I mean the startup items, for which "Wait for system tray" is checked:

tray

tsujan commented 1 year ago

Actually, I think using of a blocking loop for finding the tray was a bad idea with X11 too. A blocking loop may be needed for finding the X11 WM, but the tray might be able to be found by checking every 5 seconds until 30 seconds are passed.

palinek commented 1 year ago

There's a 30-second blocking loop in the code for finding the tray if there are tray apps in the startup,

Nope, 30 s is for waiting to start the WM. Starting/waiting for WM under wayland is not feasible. as with wayland the lxqt-session is started by compositor. Am I right?

tsujan commented 1 year ago

https://github.com/lxqt/lxqt-session/blob/c630af9ae592d7a39882bd307b3feaab9fb75cd8/lxqt-session/src/lxqtmodman.cpp#L122-L140

palinek commented 1 year ago

lxqt-session/lxqt-session/src/lxqtmodman.cpp Lines 122 to 140 in c630af9

Yes, this is the next 60 s wait for starting apps, which are requiring system tray in their .desktop files.

tsujan commented 1 year ago

I meant it — didn't pay attention to 60 (supposed it was 30).

palinek commented 1 year ago

But the 30sec delay, which @stefonarch is talking here is caused by the waiting for window manager, not by waiting for systemtray.

Please, what is the logic/architecture with wayland? Is the session compositor starting the lxqt-session or lxqt-session is starting the wayland session compositor?

tsujan commented 1 year ago

But the 30sec delay, which @stefonarch is talking here is caused by the waiting for window manager

WM is already excluded from Wayland: https://github.com/lxqt/lxqt-session/blob/c630af9ae592d7a39882bd307b3feaab9fb75cd8/lxqt-session/src/lxqtmodman.cpp#L87-L88

Is the session compositor starting the lxqt-session or lxqt-session is starting the wayland session compositor?

lxqt-session can't start the compositor because, if it tried, it would crash as aQApplication (there's no platform before the Wayland compositor-WM starts).

tsujan commented 1 year ago

Apart from this issue — which, IMO, can be easily fixed — we have the above-mentioned problem:

We need a more basic app to start a Wayland compositor-WM — a QCoreApplication or even only a purely c++-based app. Otherwise, we'll be condemned to starting lxqt-session with Wayland compositors, which isn't good because other apps that might be started by those compositors won't be under lxqt-session.

palinek commented 1 year ago

How about completely removing the native event filter logic -> https://github.com/lxqt/lxqt-session/tree/timers; and just check in timer based fashion.

stefonarch commented 1 year ago

Actually I didn't measure the ~30sec, probably it's 60s.

I checked shortly also another application with no tray icon which had the same delay. Looks like thunderbird is the exception.

stefonarch commented 1 year ago

How about completely removing the native event filter logic -> https://github.com/lxqt/lxqt-session/tree/timers; and just check in timer based fashion.

I tried this, under wayland no application in autostart starts anymore, maybe I'm missing something. Didn't check it under X11 though.

Atm I set the timer to 3sec and it's perfect - if there is a panel(status notifier area). If it's started later some apps remain invisible which is logical.

My guess is that the availability check under wayland has to be different as it's under X11; QSystemTrayIcon::isSystemTrayAvailable() looks like returning nothing if the panel is started by lxqt-session. Not sure if we can use checking fororg.kde.StatusNotifierWatcher instead.

tsujan commented 1 year ago

My guess is that the availability check under wayland has to be different as it's under X11;

QSystemTrayIcon::isSystemTrayAvailable() works fine everywhere. FeatherNotes uses it by waiting 20 sec for the tray, checking its existence every 5s.

stefonarch commented 1 year ago

The simple question is: why do applications finish in the loop waiting for the systray if the panel is started by lxqt-session and the systray is present? The same is true for waybar.

tsujan commented 1 year ago

A lightweight app like FeatherNotes may be started before the tray is available; hence the loop.

In November, Plasma-Wayland had a problem: its tray started too late after a cold boot, so that FeatherNotes couldn't always find it after 20 seconds. I don't know if the problem is fixed, but a 30 or 60-second loop is reasonable.

Here, the problem is just that it's blocking, and the solution is a non-blocking loop.

stefonarch commented 1 year ago

Here, the problem is just that it's blocking, and the solution is a non-blocking loop.

But it shoulḍ block if no tray is found, no? Here it blocks without reason.

tsujan commented 1 year ago

But it shoulḍ block if no tray is found, no?

It can delay starting of tray apps until the systray is found but shouldn't block everything. The current code blocks everything because of tray.

Here it blocks without reason.

The reason is that there's no systray at the moment lxqt-session is started. The systray may be available a few milliseconds later, but the code waits 60 seconds under Wayland because the following condition is never reached there: https://github.com/lxqt/lxqt-session/blob/c630af9ae592d7a39882bd307b3feaab9fb75cd8/lxqt-session/src/lxqtmodman.cpp#L419

The reason it isn't reached is that this condition above it is always satisfied under Wayland: https://github.com/lxqt/lxqt-session/blob/c630af9ae592d7a39882bd307b3feaab9fb75cd8/lxqt-session/src/lxqtmodman.cpp#L404-L405

stefonarch commented 1 year ago

Thanks, now I see why it works fine if started by the compositor.

We need a more basic app to start a Wayland compositor-WM — a QCoreApplication or even only a purely c++-based app. Otherwise, we'll be condemned to starting lxqt-session with Wayland compositors, which isn't good because other apps that might be started by those compositors won't be under lxqt-session.

I wonder if such an app can do what no script can do afaik. Played around with $WAYLAND_DISPLAY /usr/bin/lxqt-session and similar things. The only apps that the compositor would eventually start are those by shortcut - so once lxqt-globalkeysd is wayland-ready there shouldn't be such processes.

tsujan commented 1 year ago

Unlike X11, Wayland can never be running without compositing. This is the only thing I like about Wayland ;)

stefonarch commented 1 year ago

The wl_event_queue_func_t event is the equivalent of the xcb_generic_event_t event in XCB and can represent a variety of events, such as touch events, keyboard events, and pointer events.

So it would need some wayland code to do a different check?

palinek commented 1 year ago

How about completely removing the native event filter logic -> https://github.com/lxqt/lxqt-session/tree/timers; and just check in timer based fashion.

I tried this, under wayland no application in autostart starts anymore, maybe I'm missing something.

I debugged a bit in VM and made some fixes into that commit. @stefonarch can you, please, give it a try again?

stefonarch commented 1 year ago

Under wayland tray apps do never start (except lxqt-notificationd which was never affected for some reason), waited some minutes. Under X11 session is crashing after 2 sec here:


Program terminated with signal SIGSEGV, Segmentation fault.
#0  std::__atomic_base<int>::load (__m=std::memory_order_relaxed, this=0x21)
    at /usr/include/c++/12.2.0/bits/atomic_base.h:488
488     /usr/include/c++/12.2.0/bits/atomic_base.h: File o directory non esistente.

[Current thread is 1 (Thread 0x7fed044038c0 (LWP 653176))]
(gdb) where
#0  std::__atomic_base<int>::load(std::memory_order) const
    (__m=std::memory_order_relaxed, this=0x21) at /usr/include/c++/12.2.0/bits/atomic_base.h:488
#1  QAtomicOps<int>::loadRelaxed<int>(std::atomic<int> const&)
    (_q_value=<error reading variable: Cannot access memory at address 0x21>)
    at /usr/include/qt/QtCore/qatomic_cxx11.h:239
#2  0x00007fed06a82bd8 in QBasicAtomicInteger<int>::loadRelaxed() const (this=0x21)
    at /usr/include/qt/QtCore/qbasicatomic.h:107
#3  0x00007fed06a8df18 in QtPrivate::RefCount::ref() (this=0x21)
    at /usr/include/qt/QtCore/qrefcount.h:55
#4  0x00007fed06a8ec45 in QString::QString(QString const&) (this=0x7fff33858528, other=...)
    at /usr/include/qt/QtCore/qstring.h:1094
#5  0x00007fed06a895e5 in XdgDesktopFile::fileName() const (this=0x55f10e5cacf0)
    at /home/stef/git/lxqt/libqtxdg/src/qtxdg/xdgdesktopfile.cpp:959
#6  0x000055f10e0d9cba in operator()() const (__closure=0x55f10e5ef730)
    at /home/stef/git/lxqt/lxqt-session/lxqt-session/src/lxqtmodman.cpp:129
#7  0x000055f10e0dcdc9 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, LXQtModuleManager::startAutostartApps()::<lambda()> >::call(struct {...} &, void **)                  
    (f=..., arg=0x7fff33858720) at /usr/include/qt/QtCore/qobjectdefs_impl.h:146
#8  0x000055f10e0dcd71 in QtPrivate::Functor<LXQtModuleManager::startAutostartApps()::<lambda()>, 0>::call<QtPrivate::List<>, void>(struct {...} &, void *, void **) (f=..., arg=0x7fff33858720)          
    at /usr/include/qt/QtCore/qobjectdefs_impl.h:256
#9  0x000055f10e0dccb6 in QtPrivate::QFunctorSlotObject<LXQtModuleManager::startAutostartApps()::<lambda()>, 0, QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase *, QObject *, void **, bool *) (which=1, this_=0x55f10e5ef720, r=0x55f10e59e650, a=0x7fff33858720, ret=0x0)                     
    at /usr/include/qt/QtCore/qobjectdefs_impl.h:443
#10 0x00007fed056be931 in  () at /usr/lib/libQt5Core.so.5
#11 0x00007fed056c0e8f in QTimer::timeout(QTimer::QPrivateSignal) () at /usr/lib/libQt5Core.so.5
#12 0x00007fed056b1a16 in QObject::event(QEvent*) () at /usr/lib/libQt5Core.so.5
#13 0x00007fed06378b5c in QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
    at /usr/lib/libQt5Widgets.so.5
#14 0x00007fed0568de08 in QCoreApplication::notifyInternal2(QObject*, QEvent*) ()
    at /usr/lib/libQt5Core.so.5
#15 0x00007fed056d8373 in QTimerInfoList::activateTimers() () at /usr/lib/libQt5Core.so.5
#16 0x00007fed056d89b2 in  () at /usr/lib/libQt5Core.so.5
#17 0x00007fed0611682b in g_main_context_dispatch () at /usr/lib/libglib-2.0.so.0
#18 0x00007fed0616dcc9 in  () at /usr/lib/libglib-2.0.so.0
#19 0x00007fed061150e2 in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0
#20 0x00007fed056d8b4f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)
    () at /usr/lib/libQt5Core.so.5
#21 0x00007fed056865ac in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) ()
    at /usr/lib/libQt5Core.so.5
#22 0x00007fed056910d9 in QCoreApplication::exec() () at /usr/lib/libQt5Core.so.5
#23 0x000055f10e0d822a in main(int, char**) (argc=1, argv=0x7fff33858da8)
    at /home/stef/git/lxqt/lxqt-session/lxqt-session/src/main.cpp:73
(gdb) 
tsujan commented 1 year ago

except lxqt-notificationd which was never affected for some reason

Because it isn't a "tray app" in the above mentioned sense (see the screenshot of https://github.com/lxqt/lxqt-session/issues/460#issuecomment-1410060248).

palinek commented 1 year ago

Under X11 session is crashing after 2 sec here:

Based on the backtrace, you were still using the "old" commit, not the fixed one 2c34159871e01292fa4b4026a37d5f6a43052294.

stefonarch commented 1 year ago

Ops, sorry you're right - pulled only master. It works perfectly both on X11 and wayland. Didn't test without tray presence though.

palinek commented 1 year ago

Didn't test without tray presence though.

W/o tray, lxqt-session will start the "need tray" autostart applications after 15s timeout anyway.