Statistics
| Branch: | Revision:

root / sdl.c @ bcfad70f

History | View | Annotate | Download (20 kB)

1 0f0b7264 bellard
/*
2 0f0b7264 bellard
 * QEMU SDL display driver
3 5fafdf24 ths
 *
4 0f0b7264 bellard
 * Copyright (c) 2003 Fabrice Bellard
5 5fafdf24 ths
 *
6 0f0b7264 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 0f0b7264 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 0f0b7264 bellard
 * in the Software without restriction, including without limitation the rights
9 0f0b7264 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 0f0b7264 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 0f0b7264 bellard
 * furnished to do so, subject to the following conditions:
12 0f0b7264 bellard
 *
13 0f0b7264 bellard
 * The above copyright notice and this permission notice shall be included in
14 0f0b7264 bellard
 * all copies or substantial portions of the Software.
15 0f0b7264 bellard
 *
16 0f0b7264 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 0f0b7264 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 0f0b7264 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 0f0b7264 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 0f0b7264 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 0f0b7264 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 0f0b7264 bellard
 * THE SOFTWARE.
23 0f0b7264 bellard
 */
24 87ecb68b pbrook
#include "qemu-common.h"
25 87ecb68b pbrook
#include "console.h"
26 87ecb68b pbrook
#include "sysemu.h"
27 0f0b7264 bellard
28 0f0b7264 bellard
#include <SDL.h>
29 0f0b7264 bellard
30 67b915a5 bellard
#ifndef _WIN32
31 67b915a5 bellard
#include <signal.h>
32 67b915a5 bellard
#endif
33 0f0b7264 bellard
34 0f0b7264 bellard
static SDL_Surface *screen;
35 0f0b7264 bellard
static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
36 8a7ddc38 bellard
static int last_vm_running;
37 8e9c4afe bellard
static int gui_saved_grab;
38 8e9c4afe bellard
static int gui_fullscreen;
39 43523e93 ths
static int gui_noframe;
40 8e9c4afe bellard
static int gui_key_modifier_pressed;
41 8e9c4afe bellard
static int gui_keysym;
42 d63d307f bellard
static int gui_fullscreen_initial_grab;
43 32ff25bf bellard
static int gui_grab_code = KMOD_LALT | KMOD_LCTRL;
44 32ff25bf bellard
static uint8_t modifiers_state[256];
45 09b26c5e bellard
static int width, height;
46 09b26c5e bellard
static SDL_Cursor *sdl_cursor_normal;
47 09b26c5e bellard
static SDL_Cursor *sdl_cursor_hidden;
48 09b26c5e bellard
static int absolute_enabled = 0;
49 d34cab9f ths
static int guest_cursor = 0;
50 d34cab9f ths
static int guest_x, guest_y;
51 d34cab9f ths
static SDL_Cursor *guest_sprite = 0;
52 0f0b7264 bellard
53 0f0b7264 bellard
static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
54 0f0b7264 bellard
{
55 898712a8 bellard
    //    printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
56 0f0b7264 bellard
    SDL_UpdateRect(screen, x, y, w, h);
57 0f0b7264 bellard
}
58 0f0b7264 bellard
59 0f0b7264 bellard
static void sdl_resize(DisplayState *ds, int w, int h)
60 0f0b7264 bellard
{
61 0f0b7264 bellard
    int flags;
62 0f0b7264 bellard
63 0f0b7264 bellard
    //    printf("resizing to %d %d\n", w, h);
64 0f0b7264 bellard
65 0f0b7264 bellard
    flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
66 8e9c4afe bellard
    if (gui_fullscreen)
67 8e9c4afe bellard
        flags |= SDL_FULLSCREEN;
68 43523e93 ths
    if (gui_noframe)
69 43523e93 ths
        flags |= SDL_NOFRAME;
70 9903da21 bellard
71 09b26c5e bellard
    width = w;
72 09b26c5e bellard
    height = h;
73 09b26c5e bellard
74 9903da21 bellard
 again:
75 0f0b7264 bellard
    screen = SDL_SetVideoMode(w, h, 0, flags);
76 0f0b7264 bellard
    if (!screen) {
77 0f0b7264 bellard
        fprintf(stderr, "Could not open SDL display\n");
78 0f0b7264 bellard
        exit(1);
79 0f0b7264 bellard
    }
80 9903da21 bellard
    if (!screen->pixels && (flags & SDL_HWSURFACE) && (flags & SDL_FULLSCREEN)) {
81 9903da21 bellard
        flags &= ~SDL_HWSURFACE;
82 9903da21 bellard
        goto again;
83 9903da21 bellard
    }
84 9903da21 bellard
85 9903da21 bellard
    if (!screen->pixels) {
86 9903da21 bellard
        fprintf(stderr, "Could not open SDL display\n");
87 9903da21 bellard
        exit(1);
88 9903da21 bellard
    }
89 0f0b7264 bellard
    ds->data = screen->pixels;
90 0f0b7264 bellard
    ds->linesize = screen->pitch;
91 0f0b7264 bellard
    ds->depth = screen->format->BitsPerPixel;
92 749ecd99 blueswir1
    /* SDL BitsPerPixel never indicates any values other than
93 749ecd99 blueswir1
       multiples of 8, so we need to check for strange depths. */
94 749ecd99 blueswir1
    if (ds->depth == 16) {
95 749ecd99 blueswir1
        uint32_t mask;
96 749ecd99 blueswir1
97 749ecd99 blueswir1
        mask = screen->format->Rmask;
98 749ecd99 blueswir1
        mask |= screen->format->Gmask;
99 749ecd99 blueswir1
        mask |= screen->format->Bmask;
100 749ecd99 blueswir1
        if ((mask & 0x8000) == 0)
101 749ecd99 blueswir1
            ds->depth = 15;
102 749ecd99 blueswir1
    }
103 c7bd7bec aliguori
    if (ds->depth == 32 && screen->format->Rshift == 0) {
104 d3079cd2 bellard
        ds->bgr = 1;
105 d3079cd2 bellard
    } else {
106 d3079cd2 bellard
        ds->bgr = 0;
107 d3079cd2 bellard
    }
108 457831f4 bellard
    ds->width = w;
109 457831f4 bellard
    ds->height = h;
110 0f0b7264 bellard
}
111 0f0b7264 bellard
112 3d11d0eb bellard
/* generic keyboard conversion */
113 e58d12ed bellard
114 3d11d0eb bellard
#include "sdl_keysym.h"
115 3d11d0eb bellard
#include "keymaps.c"
116 3d11d0eb bellard
117 3d11d0eb bellard
static kbd_layout_t *kbd_layout = NULL;
118 3d11d0eb bellard
119 3d11d0eb bellard
static uint8_t sdl_keyevent_to_keycode_generic(const SDL_KeyboardEvent *ev)
120 e58d12ed bellard
{
121 3d11d0eb bellard
    int keysym;
122 3d11d0eb bellard
    /* workaround for X11+SDL bug with AltGR */
123 3d11d0eb bellard
    keysym = ev->keysym.sym;
124 3d11d0eb bellard
    if (keysym == 0 && ev->keysym.scancode == 113)
125 3d11d0eb bellard
        keysym = SDLK_MODE;
126 60659e3b bellard
    /* For Japanese key '\' and '|' */
127 60659e3b bellard
    if (keysym == 92 && ev->keysym.scancode == 133) {
128 60659e3b bellard
        keysym = 0xa5;
129 60659e3b bellard
    }
130 3d11d0eb bellard
    return keysym2scancode(kbd_layout, keysym);
131 e58d12ed bellard
}
132 e58d12ed bellard
133 3d11d0eb bellard
/* specific keyboard conversions from scan codes */
134 3d11d0eb bellard
135 3d11d0eb bellard
#if defined(_WIN32)
136 e58d12ed bellard
137 e58d12ed bellard
static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
138 e58d12ed bellard
{
139 e58d12ed bellard
    return ev->keysym.scancode;
140 e58d12ed bellard
}
141 e58d12ed bellard
142 e58d12ed bellard
#else
143 e58d12ed bellard
144 e58d12ed bellard
static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
145 e58d12ed bellard
{
146 e58d12ed bellard
    int keycode;
147 e58d12ed bellard
148 e58d12ed bellard
    keycode = ev->keysym.scancode;
149 e58d12ed bellard
150 e58d12ed bellard
    if (keycode < 9) {
151 e58d12ed bellard
        keycode = 0;
152 e58d12ed bellard
    } else if (keycode < 97) {
153 e58d12ed bellard
        keycode -= 8; /* just an offset */
154 60659e3b bellard
    } else if (keycode < 212) {
155 e58d12ed bellard
        /* use conversion table */
156 6070dd07 ths
        keycode = _translate_keycode(keycode - 97);
157 e58d12ed bellard
    } else {
158 e58d12ed bellard
        keycode = 0;
159 e58d12ed bellard
    }
160 e58d12ed bellard
    return keycode;
161 e58d12ed bellard
}
162 e58d12ed bellard
163 e58d12ed bellard
#endif
164 e58d12ed bellard
165 32ff25bf bellard
static void reset_keys(void)
166 32ff25bf bellard
{
167 32ff25bf bellard
    int i;
168 32ff25bf bellard
    for(i = 0; i < 256; i++) {
169 32ff25bf bellard
        if (modifiers_state[i]) {
170 32ff25bf bellard
            if (i & 0x80)
171 32ff25bf bellard
                kbd_put_keycode(0xe0);
172 32ff25bf bellard
            kbd_put_keycode(i | 0x80);
173 32ff25bf bellard
            modifiers_state[i] = 0;
174 32ff25bf bellard
        }
175 32ff25bf bellard
    }
176 32ff25bf bellard
}
177 32ff25bf bellard
178 0f0b7264 bellard
static void sdl_process_key(SDL_KeyboardEvent *ev)
179 0f0b7264 bellard
{
180 32ff25bf bellard
    int keycode, v;
181 de2200d3 bellard
182 de2200d3 bellard
    if (ev->keysym.sym == SDLK_PAUSE) {
183 de2200d3 bellard
        /* specific case */
184 de2200d3 bellard
        v = 0;
185 de2200d3 bellard
        if (ev->type == SDL_KEYUP)
186 de2200d3 bellard
            v |= 0x80;
187 de2200d3 bellard
        kbd_put_keycode(0xe1);
188 de2200d3 bellard
        kbd_put_keycode(0x1d | v);
189 de2200d3 bellard
        kbd_put_keycode(0x45 | v);
190 de2200d3 bellard
        return;
191 de2200d3 bellard
    }
192 de2200d3 bellard
193 3d11d0eb bellard
    if (kbd_layout) {
194 3d11d0eb bellard
        keycode = sdl_keyevent_to_keycode_generic(ev);
195 3d11d0eb bellard
    } else {
196 3d11d0eb bellard
        keycode = sdl_keyevent_to_keycode(ev);
197 3d11d0eb bellard
    }
198 de2200d3 bellard
199 de2200d3 bellard
    switch(keycode) {
200 de2200d3 bellard
    case 0x00:
201 de2200d3 bellard
        /* sent when leaving window: reset the modifiers state */
202 32ff25bf bellard
        reset_keys();
203 de2200d3 bellard
        return;
204 de2200d3 bellard
    case 0x2a:                          /* Left Shift */
205 de2200d3 bellard
    case 0x36:                          /* Right Shift */
206 de2200d3 bellard
    case 0x1d:                          /* Left CTRL */
207 de2200d3 bellard
    case 0x9d:                          /* Right CTRL */
208 de2200d3 bellard
    case 0x38:                          /* Left ALT */
209 de2200d3 bellard
    case 0xb8:                         /* Right ALT */
210 0f0b7264 bellard
        if (ev->type == SDL_KEYUP)
211 de2200d3 bellard
            modifiers_state[keycode] = 0;
212 de2200d3 bellard
        else
213 de2200d3 bellard
            modifiers_state[keycode] = 1;
214 de2200d3 bellard
        break;
215 de2200d3 bellard
    case 0x45: /* num lock */
216 de2200d3 bellard
    case 0x3a: /* caps lock */
217 de2200d3 bellard
        /* SDL does not send the key up event, so we generate it */
218 de2200d3 bellard
        kbd_put_keycode(keycode);
219 de2200d3 bellard
        kbd_put_keycode(keycode | 0x80);
220 de2200d3 bellard
        return;
221 0f0b7264 bellard
    }
222 de2200d3 bellard
223 de2200d3 bellard
    /* now send the key code */
224 de2200d3 bellard
    if (keycode & 0x80)
225 de2200d3 bellard
        kbd_put_keycode(0xe0);
226 de2200d3 bellard
    if (ev->type == SDL_KEYUP)
227 de2200d3 bellard
        kbd_put_keycode(keycode | 0x80);
228 de2200d3 bellard
    else
229 de2200d3 bellard
        kbd_put_keycode(keycode & 0x7f);
230 0f0b7264 bellard
}
231 0f0b7264 bellard
232 8a7ddc38 bellard
static void sdl_update_caption(void)
233 8a7ddc38 bellard
{
234 8a7ddc38 bellard
    char buf[1024];
235 c35734b2 ths
    const char *status = "";
236 c35734b2 ths
237 c35734b2 ths
    if (!vm_running)
238 c35734b2 ths
        status = " [Stopped]";
239 3780e197 ths
    else if (gui_grab) {
240 3780e197 ths
        if (!alt_grab)
241 3780e197 ths
            status = " - Press Ctrl-Alt to exit grab";
242 3780e197 ths
        else
243 3780e197 ths
            status = " - Press Ctrl-Alt-Shift to exit grab";
244 3780e197 ths
    }
245 c35734b2 ths
246 c35734b2 ths
    if (qemu_name)
247 c35734b2 ths
        snprintf(buf, sizeof(buf), "QEMU (%s)%s", qemu_name, status);
248 c35734b2 ths
    else
249 c35734b2 ths
        snprintf(buf, sizeof(buf), "QEMU%s", status);
250 c35734b2 ths
251 8a7ddc38 bellard
    SDL_WM_SetCaption(buf, "QEMU");
252 8a7ddc38 bellard
}
253 8a7ddc38 bellard
254 09b26c5e bellard
static void sdl_hide_cursor(void)
255 09b26c5e bellard
{
256 9467cd46 balrog
    if (!cursor_hide)
257 9467cd46 balrog
        return;
258 9467cd46 balrog
259 8785a8dd bellard
    if (kbd_mouse_is_absolute()) {
260 8785a8dd bellard
        SDL_ShowCursor(1);
261 8785a8dd bellard
        SDL_SetCursor(sdl_cursor_hidden);
262 8785a8dd bellard
    } else {
263 8785a8dd bellard
        SDL_ShowCursor(0);
264 8785a8dd bellard
    }
265 09b26c5e bellard
}
266 09b26c5e bellard
267 09b26c5e bellard
static void sdl_show_cursor(void)
268 09b26c5e bellard
{
269 9467cd46 balrog
    if (!cursor_hide)
270 9467cd46 balrog
        return;
271 9467cd46 balrog
272 09b26c5e bellard
    if (!kbd_mouse_is_absolute()) {
273 8785a8dd bellard
        SDL_ShowCursor(1);
274 d34cab9f ths
        if (guest_cursor &&
275 d34cab9f ths
                (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
276 d34cab9f ths
            SDL_SetCursor(guest_sprite);
277 d34cab9f ths
        else
278 d34cab9f ths
            SDL_SetCursor(sdl_cursor_normal);
279 09b26c5e bellard
    }
280 09b26c5e bellard
}
281 09b26c5e bellard
282 0f0b7264 bellard
static void sdl_grab_start(void)
283 0f0b7264 bellard
{
284 d34cab9f ths
    if (guest_cursor) {
285 d34cab9f ths
        SDL_SetCursor(guest_sprite);
286 d34cab9f ths
        SDL_WarpMouse(guest_x, guest_y);
287 d34cab9f ths
    } else
288 d34cab9f ths
        sdl_hide_cursor();
289 0f0b7264 bellard
    SDL_WM_GrabInput(SDL_GRAB_ON);
290 0f0b7264 bellard
    gui_grab = 1;
291 8a7ddc38 bellard
    sdl_update_caption();
292 0f0b7264 bellard
}
293 0f0b7264 bellard
294 0f0b7264 bellard
static void sdl_grab_end(void)
295 0f0b7264 bellard
{
296 0f0b7264 bellard
    SDL_WM_GrabInput(SDL_GRAB_OFF);
297 0f0b7264 bellard
    gui_grab = 0;
298 d34cab9f ths
    sdl_show_cursor();
299 8a7ddc38 bellard
    sdl_update_caption();
300 0f0b7264 bellard
}
301 0f0b7264 bellard
302 4c44bdcb aurel32
static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state)
303 0f0b7264 bellard
{
304 4c44bdcb aurel32
    int buttons;
305 0f0b7264 bellard
    buttons = 0;
306 0f0b7264 bellard
    if (state & SDL_BUTTON(SDL_BUTTON_LEFT))
307 0f0b7264 bellard
        buttons |= MOUSE_EVENT_LBUTTON;
308 0f0b7264 bellard
    if (state & SDL_BUTTON(SDL_BUTTON_RIGHT))
309 0f0b7264 bellard
        buttons |= MOUSE_EVENT_RBUTTON;
310 0f0b7264 bellard
    if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE))
311 0f0b7264 bellard
        buttons |= MOUSE_EVENT_MBUTTON;
312 09b26c5e bellard
313 09b26c5e bellard
    if (kbd_mouse_is_absolute()) {
314 09b26c5e bellard
        if (!absolute_enabled) {
315 09b26c5e bellard
            sdl_hide_cursor();
316 09b26c5e bellard
            if (gui_grab) {
317 09b26c5e bellard
                sdl_grab_end();
318 09b26c5e bellard
            }
319 09b26c5e bellard
            absolute_enabled = 1;
320 09b26c5e bellard
        }
321 09b26c5e bellard
322 4c44bdcb aurel32
       dx = x * 0x7FFF / (width - 1);
323 4c44bdcb aurel32
       dy = y * 0x7FFF / (height - 1);
324 455204eb ths
    } else if (absolute_enabled) {
325 455204eb ths
        sdl_show_cursor();
326 455204eb ths
        absolute_enabled = 0;
327 d34cab9f ths
    } else if (guest_cursor) {
328 4c44bdcb aurel32
        x -= guest_x;
329 4c44bdcb aurel32
        y -= guest_y;
330 4c44bdcb aurel32
        guest_x += x;
331 4c44bdcb aurel32
        guest_y += y;
332 4c44bdcb aurel32
        dx = x;
333 4c44bdcb aurel32
        dy = y;
334 09b26c5e bellard
    }
335 09b26c5e bellard
336 0f0b7264 bellard
    kbd_mouse_event(dx, dy, dz, buttons);
337 0f0b7264 bellard
}
338 0f0b7264 bellard
339 8e9c4afe bellard
static void toggle_full_screen(DisplayState *ds)
340 8e9c4afe bellard
{
341 8e9c4afe bellard
    gui_fullscreen = !gui_fullscreen;
342 8e9c4afe bellard
    sdl_resize(ds, screen->w, screen->h);
343 8e9c4afe bellard
    if (gui_fullscreen) {
344 8e9c4afe bellard
        gui_saved_grab = gui_grab;
345 8e9c4afe bellard
        sdl_grab_start();
346 8e9c4afe bellard
    } else {
347 8e9c4afe bellard
        if (!gui_saved_grab)
348 8e9c4afe bellard
            sdl_grab_end();
349 8e9c4afe bellard
    }
350 95219897 pbrook
    vga_hw_invalidate();
351 95219897 pbrook
    vga_hw_update();
352 8e9c4afe bellard
}
353 8e9c4afe bellard
354 0f0b7264 bellard
static void sdl_refresh(DisplayState *ds)
355 0f0b7264 bellard
{
356 0f0b7264 bellard
    SDL_Event ev1, *ev = &ev1;
357 8e9c4afe bellard
    int mod_state;
358 4c44bdcb aurel32
    int buttonstate = SDL_GetMouseState(NULL, NULL);
359 3b46e624 ths
360 8a7ddc38 bellard
    if (last_vm_running != vm_running) {
361 8a7ddc38 bellard
        last_vm_running = vm_running;
362 8a7ddc38 bellard
        sdl_update_caption();
363 8a7ddc38 bellard
    }
364 8a7ddc38 bellard
365 95219897 pbrook
    vga_hw_update();
366 3bee8bd0 aurel32
    SDL_EnableUNICODE(!is_graphic_console());
367 457831f4 bellard
368 0f0b7264 bellard
    while (SDL_PollEvent(ev)) {
369 0f0b7264 bellard
        switch (ev->type) {
370 0f0b7264 bellard
        case SDL_VIDEOEXPOSE:
371 0f0b7264 bellard
            sdl_update(ds, 0, 0, screen->w, screen->h);
372 0f0b7264 bellard
            break;
373 0f0b7264 bellard
        case SDL_KEYDOWN:
374 0f0b7264 bellard
        case SDL_KEYUP:
375 0f0b7264 bellard
            if (ev->type == SDL_KEYDOWN) {
376 3780e197 ths
                if (!alt_grab) {
377 3780e197 ths
                    mod_state = (SDL_GetModState() & gui_grab_code) ==
378 3780e197 ths
                                gui_grab_code;
379 3780e197 ths
                } else {
380 3780e197 ths
                    mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) ==
381 3780e197 ths
                                (gui_grab_code | KMOD_LSHIFT);
382 3780e197 ths
                }
383 8e9c4afe bellard
                gui_key_modifier_pressed = mod_state;
384 457831f4 bellard
                if (gui_key_modifier_pressed) {
385 32ff25bf bellard
                    int keycode;
386 32ff25bf bellard
                    keycode = sdl_keyevent_to_keycode(&ev->key);
387 32ff25bf bellard
                    switch(keycode) {
388 32ff25bf bellard
                    case 0x21: /* 'f' key on US keyboard */
389 457831f4 bellard
                        toggle_full_screen(ds);
390 457831f4 bellard
                        gui_keysym = 1;
391 457831f4 bellard
                        break;
392 5fafdf24 ths
                    case 0x02 ... 0x0a: /* '1' to '9' keys */
393 dfd92d3a bellard
                        /* Reset the modifiers sent to the current console */
394 dfd92d3a bellard
                        reset_keys();
395 32ff25bf bellard
                        console_select(keycode - 0x02);
396 95219897 pbrook
                        if (!is_graphic_console()) {
397 457831f4 bellard
                            /* display grab if going to a text console */
398 457831f4 bellard
                            if (gui_grab)
399 457831f4 bellard
                                sdl_grab_end();
400 457831f4 bellard
                        }
401 457831f4 bellard
                        gui_keysym = 1;
402 457831f4 bellard
                        break;
403 457831f4 bellard
                    default:
404 457831f4 bellard
                        break;
405 457831f4 bellard
                    }
406 95219897 pbrook
                } else if (!is_graphic_console()) {
407 457831f4 bellard
                    int keysym;
408 457831f4 bellard
                    keysym = 0;
409 457831f4 bellard
                    if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) {
410 457831f4 bellard
                        switch(ev->key.keysym.sym) {
411 457831f4 bellard
                        case SDLK_UP: keysym = QEMU_KEY_CTRL_UP; break;
412 457831f4 bellard
                        case SDLK_DOWN: keysym = QEMU_KEY_CTRL_DOWN; break;
413 457831f4 bellard
                        case SDLK_LEFT: keysym = QEMU_KEY_CTRL_LEFT; break;
414 457831f4 bellard
                        case SDLK_RIGHT: keysym = QEMU_KEY_CTRL_RIGHT; break;
415 457831f4 bellard
                        case SDLK_HOME: keysym = QEMU_KEY_CTRL_HOME; break;
416 457831f4 bellard
                        case SDLK_END: keysym = QEMU_KEY_CTRL_END; break;
417 457831f4 bellard
                        case SDLK_PAGEUP: keysym = QEMU_KEY_CTRL_PAGEUP; break;
418 457831f4 bellard
                        case SDLK_PAGEDOWN: keysym = QEMU_KEY_CTRL_PAGEDOWN; break;
419 457831f4 bellard
                        default: break;
420 457831f4 bellard
                        }
421 457831f4 bellard
                    } else {
422 457831f4 bellard
                        switch(ev->key.keysym.sym) {
423 457831f4 bellard
                        case SDLK_UP: keysym = QEMU_KEY_UP; break;
424 457831f4 bellard
                        case SDLK_DOWN: keysym = QEMU_KEY_DOWN; break;
425 457831f4 bellard
                        case SDLK_LEFT: keysym = QEMU_KEY_LEFT; break;
426 457831f4 bellard
                        case SDLK_RIGHT: keysym = QEMU_KEY_RIGHT; break;
427 457831f4 bellard
                        case SDLK_HOME: keysym = QEMU_KEY_HOME; break;
428 457831f4 bellard
                        case SDLK_END: keysym = QEMU_KEY_END; break;
429 457831f4 bellard
                        case SDLK_PAGEUP: keysym = QEMU_KEY_PAGEUP; break;
430 457831f4 bellard
                        case SDLK_PAGEDOWN: keysym = QEMU_KEY_PAGEDOWN; break;
431 e91c8a77 ths
                        case SDLK_BACKSPACE: keysym = QEMU_KEY_BACKSPACE; break;
432 e91c8a77 ths
                        case SDLK_DELETE: keysym = QEMU_KEY_DELETE; break;
433 457831f4 bellard
                        default: break;
434 457831f4 bellard
                        }
435 457831f4 bellard
                    }
436 457831f4 bellard
                    if (keysym) {
437 457831f4 bellard
                        kbd_put_keysym(keysym);
438 457831f4 bellard
                    } else if (ev->key.keysym.unicode != 0) {
439 457831f4 bellard
                        kbd_put_keysym(ev->key.keysym.unicode);
440 457831f4 bellard
                    }
441 8e9c4afe bellard
                }
442 8e9c4afe bellard
            } else if (ev->type == SDL_KEYUP) {
443 3780e197 ths
                if (!alt_grab) {
444 3780e197 ths
                    mod_state = (ev->key.keysym.mod & gui_grab_code);
445 3780e197 ths
                } else {
446 3780e197 ths
                    mod_state = (ev->key.keysym.mod &
447 3780e197 ths
                                 (gui_grab_code | KMOD_LSHIFT));
448 3780e197 ths
                }
449 8e9c4afe bellard
                if (!mod_state) {
450 8e9c4afe bellard
                    if (gui_key_modifier_pressed) {
451 5b311878 pbrook
                        gui_key_modifier_pressed = 0;
452 457831f4 bellard
                        if (gui_keysym == 0) {
453 32ff25bf bellard
                            /* exit/enter grab if pressing Ctrl-Alt */
454 c66b0d4c bellard
                            if (!gui_grab) {
455 c66b0d4c bellard
                                /* if the application is not active,
456 c66b0d4c bellard
                                   do not try to enter grab state. It
457 c66b0d4c bellard
                                   prevents
458 c66b0d4c bellard
                                   'SDL_WM_GrabInput(SDL_GRAB_ON)'
459 c66b0d4c bellard
                                   from blocking all the application
460 c66b0d4c bellard
                                   (SDL bug). */
461 c66b0d4c bellard
                                if (SDL_GetAppState() & SDL_APPACTIVE)
462 c66b0d4c bellard
                                    sdl_grab_start();
463 c66b0d4c bellard
                            } else {
464 8e9c4afe bellard
                                sdl_grab_end();
465 c66b0d4c bellard
                            }
466 32ff25bf bellard
                            /* SDL does not send back all the
467 32ff25bf bellard
                               modifiers key, so we must correct it */
468 32ff25bf bellard
                            reset_keys();
469 8e9c4afe bellard
                            break;
470 8e9c4afe bellard
                        }
471 8e9c4afe bellard
                        gui_keysym = 0;
472 8e9c4afe bellard
                    }
473 0f0b7264 bellard
                }
474 0f0b7264 bellard
            }
475 5fafdf24 ths
            if (is_graphic_console() && !gui_keysym)
476 457831f4 bellard
                sdl_process_key(&ev->key);
477 0f0b7264 bellard
            break;
478 0f0b7264 bellard
        case SDL_QUIT:
479 5b08fc10 aliguori
            if (!no_quit)
480 731345e1 balrog
                qemu_system_shutdown_request();
481 0f0b7264 bellard
            break;
482 0f0b7264 bellard
        case SDL_MOUSEMOTION:
483 455204eb ths
            if (gui_grab || kbd_mouse_is_absolute() ||
484 455204eb ths
                absolute_enabled) {
485 4c44bdcb aurel32
                sdl_send_mouse_event(ev->motion.xrel, ev->motion.yrel, 0,
486 4c44bdcb aurel32
                       ev->motion.x, ev->motion.y, ev->motion.state);
487 0f0b7264 bellard
            }
488 0f0b7264 bellard
            break;
489 0f0b7264 bellard
        case SDL_MOUSEBUTTONDOWN:
490 0f0b7264 bellard
        case SDL_MOUSEBUTTONUP:
491 0f0b7264 bellard
            {
492 0f0b7264 bellard
                SDL_MouseButtonEvent *bev = &ev->button;
493 09b26c5e bellard
                if (!gui_grab && !kbd_mouse_is_absolute()) {
494 0f0b7264 bellard
                    if (ev->type == SDL_MOUSEBUTTONDOWN &&
495 4c44bdcb aurel32
                        (bev->button == SDL_BUTTON_LEFT)) {
496 0f0b7264 bellard
                        /* start grabbing all events */
497 0f0b7264 bellard
                        sdl_grab_start();
498 0f0b7264 bellard
                    }
499 0f0b7264 bellard
                } else {
500 18a6d284 bellard
                    int dz;
501 18a6d284 bellard
                    dz = 0;
502 4c44bdcb aurel32
                    if (ev->type == SDL_MOUSEBUTTONDOWN) {
503 4c44bdcb aurel32
                        buttonstate |= SDL_BUTTON(bev->button);
504 4c44bdcb aurel32
                    } else {
505 4c44bdcb aurel32
                        buttonstate &= ~SDL_BUTTON(bev->button);
506 4c44bdcb aurel32
                    }
507 18a6d284 bellard
#ifdef SDL_BUTTON_WHEELUP
508 09b26c5e bellard
                    if (bev->button == SDL_BUTTON_WHEELUP && ev->type == SDL_MOUSEBUTTONDOWN) {
509 18a6d284 bellard
                        dz = -1;
510 09b26c5e bellard
                    } else if (bev->button == SDL_BUTTON_WHEELDOWN && ev->type == SDL_MOUSEBUTTONDOWN) {
511 18a6d284 bellard
                        dz = 1;
512 18a6d284 bellard
                    }
513 3b46e624 ths
#endif
514 4c44bdcb aurel32
                    sdl_send_mouse_event(0, 0, dz, bev->x, bev->y, buttonstate);
515 0f0b7264 bellard
                }
516 0f0b7264 bellard
            }
517 0f0b7264 bellard
            break;
518 0294ffb9 bellard
        case SDL_ACTIVEEVENT:
519 5b311878 pbrook
            if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS &&
520 5b311878 pbrook
                !ev->active.gain && !gui_fullscreen_initial_grab) {
521 0294ffb9 bellard
                sdl_grab_end();
522 0294ffb9 bellard
            }
523 f442e08b aurel32
            if (ev->active.state & SDL_APPACTIVE) {
524 f442e08b aurel32
                if (ev->active.gain) {
525 f442e08b aurel32
                    /* Back to default interval */
526 f442e08b aurel32
                    ds->gui_timer_interval = 0;
527 bcfad70f aliguori
                    ds->idle = 0;
528 f442e08b aurel32
                } else {
529 f442e08b aurel32
                    /* Sleeping interval */
530 f442e08b aurel32
                    ds->gui_timer_interval = 500;
531 bcfad70f aliguori
                    ds->idle = 1;
532 f442e08b aurel32
                }
533 f442e08b aurel32
            }
534 0294ffb9 bellard
            break;
535 0f0b7264 bellard
        default:
536 0f0b7264 bellard
            break;
537 0f0b7264 bellard
        }
538 0f0b7264 bellard
    }
539 0f0b7264 bellard
}
540 0f0b7264 bellard
541 d34cab9f ths
static void sdl_fill(DisplayState *ds, int x, int y, int w, int h, uint32_t c)
542 d34cab9f ths
{
543 d34cab9f ths
    SDL_Rect dst = { x, y, w, h };
544 d34cab9f ths
    SDL_FillRect(screen, &dst, c);
545 d34cab9f ths
}
546 d34cab9f ths
547 d34cab9f ths
static void sdl_mouse_warp(int x, int y, int on)
548 d34cab9f ths
{
549 d34cab9f ths
    if (on) {
550 d34cab9f ths
        if (!guest_cursor)
551 d34cab9f ths
            sdl_show_cursor();
552 d34cab9f ths
        if (gui_grab || kbd_mouse_is_absolute() || absolute_enabled) {
553 d34cab9f ths
            SDL_SetCursor(guest_sprite);
554 d34cab9f ths
            SDL_WarpMouse(x, y);
555 d34cab9f ths
        }
556 d34cab9f ths
    } else if (gui_grab)
557 d34cab9f ths
        sdl_hide_cursor();
558 d34cab9f ths
    guest_cursor = on;
559 d34cab9f ths
    guest_x = x, guest_y = y;
560 d34cab9f ths
}
561 d34cab9f ths
562 d34cab9f ths
static void sdl_mouse_define(int width, int height, int bpp,
563 d34cab9f ths
                             int hot_x, int hot_y,
564 d34cab9f ths
                             uint8_t *image, uint8_t *mask)
565 d34cab9f ths
{
566 d34cab9f ths
    uint8_t sprite[256], *line;
567 d34cab9f ths
    int x, y, dst, bypl, src = 0;
568 d34cab9f ths
    if (guest_sprite)
569 d34cab9f ths
        SDL_FreeCursor(guest_sprite);
570 d34cab9f ths
571 d34cab9f ths
    memset(sprite, 0, 256);
572 d34cab9f ths
    bypl = ((width * bpp + 31) >> 5) << 2;
573 d34cab9f ths
    for (y = 0, dst = 0; y < height; y ++, image += bypl) {
574 d34cab9f ths
        line = image;
575 d34cab9f ths
        for (x = 0; x < width; x ++, dst ++) {
576 d34cab9f ths
            switch (bpp) {
577 d34cab9f ths
            case 24:
578 d34cab9f ths
                src = *(line ++); src |= *(line ++); src |= *(line ++);
579 d34cab9f ths
                break;
580 d34cab9f ths
            case 16:
581 d34cab9f ths
            case 15:
582 d34cab9f ths
                src = *(line ++); src |= *(line ++);
583 d34cab9f ths
                break;
584 d34cab9f ths
            case 8:
585 d34cab9f ths
                src = *(line ++);
586 d34cab9f ths
                break;
587 d34cab9f ths
            case 4:
588 d34cab9f ths
                src = 0xf & (line[x >> 1] >> ((x & 1)) << 2);
589 d34cab9f ths
                break;
590 d34cab9f ths
            case 2:
591 d34cab9f ths
                src = 3 & (line[x >> 2] >> ((x & 3)) << 1);
592 d34cab9f ths
                break;
593 d34cab9f ths
            case 1:
594 d34cab9f ths
                src = 1 & (line[x >> 3] >> (x & 7));
595 d34cab9f ths
                break;
596 d34cab9f ths
            }
597 d34cab9f ths
            if (!src)
598 d34cab9f ths
                sprite[dst >> 3] |= (1 << (~dst & 7)) & mask[dst >> 3];
599 d34cab9f ths
        }
600 d34cab9f ths
    }
601 d34cab9f ths
    guest_sprite = SDL_CreateCursor(sprite, mask, width, height, hot_x, hot_y);
602 d34cab9f ths
603 d34cab9f ths
    if (guest_cursor &&
604 d34cab9f ths
            (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
605 d34cab9f ths
        SDL_SetCursor(guest_sprite);
606 d34cab9f ths
}
607 d34cab9f ths
608 5fafdf24 ths
static void sdl_cleanup(void)
609 898712a8 bellard
{
610 d34cab9f ths
    if (guest_sprite)
611 d34cab9f ths
        SDL_FreeCursor(guest_sprite);
612 898712a8 bellard
    SDL_Quit();
613 898712a8 bellard
}
614 898712a8 bellard
615 43523e93 ths
void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
616 0f0b7264 bellard
{
617 0f0b7264 bellard
    int flags;
618 09b26c5e bellard
    uint8_t data = 0;
619 0f0b7264 bellard
620 3d11d0eb bellard
#if defined(__APPLE__)
621 3d11d0eb bellard
    /* always use generic keymaps */
622 3d11d0eb bellard
    if (!keyboard_layout)
623 3d11d0eb bellard
        keyboard_layout = "en-us";
624 3d11d0eb bellard
#endif
625 3d11d0eb bellard
    if(keyboard_layout) {
626 3d11d0eb bellard
        kbd_layout = init_keyboard_layout(keyboard_layout);
627 3d11d0eb bellard
        if (!kbd_layout)
628 3d11d0eb bellard
            exit(1);
629 3d11d0eb bellard
    }
630 3d11d0eb bellard
631 43523e93 ths
    if (no_frame)
632 43523e93 ths
        gui_noframe = 1;
633 43523e93 ths
634 0f0b7264 bellard
    flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE;
635 0f0b7264 bellard
    if (SDL_Init (flags)) {
636 0f0b7264 bellard
        fprintf(stderr, "Could not initialize SDL - exiting\n");
637 0f0b7264 bellard
        exit(1);
638 0f0b7264 bellard
    }
639 0ae04d73 bellard
640 0f0b7264 bellard
    ds->dpy_update = sdl_update;
641 0f0b7264 bellard
    ds->dpy_resize = sdl_resize;
642 0f0b7264 bellard
    ds->dpy_refresh = sdl_refresh;
643 d34cab9f ths
    ds->dpy_fill = sdl_fill;
644 d34cab9f ths
    ds->mouse_set = sdl_mouse_warp;
645 d34cab9f ths
    ds->cursor_define = sdl_mouse_define;
646 0f0b7264 bellard
647 0f0b7264 bellard
    sdl_resize(ds, 640, 400);
648 8a7ddc38 bellard
    sdl_update_caption();
649 0f0b7264 bellard
    SDL_EnableKeyRepeat(250, 50);
650 0f0b7264 bellard
    gui_grab = 0;
651 898712a8 bellard
652 09b26c5e bellard
    sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0);
653 09b26c5e bellard
    sdl_cursor_normal = SDL_GetCursor();
654 09b26c5e bellard
655 898712a8 bellard
    atexit(sdl_cleanup);
656 d63d307f bellard
    if (full_screen) {
657 d63d307f bellard
        gui_fullscreen = 1;
658 d63d307f bellard
        gui_fullscreen_initial_grab = 1;
659 d63d307f bellard
        sdl_grab_start();
660 d63d307f bellard
    }
661 0f0b7264 bellard
}