diff --git a/widget/gonk/nsScreenManagerGonk.h b/widget/gonk/nsScreenManagerGonk.h index 2a7e30e9eaff..9558a168a4f2 100644 --- a/widget/gonk/nsScreenManagerGonk.h +++ b/widget/gonk/nsScreenManagerGonk.h @@ -31,7 +31,8 @@ class nsScreenGonk : public nsBaseScreen typedef mozilla::hal::ScreenConfiguration ScreenConfiguration; public: - nsScreenGonk(); + nsScreenGonk(uint32_t aId, ANativeWindow* aNativeWindow); + ~nsScreenGonk(); NS_IMETHOD GetId(uint32_t* aId); @@ -42,9 +43,14 @@ class nsScreenGonk : public nsBaseScreen NS_IMETHOD GetRotation(uint32_t* aRotation); NS_IMETHOD SetRotation(uint32_t aRotation); + uint32_t GetId(); + nsIntRect GetRect(); + float GetDpi(); + ANativeWindow* GetNativeWindow(); nsIntRect GetNaturalBounds(); uint32_t EffectiveScreenRotation(); ScreenConfiguration GetConfiguration(); + bool IsPrimaryScreen(); void RegisterWindow(nsWindow* aWindow); void UnregisterWindow(nsWindow* aWindow); @@ -56,8 +62,12 @@ class nsScreenGonk : public nsBaseScreen } protected: - nsIntRect mScreenBounds; - nsIntRect mVirtualBounds; + uint32_t mId; + int32_t mColorDepth; + android::sp mNativeWindow; + float mDpi; + nsIntRect mNaturalBounds; // Screen bounds w/o rotation taken into account. + nsIntRect mVirtualBounds; // Screen bounds w/ rotation taken into account. uint32_t mScreenRotation; uint32_t mPhysicalScreenRotation; nsTArray mTopWindows; @@ -65,6 +75,15 @@ class nsScreenGonk : public nsBaseScreen class nsScreenManagerGonk final : public nsIScreenManager { +public: + enum { + // TODO: Bug 1138287 will define more screen/display types. + PRIMARY_SCREEN_TYPE = 0, + + // TODO: Maintain a mapping from type to id dynamically. + PRIMARY_SCREEN_ID = 0, + }; + public: nsScreenManagerGonk(); @@ -77,12 +96,16 @@ class nsScreenManagerGonk final : public nsIScreenManager void Initialize(); void DisplayEnabled(bool aEnabled); + void AddScreen(uint32_t aDisplayType); + void RemoveScreen(uint32_t aDisplayType); + protected: ~nsScreenManagerGonk(); void VsyncControl(bool aEnabled); + uint32_t GetIdFromType(uint32_t aDisplayType); bool mInitialized; - nsCOMPtr mOneScreen; + nsTArray> mScreens; nsRefPtr mScreenOnEvent; nsRefPtr mScreenOffEvent; }; diff --git a/widget/gonk/nsWindow.cpp b/widget/gonk/nsWindow.cpp index 95b40c574330..db3c17b2d629 100644 --- a/widget/gonk/nsWindow.cpp +++ b/widget/gonk/nsWindow.cpp @@ -134,7 +134,6 @@ nsWindow::nsWindow() nsRefPtr screenManager = nsScreenManagerGonk::GetInstance(); screenManager->Initialize(); - mScreen = nsScreenManagerGonk::GetPrimaryScreen(); // This is a hack to force initialization of the compositor // resources, if we're going to use omtc. @@ -150,7 +149,9 @@ nsWindow::nsWindow() nsWindow::~nsWindow() { - HwcComposer2D::GetInstance()->SetCompositorParent(nullptr); + if (mScreen->IsPrimaryScreen()) { + HwcComposer2D::GetInstance()->SetCompositorParent(nullptr); + } } void @@ -397,11 +398,17 @@ nsWindow::Create(nsIWidget *aParent, const nsIntRect &aRect, nsWidgetInitData *aInitData) { - nsIntRect virtualBounds; - mScreen->GetRect(&virtualBounds.x, &virtualBounds.y, - &virtualBounds.width, &virtualBounds.height); - BaseCreate(aParent, IS_TOPLEVEL() ? virtualBounds : aRect, - aInitData); + BaseCreate(aParent, aRect, aInitData); + + nsCOMPtr screen; + + uint32_t screenId = aParent ? ((nsWindow*)aParent)->mScreen->GetId() : + aInitData->mScreenId; + + nsRefPtr screenManager = nsScreenManagerGonk::GetInstance(); + screenManager->ScreenForId(screenId, getter_AddRefs(screen)); + + mScreen = static_cast(screen.get()); mBounds = aRect; @@ -409,7 +416,7 @@ nsWindow::Create(nsIWidget *aParent, mVisible = false; if (!aParent) { - mBounds = virtualBounds; + mBounds = mScreen->GetRect(); } if (!IS_TOPLEVEL()) { @@ -418,7 +425,8 @@ nsWindow::Create(nsIWidget *aParent, mScreen->RegisterWindow(this); - Resize(0, 0, virtualBounds.width, virtualBounds.height, false); + Resize(0, 0, mBounds.width, mBounds.height, false); + return NS_OK; } @@ -511,10 +519,7 @@ nsWindow::Resize(double aX, } if (aRepaint) { - nsIntRect virtualBounds; - mScreen->GetRect(&virtualBounds.x, &virtualBounds.y, - &virtualBounds.width, &virtualBounds.height); - Invalidate(virtualBounds); + Invalidate(mBounds); } return NS_OK; @@ -538,7 +543,12 @@ nsWindow::SetFocus(bool aRaise) if (aRaise) { BringToTop(); } - gFocusedWindow = this; + + if (!IS_TOPLEVEL() && mScreen->IsPrimaryScreen()) { + // We should only set focused window on non-toplevel primary window. + gFocusedWindow = this; + } + return NS_OK; } @@ -587,7 +597,7 @@ nsWindow::GetNativeData(uint32_t aDataType) switch (aDataType) { case NS_NATIVE_WINDOW: // Called before primary display's EGLSurface creation. - return GetGonkDisplay()->GetNativeWindow(); + return mScreen->GetNativeWindow(); } return nullptr; } @@ -748,7 +758,7 @@ nsWindow::EndRemoteDrawing() float nsWindow::GetDPI() { - return GetGonkDisplay()->xdpi; + return mScreen->GetDpi(); } double @@ -803,7 +813,7 @@ nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager, } CreateCompositor(); - if (mCompositorParent) { + if (mCompositorParent && mScreen->IsPrimaryScreen()) { HwcComposer2D::GetInstance()->SetCompositorParent(mCompositorParent); } MOZ_ASSERT(mLayerManager); @@ -826,10 +836,7 @@ nsWindow::BringToTop() mWidgetListener->WindowActivated(); } - nsIntRect virtualBounds; - mScreen->GetRect(&virtualBounds.x, &virtualBounds.y, - &virtualBounds.width, &virtualBounds.height); - Invalidate(virtualBounds); + Invalidate(mBounds); } void @@ -874,42 +881,75 @@ nsWindow::NeedsPaint() Composer2D* nsWindow::GetComposer2D() { + if (!mScreen->IsPrimaryScreen()) { + return nullptr; + } + return HwcComposer2D::GetInstance(); } +static uint32_t +SurfaceFormatToColorDepth(int32_t aSurfaceFormat) +{ + switch (aSurfaceFormat) { + case GGL_PIXEL_FORMAT_RGB_565: + return 16; + case GGL_PIXEL_FORMAT_RGBA_8888: + return 32; + } + return 24; // GGL_PIXEL_FORMAT_RGBX_8888 +} + // nsScreenGonk.cpp -nsScreenGonk::nsScreenGonk() - : mScreenRotation(nsIScreen::ROTATION_0_DEG) +nsScreenGonk::nsScreenGonk(uint32_t aId, ANativeWindow* aNativeWindow) + : mId(aId) + , mNativeWindow(aNativeWindow) + , mScreenRotation(nsIScreen::ROTATION_0_DEG) , mPhysicalScreenRotation(nsIScreen::ROTATION_0_DEG) { - nsIntSize screenSize; - - ANativeWindow *win = GetGonkDisplay()->GetNativeWindow(); - if (win->query(win, NATIVE_WINDOW_WIDTH, &screenSize.width) || - win->query(win, NATIVE_WINDOW_HEIGHT, &screenSize.height)) { + int surfaceFormat; + if (mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_WIDTH, &mVirtualBounds.width) || + mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_HEIGHT, &mVirtualBounds.height) || + mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_FORMAT, &surfaceFormat)) { NS_RUNTIMEABORT("Failed to get native window size, aborting..."); } - mScreenBounds = gfx::IntRect(gfx::IntPoint(0, 0), screenSize); - char propValue[PROPERTY_VALUE_MAX]; - property_get("ro.sf.hwrotation", propValue, "0"); - mPhysicalScreenRotation = atoi(propValue) / 90; + mNaturalBounds = mVirtualBounds; + + if (IsPrimaryScreen()) { + char propValue[PROPERTY_VALUE_MAX]; + property_get("ro.sf.hwrotation", propValue, "0"); + mPhysicalScreenRotation = atoi(propValue) / 90; + } - mVirtualBounds = mScreenBounds; + mDpi = GetGonkDisplay()->xdpi; + mColorDepth = SurfaceFormatToColorDepth(surfaceFormat); } nsScreenGonk::~nsScreenGonk() { } +bool +nsScreenGonk::IsPrimaryScreen() +{ + return nsScreenManagerGonk::PRIMARY_SCREEN_ID == mId; +} + NS_IMETHODIMP nsScreenGonk::GetId(uint32_t *outId) { - *outId = 1; + *outId = mId; return NS_OK; } +uint32_t +nsScreenGonk::GetId() +{ + return mId; +} + NS_IMETHODIMP nsScreenGonk::GetRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight) @@ -923,6 +963,12 @@ nsScreenGonk::GetRect(int32_t *outLeft, int32_t *outTop, return NS_OK; } +nsIntRect +nsScreenGonk::GetRect() +{ + return mVirtualBounds; +} + NS_IMETHODIMP nsScreenGonk::GetAvailRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight) @@ -930,31 +976,20 @@ nsScreenGonk::GetAvailRect(int32_t *outLeft, int32_t *outTop, return GetRect(outLeft, outTop, outWidth, outHeight); } -static uint32_t -ColorDepth() -{ - switch (GetGonkDisplay()->surfaceformat) { - case GGL_PIXEL_FORMAT_RGB_565: - return 16; - case GGL_PIXEL_FORMAT_RGBA_8888: - return 32; - } - return 24; // GGL_PIXEL_FORMAT_RGBX_8888 -} - NS_IMETHODIMP nsScreenGonk::GetPixelDepth(int32_t *aPixelDepth) { // XXX: this should actually return 32 when we're using 24-bit // color, because we use RGBX. - *aPixelDepth = ColorDepth(); + *aPixelDepth = mColorDepth; return NS_OK; } NS_IMETHODIMP nsScreenGonk::GetColorDepth(int32_t *aColorDepth) { - return GetPixelDepth(aColorDepth); + *aColorDepth = mColorDepth; + return NS_OK; } NS_IMETHODIMP @@ -964,6 +999,18 @@ nsScreenGonk::GetRotation(uint32_t* aRotation) return NS_OK; } +float +nsScreenGonk::GetDpi() +{ + return mDpi; +} + +ANativeWindow* +nsScreenGonk::GetNativeWindow() +{ + return mNativeWindow.get(); +} + NS_IMETHODIMP nsScreenGonk::SetRotation(uint32_t aRotation) { @@ -980,10 +1027,10 @@ nsScreenGonk::SetRotation(uint32_t aRotation) if (rotation == nsIScreen::ROTATION_90_DEG || rotation == nsIScreen::ROTATION_270_DEG) { mVirtualBounds = nsIntRect(0, 0, - mScreenBounds.height, - mScreenBounds.width); + mNaturalBounds.height, + mNaturalBounds.width); } else { - mVirtualBounds = mScreenBounds; + mVirtualBounds = mNaturalBounds; } nsAppShell::NotifyScreenRotation(); @@ -1000,7 +1047,7 @@ nsScreenGonk::SetRotation(uint32_t aRotation) nsIntRect nsScreenGonk::GetNaturalBounds() { - return mScreenBounds; + return mNaturalBounds; } uint32_t @@ -1039,12 +1086,12 @@ ScreenConfiguration nsScreenGonk::GetConfiguration() { ScreenOrientation orientation = ComputeOrientation(mScreenRotation, - mScreenBounds.Size()); - uint32_t colorDepth = ColorDepth(); + mNaturalBounds.Size()); + // NB: perpetuating colorDepth == pixelDepth illusion here, for // consistency. return ScreenConfiguration(mVirtualBounds, orientation, - colorDepth, colorDepth); + mColorDepth, mColorDepth); } void @@ -1071,7 +1118,6 @@ NS_IMPL_ISUPPORTS(nsScreenManagerGonk, nsIScreenManager) nsScreenManagerGonk::nsScreenManagerGonk() : mInitialized(false) { - mOneScreen = new nsScreenGonk(); } nsScreenManagerGonk::~nsScreenManagerGonk() @@ -1110,6 +1156,8 @@ nsScreenManagerGonk::Initialize() mScreenOffEvent = new ScreenOnOffEvent(false); GetGonkDisplay()->OnEnabled(displayEnabledCallback); + AddScreen(PRIMARY_SCREEN_TYPE); + nsAppShell::NotifyScreenInitialized(); mInitialized = true; } @@ -1127,7 +1175,7 @@ nsScreenManagerGonk::DisplayEnabled(bool aEnabled) NS_IMETHODIMP nsScreenManagerGonk::GetPrimaryScreen(nsIScreen **outScreen) { - NS_IF_ADDREF(*outScreen = mOneScreen.get()); + NS_IF_ADDREF(*outScreen = mScreens[0].get()); return NS_OK; } @@ -1135,7 +1183,15 @@ NS_IMETHODIMP nsScreenManagerGonk::ScreenForId(uint32_t aId, nsIScreen **outScreen) { - return GetPrimaryScreen(outScreen); + for (size_t i = 0; i < mScreens.Length(); i++) { + if (mScreens[i]->GetId() == aId) { + NS_IF_ADDREF(*outScreen = mScreens[i].get()); + return NS_OK; + } + } + + *outScreen = nullptr; + return NS_OK; } NS_IMETHODIMP @@ -1145,19 +1201,29 @@ nsScreenManagerGonk::ScreenForRect(int32_t inLeft, int32_t inHeight, nsIScreen **outScreen) { + // Since all screens have independent coordinate system, we could + // only return the primary screen no matter what rect is given. return GetPrimaryScreen(outScreen); } NS_IMETHODIMP nsScreenManagerGonk::ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen) { - return GetPrimaryScreen(outScreen); + for (size_t i = 0; i < mScreens.Length(); i++) { + if (aWidget == mScreens[i]->GetNativeWindow()) { + NS_IF_ADDREF(*outScreen = mScreens[i].get()); + return NS_OK; + } + } + + *outScreen = nullptr; + return NS_OK; } NS_IMETHODIMP nsScreenManagerGonk::GetNumberOfScreens(uint32_t *aNumberOfScreens) { - *aNumberOfScreens = 1; + *aNumberOfScreens = mScreens.Length(); return NS_OK; } @@ -1189,3 +1255,39 @@ nsScreenManagerGonk::VsyncControl(bool aEnabled) display.DisableVsync(); } } + +uint32_t +nsScreenManagerGonk::GetIdFromType(uint32_t aDisplayType) +{ + // This is the only place where we make the assumption that + // display type is equivalent to screen id. + + // Bug 1138287 will address the conversion from type to id. + return aDisplayType; +} + +void +nsScreenManagerGonk::AddScreen(uint32_t aDisplayType) +{ + // We currently only support adding primary screen. + MOZ_ASSERT(PRIMARY_SCREEN_TYPE == aDisplayType); + + uint32_t id = GetIdFromType(aDisplayType); + + ANativeWindow* win = GetGonkDisplay()->GetNativeWindow(); + nsScreenGonk* screen = new nsScreenGonk(id, win); + + mScreens.AppendElement(screen); +} + +void +nsScreenManagerGonk::RemoveScreen(uint32_t aDisplayType) +{ + uint32_t screenId = GetIdFromType(aDisplayType); + for (size_t i = 0; i < mScreens.Length(); i++) { + if (mScreens[i]->GetId() == screenId) { + mScreens.RemoveElementAt(i); + break; + } + } +}