blob: de9cd73c95142081bc2c12d348b79e39a56b5281 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "garnet/bin/ui/root_presenter/display_flipper.h"
#if defined(countof)
// Workaround for compiler error due to Zircon defining countof() as a macro.
// Redefines countof() using GLM_COUNTOF(), which currently provides a more
// sophisticated implementation anyway.
#undef countof
#include <glm/glm.hpp>
#define countof(X) GLM_COUNTOF(X)
#else
// No workaround required.
#include <glm/glm.hpp>
#endif
#include <glm/ext.hpp>
#include <glm/gtc/constants.hpp>
namespace root_presenter {
namespace {
constexpr float kPi = glm::pi<float>();
}
DisplayFlipper::DisplayFlipper() {}
bool DisplayFlipper::OnEvent(const mozart::InputEventPtr& event,
scenic_lib::Scene* scene,
const scenic::DisplayInfoPtr& display_info,
bool* continue_dispatch_out) {
FXL_DCHECK(continue_dispatch_out);
bool invalidate = false;
if (event->is_pointer()) {
const mozart::PointerEventPtr& pointer = event->get_pointer();
// Mouse coordinates don't need to be transformed.
if (pointer->type != mozart::PointerEvent::Type::MOUSE) {
// Take into account screen rotation.
// TODO(MZ-389): Do this in Scenic instead.
if (display_flipped_) {
auto new_coords =
FlipPointerCoordinates(pointer->x, pointer->y, display_info);
pointer->x = new_coords.first;
pointer->y = new_coords.second;
*continue_dispatch_out = true;
}
}
} else if (event->is_keyboard()) {
const mozart::KeyboardEventPtr& kbd = event->get_keyboard();
const uint32_t kVolumeDownKey = 232;
if (kbd->modifiers == 0 &&
kbd->phase == mozart::KeyboardEvent::Phase::PRESSED &&
kbd->code_point == 0 && kbd->hid_usage == kVolumeDownKey) {
FlipDisplay(scene, display_info);
invalidate = true;
*continue_dispatch_out = false;
}
}
return invalidate;
}
void DisplayFlipper::FlipDisplay(scenic_lib::Scene* scene,
const scenic::DisplayInfoPtr& display_info) {
if (display_flipped_) {
scene->SetAnchor(0, 0, 0);
scene->SetRotation(0, 0, 0, 0);
scene->SetTranslation(0, 0, 0);
} else {
float device_pixel_ratio = display_info->device_pixel_ratio;
float logical_width = display_info->physical_width / device_pixel_ratio;
float logical_height = display_info->physical_height / device_pixel_ratio;
float anchor_x = logical_width / 2;
float anchor_y = logical_height / 2;
glm::quat display_rotation = glm::quat(glm::vec3(0, 0, kPi));
scene->SetAnchor(anchor_x, anchor_y, 0);
scene->SetRotation(display_rotation.x, display_rotation.y,
display_rotation.z, display_rotation.w);
scene->SetTranslation(display_info->physical_width / 2 - anchor_x,
display_info->physical_height / 2 - anchor_y, 0);
}
display_flipped_ = !display_flipped_;
}
std::pair<float, float> DisplayFlipper::FlipPointerCoordinates(
float x,
float y,
const scenic::DisplayInfoPtr& display_info) {
glm::vec4 pointer_vec(x, y, 0.f, 1.f);
float device_pixel_ratio = display_info->device_pixel_ratio;
float logical_width = display_info->physical_width / device_pixel_ratio;
float logical_height = display_info->physical_height / device_pixel_ratio;
glm::vec4 rotated_coords =
glm::translate(glm::vec3(logical_width / 2, logical_height / 2, 0)) *
glm::rotate(kPi, glm::vec3(0, 0, 1)) *
glm::translate(glm::vec3(-logical_width / 2, -logical_height / 2, 0)) *
pointer_vec;
return std::pair<float, float>(rotated_coords.x, rotated_coords.y);
}
} // namespace root_presenter