Bug 628949 - Update visible region / glass regions after we paint. r=roc a=2.0.
[mozilla-central.git] / dom / system / nsAccelerometer.cpp
blob330fbaf14e427d646c74a01d2f1ab6db260b9e96
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is mozilla.org code.
16 * The Initial Developer of the Original Code is
17 * Doug Turner <dougt@dougt.org>
18 * Portions created by the Initial Developer are Copyright (C) 2009
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 #include "nsAccelerometer.h"
39 #include "nsAutoPtr.h"
40 #include "nsIDOMEvent.h"
41 #include "nsIDOMWindow.h"
42 #include "nsIDOMDocument.h"
43 #include "nsIDOMEventTarget.h"
44 #include "nsIServiceManager.h"
45 #include "nsIPrivateDOMEvent.h"
46 #include "nsIDOMDocumentEvent.h"
47 #include "nsIDOMOrientationEvent.h"
48 #include "nsIServiceManager.h"
49 #include "nsIPrefService.h"
51 class nsAcceleration : public nsIAcceleration
53 public:
54 NS_DECL_ISUPPORTS
55 NS_DECL_NSIACCELERATION
57 nsAcceleration(double x, double y, double z);
59 private:
60 ~nsAcceleration();
62 protected:
63 /* additional members */
64 double mX, mY, mZ;
67 /* Implementation file */
68 NS_IMPL_ISUPPORTS1(nsAcceleration, nsIAcceleration)
70 nsAcceleration::nsAcceleration(double x, double y, double z)
71 :mX(x), mY(y), mZ(z)
75 nsAcceleration::~nsAcceleration()
79 NS_IMETHODIMP nsAcceleration::GetX(double *aX)
81 NS_ENSURE_ARG_POINTER(aX);
82 *aX = mX;
83 return NS_OK;
86 NS_IMETHODIMP nsAcceleration::GetY(double *aY)
88 NS_ENSURE_ARG_POINTER(aY);
89 *aY = mY;
90 return NS_OK;
93 NS_IMETHODIMP nsAcceleration::GetZ(double *aZ)
95 NS_ENSURE_ARG_POINTER(aZ);
96 *aZ = mZ;
97 return NS_OK;
100 NS_IMPL_ISUPPORTS2(nsAccelerometer, nsIAccelerometer, nsIAccelerometerUpdate)
102 nsAccelerometer::nsAccelerometer()
103 : mLastX(10), /* initialize to values that can't be possible */
104 mLastY(10),
105 mLastZ(10),
106 mStarted(PR_FALSE),
107 mNewListener(PR_FALSE),
108 mUpdateInterval(50), /* default to 50 ms */
109 mEnabled(PR_TRUE)
111 nsCOMPtr<nsIPrefBranch> prefSrv = do_GetService(NS_PREFSERVICE_CONTRACTID);
112 if (prefSrv) {
113 PRInt32 value;
114 nsresult rv = prefSrv->GetIntPref("accelerometer.update.interval", &value);
115 if (NS_SUCCEEDED(rv))
116 mUpdateInterval = value;
118 PRBool bvalue;
119 rv = prefSrv->GetBoolPref("accelerometer.enabled", &bvalue);
120 if (NS_SUCCEEDED(rv) && bvalue == PR_FALSE)
121 mEnabled = PR_FALSE;
125 nsAccelerometer::~nsAccelerometer()
127 if (mTimeoutTimer)
128 mTimeoutTimer->Cancel();
131 void
132 nsAccelerometer::StartDisconnectTimer()
134 if (mTimeoutTimer)
135 mTimeoutTimer->Cancel();
137 mTimeoutTimer = do_CreateInstance("@mozilla.org/timer;1");
138 if (mTimeoutTimer)
139 mTimeoutTimer->InitWithFuncCallback(TimeoutHandler,
140 this,
141 2000,
142 nsITimer::TYPE_ONE_SHOT);
145 void
146 nsAccelerometer::TimeoutHandler(nsITimer *aTimer, void *aClosure)
148 // the reason that we use self, instead of just using nsITimerCallback or nsIObserver
149 // is so that subclasses are free to use timers without worry about the base classes's
150 // usage.
151 nsAccelerometer *self = reinterpret_cast<nsAccelerometer *>(aClosure);
152 if (!self) {
153 NS_ERROR("no self");
154 return;
157 // what about listeners that don't clean up properly? they will leak
158 if (self->mListeners.Count() == 0 && self->mWindowListeners.Count() == 0) {
159 self->Shutdown();
160 self->mStarted = PR_FALSE;
164 NS_IMETHODIMP nsAccelerometer::AddListener(nsIAccelerationListener *aListener)
166 if (mListeners.IndexOf(aListener) >= 0)
167 return NS_OK; // already exists
169 if (mStarted == PR_FALSE) {
170 mStarted = PR_TRUE;
171 mNewListener = PR_TRUE;
172 Startup();
175 mListeners.AppendObject(aListener);
176 return NS_OK;
179 NS_IMETHODIMP nsAccelerometer::RemoveListener(nsIAccelerationListener *aListener)
181 if (mListeners.IndexOf(aListener) < 0)
182 return NS_OK; // doesn't exist
184 mListeners.RemoveObject(aListener);
185 StartDisconnectTimer();
186 return NS_OK;
189 NS_IMETHODIMP nsAccelerometer::AddWindowListener(nsIDOMWindow *aWindow)
191 if (mWindowListeners.IndexOf(aWindow) >= 0)
192 return NS_OK; // already exists
194 if (mStarted == PR_FALSE) {
195 mStarted = PR_TRUE;
196 mNewListener = PR_TRUE;
197 Startup();
200 mWindowListeners.AppendObject(aWindow);
201 return NS_OK;
204 NS_IMETHODIMP nsAccelerometer::RemoveWindowListener(nsIDOMWindow *aWindow)
206 if (mWindowListeners.IndexOf(aWindow) < 0)
207 return NS_OK; // doesn't exist
209 mWindowListeners.RemoveObject(aWindow);
210 StartDisconnectTimer();
212 return NS_OK;
215 NS_IMETHODIMP
216 nsAccelerometer::AccelerationChanged(double x, double y, double z)
218 if (!mEnabled)
219 return NS_ERROR_NOT_INITIALIZED;
221 if (x > 1)
222 x = 1;
223 if (y > 1)
224 y = 1;
225 if (z > 1)
226 z = 1;
227 if (x < -1)
228 x = -1;
229 if (y < -1)
230 y = -1;
231 if (z < -1)
232 z = -1;
234 if (!mNewListener) {
235 if (PR_ABS(mLastX - x) < .01 &&
236 PR_ABS(mLastY - y) < .01 &&
237 PR_ABS(mLastZ - z) < .01)
238 return NS_OK;
241 mLastX = x;
242 mLastY = y;
243 mLastZ = z;
244 mNewListener = PR_FALSE;
246 for (PRUint32 i = mListeners.Count(); i > 0 ; ) {
247 --i;
248 nsRefPtr<nsIAcceleration> a = new nsAcceleration(x, y, z);
249 mListeners[i]->OnAccelerationChange(a);
252 for (PRUint32 i = mWindowListeners.Count(); i > 0 ; ) {
253 --i;
255 nsCOMPtr<nsIDOMDocument> domdoc;
256 mWindowListeners[i]->GetDocument(getter_AddRefs(domdoc));
258 nsCOMPtr<nsIDOMDocumentEvent> docevent(do_QueryInterface(domdoc));
259 nsCOMPtr<nsIDOMEvent> event;
261 PRBool defaultActionEnabled = PR_TRUE;
263 if (docevent) {
264 docevent->CreateEvent(NS_LITERAL_STRING("orientation"), getter_AddRefs(event));
266 nsCOMPtr<nsIDOMOrientationEvent> oe = do_QueryInterface(event);
268 if (event) {
269 oe->InitOrientationEvent(NS_LITERAL_STRING("MozOrientation"),
270 PR_TRUE,
271 PR_FALSE,
276 nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(event);
277 if (privateEvent)
278 privateEvent->SetTrusted(PR_TRUE);
280 nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mWindowListeners[i]));
281 target->DispatchEvent(event, &defaultActionEnabled);
285 return NS_OK;