Commit e319550a authored by James Cook's avatar James Cook Committed by Commit Bot

cros: Fix touch HUD application to support multiple displays

Create one touch hud views::Widget per display and open/close new
widgets as displays are added and removed.

Bug: 840380
Test: run chrome --show-taps-app and add/remove displays
Change-Id: I21c87b35ec520bd1501f0cbf02c073d030c7ff64
Reviewed-on: https://chromium-review.googlesource.com/1058591
Commit-Queue: James Cook <jamescook@chromium.org>
Reviewed-by: default avatarMichael Wasserman <msw@chromium.org>
Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#558731}
parent f0425a24
......@@ -7,5 +7,6 @@ include_rules = [
"+services/service_manager/public",
"+services/ui/public",
"+ui/aura",
"+ui/display",
"+ui/views",
]
......@@ -15,6 +15,8 @@
#include "services/ui/public/cpp/property_type_converters.h"
#include "services/ui/public/interfaces/window_manager_constants.mojom.h"
#include "ui/aura/mus/property_converter.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/views/mus/aura_init.h"
#include "ui/views/mus/mus_client.h"
#include "ui/views/mus/pointer_watcher_event_router.h"
......@@ -23,6 +25,7 @@
#include "ui/views/widget/widget_delegate.h"
namespace touch_hud {
namespace {
// TouchHudUI handles events on the widget of the touch-hud app. After
// receiving touch events from PointerWatcher, it calls ash::TouchHudRenderer to
......@@ -31,7 +34,8 @@ class TouchHudUI : public views::WidgetDelegateView,
public views::PointerWatcher {
public:
explicit TouchHudUI(views::Widget* widget)
: touch_hud_renderer_(new ash::TouchHudRenderer(widget)) {
: touch_hud_renderer_(std::make_unique<ash::TouchHudRenderer>(widget)) {
// Watches moves so the user can drag around a touch point.
views::MusClient::Get()->pointer_watcher_event_router()->AddPointerWatcher(
this, true /* want_moves */);
}
......@@ -52,21 +56,31 @@ class TouchHudUI : public views::WidgetDelegateView,
void OnPointerEventObserved(const ui::PointerEvent& event,
const gfx::Point& location_in_screen,
gfx::NativeView target) override {
if (event.IsTouchPointerEvent())
touch_hud_renderer_->HandleTouchEvent(event);
if (!event.IsTouchPointerEvent())
return;
// Ignore taps on other displays.
if (!GetWidget()->GetWindowBoundsInScreen().Contains(location_in_screen))
return;
touch_hud_renderer_->HandleTouchEvent(event);
}
// TODO(jamescook): Don't leak this.
ash::TouchHudRenderer* touch_hud_renderer_;
std::unique_ptr<ash::TouchHudRenderer> touch_hud_renderer_;
DISALLOW_COPY_AND_ASSIGN(TouchHudUI);
};
} // namespace
TouchHudApplication::TouchHudApplication() : binding_(this) {
registry_.AddInterface<mash::mojom::Launchable>(base::BindRepeating(
&TouchHudApplication::Create, base::Unretained(this)));
}
TouchHudApplication::~TouchHudApplication() = default;
TouchHudApplication::~TouchHudApplication() {
display::Screen::GetScreen()->RemoveObserver(this);
}
void TouchHudApplication::OnStart() {
const bool register_path_provider = running_standalone_;
......@@ -78,6 +92,7 @@ void TouchHudApplication::OnStart() {
context()->QuitNow();
return;
}
display::Screen::GetScreen()->AddObserver(this);
Launch(mash::mojom::kWindow, mash::mojom::LaunchMode::DEFAULT);
}
......@@ -89,25 +104,43 @@ void TouchHudApplication::OnBindInterface(
}
void TouchHudApplication::Launch(uint32_t what, mash::mojom::LaunchMode how) {
if (!widget_) {
widget_ = new views::Widget;
views::Widget::InitParams params(
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
params.accept_events = false;
params.delegate = new TouchHudUI(widget_);
params.mus_properties[ui::mojom::WindowManager::kContainerId_InitProperty] =
mojo::ConvertTo<std::vector<uint8_t>>(
static_cast<int32_t>(ash::kShellWindowId_OverlayContainer));
params.show_state = ui::SHOW_STATE_FULLSCREEN;
widget_->Init(params);
widget_->Show();
} else {
widget_->Activate();
for (const display::Display& display :
display::Screen::GetScreen()->GetAllDisplays()) {
CreateWidgetForDisplay(display.id());
}
}
void TouchHudApplication::OnDisplayAdded(const display::Display& new_display) {
CreateWidgetForDisplay(new_display.id());
}
void TouchHudApplication::OnDisplayRemoved(
const display::Display& old_display) {
// Deletes the widget.
display_id_to_widget_.erase(old_display.id());
}
void TouchHudApplication::CreateWidgetForDisplay(int64_t display_id) {
std::unique_ptr<views::Widget> widget = std::make_unique<views::Widget>();
views::Widget::InitParams params(
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
params.accept_events = false;
params.delegate = new TouchHudUI(widget.get());
params.mus_properties[ui::mojom::WindowManager::kContainerId_InitProperty] =
mojo::ConvertTo<std::vector<uint8_t>>(
static_cast<int32_t>(ash::kShellWindowId_OverlayContainer));
params.mus_properties[ui::mojom::WindowManager::kDisplayId_InitProperty] =
mojo::ConvertTo<std::vector<uint8_t>>(display_id);
params.show_state = ui::SHOW_STATE_FULLSCREEN;
params.name = "TouchHud";
widget->Init(params);
widget->Show();
display_id_to_widget_[display_id] = std::move(widget);
}
void TouchHudApplication::Create(mash::mojom::LaunchableRequest request) {
binding_.Close();
binding_.Bind(std::move(request));
......
......@@ -5,11 +5,17 @@
#ifndef ASH_COMPONENTS_TOUCH_HUD_TOUCH_HUD_APPLICATION_H_
#define ASH_COMPONENTS_TOUCH_HUD_TOUCH_HUD_APPLICATION_H_
#include <stdint.h>
#include <map>
#include <memory>
#include "base/macros.h"
#include "mash/public/mojom/launchable.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/service.h"
#include "ui/display/display_observer.h"
namespace views {
class AuraInit;
......@@ -18,8 +24,11 @@ class Widget;
namespace touch_hud {
// Application that paints touch tap points as circles. Creates a fullscreen
// transparent widget on each display to draw the taps.
class TouchHudApplication : public service_manager::Service,
public mash::mojom::Launchable {
public mash::mojom::Launchable,
public display::DisplayObserver {
public:
TouchHudApplication();
~TouchHudApplication() override;
......@@ -36,11 +45,20 @@ class TouchHudApplication : public service_manager::Service,
// mojom::Launchable:
void Launch(uint32_t what, mash::mojom::LaunchMode how) override;
// display::DisplayObserver:
void OnDisplayAdded(const display::Display& new_display) override;
void OnDisplayRemoved(const display::Display& old_display) override;
// Creates the touch HUD widget for a display.
void CreateWidgetForDisplay(int64_t display_id);
void Create(mash::mojom::LaunchableRequest request);
service_manager::BinderRegistry registry_;
mojo::Binding<mash::mojom::Launchable> binding_;
views::Widget* widget_ = nullptr;
// Maps display::Display::id() to the touch HUD widget for that display.
std::map<int64_t, std::unique_ptr<views::Widget>> display_id_to_widget_;
std::unique_ptr<views::AuraInit> aura_init_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment