diff options
Diffstat (limited to 'widget/gonk/nsWindow.cpp')
-rw-r--r-- | widget/gonk/nsWindow.cpp | 744 |
1 files changed, 0 insertions, 744 deletions
diff --git a/widget/gonk/nsWindow.cpp b/widget/gonk/nsWindow.cpp deleted file mode 100644 index e11b7f233..000000000 --- a/widget/gonk/nsWindow.cpp +++ /dev/null @@ -1,744 +0,0 @@ -/* 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 "nsWindow.h" - -#include "mozilla/DebugOnly.h" - -#include <fcntl.h> - -#include "android/log.h" -#include "mozilla/dom/TabParent.h" -#include "mozilla/Preferences.h" -#include "mozilla/RefPtr.h" -#include "mozilla/Services.h" -#include "mozilla/FileUtils.h" -#include "mozilla/ClearOnShutdown.h" -#include "gfxContext.h" -#include "gfxPlatform.h" -#include "GLContextProvider.h" -#include "GLContext.h" -#include "GLContextEGL.h" -#include "nsAppShell.h" -#include "nsScreenManagerGonk.h" -#include "nsTArray.h" -#include "nsIWidgetListener.h" -#include "ClientLayerManager.h" -#include "BasicLayers.h" -#include "libdisplay/GonkDisplay.h" -#include "mozilla/TextEvents.h" -#include "mozilla/gfx/2D.h" -#include "mozilla/gfx/Logging.h" -#include "mozilla/layers/APZCTreeManager.h" -#include "mozilla/layers/APZThreadUtils.h" -#include "mozilla/layers/CompositorBridgeParent.h" -#include "mozilla/layers/CompositorThread.h" -#include "mozilla/layers/CompositorSession.h" -#include "mozilla/TouchEvents.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::gfx; -using namespace mozilla::gl; -using namespace mozilla::layers; -using namespace mozilla::widget; - -static nsWindow *gFocusedWindow = nullptr; - -NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsBaseWidget) - -nsWindow::nsWindow() -{ - RefPtr<nsScreenManagerGonk> screenManager = nsScreenManagerGonk::GetInstance(); - screenManager->Initialize(); - - // 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(); - if (!ShouldUseOffMainThreadCompositing()) { - MOZ_CRASH("How can we render apps, then?"); - } -} - -nsWindow::~nsWindow() -{ - if (mScreen->IsPrimaryScreen()) { - mComposer2D->SetCompositorBridgeParent(nullptr); - } -} - -void -nsWindow::DoDraw(void) -{ - if (!hal::GetScreenEnabled()) { - gDrawRequest = true; - return; - } - - RefPtr<nsScreenGonk> screen = nsScreenManagerGonk::GetPrimaryScreen(); - const nsTArray<nsWindow*>& windows = screen->GetTopWindows(); - - if (windows.IsEmpty()) { - LOG(" no window to draw, bailing"); - return; - } - - RefPtr<nsWindow> targetWindow = (nsWindow *)windows[0]; - while (targetWindow->GetLastChild()) { - targetWindow = (nsWindow *)targetWindow->GetLastChild(); - } - - nsIWidgetListener* listener = targetWindow->GetWidgetListener(); - if (listener) { - listener->WillPaintWindow(targetWindow); - } - - listener = targetWindow->GetWidgetListener(); - if (listener) { - LayerManager* lm = targetWindow->GetLayerManager(); - if (mozilla::layers::LayersBackend::LAYERS_CLIENT == lm->GetBackendType()) { - // No need to do anything, the compositor will handle drawing - } else { - NS_RUNTIMEABORT("Unexpected layer manager type"); - } - - listener->DidPaintWindow(); - } -} - -void -nsWindow::ConfigureAPZControllerThread() -{ - APZThreadUtils::SetControllerThread(CompositorThreadHolder::Loop()); -} - -/*static*/ nsEventStatus -nsWindow::DispatchKeyInput(WidgetKeyboardEvent& aEvent) -{ - if (!gFocusedWindow) { - return nsEventStatus_eIgnore; - } - - gFocusedWindow->UserActivity(); - - nsEventStatus status; - aEvent.mWidget = gFocusedWindow; - gFocusedWindow->DispatchEvent(&aEvent, status); - return status; -} - -/*static*/ void -nsWindow::DispatchTouchInput(MultiTouchInput& aInput) -{ - APZThreadUtils::AssertOnControllerThread(); - - if (!gFocusedWindow) { - return; - } - - gFocusedWindow->DispatchTouchInputViaAPZ(aInput); -} - -class DispatchTouchInputOnMainThread : public mozilla::Runnable -{ -public: - DispatchTouchInputOnMainThread(const MultiTouchInput& aInput, - const ScrollableLayerGuid& aGuid, - const uint64_t& aInputBlockId, - nsEventStatus aApzResponse) - : mInput(aInput) - , mGuid(aGuid) - , mInputBlockId(aInputBlockId) - , mApzResponse(aApzResponse) - {} - - NS_IMETHOD Run() override { - if (gFocusedWindow) { - gFocusedWindow->DispatchTouchEventForAPZ(mInput, mGuid, mInputBlockId, mApzResponse); - } - return NS_OK; - } - -private: - MultiTouchInput mInput; - ScrollableLayerGuid mGuid; - uint64_t mInputBlockId; - nsEventStatus mApzResponse; -}; - -void -nsWindow::DispatchTouchInputViaAPZ(MultiTouchInput& aInput) -{ - APZThreadUtils::AssertOnControllerThread(); - - if (!mAPZC) { - // In general mAPZC should not be null, but during initial setup - // it might be, so we handle that case by ignoring touch input there. - return; - } - - // First send it through the APZ code - mozilla::layers::ScrollableLayerGuid guid; - uint64_t inputBlockId; - nsEventStatus result = mAPZC->ReceiveInputEvent(aInput, &guid, &inputBlockId); - // If the APZ says to drop it, then we drop it - if (result == nsEventStatus_eConsumeNoDefault) { - return; - } - - // Can't use NS_NewRunnableMethod because it only takes up to one arg and - // we need more. Also we can't pass in |this| to the task because nsWindow - // refcounting is not threadsafe. Instead we just use the gFocusedWindow - // static ptr inside the task. - NS_DispatchToMainThread(new DispatchTouchInputOnMainThread( - aInput, guid, inputBlockId, result)); -} - -void -nsWindow::DispatchTouchEventForAPZ(const MultiTouchInput& aInput, - const ScrollableLayerGuid& aGuid, - const uint64_t aInputBlockId, - nsEventStatus aApzResponse) -{ - MOZ_ASSERT(NS_IsMainThread()); - UserActivity(); - - // Convert it to an event we can send to Gecko - WidgetTouchEvent event = aInput.ToWidgetTouchEvent(this); - - // Dispatch the event into the gecko root process for "normal" flow. - // The event might get sent to a child process, - // but if it doesn't we need to notify the APZ of various things. - // All of that happens in ProcessUntransformedAPZEvent - ProcessUntransformedAPZEvent(&event, aGuid, aInputBlockId, aApzResponse); -} - -class DispatchTouchInputOnControllerThread : public Runnable -{ -public: - DispatchTouchInputOnControllerThread(const MultiTouchInput& aInput) - : mInput(aInput) - {} - - NS_IMETHOD Run() override { - if (gFocusedWindow) { - gFocusedWindow->DispatchTouchInputViaAPZ(mInput); - } - return NS_OK; - } - -private: - MultiTouchInput mInput; -}; - -nsresult -nsWindow::SynthesizeNativeTouchPoint(uint32_t aPointerId, - TouchPointerState aPointerState, - LayoutDeviceIntPoint aPoint, - double aPointerPressure, - uint32_t aPointerOrientation, - nsIObserver* aObserver) -{ - AutoObserverNotifier notifier(aObserver, "touchpoint"); - - if (aPointerState == TOUCH_HOVER) { - return NS_ERROR_UNEXPECTED; - } - - if (!mSynthesizedTouchInput) { - mSynthesizedTouchInput = MakeUnique<MultiTouchInput>(); - } - - // We should probably use a real timestamp here, but this is B2G and - // so this probably never even exercised any more. - uint32_t time = 0; - TimeStamp timestamp = TimeStamp::FromSystemTime(time); - - MultiTouchInput inputToDispatch = UpdateSynthesizedTouchState( - mSynthesizedTouchInput.get(), time, timestamp, aPointerId, aPointerState, - aPoint, aPointerPressure, aPointerOrientation); - - // Can't use NewRunnableMethod here because that will pass a const-ref - // argument to DispatchTouchInputViaAPZ whereas that function takes a - // non-const ref. At this callsite we don't care about the mutations that - // the function performs so this is fine. Also we can't pass |this| to the - // task because nsWindow refcounting is not threadsafe. Instead we just use - // the gFocusedWindow static ptr instead the task. - APZThreadUtils::RunOnControllerThread( - MakeAndAddRef<DispatchTouchInputOnControllerThread>(inputToDispatch)); - - return NS_OK; -} - -nsresult -nsWindow::Create(nsIWidget* aParent, - void* aNativeParent, - const LayoutDeviceIntRect& aRect, - nsWidgetInitData* aInitData) -{ - BaseCreate(aParent, aInitData); - - nsCOMPtr<nsIScreen> screen; - - uint32_t screenId = aParent ? ((nsWindow*)aParent)->mScreen->GetId() : - aInitData->mScreenId; - - RefPtr<nsScreenManagerGonk> screenManager = nsScreenManagerGonk::GetInstance(); - screenManager->ScreenForId(screenId, getter_AddRefs(screen)); - - mScreen = static_cast<nsScreenGonk*>(screen.get()); - - mBounds = aRect; - - mParent = (nsWindow *)aParent; - mVisible = false; - - if (!aParent) { - mBounds = mScreen->GetRect(); - } - - mComposer2D = HwcComposer2D::GetInstance(); - - if (!IS_TOPLEVEL()) { - return NS_OK; - } - - mScreen->RegisterWindow(this); - - Resize(0, 0, mBounds.width, mBounds.height, false); - - return NS_OK; -} - -void -nsWindow::Destroy() -{ - mOnDestroyCalled = true; - mScreen->UnregisterWindow(this); - if (this == gFocusedWindow) { - gFocusedWindow = nullptr; - } - nsBaseWidget::OnDestroy(); -} - -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 { - const nsTArray<nsWindow*>& windows = - mScreen->GetTopWindows(); - for (unsigned int i = 0; i < windows.Length(); i++) { - nsWindow *win = windows[i]; - if (!win->mVisible) { - continue; - } - win->BringToTop(); - break; - } - } - - return NS_OK; -} - -bool -nsWindow::IsVisible() const -{ - return mVisible; -} - -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 = LayoutDeviceIntRect(NSToIntRound(aX), NSToIntRound(aY), - NSToIntRound(aWidth), NSToIntRound(aHeight)); - if (mWidgetListener) { - mWidgetListener->WindowResized(this, mBounds.width, mBounds.height); - } - - if (aRepaint) { - Invalidate(mBounds); - } - - 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(); - } - - if (!IS_TOPLEVEL() && mScreen->IsPrimaryScreen()) { - // We should only set focused window on non-toplevel primary window. - gFocusedWindow = this; - } - - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::ConfigureChildren(const nsTArray<nsIWidget::Configuration>&) -{ - return NS_OK; -} - -NS_IMETHODIMP -nsWindow::Invalidate(const LayoutDeviceIntRect& aRect) -{ - nsWindow *top = mParent; - while (top && top->mParent) { - top = top->mParent; - } - const nsTArray<nsWindow*>& windows = mScreen->GetTopWindows(); - if (top != windows[0] && this != windows[0]) { - return NS_OK; - } - - gDrawRequest = true; - mozilla::NotifyEvent(); - return NS_OK; -} - -LayoutDeviceIntPoint -nsWindow::WidgetToScreenOffset() -{ - LayoutDeviceIntPoint 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: - // Called before primary display's EGLSurface creation. - return mScreen->GetNativeWindow(); - case NS_NATIVE_OPENGL_CONTEXT: - return mScreen->GetGLContext().take(); - case NS_RAW_NATIVE_IME_CONTEXT: { - void* pseudoIMEContext = GetPseudoIMEContext(); - if (pseudoIMEContext) { - return pseudoIMEContext; - } - // There is only one IME context on Gonk. - return NS_ONLY_ONE_NATIVE_IME_CONTEXT; - } - } - - return nullptr; -} - -void -nsWindow::SetNativeData(uint32_t aDataType, uintptr_t aVal) -{ - switch (aDataType) { - case NS_NATIVE_OPENGL_CONTEXT: - GLContext* context = reinterpret_cast<GLContext*>(aVal); - if (!context) { - mScreen->SetEGLInfo(EGL_NO_DISPLAY, - EGL_NO_SURFACE, - nullptr); - return; - } - mScreen->SetEGLInfo(GLContextEGL::Cast(context)->GetEGLDisplay(), - GLContextEGL::Cast(context)->GetEGLSurface(), - context); - return; - } -} - -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() -{ - return mInputContext; -} - -nsresult -nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen*) -{ - if (mWindowType != eWindowType_toplevel) { - // Ignore fullscreen request for non-toplevel windows. - NS_WARNING("MakeFullScreen() on a dialog or child widget?"); - nsBaseWidget::InfallibleMakeFullScreen(aFullScreen); - return NS_OK; - } - - 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. - nsIntRect virtualBounds; - mScreen->GetRect(&virtualBounds.x, &virtualBounds.y, - &virtualBounds.width, &virtualBounds.height); - Resize(virtualBounds.x, virtualBounds.y, - virtualBounds.width, virtualBounds.height, - /*repaint*/true); - } - - if (nsIWidgetListener* listener = GetWidgetListener()) { - listener->FullscreenChanged(aFullScreen); - } - return NS_OK; -} - -already_AddRefed<DrawTarget> -nsWindow::StartRemoteDrawing() -{ - RefPtr<DrawTarget> buffer = mScreen->StartRemoteDrawing(); - return buffer.forget(); -} - -void -nsWindow::EndRemoteDrawing() -{ - mScreen->EndRemoteDrawing(); -} - -float -nsWindow::GetDPI() -{ - return mScreen->GetDpi(); -} - -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. - } - // xhdpi devices and beyond. - return floor(dpi / 150.0 + 0.5); -} - -LayerManager * -nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager, - LayersBackend aBackendHint, - LayerManagerPersistence aPersistence) -{ - if (mLayerManager) { - // This layer manager might be used for painting outside of DoDraw(), so we need - // to set the correct rotation on it. - if (ClientLayerManager* manager = mLayerManager->AsClientLayerManager()) { - uint32_t rotation = mScreen->EffectiveScreenRotation(); - manager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE, - ScreenRotation(rotation)); - } - return mLayerManager; - } - - const nsTArray<nsWindow*>& windows = mScreen->GetTopWindows(); - nsWindow *topWindow = windows[0]; - - if (!topWindow) { - LOGW(" -- no topwindow\n"); - return nullptr; - } - - CreateCompositor(); - if (RefPtr<CompositorBridgeParent> bridge = GetCompositorBridgeParent()) { - mScreen->SetCompositorBridgeParent(bridge); - if (mScreen->IsPrimaryScreen()) { - mComposer2D->SetCompositorBridgeParent(bridge); - } - } - MOZ_ASSERT(mLayerManager); - return mLayerManager; -} - -void -nsWindow::DestroyCompositor() -{ - if (RefPtr<CompositorBridgeParent> bridge = GetCompositorBridgeParent()) { - mScreen->SetCompositorBridgeParent(nullptr); - if (mScreen->IsPrimaryScreen()) { - // Unset CompositorBridgeParent - mComposer2D->SetCompositorBridgeParent(nullptr); - } - } - nsBaseWidget::DestroyCompositor(); -} - -void -nsWindow::BringToTop() -{ - const nsTArray<nsWindow*>& windows = mScreen->GetTopWindows(); - if (!windows.IsEmpty()) { - if (nsIWidgetListener* listener = windows[0]->GetWidgetListener()) { - listener->WindowDeactivated(); - } - } - - mScreen->BringToTop(this); - - if (mWidgetListener) { - mWidgetListener->WindowActivated(); - } - - Invalidate(mBounds); -} - -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::LayersBackend::LAYERS_OPENGL) { - // We directly map the hardware fb on Gonk. The hardware fb - // has RGB format. - return LOCAL_GL_RGB; - } - return LOCAL_GL_NONE; -} - -LayoutDeviceIntRect -nsWindow::GetNaturalBounds() -{ - return mScreen->GetNaturalBounds(); -} - -nsScreenGonk* -nsWindow::GetScreen() -{ - return mScreen; -} - -bool -nsWindow::NeedsPaint() -{ - if (!mLayerManager) { - return false; - } - return nsIWidget::NeedsPaint(); -} - -Composer2D* -nsWindow::GetComposer2D() -{ - if (mScreen->GetDisplayType() == GonkDisplay::DISPLAY_VIRTUAL) { - return nullptr; - } - - return mComposer2D; -} - -CompositorBridgeParent* -nsWindow::GetCompositorBridgeParent() const -{ - return mCompositorSession ? mCompositorSession->GetInProcessBridge() : nullptr; -} |