diff --git a/src/video/bwindow/SDL_BWin.h b/src/video/bwindow/SDL_BWin.h index c3dfc1a51..b232534d1 100644 --- a/src/video/bwindow/SDL_BWin.h +++ b/src/video/bwindow/SDL_BWin.h @@ -35,6 +35,7 @@ static char rcsid = #ifdef HAVE_OPENGL #include #endif +#include #include "SDL_BeApp.h" #include "SDL_events.h" @@ -49,6 +50,9 @@ class SDL_BWin : public BDirectWindow public: SDL_BWin(BRect bounds) : BDirectWindow(bounds, "Untitled", B_TITLED_WINDOW, 0) { + InitKeyboard(); + last_buttons = 0; + the_view = NULL; #ifdef HAVE_OPENGL SDL_GLView = NULL; @@ -58,6 +62,7 @@ public: shown = false; inhibit_resize = false; } + virtual ~SDL_BWin() { Lock(); if ( the_view ) { @@ -79,6 +84,119 @@ public: delete SDL_View; } } + + virtual void InitKeyboard(void) { + for ( uint i=0; i 127) { + state = 0; + srclen = strlen(buf); + dstlen = sizeof(destbuf); + convert_from_utf8(B_UNICODE_CONVERSION, buf, &srclen, (char *)destbuf, &dstlen, &state); + unicode = destbuf[0]; + unicode <<= 8; + unicode |= destbuf[1]; + } else + unicode = buf[0]; + + /* For some reason function keys map to control characters */ +# define CTRL(X) ((X)-'@') + switch (unicode) { + case CTRL('A'): + case CTRL('B'): + case CTRL('C'): + case CTRL('D'): + case CTRL('E'): + case CTRL('K'): + case CTRL('L'): + case CTRL('P'): + if ( ! (SDL_GetModState() & KMOD_CTRL) ) + unicode = 0; + break; + /* Keyboard input maps newline to carriage return */ + case '\n': + unicode = '\r'; + break; + default: + break; + } + + return unicode; + } + + virtual void DispatchMessage(BMessage *msg, BHandler *target) { + switch (msg->what) { + case B_MOUSE_MOVED: + { + BPoint where; + int32 transit; + if (msg->FindPoint("where", &where) == B_OK && msg->FindInt32("be:transit", &transit) == B_OK) { + if (transit == B_EXITED_VIEW) { + if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { + SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); + be_app->SetCursor(B_HAND_CURSOR); + } + } else { + int x, y; + if ( ! (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { + SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); + SDL_SetCursor(NULL); + } + GetXYOffset(x, y); + x = (int)where.x - x; + y = (int)where.y - y; + SDL_PrivateMouseMotion(0, 0, x, y); + } + } + break; + } + + case B_MOUSE_DOWN: + { + /* it looks like mouse down is send only for first clicked + button, each next is not send while last one is holded */ + int32 buttons; + int sdl_buttons = 0; + if (msg->FindInt32("buttons", &buttons) == B_OK) { + /* Add any mouse button events */ + if (buttons & B_PRIMARY_MOUSE_BUTTON) { + sdl_buttons |= SDL_BUTTON_LEFT; + } + if (buttons & B_SECONDARY_MOUSE_BUTTON) { + sdl_buttons |= SDL_BUTTON_RIGHT; + } + if (buttons & B_TERTIARY_MOUSE_BUTTON) { + sdl_buttons |= SDL_BUTTON_MIDDLE; + } + SDL_PrivateMouseButton(SDL_PRESSED, sdl_buttons, 0, 0); + + last_buttons = buttons; + } + break; + } + + case B_MOUSE_UP: + { + /* mouse up doesn't give which button was released, + only state of buttons (after release, so it's always = 0), + which is is not what we need ;] + So we need to store button in mouse down, and restore + in mouse up :( + mouse up is (similarly to mouse down) send only when + no more buttons are down */ + int32 buttons; + int sdl_buttons = 0; + if (msg->FindInt32("buttons", &buttons) == B_OK) { + /* Add any mouse button events */ + if ((buttons ^ B_PRIMARY_MOUSE_BUTTON) & last_buttons) { + sdl_buttons |= SDL_BUTTON_LEFT; + } + if ((buttons ^ B_SECONDARY_MOUSE_BUTTON) & last_buttons) { + sdl_buttons |= SDL_BUTTON_RIGHT; + } + if ((buttons ^ B_TERTIARY_MOUSE_BUTTON) & last_buttons) { + sdl_buttons |= SDL_BUTTON_MIDDLE; + } + SDL_PrivateMouseButton(SDL_RELEASED, sdl_buttons, 0, 0); + + last_buttons = buttons; + } + break; + } + + case B_MOUSE_WHEEL_CHANGED: + { + float x, y; + x = y = 0; + if (msg->FindFloat("be:wheel_delta_x", &x) == B_OK && msg->FindFloat("be:wheel_delta_y", &y) == B_OK) { + if (x < 0 || y < 0) { + SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELDOWN, 0, 0); + SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELDOWN, 0, 0); + } else if (x > 0 || y > 0) { + SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELUP, 0, 0); + SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELUP, 0, 0); + } + } + break; + } + + case B_KEY_DOWN: + case B_UNMAPPED_KEY_DOWN: /* modifier keys are unmapped */ + { + int32 key; + int32 modifiers; + if (msg->FindInt32("key", &key) == B_OK && msg->FindInt32("modifiers", &modifiers) == B_OK) { + SDL_keysym keysym; + keysym.scancode = key; + if (key < 128) { + keysym.sym = keymap[key]; + } else { + keysym.sym = SDLK_UNKNOWN; + } + /* FIX THIS? + it seems SDL_PrivateKeyboard() changes mod value + anyway, and doesn't care about what we setup here */ + keysym.mod = KMOD_NONE; + keysym.unicode = 0; + if (SDL_TranslateUNICODE) { + const char *bytes; + if (msg->FindString("bytes", &bytes) == B_OK) { + /* FIX THIS? + this cares only about first "letter", + so if someone maps some key to print + "BeOS rulez!" only "B" will be used. */ + keysym.unicode = Translate2Unicode(bytes); + } + } + SDL_PrivateKeyboard(SDL_PRESSED, &keysym); + } + break; + } + + case B_KEY_UP: + case B_UNMAPPED_KEY_UP: /* modifier keys are unmapped */ + { + int32 key; + int32 modifiers; + if (msg->FindInt32("key", &key) == B_OK && msg->FindInt32("modifiers", &modifiers) == B_OK) { + SDL_keysym keysym; + keysym.scancode = key; + if (key < 128) { + keysym.sym = keymap[key]; + } else { + keysym.sym = SDLK_UNKNOWN; + } + keysym.mod = KMOD_NONE; /* FIX THIS? */ + keysym.unicode = 0; + if (SDL_TranslateUNICODE) { + const char *bytes; + if (msg->FindString("bytes", &bytes) == B_OK) { + keysym.unicode = Translate2Unicode(bytes); + } + } + SDL_PrivateKeyboard(SDL_RELEASED, &keysym); + } + break; + } + + default: + /* move it after switch{} so it's always handled + that way we keep BeOS feautures like: + - CTRL+Q to close window (and other shortcuts) + - PrintScreen to make screenshot into /boot/home + - etc.. */ + //BDirectWindow::DispatchMessage(msg, target); + break; + } + BDirectWindow::DispatchMessage(msg, target); + } + private: #ifdef HAVE_OPENGL BGLView *SDL_GLView; @@ -220,6 +546,9 @@ private: bool shown; bool inhibit_resize; + + int32 last_buttons; + SDLKey keymap[128]; }; #endif /* _SDL_BWin_h */ diff --git a/src/video/bwindow/SDL_lowvideo.h b/src/video/bwindow/SDL_lowvideo.h index d65f3ef64..b12b105b5 100644 --- a/src/video/bwindow/SDL_lowvideo.h +++ b/src/video/bwindow/SDL_lowvideo.h @@ -49,14 +49,6 @@ struct SDL_PrivateVideoData { /* A completely clear cursor */ WMcursor *BlankCursor; - /* Mouse state variables */ - uint32 last_buttons; - BPoint last_point; - - /* Keyboard state variables */ - int key_flip; - struct key_info keyinfo[2]; - SDL_Overlay *overlay; }; /* Old variable names */ @@ -65,10 +57,6 @@ struct SDL_PrivateVideoData { #define SDL_nummodes (_this->hidden->SDL_nummodes) #define SDL_modelist (_this->hidden->SDL_modelist) #define SDL_BlankCursor (_this->hidden->BlankCursor) -#define last_buttons (_this->hidden->last_buttons) -#define last_point (_this->hidden->last_point) -#define key_flip (_this->hidden->key_flip) -#define keyinfo (_this->hidden->keyinfo) #define current_overlay (_this->hidden->overlay) #endif /* _SDL_lowvideo_h */ diff --git a/src/video/bwindow/SDL_sysevents.cc b/src/video/bwindow/SDL_sysevents.cc index 08cc4406e..12ff1eb5c 100644 --- a/src/video/bwindow/SDL_sysevents.cc +++ b/src/video/bwindow/SDL_sysevents.cc @@ -39,403 +39,12 @@ extern "C" { #include "SDL_sysevents.h" #include "SDL_sysevents_c.h" -/* A note on why the polling loops are necessary. - The BeOS Preview 2 implementation of BView->MouseMoved() only notifies - the view when the mouse enters or leaves the view. The documentation - says that you should loop and use GetMouse() to detect mouse motion. - The BeOS Preview 2 implementation of BView->KeyDown() and BView->KeyUp() - are only called for keys that generate ASCII characters. Since we want - to act like a low level raw keyboard, we need to poll the state of the - keys instead of catching the keys in callbacks. - These are documented portions of the BeBook for Preview Release 2 -*/ - -/* Table to convert scancodes to SDL virtual keys */ -static SDLKey keymap[128]; - -/* Function to convert from a key scancode to a UNICODE character */ -static key_map *be_keymap; -static int32 *option_caps_map[2], *option_map[2], *caps_map[2], *normal_map[2]; -static char *unicode_map; -static Uint16 TranslateScancode(int scancode) -{ - SDLMod modstate; - int shifted; - int32 index; /* Index into system unicode map */ - Uint16 unicode; - - /* Set the default character -- no character */ - unicode = 0; - - /* See whether or not the shift state is set */ - modstate = SDL_GetModState(); - if ( modstate & KMOD_SHIFT ) { - shifted = 1; - } else { - shifted = 0; - } - - if ( modstate & KMOD_NUM ) { - /* If numlock is on, numeric keypad keys have shift state inverted */ - switch (keymap[scancode]) { - case SDLK_KP0: - case SDLK_KP1: - case SDLK_KP2: - case SDLK_KP3: - case SDLK_KP4: - case SDLK_KP5: - case SDLK_KP6: - case SDLK_KP7: - case SDLK_KP8: - case SDLK_KP9: - case SDLK_KP_PERIOD: - case SDLK_KP_DIVIDE: - case SDLK_KP_MULTIPLY: - case SDLK_KP_MINUS: - case SDLK_KP_PLUS: - case SDLK_KP_ENTER: - case SDLK_KP_EQUALS: - shifted = !shifted; - break; - default: - break; - } - } - - /* Get the index based on modifier state */ - if ( modstate & KMOD_CTRL ) - index = be_keymap->control_map[scancode]; - else - if ( (modstate & KMOD_META) && (modstate & KMOD_CAPS) ) - index = option_caps_map[shifted][scancode]; - else - if ( modstate & KMOD_META ) - index = option_map[shifted][scancode]; - else - if ( modstate & KMOD_CAPS ) - index = caps_map[shifted][scancode]; - else - index = normal_map[shifted][scancode]; - - /* If there is a mapping, convert character from UTF-8 to UNICODE */ - if ( unicode_map[index] ) { - int32 state, srclen, dstlen; - unsigned char destbuf[2]; - - state = 0; - srclen = unicode_map[index++]; - dstlen = sizeof(destbuf); - convert_from_utf8(B_UNICODE_CONVERSION, - &unicode_map[index], &srclen, (char *)destbuf, &dstlen, - &state); - unicode = destbuf[0]; - unicode <<= 8; - unicode |= destbuf[1]; - - /* Keyboard input maps newline to carriage return */ - if ( unicode == '\n' ) { - unicode = '\r'; - } - - /* For some reason function keys map to control characters */ -# define CTRL(X) ((X)-'@') - switch (unicode) { - case CTRL('A'): - case CTRL('B'): - case CTRL('C'): - case CTRL('D'): - case CTRL('E'): - case CTRL('K'): - case CTRL('L'): - case CTRL('P'): - if ( ! (modstate & KMOD_CTRL) ) - unicode = 0; - break; - default: - break; - } - } - return(unicode); -} - -/* Function to translate a keyboard transition and queue the key event */ -static void QueueKey(int scancode, int pressed) -{ - SDL_keysym keysym; - - /* Set the keysym information */ - keysym.scancode = scancode; - keysym.sym = keymap[scancode]; - keysym.mod = KMOD_NONE; - if ( SDL_TranslateUNICODE ) { - keysym.unicode = TranslateScancode(scancode); - } else { - keysym.unicode = 0; - } - - /* NUMLOCK and CAPSLOCK are implemented as double-presses in reality */ - if ( (keysym.sym == SDLK_NUMLOCK) || (keysym.sym == SDLK_CAPSLOCK) ) { - pressed = 1; - } - - /* Queue the key event */ - if ( pressed ) { - SDL_PrivateKeyboard(SDL_PRESSED, &keysym); - } else { - SDL_PrivateKeyboard(SDL_RELEASED, &keysym); - } -} - -/* This is special because we know it will be run in a loop in a separate - thread. Normally this function should loop as long as there are input - states changing, i.e. new events arriving. -*/ void BE_PumpEvents(_THIS) { - BView *view; - BRect bounds; - BPoint point; - uint32 buttons; - const uint32 button_masks[3] = { - B_PRIMARY_MOUSE_BUTTON, - B_TERTIARY_MOUSE_BUTTON, - B_SECONDARY_MOUSE_BUTTON, - }; - unsigned int i, j; - - /* Check out the mouse buttons and position (slight race condition) */ - if ( SDL_Win->Lock() ) { - /* Don't do anything if we have no view */ - view = SDL_Win->View(); - if ( ! view ) { - SDL_Win->Unlock(); - return; - } - bounds = view->Bounds(); - /* Get new input state, if still active */ - if ( SDL_Win->IsActive() ) { - key_flip = !key_flip; - get_key_info(&keyinfo[key_flip]); - view->GetMouse(&point, &buttons, true); - } else { - key_flip = key_flip; - point = last_point; - buttons = last_buttons; - } - SDL_Win->Unlock(); - } else { - return; - } - - /* If our view is active, we'll find key changes here */ - if ( memcmp(keyinfo[0].key_states, keyinfo[1].key_states, 16) != 0 ) { - for ( i=0; i<16; ++i ) { - Uint8 new_state, transition; - - new_state = keyinfo[key_flip].key_states[i]; - transition = keyinfo[!key_flip].key_states[i] ^ - keyinfo[ key_flip].key_states[i]; - for ( j=0; j<8; ++j ) { - if ( transition&0x80 ) - QueueKey(i*8+j, new_state&0x80); - transition <<= 1; - new_state <<= 1; - } - } - } - - /* We check keyboard, but not mouse if mouse isn't in window */ - if ( ! bounds.Contains(point) ) { - /* Mouse moved outside our view? */ - if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { - SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); - be_app->SetCursor(B_HAND_CURSOR); - } - return; - } - /* Has the mouse moved back into our view? */ - if ( ! (SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { - /* Reset the B_HAND_CURSOR to our own */ - SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); - SDL_SetCursor(NULL); - } - - /* Check for mouse motion */ - if ( point != last_point ) { - int x, y; - - SDL_Win->GetXYOffset(x, y); - x = (int)point.x - x; - y = (int)point.y - y; - SDL_PrivateMouseMotion(0, 0, x, y); - } - last_point = point; - - /* Add any mouse button events */ - for ( i=0; i and BeOS keyboard info */ - for ( i=0; icaps_key] = SDLK_CAPSLOCK; - keymap[be_keymap->scroll_key] = SDLK_SCROLLOCK; - keymap[be_keymap->num_key] = SDLK_NUMLOCK; - keymap[be_keymap->left_shift_key] = SDLK_LSHIFT; - keymap[be_keymap->right_shift_key] = SDLK_RSHIFT; - keymap[be_keymap->left_command_key] = SDLK_LALT; - keymap[be_keymap->right_command_key] = SDLK_RALT; - keymap[be_keymap->left_control_key] = SDLK_LCTRL; - keymap[be_keymap->right_control_key] = SDLK_RCTRL; - keymap[be_keymap->left_option_key] = SDLK_LMETA; - keymap[be_keymap->right_option_key] = SDLK_RMETA; - keymap[be_keymap->menu_key] = SDLK_MENU; - - /* Set the modifier map pointers */ - option_caps_map[0] = be_keymap->option_caps_map; - option_caps_map[1] = be_keymap->option_caps_shift_map; - option_map[0] = be_keymap->option_map; - option_map[1] = be_keymap->option_shift_map; - caps_map[0] = be_keymap->caps_map; - caps_map[1] = be_keymap->caps_shift_map; - normal_map[0] = be_keymap->normal_map; - normal_map[1] = be_keymap->shift_map; } }; /* Extern C */