1 /**
2 * @file lv_sdl_mouse.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9 #include "lv_sdl_mouse.h"
10 #if LV_USE_SDL
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 #ifndef KEYBOARD_BUFFER_SIZE
21 #define KEYBOARD_BUFFER_SIZE 32
22 #endif
23
24 /**********************
25 * STATIC PROTOTYPES
26 **********************/
27 static void sdl_mouse_read(lv_indev_t * indev, lv_indev_data_t * data);
28 static void release_indev_cb(lv_event_t * e);
29
30 /**********************
31 * STATIC VARIABLES
32 **********************/
33
34 typedef struct {
35 int16_t last_x;
36 int16_t last_y;
37 bool left_button_down;
38 #if LV_SDL_MOUSEWHEEL_MODE == LV_SDL_MOUSEWHEEL_MODE_CROWN
39 int32_t diff;
40 #endif
41 } lv_sdl_mouse_t;
42
43 /**********************
44 * GLOBAL FUNCTIONS
45 **********************/
46
lv_sdl_mouse_create(void)47 lv_indev_t * lv_sdl_mouse_create(void)
48 {
49 lv_sdl_mouse_t * dsc = lv_malloc_zeroed(sizeof(lv_sdl_mouse_t));
50 LV_ASSERT_MALLOC(dsc);
51 if(dsc == NULL) return NULL;
52
53 lv_indev_t * indev = lv_indev_create();
54 LV_ASSERT_MALLOC(indev);
55 if(indev == NULL) {
56 lv_free(dsc);
57 return NULL;
58 }
59
60 lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
61 lv_indev_set_read_cb(indev, sdl_mouse_read);
62 lv_indev_set_driver_data(indev, dsc);
63
64 lv_indev_set_mode(indev, LV_INDEV_MODE_EVENT);
65 lv_indev_add_event_cb(indev, release_indev_cb, LV_EVENT_DELETE, indev);
66
67 return indev;
68 }
69
70 /**********************
71 * STATIC FUNCTIONS
72 **********************/
73
sdl_mouse_read(lv_indev_t * indev,lv_indev_data_t * data)74 static void sdl_mouse_read(lv_indev_t * indev, lv_indev_data_t * data)
75 {
76 lv_sdl_mouse_t * dsc = lv_indev_get_driver_data(indev);
77
78 /*Store the collected data*/
79 data->point.x = dsc->last_x;
80 data->point.y = dsc->last_y;
81 data->state = dsc->left_button_down ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
82 #if LV_SDL_MOUSEWHEEL_MODE == LV_SDL_MOUSEWHEEL_MODE_CROWN
83 data->enc_diff = dsc->diff;
84 dsc->diff = 0;
85 #endif
86 }
87
release_indev_cb(lv_event_t * e)88 static void release_indev_cb(lv_event_t * e)
89 {
90 lv_indev_t * indev = (lv_indev_t *) lv_event_get_user_data(e);
91 lv_sdl_mouse_t * dsc = lv_indev_get_driver_data(indev);
92 if(dsc) {
93 lv_indev_set_driver_data(indev, NULL);
94 lv_indev_set_read_cb(indev, NULL);
95 lv_free(dsc);
96 LV_LOG_INFO("done");
97 }
98 }
99
lv_sdl_mouse_handler(SDL_Event * event)100 void lv_sdl_mouse_handler(SDL_Event * event)
101 {
102 uint32_t win_id = UINT32_MAX;
103 switch(event->type) {
104 case SDL_MOUSEBUTTONUP:
105 case SDL_MOUSEBUTTONDOWN:
106 win_id = event->button.windowID;
107 break;
108 case SDL_MOUSEMOTION:
109 win_id = event->motion.windowID;
110 break;
111 #if LV_SDL_MOUSEWHEEL_MODE == LV_SDL_MOUSEWHEEL_MODE_CROWN
112 case SDL_MOUSEWHEEL:
113 win_id = event->wheel.windowID;
114 break;
115 #endif
116 case SDL_FINGERUP:
117 case SDL_FINGERDOWN:
118 case SDL_FINGERMOTION:
119 #if SDL_VERSION_ATLEAST(2,0,12)
120 win_id = event->tfinger.windowID;
121 #endif
122 break;
123 case SDL_WINDOWEVENT:
124 win_id = event->window.windowID;
125 break;
126 default:
127 return;
128 }
129
130 lv_display_t * disp = lv_sdl_get_disp_from_win_id(win_id);
131
132 /*Find a suitable indev*/
133 lv_indev_t * indev = lv_indev_get_next(NULL);
134 while(indev) {
135 if(lv_indev_get_read_cb(indev) == sdl_mouse_read) {
136 /*If disp is NULL for any reason use the first indev with the correct type*/
137 if(disp == NULL || lv_indev_get_display(indev) == disp) break;
138 }
139 indev = lv_indev_get_next(indev);
140 }
141
142 if(indev == NULL) return;
143 lv_sdl_mouse_t * indev_dev = lv_indev_get_driver_data(indev);
144 if(indev_dev == NULL) return;
145
146 int32_t hor_res = lv_display_get_horizontal_resolution(disp);
147 int32_t ver_res = lv_display_get_vertical_resolution(disp);
148 float zoom = lv_sdl_window_get_zoom(disp);
149
150 switch(event->type) {
151 case SDL_WINDOWEVENT:
152 if(event->window.event == SDL_WINDOWEVENT_LEAVE) {
153 indev_dev->left_button_down = false;
154 }
155 break;
156 case SDL_MOUSEBUTTONUP:
157 if(event->button.button == SDL_BUTTON_LEFT)
158 indev_dev->left_button_down = false;
159 break;
160 case SDL_WINDOWEVENT_LEAVE:
161 indev_dev->left_button_down = false;
162 break;
163 case SDL_MOUSEBUTTONDOWN:
164 if(event->button.button == SDL_BUTTON_LEFT) {
165 indev_dev->left_button_down = true;
166 indev_dev->last_x = (int16_t)((float)(event->motion.x) / zoom);
167 indev_dev->last_y = (int16_t)((float)(event->motion.y) / zoom);
168 }
169 break;
170 case SDL_MOUSEMOTION:
171 indev_dev->last_x = (int16_t)((float)(event->motion.x) / zoom);
172 indev_dev->last_y = (int16_t)((float)(event->motion.y) / zoom);
173 break;
174
175 case SDL_FINGERUP:
176 indev_dev->left_button_down = false;
177 indev_dev->last_x = (int16_t)((float)hor_res * event->tfinger.x / zoom);
178 indev_dev->last_y = (int16_t)((float)ver_res * event->tfinger.y / zoom);
179 break;
180 case SDL_FINGERDOWN:
181 indev_dev->left_button_down = true;
182 indev_dev->last_x = (int16_t)((float)hor_res * event->tfinger.x / zoom);
183 indev_dev->last_y = (int16_t)((float)ver_res * event->tfinger.y / zoom);
184 break;
185 case SDL_FINGERMOTION:
186 indev_dev->last_x = (int16_t)((float)hor_res * event->tfinger.x / zoom);
187 indev_dev->last_y = (int16_t)((float)ver_res * event->tfinger.y / zoom);
188 break;
189 case SDL_MOUSEWHEEL:
190 #if LV_SDL_MOUSEWHEEL_MODE == LV_SDL_MOUSEWHEEL_MODE_CROWN
191 #ifdef __EMSCRIPTEN__
192 /*Emscripten scales it wrong*/
193 if(event->wheel.y < 0) dsc->diff++;
194 if(event->wheel.y > 0) dsc->diff--;
195 #else
196 indev_dev->diff = -event->wheel.y;
197 #endif /*__EMSCRIPTEN__*/
198 #endif /*LV_SDL_MOUSEWHEEL_MODE == LV_SDL_MOUSEWHEEL_MODE_CROWN*/
199 break;
200 }
201 lv_indev_read(indev);
202 }
203
204 #endif /*LV_USE_SDL*/
205