Ubuntu – Ubuntu 18.04: Changing dock location on monitor rotation

18.04display-rotationgnome-shellubuntu-dock

In my current configuration, I have a dock (which shows application icons) on the left of the screen. I was wondering whether it is possible to move the dock to the top when the monitor is rotated 90 degrees (so to avoid narrowing down the width of the screen). Also, I want the dock to be back in the original position when I go back to the horizontal monitor orientation. Could someone help me do this?

Environment

I am running Ubuntu 18.04 and using the default gnome desktop environment. My computer is a 2-in-1 laptop which automatically rotates screen based on device orientation.

Current Attempt

I looked into possible gnome extensions that would do this, but Dash to Dock did not have such options.

Best Answer

We have to change approaches based on whether your computer comes with an accelerometer or not. If your computer comes with an accelerometer (usually a 2-in-1 laptop or a tablet), this can be completely automated by detecting screen orientation changes. Otherwise, creating a bash script to change the orientation and dock location at the same time would give you enough convenience.

Laptop with an Accelerometer

I wrote a python3 code that gets run on boot. The script listens to the screen rotation changes and changes the dock position accordingly.

  1. Download Dash to Dock gnome extension. In my case, it did not need to be enabled, but it might be required.
  2. With your favorite text editor, create a python3 file, put the following code, and save it. You can pick any name or location of the file as long as you remember where it is so that you can refer to it in Step 3 and 4. I called it "dock_rotator.py".

#!/usr/bin/env python3
import os
import subprocess
import dbus
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GObject as gobject


def run_command(command, shell=False):
    """ Takes a string to run a command on bash
    """
    p = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
    output = p.communicate()[0]
    return output.decode()


def enable_view_rotation_lock():
    os.environ["GIO_EXTRA_MODULES"] = "/usr/lib/x86_64-linux-gnu/gio/modules/"


def rotation_locked():
    locked = run_command("gsettings get \
        org.gnome.settings-daemon.peripherals.touchscreen \
        orientation-lock")

    return locked.strip() == "true"

def move_dash_top():
    run_command("gsettings set org.gnome.shell.extensions.dash-to-dock dock-position TOP")

def move_dash_left():
    run_command("gsettings set org.gnome.shell.extensions.dash-to-dock dock-position LEFT")


def sensor_handler(*args, **kwargs):
    if len(args) < 2:
        return

    dbus_dict = args[1]
    key = 'AccelerometerOrientation'
    if key not in dbus_dict:
        return
    orientation = dbus_dict[key]

    if not rotation_locked():
        if orientation in ["left-up", "right-up"]:
            move_dash_top()
        else:
            move_dash_left()

def main():
    enable_view_rotation_lock()
    global loop
    DBusGMainLoop(set_as_default=True)

    loop = gobject.MainLoop()
    bus = dbus.SystemBus()

    bus.add_signal_receiver(
        sensor_handler,
        path='/net/hadess/SensorProxy')

    loop.run()


if __name__ == "__main__":
    main()
  1. Make the code executable by chmod +x <filename> command. If you saved your file in a directory owned by root in Step 2, you need to run sudo chmod +x <filename> instead.
  2. Open "Startup Application" and add a new entry to direct to the python file you just created.

Name: <any>
Command: <path to the file>
Comment: <any>

  1. Restart your computer.

Computer without an Accelerometer

This approach creates a bash script which needs to be executed when you want to change your display orientation.

  1. Download Dash to Dock gnome extension. In my case, it did not need to be enabled, but it might be required.

  2. With your favorite text editor, create a bash file called "drotate" (for dash rotate), put the following code, and save it.

#!/bin/bash

show_help () {
    echo "drotate <rotation> [<display number>]"
    echo "<rotation> : inverted | left | normal | right "
    echo "<display number> : any number between 1 to number of displays connected"
    echo "                   defaults to 1"
}

set_gnome_orientation () {
    case "$1" in
        inverted)
            GNOME_ORIENTATION=LEFT
        ;;
        normal)
            GNOME_ORIENTATION=LEFT
        ;;
        left)
            GNOME_ORIENTATION=TOP
        ;;
        right)
            GNOME_ORIENTATION=TOP
        ;;
        *)
        echo "Invalid orientation"
        show_help
        exit 1
        ;;
        esac
}

if [ $# -eq 0 ] || [ $# -gt 2 ]; then
    show_help 
    exit 1
fi

if [ $# -eq 1 ]; then
    DISPLAY_INDEX=1 # any number between 1 to # of displays connected
else
    DISPLAY_INDEX=$2
fi

DISPLAY=$( xrandr --current | grep -F connected |\
 grep -Fv disconnected | cut -d" " -f 1 | head -${DISPLAY_INDEX} | tail -1 )

if [ -z "$DISPLAY" ]; then
    echo Could not find display $DISPLAY_INDEX
    exit 1
fi
echo $DISPLAY

ORIENTATION="$1"
GNOME_ORIENTATION=""
set_gnome_orientation $ORIENTATION

xrandr -d :0 --output ${DISPLAY} --rotate ${ORIENTATION}

export GIO_EXTRA_MODULES=/usr/lib/x86_64-linux-gnu/gio/modules/
gsettings set org.gnome.shell.extensions.dash-to-dock dock-position $GNOME_ORIENTATION
  1. Make the code executable by chmod +x drotate command. If you saved your file in a directory owned by root in Step 2, you need to run sudo chmod +x drotate instead.

  2. Open ~/.bash. Create a new line in the end of the file and paste the following line. export PATH="<path/to/the/directory/with/your/script>:$PATH. For example, if you saved your file in /usr/local/drotate, the command becomes export PATH="/usr/local:$PATH. Notice drotate being omitted.

  3. Save the file.

  4. Either restart your terminal or run source .bashrc. They do the same thing. Now your script should be able to run.

Usage

Open your terminal (Ctrl-Alt-t) and type drotate <rotation> [<display number>].

drotate <rotation> [<display number>]
<rotation> : inverted | left | normal | right 
<display number> : any number between 1 to number of displays connected
                   defaults to 1
Examples
  1. Rotate the main display to left up: drotate left
  2. Rotate the main display back to normal: drotate normal
  3. Rotate your subdisplay to left up: drotate left 2
Related Question