diff --git a/mobile/android/base/java/org/mozilla/gecko/ScreenManagerHelper.java b/mobile/android/base/java/org/mozilla/gecko/ScreenManagerHelper.java new file mode 100644 index 000000000000..5cb404ce8a93 --- /dev/null +++ b/mobile/android/base/java/org/mozilla/gecko/ScreenManagerHelper.java @@ -0,0 +1,43 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- + * 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/. */ + +package org.mozilla.gecko; + +import org.mozilla.gecko.annotation.WrapForJNI; + +class ScreenManagerHelper { + + /** + * The following display types use the same definition in nsIScreen.idl + */ + final static int DISPLAY_PRIMARY = 0; // primary screen + final static int DISPLAY_EXTERNAL = 1; // wired displays, such as HDMI, DisplayPort, etc. + final static int DISPLAY_VIRTUAL = 2; // wireless displays, such as Chromecast, WiFi-Display, etc. + + /** + * Add a new nsScreen when a new display in Android is available. + * + * @param displayType the display type of the nsScreen would be added + * @param width the width of the new nsScreen + * @param height the height of the new nsScreen + * @param density the density of the new nsScreen + * + * @return return the ID of the added nsScreen + */ + @WrapForJNI + public native static int addDisplay(int displayType, + int width, + int height, + float density); + + /** + * Remove the nsScreen by the specific screen ID. + * + * @param screenId the ID of the screen would be removed. + */ + @WrapForJNI + public native static void removeDisplay(int screenId); +} diff --git a/mobile/android/base/moz.build b/mobile/android/base/moz.build index 1183191ead4e..1b9194264b6b 100644 --- a/mobile/android/base/moz.build +++ b/mobile/android/base/moz.build @@ -648,6 +648,7 @@ gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [ 'restrictions/RestrictionConfiguration.java', 'restrictions/RestrictionProvider.java', 'restrictions/Restrictions.java', + 'ScreenManagerHelper.java', 'ScreenshotObserver.java', 'search/SearchEngine.java', 'search/SearchEngineManager.java', diff --git a/widget/android/fennec/FennecJNINatives.h b/widget/android/fennec/FennecJNINatives.h index f8580e9830f0..00dc859729e5 100644 --- a/widget/android/fennec/FennecJNINatives.h +++ b/widget/android/fennec/FennecJNINatives.h @@ -89,6 +89,25 @@ const JNINativeMethod PresentationMediaPlayerManager::Natives::methods[] = ::template Wrap<&Impl::RemovePresentationSurface>) }; +template +class ScreenManagerHelper::Natives : public mozilla::jni::NativeImpl +{ +public: + static const JNINativeMethod methods[2]; +}; + +template +const JNINativeMethod ScreenManagerHelper::Natives::methods[] = { + + mozilla::jni::MakeNativeMethod( + mozilla::jni::NativeStub + ::template Wrap<&Impl::AddDisplay>), + + mozilla::jni::MakeNativeMethod( + mozilla::jni::NativeStub + ::template Wrap<&Impl::RemoveDisplay>) +}; + template class Telemetry::Natives : public mozilla::jni::NativeImpl { diff --git a/widget/android/fennec/FennecJNIWrappers.cpp b/widget/android/fennec/FennecJNIWrappers.cpp index 128c34c07f34..73b5ea876e32 100644 --- a/widget/android/fennec/FennecJNIWrappers.cpp +++ b/widget/android/fennec/FennecJNIWrappers.cpp @@ -121,6 +121,15 @@ constexpr char PresentationMediaPlayerManager::InvalidateAndScheduleComposite_t: constexpr char PresentationMediaPlayerManager::RemovePresentationSurface_t::name[]; constexpr char PresentationMediaPlayerManager::RemovePresentationSurface_t::signature[]; +const char ScreenManagerHelper::name[] = + "org/mozilla/gecko/ScreenManagerHelper"; + +constexpr char ScreenManagerHelper::AddDisplay_t::name[]; +constexpr char ScreenManagerHelper::AddDisplay_t::signature[]; + +constexpr char ScreenManagerHelper::RemoveDisplay_t::name[]; +constexpr char ScreenManagerHelper::RemoveDisplay_t::signature[]; + const char Telemetry::name[] = "org/mozilla/gecko/Telemetry"; diff --git a/widget/android/fennec/FennecJNIWrappers.h b/widget/android/fennec/FennecJNIWrappers.h index 5480a3d84711..d573cc9df46e 100644 --- a/widget/android/fennec/FennecJNIWrappers.h +++ b/widget/android/fennec/FennecJNIWrappers.h @@ -397,6 +397,58 @@ public: template class Natives; }; +class ScreenManagerHelper : public mozilla::jni::ObjectBase +{ +public: + static const char name[]; + + explicit ScreenManagerHelper(const Context& ctx) : ObjectBase(ctx) {} + + struct AddDisplay_t { + typedef ScreenManagerHelper Owner; + typedef int32_t ReturnType; + typedef int32_t SetterType; + typedef mozilla::jni::Args< + int32_t, + int32_t, + int32_t, + float> Args; + static constexpr char name[] = "addDisplay"; + static constexpr char signature[] = + "(IIIF)I"; + static const bool isStatic = true; + static const mozilla::jni::ExceptionMode exceptionMode = + mozilla::jni::ExceptionMode::ABORT; + static const mozilla::jni::CallingThread callingThread = + mozilla::jni::CallingThread::ANY; + static const mozilla::jni::DispatchTarget dispatchTarget = + mozilla::jni::DispatchTarget::CURRENT; + }; + + struct RemoveDisplay_t { + typedef ScreenManagerHelper Owner; + typedef void ReturnType; + typedef void SetterType; + typedef mozilla::jni::Args< + int32_t> Args; + static constexpr char name[] = "removeDisplay"; + static constexpr char signature[] = + "(I)V"; + static const bool isStatic = true; + static const mozilla::jni::ExceptionMode exceptionMode = + mozilla::jni::ExceptionMode::ABORT; + static const mozilla::jni::CallingThread callingThread = + mozilla::jni::CallingThread::ANY; + static const mozilla::jni::DispatchTarget dispatchTarget = + mozilla::jni::DispatchTarget::CURRENT; + }; + + static const mozilla::jni::CallingThread callingThread = + mozilla::jni::CallingThread::ANY; + + template class Natives; +}; + class Telemetry : public mozilla::jni::ObjectBase { public: diff --git a/widget/android/nsScreenManagerAndroid.cpp b/widget/android/nsScreenManagerAndroid.cpp index 61b95d0f8ed3..4a79b9dab283 100644 --- a/widget/android/nsScreenManagerAndroid.cpp +++ b/widget/android/nsScreenManagerAndroid.cpp @@ -6,15 +6,21 @@ #define MOZ_FATAL_ASSERTIONS_FOR_THREAD_SAFETY +#include "mozilla/SyncRunnable.h" #include "nsScreenManagerAndroid.h" -#include "nsWindow.h" -#include "GeneratedJNIWrappers.h" +#include "nsServiceManagerUtils.h" #include "AndroidRect.h" +#include "FennecJNINatives.h" +#include "nsAppShell.h" +#include "nsThreadUtils.h" + +#include #include #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; @@ -121,10 +127,57 @@ nsScreenAndroid::ApplyMinimumBrightness(uint32_t aBrightness) } } +class nsScreenManagerAndroid::ScreenManagerHelperSupport final + : public ScreenManagerHelper::Natives +{ +public: + typedef ScreenManagerHelper::Natives Base; + + static int32_t AddDisplay(int32_t aDisplayType, int32_t aWidth, int32_t aHeight, float aDensity) { + int32_t screenId = -1; // return value + nsCOMPtr mainThread = do_GetMainThread(); + SyncRunnable::DispatchToThread(mainThread, NS_NewRunnableFunction( + [&aDisplayType, &aWidth, &aHeight, &aDensity, &screenId] { + MOZ_ASSERT(NS_IsMainThread()); + nsCOMPtr screenMgr = + do_GetService("@mozilla.org/gfx/screenmanager;1"); + MOZ_ASSERT(screenMgr, "Failed to get nsIScreenManager"); + + RefPtr screenMgrAndroid = + (nsScreenManagerAndroid*) screenMgr.get(); + RefPtr screen = + screenMgrAndroid->AddScreen(static_cast(aDisplayType), + nsIntRect(0, 0, aWidth, aHeight)); + MOZ_ASSERT(screen); + screen->SetDensity(aDensity); + screenId = static_cast(screen->GetId()); + }).take()); + return screenId; + } + + static void RemoveDisplay(int32_t aScreenId) { + nsCOMPtr mainThread = do_GetMainThread(); + SyncRunnable::DispatchToThread(mainThread, NS_NewRunnableFunction( + [&aScreenId] { + MOZ_ASSERT(NS_IsMainThread()); + nsCOMPtr screenMgr = + do_GetService("@mozilla.org/gfx/screenmanager;1"); + MOZ_ASSERT(screenMgr, "Failed to get nsIScreenManager"); + + RefPtr screenMgrAndroid = + (nsScreenManagerAndroid*) screenMgr.get(); + screenMgrAndroid->RemoveScreen(aScreenId); + }).take()); + } +}; + NS_IMPL_ISUPPORTS(nsScreenManagerAndroid, nsIScreenManager) nsScreenManagerAndroid::nsScreenManagerAndroid() { + if (mozilla::jni::IsAvailable()) { + ScreenManagerHelperSupport::Base::Init(); + } nsCOMPtr screen = AddScreen(DisplayType::DISPLAY_PRIMARY); MOZ_ASSERT(screen); } diff --git a/widget/android/nsScreenManagerAndroid.h b/widget/android/nsScreenManagerAndroid.h index 91c1c6c9ce09..cf8bfb245f60 100644 --- a/widget/android/nsScreenManagerAndroid.h +++ b/widget/android/nsScreenManagerAndroid.h @@ -48,6 +48,8 @@ private: ~nsScreenManagerAndroid(); public: + class ScreenManagerHelperSupport; + nsScreenManagerAndroid(); NS_DECL_ISUPPORTS