11

Is it possible to have single click on the dock icons activate expose by default?

If you have a single window open in ubuntu it doesn't activate expose but if you have multiple windows open it does. This cause issues when I tried to use expose on several different windows in ubuntu.

enter image description here

14
  • 1
    Could you add a link to what expose is to your question?
    – Bruni
    Jul 21 '16 at 6:29
  • so, in other words, you want to have such view even if there's only one window of that app open ? Sep 5 '16 at 6:05
  • @LiamWilliam is it expose or scale?
    – Anwar
    Sep 5 '16 at 8:36
  • 1
    @LiamWilliam no, unfortunately I didn't find anything relevant so far :( Sep 17 '16 at 2:44
  • 1
    @LiamWilliam I only found "spread" option via shortcut, but your window has to be focused in order to do that. I've not found a way via click Sep 17 '16 at 3:33
6

Contents:

  1. Overview
  2. Script source
  3. Additional notes

1. Overview

As mentioned in the comments, this functionality apparently got removed since 12.04 and now click on the launcher icon minimizes the window (which apparently was a highly-requested feature, from what I can see in my online searches). However, there exists a keyboard to turn on expo for a single window, which is Super+Ctrl+W. Knowing that, if we can detect click on the launcher or position of the cursor when window is raised , then we can simulate that single window expo via that keyboard shortcut. The script below does exactly that.

This is meant to be saved as /usr/bin/single_click_expo.py file and added to Startup Applications

enter image description here

2. Script Source

Also available on GitHub

#!/usr/bin/env python3

# Author: Serg Kolo
# Date: Sept 28, 2016
# Purpose: activates
# Depends: python3-gi
#          xdotool
# Written for: http://askubuntu.com/q/651188/295286

# just in case user runs this with python 2
from __future__ import print_function
import gi
gi.require_version('Gdk', '3.0')
from gi.repository import Gdk,Gio
import sys
import dbus
import subprocess

def run_cmd(cmdlist):
    """ Reusable function for running shell commands"""
    try:
        stdout = subprocess.check_output(cmdlist)
    except subprocess.CalledProcessError:
        print(">>> subprocess:",cmdlist)
        sys.exit(1)
    else:
        if stdout:
            return stdout

def gsettings_get(schema,path,key):
    """Get value of gsettings schema"""
    if path is None:
        gsettings = Gio.Settings.new(schema)
    else:
        gsettings = Gio.Settings.new_with_path(schema,path)
    return gsettings.get_value(key)


def get_launcher_object(screen):
    
    # Unity allows launcher to be on multiple
    # monitors, so we need to account for all 
    # window objects of the launcher
    launchers = []

    for window in screen.get_window_stack():
        xid = window.get_xid()
        command = ['xprop','-notype',
                   'WM_NAME','-id',str(xid)
        ]
        xprop = run_cmd(command).decode()
        title = xprop.replace("WM_NAME =","")
        if title.strip()  == '"unity-launcher"':
           launchers.append(window)
           #return window
    return launchers

def get_dbus(bus_type,obj,path,interface,method,arg):
    # Reusable function for accessing dbus
    # This basically works the same as 
    # dbus-send or qdbus. Just give it
    # all the info, and it will spit out output
    if bus_type == "session":
        bus = dbus.SessionBus() 
    if bus_type == "system":
        bus = dbus.SystemBus()
    proxy = bus.get_object(obj,path)
    method = proxy.get_dbus_method(method,interface)
    if arg:
        return method(arg)
    else:
        return method() 
 

def main():


    previous_xid = int()
    screen = Gdk.Screen.get_default()

    while True:

        current_xid = screen.get_active_window().get_xid()
        if  int(current_xid) == previous_xid:
            continue
        previous_xid = int(current_xid)
        icon_size = gsettings_get(
                        'org.compiz.unityshell',
                        '/org/compiz/profiles/unity/plugins/unityshell/',
                        'icon-size')
        icon_size = int(str(icon_size))
        position = str(gsettings_get(
                       'com.canonical.Unity.Launcher',
                       None,
                       'launcher-position'))
        screen = Gdk.Screen.get_default()
        launcher_objs = get_launcher_object(screen)

        # for faster processing,figure out which launcher is used
        # first before running xdotool command. We also need
        # to account for different launcher positions (available since 16.04)
        pointer_on_launcher = None
        for launcher in launcher_objs:
            if 'Left' in position and  \
               abs(launcher.get_pointer().x) <= icon_size:
                  pointer_on_launcher = True
            elif 'Bottom' in position and \
               abs(launcher.get_pointer().y) <= icon_size:
                  pointer_on_launcher = True
            else:
               continue


        active_xid = int(screen.get_active_window().get_xid())
        
        application = get_dbus('session',
                               'org.ayatana.bamf',
                               '/org/ayatana/bamf/matcher',
                               'org.ayatana.bamf.matcher',
                               'ApplicationForXid',
                               active_xid)

        # Apparently desktop window returns empty application
        # we need to account for that as well
        if application:
            xids = list(get_dbus('session',
                            'org.ayatana.bamf',
                            application,
                            'org.ayatana.bamf.application',
                            'Xids',None))

        if pointer_on_launcher and\
           len(xids) == 1:
               run_cmd(['xdotool','key','Ctrl+Super+W'])


if __name__ == '__main__':
    main()

3. Additional notes

  • It might be advisable to remap the shortcut to something other Super+Ctrl+W , because in expo Ctrl+W in Expo corresponds to "close window" command. Potential issue here is that frequent switching may cause window closing. The script would have to be adjusted as well accordingly.

NOTE:

The script relies on xdotool utility. You must have it installed. Without xdotool it won't work, since xdotool is used to simulate keypresses. Install it via sudo apt-get install xdotool

14
  • I get No module named gi
    – William
    Oct 10 '16 at 18:20
  • @LiamWilliam You probably need to install python3-gi package. Odd, since it's like a standard module and comes with Ubuntu by default. Oct 10 '16 at 18:26
  • What version of ubuntu are you on?
    – William
    Oct 10 '16 at 22:31
  • @LiamWilliam 16.04 LTS, but python3-gi also comes by default in 14.04 LTS. I don't know about earlier versions Oct 10 '16 at 22:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.