| // Copyright 2021 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/exo/wayland/zcr_remote_shell_impl.h" |
| |
| #include "ash/public/cpp/arc_resize_lock_type.h" |
| #include "ash/shelf/shelf_layout_manager.h" |
| #include "ash/shell.h" |
| #include "ash/wm/window_resizer.h" |
| #include "base/command_line.h" |
| #include "chromeos/ui/base/window_pin_type.h" |
| #include "components/exo/display.h" |
| #include "components/exo/wayland/server_util.h" |
| #include "components/exo/wm_helper_chromeos.h" |
| #include "ui/display/screen.h" |
| #include "ui/views/window/caption_button_types.h" |
| #include "ui/wm/core/window_animations.h" |
| |
| namespace exo { |
| namespace wayland { |
| |
| // Ensure that V1 and V2 constants remain identical. |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_VISIBLE) == |
| static_cast<int>( |
| ZCR_REMOTE_SURFACE_V2_SYSTEMUI_VISIBILITY_STATE_VISIBLE), |
| "ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_VISIBLE and " |
| "ZCR_REMOTE_SURFACE_V2_SYSTEMUI_VISIBILITY_STATE_VISIBLE should be equal"); |
| static_assert( |
| static_cast<int>( |
| ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_AUTOHIDE_NON_STICKY) == |
| static_cast<int>( |
| ZCR_REMOTE_SURFACE_V2_SYSTEMUI_VISIBILITY_STATE_AUTOHIDE_NON_STICKY), |
| "ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_AUTOHIDE_NON_STICKY and " |
| "ZCR_REMOTE_SURFACE_V2_SYSTEMUI_VISIBILITY_STATE_AUTOHIDE_NON_STICKY " |
| "should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_VISIBLE) == |
| static_cast<int>(ZCR_REMOTE_OUTPUT_V2_SYSTEMUI_BEHAVIOR_VISIBLE), |
| "ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_VISIBLE and " |
| "ZCR_REMOTE_OUTPUT_V2_SYSTEMUI_BEHAVIOR_VISIBLE should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_HIDDEN) == |
| static_cast<int>(ZCR_REMOTE_OUTPUT_V2_SYSTEMUI_BEHAVIOR_HIDDEN), |
| "ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_HIDDEN and " |
| "ZCR_REMOTE_OUTPUT_V2_SYSTEMUI_BEHAVIOR_HIDDEN should be equal"); |
| static_assert(static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_NONE), |
| "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE and " |
| "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_NONE should be equal"); |
| static_assert(static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_TOP), |
| "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP and " |
| "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_TOP should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_TOPRIGHT), |
| "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT and " |
| "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_TOPRIGHT should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_RIGHT), |
| "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT and " |
| "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_RIGHT should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_BOTTOMRIGHT), |
| "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT and " |
| "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_BOTTOMRIGHT should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_BOTTOM), |
| "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM and " |
| "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_BOTTOM should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_BOTTOMLEFT), |
| "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT and " |
| "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_BOTTOMLEFT should be equal"); |
| static_assert(static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_LEFT), |
| "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT and " |
| "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_LEFT should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_TOPLEFT), |
| "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT and " |
| "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_TOPLEFT should be equal"); |
| static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET) == |
| static_cast<int>(ZCR_REMOTE_SHELL_V2_LAYOUT_MODE_TABLET), |
| "ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET and " |
| "ZCR_REMOTE_SHELL_V2_LAYOUT_MODE_TABLET should be equal"); |
| static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED) == |
| static_cast<int>(ZCR_REMOTE_SHELL_V2_LAYOUT_MODE_WINDOWED), |
| "ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED and " |
| "ZCR_REMOTE_SHELL_V2_LAYOUT_MODE_WINDOWED should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_CLIENT_FOCUSED) == |
| static_cast<int>( |
| ZCR_REMOTE_SHELL_V2_DESKTOP_FOCUS_STATE_CLIENT_FOCUSED), |
| "ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_CLIENT_FOCUSED and " |
| "ZCR_REMOTE_SHELL_V2_DESKTOP_FOCUS_STATE_CLIENT_FOCUSED should be equal"); |
| static_assert( |
| static_cast<int>( |
| ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_OTHER_CLIENT_FOCUSED) == |
| static_cast<int>( |
| ZCR_REMOTE_SHELL_V2_DESKTOP_FOCUS_STATE_OTHER_CLIENT_FOCUSED), |
| "ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_OTHER_CLIENT_FOCUSED and " |
| "ZCR_REMOTE_SHELL_V2_DESKTOP_FOCUS_STATE_OTHER_CLIENT_FOCUSED should be " |
| "equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_NO_FOCUS) == |
| static_cast<int>(ZCR_REMOTE_SHELL_V2_DESKTOP_FOCUS_STATE_NO_FOCUS), |
| "ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_NO_FOCUS and " |
| "ZCR_REMOTE_SHELL_V2_DESKTOP_FOCUS_STATE_NO_FOCUS should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_RESIZE) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_RESIZE), |
| "ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_RESIZE and " |
| "ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_RESIZE should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_MOVE) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_MOVE), |
| "ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_MOVE and " |
| "ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_MOVE should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_PIP) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_PIP), |
| "ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_PIP and " |
| "ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_PIP should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_RESIZE) == |
| static_cast<int>( |
| ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_DRAG_RESIZE), |
| "ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_RESIZE and " |
| "ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_DRAG_RESIZE should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_MOVE) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_DRAG_MOVE), |
| "ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_MOVE and " |
| "ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_DRAG_MOVE should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_LEFT) == |
| static_cast<int>( |
| ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_SNAP_TO_LEFT), |
| "ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_LEFT and " |
| "ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_SNAP_TO_LEFT should be equal"); |
| static_assert( |
| static_cast<int>( |
| ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_RIGHT) == |
| static_cast<int>( |
| ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_SNAP_TO_RIGHT), |
| "ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_RIGHT and " |
| "ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_SNAP_TO_RIGHT should be equal"); |
| static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_NORMAL) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_NORMAL), |
| "ZCR_REMOTE_SHELL_V1_STATE_TYPE_NORMAL and " |
| "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_NORMAL should be equal"); |
| static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_MINIMIZED) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_MINIMIZED), |
| "ZCR_REMOTE_SHELL_V1_STATE_TYPE_MINIMIZED and " |
| "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_MINIMIZED should be equal"); |
| static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_MAXIMIZED) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_MAXIMIZED), |
| "ZCR_REMOTE_SHELL_V1_STATE_TYPE_MAXIMIZED and " |
| "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_MAXIMIZED should be equal"); |
| static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_FULLSCREEN) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_FULLSCREEN), |
| "ZCR_REMOTE_SHELL_V1_STATE_TYPE_FULLSCREEN and " |
| "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_FULLSCREEN should be equal"); |
| static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_PINNED) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_PINNED), |
| "ZCR_REMOTE_SHELL_V1_STATE_TYPE_PINNED and " |
| "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_PINNED should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_TRUSTED_PINNED) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_TRUSTED_PINNED), |
| "ZCR_REMOTE_SHELL_V1_STATE_TYPE_TRUSTED_PINNED and " |
| "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_TRUSTED_PINNED should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_LEFT_SNAPPED) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_LEFT_SNAPPED), |
| "ZCR_REMOTE_SHELL_V1_STATE_TYPE_LEFT_SNAPPED and " |
| "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_LEFT_SNAPPED should be equal"); |
| static_assert( |
| static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_RIGHT_SNAPPED) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_RIGHT_SNAPPED), |
| "ZCR_REMOTE_SHELL_V1_STATE_TYPE_RIGHT_SNAPPED and " |
| "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_RIGHT_SNAPPED should be equal"); |
| static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_PIP) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_PIP), |
| "ZCR_REMOTE_SHELL_V1_STATE_TYPE_PIP and " |
| "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_PIP should be equal"); |
| static_assert(static_cast<int>(ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_IN) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_ZOOM_CHANGE_IN), |
| "ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_IN and " |
| "ZCR_REMOTE_SURFACE_V2_ZOOM_CHANGE_IN should be equal"); |
| static_assert(static_cast<int>(ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_OUT) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_ZOOM_CHANGE_OUT), |
| "ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_OUT and " |
| "ZCR_REMOTE_SURFACE_V2_ZOOM_CHANGE_OUT should be equal"); |
| static_assert(static_cast<int>(ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_RESET) == |
| static_cast<int>(ZCR_REMOTE_SURFACE_V2_ZOOM_CHANGE_RESET), |
| "ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_RESET and " |
| "ZCR_REMOTE_SURFACE_V2_ZOOM_CHANGE_RESET should be equal"); |
| |
| using chromeos::WindowStateType; |
| |
| // We don't send configure immediately after tablet mode switch |
| // because layout can change due to orientation lock state or accelerometer. |
| constexpr int kConfigureDelayAfterLayoutSwitchMs = 300; |
| |
| constexpr int kRemoteShellSeatObserverPriority = 0; |
| static_assert(Seat::IsValidObserverPriority(kRemoteShellSeatObserverPriority), |
| "kRemoteShellSeatObserverPriority is not in the valid range."); |
| |
| // Convert to 8.24 fixed format. |
| int32_t To8_24Fixed(double value) { |
| constexpr int kDecimalBits = 24; |
| return static_cast<int32_t>(value * (1 << kDecimalBits)); |
| } |
| |
| ash::ShelfLayoutManager* GetShelfLayoutManagerForDisplay( |
| const display::Display& display) { |
| auto* root = ash::Shell::GetRootWindowForDisplayId(display.id()); |
| return ash::Shelf::ForWindow(root)->shelf_layout_manager(); |
| } |
| |
| int SystemUiVisibility(const display::Display& display) { |
| auto* shelf_layout_manager = GetShelfLayoutManagerForDisplay(display); |
| switch (shelf_layout_manager->visibility_state()) { |
| case ash::SHELF_VISIBLE: |
| return ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_VISIBLE; |
| case ash::SHELF_AUTO_HIDE: |
| case ash::SHELF_HIDDEN: |
| return ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_AUTOHIDE_NON_STICKY; |
| } |
| NOTREACHED() << "Got unexpected shelf visibility state " |
| << shelf_layout_manager->visibility_state(); |
| return 0; |
| } |
| |
| int SystemUiBehavior(const display::Display& display) { |
| auto* shelf_layout_manager = GetShelfLayoutManagerForDisplay(display); |
| switch (shelf_layout_manager->auto_hide_behavior()) { |
| case ash::ShelfAutoHideBehavior::kNever: |
| return ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_VISIBLE; |
| case ash::ShelfAutoHideBehavior::kAlways: |
| case ash::ShelfAutoHideBehavior::kAlwaysHidden: |
| return ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_HIDDEN; |
| } |
| NOTREACHED() << "Got unexpected shelf visibility behavior."; |
| return 0; |
| } |
| |
| 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; |
| } |
| |
| // This is a workaround for b/148977363 |
| void MaybeApplyCTSHack(int layout_mode, |
| const gfx::Size& size_in_pixel, |
| gfx::Insets* insets_in_client_pixel, |
| gfx::Insets* stable_insets_in_client_pixel) { |
| constexpr int kBadBottomInsets = 90; |
| if (layout_mode == ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET && |
| size_in_pixel.width() == 3000 && size_in_pixel.height() == 2000 && |
| stable_insets_in_client_pixel->bottom() == kBadBottomInsets) { |
| stable_insets_in_client_pixel->set_bottom(kBadBottomInsets + 1); |
| if (insets_in_client_pixel->bottom() == kBadBottomInsets) |
| insets_in_client_pixel->set_bottom(kBadBottomInsets + 1); |
| } |
| } |
| |
| bool WaylandRemoteOutput::SendDisplayMetrics(const display::Display& display, |
| uint32_t changed_metrics) { |
| if (wl_resource_get_version(resource_) < |
| event_mapping_.stable_insets_since_version) { |
| return false; |
| } |
| |
| if (initial_config_sent_ && |
| !(changed_metrics & display::DisplayObserver::DISPLAY_METRIC_WORK_AREA)) { |
| return false; |
| } |
| |
| if (!initial_config_sent_) { |
| initial_config_sent_ = true; |
| |
| uint32_t display_id_hi = static_cast<uint32_t>(display.id() >> 32); |
| uint32_t display_id_lo = static_cast<uint32_t>(display.id()); |
| if (event_mapping_.send_display_id) |
| event_mapping_.send_display_id(resource_, display_id_hi, display_id_lo); |
| |
| constexpr int64_t DISPLAY_ID_PORT_MASK = 0xff; |
| uint32_t port = static_cast<uint32_t>(display.id() & DISPLAY_ID_PORT_MASK); |
| if (event_mapping_.send_port) |
| event_mapping_.send_port(resource_, port); |
| |
| wl_array data; |
| wl_array_init(&data); |
| |
| const auto& bytes = |
| WMHelper::GetInstance()->GetDisplayIdentificationData(display.id()); |
| for (uint8_t byte : bytes) { |
| uint8_t* ptr = |
| static_cast<uint8_t*>(wl_array_add(&data, sizeof(uint8_t))); |
| DCHECK(ptr); |
| *ptr = byte; |
| } |
| event_mapping_.send_identification_data(resource_, &data); |
| wl_array_release(&data); |
| } |
| |
| float device_scale_factor = display.device_scale_factor(); |
| gfx::Size size_in_pixel = display.GetSizeInPixel(); |
| |
| gfx::Insets insets_in_pixel = GetWorkAreaInsetsInPixel( |
| display, device_scale_factor, size_in_pixel, display.work_area()); |
| event_mapping_.send_insets(resource_, insets_in_pixel.left(), |
| insets_in_pixel.top(), insets_in_pixel.right(), |
| insets_in_pixel.bottom()); |
| |
| gfx::Insets stable_insets_in_pixel = GetWorkAreaInsetsInPixel( |
| display, device_scale_factor, size_in_pixel, GetStableWorkArea(display)); |
| event_mapping_.send_stable_insets( |
| resource_, stable_insets_in_pixel.left(), stable_insets_in_pixel.top(), |
| stable_insets_in_pixel.right(), stable_insets_in_pixel.bottom()); |
| |
| // Currently no client uses zcr_remote_output_v1 systemui_visibility. |
| // Only systemui_behavior is sent here. |
| if (wl_resource_get_version(resource_) >= |
| event_mapping_.system_ui_behavior_since_version) { |
| int systemui_behavior = SystemUiBehavior(display); |
| event_mapping_.send_systemui_behavior(resource_, systemui_behavior); |
| } |
| |
| return true; |
| } |
| |
| WaylandRemoteSurfaceDelegate::WaylandRemoteSurfaceDelegate( |
| base::WeakPtr<WaylandRemoteShell> shell, |
| wl_resource* resource, |
| WaylandRemoteShellEventMapping event_mapping) |
| : shell_(std::move(shell)), |
| resource_(resource), |
| event_mapping_(event_mapping) {} |
| |
| WaylandRemoteSurfaceDelegate::~WaylandRemoteSurfaceDelegate() { |
| if (shell_) |
| shell_->OnRemoteSurfaceDestroyed(resource_); |
| } |
| |
| // ClientControlledShellSurfaceDelegate: |
| void WaylandRemoteSurfaceDelegate::OnGeometryChanged( |
| const gfx::Rect& geometry) { |
| if (shell_) |
| shell_->OnRemoteSurfaceGeometryChanged(resource_, geometry); |
| } |
| void WaylandRemoteSurfaceDelegate::OnStateChanged( |
| chromeos::WindowStateType old_state_type, |
| chromeos::WindowStateType new_state_type) { |
| shell_->OnRemoteSurfaceStateChanged(resource_, old_state_type, |
| new_state_type); |
| } |
| void WaylandRemoteSurfaceDelegate::OnBoundsChanged( |
| chromeos::WindowStateType current_state, |
| chromeos::WindowStateType requested_state, |
| int64_t display_id, |
| const gfx::Rect& bounds_in_display, |
| bool is_resize, |
| int bounds_change) { |
| if (shell_) { |
| shell_->OnRemoteSurfaceBoundsChanged( |
| resource_, current_state, requested_state, display_id, |
| bounds_in_display, is_resize, bounds_change); |
| } |
| } |
| void WaylandRemoteSurfaceDelegate::OnDragStarted(int component) { |
| event_mapping_.send_drag_started(resource_, ResizeDirection(component)); |
| wl_client_flush(wl_resource_get_client(resource_)); |
| } |
| void WaylandRemoteSurfaceDelegate::OnDragFinished(int x, int y, bool canceled) { |
| event_mapping_.send_drag_finished(resource_, x, y, canceled ? 1 : 0); |
| wl_client_flush(wl_resource_get_client(resource_)); |
| } |
| void WaylandRemoteSurfaceDelegate::OnZoomLevelChanged(ZoomChange zoom_change) { |
| if (wl_resource_get_version(resource_) >= |
| event_mapping_.change_zoom_level_since_version && |
| shell_) { |
| shell_->OnRemoteSurfaceChangeZoomLevel(resource_, zoom_change); |
| } |
| } |
| |
| using OutputResourceProvider = base::RepeatingCallback<wl_resource*(int64_t)>; |
| |
| WaylandRemoteShell::WaylandRemoteShell( |
| Display* display, |
| wl_resource* remote_shell_resource, |
| OutputResourceProvider output_provider, |
| WaylandRemoteShellEventMapping event_mapping, |
| bool use_default_scale_cancellation_default) |
| : event_mapping_(event_mapping), |
| display_(display), |
| remote_shell_resource_(remote_shell_resource), |
| output_provider_(output_provider), |
| use_default_scale_cancellation_(use_default_scale_cancellation_default), |
| seat_(display->seat()) { |
| WMHelperChromeOS* helper = WMHelperChromeOS::GetInstance(); |
| helper->AddTabletModeObserver(this); |
| helper->AddFrameThrottlingObserver(); |
| helper->SetDefaultScaleCancellation(use_default_scale_cancellation_); |
| |
| layout_mode_ = helper->InTabletMode() |
| ? ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET |
| : ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED; |
| |
| if (wl_resource_get_version(remote_shell_resource_) >= |
| event_mapping_.layout_mode_since_version) { |
| event_mapping_.send_layout_mode(remote_shell_resource_, layout_mode_); |
| } |
| |
| if (wl_resource_get_version(remote_shell_resource_) >= |
| event_mapping_.default_device_scale_factor_since_version) { |
| double scale_factor = GetDefaultDeviceScaleFactor(); |
| int32_t fixed_scale = To8_24Fixed(scale_factor); |
| event_mapping_.send_default_device_scale_factor(remote_shell_resource_, |
| fixed_scale); |
| } |
| |
| SendDisplayMetrics(); |
| |
| // The activation event has been moved to aura_shell, but the |
| // desktop_focus_state event is still in remote_shell, which needs to be |
| // called before the activation event. |
| display->seat()->AddObserver(this, kRemoteShellSeatObserverPriority); |
| } |
| |
| WaylandRemoteShell::~WaylandRemoteShell() { |
| WMHelperChromeOS* helper = WMHelperChromeOS::GetInstance(); |
| helper->RemoveTabletModeObserver(this); |
| helper->RemoveFrameThrottlingObserver(); |
| if (seat_) |
| seat_->RemoveObserver(this); |
| } |
| |
| std::unique_ptr<ClientControlledShellSurface> |
| WaylandRemoteShell::CreateShellSurface(Surface* surface, |
| int container, |
| double default_device_scale_factor) { |
| return display_->CreateOrGetClientControlledShellSurface( |
| surface, container, default_device_scale_factor, |
| use_default_scale_cancellation_); |
| } |
| |
| std::unique_ptr<ClientControlledShellSurface::Delegate> |
| WaylandRemoteShell::CreateShellSurfaceDelegate(wl_resource* resource) { |
| return std::make_unique<WaylandRemoteSurfaceDelegate>( |
| weak_ptr_factory_.GetWeakPtr(), resource, event_mapping_); |
| } |
| |
| std::unique_ptr<NotificationSurface> |
| WaylandRemoteShell::CreateNotificationSurface( |
| Surface* surface, |
| const std::string& notification_key) { |
| return display_->CreateNotificationSurface(surface, notification_key); |
| } |
| |
| std::unique_ptr<InputMethodSurface> |
| WaylandRemoteShell::CreateInputMethodSurface( |
| Surface* surface, |
| double default_device_scale_factor) { |
| return display_->CreateInputMethodSurface( |
| surface, default_device_scale_factor, use_default_scale_cancellation_); |
| } |
| |
| std::unique_ptr<ToastSurface> WaylandRemoteShell::CreateToastSurface( |
| Surface* surface, |
| double default_device_scale_factor) { |
| return display_->CreateToastSurface(surface, default_device_scale_factor, |
| use_default_scale_cancellation_); |
| } |
| |
| void WaylandRemoteShell::SetUseDefaultScaleCancellation( |
| bool use_default_scale) { |
| use_default_scale_cancellation_ = use_default_scale; |
| WMHelper::GetInstance()->SetDefaultScaleCancellation(use_default_scale); |
| } |
| |
| void WaylandRemoteShell::OnRemoteSurfaceDestroyed(wl_resource* resource) { |
| // Sometimes resource might be destroyed after bounds change is scheduled to |
| // |pending_bounds_change_| but before that bounds change is emitted. Erase |
| // it from |pending_bounds_changes_| to prevent crashes. See also |
| // https://crbug.com/1163271. |
| pending_bounds_changes_.erase(resource); |
| } |
| |
| // Overridden from display::DisplayObserver: |
| void WaylandRemoteShell::OnDisplayAdded(const display::Display& new_display) { |
| ScheduleSendDisplayMetrics(0); |
| } |
| |
| void WaylandRemoteShell::OnDisplayRemoved(const display::Display& old_display) { |
| ScheduleSendDisplayMetrics(0); |
| } |
| |
| void WaylandRemoteShell::OnDisplayTabletStateChanged( |
| display::TabletState state) { |
| const bool layout_change_started = |
| state == display::TabletState::kEnteringTabletMode || |
| state == display::TabletState::kExitingTabletMode; |
| if (layout_change_started) |
| ScheduleSendDisplayMetrics(kConfigureDelayAfterLayoutSwitchMs); |
| } |
| |
| void WaylandRemoteShell::OnDisplayMetricsChanged( |
| const display::Display& display, |
| uint32_t changed_metrics) { |
| // No need to update when a primary display has changed without bounds |
| // change. See WaylandDisplayObserver::OnDisplayMetricsChanged |
| // for more details. |
| if (changed_metrics & |
| (DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_DEVICE_SCALE_FACTOR | |
| DISPLAY_METRIC_ROTATION | DISPLAY_METRIC_WORK_AREA)) { |
| ScheduleSendDisplayMetrics(0); |
| } |
| } |
| |
| // Overridden from ash::TabletModeObserver: |
| void WaylandRemoteShell::OnTabletModeStarted() { |
| layout_mode_ = ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET; |
| if (wl_resource_get_version(remote_shell_resource_) >= |
| event_mapping_.layout_mode_since_version) |
| event_mapping_.send_layout_mode(remote_shell_resource_, layout_mode_); |
| } |
| void WaylandRemoteShell::OnTabletModeEnding() { |
| layout_mode_ = ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED; |
| if (wl_resource_get_version(remote_shell_resource_) >= |
| event_mapping_.layout_mode_since_version) |
| event_mapping_.send_layout_mode(remote_shell_resource_, layout_mode_); |
| } |
| void WaylandRemoteShell::OnTabletModeEnded() {} |
| |
| void WaylandRemoteShell::ScheduleSendDisplayMetrics(int delay_ms) { |
| needs_send_display_metrics_ = true; |
| base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| FROM_HERE, |
| base::BindOnce(&WaylandRemoteShell::SendDisplayMetrics, |
| weak_ptr_factory_.GetWeakPtr()), |
| base::Milliseconds(delay_ms)); |
| } |
| |
| // Returns the transform that a display's output is currently adjusted for. |
| wl_output_transform WaylandRemoteShell::DisplayTransform( |
| display::Display::Rotation rotation) { |
| switch (rotation) { |
| case display::Display::ROTATE_0: |
| return WL_OUTPUT_TRANSFORM_NORMAL; |
| case display::Display::ROTATE_90: |
| return WL_OUTPUT_TRANSFORM_90; |
| case display::Display::ROTATE_180: |
| return WL_OUTPUT_TRANSFORM_180; |
| case display::Display::ROTATE_270: |
| return WL_OUTPUT_TRANSFORM_270; |
| } |
| NOTREACHED(); |
| return WL_OUTPUT_TRANSFORM_NORMAL; |
| } |
| |
| void WaylandRemoteShell::SendDisplayMetrics() { |
| if (!needs_send_display_metrics_) |
| return; |
| needs_send_display_metrics_ = false; |
| |
| const display::Screen* screen = display::Screen::GetScreen(); |
| double default_dsf = GetDefaultDeviceScaleFactor(); |
| |
| for (const auto& display : screen->GetAllDisplays()) { |
| double device_scale_factor = display.device_scale_factor(); |
| |
| uint32_t display_id_hi = static_cast<uint32_t>(display.id() >> 32); |
| uint32_t display_id_lo = static_cast<uint32_t>(display.id()); |
| gfx::Size size_in_pixel = display.GetSizeInPixel(); |
| |
| wl_array data; |
| wl_array_init(&data); |
| |
| const auto& bytes = |
| WMHelper::GetInstance()->GetDisplayIdentificationData(display.id()); |
| for (uint8_t byte : bytes) { |
| uint8_t* ptr = |
| static_cast<uint8_t*>(wl_array_add(&data, sizeof(uint8_t))); |
| DCHECK(ptr); |
| *ptr = byte; |
| } |
| |
| if (wl_resource_get_version(remote_shell_resource_) >= |
| event_mapping_.send_workspace_info_since_version) { |
| // Apply the scale factor used on the remote shell client (ARC). |
| const gfx::Rect& bounds = display.bounds(); |
| |
| // Note: The origin is used just to identify the workspace on the client |
| // side, and does not account the actual pixel size of other workspace |
| // on the client side. |
| int x_px = base::ClampRound(bounds.x() * default_dsf); |
| int y_px = base::ClampRound(bounds.y() * default_dsf); |
| |
| float server_to_client_pixel_scale = default_dsf / device_scale_factor; |
| |
| gfx::Size size_in_client_pixel = |
| gfx::ScaleToRoundedSize(size_in_pixel, server_to_client_pixel_scale); |
| |
| gfx::Insets insets_in_client_pixel = GetWorkAreaInsetsInPixel( |
| display, default_dsf, size_in_client_pixel, display.work_area()); |
| |
| gfx::Insets stable_insets_in_client_pixel = |
| GetWorkAreaInsetsInPixel(display, default_dsf, size_in_client_pixel, |
| GetStableWorkArea(display)); |
| |
| // TODO(b/148977363): Fix the issue and remove the hack. |
| MaybeApplyCTSHack(layout_mode_, size_in_pixel, &insets_in_client_pixel, |
| &stable_insets_in_client_pixel); |
| |
| int systemui_visibility = SystemUiVisibility(display); |
| if (event_mapping_.send_workspace_info) |
| event_mapping_.send_workspace_info( |
| remote_shell_resource_, display_id_hi, display_id_lo, x_px, y_px, |
| size_in_client_pixel.width(), size_in_client_pixel.height(), |
| insets_in_client_pixel.left(), insets_in_client_pixel.top(), |
| insets_in_client_pixel.right(), insets_in_client_pixel.bottom(), |
| stable_insets_in_client_pixel.left(), |
| stable_insets_in_client_pixel.top(), |
| stable_insets_in_client_pixel.right(), |
| stable_insets_in_client_pixel.bottom(), systemui_visibility, |
| DisplayTransform(display.rotation()), display.IsInternal(), &data); |
| } else { |
| NOTREACHED() << "The remote shell resource version being used (" |
| << wl_resource_get_version(remote_shell_resource_) |
| << ") is not supported."; |
| } |
| |
| wl_array_release(&data); |
| } |
| if (event_mapping_.send_configure) |
| event_mapping_.send_configure(remote_shell_resource_, layout_mode_); |
| |
| base::flat_set<wl_client*> clients; |
| clients.insert(wl_resource_get_client(remote_shell_resource_)); |
| |
| for (const auto& bounds_change : pending_bounds_changes_) { |
| SendBoundsChanged(bounds_change.first, bounds_change.second.display_id, |
| bounds_change.second.bounds_in_display, |
| bounds_change.second.reason); |
| clients.insert(wl_resource_get_client(bounds_change.first)); |
| } |
| pending_bounds_changes_.clear(); |
| |
| for (auto* client : clients) |
| wl_client_flush(client); |
| } |
| |
| void WaylandRemoteShell::OnSurfaceFocused(Surface* gained_focus, |
| Surface* lost_focus, |
| bool has_focused_client) { |
| FocusedSurfaceChanged(gained_focus, lost_focus, has_focused_client); |
| } |
| |
| void WaylandRemoteShell::FocusedSurfaceChanged(Surface* gained_active_surface, |
| Surface* lost_active_surface, |
| bool has_focused_client) { |
| if (gained_active_surface == lost_active_surface && |
| last_has_focused_client_ == has_focused_client) { |
| return; |
| } |
| last_has_focused_client_ = has_focused_client; |
| |
| wl_resource* gained_active_surface_resource = |
| gained_active_surface ? GetSurfaceResource(gained_active_surface) |
| : nullptr; |
| wl_resource* lost_active_surface_resource = |
| lost_active_surface ? GetSurfaceResource(lost_active_surface) : nullptr; |
| |
| wl_client* client = wl_resource_get_client(remote_shell_resource_); |
| |
| // If surface that gained active is not owned by remote shell client then |
| // set it to null. |
| if (gained_active_surface_resource && |
| wl_resource_get_client(gained_active_surface_resource) != client) { |
| gained_active_surface_resource = nullptr; |
| } |
| |
| // If surface that lost active is not owned by remote shell client then |
| // set it to null. |
| if (lost_active_surface_resource && |
| wl_resource_get_client(lost_active_surface_resource) != client) { |
| lost_active_surface_resource = nullptr; |
| } |
| |
| if (wl_resource_get_version(remote_shell_resource_) >= |
| event_mapping_.desktop_focus_state_changed_since_version) { |
| uint32_t focus_state; |
| if (gained_active_surface_resource) { |
| focus_state = ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_CLIENT_FOCUSED; |
| } else if (has_focused_client) { |
| focus_state = |
| ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_OTHER_CLIENT_FOCUSED; |
| } else { |
| focus_state = ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_NO_FOCUS; |
| } |
| event_mapping_.send_desktop_focus_state_changed(remote_shell_resource_, |
| focus_state); |
| } |
| |
| if (event_mapping_.send_activated) { |
| event_mapping_.send_activated(remote_shell_resource_, |
| gained_active_surface_resource, |
| lost_active_surface_resource); |
| } |
| |
| wl_client_flush(client); |
| } |
| |
| void WaylandRemoteShell::OnRemoteSurfaceBoundsChanged( |
| wl_resource* resource, |
| WindowStateType current_state, |
| WindowStateType requested_state, |
| int64_t display_id, |
| const gfx::Rect& bounds_in_display, |
| bool resize, |
| int bounds_change) { |
| zcr_remote_surface_v1_bounds_change_reason reason = |
| ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_RESIZE; |
| if (!resize) |
| reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_MOVE; |
| if (current_state == WindowStateType::kPip) |
| reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_PIP; |
| 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; |
| } |
| // Override the reason only if the window enters snapped mode. If the window |
| // resizes by dragging in snapped mode, we need to keep the original reason. |
| if (requested_state != current_state) { |
| if (requested_state == WindowStateType::kPrimarySnapped) { |
| reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_LEFT; |
| } else if (requested_state == WindowStateType::kSecondarySnapped) { |
| reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_RIGHT; |
| } |
| } |
| |
| if (needs_send_display_metrics_) { |
| // We store only the latest bounds for each |resource|. |
| pending_bounds_changes_.insert_or_assign( |
| std::move(resource), |
| BoundsChangeData(display_id, bounds_in_display, reason)); |
| return; |
| } |
| SendBoundsChanged(resource, display_id, bounds_in_display, reason); |
| |
| wl_client_flush(wl_resource_get_client(resource)); |
| } |
| |
| void WaylandRemoteShell::SendBoundsChanged( |
| wl_resource* resource, |
| int64_t display_id, |
| const gfx::Rect& bounds_in_display, |
| zcr_remote_surface_v1_bounds_change_reason reason) { |
| if (event_mapping_.send_bounds_changed) |
| event_mapping_.send_bounds_changed( |
| resource, static_cast<uint32_t>(display_id >> 32), |
| static_cast<uint32_t>(display_id), bounds_in_display.x(), |
| bounds_in_display.y(), bounds_in_display.width(), |
| bounds_in_display.height(), reason); |
| |
| if (wl_resource_get_version(resource) >= |
| event_mapping_.bounds_changed_in_output_since_version) { |
| wl_resource* output = output_provider_.Run(display_id); |
| if (output == nullptr) { |
| LOG(WARNING) << "Failed to get wayland_output resource for display_id: " |
| << display_id; |
| return; |
| } |
| event_mapping_.send_bounds_changed_in_output( |
| resource, output, bounds_in_display.x(), bounds_in_display.y(), |
| bounds_in_display.width(), bounds_in_display.height(), reason); |
| } |
| } |
| |
| void WaylandRemoteShell::OnRemoteSurfaceStateChanged( |
| wl_resource* resource, |
| WindowStateType old_state_type, |
| WindowStateType new_state_type) { |
| DCHECK_NE(old_state_type, new_state_type); |
| LOG_IF(ERROR, pending_bounds_changes_.count(resource) > 0) |
| << "Sending window state while there is a pending bounds change. This " |
| "should not happen."; |
| |
| uint32_t state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_NORMAL; |
| switch (new_state_type) { |
| case WindowStateType::kMinimized: |
| state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_MINIMIZED; |
| break; |
| case WindowStateType::kMaximized: |
| state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_MAXIMIZED; |
| break; |
| case WindowStateType::kFullscreen: |
| state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_FULLSCREEN; |
| break; |
| case WindowStateType::kPinned: |
| state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_PINNED; |
| break; |
| case WindowStateType::kTrustedPinned: |
| state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_TRUSTED_PINNED; |
| break; |
| case WindowStateType::kPrimarySnapped: |
| state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_LEFT_SNAPPED; |
| break; |
| case WindowStateType::kSecondarySnapped: |
| state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_RIGHT_SNAPPED; |
| break; |
| case WindowStateType::kPip: |
| state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_PIP; |
| break; |
| default: |
| break; |
| } |
| |
| event_mapping_.send_state_type_changed(resource, state_type); |
| wl_client_flush(wl_resource_get_client(resource)); |
| } |
| |
| void WaylandRemoteShell::OnRemoteSurfaceChangeZoomLevel(wl_resource* resource, |
| ZoomChange change) { |
| int32_t value = 0; |
| switch (change) { |
| case ZoomChange::IN: |
| value = ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_IN; |
| break; |
| case ZoomChange::OUT: |
| value = ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_OUT; |
| break; |
| case ZoomChange::RESET: |
| value = ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_RESET; |
| break; |
| } |
| event_mapping_.send_change_zoom_level(resource, value); |
| wl_client_flush(wl_resource_get_client(resource)); |
| } |
| |
| void WaylandRemoteShell::OnRemoteSurfaceGeometryChanged( |
| wl_resource* resource, |
| const gfx::Rect& geometry) { |
| LOG_IF(ERROR, pending_bounds_changes_.count(resource) > 0) |
| << "Sending the new window geometry while there is a pending bounds " |
| "change. This should not happen."; |
| event_mapping_.send_window_geometry_changed(resource, geometry.x(), |
| geometry.y(), geometry.width(), |
| geometry.height()); |
| wl_client_flush(wl_resource_get_client(resource)); |
| } |
| |
| namespace switches { |
| |
| // This flag can be used to emulate device scale factor for remote shell. |
| constexpr char kForceRemoteShellScale[] = "force-remote-shell-scale"; |
| |
| } // namespace switches |
| |
| using chromeos::WindowStateType; |
| |
| namespace zcr_remote_shell { |
| |
| // Returns the scale factor to be used by remote shell clients. |
| double GetDefaultDeviceScaleFactor() { |
| // A flag used by VM to emulate a device scale for a particular board. |
| base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| if (command_line->HasSwitch(switches::kForceRemoteShellScale)) { |
| std::string value = |
| command_line->GetSwitchValueASCII(switches::kForceRemoteShellScale); |
| double scale = 1.0; |
| if (base::StringToDouble(value, &scale)) |
| return std::max(1.0, scale); |
| } |
| return WMHelper::GetInstance()->GetDefaultDeviceScaleFactor(); |
| } |
| |
| // Scale the |child_bounds| in such a way that if it should fill the |
| // |parent_size|'s width/height, it returns the |parent_size_in_pixel|'s |
| // width/height. |
| gfx::Rect ScaleBoundsToPixelSnappedToParent( |
| const gfx::Size& parent_size_in_pixel, |
| const gfx::Size& parent_size, |
| float device_scale_factor, |
| const gfx::Rect& child_bounds) { |
| int right = child_bounds.right(); |
| int bottom = child_bounds.bottom(); |
| |
| int new_x = base::ClampRound(child_bounds.x() * device_scale_factor); |
| int new_y = base::ClampRound(child_bounds.y() * device_scale_factor); |
| |
| int new_right = right == parent_size.width() |
| ? parent_size_in_pixel.width() |
| : base::ClampRound(right * device_scale_factor); |
| |
| int new_bottom = bottom == parent_size.height() |
| ? parent_size_in_pixel.height() |
| : base::ClampRound(bottom * device_scale_factor); |
| return gfx::Rect(new_x, new_y, new_right - new_x, new_bottom - new_y); |
| } |
| |
| void ScaleSkRegion(const SkRegion& src, float scale, SkRegion* dst) { |
| SkRegion::Iterator iter(src); |
| for (; !iter.done(); iter.next()) { |
| SkIRect r; |
| r.fLeft = base::ClampFloor(iter.rect().fLeft * scale); |
| r.fTop = base::ClampFloor(iter.rect().fTop * scale); |
| r.fRight = base::ClampCeil(iter.rect().fRight * scale); |
| r.fBottom = base::ClampCeil(iter.rect().fBottom * scale); |
| dst->op(r, SkRegion::kUnion_Op); |
| } |
| } |
| |
| int Component(uint32_t direction) { |
| switch (direction) { |
| case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE: |
| return HTNOWHERE; |
| case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP: |
| return HTTOP; |
| case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT: |
| return HTTOPRIGHT; |
| case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT: |
| return HTRIGHT; |
| case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT: |
| return HTBOTTOMRIGHT; |
| case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM: |
| return HTBOTTOM; |
| case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT: |
| return HTBOTTOMLEFT; |
| case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT: |
| return HTLEFT; |
| case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT: |
| return HTTOPLEFT; |
| default: |
| VLOG(2) << "Unknown direction:" << direction; |
| break; |
| } |
| return HTNOWHERE; |
| } |
| |
| uint32_t CaptionButtonMask(uint32_t mask) { |
| uint32_t caption_button_icon_mask = 0; |
| if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_BACK) |
| caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_BACK; |
| if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_MENU) |
| caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_MENU; |
| if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_MINIMIZE) |
| caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_MINIMIZE; |
| if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_MAXIMIZE_RESTORE) |
| caption_button_icon_mask |= 1 |
| << views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE; |
| if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_CLOSE) |
| caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_CLOSE; |
| if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_ZOOM) |
| caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_ZOOM; |
| if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_CENTER) |
| caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_CENTER; |
| return caption_button_icon_mask; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // remote_surface_interface: |
| |
| SurfaceFrameType RemoteShellSurfaceFrameType(uint32_t frame_type) { |
| switch (frame_type) { |
| case ZCR_REMOTE_SURFACE_V1_FRAME_TYPE_NONE: |
| return SurfaceFrameType::NONE; |
| case ZCR_REMOTE_SURFACE_V1_FRAME_TYPE_NORMAL: |
| return SurfaceFrameType::NORMAL; |
| case ZCR_REMOTE_SURFACE_V1_FRAME_TYPE_SHADOW: |
| return SurfaceFrameType::SHADOW; |
| case ZCR_REMOTE_SURFACE_V1_FRAME_TYPE_AUTOHIDE: |
| return SurfaceFrameType::AUTOHIDE; |
| case ZCR_REMOTE_SURFACE_V1_FRAME_TYPE_OVERLAY: |
| return SurfaceFrameType::OVERLAY; |
| default: |
| VLOG(2) << "Unknown remote-shell frame type: " << frame_type; |
| return SurfaceFrameType::NONE; |
| } |
| } |
| |
| void remote_surface_set_app_id(wl_client* client, |
| wl_resource* resource, |
| const char* app_id) { |
| GetUserDataAs<ShellSurfaceBase>(resource)->SetApplicationId(app_id); |
| } |
| |
| void remote_surface_set_window_geometry(wl_client* client, |
| wl_resource* resource, |
| int32_t x, |
| int32_t y, |
| int32_t width, |
| int32_t height) { |
| // DEPRECATED - Use set_bounds to send bounds info with a display_id. |
| GetUserDataAs<ShellSurfaceBase>(resource)->SetGeometry( |
| gfx::Rect(x, y, width, height)); |
| } |
| |
| void remote_surface_set_orientation(wl_client* client, |
| wl_resource* resource, |
| int32_t orientation) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetOrientation( |
| orientation == ZCR_REMOTE_SURFACE_V1_ORIENTATION_PORTRAIT |
| ? Orientation::PORTRAIT |
| : Orientation::LANDSCAPE); |
| } |
| |
| void remote_surface_set_scale(wl_client* client, |
| wl_resource* resource, |
| wl_fixed_t scale) { |
| // DEPRECATED (b/141715728) - The server updates the client's scale. |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetScale( |
| wl_fixed_to_double(scale)); |
| } |
| |
| void remote_surface_set_rectangular_shadow_DEPRECATED(wl_client* client, |
| wl_resource* resource, |
| int32_t x, |
| int32_t y, |
| int32_t width, |
| int32_t height) { |
| NOTREACHED(); |
| } |
| |
| void remote_surface_set_rectangular_shadow_background_opacity_DEPRECATED( |
| wl_client* client, |
| wl_resource* resource, |
| wl_fixed_t opacity) { |
| NOTREACHED(); |
| } |
| |
| void remote_surface_set_title(wl_client* client, |
| wl_resource* resource, |
| const char* title) { |
| GetUserDataAs<ShellSurfaceBase>(resource)->SetTitle( |
| std::u16string(base::UTF8ToUTF16(title))); |
| } |
| |
| void remote_surface_set_top_inset(wl_client* client, |
| wl_resource* resource, |
| int32_t height) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetTopInset(height); |
| } |
| |
| void remote_surface_activate(wl_client* client, |
| wl_resource* resource, |
| uint32_t serial) { |
| ShellSurfaceBase* shell_surface = GetUserDataAs<ShellSurfaceBase>(resource); |
| shell_surface->Activate(); |
| } |
| |
| void remote_surface_maximize(wl_client* client, wl_resource* resource) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetMaximized(); |
| } |
| |
| void remote_surface_minimize(wl_client* client, wl_resource* resource) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetMinimized(); |
| } |
| |
| void remote_surface_restore(wl_client* client, wl_resource* resource) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetRestored(); |
| } |
| |
| void remote_surface_fullscreen(wl_client* client, wl_resource* resource) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetFullscreen(true); |
| } |
| |
| void remote_surface_unfullscreen(wl_client* client, wl_resource* resource) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetFullscreen(false); |
| } |
| |
| void remote_surface_pin(wl_client* client, |
| wl_resource* resource, |
| int32_t trusted) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetPinned( |
| trusted ? chromeos::WindowPinType::kTrustedPinned |
| : chromeos::WindowPinType::kPinned); |
| } |
| |
| void remote_surface_unpin(wl_client* client, wl_resource* resource) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetPinned( |
| chromeos::WindowPinType::kNone); |
| } |
| |
| void remote_surface_set_system_modal(wl_client* client, wl_resource* resource) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetSystemModal(true); |
| } |
| |
| void remote_surface_unset_system_modal(wl_client* client, |
| wl_resource* resource) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetSystemModal(false); |
| } |
| |
| void remote_surface_set_rectangular_surface_shadow(wl_client* client, |
| wl_resource* resource, |
| int32_t x, |
| int32_t y, |
| int32_t width, |
| int32_t height) { |
| // Shadow Bounds are set in pixels, and should not be scaled. |
| ClientControlledShellSurface* shell_surface = |
| GetUserDataAs<ClientControlledShellSurface>(resource); |
| shell_surface->SetShadowBounds(gfx::Rect(x, y, width, height)); |
| } |
| |
| void remote_surface_set_systemui_visibility(wl_client* client, |
| wl_resource* resource, |
| uint32_t visibility) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetSystemUiVisibility( |
| visibility != ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_VISIBLE); |
| } |
| |
| void remote_surface_set_always_on_top(wl_client* client, |
| wl_resource* resource) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetAlwaysOnTop(true); |
| } |
| |
| void remote_surface_unset_always_on_top(wl_client* client, |
| wl_resource* resource) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetAlwaysOnTop(false); |
| } |
| |
| void remote_surface_ack_configure_DEPRECATED(wl_client* client, |
| wl_resource* resource, |
| uint32_t serial) { |
| NOTREACHED(); |
| } |
| |
| void remote_surface_move_DEPRECATED(wl_client* client, wl_resource* resource) { |
| NOTREACHED(); |
| } |
| |
| void remote_surface_set_window_type(wl_client* client, |
| wl_resource* resource, |
| uint32_t type) { |
| auto* widget = GetUserDataAs<ShellSurfaceBase>(resource)->GetWidget(); |
| if (!widget) |
| return; |
| |
| switch (type) { |
| case ZCR_REMOTE_SURFACE_V1_WINDOW_TYPE_NORMAL: |
| widget->GetNativeWindow()->SetProperty(ash::kHideInOverviewKey, false); |
| break; |
| case ZCR_REMOTE_SURFACE_V1_WINDOW_TYPE_SYSTEM_UI: |
| // TODO(takise): Consider removing this as this window type was added for |
| // the old assistant and is not longer used. |
| widget->GetNativeWindow()->SetProperty(ash::kHideInOverviewKey, true); |
| wm::SetWindowVisibilityAnimationType( |
| widget->GetNativeWindow(), wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); |
| break; |
| case ZCR_REMOTE_SURFACE_V1_WINDOW_TYPE_HIDDEN_IN_OVERVIEW: |
| widget->GetNativeWindow()->SetProperty(ash::kHideInOverviewKey, true); |
| break; |
| } |
| } |
| |
| void remote_surface_resize_DEPRECATED(wl_client* client, |
| wl_resource* resource) { |
| // DEPRECATED |
| NOTREACHED(); |
| } |
| |
| void remote_surface_set_resize_outset_DEPRECATED(wl_client* client, |
| wl_resource* resource, |
| int32_t outset) { |
| // DEPRECATED |
| NOTREACHED(); |
| } |
| |
| void remote_surface_start_move(wl_client* client, |
| wl_resource* resource, |
| int32_t x, |
| int32_t y) { |
| ClientControlledShellSurface* shell_surface = |
| GetUserDataAs<ClientControlledShellSurface>(resource); |
| float scale = shell_surface->GetClientToDpScale(); |
| gfx::PointF p(x, y); |
| shell_surface->StartDrag(HTCAPTION, gfx::ScalePoint(p, scale)); |
| } |
| |
| 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) { |
| ClientControlledShellSurface* shell_surface = |
| GetUserDataAs<ClientControlledShellSurface>(resource); |
| float scale = shell_surface->GetClientToDpScale(); |
| gfx::Size s(width, height); |
| shell_surface->SetMinimumSize(gfx::ScaleToRoundedSize(s, scale)); |
| } |
| |
| void remote_surface_set_max_size(wl_client* client, |
| wl_resource* resource, |
| int32_t width, |
| int32_t height) { |
| ClientControlledShellSurface* shell_surface = |
| GetUserDataAs<ClientControlledShellSurface>(resource); |
| float scale = shell_surface->GetClientToDpScale(); |
| gfx::Size s(width, height); |
| shell_surface->SetMaximumSize(gfx::ScaleToRoundedSize(s, scale)); |
| } |
| |
| void remote_surface_set_aspect_ratio(wl_client* client, |
| wl_resource* resource, |
| int32_t aspect_ratio_width, |
| int32_t aspect_ratio_height) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetAspectRatio( |
| gfx::SizeF(aspect_ratio_width, aspect_ratio_height)); |
| } |
| |
| void remote_surface_set_snapped_to_left(wl_client* client, |
| wl_resource* resource) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetSnappedToPrimary(); |
| } |
| |
| void remote_surface_set_snapped_to_right(wl_client* client, |
| wl_resource* resource) { |
| GetUserDataAs<ClientControlledShellSurface>(resource) |
| ->SetSnappedToSecondary(); |
| } |
| |
| void remote_surface_start_resize(wl_client* client, |
| wl_resource* resource, |
| uint32_t direction, |
| int32_t x, |
| int32_t y) { |
| ClientControlledShellSurface* shell_surface = |
| GetUserDataAs<ClientControlledShellSurface>(resource); |
| float scale = shell_surface->GetClientToDpScale(); |
| gfx::PointF p(x, y); |
| shell_surface->StartDrag(Component(direction), gfx::ScalePoint(p, scale)); |
| } |
| |
| void remote_surface_set_frame(wl_client* client, |
| wl_resource* resource, |
| uint32_t type) { |
| ClientControlledShellSurface* shell_surface = |
| GetUserDataAs<ClientControlledShellSurface>(resource); |
| shell_surface->root_surface()->SetFrame(RemoteShellSurfaceFrameType(type)); |
| } |
| |
| void remote_surface_set_frame_buttons(wl_client* client, |
| wl_resource* resource, |
| uint32_t visible_button_mask, |
| uint32_t enabled_button_mask) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetFrameButtons( |
| CaptionButtonMask(visible_button_mask), |
| CaptionButtonMask(enabled_button_mask)); |
| } |
| |
| void remote_surface_set_extra_title(wl_client* client, |
| wl_resource* resource, |
| const char* extra_title) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetExtraTitle( |
| std::u16string(base::UTF8ToUTF16(extra_title))); |
| } |
| |
| chromeos::OrientationType OrientationLock(uint32_t orientation_lock) { |
| switch (orientation_lock) { |
| case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_NONE: |
| return chromeos::OrientationType::kAny; |
| case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_CURRENT: |
| return chromeos::OrientationType::kCurrent; |
| case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_PORTRAIT: |
| return chromeos::OrientationType::kPortrait; |
| case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_LANDSCAPE: |
| return chromeos::OrientationType::kLandscape; |
| case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_PORTRAIT_PRIMARY: |
| return chromeos::OrientationType::kPortraitPrimary; |
| case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_PORTRAIT_SECONDARY: |
| return chromeos::OrientationType::kPortraitSecondary; |
| case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_LANDSCAPE_PRIMARY: |
| return chromeos::OrientationType::kLandscapePrimary; |
| case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_LANDSCAPE_SECONDARY: |
| return chromeos::OrientationType::kLandscapeSecondary; |
| } |
| VLOG(2) << "Unexpected value of orientation_lock: " << orientation_lock; |
| return chromeos::OrientationType::kAny; |
| } |
| |
| void remote_surface_set_orientation_lock(wl_client* client, |
| wl_resource* resource, |
| uint32_t orientation_lock) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetOrientationLock( |
| OrientationLock(orientation_lock)); |
| } |
| |
| void remote_surface_pip(wl_client* client, wl_resource* resource) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetPip(); |
| } |
| |
| void remote_surface_set_bounds(wl_client* client, |
| wl_resource* resource, |
| uint32_t display_id_hi, |
| uint32_t display_id_lo, |
| int32_t x, |
| int32_t y, |
| int32_t width, |
| int32_t height) { |
| // Bounds are set in pixels, and should not be scaled. |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetBounds( |
| static_cast<int64_t>(display_id_hi) << 32 | display_id_lo, |
| gfx::Rect(x, y, width, height)); |
| } |
| |
| void remote_surface_block_ime(wl_client* client, wl_resource* resource) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void remote_surface_unblock_ime(wl_client* client, wl_resource* resource) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void remote_surface_set_accessibility_id(wl_client* client, |
| wl_resource* resource, |
| int32_t accessibility_id) { |
| GetUserDataAs<ClientControlledShellSurface>(resource) |
| ->SetClientAccessibilityId(accessibility_id); |
| } |
| |
| void remote_surface_set_pip_original_window(wl_client* client, |
| wl_resource* resource) { |
| auto* widget = GetUserDataAs<ShellSurfaceBase>(resource)->GetWidget(); |
| if (!widget) { |
| LOG(ERROR) << "no widget found for setting pip original window"; |
| return; |
| } |
| |
| widget->GetNativeWindow()->SetProperty(ash::kPipOriginalWindowKey, true); |
| } |
| |
| void remote_surface_unset_pip_original_window(wl_client* client, |
| wl_resource* resource) { |
| auto* widget = GetUserDataAs<ShellSurfaceBase>(resource)->GetWidget(); |
| if (!widget) { |
| LOG(ERROR) << "no widget found for unsetting pip original window"; |
| return; |
| } |
| |
| widget->GetNativeWindow()->SetProperty(ash::kPipOriginalWindowKey, false); |
| } |
| |
| void remote_surface_set_system_gesture_exclusion(wl_client* client, |
| wl_resource* resource, |
| wl_resource* region_resource) { |
| auto* shell_surface = GetUserDataAs<ClientControlledShellSurface>(resource); |
| auto* widget = shell_surface->GetWidget(); |
| if (!widget) { |
| LOG(ERROR) << "no widget found for setting system gesture exclusion"; |
| return; |
| } |
| |
| if (region_resource) { |
| SkRegion* dst = new SkRegion; |
| ScaleSkRegion(*GetUserDataAs<SkRegion>(region_resource), |
| shell_surface->GetClientToDpScale(), dst); |
| widget->GetNativeWindow()->SetProperty(ash::kSystemGestureExclusionKey, |
| dst); |
| } else { |
| widget->GetNativeWindow()->ClearProperty(ash::kSystemGestureExclusionKey); |
| } |
| } |
| |
| void remote_surface_set_resize_lock(wl_client* client, wl_resource* resource) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetResizeLockType( |
| ash::ArcResizeLockType::RESIZE_DISABLED_TOGGLABLE); |
| } |
| |
| void remote_surface_unset_resize_lock(wl_client* client, |
| wl_resource* resource) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetResizeLockType( |
| ash::ArcResizeLockType::NONE); |
| } |
| |
| void remote_surface_set_bounds_in_output(wl_client* client, |
| wl_resource* resource, |
| wl_resource* output_resource, |
| int32_t x, |
| int32_t y, |
| int32_t width, |
| int32_t height) { |
| WaylandDisplayHandler* display_handler = |
| GetUserDataAs<WaylandDisplayHandler>(output_resource); |
| // Bounds are set in pixels, and should not be scaled. |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetBounds( |
| display_handler->id(), gfx::Rect(x, y, width, height)); |
| } |
| |
| void remote_surface_set_resize_lock_type(wl_client* client, |
| wl_resource* resource, |
| uint32_t type) { |
| GetUserDataAs<ClientControlledShellSurface>(resource)->SetResizeLockType( |
| static_cast<ash::ArcResizeLockType>(type)); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // notification_surface_interface: |
| |
| void notification_surface_set_app_id(wl_client* client, |
| wl_resource* resource, |
| const char* app_id) { |
| GetUserDataAs<NotificationSurface>(resource)->SetApplicationId(app_id); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // input_method_surface_interface: |
| |
| void input_method_surface_set_bounds(wl_client* client, |
| wl_resource* resource, |
| uint32_t display_id_hi, |
| uint32_t display_id_lo, |
| int32_t x, |
| int32_t y, |
| int32_t width, |
| int32_t height) { |
| GetUserDataAs<InputMethodSurface>(resource)->SetBounds( |
| static_cast<int64_t>(display_id_hi) << 32 | display_id_lo, |
| gfx::Rect(x, y, width, height)); |
| } |
| |
| void input_method_surface_set_bounds_in_output(wl_client* client, |
| wl_resource* resource, |
| wl_resource* output_resource, |
| int32_t x, |
| int32_t y, |
| int32_t width, |
| int32_t height) { |
| WaylandDisplayHandler* display_handler = |
| GetUserDataAs<WaylandDisplayHandler>(output_resource); |
| GetUserDataAs<InputMethodSurface>(resource)->SetBounds( |
| display_handler->id(), gfx::Rect(x, y, width, height)); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // toast_surface_interface: |
| |
| void toast_surface_set_position(wl_client* client, |
| wl_resource* resource, |
| uint32_t display_id_hi, |
| uint32_t display_id_lo, |
| int32_t x, |
| int32_t y) { |
| GetUserDataAs<ToastSurface>(resource)->SetDisplay( |
| static_cast<int64_t>(display_id_hi) << 32 | display_id_lo); |
| GetUserDataAs<ToastSurface>(resource)->SetBoundsOrigin(gfx::Point(x, y)); |
| } |
| |
| void toast_surface_set_size(wl_client* client, |
| wl_resource* resource, |
| int32_t width, |
| int32_t height) { |
| GetUserDataAs<ToastSurface>(resource)->SetBoundsSize( |
| gfx::Size(width, height)); |
| } |
| |
| void toast_surface_set_bounds_in_output(wl_client* client, |
| wl_resource* resource, |
| wl_resource* output_resource, |
| int32_t x, |
| int32_t y, |
| int32_t width, |
| int32_t height) { |
| WaylandDisplayHandler* display_handler = |
| GetUserDataAs<WaylandDisplayHandler>(output_resource); |
| GetUserDataAs<ToastSurface>(resource)->SetBounds( |
| display_handler->id(), gfx::Rect(x, y, width, height)); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // remote_shell_interface: |
| |
| void remote_shell_set_use_default_scale_cancellation( |
| wl_client*, |
| wl_resource* resource, |
| int32_t use_default_scale_cancellation) { |
| auto* shell = GetUserDataAs<WaylandRemoteShell>(resource); |
| if (wl_resource_get_version(resource) < |
| shell->event_mapping_.set_use_default_scale_cancellation_since_version) { |
| return; |
| } |
| shell->SetUseDefaultScaleCancellation(use_default_scale_cancellation != 0); |
| } |
| |
| } // namespace zcr_remote_shell |
| |
| } // namespace wayland |
| } // namespace exo |