Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(635)

Side by Side Diff: remoting/client/desktop_viewport.cc

Issue 2879383002: [CRD iOS] Move UI stuff into a subdirectory (Closed)
Patch Set: Fix include Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « remoting/client/desktop_viewport.h ('k') | remoting/client/desktop_viewport_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 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 "remoting/client/desktop_viewport.h"
6
7 #include <algorithm>
8
9 #include "base/logging.h"
10
11 namespace remoting {
12
13 namespace {
14
15 float MAX_ZOOM_LEVEL = 100.f;
16
17 } // namespace
18
19 DesktopViewport::DesktopViewport() : desktop_to_surface_transform_() {}
20
21 DesktopViewport::~DesktopViewport() {}
22
23 void DesktopViewport::SetDesktopSize(int desktop_width, int desktop_height) {
24 if (desktop_width == desktop_size_.x && desktop_height == desktop_size_.y) {
25 return;
26 }
27
28 desktop_size_.x = desktop_width;
29 desktop_size_.y = desktop_height;
30 ResizeToFit();
31 }
32
33 void DesktopViewport::SetSurfaceSize(int surface_width, int surface_height) {
34 if (surface_width == surface_size_.x && surface_height == surface_size_.y) {
35 return;
36 }
37
38 surface_size_.x = surface_width;
39 surface_size_.y = surface_height;
40 ResizeToFit();
41 }
42
43 void DesktopViewport::MoveDesktop(float dx, float dy) {
44 desktop_to_surface_transform_.PostTranslate({dx, dy});
45 UpdateViewport();
46 }
47
48 void DesktopViewport::ScaleDesktop(float px, float py, float scale) {
49 desktop_to_surface_transform_.PostScale({px, py}, scale);
50 UpdateViewport();
51 }
52
53 void DesktopViewport::MoveViewport(float dx, float dy) {
54 MoveViewportWithoutUpdate(dx, dy);
55 UpdateViewport();
56 }
57
58 void DesktopViewport::SetViewportCenter(float x, float y) {
59 ViewMatrix::Point old_center = GetViewportCenter();
60 MoveViewport(x - old_center.x, y - old_center.y);
61 }
62
63 void DesktopViewport::RegisterOnTransformationChangedCallback(
64 const TransformationCallback& callback,
65 bool run_immediately) {
66 on_transformation_changed_ = callback;
67 if (IsViewportReady() && run_immediately) {
68 callback.Run(desktop_to_surface_transform_);
69 }
70 }
71
72 const ViewMatrix& DesktopViewport::GetTransformation() const {
73 return desktop_to_surface_transform_;
74 }
75
76 void DesktopViewport::ResizeToFit() {
77 if (!IsViewportReady()) {
78 return;
79 }
80
81 // <---Desktop Width---->
82 // +==========+---------+
83 // | | |
84 // | Viewport | Desktop |
85 // | | |
86 // +==========+---------+
87 //
88 // +==========+ ^
89 // | | |
90 // | Viewport | |
91 // | | |
92 // +==========+ | Desktop
93 // | | | Height
94 // | Desktop | |
95 // | | |
96 // +----------+ v
97 // resize the desktop such that it fits the viewport in one dimension.
98
99 float scale = std::max(surface_size_.x / desktop_size_.x,
100 surface_size_.y / desktop_size_.y);
101 desktop_to_surface_transform_.SetScale(scale);
102 desktop_to_surface_transform_.SetOffset({0.f, 0.f});
103 UpdateViewport();
104 }
105
106 bool DesktopViewport::IsViewportReady() const {
107 return desktop_size_.x != 0 && desktop_size_.y != 0 && surface_size_.x != 0 &&
108 surface_size_.y != 0;
109 }
110
111 void DesktopViewport::UpdateViewport() {
112 if (!IsViewportReady()) {
113 // User may attempt to zoom and pan before the desktop image is received.
114 // This should be fine since the viewport will be reset once the image
115 // dimension is set.
116 VLOG(1) << "Viewport is not ready yet.";
117 return;
118 }
119
120 // Adjust zoom level.
121 float zoom_level = desktop_to_surface_transform_.GetScale();
122 if (zoom_level > MAX_ZOOM_LEVEL) {
123 // TODO(yuweih): This doesn't account for the effect of the pivot point,
124 // which will shift the desktop closer to the origin.
125 desktop_to_surface_transform_.SetScale(MAX_ZOOM_LEVEL);
126 }
127
128 ViewMatrix::Vector2D desktop_size_on_surface_ =
129 desktop_to_surface_transform_.MapVector(desktop_size_);
130 if (desktop_size_on_surface_.x < surface_size_.x &&
131 desktop_size_on_surface_.y < surface_size_.y) {
132 // +==============+
133 // | VP | +==========+
134 // | | | VP |
135 // | +----------+ | +----------+
136 // | | DP | | ==> | DP |
137 // | +----------+ | +----------+
138 // | | | |
139 // | | +==========+
140 // +==============+
141 // Displayed desktop is too small in both directions, so apply the minimum
142 // zoom level needed to fit either the width or height.
143 float scale = std::min(surface_size_.x / desktop_size_.x,
144 surface_size_.y / desktop_size_.y);
145 desktop_to_surface_transform_.SetScale(scale);
146 }
147
148 // Adjust position.
149 // Scenarios:
150 // 1. If the viewport can fully fit inside the desktop (smaller or equal width
151 // and height) but it overlaps with the border, it will be moved in minimum
152 // distance to be fitted inside the desktop.
153 //
154 // +========+
155 // | VP |
156 // | +----|--------+ +========+-----+
157 // | | | | | | |
158 // +========+ | | VP | DP |
159 // | DP | ==> | | |
160 // | | +========+ |
161 // | | | |
162 // +-------------+ +--------------+
163 //
164 // 2. If the viewport is larger than the desktop, the viewport will always
165 // share the same center as the desktop.
166 //
167 // +==========+------+==+ +======+------+======+
168 // | VP | DP | | ==> | VP | DP | |
169 // +==========+------+==+ +======+------+======+
170 //
171 // This is done on the desktop's reference frame to simplify things a bit.
172 ViewMatrix::Point old_center = GetViewportCenter();
173 ViewMatrix::Point new_center =
174 ConstrainPointToBounds(GetViewportCenterBounds(), old_center);
175 MoveViewportWithoutUpdate(new_center.x - old_center.x,
176 new_center.y - old_center.y);
177
178 if (on_transformation_changed_) {
179 on_transformation_changed_.Run(desktop_to_surface_transform_);
180 }
181 }
182
183 DesktopViewport::Bounds DesktopViewport::GetViewportCenterBounds() const {
184 Bounds bounds;
185
186 // Viewport size on the desktop space.
187 ViewMatrix::Vector2D viewport_size =
188 desktop_to_surface_transform_.Invert().MapVector(surface_size_);
189
190 // Scenario 1: If VP can fully fit inside the desktop, then VP's center can be
191 // anywhere inside the desktop as long as VP doesn't overlap with the border.
192 bounds.left = viewport_size.x / 2.f;
193 bounds.right = desktop_size_.x - viewport_size.x / 2.f;
194 bounds.top = viewport_size.y / 2.f;
195 bounds.bottom = desktop_size_.y - viewport_size.y / 2.f;
196
197 // Scenario 2: If VP can't fully fit inside the desktop in dimension D, then
198 // its bounds in dimension D is tightly restricted to the center of the
199 // desktop.
200 if (bounds.left > bounds.right) {
201 float desktop_width_center = desktop_size_.x / 2.f;
202 bounds.left = desktop_width_center;
203 bounds.right = desktop_width_center;
204 }
205
206 if (bounds.top > bounds.bottom) {
207 float desktop_height_center = desktop_size_.y / 2.f;
208 bounds.top = desktop_height_center;
209 bounds.bottom = desktop_height_center;
210 }
211
212 return bounds;
213 }
214
215 ViewMatrix::Point DesktopViewport::GetViewportCenter() const {
216 return desktop_to_surface_transform_.Invert().MapPoint(
217 {surface_size_.x / 2.f, surface_size_.y / 2.f});
218 }
219
220 void DesktopViewport::MoveViewportWithoutUpdate(float dx, float dy) {
221 // <dx, dy> is defined on desktop's reference frame. Translation must be
222 // flipped and scaled.
223 desktop_to_surface_transform_.PostTranslate(
224 desktop_to_surface_transform_.MapVector({-dx, -dy}));
225 }
226
227 // static
228 ViewMatrix::Point DesktopViewport::ConstrainPointToBounds(
229 const Bounds& bounds,
230 const ViewMatrix::Point& point) {
231 ViewMatrix::Point new_point = point;
232 if (new_point.x < bounds.left) {
233 new_point.x = bounds.left;
234 } else if (new_point.x > bounds.right) {
235 new_point.x = bounds.right;
236 }
237
238 if (new_point.y < bounds.top) {
239 new_point.y = bounds.top;
240 } else if (new_point.y > bounds.bottom) {
241 new_point.y = bounds.bottom;
242 }
243 return new_point;
244 }
245
246 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/client/desktop_viewport.h ('k') | remoting/client/desktop_viewport_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698