Compare commits

..

2 Commits

Author SHA1 Message Date
Cole Robinson
3f2fde2a00 sdl2: Support mouse wheel
In SDL2, wheel movement is its own event, not a button event. Wire
it up similar to gtk.c

Signed-off-by: Cole Robinson <crobinso@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-04-29 10:46:33 +02:00
Dave Airlie
8b15d9f1d2 sdl2: add ui info setting.
Allows you to resize the sdl2 window and have the guest notice.

[ kraxel: zero-initialize QemuUIInfo ]

Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2014-04-29 10:46:33 +02:00
3 changed files with 98 additions and 44 deletions

3
configure vendored
View File

@@ -1233,7 +1233,6 @@ Advanced options (experts only):
--with-sdlabi select preferred SDL ABI 1.2 or 2.0 --with-sdlabi select preferred SDL ABI 1.2 or 2.0
--disable-gtk disable gtk UI --disable-gtk disable gtk UI
--enable-gtk enable gtk UI --enable-gtk enable gtk UI
--with-gtkabi select preferred GTK ABI 2.0 or 3.0
--disable-virtfs disable VirtFS --disable-virtfs disable VirtFS
--enable-virtfs enable VirtFS --enable-virtfs enable VirtFS
--disable-vnc disable VNC --disable-vnc disable VNC
@@ -4350,7 +4349,6 @@ if test "$modules" = "yes"; then
fi fi
if test "$sdl" = "yes" ; then if test "$sdl" = "yes" ; then
echo "CONFIG_SDL=y" >> $config_host_mak echo "CONFIG_SDL=y" >> $config_host_mak
echo "CONFIG_SDLABI=$sdlabi" >> $config_host_mak
echo "SDL_CFLAGS=$sdl_cflags" >> $config_host_mak echo "SDL_CFLAGS=$sdl_cflags" >> $config_host_mak
fi fi
if test "$cocoa" = "yes" ; then if test "$cocoa" = "yes" ; then
@@ -4434,7 +4432,6 @@ fi
echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
if test "$gtk" = "yes" ; then if test "$gtk" = "yes" ; then
echo "CONFIG_GTK=y" >> $config_host_mak echo "CONFIG_GTK=y" >> $config_host_mak
echo "CONFIG_GTKABI=$gtkabi" >> $config_host_mak
echo "GTK_CFLAGS=$gtk_cflags" >> $config_host_mak echo "GTK_CFLAGS=$gtk_cflags" >> $config_host_mak
fi fi
if test "$vte" = "yes" ; then if test "$vte" = "yes" ; then

View File

@@ -93,12 +93,13 @@ static inline void gdk_drawable_get_size(GdkWindow *w, gint *ww, gint *wh)
#define GDK_KEY_2 GDK_2 #define GDK_KEY_2 GDK_2
#define GDK_KEY_f GDK_f #define GDK_KEY_f GDK_f
#define GDK_KEY_g GDK_g #define GDK_KEY_g GDK_g
#define GDK_KEY_q GDK_q
#define GDK_KEY_plus GDK_plus #define GDK_KEY_plus GDK_plus
#define GDK_KEY_minus GDK_minus #define GDK_KEY_minus GDK_minus
#endif #endif
#define HOTKEY_MODIFIERS (GDK_CONTROL_MASK | GDK_MOD1_MASK) #define HOTKEY_MODIFIERS (GDK_CONTROL_MASK | GDK_MOD1_MASK)
#define IGNORE_MODIFIER_MASK \
(GDK_MODIFIER_MASK & ~(GDK_LOCK_MASK | GDK_MOD2_MASK))
static const int modifier_keycode[] = { static const int modifier_keycode[] = {
/* shift, control, alt keys, meta keys, both left & right */ /* shift, control, alt keys, meta keys, both left & right */
@@ -113,6 +114,7 @@ typedef struct VirtualConsole
GtkWidget *scrolled_window; GtkWidget *scrolled_window;
CharDriverState *chr; CharDriverState *chr;
#endif #endif
int fd;
} VirtualConsole; } VirtualConsole;
typedef struct GtkDisplayState typedef struct GtkDisplayState
@@ -487,6 +489,24 @@ static void gd_mouse_mode_change(Notifier *notify, void *data)
/** GTK Events **/ /** GTK Events **/
static gboolean gd_window_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
{
GtkDisplayState *s = opaque;
gboolean handled = FALSE;
if (!gd_is_grab_active(s) ||
(key->state & IGNORE_MODIFIER_MASK) == HOTKEY_MODIFIERS) {
handled = gtk_window_activate_key(GTK_WINDOW(widget), key);
}
if (handled) {
gtk_release_modifiers(s);
} else {
handled = gtk_window_propagate_key_event(GTK_WINDOW(widget), key);
}
return handled;
}
static gboolean gd_window_close(GtkWidget *widget, GdkEvent *event, static gboolean gd_window_close(GtkWidget *widget, GdkEvent *event,
void *opaque) void *opaque)
{ {
@@ -1141,12 +1161,9 @@ static gboolean gd_focus_out_event(GtkWidget *widget,
static int gd_vc_chr_write(CharDriverState *chr, const uint8_t *buf, int len) static int gd_vc_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
{ {
#if defined(CONFIG_VTE)
VirtualConsole *vc = chr->opaque; VirtualConsole *vc = chr->opaque;
vte_terminal_feed(VTE_TERMINAL(vc->terminal), (const char *)buf, len); return vc ? write(vc->fd, buf, len) : len;
#endif
return len;
} }
static int nb_vcs; static int nb_vcs;
@@ -1172,12 +1189,19 @@ void early_gtk_display_init(void)
} }
#if defined(CONFIG_VTE) #if defined(CONFIG_VTE)
static gboolean gd_vc_in(VteTerminal *terminal, gchar *text, guint size, static gboolean gd_vc_in(GIOChannel *chan, GIOCondition cond, void *opaque)
gpointer user_data)
{ {
VirtualConsole *vc = user_data; VirtualConsole *vc = opaque;
uint8_t buffer[1024];
ssize_t len;
len = read(vc->fd, buffer, sizeof(buffer));
if (len <= 0) {
return FALSE;
}
qemu_chr_be_write(vc->chr, buffer, len);
qemu_chr_be_write(vc->chr, (uint8_t *)text, (unsigned int)size);
return TRUE; return TRUE;
} }
#endif #endif
@@ -1189,8 +1213,13 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
const char *label; const char *label;
char buffer[32]; char buffer[32];
char path[32]; char path[32];
#if VTE_CHECK_VERSION(0, 26, 0)
VtePty *pty;
#endif
GIOChannel *chan;
GtkWidget *scrolled_window; GtkWidget *scrolled_window;
GtkAdjustment *vadjustment; GtkAdjustment *vadjustment;
int master_fd, slave_fd;
snprintf(buffer, sizeof(buffer), "vc%d", index); snprintf(buffer, sizeof(buffer), "vc%d", index);
snprintf(path, sizeof(path), "<QEMU>/View/VC%d", index); snprintf(path, sizeof(path), "<QEMU>/View/VC%d", index);
@@ -1209,21 +1238,27 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
gtk_accel_map_add_entry(path, GDK_KEY_2 + index, HOTKEY_MODIFIERS); gtk_accel_map_add_entry(path, GDK_KEY_2 + index, HOTKEY_MODIFIERS);
vc->terminal = vte_terminal_new(); vc->terminal = vte_terminal_new();
g_signal_connect(vc->terminal, "commit", G_CALLBACK(gd_vc_in), vc);
master_fd = qemu_openpty_raw(&slave_fd, NULL);
g_assert(master_fd != -1);
#if VTE_CHECK_VERSION(0, 26, 0)
pty = vte_pty_new_foreign(master_fd, NULL);
vte_terminal_set_pty_object(VTE_TERMINAL(vc->terminal), pty);
#else
vte_terminal_set_pty(VTE_TERMINAL(vc->terminal), master_fd);
#endif
vte_terminal_set_scrollback_lines(VTE_TERMINAL(vc->terminal), -1); vte_terminal_set_scrollback_lines(VTE_TERMINAL(vc->terminal), -1);
#if VTE_CHECK_VERSION(0, 28, 0) && GTK_CHECK_VERSION(3, 0, 0)
vadjustment = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(vc->terminal));
#else
vadjustment = vte_terminal_get_adjustment(VTE_TERMINAL(vc->terminal)); vadjustment = vte_terminal_get_adjustment(VTE_TERMINAL(vc->terminal));
#endif
scrolled_window = gtk_scrolled_window_new(NULL, vadjustment); scrolled_window = gtk_scrolled_window_new(NULL, vadjustment);
gtk_container_add(GTK_CONTAINER(scrolled_window), vc->terminal); gtk_container_add(GTK_CONTAINER(scrolled_window), vc->terminal);
vte_terminal_set_size(VTE_TERMINAL(vc->terminal), 80, 25); vte_terminal_set_size(VTE_TERMINAL(vc->terminal), 80, 25);
vc->fd = slave_fd;
vc->chr->opaque = vc; vc->chr->opaque = vc;
vc->scrolled_window = scrolled_window; vc->scrolled_window = scrolled_window;
@@ -1241,6 +1276,9 @@ static GSList *gd_vc_init(GtkDisplayState *s, VirtualConsole *vc, int index, GSL
vc->chr->init(vc->chr); vc->chr->init(vc->chr);
} }
chan = g_io_channel_unix_new(vc->fd);
g_io_add_watch(chan, G_IO_IN, gd_vc_in, vc);
#endif /* CONFIG_VTE */ #endif /* CONFIG_VTE */
return group; return group;
} }
@@ -1252,6 +1290,8 @@ static void gd_connect_signals(GtkDisplayState *s)
g_signal_connect(s->show_tabs_item, "activate", g_signal_connect(s->show_tabs_item, "activate",
G_CALLBACK(gd_menu_show_tabs), s); G_CALLBACK(gd_menu_show_tabs), s);
g_signal_connect(s->window, "key-press-event",
G_CALLBACK(gd_window_key_event), s);
g_signal_connect(s->window, "delete-event", g_signal_connect(s->window, "delete-event",
G_CALLBACK(gd_window_close), s); G_CALLBACK(gd_window_close), s);
@@ -1311,6 +1351,7 @@ static GtkWidget *gd_create_menu_machine(GtkDisplayState *s, GtkAccelGroup *acce
{ {
GtkWidget *machine_menu; GtkWidget *machine_menu;
GtkWidget *separator; GtkWidget *separator;
GtkStockItem item;
machine_menu = gtk_menu_new(); machine_menu = gtk_menu_new();
gtk_menu_set_accel_group(GTK_MENU(machine_menu), accel_group); gtk_menu_set_accel_group(GTK_MENU(machine_menu), accel_group);
@@ -1321,20 +1362,20 @@ static GtkWidget *gd_create_menu_machine(GtkDisplayState *s, GtkAccelGroup *acce
separator = gtk_separator_menu_item_new(); separator = gtk_separator_menu_item_new();
gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), separator); gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), separator);
s->reset_item = gtk_menu_item_new_with_mnemonic(_("_Reset")); s->reset_item = gtk_image_menu_item_new_with_mnemonic(_("_Reset"));
gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), s->reset_item); gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), s->reset_item);
s->powerdown_item = gtk_menu_item_new_with_mnemonic(_("Power _Down")); s->powerdown_item = gtk_image_menu_item_new_with_mnemonic(_("Power _Down"));
gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), s->powerdown_item); gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), s->powerdown_item);
separator = gtk_separator_menu_item_new(); separator = gtk_separator_menu_item_new();
gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), separator); gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), separator);
s->quit_item = gtk_menu_item_new_with_mnemonic(_("_Quit")); s->quit_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
gtk_stock_lookup(GTK_STOCK_QUIT, &item);
gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->quit_item), gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->quit_item),
"<QEMU>/Machine/Quit"); "<QEMU>/Machine/Quit");
gtk_accel_map_add_entry("<QEMU>/Machine/Quit", gtk_accel_map_add_entry("<QEMU>/Machine/Quit", item.keyval, item.modifier);
GDK_KEY_q, HOTKEY_MODIFIERS);
gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), s->quit_item); gtk_menu_shell_append(GTK_MENU_SHELL(machine_menu), s->quit_item);
return machine_menu; return machine_menu;
@@ -1350,7 +1391,8 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s, GtkAccelGroup *accel_g
view_menu = gtk_menu_new(); view_menu = gtk_menu_new();
gtk_menu_set_accel_group(GTK_MENU(view_menu), accel_group); gtk_menu_set_accel_group(GTK_MENU(view_menu), accel_group);
s->full_screen_item = gtk_menu_item_new_with_mnemonic(_("_Fullscreen")); s->full_screen_item =
gtk_image_menu_item_new_from_stock(GTK_STOCK_FULLSCREEN, NULL);
gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->full_screen_item), gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->full_screen_item),
"<QEMU>/View/Full Screen"); "<QEMU>/View/Full Screen");
gtk_accel_map_add_entry("<QEMU>/View/Full Screen", GDK_KEY_f, gtk_accel_map_add_entry("<QEMU>/View/Full Screen", GDK_KEY_f,
@@ -1360,21 +1402,21 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s, GtkAccelGroup *accel_g
separator = gtk_separator_menu_item_new(); separator = gtk_separator_menu_item_new();
gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), separator); gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), separator);
s->zoom_in_item = gtk_menu_item_new_with_mnemonic(_("Zoom _In")); s->zoom_in_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ZOOM_IN, NULL);
gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->zoom_in_item), gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->zoom_in_item),
"<QEMU>/View/Zoom In"); "<QEMU>/View/Zoom In");
gtk_accel_map_add_entry("<QEMU>/View/Zoom In", GDK_KEY_plus, gtk_accel_map_add_entry("<QEMU>/View/Zoom In", GDK_KEY_plus,
HOTKEY_MODIFIERS); HOTKEY_MODIFIERS);
gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->zoom_in_item); gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->zoom_in_item);
s->zoom_out_item = gtk_menu_item_new_with_mnemonic(_("Zoom _Out")); s->zoom_out_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ZOOM_OUT, NULL);
gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->zoom_out_item), gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->zoom_out_item),
"<QEMU>/View/Zoom Out"); "<QEMU>/View/Zoom Out");
gtk_accel_map_add_entry("<QEMU>/View/Zoom Out", GDK_KEY_minus, gtk_accel_map_add_entry("<QEMU>/View/Zoom Out", GDK_KEY_minus,
HOTKEY_MODIFIERS); HOTKEY_MODIFIERS);
gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->zoom_out_item); gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->zoom_out_item);
s->zoom_fixed_item = gtk_menu_item_new_with_mnemonic(_("Best _Fit")); s->zoom_fixed_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_ZOOM_100, NULL);
gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->zoom_fixed_item), gtk_menu_item_set_accel_path(GTK_MENU_ITEM(s->zoom_fixed_item),
"<QEMU>/View/Zoom Fixed"); "<QEMU>/View/Zoom Fixed");
gtk_accel_map_add_entry("<QEMU>/View/Zoom Fixed", GDK_KEY_0, gtk_accel_map_add_entry("<QEMU>/View/Zoom Fixed", GDK_KEY_0,

View File

@@ -359,16 +359,12 @@ static void sdl_mouse_mode_change(Notifier *notify, void *data)
} }
static void sdl_send_mouse_event(struct sdl2_state *scon, int dx, int dy, static void sdl_send_mouse_event(struct sdl2_state *scon, int dx, int dy,
int dz, int x, int y, int state) int x, int y, int state)
{ {
static uint32_t bmap[INPUT_BUTTON_MAX] = { static uint32_t bmap[INPUT_BUTTON_MAX] = {
[INPUT_BUTTON_LEFT] = SDL_BUTTON(SDL_BUTTON_LEFT), [INPUT_BUTTON_LEFT] = SDL_BUTTON(SDL_BUTTON_LEFT),
[INPUT_BUTTON_MIDDLE] = SDL_BUTTON(SDL_BUTTON_MIDDLE), [INPUT_BUTTON_MIDDLE] = SDL_BUTTON(SDL_BUTTON_MIDDLE),
[INPUT_BUTTON_RIGHT] = SDL_BUTTON(SDL_BUTTON_RIGHT), [INPUT_BUTTON_RIGHT] = SDL_BUTTON(SDL_BUTTON_RIGHT),
#if 0
[INPUT_BUTTON_WHEEL_UP] = SDL_BUTTON(SDL_BUTTON_WHEELUP),
[INPUT_BUTTON_WHEEL_DOWN] = SDL_BUTTON(SDL_BUTTON_WHEELDOWN),
#endif
}; };
static uint32_t prev_state; static uint32_t prev_state;
@@ -566,7 +562,7 @@ static void handle_mousemotion(SDL_Event *ev)
} }
} }
if (gui_grab || qemu_input_is_absolute() || absolute_enabled) { if (gui_grab || qemu_input_is_absolute() || absolute_enabled) {
sdl_send_mouse_event(scon, ev->motion.xrel, ev->motion.yrel, 0, sdl_send_mouse_event(scon, ev->motion.xrel, ev->motion.yrel,
ev->motion.x, ev->motion.y, ev->motion.state); ev->motion.x, ev->motion.y, ev->motion.state);
} }
} }
@@ -576,7 +572,6 @@ static void handle_mousebutton(SDL_Event *ev)
int buttonstate = SDL_GetMouseState(NULL, NULL); int buttonstate = SDL_GetMouseState(NULL, NULL);
SDL_MouseButtonEvent *bev; SDL_MouseButtonEvent *bev;
struct sdl2_state *scon = get_scon_from_window(ev->key.windowID); struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
int dz;
bev = &ev->button; bev = &ev->button;
if (!gui_grab && !qemu_input_is_absolute()) { if (!gui_grab && !qemu_input_is_absolute()) {
@@ -585,25 +580,35 @@ static void handle_mousebutton(SDL_Event *ev)
sdl_grab_start(scon); sdl_grab_start(scon);
} }
} else { } else {
dz = 0;
if (ev->type == SDL_MOUSEBUTTONDOWN) { if (ev->type == SDL_MOUSEBUTTONDOWN) {
buttonstate |= SDL_BUTTON(bev->button); buttonstate |= SDL_BUTTON(bev->button);
} else { } else {
buttonstate &= ~SDL_BUTTON(bev->button); buttonstate &= ~SDL_BUTTON(bev->button);
} }
#ifdef SDL_BUTTON_WHEELUP sdl_send_mouse_event(scon, 0, 0, bev->x, bev->y, buttonstate);
if (bev->button == SDL_BUTTON_WHEELUP &&
ev->type == SDL_MOUSEBUTTONDOWN) {
dz = -1;
} else if (bev->button == SDL_BUTTON_WHEELDOWN &&
ev->type == SDL_MOUSEBUTTONDOWN) {
dz = 1;
}
#endif
sdl_send_mouse_event(scon, 0, 0, dz, bev->x, bev->y, buttonstate);
} }
} }
static void handle_mousewheel(SDL_Event *ev)
{
struct sdl2_state *scon = get_scon_from_window(ev->key.windowID);
SDL_MouseWheelEvent *wev = &ev->wheel;
InputButton btn;
if (wev->y > 0) {
btn = INPUT_BUTTON_WHEEL_UP;
} else if (wev->y < 0) {
btn = INPUT_BUTTON_WHEEL_DOWN;
} else {
return;
}
qemu_input_queue_btn(scon->dcl.con, btn, true);
qemu_input_event_sync();
qemu_input_queue_btn(scon->dcl.con, btn, false);
qemu_input_event_sync();
}
static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev) static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev)
{ {
int w, h; int w, h;
@@ -612,6 +617,13 @@ static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev)
switch (ev->window.event) { switch (ev->window.event) {
case SDL_WINDOWEVENT_RESIZED: case SDL_WINDOWEVENT_RESIZED:
sdl_scale(scon, ev->window.data1, ev->window.data2); sdl_scale(scon, ev->window.data1, ev->window.data2);
{
QemuUIInfo info;
memset(&info, 0, sizeof(info));
info.width = ev->window.data1;
info.height = ev->window.data2;
dpy_set_ui_info(scon->dcl.con, &info);
}
graphic_hw_invalidate(scon->dcl.con); graphic_hw_invalidate(scon->dcl.con);
graphic_hw_update(scon->dcl.con); graphic_hw_update(scon->dcl.con);
break; break;
@@ -678,6 +690,9 @@ static void sdl_refresh(DisplayChangeListener *dcl)
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
handle_mousebutton(ev); handle_mousebutton(ev);
break; break;
case SDL_MOUSEWHEEL:
handle_mousewheel(ev);
break;
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
handle_windowevent(dcl, ev); handle_windowevent(dcl, ev);
break; break;