提交 bd0cc2f5 编写于 作者: V vit9696

OpenCanopy: Added partial hotkey support (e.g. Ctrl+Enter)

上级 c04980f3
......@@ -3,7 +3,7 @@ OpenCore Changelog
#### v0.5.9
- Added full HiDPI support in OpenCanopy
- Improved font rendering by using CoreText
- Improved OpenCanopy font rendering by using CoreText
- Fixed light and custom background font rendering
- Added `Boot####` options support in boot entry listing
- Removed `HideSelf` by pattern recognising `BOOTx64.efi`
......@@ -18,6 +18,7 @@ OpenCore Changelog
- Fixed `ReconnectOnResChange` reconnecting even without res change
- Fixed OpenCanopy showing internal icons for external drives
- Fixed OpenCanopy launching Shell with text over it
- Added partial hotkey support to OpenCanopy (e.g. Ctrl+Enter)
#### v0.5.8
- Fixed invalid CPU object reference in SSDT-PLUG
......
......@@ -916,15 +916,33 @@ OcLoadPickerHotKeys (
#define OC_INPUT_BOTTOM -10 ///< Move to bottom
#define OC_INPUT_MORE -11 ///< Show more entries (press space)
#define OC_INPUT_VOICE_OVER -12 ///< Toggle VoiceOver (press CMD+F5)
#define OC_INPUT_INTERNAL -13 ///< Accepted internal hotkey (e.g. Apple)
#define OC_INPUT_FUNCTIONAL(x) (-20 - (x)) ///< Functional hotkeys
/**
Obtains key index from user input.
@param[in,out] Context Picker context.
@param[in] KeyMap Apple Key Map Aggregator protocol.
@param[out] SetDefault Set boot option as default, optional.
@returns key index [0, OC_INPUT_MAX) or OC_INPUT_* value.
@returns OC_INPUT_TIMEOUT when no key is pressed.
@returns OC_INPUT_INVALID when unknown key is pressed.
**/
INTN
OcGetAppleKeyIndex (
IN OUT OC_PICKER_CONTEXT *Context,
IN APPLE_KEY_MAP_AGGREGATOR_PROTOCOL *KeyMap,
OUT BOOLEAN *SetDefault OPTIONAL
);
/**
Waits for key index from user input.
@param[in,out] Context Picker context.
@param[in] KeyMap Apple Key Map Aggregator protocol.
@param[in] Timeout Timeout to wait for in milliseconds.
@param[in] PollHotkeys Poll key combinations.
@param[out] SetDefault Set boot option as default, optional.
@returns key index [0, OC_INPUT_MAX) or OC_INPUT_* value.
......@@ -934,7 +952,6 @@ OcWaitForAppleKeyIndex (
IN OUT OC_PICKER_CONTEXT *Context,
IN APPLE_KEY_MAP_AGGREGATOR_PROTOCOL *KeyMap,
IN UINTN Timeout,
IN BOOLEAN PollHotkeys,
OUT BOOLEAN *SetDefault OPTIONAL
);
......
......@@ -121,11 +121,9 @@ OcLoadPickerHotKeys (
}
INTN
OcWaitForAppleKeyIndex (
OcGetAppleKeyIndex (
IN OUT OC_PICKER_CONTEXT *Context,
IN APPLE_KEY_MAP_AGGREGATOR_PROTOCOL *KeyMap,
IN UINTN Timeout,
IN BOOLEAN PollHotkeys,
OUT BOOLEAN *SetDefault OPTIONAL
)
{
......@@ -146,259 +144,293 @@ OcWaitForAppleKeyIndex (
BOOLEAN WantsZeroSlide;
BOOLEAN WantsDefault;
UINT32 CsrActiveConfig;
UINT64 CurrTime;
UINT64 EndTime;
UINTN CsrActiveConfigSize;
//
// These hotkeys are normally parsed by boot.efi, and they work just fine
// when ShowPicker is disabled. On some BSPs, however, they may fail badly
// when ShowPicker is enabled, and for this reason we support these hotkeys
// within picker itself.
//
CurrTime = GetTimeInNanoSecond (GetPerformanceCounter ());
EndTime = CurrTime + Timeout * 1000000ULL;
NumKeys = ARRAY_SIZE (Keys);
Status = KeyMap->GetKeyStrokes (
KeyMap,
&Modifiers,
&NumKeys,
Keys
);
if (SetDefault != NULL) {
*SetDefault = FALSE;
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "OCB: GetKeyStrokes - %r\n", Status));
return OC_INPUT_INVALID;
}
while (Timeout == 0 || CurrTime == 0 || CurrTime < EndTime) {
NumKeys = ARRAY_SIZE (Keys);
Status = KeyMap->GetKeyStrokes (
KeyMap,
&Modifiers,
&NumKeys,
Keys
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "OCB: GetKeyStrokes - %r\n", Status));
return OC_INPUT_INVALID;
//
// Handle key combinations.
//
if (Context->PollAppleHotKeys) {
HasCommand = (Modifiers & (APPLE_MODIFIER_LEFT_COMMAND | APPLE_MODIFIER_RIGHT_COMMAND)) != 0;
HasShift = (Modifiers & (APPLE_MODIFIER_LEFT_SHIFT | APPLE_MODIFIER_RIGHT_SHIFT)) != 0;
HasKeyC = OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyC);
HasKeyK = OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyK);
HasKeyS = OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyS);
HasKeyV = OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyV);
//
// Checking for PAD minus is our extension to support more keyboards.
//
HasKeyMinus = OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyMinus)
|| OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyPadMinus);
//
// Shift is always valid and enables Safe Mode.
//
if (HasShift) {
if (OcGetArgumentFromCmd (Context->AppleBootArgs, "-x", L_STR_LEN ("-x")) == NULL) {
DEBUG ((DEBUG_INFO, "OCB: Shift means -x\n"));
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "-x", L_STR_LEN ("-x"));
}
return OC_INPUT_INTERNAL;
}
CurrTime = GetTimeInNanoSecond (GetPerformanceCounter ());
//
// CMD+V is always valid and enables Verbose Mode.
//
if (HasCommand && HasKeyV) {
if (OcGetArgumentFromCmd (Context->AppleBootArgs, "-v", L_STR_LEN ("-v")) == NULL) {
DEBUG ((DEBUG_INFO, "OCB: CMD+V means -v\n"));
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "-v", L_STR_LEN ("-v"));
}
return OC_INPUT_INTERNAL;
}
//
// Handle key combinations.
// CMD+C+MINUS is always valid and disables compatibility check.
//
if (PollHotkeys) {
HasCommand = (Modifiers & (APPLE_MODIFIER_LEFT_COMMAND | APPLE_MODIFIER_RIGHT_COMMAND)) != 0;
HasShift = (Modifiers & (APPLE_MODIFIER_LEFT_SHIFT | APPLE_MODIFIER_RIGHT_SHIFT)) != 0;
HasKeyC = OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyC);
HasKeyK = OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyK);
HasKeyS = OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyS);
HasKeyV = OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyV);
//
// Checking for PAD minus is our extension to support more keyboards.
//
HasKeyMinus = OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyMinus)
|| OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyPadMinus);
//
// Shift is always valid and enables Safe Mode.
//
if (HasShift) {
if (OcGetArgumentFromCmd (Context->AppleBootArgs, "-x", L_STR_LEN ("-x")) == NULL) {
DEBUG ((DEBUG_INFO, "OCB: Shift means -x\n"));
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "-x", L_STR_LEN ("-x"));
}
continue;
if (HasCommand && HasKeyC && HasKeyMinus) {
if (OcGetArgumentFromCmd (Context->AppleBootArgs, "-no_compat_check", L_STR_LEN ("-no_compat_check")) == NULL) {
DEBUG ((DEBUG_INFO, "OCB: CMD+C+MINUS means -no_compat_check\n"));
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "-no_compat_check", L_STR_LEN ("-no_compat_check"));
}
return OC_INPUT_INTERNAL;
}
//
// CMD+V is always valid and enables Verbose Mode.
//
if (HasCommand && HasKeyV) {
if (OcGetArgumentFromCmd (Context->AppleBootArgs, "-v", L_STR_LEN ("-v")) == NULL) {
DEBUG ((DEBUG_INFO, "OCB: CMD+V means -v\n"));
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "-v", L_STR_LEN ("-v"));
}
continue;
//
// CMD+K is always valid for new macOS and means force boot to release kernel.
//
if (HasCommand && HasKeyK) {
if (AsciiStrStr (Context->AppleBootArgs, "kcsuffix=release") == NULL) {
DEBUG ((DEBUG_INFO, "OCB: CMD+K means kcsuffix=release\n"));
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "kcsuffix=release", L_STR_LEN ("kcsuffix=release"));
}
return OC_INPUT_INTERNAL;
}
//
// CMD+C+MINUS is always valid and disables compatibility check.
//
if (HasCommand && HasKeyC && HasKeyMinus) {
if (OcGetArgumentFromCmd (Context->AppleBootArgs, "-no_compat_check", L_STR_LEN ("-no_compat_check")) == NULL) {
DEBUG ((DEBUG_INFO, "OCB: CMD+C+MINUS means -no_compat_check\n"));
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "-no_compat_check", L_STR_LEN ("-no_compat_check"));
}
continue;
//
// boot.efi also checks for CMD+X, but I have no idea what it is for.
//
//
// boot.efi requires unrestricted NVRAM just for CMD+S+MINUS, and CMD+S
// does not work at all on T2 macs. For CMD+S we simulate T2 behaviour with
// DisableSingleUser Booter quirk if necessary.
// Ref: https://support.apple.com/HT201573
//
if (HasCommand && HasKeyS) {
WantsZeroSlide = HasKeyMinus;
if (WantsZeroSlide) {
CsrActiveConfig = 0;
CsrActiveConfigSize = sizeof (CsrActiveConfig);
Status = gRT->GetVariable (
L"csr-active-config",
&gAppleBootVariableGuid,
NULL,
&CsrActiveConfigSize,
&CsrActiveConfig
);
//
// FIXME: CMD+S+Minus behaves as CMD+S when "slide=0" is not supported
// by the SIP configuration. This might be an oversight, but is
// consistent with the boot.efi implementation.
//
WantsZeroSlide = !EFI_ERROR (Status) && (CsrActiveConfig & CSR_ALLOW_UNRESTRICTED_NVRAM) != 0;
}
//
// CMD+K is always valid for new macOS and means force boot to release kernel.
//
if (HasCommand && HasKeyK) {
if (AsciiStrStr (Context->AppleBootArgs, "kcsuffix=release") == NULL) {
DEBUG ((DEBUG_INFO, "OCB: CMD+K means kcsuffix=release\n"));
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "kcsuffix=release", L_STR_LEN ("kcsuffix=release"));
if (WantsZeroSlide) {
if (AsciiStrStr (Context->AppleBootArgs, "slide=0") == NULL) {
DEBUG ((DEBUG_INFO, "OCB: CMD+S+MINUS means slide=0\n"));
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "slide=0", L_STR_LEN ("slide=0"));
}
continue;
} else if (OcGetArgumentFromCmd (Context->AppleBootArgs, "-s", L_STR_LEN ("-s")) == NULL) {
DEBUG ((DEBUG_INFO, "OCB: CMD+S means -s\n"));
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "-s", L_STR_LEN ("-s"));
}
return OC_INPUT_INTERNAL;
}
}
//
// boot.efi also checks for CMD+X, but I have no idea what it is for.
//
//
// boot.efi requires unrestricted NVRAM just for CMD+S+MINUS, and CMD+S
// does not work at all on T2 macs. For CMD+S we simulate T2 behaviour with
// DisableSingleUser Booter quirk if necessary.
// Ref: https://support.apple.com/HT201573
//
if (HasCommand && HasKeyS) {
WantsZeroSlide = HasKeyMinus;
if (WantsZeroSlide) {
CsrActiveConfig = 0;
CsrActiveConfigSize = sizeof (CsrActiveConfig);
Status = gRT->GetVariable (
L"csr-active-config",
&gAppleBootVariableGuid,
NULL,
&CsrActiveConfigSize,
&CsrActiveConfig
);
//
// FIXME: CMD+S+Minus behaves as CMD+S when "slide=0" is not supported
// by the SIP configuration. This might be an oversight, but is
// consistent with the boot.efi implementation.
//
WantsZeroSlide = !EFI_ERROR (Status) && (CsrActiveConfig & CSR_ALLOW_UNRESTRICTED_NVRAM) != 0;
}
//
// Handle VoiceOver.
//
if ((Modifiers & (APPLE_MODIFIER_LEFT_COMMAND | APPLE_MODIFIER_RIGHT_COMMAND)) != 0
&& OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyF5)) {
OcKeyMapFlush (KeyMap, 0, TRUE);
return OC_INPUT_VOICE_OVER;
}
if (WantsZeroSlide) {
if (AsciiStrStr (Context->AppleBootArgs, "slide=0") == NULL) {
DEBUG ((DEBUG_INFO, "OCB: CMD+S+MINUS means slide=0\n"));
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "slide=0", L_STR_LEN ("slide=0"));
}
} else if (OcGetArgumentFromCmd (Context->AppleBootArgs, "-s", L_STR_LEN ("-s")) == NULL) {
DEBUG ((DEBUG_INFO, "OCB: CMD+S means -s\n"));
OcAppendArgumentToCmd (Context, Context->AppleBootArgs, "-s", L_STR_LEN ("-s"));
}
continue;
//
// Handle reload menu.
//
if (OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyEscape)
|| OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyZero)) {
OcKeyMapFlush (KeyMap, 0, TRUE);
return OC_INPUT_ABORTED;
}
if (OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeySpaceBar)) {
OcKeyMapFlush (KeyMap, 0, TRUE);
return OC_INPUT_MORE;
}
//
// Default update is desired for Ctrl+Index and Ctrl+Enter.
//
WantsDefault = Modifiers != 0 && (Modifiers & ~(APPLE_MODIFIER_LEFT_CONTROL | APPLE_MODIFIER_RIGHT_CONTROL)) == 0;
//
// Check exact match on index strokes.
//
if ((Modifiers == 0 || WantsDefault) && NumKeys == 1) {
if (Keys[0] == AppleHidUsbKbUsageKeyEnter
|| Keys[0] == AppleHidUsbKbUsageKeyReturn
|| Keys[0] == AppleHidUsbKbUsageKeyPadEnter) {
if (WantsDefault && SetDefault != NULL) {
*SetDefault = TRUE;
}
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_CONTINUE;
}
//
// Handle VoiceOver.
//
if ((Modifiers & (APPLE_MODIFIER_LEFT_COMMAND | APPLE_MODIFIER_RIGHT_COMMAND)) != 0
&& OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyF5)) {
OcKeyMapFlush (KeyMap, 0, TRUE);
return OC_INPUT_VOICE_OVER;
if (Keys[0] == AppleHidUsbKbUsageKeyUpArrow) {
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_UP;
}
//
// Handle reload menu.
//
if (OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyEscape)
|| OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeyZero)) {
OcKeyMapFlush (KeyMap, 0, TRUE);
return OC_INPUT_ABORTED;
if (Keys[0] == AppleHidUsbKbUsageKeyDownArrow) {
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_DOWN;
}
if (OcKeyMapHasKey (Keys, NumKeys, AppleHidUsbKbUsageKeySpaceBar)) {
OcKeyMapFlush (KeyMap, 0, TRUE);
return OC_INPUT_MORE;
if (Keys[0] == AppleHidUsbKbUsageKeyLeftArrow) {
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_LEFT;
}
//
// Default update is desired for Ctrl+Index and Ctrl+Enter.
//
WantsDefault = Modifiers != 0 && (Modifiers & ~(APPLE_MODIFIER_LEFT_CONTROL | APPLE_MODIFIER_RIGHT_CONTROL)) == 0;
if (Keys[0] == AppleHidUsbKbUsageKeyRightArrow) {
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_RIGHT;
}
//
// Check exact match on index strokes.
//
if ((Modifiers == 0 || WantsDefault) && NumKeys == 1) {
if (Keys[0] == AppleHidUsbKbUsageKeyEnter
|| Keys[0] == AppleHidUsbKbUsageKeyReturn
|| Keys[0] == AppleHidUsbKbUsageKeyPadEnter) {
if (Keys[0] == AppleHidUsbKbUsageKeyPgUp
|| Keys[0] == AppleHidUsbKbUsageKeyHome) {
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_TOP;
}
if (Keys[0] == AppleHidUsbKbUsageKeyPgDn
|| Keys[0] == AppleHidUsbKbUsageKeyEnd) {
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_BOTTOM;
}
STATIC_ASSERT (AppleHidUsbKbUsageKeyF1 + 11 == AppleHidUsbKbUsageKeyF12, "Unexpected encoding");
if (Keys[0] >= AppleHidUsbKbUsageKeyF1 && Keys[0] <= AppleHidUsbKbUsageKeyF12) {
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_FUNCTIONAL (Keys[0] - AppleHidUsbKbUsageKeyF1 + 1);
}
STATIC_ASSERT (AppleHidUsbKbUsageKeyF13 + 11 == AppleHidUsbKbUsageKeyF24, "Unexpected encoding");
if (Keys[0] >= AppleHidUsbKbUsageKeyF13 && Keys[0] <= AppleHidUsbKbUsageKeyF24) {
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_FUNCTIONAL (Keys[0] - AppleHidUsbKbUsageKeyF13 + 13);
}
STATIC_ASSERT (AppleHidUsbKbUsageKeyOne + 8 == AppleHidUsbKbUsageKeyNine, "Unexpected encoding");
for (KeyCode = AppleHidUsbKbUsageKeyOne; KeyCode <= AppleHidUsbKbUsageKeyNine; ++KeyCode) {
if (OcKeyMapHasKey (Keys, NumKeys, KeyCode)) {
if (WantsDefault && SetDefault != NULL) {
*SetDefault = TRUE;
}
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_CONTINUE;
return (INTN) (KeyCode - AppleHidUsbKbUsageKeyOne);
}
}
if (Keys[0] == AppleHidUsbKbUsageKeyUpArrow) {
STATIC_ASSERT (AppleHidUsbKbUsageKeyA + 25 == AppleHidUsbKbUsageKeyZ, "Unexpected encoding");
for (KeyCode = AppleHidUsbKbUsageKeyA; KeyCode <= AppleHidUsbKbUsageKeyZ; ++KeyCode) {
if (OcKeyMapHasKey (Keys, NumKeys, KeyCode)) {
if (WantsDefault && SetDefault != NULL) {
*SetDefault = TRUE;
}
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_UP;
return (INTN) (KeyCode - AppleHidUsbKbUsageKeyA + 9);
}
}
}
if (Keys[0] == AppleHidUsbKbUsageKeyDownArrow) {
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_DOWN;
}
if (NumKeys > 0) {
return OC_INPUT_INVALID;
}
if (Keys[0] == AppleHidUsbKbUsageKeyLeftArrow) {
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_LEFT;
}
return OC_INPUT_TIMEOUT;
}
if (Keys[0] == AppleHidUsbKbUsageKeyRightArrow) {
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_RIGHT;
}
INTN
OcWaitForAppleKeyIndex (
IN OUT OC_PICKER_CONTEXT *Context,
IN APPLE_KEY_MAP_AGGREGATOR_PROTOCOL *KeyMap,
IN UINTN Timeout,
OUT BOOLEAN *SetDefault OPTIONAL
)
{
INTN ResultingKey;
UINT64 CurrTime;
UINT64 EndTime;
if (Keys[0] == AppleHidUsbKbUsageKeyPgUp
|| Keys[0] == AppleHidUsbKbUsageKeyHome) {
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_TOP;
}
//
// These hotkeys are normally parsed by boot.efi, and they work just fine
// when ShowPicker is disabled. On some BSPs, however, they may fail badly
// when ShowPicker is enabled, and for this reason we support these hotkeys
// within picker itself.
//
if (Keys[0] == AppleHidUsbKbUsageKeyPgDn
|| Keys[0] == AppleHidUsbKbUsageKeyEnd) {
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_BOTTOM;
}
CurrTime = GetTimeInNanoSecond (GetPerformanceCounter ());
EndTime = CurrTime + Timeout * 1000000ULL;
STATIC_ASSERT (AppleHidUsbKbUsageKeyF1 + 11 == AppleHidUsbKbUsageKeyF12, "Unexpected encoding");
if (Keys[0] >= AppleHidUsbKbUsageKeyF1 && Keys[0] <= AppleHidUsbKbUsageKeyF12) {
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_FUNCTIONAL (Keys[0] - AppleHidUsbKbUsageKeyF1 + 1);
}
if (SetDefault != NULL) {
*SetDefault = FALSE;
}
STATIC_ASSERT (AppleHidUsbKbUsageKeyF13 + 11 == AppleHidUsbKbUsageKeyF24, "Unexpected encoding");
if (Keys[0] >= AppleHidUsbKbUsageKeyF13 && Keys[0] <= AppleHidUsbKbUsageKeyF24) {
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return OC_INPUT_FUNCTIONAL (Keys[0] - AppleHidUsbKbUsageKeyF13 + 13);
}
while (Timeout == 0 || CurrTime == 0 || CurrTime < EndTime) {
CurrTime = GetTimeInNanoSecond (GetPerformanceCounter ());
STATIC_ASSERT (AppleHidUsbKbUsageKeyOne + 8 == AppleHidUsbKbUsageKeyNine, "Unexpected encoding");
for (KeyCode = AppleHidUsbKbUsageKeyOne; KeyCode <= AppleHidUsbKbUsageKeyNine; ++KeyCode) {
if (OcKeyMapHasKey (Keys, NumKeys, KeyCode)) {
if (WantsDefault && SetDefault != NULL) {
*SetDefault = TRUE;
}
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return (INTN) (KeyCode - AppleHidUsbKbUsageKeyOne);
}
}
ResultingKey = OcGetAppleKeyIndex (Context, KeyMap, SetDefault);
STATIC_ASSERT (AppleHidUsbKbUsageKeyA + 25 == AppleHidUsbKbUsageKeyZ, "Unexpected encoding");
for (KeyCode = AppleHidUsbKbUsageKeyA; KeyCode <= AppleHidUsbKbUsageKeyZ; ++KeyCode) {
if (OcKeyMapHasKey (Keys, NumKeys, KeyCode)) {
if (WantsDefault && SetDefault != NULL) {
*SetDefault = TRUE;
}
OcKeyMapFlush (KeyMap, Keys[0], TRUE);
return (INTN) (KeyCode - AppleHidUsbKbUsageKeyA + 9);
}
}
//
// Requested for another iteration, handled Apple hotkey.
//
if (ResultingKey == OC_INPUT_INTERNAL) {
continue;
}
//
// Abort the timeout when unrecognised keys are pressed.
//
if (Timeout != 0 && NumKeys != 0) {
if (Timeout != 0 && ResultingKey == OC_INPUT_INVALID) {
return OC_INPUT_INVALID;
}
//
// Found key, return it.
//
if (ResultingKey != OC_INPUT_INVALID && ResultingKey != OC_INPUT_TIMEOUT) {
return ResultingKey;
}
MicroSecondDelay (10);
}
......
......@@ -225,7 +225,6 @@ OcShowSimpleBootMenu (
BootContext->PickerContext,
KeyMap,
PlayChosen ? OC_VOICE_OVER_IDLE_TIMEOUT_MS : TimeOutSeconds * 1000,
BootContext->PickerContext->PollAppleHotKeys,
&SetDefault
);
......
......@@ -8,6 +8,7 @@
#ifndef GUI_IO_H
#define GUI_IO_H
#include <Library/OcBootManagementLib.h>
#include <Protocol/GraphicsOutput.h>
#include "OpenCanopy.h"
......@@ -65,10 +66,11 @@ GuiPointerReset (
GUI_POINTER_CONTEXT *
GuiPointerConstruct (
IN UINT32 DefaultX,
IN UINT32 DefaultY,
IN UINT32 Width,
IN UINT32 Height
IN OC_PICKER_CONTEXT *PickerContext,
IN UINT32 DefaultX,
IN UINT32 DefaultY,
IN UINT32 Width,
IN UINT32 Height
);
VOID
......@@ -78,7 +80,7 @@ GuiPointerDestruct (
GUI_KEY_CONTEXT *
GuiKeyConstruct (
VOID
IN OC_PICKER_CONTEXT *PickerContext
);
VOID
......@@ -91,7 +93,8 @@ EFI_STATUS
EFIAPI
GuiKeyRead (
IN OUT GUI_KEY_CONTEXT *Context,
OUT EFI_INPUT_KEY *Key
OUT INTN *KeyIndex,
OUT BOOLEAN *Modifier
);
VOID
......
......@@ -451,10 +451,11 @@ GuiPointerGetState (
GUI_POINTER_CONTEXT *
GuiPointerConstruct (
IN UINT32 DefaultX,
IN UINT32 DefaultY,
IN UINT32 Width,
IN UINT32 Height
IN OC_PICKER_CONTEXT *PickerContext,
IN UINT32 DefaultX,
IN UINT32 DefaultY,
IN UINT32 Width,
IN UINT32 Height
)
{
// TODO: alloc on the fly?
......
......@@ -7,39 +7,69 @@
#include <Uefi.h>
#include <Protocol/SimpleTextIn.h>
#include <Protocol/AppleKeyMapAggregator.h>
#include <Library/DebugLib.h>
#include <Library/OcAppleKeyMapLib.h>
#include <Library/OcBootManagementLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include "../GuiIo.h"
struct GUI_KEY_CONTEXT_ {
EFI_SIMPLE_TEXT_INPUT_PROTOCOL TextIn;
APPLE_KEY_MAP_AGGREGATOR_PROTOCOL *KeyMap;
OC_PICKER_CONTEXT *Context;
};
GUI_KEY_CONTEXT *
GuiKeyConstruct (
VOID
IN OC_PICKER_CONTEXT *PickerContext
)
{
ASSERT (gST->ConIn != NULL);
return (GUI_KEY_CONTEXT *)gST->ConIn;
STATIC GUI_KEY_CONTEXT mContext;
mContext.KeyMap = OcAppleKeyMapInstallProtocols (FALSE);
mContext.Context = PickerContext;
if (mContext.KeyMap == NULL) {
DEBUG ((DEBUG_WARN, "OCUI: Missing AppleKeyMapAggregator\n"));
return NULL;
}
return &mContext;
}
EFI_STATUS
EFIAPI
GuiKeyRead (
IN OUT GUI_KEY_CONTEXT *Context,
OUT EFI_INPUT_KEY *Key
OUT INTN *KeyIndex,
OUT BOOLEAN *Modifier
)
{
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextIn;
ASSERT (Context != NULL);
TextIn = &Context->TextIn;
return TextIn->ReadKeyStroke (TextIn, Key);
*Modifier = FALSE;
*KeyIndex = OcGetAppleKeyIndex (
Context->Context,
Context->KeyMap,
Modifier
);
//
// No key was pressed.
//
if (*KeyIndex == OC_INPUT_TIMEOUT) {
return EFI_NOT_FOUND;
}
//
// Internal key was pressed and handled.
//
if (*KeyIndex == OC_INPUT_INTERNAL) {
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
VOID
......@@ -48,14 +78,10 @@ GuiKeyReset (
IN OUT GUI_KEY_CONTEXT *Context
)
{
EFI_STATUS Status;
EFI_INPUT_KEY Key;
ASSERT (Context != NULL);
do {
Status = GuiKeyRead (Context, &Key);
} while (!EFI_ERROR (Status));
//
// Flush console here?
//
}
VOID
......@@ -64,4 +90,5 @@ GuiKeyDestruct (
)
{
ASSERT (Context != NULL);
ZeroMem (Context, sizeof (*Context));
}
......@@ -54,6 +54,7 @@ OcShowMenuByOc (
mGuiContext.Refresh = FALSE;
Status = GuiLibConstruct (
BootContext->PickerContext,
mGuiContext.CursorDefaultX,
mGuiContext.CursorDefaultY
);
......
......@@ -956,8 +956,9 @@ GuiRedrawAndFlushScreen (
EFI_STATUS
GuiLibConstruct (
IN UINT32 CursorDefaultX,
IN UINT32 CursorDefaultY
IN OC_PICKER_CONTEXT *PickerContet,
IN UINT32 CursorDefaultX,
IN UINT32 CursorDefaultY
)
{
CONST EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *OutputInfo;
......@@ -975,16 +976,17 @@ GuiLibConstruct (
CursorDefaultY = MIN (CursorDefaultY, OutputInfo->VerticalResolution - 1);
mPointerContext = GuiPointerConstruct (
CursorDefaultX,
CursorDefaultY,
OutputInfo->HorizontalResolution,
OutputInfo->VerticalResolution
);
PickerContet,
CursorDefaultX,
CursorDefaultY,
OutputInfo->HorizontalResolution,
OutputInfo->VerticalResolution
);
if (mPointerContext == NULL) {
DEBUG ((DEBUG_WARN, "OCUI: Failed to initialise pointer\n"));
}
mKeyContext = GuiKeyConstruct ();
mKeyContext = GuiKeyConstruct (PickerContet);
if (mKeyContext == NULL) {
DEBUG ((DEBUG_WARN, "OCUI: Failed to initialise key input\n"));
}
......@@ -1128,7 +1130,8 @@ GuiDrawLoop (
EFI_STATUS Status;
BOOLEAN Result;
EFI_INPUT_KEY InputKey;
INTN InputKey;
BOOLEAN Modifier;
GUI_POINTER_STATE PointerState;
GUI_OBJ *HoldObject;
INT64 HoldObjBaseX;
......@@ -1203,7 +1206,7 @@ GuiDrawLoop (
//
// Process key events. Only allow one key at a time for now.
//
Status = GuiKeyRead (mKeyContext, &InputKey);
Status = GuiKeyRead (mKeyContext, &InputKey, &Modifier);
if (!EFI_ERROR (Status)) {
ASSERT (DrawContext->Screen->KeyEvent != NULL);
DrawContext->Screen->KeyEvent (
......@@ -1212,7 +1215,8 @@ GuiDrawLoop (
DrawContext->GuiContext,
0,
0,
&InputKey
InputKey,
Modifier
);
//
// If detected key press then disable menu timeout
......
......@@ -8,6 +8,7 @@
#ifndef OPEN_CANOPY_H
#define OPEN_CANOPY_H
#include <Library/OcBootManagementLib.h>
#include <Protocol/GraphicsOutput.h>
#include <Protocol/SimpleTextIn.h>
......@@ -58,7 +59,8 @@ VOID
IN VOID *Context OPTIONAL,
IN INT64 BaseX,
IN INT64 BaseY,
IN CONST EFI_INPUT_KEY *Key
IN INTN Key,
IN BOOLEAN Modifier
);
typedef
......@@ -259,8 +261,9 @@ GuiClearScreen (
EFI_STATUS
GuiLibConstruct (
IN UINT32 CursorDefaultX,
IN UINT32 CursorDefaultY
IN OC_PICKER_CONTEXT *PickerContet,
IN UINT32 CursorDefaultX,
IN UINT32 CursorDefaultY
);
VOID
......
......@@ -68,6 +68,7 @@
DebugLib
FrameBufferBltLib
MemoryAllocationLib
OcAppleKeyMapLib
OcBootManagementLib
OcCompressionLib
OcGuardLib
......
......@@ -134,12 +134,13 @@ InternalBootPickerViewKeyEvent (
IN VOID *Context OPTIONAL,
IN INT64 BaseX,
IN INT64 BaseY,
IN CONST EFI_INPUT_KEY *Key
IN INTN Key,
IN BOOLEAN Modifier
)
{
ASSERT (This != NULL);
ASSERT (DrawContext != NULL);
ASSERT (Key != NULL);
//
// Consider moving between multiple panes with UP/DOWN and store the current
// view within the object - for now, hardcoding this is enough.
......@@ -151,7 +152,8 @@ InternalBootPickerViewKeyEvent (
Context,
BaseX + mBootPicker.Hdr.Obj.OffsetX,
BaseY + mBootPicker.Hdr.Obj.OffsetY,
Key
Key,
Modifier
);
}
......@@ -239,7 +241,8 @@ InternalBootPickerKeyEvent (
IN VOID *Context OPTIONAL,
IN INT64 BaseX,
IN INT64 BaseY,
IN CONST EFI_INPUT_KEY *Key
IN INTN Key,
IN BOOLEAN Modifier
)
{
GUI_VOLUME_PICKER *Picker;
......@@ -250,13 +253,12 @@ InternalBootPickerKeyEvent (
ASSERT (This != NULL);
ASSERT (DrawContext != NULL);
ASSERT (Key != NULL);
Picker = BASE_CR (This, GUI_VOLUME_PICKER, Hdr.Obj);
PrevEntry = Picker->SelectedEntry;
ASSERT (PrevEntry != NULL);
if (Key->ScanCode == SCAN_RIGHT) {
if (Key == OC_INPUT_RIGHT) {
NextLink = GetNextNode (
&Picker->Hdr.Obj.Children,
&PrevEntry->Hdr.Link
......@@ -271,7 +273,7 @@ InternalBootPickerKeyEvent (
NextEntry = BASE_CR (NextLink, GUI_VOLUME_ENTRY, Hdr.Link);
InternalBootPickerChangeEntry (Picker, DrawContext, BaseX, BaseY, NextEntry);
}
} else if (Key->ScanCode == SCAN_LEFT) {
} else if (Key == OC_INPUT_LEFT) {
NextLink = GetPreviousNode (
&Picker->Hdr.Obj.Children,
&PrevEntry->Hdr.Link
......@@ -283,10 +285,11 @@ InternalBootPickerKeyEvent (
NextEntry = BASE_CR (NextLink, GUI_VOLUME_ENTRY, Hdr.Link);
InternalBootPickerChangeEntry (Picker, DrawContext, BaseX, BaseY, NextEntry);
}
} else if (Key->UnicodeChar == CHAR_CARRIAGE_RETURN) {
} else if (Key == OC_INPUT_CONTINUE) {
ASSERT (Context != NULL);
ASSERT (Picker->SelectedEntry != NULL);
GuiContext = (BOOT_PICKER_GUI_CONTEXT *)Context;
Picker->SelectedEntry->Context->SetDefault = Modifier;
GuiContext->BootEntry = Picker->SelectedEntry->Context;
} else if (mBootPickerOpacity != 0xFF) {
//
......@@ -295,11 +298,11 @@ InternalBootPickerKeyEvent (
return;
}
if (Key->UnicodeChar == L' ') {
if (Key == OC_INPUT_MORE) {
GuiContext = (BOOT_PICKER_GUI_CONTEXT *)Context;
GuiContext->HideAuxiliary = FALSE;
GuiContext->Refresh = TRUE;
} else if (Key->ScanCode == SCAN_ESC) {
} else if (Key == OC_INPUT_ABORTED) {
GuiContext = (BOOT_PICKER_GUI_CONTEXT *)Context;
GuiContext->Refresh = TRUE;
}
......
......@@ -8,6 +8,8 @@
#ifndef BOOT_PICKER_H
#define BOOT_PICKER_H
#include "../OpenCanopy.h"
typedef struct {
GUI_OBJ_CHILD Hdr;
CONST GUI_IMAGE *ClickImage;
......@@ -18,7 +20,7 @@ typedef struct {
GUI_OBJ_CHILD Hdr;
GUI_IMAGE EntryIcon;
GUI_IMAGE Label;
VOID *Context;
OC_BOOT_ENTRY *Context;
BOOLEAN CustomIcon;
} GUI_VOLUME_ENTRY;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册