Source: lib/polyfill/orientation.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.polyfill.Orientation');
  7. goog.require('shaka.util.FakeEvent');
  8. goog.require('shaka.util.FakeEventTarget');
  9. goog.require('shaka.polyfill');
  10. /**
  11. * @summary A polyfill for systems that do not implement screen.orientation.
  12. * For now, this only handles systems that implement the deprecated
  13. * window.orientation feature... e.g. iPad.
  14. * @export
  15. */
  16. shaka.polyfill.Orientation = class {
  17. /**
  18. * Install the polyfill if needed.
  19. * @export
  20. */
  21. static install() {
  22. if (screen.orientation) {
  23. // Not needed.
  24. return;
  25. }
  26. // There is no way to check to see if the 'orientationchange' event exists
  27. // on window, which could theoretically lead to this making a
  28. // screen.orientation object that doesn't actually work.
  29. // However, it looks like all platforms that support the deprecated
  30. // window.orientation feature also support that event.
  31. if (window.orientation != undefined) {
  32. shaka.polyfill.Orientation.installBasedOnWindowMethods_();
  33. }
  34. }
  35. /**
  36. * Makes a polyfill for orientation, based on window methods.
  37. * Note that some of the features this is based on are deprecated, so this
  38. * will not necessarily work on all platforms.
  39. * @private
  40. */
  41. static installBasedOnWindowMethods_() {
  42. const orientation = new shaka.polyfill.Orientation.FakeOrientation();
  43. screen.orientation = /** @type {!ScreenOrientation} */ (orientation);
  44. const setValues = () => {
  45. switch (window.orientation) {
  46. case -90:
  47. orientation.type = 'landscape-secondary';
  48. orientation.angle = 270;
  49. break;
  50. case 0:
  51. orientation.type = 'portrait-primary';
  52. orientation.angle = 0;
  53. break;
  54. case 90:
  55. orientation.type = 'landscape-primary';
  56. orientation.angle = 90;
  57. break;
  58. case 180:
  59. orientation.type = 'portrait-secondary';
  60. orientation.angle = 180;
  61. break;
  62. }
  63. };
  64. setValues();
  65. window.addEventListener('orientationchange', () => {
  66. setValues();
  67. orientation.dispatchChangeEvent();
  68. });
  69. }
  70. };
  71. shaka.polyfill.Orientation.FakeOrientation =
  72. class extends shaka.util.FakeEventTarget {
  73. /** */
  74. constructor() {
  75. super();
  76. /** @type {string} */
  77. this.type = '';
  78. /** @type {number} */
  79. this.angle = 0;
  80. }
  81. /** Dispatch a 'change' event. */
  82. dispatchChangeEvent() {
  83. const event = new shaka.util.FakeEvent('change');
  84. this.dispatchEvent(event);
  85. }
  86. /**
  87. * @param {string} orientation
  88. * @return {!Promise}
  89. */
  90. lock(orientation) {
  91. /**
  92. * @param {string} orientation
  93. * @return {boolean}
  94. */
  95. const lockOrientation = (orientation) => {
  96. if (screen.lockOrientation) {
  97. return screen.lockOrientation(orientation);
  98. }
  99. if (screen.mozLockOrientation) {
  100. return screen.mozLockOrientation(orientation);
  101. }
  102. if (screen.msLockOrientation) {
  103. return screen.msLockOrientation(orientation);
  104. }
  105. return false;
  106. };
  107. let success = false;
  108. // The set of input strings for screen.orientation.lock and for
  109. // screen.lockOrientation are almost, but not entirely, the same.
  110. switch (orientation) {
  111. case 'natural':
  112. success = lockOrientation('default');
  113. break;
  114. case 'any':
  115. // It's not quite clear what locking the screen orientation to 'any'
  116. // is supposed to mean... presumably, that's equivalent to not being
  117. // locked?
  118. success = true;
  119. this.unlock();
  120. break;
  121. default:
  122. success = lockOrientation(orientation);
  123. break;
  124. }
  125. // According to the docs, there "may be a delay" between the
  126. // lockOrientation method being called and the screen actually being
  127. // locked. Unfortunately, without any idea as to how long that delay is,
  128. // and with no events to listen for, we cannot account for it here.
  129. if (success) {
  130. return Promise.resolve();
  131. }
  132. // Either locking was not available, or the process failed... either way,
  133. // reject this with a mock error.
  134. // This should be a DOMException, but there is not a public constructor for
  135. // that. So we make this look-alike instead.
  136. const unsupportedKeySystemError =
  137. new Error('screen.orientation.lock() is not available on this device');
  138. unsupportedKeySystemError.name = 'NotSupportedError';
  139. unsupportedKeySystemError['code'] = DOMException.NOT_SUPPORTED_ERR;
  140. return Promise.reject(unsupportedKeySystemError);
  141. }
  142. /** Unlock the screen orientation. */
  143. unlock() {
  144. // screen.unlockOrientation has a return value, but
  145. // screen.orientation.unlock does not. So ignore the return value.
  146. if (screen.unlockOrientation) {
  147. screen.unlockOrientation();
  148. } else if (screen.mozUnlockOrientation) {
  149. screen.mozUnlockOrientation();
  150. } else if (screen.msUnlockOrientation) {
  151. screen.msUnlockOrientation();
  152. }
  153. }
  154. };
  155. shaka.polyfill.register(shaka.polyfill.Orientation.install);