1 /**
2  * @file lv_sdl_mousewheel.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_sdl_mousewheel.h"
10 #if LV_USE_SDL && LV_SDL_MOUSEWHEEL_MODE == LV_SDL_MOUSEWHEEL_MODE_ENCODER
11 
12 #include "../../core/lv_group.h"
13 #include "../../stdlib/lv_string.h"
14 #include "lv_sdl_private.h"
15 
16 /*********************
17  *      DEFINES
18  *********************/
19 
20 /**********************
21  *  STATIC PROTOTYPES
22  **********************/
23 static void sdl_mousewheel_read(lv_indev_t * indev, lv_indev_data_t * data);
24 static void release_indev_cb(lv_event_t * e);
25 
26 /**********************
27  *  STATIC VARIABLES
28  **********************/
29 
30 typedef struct {
31     int16_t diff;
32     lv_indev_state_t state;
33 } lv_sdl_mousewheel_t;
34 
35 /**********************
36  *   GLOBAL FUNCTIONS
37  **********************/
38 
lv_sdl_mousewheel_create(void)39 lv_indev_t * lv_sdl_mousewheel_create(void)
40 {
41     lv_sdl_mousewheel_t * dsc = lv_malloc_zeroed(sizeof(lv_sdl_mousewheel_t));
42     LV_ASSERT_MALLOC(dsc);
43     if(dsc == NULL) return NULL;
44 
45     lv_indev_t * indev = lv_indev_create();
46     if(indev == NULL) {
47         lv_free(dsc);
48         return NULL;
49     }
50 
51     lv_indev_set_type(indev, LV_INDEV_TYPE_ENCODER);
52     lv_indev_set_read_cb(indev, sdl_mousewheel_read);
53     lv_indev_set_driver_data(indev, dsc);
54 
55     lv_indev_set_mode(indev, LV_INDEV_MODE_EVENT);
56     lv_indev_add_event_cb(indev, release_indev_cb, LV_EVENT_DELETE, indev);
57 
58     return indev;
59 }
60 
61 /**********************
62  *   STATIC FUNCTIONS
63  **********************/
64 
sdl_mousewheel_read(lv_indev_t * indev,lv_indev_data_t * data)65 static void sdl_mousewheel_read(lv_indev_t * indev, lv_indev_data_t * data)
66 {
67     lv_sdl_mousewheel_t * dsc = lv_indev_get_driver_data(indev);
68 
69     data->state = dsc->state;
70     data->enc_diff = dsc->diff;
71     dsc->diff = 0;
72 }
73 
release_indev_cb(lv_event_t * e)74 static void release_indev_cb(lv_event_t * e)
75 {
76     lv_indev_t * indev = (lv_indev_t *) lv_event_get_user_data(e);
77     lv_sdl_mousewheel_t * dsc = lv_indev_get_driver_data(indev);
78     if(dsc) {
79         lv_indev_set_driver_data(indev, NULL);
80         lv_indev_set_read_cb(indev, NULL);
81         lv_free(dsc);
82         LV_LOG_INFO("done");
83     }
84 }
85 
lv_sdl_mousewheel_handler(SDL_Event * event)86 void lv_sdl_mousewheel_handler(SDL_Event * event)
87 {
88     uint32_t win_id = UINT32_MAX;
89     switch(event->type) {
90         case SDL_MOUSEWHEEL:
91             win_id = event->wheel.windowID;
92             break;
93         case SDL_MOUSEBUTTONDOWN:
94         case SDL_MOUSEBUTTONUP:
95             win_id = event->button.windowID;
96             break;
97         default:
98             return;
99     }
100 
101     lv_display_t * disp = lv_sdl_get_disp_from_win_id(win_id);
102 
103     /*Find a suitable indev*/
104     lv_indev_t * indev = lv_indev_get_next(NULL);
105     while(indev) {
106         if(lv_indev_get_read_cb(indev) == sdl_mousewheel_read) {
107             /*If disp is NULL for any reason use the first indev with the correct type*/
108             if(disp == NULL || lv_indev_get_display(indev) == disp) break;
109         }
110         indev = lv_indev_get_next(indev);
111     }
112 
113     if(indev == NULL) return;
114     lv_sdl_mousewheel_t * dsc = lv_indev_get_driver_data(indev);
115 
116     switch(event->type) {
117         case SDL_MOUSEWHEEL:
118 #ifdef __EMSCRIPTEN__
119             /*Emscripten scales it wrong*/
120             if(event->wheel.y < 0) dsc->diff++;
121             if(event->wheel.y > 0) dsc->diff--;
122 #else
123             dsc->diff = -event->wheel.y;
124 #endif
125             break;
126         case SDL_MOUSEBUTTONDOWN:
127             if(event->button.button == SDL_BUTTON_MIDDLE) {
128                 dsc->state = LV_INDEV_STATE_PRESSED;
129             }
130             break;
131         case SDL_MOUSEBUTTONUP:
132             if(event->button.button == SDL_BUTTON_MIDDLE) {
133                 dsc->state = LV_INDEV_STATE_RELEASED;
134             }
135             break;
136         default:
137             break;
138     }
139     lv_indev_read(indev);
140 }
141 
142 #endif /*LV_USE_SDL*/
143