/** @file
Virtural Keyboard Layout Engine
Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "VirtualKeyboard.h"
//
// 1.FullKeyboardBody
// Follow below design
// (1).\KeyboardLayout\CapitalLetterKeyboard.bmp
// (2).\KeyboardLayout\DigitKeyboard.bmp
// Based on keyboard's (startX, startY)
//
// Page0Font
// +---+---+---+---+---+---+---+---+---+---+---+
// | q | w | e | r | t | y | u | i | o | p | | ? |F11|F12|Enter| Line 2
// +-----+---+---+---+---+---+---+---+---+---+-+
// | Esc |12#| Space | | | _ | + | | Line 3
// +-----+---+-------------------+---+---+---+-+
//
// 2.Screen Corner
// Follow below design
// (1).\KeyboardLayout\SimpleIcon.bmp # Screen Corner A/B
// (2).\KeyboardLayout\FullIcon.bmp # Screen Corner C/D
// +-+------------------------------------+-+
// |A| |C|
// +-+ +-+
// | |
// | |
// | |
// | |
// | |
// | |
// +-+ +-+
// |B| |D|
// +-+------------------------------------+-+
//
VK_STRUCT mFullKeyboardBody[] = {
// StartX StartY EndX EndY Page0Font Page1Font Page2Font Page3Font
// Line 0
{ 0x0000, 0x0000, 0x0032, 0x0032, {L'q', L'Q', L'1', L'!' }},
{ 0x0032, 0x0000, 0x0064, 0x0032, {L'w', L'W', L'2', L'@' }},
{ 0x0064, 0x0000, 0x0096, 0x0032, {L'e', L'E', L'3', L'#' }},
{ 0x0096, 0x0000, 0x00C8, 0x0032, {L'r', L'R', L'4', L'$' }},
{ 0x00C8, 0x0000, 0x00FA, 0x0032, {L't', L'T', L'5', L'%' }},
{ 0x00FA, 0x0000, 0x012C, 0x0032, {L'y', L'Y', L'6', L'^' }},
{ 0x012C, 0x0000, 0x015E, 0x0032, {L'u', L'U', L'7', L'&' }},
{ 0x015E, 0x0000, 0x0190, 0x0032, {L'i', L'I', L'8', L'*' }},
{ 0x0190, 0x0000, 0x01C2, 0x0032, {L'o', L'O', L'9', L'(' }},
{ 0x01C2, 0x0000, 0x01F4, 0x0032, {L'p', L'P', L'0', L')' }},
{ 0x01F4, 0x0000, 0x0226, 0x0032, {VkKeyBackspace, VkKeyBackspace, VkKeyBackspace, VkKeyBackspace }},
// Line 1
{ 0x0000, 0x0032, 0x0019, 0x0064, {VkKeyNull, VkKeyNull, VkKeyNull, VkKeyNull }},
{ 0x0019, 0x0032, 0x004B, 0x0064, {L'a', L'A', VkKeyF1, VkKeyF1 }},
{ 0x004B, 0x0032, 0x007D, 0x0064, {L's', L'S', VkKeyF2, VkKeyF2 }},
{ 0x007D, 0x0032, 0x00AF, 0x0064, {L'd', L'D', VkKeyF3, VkKeyF3 }},
{ 0x00AF, 0x0032, 0x00E1, 0x0064, {L'f', L'F', VkKeyF4, VkKeyF4 }},
{ 0x00E1, 0x0032, 0x0113, 0x0064, {L'g', L'G', VkKeyF5, VkKeyF5 }},
{ 0x0113, 0x0032, 0x0145, 0x0064, {L'h', L'H', VkKeyF6, VkKeyF6 }},
{ 0x0145, 0x0032, 0x0177, 0x0064, {L'j', L'J', VkKeyF7, VkKeyF7 }},
{ 0x0177, 0x0032, 0x01A9, 0x0064, {L'k', L'K', VkKeyF8, VkKeyF8 }},
{ 0x01A9, 0x0032, 0x01DB, 0x0064, {L'l', L'L', VkKeyF9, VkKeyF9 }},
{ 0x01DB, 0x0032, 0x020D, 0x0064, {VkKeyF2, VkKeyF2, VkKeyF10, VkKeyF10 }},
// Line 2
{ 0x0000, 0x0064, 0x004B, 0x0096, {VkKeyCapslock, VkKeyCapslock, VkKeyShift, VkKeyShift }},
{ 0x004B, 0x0064, 0x007D, 0x0096, {L'z', L'Z', L'`', L'~' }},
{ 0x007D, 0x0064, 0x00AF, 0x0096, {L'x', L'X', L';', L':' }},
{ 0x00AF, 0x0064, 0x00E1, 0x0096, {L'c', L'C', L'\'', L'"' }},
{ 0x00E1, 0x0064, 0x0113, 0x0096, {L'v', L'V', L',', L'<' }},
{ 0x0113, 0x0064, 0x0145, 0x0096, {L'b', L'B', L'.', L'>' }},
{ 0x0145, 0x0064, 0x0177, 0x0096, {L'n', L'N', L'/', L'?' }},
{ 0x0177, 0x0064, 0x01A9, 0x0096, {L'm', L'M', VkKeyF11, VkKeyF11 }},
{ 0x01A9, 0x0064, 0x01DB, 0x0096, {VkKeyUp, VkKeyUp, VkKeyF12, VkKeyF12 }},
{ 0x01DB, 0x0064, 0x0226, 0x0096, {VkKeyEnter, VkKeyEnter, VkKeyEnter, VkKeyEnter }},
// Line 3
{ 0x0000, 0x0096, 0x004B, 0x00C8, {VkKeyEsc, VkKeyEsc, VkKeyEsc, VkKeyEsc }},
{ 0x004B, 0x0096, 0x007D, 0x00C8, {VkKeyTwoPage, VkKeyTwoPage, VkKeyTwoPage, VkKeyTwoPage }},
{ 0x007D, 0x0096, 0x0177, 0x00C8, {L' ', L' ', L' ', L' ' }},
{ 0x0177, 0x0096, 0x01A9, 0x00C8, {VkKeyLeft, VkKeyLeft, L'\\', L'|' }},
{ 0x01A9, 0x0096, 0x01DB, 0x00C8, {VkKeyDown, VkKeyDown, L'-', L'_' }},
{ 0x01DB, 0x0096, 0x020D, 0x00C8, {VkKeyRight, VkKeyRight, L'=', L'+' }},
// Screen Corner A
{ 0x0000, 0x0000, 0x001E, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}},
// Screen Corner B
{ 0x0000, 0x023A, 0x001E, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}},
// Screen Corner C
{ 0x02E4, 0x0000, 0x0320, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}},
// Screen Corner D
{ 0x02E4, 0x023A, 0x0320, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}}
};
//
// 1.SimpleKeyboardBody
// Follow below design
// (1).\KeyboardLayout\SimpleKeyboard.bmp
// Based on keyboard's (startX, startY)
// +-----+-----+
// | Esc |Enter| Line 0
// +-----+-----+
// | Up | Down| Line 1
// +-----+-----+
//
// 2.Screen Corner
// Follow below design
// (1).\KeyboardLayout\SimpleIcon.bmp # Screen Corner A/B
// (2).\KeyboardLayout\FullIcon.bmp # Screen Corner C/D
// +-+------------------------------------+-+
// |A| |C|
// +-+ +-+
// | |
// | |
// | |
// | |
// | |
// | |
// +-+ +-+
// |B| |D|
// +-+------------------------------------+-+
//
VK_STRUCT mSimpleKeyboardBody[] = {
// StartX StartY EndX EndY Page0Font Page1Font Page2Font Page3Font
// Line 0
{ 0x0000, 0x0000, 0x0032, 0x0032, {VkKeyEsc, VkKeyEsc, VkKeyEsc, VkKeyEsc }},
{ 0x0032, 0x0000, 0x0064, 0x0032, {VkKeyEnter, VkKeyEnter, VkKeyEnter, VkKeyEnter }},
// Line 1
{ 0x0000, 0x0032, 0x0032, 0x0064, {VkKeyUp, VkKeyUp, VkKeyUp, VkKeyUp }},
{ 0x0032, 0x0032, 0x0064, 0x0064, {VkKeyDown, VkKeyDown, VkKeyDown, VkKeyDown }},
// Screen Corner A
{ 0x0000, 0x0000, 0x001E, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}},
// Screen Corner B
{ 0x0000, 0x023A, 0x001E, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}},
// Screen Corner C
{ 0x02E4, 0x0000, 0x0320, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}},
// Screen Corner D
{ 0x02E4, 0x023A, 0x0320, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum}}
};
/**
Modify the color of key if Shift or CapsLock is pressed.
@param[in] VkContext Address of an VK_CONTEXT structure.
@param[in, out] BltBuffer Address of a blt buffer.
@retval EFI_SUCCESS Success for the function.
**/
EFI_STATUS
ModifyShiftKeyColor (
IN VK_CONTEXT *VkContext,
IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **BltBuffer
)
{
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *TempBltBuffer;
UINTN BltSize;
BOOLEAN IsPressed;
TempBltBuffer = *BltBuffer;
BltSize = VkContext->VkBodyBltHeight * VkContext->VkBodyBltWidth;
IsPressed = VkContext->PageNumber <= VkPage1 ?
VkContext->IsCapsLockFlag :
VkContext->IsShiftKeyFlag;
while (BltSize-- != 0) {
//
// Color gradient issue
//
if (((TempBltBuffer->Red - TempBltBuffer->Green) > 0x20) &&
((TempBltBuffer->Red - TempBltBuffer->Blue) > 0x20)) {
if (IsPressed) {
TempBltBuffer->Red = 0;
TempBltBuffer->Green = 255;
TempBltBuffer->Blue = 255;
} else {
TempBltBuffer->Red = 255;
TempBltBuffer->Green = 255;
TempBltBuffer->Blue = 255;
}
}
TempBltBuffer++;
}
return EFI_SUCCESS;
}
/**
Make the keyboard transparent.
@param[in] VkContext Address of an VK_CONTEXT structure.
@param[in] IsTransparent TRUE for set keyboard transparent.
@param[in] BltIn Address of keyboard blt buffer.
@param[in, out] BltOut Address of output blt buffer.
NULL will allocate it.
@retval EFI_SUCCESS Success for the function.
@retval EFI_OUT_OF_RESOURCES Allocate memory failed.
**/
EFI_STATUS
MakeKeyboardTransparent (
IN VK_CONTEXT *VkContext,
IN BOOLEAN IsTransparent,
IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltIn,
IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **BltOut
)
{
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Compound;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Keyboard;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background;
UINTN BltSize;
if (*BltOut == NULL) {
*BltOut = AllocateZeroPool (VkContext->VkBodyBltSize);
if (*BltOut == NULL) {
return EFI_OUT_OF_RESOURCES;
}
}
Compound = *BltOut;
Keyboard = BltIn;
Background = VkContext->VkBodyBackgroundBltBuffer;
BltSize = VkContext->VkBodyBltHeight * VkContext->VkBodyBltWidth;
while (BltSize-- != 0) {
if (IsTransparent) {
Compound->Red = (Keyboard->Red * TRANSPARENCY_WEIGHT) / 100 + (Background->Red * (100 - TRANSPARENCY_WEIGHT)) / 100;
Compound->Green = (Keyboard->Green * TRANSPARENCY_WEIGHT) / 100 + (Background->Green * (100 - TRANSPARENCY_WEIGHT)) / 100;
Compound->Blue = (Keyboard->Blue * TRANSPARENCY_WEIGHT) / 100 + (Background->Blue * (100 - TRANSPARENCY_WEIGHT)) / 100;
} else {
*Compound = *Keyboard;
}
Compound++;
Keyboard++;
Background++;
}
return EFI_SUCCESS;
}
/**
Save the background blt buffer.
@param[in] VkContext Address of an VK_CONTEXT structure.
@param[in] BltSize Size of blt.
@retval EFI_SUCCESS Success for the function.
@retval EFI_OUT_OF_RESOURCES Allocate memory failed.
**/
EFI_STATUS
EFIAPI
SaveVkBodyBackgroundBltBuffer (
IN VK_CONTEXT *VkContext,
IN UINTN BltSize
)
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *CurrentBltBuffer;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *CurrentBltBufferSave;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *OldBltBuffer;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *OldBltBufferSave;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Compound;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background;
UINTN Size;
CurrentBltBufferSave = NULL;
OldBltBufferSave = NULL;
//
// Save original blt buffer first.
//
OldBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);
if (OldBltBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
if (VkContext->VkBodyBackgroundBltBuffer != NULL) {
CopyMem (OldBltBuffer, VkContext->VkBodyBackgroundBltBuffer, VkContext->VkBodyBltSize);
}
if (VkContext->VkBodyBackgroundBltBuffer == NULL) {
VkContext->VkBodyBltSize = BltSize;
VkContext->VkBodyBackgroundBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);
ASSERT (VkContext->VkBodyBackgroundBltBuffer != NULL);
if (VkContext->VkBodyBackgroundBltBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
} else if (BltSize > VkContext->VkBodyBltSize) {
VkContext->VkBodyBltSize = BltSize;
FreePool (VkContext->VkBodyBackgroundBltBuffer);
VkContext->VkBodyBackgroundBltBuffer = NULL;
VkContext->VkBodyBackgroundBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);
ASSERT (VkContext->VkBodyBackgroundBltBuffer != NULL);
if (VkContext->VkBodyBackgroundBltBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
} else {
ZeroMem (VkContext->VkBodyBackgroundBltBuffer, VkContext->VkBodyBltSize);
}
CurrentBltBuffer = NULL;
if (VkContext->IsBackgroundChanged == TRUE) {
//
// Background changed, merge current visioning blt buffer with old background blt buffer.
//
Compound = VkContext->VkBodyCompoundBltBuffer;
Background = VkContext->VkBodyBackgroundBltBuffer;
CurrentBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);
ASSERT (CurrentBltBuffer != NULL);
if (CurrentBltBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = VkContext->GraphicsOutput->Blt (
VkContext->GraphicsOutput,
CurrentBltBuffer,
EfiBltVideoToBltBuffer,
VkContext->VkBodyBltStartX,
VkContext->VkBodyBltStartY,
0,
0,
VkContext->VkBodyBltWidth,
VkContext->VkBodyBltHeight,
VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
);
CurrentBltBufferSave = CurrentBltBuffer;
OldBltBufferSave = OldBltBuffer;
Size = VkContext->VkBodyBltHeight * VkContext->VkBodyBltWidth;
while (Size-- != 0) {
if ((Compound->Red != CurrentBltBuffer->Red) ||
(Compound->Green != CurrentBltBuffer->Green) ||
(Compound->Blue != CurrentBltBuffer->Blue)) {
*Background = *CurrentBltBuffer;
} else {
*Background = *OldBltBuffer;
}
Compound++;
Background++;
CurrentBltBuffer++;
OldBltBuffer++;
}
} else {
//
// Background NOT changed, save it to VkBodyBackgroundBltBuffer directly.
//
Status = VkContext->GraphicsOutput->Blt (
VkContext->GraphicsOutput,
VkContext->VkBodyBackgroundBltBuffer,
EfiBltVideoToBltBuffer,
VkContext->VkBodyBltStartX,
VkContext->VkBodyBltStartY,
0,
0,
VkContext->VkBodyBltWidth,
VkContext->VkBodyBltHeight,
VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
);
}
if (CurrentBltBufferSave != NULL) {
FreePool (CurrentBltBufferSave);
}
if (OldBltBufferSave != NULL) {
FreePool (OldBltBufferSave);
}
return Status;
}
/**
Restore the background blt buffer.
@param[in] VkContext Address of an VK_CONTEXT structure.
@retval EFI_SUCCESS Success for the function.
@retval EFI_UNSUPPORTED Input blt buffer is NULL.
@retval Others An unexpected error occurred.
**/
EFI_STATUS
EFIAPI
RestoreVkBodyBackgroundBltBuffer (
IN VK_CONTEXT *VkContext
)
{
EFI_STATUS Status;
if (VkContext->VkBodyBackgroundBltBuffer == NULL) {
return EFI_UNSUPPORTED;
}
Status = VkContext->GraphicsOutput->Blt (
VkContext->GraphicsOutput,
VkContext->VkBodyBackgroundBltBuffer,
EfiBltBufferToVideo,
0,
0,
VkContext->VkBodyBltStartX,
VkContext->VkBodyBltStartY,
VkContext->VkBodyBltWidth,
VkContext->VkBodyBltHeight,
VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
);
FreePool (VkContext->VkBodyBackgroundBltBuffer);
VkContext->VkBodyBackgroundBltBuffer = NULL;
return Status;
}
/**
Set the position of character.
@param[in] VkContext Address of an VK_CONTEXT structure.
@param[in] DestX X position.
@param[in] DestY Y position.
@retval EFI_SUCCESS Success for the function.
@retval Others An unexpected error occurred.
**/
EFI_STATUS
SetCharacterPosition (
IN VK_CONTEXT *VkContext,
IN UINT32 DestX,
IN UINT32 DestY
)
{
UINTN Index;
VK_STRUCT *KeyArryPtr;
UINT32 KeyArrySize;
switch (VkContext->TargetKeyboardDisplay) {
case VkDisplayAttributeSimpleTop:
case VkDisplayAttributeSimpleBottom:
KeyArryPtr = mSimpleKeyboardBody;
KeyArrySize = DIM (mSimpleKeyboardBody);
break;
case VkDisplayAttributeFullBottom:
case VkDisplayAttributeFullTop:
KeyArryPtr = mFullKeyboardBody;
KeyArrySize = DIM (mFullKeyboardBody);
break;
case VkDisplayAttributeNone:
KeyArryPtr = mFullKeyboardBody;
KeyArrySize = DIM (mFullKeyboardBody);
break;
default:
return EFI_UNSUPPORTED;
}
for (Index = 0; Index < KeyArrySize; Index++) {
VkContext->KeyboardBodyPtr[Index] = KeyArryPtr[Index];
}
VkContext->NumOfKeysInfo = KeyArrySize;
for (Index = 0; Index < (VkContext->NumOfKeysInfo - 4); Index++) {
VkContext->KeyboardBodyPtr[Index].DisStartX += (UINT16)DestX;
VkContext->KeyboardBodyPtr[Index].DisStartY += (UINT16)DestY;
VkContext->KeyboardBodyPtr[Index].DisEndX += (UINT16)DestX;
VkContext->KeyboardBodyPtr[Index].DisEndY += (UINT16)DestY;
}
return EFI_SUCCESS;
}
/**
Save the icon background blt buffer.
@param[in] VkContext Address of an VK_CONTEXT structure.
@param[in] IconType The icon type.
@retval EFI_SUCCESS Success for the function.
@retval EFI_OUT_OF_RESOURCES Allocate memory failed.
@retval Others An unexpected error occurred.
**/
EFI_STATUS
EFIAPI
SaveVkIconBackgroundBltBuffer (
IN VK_CONTEXT *VkContext,
IN VK_DISPLAY_ATTRIBUTE IconType
)
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GraphicBlt;
UINTN BltSize;
UINTN Height;
UINTN Width;
INTN StartX;
INTN StartY;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *TempIconBackBuffer;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *IconBackBuffer;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Compound;
UINTN Size;
BOOLEAN SaveCursor;
Status = EFI_SUCCESS;
StartX = 0;
StartY = 0;
TempIconBackBuffer = NULL;
IconBackBuffer = NULL;
Compound = NULL;
if ((IconType == VkDisplayAttributeFullTop) ||
(IconType == VkDisplayAttributeSimpleTop)) {
return EFI_SUCCESS;
}
SaveCursor = gST->ConOut->Mode->CursorVisible;
gST->ConOut->EnableCursor (gST->ConOut, FALSE);
if (IconType == VkDisplayAttributeFullBottom) {
GraphicBlt = VkContext->FullIcon->Bitmap;
BltSize = VkContext->FullIcon->Height * VkContext->FullIcon->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
Height = VkContext->FullIcon->Height;
Width = VkContext->FullIcon->Width;
StartX = VkContext->FullIconBackStartX;
StartY = VkContext->FullIconBackStartY;
} else if (IconType == VkDisplayAttributeSimpleBottom) {
GraphicBlt = VkContext->SmallIcon->Bitmap;
BltSize = VkContext->SmallIcon->Height * VkContext->SmallIcon->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
Height = VkContext->SmallIcon->Height;
Width = VkContext->SmallIcon->Width;
StartX = VkContext->SimIconBackStartX;
StartY = VkContext->SimIconBackStartY;
} else {
gST->ConOut->EnableCursor (gST->ConOut, SaveCursor);
return EFI_UNSUPPORTED;
}
IconBackBuffer = AllocateZeroPool (BltSize);
if (IconBackBuffer == NULL) {
gST->ConOut->EnableCursor (gST->ConOut, SaveCursor);
return EFI_OUT_OF_RESOURCES;
}
TempIconBackBuffer = IconBackBuffer;
Status = VkContext->GraphicsOutput->Blt (
VkContext->GraphicsOutput,
IconBackBuffer,
EfiBltVideoToBltBuffer,
StartX,
StartY,
0,
0,
Width,
Height,
Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
);
if (IconType == VkDisplayAttributeFullBottom) {
//
// Store full icon background framebuffer
//
VkContext->FullIconBackHeight = Height;
VkContext->FullIconBackWidth = Width;
if (VkContext->FullIconUpdatedFlag == FALSE) {
//
// No icon draw, save the buffer directly.
//
if (VkContext->FullIconBackBuffer == NULL) {
VkContext->FullIconBackBuffer = AllocateZeroPool (BltSize);
VkContext->FullIconBackSize = BltSize;
}
CopyMem (VkContext->FullIconBackBuffer, IconBackBuffer, BltSize);
VkContext->FullIconUpdatedFlag = TRUE;
} else {
if (CompareMem (VkContext->FullIconBackBuffer, IconBackBuffer, BltSize) != 0) {
Compound = VkContext->FullIconBackBuffer;
Size = Height * Width;
while (Size-- != 0) {
if ((GraphicBlt->Red != IconBackBuffer->Red) ||
(GraphicBlt->Green != IconBackBuffer->Green) ||
(GraphicBlt->Blue != IconBackBuffer->Blue)) {
*Compound = *IconBackBuffer;
}
Compound++;
GraphicBlt++;
IconBackBuffer++;
}
}
}
} else if (IconType == VkDisplayAttributeSimpleBottom) {
//
// Store simple icon background framebuffer
//
VkContext->SimIconBackHeight = Height;
VkContext->SimIconBackWidth = Width;
if (VkContext->SimIconUpdatedFlag == FALSE) {
//
// No icon draw, save the buffer directly.
//
if (VkContext->SimIconBackBuffer == NULL) {
VkContext->SimIconBackBuffer = AllocateZeroPool (BltSize);
VkContext->SimIconBackSize = BltSize;
}
CopyMem (VkContext->SimIconBackBuffer, IconBackBuffer, BltSize);
VkContext->SimIconUpdatedFlag = TRUE;
} else {
if (CompareMem (VkContext->SimIconBackBuffer, IconBackBuffer, BltSize) != 0) {
Compound = VkContext->SimIconBackBuffer;
Size = Height * Width;
while (Size-- != 0) {
if ((GraphicBlt->Red != IconBackBuffer->Red) ||
(GraphicBlt->Green != IconBackBuffer->Green) ||
(GraphicBlt->Blue != IconBackBuffer->Blue)) {
*Compound = *IconBackBuffer;
}
Compound++;
GraphicBlt++;
IconBackBuffer++;
}
}
}
}
if (TempIconBackBuffer != NULL) FreePool (TempIconBackBuffer);
gST->ConOut->EnableCursor (gST->ConOut, SaveCursor);
return Status;
}
/**
Use to draw the keyboard icon.
@param[in] VkContext Pointer to virtual keyboard's context
@param[in] VkImage Image of keyboard to display on the screen.
@param[in] Attribute Attribute of keyboard to display on the screen.
@retval EFI_SUCCESS ConsoleControl has been flipped to graphics and keyboard icon displayed.
@retval EFI_UNSUPPORTED KeyboardFile not found
@retval EFI_INVALID_PARAMETER Attribute is unknown.
**/
EFI_STATUS
EFIAPI
DrawVkIcon (
IN VK_CONTEXT *VkContext,
IN EFI_IMAGE_INPUT *VkImage,
IN VK_DISPLAY_ATTRIBUTE Attribute
)
{
EFI_STATUS Status;
UINT32 SizeOfX;
UINT32 SizeOfY;
INTN DestX;
INTN DestY;
UINTN CoordinateX;
UINTN CoordinateY;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
UINTN BltSize;
UINTN Height;
UINTN Width;
Status = EFI_SUCCESS;
GraphicsOutput = VkContext->GraphicsOutput;
SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
CoordinateX = 0;
CoordinateY = 0;
Height = VkImage->Height;
Width = VkImage->Width;
Blt = VkImage->Bitmap;
BltSize = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (UINT32)(Width * Height);
//
// Calculate the display position according to Attribute.
//
switch (Attribute) {
case VkDisplayAttributeSimpleTop:
DestX = CoordinateX;
DestY = CoordinateY;
break;
case VkDisplayAttributeFullTop:
DestX = (SizeOfX - Width - CoordinateX);
DestY = CoordinateY;;
break;
case VkDisplayAttributeFullBottom:
DestX = (SizeOfX - Width - CoordinateX);
DestY = (SizeOfY - Height - CoordinateY);
VkContext->FullIconBackStartX = DestX;
VkContext->FullIconBackStartY = DestY;
break;
case VkDisplayAttributeSimpleBottom:
DestX = CoordinateX;
DestY = (SizeOfY - Height - CoordinateY);
//
// Save to check icon/screen cleared
//
if (VkContext->IconBltBuffer == NULL) {
VkContext->IconBltSize = BltSize;
VkContext->IconBltWidth = Width;
VkContext->IconBltHeight = Height;
VkContext->IconBltBuffer = AllocateZeroPool (BltSize);
}
CopyMem (VkContext->IconBltBuffer, Blt, VkContext->IconBltSize);
VkContext->SimIconBackStartX = DestX;
VkContext->SimIconBackStartY = DestY;
break;
case VkDisplayAttributeNone:
return EFI_SUCCESS;
default:
return EFI_INVALID_PARAMETER;
}
if ((DestX >= 0) && (DestY >= 0)) {
//
// Store icon background framebuffer
//
SaveVkIconBackgroundBltBuffer (VkContext, Attribute);
Status = GraphicsOutput->Blt (
GraphicsOutput,
Blt,
EfiBltBufferToVideo,
0,
0,
(UINTN) DestX,
(UINTN) DestY,
Width,
Height,
Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
);
}
return Status;
}
/**
Use to draw the keyboard.
@param[in] VkContext Pointer to virtual keyboard's context
@param[in] VkImage Image of keyboard to display on the screen.
@param[in] Attribute Attribute of keyboard to display on the screen.
@retval EFI_SUCCESS ConsoleControl has been flipped to graphics and keyboard displayed.
@retval EFI_UNSUPPORTED KeyboardFile not found
@retval EFI_INVALID_PARAMETER Attribute is unknown.
**/
EFI_STATUS
EFIAPI
DrawVkBody (
IN VK_CONTEXT *VkContext,
IN EFI_IMAGE_INPUT *VkImage,
IN VK_DISPLAY_ATTRIBUTE Attribute
)
{
EFI_STATUS Status;
UINT32 SizeOfX;
UINT32 SizeOfY;
INTN DestX;
INTN DestY;
UINTN BltSize;
UINTN Height;
UINTN Width;
UINTN CoordinateY;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltIn;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
Status = EFI_SUCCESS;
GraphicsOutput = VkContext->GraphicsOutput;
SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
CoordinateY = 0;
Height = VkImage->Height;
Width = VkImage->Width;
BltSize = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (UINT32)(Width * Height);
BltIn = AllocateCopyPool (BltSize, VkImage->Bitmap);
if (BltIn == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Calculate the display position according to Attribute.
//
switch (Attribute) {
case VkDisplayAttributeSimpleTop:
DestX = ((SizeOfX / 2) - Width) / 4;
DestY = CoordinateY;
VkContext->CurrentKeyboardDisplay = VkDisplayAttributeSimpleTop;
break;
case VkDisplayAttributeSimpleBottom:
DestX = ((SizeOfX / 2) - Width) / 4;
DestY = (SizeOfY - Height - CoordinateY);
VkContext->CurrentKeyboardDisplay = VkDisplayAttributeSimpleBottom;
break;
case VkDisplayAttributeFullTop:
DestX = (SizeOfX - Width) / 2;
DestY = CoordinateY;
VkContext->CurrentKeyboardDisplay = VkDisplayAttributeFullTop;
break;
case VkDisplayAttributeFullBottom:
DestX = (SizeOfX - Width) / 2;
DestY = (SizeOfY - Height - CoordinateY);
VkContext->CurrentKeyboardDisplay = VkDisplayAttributeFullBottom;
break;
case VkDisplayAttributeNone:
VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
goto DVKBODY_Exit;
default:
VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
Status = EFI_INVALID_PARAMETER;
goto DVKBODY_Exit;
}
if ((DestX >= 0) && (DestY >= 0)) {
SetCharacterPosition (VkContext, (UINT32)DestX, (UINT32)DestY);
//
// Store current framebuffer
//
VkContext->VkBodyBltStartX = DestX;
VkContext->VkBodyBltStartY = DestY;
VkContext->VkBodyBltHeight = Height;
VkContext->VkBodyBltWidth = Width;
SaveVkBodyBackgroundBltBuffer (VkContext, BltSize);
//
// Free compound buffer first.
//
if (VkContext->VkBodyCompoundBltBuffer != NULL) {
FreePool (VkContext->VkBodyCompoundBltBuffer);
}
VkContext->VkBodyCompoundBltBuffer = NULL;
ModifyShiftKeyColor (VkContext, &BltIn);
MakeKeyboardTransparent (VkContext, TRUE, BltIn, &(VkContext->VkBodyCompoundBltBuffer));
//
// Draw keyboard body
//
Status = GraphicsOutput->Blt (
GraphicsOutput,
VkContext->VkBodyCompoundBltBuffer,
EfiBltBufferToVideo,
0,
0,
(UINTN) DestX,
(UINTN) DestY,
Width,
Height,
Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
);
}
DVKBODY_Exit:
if (BltIn != NULL) {
FreePool (BltIn);
}
return Status;
}
/**
Clear the keyboard body
@param VkContext Code context.
@retval EFI_SUCCESS Clear rectangle is done.
**/
EFI_STATUS
HideVkBody (
IN VK_CONTEXT *VkContext
)
{
RestoreVkBodyBackgroundBltBuffer (VkContext);
VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
return EFI_SUCCESS;
}
/**
Clear the keyboard icon
@param VkContext Code context.
@retval EFI_SUCCESS Clear rectangle is done.
**/
EFI_STATUS
HideVkIcon (
IN VK_CONTEXT *VkContext
)
{
EFI_STATUS Status;
if ((VkContext->FullIconBackBuffer == NULL) || (VkContext->SimIconBackBuffer == NULL)) {
return EFI_UNSUPPORTED;
}
if ((VkContext->FullIconUpdatedFlag == FALSE) || (VkContext->SimIconUpdatedFlag == FALSE)) {
return EFI_UNSUPPORTED;
}
Status = VkContext->GraphicsOutput->Blt (
VkContext->GraphicsOutput,
VkContext->FullIconBackBuffer,
EfiBltBufferToVideo,
0,
0,
VkContext->FullIconBackStartX,
VkContext->FullIconBackStartY,
VkContext->FullIconBackWidth,
VkContext->FullIconBackHeight,
VkContext->FullIconBackWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
);
ZeroMem (VkContext->FullIconBackBuffer, VkContext->FullIconBackSize);
VkContext->FullIconUpdatedFlag = FALSE;
Status = VkContext->GraphicsOutput->Blt (
VkContext->GraphicsOutput,
VkContext->SimIconBackBuffer,
EfiBltBufferToVideo,
0,
0,
VkContext->SimIconBackStartX,
VkContext->SimIconBackStartY,
VkContext->SimIconBackWidth,
VkContext->SimIconBackHeight,
VkContext->SimIconBackWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
);
if (!EFI_ERROR (Status)) {
if (VkContext->ScreenCheckBuffer == NULL) {
VkContext->ScreenCheckBufferSize = VkContext->SimIconBackHeight *
VkContext->SimIconBackWidth *
sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
VkContext->ScreenCheckBuffer = AllocateZeroPool (VkContext->ScreenCheckBufferSize);
}
CopyMem (
VkContext->ScreenCheckBuffer,
VkContext->SimIconBackBuffer,
(VkContext->SimIconBackHeight * VkContext->SimIconBackWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))
);
}
ZeroMem (VkContext->SimIconBackBuffer, VkContext->SimIconBackSize);
VkContext->SimIconUpdatedFlag = FALSE;
return EFI_SUCCESS;
}
/**
Draw key board on the display
@param[in] VkContext Graphic Protocol for draw the alphabet.
@retval EFI_SUCCESS Draw keyboard was done.
@retval EFI_UNSUPPORTED Did not get key mapping table.
**/
EFI_STATUS
DrawKeyboardLayout (
IN VK_CONTEXT *VkContext
)
{
EFI_STATUS Status;
if (!VkContext->IsIconShowed) {
Status = DrawVkIcon (VkContext, VkContext->SmallIcon, VkDisplayAttributeSimpleTop);
ASSERT_EFI_ERROR (Status);
Status = DrawVkIcon (VkContext, VkContext->SmallIcon, VkDisplayAttributeSimpleBottom);
ASSERT_EFI_ERROR (Status);
Status = DrawVkIcon (VkContext, VkContext->FullIcon, VkDisplayAttributeFullTop);
ASSERT_EFI_ERROR (Status);
Status = DrawVkIcon (VkContext, VkContext->FullIcon, VkDisplayAttributeFullBottom);
ASSERT_EFI_ERROR (Status);
VkContext->IsIconShowed = TRUE;
}
if (VkContext->TargetKeyboardDisplay != VkContext->CurrentKeyboardDisplay) {
switch (VkContext->TargetKeyboardDisplay) {
case VkDisplayAttributeSimpleTop:
case VkDisplayAttributeSimpleBottom:
DrawVkBody (VkContext, VkContext->SimKeyBody, VkContext->TargetKeyboardDisplay);
break;
case VkDisplayAttributeFullTop:
case VkDisplayAttributeFullBottom:
if (VkContext->PageNumber <= VkPage1) {
DrawVkBody (VkContext, VkContext->CapLeKeyBody, VkContext->TargetKeyboardDisplay);
} else {
DrawVkBody (VkContext, VkContext->DigKeyBody, VkContext->TargetKeyboardDisplay);
}
case VkDisplayAttributeNone:
break;
default:
break;
}
}
return EFI_SUCCESS;
}
/**
Set the keyboard layout.
@param[in] VkContext Graphic Protocol for draw the alphabet.
@param[in] Index The layout selected.
@retval EFI_SUCCESS Draw keyboard was done.
@retval Others An unexpected error occurred.
**/
EFI_STATUS
KeyboardLayoutHandler (
IN VK_CONTEXT *VkContext,
IN UINT32 Index
)
{
EFI_STATUS Status;
Status = EFI_SUCCESS;
if (Index == (VkContext->NumOfKeysInfo - 4)) {
//
// Touch the LeftTop icon
//
if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeSimpleTop) {
VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;
} else {
VkContext->TargetKeyboardDisplay = VkDisplayAttributeSimpleTop;
}
} else if (Index == (VkContext->NumOfKeysInfo - 3)) {
//
// Touch the LeftBottom icon
//
if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeSimpleBottom) {
VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;
} else {
VkContext->TargetKeyboardDisplay = VkDisplayAttributeSimpleBottom;
}
} else if (Index == (VkContext->NumOfKeysInfo - 2)) {
//
// Touch the RightTop icon
//
if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeFullTop) {
VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;
} else {
VkContext->TargetKeyboardDisplay = VkDisplayAttributeFullTop;
}
} else {
//
// Touch the RightBottom icon
//
if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeFullBottom) {
VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;
} else {
VkContext->TargetKeyboardDisplay = VkDisplayAttributeFullBottom;
}
}
if (VkContext->TargetKeyboardDisplay == VkDisplayAttributeNone) {
//
// Just hide the current keyboard
//
HideVkBody (VkContext);
VkContext->KeyTouchedTimeOut = VK_REPEAT_TIMEOUT;
} else {
//
// If current keyboard status is NOT none,
// hide current keyboard first and then draw the target keyboard
//
if (VkContext->CurrentKeyboardDisplay != VkDisplayAttributeNone) {
HideVkBody (VkContext);
}
Status = DrawKeyboardLayout (VkContext);
}
return Status;
}
/**
This routine is used to check if icon has been cleared.
@param[in] VkContext Pointer to virtual keyboard's context
@retval EFI_SUCCESS Function completed.
**/
EFI_STATUS
CheckIconCleared (
IN VK_CONTEXT *VkContext
)
{
EFI_STATUS Status;
UINT32 VerticalResolution;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
Status = EFI_SUCCESS;
BltBuffer = NULL;
VkContext->IconReDrawCheck++;
if (VkContext->IconReDrawCheck <= 10) {
//
// Check it every 10 * 100ms.
//
return Status;
}
//
// Check if right-bottomed region is black, if yes, clean screen happened, need to re-draw keyboard.
//
VerticalResolution = VkContext->GraphicsOutput->Mode->Info->VerticalResolution;
BltBuffer = AllocateZeroPool (VkContext->IconBltSize);
if (BltBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = VkContext->GraphicsOutput->Blt (
VkContext->GraphicsOutput,
BltBuffer,
EfiBltVideoToBltBuffer,
0,
(VerticalResolution - VkContext->IconBltHeight),
0,
0,
VkContext->IconBltWidth,
VkContext->IconBltHeight,
VkContext->IconBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
);
if (EFI_ERROR (Status)) {
FreePool (BltBuffer);
return Status;
}
VkContext->IsIconShowed = TRUE;
if (VkContext->IconBltBuffer == NULL) {
//
// No icon has been drawn.
//
VkContext->IsIconShowed = FALSE;
} else {
if (CompareMem (BltBuffer, VkContext->IconBltBuffer, VkContext->IconBltSize) != 0) {
//
// Icon has been overridden, need to re-draw.
//
VkContext->IsIconShowed = FALSE;
}
}
if (VkContext->IsIconShowed == FALSE) {
if (VkContext->ScreenCheckBuffer != NULL) {
if (CompareMem (BltBuffer, VkContext->ScreenCheckBuffer, VkContext->IconBltSize) == 0) {
//
// Icon has been overridden, force to re-draw the keyboard.
//
Status = DrawKeyboardLayout (VkContext);
} else {
//
// Save blt buffer of icon position and use it to check if icon is overridden.
//
CopyMem (VkContext->ScreenCheckBuffer, BltBuffer, VkContext->IconBltSize);
}
} else {
//
// Draw the keyboard.
//
Status = DrawKeyboardLayout (VkContext);
}
}
if (BltBuffer != NULL) {
FreePool (BltBuffer);
}
VkContext->IconReDrawCheck = 0;
return Status;
}
/**
ConvertCoordinate - Convert the touch panel's coordinate to display's coordinate.
@param[in] VkContext Virtual Keyboard context.
@param[in] Point The coordinate reported from touch panel.
@param[out] TouchX The coordinate X converted to display panel.
@param[out] TouchY The coordinate Y converted to display panel..
@retval EFI_SUCCESS Convert success.
**/
EFI_STATUS
ConvertCoordinate (
IN VK_CONTEXT *VkContext,
IN EFI_ABSOLUTE_POINTER_STATE Point,
OUT UINT32 *TouchX,
OUT UINT32 *TouchY
)
{
UINT64 AbsoluteMaxX;
UINT64 AbsoluteMaxY;
UINT32 HorizontalResolution;
UINT32 VerticalResolution;
AbsoluteMaxX = VkContext->AbsolutePointer->Mode->AbsoluteMaxX;
AbsoluteMaxY = VkContext->AbsolutePointer->Mode->AbsoluteMaxY;
HorizontalResolution = VkContext->GraphicsOutput->Mode->Info->HorizontalResolution;
VerticalResolution = VkContext->GraphicsOutput->Mode->Info->VerticalResolution;
*TouchX = (UINT32) MultU64x32 (Point.CurrentX, HorizontalResolution) / (UINT32) AbsoluteMaxX;
*TouchY = (UINT32) MultU64x32 (Point.CurrentY, VerticalResolution) / (UINT32) AbsoluteMaxY;
return EFI_SUCCESS;
}
/**
This routine is used to check if screen has been cleared.
@param[in] VkContext Pointer to virtual keyboard's context
@retval EFI_SUCCESS Function completed.
**/
EFI_STATUS
CheckScreenCleared (
IN VK_CONTEXT *VkContext
)
{
EFI_STATUS Status;
UINT32 HorizontalResolution;
UINT32 VerticalResolution;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBufferIndex;
UINTN BltSize;
BOOLEAN IsScreenCleared;
//
// Check left-bottom side.
// If IconBltBuffer is null, checking is meaningless.
//
if (VkContext->IconBltBuffer == NULL) {
return EFI_SUCCESS;
}
IsScreenCleared = FALSE;
Status = EFI_SUCCESS;
if ((gST->ConOut->Mode->CursorColumn == 0) && (gST->ConOut->Mode->CursorRow == 0)) {
//
// System may call gST->ConOut->ClearScreen
//
HorizontalResolution = VkContext->GraphicsOutput->Mode->Info->HorizontalResolution;
VerticalResolution = VkContext->GraphicsOutput->Mode->Info->VerticalResolution;
BltBuffer = AllocateZeroPool (VkContext->IconBltSize);
if (BltBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
BltBufferIndex = BltBuffer;
Status = VkContext->GraphicsOutput->Blt (
VkContext->GraphicsOutput,
BltBuffer,
EfiBltVideoToBltBuffer,
(HorizontalResolution - VkContext->IconBltWidth),
(VerticalResolution - VkContext->IconBltHeight),
0,
0,
VkContext->IconBltWidth,
VkContext->IconBltHeight,
VkContext->IconBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
);
if (EFI_ERROR (Status)) {
FreePool (BltBuffer);
return Status;
}
BltSize = VkContext->IconBltHeight * VkContext->IconBltWidth;
IsScreenCleared = TRUE;
while (BltSize-- != 0) {
if ((BltBufferIndex->Red != 0) || (BltBufferIndex->Green != 0) || (BltBufferIndex->Blue != 0)) {
IsScreenCleared = FALSE;
break;
}
BltBufferIndex++;
}
FreePool (BltBuffer);
}
if (IsScreenCleared) {
VkContext->IsIconShowed = FALSE;
VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
if (VkContext->VkBodyBackgroundBltBuffer != NULL) {
FreePool (VkContext->VkBodyBackgroundBltBuffer);
VkContext->VkBodyBackgroundBltBuffer = NULL;
}
if (VkContext->VkBodyCompoundBltBuffer != NULL) {
FreePool (VkContext->VkBodyCompoundBltBuffer);
VkContext->VkBodyCompoundBltBuffer = NULL;
}
if (VkContext->IconBltBuffer != NULL) {
FreePool (VkContext->IconBltBuffer);
VkContext->IconBltBuffer = NULL;
}
}
return Status;
}
/**
This routine is used to check if background beneath virtual keyboard has been cleared.
@param[in] VkContext Pointer to virtual keyboard's context
@retval EFI_SUCCESS Function completed.
**/
EFI_STATUS
CheckBackgroundChanged (
IN VK_CONTEXT *VkContext
)
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
Status = EFI_SUCCESS;
VkContext->IsBackgroundChanged = FALSE;
if ((VkContext->CurrentKeyboardDisplay == VkDisplayAttributeNone) || (VkContext->VkBodyCompoundBltBuffer == NULL)) {
return EFI_SUCCESS;
}
BltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);
if (BltBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = VkContext->GraphicsOutput->Blt (
VkContext->GraphicsOutput,
BltBuffer,
EfiBltVideoToBltBuffer,
VkContext->VkBodyBltStartX,
VkContext->VkBodyBltStartY,
0,
0,
VkContext->VkBodyBltWidth,
VkContext->VkBodyBltHeight,
VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
);
if (EFI_ERROR (Status)) {
FreePool (BltBuffer);
return Status;
}
if (CompareMem (BltBuffer, VkContext->VkBodyCompoundBltBuffer, VkContext->VkBodyBltSize) != 0) {
VkContext->IsBackgroundChanged = TRUE;
VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;
DrawKeyboardLayout (VkContext);
}
if (BltBuffer != NULL) {
FreePool (BltBuffer);
}
return Status;
}
/**
Get unicode by VkContext->PageNumber and VkContext->KeyboardBodyPtr.
@param[in] VkContext Address of an VK_CONTEXT structure.
@param[in] KeyItem Key Item.
@param[out] FontPtr Follow VkContext->PageNumber to translate
font unicode.
@retval EFI_SUCCESS Finish translating FontPtr.
@retval EFI_INVALID_PARAMETER VkContext or FontPtr is NULL.
**/
EFI_STATUS
VkGetMappingFont (
IN VK_CONTEXT *VkContext,
IN VK_STRUCT KeyItem,
OUT UINT32 *FontPtr
)
{
if ((VkContext == NULL) || (FontPtr == NULL) || (VkContext->PageNumber>=VkPageMaximum)) {
return EFI_INVALID_PARAMETER;
}
*FontPtr = (UINT32) KeyItem.PageFont[VkContext->PageNumber];
return EFI_SUCCESS;
}