#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"
#include "SDL_video.h"
#include "../../events/SDL_events_c.h"
#include "../../video/haiku/SDL_bframebuffer.h"
#ifdef __cplusplus
}
#endif
#include <vector>
class SDL_BWin;
enum ToSDL {
BAPP_MOUSE_MOVED,
BAPP_MOUSE_BUTTON,
BAPP_MOUSE_WHEEL,
BAPP_KEY,
BAPP_REPAINT,
BAPP_MAXIMIZE,
BAPP_MINIMIZE,
BAPP_RESTORE,
BAPP_SHOW,
BAPP_HIDE,
BAPP_MOUSE_FOCUS,
BAPP_KEYBOARD_FOCUS,
BAPP_WINDOW_CLOSE_REQUESTED,
BAPP_WINDOW_MOVED,
BAPP_WINDOW_RESIZED,
BAPP_SCREEN_CHANGED
};
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) {
char filePath[512];
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;
}
virtual void MessageReceived(BMessage* message) {
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_WINDOWEVENT_EXPOSED);
break;
case BAPP_MAXIMIZE:
_HandleBasicWindowEvent(message, SDL_WINDOWEVENT_MAXIMIZED);
break;
case BAPP_MINIMIZE:
_HandleBasicWindowEvent(message, SDL_WINDOWEVENT_MINIMIZED);
break;
case BAPP_SHOW:
_HandleBasicWindowEvent(message, SDL_WINDOWEVENT_SHOWN);
break;
case BAPP_HIDE:
_HandleBasicWindowEvent(message, SDL_WINDOWEVENT_HIDDEN);
break;
case BAPP_MOUSE_FOCUS:
_HandleMouseFocus(message);
break;
case BAPP_KEYBOARD_FOCUS:
_HandleKeyboardFocus(message);
break;
case BAPP_WINDOW_CLOSE_REQUESTED:
_HandleBasicWindowEvent(message, SDL_WINDOWEVENT_CLOSE);
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:
break;
default:
BApplication::MessageReceived(message);
break;
}
}
int32 GetID(SDL_Window *win) {
int32 i;
for(i = 0; i < _GetNumWindowSlots(); ++i) {
if( GetSDLWindow(i) == NULL ) {
_SetSDLWindow(win, i);
return i;
}
}
if( i == _GetNumWindowSlots() ) {
_PushBackWindow(win);
return i;
}
return 0;
}
void ClearID(SDL_BWin *bwin);
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:
void _HandleBasicWindowEvent(BMessage *msg, int32 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 ||
msg->FindInt32("y", &y) != B_OK
) {
return;
}
win = GetSDLWindow(winID);
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(win, 0, SDL_GetMouse()->relative_mode, dx, dy);
set_mouse_position((winPosX + winWidth / 2), (winPosY + winHeight / 2));
if (!be_app->IsCursorHidden())
be_app->HideCursor();
} else {
SDL_SendMouseMotion(win, 0, 0, x, y);
if (SDL_ShowCursor(-1) && be_app->IsCursorHidden())
be_app->ShowCursor();
}
}
void _HandleMouseButton(BMessage *msg) {
SDL_Window *win;
int32 winID;
int32 button, state;
if(
!_GetWinID(msg, &winID) ||
msg->FindInt32("button-id", &button) != B_OK ||
msg->FindInt32("button-state", &state) != B_OK
) {
return;
}
win = GetSDLWindow(winID);
SDL_SendMouseButton(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(win, 0, xTicks, -yTicks, SDL_MOUSEWHEEL_NORMAL);
}
void _HandleKey(BMessage *msg) {
int32 scancode, state;
if(
msg->FindInt32("key-state", &state) != B_OK ||
msg->FindInt32("key-scancode", &scancode) != B_OK
) {
return;
}
if(state == SDL_PRESSED && HAIKU_GetKeyState(scancode) == SDL_PRESSED) {
return;
}
HAIKU_SetKeyState(scancode, state);
SDL_SendKeyboardKey(state, HAIKU_GetScancodeFromBeKey(scancode));
if (state == SDL_PRESSED && SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
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(
!_GetWinID(msg, &winID) ||
msg->FindBool("focusGained", &bSetFocus) != B_OK
) {
return;
}
win = GetSDLWindow(winID);
if(bSetFocus) {
SDL_SetMouseFocus(win);
} else if(SDL_GetMouseFocus() == win) {
SDL_SetMouseFocus(NULL);
}
}
void _HandleKeyboardFocus(BMessage *msg) {
SDL_Window *win;
int32 winID;
bool bSetFocus;
if(
!_GetWinID(msg, &winID) ||
msg->FindBool("focusGained", &bSetFocus) != B_OK
) {
return;
}
win = GetSDLWindow(winID);
if(bSetFocus) {
SDL_SetKeyboardFocus(win);
} else if(SDL_GetKeyboardFocus() == win) {
SDL_SetKeyboardFocus(NULL);
}
}
void _HandleWindowMoved(BMessage *msg) {
SDL_Window *win;
int32 winID;
int32 xPos, yPos;
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_WINDOWEVENT_MOVED, xPos, yPos);
}
void _HandleWindowResized(BMessage *msg) {
SDL_Window *win;
int32 winID;
int32 w, h;
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_WINDOWEVENT_RESIZED, w, h);
}
bool _GetWinID(BMessage *msg, int32 *winID) {
return msg->FindInt32("window-id", winID) == B_OK;
}
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);
}
std::vector<SDL_Window*> _window_map;
#if SDL_VIDEO_OPENGL
BGLView *_current_context;
#endif
};
#endif