Skip to content
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

Workspaces, tabs, and multi-monitor support #8

Open
Stebalien opened this issue Jan 24, 2024 · 19 comments
Open

Workspaces, tabs, and multi-monitor support #8

Stebalien opened this issue Jan 24, 2024 · 19 comments

Comments

@Stebalien
Copy link
Contributor

EXWM currently supports "workspaces" by creating a new frame per workspace. Additionally, multiple monitors can be supported by assigning workspaces to monitors.

Unfortunately:

  1. Assignment of workspaces to monitors isn't automatic.
  2. With the introduction of the tab-bar, frame-based workspaces are mostly redundant.

So, my proposal is to:

  1. Remove or deprecate the current workspace feature.
  2. Associate floating windows with tabs, unless they're marked as sticky. We may have to advise tab-bar-select-tab, but I'm hoping that the window-configuration-change-hook is enough.
  3. Make the randr module automatically create/delete frames.

The tricky parts will be:

  1. Making this "just work", especially monitor configuration.
  2. Backwards compatibility. We can probably introduce some aliases for, e.g., exwm-workspace-next and friends, but we likely won't be able to replicate all features.

The upsides are:

  1. Better integration with Emacs packages by using the tab-bar.
  2. Visual indication of the current workspace (again, via the tab-bar).
  3. Automatic support for multiple monitors.
@Stebalien
Copy link
Contributor Author

I'm currently approximating this setup by only using workspaces for multiple monitors, and using tabs for everything else.

I have a bash script to automatically configure and list connected monitors:

#!/bin/bash
export DISPLAY="${1:-$DISPLAY}"

xrandr -display "$DISPLAY" -q | awk '
($2 == "connected"){
    on_screens[connected++]=$1
}

($2 == "disconnected"){
    off_screens[disconnected++]=$1
}

END {
    CMD="xrandr"
    for (i = 0; i < connected; i++) {
        screen=on_screens[i]
        CMD=CMD" --output "screen" --auto"
        if (PREV) {
            CMD=CMD" --above "PREV
        }
        PREV=screen
        print(screen)
    }
    for (i = 0; i < disconnected; i++) {
        screen=off_screens[i]
        CMD=CMD" --output "screen" --off"
    }
    system(CMD)
}
'

Then I invoke this from exwm-randr-screen-change-hook:

  (setq exwm-randr-workspace-monitor-plist nil)
  (hook! exwm-randr-screen-change setup-monitors
    (let* ((cmd (expand-file-name "bin/configure-monitors.sh" user-emacs-directory))
           (monitors (thread-last
                       cmd
                       shell-command-to-string
                       string-trim
                       string-lines))
           (mc (length monitors))
           (wc (exwm-workspace--count)))
      (setq exwm-randr-workspace-monitor-plist
            (thread-last monitors (-map-indexed #'list) (-flatten-n 1)))
      (while (> wc mc) (cl-decf wc) (exwm-workspace-delete wc))
      (while (< wc mc) (exwm-workspace-add wc) (cl-incf wc))))

(and I just treat all floating windows as sticky)

@minad
Copy link
Member

minad commented Jan 24, 2024

I like this proposal. I also use tabs instead of frame-based workspaces, because of the better support/integration. I think it is okay if there will be some workflow changes if we move to tabs from frame-based workspaces, but these changes will be worth it in the long term given the better integration and better automatic multi-monitor support.

Do you think deprecating the workspace feature is necessary or could we rebase it mostly on tabs, providing (deprecated) compatibility commands? Another thing to consider - iirc tabs have changed a little bit since Emacs 27. Hopefully we won't be affected if we don't rely to deeply on internals.

@Stebalien
Copy link
Contributor Author

Do you think deprecating the workspace feature is necessary or could we rebase it mostly on tabs, providing (deprecated) compatibility commands? Another thing to consider - iirc tabs have changed a little bit since Emacs 27. Hopefully we won't be affected if we don't rely to deeply on internals.

I'm not sure if we can get a 1:1 mapping.

  1. Workspaces can be moved between monitors, tabs would be dedicated to the specific monitor (frame). I prefer the tab approach, but it's different.
  2. I'm not sure if we can replicate all of the workspace options. Although we maybe able to get some of them to work (change hooks, switch hooks, etc.). And I guess we could create tabs based on exwm-workspace-number (if > 1)?

So yeah, we can probably rebase some of it on tabs.

@minad
Copy link
Member

minad commented Jan 24, 2024

I'm not sure if we can replicate all of the workspace options. Although we maybe able to get some of them to work (change hooks, switch hooks, etc.). And I guess we could create tabs based on exwm-workspace-number (if > 1)?

Thinking about this more, it may be better to not do this and rather rely on the raw tab-bar functionality. Otherwise we just recreate an artificial layer above tabs and I guess we don't want that in the long term.

So I'd go with your proposal of deprecating exwm-workspace-*. We can still offer a little bit of compatibility functionality in a few selected cases, but I would not aim to replicate hooks for example. We could create a new exwm-tab feature, where we bundle the new functionality.

@medranocalvo
Copy link
Contributor

Do you think deprecating the workspace feature is necessary or could we rebase it mostly on tabs, providing (deprecated) compatibility commands? Another thing to consider - iirc tabs have changed a little bit since Emacs 27. Hopefully we won't be affected if we don't rely to deeply on internals.

I'm not sure if we can get a 1:1 mapping.

1. Workspaces can be moved between monitors, tabs would be dedicated to the specific monitor (frame). I _prefer_ the tab approach, but it's different.

Tabs are window configurations, if I understand correctly. I don't see why they must be dedicated to a particular frame. It should be possible to "move" a tab to other frame. For example, I could imagine drag&dropping a tab between Emacs frames. (I'm not saying this is supported right now, but I think it's a feature that would be generally useful in Emacs, and wanted for EXWM, no matter whether we switch to tabs-are-workspaces.)

2. I'm not sure if we can replicate all of the workspace options. Although we maybe able to get some of them to work (change hooks, switch hooks, etc.). And I guess we could create tabs based on `exwm-workspace-number` (if > 1)?

A good exercise would be conceptually split exwm-workspace into the "physical" part, that is, making the frame adjust to the screen dimensions etc., and the logical part. The former we'd need in a frame-per-monitor situation, the latter could be replaced with tabs (maybe).

So yeah, we can probably rebase some of it on tabs.

@medranocalvo
Copy link
Contributor

EXWM currently supports "workspaces" by creating a new frame per workspace. Additionally, multiple monitors can be supported by assigning workspaces to monitors.

Unfortunately:

  1. Assignment of workspaces to monitors isn't automatic.

This is a long-time deficit of EXWM, but is not due to the use of frames as workspaces. For example, I would happily use XMonad's approach to workspaces and monitors (ch11ng/exwm#202 (comment)). I have some half-backed code for kind of substituting exwm-randr-workspace-monitor-plist with a function or something similiar, but can't find it at the moment.

To summarize: I don't like exwm-randr-workspace-monitor-plist, but it's not necessary and using frames as workspaces does not imply that method of assigning them to monitors.

  1. With the introduction of the tab-bar, frame-based workspaces are mostly redundant.

Hmm... I'd say that much of the functionality offered by exwm-workspace on top of Emacs frames (e.g., exwm-workspace-number, exwm-workspace-index-map, exwm-workspace--list, ...) can be implemented on top of the tab feature. I like to say that EXWM is Emacs extrapolated to an X11 window manager. In that sense, I could say that Emacs' tabs offer the workspace funcionality expected of an X11 window manager (I'm not sure as I have no experience with Emacs tabs). What I'm not sure about or, what I resist, is that this must mean that Emacs frames will no longer be extrapolated to an X11 window manager concept (or be limited to a single frame per monitor).

I must think more about this.

So, my proposal is to:

  1. Remove or deprecate the current workspace feature.

  2. Associate floating windows with tabs, unless they're marked as sticky. We may have to advise tab-bar-select-tab, but I'm hoping that the window-configuration-change-hook is enough.

I'd say that this something we want independent of how we offer workspace functionality.

  1. Make the randr module automatically create/delete frames.

Same here.

Additionally, I think we should liberate the monitors from static workspace assignment and make select-frame change the frame displayed at current monitor (this was XMonad's behaviour).

The tricky parts will be:

  1. Making this "just work", especially monitor configuration.

  2. Backwards compatibility. We can probably introduce some aliases for, e.g., exwm-workspace-next and friends, but we likely won't be able to replicate all features.

The upsides are:

  1. Better integration with Emacs packages by using the tab-bar.

I see better integration, using standard Emacs functionality and less EXWM-custom functionality desirable.

  1. Visual indication of the current workspace (again, via the tab-bar).

This is usually done with a pager in X11. We should watch how this impacts integration with desktop environments (think using EXWM within KDE).

  1. Automatic support for multiple monitors.

This together with more dynamic and intuitive (or configurable) assignment of workspaces to monitors.


Thank you for making this well thought-out proposal.

@minad
Copy link
Member

minad commented Jan 24, 2024

@medranocalvo

I like to say that EXWM is Emacs extrapolated to an X11 window manager. In that sense, I could say that Emacs' tabs offer the workspace funcionality expected of an X11 window manager (I'm not sure as I have no experience with Emacs tabs). What I'm not sure about or, what I resist, is that this must mean that Emacs frames will no longer be extrapolated to an X11 window manager concept (or be limited to a single frame per monitor).

But is the frame-based concept not just a means to achieve the goal of having different workspaces, in other words an implementation detail? Given that tabs enable us to have multiple window configurations side by side, we don't need frames anymore for this. On top the builtin Emacs tab bar (if visible) highlights the active tab and allows us to toggle with the mouse.

I use the tab bar to show me the active tabs and also as a global system status bar (next org agenda appointment, music player, display brightness, network status, battery status, date, etc., like xmobar or polybar).

@port19x
Copy link

port19x commented Jan 24, 2024

Just to chime in, I only use regular buffer switching commands on multi-monitor setups and only explicitly move X windows when I absolutely have to, as I do find it tedious.
A lot would be achieved if EXWM buffers would be shared between frames, making exwm-workspace-move-window avoidable that way

@medranocalvo
Copy link
Contributor

Just to chime in, I only use regular buffer switching commands on multi-monitor setups and only explicitly move X windows when I absolutely have to, as I do find it tedious. A lot would be achieved if EXWM buffers would be shared between frames, making exwm-workspace-move-window avoidable that way

What you desire is available by setting both exwm-layout-show-all-buffers and exwm-workspace-show-all-buffers to t. (Those two should default to t and be declared obsolete; I'll open a ticket when I find the time.) Once that's done, one can use switch-to-buffer regularly, with the caveat that we don't allow an exwm-mode buffer to be current in more than one window. (That's a limitation that should be lifted. Using tab-bar as proposed here solves it partially.)

@gdindi
Copy link

gdindi commented Jan 24, 2024

I use the tab bar to show me the active tabs and also as a global system status bar (next org agenda appointment, music player, display brightness, network status, battery status, date, etc., like xmobar or polybar).

Me too. And actually, I was wondering if using tabs as workspaces wouldn't clutter the tab bar. I currently use 5 workspaces with 2 or 3 tabs per work-space. Workspaces give me a first level of hierarchy and in each workspace I can have a second level of grouping.

I am afraid that using tabs as workspaces would imply loosing this organization.

I may not have understood the proposal, though.

In any case, THANK YOU VERY MUCH for the work you are doing for us EXWM users!

@minad
Copy link
Member

minad commented Jan 24, 2024

@gdindi

Me too. And actually, I was wondering if using tabs as workspaces wouldn't clutter the tab bar. I currently use 5 workspaces with 2 or 3 tabs per work-space. Workspaces give me a first level of hierarchy and in each workspace I can have a second level of grouping.

I am afraid that using tabs as workspaces would imply loosing this organization.

Emacs 28.1 supports tab groups which could be an adequate substitute if you need a second level. I haven't used tab groups myself yet, so I am not sure how well they work and if they are indeed a good match for your workflow. In case you haven't, maybe you could give them a try and provide feedback?

@gdindi
Copy link

gdindi commented Jan 24, 2024

Emacs 28.1 supports tab groups which could be an adequate substitute if you need a second level. I haven't used tab groups myself yet, so I am not sure how well they work and if they are indeed a good match for your workflow. In case you haven't, maybe you could give them a try and provide feedback?

Thanks for the idea. Tab groups allow to hide tabs not belonging to the current group. This allows to have only visible the tabs of the current group. However, switching tab by name still shows all the tabs of the frame. So the hierarchy group->tab is only a visibility one. I guess this is just a matter of personal taste and getting used to a different workflow. I’ll experiment a bit with that.

Another issue is the following: if only one frame is created by EXWM, what happens when an external monitor is connected? Currently, I have WS 0 sent to the external monitor and all the others to the main screen.

@Stebalien
Copy link
Contributor Author

Another issue is the following: if only one frame is created by EXWM, what happens when an external monitor is connected? Currently, I have WS 0 sent to the external monitor and all the others to the main screen.

The idea is to automatically create one frame per monitor.

@tazjin
Copy link

tazjin commented Jan 25, 2024

I pretty much do what you suggest in the OP in my config. I create & assign frames to monitors automatically, and call that function from my randr-invocations (details not relevant, but they're in the same file) when connecting/disconnecting screens. The only guaranteed thing about the order is that the first frame follows the primary monitor, which in my use-cases perfectly "just works".

Management of window groups within the frame of each monitor is done using tabs, and that seems to be a lot more reliable than using multiple frames per monitor in terms of focus issues (with the exception of a bizarre bug where fullscreening/unfullscreening e.g. a video in a browser window will somehow partially break input handling to that browser window until it is closed, should probably open a separate bug for that).

Minor issues notwithstanding I'd say that this suggestion would make EXWM behave a lot more "sanely", which might be a good thing!

@franburstall
Copy link

Can I plead for a compatibility layer here? I have only one monitor so the changes proposed solve problems I do not have or (in the case of visual indication of workspace) have already solved. OTOH, I use workspaces a lot to separate concerns.

@Stebalien
Copy link
Contributor Author

We will try our best. Or, at a minimum, we'll make sure there's a very easy migration path.

It should be possible to provide easy aliases for workspace switching, adding, removing, etc. The difficult parts are:

  1. Hooks.
  2. Assigning workspaces to monitors (nonsensical).

@franburstall
Copy link

We will try our best. Or, at a minimum, we'll make sure there's a very easy migration path.

OK. Good luck with this!

@Stebalien
Copy link
Contributor Author

Ok, Emacs 30 (to be released) just landed a tab-bar-tab-post-select-functions hook. So, on that version at least, we'll be able to replicate the workspace switch hook.

@mirdono
Copy link

mirdono commented Apr 6, 2024

Tabs are window configurations, if I understand correctly. I don't see why they must be dedicated to a particular frame. It should be possible to "move" a tab to other frame. For example, I could imagine drag&dropping a tab between Emacs frames. (I'm not saying this is supported right now, but I think it's a feature that would be generally useful in Emacs, and wanted for EXWM, no matter whether we switch to tabs-are-workspaces.)

The tab-bar-move-tab-to-frame function provides this functionality.

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

No branches or pull requests

8 participants