//Kali 不显示鼠标,但鼠标能用, 因为某些原因,不能升级虚拟机,
//下面的方法只适合懂点编程的,写一个指针实时跟随鼠标,当做指针就行了
//编译相关
//sudo apt install libcairo2-dev
//g++ mymouse.cpp -o mymouse -lX11 -lcairo -lpthread -std=c++11
#define _XOPEN_SOURCE 700
#define _BSD_SOURCE
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <cairo/cairo-xlib.h>
#include <thread>
#include <chrono>
#include <cstdio>
#include <cstring>
int main() {
Display* display = XOpenDisplay(nullptr);
if (!display) {
fprintf(stderr, "无法打开X11显示连接\n");
return 1;
}
int screen = DefaultScreen(display);
Window root = RootWindow(display, screen);
Visual* visual = DefaultVisual(display, screen);
int depth = DefaultDepth(display, screen);
// 1. 创建无边框、透明、输入穿透的窗口(核心修改)//
XSetWindowAttributes win_attr;
// 窗口背景透明 + 不接收输入事件(鼠标/键盘穿透)//
win_attr.background_pixel = 0;
win_attr.border_pixel = 0;
win_attr.override_redirect = True; // 绕过窗口管理器,无标题栏/边框//
win_attr.event_mask = 0; // 不接收任何事件,避免干扰其他程序//
// 创建窗口(初始位置(0,0),大小足够显示文字即可)//
Window win = XCreateWindow(
display, root,
0, 0, 20, 20, // x,y,width,height
0, depth, InputOutput, visual,
CWBackPixel | CWBorderPixel | CWOverrideRedirect | CWEventMask,
&win_attr
);
// 设置窗口属性:透明 + 始终在顶层 + 输入穿透//
// 1) 设置窗口为透明(忽略背景色)//
Atom wm_transient = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
XChangeProperty(display, win,
XInternAtom(display, "_NET_WM_WINDOW_TYPE_UTILITY", False),
XA_ATOM, 32, PropModeReplace,
(unsigned char*)&wm_transient, 1);
// 2) 设置输入穿透(鼠标事件直接透传给下层窗口)//
Atom input_props = XInternAtom(display, "_NET_WM_BYPASS_COMPOSITOR", False);
long value = 1;
XChangeProperty(display, win, input_props, XA_CARDINAL, 32,
PropModeReplace, (unsigned char*)&value, 1);
Atom wm_input = XInternAtom(display,"WM_INPUT",False);
long input_off = 0;
XChangeProperty(display,win,wm_input,XA_INTEGER,32,PropModeReplace,(unsigned char*)&input_off,1);
// 3) 窗口始终在顶层//
XSetWindowAttributes top_attr;
top_attr.win_gravity = StaticGravity;
XChangeWindowAttributes(display, win, CWWinGravity, &top_attr);
//XSetWindowStackMode(display, win, Above);
XRaiseWindow(display,win);
// 显示窗口//
XMapWindow(display, win);
XFlush(display);
// 2. 创建Cairo表面(绑定到自定义窗口,而非根窗口)//
cairo_surface_t* surface = cairo_xlib_surface_create(
display, win, visual,
20, 20 // 窗口大小,匹配XCreateWindow的尺寸//
);
cairo_t* cr = cairo_create(surface);
int mouse_x = 0, mouse_y = 0;
int child_x = 0, child_y = 0;
Window child;
unsigned int mask;
int offset_x = 3;
int offset_y = 3;
// 主循环:实时更新鼠标位置和文字显示//
while (true) {
// 获取最新鼠标坐标
XQueryPointer(display, root, &root, &child,
&mouse_x, &mouse_y, &child_x, &child_y, &mask);
// 移动窗口到鼠标位置(偏移(10,20)避免文字挡住鼠标指针)//
XMoveWindow(display, win, mouse_x + offset_x, mouse_y + offset_y);
XFlush(display);
// 清屏(透明背景)//
cairo_set_source_rgba(cr, 0, 0, 0, 0);
cairo_paint(cr);
// 绘制鼠标坐标文字(白色粗体)//
cairo_set_source_rgb(cr, 1, 1, 1); // 白色//
cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size(cr, 24);
char text[50];
snprintf(text, sizeof(text), "X: %d, Y: %d", mouse_x, mouse_y);
// 文字绘制在窗口左上角(窗口已跟随鼠标,所以文字也跟随)//
cairo_move_to(cr, 10, 30); // 窗口内偏移,避免文字贴边//
cairo_show_text(cr, text);
// 刷新绘制内容到窗口//
cairo_surface_flush(surface);
cairo_paint(cr);
// 短暂休眠,降低CPU占用(20ms = 50帧/秒,更流畅)//
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
// 资源释放(实际需手动Ctrl+C终止,此处为规范写法)//
cairo_destroy(cr);
cairo_surface_destroy(surface);
XDestroyWindow(display, win);
XCloseDisplay(display);
return 0;
}
2025年12月21日 03点12分
12