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