paperwm / PaperWM

Tiled scrollable window management for Gnome Shell
GNU General Public License v3.0
2.75k stars 122 forks source link

Add option to keep tob bar on primary monitor #143

Closed Pajn closed 4 years ago

Pajn commented 4 years ago

When the top bar changes monitor, the whole DE freezes for a second while it changing everything around and I also get a graphic glitch with the Ubuntu side panel which expands to fill the space where the top bar previously was. I think that, especially the performance problem, will be hard or impossible to resolve and it would be better to keep the top bar on the primary monitor just as Gnome default.

As a quick hack I tried to modify the code that sets the top bar monitor to:

let topBarMonitor = Main.layoutManager.monitors[2];
TopBar.setMonitor(topBarMonitor);

and while the transition still isn't super smooth, it is at least better. And the Ubuntu side panel issue is gone.

This simple hack is not without bugs though so a bit better implementation would be needed.

Bugs I have noticed so far with the hack:

  1. If the workspace on the active monitor has "hide top bar", the top bar is hidden even though it is now on another monitor.
  2. The name from the workspace on the active monitor is stacked above the name of the workspace on the primary monitor.
  3. The overview is always on the primary monitor.

1 and 2 I think I could solve, but number 3 is harder. Would you be interested in a feature like this, and if so, is there any gotchas I should think about when implementing it?

hedning commented 4 years ago

Yeah, moving the top bar around is really too much trouble. It also looks really ugly when using different scaling on different monitors. IIRC we did it as a quick hack to fix workspaces having a big empty bar on top.

I mocked up a quick prototype a few days ago, the missing bit here is some sort of pseudo top bar which displays the workspace names when using the workspace carousel.

diff --git a/tiling.js b/tiling.js
index effca16ec..18e775a60 100644
--- a/tiling.js
+++ b/tiling.js
@@ -918,6 +918,8 @@ class Space extends Array {
     }

     updateShowTopBar() {
+        if (!this.settings)
+            return;
         let showTopBar = prefs.default_show_top_bar;
         let userValue = this.settings.get_user_value('show-top-bar');
         if (userValue) {
@@ -976,12 +978,19 @@ box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, .7);
         this.label.text = name;
         this.name = name;

-        if (this.workspace === workspaceManager.get_active_workspace()) {
+        if (this.workspace === workspaceManager.get_active_workspace() &&
+            this.monitor === Main.layoutManager.primaryMonitor) {
             TopBar.setWorkspaceName(this.name);
         }
     }

     setMonitor(monitor, animate) {
+        if (Main.layoutManager.primaryMonitor !== monitor) {
+            this.showTopBar = false;
+        } else {
+            this.updateShowTopBar();
+        }
+
         let cloneContainer = this.cloneContainer;
         let background = this.background;
         let clip = this.clip;
@@ -1437,7 +1446,7 @@ class Spaces extends Map {

         this.animateToSpace(toSpace, fromSpace);

-        TopBar.setMonitor(toSpace.monitor);
+        // TopBar.setMonitor(toSpace.monitor);
         toSpace.monitor.clickOverlay.deactivate();

         let [x, y, _mods] = global.get_pointer();
diff --git a/topbar.js b/topbar.js
index 4d022a562..9b742b258 100644
--- a/topbar.js
+++ b/topbar.js
@@ -483,9 +483,10 @@ function disable() {
 }

 function show() {
+    let primary = Tiling.spaces && Tiling.spaces.monitors.get(Main.layoutManager.primaryMonitor);
     if (!Main.overview.visible &&
         !Tiling.inPreview &&
-        !(Tiling.spaces && Tiling.spaces.selectedSpace.showTopBar)) {
+        !(primary && primary.showTopBar)) {
         hide();
         return;
     }
@@ -518,7 +519,7 @@ function hide() {
    let workspaceIndex = 0
 */
 function updateWorkspaceIndicator (index) {
-    let space = Tiling.spaces.spaceOf(workspaceManager.get_workspace_by_index(index));
+    let space = Tiling.spaces.monitors.get(Main.layoutManager.primaryMonitor);
     setWorkspaceName(space.name);
 };

@@ -527,6 +528,7 @@ function setWorkspaceName (name) {
 }

 function setMonitor(monitor) {
+    return;
     let panelBox = Main.layoutManager.panelBox;
     panelBox.set_position(monitor.x, monitor.y);
     panelBox.width = monitor.width;
Pajn commented 4 years ago

I've tried running with static top bar for a few days an noted a much bigger problem. Often when I move the mouse from one monitor to the next, the old monitor becomes impossible to click and scroll in. I would believe that click-overlay is there but that's just a guess. The behaviour is quite strange, as the problem only seems to be going in one direction. Moving from my right most monitor to the center monitor "breaks" the right most monitor, but I can then move to my left most monitor without problem, however after doing that, the center monitor is also "broken". And sometime the problem is in the other direction, so I can move to the right but not to the left. Switching workspace fixes all monitors again.

I have tried following the code but can't see anything that shouldn't be run by doing this. My current hunch though is that a layout of the shell fixes is, which is why moving the top bar works (as that causes a layout when things expand/shrinks). Is there a related signal, controlling the click overlay, that I have missed or is there maybe a deeper problem?

hedning commented 4 years ago

Yeah, that sounds like a variant of #111 (if you're using x11 at least).

Pajn commented 4 years ago

I'm using Wayland so it's not that one. The reason I'm using Wayland is that Xorg won't start on my machine so unfortunately I can't test it, however if I can get get it running I will.

hedning commented 4 years ago

Ok, made a branch to test this out: topbar-only-primary (e6c6200057b61aedcdf942c1945ba1697323f426).

The main issue is workspace names not being visible when using eg. super+above_tab. The simplest solution might be a dummy top bar that's activated when navigating workspaces (pushing the windows a bit down is also an option, like we do with fullscreen windows).

jtagcat commented 4 years ago

e6c6200 is working as intended (and i guess actually-support-only-on-primary is for adding an on/off switch for that).

jtagcat commented 4 years ago

Hold on, @hedning image there's a small blue border on the top and right side of the 2nd display, only happens when fullscreening on the same display, moving focus to an another display and back fixes it

hedning commented 4 years ago

Ok, added in ecd355115ce0dfba65f793123778d7ad660c52bb. If you find any problems feel free to open new issues :)

jtagcat commented 4 years ago

@hedning the blue corner thing is sometimes still happening - now instead of being on top and left, it's always bottom and right

hedning commented 4 years ago

Hmm, right managed to forget that one. I'm unable to reproduce with firefox nightly in a nested wayland shell (3.34.4 specifically). The blue sure looks like the active window highlight. If the window is unresponsive to button-presses then you're seeing a clone of window, which for some reason have been positioned incorrectly. I wouldn't be surprised if it was application specific (eg. firefox wayland reports incorrect window coordinates right after being maxmized).

How do you reproduce it? Eg. is it only a specific application, is the window XWayland or native, do you use any scaling etc.?

jtagcat commented 4 years ago

No scaling, it doesn't always happen, often it happens with something else than ff, like vscode, joplin, slack, thunderbird (most of them go towards the web app side). Only happens when a single app is full-screened, you can switch between apps, but one app will stay with the border indefinitely (haven't tried to purposely get rid of it).

hedning commented 4 years ago

Right, assuming you're in wayland, and not using firefox-wayland, it could be XWayland specific (the electron stuff is all x11 for the time being). I only tested with firefox running as a wayland window, will test x11 apps and see.

jtagcat commented 4 years ago

Here's Slack. Screenshot from 2020-03-10 10-46-35 Screenshot from 2020-03-10 10-47-07 It's like it's cut off, but I'd also note the small black bar behind the top bar.

hedning commented 4 years ago

Right, that looks a bad clip on the window actor (we clip the windows so they won't stick out of their monitor).

Not sure about the black bar, though it does look like the width matches with clip on the bottom.

You can try this in looking glass when you encounter the bug, to check if that's actually the case (Alt-F2 lg):

global.display.focus_window.get_compositor_private().remove_clip()

Does it only happen when you have more than one monitor? On all monitors? Only on focused windows?

jtagcat commented 4 years ago

Does it only happen when you have more than one monitor? On all monitors? Only on focused windows?

any

lg output while problematic window active: r(0) = undefined

hedning commented 4 years ago

Ok, so running the the code in lg (while having the problematic window in focus) didn't fix the problem on the active window? (the undefined output is expected as the method doesn't return anything).

jtagcat commented 4 years ago

Ok, so running the the code in lg (while having the problematic window in focus) didn't fix the problem on the active window? (the undefined output is expected as the method doesn't return anything).

didn't fix, the 'eating blue sides' remained