diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-01-31 16:33:43 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-02-06 16:33:22 +0000 |
commit | da51f56cc21233c2d30f0fe0d171727c3102b2e0 (patch) | |
tree | 4e579ab70ce4b19bee7984237f3ce05a96d59d83 /chromium/components/exo | |
parent | c8c2d1901aec01e934adf561a9fdf0cc776cdef8 (diff) | |
download | qtwebengine-chromium-da51f56cc21233c2d30f0fe0d171727c3102b2e0.tar.gz |
BASELINE: Update Chromium to 65.0.3525.40
Also imports missing submodules
Change-Id: I36901b7c6a325cda3d2c10cedb2186c25af3b79b
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/components/exo')
34 files changed, 815 insertions, 220 deletions
diff --git a/chromium/components/exo/buffer.cc b/chromium/components/exo/buffer.cc index 92cc461b20d..5b350b216c5 100644 --- a/chromium/components/exo/buffer.cc +++ b/chromium/components/exo/buffer.cc @@ -86,10 +86,8 @@ void CreateGLMailbox(gpu::gles2::GLES2Interface* gles2, unsigned texture_id, GLenum target, gpu::Mailbox* mailbox) { - gles2->ActiveTexture(GL_TEXTURE0); - gles2->BindTexture(target, texture_id); gles2->GenMailboxCHROMIUM(mailbox->name); - gles2->ProduceTextureCHROMIUM(target, mailbox->name); + gles2->ProduceTextureDirectCHROMIUM(texture_id, mailbox->name); } } // namespace @@ -261,9 +259,7 @@ gpu::SyncToken Buffer::Texture::BindTexImage() { // Create and return a sync token that can be used to ensure that the // BindTexImage2DCHROMIUM call is processed before issuing any commands // that will read from the texture on a different context. - uint64_t fence_sync = gles2->InsertFenceSyncCHROMIUM(); - gles2->OrderingBarrierCHROMIUM(); - gles2->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gles2->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); TRACE_EVENT_ASYNC_STEP_INTO0("exo", "BufferInUse", gpu_memory_buffer_, "bound"); } @@ -316,9 +312,7 @@ gpu::SyncToken Buffer::Texture::CopyTexImage(Texture* destination, // Create and return a sync token that can be used to ensure that the // CopyTextureCHROMIUM call is processed before issuing any commands // that will read from the target texture on a different context. - uint64_t fence_sync = gles2->InsertFenceSyncCHROMIUM(); - gles2->OrderingBarrierCHROMIUM(); - gles2->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gles2->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); } return sync_token; } diff --git a/chromium/components/exo/buffer_unittest.cc b/chromium/components/exo/buffer_unittest.cc index 033c5b2943e..460d61aa896 100644 --- a/chromium/components/exo/buffer_unittest.cc +++ b/chromium/components/exo/buffer_unittest.cc @@ -168,29 +168,27 @@ TEST_F(BufferTest, SurfaceTreeHostDestruction) { buffer->ProduceTransferableResource(frame_sink_holder, false, &resource); ASSERT_TRUE(rv); + // Submit frame with resource. + { + viz::CompositorFrame frame; + frame.metadata.begin_frame_ack.source_id = + viz::BeginFrameArgs::kManualSourceId; + frame.metadata.begin_frame_ack.sequence_number = + viz::BeginFrameArgs::kStartingFrameNumber; + frame.metadata.begin_frame_ack.has_damage = true; + frame.metadata.device_scale_factor = 1; + std::unique_ptr<viz::RenderPass> pass = viz::RenderPass::Create(); + pass->SetNew(1, gfx::Rect(buffer_size), gfx::Rect(buffer_size), + gfx::Transform()); + frame.render_pass_list.push_back(std::move(pass)); + frame.resource_list.push_back(resource); + frame_sink_holder->SubmitCompositorFrame(std::move(frame)); + } + buffer->OnDetach(); ASSERT_EQ(release_call_count, 0); - // Get a weak reference to frame sink holder. - auto weak_frame_sink_holder = frame_sink_holder->GetWeakPtr(); - - // Destroy surface tree host. Weak reference should be valid until all - // resources have been reclaimed. surface_tree_host.reset(); - ASSERT_EQ(release_call_count, 0); - ASSERT_TRUE(weak_frame_sink_holder); - - // Release buffer. - viz::ReturnedResource returned_resource; - returned_resource.id = resource.id; - returned_resource.sync_token = resource.mailbox_holder.sync_token; - returned_resource.lost = false; - std::vector<viz::ReturnedResource> resources = {returned_resource}; - weak_frame_sink_holder->ReclaimResources(resources); - - RunAllPendingInMessageLoop(); - - // Release() should have been called exactly once. ASSERT_EQ(release_call_count, 1); } @@ -228,7 +226,8 @@ TEST_F(BufferTest, SurfaceTreeHostLastFrame) { frame.metadata.begin_frame_ack.has_damage = true; frame.metadata.device_scale_factor = 1; std::unique_ptr<viz::RenderPass> pass = viz::RenderPass::Create(); - pass->SetNew(1, gfx::Rect(buffer_size), gfx::Rect(), gfx::Transform()); + pass->SetNew(1, gfx::Rect(buffer_size), gfx::Rect(buffer_size), + gfx::Transform()); frame.render_pass_list.push_back(std::move(pass)); frame.resource_list.push_back(resource); frame_sink_holder->SubmitCompositorFrame(std::move(frame)); @@ -259,7 +258,8 @@ TEST_F(BufferTest, SurfaceTreeHostLastFrame) { frame.metadata.begin_frame_ack.has_damage = true; frame.metadata.device_scale_factor = 1; std::unique_ptr<viz::RenderPass> pass = viz::RenderPass::Create(); - pass->SetNew(1, gfx::Rect(buffer_size), gfx::Rect(), gfx::Transform()); + pass->SetNew(1, gfx::Rect(buffer_size), gfx::Rect(buffer_size), + gfx::Transform()); frame.render_pass_list.push_back(std::move(pass)); frame_sink_holder->SubmitCompositorFrame(std::move(frame)); } diff --git a/chromium/components/exo/client_controlled_shell_surface.cc b/chromium/components/exo/client_controlled_shell_surface.cc index fe8732e5dcc..348a3168631 100644 --- a/chromium/components/exo/client_controlled_shell_surface.cc +++ b/chromium/components/exo/client_controlled_shell_surface.cc @@ -8,8 +8,12 @@ #include "ash/public/cpp/window_properties.h" #include "ash/public/cpp/window_state_type.h" #include "ash/public/interfaces/window_pin_type.mojom.h" +#include "ash/shell.h" #include "ash/wm/client_controlled_state.h" +#include "ash/wm/drag_details.h" #include "ash/wm/drag_window_resizer.h" +#include "ash/wm/toplevel_window_event_handler.h" +#include "ash/wm/window_properties.h" #include "ash/wm/window_resizer.h" #include "ash/wm/window_state.h" #include "ash/wm/window_state_delegate.h" @@ -81,7 +85,20 @@ class ClientControlledStateDelegate } void HandleBoundsRequest(ash::wm::WindowState* window_state, const gfx::Rect& bounds) override { - // TODO(oshima): Implement this. + bool is_resize = window_state->window()->bounds().size() != bounds.size(); + + gfx::Rect bounds_in_screen(bounds); + ::wm::ConvertRectToScreen(window_state->window()->GetRootWindow(), + &bounds_in_screen); + int64_t display_id = display::Screen::GetScreen() + ->GetDisplayNearestWindow(window_state->window()) + .id(); + + shell_surface_->OnBoundsChangeEvent( + window_state->GetStateType(), display_id, bounds_in_screen, is_resize, + window_state->drag_details() + ? window_state->drag_details()->bounds_change + : 0); } private: @@ -95,8 +112,9 @@ class ClientControlledWindowStateDelegate : public ash::wm::WindowStateDelegate { public: explicit ClientControlledWindowStateDelegate( + ClientControlledShellSurface* shell_surface, ash::wm::ClientControlledState::Delegate* delegate) - : delegate_(delegate) {} + : shell_surface_(shell_surface), delegate_(delegate) {} ~ClientControlledWindowStateDelegate() override {} // Overridden from ash::wm::WindowStateDelegate: @@ -156,7 +174,16 @@ class ClientControlledWindowStateDelegate return true; } + void OnDragStarted(int component) override { + shell_surface_->OnDragStarted(component); + } + + void OnDragFinished(bool canceled, const gfx::Point& location) override { + shell_surface_->OnDragFinished(canceled, location); + } + private: + ClientControlledShellSurface* shell_surface_; ash::wm::ClientControlledState::Delegate* delegate_; DISALLOW_COPY_AND_ASSIGN(ClientControlledWindowStateDelegate); @@ -168,6 +195,34 @@ bool IsPinned(const ash::wm::WindowState* window_state) { } // namespace +class ClientControlledShellSurface::ScopedSetBoundsLocally { + public: + ScopedSetBoundsLocally(ClientControlledShellSurface* shell_surface) + : state_(shell_surface->client_controlled_state_) { + state_->set_bounds_locally(true); + } + ~ScopedSetBoundsLocally() { state_->set_bounds_locally(false); } + + private: + ash::wm::ClientControlledState* const state_; + + DISALLOW_COPY_AND_ASSIGN(ScopedSetBoundsLocally); +}; + +class ClientControlledShellSurface::ScopedLockedToRoot { + public: + ScopedLockedToRoot(views::Widget* widget) + : window_(widget->GetNativeWindow()) { + window_->SetProperty(ash::kLockedToRootKey, true); + } + ~ScopedLockedToRoot() { window_->ClearProperty(ash::kLockedToRootKey); } + + private: + aura::Window* const window_; + + DISALLOW_COPY_AND_ASSIGN(ScopedLockedToRoot); +}; + //////////////////////////////////////////////////////////////////////////////// // ClientControlledShellSurface, public: @@ -281,9 +336,10 @@ void ClientControlledShellSurface::SetTopInset(int height) { void ClientControlledShellSurface::SetResizeOutset(int outset) { TRACE_EVENT1("exo", "ClientControlledShellSurface::SetResizeOutset", "outset", outset); - - if (root_surface()) - root_surface()->SetInputOutset(outset); + if (client_controlled_move_resize_) { + if (root_surface()) + root_surface()->SetInputOutset(outset); + } } void ClientControlledShellSurface::OnWindowStateChangeEvent( @@ -293,6 +349,61 @@ void ClientControlledShellSurface::OnWindowStateChangeEvent( state_changed_callback_.Run(current_state, next_state); } +void ClientControlledShellSurface::StartResize_DEPRECATED() { + TRACE_EVENT0("exo", "ClientControlledShellSurface::StartResize"); + + if (!widget_ || !client_controlled_move_resize_) + return; + + AttemptToStartDrag(HTBORDER); +} + +void ClientControlledShellSurface::StartMove(const gfx::Point& location) { + TRACE_EVENT0("exo", "ClientControlledShellSurface::StartMove"); + + if (!widget_) + return; + + gfx::Point point_in_root(location); + wm::ConvertPointFromScreen(widget_->GetNativeWindow()->GetRootWindow(), + &point_in_root); + + aura::Window* target = widget_->GetNativeWindow(); + ash::Shell::Get()->toplevel_window_event_handler()->AttemptToStartDrag( + target, point_in_root, HTCAPTION, + ash::wm::WmToplevelWindowEventHandler::EndClosure()); +} + +void ClientControlledShellSurface::SetCanMaximize(bool can_maximize) { + TRACE_EVENT1("exo", "ClientControlledShellSurface::SetCanMaximize", + "can_maximzie", can_maximize); + can_maximize_ = can_maximize; + if (widget_) + widget_->OnSizeConstraintsChanged(); +} + +void ClientControlledShellSurface::OnBoundsChangeEvent( + ash::mojom::WindowStateType current_state, + int64_t display_id, + const gfx::Rect& bounds, + bool is_resize, + int bounds_change) { + if (!bounds.IsEmpty() && !bounds_changed_callback_.is_null()) { + bounds_changed_callback_.Run(current_state, display_id, bounds, is_resize, + bounds_change); + } +} + +void ClientControlledShellSurface::OnDragStarted(int component) { + if (!drag_started_callback_.is_null()) + drag_started_callback_.Run(component); +} + +void ClientControlledShellSurface::OnDragFinished(bool canceled, + const gfx::Point& location) { + if (!drag_finished_callback_.is_null()) + drag_finished_callback_.Run(location.x(), location.y(), canceled); +} //////////////////////////////////////////////////////////////////////////////// // SurfaceDelegate overrides: @@ -382,11 +493,17 @@ void ClientControlledShellSurface::OnWindowBoundsChanged( const gfx::Rect& new_bounds, ui::PropertyChangeReason reason) {} +void ClientControlledShellSurface::OnWindowAddedToRootWindow( + aura::Window* window) { + ScopedLockedToRoot scoped_locked_to_root(widget_); + UpdateWidgetBounds(); +} + //////////////////////////////////////////////////////////////////////////////// // views::WidgetDelegate overrides: -bool ClientControlledShellSurface::CanResize() const { - return false; +bool ClientControlledShellSurface::CanMaximize() const { + return can_maximize_; } views::NonClientFrameView* @@ -397,8 +514,8 @@ ClientControlledShellSurface::CreateNonClientFrameView(views::Widget* widget) { ? std::make_unique<ClientControlledStateDelegate>(this) : g_factory_callback.Run(); - auto window_delegate = - std::make_unique<ClientControlledWindowStateDelegate>(delegate.get()); + auto window_delegate = std::make_unique<ClientControlledWindowStateDelegate>( + this, delegate.get()); auto state = std::make_unique<ash::wm::ClientControlledState>(std::move(delegate)); client_controlled_state_ = state.get(); @@ -419,6 +536,19 @@ bool ClientControlledShellSurface::GetSavedWindowPlacement( } //////////////////////////////////////////////////////////////////////////////// +// views::View overrides: + +gfx::Size ClientControlledShellSurface::GetMaximumSize() const { + // On ChromeOS, a window with non empty maximum size is non-maximizable, + // even if CanMaximize() returns true. ClientControlledShellSurface + // sololy depends on |can_maximize_| to determine if it is maximizable, + // so just return empty size because the maximum size in + // ClientControlledShellSurface is used only to tell the resizability, + // but not real maximum size. + return gfx::Size(); +} + +//////////////////////////////////////////////////////////////////////////////// // display::DisplayObserver overrides: void ClientControlledShellSurface::OnDisplayMetricsChanged( @@ -485,10 +615,13 @@ void ClientControlledShellSurface::CompositorLockTimedOut() { // ShellSurface overrides: void ClientControlledShellSurface::SetWidgetBounds(const gfx::Rect& bounds) { - if (!resizer_ || resizer_->details().window_component != HTCAPTION) { - client_controlled_state_->set_bounds_locally(true); - widget_->SetBounds(bounds); - client_controlled_state_->set_bounds_locally(false); + if ((!client_controlled_move_resize_ && !GetWindowState()->is_dragged()) || + (client_controlled_move_resize_ && + (!resizer_ || resizer_->details().window_component != HTCAPTION))) { + { + ScopedSetBoundsLocally scoped_set_bounds(this); + widget_->SetBounds(bounds); + } UpdateSurfaceBounds(); return; } @@ -504,13 +637,15 @@ void ClientControlledShellSurface::SetWidgetBounds(const gfx::Rect& bounds) { wm::ConvertPointFromScreen(widget_->GetNativeWindow()->parent(), &origin); // Move the window relative to the current display. - client_controlled_state_->set_bounds_locally(true); - widget_->GetNativeWindow()->SetBounds(gfx::Rect(origin, bounds.size())); - client_controlled_state_->set_bounds_locally(false); + { + ScopedSetBoundsLocally scoped_set_bounds(this); + widget_->GetNativeWindow()->SetBounds(gfx::Rect(origin, bounds.size())); + } UpdateSurfaceBounds(); // Render phantom windows when beyond the current display. - resizer_->Drag(GetMouseLocation(), 0); + if (resizer_) + resizer_->Drag(GetMouseLocation(), 0); } gfx::Rect ClientControlledShellSurface::GetShadowBounds() const { diff --git a/chromium/components/exo/client_controlled_shell_surface.h b/chromium/components/exo/client_controlled_shell_surface.h index e15247209c5..7c9349db058 100644 --- a/chromium/components/exo/client_controlled_shell_surface.h +++ b/chromium/components/exo/client_controlled_shell_surface.h @@ -50,6 +50,10 @@ class ClientControlledShellSurface geometry_changed_callback_ = callback; } + void set_client_controlled_move_resize(bool client_controlled_move_resize) { + client_controlled_move_resize_ = client_controlled_move_resize; + } + // Called when the client was maximized. void SetMaximized(); @@ -71,6 +75,30 @@ class ClientControlledShellSurface state_changed_callback_ = state_changed_callback; } + // Set the callback to run when the surface bounds changed. + using BoundsChangedCallback = base::RepeatingCallback<void( + ash::mojom::WindowStateType current_state_type, + int64_t display_id, + const gfx::Rect& bounds, + bool is_resize, + int bounds_change)>; + void set_bounds_changed_callback( + const BoundsChangedCallback& bounds_changed_callback) { + bounds_changed_callback_ = bounds_changed_callback; + } + + // Set the callback to run when the drag operation started. + using DragStartedCallback = base::RepeatingCallback<void(int direction)>; + void set_drag_started_callback(const DragStartedCallback& callback) { + drag_started_callback_ = callback; + } + + // Set the callback to run when the drag operation finished. + using DragFinishedCallback = base::RepeatingCallback<void(int, int, bool)>; + void set_drag_finished_callback(const DragFinishedCallback& callback) { + drag_finished_callback_ = callback; + } + // Pin/unpin the surface. Pinned surface cannot be switched to // other windows unless its explicitly unpinned. void SetPinned(ash::mojom::WindowPinType type); @@ -99,26 +127,50 @@ class ClientControlledShellSurface void OnWindowStateChangeEvent(ash::mojom::WindowStateType old_state, ash::mojom::WindowStateType next_state); + // Sends the window bounds change event to client. |display_id| specifies in + // which display the surface should live in. |drag_bounds_change| is + // a masked value of ash::WindowResizer::kBoundsChange_Xxx, and specifies + // how the bounds was changed. + void OnBoundsChangeEvent(ash::mojom::WindowStateType current_state, + int64_t display_id, + const gfx::Rect& bounds, + bool is_resize, + int drag_bounds_change); + // Sends the window drag events to client. + void OnDragStarted(int component); + void OnDragFinished(bool cancel, const gfx::Point& location); + + void StartResize_DEPRECATED(); + + // Starts the move-by-drag operation. + void StartMove(const gfx::Point& location); + + // Set if the surface can be maximzied. + void SetCanMaximize(bool can_maximize); + // Overridden from SurfaceDelegate: void OnSurfaceCommit() override; bool IsTouchEnabled(Surface* surface) const override; // Overridden from views::WidgetDelegate: - bool CanResize() const override; + bool CanMaximize() const override; views::NonClientFrameView* CreateNonClientFrameView( views::Widget* widget) override; - void SaveWindowPlacement(const gfx::Rect& bounds, ui::WindowShowState show_state) override; bool GetSavedWindowPlacement(const views::Widget* widget, gfx::Rect* bounds, ui::WindowShowState* show_state) const override; + // Overridden from views::View: + gfx::Size GetMaximumSize() const override; + // Overridden from aura::WindowObserver: void OnWindowBoundsChanged(aura::Window* window, const gfx::Rect& old_bounds, const gfx::Rect& new_bounds, ui::PropertyChangeReason reason) override; + void OnWindowAddedToRootWindow(aura::Window* window) override; // Overridden from display::DisplayObserver: void OnDisplayMetricsChanged(const display::Display& display, @@ -139,6 +191,9 @@ class ClientControlledShellSurface const DelegateFactoryCallback& callback); private: + class ScopedSetBoundsLocally; + class ScopedLockedToRoot; + // Overridden from ShellSurface: void SetWidgetBounds(const gfx::Rect& bounds) override; gfx::Rect GetShadowBounds() const override; @@ -172,6 +227,9 @@ class ClientControlledShellSurface double pending_scale_ = 1.0; StateChangedCallback state_changed_callback_; + BoundsChangedCallback bounds_changed_callback_; + DragStartedCallback drag_started_callback_; + DragFinishedCallback drag_finished_callback_; // TODO(reveman): Use configure callbacks for orientation. crbug.com/765954 Orientation pending_orientation_ = Orientation::LANDSCAPE; @@ -182,6 +240,8 @@ class ClientControlledShellSurface ui::WindowShowState pending_show_state_ = ui::SHOW_STATE_NORMAL; + bool can_maximize_ = true; + std::unique_ptr<ui::CompositorLock> orientation_compositor_lock_; DISALLOW_COPY_AND_ASSIGN(ClientControlledShellSurface); diff --git a/chromium/components/exo/client_controlled_shell_surface_unittest.cc b/chromium/components/exo/client_controlled_shell_surface_unittest.cc index 7a1d2fe9e75..78da5c0e8af 100644 --- a/chromium/components/exo/client_controlled_shell_surface_unittest.cc +++ b/chromium/components/exo/client_controlled_shell_surface_unittest.cc @@ -7,7 +7,6 @@ #include "ash/public/cpp/window_properties.h" #include "ash/public/interfaces/window_pin_type.mojom.h" #include "ash/shell.h" -#include "ash/shell_port.h" #include "ash/shell_test_api.h" #include "ash/system/tray/system_tray.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" @@ -26,6 +25,10 @@ #include "components/exo/wm_helper.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" +#include "ui/aura/window_event_dispatcher.h" +#include "ui/aura/window_tree_host.h" +#include "ui/events/base_event_utils.h" +#include "ui/events/event_targeter.h" #include "ui/events/test/event_generator.h" #include "ui/views/widget/widget.h" #include "ui/wm/core/shadow.h" @@ -59,7 +62,11 @@ TEST_F(ClientControlledShellSurfaceTest, SetPinned) { gfx::Size buffer_size(256, 256); std::unique_ptr<Buffer> buffer( new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface); + surface->Attach(buffer.get()); + surface->Commit(); + auto shell_surface( exo_test_helper()->CreateClientControlledShellSurface(surface.get())); @@ -132,7 +139,7 @@ TEST_F(ClientControlledShellSurfaceTest, ModalWindowDefaultActive) { shell_surface->SetSystemModal(true); surface->Commit(); - EXPECT_TRUE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_TRUE(ash::Shell::IsSystemModalWindowOpen()); EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); } @@ -147,7 +154,7 @@ TEST_F(ClientControlledShellSurfaceTest, UpdateModalWindow) { surface->SetInputRegion(cc::Region()); surface->Commit(); - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_FALSE(ash::Shell::IsSystemModalWindowOpen()); EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); // Creating a surface without input region should not make it modal. @@ -162,31 +169,31 @@ TEST_F(ClientControlledShellSurfaceTest, UpdateModalWindow) { surface->SetSubSurfacePosition(child.get(), gfx::Point(10, 10)); child->Commit(); surface->Commit(); - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_FALSE(ash::Shell::IsSystemModalWindowOpen()); EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); // Making the surface opaque shouldn't make it modal either. child->SetBlendMode(SkBlendMode::kSrc); child->Commit(); surface->Commit(); - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_FALSE(ash::Shell::IsSystemModalWindowOpen()); EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); // Setting input regions won't make it modal either. surface->SetInputRegion(gfx::Rect(10, 10, 100, 100)); surface->Commit(); - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_FALSE(ash::Shell::IsSystemModalWindowOpen()); EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); // Only SetSystemModal changes modality. shell_surface->SetSystemModal(true); - EXPECT_TRUE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_TRUE(ash::Shell::IsSystemModalWindowOpen()); EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); shell_surface->SetSystemModal(false); - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_FALSE(ash::Shell::IsSystemModalWindowOpen()); EXPECT_FALSE(shell_surface->GetWidget()->IsActive()); // If the non modal system window was active, @@ -194,11 +201,11 @@ TEST_F(ClientControlledShellSurfaceTest, UpdateModalWindow) { EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); shell_surface->SetSystemModal(true); - EXPECT_TRUE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_TRUE(ash::Shell::IsSystemModalWindowOpen()); EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); shell_surface->SetSystemModal(false); - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_FALSE(ash::Shell::IsSystemModalWindowOpen()); EXPECT_TRUE(shell_surface->GetWidget()->IsActive()); } @@ -222,12 +229,12 @@ TEST_F(ClientControlledShellSurfaceTest, // It is expected that modal window is shown. EXPECT_TRUE(shell_surface->GetWidget()); - EXPECT_TRUE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_TRUE(ash::Shell::IsSystemModalWindowOpen()); // Now widget is created and setting modal state should be applied // immediately. shell_surface->SetSystemModal(false); - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_FALSE(ash::Shell::IsSystemModalWindowOpen()); } TEST_F(ClientControlledShellSurfaceTest, SurfaceShadow) { @@ -390,11 +397,18 @@ TEST_F(ClientControlledShellSurfaceTest, ShadowWithTransform) { } TEST_F(ClientControlledShellSurfaceTest, ShadowStartMaximized) { + gfx::Size buffer_size(256, 256); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface = exo_test_helper()->CreateClientControlledShellSurface(surface.get()); shell_surface->SetMaximized(); + surface->Attach(buffer.get()); surface->Commit(); + views::Widget* widget = shell_surface->GetWidget(); aura::Window* window = widget->GetNativeWindow(); @@ -691,4 +705,53 @@ TEST_F(ClientControlledShellSurfaceTest, shell_surface->host_window()->layer()->GetTargetTransform().ToString()); } +TEST_F(ClientControlledShellSurfaceTest, MouseAndTouchTarget) { + gfx::Size buffer_size(256, 256); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface( + exo_test_helper()->CreateClientControlledShellSurface(surface.get())); + + const gfx::Rect original_bounds(0, 0, 256, 256); + shell_surface->SetGeometry(original_bounds); + shell_surface->set_client_controlled_move_resize(false); + surface->Attach(buffer.get()); + surface->Commit(); + + EXPECT_TRUE(shell_surface->CanResize()); + + aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); + aura::Window* root = window->GetRootWindow(); + ui::EventTargeter* targeter = + root->GetHost()->dispatcher()->GetDefaultEventTargeter(); + + gfx::Point mouse_location(256 + 5, 150); + + ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, mouse_location, mouse_location, + ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); + EXPECT_EQ(window, targeter->FindTargetForEvent(root, &mouse)); + + // Move 20px further away. Touch event can hit the window but + // mouse event will not. + gfx::Point touch_location(256 + 25, 150); + ui::MouseEvent touch(ui::ET_TOUCH_PRESSED, touch_location, touch_location, + ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); + EXPECT_EQ(window, targeter->FindTargetForEvent(root, &touch)); + + ui::MouseEvent mouse_with_touch_loc(ui::ET_MOUSE_MOVED, touch_location, + touch_location, ui::EventTimeForNow(), + ui::EF_NONE, ui::EF_NONE); + EXPECT_FALSE(window->Contains(static_cast<aura::Window*>( + targeter->FindTargetForEvent(root, &mouse_with_touch_loc)))); + + // Touching futher away shouldn't hit the window. + gfx::Point no_touch_location(256 + 35, 150); + ui::MouseEvent no_touch(ui::ET_TOUCH_PRESSED, no_touch_location, + no_touch_location, ui::EventTimeForNow(), ui::EF_NONE, + ui::EF_NONE); + EXPECT_FALSE(window->Contains(static_cast<aura::Window*>( + targeter->FindTargetForEvent(root, &no_touch)))); +} + } // namespace exo diff --git a/chromium/components/exo/data_device_unittest.cc b/chromium/components/exo/data_device_unittest.cc index 71f836a732e..e721cfdc422 100644 --- a/chromium/components/exo/data_device_unittest.cc +++ b/chromium/components/exo/data_device_unittest.cc @@ -109,9 +109,16 @@ class TestFileHelper : public FileHelper { // Overridden from FileHelper: std::string GetMimeTypeForUriList() const override { return ""; } - bool ConvertPathToUrl(const base::FilePath& path, GURL* out) override { + bool GetUrlFromPath(const std::string& app_id, + const base::FilePath& path, + GURL* out) override { return true; } + bool GetUrlFromFileSystemUrl(const std::string& app_id, + const GURL& url, + GURL* out) override { + return false; + } private: DISALLOW_COPY_AND_ASSIGN(TestFileHelper); diff --git a/chromium/components/exo/data_offer.cc b/chromium/components/exo/data_offer.cc index 33d375f5958..13fca50d435 100644 --- a/chromium/components/exo/data_offer.cc +++ b/chromium/components/exo/data_offer.cc @@ -115,7 +115,8 @@ void DataOffer::SetDropData(FileHelper* file_helper, base::string16 url_list; for (const auto& info : files) { GURL url; - if (file_helper->ConvertPathToUrl(info.path, &url)) { + // TODO(hirono): Need to fill the corret app_id. + if (file_helper->GetUrlFromPath(/* app_id */ "", info.path, &url)) { if (!url_list.empty()) url_list += base::UTF8ToUTF16(kUriListSeparator); url_list += base::UTF8ToUTF16(url.spec()); diff --git a/chromium/components/exo/data_offer_unittest.cc b/chromium/components/exo/data_offer_unittest.cc index 6100b50c150..0c8976ec1bf 100644 --- a/chromium/components/exo/data_offer_unittest.cc +++ b/chromium/components/exo/data_offer_unittest.cc @@ -71,10 +71,17 @@ class TestFileHelper : public FileHelper { // Overridden from FileHelper: std::string GetMimeTypeForUriList() const override { return "text/uri-list"; } - bool ConvertPathToUrl(const base::FilePath& path, GURL* out) override { + bool GetUrlFromPath(const std::string& app_id, + const base::FilePath& path, + GURL* out) override { *out = GURL("file://" + path.AsUTF8Unsafe()); return true; } + bool GetUrlFromFileSystemUrl(const std::string& app_id, + const GURL& url, + GURL* out) override { + return false; + } private: DISALLOW_COPY_AND_ASSIGN(TestFileHelper); diff --git a/chromium/components/exo/display_unittest.cc b/chromium/components/exo/display_unittest.cc index 7985b6b55c5..cf56b5596ad 100644 --- a/chromium/components/exo/display_unittest.cc +++ b/chromium/components/exo/display_unittest.cc @@ -227,9 +227,16 @@ class TestFileHelper : public FileHelper { // Overriden from TestFileHelper: TestFileHelper() {} std::string GetMimeTypeForUriList() const override { return ""; } - bool ConvertPathToUrl(const base::FilePath& path, GURL* out) override { + bool GetUrlFromPath(const std::string& app_id, + const base::FilePath& path, + GURL* out) override { return true; } + bool GetUrlFromFileSystemUrl(const std::string& app_id, + const GURL& url, + GURL* out) override { + return false; + } }; TEST_F(DisplayTest, CreateDataDevice) { diff --git a/chromium/components/exo/file_helper.h b/chromium/components/exo/file_helper.h index ccf1c9c1e24..28702db66c2 100644 --- a/chromium/components/exo/file_helper.h +++ b/chromium/components/exo/file_helper.h @@ -23,13 +23,21 @@ class FileHelper { // FileHelper. virtual std::string GetMimeTypeForUriList() const = 0; - // Convert natife file path to URL which can be used in container. We don't - // expose enter file system to a container directly. Instead we mount - // specific directory in the containers' namespace. Thus we need to convert - // native path to file URL which points mount point in containers. The - // conversion should be container specific, now we only have ARC container - // though. - virtual bool ConvertPathToUrl(const base::FilePath& path, GURL* out) = 0; + // Converts native file path to URL which can be used by application with + // |app_id|. We don't expose enter file system to a container directly. + // Instead we mount specific directory in the containers' namespace. Thus we + // need to convert native path to file URL which points mount point in + // containers. The conversion should be container specific, now we only have + // ARC container though. + virtual bool GetUrlFromPath(const std::string& app_id, + const base::FilePath& path, + GURL* out) = 0; + + // Converts filesystem:// URL to something that applications can understand. + // e.g. content:// URI for Android apps. + virtual bool GetUrlFromFileSystemUrl(const std::string& app_id, + const GURL& file_system_url, + GURL* out) = 0; }; } // namespace exo diff --git a/chromium/components/exo/keyboard.cc b/chromium/components/exo/keyboard.cc index 3c7644c96e7..b42fb1153f6 100644 --- a/chromium/components/exo/keyboard.cc +++ b/chromium/components/exo/keyboard.cc @@ -69,24 +69,29 @@ bool ConsumedByIme(Surface* focus, const ui::KeyEvent* event) { if (event->key_code() == ui::VKEY_PROCESSKEY) return true; + // Except for PROCESSKEY, never discard "key-up" events. A keydown not paired + // by a keyup can trigger a never-ending key repeat in the client, which can + // never be desirable. + if (event->type() == ui::ET_KEY_RELEASED) + return false; + // Case 2: // When IME ate a key event and generated a single character input, it leaves // the key event as-is, and in addition calls the active ui::TextInputClient's // InsertChar() method. (In our case, arc::ArcImeService::InsertChar()). // - // In Chrome OS (and Web) convention, the two calls wont't cause duplicates, + // In Chrome OS (and Web) convention, the two calls won't cause duplicates, // because key-down events do not mean any character inputs there. // (InsertChar issues a DOM "keypress" event, which is distinct from keydown.) // Unfortunately, this is not necessary the case for our clients that may // treat keydown as a trigger of text inputs. We need suppression for keydown. - if (event->type() == ui::ET_KEY_PRESSED) { - // Same condition as components/arc/ime/arc_ime_service.cc#InsertChar. - const base::char16 ch = event->GetCharacter(); - const bool is_control_char = - (0x00 <= ch && ch <= 0x1f) || (0x7f <= ch && ch <= 0x9f); - if (!is_control_char && !ui::IsSystemKeyModifier(event->flags())) - return true; - } + // + // Same condition as components/arc/ime/arc_ime_service.cc#InsertChar. + const base::char16 ch = event->GetCharacter(); + const bool is_control_char = + (0x00 <= ch && ch <= 0x1f) || (0x7f <= ch && ch <= 0x9f); + if (!is_control_char && !ui::IsSystemKeyModifier(event->flags())) + return true; // Case 3: // Workaround for apps that doesn't handle hardware keyboard events well. @@ -129,6 +134,11 @@ bool IsReservedAccelerator(const ui::KeyEvent* event) { return false; } +// Returns false if an accelerator is not reserved or it's not enabled. +bool ProcessAcceleratorIfReserved(Surface* surface, ui::KeyEvent* event) { + return IsReservedAccelerator(event) && ProcessAccelerator(surface, event); +} + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -179,7 +189,7 @@ bool Keyboard::HasObserver(KeyboardObserver* observer) const { } void Keyboard::RemoveObserver(KeyboardObserver* observer) { - observer_list_.HasObserver(observer); + observer_list_.RemoveObserver(observer); } void Keyboard::SetNeedKeyboardKeyAcks(bool need_acks) { @@ -213,6 +223,17 @@ void Keyboard::OnKeyEvent(ui::KeyEvent* event) { delegate_->OnKeyboardModifiers(modifier_flags_); } + // Process reserved accelerators before sending it to client. + if (focus_ && ProcessAcceleratorIfReserved(focus_, event)) { + // Discard a key press event if it's a reserved accelerator and it's + // enabled. + event->SetHandled(); + // Send leave/enter event instead of key event, so the client can know the + // actual state of the keyboard. + SetFocus(focus_); + return; + } + // When IME ate a key event, we use the event only for tracking key states and // ignore for further processing. Otherwise it is handled in two places (IME // and client) and causes undesired behavior. @@ -220,7 +241,7 @@ void Keyboard::OnKeyEvent(ui::KeyEvent* event) { switch (event->type()) { case ui::ET_KEY_PRESSED: - if (focus_ && !consumed_by_ime && !IsReservedAccelerator(event)) { + if (focus_ && !consumed_by_ime && !event->handled()) { uint32_t serial = delegate_->OnKeyboardKey(event->time_stamp(), event->code(), true); if (are_keyboard_key_acks_needed_) { @@ -233,7 +254,7 @@ void Keyboard::OnKeyEvent(ui::KeyEvent* event) { } break; case ui::ET_KEY_RELEASED: - if (focus_ && !consumed_by_ime && !IsReservedAccelerator(event)) { + if (focus_ && !consumed_by_ime && !event->handled()) { uint32_t serial = delegate_->OnKeyboardKey(event->time_stamp(), event->code(), false); if (are_keyboard_key_acks_needed_) { diff --git a/chromium/components/exo/keyboard_unittest.cc b/chromium/components/exo/keyboard_unittest.cc index ccf6f9173de..7948ca0b77b 100644 --- a/chromium/components/exo/keyboard_unittest.cc +++ b/chromium/components/exo/keyboard_unittest.cc @@ -275,25 +275,23 @@ TEST_F(KeyboardTest, OnKeyboardTypeChanged) { } TEST_F(KeyboardTest, KeyboardObserver) { - std::unique_ptr<Surface> surface(new Surface); - std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); - gfx::Size buffer_size(10, 10); - std::unique_ptr<Buffer> buffer( - new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); - surface->Attach(buffer.get()); - surface->Commit(); - - aura::client::FocusClient* focus_client = - aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow()); - focus_client->FocusWindow(nullptr); - MockKeyboardDelegate delegate; Seat seat; auto keyboard = std::make_unique<Keyboard>(&delegate, &seat); - MockKeyboardObserver observer; - keyboard->AddObserver(&observer); + MockKeyboardObserver observer1; + MockKeyboardObserver observer2; + + keyboard->AddObserver(&observer1); + keyboard->AddObserver(&observer2); + EXPECT_TRUE(keyboard->HasObserver(&observer1)); + EXPECT_TRUE(keyboard->HasObserver(&observer2)); + + keyboard->RemoveObserver(&observer1); + EXPECT_FALSE(keyboard->HasObserver(&observer1)); + EXPECT_TRUE(keyboard->HasObserver(&observer2)); - EXPECT_CALL(observer, OnKeyboardDestroying(keyboard.get())); + EXPECT_CALL(observer1, OnKeyboardDestroying(keyboard.get())).Times(0); + EXPECT_CALL(observer2, OnKeyboardDestroying(keyboard.get())); keyboard.reset(); } diff --git a/chromium/components/exo/layer_tree_frame_sink_holder.cc b/chromium/components/exo/layer_tree_frame_sink_holder.cc index a553af49fc9..7da7e8bb24a 100644 --- a/chromium/components/exo/layer_tree_frame_sink_holder.cc +++ b/chromium/components/exo/layer_tree_frame_sink_holder.cc @@ -38,6 +38,12 @@ LayerTreeFrameSinkHolder::~LayerTreeFrameSinkHolder() { // static void LayerTreeFrameSinkHolder::DeleteWhenLastResourceHasBeenReclaimed( std::unique_ptr<LayerTreeFrameSinkHolder> holder) { + if (holder->last_frame_size_in_pixels_.IsEmpty()) { + // Delete sink holder immediately if no frame has been submitted. + DCHECK(holder->last_frame_resources_.empty()); + return; + } + // Submit an empty frame to ensure that pending release callbacks will be // processed in a finite amount of time. viz::CompositorFrame frame; @@ -48,8 +54,8 @@ void LayerTreeFrameSinkHolder::DeleteWhenLastResourceHasBeenReclaimed( frame.metadata.begin_frame_ack.has_damage = true; frame.metadata.device_scale_factor = holder->last_frame_device_scale_factor_; std::unique_ptr<viz::RenderPass> pass = viz::RenderPass::Create(); - pass->SetNew(1, gfx::Rect(holder->last_frame_size_in_pixels_), gfx::Rect(), - gfx::Transform()); + pass->SetNew(1, gfx::Rect(holder->last_frame_size_in_pixels_), + gfx::Rect(holder->last_frame_size_in_pixels_), gfx::Transform()); frame.render_pass_list.push_back(std::move(pass)); holder->last_frame_resources_.clear(); holder->frame_sink_->SubmitCompositorFrame(std::move(frame)); diff --git a/chromium/components/exo/pointer.cc b/chromium/components/exo/pointer.cc index f395a767ec1..5d278bbe7b9 100644 --- a/chromium/components/exo/pointer.cc +++ b/chromium/components/exo/pointer.cc @@ -86,8 +86,8 @@ Pointer::Pointer(PointerDelegate* delegate) cursor_capture_weak_ptr_factory_(this) { auto* helper = WMHelper::GetInstance(); helper->AddPreTargetHandler(this); - helper->AddCursorObserver(this); helper->AddDisplayConfigurationObserver(this); + helper->GetCursorClient()->AddObserver(this); } Pointer::~Pointer() { @@ -100,8 +100,8 @@ Pointer::~Pointer() { pinch_delegate_->OnPointerDestroying(this); auto* helper = WMHelper::GetInstance(); helper->RemoveDisplayConfigurationObserver(this); - helper->RemoveCursorObserver(this); helper->RemovePreTargetHandler(this); + helper->GetCursorClient()->RemoveObserver(this); if (root_surface()) root_surface()->RemoveSurfaceObserver(this); } @@ -315,11 +315,15 @@ void Pointer::OnCursorSizeChanged(ui::CursorSize cursor_size) { } void Pointer::OnCursorDisplayChanged(const display::Display& display) { - if (!focus_surface_) - return; - - if (cursor_ != ui::CursorType::kNull) + auto* cursor_client = WMHelper::GetInstance()->GetCursorClient(); + if (cursor_ == ui::CursorType::kCustom && + cursor_client->GetCursor() == cursor_client->GetCursor()) { + // If the current cursor is still the one created by us, + // it's our responsibility to update the cursor for the new display. + // Don't check |focus_surface_| because it can be null while + // dragging the window due to an event capture. UpdateCursor(); + } } //////////////////////////////////////////////////////////////////////////////// @@ -355,7 +359,6 @@ void Pointer::SetFocus(Surface* surface, // response to each OnPointerEnter() call. focus_surface_->UnregisterCursorProvider(this); focus_surface_ = nullptr; - cursor_ = ui::CursorType::kNull; cursor_capture_weak_ptr_factory_.InvalidateWeakPtrs(); } // Second generate an enter event if focus moved to a new surface. @@ -434,7 +437,8 @@ void Pointer::OnCursorCaptured(const gfx::Point& hotspot, } void Pointer::UpdateCursor() { - DCHECK(focus_surface_); + auto* helper = WMHelper::GetInstance(); + aura::client::CursorClient* cursor_client = helper->GetCursorClient(); if (cursor_bitmap_.drawsNothing()) { cursor_ = ui::CursorType::kNone; @@ -443,12 +447,13 @@ void Pointer::UpdateCursor() { gfx::Point hotspot = gfx::ScaleToFlooredPoint(cursor_hotspot_, capture_ratio_); - auto* helper = WMHelper::GetInstance(); - const display::Display& display = helper->GetCursorDisplay(); + // TODO(oshima|weidongg): Add cutsom cursor API to handle size/display + // change without explicit management like this. https://crbug.com/721601. + const display::Display& display = cursor_client->GetDisplay(); float scale = helper->GetDisplayInfo(display.id()).GetDensityRatio() / capture_ratio_; - if (helper->GetCursorSize() == ui::CursorSize::kLarge) + if (cursor_client->GetCursorSize() == ui::CursorSize::kLarge) scale *= kLargeCursorScale; ui::ScaleAndRotateCursorBitmapAndHotpoint(scale, display.rotation(), @@ -473,14 +478,7 @@ void Pointer::UpdateCursor() { #endif } - aura::Window* root_window = focus_surface_->window()->GetRootWindow(); - if (!root_window) - return; - - aura::client::CursorClient* cursor_client = - aura::client::GetCursorClient(root_window); - if (cursor_client) - cursor_client->SetCursor(cursor_); + cursor_client->SetCursor(cursor_); } } // namespace exo diff --git a/chromium/components/exo/pointer_unittest.cc b/chromium/components/exo/pointer_unittest.cc index 67a896fad86..5b81adc18e3 100644 --- a/chromium/components/exo/pointer_unittest.cc +++ b/chromium/components/exo/pointer_unittest.cc @@ -6,7 +6,6 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/shell.h" -#include "ash/shell_port.h" #include "ash/wm/window_positioning_utils.h" #include "components/exo/buffer.h" #include "components/exo/pointer_delegate.h" @@ -347,7 +346,7 @@ TEST_F(PointerTest, IgnorePointerEventDuringModal) { // Make the window modal. shell_surface2->SetSystemModal(true); - EXPECT_TRUE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_TRUE(ash::Shell::IsSystemModalWindowOpen()); EXPECT_CALL(delegate, OnPointerFrame()).Times(testing::AnyNumber()); EXPECT_CALL(delegate, CanAcceptPointerEventsForSurface(surface.get())) @@ -434,7 +433,7 @@ TEST_F(PointerTest, IgnorePointerEventDuringModal) { // Make the window non-modal. shell_surface2->SetSystemModal(false); - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_FALSE(ash::Shell::IsSystemModalWindowOpen()); // Check if pointer events on non-modal window are registered. { diff --git a/chromium/components/exo/shell_surface_base.cc b/chromium/components/exo/shell_surface_base.cc index fc8e2d99648..3a189d58e7c 100644 --- a/chromium/components/exo/shell_surface_base.cc +++ b/chromium/components/exo/shell_surface_base.cc @@ -65,12 +65,38 @@ const struct { {ui::VKEY_W, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}, {ui::VKEY_F4, ui::EF_ALT_DOWN}}; +class ShellSurfaceWidget : public views::Widget { + public: + explicit ShellSurfaceWidget(ShellSurfaceBase* shell_surface) + : shell_surface_(shell_surface) {} + + // Overridden from views::Widget: + void Close() override { shell_surface_->Close(); } + void OnKeyEvent(ui::KeyEvent* event) override { + // Handle only accelerators. Do not call Widget::OnKeyEvent that eats focus + // management keys (like the tab key) as well. + if (GetFocusManager()->ProcessAccelerator(ui::Accelerator(*event))) + event->SetHandled(); + } + gfx::Size GetMinimumSize() const override { + return shell_surface_->GetMinimumSize(); + } + + private: + ShellSurfaceBase* const shell_surface_; + + DISALLOW_COPY_AND_ASSIGN(ShellSurfaceWidget); +}; + class CustomFrameView : public ash::CustomFrameViewAsh { public: using ShapeRects = std::vector<gfx::Rect>; - CustomFrameView(views::Widget* widget, bool enabled) - : CustomFrameViewAsh(widget) { + CustomFrameView(views::Widget* widget, + bool enabled, + bool client_controlled_move_resize) + : CustomFrameViewAsh(widget), + client_controlled_move_resize_(client_controlled_move_resize) { SetEnabled(enabled); if (!enabled) CustomFrameViewAsh::SetShouldPaintHeader(false); @@ -121,7 +147,7 @@ class CustomFrameView : public ash::CustomFrameViewAsh { return client_bounds; } int NonClientHitTest(const gfx::Point& point) override { - if (enabled()) + if (enabled() || !client_controlled_move_resize_) return ash::CustomFrameViewAsh::NonClientHitTest(point); return GetWidget()->client_view()->NonClientHitTest(point); } @@ -145,23 +171,30 @@ class CustomFrameView : public ash::CustomFrameViewAsh { if (enabled()) return ash::CustomFrameViewAsh::SizeConstraintsChanged(); } + gfx::Size GetMinimumSize() const override { + return static_cast<const ShellSurfaceWidget*>(GetWidget()) + ->GetMinimumSize(); + } private: + // TODO(oshima): Remove this once the transition to new drag/resize + // is complete. https://crbug.com/801666. + const bool client_controlled_move_resize_; + DISALLOW_COPY_AND_ASSIGN(CustomFrameView); }; class CustomWindowTargeter : public aura::WindowTargeter { public: - CustomWindowTargeter(views::Widget* widget) : widget_(widget) {} + CustomWindowTargeter(views::Widget* widget, + bool client_controlled_move_resize) + : widget_(widget), + client_controlled_move_resize_(client_controlled_move_resize) {} ~CustomWindowTargeter() override {} // Overridden from aura::WindowTargeter: bool EventLocationInsideBounds(aura::Window* window, const ui::LocatedEvent& event) const override { - Surface* surface = ShellSurfaceBase::GetMainSurface(window); - if (!surface) - return false; - gfx::Point local_point = event.location(); if (window->parent()) { @@ -169,6 +202,13 @@ class CustomWindowTargeter : public aura::WindowTargeter { &local_point); } + if (IsInResizeHandle(window, event, local_point)) + return true; + + Surface* surface = ShellSurfaceBase::GetMainSurface(window); + if (!surface) + return false; + int component = widget_->non_client_view()->NonClientHitTest(local_point); if (component != HTNOWHERE && component != HTCLIENT) return true; @@ -178,29 +218,54 @@ class CustomWindowTargeter : public aura::WindowTargeter { } private: - views::Widget* const widget_; - - DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter); -}; + bool IsInResizeHandle(aura::Window* window, + const ui::LocatedEvent& event, + const gfx::Point& local_point) const { + if (window != widget_->GetNativeWindow() || + !widget_->widget_delegate()->CanResize()) { + return false; + } -class ShellSurfaceWidget : public views::Widget { - public: - explicit ShellSurfaceWidget(ShellSurfaceBase* shell_surface) - : shell_surface_(shell_surface) {} + // Use ash's resize handle detection logic if + // a) ClientControlledShellSurface uses server side resize or + // b) xdg shell is using the server side decoration. + if (ash::wm::GetWindowState(widget_->GetNativeWindow()) + ->allow_set_bounds_direct() + ? client_controlled_move_resize_ + : !widget_->non_client_view()->frame_view()->enabled()) { + return false; + } - // Overridden from views::Widget - void Close() override { shell_surface_->Close(); } - void OnKeyEvent(ui::KeyEvent* event) override { - // Handle only accelerators. Do not call Widget::OnKeyEvent that eats focus - // management keys (like the tab key) as well. - if (GetFocusManager()->ProcessAccelerator(ui::Accelerator(*event))) - event->SetHandled(); + ui::EventTarget* parent = + static_cast<ui::EventTarget*>(window)->GetParentTarget(); + if (parent) { + aura::WindowTargeter* parent_targeter = + static_cast<aura::WindowTargeter*>(parent->GetEventTargeter()); + + if (parent_targeter) { + gfx::Rect mouse_rect; + gfx::Rect touch_rect; + + if (parent_targeter->GetHitTestRects(window, &mouse_rect, + &touch_rect)) { + const gfx::Vector2d offset = -window->bounds().OffsetFromOrigin(); + mouse_rect.Offset(offset); + touch_rect.Offset(offset); + if (event.IsTouchEvent() || event.IsGestureEvent() + ? touch_rect.Contains(local_point) + : mouse_rect.Contains(local_point)) { + return true; + } + } + } + } + return false; } - private: - ShellSurfaceBase* const shell_surface_; + views::Widget* const widget_; + const bool client_controlled_move_resize_; - DISALLOW_COPY_AND_ASSIGN(ShellSurfaceWidget); + DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter); }; // A place holder to disable default implementation created by @@ -606,6 +671,8 @@ void ShellSurfaceBase::OnSurfaceCommit() { } SubmitCompositorFrame(); + + widget_->OnSizeConstraintsChanged(); } bool ShellSurfaceBase::IsTouchEnabled(Surface*) const { @@ -630,6 +697,14 @@ void ShellSurfaceBase::OnSetFrame(SurfaceFrameType type) { } } +void ShellSurfaceBase::OnSetFrameColors(SkColor active_color, + SkColor inactive_color) { + // TODO(reveman): Allow frame colors to change after surface has been enabled. + has_frame_colors_ = true; + active_frame_color_ = active_color; + inactive_frame_color_ = inactive_color; +} + void ShellSurfaceBase::OnSetParent(Surface* parent, const gfx::Point& position) { views::Widget* parent_widget = @@ -697,7 +772,11 @@ void ShellSurfaceBase::OnSurfaceDestroying(Surface* surface) { // views::WidgetDelegate overrides: bool ShellSurfaceBase::CanResize() const { - return !movement_disabled_; + if (movement_disabled_) + return false; + // The shell surface is resizable by default when min/max size is empty, + // othersize it's resizable when min size != max size. + return minimum_size_.IsEmpty() || minimum_size_ != maximum_size_; } bool ShellSurfaceBase::CanMaximize() const { @@ -749,7 +828,11 @@ views::NonClientFrameView* ShellSurfaceBase::CreateNonClientFrameView( if (!frame_enabled_ && !window_state->HasDelegate()) { window_state->SetDelegate(std::make_unique<CustomWindowStateDelegate>()); } - return new CustomFrameView(widget, frame_enabled_); + CustomFrameView* frame_view = new CustomFrameView( + widget, frame_enabled_, client_controlled_move_resize_); + if (has_frame_colors_) + frame_view->SetFrameColors(active_frame_color_, inactive_frame_color_); + return frame_view; } bool ShellSurfaceBase::WidgetHasHitTestMask() const { @@ -783,6 +866,8 @@ gfx::Size ShellSurfaceBase::GetMinimumSize() const { } gfx::Size ShellSurfaceBase::GetMaximumSize() const { + // On ChromeOS, non empty maximum size will make the window + // non maximizable. return maximum_size_; } @@ -1004,7 +1089,8 @@ void ShellSurfaceBase::CreateShellSurfaceWidget( // events. window->SetEventTargetingPolicy( ui::mojom::EventTargetingPolicy::DESCENDANTS_ONLY); - window->SetEventTargeter(base::WrapUnique(new CustomWindowTargeter(widget_))); + window->SetEventTargeter(base::WrapUnique( + new CustomWindowTargeter(widget_, client_controlled_move_resize_))); SetApplicationId(window, application_id_); SetMainSurface(window, root_surface()); @@ -1086,6 +1172,8 @@ void ShellSurfaceBase::Configure() { } bool ShellSurfaceBase::IsResizing() const { + if (!resizer_) + return false; ash::wm::WindowState* window_state = ash::wm::GetWindowState(widget_->GetNativeWindow()); if (!window_state->is_dragged()) @@ -1108,7 +1196,7 @@ void ShellSurfaceBase::UpdateWidgetBounds() { return; } - // 2) When a window is being dragged. + // 2) When a window is being dragged by |resizer_|. if (IsResizing()) return; diff --git a/chromium/components/exo/shell_surface_base.h b/chromium/components/exo/shell_surface_base.h index 54ccf3a90cd..58d91216f18 100644 --- a/chromium/components/exo/shell_surface_base.h +++ b/chromium/components/exo/shell_surface_base.h @@ -110,6 +110,7 @@ class ShellSurfaceBase : public SurfaceTreeHost, void SetSystemModal(bool system_modal); // Start an interactive move of surface. + // TODO(oshima): Move this to ShellSurface. void Move(); // Sets the application ID for the window. The application ID identifies the @@ -159,6 +160,7 @@ class ShellSurfaceBase : public SurfaceTreeHost, void OnSurfaceCommit() override; bool IsTouchEnabled(Surface* surface) const override; void OnSetFrame(SurfaceFrameType type) override; + void OnSetFrameColors(SkColor active_color, SkColor inactive_color) override; void OnSetParent(Surface* parent, const gfx::Point& position) override; // Overridden from SurfaceObserver: @@ -265,6 +267,7 @@ class ShellSurfaceBase : public SurfaceTreeHost, // Attempt to start a drag operation. The type of drag operation to start is // determined by |component|. + // TODO(oshima): Move this to ShellSurface. void AttemptToStartDrag(int component); // Set the parent window of this surface. @@ -289,6 +292,9 @@ class ShellSurfaceBase : public SurfaceTreeHost, base::string16 title_; std::unique_ptr<ui::CompositorLock> configure_compositor_lock_; ConfigureCallback configure_callback_; + // TODO(oshima): Remove this once the transition to new drag/resize + // complete. https://crbug.com/801666. + bool client_controlled_move_resize_ = true; private: struct Config; @@ -322,6 +328,9 @@ class ShellSurfaceBase : public SurfaceTreeHost, bool activatable_ = true; bool can_minimize_ = true; bool frame_enabled_ = false; + bool has_frame_colors_ = false; + SkColor active_frame_color_ = SK_ColorBLACK; + SkColor inactive_frame_color_ = SK_ColorBLACK; bool pending_show_widget_ = false; std::string application_id_; gfx::Rect geometry_; diff --git a/chromium/components/exo/shell_surface_unittest.cc b/chromium/components/exo/shell_surface_unittest.cc index 117f1fac0e7..ea3e69d668b 100644 --- a/chromium/components/exo/shell_surface_unittest.cc +++ b/chromium/components/exo/shell_surface_unittest.cc @@ -26,6 +26,7 @@ #include "components/exo/wm_helper.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/window.h" +#include "ui/aura/window_delegate.h" #include "ui/base/hit_test.h" #include "ui/compositor/compositor.h" #include "ui/compositor/layer.h" @@ -312,6 +313,11 @@ TEST_F(ShellSurfaceTest, SetMinimumSize) { surface->Attach(buffer.get()); surface->Commit(); EXPECT_EQ(size, shell_surface->GetMinimumSize()); + EXPECT_EQ(size, shell_surface->GetWidget()->GetMinimumSize()); + EXPECT_EQ(size, shell_surface->GetWidget() + ->GetNativeWindow() + ->delegate() + ->GetMinimumSize()); } TEST_F(ShellSurfaceTest, SetMaximumSize) { diff --git a/chromium/components/exo/sub_surface.h b/chromium/components/exo/sub_surface.h index 4663036124b..e0a11185c20 100644 --- a/chromium/components/exo/sub_surface.h +++ b/chromium/components/exo/sub_surface.h @@ -53,6 +53,8 @@ class SubSurface : public SurfaceDelegate, public SurfaceObserver { bool IsSurfaceSynchronized() const override; bool IsTouchEnabled(Surface* surface) const override; void OnSetFrame(SurfaceFrameType type) override {} + void OnSetFrameColors(SkColor active_color, SkColor inactive_color) override { + } void OnSetParent(Surface* parent, const gfx::Point& position) override {} // Overridden from SurfaceObserver: diff --git a/chromium/components/exo/surface.cc b/chromium/components/exo/surface.cc index b9ef72e157e..6b9d48ab3f4 100644 --- a/chromium/components/exo/surface.cc +++ b/chromium/components/exo/surface.cc @@ -46,7 +46,7 @@ #include "ui/gfx/transform_util.h" #include "ui/views/widget/widget.h" -DECLARE_UI_CLASS_PROPERTY_TYPE(exo::Surface*); +DEFINE_UI_CLASS_PROPERTY_TYPE(exo::Surface*); namespace exo { namespace { @@ -264,6 +264,12 @@ void Surface::SetInputRegion(const cc::Region& region) { pending_state_.input_region = region; } +void Surface::ResetInputRegion() { + TRACE_EVENT0("exo", "Surface::ResetInputRegion"); + + pending_state_.input_region = base::nullopt; +} + void Surface::SetInputOutset(int outset) { TRACE_EVENT1("exo", "Surface::SetInputOutset", "outset", outset); @@ -433,6 +439,14 @@ void Surface::SetFrame(SurfaceFrameType type) { delegate_->OnSetFrame(type); } +void Surface::SetFrameColors(SkColor active_color, SkColor inactive_color) { + TRACE_EVENT2("exo", "Surface::SetFrameColors", "active_color", active_color, + "inactive_color", inactive_color); + + if (delegate_) + delegate_->OnSetFrameColors(active_color, inactive_color); +} + void Surface::SetParent(Surface* parent, const gfx::Point& position) { TRACE_EVENT2("exo", "Surface::SetParent", "parent", !!parent, "position", position.ToString()); @@ -484,7 +498,7 @@ void Surface::CommitSurfaceHierarchy(bool synchronized) { pending_state_.only_visible_on_secure_output = false; window_->SetEventTargetingPolicy( - state_.input_region.IsEmpty() + (state_.input_region.has_value() && state_.input_region->IsEmpty()) ? ui::mojom::EventTargetingPolicy::DESCENDANTS_ONLY : ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); @@ -544,8 +558,11 @@ void Surface::CommitSurfaceHierarchy(bool synchronized) { } surface_hierarchy_content_bounds_ = gfx::Rect(content_size_); - hit_test_region_ = state_.input_region; - hit_test_region_.Intersect(surface_hierarchy_content_bounds_); + if (state_.input_region) { + hit_test_region_ = *state_.input_region; + hit_test_region_.Intersect(surface_hierarchy_content_bounds_); + } else + hit_test_region_ = surface_hierarchy_content_bounds_; int outset = state_.input_outset; if (outset > 0) { @@ -634,8 +651,8 @@ Surface::GetHitTestShapeRects() const { return nullptr; auto rects = std::make_unique<aura::WindowTargeter::HitTestRects>(); - for (cc::Region::Iterator it(hit_test_region_); it.has_rect(); it.next()) - rects->push_back(it.rect()); + for (gfx::Rect rect : hit_test_region_) + rects->push_back(rect); return rects; } @@ -710,7 +727,7 @@ bool Surface::FillsBoundsOpaquely() const { //////////////////////////////////////////////////////////////////////////////// // Buffer, private: -Surface::State::State() : input_region(SkRegion(SkIRect::MakeLargest())) {} +Surface::State::State() {} Surface::State::~State() = default; diff --git a/chromium/components/exo/surface.h b/chromium/components/exo/surface.h index 312d9c6d3cd..888a518a9b9 100644 --- a/chromium/components/exo/surface.h +++ b/chromium/components/exo/surface.h @@ -101,6 +101,10 @@ class Surface final : public ui::PropertyHandler { // events. The region is clipped to the surface bounds. void SetInputRegion(const cc::Region& region); + // This resets the region of the surface that can receive pointer and touch + // events to be wide-open. This will be clipped to the surface bounds. + void ResetInputRegion(); + // This overrides the input region to the surface bounds with an outset. // TODO(domlaskowski): Remove this once client-driven resizing is removed. void SetInputOutset(int outset); @@ -143,6 +147,9 @@ class Surface final : public ui::PropertyHandler { // Request that surface should have the specified frame type. void SetFrame(SurfaceFrameType type); + // Request that surface should use a specific set of frame colors. + void SetFrameColors(SkColor active_color, SkColor inactive_color); + // Request "parent" for surface. void SetParent(Surface* parent, const gfx::Point& position); @@ -253,7 +260,7 @@ class Surface final : public ui::PropertyHandler { bool operator!=(const State& other) { return !(*this == other); } cc::Region opaque_region; - cc::Region input_region; + base::Optional<cc::Region> input_region; int input_outset = 0; float buffer_scale = 1.0f; Transform buffer_transform = Transform::NORMAL; diff --git a/chromium/components/exo/surface_delegate.h b/chromium/components/exo/surface_delegate.h index 8c8406d0124..a1895815d07 100644 --- a/chromium/components/exo/surface_delegate.h +++ b/chromium/components/exo/surface_delegate.h @@ -5,6 +5,7 @@ #ifndef COMPONENTS_EXO_SURFACE_DELEGATE_H_ #define COMPONENTS_EXO_SURFACE_DELEGATE_H_ +#include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/point.h" namespace exo { @@ -31,6 +32,10 @@ class SurfaceDelegate { // Called when surface was requested to use a specific frame type. virtual void OnSetFrame(SurfaceFrameType type) = 0; + // Called when surface was requested to use a specific set of frame colors. + virtual void OnSetFrameColors(SkColor active_color, + SkColor inactive_color) = 0; + // Called when a new "parent" was requested for this surface. |position| // is the initial position of surface relative to origin of parent. virtual void OnSetParent(Surface* parent, const gfx::Point& position) = 0; diff --git a/chromium/components/exo/surface_tree_host.h b/chromium/components/exo/surface_tree_host.h index 274a168acee..0cfff8f0dd5 100644 --- a/chromium/components/exo/surface_tree_host.h +++ b/chromium/components/exo/surface_tree_host.h @@ -92,6 +92,8 @@ class SurfaceTreeHost : public SurfaceDelegate, bool IsSurfaceSynchronized() const override; bool IsTouchEnabled(Surface* surface) const override; void OnSetFrame(SurfaceFrameType type) override {} + void OnSetFrameColors(SkColor active_color, SkColor inactive_color) override { + } void OnSetParent(Surface* parent, const gfx::Point& position) override {} // Overridden from cc::BeginFrameObserverBase: diff --git a/chromium/components/exo/touch_unittest.cc b/chromium/components/exo/touch_unittest.cc index 8d5cf6f1412..95411fad841 100644 --- a/chromium/components/exo/touch_unittest.cc +++ b/chromium/components/exo/touch_unittest.cc @@ -6,7 +6,6 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/shell.h" -#include "ash/shell_port.h" #include "ash/wm/window_positioner.h" #include "ash/wm/window_positioning_utils.h" #include "components/exo/buffer.h" @@ -230,7 +229,7 @@ TEST_F(TouchTest, IgnoreTouchEventDuringModal) { // Make the window modal. modal.shell_surface()->SetSystemModal(true); - EXPECT_TRUE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_TRUE(ash::Shell::IsSystemModalWindowOpen()); EXPECT_CALL(delegate, OnTouchShape(testing::_, testing::_, testing::_)) .Times(testing::AnyNumber()); EXPECT_CALL(delegate, CanAcceptTouchEventsForSurface(window.surface())) @@ -270,7 +269,7 @@ TEST_F(TouchTest, IgnoreTouchEventDuringModal) { // Make the window non-modal. modal.shell_surface()->SetSystemModal(false); - EXPECT_FALSE(ash::ShellPort::Get()->IsSystemModalWindowOpen()); + EXPECT_FALSE(ash::Shell::IsSystemModalWindowOpen()); // Check if touch events on non-modal window are registered. { diff --git a/chromium/components/exo/wayland/aura-shell-client-protocol.h b/chromium/components/exo/wayland/aura-shell-client-protocol.h index 8131b8a44ec..bdee99af0cf 100644 --- a/chromium/components/exo/wayland/aura-shell-client-protocol.h +++ b/chromium/components/exo/wayland/aura-shell-client-protocol.h @@ -217,6 +217,7 @@ enum zaura_surface_frame_type { #define ZAURA_SURFACE_SET_FRAME 0 #define ZAURA_SURFACE_SET_PARENT 1 +#define ZAURA_SURFACE_SET_FRAME_COLORS 2 /** @@ -227,6 +228,10 @@ enum zaura_surface_frame_type { * @ingroup iface_zaura_surface */ #define ZAURA_SURFACE_SET_PARENT_SINCE_VERSION 2 +/** + * @ingroup iface_zaura_surface + */ +#define ZAURA_SURFACE_SET_FRAME_COLORS_SINCE_VERSION 3 /** @ingroup iface_zaura_surface */ static inline void @@ -280,6 +285,18 @@ zaura_surface_set_parent(struct zaura_surface *zaura_surface, struct zaura_surfa ZAURA_SURFACE_SET_PARENT, parent, x, y); } +/** + * @ingroup iface_zaura_surface + * + * Set the frame colors. + */ +static inline void +zaura_surface_set_frame_colors(struct zaura_surface *zaura_surface, uint32_t active_color, uint32_t inactive_color) +{ + wl_proxy_marshal((struct wl_proxy *) zaura_surface, + ZAURA_SURFACE_SET_FRAME_COLORS, active_color, inactive_color); +} + #ifndef ZAURA_OUTPUT_SCALE_PROPERTY_ENUM #define ZAURA_OUTPUT_SCALE_PROPERTY_ENUM /** diff --git a/chromium/components/exo/wayland/aura-shell-protocol.c b/chromium/components/exo/wayland/aura-shell-protocol.c index 8dc43414e0e..1e6d4245326 100644 --- a/chromium/components/exo/wayland/aura-shell-protocol.c +++ b/chromium/components/exo/wayland/aura-shell-protocol.c @@ -50,7 +50,7 @@ static const struct wl_message zaura_shell_requests[] = { }; WL_EXPORT const struct wl_interface zaura_shell_interface = { - "zaura_shell", 2, + "zaura_shell", 3, 2, zaura_shell_requests, 0, NULL, }; @@ -58,11 +58,12 @@ WL_EXPORT const struct wl_interface zaura_shell_interface = { static const struct wl_message zaura_surface_requests[] = { { "set_frame", "u", types + 0 }, { "set_parent", "2?oii", types + 6 }, + { "set_frame_colors", "3uu", types + 0 }, }; WL_EXPORT const struct wl_interface zaura_surface_interface = { - "zaura_surface", 2, - 2, zaura_surface_requests, + "zaura_surface", 3, + 3, zaura_surface_requests, 0, NULL, }; diff --git a/chromium/components/exo/wayland/aura-shell-server-protocol.h b/chromium/components/exo/wayland/aura-shell-server-protocol.h index 9328c45e7e0..e306f8d96e4 100644 --- a/chromium/components/exo/wayland/aura-shell-server-protocol.h +++ b/chromium/components/exo/wayland/aura-shell-server-protocol.h @@ -212,6 +212,18 @@ struct zaura_surface_interface { struct wl_resource *parent, int32_t x, int32_t y); + /** + * set the frame colors of this surface + * + * Set the frame colors. + * @param active_color 32 bit ARGB color value, not premultiplied + * @param inactive_color 32 bit ARGB color value, not premultiplied + * @since 3 + */ + void (*set_frame_colors)(struct wl_client *client, + struct wl_resource *resource, + uint32_t active_color, + uint32_t inactive_color); }; @@ -223,6 +235,10 @@ struct zaura_surface_interface { * @ingroup iface_zaura_surface */ #define ZAURA_SURFACE_SET_PARENT_SINCE_VERSION 2 +/** + * @ingroup iface_zaura_surface + */ +#define ZAURA_SURFACE_SET_FRAME_COLORS_SINCE_VERSION 3 #ifndef ZAURA_OUTPUT_SCALE_PROPERTY_ENUM #define ZAURA_OUTPUT_SCALE_PROPERTY_ENUM diff --git a/chromium/components/exo/wayland/clients/client_base.cc b/chromium/components/exo/wayland/clients/client_base.cc index 28b75a1cbbd..88e6255b3e2 100644 --- a/chromium/components/exo/wayland/clients/client_base.cc +++ b/chromium/components/exo/wayland/clients/client_base.cc @@ -471,9 +471,7 @@ bool ClientBase::Init(const InitParams& params) { native_interface = sk_sp<const GrGLInterface>(GrGLCreateNativeInterface()); DCHECK(native_interface); - gr_context_ = sk_sp<GrContext>(GrContext::Create( - kOpenGL_GrBackend, - reinterpret_cast<GrBackendContext>(native_interface.get()))); + gr_context_ = GrContext::MakeGL(std::move(native_interface)); DCHECK(gr_context_); #if defined(USE_VULKAN) diff --git a/chromium/components/exo/wayland/clients/rects.cc b/chromium/components/exo/wayland/clients/rects.cc index 307ad3a4c72..f15af3066a0 100644 --- a/chromium/components/exo/wayland/clients/rects.cc +++ b/chromium/components/exo/wayland/clients/rects.cc @@ -196,9 +196,14 @@ void FeedbackDiscarded(void* data, struct wp_presentation_feedback* presentation_feedback) { Presentation* presentation = static_cast<Presentation*>(data); DCHECK_GT(presentation->scheduled_frames.size(), 0u); - std::unique_ptr<Frame> frame = - std::move(presentation->scheduled_frames.front()); - presentation->scheduled_frames.pop_front(); + auto it = + std::find_if(presentation->scheduled_frames.begin(), + presentation->scheduled_frames.end(), + [presentation_feedback](std::unique_ptr<Frame>& frame) { + return frame->feedback.get() == presentation_feedback; + }); + DCHECK(it != presentation->scheduled_frames.end()); + presentation->scheduled_frames.erase(it); LOG(WARNING) << "Frame discarded"; } diff --git a/chromium/components/exo/wayland/clients/simple.cc b/chromium/components/exo/wayland/clients/simple.cc index 6f59102fa1b..2712e35cee2 100644 --- a/chromium/components/exo/wayland/clients/simple.cc +++ b/chromium/components/exo/wayland/clients/simple.cc @@ -68,10 +68,12 @@ void FeedbackPresented(void* data, void FeedbackDiscarded(void* data, struct wp_presentation_feedback* feedback) { Presentation* presentation = static_cast<Presentation*>(data); DCHECK_GT(presentation->submitted_frames.size(), 0u); - - Frame& frame = presentation->submitted_frames.front(); - DCHECK_EQ(frame.feedback.get(), feedback); - presentation->submitted_frames.pop_front(); + auto it = std::find_if( + presentation->submitted_frames.begin(), + presentation->submitted_frames.end(), + [feedback](Frame& frame) { return frame.feedback.get() == feedback; }); + DCHECK(it != presentation->submitted_frames.end()); + presentation->submitted_frames.erase(it); } } // namespace diff --git a/chromium/components/exo/wayland/protocol/aura-shell.xml b/chromium/components/exo/wayland/protocol/aura-shell.xml index f4d99e7c6b2..549b2883888 100644 --- a/chromium/components/exo/wayland/protocol/aura-shell.xml +++ b/chromium/components/exo/wayland/protocol/aura-shell.xml @@ -24,7 +24,7 @@ DEALINGS IN THE SOFTWARE. </copyright> - <interface name="zaura_shell" version="2"> + <interface name="zaura_shell" version="3"> <description summary="aura_shell"> The global interface exposing aura shell capabilities is used to instantiate an interface extension for a wl_surface object. @@ -68,7 +68,7 @@ </request> </interface> - <interface name="zaura_surface" version="2"> + <interface name="zaura_surface" version="3"> <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. @@ -101,6 +101,16 @@ <arg name="x" type="int"/> <arg name="y" type="int"/> </request> + + <!-- Version 3 additions --> + + <request name="set_frame_colors" since="3"> + <description summary="set the frame colors of this surface"> + Set the frame colors. + </description> + <arg name="active_color" type="uint" summary="32 bit ARGB color value, not premultiplied"/> + <arg name="inactive_color" type="uint" summary="32 bit ARGB color value, not premultiplied"/> + </request> </interface> <interface name="zaura_output" version="2"> diff --git a/chromium/components/exo/wayland/server.cc b/chromium/components/exo/wayland/server.cc index 120e9d40870..c60295e8c97 100644 --- a/chromium/components/exo/wayland/server.cc +++ b/chromium/components/exo/wayland/server.cc @@ -39,6 +39,7 @@ #include "ash/public/interfaces/window_pin_type.mojom.h" #include "ash/public/interfaces/window_state_type.mojom.h" #include "ash/shell.h" +#include "ash/wm/window_resizer.h" #include "base/bind.h" #include "base/cancelable_callback.h" #include "base/command_line.h" @@ -117,7 +118,7 @@ #include "ui/events/keycodes/scoped_xkb.h" // nogncheck #endif -DECLARE_UI_CLASS_PROPERTY_TYPE(wl_resource*); +DEFINE_UI_CLASS_PROPERTY_TYPE(wl_resource*); namespace exo { namespace wayland { @@ -362,9 +363,12 @@ void surface_set_opaque_region(wl_client* client, void surface_set_input_region(wl_client* client, wl_resource* resource, wl_resource* region_resource) { - SkRegion region = region_resource ? *GetUserDataAs<SkRegion>(region_resource) - : SkRegion(SkIRect::MakeLargest()); - GetUserDataAs<Surface>(resource)->SetInputRegion(cc::Region(region)); + Surface* surface = GetUserDataAs<Surface>(resource); + if (region_resource) { + surface->SetInputRegion( + cc::Region(*GetUserDataAs<SkRegion>(region_resource))); + } else + surface->ResetInputRegion(); } void surface_commit(wl_client* client, wl_resource* resource) { @@ -2030,7 +2034,8 @@ void remote_surface_set_window_type(wl_client* client, } void remote_surface_resize(wl_client* client, wl_resource* resource) { - GetUserDataAs<ShellSurface>(resource)->Resize(HTBORDER); + GetUserDataAs<ClientControlledShellSurface>(resource) + ->StartResize_DEPRECATED(); } void remote_surface_set_resize_outset(wl_client* client, @@ -2040,6 +2045,39 @@ void remote_surface_set_resize_outset(wl_client* client, outset); } +void remote_surface_start_move(wl_client* client, + wl_resource* resource, + int32_t x, + int32_t y) { + GetUserDataAs<ClientControlledShellSurface>(resource)->StartMove( + gfx::Point(x, y)); +} + +void remote_surface_set_can_maximize(wl_client* client, wl_resource* resource) { + GetUserDataAs<ClientControlledShellSurface>(resource)->SetCanMaximize(true); +} + +void remote_surface_unset_can_maximize(wl_client* client, + wl_resource* resource) { + GetUserDataAs<ClientControlledShellSurface>(resource)->SetCanMaximize(false); +} + +void remote_surface_set_min_size(wl_client* client, + wl_resource* resource, + int32_t width, + int32_t height) { + GetUserDataAs<ClientControlledShellSurface>(resource)->SetMinimumSize( + gfx::Size(width, height)); +} + +void remote_surface_set_max_size(wl_client* client, + wl_resource* resource, + int32_t width, + int32_t height) { + GetUserDataAs<ClientControlledShellSurface>(resource)->SetMaximumSize( + gfx::Size(width, height)); +} + const struct zcr_remote_surface_v1_interface remote_surface_implementation = { remote_surface_destroy, remote_surface_set_app_id, @@ -2068,7 +2106,12 @@ const struct zcr_remote_surface_v1_interface remote_surface_implementation = { remote_surface_set_orientation, remote_surface_set_window_type, remote_surface_resize, - remote_surface_set_resize_outset}; + remote_surface_set_resize_outset, + remote_surface_start_move, + remote_surface_set_can_maximize, + remote_surface_unset_can_maximize, + remote_surface_set_min_size, + remote_surface_set_max_size}; //////////////////////////////////////////////////////////////////////////////// // notification_surface_interface: @@ -2331,6 +2374,70 @@ void HandleRemoteSurfaceStateChangedCallback( wl_client_flush(wl_resource_get_client(resource)); } +void HandleRemoteSurfaceBoundsChangedCallback( + wl_resource* resource, + ash::mojom::WindowStateType current_state_type, + int64_t display_id, + const gfx::Rect& bounds, + bool resize, + int bounds_change) { + zcr_remote_surface_v1_bounds_change_reason reason = + resize ? ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_RESIZE + : ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_MOVE; + if (bounds_change & ash::WindowResizer::kBoundsChange_Resizes) { + reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_RESIZE; + } else if (bounds_change & ash::WindowResizer::kBoundsChange_Repositions) { + reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_MOVE; + } + zcr_remote_surface_v1_send_bounds_changed( + resource, static_cast<uint32_t>(display_id >> 32), + static_cast<uint32_t>(display_id), bounds.x(), bounds.y(), bounds.width(), + bounds.height(), reason); + wl_client_flush(wl_resource_get_client(resource)); +} + +uint32_t ResizeDirection(int component) { + switch (component) { + case HTCAPTION: + return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE; + case HTTOP: + return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP; + case HTTOPRIGHT: + return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT; + case HTRIGHT: + return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT; + case HTBOTTOMRIGHT: + return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT; + case HTBOTTOM: + return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM; + case HTBOTTOMLEFT: + return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT; + case HTLEFT: + return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT; + case HTTOPLEFT: + return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT; + default: + LOG(ERROR) << "Unknown component:" << component; + break; + } + NOTREACHED(); + return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE; +} + +void HandleRemoteSurfaceDragStartedCallback(wl_resource* resource, + int component) { + zcr_remote_surface_v1_send_drag_started(resource, ResizeDirection(component)); + wl_client_flush(wl_resource_get_client(resource)); +} + +void HandleRemoteSurfaceDragFinishedCallback(wl_resource* resource, + int x, + int y, + bool canceled) { + zcr_remote_surface_v1_send_drag_finished(resource, x, y, canceled ? 1 : 0); + wl_client_flush(wl_resource_get_client(resource)); +} + uint32_t HandleRemoteSurfaceConfigureCallback( wl_resource* resource, const gfx::Size& size, @@ -2398,6 +2505,19 @@ void remote_shell_get_remote_surface(wl_client* client, base::Unretained(remote_surface_resource))); } + if (wl_resource_get_version(remote_surface_resource) >= 10) { + shell_surface->set_client_controlled_move_resize(false); + shell_surface->set_bounds_changed_callback( + base::BindRepeating(&HandleRemoteSurfaceBoundsChangedCallback, + base::Unretained(remote_surface_resource))); + shell_surface->set_drag_started_callback( + base::BindRepeating(&HandleRemoteSurfaceDragStartedCallback, + base::Unretained(remote_surface_resource))); + shell_surface->set_drag_finished_callback( + base::BindRepeating(&HandleRemoteSurfaceDragFinishedCallback, + base::Unretained(remote_surface_resource))); + } + SetImplementation(remote_surface_resource, &remote_surface_implementation, std::move(shell_surface)); } @@ -2435,7 +2555,7 @@ const struct zcr_remote_shell_v1_interface remote_shell_implementation = { remote_shell_destroy, remote_shell_get_remote_surface, remote_shell_get_notification_surface}; -const uint32_t remote_shell_version = 9; +const uint32_t remote_shell_version = 10; void bind_remote_shell(wl_client* client, void* data, @@ -2471,6 +2591,12 @@ class AuraSurface : public SurfaceObserver { surface_->SetFrame(type); } + void SetFrameColors(SkColor active_frame_color, + SkColor inactive_frame_color) { + if (surface_) + surface_->SetFrameColors(active_frame_color, inactive_frame_color); + } + void SetParent(AuraSurface* parent, const gfx::Point& position) { if (surface_) surface_->SetParent(parent ? parent->surface_ : nullptr, position); @@ -2517,8 +2643,17 @@ void aura_surface_set_parent(wl_client* client, gfx::Point(x, y)); } +void aura_surface_set_frame_colors(wl_client* client, + wl_resource* resource, + uint32_t active_color, + uint32_t inactive_color) { + GetUserDataAs<AuraSurface>(resource)->SetFrameColors(active_color, + inactive_color); +} + const struct zaura_surface_interface aura_surface_implementation = { - aura_surface_set_frame, aura_surface_set_parent}; + aura_surface_set_frame, aura_surface_set_parent, + aura_surface_set_frame_colors}; //////////////////////////////////////////////////////////////////////////////// // aura_output_interface: @@ -2609,7 +2744,7 @@ void aura_shell_get_aura_output(wl_client* client, const struct zaura_shell_interface aura_shell_implementation = { aura_shell_get_aura_surface, aura_shell_get_aura_output}; -const uint32_t aura_shell_version = 2; +const uint32_t aura_shell_version = 3; void bind_aura_shell(wl_client* client, void* data, diff --git a/chromium/components/exo/wm_helper.cc b/chromium/components/exo/wm_helper.cc index 9a086bda61a..bb5210ebbdb 100644 --- a/chromium/components/exo/wm_helper.cc +++ b/chromium/components/exo/wm_helper.cc @@ -71,18 +71,6 @@ void WMHelper::RemoveFocusObserver( aura::client::GetFocusClient(GetPrimaryRoot())->RemoveObserver(observer); } -void WMHelper::AddCursorObserver(aura::client::CursorClientObserver* observer) { - // TODO(crbug.com/631103): Mushrome doesn't have a cursor manager yet. - if (ash::Shell::GetAshConfig() == ash::Config::CLASSIC) - ash::Shell::Get()->cursor_manager()->AddObserver(observer); -} - -void WMHelper::RemoveCursorObserver( - aura::client::CursorClientObserver* observer) { - if (ash::Shell::GetAshConfig() == ash::Config::CLASSIC) - ash::Shell::Get()->cursor_manager()->RemoveObserver(observer); -} - void WMHelper::AddTabletModeObserver(ash::TabletModeObserver* observer) { ash::Shell::Get()->tablet_mode_controller()->AddObserver(observer); } @@ -182,20 +170,8 @@ aura::Window* WMHelper::GetFocusedWindow() const { return focus_client->GetFocusedWindow(); } -ui::CursorSize WMHelper::GetCursorSize() const { - // TODO(crbug.com/631103): Mushrome doesn't have a cursor manager yet. - if (ash::Shell::GetAshConfig() == ash::Config::MUS) - return ui::CursorSize::kNormal; - return ash::Shell::Get()->cursor_manager()->GetCursorSize(); -} - -const display::Display& WMHelper::GetCursorDisplay() const { - // TODO(crbug.com/631103): Mushrome doesn't have a cursor manager yet. - if (ash::Shell::GetAshConfig() == ash::Config::MUS) { - static const display::Display display; - return display; - } - return ash::Shell::Get()->cursor_manager()->GetDisplay(); +aura::client::CursorClient* WMHelper::GetCursorClient() { + return aura::client::GetCursorClient(ash::Shell::GetPrimaryRootWindow()); } void WMHelper::AddPreTargetHandler(ui::EventHandler* handler) { diff --git a/chromium/components/exo/wm_helper.h b/chromium/components/exo/wm_helper.h index 2911c6d5526..fabb42d4b39 100644 --- a/chromium/components/exo/wm_helper.h +++ b/chromium/components/exo/wm_helper.h @@ -19,7 +19,7 @@ class TabletModeObserver; namespace aura { class Window; namespace client { -class CursorClientObserver; +class CursorClient; class FocusChangeObserver; } // namespace client } // namespace aura @@ -29,7 +29,6 @@ class ActivationChangeObserver; } namespace display { -class Display; class ManagedDisplayInfo; } @@ -70,8 +69,6 @@ class WMHelper : public aura::client::DragDropDelegate { void RemoveActivationObserver(wm::ActivationChangeObserver* observer); void AddFocusObserver(aura::client::FocusChangeObserver* observer); void RemoveFocusObserver(aura::client::FocusChangeObserver* observer); - void AddCursorObserver(aura::client::CursorClientObserver* observer); - void RemoveCursorObserver(aura::client::CursorClientObserver* observer); void AddTabletModeObserver(ash::TabletModeObserver* observer); void RemoveTabletModeObserver(ash::TabletModeObserver* observer); void AddInputDeviceEventObserver(ui::InputDeviceEventObserver* observer); @@ -92,8 +89,7 @@ class WMHelper : public aura::client::DragDropDelegate { aura::Window* GetPrimaryDisplayContainer(int container_id); aura::Window* GetActiveWindow() const; aura::Window* GetFocusedWindow() const; - ui::CursorSize GetCursorSize() const; - const display::Display& GetCursorDisplay() const; + aura::client::CursorClient* GetCursorClient(); void AddPreTargetHandler(ui::EventHandler* handler); void PrependPreTargetHandler(ui::EventHandler* handler); void RemovePreTargetHandler(ui::EventHandler* handler); |