Support ClosedApple+key with Alt Gr when combined with a regular keyboard key:

. When Alt Gr is pressed, then manually post WM_CHAR message on receiving a WM_KEYDOWN (manually translate and account for shift/control/caps-lock)
. Hook filter: suppress Alt Gr's (ie. RMENU's) fake LCONTROL messages

Also:
. Hook filter: allow Ctrl+Shift+Esc (for Task Manager)
. Keyboard: refactor only use accessor functions to get the Alt/Control/Shift state
This commit is contained in:
TomCh 2018-07-27 21:55:53 +01:00 committed by GitHub
parent 1afa2490c5
commit 6ed354714e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 101 additions and 58 deletions

View File

@ -20,6 +20,18 @@ extern "C" __declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc(
UINT newMsg = pKbdLlHookStruct->flags & LLKHF_UP ? WM_KEYUP : WM_KEYDOWN;
LPARAM newlParam = newMsg == WM_KEYUP ? 3<<30 : 0; // b31:transition state, b30:previous key state
//
// NB. Alt Gr (Right-Alt): this normally send 2 WM_KEYDOWN messages for: VK_LCONTROL, then VK_RMENU
// Keyboard scanCodes: LCONTROL=0x1D, LCONTROL_from_RMENU=0x21D
// . For: Microsoft PS/2/Win7-64, VAIO laptop/Win7-64, Microsoft USB/Win10-64
// NB. WM_KEYDOWN also includes a 9/10-bit? scanCode: LCONTROL=0x1D, RCONTROL=0x11D, RMENU=0x1D(not 0x21D)
// . Can't suppress in app, since scanCode is not >= 0x200
if (pKbdLlHookStruct->vkCode == VK_LCONTROL && pKbdLlHookStruct->scanCode >= 0x200)
{
suppress = true;
}
// Suppress alt-tab
if (pKbdLlHookStruct->vkCode == VK_TAB && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
{
@ -44,8 +56,8 @@ extern "C" __declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc(
// Suppress ctrl-escape
if (pKbdLlHookStruct->vkCode == VK_ESCAPE)
{
bool ControlDown = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
if (ControlDown)
// But don't suppress CTRL+SHIFT+ESC
if (GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) >= 0)
suppress = true;
}

View File

@ -9709,11 +9709,11 @@ void DebuggerMouseClick( int x, int y )
if (g_nAppMode != MODE_DEBUG)
return;
// NOTE: KeybUpdateCtrlShiftStatus() should be called before
KeybUpdateCtrlShiftStatus();
int iAltCtrlShift = 0;
iAltCtrlShift |= (g_bAltKey & 1) << 0;
iAltCtrlShift |= (g_bCtrlKey & 1) << 1;
iAltCtrlShift |= (g_bShiftKey & 1) << 2;
iAltCtrlShift |= KeybGetAltStatus() ? 1<<0 : 0;
iAltCtrlShift |= KeybGetCtrlStatus() ? 1<<1 : 0;
iAltCtrlShift |= KeybGetShiftStatus() ? 1<<2 : 0;
// GH#462 disasm click #
if (iAltCtrlShift != g_bConfigDisasmClick)

View File

@ -57,6 +57,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Debugger/Debug.h"
//#define ENABLE_MENU 0
#define DEBUG_KEY_MESSAGES 0
// 3D border around the 560x384 Apple II display
#define VIEWPORTX 5
@ -1096,15 +1097,16 @@ LRESULT CALLBACK FrameWndProc (
case WM_CHAR:
if ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_STEPPING) || (g_nAppMode == MODE_LOGO))
{
if( !g_bDebuggerEatKey )
if (!g_bDebuggerEatKey)
{
#if DEBUG_KEY_MESSAGES
LogOutput("WM_CHAR: %08X\n", wparam);
#endif
if (g_nAppMode != MODE_LOGO) // !MODE_LOGO - not emulating so don't pass to the VM's keyboard
KeybQueueKeypress((int)wparam, ASCII);
}
else
{
g_bDebuggerEatKey = false;
KeybQueueKeypress(wparam, ASCII);
}
g_bDebuggerEatKey = false;
}
else if (g_nAppMode == MODE_DEBUG)
{
@ -1290,19 +1292,19 @@ LRESULT CALLBACK FrameWndProc (
// CTRL+SHIFT+F9 Toggle 50% Scan Lines
// ALT+F9 Can't use Alt-F9 as Alt is Open-Apple = Joystick Button #1
if ( !g_bCtrlKey && !g_bShiftKey ) // F9
if ( !KeybGetCtrlStatus() && !KeybGetShiftStatus() ) // F9
{
g_eVideoType++;
if (g_eVideoType >= NUM_VIDEO_MODES)
g_eVideoType = 0;
}
else if ( !g_bCtrlKey && g_bShiftKey ) // SHIFT+F9
else if ( !KeybGetCtrlStatus() && KeybGetShiftStatus() ) // SHIFT+F9
{
if (g_eVideoType <= 0)
g_eVideoType = NUM_VIDEO_MODES;
g_eVideoType--;
}
else if ( g_bCtrlKey && g_bShiftKey ) // CTRL+SHIFT+F9
else if ( KeybGetCtrlStatus() && KeybGetShiftStatus() ) // CTRL+SHIFT+F9
{
g_uHalfScanLines = !g_uHalfScanLines;
}
@ -1331,7 +1333,7 @@ LRESULT CALLBACK FrameWndProc (
}
else if (wparam == VK_F10)
{
if (g_Apple2Type == A2TYPE_PRAVETS8A && !g_bCtrlKey)
if (g_Apple2Type == A2TYPE_PRAVETS8A && !KeybGetCtrlStatus())
{
KeybToggleP8ACapsLock (); // F10: Toggles P8 Capslock
}
@ -1340,7 +1342,7 @@ LRESULT CALLBACK FrameWndProc (
SetUsingCursor(FALSE); // Ctrl+F10
}
}
else if (wparam == VK_F11 && !g_bCtrlKey) // Save state (F11)
else if (wparam == VK_F11 && !KeybGetCtrlStatus()) // Save state (F11)
{
SoundCore_SetFade(FADE_OUT);
if(sg_PropertySheet.SaveStateSelectImage(window, true))
@ -1392,18 +1394,20 @@ LRESULT CALLBACK FrameWndProc (
}
else if ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_LOGO) || (g_nAppMode == MODE_STEPPING))
{
// Note about Alt Gr (Right-Alt):
// . WM_KEYDOWN[Left-Control], then:
// . WM_KEYDOWN[Right-Alt]
// NB. Alt Gr (Right-Alt): this normally send 2 WM_KEYDOWN messages for: VK_LCONTROL, then VK_RMENU
// . NB. The keyboard hook filter now suppresses VK_LCONTROL
bool extended = (HIWORD(lparam) & KF_EXTENDED) != 0;
BOOL down = 1;
BOOL autorep = (HIWORD(lparam) & KF_REPEAT) != 0;
BOOL IsJoyKey = JoyProcessKey((int)wparam, extended, down, autorep);
#if DEBUG_KEY_MESSAGES
LogOutput("WM_KEYDOWN: %08X (scanCode=%04X)\n", wparam, (lparam>>16)&0xfff);
#endif
if (!IsJoyKey &&
(g_nAppMode != MODE_LOGO)) // !MODE_LOGO - not emulating so don't pass to the VM's keyboard
{
KeybQueueKeypress((int)wparam, NOT_ASCII);
KeybQueueKeypress(wparam, NOT_ASCII);
if (!autorep)
KeybAnyKeyDown(WM_KEYDOWN, wparam, extended);
@ -1433,6 +1437,9 @@ LRESULT CALLBACK FrameWndProc (
BOOL autorep = 0;
BOOL bIsJoyKey = JoyProcessKey((int)wparam, extended, down, autorep);
#if DEBUG_KEY_MESSAGES
LogOutput("WM_KEYUP: %08X\n", wparam);
#endif
if (!bIsJoyKey)
KeybAnyKeyDown(WM_KEYUP, wparam, extended);
}
@ -1749,7 +1756,7 @@ LRESULT CALLBACK FrameWndProc (
// http://msdn.microsoft.com/en-us/library/windows/desktop/gg153546(v=vs.85).aspx
// v1.25.0: Alt-Return Alt-Enter toggle fullscreen
if (g_bAltEnter_ToggleFullScreen && g_bAltKey && (wparam == VK_RETURN)) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
if (g_bAltEnter_ToggleFullScreen && KeybGetAltStatus() && (wparam == VK_RETURN)) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
return 0; // NOP -- eat key
PostMessage(window,WM_KEYDOWN,wparam,lparam);
@ -1763,7 +1770,7 @@ LRESULT CALLBACK FrameWndProc (
KeybUpdateCtrlShiftStatus();
// v1.25.0: Alt-Return Alt-Enter toggle fullscreen
if (g_bAltEnter_ToggleFullScreen && g_bAltKey && (wparam == VK_RETURN)) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
if (g_bAltEnter_ToggleFullScreen && KeybGetAltStatus() && (wparam == VK_RETURN)) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
ScreenWindowResize(false);
else
PostMessage(window,WM_KEYUP,wparam,lparam);
@ -1946,7 +1953,7 @@ static void ProcessButtonClick(int button, bool bFromButtonUI /*=false*/)
case BTN_RUN:
KeybUpdateCtrlShiftStatus();
if( g_bCtrlKey )
if( KeybGetCtrlStatus() )
{
CtrlReset();
if (g_nAppMode == MODE_DEBUG)
@ -1990,7 +1997,7 @@ static void ProcessButtonClick(int button, bool bFromButtonUI /*=false*/)
case BTN_FULLSCR:
KeybUpdateCtrlShiftStatus();
ScreenWindowResize(g_bCtrlKey);
ScreenWindowResize( KeybGetCtrlStatus() );
break;
case BTN_DEBUG:

View File

@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Tape.h"
#include "YamlHelper.h"
#include "Video.h" // Needed by TK3000 //e, to refresh the frame at each |Mode| change
#include "Log.h"
static BYTE asciicode[2][10] = {
// VK_LEFT/UP/RIGHT/DOWN/SELECT, VK_PRINT/EXECUTE/SNAPSHOT/INSERT/DELETE
@ -65,36 +66,31 @@ void KeybReset()
}
//===========================================================================
bool KeybGetAltStatus ()
{
return g_bAltKey;
}
//===========================================================================
bool KeybGetCapsStatus ()
bool KeybGetCapsStatus()
{
return g_bCapsLock;
}
//===========================================================================
bool KeybGetP8CapsStatus()
{
return g_bP8CapsLock;
}
//===========================================================================
/*
bool KeybGetCapsAllowed() //For Pravets 8A/C only
bool KeybGetAltStatus()
{
return g_CapsLockAllowed;
return g_bAltKey;
}
*/
//===========================================================================
bool KeybGetCtrlStatus ()
bool KeybGetCtrlStatus()
{
return g_bCtrlKey;
}
//===========================================================================
bool KeybGetShiftStatus ()
bool KeybGetShiftStatus()
{
return g_bShiftKey;
}
@ -102,9 +98,9 @@ bool KeybGetShiftStatus ()
//===========================================================================
void KeybUpdateCtrlShiftStatus()
{
g_bShiftKey = (GetKeyState( VK_SHIFT ) < 0) ? true : false; // L or R shift
g_bCtrlKey = (GetKeyState( VK_CONTROL) < 0) ? true : false; // L or R ctrl
g_bAltKey = (GetKeyState( VK_MENU ) < 0) ? true : false; // L or R alt
g_bCtrlKey = (GetKeyState( VK_CONTROL) < 0) ? true : false; // L or R ctrl
g_bShiftKey = (GetKeyState( VK_SHIFT ) < 0) ? true : false; // L or R shift
}
//===========================================================================
@ -114,7 +110,10 @@ BYTE KeybGetKeycode () // Used by IORead_C01x() and TapeRead() for Pravets8A
}
//===========================================================================
void KeybQueueKeypress(WPARAM key, Keystroke_e bASCII)
bool IsVirtualKeyAnAppleIIKey(WPARAM wparam);
void KeybQueueKeypress (WPARAM key, Keystroke_e bASCII)
{
if (bASCII == ASCII) // WM_CHAR
{
@ -205,7 +204,7 @@ void KeybQueueKeypress(WPARAM key, Keystroke_e bASCII)
}
else //i.e. latin letters
{
if (GetCapsLockAllowed() == false)
if (GetCapsLockAllowed() == false)
{
if (key == '{') keycode = '[';
if (key == '}') keycode = ']';
@ -309,7 +308,27 @@ void KeybQueueKeypress(WPARAM key, Keystroke_e bASCII)
}
else if ((GetKeyState(VK_RMENU) < 0)) // Right Alt (aka Alt Gr)
{
//
if (IsVirtualKeyAnAppleIIKey(key))
{
// When Alt Gr is down, then WM_CHAR is not posted - so fix this.
// NB. Still get WM_KEYDOWN/WM_KEYUP for the virtual key, so AKD works.
WPARAM newKey = key;
// Translate if shift or ctrl is down
if (key >= 'A' && key <= 'Z')
{
if ( (GetKeyState(VK_SHIFT) >= 0) && !g_bCapsLock )
newKey += 'a' - 'A'; // convert to lowercase key
else if (GetKeyState(VK_CONTROL) < 0)
{
LogOutput("L-Control=%d, R-Control=%d\n", GetKeyState(VK_LCONTROL), GetKeyState(VK_RCONTROL));
newKey -= 'A' - 1; // convert to control-key
}
}
PostMessage(g_hFrameWindow, WM_CHAR, newKey, 0);
}
return;
}
else
@ -401,16 +420,8 @@ const UINT kAKDNumElements = 256/64;
static uint64_t g_AKDFlags[2][kAKDNumElements] = { {0,0,0,0}, // normal
{0,0,0,0}}; // extended
// NB. Don't need to be concerned about if numpad/cursors are used for joystick,
// since parent calls JoyProcessKey() just before this.
void KeybAnyKeyDown(UINT message, WPARAM wparam, bool bIsExtended)
static bool IsVirtualKeyAnAppleIIKey(WPARAM wparam)
{
if (wparam > 255)
{
_ASSERT(0);
return;
}
if (wparam == VK_BACK ||
wparam == VK_TAB ||
wparam == VK_RETURN ||
@ -425,6 +436,24 @@ void KeybAnyKeyDown(UINT message, WPARAM wparam, bool bIsExtended)
(wparam >= VK_OEM_1 && wparam <= VK_OEM_3) || // 7 in total
(wparam >= VK_OEM_4 && wparam <= VK_OEM_8) || // 5 in total
(wparam == VK_OEM_102))
{
return true;
}
return false;
}
// NB. Don't need to be concerned about if numpad/cursors are used for joystick,
// since parent calls JoyProcessKey() just before this.
void KeybAnyKeyDown(UINT message, WPARAM wparam, bool bIsExtended)
{
if (wparam > 255)
{
_ASSERT(0);
return;
}
if (IsVirtualKeyAnAppleIIKey(wparam))
{
UINT offset = wparam >> 6;
UINT bit = wparam & 0x3f;

View File

@ -5,12 +5,11 @@ enum Keystroke_e {NOT_ASCII=0, ASCII};
void ClipboardInitiatePaste();
void KeybReset();
bool KeybGetAltStatus();
bool KeybGetCapsStatus();
bool KeybGetP8CapsStatus();
bool KeybGetAltStatus();
bool KeybGetCtrlStatus();
bool KeybGetShiftStatus();
bool KeybGetCapsAllowed(); //For Pravets8A/C only
void KeybUpdateCtrlShiftStatus();
BYTE KeybGetKeycode ();
void KeybQueueKeypress(WPARAM key, Keystroke_e bASCII);
@ -22,7 +21,3 @@ BYTE KeybReadFlag (void);
void KeybSetSnapshot_v1(const BYTE LastKey);
void KeybSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
void KeybLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
extern bool g_bShiftKey;
extern bool g_bCtrlKey;
extern bool g_bAltKey;