Upside down / left handed orientation support (#2462)
* Add backup files to .gitignore * Added lefty support in Settings > System > hand Orient: Fixes: #1015 * Left handed mode * Fix lefthanded mode on vertical interfaces * Input: new composite sequence identifier * Gui: move input mapping from Canvas to ViewPort, properly handle input mapping on View switch in ViewDispatcher * Rpc: proper input sequencing and tagging in RpcGui * Rpc: remove magic from RpcGui Co-authored-by: MrDaGree <5050898+MrDaGree@users.noreply.github.com> Co-authored-by: Willy-JL <willy.leslie@icloud.com> Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com> Co-authored-by: Sergey Gavrilov <who.just.the.doctor@gmail.com>
This commit is contained in:
		| @@ -4,6 +4,7 @@ | ||||
|  | ||||
| #include <furi.h> | ||||
| #include <furi_hal.h> | ||||
| #include <furi_hal_rtc.h> | ||||
| #include <stdint.h> | ||||
| #include <u8g2_glue.h> | ||||
|  | ||||
| @@ -376,39 +377,36 @@ void canvas_set_bitmap_mode(Canvas* canvas, bool alpha) { | ||||
|  | ||||
| void canvas_set_orientation(Canvas* canvas, CanvasOrientation orientation) { | ||||
|     furi_assert(canvas); | ||||
|     const u8g2_cb_t* rotate_cb = NULL; | ||||
|     bool need_swap = false; | ||||
|     if(canvas->orientation != orientation) { | ||||
|         switch(orientation) { | ||||
|         case CanvasOrientationHorizontal: | ||||
|             if(canvas->orientation == CanvasOrientationVertical || | ||||
|                canvas->orientation == CanvasOrientationVerticalFlip) { | ||||
|                 FURI_SWAP(canvas->width, canvas->height); | ||||
|             } | ||||
|             u8g2_SetDisplayRotation(&canvas->fb, U8G2_R0); | ||||
|             need_swap = canvas->orientation == CanvasOrientationVertical || | ||||
|                         canvas->orientation == CanvasOrientationVerticalFlip; | ||||
|             rotate_cb = U8G2_R0; | ||||
|             break; | ||||
|         case CanvasOrientationHorizontalFlip: | ||||
|             if(canvas->orientation == CanvasOrientationVertical || | ||||
|                canvas->orientation == CanvasOrientationVerticalFlip) { | ||||
|                 FURI_SWAP(canvas->width, canvas->height); | ||||
|             } | ||||
|             u8g2_SetDisplayRotation(&canvas->fb, U8G2_R2); | ||||
|             need_swap = canvas->orientation == CanvasOrientationVertical || | ||||
|                         canvas->orientation == CanvasOrientationVerticalFlip; | ||||
|             rotate_cb = U8G2_R2; | ||||
|             break; | ||||
|         case CanvasOrientationVertical: | ||||
|             if(canvas->orientation == CanvasOrientationHorizontal || | ||||
|                canvas->orientation == CanvasOrientationHorizontalFlip) { | ||||
|                 FURI_SWAP(canvas->width, canvas->height); | ||||
|             }; | ||||
|             u8g2_SetDisplayRotation(&canvas->fb, U8G2_R3); | ||||
|             need_swap = canvas->orientation == CanvasOrientationHorizontal || | ||||
|                         canvas->orientation == CanvasOrientationHorizontalFlip; | ||||
|             rotate_cb = U8G2_R3; | ||||
|             break; | ||||
|         case CanvasOrientationVerticalFlip: | ||||
|             if(canvas->orientation == CanvasOrientationHorizontal || | ||||
|                canvas->orientation == CanvasOrientationHorizontalFlip) { | ||||
|                 FURI_SWAP(canvas->width, canvas->height); | ||||
|             } | ||||
|             u8g2_SetDisplayRotation(&canvas->fb, U8G2_R1); | ||||
|             need_swap = canvas->orientation == CanvasOrientationHorizontal || | ||||
|                         canvas->orientation == CanvasOrientationHorizontalFlip; | ||||
|             rotate_cb = U8G2_R1; | ||||
|             break; | ||||
|         default: | ||||
|             furi_assert(0); | ||||
|         } | ||||
|  | ||||
|         if(need_swap) FURI_SWAP(canvas->width, canvas->height); | ||||
|         u8g2_SetDisplayRotation(&canvas->fb, rotate_cb); | ||||
|         canvas->orientation = orientation; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -50,7 +50,13 @@ static void gui_redraw_status_bar(Gui* gui, bool need_attention) { | ||||
|     uint8_t left_used = 0; | ||||
|     uint8_t right_used = 0; | ||||
|     uint8_t width; | ||||
|     canvas_set_orientation(gui->canvas, CanvasOrientationHorizontal); | ||||
|  | ||||
|     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagHandOrient)) { | ||||
|         canvas_set_orientation(gui->canvas, CanvasOrientationHorizontalFlip); | ||||
|     } else { | ||||
|         canvas_set_orientation(gui->canvas, CanvasOrientationHorizontal); | ||||
|     } | ||||
|  | ||||
|     canvas_frame_set( | ||||
|         gui->canvas, GUI_STATUS_BAR_X, GUI_STATUS_BAR_Y, GUI_DISPLAY_WIDTH, GUI_STATUS_BAR_HEIGHT); | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| #include "gui.h" | ||||
|  | ||||
| #include <furi.h> | ||||
| #include <furi_hal_rtc.h> | ||||
| #include <m-array.h> | ||||
| #include <m-algo.h> | ||||
| #include <stdio.h> | ||||
|   | ||||
| @@ -320,6 +320,13 @@ void view_dispatcher_send_custom_event(ViewDispatcher* view_dispatcher, uint32_t | ||||
|         furi_message_queue_put(view_dispatcher->queue, &message, FuriWaitForever) == FuriStatusOk); | ||||
| } | ||||
|  | ||||
| static const ViewPortOrientation view_dispatcher_view_port_orientation_table[] = { | ||||
|     [ViewOrientationVertical] = ViewPortOrientationVertical, | ||||
|     [ViewOrientationVerticalFlip] = ViewPortOrientationVerticalFlip, | ||||
|     [ViewOrientationHorizontal] = ViewPortOrientationHorizontal, | ||||
|     [ViewOrientationHorizontalFlip] = ViewPortOrientationHorizontalFlip, | ||||
| }; | ||||
|  | ||||
| void view_dispatcher_set_current_view(ViewDispatcher* view_dispatcher, View* view) { | ||||
|     furi_assert(view_dispatcher); | ||||
|     // Dispatch view exit event | ||||
| @@ -330,15 +337,12 @@ 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) { | ||||
|             view_port_set_orientation(view_dispatcher->view_port, ViewPortOrientationVertical); | ||||
|         } 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); | ||||
|         ViewPortOrientation orientation = | ||||
|             view_dispatcher_view_port_orientation_table[view->orientation]; | ||||
|         if(view_port_get_orientation(view_dispatcher->view_port) != orientation) { | ||||
|             view_port_set_orientation(view_dispatcher->view_port, orientation); | ||||
|             // we just rotated input keys, now it's time to sacrifice some input | ||||
|             view_dispatcher->ongoing_input = 0; | ||||
|         } | ||||
|         view_enter(view_dispatcher->current_view); | ||||
|         view_port_enabled_set(view_dispatcher->view_port, true); | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| #include "view_port_i.h" | ||||
|  | ||||
| #include <furi.h> | ||||
| #include <furi_hal.h> | ||||
| #include <furi_hal_rtc.h> | ||||
|  | ||||
| #include "gui.h" | ||||
| #include "gui_i.h" | ||||
| @@ -48,27 +50,45 @@ static const InputKey view_port_input_mapping[ViewPortOrientationMAX][InputKeyMA | ||||
|      InputKeyBack}, //ViewPortOrientationVerticalFlip | ||||
| }; | ||||
|  | ||||
| static const InputKey view_port_left_hand_input_mapping[InputKeyMAX] = | ||||
|     {InputKeyDown, InputKeyUp, InputKeyLeft, InputKeyRight, InputKeyOk, InputKeyBack}; | ||||
|  | ||||
| static const CanvasOrientation view_port_orientation_mapping[ViewPortOrientationMAX] = { | ||||
|     [ViewPortOrientationHorizontal] = CanvasOrientationHorizontal, | ||||
|     [ViewPortOrientationHorizontalFlip] = CanvasOrientationHorizontalFlip, | ||||
|     [ViewPortOrientationVertical] = CanvasOrientationVertical, | ||||
|     [ViewPortOrientationVerticalFlip] = CanvasOrientationVerticalFlip, | ||||
| }; | ||||
|  | ||||
| // Remaps directional pad buttons on Flipper based on ViewPort orientation | ||||
| static void view_port_map_input(InputEvent* event, ViewPortOrientation orientation) { | ||||
|     furi_assert(orientation < ViewPortOrientationMAX && event->key < InputKeyMAX); | ||||
|  | ||||
|     if(event->sequence_source != INPUT_SEQUENCE_SOURCE_HARDWARE) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if(orientation == ViewPortOrientationHorizontal || | ||||
|        orientation == ViewPortOrientationHorizontalFlip) { | ||||
|         if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagHandOrient)) { | ||||
|             event->key = view_port_left_hand_input_mapping[event->key]; | ||||
|         } | ||||
|     } | ||||
|     event->key = view_port_input_mapping[orientation][event->key]; | ||||
| } | ||||
|  | ||||
| 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; | ||||
|     }; | ||||
|     CanvasOrientation orientation = view_port_orientation_mapping[view_port->orientation]; | ||||
|  | ||||
|     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagHandOrient)) { | ||||
|         if(orientation == CanvasOrientationHorizontal) { | ||||
|             orientation = CanvasOrientationHorizontalFlip; | ||||
|         } else if(orientation == CanvasOrientationHorizontalFlip) { | ||||
|             orientation = CanvasOrientationHorizontal; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     canvas_set_orientation(canvas, orientation); | ||||
| } | ||||
|  | ||||
| ViewPort* view_port_alloc() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user