Merge pull request #580 from ubports/basic-touch

Add basic touchscreen support
This commit is contained in:
Simon Fels 2018-05-25 09:29:40 +02:00 committed by GitHub
commit b66af1210b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 133 additions and 3 deletions

View file

@ -70,6 +70,7 @@ Platform::Platform(
}
graphics::emugl::DisplayInfo::get()->set_resolution(display_frame.width(), display_frame.height());
display_frame_ = display_frame;
pointer_ = input_manager->create_device();
pointer_->set_name("anbox-pointer");
@ -93,6 +94,28 @@ Platform::Platform(
keyboard_->set_key_bit(BTN_MISC);
keyboard_->set_key_bit(KEY_OK);
touch_ = input_manager->create_device();
touch_->set_name("anbox-touch");
touch_->set_driver_version(1);
touch_->set_input_id({BUS_VIRTUAL, 4, 4, 4});
touch_->set_physical_location("none");
touch_->set_key_bit(BTN_TOUCH);
touch_->set_key_bit(BTN_TOOL_FINGER);
touch_->set_abs_bit(ABS_MT_SLOT);
touch_->set_abs_max(ABS_MT_SLOT, 10);
touch_->set_abs_bit(ABS_MT_TOUCH_MAJOR);
touch_->set_abs_max(ABS_MT_TOUCH_MAJOR, 127);
touch_->set_abs_bit(ABS_MT_TOUCH_MINOR);
touch_->set_abs_max(ABS_MT_TOUCH_MINOR, 127);
touch_->set_abs_bit(ABS_MT_POSITION_X);
touch_->set_abs_max(ABS_MT_POSITION_X, display_frame.width());
touch_->set_abs_bit(ABS_MT_POSITION_Y);
touch_->set_abs_max(ABS_MT_POSITION_Y, display_frame.height());
touch_->set_abs_bit(ABS_MT_TRACKING_ID);
touch_->set_abs_max(ABS_MT_TRACKING_ID, 10);
touch_->set_prop_bit(INPUT_PROP_DIRECT);
event_thread_ = std::thread(&Platform::process_events, this);
}
@ -130,12 +153,18 @@ void Platform::process_events() {
}
}
break;
case SDL_KEYDOWN:
case SDL_KEYUP:
if (keyboard_)
process_input_event(event);
break;
case SDL_MOUSEMOTION:
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEWHEEL:
case SDL_KEYDOWN:
case SDL_KEYUP:
case SDL_FINGERDOWN:
case SDL_FINGERUP:
case SDL_FINGERMOTION:
process_input_event(event);
break;
default:
@ -148,12 +177,18 @@ void Platform::process_events() {
void Platform::process_input_event(const SDL_Event &event) {
std::vector<input::Event> mouse_events;
std::vector<input::Event> keyboard_events;
std::vector<input::Event> touch_events;
std::int32_t x = 0;
std::int32_t y = 0;
std::int32_t rel_x = 0;
std::int32_t rel_y = 0;
SDL_Window *window = nullptr;
switch (event.type) {
// Mouse
case SDL_MOUSEBUTTONDOWN:
mouse_events.push_back({EV_KEY, BTN_LEFT, 1});
mouse_events.push_back({EV_SYN, SYN_REPORT, 0});
@ -196,6 +231,7 @@ void Platform::process_input_event(const SDL_Event &event) {
mouse_events.push_back(
{EV_REL, REL_WHEEL, static_cast<std::int32_t>(event.wheel.y)});
break;
// Keyboard
case SDL_KEYDOWN: {
const auto code = KeycodeConverter::convert(event.key.keysym.scancode);
if (code == KEY_RESERVED) break;
@ -208,13 +244,105 @@ void Platform::process_input_event(const SDL_Event &event) {
keyboard_events.push_back({EV_KEY, code, 0});
break;
}
// Touch screen
case SDL_FINGERDOWN: {
touch_events.push_back({EV_ABS, ABS_MT_TRACKING_ID, static_cast<std::int32_t>(event.tfinger.fingerId)});
touch_events.push_back({EV_ABS, ABS_MT_SLOT, 0});
touch_events.push_back({EV_KEY, BTN_TOUCH, 1});
touch_events.push_back({EV_KEY, BTN_TOOL_FINGER, 1});
window = SDL_GetWindowFromID(event.window.windowID);
if (window) {
SDL_GetWindowSize(window, &rel_x, &rel_y);
rel_x *= event.tfinger.x;
rel_y *= event.tfinger.y;
} else {
rel_x = display_frame_.width() * event.tfinger.x;
rel_y = display_frame_.height() * event.tfinger.y;
}
if (!single_window_) {
if (!window) {
break;
}
// As we get only absolute coordindates relative to our window we have to
// calculate the correct position based on the current focused window
SDL_GetWindowPosition(window, &x, &y);
x += rel_x;
y += rel_y;
} else {
// When running the whole Android system in a single window we don't
// need to reacalculate and the pointer position as they are already
// relative to our window.
x = rel_x;
y = rel_y;
}
touch_events.push_back({EV_ABS, ABS_MT_POSITION_X, x});
touch_events.push_back({EV_ABS, ABS_MT_POSITION_Y, y});
touch_events.push_back({EV_ABS, ABS_MT_TOUCH_MAJOR, 24});
touch_events.push_back({EV_ABS, ABS_MT_TOUCH_MINOR, 24});
touch_events.push_back({EV_SYN, SYN_REPORT, 0});
break;
}
case SDL_FINGERUP: {
touch_events.push_back({EV_ABS, ABS_MT_TRACKING_ID, -1});
touch_events.push_back({EV_ABS, ABS_MT_SLOT, 0});
touch_events.push_back({EV_KEY, BTN_TOUCH, 0});
touch_events.push_back({EV_KEY, BTN_TOOL_FINGER, 0});
touch_events.push_back({EV_SYN, SYN_REPORT, 0});
break;
}
case SDL_FINGERMOTION: {
touch_events.push_back({EV_ABS, ABS_MT_SLOT, 0});
window = SDL_GetWindowFromID(event.window.windowID);
if (window) {
SDL_GetWindowSize(window, &rel_x, &rel_y);
rel_x *= event.tfinger.x;
rel_y *= event.tfinger.y;
} else {
rel_x = display_frame_.width() * event.tfinger.x;
rel_y = display_frame_.height() * event.tfinger.y;
}
if (!single_window_) {
if (!window) {
break;
}
// As we get only absolute coordindates relative to our window we have to
// calculate the correct position based on the current focused window
SDL_GetWindowPosition(window, &x, &y);
x += rel_x;
y += rel_y;
} else {
// When running the whole Android system in a single window we don't
// need to reacalculate and the pointer position as they are already
// relative to our window.
x = rel_x;
y = rel_y;
}
touch_events.push_back({EV_ABS, ABS_MT_POSITION_X, x});
touch_events.push_back({EV_ABS, ABS_MT_POSITION_Y, y});
DEBUG("ABS_MT_POSITION: x: %i y: %i", x,y);
touch_events.push_back({EV_ABS, ABS_MT_TOUCH_MAJOR, 24});
touch_events.push_back({EV_ABS, ABS_MT_TOUCH_MINOR, 24});
touch_events.push_back({EV_SYN, SYN_REPORT, 0});
break;
}
default:
break;
}
if (mouse_events.size() > 0) pointer_->send_events(mouse_events);
if (keyboard_events.size() > 0) keyboard_->send_events(keyboard_events);
if (touch_events.size() > 0) touch_->send_events(touch_events);
}
Window::Id Platform::next_window_id() {

View file

@ -87,6 +87,8 @@ class Platform : public std::enable_shared_from_this<Platform>,
bool event_thread_running_;
std::shared_ptr<input::Device> pointer_;
std::shared_ptr<input::Device> keyboard_;
std::shared_ptr<input::Device> touch_;
graphics::Rect display_frame_;
bool window_size_immutable_ = false;
bool single_window_ = false;
};