[retro-gtk/wip/aplazas/core-view: 5/8] core-view: Add mouse support
- From: Adrien Plazas <aplazas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [retro-gtk/wip/aplazas/core-view: 5/8] core-view: Add mouse support
- Date: Wed, 30 Aug 2017 10:52:40 +0000 (UTC)
commit 750650420d2a3fcbdd8e41a97adcb8c34b6a607f
Author: Adrien Plazas <kekun plazas laposte net>
Date: Fri Aug 11 08:40:57 2017 +0200
core-view: Add mouse support
retro-gtk/retro-core-view-extern.c | 189 +++++++++++++++++++++++++++++++++++-
retro-gtk/retro-core-view.vala | 40 ++++++++
2 files changed, 228 insertions(+), 1 deletions(-)
---
diff --git a/retro-gtk/retro-core-view-extern.c b/retro-gtk/retro-core-view-extern.c
index be9a1ef..441ac51 100644
--- a/retro-gtk/retro-core-view-extern.c
+++ b/retro-gtk/retro-core-view-extern.c
@@ -55,6 +55,84 @@ get_input_state (GHashTable *table,
return g_hash_table_contains (table, &input);
}
+static void
+recenter_pointer (RetroCoreView *self)
+{
+ gdk_device_warp (self->grabbed_device, self->grabbed_screen,
+ self->screen_center_x, self->screen_center_y);
+}
+
+// FIXME Make static as soon as possible.
+gboolean
+retro_core_view_get_is_pointer_grabbed (RetroCoreView *self)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ return self->grabbed_device != NULL;
+}
+
+static void
+retro_core_view_grab (RetroCoreView *self,
+ GdkDevice *device,
+ GdkWindow *window,
+ GdkEvent *event)
+{
+ GdkSeat *seat;
+ GdkDisplay *display;
+ GdkCursor *cursor;
+ GdkScreen *screen = NULL;
+ GdkMonitor *monitor;
+ GdkRectangle monitor_geometry;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (device != NULL);
+ g_return_if_fail (window != NULL);
+ g_return_if_fail (event != NULL);
+
+ if (self->grabbed_device != NULL)
+ g_object_unref (self->grabbed_device);
+
+ if (self->grabbed_screen != NULL)
+ g_object_unref (self->grabbed_screen);
+
+ self->grabbed_device = g_object_ref (device);
+ seat = gdk_device_get_seat (device);
+ display = gdk_device_get_display (device);
+ cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR);
+ gdk_seat_grab (seat, window, GDK_SEAT_CAPABILITY_ALL_POINTING, FALSE, cursor, event, NULL, NULL);
+ monitor = gdk_display_get_monitor_at_window (display, window);
+ gdk_monitor_get_geometry (monitor, &monitor_geometry);
+
+ gdk_device_get_position (device, &screen, &self->position_on_grab_x, &self->position_on_grab_y);
+ self->grabbed_screen = g_object_ref (screen);
+ self->screen_center_x = monitor_geometry.x + monitor_geometry.width / 2;
+ self->screen_center_y = monitor_geometry.y + monitor_geometry.height / 2;
+ self->mouse_x_delta = 0;
+ self->mouse_y_delta = 0;
+
+ recenter_pointer (self);
+
+ g_object_unref (cursor);
+}
+
+// FIXME Make static as soon as possible.
+void
+retro_core_view_ungrab (RetroCoreView *self)
+{
+ GdkSeat *seat;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (self->grabbed_device != NULL);
+
+ seat = gdk_device_get_seat (self->grabbed_device);
+ gdk_seat_ungrab (seat);
+ gdk_device_warp (self->grabbed_device, self->grabbed_screen,
+ self->position_on_grab_x, self->position_on_grab_y);
+
+ g_clear_object (&self->grabbed_device);
+ g_clear_object (&self->grabbed_screen);
+}
+
// FIXME Make static as soon as possible.
gboolean
retro_core_view_on_key_press_event (RetroCoreView *self,
@@ -64,6 +142,11 @@ retro_core_view_on_key_press_event (RetroCoreView *self,
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (event != NULL, FALSE);
+ if (event->keyval == GDK_KEY_Escape &&
+ (event->state & GDK_CONTROL_MASK) &&
+ retro_core_view_get_is_pointer_grabbed (self))
+ retro_core_view_ungrab (self);
+
set_input_pressed (self->key_state, event->hardware_keycode);
return FALSE;
@@ -83,6 +166,79 @@ retro_core_view_on_key_release_event (RetroCoreView *self,
return FALSE;
}
+// FIXME Make static as soon as possible.
+gboolean
+retro_core_view_on_button_press_event (RetroCoreView *self,
+ GtkWidget *source,
+ GdkEventButton *event)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (retro_core_view_get_can_grab_pointer (self)) {
+ if (retro_core_view_get_is_pointer_grabbed (self))
+ set_input_pressed (self->mouse_button_state, event->button);
+ else
+ retro_core_view_grab (self,
+ event->device,
+ event->window,
+ (GdkEvent *) event);
+ }
+
+ return FALSE;
+}
+
+// FIXME Make static as soon as possible.
+gboolean
+retro_core_view_on_button_release_event (RetroCoreView *self,
+ GtkWidget *source,
+ GdkEventButton *event)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ set_input_released (self->mouse_button_state, event->button);
+
+ return FALSE;
+}
+
+// FIXME Make static as soon as possible.
+gboolean
+retro_core_view_on_focus_out_event (RetroCoreView *self,
+ GtkWidget *source,
+ GdkEventFocus *event)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (retro_core_view_get_is_pointer_grabbed (self))
+ retro_core_view_ungrab (self);
+
+ return FALSE;
+}
+
+// FIXME Make static as soon as possible.
+gboolean
+retro_core_view_on_motion_notify_event (RetroCoreView *self,
+ GtkWidget *source,
+ GdkEventMotion *event)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (retro_core_view_get_can_grab_pointer (self)) {
+ if (retro_core_view_get_is_pointer_grabbed (self) &&
+ event->device == self->grabbed_device) {
+ self->mouse_x_delta += event->x_root - (double) self->screen_center_x;
+ self->mouse_y_delta += event->y_root - (double) self->screen_center_y;
+
+ recenter_pointer (self);
+ }
+ }
+
+ return FALSE;
+}
+
static gboolean
retro_core_view_get_key_state (RetroCoreView *self,
guint16 hardware_keycode)
@@ -109,6 +265,15 @@ retro_core_view_get_joypad_button_state (RetroCoreView *self,
return retro_core_view_get_key_state (self, hardware_keycode);
}
+static gboolean
+retro_core_view_get_mouse_button_state (RetroCoreView *self,
+ guint16 button)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ return get_input_state (self->mouse_button_state, button);
+}
+
// FIXME Make static as soon as possible.
gint16
retro_core_view_get_input_state (RetroCoreView *self,
@@ -116,6 +281,8 @@ retro_core_view_get_input_state (RetroCoreView *self,
guint index,
guint id)
{
+ gint16 result;
+
g_return_val_if_fail (self != NULL, 0);
switch (device) {
@@ -124,6 +291,25 @@ retro_core_view_get_input_state (RetroCoreView *self,
return 0;
return retro_core_view_get_joypad_button_state (self, id) ? G_MAXINT16 : 0;
+ case RETRO_DEVICE_TYPE_MOUSE:
+ switch (id) {
+ case RETRO_MOUSE_ID_X:
+ result = (gint16) self->mouse_x_delta;
+ self->mouse_x_delta = 0;
+
+ return result;
+ case RETRO_MOUSE_ID_Y:
+ result = self->mouse_y_delta;
+ self->mouse_y_delta = 0;
+
+ return result;
+ case RETRO_MOUSE_ID_LEFT:
+ return retro_core_view_get_mouse_button_state (self, 1) ? G_MAXINT16 : 0;
+ case RETRO_MOUSE_ID_RIGHT:
+ return retro_core_view_get_mouse_button_state (self, 3) ? G_MAXINT16 : 0;
+ default:
+ return 0;
+ }
default:
return 0;
}
@@ -135,7 +321,8 @@ retro_core_view_get_device_capabilities (RetroCoreView *self)
{
g_return_val_if_fail (self != NULL, 0);
- return 1 << RETRO_DEVICE_TYPE_JOYPAD;
+ return 1 << RETRO_DEVICE_TYPE_JOYPAD |
+ 1 << RETRO_DEVICE_TYPE_MOUSE;
}
/* Public */
diff --git a/retro-gtk/retro-core-view.vala b/retro-gtk/retro-core-view.vala
index a180fbe..742b5cd 100644
--- a/retro-gtk/retro-core-view.vala
+++ b/retro-gtk/retro-core-view.vala
@@ -1,10 +1,35 @@
// This file is part of retro-gtk. License: GPL-3.0+.
public class Retro.CoreView : Gtk.EventBox {
+ private bool _can_grab_pointer;
+ public bool can_grab_pointer {
+ set {
+ if (value == _can_grab_pointer)
+ return;
+
+ _can_grab_pointer = value;
+
+ if (_can_grab_pointer == false && get_is_pointer_grabbed ())
+ ungrab ();
+ }
+ get { return _can_grab_pointer; }
+ default = false;
+ }
+
+
private Core core;
private CairoDisplay display;
internal HashTable<uint?, bool?> key_state;
+ internal HashTable<uint?, bool?> mouse_button_state;
+ internal Gdk.Screen grabbed_screen;
+ internal Gdk.Device grabbed_device;
+ internal double mouse_x_delta;
+ internal double mouse_y_delta;
+ internal int screen_center_x;
+ internal int screen_center_y;
+ internal int position_on_grab_x;
+ internal int position_on_grab_y;
construct {
can_focus = true;
@@ -15,9 +40,14 @@ public class Retro.CoreView : Gtk.EventBox {
add (display);
key_state = new HashTable<uint?, bool?> (int_hash, int_equal);
+ mouse_button_state = new HashTable<uint?, bool?> (int_hash, int_equal);
key_press_event.connect (on_key_press_event);
key_release_event.connect (on_key_release_event);
+ button_press_event.connect (on_button_press_event);
+ button_release_event.connect (on_button_release_event);
+ focus_out_event.connect (on_focus_out_event);
+ motion_notify_event.connect (on_motion_notify_event);
}
public void set_core (Core? core) {
@@ -30,9 +60,19 @@ public class Retro.CoreView : Gtk.EventBox {
display.set_core (core);
}
+ public CairoDisplay get_display () {
+ return display;
+ }
+
public extern InputDevice as_input_device (DeviceType device_type);
internal extern int16 get_input_state (DeviceType device, uint index, uint id);
internal extern uint64 get_device_capabilities ();
+ internal extern bool get_is_pointer_grabbed ();
+ internal extern void ungrab ();
internal extern bool on_key_press_event (Gtk.Widget source, Gdk.EventKey event);
internal extern bool on_key_release_event (Gtk.Widget source, Gdk.EventKey event);
+ internal extern bool on_button_press_event (Gtk.Widget source, Gdk.EventButton event);
+ internal extern bool on_button_release_event (Gtk.Widget source, Gdk.EventButton event);
+ internal extern bool on_focus_out_event (Gtk.Widget source, Gdk.EventFocus event);
+ internal extern bool on_motion_notify_event (Gtk.Widget source, Gdk.EventMotion event);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]