[retro-gtk/wip/aplazas/0.13: 16/22] Port CoreView to C
- From: Adrien Plazas <aplazas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [retro-gtk/wip/aplazas/0.13: 16/22] Port CoreView to C
- Date: Fri, 8 Sep 2017 10:49:54 +0000 (UTC)
commit 680456f37b6c76f5fa0df9e0a97ef1ca186514ff
Author: Adrien Plazas <kekun plazas laposte net>
Date: Tue Sep 5 12:17:41 2017 +0200
Port CoreView to C
demos/retro-demo.c | 1 +
retro-gtk/Makefile.am | 6 +-
retro-gtk/core.vala | 132 +-------
retro-gtk/retro-core-view-extern.c | 386 ------------------
retro-gtk/retro-core-view-input-device.h | 1 +
retro-gtk/retro-core-view.c | 624 ++++++++++++++++++++++++++++++
retro-gtk/retro-core-view.h | 40 ++
retro-gtk/retro-core-view.vala | 82 ----
retro-gtk/retro-gtk.h | 1 +
9 files changed, 671 insertions(+), 602 deletions(-)
---
diff --git a/demos/retro-demo.c b/demos/retro-demo.c
index 8093da8..0cf7ccc 100644
--- a/demos/retro-demo.c
+++ b/demos/retro-demo.c
@@ -1,6 +1,7 @@
// This file is part of retro-gtk. License: GPL-3.0+.
#include <retro-gtk/retro-gtk.h>
+#include <retro-gtk/retro-core-view.h>
#define RETRO_TYPE_DEMO_APPLICATION (retro_demo_application_get_type())
diff --git a/retro-gtk/Makefile.am b/retro-gtk/Makefile.am
index 0769308..6230ed5 100644
--- a/retro-gtk/Makefile.am
+++ b/retro-gtk/Makefile.am
@@ -45,8 +45,7 @@ libretro_gtk_la_SOURCES = \
retro.vala \
retro-core-descriptor.vala \
retro-core-descriptor-error.vala \
- retro-core-view.vala \
- retro-core-view-extern.c \
+ retro-core-view.c \
retro-core-view-input-device.c \
retro-game-info.c \
retro-input-descriptor.c \
@@ -70,7 +69,7 @@ video/retro-video-converter.c: retro-gtk-internal.h
retro-core.c: retro-gtk-internal.h
-retro-core-view-extern.c: retro-gtk-internal.h
+retro-core-view.c: retro-gtk-internal.h
retro-core-view-input-device.c: retro-gtk-internal.h
@@ -108,6 +107,7 @@ retro_gtkincludedir = $(includedir)/retro-gtk-0.12
retro_gtkinclude_HEADERS = \
retro-analog-id.h \
retro-analog-index.h \
+ retro-core-view.h \
retro-device-type.h \
retro-gtk.h \
retro-gtk-vala.h \
diff --git a/retro-gtk/core.vala b/retro-gtk/core.vala
index e898f2f..5da72d5 100644
--- a/retro-gtk/core.vala
+++ b/retro-gtk/core.vala
@@ -2,82 +2,27 @@
namespace Retro {
-/**
- * Handles a Libretro module.
- */
public class Core : Object {
public signal void video_output (uint8[] data, uint width, uint height, size_t pitch, PixelFormat
pixel_format, float aspect_ratio);
public signal void audio_output (int16[] frames, double sample_rate);
public signal void log (string log_domain, LogLevelFlags log_level, string message);
- /**
- * Stores the current Core instance in a stack.
- *
- * Stores the current instance of Core in a thread local global stack.
- * It allows to know wich Core a callback is related to.
- *
- * Must be called before any call to a function from the module.
- */
internal extern void push_cb_data ();
-
- /**
- * Removes the Core at the head of the stack.
- *
- * Must be called after any call to {@link push_cb_data()}.
- */
internal extern static void pop_cb_data ();
-
internal extern static unowned Core get_cb_data ();
private extern uint get_api_version_real ();
- /**
- * The version of Libretro used by the module.
- *
- * Can be compared with {@link API_VERSION} to validate ABI
- * compatibility.
- */
public uint api_version {
get { return get_api_version_real (); }
}
- /**
- * The file name of the module.
- */
public string file_name { internal set; get; }
-
- /**
- * The directory the core will use to look for for additional data.
- */
public string system_directory { set; get; default = "."; }
-
- /**
- * The absolute path to the source module file.
- */
public string libretro_path { set; get; default = "."; }
-
- /**
- * The directory the core will use to look for for additional assets.
- */
public string content_directory { set; get; default = "."; }
-
- /**
- * The directory the core will use to save user data.
- */
public string save_directory { set; get; default = "."; }
-
- /**
- * Whether or not the a game is loaded.
- */
public bool is_initiated { internal set; get; default = false; }
-
- /**
- * Whether or not the a game is loaded.
- */
public bool game_loaded { internal set; get; default = false; }
-
- /**
- * Whether or not the core supports games.
- */
public bool support_no_game { internal set; get; default = false; }
internal double _frames_per_second;
@@ -89,11 +34,7 @@ public class Core : Object {
private ulong input_controller_connected_id;
private ulong input_controller_disconnected_id;
private ulong input_key_event_id;
- /**
- * The input interface.
- *
- * It must be set before {@link init} is called.
- */
+
public Input input_interface {
get { return _input_interface; }
construct set {
@@ -120,36 +61,16 @@ public class Core : Object {
}
}
- /**
- * The rumble interface.
- *
- * Optional.
- * If set, it must be set before {@link init} is called.
- */
public Rumble rumble_interface { set; get; }
- /**
- * Asks the frontend to shut down.
- */
public signal bool shutdown ();
- /**
- * Asks the frontend to display a message for an amount of frames.
- */
public signal bool message (string message, uint frames);
internal Variables variables_interface;
internal void *environment_internal;
- /**
- * Creates a Core from the file name of a Libretro implementation.
- *
- * The file must be a dynamically loadable shared object implementing the
- * same version of the Libretro API as Retro.
- *
- * @param file_name the file name of the Libretro implementation to load
- */
public Core (string file_name) {
constructor (file_name);
}
@@ -161,69 +82,18 @@ public class Core : Object {
private extern void constructor (string file_name);
private extern void destructor ();
- /**
- * Initializes the module.
- *
- * Must be called before loading a game and running the core.
- */
public extern void init () throws Error;
-
public extern void set_medias ([CCode (array_null_terminated = true, array_length = false)] string[]
uris);
-
public extern void set_current_media (uint media_index) throws Error;
-
public extern void set_controller_port_device (uint port, DeviceType device);
-
- /**
- * Resets the current game.
- */
public extern void reset ();
-
- /**
- * Runs the game for one video frame.
- *
- * The callbacks must be set and the core must be initialized before
- * running the core.
- *
- * During {@link run}, the input_poll callback will be called
- * at least once.
- *
- * If a frame is not rendered for reasons where a game "dropped" a frame,
- * this still counts as a frame, and {@link run} will explicitly dupe a
- * frame if the can_dupe property of {@link video_interface} is set to true.
- * In this case, the video callback can take a null argument for data.
- */
public extern void run ();
-
public extern bool supports_serialization ();
-
[CCode (array_length_type = "gsize")]
public extern uint8[] serialize_state () throws Error;
-
public extern void deserialize_state ([CCode (array_length_type = "gsize")] uint8[] data) throws
Error;
-
- /**
- * Gets the size of a region of memory.
- *
- * @param id the region of memory
- * @return the size of the region of memory
- */
public extern size_t get_memory_size (MemoryType id);
-
- /**
- * Gets a region of memory.
- *
- * @param id the region of memory
- * @return the region of memory
- */
public extern uint8[] get_memory (MemoryType id);
-
- /**
- * Sets a region of memory.
- *
- * @param id the region of memory
- * @param data the data to write in the memory region
- */
public extern void set_memory (MemoryType id, uint8[] data);
private extern void init_input ();
diff --git a/retro-gtk/retro-core-view-input-device.h b/retro-gtk/retro-core-view-input-device.h
index 4520d40..fff4a3c 100644
--- a/retro-gtk/retro-core-view-input-device.h
+++ b/retro-gtk/retro-core-view-input-device.h
@@ -4,6 +4,7 @@
#define RETRO_CORE_VIEW_INPUT_DEVICE_H
#include <glib-object.h>
+#include "retro-core-view.h"
#include "retro-device-type.h"
#include "retro-gtk-internal.h"
diff --git a/retro-gtk/retro-core-view.c b/retro-gtk/retro-core-view.c
new file mode 100644
index 0000000..99ed6fc
--- /dev/null
+++ b/retro-gtk/retro-core-view.c
@@ -0,0 +1,624 @@
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+#include <linux/input-event-codes.h>
+#include "retro-gtk-internal.h"
+#include "retro-core-view.h"
+#include "retro-core-view-input-device.h"
+#include "retro-joypad-id.h"
+#include "retro-mouse-id.h"
+#include "retro-pointer-id.h"
+
+static guint16 DEFAULT_KEY_JOYPAD_BUTTON_MAPPING[RETRO_JOYPAD_ID_COUNT] = {
+ KEY_S,
+ KEY_A,
+ KEY_BACKSPACE,
+ KEY_ENTER,
+ KEY_UP,
+ KEY_DOWN,
+ KEY_LEFT,
+ KEY_RIGHT,
+ KEY_D,
+ KEY_W,
+ KEY_Q,
+ KEY_E,
+ KEY_Z,
+ KEY_C,
+ KEY_1,
+ KEY_3,
+};
+
+struct _RetroCoreView
+{
+ GtkEventBox parent_instance;
+ RetroCore *core;
+ RetroCairoDisplay *display;
+ gboolean can_grab_pointer;
+ gboolean snap_pointer_to_borders;
+ GHashTable *key_state;
+ GHashTable *mouse_button_state;
+ GdkScreen *grabbed_screen;
+ GdkDevice *grabbed_device;
+ gdouble mouse_x_delta;
+ gdouble mouse_y_delta;
+ gint screen_center_x;
+ gint screen_center_y;
+ gint position_on_grab_x;
+ gint position_on_grab_y;
+ gboolean pointer_is_on_display;
+ gdouble pointer_x;
+ gdouble pointer_y;
+};
+
+G_DEFINE_TYPE (RetroCoreView, retro_core_view, GTK_TYPE_EVENT_BOX)
+
+enum {
+ PROP_CAN_GRAB_POINTER = 1,
+ PROP_SNAP_POINTER_TO_BORDERS,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+/* Private */
+
+static void
+set_input_pressed (GHashTable *table,
+ guint input)
+{
+ static gboolean value = TRUE;
+
+ if (g_hash_table_contains (table, &input))
+ g_hash_table_replace (table,
+ g_memdup (&input, sizeof (guint)),
+ g_memdup (&value, sizeof (gboolean)));
+ else
+ g_hash_table_insert (table,
+ g_memdup (&input, sizeof (guint)),
+ g_memdup (&value, sizeof (gboolean)));
+}
+
+static void
+set_input_released (GHashTable *table,
+ guint input)
+{
+ g_hash_table_remove (table, &input);
+}
+
+static gboolean
+get_input_state (GHashTable *table,
+ guint input)
+{
+ return g_hash_table_contains (table, &input);
+}
+
+static gint16
+axis_to_retro_axis (gdouble value)
+{
+ if (value <= -1.0)
+ return -G_MAXINT16;
+
+ if (value >= 1.0)
+ return G_MAXINT16;
+
+ return (gint16) (value * G_MAXINT16);
+}
+
+static void
+recenter_pointer (RetroCoreView *self)
+{
+ gdk_device_warp (self->grabbed_device, self->grabbed_screen,
+ self->screen_center_x, self->screen_center_y);
+}
+
+static 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);
+}
+
+static 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);
+}
+
+static gboolean
+retro_core_view_on_key_press_event (GtkWidget *source,
+ GdkEventKey *event,
+ gpointer data)
+{
+ RetroCoreView *self = RETRO_CORE_VIEW (data);
+
+ 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;
+}
+
+static gboolean
+retro_core_view_on_key_release_event (GtkWidget *source,
+ GdkEventKey *event,
+ gpointer data)
+{
+ RetroCoreView *self = RETRO_CORE_VIEW (data);
+
+ g_return_val_if_fail (self != NULL, FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ set_input_released (self->key_state, event->hardware_keycode);
+
+ return FALSE;
+}
+
+static gboolean
+retro_core_view_on_button_press_event (GtkWidget *source,
+ GdkEventButton *event,
+ gpointer data)
+{
+ RetroCoreView *self = RETRO_CORE_VIEW (data);
+
+ 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);
+ }
+ else {
+ set_input_pressed (self->mouse_button_state, event->button);
+ self->pointer_is_on_display =
+ retro_cairo_display_get_coordinates_on_display (self->display,
+ event->x,
+ event->y,
+ &self->pointer_x,
+ &self->pointer_y);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+retro_core_view_on_button_release_event (GtkWidget *source,
+ GdkEventButton *event,
+ gpointer data)
+{
+ RetroCoreView *self = RETRO_CORE_VIEW (data);
+
+ 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;
+}
+
+static gboolean
+retro_core_view_on_focus_out_event (GtkWidget *source,
+ GdkEventFocus *event,
+ gpointer data)
+{
+ RetroCoreView *self = RETRO_CORE_VIEW (data);
+
+ 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;
+}
+
+static gboolean
+retro_core_view_on_motion_notify_event (GtkWidget *source,
+ GdkEventMotion *event,
+ gpointer data)
+{
+ RetroCoreView *self = RETRO_CORE_VIEW (data);
+
+ 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);
+ }
+ }
+ else {
+ self->pointer_is_on_display =
+ retro_cairo_display_get_coordinates_on_display (self->display,
+ event->x,
+ event->y,
+ &self->pointer_x,
+ &self->pointer_y);
+
+ }
+
+ return FALSE;
+}
+
+static gboolean
+retro_core_view_get_key_state (RetroCoreView *self,
+ guint16 hardware_keycode)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ return get_input_state (self->key_state, hardware_keycode);
+}
+
+static gboolean
+retro_core_view_get_joypad_button_state (RetroCoreView *self,
+ RetroJoypadId button)
+{
+ guint16 hardware_keycode;
+
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ if (button >= RETRO_JOYPAD_ID_COUNT)
+ return 0;
+
+ // GDK adds 8 to the Linux input event codes to create the hardware keycode.
+ hardware_keycode = DEFAULT_KEY_JOYPAD_BUTTON_MAPPING[button] + 8;
+
+ 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);
+}
+
+static void
+retro_core_view_finalize (GObject *object)
+{
+ RetroCoreView *self = RETRO_CORE_VIEW (object);
+
+ g_clear_object (&self->core);
+ g_object_unref (self->display);
+ g_hash_table_unref (self->key_state);
+ g_hash_table_unref (self->mouse_button_state);
+ g_clear_object (&self->grabbed_screen);
+ g_clear_object (&self->grabbed_device);
+
+ G_OBJECT_CLASS (retro_core_view_parent_class)->finalize (object);
+}
+
+static void
+retro_core_view_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ RetroCoreView *self = RETRO_CORE_VIEW (object);
+
+ switch (prop_id) {
+ case PROP_CAN_GRAB_POINTER:
+ g_value_set_boolean (value, retro_core_view_get_can_grab_pointer (self));
+
+ break;
+ case PROP_SNAP_POINTER_TO_BORDERS:
+ g_value_set_boolean (value, retro_core_view_get_snap_pointer_to_borders (self));
+
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+
+ break;
+ }
+}
+
+static void
+retro_core_view_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ RetroCoreView *self = RETRO_CORE_VIEW (object);
+
+ switch (prop_id) {
+ case PROP_CAN_GRAB_POINTER:
+ retro_core_view_set_can_grab_pointer (self, g_value_get_boolean (value));
+
+ break;
+ case PROP_SNAP_POINTER_TO_BORDERS:
+ retro_core_view_set_snap_pointer_to_borders (self, g_value_get_boolean (value));
+
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+
+ break;
+ }
+}
+
+static void
+retro_core_view_class_init (RetroCoreViewClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = retro_core_view_finalize;
+ object_class->get_property = retro_core_view_get_property;
+ object_class->set_property = retro_core_view_set_property;
+
+ properties[PROP_CAN_GRAB_POINTER] =
+ g_param_spec_boolean ("can-grab-pointer",
+ "Can grab pointer",
+ "Whether the pointer can be grabbed",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB);
+ properties[PROP_SNAP_POINTER_TO_BORDERS] =
+ g_param_spec_boolean ("snap-pointer-to-borders",
+ "Snap pointer to borders",
+ "Wheter the pointer is considered to be on the border when it is out of the
display",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_NICK |
+ G_PARAM_STATIC_BLURB);
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_CAN_GRAB_POINTER,
properties[PROP_CAN_GRAB_POINTER]);
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SNAP_POINTER_TO_BORDERS,
properties[PROP_SNAP_POINTER_TO_BORDERS]);
+}
+
+RetroCoreView* retro_core_view_construct (GType object_type) {
+ RetroCoreView * self = NULL;
+ self = (RetroCoreView*) g_object_new (object_type, NULL);
+ return self;
+}
+
+static void
+retro_core_view_init (RetroCoreView *self)
+{
+ g_object_set ((GtkWidget*) self, "can-focus", TRUE, NULL);
+
+ self->display = g_object_ref_sink (retro_cairo_display_new ());
+ gtk_widget_set_visible (GTK_WIDGET (self->display), TRUE);
+ g_object_set (GTK_WIDGET (self->display), "can-focus", FALSE, NULL);
+ gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (self->display));
+
+ self->key_state = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_free);
+ self->mouse_button_state = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_free);
+
+ g_signal_connect_object (self, "key-press-event", (GCallback) retro_core_view_on_key_press_event, self, 0);
+ g_signal_connect_object (self, "key-release-event", (GCallback) retro_core_view_on_key_release_event,
self, 0);
+ g_signal_connect_object (self, "button-press-event", (GCallback) retro_core_view_on_button_press_event,
self, 0);
+ g_signal_connect_object (self, "button-release-event", (GCallback)
retro_core_view_on_button_release_event, self, 0);
+ g_signal_connect_object (self, "focus-out-event", (GCallback) retro_core_view_on_focus_out_event, self, 0);
+ g_signal_connect_object (self, "motion-notify-event", (GCallback) retro_core_view_on_motion_notify_event,
self, 0);
+}
+
+/* Public */
+
+void
+retro_core_view_set_core (RetroCoreView *self,
+ RetroCore *core)
+{
+ g_return_if_fail (self != NULL);
+
+ if (self->core == core)
+ return;
+
+ if (self->core != NULL) {
+ g_clear_object (&self->core);
+ retro_cairo_display_set_core (self->display, NULL);
+ }
+
+ if (core != NULL) {
+ self->core = g_object_ref (core);
+ retro_cairo_display_set_core (self->display, core);
+ }
+}
+
+RetroCairoDisplay *
+retro_core_view_get_display (RetroCoreView *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+
+ return self->display;
+}
+
+RetroInputDevice *
+retro_core_view_as_input_device (RetroCoreView *self,
+ RetroDeviceType device_type)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+
+ return RETRO_INPUT_DEVICE (retro_core_view_input_device_new (self, device_type));
+}
+
+gint16
+retro_core_view_get_input_state (RetroCoreView *self,
+ RetroDeviceType device,
+ guint index,
+ guint id)
+{
+ gint16 result;
+
+ g_return_val_if_fail (self != NULL, 0);
+
+ switch (device) {
+ case RETRO_DEVICE_TYPE_JOYPAD:
+ if (id >= RETRO_JOYPAD_ID_COUNT)
+ 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;
+ }
+ case RETRO_DEVICE_TYPE_POINTER:
+ switch (id) {
+ case RETRO_POINTER_ID_X:
+ return axis_to_retro_axis (self->pointer_x);
+ case RETRO_POINTER_ID_Y:
+ return axis_to_retro_axis (self->pointer_y);
+ case RETRO_POINTER_ID_PRESSED:
+ if (!self->pointer_is_on_display ||
+ retro_core_view_get_snap_pointer_to_borders (self))
+ return 0;
+
+ return retro_core_view_get_mouse_button_state (self, 1) ? 1 : 0;
+ default:
+ return 0;
+ }
+ default:
+ return 0;
+ }
+}
+
+guint64
+retro_core_view_get_device_capabilities (RetroCoreView *self)
+{
+ g_return_val_if_fail (self != NULL, 0);
+
+ return 1 << RETRO_DEVICE_TYPE_JOYPAD |
+ 1 << RETRO_DEVICE_TYPE_MOUSE |
+ 1 << RETRO_DEVICE_TYPE_POINTER;
+}
+
+gboolean
+retro_core_view_get_can_grab_pointer (RetroCoreView *self)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ return self->can_grab_pointer;
+}
+
+void
+retro_core_view_set_can_grab_pointer (RetroCoreView *self,
+ gboolean can_grab_pointer)
+{
+ g_return_if_fail (self != NULL);
+
+ if (self->can_grab_pointer == can_grab_pointer)
+ return;
+
+ self->can_grab_pointer = can_grab_pointer;
+
+ if (can_grab_pointer == FALSE &&
+ retro_core_view_get_is_pointer_grabbed (self))
+ retro_core_view_ungrab (self);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CAN_GRAB_POINTER]);
+}
+
+gboolean
+retro_core_view_get_snap_pointer_to_borders (RetroCoreView *self)
+{
+ g_return_val_if_fail (self != NULL, FALSE);
+
+ return self->snap_pointer_to_borders;
+}
+
+void
+retro_core_view_set_snap_pointer_to_borders (RetroCoreView *self,
+ gboolean snap_pointer_to_borders)
+{
+ g_return_if_fail (self != NULL);
+
+ if (self->snap_pointer_to_borders == snap_pointer_to_borders)
+ return;
+
+ self->snap_pointer_to_borders = snap_pointer_to_borders;
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SNAP_POINTER_TO_BORDERS]);
+}
+
+RetroCoreView *
+retro_core_view_new (void)
+{
+ return g_object_new (RETRO_TYPE_CORE_VIEW, NULL);
+}
diff --git a/retro-gtk/retro-core-view.h b/retro-gtk/retro-core-view.h
new file mode 100644
index 0000000..bf26158
--- /dev/null
+++ b/retro-gtk/retro-core-view.h
@@ -0,0 +1,40 @@
+#ifndef RETRO_CORE_VIEW_H
+#define RETRO_CORE_VIEW_H
+
+#include <gtk/gtk.h>
+#include "retro-device-type.h"
+#include "retro-input-device.h"
+
+G_BEGIN_DECLS
+
+// FIXME Remove as soon as possible.
+typedef struct _RetroCairoDisplay RetroCairoDisplay;
+// FIXME Remove as soon as possible.
+typedef struct _RetroCore RetroCore;
+
+#define RETRO_TYPE_CORE_VIEW (retro_core_view_get_type())
+
+G_DECLARE_FINAL_TYPE (RetroCoreView, retro_core_view, RETRO, CORE_VIEW, GtkEventBox)
+
+RetroCoreView *retro_core_view_new (void);
+
+void retro_core_view_set_core (RetroCoreView *self,
+ RetroCore *core);
+RetroCairoDisplay *retro_core_view_get_display (RetroCoreView *self);
+RetroInputDevice *retro_core_view_as_input_device (RetroCoreView *self,
+ RetroDeviceType device_type);
+gint16 retro_core_view_get_input_state (RetroCoreView *self,
+ RetroDeviceType device,
+ guint index,
+ guint id);
+guint64 retro_core_view_get_device_capabilities (RetroCoreView *self);
+gboolean retro_core_view_get_can_grab_pointer (RetroCoreView *self);
+void retro_core_view_set_can_grab_pointer (RetroCoreView *self,
+ gboolean can_grab_pointer);
+gboolean retro_core_view_get_snap_pointer_to_borders (RetroCoreView *self);
+void retro_core_view_set_snap_pointer_to_borders (RetroCoreView *self,
+ gboolean snap_pointer_to_borders);
+
+G_END_DECLS
+
+#endif /* RETRO_CORE_VIEW_H */
diff --git a/retro-gtk/retro-gtk.h b/retro-gtk/retro-gtk.h
index 281c1cf..8769435 100644
--- a/retro-gtk/retro-gtk.h
+++ b/retro-gtk/retro-gtk.h
@@ -5,6 +5,7 @@
#include "retro-analog-id.h"
#include "retro-analog-index.h"
+#include "retro-core-view.h"
#include "retro-device-type.h"
#include "retro-gtk-vala.h"
#include "retro-input-descriptor.h"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]