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

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

imlib: clean up EventHandler? and JCMouse.

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