SDL2 应用程序在 Xmonad 中无法正常工作

Posted

技术标签:

【中文标题】SDL2 应用程序在 Xmonad 中无法正常工作【英文标题】:SDL2 applications do not work correctly in Xmonad 【发布时间】:2021-01-17 19:20:59 【问题描述】:

使用SDL2 的程序,例如使用pygame 和Mednafen 模拟器构建的游戏,在默认Xmonad 配置下无法正常工作。当它们以全屏模式启动时,它们的窗口不会显示。这是一个无法显示其窗口的 SDL2 程序的最小可重现示例:

#include "SDL.h"
#include <stdio.h>

int main(int argc, char* argv[]) 
  SDL_Window *window;
  SDL_Surface *screen;
  SDL_Init(SDL_INIT_VIDEO);
  window = SDL_CreateWindow("Example Window",
                            SDL_WINDOWPOS_UNDEFINED,
                            SDL_WINDOWPOS_UNDEFINED,
                            640, 480,
                            SDL_WINDOW_FULLSCREEN
                            );
  screen = SDL_GetWindowSurface(window);
  SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 0, 0));
  SDL_UpdateWindowSurface(window);
  SDL_Delay(3000);
  SDL_DestroyWindow(window);
  SDL_Quit();
  return 0;

您可以使用命令cc main.c -o main -D_REENTRANT -I/usr/include/SDL2 -lSDL2 编译此程序。

这里是重现问题的最小 xmonad 配置文件。请注意,我使用的是 xmonad v0.15 和 SDL v2.0.14。

import XMonad

main = xmonad $ def 
  modMask = mod4Mask
  

如果一切正确,该程序应显示一个 640 x 480 像素的红色背景窗口 3 秒钟,然后退出。但是,我可以让它与 Xmonad 一起使用的唯一方法是指定以下manageHook

import XMonad

main = xmonad $ def 
  modMask = mod4Mask,
  manageHook = composeAll [className =? "main" --> doIgnore]
  

目前,我的 Xmonad 配置中有许多这样的例外,以使 SDL2 程序在每个应用程序的基础上运行。这很烦人,尤其是因为 SDL1.2 应用程序 - 尤其是 DOSBox - 没有这个问题。

所以,我的问题是:

这是 SDL 还是 Xmonad 的问题? 此问题的原因是什么? 如何重写上面的程序以在 Xmonad 下正常工作?

【问题讨论】:

无论如何我都不是 SDL2 的专家,但我认为 SDL(不是 SDL2)作为屏幕从表面运行,而 SDL2 从SDL_Renderer 运行?您是否尝试过使用渲染器而不是表面? 我已尝试重现此问题,但它似乎在这里工作正常:我得到了一个 640x480 的窗口,按照您描述的方式放大到全屏。您可能想要指定您正在使用的 xmonad 和 xmonad-contrib 版本,并将您的 xmonad.hs(或重现问题的最小版本)添加到问题中。 非常感谢您的努力!我已经用版本号和最小的 xmonad 配置文件更新了帖子。 【参考方案1】:

虽然我对正在发生的事情的细节没有太多要说的,但我显然通过戳我自己的xmonad.hs 成功地重现了您的问题。从中删除对ewmh 的调用后,运行程序会导致一个空的全屏窗口,而不是一个红色的窗口。既然如此,请将您的最小配置更改为...

import XMonad
import XMonad.Hooks.EwmhDesktops

main = xmonad $ ewmh def 
  modMask = mod4Mask
  

... 可能会解决问题。

当您使用它时,您可能希望启用XMonad.Hooks.EwmhDesktops 提供的额外全屏支持,某些应用程序需要这些支持才能正常工作。这是 xmonad-contrib 0.16...

的样子
import XMonad
import XMonad.Hooks.EwmhDesktops

main = xmonad $ ewmh def 
  modMask = mod4Mask,
  handleEventHook = handleEventHook def <+> fullscreenEventHook
  

...以及 0.16 后的版本,例如来自 GitHub 的最新版本,遵循 a changelog entry 的建议:

import XMonad
import XMonad.Hooks.EwmhDesktops

main = xmonad $ ewmhFullscreen $ ewmh def 
  modMask = mod4Mask,
  

【讨论】:

非常感谢。我自己永远也想不通!你是对的,C 示例程序现在可以正常运行。但是,我仍然遇到使用pygame 编写的游戏的问题。我已经用一个 pygame 示例更新了我原来的问题。 @hedgie 您的 pygame 程序在 Xfce 下的行为方式相同,因此这不是 XMonad 问题。我对 pygame 不熟悉,但似乎您需要一个游戏循环才能使事情正常工作(例如,参见this Q&A)。此外,我相信您并不是要在screen = screen.fill((255,0,0)) 中重新分配screen。如果需要,我建议就这些问题提出一个单独的问题。 你完全正确,我已经从问题中删除了 pygame 问题。再次感谢您帮助我!

以上是关于SDL2 应用程序在 Xmonad 中无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL / SDL2:模板缓冲区位在 PC 上始终为 0

Make标签在多个监视器上的xmonad中表现得像工作区行为

xmonad - 打开一个特定图块的窗口

SDL2访问冲突多个窗口

如何在 SDL2 中旋转矩形?

无法为 Android 构建 SDL2