Statistics
| Branch: | Revision:

root / ui / sdl.c @ 957f1f99

History | View | Annotate | Download (29.9 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 cdfb017e Stefan Weil
25 cdfb017e Stefan Weil
/* Avoid compiler warning because macro is redefined in SDL_syswm.h. */
26 cdfb017e Stefan Weil
#undef WIN32_LEAN_AND_MEAN
27 cdfb017e Stefan Weil
28 0f0b7264 bellard
#include <SDL.h>
29 c9985aa8 aliguori
#include <SDL_syswm.h>
30 0f0b7264 bellard
31 511d2b14 blueswir1
#include "qemu-common.h"
32 511d2b14 blueswir1
#include "console.h"
33 511d2b14 blueswir1
#include "sysemu.h"
34 511d2b14 blueswir1
#include "x_keymap.h"
35 c18a2c36 Stefano Stabellini
#include "sdl_zoom.h"
36 511d2b14 blueswir1
37 7d957bd8 aliguori
static DisplayChangeListener *dcl;
38 7d957bd8 aliguori
static SDL_Surface *real_screen;
39 7d957bd8 aliguori
static SDL_Surface *guest_screen = NULL;
40 0f0b7264 bellard
static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
41 8a7ddc38 bellard
static int last_vm_running;
42 f9977897 Jan Kiszka
static bool gui_saved_scaling;
43 f9977897 Jan Kiszka
static int gui_saved_width;
44 f9977897 Jan Kiszka
static int gui_saved_height;
45 8e9c4afe bellard
static int gui_saved_grab;
46 8e9c4afe bellard
static int gui_fullscreen;
47 43523e93 ths
static int gui_noframe;
48 8e9c4afe bellard
static int gui_key_modifier_pressed;
49 8e9c4afe bellard
static int gui_keysym;
50 32ff25bf bellard
static int gui_grab_code = KMOD_LALT | KMOD_LCTRL;
51 32ff25bf bellard
static uint8_t modifiers_state[256];
52 09b26c5e bellard
static SDL_Cursor *sdl_cursor_normal;
53 09b26c5e bellard
static SDL_Cursor *sdl_cursor_hidden;
54 09b26c5e bellard
static int absolute_enabled = 0;
55 d34cab9f ths
static int guest_cursor = 0;
56 d34cab9f ths
static int guest_x, guest_y;
57 660f11be Blue Swirl
static SDL_Cursor *guest_sprite = NULL;
58 7b5d76da aliguori
static uint8_t allocator;
59 c18a2c36 Stefano Stabellini
static SDL_PixelFormat host_format;
60 c18a2c36 Stefano Stabellini
static int scaling_active = 0;
61 3af12c86 Anthony Liguori
static Notifier mouse_mode_notifier;
62 0f0b7264 bellard
63 0f0b7264 bellard
static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
64 0f0b7264 bellard
{
65 898712a8 bellard
    //    printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
66 c18a2c36 Stefano Stabellini
    SDL_Rect rec;
67 c18a2c36 Stefano Stabellini
    rec.x = x;
68 c18a2c36 Stefano Stabellini
    rec.y = y;
69 c18a2c36 Stefano Stabellini
    rec.w = w;
70 c18a2c36 Stefano Stabellini
    rec.h = h;
71 c18a2c36 Stefano Stabellini
72 7b5d76da aliguori
    if (guest_screen) {
73 c18a2c36 Stefano Stabellini
        if (!scaling_active) {
74 c18a2c36 Stefano Stabellini
            SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
75 c18a2c36 Stefano Stabellini
        } else {
76 c18a2c36 Stefano Stabellini
            if (sdl_zoom_blit(guest_screen, real_screen, SMOOTHING_ON, &rec) < 0) {
77 c18a2c36 Stefano Stabellini
                fprintf(stderr, "Zoom blit failed\n");
78 c18a2c36 Stefano Stabellini
                exit(1);
79 c18a2c36 Stefano Stabellini
            }
80 c18a2c36 Stefano Stabellini
        }
81 c18a2c36 Stefano Stabellini
    } 
82 c18a2c36 Stefano Stabellini
    SDL_UpdateRect(real_screen, rec.x, rec.y, rec.w, rec.h);
83 7d957bd8 aliguori
}
84 7d957bd8 aliguori
85 7d957bd8 aliguori
static void sdl_setdata(DisplayState *ds)
86 7d957bd8 aliguori
{
87 7d957bd8 aliguori
    if (guest_screen != NULL) SDL_FreeSurface(guest_screen);
88 7d957bd8 aliguori
89 7d957bd8 aliguori
    guest_screen = SDL_CreateRGBSurfaceFrom(ds_get_data(ds), ds_get_width(ds), ds_get_height(ds),
90 7d957bd8 aliguori
                                            ds_get_bits_per_pixel(ds), ds_get_linesize(ds),
91 7d957bd8 aliguori
                                            ds->surface->pf.rmask, ds->surface->pf.gmask,
92 7d957bd8 aliguori
                                            ds->surface->pf.bmask, ds->surface->pf.amask);
93 0f0b7264 bellard
}
94 0f0b7264 bellard
95 9510a486 Jan Kiszka
static void do_sdl_resize(int width, int height, int bpp)
96 0f0b7264 bellard
{
97 0f0b7264 bellard
    int flags;
98 0f0b7264 bellard
99 0f0b7264 bellard
    //    printf("resizing to %d %d\n", w, h);
100 0f0b7264 bellard
101 91ada980 Jan Kiszka
    flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
102 91ada980 Jan Kiszka
    if (gui_fullscreen) {
103 8e9c4afe bellard
        flags |= SDL_FULLSCREEN;
104 91ada980 Jan Kiszka
    } else {
105 91ada980 Jan Kiszka
        flags |= SDL_RESIZABLE;
106 91ada980 Jan Kiszka
    }
107 43523e93 ths
    if (gui_noframe)
108 43523e93 ths
        flags |= SDL_NOFRAME;
109 9903da21 bellard
110 7b5d76da aliguori
    real_screen = SDL_SetVideoMode(width, height, bpp, flags);
111 7d957bd8 aliguori
    if (!real_screen) {
112 b6034a39 Bjørn Mork
        fprintf(stderr, "Could not open SDL display (%dx%dx%d): %s\n", width, 
113 b6034a39 Bjørn Mork
                height, bpp, SDL_GetError());
114 0f0b7264 bellard
        exit(1);
115 0f0b7264 bellard
    }
116 7b5d76da aliguori
}
117 7b5d76da aliguori
118 7b5d76da aliguori
static void sdl_resize(DisplayState *ds)
119 7b5d76da aliguori
{
120 7b5d76da aliguori
    if  (!allocator) {
121 c18a2c36 Stefano Stabellini
        if (!scaling_active)
122 c18a2c36 Stefano Stabellini
            do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
123 c18a2c36 Stefano Stabellini
        else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds))
124 c18a2c36 Stefano Stabellini
            do_sdl_resize(real_screen->w, real_screen->h, ds_get_bits_per_pixel(ds));
125 7b5d76da aliguori
        sdl_setdata(ds);
126 7b5d76da aliguori
    } else {
127 7b5d76da aliguori
        if (guest_screen != NULL) {
128 7b5d76da aliguori
            SDL_FreeSurface(guest_screen);
129 7b5d76da aliguori
            guest_screen = NULL;
130 7b5d76da aliguori
        }
131 7b5d76da aliguori
    }
132 7b5d76da aliguori
}
133 7b5d76da aliguori
134 7b5d76da aliguori
static PixelFormat sdl_to_qemu_pixelformat(SDL_PixelFormat *sdl_pf)
135 7b5d76da aliguori
{
136 7b5d76da aliguori
    PixelFormat qemu_pf;
137 7b5d76da aliguori
138 7b5d76da aliguori
    memset(&qemu_pf, 0x00, sizeof(PixelFormat));
139 7b5d76da aliguori
140 7b5d76da aliguori
    qemu_pf.bits_per_pixel = sdl_pf->BitsPerPixel;
141 7b5d76da aliguori
    qemu_pf.bytes_per_pixel = sdl_pf->BytesPerPixel;
142 7b5d76da aliguori
    qemu_pf.depth = (qemu_pf.bits_per_pixel) == 32 ? 24 : (qemu_pf.bits_per_pixel);
143 7b5d76da aliguori
144 7b5d76da aliguori
    qemu_pf.rmask = sdl_pf->Rmask;
145 7b5d76da aliguori
    qemu_pf.gmask = sdl_pf->Gmask;
146 7b5d76da aliguori
    qemu_pf.bmask = sdl_pf->Bmask;
147 7b5d76da aliguori
    qemu_pf.amask = sdl_pf->Amask;
148 7b5d76da aliguori
149 7b5d76da aliguori
    qemu_pf.rshift = sdl_pf->Rshift;
150 7b5d76da aliguori
    qemu_pf.gshift = sdl_pf->Gshift;
151 7b5d76da aliguori
    qemu_pf.bshift = sdl_pf->Bshift;
152 7b5d76da aliguori
    qemu_pf.ashift = sdl_pf->Ashift;
153 7b5d76da aliguori
154 7b5d76da aliguori
    qemu_pf.rbits = 8 - sdl_pf->Rloss;
155 7b5d76da aliguori
    qemu_pf.gbits = 8 - sdl_pf->Gloss;
156 7b5d76da aliguori
    qemu_pf.bbits = 8 - sdl_pf->Bloss;
157 7b5d76da aliguori
    qemu_pf.abits = 8 - sdl_pf->Aloss;
158 7b5d76da aliguori
159 7b5d76da aliguori
    qemu_pf.rmax = ((1 << qemu_pf.rbits) - 1);
160 7b5d76da aliguori
    qemu_pf.gmax = ((1 << qemu_pf.gbits) - 1);
161 7b5d76da aliguori
    qemu_pf.bmax = ((1 << qemu_pf.bbits) - 1);
162 7b5d76da aliguori
    qemu_pf.amax = ((1 << qemu_pf.abits) - 1);
163 7b5d76da aliguori
164 7b5d76da aliguori
    return qemu_pf;
165 7b5d76da aliguori
}
166 7b5d76da aliguori
167 7b5d76da aliguori
static DisplaySurface* sdl_create_displaysurface(int width, int height)
168 7b5d76da aliguori
{
169 7267c094 Anthony Liguori
    DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
170 7b5d76da aliguori
    if (surface == NULL) {
171 7b5d76da aliguori
        fprintf(stderr, "sdl_create_displaysurface: malloc failed\n");
172 7b5d76da aliguori
        exit(1);
173 7b5d76da aliguori
    }
174 7b5d76da aliguori
175 7b5d76da aliguori
    surface->width = width;
176 7b5d76da aliguori
    surface->height = height;
177 ffe8b821 Jes Sorensen
178 c18a2c36 Stefano Stabellini
    if (scaling_active) {
179 ffe8b821 Jes Sorensen
        int linesize;
180 ffe8b821 Jes Sorensen
        PixelFormat pf;
181 c18a2c36 Stefano Stabellini
        if (host_format.BytesPerPixel != 2 && host_format.BytesPerPixel != 4) {
182 ffe8b821 Jes Sorensen
            linesize = width * 4;
183 ffe8b821 Jes Sorensen
            pf = qemu_default_pixelformat(32);
184 c18a2c36 Stefano Stabellini
        } else {
185 ffe8b821 Jes Sorensen
            linesize = width * host_format.BytesPerPixel;
186 ffe8b821 Jes Sorensen
            pf = sdl_to_qemu_pixelformat(&host_format);
187 c18a2c36 Stefano Stabellini
        }
188 ffe8b821 Jes Sorensen
        qemu_alloc_display(surface, width, height, linesize, pf, 0);
189 c18a2c36 Stefano Stabellini
        return surface;
190 c18a2c36 Stefano Stabellini
    }
191 7d957bd8 aliguori
192 c18a2c36 Stefano Stabellini
    if (host_format.BitsPerPixel == 16)
193 7b5d76da aliguori
        do_sdl_resize(width, height, 16);
194 7b5d76da aliguori
    else
195 7b5d76da aliguori
        do_sdl_resize(width, height, 32);
196 7b5d76da aliguori
197 7b5d76da aliguori
    surface->pf = sdl_to_qemu_pixelformat(real_screen->format);
198 7b5d76da aliguori
    surface->linesize = real_screen->pitch;
199 7b5d76da aliguori
    surface->data = real_screen->pixels;
200 7b5d76da aliguori
201 e2542fe2 Juan Quintela
#ifdef HOST_WORDS_BIGENDIAN
202 c18a2c36 Stefano Stabellini
    surface->flags = QEMU_REALPIXELS_FLAG | QEMU_BIG_ENDIAN_FLAG;
203 7b5d76da aliguori
#else
204 c18a2c36 Stefano Stabellini
    surface->flags = QEMU_REALPIXELS_FLAG;
205 7b5d76da aliguori
#endif
206 7b5d76da aliguori
    allocator = 1;
207 7b5d76da aliguori
208 7b5d76da aliguori
    return surface;
209 7b5d76da aliguori
}
210 7b5d76da aliguori
211 7b5d76da aliguori
static void sdl_free_displaysurface(DisplaySurface *surface)
212 7b5d76da aliguori
{
213 7b5d76da aliguori
    allocator = 0;
214 7b5d76da aliguori
    if (surface == NULL)
215 7b5d76da aliguori
        return;
216 c18a2c36 Stefano Stabellini
217 c18a2c36 Stefano Stabellini
    if (surface->flags & QEMU_ALLOCATED_FLAG)
218 7267c094 Anthony Liguori
        g_free(surface->data);
219 7267c094 Anthony Liguori
    g_free(surface);
220 7b5d76da aliguori
}
221 7b5d76da aliguori
222 7b5d76da aliguori
static DisplaySurface* sdl_resize_displaysurface(DisplaySurface *surface, int width, int height)
223 7b5d76da aliguori
{
224 7b5d76da aliguori
    sdl_free_displaysurface(surface);
225 7b5d76da aliguori
    return sdl_create_displaysurface(width, height);
226 0f0b7264 bellard
}
227 0f0b7264 bellard
228 3d11d0eb bellard
/* generic keyboard conversion */
229 e58d12ed bellard
230 3d11d0eb bellard
#include "sdl_keysym.h"
231 3d11d0eb bellard
232 c227f099 Anthony Liguori
static kbd_layout_t *kbd_layout = NULL;
233 3d11d0eb bellard
234 3d11d0eb bellard
static uint8_t sdl_keyevent_to_keycode_generic(const SDL_KeyboardEvent *ev)
235 e58d12ed bellard
{
236 3d11d0eb bellard
    int keysym;
237 3d11d0eb bellard
    /* workaround for X11+SDL bug with AltGR */
238 3d11d0eb bellard
    keysym = ev->keysym.sym;
239 3d11d0eb bellard
    if (keysym == 0 && ev->keysym.scancode == 113)
240 3d11d0eb bellard
        keysym = SDLK_MODE;
241 60659e3b bellard
    /* For Japanese key '\' and '|' */
242 60659e3b bellard
    if (keysym == 92 && ev->keysym.scancode == 133) {
243 60659e3b bellard
        keysym = 0xa5;
244 60659e3b bellard
    }
245 44bb61c8 Samuel Thibault
    return keysym2scancode(kbd_layout, keysym) & SCANCODE_KEYMASK;
246 e58d12ed bellard
}
247 e58d12ed bellard
248 3d11d0eb bellard
/* specific keyboard conversions from scan codes */
249 3d11d0eb bellard
250 3d11d0eb bellard
#if defined(_WIN32)
251 e58d12ed bellard
252 e58d12ed bellard
static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
253 e58d12ed bellard
{
254 e58d12ed bellard
    return ev->keysym.scancode;
255 e58d12ed bellard
}
256 e58d12ed bellard
257 e58d12ed bellard
#else
258 e58d12ed bellard
259 5368a422 aliguori
#if defined(SDL_VIDEO_DRIVER_X11)
260 5368a422 aliguori
#include <X11/XKBlib.h>
261 5368a422 aliguori
262 5368a422 aliguori
static int check_for_evdev(void)
263 5368a422 aliguori
{
264 5368a422 aliguori
    SDL_SysWMinfo info;
265 229609dd Jan Kiszka
    XkbDescPtr desc = NULL;
266 5368a422 aliguori
    int has_evdev = 0;
267 229609dd Jan Kiszka
    char *keycodes = NULL;
268 5368a422 aliguori
269 5368a422 aliguori
    SDL_VERSION(&info.version);
270 229609dd Jan Kiszka
    if (!SDL_GetWMInfo(&info)) {
271 5368a422 aliguori
        return 0;
272 229609dd Jan Kiszka
    }
273 5368a422 aliguori
    desc = XkbGetKeyboard(info.info.x11.display,
274 5368a422 aliguori
                          XkbGBN_AllComponentsMask,
275 5368a422 aliguori
                          XkbUseCoreKbd);
276 229609dd Jan Kiszka
    if (desc && desc->names) {
277 229609dd Jan Kiszka
        keycodes = XGetAtomName(info.info.x11.display, desc->names->keycodes);
278 229609dd Jan Kiszka
        if (keycodes == NULL) {
279 229609dd Jan Kiszka
            fprintf(stderr, "could not lookup keycode name\n");
280 229609dd Jan Kiszka
        } else if (strstart(keycodes, "evdev", NULL)) {
281 229609dd Jan Kiszka
            has_evdev = 1;
282 229609dd Jan Kiszka
        } else if (!strstart(keycodes, "xfree86", NULL)) {
283 229609dd Jan Kiszka
            fprintf(stderr, "unknown keycodes `%s', please report to "
284 229609dd Jan Kiszka
                    "qemu-devel@nongnu.org\n", keycodes);
285 229609dd Jan Kiszka
        }
286 229609dd Jan Kiszka
    }
287 5368a422 aliguori
288 229609dd Jan Kiszka
    if (desc) {
289 229609dd Jan Kiszka
        XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True);
290 229609dd Jan Kiszka
    }
291 229609dd Jan Kiszka
    if (keycodes) {
292 229609dd Jan Kiszka
        XFree(keycodes);
293 229609dd Jan Kiszka
    }
294 5368a422 aliguori
    return has_evdev;
295 5368a422 aliguori
}
296 5368a422 aliguori
#else
297 5368a422 aliguori
static int check_for_evdev(void)
298 5368a422 aliguori
{
299 5368a422 aliguori
        return 0;
300 5368a422 aliguori
}
301 5368a422 aliguori
#endif
302 5368a422 aliguori
303 e58d12ed bellard
static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
304 e58d12ed bellard
{
305 e58d12ed bellard
    int keycode;
306 5368a422 aliguori
    static int has_evdev = -1;
307 5368a422 aliguori
308 5368a422 aliguori
    if (has_evdev == -1)
309 5368a422 aliguori
        has_evdev = check_for_evdev();
310 e58d12ed bellard
311 e58d12ed bellard
    keycode = ev->keysym.scancode;
312 e58d12ed bellard
313 e58d12ed bellard
    if (keycode < 9) {
314 e58d12ed bellard
        keycode = 0;
315 e58d12ed bellard
    } else if (keycode < 97) {
316 e58d12ed bellard
        keycode -= 8; /* just an offset */
317 5368a422 aliguori
    } else if (keycode < 158) {
318 e58d12ed bellard
        /* use conversion table */
319 5368a422 aliguori
        if (has_evdev)
320 5368a422 aliguori
            keycode = translate_evdev_keycode(keycode - 97);
321 5368a422 aliguori
        else
322 5368a422 aliguori
            keycode = translate_xfree86_keycode(keycode - 97);
323 5368a422 aliguori
    } else if (keycode == 208) { /* Hiragana_Katakana */
324 5368a422 aliguori
        keycode = 0x70;
325 5368a422 aliguori
    } else if (keycode == 211) { /* backslash */
326 5368a422 aliguori
        keycode = 0x73;
327 e58d12ed bellard
    } else {
328 e58d12ed bellard
        keycode = 0;
329 e58d12ed bellard
    }
330 e58d12ed bellard
    return keycode;
331 e58d12ed bellard
}
332 e58d12ed bellard
333 e58d12ed bellard
#endif
334 e58d12ed bellard
335 32ff25bf bellard
static void reset_keys(void)
336 32ff25bf bellard
{
337 32ff25bf bellard
    int i;
338 32ff25bf bellard
    for(i = 0; i < 256; i++) {
339 32ff25bf bellard
        if (modifiers_state[i]) {
340 44bb61c8 Samuel Thibault
            if (i & SCANCODE_GREY)
341 44bb61c8 Samuel Thibault
                kbd_put_keycode(SCANCODE_EMUL0);
342 44bb61c8 Samuel Thibault
            kbd_put_keycode(i | SCANCODE_UP);
343 32ff25bf bellard
            modifiers_state[i] = 0;
344 32ff25bf bellard
        }
345 32ff25bf bellard
    }
346 32ff25bf bellard
}
347 32ff25bf bellard
348 0f0b7264 bellard
static void sdl_process_key(SDL_KeyboardEvent *ev)
349 0f0b7264 bellard
{
350 32ff25bf bellard
    int keycode, v;
351 de2200d3 bellard
352 de2200d3 bellard
    if (ev->keysym.sym == SDLK_PAUSE) {
353 de2200d3 bellard
        /* specific case */
354 de2200d3 bellard
        v = 0;
355 de2200d3 bellard
        if (ev->type == SDL_KEYUP)
356 44bb61c8 Samuel Thibault
            v |= SCANCODE_UP;
357 de2200d3 bellard
        kbd_put_keycode(0xe1);
358 de2200d3 bellard
        kbd_put_keycode(0x1d | v);
359 de2200d3 bellard
        kbd_put_keycode(0x45 | v);
360 de2200d3 bellard
        return;
361 de2200d3 bellard
    }
362 de2200d3 bellard
363 3d11d0eb bellard
    if (kbd_layout) {
364 3d11d0eb bellard
        keycode = sdl_keyevent_to_keycode_generic(ev);
365 3d11d0eb bellard
    } else {
366 3d11d0eb bellard
        keycode = sdl_keyevent_to_keycode(ev);
367 3d11d0eb bellard
    }
368 de2200d3 bellard
369 de2200d3 bellard
    switch(keycode) {
370 de2200d3 bellard
    case 0x00:
371 de2200d3 bellard
        /* sent when leaving window: reset the modifiers state */
372 32ff25bf bellard
        reset_keys();
373 de2200d3 bellard
        return;
374 de2200d3 bellard
    case 0x2a:                          /* Left Shift */
375 de2200d3 bellard
    case 0x36:                          /* Right Shift */
376 de2200d3 bellard
    case 0x1d:                          /* Left CTRL */
377 de2200d3 bellard
    case 0x9d:                          /* Right CTRL */
378 de2200d3 bellard
    case 0x38:                          /* Left ALT */
379 de2200d3 bellard
    case 0xb8:                         /* Right ALT */
380 0f0b7264 bellard
        if (ev->type == SDL_KEYUP)
381 de2200d3 bellard
            modifiers_state[keycode] = 0;
382 de2200d3 bellard
        else
383 de2200d3 bellard
            modifiers_state[keycode] = 1;
384 de2200d3 bellard
        break;
385 4e79bcbb Stefan Weil
#define QEMU_SDL_VERSION ((SDL_MAJOR_VERSION << 8) + SDL_MINOR_VERSION)
386 4e79bcbb Stefan Weil
#if QEMU_SDL_VERSION < 0x102 || QEMU_SDL_VERSION == 0x102 && SDL_PATCHLEVEL < 14
387 4e79bcbb Stefan Weil
        /* SDL versions before 1.2.14 don't support key up for caps/num lock. */
388 de2200d3 bellard
    case 0x45: /* num lock */
389 de2200d3 bellard
    case 0x3a: /* caps lock */
390 de2200d3 bellard
        /* SDL does not send the key up event, so we generate it */
391 de2200d3 bellard
        kbd_put_keycode(keycode);
392 44bb61c8 Samuel Thibault
        kbd_put_keycode(keycode | SCANCODE_UP);
393 de2200d3 bellard
        return;
394 4e79bcbb Stefan Weil
#endif
395 0f0b7264 bellard
    }
396 de2200d3 bellard
397 de2200d3 bellard
    /* now send the key code */
398 44bb61c8 Samuel Thibault
    if (keycode & SCANCODE_GREY)
399 44bb61c8 Samuel Thibault
        kbd_put_keycode(SCANCODE_EMUL0);
400 de2200d3 bellard
    if (ev->type == SDL_KEYUP)
401 44bb61c8 Samuel Thibault
        kbd_put_keycode(keycode | SCANCODE_UP);
402 de2200d3 bellard
    else
403 44bb61c8 Samuel Thibault
        kbd_put_keycode(keycode & SCANCODE_KEYCODEMASK);
404 0f0b7264 bellard
}
405 0f0b7264 bellard
406 8a7ddc38 bellard
static void sdl_update_caption(void)
407 8a7ddc38 bellard
{
408 b4ed5d18 Dominic Evans
    char win_title[1024];
409 b4ed5d18 Dominic Evans
    char icon_title[1024];
410 c35734b2 ths
    const char *status = "";
411 c35734b2 ths
412 c35734b2 ths
    if (!vm_running)
413 c35734b2 ths
        status = " [Stopped]";
414 3780e197 ths
    else if (gui_grab) {
415 0ca9f8a4 Dustin Kirkland
        if (alt_grab)
416 4e75b342 Anthony Liguori
            status = " - Press Ctrl-Alt-Shift to exit mouse grab";
417 0ca9f8a4 Dustin Kirkland
        else if (ctrl_grab)
418 4e75b342 Anthony Liguori
            status = " - Press Right-Ctrl to exit mouse grab";
419 0ca9f8a4 Dustin Kirkland
        else
420 4e75b342 Anthony Liguori
            status = " - Press Ctrl-Alt to exit mouse grab";
421 3780e197 ths
    }
422 c35734b2 ths
423 b4ed5d18 Dominic Evans
    if (qemu_name) {
424 b4ed5d18 Dominic Evans
        snprintf(win_title, sizeof(win_title), "QEMU (%s)%s", qemu_name, status);
425 b4ed5d18 Dominic Evans
        snprintf(icon_title, sizeof(icon_title), "QEMU (%s)", qemu_name);
426 b4ed5d18 Dominic Evans
    } else {
427 b4ed5d18 Dominic Evans
        snprintf(win_title, sizeof(win_title), "QEMU%s", status);
428 b4ed5d18 Dominic Evans
        snprintf(icon_title, sizeof(icon_title), "QEMU");
429 b4ed5d18 Dominic Evans
    }
430 c35734b2 ths
431 b4ed5d18 Dominic Evans
    SDL_WM_SetCaption(win_title, icon_title);
432 8a7ddc38 bellard
}
433 8a7ddc38 bellard
434 09b26c5e bellard
static void sdl_hide_cursor(void)
435 09b26c5e bellard
{
436 9467cd46 balrog
    if (!cursor_hide)
437 9467cd46 balrog
        return;
438 9467cd46 balrog
439 8785a8dd bellard
    if (kbd_mouse_is_absolute()) {
440 8785a8dd bellard
        SDL_ShowCursor(1);
441 8785a8dd bellard
        SDL_SetCursor(sdl_cursor_hidden);
442 8785a8dd bellard
    } else {
443 8785a8dd bellard
        SDL_ShowCursor(0);
444 8785a8dd bellard
    }
445 09b26c5e bellard
}
446 09b26c5e bellard
447 09b26c5e bellard
static void sdl_show_cursor(void)
448 09b26c5e bellard
{
449 9467cd46 balrog
    if (!cursor_hide)
450 9467cd46 balrog
        return;
451 9467cd46 balrog
452 74d9dc69 Jan Kiszka
    if (!kbd_mouse_is_absolute() || !is_graphic_console()) {
453 8785a8dd bellard
        SDL_ShowCursor(1);
454 d34cab9f ths
        if (guest_cursor &&
455 d34cab9f ths
                (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
456 d34cab9f ths
            SDL_SetCursor(guest_sprite);
457 d34cab9f ths
        else
458 d34cab9f ths
            SDL_SetCursor(sdl_cursor_normal);
459 09b26c5e bellard
    }
460 09b26c5e bellard
}
461 09b26c5e bellard
462 0f0b7264 bellard
static void sdl_grab_start(void)
463 0f0b7264 bellard
{
464 d34cab9f ths
    if (guest_cursor) {
465 d34cab9f ths
        SDL_SetCursor(guest_sprite);
466 08a2d4c4 balrog
        if (!kbd_mouse_is_absolute() && !absolute_enabled)
467 08a2d4c4 balrog
            SDL_WarpMouse(guest_x, guest_y);
468 d34cab9f ths
    } else
469 d34cab9f ths
        sdl_hide_cursor();
470 6bb81603 aliguori
471 6bb81603 aliguori
    if (SDL_WM_GrabInput(SDL_GRAB_ON) == SDL_GRAB_ON) {
472 6bb81603 aliguori
        gui_grab = 1;
473 6bb81603 aliguori
        sdl_update_caption();
474 6bb81603 aliguori
    } else
475 6bb81603 aliguori
        sdl_show_cursor();
476 0f0b7264 bellard
}
477 0f0b7264 bellard
478 0f0b7264 bellard
static void sdl_grab_end(void)
479 0f0b7264 bellard
{
480 0f0b7264 bellard
    SDL_WM_GrabInput(SDL_GRAB_OFF);
481 0f0b7264 bellard
    gui_grab = 0;
482 d34cab9f ths
    sdl_show_cursor();
483 8a7ddc38 bellard
    sdl_update_caption();
484 0f0b7264 bellard
}
485 0f0b7264 bellard
486 9e8dd451 Jan Kiszka
static void sdl_mouse_mode_change(Notifier *notify, void *data)
487 3af12c86 Anthony Liguori
{
488 3af12c86 Anthony Liguori
    if (kbd_mouse_is_absolute()) {
489 3af12c86 Anthony Liguori
        if (!absolute_enabled) {
490 35b0f237 Jan Kiszka
            sdl_grab_start();
491 3af12c86 Anthony Liguori
            absolute_enabled = 1;
492 3af12c86 Anthony Liguori
        }
493 3af12c86 Anthony Liguori
    } else if (absolute_enabled) {
494 35b0f237 Jan Kiszka
        sdl_grab_end();
495 35b0f237 Jan Kiszka
        absolute_enabled = 0;
496 3af12c86 Anthony Liguori
    }
497 3af12c86 Anthony Liguori
}
498 3af12c86 Anthony Liguori
499 4c44bdcb aurel32
static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state)
500 0f0b7264 bellard
{
501 9510a486 Jan Kiszka
    int buttons = 0;
502 9510a486 Jan Kiszka
503 9510a486 Jan Kiszka
    if (state & SDL_BUTTON(SDL_BUTTON_LEFT)) {
504 0f0b7264 bellard
        buttons |= MOUSE_EVENT_LBUTTON;
505 9510a486 Jan Kiszka
    }
506 9510a486 Jan Kiszka
    if (state & SDL_BUTTON(SDL_BUTTON_RIGHT)) {
507 0f0b7264 bellard
        buttons |= MOUSE_EVENT_RBUTTON;
508 9510a486 Jan Kiszka
    }
509 9510a486 Jan Kiszka
    if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) {
510 0f0b7264 bellard
        buttons |= MOUSE_EVENT_MBUTTON;
511 9510a486 Jan Kiszka
    }
512 09b26c5e bellard
513 09b26c5e bellard
    if (kbd_mouse_is_absolute()) {
514 9510a486 Jan Kiszka
        dx = x * 0x7FFF / (real_screen->w - 1);
515 9510a486 Jan Kiszka
        dy = y * 0x7FFF / (real_screen->h - 1);
516 d34cab9f ths
    } else if (guest_cursor) {
517 4c44bdcb aurel32
        x -= guest_x;
518 4c44bdcb aurel32
        y -= guest_y;
519 4c44bdcb aurel32
        guest_x += x;
520 4c44bdcb aurel32
        guest_y += y;
521 4c44bdcb aurel32
        dx = x;
522 4c44bdcb aurel32
        dy = y;
523 09b26c5e bellard
    }
524 09b26c5e bellard
525 0f0b7264 bellard
    kbd_mouse_event(dx, dy, dz, buttons);
526 0f0b7264 bellard
}
527 0f0b7264 bellard
528 f9977897 Jan Kiszka
static void sdl_scale(DisplayState *ds, int width, int height)
529 f9977897 Jan Kiszka
{
530 f9977897 Jan Kiszka
    int bpp = real_screen->format->BitsPerPixel;
531 f9977897 Jan Kiszka
532 f9977897 Jan Kiszka
    if (bpp != 16 && bpp != 32) {
533 f9977897 Jan Kiszka
        bpp = 32;
534 f9977897 Jan Kiszka
    }
535 f9977897 Jan Kiszka
    do_sdl_resize(width, height, bpp);
536 f9977897 Jan Kiszka
    scaling_active = 1;
537 f9977897 Jan Kiszka
    if (!is_buffer_shared(ds->surface)) {
538 f9977897 Jan Kiszka
        ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds),
539 f9977897 Jan Kiszka
                                                 ds_get_height(ds));
540 f9977897 Jan Kiszka
        dpy_resize(ds);
541 f9977897 Jan Kiszka
    }
542 f9977897 Jan Kiszka
}
543 f9977897 Jan Kiszka
544 8e9c4afe bellard
static void toggle_full_screen(DisplayState *ds)
545 8e9c4afe bellard
{
546 8e9c4afe bellard
    gui_fullscreen = !gui_fullscreen;
547 8e9c4afe bellard
    if (gui_fullscreen) {
548 f9977897 Jan Kiszka
        gui_saved_width = real_screen->w;
549 f9977897 Jan Kiszka
        gui_saved_height = real_screen->h;
550 f9977897 Jan Kiszka
        gui_saved_scaling = scaling_active;
551 f9977897 Jan Kiszka
552 f9977897 Jan Kiszka
        do_sdl_resize(ds_get_width(ds), ds_get_height(ds),
553 f9977897 Jan Kiszka
                      ds_get_bits_per_pixel(ds));
554 c18a2c36 Stefano Stabellini
        scaling_active = 0;
555 f9977897 Jan Kiszka
556 8e9c4afe bellard
        gui_saved_grab = gui_grab;
557 8e9c4afe bellard
        sdl_grab_start();
558 8e9c4afe bellard
    } else {
559 f9977897 Jan Kiszka
        if (gui_saved_scaling) {
560 f9977897 Jan Kiszka
            sdl_scale(ds, gui_saved_width, gui_saved_height);
561 f9977897 Jan Kiszka
        } else {
562 f9977897 Jan Kiszka
            do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
563 f9977897 Jan Kiszka
        }
564 f8558100 Jan Kiszka
        if (!gui_saved_grab || !is_graphic_console()) {
565 8e9c4afe bellard
            sdl_grab_end();
566 f8558100 Jan Kiszka
        }
567 8e9c4afe bellard
    }
568 95219897 pbrook
    vga_hw_invalidate();
569 95219897 pbrook
    vga_hw_update();
570 8e9c4afe bellard
}
571 8e9c4afe bellard
572 35b0f237 Jan Kiszka
static void absolute_mouse_grab(void)
573 35b0f237 Jan Kiszka
{
574 35b0f237 Jan Kiszka
    int mouse_x, mouse_y;
575 35b0f237 Jan Kiszka
576 35b0f237 Jan Kiszka
    if (SDL_GetAppState() & SDL_APPINPUTFOCUS) {
577 35b0f237 Jan Kiszka
        SDL_GetMouseState(&mouse_x, &mouse_y);
578 35b0f237 Jan Kiszka
        if (mouse_x > 0 && mouse_x < real_screen->w - 1 &&
579 35b0f237 Jan Kiszka
            mouse_y > 0 && mouse_y < real_screen->h - 1) {
580 35b0f237 Jan Kiszka
            sdl_grab_start();
581 35b0f237 Jan Kiszka
        }
582 35b0f237 Jan Kiszka
    }
583 35b0f237 Jan Kiszka
}
584 35b0f237 Jan Kiszka
585 1ae1caf1 Jan Kiszka
static void handle_keydown(DisplayState *ds, SDL_Event *ev)
586 0f0b7264 bellard
{
587 8e9c4afe bellard
    int mod_state;
588 1ae1caf1 Jan Kiszka
    int keycode;
589 1ae1caf1 Jan Kiszka
590 1ae1caf1 Jan Kiszka
    if (alt_grab) {
591 1ae1caf1 Jan Kiszka
        mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) ==
592 1ae1caf1 Jan Kiszka
                    (gui_grab_code | KMOD_LSHIFT);
593 1ae1caf1 Jan Kiszka
    } else if (ctrl_grab) {
594 1ae1caf1 Jan Kiszka
        mod_state = (SDL_GetModState() & KMOD_RCTRL) == KMOD_RCTRL;
595 1ae1caf1 Jan Kiszka
    } else {
596 1ae1caf1 Jan Kiszka
        mod_state = (SDL_GetModState() & gui_grab_code) == gui_grab_code;
597 1ae1caf1 Jan Kiszka
    }
598 1ae1caf1 Jan Kiszka
    gui_key_modifier_pressed = mod_state;
599 1ae1caf1 Jan Kiszka
600 1ae1caf1 Jan Kiszka
    if (gui_key_modifier_pressed) {
601 1ae1caf1 Jan Kiszka
        keycode = sdl_keyevent_to_keycode(&ev->key);
602 1ae1caf1 Jan Kiszka
        switch (keycode) {
603 1ae1caf1 Jan Kiszka
        case 0x21: /* 'f' key on US keyboard */
604 1ae1caf1 Jan Kiszka
            toggle_full_screen(ds);
605 1ae1caf1 Jan Kiszka
            gui_keysym = 1;
606 1ae1caf1 Jan Kiszka
            break;
607 1ae1caf1 Jan Kiszka
        case 0x16: /* 'u' key on US keyboard */
608 1ae1caf1 Jan Kiszka
            if (scaling_active) {
609 1ae1caf1 Jan Kiszka
                scaling_active = 0;
610 1ae1caf1 Jan Kiszka
                sdl_resize(ds);
611 1ae1caf1 Jan Kiszka
                vga_hw_invalidate();
612 1ae1caf1 Jan Kiszka
                vga_hw_update();
613 1ae1caf1 Jan Kiszka
            }
614 1ae1caf1 Jan Kiszka
            gui_keysym = 1;
615 1ae1caf1 Jan Kiszka
            break;
616 1ae1caf1 Jan Kiszka
        case 0x02 ... 0x0a: /* '1' to '9' keys */
617 1ae1caf1 Jan Kiszka
            /* Reset the modifiers sent to the current console */
618 1ae1caf1 Jan Kiszka
            reset_keys();
619 1ae1caf1 Jan Kiszka
            console_select(keycode - 0x02);
620 1ae1caf1 Jan Kiszka
            gui_keysym = 1;
621 1ae1caf1 Jan Kiszka
            if (gui_fullscreen) {
622 1ae1caf1 Jan Kiszka
                break;
623 1ae1caf1 Jan Kiszka
            }
624 1ae1caf1 Jan Kiszka
            if (!is_graphic_console()) {
625 1ae1caf1 Jan Kiszka
                /* release grab if going to a text console */
626 1ae1caf1 Jan Kiszka
                if (gui_grab) {
627 1ae1caf1 Jan Kiszka
                    sdl_grab_end();
628 1ae1caf1 Jan Kiszka
                } else if (absolute_enabled) {
629 1ae1caf1 Jan Kiszka
                    sdl_show_cursor();
630 1ae1caf1 Jan Kiszka
                }
631 1ae1caf1 Jan Kiszka
            } else if (absolute_enabled) {
632 1ae1caf1 Jan Kiszka
                sdl_hide_cursor();
633 1ae1caf1 Jan Kiszka
                absolute_mouse_grab();
634 1ae1caf1 Jan Kiszka
            }
635 1ae1caf1 Jan Kiszka
            break;
636 1ae1caf1 Jan Kiszka
        case 0x1b: /* '+' */
637 1ae1caf1 Jan Kiszka
        case 0x35: /* '-' */
638 1ae1caf1 Jan Kiszka
            if (!gui_fullscreen) {
639 1ae1caf1 Jan Kiszka
                int width = MAX(real_screen->w + (keycode == 0x1b ? 50 : -50),
640 1ae1caf1 Jan Kiszka
                                160);
641 1ae1caf1 Jan Kiszka
                int height = (ds_get_height(ds) * width) / ds_get_width(ds);
642 1ae1caf1 Jan Kiszka
643 1ae1caf1 Jan Kiszka
                sdl_scale(ds, width, height);
644 1ae1caf1 Jan Kiszka
                vga_hw_invalidate();
645 1ae1caf1 Jan Kiszka
                vga_hw_update();
646 1ae1caf1 Jan Kiszka
                gui_keysym = 1;
647 1ae1caf1 Jan Kiszka
            }
648 1ae1caf1 Jan Kiszka
        default:
649 1ae1caf1 Jan Kiszka
            break;
650 1ae1caf1 Jan Kiszka
        }
651 1ae1caf1 Jan Kiszka
    } else if (!is_graphic_console()) {
652 1ae1caf1 Jan Kiszka
        int keysym = 0;
653 1ae1caf1 Jan Kiszka
654 1ae1caf1 Jan Kiszka
        if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) {
655 1ae1caf1 Jan Kiszka
            switch (ev->key.keysym.sym) {
656 1ae1caf1 Jan Kiszka
            case SDLK_UP:
657 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_CTRL_UP;
658 1ae1caf1 Jan Kiszka
                break;
659 1ae1caf1 Jan Kiszka
            case SDLK_DOWN:
660 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_CTRL_DOWN;
661 1ae1caf1 Jan Kiszka
                break;
662 1ae1caf1 Jan Kiszka
            case SDLK_LEFT:
663 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_CTRL_LEFT;
664 1ae1caf1 Jan Kiszka
                break;
665 1ae1caf1 Jan Kiszka
            case SDLK_RIGHT:
666 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_CTRL_RIGHT;
667 1ae1caf1 Jan Kiszka
                break;
668 1ae1caf1 Jan Kiszka
            case SDLK_HOME:
669 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_CTRL_HOME;
670 1ae1caf1 Jan Kiszka
                break;
671 1ae1caf1 Jan Kiszka
            case SDLK_END:
672 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_CTRL_END;
673 1ae1caf1 Jan Kiszka
                break;
674 1ae1caf1 Jan Kiszka
            case SDLK_PAGEUP:
675 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_CTRL_PAGEUP;
676 1ae1caf1 Jan Kiszka
                break;
677 1ae1caf1 Jan Kiszka
            case SDLK_PAGEDOWN:
678 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_CTRL_PAGEDOWN;
679 1ae1caf1 Jan Kiszka
                break;
680 1ae1caf1 Jan Kiszka
            default:
681 1ae1caf1 Jan Kiszka
                break;
682 1ae1caf1 Jan Kiszka
            }
683 1ae1caf1 Jan Kiszka
        } else {
684 1ae1caf1 Jan Kiszka
            switch (ev->key.keysym.sym) {
685 1ae1caf1 Jan Kiszka
            case SDLK_UP:
686 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_UP;
687 1ae1caf1 Jan Kiszka
                break;
688 1ae1caf1 Jan Kiszka
            case SDLK_DOWN:
689 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_DOWN;
690 1ae1caf1 Jan Kiszka
                break;
691 1ae1caf1 Jan Kiszka
            case SDLK_LEFT:
692 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_LEFT;
693 1ae1caf1 Jan Kiszka
                break;
694 1ae1caf1 Jan Kiszka
            case SDLK_RIGHT:
695 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_RIGHT;
696 1ae1caf1 Jan Kiszka
                break;
697 1ae1caf1 Jan Kiszka
            case SDLK_HOME:
698 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_HOME;
699 1ae1caf1 Jan Kiszka
                break;
700 1ae1caf1 Jan Kiszka
            case SDLK_END:
701 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_END;
702 1ae1caf1 Jan Kiszka
                break;
703 1ae1caf1 Jan Kiszka
            case SDLK_PAGEUP:
704 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_PAGEUP;
705 1ae1caf1 Jan Kiszka
                break;
706 1ae1caf1 Jan Kiszka
            case SDLK_PAGEDOWN:
707 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_PAGEDOWN;
708 1ae1caf1 Jan Kiszka
                break;
709 1ae1caf1 Jan Kiszka
            case SDLK_BACKSPACE:
710 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_BACKSPACE;
711 1ae1caf1 Jan Kiszka
                break;
712 1ae1caf1 Jan Kiszka
            case SDLK_DELETE:
713 1ae1caf1 Jan Kiszka
                keysym = QEMU_KEY_DELETE;
714 1ae1caf1 Jan Kiszka
                break;
715 1ae1caf1 Jan Kiszka
            default:
716 1ae1caf1 Jan Kiszka
                break;
717 1ae1caf1 Jan Kiszka
            }
718 1ae1caf1 Jan Kiszka
        }
719 1ae1caf1 Jan Kiszka
        if (keysym) {
720 1ae1caf1 Jan Kiszka
            kbd_put_keysym(keysym);
721 1ae1caf1 Jan Kiszka
        } else if (ev->key.keysym.unicode != 0) {
722 1ae1caf1 Jan Kiszka
            kbd_put_keysym(ev->key.keysym.unicode);
723 1ae1caf1 Jan Kiszka
        }
724 1ae1caf1 Jan Kiszka
    }
725 1ae1caf1 Jan Kiszka
    if (is_graphic_console() && !gui_keysym) {
726 1ae1caf1 Jan Kiszka
        sdl_process_key(&ev->key);
727 1ae1caf1 Jan Kiszka
    }
728 1ae1caf1 Jan Kiszka
}
729 1ae1caf1 Jan Kiszka
730 1ae1caf1 Jan Kiszka
static void handle_keyup(DisplayState *ds, SDL_Event *ev)
731 1ae1caf1 Jan Kiszka
{
732 1ae1caf1 Jan Kiszka
    int mod_state;
733 1ae1caf1 Jan Kiszka
734 1ae1caf1 Jan Kiszka
    if (!alt_grab) {
735 1ae1caf1 Jan Kiszka
        mod_state = (ev->key.keysym.mod & gui_grab_code);
736 1ae1caf1 Jan Kiszka
    } else {
737 1ae1caf1 Jan Kiszka
        mod_state = (ev->key.keysym.mod & (gui_grab_code | KMOD_LSHIFT));
738 1ae1caf1 Jan Kiszka
    }
739 1ae1caf1 Jan Kiszka
    if (!mod_state && gui_key_modifier_pressed) {
740 1ae1caf1 Jan Kiszka
        gui_key_modifier_pressed = 0;
741 1ae1caf1 Jan Kiszka
        if (gui_keysym == 0) {
742 1ae1caf1 Jan Kiszka
            /* exit/enter grab if pressing Ctrl-Alt */
743 1ae1caf1 Jan Kiszka
            if (!gui_grab) {
744 1ae1caf1 Jan Kiszka
                /* If the application is not active, do not try to enter grab
745 1ae1caf1 Jan Kiszka
                 * state. It prevents 'SDL_WM_GrabInput(SDL_GRAB_ON)' from
746 1ae1caf1 Jan Kiszka
                 * blocking all the application (SDL bug). */
747 1ae1caf1 Jan Kiszka
                if (is_graphic_console() &&
748 1ae1caf1 Jan Kiszka
                    SDL_GetAppState() & SDL_APPACTIVE) {
749 1ae1caf1 Jan Kiszka
                    sdl_grab_start();
750 1ae1caf1 Jan Kiszka
                }
751 1ae1caf1 Jan Kiszka
            } else if (!gui_fullscreen) {
752 1ae1caf1 Jan Kiszka
                sdl_grab_end();
753 1ae1caf1 Jan Kiszka
            }
754 1ae1caf1 Jan Kiszka
            /* SDL does not send back all the modifiers key, so we must
755 1ae1caf1 Jan Kiszka
             * correct it. */
756 1ae1caf1 Jan Kiszka
            reset_keys();
757 1ae1caf1 Jan Kiszka
            return;
758 1ae1caf1 Jan Kiszka
        }
759 1ae1caf1 Jan Kiszka
        gui_keysym = 0;
760 1ae1caf1 Jan Kiszka
    }
761 1ae1caf1 Jan Kiszka
    if (is_graphic_console() && !gui_keysym) {
762 1ae1caf1 Jan Kiszka
        sdl_process_key(&ev->key);
763 1ae1caf1 Jan Kiszka
    }
764 1ae1caf1 Jan Kiszka
}
765 1ae1caf1 Jan Kiszka
766 1ae1caf1 Jan Kiszka
static void handle_mousemotion(DisplayState *ds, SDL_Event *ev)
767 1ae1caf1 Jan Kiszka
{
768 1ae1caf1 Jan Kiszka
    int max_x, max_y;
769 1ae1caf1 Jan Kiszka
770 1ae1caf1 Jan Kiszka
    if (is_graphic_console() &&
771 1ae1caf1 Jan Kiszka
        (kbd_mouse_is_absolute() || absolute_enabled)) {
772 1ae1caf1 Jan Kiszka
        max_x = real_screen->w - 1;
773 1ae1caf1 Jan Kiszka
        max_y = real_screen->h - 1;
774 1ae1caf1 Jan Kiszka
        if (gui_grab && (ev->motion.x == 0 || ev->motion.y == 0 ||
775 1ae1caf1 Jan Kiszka
            ev->motion.x == max_x || ev->motion.y == max_y)) {
776 1ae1caf1 Jan Kiszka
            sdl_grab_end();
777 1ae1caf1 Jan Kiszka
        }
778 1ae1caf1 Jan Kiszka
        if (!gui_grab && SDL_GetAppState() & SDL_APPINPUTFOCUS &&
779 1ae1caf1 Jan Kiszka
            (ev->motion.x > 0 && ev->motion.x < max_x &&
780 1ae1caf1 Jan Kiszka
            ev->motion.y > 0 && ev->motion.y < max_y)) {
781 1ae1caf1 Jan Kiszka
            sdl_grab_start();
782 1ae1caf1 Jan Kiszka
        }
783 1ae1caf1 Jan Kiszka
    }
784 1ae1caf1 Jan Kiszka
    if (gui_grab || kbd_mouse_is_absolute() || absolute_enabled) {
785 1ae1caf1 Jan Kiszka
        sdl_send_mouse_event(ev->motion.xrel, ev->motion.yrel, 0,
786 1ae1caf1 Jan Kiszka
                             ev->motion.x, ev->motion.y, ev->motion.state);
787 1ae1caf1 Jan Kiszka
    }
788 1ae1caf1 Jan Kiszka
}
789 1ae1caf1 Jan Kiszka
790 1ae1caf1 Jan Kiszka
static void handle_mousebutton(DisplayState *ds, SDL_Event *ev)
791 1ae1caf1 Jan Kiszka
{
792 4c44bdcb aurel32
    int buttonstate = SDL_GetMouseState(NULL, NULL);
793 1ae1caf1 Jan Kiszka
    SDL_MouseButtonEvent *bev;
794 1ae1caf1 Jan Kiszka
    int dz;
795 1ae1caf1 Jan Kiszka
796 1ae1caf1 Jan Kiszka
    if (!is_graphic_console()) {
797 1ae1caf1 Jan Kiszka
        return;
798 1ae1caf1 Jan Kiszka
    }
799 1ae1caf1 Jan Kiszka
800 1ae1caf1 Jan Kiszka
    bev = &ev->button;
801 1ae1caf1 Jan Kiszka
    if (!gui_grab && !kbd_mouse_is_absolute()) {
802 1ae1caf1 Jan Kiszka
        if (ev->type == SDL_MOUSEBUTTONDOWN &&
803 1ae1caf1 Jan Kiszka
            (bev->button == SDL_BUTTON_LEFT)) {
804 1ae1caf1 Jan Kiszka
            /* start grabbing all events */
805 1ae1caf1 Jan Kiszka
            sdl_grab_start();
806 1ae1caf1 Jan Kiszka
        }
807 1ae1caf1 Jan Kiszka
    } else {
808 1ae1caf1 Jan Kiszka
        dz = 0;
809 1ae1caf1 Jan Kiszka
        if (ev->type == SDL_MOUSEBUTTONDOWN) {
810 1ae1caf1 Jan Kiszka
            buttonstate |= SDL_BUTTON(bev->button);
811 1ae1caf1 Jan Kiszka
        } else {
812 1ae1caf1 Jan Kiszka
            buttonstate &= ~SDL_BUTTON(bev->button);
813 1ae1caf1 Jan Kiszka
        }
814 1ae1caf1 Jan Kiszka
#ifdef SDL_BUTTON_WHEELUP
815 1ae1caf1 Jan Kiszka
        if (bev->button == SDL_BUTTON_WHEELUP &&
816 1ae1caf1 Jan Kiszka
            ev->type == SDL_MOUSEBUTTONDOWN) {
817 1ae1caf1 Jan Kiszka
            dz = -1;
818 1ae1caf1 Jan Kiszka
        } else if (bev->button == SDL_BUTTON_WHEELDOWN &&
819 1ae1caf1 Jan Kiszka
                   ev->type == SDL_MOUSEBUTTONDOWN) {
820 1ae1caf1 Jan Kiszka
            dz = 1;
821 1ae1caf1 Jan Kiszka
        }
822 1ae1caf1 Jan Kiszka
#endif
823 1ae1caf1 Jan Kiszka
        sdl_send_mouse_event(0, 0, dz, bev->x, bev->y, buttonstate);
824 1ae1caf1 Jan Kiszka
    }
825 1ae1caf1 Jan Kiszka
}
826 1ae1caf1 Jan Kiszka
827 1ae1caf1 Jan Kiszka
static void handle_activation(DisplayState *ds, SDL_Event *ev)
828 1ae1caf1 Jan Kiszka
{
829 1ae1caf1 Jan Kiszka
    if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS &&
830 1ae1caf1 Jan Kiszka
        !ev->active.gain && !gui_fullscreen) {
831 1ae1caf1 Jan Kiszka
        sdl_grab_end();
832 1ae1caf1 Jan Kiszka
    }
833 1ae1caf1 Jan Kiszka
    if (!gui_grab && ev->active.gain && is_graphic_console() &&
834 1ae1caf1 Jan Kiszka
        (kbd_mouse_is_absolute() || absolute_enabled)) {
835 1ae1caf1 Jan Kiszka
        absolute_mouse_grab();
836 1ae1caf1 Jan Kiszka
    }
837 1ae1caf1 Jan Kiszka
    if (ev->active.state & SDL_APPACTIVE) {
838 1ae1caf1 Jan Kiszka
        if (ev->active.gain) {
839 1ae1caf1 Jan Kiszka
            /* Back to default interval */
840 1ae1caf1 Jan Kiszka
            dcl->gui_timer_interval = 0;
841 1ae1caf1 Jan Kiszka
            dcl->idle = 0;
842 1ae1caf1 Jan Kiszka
        } else {
843 1ae1caf1 Jan Kiszka
            /* Sleeping interval */
844 1ae1caf1 Jan Kiszka
            dcl->gui_timer_interval = 500;
845 1ae1caf1 Jan Kiszka
            dcl->idle = 1;
846 1ae1caf1 Jan Kiszka
        }
847 1ae1caf1 Jan Kiszka
    }
848 1ae1caf1 Jan Kiszka
}
849 1ae1caf1 Jan Kiszka
850 1ae1caf1 Jan Kiszka
static void sdl_refresh(DisplayState *ds)
851 1ae1caf1 Jan Kiszka
{
852 1ae1caf1 Jan Kiszka
    SDL_Event ev1, *ev = &ev1;
853 3b46e624 ths
854 8a7ddc38 bellard
    if (last_vm_running != vm_running) {
855 8a7ddc38 bellard
        last_vm_running = vm_running;
856 8a7ddc38 bellard
        sdl_update_caption();
857 8a7ddc38 bellard
    }
858 8a7ddc38 bellard
859 95219897 pbrook
    vga_hw_update();
860 3bee8bd0 aurel32
    SDL_EnableUNICODE(!is_graphic_console());
861 457831f4 bellard
862 0f0b7264 bellard
    while (SDL_PollEvent(ev)) {
863 0f0b7264 bellard
        switch (ev->type) {
864 0f0b7264 bellard
        case SDL_VIDEOEXPOSE:
865 7d957bd8 aliguori
            sdl_update(ds, 0, 0, real_screen->w, real_screen->h);
866 0f0b7264 bellard
            break;
867 0f0b7264 bellard
        case SDL_KEYDOWN:
868 1ae1caf1 Jan Kiszka
            handle_keydown(ds, ev);
869 1ae1caf1 Jan Kiszka
            break;
870 0f0b7264 bellard
        case SDL_KEYUP:
871 1ae1caf1 Jan Kiszka
            handle_keyup(ds, ev);
872 0f0b7264 bellard
            break;
873 0f0b7264 bellard
        case SDL_QUIT:
874 941f511a Jan Kiszka
            if (!no_quit) {
875 941f511a Jan Kiszka
                no_shutdown = 0;
876 731345e1 balrog
                qemu_system_shutdown_request();
877 941f511a Jan Kiszka
            }
878 0f0b7264 bellard
            break;
879 0f0b7264 bellard
        case SDL_MOUSEMOTION:
880 1ae1caf1 Jan Kiszka
            handle_mousemotion(ds, ev);
881 0f0b7264 bellard
            break;
882 0f0b7264 bellard
        case SDL_MOUSEBUTTONDOWN:
883 0f0b7264 bellard
        case SDL_MOUSEBUTTONUP:
884 1ae1caf1 Jan Kiszka
            handle_mousebutton(ds, ev);
885 0f0b7264 bellard
            break;
886 0294ffb9 bellard
        case SDL_ACTIVEEVENT:
887 1ae1caf1 Jan Kiszka
            handle_activation(ds, ev);
888 0294ffb9 bellard
            break;
889 f9977897 Jan Kiszka
        case SDL_VIDEORESIZE:
890 f9977897 Jan Kiszka
            sdl_scale(ds, ev->resize.w, ev->resize.h);
891 c18a2c36 Stefano Stabellini
            vga_hw_invalidate();
892 c18a2c36 Stefano Stabellini
            vga_hw_update();
893 c18a2c36 Stefano Stabellini
            break;
894 0f0b7264 bellard
        default:
895 0f0b7264 bellard
            break;
896 0f0b7264 bellard
        }
897 0f0b7264 bellard
    }
898 0f0b7264 bellard
}
899 0f0b7264 bellard
900 d34cab9f ths
static void sdl_fill(DisplayState *ds, int x, int y, int w, int h, uint32_t c)
901 d34cab9f ths
{
902 d34cab9f ths
    SDL_Rect dst = { x, y, w, h };
903 7d957bd8 aliguori
    SDL_FillRect(real_screen, &dst, c);
904 d34cab9f ths
}
905 d34cab9f ths
906 d34cab9f ths
static void sdl_mouse_warp(int x, int y, int on)
907 d34cab9f ths
{
908 d34cab9f ths
    if (on) {
909 d34cab9f ths
        if (!guest_cursor)
910 d34cab9f ths
            sdl_show_cursor();
911 d34cab9f ths
        if (gui_grab || kbd_mouse_is_absolute() || absolute_enabled) {
912 d34cab9f ths
            SDL_SetCursor(guest_sprite);
913 08a2d4c4 balrog
            if (!kbd_mouse_is_absolute() && !absolute_enabled)
914 08a2d4c4 balrog
                SDL_WarpMouse(x, y);
915 d34cab9f ths
        }
916 d34cab9f ths
    } else if (gui_grab)
917 d34cab9f ths
        sdl_hide_cursor();
918 d34cab9f ths
    guest_cursor = on;
919 d34cab9f ths
    guest_x = x, guest_y = y;
920 d34cab9f ths
}
921 d34cab9f ths
922 fbe6d7a4 Gerd Hoffmann
static void sdl_mouse_define(QEMUCursor *c)
923 d34cab9f ths
{
924 fbe6d7a4 Gerd Hoffmann
    uint8_t *image, *mask;
925 fbe6d7a4 Gerd Hoffmann
    int bpl;
926 fbe6d7a4 Gerd Hoffmann
927 d34cab9f ths
    if (guest_sprite)
928 d34cab9f ths
        SDL_FreeCursor(guest_sprite);
929 d34cab9f ths
930 fbe6d7a4 Gerd Hoffmann
    bpl = cursor_get_mono_bpl(c);
931 7267c094 Anthony Liguori
    image = g_malloc0(bpl * c->height);
932 7267c094 Anthony Liguori
    mask  = g_malloc0(bpl * c->height);
933 fbe6d7a4 Gerd Hoffmann
    cursor_get_mono_image(c, 0x000000, image);
934 fbe6d7a4 Gerd Hoffmann
    cursor_get_mono_mask(c, 0, mask);
935 fbe6d7a4 Gerd Hoffmann
    guest_sprite = SDL_CreateCursor(image, mask, c->width, c->height,
936 fbe6d7a4 Gerd Hoffmann
                                    c->hot_x, c->hot_y);
937 7267c094 Anthony Liguori
    g_free(image);
938 7267c094 Anthony Liguori
    g_free(mask);
939 d34cab9f ths
940 d34cab9f ths
    if (guest_cursor &&
941 d34cab9f ths
            (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
942 d34cab9f ths
        SDL_SetCursor(guest_sprite);
943 d34cab9f ths
}
944 d34cab9f ths
945 28695489 Anthony Liguori
static void sdl_cleanup(void)
946 898712a8 bellard
{
947 d34cab9f ths
    if (guest_sprite)
948 d34cab9f ths
        SDL_FreeCursor(guest_sprite);
949 d8ee7665 malc
    SDL_QuitSubSystem(SDL_INIT_VIDEO);
950 898712a8 bellard
}
951 898712a8 bellard
952 43523e93 ths
void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
953 0f0b7264 bellard
{
954 0f0b7264 bellard
    int flags;
955 09b26c5e bellard
    uint8_t data = 0;
956 7b5d76da aliguori
    DisplayAllocator *da;
957 7b5d76da aliguori
    const SDL_VideoInfo *vi;
958 09cec717 Stefan Weil
    char *filename;
959 0f0b7264 bellard
960 3d11d0eb bellard
#if defined(__APPLE__)
961 3d11d0eb bellard
    /* always use generic keymaps */
962 3d11d0eb bellard
    if (!keyboard_layout)
963 3d11d0eb bellard
        keyboard_layout = "en-us";
964 3d11d0eb bellard
#endif
965 3d11d0eb bellard
    if(keyboard_layout) {
966 0483755a aliguori
        kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout);
967 3d11d0eb bellard
        if (!kbd_layout)
968 3d11d0eb bellard
            exit(1);
969 3d11d0eb bellard
    }
970 3d11d0eb bellard
971 43523e93 ths
    if (no_frame)
972 43523e93 ths
        gui_noframe = 1;
973 43523e93 ths
974 111f8ec9 Jan Kiszka
    if (!full_screen) {
975 111f8ec9 Jan Kiszka
        setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
976 111f8ec9 Jan Kiszka
    }
977 1de9756b Michael Tokarev
#ifdef __linux__
978 1de9756b Michael Tokarev
    /* on Linux, SDL may use fbcon|directfb|svgalib when run without
979 1de9756b Michael Tokarev
     * accessible $DISPLAY to open X11 window.  This is often the case
980 1de9756b Michael Tokarev
     * when qemu is run using sudo.  But in this case, and when actually
981 1de9756b Michael Tokarev
     * run in X11 environment, SDL fights with X11 for the video card,
982 1de9756b Michael Tokarev
     * making current display unavailable, often until reboot.
983 1de9756b Michael Tokarev
     * So make x11 the default SDL video driver if this variable is unset.
984 1de9756b Michael Tokarev
     * This is a bit hackish but saves us from bigger problem.
985 1de9756b Michael Tokarev
     * Maybe it's a good idea to fix this in SDL instead.
986 1de9756b Michael Tokarev
     */
987 1de9756b Michael Tokarev
    setenv("SDL_VIDEODRIVER", "x11", 0);
988 1de9756b Michael Tokarev
#endif
989 111f8ec9 Jan Kiszka
990 4e79bcbb Stefan Weil
    /* Enable normal up/down events for Caps-Lock and Num-Lock keys.
991 4e79bcbb Stefan Weil
     * This requires SDL >= 1.2.14. */
992 4e79bcbb Stefan Weil
    setenv("SDL_DISABLE_LOCK_KEYS", "1", 1);
993 4e79bcbb Stefan Weil
994 0f0b7264 bellard
    flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE;
995 0f0b7264 bellard
    if (SDL_Init (flags)) {
996 3caf2562 malc
        fprintf(stderr, "Could not initialize SDL(%s) - exiting\n",
997 3caf2562 malc
                SDL_GetError());
998 0f0b7264 bellard
        exit(1);
999 0f0b7264 bellard
    }
1000 7b5d76da aliguori
    vi = SDL_GetVideoInfo();
1001 c18a2c36 Stefano Stabellini
    host_format = *(vi->vfmt);
1002 0ae04d73 bellard
1003 09cec717 Stefan Weil
    /* Load a 32x32x4 image. White pixels are transparent. */
1004 09cec717 Stefan Weil
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "qemu-icon.bmp");
1005 09cec717 Stefan Weil
    if (filename) {
1006 09cec717 Stefan Weil
        SDL_Surface *image = SDL_LoadBMP(filename);
1007 09cec717 Stefan Weil
        if (image) {
1008 09cec717 Stefan Weil
            uint32_t colorkey = SDL_MapRGB(image->format, 255, 255, 255);
1009 09cec717 Stefan Weil
            SDL_SetColorKey(image, SDL_SRCCOLORKEY, colorkey);
1010 09cec717 Stefan Weil
            SDL_WM_SetIcon(image, NULL);
1011 09cec717 Stefan Weil
        }
1012 7267c094 Anthony Liguori
        g_free(filename);
1013 09cec717 Stefan Weil
    }
1014 09cec717 Stefan Weil
1015 110defd7 Jan Kiszka
    if (full_screen) {
1016 110defd7 Jan Kiszka
        gui_fullscreen = 1;
1017 110defd7 Jan Kiszka
        sdl_grab_start();
1018 110defd7 Jan Kiszka
    }
1019 110defd7 Jan Kiszka
1020 7267c094 Anthony Liguori
    dcl = g_malloc0(sizeof(DisplayChangeListener));
1021 7d957bd8 aliguori
    dcl->dpy_update = sdl_update;
1022 7d957bd8 aliguori
    dcl->dpy_resize = sdl_resize;
1023 7d957bd8 aliguori
    dcl->dpy_refresh = sdl_refresh;
1024 7d957bd8 aliguori
    dcl->dpy_setdata = sdl_setdata;
1025 7d957bd8 aliguori
    dcl->dpy_fill = sdl_fill;
1026 d34cab9f ths
    ds->mouse_set = sdl_mouse_warp;
1027 d34cab9f ths
    ds->cursor_define = sdl_mouse_define;
1028 7d957bd8 aliguori
    register_displaychangelistener(ds, dcl);
1029 0f0b7264 bellard
1030 7267c094 Anthony Liguori
    da = g_malloc0(sizeof(DisplayAllocator));
1031 7b5d76da aliguori
    da->create_displaysurface = sdl_create_displaysurface;
1032 7b5d76da aliguori
    da->resize_displaysurface = sdl_resize_displaysurface;
1033 7b5d76da aliguori
    da->free_displaysurface = sdl_free_displaysurface;
1034 7b5d76da aliguori
    if (register_displayallocator(ds, da) == da) {
1035 7b5d76da aliguori
        dpy_resize(ds);
1036 7b5d76da aliguori
    }
1037 7b5d76da aliguori
1038 3af12c86 Anthony Liguori
    mouse_mode_notifier.notify = sdl_mouse_mode_change;
1039 3af12c86 Anthony Liguori
    qemu_add_mouse_mode_change_notifier(&mouse_mode_notifier);
1040 3af12c86 Anthony Liguori
1041 8a7ddc38 bellard
    sdl_update_caption();
1042 0f0b7264 bellard
    SDL_EnableKeyRepeat(250, 50);
1043 0f0b7264 bellard
    gui_grab = 0;
1044 898712a8 bellard
1045 09b26c5e bellard
    sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0);
1046 09b26c5e bellard
    sdl_cursor_normal = SDL_GetCursor();
1047 09b26c5e bellard
1048 28695489 Anthony Liguori
    atexit(sdl_cleanup);
1049 0f0b7264 bellard
}