2 * QEMU GTK2 display driver
3 * based on SDL driver by Fabrice
5 * Copyright (c) 2005 Jim Brown
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30 #include "fullscreen.h"
32 /* define our own bitshift enums to allow qemugtk to know difference between left and right alt - something gtk doesnt provide in its modifiers mask. this uses qemu's own modifier_state[] map in order to guess correctly */
35 gtkshiftleft = 1 << 0,
36 gtkshiftright = 1 << 1,
37 gtkcontrolleft = 1 << 2,
38 gtkcontrolright = 1 << 3,
45 static GtkWidget *window, *swindow;
46 static GtkWidget *event_port, *menubar;
47 static GdkImage *image=NULL;
48 static GdkCursor *invisible_cursor;
49 static int ox = 0, oy = 0;
50 static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
51 static int gui_rgrab; /* if true, all keyboard/mouse events are grabbed */
52 static int last_vm_running;
53 static int gui_saved_grab;
54 static int gui_fullscreen;
55 static int gui_key_modifier_pressed;
56 static int gui_keysym;
57 static int gui_fullscreen_initial_grab;
58 static int gui_grab_code = gtkaltleft | gtkcontrolleft;
59 static uint8_t modifiers_state[256];
60 static int window_resize = 0;
61 static unsigned int cw, ch;
62 static gint win_x, win_y, win_w, win_h;
63 static GtkWidget * box; /* because GtkWindow/GtkBin holds only one widget */
65 static gboolean gtk2_expose(GtkWidget *wid, GdkEventExpose *event)
67 if (gui_fullscreen && wid == event_port) return FALSE;
68 if (!gui_fullscreen && wid == window) return FALSE;
69 gdk_draw_image(wid->window, wid->style->fg_gc[GTK_WIDGET_STATE(wid)], image, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height);
73 static void gtk2_update(DisplayState *ds, int x, int y, int w, int h)
75 // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
81 /* catch the first resize done by the init function - make sure we don't **
82 ** try to draw an image until screen has been finalized/realized/etc */
83 if (event_port->window != NULL)
86 gtk2_expose(window, &ev);
88 gtk2_expose(event_port, &ev);
92 static void gtk2_resize(DisplayState *ds, int w, int h)
95 // printf(" resizing to %d %d\n", w, h);
99 if (cw != w || ch != h)
101 fullscreen_switch(win_x, win_y, w, h); /* changing video modes */
102 /* apparently GTK enjoys moving static windows all over the place while
103 they are being resized - so we have to be tricky */
104 //gtk_window_move(GTK_WINDOW(window), win_x, win_y);
105 //gtk_window_move(GTK_WINDOW(window), 0, 0);
106 gdk_window_move_resize(window->window, 0, 0, w, h);
113 g_object_unref(image);
115 /* gdk_visual_get_best_with_depth() ??? but then how to paint onto window? */
116 image = gdk_image_new(GDK_IMAGE_NORMAL, gdk_visual_get_system(), w, h);
117 gdk_image_set_colormap(image, gdk_colormap_get_system());
119 gtk_widget_set_size_request(event_port, w, h);
121 gdk_window_move_resize(window->window, win_x, win_y, w+25, h+50);
123 ds->data = image->mem;
124 ds->linesize = image->bpl;
125 ds->depth = image->bits_per_pixel;
128 gtk2_update(ds, 0, 0, w, h);
131 static gboolean gtk2_config(GtkWidget *wid, GdkEventConfigure *ev, DisplayState *ds)
143 /* generic keyboard conversion */
145 #include "gdk_keysym.h"
148 static kbd_layout_t *kbd_layout = NULL;
150 static uint8_t gtk2_keyevent_to_keycode_generic(const GdkEventKey *ev)
153 /* workaround for X11+SDL bug with AltGR - is it still needed for Gtk2? */
155 if (keysym == 0 && ev->hardware_keycode == 113)
156 keysym = GDK_Mode_switch;
157 return keysym2scancode(kbd_layout, keysym);
160 /* specific keyboard conversions from scan codes */
166 static UINT vk2scan(UINT vk)
168 return MapVirtualKey(vk,0);
170 static uint8_t gtk2_keyevent_to_keycode(const GdkEventKey *ev)
172 return (uint8_t)vk2scan((UINT)(ev->hardware_keycode));
177 static const uint8_t x_keycode_to_pc_keycode[61] = {
183 0xcd, /* 102 Right */
189 0x9c, /* 108 Enter */
190 0x9d, /* 109 Ctrl-R */
192 0xb7, /* 111 Print */
193 0xb5, /* 112 Divide */
194 0xb8, /* 113 Alt-R */
195 0xc6, /* 114 Break */
196 0xdb, /* 115 windows left button */
197 0xdc, /* 116 windows right button */
198 0xdd, /* 117 right menu button */
201 0x70, /* 120 Hiragana_Katakana */
204 0x73, /* 123 backslash */
210 0x79, /* 129 Henkan */
212 0x7b, /* 131 Muhenkan */
228 0x47, /* 147 KP_HOME */
229 0x48, /* 148 KP_UP */
230 0x49, /* 149 KP_PgUp */
231 0x4b, /* 150 KP_Left */
233 0x4d, /* 152 KP_Right */
234 0x4f, /* 153 KP_End */
235 0x50, /* 154 KP_Down */
236 0x51, /* 155 KP_PgDn */
237 0x52, /* 156 KP_Ins */
238 0x53, /* 157 KP_Del */
241 static uint8_t gtk2_keyevent_to_keycode(const GdkEventKey *ev)
245 keycode = ev->hardware_keycode;
249 } else if (keycode < 97) {
250 keycode -= 8; /* just an offset */
251 } else if (keycode < 158) {
252 /* use conversion table */
253 keycode = x_keycode_to_pc_keycode[keycode - 97];
262 static void reset_keys(void)
265 for(i = 0; i < 256; i++) {
266 if (modifiers_state[i]) {
268 kbd_put_keycode(0xe0);
269 kbd_put_keycode(i | 0x80);
270 modifiers_state[i] = 0;
275 /* convert GDK modifiers and invoke ugly hack to distinguish
276 between left and right shift/control/alt */
277 static guint gtk2_GetModState(const GdkEventKey *ev)
279 guint key = 0, keyval = ev->keyval, state = ev->state;
283 if (ev->type != GDK_KEY_RELEASE)
288 if (ev->type != GDK_KEY_RELEASE)
289 key |= gtkshiftright;
293 if (ev->type != GDK_KEY_RELEASE)
294 key |= gtkcontrolleft;
298 if (ev->type != GDK_KEY_RELEASE)
299 key |= gtkcontrolright;
303 if (ev->type != GDK_KEY_RELEASE)
308 if (ev->type != GDK_KEY_RELEASE)
313 if (ev->type != GDK_KEY_RELEASE)
321 if (keyval != 1 && (state & GDK_SHIFT_MASK))
323 if (modifiers_state[0x2a])
325 if (modifiers_state[0x36])
326 key |= gtkshiftright;
328 if (keyval != 2 && (state & GDK_CONTROL_MASK))
330 if (modifiers_state[0x1d])
331 key |= gtkcontrolleft;
332 if (modifiers_state[0x9d])
333 key |= gtkcontrolright;
335 if (keyval != 3 && (state & GDK_MOD1_MASK)) /* fixme: need to do a check to make sure that alt is mapped to GDK_MOD1_MASK in the GDK_Keymap */
337 if (modifiers_state[0x38])
339 if (modifiers_state[0xb8])
342 if (keyval != 4 && (state & GDK_LOCK_MASK))
347 static void gtk2_process_key(GdkEventKey *ev)
351 if (ev->keyval == GDK_Pause) {
354 if (ev->type == GDK_KEY_RELEASE)
356 kbd_put_keycode(0xe1);
357 kbd_put_keycode(0x1d | v);
358 kbd_put_keycode(0x45 | v);
363 keycode = gtk2_keyevent_to_keycode_generic(ev);
365 keycode = gtk2_keyevent_to_keycode(ev);
370 /* sent when leaving window: reset the modifiers state */
373 case 0x2a: /* Left Shift */
374 case 0x36: /* Right Shift */
375 case 0x1d: /* Left CTRL */
376 case 0x9d: /* Right CTRL */
377 case 0x38: /* Left ALT */
378 case 0xb8: /* Right ALT */
379 if (ev->type == GDK_KEY_RELEASE)
380 modifiers_state[keycode] = 0;
382 modifiers_state[keycode] = 1;
384 case 0x45: /* num lock */
385 case 0x3a: /* caps lock */
386 /* GTK does send the key up event, so we dont generate it */
387 /*kbd_put_keycode(keycode);
388 kbd_put_keycode(keycode | 0x80);
393 /* now send the key code */
395 kbd_put_keycode(0xe0);
396 if (ev->type == GDK_KEY_RELEASE)
397 kbd_put_keycode(keycode | 0x80);
399 kbd_put_keycode(keycode & 0x7f);
402 static void gtk2_update_caption(void)
405 strcpy(buf, "QEMU Gtk");
407 strcat(buf, " [Stopped]");
410 strcat(buf, " - Press Ctrl-Alt to exit grab");
412 gtk_window_set_title(GTK_WINDOW(window), buf);
415 /* what a nasty hack. this should be a part of the GDK, not external!!! */
416 #include "gdk_set_window_pointer.c"
418 static void gtk2_grab_start(void)
422 GdkModifierType state; /* dummy var */
424 if (gui_fullscreen) /* make sure grab is on correct x window */
428 if (gui_rgrab || gui_fullscreen)
430 events = GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK;
431 y = gdk_pointer_grab(grab->window, TRUE, events, grab->window, invisible_cursor, GDK_CURRENT_TIME);
433 printf("GTK Warning - pointer grab failed!\n");
434 y = gdk_keyboard_grab(grab->window, TRUE, GDK_CURRENT_TIME);
436 printf("GTK Warning - keyboard grab failed!\n");
438 /* do a dummy read to avoid moving mouse - set ox and oy to stay in sync */
439 gdk_window_get_pointer(event_port->window, &ox, &oy, &state);
441 gtk2_update_caption();
444 static void gtk2_grab_end(void)
451 if (gui_rgrab || gui_fullscreen)
453 gdk_pointer_ungrab(GDK_CURRENT_TIME);
454 gdk_keyboard_ungrab(GDK_CURRENT_TIME);
455 gdk_window_set_pointer(grab->window, win_x, win_y);
458 gtk2_update_caption();
461 static gboolean gtk2_send_mouse_event(GtkWidget *wid, GdkEvent *ev)
463 int x, y, dx, dy, dz, state, buttons;
465 if (gui_fullscreen) /* make sure grab is on correct x window */
470 if (gui_fullscreen && wid == event_port) return FALSE;
471 if (!gui_fullscreen && wid == window) return FALSE;
472 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS)
473 return TRUE; /* double or triple click - superflurious - ignore */
478 if (ev->type == GDK_MOTION_NOTIFY && ev->motion.is_hint)
480 gdk_window_get_pointer(ev->motion.window, &x, &y, (GdkModifierType*)&state);
486 /* scroll.state occupies a different position in the union */
487 if (ev->type == GDK_SCROLL)
488 state = ev->scroll.state;
490 state = ev->motion.state;
495 // prevent infinite looping - 2.6.X
496 if ((ev->type == GDK_MOTION_NOTIFY) && (dx == 0) && (dy == 0)) return TRUE;
502 if ((state & GDK_BUTTON1_MASK))
503 buttons |= MOUSE_EVENT_LBUTTON;
504 if ((state & GDK_BUTTON3_MASK))
505 buttons |= MOUSE_EVENT_RBUTTON;
506 if ((state & GDK_BUTTON2_MASK))
507 buttons |= MOUSE_EVENT_MBUTTON;
509 if (ev->type == GDK_BUTTON_PRESS)
511 if (ev->button.button == 1)
512 buttons |= MOUSE_EVENT_LBUTTON;
513 if (ev->button.button == 3)
514 buttons |= MOUSE_EVENT_RBUTTON;
515 if (ev->button.button == 2)
516 buttons |= MOUSE_EVENT_MBUTTON;
518 else if (ev->type == GDK_BUTTON_RELEASE)
520 /* not sure if this is really necessary, but just to be on the safe side **
521 ** reset qemu's mask so that a button thats being released will be shown **
522 * missing from the mask (which lets the guest know the button was relased */
525 if ((state & GDK_BUTTON1_MASK) && ev->button.button != 1)
526 buttons |= MOUSE_EVENT_LBUTTON;
527 if ((state & GDK_BUTTON3_MASK) && ev->button.button != 3)
528 buttons |= MOUSE_EVENT_RBUTTON;
529 if ((state & GDK_BUTTON2_MASK) && ev->button.button != 2)
530 buttons |= MOUSE_EVENT_MBUTTON;
532 else if (ev->type == GDK_SCROLL)
534 /* test wheel - copied from Sebastien Bechet's gtk.c */
535 if (ev->scroll.direction == GDK_SCROLL_UP)
537 if (ev->scroll.direction == GDK_SCROLL_DOWN)
541 if ((ev->type == GDK_MOTION_NOTIFY) && (gui_rgrab || gui_fullscreen))
543 /* wrap the x,y coordinates back onto the window */
544 if (ev->motion.x <= (cw/4))
546 if (ev->motion.y <= (ch/4))
548 if (ev->motion.x >= (3*cw/4))
550 if (ev->motion.y >= (3*ch/4))
553 /* make internal mouse move invisible */
557 gdk_window_set_pointer(grab->window, (gint)x, (gint)y);
560 kbd_mouse_event(dx, dy, dz, buttons);
566 if (ev->type == GDK_BUTTON_PRESS && ev->button.button == 1)
568 /* start grabbing all events */
576 static void toggle_full_screen(DisplayState *ds)
578 gui_fullscreen = !gui_fullscreen;
579 gtk2_resize(ds, image->width, image->height);
580 if (gui_fullscreen) {
581 gui_saved_grab = gui_grab;
583 gtk_window_get_position(GTK_WINDOW(window), &win_x, &win_y);
584 gdk_window_move_resize(window->window, 0, 0, ds->width, ds->height);
585 gtk_widget_hide(box);
586 fullscreen_switch(win_x, win_y, ds->width, ds->height);
589 gdk_window_move_resize(window->window, win_x, win_y, win_w, win_h);
590 gui_fullscreen = !gui_fullscreen;
593 gui_fullscreen = !gui_fullscreen;
594 gtk_widget_show(box);
596 vga_invalidate_display();
597 vga_update_display();
600 static gboolean gtk2_key_press(GtkWidget *wid, GdkEventKey *ev, DisplayState *ds)
602 int mod_state, internal_key = 0;
603 if (ev->type == GDK_KEY_PRESS) {
604 mod_state = (gtk2_GetModState(ev) & (int)gui_grab_code) == (int)gui_grab_code;
605 gui_key_modifier_pressed = mod_state;
606 if (gui_key_modifier_pressed) {
609 keycode = gtk2_keyevent_to_keycode(ev);
611 case 0x21: /* 'f' key on US keyboard */
612 toggle_full_screen(ds);
615 case 0x02 ... 0x0a: /* '1' to '9' keys */
616 console_select(keycode - 0x02);
617 if (is_active_console(vga_console)) {
618 /* tell the vga console to redisplay itself */
619 vga_invalidate_display();
621 /* display grab if going to a text console */
630 } else if (!is_active_console(vga_console)) {
633 if (ev->state & GDK_CONTROL_MASK) {
635 case GDK_Up: keysym = QEMU_KEY_CTRL_UP; break;
636 case GDK_Down: keysym = QEMU_KEY_CTRL_DOWN; break;
637 case GDK_Left: keysym = QEMU_KEY_CTRL_LEFT; break;
638 case GDK_Right: keysym = QEMU_KEY_CTRL_RIGHT; break;
639 case GDK_Home: keysym = QEMU_KEY_CTRL_HOME; break;
640 case GDK_End: keysym = QEMU_KEY_CTRL_END; break;
641 case GDK_Page_Up: keysym = QEMU_KEY_CTRL_PAGEUP; break;
642 case GDK_Page_Down: keysym = QEMU_KEY_CTRL_PAGEDOWN; break;
647 case GDK_Up: keysym = QEMU_KEY_UP; break;
648 case GDK_Down: keysym = QEMU_KEY_DOWN; break;
649 case GDK_Left: keysym = QEMU_KEY_LEFT; break;
650 case GDK_Right: keysym = QEMU_KEY_RIGHT; break;
651 case GDK_Home: keysym = QEMU_KEY_HOME; break;
652 case GDK_End: keysym = QEMU_KEY_END; break;
653 case GDK_Page_Up: keysym = QEMU_KEY_PAGEUP; break;
654 case GDK_Page_Down: keysym = QEMU_KEY_PAGEDOWN; break;
655 case GDK_BackSpace: keysym = QEMU_KEY_BACKSPACE; break;
656 case GDK_Delete: keysym = QEMU_KEY_DELETE; break;
661 kbd_put_keysym(keysym);
662 } /*else if (ev->key.keysym.unicode != 0) {
663 kbd_put_keysym(ev->key.keysym.unicode);
666 } else if (ev->type == GDK_KEY_RELEASE) {
667 mod_state = (gtk2_GetModState(ev) & gui_grab_code);
669 if (gui_key_modifier_pressed) {
670 if (gui_keysym == 0) {
671 /* exit/enter grab if pressing Ctrl-Alt */
676 /* SDL does not send back all the
677 modifiers key, so we must correct it */
681 gui_key_modifier_pressed = 0;
687 if (is_active_console(vga_console) && !internal_key)
688 gtk2_process_key(ev);
689 else if (internal_key && ev->type == GDK_KEY_RELEASE)
691 modifiers_state[0x38] = 0;
692 modifiers_state[0x1d] = 0;
693 kbd_put_keycode(0x38 | 0x80);
694 kbd_put_keycode(0x1d | 0x80);
696 else if (internal_key && ev->type == GDK_KEY_PRESS)
698 modifiers_state[0x38] = 1;
699 modifiers_state[0x1d] = 1;
704 static void gtk2_refresh(DisplayState *ds)
706 if (last_vm_running != vm_running) {
707 last_vm_running = vm_running;
708 gtk2_update_caption();
710 if (ds->data != image->mem)
712 ds->data = image->mem;
715 if (is_active_console(vga_console))
716 vga_update_display();
717 while (gtk_events_pending())
718 gtk_main_iteration();
721 static void gtk2_cleanup(void)
723 if (gtk_main_level() != 0)
725 fullscreen_cleanup();
728 static gboolean gtk2_deletewin(void)
730 /* signal qemu that its time to shut itself off - this is the place that we hook to trap attempts to close the main qemu window */
731 qemu_system_shutdown_request();
733 return TRUE; /* dont close the window right away! give qemu time to think */
736 static void gtk2_destroy(void)
738 /* ideally we would call a hook here so qemu could clean itself up */
742 GtkWidget * gui_menu_add(const gchar * name)
744 GtkWidget *menu, *menu_name;
745 menu = gtk_menu_new();
746 menu_name = gtk_menu_item_new_with_label(name);
747 gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menu_name);
748 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_name), menu);
749 gtk_widget_show(menu_name);
753 GtkWidget * gui_menuitem_add(GtkWidget * menu, const gchar * name, void (*item_handler)(void))
755 GtkWidget *menu_item;
756 menu_item = gtk_menu_item_new_with_label(name);
757 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
758 g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(item_handler), NULL);
759 gtk_widget_show(menu_item);
763 GtkWidget * gui_menusep_add(GtkWidget * menu)
765 GtkWidget *menu_item;
766 menu_item = gtk_menu_item_new();
767 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
768 gtk_widget_show(menu_item);
772 GtkWidget * gui_submenu_add(GtkWidget * menu, const gchar * name)
774 GtkWidget *submenu, *menu_name;
775 submenu = gtk_menu_new();
776 menu_name = gtk_menu_item_new_with_label(name);
777 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_name);
778 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_name), submenu);
779 gtk_widget_show(menu_name);
783 void base_vc_switch(int i)
786 if (is_active_console(vga_console)) {
787 /* tell the vga console to redisplay itself */
788 vga_invalidate_display();
790 /* display grab if going to a text console */
795 void vc_guest(void) { base_vc_switch(0); }
796 void vc_monitor(void) { base_vc_switch(1); }
797 void vc_serial(void) { base_vc_switch(2); }
798 void vc_para(void) { base_vc_switch(3); }
801 void gtk2_menu_init(void)
804 menu = gui_menu_add("Monitor");
805 gui_menuitem_add(menu, "Reset", qemu_system_reset_request);
806 gui_menuitem_add(menu, "Quit", qemu_system_shutdown_request);
807 menu = gui_menu_add("Virtual Console");
808 menu = gui_submenu_add(menu, "Switch to");
809 gui_menuitem_add(menu, "Guest", vc_guest);
810 gui_menuitem_add(menu, "Monitor", vc_monitor);
811 gui_menuitem_add(menu, "Serial", vc_serial);
812 gui_menuitem_add(menu, "Parallel", vc_para);
813 menu = gui_menu_add("Help");
814 gui_menuitem_add(menu, "About", nop);
818 static char ** gargv=NULL;
819 void gtk2_display_init(DisplayState *ds, int full_screen)
823 #if defined(__APPLE__)
824 /* always use generic keymaps */
825 if (!keyboard_layout)
826 keyboard_layout = "en-us";
828 if(keyboard_layout) {
829 kbd_layout = init_keyboard_layout(keyboard_layout);
834 /* note - this strips the GTK-specific args after the main program is done with them */
835 if (!gtk_init_check (&gargc,&gargv))
837 fprintf(stderr, "Could not load GTK\n");
843 /* note: adding GDK_DRAG_* and GDK_DROP_* would provide a mechanism for supporting drag and drop between host and guest */
844 events = GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_SCROLL_MASK | GDK_STRUCTURE_MASK;
846 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
847 swindow = gtk_scrolled_window_new(NULL,NULL);
848 event_port = gtk_event_box_new();
849 menubar = gtk_menu_bar_new();
850 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swindow), GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS);
851 box = gtk_vbox_new(FALSE, 0);
852 gtk_container_add(GTK_CONTAINER(window), box);
853 gtk_box_pack_start(GTK_BOX(box), menubar, FALSE, FALSE, 0);
854 gtk_box_pack_start(GTK_BOX(box), swindow, TRUE, TRUE, 0);
855 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(swindow), event_port);
856 gtk_widget_set_events(event_port, events);
857 gtk_window_set_default_size(GTK_WINDOW(window), 720, 420);
858 gtk_widget_set_size_request(window, 0, 0);
859 gtk_widget_set_size_request(swindow, 720, 400);
860 gtk_widget_set_size_request(event_port, 720, 400);
861 gtk_window_set_gravity(GTK_WINDOW(window), GDK_GRAVITY_STATIC);
864 g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(gtk2_deletewin), NULL);
865 g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk2_destroy), NULL);
866 gtk_container_set_border_width(GTK_CONTAINER(window), 0);
868 g_signal_connect(G_OBJECT(window), "configure_event", G_CALLBACK(gtk2_config), NULL);
869 g_signal_connect(G_OBJECT(window), "expose_event", G_CALLBACK(gtk2_expose), NULL);
870 g_signal_connect(G_OBJECT(window), "motion_notify_event", G_CALLBACK(gtk2_send_mouse_event), NULL);
871 g_signal_connect(G_OBJECT(window), "button_press_event", G_CALLBACK(gtk2_send_mouse_event), NULL);
872 g_signal_connect(G_OBJECT(window), "button_release_event", G_CALLBACK(gtk2_send_mouse_event), NULL);
873 g_signal_connect(G_OBJECT(window), "scroll_event", G_CALLBACK(gtk2_send_mouse_event), NULL);
874 g_signal_connect(G_OBJECT(event_port), "expose_event", G_CALLBACK(gtk2_expose), NULL);
875 g_signal_connect(G_OBJECT(event_port), "motion_notify_event", G_CALLBACK(gtk2_send_mouse_event), NULL);
876 g_signal_connect(G_OBJECT(event_port), "button_press_event", G_CALLBACK(gtk2_send_mouse_event), NULL);
877 g_signal_connect(G_OBJECT(event_port), "button_release_event", G_CALLBACK(gtk2_send_mouse_event), NULL);
878 g_signal_connect(G_OBJECT(event_port), "scroll_event", G_CALLBACK(gtk2_send_mouse_event), NULL);
879 g_signal_connect(G_OBJECT(window), "key_press_event", G_CALLBACK(gtk2_key_press), ds);
880 g_signal_connect(G_OBJECT(window), "key_release_event", G_CALLBACK(gtk2_key_press), ds);
882 ds->dpy_update = gtk2_update;
883 ds->dpy_resize = gtk2_resize;
884 ds->dpy_refresh = gtk2_refresh;
886 gchar nullpixdata[1] = { 0 };
887 GdkColor nullcolor = { 0, 0, 0, 0 };
888 GdkPixmap *invis = gdk_bitmap_create_from_data(window->window, nullpixdata, 1, 1);
889 invisible_cursor = gdk_cursor_new_from_pixmap(invis, invis, &nullcolor, &nullcolor, 0, 0);
891 gtk2_resize(ds, 720, 400);
892 gtk2_update_caption();
895 gtk_widget_show(event_port);
896 gtk_widget_show(swindow);
897 gtk_widget_show(menubar);
898 gtk_widget_show(box);
899 gtk_widget_show(window);
902 gui_fullscreen_initial_grab = 1;
907 /* we are allowed to look at the args, but not allowed to modify them
908 with the exception that we have to remove args that are meant for us, as
909 main qemu will not recognize them */
910 void gui_checkargs(int * pargc, char *** pargv)
913 char ** argv = *pargv;
916 vargv = malloc(argc * sizeof(char*));
917 for (i = 0; i < argc; i++)
919 if (!strcmp(argv[i], "-window-resize-on"))
924 else if (!strcmp(argv[i], "-raw-grab"))
935 /* so lets hide them */
936 for (i = 0; i < *pargc; i++)
938 (*pargv)[i] = vargv[i];
940 if (argc != (*pargc)) (*pargv)[*pargc] = NULL;
942 /* save a copy so we can pass them to gtk_init() later */