如何创建Alt+;Linux中的Tab友好全屏程序(如游戏)?

如何创建Alt+;Linux中的Tab友好全屏程序(如游戏)?,linux,sdl,fullscreen,x11,screen-grab,Linux,Sdl,Fullscreen,X11,Screen Grab,我想创建一个应用程序,在其中我在一个窗口上绘制,无论是窗口还是全屏,在那里我抓取鼠标,但不截取任何WM键盘快捷键,如Alt+Tab,并且每当用户进入/离开焦点时,我还需要得到通知 像谷歌浏览器、火狐或gnome终端这样的普通应用程序可以很好地处理这个问题(使用F11全屏显示,但仍然有Alt+Tab),但它们不会抓取鼠标 SDL在处理这个用例方面有一个臭名昭著的错误:SDL_WM_GrabInput抓取鼠标,但也截取WM快捷方式;SDL_全屏似乎有某种自动抓取功能(别问我为什么) 一个解决方案可能

我想创建一个应用程序,在其中我在一个窗口上绘制,无论是窗口还是全屏,在那里我抓取鼠标,但不截取任何WM键盘快捷键,如Alt+Tab,并且每当用户进入/离开焦点时,我还需要得到通知

像谷歌浏览器、火狐或gnome终端这样的普通应用程序可以很好地处理这个问题(使用F11全屏显示,但仍然有Alt+Tab),但它们不会抓取鼠标

SDL在处理这个用例方面有一个臭名昭著的错误:SDL_WM_GrabInput抓取鼠标,但也截取WM快捷方式;SDL_全屏似乎有某种自动抓取功能(别问我为什么)

一个解决方案可能是自己为Alt+Tab编写代码,但这很糟糕(而且对其他WM快捷方式没有帮助,比如更改到另一个工作区)

另一个解决方案是不调用SDL_WM_GrabInput,而是假装抓取:只要隐藏鼠标指针(使用SDL_ShowCursor),并在用户移动时将其移回中心。这很难看,但实际上是可行的——当然SDL_全屏除外,因为它会自动抓取(与sane实现不同)。支持全屏显示的SDL解决方案就是这样,但这仍然不是我想要的。我不想有黑客来启用和禁用抓取,我想抓取鼠标,但不抓取键盘

所以我对SDL很生气,想看看其他的选择。我想使用SDL,但这不是必需的

似乎指出SDL实际上做的是使用XGrabKeyboard。通过阅读手册页,我现在还不清楚你是否可以在不抓取键盘的情况下抓取鼠标(我自己从未使用过Xlib)

我知道如何使用GTK制作“假全屏”(也就是说,使用Alt+Tab友好的gnome终端)。我想这样做,再加上隐藏鼠标并将其移回中心(“假抓取”)可以达到目的,但这感觉像是太多的胶带。一定有更简单的方法。(此外,我不想将GTK添加为依赖项;但我也不确定进行原始Xlib调用是否是一个好主意)

有什么好的解决办法

我需要一个Linux/X11解决方案,但它最好是跨平台的-我知道这可以在Windows上顺利解决,所以也许有一个库可以做到这一点。(另外,我使用OpenGL进行渲染,但这与此无关)


PS:也许我对这个问题的理解不好,我问的问题不对,所以请随意指出我没有考虑过的方法。

最近我一直在使用Gtk和GtkGLExt在Linux上玩游戏(例如,我的Ludum Dare条目)。这里()是我的代码,我是根据FreeBSD许可证发布的。您可以看到我注释掉的调试窗口状态更改的代码。我应该提到,这是一个更大的框架的一部分,我用于Ludum Dare之类的东西,我更喜欢它而不是SDL,原因与您提到的相同:生成的应用程序更符合用户对其平台(Linux、OS X、Windows)上本机应用程序的期望。不用说,走这条路需要很多工作

然而,原始X11编程真是一团糟。我估计,要将我的Gtk代码转换成X11代码,我需要花上几周的时间进行扎实的编程和阅读文档;这对我来说不值得,但你可能会做出不同的决定。(为了消除每个人都安装过的依赖项,需要花费很多时间!)Gtk依赖项实际上并没有那么离谱,它可能已经加载到内存中了,而且ABI for 2.x非常稳定,因此不会影响二进制兼容性

X11游戏编程的一个大问题是事件处理非常混乱。你不能轻易地对事件进行投票。Xlib接口正在阻塞,因此您必须使用一系列神秘的函数调用来读取数据,检查是否存在挂起的事件,然后仅读取队列中存在的事件(否则应用程序将阻塞,直到事件出现)。xcb库是Xlib的替代品,Xlib在各个方面都要好得多,并且支持非阻塞接口,但它不能很好地与OpenGL配合使用。因此,您可以尝试将两者混合,也可以使用Gtk

让我给你一段Gtk全屏代码:

static void toggle_fullscreen()
{
    if (sg_gtk_status & SG_STATUS_VISIBLE) {
        if (sg_gtk_status & SG_STATUS_FULLSCREEN)
            gtk_window_unfullscreen(sg_window);
        else
            gtk_window_fullscreen(sg_window);
    }
}
想象一下使用X11界面需要做多少工作:计算屏幕的大小(可能不止一个!),调整窗口大小,更改顺序,使其位于其他所有内容之上,更改装饰,然后在用户切换虚拟桌面时智能地响应。废话!(实际上,这描述了我的代码在OSX上的工作方式,但API要好得多。)

除此之外,如果您使用的是X11,您必须学会如何以预期的方式对用户做出反应。X11是从20世纪80年代开始的。相比之下,Gtk为您的应用程序提供了Gtk的UI设计器提供的一系列适当的默认值。用户界面设计就是工作。请记住:您可以将X11与Gtk混合使用

总结:X11编程适用于有大量空闲时间的程序员

注意:GtkGLExt添加了一个恼人的链接器标志,
-Wl,--export-dynamic
。我的构建脚本从
pkg config
的输出中删除该标志


X11体验:我想我花了大约一周的时间试图让整个事情在X11上运行,结果我在这个过程中遇到了很多死胡同。从失败中吸取教训。

在我看来,这并不是真正的重复,因为我不是专门寻找SDL解决方案。SDL只是我现在正在使用的库,我刚刚在XLIBAPI上看到了这个函数。所以,很明显,Xlib有足够的功能只抓取鼠标,而不必抓取键盘。嘿,非常感谢!我会看看你的代码。我同意简化编程的好处很快就超过了t