쉘 스크립트 버전

쉘 스크립트 버전

하나의 작업이 작업 공간에 따라 두 가지 다른 효과를 갖도록 하는 방법이 있는지 궁금합니다.

예를 들어 워크스페이스 1의 경우 Empathy의 채팅 목록에 포커스를 두는 명령이 사용되고, 워크스페이스 2의 경우 Chrome을 여는 명령이 사용됩니다.

Compiz의 화면 오른쪽 가장자리에 마우스를 올리면 연결됩니다.

이것이 가능한가?

답변1

보세요xdotool. get_desktop보기에 현재 데스크탑을 출력합니다.

Unity가 포함된 Ubuntu의 경우 작업 공간이 호출 viewports되고 왼쪽 상단 모서리의 x 및 y 위치에 좌표 형식으로 표시됩니다.

예를 들어,

$ xdotool get_desktop_viewport     
4780 0

해당 정보를 사용하여 현재 어떤 작업 공간에 있는지 파악하고 각 작업 공간별로 명령을 실행할 수 있습니다.

답변2

메모: 더 나은 성능을 위해 답변이 Python으로 다시 작성되었지만 GUI 요소는 없습니다. 섹션을 참조하세요파이썬 버전

쉘 스크립트 버전

소개

아래 스크립트를 사용하면 현재 활성 작업공간에 따라 특정 명령을 실행할 수 있습니다. 키보드 단축키에 바인딩되도록 고안되었습니다. 실제 스크립트 데모는 여기에서 찾을 수 있습니다: https://www.youtube.com/watch?v=oxim3JbeiVM

스크립트 얻기

이 게시물에서 스크립트 소스를 복사하거나 다음 단계를 통해 설치하세요.

  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: [email protected] 
# 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 "$@"

간단한 쉘 스크립트 버전(원래 답변)

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각 뷰포트의 좌표를 결정합니다.

마지막으로, 사례문 옵션에는 공백이 없어야 합니다. 예를 들어 "0,0"작동하지만 "0, 0"작동하지 않습니다.


파이썬 버전

소개

이 버전의 스크립트는 동일한 기능을 수행하지만 단순성과 유용성을 위해 명령줄 인수나 GUI 요소를 포함하지 않습니다. 스크립트는 다음과 같이 사용 가능합니다.Github 요지아래도 마찬가지입니다:

용법:

사용법은 매우 간단합니다.

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: [email protected] 
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 <[email protected]>

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()

마우스 오버 동작:

원래 질문은 화면 오른쪽의 마우스 오버 동작으로 작동하도록 하는 방법에 대해 묻습니다. 키보드 단축키에 연결된 위 스크립트를 사용하는 것이 좋지만 마우스 오버 동작도 가능합니다. 다음은 마우스가 화면 오른쪽 상단에 있는 경우 위의 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()

노트:

명령을 사용하고 출력을 구문 분석하는 쉘 스크립트를 사용하여 유사한 마우스 이벤트 스크립트를 수행할 수 있습니다 xdotool getmouselocation. 이는 다음과 같습니다.

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

관련 정보