q77190858
deepin
2022-03-14 09:32 牛逼牛逼,膜拜大佬
Reply Like 0 View the author
牛逼牛逼,膜拜大佬
大神!大赞👍

膜拜大佬,希望以后多多输出这类型高质量文章
for (auto it = windowRects.rbegin(); it != windowRects.rend(); ++it) {
if (!qFuzzyCompare(1.0, m_pixelRatio) && m_screenCount > 1) {
int x = it->x();
int y = it->y();
- int beforeWidth = 0;
- for (int index = 0; index < m_screenCount; ++index) {
- if (x >= m_screenInfo[index].x && x < (m_screenInfo[index].x + m_screenInfo[index].width)) {
- recordX = static_cast((x - m_screenInfo[index].x) + beforeWidth / m_pixelRatio);
- break;
- }
- beforeWidth += m_screenInfo[index].width;
- }
- int beforeHeight = 0;
- for (int index = 0; index < m_screenCount; ++index) {
- if (y >= m_screenInfo[index].y && y < (m_screenInfo[index].y + m_screenInfo[index].height)) {
- recordY = static_cast((y - m_screenInfo[index].y) + beforeHeight / m_pixelRatio);
+ ScreenInfo info = m_screenInfo[0];
+
+ for ( int index = 0; index < m_screenCount; ++index) {
+ auto si = m_screenInfo[index];
+ if ( x >= si.x && x < si.x + si.width && y >= si.y && y < si.y + si.height) {
+ info = si;
break;
}
- beforeHeight += m_screenInfo[index].height;
}
+ recordX = static_cast((x - info.x) + info.x / m_pixelRatio);
+ recordY = static_cast((y - info.y) + info.y / m_pixelRatio);
} else {
recordX = it->x() - static_cast(screenRect.x() * m_pixelRatio);
recordY = it->y() - static_cast(screenRect.y() * m_pixelRatio);
Popular Ranking
ChangePopular Events
More
出发点
发帖子的时候,发现deepin自带的截屏工具在自己的电脑上工作不正常。确认了一下,自己是最新的版本,确认是一个目前存在的bug了。想着自己怎么的也是一个程序员,改bug最熟练了,而且这应该是一个开源的工具,那么就自己改一改。虽然没有任何的上下文。
俗话说满桶不会响,半桶响叮当。我这个半桶水希望能够记录下来,自己试图解决这样一个bug过程中,遇到的问题。或许其它开发者看到,不说改进,算是帮人蹚雷吧。
bug描述 和 系统配置,见之前的帖子 尝试修好一个bug(一)
寻找问题的出处
一点上下文
在本地编译构建,复现了问题之后,紧接着就是定位bug的位置所在了。为了读者理解通顺,我解释一下我电脑显示器的排列。
一共6台4k显示器,分辨率都是3840x2160,dpi设置是150(放大1.5倍)。换算成等效的分辨率,就是2560x1440(2560 = 3840 / 1.5)。把显示器的位置和大小复合表示,以DisplayPort-5为例,3840x2160+7680+2160。前两个数字是分辨率,有两个数值是相对与拼接复合画面的左上角的偏移量。
一点点分析
根据问题的表现来分析和猜测:
想得太多,还是一边调试代码,一边看好了。
进入源代码
先放一下项目的代码仓库地址。对于qt的项目,首先就看MainWindow代码的逻辑。好家伙,5千行的文件,不愧是c++。硬着头从init开始看把。
先看了一下initMainWindow这个函数。里面有初始化每个屏幕大小和偏移量的逻辑。m_screenInfo 这个变量存了屏幕信息的list。我检查了生成的每一个屏幕信息,对于我的电脑而言,就是6个显示器的参数,确实都是正确的。dpi获取的数值也是
既然不是这里,那就继续找。然后看initAttributes这个函数。发现我的debugger会因为段错误异常退出。从更上层screenshot.cpp里,step into。找到了段错误的位置。
看起来是为了兆芯准备的代码,注释掉,不管。继续往后找。然后倍initShortcut函数强行中断,应该和bug无关,注释掉,继续往后走。
接下来,我被一个名字叫做widthAfterFirst的变量吸引了注意力。这个变量,算出了一个19200的天文数字,看起来不太对。不过和我遇到的bug表现形式来推断,应该不是(窗口的偏移量没有这么大)。虽然看着像有问题,但是依然选择忽略。
然后是一个move的函数。这种移动窗体的函数,我非常感兴趣,因为或许是移动计算逻辑出错。 但是我找不到具体的定义位置。那应该是基类里的方法。看一下DWidget。找到了DWdiget.h
啊?!,还好还好,这个不是完全重命名QWidget。我看看第一个头文件里定义了啥。
呀哈哈…… 看来,这里没有bug相关的信息,我直接去看QWidget文档好了。看了一下,move只是移动框口位置,没有计算逻辑。放过这个move函数了。
柳暗花明又一村
初始化没有看出来什么问题,那只好从信号系统去找问题。至少,每一次重新选择窗体的时候,都会有高亮窗口的变化,那么一定是有事件响应函数的。所以一点一点找,resizeLeft -> eventFilter -> recordX , 诶, 这个recordX变量,看起来就是每次调整高亮窗口的偏移量。打印了一下,发现算出来的值确实不对!!找到问题代码了!!
分析问题的原因
先把计算高亮框体位置的代码逻辑放在下面
这个逻辑中,对于多个显示器,或者缩放率不是1的情况,进行了计算。这里有一个beforeWidth和beforeHeight的计算。是统计,在当前这个显示器的左侧,和上方,的偏移量是多少。
我打印了一下,计算出来的beforeWidth, 发现,对于DisplayPort1(中间下方的显示器)的内容,有7680。仔细看这段代码的逻辑,发现了问题。因为我显示器的排列是3×2,所以,对于DisplayPort1,左侧确实有两块显示器,但是他们的宽度应该只需要计算一次。按照上面的代码,会导致一些显示器的宽高被重复计算了。
解决问题的代码
找到了问题,那就很简单。我不需要知道一台显示器的左侧和上方有几台显示器。确认鼠标所在的显示器,在所在显示器的信息里,就有偏移量,直接用就好了。
下面是更改后的代码
编译,运行,程序可以正确的高亮鼠标所在的窗口了。截图,内容也是高亮区域的内容。问题解决了。
感想和后续
在对qt有基础了解的情况下,寻找问题所在还是比较符合直觉的。一点一点调试,就能够找到问题所在。在周末把这个bug找到并且解决,内心是非常激动的。这是我第一次试图在开源项目上定位和解决问题,比想象中的要容易很多。虽然在开始之前对于项目一无所知,但是按照解决问题的基本流程来走,每一步都还是比较顺畅的。
这个问题虽然解决了,但是,由于没有找到项目的单元测试代码,不知道是否会破坏已有功能。为了保险,还需要进一步人工测试,还有写代码测试。这些,或许需要重构代码,或者调整实现。当然,这些都离不开和项目维护者的沟通。不知道论坛里有没有这个项目的维护人员,以及能否看到这篇帖子。如果联系不上,估计测试完成,就只能直接提交PR了。