OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "modules/media_controls/MediaControlsOrientationLockDelegate.h" | 5 #include "modules/media_controls/MediaControlsOrientationLockDelegate.h" |
6 | 6 |
7 #include "core/events/Event.h" | 7 #include "core/events/Event.h" |
8 #include "core/frame/LocalDOMWindow.h" | 8 #include "core/frame/LocalDOMWindow.h" |
9 #include "core/frame/Screen.h" | 9 #include "core/frame/Screen.h" |
10 #include "core/frame/ScreenOrientationController.h" | 10 #include "core/frame/ScreenOrientationController.h" |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
177 // If the rotate-to-fullscreen feature is also enabled, then start listening | 177 // If the rotate-to-fullscreen feature is also enabled, then start listening |
178 // to deviceorientation events so the orientation can be unlocked once the | 178 // to deviceorientation events so the orientation can be unlocked once the |
179 // user rotates the device to match the video's orientation (allowing the user | 179 // user rotates the device to match the video's orientation (allowing the user |
180 // to then exit fullscreen by rotating their device back to the opposite | 180 // to then exit fullscreen by rotating their device back to the opposite |
181 // orientation). Otherwise, don't listen for deviceorientation events and just | 181 // orientation). Otherwise, don't listen for deviceorientation events and just |
182 // hold the orientation lock until the user exits fullscreen (which prevents | 182 // hold the orientation lock until the user exits fullscreen (which prevents |
183 // the user rotating to the wrong fullscreen orientation). | 183 // the user rotating to the wrong fullscreen orientation). |
184 if (!RuntimeEnabledFeatures::videoRotateToFullscreenEnabled()) | 184 if (!RuntimeEnabledFeatures::videoRotateToFullscreenEnabled()) |
185 return; | 185 return; |
186 | 186 |
187 if (is_auto_rotate_enabled_by_user_for_testing_ != -1) { | |
188 GotIsAutoRotateEnabledByUser( | |
189 static_cast<bool>(is_auto_rotate_enabled_by_user_for_testing_)); | |
190 return; | |
191 } | |
192 | |
187 // Check whether the user locked screen orientation at the OS level. | 193 // Check whether the user locked screen orientation at the OS level. |
188 #if OS(ANDROID) | 194 #if OS(ANDROID) |
189 DCHECK(!monitor_.is_bound()); | 195 DCHECK(!monitor_.is_bound()); |
190 Platform::Current()->GetConnector()->BindInterface( | 196 Platform::Current()->GetConnector()->BindInterface( |
191 device::mojom::blink::kServiceName, mojo::MakeRequest(&monitor_)); | 197 device::mojom::blink::kServiceName, mojo::MakeRequest(&monitor_)); |
192 monitor_->IsAutoRotateEnabledByUser(ConvertToBaseCallback(WTF::Bind( | 198 monitor_->IsAutoRotateEnabledByUser(ConvertToBaseCallback(WTF::Bind( |
193 &MediaControlsOrientationLockDelegate::GotIsAutoRotateEnabledByUser, | 199 &MediaControlsOrientationLockDelegate::GotIsAutoRotateEnabledByUser, |
194 WrapPersistent(this)))); | 200 WrapPersistent(this)))); |
195 #else | 201 #else |
196 GotIsAutoRotateEnabledByUser(true); // Assume always enabled on other OSes. | 202 GotIsAutoRotateEnabledByUser(true); // Assume always enabled on other OSes. |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
290 case kWebScreenOrientationLandscapeSecondary: | 296 case kWebScreenOrientationLandscapeSecondary: |
291 return kWebScreenOrientationLockLandscape; | 297 return kWebScreenOrientationLockLandscape; |
292 case kWebScreenOrientationUndefined: | 298 case kWebScreenOrientationUndefined: |
293 return kWebScreenOrientationLockLandscape; | 299 return kWebScreenOrientationLockLandscape; |
294 } | 300 } |
295 | 301 |
296 NOTREACHED(); | 302 NOTREACHED(); |
297 return kWebScreenOrientationLockLandscape; | 303 return kWebScreenOrientationLockLandscape; |
298 } | 304 } |
299 | 305 |
300 void MediaControlsOrientationLockDelegate:: | 306 MediaControlsOrientationLockDelegate::DeviceOrientation |
301 MaybeUnlockIfDeviceOrientationMatchesVideo(DeviceOrientationEvent* event) { | 307 MediaControlsOrientationLockDelegate::ComputeDeviceOrientation( |
302 DCHECK_EQ(state_, State::kMaybeLockedFullscreen); | 308 DeviceOrientationData* data) const { |
303 DCHECK_NE(locked_orientation_, kWebScreenOrientationLockDefault); | |
304 | |
305 LocalDOMWindow* dom_window = GetDocument().domWindow(); | 309 LocalDOMWindow* dom_window = GetDocument().domWindow(); |
306 if (!dom_window) | 310 if (!dom_window) |
307 return; | 311 return DeviceOrientation::kUnknown; |
308 | 312 |
309 if (!event->Orientation()->CanProvideBeta() || | 313 if (!data->CanProvideBeta() || !data->CanProvideGamma()) |
310 !event->Orientation()->CanProvideGamma()) { | 314 return DeviceOrientation::kUnknown; |
311 return; | 315 double beta = data->Beta(); |
312 } | 316 double gamma = data->Gamma(); |
313 double beta = event->Orientation()->Beta(); | |
314 double gamma = event->Orientation()->Gamma(); | |
315 | 317 |
316 // Calculate the projection of the up vector (normal to the earth's surface) | 318 // Calculate the projection of the up vector (normal to the earth's surface) |
317 // onto the device's screen in its natural orientation. (x,y) will lie within | 319 // onto the device's screen in its natural orientation. (x,y) will lie within |
318 // the unit circle centered on (0,0), e.g. if the top of the device is | 320 // the unit circle centered on (0,0), e.g. if the top of the device is |
319 // pointing upwards (x,y) will be (0,-1). | 321 // pointing upwards (x,y) will be (0,-1). |
320 double x = -std::sin(deg2rad(gamma)) * std::cos(deg2rad(beta)); | 322 double x = -std::sin(deg2rad(gamma)) * std::cos(deg2rad(beta)); |
321 double y = -std::sin(deg2rad(beta)); | 323 double y = -std::sin(deg2rad(beta)); |
322 | 324 |
323 // Convert (x,y) to polar coordinates: 0 <= device_orientation_angle < 360 and | 325 // Convert (x,y) to polar coordinates: 0 <= device_orientation_angle < 360 and |
324 // 0 <= r <= 1, such that device_orientation_angle is the clockwise angle in | 326 // 0 <= r <= 1, such that device_orientation_angle is the clockwise angle in |
325 // degrees between the current physical orientation of the device and the | 327 // degrees between the current physical orientation of the device and the |
326 // natural physical orientation of the device (ignoring the screen | 328 // natural physical orientation of the device (ignoring the screen |
327 // orientation). Thus snapping device_orientation_angle to the nearest | 329 // orientation). Thus snapping device_orientation_angle to the nearest |
328 // multiple of 90 gives the value screen.orientation.angle would have if the | 330 // multiple of 90 gives the value screen.orientation.angle would have if the |
329 // screen orientation was allowed to rotate freely to match the device | 331 // screen orientation was allowed to rotate freely to match the device |
330 // orientation. Note that we want device_orientation_angle==0 when the top of | 332 // orientation. Note that we want device_orientation_angle==0 when the top of |
331 // the device is pointing upwards, but atan2's zero angle points to the right, | 333 // the device is pointing upwards, but atan2's zero angle points to the right, |
332 // so we pass y=x and x=-y to atan2 to rotate by 90 degrees. | 334 // so we pass y=x and x=-y to atan2 to rotate by 90 degrees. |
333 double r = std::sqrt(x * x + y * y); | 335 double r = std::sqrt(x * x + y * y); |
334 double device_orientation_angle = | 336 double device_orientation_angle = |
335 std::fmod(rad2deg(std::atan2(/* y= */ x, /* x= */ -y)) + 360, 360); | 337 std::fmod(rad2deg(std::atan2(/* y= */ x, /* x= */ -y)) + 360, 360); |
336 | 338 |
337 constexpr double kMinElevationAngle = 24; // degrees from horizontal plane | 339 constexpr double kMinElevationAngle = 24; // degrees from horizontal plane |
338 if (r < std::sin(deg2rad(kMinElevationAngle))) | 340 if (r < std::sin(deg2rad(kMinElevationAngle))) |
339 return; // Device is too flat to reliably determine orientation. | 341 return DeviceOrientation::kFlat; // Can't reliably determine orientation. |
340 | 342 |
341 // device_orientation_angle snapped to nearest multiple of 90. | 343 // device_orientation_angle snapped to nearest multiple of 90. |
342 int device_orientation_angle90 = | 344 int device_orientation_angle90 = |
343 std::lround(device_orientation_angle / 90) * 90; | 345 std::lround(device_orientation_angle / 90) * 90; |
344 | 346 |
345 if (std::abs(device_orientation_angle - device_orientation_angle90) > 23) { | 347 if (std::abs(device_orientation_angle - device_orientation_angle90) > 23) |
timvolodine
2017/05/31 18:07:21
nit: not really related to this CL, but how was th
johnme
2017/06/01 13:15:10
I expanded the comment.
| |
346 // Device is diagonal (within 44 degree hysteresis zone). | 348 return DeviceOrientation::kDiagonal; // Within 44 degree hysteresis zone. |
347 return; | |
348 } | |
349 | 349 |
350 // screen.orientation.angle is the standardized replacement for | 350 // screen.orientation.angle is the standardized replacement for |
351 // window.orientation. They are equal, except -90 was replaced by 270. | 351 // window.orientation. They are equal, except -90 was replaced by 270. |
352 int screen_orientation_angle = | 352 int screen_orientation_angle = |
353 ScreenScreenOrientation::orientation(nullptr /* ScriptState */, | 353 ScreenScreenOrientation::orientation(nullptr /* ScriptState */, |
354 *dom_window->screen()) | 354 *dom_window->screen()) |
355 ->angle(); | 355 ->angle(); |
356 | 356 |
357 // This is equivalent to screen.orientation.type.startsWith('landscape'). | 357 // This is equivalent to screen.orientation.type.startsWith('landscape'). |
358 bool screen_orientation_is_landscape = | 358 bool screen_orientation_is_portrait = |
359 dom_window->screen()->width() > dom_window->screen()->height(); | 359 dom_window->screen()->width() <= dom_window->screen()->height(); |
360 | 360 |
361 // The natural orientation of the device could either be portrait (almost | 361 // The natural orientation of the device could either be portrait (almost |
362 // all phones, and some tablets like Nexus 7) or landscape (other tablets | 362 // all phones, and some tablets like Nexus 7) or landscape (other tablets |
363 // like Pixel C). Detect this by comparing angle to orientation. | 363 // like Pixel C). Detect this by comparing angle to orientation. |
364 // TODO(johnme): This might get confused on square screens. | 364 // TODO(johnme): This might get confused on square screens. |
365 bool screen_orientation_is_natural_or_flipped_natural = | 365 bool screen_orientation_is_natural_or_flipped_natural = |
366 screen_orientation_angle % 180 == 0; | 366 screen_orientation_angle % 180 == 0; |
367 bool natural_orientation_is_landscape = | 367 bool natural_orientation_is_portrait = |
368 screen_orientation_is_landscape == | 368 screen_orientation_is_portrait == |
369 screen_orientation_is_natural_or_flipped_natural; | 369 screen_orientation_is_natural_or_flipped_natural; |
370 | 370 |
371 bool natural_orientation_matches_video = | 371 // If natural_orientation_is_portrait_, then angles 0 and 180 are portrait, |
372 natural_orientation_is_landscape == | 372 // otherwise angles 90 and 270 are portrait. |
373 (locked_orientation_ == kWebScreenOrientationLockLandscape); | 373 int portrait_angle_mod_180 = natural_orientation_is_portrait ? 0 : 90; |
374 return device_orientation_angle90 % 180 == portrait_angle_mod_180 | |
375 ? DeviceOrientation::kPortrait | |
376 : DeviceOrientation::kLandscape; | |
377 } | |
374 | 378 |
375 // If natural_orientation_matches_video, then 0 and 180 match video, otherwise | 379 void MediaControlsOrientationLockDelegate:: |
376 // 90 and 270 match video. | 380 MaybeUnlockIfDeviceOrientationMatchesVideo(DeviceOrientationEvent* event) { |
377 bool device_orientation_matches_video = | 381 DCHECK_EQ(state_, State::kMaybeLockedFullscreen); |
378 (device_orientation_angle90 % 180) == | 382 DCHECK(locked_orientation_ == kWebScreenOrientationLockPortrait || |
379 (natural_orientation_matches_video ? 0 : 90); | 383 locked_orientation_ == kWebScreenOrientationLockLandscape); |
380 | 384 |
381 if (!device_orientation_matches_video) | 385 DeviceOrientation device_orientation = |
386 ComputeDeviceOrientation(event->Orientation()); | |
387 | |
388 DeviceOrientation video_orientation = | |
389 locked_orientation_ == kWebScreenOrientationLockPortrait | |
390 ? DeviceOrientation::kPortrait | |
391 : DeviceOrientation::kLandscape; | |
392 | |
393 if (device_orientation != video_orientation) | |
382 return; | 394 return; |
383 | 395 |
384 // Job done: the user rotated their device to match the orientation of the | 396 // Job done: the user rotated their device to match the orientation of the |
385 // video that we locked to, so now we can unlock (and stop listening). | 397 // video that we locked to, so now we can unlock (and stop listening). |
386 MaybeUnlockOrientation(); | 398 MaybeUnlockOrientation(); |
387 } | 399 } |
388 | 400 |
389 DEFINE_TRACE(MediaControlsOrientationLockDelegate) { | 401 DEFINE_TRACE(MediaControlsOrientationLockDelegate) { |
390 EventListener::Trace(visitor); | 402 EventListener::Trace(visitor); |
391 visitor->Trace(video_element_); | 403 visitor->Trace(video_element_); |
392 } | 404 } |
393 | 405 |
394 } // namespace blink | 406 } // namespace blink |
OLD | NEW |