diff --git a/Source/debug.cpp b/Source/debug.cpp index a292ff9f1..9a8ad0a59 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -116,14 +116,15 @@ void PrintDebugMonster(const Monster &monster) void ProcessMessages() { - tagMSG msg; - while (FetchMessage(&msg)) { - if (msg.message == DVL_WM_QUIT) { + SDL_Event event; + uint16_t modState; + while (FetchMessage(&event, &modState)) { + if (event.type == SDL_QUIT) { gbRunGameResult = false; gbRunGame = false; break; } - PushMessage(&msg); + HandleMessage(event, modState); } } diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 637d02b11..762387144 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -594,110 +594,79 @@ void PressKey(SDL_Keycode vkey, uint16_t modState) } } -void GetMousePos(uint32_t lParam) +void GameEventHandler(const SDL_Event &event, uint16_t modState) { - MousePosition = { (std::int16_t)(lParam & 0xffff), (std::int16_t)((lParam >> 16) & 0xffff) }; -} - -void GameEventHandler(uint32_t uMsg, uint32_t wParam, uint16_t lParam) -{ - switch (uMsg) { - case DVL_WM_KEYDOWN: - PressKey(static_cast(wParam), lParam); + switch (event.type) { + case SDL_KEYDOWN: + PressKey(event.key.keysym.sym, modState); return; - case DVL_WM_KEYUP: - ReleaseKey(static_cast(wParam)); + case SDL_KEYUP: + ReleaseKey(event.key.keysym.sym); return; - case DVL_WM_MOUSEMOVE: - GetMousePos(wParam); + case SDL_MOUSEMOTION: + MousePosition = { event.motion.x, event.motion.y }; gmenu_on_mouse_move(); return; - case DVL_WM_LBUTTONDOWN: - GetMousePos(wParam); + case SDL_MOUSEBUTTONDOWN: + MousePosition = { event.button.x, event.button.y }; if (sgbMouseDown == CLICK_NONE) { - sgbMouseDown = CLICK_LEFT; - LeftMouseDown(lParam); + switch (event.button.button) { + case SDL_BUTTON_LEFT: + sgbMouseDown = CLICK_LEFT; + LeftMouseDown(modState); + break; + case SDL_BUTTON_RIGHT: + sgbMouseDown = CLICK_RIGHT; + RightMouseDown((modState & KMOD_SHIFT) != 0); + break; + default: + sgOptions.Keymapper.KeyPressed(event.button.button | KeymapperMouseButtonMask); + break; + } } return; - case DVL_WM_LBUTTONUP: - GetMousePos(wParam); - if (sgbMouseDown == CLICK_LEFT) { + case SDL_MOUSEBUTTONUP: + MousePosition = { event.button.x, event.button.y }; + + if (sgbMouseDown == CLICK_LEFT && event.button.button == SDL_BUTTON_LEFT) { LastMouseButtonAction = MouseActionType::None; sgbMouseDown = CLICK_NONE; - LeftMouseUp(lParam); - } - return; - case DVL_WM_RBUTTONDOWN: - GetMousePos(wParam); - if (sgbMouseDown == CLICK_NONE) { - sgbMouseDown = CLICK_RIGHT; - RightMouseDown((lParam & KMOD_SHIFT) != 0); + LeftMouseUp(modState); + } else if (sgbMouseDown == CLICK_RIGHT && event.button.button == SDL_BUTTON_RIGHT) { + LastMouseButtonAction = MouseActionType::None; + sgbMouseDown = CLICK_NONE; + } else { + sgOptions.Keymapper.KeyReleased(event.button.button | KeymapperMouseButtonMask); } return; - case DVL_WM_RBUTTONUP: - GetMousePos(wParam); - if (sgbMouseDown == CLICK_RIGHT) { + default: + if (IsCustomEvent(event.type)) { + if (gbIsMultiplayer) + pfile_write_hero(); + nthread_ignore_mutex(true); + PaletteFadeOut(8); + sound_stop(); LastMouseButtonAction = MouseActionType::None; sgbMouseDown = CLICK_NONE; + ShowProgress(GetCustomEvent(event.type)); + force_redraw = 255; + DrawAndBlit(); + LoadPWaterPalette(); + if (gbRunGame) + PaletteFadeIn(8); + nthread_ignore_mutex(false); + gbGameLoopStartup = true; + return; } - return; - case DVL_WM_MBUTTONDOWN: - sgOptions.Keymapper.KeyPressed(SDL_BUTTON_MIDDLE | KeymapperMouseButtonMask); - return; - case DVL_WM_MBUTTONUP: - sgOptions.Keymapper.KeyReleased(SDL_BUTTON_MIDDLE | KeymapperMouseButtonMask); - return; - case DVL_WM_X1BUTTONDOWN: - sgOptions.Keymapper.KeyPressed(SDL_BUTTON_X1 | KeymapperMouseButtonMask); - return; - case DVL_WM_X1BUTTONUP: - sgOptions.Keymapper.KeyReleased(SDL_BUTTON_X1 | KeymapperMouseButtonMask); - return; - case DVL_WM_X2BUTTONDOWN: - sgOptions.Keymapper.KeyPressed(SDL_BUTTON_X2 | KeymapperMouseButtonMask); - return; - case DVL_WM_X2BUTTONUP: - sgOptions.Keymapper.KeyReleased(SDL_BUTTON_X2 | KeymapperMouseButtonMask); - return; - case DVL_WM_CAPTURECHANGED: - sgbMouseDown = CLICK_NONE; - LastMouseButtonAction = MouseActionType::None; + MainWndProc(event); break; - case WM_DIABNEXTLVL: - case WM_DIABPREVLVL: - case WM_DIABRTNLVL: - case WM_DIABSETLVL: - case WM_DIABWARPLVL: - case WM_DIABTOWNWARP: - case WM_DIABTWARPUP: - case WM_DIABRETOWN: - if (gbIsMultiplayer) - pfile_write_hero(); - nthread_ignore_mutex(true); - PaletteFadeOut(8); - sound_stop(); - LastMouseButtonAction = MouseActionType::None; - sgbMouseDown = CLICK_NONE; - ShowProgress((interface_mode)uMsg); - force_redraw = 255; - DrawAndBlit(); - LoadPWaterPalette(); - if (gbRunGame) - PaletteFadeIn(8); - nthread_ignore_mutex(false); - gbGameLoopStartup = true; - return; } - - MainWndProc(uMsg); } void RunGameLoop(interface_mode uMsg) { demo::NotifyGameLoopStart(); - tagMSG msg; - nthread_ignore_mutex(true); StartGame(uMsg); assert(HeadlessMode || ghMainWnd); @@ -730,13 +699,15 @@ void RunGameLoop(interface_mode uMsg) } #endif - while (FetchMessage(&msg)) { - if (msg.message == DVL_WM_QUIT) { + SDL_Event event; + uint16_t modState; + while (FetchMessage(&event, &modState)) { + if (event.type == SDL_QUIT) { gbRunGameResult = false; gbRunGame = false; break; } - PushMessage(&msg); + HandleMessage(event, modState); } if (!gbRunGame) break; @@ -2015,41 +1986,31 @@ bool PressEscKey() return rv; } -void DisableInputEventHandler(uint32_t uMsg, uint32_t wParam, uint16_t /*lParam*/) +void DisableInputEventHandler(const SDL_Event &event, uint16_t modState) { - switch (uMsg) { - case DVL_WM_KEYDOWN: - case DVL_WM_KEYUP: - return; - case DVL_WM_MOUSEMOVE: - GetMousePos(wParam); + switch (event.type) { + case SDL_MOUSEMOTION: + MousePosition = { event.motion.x, event.motion.y }; return; - case DVL_WM_LBUTTONDOWN: + case SDL_MOUSEBUTTONDOWN: if (sgbMouseDown != CLICK_NONE) return; - sgbMouseDown = CLICK_LEFT; - return; - case DVL_WM_LBUTTONUP: - if (sgbMouseDown != CLICK_LEFT) + switch (event.button.button) { + case SDL_BUTTON_LEFT: + sgbMouseDown = CLICK_LEFT; return; - sgbMouseDown = CLICK_NONE; - return; - case DVL_WM_RBUTTONDOWN: - if (sgbMouseDown != CLICK_NONE) + case SDL_BUTTON_RIGHT: + sgbMouseDown = CLICK_RIGHT; return; - sgbMouseDown = CLICK_RIGHT; - return; - case DVL_WM_RBUTTONUP: - if (sgbMouseDown != CLICK_RIGHT) + default: return; - sgbMouseDown = CLICK_NONE; - return; - case DVL_WM_CAPTURECHANGED: + } + case SDL_MOUSEBUTTONUP: sgbMouseDown = CLICK_NONE; return; } - MainWndProc(uMsg); + MainWndProc(event); } void LoadGameLevel(bool firstflag, lvl_entry lvldir) diff --git a/Source/diablo.h b/Source/diablo.h index b494298c1..bb163c5d2 100644 --- a/Source/diablo.h +++ b/Source/diablo.h @@ -93,7 +93,7 @@ bool diablo_is_focused(); void diablo_focus_pause(); void diablo_focus_unpause(); bool PressEscKey(); -void DisableInputEventHandler(uint32_t uMsg, uint32_t wParam, uint16_t lParam); +void DisableInputEventHandler(const SDL_Event &event, uint16_t modState); void LoadGameLevel(bool firstflag, lvl_entry lvldir); /** diff --git a/Source/engine/demomode.cpp b/Source/engine/demomode.cpp index 3626a93a4..3d3b9e503 100644 --- a/Source/engine/demomode.cpp +++ b/Source/engine/demomode.cpp @@ -25,12 +25,39 @@ enum class DemoMsgType { Message = 2, }; +struct MouseMotionEventData { + uint16_t x; + uint16_t y; +}; + +struct MouseButtonEventData { + uint8_t button; + uint16_t x; + uint16_t y; + uint16_t mod; +}; + +struct MouseWheelEventData { + int32_t x; + int32_t y; + uint16_t mod; +}; + +struct KeyEventData { + SDL_Keycode sym; + SDL_Keymod mod; +}; + struct DemoMsg { DemoMsgType type; - uint32_t message; - uint32_t wParam; - uint16_t lParam; float progressToNextGameTick; + SDL_EventType eventType; + union { + MouseMotionEventData motion; + MouseButtonEventData button; + MouseWheelEventData wheel; + KeyEventData key; + }; }; int DemoNumber = -1; @@ -48,11 +75,6 @@ int StartTime = 0; uint16_t DemoGraphicsWidth = 640; uint16_t DemoGraphicsHeight = 480; -void PumpDemoMessage(DemoMsgType demoMsgType, uint32_t message, uint32_t wParam, uint16_t lParam, float progressToNextGameTick) -{ - Demo_Message_Queue.push_back(DemoMsg { demoMsgType, message, wParam, lParam, progressToNextGameTick }); -} - bool LoadDemoMessages(int i) { std::ifstream demofile; @@ -78,14 +100,45 @@ bool LoadDemoMessages(int i) switch (type) { case DemoMsgType::Message: { - const uint32_t message = ReadLE32(demofile); - const uint32_t wParam = ReadLE32(demofile); - const uint16_t lParam = ReadLE16(demofile); - PumpDemoMessage(type, message, wParam, lParam, progressToNextGameTick); + const auto eventType = static_cast(ReadLE32(demofile)); + DemoMsg msg { type, progressToNextGameTick, eventType, {} }; + switch (eventType) { + case SDL_MOUSEMOTION: + msg.motion.x = ReadLE16(demofile); + msg.motion.y = ReadLE16(demofile); + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + msg.button.button = ReadByte(demofile); + msg.button.x = ReadLE16(demofile); + msg.button.y = ReadLE16(demofile); + msg.button.mod = ReadLE16(demofile); + break; +#ifndef USE_SDL1 + case SDL_MOUSEWHEEL: + msg.wheel.x = ReadLE32(demofile); + msg.wheel.y = ReadLE32(demofile); + msg.wheel.mod = ReadLE16(demofile); + break; +#endif + case SDL_KEYDOWN: + case SDL_KEYUP: + msg.key.sym = static_cast(ReadLE32(demofile)); + msg.key.mod = static_cast(ReadLE16(demofile)); + break; + case SDL_QUIT: + break; + default: + if (eventType < SDL_USEREVENT) { + app_fatal(StrCat("Unknown event ", static_cast(eventType))); + } + break; + } + Demo_Message_Queue.push_back(msg); break; } default: - PumpDemoMessage(type, 0, 0, 0, progressToNextGameTick); + Demo_Message_Queue.push_back(DemoMsg { type, progressToNextGameTick, static_cast(0), {} }); break; } } @@ -97,6 +150,13 @@ bool LoadDemoMessages(int i) return true; } +void RecordEventHeader(const SDL_Event &event) +{ + WriteLE32(DemoRecording, static_cast(DemoMsgType::Message)); + WriteLEFloat(DemoRecording, gfProgressToNextGameTick); + WriteLE32(DemoRecording, event.type); +} + } // namespace namespace demo { @@ -180,19 +240,16 @@ bool GetRunGameLoop(bool &drawGame, bool &processInput) return dmsg.type == DemoMsgType::GameTick; } -bool FetchMessage(tagMSG *lpMsg) +bool FetchMessage(SDL_Event *event, uint16_t *modState) { SDL_Event e; if (SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { - lpMsg->message = DVL_WM_QUIT; - lpMsg->wParam = 0; - lpMsg->lParam = 0; + *event = e; return true; } if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE) { Demo_Message_Queue.clear(); - ClearMessageQueue(); DemoNumber = -1; Timedemo = false; last_tick = SDL_GetTicks(); @@ -212,19 +269,45 @@ bool FetchMessage(tagMSG *lpMsg) if (!Demo_Message_Queue.empty()) { const DemoMsg dmsg = Demo_Message_Queue.front(); if (dmsg.type == DemoMsgType::Message) { - lpMsg->message = dmsg.message; - lpMsg->wParam = dmsg.wParam; - lpMsg->lParam = dmsg.lParam; + event->type = dmsg.eventType; + switch (dmsg.eventType) { + case SDL_MOUSEMOTION: + event->motion.x = dmsg.motion.x; + event->motion.y = dmsg.motion.y; + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + event->button.button = dmsg.button.button; + event->button.state = dmsg.eventType == SDL_MOUSEBUTTONDOWN ? SDL_PRESSED : SDL_RELEASED; + event->button.x = dmsg.button.x; + event->button.y = dmsg.button.y; + *modState = dmsg.button.mod; + break; +#ifndef USE_SDL1 + case SDL_MOUSEWHEEL: + event->wheel.x = dmsg.wheel.x; + event->wheel.y = dmsg.wheel.y; + *modState = dmsg.wheel.mod; + break; +#endif + case SDL_KEYDOWN: + case SDL_KEYUP: + event->key.state = dmsg.eventType == SDL_KEYDOWN ? SDL_PRESSED : SDL_RELEASED; + event->key.keysym.sym = dmsg.key.sym; + event->key.keysym.mod = dmsg.key.mod; + break; + default: + if (dmsg.eventType >= SDL_USEREVENT) { + event->type = CustomEventToSdlEvent(static_cast(dmsg.eventType - SDL_USEREVENT)); + } + break; + } gfProgressToNextGameTick = dmsg.progressToNextGameTick; Demo_Message_Queue.pop_front(); return true; } } - lpMsg->message = 0; - lpMsg->wParam = 0; - lpMsg->lParam = 0; - return false; } @@ -234,15 +317,58 @@ void RecordGameLoopResult(bool runGameLoop) WriteLEFloat(DemoRecording, gfProgressToNextGameTick); } -void RecordMessage(tagMSG *lpMsg) +void RecordMessage(const SDL_Event &event, uint16_t modState) { if (!gbRunGame || !DemoRecording.is_open()) return; - WriteLE32(DemoRecording, static_cast(DemoMsgType::Message)); - WriteLEFloat(DemoRecording, gfProgressToNextGameTick); - WriteLE32(DemoRecording, lpMsg->message); - WriteLE32(DemoRecording, lpMsg->wParam); - WriteLE16(DemoRecording, lpMsg->lParam); + switch (event.type) { + case SDL_MOUSEMOTION: + RecordEventHeader(event); + WriteLE16(DemoRecording, event.motion.x); + WriteLE16(DemoRecording, event.motion.y); + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + RecordEventHeader(event); + WriteByte(DemoRecording, event.button.button); + WriteLE16(DemoRecording, event.button.x); + WriteLE16(DemoRecording, event.button.y); + WriteLE16(DemoRecording, modState); + break; +#ifndef USE_SDL1 + case SDL_MOUSEWHEEL: + RecordEventHeader(event); + WriteLE32(DemoRecording, event.wheel.x); + WriteLE32(DemoRecording, event.wheel.y); + WriteLE16(DemoRecording, modState); + break; +#endif + case SDL_KEYDOWN: + case SDL_KEYUP: + RecordEventHeader(event); + WriteLE32(DemoRecording, static_cast(event.key.keysym.sym)); + WriteLE16(DemoRecording, static_cast(event.key.keysym.mod)); + break; +#ifndef USE_SDL1 + case SDL_WINDOWEVENT: + if (event.window.type == SDL_WINDOWEVENT_CLOSE) { + SDL_Event quitEvent; + quitEvent.type = SDL_QUIT; + RecordEventHeader(quitEvent); + } + break; +#endif + case SDL_QUIT: + RecordEventHeader(event); + break; + default: + if (IsCustomEvent(event.type)) { + SDL_Event stableCustomEvent; + stableCustomEvent.type = SDL_USEREVENT + static_cast(GetCustomEvent(event.type)); + RecordEventHeader(stableCustomEvent); + } + break; + } } void NotifyGameLoopStart() diff --git a/Source/engine/demomode.h b/Source/engine/demomode.h index 5ff93987f..011e39d2e 100644 --- a/Source/engine/demomode.h +++ b/Source/engine/demomode.h @@ -5,6 +5,8 @@ */ #pragma once +#include + #include "miniwin/misc_msg.h" namespace devilution { @@ -19,9 +21,9 @@ bool IsRunning(); bool IsRecording(); bool GetRunGameLoop(bool &drawGame, bool &processInput); -bool FetchMessage(tagMSG *lpMsg); +bool FetchMessage(SDL_Event *event, uint16_t *modState); void RecordGameLoopResult(bool runGameLoop); -void RecordMessage(tagMSG *lpMsg); +void RecordMessage(const SDL_Event &event, uint16_t modState); void NotifyGameLoopStart(); void NotifyGameLoopEnd(); diff --git a/Source/init.cpp b/Source/init.cpp index 729374c7e..a25d55bf3 100644 --- a/Source/init.cpp +++ b/Source/init.cpp @@ -229,15 +229,50 @@ void init_create_window() #endif } -void MainWndProc(uint32_t msg) +void MainWndProc(const SDL_Event &event) { - switch (msg) { - case DVL_WM_PAINT: +#ifndef USE_SDL1 + if (event.type != SDL_WINDOWEVENT) + return; + switch (event.window.event) { + case SDL_WINDOWEVENT_HIDDEN: + gbActive = false; + break; + case SDL_WINDOWEVENT_SHOWN: + gbActive = false; + force_redraw = 255; + break; + case SDL_WINDOWEVENT_EXPOSED: + force_redraw = 255; + break; + case SDL_WINDOWEVENT_LEAVE: + sgbMouseDown = CLICK_NONE; + LastMouseButtonAction = MouseActionType::None; force_redraw = 255; break; - case DVL_WM_QUERYENDSESSION: + case SDL_WINDOWEVENT_CLOSE: diablo_quit(0); + break; + case SDL_WINDOWEVENT_FOCUS_LOST: + diablo_focus_pause(); + break; + case SDL_WINDOWEVENT_FOCUS_GAINED: + diablo_focus_unpause(); + break; + default: + LogVerbose("Unhandled SDL_WINDOWEVENT event: ", event.window.event); + break; + } +#else + if (event.type != SDL_ACTIVEEVENT) + return; + if ((event.active.state & SDL_APPINPUTFOCUS) != 0) { + if (event.active.gain == 0) + diablo_focus_pause(); + else + diablo_focus_unpause(); } +#endif } EventHandler SetEventHandler(EventHandler eventHandler) diff --git a/Source/init.h b/Source/init.h index 57d15fde0..75cf48190 100644 --- a/Source/init.h +++ b/Source/init.h @@ -34,7 +34,7 @@ void LoadCoreArchives(); void LoadLanguageArchive(); void LoadGameArchives(); void init_create_window(); -void MainWndProc(uint32_t Msg); +void MainWndProc(const SDL_Event &event); EventHandler SetEventHandler(EventHandler NewProc); } // namespace devilution diff --git a/Source/interfac.cpp b/Source/interfac.cpp index 9881daa99..50952f91a 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -44,6 +44,9 @@ const int BarPos[3][2] = { { 53, 37 }, { 53, 421 }, { 53, 37 } }; OptionalOwnedClxSpriteList ArtCutsceneWidescreen; +uint32_t CustomEventsBegin = SDL_USEREVENT; +constexpr uint32_t NumCustomEvents = WM_LAST - WM_FIRST + 1; + Cutscenes PickCutscene(interface_mode uMsg) { switch (uMsg) { @@ -204,13 +207,35 @@ void DrawCutsceneForeground() } // namespace -void interface_msg_pump() +void RegisterCustomEvents() +{ +#ifndef USE_SDL1 + CustomEventsBegin = SDL_RegisterEvents(NumCustomEvents); +#endif +} + +bool IsCustomEvent(uint32_t eventType) +{ + return eventType >= CustomEventsBegin && eventType < CustomEventsBegin + NumCustomEvents; +} + +interface_mode GetCustomEvent(uint32_t eventType) { - tagMSG msg; + return static_cast(eventType - CustomEventsBegin); +} - while (FetchMessage(&msg)) { - if (msg.message != DVL_WM_QUIT) { - PushMessage(&msg); +uint32_t CustomEventToSdlEvent(interface_mode eventType) +{ + return CustomEventsBegin + eventType; +} + +void interface_msg_pump() +{ + SDL_Event event; + uint16_t modState; + while (FetchMessage(&event, &modState)) { + if (event.type != SDL_QUIT) { + HandleMessage(event, modState); } } } diff --git a/Source/interfac.h b/Source/interfac.h index c3ca87989..ab33c521d 100644 --- a/Source/interfac.h +++ b/Source/interfac.h @@ -11,24 +11,33 @@ namespace devilution { +/** + * @brief Custom events. + */ enum interface_mode : uint16_t { - // clang-format off - WM_DIABNEXTLVL = 0x402, // WM_USER+2 - WM_DIABPREVLVL = 0x403, - WM_DIABRTNLVL = 0x404, - WM_DIABSETLVL = 0x405, - WM_DIABWARPLVL = 0x406, - WM_DIABTOWNWARP = 0x407, - WM_DIABTWARPUP = 0x408, - WM_DIABRETOWN = 0x409, - WM_DIABNEWGAME = 0x40A, - WM_DIABLOADGAME = 0x40B, - // clang-format on + WM_DIABNEXTLVL = 0, + WM_DIABPREVLVL, + WM_DIABRTNLVL, + WM_DIABSETLVL, + WM_DIABWARPLVL, + WM_DIABTOWNWARP, + WM_DIABTWARPUP, + WM_DIABRETOWN, + WM_DIABNEWGAME, + WM_DIABLOADGAME, WM_FIRST = WM_DIABNEXTLVL, WM_LAST = WM_DIABLOADGAME, }; +void RegisterCustomEvents(); + +bool IsCustomEvent(uint32_t eventType); + +interface_mode GetCustomEvent(uint32_t eventType); + +uint32_t CustomEventToSdlEvent(interface_mode eventType); + enum Cutscenes : uint8_t { CutStart, CutTown, diff --git a/Source/miniwin/misc_msg.cpp b/Source/miniwin/misc_msg.cpp index 933882978..ef6e4c4a5 100644 --- a/Source/miniwin/misc_msg.cpp +++ b/Source/miniwin/misc_msg.cpp @@ -47,8 +47,6 @@ namespace devilution { -static std::deque message_queue; - void SetMouseButtonEvent(SDL_Event &event, uint32_t type, uint8_t button, Point position) { event.type = type; @@ -97,11 +95,6 @@ void FocusOnCharInfo() namespace { -uint32_t PositionForMouse(int16_t x, int16_t y) -{ - return (static_cast(y) << 16) | static_cast(x); -} - bool FalseAvail(const char *name, int value) { LogVerbose("Unhandled SDL event: {} {}", name, value); @@ -217,26 +210,19 @@ void ProcessGamepadEvents(GameAction &action) } // namespace -bool FetchMessage_Real(tagMSG *lpMsg) +bool FetchMessage_Real(SDL_Event *event, uint16_t *modState) { #ifdef __SWITCH__ HandleDocking(); #endif - if (!message_queue.empty()) { - *lpMsg = message_queue.front(); - message_queue.pop_front(); - return true; - } - SDL_Event e; if (PollEvent(&e) == 0) { return false; } - lpMsg->message = 0; - lpMsg->wParam = 0; - lpMsg->lParam = 0; + event->type = static_cast(0); + *modState = SDL_GetModState(); #ifdef __vita__ HandleTouchEvent(&e, MousePosition); @@ -244,8 +230,8 @@ bool FetchMessage_Real(tagMSG *lpMsg) HandleTouchEvent(e); #endif - if (e.type == SDL_QUIT) { - lpMsg->message = DVL_WM_QUIT; + if (e.type == SDL_QUIT || IsCustomEvent(e.type)) { + *event = e; return true; } @@ -292,21 +278,18 @@ bool FetchMessage_Real(tagMSG *lpMsg) if (GetGameAction(e, ctrlEvent, &action)) { if (movie_playing) { if (action.type != GameActionType_NONE) { - lpMsg->message = DVL_WM_KEYDOWN; + event->type = SDL_KEYDOWN; if (action.type == GameActionType_SEND_KEY) - lpMsg->wParam = action.send_key.vk_code; + event->key.keysym.sym = static_cast(action.send_key.vk_code); } } else if (action.type == GameActionType_SEND_KEY) { if ((action.send_key.vk_code & KeymapperMouseButtonMask) != 0) { const unsigned button = action.send_key.vk_code & ~KeymapperMouseButtonMask; - lpMsg->message = action.send_key.up - ? (button == SDL_BUTTON_LEFT ? DVL_WM_LBUTTONUP : DVL_WM_RBUTTONUP) - : (button == SDL_BUTTON_RIGHT ? DVL_WM_LBUTTONDOWN : DVL_WM_RBUTTONDOWN); - lpMsg->wParam = (static_cast(MousePosition.y) << 16) | static_cast(MousePosition.x); - lpMsg->lParam = 0; + SetMouseButtonEvent(*event, action.send_key.up ? SDL_MOUSEBUTTONUP : SDL_MOUSEBUTTONDOWN, static_cast(button), MousePosition); } else { - lpMsg->message = action.send_key.up ? DVL_WM_KEYUP : DVL_WM_KEYDOWN; - lpMsg->wParam = action.send_key.vk_code; + event->type = action.send_key.up ? SDL_KEYUP : SDL_KEYDOWN; + event->key.state = action.send_key.up ? SDL_PRESSED : SDL_RELEASED; + event->key.keysym.sym = static_cast(action.send_key.vk_code); } } else { ProcessGamepadEvents(action); @@ -318,9 +301,6 @@ bool FetchMessage_Real(tagMSG *lpMsg) return true; switch (e.type) { - case SDL_QUIT: - lpMsg->message = DVL_WM_QUIT; - break; case SDL_KEYDOWN: case SDL_KEYUP: { #ifdef USE_SDL1 @@ -340,72 +320,31 @@ bool FetchMessage_Real(tagMSG *lpMsg) remap_keyboard_key(&key); if (key == -1) return FalseAvail(e.type == SDL_KEYDOWN ? "SDL_KEYDOWN" : "SDL_KEYUP", e.key.keysym.sym); - lpMsg->message = e.type == SDL_KEYDOWN ? DVL_WM_KEYDOWN : DVL_WM_KEYUP; - lpMsg->wParam = static_cast(key); - lpMsg->lParam = e.key.keysym.mod; + event->type = e.type; + event->key.state = e.key.state; + event->key.keysym.sym = key; + event->key.keysym.mod = e.key.keysym.mod; } break; case SDL_MOUSEMOTION: - lpMsg->message = DVL_WM_MOUSEMOVE; - lpMsg->wParam = PositionForMouse(e.motion.x, e.motion.y); - lpMsg->lParam = SDL_GetModState(); + *event = e; if (ControlMode == ControlTypes::KeyboardAndMouse && invflag) InvalidateInventorySlot(); break; - case SDL_MOUSEBUTTONDOWN: { - lpMsg->wParam = PositionForMouse(e.button.x, e.button.y); - lpMsg->lParam = SDL_GetModState(); - const int button = e.button.button; - switch (button) { - case SDL_BUTTON_LEFT: - lpMsg->message = DVL_WM_LBUTTONDOWN; - break; - case SDL_BUTTON_RIGHT: - lpMsg->message = DVL_WM_RBUTTONDOWN; - break; - case SDL_BUTTON_MIDDLE: - lpMsg->message = DVL_WM_MBUTTONDOWN; - break; - case SDL_BUTTON_X1: - lpMsg->message = DVL_WM_X1BUTTONDOWN; - break; - case SDL_BUTTON_X2: - lpMsg->message = DVL_WM_X2BUTTONDOWN; - break; - } - } break; - case SDL_MOUSEBUTTONUP: { - lpMsg->wParam = PositionForMouse(e.button.x, e.button.y); - lpMsg->lParam = SDL_GetModState(); - const int button = e.button.button; - switch (button) { - case SDL_BUTTON_LEFT: - lpMsg->message = DVL_WM_LBUTTONUP; - break; - case SDL_BUTTON_RIGHT: - lpMsg->message = DVL_WM_RBUTTONUP; - break; - case SDL_BUTTON_MIDDLE: - lpMsg->message = DVL_WM_MBUTTONUP; - break; - case SDL_BUTTON_X1: - lpMsg->message = DVL_WM_X1BUTTONUP; - break; - case SDL_BUTTON_X2: - lpMsg->message = DVL_WM_X2BUTTONUP; - break; - } - } break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + *event = e; + break; #ifndef USE_SDL1 case SDL_MOUSEWHEEL: - lpMsg->message = DVL_WM_KEYDOWN; + event->type = SDL_KEYDOWN; if (e.wheel.y > 0) { - lpMsg->wParam = (SDL_GetModState() & KMOD_CTRL) != 0 ? SDLK_KP_PLUS : SDLK_UP; + event->key.keysym.sym = (SDL_GetModState() & KMOD_CTRL) != 0 ? SDLK_KP_PLUS : SDLK_UP; } else if (e.wheel.y < 0) { - lpMsg->wParam = (SDL_GetModState() & KMOD_CTRL) != 0 ? SDLK_KP_MINUS : SDLK_DOWN; + event->key.keysym.sym = (SDL_GetModState() & KMOD_CTRL) != 0 ? SDLK_KP_MINUS : SDLK_DOWN; } else if (e.wheel.x > 0) { - lpMsg->wParam = SDLK_LEFT; + event->key.keysym.sym = SDLK_LEFT; } else if (e.wheel.x < 0) { - lpMsg->wParam = SDLK_RIGHT; + event->key.keysym.sym = SDLK_RIGHT; } break; #if SDL_VERSION_ATLEAST(2, 0, 4) @@ -435,56 +374,11 @@ bool FetchMessage_Real(tagMSG *lpMsg) } return FalseAvail("SDL_TEXTINPUT", e.text.windowID); case SDL_WINDOWEVENT: - switch (e.window.event) { - case SDL_WINDOWEVENT_SHOWN: - gbActive = true; - lpMsg->message = DVL_WM_PAINT; - break; - case SDL_WINDOWEVENT_HIDDEN: - gbActive = false; - break; - case SDL_WINDOWEVENT_EXPOSED: - lpMsg->message = DVL_WM_PAINT; - break; - case SDL_WINDOWEVENT_LEAVE: - lpMsg->message = DVL_WM_CAPTURECHANGED; - break; - case SDL_WINDOWEVENT_SIZE_CHANGED: - ReinitializeHardwareCursor(); - break; - case SDL_WINDOWEVENT_MOVED: - case SDL_WINDOWEVENT_RESIZED: - case SDL_WINDOWEVENT_MINIMIZED: - case SDL_WINDOWEVENT_MAXIMIZED: - case SDL_WINDOWEVENT_RESTORED: -#if SDL_VERSION_ATLEAST(2, 0, 5) - case SDL_WINDOWEVENT_TAKE_FOCUS: -#endif - break; - case SDL_WINDOWEVENT_CLOSE: - lpMsg->message = DVL_WM_QUERYENDSESSION; - break; - - case SDL_WINDOWEVENT_FOCUS_LOST: - diablo_focus_pause(); - break; - case SDL_WINDOWEVENT_FOCUS_GAINED: - diablo_focus_unpause(); - break; - - default: - return FalseAvail("SDL_WINDOWEVENT", e.window.event); - } - + *event = e; break; #else case SDL_ACTIVEEVENT: - if ((e.active.state & SDL_APPINPUTFOCUS) != 0) { - if (e.active.gain == 0) - diablo_focus_pause(); - else - diablo_focus_unpause(); - } + *event = e; break; #endif default: @@ -493,31 +387,21 @@ bool FetchMessage_Real(tagMSG *lpMsg) return true; } -bool FetchMessage(tagMSG *lpMsg) +bool FetchMessage(SDL_Event *event, uint16_t *modState) { - bool available = demo::IsRunning() ? demo::FetchMessage(lpMsg) : FetchMessage_Real(lpMsg); + const bool available = demo::IsRunning() ? demo::FetchMessage(event, modState) : FetchMessage_Real(event, modState); if (available && demo::IsRecording()) - demo::RecordMessage(lpMsg); + demo::RecordMessage(*event, *modState); return available; } -void PushMessage(const tagMSG *lpMsg) +void HandleMessage(const SDL_Event &event, uint16_t modState) { assert(CurrentEventHandler != nullptr); - CurrentEventHandler(lpMsg->message, lpMsg->wParam, lpMsg->lParam); -} - -void PostMessage(uint32_t type, uint32_t wParam, uint16_t lParam) -{ - message_queue.push_back({ type, wParam, lParam }); -} - -void ClearMessageQueue() -{ - message_queue.clear(); + CurrentEventHandler(event, modState); } } // namespace devilution diff --git a/Source/miniwin/misc_msg.h b/Source/miniwin/misc_msg.h index 9d7e07d8b..e3095adaa 100644 --- a/Source/miniwin/misc_msg.h +++ b/Source/miniwin/misc_msg.h @@ -16,47 +16,14 @@ namespace devilution { -struct tagMSG { - uint32_t message; - uint32_t wParam; - uint16_t lParam; -}; - -typedef void (*EventHandler)(uint32_t, uint32_t, uint16_t); +using EventHandler = void (*)(const SDL_Event &event, uint16_t modState); void SetCursorPos(Point position); void FocusOnCharInfo(); void SetMouseButtonEvent(SDL_Event &event, uint32_t type, uint8_t button, Point position); -bool FetchMessage(tagMSG *lpMsg); - -void PushMessage(const tagMSG *lpMsg); -void PostMessage(uint32_t type, uint32_t wParam, uint16_t lParam); -void ClearMessageQueue(); - -// -// Events -// -#define DVL_WM_QUIT 0x0012 - -#define DVL_WM_MOUSEMOVE 0x0200 -#define DVL_WM_LBUTTONDOWN 0x0201 -#define DVL_WM_LBUTTONUP 0x0202 -#define DVL_WM_RBUTTONDOWN 0x0204 -#define DVL_WM_RBUTTONUP 0x0205 -#define DVL_WM_MBUTTONDOWN 0x0206 -#define DVL_WM_MBUTTONUP 0x0207 -#define DVL_WM_X1BUTTONDOWN 0x0208 -#define DVL_WM_X1BUTTONUP 0x0209 -#define DVL_WM_X2BUTTONDOWN 0x020A -#define DVL_WM_X2BUTTONUP 0x020B - -#define DVL_WM_KEYDOWN 0x0100 -#define DVL_WM_KEYUP 0x0101 - -#define DVL_WM_CAPTURECHANGED 0x0215 - -#define DVL_WM_PAINT 0x000F -#define DVL_WM_QUERYENDSESSION 0x0011 +bool FetchMessage(SDL_Event *event, uint16_t *modState); + +void HandleMessage(const SDL_Event &event, uint16_t modState); } // namespace devilution diff --git a/Source/movie.cpp b/Source/movie.cpp index de8618a8d..4cc76e44c 100644 --- a/Source/movie.cpp +++ b/Source/movie.cpp @@ -37,17 +37,17 @@ void play_movie(const char *pszMovie, bool userCanClose) } if (SVidPlayBegin(pszMovie, loop_movie ? 0x100C0808 : 0x10280808)) { - tagMSG msg; + SDL_Event event; + uint16_t modState; while (movie_playing) { - while (movie_playing && FetchMessage(&msg)) { - switch (msg.message) { - case DVL_WM_KEYDOWN: - case DVL_WM_LBUTTONUP: - case DVL_WM_RBUTTONUP: - if (userCanClose || (msg.message == DVL_WM_KEYDOWN && msg.wParam == SDLK_ESCAPE)) + while (movie_playing && FetchMessage(&event, &modState)) { + switch (event.type) { + case SDL_KEYDOWN: + case SDL_MOUSEBUTTONUP: + if (userCanClose || (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)) movie_playing = false; break; - case DVL_WM_QUIT: + case SDL_QUIT: SVidPlayEnd(); diablo_quit(0); } diff --git a/Source/player.cpp b/Source/player.cpp index 52894056e..81e5ae890 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -3191,7 +3191,9 @@ StartNewLvl(Player &player, interface_mode fom, int lvl) if (&player == MyPlayer) { player._pmode = PM_NEWLVL; player._pInvincible = true; - PostMessage(fom, 0, 0); + SDL_Event event; + event.type = CustomEventToSdlEvent(fom); + SDL_PushEvent(&event); if (gbIsMultiplayer) { NetSendCmdParam2(true, CMD_NEWLVL, fom, lvl); } @@ -3215,7 +3217,9 @@ void RestartTownLvl(Player &player) if (&player == MyPlayer) { player._pmode = PM_NEWLVL; player._pInvincible = true; - PostMessage(WM_DIABRETOWN, 0, 0); + SDL_Event event; + event.type = CustomEventToSdlEvent(WM_DIABRETOWN); + SDL_PushEvent(&event); } } @@ -3238,7 +3242,9 @@ void StartWarpLvl(Player &player, int pidx) SetCurrentPortal(pidx); player._pmode = PM_NEWLVL; player._pInvincible = true; - PostMessage(WM_DIABWARPLVL, 0, 0); + SDL_Event event; + event.type = CustomEventToSdlEvent(WM_DIABWARPLVL); + SDL_PushEvent(&event); } } diff --git a/Source/utils/display.cpp b/Source/utils/display.cpp index c9f1a959b..fb09cf37e 100644 --- a/Source/utils/display.cpp +++ b/Source/utils/display.cpp @@ -275,6 +275,7 @@ bool SpawnWindow(const char *lpWindowName) if (SDL_Init(initFlags) <= -1) { ErrSdl(); } + RegisterCustomEvents(); #ifndef USE_SDL1 if (sgOptions.Controller.szMapping[0] != '\0') { diff --git a/test/fixtures/timedemo/WarriorLevel1to2/demo_0.dmo b/test/fixtures/timedemo/WarriorLevel1to2/demo_0.dmo index 7dd62739d..76bd6b114 100644 Binary files a/test/fixtures/timedemo/WarriorLevel1to2/demo_0.dmo and b/test/fixtures/timedemo/WarriorLevel1to2/demo_0.dmo differ