Destacar a posição atual do mouse

18

Estou executando uma configuração de tela dupla e meu trackpad fica desativado a maior parte do tempo (o que inclui ocultar o ponteiro do mouse). Ao reativar o trackpad (e exibir o ponteiro do mouse novamente), perdi a noção de onde estava o ponteiro antes.

Estou procurando uma ferramenta para destacar a posição atual do mouse (por exemplo, por um círculo). Idealmente, esse seria um único comando que mostraria o círculo por um curto período de tempo.

Estou ciente de que xdotoolpode encontrar a posição atual, mas não há destaque; Além disso, key-monnão fornece essa funcionalidade. Eu também li que cairo composition managerfornece essa funcionalidade, mas estou me perguntando se existe uma ferramenta menor para conseguir isso.

Caso não exista essa ferramenta: Qual é a maneira mais fácil de exibir um círculo em torno do cursor usando os dados fornecidos por xdotool getmouselocation ?

Caso isso seja relevante: não uso um ambiente de área de trabalho, apenas o xmonadgerenciador de janelas.

deshtop
fonte

Respostas:

18

Embora eu goste da resposta de Mikeserv por sua esperteza, ela tem a desvantagem de criar uma janela que "rouba" o foco e precisa ser clicada. Também acho que demora um pouco demais para iniciar: cerca de 0,2 a 0,3 segundos, o que é um pouco lento demais para uma experiência "suave".

Finalmente cheguei a explorar o XLib e juntei um programa C básico para fazer isso. O efeito visual é aproximadamente semelhante ao que o Windows (XP) possui (da memória). Não é muito bonito, mas funciona ;-) Não "rouba" o foco, começa quase instantaneamente e você pode clicar em "através" dele.

insira a descrição da imagem aqui

Você pode compilá-lo com cc find-cursor.c -o find-cursor -lX11 -lXext -lXfixes. Existem algumas variáveis ​​no topo que você pode ajustar para alterar o tamanho, velocidade, etc.

Lancei isso como um programa em http://code.arp242.net/find-cursor . Eu recomendo que você use esta versão, pois ela possui algumas melhorias que o script abaixo não possui (como argumentos da linha de comando e capacidade de clicar em "através" da janela). Deixei o abaixo como está devido à sua simplicidade.

/*
 * http://code.arp242.net/find-cursor
 * Copyright © 2015 Martin Tournoij <[email protected]>
 * See below for full copyright
 */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>


// Some variables you can play with :-)
int size = 220;
int step = 40;
int speed = 400;
int line_width = 2;
char color_name[] = "black";


int main(int argc, char* argv[]) {
    // Setup display and such
    char *display_name = getenv("DISPLAY");
    if (!display_name) {
        fprintf(stderr, "%s: cannot connect to X server '%s'\n", argv[0], display_name);
        exit(1);
    }

    Display *display = XOpenDisplay(display_name);
    int screen = DefaultScreen(display);

    // Get the mouse cursor position
    int win_x, win_y, root_x, root_y = 0;
    unsigned int mask = 0;
    Window child_win, root_win;
    XQueryPointer(display, XRootWindow(display, screen),
        &child_win, &root_win,
        &root_x, &root_y, &win_x, &win_y, &mask);

    // Create a window at the mouse position
    XSetWindowAttributes window_attr;
    window_attr.override_redirect = 1;
    Window window = XCreateWindow(display, XRootWindow(display, screen),
        root_x - size/2, root_y - size/2,   // x, y position
        size, size,                         // width, height
        0,                                  // border width
        DefaultDepth(display, screen),      // depth
        CopyFromParent,                     // class
        DefaultVisual(display, screen),     // visual
        CWOverrideRedirect,                 // valuemask
        &window_attr                        // attributes
    );
    XMapWindow(display, window);
    XStoreName(display, window, "find-cursor");

    XClassHint *class = XAllocClassHint();
    class->res_name = "find-cursor";
    class->res_class = "find-cursor";
    XSetClassHint(display, window, class);
    XFree(class);

    // Keep the window on top
    XEvent e;
    memset(&e, 0, sizeof(e));
    e.xclient.type = ClientMessage;
    e.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", False);
    e.xclient.display = display;
    e.xclient.window = window;
    e.xclient.format = 32;
    e.xclient.data.l[0] = 1;
    e.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_STAYS_ON_TOP", False);
    XSendEvent(display, XRootWindow(display, screen), False, SubstructureRedirectMask, &e);

    XRaiseWindow(display, window);
    XFlush(display);

    // Prepare to draw on this window
    XGCValues values = { .graphics_exposures = False };
    unsigned long valuemask = 0;
    GC gc = XCreateGC(display, window, valuemask, &values);

    Colormap colormap = DefaultColormap(display, screen);
    XColor color;
    XAllocNamedColor(display, colormap, color_name, &color, &color);
    XSetForeground(display, gc, color.pixel);
    XSetLineAttributes(display, gc, line_width, LineSolid, CapButt, JoinBevel);

    // Draw the circles
    for (int i=1; i<=size; i+=step) { 
        XDrawArc(display, window, gc,
            size/2 - i/2, size/2 - i/2,   // x, y position
            i, i,                         // Size
            0, 360 * 64);                 // Make it a full circle

        XSync(display, False);
        usleep(speed * 100);
    }
    XFreeGC(display, gc);
    XCloseDisplay(display);
}


/*
 *  The MIT License (MIT)
 * 
 *  Copyright © 2015 Martin Tournoij
 * 
 *  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.
 */
Martin Tournoij
fonte
Quão fácil seria transformar isso em uma janela com um buraco no meio para que os eventos do mouse passassem? Tentei transformar o seu exemplo em algo parecido com o que o OP está procurando aqui , mas ter nenhuma experiência com xlib, acabei irremediavelmente perdido ..
gandalf3
FTR: Como compilá-lo no Ubuntu: askubuntu.com/q/801252/31300
Grzegorz Wierzowiecki
@ gandalf3 Quase um ano depois, finalmente consegui implementar isso :-) Não modifiquei o trecho acima para manter sua simplicidade, apenas modifiquei a versão em github.com/Carpetsmoker/find-cursor .
Martin Tournoij 24/03
@Carpetsmoker Funciona como um encanto, brilhante! Obrigado por isso :) Agora para tê-lo atualizar posição para seguir o mouse ..
gandalf3
1
O aplicativo mostra o círculo e sai do @AquariusPower, então esse é o comportamento esperado. A maneira de usá-lo é mapear uma combinação de teclas para iniciá-lo. A -fopção significa que ele seguirá o cursor do mouse durante a execução , mas na verdade não altera esse conceito básico (isso não é compatível com todos os gerenciadores de janelas, e é por isso que é uma opção).
Martin Tournoij 6/06
6

Provavelmente, o seguinte funcionará para você:

#!/bin/sh
unset X Y; sleep 1
eval "$(xdotool getmouselocation -shell 2>/dev/null)"
for n in X Y; do  : "$(($n-=$n>25?25:$n))"; done
xwd -root -silent |
xv -    -crop "$X" "$Y" 50 50 \
        -geometry "50x50+$X+$Y" \
        -nodecor -viewonly -rv -quit

Depende dos três utilitários xv, xwde xdotool. Os dois primeiros são Xutilitários muito comuns e o terceiro tenho quase certeza de que você já possui.

Após sleepum segundo, xdotoolgrava as coordenadas atuais do mouse no stdout em um -shellformato compatível com a avaliação , como:

X=[num]
Y=[num]
windowID=[num]

evaldefine as variáveis do shell Nesse sentido, e o forsubtrai laço metade do tamanho da imagem logo-a-ser-exibido de cada uma $Xe $Yvalores 's ou, se qualquer valor for inferior a 25, define-los a 0.

xwddespeja a janela raiz sobre um tubo para xv, que corta ao redor da localização do mouse para um tamanho de imagem de 50x50 e exibe um negativo da imagem sob o cursor atual do mouse em uma pequena janela sem qualquer decoração do gerenciador de janelas.

O resultado final é algo como isto:

findmouse

... embora eu ache que o cursor do mouse não apareça nas capturas de tela. Tenha certeza, porém, estava logo acima da caixa branca quando tirei a foto.

Você pode ver na imagem como eu também escrevi como uma função shell e a coloquei em segundo plano. É principalmente por esse motivo que existe um sleep- pressione a RETURNtecla para rolar o terminal se você já estiver na parte inferior e xwdfoi rápido o suficiente para capturar a imagem da tela antes do terminal rolar - o que compensaria minha negativo na imagem um pouco e eu não gostei.

De qualquer forma, como xvé executado com os botões -viewonlye -quit, ele desaparecerá assim que um botão do mouse for pressionado ou uma tecla do teclado for pressionada - mas permanecerá até que você o faça.

Sem dúvida, você poderia fazer coisas muito mais elaboradas com ImageMagickou mesmo xvsozinho - mas eu apenas fiz uma pequena caixa negativa sob o cursor do mouse. Você pode encontrar os xvdocumentos aqui e os documentos xwdem man xwd.

mikeserv
fonte
1
Parece bom, exceto pelo fato de que minha distribuição (debian) não fornece xv. Se possível, gostaria de evitar a compilação xvpor conta própria e deixar aptlidar com o gerenciamento de pacotes.
Deshtop 10/02/2015
1
@ dtoptop - aqui está um repo, se você quiser. Você também pode provavelmente fazer coisas semelhantes com o displayutilitário ImageMagick . E é claro que sempre existe feh. Eu não tinha fehinstalado no momento em que escrevi isso e, apesar de ter tentado uma ou duas vezes, não conseguia descobrir com facilidade como displayabrir sem bordas com janelas.
mikeserv
Obrigado pelo repo, mas sou um pouco cauteloso com repositórios não oficiais. Vou ver se consigo usar o ImageMagick
deshtop 10/02/2015
1
@ deshtop - você provavelmente pode. No mínimo, você pode configurar xmonad não para decorar a displayjanela que isso iria lançar - ou então você pode lançar displaycomo -iconicentão usar xdotoolpara remover as suas decorações e uniconify (ou seja lá o que é chamado) -lo.
mikeserv
isso parece realmente interessante, mas xvparece que não existe no ubuntu 14.04 (não estava compilando apesar de todos os deps terem sido fornecidos) e displayestá abrindo uma grande janela, e ainda não tenho idéia de como usá- fehlo, apenas digitalizei todos os arquivos da minha casa (caminho atual) procurando imagens engraçadas .. hehe é um catalogador.
Potência de Aquário