Skip to content
Browse files

Always reset all keyboard and mouse buttons to released when window f…

…ocus is lost on all platforms.

Previously, this was left up to the platform. On Windows this almost always worked because mouse button state was checked on every mouse move message. On macOS this did nothing, so if you held down left mouse button, went to another application, released left mouse and then came back to the game, it'd still think the left mouse was down, so once you closed the menu, the game started deleting blocks. On linux the window still seemed to get a 'mouse up' even when the window wasn't focused anymore, although I didn't rigorously test this. For the web client, seemed to get 'mouse up' tooin chrome, not sure if other browsers had issues. SDL backend wasn't tested.
  • Loading branch information
UnknownShadow200 committed Nov 30, 2019
1 parent b26ab73 commit ca72cf66a36b506af48dcc00d414170288eed56d
Showing with 10 additions and 14 deletions.
  1. +4 −3 src/Input.c
  2. +3 −3 src/Input.h
  3. +3 −8 src/Window.c
@@ -200,10 +200,9 @@ void Input_SetPressed(int key, cc_bool pressed) {
Pointer_SetPressed(0, pressed);

void Key_Clear(void) {
void Input_Clear(void) {
int i;
/* only resets keyboard keys, not mouse state */
for (i = 0; i < KEY_XBUTTON1; i++) {
for (i = 0; i < INPUT_COUNT; i++) {
if (Input_Pressed[i]) Input_SetPressed(i, false);
@@ -1033,6 +1032,7 @@ static void HandleInputUp(void* obj, int key) {
if (key == KeyBinds[KEYBIND_PICK_BLOCK]) MouseStateRelease(MOUSE_MIDDLE);

static void HandleFocusChanged(void* obj) { if (!Window_Focused) Input_Clear(); }
void InputHandler_Init(void) {
Event_RegisterMove(&PointerEvents.Moved, NULL, HandlePointerMove);
Event_RegisterInt(&PointerEvents.Down, NULL, HandlePointerDown);
@@ -1041,6 +1041,7 @@ void InputHandler_Init(void) {
Event_RegisterInt(&InputEvents.Up, NULL, HandleInputUp);
Event_RegisterFloat(&InputEvents.Wheel, NULL, HandleMouseWheel);

Event_RegisterVoid(&WindowEvents.FocusChanged, NULL, HandleFocusChanged);
Event_RegisterVoid(&UserEvents.HackPermissionsChanged, NULL, InputHandler_CheckZoomFov);
@@ -66,9 +66,9 @@ extern cc_bool Input_Pressed[INPUT_COUNT];
/* Raises InputEvents.Up if not pressed, but was pressed before. */
/* Raises InputEvents.Down if pressed (repeating is whether it was pressed before) */
void Input_SetPressed(int key, cc_bool pressed);
/* Resets all keyboard keys to released state. */
/* Raises InputEvents.Up for each previously pressed key. */
void Key_Clear(void);
/* Resets all keyboard buttons to released state. */
/* Raises InputEvents.Up for each previously pressed button. */
void Input_Clear(void);

/* Whether raw mouse/touch input is being listened for. */
extern cc_bool Input_RawMode;
@@ -231,11 +231,6 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara

/* Set before position change, in case mouse buttons changed when outside window */
Input_SetPressed(KEY_LMOUSE, (wParam & 0x01) != 0);
Input_SetPressed(KEY_RMOUSE, (wParam & 0x02) != 0);
Input_SetPressed(KEY_MMOUSE, (wParam & 0x10) != 0);
/* TODO: do we need to set XBUTTON1/XBUTTON2 here */
Pointer_SetPosition(0, LOWORD(lParam), HIWORD(lParam));

@@ -341,7 +336,7 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara

/* TODO: Keep track of keyboard when focus is lost */

case WM_CLOSE:
@@ -1163,7 +1158,7 @@ void Window_ProcessEvents(void) {
Window_Focused = e.type == FocusIn;
/* TODO: Keep track of keyboard when focus is lost */
if (!Window_Focused) Key_Clear();
if (!Window_Focused) Input_Clear();

case MappingNotify:
@@ -2909,7 +2904,7 @@ static EM_BOOL Window_TouchEnd(int type, const EmscriptenTouchEvent* ev, void* d

static EM_BOOL Window_Focus(int type, const EmscriptenFocusEvent* ev, void* data) {
Window_Focused = type == EMSCRIPTEN_EVENT_FOCUS;
if (!Window_Focused) Key_Clear();
if (!Window_Focused) Input_Clear();

return true;

0 comments on commit ca72cf6

Please sign in to comment.
You can’t perform that action at this time.