我有两个窗口A和B。是否可以将两个窗口以某种方式链接在一起,例如切换到A也会引发B,或者切换到B也会引发A?
我知道使用多个工作空间是一个替代选择,但想知道是否还可以?
我有两个窗口A和B。是否可以将两个窗口以某种方式链接在一起,例如切换到A也会引发B,或者切换到B也会引发A?
我知道使用多个工作空间是一个替代选择,但想知道是否还可以?
Answers:
以下脚本允许选择两个窗口,并且当两个窗口都打开时,当用户将其中一个聚焦时,它将同时升高两个窗口。例如,如果一个链接寡妇A和B,则对A或B进行巫婆会使两者都高于其他寡妇。
要停止脚本,您可以killall link_windows.py
在terminal中使用,或关闭并重新打开其中一个窗口。您也可以通过X在两个窗口选择弹出对话框中按关闭按钮来取消执行。
潜在的调整:
运行脚本为:
python link_windows.py
该脚本与Python 3兼容,因此也可以作为
python3 link_windows.py
有两个命令行选项:
--quiet
或-q
,可以使GUI窗口静音。使用此选项,您只需在任何两个窗口上单击鼠标,脚本就会开始链接它们。--help
或-h
,打印用法和描述信息。该-h
选项产生以下信息:
$ python3 link_windows.py -h
usage: link_windows.py [-h] [--quiet]
Linker for two X11 windows.Allows raising two user selected windows together
optional arguments:
-h, --help show this help message and exit
-q, --quiet Blocks GUI dialogs.
可以通过查看其他技术信息pydoc ./link_windows.py
,其中./
表示您必须与脚本位于同一目录中。
两个窗口的简单使用过程:
将出现一个弹出窗口,要求您选择#1窗口,按OK或Enter。鼠标指针将变成十字形。单击要链接的窗口之一。
出现第二个弹出窗口,要求您选择窗口#2,按OK或Enter。同样,鼠标指针将变成十字形。单击要链接的另一个窗口。之后,将开始执行。
每当您将一个窗口聚焦时,脚本都会将另一个窗口上移,但会将焦点返回到最初选择的那个窗口(请注意-延迟四分之一秒以获得最佳性能),从而产生将窗口链接在一起的感觉。
如果两次都选择同一窗口,则脚本将退出。如果您随时单击弹出对话框的关闭按钮,则脚本将退出。
也可以作为GitHub Gist使用
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Author: Sergiy Kolodyazhnyy
Date: August 2nd, 2016
Written for: https://askubuntu.com/q/805515/295286
Tested on Ubuntu 16.04 LTS
"""
import gi
gi.require_version('Gdk', '3.0')
gi.require_version('Gtk', '3.0')
from gi.repository import Gdk, Gtk
import time
import subprocess
import sys
import argparse
def run_cmd(cmdlist):
""" Reusable function for running shell commands"""
try:
stdout = subprocess.check_output(cmdlist)
except subprocess.CalledProcessError:
sys.exit(1)
else:
if stdout:
return stdout
def focus_windows_in_order(first, second, scr):
"""Raise two user-defined windows above others.
Takes two XID integers and screen object.
Window with first XID will have the focus"""
first_obj = None
second_obj = None
for window in scr.get_window_stack():
if window.get_xid() == first:
first_obj = window
if window.get_xid() == second:
second_obj = window
# When this function is called first_obj is alread
# raised. Therefore we must raise second one, and switch
# back to first
second_obj.focus(int(time.time()))
second_obj.get_update_area()
# time.sleep(0.25)
first_obj.focus(int(time.time()))
first_obj.get_update_area()
def get_user_window():
"""Select two windows via mouse. Returns integer value of window's id"""
window_id = None
while not window_id:
for line in run_cmd(['xwininfo', '-int']).decode().split('\n'):
if 'Window id:' in line:
window_id = line.split()[3]
return int(window_id)
def main():
""" Main function. This is where polling for window stack is done"""
# Parse command line arguments
arg_parser = argparse.ArgumentParser(
description="""Linker for two X11 windows.Allows raising """ +
"""two user selected windows together""")
arg_parser.add_argument(
'-q','--quiet', action='store_true',
help='Blocks GUI dialogs.',
required=False)
args = arg_parser.parse_args()
# Obtain list of two user windows
user_windows = [None, None]
if not args.quiet:
run_cmd(['zenity', '--info', '--text="select first window"'])
user_windows[0] = get_user_window()
if not args.quiet:
run_cmd(['zenity', '--info', '--text="select second window"'])
user_windows[1] = get_user_window()
if user_windows[0] == user_windows[1]:
run_cmd(
['zenity', '--error', '--text="Same window selected. Exiting"'])
sys.exit(1)
screen = Gdk.Screen.get_default()
flag = False
# begin watching for changes in window stack
while True:
window_stack = [window.get_xid()
for window in screen.get_window_stack()]
if user_windows[0] in window_stack and user_windows[1] in window_stack:
active_xid = screen.get_active_window().get_xid()
if active_xid not in user_windows:
flag = True
if flag and active_xid == user_windows[0]:
focus_windows_in_order(
user_windows[0], user_windows[1], screen)
flag = False
elif flag and active_xid == user_windows[1]:
focus_windows_in_order(
user_windows[1], user_windows[0], screen)
flag = False
else:
break
time.sleep(0.15)
if __name__ == "__main__":
main()
Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged.
这些可以忽略。time.sleep
切换之间的位,我能否将其设为零?有延迟的原因吗?
# time.sleep(0.25)
并且该行不会执行。这样做的原因是要确保正确抬起每个窗口。根据我过去的经验,我需要在Windows上进行一些延迟操作。我认为延迟不到四分之一秒。实际上,让我在脚本中再添加一行,可以加快速度。好 ?
下面的解决方案将让你选择任意的两个,三个或多个窗口进行组合,并提出作为一个使用键盘快捷键组合。
该脚本使用三个参数来完成其工作:
add
将活动窗口添加到组中
raise
筹集组
clear
清除组,准备定义一个新组
#!/usr/bin/env python3
import sys
import os
import subprocess
wlist = os.path.join(os.environ["HOME"], ".windowlist")
arg = sys.argv[1]
if arg == "add":
active = subprocess.check_output([
"xdotool", "getactivewindow"
]).decode("utf-8").strip()
try:
currlist = open(wlist).read()
except FileNotFoundError:
currlist = []
if not active in currlist:
open(wlist, "a").write(active + "\n")
elif arg == "raise":
group = [w.strip() for w in open(wlist).readlines()]
[subprocess.call(["wmctrl", "-ia", w]) for w in group]
elif arg == "clear":
os.remove(wlist)
该脚本需要wmctrl
和xdotool
:
sudo apt-get install wmctrl xdotool
groupwindows.py
测试脚本:打开两个终端窗口,运行命令:
python3 /absolute/path/to/groupwindows.py add
在他们两个。用其他窗户盖住它们(或将其最小化)。打开第三个终端窗口,运行命令:
python3 /absolute/path/to/groupwindows.py raise
前两个窗口将被提升为一个。
如果一切正常,请创建三个自定义快捷键:选择:“系统设置”>“键盘”>“快捷方式”>“自定义快捷方式”。单击“ +”,然后将以下命令添加到三个单独的快捷方式:
在我的系统上,我使用了:
Alt+ A,运行命令:
python3 /absolute/path/to/groupwindows.py add
...向该组添加一个窗口。
Alt+ R,运行命令:
python3 /absolute/path/to/groupwindows.py raise
...以提高团队。
Alt+ C,运行命令:
python3 /absolute/path/to/groupwindows.py clear
...清除小组
该脚本的工作原理非常简单:
add
,脚本会将活动窗口的window-id存储/添加到隐藏文件中~/.windowlist
当使用参数运行时raise
,脚本将读取文件,并使用以下命令引发列表中的窗口:
wmctrl -ia <window_id>
clear
,脚本将删除隐藏文件~/.windowlist
。如前所述,上面的脚本允许随时将窗口添加到分组的窗口中。以下版本还允许(在任何时候)从分组列表中删除任何窗口:
#!/usr/bin/env python3
import sys
import os
import subprocess
wlist = os.path.join(os.environ["HOME"], ".windowlist")
arg = sys.argv[1]
# add windows to the group
if arg == "add":
active = subprocess.check_output([
"xdotool", "getactivewindow"
]).decode("utf-8").strip()
try:
currlist = open(wlist).read()
except FileNotFoundError:
currlist = []
if not active in currlist:
open(wlist, "a").write(active + "\n")
# delete window from the group
if arg == "delete":
try:
currlist = [w.strip() for w in open(wlist).readlines()]
except FileNotFoundError:
pass
else:
currlist.remove(subprocess.check_output([
"xdotool", "getactivewindow"]).decode("utf-8").strip())
open(wlist, "w").write("\n".join(currlist)+"\n")
# raise the grouped windows
elif arg == "raise":
group = [w.strip() for w in open(wlist).readlines()]
[subprocess.call(["wmctrl", "-ia", w]) for w in group]
# clear the grouped window list
elif arg == "clear":
os.remove(wlist)
运行脚本的附加参数是delete
,因此:
python3 /absolute/path/to/groupwindows.py delete
从分组的窗口中删除活动窗口。要运行此命令,请在我的系统上将Alt+ 设置D为快捷方式。