Open Windows on Specific Workspaces

πŸ“… January 25, 2024
“Is it possible to open a terminal on a specific workspace instead of the current one?”

Yes!

We can position a gnome-terminal anywhere on a desktop workspace using its geometry option, and we can go further by moving that window off-screen to a different workspace using wmctrl.

Here is how to achieve this magic.

Linux Workspaces

If you use a Linux GUI-based OS, such as Linux Mint, Ubuntu, Xubuntu, Ubuntu Cinnamon, or any of the others, then you already have workspaces available.

Expo view (CTRL + ALT + UP Arrow Key) in Linux Mint 21.2 showing the default four workspaces available.

We can easily add or remove workspaces at will and move windows to different workspaces via drag and drop, but what about moving them via bash scripting?

wmctrl

wmctrl allows use to control windows on workspaces. A few things we can do:

  • List all open windows across all workspaces and show where each window is located
  • List all available workspaces
  • Switch between workspaces
  • Move any window to another workspace
  • …and much, much more.

wmctrl allows us to perform more window tricks than can be covered here, so have a look at its man page.

But, wait! We need to install wmctrl before we can use it.

sudo apt install wmctrl

wmctrl Usage (A little bit)

To become familiar with what wmctrl can do, try these commands:

View the man page

man wmctrl

Show all available workspaces

wmctrl -d

Four workspaces are available in this default Linux Mint system.

Workspaces are numbered starting at 0 for the first (leftmost) workspace. The current workspace is indicated by an asterisk (*). In the example shown above, workspace 0 is the current workspace. Resolution of each workspace is also provided. The workspace number is important since that is how we tell wmctrl where to move a window. Negative workspace numbers are not allowed.

List all open windows

wmctrl -l

Each line is one open window. There are six windows open spread across four workspaces.

The second column of numbers (0, 0, 0, 1, 2, 3) is the workspace number telling us which workspace the window is on. The names in the last column are the window names. These names appear in the window title bars.

For example, Home is on workspace 0, while Calendar is open on workspace 3 (the rightmost workspace).

 

Expo view of the example command above. Even though Linux Mint displays them as “Workspace 1” and so on, wmctrl identifies them as 0, 1, 2, and 3.

Window Name

This is important! To identify a specific window that wmctrl can manipulate, we must use the window’s name found in its title bar. The man page refers to this as -r <WIN> where <WIN> is the name of the window.

“What if I have multiple windows with matching names?”

Then only the first matching name (found in the wmctrl -l listing) will be affected. For best results, ensure unique names for your gnome-terminal windows in your script.

Moving a Window

Suppose we have a terminal window named “Terminal” and we want to move it to the third workspace (workspace #2 according to wmctrl).

wmctrl -r Terminal -t 2

Handling Duplicate Window Names

When opening a terminal from a script, gnome-terminal is great because it allows us to customize window names when they are created. However, in Linux Mint 21.2, the gnome-terminal –title=mytitle does not seem to work. The terminal title insists upon naming itself something like username@hostname no matter what attempts to title the window might be. In this case, we can end up with multiple windows having the sane username@hostname window name, making it hard to distinguish among them for manipulation.

To solve this issue, wmctrl allows us to identify by window IDs.

There are five open windows, but the last three are open terminal windows with the same name.

“How can we access the second terminal by name when they are all named ty?”

We cannot, so wmctrl allows us to also identify a window by its window ID, which is the shown in the first column.

The second column has a hexadecimal id of 0x04a002db for the ty window we are interested in. To use this and change the window title to something more unique, we use the -i option and -N option with wmctrl.

wmctrl -ri 0x04a006a1 -N SunshineAndMoonbeams

If you have the terminal open at the time the command runs in another terminal, you will see it change to the new title SunshineAndMoonbeams immediately.

  • -r sets the window name
  • -i tells wmctrl to use the window ID, not the window name.
  • -N sets the new name for a window’s title bar (it’s name)

Open Windows on Specific Workspaces from a Script

With a little understanding of what wmctrl does, let’s write a script!

With gnome-terminal experiments in previous articles, we can open terminals that monitor Pi-Hole using PADD and remote systems with BpyTOP via SSH in separate terminal windows. These windows were opened at specified locations on the workspace from which the script was executed.

PADD and BpyTOP monitoring a remote Pi-Hole system. These terminals open and connect automatically in the same location at the far right of the desktop when the script executes. We can move the same terminals to any given workspace using wmctrl for better organization.

Let’s go a bit further with this experiment and not only open those windows at the same locations on a desktop, but on a different workspace too! This way, we can open all remote monitoring windows that we need on a dedicated workspace.

The original script looked like this:

#!/bin/bash

gnome-terminal --hide-menubar --geometry 80x24+1100+50 -- ssh 192.168.37.88 -t ~/padd/padd.sh
gnome-terminal --hide-menubar --geometry 80x24+1100+514 -- ssh 192.168.37.88 -t bpytop

Let’s use wmctrl to move these windows to the third workspace (2).

Modified Script

#!/bin/bash

gnome-terminal --hide-menubar --title=pihole-padd --geometry 80x24+2650+50 -- ssh 192.168.37.88 -t ~/padd/padd.sh
wmctrl -r pihole-padd -t 2

gnome-terminal --hide-menubar --title=pihole-bpytop --geometry 80x24+2650+514 -- ssh 192.168.37.88 -t bpytop
wmctrl -r pihole-bpytop -t 2

This is trickier than it looks because of some unexpected behaviors we run into, so here are a few points to explain what seems straightforward at first glance.

Point 1 – Custom Titles

gnome-terminal --hide-menubar --title=pihole-padd --geometry 80x24+2650+50 -- ssh 192.168.37.88 -t ~/padd/padd.sh
wmctrl -r pihole-padd -t 2

The windows are being identified by name, so we use the –title option with gnome terminal to provide a custom title for the new window. Terminal is the default window name in Ubuntu Cinnamon (another system on which this was tested), but something more custom helps avoid ambiguity.

–title=pihole-padd just means we are naming this terminal window as pihole-padd to help identify its purpose through the name, which is unique to this system.

Point 2 – Create and then Move

wmctrl -r pihole-padd -t 2

This command moves the newly-created window to the destination workspace 2 (the third from the left). We are not opening a terminal directly on another workspace. We are opening a new window on the current workspace and then moving it to another. This process happens so fast that it seems like we are opening a new window directly on a specified workspace.

If you provide an invalid workspace number or invalid name, then nothing will happen. The window stay on the current workspace.

Point 3 – Auto-Changing Title Bar Names

This makes a difference in behavior. For the pihole-padd terminal above, everything works as expected. The terminal window title bar will remain phole-padd as defined in the gnome-terminal command. So far, so good.

And then we have programs like BpyTOP.

No matter what title is assigned to gnome-terminal, BpyTOP always renames its terminal window to BpyTOP. And, surprisingly, I have found that I cannot move the window from the same script using the renamed BpyTOP. It would move as a separate command outside the script.

The solution is to still name the gnome-terminal window to something unique just like before, and then move the window immediately using this name before it gets renamed to BpyTOP.

gnome-terminal --hide-menubar --title=pihole-bpytop --geometry 80x24+2650+514 -- ssh 192.168.37.88 -t bpytop
wmctrl -r pihole-bpytop -t 2

The terminal is created with the unique name pihole-bpytop, and then wmctrl moves the window to workspace 2 using this name before BpyTOP changes the name. By the time BpyTOP initializes, the terminal window will already be moved to the destination workspace when BpyTOP takes control and modifies it. Kind of hackish, but it works.

Point 4 – No Need to Change Window Geometry

When a window is moved to another location, it will be placed at the same (x, y) coordinates as when opened. So, there is no need to modify the geometry of gnome-terminal. (This assumes all workspaces are of the same resolution.)

Auto-Switch Workspaces

As a bonus, we can modify the script to switch to workspace 2, wait a little, and then switch back to the first workspace as a convenience feature.

#!/bin/bash

gnome-terminal --hide-menubar --title=pihole-padd --geometry 80x24+2650+50 -- ssh 192.168.37.88 -t ~/padd/padd.sh
wmctrl -r pihole-padd -t 2

gnome-terminal --hide-menubar --title=pihole-bpytop --geometry 80x24+2650+514 -- ssh 192.168.37.88 -t bpytop
wmctrl -r pihole-bpytop -t 2

# Switch to workspace 2
wmctrl -s 2

# Wait five seconds
sleep 5

# Switch to workspace 0
wmctrl -s 0

 

The idea here is to monitor the initial connections of the remote systems (to manually check that everything connects and starts up okay). This is purely optional, but it looks cool to see the computer auto-switching workspaces like this!

Move all terminals to the Last Workspace

What if we have a different number of workspaces? What if workspace 2 does not exist? We can modify our script to get the last workspace number and store it in a variable to be used later. This way, we can open all terminals and place them out of the way onto the last (rightmost) workspace for better organization.

#!/bin/bash

# Get last workspace number
lastworkspace=$(wmctrl -d | tail -n 1 | cut -f1 -d' ')

gnome-terminal --hide-menubar --title=pihole-padd --geometry 80x24+2650+50 -- ssh 192.168.37.88 -t ~/padd/padd.sh
wmctrl -r pihole-padd -t $lastworkspace

gnome-terminal --hide-menubar --title=pihole-bpytop --geometry 80x24+2650+514 -- ssh 192.168.37.88 -t bpytop
wmctrl -r pihole-bpytop -t $lastworkspace

# Switch to last workspace
wmctrl -s $lastworkspace

# Wait
sleep 6

# Switch to workspace 0
wmctrl -s 0

Watching this in actions brings a smile to my face!

 

lastworkspace=$(wmctrl -d | tail -n 1 | cut -f1 -d' ')

The last line from wmctrl -l is the last workspace — whatever it might be. We just need to get the number found in the first column, which is the workspace number of the last workspace. Store this in a variable, and you are good to go.

Conclusion

There is much more that is possible, so experiment!

More windows can be opened, and we are not limited to terminals. The principles described here should apply to any initial configuration to help make it easier to monitor remote systems or simply set up to initial windows on a specific workspace.

Have fun!

, ,

  1. Leave a comment

Leave a comment