diff --git a/Makefile.common b/Makefile.common index 3cd2c39654..5f4106db23 100644 --- a/Makefile.common +++ b/Makefile.common @@ -960,6 +960,9 @@ endif ifeq ($(HAVE_WAYLAND), 1) OBJ += gfx/drivers_context/wayland_ctx.o \ input/drivers/wayland_input.o + ifeq ($(HAVE_EGL), 1) + LIBS += $(EGL_LIBS) + endif DEFINES += $(WAYLAND_CFLAGS) $(WAYLAND_CURSOR_CFLAGS) LIBS += $(WAYLAND_LIBS) $(WAYLAND_CURSOR_LIBS) endif diff --git a/gfx/common/wayland_common.h b/gfx/common/wayland_common.h index e48f450907..3cbedb9048 100644 --- a/gfx/common/wayland_common.h +++ b/gfx/common/wayland_common.h @@ -28,6 +28,16 @@ #define UDEV_KEY_MAX 0x2ff #define UDEV_MAX_KEYS (UDEV_KEY_MAX + 7) / 8 +#define MAX_TOUCHES 16 + +typedef struct +{ + bool active; + int16_t x; + int16_t y; +} wayland_touch_data_t; + + typedef struct input_ctx_wayland_data { /* Wayland uses Linux keysyms. */ @@ -49,6 +59,9 @@ typedef struct input_ctx_wayland_data const input_device_driver_t *joypad; bool blocked; + + wayland_touch_data_t touches[MAX_TOUCHES]; + } input_ctx_wayland_data_t; #endif diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index 2462fc5ef0..7778e6c280 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -51,6 +51,19 @@ #include "../../input/input_driver.h" #include "../../input/input_keymaps.h" + +typedef struct touch_pos +{ + bool active; + int32_t id; + unsigned x; + unsigned y; +} touch_pos_t; + +static int num_active_touches; +static touch_pos_t active_touch_positions[MAX_TOUCHES]; + + typedef struct gfx_ctx_wayland_data { #ifdef HAVE_EGL @@ -70,6 +83,7 @@ typedef struct gfx_ctx_wayland_data struct wl_shell *shell; struct wl_keyboard *wl_keyboard; struct wl_pointer *wl_pointer; + struct wl_touch *wl_touch; struct wl_seat *seat; struct wl_shm *shm; unsigned swap_interval; @@ -329,8 +343,136 @@ static const struct wl_pointer_listener pointer_listener = { pointer_handle_axis, }; +static void touch_handle_down(void *data, + struct wl_touch *wl_touch, + uint32_t serial, + uint32_t time, + struct wl_surface *surface, + int32_t id, + wl_fixed_t x, + wl_fixed_t y) +{ + int i; + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + if (num_active_touches < MAX_TOUCHES) + { + for (i=0; iwl_pointer); wl->wl_pointer = NULL; } + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !wl->wl_touch) + { + wl->wl_touch = wl_seat_get_touch(seat); + wl_touch_add_listener(wl->wl_touch, &touch_listener, wl); + } + else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && wl->wl_touch) + { + wl_touch_destroy(wl->wl_touch); + wl->wl_touch = NULL; + } + } static void seat_handle_name(void *data, struct wl_seat *seat, const char *name) @@ -368,6 +521,22 @@ static const struct wl_seat_listener seat_listener = { seat_handle_name, }; +/* Touch handle functions */ + +bool wayland_context_gettouchpos(void *data, unsigned id, + unsigned* touch_x, unsigned* touch_y) +{ + gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; + + if (id >= MAX_TOUCHES) + return false; + *touch_x = active_touch_positions[id].x; + *touch_y = active_touch_positions[id].y; + return active_touch_positions[id].active; +} + + + /* Shell surface callbacks. */ static void shell_surface_handle_ping(void *data, struct wl_shell_surface *shell_surface, @@ -503,7 +672,7 @@ static void registry_handle_global(void *data, struct wl_registry *reg, wl->shm = (struct wl_shm*)wl_registry_bind(reg, id, &wl_shm_interface, 1); else if (string_is_equal(interface, "wl_seat")) { - wl->seat = (struct wl_seat*)wl_registry_bind(reg, id, &wl_seat_interface, 4); + wl->seat = (struct wl_seat*)wl_registry_bind(reg, id, &wl_seat_interface, 2); wl_seat_add_listener(wl->seat, &seat_listener, wl); } } @@ -568,6 +737,8 @@ static void gfx_ctx_wl_destroy_resources(gfx_ctx_wayland_data_t *wl) wl_keyboard_destroy(wl->wl_keyboard); if (wl->wl_pointer) wl_pointer_destroy(wl->wl_pointer); + if (wl->wl_touch) + wl_touch_destroy(wl->wl_touch); if (wl->cursor.theme) wl_cursor_theme_destroy(wl->cursor.theme); @@ -776,6 +947,7 @@ static bool gfx_ctx_wl_get_metrics(void *data, static void *gfx_ctx_wl_init(video_frame_info_t *video_info, void *video_driver) { + int i; #ifdef HAVE_OPENGL static const EGLint egl_attribs_gl[] = { WL_EGL_ATTRIBS_BASE, @@ -924,12 +1096,23 @@ static void *gfx_ctx_wl_init(video_frame_info_t *video_info, void *video_driver) break; } + wl->input.keyboard_focus = true; wl->input.mouse.focus = true; wl->cursor.surface = wl_compositor_create_surface(wl->compositor); wl->cursor.theme = wl_cursor_theme_load(NULL, 16, wl->shm); wl->cursor.default_cursor = wl_cursor_theme_get_cursor(wl->cursor.theme, "left_ptr"); + + num_active_touches = 0; + for (i=0;iinput); #ifdef HAVE_DBUS diff --git a/input/drivers/wayland_input.c b/input/drivers/wayland_input.c index 0363624320..782311f090 100644 --- a/input/drivers/wayland_input.c +++ b/input/drivers/wayland_input.c @@ -50,6 +50,7 @@ /* TODO/FIXME - * fix game focus toggle */ + /* Forward declaration */ void flush_wayland_fd(void *data); @@ -98,6 +99,32 @@ static int16_t input_wl_lightgun_state(input_ctx_wayland_data_t *wl, unsigned id return 0; } +static void input_wl_touch_pool(void *data) +{ + int id; + input_ctx_wayland_data_t *wl = (input_ctx_wayland_data_t*)data; + + if (!wl) + return; + + unsigned touch_x = 0; + unsigned touch_y = 0; + + for (id=0; idtouches[id].active = true; + } + else + { + wl->touches[id].active = false; + } + wl->touches[id].x = touch_x; + wl->touches[id].y = touch_y; + } +} + static void input_wl_poll(void *data) { input_ctx_wayland_data_t *wl = (input_ctx_wayland_data_t*)data; @@ -119,6 +146,8 @@ static void input_wl_poll(void *data) if (wl->joypad) wl->joypad->poll(); + + input_wl_touch_pool(wl); } static int16_t input_wl_analog_pressed(input_ctx_wayland_data_t *wl, @@ -175,8 +204,9 @@ static int16_t input_wl_pointer_state(input_ctx_wayland_data_t *wl, vp.full_height = 0; if (!(video_driver_translate_coord_viewport_wrap(&vp, - wl->mouse.x, wl->mouse.y, + wl->mouse.x, wl->mouse.y, &res_x, &res_y, &res_screen_x, &res_screen_y))) + return 0; if (screen) @@ -203,6 +233,59 @@ static int16_t input_wl_pointer_state(input_ctx_wayland_data_t *wl, return 0; } +static int16_t input_wl_touch_state(input_ctx_wayland_data_t *wl, + unsigned idx, unsigned id, bool screen) +{ + struct video_viewport vp; + + bool inside = false; + int16_t res_x = 0; + int16_t res_y = 0; + int16_t res_screen_x = 0; + int16_t res_screen_y = 0; + + vp.x = 0; + vp.y = 0; + vp.width = 0; + vp.height = 0; + vp.full_width = 0; + vp.full_height = 0; + + if (idx > MAX_TOUCHES) + return 0; + + if (!(video_driver_translate_coord_viewport_wrap(&vp, + wl->touches[idx].x, wl->touches[idx].y, + &res_x, &res_y, &res_screen_x, &res_screen_y))) + return 0; + + if (screen) + { + res_x = res_screen_x; + res_y = res_screen_y; + } + + inside = (res_x >= -0x7fff) && (res_y >= -0x7fff); + + if (!inside) + return 0; + + switch (id) + { + case RETRO_DEVICE_ID_POINTER_X: + return res_x; + case RETRO_DEVICE_ID_POINTER_Y: + return res_y; + case RETRO_DEVICE_ID_POINTER_PRESSED: + return wl->touches[idx].active; + } + + return 0; +} + + + + static int16_t input_wl_state(void *data, rarch_joypad_info_t joypad_info, const struct retro_keybind **binds, @@ -233,11 +316,15 @@ static int16_t input_wl_state(void *data, return input_wl_mouse_state(wl, id, true); case RETRO_DEVICE_POINTER: - case RARCH_DEVICE_POINTER_SCREEN: if (idx == 0) return input_wl_pointer_state(wl, idx, id, device == RARCH_DEVICE_POINTER_SCREEN); break; + case RARCH_DEVICE_POINTER_SCREEN: + if (idx < MAX_TOUCHES) + return input_wl_touch_state(wl, idx, id, + device == RARCH_DEVICE_POINTER_SCREEN); + break; case RETRO_DEVICE_LIGHTGUN: return input_wl_lightgun_state(wl, id); } diff --git a/pkg/sailfishos/retroarch-sailfishos.spec b/pkg/sailfishos/retroarch-sailfishos.spec new file mode 100644 index 0000000000..e5e54448b2 --- /dev/null +++ b/pkg/sailfishos/retroarch-sailfishos.spec @@ -0,0 +1,87 @@ +Name: retroarch +Version: 1.7.3 +Release: v1.2 +Summary: Official reference frontend for libretro + +Group: Applications/Emulators +License: GPLv3+ +URL: http://www.libretro.com/ + +BuildRequires: libxml2-devel +BuildRequires: mesa-llvmpipe-libwayland-egl-devel +BuildRequires: pulseaudio-devel +BuildRequires: OpenAL-devel +BuildRequires: libxkbcommon-devel +BuildRequires: zlib-devel +BuildRequires: freetype-devel +#BuildRequires: ffmpeg-devel +BuildRequires: SDL2-devel +BuildRequires: SDL2_image-devel +#Requires libusb 1.0.16 +#BuildRequires: libusb-devel + +%description +RetroArch is the official reference frontend for the libretro API. +Libretro is a simple but powerful development interface that allows for the +easy creation of emulators, games and multimedia applications that can plug +straight into any libretro-compatible frontend. This development interface +is open to others so that they can run these pluggable emulator and game +cores also in their own programs or devices. + +%build +# No autotools, custom configure script +%ifarch armv7hl +./configure --prefix=%{_prefix} --enable-opengles --enable-neon --enable-egl --enable-wayland +%else +./configure --prefix=%{_prefix} --enable-gles +%endif +make %{?_smp_mflags} + + +%install +make install DESTDIR=%{buildroot} +# Configuration changes +sed -i \ + 's|^# libretro_directory =.*|libretro_directory = "~/.config/retroarch/cores/"|; + s|^# libretro_info_path =.*|libretro_info_path = "~/.config/retroarch/cores/"|; + s|^# joypad_autoconfig_dir =.*|joypad_autoconfig_dir = "/etc/retroarch/joypad"|; + s|^# video_fullscreen =.*|video_fullscreen = "true"|; + s|^# menu_driver =.*|menu_driver = "glui"|; + s|^# menu_pointer_enable =.*|menu_pointer_enable = "true"|; + s|^# input_driver =.*|input_driver = "wayland"|' \ + %{buildroot}/etc/retroarch.cfg + +%ifarch armv7hl +sed -i \ + 's|^# core_updater_buildbot_url =.*|core_updater_buildbot_url = "http://buildbot.libretro.com/nightly/linux/armhf/latest/"|;' \ + %{buildroot}/etc/retroarch.cfg +%endif + +#Disabling audio till it's fixed +sed -i \ + 's|^# audio_enable.*|audio_enable = "false"|' \ + %{buildroot}/etc/retroarch.cfg + +sed -i \ + 's|^Exec=retroarch|Exec=retroarch --menu|' \ + %{buildroot}/usr/share/applications/retroarch.desktop + + # Install icon file in the correct place + mkdir -p %{buildroot}/usr/share/icons/hicolor/86x86/apps + install -m 644 "./media/retroarch-96x96.png" "%{buildroot}/usr/share/icons/hicolor/86x86/apps/retroarch.png" + rm "%{buildroot}/usr/share/pixmaps/retroarch.svg" + rmdir "%{buildroot}/usr/share/pixmaps" + +%files +%doc README.md +%config /etc/retroarch.cfg +%{_prefix}/bin/retroarch +%{_prefix}/bin/retroarch-cg2glsl +%{_prefix}/share/applications/retroarch.desktop +%{_prefix}/share/man/man6/*.6* +%{_prefix}/share/icons/hicolor/86x86/apps/retroarch.* +%{_prefix}/share/doc/retroarch/* +%changelog + + +