OpenCanopy: Support basic keyboard-based scrolling
@@ -185,6 +185,39 @@ InternalBootPickerSelectEntry (
Selector->Obj.OffsetX += (VolumeEntryObj->Width - Selector->Obj.Width) / 2;
}
+INT64
+InternelBootPickerScrollSelected (
+ IN UINT32 Scale
+ )
+{
+ CONST GUI_VOLUME_ENTRY *SelectedEntry;
+ INT64 EntryOffsetX;
+ INT64 ScrollDelta;
+
+ ASSERT (mBootPicker.SelectedEntry != NULL);
+ //
+ // If the selected entry is outside of the view, scroll it accordingly.
+ // This function is called every time an entry is added or changed.
+ // 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;
+ ScrollDelta = (BOOT_ENTRY_WIDTH + BOOT_ENTRY_SPACE) * Scale;
+
+ if (EntryOffsetX < 0) {
+ mBootPicker.Hdr.Obj.OffsetX += ScrollDelta;
+ return ScrollDelta;
+ }
+
+ if (EntryOffsetX + SelectedEntry->Hdr.Obj.Width > mBootPickerView.Width) {
+ mBootPicker.Hdr.Obj.OffsetX -= ScrollDelta;
+ return -ScrollDelta;
+ }
+
+ return 0;
+}
+
VOID
InternalBootPickerChangeEntry (
IN OUT GUI_VOLUME_PICKER *This,
@@ -195,6 +228,9 @@ InternalBootPickerChangeEntry (
)
{
GUI_VOLUME_ENTRY *PrevEntry;
+ INT64 ScrollOffset;
+ INT64 DrawX;
+ UINT32 DrawWidth;
ASSERT (This != NULL);
ASSERT (DrawContext != NULL);
@@ -211,6 +247,8 @@ InternalBootPickerChangeEntry (
PrevEntry = This->SelectedEntry;
InternalBootPickerSelectEntry (This, NewEntry);
+ ScrollOffset = InternelBootPickerScrollSelected (DrawContext->Scale);
+ if (ScrollOffset == 0) {
//
// To redraw the entry *and* the selector, draw the entire height of the
// Picker object. For this, the height just reach from the top of the entries
@@ -233,6 +271,30 @@ InternalBootPickerChangeEntry (
This->Hdr.Obj.Height,
TRUE
);
+ } else {
+ //
+ // The X coordinate of the view changed by scrolling, so adjust it.
+ // The entire view plus an entry prior or following need to be drawn.
+ //
+ if (ScrollOffset < 0) {
+ DrawX = BaseX + ScrollOffset;
+ DrawWidth = (UINT32) (This->Hdr.Obj.Width - ScrollOffset);
+ } else {
+ DrawX = BaseX;
+ DrawWidth = (UINT32) (This->Hdr.Obj.Width + ScrollOffset);
+ }
+ //
+ // The entry list has been scrolled, redraw the entire view.
+ //
+ GuiDrawScreen (
+ DrawContext,
+ DrawX,
+ BaseY,
+ DrawWidth,
+ This->Hdr.Obj.Height,
+ TRUE
+ );
+ }
//
// Set voice timeout to N frames from now.
@@ -969,6 +1031,10 @@ BootPickerEntriesAdd (
GuiContext->BootEntry = Entry;
}
+ if (mBootPicker.SelectedEntry != NULL) {
+ InternelBootPickerScrollSelected (GuiContext->Scale);
+ }
+
return EFI_SUCCESS;
}
