alder_lake_bios/Insyde/InsydeModulePkg/Universal/UserInterface/SetupMouseDxe/SetupMouseCursor.c

311 lines
10 KiB
C

/** @file
Setup Mouse Cursor implementation
;******************************************************************************
;* Copyright (c) 2012 - 2020, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "SetupMouse.h"
#include <Library/UefiHiiServicesLib.h>
extern EFI_HII_HANDLE mImageHiiHandle;
/**
Initialize cursor data
@param[in, out] Private PRIVATE_MOUSE_DATA
@retval EFI_SUCCESS Initialize success
**/
EFI_STATUS
InitializeCursor (
IN OUT PRIVATE_MOUSE_DATA *Private
)
{
EFI_STATUS Status;
EFI_IMAGE_INPUT Image;
if (mImageHiiHandle == NULL) {
return EFI_NOT_READY;
}
Status = gHiiImage->GetImage (
gHiiImage,
mImageHiiHandle,
IMAGE_TOKEN (IMAGE_CURSOR),
&Image
);
if (EFI_ERROR (Status) || Image.Bitmap == NULL) {
return Status;
}
if ((Image.Flags & H2O_IMAGE_ALPHA_CHANNEL) != H2O_IMAGE_ALPHA_CHANNEL) {
ConvertToAlphaChannelImage (&Image);
}
SetRect (&Private->Cursor.ImageRc, 0, 0, Image.Width, Image.Height);
Private->Cursor.Image = Image.Bitmap;
return EFI_SUCCESS;
}
/**
Destroy cursor data
@param[in, out] Private PRIVATE_MOUSE_DATA
@retval EFI_SUCCESS destroy success
**/
VOID
DestroyCursor (
IN OUT PRIVATE_MOUSE_DATA *Private
)
{
DestroyImage (&Private->Cursor);
}
/**
Move the cursor to a particular point indicated by the X, Y axis.
@param [in] X indicates location to move to.
@param [in] Y indicates location to move to.
@retval None
**/
EFI_STATUS
EFIAPI
InternalSetCursorPos (
IN UINTN X,
IN UINTN Y
)
{
PRIVATE_MOUSE_DATA *Private;
Private = mPrivate;
ASSERT_LOCKED (&Private->SetupMouseLock);
if (X < Private->MouseRange.StartX || Y < Private->MouseRange.StartY ||
X > Private->MouseRange.EndX || Y > Private->MouseRange.EndY) {
return EFI_SUCCESS;
}
Private->SaveCursorX = (UINT32)X;
Private->SaveCursorY = (UINT32)Y;
if ((INT32)X != Private->Cursor.ImageRc.left || (INT32)Y != Private->Cursor.ImageRc.top) {
MoveImage (&Private->Cursor, X, Y);
}
return EFI_SUCCESS;
}
/**
According mouse / touch event to determinate cursor postion and button state
@param [in] Event and Context Not actually used in the function
@param [in] Context
@retval EFI_SUCCESS If receive mouse / touch event
**/
VOID
EFIAPI
ProcessMouse (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
PRIVATE_MOUSE_DATA *Private;
INTN CurX, CurY;
UINTN Count;
POINTER_PROTOCOL_INFO *PointerProtocolInfo;
EFI_SIMPLE_POINTER_STATE SimplePointerState;
EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer;
EFI_ABSOLUTE_POINTER_STATE AbsolutePointerState;
UINT64 ScreenFactor;
EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerPtr;
STATIC UINTN TimeCount = 0;
BOOLEAN ImageIsSame;
RECT InvalidateRc;
RECT Rc;
GOP_ENTRY *GopEntry;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
LIST_ENTRY *Node;
UINTN BufferIn;
Private = SETUP_MOUSE_DEV_FROM_THIS (Context);
ASSERT (Private->IsStart);
CurX = (INTN)Private->Cursor.ImageRc.left;
CurY = (INTN)Private->Cursor.ImageRc.top;
if (IsListEmpty (&Private->GopList)) {
return ;
}
GopEntry = GOP_ENTRY_FROM_THIS (GetFirstNode (&Private->GopList));
GraphicsOutput = GopEntry->GraphicsOutput;
PointerProtocolInfo = Private->PointerProtocolInfo;
for (Count = 0; Count < PointerProtocolInfo->Count; Count ++) {
if ((PointerProtocolInfo->Data[Count].Attributes & ATTRIBUTE_BIT_SIMPLE_OR_ABSOLUTE) == ATTRIBUTE_VALUE_SIMPLE) {
//
// Use Simple Pointer protocol to update current mouse state
//
SimplePointerPtr = (EFI_SIMPLE_POINTER_PROTOCOL*) PointerProtocolInfo->Data[Count].PointerProtocol;
Status = SimplePointerPtr->GetState(SimplePointerPtr, &SimplePointerState);
if (EFI_ERROR(Status)) {
continue;
}
if (!Private->HideCursor) {
AcquireSetupMouseLock (Private);
ShowImage (&Private->Cursor);
ReleaseSetupMouseLock (Private);
}
CurX += (SimplePointerState.RelativeMovementX) / MOUSE_RESOLUTION;
CurY += (SimplePointerState.RelativeMovementY) / MOUSE_RESOLUTION;
Private->LButton = SimplePointerState.LeftButton;
Private->RButton = SimplePointerState.RightButton;
} else if ((PointerProtocolInfo->Data[Count].Attributes & ATTRIBUTE_BIT_SIMPLE_OR_ABSOLUTE) == ATTRIBUTE_VALUE_ABSOLUTE) {
//
// Use Absolute Pointer protocol to update current mouse state
//
AbsolutePointer = (EFI_ABSOLUTE_POINTER_PROTOCOL*) PointerProtocolInfo->Data[Count].PointerProtocol;
Status = AbsolutePointer->GetState (AbsolutePointer, &AbsolutePointerState);
if (EFI_ERROR (Status)) {
continue;
}
if (Private->HideCursorWhenTouch) {
AcquireSetupMouseLock (Private);
HideImage (&Private->Cursor);
ReleaseSetupMouseLock (Private);
}
ScreenFactor = DivU64x32 (LShiftU64 ((UINT64)(GraphicsOutput->Mode->Info->HorizontalResolution), 32), (UINT32)(AbsolutePointer->Mode->AbsoluteMaxX - AbsolutePointer->Mode->AbsoluteMinX));
CurX = (UINTN)(RShiftU64 (MultU64x32 (ScreenFactor, (UINT32)(AbsolutePointerState.CurrentX - AbsolutePointer->Mode->AbsoluteMinX)), 32));
ScreenFactor = DivU64x32 (LShiftU64 ((UINT64)(GraphicsOutput->Mode->Info->VerticalResolution), 32), (UINT32)(AbsolutePointer->Mode->AbsoluteMaxY - AbsolutePointer->Mode->AbsoluteMinY));
CurY = (UINTN)(RShiftU64 (MultU64x32 (ScreenFactor, (UINT32)(AbsolutePointerState.CurrentY - AbsolutePointer->Mode->AbsoluteMinY)), 32));
Private->LButton = (BOOLEAN) ((AbsolutePointerState.ActiveButtons & EFI_ABSP_TouchActive) == EFI_ABSP_TouchActive);
Private->RButton = (BOOLEAN) ((AbsolutePointerState.ActiveButtons & EFI_ABS_AltActive) == EFI_ABS_AltActive);
}
//
// Bugbug: if event is touch, do we fix the position ?
//
if (CurX <= (INTN) Private->MouseRange.StartX) {
CurX = (INTN) Private->MouseRange.StartX;
} else if (CurX >= (INTN) Private->MouseRange.EndX) {
CurX = (INTN) Private->MouseRange.EndX;
}
if (CurY <= (INTN) Private->MouseRange.StartY) {
CurY = (INTN) Private->MouseRange.StartY;
} else if (CurY >= (INTN) mPrivate->MouseRange.EndY) {
CurY = (INTN) Private->MouseRange.EndY;
}
SetCursorPos (CurX, CurY);
AcquireSetupMouseLock (Private);
Status = ProcessKeyboard ();
ReleaseSetupMouseLock (Private);
if (!EFI_ERROR (Status)) {
continue;
}
Private->HaveRawData = TRUE;
Private->State[Private->BufferIn].CurrentX = (UINTN) Private->Cursor.ImageRc.left;
Private->State[Private->BufferIn].CurrentY = (UINTN) Private->Cursor.ImageRc.top;
Private->State[Private->BufferIn].CurrentZ = 0;
if (Private->LButton != Private->State[Private->BufferIn].LButton ||
Private->RButton != Private->State[Private->BufferIn].RButton) {
Private->State[Private->BufferIn].LButton = Private->LButton;
Private->State[Private->BufferIn].RButton = Private->RButton;
BufferIn = Private->BufferIn + 1;
if (BufferIn == STATE_BUFFER_SIZE) BufferIn = 0;
if (BufferIn != Private->BufferOut) {
CopyMem (
&Private->State[BufferIn],
&Private->State[Private->BufferIn],
sizeof (SETUP_MOUSE_STATE)
);
Private->BufferIn = BufferIn;
}
}
}
AcquireSetupMouseLock (Private);
RenderImageForAllGop (Private);
//
// sync the keyboard state
//
UpdateKeyboardStateByBDA ();
if (!Private->NeedSyncFrameBuffer) {
ReleaseSetupMouseLock (Private);
return ;
}
//
// check screen per 30 ms
//
if (TimeCount++ < ((TICKS_PER_SECOND / 30) / MOUSE_TIMER)) {
ReleaseSetupMouseLock (Private);
return;
}
TimeCount = 0;
ImageIsSame = FALSE;
Node = GetFirstNode (&Private->GopList);
while (!IsNull (&Private->GopList, Node)) {
GopEntry = GOP_ENTRY_FROM_THIS (Node);
//
// sync (0,0) pixel with screen buffer for bitlocker
//
SetRect(&Rc, 0, 0, 1, 1);
IntersectRect (&InvalidateRc, &Rc, &GopEntry->Screen.ImageRc);
SyncScreenImage (Private, GopEntry, &InvalidateRc, &ImageIsSame);
//
// sync cursor pixel, for bitlocker read input box
//
IntersectRect (&InvalidateRc, &Private->Cursor.ImageRc, &GopEntry->Screen.ImageRc);
SyncScreenImage (Private, GopEntry, &InvalidateRc, &ImageIsSame);
if (!ImageIsSame) {
UnionRect (&GopEntry->InvalidateRc, &GopEntry->InvalidateRc, &Private->Cursor.ImageRc);
}
if (Private->Keyboard.Visible) {
IntersectRect (&InvalidateRc, &Private->Keyboard.ImageRc, &GopEntry->Screen.ImageRc);
SyncScreenImage (Private, GopEntry, &InvalidateRc, &ImageIsSame);
if (!ImageIsSame) {
UnionRect (&GopEntry->InvalidateRc, &GopEntry->InvalidateRc, &Private->Keyboard.ImageRc);
}
}
RenderImage (Private, GopEntry, TRUE);
Node = GetNextNode (&Private->GopList, Node);
}
ReleaseSetupMouseLock (Private);
}