mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
1164 lines
33 KiB
C
1164 lines
33 KiB
C
/** @file
|
|
|
|
AppleEventDxe
|
|
|
|
Copyright (c) 2018, vit9696
|
|
|
|
All rights reserved.
|
|
|
|
This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
**/
|
|
|
|
#include <AppleMacEfi.h>
|
|
|
|
#include <Guid/AppleVariable.h>
|
|
|
|
#include <Protocol/GraphicsOutput.h>
|
|
#include <Protocol/UgaDraw.h>
|
|
#include <Protocol/SimplePointer.h>
|
|
|
|
#include <Library/AppleEventLib.h>
|
|
#include <Library/OcAppleEventLib.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiLib.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
#include <Library/TimerLib.h>
|
|
|
|
#include "AppleEventInternal.h"
|
|
|
|
#include <Library/BaseLib.h>
|
|
|
|
//
|
|
// CHANGE: Apple polls with a frequency of 2 ms, however this is infeasible on
|
|
// most machines. Poll with 10 ms, which matches the keyboard behaviour,
|
|
// and also is the minimum for QEMU.
|
|
//
|
|
#define MIN_POINTER_POLL_PERIOD 10
|
|
#define MAX_POINTER_POLL_PERIOD 80
|
|
|
|
#define MAX_CLICK_DURATION 148 // 74 for 2 ms
|
|
#define MAX_DOUBLE_CLICK_SPEED 748 // 374 for 2 ms
|
|
|
|
#define MAX_POLL_DURATION ((MAX_UINT32 / 10000) / MAX_DOUBLE_CLICK_SPEED)
|
|
|
|
GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mPointerSpeedDiv = 0;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mPointerSpeedMul = 0;
|
|
|
|
STATIC UINT16 mMaximumDoubleClickSpeed = 0;
|
|
STATIC UINT16 mMaximumClickDuration = 0;
|
|
|
|
// MINIMAL_MOVEMENT
|
|
#define MINIMAL_MOVEMENT 5
|
|
|
|
// POINTER_BUTTON_INFORMATION
|
|
typedef struct {
|
|
APPLE_EVENT_TYPE EventType;
|
|
UINTN ButtonTicksHold;
|
|
UINTN ButtonTicksSinceClick;
|
|
UINTN PreviousClickEventType;
|
|
BOOLEAN PreviousButton;
|
|
BOOLEAN CurrentButton;
|
|
DIMENSION MouseDownPosition;
|
|
DIMENSION ClickPosition;
|
|
} POINTER_BUTTON_INFORMATION;
|
|
|
|
// SIMPLE_POINTER_INSTANCE
|
|
typedef struct {
|
|
EFI_HANDLE Handle; ///<
|
|
EFI_SIMPLE_POINTER_PROTOCOL *Interface; ///<
|
|
BOOLEAN Installed; ///<
|
|
} SIMPLE_POINTER_INSTANCE;
|
|
|
|
// mSimplePointerInstallNotifyEvent
|
|
STATIC EFI_EVENT mSimplePointerInstallNotifyEvent = NULL;
|
|
|
|
// mSimplePointerInstallNotifyRegistration
|
|
STATIC VOID *mSimplePointerInstallNotifyRegistration = NULL;
|
|
|
|
// mSimplePointerInstances
|
|
STATIC SIMPLE_POINTER_INSTANCE *mPointerProtocols = NULL;
|
|
|
|
// mNoSimplePointerInstances
|
|
STATIC UINTN mNumberOfPointerProtocols = 0;
|
|
|
|
// mSimplePointerPollEvent
|
|
STATIC EFI_EVENT mSimplePointerPollEvent = NULL;
|
|
|
|
// mSimplePointerPollTime
|
|
STATIC UINT32 mSimplePointerPollTime = 0;
|
|
STATIC UINT32 mSimplePointerMinPollTime = 0;
|
|
STATIC UINT32 mSimplePointerMaxPollTime = 0;
|
|
|
|
STATIC UINT32 mSimplePointerPollMask = POINTER_POLL_ALL_MASK;
|
|
|
|
// mUiScale
|
|
STATIC UINT8 mUiScale = 1;
|
|
|
|
// mLeftButtonInfo
|
|
STATIC POINTER_BUTTON_INFORMATION mLeftButtonInfo = {
|
|
APPLE_EVENT_TYPE_LEFT_BUTTON,
|
|
0,
|
|
0,
|
|
0,
|
|
FALSE,
|
|
FALSE,
|
|
{ 0, 0 },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
// mRightButtonInfo
|
|
STATIC POINTER_BUTTON_INFORMATION mRightButtonInfo = {
|
|
APPLE_EVENT_TYPE_RIGHT_BUTTON,
|
|
0,
|
|
0,
|
|
0,
|
|
FALSE,
|
|
FALSE,
|
|
{ 0, 0 },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
// mCursorPosition
|
|
STATIC DIMENSION mCursorPosition;
|
|
|
|
// mMouseMoved
|
|
STATIC BOOLEAN mMouseMoved;
|
|
|
|
// mScreenResolution
|
|
STATIC DIMENSION mResolution = { 800, 600 };
|
|
|
|
STATIC UINT64 mMaxPointerResolutionX = 1;
|
|
STATIC UINT64 mMaxPointerResolutionY = 1;
|
|
|
|
STATIC UINT64 mPointerRawX;
|
|
STATIC UINT64 mPointerRawY;
|
|
|
|
STATIC UINT32 mDwellClickTimeout;
|
|
STATIC UINT32 mDwellDoubleClickTimeout;
|
|
STATIC UINT32 mDwellClickRadiusSqr;
|
|
STATIC DIMENSION mDwellPosition;
|
|
STATIC UINT32 mDwellClickTime;
|
|
|
|
VOID
|
|
InternalInitializePointerUiScale (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN DataSize;
|
|
|
|
DataSize = sizeof (mUiScale);
|
|
Status = gRT->GetVariable (
|
|
APPLE_UI_SCALE_VARIABLE_NAME,
|
|
&gAppleVendorVariableGuid,
|
|
NULL,
|
|
&DataSize,
|
|
(VOID *)&mUiScale
|
|
);
|
|
if (EFI_ERROR (Status) || (mUiScale != 2)) {
|
|
mUiScale = 1;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
InternalSetPointerPolling (
|
|
IN UINT32 PointerPollMin,
|
|
IN UINT32 PointerPollMax,
|
|
IN UINT32 PointerPollMask
|
|
)
|
|
{
|
|
if (PointerPollMin == POINTER_POLL_DEFAULT) {
|
|
PointerPollMin = MIN_POINTER_POLL_PERIOD;
|
|
} else if (PointerPollMin > MAX_POLL_DURATION) {
|
|
PointerPollMin = MAX_POLL_DURATION;
|
|
}
|
|
|
|
mSimplePointerMinPollTime = PointerPollMin * 10000;
|
|
|
|
mMaximumClickDuration = (UINT16)(MAX_CLICK_DURATION / PointerPollMin);
|
|
mMaximumDoubleClickSpeed = (UINT16)(MAX_DOUBLE_CLICK_SPEED / PointerPollMin);
|
|
|
|
if (PointerPollMax == POINTER_POLL_DEFAULT) {
|
|
PointerPollMax = MAX_POINTER_POLL_PERIOD;
|
|
} else if (PointerPollMax > MAX_POLL_DURATION) {
|
|
PointerPollMax = MAX_POLL_DURATION;
|
|
}
|
|
|
|
mSimplePointerMaxPollTime = PointerPollMax * 10000;
|
|
|
|
mSimplePointerPollMask = PointerPollMask;
|
|
}
|
|
|
|
VOID
|
|
InternalSetPointerSpeed (
|
|
IN UINT16 PointerSpeedDiv,
|
|
IN UINT16 PointerSpeedMul
|
|
)
|
|
{
|
|
if (PointerSpeedDiv != 0) {
|
|
mPointerSpeedDiv = PointerSpeedDiv;
|
|
} else {
|
|
DEBUG ((
|
|
DEBUG_WARN,
|
|
"OCAE: Illegal PointerSpeedDiv value 0, using 1\n",
|
|
mPointerSpeedDiv
|
|
));
|
|
mPointerSpeedDiv = 1;
|
|
}
|
|
|
|
mPointerSpeedMul = PointerSpeedMul;
|
|
}
|
|
|
|
VOID
|
|
InternalSetDwellClicking (
|
|
IN UINT16 ClickTimeout,
|
|
IN UINT16 DoubleClickTimeout,
|
|
IN UINT16 Radius
|
|
)
|
|
{
|
|
mDwellClickTimeout = (UINT32)ClickTimeout * 10000;
|
|
mDwellDoubleClickTimeout = (UINT32)DoubleClickTimeout * 10000;
|
|
mDwellClickRadiusSqr = ((UINT32)Radius * Radius) * (mUiScale * mUiScale);
|
|
}
|
|
|
|
// InternalRegisterSimplePointerInterface
|
|
STATIC
|
|
VOID
|
|
InternalRegisterSimplePointerInterface (
|
|
IN EFI_HANDLE Handle,
|
|
IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer
|
|
)
|
|
{
|
|
SIMPLE_POINTER_INSTANCE *Instance;
|
|
UINTN Index;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalRegisterSimplePointerInterface\n"));
|
|
|
|
Instance = AllocateZeroPool (
|
|
(mNumberOfPointerProtocols + 1) * sizeof (*Instance)
|
|
);
|
|
|
|
if (Instance != NULL) {
|
|
//
|
|
// Apple did not check against NULL here and below as of boot.efi
|
|
//
|
|
if (mPointerProtocols != NULL) {
|
|
CopyMem (
|
|
Instance,
|
|
mPointerProtocols,
|
|
(mNumberOfPointerProtocols * sizeof (*Instance))
|
|
);
|
|
}
|
|
|
|
Index = mNumberOfPointerProtocols;
|
|
|
|
++mNumberOfPointerProtocols;
|
|
|
|
Instance[Index].Handle = Handle;
|
|
Instance[Index].Interface = SimplePointer;
|
|
Instance[Index].Installed = TRUE;
|
|
|
|
if (mPointerProtocols != NULL) {
|
|
FreePool ((VOID *)mPointerProtocols);
|
|
}
|
|
|
|
mPointerProtocols = Instance;
|
|
|
|
if (SimplePointer->Mode->ResolutionX > mMaxPointerResolutionX) {
|
|
mPointerRawX = MultU64x64 (mPointerRawX, mMaxPointerResolutionX);
|
|
mPointerRawX = DivU64x64Remainder (
|
|
mPointerRawX,
|
|
SimplePointer->Mode->ResolutionX,
|
|
NULL
|
|
);
|
|
mMaxPointerResolutionX = SimplePointer->Mode->ResolutionX;
|
|
}
|
|
|
|
if (SimplePointer->Mode->ResolutionY > mMaxPointerResolutionY) {
|
|
mPointerRawY = MultU64x64 (mPointerRawY, mMaxPointerResolutionY);
|
|
mPointerRawY = DivU64x64Remainder (
|
|
mPointerRawY,
|
|
SimplePointer->Mode->ResolutionY,
|
|
NULL
|
|
);
|
|
mMaxPointerResolutionY = SimplePointer->Mode->ResolutionY;
|
|
}
|
|
}
|
|
}
|
|
|
|
// EventSimplePointerDesctructor
|
|
VOID
|
|
EventSimplePointerDesctructor (
|
|
VOID
|
|
)
|
|
{
|
|
DEBUG ((DEBUG_VERBOSE, "EventSimplePointerDesctructor\n"));
|
|
|
|
if (mPointerProtocols != NULL) {
|
|
FreePool ((VOID *)mPointerProtocols);
|
|
//
|
|
// Apple did not null the pointer here (not an error)
|
|
//
|
|
mPointerProtocols = NULL;
|
|
}
|
|
}
|
|
|
|
// InternalRemoveUninstalledInstances
|
|
STATIC
|
|
VOID
|
|
InternalRemoveUninstalledInstances (
|
|
IN OUT SIMPLE_POINTER_INSTANCE **InstancesPtr,
|
|
IN UINTN *NumberOfInstances,
|
|
IN EFI_GUID *Protocol
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN NumberHandles;
|
|
EFI_HANDLE *Buffer;
|
|
SIMPLE_POINTER_INSTANCE *Instance;
|
|
UINTN Index;
|
|
UINTN Index2;
|
|
SIMPLE_POINTER_INSTANCE *OrgInstances;
|
|
SIMPLE_POINTER_INSTANCE *NewInstances;
|
|
UINTN NumberOfMatches;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalRemoveUninstalledInstances\n"));
|
|
|
|
OrgInstances = *InstancesPtr;
|
|
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
Protocol,
|
|
NULL,
|
|
&NumberHandles,
|
|
&Buffer
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
if (*NumberOfInstances > 0) {
|
|
NumberOfMatches = 0;
|
|
|
|
for (Index = 0; Index < *NumberOfInstances; ++Index) {
|
|
Instance = &OrgInstances[Index];
|
|
|
|
if (Instance->Installed) {
|
|
for (Index2 = 0; Index2 < NumberHandles; ++Index2) {
|
|
if (Instance->Handle == Buffer[Index2]) {
|
|
++NumberOfMatches;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (NumberHandles == Index2) {
|
|
Instance->Installed = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NumberOfMatches != *NumberOfInstances) {
|
|
//
|
|
// Apple did not check for NumberOfMatches being > 0.
|
|
//
|
|
NewInstances = NULL;
|
|
if (NumberOfMatches > 0) {
|
|
NewInstances = AllocateZeroPool (
|
|
NumberOfMatches * sizeof (*NewInstances)
|
|
);
|
|
}
|
|
|
|
if (NewInstances != NULL) {
|
|
Index2 = 0;
|
|
for (Index = 0; Index < *NumberOfInstances; ++Index) {
|
|
Instance = &OrgInstances[Index];
|
|
if (Instance->Installed) {
|
|
CopyMem (
|
|
(VOID *)&NewInstances[Index2],
|
|
(VOID *)Instance,
|
|
sizeof (*Instance)
|
|
);
|
|
|
|
++Index2;
|
|
}
|
|
}
|
|
|
|
FreePool (OrgInstances);
|
|
|
|
*InstancesPtr = NewInstances;
|
|
*NumberOfInstances = NumberOfMatches;
|
|
}
|
|
}
|
|
}
|
|
|
|
FreePool (Buffer);
|
|
} else {
|
|
if (OrgInstances != NULL) {
|
|
FreePool (OrgInstances);
|
|
}
|
|
|
|
*InstancesPtr = NULL;
|
|
*NumberOfInstances = 0;
|
|
}
|
|
}
|
|
|
|
// InternalSimplePointerInstallNotifyFunction
|
|
STATIC
|
|
VOID
|
|
EFIAPI
|
|
InternalSimplePointerInstallNotifyFunction (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN NumberHandles;
|
|
EFI_HANDLE *Buffer;
|
|
UINTN Index;
|
|
EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalSimplePointerInstallNotifyFunction\n"));
|
|
|
|
if (Event != NULL) {
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByRegisterNotify,
|
|
NULL,
|
|
mSimplePointerInstallNotifyRegistration,
|
|
&NumberHandles,
|
|
&Buffer
|
|
);
|
|
} else {
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiSimplePointerProtocolGuid,
|
|
NULL,
|
|
&NumberHandles,
|
|
&Buffer
|
|
);
|
|
}
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
for (Index = 0; Index < NumberHandles; ++Index) {
|
|
Status = gBS->HandleProtocol (
|
|
Buffer[Index],
|
|
&gEfiSimplePointerProtocolGuid,
|
|
(VOID **)&SimplePointer
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
InternalRegisterSimplePointerInterface (Buffer[Index], SimplePointer);
|
|
}
|
|
}
|
|
|
|
FreePool ((VOID *)Buffer);
|
|
}
|
|
}
|
|
|
|
// EventCreateSimplePointerInstallNotifyEvent
|
|
EFI_STATUS
|
|
EventCreateSimplePointerInstallNotifyEvent (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "EventCreateSimplePointerInstallNotifyEvent\n"));
|
|
|
|
Status = gBS->CreateEvent (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_CALLBACK,
|
|
InternalSimplePointerInstallNotifyFunction,
|
|
NULL,
|
|
&mSimplePointerInstallNotifyEvent
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = gBS->RegisterProtocolNotify (
|
|
&gEfiSimplePointerProtocolGuid,
|
|
mSimplePointerInstallNotifyEvent,
|
|
&mSimplePointerInstallNotifyRegistration
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
gBS->CloseEvent (mSimplePointerInstallNotifyEvent);
|
|
|
|
mSimplePointerInstallNotifyEvent = NULL;
|
|
} else {
|
|
InternalSimplePointerInstallNotifyFunction (NULL, NULL);
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
// EventCreateSimplePointerInstallNotifyEvent
|
|
VOID
|
|
EventCloseSimplePointerInstallNotifyEvent (
|
|
VOID
|
|
)
|
|
{
|
|
DEBUG ((DEBUG_VERBOSE, "EventCloseSimplePointerInstallNotifyEvent\n"));
|
|
|
|
if (mSimplePointerInstallNotifyEvent != NULL) {
|
|
gBS->CloseEvent (mSimplePointerInstallNotifyEvent);
|
|
}
|
|
}
|
|
|
|
// InternalGetScreenResolution
|
|
STATIC
|
|
VOID
|
|
InternalGetScreenResolution (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
|
|
EFI_UGA_DRAW_PROTOCOL *UgaDraw;
|
|
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
|
|
UINT32 HorizontalResolution;
|
|
UINT32 VerticalResolution;
|
|
UINT32 ColorDepth;
|
|
UINT32 RefreshRate;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalGetScreenResolution\n"));
|
|
|
|
//
|
|
// CHANGE: Do not cache screen resolution to account for changes.
|
|
//
|
|
|
|
HorizontalResolution = 0;
|
|
VerticalResolution = 0;
|
|
|
|
Status = gBS->HandleProtocol (
|
|
gST->ConsoleOutHandle,
|
|
&gEfiGraphicsOutputProtocolGuid,
|
|
(VOID **)&GraphicsOutput
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Info = GraphicsOutput->Mode->Info;
|
|
HorizontalResolution = Info->HorizontalResolution;
|
|
VerticalResolution = Info->VerticalResolution;
|
|
} else if (Status == EFI_UNSUPPORTED) {
|
|
Status = gBS->HandleProtocol (
|
|
gST->ConsoleOutHandle,
|
|
&gEfiUgaDrawProtocolGuid,
|
|
(VOID **)&UgaDraw
|
|
);
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"OCAE: Failed to handle GOP, discovering UGA - %r\n",
|
|
Status
|
|
));
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = UgaDraw->GetMode (
|
|
UgaDraw,
|
|
&HorizontalResolution,
|
|
&VerticalResolution,
|
|
&ColorDepth,
|
|
&RefreshRate
|
|
);
|
|
}
|
|
}
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
if ((HorizontalResolution > 0) && (VerticalResolution > 0)) {
|
|
mResolution.Horizontal = (INT32)HorizontalResolution;
|
|
mResolution.Vertical = (INT32)VerticalResolution;
|
|
|
|
if (mCursorPosition.Horizontal >= mResolution.Horizontal) {
|
|
mCursorPosition.Horizontal = mResolution.Horizontal - 1;
|
|
}
|
|
|
|
if (mCursorPosition.Vertical >= mResolution.Vertical) {
|
|
mCursorPosition.Vertical = mResolution.Vertical - 1;
|
|
}
|
|
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"OCAE: Set screen resolution to %dx%d - %r\n",
|
|
mResolution.Horizontal,
|
|
mResolution.Vertical,
|
|
Status
|
|
));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "OCAE: Screen resolution has 0-dimension\n"));
|
|
}
|
|
} else {
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"OCAE: Failed to get screen resolution - %r\n",
|
|
Status
|
|
));
|
|
}
|
|
}
|
|
|
|
// InternalGetUiScaleData
|
|
STATIC
|
|
INT64
|
|
InternalGetUiScaleData (
|
|
IN INT64 Movement
|
|
)
|
|
{
|
|
INT64 AbsoluteValue;
|
|
INTN Value;
|
|
INT64 Factor;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalGetUiScaleData\n"));
|
|
|
|
AbsoluteValue = ABS (Movement);
|
|
Value = HighBitSet64 ((UINT64)(AbsoluteValue));
|
|
Factor = 5;
|
|
|
|
if (Value <= 3) {
|
|
Factor = (HighBitSet64 ((UINT64)(AbsoluteValue) + 1));
|
|
}
|
|
|
|
return (INT64)(MultS64x64 (
|
|
(INT64)(INT32)mUiScale,
|
|
MultS64x64 (Movement, Factor)
|
|
));
|
|
}
|
|
|
|
// InternalCreatePointerEventQueueInformation
|
|
STATIC
|
|
APPLE_EVENT_INFORMATION *
|
|
InternalCreatePointerEventQueueInformation (
|
|
IN APPLE_EVENT_TYPE EventType,
|
|
IN APPLE_MODIFIER_MAP Modifiers
|
|
)
|
|
{
|
|
UINT32 FinalEventType;
|
|
APPLE_EVENT_DATA EventData;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalCreatePointerEventQueueInformation\n"));
|
|
|
|
FinalEventType = APPLE_EVENT_TYPE_MOUSE_MOVED;
|
|
|
|
if ((EventType & APPLE_EVENT_TYPE_MOUSE_MOVED) == 0) {
|
|
FinalEventType = APPLE_ALL_MOUSE_EVENTS;
|
|
|
|
if ((EventType & APPLE_CLICK_MOUSE_EVENTS) != 0) {
|
|
FinalEventType = APPLE_CLICK_MOUSE_EVENTS;
|
|
}
|
|
}
|
|
|
|
EventData.PointerEventType = EventType;
|
|
|
|
return EventCreateAppleEventQueueInfo (
|
|
EventData,
|
|
FinalEventType,
|
|
&mCursorPosition,
|
|
Modifiers
|
|
);
|
|
}
|
|
|
|
// InternalHandleButtonInteraction
|
|
STATIC
|
|
VOID
|
|
InternalHandleButtonInteraction (
|
|
IN EFI_STATUS PointerStatus,
|
|
IN OUT POINTER_BUTTON_INFORMATION *Pointer,
|
|
IN APPLE_MODIFIER_MAP Modifiers
|
|
)
|
|
{
|
|
APPLE_EVENT_INFORMATION *Information;
|
|
INT32 HorizontalMovement;
|
|
INT32 VerticalMovement;
|
|
APPLE_EVENT_TYPE EventType;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalHandleButtonInteraction\n"));
|
|
|
|
if (!EFI_ERROR (PointerStatus)) {
|
|
if (!Pointer->PreviousButton) {
|
|
if (Pointer->CurrentButton) {
|
|
Pointer->ButtonTicksHold = 0;
|
|
Pointer->MouseDownPosition = mCursorPosition;
|
|
|
|
Information = InternalCreatePointerEventQueueInformation (
|
|
(Pointer->EventType | APPLE_EVENT_TYPE_MOUSE_DOWN),
|
|
Modifiers
|
|
);
|
|
|
|
if (Information != NULL) {
|
|
EventAddEventToQueue (Information);
|
|
}
|
|
}
|
|
} else if (!Pointer->CurrentButton) {
|
|
Information = InternalCreatePointerEventQueueInformation (
|
|
(Pointer->EventType | APPLE_EVENT_TYPE_MOUSE_UP),
|
|
Modifiers
|
|
);
|
|
|
|
if (Information != NULL) {
|
|
EventAddEventToQueue (Information);
|
|
}
|
|
|
|
if (Pointer->ButtonTicksHold <= mMaximumClickDuration) {
|
|
HorizontalMovement = ABS (Pointer->MouseDownPosition.Horizontal - mCursorPosition.Horizontal);
|
|
VerticalMovement = ABS (Pointer->MouseDownPosition.Vertical - mCursorPosition.Vertical);
|
|
//
|
|
// CHANGE: Apple did not scale by UIScale.
|
|
//
|
|
if ( (HorizontalMovement <= mUiScale * MINIMAL_MOVEMENT)
|
|
&& (VerticalMovement <= mUiScale * MINIMAL_MOVEMENT))
|
|
{
|
|
EventType = APPLE_EVENT_TYPE_MOUSE_CLICK;
|
|
|
|
if ( (Pointer->PreviousClickEventType == APPLE_EVENT_TYPE_MOUSE_CLICK)
|
|
&& (Pointer->ButtonTicksSinceClick <= mMaximumDoubleClickSpeed))
|
|
{
|
|
HorizontalMovement = ABS (Pointer->ClickPosition.Horizontal - mCursorPosition.Horizontal);
|
|
VerticalMovement = ABS (Pointer->ClickPosition.Vertical - mCursorPosition.Vertical);
|
|
|
|
if ( (HorizontalMovement <= mUiScale * MINIMAL_MOVEMENT)
|
|
&& (VerticalMovement <= mUiScale * MINIMAL_MOVEMENT))
|
|
{
|
|
EventType = APPLE_EVENT_TYPE_MOUSE_DOUBLE_CLICK;
|
|
}
|
|
}
|
|
|
|
Information = InternalCreatePointerEventQueueInformation (
|
|
(Pointer->EventType | EventType),
|
|
Modifiers
|
|
);
|
|
|
|
if (Information != NULL) {
|
|
EventAddEventToQueue (Information);
|
|
}
|
|
|
|
if (Pointer->PreviousClickEventType == APPLE_EVENT_TYPE_MOUSE_DOUBLE_CLICK) {
|
|
EventType = ((Pointer->ButtonTicksSinceClick <= mMaximumDoubleClickSpeed)
|
|
? APPLE_EVENT_TYPE_MOUSE_DOUBLE_CLICK
|
|
: APPLE_EVENT_TYPE_MOUSE_CLICK);
|
|
}
|
|
|
|
Pointer->PreviousClickEventType = EventType;
|
|
Pointer->ClickPosition = mCursorPosition;
|
|
Pointer->ButtonTicksSinceClick = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
Pointer->PreviousButton = Pointer->CurrentButton;
|
|
}
|
|
|
|
if (Pointer->PreviousButton && Pointer->CurrentButton) {
|
|
++Pointer->ButtonTicksHold;
|
|
}
|
|
|
|
++Pointer->ButtonTicksSinceClick;
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
InternalResetDwellClicking (
|
|
VOID
|
|
)
|
|
{
|
|
mDwellClickTime = 0;
|
|
CopyMem (
|
|
&mDwellPosition,
|
|
&mCursorPosition,
|
|
sizeof (mDwellPosition)
|
|
);
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
InternalQueueDwellClick (
|
|
IN APPLE_EVENT_TYPE EventType,
|
|
IN APPLE_MODIFIER_MAP Modifiers
|
|
)
|
|
{
|
|
APPLE_EVENT_INFORMATION *Information;
|
|
|
|
Information = InternalCreatePointerEventQueueInformation (
|
|
APPLE_EVENT_TYPE_LEFT_BUTTON | APPLE_EVENT_TYPE_MOUSE_DOWN,
|
|
Modifiers
|
|
);
|
|
if (Information != NULL) {
|
|
EventAddEventToQueue (Information);
|
|
}
|
|
|
|
Information = InternalCreatePointerEventQueueInformation (
|
|
APPLE_EVENT_TYPE_LEFT_BUTTON | APPLE_EVENT_TYPE_MOUSE_UP,
|
|
Modifiers
|
|
);
|
|
if (Information != NULL) {
|
|
EventAddEventToQueue (Information);
|
|
}
|
|
|
|
Information = InternalCreatePointerEventQueueInformation (
|
|
APPLE_EVENT_TYPE_LEFT_BUTTON | EventType,
|
|
Modifiers
|
|
);
|
|
if (Information != NULL) {
|
|
EventAddEventToQueue (Information);
|
|
}
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
InternalHandleDwellClicking (
|
|
IN APPLE_MODIFIER_MAP Modifiers
|
|
)
|
|
{
|
|
BOOLEAN ClickDisabled;
|
|
BOOLEAN DoubleClickDisabled;
|
|
INT32 DistX;
|
|
INT32 DistY;
|
|
|
|
ClickDisabled = mDwellClickTimeout == 0;
|
|
DoubleClickDisabled = mDwellDoubleClickTimeout == 0;
|
|
if (ClickDisabled && DoubleClickDisabled) {
|
|
return;
|
|
}
|
|
|
|
DistX = mCursorPosition.Horizontal - mDwellPosition.Horizontal;
|
|
DistY = mCursorPosition.Vertical - mDwellPosition.Vertical;
|
|
if ((UINT32)(DistX * DistX + DistY * DistY) <= mDwellClickRadiusSqr) {
|
|
mDwellClickTime += mSimplePointerPollTime;
|
|
|
|
if (!DoubleClickDisabled && (mDwellClickTime >= mDwellDoubleClickTimeout)) {
|
|
InternalQueueDwellClick (APPLE_EVENT_TYPE_MOUSE_DOUBLE_CLICK, Modifiers);
|
|
InternalResetDwellClicking ();
|
|
} else if (!ClickDisabled && (mDwellClickTime >= mDwellClickTimeout)) {
|
|
InternalQueueDwellClick (APPLE_EVENT_TYPE_MOUSE_CLICK, Modifiers);
|
|
if (DoubleClickDisabled) {
|
|
InternalResetDwellClicking ();
|
|
}
|
|
}
|
|
} else {
|
|
InternalResetDwellClicking ();
|
|
}
|
|
}
|
|
|
|
// InternalSimplePointerPollNotifyFunction
|
|
STATIC
|
|
VOID
|
|
EFIAPI
|
|
InternalSimplePointerPollNotifyFunction (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
APPLE_MODIFIER_MAP Modifiers;
|
|
UINTN Index;
|
|
SIMPLE_POINTER_INSTANCE *Instance;
|
|
EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;
|
|
EFI_STATUS Status;
|
|
EFI_STATUS CommonStatus;
|
|
EFI_SIMPLE_POINTER_STATE State;
|
|
INT64 UiScaleX;
|
|
INT64 UiScaleY;
|
|
INT64 ScaledY;
|
|
INT64 ScaledX;
|
|
DIMENSION NewPosition;
|
|
APPLE_EVENT_INFORMATION *Information;
|
|
APPLE_EVENT_DATA EventData;
|
|
UINT64 StartTime;
|
|
UINT64 EndTime;
|
|
INT64 MaxRawPointerX;
|
|
INT64 MaxRawPointerY;
|
|
UINT32 ClickTemp;
|
|
UINT32 DoubleClickTemp;
|
|
UINT64 SimplePointerPollTime;
|
|
|
|
StartTime = GetPerformanceCounter ();
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalSimplePointerPollNotifyFunction\n"));
|
|
|
|
Modifiers = InternalGetModifierStrokes ();
|
|
|
|
InternalRemoveUninstalledInstances (
|
|
&mPointerProtocols,
|
|
&mNumberOfPointerProtocols,
|
|
&gEfiSimplePointerProtocolGuid
|
|
);
|
|
|
|
CommonStatus = EFI_UNSUPPORTED;
|
|
|
|
if (mNumberOfPointerProtocols > 0) {
|
|
CommonStatus = EFI_NOT_READY;
|
|
|
|
for (Index = 0; Index < mNumberOfPointerProtocols; ++Index) {
|
|
if ( (mSimplePointerPollMask != POINTER_POLL_ALL_MASK)
|
|
&& ((Index >= 32) || (((1U << Index) & mSimplePointerPollMask) == 0)))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Instance = &mPointerProtocols[Index];
|
|
SimplePointer = Instance->Interface;
|
|
Status = SimplePointer->GetState (SimplePointer, &State);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
//
|
|
// CHANGE: Apple scaled the deltas and due to rounding errors, this is
|
|
// unacceptable. Changed to scale all pointer deltas to the
|
|
// maximum pointer resolution and scaling down to display
|
|
// coordinates always based on the accurate raw input value.
|
|
//
|
|
|
|
UiScaleX = InternalGetUiScaleData ((INT64)State.RelativeMovementX);
|
|
UiScaleX = MultS64x64 (UiScaleX, (INT64)mMaxPointerResolutionX);
|
|
UiScaleX = MultS64x64 (UiScaleX, mPointerSpeedMul);
|
|
UiScaleX = DivS64x64Remainder (UiScaleX, mPointerSpeedDiv, NULL);
|
|
|
|
UiScaleY = InternalGetUiScaleData ((INT64)State.RelativeMovementY);
|
|
UiScaleY = MultS64x64 (UiScaleY, (INT64)mMaxPointerResolutionY);
|
|
UiScaleY = MultS64x64 (UiScaleY, mPointerSpeedMul);
|
|
UiScaleY = DivS64x64Remainder (UiScaleY, mPointerSpeedDiv, NULL);
|
|
|
|
if (SimplePointer->Mode->ResolutionX > 0) {
|
|
UiScaleX = DivS64x64Remainder (
|
|
UiScaleX,
|
|
(INT64)SimplePointer->Mode->ResolutionX,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
if (SimplePointer->Mode->ResolutionY > 0) {
|
|
UiScaleY = DivS64x64Remainder (
|
|
UiScaleY,
|
|
(INT64)SimplePointer->Mode->ResolutionY,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
//
|
|
// CHANGE: Fix maximum coordinates.
|
|
//
|
|
ScaledX = mPointerRawX + UiScaleX;
|
|
MaxRawPointerX = MultU64x64 (
|
|
mResolution.Horizontal - 1,
|
|
mMaxPointerResolutionX
|
|
);
|
|
if (ScaledX > MaxRawPointerX) {
|
|
ScaledX = MaxRawPointerX;
|
|
} else if (ScaledX < 0) {
|
|
ScaledX = 0;
|
|
}
|
|
|
|
mPointerRawX = (UINT64)ScaledX;
|
|
|
|
ScaledY = mPointerRawY + UiScaleY;
|
|
MaxRawPointerY = MultS64x64 (
|
|
mResolution.Vertical - 1,
|
|
(INT64)mMaxPointerResolutionY
|
|
);
|
|
if (ScaledY > MaxRawPointerY) {
|
|
ScaledY = MaxRawPointerY;
|
|
} else if (ScaledY < 0) {
|
|
ScaledY = 0;
|
|
}
|
|
|
|
mPointerRawY = (UINT64)ScaledY;
|
|
|
|
ScaledX = DivU64x64Remainder (
|
|
ScaledX,
|
|
mMaxPointerResolutionX,
|
|
NULL
|
|
);
|
|
|
|
ScaledY = DivS64x64Remainder (
|
|
ScaledY,
|
|
(INT64)mMaxPointerResolutionY,
|
|
NULL
|
|
);
|
|
|
|
NewPosition.Horizontal = (INT32)ScaledX;
|
|
NewPosition.Vertical = (INT32)ScaledY;
|
|
|
|
if ( (mCursorPosition.Horizontal != NewPosition.Horizontal)
|
|
|| (mCursorPosition.Vertical != NewPosition.Vertical))
|
|
{
|
|
CopyMem (
|
|
&mCursorPosition,
|
|
&NewPosition,
|
|
sizeof (mCursorPosition)
|
|
);
|
|
|
|
mMouseMoved = TRUE;
|
|
}
|
|
|
|
mLeftButtonInfo.PreviousButton = mLeftButtonInfo.CurrentButton;
|
|
mLeftButtonInfo.CurrentButton = State.LeftButton;
|
|
mRightButtonInfo.PreviousButton = mRightButtonInfo.CurrentButton;
|
|
mRightButtonInfo.CurrentButton = State.RightButton;
|
|
CommonStatus = Status;
|
|
}
|
|
}
|
|
|
|
InternalHandleButtonInteraction (CommonStatus, &mLeftButtonInfo, Modifiers);
|
|
InternalHandleButtonInteraction (CommonStatus, &mRightButtonInfo, Modifiers);
|
|
|
|
InternalHandleDwellClicking (Modifiers);
|
|
}
|
|
|
|
if (EFI_ERROR (CommonStatus)) {
|
|
if (CommonStatus == EFI_UNSUPPORTED) {
|
|
EventLibCancelEvent (mSimplePointerPollEvent);
|
|
|
|
mSimplePointerPollEvent = NULL;
|
|
}
|
|
} else if (mMouseMoved != FALSE) {
|
|
mMouseMoved = FALSE;
|
|
|
|
EventData.PointerEventType = APPLE_EVENT_TYPE_MOUSE_MOVED;
|
|
Information = EventCreateAppleEventQueueInfo (
|
|
EventData,
|
|
APPLE_EVENT_TYPE_MOUSE_MOVED,
|
|
&mCursorPosition,
|
|
Modifiers
|
|
);
|
|
|
|
if (Information != NULL) {
|
|
EventAddEventToQueue (Information);
|
|
}
|
|
}
|
|
|
|
//
|
|
// This code is here to workaround very slow mouse polling performance on some computers,
|
|
// like most of Dell laptops (one of the worst examples is Dell Latitude 3330 with ~50 ms).
|
|
// Even if we try all the hacks we could make this code approximately only twice faster,
|
|
// which is still far from enough. The event system on these laptops is pretty broken,
|
|
// and even adding gBS->CheckEvent prior to GetState almost does not reduce the time spent.
|
|
//
|
|
if ((mSimplePointerPollEvent != NULL) && (mSimplePointerPollTime < mSimplePointerMaxPollTime)) {
|
|
EndTime = GetPerformanceCounter ();
|
|
if (StartTime > EndTime) {
|
|
EndTime = StartTime;
|
|
}
|
|
|
|
EndTime = GetTimeInNanoSecond (EndTime - StartTime);
|
|
// Maximum time allowed in this function is half the interval plus some margin (0.55 * 100ns)
|
|
if (EndTime > mSimplePointerPollTime * 55) {
|
|
ClickTemp = mSimplePointerPollTime * mMaximumClickDuration;
|
|
DoubleClickTemp = mSimplePointerPollTime * mMaximumDoubleClickSpeed;
|
|
|
|
SimplePointerPollTime = DivU64x32 (EndTime, 50);
|
|
if (SimplePointerPollTime <= mSimplePointerMaxPollTime) {
|
|
mSimplePointerPollTime = (UINT32)SimplePointerPollTime;
|
|
} else {
|
|
mSimplePointerPollTime = mSimplePointerMaxPollTime;
|
|
}
|
|
|
|
mMaximumClickDuration = (UINT16)(ClickTemp / mSimplePointerPollTime);
|
|
mMaximumDoubleClickSpeed = (UINT16)(DoubleClickTemp / mSimplePointerPollTime);
|
|
|
|
gBS->SetTimer (mSimplePointerPollEvent, TimerPeriodic, mSimplePointerPollTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
// EventCreateSimplePointerPollEvent
|
|
EFI_STATUS
|
|
EventCreateSimplePointerPollEvent (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "EventCreateSimplePointerPollEvent\n"));
|
|
|
|
InternalRemoveUninstalledInstances (
|
|
&mPointerProtocols,
|
|
&mNumberOfPointerProtocols,
|
|
&gEfiSimplePointerProtocolGuid
|
|
);
|
|
|
|
for (Index = 0; Index < mNumberOfPointerProtocols; ++Index) {
|
|
mPointerProtocols[Index].Interface->Reset (
|
|
mPointerProtocols[Index].Interface,
|
|
FALSE
|
|
);
|
|
}
|
|
|
|
InternalGetScreenResolution ();
|
|
ZeroMem (&mCursorPosition, sizeof (mCursorPosition));
|
|
|
|
mSimplePointerPollTime = mSimplePointerMinPollTime;
|
|
mSimplePointerPollEvent = EventLibCreateNotifyTimerEvent (
|
|
InternalSimplePointerPollNotifyFunction,
|
|
NULL,
|
|
mSimplePointerPollTime,
|
|
TRUE
|
|
);
|
|
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
|
|
if (mSimplePointerPollEvent != NULL) {
|
|
mRightButtonInfo.CurrentButton = FALSE;
|
|
mLeftButtonInfo.CurrentButton = FALSE;
|
|
mRightButtonInfo.PreviousButton = FALSE;
|
|
mLeftButtonInfo.PreviousButton = FALSE;
|
|
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
// EventCancelSimplePointerPollEvent
|
|
VOID
|
|
EventCancelSimplePointerPollEvent (
|
|
VOID
|
|
)
|
|
{
|
|
DEBUG ((DEBUG_VERBOSE, "EventCancelSimplePointerPollEvent\n"));
|
|
|
|
EventLibCancelEvent (mSimplePointerPollEvent);
|
|
|
|
mSimplePointerPollEvent = NULL;
|
|
}
|
|
|
|
// EventSetCursorPositionImpl
|
|
EFI_STATUS
|
|
EventSetCursorPositionImpl (
|
|
IN DIMENSION *Position
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "EventSetCursorPositionImpl\n"));
|
|
|
|
InternalGetScreenResolution ();
|
|
|
|
Status = EFI_INVALID_PARAMETER;
|
|
|
|
//
|
|
// Apple did not check for negatives here.
|
|
//
|
|
|
|
if ( (Position->Horizontal >= 0) && (Position->Vertical >= 0)
|
|
&& (Position->Horizontal < mResolution.Horizontal)
|
|
&& (Position->Vertical < mResolution.Vertical))
|
|
{
|
|
mCursorPosition.Horizontal = Position->Horizontal;
|
|
mCursorPosition.Vertical = Position->Vertical;
|
|
mPointerRawX = MultS64x64 (
|
|
mCursorPosition.Horizontal,
|
|
(INT64)mMaxPointerResolutionX
|
|
);
|
|
mPointerRawY = MultS64x64 (
|
|
mCursorPosition.Vertical,
|
|
(INT64)mMaxPointerResolutionY
|
|
);
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
|
|
return Status;
|
|
}
|