New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wayland taskbar support v2 #2043
base: master
Are you sure you want to change the base?
Conversation
Nice! Taskbar under kwin_wayland works again I see.
It does here :) (had always worked on this branch). |
Something has gone wrong I think, I recompiled the changes this afternoon and taskbar is gone again. |
Taskbar is back here now I see, and crash on clicking showdesktop is avoided too. |
Just noticed a different behavior here compared to wlroots and X11 (any WM): the taskbar buttons only activates windows, but don't toggle minimize/restore. |
@@ -0,0 +1,13 @@ | |||
[Desktop Entry] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get always 2 panels now after login as there is also the lxqt-panel.desktop
from regular installation in autostart - in some way it ends up also in /etc/xdg/autostart/
with the _wayland name, didn't have time to investigate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's here, it installs any *.desktop
file:
lxqt-panel/autostart/CMakeLists.txt
Line 1 in 2ad883e
file(GLOB DESKTOP_FILES_IN *.desktop.in) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO panel_wayland.conf.in
could be panel_kwin.conf.in
and be inside the plasma backend folder, as it's not generic for wayland but compositor-specific.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better to install a single .desktop
file (plus another or symlink inside autostart folder)
This is because KWin might get confused about which file the panel belongs and it needs to check the one with absolute path and KDE specific entries.
In the meantime we discuss this issue, I will solve the double install problem
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my tests it looks that Another remaining issue is the "Maximize" item in menu which is always greyed out. |
Is this not implemented yet, or, the implementation gives some problems? Edit:
From the code it seems to me that you have problems about how. With layer-shell, we can set the margin to a negative value. For a bottom panel, setting the bottom margin to However, the issue of how to show the panel becomes a problem. With wayfire, we can use wayfire-shell or wayfire-desktop-shell, both of which provide an equivalent of screen-edge protocol. But in general, we can partially hide the panel, instead of resizing the panel. For example, set the bottom margin to |
Are negative margin value allowed by layer shell? |
Well... It's not specifically, disallowed. On wayfire, we simply use negative margins. I've not tested on other compositors, though. |
Negative layershell margins may end up on other outputs or don't receive frame / configure events anymore because the surface is not actually visible (which revealed a bug in the GTK layershell wrapper in the past), depending on the compositor. (Although I'd actually categorize the shows-up-on-other-output as a compositor bug). AFAIR a discussion in the ext-layershell protocol MR concluded to not allow negative margins at all (but memory is a bit fuzzy there). Another option that should always work is hiding the panel and replacing it with a transparent hitbox without exclusive zone. On mouse movement on the hitbox that one is hidden and the panel is shown again. This implements it in Python with GTK but something similar should be possible with Qt as well.#!/usr/bin/env python3
from functools import partial
import gi
gi.require_version("GLib", "2.0")
gi.require_version("Gdk", "3.0")
gi.require_version("Gtk", "3.0")
gi.require_version('GtkLayerShell', '0.1')
from gi.repository import GLib, Gdk, Gtk, GtkLayerShell
class Context:
def __init__(self):
self.panel = Panel(self, auto_hide_seconds=5)
self.dummy = HitBox(self)
self.show_panel()
def log(self, msg):
print(f"[{self.__class__.__name__}] {msg}")
def hide_panel(self):
self.log("Hiding panel")
self.dummy.show()
self.panel.hide()
def show_panel(self):
self.log("Showing panel")
self.dummy.hide()
self.panel.show()
class Base(Gtk.Window):
def __init__(self, context):
super().__init__()
self.context = context
self.connect('motion-notify-event', self.on_mouse_move)
self.set_events(Gdk.EventMask.POINTER_MOTION_MASK)
self.set_size_request(-1, 30)
GtkLayerShell.init_for_window(self)
GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.BOTTOM, True)
GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.LEFT, True)
GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.RIGHT, True)
self.log = partial(context.__class__.log, self)
self.log("init done")
def on_mouse_move(self, src, event):
pass
def add_style(self, css):
if isinstance(css, str):
css = css.encode('utf-8')
css_provider = Gtk.CssProvider()
css_provider.load_from_data(css)
style_context = Gtk.StyleContext()
style_context.add_provider_for_screen(
Gdk.Screen.get_default(),
css_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
)
class Panel(Base):
def __init__(self, *args, auto_hide_seconds=3, **kwargs):
super().__init__(*args, **kwargs)
GtkLayerShell.set_layer(self, GtkLayerShell.Layer.BOTTOM)
GtkLayerShell.auto_exclusive_zone_enable(self)
self.auto_hide_seconds = auto_hide_seconds
self.timer = None
def timer_rearm(self):
if self.timer:
GLib.source_remove(self.timer)
self.timer = GLib.timeout_add_seconds(
self.auto_hide_seconds, self.on_timer,
priority=GLib.PRIORITY_LOW
)
def on_timer(self):
self.log("Timer hit")
self.context.hide_panel()
self.timer = None
return False
def show(self):
super().show()
self.timer_rearm()
def on_mouse_move(self, src, event):
self.timer_rearm()
class HitBox(Base):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
#self.set_size_request(-1, 2)
GtkLayerShell.set_layer(self, GtkLayerShell.Layer.TOP)
self.set_name('hitbox')
#self.add_style('#hitbox { background-color: transparent; }')
self.add_style('#hitbox { background-color: rgba(255, 128, 128, 0.5); }')
def on_mouse_move(self, src, event):
self.context.show_panel()
if __name__ == '__main__':
context = Context()
Gtk.main() The variant also has the benefit that rather than just having a transparent non-exclusive hitbox, one could also anchor the replacement surface to e.g. the bottom-left edge and show a small button instead which - when triggered - hides the replacement surface and restores the panel one. That replacement surface would then be non-exclusive, only be the width of the button and using the top layer so its always visible on top of usual windows. |
I didn't notice that as I don't really use it, but it's on all compositors the same, getting triggered at panel height and not screen border. |
That could also be solved by using the transparent replacement surface, either via the button-only variant or by defining a 1px or 2px height of the surface (added a commented out call to the GTK example above). |
Under X11, the panel is moved out of the screen appropriately, such that only 4 pixels (PANEL_HIDE_SIZE) of its height or width remain visible, depending on whether it's horizontal or vertical. Then its opacity is made zero. Those invisible 4 pixels serve to show the panel on mouse-over. Since the panel is never positioned between screens, this method works fine. Of course, there are other details/options, like animation and auto-hiding on overlapping windows. |
Btw what about lxqt/lxqt#2531 (comment) ? |
I'm ok for extracting layer shell code and make a new PR |
This is an abstract interface to operate windows and workspaces
- Move WindowProperty enum to lxqttaskbartypes.h
This model will manage the tasks shown
Also use it to get window icon
- Clarify desktop index range
TODO: this will disable changing desktop names
NOTE: works only on KWin - Choose backend at runtime - Windows filter logic is re-evaluated on window property changes
TODO: is this correct? Seems to call wl_proxy_destroy underneath
…TODO TODO: is this correct approach?
bd3ebe6
to
5269af5
Compare
NOTE: absolute path is needed inside .desktop file for this to work use CMake to get it. - Prevent double dekstop file installed in autostart
- reloadWindows() force removal and readding of windows This fixes changing windows grouping settings and adding taskbar plugin AFTER panel is started. Both situations resulted in empty taskbar previously
TODO: show error message when not supported
- Add NoDisplay=true to .desktop file
5269af5
to
414e7d0
Compare
Awesome that the code works for you but in this case the inspiration seems was rather strong and seems to include copied code from Plasma in multiple files as the commented out lines still references the original class and the general structure of the code (for example The original license headers are the two SPDX- lines at the top of the file, e.g. SPDX-License-Identifier: LGPL-2.1-only. Since lxqt is LGPL v2.1, you can specifically choose to re-use the code from KDE under the LGPL v2.1. |
In that case, the original codes should be referenced by comments like "Adapted from...". |
@Sodivad Hi, I've updated the license headers. Is it ok like that? |
Depends on #2041 (WM abstraction)
Replaces #2031
This is an experimental implementation on taskbar, desktopswitch and showdesktop functionality for KWin Wayland compositor.
It uses following protocols:
org-kde-plasma-virtual-desktop
plasma-window-management
(Taken from plasma-wayland-protocols repository)
Code is inspired by libtaskmanager/waylandtasksmodel.cpp
Ideally the Wayland backend should have sub-backends targeting specific compositors when no standard protocol is available.
It also uses layer shell protocol to place panel on screen edge.
NOTE: panel auto-hide is not working yet