GTK+: Add hotkey to capture the mouse.

This commit is contained in:
Brandon Wright 2018-11-08 14:23:37 -06:00
parent af2df5869d
commit 8c7b326254
5 changed files with 142 additions and 3 deletions

View File

@ -99,6 +99,7 @@ const BindingLink b_links[] =
{ "b_seek_to_frame", "GTK_seek_to_frame" }, { "b_seek_to_frame", "GTK_seek_to_frame" },
{ "b_swap_controllers", "GTK_swap_controllers" }, { "b_swap_controllers", "GTK_swap_controllers" },
{ "b_rewind", "GTK_rewind" }, { "b_rewind", "GTK_rewind" },
{ "b_grab_mouse", "GTK_grab_mouse" },
{ NULL, NULL } { NULL, NULL }
}; };
@ -112,7 +113,7 @@ const int b_breaks[] =
43, /* End of Graphic options */ 43, /* End of Graphic options */
69, /* End of save/load states */ 69, /* End of save/load states */
78, /* End of sound buttons */ 78, /* End of sound buttons */
85, /* End of miscellaneous buttons */ 86, /* End of miscellaneous buttons */
-1 -1
}; };
@ -289,6 +290,11 @@ void S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2)
{ {
change_slot (-1); change_slot (-1);
} }
else if (cmd.port[0] == PORT_GRABMOUSE)
{
top_level->toggle_grab_mouse ();
}
} }
} }
@ -437,6 +443,11 @@ s9xcommand_t S9xGetPortCommandT (const char *name)
cmd.port[0] = PORT_DECREMENTSLOT; cmd.port[0] = PORT_DECREMENTSLOT;
} }
else if (strstr (name, "GTK_grab_mouse"))
{
cmd.port[0] = PORT_GRABMOUSE;
}
else else
{ {

View File

@ -49,6 +49,7 @@ enum
PORT_DECREMENTLOADSLOT = 22, PORT_DECREMENTLOADSLOT = 22,
PORT_INCREMENTSLOT = 23, PORT_INCREMENTSLOT = 23,
PORT_DECREMENTSLOT = 24, PORT_DECREMENTSLOT = 24,
PORT_GRABMOUSE = 25
}; };
typedef struct BindingLink typedef struct BindingLink
@ -61,7 +62,7 @@ typedef struct BindingLink
extern const BindingLink b_links[]; extern const BindingLink b_links[];
extern const int b_breaks[]; extern const int b_breaks[];
const int NUM_JOYPAD_LINKS = 24; const int NUM_JOYPAD_LINKS = 24;
const int NUM_EMU_LINKS = 61; const int NUM_EMU_LINKS = 62;
typedef struct JoypadBinding typedef struct JoypadBinding
{ {

View File

@ -232,6 +232,19 @@ event_motion_notify (GtkWidget *widget,
return FALSE; return FALSE;
} }
if (window->mouse_grabbed)
{
if (event->x_root == window->mouse_reported_x &&
event->y_root == window->mouse_reported_y)
return FALSE;
window->mouse_loc_x += (event->x_root - window->mouse_reported_x);
window->mouse_loc_y += (event->y_root - window->mouse_reported_y);
window->center_mouse ();
return FALSE;
}
#if GTK_CHECK_VERSION(3,10,0) #if GTK_CHECK_VERSION(3,10,0)
int scale_factor = gdk_window_get_scale_factor (gtk_widget_get_window (GTK_WIDGET (window->get_window ()))); int scale_factor = gdk_window_get_scale_factor (gtk_widget_get_window (GTK_WIDGET (window->get_window ())));
#else #else
@ -594,6 +607,7 @@ Snes9xWindow::Snes9xWindow (Snes9xConfig *config) :
paused_from_focus_loss = 0; paused_from_focus_loss = 0;
cr = NULL; cr = NULL;
cairo_owned = 0; cairo_owned = 0;
mouse_grabbed = 0;
if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), "snes9x")) if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), "snes9x"))
{ {
@ -1804,6 +1818,84 @@ Snes9xWindow::show_mouse_cursor ()
config->pointer_is_visible = TRUE; config->pointer_is_visible = TRUE;
} }
void
Snes9xWindow::center_mouse ()
{
GdkWindow *gdk_window = gtk_widget_get_window (window);
GdkDisplay *gdk_display = gdk_window_get_display (gdk_window);
GdkScreen *gdk_screen = gdk_window_get_screen (gdk_window);
int x, y, w, h;
gdk_window_get_origin (gdk_window, &x, &y);
w = gdk_window_get_width (gdk_window);
h = gdk_window_get_height (gdk_window);
mouse_reported_x = x + w / 2;
mouse_reported_y = y + h / 2;
#if GTK_MAJOR_VERSION < 3
gdk_display_warp_pointer (gdk_display, gdk_screen, mouse_reported_x,
mouse_reported_y);
#elif GTK_MINOR_VERSION < 20
GdkDeviceManager *manager = gdk_display_get_device_manager (gdk_display);
GdkDevice *pointer = gdk_device_manager_get_client_pointer (manager);
gdk_device_warp (pointer, gdk_screen, mouse_reported_x, mouse_reported_y);
#else
GdkSeat *seat = gdk_display_get_default_seat (gdk_display);
GdkDevice *pointer = gdk_seat_get_pointer (seat);
gdk_device_warp (pointer, gdk_screen, mouse_reported_x, mouse_reported_y);
#endif
}
void
Snes9xWindow::toggle_grab_mouse ()
{
GdkWindow *gdk_window = gtk_widget_get_window (window);
GdkDisplay *gdk_display = gdk_window_get_display (gdk_window);
if ((!mouse_grabbed && !S9xIsMousePluggedIn ()) || !config->rom_loaded)
return;
#if GTK_MAJOR_VERSION < 3
if (!mouse_grabbed)
{
gdk_pointer_grab (gdk_window, TRUE, (GdkEventMask) 1020, gdk_window, empty_cursor, GDK_CURRENT_TIME);
center_mouse ();
}
else
{
gdk_pointer_ungrab (GDK_CURRENT_TIME);
if (config->pointer_is_visible)
show_mouse_cursor ();
}
#elif GTK_MINOR_VERSION < 20
GdkDeviceManager *manager = gdk_display_get_device_manager (gdk_display);
GdkDevice *pointer = gdk_device_manager_get_client_pointer (manager);
if (!mouse_grabbed)
gdk_device_grab (pointer, gdk_window, GDK_OWNERSHIP_NONE, TRUE,
(GdkEventMask) 1020, empty_cursor, GDK_CURRENT_TIME);
else
gdk_device_ungrab (pointer, GDK_CURRENT_TIME);
#else
GdkSeat *seat = gdk_display_get_default_seat (gdk_display);
if (!mouse_grabbed)
gdk_seat_grab (seat, gdk_window, GDK_SEAT_CAPABILITY_ALL_POINTING, TRUE,
empty_cursor, NULL, NULL, NULL);
else
gdk_seat_ungrab (seat);
#endif
S9xReportPointer (BINDING_MOUSE_POINTER, 0, 0);
mouse_loc_x = 0; mouse_loc_y = 0;
mouse_grabbed ^= 1;
if (mouse_grabbed)
center_mouse ();
}
void void
Snes9xWindow::show () Snes9xWindow::show ()
{ {

View File

@ -30,6 +30,8 @@ class Snes9xWindow : public GtkBuilderWindow
/* Cursor modifying functions */ /* Cursor modifying functions */
void show_mouse_cursor (); void show_mouse_cursor ();
void hide_mouse_cursor (); void hide_mouse_cursor ();
void toggle_grab_mouse ();
void center_mouse ();
/* Rom-related functions */ /* Rom-related functions */
void open_rom_dialog (); void open_rom_dialog ();
@ -75,6 +77,8 @@ class Snes9xWindow : public GtkBuilderWindow
int focused; int focused;
int paused_from_focus_loss; int paused_from_focus_loss;
uint16 mouse_loc_x, mouse_loc_y; uint16 mouse_loc_x, mouse_loc_y;
uint16 mouse_reported_x, mouse_reported_y;
int mouse_grabbed;
GdkPixbuf *icon, *splash; GdkPixbuf *icon, *splash;
GdkCursor *default_cursor, *empty_cursor; GdkCursor *default_cursor, *empty_cursor;
GtkDrawingArea *drawing_area; GtkDrawingArea *drawing_area;

View File

@ -8709,7 +8709,7 @@
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="border_width">10</property> <property name="border_width">10</property>
<property name="n_rows">7</property> <property name="n_rows">8</property>
<property name="n_columns">2</property> <property name="n_columns">2</property>
<property name="column_spacing">10</property> <property name="column_spacing">10</property>
<property name="row_spacing">5</property> <property name="row_spacing">5</property>
@ -8936,6 +8936,37 @@
<property name="y_options">GTK_FILL</property> <property name="y_options">GTK_FILL</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkLabel" id="label_grab_mouse">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Capture/release mouse</property>
</object>
<packing>
<property name="top_attach">7</property>
<property name="bottom_attach">8</property>
<property name="x_options">GTK_FILL</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkEntry" id="b_grab_mouse">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">7</property>
<property name="bottom_attach">8</property>
<property name="y_options">GTK_FILL</property>
</packing>
</child>
</object> </object>
<packing> <packing>
<property name="position">4</property> <property name="position">4</property>