Highlight the focussed screen (or dim- flash on focus change, see EDIT further below)
In a side-by-side dual monitor setup (left-right), the script below will set
the brightness of the monitor with the focussed window to "normal" (100%),
while other one is dimmed to 60%.
If the focus changes, the brightness will follow the focus:
focus on (a window) on the right screen
focus on (a window) on the left screen
The script
#!/usr/bin/env python3
"""
In a side-by-side dual monitor setup (left-right), the script below will set
the brightness of the monitor with the focussed window to "normal" (100%),
while other one is dimmed to 60%. If the focus changes, the brightness will
follow the focus
"""
import subprocess
import time
def get_wposition():
# get the position of the currently frontmost window
try:
w_data = subprocess.check_output(["wmctrl", "-lG"]).decode("utf-8").splitlines()
frontmost = subprocess.check_output(["xprop", "-root", "_NET_ACTIVE_WINDOW"]).decode("utf-8").split()[-1].strip()
z = 10-len(frontmost); frontmost = frontmost[:2]+z*"0"+frontmost[2:]
return [int(l.split()[2]) for l in w_data if frontmost in l][0]
except subprocess.CalledProcessError:
pass
def get_onscreen():
# get the size of the desktop, the names of both screens and the x-resolution of the left screen
resdata = subprocess.check_output(["xrandr"]).decode("utf-8")
if resdata.count(" connected") == 2:
resdata = resdata.splitlines()
r = resdata[0].split(); span = int(r[r.index("current")+1])
screens = [l for l in resdata if " connected" in l]
lr = [[(l.split()[0], int([s.split("x")[0] for s in l.split() if "+0+0" in s][0])) for l in screens if "+0+0" in l][0],
[l.split()[0] for l in screens if not "+0+0" in l][0]]
return [span, lr]
else:
print("no second screen seems to be connected")
def scr_position(span, limit, pos):
# determine if the frontmost window is on the left- or right screen
if limit < pos < span:
return [right_scr, left_scr]
else:
return [left_scr, right_scr]
def highlight(scr1, scr2):
# highlight the "active" window, dim the other one
action1 = "xrandr", "--output", scr1, "--brightness", "1.0"
action2 = "xrandr", "--output", scr2, "--brightness", "0.6"
for action in [action1, action2]:
subprocess.Popen(action)
# determine the screen setup
screendata = get_onscreen()
left_scr = screendata[1][0][0]; right_scr = screendata[1][1]
limit = screendata[1][0][1]; span = screendata[0]
# set initial highlight
oncurrent1 = scr_position(span, limit, get_wposition())
highlight(oncurrent1[0], oncurrent1[1])
while True:
time.sleep(0.5)
pos = get_wposition()
# bypass possible incidental failures of the wmctrl command
if pos != None:
oncurrent2 = scr_position(span, limit, pos)
# only set highlight if there is a change in active window
if oncurrent2 != oncurrent1:
highlight(oncurrent1[1], oncurrent1[0])
oncurrent1 = oncurrent2
How to use
The script needs wmctrl
:
sudo apt-get install wmctrl
Copy the script into an empty file, save it as highlight_focus.py
Test- run it by the command:
python3 /path/to/highlight_focus.py
With the second monitor connected, test if the script works as expected.
If all works fine, add it to startup applications: Dash > Startup Applications > Add the command:
/bin/bash -c "sleep 15 && python3 /path/to/highlight_focus.py"
Notes
The script is extremely low on resources. To "save fuel", the screen setup; resolutions, span size etc. is read only once, during startup of the script (not included in the loop). That implies that you have to restart the script if you connect/disconnect the second monitor.
If you added it to startup applications, it means you have to log out/in after changes in monitor configuration.
If you'd prefer another brightness percentage for the dimmed screen, change the value in the line:
action2 = "xrandr", "--output", scr2, "--brightness", "0.6"
The value can be between 0,0
(black screen) and 1.0
(100%).
Explanation
On startup of the script, it determines:
- the spanning resolution of both screens
- the x-resolution of the left screen
- the names of both screens
Then, in a loop (once per second), it:
If the window's (x-) position is greater then the x-resolution of the left screen, the window apparently is on the right screen, unless it is greater then the spanning size of the two screens (then it would be on the workspace on the right). therefore:
if limit < pos < span:
determines if the window is on the right screen (where limit
is x-res of the left screen, pos
is the window's x-position and span
is the combined x-res of both screens).
If there is a change in the position of the frontmost window (on left screen or right screen), the script sets the brightness of both screens with the xrandr
command:
xrandr --output <screen_name> --brightness <value>
EDIT
Dim-flash the focussed screen instead of a permanent dimmed "unfocussed" screen
As requested in a comment and in chat, below a version of the script that gives a short dim flash on the newly focussed screen instead:
#!/usr/bin/env python3
"""
In a side-by-side dual monitor setup (left-right), the script below will give
a short dim- flash on the newly focussed screen if the focussed screen changes
"""
import subprocess
import time
def get_wposition():
# get the position of the currently frontmost window
try:
w_data = subprocess.check_output(["wmctrl", "-lG"]).decode("utf-8").splitlines()
frontmost = subprocess.check_output(["xprop", "-root", "_NET_ACTIVE_WINDOW"]).decode("utf-8").split()[-1].strip()
z = 10-len(frontmost); frontmost = frontmost[:2]+z*"0"+frontmost[2:]
return [int(l.split()[2]) for l in w_data if frontmost in l][0]
except subprocess.CalledProcessError:
pass
def get_onscreen():
# get the size of the desktop, the names of both screens and the x-resolution of the left screen
resdata = subprocess.check_output(["xrandr"]).decode("utf-8")
if resdata.count(" connected") == 2:
resdata = resdata.splitlines()
r = resdata[0].split(); span = int(r[r.index("current")+1])
screens = [l for l in resdata if " connected" in l]
lr = [[(l.split()[0], int([s.split("x")[0] for s in l.split() if "+0+0" in s][0])) for l in screens if "+0+0" in l][0],
[l.split()[0] for l in screens if not "+0+0" in l][0]]
return [span, lr]
else:
print("no second screen seems to be connected")
def scr_position(span, limit, pos):
# determine if the frontmost window is on the left- or right screen
if limit < pos < span:
return [right_scr, left_scr]
else:
return [left_scr, right_scr]
def highlight(scr1):
# highlight the "active" window, dim the other one
subprocess.Popen([ "xrandr", "--output", scr1, "--brightness", "0.3"])
time.sleep(0.1)
subprocess.Popen([ "xrandr", "--output", scr1, "--brightness", "1.0"])
# determine the screen setup
screendata = get_onscreen()
left_scr = screendata[1][0][0]; right_scr = screendata[1][1]
limit = screendata[1][0][1]; span = screendata[0]
# set initial highlight
oncurrent1 = []
while True:
time.sleep(0.5)
pos = get_wposition()
# bypass possible incidental failures of the wmctrl command
if pos != None:
oncurrent2 = scr_position(span, limit, pos)
# only set highlight if there is a change in active window
if oncurrent2 != oncurrent1:
highlight(oncurrent2[0])
oncurrent1 = oncurrent2
Best Answer
List windows, choose one to move to the current workspace
When the script below is called, it will list all windows on all workspaces. Pick one and press OK to move the window to the current workspace and raise it. By default, it moves the window to position
100
(x),100
(y)The script is relatively simple as a result of the use of both
wmctrl
andxdotool
. Whilewmctrl
is used to list all windows,xdotool
simply moves them to a predefined position on the current workspace "without asking questions" on the window's size (unlikewmctrl
) and relative positions of both workspaces to each other.A more precise positioning of the window, according to the position on its original workspace, would very well be possible, but would also multiply the needed code (like e.g. here). I assume in most situations, this will do.
An example:
I am on workspace 8, while I have a
gedit
window on workspace 1. Calling the script lists the windows:picking the gedit window will move it to the current workspace:
The script
How to use
The script needs both
wmctrl
andxdotool
copy the script into an empty file, svae it as
move_windows.py
Test-run it by the command:
a window should appear, listing currently opened windows:
pick one to see if it is moved to the current workspace and raised correctly.
If all works fine, ad it to a shortcut key: choose: System Settings > "Keyboard" > "Shortcuts" > "Custom Shortcuts". Click the "+" and add the command:
Note
The size of the
zenity
window, listing current windows, is set automatically. The script looks for the longest window name and the number of rows (windows) and sets the size accordingly.EDIT
As requested in a comment, below a version in which the
zenity
list- window includes more information: de current workspace of the targeted window(s) and the application it belongs to.As mentioned above, the information on the relative/absolute workspace positions leads to a more "substantial" amount of code, but luckily I could use this earlier answer as a base.
How to use
The use is pretty much the same as the first version of the script (above), but the command needs to include the preferred sorting option. Run it by one of the commands:
to sort the list by application,
to sort the list by workspace, and
to sort the list by window name.
The script:
EDIT 2: 15.04 specific
The output of the used
ps
command seems to have changed forgnome-terminal
in 15.04. Therefore, in 15.04, the application name ofgnome-terminal
was not displayed correctly in the script above. The version below derives the application name from theWM_CLASS
, as in the output of thexprop
command:The usage is exactly the same as in the (second) script above: