mirror of
https://github.com/AppleWin/AppleWin.git
synced 2025-01-08 13:31:00 +00:00
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:
parent
1afa2490c5
commit
6ed354714e
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user