diff --git a/include/BetterSpades/hud.h b/include/BetterSpades/hud.h index ca24861..80c8124 100644 --- a/include/BetterSpades/hud.h +++ b/include/BetterSpades/hud.h @@ -36,6 +36,8 @@ typedef struct { void (*input_mouseclick)(double x, double y, int button, int action, int mods); void (*input_mousescroll)(double yoffset); void (*input_touch)(void * finger, int action, float x, float y, float dx, float dy); + void (*focus)(bool); + void (*hover)(bool); Texture * (*ui_images)(int icon_id, bool * resize); char render_world; char render_localplayer; diff --git a/include/BetterSpades/main.h b/include/BetterSpades/main.h index 5550849..c0bd645 100644 --- a/include/BetterSpades/main.h +++ b/include/BetterSpades/main.h @@ -21,6 +21,7 @@ #define MAIN_H #include +#include void reshape(struct window_instance * window, int width, int height); void text_input(struct window_instance * window, const uint8_t *); @@ -28,6 +29,8 @@ void keys(struct window_instance * window, int key, int action, int mods); void mouse_click(struct window_instance * window, int button, int action, int mods); void mouse(struct window_instance * window, double x, double y); void mouse_scroll(struct window_instance * window, double xoffset, double yoffset); +void mouse_focus(struct window_instance *, bool); +void mouse_hover(struct window_instance *, bool); void on_error(int i, const char * s); #endif diff --git a/include/BetterSpades/window.h b/include/BetterSpades/window.h index f322fbf..fd1033e 100644 --- a/include/BetterSpades/window.h +++ b/include/BetterSpades/window.h @@ -149,6 +149,8 @@ int window_cpucores(); void window_title(char * suffix); void window_sendkey(int action, int keycode, int mod); +int window_get_mousemode(); + typedef void (*Idle)(double); typedef void (*Display)(void); diff --git a/src/GUI/glfw.c b/src/GUI/glfw.c index 5748ac0..6a8c8bb 100644 --- a/src/GUI/glfw.c +++ b/src/GUI/glfw.c @@ -92,6 +92,19 @@ static void window_impl_keys(GLFWwindow * window, int key, int scancode, int act window_sendkey(a, key, mods & GLFW_MOD_CONTROL); } +static void window_cursor_enter_callback(GLFWwindow * window, int entered) { + mouse_hover(hud_window, entered); +} + +static void window_focus_callback(GLFWwindow * window, int focused) { + mouse_focus(hud_window, focused); +} + +int window_get_mousemode() { + int s = glfwGetInputMode(hud_window->impl, GLFW_CURSOR); + return s == GLFW_CURSOR_DISABLED ? WINDOW_CURSOR_DISABLED : WINDOW_CURSOR_ENABLED; +} + void window_init(int * argc, char ** argv) { static struct window_instance i; hud_window = &i; @@ -147,6 +160,8 @@ void window_init(int * argc, char ** argv) { glfwSetMouseButtonCallback(hud_window->impl, window_impl_mouseclick); glfwSetScrollCallback(hud_window->impl, window_impl_mousescroll); glfwSetCharCallback(hud_window->impl, window_impl_textinput); + glfwSetWindowFocusCallback(hud_window->impl, window_focus_callback); + glfwSetCursorEnterCallback(hud_window->impl, window_cursor_enter_callback); if (glfwRawMouseMotionSupported()) glfwSetInputMode(hud_window->impl, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE); diff --git a/src/GUI/glut.c b/src/GUI/glut.c index 0633c04..1f68057 100644 --- a/src/GUI/glut.c +++ b/src/GUI/glut.c @@ -78,6 +78,10 @@ void window_mouse_button(int button, int state, int x, int y) { mouse_click(hud_window, but, action, mod); } +int window_get_mousemode() { + return captured ? WINDOW_CURSOR_DISABLED : WINDOW_CURSOR_ENABLED; +} + void window_mouse_motion(int x, int y) { static int warped = 0; mx = x; my = y; @@ -99,6 +103,10 @@ void window_mouse_motion(int x, int y) { } else mouse(hud_window, x, y); } +void window_entry(int state) { + mouse_hover(hud_window, state == GLUT_ENTERED ? true : false); +} + void window_init(int * argc, char ** argv) { static struct window_instance i; hud_window = &i; @@ -118,6 +126,7 @@ void window_init(int * argc, char ** argv) { glutMouseFunc(window_mouse_button); glutMotionFunc(window_mouse_motion); glutPassiveMotionFunc(window_mouse_motion); + glutEntryFunc(window_entry); } static Idle idle = NULL; diff --git a/src/GUI/sdl.c b/src/GUI/sdl.c index ffdc387..96e463f 100644 --- a/src/GUI/sdl.c +++ b/src/GUI/sdl.c @@ -66,6 +66,11 @@ int get_sdl_button(int button) { } } +int window_get_mousemode() { + int s = SDL_GetRelativeMouseMode(); + return s ? WINDOW_CURSOR_DISABLED : WINDOW_CURSOR_ENABLED; +} + void window_update() { SDL_GL_SwapWindow(hud_window->impl); SDL_Event event; @@ -79,12 +84,26 @@ void window_update() { case SDL_MOUSEBUTTONDOWN: mouse_click(hud_window, get_sdl_button(event.button.button), WINDOW_PRESS, 0); break; case SDL_MOUSEBUTTONUP: mouse_click(hud_window, get_sdl_button(event.button.button), WINDOW_RELEASE, 0); break; - case SDL_WINDOWEVENT: + case SDL_WINDOWEVENT: { if (event.window.event == SDL_WINDOWEVENT_RESIZED || event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { reshape(hud_window, event.window.data1, event.window.data2); } + + if (event.window.event == SDL_WINDOWEVENT_LEAVE) + mouse_hover(hud_window, false); + + if (event.window.event == SDL_WINDOWEVENT_ENTER) + mouse_hover(hud_window, true); + + if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST) + mouse_focus(hud_window, false); + + if (event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) + mouse_focus(hud_window, true); + break; + } case SDL_MOUSEWHEEL: mouse_scroll(hud_window, event.wheel.x, event.wheel.y); break; diff --git a/src/hud.c b/src/hud.c index 1b81b73..aa5efe3 100644 --- a/src/hud.c +++ b/src/hud.c @@ -1257,13 +1257,29 @@ static void hud_ingame_scroll(double yoffset) { } } +bool window_focused = true, window_hovered = true; + +void hud_ingame_focus(bool focused) { + window_focused = focused; + if (!focused) window_mousemode(WINDOW_CURSOR_ENABLED); +} + +void hud_ingame_hover(bool hovered) { + window_hovered = hovered; + if (!hovered) window_mousemode(WINDOW_CURSOR_ENABLED); +} + static double last_x, last_y; static void hud_ingame_mouselocation(double x, double y) { + if (window_get_mousemode() != WINDOW_CURSOR_DISABLED) + return; + if (show_exit) { last_x = x; last_y = y; return; } + float dx = x - last_x; float dy = y - last_y; last_x = x; @@ -1285,6 +1301,13 @@ static void hud_ingame_mouselocation(double x, double y) { } static void hud_ingame_mouseclick(double x, double y, int button, int action, int mods) { + if (window_get_mousemode() == WINDOW_CURSOR_ENABLED) { + if (window_focused && window_hovered && action == WINDOW_RELEASE && !show_exit) + window_mousemode(WINDOW_CURSOR_DISABLED); + + return; + } + if (button == WINDOW_MOUSE_LMB) button_map[0] = (action == WINDOW_PRESS); @@ -1954,6 +1977,8 @@ HUD hud_ingame = { hud_ingame_mouseclick, hud_ingame_scroll, hud_ingame_touch, + hud_ingame_focus, + hud_ingame_hover, NULL, 1, 0, @@ -2464,6 +2489,8 @@ HUD hud_serverlist = { NULL, NULL, hud_serverlist_touch, + NULL, + NULL, hud_serverlist_ui_images, 0, 0, @@ -2644,6 +2671,8 @@ HUD hud_settings = { NULL, NULL, hud_settings_touch, + NULL, + NULL, hud_settings_ui_images, 0, 0, @@ -2794,6 +2823,8 @@ HUD hud_controls = { NULL, NULL, hud_controls_touch, + NULL, + NULL, hud_settings_ui_images, 0, 0, diff --git a/src/main.c b/src/main.c index 8afba22..f928531 100644 --- a/src/main.c +++ b/src/main.c @@ -676,6 +676,14 @@ void mouse_click(struct window_instance * window, int button, int action, int mo } } +void mouse_focus(struct window_instance * window, bool focused) { + if (hud_active->focus) hud_active->focus(focused); +} + +void mouse_hover(struct window_instance * window, bool hovered) { + if (hud_active->hover) hud_active->hover(hovered); +} + void mouse(struct window_instance * window, double x, double y) { if (hud_active->input_mouselocation) hud_active->input_mouselocation(x, y);