From ebaa84b0c27548dd4df1a9584fe22ee797a68331 Mon Sep 17 00:00:00 2001 From: "Vasyl \"vk\" Kaigorodov" Date: Wed, 26 Oct 2022 20:35:49 +0200 Subject: [PATCH] Support for setting all screen orientations (#1928) * Support for setting all screen orientations * Gui: add flipped orientation to view * Gui: correct assert conditions in gui_add_view_port Co-authored-by: Aleksandr Kutuzov --- applications/services/gui/canvas.c | 35 ++++++++-- applications/services/gui/canvas.h | 2 + applications/services/gui/gui.c | 4 +- applications/services/gui/view.h | 2 + applications/services/gui/view_dispatcher.c | 10 ++- applications/services/gui/view_port.c | 74 ++++++++++++++++++--- applications/services/gui/view_port.h | 2 + 7 files changed, 112 insertions(+), 17 deletions(-) diff --git a/applications/services/gui/canvas.c b/applications/services/gui/canvas.c index 1e275aafb..a2979d56b 100644 --- a/applications/services/gui/canvas.c +++ b/applications/services/gui/canvas.c @@ -371,16 +371,39 @@ void canvas_set_bitmap_mode(Canvas* canvas, bool alpha) { void canvas_set_orientation(Canvas* canvas, CanvasOrientation orientation) { furi_assert(canvas); if(canvas->orientation != orientation) { - canvas->orientation = orientation; - if(canvas->orientation == CanvasOrientationHorizontal) { - FURI_SWAP(canvas->width, canvas->height); + switch(orientation) { + case CanvasOrientationHorizontal: + if(canvas->orientation == CanvasOrientationVertical || + canvas->orientation == CanvasOrientationVerticalFlip) { + FURI_SWAP(canvas->width, canvas->height); + } u8g2_SetDisplayRotation(&canvas->fb, U8G2_R0); - } else if(canvas->orientation == CanvasOrientationVertical) { - FURI_SWAP(canvas->width, canvas->height); + break; + case CanvasOrientationHorizontalFlip: + if(canvas->orientation == CanvasOrientationVertical || + canvas->orientation == CanvasOrientationVerticalFlip) { + FURI_SWAP(canvas->width, canvas->height); + } + u8g2_SetDisplayRotation(&canvas->fb, U8G2_R2); + break; + case CanvasOrientationVertical: + if(canvas->orientation == CanvasOrientationHorizontal || + canvas->orientation == CanvasOrientationHorizontalFlip) { + FURI_SWAP(canvas->width, canvas->height); + }; u8g2_SetDisplayRotation(&canvas->fb, U8G2_R3); - } else { + break; + case CanvasOrientationVerticalFlip: + if(canvas->orientation == CanvasOrientationHorizontal || + canvas->orientation == CanvasOrientationHorizontalFlip) { + FURI_SWAP(canvas->width, canvas->height); + } + u8g2_SetDisplayRotation(&canvas->fb, U8G2_R1); + break; + default: furi_assert(0); } + canvas->orientation = orientation; } } diff --git a/applications/services/gui/canvas.h b/applications/services/gui/canvas.h index 49bbd7d68..a67e58494 100644 --- a/applications/services/gui/canvas.h +++ b/applications/services/gui/canvas.h @@ -42,7 +42,9 @@ typedef enum { /** Canvas Orientation */ typedef enum { CanvasOrientationHorizontal, + CanvasOrientationHorizontalFlip, CanvasOrientationVertical, + CanvasOrientationVerticalFlip, } CanvasOrientation; /** Font Direction */ diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index 8c5ed91a9..42712ed90 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -322,7 +322,9 @@ void gui_add_view_port(Gui* gui, ViewPort* view_port, GuiLayer layer) { furi_check(layer < GuiLayerMAX); // Only fullscreen supports Vertical orientation for now furi_assert( - (layer == GuiLayerFullscreen) || (view_port->orientation != ViewPortOrientationVertical)); + (layer == GuiLayerFullscreen) || + ((view_port->orientation != ViewPortOrientationVertical) && + (view_port->orientation != ViewPortOrientationVerticalFlip))); gui_lock(gui); // Verify that view port is not yet added diff --git a/applications/services/gui/view.h b/applications/services/gui/view.h index b40f8ded5..7a2003a63 100644 --- a/applications/services/gui/view.h +++ b/applications/services/gui/view.h @@ -25,7 +25,9 @@ extern "C" { typedef enum { ViewOrientationHorizontal, + ViewOrientationHorizontalFlip, ViewOrientationVertical, + ViewOrientationVerticalFlip, } ViewOrientation; /** View, anonymous type */ diff --git a/applications/services/gui/view_dispatcher.c b/applications/services/gui/view_dispatcher.c index 6e4ce8360..1736558cb 100644 --- a/applications/services/gui/view_dispatcher.c +++ b/applications/services/gui/view_dispatcher.c @@ -331,10 +331,16 @@ void view_dispatcher_set_current_view(ViewDispatcher* view_dispatcher, View* vie view_dispatcher->current_view = view; // Dispatch view enter event if(view_dispatcher->current_view) { - if(view->orientation == ViewOrientationVertical) + if(view->orientation == ViewOrientationVertical) { view_port_set_orientation(view_dispatcher->view_port, ViewPortOrientationVertical); - else if(view->orientation == ViewOrientationHorizontal) + } else if(view->orientation == ViewOrientationVerticalFlip) { + view_port_set_orientation(view_dispatcher->view_port, ViewPortOrientationVerticalFlip); + } else if(view->orientation == ViewOrientationHorizontal) { view_port_set_orientation(view_dispatcher->view_port, ViewPortOrientationHorizontal); + } else if(view->orientation == ViewOrientationHorizontalFlip) { + view_port_set_orientation( + view_dispatcher->view_port, ViewPortOrientationHorizontalFlip); + } view_enter(view_dispatcher->current_view); view_port_enabled_set(view_dispatcher->view_port, true); view_port_update(view_dispatcher->view_port); diff --git a/applications/services/gui/view_port.c b/applications/services/gui/view_port.c index 8069a02e5..baa8f7bd2 100644 --- a/applications/services/gui/view_port.c +++ b/applications/services/gui/view_port.c @@ -7,7 +7,7 @@ // TODO add mutex to view_port ops -static void view_port_rotate_buttons(InputEvent* event) { +static void view_port_remap_buttons_vertical(InputEvent* event) { switch(event->key) { case InputKeyUp: event->key = InputKeyRight; @@ -26,14 +26,61 @@ static void view_port_rotate_buttons(InputEvent* event) { } } -static void view_port_setup_canvas_orientation(const ViewPort* view_port, Canvas* canvas) { - if(view_port->orientation == ViewPortOrientationHorizontal) { - canvas_set_orientation(canvas, CanvasOrientationHorizontal); - } else if(view_port->orientation == ViewPortOrientationVertical) { - canvas_set_orientation(canvas, CanvasOrientationVertical); +static void view_port_remap_buttons_vertical_flip(InputEvent* event) { + switch(event->key) { + case InputKeyUp: + event->key = InputKeyLeft; + break; + case InputKeyDown: + event->key = InputKeyRight; + break; + case InputKeyRight: + event->key = InputKeyUp; + break; + case InputKeyLeft: + event->key = InputKeyDown; + break; + default: + break; } } +static void view_port_remap_buttons_horizontal_flip(InputEvent* event) { + switch(event->key) { + case InputKeyUp: + event->key = InputKeyDown; + break; + case InputKeyDown: + event->key = InputKeyUp; + break; + case InputKeyRight: + event->key = InputKeyLeft; + break; + case InputKeyLeft: + event->key = InputKeyRight; + break; + default: + break; + } +} + +static void view_port_setup_canvas_orientation(const ViewPort* view_port, Canvas* canvas) { + switch(view_port->orientation) { + case ViewPortOrientationHorizontalFlip: + canvas_set_orientation(canvas, CanvasOrientationHorizontalFlip); + break; + case ViewPortOrientationVertical: + canvas_set_orientation(canvas, CanvasOrientationVertical); + break; + case ViewPortOrientationVerticalFlip: + canvas_set_orientation(canvas, CanvasOrientationVerticalFlip); + break; + default: + canvas_set_orientation(canvas, CanvasOrientationHorizontal); + break; + }; +} + ViewPort* view_port_alloc() { ViewPort* view_port = malloc(sizeof(ViewPort)); view_port->orientation = ViewPortOrientationHorizontal; @@ -122,8 +169,19 @@ void view_port_input(ViewPort* view_port, InputEvent* event) { furi_check(view_port->gui); if(view_port->input_callback) { - if(view_port_get_orientation(view_port) == ViewPortOrientationVertical) { - view_port_rotate_buttons(event); + ViewPortOrientation orientation = view_port_get_orientation(view_port); + switch(orientation) { + case ViewPortOrientationHorizontalFlip: + view_port_remap_buttons_horizontal_flip(event); + break; + case ViewPortOrientationVertical: + view_port_remap_buttons_vertical(event); + break; + case ViewPortOrientationVerticalFlip: + view_port_remap_buttons_vertical_flip(event); + break; + default: + break; } view_port->input_callback(event, view_port->input_callback_context); } diff --git a/applications/services/gui/view_port.h b/applications/services/gui/view_port.h index 96f2798e2..169681ac0 100644 --- a/applications/services/gui/view_port.h +++ b/applications/services/gui/view_port.h @@ -16,7 +16,9 @@ typedef struct ViewPort ViewPort; typedef enum { ViewPortOrientationHorizontal, + ViewPortOrientationHorizontalFlip, ViewPortOrientationVertical, + ViewPortOrientationVerticalFlip, } ViewPortOrientation; /** ViewPort Draw callback