Skip to content

Commit

Permalink
TooltipLacros: Ash implementation of Server side tooltip for Lacros.
Browse files Browse the repository at this point in the history
This CL adds Ash implementation for Server side tooltip.
Lacros uses extended wayland protocol to show/hide tooltip and interact
with Ash when Lacros needs to show/hide tooltip.

This is a part of tooltip fix to move tooltip mechanism from Lacros
to Ash.
See crrev.com/c/3878453 for PoC.

Bug: 1338597
Change-Id: I7c2605f686b6cc61eb179d381e878ce27f5f8040
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4012189
Reviewed-by: Mitsuru Oshima <oshima@chromium.org>
Commit-Queue: Eriko Kurimoto <elkurin@chromium.org>
Reviewed-by: Scott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1077498}
  • Loading branch information
elkurin authored and Chromium LUCI CQ committed Nov 30, 2022
1 parent af9c82b commit f66bb1f
Show file tree
Hide file tree
Showing 25 changed files with 416 additions and 20 deletions.
15 changes: 15 additions & 0 deletions components/exo/shell_surface_base.cc
Expand Up @@ -301,6 +301,7 @@ ShellSurfaceBase::ShellSurfaceBase(Surface* surface,
container_(container),
can_minimize_(can_minimize) {
WMHelper::GetInstance()->AddActivationObserver(this);
WMHelper::GetInstance()->AddTooltipObserver(this);
surface->AddSurfaceObserver(this);
SetRootSurface(surface);
host_window()->Show();
Expand Down Expand Up @@ -348,6 +349,7 @@ ShellSurfaceBase::~ShellSurfaceBase() {
root_surface()->RemoveSurfaceObserver(this);
if (has_grab_)
WMHelper::GetInstance()->GetCaptureClient()->RemoveObserver(this);
WMHelper::GetInstance()->RemoveTooltipObserver(this);
CHECK(!views::WidgetObserver::IsInObserverList());
}

Expand Down Expand Up @@ -1289,6 +1291,19 @@ void ShellSurfaceBase::OnWindowActivated(ActivationReason reason,
}
}

////////////////////////////////////////////////////////////////////////////////
// wm::TooltipObserver overrides:

void ShellSurfaceBase::OnTooltipShown(aura::Window* target,
const std::u16string& text,
const gfx::Rect& bounds) {
root_surface()->OnTooltipShown(text, bounds);
}

void ShellSurfaceBase::OnTooltipHidden(aura::Window* target) {
root_surface()->OnTooltipHidden();
}

// Returns true if surface is currently being resized.
bool ShellSurfaceBase::IsDragged() const {
if (in_extended_drag_)
Expand Down
14 changes: 13 additions & 1 deletion components/exo/shell_surface_base.h
Expand Up @@ -28,6 +28,7 @@
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/widget/widget_observer.h"
#include "ui/wm/public/activation_change_observer.h"
#include "ui/wm/public/tooltip_observer.h"

namespace ash {
class WindowState;
Expand All @@ -52,7 +53,8 @@ class ShellSurfaceBase : public SurfaceTreeHost,
public views::WidgetDelegate,
public views::WidgetObserver,
public views::View,
public wm::ActivationChangeObserver {
public wm::ActivationChangeObserver,
public wm::TooltipObserver {
public:
// The |origin| is the initial position in screen coordinates. The position
// specified as part of the geometry is relative to the shell surface.
Expand Down Expand Up @@ -251,6 +253,10 @@ class ShellSurfaceBase : public SurfaceTreeHost,
void OnContentSizeChanged(Surface*) override {}
void OnFrameLockingChanged(Surface*, bool) override {}
void OnDeskChanged(Surface*, int) override {}
void OnTooltipShown(Surface* surface,
const std::u16string& text,
const gfx::Rect& bounds) override {}
void OnTooltipHidden(Surface* surface) override {}

// CaptureClientObserver:
void OnCaptureChanged(aura::Window* lost_capture,
Expand Down Expand Up @@ -295,6 +301,12 @@ class ShellSurfaceBase : public SurfaceTreeHost,
aura::Window* gained_active,
aura::Window* lost_active) override;

// wm::TooltipObserver:
void OnTooltipShown(aura::Window* target,
const std::u16string& text,
const gfx::Rect& bounds) override;
void OnTooltipHidden(aura::Window* target) override;

// ui::AcceleratorTarget:
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;

Expand Down
11 changes: 11 additions & 0 deletions components/exo/surface.cc
Expand Up @@ -1688,6 +1688,17 @@ void Surface::OnDeskChanged(int state) {
observer.OnDeskChanged(this, state);
}

void Surface::OnTooltipShown(const std::u16string& text,
const gfx::Rect& bounds) {
for (SurfaceObserver& observer : observers_)
observer.OnTooltipShown(this, text, bounds);
}

void Surface::OnTooltipHidden() {
for (SurfaceObserver& observer : observers_)
observer.OnTooltipHidden(this);
}

void Surface::MoveToDesk(int desk_index) {
if (delegate_)
delegate_->MoveToDesk(desk_index);
Expand Down
6 changes: 6 additions & 0 deletions components/exo/surface.h
Expand Up @@ -419,6 +419,12 @@ class Surface final : public ui::PropertyHandler {
// Starts or ends throttling on the surface.
void ThrottleFrameRate(bool on);

// Informs tooltip is shown.
void OnTooltipShown(const std::u16string& text, const gfx::Rect& bounds);

// Informs tooltip is hidden.
void OnTooltipHidden();

// If true is set, if this window has a focus, key events should be sent to
// the app, even if it is an ash shortcut (with some exceptions).
// See exo::Keyboard for more details.
Expand Down
14 changes: 14 additions & 0 deletions components/exo/surface_observer.h
Expand Up @@ -6,6 +6,11 @@
#define COMPONENTS_EXO_SURFACE_OBSERVER_H_

#include <cstdint>
#include <string>

namespace gfx {
class Rect;
}

namespace exo {
class Surface;
Expand Down Expand Up @@ -45,6 +50,15 @@ class SurfaceObserver {
// Starts or ends throttling.
virtual void ThrottleFrameRate(bool on) {}

// Called when tooltip is shown.
// `bounds` is relative to `surface`.
virtual void OnTooltipShown(Surface* surface,
const std::u16string& text,
const gfx::Rect& bounds) {}

// Called when tooltip is hidden.
virtual void OnTooltipHidden(Surface* surface) {}

protected:
virtual ~SurfaceObserver() {}
};
Expand Down
2 changes: 2 additions & 0 deletions components/exo/test/exo_test_base_views.cc
Expand Up @@ -34,6 +34,8 @@ class WMHelperTester : public WMHelper, public VSyncTimingManager::Delegate {
void AddActivationObserver(wm::ActivationChangeObserver* observer) override {}
void RemoveActivationObserver(
wm::ActivationChangeObserver* observer) override {}
void AddTooltipObserver(wm::TooltipObserver* observer) override {}
void RemoveTooltipObserver(wm::TooltipObserver* observer) override {}
void AddFocusObserver(aura::client::FocusChangeObserver* observer) override {}
void RemoveFocusObserver(
aura::client::FocusChangeObserver* observer) override {}
Expand Down
53 changes: 51 additions & 2 deletions components/exo/wayland/protocol/aura-shell.xml
Expand Up @@ -24,7 +24,7 @@
DEALINGS IN THE SOFTWARE.
</copyright>

<interface name="zaura_shell" version="46">
<interface name="zaura_shell" version="47">
<description summary="aura_shell">
The global interface exposing aura shell capabilities is used to
instantiate an interface extension for a wl_surface object.
Expand Down Expand Up @@ -160,7 +160,7 @@
</request>
</interface>

<interface name="zaura_surface" version="38">
<interface name="zaura_surface" version="47">
<description summary="aura shell interface to a wl_surface">
An additional interface to a wl_surface object, which allows the
client to access aura shell specific functionality for surface.
Expand Down Expand Up @@ -535,6 +535,55 @@
See zaura_shell.release for destructor naming.
</description>
</request>

<!-- Version 47 additions -->
<request name="show_tooltip" since="47">
<description summary="show tooltip window">
Show tooltip on server side.
`x` and `y` specifies the location of tooltip in surface local coordinates.
`hide_delay` and `show_delay` specify the time to wait until showing/hiding tooltip.
The unit is millisecond.
</description>
<arg name="text" type="string"/>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
<arg name="tooltip_trigger" type="uint" summary="tooltip_trigger enum"/>
<arg name="show_delay" type="uint" summary="delay to show tooltip in millisecond"/>
<arg name="hide_delay" type="uint" summary="delay to hide tooltip in millisecond"/>
</request>

<enum name="tooltip_trigger">
<description summary="type of tooltip trigger">
Describes what triggered tooltip
</description>
<entry name="cursor" value="0" summary="triggered by cursor"/>
<entry name="keyboard" value="1" summary="triggered by keyboard"/>
</enum>

<request name="hide_tooltip" since="47">
<description summary="hide tooltip window">
Hide tooltip created by the same client on server side.
This may be called even when there is no tooltip window to hide.
</description>
</request>

<event name="tooltip_shown" since="47">
<description summary="tooltip is shown by server side">
Informs the client that the tooltip is shown with states.
`x` and `y` specifies the location of tooltip in surface local coordinates.
</description>
<arg name="text" type="string"/>
<arg name="x" type="int"/>
<arg name="y" type="int"/>
<arg name="width" type="int"/>
<arg name="height" type="int"/>
</event>

<event name="tooltip_hidden" since="47">
<description summary="tooltip is hidden by server side">
Informs the client that the tooltip is hidden.
</description>
</event>
</interface>

<interface name="zaura_output" version="45">
Expand Down
71 changes: 71 additions & 0 deletions components/exo/wayland/zaura_shell.cc
Expand Up @@ -51,6 +51,8 @@
#include "ui/display/manager/display_manager.h"
#include "ui/display/manager/display_manager_util.h"
#include "ui/display/screen.h"
#include "ui/views/corewm/tooltip.h"
#include "ui/views/corewm/tooltip_controller.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h"
#include "ui/wm/public/activation_client.h"
Expand Down Expand Up @@ -120,6 +122,18 @@ zaura_surface_occlusion_state WaylandOcclusionState(
return ZAURA_SURFACE_OCCLUSION_STATE_UNKNOWN;
}

views::corewm::TooltipTrigger TooltipTrigger(uint32_t tooltip_trigger) {
switch (tooltip_trigger) {
case ZAURA_SURFACE_TOOLTIP_TRIGGER_CURSOR:
return views::corewm::TooltipTrigger::kCursor;
case ZAURA_SURFACE_TOOLTIP_TRIGGER_KEYBOARD:
return views::corewm::TooltipTrigger::kKeyboard;
default:
VLOG(2) << "Unknown aura-shell tooltip trigger: " << tooltip_trigger;
return views::corewm::TooltipTrigger::kCursor;
}
}

void aura_surface_set_frame(wl_client* client,
wl_resource* resource,
uint32_t type) {
Expand Down Expand Up @@ -274,6 +288,23 @@ void aura_surface_release(wl_client* client, wl_resource* resource) {
wl_resource_destroy(resource);
}

void aura_surface_show_tooltip(wl_client* client,
wl_resource* resource,
const char* text,
int32_t x,
int32_t y,
uint32_t trigger,
uint32_t show_delay,
uint32_t hide_delay) {
GetUserDataAs<AuraSurface>(resource)->ShowTooltip(
text, gfx::Point(x, y), trigger, base::Milliseconds((uint64_t)show_delay),
base::Milliseconds((uint64_t)hide_delay));
}

void aura_surface_hide_tooltip(wl_client* client, wl_resource* resource) {
GetUserDataAs<AuraSurface>(resource)->HideTooltip();
}

const struct zaura_surface_interface aura_surface_implementation = {
aura_surface_set_frame,
aura_surface_set_parent,
Expand Down Expand Up @@ -303,6 +334,8 @@ const struct zaura_surface_interface aura_surface_implementation = {
aura_surface_set_pin,
aura_surface_unset_pin,
aura_surface_release,
aura_surface_show_tooltip,
aura_surface_hide_tooltip,
};

} // namespace
Expand Down Expand Up @@ -608,6 +641,26 @@ void AuraSurface::ThrottleFrameRate(bool on) {
wl_client_flush(wl_resource_get_client(resource_));
}

void AuraSurface::OnTooltipShown(Surface* surface,
const std::u16string& text,
const gfx::Rect& bounds) {
if (wl_resource_get_version(resource_) <
ZAURA_SURFACE_TOOLTIP_SHOWN_SINCE_VERSION) {
return;
}
zaura_surface_send_tooltip_shown(resource_, base::UTF16ToUTF8(text).c_str(),
bounds.x(), bounds.y(), bounds.width(),
bounds.height());
}

void AuraSurface::OnTooltipHidden(Surface* surface) {
if (wl_resource_get_version(resource_) <
ZAURA_SURFACE_TOOLTIP_HIDDEN_SINCE_VERSION) {
return;
}
zaura_surface_send_tooltip_hidden(resource_);
}

void AuraSurface::MoveToDesk(int desk_index) {
constexpr int kToggleVisibleOnAllWorkspacesValue = -1;
if (desk_index == kToggleVisibleOnAllWorkspacesValue) {
Expand All @@ -629,6 +682,24 @@ void AuraSurface::Unpin() {
surface_->Unpin();
}

void AuraSurface::ShowTooltip(const char* text,
const gfx::Point& position,
uint32_t trigger,
const base::TimeDelta& show_delay,
const base::TimeDelta& hide_delay) {
tooltip_text_ = base::UTF8ToUTF16(text);
wm::SetTooltipText(surface_->window(), &tooltip_text_);
wm::SetTooltipId(surface_->window(), surface_);
ash::Shell::Get()->tooltip_controller()->UpdateAndShow(
surface_->window(), tooltip_text_, position, TooltipTrigger(trigger),
show_delay, hide_delay);
}

void AuraSurface::HideTooltip() {
tooltip_text_ = std::u16string();
ash::Shell::Get()->tooltip_controller()->HideAndReset();
}

chromeos::OrientationType OrientationLock(uint32_t orientation_lock) {
switch (orientation_lock) {
case ZAURA_TOPLEVEL_ORIENTATION_LOCK_NONE:
Expand Down
20 changes: 19 additions & 1 deletion components/exo/wayland/zaura_shell.h
Expand Up @@ -19,6 +19,10 @@
struct wl_client;
struct wl_resource;

namespace base {
class TimeDelta;
}

namespace exo {

class ShellSurface;
Expand All @@ -27,7 +31,7 @@ class ShellSurfaceBase;
namespace wayland {
class SerialTracker;

constexpr uint32_t kZAuraShellVersion = 46;
constexpr uint32_t kZAuraShellVersion = 47;

// Adds bindings to the Aura Shell. Normally this implies Ash on ChromeOS
// builds. On non-ChromeOS builds the protocol provides access to Aura windowing
Expand Down Expand Up @@ -73,13 +77,23 @@ class AuraSurface : public SurfaceObserver,
void Pin(bool trusted);
void Unpin();
void SetOrientationLock(uint32_t orientation_lock);
void ShowTooltip(const char* text,
const gfx::Point& position,
uint32_t trigger,
const base::TimeDelta& show_delay,
const base::TimeDelta& hide_delay);
void HideTooltip();

// Overridden from SurfaceObserver:
void OnSurfaceDestroying(Surface* surface) override;
void OnWindowOcclusionChanged(Surface* surface) override;
void OnFrameLockingChanged(Surface* surface, bool lock) override;
void OnDeskChanged(Surface* surface, int state) override;
void ThrottleFrameRate(bool on) override;
void OnTooltipShown(Surface* surface,
const std::u16string& text,
const gfx::Rect& bounds) override;
void OnTooltipHidden(Surface* surface) override;

// Overridden from ActivationChangeObserver:
void OnWindowActivating(ActivationReason reason,
Expand All @@ -98,6 +112,10 @@ class AuraSurface : public SurfaceObserver,
Surface* surface_;
wl_resource* const resource_;

// Tooltip text sent from Lacros.
// This is kept here since it should out-live ShowTooltip() scope.
std::u16string tooltip_text_;

void ComputeAndSendOcclusion(
const aura::Window::OcclusionState occlusion_state,
const SkRegion& occluded_region);
Expand Down

0 comments on commit f66bb1f

Please sign in to comment.