On WIN32, process pending PL_Events and paints after mouse and keyboard events to eliminate starvation of reflow and paints bug 163528 r=rods@netscape.com sr=kin@netscape.com

This commit is contained in:
kmcclusk%netscape.com 2002-09-28 15:04:47 +00:00
parent e28f216899
commit b515157170
4 changed files with 69 additions and 16 deletions

View File

@ -40,6 +40,9 @@
#include "prmon.h"
#include "prtime.h"
#include "nsGUIEvent.h"
#include "nsIServiceManager.h"
#include "nsIEventQueueService.h"
#include "nsIEventQueue.h"
#ifdef MOZ_AIMM
#include <initguid.h>
#include "aimm.h"
@ -63,6 +66,11 @@ NS_RegisterClass nsToolkit::mRegisterClass = &RegisterClassW;
#endif
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
// Cached reference to event queue service
static nsCOMPtr<nsIEventQueueService> gEventQueueService;
NS_IMPL_ISUPPORTS1(nsToolkit, nsIToolkit)
//
@ -438,6 +446,9 @@ nsToolkit::~nsToolkit()
// Remove the TLS reference to the toolkit...
PR_SetThreadPrivate(gToolkitTLSIndex, nsnull);
// Remove reference to cached event queue
gEventQueueService = nsnull;
#ifdef MOZ_STATIC_COMPONENT_LIBS
nsToolkit::Shutdown();
#endif
@ -536,6 +547,23 @@ nsToolkit::Shutdown()
::UnregisterClass("nsToolkitClass", nsToolkit::mDllInstance);
}
nsIEventQueue*
nsToolkit::GetEventQueue()
{
if (! gEventQueueService) {
gEventQueueService = do_GetService(kEventQueueServiceCID);
}
if (gEventQueueService) {
nsCOMPtr<nsIEventQueue> eventQueue;
gEventQueueService->GetSpecialEventQueue(
nsIEventQueueService::UI_THREAD_EVENT_QUEUE,
getter_AddRefs(eventQueue));
return eventQueue;
}
return nsnull;
}
//-------------------------------------------------------------------------
//

View File

@ -50,6 +50,8 @@ struct IActiveIMMApp;
#endif
struct MethodInfo;
class nsIEventQueue;
/**
* Wrapper around the thread running the message pump.
@ -72,6 +74,7 @@ class nsToolkit : public nsIToolkit
PRThread* GetGuiThread(void) { return mGuiThread; }
HWND GetDispatchWindow(void) { return mDispatchWnd; }
void CreateInternalWindow(PRThread *aThread);
nsIEventQueue* GetEventQueue(void);
private:
~nsToolkit();

View File

@ -63,6 +63,7 @@
#include "nsIScreenManager.h"
#include "nsRect.h"
#include "nsTransform2D.h"
#include "nsIEventQueue.h"
#include <windows.h>
//#include <winuser.h>
@ -3581,14 +3582,28 @@ BOOL CALLBACK nsWindow::DispatchStarvedPaints(HWND aWnd, LPARAM aMsg)
return TRUE;
}
// Check for starved paints and dispatch any pending paint
// Check for pending paints and dispatch any pending paint
// messages for any nsIWidget which is a descendant of the
// top-level window that *this* window is embedded within.
// Note: We do not dispatch pending messages for non nsIWidget
// managed windows.
// Also dispatch pending PL_Events to avoid PL_EventQueue starvation.
// Note: We do not dispatch pending paint messages for non
// nsIWidget managed windows.
void nsWindow::CheckForStarvedPaints()
void nsWindow::DispatchPendingEvents()
{
// Need to flush all pending PL_Events before
// painting to prevent reflow events from being starved.
// Note: Unfortunately, The flushing of PL_Events can not done by
// dispatching the native WM_TIMER event that is used for PL_Event
// notification because the timer message will not appear in the
// native msg queue until 10ms after the event is posted. Which is too late.
nsCOMPtr<nsIEventQueue> eventQueue;
nsToolkit *toolkit = NS_STATIC_CAST(nsToolkit *, mToolkit);
eventQueue = toolkit->GetEventQueue();
if (eventQueue) {
eventQueue->ProcessPendingEvents();
}
// Quickly check to see if there are any
// paint events pending.
if (::GetQueueStatus(QS_PAINT)) {
@ -3790,7 +3805,6 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
printf("%s\t\twp=%x\tlp=%x\n",
(WM_KEYUP==msg)?"WM_KEYUP":"WM_SYSKEYUP" , wParam, lParam);
#endif
CheckForStarvedPaints();
mIsShiftDown = IS_VK_DOWN(NS_VK_SHIFT);
if(WM_SYSKEYUP==msg)
{
@ -3817,6 +3831,7 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
// ignore [shift+]alt+space so the OS can handle it
if (mIsAltDown && !mIsControlDown && IS_VK_DOWN(NS_VK_SPACE)) {
result = PR_FALSE;
DispatchPendingEvents();
break;
}
@ -3824,6 +3839,8 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
result = OnKeyUp(wParam, (HIWORD(lParam)), lParam);
else
result = PR_FALSE;
DispatchPendingEvents();
break;
// Let ths fall through if it isn't a key pad
@ -3833,7 +3850,6 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
printf("%s\t\twp=%4x\tlp=%8x\n",
(WM_KEYDOWN==msg)?"WM_KEYDOWN":"WM_SYSKEYDOWN" , wParam, lParam);
#endif
CheckForStarvedPaints();
mIsShiftDown = IS_VK_DOWN(NS_VK_SHIFT);
if(WM_SYSKEYDOWN==msg)
@ -3860,6 +3876,7 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
// ignore [shift+]alt+space so the OS can handle it
if (mIsAltDown && !mIsControlDown && IS_VK_DOWN(NS_VK_SPACE)) {
result = PR_FALSE;
DispatchPendingEvents();
break;
}
@ -3884,6 +3901,7 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
result = PR_TRUE;
*aRetValue = 0;
}
DispatchPendingEvents();
break;
// say we've dealt with erase background if widget does
@ -3903,20 +3921,24 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
case WM_MOUSEMOVE:
//RelayMouseEvent(msg,wParam, lParam);
// Suppress synchronous painting of starved paint
// events when mouse moves are generated by widget
// Suppress dispatch of pending events
// when mouse moves are generated by widget
// creation instead of user input.
{
POINT mp;
DWORD pos = ::GetMessagePos();
mp.x = (short)LOWORD(pos);
mp.y = (short)HIWORD(pos);
PRBool userMovedMouse = PR_FALSE;
if ((gLastMouseMovePoint.x != mp.x) ||
(gLastMouseMovePoint.y != mp.y)) {
CheckForStarvedPaints();
userMovedMouse = PR_TRUE;
}
result = DispatchMouseEvent(NS_MOUSE_MOVE, wParam);
if (userMovedMouse) {
DispatchPendingEvents();
}
}
break;
@ -3935,14 +3957,14 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
break;
}
#endif
CheckForStarvedPaints();
result = DispatchMouseEvent(NS_MOUSE_LEFT_BUTTON_DOWN, wParam);
DispatchPendingEvents();
} break;
case WM_LBUTTONUP:
//RelayMouseEvent(msg,wParam, lParam);
CheckForStarvedPaints();
result = DispatchMouseEvent(NS_MOUSE_LEFT_BUTTON_UP, wParam);
DispatchPendingEvents();
break;
case WM_CONTEXTMENU:
@ -3971,13 +3993,13 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
break;
}
#endif
CheckForStarvedPaints();
result = DispatchMouseEvent(NS_MOUSE_MIDDLE_BUTTON_DOWN, wParam);
DispatchPendingEvents();
} break;
case WM_MBUTTONUP:
CheckForStarvedPaints();
result = DispatchMouseEvent(NS_MOUSE_MIDDLE_BUTTON_UP, wParam);
DispatchPendingEvents();
break;
case WM_MBUTTONDBLCLK:
@ -3997,13 +4019,13 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT
break;
}
#endif
CheckForStarvedPaints();
result = DispatchMouseEvent(NS_MOUSE_RIGHT_BUTTON_DOWN, wParam);
DispatchPendingEvents();
} break;
case WM_RBUTTONUP:
CheckForStarvedPaints();
result = DispatchMouseEvent(NS_MOUSE_RIGHT_BUTTON_UP, wParam);
DispatchPendingEvents();
break;
case WM_RBUTTONDBLCLK:

View File

@ -401,7 +401,7 @@ protected:
static nsWindow * GetNSWindowPtr(HWND aWnd);
static BOOL SetNSWindowPtr(HWND aWnd, nsWindow * ptr);
void CheckForStarvedPaints();
void DispatchPendingEvents();
virtual PRBool ProcessMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *aRetValue);
virtual PRBool DispatchWindowEvent(nsGUIEvent* event);
virtual PRBool DispatchWindowEvent(nsGUIEvent*event, nsEventStatus &aStatus);