diff --git a/Changelog.md b/Changelog.md index 6996fcb2638fa9436122b691a0f46b6567cc4a88..bc7da6d1b19bc4887aa3f31f2390190171364c02 100644 --- a/Changelog.md +++ b/Changelog.md @@ -12,6 +12,7 @@ OpenCore Changelog - Fixed creating log file when root file system is not writable - Fixed `DisableSingleUser` not being enabled in certain cases - Added `ForceBooterSignature` quirk for Mac EFI firmware +- Fixed OpenCanopy sometimes cutting off shown boot entries #### v0.6.7 - Fixed ocvalidate return code to be non-zero when issues are found diff --git a/Platform/OpenCanopy/GuiApp.h b/Platform/OpenCanopy/GuiApp.h index 6b9a6e46aa9c34423a0d855d8ff6eb9e576dc999..bec2c59f77637ae9a6dc6c0225912f253778cbc5 100644 --- a/Platform/OpenCanopy/GuiApp.h +++ b/Platform/OpenCanopy/GuiApp.h @@ -103,6 +103,11 @@ BootPickerViewInitialize ( IN GUI_CURSOR_GET_IMAGE GetCursorImage ); +VOID +BootPickerViewLateInitialize ( + VOID + ); + EFI_STATUS BootPickerEntriesAdd ( IN OC_PICKER_CONTEXT *Context, diff --git a/Platform/OpenCanopy/OcBootstrap.c b/Platform/OpenCanopy/OcBootstrap.c index 879aad2872d2b63f17fb6e0fd1feaefbe13e5765..4cb3e1fcd6f6216df0874d3487bad9f6aa8e1b40 100644 --- a/Platform/OpenCanopy/OcBootstrap.c +++ b/Platform/OpenCanopy/OcBootstrap.c @@ -130,6 +130,8 @@ OcShowMenuByOc ( } } + BootPickerViewLateInitialize (); + GuiRedrawAndFlushScreen (&mDrawContext); if (BootContext->PickerContext->PickerAudioAssist) { diff --git a/Platform/OpenCanopy/Views/BootPicker.c b/Platform/OpenCanopy/Views/BootPicker.c index dafc005a9db1b1483169e2c330e07b7e6e68faab..7520d7ed1f1673ceb34f96d159dc51674fbefc4e 100644 --- a/Platform/OpenCanopy/Views/BootPicker.c +++ b/Platform/OpenCanopy/Views/BootPicker.c @@ -272,30 +272,20 @@ InternalBootPickerSelectEntry ( INT64 InternelBootPickerScrollSelected ( - IN UINT32 Scale + VOID ) { CONST GUI_VOLUME_ENTRY *SelectedEntry; INT64 EntryOffsetX; - ASSERT (mBootPicker.SelectedEntry != NULL); + if (mBootPicker.SelectedEntry == NULL) { + return 0; + } // // If the selected entry is outside of the view, scroll it accordingly. - // This function is called every time an entry is added or changed by the - // user. Due to this internal design, the selected entry can never be outside - // of the view by more than one entry's size. // SelectedEntry = mBootPicker.SelectedEntry; EntryOffsetX = mBootPicker.Hdr.Obj.OffsetX + SelectedEntry->Hdr.Obj.OffsetX; - // - // If the selected element is off-screen, scroll the view such that it is at - // the very edge of the view. As the view's width bounds precisely a set of - // boot entries (i.e. there can never be a partial entry or extra padding), - // this is equivalent to scrolling one boot entry spot. - // This is done to achieve the correct offset during initialisation as the - // entries may be at "half-steps" due to centering. - // - ASSERT ((mBootPickerContainer.Obj.Width + BOOT_ENTRY_SPACE * Scale) % ((BOOT_ENTRY_WIDTH + BOOT_ENTRY_SPACE) * Scale) == 0); if (EntryOffsetX < 0) { return -EntryOffsetX; @@ -385,7 +375,7 @@ InternalBootPickerChangeEntry ( PrevEntry = This->SelectedEntry; InternalBootPickerSelectEntry (This, DrawContext, NewEntry); - ScrollOffset = InternelBootPickerScrollSelected (DrawContext->Scale); + ScrollOffset = InternelBootPickerScrollSelected (); if (ScrollOffset == 0) { // // To redraw the entry *and* the selector, draw the entire height of the @@ -1233,7 +1223,6 @@ BootPickerEntriesAdd ( BOOLEAN UseDiskLabel; BOOLEAN UseGenericLabel; BOOLEAN Result; - INT64 ScrollOffset; ASSERT (GuiContext != NULL); ASSERT (Entry != NULL); @@ -1447,11 +1436,6 @@ BootPickerEntriesAdd ( GuiContext->BootEntry = Entry; } - if (mBootPicker.SelectedEntry != NULL) { - ScrollOffset = InternelBootPickerScrollSelected (GuiContext->Scale); - mBootPicker.Hdr.Obj.OffsetX += ScrollOffset; - } - return EFI_SUCCESS; } @@ -1704,6 +1688,55 @@ BootPickerViewInitialize ( return EFI_SUCCESS; } +VOID +BootPickerViewLateInitialize ( + VOID + ) +{ + INT64 ScrollOffset; + CONST LIST_ENTRY *ListEntry; + CONST GUI_VOLUME_ENTRY *BootEntry; + INT64 FirstPosOffset; + + ASSERT (mBootPicker.SelectedEntry != NULL); + + ScrollOffset = InternelBootPickerScrollSelected (); + // + // If ScrollOffset is non-0, the selected entry will be aligned left- or + // right-most. The view holds a discrete amount of entries, so cut-offs are + // impossible. + // + if (ScrollOffset == 0) { + ListEntry = mBootPicker.Hdr.Obj.Children.BackLink; + ASSERT (ListEntry == &mBootPickerSelector.Hdr.Link); + + FirstPosOffset = 0; + // + // Last entry is always the selector. + // + ListEntry = ListEntry->BackLink; + // + // Find the first entry that is fully visible. + // + while (!IsNull (&mBootPicker.Hdr.Obj.Children, ListEntry)) { + BootEntry = BASE_CR (ListEntry, GUI_VOLUME_ENTRY, Hdr.Link); + if (mBootPicker.Hdr.Obj.OffsetX + BootEntry->Hdr.Obj.OffsetX < 0) { + break; + } + + FirstPosOffset = mBootPicker.Hdr.Obj.OffsetX + BootEntry->Hdr.Obj.OffsetX; + ListEntry = ListEntry->BackLink; + } + // + // Move the first fully visible boot entry to the very left to prevent + // cut-off entries. + // + ScrollOffset = -(INT64) FirstPosOffset; + } + + mBootPicker.Hdr.Obj.OffsetX += ScrollOffset; +} + VOID BootPickerViewDeinitialize ( IN OUT GUI_DRAWING_CONTEXT *DrawContext,