Table of Contents
Manually rotation screen
The following procedures allow to rotate the screen by means of two different methods:
- choose of the orientation, independently from the current one;
- clockwise rotation at intervals of 90°.
Important: the maximum resolution supported by Fujitsu Lifebook T4220 monitor is 1400×1050 px.
However, when the monitor is rotated in the portrait format, this resolution is no longer supported and it's necessary to come down at 1024×768 px.
Packages required
From Synaptic, install the packages::
xserver-xorg-input-synaptics
xserver-xorg-input-wacom
After that, restart the PC.
Get pointing system name
So that pointing systems, also called Virtual core pointer
, are coordinated with the monitor rotation, it's necessary to refer to them, in the configuration script, with their right name.
To list them, give the command:
xinput
Script for rotate the monitor
Save in /usr/local/bin/rotate-screen/
the following two scripts:
- gui.py
#!/usr/bin/env python3 import tkinter as tk import rotate class App(tk.Frame, rotate.Rotate): def __init__(self, master=None): """ Initialize the class. """ tk.Frame.__init__(self, master) self.grid() self.createWidgets() self.color_std = tk.Button.cget(self, "bg") # get default colour name self.status(self.color_std) def createWidgets(self): """ Create the buttons to choose the direction. """ self.button_n = tk.Button(self) self.button_n["text"] = "NORMAL" self.button_n["command"] = self.call_normal self.button_n.grid(row=1, column=1, sticky=tk.E+tk.W) self.button_l = tk.Button(self) self.button_l["text"] = "LEFT" self.button_l["command"] = self.call_left self.button_l.grid(row=2, column=1, sticky=tk.E+tk.W) self.button_r = tk.Button(self) self.button_r["text"] = "RIGHT" self.button_r["command"] = self.call_right self.button_r.grid(row=3, column=1, sticky=tk.E+tk.W) self.button_i = tk.Button(self) self.button_i["text"] = "INVERTED" self.button_i["command"] = self.call_inverted self.button_i.grid(row=4, column=1, sticky=tk.E+tk.W) def status(self, color_std): """ Depending on the current direction, highlight the relative button. """ cur_dir = rotate.get_direction() if (cur_dir == "normal"): self.button_n["bg"] = "light green" self.button_l["bg"] = color_std self.button_r["bg"] = color_std self.button_i["bg"] = color_std elif (cur_dir == "left"): self.button_n["bg"] = color_std self.button_l["bg"] = "light green" self.button_r["bg"] = color_std self.button_i["bg"] = color_std elif (cur_dir == "right"): self.button_n["bg"] = color_std self.button_l["bg"] = color_std self.button_r["bg"] = "light green" self.button_i["bg"] = color_std elif (cur_dir == "inverted"): self.button_n["bg"] = color_std self.button_l["bg"] = color_std self.button_r["bg"] = color_std self.button_i["bg"] = "light green" def call_normal(self): """ Invoke the methods that rotate the screen to normal. """ cur_dir = rotate.get_direction() new_dir = "normal" rotate.choose(cur_dir, new_dir) self.status(self.color_std) def call_left(self): """ Invoke the methods that rotate the screen to left. """ cur_dir = rotate.get_direction() new_dir = "left" rotate.choose(cur_dir, new_dir) self.status(self.color_std) def call_right(self): """ Invoke the methods that rotate the screen to right. """ cur_dir = rotate.get_direction() new_dir = "right" rotate.choose(cur_dir, new_dir) self.status(self.color_std) def call_inverted(self): """ Invoke the methods that rotate the screen to upside-down. """ cur_dir = rotate.get_direction() new_dir = "inverted" rotate.choose(cur_dir, new_dir) self.status(self.color_std) if __name__ == '__main__': root = tk.Tk() rotate = rotate.Rotate() app = App(master=root) app.master.title("") app.mainloop()
- rotate.py
#!/usr/bin/env python3 import subprocess import re STYLUS = "Serial Wacom Tablet FUJ02e5 stylus" TOUCH = "SynPS/2 Synaptics TouchPad" RES_1 = "1400x1050" RES_2 = "1024x768" CMT_N = ["1", "0", "0", "0", "1", "0", "0", "0", "1"] CMT_L = ["0", "-1", "1", "1", "0", "0", "0", "0", "1"] CMT_R = ["0", "1", "0", "-1", "0", "1", "0", "0", "1"] CMT_I = ["-1", "0", "1", "0", "-1", "1", "0", "0", "1"] class Rotate(object): def get_direction(self): """ Extract the actual direction of the screen. executing the bash command: xrandr | grep ' connected' we get a line of the form: "LVDS1 connected 1400x1050+0+0 <direction> (normal left inverted right x axis y axis) 0mm x 0mm" where: <direction> = "left"|"inverted"|"right" but if: <direction> = "" the screen is in "normal" OUTPUT cur_dir: (str) the name of the current direction among "normal"|"left"|"inverted"|"right" """ line = subprocess.check_output("xrandr | grep ' connected'", shell=True) p = re.compile(r'(left|right|inverted)(?=\s\()') m = p.search(str(line)) if m: cur_dir = str(m.group()) else: cur_dir = "normal" return cur_dir def choose(self, cur_dir, new_dir): """ Depending on the current direction and the new direction, call the appropriate function which sets the new direction of the screen. INPUT cur_dir: (str) the name of the current direction among "normal"|"left"|"inverted"|"right" new_dir: (str) the name of the new direction among "normal"|"left"|"inverted"|"right" """ if (cur_dir == "normal"): if (new_dir == "left"): self.set_left() elif (new_dir == "right"): self.set_right() elif (new_dir == "inverted"): self.set_inverted() if (cur_dir == "left"): if (new_dir == "normal"): self.set_normal() elif (new_dir == "right"): self.set_right() elif (new_dir == "inverted"): self.set_inverted() elif (cur_dir == "right"): if (new_dir == "normal"): self.set_normal() elif (new_dir == "left"): self.set_left() elif (new_dir == "inverted"): self.set_inverted() elif (cur_dir == "inverted"): if (new_dir == "normal"): self.set_normal() elif (new_dir == "left"): self.set_left() elif (new_dir == "right"): self.set_right() def set_normal(self): """ Rotate the screen to normal. """ subprocess.call(["xrandr", "-o", "normal"]) subprocess.call(["xrandr", "-s", RES_1]) subprocess.call(["xsetwacom", "set", STYLUS, "Rotate", "none"]) subprocess.call(["xinput", "set-prop", TOUCH, "Coordinate Transformation Matrix"] + CMT_N) def set_left(self): """ Rotate the screen to left. In this direction, the screen can support only 1024x768 resolution. """ subprocess.call(["xrandr", "-o", "left"]) subprocess.call(["xrandr", "-s", RES_2]) subprocess.call(["xsetwacom", "set", STYLUS, "Rotate", "ccw"]) subprocess.call(["xinput", "set-prop", TOUCH, "Coordinate Transformation Matrix"] + CMT_L) def set_right(self): """ Rotate the screen to right. In this direction, the screen can support only 1024x768 resolution. """ subprocess.call(["xrandr", "-o", "right"]) subprocess.call(["xrandr", "-s", RES_2]) subprocess.call(["xsetwacom", "set", STYLUS, "Rotate", "cw"]) subprocess.call(["xinput", "set-prop", TOUCH, "Coordinate Transformation Matrix"] + CMT_R) def set_inverted(self): """ Rotate the screen upside-down. """ subprocess.call(["xrandr", "-o", "inverted"]) subprocess.call(["xrandr", "-s", RES_1]) subprocess.call(["xsetwacom", "set", STYLUS, "Rotate", "half"]) subprocess.call(["xinput", "set-prop", TOUCH, "Coordinate Transformation Matrix"] + CMT_I) def bezel_button(self): """ Depending on the current direction, perform rotation in counter clock wise in the followin order: left inverted right normal """ cur_dir = self.get_direction() if (cur_dir == "normal"): self.set_left() elif (cur_dir == "left"): self.set_inverted() elif (cur_dir == "inverted"): self.set_right() elif (cur_dir == "right"): self.set_normal() if __name__ == '__main__': rotate = Rotate() rotate.bezel_button()
Connect the script to a panel button
Add a launcher in the panel as follows:
Command | python3 gui.py |
---|---|
Working Directory | /usr/local/bin/rotate-screen |
Connect the script to a bezel button
Bezel buttons are those ones around the monitor frame. Hereafter the steps to associate an action to a given bezel button using its keycode
.
- Run the command
xev
- Hit the button to use for the monitor rotation and write down its
keycode
. - Edit the file
/usr/share/X11/xkb/symbols/inet
, replacing the lines:// key <I161> { [ ] }; // KEY_DIRECTION key <I162> { [ XF86RotateWindows ] };
in:
key <I161> { [ XF86RotateWindows ] }; // key <I161> { [ ] }; // KEY_DIRECTION // key <I162> { [ XF86RotateWindows ] };
- Eventually clean the cache in
/var/lib/xkb/*.xkm
. - In
Settings
>Keyboard
>Application Shortcuts
, add a new shortcut:Shortcut XF86RotateWindows
Command python3 /usr/local/bin/rotate-screen/rotate.py
Links
- The original guide: forum.thinkpads.com
- List of symbolic codes: keytouch.sourceforge.net