How to get a list of active windows when using wayland

gnomewayland

I recently installed Ubuntu 17.10 which uses Wayland instead of (or in some sort of combination?) X11. Before I could use xprop -root|grep ^_NET_CLIENT_LIST or wmctrl (wmctrl -lpGxu) to get a list of all active windows. This doesn't work any more with all gnome applications like the terminal and some others like nautlius. Is there any way to list those?

Best Answer

Yeah, on Wayland, sadly Xorg utilities like wmctrl and xdotool do not function. Instead we can talk to the window manager.

For Gnome, we can run gdbus to send a DBUS message to execute some GJS (JavaScript bindings for the GNOME C APIs).

To get a list of windows, with their class and title (using sed and jq to prettify):

$ gdbus call \
  --session \
  --dest org.gnome.Shell \
  --object-path /org/gnome/Shell \
  --method org.gnome.Shell.Eval "      
    global              
      .get_window_actors()
      .map(a=>a.meta_window)                                   
      .map(w=>({class: w.get_wm_class(), title: w.get_title()}))" \
  | sed -E -e "s/^\(\S+, '//" -e "s/'\)$//" \
  | jq .

Example output:

[
  {
    "class": "firefox",
    "title": "Mozilla Firefox"
  },
  {
    "class": "org.gnome.Nautilus",
    "title": "Downloads"
  },
  {
    "class": "Google-chrome",
    "title": "ubuntu - Bash command to focus a specific window - Super User - Google Chrome"
  },
  {
    "class": "sublime_text",
    "title": "untitled (dotfiles) - Sublime Text"
  },
  {
    "class": "gnome-terminal-server",
    "title": "Projects"
  },
  {
    "class": "Gnome-shell",
    "title": "gnome-shell"
  }
]

To get the class of the currently focused window:

$ gdbus call \
  --session \
  --dest org.gnome.Shell \
  --object-path /org/gnome/Shell \
  --method org.gnome.Shell.Eval "
    global
      .get_window_actors()
      .map(a=>a.meta_window)
      .find(w=>w.has_focus())
      .get_wm_class()" \
  | cut -d'"' -f 2
gnome-terminal-server

You can play around with what's possible in GJS using Gnome's 'Looking Glass' debugger: Alt+F2, and run lg