提交 29b6a698 编写于 作者: M Marvin Häuser

OpenCanopy: Initial double-click support

上级 0a97ed4f
......@@ -16,13 +16,6 @@ typedef struct GUI_OUTPUT_CONTEXT_ GUI_OUTPUT_CONTEXT;
typedef struct GUI_POINTER_CONTEXT_ GUI_POINTER_CONTEXT;
typedef struct GUI_KEY_CONTEXT_ GUI_KEY_CONTEXT;
typedef struct {
UINT32 X;
UINT32 Y;
BOOLEAN PrimaryDown;
BOOLEAN SecondaryDown;
} GUI_POINTER_STATE;
GUI_OUTPUT_CONTEXT *
GuiOutputConstruct (
VOID
......@@ -53,10 +46,16 @@ GuiOutputDestruct (
IN GUI_OUTPUT_CONTEXT *Context
);
BOOLEAN
GuiPointerGetEvent (
IN OUT GUI_POINTER_CONTEXT *Context,
OUT GUI_PTR_EVENT *Event
);
VOID
GuiPointerGetState (
GuiPointerGetPosition (
IN OUT GUI_POINTER_CONTEXT *Context,
OUT GUI_POINTER_STATE *State
OUT GUI_PTR_POSITION *Position
);
VOID
......@@ -69,7 +68,8 @@ GuiPointerConstruct (
IN UINT32 DefaultX,
IN UINT32 DefaultY,
IN UINT32 Width,
IN UINT32 Height
IN UINT32 Height,
IN UINT8 UiScale
);
VOID
......
......@@ -13,6 +13,7 @@
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/OcCpuLib.h>
#include <Library/OcGuardLib.h>
#include <Library/OcMiscLib.h>
#include <Library/UefiBootServicesTableLib.h>
......@@ -20,16 +21,25 @@
#include "../OpenCanopy.h"
#include "../GuiIo.h"
#define ABS_DOUBLE_CLICK_RADIUS 25U
#define IS_POWER_2(x) (((x) & ((x) - 1)) == 0 && (x) != 0)
struct GUI_POINTER_CONTEXT_ {
APPLE_EVENT_PROTOCOL *AppleEvent;
EFI_ABSOLUTE_POINTER_PROTOCOL *AbsPointer;
APPLE_EVENT_HANDLE AppleEventHandle;
UINT32 MaxX;
UINT32 MaxY;
INT32 RawX;
INT32 RawY;
GUI_POINTER_STATE CurState;
GUI_PTR_POSITION RawPos;
GUI_PTR_POSITION CurPos;
GUI_PTR_POSITION AbsLastDownPos;
BOOLEAN AbsPrimaryDown;
BOOLEAN AbsDoubleClick;
UINT8 UiScale;
UINT8 LockedBy;
UINT8 EventQueueHead;
UINT8 EventQueueTail;
GUI_PTR_EVENT EventQueue[16];
};
enum {
......@@ -38,6 +48,63 @@ enum {
PointerLockedAbsolute
};
STATIC
VOID
InternalQueuePointerEvent (
IN OUT GUI_POINTER_CONTEXT *Context,
IN UINT8 Type,
IN UINT32 X,
IN UINT32 Y
)
{
UINT32 Tail;
//
// Tail can be accessed concurrently, so increment atomically.
// Due to the modulus, wraparounds do not matter. The size of the queue must
// be a power of two for this to hold.
//
STATIC_ASSERT (
IS_POWER_2 (ARRAY_SIZE (Context->EventQueue)),
"The pointer event queue must have a power of two length."
);
Tail = OcAtomicPreIncUint8 (&Context->EventQueueTail) % ARRAY_SIZE (Context->EventQueue);
Context->EventQueue[Tail].Type = Type;
Context->EventQueue[Tail].Pos.Pos.X = X;
Context->EventQueue[Tail].Pos.Pos.Y = Y;
}
BOOLEAN
GuiPointerGetEvent (
IN OUT GUI_POINTER_CONTEXT *Context,
OUT GUI_PTR_EVENT *Event
)
{
//
// EventQueueHead cannot be accessed concurrently.
//
if (Context->EventQueueHead == Context->EventQueueTail) {
return FALSE;
}
CopyMem (
Event,
&Context->EventQueue[Context->EventQueueHead % ARRAY_SIZE (Context->EventQueue)],
sizeof (*Event)
);
//
// Due to the modulus, wraparounds do not matter. The size of the queue must
// be a power of two for this to hold.
//
STATIC_ASSERT (
IS_POWER_2 (ARRAY_SIZE (Context->EventQueue)),
"The pointer event queue must have a power of two length."
);
++Context->EventQueueHead;
return TRUE;
}
STATIC
VOID
EFIAPI
......@@ -48,8 +115,8 @@ InternalAppleEventNotification (
{
APPLE_POINTER_EVENT_TYPE EventType;
GUI_POINTER_CONTEXT *Context;
INT32 NewX;
INT32 NewY;
GUI_PTR_POSITION NewPos;
GUI_PTR_POSITION NewRaw;
INT64 NewCoord;
Context = NotifyContext;
......@@ -62,12 +129,6 @@ InternalAppleEventNotification (
return;
}
if ((Context->CurState.PrimaryDown | Context->CurState.SecondaryDown) == 0) {
ASSERT (Context->LockedBy == PointerUnlocked);
} else {
ASSERT (Context->LockedBy == PointerLockedSimple);
}
EventType = Information->EventData.PointerEventType;
if ((EventType & APPLE_EVENT_TYPE_MOUSE_MOVED) != 0) {
......@@ -75,49 +136,63 @@ InternalAppleEventNotification (
// Use a factor of 2 for pointer acceleration.
//
NewX = Information->PointerPosition.Horizontal;
NewRaw.Pos.X = (UINT32) Information->PointerPosition.Horizontal;
NewCoord = (INT64) Context->CurState.X + 2 * ((INT64) NewX - Context->RawX);
NewCoord = (INT64) Context->CurPos.Pos.X + 2 * ((INT64) NewRaw.Pos.X - Context->RawPos.Pos.X);
if (NewCoord < 0) {
NewCoord = 0;
NewPos.Pos.X = 0;
} else if (NewCoord > Context->MaxX) {
NewCoord = Context->MaxX;
NewPos.Pos.X = Context->MaxX;
} else {
NewPos.Pos.X = (UINT32) NewCoord;
}
Context->CurState.X = (UINT32) NewCoord;
Context->RawX = NewX;
NewRaw.Pos.Y = (UINT32) Information->PointerPosition.Vertical;
NewY = Information->PointerPosition.Vertical;
NewCoord = (INT64) Context->CurState.Y + 2 * ((INT64) NewY - Context->RawY);
NewCoord = (INT64) Context->CurPos.Pos.Y + 2 * ((INT64) NewRaw.Pos.Y - Context->RawPos.Pos.Y);
if (NewCoord < 0) {
NewCoord = 0;
NewPos.Pos.Y = 0;
} else if (NewCoord > Context->MaxY) {
NewCoord = Context->MaxY;
NewPos.Pos.Y = Context->MaxY;
} else {
NewPos.Pos.Y = (UINT32) NewCoord;
}
Context->CurState.Y = (UINT32) NewCoord;
Context->RawY = NewY;
Context->CurPos.Uint64 = NewPos.Uint64;
Context->RawPos.Uint64 = NewRaw.Uint64;
}
if ((EventType & APPLE_EVENT_TYPE_MOUSE_DOWN) != 0) {
if ((EventType & APPLE_EVENT_TYPE_LEFT_BUTTON) != 0) {
Context->CurState.PrimaryDown = TRUE;
} else if ((EventType & APPLE_EVENT_TYPE_RIGHT_BUTTON) != 0) {
Context->CurState.SecondaryDown = TRUE;
ASSERT (Context->LockedBy == PointerUnlocked);
InternalQueuePointerEvent (
Context,
GuiPointerPrimaryDown,
Context->CurPos.Pos.X,
Context->CurPos.Pos.Y
);
Context->LockedBy = PointerLockedSimple;
}
} else if ((EventType & APPLE_EVENT_TYPE_MOUSE_UP) != 0) {
if ((EventType & APPLE_EVENT_TYPE_LEFT_BUTTON) != 0) {
Context->CurState.PrimaryDown = FALSE;
} else if ((EventType & APPLE_EVENT_TYPE_RIGHT_BUTTON) != 0) {
Context->CurState.SecondaryDown = FALSE;
ASSERT (Context->LockedBy == PointerLockedSimple);
InternalQueuePointerEvent (
Context,
GuiPointerPrimaryUp,
Context->CurPos.Pos.X,
Context->CurPos.Pos.Y
);
Context->LockedBy = PointerUnlocked;
}
} else if ((EventType & APPLE_EVENT_TYPE_MOUSE_DOUBLE_CLICK) != 0) {
if ((EventType & APPLE_EVENT_TYPE_LEFT_BUTTON) != 0) {
InternalQueuePointerEvent (
Context,
GuiPointerPrimaryDoubleClick,
Context->CurPos.Pos.X,
Context->CurPos.Pos.Y
);
}
if ((Context->CurState.PrimaryDown | Context->CurState.SecondaryDown) == 0) {
Context->LockedBy = PointerUnlocked;
} else {
Context->LockedBy = PointerLockedSimple;
}
}
......@@ -131,6 +206,7 @@ InternalUpdateContextAbsolute (
EFI_ABSOLUTE_POINTER_STATE PointerState;
UINT64 NewX;
UINT64 NewY;
GUI_PTR_POSITION NewPos;
ASSERT (Context != NULL);
......@@ -144,12 +220,6 @@ InternalUpdateContextAbsolute (
return;
}
if ((Context->CurState.PrimaryDown | Context->CurState.SecondaryDown) == 0) {
ASSERT (Context->LockedBy == PointerUnlocked);
} else {
ASSERT (Context->LockedBy == PointerLockedAbsolute);
}
Status = Context->AbsPointer->GetState (Context->AbsPointer, &PointerState);
if (EFI_ERROR (Status)) {
return;
......@@ -157,27 +227,69 @@ InternalUpdateContextAbsolute (
NewX = PointerState.CurrentX - Context->AbsPointer->Mode->AbsoluteMinX;
NewX *= Context->MaxX + 1;
Context->CurState.X = (UINT32) DivU64x32 (
NewPos.Pos.X = (UINT32) DivU64x32 (
NewX,
(UINT32) (Context->AbsPointer->Mode->AbsoluteMaxX - Context->AbsPointer->Mode->AbsoluteMinX)
);
Context->RawX = (INT32) Context->CurState.X;
NewY = PointerState.CurrentY - Context->AbsPointer->Mode->AbsoluteMinY;
NewY *= Context->MaxY + 1;
Context->CurState.Y = (UINT32) DivU64x32 (
NewPos.Pos.Y = (UINT32) DivU64x32 (
NewY,
(UINT32) (Context->AbsPointer->Mode->AbsoluteMaxY - Context->AbsPointer->Mode->AbsoluteMinY)
);
Context->RawY = (INT32) Context->CurState.Y;
//
// This is not perfectly concurrent, but good enough.
//
Context->CurPos.Uint64 = NewPos.Uint64;
Context->RawPos.Uint64 = NewPos.Uint64;
//
// Cancel double click when the finger is moved too far away.
//
if (Context->AbsDoubleClick) {
if (ABS ((INT64) NewPos.Pos.X - Context->AbsLastDownPos.Pos.X) > ABS_DOUBLE_CLICK_RADIUS * Context->UiScale
|| ABS ((INT64) NewPos.Pos.Y - Context->AbsLastDownPos.Pos.Y) > ABS_DOUBLE_CLICK_RADIUS * Context->UiScale) {
Context->AbsDoubleClick = FALSE;
}
}
Context->CurState.PrimaryDown = (PointerState.ActiveButtons & EFI_ABSP_TouchActive) != 0;
Context->CurState.SecondaryDown = (PointerState.ActiveButtons & EFI_ABS_AltActive) != 0;
if (Context->AbsPrimaryDown != ((PointerState.ActiveButtons & EFI_ABSP_TouchActive) != 0)) {
Context->AbsPrimaryDown = ((PointerState.ActiveButtons & EFI_ABSP_TouchActive) != 0);
if (Context->AbsPrimaryDown) {
ASSERT (Context->LockedBy == PointerUnlocked);
InternalQueuePointerEvent (
Context,
GuiPointerPrimaryDown,
NewPos.Pos.X,
NewPos.Pos.Y
);
Context->LockedBy = PointerLockedAbsolute;
if ((Context->CurState.PrimaryDown | Context->CurState.SecondaryDown) == 0) {
Context->LockedBy = PointerUnlocked;
Context->AbsLastDownPos.Pos.X = NewPos.Pos.X;
Context->AbsLastDownPos.Pos.Y = NewPos.Pos.Y;
Context->AbsDoubleClick = TRUE;
} else {
Context->LockedBy = PointerLockedAbsolute;
ASSERT (Context->LockedBy == PointerLockedAbsolute);
InternalQueuePointerEvent (
Context,
GuiPointerPrimaryUp,
NewPos.Pos.X,
NewPos.Pos.Y
);
Context->LockedBy = PointerUnlocked;
ASSERT (Context->UiScale > 0);
if (Context->AbsDoubleClick) {
InternalQueuePointerEvent (
Context,
GuiPointerPrimaryDoubleClick,
NewPos.Pos.X,
NewPos.Pos.Y
);
Context->AbsDoubleClick = FALSE;
}
}
}
}
......@@ -198,32 +310,34 @@ GuiPointerReset (
}
VOID
GuiPointerGetState (
GuiPointerGetPosition (
IN OUT GUI_POINTER_CONTEXT *Context,
OUT GUI_POINTER_STATE *State
OUT GUI_PTR_POSITION *Position
)
{
EFI_TPL OldTpl;
ASSERT (Context != NULL);
ASSERT (State != NULL);
ASSERT (Position != NULL);
//
// Prevent simple pointer updates during state retrieval.
// On 64+-bit systems, the operation is atomic.
//
if (sizeof (UINTN) < sizeof (UINT64)) {
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
}
//
// The simple pointer updates are done in InternalAppleEventNotification().
//
InternalUpdateContextAbsolute (Context);
//
// Return the current pointer state.
// Return the current pointer position.
//
State->X = Context->CurState.X;
State->Y = Context->CurState.Y;
State->PrimaryDown = Context->CurState.PrimaryDown;
State->SecondaryDown = Context->CurState.SecondaryDown;
Position->Uint64 = Context->CurPos.Uint64;
if (sizeof (UINTN) < sizeof (UINT64)) {
gBS->RestoreTPL (OldTpl);
}
}
GUI_POINTER_CONTEXT *
......@@ -231,7 +345,8 @@ GuiPointerConstruct (
IN UINT32 DefaultX,
IN UINT32 DefaultY,
IN UINT32 Width,
IN UINT32 Height
IN UINT32 Height,
IN UINT8 UiScale
)
{
// TODO: alloc on the fly?
......@@ -248,10 +363,11 @@ GuiPointerConstruct (
Context.MaxX = Width - 1;
Context.MaxY = Height - 1;
Context.CurState.X = DefaultX;
Context.CurState.Y = DefaultY;
Context.RawX = (INT32) DefaultX;
Context.RawY = (INT32) DefaultY;
Context.CurPos.Pos.X = DefaultX;
Context.CurPos.Pos.Y = DefaultY;
Context.RawPos.Pos.X = DefaultX;
Context.RawPos.Pos.Y = DefaultY;
Context.UiScale = UiScale;
Status = OcHandleProtocolFallback (
gST->ConsoleInHandle,
......
......@@ -38,13 +38,13 @@ STATIC EFI_CONSOLE_CONTROL_SCREEN_MODE mPreviousMode;
STATIC
EFI_STATUS
OcShowMenuByOcEnter (
IN OC_BOOT_CONTEXT *BootContext
IN BOOT_PICKER_GUI_CONTEXT *GuiContext
)
{
EFI_STATUS Status;
Status = GuiLibConstruct (
BootContext->PickerContext,
GuiContext,
mGuiContext.CursorDefaultX,
mGuiContext.CursorDefaultY
);
......@@ -94,7 +94,7 @@ OcShowMenuByOc (
mGuiContext.PickerContext = BootContext->PickerContext;
mGuiContext.AudioPlaybackTimeout = -1;
Status = OcShowMenuByOcEnter (BootContext);
Status = OcShowMenuByOcEnter (&mGuiContext);
if (EFI_ERROR (Status)) {
return Status;
}
......
......@@ -209,11 +209,9 @@ GuiObjDelegatePtrEvent (
IN OUT GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN GUI_PTR_EVENT Event,
IN INT64 BaseX,
IN INT64 BaseY,
IN INT64 OffsetX,
IN INT64 OffsetY
IN CONST GUI_PTR_EVENT *Event
)
{
UINTN Index;
......@@ -221,18 +219,20 @@ GuiObjDelegatePtrEvent (
GUI_OBJ_CHILD *Child;
ASSERT (This != NULL);
ASSERT (This->Width > OffsetX);
ASSERT (This->Height > OffsetY);
ASSERT (Event->Pos.Pos.X >= BaseX);
ASSERT (Event->Pos.Pos.Y >= BaseY);
ASSERT (This->Width > Event->Pos.Pos.X - BaseX);
ASSERT (This->Height > Event->Pos.Pos.Y - BaseY);
ASSERT (DrawContext != NULL);
//
// Pointer event propagation is backwards due to forwards draw order.
//
for (Index = This->NumChildren; Index > 0; --Index) {
Child = This->Children[Index - 1];
if (OffsetX < Child->Obj.OffsetX
|| OffsetX >= Child->Obj.OffsetX + Child->Obj.Width
|| OffsetY < Child->Obj.OffsetY
|| OffsetY >= Child->Obj.OffsetY + Child->Obj.Height) {
if (Event->Pos.Pos.X - BaseX < Child->Obj.OffsetX
|| Event->Pos.Pos.X - BaseX >= Child->Obj.OffsetX + Child->Obj.Width
|| Event->Pos.Pos.Y - BaseY < Child->Obj.OffsetY
|| Event->Pos.Pos.Y - BaseY >= Child->Obj.OffsetY + Child->Obj.Height) {
continue;
}
......@@ -241,11 +241,9 @@ GuiObjDelegatePtrEvent (
&Child->Obj,
DrawContext,
Context,
Event,
BaseX + Child->Obj.OffsetX,
BaseY + Child->Obj.OffsetY,
OffsetX - Child->Obj.OffsetX,
OffsetY - Child->Obj.OffsetY
Event
);
if (Obj != NULL) {
return Obj;
......@@ -595,7 +593,7 @@ GuiOverlayPointer (
CONST GUI_IMAGE *CursorImage;
UINT32 MaxWidth;
UINT32 MaxHeight;
GUI_POINTER_STATE PointerState;
GUI_PTR_POSITION PointerPos;
INT64 BaseX;
INT64 BaseY;
......@@ -612,10 +610,10 @@ GuiOverlayPointer (
//
// Poll the current cursor position late to reduce input lag.
//
GuiPointerGetState (mPointerContext, &PointerState);
GuiPointerGetPosition (mPointerContext, &PointerPos);
ASSERT (PointerState.X < DrawContext->Screen->Width);
ASSERT (PointerState.Y < DrawContext->Screen->Height);
ASSERT (PointerPos.Pos.X < DrawContext->Screen->Width);
ASSERT (PointerPos.Pos.Y < DrawContext->Screen->Height);
//
// Unconditionally draw the cursor to increase frametime consistency and
......@@ -629,7 +627,7 @@ GuiOverlayPointer (
// Draw the new cursor at the new position.
//
BaseX = (INT64) PointerState.X - BOOT_CURSOR_OFFSET * DrawContext->Scale;
BaseX = (INT64) PointerPos.Pos.X - BOOT_CURSOR_OFFSET * DrawContext->Scale;
if (BaseX < 0) {
ImageOffsetX = (UINT32) -BaseX;
DrawBaseX = 0;
......@@ -640,7 +638,7 @@ GuiOverlayPointer (
MaxWidth = MIN (CursorImage->Width, (UINT32) (DrawContext->Screen->Width - BaseX));
BaseY = (INT64) PointerState.Y - BOOT_CURSOR_OFFSET * DrawContext->Scale;
BaseY = (INT64) PointerPos.Pos.Y - BOOT_CURSOR_OFFSET * DrawContext->Scale;
if (BaseY < 0) {
ImageOffsetY = (UINT32) -BaseY;
DrawBaseY = 0;
......@@ -792,7 +790,7 @@ GuiRedrawAndFlushScreen (
EFI_STATUS
GuiLibConstruct (
IN OC_PICKER_CONTEXT *PickerContext,
IN BOOT_PICKER_GUI_CONTEXT *GuiContext,
IN UINT32 CursorDefaultX,
IN UINT32 CursorDefaultY
)
......@@ -811,19 +809,20 @@ GuiLibConstruct (
CursorDefaultX = MIN (CursorDefaultX, OutputInfo->HorizontalResolution - 1);
CursorDefaultY = MIN (CursorDefaultY, OutputInfo->VerticalResolution - 1);
if ((PickerContext->PickerAttributes & OC_ATTR_USE_POINTER_CONTROL) != 0) {
if ((GuiContext->PickerContext->PickerAttributes & OC_ATTR_USE_POINTER_CONTROL) != 0) {
mPointerContext = GuiPointerConstruct (
CursorDefaultX,
CursorDefaultY,
OutputInfo->HorizontalResolution,
OutputInfo->VerticalResolution
OutputInfo->VerticalResolution,
GuiContext->Scale
);
if (mPointerContext == NULL) {
DEBUG ((DEBUG_WARN, "OCUI: Failed to initialise pointer\n"));
}
}
mKeyContext = GuiKeyConstruct (PickerContext);
mKeyContext = GuiKeyConstruct (GuiContext->PickerContext);
if (mKeyContext == NULL) {
DEBUG ((DEBUG_WARN, "OCUI: Failed to initialise key input\n"));
}
......@@ -911,12 +910,12 @@ GuiViewDeinitialize (
OUT BOOT_PICKER_GUI_CONTEXT *GuiContext
)
{
GUI_POINTER_STATE PointerState;
GUI_PTR_POSITION PointerPos;
if (mPointerContext != NULL) {
GuiPointerGetState (mPointerContext, &PointerState);
GuiContext->CursorDefaultX = PointerState.X;
GuiContext->CursorDefaultY = PointerState.Y;
GuiPointerGetPosition (mPointerContext, &PointerPos);
GuiContext->CursorDefaultX = PointerPos.Pos.X;
GuiContext->CursorDefaultY = PointerPos.Pos.Y;
}
ZeroMem (DrawContext, sizeof (*DrawContext));
......@@ -979,7 +978,8 @@ GuiDrawLoop (
INTN InputKey;
BOOLEAN Modifier;
GUI_POINTER_STATE PointerState;
GUI_PTR_EVENT PointerEvent;
GUI_OBJ *TempObject;
GUI_OBJ *HoldObject;
INT64 HoldObjBaseX;
INT64 HoldObjBaseY;
......@@ -998,7 +998,10 @@ GuiDrawLoop (
mNumValidDrawReqs = 0;
FrameTime = 0;
HoldObject = NULL;
DEBUG_CODE_BEGIN ();
ObjectHeld = FALSE;
DEBUG_CODE_END ();
//
// Clear previous inputs.
......@@ -1038,29 +1041,65 @@ GuiDrawLoop (
//
// Process pointer events.
//
GuiPointerGetState (mPointerContext, &PointerState);
Result = GuiPointerGetEvent (mPointerContext, &PointerEvent);
if (Result) {
if (PointerEvent.Type == GuiPointerPrimaryUp) {
//
// 'Button down' must have caught and set an interaction object.
// It may be NULL for objects that solely delegate pointer events.
//
ASSERT (ObjectHeld);
if (HoldObject != NULL) {
GuiGetBaseCoords (
HoldObject,
DrawContext,
&HoldObjBaseX,
&HoldObjBaseY
);
HoldObject->PtrEvent (
HoldObject,
DrawContext,
DrawContext->GuiContext,
HoldObjBaseX,
HoldObjBaseY,
&PointerEvent
);
HoldObject = NULL;
}
if (PointerState.PrimaryDown) {
if (!ObjectHeld && HoldObject == NULL) {
HoldObject = GuiObjDelegatePtrEvent (
DEBUG_CODE_BEGIN ();
ObjectHeld = FALSE;
DEBUG_CODE_END ();
} else {
//
// HoldObject == NULL cannot be tested here as double-click may arrive
// before button up.
//
ASSERT (PointerEvent.Type != GuiPointerPrimaryUp);
TempObject = GuiObjDelegatePtrEvent (
DrawContext->Screen,
DrawContext,
DrawContext->GuiContext,
GuiPointerPrimaryDown,
0,
0,
PointerState.X,
PointerState.Y
&PointerEvent
);
if (PointerEvent.Type == GuiPointerPrimaryDown) {
DEBUG_CODE_BEGIN ();
ObjectHeld = TRUE;
DEBUG_CODE_END ();
HoldObject = TempObject;
}
ObjectHeld = TRUE;
} else {
ObjectHeld = FALSE;
}
if (HoldObject != NULL) {
} else if (HoldObject != NULL) {
//
// If there are no events to process, update the cursor position with
// the interaction object for visual effects.
//
PointerEvent.Type = GuiPointerPrimaryDown;
GuiPointerGetPosition (mPointerContext, &PointerEvent.Pos);
GuiGetBaseCoords (
HoldObject,
DrawContext,
......@@ -1071,15 +1110,10 @@ GuiDrawLoop (
HoldObject,
DrawContext,
DrawContext->GuiContext,
!PointerState.PrimaryDown ? GuiPointerPrimaryUp : GuiPointerPrimaryHold,
HoldObjBaseX,
HoldObjBaseY,
(INT64)PointerState.X - HoldObjBaseX,
(INT64)PointerState.Y - HoldObjBaseY
&PointerEvent
);
if (!PointerState.PrimaryDown) {
HoldObject = NULL;
}
}
}
......
......@@ -20,11 +20,23 @@ typedef struct _BOOT_PICKER_GUI_CONTEXT BOOT_PICKER_GUI_CONTEXT;
enum {
GuiPointerPrimaryDown,
GuiPointerPrimaryHold,
GuiPointerPrimaryUp
GuiPointerPrimaryUp,
GuiPointerPrimaryDoubleClick
};
typedef UINT8 GUI_PTR_EVENT;
typedef union {
struct {
UINT32 X;
UINT32 Y;
} Pos;
UINT64 Uint64;
} GUI_PTR_POSITION;
typedef struct {
UINT8 Type;
GUI_PTR_POSITION Pos;
} GUI_PTR_EVENT;
typedef
VOID
......@@ -46,11 +58,9 @@ GUI_OBJ *
IN OUT GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN GUI_PTR_EVENT Event,
IN INT64 BaseX,
IN INT64 BaseY,
IN INT64 OffsetX,
IN INT64 OffsetY
IN CONST GUI_PTR_EVENT *Event
);
typedef
......@@ -181,11 +191,9 @@ GuiObjDelegatePtrEvent (
IN OUT GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN GUI_PTR_EVENT Event,
IN INT64 BaseX,
IN INT64 BaseY,
IN INT64 OffsetX,
IN INT64 OffsetY
IN CONST GUI_PTR_EVENT *Event
);
BOOLEAN
......@@ -271,7 +279,7 @@ GuiClearScreen (
EFI_STATUS
GuiLibConstruct (
IN OC_PICKER_CONTEXT *PickerContext,
IN BOOT_PICKER_GUI_CONTEXT *GuiContext,
IN UINT32 CursorDefaultX,
IN UINT32 CursorDefaultY
);
......
......@@ -473,24 +473,22 @@ InternalBootPickerEntryPtrEvent (
IN OUT GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN GUI_PTR_EVENT Event,
IN INT64 BaseX,
IN INT64 BaseY,
IN INT64 OffsetX,
IN INT64 OffsetY
IN CONST GUI_PTR_EVENT *Event
)
{
STATIC BOOLEAN SameIter = FALSE;
GUI_VOLUME_ENTRY *Entry;
BOOLEAN IsHit;
UINT32 OffsetX;
UINT32 OffsetY;
ASSERT (Event == GuiPointerPrimaryDown
|| Event == GuiPointerPrimaryHold
|| Event == GuiPointerPrimaryUp);
if (Event == GuiPointerPrimaryHold) {
return This;
}
OffsetX = (UINT32) (Event->Pos.Pos.X - BaseX);
OffsetY = (UINT32) (Event->Pos.Pos.Y - BaseY);
ASSERT (Event->Type == GuiPointerPrimaryDown
|| Event->Type == GuiPointerPrimaryUp
|| Event->Type == GuiPointerPrimaryDoubleClick);
if (OffsetX < BOOT_ENTRY_ICON_SPACE * DrawContext->Scale
|| OffsetY < BOOT_ENTRY_ICON_SPACE * DrawContext->Scale) {
......@@ -508,7 +506,7 @@ InternalBootPickerEntryPtrEvent (
return This;
}
if (Event == GuiPointerPrimaryDown) {
if (Event->Type == GuiPointerPrimaryDown) {
if (mBootPicker.SelectedIndex != Entry->Index) {
ASSERT (Entry->Hdr.Parent == &mBootPicker.Hdr.Obj);
InternalBootPickerChangeEntry (
......@@ -518,22 +516,17 @@ InternalBootPickerEntryPtrEvent (
BaseY - This->OffsetY,
Entry->Index
);
SameIter = TRUE;
}
} else {
} else if (Event->Type == GuiPointerPrimaryDoubleClick) {
//
// This must be ensured because the UI directs Move/Up events to the object
// Down had been sent to.
//
ASSERT (mBootPicker.SelectedIndex == Entry->Index);
if (SameIter) {
SameIter = FALSE;
} else {
Context->ReadyToBoot = TRUE;
ASSERT (Context->BootEntry == Entry->Context);
}
}
//
// There should be no children.
//
......@@ -724,17 +717,17 @@ InternalBootPickerSelectorPtrEvent (
IN OUT GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN GUI_PTR_EVENT Event,
IN INT64 BaseX,
IN INT64 BaseY,
IN INT64 OffsetX,
IN INT64 OffsetY
IN CONST GUI_PTR_EVENT *Event
)
{
GUI_OBJ_CLICKABLE *Clickable;
CONST GUI_IMAGE *ButtonImage;
BOOLEAN IsHit;
UINT32 OffsetX;
UINT32 OffsetY;
ASSERT (This != NULL);
ASSERT (DrawContext != NULL);
......@@ -744,12 +737,15 @@ InternalBootPickerSelectorPtrEvent (
//
ASSERT (This->NumChildren == 0);
OffsetX = (UINT32) (Event->Pos.Pos.X - BaseX);
OffsetY = (UINT32) (Event->Pos.Pos.Y - BaseY);
Clickable = BASE_CR (This, GUI_OBJ_CLICKABLE, Hdr.Obj);
ButtonImage = &Context->Icons[ICON_SELECTOR][ICON_TYPE_BASE];
ASSERT (Event == GuiPointerPrimaryDown
|| Event == GuiPointerPrimaryHold
|| Event == GuiPointerPrimaryUp);
ASSERT (Event->Type == GuiPointerPrimaryDown
|| Event->Type == GuiPointerPrimaryUp
|| Event->Type == GuiPointerPrimaryDoubleClick);
if (OffsetX >= (BOOT_SELECTOR_BACKGROUND_DIMENSION * DrawContext->Scale - ButtonImage->Width) / 2
&& OffsetY >= (BOOT_SELECTOR_BACKGROUND_DIMENSION + BOOT_SELECTOR_BUTTON_SPACE) * DrawContext->Scale) {
IsHit = GuiClickableIsHit (
......@@ -758,7 +754,7 @@ InternalBootPickerSelectorPtrEvent (
OffsetY - (BOOT_SELECTOR_BACKGROUND_DIMENSION + BOOT_SELECTOR_BUTTON_SPACE) * DrawContext->Scale
);
if (IsHit) {
if (Event == GuiPointerPrimaryUp) {
if (Event->Type == GuiPointerPrimaryUp) {
ASSERT (Context->BootEntry == InternalGetVolumeEntry (mBootPicker.SelectedIndex)->Context);
Context->ReadyToBoot = TRUE;
} else {
......@@ -787,11 +783,9 @@ InternalBootPickerLeftScrollPtrEvent (
IN OUT GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN GUI_PTR_EVENT Event,
IN INT64 BaseX,
IN INT64 BaseY,
IN INT64 OffsetX,
IN INT64 OffsetY
IN CONST GUI_PTR_EVENT *Event
)
{
GUI_OBJ_CLICKABLE *Clickable;
......@@ -812,19 +806,19 @@ InternalBootPickerLeftScrollPtrEvent (
Clickable = BASE_CR (This, GUI_OBJ_CLICKABLE, Hdr.Obj);
ButtonImage = &Context->Icons[ICON_LEFT][ICON_TYPE_BASE];
ASSERT (Event == GuiPointerPrimaryDown
|| Event == GuiPointerPrimaryHold
|| Event == GuiPointerPrimaryUp);
ASSERT (Event->Type == GuiPointerPrimaryDown
|| Event->Type == GuiPointerPrimaryUp
|| Event->Type == GuiPointerPrimaryDoubleClick);
ASSERT (ButtonImage->Width == This->Width);
ASSERT (ButtonImage->Height == This->Height);
IsHit = GuiClickableIsHit (
ButtonImage,
OffsetX,
OffsetY
Event->Pos.Pos.X - BaseX,
Event->Pos.Pos.Y - BaseY
);
if (IsHit) {
if (Event != GuiPointerPrimaryUp) {
if (Event->Type == GuiPointerPrimaryDown) {
ButtonImage = &Context->Icons[ICON_LEFT][ICON_TYPE_HELD];
} else if (mBootPicker.Hdr.Obj.OffsetX < 0) {
//
......@@ -891,11 +885,9 @@ InternalBootPickerRightScrollPtrEvent (
IN OUT GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN GUI_PTR_EVENT Event,
IN INT64 BaseX,
IN INT64 BaseY,
IN INT64 OffsetX,
IN INT64 OffsetY
IN CONST GUI_PTR_EVENT *Event
)
{
GUI_OBJ_CLICKABLE *Clickable;
......@@ -916,17 +908,17 @@ InternalBootPickerRightScrollPtrEvent (
Clickable = BASE_CR (This, GUI_OBJ_CLICKABLE, Hdr.Obj);
ButtonImage = &Context->Icons[ICON_RIGHT][ICON_TYPE_BASE];
ASSERT (Event == GuiPointerPrimaryDown
|| Event == GuiPointerPrimaryHold
|| Event == GuiPointerPrimaryUp);
ASSERT (Event->Type == GuiPointerPrimaryDown
|| Event->Type == GuiPointerPrimaryUp
|| Event->Type == GuiPointerPrimaryDoubleClick);
IsHit = GuiClickableIsHit (
ButtonImage,
OffsetX,
OffsetY
Event->Pos.Pos.X - BaseX,
Event->Pos.Pos.Y - BaseY
);
if (IsHit) {
if (Event != GuiPointerPrimaryUp) {
if (Event->Type == GuiPointerPrimaryDown) {
ButtonImage = &Context->Icons[ICON_RIGHT][ICON_TYPE_HELD];
} else if (mBootPicker.Hdr.Obj.OffsetX + mBootPicker.Hdr.Obj.Width > mBootPickerContainer.Obj.Width) {
//
......@@ -1038,11 +1030,9 @@ InternalBootPickerShutDownPtrEvent (
IN OUT GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN GUI_PTR_EVENT Event,
IN INT64 BaseX,
IN INT64 BaseY,
IN INT64 OffsetX,
IN INT64 OffsetY
IN CONST GUI_PTR_EVENT *Event
)
{
GUI_OBJ_CLICKABLE *Clickable;
......@@ -1052,17 +1042,17 @@ InternalBootPickerShutDownPtrEvent (
Clickable = BASE_CR (This, GUI_OBJ_CLICKABLE, Hdr.Obj);
ButtonImage = &Context->Icons[ICON_SHUT_DOWN][ICON_TYPE_BASE];
ASSERT (Event == GuiPointerPrimaryDown
|| Event == GuiPointerPrimaryHold
|| Event == GuiPointerPrimaryUp);
ASSERT (Event->Type == GuiPointerPrimaryDown
|| Event->Type == GuiPointerPrimaryUp
|| Event->Type == GuiPointerPrimaryDoubleClick);
IsHit = GuiClickableIsHit (
ButtonImage,
OffsetX,
OffsetY
Event->Pos.Pos.X - BaseX,
Event->Pos.Pos.Y - BaseY
);
if (IsHit) {
if (Event != GuiPointerPrimaryUp) {
if (Event->Type == GuiPointerPrimaryDown) {
ButtonImage = &Context->Icons[ICON_SHUT_DOWN][ICON_TYPE_HELD];
} else {
gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
......@@ -1090,11 +1080,9 @@ InternalBootPickerRestartPtrEvent (
IN OUT GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN GUI_PTR_EVENT Event,
IN INT64 BaseX,
IN INT64 BaseY,
IN INT64 OffsetX,
IN INT64 OffsetY
IN CONST GUI_PTR_EVENT *Event
)
{
GUI_OBJ_CLICKABLE *Clickable;
......@@ -1104,17 +1092,17 @@ InternalBootPickerRestartPtrEvent (
Clickable = BASE_CR (This, GUI_OBJ_CLICKABLE, Hdr.Obj);
ButtonImage = &Context->Icons[ICON_RESTART][ICON_TYPE_BASE];
ASSERT (Event == GuiPointerPrimaryDown
|| Event == GuiPointerPrimaryHold
|| Event == GuiPointerPrimaryUp);
ASSERT (Event->Type == GuiPointerPrimaryDown
|| Event->Type == GuiPointerPrimaryUp
|| Event->Type == GuiPointerPrimaryDoubleClick);
IsHit = GuiClickableIsHit (
ButtonImage,
OffsetX,
OffsetY
Event->Pos.Pos.X - BaseX,
Event->Pos.Pos.Y - BaseY
);
if (IsHit) {
if (Event != GuiPointerPrimaryUp) {
if (Event->Type == GuiPointerPrimaryDown) {
ButtonImage = &Context->Icons[ICON_RESTART][ICON_TYPE_HELD];
} else {
gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册