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