Merge pull request #7061 from wiktorek140/sailfishos-touch

Sailfish OS  device build configuration connected with touch screen support required for device with this OS
This commit is contained in:
Twinaphex 2018-08-15 13:30:04 +02:00 committed by GitHub
commit 4d96fddf5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 377 additions and 4 deletions

View File

@ -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

View File

@ -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

View File

@ -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; i<MAX_TOUCHES; i++)
{
/* Use next empty slot */
if (!active_touch_positions[i].active)
{
active_touch_positions[num_active_touches].active = true;
active_touch_positions[num_active_touches].id = id;
active_touch_positions[num_active_touches].x = (unsigned) wl_fixed_to_int(x);
active_touch_positions[num_active_touches].y = (unsigned) wl_fixed_to_int(y);
num_active_touches++;
break;
}
}
}
}
static void reorder_touches()
{
int i, j;
if (num_active_touches == 0)
return;
for (i=0; i<MAX_TOUCHES; i++)
{
if (!active_touch_positions[i].active)
{
for (j=i+1; j<MAX_TOUCHES; j++)
{
if (active_touch_positions[j].active)
{
active_touch_positions[i].active = active_touch_positions[j].active;
active_touch_positions[i].id = active_touch_positions[j].id;
active_touch_positions[i].x = active_touch_positions[j].x;
active_touch_positions[i].y = active_touch_positions[j].y;
active_touch_positions[j].active = false;
active_touch_positions[j].id = -1;
active_touch_positions[j].x = (unsigned) 0;
active_touch_positions[j].y = (unsigned) 0;
break;
}
if (j == MAX_TOUCHES)
return;
}
}
}
}
static void touch_handle_up(void *data,
struct wl_touch *wl_touch,
uint32_t serial,
uint32_t time,
int32_t id)
{
int i;
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
for (i=0; i<MAX_TOUCHES; i++)
{
if (active_touch_positions[i].active && active_touch_positions[i].id == id)
{
active_touch_positions[i].active = false;
active_touch_positions[i].id = -1;
active_touch_positions[i].x = (unsigned) 0;
active_touch_positions[i].y = (unsigned) 0;
num_active_touches--;
}
}
reorder_touches(wl);
}
static void touch_handle_motion(void *data,
struct wl_touch *wl_touch,
uint32_t time,
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;
for (i=0; i<MAX_TOUCHES; i++)
{
if (active_touch_positions[i].active && active_touch_positions[i].id == id)
{
active_touch_positions[i].x = (unsigned) wl_fixed_to_int(x);
active_touch_positions[i].y = (unsigned) wl_fixed_to_int(y);
}
}
}
static void touch_handle_frame(void *data,
struct wl_touch *wl_touch)
{
/* TODO */
}
static void touch_handle_cancel(void *data,
struct wl_touch *wl_touch)
{
/* If i understand the spec correctly we have to reset all touches here
* since they were not ment for us anyway */
int i;
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
for (i=0; i<MAX_TOUCHES; i++)
{
active_touch_positions[i].active = false;
active_touch_positions[i].id = -1;
active_touch_positions[i].x = (unsigned) 0;
active_touch_positions[i].y = (unsigned) 0;
}
num_active_touches = 0;
}
static const struct wl_touch_listener touch_listener = {
touch_handle_down,
touch_handle_up,
touch_handle_motion,
touch_handle_frame,
touch_handle_cancel,
};
static void seat_handle_capabilities(void *data,
struct wl_seat *seat, unsigned caps)
struct wl_seat *seat, unsigned caps)
{
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
@ -354,6 +496,17 @@ struct wl_seat *seat, unsigned caps)
wl_pointer_destroy(wl->wl_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;i<MAX_TOUCHES;i++)
{
active_touch_positions[i].active = false;
active_touch_positions[i].id = -1;
active_touch_positions[i].x = (unsigned) 0;
active_touch_positions[i].y = (unsigned) 0;
}
flush_wayland_fd(&wl->input);
#ifdef HAVE_DBUS

View File

@ -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; id<MAX_TOUCHES; id++)
{
if (wayland_context_gettouchpos(wl, id, &touch_x, &touch_y))
{
wl->touches[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);
}

View File

@ -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