我可以创建工作区相关的命令触发器吗?

我想知道是否有办法让一个动作有两种不同的效果,具体取决于它所在的工作空间。

例如:如果在工作区1上,则使用聚焦Empathy的聊天列表的命令,但如果在工作区2上,则使用打开Chrome的命令。

它将与在Compiz中鼠标hover在屏幕右边缘相关联。

这可能吗?

看看xdotoolget_desktop将在视图中输出当前桌面。

对于带有Unity的Ubuntu,工作空间称为viewports ,并以坐标forms显示,左上角的x和y位置。

例如,

 $ xdotool get_desktop_viewport 4780 0 

您可以使用该信息来确定您所在的工作空间,并为每个工作空间执行命令。

注意 :答案已经在python中重写,以获得更好的性能,但没有GUI元素。 请参阅Python版本一节

Shell脚本版本

介绍

下面的脚本允许根据当前活动的工作区运行特定命令。 它旨在绑定到键盘快捷方式。 可以在此处找到脚本的演示: https : //www.youtube.com/watch?v =oxim3JbeiVM

获取脚本

从此post复制脚本源或通过以下步骤安装:

  1. sudo apt-get install git
  2. cd /opt ; sudo git clone https://github.com/SergKolo/sergrep.git
  3. sudo chmod -R +x sergrep

该文件是/opt/sergrep/unity_viewport_commands.sh

使用和选项概述

该脚本具有以下标志:

  • -r运行当前视口的命令
  • -g生成新的命令列表
  • -h打印帮助文本
  • -v查看当前设置
  • -s更改单个视口的设置

该脚本旨在绑定到具有特定标志的键盘快捷方式。 例如, Ctrl + Alt + I将绑定到unity_viewport_commands.sh -r以调用命令。

要将脚本绑定到快捷方式,请参阅如何将.sh文件绑定到键盘组合?

脚本来源

 #!/usr/bin/env bash # ########################################################### # Author: Serg Kolo , contact: 1047481448@qq.com # Date: April 18th, 2016 # Purpose: Script that runs a command depending # on the current viewport # Written for: https://askubuntu.com/q/56367/295286 # Tested on: Ubuntu 14.04 , Unity 7.2.6 ########################################################### # Copyright: Serg Kolo , 2016 # # Permission to use, copy, modify, and distribute this software is hereby granted # without fee, provided that the copyright notice above and this permission statement # appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. ARGV0="$0" ARGC=$# get_screen_geometry() { xwininfo -root | awk '/-geometry/{gsub(/+|x/," ");print $2,$3}' } gui_dialog() { SCHEMA="org.compiz.core:/org/compiz/profiles/unity/plugins/core/" read swidth sdepth <<< "$(get_screen_geometry)" vwidth=$(gsettings get $SCHEMA hsize) vheight=$(gsettings get $SCHEMA vsize) width=0 for horizontal in $(seq 1 $vwidth); do height=0 for vertical in $(seq 1 $vheight); do # array+=( FALSE ) viewport+=( $(echo "$width"x"$height") ) height=$(($height+$sdepth)) done width=$(($width+$swidth)) done local fmtstr="" for i in ${viewport[@]} ; do fmtstr=$fmtstr"$(printf "%s\"%s\" " "--add-entry=" $i)" done STR=$(zenity --forms --title="Set Viewport Commands" \ --text='Please avoid using # character' --separator="#" \ $fmtstr 2>/dev/null) OLDIFS=$IFS IFS="#" commands=( $STR ) IFS=$OLDIFS # for loop done with while loop counter=0 while [ $counter -lt ${#viewport[@]} ] ; do echo "${viewport[$counter]}":"${commands[$counter]}" counter=$(($counter+1)) done } get_current_viewport() { xprop -root -notype _NET_DESKTOP_VIEWPORT | \ awk -F'=' '{gsub(/\,/,"x");gsub(/\ /,"");print $2}' } run_viewport_command() { [ -r "$HOME"/"$DATAFILE" ] || \ { printf ">>> ERR: commands file doesn't exit. \ \nCreate new one using -g flag" > /dev/stderr ; exit 1 ;} local VP=$(get_current_viewport) cmd=$(awk -v regex="^$VP" -F ':' '$0~regex{ $1="";print }' "$HOME"/"$DATAFILE") eval $cmd " &> /dev/null &" } view_current_settings() { if [ -r "$HOME"/"$DATAFILE" ]; then cat "$HOME"/"$DATAFILE" | \ zenity --list --height=250 --width=250 \ --title="current settings" --column="" 2> /dev/null else printf ">>> ERR: commands file doesn't exist \\nCreate new one using -g flag" > /dev/stderr exit 1 fi } change_single() { if [ -r "$HOME"/"$DATAFILE" ] ;then NEWLINE="$(zenity --forms --separator='#' \ --add-entry="viewport to change(XPOSxYPOS):"\ --add-entry="new command")" remove_this=$(awk -F '#' '{ print $1 }' <<< "$NEWLINE") sed -i '/^'$remove_this'/d' "$HOME"/"$DATAFILE" new_cmd=$(awk -F '#' '{$1="";printf "%s",$0}' <<< "$NEWLINE") echo "$remove_this":"$new_cmd" >> "$HOME"/"$DATAFILE" fi } print_usage() { cat << EOF Usage: viewport_commands.sh [option] Copyright Serg Kolo , 2016 -r run a command for current viewport -g generate new list of commands -h print this text -v view current settings -s change setting for a single viewport EOF } parse_args() { [ $# -eq 0 ] && print_usage && exit 0 local option OPTIND while getopts "grvhs" option ; do case ${option} in g) gui_dialog > "$HOME"/"$DATAFILE" ;; r) run_viewport_command ;; v) view_current_settings ;; s) change_single ;; h) print_usage && exit 0 ;; \?) echo "Invalid option: -$OPTARG" >&2 ;; esac done shift $((OPTIND-1)) } main() { local DATAFILE=".viewport_commands" parse_args "$@" exit 0 } main "$@" 

简单的shell脚本版本(原始答案)

Ubuntu使用视口而不是工作区。 这是一个坐标系统,向下和向右计数正数,其中0,0将是你的左上角工作区。

通过了解,我们可以拥有一个简单的脚本来获取当前坐标,测试它们并执行适当的命令。 下面的脚本就是这么做的。

 #!/bin/bash get_viewport() { xprop -root -notype _NET_DESKTOP_VIEWPORT | \ awk -F '=' '{ gsub(/\ /,"");print $2 }' } get_viewport case "$(get_viewport)" in "0,0") notify-send 'You are in the top left viewport' ;; "2732,768") notify-send 'You are in the bottom right viewport' ;; esac 

使用您想要的任何操作替换notify-send命令。 使用nohup COMMAND 2>/dev/null &以避免命令挂起脚本( notify-send是一个例外,因此没有在那里添加它)。

使用xprop -root -notype _NET_DESKTOP_VIEWPORT确定每个视口的坐标。

最后,case语句选项中应该没有空格,例如"0,0"可以工作,但"0, 0" "0,0"不会。


Python版本

介绍

此版本的脚本执行相同的function,但为了简单和可用性,不包含命令行参数或GUI元素。 该脚本可以作为Github Gist以及以下内容获得:

用法:

用法很简单:

 python3 /path/to/workspace_command.py 

该脚本确定当前工作空间并运行~/.workspace_commands.json定义的适当命令。 确保首先创建此文件,否则脚本将无法运行。 另请注意,必须使用双引号来定义每个工作空间和命令+参数

示例~/workspace_commands.json

 { "1":["nautilus"], "2":["firefox","google.com"], "3":["virtualbox"] } 

脚本源代码

 #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Author: Serg Kolo , contact: 1047481448@qq.com Date: August 9th, 2016 Purpose: Spawns a command depending on current viewport, as defined in ~/.workspace_commands.json Written for: https://askubuntu.com/q/56367/295286 Tested on: Ubuntu 16.04 LTS , Unity desktop The MIT License (MIT) Copyright © 2016 Sergiy Kolodyazhnyy <1047481448@qq.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE """ # Just in case the user runs # the script with python 2, import # print function from __future__ import print_function import gi gi.require_version('Gdk', '3.0') from gi.repository import Gio,Gdk import json import subprocess import os def gsettings_get(schema,path,key): """Get value of gsettings schema""" if path is None: gsettings = Gio.Settings.new(schema) else: gsettings = Gio.Settings.new_with_path(schema,path) return gsettings.get_value(key) def run_cmd(cmdlist): """ Reusable function for running shell commands""" try: stdout = subprocess.check_output(cmdlist) except subprocess.CalledProcessError: print(">>> subprocess:",cmdlist) sys.exit(1) else: if stdout: return stdout def enumerate_viewports(): """ generates enumerated dictionary of viewports and their indexes, counting left to right """ schema="org.compiz.core" path="/org/compiz/profiles/unity/plugins/core/" keys=['hsize','vsize'] screen = Gdk.Screen.get_default() screen_size=[ screen.get_width(),screen.get_height()] grid=[ int(str(gsettings_get(schema,path,key))) for key in keys] x_vals=[ screen_size[0]*x for x in range(0,grid[0]) ] y_vals=[screen_size[1]*x for x in range(0,grid[1]) ] viewports=[(x,y) for y in y_vals for x in x_vals ] return {vp:ix for ix,vp in enumerate(viewports,1)} def get_current_viewport(): """returns tuple representing current viewport, in format (width,height)""" vp_string = run_cmd(['xprop', '-root', '-notype', '_NET_DESKTOP_VIEWPORT']) vp_list=vp_string.decode().strip().split('=')[1].split(',') return tuple( int(i) for i in vp_list ) def read_config_file(): """ reads ~/.workspace_commands file """ rcfile = os.path.join( os.path.expanduser('~'), '.workspace_commands.json') try: with open(rcfile) as config_file: config_data = json.load(config_file) except IOError as error: print(error.__repr__()) else: if config_data: return config_data def main(): # get all the info we need first viewports_dict=enumerate_viewports() current_viewport = get_current_viewport() current_vp_number = viewports_dict[current_viewport] viewport_config = read_config_file() for vp,command in viewport_config.items(): if int(vp) == current_vp_number: # spawn the command and let us exit pid = subprocess.Popen(command).pid break if __name__ == '__main__': main() 

鼠标hover操作:

原始问题询问是否在屏幕右侧使用鼠标hover操作。 虽然我建议使用上面的脚本链接到键盘快捷键,但鼠标hover操作是可行的。 下面是一个简单的脚本,如果鼠标位于屏幕的右上角,则会启动上面的python版本。 随意调整脚本以满足您的需求

 #!/usr/bin/env python3 import gi gi.require_version('Gdk', '3.0') from gi.repository import Gio,Gdk import subprocess from time import sleep def main(): screen = Gdk.Screen.get_default() root_window = screen.get_root_window() while True: if root_window.get_pointer()[2] == 0 and \ root_window.get_pointer()[1] >= root_window.get_width()-2: proc = subprocess.Popen(['python3','/home/user/bin/python/workspace_command.py']).pid sleep(0.75) if __name__ == '__main__': main() 

笔记:

类似的鼠标事件脚本可以使用shell脚本完成,该脚本使用xdotool getmouselocation命令并解析其输出,如下所示:

 $ xdotool getmouselocation x:1140 y:420 screen:0 window:14680095