From f490649905228eeec4597a0574f2e0f7b37dad61 Mon Sep 17 00:00:00 2001 From: GameParrot <85067619+GameParrot@users.noreply.github.com> Date: Sat, 3 May 2025 15:15:26 -0400 Subject: [PATCH] sdl3 fixes, add mods to onKeyboard --- include/game_window.h | 117 +++++---- include/key_mapping.h | 86 ++++++- src/window_eglut.cpp | 313 +++++++++++++++--------- src/window_eglut.h | 6 +- src/window_glfw.cpp | 310 +++++++++++++----------- src/window_glfw.h | 5 +- src/window_sdl3.cpp | 551 ++++++++++++++++++++++++++++++++---------- src/window_sdl3.h | 14 +- 8 files changed, 935 insertions(+), 467 deletions(-) diff --git a/include/game_window.h b/include/game_window.h index 27f2516..4c7bc5e 100644 --- a/include/game_window.h +++ b/include/game_window.h @@ -6,21 +6,43 @@ #include "key_mapping.h" enum class GraphicsApi { - OPENGL, OPENGL_ES2 + OPENGL, + OPENGL_ES2 }; enum class KeyAction { - PRESS, REPEAT, RELEASE + PRESS, + REPEAT, + RELEASE }; enum class MouseButtonAction { - PRESS, RELEASE + PRESS, + RELEASE }; enum class GamepadButtonId { - A, B, X, Y, LB, RB, BACK, START, GUIDE, LEFT_STICK, RIGHT_STICK, - DPAD_UP, DPAD_RIGHT, DPAD_DOWN, DPAD_LEFT, + A, + B, + X, + Y, + LB, + RB, + BACK, + START, + GUIDE, + LEFT_STICK, + RIGHT_STICK, + DPAD_UP, + DPAD_RIGHT, + DPAD_DOWN, + DPAD_LEFT, UNKNOWN = -1 }; enum class GamepadAxisId { - LEFT_X, LEFT_Y, RIGHT_X, RIGHT_Y, LEFT_TRIGGER, RIGHT_TRIGGER, + LEFT_X, + LEFT_Y, + RIGHT_X, + RIGHT_Y, + LEFT_TRIGGER, + RIGHT_TRIGGER, UNKNOWN = -1 }; struct FullscreenMode { @@ -29,24 +51,23 @@ struct FullscreenMode { }; class GameWindow { - public: - using DrawCallback = std::function; - using WindowSizeCallback = std::function; - using MouseButtonCallback = std::function; - using MousePositionCallback = std::function; - using MouseScrollCallback = std::function; - using TouchStartCallback = std::function; - using TouchUpdateCallback = std::function; - using TouchEndCallback = std::function; - using KeyboardCallback = std::function; - using KeyboardTextCallback = std::function; - using DropCallback = std::function; - using PasteCallback = std::function; - using GamepadStateCallback = std::function; - using GamepadButtonCallback = std::function; - using GamepadAxisCallback = std::function; - using CloseCallback = std::function; + using DrawCallback = std::function; + using WindowSizeCallback = std::function; + using MouseButtonCallback = std::function; + using MousePositionCallback = std::function; + using MouseScrollCallback = std::function; + using TouchStartCallback = std::function; + using TouchUpdateCallback = std::function; + using TouchEndCallback = std::function; + using KeyboardCallback = std::function; + using KeyboardTextCallback = std::function; + using DropCallback = std::function; + using PasteCallback = std::function; + using GamepadStateCallback = std::function; + using GamepadButtonCallback = std::function; + using GamepadAxisCallback = std::function; + using CloseCallback = std::function; private: DrawCallback drawCallback; @@ -67,7 +88,6 @@ class GameWindow { CloseCallback closeCallback; public: - GameWindow(std::string const& title, int width, int height, GraphicsApi api) {} virtual ~GameWindow() {} @@ -100,19 +120,23 @@ class GameWindow { virtual void setSwapInterval(int interval) = 0; virtual void startTextInput() {} - + virtual void stopTextInput() {} virtual void setFullscreenMode(const FullscreenMode& mode) {} virtual FullscreenMode getFullscreenMode() { - return { -1 }; + return {-1}; } virtual std::vector getFullscreenModes() { return {}; } + virtual uint32_t getKeyFromKeyCode(KeyCode code, int metaState) { + return 0; + } + void setDrawCallback(DrawCallback callback) { drawCallback = std::move(callback); } void setWindowSizeCallback(WindowSizeCallback callback) { windowSizeCallback = std::move(callback); } @@ -148,77 +172,74 @@ class GameWindow { void setCloseCallback(CloseCallback callback) { closeCallback = std::move(callback); } - protected: - void onDraw() { - if (drawCallback != nullptr) + if(drawCallback != nullptr) drawCallback(); } void onWindowSizeChanged(int w, int h) { - if (windowSizeCallback != nullptr) + if(windowSizeCallback != nullptr) windowSizeCallback(w, h); } void onMouseButton(double x, double y, int button, MouseButtonAction action) { - if (mouseButtonCallback != nullptr) + if(mouseButtonCallback != nullptr) mouseButtonCallback(x, y, button, action); } void onMousePosition(double x, double y) { - if (mousePositionCallback != nullptr) + if(mousePositionCallback != nullptr) mousePositionCallback(x, y); } void onMouseRelativePosition(double x, double y) { - if (mouseRelativePositionCallback != nullptr) + if(mouseRelativePositionCallback != nullptr) mouseRelativePositionCallback(x, y); } void onMouseScroll(double x, double y, double dx, double dy) { - if (mouseScrollCallback != nullptr) + if(mouseScrollCallback != nullptr) mouseScrollCallback(x, y, dx, dy); } void onTouchStart(int id, double x, double y) { - if (touchStartCallback != nullptr) + if(touchStartCallback != nullptr) touchStartCallback(id, x, y); } void onTouchUpdate(int id, double x, double y) { - if (touchUpdateCallback != nullptr) + if(touchUpdateCallback != nullptr) touchUpdateCallback(id, x, y); } void onTouchEnd(int id, double x, double y) { - if (touchEndCallback != nullptr) + if(touchEndCallback != nullptr) touchEndCallback(id, x, y); } - void onKeyboard(KeyCode key, KeyAction action) { - if (keyboardCallback != nullptr) - keyboardCallback(key, action); + void onKeyboard(KeyCode key, KeyAction action, int mods) { + if(keyboardCallback != nullptr) + keyboardCallback(key, action, mods); } void onKeyboardText(std::string const& c) { - if (keyboardTextCallback != nullptr) + if(keyboardTextCallback != nullptr) keyboardTextCallback(c); } void onDrop(std::string const& path) { - if (dropCallback != nullptr) { + if(dropCallback != nullptr) { dropCallback(path); } } void onPaste(std::string const& c) { - if (pasteCallback != nullptr) + if(pasteCallback != nullptr) pasteCallback(c); } void onGamepadState(int id, bool connected) { - if (gamepadStateCallback != nullptr) + if(gamepadStateCallback != nullptr) gamepadStateCallback(id, connected); } void onGamepadButton(int id, GamepadButtonId btn, bool pressed) { - if (gamepadButtonCallback != nullptr && btn != GamepadButtonId::UNKNOWN) + if(gamepadButtonCallback != nullptr && btn != GamepadButtonId::UNKNOWN) gamepadButtonCallback(id, btn, pressed); } void onGamepadAxis(int id, GamepadAxisId axis, float val) { - if (gamepadAxisCallback != nullptr && axis != GamepadAxisId::UNKNOWN) + if(gamepadAxisCallback != nullptr && axis != GamepadAxisId::UNKNOWN) gamepadAxisCallback(id, axis, val); } void onClose() { - if (closeCallback != nullptr) + if(closeCallback != nullptr) closeCallback(); } - }; diff --git a/include/key_mapping.h b/include/key_mapping.h index a7b50e0..bad303b 100644 --- a/include/key_mapping.h +++ b/include/key_mapping.h @@ -7,9 +7,9 @@ enum class KeyCode { TAB = 9, ENTER = 13, LEFT_SHIFT = 16, - RIGHT_SHIFT = 16|256, + RIGHT_SHIFT = 16 | 256, LEFT_CTRL = 17, - RIGHT_CTRL = 17|256, + RIGHT_CTRL = 17 | 256, PAUSE = 19, CAPS_LOCK = 20, ESCAPE = 27, @@ -24,11 +24,70 @@ enum class KeyCode { DOWN = 40, INSERT = 45, DELETE = 46, - NUM_0 = 48, NUM_1, NUM_2, NUM_3, NUM_4, NUM_5, NUM_6, NUM_7, NUM_8, NUM_9 = 57, - NUMPAD_0 = 0x60, NUMPAD_1, NUMPAD_2, NUMPAD_3, NUMPAD_4, NUMPAD_5, NUMPAD_6, NUMPAD_7, NUMPAD_8, NUMPAD_9 = 0x69, - NUMPAD_MULTIPLY = 0x6a, NUMPAD_ADD, NUMPAD_SEPERATOR, NUMPAD_SUBTRACT, NUMPAD_DECIMAL, NUMPAD_DIVIDE = 0x6F, - A = 65, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z = 90, - FN1 = 112, FN2, FN3, FN4, FN5, FN6, FN7, FN8, FN9, FN10, FN11, FN12, + NUM_0 = 48, + NUM_1, + NUM_2, + NUM_3, + NUM_4, + NUM_5, + NUM_6, + NUM_7, + NUM_8, + NUM_9 = 57, + NUMPAD_0 = 0x60, + NUMPAD_1, + NUMPAD_2, + NUMPAD_3, + NUMPAD_4, + NUMPAD_5, + NUMPAD_6, + NUMPAD_7, + NUMPAD_8, + NUMPAD_9 = 0x69, + NUMPAD_MULTIPLY = 0x6a, + NUMPAD_ADD, + NUMPAD_SEPERATOR, + NUMPAD_SUBTRACT, + NUMPAD_DECIMAL, + NUMPAD_DIVIDE = 0x6F, + A = 65, + B, + C, + D, + E, + F, + G, + H, + I, + J, + K, + L, + M, + N, + O, + P, + Q, + R, + S, + T, + U, + V, + W, + X, + Y, + Z = 90, + FN1 = 112, + FN2, + FN3, + FN4, + FN5, + FN6, + FN7, + FN8, + FN9, + FN10, + FN11, + FN12, NUM_LOCK = 144, SCROLL_LOCK = 145, SEMICOLON = 186, @@ -46,7 +105,14 @@ enum class KeyCode { // Keys not defined in Minecraft but we use them anyways LEFT_SUPER = 1, - RIGHT_SUPER = 1|256, + RIGHT_SUPER = 1 | 256, LEFT_ALT = 0x12, - RIGHT_ALT = 0x12|256 -}; \ No newline at end of file + RIGHT_ALT = 0x12 | 256 +}; + +#define KEY_MOD_SHIFT (1 << 0) +#define KEY_MOD_CTRL (1 << 1) +#define KEY_MOD_SUPER (1 << 2) +#define KEY_MOD_ALT (1 << 3) +#define KEY_MOD_CAPSLOCK (1 << 4) +#define KEY_MOD_NUMLOCK (1 << 5) \ No newline at end of file diff --git a/src/window_eglut.cpp b/src/window_eglut.cpp index 6b8bc79..793623b 100644 --- a/src/window_eglut.cpp +++ b/src/window_eglut.cpp @@ -10,18 +10,25 @@ #define XK_XKB_KEYS #include +#define ShiftMask (1 << 0) +#define LockMask (1 << 1) +#define ControlMask (1 << 2) +#define Mod1Mask (1 << 3) +#define Mod2Mask (1 << 4) +#define Mod3Mask (1 << 5) +#define Mod4Mask (1 << 6) +#define Mod5Mask (1 << 7) + EGLUTWindow* EGLUTWindow::currentWindow; -EGLUTWindow::EGLUTWindow(const std::string& title, int width, int height, GraphicsApi api) : - WindowWithLinuxJoystick(title, width, height, api), title(title), width(width), height(height), - graphicsApi(api) { +EGLUTWindow::EGLUTWindow(const std::string& title, int width, int height, GraphicsApi api) : WindowWithLinuxJoystick(title, width, height, api), title(title), width(width), height(height), graphicsApi(api) { #ifdef GAMEWINDOW_X11_LOCK std::lock_guard lock(x11_sync); #endif eglutInitWindowSize(width, height); - if (graphicsApi == GraphicsApi::OPENGL_ES2) + if(graphicsApi == GraphicsApi::OPENGL_ES2) eglutInitAPIMask(EGLUT_OPENGL_ES2_BIT); - if (graphicsApi == GraphicsApi::OPENGL) + if(graphicsApi == GraphicsApi::OPENGL) eglutInitAPIMask(EGLUT_OPENGL_BIT); winId = eglutCreateWindow(title.c_str()); @@ -49,13 +56,13 @@ EGLUTWindow::~EGLUTWindow() { #ifdef GAMEWINDOW_X11_LOCK std::lock_guard lock(x11_sync); #endif - if (currentWindow == this) + if(currentWindow == this) currentWindow = nullptr; - if (winId != -1) + if(winId != -1) eglutDestroyWindow(winId); } -void EGLUTWindow::setIcon(std::string const &iconPath) { +void EGLUTWindow::setIcon(std::string const& iconPath) { #ifdef GAMEWINDOW_X11_LOCK std::lock_guard lock(x11_sync); #endif @@ -106,8 +113,8 @@ void EGLUTWindow::setCursorDisabled(bool disabled) { #ifdef GAMEWINDOW_X11_LOCK std::lock_guard lock(x11_sync); #endif - if (!disabled && !getenv("GAMEWINDOW_CENTER_CURSOR")) { - eglutWarpMousePointer(lastMouseX,lastMouseY); + if(!disabled && !getenv("GAMEWINDOW_CENTER_CURSOR")) { + eglutWarpMousePointer(lastMouseX, lastMouseY); } cursorDisabled = disabled; eglutSetMousePointerLocked(disabled ? EGLUT_POINTER_LOCKED : EGLUT_POINTER_UNLOCKED); @@ -121,7 +128,7 @@ void EGLUTWindow::setFullscreen(bool fullscreen) { #ifdef GAMEWINDOW_X11_LOCK std::lock_guard lock(x11_sync); #endif - if (eglutGet(EGLUT_FULLSCREEN_MODE) != (fullscreen ? EGLUT_FULLSCREEN : EGLUT_WINDOWED)) + if(eglutGet(EGLUT_FULLSCREEN_MODE) != (fullscreen ? EGLUT_FULLSCREEN : EGLUT_WINDOWED)) eglutToggleFullscreen(); } @@ -140,20 +147,20 @@ void EGLUTWindow::setSwapInterval(int interval) { } void EGLUTWindow::_eglutIdleFunc() { - if (currentWindow == nullptr) + if(currentWindow == nullptr) return; currentWindow->updateGamepad(); eglutPostRedisplay(); } void EGLUTWindow::_eglutDisplayFunc() { - if (currentWindow == nullptr) + if(currentWindow == nullptr) return; currentWindow->onDraw(); } void EGLUTWindow::_eglutReshapeFunc(int w, int h) { - if (currentWindow == nullptr || (currentWindow->width == w && currentWindow->height == h)) + if(currentWindow == nullptr || (currentWindow->width == w && currentWindow->height == h)) return; currentWindow->onWindowSizeChanged(w, h); currentWindow->width = w; @@ -163,40 +170,39 @@ void EGLUTWindow::_eglutReshapeFunc(int w, int h) { void EGLUTWindow::_eglutMouseFunc(int x, int y) { currentWindow->lastMouseX = x; currentWindow->lastMouseY = y; - if (currentWindow == nullptr) + if(currentWindow == nullptr) return; currentWindow->onMousePosition(x, y); } void EGLUTWindow::_eglutMouseRawFunc(double x, double y) { - if (currentWindow == nullptr) + if(currentWindow == nullptr) return; currentWindow->onMouseRelativePosition(x, y); } void EGLUTWindow::_eglutMouseButtonFunc(int x, int y, int btn, int action) { - if (currentWindow == nullptr) + if(currentWindow == nullptr) return; - if ((btn == 4 || btn == 5) && action == EGLUT_MOUSE_PRESS) { + if((btn == 4 || btn == 5) && action == EGLUT_MOUSE_PRESS) { currentWindow->onMouseScroll(x, y, 0.0, (btn == 5 ? -1.0 : 1.0)); return; } - if ((btn == 6 || btn == 7) && action == EGLUT_MOUSE_PRESS) { + if((btn == 6 || btn == 7) && action == EGLUT_MOUSE_PRESS) { currentWindow->onMouseScroll(x, y, (btn == 7 ? -1.0 : 1.0), 0.0); return; } btn = (btn == 2 ? 3 : (btn == 3 ? 2 : btn)); - currentWindow->onMouseButton(x, y, btn, action == EGLUT_MOUSE_PRESS ? MouseButtonAction::PRESS : - MouseButtonAction::RELEASE); + currentWindow->onMouseButton(x, y, btn, action == EGLUT_MOUSE_PRESS ? MouseButtonAction::PRESS : MouseButtonAction::RELEASE); } int EGLUTWindow::obtainTouchPointer(int eglutId) { - for (int i = 0; i < sizeof(pointerIds) / sizeof(int); i++) { - if (pointerIds[i] == eglutId) + for(int i = 0; i < sizeof(pointerIds) / sizeof(int); i++) { + if(pointerIds[i] == eglutId) return i; } - for (int i = 0; i < sizeof(pointerIds) / sizeof(int); i++) { - if (pointerIds[i] == -1) { + for(int i = 0; i < sizeof(pointerIds) / sizeof(int); i++) { + if(pointerIds[i] == -1) { pointerIds[i] = eglutId; return i; } @@ -209,21 +215,21 @@ void EGLUTWindow::releaseTouchPointer(int ourId) { } void EGLUTWindow::_eglutTouchStartFunc(int id, double x, double y) { - if (currentWindow == nullptr) + if(currentWindow == nullptr) return; int ourId = currentWindow->obtainTouchPointer(id); currentWindow->onTouchStart(ourId, x, y); } void EGLUTWindow::_eglutTouchUpdateFunc(int id, double x, double y) { - if (currentWindow == nullptr) + if(currentWindow == nullptr) return; int ourId = currentWindow->obtainTouchPointer(id); currentWindow->onTouchUpdate(ourId, x, y); } void EGLUTWindow::_eglutTouchEndFunc(int id, double x, double y) { - if (currentWindow == nullptr) + if(currentWindow == nullptr) return; int ourId = currentWindow->obtainTouchPointer(id); currentWindow->onTouchEnd(ourId, x, y); @@ -231,12 +237,12 @@ void EGLUTWindow::_eglutTouchEndFunc(int id, double x, double y) { } void EGLUTWindow::_eglutKeyboardFunc(char str[5], int action) { - if (currentWindow == nullptr || - strcmp(str, "\t") == 0 || strcmp(str, "\03") == 0 || strcmp(str, "\26") == 0 || - strcmp(str, "\33") == 0) // \t, copy, paste, esc + if(currentWindow == nullptr || + strcmp(str, "\t") == 0 || strcmp(str, "\03") == 0 || strcmp(str, "\26") == 0 || + strcmp(str, "\33") == 0) // \t, copy, paste, esc return; - if (action == EGLUT_KEY_PRESS || action == EGLUT_KEY_REPEAT) { - if (str[0] == 13 && str[1] == 0) + if(action == EGLUT_KEY_PRESS || action == EGLUT_KEY_REPEAT) { + if(str[0] == 13 && str[1] == 0) str[0] = 10; std::stringstream ss; ss << str; @@ -245,123 +251,169 @@ void EGLUTWindow::_eglutKeyboardFunc(char str[5], int action) { } void EGLUTWindow::_eglutDropFunc(const char* path) { - if (currentWindow == nullptr) + if(currentWindow == nullptr) return; currentWindow->onDrop(path); } KeyCode EGLUTWindow::getKeyMinecraft(int keyCode) { - if (keyCode >= XK_A && keyCode <= XK_Z) - return (KeyCode) (keyCode - XK_A + (int) KeyCode::A); - if (keyCode >= XK_a && keyCode <= XK_z) - return (KeyCode) (keyCode - XK_a + (int) KeyCode::A); - if (keyCode >= XK_F1 && keyCode <= XK_F12) - return (KeyCode) (keyCode - XK_F1 + (int) KeyCode::FN1); + if(keyCode >= XK_A && keyCode <= XK_Z) + return (KeyCode)(keyCode - XK_A + (int)KeyCode::A); + if(keyCode >= XK_a && keyCode <= XK_z) + return (KeyCode)(keyCode - XK_a + (int)KeyCode::A); + if(keyCode >= XK_F1 && keyCode <= XK_F12) + return (KeyCode)(keyCode - XK_F1 + (int)KeyCode::FN1); // if (keyCode >= XK_exclam && keyCode <= XK_parenleft) // return (KeyCode) (keyCode - XK_exclam + (int) KeyCode::NUM_1); - if (keyCode >= XK_KP_0 && keyCode <= XK_KP_9) - return (KeyCode) (keyCode - XK_KP_0 + (int) KeyCode::NUMPAD_0); - if (keyCode >= XK_KP_Multiply && keyCode <= XK_KP_Divide) - return (KeyCode) (keyCode - XK_KP_Multiply + (int) KeyCode::NUMPAD_MULTIPLY); - if (keyCode >= XK_KP_Home && keyCode <= XK_KP_Down) - return (KeyCode) (keyCode - XK_KP_Home + (int) KeyCode::HOME); - if (keyCode >= XK_KP_Prior && keyCode <= XK_KP_End) - return (KeyCode) (keyCode - XK_KP_Prior + (int) KeyCode::PAGE_UP); - - switch (keyCode) { - case XK_exclam: return KeyCode::NUM_1; - case XK_at: return KeyCode::NUM_2; - case XK_numbersign: return KeyCode::NUM_3; - case XK_dollar: return KeyCode::NUM_4; - case XK_percent: return KeyCode::NUM_5; - case XK_asciicircum: return KeyCode::NUM_6; - case XK_ampersand: return KeyCode::NUM_7; - case XK_asterisk: return KeyCode::NUM_8; - case XK_parenleft: return KeyCode::NUM_9; - case XK_parenright: return KeyCode::NUM_0; - case XK_underscore: return KeyCode::MINUS; - case XK_plus: return KeyCode::EQUAL; - - // case XK_parenright: return KeyCode::RIGHT_BRACKET; - case XK_BackSpace: return KeyCode::BACKSPACE; - case XK_ISO_Left_Tab: - case XK_Tab: return KeyCode::TAB; - case XK_Return: return KeyCode::ENTER; - case XK_Shift_L: return KeyCode::LEFT_SHIFT; - case XK_Shift_R: return KeyCode::RIGHT_SHIFT; - case XK_Control_L: return KeyCode::LEFT_CTRL; - case XK_Control_R: return KeyCode::RIGHT_CTRL; - case XK_Pause: return KeyCode::PAUSE; - case XK_Caps_Lock: return KeyCode::CAPS_LOCK; - case XK_Escape: return KeyCode::ESCAPE; - case XK_Page_Up: return KeyCode::PAGE_UP; - case XK_Page_Down: return KeyCode::PAGE_DOWN; - case XK_End: return KeyCode::END; - case XK_Home: return KeyCode::HOME; - case XK_Left: return KeyCode::LEFT; - case XK_Up: return KeyCode::UP; - case XK_Right: return KeyCode::RIGHT; - case XK_Down: return KeyCode::DOWN; - case XK_Insert: return KeyCode::INSERT; - case XK_Delete: return KeyCode::DELETE; - case XK_Num_Lock: return KeyCode::NUM_LOCK; - case XK_Scroll_Lock: return KeyCode::SCROLL_LOCK; - case XK_semicolon: return KeyCode::SEMICOLON; - case XK_equal: return KeyCode::EQUAL; - case XK_comma: return KeyCode::COMMA; - case XK_minus: return KeyCode::MINUS; - case XK_period: return KeyCode::PERIOD; - case XK_slash: return KeyCode::SLASH; - case XK_grave: return KeyCode::GRAVE; - case XK_bracketleft: return KeyCode::LEFT_BRACKET; - case XK_backslash: return KeyCode::BACKSLASH; - case XK_bracketright: return KeyCode::RIGHT_BRACKET; - case XK_apostrophe: return KeyCode::APOSTROPHE; - case XK_Alt_L: return KeyCode::LEFT_ALT; - case XK_Alt_R: return KeyCode::RIGHT_ALT; - case XK_KP_Enter: return KeyCode::ENTER; + if(keyCode >= XK_KP_0 && keyCode <= XK_KP_9) + return (KeyCode)(keyCode - XK_KP_0 + (int)KeyCode::NUMPAD_0); + if(keyCode >= XK_KP_Multiply && keyCode <= XK_KP_Divide) + return (KeyCode)(keyCode - XK_KP_Multiply + (int)KeyCode::NUMPAD_MULTIPLY); + if(keyCode >= XK_KP_Home && keyCode <= XK_KP_Down) + return (KeyCode)(keyCode - XK_KP_Home + (int)KeyCode::HOME); + if(keyCode >= XK_KP_Prior && keyCode <= XK_KP_End) + return (KeyCode)(keyCode - XK_KP_Prior + (int)KeyCode::PAGE_UP); + + switch(keyCode) { + case XK_exclam: + return KeyCode::NUM_1; + case XK_at: + return KeyCode::NUM_2; + case XK_numbersign: + return KeyCode::NUM_3; + case XK_dollar: + return KeyCode::NUM_4; + case XK_percent: + return KeyCode::NUM_5; + case XK_asciicircum: + return KeyCode::NUM_6; + case XK_ampersand: + return KeyCode::NUM_7; + case XK_asterisk: + return KeyCode::NUM_8; + case XK_parenleft: + return KeyCode::NUM_9; + case XK_parenright: + return KeyCode::NUM_0; + case XK_underscore: + return KeyCode::MINUS; + case XK_plus: + return KeyCode::EQUAL; + + // case XK_parenright: return KeyCode::RIGHT_BRACKET; + case XK_BackSpace: + return KeyCode::BACKSPACE; + case XK_ISO_Left_Tab: + case XK_Tab: + return KeyCode::TAB; + case XK_Return: + return KeyCode::ENTER; + case XK_Shift_L: + return KeyCode::LEFT_SHIFT; + case XK_Shift_R: + return KeyCode::RIGHT_SHIFT; + case XK_Control_L: + return KeyCode::LEFT_CTRL; + case XK_Control_R: + return KeyCode::RIGHT_CTRL; + case XK_Pause: + return KeyCode::PAUSE; + case XK_Caps_Lock: + return KeyCode::CAPS_LOCK; + case XK_Escape: + return KeyCode::ESCAPE; + case XK_Page_Up: + return KeyCode::PAGE_UP; + case XK_Page_Down: + return KeyCode::PAGE_DOWN; + case XK_End: + return KeyCode::END; + case XK_Home: + return KeyCode::HOME; + case XK_Left: + return KeyCode::LEFT; + case XK_Up: + return KeyCode::UP; + case XK_Right: + return KeyCode::RIGHT; + case XK_Down: + return KeyCode::DOWN; + case XK_Insert: + return KeyCode::INSERT; + case XK_Delete: + return KeyCode::DELETE; + case XK_Num_Lock: + return KeyCode::NUM_LOCK; + case XK_Scroll_Lock: + return KeyCode::SCROLL_LOCK; + case XK_semicolon: + return KeyCode::SEMICOLON; + case XK_equal: + return KeyCode::EQUAL; + case XK_comma: + return KeyCode::COMMA; + case XK_minus: + return KeyCode::MINUS; + case XK_period: + return KeyCode::PERIOD; + case XK_slash: + return KeyCode::SLASH; + case XK_grave: + return KeyCode::GRAVE; + case XK_bracketleft: + return KeyCode::LEFT_BRACKET; + case XK_backslash: + return KeyCode::BACKSLASH; + case XK_bracketright: + return KeyCode::RIGHT_BRACKET; + case XK_apostrophe: + return KeyCode::APOSTROPHE; + case XK_Alt_L: + return KeyCode::LEFT_ALT; + case XK_Alt_R: + return KeyCode::RIGHT_ALT; + case XK_KP_Enter: + return KeyCode::ENTER; } - if (keyCode < 256) - return (KeyCode) keyCode; + if(keyCode < 256) + return (KeyCode)keyCode; return KeyCode::UNKNOWN; } -void EGLUTWindow::_eglutKeyboardSpecialFunc(int key, int action) { - if (currentWindow == nullptr) +void EGLUTWindow::_eglutKeyboardSpecialFunc(int key, int action, unsigned int meta) { + if(currentWindow == nullptr) return; - if (key == 65507) - currentWindow->modCTRL = (action != EGLUT_KEY_RELEASE); - if (currentWindow->modCTRL && (key == 86 || key == 118) && action == EGLUT_KEY_PRESS) { - eglutRequestPaste(); - } + int mods = translateMeta(meta); KeyCode mKey = getKeyMinecraft(key); - KeyAction enumAction = (action == EGLUT_KEY_PRESS ? KeyAction::PRESS : - (action == EGLUT_KEY_REPEAT ? KeyAction::REPEAT : KeyAction::RELEASE)); - if (mKey != KeyCode::UNKNOWN) { - currentWindow->onKeyboard(mKey, enumAction); + KeyAction enumAction = (action == EGLUT_KEY_PRESS ? KeyAction::PRESS : (action == EGLUT_KEY_REPEAT ? KeyAction::REPEAT : KeyAction::RELEASE)); + if(mKey != KeyCode::UNKNOWN) { + currentWindow->onKeyboard(mKey, enumAction, mods); + } + if((key == 86 || key == 118) && mods & KEY_MOD_CTRL && action == EGLUT_KEY_PRESS) { + eglutRequestPaste(); } #ifndef NDEBUG - else if (enumAction == KeyAction::PRESS){ + else if(enumAction == KeyAction::PRESS) { GameWindowManager::getManager()->getErrorHandler()->onError("EGLUT Unknown Key", "Please check your Keyboard Layout. No Fallback Implemented"); } #endif } void EGLUTWindow::_eglutPasteFunc(const char* str, int len) { - if (currentWindow == nullptr) + if(currentWindow == nullptr) return; currentWindow->onPaste(std::string(str, len)); } void EGLUTWindow::_eglutFocusFunc(int action) { - if (currentWindow == nullptr) + if(currentWindow == nullptr) return; LinuxGamepadJoystickManager::instance.onWindowFocused(currentWindow, (action == EGLUT_FOCUSED)); } void EGLUTWindow::_eglutCloseWindowFunc() { - if (currentWindow == nullptr) + if(currentWindow == nullptr) return; currentWindow->onClose(); } @@ -371,9 +423,32 @@ void EGLUTWindow::getWindowSize(int& width, int& height) const { height = this->height; } -void EGLUTWindow::setClipboardText(std::string const &text) { +void EGLUTWindow::setClipboardText(std::string const& text) { #ifdef GAMEWINDOW_X11_LOCK std::lock_guard lock(x11_sync); #endif eglutSetClipboardText(text.c_str()); } + +int EGLUTWindow::translateMeta(unsigned int meta) { + int mods = 0; + if(meta & ShiftMask) { + mods |= KEY_MOD_SHIFT; + } + if(meta & ControlMask) { + mods |= KEY_MOD_CTRL; + } + if(meta & Mod1Mask) { + mods |= KEY_MOD_ALT; + } + if(meta & Mod4Mask) { + mods |= KEY_MOD_SUPER; + } + if(meta & LockMask) { + mods |= KEY_MOD_CAPSLOCK; + } + if(meta & Mod2Mask) { + mods |= KEY_MOD_NUMLOCK; + } + return mods; +} \ No newline at end of file diff --git a/src/window_eglut.h b/src/window_eglut.h index 7c4e32c..02aab8f 100644 --- a/src/window_eglut.h +++ b/src/window_eglut.h @@ -8,7 +8,6 @@ #include class EGLUTWindow : public WindowWithLinuxJoystick { - private: static EGLUTWindow* currentWindow; @@ -19,7 +18,6 @@ class EGLUTWindow : public WindowWithLinuxJoystick { bool cursorDisabled = false; bool moveMouseToCenter = false; int lastMouseX = -1, lastMouseY = -1; - bool modCTRL = false; int pointerIds[16]; #ifdef GAMEWINDOW_X11_LOCK @@ -39,13 +37,14 @@ class EGLUTWindow : public WindowWithLinuxJoystick { static void _eglutTouchEndFunc(int id, double x, double y); static void _eglutKeyboardFunc(char str[5], int action); static void _eglutDropFunc(const char* path); - static void _eglutKeyboardSpecialFunc(int key, int action); + static void _eglutKeyboardSpecialFunc(int key, int action, unsigned int meta); static void _eglutPasteFunc(const char* str, int len); static void _eglutFocusFunc(int action); static void _eglutCloseWindowFunc(); int obtainTouchPointer(int eglutId); void releaseTouchPointer(int ourId); + static int translateMeta(unsigned int meta); public: EGLUTWindow(const std::string& title, int width, int height, GraphicsApi api); @@ -77,5 +76,4 @@ class EGLUTWindow : public WindowWithLinuxJoystick { void swapBuffers() override; void setSwapInterval(int interval) override; - }; diff --git a/src/window_glfw.cpp b/src/window_glfw.cpp index bda2f3c..7e0a85b 100644 --- a/src/window_glfw.cpp +++ b/src/window_glfw.cpp @@ -9,25 +9,24 @@ #include -GLFWGameWindow::GLFWGameWindow(const std::string& title, int width, int height, GraphicsApi api) : - GameWindow(title, width, height, api), width(width), height(height), windowedWidth(width), windowedHeight(height) { +GLFWGameWindow::GLFWGameWindow(const std::string& title, int width, int height, GraphicsApi api) : GameWindow(title, width, height, api), width(width), height(height), windowedWidth(width), windowedHeight(height) { #ifdef GAMEWINDOW_X11_LOCK std::lock_guard lock(x11_sync); #endif glfwDefaultWindowHints(); - if (api == GraphicsApi::OPENGL_ES2) { + if(api == GraphicsApi::OPENGL_ES2) { glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); - } else if (api == GraphicsApi::OPENGL) { + } else if(api == GraphicsApi::OPENGL) { glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); } window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr); - if (window == nullptr && api == GraphicsApi::OPENGL_ES2) { + if(window == nullptr && api == GraphicsApi::OPENGL_ES2) { // Failed to get es3 request es2 glfwDefaultWindowHints(); glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); @@ -89,7 +88,7 @@ void GLFWGameWindow::setRelativeScale() { int wx, wy; glfwGetWindowSize(window, &wx, &wy); - relativeScale = (((double) fx / (double) wx) + ((double) fy / (double) wy)) / 2.0; + relativeScale = (((double)fx / (double)wx) + ((double)fy / (double)wy)) / 2.0; // Update window size to match content size mismatch width = fx; height = fy; @@ -135,8 +134,8 @@ void GLFWGameWindow::pollEvents() { if(requestFullscreen) { glfwGetWindowPos(window, &windowedX, &windowedY); // convert pixels to window coordinates getRelativeScale() is 2 on macOS retina screens - windowedWidth = (int) floor(width / getRelativeScale()); - windowedHeight = (int) floor(height / getRelativeScale()); + windowedWidth = (int)floor(width / getRelativeScale()); + windowedHeight = (int)floor(height / getRelativeScale()); GLFWmonitor* monitor = glfwGetPrimaryMonitor(); int nModes = 0; auto modes = glfwGetVideoModes(monitor, &nModes); @@ -155,15 +154,15 @@ void GLFWGameWindow::pollEvents() { auto display = glfwGetWindowMonitor(window); if(display) { auto modes = glfwGetVideoModes(display, &nModes); - if(nModes > mode.id && mode.description == getModeDescription(modes[mode.id])) { + if(mode.id != -1 && nModes > mode.id && mode.description == getModeDescription(modes[mode.id])) { glfwSetWindowMonitor(window, display, 0, 0, modes[mode.id].width, modes[mode.id].height, modes[mode.id].refreshRate); } } } glfwPollEvents(); if(resized) { - onWindowSizeChanged(width, height); - resized = false; + onWindowSizeChanged(width, height); + resized = false; } GLFWJoystickManager::update(this); } @@ -176,14 +175,14 @@ void GLFWGameWindow::setCursorDisabled(bool disabled) { #ifdef GAMEWINDOW_X11_LOCK std::lock_guard lock(x11_sync); #endif - if (disabled) { - if (glfwRawMouseMotionSupported()) + if(disabled) { + if(glfwRawMouseMotionSupported()) glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE); - if (getenv("GAMEWINDOW_CENTER_CURSOR")) { + if(getenv("GAMEWINDOW_CENTER_CURSOR")) { glfwSetCursorPos(window, (width / 2) / getRelativeScale(), (height / 2) / getRelativeScale()); } } else { - if (glfwRawMouseMotionSupported()) + if(glfwRawMouseMotionSupported()) glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_FALSE); } glfwSetInputMode(window, GLFW_CURSOR, disabled ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_NORMAL); @@ -203,7 +202,7 @@ void GLFWGameWindow::setFullscreen(bool fullscreen) { requestFullscreen = fullscreen; } -void GLFWGameWindow::setClipboardText(std::string const &text) { +void GLFWGameWindow::setClipboardText(std::string const& text) { #ifdef GAMEWINDOW_X11_LOCK std::lock_guard lock(x11_sync); #endif @@ -247,16 +246,16 @@ void GLFWGameWindow::setSwapInterval(int interval) { } void GLFWGameWindow::_glfwWindowSizeCallback(GLFWwindow* window, int w, int h) { - GLFWGameWindow* user = (GLFWGameWindow*) glfwGetWindowUserPointer(window); + GLFWGameWindow* user = (GLFWGameWindow*)glfwGetWindowUserPointer(window); user->width = w; user->height = h; user->resized = true; } void GLFWGameWindow::_glfwCursorPosCallback(GLFWwindow* window, double x, double y) { - GLFWGameWindow* user = (GLFWGameWindow*) glfwGetWindowUserPointer(window); + GLFWGameWindow* user = (GLFWGameWindow*)glfwGetWindowUserPointer(window); - if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) { + if(glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) { double dx = (x - user->lastMouseX) * user->getRelativeScale(); double dy = (y - user->lastMouseY) * user->getRelativeScale(); @@ -272,7 +271,7 @@ void GLFWGameWindow::_glfwCursorPosCallback(GLFWwindow* window, double x, double } void GLFWGameWindow::_glfwMouseButtonCallback(GLFWwindow* window, int button, int action, int mods) { - GLFWGameWindow* user = (GLFWGameWindow*) glfwGetWindowUserPointer(window); + GLFWGameWindow* user = (GLFWGameWindow*)glfwGetWindowUserPointer(window); double x, y; glfwGetCursorPos(window, &x, &y); @@ -283,175 +282,175 @@ void GLFWGameWindow::_glfwMouseButtonCallback(GLFWwindow* window, int button, in } void GLFWGameWindow::_glfwScrollCallback(GLFWwindow* window, double x, double y) { - GLFWGameWindow* user = (GLFWGameWindow*) glfwGetWindowUserPointer(window); + GLFWGameWindow* user = (GLFWGameWindow*)glfwGetWindowUserPointer(window); double cx, cy; glfwGetCursorPos(window, &cx, &cy); user->onMouseScroll(cx, cy, x, y); } KeyCode GLFWGameWindow::getKeyMinecraft(int keyCode) { - if (keyCode >= GLFW_KEY_F1 && keyCode <= GLFW_KEY_F12) - return (KeyCode) (keyCode - GLFW_KEY_F1 + (int) KeyCode::FN1); - if (keyCode >= GLFW_KEY_KP_0 && keyCode <= GLFW_KEY_KP_9) - return (KeyCode) (keyCode - GLFW_KEY_KP_0 + (int) KeyCode::NUMPAD_0); - switch (keyCode) { - case GLFW_KEY_BACKSPACE: - return KeyCode::BACKSPACE; - case GLFW_KEY_TAB: - return KeyCode::TAB; - case GLFW_KEY_ENTER: - return KeyCode::ENTER; - case GLFW_KEY_LEFT_SHIFT: - return KeyCode::LEFT_SHIFT; - case GLFW_KEY_RIGHT_SHIFT: - return KeyCode::RIGHT_SHIFT; - case GLFW_KEY_LEFT_CONTROL: - return KeyCode::LEFT_CTRL; - case GLFW_KEY_RIGHT_CONTROL: - return KeyCode::RIGHT_CTRL; - case GLFW_KEY_PAUSE: - return KeyCode::PAUSE; - case GLFW_KEY_CAPS_LOCK: - return KeyCode::CAPS_LOCK; - case GLFW_KEY_ESCAPE: - return KeyCode::ESCAPE; - case GLFW_KEY_PAGE_UP: - return KeyCode::PAGE_UP; - case GLFW_KEY_PAGE_DOWN: - return KeyCode::PAGE_DOWN; - case GLFW_KEY_END: - return KeyCode::END; - case GLFW_KEY_HOME: - return KeyCode::HOME; - case GLFW_KEY_LEFT: - return KeyCode::LEFT; - case GLFW_KEY_UP: - return KeyCode::UP; - case GLFW_KEY_RIGHT: - return KeyCode::RIGHT; - case GLFW_KEY_DOWN: - return KeyCode::DOWN; - case GLFW_KEY_INSERT: - return KeyCode::INSERT; - case GLFW_KEY_DELETE: - return KeyCode::DELETE; - case GLFW_KEY_NUM_LOCK: - return KeyCode::NUM_LOCK; - case GLFW_KEY_SCROLL_LOCK: - return KeyCode::SCROLL_LOCK; - case GLFW_KEY_SEMICOLON: - return KeyCode::SEMICOLON; - case GLFW_KEY_EQUAL: - return KeyCode::EQUAL; - case GLFW_KEY_COMMA: - return KeyCode::COMMA; - case GLFW_KEY_MINUS: - return KeyCode::MINUS; - case GLFW_KEY_PERIOD: - return KeyCode::PERIOD; - case GLFW_KEY_SLASH: - return KeyCode::SLASH; - case GLFW_KEY_GRAVE_ACCENT: - return KeyCode::GRAVE; - case GLFW_KEY_LEFT_BRACKET: - return KeyCode::LEFT_BRACKET; - case GLFW_KEY_BACKSLASH: - return KeyCode::BACKSLASH; - case GLFW_KEY_RIGHT_BRACKET: - return KeyCode::RIGHT_BRACKET; - case GLFW_KEY_APOSTROPHE: - return KeyCode::APOSTROPHE; - - case GLFW_KEY_LEFT_SUPER: - return KeyCode::LEFT_SUPER; - case GLFW_KEY_RIGHT_SUPER: - return KeyCode::RIGHT_SUPER; - case GLFW_KEY_LEFT_ALT: - return KeyCode::LEFT_ALT; - case GLFW_KEY_RIGHT_ALT: - return KeyCode::RIGHT_ALT; - - case GLFW_KEY_KP_ENTER: - return KeyCode::ENTER; - case GLFW_KEY_KP_SUBTRACT: - return KeyCode::NUMPAD_SUBTRACT; - case GLFW_KEY_KP_MULTIPLY: - return KeyCode::NUMPAD_MULTIPLY; - case GLFW_KEY_KP_ADD: - return KeyCode::NUMPAD_ADD; - case GLFW_KEY_KP_DIVIDE: - return KeyCode::NUMPAD_DIVIDE; - case GLFW_KEY_KP_DECIMAL: - return KeyCode::NUMPAD_DECIMAL; + if(keyCode >= GLFW_KEY_F1 && keyCode <= GLFW_KEY_F12) + return (KeyCode)(keyCode - GLFW_KEY_F1 + (int)KeyCode::FN1); + if(keyCode >= GLFW_KEY_KP_0 && keyCode <= GLFW_KEY_KP_9) + return (KeyCode)(keyCode - GLFW_KEY_KP_0 + (int)KeyCode::NUMPAD_0); + switch(keyCode) { + case GLFW_KEY_BACKSPACE: + return KeyCode::BACKSPACE; + case GLFW_KEY_TAB: + return KeyCode::TAB; + case GLFW_KEY_ENTER: + return KeyCode::ENTER; + case GLFW_KEY_LEFT_SHIFT: + return KeyCode::LEFT_SHIFT; + case GLFW_KEY_RIGHT_SHIFT: + return KeyCode::RIGHT_SHIFT; + case GLFW_KEY_LEFT_CONTROL: + return KeyCode::LEFT_CTRL; + case GLFW_KEY_RIGHT_CONTROL: + return KeyCode::RIGHT_CTRL; + case GLFW_KEY_PAUSE: + return KeyCode::PAUSE; + case GLFW_KEY_CAPS_LOCK: + return KeyCode::CAPS_LOCK; + case GLFW_KEY_ESCAPE: + return KeyCode::ESCAPE; + case GLFW_KEY_PAGE_UP: + return KeyCode::PAGE_UP; + case GLFW_KEY_PAGE_DOWN: + return KeyCode::PAGE_DOWN; + case GLFW_KEY_END: + return KeyCode::END; + case GLFW_KEY_HOME: + return KeyCode::HOME; + case GLFW_KEY_LEFT: + return KeyCode::LEFT; + case GLFW_KEY_UP: + return KeyCode::UP; + case GLFW_KEY_RIGHT: + return KeyCode::RIGHT; + case GLFW_KEY_DOWN: + return KeyCode::DOWN; + case GLFW_KEY_INSERT: + return KeyCode::INSERT; + case GLFW_KEY_DELETE: + return KeyCode::DELETE; + case GLFW_KEY_NUM_LOCK: + return KeyCode::NUM_LOCK; + case GLFW_KEY_SCROLL_LOCK: + return KeyCode::SCROLL_LOCK; + case GLFW_KEY_SEMICOLON: + return KeyCode::SEMICOLON; + case GLFW_KEY_EQUAL: + return KeyCode::EQUAL; + case GLFW_KEY_COMMA: + return KeyCode::COMMA; + case GLFW_KEY_MINUS: + return KeyCode::MINUS; + case GLFW_KEY_PERIOD: + return KeyCode::PERIOD; + case GLFW_KEY_SLASH: + return KeyCode::SLASH; + case GLFW_KEY_GRAVE_ACCENT: + return KeyCode::GRAVE; + case GLFW_KEY_LEFT_BRACKET: + return KeyCode::LEFT_BRACKET; + case GLFW_KEY_BACKSLASH: + return KeyCode::BACKSLASH; + case GLFW_KEY_RIGHT_BRACKET: + return KeyCode::RIGHT_BRACKET; + case GLFW_KEY_APOSTROPHE: + return KeyCode::APOSTROPHE; + + case GLFW_KEY_LEFT_SUPER: + return KeyCode::LEFT_SUPER; + case GLFW_KEY_RIGHT_SUPER: + return KeyCode::RIGHT_SUPER; + case GLFW_KEY_LEFT_ALT: + return KeyCode::LEFT_ALT; + case GLFW_KEY_RIGHT_ALT: + return KeyCode::RIGHT_ALT; + + case GLFW_KEY_KP_ENTER: + return KeyCode::ENTER; + case GLFW_KEY_KP_SUBTRACT: + return KeyCode::NUMPAD_SUBTRACT; + case GLFW_KEY_KP_MULTIPLY: + return KeyCode::NUMPAD_MULTIPLY; + case GLFW_KEY_KP_ADD: + return KeyCode::NUMPAD_ADD; + case GLFW_KEY_KP_DIVIDE: + return KeyCode::NUMPAD_DIVIDE; + case GLFW_KEY_KP_DECIMAL: + return KeyCode::NUMPAD_DECIMAL; } - if (keyCode < 256) - return (KeyCode) keyCode; + if(keyCode < 256) + return (KeyCode)keyCode; return KeyCode::UNKNOWN; } void GLFWGameWindow::_glfwKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { - GLFWGameWindow* user = (GLFWGameWindow*) glfwGetWindowUserPointer(window); + GLFWGameWindow* user = (GLFWGameWindow*)glfwGetWindowUserPointer(window); + if(action == GLFW_PRESS || action == GLFW_REPEAT) { + if(key == GLFW_KEY_BACKSPACE) + user->onKeyboardText("\x08"); + if(key == GLFW_KEY_DELETE) + user->onKeyboardText("\x7f"); + if(key == GLFW_KEY_ENTER) + user->onKeyboardText("\n"); + } + KeyAction enumAction = (action == GLFW_PRESS ? KeyAction::PRESS : (action == GLFW_REPEAT ? KeyAction::REPEAT : KeyAction::RELEASE)); + auto minecraftKey = getKeyMinecraft(key); + int meta = translateMeta(mods); + if(key != GLFW_KEY_UNKNOWN && minecraftKey != KeyCode::UNKNOWN) { + user->onKeyboard(minecraftKey, enumAction, meta); + } #ifdef __APPLE__ - if (action == GLFW_PRESS && mods & GLFW_MOD_SUPER && key == GLFW_KEY_V) { + if(action == GLFW_PRESS && mods & GLFW_MOD_SUPER && key == GLFW_KEY_V) { #else - if (action == GLFW_PRESS && mods & GLFW_MOD_CONTROL && key == GLFW_KEY_V) { + if(action == GLFW_PRESS && mods & GLFW_MOD_CONTROL && key == GLFW_KEY_V) { #endif auto clipboardString = glfwGetClipboardString(window); if(clipboardString != nullptr) user->onPaste(clipboardString); } - if (action == GLFW_PRESS || action == GLFW_REPEAT) { - if (key == GLFW_KEY_BACKSPACE) - user->onKeyboardText("\x08"); - if (key == GLFW_KEY_DELETE) - user->onKeyboardText("\x7f"); - if (key == GLFW_KEY_ENTER) - user->onKeyboardText("\n"); - } - KeyAction enumAction = (action == GLFW_PRESS ? KeyAction::PRESS : - (action == GLFW_REPEAT ? KeyAction::REPEAT : KeyAction::RELEASE)); - auto minecraftKey = getKeyMinecraft(key); - if (key != GLFW_KEY_UNKNOWN && minecraftKey != KeyCode::UNKNOWN) { - user->onKeyboard(minecraftKey, enumAction); - } #ifndef NDEBUG else { - if (!user->warnedButtons) { + if(!user->warnedButtons) { user->warnedButtons = true; GameWindowManager::getManager()->getErrorHandler()->onError("GLFW Unknown Key", "Please check your Keyboard Layout. Falling back to scancode for unknown Keys."); } - user->onKeyboard((KeyCode) scancode, enumAction); + user->onKeyboard((KeyCode)scancode, enumAction, meta); } #endif } void GLFWGameWindow::_glfwCharCallback(GLFWwindow* window, unsigned int ch) { - GLFWGameWindow* user = (GLFWGameWindow*) glfwGetWindowUserPointer(window); + GLFWGameWindow* user = (GLFWGameWindow*)glfwGetWindowUserPointer(window); std::wstring_convert, char32_t> cvt; user->onKeyboardText(cvt.to_bytes(ch)); } void GLFWGameWindow::_glfwDropCallback(GLFWwindow* window, int count, const char** paths) { - GLFWGameWindow* user = (GLFWGameWindow*) glfwGetWindowUserPointer(window); - for (int i = 0; i < count; i++) { + GLFWGameWindow* user = (GLFWGameWindow*)glfwGetWindowUserPointer(window); + for(int i = 0; i < count; i++) { user->onDrop(std::string(paths[i])); } } void GLFWGameWindow::_glfwWindowCloseCallback(GLFWwindow* window) { - GLFWGameWindow* user = (GLFWGameWindow*) glfwGetWindowUserPointer(window); + GLFWGameWindow* user = (GLFWGameWindow*)glfwGetWindowUserPointer(window); glfwSetWindowShouldClose(window, GLFW_FALSE); user->onClose(); } void GLFWGameWindow::_glfwWindowFocusCallback(GLFWwindow* window, int focused) { - GLFWGameWindow* user = (GLFWGameWindow*) glfwGetWindowUserPointer(window); + GLFWGameWindow* user = (GLFWGameWindow*)glfwGetWindowUserPointer(window); GLFWJoystickManager::onWindowFocused(user, focused == GLFW_TRUE); user->focused = (focused == GLFW_TRUE); } void GLFWGameWindow::_glfwWindowContentScaleCallback(GLFWwindow* window, float scalex, float scaley) { - GLFWGameWindow* user = (GLFWGameWindow*) glfwGetWindowUserPointer(window); + GLFWGameWindow* user = (GLFWGameWindow*)glfwGetWindowUserPointer(window); user->setRelativeScale(); } @@ -466,7 +465,7 @@ std::vector GLFWGameWindow::getFullscreenModes() { auto display = glfwGetPrimaryMonitor(); auto modes = glfwGetVideoModes(display, &nModes); for(int j = 0; j < nModes; j++) { - this->modes.emplace_back(FullscreenMode { .id = j, .description = getModeDescription(modes[j])}); + this->modes.emplace_back(FullscreenMode{.id = j, .description = getModeDescription(modes[j])}); } } return modes; @@ -481,9 +480,32 @@ FullscreenMode GLFWGameWindow::getFullscreenMode() { auto desc = getModeDescription(*mode); for(int i = 0; i < nModes; i++) { if(desc == getModeDescription(modes[i])) { - return FullscreenMode { .id = i, .description = desc}; + return FullscreenMode{.id = i, .description = desc}; } } } - return FullscreenMode { -1 }; + return FullscreenMode{-1}; } + +int GLFWGameWindow::translateMeta(unsigned int meta) { + int mods = 0; + if(meta & GLFW_MOD_SHIFT) { + mods |= KEY_MOD_SHIFT; + } + if(meta & GLFW_MOD_CONTROL) { + mods |= KEY_MOD_CTRL; + } + if(meta & GLFW_MOD_ALT) { + mods |= KEY_MOD_ALT; + } + if(meta & GLFW_MOD_SUPER) { + mods |= KEY_MOD_SUPER; + } + if(meta & GLFW_MOD_CAPS_LOCK) { + mods |= KEY_MOD_CAPSLOCK; + } + if(meta & GLFW_MOD_NUM_LOCK) { + mods |= KEY_MOD_NUMLOCK; + } + return mods; +} \ No newline at end of file diff --git a/src/window_glfw.h b/src/window_glfw.h index 630f781..9d81267 100644 --- a/src/window_glfw.h +++ b/src/window_glfw.h @@ -9,7 +9,6 @@ #include class GLFWGameWindow : public GameWindow { - private: GLFWwindow* window; double lastMouseX = 0.0, lastMouseY = 0.0; @@ -25,7 +24,7 @@ class GLFWGameWindow : public GameWindow { bool requestFullscreen = false; bool pendingFullscreenModeSwitch = false; std::vector modes; - FullscreenMode mode = { -1 }; + FullscreenMode mode = {-1}; std::chrono::time_point lastFrame; int swapInterval = 0; int checkBrokenVSync = 0; @@ -38,6 +37,7 @@ class GLFWGameWindow : public GameWindow { #endif static KeyCode getKeyMinecraft(int keyCode); + static int translateMeta(unsigned int meta); static void _glfwWindowSizeCallback(GLFWwindow* window, int w, int h); static void _glfwCursorPosCallback(GLFWwindow* window, double x, double y); @@ -51,7 +51,6 @@ class GLFWGameWindow : public GameWindow { static void _glfwWindowContentScaleCallback(GLFWwindow* window, float scalex, float scaley); public: - GLFWGameWindow(const std::string& title, int width, int height, GraphicsApi api); ~GLFWGameWindow() override; diff --git a/src/window_sdl3.cpp b/src/window_sdl3.cpp index f3bf79c..56fe148 100644 --- a/src/window_sdl3.cpp +++ b/src/window_sdl3.cpp @@ -9,14 +9,21 @@ #include #include -SDL3GameWindow::SDL3GameWindow(const std::string& title, int width, int height, GraphicsApi api) : - GameWindow(title, width, height, api), width(width), height(height), windowedWidth(width), windowedHeight(height) { +struct SDL_X11CursorData { + void* cursor; +}; +struct SDL_X11Cursor { + SDL_X11Cursor* next; + SDL_X11CursorData* internal; +}; + +SDL3GameWindow::SDL3GameWindow(const std::string& title, int width, int height, GraphicsApi api) : GameWindow(title, width, height, api), width(width), height(height), windowedWidth(width), windowedHeight(height) { SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); - SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0"); + SDL_SetHint(SDL_HINT_APP_NAME, "Minecraft"); if(api == GraphicsApi::OPENGL_ES2) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); } else if(api == GraphicsApi::OPENGL) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); @@ -44,6 +51,12 @@ SDL3GameWindow::SDL3GameWindow(const std::string& title, int width, int height, // SDL_SetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD, "0"); SDL_StopTextInput(window); setRelativeScale(); + + // HACK: Force SDL to not alter the cursor on x11, fixing cursor scaling issues + if(strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { + SDL_X11Cursor* def = (SDL_X11Cursor*)SDL_GetDefaultCursor(); + def->internal->cursor = NULL; + } } void SDL3GameWindow::makeCurrent(bool c) { @@ -58,7 +71,6 @@ SDL3GameWindow::~SDL3GameWindow() { } void SDL3GameWindow::setIcon(std::string const& iconPath) { - } void SDL3GameWindow::setRelativeScale() { @@ -68,7 +80,7 @@ void SDL3GameWindow::setRelativeScale() { int wx, wy; SDL_GetWindowSize(window, &wx, &wy); - relativeScale = (int) floor(((fx / wx) + (fy / wy)) / 2); + relativeScale = (int)floor(((fx / wx) + (fy / wy)) / 2); relativeScaleX = (double)fx / wx; relativeScaleY = (double)fy / wy; // Update window size to match content size mismatch @@ -99,8 +111,7 @@ void SDL3GameWindow::close() { } static GamepadButtonId getKeyGamePad(int btn) { - switch (btn) - { + switch(btn) { case SDL_GAMEPAD_BUTTON_SOUTH: return GamepadButtonId::A; case SDL_GAMEPAD_BUTTON_EAST: @@ -137,8 +148,7 @@ static GamepadButtonId getKeyGamePad(int btn) { } static GamepadAxisId getAxisGamepad(int btn) { - switch (btn) - { + switch(btn) { case SDL_GAMEPAD_AXIS_LEFT_TRIGGER: return GamepadAxisId::LEFT_TRIGGER; case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER: @@ -161,8 +171,7 @@ static int getMouseButton(int btn) { // To match glfw codebase return 8 + btn - SDL_BUTTON_X1; } - switch (btn) - { + switch(btn) { case SDL_BUTTON_LEFT: return 1; case SDL_BUTTON_RIGHT: @@ -187,17 +196,20 @@ void SDL3GameWindow::pollEvents() { } if(pendingFullscreenModeSwitch) { pendingFullscreenModeSwitch = false; - int nModes = 0; - auto display = SDL_GetDisplayForWindow(window); - auto modes = SDL_GetFullscreenDisplayModes(display, &nModes); - if(nModes > mode.id && mode.description == getModeDescription(modes[mode.id])) { - SDL_SetWindowFullscreenMode(window, modes[mode.id]); + if(mode.id == -1) { + SDL_SetWindowFullscreenMode(window, NULL); + } else { + int nModes = 0; + auto display = SDL_GetDisplayForWindow(window); + auto modes = SDL_GetFullscreenDisplayModes(display, &nModes); + if(nModes > mode.id && mode.description == getModeDescription(modes[mode.id])) { + SDL_SetWindowFullscreenMode(window, modes[mode.id]); + } } } SDL_Event ev; while(SDL_PollEvent(&ev)) { - switch (ev.type) - { + switch(ev.type) { case SDL_EVENT_MOUSE_MOTION: if(!SDL_GetWindowRelativeMouseMode(window)) { onMousePosition(ev.motion.x * relativeScaleX, ev.motion.y * relativeScaleY); @@ -212,22 +224,19 @@ void SDL3GameWindow::pollEvents() { case SDL_EVENT_MOUSE_BUTTON_UP: onMouseButton(ev.button.x, ev.button.y, getMouseButton(ev.button.button), ev.type == SDL_EVENT_MOUSE_BUTTON_DOWN ? MouseButtonAction::PRESS : MouseButtonAction::RELEASE); break; - case SDL_EVENT_FINGER_DOWN: - { + case SDL_EVENT_FINGER_DOWN: { int w, h; getWindowSize(w, h); onTouchStart(ev.tfinger.fingerID, ev.tfinger.x * w, ev.tfinger.y * h); break; } - case SDL_EVENT_FINGER_UP: - { + case SDL_EVENT_FINGER_UP: { int w, h; getWindowSize(w, h); onTouchEnd(ev.tfinger.fingerID, ev.tfinger.x * w, ev.tfinger.y * h); break; } - case SDL_EVENT_FINGER_MOTION: - { + case SDL_EVENT_FINGER_MOTION: { int w, h; getWindowSize(w, h); onTouchUpdate(ev.tfinger.fingerID, ev.tfinger.x * w, ev.tfinger.y * h); @@ -249,18 +258,20 @@ void SDL3GameWindow::pollEvents() { } } - if(SDL_GetModState() & SDL_KMOD_CTRL && ev.key.key == SDLK_V) { + SDL_Keymod mods; + mods = SDL_GetModState(); + if(mods & SDL_KMOD_CTRL && ev.key.key == SDLK_V && ev.type == SDL_EVENT_KEY_DOWN) { auto str = SDL_GetClipboardText(); onPaste(str); } - onKeyboard(getKeyMinecraft(SDL_GetKeyFromScancode(ev.key.scancode, SDL_KMOD_NONE, false)), ev.type == SDL_EVENT_KEY_DOWN ? ev.key.repeat ? KeyAction::REPEAT : KeyAction::PRESS : KeyAction::RELEASE ); + onKeyboard(getKeyMinecraft(SDL_GetKeyFromScancode(ev.key.scancode, SDL_KMOD_NONE, false)), ev.type == SDL_EVENT_KEY_DOWN ? ev.key.repeat ? KeyAction::REPEAT : KeyAction::PRESS : KeyAction::RELEASE, translateMeta(mods)); break; case SDL_EVENT_GAMEPAD_BUTTON_DOWN: case SDL_EVENT_GAMEPAD_BUTTON_UP: onGamepadButton(ev.gbutton.which, getKeyGamePad(ev.gbutton.button), ev.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN); break; case SDL_EVENT_GAMEPAD_AXIS_MOTION: - onGamepadAxis(ev.gaxis.which, getAxisGamepad(ev.gaxis.axis), (float)ev.gaxis.value / 32767.0f ); + onGamepadAxis(ev.gaxis.which, getAxisGamepad(ev.gaxis.axis), (float)ev.gaxis.value / 32767.0f); break; case SDL_EVENT_GAMEPAD_ADDED: case SDL_EVENT_GAMEPAD_REMOVED: { @@ -275,6 +286,14 @@ void SDL3GameWindow::pollEvents() { } case SDL_EVENT_WINDOW_RESIZED: setRelativeScale(); + if(cursorDisabled) { + const SDL_Rect* currentMouseRect = SDL_GetWindowMouseRect(window); + if(currentMouseRect != NULL && (currentMouseRect->x > width || currentMouseRect->y > height)) { + SDL_Rect r = SDL_Rect{.x = width / 2, .y = height / 2, .w = 1, .h = 1}; + SDL_SetWindowMouseRect(window, &r); + SDL_WarpMouseInWindow(window, width / 2, height / 2); + } + } break; case SDL_EVENT_TEXT_INPUT: onKeyboardText(ev.text.text ? ev.text.text : ""); @@ -282,7 +301,11 @@ void SDL3GameWindow::pollEvents() { case SDL_EVENT_DROP_FILE: onDrop(ev.drop.data); break; - case SDL_EVENT_WINDOW_CLOSE_REQUESTED: + case SDL_EVENT_DROP_TEXT: + onPaste(ev.drop.data); + break; + // case SDL_EVENT_WINDOW_CLOSE_REQUESTED: + case SDL_EVENT_QUIT: onClose(); break; case SDL_EVENT_WINDOW_DISPLAY_CHANGED: @@ -292,6 +315,26 @@ void SDL3GameWindow::pollEvents() { case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED: setRelativeScale(); break; + case SDL_EVENT_WINDOW_FOCUS_GAINED: + if(cursorDisabled) { + float x, y; + SDL_GetGlobalMouseState(&x, &y); + int windowX, windowY; + SDL_GetWindowPosition(window, &windowX, &windowY); + SDL_Rect r = {.x = (int)x - windowX, .y = (int)y - windowY, .w = 1, .h = 1}; + SDL_SetWindowMouseRect(window, &r); + SDL_SetWindowRelativeMouseMode(window, true); + } + break; + case SDL_EVENT_WINDOW_FOCUS_LOST: + if(cursorDisabled) { + SDL_SetWindowRelativeMouseMode(window, false); + SDL_SetWindowMouseRect(window, NULL); + } + if(centerMouseNextEnable) { + centerMouseNextEnable = false; + } + break; default: break; } @@ -306,7 +349,33 @@ bool SDL3GameWindow::getCursorDisabled() { } void SDL3GameWindow::setCursorDisabled(bool disabled) { - SDL_SetWindowRelativeMouseMode(window, disabled); + if(disabled == cursorDisabled) { + return; + } + cursorDisabled = disabled; + SDL_WindowFlags flags = SDL_GetWindowFlags(window); + if(flags & SDL_WINDOW_INPUT_FOCUS) { + if(disabled) { + if(isMouseInWindow()) { + float x, y; + SDL_GetMouseState(&x, &y); + SDL_Rect r = {.x = (int)x, .y = (int)y, .w = 1, .h = 1}; + SDL_SetWindowMouseRect(window, &r); + } else { + SDL_WarpMouseInWindow(window, width / 2, height / 2); + SDL_Rect r = {.x = width / 2, .y = height / 2, .w = 1, .h = 1}; + SDL_SetWindowMouseRect(window, &r); + centerMouseNextEnable = true; + } + } else { + SDL_SetWindowMouseRect(window, NULL); + if(getenv("GAMEWINDOW_CENTER_CURSOR") || centerMouseNextEnable) { + SDL_WarpMouseInWindow(window, width / 2, height / 2); + centerMouseNextEnable = false; + } + } + SDL_SetWindowRelativeMouseMode(window, disabled); + } } void SDL3GameWindow::setFullscreenMode(const FullscreenMode& mode) { @@ -323,11 +392,11 @@ FullscreenMode SDL3GameWindow::getFullscreenMode() { auto desc = getModeDescription(mode); for(int i = 0; i < nModes; i++) { if(desc == getModeDescription(modes[i])) { - return FullscreenMode { .id = i, .description = desc}; + return FullscreenMode{.id = i, .description = desc}; } } } - return FullscreenMode { -1 }; + return FullscreenMode{-1}; } std::vector SDL3GameWindow::getFullscreenModes() { @@ -336,7 +405,7 @@ std::vector SDL3GameWindow::getFullscreenModes() { auto display = SDL_GetDisplayForWindow(window); auto modes = SDL_GetFullscreenDisplayModes(display, &nModes); for(int j = 0; j < nModes; j++) { - this->modes.emplace_back(FullscreenMode { .id = j, .description = getModeDescription(modes[j]) }); + this->modes.emplace_back(FullscreenMode{.id = j, .description = getModeDescription(modes[j])}); } } return modes; @@ -347,13 +416,13 @@ bool SDL3GameWindow::getFullscreen() { } void SDL3GameWindow::setFullscreen(bool fullscreen) { - if (fullscreen) + if(fullscreen) requestedWindowMode = RequestWindowMode::Fullscreen; else requestedWindowMode = RequestWindowMode::Windowed; } -void SDL3GameWindow::setClipboardText(std::string const &text) { +void SDL3GameWindow::setClipboardText(std::string const& text) { SDL_SetClipboardText(text.data()); } @@ -378,104 +447,318 @@ void SDL3GameWindow::stopTextInput() { // SDL_StartTextInput(); } +bool SDL3GameWindow::isMouseInWindow() { + int windowX, windowY; + SDL_GetWindowPosition(window, &windowX, &windowY); + float mouseX, mouseY; + SDL_GetGlobalMouseState(&mouseX, &mouseY); + return (mouseX >= windowX && mouseY >= windowY && mouseX <= windowX + width && mouseY <= windowY + height); +} + KeyCode SDL3GameWindow::getKeyMinecraft(int keyCode) { - if (keyCode >= SDLK_F1 && keyCode <= SDLK_F12) - return (KeyCode) (keyCode - SDLK_F1 + (int) KeyCode::FN1); - if (keyCode >= SDLK_KP_1 && keyCode <= SDLK_KP_9) - return (KeyCode) (keyCode - SDLK_KP_1 + (int) KeyCode::NUMPAD_1); - if (keyCode >= SDLK_A && keyCode <= SDLK_Z) - return (KeyCode) (keyCode - SDLK_A + (int) KeyCode::A); - switch (keyCode) { - case SDLK_BACKSPACE: - return KeyCode::BACKSPACE; - case SDLK_TAB: - return KeyCode::TAB; - case SDLK_RETURN: - return KeyCode::ENTER; - case SDLK_LSHIFT: - return KeyCode::LEFT_SHIFT; - case SDLK_RSHIFT: - return KeyCode::RIGHT_SHIFT; - case SDLK_LCTRL: - return KeyCode::LEFT_CTRL; - case SDLK_RCTRL: - return KeyCode::RIGHT_CTRL; - case SDLK_PAUSE: - return KeyCode::PAUSE; - case SDLK_CAPSLOCK: - return KeyCode::CAPS_LOCK; - case SDLK_ESCAPE: - return KeyCode::ESCAPE; - case SDLK_PAGEUP: - return KeyCode::PAGE_UP; - case SDLK_PAGEDOWN: - return KeyCode::PAGE_DOWN; - case SDLK_END: - return KeyCode::END; - case SDLK_HOME: - return KeyCode::HOME; - case SDLK_LEFT: - return KeyCode::LEFT; - case SDLK_UP: - return KeyCode::UP; - case SDLK_RIGHT: - return KeyCode::RIGHT; - case SDLK_DOWN: - return KeyCode::DOWN; - case SDLK_INSERT: - return KeyCode::INSERT; - case SDLK_DELETE: - return KeyCode::DELETE; - case SDLK_NUMLOCKCLEAR: - return KeyCode::NUM_LOCK; - case SDLK_SCROLLLOCK: - return KeyCode::SCROLL_LOCK; - case SDLK_SEMICOLON: - return KeyCode::SEMICOLON; - case SDLK_EQUALS: - return KeyCode::EQUAL; - case SDLK_COMMA: - return KeyCode::COMMA; - case SDLK_MINUS: - return KeyCode::MINUS; - case SDLK_PERIOD: - return KeyCode::PERIOD; - case SDLK_SLASH: - return KeyCode::SLASH; - case SDLK_GRAVE: - return KeyCode::GRAVE; - case SDLK_LEFTBRACKET: - return KeyCode::LEFT_BRACKET; - case SDLK_BACKSLASH: - return KeyCode::BACKSLASH; - case SDLK_RIGHTBRACKET: - return KeyCode::RIGHT_BRACKET; - case SDLK_APOSTROPHE: - return KeyCode::APOSTROPHE; - case SDLK_LGUI: - return KeyCode::LEFT_SUPER; - case SDLK_RGUI: - return KeyCode::RIGHT_SUPER; - case SDLK_LALT: - return KeyCode::LEFT_ALT; - case SDLK_RALT: - return KeyCode::RIGHT_ALT; - case SDLK_KP_ENTER: - return KeyCode::ENTER; - case SDLK_KP_MINUS: - return KeyCode::NUMPAD_SUBTRACT; - case SDLK_KP_MULTIPLY: - return KeyCode::NUMPAD_MULTIPLY; - case SDLK_KP_PLUS: - return KeyCode::NUMPAD_ADD; - case SDLK_KP_DIVIDE: - return KeyCode::NUMPAD_DIVIDE; - case SDLK_KP_DECIMAL: - return KeyCode::NUMPAD_DECIMAL; - case SDLK_KP_0: - return KeyCode::NUMPAD_0; - } - if (keyCode < 256) - return (KeyCode) keyCode; + if(keyCode >= SDLK_F1 && keyCode <= SDLK_F12) + return (KeyCode)(keyCode - SDLK_F1 + (int)KeyCode::FN1); + if(keyCode >= SDLK_KP_1 && keyCode <= SDLK_KP_9) + return (KeyCode)(keyCode - SDLK_KP_1 + (int)KeyCode::NUMPAD_1); + if(keyCode >= SDLK_A && keyCode <= SDLK_Z) + return (KeyCode)(keyCode - SDLK_A + (int)KeyCode::A); + switch(keyCode) { + case SDLK_BACKSPACE: + return KeyCode::BACKSPACE; + case SDLK_TAB: + return KeyCode::TAB; + case SDLK_RETURN: + return KeyCode::ENTER; + case SDLK_LSHIFT: + return KeyCode::LEFT_SHIFT; + case SDLK_RSHIFT: + return KeyCode::RIGHT_SHIFT; + case SDLK_LCTRL: + return KeyCode::LEFT_CTRL; + case SDLK_RCTRL: + return KeyCode::RIGHT_CTRL; + case SDLK_PAUSE: + return KeyCode::PAUSE; + case SDLK_CAPSLOCK: + return KeyCode::CAPS_LOCK; + case SDLK_ESCAPE: + return KeyCode::ESCAPE; + case SDLK_PAGEUP: + return KeyCode::PAGE_UP; + case SDLK_PAGEDOWN: + return KeyCode::PAGE_DOWN; + case SDLK_END: + return KeyCode::END; + case SDLK_HOME: + return KeyCode::HOME; + case SDLK_LEFT: + return KeyCode::LEFT; + case SDLK_UP: + return KeyCode::UP; + case SDLK_RIGHT: + return KeyCode::RIGHT; + case SDLK_DOWN: + return KeyCode::DOWN; + case SDLK_INSERT: + return KeyCode::INSERT; + case SDLK_DELETE: + return KeyCode::DELETE; + case SDLK_NUMLOCKCLEAR: + return KeyCode::NUM_LOCK; + case SDLK_SCROLLLOCK: + return KeyCode::SCROLL_LOCK; + case SDLK_SEMICOLON: + return KeyCode::SEMICOLON; + case SDLK_EQUALS: + return KeyCode::EQUAL; + case SDLK_COMMA: + return KeyCode::COMMA; + case SDLK_MINUS: + return KeyCode::MINUS; + case SDLK_PERIOD: + return KeyCode::PERIOD; + case SDLK_SLASH: + return KeyCode::SLASH; + case SDLK_GRAVE: + return KeyCode::GRAVE; + case SDLK_LEFTBRACKET: + return KeyCode::LEFT_BRACKET; + case SDLK_BACKSLASH: + return KeyCode::BACKSLASH; + case SDLK_RIGHTBRACKET: + return KeyCode::RIGHT_BRACKET; + case SDLK_APOSTROPHE: + return KeyCode::APOSTROPHE; + case SDLK_LGUI: + return KeyCode::LEFT_SUPER; + case SDLK_RGUI: + return KeyCode::RIGHT_SUPER; + case SDLK_LALT: + return KeyCode::LEFT_ALT; + case SDLK_RALT: + return KeyCode::RIGHT_ALT; + case SDLK_KP_ENTER: + return KeyCode::ENTER; + case SDLK_KP_MINUS: + return KeyCode::NUMPAD_SUBTRACT; + case SDLK_KP_MULTIPLY: + return KeyCode::NUMPAD_MULTIPLY; + case SDLK_KP_PLUS: + return KeyCode::NUMPAD_ADD; + case SDLK_KP_DIVIDE: + return KeyCode::NUMPAD_DIVIDE; + case SDLK_KP_DECIMAL: + return KeyCode::NUMPAD_DECIMAL; + case SDLK_KP_0: + return KeyCode::NUMPAD_0; + } + if(keyCode < 256) + return (KeyCode)keyCode; return KeyCode::UNKNOWN; -} \ No newline at end of file +} + +uint32_t SDL3GameWindow::getKeyFromKeyCode(KeyCode code, int metaState) { + SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN; + if(code >= KeyCode::NUM_1 && code <= KeyCode::NUM_9) + scancode = (SDL_Scancode)((int)code - (int)KeyCode::NUM_1 + SDL_SCANCODE_1); + else if(code >= KeyCode::NUMPAD_1 && code <= KeyCode::NUMPAD_9) + scancode = (SDL_Scancode)((int)code - (int)KeyCode::NUMPAD_1 + SDL_SCANCODE_KP_1); + else if(code >= KeyCode::A && code <= KeyCode::Z) + scancode = (SDL_Scancode)((int)code - (int)KeyCode::A + SDL_SCANCODE_A); + else if(code >= KeyCode::FN1 && code <= KeyCode::FN12) + scancode = (SDL_Scancode)((int)code - (int)KeyCode::FN1 + SDL_SCANCODE_F1); + else { + switch(code) { + case KeyCode::BACK: + scancode = SDL_SCANCODE_AC_BACK; + break; + case KeyCode::BACKSPACE: + scancode = SDL_SCANCODE_BACKSPACE; + break; + case KeyCode::TAB: + scancode = SDL_SCANCODE_TAB; + break; + case KeyCode::ENTER: + scancode = SDL_SCANCODE_RETURN; + break; + case KeyCode::LEFT_SHIFT: + scancode = SDL_SCANCODE_LSHIFT; + break; + case KeyCode::RIGHT_SHIFT: + scancode = SDL_SCANCODE_RSHIFT; + break; + case KeyCode::LEFT_CTRL: + scancode = SDL_SCANCODE_LCTRL; + break; + case KeyCode::RIGHT_CTRL: + scancode = SDL_SCANCODE_RCTRL; + break; + case KeyCode::PAUSE: + scancode = SDL_SCANCODE_PAUSE; + break; + case KeyCode::CAPS_LOCK: + scancode = SDL_SCANCODE_CAPSLOCK; + break; + case KeyCode::ESCAPE: + scancode = SDL_SCANCODE_ESCAPE; + break; + case KeyCode::SPACE: + scancode = SDL_SCANCODE_SPACE; + break; + case KeyCode::PAGE_UP: + scancode = SDL_SCANCODE_PAGEUP; + break; + case KeyCode::PAGE_DOWN: + scancode = SDL_SCANCODE_PAGEDOWN; + break; + case KeyCode::END: + scancode = SDL_SCANCODE_END; + break; + case KeyCode::HOME: + scancode = SDL_SCANCODE_HOME; + break; + case KeyCode::LEFT: + scancode = SDL_SCANCODE_LEFT; + break; + case KeyCode::UP: + scancode = SDL_SCANCODE_UP; + break; + case KeyCode::RIGHT: + scancode = SDL_SCANCODE_RIGHT; + break; + case KeyCode::DOWN: + scancode = SDL_SCANCODE_DOWN; + break; + case KeyCode::INSERT: + scancode = SDL_SCANCODE_INSERT; + break; + case KeyCode::DELETE: + scancode = SDL_SCANCODE_DELETE; + break; + case KeyCode::NUM_LOCK: + scancode = SDL_SCANCODE_NUMLOCKCLEAR; + break; + case KeyCode::SCROLL_LOCK: + scancode = SDL_SCANCODE_SCROLLLOCK; + break; + case KeyCode::SEMICOLON: + scancode = SDL_SCANCODE_SEMICOLON; + break; + case KeyCode::EQUAL: + scancode = SDL_SCANCODE_EQUALS; + break; + case KeyCode::COMMA: + scancode = SDL_SCANCODE_COMMA; + break; + case KeyCode::MINUS: + scancode = SDL_SCANCODE_MINUS; + break; + case KeyCode::NUMPAD_ADD: + scancode = SDL_SCANCODE_KP_PLUS; + break; + case KeyCode::NUMPAD_SUBTRACT: + scancode = SDL_SCANCODE_KP_MINUS; + break; + case KeyCode::NUMPAD_MULTIPLY: + scancode = SDL_SCANCODE_KP_MULTIPLY; + break; + case KeyCode::NUMPAD_DIVIDE: + scancode = SDL_SCANCODE_KP_DIVIDE; + break; + case KeyCode::PERIOD: + scancode = SDL_SCANCODE_KP_PERIOD; + break; + case KeyCode::NUMPAD_DECIMAL: + scancode = SDL_SCANCODE_KP_DECIMAL; + break; + case KeyCode::SLASH: + scancode = SDL_SCANCODE_SLASH; + break; + case KeyCode::GRAVE: + scancode = SDL_SCANCODE_GRAVE; + break; + case KeyCode::LEFT_BRACKET: + scancode = SDL_SCANCODE_LEFTBRACKET; + break; + case KeyCode::BACKSLASH: + scancode = SDL_SCANCODE_BACKSLASH; + break; + case KeyCode::RIGHT_BRACKET: + scancode = SDL_SCANCODE_RIGHTBRACKET; + break; + case KeyCode::APOSTROPHE: + scancode = SDL_SCANCODE_APOSTROPHE; + break; + case KeyCode::MENU: + scancode = SDL_SCANCODE_MENU; + break; + case KeyCode::LEFT_SUPER: + scancode = SDL_SCANCODE_LGUI; + break; + case KeyCode::RIGHT_SUPER: + scancode = SDL_SCANCODE_RGUI; + break; + case KeyCode::LEFT_ALT: + scancode = SDL_SCANCODE_LALT; + break; + case KeyCode::RIGHT_ALT: + scancode = SDL_SCANCODE_RALT; + break; + case KeyCode::NUM_0: + scancode = SDL_SCANCODE_0; + break; + case KeyCode::NUMPAD_0: + scancode = SDL_SCANCODE_KP_0; + break; + default: + return 0; + } + } + SDL_Keymod modstate = SDL_KMOD_NONE; + if(metaState & KEY_MOD_SHIFT) { + modstate |= SDL_KMOD_SHIFT; + } + if(metaState & KEY_MOD_CTRL) { + modstate |= SDL_KMOD_CTRL; + } + if(metaState & KEY_MOD_SUPER) { + modstate |= SDL_KMOD_GUI; + } + if(metaState & KEY_MOD_ALT) { + modstate |= SDL_KMOD_ALT; + } + if(metaState & KEY_MOD_CAPSLOCK) { + modstate |= SDL_KMOD_CAPS; + } + if(metaState & KEY_MOD_NUMLOCK) { + modstate |= SDL_KMOD_NUM; + } + SDL_Keycode keyCode = SDL_GetKeyFromScancode(scancode, modstate, false); + if((modstate & SDL_KMOD_SHIFT || modstate & SDL_KMOD_CAPS) && (keyCode >= SDLK_A && keyCode <= SDLK_Z)) { + keyCode += 'A' - 'a'; + } + return keyCode; +} + +int SDL3GameWindow::translateMeta(SDL_Keymod meta) { + int mods = 0; + if(meta & SDL_KMOD_SHIFT) { + mods |= KEY_MOD_SHIFT; + } + if(meta & SDL_KMOD_CTRL) { + mods |= KEY_MOD_CTRL; + } + if(meta & SDL_KMOD_ALT) { + mods |= KEY_MOD_ALT; + } + if(meta & SDL_KMOD_GUI) { + mods |= KEY_MOD_SUPER; + } + if(meta & SDL_KMOD_CAPS) { + mods |= KEY_MOD_CAPSLOCK; + } + if(meta & SDL_KMOD_NUM) { + mods |= KEY_MOD_NUMLOCK; + } + return mods; +} diff --git a/src/window_sdl3.h b/src/window_sdl3.h index 5b85664..f07fc77 100644 --- a/src/window_sdl3.h +++ b/src/window_sdl3.h @@ -8,12 +8,14 @@ #include class SDL3GameWindow : public GameWindow { - private: - enum RequestWindowMode { Fullscreen, Windowed, None }; + enum RequestWindowMode { Fullscreen, + Windowed, + None }; SDL_Window* window; SDL_GLContext context; - double lastMouseX = 0.0, lastMouseY = 0.0; + bool cursorDisabled = false; + bool centerMouseNextEnable = false; int windowedX = -1, windowedY = -1; // width and height in content pixels int width = -1, height = -1; @@ -29,10 +31,11 @@ class SDL3GameWindow : public GameWindow { FullscreenMode mode; std::vector modes; + bool isMouseInWindow(); static KeyCode getKeyMinecraft(int keyCode); + static int translateMeta(SDL_Keymod meta); public: - SDL3GameWindow(const std::string& title, int width, int height, GraphicsApi api); ~SDL3GameWindow() override; @@ -68,7 +71,7 @@ class SDL3GameWindow : public GameWindow { void setSwapInterval(int interval) override; void startTextInput() override; - + void stopTextInput() override; void setFullscreenMode(const FullscreenMode& mode) override; @@ -77,4 +80,5 @@ class SDL3GameWindow : public GameWindow { std::vector getFullscreenModes() override; + uint32_t getKeyFromKeyCode(KeyCode code, int metaState) override; };