summaryrefslogtreecommitdiffstats
path: root/widget/gonk/nsWindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'widget/gonk/nsWindow.cpp')
-rw-r--r--widget/gonk/nsWindow.cpp744
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;
-}