1 // Copyright (c) 2013 Intel Corporation. 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.
5 var internal = requireNative('internal');
6 internal.setupInternalExtension(extension);
8 // These constants must correspond with C++ side:
9 // xwalk/runtime/browser/ui/screen_orientation.h
10 var PORTRAIT_PRIMARY = 1 << 0;
11 var LANDSCAPE_PRIMARY = 1 << 1;
12 var PORTRAIT_SECONDARY = 1 << 2;
13 var LANDSCAPE_SECONDARY = 1 << 3;
14 var PORTRAIT = PORTRAIT_PRIMARY | PORTRAIT_SECONDARY;
15 var LANDSCAPE = LANDSCAPE_PRIMARY | LANDSCAPE_SECONDARY;
16 var ANY = PORTRAIT | LANDSCAPE;
18 // Values that can be set externally.
19 var uaDefault = uaDefault || ANY;
20 var isAndroid = isAndroid || false;
22 // Store the real Screen object.
23 var realScreen = window.screen;
25 function cloneProperties(target, source) {
26 var props = Object.getOwnPropertyNames(source);
27 props.forEach(function(item) {
28 target[item] = source[item];
32 // Create replacement Screen and make it an EventTarget.
33 function Screen() { cloneProperties(this, realScreen); };
34 Screen.prototype = Object.create(EventTarget.prototype);
35 Screen.prototype.constructor = Screen;
38 window.screen = new Screen();
40 function postMessage(command, value) {
41 // Currently, internal.postMessage can't work on Android.
42 // https://crosswalk-project.org/jira/browse/XWALK-855
44 var message = JSON.stringify({
46 value: value.toString()
48 extension.postMessage(message);
50 internal.postMessage(command, value, null);
54 window.screen.lockOrientation = function(orientations) {
55 if (!Array.isArray(orientations)) {
56 if (typeof orientations != 'string')
58 orientations = [orientations];
62 for (var i = 0; i < orientations.length; ++i) {
63 switch (orientations[i]) {
64 case 'portrait-primary':
65 value |= PORTRAIT_PRIMARY;
67 case 'portrait-secondary':
68 value |= PORTRAIT_SECONDARY;
70 case 'landscape-primary':
71 value |= LANDSCAPE_PRIMARY;
73 case 'landscape-secondary':
74 value |= LANDSCAPE_SECONDARY;
83 console.error('Invalid screen orientation');
86 // If the orientations aren't all part of the default allowed
87 // orientations, the steps must stop here and return false.
88 if ((uaDefault & value) != value)
91 postMessage('lock', [value]);
95 window.screen.unlockOrientation = function() {
96 postMessage('lock', [uaDefault]);
99 // Create a HTMLUnknownElement and do not attach it to the DOM.
100 var dispatcher = document.createElement('xwalk-EventDispatcher');
102 // Implement EventTarget interface on object.
103 Object.defineProperty(window.screen, 'addEventListener', {
104 value: function(type, callback, capture) {
105 dispatcher.addEventListener(type, callback, capture);
109 Object.defineProperty(window.screen, 'removeEventListener', {
110 value: function(type, callback, capture) {
111 dispatcher.removeEventListener(type, callback, capture);
115 Object.defineProperty(window.screen, 'dispatchEvent', {
117 dispatcher.dispatchEvent(e);
121 var orientationchangeCallback = null;
122 var orientationchangeCallbackWrapper = null;
124 Object.defineProperty(window.screen, 'onorientationchange', {
127 get: function() { return orientationchangeCallback; },
128 set: function(callback) {
129 // We must add the on* event as an event listener so that
130 // it is called at the right point between potential
131 // event listeners, but it cannot be the exact method
132 // as that would allow removeEventListener to remove it.
134 // Remove existing (wrapped) listener.
135 window.screen.removeEventListener('orientationchange',
136 orientationchangeCallbackWrapper);
138 // If valid, store and add a wrapped version as listener.
139 if (callback instanceof Function) {
140 orientationchangeCallback = callback;
141 orientationchangeCallbackWrapper = function() { callback(); };
142 window.screen.addEventListener('orientationchange',
143 orientationchangeCallbackWrapper);
145 // If not valid, reset to null.
147 orientationchangeCallback = null;
148 orientationchangeCallbackWrapper = null;
153 function handleOrientationChange(newOrientation) {
154 switch (newOrientation) {
155 case PORTRAIT_PRIMARY:
156 orientationValue = 'portrait-primary';
158 case PORTRAIT_SECONDARY:
159 orientationValue = 'portrait-secondary';
161 case LANDSCAPE_PRIMARY:
162 orientationValue = 'landscape-primary';
164 case LANDSCAPE_SECONDARY:
165 orientationValue = 'landscape-secondary';
168 console.error('Received unknown value for current orientation');
172 // The first time the listener is called it is to set the current
173 // orientation, so do not dispatch the orientationchange in that case.
174 if (handleOrientationChange.shouldDispatchEvent) {
175 var event = new Event('orientationchange');
176 dispatcher.dispatchEvent(event);
179 handleOrientationChange.shouldDispatchEvent = true;
182 var orientationValue;
184 Object.defineProperty(window.screen, 'orientation', {
188 if (typeof orientationValue == 'undefined') {
189 var msg = JSON.stringify({
190 cmd: 'GetScreenOrientation'
192 var newOrientation = extension.internal.sendSyncMessage(msg);
193 handleOrientationChange(newOrientation);
195 return orientationValue;
199 // FIXME: Extend message listener to handle screen changes.
200 extension.setMessageListener(handleOrientationChange);