Bug 1282003 - (Part 1) Add display type/density info and addScreen/removeScreen function. r=snorp
authorKuoE0 <kuoe0.tw@gmail.com>
Mon, 03 Oct 2016 16:23:23 +0800
changeset 318666 6be3aa402016169a3c7e8379740e383f46032198
parent 318665 6d73b7dae5983d707cac1e2b1fd44b3b7c9a4bca
child 318667 d9148f4b2ef5a23f58a19a93e505065869fd5219
push id30849
push usercbook@mozilla.com
push dateThu, 20 Oct 2016 14:45:29 +0000
treeherdermozilla-central@c2753c9ba68e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1282003
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1282003 - (Part 1) Add display type/density info and addScreen/removeScreen function. r=snorp MozReview-Commit-ID: 52IoWc1xevL
widget/android/nsScreenManagerAndroid.cpp
widget/android/nsScreenManagerAndroid.h
widget/nsIScreen.idl
--- a/widget/android/nsScreenManagerAndroid.cpp
+++ b/widget/android/nsScreenManagerAndroid.cpp
@@ -1,41 +1,77 @@
-/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
+/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=4 expandtab:
+ * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #define MOZ_FATAL_ASSERTIONS_FOR_THREAD_SAFETY
 
 #include "nsScreenManagerAndroid.h"
 #include "nsWindow.h"
 #include "GeneratedJNIWrappers.h"
 #include "AndroidRect.h"
 #include <mozilla/jni/Refs.h>
 
+#define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "nsScreenManagerAndroid", ## args)
+
 using namespace mozilla;
 
-nsScreenAndroid::nsScreenAndroid(void *nativeScreen)
+static uint32_t sScreenId = 0;
+const uint32_t PRIMARY_SCREEN_ID = 0;
+
+nsScreenAndroid::nsScreenAndroid(DisplayType aDisplayType, nsIntRect aRect)
+    : mId(sScreenId++)
+    , mDisplayType(aDisplayType)
+    , mRect(aRect)
+    , mDensity(0.0)
 {
+    // ensure that the ID of the primary screen would be PRIMARY_SCREEN_ID.
+    if (mDisplayType == DisplayType::DISPLAY_PRIMARY) {
+        mId = PRIMARY_SCREEN_ID;
+    }
 }
 
 nsScreenAndroid::~nsScreenAndroid()
 {
 }
 
+float
+nsScreenAndroid::GetDensity() {
+    if (mDensity != 0.0) {
+        return mDensity;
+    }
+    if (mDisplayType == DisplayType::DISPLAY_PRIMARY) {
+        mDensity = mozilla::jni::IsAvailable() ? GeckoAppShell::GetDensity()
+                                               : 1.0; // xpcshell most likely
+        return mDensity;
+    }
+    return 1.0;
+}
+
 NS_IMETHODIMP
 nsScreenAndroid::GetId(uint32_t *outId)
 {
-    *outId = 1;
+    *outId = mId;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsScreenAndroid::GetRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight)
 {
+    if (mDisplayType != DisplayType::DISPLAY_PRIMARY) {
+        *outLeft   = mRect.x;
+        *outTop    = mRect.y;
+        *outWidth  = mRect.width;
+        *outHeight = mRect.height;
+
+        return NS_OK;
+    }
+
     if (!mozilla::jni::IsAvailable()) {
       // xpcshell most likely
       *outLeft = *outTop = *outWidth = *outHeight = 0;
       return NS_ERROR_FAILURE;
     }
 
     java::sdk::Rect::LocalRef rect = java::GeckoAppShell::GetScreenSize();
     rect->Left(outLeft);
@@ -70,70 +106,106 @@ nsScreenAndroid::GetPixelDepth(int32_t *
 
 
 NS_IMETHODIMP
 nsScreenAndroid::GetColorDepth(int32_t *aColorDepth)
 {
     return GetPixelDepth(aColorDepth);
 }
 
+
 void
 nsScreenAndroid::ApplyMinimumBrightness(uint32_t aBrightness)
 {
-    if (mozilla::jni::IsAvailable()) {
-      java::GeckoAppShell::SetKeepScreenOn(aBrightness == BRIGHTNESS_FULL);
+    if (mDisplayType == DisplayType::DISPLAY_PRIMARY &&
+        mozilla::jni::IsAvailable()) {
+        java::GeckoAppShell::SetKeepScreenOn(aBrightness == BRIGHTNESS_FULL);
     }
 }
 
 NS_IMPL_ISUPPORTS(nsScreenManagerAndroid, nsIScreenManager)
 
 nsScreenManagerAndroid::nsScreenManagerAndroid()
 {
-    mOneScreen = new nsScreenAndroid(nullptr);
+    nsCOMPtr<nsIScreen> screen = AddScreen(DisplayType::DISPLAY_PRIMARY);
+    MOZ_ASSERT(screen);
 }
 
 nsScreenManagerAndroid::~nsScreenManagerAndroid()
 {
 }
 
 NS_IMETHODIMP
 nsScreenManagerAndroid::GetPrimaryScreen(nsIScreen **outScreen)
 {
-    NS_IF_ADDREF(*outScreen = mOneScreen.get());
+    ScreenForId(PRIMARY_SCREEN_ID, outScreen);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsScreenManagerAndroid::ScreenForId(uint32_t aId,
                                     nsIScreen **outScreen)
 {
-    return GetPrimaryScreen(outScreen);
+    for (size_t i = 0; i < mScreens.Length(); ++i) {
+        if (aId == mScreens[i]->GetId()) {
+            nsCOMPtr<nsIScreen> screen = (nsIScreen*) mScreens[i];
+            screen.forget(outScreen);
+            return NS_OK;
+        }
+    }
+
+    *outScreen = nullptr;
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsScreenManagerAndroid::ScreenForRect(int32_t inLeft,
                                       int32_t inTop,
                                       int32_t inWidth,
                                       int32_t inHeight,
                                       nsIScreen **outScreen)
 {
+    // Not support to query non-primary screen with rect.
     return GetPrimaryScreen(outScreen);
 }
 
 NS_IMETHODIMP
 nsScreenManagerAndroid::ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen)
 {
+    // Not support to query non-primary screen with native widget.
     return GetPrimaryScreen(outScreen);
 }
 
 NS_IMETHODIMP
 nsScreenManagerAndroid::GetNumberOfScreens(uint32_t *aNumberOfScreens)
 {
-    *aNumberOfScreens = 1;
+    *aNumberOfScreens = mScreens.Length();
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsScreenManagerAndroid::GetSystemDefaultScale(float *aDefaultScale)
 {
     *aDefaultScale = 1.0f;
     return NS_OK;
 }
+
+already_AddRefed<nsScreenAndroid>
+nsScreenManagerAndroid::AddScreen(DisplayType aDisplayType, nsIntRect aRect)
+{
+    ALOG("nsScreenManagerAndroid: add %s screen",
+        (aDisplayType == DisplayType::DISPLAY_PRIMARY  ? "PRIMARY"  :
+        (aDisplayType == DisplayType::DISPLAY_EXTERNAL ? "EXTERNAL" :
+                                                         "VIRTUAL")));
+    RefPtr<nsScreenAndroid> screen = new nsScreenAndroid(aDisplayType, aRect);
+    mScreens.AppendElement(screen);
+    return screen.forget();
+}
+
+void
+nsScreenManagerAndroid::RemoveScreen(uint32_t aScreenId)
+{
+    for (size_t i = 0; i < mScreens.Length(); i++) {
+        if (aScreenId == mScreens[i]->GetId()) {
+            mScreens.RemoveElementAt(i);
+        }
+    }
+}
--- a/widget/android/nsScreenManagerAndroid.h
+++ b/widget/android/nsScreenManagerAndroid.h
@@ -1,46 +1,64 @@
-/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
+/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: ts=4 sw=4 expandtab:
+ * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsScreenManagerAndroid_h___
 #define nsScreenManagerAndroid_h___
 
 #include "nsCOMPtr.h"
 
 #include "nsBaseScreen.h"
 #include "nsIScreenManager.h"
-#include "WidgetUtils.h"
+#include "nsRect.h"
+#include "mozilla/WidgetUtils.h"
 
 class nsScreenAndroid final : public nsBaseScreen
 {
 public:
-    nsScreenAndroid(void *nativeScreen);
+    nsScreenAndroid(DisplayType aDisplayType, nsIntRect aRect);
     ~nsScreenAndroid();
 
     NS_IMETHOD GetId(uint32_t* aId) override;
     NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override;
     NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override;
     NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override;
     NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override;
 
+    uint32_t GetId() const { return mId; };
+    DisplayType GetDisplayType() const { return mDisplayType; }
+
+    void SetDensity(double aDensity) { mDensity = aDensity; }
+    float GetDensity();
+
 protected:
     virtual void ApplyMinimumBrightness(uint32_t aBrightness) override;
+
+private:
+    uint32_t mId;
+    DisplayType mDisplayType;
+    nsIntRect mRect;
+    float mDensity;
 };
 
 class nsScreenManagerAndroid final : public nsIScreenManager
 {
 private:
     ~nsScreenManagerAndroid();
 
 public:
     nsScreenManagerAndroid();
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSISCREENMANAGER
 
+    already_AddRefed<nsScreenAndroid> AddScreen(DisplayType aDisplayType,
+                                                nsIntRect aRect = nsIntRect());
+    void RemoveScreen(uint32_t aScreenId);
+
 protected:
-    nsCOMPtr<nsIScreen> mOneScreen;
+    nsTArray<RefPtr<nsScreenAndroid>> mScreens;
 };
 
 #endif /* nsScreenManagerAndroid_h___ */
--- a/widget/nsIScreen.idl
+++ b/widget/nsIScreen.idl
@@ -1,16 +1,27 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
+%{C++
+/**
+ * The display type of nsIScreen belongs to.
+ */
+enum class DisplayType: int32_t {
+  DISPLAY_PRIMARY,  // primary screen
+  DISPLAY_EXTERNAL, // wired displays, such as HDMI, DisplayPort, etc.
+  DISPLAY_VIRTUAL   // wireless displays, such as Chromecast, WiFi-Display, etc.
+};
+%}
+
 [scriptable, uuid(826e80c8-d70f-42e2-8aa9-82c05f2a370a)]
 interface nsIScreen : nsISupports
 {
   /**
    * Levels of brightness for the screen, from off to full brightness.
    */
   const unsigned long BRIGHTNESS_DIM = 0;
   const unsigned long BRIGHTNESS_FULL = 1;