123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- /*
- Simple DirectMedia Layer
- Copyright (C) 1997-2023 Sam Lantinga <[email protected]>
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #ifndef SDL_BAPP_H
- #define SDL_BAPP_H
- #include <Path.h>
- #include <InterfaceKit.h>
- #include <LocaleRoster.h>
- #if SDL_VIDEO_OPENGL
- #include <OpenGLKit.h>
- #endif
- #include "../../video/haiku/SDL_bkeyboard.h"
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include "SDL_internal.h"
- /* Local includes */
- #include "../../events/SDL_events_c.h"
- #include "../../video/haiku/SDL_bframebuffer.h"
- #ifdef __cplusplus
- }
- #endif
- #include <vector>
- /* Forward declarations */
- class SDL_BWin;
- /* Message constants */
- enum ToSDL
- {
- /* Intercepted by BWindow on its way to BView */
- BAPP_MOUSE_MOVED,
- BAPP_MOUSE_BUTTON,
- BAPP_MOUSE_WHEEL,
- BAPP_KEY,
- BAPP_REPAINT, /* from _UPDATE_ */
- /* From BWindow */
- BAPP_MAXIMIZE, /* from B_ZOOM */
- BAPP_MINIMIZE,
- BAPP_RESTORE, /* TODO: IMPLEMENT! */
- BAPP_SHOW,
- BAPP_HIDE,
- BAPP_MOUSE_FOCUS, /* caused by MOUSE_MOVE */
- BAPP_KEYBOARD_FOCUS, /* from WINDOW_ACTIVATED */
- BAPP_WINDOW_CLOSE_REQUESTED,
- BAPP_WINDOW_MOVED,
- BAPP_WINDOW_RESIZED,
- BAPP_SCREEN_CHANGED
- };
- /* Create a descendant of BApplication */
- class SDL_BApp : public BApplication
- {
- public:
- SDL_BApp(const char *signature) : BApplication(signature)
- {
- #if SDL_VIDEO_OPENGL
- _current_context = NULL;
- #endif
- }
- virtual ~SDL_BApp()
- {
- }
- virtual void RefsReceived(BMessage *message)
- {
- entry_ref entryRef;
- for (int32 i = 0; message->FindRef("refs", i, &entryRef) == B_OK; i++) {
- BPath referencePath = BPath(&entryRef);
- SDL_SendDropFile(NULL, referencePath.Path());
- }
- return;
- }
- /* Event-handling functions */
- virtual void MessageReceived(BMessage *message)
- {
- /* Sort out SDL-related messages */
- switch (message->what) {
- case BAPP_MOUSE_MOVED:
- _HandleMouseMove(message);
- break;
- case BAPP_MOUSE_BUTTON:
- _HandleMouseButton(message);
- break;
- case BAPP_MOUSE_WHEEL:
- _HandleMouseWheel(message);
- break;
- case BAPP_KEY:
- _HandleKey(message);
- break;
- case BAPP_REPAINT:
- _HandleBasicWindowEvent(message, SDL_EVENT_WINDOW_EXPOSED);
- break;
- case BAPP_MAXIMIZE:
- _HandleBasicWindowEvent(message, SDL_EVENT_WINDOW_MAXIMIZED);
- break;
- case BAPP_MINIMIZE:
- _HandleBasicWindowEvent(message, SDL_EVENT_WINDOW_MINIMIZED);
- break;
- case BAPP_SHOW:
- _HandleBasicWindowEvent(message, SDL_EVENT_WINDOW_SHOWN);
- break;
- case BAPP_HIDE:
- _HandleBasicWindowEvent(message, SDL_EVENT_WINDOW_HIDDEN);
- break;
- case BAPP_MOUSE_FOCUS:
- _HandleMouseFocus(message);
- break;
- case BAPP_KEYBOARD_FOCUS:
- _HandleKeyboardFocus(message);
- break;
- case BAPP_WINDOW_CLOSE_REQUESTED:
- _HandleBasicWindowEvent(message, SDL_EVENT_WINDOW_CLOSE_REQUESTED);
- break;
- case BAPP_WINDOW_MOVED:
- _HandleWindowMoved(message);
- break;
- case BAPP_WINDOW_RESIZED:
- _HandleWindowResized(message);
- break;
- case B_LOCALE_CHANGED:
- SDL_SendLocaleChangedEvent();
- break;
- case BAPP_SCREEN_CHANGED:
- /* TODO: Handle screen resize or workspace change */
- break;
- default:
- BApplication::MessageReceived(message);
- break;
- }
- }
- /* Window creation/destruction methods */
- int32 GetID(SDL_Window *win)
- {
- int32 i;
- for (i = 0; i < _GetNumWindowSlots(); ++i) {
- if (GetSDLWindow(i) == NULL) {
- _SetSDLWindow(win, i);
- return i;
- }
- }
- /* Expand the vector if all slots are full */
- if (i == _GetNumWindowSlots()) {
- _PushBackWindow(win);
- return i;
- }
- /* TODO: error handling */
- return 0;
- }
- /* FIXME: Bad coding practice, but I can't include SDL_BWin.h here. Is
- there another way to do this? */
- void ClearID(SDL_BWin *bwin); /* Defined in SDL_BeApp.cc */
- SDL_Window *GetSDLWindow(int32 winID)
- {
- return _window_map[winID];
- }
- #if SDL_VIDEO_OPENGL
- BGLView *GetCurrentContext()
- {
- return _current_context;
- }
- void SetCurrentContext(BGLView *newContext)
- {
- if (_current_context)
- _current_context->UnlockGL();
- _current_context = newContext;
- if (_current_context)
- _current_context->LockGL();
- }
- #endif
- private:
- /* Event management */
- void _HandleBasicWindowEvent(BMessage *msg, SDL_EventType sdlEventType)
- {
- SDL_Window *win;
- int32 winID;
- if (
- !_GetWinID(msg, &winID)) {
- return;
- }
- win = GetSDLWindow(winID);
- SDL_SendWindowEvent(win, sdlEventType, 0, 0);
- }
- void _HandleMouseMove(BMessage *msg)
- {
- SDL_Window *win;
- int32 winID;
- int32 x = 0, y = 0;
- if (
- !_GetWinID(msg, &winID) ||
- msg->FindInt32("x", &x) != B_OK || /* x movement */
- msg->FindInt32("y", &y) != B_OK /* y movement */
- ) {
- return;
- }
- win = GetSDLWindow(winID);
- // Simple relative mode support for mouse.
- if (SDL_GetMouse()->relative_mode) {
- int winWidth, winHeight, winPosX, winPosY;
- SDL_GetWindowSize(win, &winWidth, &winHeight);
- SDL_GetWindowPosition(win, &winPosX, &winPosY);
- int dx = x - (winWidth / 2);
- int dy = y - (winHeight / 2);
- SDL_SendMouseMotion(0, win, 0, SDL_GetMouse()->relative_mode, (float)dx, (float)dy);
- set_mouse_position((winPosX + winWidth / 2), (winPosY + winHeight / 2));
- if (!be_app->IsCursorHidden())
- be_app->HideCursor();
- } else {
- SDL_SendMouseMotion(0, win, 0, 0, (float)x, (float)y);
- if (SDL_CursorVisible() && be_app->IsCursorHidden())
- be_app->ShowCursor();
- }
- }
- void _HandleMouseButton(BMessage *msg)
- {
- SDL_Window *win;
- int32 winID;
- int32 button, state; /* left/middle/right, pressed/released */
- if (
- !_GetWinID(msg, &winID) ||
- msg->FindInt32("button-id", &button) != B_OK ||
- msg->FindInt32("button-state", &state) != B_OK) {
- return;
- }
- win = GetSDLWindow(winID);
- SDL_SendMouseButton(0, win, 0, state, button);
- }
- void _HandleMouseWheel(BMessage *msg)
- {
- SDL_Window *win;
- int32 winID;
- int32 xTicks, yTicks;
- if (
- !_GetWinID(msg, &winID) ||
- msg->FindInt32("xticks", &xTicks) != B_OK ||
- msg->FindInt32("yticks", &yTicks) != B_OK) {
- return;
- }
- win = GetSDLWindow(winID);
- SDL_SendMouseWheel(0, win, 0, xTicks, -yTicks, SDL_MOUSEWHEEL_NORMAL);
- }
- void _HandleKey(BMessage *msg)
- {
- int32 scancode, state; /* scancode, pressed/released */
- if (
- msg->FindInt32("key-state", &state) != B_OK ||
- msg->FindInt32("key-scancode", &scancode) != B_OK) {
- return;
- }
- /* Make sure this isn't a repeated event (key pressed and held) */
- if (state == SDL_PRESSED && HAIKU_GetKeyState(scancode) == SDL_PRESSED) {
- return;
- }
- HAIKU_SetKeyState(scancode, state);
- SDL_SendKeyboardKey(0, state, HAIKU_GetScancodeFromBeKey(scancode));
- if (state == SDL_PRESSED && SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) {
- const int8 *keyUtf8;
- ssize_t count;
- if (msg->FindData("key-utf8", B_INT8_TYPE, (const void **)&keyUtf8, &count) == B_OK) {
- char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
- SDL_zeroa(text);
- SDL_memcpy(text, keyUtf8, count);
- SDL_SendKeyboardText(text);
- }
- }
- }
- void _HandleMouseFocus(BMessage *msg)
- {
- SDL_Window *win;
- int32 winID;
- bool bSetFocus; /* If false, lose focus */
- if (
- !_GetWinID(msg, &winID) ||
- msg->FindBool("focusGained", &bSetFocus) != B_OK) {
- return;
- }
- win = GetSDLWindow(winID);
- if (bSetFocus) {
- SDL_SetMouseFocus(win);
- } else if (SDL_GetMouseFocus() == win) {
- /* Only lose all focus if this window was the current focus */
- SDL_SetMouseFocus(NULL);
- }
- }
- void _HandleKeyboardFocus(BMessage *msg)
- {
- SDL_Window *win;
- int32 winID;
- bool bSetFocus; /* If false, lose focus */
- if (
- !_GetWinID(msg, &winID) ||
- msg->FindBool("focusGained", &bSetFocus) != B_OK) {
- return;
- }
- win = GetSDLWindow(winID);
- if (bSetFocus) {
- SDL_SetKeyboardFocus(win);
- } else if (SDL_GetKeyboardFocus() == win) {
- /* Only lose all focus if this window was the current focus */
- SDL_SetKeyboardFocus(NULL);
- }
- }
- void _HandleWindowMoved(BMessage *msg)
- {
- SDL_Window *win;
- int32 winID;
- int32 xPos, yPos;
- /* Get the window id and new x/y position of the window */
- if (
- !_GetWinID(msg, &winID) ||
- msg->FindInt32("window-x", &xPos) != B_OK ||
- msg->FindInt32("window-y", &yPos) != B_OK) {
- return;
- }
- win = GetSDLWindow(winID);
- SDL_SendWindowEvent(win, SDL_EVENT_WINDOW_MOVED, xPos, yPos);
- }
- void _HandleWindowResized(BMessage *msg)
- {
- SDL_Window *win;
- int32 winID;
- int32 w, h;
- /* Get the window id ]and new x/y position of the window */
- if (
- !_GetWinID(msg, &winID) ||
- msg->FindInt32("window-w", &w) != B_OK ||
- msg->FindInt32("window-h", &h) != B_OK) {
- return;
- }
- win = GetSDLWindow(winID);
- SDL_SendWindowEvent(win, SDL_EVENT_WINDOW_RESIZED, w, h);
- }
- bool _GetWinID(BMessage *msg, int32 *winID)
- {
- return msg->FindInt32("window-id", winID) == B_OK;
- }
- /* Vector functions: Wraps vector stuff in case we need to change
- implementation */
- void _SetSDLWindow(SDL_Window *win, int32 winID)
- {
- _window_map[winID] = win;
- }
- int32 _GetNumWindowSlots()
- {
- return _window_map.size();
- }
- void _PopBackWindow()
- {
- _window_map.pop_back();
- }
- void _PushBackWindow(SDL_Window *win)
- {
- _window_map.push_back(win);
- }
- /* Members */
- std::vector<SDL_Window *> _window_map; /* Keeps track of SDL_Windows by index-id */
- #if SDL_VIDEO_OPENGL
- BGLView *_current_context;
- #endif
- };
- #endif
|