Barrier 的卡顿问题解决

记录一下barrier的卡顿问题解决过程

在自己家里有一台老旧的笔记本(使用了固态,和安装了ubuntu 24.04, 在焕发第二春) 另外有一个台式机(win 11),使用了小米的24英寸的显示器

两台电脑之间希望可以使用barrier来共享键盘和鼠标

因为barrier属于开源软件,所以出现问题可以在社区中寻找答案。

在使用两台设备共享键盘和鼠标时,发现在移动到client端的屏幕时,总是出现了鼠标不跟手的情况,看起来一卡一卡的。

开启调试日志

查看日志中的信息发现

shell 复制代码
[2025-08-07T22:23:51] DEBUG2: event: MotionNotify 924,568  
[2025-08-07T22:23:51] DEBUG2: warped to 960,540  
[2025-08-07T22:23:51] DEBUG2: event: MotionNotify 924,568  
[2025-08-07T22:23:51] DEBUG2: warped to 960,540  
[2025-08-07T22:23:51] DEBUG2: event: MotionNotify 960,540  
[2025-08-07T22:23:51] DEBUG2: onMouseMoveSecondary -5,+5  
[2025-08-07T22:23:51] DEBUG2: move on pc to 538,451  

发现触发的鼠标移动事件,多个事件触发,才发送了一次给远端,所以问题的根因肯定在这里。

根据代码寻找根因:

cpp 复制代码
void
XWindowsScreen::onMouseMove(const XMotionEvent& xmotion)
{
	LOG((CLOG_DEBUG2 "event: MotionNotify %d,%d", xmotion.x_root, xmotion.y_root));

	// compute motion delta (relative to the last known
	// mouse position)
	SInt32 x = xmotion.x_root - m_xCursor;
	SInt32 y = xmotion.y_root - m_yCursor;

	// save position to compute delta of next motion
	m_xCursor = xmotion.x_root;
	m_yCursor = xmotion.y_root;

	if (xmotion.send_event) {
		// we warped the mouse.  discard events until we
		// find the matching sent event.  see
		// warpCursorNoFlush() for where the events are
		// sent.  we discard the matching sent event and
		// can be sure we've skipped the warp event.
		XEvent xevent;
		char cntr = 0;
		do {
            m_impl->XMaskEvent(m_display, PointerMotionMask, &xevent);
			if (cntr++ > 10) {
				LOG((CLOG_WARN "too many discarded events! %d", cntr));
				break;
			}
		} while (!xevent.xany.send_event);
		cntr = 0;
	}
	else if (m_isOnScreen) {
		// motion on primary screen
		sendEvent(m_events->forIPrimaryScreen().motionOnPrimary(),
							MotionInfo::alloc(m_xCursor, m_yCursor));
	}

发现上方有一些判断条件,核心与warpCursorNoFlush相关

cpp 复制代码
void
MSWindowsScreen::warpCursorNoFlush(SInt32 x, SInt32 y)
{
    // send an event that we can recognize before the mouse warp
    PostThreadMessage(GetCurrentThreadId(), BARRIER_MSG_PRE_WARP, x, y);

    // warp mouse.  hopefully this inserts a mouse motion event
    // between the previous message and the following message.
    SetCursorPos(x, y);

    // check to see if the mouse pos was set correctly
    POINT cursorPos;
    GetCursorPos(&cursorPos);

    // there is a bug or round error in SetCursorPos and GetCursorPos on
    // a high DPI setting. The check here is for Vista/7 login screen.
    // since this feature is mainly for client, so only check on client.
    if (!isPrimary()) {
        if ((cursorPos.x != x) && (cursorPos.y != y)) {
            LOG((CLOG_DEBUG "SetCursorPos did not work; using fakeMouseMove instead"));
            LOG((CLOG_DEBUG "cursor pos %d, %d expected pos %d, %d", cursorPos.x, cursorPos.y, x, y));
            // when at Vista/7 login screen, SetCursorPos does not work (which could be
            // an MS security feature). instead we can use fakeMouseMove, which calls
            // mouse_event.
            // IMPORTANT: as of implementing this function, it has an annoying side
            // effect; instead of the mouse returning to the correct exit point, it
            // returns to the center of the screen. this could have something to do with
            // the center screen warping technique used (see comments for onMouseMove
            // definition).
            fakeMouseMove(x, y);
        }
    }

    // yield the CPU.  there's a race condition when warping:
    //   a hardware mouse event occurs
    //   the mouse hook is not called because that process doesn't have the CPU
    //   we send PRE_WARP, SetCursorPos(), send POST_WARP
    //   we process all of those events and update m_x, m_y
    //   we finish our time slice
    //   the hook is called
    //   the hook sends us a mouse event from the pre-warp position
    //   we get the CPU
    //   we compute a bogus warp
    // we need the hook to process all mouse events that occur
    // before we warp before we do the warp but i'm not sure how
    // to guarantee that.  yielding the CPU here may reduce the
    // chance of undesired behavior.  we'll also check for very
    // large motions that look suspiciously like about half width
    // or height of the screen.
    ARCH->sleep(0.0);

    // send an event that we can recognize after the mouse warp
    PostThreadMessage(GetCurrentThreadId(), BARRIER_MSG_POST_WARP, 0, 0);
}

我们看到了核心的关键问题,BUG

cpp 复制代码
    // there is a bug or round error in SetCursorPos and GetCursorPos on
    // a high DPI setting. The check here is for Vista/7 login screen.
    // since this feature is mainly for client, so only check on client.

所以属于高DPI的设置中,这个SetCursorPos可能不准确,那么我们需要设置兼容性

在windows上右击barrier, 找到属性,兼容性,更改高DPI设置

选中替代高DPI缩放行为, 切换为系统增强

恢复正常.

相关推荐
uzong13 小时前
技术管理者,什么是 high level 的事情
程序员
databook17 小时前
当AI学会编程,我们还能做什么
人工智能·程序员·ai编程
两万五千个小时18 小时前
AI Agent 能力分级:从工具到 AGI
人工智能·程序员·架构
陈随易1 天前
站在普通开发者的角度,我觉得 RollCode 更像是“把 H5 交付这件事重新捋顺了”
前端·后端·程序员
文心快码BaiduComate1 天前
Comate内置模型已支持 MiniMax-M2.7!
设计模式·程序员·前端框架
陈随易2 天前
AI时代,说点心里话
前端·后端·程序员
CoovallyAIHub2 天前
Django 大佬亲授:8 个 Coding Agent 工程模式,重新定义程序员价值
程序员·测试·代码规范
NineData2 天前
NineData 新增支持 MySQL 到 openGauss PostgreSQL 兼容版数据复制链路
数据库·mysql·程序员
陈随易2 天前
MoonBit访谈:MoonBit开发moonclaw实现“养虾”自由
前端·后端·程序员