alder_lake_bios/Insyde/InsydeSetupPkg/Drivers/H2ODisplayEngineLocalMetroDxe/H2ODialogs/MetroDialog.c

996 lines
30 KiB
C

/** @file
Entry point and initial functions for H2O local Metro display engine driver
;******************************************************************************
;* Copyright (c) 2013 - 2021, 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 "H2ODisplayEngineLocalMetro.h"
#include "UiControls.h"
#include "H2ODialogs.h"
#include "MetroDialog.h"
#include "MetroUi.h"
#include <Library/ConsoleLib.h>
extern H2O_DISPLAY_ENGINE_METRO_PRIVATE_DATA *mMetroPrivate;
extern HWND gWnd;
extern EFI_ABSOLUTE_POINTER_STATE mPreviousAbsPtrState;
HWND mDialogWnd = NULL;
HWND mOverlayWnd = NULL;
H2O_FORM_BROWSER_D *mFbDialog;
BOOLEAN mTitleVisible;
BOOLEAN mIsSendForm;
typedef struct {
UINT8 Operand;
CHAR16 *ClassName;
} DIALOG_CLASS_NAME;
DIALOG_CLASS_NAME mDialogClassNameList[] = {
//{EFI_IFR_CHECKBOX_OP , L"H2OCheckboxDialog" },
{EFI_IFR_DATE_OP , L"H2ODateTimeDialog" },
{EFI_IFR_ONE_OF_OP , L"H2OOneOfInputDialog" },
{EFI_IFR_ORDERED_LIST_OP, L"H2OOrderedListDialog"},
{EFI_IFR_NUMERIC_OP , L"H2ONumericDialog" },
{EFI_IFR_PASSWORD_OP , L"H2OPasswordDialog" },
{EFI_IFR_STRING_OP , L"H2OStringDialog" },
{EFI_IFR_TIME_OP , L"H2ODateTimeDialog" },
{0 , NULL }
};
STATIC
CHAR16 *
GetClassNameByOperand (
IN UINT8 Operand
)
{
UINT32 Index;
if (Operand == 0) {
return NULL;
}
for (Index = 0; mDialogClassNameList[Index].Operand != 0; Index ++) {
if (mDialogClassNameList[Index].Operand == Operand) {
return mDialogClassNameList[Index].ClassName;
}
}
return NULL;
}
VOID
H2OCommonDialogWithHelpOnSetState (
UI_CONTROL *Control,
UI_STATE SetState,
UI_STATE ClearState
)
{
UI_CONTROL *Child;
if (SetState & UISTATE_FOCUSED) {
Child = UiFindChildByName (Control, L"DialogText");
UiSetAttribute (Child, L"textcolor", L"0xFFFFFFFF");
}
if (ClearState & UISTATE_FOCUSED) {
Child = UiFindChildByName (Control, L"DialogText");
UiSetAttribute (Child, L"textcolor", L"0xFFA8D2DF");
}
}
#if FixedPcdGet32(PcdH2OLmdeMultiLayout) == 0
CHAR16 *mCommonDialogChilds = L""
L"<VerticalLayout padding='40,30,40,30' background-color='@menucolor' name='PopUpDialog'>"
L"<VerticalLayout name='TitleLayout'>"
L"<Label padding='0,0,30,0' textcolor='0xFFFFFFFF' font-size='29' name='DialogTitle' height='80'/>"
L"<Label padding='0,0,45,0' textcolor='0xFFA8D2DF' font-size='19' name='DialogText'/>"
L"</VerticalLayout>"
L"<Control background-image='@DialogSeparator' background-color='0x0' name='DialogSeparator' height='10'/>"
L"<VerticalLayout>"
L"<HorizontalLayout padding='10,0,0,0' visibility='false' name='DialogPasswordInput' height='41'>"
L"<Label name='ConfirmNewPasswordLabel' height='41' width='119' font-size='16' background-color='0xFFF2F2F2' textcolor='0xFF4D4D4D'/>"
L"<VerticalLayout padding='6,8,6,8' background-color='0xFFF2F2F2' height='29'>"
L"<Control padding='1,1,1,1' background-color='0xFF999999' height='27'>"
L"<UiEdit name='ConfirmPasswordInput' focusbkcolor='@menulightcolor' height='20' padding='7,3,0,3' background-color='0xFFF2F2F2' password='true'/>"
L"</Control>"
L"</VerticalLayout>"
L"</HorizontalLayout>"
L"<HorizontalLayout padding='10,0,0,0' child-padding='2' name='DialogButtonList'/>"
L"</VerticalLayout>"
L"</VerticalLayout>";
CHAR16 *mCommonDialogWithHelpChilds = L""
L"<VerticalLayout padding='40,30,40,30' width='-1' float='true' name='HelpMenu' height='-1' background-color='@menucolor' name='Dialog'>"
L"<VerticalLayout name='TitleLayout'>"
L"<HorizontalLayout padding='0,0,8,0' min-height='50' height='wrap_content'>"
L"<Label width='200' textcolor='0xFFFFFFFF' font-size='29' name='DialogTitle' height='wrap_content'/>"
L"<Control padding='0,25,0,25' height='50'>"
L"<Texture width='50' height='50' name='DialogImage' background-image-style='stretch|light'/>"
L"</Control>"
L"</HorizontalLayout>"
L"<ScrollView taborder='20' name='DialogTextScrollView' vscrollbar='true' scale9grid='1,13,1,13'>"
L"<Label name='DialogText' height='wrap_content' width='match_parent' font-size='19' textcolor='0xFFA8D2DF'/>"
L"</ScrollView>"
L"</VerticalLayout>"
L"<VerticalLayout>"
L"<Control background-image='@DialogSeparator' background-color='0x0' height='2'/>"
L"<Control height='5'/>"
L"<Control name='Content'/>"
L"</VerticalLayout>"
L"</VerticalLayout>";
CHAR16 *mDialogWithoutSendFormChilds = L""
L"<VerticalLayout name='DialogWithoutSendForm'>"
L"<Control/>"
L"<Control background-color='@menucolor' name='parent' height='wrap_content'>"
L"<VerticalLayout padding='20,30,20,30' background-color='@menucolor' height='wrap_content'>"
L"<VerticalLayout name='TitleLayout' height='wrap_content'>"
L"<Label name='DialogTitle' text-align='center' height='40' visibility='false' font-size='19' textcolor='0xFFFFFFFF'/>"
L"<Label width='match_parent' textcolor='0xFFFFFFFF' font-size='19' name='DialogText' height='wrap_content'/>"
L"<Control height='15'/>"
L"<Control height='10' background-image='@DialogSeparator' background-color='0x0' background-image-style='center'/>"
L"<Control height='15'/>"
L"</VerticalLayout>"
L"<VerticalLayout padding='0,0,10,0' visibility='false' min-height='51' name='DialogPasswordInput' height='wrap_content'>"
L"<Label name='ConfirmNewPasswordLabel' height='wrap_content' padding='0,0,2,0' width='match_parent' font-size='18' textcolor='0xFFFFFFFF'/>"
L"<Control padding='2,2,2,2' background-color='0xFFCCCCCC' height='wrap_content'>"
L"<UiEdit name='ConfirmPasswordInput' focusbkcolor='0xFFFFFFFF' tabstop='true' height='20' padding='7,3,0,3' taborder='1' background-color='@menulightcolor' password='true'/>"
L"</Control>"
L"</VerticalLayout>"
L"<HorizontalLayout padding='1,0,0,0' child-padding='2' visibility='false' name='DialogButtonList' height='31'/>"
L"</VerticalLayout>"
L"<Texture name='FormHalo' float='true' height='-1' width='-1' background-image='@FormHalo' scale9grid='23,26,22,31'/>"
L"</Control>"
L"<Control/>"
L"</VerticalLayout>";
#endif
VOID
FreeDialogEvent (
IN H2O_FORM_BROWSER_D **DialogEvt
)
{
H2O_FORM_BROWSER_D *Event;
if (DialogEvt == NULL || *DialogEvt == NULL) {
return;
}
Event = *DialogEvt;
if (Event->TitleString != NULL) {
FreePool (Event->TitleString);
}
if (Event->BodyStringArray != NULL && Event->BodyStringCount != 0) {
FreeStringArray (Event->BodyStringArray, Event->BodyStringCount);
}
if (Event->BodyInputStringArray != NULL && Event->BodyInputCount != 0) {
FreeStringArray (Event->BodyInputStringArray, Event->BodyInputCount);
}
if (Event->ButtonStringArray != NULL && Event->ButtonCount != 0) {
FreeStringArray (Event->ButtonStringArray, Event->ButtonCount);
}
if (Event->BodyHiiValueArray != NULL && Event->BodyStringCount != 0) {
FreeHiiValueArray (Event->BodyHiiValueArray, Event->BodyStringCount);
}
if (Event->ButtonHiiValueArray != NULL && Event->ButtonCount != 0) {
FreeHiiValueArray (Event->ButtonHiiValueArray, Event->ButtonCount);
}
if (Event->ConfirmHiiValue.Type == EFI_IFR_TYPE_BUFFER && Event->ConfirmHiiValue.Buffer != NULL && Event->ConfirmHiiValue.BufferLen != 0) {
FreePool (Event->ConfirmHiiValue.Buffer);
}
FreePool (Event);
*DialogEvt = NULL;
}
H2O_FORM_BROWSER_D *
CopyDialogEvent (
IN H2O_FORM_BROWSER_D *SrcDialogEvt
)
{
H2O_FORM_BROWSER_D *DialogEvt;
if (SrcDialogEvt == NULL) {
return NULL;
}
DialogEvt = AllocateCopyPool (sizeof (H2O_FORM_BROWSER_D), SrcDialogEvt);
if (DialogEvt == NULL) {
return NULL;
}
if (SrcDialogEvt->TitleString != NULL) {
DialogEvt->TitleString = AllocateCopyPool (StrSize (SrcDialogEvt->TitleString), SrcDialogEvt->TitleString);
if (DialogEvt->TitleString == NULL) {
goto Error;
}
}
if (SrcDialogEvt->BodyStringArray != NULL && SrcDialogEvt->BodyStringCount != 0) {
DialogEvt->BodyStringArray = CopyStringArray (SrcDialogEvt->BodyStringArray, SrcDialogEvt->BodyStringCount);
if (DialogEvt->BodyStringArray == NULL) {
goto Error;
}
}
if (SrcDialogEvt->BodyInputStringArray != NULL && SrcDialogEvt->BodyInputCount != 0) {
DialogEvt->BodyInputStringArray = CopyStringArray (SrcDialogEvt->BodyInputStringArray, SrcDialogEvt->BodyInputCount);
if (DialogEvt->BodyInputStringArray == NULL) {
goto Error;
}
}
if (SrcDialogEvt->ButtonStringArray != NULL && SrcDialogEvt->ButtonCount != 0) {
DialogEvt->ButtonStringArray = CopyStringArray (SrcDialogEvt->ButtonStringArray, SrcDialogEvt->ButtonCount);
if (DialogEvt->ButtonStringArray == NULL) {
goto Error;
}
}
if (SrcDialogEvt->BodyHiiValueArray != NULL && SrcDialogEvt->BodyStringCount != 0) {
DialogEvt->BodyHiiValueArray = CopyHiiValueArray (SrcDialogEvt->BodyHiiValueArray, SrcDialogEvt->BodyStringCount);
if (DialogEvt->BodyHiiValueArray == NULL) {
goto Error;
}
}
if (SrcDialogEvt->ButtonHiiValueArray != NULL && SrcDialogEvt->ButtonCount != 0) {
DialogEvt->ButtonHiiValueArray = CopyHiiValueArray (SrcDialogEvt->ButtonHiiValueArray, SrcDialogEvt->ButtonCount);
if (DialogEvt->ButtonHiiValueArray == NULL) {
goto Error;
}
}
if (SrcDialogEvt->ConfirmHiiValue.Type == EFI_IFR_TYPE_BUFFER && SrcDialogEvt->ConfirmHiiValue.Buffer != NULL && SrcDialogEvt->ConfirmHiiValue.BufferLen != 0) {
DialogEvt->ConfirmHiiValue.Buffer = AllocateCopyPool (SrcDialogEvt->ConfirmHiiValue.BufferLen, SrcDialogEvt->ConfirmHiiValue.Buffer);
if (DialogEvt->ConfirmHiiValue.Buffer == NULL) {
goto Error;
}
}
return DialogEvt;
Error:
FreeDialogEvent (&DialogEvt);
return NULL;
}
STATIC
HWND
CreateModalDialog (
CHAR16 *ClassName,
HINSTANCE Instance,
HWND ParentWnd,
LPARAM Param,
INT32 X,
INT32 Y,
INT32 Width,
INT32 Height,
BOOLEAN CloseDlgWhenTouchOutside
)
{
UI_DIALOG *DialogData;
HWND Dlg;
UI_CONTROL *Control;
UI_MANAGER *Manager;
DialogData = AllocateZeroPool (sizeof (UI_DIALOG));
if (DialogData == NULL) {
return NULL;
}
DialogData->Instance = Instance;
DialogData->ParentWnd = ParentWnd;
DialogData->Param = Param;
DialogData->Running = TRUE;
DialogData->CloseDlgWhenTouchOutside = CloseDlgWhenTouchOutside;
Dlg = CreateWindowEx (
WS_EX_NOACTIVATE, ClassName, L"", WS_VISIBLE | WS_POPUP,
X, Y, Width, Height, ParentWnd, NULL, Instance, DialogData
);
// ASSERT (Dlg != NULL);
if (Dlg == NULL) {
return NULL;
}
Control = (UI_CONTROL *) (UINTN) GetWindowLongPtr (Dlg, 0);
Manager = Control->Manager;
SetWindowLongPtr (Control->Wnd, GWLP_USERDATA, (INTN)mFbDialog);
SendMessage (Manager->MainWnd, UI_NOTIFY_WINDOWINIT, (WPARAM)Manager->Root, 0);
return Dlg;
}
BOOLEAN
ClickOnOutsideOfDlgRegion (
IN EFI_ABSOLUTE_POINTER_STATE *AbsPtrState
)
{
RECT DlgRect;
POINT Pt;
ASSERT (mDialogWnd != NULL);
ASSERT (AbsPtrState != NULL);
if (GetCapture () != NULL) {
return FALSE;
}
if (AbsPtrState->ActiveButtons == 0) {
return FALSE;
}
Pt.x = (INT32) AbsPtrState->CurrentX;
Pt.y = (INT32) AbsPtrState->CurrentY;
GetWindowRect (mDialogWnd, &DlgRect);
if (PtInRect (&DlgRect, Pt)) {
return FALSE;
}
return TRUE;
}
UINT32
GetButtonWidthByStr (
VOID
)
{
UINT32 Index;
UINT32 ButtonWidth;
ButtonWidth = 0;
for (Index = 0; Index < mFbDialog->ButtonCount; Index++) {
if (mFbDialog->ButtonStringArray[Index] != NULL) {
ButtonWidth = (UINT32) MAX (GetStringWidth (mFbDialog->ButtonStringArray[Index]), ButtonWidth);
}
}
return (ButtonWidth * 5 + 4);
}
VOID
EnableTitle (
HWND Wnd,
BOOLEAN Enable
)
{
CHAR16 *Str;
UI_DIALOG *Dialog;
UI_CONTROL *Control;
HWND FocusedWnd;
//
// Prevent from button location change to cause invalid button press, NOT do
// enable/disable password during this period.
//
FocusedWnd = GetFocus ();
Control = (UI_CONTROL *) GetWindowLongPtr (FocusedWnd, 0);
if (Control != NULL && (StrCmp (Control->Name, L"Ok") == 0 ||
StrCmp (Control->Name, L"Cancel") == 0) &&
(CONTROL_CLASS_GET_STATE(Control) & UISTATE_PRESSED)) {
return;
}
Dialog = (UI_DIALOG *) GetWindowLongPtr (Wnd, 0);
Str = Enable ? L"true" : L"false";
Control = UiFindChildByName (Dialog, L"TitleLayout");
UiSetAttribute (Control, L"visibility", Str);
mTitleVisible = Enable;
CONTROL_CLASS_INVALIDATE (Dialog);
}
LRESULT
WINAPI
DialogCallback (
HWND Wnd,
UINT Msg,
WPARAM WParam,
LPARAM LParam
)
{
KEYBOARD_ATTRIBUTES KeyboardAttributes;
if (mSetupMouse == NULL) {
return 0;
}
mSetupMouse->GetKeyboardAttributes (mSetupMouse, &KeyboardAttributes);
if (KeyboardAttributes.IsStart && mTitleVisible) {
EnableTitle (Wnd, FALSE);
} else if (!KeyboardAttributes.IsStart && !mTitleVisible) {
EnableTitle (Wnd, TRUE);
}
return 0;
}
EFI_STATUS
GetDialogRegion (
IN CHAR16 *PanelName,
OUT RECT *DlgRect
)
{
EFI_STATUS Status;
RECT PanelRect;
UINT32 PanelWidth;
UINT32 PanelHeight;
UINT32 DlgWidth;
UINT32 DlgHeight;
ASSERT (PanelName != NULL);
ASSERT (DlgRect != NULL);
Status = GetRectByName (gWnd, PanelName, &PanelRect);
if (EFI_ERROR (Status)) {
return Status;
}
PanelWidth = PanelRect.right - PanelRect.left;
PanelHeight = PanelRect.bottom - PanelRect.top;
if ((mFbDialog->DialogType & H2O_FORM_BROWSER_D_TYPE_QUESTIONS) == 0) {
if ((mFbDialog->DialogType & H2O_FORM_BROWSER_D_TYPE_SELECTION) == H2O_FORM_BROWSER_D_TYPE_SELECTION) {
DlgWidth = 360;
DlgHeight = PanelHeight;
} else if ((mFbDialog->DialogType & H2O_FORM_BROWSER_D_TYPE_MSG ) == H2O_FORM_BROWSER_D_TYPE_MSG ||
(mFbDialog->DialogType & H2O_FORM_BROWSER_D_TYPE_CONFIRM) == H2O_FORM_BROWSER_D_TYPE_CONFIRM) {
DlgWidth = 360;
DlgHeight = PanelHeight;
} else if ((mFbDialog->DialogType & H2O_FORM_BROWSER_D_TYPE_SHOW_CONFIRM_PAGE) == H2O_FORM_BROWSER_D_TYPE_SHOW_CONFIRM_PAGE) {
DlgWidth = PanelWidth;
DlgHeight = PanelHeight;
} else {
return EFI_UNSUPPORTED;
}
} else {
switch (GetOpCodeByDialogType (mFbDialog->DialogType)) {
case EFI_IFR_ONE_OF_OP:
DlgWidth = PanelWidth;
DlgHeight = PanelHeight;
break;
case EFI_IFR_NUMERIC_OP:
DlgWidth = 360;
DlgHeight = 200;
break;
case EFI_IFR_PASSWORD_OP:
DlgWidth = 400;
DlgHeight = PanelHeight;
break;
default:
return EFI_UNSUPPORTED;
break;
}
}
DlgRect->left = PanelRect.left + ((PanelWidth - DlgWidth) / 2);
DlgRect->top = PanelRect.top + ((PanelHeight - DlgHeight) / 2);
DlgRect->right = DlgRect->left + DlgWidth;
DlgRect->bottom = DlgRect->top + DlgHeight;
return EFI_SUCCESS;
}
HWND
FindOverlayDialog (
)
{
UI_CONTROL *Control;
UI_CONTROL *Overlay;
UI_MANAGER *Manager;
Control = GetUiControl (gWnd);
Manager = Control->Manager;
Overlay = Manager->FindControlByName (Manager, L"overlay");
if (Overlay != NULL) {
CONTROL_CLASS(Overlay)->SetAttribute (Overlay, L"visibility", L"true");
return Overlay->Wnd;
}
return NULL;
}
HWND
LocalMetroCreateDialog (
IN CONST H2O_DISPLAY_ENGINE_EVT *Notify
)
{
HWND Wnd;
H2O_DISPLAY_ENGINE_EVT_OPEN_D *OpenDNotify;
H2O_FORM_BROWSER_D *Dialog;
BOOLEAN CloseOnTouchOutside;
UINT8 OpCode;
HWND ParentWnd;
RECT DlgRect;
EFI_STATUS Status;
INT32 Id;
CHAR16 *ClassName;
EFI_GUID PopUpFormsetId;
UINT16 PopUpFormId;
OpenDNotify = (H2O_DISPLAY_ENGINE_EVT_OPEN_D *) Notify;
Dialog = &OpenDNotify->Dialog;
Wnd = NULL;
if (gFB->CurrentP != NULL) {
CloseOnTouchOutside = TRUE;
mIsSendForm = TRUE;
} else {
CloseOnTouchOutside = FALSE;
mIsSendForm = FALSE;
ZeroMem (&mPreviousAbsPtrState, sizeof (EFI_ABSOLUTE_POINTER_STATE));
}
SetRectEmpty (&DlgRect);
ParentWnd = GetFocus();
mFbDialog = Dialog;
if (mIsSendForm) {
Status = GetRectByName (gWnd, L"H2OHelpTextPanel", &DlgRect);
} else {
Status = GetDialogRegion (L"DialogPanel", &DlgRect);
}
ASSERT_EFI_ERROR (Status);
if ((Dialog->DialogType & H2O_FORM_BROWSER_D_TYPE_QUESTIONS) == 0) {
if ((Dialog->DialogType & H2O_FORM_BROWSER_D_TYPE_SHOW_HELP) == H2O_FORM_BROWSER_D_TYPE_SHOW_HELP) {
Status = GetInformationField (&DlgRect);
ASSERT (!EFI_ERROR (Status));
ClassName = L"H2OHelpDialog";
} else if ((Dialog->DialogType & H2O_FORM_BROWSER_D_TYPE_SHOW_CONFIRM_PAGE) == H2O_FORM_BROWSER_D_TYPE_SHOW_CONFIRM_PAGE) {
Status = GetInformationField (&DlgRect);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_INFO, "GetInformationField(): %r", Status));
}
ClassName = L"H2OConfirmPageDialog";
} else if ((Dialog->DialogType & H2O_FORM_BROWSER_D_TYPE_SELECTION) == H2O_FORM_BROWSER_D_TYPE_SELECTION) {
mFbDialog = CopyDialogEvent (Dialog);
if (mFbDialog == NULL) {
return NULL;
}
ClassName = L"H2OPopupDialog";
} else if ((Dialog->DialogType & H2O_FORM_BROWSER_D_TYPE_MSG ) == H2O_FORM_BROWSER_D_TYPE_MSG ||
(Dialog->DialogType & H2O_FORM_BROWSER_D_TYPE_CONFIRM) == H2O_FORM_BROWSER_D_TYPE_CONFIRM) {
mFbDialog = CopyDialogEvent (Dialog);
if (mFbDialog == NULL) {
return NULL;
}
ClassName = L"H2OMsgPopUpDialog";
} else {
return NULL;
}
} else {
OpCode = GetOpCodeByDialogType (Dialog->DialogType);
mFbDialog = CopyDialogEvent (Dialog);
if (mFbDialog == NULL) {
return NULL;
}
//
// Question dialog is determined by Pop Up form (highest priority), VFCF control-type or LMDE XML strings (lowest priority).
//
ClassName = NULL;
if (GetPopUpForm (mFbDialog->H2OStatement, &PopUpFormsetId, &PopUpFormId) == EFI_SUCCESS) {
GetPopUpFormRect (&PopUpFormsetId, PopUpFormId, &DlgRect);
ClassName = L"H2OFormDialog";
}
if (ClassName == NULL) {
ClassName = GetClassNameBySetupPageStatementControlType (mFbDialog->H2OStatement);
}
if (ClassName == NULL) {
ClassName = GetClassNameByOperand (OpCode);
}
if (ClassName == NULL) {
ClassName = L"DIALOG";
}
switch (OpCode) {
case EFI_IFR_NUMERIC_OP:
case EFI_IFR_ORDERED_LIST_OP:
case EFI_IFR_CHECKBOX_OP:
case EFI_IFR_PASSWORD_OP:
case EFI_IFR_STRING_OP:
//
// TODO: Need receive and sending H2O_DISPLAY_ENGINE_EVT_TYPE_CHANGING_Q to synchronize
// with other display engine.
//
CloseOnTouchOutside = FALSE;
break;
case EFI_IFR_ONE_OF_OP:
case EFI_IFR_DATE_OP:
case EFI_IFR_TIME_OP:
break;
default:
ASSERT (FALSE);
break;
}
}
Id = 1;
while (TRUE) {
if (!UnregisterHotKey (Wnd, Id++)) {
break;
}
}
Wnd = CreateModalDialog (
ClassName,
NULL,
ParentWnd,
0,
DlgRect.left,
DlgRect.top,
DlgRect.right - DlgRect.left,
DlgRect.bottom - DlgRect.top,
CloseOnTouchOutside
);
MwRegisterHotKey (Wnd, 1, 0, VK_ESCAPE);
return Wnd;
}
VOID
LocalMetroRegisterHotkey (
HWND Wnd
);
HWND
GetNextTabItemByTabOrder (
IN HWND Dialog,
IN UI_CONTROL *Current,
IN BOOL Previous
)
{
INTN Style;
INTN ExStyle;
HWND Child;
HWND Node;
UI_CONTROL *Candidate;
UI_CONTROL *Next;
UI_CONTROL *Control;
Next = NULL;
Candidate = NULL;
Node = GetWindow (Dialog, GW_CHILD);
while (Node != NULL && Node != Dialog) {
Child = GetWindow (Node, GW_CHILD);
Style = GetWindowLongPtr (Node, GWL_STYLE);
ExStyle = GetWindowLongPtr (Node, GWL_EXSTYLE);
do {
if (!((Style & WS_VISIBLE) && !(Style & WS_DISABLED))) {
Child = NULL;
break;
}
if (!(ExStyle & WS_EX_CONTROLPARENT)) {
Child = NULL;
break;
}
if (Style & WS_TABSTOP) {
Child = NULL;
Control = GetUiControl (Node);
ASSERT (Control != NULL);
if (Control == NULL) {
break;
}
if (Control->TabOrder == (Current->TabOrder + 1)) {
return Control->Wnd;
}
if ((Control->TabOrder > Current->TabOrder) &&
((Next == NULL) || (Next->TabOrder > Control->TabOrder))) {
Next = Control;
}
if ((Control->TabOrder < Current->TabOrder) &&
((Candidate == NULL) || (Candidate->TabOrder > Control->TabOrder))) {
Candidate = Control;
}
}
} while (0);
if (Child != NULL) {
Node = Child;
} else if (GetWindow (Node, GW_HWNDNEXT) != NULL) {
Node = GetWindow (Node, GW_HWNDNEXT);
} else {
Node = GetParent (Node);
while (Node != NULL && Node != Dialog) {
if (GetWindow (Node, GW_HWNDNEXT) != NULL) {
Node = GetWindow (Node, GW_HWNDNEXT);
break;
} else {
Node = GetParent (Node);
}
}
}
}
if (Next == NULL) {
Next = Candidate;
}
if (Next != NULL) {
return Next->Wnd;
}
return NULL;
}
HWND
GetNextTabItem (
IN HWND MainWnd,
IN HWND DlgWnd,
IN HWND CtrlWnd,
IN BOOL Previous
)
{
INTN Style;
INTN ExStyle;
UINT32 WndSearch;
HWND ChildFirst;
HWND RetWnd;
WndSearch = Previous ? GW_HWNDPREV : GW_HWNDNEXT;
if (DlgWnd == CtrlWnd) {
CtrlWnd = NULL;
}
ChildFirst = NULL;
RetWnd = NULL;
if (!CtrlWnd) {
ChildFirst = GetWindow (DlgWnd, GW_CHILD);
if (Previous) {
ChildFirst = GetWindow (ChildFirst, GW_HWNDLAST);
}
} else if (IsChild (MainWnd, CtrlWnd)) {
ChildFirst = GetWindow (CtrlWnd, WndSearch);
if (!ChildFirst) {
if (GetParent (CtrlWnd) != MainWnd) {
ChildFirst = GetWindow (GetParent (CtrlWnd), WndSearch);
} else {
ChildFirst = GetWindow (CtrlWnd, Previous ? GW_HWNDLAST : GW_HWNDFIRST);
}
}
}
while (ChildFirst != NULL) {
Style = GetWindowLongPtr (ChildFirst, GWL_STYLE);
ExStyle = GetWindowLongPtr (ChildFirst, GWL_EXSTYLE);
if ((Style & WS_TABSTOP) && (Style & WS_VISIBLE) && !(Style & WS_DISABLED)) {
return ChildFirst;
} else if ((ExStyle & WS_EX_CONTROLPARENT) && (Style & WS_VISIBLE) && !(Style &WS_DISABLED)) {
RetWnd = GetNextTabItem (MainWnd, ChildFirst, NULL, Previous);
if (RetWnd != NULL) {
return RetWnd;
}
}
ChildFirst = GetWindow (ChildFirst, WndSearch);
}
if (CtrlWnd != NULL) {
HWND Parent;
Parent = GetParent (CtrlWnd);
while (Parent != NULL) {
if (Parent == MainWnd) {
break;
}
RetWnd = GetNextTabItem (MainWnd, GetParent (Parent), Parent, Previous);
if (RetWnd != NULL) {
break;
}
}
if(RetWnd == NULL) {
RetWnd = GetNextTabItem (MainWnd, MainWnd, NULL, Previous);
}
}
return RetWnd ? RetWnd : CtrlWnd;
}
BOOLEAN
IsUiDialogMessage (
HWND DlgWnd,
LPMSG Msg
)
{
HWND Focus;
HWND Next;
LRESULT DlgCode;
if (Msg->message == WM_TIMER) {
return FALSE;
}
if ((DlgWnd != Msg->hwnd) && !IsChild(DlgWnd, Msg->hwnd)) {
return FALSE;
}
switch(Msg->message)
{
case WM_KEYDOWN:
DlgCode = SendMessage (Msg->hwnd, WM_GETDLGCODE, Msg->wParam, (LPARAM) Msg);
if (DlgCode & (DLGC_WANTMESSAGE)) break;
switch (Msg->wParam) {
case VK_TAB:
if (DlgCode & DLGC_WANTTAB) break;
Focus = GetFocus ();
Next = GetNextTabItemByTabOrder (DlgWnd, GetUiControl (Focus), FALSE);
if (Next == NULL) {
Next = GetNextTabItem (DlgWnd, DlgWnd, Focus == DlgWnd ? NULL : Focus, FALSE);
}
if (Next != NULL) {
SetFocus (Next);
return TRUE;
}
break;
}
}
TranslateMessage (Msg);
DispatchMessage (Msg);
return TRUE;
}
EFI_STATUS
EFIAPI
LocalMetroDialogNotify (
IN H2O_DISPLAY_ENGINE_PROTOCOL *This,
IN CONST H2O_DISPLAY_ENGINE_EVT *Notify
)
{
MSG Msg;
H2O_DISPLAY_ENGINE_EVT_ABS_PTR_MOVE *AbsPtr;
H2O_DISPLAY_ENGINE_EVT_KEYPRESS *KeyPress;
UI_DIALOG *Dialog;
UI_CONTROL *Control;
STATIC HWND FocusWnd = NULL;
switch (Notify->Type) {
case H2O_DISPLAY_ENGINE_EVT_TYPE_OPEN_D:
if (mDialogWnd != NULL) {
if (((H2O_DISPLAY_ENGINE_EVT_OPEN_D *) Notify)->Dialog.DialogType != mFbDialog->DialogType) {
return EFI_ALREADY_STARTED;
}
EnableWindow (gWnd, FALSE);
EnableWindow (GetDesktopWindow(), FALSE);
Control = (UI_CONTROL *) GetWindowLongPtr (mDialogWnd, 0);
CONTROL_CLASS_INVALIDATE (Control );
LocalMetroRegisterHotkey (mDialogWnd);
if (FocusWnd != NULL) {
SetFocus (FocusWnd);
FocusWnd = NULL;
}
break;
}
EnableWindow (gWnd, FALSE);
EnableWindow (GetDesktopWindow(), FALSE);
mDialogWnd = LocalMetroCreateDialog (Notify);
if (mDialogWnd == NULL) {
SendShutDNotify ();
}
GrayOutBackground (gWnd, TRUE);
break;
case H2O_DISPLAY_ENGINE_EVT_TYPE_SHUT_D:
if (mDialogWnd != NULL) {
if (!(mFbDialog->DialogType == (H2O_FORM_BROWSER_D_TYPE_MSG|H2O_FORM_BROWSER_D_TYPE_FROM_H2O_DIALOG))) {
DestroyWindow(mDialogWnd);
mDialogWnd = NULL;
}
}
This->Notify = LocalMetroNotify;
EnableWindow (gWnd, TRUE);
GrayOutBackground (gWnd, FALSE);
SetFocus (gWnd);
LocalMetroRegisterHotkey (gWnd);
break;
case H2O_DISPLAY_ENGINE_EVT_TYPE_OPEN_L:
case H2O_DISPLAY_ENGINE_EVT_TYPE_OPEN_P:
//
// OPEN_L and OPEN_P should be handled by LocalMetroNotify. For example: Triggering repaint in dialog screen.
//
FocusWnd = GetFocus ();
This->Notify = LocalMetroNotify;
This->Notify (This, Notify);
break;
case H2O_DISPLAY_ENGINE_EVT_TYPE_ABS_PTR_MOVE:
AbsPtr = (H2O_DISPLAY_ENGINE_EVT_ABS_PTR_MOVE *) Notify;
Dialog = (UI_DIALOG *) GetWindowLongPtr (mDialogWnd, 0);
if (Dialog->CloseDlgWhenTouchOutside && ClickOnOutsideOfDlgRegion (&AbsPtr->AbsPtrState) && mPreviousAbsPtrState.ActiveButtons == 0) {
CopyMem (&mPreviousAbsPtrState, &AbsPtr->AbsPtrState, sizeof (EFI_ABSOLUTE_POINTER_STATE));
SendShutDNotify ();
break;
}
CopyMem (&mPreviousAbsPtrState, &AbsPtr->AbsPtrState, sizeof (EFI_ABSOLUTE_POINTER_STATE));
GdAddPointerData (NULL, &AbsPtr->AbsPtrState);
break;
case H2O_DISPLAY_ENGINE_EVT_TYPE_KEYPRESS:
KeyPress = (H2O_DISPLAY_ENGINE_EVT_KEYPRESS *) Notify;
GdAddEfiKeyData (&KeyPress->KeyData);
break;
case H2O_DISPLAY_ENGINE_EVT_TYPE_TIMER:
if (((H2O_DISPLAY_ENGINE_EVT_TIMER *) Notify)->TimerId == H2O_METRO_DE_TIMER_ID_PERIODIC_TIMER) {
RegisterTimerEvent (H2O_METRO_DE_TIMER_ID_PERIODIC_TIMER, H2O_METRO_DE_TIMER_PERIODIC_TIME);
}
break;
case H2O_DISPLAY_ENGINE_EVT_TYPE_REFRESH_Q:
break;
case H2O_DISPLAY_ENGINE_EVT_TYPE_CHANGING_Q:
break;
case H2O_DISPLAY_ENGINE_EVT_TYPE_SUBMIT_EXIT:
break;
default:
ASSERT (FALSE);
}
while (PeekMessage (&Msg, NULL, 0, 0, PM_REMOVE)) {
if (Msg.message == WM_RBUTTONUP && GetCapture () == NULL) {
SendMessage (mDialogWnd, WM_HOTKEY, 0, MAKELPARAM(0, VK_ESCAPE));
} else if (mDialogWnd == NULL || !IsUiDialogMessage (mDialogWnd, &Msg)) {
TranslateMessage (&Msg);
DispatchMessage (&Msg);
}
}
return EFI_SUCCESS;
}