mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 01:48:05 +00:00
f478d39678
This is where the magic starts to happen. We move includes from the base protocol header (${NAME}.h) to the parent and child headers (${NAME}Parent.h and ${NAME}Child.h) to follow good include hygiene. For the base protocol header, we examine the set of types used by struct and union definitions to determine which headers we need to include. For parent and child headers, we forward declare what we can and include appropriate headers otherwise. For forward-declared types, we include the appropriate headers in the parent and child source files.
899 lines
24 KiB
C++
899 lines
24 KiB
C++
/* Copyright 2012 Mozilla Foundation and Mozilla contributors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "mozilla/DebugOnly.h"
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include "android/log.h"
|
|
|
|
#include "mozilla/dom/TabParent.h"
|
|
#include "mozilla/Hal.h"
|
|
#include "mozilla/Preferences.h"
|
|
#include "mozilla/FileUtils.h"
|
|
#include "mozilla/ClearOnShutdown.h"
|
|
#include "Framebuffer.h"
|
|
#include "gfxContext.h"
|
|
#include "gfxPlatform.h"
|
|
#include "gfxUtils.h"
|
|
#include "GLContextProvider.h"
|
|
#include "GLContext.h"
|
|
#include "LayerManagerOGL.h"
|
|
#include "nsAutoPtr.h"
|
|
#include "nsAppShell.h"
|
|
#include "nsIdleService.h"
|
|
#include "nsScreenManagerGonk.h"
|
|
#include "nsTArray.h"
|
|
#include "nsWindow.h"
|
|
#include "nsIWidgetListener.h"
|
|
#include "cutils/properties.h"
|
|
#include "ClientLayerManager.h"
|
|
#include "BasicLayers.h"
|
|
#include "libdisplay/GonkDisplay.h"
|
|
#include "pixelflinger/format.h"
|
|
#include "mozilla/BasicEvents.h"
|
|
|
|
#include "HwcComposer2D.h"
|
|
|
|
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
|
|
#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "Gonk", ## args)
|
|
#define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "Gonk", ## args)
|
|
|
|
#define IS_TOPLEVEL() (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog)
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::dom;
|
|
using namespace mozilla::hal;
|
|
using namespace mozilla::gl;
|
|
using namespace mozilla::layers;
|
|
using namespace mozilla::widget;
|
|
|
|
nsIntRect gScreenBounds;
|
|
static uint32_t sScreenRotation;
|
|
static uint32_t sPhysicalScreenRotation;
|
|
static nsIntRect sVirtualBounds;
|
|
static gfxMatrix sRotationMatrix;
|
|
|
|
static nsRefPtr<GLContext> sGLContext;
|
|
static nsTArray<nsWindow *> sTopWindows;
|
|
static nsWindow *gWindowToRedraw = nullptr;
|
|
static nsWindow *gFocusedWindow = nullptr;
|
|
static bool sFramebufferOpen;
|
|
static bool sUsingOMTC;
|
|
static bool sUsingHwc;
|
|
static bool sScreenInitialized;
|
|
static nsRefPtr<gfxASurface> sOMTCSurface;
|
|
|
|
namespace {
|
|
|
|
static uint32_t
|
|
EffectiveScreenRotation()
|
|
{
|
|
return (sScreenRotation + sPhysicalScreenRotation) % (360 / 90);
|
|
}
|
|
|
|
class ScreenOnOffEvent : public nsRunnable {
|
|
public:
|
|
ScreenOnOffEvent(bool on)
|
|
: mIsOn(on)
|
|
{}
|
|
|
|
NS_IMETHOD Run() {
|
|
for (uint32_t i = 0; i < sTopWindows.Length(); i++) {
|
|
nsWindow *win = sTopWindows[i];
|
|
|
|
if (nsIWidgetListener* listener = win->GetWidgetListener()) {
|
|
listener->SizeModeChanged(mIsOn ? nsSizeMode_Fullscreen : nsSizeMode_Minimized);
|
|
}
|
|
}
|
|
|
|
// Notify observers that the screen state has just changed.
|
|
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
|
|
if (observerService) {
|
|
observerService->NotifyObservers(
|
|
nullptr, "screen-state-changed",
|
|
mIsOn ? NS_LITERAL_STRING("on").get() : NS_LITERAL_STRING("off").get()
|
|
);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
private:
|
|
bool mIsOn;
|
|
};
|
|
|
|
static StaticRefPtr<ScreenOnOffEvent> sScreenOnEvent;
|
|
static StaticRefPtr<ScreenOnOffEvent> sScreenOffEvent;
|
|
|
|
static void
|
|
displayEnabledCallback(bool enabled)
|
|
{
|
|
NS_DispatchToMainThread(enabled ? sScreenOnEvent : sScreenOffEvent);
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
nsWindow::nsWindow()
|
|
{
|
|
if (!sScreenInitialized) {
|
|
sScreenOnEvent = new ScreenOnOffEvent(true);
|
|
ClearOnShutdown(&sScreenOnEvent);
|
|
sScreenOffEvent = new ScreenOnOffEvent(false);
|
|
ClearOnShutdown(&sScreenOffEvent);
|
|
GetGonkDisplay()->OnEnabled(displayEnabledCallback);
|
|
|
|
nsIntSize screenSize;
|
|
bool gotFB = Framebuffer::GetSize(&screenSize);
|
|
if (!gotFB) {
|
|
NS_RUNTIMEABORT("Failed to get size from framebuffer, aborting...");
|
|
}
|
|
gScreenBounds = nsIntRect(nsIntPoint(0, 0), screenSize);
|
|
|
|
char propValue[PROPERTY_VALUE_MAX];
|
|
property_get("ro.sf.hwrotation", propValue, "0");
|
|
sPhysicalScreenRotation = atoi(propValue) / 90;
|
|
|
|
// Unlike nsScreenGonk::SetRotation(), only support 0 and 180 as there
|
|
// are no known screens that are mounted at 90 or 270 at the moment.
|
|
switch (sPhysicalScreenRotation) {
|
|
case nsIScreen::ROTATION_0_DEG:
|
|
break;
|
|
case nsIScreen::ROTATION_180_DEG:
|
|
sRotationMatrix.Translate(gfxPoint(gScreenBounds.width,
|
|
gScreenBounds.height));
|
|
sRotationMatrix.Rotate(M_PI);
|
|
break;
|
|
default:
|
|
MOZ_CRASH("Unknown rotation");
|
|
}
|
|
sVirtualBounds = gScreenBounds;
|
|
|
|
sScreenInitialized = true;
|
|
|
|
nsAppShell::NotifyScreenInitialized();
|
|
|
|
// This is a hack to force initialization of the compositor
|
|
// resources, if we're going to use omtc.
|
|
//
|
|
// NB: GetPlatform() will create the gfxPlatform, which wants
|
|
// to know the color depth, which asks our native window.
|
|
// This has to happen after other init has finished.
|
|
gfxPlatform::GetPlatform();
|
|
sUsingOMTC = ShouldUseOffMainThreadCompositing();
|
|
|
|
property_get("ro.display.colorfill", propValue, "0");
|
|
sUsingHwc = Preferences::GetBool("layers.composer2d.enabled",
|
|
atoi(propValue) == 1);
|
|
|
|
if (sUsingOMTC) {
|
|
sOMTCSurface = new gfxImageSurface(gfxIntSize(1, 1),
|
|
gfxImageFormatRGB24);
|
|
}
|
|
}
|
|
}
|
|
|
|
nsWindow::~nsWindow()
|
|
{
|
|
}
|
|
|
|
void
|
|
nsWindow::DoDraw(void)
|
|
{
|
|
if (!hal::GetScreenEnabled()) {
|
|
gDrawRequest = true;
|
|
return;
|
|
}
|
|
|
|
if (!gWindowToRedraw) {
|
|
LOG(" no window to draw, bailing");
|
|
return;
|
|
}
|
|
|
|
nsIntRegion region = gWindowToRedraw->mDirtyRegion;
|
|
gWindowToRedraw->mDirtyRegion.SetEmpty();
|
|
|
|
nsIWidgetListener* listener = gWindowToRedraw->GetWidgetListener();
|
|
if (listener) {
|
|
listener->WillPaintWindow(gWindowToRedraw);
|
|
}
|
|
|
|
LayerManager* lm = gWindowToRedraw->GetLayerManager();
|
|
if (mozilla::layers::LAYERS_OPENGL == lm->GetBackendType()) {
|
|
LayerManagerOGL* oglm = static_cast<LayerManagerOGL*>(lm);
|
|
oglm->SetClippingRegion(region);
|
|
oglm->SetWorldTransform(sRotationMatrix);
|
|
|
|
listener = gWindowToRedraw->GetWidgetListener();
|
|
if (listener) {
|
|
listener->PaintWindow(gWindowToRedraw, region);
|
|
}
|
|
} else if (mozilla::layers::LAYERS_CLIENT == lm->GetBackendType()) {
|
|
// No need to do anything, the compositor will handle drawing
|
|
} else if (mozilla::layers::LAYERS_BASIC == lm->GetBackendType()) {
|
|
MOZ_ASSERT(sFramebufferOpen || sUsingOMTC);
|
|
nsRefPtr<gfxASurface> targetSurface;
|
|
|
|
if(sUsingOMTC)
|
|
targetSurface = sOMTCSurface;
|
|
else
|
|
targetSurface = Framebuffer::BackBuffer();
|
|
|
|
{
|
|
nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
|
|
gfxUtils::PathFromRegion(ctx, region);
|
|
ctx->Clip();
|
|
|
|
// No double-buffering needed.
|
|
AutoLayerManagerSetup setupLayerManager(
|
|
gWindowToRedraw, ctx, mozilla::layers::BUFFER_NONE,
|
|
ScreenRotation(EffectiveScreenRotation()));
|
|
|
|
listener = gWindowToRedraw->GetWidgetListener();
|
|
if (listener) {
|
|
listener->PaintWindow(gWindowToRedraw, region);
|
|
}
|
|
}
|
|
|
|
if (!sUsingOMTC) {
|
|
targetSurface->Flush();
|
|
Framebuffer::Present(region);
|
|
}
|
|
} else {
|
|
NS_RUNTIMEABORT("Unexpected layer manager type");
|
|
}
|
|
|
|
listener = gWindowToRedraw->GetWidgetListener();
|
|
if (listener) {
|
|
listener->DidPaintWindow();
|
|
}
|
|
}
|
|
|
|
nsEventStatus
|
|
nsWindow::DispatchInputEvent(WidgetGUIEvent& aEvent, bool* aWasCaptured)
|
|
{
|
|
if (aWasCaptured) {
|
|
*aWasCaptured = false;
|
|
}
|
|
if (!gFocusedWindow) {
|
|
return nsEventStatus_eIgnore;
|
|
}
|
|
|
|
gFocusedWindow->UserActivity();
|
|
|
|
aEvent.widget = gFocusedWindow;
|
|
|
|
if (TabParent* capturer = TabParent::GetEventCapturer()) {
|
|
bool captured = capturer->TryCapture(aEvent);
|
|
if (aWasCaptured) {
|
|
*aWasCaptured = captured;
|
|
}
|
|
if (captured) {
|
|
return nsEventStatus_eConsumeNoDefault;
|
|
}
|
|
}
|
|
|
|
nsEventStatus status;
|
|
gFocusedWindow->DispatchEvent(&aEvent, status);
|
|
return status;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::Create(nsIWidget *aParent,
|
|
void *aNativeParent,
|
|
const nsIntRect &aRect,
|
|
nsDeviceContext *aContext,
|
|
nsWidgetInitData *aInitData)
|
|
{
|
|
BaseCreate(aParent, IS_TOPLEVEL() ? sVirtualBounds : aRect,
|
|
aContext, aInitData);
|
|
|
|
mBounds = aRect;
|
|
|
|
nsWindow *parent = (nsWindow *)aNativeParent;
|
|
mParent = parent;
|
|
mVisible = false;
|
|
|
|
if (!aNativeParent) {
|
|
mBounds = sVirtualBounds;
|
|
}
|
|
|
|
if (!IS_TOPLEVEL())
|
|
return NS_OK;
|
|
|
|
sTopWindows.AppendElement(this);
|
|
|
|
Resize(0, 0, sVirtualBounds.width, sVirtualBounds.height, false);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::Destroy(void)
|
|
{
|
|
sTopWindows.RemoveElement(this);
|
|
if (this == gWindowToRedraw)
|
|
gWindowToRedraw = nullptr;
|
|
if (this == gFocusedWindow)
|
|
gFocusedWindow = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::Show(bool aState)
|
|
{
|
|
if (mWindowType == eWindowType_invisible)
|
|
return NS_OK;
|
|
|
|
if (mVisible == aState)
|
|
return NS_OK;
|
|
|
|
mVisible = aState;
|
|
if (!IS_TOPLEVEL())
|
|
return mParent ? mParent->Show(aState) : NS_OK;
|
|
|
|
if (aState) {
|
|
BringToTop();
|
|
} else {
|
|
for (unsigned int i = 0; i < sTopWindows.Length(); i++) {
|
|
nsWindow *win = sTopWindows[i];
|
|
if (!win->mVisible)
|
|
continue;
|
|
|
|
win->BringToTop();
|
|
break;
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
bool
|
|
nsWindow::IsVisible() const
|
|
{
|
|
return mVisible;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::ConstrainPosition(bool aAllowSlop,
|
|
int32_t *aX,
|
|
int32_t *aY)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::Move(double aX,
|
|
double aY)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::Resize(double aWidth,
|
|
double aHeight,
|
|
bool aRepaint)
|
|
{
|
|
return Resize(0, 0, aWidth, aHeight, aRepaint);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::Resize(double aX,
|
|
double aY,
|
|
double aWidth,
|
|
double aHeight,
|
|
bool aRepaint)
|
|
{
|
|
mBounds = nsIntRect(NSToIntRound(aX), NSToIntRound(aY),
|
|
NSToIntRound(aWidth), NSToIntRound(aHeight));
|
|
if (mWidgetListener)
|
|
mWidgetListener->WindowResized(this, mBounds.width, mBounds.height);
|
|
|
|
if (aRepaint && gWindowToRedraw)
|
|
gWindowToRedraw->Invalidate(sVirtualBounds);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::Enable(bool aState)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
bool
|
|
nsWindow::IsEnabled() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::SetFocus(bool aRaise)
|
|
{
|
|
if (aRaise)
|
|
BringToTop();
|
|
|
|
gFocusedWindow = this;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::ConfigureChildren(const nsTArray<nsIWidget::Configuration>&)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::Invalidate(const nsIntRect &aRect)
|
|
{
|
|
nsWindow *parent = mParent;
|
|
while (parent && parent != sTopWindows[0])
|
|
parent = parent->mParent;
|
|
if (parent != sTopWindows[0])
|
|
return NS_OK;
|
|
|
|
mDirtyRegion.Or(mDirtyRegion, aRect);
|
|
gWindowToRedraw = this;
|
|
gDrawRequest = true;
|
|
mozilla::NotifyEvent();
|
|
return NS_OK;
|
|
}
|
|
|
|
nsIntPoint
|
|
nsWindow::WidgetToScreenOffset()
|
|
{
|
|
nsIntPoint p(0, 0);
|
|
nsWindow *w = this;
|
|
|
|
while (w && w->mParent) {
|
|
p.x += w->mBounds.x;
|
|
p.y += w->mBounds.y;
|
|
|
|
w = w->mParent;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
void*
|
|
nsWindow::GetNativeData(uint32_t aDataType)
|
|
{
|
|
switch (aDataType) {
|
|
case NS_NATIVE_WINDOW:
|
|
return GetGonkDisplay()->GetNativeWindow();
|
|
case NS_NATIVE_WIDGET:
|
|
return this;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus)
|
|
{
|
|
if (mWidgetListener)
|
|
aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP_(void)
|
|
nsWindow::SetInputContext(const InputContext& aContext,
|
|
const InputContextAction& aAction)
|
|
{
|
|
mInputContext = aContext;
|
|
}
|
|
|
|
NS_IMETHODIMP_(InputContext)
|
|
nsWindow::GetInputContext()
|
|
{
|
|
// There is only one IME context on Gonk.
|
|
mInputContext.mNativeIMEContext = nullptr;
|
|
return mInputContext;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::ReparentNativeWidget(nsIWidget* aNewParent)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindow::MakeFullScreen(bool aFullScreen)
|
|
{
|
|
if (mWindowType != eWindowType_toplevel) {
|
|
// Ignore fullscreen request for non-toplevel windows.
|
|
NS_WARNING("MakeFullScreen() on a dialog or child widget?");
|
|
return nsBaseWidget::MakeFullScreen(aFullScreen);
|
|
}
|
|
|
|
if (aFullScreen) {
|
|
// Fullscreen is "sticky" for toplevel widgets on gonk: we
|
|
// must paint the entire screen, and should only have one
|
|
// toplevel widget, so it doesn't make sense to ever "exit"
|
|
// fullscreen. If we do, we can leave parts of the screen
|
|
// unpainted.
|
|
Resize(sVirtualBounds.x, sVirtualBounds.y,
|
|
sVirtualBounds.width, sVirtualBounds.height,
|
|
/*repaint*/true);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
float
|
|
nsWindow::GetDPI()
|
|
{
|
|
return GetGonkDisplay()->xdpi;
|
|
}
|
|
|
|
double
|
|
nsWindow::GetDefaultScaleInternal()
|
|
{
|
|
float dpi = GetDPI();
|
|
// The mean pixel density for mdpi devices is 160dpi, 240dpi for hdpi,
|
|
// and 320dpi for xhdpi, respectively.
|
|
// We'll take the mid-value between these three numbers as the boundary.
|
|
if (dpi < 200.0) {
|
|
return 1.0; // mdpi devices.
|
|
}
|
|
if (dpi < 280.0) {
|
|
return 1.5; // hdpi devices.
|
|
}
|
|
return 2.0; // xhdpi devices.
|
|
}
|
|
|
|
LayerManager *
|
|
nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
|
|
LayersBackend aBackendHint,
|
|
LayerManagerPersistence aPersistence,
|
|
bool* aAllowRetaining)
|
|
{
|
|
if (aAllowRetaining)
|
|
*aAllowRetaining = true;
|
|
if (mLayerManager) {
|
|
// This layer manager might be used for painting outside of DoDraw(), so we need
|
|
// to set the correct rotation on it.
|
|
if (mLayerManager->GetBackendType() == LAYERS_BASIC) {
|
|
BasicLayerManager* manager =
|
|
static_cast<BasicLayerManager*>(mLayerManager.get());
|
|
manager->SetDefaultTargetConfiguration(mozilla::layers::BUFFER_NONE,
|
|
ScreenRotation(EffectiveScreenRotation()));
|
|
} else if (mLayerManager->GetBackendType() == LAYERS_CLIENT) {
|
|
ClientLayerManager* manager =
|
|
static_cast<ClientLayerManager*>(mLayerManager.get());
|
|
manager->SetDefaultTargetConfiguration(mozilla::layers::BUFFER_NONE,
|
|
ScreenRotation(EffectiveScreenRotation()));
|
|
}
|
|
return mLayerManager;
|
|
}
|
|
|
|
// Set mUseLayersAcceleration here to make it consistent with
|
|
// nsBaseWidget::GetLayerManager
|
|
mUseLayersAcceleration = ComputeShouldAccelerate(mUseLayersAcceleration);
|
|
nsWindow *topWindow = sTopWindows[0];
|
|
|
|
if (!topWindow) {
|
|
LOGW(" -- no topwindow\n");
|
|
return nullptr;
|
|
}
|
|
|
|
if (sUsingOMTC) {
|
|
CreateCompositor();
|
|
if (mLayerManager)
|
|
return mLayerManager;
|
|
}
|
|
|
|
if (mUseLayersAcceleration) {
|
|
DebugOnly<nsIntRect> fbBounds = gScreenBounds;
|
|
if (!sGLContext) {
|
|
sGLContext = GLContextProvider::CreateForWindow(this);
|
|
}
|
|
|
|
MOZ_ASSERT(fbBounds.value == gScreenBounds);
|
|
if (sGLContext) {
|
|
nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(this);
|
|
|
|
if (layerManager->Initialize(sGLContext)) {
|
|
mLayerManager = layerManager;
|
|
return mLayerManager;
|
|
} else {
|
|
LOGW("Could not create OGL LayerManager");
|
|
}
|
|
} else {
|
|
LOGW("GL context was not created");
|
|
}
|
|
}
|
|
|
|
// Fall back to software rendering.
|
|
sFramebufferOpen = Framebuffer::Open();
|
|
if (sFramebufferOpen) {
|
|
LOG("Falling back to framebuffer software rendering");
|
|
} else {
|
|
LOGE("Failed to mmap fb(?!?), aborting ...");
|
|
NS_RUNTIMEABORT("Can't open GL context and can't fall back on /dev/graphics/fb0 ...");
|
|
}
|
|
|
|
mLayerManager = new ClientLayerManager(this);
|
|
mUseLayersAcceleration = false;
|
|
|
|
return mLayerManager;
|
|
}
|
|
|
|
gfxASurface *
|
|
nsWindow::GetThebesSurface()
|
|
{
|
|
/* This is really a dummy surface; this is only used when doing reflow, because
|
|
* we need a RenderingContext to measure text against.
|
|
*/
|
|
|
|
// XXX this really wants to return already_AddRefed, but this only really gets used
|
|
// on direct assignment to a gfxASurface
|
|
return new gfxImageSurface(gfxIntSize(5,5), gfxImageFormatRGB24);
|
|
}
|
|
|
|
void
|
|
nsWindow::BringToTop()
|
|
{
|
|
if (!sTopWindows.IsEmpty()) {
|
|
if (nsIWidgetListener* listener = sTopWindows[0]->GetWidgetListener())
|
|
listener->WindowDeactivated();
|
|
}
|
|
|
|
sTopWindows.RemoveElement(this);
|
|
sTopWindows.InsertElementAt(0, this);
|
|
|
|
if (mWidgetListener)
|
|
mWidgetListener->WindowActivated();
|
|
Invalidate(sVirtualBounds);
|
|
}
|
|
|
|
void
|
|
nsWindow::UserActivity()
|
|
{
|
|
if (!mIdleService) {
|
|
mIdleService = do_GetService("@mozilla.org/widget/idleservice;1");
|
|
}
|
|
|
|
if (mIdleService) {
|
|
mIdleService->ResetIdleTimeOut(0);
|
|
}
|
|
}
|
|
|
|
uint32_t
|
|
nsWindow::GetGLFrameBufferFormat()
|
|
{
|
|
if (mLayerManager &&
|
|
mLayerManager->GetBackendType() == mozilla::layers::LAYERS_OPENGL) {
|
|
// We directly map the hardware fb on Gonk. The hardware fb
|
|
// has RGB format.
|
|
return LOCAL_GL_RGB;
|
|
}
|
|
return LOCAL_GL_NONE;
|
|
}
|
|
|
|
nsIntRect
|
|
nsWindow::GetNaturalBounds()
|
|
{
|
|
return gScreenBounds;
|
|
}
|
|
|
|
bool
|
|
nsWindow::NeedsPaint()
|
|
{
|
|
if (!mLayerManager) {
|
|
return false;
|
|
}
|
|
return nsIWidget::NeedsPaint();
|
|
}
|
|
|
|
Composer2D*
|
|
nsWindow::GetComposer2D()
|
|
{
|
|
if (!sUsingHwc) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (HwcComposer2D* hwc = HwcComposer2D::GetInstance()) {
|
|
return hwc->Initialized() ? hwc : nullptr;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
// nsScreenGonk.cpp
|
|
|
|
nsScreenGonk::nsScreenGonk(void *nativeScreen)
|
|
{
|
|
}
|
|
|
|
nsScreenGonk::~nsScreenGonk()
|
|
{
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsScreenGonk::GetRect(int32_t *outLeft, int32_t *outTop,
|
|
int32_t *outWidth, int32_t *outHeight)
|
|
{
|
|
*outLeft = sVirtualBounds.x;
|
|
*outTop = sVirtualBounds.y;
|
|
|
|
*outWidth = sVirtualBounds.width;
|
|
*outHeight = sVirtualBounds.height;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsScreenGonk::GetAvailRect(int32_t *outLeft, int32_t *outTop,
|
|
int32_t *outWidth, int32_t *outHeight)
|
|
{
|
|
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();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsScreenGonk::GetColorDepth(int32_t *aColorDepth)
|
|
{
|
|
return GetPixelDepth(aColorDepth);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsScreenGonk::GetRotation(uint32_t* aRotation)
|
|
{
|
|
*aRotation = sScreenRotation;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsScreenGonk::SetRotation(uint32_t aRotation)
|
|
{
|
|
if (!(aRotation <= ROTATION_270_DEG))
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
|
|
if (sScreenRotation == aRotation)
|
|
return NS_OK;
|
|
|
|
sScreenRotation = aRotation;
|
|
sRotationMatrix =
|
|
ComputeTransformForRotation(gScreenBounds,
|
|
ScreenRotation(EffectiveScreenRotation()));
|
|
uint32_t rotation = EffectiveScreenRotation();
|
|
if (rotation == nsIScreen::ROTATION_90_DEG ||
|
|
rotation == nsIScreen::ROTATION_270_DEG) {
|
|
sVirtualBounds = nsIntRect(0, 0, gScreenBounds.height,
|
|
gScreenBounds.width);
|
|
} else {
|
|
sVirtualBounds = gScreenBounds;
|
|
}
|
|
|
|
for (unsigned int i = 0; i < sTopWindows.Length(); i++)
|
|
sTopWindows[i]->Resize(sVirtualBounds.width,
|
|
sVirtualBounds.height,
|
|
!i);
|
|
|
|
nsAppShell::NotifyScreenRotation();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
// NB: This isn't gonk-specific, but gonk is the only widget backend
|
|
// that does this calculation itself, currently.
|
|
static ScreenOrientation
|
|
ComputeOrientation(uint32_t aRotation, const nsIntSize& aScreenSize)
|
|
{
|
|
bool naturallyPortrait = (aScreenSize.height > aScreenSize.width);
|
|
switch (aRotation) {
|
|
case nsIScreen::ROTATION_0_DEG:
|
|
return (naturallyPortrait ? eScreenOrientation_PortraitPrimary :
|
|
eScreenOrientation_LandscapePrimary);
|
|
case nsIScreen::ROTATION_90_DEG:
|
|
// Arbitrarily choosing 90deg to be primary "unnatural"
|
|
// rotation.
|
|
return (naturallyPortrait ? eScreenOrientation_LandscapePrimary :
|
|
eScreenOrientation_PortraitPrimary);
|
|
case nsIScreen::ROTATION_180_DEG:
|
|
return (naturallyPortrait ? eScreenOrientation_PortraitSecondary :
|
|
eScreenOrientation_LandscapeSecondary);
|
|
case nsIScreen::ROTATION_270_DEG:
|
|
return (naturallyPortrait ? eScreenOrientation_LandscapeSecondary :
|
|
eScreenOrientation_PortraitSecondary);
|
|
default:
|
|
MOZ_CRASH("Gonk screen must always have a known rotation");
|
|
}
|
|
}
|
|
|
|
/*static*/ uint32_t
|
|
nsScreenGonk::GetRotation()
|
|
{
|
|
return sScreenRotation;
|
|
}
|
|
|
|
/*static*/ ScreenConfiguration
|
|
nsScreenGonk::GetConfiguration()
|
|
{
|
|
ScreenOrientation orientation = ComputeOrientation(sScreenRotation,
|
|
gScreenBounds.Size());
|
|
uint32_t colorDepth = ColorDepth();
|
|
// NB: perpetuating colorDepth == pixelDepth illusion here, for
|
|
// consistency.
|
|
return ScreenConfiguration(sVirtualBounds, orientation,
|
|
colorDepth, colorDepth);
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS1(nsScreenManagerGonk, nsIScreenManager)
|
|
|
|
nsScreenManagerGonk::nsScreenManagerGonk()
|
|
{
|
|
mOneScreen = new nsScreenGonk(nullptr);
|
|
}
|
|
|
|
nsScreenManagerGonk::~nsScreenManagerGonk()
|
|
{
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsScreenManagerGonk::GetPrimaryScreen(nsIScreen **outScreen)
|
|
{
|
|
NS_IF_ADDREF(*outScreen = mOneScreen.get());
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsScreenManagerGonk::ScreenForRect(int32_t inLeft,
|
|
int32_t inTop,
|
|
int32_t inWidth,
|
|
int32_t inHeight,
|
|
nsIScreen **outScreen)
|
|
{
|
|
return GetPrimaryScreen(outScreen);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsScreenManagerGonk::ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen)
|
|
{
|
|
return GetPrimaryScreen(outScreen);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsScreenManagerGonk::GetNumberOfScreens(uint32_t *aNumberOfScreens)
|
|
{
|
|
*aNumberOfScreens = 1;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsScreenManagerGonk::GetSystemDefaultScale(float *aDefaultScale)
|
|
{
|
|
*aDefaultScale = 1.0f;
|
|
return NS_OK;
|
|
}
|