突出显示当前鼠标位置


18

我正在运行双屏设置,并且大多数时候都禁用触控板(包括隐藏鼠标指针)。重新启用触控板(并再次显示鼠标指针)时,我已经失去了指针之前所在的位置的信息。

我正在寻找一种突出显示当前鼠标位置的工具(例如,用圆圈)。理想情况下,这将是单个命令在短时间内使圆圈闪烁。

我知道xdotool可以找到当前位置,但是没有突出显示;同样,key-mon不提供此功能。我也读过cairo composition manager提供这种功能的文档,但我想知道是否有一个较小的工具可以实现此功能。

如果没有这样的工具:使用提供的数据,最简单的方法是在光标周围显示这样的圆圈 xdotool getmouselocation

如果这是相关的:我不使用桌面环境,仅使用 xmonad窗口管理器。

Answers:


18

尽管我喜欢Mikeserv的聪明回答,但它的缺点是它将创建一个“窃取”焦点的窗口,并且必须单击该窗口。我也发现这个时间只是略微开始太长:约0.2至0.3秒,也就是稍稍太慢了“平稳”的经验。

我终于开始深入研究XLib,并整理了一个基本的C程序来完成此工作。视觉效果与Windows(XP)具有(从内存中)大致相似。它不是很漂亮,但是可以工作;-)它不会“偷”焦点,几乎是瞬时开始的,您可以单击它。

在此处输入图片说明

您可以使用进行编译cc find-cursor.c -o find-cursor -lX11 -lXext -lXfixes。您可以调整顶部的一些变量来更改大小,速度等。

我将此程序作为程序发布在http://code.arp242.net/find-cursor上。我建议您使用此版本,因为它具有以下脚本所没有的一些改进(例如命令行参数和单击“通过”窗口的功能)。由于其简单性,我按原样保留了以下内容。

/*
 * http://code.arp242.net/find-cursor
 * Copyright © 2015 Martin Tournoij <martin@arp242.net>
 * 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.
 */

将其变成一个在中间带有形状的窗口使鼠标事件通过的难易程度如何我试图把你的例子弄成什么OP是寻找在这里,但与Xlib中没有经验,我最终彻底失败了..
gandalf3

FTR:如何在Ubuntu下进行编译:askubuntu.com/q/801252/31300
Grzegorz Wierzowiecki

@ gandalf3大约一年后,我终于实现了这一目标:-)我没有修改上面的代码片段,因此它可以保持其简单性,我只在github.com/Carpetsmoker/find-cursor上修改了该版本。
马丁·图尔诺伊

@Carpetsmoker就像魅力一样,辉煌!谢谢:)现在让它更新位置以跟随鼠标
。– gandalf3

1
该应用程序显示圆圈,然后退出@AquariusPower,这就是预期的行为。使用它的方法是映射一个组合键来启动它。该-f选项意味着它将在运行时跟随鼠标光标移动,但实际上并没有改变该基本概念(这与所有窗口管理器都不兼容,这就是为什么要使用它)。
Martin Tournoij

6

以下内容可能适合您:

#!/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

这取决于三个工具xvxwdxdotool。前两个是非常通用的X实用程序,第三个我可以肯定地说您已经拥有了。

之后sleep荷兰国际集团一秒钟,xdotool写鼠标的当前坐标其在一个eval友好的标准输出-shell一样的格式:

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

eval相应地设置壳变量和for循环半减去即将待显示的图像的尺寸的从每个$X$Y的值,或者,如果有一个值小于25,将它们设置为0。

xwd 将根窗口转储到管道上 xv,该在鼠标位置附近裁剪为50x50的图像大小,并在没有任何窗口管理器修饰的情况下在小窗口中的当前鼠标光标下显示图像的负片。

最终结果是这样的:

寻找老鼠

...虽然我猜我的鼠标光标没有出现在屏幕截图中。不过请放心,当我拍摄照片时,它就在那里的白盒子正上方。

您可以在图像中看到我也是如何将其编写为Shell函数并使其成为背景的。主要是因为这个原因,里面根本sleep没有-按下RETURN键将滚动终端(如果您已经在底部),并且xwd在终端滚动之前足够快地捕获其屏幕图像-这会使我图片有点负面,我不喜欢它。

无论如何,因为和和一起xv运行-viewonly-quit开关,因此一旦单击鼠标按钮或按下键盘键,它就会消失-但将一直保留到您执行任一个为止。

毫无疑问,您ImageMagick甚至可以xv单独进行甚至更复杂的操作-但我只是在鼠标光标下做了一个小否定框。您可以在xv这里文档和文档为xwdman xwd


1
看起来不错,除了我的发行版(debian)没有提供xv。如果可能的话,我想避免xv自己编译,而让apt软件包管理。
deshtop

1
@deshtop- 如果需要,这一个回购协议。您也可以使用ImageMagick display实用程序执行类似的操作。当然总是有feh。目前,我还没有feh安装它,尽管我尝试了一次或两次,但我不容易想出如何在display没有窗口边框的情况下打开。
mikeserv'2

感谢您的回购,但是对于非官方的存储库我还是有些谨慎。我看看是否可以使用ImageMagick
deshtop 2015年

1
@deshtop-您可能可以。至少您可以配置为xmonad 装饰display将要启动的窗口-否则可以先启动display-iconic然后再使用xdotool其删除其装饰并取消图标化 (或任何所谓的)
mikeserv

这听起来真的很有趣,但是xv似乎在ubuntu 14.04上还是无法运行的(尽管提供了所有dep,它仍未编译),并且display正在打开一个大窗口,我还不知道如何使用feh它,只是扫描了我家中的所有文件(当前路径)寻找图片,很有趣..呵呵是一个编录。
Aquarius Power
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.