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