Bug 1282003 - (Part 1) Add display type/density info and addScreen/removeScreen function. r=snorp
☠☠ backed out by ef345e3b5fa9 ☠ ☠
authorKuoE0 <kuoe0.tw@gmail.com>
Mon, 03 Oct 2016 16:23:23 +0800
changeset 316582 ddf5af982d8b7a4258b3a6e05ee4c76ce66af605
parent 316581 80d979342a04c163156c1b74235cb9c24f850658
child 316583 13db73034f80ba7dba3c0665380b86d23ddb38ea
push id20663
push usercbook@mozilla.com
push dateThu, 06 Oct 2016 06:48:08 +0000
treeherderfx-team@1d7748535fa3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1282003
milestone52.0a1
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,65 @@
-/* -*- 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 "AndroidBridge.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(mozilla::java::GeckoAppShell::GetDensity())
 {
+    // ensure that the ID of the primary screen would be PRIMARY_SCREEN_ID.
+    if (mDisplayType == DisplayType::DISPLAY_PRIMARY) {
+        mId = PRIMARY_SCREEN_ID;
+    }
 }
 
 nsScreenAndroid::~nsScreenAndroid()
 {
 }
 
 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 +94,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() const { return mDensity; }
+
 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;