admin管理员组

文章数量:1558697

最近一个时期可以看到我的博客文章都是围绕系统截屏展开的,从Spectale到FlameShot再到X11/Xlib,及至最近的libX11,都是在设法找到工作中遇到的一个比较严重的Bug的根源——截屏的时候截取到的(有时甚至很多时候)不是当前屏幕的内容。问题的细节及复现过程描述如下:

问题细节

一开始的时候系统中只有Spectacle,有些人在使用飞书截屏的时候发现截取的屏幕并不是当前的屏幕。进而不使用飞书、而直接通过键盘的“截屏”按键(笔者电脑是Fn+PrtSrc)发现反复截屏后也会出现同样问题(截屏按键调用的是Spectacle),于是将此问题上报。

笔者在进行测试时,将问题现象更进一步细化。使用飞书截屏的时候非常容易复现,而不使用飞书的时候概率低得多。一度以为是飞书截屏导致了问题,直到有一次完全不启动飞书,通过截屏键反复截屏,最终也复现了问题,这才确定飞书只是问题的催化剂,而并不是问题的根因。

为了验证是否是Spectacle自身的问题,使用了另外一个截屏工具——Flameshot。测试中发现Flameshot截屏出现问题的概率远高于Spectacle,基本上几次就会出现。

由于Spectacle和Flameshot都是基于Qt的,为了排除Qt的影响,写了一个基于Xlib的XWindow程序,完全与Qt无关,结果经过测试,问题现象仍然相同。

而且不论是Spectacle、Flameshot还是Xlib,重启后的几次一般不出问题,但几次之后一旦出现问题,基本上就一直出现同样的问题了(偶尔会消失,但很快又出现问题)。还有一点,有时感觉上是截取的几秒之前的屏幕;而更多时候一旦出现问题,似乎是掉进了一个环形缓冲,截取的内容是循环出现的。

从现象上分析,应该是图层的内容合成有问题,也有可能是获取的屏幕内容的序列不对。可能是Xorg的问题,也可能是Compositor的问题,还可能是显卡等相关驱动的问题。

问题探索

问题探索的过程无需多说了,可以参见之前的一系列文章。最终由应用一直分析到了上一篇文章,即《X11 Xlib截屏问题及深入分析五 —— XOpenDisplay函数源码分析(2)》。这只是冰山一角,再往下分析,需要研究Xlib、Xorg0Server、Xcb、显卡驱动等等内容……

问题解决

在百度搜索关键字“xorg 截屏”,无意间发现了解决方法!在此要特别非常感谢以下链接中博主分享的内容:

解决kde/flameshot/spectacle on x11 截屏错乱问题 - oaksharks - 博客园

这篇博客中提到的问题和我实际遇到的完全一致,提供的解决方法也完全有效。应该说,如果没有这篇文章,至少还需要几个月甚至空拍是半年的时间才能从源码上分析清楚,那时候黄花菜都凉了……

现将以上博客中提到的解决方法,结合我实际操作的过程记录在此,供后来同样遇到此问题的人参考,为他们提供方便,无需重走我的复杂而艰辛的探索过程。

先把原贴全部贴出来:

解决kde/flameshot/spectacle on x11 截屏错乱问题

现象:

截屏截不到应用,一进入截图页面应用就跳转,要么跳转到其他应用,要不跳转到已经关闭的应用。不管是flameshot或者spectacle 都是这样,其他用户发现的这个问题参考:

  •     https://bbs.archlinuxcn/viewtopic.php?id=12182
  •     https://github/flameshot-org/flameshot/issues/1677

原因以及解决建议:

原因: x11 使用了 intel的驱动导致的。
建议: 卸载intel的驱动,使用其他驱动代替。

解决过程:

卸载xf86-video-intel并确保目录/etc/X11/xorg.conf.d/没有关于intel的配置
 

sudo pacman -Rns xf86-video-intel

ls -l /etc/X11/xorg.conf.d/  # 检查此目录没有关于intel的配置

卸载后重启卡开机界面黑屏了。切换到tty2,按ctl+alt+f2 手动启动x:

startx

根据报错日志查看,/var/log、Xorg.0.log 发现日志提示 Failed to load driver intel,推测应该是X的配置中是用了intel的驱动,然后由被卸载了导致的,查看配置文件 /etc/X11/xorg.conf:

...
Section "Device"
    Identifier     "Device0"
    Driver         "intel"
    VendorName     "Intel Corporation"
    BusID          "PCI:0:2:0"
EndSection

...

X的配置文件中显示显卡设备用的是intel的Driver。

在https://wiki.archlinux/title/Intel_graphics#Installation 中看到:

  •     安装了mesa 这个包就有驱动了。
  •     一般不推荐使用xf86-video-intel可以使用modesetting 这个驱动代替。

一个可行的方法是把"Device"中的"Driver"改成"modesetting",我是重新生成了一下X的配置文件:
 

sudo mv /etc/X11/xorg.conf /etc/X11/xorg.conf.bak
sudo systemctl stop sddm  # 必须在x停止的情况下才能重新生成配置文件,通过停掉sddm 关闭X
sudo xorg -configure # 生成配置文件到 /root/xorg.conf.new

sudo mv /root/xorg.conf.new /etc/X11/xorg.conf

检查新生成的文件:

....
Section "Device"
        Identifier  "Card0"
        Driver      "modesetting"
        BusID       "PCI:0:2:0"
EndSection

...

新的配置文件已经不在使用intel驱动了,重启。
重启发现磁盘clean日志之后直接就黑屏了,再切换到tty2,查看系统日志:

jounalctl -f

日志中提示是关于nouveau的错误。查看当前是否加载了这个模块:

lsmod |grep nouveau

由于不打算使用nvidia显卡,直接屏蔽这个驱动,添加配置文件 /etc/modprobe.d/blacklist_nouveau.conf,内容:

blacklist nouveau

options nouveau modeset=0

重启,正常启动,也不在加载nouveau模块,flameshot功能正常了。

参考:

    https://bbs.archlinuxcn/viewtopic.php?id=12182
    https://github/flameshot-org/flameshot/issues/1677
    https://wiki.archlinux/title/Flameshot
    https://wiki.archlinux/title/Intel_graphics#Installation

对照以上文章中的解决过程,列出笔者实际的解决过程:

1. 通过Ctrl+Alt+F2/F3/F4/F5/F6打开控制台,输入root用户名和密码,登录

2. 将/etc/X11/xorg.conf.d/20-intel

root [ ~ ]# mv /etc/X11/xorg.conf.d/20-intel.conf /etc/X11/xorg.conf.d/20-intel.conf.bak

3. 停止sddm(由于笔者的/etc/X11/下并没有xorg.conf文件,因此不需要备份原始文件)

systemctl stop sddm

 4. 生成配置文件

root [ ~ ]# Xorg -configure

5. 重命名配置文件

root [ ~ ]# mv /root/xorg.conf.new /etc/X11/xorg.conf

xorg.conf初始文件内容如下:

Section "ServerLayout"
        Identifier     "X Configured"
        Screen      0  "Screen0" 0 0
        InputDevice    "Mouse0" "CorePointer"
        InputDevice    "Keyboard0" "CoreKeyboard"
EndSection

Section "Files"
        ModulePath   "/usr/lib/xorg/modules"
        FontPath     "/usr/share/fonts/X11/misc"
        FontPath     "/usr/share/fonts/X11/TTF"
        FontPath     "/usr/share/fonts/X11/OTF"
        FontPath     "/usr/share/fonts/X11/Type1"
        FontPath     "/usr/share/fonts/X11/100dpi"
        FontPath     "/usr/share/fonts/X11/75dpi"
EndSection

Section "Module"
        Load  "glx"
EndSection

Section "InputDevice"
        Identifier  "Keyboard0"
        Driver      "kbd"
EndSection

Section "InputDevice"
        Identifier  "Mouse0"
        Driver      "mouse"
        Option      "Protocol" "auto"
        Option      "Device" "/dev/input/mice"
        Option      "ZAxisMapping" "4 5 6 7"
EndSection

Section "Monitor"
        Identifier   "Monitor0"
        VendorName   "Monitor Vendor"
        ModelName    "Monitor Model"
EndSection

Section "Device"
        ### Available Driver options are:-
        ### Values: <i>: integer, <f>: float, <bool>: "True"/"False",
        ### <string>: "String", <freq>: "<f> Hz/kHz/MHz",
        ### <percent>: "<f>%"
        ### [arg]: arg optional
        #Option     "Accel"                     # [<bool>]
        #Option     "AccelMethod"               # <str>
        #Option     "Backlight"                 # <str>
        #Option     "CustomEDID"                # <str>
        #Option     "DRI"                       # <str>
        #Option     "Present"                   # [<bool>]
        #Option     "ColorKey"                  # <i>
        #Option     "VideoKey"                  # <i>
        #Option     "Tiling"                    # [<bool>]
        #Option     "LinearFramebuffer"         # [<bool>]
        #Option     "HWRotation"                # [<bool>]
        #Option     "VSync"                     # [<bool>]
        #Option     "PageFlip"                  # [<bool>]
        #Option     "SwapbuffersWait"           # [<bool>]
        #Option     "TripleBuffer"              # [<bool>]
        #Option     "XvPreferOverlay"           # [<bool>]
        #Option     "HotPlug"                   # [<bool>]
        #Option     "ReprobeOutputs"            # [<bool>]
        #Option     "XvMC"                      # [<bool>]
        #Option     "ZaphodHeads"               # <str>
        #Option     "VirtualHeads"              # <i>
        #Option     "TearFree"                  # [<bool>]
        #Option     "PerCrtcPixmaps"            # [<bool>]
        #Option     "FallbackDebug"             # [<bool>]
        #Option     "DebugFlushBatches"         # [<bool>]
        #Option     "DebugFlushCaches"          # [<bool>]
        #Option     "DebugWait"                 # [<bool>]
        #Option     "BufferCache"               # [<bool>]
        Identifier  "Card0"
        Driver      "intel"
        BusID       "PCI:0:2:0"
EndSection

Section "Screen"
        Identifier "Screen0"
        Device     "Card0"
        Monitor    "Monitor0"
        SubSection "Display"
                Viewport   0 0
                Depth     1
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     4
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     8
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     15
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     16
        EndSubSection
        SubSection "Display"
                Viewport   0 0
                Depth     24
        EndSubSection
EndSection

5. 修改默认驱动

将以上/etc/X11/xorg.conf文件中的Section:"Device"中的Driver项由"Intel"修改为"modesetting"。

6. 重启

执行以上步骤后,再次测试,问题就不存在了。

当然,这其实不是最好的解决方法。真正最好的解决方法是看懂Intel的源码并且改正过来,但是那恐怕需要很长的时间了。

本文标签: 解决方法现象FlameshotSpectacleXlib