ui_sdl.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * sfnedit/ui_sdl.c
  3. *
  4. * Copyright (C) 2019 bzt (bztsrc@gitlab)
  5. *
  6. * Permission is hereby granted, free of charge, to any person
  7. * obtaining a copy of this software and associated documentation
  8. * files (the "Software"), to deal in the Software without
  9. * restriction, including without limitation the rights to use, copy,
  10. * modify, merge, publish, distribute, sublicense, and/or sell copies
  11. * of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  21. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  22. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  24. * DEALINGS IN THE SOFTWARE.
  25. *
  26. * @brief User interface driver for SDL
  27. *
  28. */
  29. #include <SDL.h>
  30. #include <string.h>
  31. #include "lang.h"
  32. #include "util.h"
  33. #include "ui.h"
  34. extern uint8_t *icon32;
  35. SDL_Surface *icons = NULL;
  36. SDL_Cursor *cursors[5];
  37. int btnflags = 0, keyflags = 0, mx = 0, my = 0, ti = 0;
  38. /**
  39. * Copy text to clipboard
  40. */
  41. void ui_copy(char *s)
  42. {
  43. SDL_SetClipboardText(s);
  44. }
  45. /**
  46. * Create a window
  47. */
  48. void *ui_createwin(int w, int h)
  49. {
  50. SDL_Window *window;
  51. if(!(window = SDL_CreateWindow("sfnedit", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, SDL_WINDOW_RESIZABLE)))
  52. return NULL;
  53. SDL_SetWindowIcon(window, icons);
  54. return (void *)window;
  55. }
  56. /**
  57. * Set window title
  58. */
  59. void ui_titlewin(ui_win_t *win, char *title)
  60. {
  61. SDL_SetWindowTitle((SDL_Window *)win->winid, title);
  62. }
  63. /**
  64. * Resize a window
  65. */
  66. void ui_resizewin(ui_win_t *win, int w, int h)
  67. {
  68. int i;
  69. (void)w; (void)h;
  70. win->surface = SDL_GetWindowSurface((SDL_Window *)win->winid);
  71. win->data = (uint32_t*)((SDL_Surface*)win->surface)->pixels;
  72. win->p = ((SDL_Surface*)win->surface)->pitch/4;
  73. win->w = ((SDL_Surface*)win->surface)->w;
  74. win->h = ((SDL_Surface*)win->surface)->h;
  75. for(i = 0; i < win->h * win->p; i++) win->data[i] = theme[THEME_BG];
  76. }
  77. /**
  78. * Display modified window
  79. */
  80. void ui_flushwin(ui_win_t *win, int x __attribute__((unused)), int y __attribute__((unused)),
  81. int w __attribute__((unused)), int h __attribute__((unused)))
  82. {
  83. SDL_UpdateWindowSurface((SDL_Window*)win->winid);
  84. }
  85. /**
  86. * Destroy a window
  87. */
  88. void ui_destroywin(ui_win_t *win)
  89. {
  90. SDL_DestroyWindow((SDL_Window*)win->winid);
  91. }
  92. /**
  93. * Focus a window
  94. */
  95. void ui_focuswin(ui_win_t *win)
  96. {
  97. SDL_UpdateWindowSurface((SDL_Window*)win->winid);
  98. SDL_ShowWindow((SDL_Window*)win->winid);
  99. SDL_RaiseWindow((SDL_Window*)win->winid);
  100. }
  101. /**
  102. * Change cursor of window
  103. */
  104. void ui_cursorwin(ui_win_t *win __attribute__((unused)), int cursor)
  105. {
  106. SDL_SetCursor(cursors[cursor]);
  107. }
  108. /**
  109. * Initialize SDL driver
  110. */
  111. void ui_init()
  112. {
  113. if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_EVENTS)) ui_error("sdl", ERR_DISPLAY);
  114. icons = SDL_CreateRGBSurfaceFrom((Uint32 *)icon32, 32, 32, 32, 32*4, 0xFF, 0xFF00, 0xFF0000, 0xFF000000);
  115. cursors[CURSOR_LOADING] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAITARROW);
  116. cursors[CURSOR_PTR] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
  117. cursors[CURSOR_CROSS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_CROSSHAIR);
  118. cursors[CURSOR_MOVE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
  119. cursors[CURSOR_GRAB] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
  120. SDL_StartTextInput();
  121. }
  122. /**
  123. * Finish SDL driver
  124. */
  125. void ui_fini()
  126. {
  127. int i;
  128. SDL_StopTextInput();
  129. for(i=0;i<5;i++) SDL_FreeCursor(cursors[i]);
  130. SDL_FreeSurface(icons);
  131. SDL_VideoQuit();
  132. SDL_Quit();
  133. }
  134. /**
  135. * Convert an SDL event
  136. */
  137. void ui_getevent()
  138. {
  139. SDL_Event e;
  140. if(SDL_WaitEvent(&e)) {
  141. event.type = E_NONE;
  142. switch(e.type) {
  143. case SDL_QUIT: event.type = E_CLOSE; event.win = 0; break;
  144. case SDL_WINDOWEVENT:
  145. event.win = ui_getwin(SDL_GetWindowFromID(e.window.windowID));
  146. switch(e.window.event) {
  147. case SDL_WINDOWEVENT_CLOSE: event.type = E_CLOSE; break;
  148. case SDL_WINDOWEVENT_RESIZED:
  149. case SDL_WINDOWEVENT_SIZE_CHANGED:
  150. event.type = E_RESIZE;
  151. event.x = event.y = 0;
  152. event.w = e.window.data1;
  153. event.h = e.window.data2;
  154. break;
  155. default:
  156. event.type = E_REFRESH;
  157. event.x = event.y = 0;
  158. event.w = e.window.data1;
  159. event.h = e.window.data2;
  160. break;
  161. }
  162. break;
  163. case SDL_TEXTINPUT:
  164. event.x = 0;
  165. memcpy(&event.x, e.text.text, strlen(e.text.text)+1);
  166. if(event.x) {
  167. event.win = ui_getwin(SDL_GetWindowFromID(e.key.windowID));
  168. event.h = keyflags;
  169. event.type = E_KEY;
  170. ti++;
  171. }
  172. break;
  173. case SDL_KEYUP:
  174. if(ti) { ti--; break; }
  175. event.x = e.key.keysym.sym;
  176. event.win = ui_getwin(SDL_GetWindowFromID(e.key.windowID));
  177. switch(e.key.keysym.sym) {
  178. case SDLK_F1: event.x = K_F1; break;
  179. case SDLK_ESCAPE: event.x = K_ESC; break;
  180. case SDLK_DELETE: event.x = K_DEL; break;
  181. case SDLK_BACKSPACE: event.x = K_BACKSPC; break;
  182. case SDLK_TAB: event.x = K_TAB; break;
  183. case SDLK_UP: event.x = K_UP; break;
  184. case SDLK_DOWN: event.x = K_DOWN; break;
  185. case SDLK_LEFT: event.x = K_LEFT; break;
  186. case SDLK_RIGHT: event.x = K_RIGHT; break;
  187. case SDLK_HOME: event.x = K_HOME; break;
  188. case SDLK_END: event.x = K_END; break;
  189. case SDLK_PAGEUP: event.x = K_PGUP; break;
  190. case SDLK_PAGEDOWN: event.x = K_PGDN; break;
  191. case SDLK_LSHIFT:
  192. case SDLK_RSHIFT: event.x = 0; keyflags &= ~1; break;
  193. case SDLK_LCTRL:
  194. case SDLK_RCTRL: event.x = 0; keyflags &= ~2; break;
  195. case SDLK_LGUI:
  196. case SDLK_RGUI:
  197. case SDLK_LALT:
  198. case SDLK_RALT: event.x = 0; keyflags &= ~4; break;
  199. }
  200. event.h = keyflags;
  201. if(event.x) event.type = E_KEY;
  202. break;
  203. case SDL_KEYDOWN:
  204. switch(e.key.keysym.sym) {
  205. case SDLK_LSHIFT:
  206. case SDLK_RSHIFT: keyflags |= 1; break;
  207. case SDLK_LCTRL:
  208. case SDLK_RCTRL: keyflags |= 2; break;
  209. case SDLK_LGUI:
  210. case SDLK_RGUI:
  211. case SDLK_LALT:
  212. case SDLK_RALT: keyflags |= 4; break;
  213. }
  214. break;
  215. case SDL_MOUSEMOTION:
  216. event.type = E_MOUSEMOVE;
  217. event.win = ui_getwin(SDL_GetWindowFromID(e.motion.windowID));
  218. event.x = mx = e.motion.x;
  219. event.y = my = e.motion.y;
  220. event.w = btnflags;
  221. event.h = keyflags;
  222. break;
  223. case SDL_MOUSEBUTTONDOWN:
  224. event.type = E_BTNPRESS;
  225. event.win = ui_getwin(SDL_GetWindowFromID(e.button.windowID));
  226. event.x = mx = e.button.x;
  227. event.y = my = e.button.y;
  228. btnflags |= (1<<(e.button.button-1));
  229. event.w = btnflags;
  230. event.h = keyflags;
  231. break;
  232. case SDL_MOUSEBUTTONUP:
  233. event.type = E_BTNRELEASE;
  234. event.win = ui_getwin(SDL_GetWindowFromID(e.button.windowID));
  235. event.x = mx = e.button.x;
  236. event.y = my = e.button.y;
  237. btnflags &= ~(1<<(e.button.button-1));
  238. event.w = btnflags;
  239. event.h = keyflags;
  240. break;
  241. case SDL_MOUSEWHEEL:
  242. event.type = E_BTNPRESS;
  243. event.win = ui_getwin(SDL_GetWindowFromID(e.button.windowID));
  244. event.x = mx;
  245. event.y = my;
  246. event.w = btnflags | (1 << (e.wheel.y > 0? 3 : (e.wheel.y < 0? 4 : (e.wheel.x > 0? 5 : 6))));
  247. event.h = keyflags;
  248. break;
  249. }
  250. }
  251. }