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

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

sdlport: mouse handling refactoring.

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