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

William
  • 886
  • 3
  • 10
  • 29
  • 1
    Could you add a link to what expose is to your question? – Bruni Jul 21 '16 at 06:29
  • so, in other words, you want to have such view even if there's only one window of that app open ? – Sergiy Kolodyazhnyy Sep 05 '16 at 06:05
  • @LiamWilliam is it expose or scale? – Anwar Sep 05 '16 at 08:36
  • @Serg that's correct that was the original behavior in 12.04 – William Sep 06 '16 at 17:59
  • @Anwar I'm not sure what is is called technically I tend to call it expose even though that might not be the right name. – William Sep 06 '16 at 18:00
  • @LiamWilliam a lot of things changed since 12.04 , so I would assume that feature was removed. I'll see if anything can be done about it – Sergiy Kolodyazhnyy Sep 06 '16 at 18:09
  • @Serg Do you have any idea where the best place to look? The bounty expires soonish. First step is probably to see what version this changed in exactly. – William Sep 09 '16 at 19:15
  • @Serg you were the only response I got did you figure anything out if you mind me asking? – William Sep 17 '16 at 02:36
  • 1
    @LiamWilliam no, unfortunately I didn't find anything relevant so far :( – Sergiy Kolodyazhnyy Sep 17 '16 at 02: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 – Sergiy Kolodyazhnyy Sep 17 '16 at 03:33
  • Question: In 16.04 the single click on icon that has only single window minimizes the window. Do you want to keep that functionality and activate expo only when active window changes ? or do you want to only have expo functionality and no minimizing ? – Sergiy Kolodyazhnyy Sep 25 '16 at 01:57
  • Back to my previous question above ^ . I don't think the minimize single window feature can be disabled. I can only make single-click expo work when you switch between windows. So for example, if you have chrome highlighted, then you click on terminal icon ( and it's a single window) , expo will be activated. – Sergiy Kolodyazhnyy Sep 25 '16 at 02:04
  • @Serg I don't care if the minimize single window feature works I will not use it. Just as your example I believe you heard me right. – William Sep 25 '16 at 03:07
  • OK. I will polish my script and post it tomorrow, i suppose. – Sergiy Kolodyazhnyy Sep 25 '16 at 03:20

1 Answers1

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

Sergiy Kolodyazhnyy
  • 103,293
  • 19
  • 273
  • 492