1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ui/ozone/platform/x11/x11_screen_ozone.h"
6 
7 #include "ui/base/x/x11_idle_query.h"
8 #include "ui/base/x/x11_screensaver_window_finder.h"
9 #include "ui/base/x/x11_util.h"
10 #include "ui/display/display_finder.h"
11 #include "ui/display/util/display_util.h"
12 #include "ui/events/platform/x11/x11_event_source.h"
13 #include "ui/gfx/font_render_params.h"
14 #include "ui/gfx/geometry/dip_util.h"
15 #include "ui/gfx/geometry/point_conversions.h"
16 #include "ui/gfx/geometry/rect_conversions.h"
17 #include "ui/gfx/native_widget_types.h"
18 #include "ui/platform_window/x11/x11_topmost_window_finder.h"
19 #include "ui/platform_window/x11/x11_window.h"
20 #include "ui/platform_window/x11/x11_window_manager.h"
21 
22 namespace ui {
23 
24 namespace {
25 
GetDeviceScaleFactor()26 float GetDeviceScaleFactor() {
27   float device_scale_factor = 1.0f;
28   // TODO(crbug.com/891175): Implement PlatformScreen for X11
29   // Get device scale factor using scale factor and resolution like
30   // 'GtkUi::GetRawDeviceScaleFactor'.
31   if (display::Display::HasForceDeviceScaleFactor())
32     device_scale_factor = display::Display::GetForcedDeviceScaleFactor();
33   return device_scale_factor;
34 }
35 
36 }  // namespace
37 
X11ScreenOzone()38 X11ScreenOzone::X11ScreenOzone()
39     : window_manager_(X11WindowManager::GetInstance()),
40       x11_display_manager_(std::make_unique<XDisplayManager>(this)) {
41   DCHECK(window_manager_);
42 }
43 
~X11ScreenOzone()44 X11ScreenOzone::~X11ScreenOzone() {
45   if (x11_display_manager_->IsXrandrAvailable() &&
46       X11EventSource::HasInstance()) {
47     X11EventSource::GetInstance()->RemoveXEventDispatcher(this);
48   }
49 }
50 
Init()51 void X11ScreenOzone::Init() {
52   if (x11_display_manager_->IsXrandrAvailable() &&
53       X11EventSource::HasInstance()) {
54     X11EventSource::GetInstance()->AddXEventDispatcher(this);
55   }
56   x11_display_manager_->Init();
57 }
58 
GetAllDisplays() const59 const std::vector<display::Display>& X11ScreenOzone::GetAllDisplays() const {
60   return x11_display_manager_->displays();
61 }
62 
GetPrimaryDisplay() const63 display::Display X11ScreenOzone::GetPrimaryDisplay() const {
64   return x11_display_manager_->GetPrimaryDisplay();
65 }
66 
GetDisplayForAcceleratedWidget(gfx::AcceleratedWidget widget) const67 display::Display X11ScreenOzone::GetDisplayForAcceleratedWidget(
68     gfx::AcceleratedWidget widget) const {
69   if (widget == gfx::kNullAcceleratedWidget)
70     return GetPrimaryDisplay();
71 
72   X11Window* window = window_manager_->GetWindow(widget);
73   return window ? GetDisplayMatching(window->GetBounds()) : GetPrimaryDisplay();
74 }
75 
GetCursorScreenPoint() const76 gfx::Point X11ScreenOzone::GetCursorScreenPoint() const {
77   base::Optional<gfx::Point> point_in_pixels;
78   if (ui::X11EventSource::HasInstance()) {
79     point_in_pixels = ui::X11EventSource::GetInstance()
80                           ->GetRootCursorLocationFromCurrentEvent();
81   }
82   if (!point_in_pixels) {
83     // This call is expensive so we explicitly only call it when
84     // |point_in_pixels| is not set. We note that base::Optional::value_or()
85     // would cause it to be called regardless.
86     point_in_pixels = GetCursorLocation();
87   }
88   // TODO(danakj): Should this be rounded? Or kept as a floating point?
89   return gfx::ToFlooredPoint(
90       gfx::ConvertPointToDips(*point_in_pixels, GetDeviceScaleFactor()));
91 }
92 
GetAcceleratedWidgetAtScreenPoint(const gfx::Point & point) const93 gfx::AcceleratedWidget X11ScreenOzone::GetAcceleratedWidgetAtScreenPoint(
94     const gfx::Point& point) const {
95   X11TopmostWindowFinder finder;
96   return static_cast<gfx::AcceleratedWidget>(finder.FindWindowAt(point));
97 }
98 
GetLocalProcessWidgetAtPoint(const gfx::Point & point,const std::set<gfx::AcceleratedWidget> & ignore) const99 gfx::AcceleratedWidget X11ScreenOzone::GetLocalProcessWidgetAtPoint(
100     const gfx::Point& point,
101     const std::set<gfx::AcceleratedWidget>& ignore) const {
102   X11TopmostWindowFinder finder;
103   return static_cast<gfx::AcceleratedWidget>(
104       finder.FindLocalProcessWindowAt(point, ignore));
105 }
106 
GetDisplayNearestPoint(const gfx::Point & point) const107 display::Display X11ScreenOzone::GetDisplayNearestPoint(
108     const gfx::Point& point) const {
109   auto displays = GetAllDisplays();
110   if (displays.size() <= 1)
111     return GetPrimaryDisplay();
112   return *display::FindDisplayNearestPoint(displays, point);
113 }
114 
GetDisplayMatching(const gfx::Rect & match_rect_in_pixels) const115 display::Display X11ScreenOzone::GetDisplayMatching(
116     const gfx::Rect& match_rect_in_pixels) const {
117   gfx::Rect match_rect = gfx::ToEnclosingRect(
118       gfx::ConvertRectToDips(match_rect_in_pixels, GetDeviceScaleFactor()));
119   const display::Display* matching_display =
120       display::FindDisplayWithBiggestIntersection(
121           x11_display_manager_->displays(), match_rect);
122   return matching_display ? *matching_display : GetPrimaryDisplay();
123 }
124 
SetScreenSaverSuspended(bool suspend)125 void X11ScreenOzone::SetScreenSaverSuspended(bool suspend) {
126   SuspendX11ScreenSaver(suspend);
127 }
128 
IsScreenSaverActive() const129 bool X11ScreenOzone::IsScreenSaverActive() const {
130   // Usually the screensaver is used to lock the screen.
131   return ScreensaverWindowFinder::ScreensaverWindowExists();
132 }
133 
CalculateIdleTime() const134 base::TimeDelta X11ScreenOzone::CalculateIdleTime() const {
135   IdleQueryX11 idle_query;
136   return base::TimeDelta::FromSeconds(idle_query.IdleTime());
137 }
138 
AddObserver(display::DisplayObserver * observer)139 void X11ScreenOzone::AddObserver(display::DisplayObserver* observer) {
140   x11_display_manager_->AddObserver(observer);
141 }
142 
RemoveObserver(display::DisplayObserver * observer)143 void X11ScreenOzone::RemoveObserver(display::DisplayObserver* observer) {
144   x11_display_manager_->RemoveObserver(observer);
145 }
146 
GetCurrentWorkspace()147 std::string X11ScreenOzone::GetCurrentWorkspace() {
148   return x11_display_manager_->GetCurrentWorkspace();
149 }
150 
GetGpuExtraInfoAsListValue(const gfx::GpuExtraInfo & gpu_extra_info)151 base::Value X11ScreenOzone::GetGpuExtraInfoAsListValue(
152     const gfx::GpuExtraInfo& gpu_extra_info) {
153   return ui::GpuExtraInfoAsListValue(gpu_extra_info.system_visual,
154                                      gpu_extra_info.rgba_visual);
155 }
156 
DispatchXEvent(x11::Event * xev)157 bool X11ScreenOzone::DispatchXEvent(x11::Event* xev) {
158   return x11_display_manager_->ProcessEvent(xev);
159 }
160 
GetCursorLocation() const161 gfx::Point X11ScreenOzone::GetCursorLocation() const {
162   return x11_display_manager_->GetCursorLocation();
163 }
164 
OnXDisplayListUpdated()165 void X11ScreenOzone::OnXDisplayListUpdated() {
166   float scale_factor =
167       x11_display_manager_->GetPrimaryDisplay().device_scale_factor();
168   gfx::SetFontRenderParamsDeviceScaleFactor(scale_factor);
169 }
170 
GetXDisplayScaleFactor() const171 float X11ScreenOzone::GetXDisplayScaleFactor() const {
172   return GetDeviceScaleFactor();
173 }
174 
175 }  // namespace ui
176