1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gonk/nsWindow.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,864 @@ 1.4 +/* Copyright 2012 Mozilla Foundation and Mozilla contributors 1.5 + * 1.6 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.7 + * you may not use this file except in compliance with the License. 1.8 + * You may obtain a copy of the License at 1.9 + * 1.10 + * http://www.apache.org/licenses/LICENSE-2.0 1.11 + * 1.12 + * Unless required by applicable law or agreed to in writing, software 1.13 + * distributed under the License is distributed on an "AS IS" BASIS, 1.14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.15 + * See the License for the specific language governing permissions and 1.16 + * limitations under the License. 1.17 + */ 1.18 + 1.19 +#include "mozilla/DebugOnly.h" 1.20 + 1.21 +#include <fcntl.h> 1.22 + 1.23 +#include "android/log.h" 1.24 + 1.25 +#include "mozilla/dom/TabParent.h" 1.26 +#include "mozilla/Hal.h" 1.27 +#include "mozilla/Preferences.h" 1.28 +#include "mozilla/FileUtils.h" 1.29 +#include "mozilla/ClearOnShutdown.h" 1.30 +#include "Framebuffer.h" 1.31 +#include "gfxContext.h" 1.32 +#include "gfxPlatform.h" 1.33 +#include "gfxUtils.h" 1.34 +#include "GLContextProvider.h" 1.35 +#include "GLContext.h" 1.36 +#include "nsAutoPtr.h" 1.37 +#include "nsAppShell.h" 1.38 +#include "nsIdleService.h" 1.39 +#include "nsScreenManagerGonk.h" 1.40 +#include "nsTArray.h" 1.41 +#include "nsWindow.h" 1.42 +#include "nsIWidgetListener.h" 1.43 +#include "cutils/properties.h" 1.44 +#include "ClientLayerManager.h" 1.45 +#include "BasicLayers.h" 1.46 +#include "libdisplay/GonkDisplay.h" 1.47 +#include "pixelflinger/format.h" 1.48 +#include "mozilla/BasicEvents.h" 1.49 +#include "mozilla/layers/APZCTreeManager.h" 1.50 +#include "mozilla/layers/CompositorParent.h" 1.51 +#include "ParentProcessController.h" 1.52 +#include "nsThreadUtils.h" 1.53 +#include "HwcComposer2D.h" 1.54 + 1.55 +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args) 1.56 +#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "Gonk", ## args) 1.57 +#define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "Gonk", ## args) 1.58 + 1.59 +#define IS_TOPLEVEL() (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog) 1.60 + 1.61 +using namespace mozilla; 1.62 +using namespace mozilla::dom; 1.63 +using namespace mozilla::hal; 1.64 +using namespace mozilla::gl; 1.65 +using namespace mozilla::layers; 1.66 +using namespace mozilla::widget; 1.67 + 1.68 +nsIntRect gScreenBounds; 1.69 +static uint32_t sScreenRotation; 1.70 +static uint32_t sPhysicalScreenRotation; 1.71 +static nsIntRect sVirtualBounds; 1.72 + 1.73 +static nsRefPtr<GLContext> sGLContext; 1.74 +static nsTArray<nsWindow *> sTopWindows; 1.75 +static nsWindow *gFocusedWindow = nullptr; 1.76 +static bool sFramebufferOpen; 1.77 +static bool sUsingOMTC; 1.78 +static bool sUsingHwc; 1.79 +static bool sScreenInitialized; 1.80 +static nsRefPtr<gfxASurface> sOMTCSurface; 1.81 + 1.82 +namespace { 1.83 + 1.84 +static uint32_t 1.85 +EffectiveScreenRotation() 1.86 +{ 1.87 + return (sScreenRotation + sPhysicalScreenRotation) % (360 / 90); 1.88 +} 1.89 + 1.90 +class ScreenOnOffEvent : public nsRunnable { 1.91 +public: 1.92 + ScreenOnOffEvent(bool on) 1.93 + : mIsOn(on) 1.94 + {} 1.95 + 1.96 + NS_IMETHOD Run() { 1.97 + for (uint32_t i = 0; i < sTopWindows.Length(); i++) { 1.98 + nsWindow *win = sTopWindows[i]; 1.99 + 1.100 + if (nsIWidgetListener* listener = win->GetWidgetListener()) { 1.101 + listener->SizeModeChanged(mIsOn ? nsSizeMode_Fullscreen : nsSizeMode_Minimized); 1.102 + } 1.103 + } 1.104 + 1.105 + // Notify observers that the screen state has just changed. 1.106 + nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService(); 1.107 + if (observerService) { 1.108 + observerService->NotifyObservers( 1.109 + nullptr, "screen-state-changed", 1.110 + mIsOn ? MOZ_UTF16("on") : MOZ_UTF16("off") 1.111 + ); 1.112 + } 1.113 + 1.114 + return NS_OK; 1.115 + } 1.116 + 1.117 +private: 1.118 + bool mIsOn; 1.119 +}; 1.120 + 1.121 +static StaticRefPtr<ScreenOnOffEvent> sScreenOnEvent; 1.122 +static StaticRefPtr<ScreenOnOffEvent> sScreenOffEvent; 1.123 + 1.124 +static void 1.125 +displayEnabledCallback(bool enabled) 1.126 +{ 1.127 + NS_DispatchToMainThread(enabled ? sScreenOnEvent : sScreenOffEvent); 1.128 +} 1.129 + 1.130 +} // anonymous namespace 1.131 + 1.132 +nsWindow::nsWindow() 1.133 +{ 1.134 + if (!sScreenInitialized) { 1.135 + sScreenOnEvent = new ScreenOnOffEvent(true); 1.136 + ClearOnShutdown(&sScreenOnEvent); 1.137 + sScreenOffEvent = new ScreenOnOffEvent(false); 1.138 + ClearOnShutdown(&sScreenOffEvent); 1.139 + GetGonkDisplay()->OnEnabled(displayEnabledCallback); 1.140 + 1.141 + nsIntSize screenSize; 1.142 + bool gotFB = Framebuffer::GetSize(&screenSize); 1.143 + if (!gotFB) { 1.144 + NS_RUNTIMEABORT("Failed to get size from framebuffer, aborting..."); 1.145 + } 1.146 + gScreenBounds = nsIntRect(nsIntPoint(0, 0), screenSize); 1.147 + 1.148 + char propValue[PROPERTY_VALUE_MAX]; 1.149 + property_get("ro.sf.hwrotation", propValue, "0"); 1.150 + sPhysicalScreenRotation = atoi(propValue) / 90; 1.151 + 1.152 + sVirtualBounds = gScreenBounds; 1.153 + 1.154 + sScreenInitialized = true; 1.155 + 1.156 + nsAppShell::NotifyScreenInitialized(); 1.157 + 1.158 + // This is a hack to force initialization of the compositor 1.159 + // resources, if we're going to use omtc. 1.160 + // 1.161 + // NB: GetPlatform() will create the gfxPlatform, which wants 1.162 + // to know the color depth, which asks our native window. 1.163 + // This has to happen after other init has finished. 1.164 + gfxPlatform::GetPlatform(); 1.165 + sUsingOMTC = ShouldUseOffMainThreadCompositing(); 1.166 + 1.167 + property_get("ro.display.colorfill", propValue, "0"); 1.168 + 1.169 + //Update sUsingHwc whenever layers.composer2d.enabled changes 1.170 + Preferences::AddBoolVarCache(&sUsingHwc, "layers.composer2d.enabled"); 1.171 + 1.172 + if (sUsingOMTC) { 1.173 + sOMTCSurface = new gfxImageSurface(gfxIntSize(1, 1), 1.174 + gfxImageFormat::RGB24); 1.175 + } 1.176 + } 1.177 +} 1.178 + 1.179 +nsWindow::~nsWindow() 1.180 +{ 1.181 +} 1.182 + 1.183 +void 1.184 +nsWindow::DoDraw(void) 1.185 +{ 1.186 + if (!hal::GetScreenEnabled()) { 1.187 + gDrawRequest = true; 1.188 + return; 1.189 + } 1.190 + 1.191 + if (sTopWindows.IsEmpty()) { 1.192 + LOG(" no window to draw, bailing"); 1.193 + return; 1.194 + } 1.195 + 1.196 + nsWindow *targetWindow = (nsWindow *)sTopWindows[0]; 1.197 + while (targetWindow->GetLastChild()) 1.198 + targetWindow = (nsWindow *)targetWindow->GetLastChild(); 1.199 + 1.200 + nsIWidgetListener* listener = targetWindow->GetWidgetListener(); 1.201 + if (listener) { 1.202 + listener->WillPaintWindow(targetWindow); 1.203 + } 1.204 + 1.205 + LayerManager* lm = targetWindow->GetLayerManager(); 1.206 + if (mozilla::layers::LayersBackend::LAYERS_CLIENT == lm->GetBackendType()) { 1.207 + // No need to do anything, the compositor will handle drawing 1.208 + } else if (mozilla::layers::LayersBackend::LAYERS_BASIC == lm->GetBackendType()) { 1.209 + MOZ_ASSERT(sFramebufferOpen || sUsingOMTC); 1.210 + nsRefPtr<gfxASurface> targetSurface; 1.211 + 1.212 + if(sUsingOMTC) 1.213 + targetSurface = sOMTCSurface; 1.214 + else 1.215 + targetSurface = Framebuffer::BackBuffer(); 1.216 + 1.217 + { 1.218 + nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface); 1.219 + gfxUtils::PathFromRegion(ctx, sVirtualBounds); 1.220 + ctx->Clip(); 1.221 + 1.222 + // No double-buffering needed. 1.223 + AutoLayerManagerSetup setupLayerManager( 1.224 + targetWindow, ctx, mozilla::layers::BufferMode::BUFFER_NONE, 1.225 + ScreenRotation(EffectiveScreenRotation())); 1.226 + 1.227 + listener = targetWindow->GetWidgetListener(); 1.228 + if (listener) { 1.229 + listener->PaintWindow(targetWindow, sVirtualBounds); 1.230 + } 1.231 + } 1.232 + 1.233 + if (!sUsingOMTC) { 1.234 + targetSurface->Flush(); 1.235 + Framebuffer::Present(sVirtualBounds); 1.236 + } 1.237 + } else { 1.238 + NS_RUNTIMEABORT("Unexpected layer manager type"); 1.239 + } 1.240 + 1.241 + listener = targetWindow->GetWidgetListener(); 1.242 + if (listener) { 1.243 + listener->DidPaintWindow(); 1.244 + } 1.245 +} 1.246 + 1.247 +nsEventStatus 1.248 +nsWindow::DispatchInputEvent(WidgetGUIEvent& aEvent, bool* aWasCaptured) 1.249 +{ 1.250 + if (aWasCaptured) { 1.251 + *aWasCaptured = false; 1.252 + } 1.253 + if (!gFocusedWindow) { 1.254 + return nsEventStatus_eIgnore; 1.255 + } 1.256 + 1.257 + gFocusedWindow->UserActivity(); 1.258 + 1.259 + aEvent.widget = gFocusedWindow; 1.260 + 1.261 + if (TabParent* capturer = TabParent::GetEventCapturer()) { 1.262 + bool captured = capturer->TryCapture(aEvent); 1.263 + if (aWasCaptured) { 1.264 + *aWasCaptured = captured; 1.265 + } 1.266 + if (captured) { 1.267 + return nsEventStatus_eConsumeNoDefault; 1.268 + } 1.269 + } 1.270 + 1.271 + nsEventStatus status; 1.272 + gFocusedWindow->DispatchEvent(&aEvent, status); 1.273 + return status; 1.274 +} 1.275 + 1.276 +NS_IMETHODIMP 1.277 +nsWindow::Create(nsIWidget *aParent, 1.278 + void *aNativeParent, 1.279 + const nsIntRect &aRect, 1.280 + nsDeviceContext *aContext, 1.281 + nsWidgetInitData *aInitData) 1.282 +{ 1.283 + BaseCreate(aParent, IS_TOPLEVEL() ? sVirtualBounds : aRect, 1.284 + aContext, aInitData); 1.285 + 1.286 + mBounds = aRect; 1.287 + 1.288 + mParent = (nsWindow *)aParent; 1.289 + mVisible = false; 1.290 + 1.291 + if (!aParent) { 1.292 + mBounds = sVirtualBounds; 1.293 + } 1.294 + 1.295 + if (!IS_TOPLEVEL()) 1.296 + return NS_OK; 1.297 + 1.298 + sTopWindows.AppendElement(this); 1.299 + 1.300 + Resize(0, 0, sVirtualBounds.width, sVirtualBounds.height, false); 1.301 + return NS_OK; 1.302 +} 1.303 + 1.304 +NS_IMETHODIMP 1.305 +nsWindow::Destroy(void) 1.306 +{ 1.307 + mOnDestroyCalled = true; 1.308 + sTopWindows.RemoveElement(this); 1.309 + if (this == gFocusedWindow) 1.310 + gFocusedWindow = nullptr; 1.311 + nsBaseWidget::OnDestroy(); 1.312 + return NS_OK; 1.313 +} 1.314 + 1.315 +NS_IMETHODIMP 1.316 +nsWindow::Show(bool aState) 1.317 +{ 1.318 + if (mWindowType == eWindowType_invisible) 1.319 + return NS_OK; 1.320 + 1.321 + if (mVisible == aState) 1.322 + return NS_OK; 1.323 + 1.324 + mVisible = aState; 1.325 + if (!IS_TOPLEVEL()) 1.326 + return mParent ? mParent->Show(aState) : NS_OK; 1.327 + 1.328 + if (aState) { 1.329 + BringToTop(); 1.330 + } else { 1.331 + for (unsigned int i = 0; i < sTopWindows.Length(); i++) { 1.332 + nsWindow *win = sTopWindows[i]; 1.333 + if (!win->mVisible) 1.334 + continue; 1.335 + 1.336 + win->BringToTop(); 1.337 + break; 1.338 + } 1.339 + } 1.340 + 1.341 + return NS_OK; 1.342 +} 1.343 + 1.344 +bool 1.345 +nsWindow::IsVisible() const 1.346 +{ 1.347 + return mVisible; 1.348 +} 1.349 + 1.350 +NS_IMETHODIMP 1.351 +nsWindow::ConstrainPosition(bool aAllowSlop, 1.352 + int32_t *aX, 1.353 + int32_t *aY) 1.354 +{ 1.355 + return NS_OK; 1.356 +} 1.357 + 1.358 +NS_IMETHODIMP 1.359 +nsWindow::Move(double aX, 1.360 + double aY) 1.361 +{ 1.362 + return NS_OK; 1.363 +} 1.364 + 1.365 +NS_IMETHODIMP 1.366 +nsWindow::Resize(double aWidth, 1.367 + double aHeight, 1.368 + bool aRepaint) 1.369 +{ 1.370 + return Resize(0, 0, aWidth, aHeight, aRepaint); 1.371 +} 1.372 + 1.373 +NS_IMETHODIMP 1.374 +nsWindow::Resize(double aX, 1.375 + double aY, 1.376 + double aWidth, 1.377 + double aHeight, 1.378 + bool aRepaint) 1.379 +{ 1.380 + mBounds = nsIntRect(NSToIntRound(aX), NSToIntRound(aY), 1.381 + NSToIntRound(aWidth), NSToIntRound(aHeight)); 1.382 + if (mWidgetListener) 1.383 + mWidgetListener->WindowResized(this, mBounds.width, mBounds.height); 1.384 + 1.385 + if (aRepaint) 1.386 + Invalidate(sVirtualBounds); 1.387 + 1.388 + return NS_OK; 1.389 +} 1.390 + 1.391 +NS_IMETHODIMP 1.392 +nsWindow::Enable(bool aState) 1.393 +{ 1.394 + return NS_OK; 1.395 +} 1.396 + 1.397 +bool 1.398 +nsWindow::IsEnabled() const 1.399 +{ 1.400 + return true; 1.401 +} 1.402 + 1.403 +NS_IMETHODIMP 1.404 +nsWindow::SetFocus(bool aRaise) 1.405 +{ 1.406 + if (aRaise) 1.407 + BringToTop(); 1.408 + 1.409 + gFocusedWindow = this; 1.410 + return NS_OK; 1.411 +} 1.412 + 1.413 +NS_IMETHODIMP 1.414 +nsWindow::ConfigureChildren(const nsTArray<nsIWidget::Configuration>&) 1.415 +{ 1.416 + return NS_OK; 1.417 +} 1.418 + 1.419 +NS_IMETHODIMP 1.420 +nsWindow::Invalidate(const nsIntRect &aRect) 1.421 +{ 1.422 + nsWindow *top = mParent; 1.423 + while (top && top->mParent) 1.424 + top = top->mParent; 1.425 + if (top != sTopWindows[0] && this != sTopWindows[0]) 1.426 + return NS_OK; 1.427 + 1.428 + gDrawRequest = true; 1.429 + mozilla::NotifyEvent(); 1.430 + return NS_OK; 1.431 +} 1.432 + 1.433 +nsIntPoint 1.434 +nsWindow::WidgetToScreenOffset() 1.435 +{ 1.436 + nsIntPoint p(0, 0); 1.437 + nsWindow *w = this; 1.438 + 1.439 + while (w && w->mParent) { 1.440 + p.x += w->mBounds.x; 1.441 + p.y += w->mBounds.y; 1.442 + 1.443 + w = w->mParent; 1.444 + } 1.445 + 1.446 + return p; 1.447 +} 1.448 + 1.449 +void* 1.450 +nsWindow::GetNativeData(uint32_t aDataType) 1.451 +{ 1.452 + switch (aDataType) { 1.453 + case NS_NATIVE_WINDOW: 1.454 + return GetGonkDisplay()->GetNativeWindow(); 1.455 + } 1.456 + return nullptr; 1.457 +} 1.458 + 1.459 +NS_IMETHODIMP 1.460 +nsWindow::DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus) 1.461 +{ 1.462 + if (mWidgetListener) 1.463 + aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents); 1.464 + return NS_OK; 1.465 +} 1.466 + 1.467 +NS_IMETHODIMP_(void) 1.468 +nsWindow::SetInputContext(const InputContext& aContext, 1.469 + const InputContextAction& aAction) 1.470 +{ 1.471 + mInputContext = aContext; 1.472 +} 1.473 + 1.474 +NS_IMETHODIMP_(InputContext) 1.475 +nsWindow::GetInputContext() 1.476 +{ 1.477 + // There is only one IME context on Gonk. 1.478 + mInputContext.mNativeIMEContext = nullptr; 1.479 + return mInputContext; 1.480 +} 1.481 + 1.482 +NS_IMETHODIMP 1.483 +nsWindow::ReparentNativeWidget(nsIWidget* aNewParent) 1.484 +{ 1.485 + return NS_OK; 1.486 +} 1.487 + 1.488 +NS_IMETHODIMP 1.489 +nsWindow::MakeFullScreen(bool aFullScreen) 1.490 +{ 1.491 + if (mWindowType != eWindowType_toplevel) { 1.492 + // Ignore fullscreen request for non-toplevel windows. 1.493 + NS_WARNING("MakeFullScreen() on a dialog or child widget?"); 1.494 + return nsBaseWidget::MakeFullScreen(aFullScreen); 1.495 + } 1.496 + 1.497 + if (aFullScreen) { 1.498 + // Fullscreen is "sticky" for toplevel widgets on gonk: we 1.499 + // must paint the entire screen, and should only have one 1.500 + // toplevel widget, so it doesn't make sense to ever "exit" 1.501 + // fullscreen. If we do, we can leave parts of the screen 1.502 + // unpainted. 1.503 + Resize(sVirtualBounds.x, sVirtualBounds.y, 1.504 + sVirtualBounds.width, sVirtualBounds.height, 1.505 + /*repaint*/true); 1.506 + } 1.507 + return NS_OK; 1.508 +} 1.509 + 1.510 +float 1.511 +nsWindow::GetDPI() 1.512 +{ 1.513 + return GetGonkDisplay()->xdpi; 1.514 +} 1.515 + 1.516 +double 1.517 +nsWindow::GetDefaultScaleInternal() 1.518 +{ 1.519 + float dpi = GetDPI(); 1.520 + // The mean pixel density for mdpi devices is 160dpi, 240dpi for hdpi, 1.521 + // and 320dpi for xhdpi, respectively. 1.522 + // We'll take the mid-value between these three numbers as the boundary. 1.523 + if (dpi < 200.0) { 1.524 + return 1.0; // mdpi devices. 1.525 + } 1.526 + if (dpi < 300.0) { 1.527 + return 1.5; // hdpi devices. 1.528 + } 1.529 + // xhdpi devices and beyond. 1.530 + return floor(dpi / 150.0 + 0.5); 1.531 +} 1.532 + 1.533 +LayerManager * 1.534 +nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager, 1.535 + LayersBackend aBackendHint, 1.536 + LayerManagerPersistence aPersistence, 1.537 + bool* aAllowRetaining) 1.538 +{ 1.539 + if (aAllowRetaining) 1.540 + *aAllowRetaining = true; 1.541 + if (mLayerManager) { 1.542 + // This layer manager might be used for painting outside of DoDraw(), so we need 1.543 + // to set the correct rotation on it. 1.544 + if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC) { 1.545 + BasicLayerManager* manager = 1.546 + static_cast<BasicLayerManager*>(mLayerManager.get()); 1.547 + manager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE, 1.548 + ScreenRotation(EffectiveScreenRotation())); 1.549 + } else if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_CLIENT) { 1.550 + ClientLayerManager* manager = 1.551 + static_cast<ClientLayerManager*>(mLayerManager.get()); 1.552 + manager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE, 1.553 + ScreenRotation(EffectiveScreenRotation())); 1.554 + } 1.555 + return mLayerManager; 1.556 + } 1.557 + 1.558 + // Set mUseLayersAcceleration here to make it consistent with 1.559 + // nsBaseWidget::GetLayerManager 1.560 + mUseLayersAcceleration = ComputeShouldAccelerate(mUseLayersAcceleration); 1.561 + nsWindow *topWindow = sTopWindows[0]; 1.562 + 1.563 + if (!topWindow) { 1.564 + LOGW(" -- no topwindow\n"); 1.565 + return nullptr; 1.566 + } 1.567 + 1.568 + if (sUsingOMTC) { 1.569 + CreateCompositor(); 1.570 + if (mCompositorParent) { 1.571 + uint64_t rootLayerTreeId = mCompositorParent->RootLayerTreeId(); 1.572 + CompositorParent::SetControllerForLayerTree(rootLayerTreeId, new ParentProcessController()); 1.573 + CompositorParent::GetAPZCTreeManager(rootLayerTreeId)->SetDPI(GetDPI()); 1.574 + } 1.575 + if (mLayerManager) 1.576 + return mLayerManager; 1.577 + } 1.578 + 1.579 + if (mUseLayersAcceleration) { 1.580 + DebugOnly<nsIntRect> fbBounds = gScreenBounds; 1.581 + if (!sGLContext) { 1.582 + sGLContext = GLContextProvider::CreateForWindow(this); 1.583 + } 1.584 + 1.585 + MOZ_ASSERT(fbBounds.value == gScreenBounds); 1.586 + } 1.587 + 1.588 + // Fall back to software rendering. 1.589 + sFramebufferOpen = Framebuffer::Open(); 1.590 + if (sFramebufferOpen) { 1.591 + LOG("Falling back to framebuffer software rendering"); 1.592 + } else { 1.593 + LOGE("Failed to mmap fb(?!?), aborting ..."); 1.594 + NS_RUNTIMEABORT("Can't open GL context and can't fall back on /dev/graphics/fb0 ..."); 1.595 + } 1.596 + 1.597 + mLayerManager = new ClientLayerManager(this); 1.598 + mUseLayersAcceleration = false; 1.599 + 1.600 + return mLayerManager; 1.601 +} 1.602 + 1.603 +gfxASurface * 1.604 +nsWindow::GetThebesSurface() 1.605 +{ 1.606 + /* This is really a dummy surface; this is only used when doing reflow, because 1.607 + * we need a RenderingContext to measure text against. 1.608 + */ 1.609 + 1.610 + // XXX this really wants to return already_AddRefed, but this only really gets used 1.611 + // on direct assignment to a gfxASurface 1.612 + return new gfxImageSurface(gfxIntSize(5,5), gfxImageFormat::RGB24); 1.613 +} 1.614 + 1.615 +void 1.616 +nsWindow::BringToTop() 1.617 +{ 1.618 + if (!sTopWindows.IsEmpty()) { 1.619 + if (nsIWidgetListener* listener = sTopWindows[0]->GetWidgetListener()) 1.620 + listener->WindowDeactivated(); 1.621 + } 1.622 + 1.623 + sTopWindows.RemoveElement(this); 1.624 + sTopWindows.InsertElementAt(0, this); 1.625 + 1.626 + if (mWidgetListener) 1.627 + mWidgetListener->WindowActivated(); 1.628 + Invalidate(sVirtualBounds); 1.629 +} 1.630 + 1.631 +void 1.632 +nsWindow::UserActivity() 1.633 +{ 1.634 + if (!mIdleService) { 1.635 + mIdleService = do_GetService("@mozilla.org/widget/idleservice;1"); 1.636 + } 1.637 + 1.638 + if (mIdleService) { 1.639 + mIdleService->ResetIdleTimeOut(0); 1.640 + } 1.641 +} 1.642 + 1.643 +uint32_t 1.644 +nsWindow::GetGLFrameBufferFormat() 1.645 +{ 1.646 + if (mLayerManager && 1.647 + mLayerManager->GetBackendType() == mozilla::layers::LayersBackend::LAYERS_OPENGL) { 1.648 + // We directly map the hardware fb on Gonk. The hardware fb 1.649 + // has RGB format. 1.650 + return LOCAL_GL_RGB; 1.651 + } 1.652 + return LOCAL_GL_NONE; 1.653 +} 1.654 + 1.655 +nsIntRect 1.656 +nsWindow::GetNaturalBounds() 1.657 +{ 1.658 + return gScreenBounds; 1.659 +} 1.660 + 1.661 +bool 1.662 +nsWindow::NeedsPaint() 1.663 +{ 1.664 + if (!mLayerManager) { 1.665 + return false; 1.666 + } 1.667 + return nsIWidget::NeedsPaint(); 1.668 +} 1.669 + 1.670 +Composer2D* 1.671 +nsWindow::GetComposer2D() 1.672 +{ 1.673 + if (!sUsingHwc) { 1.674 + return nullptr; 1.675 + } 1.676 + 1.677 + if (HwcComposer2D* hwc = HwcComposer2D::GetInstance()) { 1.678 + return hwc->Initialized() ? hwc : nullptr; 1.679 + } 1.680 + 1.681 + return nullptr; 1.682 +} 1.683 + 1.684 +// nsScreenGonk.cpp 1.685 + 1.686 +nsScreenGonk::nsScreenGonk(void *nativeScreen) 1.687 +{ 1.688 +} 1.689 + 1.690 +nsScreenGonk::~nsScreenGonk() 1.691 +{ 1.692 +} 1.693 + 1.694 +NS_IMETHODIMP 1.695 +nsScreenGonk::GetRect(int32_t *outLeft, int32_t *outTop, 1.696 + int32_t *outWidth, int32_t *outHeight) 1.697 +{ 1.698 + *outLeft = sVirtualBounds.x; 1.699 + *outTop = sVirtualBounds.y; 1.700 + 1.701 + *outWidth = sVirtualBounds.width; 1.702 + *outHeight = sVirtualBounds.height; 1.703 + 1.704 + return NS_OK; 1.705 +} 1.706 + 1.707 +NS_IMETHODIMP 1.708 +nsScreenGonk::GetAvailRect(int32_t *outLeft, int32_t *outTop, 1.709 + int32_t *outWidth, int32_t *outHeight) 1.710 +{ 1.711 + return GetRect(outLeft, outTop, outWidth, outHeight); 1.712 +} 1.713 + 1.714 +static uint32_t 1.715 +ColorDepth() 1.716 +{ 1.717 + switch (GetGonkDisplay()->surfaceformat) { 1.718 + case GGL_PIXEL_FORMAT_RGB_565: 1.719 + return 16; 1.720 + case GGL_PIXEL_FORMAT_RGBA_8888: 1.721 + return 32; 1.722 + } 1.723 + return 24; // GGL_PIXEL_FORMAT_RGBX_8888 1.724 +} 1.725 + 1.726 +NS_IMETHODIMP 1.727 +nsScreenGonk::GetPixelDepth(int32_t *aPixelDepth) 1.728 +{ 1.729 + // XXX: this should actually return 32 when we're using 24-bit 1.730 + // color, because we use RGBX. 1.731 + *aPixelDepth = ColorDepth(); 1.732 + return NS_OK; 1.733 +} 1.734 + 1.735 +NS_IMETHODIMP 1.736 +nsScreenGonk::GetColorDepth(int32_t *aColorDepth) 1.737 +{ 1.738 + return GetPixelDepth(aColorDepth); 1.739 +} 1.740 + 1.741 +NS_IMETHODIMP 1.742 +nsScreenGonk::GetRotation(uint32_t* aRotation) 1.743 +{ 1.744 + *aRotation = sScreenRotation; 1.745 + return NS_OK; 1.746 +} 1.747 + 1.748 +NS_IMETHODIMP 1.749 +nsScreenGonk::SetRotation(uint32_t aRotation) 1.750 +{ 1.751 + if (!(aRotation <= ROTATION_270_DEG)) 1.752 + return NS_ERROR_ILLEGAL_VALUE; 1.753 + 1.754 + if (sScreenRotation == aRotation) 1.755 + return NS_OK; 1.756 + 1.757 + sScreenRotation = aRotation; 1.758 + uint32_t rotation = EffectiveScreenRotation(); 1.759 + if (rotation == nsIScreen::ROTATION_90_DEG || 1.760 + rotation == nsIScreen::ROTATION_270_DEG) { 1.761 + sVirtualBounds = nsIntRect(0, 0, gScreenBounds.height, 1.762 + gScreenBounds.width); 1.763 + } else { 1.764 + sVirtualBounds = gScreenBounds; 1.765 + } 1.766 + 1.767 + nsAppShell::NotifyScreenRotation(); 1.768 + 1.769 + for (unsigned int i = 0; i < sTopWindows.Length(); i++) 1.770 + sTopWindows[i]->Resize(sVirtualBounds.width, 1.771 + sVirtualBounds.height, 1.772 + true); 1.773 + 1.774 + return NS_OK; 1.775 +} 1.776 + 1.777 +// NB: This isn't gonk-specific, but gonk is the only widget backend 1.778 +// that does this calculation itself, currently. 1.779 +static ScreenOrientation 1.780 +ComputeOrientation(uint32_t aRotation, const nsIntSize& aScreenSize) 1.781 +{ 1.782 + bool naturallyPortrait = (aScreenSize.height > aScreenSize.width); 1.783 + switch (aRotation) { 1.784 + case nsIScreen::ROTATION_0_DEG: 1.785 + return (naturallyPortrait ? eScreenOrientation_PortraitPrimary : 1.786 + eScreenOrientation_LandscapePrimary); 1.787 + case nsIScreen::ROTATION_90_DEG: 1.788 + // Arbitrarily choosing 90deg to be primary "unnatural" 1.789 + // rotation. 1.790 + return (naturallyPortrait ? eScreenOrientation_LandscapePrimary : 1.791 + eScreenOrientation_PortraitPrimary); 1.792 + case nsIScreen::ROTATION_180_DEG: 1.793 + return (naturallyPortrait ? eScreenOrientation_PortraitSecondary : 1.794 + eScreenOrientation_LandscapeSecondary); 1.795 + case nsIScreen::ROTATION_270_DEG: 1.796 + return (naturallyPortrait ? eScreenOrientation_LandscapeSecondary : 1.797 + eScreenOrientation_PortraitSecondary); 1.798 + default: 1.799 + MOZ_CRASH("Gonk screen must always have a known rotation"); 1.800 + } 1.801 +} 1.802 + 1.803 +/*static*/ uint32_t 1.804 +nsScreenGonk::GetRotation() 1.805 +{ 1.806 + return sScreenRotation; 1.807 +} 1.808 + 1.809 +/*static*/ ScreenConfiguration 1.810 +nsScreenGonk::GetConfiguration() 1.811 +{ 1.812 + ScreenOrientation orientation = ComputeOrientation(sScreenRotation, 1.813 + gScreenBounds.Size()); 1.814 + uint32_t colorDepth = ColorDepth(); 1.815 + // NB: perpetuating colorDepth == pixelDepth illusion here, for 1.816 + // consistency. 1.817 + return ScreenConfiguration(sVirtualBounds, orientation, 1.818 + colorDepth, colorDepth); 1.819 +} 1.820 + 1.821 +NS_IMPL_ISUPPORTS(nsScreenManagerGonk, nsIScreenManager) 1.822 + 1.823 +nsScreenManagerGonk::nsScreenManagerGonk() 1.824 +{ 1.825 + mOneScreen = new nsScreenGonk(nullptr); 1.826 +} 1.827 + 1.828 +nsScreenManagerGonk::~nsScreenManagerGonk() 1.829 +{ 1.830 +} 1.831 + 1.832 +NS_IMETHODIMP 1.833 +nsScreenManagerGonk::GetPrimaryScreen(nsIScreen **outScreen) 1.834 +{ 1.835 + NS_IF_ADDREF(*outScreen = mOneScreen.get()); 1.836 + return NS_OK; 1.837 +} 1.838 + 1.839 +NS_IMETHODIMP 1.840 +nsScreenManagerGonk::ScreenForRect(int32_t inLeft, 1.841 + int32_t inTop, 1.842 + int32_t inWidth, 1.843 + int32_t inHeight, 1.844 + nsIScreen **outScreen) 1.845 +{ 1.846 + return GetPrimaryScreen(outScreen); 1.847 +} 1.848 + 1.849 +NS_IMETHODIMP 1.850 +nsScreenManagerGonk::ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen) 1.851 +{ 1.852 + return GetPrimaryScreen(outScreen); 1.853 +} 1.854 + 1.855 +NS_IMETHODIMP 1.856 +nsScreenManagerGonk::GetNumberOfScreens(uint32_t *aNumberOfScreens) 1.857 +{ 1.858 + *aNumberOfScreens = 1; 1.859 + return NS_OK; 1.860 +} 1.861 + 1.862 +NS_IMETHODIMP 1.863 +nsScreenManagerGonk::GetSystemDefaultScale(float *aDefaultScale) 1.864 +{ 1.865 + *aDefaultScale = 1.0f; 1.866 + return NS_OK; 1.867 +}