Statistics
| Branch: | Revision:

root / sdl.c @ 511d2b14

History | View | Annotate | Download (21.7 kB)

1
/*
2
 * QEMU SDL display driver
3
 *
4
 * Copyright (c) 2003 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include <SDL.h>
25
#include <SDL/SDL_syswm.h>
26

    
27
#ifndef _WIN32
28
#include <signal.h>
29
#endif
30

    
31
#include "qemu-common.h"
32
#include "console.h"
33
#include "sysemu.h"
34
#include "x_keymap.h"
35

    
36
static DisplayChangeListener *dcl;
37
static SDL_Surface *real_screen;
38
static SDL_Surface *guest_screen = NULL;
39
static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
40
static int last_vm_running;
41
static int gui_saved_grab;
42
static int gui_fullscreen;
43
static int gui_noframe;
44
static int gui_key_modifier_pressed;
45
static int gui_keysym;
46
static int gui_fullscreen_initial_grab;
47
static int gui_grab_code = KMOD_LALT | KMOD_LCTRL;
48
static uint8_t modifiers_state[256];
49
static int width, height;
50
static SDL_Cursor *sdl_cursor_normal;
51
static SDL_Cursor *sdl_cursor_hidden;
52
static int absolute_enabled = 0;
53
static int guest_cursor = 0;
54
static int guest_x, guest_y;
55
static SDL_Cursor *guest_sprite = 0;
56

    
57
static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
58
{
59
    SDL_Rect rec;
60
    rec.x = x;
61
    rec.y = y;
62
    rec.w = w;
63
    rec.h = h;
64
    //    printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
65

    
66
    SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
67
    SDL_UpdateRect(real_screen, x, y, w, h);
68
}
69

    
70
static void sdl_setdata(DisplayState *ds)
71
{
72
    SDL_Rect rec;
73
    rec.x = 0;
74
    rec.y = 0;
75
    rec.w = real_screen->w;
76
    rec.h = real_screen->h;
77

    
78
    if (guest_screen != NULL) SDL_FreeSurface(guest_screen);
79

    
80
    guest_screen = SDL_CreateRGBSurfaceFrom(ds_get_data(ds), ds_get_width(ds), ds_get_height(ds),
81
                                            ds_get_bits_per_pixel(ds), ds_get_linesize(ds),
82
                                            ds->surface->pf.rmask, ds->surface->pf.gmask,
83
                                            ds->surface->pf.bmask, ds->surface->pf.amask);
84
}
85

    
86
static void sdl_resize(DisplayState *ds)
87
{
88
    int flags;
89

    
90
    //    printf("resizing to %d %d\n", w, h);
91

    
92
    flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
93
    if (gui_fullscreen)
94
        flags |= SDL_FULLSCREEN;
95
    if (gui_noframe)
96
        flags |= SDL_NOFRAME;
97

    
98
    width = ds_get_width(ds);
99
    height = ds_get_height(ds);
100
    real_screen = SDL_SetVideoMode(width, height, 0, flags);
101
    if (!real_screen) {
102
        fprintf(stderr, "Could not open SDL display\n");
103
        exit(1);
104
    }
105

    
106
    sdl_setdata(ds);
107
}
108

    
109
/* generic keyboard conversion */
110

    
111
#include "sdl_keysym.h"
112

    
113
static kbd_layout_t *kbd_layout = NULL;
114

    
115
static uint8_t sdl_keyevent_to_keycode_generic(const SDL_KeyboardEvent *ev)
116
{
117
    int keysym;
118
    /* workaround for X11+SDL bug with AltGR */
119
    keysym = ev->keysym.sym;
120
    if (keysym == 0 && ev->keysym.scancode == 113)
121
        keysym = SDLK_MODE;
122
    /* For Japanese key '\' and '|' */
123
    if (keysym == 92 && ev->keysym.scancode == 133) {
124
        keysym = 0xa5;
125
    }
126
    return keysym2scancode(kbd_layout, keysym);
127
}
128

    
129
/* specific keyboard conversions from scan codes */
130

    
131
#if defined(_WIN32)
132

    
133
static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
134
{
135
    return ev->keysym.scancode;
136
}
137

    
138
#else
139

    
140
#if defined(SDL_VIDEO_DRIVER_X11)
141
#include <X11/XKBlib.h>
142

    
143
static int check_for_evdev(void)
144
{
145
    SDL_SysWMinfo info;
146
    XkbDescPtr desc;
147
    int has_evdev = 0;
148
    const char *keycodes;
149

    
150
    SDL_VERSION(&info.version);
151
    if (!SDL_GetWMInfo(&info))
152
        return 0;
153

    
154
    desc = XkbGetKeyboard(info.info.x11.display,
155
                          XkbGBN_AllComponentsMask,
156
                          XkbUseCoreKbd);
157
    if (desc == NULL || desc->names == NULL)
158
        return 0;
159

    
160
    keycodes = XGetAtomName(info.info.x11.display, desc->names->keycodes);
161
    if (keycodes == NULL)
162
        fprintf(stderr, "could not lookup keycode name\n");
163
    else if (strstart(keycodes, "evdev_", NULL))
164
        has_evdev = 1;
165
    else if (!strstart(keycodes, "xfree86_", NULL))
166
        fprintf(stderr,
167
                "unknown keycodes `%s', please report to qemu-devel@nongnu.org\n",
168
                keycodes);
169

    
170
    XkbFreeClientMap(desc, XkbGBN_AllComponentsMask, True);
171

    
172
    return has_evdev;
173
}
174
#else
175
static int check_for_evdev(void)
176
{
177
        return 0;
178
}
179
#endif
180

    
181
static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
182
{
183
    int keycode;
184
    static int has_evdev = -1;
185

    
186
    if (has_evdev == -1)
187
        has_evdev = check_for_evdev();
188

    
189
    keycode = ev->keysym.scancode;
190

    
191
    if (keycode < 9) {
192
        keycode = 0;
193
    } else if (keycode < 97) {
194
        keycode -= 8; /* just an offset */
195
    } else if (keycode < 158) {
196
        /* use conversion table */
197
        if (has_evdev)
198
            keycode = translate_evdev_keycode(keycode - 97);
199
        else
200
            keycode = translate_xfree86_keycode(keycode - 97);
201
    } else if (keycode == 208) { /* Hiragana_Katakana */
202
        keycode = 0x70;
203
    } else if (keycode == 211) { /* backslash */
204
        keycode = 0x73;
205
    } else {
206
        keycode = 0;
207
    }
208
    return keycode;
209
}
210

    
211
#endif
212

    
213
static void reset_keys(void)
214
{
215
    int i;
216
    for(i = 0; i < 256; i++) {
217
        if (modifiers_state[i]) {
218
            if (i & 0x80)
219
                kbd_put_keycode(0xe0);
220
            kbd_put_keycode(i | 0x80);
221
            modifiers_state[i] = 0;
222
        }
223
    }
224
}
225

    
226
static void sdl_process_key(SDL_KeyboardEvent *ev)
227
{
228
    int keycode, v;
229

    
230
    if (ev->keysym.sym == SDLK_PAUSE) {
231
        /* specific case */
232
        v = 0;
233
        if (ev->type == SDL_KEYUP)
234
            v |= 0x80;
235
        kbd_put_keycode(0xe1);
236
        kbd_put_keycode(0x1d | v);
237
        kbd_put_keycode(0x45 | v);
238
        return;
239
    }
240

    
241
    if (kbd_layout) {
242
        keycode = sdl_keyevent_to_keycode_generic(ev);
243
    } else {
244
        keycode = sdl_keyevent_to_keycode(ev);
245
    }
246

    
247
    switch(keycode) {
248
    case 0x00:
249
        /* sent when leaving window: reset the modifiers state */
250
        reset_keys();
251
        return;
252
    case 0x2a:                          /* Left Shift */
253
    case 0x36:                          /* Right Shift */
254
    case 0x1d:                          /* Left CTRL */
255
    case 0x9d:                          /* Right CTRL */
256
    case 0x38:                          /* Left ALT */
257
    case 0xb8:                         /* Right ALT */
258
        if (ev->type == SDL_KEYUP)
259
            modifiers_state[keycode] = 0;
260
        else
261
            modifiers_state[keycode] = 1;
262
        break;
263
    case 0x45: /* num lock */
264
    case 0x3a: /* caps lock */
265
        /* SDL does not send the key up event, so we generate it */
266
        kbd_put_keycode(keycode);
267
        kbd_put_keycode(keycode | 0x80);
268
        return;
269
    }
270

    
271
    /* now send the key code */
272
    if (keycode & 0x80)
273
        kbd_put_keycode(0xe0);
274
    if (ev->type == SDL_KEYUP)
275
        kbd_put_keycode(keycode | 0x80);
276
    else
277
        kbd_put_keycode(keycode & 0x7f);
278
}
279

    
280
static void sdl_update_caption(void)
281
{
282
    char buf[1024];
283
    const char *status = "";
284

    
285
    if (!vm_running)
286
        status = " [Stopped]";
287
    else if (gui_grab) {
288
        if (!alt_grab)
289
            status = " - Press Ctrl-Alt to exit grab";
290
        else
291
            status = " - Press Ctrl-Alt-Shift to exit grab";
292
    }
293

    
294
    if (qemu_name)
295
        snprintf(buf, sizeof(buf), "QEMU (%s)%s", qemu_name, status);
296
    else
297
        snprintf(buf, sizeof(buf), "QEMU%s", status);
298

    
299
    SDL_WM_SetCaption(buf, "QEMU");
300
}
301

    
302
static void sdl_hide_cursor(void)
303
{
304
    if (!cursor_hide)
305
        return;
306

    
307
    if (kbd_mouse_is_absolute()) {
308
        SDL_ShowCursor(1);
309
        SDL_SetCursor(sdl_cursor_hidden);
310
    } else {
311
        SDL_ShowCursor(0);
312
    }
313
}
314

    
315
static void sdl_show_cursor(void)
316
{
317
    if (!cursor_hide)
318
        return;
319

    
320
    if (!kbd_mouse_is_absolute()) {
321
        SDL_ShowCursor(1);
322
        if (guest_cursor &&
323
                (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
324
            SDL_SetCursor(guest_sprite);
325
        else
326
            SDL_SetCursor(sdl_cursor_normal);
327
    }
328
}
329

    
330
static void sdl_grab_start(void)
331
{
332
    if (guest_cursor) {
333
        SDL_SetCursor(guest_sprite);
334
        if (!kbd_mouse_is_absolute() && !absolute_enabled)
335
            SDL_WarpMouse(guest_x, guest_y);
336
    } else
337
        sdl_hide_cursor();
338

    
339
    if (SDL_WM_GrabInput(SDL_GRAB_ON) == SDL_GRAB_ON) {
340
        gui_grab = 1;
341
        sdl_update_caption();
342
    } else
343
        sdl_show_cursor();
344
}
345

    
346
static void sdl_grab_end(void)
347
{
348
    SDL_WM_GrabInput(SDL_GRAB_OFF);
349
    gui_grab = 0;
350
    sdl_show_cursor();
351
    sdl_update_caption();
352
}
353

    
354
static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state)
355
{
356
    int buttons;
357
    buttons = 0;
358
    if (state & SDL_BUTTON(SDL_BUTTON_LEFT))
359
        buttons |= MOUSE_EVENT_LBUTTON;
360
    if (state & SDL_BUTTON(SDL_BUTTON_RIGHT))
361
        buttons |= MOUSE_EVENT_RBUTTON;
362
    if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE))
363
        buttons |= MOUSE_EVENT_MBUTTON;
364

    
365
    if (kbd_mouse_is_absolute()) {
366
        if (!absolute_enabled) {
367
            sdl_hide_cursor();
368
            if (gui_grab) {
369
                sdl_grab_end();
370
            }
371
            absolute_enabled = 1;
372
        }
373

    
374
       dx = x * 0x7FFF / (width - 1);
375
       dy = y * 0x7FFF / (height - 1);
376
    } else if (absolute_enabled) {
377
        sdl_show_cursor();
378
        absolute_enabled = 0;
379
    } else if (guest_cursor) {
380
        x -= guest_x;
381
        y -= guest_y;
382
        guest_x += x;
383
        guest_y += y;
384
        dx = x;
385
        dy = y;
386
    }
387

    
388
    kbd_mouse_event(dx, dy, dz, buttons);
389
}
390

    
391
static void toggle_full_screen(DisplayState *ds)
392
{
393
    gui_fullscreen = !gui_fullscreen;
394
    sdl_resize(ds);
395
    if (gui_fullscreen) {
396
        gui_saved_grab = gui_grab;
397
        sdl_grab_start();
398
    } else {
399
        if (!gui_saved_grab)
400
            sdl_grab_end();
401
    }
402
    vga_hw_invalidate();
403
    vga_hw_update();
404
}
405

    
406
static void sdl_refresh(DisplayState *ds)
407
{
408
    SDL_Event ev1, *ev = &ev1;
409
    int mod_state;
410
    int buttonstate = SDL_GetMouseState(NULL, NULL);
411

    
412
    if (last_vm_running != vm_running) {
413
        last_vm_running = vm_running;
414
        sdl_update_caption();
415
    }
416

    
417
    vga_hw_update();
418
    SDL_EnableUNICODE(!is_graphic_console());
419

    
420
    while (SDL_PollEvent(ev)) {
421
        switch (ev->type) {
422
        case SDL_VIDEOEXPOSE:
423
            sdl_update(ds, 0, 0, real_screen->w, real_screen->h);
424
            break;
425
        case SDL_KEYDOWN:
426
        case SDL_KEYUP:
427
            if (ev->type == SDL_KEYDOWN) {
428
                if (!alt_grab) {
429
                    mod_state = (SDL_GetModState() & gui_grab_code) ==
430
                                gui_grab_code;
431
                } else {
432
                    mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) ==
433
                                (gui_grab_code | KMOD_LSHIFT);
434
                }
435
                gui_key_modifier_pressed = mod_state;
436
                if (gui_key_modifier_pressed) {
437
                    int keycode;
438
                    keycode = sdl_keyevent_to_keycode(&ev->key);
439
                    switch(keycode) {
440
                    case 0x21: /* 'f' key on US keyboard */
441
                        toggle_full_screen(ds);
442
                        gui_keysym = 1;
443
                        break;
444
                    case 0x02 ... 0x0a: /* '1' to '9' keys */
445
                        /* Reset the modifiers sent to the current console */
446
                        reset_keys();
447
                        console_select(keycode - 0x02);
448
                        if (!is_graphic_console()) {
449
                            /* display grab if going to a text console */
450
                            if (gui_grab)
451
                                sdl_grab_end();
452
                        }
453
                        gui_keysym = 1;
454
                        break;
455
                    default:
456
                        break;
457
                    }
458
                } else if (!is_graphic_console()) {
459
                    int keysym;
460
                    keysym = 0;
461
                    if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) {
462
                        switch(ev->key.keysym.sym) {
463
                        case SDLK_UP: keysym = QEMU_KEY_CTRL_UP; break;
464
                        case SDLK_DOWN: keysym = QEMU_KEY_CTRL_DOWN; break;
465
                        case SDLK_LEFT: keysym = QEMU_KEY_CTRL_LEFT; break;
466
                        case SDLK_RIGHT: keysym = QEMU_KEY_CTRL_RIGHT; break;
467
                        case SDLK_HOME: keysym = QEMU_KEY_CTRL_HOME; break;
468
                        case SDLK_END: keysym = QEMU_KEY_CTRL_END; break;
469
                        case SDLK_PAGEUP: keysym = QEMU_KEY_CTRL_PAGEUP; break;
470
                        case SDLK_PAGEDOWN: keysym = QEMU_KEY_CTRL_PAGEDOWN; break;
471
                        default: break;
472
                        }
473
                    } else {
474
                        switch(ev->key.keysym.sym) {
475
                        case SDLK_UP: keysym = QEMU_KEY_UP; break;
476
                        case SDLK_DOWN: keysym = QEMU_KEY_DOWN; break;
477
                        case SDLK_LEFT: keysym = QEMU_KEY_LEFT; break;
478
                        case SDLK_RIGHT: keysym = QEMU_KEY_RIGHT; break;
479
                        case SDLK_HOME: keysym = QEMU_KEY_HOME; break;
480
                        case SDLK_END: keysym = QEMU_KEY_END; break;
481
                        case SDLK_PAGEUP: keysym = QEMU_KEY_PAGEUP; break;
482
                        case SDLK_PAGEDOWN: keysym = QEMU_KEY_PAGEDOWN; break;
483
                        case SDLK_BACKSPACE: keysym = QEMU_KEY_BACKSPACE; break;
484
                        case SDLK_DELETE: keysym = QEMU_KEY_DELETE; break;
485
                        default: break;
486
                        }
487
                    }
488
                    if (keysym) {
489
                        kbd_put_keysym(keysym);
490
                    } else if (ev->key.keysym.unicode != 0) {
491
                        kbd_put_keysym(ev->key.keysym.unicode);
492
                    }
493
                }
494
            } else if (ev->type == SDL_KEYUP) {
495
                if (!alt_grab) {
496
                    mod_state = (ev->key.keysym.mod & gui_grab_code);
497
                } else {
498
                    mod_state = (ev->key.keysym.mod &
499
                                 (gui_grab_code | KMOD_LSHIFT));
500
                }
501
                if (!mod_state) {
502
                    if (gui_key_modifier_pressed) {
503
                        gui_key_modifier_pressed = 0;
504
                        if (gui_keysym == 0) {
505
                            /* exit/enter grab if pressing Ctrl-Alt */
506
                            if (!gui_grab) {
507
                                /* if the application is not active,
508
                                   do not try to enter grab state. It
509
                                   prevents
510
                                   'SDL_WM_GrabInput(SDL_GRAB_ON)'
511
                                   from blocking all the application
512
                                   (SDL bug). */
513
                                if (SDL_GetAppState() & SDL_APPACTIVE)
514
                                    sdl_grab_start();
515
                            } else {
516
                                sdl_grab_end();
517
                            }
518
                            /* SDL does not send back all the
519
                               modifiers key, so we must correct it */
520
                            reset_keys();
521
                            break;
522
                        }
523
                        gui_keysym = 0;
524
                    }
525
                }
526
            }
527
            if (is_graphic_console() && !gui_keysym)
528
                sdl_process_key(&ev->key);
529
            break;
530
        case SDL_QUIT:
531
            if (!no_quit)
532
                qemu_system_shutdown_request();
533
            break;
534
        case SDL_MOUSEMOTION:
535
            if (gui_grab || kbd_mouse_is_absolute() ||
536
                absolute_enabled) {
537
                sdl_send_mouse_event(ev->motion.xrel, ev->motion.yrel, 0,
538
                       ev->motion.x, ev->motion.y, ev->motion.state);
539
            }
540
            break;
541
        case SDL_MOUSEBUTTONDOWN:
542
        case SDL_MOUSEBUTTONUP:
543
            {
544
                SDL_MouseButtonEvent *bev = &ev->button;
545
                if (!gui_grab && !kbd_mouse_is_absolute()) {
546
                    if (ev->type == SDL_MOUSEBUTTONDOWN &&
547
                        (bev->button == SDL_BUTTON_LEFT)) {
548
                        /* start grabbing all events */
549
                        sdl_grab_start();
550
                    }
551
                } else {
552
                    int dz;
553
                    dz = 0;
554
                    if (ev->type == SDL_MOUSEBUTTONDOWN) {
555
                        buttonstate |= SDL_BUTTON(bev->button);
556
                    } else {
557
                        buttonstate &= ~SDL_BUTTON(bev->button);
558
                    }
559
#ifdef SDL_BUTTON_WHEELUP
560
                    if (bev->button == SDL_BUTTON_WHEELUP && ev->type == SDL_MOUSEBUTTONDOWN) {
561
                        dz = -1;
562
                    } else if (bev->button == SDL_BUTTON_WHEELDOWN && ev->type == SDL_MOUSEBUTTONDOWN) {
563
                        dz = 1;
564
                    }
565
#endif
566
                    sdl_send_mouse_event(0, 0, dz, bev->x, bev->y, buttonstate);
567
                }
568
            }
569
            break;
570
        case SDL_ACTIVEEVENT:
571
            if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS &&
572
                !ev->active.gain && !gui_fullscreen_initial_grab) {
573
                sdl_grab_end();
574
            }
575
            if (ev->active.state & SDL_APPACTIVE) {
576
                if (ev->active.gain) {
577
                    /* Back to default interval */
578
                    dcl->gui_timer_interval = 0;
579
                    dcl->idle = 0;
580
                } else {
581
                    /* Sleeping interval */
582
                    dcl->gui_timer_interval = 500;
583
                    dcl->idle = 1;
584
                }
585
            }
586
            break;
587
        default:
588
            break;
589
        }
590
    }
591
}
592

    
593
static void sdl_fill(DisplayState *ds, int x, int y, int w, int h, uint32_t c)
594
{
595
    SDL_Rect dst = { x, y, w, h };
596
    SDL_FillRect(real_screen, &dst, c);
597
}
598

    
599
static void sdl_mouse_warp(int x, int y, int on)
600
{
601
    if (on) {
602
        if (!guest_cursor)
603
            sdl_show_cursor();
604
        if (gui_grab || kbd_mouse_is_absolute() || absolute_enabled) {
605
            SDL_SetCursor(guest_sprite);
606
            if (!kbd_mouse_is_absolute() && !absolute_enabled)
607
                SDL_WarpMouse(x, y);
608
        }
609
    } else if (gui_grab)
610
        sdl_hide_cursor();
611
    guest_cursor = on;
612
    guest_x = x, guest_y = y;
613
}
614

    
615
static void sdl_mouse_define(int width, int height, int bpp,
616
                             int hot_x, int hot_y,
617
                             uint8_t *image, uint8_t *mask)
618
{
619
    uint8_t sprite[256], *line;
620
    int x, y, dst, bypl, src = 0;
621
    if (guest_sprite)
622
        SDL_FreeCursor(guest_sprite);
623

    
624
    memset(sprite, 0, 256);
625
    bypl = ((width * bpp + 31) >> 5) << 2;
626
    for (y = 0, dst = 0; y < height; y ++, image += bypl) {
627
        line = image;
628
        for (x = 0; x < width; x ++, dst ++) {
629
            switch (bpp) {
630
            case 24:
631
                src = *(line ++); src |= *(line ++); src |= *(line ++);
632
                break;
633
            case 16:
634
            case 15:
635
                src = *(line ++); src |= *(line ++);
636
                break;
637
            case 8:
638
                src = *(line ++);
639
                break;
640
            case 4:
641
                src = 0xf & (line[x >> 1] >> ((x & 1)) << 2);
642
                break;
643
            case 2:
644
                src = 3 & (line[x >> 2] >> ((x & 3)) << 1);
645
                break;
646
            case 1:
647
                src = 1 & (line[x >> 3] >> (x & 7));
648
                break;
649
            }
650
            if (!src)
651
                sprite[dst >> 3] |= (1 << (~dst & 7)) & mask[dst >> 3];
652
        }
653
    }
654
    guest_sprite = SDL_CreateCursor(sprite, mask, width, height, hot_x, hot_y);
655

    
656
    if (guest_cursor &&
657
            (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
658
        SDL_SetCursor(guest_sprite);
659
}
660

    
661
static void sdl_cleanup(void)
662
{
663
    if (guest_sprite)
664
        SDL_FreeCursor(guest_sprite);
665
    SDL_Quit();
666
}
667

    
668
void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
669
{
670
    int flags;
671
    uint8_t data = 0;
672

    
673
#if defined(__APPLE__)
674
    /* always use generic keymaps */
675
    if (!keyboard_layout)
676
        keyboard_layout = "en-us";
677
#endif
678
    if(keyboard_layout) {
679
        kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout);
680
        if (!kbd_layout)
681
            exit(1);
682
    }
683

    
684
    if (no_frame)
685
        gui_noframe = 1;
686

    
687
    flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE;
688
    if (SDL_Init (flags)) {
689
        fprintf(stderr, "Could not initialize SDL - exiting\n");
690
        exit(1);
691
    }
692

    
693
    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
694
    dcl->dpy_update = sdl_update;
695
    dcl->dpy_resize = sdl_resize;
696
    dcl->dpy_refresh = sdl_refresh;
697
    dcl->dpy_setdata = sdl_setdata;
698
    dcl->dpy_fill = sdl_fill;
699
    ds->mouse_set = sdl_mouse_warp;
700
    ds->cursor_define = sdl_mouse_define;
701
    register_displaychangelistener(ds, dcl);
702

    
703
    sdl_update_caption();
704
    SDL_EnableKeyRepeat(250, 50);
705
    gui_grab = 0;
706

    
707
    sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0);
708
    sdl_cursor_normal = SDL_GetCursor();
709

    
710
    atexit(sdl_cleanup);
711
    if (full_screen) {
712
        gui_fullscreen = 1;
713
        gui_fullscreen_initial_grab = 1;
714
        sdl_grab_start();
715
    }
716
}