• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5   This software is provided 'as-is', without any express or implied
6   warranty.  In no event will the authors be held liable for any damages
7   arising from the use of this software.
8 
9   Permission is granted to anyone to use this software for any purpose,
10   including commercial applications, and to alter it and redistribute it
11   freely, subject to the following restrictions:
12 
13   1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17   2. Altered source versions must be plainly marked as such, and must not be
18      misrepresented as being the original software.
19   3. This notice may not be removed or altered from any source distribution.
20 */
21 #ifndef SDL_BAPP_H
22 #define SDL_BAPP_H
23 
24 #include <InterfaceKit.h>
25 #include <OpenGLKit.h>
26 
27 #include "../../video/haiku/SDL_bkeyboard.h"
28 
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 #include "../../SDL_internal.h"
35 
36 #include "SDL_video.h"
37 
38 /* Local includes */
39 #include "../../events/SDL_events_c.h"
40 #include "../../video/haiku/SDL_bkeyboard.h"
41 #include "../../video/haiku/SDL_bframebuffer.h"
42 
43 #ifdef __cplusplus
44 }
45 #endif
46 
47 #include <vector>
48 
49 
50 
51 
52 /* Forward declarations */
53 class SDL_BWin;
54 
55 /* Message constants */
56 enum ToSDL {
57     /* Intercepted by BWindow on its way to BView */
58     BAPP_MOUSE_MOVED,
59     BAPP_MOUSE_BUTTON,
60     BAPP_MOUSE_WHEEL,
61     BAPP_KEY,
62     BAPP_REPAINT,           /* from _UPDATE_ */
63     /* From BWindow */
64     BAPP_MAXIMIZE,          /* from B_ZOOM */
65     BAPP_MINIMIZE,
66     BAPP_RESTORE,           /* TODO: IMPLEMENT! */
67     BAPP_SHOW,
68     BAPP_HIDE,
69     BAPP_MOUSE_FOCUS,       /* caused by MOUSE_MOVE */
70     BAPP_KEYBOARD_FOCUS,    /* from WINDOW_ACTIVATED */
71     BAPP_WINDOW_CLOSE_REQUESTED,
72     BAPP_WINDOW_MOVED,
73     BAPP_WINDOW_RESIZED,
74     BAPP_SCREEN_CHANGED
75 };
76 
77 
78 
79 /* Create a descendant of BApplication */
80 class SDL_BApp : public BApplication {
81 public:
SDL_BApp(const char * signature)82     SDL_BApp(const char* signature) :
83         BApplication(signature) {
84         _current_context = NULL;
85     }
86 
87 
~SDL_BApp()88     virtual ~SDL_BApp() {
89     }
90 
91 
92 
93         /* Event-handling functions */
MessageReceived(BMessage * message)94     virtual void MessageReceived(BMessage* message) {
95         /* Sort out SDL-related messages */
96         switch ( message->what ) {
97         case BAPP_MOUSE_MOVED:
98             _HandleMouseMove(message);
99             break;
100 
101         case BAPP_MOUSE_BUTTON:
102             _HandleMouseButton(message);
103             break;
104 
105         case BAPP_MOUSE_WHEEL:
106             _HandleMouseWheel(message);
107             break;
108 
109         case BAPP_KEY:
110             _HandleKey(message);
111             break;
112 
113         case BAPP_REPAINT:
114             _HandleBasicWindowEvent(message, SDL_WINDOWEVENT_EXPOSED);
115             break;
116 
117         case BAPP_MAXIMIZE:
118             _HandleBasicWindowEvent(message, SDL_WINDOWEVENT_MAXIMIZED);
119             break;
120 
121         case BAPP_MINIMIZE:
122             _HandleBasicWindowEvent(message, SDL_WINDOWEVENT_MINIMIZED);
123             break;
124 
125         case BAPP_SHOW:
126             _HandleBasicWindowEvent(message, SDL_WINDOWEVENT_SHOWN);
127             break;
128 
129         case BAPP_HIDE:
130             _HandleBasicWindowEvent(message, SDL_WINDOWEVENT_HIDDEN);
131             break;
132 
133         case BAPP_MOUSE_FOCUS:
134             _HandleMouseFocus(message);
135             break;
136 
137         case BAPP_KEYBOARD_FOCUS:
138             _HandleKeyboardFocus(message);
139             break;
140 
141         case BAPP_WINDOW_CLOSE_REQUESTED:
142             _HandleBasicWindowEvent(message, SDL_WINDOWEVENT_CLOSE);
143             break;
144 
145         case BAPP_WINDOW_MOVED:
146             _HandleWindowMoved(message);
147             break;
148 
149         case BAPP_WINDOW_RESIZED:
150             _HandleWindowResized(message);
151             break;
152 
153         case BAPP_SCREEN_CHANGED:
154             /* TODO: Handle screen resize or workspace change */
155             break;
156 
157         default:
158            BApplication::MessageReceived(message);
159            break;
160         }
161     }
162 
163     /* Window creation/destruction methods */
GetID(SDL_Window * win)164     int32 GetID(SDL_Window *win) {
165         int32 i;
166         for(i = 0; i < _GetNumWindowSlots(); ++i) {
167             if( GetSDLWindow(i) == NULL ) {
168                 _SetSDLWindow(win, i);
169                 return i;
170             }
171         }
172 
173         /* Expand the vector if all slots are full */
174         if( i == _GetNumWindowSlots() ) {
175             _PushBackWindow(win);
176             return i;
177         }
178 
179         /* TODO: error handling */
180         return 0;
181     }
182 
183     /* FIXME: Bad coding practice, but I can't include SDL_BWin.h here.  Is
184        there another way to do this? */
185     void ClearID(SDL_BWin *bwin); /* Defined in SDL_BeApp.cc */
186 
187 
GetSDLWindow(int32 winID)188     SDL_Window *GetSDLWindow(int32 winID) {
189         return _window_map[winID];
190     }
191 
SetCurrentContext(BGLView * newContext)192     void SetCurrentContext(BGLView *newContext) {
193         if(_current_context)
194             _current_context->UnlockGL();
195         _current_context = newContext;
196         if (_current_context)
197 	        _current_context->LockGL();
198     }
199 private:
200     /* Event management */
_HandleBasicWindowEvent(BMessage * msg,int32 sdlEventType)201     void _HandleBasicWindowEvent(BMessage *msg, int32 sdlEventType) {
202         SDL_Window *win;
203         int32 winID;
204         if(
205             !_GetWinID(msg, &winID)
206         ) {
207             return;
208         }
209         win = GetSDLWindow(winID);
210         SDL_SendWindowEvent(win, sdlEventType, 0, 0);
211     }
212 
_HandleMouseMove(BMessage * msg)213     void _HandleMouseMove(BMessage *msg) {
214         SDL_Window *win;
215         int32 winID;
216         int32 x = 0, y = 0;
217         if(
218             !_GetWinID(msg, &winID) ||
219             msg->FindInt32("x", &x) != B_OK || /* x movement */
220             msg->FindInt32("y", &y) != B_OK    /* y movement */
221         ) {
222             return;
223         }
224         win = GetSDLWindow(winID);
225         SDL_SendMouseMotion(win, 0, 0, x, y);
226 
227         /* Tell the application that the mouse passed over, redraw needed */
228         BE_UpdateWindowFramebuffer(NULL,win,NULL,-1);
229     }
230 
_HandleMouseButton(BMessage * msg)231     void _HandleMouseButton(BMessage *msg) {
232         SDL_Window *win;
233         int32 winID;
234         int32 button, state;    /* left/middle/right, pressed/released */
235         if(
236             !_GetWinID(msg, &winID) ||
237             msg->FindInt32("button-id", &button) != B_OK ||
238             msg->FindInt32("button-state", &state) != B_OK
239         ) {
240             return;
241         }
242         win = GetSDLWindow(winID);
243         SDL_SendMouseButton(win, 0, state, button);
244     }
245 
_HandleMouseWheel(BMessage * msg)246     void _HandleMouseWheel(BMessage *msg) {
247         SDL_Window *win;
248         int32 winID;
249         int32 xTicks, yTicks;
250         if(
251             !_GetWinID(msg, &winID) ||
252             msg->FindInt32("xticks", &xTicks) != B_OK ||
253             msg->FindInt32("yticks", &yTicks) != B_OK
254         ) {
255             return;
256         }
257         win = GetSDLWindow(winID);
258         SDL_SendMouseWheel(win, 0, xTicks, yTicks, SDL_MOUSEWHEEL_NORMAL);
259     }
260 
_HandleKey(BMessage * msg)261     void _HandleKey(BMessage *msg) {
262         int32 scancode, state;  /* scancode, pressed/released */
263         if(
264             msg->FindInt32("key-state", &state) != B_OK ||
265             msg->FindInt32("key-scancode", &scancode) != B_OK
266         ) {
267             return;
268         }
269 
270         /* Make sure this isn't a repeated event (key pressed and held) */
271         if(state == SDL_PRESSED && BE_GetKeyState(scancode) == SDL_PRESSED) {
272             return;
273         }
274         BE_SetKeyState(scancode, state);
275         SDL_SendKeyboardKey(state, BE_GetScancodeFromBeKey(scancode));
276 
277         if (state == SDL_PRESSED && SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
278             const int8 *keyUtf8;
279             ssize_t count;
280             if (msg->FindData("key-utf8", B_INT8_TYPE, (const void**)&keyUtf8, &count) == B_OK) {
281                 char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
282                 SDL_zero(text);
283                 SDL_memcpy(text, keyUtf8, count);
284                 SDL_SendKeyboardText(text);
285             }
286         }
287     }
288 
_HandleMouseFocus(BMessage * msg)289     void _HandleMouseFocus(BMessage *msg) {
290         SDL_Window *win;
291         int32 winID;
292         bool bSetFocus; /* If false, lose focus */
293         if(
294             !_GetWinID(msg, &winID) ||
295             msg->FindBool("focusGained", &bSetFocus) != B_OK
296         ) {
297             return;
298         }
299         win = GetSDLWindow(winID);
300         if(bSetFocus) {
301             SDL_SetMouseFocus(win);
302         } else if(SDL_GetMouseFocus() == win) {
303             /* Only lose all focus if this window was the current focus */
304             SDL_SetMouseFocus(NULL);
305         }
306     }
307 
_HandleKeyboardFocus(BMessage * msg)308     void _HandleKeyboardFocus(BMessage *msg) {
309         SDL_Window *win;
310         int32 winID;
311         bool bSetFocus; /* If false, lose focus */
312         if(
313             !_GetWinID(msg, &winID) ||
314             msg->FindBool("focusGained", &bSetFocus) != B_OK
315         ) {
316             return;
317         }
318         win = GetSDLWindow(winID);
319         if(bSetFocus) {
320             SDL_SetKeyboardFocus(win);
321         } else if(SDL_GetKeyboardFocus() == win) {
322             /* Only lose all focus if this window was the current focus */
323             SDL_SetKeyboardFocus(NULL);
324         }
325     }
326 
_HandleWindowMoved(BMessage * msg)327     void _HandleWindowMoved(BMessage *msg) {
328         SDL_Window *win;
329         int32 winID;
330         int32 xPos, yPos;
331         /* Get the window id and new x/y position of the window */
332         if(
333             !_GetWinID(msg, &winID) ||
334             msg->FindInt32("window-x", &xPos) != B_OK ||
335             msg->FindInt32("window-y", &yPos) != B_OK
336         ) {
337             return;
338         }
339         win = GetSDLWindow(winID);
340         SDL_SendWindowEvent(win, SDL_WINDOWEVENT_MOVED, xPos, yPos);
341     }
342 
_HandleWindowResized(BMessage * msg)343     void _HandleWindowResized(BMessage *msg) {
344         SDL_Window *win;
345         int32 winID;
346         int32 w, h;
347         /* Get the window id ]and new x/y position of the window */
348         if(
349             !_GetWinID(msg, &winID) ||
350             msg->FindInt32("window-w", &w) != B_OK ||
351             msg->FindInt32("window-h", &h) != B_OK
352         ) {
353             return;
354         }
355         win = GetSDLWindow(winID);
356         SDL_SendWindowEvent(win, SDL_WINDOWEVENT_RESIZED, w, h);
357     }
358 
_GetWinID(BMessage * msg,int32 * winID)359     bool _GetWinID(BMessage *msg, int32 *winID) {
360         return msg->FindInt32("window-id", winID) == B_OK;
361     }
362 
363 
364 
365     /* Vector functions: Wraps vector stuff in case we need to change
366        implementation */
_SetSDLWindow(SDL_Window * win,int32 winID)367     void _SetSDLWindow(SDL_Window *win, int32 winID) {
368         _window_map[winID] = win;
369     }
370 
_GetNumWindowSlots()371     int32 _GetNumWindowSlots() {
372         return _window_map.size();
373     }
374 
375 
_PopBackWindow()376     void _PopBackWindow() {
377         _window_map.pop_back();
378     }
379 
_PushBackWindow(SDL_Window * win)380     void _PushBackWindow(SDL_Window *win) {
381         _window_map.push_back(win);
382     }
383 
384 
385     /* Members */
386     std::vector<SDL_Window*> _window_map; /* Keeps track of SDL_Windows by index-id */
387 
388     display_mode *_saved_mode;
389     BGLView      *_current_context;
390 };
391 
392 #endif
393