diff --git a/sunshine/input.cpp b/sunshine/input.cpp index 81a4920a..2ad4b7cf 100644 --- a/sunshine/input.cpp +++ b/sunshine/input.cpp @@ -13,8 +13,9 @@ extern "C" { #include "main.h" #include "config.h" #include "utility.h" -#include "platform/common.h" #include "thread_pool.h" +#include "input.h" +#include "platform/common.h" namespace input { @@ -45,6 +46,11 @@ void free_id(std::bitset &gamepad_mask, int id) { gamepad_mask[id] = false; } +touch_port_event_t touch_port_event; +platf::touch_port_t touch_port { + 0, 0, 0, 0 +}; + static util::TaskPool::task_id_t task_id {}; static std::unordered_map key_press {}; static std::array mouse_press {}; @@ -196,7 +202,20 @@ void passthrough(std::shared_ptr &input, PNV_ABS_MOUSE_MOVE_PACKET pack input->mouse_left_button_timeout = ENABLE_LEFT_BUTTON_DELAY; } - platf::abs_mouse(platf_input, util::endian::big(packet->x), util::endian::big(packet->y)); + if(touch_port_event->peek()) { + touch_port = *touch_port_event->pop(); + } + + float x = util::endian::big(packet->x); + float y = util::endian::big(packet->y); + + float width = util::endian::big(packet->width); + float height = util::endian::big(packet->height); + + auto scale_x = (float)touch_port.width / width; + auto scale_y = (float)touch_port.height / height; + + platf::abs_mouse(platf_input, touch_port, x * scale_x, y * scale_y); } void passthrough(std::shared_ptr &input, PNV_MOUSE_BUTTON_PACKET packet) { @@ -481,6 +500,7 @@ void reset(std::shared_ptr &input) { } void init() { + touch_port_event = std::make_unique(); platf_input = platf::input(); } diff --git a/sunshine/input.h b/sunshine/input.h index 71e1805c..16267619 100644 --- a/sunshine/input.h +++ b/sunshine/input.h @@ -5,7 +5,8 @@ #ifndef SUNSHINE_INPUT_H #define SUNSHINE_INPUT_H - +#include "thread_safe.h" +#include "platform/common.h" namespace input { struct input_t; @@ -14,9 +15,13 @@ void print(void *input); void reset(std::shared_ptr &input); void passthrough(std::shared_ptr &input, std::vector &&input_data); + void init(); std::shared_ptr alloc(); + +using touch_port_event_t = std::unique_ptr>; +extern touch_port_event_t touch_port_event; } #endif //SUNSHINE_INPUT_H diff --git a/sunshine/platform/common.h b/sunshine/platform/common.h index c8675bfc..69e41922 100644 --- a/sunshine/platform/common.h +++ b/sunshine/platform/common.h @@ -58,6 +58,18 @@ using namespace std::literals; return "unknown"sv; } +// Dimensions for touchscreen input +struct touch_port_t { + std::uint32_t offset_x, offset_y; + std::uint32_t width, height; + + constexpr touch_port_t( + std::uint32_t offset_x, std::uint32_t offset_y, + std::uint32_t width, std::uint32_t height) noexcept : + offset_x { offset_x }, offset_y { offset_y }, + width { width }, height { height } {}; +}; + struct gamepad_state_t { std::uint16_t buttonFlags; std::uint8_t lt; @@ -146,7 +158,7 @@ std::shared_ptr display(dev_type_e hwdevice_type); input_t input(); void move_mouse(input_t &input, int deltaX, int deltaY); -void abs_mouse(input_t &input, int x, int y); +void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y); void button_mouse(input_t &input, int button, bool release); void scroll(input_t &input, int distance); void keyboard(input_t &input, uint16_t modcode, bool release); diff --git a/sunshine/platform/linux/input.cpp b/sunshine/platform/linux/input.cpp index df34e6e8..8b4578bc 100644 --- a/sunshine/platform/linux/input.cpp +++ b/sunshine/platform/linux/input.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -29,6 +30,11 @@ using uinput_t = util::safe_ptr; using keyboard_t = util::safe_ptr_v2; +constexpr touch_port_t target_touch_port { + 0, 0, + 19200, 12000 +}; + struct input_raw_t { public: void clear_touchscreen() { @@ -136,11 +142,14 @@ public: keyboard_t keyboard; }; -void abs_mouse(input_t &input, int x, int y) { +void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { auto touchscreen = ((input_raw_t*)input.get())->touch_input.get(); - libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_X, x); - libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_Y, y); + auto scaled_x = (int)std::lround(x * ((float)target_touch_port.width / (float)touch_port.width)); + auto scaled_y = (int)std::lround(y * ((float)target_touch_port.height / (float)touch_port.height)); + + libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_X, scaled_x + touch_port.offset_x); + libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_Y, scaled_y + touch_port.offset_y); libevdev_uinput_write_event(touchscreen, EV_KEY, BTN_TOOL_FINGER, 1); libevdev_uinput_write_event(touchscreen, EV_KEY, BTN_TOOL_FINGER, 0); @@ -461,7 +470,7 @@ evdev_t touchscreen() { input_absinfo absx { 0, 0, - 1919, + target_touch_port.width, 1, 0, 28 @@ -470,7 +479,7 @@ evdev_t touchscreen() { input_absinfo absy { 0, 0, - 1199, + target_touch_port.height, 1, 0, 28 diff --git a/sunshine/video.cpp b/sunshine/video.cpp index c6befe8d..88dfd01b 100644 --- a/sunshine/video.cpp +++ b/sunshine/video.cpp @@ -38,10 +38,6 @@ void free_buffer(AVBufferRef *ref) { av_buffer_unref(&ref); } -void free_packet(AVPacket *packet) { - av_packet_free(&packet); -} - namespace nv { enum class profile_h264_e : int { @@ -70,8 +66,6 @@ platf::pix_fmt_e map_pix_fmt(AVPixelFormat fmt); void sw_img_to_frame(const platf::img_t &img, frame_t &frame); void dxgi_img_to_frame(const platf::img_t &img, frame_t &frame); util::Either dxgi_make_hwdevice_ctx(platf::hwdevice_t *hwdevice_ctx); -void dxgi_img_to_frame(const platf::img_t &img, frame_t &frame); -util::Either dxgi_make_hwdevice_ctx(platf::hwdevice_t *hwdevice_ctx); util::Either make_hwdevice_ctx(AVHWDeviceType type, void *hwdevice_ctx); int hwframe_ctx(ctx_t &ctx, buffer_t &hwdevice, AVPixelFormat format); @@ -183,7 +177,7 @@ public: session_t(ctx_t &&ctx, frame_t &&frame, util::wrap_ptr &&device) : ctx { std::move(ctx) }, frame { std::move(frame) }, device { std::move(device) } {} - session_t(session_t &&other) : + session_t(session_t &&other) noexcept : ctx { std::move(other.ctx) }, frame { std::move(other.frame) }, device { std::move(other.device) } {} // Ensure objects are destroyed in the correct order @@ -862,6 +856,7 @@ encode_e encode_run_sync(std::vector> &synce return encode_e::error; } + input::touch_port_event->raise(0, 0, img->width, img->height); std::vector synced_sessions; for(auto &ctx : synced_session_ctxs) { auto synced_session = make_synced_session(disp.get(), encoder, *img, *ctx); @@ -1069,6 +1064,7 @@ void capture_async( if(display->dummy_img(dummy_img.get())) { return; } + input::touch_port_event->raise(0, 0, dummy_img->width, dummy_img->height); images->raise(std::move(dummy_img)); encode_run( diff --git a/sunshine/video.h b/sunshine/video.h index e4560e05..b628f303 100644 --- a/sunshine/video.h +++ b/sunshine/video.h @@ -6,6 +6,7 @@ #define SUNSHINE_VIDEO_H #include "thread_safe.h" +#include "input.h" #include "platform/common.h" extern "C" { @@ -14,16 +15,27 @@ extern "C" { struct AVPacket; namespace video { -void free_packet(AVPacket *packet); struct packet_raw_t : public AVPacket { - template - explicit packet_raw_t(P *user_data) : channel_data { user_data } { - av_init_packet(this); + void init_packet() { + pts = AV_NOPTS_VALUE; + dts = AV_NOPTS_VALUE; + pos = -1; + duration = 0; + flags = 0; + stream_index = 0; + buf = nullptr; + side_data = nullptr; + side_data_elems = 0; } - explicit packet_raw_t(std::nullptr_t null) : channel_data { nullptr } { - av_init_packet(this); + template + explicit packet_raw_t(P *user_data) : channel_data { user_data } { + init_packet(); + } + + explicit packet_raw_t(std::nullptr_t) : channel_data { nullptr } { + init_packet(); } ~packet_raw_t() {