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