#include #include #include #include "../OpenCanopy.h" #include "../GuiApp.h" #include #include #include #include "Common.h" // // FIXME: Create BootPickerView struct with background colour/image info. // GLOBAL_REMOVE_IF_UNREFERENCED INT64 mBackgroundImageOffsetX; GLOBAL_REMOVE_IF_UNREFERENCED INT64 mBackgroundImageOffsetY; GLOBAL_REMOVE_IF_UNREFERENCED GUI_INTERPOLATION mCommonIntroOpacityInterpol = { GuiInterpolTypeSmooth, 0, 25, 0, 0xFF, 0 }; STATIC UINT8 mCommonFocusState = 0; STATIC GUI_OBJ **mCommonFocusList = NULL; STATIC UINT8 mNumCommonFocusList = 0; VOID GuiDrawChildImage ( IN CONST GUI_IMAGE *Image, IN UINT8 Opacity, IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN INT64 ParentBaseX, IN INT64 ParentBaseY, IN INT64 ChildBaseX, IN INT64 ChildBaseY, IN UINT32 OffsetX, IN UINT32 OffsetY, IN UINT32 Width, IN UINT32 Height ) { BOOLEAN Result; ASSERT (Image != NULL); ASSERT (DrawContext != NULL); Result = GuiClipChildBounds ( ChildBaseX, Image->Width, &OffsetX, &Width ); if (Result) { Result = GuiClipChildBounds ( ChildBaseY, Image->Height, &OffsetY, &Height ); if (Result) { ASSERT (Image->Width > OffsetX); ASSERT (Image->Height > OffsetY); ASSERT (Image->Buffer != NULL); GuiDrawToBuffer ( Image, Opacity, DrawContext, ParentBaseX + ChildBaseX, ParentBaseY + ChildBaseY, OffsetX, OffsetY, Width, Height ); } } } BOOLEAN GuiClickableIsHit ( IN CONST GUI_IMAGE *Image, IN INT64 OffsetX, IN INT64 OffsetY ) { ASSERT (Image != NULL); ASSERT (Image->Buffer != NULL); if ( (OffsetX < 0) || (OffsetX >= Image->Width) || (OffsetY < 0) || (OffsetY >= Image->Height)) { return FALSE; } return Image->Buffer[(UINT32)OffsetY * Image->Width + (UINT32)OffsetX].Reserved > 0; } GUI_OBJ * InternalFocusKeyHandler ( IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *Context, IN CONST GUI_KEY_EVENT *KeyEvent ) { UINT8 CommonFocusState; GUI_OBJ *FocusChangedObj; if (KeyEvent->OcKeyCode == OC_INPUT_SWITCH_FOCUS) { if (mNumCommonFocusList > 1) { mCommonFocusList[mCommonFocusState]->Focus ( mCommonFocusList[mCommonFocusState], DrawContext, FALSE ); if ((KeyEvent->OcModifiers & OC_MODIFIERS_REVERSE_SWITCH_FOCUS) == 0) { CommonFocusState = mCommonFocusState + 1; if (CommonFocusState == mNumCommonFocusList) { CommonFocusState = 0; } } else { CommonFocusState = mCommonFocusState - 1; if (CommonFocusState == MAX_UINT8) { CommonFocusState = mNumCommonFocusList - 1; } } mCommonFocusState = CommonFocusState; mCommonFocusList[CommonFocusState]->Focus ( mCommonFocusList[CommonFocusState], DrawContext, TRUE ); FocusChangedObj = mCommonFocusList[CommonFocusState]; } else { FocusChangedObj = NULL; } } else { mCommonFocusList[mCommonFocusState]->KeyEvent ( mCommonFocusList[mCommonFocusState], DrawContext, Context, KeyEvent ); FocusChangedObj = NULL; } return FocusChangedObj; } VOID InternalResetFocus ( IN OUT GUI_DRAWING_CONTEXT *DrawContext ) { if (mCommonFocusState == 0) { return; } mCommonFocusList[mCommonFocusState]->Focus ( mCommonFocusList[mCommonFocusState], DrawContext, FALSE ); mCommonFocusState = 0; mCommonFocusList[mCommonFocusState]->Focus ( mCommonFocusList[mCommonFocusState], DrawContext, TRUE ); } VOID InternalCommonViewDraw ( IN OUT GUI_OBJ *This, IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *Context, IN INT64 BaseX, IN INT64 BaseY, IN UINT32 OffsetX, IN UINT32 OffsetY, IN UINT32 Width, IN UINT32 Height, IN UINT8 Opacity ) { ASSERT (This != NULL); ASSERT (DrawContext != NULL); ASSERT (Context != NULL); ASSERT (BaseX == 0); ASSERT (BaseY == 0); GuiDrawToBufferFill ( &Context->BackgroundColor.Pixel, DrawContext, OffsetX, OffsetY, Width, Height ); if (DrawContext->GuiContext->Background.Buffer != NULL) { GuiDrawChildImage ( &DrawContext->GuiContext->Background, 0xFF, DrawContext, 0, 0, mBackgroundImageOffsetX, mBackgroundImageOffsetY, OffsetX, OffsetY, Width, Height ); } GuiObjDrawDelegate ( This, DrawContext, Context, 0, 0, OffsetX, OffsetY, Width, Height, Opacity ); } GUI_OBJ * InternalCommonViewPtrEvent ( IN OUT GUI_OBJ *This, IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *Context, IN INT64 BaseX, IN INT64 BaseY, IN CONST GUI_PTR_EVENT *Event ) { InternalResetFocus (DrawContext); return GuiObjDelegatePtrEvent (This, DrawContext, Context, BaseX, BaseY, Event); } VOID InternalCommonSimpleButtonDraw ( IN OUT GUI_OBJ *This, IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *Context, IN INT64 BaseX, IN INT64 BaseY, IN UINT32 OffsetX, IN UINT32 OffsetY, IN UINT32 Width, IN UINT32 Height, IN UINT8 Opacity ) { CONST GUI_OBJ_CLICKABLE *Clickable; CONST GUI_IMAGE *ButtonImage; ASSERT (This != NULL); ASSERT (DrawContext != NULL); ASSERT (Context != NULL); // // There should be no children. // ASSERT (This->NumChildren == 0); Clickable = BASE_CR (This, GUI_OBJ_CLICKABLE, Hdr.Obj); ButtonImage = &Context->Icons[Clickable->ImageId][Clickable->ImageState]; ASSERT (ButtonImage != NULL); ASSERT (ButtonImage->Width == This->Width); ASSERT (ButtonImage->Height == This->Height); ASSERT (ButtonImage->Buffer != NULL); GuiDrawToBuffer ( ButtonImage, Opacity, DrawContext, BaseX, BaseY, OffsetX, OffsetY, Width, Height ); } UINT8 InternalCommonSimpleButtonPtrEvent ( IN OUT GUI_OBJ *This, IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *Context, IN INT64 BaseX, IN INT64 BaseY, IN CONST GUI_PTR_EVENT *Event ) { UINT8 Return; GUI_OBJ_CLICKABLE *Clickable; CONST GUI_IMAGE *ButtonImage; UINT8 ImageState; BOOLEAN IsHit; ASSERT (This != NULL); ASSERT (DrawContext != NULL); ASSERT (Context != NULL); // // There should be no children. // ASSERT (This->NumChildren == 0); // // Ignore double-clicks. // if (Event->Type == GuiPointerPrimaryDoubleClick) { return 1; } Clickable = BASE_CR (This, GUI_OBJ_CLICKABLE, Hdr.Obj); ImageState = ICON_TYPE_BASE; ButtonImage = &Context->Icons[Clickable->ImageId][ImageState]; Return = CommonPtrNotHit; IsHit = GuiClickableIsHit ( ButtonImage, Event->Pos.Pos.X - BaseX, Event->Pos.Pos.Y - BaseY ); if (IsHit) { if (Event->Type == GuiPointerPrimaryUp) { Return = CommonPtrAction; } else { ImageState = ICON_TYPE_HELD; Return = CommonPtrHit; } } if (Clickable->ImageState != ImageState) { Clickable->ImageState = ImageState; // // The view is constructed such that the selector is always fully visible. // ASSERT (BaseX >= 0); ASSERT (BaseY >= 0); ASSERT (BaseX + This->Width <= DrawContext->Screen.Width); ASSERT (BaseY + This->Height <= DrawContext->Screen.Height); GuiRequestDraw ((UINT32)BaseX, (UINT32)BaseY, This->Width, This->Height); } return Return; } VOID InternalCommonSimpleButtonFocusDraw ( IN OUT GUI_OBJ *This, IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *Context, IN INT64 BaseX, IN INT64 BaseY, IN UINT32 OffsetX, IN UINT32 OffsetY, IN UINT32 Width, IN UINT32 Height, IN UINT8 Opacity ) { ASSERT (This != NULL); ASSERT (DrawContext != NULL); ASSERT (Context != NULL); GuiDrawChildImage ( &Context->Icons[ICON_BUTTON_FOCUS][ICON_TYPE_BASE], Opacity, DrawContext, BaseX, BaseY, ((INT32)This->Width - (INT32)Context->Icons[ICON_BUTTON_FOCUS][ICON_TYPE_BASE].Width) / 2, ((INT32)This->Height - (INT32)Context->Icons[ICON_BUTTON_FOCUS][ICON_TYPE_BASE].Height) / 2, OffsetX, OffsetY, Width, Height ); // // There should be no children. // ASSERT (This->NumChildren == 0); } VOID InternalCommonShutDownKeyEvent ( IN OUT GUI_OBJ *This, IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *Context, IN CONST GUI_KEY_EVENT *KeyEvent ) { if ( (KeyEvent->OcKeyCode == OC_INPUT_CONTINUE) || (KeyEvent->OcKeyCode == OC_INPUT_TYPING_CONFIRM)) { if (Context->PickerContext->PickerAudioAssist) { Context->PickerContext->PlayAudioFile ( Context->PickerContext, APPLE_VOICE_OVER_AUDIO_FILE_BEEP, OC_VOICE_OVER_AUDIO_BASE_TYPE_APPLE, TRUE ); } ResetShutdown (); } } GUI_OBJ * InternalCommonShutDownPtrEvent ( IN OUT GUI_OBJ *This, IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *Context, IN INT64 BaseX, IN INT64 BaseY, IN CONST GUI_PTR_EVENT *Event ) { UINT8 Result; Result = InternalCommonSimpleButtonPtrEvent ( This, DrawContext, Context, BaseX, BaseY, Event ); switch (Result) { case CommonPtrNotHit: { return NULL; } case CommonPtrAction: { ResetShutdown (); // // Falthrough to 'hit' case. // } case CommonPtrHit: { break; } } return This; } VOID InternalCommonRestartKeyEvent ( IN OUT GUI_OBJ *This, IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *Context, IN CONST GUI_KEY_EVENT *KeyEvent ) { if ( (KeyEvent->OcKeyCode == OC_INPUT_CONTINUE) || (KeyEvent->OcKeyCode == OC_INPUT_TYPING_CONFIRM)) { if (Context->PickerContext->PickerAudioAssist) { Context->PickerContext->PlayAudioFile ( Context->PickerContext, APPLE_VOICE_OVER_AUDIO_FILE_BEEP, OC_VOICE_OVER_AUDIO_BASE_TYPE_APPLE, TRUE ); } ResetWarm (); } } GUI_OBJ * InternalCommonRestartPtrEvent ( IN OUT GUI_OBJ *This, IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *Context, IN INT64 BaseX, IN INT64 BaseY, IN CONST GUI_PTR_EVENT *Event ) { UINT8 Result; Result = InternalCommonSimpleButtonPtrEvent ( This, DrawContext, Context, BaseX, BaseY, Event ); switch (Result) { case CommonPtrNotHit: { return NULL; } case CommonPtrAction: { ResetWarm (); // // Falthrough to 'hit' case. // } case CommonPtrHit: { break; } } return This; } extern GUI_OBJ_CHILD mCommonFocus; STATIC GUI_OBJ_CHILD *mCommonActionButtonsContainerChildren[] = { &mCommonRestart.Hdr, &mCommonShutDown.Hdr, &mCommonFocus }; VOID InternalCommonActionButtonFocus ( IN CONST GUI_OBJ *This, IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOLEAN Focus ) { if (!Focus) { mCommonActionButtonsContainer.Obj.NumChildren = ARRAY_SIZE (mCommonActionButtonsContainerChildren) - 1; } else { mCommonActionButtonsContainer.Obj.NumChildren = ARRAY_SIZE (mCommonActionButtonsContainerChildren); GuiRequestDrawCrop ( DrawContext, mCommonActionButtonsContainer.Obj.OffsetX + mCommonFocus.Obj.OffsetX, mCommonActionButtonsContainer.Obj.OffsetY + mCommonFocus.Obj.OffsetY, mCommonFocus.Obj.Width, mCommonFocus.Obj.Height ); mCommonFocus.Obj.OffsetX = This->OffsetX + ((INT32)This->Width - (INT32)mCommonFocus.Obj.Width) / 2; mCommonFocus.Obj.OffsetY = This->OffsetY + ((INT32)This->Height - (INT32)mCommonFocus.Obj.Height) / 2; DrawContext->GuiContext->AudioPlaybackTimeout = 0; if (This == &mCommonShutDown.Hdr.Obj) { DrawContext->GuiContext->VoAction = CanopyVoFocusShutDown; } else { ASSERT (This == &mCommonRestart.Hdr.Obj); DrawContext->GuiContext->VoAction = CanopyVoFocusRestart; } } GuiRequestDrawCrop ( DrawContext, mCommonActionButtonsContainer.Obj.OffsetX + mCommonFocus.Obj.OffsetX, mCommonActionButtonsContainer.Obj.OffsetY + mCommonFocus.Obj.OffsetY, mCommonFocus.Obj.Width, mCommonFocus.Obj.Height ); } GLOBAL_REMOVE_IF_UNREFERENCED GUI_OBJ_CHILD mCommonFocus = { { 0, 0, 0, 0, 0xFF, InternalCommonSimpleButtonFocusDraw, NULL, GuiObjDelegatePtrEvent, NULL, 0, NULL }, &mCommonActionButtonsContainer.Obj }; GLOBAL_REMOVE_IF_UNREFERENCED GUI_OBJ_CLICKABLE mCommonRestart = { { { 0, 0, 0, 0, 0xFF, InternalCommonSimpleButtonDraw, InternalCommonRestartKeyEvent, InternalCommonRestartPtrEvent, InternalCommonActionButtonFocus, 0, NULL }, &mCommonActionButtonsContainer.Obj }, 0, 0 }; GLOBAL_REMOVE_IF_UNREFERENCED GUI_OBJ_CLICKABLE mCommonShutDown = { { { 0, 0, 0, 0, 0xFF, InternalCommonSimpleButtonDraw, InternalCommonShutDownKeyEvent, InternalCommonShutDownPtrEvent, InternalCommonActionButtonFocus, 0, NULL }, &mCommonActionButtonsContainer.Obj }, 0, 0 }; GLOBAL_REMOVE_IF_UNREFERENCED GUI_OBJ_CHILD mCommonActionButtonsContainer = { { 0, 0, 0, 0, 0, GuiObjDrawDelegate, NULL, GuiObjDelegatePtrEvent, NULL, ARRAY_SIZE (mCommonActionButtonsContainerChildren) - 1, mCommonActionButtonsContainerChildren }, NULL }; VOID CommonViewInitialize ( IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *GuiContext, IN CONST GUI_VIEW_CONTEXT *ViewContext ) { CONST GUI_IMAGE *FocusImage; CONST GUI_IMAGE *RestartImage; CONST GUI_IMAGE *ShutDownImage; UINT32 RestartWidth; UINT32 RestartHeight; UINT32 ShutDownWidth; UINT32 ShutDownHeight; ASSERT (GuiContext != NULL); mCommonFocusState = 0; mCommonFocusList = ViewContext->FocusList; mNumCommonFocusList = ViewContext->NumFocusList; GuiViewInitialize (DrawContext, GuiContext, ViewContext); mBackgroundImageOffsetX = DivS64x64Remainder ( (INT64)DrawContext->Screen.Width - GuiContext->Background.Width, 2, NULL ); mBackgroundImageOffsetY = DivS64x64Remainder ( (INT64)DrawContext->Screen.Height - GuiContext->Background.Height, 2, NULL ); FocusImage = &GuiContext->Icons[ICON_BUTTON_FOCUS][ICON_TYPE_BASE]; RestartImage = &GuiContext->Icons[ICON_RESTART][ICON_TYPE_BASE]; ShutDownImage = &GuiContext->Icons[ICON_SHUT_DOWN][ICON_TYPE_BASE]; mCommonFocus.Obj.OffsetX = 0; mCommonFocus.Obj.OffsetY = 0; mCommonFocus.Obj.Width = FocusImage->Width; mCommonFocus.Obj.Height = FocusImage->Height; RestartWidth = MAX (RestartImage->Width, FocusImage->Width); RestartHeight = MAX (RestartImage->Height, FocusImage->Height); ShutDownWidth = MAX (ShutDownImage->Width, FocusImage->Width); ShutDownHeight = MAX (ShutDownImage->Height, FocusImage->Height); mCommonRestart.Hdr.Obj.OffsetX = (RestartWidth - RestartImage->Width) / 2; mCommonRestart.Hdr.Obj.OffsetY = (RestartHeight - RestartImage->Height) / 2; mCommonRestart.Hdr.Obj.Width = RestartImage->Width; mCommonRestart.Hdr.Obj.Height = RestartImage->Height; mCommonRestart.ImageId = ICON_RESTART; mCommonRestart.ImageState = ICON_TYPE_BASE; mCommonShutDown.Hdr.Obj.OffsetX = RestartWidth + BOOT_ACTION_BUTTON_SPACE * GuiContext->Scale + (ShutDownWidth - ShutDownImage->Width) / 2; mCommonShutDown.Hdr.Obj.OffsetY = (ShutDownHeight - ShutDownImage->Height) / 2; mCommonShutDown.Hdr.Obj.Width = ShutDownImage->Width; mCommonShutDown.Hdr.Obj.Height = ShutDownImage->Height; mCommonShutDown.ImageId = ICON_SHUT_DOWN; mCommonShutDown.ImageState = ICON_TYPE_BASE; mCommonActionButtonsContainer.Obj.Width = RestartWidth + ShutDownWidth + BOOT_ACTION_BUTTON_SPACE * GuiContext->Scale; mCommonActionButtonsContainer.Obj.Height = MAX (RestartHeight, ShutDownHeight); mCommonActionButtonsContainer.Obj.OffsetX = (DrawContext->Screen.Width - mCommonActionButtonsContainer.Obj.Width) / 2; mCommonActionButtonsContainer.Obj.OffsetY = DrawContext->Screen.Height - mCommonActionButtonsContainer.Obj.Height - BOOT_ACTION_BUTTON_SPACE * GuiContext->Scale; }