summaryrefslogtreecommitdiffstats
path: root/widget/android/nsScreenManagerAndroid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'widget/android/nsScreenManagerAndroid.cpp')
-rw-r--r--widget/android/nsScreenManagerAndroid.cpp264
1 files changed, 264 insertions, 0 deletions
diff --git a/widget/android/nsScreenManagerAndroid.cpp b/widget/android/nsScreenManagerAndroid.cpp
new file mode 100644
index 000000000..4a79b9dab
--- /dev/null
+++ b/widget/android/nsScreenManagerAndroid.cpp
@@ -0,0 +1,264 @@
+/* -*- 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 "mozilla/SyncRunnable.h"
+#include "nsScreenManagerAndroid.h"
+#include "nsServiceManagerUtils.h"
+#include "AndroidRect.h"
+#include "FennecJNINatives.h"
+#include "nsAppShell.h"
+#include "nsThreadUtils.h"
+
+#include <android/log.h>
+#include <mozilla/jni/Refs.h>
+
+#define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "nsScreenManagerAndroid", ## args)
+
+using namespace mozilla;
+using namespace mozilla::java;
+
+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 = 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);
+ rect->Top(outTop);
+ rect->Width(outWidth);
+ rect->Height(outHeight);
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsScreenAndroid::GetAvailRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight)
+{
+ return GetRect(outLeft, outTop, outWidth, outHeight);
+}
+
+
+
+NS_IMETHODIMP
+nsScreenAndroid::GetPixelDepth(int32_t *aPixelDepth)
+{
+ if (!mozilla::jni::IsAvailable()) {
+ // xpcshell most likely
+ *aPixelDepth = 16;
+ return NS_ERROR_FAILURE;
+ }
+
+ *aPixelDepth = java::GeckoAppShell::GetScreenDepth();
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsScreenAndroid::GetColorDepth(int32_t *aColorDepth)
+{
+ return GetPixelDepth(aColorDepth);
+}
+
+
+void
+nsScreenAndroid::ApplyMinimumBrightness(uint32_t aBrightness)
+{
+ if (mDisplayType == DisplayType::DISPLAY_PRIMARY &&
+ mozilla::jni::IsAvailable()) {
+ java::GeckoAppShell::SetKeepScreenOn(aBrightness == BRIGHTNESS_FULL);
+ }
+}
+
+class nsScreenManagerAndroid::ScreenManagerHelperSupport final
+ : public ScreenManagerHelper::Natives<ScreenManagerHelperSupport>
+{
+public:
+ typedef ScreenManagerHelper::Natives<ScreenManagerHelperSupport> Base;
+
+ static int32_t AddDisplay(int32_t aDisplayType, int32_t aWidth, int32_t aHeight, float aDensity) {
+ int32_t screenId = -1; // return value
+ nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
+ SyncRunnable::DispatchToThread(mainThread, NS_NewRunnableFunction(
+ [&aDisplayType, &aWidth, &aHeight, &aDensity, &screenId] {
+ MOZ_ASSERT(NS_IsMainThread());
+ nsCOMPtr<nsIScreenManager> screenMgr =
+ do_GetService("@mozilla.org/gfx/screenmanager;1");
+ MOZ_ASSERT(screenMgr, "Failed to get nsIScreenManager");
+
+ RefPtr<nsScreenManagerAndroid> screenMgrAndroid =
+ (nsScreenManagerAndroid*) screenMgr.get();
+ RefPtr<nsScreenAndroid> screen =
+ screenMgrAndroid->AddScreen(static_cast<DisplayType>(aDisplayType),
+ nsIntRect(0, 0, aWidth, aHeight));
+ MOZ_ASSERT(screen);
+ screen->SetDensity(aDensity);
+ screenId = static_cast<int32_t>(screen->GetId());
+ }).take());
+ return screenId;
+ }
+
+ static void RemoveDisplay(int32_t aScreenId) {
+ nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
+ SyncRunnable::DispatchToThread(mainThread, NS_NewRunnableFunction(
+ [&aScreenId] {
+ MOZ_ASSERT(NS_IsMainThread());
+ nsCOMPtr<nsIScreenManager> screenMgr =
+ do_GetService("@mozilla.org/gfx/screenmanager;1");
+ MOZ_ASSERT(screenMgr, "Failed to get nsIScreenManager");
+
+ RefPtr<nsScreenManagerAndroid> screenMgrAndroid =
+ (nsScreenManagerAndroid*) screenMgr.get();
+ screenMgrAndroid->RemoveScreen(aScreenId);
+ }).take());
+ }
+};
+
+NS_IMPL_ISUPPORTS(nsScreenManagerAndroid, nsIScreenManager)
+
+nsScreenManagerAndroid::nsScreenManagerAndroid()
+{
+ if (mozilla::jni::IsAvailable()) {
+ ScreenManagerHelperSupport::Base::Init();
+ }
+ nsCOMPtr<nsIScreen> screen = AddScreen(DisplayType::DISPLAY_PRIMARY);
+ MOZ_ASSERT(screen);
+}
+
+nsScreenManagerAndroid::~nsScreenManagerAndroid()
+{
+}
+
+NS_IMETHODIMP
+nsScreenManagerAndroid::GetPrimaryScreen(nsIScreen **outScreen)
+{
+ ScreenForId(PRIMARY_SCREEN_ID, outScreen);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsScreenManagerAndroid::ScreenForId(uint32_t aId,
+ nsIScreen **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 = 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);
+ }
+ }
+}