diff --git a/BasiliskII/src/Windows/main_windows.cpp b/BasiliskII/src/Windows/main_windows.cpp index e8d39095..77e2db5d 100755 --- a/BasiliskII/src/Windows/main_windows.cpp +++ b/BasiliskII/src/Windows/main_windows.cpp @@ -98,11 +98,14 @@ uint8 *ScratchMem = NULL; // Scratch memory for Mac ROM writes static bool lm_area_mapped = false; // Flag: Low Memory area mmap()ped #endif +static HHOOK keyboard_hook; // Hook for intercepting windows key events + // Prototypes static int xpram_func(void *arg); static int tick_func(void *arg); static void one_tick(...); +static LRESULT CALLBACK low_level_keyboard_hook(int nCode, WPARAM wParam, LPARAM lParam); /* @@ -283,6 +286,12 @@ int main(int argc, char **argv) QuitEmulator(); #endif + // Install keyboard hook to block Windows key if enabled in prefs + if (PrefsFindBool("reservewindowskey")) + { + keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL, low_level_keyboard_hook, GetModuleHandle(NULL), 0); + } + // Initialize SDL system int sdl_flags = 0; #ifdef USE_SDL_VIDEO @@ -711,3 +720,42 @@ bool ChoiceAlert(const char *text, const char *pos, const char *neg) printf(GetString(STR_SHELL_WARNING_PREFIX), text); return false; //!! } + +/* + * Low level keyboard hook allowing us to intercept events involving the Windows key + */ +static LRESULT CALLBACK low_level_keyboard_hook(int nCode, WPARAM wParam, LPARAM lParam) +{ + // Not a relevant event, immediately pass it on + if (nCode != HC_ACTION) + return CallNextHookEx(keyboard_hook, nCode, wParam, lParam); + + KBDLLHOOKSTRUCT *p = (KBDLLHOOKSTRUCT *)lParam; + switch (wParam) { + case WM_KEYDOWN: + case WM_KEYUP: + // Intercept left/right windows keys when we have keyboard focus so Windows doesn't handle them + if (p->vkCode == VK_LWIN || p->vkCode == VK_RWIN) { + bool intercept_event = false; +#ifdef USE_SDL_VIDEO + if (sdl_window && (SDL_GetWindowFlags(sdl_window) & SDL_WINDOW_INPUT_FOCUS)) { + intercept_event = true; + } +#endif + + // If we've determined we should intercept the event, intercept it. But pass the event onto SDL so Basilisk handles it. + if (intercept_event) { + SDL_Event e; + memset(&e, 0, sizeof(e)); + e.type = (wParam == WM_KEYDOWN) ? SDL_KEYDOWN : SDL_KEYUP; + e.key.keysym.sym = (p->vkCode == VK_LWIN) ? SDLK_LGUI : SDLK_RGUI; + SDL_PushEvent(&e); + return 1; + } + } + break; + } + + // If we fall here, we weren't supposed to intercept it. + return CallNextHookEx(keyboard_hook, nCode, wParam, lParam); +} diff --git a/BasiliskII/src/Windows/prefs_editor_gtk.cpp b/BasiliskII/src/Windows/prefs_editor_gtk.cpp index 50e8d9f8..b1cc44dc 100644 --- a/BasiliskII/src/Windows/prefs_editor_gtk.cpp +++ b/BasiliskII/src/Windows/prefs_editor_gtk.cpp @@ -1298,6 +1298,12 @@ static void tb_keycodes(GtkWidget *widget) set_input_sensitive(); } +// "Reserve Windows Key" button toggled +static void tb_reservewindowskey(GtkWidget *widget) +{ + PrefsReplaceBool("reservewindowskey", GTK_TOGGLE_BUTTON(widget)->active); +} + // "Mouse Wheel Mode" selected static void mn_wheel_page(...) {PrefsReplaceInt32("mousewheelmode", 0); set_input_sensitive();} static void mn_wheel_cursor(...) {PrefsReplaceInt32("mousewheelmode", 1); set_input_sensitive();} @@ -1345,6 +1351,8 @@ static void create_input_pane(GtkWidget *top) gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); g_object_set_data(G_OBJECT(w_keycode_file), "chooser_button", button); + make_checkbox(box, STR_RESERVE_WINDOWS_KEY_CTRL, "reservewindowskey", GTK_SIGNAL_FUNC(tb_reservewindowskey)); + make_separator(box); static const opt_desc options[] = { diff --git a/BasiliskII/src/Windows/prefs_windows.cpp b/BasiliskII/src/Windows/prefs_windows.cpp index 527dcbfc..4404c12c 100755 --- a/BasiliskII/src/Windows/prefs_windows.cpp +++ b/BasiliskII/src/Windows/prefs_windows.cpp @@ -53,6 +53,8 @@ prefs_desc platform_prefs_items[] = { {"sdlrender", TYPE_STRING, false, "SDL_Renderer driver (\"auto\", \"software\" (may be faster), etc.)"}, {"sdl_vsync", TYPE_BOOLEAN, false, "Make SDL_Renderer vertical sync frames to host (eg. with software renderer)"}, #endif + {"reservewindowskey", TYPE_BOOLEAN, false, "block Windows key from activating start menu"}, + {NULL, TYPE_END, false, NULL} // End of list }; @@ -136,4 +138,5 @@ void AddPlatformPrefsDefaults(void) PrefsReplaceString("sdlrender", "software"); PrefsReplaceBool("sdl_vsync", false); #endif + PrefsAddBool("reservewindowskey", false); } diff --git a/BasiliskII/src/Windows/user_strings_windows.cpp b/BasiliskII/src/Windows/user_strings_windows.cpp index dc2993da..2b3c3c6b 100755 --- a/BasiliskII/src/Windows/user_strings_windows.cpp +++ b/BasiliskII/src/Windows/user_strings_windows.cpp @@ -56,6 +56,7 @@ user_string_def platform_strings[] = { {STR_INPUT_PANE_TITLE, "Keyboard/Mouse"}, {STR_KEYCODES_CTRL, "Use Raw Keycodes"}, {STR_KEYCODE_FILE_CTRL, "Keycode Translation File"}, + {STR_RESERVE_WINDOWS_KEY_CTRL, "Reserve Windows Key"}, {STR_MOUSEWHEELMODE_CTRL, "Mouse Wheel Function"}, {STR_MOUSEWHEELMODE_PAGE_LAB, "Page Up/Down"}, {STR_MOUSEWHEELMODE_CURSOR_LAB, "Cursor Up/Down"}, diff --git a/BasiliskII/src/Windows/user_strings_windows.h b/BasiliskII/src/Windows/user_strings_windows.h index c8e21e31..7daea7a1 100755 --- a/BasiliskII/src/Windows/user_strings_windows.h +++ b/BasiliskII/src/Windows/user_strings_windows.h @@ -58,6 +58,7 @@ enum { STR_INPUT_PANE_TITLE, STR_KEYCODES_CTRL, STR_KEYCODE_FILE_CTRL, + STR_RESERVE_WINDOWS_KEY_CTRL, STR_MOUSEWHEELMODE_CTRL, STR_MOUSEWHEELMODE_PAGE_LAB, STR_MOUSEWHEELMODE_CURSOR_LAB, diff --git a/SheepShaver/src/Windows/main_windows.cpp b/SheepShaver/src/Windows/main_windows.cpp index 0683c471..0ee65b12 100755 --- a/SheepShaver/src/Windows/main_windows.cpp +++ b/SheepShaver/src/Windows/main_windows.cpp @@ -105,6 +105,8 @@ uintptr SheepMem::base = 0x60000000; // Address of SheepShaver data uintptr SheepMem::proc; // Bottom address of SheepShave procedures uintptr SheepMem::data; // Top of SheepShaver data (stack like storage) +static HHOOK keyboard_hook; // Hook for intercepting windows key events + // Prototypes static bool kernel_data_init(void); @@ -118,6 +120,7 @@ extern void emul_ppc(uint32 start); extern void init_emul_ppc(void); extern void exit_emul_ppc(void); sigsegv_return_t sigsegv_handler(sigsegv_info_t *sip); +static LRESULT CALLBACK low_level_keyboard_hook(int nCode, WPARAM wParam, LPARAM lParam); /* @@ -210,6 +213,12 @@ int main(int argc, char **argv) // // Load win32 libraries // KernelInit(); + // Install keyboard hook to block Windows key if enabled in prefs + if (PrefsFindBool("reservewindowskey")) + { + keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL, low_level_keyboard_hook, GetModuleHandle(NULL), 0); + } + // Initialize SDL system int sdl_flags = 0; #ifdef USE_SDL_VIDEO @@ -839,3 +848,42 @@ bool ChoiceAlert(const char *text, const char *pos, const char *neg) printf(GetString(STR_SHELL_WARNING_PREFIX), text); return false; //!! } + +/* + * Low level keyboard hook allowing us to intercept events involving the Windows key + */ +static LRESULT CALLBACK low_level_keyboard_hook(int nCode, WPARAM wParam, LPARAM lParam) +{ + // Not a relevant event, immediately pass it on + if (nCode != HC_ACTION) + return CallNextHookEx(keyboard_hook, nCode, wParam, lParam); + + KBDLLHOOKSTRUCT *p = (KBDLLHOOKSTRUCT *)lParam; + switch (wParam) { + case WM_KEYDOWN: + case WM_KEYUP: + // Intercept left/right windows keys when we have keyboard focus so Windows doesn't handle them + if (p->vkCode == VK_LWIN || p->vkCode == VK_RWIN) { + bool intercept_event = false; +#ifdef USE_SDL_VIDEO + if (sdl_window && (SDL_GetWindowFlags(sdl_window) & SDL_WINDOW_INPUT_FOCUS)) { + intercept_event = true; + } +#endif + + // If we've determined we should intercept the event, intercept it. But pass the event onto SDL so SheepShaver handles it. + if (intercept_event) { + SDL_Event e; + memset(&e, 0, sizeof(e)); + e.type = (wParam == WM_KEYDOWN) ? SDL_KEYDOWN : SDL_KEYUP; + e.key.keysym.sym = (p->vkCode == VK_LWIN) ? SDLK_LGUI : SDLK_RGUI; + SDL_PushEvent(&e); + return 1; + } + } + break; + } + + // If we fall here, we weren't supposed to intercept it. + return CallNextHookEx(keyboard_hook, nCode, wParam, lParam); +} diff --git a/SheepShaver/src/Windows/prefs_windows.cpp b/SheepShaver/src/Windows/prefs_windows.cpp index 9c3865bf..b0b5d632 100755 --- a/SheepShaver/src/Windows/prefs_windows.cpp +++ b/SheepShaver/src/Windows/prefs_windows.cpp @@ -58,6 +58,7 @@ prefs_desc platform_prefs_items[] = { {"sdlrender", TYPE_STRING, false, "SDL_Renderer driver (\"auto\", \"software\" (may be faster), etc.)"}, {"sdl_vsync", TYPE_BOOLEAN, false, "Make SDL_Renderer vertical sync frames to host (eg. with software renderer)"}, #endif + {"reservewindowskey", TYPE_BOOLEAN, false, "block Windows key from activating start menu"}, {NULL, TYPE_END, false, NULL} // End of list }; @@ -145,4 +146,5 @@ void AddPlatformPrefsDefaults(void) PrefsReplaceString("sdlrender", "software"); PrefsReplaceBool("sdl_vsync", false); #endif + PrefsAddBool("reservewindowskey", false); } diff --git a/SheepShaver/src/Windows/user_strings_windows.cpp b/SheepShaver/src/Windows/user_strings_windows.cpp index eb12de57..f4dbb585 100755 --- a/SheepShaver/src/Windows/user_strings_windows.cpp +++ b/SheepShaver/src/Windows/user_strings_windows.cpp @@ -63,6 +63,7 @@ user_string_def platform_strings[] = { {STR_INPUT_PANE_TITLE, "Keyboard/Mouse"}, {STR_KEYCODES_CTRL, "Use Raw Keycodes"}, {STR_KEYCODE_FILE_CTRL, "Keycode Translation File"}, + {STR_RESERVE_WINDOWS_KEY_CTRL, "Reserve Windows Key"}, {STR_MOUSEWHEELMODE_CTRL, "Mouse Wheel Function"}, {STR_MOUSEWHEELMODE_PAGE_LAB, "Page Up/Down"}, {STR_MOUSEWHEELMODE_CURSOR_LAB, "Cursor Up/Down"}, diff --git a/SheepShaver/src/Windows/user_strings_windows.h b/SheepShaver/src/Windows/user_strings_windows.h index 7db10a74..2a606fe6 100755 --- a/SheepShaver/src/Windows/user_strings_windows.h +++ b/SheepShaver/src/Windows/user_strings_windows.h @@ -57,6 +57,7 @@ enum { STR_INPUT_PANE_TITLE, STR_KEYCODES_CTRL, STR_KEYCODE_FILE_CTRL, + STR_RESERVE_WINDOWS_KEY_CTRL, STR_MOUSEWHEELMODE_CTRL, STR_MOUSEWHEELMODE_PAGE_LAB, STR_MOUSEWHEELMODE_CURSOR_LAB,