SDL2 SDL_SetEventFilter против SDL_WaitEvent

У меня был типичный цикл событий SDL, вызывающий SDL_WaitEvent, и я столкнулся с широко обсуждаемой проблемой (см. здесь и здесь), где мое приложение не могло перерисовать во время изменения размера, потому что SDL_WaitEvent не возвращается, пока изменение размера не будет завершено на определенных платформах (Win32 и Mac OS). В каждом из этих обсуждений техника использования SDL_SetEventFilter для ее обхода упоминается и более или менее принимается как решение и хак.

Использование подхода SDL_SetEventFilter работает отлично, но теперь я смотрю на свой код и практически переместил весь код из моего SDL_WaitEvent в свой EventFilter и просто обрабатываю там события.

Архитектурно это подозрительно, как черт.

Есть ли какие-либо проблемы с этим подходом к отправке сообщений моему приложению в функции, установленной SDL_SetEventFilter, помимо возможности вызова в отдельном потоке?

Бонусный вопрос: как SDL справляется с этим внутри? Насколько я понимаю, эта проблема с изменением размера связана с базовой платформой. Например, Win32 выдаст WM_SIZING, а затем введет свой собственный внутренний поток сообщений, пока не будет выдано WM_SIZE. Что запускает SDL EventFilter?


person Wilfredo Velázquez-Rodríguez    schedule 22.10.2017    source источник
comment
Что против SDL_PollEvent? Вместо того, чтобы бесконечно ждать событий, просто опрашивайте их каждый цикл, если таковые имеются.   -  person skypjack    schedule 22.10.2017
comment
Это не помогает. SDL_PollEvent ведет себя точно так же, как SDL_WaitEvent и будет блокироваться до завершения изменения размера/перемещения.   -  person Wilfredo Velázquez-Rodríguez    schedule 22.10.2017
comment
Если бы это решило проблему, я бы не публиковал это как комментарий, верно? Это было просто предложение не по теме.   -  person skypjack    schedule 22.10.2017
comment
Тогда я не уверен, что вы хотите, чтобы я ответил. Я не использую SDL_PollEvent, потому что мне не нужен тайм-аут. Я бы зря тратил циклы на опрос вместо того, чтобы просто ждать.   -  person Wilfredo Velázquez-Rodríguez    schedule 23.10.2017


Ответы (1)


Отвечая на мой собственный вопрос после дополнительных экспериментов и просеивания источника.

SDL обрабатывает события следующим образом: когда вы вызываете SDL_WaitEvent/SDL_PeekEvent/SDL_PeepEvents, он загружает win32 до тех пор, пока не останется сообщений. Во время этого насоса он будет обрабатывать сообщения win32 и превращать их в события SDL, которые он ставит в очередь, чтобы вернуть их после завершения насоса.

Способ, которым win32 обрабатывает операции перемещения/изменения размера, состоит в том, чтобы перейти к насосу сообщений до завершения перемещения/изменения размера. Это обычный насос сообщений, поэтому ваш WndProc все еще вызывается в это время. Вы получите WM_ENTERSIZEMOVE, затем множество сообщений WM_SIZING или WM_MOVING, а затем, наконец, WM_EXITSIZEMOVE.

Эти две вещи вместе означают, что когда вы вызываете любую из функций обработки событий SDL, а Win32 выполняет операцию перемещения/изменения размера, вы застреваете до завершения перетаскивания.

Способ, которым EventFilter обходит это, заключается в том, что он вызывается как часть самого WndProc. Это означает, что вам не нужно ставить сообщения в очередь и возвращать их вам в конце события SDL_Peek/Wait/Peep. Вы получаете их сразу же, как часть прокачки.

В мою архитектуру это вписывается идеально. YMMV.

person Wilfredo Velázquez-Rodríguez    schedule 26.10.2017