зеркало из https://github.com/mozilla/gecko-dev.git
Bug 506815 - Replace MouseTrailer with TrackMouseEvent. r=jimm
MouseTrailer, using a 200ms timer, was used to track whether a pointer was still present over a window. Windows has, since Windows 2000, offered to do this for us via an API called TrackMouseEvent. (It'll also give us hover timings and non-client area versions if we want) I'm all for having Windows do the work for us, and it'll save us from waking up the main thread five times a second. --HG-- extra : rebase_source : 9e56fd40929257d847c5cddb8a998c3ca2381655
This commit is contained in:
Родитель
22151cf459
Коммит
53663750f7
|
@ -23,7 +23,6 @@ using namespace mozilla::widget;
|
|||
|
||||
nsToolkit* nsToolkit::gToolkit = nullptr;
|
||||
HINSTANCE nsToolkit::mDllInstance = 0;
|
||||
MouseTrailer* nsToolkit::gMouseTrailer;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -37,8 +36,6 @@ nsToolkit::nsToolkit()
|
|||
#if defined(MOZ_STATIC_COMPONENT_LIBS)
|
||||
nsToolkit::Startup(GetModuleHandle(nullptr));
|
||||
#endif
|
||||
|
||||
gMouseTrailer = &mMouseTrailer;
|
||||
}
|
||||
|
||||
|
||||
|
@ -50,7 +47,6 @@ nsToolkit::nsToolkit()
|
|||
nsToolkit::~nsToolkit()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsToolkit);
|
||||
gMouseTrailer = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -83,126 +79,3 @@ nsToolkit* nsToolkit::GetToolkit()
|
|||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,41 +20,6 @@
|
|||
#define GET_Y_LPARAM(pt) (short(HIWORD(pt)))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Makes sure exit/enter mouse messages are always dispatched.
|
||||
* In the case where the mouse has exited the outer most window the
|
||||
* only way to tell if it has exited is to set a timer and look at the
|
||||
* mouse pointer to see if it is within the outer most window.
|
||||
*/
|
||||
|
||||
class MouseTrailer
|
||||
{
|
||||
public:
|
||||
HWND GetMouseTrailerWindow() { return mMouseTrailerWindow; }
|
||||
HWND GetCaptureWindow() { return mCaptureWindow; }
|
||||
|
||||
void SetMouseTrailerWindow(HWND aWnd);
|
||||
void SetCaptureWindow(HWND aWnd);
|
||||
void Disable() { mEnabled = false; DestroyTimer(); }
|
||||
void Enable() { mEnabled = true; CreateTimer(); }
|
||||
void DestroyTimer();
|
||||
|
||||
MouseTrailer();
|
||||
~MouseTrailer();
|
||||
private:
|
||||
|
||||
nsresult CreateTimer();
|
||||
|
||||
static void TimerProc(nsITimer* aTimer, void* aClosure);
|
||||
|
||||
// Information for mouse enter/exit events
|
||||
HWND mMouseTrailerWindow;
|
||||
HWND mCaptureWindow;
|
||||
bool mIsInCaptureMode;
|
||||
bool mEnabled;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrapper around the thread running the message pump.
|
||||
* The toolkit abstraction is necessary because the message pump must
|
||||
|
@ -73,15 +38,12 @@ public:
|
|||
static nsToolkit* GetToolkit();
|
||||
|
||||
static HINSTANCE mDllInstance;
|
||||
static MouseTrailer *gMouseTrailer;
|
||||
|
||||
static void Startup(HMODULE hModule);
|
||||
static void Shutdown();
|
||||
|
||||
protected:
|
||||
static nsToolkit* gToolkit;
|
||||
|
||||
MouseTrailer mMouseTrailer;
|
||||
};
|
||||
|
||||
#endif // TOOLKIT_H
|
||||
|
|
|
@ -3381,16 +3381,9 @@ NS_METHOD nsWindow::EnableDragDrop(bool aEnable)
|
|||
|
||||
NS_METHOD nsWindow::CaptureMouse(bool aCapture)
|
||||
{
|
||||
if (!nsToolkit::gMouseTrailer) {
|
||||
NS_ERROR("nsWindow::CaptureMouse called after nsToolkit destroyed");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aCapture) {
|
||||
nsToolkit::gMouseTrailer->SetCaptureWindow(mWnd);
|
||||
::SetCapture(mWnd);
|
||||
} else {
|
||||
nsToolkit::gMouseTrailer->SetCaptureWindow(nullptr);
|
||||
::ReleaseCapture();
|
||||
}
|
||||
sIsInMouseCapture = aCapture;
|
||||
|
@ -4200,12 +4193,7 @@ nsWindow::DispatchMouseEvent(EventMessage aEventMessage, WPARAM wParam,
|
|||
|
||||
// call the event callback
|
||||
if (mWidgetListener) {
|
||||
if (nsToolkit::gMouseTrailer)
|
||||
nsToolkit::gMouseTrailer->Disable();
|
||||
if (aEventMessage == eMouseMove) {
|
||||
if (nsToolkit::gMouseTrailer && !sIsInMouseCapture) {
|
||||
nsToolkit::gMouseTrailer->SetMouseTrailerWindow(mWnd);
|
||||
}
|
||||
LayoutDeviceIntRect rect;
|
||||
GetBounds(rect);
|
||||
rect.x = 0;
|
||||
|
@ -4238,9 +4226,6 @@ nsWindow::DispatchMouseEvent(EventMessage aEventMessage, WPARAM wParam,
|
|||
|
||||
result = ConvertStatus(DispatchAPZAwareEvent(&event));
|
||||
|
||||
if (nsToolkit::gMouseTrailer)
|
||||
nsToolkit::gMouseTrailer->Enable();
|
||||
|
||||
// Release the widget with NS_IF_RELEASE() just in case
|
||||
// the context menu key code in EventListenerManager::HandleEvent()
|
||||
// released it already.
|
||||
|
@ -5093,6 +5078,15 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
|||
|
||||
case WM_MOUSEMOVE:
|
||||
{
|
||||
if (!mMousePresent) {
|
||||
// First MOOUSEMOVE over the client area. Ask for MOUSELEAVE
|
||||
TRACKMOUSEEVENT mTrack;
|
||||
mTrack.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||
mTrack.dwFlags = TME_LEAVE;
|
||||
mTrack.dwHoverTime = 0;
|
||||
mTrack.hwndTrack = mWnd;
|
||||
TrackMouseEvent(&mTrack);
|
||||
}
|
||||
mMousePresent = true;
|
||||
|
||||
// Suppress dispatch of pending events
|
||||
|
@ -6685,23 +6679,12 @@ void nsWindow::OnDestroy()
|
|||
|
||||
IMEHandler::OnDestroyWindow(this);
|
||||
|
||||
// Turn off mouse trails if enabled.
|
||||
MouseTrailer* mtrailer = nsToolkit::gMouseTrailer;
|
||||
if (mtrailer) {
|
||||
if (mtrailer->GetMouseTrailerWindow() == mWnd)
|
||||
mtrailer->DestroyTimer();
|
||||
|
||||
if (mtrailer->GetCaptureWindow() == mWnd)
|
||||
mtrailer->SetCaptureWindow(nullptr);
|
||||
}
|
||||
|
||||
// Free GDI window class objects
|
||||
if (mBrush) {
|
||||
VERIFY(::DeleteObject(mBrush));
|
||||
mBrush = nullptr;
|
||||
}
|
||||
|
||||
|
||||
// Destroy any custom cursor resources.
|
||||
if (mCursor == -1)
|
||||
SetCursor(eCursor_standard);
|
||||
|
|
Загрузка…
Ссылка в новой задаче