зеркало из https://github.com/mozilla/pjs.git
Bug #67370. Better interleaving of xlib + plevents. r=danm sr=shaver
This commit is contained in:
Родитель
a3dcfdcd14
Коммит
2bb54a9dae
|
@ -30,6 +30,7 @@
|
|||
#include "nsICmdLineService.h"
|
||||
#include "nsGtkEventHandler.h"
|
||||
#include <stdlib.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#ifdef MOZ_GLE
|
||||
#include <gle/gle.h>
|
||||
|
@ -39,10 +40,12 @@
|
|||
#include "nsIPref.h"
|
||||
|
||||
#include "glib.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
static PRBool sInitialized = PR_FALSE;
|
||||
static PLHashTable *sQueueHashTable = nsnull;
|
||||
static PLHashTable *sCountHashTable = nsnull;
|
||||
static nsVoidArray *sEventQueueList = nsnull;
|
||||
|
||||
struct OurGdkIOClosure {
|
||||
GdkInputFunction function;
|
||||
|
@ -97,6 +100,11 @@ our_gdk_input_add (gint source,
|
|||
return result;
|
||||
}
|
||||
|
||||
// wrapper so we can call a macro
|
||||
static unsigned long getNextRequest (void *aClosure) {
|
||||
return NextRequest(GDK_DISPLAY());
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -119,6 +127,8 @@ nsAppShell::nsAppShell()
|
|||
#ifdef DEBUG_APPSHELL
|
||||
printf("nsAppShell::nsAppShell()\n");
|
||||
#endif
|
||||
if (!sEventQueueList)
|
||||
sEventQueueList = new nsVoidArray();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -426,6 +436,10 @@ NS_IMETHODIMP nsAppShell::ListenToEventQueue(nsIEventQueue *aQueue,
|
|||
if (tag >= 0) {
|
||||
PL_HashTableAdd(sQueueHashTable, GINT_TO_POINTER(key), GINT_TO_POINTER(tag));
|
||||
}
|
||||
PLEventQueue *plqueue;
|
||||
aQueue->GetPLEventQueue(&plqueue);
|
||||
PL_RegisterEventIDFunc(plqueue, getNextRequest, 0);
|
||||
sEventQueueList->AppendElement(plqueue);
|
||||
}
|
||||
/* bump up the count */
|
||||
gint count = GPOINTER_TO_INT(PL_HashTableLookup(sCountHashTable, GINT_TO_POINTER(key)));
|
||||
|
@ -433,6 +447,11 @@ NS_IMETHODIMP nsAppShell::ListenToEventQueue(nsIEventQueue *aQueue,
|
|||
} else {
|
||||
/* remove listener */
|
||||
PRInt32 key = aQueue->GetEventQueueSelectFD();
|
||||
|
||||
PLEventQueue *plqueue;
|
||||
aQueue->GetPLEventQueue(&plqueue);
|
||||
PL_UnregisterEventIDFunc(plqueue);
|
||||
sEventQueueList->RemoveElement(plqueue);
|
||||
|
||||
gint count = GPOINTER_TO_INT(PL_HashTableLookup(sCountHashTable, GINT_TO_POINTER(key)));
|
||||
if (count - 1 == 0) {
|
||||
|
@ -449,3 +468,16 @@ NS_IMETHODIMP nsAppShell::ListenToEventQueue(nsIEventQueue *aQueue,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool processQueue(void *aElement, void *aData)
|
||||
{
|
||||
PLEventQueue *queue = NS_STATIC_CAST(PLEventQueue *, aElement);
|
||||
unsigned int id = (unsigned int)aData;
|
||||
PL_ProcessEventsBeforeID(queue, id);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nsAppShell::ProcessBeforeID(unsigned long aID)
|
||||
{
|
||||
sEventQueueList->EnumerateForwards(processQueue, (void *)aID);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ public:
|
|||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIAPPSHELL
|
||||
|
||||
static void ProcessBeforeID(unsigned long aID);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIEventQueue> mEventQueue;
|
||||
};
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "nsWidget.h"
|
||||
#include "keysym2ucs.h"
|
||||
#include "nsWindow.h"
|
||||
#include "nsAppShell.h"
|
||||
|
||||
#include "nsScrollbar.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
@ -776,6 +777,13 @@ handle_gdk_event (GdkEvent *event, gpointer data)
|
|||
if (event_time)
|
||||
nsWidget::SetLastEventTime(event_time);
|
||||
|
||||
// process any pending events first
|
||||
if (XPending(GDK_DISPLAY())) {
|
||||
XEvent temp_event;
|
||||
XPeekEvent(GDK_DISPLAY(), &temp_event);
|
||||
nsAppShell::ProcessBeforeID(temp_event.xany.serial - 1);
|
||||
}
|
||||
|
||||
// try to get the user data for the event window.
|
||||
if (event->any.window)
|
||||
gdk_window_get_user_data (event->any.window, (void **)&object);
|
||||
|
|
|
@ -103,6 +103,8 @@ struct PLEventQueue {
|
|||
int efn;
|
||||
#elif defined(XP_UNIX)
|
||||
PRInt32 eventPipe[2];
|
||||
PLGetEventIDFunc idFunc;
|
||||
void *idFuncClosure;
|
||||
#elif defined(_WIN32) || defined(WIN16) || defined(XP_OS2)
|
||||
HWND eventReceiverWindow;
|
||||
PRBool removeMsg;
|
||||
|
@ -246,6 +248,9 @@ PL_PostEvent(PLEventQueue* self, PLEvent* event)
|
|||
mon = self->monitor;
|
||||
PR_EnterMonitor(mon);
|
||||
|
||||
if (self->idFunc && event)
|
||||
event->id = self->idFunc(self->idFuncClosure);
|
||||
|
||||
/* insert event into thread's event queue: */
|
||||
if (event != NULL) {
|
||||
PR_APPEND_LINK(&event->link, &self->queue);
|
||||
|
@ -555,6 +560,7 @@ PL_InitEvent(PLEvent* self, void* owner,
|
|||
PR_ASSERT(self->lock);
|
||||
self->condVar = PR_NewCondVar(self->lock);
|
||||
PR_ASSERT(self->condVar);
|
||||
self->id = 0;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void*)
|
||||
|
@ -569,7 +575,7 @@ PL_HandleEvent(PLEvent* self)
|
|||
void* result;
|
||||
if (self == NULL)
|
||||
return;
|
||||
|
||||
|
||||
/* This event better not be on an event queue anymore. */
|
||||
PR_ASSERT(PR_CLIST_IS_EMPTY(&self->link));
|
||||
|
||||
|
@ -725,6 +731,9 @@ _pl_SetupNativeNotifier(PLEventQueue* self)
|
|||
int err;
|
||||
int flags;
|
||||
|
||||
self->idFunc = 0;
|
||||
self->idFuncClosure = 0;
|
||||
|
||||
err = pipe(self->eventPipe);
|
||||
if (err != 0) {
|
||||
return PR_FAILURE;
|
||||
|
@ -1187,4 +1196,103 @@ static void _md_CreateEventQueue( PLEventQueue *eventQueue )
|
|||
return;
|
||||
} /* end _md_CreateEventQueue() */
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
/* extra functions for unix */
|
||||
|
||||
#ifdef XP_UNIX
|
||||
|
||||
PR_IMPLEMENT(PRInt32)
|
||||
PL_ProcessEventsBeforeID(PLEventQueue *aSelf, unsigned long aID)
|
||||
{
|
||||
PRInt32 count = 0;
|
||||
PRInt32 fullCount;
|
||||
|
||||
if (aSelf == NULL)
|
||||
return -1;
|
||||
|
||||
PR_EnterMonitor(aSelf->monitor);
|
||||
|
||||
if (aSelf->processingEvents) {
|
||||
PR_ExitMonitor(aSelf->monitor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
aSelf->processingEvents = PR_TRUE;
|
||||
|
||||
/* Only process the events that are already in the queue, and
|
||||
* not any new events that get added. Do this by counting the
|
||||
* number of events currently in the queue
|
||||
*/
|
||||
fullCount = _pl_GetEventCount(aSelf);
|
||||
PR_LOG(event_lm, PR_LOG_DEBUG,
|
||||
("$$$ fullCount is %d id is %ld\n", fullCount, aID));
|
||||
|
||||
if (fullCount == 0) {
|
||||
aSelf->processingEvents = PR_FALSE;
|
||||
PR_ExitMonitor(aSelf->monitor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
PR_ExitMonitor(aSelf->monitor);
|
||||
|
||||
while(fullCount-- > 0) {
|
||||
/* peek at the next event */
|
||||
PLEvent *event;
|
||||
event = PR_EVENT_PTR(aSelf->queue.next);
|
||||
if (event == NULL)
|
||||
break;
|
||||
PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ processing event %ld\n",
|
||||
event->id));
|
||||
if (event->id < aID) {
|
||||
event = PL_GetEvent(aSelf);
|
||||
PL_HandleEvent(event);
|
||||
PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ done processing event"));
|
||||
count++;
|
||||
}
|
||||
else {
|
||||
PR_LOG(event_lm, PR_LOG_DEBUG, ("$$$ skipping event and breaking"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PR_EnterMonitor(aSelf->monitor);
|
||||
|
||||
/* if full count still had items left then there's still items left
|
||||
in the queue. Let the native notify token stay. */
|
||||
|
||||
if (aSelf->type == EventQueueIsNative)
|
||||
{
|
||||
fullCount = _pl_GetEventCount(aSelf);
|
||||
|
||||
if (fullCount <= 0)
|
||||
{
|
||||
_pl_AcknowledgeNativeNotify(aSelf);
|
||||
aSelf->notified = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
aSelf->processingEvents = PR_FALSE;
|
||||
|
||||
PR_ExitMonitor(aSelf->monitor);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_RegisterEventIDFunc(PLEventQueue *aSelf, PLGetEventIDFunc aFunc,
|
||||
void *aClosure)
|
||||
{
|
||||
aSelf->idFunc = aFunc;
|
||||
aSelf->idFuncClosure = aClosure;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PL_UnregisterEventIDFunc(PLEventQueue *aSelf)
|
||||
{
|
||||
aSelf->idFunc = 0;
|
||||
aSelf->idFuncClosure = 0;
|
||||
}
|
||||
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
/* --- end plevent.c --- */
|
||||
|
|
|
@ -473,6 +473,9 @@ struct PLEvent {
|
|||
#ifdef PL_POST_TIMINGS
|
||||
PRIntervalTime postTime;
|
||||
#endif
|
||||
#ifdef XP_UNIX
|
||||
unsigned long id;
|
||||
#endif /* XP_UNIX */
|
||||
/* other fields follow... */
|
||||
};
|
||||
|
||||
|
@ -507,6 +510,78 @@ PR_EXTERN(HWND)
|
|||
|
||||
#endif /* XP_PC */
|
||||
|
||||
#ifdef XP_UNIX
|
||||
/* -----------------------------------------------------------------------
|
||||
** FUNCTION: PL_ProcessEventsBeforeID()
|
||||
**
|
||||
** DESCRIPTION:
|
||||
**
|
||||
** PL_ProcessEventsBeforeID() will process events in a native event
|
||||
** queue that have an id that is older than the ID passed in.
|
||||
**
|
||||
** INPUTS:
|
||||
** PLEventQueue *aSelf
|
||||
** unsigned long aID
|
||||
**
|
||||
** RETURNS:
|
||||
** PRInt32 number of requests processed, -1 on error.
|
||||
**
|
||||
** RESTRICTIONS: Unix only (well, X based unix only)
|
||||
*/
|
||||
PR_EXTERN(PRInt32)
|
||||
PL_ProcessEventsBeforeID(PLEventQueue *aSelf, unsigned long aID);
|
||||
|
||||
/* This prototype is a function that can be called when an event is
|
||||
posted to stick an ID on it. */
|
||||
|
||||
typedef unsigned long
|
||||
(PR_CALLBACK *PLGetEventIDFunc)(void *aClosure);
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
** FUNCTION: PL_RegisterEventIDFunc()
|
||||
**
|
||||
** DESCRIPTION:
|
||||
**
|
||||
** This function registers a function for getting the ID on unix for
|
||||
** this event queue.
|
||||
**
|
||||
** INPUTS:
|
||||
** PLEventQueue *aSelf
|
||||
** PLGetEventIDFunc func
|
||||
** void *aClosure
|
||||
**
|
||||
** RETURNS:
|
||||
** void
|
||||
**
|
||||
** RESTRICTIONS: Unix only (well, X based unix only) */
|
||||
PR_EXTERN(void)
|
||||
PL_RegisterEventIDFunc(PLEventQueue *aSelf, PLGetEventIDFunc aFunc,
|
||||
void *aClosure);
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
** FUNCTION: PL_RegisterEventIDFunc()
|
||||
**
|
||||
** DESCRIPTION:
|
||||
**
|
||||
** This function unregisters a function for getting the ID on unix for
|
||||
** this event queue.
|
||||
**
|
||||
** INPUTS:
|
||||
** PLEventQueue *aSelf
|
||||
**
|
||||
** RETURNS:
|
||||
** void
|
||||
**
|
||||
** RESTRICTIONS: Unix only (well, X based unix only) */
|
||||
PR_EXTERN(void)
|
||||
PL_UnregisterEventIDFunc(PLEventQueue *aSelf);
|
||||
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
#if defined(NO_NSPR_10_SUPPORT)
|
||||
#else
|
||||
/********* ???????????????? FIX ME ??????????????????????????? *****/
|
||||
|
|
Загрузка…
Ссылка в новой задаче