source: abuse/trunk/src/sdlport/event.cpp @ 652

Last change on this file since 652 was 652, checked in by Sam Hocevar, 11 years ago

imlib: merge JCMouse into EventHandler?.

File size: 10.7 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 2001 Anthony Kruize <trandor@labyrinth.net.au>
4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 *  This program is free software; you can redistribute it and/or modify
7 *  it under the terms of the GNU General Public License as published by
8 *  the Free Software Foundation; either version 2 of the License, or
9 *  (at your option) any later version.
10 *
11 *  This program is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *  GNU General Public License for more details.
15 *
16 *  You should have received a copy of the GNU General Public License
17 *  along with this program; if not, write to the Free Software Foundation,
18 *  Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 */
20
21#if defined HAVE_CONFIG_H
22#   include "config.h"
23#endif
24
25#include <SDL.h>
26
27#include "common.h"
28
29#include "image.h"
30#include "palette.h"
31#include "video.h"
32#include "event.h"
33#include "timing.h"
34#include "sprite.h"
35#include "game.h"
36
37extern int get_key_binding(char const *dir, int i);
38extern int mouse_xscale, mouse_yscale;
39short mouse_buttons[5] = { 0, 0, 0, 0, 0 };
40
41void EventHandler::SysInit()
42{
43    // Ignore activate events
44    SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);
45}
46
47void EventHandler::SysWarpMouse(vec2i pos)
48{
49    SDL_WarpMouse(pos.x, pos.y);
50}
51
52//
53// get_key_flags()
54// Return the flag for the key modifiers
55//
56int EventHandler::get_key_flags()
57{
58    SDLMod key_flag = SDL_GetModState();
59
60    return ((key_flag & KMOD_SHIFT) != 0) << 3 |
61           ((key_flag & KMOD_CTRL) != 0) << 2 |
62           ((key_flag & KMOD_ALT) != 0) << 1;
63}
64
65//
66// IsPending()
67// Are there any events in the queue?
68//
69int EventHandler::IsPending()
70{
71    if (!m_pending && SDL_PollEvent(NULL))
72        m_pending = 1;
73
74    return m_pending;
75}
76
77//
78// get_event()
79// Get and handle waiting events
80//
81void EventHandler::Get(Event &ev)
82{
83    while(!m_pending)
84    {
85        IsPending();
86
87        if (!m_pending)
88        {
89            // Sleep for 1 millisecond if there are no events
90            Timer tmp; tmp.WaitMs(1);
91        }
92    }
93
94    Event *ep = (Event *)m_events.first();
95    if(ep)
96    {
97        ev = *ep;
98        m_events.unlink(ep);
99        delete ep;
100        m_pending = m_events.first() != NULL;
101        return;
102    }
103
104    // No more events
105    m_pending = 0;
106
107    // NOTE : that the mouse status should be known
108    // even if another event has occurred.
109    ev.mouse_move.x = m_pos.x;
110    ev.mouse_move.y = m_pos.y;
111    ev.mouse_button = m_button;
112
113    // Gather next event
114    SDL_Event sdlev;
115    if (!SDL_PollEvent(&sdlev))
116        return; // This should not happen
117
118    // Sort the mouse out
119    int x, y;
120    uint8_t buttons = SDL_GetMouseState(&x, &y);
121    x = Min((x << 16) / mouse_xscale, main_screen->Size().x - 1);
122    y = Min((y << 16) / mouse_yscale, main_screen->Size().y - 1);
123    ev.mouse_move.x = x;
124    ev.mouse_move.y = y;
125    ev.type = EV_MOUSE_MOVE;
126
127    // Left button
128    if((buttons & SDL_BUTTON(1)) && !mouse_buttons[1])
129    {
130        ev.type = EV_MOUSE_BUTTON;
131        mouse_buttons[1] = !mouse_buttons[1];
132        ev.mouse_button |= LEFT_BUTTON;
133    }
134    else if(!(buttons & SDL_BUTTON(1)) && mouse_buttons[1])
135    {
136        ev.type = EV_MOUSE_BUTTON;
137        mouse_buttons[1] = !mouse_buttons[1];
138        ev.mouse_button &= (0xff - LEFT_BUTTON);
139    }
140
141    // Middle button
142    if((buttons & SDL_BUTTON(2)) && !mouse_buttons[2])
143    {
144        ev.type = EV_MOUSE_BUTTON;
145        mouse_buttons[2] = !mouse_buttons[2];
146        ev.mouse_button |= LEFT_BUTTON;
147        ev.mouse_button |= RIGHT_BUTTON;
148    }
149    else if(!(buttons & SDL_BUTTON(2)) && mouse_buttons[2])
150    {
151        ev.type = EV_MOUSE_BUTTON;
152        mouse_buttons[2] = !mouse_buttons[2];
153        ev.mouse_button &= (0xff - LEFT_BUTTON);
154        ev.mouse_button &= (0xff - RIGHT_BUTTON);
155    }
156
157    // Right button
158    if((buttons & SDL_BUTTON(3)) && !mouse_buttons[3])
159    {
160        ev.type = EV_MOUSE_BUTTON;
161        mouse_buttons[3] = !mouse_buttons[3];
162        ev.mouse_button |= RIGHT_BUTTON;
163    }
164    else if(!(buttons & SDL_BUTTON(3)) && mouse_buttons[3])
165    {
166        ev.type = EV_MOUSE_BUTTON;
167        mouse_buttons[3] = !mouse_buttons[3];
168        ev.mouse_button &= (0xff - RIGHT_BUTTON);
169    }
170    m_pos = vec2i(ev.mouse_move.x, ev.mouse_move.y);
171    m_button = ev.mouse_button;
172
173    // Sort out other kinds of events
174    switch(sdlev.type)
175    {
176    case SDL_QUIT:
177        exit(0);
178        break;
179    case SDL_MOUSEBUTTONUP:
180        switch(sdlev.button.button)
181        {
182        case 4:        // Mouse wheel goes up...
183            ev.key = get_key_binding("b4", 0);
184            ev.type = EV_KEYRELEASE;
185            break;
186        case 5:        // Mouse wheel goes down...
187            ev.key = get_key_binding("b3", 0);
188            ev.type = EV_KEYRELEASE;
189            break;
190        }
191        break;
192    case SDL_MOUSEBUTTONDOWN:
193        switch(sdlev.button.button)
194        {
195        case 4:        // Mouse wheel goes up...
196            ev.key = get_key_binding("b4", 0);
197            ev.type = EV_KEY;
198            break;
199        case 5:        // Mouse wheel goes down...
200            ev.key = get_key_binding("b3", 0);
201            ev.type = EV_KEY;
202            break;
203        }
204        break;
205    case SDL_KEYDOWN:
206    case SDL_KEYUP:
207        // Default to EV_SPURIOUS
208        ev.key = EV_SPURIOUS;
209        if(sdlev.type == SDL_KEYDOWN)
210        {
211            ev.type = EV_KEY;
212        }
213        else
214        {
215            ev.type = EV_KEYRELEASE;
216        }
217        switch(sdlev.key.keysym.sym)
218        {
219        case SDLK_DOWN:         ev.key = JK_DOWN; break;
220        case SDLK_UP:           ev.key = JK_UP; break;
221        case SDLK_LEFT:         ev.key = JK_LEFT; break;
222        case SDLK_RIGHT:        ev.key = JK_RIGHT; break;
223        case SDLK_LCTRL:        ev.key = JK_CTRL_L; break;
224        case SDLK_RCTRL:        ev.key = JK_CTRL_R; break;
225        case SDLK_LALT:         ev.key = JK_ALT_L; break;
226        case SDLK_RALT:         ev.key = JK_ALT_R; break;
227        case SDLK_LSHIFT:       ev.key = JK_SHIFT_L; break;
228        case SDLK_RSHIFT:       ev.key = JK_SHIFT_R; break;
229        case SDLK_NUMLOCK:      ev.key = JK_NUM_LOCK; break;
230        case SDLK_HOME:         ev.key = JK_HOME; break;
231        case SDLK_END:          ev.key = JK_END; break;
232        case SDLK_BACKSPACE:    ev.key = JK_BACKSPACE; break;
233        case SDLK_TAB:          ev.key = JK_TAB; break;
234        case SDLK_RETURN:       ev.key = JK_ENTER; break;
235        case SDLK_SPACE:        ev.key = JK_SPACE; break;
236        case SDLK_CAPSLOCK:     ev.key = JK_CAPS; break;
237        case SDLK_ESCAPE:       ev.key = JK_ESC; break;
238        case SDLK_F1:           ev.key = JK_F1; break;
239        case SDLK_F2:           ev.key = JK_F2; break;
240        case SDLK_F3:           ev.key = JK_F3; break;
241        case SDLK_F4:           ev.key = JK_F4; break;
242        case SDLK_F5:           ev.key = JK_F5; break;
243        case SDLK_F6:           ev.key = JK_F6; break;
244        case SDLK_F7:           ev.key = JK_F7; break;
245        case SDLK_F8:           ev.key = JK_F8; break;
246        case SDLK_F9:           ev.key = JK_F9; break;
247        case SDLK_F10:          ev.key = JK_F10; break;
248        case SDLK_INSERT:       ev.key = JK_INSERT; break;
249        case SDLK_KP0:          ev.key = JK_INSERT; break;
250        case SDLK_PAGEUP:       ev.key = JK_PAGEUP; break;
251        case SDLK_PAGEDOWN:     ev.key = JK_PAGEDOWN; break;
252        case SDLK_KP8:          ev.key = JK_UP; break;
253        case SDLK_KP2:          ev.key = JK_DOWN; break;
254        case SDLK_KP4:          ev.key = JK_LEFT; break;
255        case SDLK_KP6:          ev.key = JK_RIGHT; break;
256        case SDLK_F11:
257            // Only handle key down
258            if(ev.type == EV_KEY)
259            {
260                // Toggle fullscreen
261                SDL_WM_ToggleFullScreen(SDL_GetVideoSurface());
262            }
263            ev.key = EV_SPURIOUS;
264            break;
265        case SDLK_F12:
266            // Only handle key down
267            if(ev.type == EV_KEY)
268            {
269                // Toggle grab mouse
270                if(SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON)
271                {
272                    the_game->show_help("Grab Mouse: OFF\n");
273                    SDL_WM_GrabInput(SDL_GRAB_OFF);
274                }
275                else
276                {
277                    the_game->show_help("Grab Mouse: ON\n");
278                    SDL_WM_GrabInput(SDL_GRAB_ON);
279                }
280            }
281            ev.key = EV_SPURIOUS;
282            break;
283        case SDLK_PRINT:    // print-screen key
284            // Only handle key down
285            if(ev.type == EV_KEY)
286            {
287                // Grab a screenshot
288                SDL_SaveBMP(SDL_GetVideoSurface(), "screenshot.bmp");
289                the_game->show_help("Screenshot saved to: screenshot.bmp.\n");
290            }
291            ev.key = EV_SPURIOUS;
292            break;
293        default:
294            ev.key = (int)sdlev.key.keysym.sym;
295            // Need to handle the case of shift being pressed
296            // There has to be a better way
297            if((sdlev.key.keysym.mod & KMOD_SHIFT) != 0)
298            {
299                if(sdlev.key.keysym.sym >= SDLK_a &&
300                    sdlev.key.keysym.sym <= SDLK_z)
301                {
302                    ev.key -= 32;
303                }
304                else if(sdlev.key.keysym.sym >= SDLK_1 &&
305                         sdlev.key.keysym.sym <= SDLK_5)
306                {
307                    ev.key -= 16;
308                }
309                else
310                {
311                    switch(sdlev.key.keysym.sym)
312                    {
313                    case SDLK_6:
314                        ev.key = SDLK_CARET; break;
315                    case SDLK_7:
316                    case SDLK_9:
317                    case SDLK_0:
318                        ev.key -= 17; break;
319                    case SDLK_8:
320                        ev.key = SDLK_ASTERISK; break;
321                    case SDLK_MINUS:
322                        ev.key = SDLK_UNDERSCORE; break;
323                    case SDLK_EQUALS:
324                        ev.key = SDLK_PLUS; break;
325                    case SDLK_COMMA:
326                        ev.key = SDLK_LESS; break;
327                    case SDLK_PERIOD:
328                        ev.key = SDLK_GREATER; break;
329                    case SDLK_SLASH:
330                        ev.key = SDLK_QUESTION; break;
331                    case SDLK_SEMICOLON:
332                        ev.key = SDLK_COLON; break;
333                    case SDLK_QUOTE:
334                        ev.key = SDLK_QUOTEDBL; break;
335                    default:
336                        break;
337                    }
338                }
339            }
340            break;
341        }
342    }
343}
344
Note: See TracBrowser for help on using the repository browser.