Make the launcher more controllable via keyboard buttons

Selected button via tab now actually displays in active state, can use up/down to cycle through selected widget now too
This commit is contained in:
UnknownShadow200 2023-06-30 11:58:35 +10:00
parent 5c973cda53
commit 9b41a3312c
4 changed files with 49 additions and 34 deletions

View File

@ -401,17 +401,18 @@ void LBackend_ButtonUpdate(struct LButton* w) {
void LBackend_ButtonDraw(struct LButton* w) { void LBackend_ButtonDraw(struct LButton* w) {
struct DrawTextArgs args; struct DrawTextArgs args;
int xOffset, yOffset; int xOffset, yOffset;
cc_bool active = w->hovered || w->selected;
LButton_DrawBackground(&framebuffer, w->x, w->y, w->width, w->height, w->hovered); LButton_DrawBackground(&framebuffer, w->x, w->y, w->width, w->height, active);
xOffset = w->width - w->_textWidth; xOffset = w->width - w->_textWidth;
yOffset = w->height - w->_textHeight; yOffset = w->height - w->_textHeight;
DrawTextArgs_Make(&args, &w->text, &titleFont, true); DrawTextArgs_Make(&args, &w->text, &titleFont, true);
if (!w->hovered) Drawer2D.Colors['f'] = Drawer2D.Colors['7']; if (!active) Drawer2D.Colors['f'] = Drawer2D.Colors['7'];
Context2D_DrawText(&framebuffer, &args, Context2D_DrawText(&framebuffer, &args,
w->x + xOffset / 2, w->y + yOffset / 2); w->x + xOffset / 2, w->y + yOffset / 2);
if (!w->hovered) Drawer2D.Colors['f'] = Drawer2D.Colors['F']; if (!active) Drawer2D.Colors['f'] = Drawer2D.Colors['F'];
} }

View File

@ -59,9 +59,8 @@ void LScreen_UnselectWidget(struct LScreen* s, int idx, struct LWidget* w) {
if (w->VTABLE->OnUnselect) w->VTABLE->OnUnselect(w, idx); if (w->VTABLE->OnUnselect) w->VTABLE->OnUnselect(w, idx);
} }
static void LScreen_HandleTab(struct LScreen* s) { static void LScreen_CycleSelected(struct LScreen* s, int dir) {
struct LWidget* w; struct LWidget* w;
int dir = Input_IsShiftPressed() ? -1 : 1;
int index = 0, i, j; int index = 0, i, j;
if (s->selectedWidget) { if (s->selectedWidget) {
@ -82,9 +81,7 @@ static void LScreen_HandleTab(struct LScreen* s) {
} }
static void LScreen_KeyDown(struct LScreen* s, int key, cc_bool was) { static void LScreen_KeyDown(struct LScreen* s, int key, cc_bool was) {
if (key == IPT_TAB) { if (key == IPT_ENTER || key == IPT_KP_ENTER) {
LScreen_HandleTab(s);
} else if (key == IPT_ENTER || key == IPT_KP_ENTER) {
/* Shouldn't multi click when holding down Enter */ /* Shouldn't multi click when holding down Enter */
if (was) return; if (was) return;
@ -95,9 +92,20 @@ static void LScreen_KeyDown(struct LScreen* s, int key, cc_bool was) {
} else if (s->onEnterWidget) { } else if (s->onEnterWidget) {
s->onEnterWidget->OnClick(s->onEnterWidget); s->onEnterWidget->OnClick(s->onEnterWidget);
} }
} else if (s->selectedWidget) { return;
if (!s->selectedWidget->VTABLE->KeyDown) return; }
s->selectedWidget->VTABLE->KeyDown(s->selectedWidget, key, was);
/* Active widget takes input priority over default behaviour */
if (s->selectedWidget && s->selectedWidget->VTABLE->KeyDown) {
if (s->selectedWidget->VTABLE->KeyDown(s->selectedWidget, key, was)) return;
}
if (key == IPT_TAB) {
LScreen_CycleSelected(s, Input_IsShiftPressed() ? -1 : 1);
} else if (key == IPT_UP) {
LScreen_CycleSelected(s, -1);
} else if (key == IPT_DOWN) {
LScreen_CycleSelected(s, 1);
} }
} }
@ -1358,13 +1366,13 @@ static struct LWidget* settings_widgets[] = {
(struct LWidget*)&SettingsScreen.btnMode, (struct LWidget*)&SettingsScreen.lblMode, (struct LWidget*)&SettingsScreen.btnMode, (struct LWidget*)&SettingsScreen.lblMode,
(struct LWidget*)&SettingsScreen.btnColours, (struct LWidget*)&SettingsScreen.lblColours, (struct LWidget*)&SettingsScreen.btnColours, (struct LWidget*)&SettingsScreen.lblColours,
(struct LWidget*)&SettingsScreen.cbExtra, (struct LWidget*)&SettingsScreen.cbEmpty, (struct LWidget*)&SettingsScreen.cbExtra, (struct LWidget*)&SettingsScreen.cbEmpty,
(struct LWidget*)&SettingsScreen.btnBack, (struct LWidget*)&SettingsScreen.cbScale (struct LWidget*)&SettingsScreen.cbScale, (struct LWidget*)&SettingsScreen.btnBack
}; };
static struct LWidget* settings_classic[] = { static struct LWidget* settings_classic[] = {
(struct LWidget*)&SettingsScreen.sep, (struct LWidget*)&SettingsScreen.sep,
(struct LWidget*)&SettingsScreen.btnMode, (struct LWidget*)&SettingsScreen.lblMode, (struct LWidget*)&SettingsScreen.btnMode, (struct LWidget*)&SettingsScreen.lblMode,
(struct LWidget*)&SettingsScreen.cbExtra, (struct LWidget*)&SettingsScreen.cbEmpty, (struct LWidget*)&SettingsScreen.cbExtra, (struct LWidget*)&SettingsScreen.cbEmpty,
(struct LWidget*)&SettingsScreen.btnBack, (struct LWidget*)&SettingsScreen.cbScale (struct LWidget*)&SettingsScreen.cbScale, (struct LWidget*)&SettingsScreen.btnBack
}; };
LAYOUTS set_btnMode[] = { { ANCHOR_CENTRE, -135 }, { ANCHOR_CENTRE, -70 } }; LAYOUTS set_btnMode[] = { { ANCHOR_CENTRE, -135 }, { ANCHOR_CENTRE, -70 } };

View File

@ -30,9 +30,9 @@ void LWidget_CalcOffsets(void) {
/*########################################################################################################################* /*########################################################################################################################*
*------------------------------------------------------ButtonWidget-------------------------------------------------------* *------------------------------------------------------ButtonWidget-------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
static void LButton_DrawBase(struct Context2D* ctx, int x, int y, int width, int height, cc_bool hovered) { static void LButton_DrawBase(struct Context2D* ctx, int x, int y, int width, int height, cc_bool active) {
BitmapCol color = hovered ? Launcher_Theme.ButtonForeActiveColor BitmapCol color = active ? Launcher_Theme.ButtonForeActiveColor
: Launcher_Theme.ButtonForeColor; : Launcher_Theme.ButtonForeColor;
if (Launcher_Theme.ClassicBackground) { if (Launcher_Theme.ClassicBackground) {
Gradient_Noise(ctx, color, 8, Gradient_Noise(ctx, color, 8,
@ -67,12 +67,12 @@ static void LButton_DrawBorder(struct Context2D* ctx, int x, int y, int width, i
oneX, height - twoY); oneX, height - twoY);
} }
static void LButton_DrawHighlight(struct Context2D* ctx, int x, int y, int width, int height, cc_bool hovered) { static void LButton_DrawHighlight(struct Context2D* ctx, int x, int y, int width, int height, cc_bool active) {
BitmapCol activeColor = BitmapColor_RGB(189, 198, 255); BitmapCol activeColor = BitmapColor_RGB(189, 198, 255);
BitmapCol color = Launcher_Theme.ButtonHighlightColor; BitmapCol color = Launcher_Theme.ButtonHighlightColor;
if (Launcher_Theme.ClassicBackground) { if (Launcher_Theme.ClassicBackground) {
if (hovered) color = activeColor; if (active) color = activeColor;
Context2D_Clear(ctx, color, Context2D_Clear(ctx, color,
x + twoX, y + oneY, x + twoX, y + oneY,
@ -80,17 +80,17 @@ static void LButton_DrawHighlight(struct Context2D* ctx, int x, int y, int width
Context2D_Clear(ctx, color, Context2D_Clear(ctx, color,
x + oneX, y + twoY, x + oneX, y + twoY,
oneX, height - fourY); oneX, height - fourY);
} else if (!hovered) { } else if (!active) {
Context2D_Clear(ctx, color, Context2D_Clear(ctx, color,
x + twoX, y + oneY, x + twoX, y + oneY,
width - fourX, oneY); width - fourX, oneY);
} }
} }
void LButton_DrawBackground(struct Context2D* ctx, int x, int y, int width, int height, cc_bool hovered) { void LButton_DrawBackground(struct Context2D* ctx, int x, int y, int width, int height, cc_bool active) {
LButton_DrawBase( ctx, x, y, width, height, hovered); LButton_DrawBase( ctx, x, y, width, height, active);
LButton_DrawBorder( ctx, x, y, width, height); LButton_DrawBorder( ctx, x, y, width, height);
LButton_DrawHighlight(ctx, x, y, width, height, hovered); LButton_DrawHighlight(ctx, x, y, width, height, active);
} }
static void LButton_Draw(void* widget) { static void LButton_Draw(void* widget) {
@ -99,19 +99,19 @@ static void LButton_Draw(void* widget) {
} }
static void LButton_Hover(void* w, int idx, cc_bool wasOver) { static void LButton_Hover(void* w, int idx, cc_bool wasOver) {
/* only need to redraw when changing from unhovered to hovered */ /* only need to redraw when changing from unhovered to active */
if (!wasOver) LBackend_MarkDirty(w); if (!wasOver) LBackend_MarkDirty(w);
} }
static void LButton_Unhover(void* w) { static void LButton_Unhover(void* w) { LBackend_MarkDirty(w); }
LBackend_MarkDirty(w); static void LButton_OnSelect(void* w, int idx, cc_bool wasSelected) { LBackend_MarkDirty(w); }
} static void LButton_OnUnselect(void* w, int idx) { LBackend_MarkDirty(w); }
static const struct LWidgetVTABLE lbutton_VTABLE = { static const struct LWidgetVTABLE lbutton_VTABLE = {
LButton_Draw, NULL, LButton_Draw, NULL,
NULL, NULL, /* Key */ NULL, NULL, /* Key */
LButton_Hover, LButton_Unhover, /* Hover */ LButton_Hover, LButton_Unhover, /* Hover */
NULL, NULL /* Select */ LButton_OnSelect, LButton_OnUnselect /* Select */
}; };
void LButton_Init(struct LButton* w, int width, int height, const char* text, const struct LLayout* layouts) { void LButton_Init(struct LButton* w, int width, int height, const char* text, const struct LLayout* layouts) {
w->VTABLE = &lbutton_VTABLE; w->VTABLE = &lbutton_VTABLE;
@ -247,7 +247,7 @@ static void LInput_Delete(struct LInput* w) {
LBackend_InputUpdate(w); LBackend_InputUpdate(w);
} }
static void LInput_KeyDown(void* widget, int key, cc_bool was) { static cc_bool LInput_KeyDown(void* widget, int key, cc_bool was) {
struct LInput* w = (struct LInput*)widget; struct LInput* w = (struct LInput*)widget;
if (key == IPT_BACKSPACE) { if (key == IPT_BACKSPACE) {
LInput_Backspace(w); LInput_Backspace(w);
@ -263,7 +263,11 @@ static void LInput_KeyDown(void* widget, int key, cc_bool was) {
LInput_AdvanceCaretPos(w, false); LInput_AdvanceCaretPos(w, false);
} else if (key == IPT_RIGHT) { } else if (key == IPT_RIGHT) {
LInput_AdvanceCaretPos(w, true); LInput_AdvanceCaretPos(w, true);
} else {
return false;
} }
return true;
} }
static cc_bool LInput_CanAppend(struct LInput* w, char c) { static cc_bool LInput_CanAppend(struct LInput* w, char c) {
@ -564,7 +568,7 @@ cc_bool LTable_HandlesKey(int key) {
return key == IPT_UP || key == IPT_DOWN || key == IPT_PAGEUP || key == IPT_PAGEDOWN; return key == IPT_UP || key == IPT_DOWN || key == IPT_PAGEUP || key == IPT_PAGEDOWN;
} }
static void LTable_KeyDown(void* widget, int key, cc_bool was) { static cc_bool LTable_KeyDown(void* widget, int key, cc_bool was) {
struct LTable* w = (struct LTable*)widget; struct LTable* w = (struct LTable*)widget;
int index = LTable_GetSelectedIndex(w); int index = LTable_GetSelectedIndex(w);
@ -576,10 +580,11 @@ static void LTable_KeyDown(void* widget, int key, cc_bool was) {
index -= w->visibleRows; index -= w->visibleRows;
} else if (key == IPT_PAGEDOWN) { } else if (key == IPT_PAGEDOWN) {
index += w->visibleRows; index += w->visibleRows;
} else { return; } } else { return false; }
w->_lastRow = -1; w->_lastRow = -1;
LTable_SetSelectedTo(w, index); LTable_SetSelectedTo(w, index);
return true;
} }
static void LTable_MouseDown(void* widget, int idx, cc_bool wasOver) { static void LTable_MouseDown(void* widget, int idx, cc_bool wasOver) {

View File

@ -23,7 +23,8 @@ struct LWidgetVTABLE {
/* Called repeatedly to update this widget when selected. */ /* Called repeatedly to update this widget when selected. */
void (*Tick)(void* widget); void (*Tick)(void* widget);
/* Called when key is pressed and this widget is selected. */ /* Called when key is pressed and this widget is selected. */
void (*KeyDown)(void* widget, int key, cc_bool wasDown); /* Returns whether the key press was intercepted */
cc_bool (*KeyDown)(void* widget, int key, cc_bool wasDown);
/* Called when key is pressed and this widget is selected. */ /* Called when key is pressed and this widget is selected. */
void (*KeyPress)(void* widget, char c); void (*KeyPress)(void* widget, char c);
/* Called when mouse hovers/moves over this widget. */ /* Called when mouse hovers/moves over this widget. */
@ -70,7 +71,7 @@ struct LButton {
}; };
CC_NOINLINE void LButton_Init(struct LButton* w, int width, int height, const char* text, const struct LLayout* layouts); CC_NOINLINE void LButton_Init(struct LButton* w, int width, int height, const char* text, const struct LLayout* layouts);
CC_NOINLINE void LButton_SetConst(struct LButton* w, const char* text); CC_NOINLINE void LButton_SetConst(struct LButton* w, const char* text);
CC_NOINLINE void LButton_DrawBackground(struct Context2D* ctx, int x, int y, int width, int height, cc_bool hovered); CC_NOINLINE void LButton_DrawBackground(struct Context2D* ctx, int x, int y, int width, int height, cc_bool active);
struct LCheckbox; struct LCheckbox;
struct LCheckbox { struct LCheckbox {