diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index d0a57442623..5bc00336d2b 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -2466,6 +2466,7 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(Screen, nsIDOMScreen) DOM_CLASSINFO_MAP_ENTRY(nsIDOMScreen) + DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMPrototype, nsIDOMDOMConstructor) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 3979a866b15..e91f1c085a1 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -1312,6 +1312,11 @@ nsGlobalWindow::FreeInnerObjects(bool aClearScope) mNavigator = nsnull; } + if (mScreen) { + mScreen->Invalidate(); + mScreen = nsnull; + } + if (mDocument) { NS_ASSERTION(mDoc, "Why is mDoc null?"); @@ -2492,8 +2497,6 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell) if (mFrames) mFrames->SetDocShell(aDocShell); - if (mScreen) - mScreen->SetDocShell(aDocShell); if (!mDocShell) { MaybeForgiveSpamCount(); @@ -3001,14 +3004,14 @@ nsGlobalWindow::GetNavigator(nsIDOMNavigator** aNavigator) NS_IMETHODIMP nsGlobalWindow::GetScreen(nsIDOMScreen** aScreen) { - FORWARD_TO_OUTER(GetScreen, (aScreen), NS_ERROR_NOT_INITIALIZED); + FORWARD_TO_INNER(GetScreen, (aScreen), NS_ERROR_NOT_INITIALIZED); *aScreen = nsnull; - if (!mScreen && mDocShell) { - mScreen = new nsScreen(mDocShell); + if (!mScreen) { + mScreen = nsScreen::Create(this); if (!mScreen) { - return NS_ERROR_OUT_OF_MEMORY; + return NS_ERROR_UNEXPECTED; } } diff --git a/dom/base/nsScreen.cpp b/dom/base/nsScreen.cpp index cb7560fd8c7..1737e3fb14a 100644 --- a/dom/base/nsScreen.cpp +++ b/dom/base/nsScreen.cpp @@ -46,8 +46,10 @@ #include "nsIDocShellTreeItem.h" #include "nsLayoutUtils.h" #include "mozilla/Preferences.h" +#include "nsDOMEvent.h" using namespace mozilla; +using namespace mozilla::dom; /* static */ bool nsScreen::sInitialized = false; /* static */ bool nsScreen::sAllowScreenEnabledProperty = false; @@ -64,42 +66,75 @@ nsScreen::Initialize() "dom.screenBrightnessProperty.enabled"); } -// -// Screen class implementation -// -nsScreen::nsScreen(nsIDocShell* aDocShell) - : mDocShell(aDocShell) +void +nsScreen::Invalidate() +{ + hal::UnregisterScreenOrientationObserver(this); +} + +/* static */ already_AddRefed +nsScreen::Create(nsPIDOMWindow* aWindow) { if (!sInitialized) { Initialize(); } + + if (!aWindow->GetDocShell()) { + return nsnull; + } + + nsRefPtr screen = new nsScreen(); + + nsCOMPtr sgo = do_QueryInterface(aWindow); + NS_ENSURE_TRUE(sgo, nsnull); + + nsCOMPtr scriptContext = sgo->GetContext(); + NS_ENSURE_TRUE(scriptContext, nsnull); + + screen->mOwner = aWindow; + screen->mScriptContext.swap(scriptContext); + screen->mDocShell = aWindow->GetDocShell(); + + hal::RegisterScreenOrientationObserver(screen); + hal::GetCurrentScreenOrientation(&(screen->mOrientation)); + + return screen.forget(); +} + +nsScreen::nsScreen() +{ } nsScreen::~nsScreen() { + Invalidate(); } - DOMCI_DATA(Screen, nsScreen) +NS_IMPL_CYCLE_COLLECTION_CLASS(nsScreen) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsScreen, + nsDOMEventTargetHelper) + NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(mozorientationchange) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsScreen, + nsDOMEventTargetHelper) + NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(mozorientationchange) +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + // QueryInterface implementation for nsScreen -NS_INTERFACE_MAP_BEGIN(nsScreen) - NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsScreen) NS_INTERFACE_MAP_ENTRY(nsIDOMScreen) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMScreen) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Screen) -NS_INTERFACE_MAP_END +NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper) +NS_IMPL_ADDREF_INHERITED(nsScreen, nsDOMEventTargetHelper) +NS_IMPL_RELEASE_INHERITED(nsScreen, nsDOMEventTargetHelper) -NS_IMPL_ADDREF(nsScreen) -NS_IMPL_RELEASE(nsScreen) - - -NS_IMETHODIMP -nsScreen::SetDocShell(nsIDocShell* aDocShell) -{ - mDocShell = aDocShell; // Weak Reference - return NS_OK; -} +NS_IMPL_EVENT_HANDLER(nsScreen, mozorientationchange) NS_IMETHODIMP nsScreen::GetTop(PRInt32* aTop) @@ -325,3 +360,63 @@ nsScreen::SetMozBrightness(double aBrightness) hal::SetScreenBrightness(aBrightness); return NS_OK; } + +void +nsScreen::Notify(const ScreenOrientationWrapper& aOrientation) +{ + ScreenOrientation previousOrientation = mOrientation; + mOrientation = aOrientation.orientation; + + NS_ASSERTION(mOrientation != eScreenOrientation_Current && + mOrientation != eScreenOrientation_EndGuard && + mOrientation != eScreenOrientation_Portrait && + mOrientation != eScreenOrientation_Landscape, + "Invalid orientation value passed to notify method!"); + + if (mOrientation != previousOrientation) { + // TODO: use an helper method, see bug 720768. + nsRefPtr event = new nsDOMEvent(nsnull, nsnull); + nsresult rv = event->InitEvent(NS_LITERAL_STRING("mozorientationchange"), false, false); + if (NS_FAILED(rv)) { + return; + } + + rv = event->SetTrusted(true); + if (NS_FAILED(rv)) { + return; + } + + bool dummy; + rv = DispatchEvent(event, &dummy); + if (NS_FAILED(rv)) { + return; + } + } +} + +NS_IMETHODIMP +nsScreen::GetMozOrientation(nsAString& aOrientation) +{ + switch (mOrientation) { + case eScreenOrientation_Current: + case eScreenOrientation_EndGuard: + case eScreenOrientation_Portrait: + case eScreenOrientation_Landscape: + NS_ASSERTION(false, "Shouldn't be used when getting value!"); + return NS_ERROR_FAILURE; + case eScreenOrientation_PortraitPrimary: + aOrientation.AssignLiteral("portrait-primary"); + break; + case eScreenOrientation_PortraitSecondary: + aOrientation.AssignLiteral("portrait-secondary"); + break; + case eScreenOrientation_LandscapePrimary: + aOrientation.AssignLiteral("landscape-primary"); + break; + case eScreenOrientation_LandscapeSecondary: + aOrientation.AssignLiteral("landscape-secondary"); + break; + } + + return NS_OK; +} diff --git a/dom/base/nsScreen.h b/dom/base/nsScreen.h index 288ab7cfc21..77311f906b9 100644 --- a/dom/base/nsScreen.h +++ b/dom/base/nsScreen.h @@ -37,26 +37,37 @@ #ifndef nsScreen_h___ #define nsScreen_h___ +#include "mozilla/Hal.h" #include "nsIDOMScreen.h" #include "nsISupports.h" #include "nsIScriptContext.h" #include "nsCOMPtr.h" +#include "mozilla/dom/ScreenOrientation.h" +#include "nsDOMEventTargetHelper.h" +#include "mozilla/Observer.h" class nsIDocShell; class nsDeviceContext; struct nsRect; // Script "screen" object -class nsScreen : public nsIDOMScreen +class nsScreen : public nsDOMEventTargetHelper + , public nsIDOMScreen + , public mozilla::hal::ScreenOrientationObserver { public: - nsScreen(nsIDocShell* aDocShell); - virtual ~nsScreen(); + static already_AddRefed Create(nsPIDOMWindow* aWindow); - NS_IMETHOD SetDocShell(nsIDocShell* aDocShell); + void Invalidate(); NS_DECL_ISUPPORTS NS_DECL_NSIDOMSCREEN + NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::) + + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsScreen, + nsDOMEventTargetHelper) + + void Notify(const mozilla::dom::ScreenOrientationWrapper& aOrientation); protected: nsDeviceContext* GetDeviceContext(); @@ -65,12 +76,19 @@ protected: nsIDocShell* mDocShell; // Weak Reference + mozilla::dom::ScreenOrientation mOrientation; + private: + nsScreen(); + virtual ~nsScreen(); + static bool sInitialized; static bool sAllowScreenEnabledProperty; static bool sAllowScreenBrightnessProperty; static void Initialize(); + + NS_DECL_EVENT_HANDLER(mozorientationchange) }; #endif /* nsScreen_h___ */ diff --git a/dom/interfaces/base/Makefile.in b/dom/interfaces/base/Makefile.in index 6db3e981e18..b15eb6e987c 100644 --- a/dom/interfaces/base/Makefile.in +++ b/dom/interfaces/base/Makefile.in @@ -91,3 +91,5 @@ XPIDLSRCS = \ $(NULL) include $(topsrcdir)/config/rules.mk + +XPIDL_FLAGS += -I$(topsrcdir)/dom/interfaces/events/ diff --git a/dom/interfaces/base/nsIDOMScreen.idl b/dom/interfaces/base/nsIDOMScreen.idl index 14cd6d1e184..cb158ffc772 100644 --- a/dom/interfaces/base/nsIDOMScreen.idl +++ b/dom/interfaces/base/nsIDOMScreen.idl @@ -37,10 +37,10 @@ * * ***** END LICENSE BLOCK ***** */ -#include "domstubs.idl" +#include "nsIDOMEventTarget.idl" -[scriptable, uuid(4507e43f-097c-452a-bfc4-dbb99748f6fd)] -interface nsIDOMScreen : nsISupports +[scriptable, uuid(6366afc9-0072-4231-a4ec-98cd65f350ef)] +interface nsIDOMScreen : nsIDOMEventTarget { readonly attribute long top; readonly attribute long left; @@ -75,4 +75,13 @@ interface nsIDOMScreen : nsISupports * @throw NS_ERROR_INVALID_ARG if brightness is not in the range [0, 1]. */ attribute double mozBrightness; + + /** + * Returns the current screen orientation. + * Can be: landscape-primary, landscape-secondary, + * portrait-primary or portrait-secondary. + */ + readonly attribute DOMString mozOrientation; + + attribute nsIDOMEventListener onmozorientationchange; };