diff -r 000000000000 -r 6474c204b198 widget/windows/nsToolkit.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/widget/windows/nsToolkit.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,235 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsToolkit.h" +#include "nsAppShell.h" +#include "nsWindow.h" +#include "nsWidgetsCID.h" +#include "prmon.h" +#include "prtime.h" +#include "nsIServiceManager.h" +#include "nsComponentManagerUtils.h" +#include +#include "WinUtils.h" + +#include "nsUXThemeData.h" + +// unknwn.h is needed to build with WIN32_LEAN_AND_MEAN +#include + +using namespace mozilla::widget; + +nsToolkit* nsToolkit::gToolkit = nullptr; +HINSTANCE nsToolkit::mDllInstance = 0; +static const unsigned long kD3DUsageDelay = 5000; + +static void +StartAllowingD3D9(nsITimer *aTimer, void *aClosure) +{ + if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) { + nsWindow::StartAllowingD3D9(true); + } +} + +MouseTrailer* nsToolkit::gMouseTrailer; + +//------------------------------------------------------------------------- +// +// constructor +// +//------------------------------------------------------------------------- +nsToolkit::nsToolkit() +{ + MOZ_COUNT_CTOR(nsToolkit); + +#if defined(MOZ_STATIC_COMPONENT_LIBS) + nsToolkit::Startup(GetModuleHandle(nullptr)); +#endif + + gMouseTrailer = &mMouseTrailer; + + if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) { + mD3D9Timer = do_CreateInstance("@mozilla.org/timer;1"); + mD3D9Timer->InitWithFuncCallback(::StartAllowingD3D9, + nullptr, + kD3DUsageDelay, + nsITimer::TYPE_ONE_SHOT); + } +} + + +//------------------------------------------------------------------------- +// +// destructor +// +//------------------------------------------------------------------------- +nsToolkit::~nsToolkit() +{ + MOZ_COUNT_DTOR(nsToolkit); + gMouseTrailer = nullptr; +} + +void +nsToolkit::Startup(HMODULE hModule) +{ + nsToolkit::mDllInstance = hModule; + WinUtils::Initialize(); + nsUXThemeData::Initialize(); +} + +void +nsToolkit::Shutdown() +{ + delete gToolkit; + gToolkit = nullptr; +} + +void +nsToolkit::StartAllowingD3D9() +{ + if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) { + nsToolkit::GetToolkit()->mD3D9Timer->Cancel(); + nsWindow::StartAllowingD3D9(false); + } +} + +//------------------------------------------------------------------------- +// +// Return the nsToolkit for the current thread. If a toolkit does not +// yet exist, then one will be created... +// +//------------------------------------------------------------------------- +// static +nsToolkit* nsToolkit::GetToolkit() +{ + if (!gToolkit) { + gToolkit = new nsToolkit(); + } + + return gToolkit; +} + + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +MouseTrailer::MouseTrailer() : mMouseTrailerWindow(nullptr), mCaptureWindow(nullptr), + mIsInCaptureMode(false), mEnabled(true) +{ +} +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +MouseTrailer::~MouseTrailer() +{ + DestroyTimer(); +} +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +void MouseTrailer::SetMouseTrailerWindow(HWND aWnd) +{ + if (mMouseTrailerWindow != aWnd && mTimer) { + // Make sure TimerProc is fired at least once for the old window + TimerProc(nullptr, nullptr); + } + mMouseTrailerWindow = aWnd; + CreateTimer(); +} + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +void MouseTrailer::SetCaptureWindow(HWND aWnd) +{ + mCaptureWindow = aWnd; + if (mCaptureWindow) { + mIsInCaptureMode = true; + } +} + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +nsresult MouseTrailer::CreateTimer() +{ + if (mTimer || !mEnabled) { + return NS_OK; + } + + nsresult rv; + mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + return mTimer->InitWithFuncCallback(TimerProc, nullptr, 200, + nsITimer::TYPE_REPEATING_SLACK); +} + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +void MouseTrailer::DestroyTimer() +{ + if (mTimer) { + mTimer->Cancel(); + mTimer = nullptr; + } +} + +//------------------------------------------------------------------------- +// +// +//------------------------------------------------------------------------- +void MouseTrailer::TimerProc(nsITimer* aTimer, void* aClosure) +{ + MouseTrailer *mtrailer = nsToolkit::gMouseTrailer; + NS_ASSERTION(mtrailer, "MouseTrailer still firing after deletion!"); + + // Check to see if we are in mouse capture mode, + // Once capture ends we could still get back one more timer event. + // Capture could end outside our window. + // Also, for some reason when the mouse is on the frame it thinks that + // it is inside the window that is being captured. + if (mtrailer->mCaptureWindow) { + if (mtrailer->mCaptureWindow != mtrailer->mMouseTrailerWindow) { + return; + } + } else { + if (mtrailer->mIsInCaptureMode) { + // mMouseTrailerWindow could be bad from rolling over the frame, so clear + // it if we were capturing and now this is the first timer callback + // since we canceled the capture + mtrailer->mMouseTrailerWindow = nullptr; + mtrailer->mIsInCaptureMode = false; + return; + } + } + + if (mtrailer->mMouseTrailerWindow && ::IsWindow(mtrailer->mMouseTrailerWindow)) { + POINT mp; + DWORD pos = ::GetMessagePos(); + mp.x = GET_X_LPARAM(pos); + mp.y = GET_Y_LPARAM(pos); + HWND mouseWnd = ::WindowFromPoint(mp); + if (mtrailer->mMouseTrailerWindow != mouseWnd) { + // Notify someone that a mouse exit happened. + PostMessage(mtrailer->mMouseTrailerWindow, WM_MOUSELEAVE, 0, 0); + + // we are out of this window, destroy timer + mtrailer->DestroyTimer(); + mtrailer->mMouseTrailerWindow = nullptr; + } + } else { + mtrailer->DestroyTimer(); + mtrailer->mMouseTrailerWindow = nullptr; + } +} +