Bug #67370. Better interleaving of xlib + plevents. r=danm sr=shaver

This commit is contained in:
blizzard%redhat.com 2001-03-12 23:57:18 +00:00
Родитель a3dcfdcd14
Коммит 2bb54a9dae
5 изменённых файлов: 226 добавлений и 1 удалений

Просмотреть файл

@ -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 ??????????????????????????? *****/