mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
OpenCanopy: Added AppleEvent mouse support
This commit is contained in:
parent
b4d52e44f6
commit
20fa82da42
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 *
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -56,6 +56,7 @@
|
||||
gEfiSimplePointerProtocolGuid
|
||||
gEfiAbsolutePointerProtocolGuid
|
||||
gEfiUserInterfaceThemeProtocolGuid
|
||||
gAppleEventProtocolGuid
|
||||
|
||||
gOcBootstrapProtocolGuid
|
||||
gOcInterfaceProtocolGuid
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user