Cairo-Dock / cairo-dock-core

Core part of Cairo-Dock project.
http://glx-dock.org
GNU General Public License v3.0
186 stars 46 forks source link

Support for layer-shell wayland protocol to position dock on the screen #8

Closed dkondor closed 7 months ago

dkondor commented 4 years ago

layer-shell is a protocol for positioning docks and similar on the screen: https://github.com/swaywm/wlr-protocols/blob/master/unstable/wlr-layer-shell-unstable-v1.xml It is supported by wayland compositors based on wlroots (https://github.com/swaywm/wlroots), but not gnome-shell or similar more mainstream ones unfortunately.

This is a proof-of-concept implementation to position cairo-dock properly and optionally reserve screen space for it. I've added minimal extra code to make it work -- it might be possible to move these to Wayland-specific parts of the codebase, but that seemed too complicated at first :)

Dependency:

What works:

What does not work:

Tested on Ubuntu 18.04 with Wayfire (https://github.com/WayfireWM/wayfire).

dkondor commented 4 years ago

I've rearranged things and moved all Wayland and layer-shell specific code to the Wayland implementation from gldit. This required to add multiple functions to _GldiContainerManagerBackend, but I think this is cleaner this way.

fabounet03 commented 4 years ago

That's very interesting ! Are there any plans in the layer-shell to be able to place sub-docks and menus ? I feel like it's a big flaw in the dock usability.

I haven't followed Wayland for a long time, how are normal GTK menus placed correctly if it's not possible to specify where they pop up ?

Also, why doesn't the hiding work ? Is it because the dock's window doesn't go behind the other windows ?

As for the mouse leaving the dock, we rely on GTK to notify us, so I was expecting it to work :-/ Although we do set a shape on the window, so maybe that's the problem... Are shapes supported on Wayland ?

dkondor commented 4 years ago

Hi,

unfortunately, I don't know the answer to most of these questions :)

Are there any plans in the layer-shell to be able to place sub-docks and menus ?

I'm not a maintainer for layer-shell, so I don't know, but I'm not sure it belongs there.

I haven't followed Wayland for a long time, how are normal GTK menus placed correctly if it's not possible to specify where they pop up ?

As far as I know, this is handled by the xdg-shell protocol, using the xdg_positioner part: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/blob/master/stable/xdg-shell/xdg-shell.xml that allows to position relative to a parent, but I haven't tried to use it directly. I'm assuming GTK uses it under the hood to put menus and popups in the correct place. Maybe this cannot work for the subdocks, since they are specialized GTK windows? I might look into this if there could be an easy fix.

Also, why doesn't the hiding work ? Is it because the dock's window doesn't go behind the other windows ?

I think the main issue is that we don't know where the other windows are. Auto-hiding could work (meaning that the dock is hidden whenever the user is not interacting with it), but recalling it is tricky since we cannot track the cursor. But it should work with the "Hit a zone to recall the dock" option if that zone is created as a layer-shell surface as well. I will try to experiment with this.

As for the mouse leaving the dock, we rely on GTK to notify us, so I was expecting it to work :-/ Although we do set a shape on the window, so maybe that's the problem... Are shapes supported on Wayland ?

No idea :) It could be worth looking into which events are delivered to the dock.

fabounet03 commented 4 years ago

I see, it seems cursor handling is done via libinput in both X and Wayland. I guess it's probably the way to go, instead of relying on the graphical server to dispatch the events.

dkondor commented 4 years ago

According to GTK doc:

rect is relative to the top-left corner of rect_window

So, we need to translate in the container's frame:

      if (pContainer->bDirectionUp)
      {
          rect.y -= pContainer->iWindowPositionY;
          rect.x -= pContainer->iWindowPositionX;
      }
      else
      {
          rect.x -= pContainer->iWindowPositionY;
          rect.y -= pContainer->iWindowPositionX;
      }

iWindowPositionX and iWindowPositionY are always zero on Wayland :) but this should make things work on X

dkondor commented 4 years ago

Hi,

I've added multiple improvements. Mainly subdocks, menus and dialogs are placed properly now, imporving usability a lot :)

I've separated the Wayland-specific positioning code. Nevertheless, for subdocks and menus, the new code actually works both on Wayland and X11, so after more testing, both cases could use the same code (I've added the cmake option -DCAIRO_DOCK_USE_NEW_POSITIONING_ON_X11 to use the new positioning code even on X11). Unfortunately, for dialogs, I haven't yet found a solution that works on both backends, so there needs to be a separate treatment for the two cases.

I have not looked into hiding / showing the dock, but I don't think the layer-shell protocol has any specific support for this, so I think that is a separate issue. Wayfire has another extension that implements "hot corners", so that can be one option to make this work.

Let me know if there are any questions on the current code :)

fabounet03 commented 4 years ago

Thanks a lot ! That's a lot of commits to review, and I have a limited amount of spare time, so please forgive me if it takes some time.

dkondor commented 4 years ago

As for the mouse leaving the dock, we rely on GTK to notify us, so I was expecting it to work :-/ Although we do set a shape on the window, so maybe that's the problem... Are shapes supported on Wayland ?

I looked into this and it turns out the reason for this is that in multiple places, cairo-dock queries the pointer position and decides if it's inside a dock or not. Getting the mouse position does not work on Wayland if it is outside a window, so this logic does not work either.

I've added a fix that makes this depend only on the leave / enter events delivered by GTK. This seems to work in the cases I've been able to test so far. Of course, there could be edge cases, since there is quite a lot of logic related to the pointer position. Also, this adds one more place where there is explicit dependence on knowing the backend in the gldit code, which I don't like, but doing this "properly" would probably require moving a lot of pointer-related code and logic to the implementations.

dkondor commented 3 years ago

Hi, I thought to ping if there is a chance to get this merged :) I've rebased and updated based on latest master and cleaned up the commit history a bit. Also, I've been using this on X11 in the past months without regressions and have been testing occasionally on Wayfire. I'm planning to do so more and more as Wayfire + cairo-dock is becoming a usable combination. Let me know if there is something else I could provide.

fabounet03 commented 3 years ago

I definitely want to merge your work, it sounds pretty cool. I will try to play a bit with wayfire to see how it looks and feels.

dkondor commented 3 years ago

Hi, I've just noticed that KDE / KWin added support for the layer-shell protocol in their recent, 5.20 release (see here, here, and here). I haven't been able to test this though, but I'm hoping to try if I can figure out how to install a recent release :)

keithbowes commented 2 years ago

I thought to ping if there is a chance to get this merged

I don't know why they wouldn't merge it. This stuff is very useful for a modern *nix desktop. If someone uses a compositor that doesn't support anything useful (ahem, GNOME), surely it would just be ignored and would act like it currently does.

The latest entry on the website is about basic Wayland support. It seems like they'd be itching to accept PRs to take the support beyond basic.

dkondor commented 7 months ago

Closing in favor of #15