7

I rely on wmctrl a lot to switch between windows, basically to avoid typing alt-tab many times. I've always used one workspace but now I want to begin using more than one.

I was wondering if it is possible to modify the context of wmctrl so that when I type wmctrl -l, only windows from the current workspace are shown, instead of all windows from all workspaces.

For example, assuming I have a Firefox window opened in workspace 1. I have a keyboard shortcut on ctrl+alt+f that executes wmctrl -a firefox, which switches to Firefox. If I open a new Firefox window on workspace 2 and type ctrl+alt+f, it will switch to the window at workspace 1, which is not what I want.

Any suggestions/ideas on how to solve this?

EDIT: I'm using compiz (Unity)

2 Answers 2

5

If you're using Compiz (run wmctrl -m if not sure), wmctrl only sees 1 desktop (2nd field of wmctrl -l, ie 0) but you can use the geometry (-G) option to know what window is on what virtual desktop. All windows in your current desktop will have an x-position between 0 and your screen's width. Same for the y-position between 0 and your screen's height. So you can use something like that

#!/bin/bash

SCREEN_W=$(xwininfo -root | sed -n 's/^  Width: \(.*\)$/\1/p')
SCREEN_H=$(xwininfo -root | sed -n 's/^  Height: \(.*\)$/\1/p')

NAME='Navigator.Firefox'

wmctrl -xlG | awk -v W="$SCREEN_W" -v H="$SCREEN_H" -v NAME="$NAME" '$7==NAME && $3>=0 && $3<W && $4>=0 && $4<H {print $1}' | while read WINS; do wmctrl -ia "$WINS"; done

exit 0

You can hardcode your screen's width and height if you will, and NAME if you want a one-liner. Im not sure how you want to handle multiple windows matching NAME. That will focus them all.

For metacity, desktop number of windows can be found using wmctrl -l and grepping the 2nd field.

10
  • 1
    The only issue is that, besides my laptop's screen (14"), I use a monitor at the lab and another at home, the three of them having distinct resolutions, so the x-position varies depending on which display I'm using. I guess I could define ranges, mmm. Will try it. I wonder if there are alternatives to make wmctlr know the desktop number on compiz
    – ivotron
    Commented Oct 1, 2012 at 20:06
  • That's what the 2 first lines are for. They get your screen resolution (SCREEN_W: width and SCREEN_H: height) and pass them in awk.. You can either use the code abore for all 3 or use 3 different commands for each of them, ae (1440x900): wmctrl -xlG | awk '$7=="Navigator.Firefox" && $3>=0 && $3<1440 && $4>=0 && $4<900 {print $1}' | while read WIN; do wmctrl -ia "$WIN"; done
    – user55822
    Commented Oct 1, 2012 at 20:27
  • i see, cool! that solves my issue then. Thanks! Will work on it and comment back on how it went
    – ivotron
    Commented Oct 1, 2012 at 22:34
  • @ivotron how did it go? Commented Oct 6, 2016 at 20:47
  • @user55822 How could one move an application from one workspace to another with wmctrl (and compiz)? Could you give an example one-liner and/or script, please please please? Commented Oct 6, 2016 at 20:49
0

I have the answer for 2022, it's quite powerful one based on The newest wmctrl logic, welp it mimics autohotkey on windows

So first we need to get the active desktop / workspace

wmctrl -d | grep "*" | awk --field-separator="  "  '{print $1}'

After that, you can piece it to get the list ONLY Window on That desktop

D=$(wmctrl -d | grep "*" | awk --field-separator="  "  '{print $1}')
WINNAME="GVIM"
# Or you can get the full name as hex, more accurate for same window name
WIN=$(wmctrl -l | grep "  $DESKTOP " | grep -i $WIN | awk '{print $1}')
# WIN will be filled with 0xYYYY ID in hex or use simple winname
IN=$(wmctrl -l | grep "  $DESKTOP " | grep -i gvim | awk --field-separator="$(hostname) " '{print $2}')
# Get the number of window contain it's name
STATUS=$(wmctrl -l | grep "  $DESKTOP " | grep -i $WINNAME | wc -l)

Then you can check it using if like this (For winname)

if [ $STATUS -gt 0 ]
then
   activeWindow=$(xprop -id $(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) WM_NAME | cut -d '"' -f 2)      
   # zenity --notification --text="$activeWindow"
   if [[ $activeWindow =~ "$WINNAME" ]]
   then
       wmctrl -r "$WIN" -b toggle,hidden
   else
       wmctrl -a "$WIN"
   fi
else
   /usr/bin/gvim # if the app hasn't started yet, start it
fi

OR

For Hex ID

# ... output omitted
   if [[ $activeWindow =~ "$WINNAME" ]]
   then
       wmctrl -i -r "$WIN" -b toggle,hidden
   else
       wmctrl -i -a "$WIN"
   fi
# ... output omitted, see source before

So if you piece it all together (for using window name, this is not bullet prof as if has same name between workspace, well, it will follow the other workspace)

#!/bin/bash

DESKTOP=$(wmctrl -d | grep "*" | awk --field-separator="  "  '{print $1}')
STATUS=$(wmctrl -l | grep "  $DESKTOP " | grep -i gvim | wc -l)
WIN=$(wmctrl -l | grep "  $DESKTOP " | grep -i gvim | awk --field-separator="$(hostname) " '{print $4}')
# zenity --notification --text="$STATUS $DESKTOP $WIN"

if [ $STATUS -gt 0 ]
then
   activeWindow=$(xprop -id $(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) WM_NAME | cut -d '"' -f 2)      
   # zenity --notification --text="$activeWindow"
   if [[ $activeWindow =~ "GVIM" ]]
   then
       wmctrl -r $WIN -b toggle,hidden
   else
       wmctrl -a $WIN
   fi
else
   /usr/bin/gvim
fi

OR BULLET PROF using HEX ID

#!/bin/bash

DESKTOP=$(wmctrl -d | grep "*" | awk --field-separator="  "  '{print $1}')
STATUS=$(wmctrl -l | grep "  $DESKTOP " | grep -i gvim | wc -l)
WIN=$(wmctrl -l | grep "  $DESKTOP " | grep -i gvim | awk '{print $1}')
#zenity --notification --text="$WIN"
if [ $STATUS -gt 0 ]
then
   activeWindow=$(xprop -id $(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) WM_NAME | cut -d '"' -f 2)      
   #zenity --notification --text="$STATUS $DESKTOP \"$WIN\" $activeWindow"
   if [[ $activeWindow =~ "GVIM" ]]
   then
       wmctrl -i -r "$WIN" -b toggle,hidden
   else
       wmctrl -i -a "$WIN"
   fi
else
   /usr/bin/gvim
fi

-i in man wmctrl means :

-i Interpret window arguments () as a numeric value rather than a string name for the window. If the numeric value starts with the prefix '0x' it is assumed to be a hexadecimal number

You can get window toggle like AHK Script on Windows, but more powerful than it should.

This script tested on XFCE, and works, either Xubuntu 22.04 or Fedora 36.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .