| 1 | /* |
| 2 | SDL - Simple DirectMedia Layer |
| 3 | Copyright (C) 1997-2009 Sam Lantinga |
| 4 | |
| 5 | This library is free software; you can redistribute it and/or |
| 6 | modify it under the terms of the GNU Lesser General Public |
| 7 | License as published by the Free Software Foundation; either |
| 8 | version 2.1 of the License, or (at your option) any later version. |
| 9 | |
| 10 | This library is distributed in the hope that it will be useful, |
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 | Lesser General Public License for more details. |
| 14 | |
| 15 | You should have received a copy of the GNU Lesser General Public |
| 16 | License along with this library; if not, write to the Free Software |
| 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 18 | |
| 19 | Sam Lantinga |
| 20 | slouken@libsdl.org |
| 21 | */ |
| 22 | #include "SDL_config.h" |
| 23 | |
| 24 | #include <support/UTF8.h> |
| 25 | #include <stdio.h> |
| 26 | #include <string.h> |
| 27 | #include "SDL_error.h" |
| 28 | #include "SDL_events.h" |
| 29 | #include "SDL_BWin.h" |
| 30 | #include "SDL_lowvideo.h" |
| 31 | |
| 32 | static SDLKey keymap[128]; |
| 33 | int mouse_relative = 0; |
| 34 | extern "C" { |
| 35 | |
| 36 | #include "../../events/SDL_sysevents.h" |
| 37 | #include "../../events/SDL_events_c.h" |
| 38 | #include "SDL_sysevents_c.h" |
| 39 | |
| 40 | void BE_PumpEvents(_THIS) |
| 41 | { |
| 42 | } |
| 43 | |
| 44 | void BE_InitOSKeymap(_THIS) |
| 45 | { |
| 46 | for ( uint i=0; i<SDL_TABLESIZE(keymap); ++i ) |
| 47 | keymap[i] = SDLK_UNKNOWN; |
| 48 | |
| 49 | keymap[0x01] = SDLK_ESCAPE; |
| 50 | keymap[B_F1_KEY] = SDLK_F1; |
| 51 | keymap[B_F2_KEY] = SDLK_F2; |
| 52 | keymap[B_F3_KEY] = SDLK_F3; |
| 53 | keymap[B_F4_KEY] = SDLK_F4; |
| 54 | keymap[B_F5_KEY] = SDLK_F5; |
| 55 | keymap[B_F6_KEY] = SDLK_F6; |
| 56 | keymap[B_F7_KEY] = SDLK_F7; |
| 57 | keymap[B_F8_KEY] = SDLK_F8; |
| 58 | keymap[B_F9_KEY] = SDLK_F9; |
| 59 | keymap[B_F10_KEY] = SDLK_F10; |
| 60 | keymap[B_F11_KEY] = SDLK_F11; |
| 61 | keymap[B_F12_KEY] = SDLK_F12; |
| 62 | keymap[B_PRINT_KEY] = SDLK_PRINT; |
| 63 | keymap[B_SCROLL_KEY] = SDLK_SCROLLOCK; |
| 64 | keymap[B_PAUSE_KEY] = SDLK_PAUSE; |
| 65 | keymap[0x11] = SDLK_BACKQUOTE; |
| 66 | keymap[0x12] = SDLK_1; |
| 67 | keymap[0x13] = SDLK_2; |
| 68 | keymap[0x14] = SDLK_3; |
| 69 | keymap[0x15] = SDLK_4; |
| 70 | keymap[0x16] = SDLK_5; |
| 71 | keymap[0x17] = SDLK_6; |
| 72 | keymap[0x18] = SDLK_7; |
| 73 | keymap[0x19] = SDLK_8; |
| 74 | keymap[0x1a] = SDLK_9; |
| 75 | keymap[0x1b] = SDLK_0; |
| 76 | keymap[0x1c] = SDLK_MINUS; |
| 77 | keymap[0x1d] = SDLK_EQUALS; |
| 78 | keymap[0x1e] = SDLK_BACKSPACE; |
| 79 | keymap[0x1f] = SDLK_INSERT; |
| 80 | keymap[0x20] = SDLK_HOME; |
| 81 | keymap[0x21] = SDLK_PAGEUP; |
| 82 | keymap[0x22] = SDLK_NUMLOCK; |
| 83 | keymap[0x23] = SDLK_KP_DIVIDE; |
| 84 | keymap[0x24] = SDLK_KP_MULTIPLY; |
| 85 | keymap[0x25] = SDLK_KP_MINUS; |
| 86 | keymap[0x26] = SDLK_TAB; |
| 87 | keymap[0x27] = SDLK_q; |
| 88 | keymap[0x28] = SDLK_w; |
| 89 | keymap[0x29] = SDLK_e; |
| 90 | keymap[0x2a] = SDLK_r; |
| 91 | keymap[0x2b] = SDLK_t; |
| 92 | keymap[0x2c] = SDLK_y; |
| 93 | keymap[0x2d] = SDLK_u; |
| 94 | keymap[0x2e] = SDLK_i; |
| 95 | keymap[0x2f] = SDLK_o; |
| 96 | keymap[0x30] = SDLK_p; |
| 97 | keymap[0x31] = SDLK_LEFTBRACKET; |
| 98 | keymap[0x32] = SDLK_RIGHTBRACKET; |
| 99 | keymap[0x33] = SDLK_BACKSLASH; |
| 100 | keymap[0x34] = SDLK_DELETE; |
| 101 | keymap[0x35] = SDLK_END; |
| 102 | keymap[0x36] = SDLK_PAGEDOWN; |
| 103 | keymap[0x37] = SDLK_KP7; |
| 104 | keymap[0x38] = SDLK_KP8; |
| 105 | keymap[0x39] = SDLK_KP9; |
| 106 | keymap[0x3a] = SDLK_KP_PLUS; |
| 107 | keymap[0x3b] = SDLK_CAPSLOCK; |
| 108 | keymap[0x3c] = SDLK_a; |
| 109 | keymap[0x3d] = SDLK_s; |
| 110 | keymap[0x3e] = SDLK_d; |
| 111 | keymap[0x3f] = SDLK_f; |
| 112 | keymap[0x40] = SDLK_g; |
| 113 | keymap[0x41] = SDLK_h; |
| 114 | keymap[0x42] = SDLK_j; |
| 115 | keymap[0x43] = SDLK_k; |
| 116 | keymap[0x44] = SDLK_l; |
| 117 | keymap[0x45] = SDLK_SEMICOLON; |
| 118 | keymap[0x46] = SDLK_QUOTE; |
| 119 | keymap[0x47] = SDLK_RETURN; |
| 120 | keymap[0x48] = SDLK_KP4; |
| 121 | keymap[0x49] = SDLK_KP5; |
| 122 | keymap[0x4a] = SDLK_KP6; |
| 123 | keymap[0x4b] = SDLK_LSHIFT; |
| 124 | keymap[0x4c] = SDLK_z; |
| 125 | keymap[0x4d] = SDLK_x; |
| 126 | keymap[0x4e] = SDLK_c; |
| 127 | keymap[0x4f] = SDLK_v; |
| 128 | keymap[0x50] = SDLK_b; |
| 129 | keymap[0x51] = SDLK_n; |
| 130 | keymap[0x52] = SDLK_m; |
| 131 | keymap[0x53] = SDLK_COMMA; |
| 132 | keymap[0x54] = SDLK_PERIOD; |
| 133 | keymap[0x55] = SDLK_SLASH; |
| 134 | keymap[0x56] = SDLK_RSHIFT; |
| 135 | keymap[0x57] = SDLK_UP; |
| 136 | keymap[0x58] = SDLK_KP1; |
| 137 | keymap[0x59] = SDLK_KP2; |
| 138 | keymap[0x5a] = SDLK_KP3; |
| 139 | keymap[0x5b] = SDLK_KP_ENTER; |
| 140 | keymap[0x5c] = SDLK_LCTRL; |
| 141 | keymap[0x5d] = SDLK_LALT; |
| 142 | keymap[0x5e] = SDLK_SPACE; |
| 143 | keymap[0x5f] = SDLK_RALT; |
| 144 | keymap[0x60] = SDLK_RCTRL; |
| 145 | keymap[0x61] = SDLK_LEFT; |
| 146 | keymap[0x62] = SDLK_DOWN; |
| 147 | keymap[0x63] = SDLK_RIGHT; |
| 148 | keymap[0x64] = SDLK_KP0; |
| 149 | keymap[0x65] = SDLK_KP_PERIOD; |
| 150 | keymap[0x66] = SDLK_LMETA; |
| 151 | keymap[0x67] = SDLK_RMETA; |
| 152 | keymap[0x68] = SDLK_MENU; |
| 153 | keymap[0x69] = SDLK_EURO; |
| 154 | keymap[0x6a] = SDLK_KP_EQUALS; |
| 155 | keymap[0x6b] = SDLK_POWER; |
| 156 | } |
| 157 | |
| 158 | }; /* Extern C */ |
| 159 | |
| 160 | void SDL_BWin::DispatchMessage(BMessage *msg, BHandler *target) |
| 161 | { |
| 162 | switch (msg->what) { |
| 163 | case B_MOUSE_MOVED: |
| 164 | { |
| 165 | SDL_VideoDevice *view = current_video; |
| 166 | BPoint where; |
| 167 | int32 transit; |
| 168 | if (msg->FindPoint("where", &where) == B_OK && msg->FindInt32("be:transit", &transit) == B_OK) { |
| 169 | int x, y; |
| 170 | |
| 171 | GetXYOffset(x, y); |
| 172 | x = (int)where.x - x; |
| 173 | y = (int)where.y - y; |
| 174 | |
| 175 | //BeSman: I need another method for cursor catching !!! |
| 176 | if (view->input_grab != SDL_GRAB_OFF) |
| 177 | { |
| 178 | bool clipped = false; |
| 179 | if ( x < 0 ) { |
| 180 | x = 0; |
| 181 | clipped = true; |
| 182 | } else if ( x >= SDL_VideoSurface->w ) { |
| 183 | x = (SDL_VideoSurface->w-1); |
| 184 | clipped = true; |
| 185 | } |
| 186 | if ( y < 0 ) { |
| 187 | y = 0; |
| 188 | clipped = true; |
| 189 | } else if ( y >= SDL_VideoSurface->h ) { |
| 190 | y = (SDL_VideoSurface->h-1); |
| 191 | clipped = true; |
| 192 | } |
| 193 | if ( clipped ) { |
| 194 | BPoint edge; |
| 195 | GetXYOffset(edge.x, edge.y); |
| 196 | edge.x += x; |
| 197 | edge.y += y; |
| 198 | ConvertToScreen(&edge); |
| 199 | set_mouse_position((int)edge.x, (int)edge.y); |
| 200 | } |
| 201 | transit = B_INSIDE_VIEW; |
| 202 | } |
| 203 | if (transit == B_EXITED_VIEW) { |
| 204 | if ( SDL_GetAppState() & SDL_APPMOUSEFOCUS ) { |
| 205 | SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); |
| 206 | be_app->SetCursor(B_HAND_CURSOR); |
| 207 | } |
| 208 | } else { |
| 209 | if ( !(SDL_GetAppState() & SDL_APPMOUSEFOCUS) ) { |
| 210 | SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); |
| 211 | SDL_SetCursor(NULL); |
| 212 | } |
| 213 | |
| 214 | if ( mouse_relative ) { |
| 215 | int half_w = (SDL_VideoSurface->w/2); |
| 216 | int half_h = (SDL_VideoSurface->h/2); |
| 217 | x -= half_w; |
| 218 | y -= half_h; |
| 219 | if ( x || y ) { |
| 220 | BPoint center; |
| 221 | GetXYOffset(center.x, center.y); |
| 222 | center.x += half_w; |
| 223 | center.y += half_h; |
| 224 | ConvertToScreen(¢er); |
| 225 | set_mouse_position((int)center.x, (int)center.y); |
| 226 | SDL_PrivateMouseMotion(0, 1, x, y); |
| 227 | } |
| 228 | } else { |
| 229 | SDL_PrivateMouseMotion(0, 0, x, y); |
| 230 | } |
| 231 | } |
| 232 | } |
| 233 | break; |
| 234 | } |
| 235 | |
| 236 | case B_MOUSE_DOWN: |
| 237 | { |
| 238 | /* it looks like mouse down is send only for first clicked |
| 239 | button, each next is not send while last one is holded */ |
| 240 | int32 buttons; |
| 241 | int sdl_buttons = 0; |
| 242 | if (msg->FindInt32("buttons", &buttons) == B_OK) { |
| 243 | /* Add any mouse button events */ |
| 244 | if (buttons & B_PRIMARY_MOUSE_BUTTON) { |
| 245 | sdl_buttons |= SDL_BUTTON_LEFT; |
| 246 | } |
| 247 | if (buttons & B_SECONDARY_MOUSE_BUTTON) { |
| 248 | sdl_buttons |= SDL_BUTTON_RIGHT; |
| 249 | } |
| 250 | if (buttons & B_TERTIARY_MOUSE_BUTTON) { |
| 251 | sdl_buttons |= SDL_BUTTON_MIDDLE; |
| 252 | } |
| 253 | SDL_PrivateMouseButton(SDL_PRESSED, sdl_buttons, 0, 0); |
| 254 | |
| 255 | last_buttons = buttons; |
| 256 | } |
| 257 | break; |
| 258 | } |
| 259 | |
| 260 | case B_MOUSE_UP: |
| 261 | { |
| 262 | /* mouse up doesn't give which button was released, |
| 263 | only state of buttons (after release, so it's always = 0), |
| 264 | which is not what we need ;] |
| 265 | So we need to store button in mouse down, and restore |
| 266 | in mouse up :( |
| 267 | mouse up is (similarly to mouse down) send only for |
| 268 | first button down (ie. it's no send if we click another button |
| 269 | without releasing previous one first) - but that's probably |
| 270 | because of how drivers are written?, not BeOS itself. */ |
| 271 | int32 buttons; |
| 272 | int sdl_buttons = 0; |
| 273 | if (msg->FindInt32("buttons", &buttons) == B_OK) { |
| 274 | /* Add any mouse button events */ |
| 275 | if ((buttons ^ B_PRIMARY_MOUSE_BUTTON) & last_buttons) { |
| 276 | sdl_buttons |= SDL_BUTTON_LEFT; |
| 277 | } |
| 278 | if ((buttons ^ B_SECONDARY_MOUSE_BUTTON) & last_buttons) { |
| 279 | sdl_buttons |= SDL_BUTTON_RIGHT; |
| 280 | } |
| 281 | if ((buttons ^ B_TERTIARY_MOUSE_BUTTON) & last_buttons) { |
| 282 | sdl_buttons |= SDL_BUTTON_MIDDLE; |
| 283 | } |
| 284 | SDL_PrivateMouseButton(SDL_RELEASED, sdl_buttons, 0, 0); |
| 285 | |
| 286 | last_buttons = buttons; |
| 287 | } |
| 288 | break; |
| 289 | } |
| 290 | |
| 291 | case B_MOUSE_WHEEL_CHANGED: |
| 292 | { |
| 293 | float x, y; |
| 294 | x = y = 0; |
| 295 | if (msg->FindFloat("be:wheel_delta_x", &x) == B_OK && msg->FindFloat("be:wheel_delta_y", &y) == B_OK) { |
| 296 | if (x < 0 || y < 0) { |
| 297 | SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELDOWN, 0, 0); |
| 298 | SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELDOWN, 0, 0); |
| 299 | } else if (x > 0 || y > 0) { |
| 300 | SDL_PrivateMouseButton(SDL_PRESSED, SDL_BUTTON_WHEELUP, 0, 0); |
| 301 | SDL_PrivateMouseButton(SDL_RELEASED, SDL_BUTTON_WHEELUP, 0, 0); |
| 302 | } |
| 303 | } |
| 304 | break; |
| 305 | } |
| 306 | |
| 307 | case B_KEY_DOWN: |
| 308 | case B_UNMAPPED_KEY_DOWN: /* modifier keys are unmapped */ |
| 309 | { |
| 310 | int32 key; |
| 311 | int32 modifiers; |
| 312 | int32 key_repeat; |
| 313 | /* Workaround for SDL message queue being filled too fast because of BeOS own key-repeat mechanism */ |
| 314 | if (msg->FindInt32("be:key_repeat", &key_repeat) == B_OK && key_repeat > 0) |
| 315 | break; |
| 316 | |
| 317 | if (msg->FindInt32("key", &key) == B_OK && msg->FindInt32("modifiers", &modifiers) == B_OK) { |
| 318 | SDL_keysym keysym; |
| 319 | keysym.scancode = key; |
| 320 | if (key < 128) { |
| 321 | keysym.sym = keymap[key]; |
| 322 | } else { |
| 323 | keysym.sym = SDLK_UNKNOWN; |
| 324 | } |
| 325 | /* FIX THIS? |
| 326 | it seems SDL_PrivateKeyboard() changes mod value |
| 327 | anyway, and doesn't care about what we setup here */ |
| 328 | keysym.mod = KMOD_NONE; |
| 329 | keysym.unicode = 0; |
| 330 | if (SDL_TranslateUNICODE) { |
| 331 | const char *bytes; |
| 332 | if (msg->FindString("bytes", &bytes) == B_OK) { |
| 333 | /* FIX THIS? |
| 334 | this cares only about first "letter", |
| 335 | so if someone maps some key to print |
| 336 | "BeOS rulez!" only "B" will be used. */ |
| 337 | keysym.unicode = Translate2Unicode(bytes); |
| 338 | } |
| 339 | } |
| 340 | SDL_PrivateKeyboard(SDL_PRESSED, &keysym); |
| 341 | } |
| 342 | break; |
| 343 | } |
| 344 | |
| 345 | case B_KEY_UP: |
| 346 | case B_UNMAPPED_KEY_UP: /* modifier keys are unmapped */ |
| 347 | { |
| 348 | int32 key; |
| 349 | int32 modifiers; |
| 350 | if (msg->FindInt32("key", &key) == B_OK && msg->FindInt32("modifiers", &modifiers) == B_OK) { |
| 351 | SDL_keysym keysym; |
| 352 | keysym.scancode = key; |
| 353 | if (key < 128) { |
| 354 | keysym.sym = keymap[key]; |
| 355 | } else { |
| 356 | keysym.sym = SDLK_UNKNOWN; |
| 357 | } |
| 358 | keysym.mod = KMOD_NONE; /* FIX THIS? */ |
| 359 | keysym.unicode = 0; |
| 360 | if (SDL_TranslateUNICODE) { |
| 361 | const char *bytes; |
| 362 | if (msg->FindString("bytes", &bytes) == B_OK) { |
| 363 | keysym.unicode = Translate2Unicode(bytes); |
| 364 | } |
| 365 | } |
| 366 | SDL_PrivateKeyboard(SDL_RELEASED, &keysym); |
| 367 | } |
| 368 | break; |
| 369 | } |
| 370 | |
| 371 | default: |
| 372 | /* move it after switch{} so it's always handled |
| 373 | that way we keep BeOS feautures like: |
| 374 | - CTRL+Q to close window (and other shortcuts) |
| 375 | - PrintScreen to make screenshot into /boot/home |
| 376 | - etc.. */ |
| 377 | //BDirectWindow::DispatchMessage(msg, target); |
| 378 | break; |
| 379 | } |
| 380 | BDirectWindow::DispatchMessage(msg, target); |
| 381 | } |
| 382 | |
| 383 | void SDL_BWin::DirectConnected(direct_buffer_info *info) { |
| 384 | switch (info->buffer_state & B_DIRECT_MODE_MASK) { |
| 385 | case B_DIRECT_START: |
| 386 | case B_DIRECT_MODIFY: |
| 387 | { |
| 388 | int32 width = info->window_bounds.right - |
| 389 | info->window_bounds.left + 1; |
| 390 | int32 height = info->window_bounds.bottom - |
| 391 | info->window_bounds.top + 1; |
| 392 | SDL_PrivateResize(width, height); |
| 393 | break; |
| 394 | } |
| 395 | default: |
| 396 | break; |
| 397 | } |
| 398 | } |