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

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

Issue 2843373005: [Remoting Client] DesktopViewport Implementation (Closed)
Patch Set: Fix 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
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_(0.f, {0.f, 0.f}) {}
joedow 2017/04/28 21:29:52 Add a default c'tor to SimpleMatrix so you don't n
Yuwei 2017/04/28 23:53:40 Done.
20
21 DesktopViewport::~DesktopViewport() {}
22
23 void DesktopViewport::SetDesktopSize(int desktop_width, int desktop_height) {
24 bool need_resize_to_fit = !desktop_size_ready_ && surface_size_ready_;
25 desktop_size_.x = desktop_width;
26 desktop_size_.y = desktop_height;
27 desktop_size_ready_ = true;
28 if (need_resize_to_fit) {
29 ResizeToFit();
30 } else if (IsViewportReady()) {
31 UpdateViewport();
32 }
33 }
34
35 void DesktopViewport::SetSurfaceSize(int surface_width, int surface_height) {
36 bool need_resize_to_fit = desktop_size_ready_ && !surface_size_ready_;
37 surface_size_.x = surface_width;
38 surface_size_.y = surface_height;
39 surface_size_ready_ = true;
40 if (need_resize_to_fit) {
41 ResizeToFit();
42 } else if (IsViewportReady()) {
43 UpdateViewport();
44 }
45 }
46
47 void DesktopViewport::ResizeToFit() {
48 if (!IsViewportReady()) {
49 LOG(ERROR) << "Viewport is not ready.";
joedow 2017/04/28 21:29:52 Should this be a DCHECK? It seems like this is un
Yuwei 2017/04/28 23:53:40 Done.
50 return;
51 }
52
53 // <---Desktop Width---->
joedow 2017/04/28 21:29:52 I like the ASCII art, I think it would be good to
Yuwei 2017/04/28 23:53:40 Done.
54 // +==========+---------+
55 // | | |
56 // | Viewport | Desktop |
57 // | | |
58 // +==========+---------+
59 //
60 // +==========+ ^
61 // | | |
62 // | Viewport | |
63 // | | |
64 // +==========+ | Desktop
65 // | | | Height
66 // | Desktop | |
67 // | | |
68 // +----------+ v
69
70 float scale = std::max(surface_size_.x / desktop_size_.x,
71 surface_size_.y / desktop_size_.y);
72 desktop_to_surface_.SetScale(scale);
73 UpdateViewport();
74 }
75
76 void DesktopViewport::MoveDesktop(float dx, float dy) {
77 desktop_to_surface_.PostTranslate({dx, dy});
78 UpdateViewport();
79 }
80
81 void DesktopViewport::ScaleDesktop(float px, float py, float scale) {
82 desktop_to_surface_.PostScale({px, py}, scale);
83 UpdateViewport();
84 }
85
86 void DesktopViewport::SetViewportCenter(float x, float y) {
87 Point old_center = GetViewportCenter();
88 MoveViewportCenterWithoutUpdate(x - old_center.x, y - old_center.y);
89 UpdateViewport();
90 }
91
92 void DesktopViewport::RegisterOnTransformationChangedCallback(
93 const TransformationCallback& callback,
94 bool run_immediately) {
95 on_transformation_changed_ = callback;
96 if (IsViewportReady() && run_immediately) {
97 callback.Run(desktop_to_surface_.ToMatrixArray());
98 }
99 }
100
101 bool DesktopViewport::IsViewportReady() const {
102 return desktop_size_ready_ && surface_size_ready_;
103 }
104
105 void DesktopViewport::UpdateViewport() {
106 // Adjust zoom level.
107 float zoom_level = desktop_to_surface_.GetScale();
108 if (zoom_level > MAX_ZOOM_LEVEL) {
109 // TODO(yuweih): This doesn't account for the effect of the pivot point,
110 // which will shift the desktop closer to the origin.
111 desktop_to_surface_.SetScale(MAX_ZOOM_LEVEL);
112 }
113
114 Vector2D desktop_size_on_surface_ =
115 desktop_to_surface_.MapVector(desktop_size_);
116 if (desktop_size_on_surface_.x < surface_size_.x &&
117 desktop_size_on_surface_.y < surface_size_.y) {
118 // +==============+
119 // | VP | +==========+
120 // | | | VP |
121 // | +----------+ | +----------+
122 // | | DP | | ==> | DP |
123 // | +----------+ | +----------+
124 // | | | |
125 // | | +==========+
126 // +==============+
127 // Displayed desktop is too small in both directions, so apply the minimum
128 // zoom level needed to fit either the width or height.
129 float scale = std::min(surface_size_.x / desktop_size_.x,
130 surface_size_.y / desktop_size_.y);
131 desktop_to_surface_.SetScale(scale);
132 }
133
134 // Adjust position.
135 // Scenarios:
136 // 1. If the viewport can fully fit inside the desktop (smaller or equal width
137 // and height), but it doesn't overlap with any non-desktop area, it will
138 // be moved in minimum distance to be fitted inside the desktop.
139 //
140 // +========+
141 // | VP |
142 // | +----|--------+ +========+-----+
143 // | | | | | | |
144 // +========+ | | VP | DP |
145 // | DP | ==> | | |
146 // | | +========+ |
147 // | | | |
148 // +-------------+ +--------------+
149 //
150 // 2. If the viewport is larger than the desktop, the viewport will always
151 // share the same center as the desktop.
152 //
153 // +==========+------+==+ +======+------+======+
154 // | VP | DP | | ==> | VP | DP | |
155 // +==========+------+==+ +======+------+======+
156 //
157 // This is done on the desktop's reference frame to simplify things a bit.
158 Point old_center = GetViewportCenter();
159 Point new_center =
160 ConstrainPointToBounds(GetViewportCenterBounds(), old_center);
161 MoveViewportCenterWithoutUpdate(new_center.x - old_center.x,
162 new_center.y - old_center.y);
163
164 if (!on_transformation_changed_.is_null()) {
joedow 2017/04/28 21:29:52 nit: You don't need to call is_null(): if (on_tra
Yuwei 2017/04/28 23:53:40 Done.
165 on_transformation_changed_.Run(desktop_to_surface_.ToMatrixArray());
166 }
167 }
168
169 Bounds DesktopViewport::GetViewportCenterBounds() const {
170 Bounds bounds;
171
172 // Viewport size on the desktop space.
173 Vector2D viewport_size =
174 desktop_to_surface_.Invert().MapVector(surface_size_);
175
176 // Scenario 1: If VP can fully fit inside the desktop, then VP's center can be
177 // anywhere inside the desktop as long as VP doesn't overlap with the border.
178 bounds.left = viewport_size.x * 0.5f;
joedow 2017/04/28 21:29:52 divide by 2? I think that is a more natural way t
Yuwei 2017/04/28 23:53:40 Done.
179 bounds.right = desktop_size_.x - viewport_size.x * 0.5f;
180 bounds.top = viewport_size.y * 0.5f;
181 bounds.bottom = desktop_size_.y - viewport_size.y * 0.5f;
182
183 // Scenario 2: If VP can't fully fit inside the desktop in dimension D, then
184 // its bounds in dimension D is tightly restricted to the center of the
185 // desktop.
186 if (bounds.left > bounds.right) {
187 float desktop_width_center = desktop_size_.x * 0.5f;
188 bounds.left = desktop_width_center;
189 bounds.right = desktop_width_center;
190 }
191
192 if (bounds.top > bounds.bottom) {
193 float desktop_height_center = desktop_size_.y * 0.5f;
194 bounds.top = desktop_height_center;
195 bounds.bottom = desktop_height_center;
196 }
197
198 return bounds;
199 }
200
201 Point DesktopViewport::GetViewportCenter() const {
202 return desktop_to_surface_.Invert().MapPoint(
203 {surface_size_.x * 0.5f, surface_size_.y * 0.5f});
204 }
205
206 void DesktopViewport::MoveViewportCenterWithoutUpdate(float dx, float dy) {
207 // <dx, dy> is defined on desktop's reference frame. Translation must be
208 // flipped and scaled.
209 desktop_to_surface_.PostTranslate(desktop_to_surface_.MapVector({-dx, -dy}));
210 }
211
212 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698