Ubuntu – Run specific scripts/settings on several occassions (connect mouse, connect screen etc)

display-resolutionmousescripts

I'm sure I'm not the only one in this situation: I run Ubuntu 16 on my laptop, and I use that to connect to my workstation in the office.

Now there are a couple things that I have to do every day when I connect to my workstation, such as fixing my bluetooth mouse speed, setting the right resolution for both screens and restoring my wallpaper with nitrogen. For each of these tasks I have a (startup) script which works fine, but when I connect my second screen, the laptop is already booted.

So my question is, next to start-up applications, how could I (i.e.) run nitrogen --restore and scale down the resolution on my laptop (from 2560×1600 to 1440×900) when I connect the second screen?

What I do now is run all seperate scripts again manually, which isn't a big deal, but we don't use Ubuntu to just accept how it is, right? 😉

To clarify; my question isn't too specific for these tasks, but more in a general sense; how could I fire anything from the terminal on specific actions like "input of display detected"?

Best Answer

Use a tiny indicator that automatically adds your scripts to a menu

Instead of creating multiple watch- procedures for each and every possible event that could take place, I'd suggest using a "one for all" solution like below.

The indicator script automatically adds your scripts to the indicator menu, if you place them in the same directory as the indicator. This way your setup scripts will be easily available from the GUI.

enter image description here

The indicator

#!/usr/bin/env python3
import subprocess
import os
import signal
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('AppIndicator3', '0.1')
from gi.repository import Gtk, AppIndicator3

currpath = os.path.dirname(os.path.realpath(__file__))

class Indicator():
    def __init__(self):
        self.app = 'update_setting'
        iconpath = currpath+"/icon.png"
        self.indicator = AppIndicator3.Indicator.new(
            self.app, iconpath,
            AppIndicator3.IndicatorCategory.SYSTEM_SERVICES)
        self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)       
        self.indicator.set_menu(self.create_menu())

    def getscripts(self):
        files = [f for f in os.listdir(currpath) if f.endswith(".sh")]
        for f in files:
            fpath = os.path.join(currpath, f)
            subprocess.Popen(["chmod", "+x", fpath])
            menuitem = Gtk.MenuItem(f.split(".")[0])
            menuitem.connect("activate", self.run_script, fpath)
            self.menu.append(menuitem)

    def create_menu(self):
        self.menu = Gtk.Menu()
        self.getscripts()
        # quit
        item_quit = Gtk.MenuItem('Quit')
        sep = Gtk.SeparatorMenuItem()
        self.menu.append(sep)
        item_quit.connect('activate', self.stop)
        self.menu.append(item_quit)
        self.menu.show_all()
        return self.menu

    def run_script(self, widget, script):
        print(script)
        subprocess.Popen(["/bin/bash", "-c", script])

    def stop(self, source):
        Gtk.main_quit()

Indicator()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()

How to use

  1. Copy the script into an empty file, save it as showscripts.py
  2. Copy the icon below (right- click -> save), save it as (exactly) icon.png in one and the same directory as the script

    enter image description here

  3. For each of your settings commands, create a small script:

    /bin/bash
    command_to_run
    

    Name them (no spaces), but make sure to use the .sh extension. Copy or move the scripts into the same folder as where you keep the indicator script.

    Now you can make as many menu items (scripts) as you like,

  4. Test- run the indicator by the command:

    python3 /path/to/showscripts.py
    
  5. If all works fine, add to Startup Applications: Dash > Startup Applications > Add. Add the command:

    /bin/bash -c "sleep 10 && python3 /path/to/showscripts.py"
    

Explanation

  1. When the script is launched, it lists all files in its own directory, looking for files with .sh extension. These files are made executable automatically.
  2. For each of these files, the indicator creates a menu item to run it from the menu.

Other options?

  1. The most advanced: writing udev rules for actions, to be taken on specific events. This is however also the most complicated option. Also not the most flexible option in case you want or need to change anything.
  2. Run a background script to check for changes in connected hardware. As far as it is about screen setup, a ready to use example is in this answer.
  3. Combine your commands into one script and run it by a keyboard shortcut. Add shortut key: Choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command to run the script.

I would however go for the indicator menu. Once setup, you can easily add, remove or edit functionality by simply moving around small scripts.

Related Question