Como posso iniciar um aplicativo com um tamanho e posição de janela predefinidos?

19

Eu estou querendo saber se existe alguma maneira de alcançar o efeito dos atalhos Ctrl-Alt-Keypad no Unity usando comandos de terminal? Eu quero um comando que defina uma janela de gui para metade do tamanho da tela, alinhado à esquerda ou à direita.

Como plano de fundo, estou escrevendo um script que é executado após o login. Ele usa o Zenity para perguntar se quero ou não abrir meu ambiente de desenvolvimento (GVim e IPython lado-a-lado). Eu tenho tentado obter duas janelas de mesmo tamanho para esses programas usando set lines= columns= no meu .gvimrc e c.IPythonWidget.width = e c.IPythonWidget.height = no meu ipython_qtconsole_config.py . No entanto, existem problemas associados a essa abordagem.

    
por STim 25.04.2015 / 19:48

6 respostas

15

O que você vai encontrar em

Se você quiser primeiro chamar um aplicativo e, subsequentemente, colocar sua janela em uma posição e tamanho específicos, o tempo entre chamar o aplicativo e no momento em que a janela realmente aparecer , é imprevisível. Se o seu sistema estiver ocupado, pode ser significativamente mais longo do que se estiver ocioso.

Você precisa de uma maneira "inteligente" para garantir que o posicionamento / redimensionamento seja feito (imediatamente) depois que a janela aparecer .

Script para chamar um aplicativo, espere ele aparecer e posicione-o na tela

Com o script abaixo, você pode chamar um aplicativo e definir a posição e o tamanho em que ele deve aparecer com o comando:

<script> <application> <x-position> <y-position> <h-size> <v-size>

Alguns exemplos:

  • Para chamar gnome-terminal e redimensionar sua janela para 50% e colocá-la na metade direita:

    <script> gnome-terminal 840 0 50 100
    

  • Parachamargedit,coloquesuajanelaàesquerdaechamegnome-terminal,coloque-aàdireita(configurandoseuv-size46%paradarumpoucodeespaçoentreasjanelas):

    <script>gedit0046100&&<script>gnome-terminal860046100

  • Para chamar o Inkscape, coloque sua janela no quarto esquerdo / superior da tela:

    <script> inkscape 0 0 50 50
    

Oscriptecomousá-lo

  1. instaleosdoisxdotoolewmctrl.Euuseiambospoisoredimensionamentocomwmctrlpodecausaralgumaspeculiaridadesem(especificamente)Unity.

    sudoapt-getinstallwmctrlsudoapt-getinstallxdotool
  2. Copieoscriptabaixoemumarquivovazio,salve-ocomosetwindow(semextensão)em~/bin;crieodiretório,senecessário.
  3. Torneoscriptexecutável(!)
  4. Sevocêacaboudecriar~bin,execute:source~/.profile
  5. Testeoscriptcomocomando(porexemplo,

    setwindowgnome-terminal0050100

    Emoutraspalavras:

    setwindow<application><horizontal-position><vertical-position><horizontal-size(%)><vertical-size(%)>

Setudofuncionarbem,useocomandoondevocêprecisar.

Oscript

#!/usr/bin/env python3 import subprocess import time import sys app = sys.argv[1] get = lambda x: subprocess.check_output(["/bin/bash", "-c", x]).decode("utf-8") ws1 = get("wmctrl -lp"); t = 0 subprocess.Popen(["/bin/bash", "-c", app]) while t < 30: ws2 = [w.split()[0:3] for w in get("wmctrl -lp").splitlines() if not w in ws1] procs = [[(p, w[0]) for p in get("ps -e ww").splitlines() \ if app in p and w[2] in p] for w in ws2] if len(procs) > 0: w_id = procs[0][0][1] cmd1 = "wmctrl -ir "+w_id+" -b remove,maximized_horz" cmd2 = "wmctrl -ir "+w_id+" -b remove,maximized_vert" cmd3 = "xdotool windowsize --sync "+procs[0][0][1]+" "+sys.argv[4]+"% "+sys.argv[5]+"%" cmd4 = "xdotool windowmove "+procs[0][0][1]+" "+sys.argv[2]+" "+sys.argv[3] for cmd in [cmd1, cmd2, cmd3, cmd4]: subprocess.call(["/bin/bash", "-c", cmd]) break time.sleep(0.5) t = t+1

O que faz

Quando o script é chamado, ele:

  1. inicia o aplicativo
  2. fica de olho na lista de janelas (usando wmctrl -lp )
  3. se uma nova janela aparecer, ele verifica se a nova janela pertence ao aplicativo chamado (usando ps -ef ww , comparando o pid da janela ao pid do aplicativo)
  4. se assim for, define o tamanho e posição, de acordo com seus argumentos. No caso de um aplicativo não "aparecer" dentro de appr. 15 segundos, o script assume que o aplicativo não será executado devido a um erro. O script então termina para evitar a espera pela nova janela infinitamente.

Questão secundária

No Unity, quando você (re) posiciona e (re) dimensiona uma janela com wmctrl ou xdotool , a janela sempre manterá uma pequena margem para as bordas da tela, a menos que você a defina para 100%. Você pode ver isso na imagem (3) acima; enquanto a janela inkscape foi colocada em x position 0, você ainda pode ver uma pequena diferença entre o Iniciador Unity e a janela inkscape .

    
por Jacob Vlijm 26.04.2015 / 11:20
4

Eu criei um aplicativo chamado Worksets (no github ) para o Unity, que permite fazer isso facilmente através de uma interface gráfica do usuário - É grátis e de código aberto.

É basicamente um wrapper para as soluções wmctrl e xdotool listadas como respostas aqui, e fornece uma maneira fácil de fazer e salvar rapidamente essas configurações.

    
por Tumult 10.07.2017 / 07:07
3

O comando real que você quer é algo como

wmctrl -r :ACTIVE: -b add,maximized_vert && 
wmctrl -r :ACTIVE: -e 0,0,0,$HALF,-1

Isso fará com que a janela atual ocupe metade da tela (altere $HALF para as dimensões da sua tela) e clique no lado esquerdo. Para encaixar à direita, use

wmctrl -r :ACTIVE: -b add,maximized_vert && 
wmctrl -r :ACTIVE: -e 0,$HALF,0,$HALF,-1 

Você também pode jogar com wmctrl para obter o ID das janelas em que está interessado, em vez de usar :ACTIVE: . Eu não posso ajudar lá, desde que depende das janelas em questão. Dê uma olhada em man wmctrl para mais.

Eu escrevi um roteiro para isso. Eu não uso o Unity, então não posso garantir que funcionará com ele, mas não vejo razão para não. Precisa de wmctrl , xdpyinfo e disper a instalar:

sudo apt-get install wmctrl x11-utils disper

Em seguida, salve o script abaixo como ~/bin/snap_windows.sh , torne-o executável com chmod a+x ~/bin/snap_windows.sh e você pode executar

snap_windows.sh r

Para encaixar no lado direito. Use l para o lado esquerdo e nenhum argumento para maximizar a janela. Note que ele é executado na janela atual, então você precisará atribuir um atalho para ele se quiser que ele seja executado em qualquer coisa, exceto no terminal.

O script é um pouco mais complicado do que o que você pediu, porque eu o escrevi para trabalhar em configurações de monitor único e duplo.

#!/usr/bin/env bash

## If no side has been given, maximize the current window and exit
if [ ! $1 ]
then
    wmctrl -r :ACTIVE: -b toggle,maximized_vert,maximized_horz
    exit
fi

## If a side has been given, continue
side=$1;
## How many screens are there?
screens='disper -l | grep -c display'
## Get screen dimensions
WIDTH='xdpyinfo | grep 'dimensions:' | cut -f 2 -d ':' | cut -f 1 -d 'x'';
HALF=$(($WIDTH/2));

## If we are running on one screen, snap to edge of screen
if [ $screens == '1' ]
then
    ## Snap to the left hand side
    if [ $side == 'l' ]
    then
        ## wmctrl format: gravity,posx,posy,width,height
    wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,0,0,$HALF,-1
    ## Snap to the right hand side
    else
    wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,$HALF,0,$HALF,-1 
    fi
## If we are running on two screens, snap to edge of right hand screen
## I use 1600 because I know it is the size of my laptop display
## and that it is not the same as that of my 2nd monitor.
else
    LAPTOP=1600; ## Change this as approrpiate for your setup.
    let "WIDTH-=LAPTOP";
    SCREEN=$LAPTOP;
    HALF=$(($WIDTH/2));
    if [ $side == 'l' ]
    then
        wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,$LAPTOP,0,$HALF,-1
    else
    let "SCREEN += HALF+2";
    wmctrl -r :ACTIVE: -b add,maximized_vert && wmctrl -r :ACTIVE: -e 0,$SCREEN,0,$HALF,-1;
    fi
fi
    
por terdon 25.04.2015 / 20:35
3

Você pode fazer isso usando xdotool .

Para instalar o xdotool , você pode executar:

sudo apt-get update && sudo apt-get install xdotool

Em seguida, para enviar um pressionamento de tecla Ctrl + Alt + para a janela X do terminal, você pode executar:

xdotool key Ctrl+Alt+<keypad_key_value>

* < keypad_key_value > = valor da chave do teclado na lista abaixo

Para executar um programa GUI e enviar o pressionamento de tecla para sua janela X (que neste caso é a janela ativa no momento da execução do comando xdotool ), você pode executar:

<command> && window="$(xdotool getactivewindow)" xdotool key --delay <delay> --window "$window" <keypad_key_value>

* < comando > = comando que abre a janela para a qual você deseja enviar o pressionamento de tecla; < atraso > = tempo para esperar em milissegundos antes de enviar o toque de tecla; < keypad_key_value > = valor da chave do teclado na lista abaixo

Observe que na maioria dos casos você precisará executar o comando que está emitindo como um processo independente (por exemplo, executando nohup <command> & em vez de <command> no exemplo acima), caso contrário, xdotool won ' t ser executado até a execução do <command> estar completa.

Além disso, você precisará definir algum atraso, caso contrário, o pressionamento de tecla será enviado antes que a janela de destino seja totalmente carregada em X (um atraso em torno de 500ms deve ser feito).

Os valores possíveis para <keypad_key_value> são:

  • 0 : 90
  • 1 : 87
  • 2 : 88
  • 3 : 89
  • 4 : 83
  • 5 : 84
  • 6 : 85
  • 7 : 79
  • 8 : 80
  • 9 : 81

Como regra geral, para descobrir o valor de qualquer tecla no teclado dentro do ambiente X , pode-se executar xev e pressionar a tecla para gerar seu valor dentro do terminal.

    
por kos 25.04.2015 / 19:55
1

Eu não tenho o representante para comentar diretamente no excelente post de Jacob Vlijm, mas modifiquei o script para permitir iniciar um aplicativo com argumentos (necessário usar setwindow com gedit --new-window ). Mudança:

if app in p and w[2] in p] for w in ws2]

para:

if app.split()[0] in p and w[2] in p] for w in ws2]
    
por D. Hancock 13.05.2016 / 19:31
0

Eu brinquei com o script de Terdon acima e adicionei algumas coisas novas (capacidade de selecionar o monitor e definir a altura de cada monitor). Seria extensível para adicionar mais monitores, eu acho. Espero que outros achem útil.

Sintaxe básica:

prog_name monitor l/r/m window_name (optional)

Onde prog_name é o que você salvou este código como; monitor é o número do monitor, e. 1 ou 2; l / r / m é esquerdo ou direito ou máximo; e window_name é o nome (ou uma fração de seu nome) da janela de destino.

Por exemplo:

setwindow 1 m chrome

Script de bash

#!/usr/bin/env bash
set -e
#######################-    Early Definitions    -#######################

snap () {
    wmctrl -r ${WIN} -b toggle,add,maximized_vert && wmctrl -r ${WIN} -e 0,${WINX},0,${WINWIDTH},${WINHEIGHT}
    }

DISPLAYWIDTH='xdpyinfo | grep 'dimensions:' | cut -f 2 -d ':' | cut -f 1 -d 'x'';       ## Get screen dimensions
LEFTSCREENWIDTH=1024    ## user set
LEFTSCREENHEIGHT=720    ## user set
RIGHTSCREENHEIGHT=960   ## user set
let "RIGHTSCREENWIDTH=(DISPLAYWIDTH-LEFTSCREENWIDTH)"

#############################-    Logic    -#############################

if [ ! ${3} ]; then
    WIN=":ACTIVE:"
else
    WIN=${3}
fi
case ${1} in
    1)  # monitor one
        LEFT=0
        WINHEIGHT=${LEFTSCREENHEIGHT}
        let "WINWIDTH=LEFTSCREENWIDTH/2"
    ;;
    2)  # monitor two
        let "LEFT=LEFTSCREENWIDTH"
        WINHEIGHT=${RIGHTSCREENHEIGHT}
        let "WINWIDTH=RIGHTSCREENWIDTH/2"
    ;;
    "") # error please select a monitor
        echo "please select a monitor (1 or 2)"
        exit 0
    ;;
esac
case ${2} in
    l|L)
        WINX=${LEFT}
        snap
    ;;
    r|R)
        let "WINX=LEFT+WINWIDTH"
        snap
    ;;
    ""|m|M)
        WINX=${LEFT}
        let "WINWIDTH=WINWIDTH*2"
        snap
    ;;
esac

exit 0
    
por Philosopher Rex 02.07.2018 / 11:49