OpenCanopy: Added AppleEvent mouse support

This commit is contained in:
vit9696 2020-04-14 06:20:50 +03:00
parent b4d52e44f6
commit 20fa82da42
9 changed files with 279 additions and 90 deletions

View File

@ -8,6 +8,7 @@ OpenCore Changelog
- Updated docs to cover separating SMBIOS via `UpdateSMBIOSMode`
- Fixed rendering macOS installer icons in OpenCanopy
- Added APFS support with Fusion Drive and enhanced security
- Added AppleEvent mouse support in OpenCanopy
#### v0.5.7
- Added TimeMachine detection to picker

View File

@ -434,14 +434,3 @@ InternalGetCursorImage (
GuiContext = (CONST BOOT_PICKER_GUI_CONTEXT *)Context;
return &GuiContext->Icons[ICON_CURSOR][ICON_TYPE_BASE];
}
EFI_STATUS
EFIAPI
UefiUnload (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
GuiLibDestruct ();
return EFI_SUCCESS;
}

View File

@ -79,7 +79,10 @@ typedef struct {
BOOLEAN HideAuxiliary;
BOOLEAN Refresh;
BOOLEAN Light;
BOOLEAN DoneIntroAnimation;
UINT8 Scale;
UINT32 CursorDefaultX;
UINT32 CursorDefaultY;
} BOOT_PICKER_GUI_CONTEXT;
RETURN_STATUS
@ -98,8 +101,9 @@ BootPickerEntriesAdd (
);
VOID
BootPickerEntriesEmpty (
VOID
BootPickerViewDeinitialize (
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN OUT BOOT_PICKER_GUI_CONTEXT *GuiContext
);
CONST GUI_IMAGE *

View File

@ -7,10 +7,12 @@
#include <Uefi.h>
#include <Protocol/AppleEvent.h>
#include <Protocol/AbsolutePointer.h>
#include <Protocol/SimplePointer.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/OcGuardLib.h>
#include <Library/UefiBootServicesTableLib.h>
@ -19,8 +21,10 @@
#include "../GuiIo.h"
struct GUI_POINTER_CONTEXT_ {
APPLE_EVENT_PROTOCOL *AppleEvent;
EFI_SIMPLE_POINTER_PROTOCOL *Pointer;
EFI_ABSOLUTE_POINTER_PROTOCOL *AbsPointer;
APPLE_EVENT_HANDLE AppleEventHandle;
UINT32 Width;
UINT32 Height;
UINT32 MaxX;
@ -28,6 +32,8 @@ struct GUI_POINTER_CONTEXT_ {
UINT32 X;
UINT32 Y;
UINT8 LockedBy;
BOOLEAN PrimaryDown;
BOOLEAN SecondaryDown;
};
enum {
@ -36,6 +42,71 @@ enum {
PointerLockedAbsolute
};
STATIC
VOID
EFIAPI
InternalAppleEventNotification (
IN APPLE_EVENT_INFORMATION *Information,
IN VOID *NotifyContext
)
{
APPLE_POINTER_EVENT_TYPE EventType;
GUI_POINTER_CONTEXT *Context;
Context = NotifyContext;
//
// Should not happen but just in case.
//
if ((Information->EventType & APPLE_ALL_MOUSE_EVENTS) == 0) {
return;
}
EventType = Information->EventData.PointerEventType;
if ((EventType & APPLE_EVENT_TYPE_MOUSE_MOVED) != 0) {
Context->X = MIN (
(UINT32) Information->PointerPosition.Horizontal,
Context->MaxX
);
Context->Y = MIN (
(UINT32) Information->PointerPosition.Vertical,
Context->MaxY
);
}
if ((EventType & APPLE_EVENT_TYPE_MOUSE_DOWN) != 0) {
if ((EventType & APPLE_EVENT_TYPE_LEFT_BUTTON) != 0) {
Context->PrimaryDown = TRUE;
} else if ((Information->EventType & APPLE_EVENT_TYPE_RIGHT_BUTTON) != 0) {
Context->SecondaryDown = TRUE;
}
} else if ((EventType & APPLE_EVENT_TYPE_MOUSE_UP) != 0) {
if ((EventType & APPLE_EVENT_TYPE_LEFT_BUTTON) != 0) {
Context->PrimaryDown = FALSE;
} else if ((EventType & APPLE_EVENT_TYPE_RIGHT_BUTTON) != 0) {
Context->SecondaryDown = FALSE;
}
}
}
STATIC
EFI_STATUS
InternalUpdateStateSimpleAppleEvent (
IN OUT GUI_POINTER_CONTEXT *Context,
OUT GUI_POINTER_STATE *State
)
{
ASSERT (Context->AppleEvent != NULL);
State->X = Context->X;
State->Y = Context->Y;
State->PrimaryDown = Context->PrimaryDown;
State->SecondaryDown = Context->SecondaryDown;
return EFI_SUCCESS;
}
STATIC
UINT32
InternalClipPointerSimple (
@ -87,7 +158,7 @@ InternalGetInterpolatedValue (
STATIC
EFI_STATUS
InternalUpdateStateSimple (
InternalUpdateStateSimplePointer (
IN OUT GUI_POINTER_CONTEXT *Context,
OUT GUI_POINTER_STATE *State
)
@ -97,12 +168,7 @@ InternalUpdateStateSimple (
INT64 InterpolatedX;
INT64 InterpolatedY;
ASSERT (Context != NULL);
ASSERT (State != NULL);
if (Context->Pointer == NULL) {
return EFI_UNSUPPORTED;
}
ASSERT (Context->Pointer != NULL);
Status = Context->Pointer->GetState (Context->Pointer, &PointerState);
if (EFI_ERROR (Status)) {
@ -156,6 +222,33 @@ InternalUpdateStateSimple (
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
InternalUpdateStateSimple (
IN OUT GUI_POINTER_CONTEXT *Context,
OUT GUI_POINTER_STATE *State
)
{
ASSERT (Context != NULL);
ASSERT (State != NULL);
if (Context->AppleEvent != NULL) {
return InternalUpdateStateSimpleAppleEvent (
Context,
State
);
}
if (Context->Pointer != NULL) {
return InternalUpdateStateSimplePointer (
Context,
State
);
}
return EFI_UNSUPPORTED;
}
STATIC
EFI_STATUS
InternalUpdateStateAbsolute (
@ -332,34 +425,75 @@ GuiPointerConstruct (
EFI_STATUS Status;
EFI_STATUS Status2;
EFI_TPL OldTpl;
DIMENSION Dimension;
ASSERT (DefaultX < Width);
ASSERT (DefaultY < Height);
Context.Width = Width;
Context.Height = Height;
Context.MaxX = Width - 1;
Context.MaxY = Height - 1;
Context.X = DefaultX;
Context.Y = DefaultY;
Status = InternalHandleProtocolFallback (
gST->ConsoleInHandle,
&gEfiSimplePointerProtocolGuid,
(VOID **)&Context.Pointer
);
gST->ConsoleInHandle,
&gAppleEventProtocolGuid,
(VOID **)&Context.AppleEvent
);
if (!EFI_ERROR (Status)) {
if (Context.AppleEvent->Revision >= APPLE_EVENT_PROTOCOL_REVISION) {
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
Status = Context.AppleEvent->RegisterHandler (
APPLE_ALL_MOUSE_EVENTS,
InternalAppleEventNotification,
&Context.AppleEventHandle,
&Context
);
Dimension.Horizontal = (INT32) DefaultX;
Dimension.Vertical = (INT32) DefaultY;
Context.AppleEvent->SetCursorPosition (
&Dimension
);
gBS->RestoreTPL (OldTpl);
} else {
Status = EFI_UNSUPPORTED;
}
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_WARN,
"OCUI: AppleEvent %u is unsupported - %r\n",
Context.AppleEvent->Revision,
Status
));
Context.AppleEvent = NULL;
}
}
if (EFI_ERROR (Status)) {
Status = InternalHandleProtocolFallback (
gST->ConsoleInHandle,
&gEfiSimplePointerProtocolGuid,
(VOID **)&Context.Pointer
);
}
Status2 = InternalHandleProtocolFallback (
gST->ConsoleInHandle,
&gEfiAbsolutePointerProtocolGuid,
(VOID **)&Context.AbsPointer
);
gST->ConsoleInHandle,
&gEfiAbsolutePointerProtocolGuid,
(VOID **)&Context.AbsPointer
);
if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {
return NULL;
}
if (Context.Pointer != NULL) {
Context.X = DefaultX;
Context.Y = DefaultY;
Context.MaxX = Width - 1;
Context.MaxY = Height - 1;
}
Context.Width = Width;
Context.Height = Height;
return &Context;
}
@ -369,4 +503,12 @@ GuiPointerDestruct (
)
{
ASSERT (Context != NULL);
if (Context->AppleEvent != NULL) {
Context->AppleEvent->UnregisterHandler (
Context->AppleEventHandle
);
}
ZeroMem (Context, sizeof (*Context));
}

View File

@ -51,7 +51,23 @@ OcShowMenuByOc (
mGuiContext.HideAuxiliary = Context->HideAuxiliary;
mGuiContext.Refresh = FALSE;
BootPickerEntriesEmpty ();
Status = GuiLibConstruct (
mGuiContext.CursorDefaultX,
mGuiContext.CursorDefaultY
);
if (RETURN_ERROR (Status)) {
return Status;
}
Status = BootPickerViewInitialize (
&mDrawContext,
&mGuiContext,
InternalGetCursorImage
);
if (RETURN_ERROR (Status)) {
GuiLibDestruct ();
return Status;
}
for (Index = 0; Index < Count; ++Index) {
Status = BootPickerEntriesAdd (
@ -61,6 +77,7 @@ OcShowMenuByOc (
Index == DefaultEntry
);
if (RETURN_ERROR (Status)) {
GuiLibDestruct ();
return Status;
}
}
@ -68,6 +85,13 @@ OcShowMenuByOc (
GuiDrawLoop (&mDrawContext);
ASSERT (mGuiContext.BootEntry != NULL || mGuiContext.Refresh);
//
// Note, it is important to destruct GUI here, as we must ensure
// that keyboard/mouse polling does not conflict with FV2 ui.
//
BootPickerViewDeinitialize (&mDrawContext, &mGuiContext);
GuiLibDestruct ();
*ChosenBootEntry = mGuiContext.BootEntry;
Context->HideAuxiliary = mGuiContext.HideAuxiliary;
if (mGuiContext.Refresh) {
@ -102,22 +126,11 @@ GuiOcInterfaceRun (
{
EFI_STATUS Status;
Status = GuiLibConstruct (0, 0);
if (RETURN_ERROR (Status)) {
return Status;
}
Status = InternalContextConstruct (&mGuiContext, Storage, Context);
if (RETURN_ERROR (Status)) {
return Status;
}
Status = BootPickerViewInitialize (
&mDrawContext,
&mGuiContext,
InternalGetCursorImage
);
Context->ShowMenu = OcShowMenuByOc;
return OcRunBootPicker (Context);

View File

@ -1057,6 +1057,22 @@ GuiViewInitialize (
InitializeListHead (&DrawContext->Animations);
}
VOID
GuiViewDeinitialize (
IN OUT GUI_DRAWING_CONTEXT *DrawContext
)
{
ZeroMem (DrawContext, sizeof (*DrawContext));
}
CONST GUI_SCREEN_CURSOR *
GuiViewCurrentCursor (
IN OUT GUI_DRAWING_CONTEXT *DrawContext
)
{
return &mScreenViewCursor;
}
VOID
GuiGetBaseCoords (
IN GUI_OBJ *This,

View File

@ -233,6 +233,16 @@ GuiViewInitialize (
IN VOID *GuiContext
);
VOID
GuiViewDeinitialize (
IN OUT GUI_DRAWING_CONTEXT *DrawContext
);
CONST GUI_SCREEN_CURSOR *
GuiViewCurrentCursor (
IN OUT GUI_DRAWING_CONTEXT *DrawContext
);
VOID
GuiDrawLoop (
IN OUT GUI_DRAWING_CONTEXT *DrawContext

View File

@ -56,6 +56,7 @@
gEfiSimplePointerProtocolGuid
gEfiAbsolutePointerProtocolGuid
gEfiUserInterfaceThemeProtocolGuid
gAppleEventProtocolGuid
gOcBootstrapProtocolGuid
gOcInterfaceProtocolGuid

View File

@ -976,36 +976,6 @@ InternalBootPickerEntryDestruct (
FreePool (Entry);
}
VOID
BootPickerEntriesEmpty (
VOID
)
{
LIST_ENTRY *ListEntry;
LIST_ENTRY *NextEntry;
GUI_VOLUME_ENTRY *BootEntry;
ListEntry = mBootPicker.Hdr.Obj.Children.BackLink;
ASSERT (ListEntry == &mBootPickerSelector.Hdr.Link);
//
// Last entry is always the selector, which is special and cannot be freed.
//
ListEntry = ListEntry->BackLink;
while (!IsNull (&mBootPicker.Hdr.Obj.Children, ListEntry)) {
NextEntry = ListEntry->BackLink;
RemoveEntryList (ListEntry);
mBootPicker.Hdr.Obj.Width -= BOOT_ENTRY_WIDTH + BOOT_ENTRY_SPACE;
mBootPicker.Hdr.Obj.OffsetX += (BOOT_ENTRY_WIDTH + BOOT_ENTRY_SPACE) / 2;
BootEntry = BASE_CR (ListEntry, GUI_VOLUME_ENTRY, Hdr.Link);
InternalBootPickerEntryDestruct (BootEntry);
ListEntry = NextEntry;
}
}
BOOLEAN
InternalBootPickerExitLoop (
IN VOID *Context
@ -1202,9 +1172,12 @@ BootPickerViewInitialize (
mBootPickerSelector.ClickImage = &GuiContext->Icons[ICON_SELECTOR][ICON_TYPE_BASE];
mBootPickerSelector.CurrentImage = &GuiContext->Icons[ICON_SELECTOR][ICON_TYPE_BASE];
mBootPickerSelector.Hdr.Obj.OffsetX = 0;
mBootPickerSelector.Hdr.Obj.OffsetY = 0;
mBootPicker.Hdr.Obj.OffsetX = mBootPickerView.Width / 2;
mBootPicker.Hdr.Obj.OffsetY = (mBootPickerView.Height - mBootPicker.Hdr.Obj.Height) / 2;
mBootPicker.Hdr.Obj.Width = 0;
// TODO: animations should be tied to UI objects, not global
// Each object has its own list of animations.
@ -1215,17 +1188,21 @@ BootPickerViewInitialize (
// Conditions for delta function:
//
InitBpAnimSinMov (GuiInterpolTypeSmooth, 0, 25);
STATIC GUI_ANIMATION PickerAnim;
PickerAnim.Context = NULL;
PickerAnim.Animate = InternalBootPickerAnimateSinMov;
InsertHeadList (&DrawContext->Animations, &PickerAnim.Link);
if (!GuiContext->DoneIntroAnimation) {
InitBpAnimSinMov (GuiInterpolTypeSmooth, 0, 25);
STATIC GUI_ANIMATION PickerAnim;
PickerAnim.Context = NULL;
PickerAnim.Animate = InternalBootPickerAnimateSinMov;
InsertHeadList (&DrawContext->Animations, &PickerAnim.Link);
InitBpAnimOpacity (GuiInterpolTypeSmooth, 0, 25);
STATIC GUI_ANIMATION PickerAnim2;
PickerAnim2.Context = NULL;
PickerAnim2.Animate = InternalBootPickerAnimateOpacity;
InsertHeadList (&DrawContext->Animations, &PickerAnim2.Link);
InitBpAnimOpacity (GuiInterpolTypeSmooth, 0, 25);
STATIC GUI_ANIMATION PickerAnim2;
PickerAnim2.Context = NULL;
PickerAnim2.Animate = InternalBootPickerAnimateOpacity;
InsertHeadList (&DrawContext->Animations, &PickerAnim2.Link);
GuiContext->DoneIntroAnimation = TRUE;
}
/*
InitBpAnimImageList(GuiInterpolTypeLinear, 25, 25);
@ -1237,3 +1214,39 @@ BootPickerViewInitialize (
return RETURN_SUCCESS;
}
VOID
BootPickerViewDeinitialize (
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN OUT BOOT_PICKER_GUI_CONTEXT *GuiContext
)
{
LIST_ENTRY *ListEntry;
LIST_ENTRY *NextEntry;
GUI_VOLUME_ENTRY *BootEntry;
CONST GUI_SCREEN_CURSOR *ScreenCursor;
ListEntry = mBootPicker.Hdr.Obj.Children.BackLink;
ASSERT (ListEntry == &mBootPickerSelector.Hdr.Link);
//
// Last entry is always the selector, which is special and cannot be freed.
//
ListEntry = ListEntry->BackLink;
while (!IsNull (&mBootPicker.Hdr.Obj.Children, ListEntry)) {
NextEntry = ListEntry->BackLink;
RemoveEntryList (ListEntry);
BootEntry = BASE_CR (ListEntry, GUI_VOLUME_ENTRY, Hdr.Link);
InternalBootPickerEntryDestruct (BootEntry);
ListEntry = NextEntry;
}
ScreenCursor = GuiViewCurrentCursor (DrawContext);
GuiContext->CursorDefaultX = ScreenCursor->X;
GuiContext->CursorDefaultY = ScreenCursor->Y;
GuiViewDeinitialize (DrawContext);
}