GLFW 窗口轮询事件滞后
我在处理 GLFW 轮询事件时遇到问题。据我所知,所有用户输入事件都是通过回调或不断检查键盘/鼠标状态来处理的。后者效率不高,甚至可能导致丢失某些输入(例如,在检查状态之间按下按钮然后释放按钮时)。更重要的是,如果没有回调,就无法处理某些事件(例如窗口大小调整)。
因此,问题是,每当用户开始调整窗口大小(按下鼠标按钮但不移动鼠标)时,应用程序似乎都会冻结。这是假设调整大小回调已启用并有效定义(即使是从 GLFW 直接复制的API)。问题不是窗口不重绘。回调重绘可以通过在回调函数中创建并调用自己的 render() 函数来完成。
实际问题是,即使我正确处理调整大小事件并在回调上重绘,仍然存在一些滞后。此滞后是在鼠标按下装饰窗口边框后且鼠标未移动时出现的。这是一个演示(按钮单击以绿色突出显示):
抱歉,GIF 搞砸了。 GLFW API 中列出的所有回调均已启用和处理(窗口回调、输入回调、操纵杆回调和监视器回调),并在每一个回调中调用重绘。看来我错过了一些回调或 GLFW 就是这样工作的。
根据 this 答案,如果没有线程,就无法完成此操作:
仅当用户按住鼠标移动鼠标时才有效 - 仅按住左键单击调整大小窗口部分仍然会停止。 要解决这个问题,除此之外,您还需要在单独的线程中进行渲染。 (不,没有线程就无法做到这一点。抱歉,这就是 GLFW 的工作方式,除了他们之外没有人可以更改它。)
因此,问题是:
- 如何在没有线程的情况下解决此问题?如果我不能,我想我可以用不同的光标形状和调整区域大小来模拟调整大小或类似的东西...
- 如果这仍然无法在 GLFW 中解决,其他 GLFW 替代方案是否有这个问题?
- GLFW 是否存在与此类似的问题?
I have a problem handling GLFW poll events. As far as I know, all user input events are handled via callbacks or via constantly checking keyboard / mouse states. The latter is not so efficient an can even result in missing some input (e. g. when button pressed and then released between checking state). What is more, some events like window resizing cannot be handled without callbacks.
So, the problem is that whenever user starts resizing window (presses mouse button but doesn't move mouse), the app seems to freeze. This is, assuming resize callback is enabled and defined validly (even when copied right from GLFW API). And the problem is not that window doesn't redraw. Redraw on callback can be done with creating and calling own render()
function in callback function.
The actual problem is that even when I handle resize event properly and redraw on callback, there is still some lag. This lag is after mouse press on decorated window border and when mouse is not moving. Here's a demonstration (button click is highlighted green):
Sorry for messed up GIF. All callbacks listed in GLFW API are enabled and handled (window-, input-, joystick- and monitor-callbacks) and redraw is called in each one. It seems that I'm missing some of the callbacks or GLFW just works like that.
According to this answer, this can't be done without threading:
That only works when the user moves the mouse while holding - just holding left-click on the resize window part still stalls. To fix that, you need to render in a separate thread in addition to this. (No, you can't do that without threading. Sorry, this is how GLFW works, no one except them can change it.)
So, the questions are:
- How can I fix this issue without threading? If I can't, I guess I can emulate resizing with different cursors shapes and resizing zones or smth like that...
- If this is still impossible to solve in GLFW, do other GLFW alternatives have this issue?
- Are there any problems with GLFW similar to this one?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
GLFW 并没有错。这是操作系统处理某些用户输入事件的方式,例如在装饰器上按下鼠标、调整窗口句柄大小或移动整个窗口。
有关更详细的详细信息,请参阅此答案:Win32:当用户调整窗口大小时我的应用程序冻结
GLFW 使用标准 Windows PeekMessage -> TranslateMessage/DispatchMessage 循环,您可以在任何 GUI Windows 应用程序中找到它。当您调用
glfwPollEvents()
时,它将被调用,并且它会处理操作系统迄今为止为该进程中的所有窗口积累的所有窗口事件消息。处理完迄今为止的所有消息后,对glfwPollEvents()
的调用将返回,并允许您自己的窗口/游戏循环继续。发生的情况是,一旦用户单击窗口装饰的调整大小手柄,对
glfwPollEvents()
的调用实际上将在操作系统本身内阻塞,以便操作系统/窗口管理器拦截鼠标和键盘消息来调整窗口大小/形状。恐怕即使 Windows 会通知进程有关窗口调整大小或移动操作的开始(之后操作系统将控制窗口消息处理)和 GLFW 已经在内部处理这些事件,现在 GLFW不会将此情况通知客户端应用程序。不过,GLFW 有可能向应用程序提供适当的事件回调,以便应用程序可以仅在窗口调整大小/移动操作发生时启动计时器或线程(同样如此)在链接的其他 Stackoverflow 答案中提到)。
因此,为了在用户按住调整大小手柄或用户移动窗口时保持渲染,您唯一可以做的就是在单独的线程中渲染。
GLFW is not at fault here. It's how the operating system handles certain user input events like mouse down on the decorator resize handles of a window or moving the whole window.
See this answer for a more elaborate detail: Win32: My Application freezes while the user resizes the window
GLFW uses the standard Windows PeekMessage -> TranslateMessage/DispatchMessage loop which you will find in any GUI Windows application. This will get invoked when you call
glfwPollEvents()
and it processes all Window event messages that the OS has accumulated so far for all windows in this process. After all messages so far have been processed, the call toglfwPollEvents()
will return and will allow your own window/game loop to continue.What happens is that once the user clicks down the window decoration's resize handles, effectively the call to
glfwPollEvents()
will block within the OS itself in order for the OS / window-manager to intercept the mouse and keyboard messages to do its window resizing/reshaping thing.I'm afraid that even though Windows will inform the process about the start of a window resize or move action (after which the OS will have control of the window message processing) and GLFW already handling these events internally, right now GLFW will not notify the client application about this. It would be possible though for GLFW to provide an appropriate event callback to the application, so that the application can start a timer or thread only for as long as the window resize/move action happens (as is also mentioned in the linked other Stackoverflow answer).
So, the only thing that you can do in order to keep rendering while the user holds onto the resize handles or while the user moves the window around, is to render in a separate thread.