1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2006 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
BE_PumpEvents(_THIS)40 void BE_PumpEvents(_THIS)
41 {
42 }
43
BE_InitOSKeymap(_THIS)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
DispatchMessage(BMessage * msg,BHandler * target)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