зеркало из https://github.com/mozilla/gecko-dev.git
[BeOS] Take in account mayWait parameter in nsAppShell::ProcessNextNativeEvent(). Bug 343100. p=sergei_d, r=thesuckiestemail, BeOS-only
This commit is contained in:
Родитель
4ed461404d
Коммит
2a761195c7
|
@ -42,40 +42,20 @@
|
|||
|
||||
#include "nsAppShell.h"
|
||||
#include "nsSwitchToUIThread.h"
|
||||
|
||||
#include "prprf.h"
|
||||
|
||||
#include <Application.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static sem_id my_find_sem(const char *name)
|
||||
{
|
||||
sem_id ret = B_ERROR;
|
||||
/* Get the sem_info for every sempahore in this team. */
|
||||
sem_info info;
|
||||
int32 cookie = 0;
|
||||
while(get_next_sem_info(0, &cookie, &info) == B_OK)
|
||||
{
|
||||
if(strcmp(name, info.name) == 0)
|
||||
{
|
||||
ret = info.sem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// nsAppShell constructor
|
||||
//
|
||||
//-------------------------------------------------------------------------
|
||||
nsAppShell::nsAppShell()
|
||||
: is_port_error(false)
|
||||
: is_port_error(false), scheduled (false)
|
||||
{
|
||||
eventport = nsnull;
|
||||
eventport = -1; // 0 is legal value for port_id!
|
||||
}
|
||||
|
||||
|
||||
|
@ -90,42 +70,21 @@ NS_IMETHODIMP nsAppShell::Init()
|
|||
// system wide unique names
|
||||
// NOTE: this needs to be run from within the main application thread
|
||||
|
||||
char portname[64];
|
||||
char semname[64];
|
||||
char portname[B_OS_NAME_LENGTH];
|
||||
PR_snprintf(portname, sizeof(portname), "event%lx", (long unsigned) PR_GetCurrentThread());
|
||||
PR_snprintf(semname, sizeof(semname), "sync%lx", (long unsigned) PR_GetCurrentThread());
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("nsAppShell::Create portname: %s, semname: %s\n", portname, semname);
|
||||
printf("nsAppShell::Create portname: %s\n", portname);
|
||||
#endif
|
||||
/*
|
||||
* Set up the port for communicating. As restarts thru execv may occur
|
||||
* and ports survive those (with faulty events as result). We need to take extra
|
||||
* care that the port is created for this launch, otherwise we need to reopen it
|
||||
* so that faulty messages gets lost.
|
||||
*
|
||||
* We do this by checking if the sem has been created. If it is we can reuse the port (if it exists).
|
||||
* Otherwise we need to create the sem and the port, deleting any open ports before.
|
||||
* TODO: The semaphore is no longer needed for syncing, so it's only use is for detecting if the
|
||||
* port needs to be reopened. This should be replaced, but I'm not sure how -tqh
|
||||
*/
|
||||
syncsem = my_find_sem(semname);
|
||||
eventport = find_port(portname);
|
||||
if (B_ERROR != syncsem)
|
||||
{
|
||||
if (eventport < 0)
|
||||
{
|
||||
eventport = create_port(200, portname);
|
||||
}
|
||||
return nsBaseAppShell::Init();
|
||||
}
|
||||
|
||||
if (eventport >= 0)
|
||||
|
||||
// Clean up things. Restart process in toolkit may leave old port alive.
|
||||
if ((eventport = find_port(portname)) >= 0)
|
||||
{
|
||||
close_port(eventport);
|
||||
delete_port(eventport);
|
||||
}
|
||||
|
||||
eventport = create_port(200, portname);
|
||||
syncsem = create_sem(0, semname);
|
||||
return nsBaseAppShell::Init();
|
||||
}
|
||||
|
||||
|
@ -140,107 +99,97 @@ nsAppShell::~nsAppShell()
|
|||
{
|
||||
close_port(eventport);
|
||||
delete_port(eventport);
|
||||
delete_sem(syncsem);
|
||||
|
||||
|
||||
if (be_app->Lock())
|
||||
{
|
||||
be_app->Quit();
|
||||
}
|
||||
}
|
||||
|
||||
// This version ignores mayWait flag totally
|
||||
PRBool nsAppShell::ProcessNextNativeEvent(PRBool mayWait)
|
||||
{
|
||||
bool gotMessage = false;
|
||||
|
||||
// should we check for eventport initialization ?
|
||||
if (eventport == 0)
|
||||
if (eventport < 0)
|
||||
{
|
||||
char portname[64];
|
||||
char portname[B_OS_NAME_LENGTH];
|
||||
PR_snprintf(portname, sizeof(portname), "event%lx", (long unsigned) PR_GetCurrentThread());
|
||||
// XXX - Do we really need to search eventport every time? There is one istance of AppShell per app
|
||||
// and finding it once in Init() might be sufficient.
|
||||
// At least version this version with if(!eventport) worked for me well in tests.
|
||||
// It may add some performance, sprintf with format is bit expensive for huge message flood.
|
||||
if((eventport = find_port(portname)) < 0)
|
||||
{
|
||||
// not initialized
|
||||
// not initialized
|
||||
#ifdef DEBUG
|
||||
printf("nsAppShell::DispatchNativeEvent() was called before init\n");
|
||||
#endif
|
||||
return gotMessage;
|
||||
}
|
||||
}
|
||||
|
||||
// Previously we collected events in RetrieveAllEvents via simple read_port,
|
||||
// and unblocking was performed by sending fake 'natv' message from _pl_NativeNotify()
|
||||
|
||||
// Currently we ignoring event type, previously we had 5 priority levels, different for mouse, kbd etc.
|
||||
// MS Windows code sets some priority for kbd and IME events by ignoring mayWait
|
||||
// There is huge need now to rewrite MouseMove handling in nsWindow.cpp.
|
||||
|
||||
|
||||
// mayWait here blocked app totally until I replaced read_port with read_port_etc.
|
||||
// I suspect it may be related to non-implemented ScheduleNativeEventCallback()
|
||||
if (port_count(eventport) || mayWait)
|
||||
if (port_count(eventport))
|
||||
gotMessage = InvokeBeOSMessage(0);
|
||||
|
||||
// There is next message in port queue
|
||||
if (port_count(eventport) && !mayWait)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("PNNE\n");
|
||||
#endif
|
||||
EventItem *newitem = new EventItem;
|
||||
if (!newitem)
|
||||
return gotMessage;
|
||||
newitem->code = 0;
|
||||
newitem->ifdata.data = nsnull;
|
||||
newitem->ifdata.waitingThread = 0;
|
||||
// Here is interesting thing, according to logic described in
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=337550#c17
|
||||
// read_port() is what should be here, if we take mayWait in account,
|
||||
// but application even don't start with that. Or, if it does, blocks in first window created.
|
||||
// Using read_port_etc with real timeout allows it work as expected.
|
||||
// Second interesting fact, if we don't use || mayWait condition, CPU load depends on timeout value -
|
||||
// smaller value, bigger CPU load.
|
||||
if (read_port_etc(eventport, &newitem->code, &newitem->ifdata, sizeof(newitem->ifdata), B_TIMEOUT, 100000) < 0)
|
||||
if (!scheduled)
|
||||
{
|
||||
delete newitem;
|
||||
newitem = nsnull;
|
||||
is_port_error = true;
|
||||
return gotMessage;
|
||||
// There is new (not scheduled) event and we cannot wait.
|
||||
// So inform AppShell about existence of new event.
|
||||
// Actually it should be called from something like BLooper::MessageReceived(),
|
||||
// or, in our case, in nsToolkit CallMethod*()
|
||||
NativeEventCallback();
|
||||
}
|
||||
else
|
||||
{
|
||||
scheduled = false;
|
||||
gotMessage = InvokeBeOSMessage(0);
|
||||
}
|
||||
gotMessage = true;
|
||||
InvokeBeOSMessage(newitem);
|
||||
delete newitem;
|
||||
newitem = nsnull;
|
||||
#ifdef DEBUG
|
||||
printf("Retrived ni = %p\n", newitem);
|
||||
#endif
|
||||
|
||||
}
|
||||
// Hack. Emulating logic for mayWait.
|
||||
// Allow next event to pass through (if it appears inside 100000 uS)
|
||||
// Actually it should block and then be unblocked from independent thread
|
||||
// In that case read_port() should be used.
|
||||
if (mayWait)
|
||||
gotMessage = InvokeBeOSMessage(100000);
|
||||
return gotMessage;
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
void nsAppShell::ScheduleNativeEventCallback()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("SNEC\n");
|
||||
#endif
|
||||
// ??? what to do here? Invoke fake message like that 'natv' from gone plevent ?
|
||||
if (eventport < 0)
|
||||
return;
|
||||
|
||||
// This should be done from different thread in reality in order to unblock
|
||||
ThreadInterfaceData id;
|
||||
id.data = 0;
|
||||
id.waitingThread = find_thread(NULL);
|
||||
write_port(eventport, 'natv', &id, sizeof(id));
|
||||
scheduled = true;
|
||||
}
|
||||
|
||||
void nsAppShell::InvokeBeOSMessage(EventItem *item)
|
||||
bool nsAppShell::InvokeBeOSMessage(bigtime_t timeout)
|
||||
{
|
||||
int32 code;
|
||||
ThreadInterfaceData id;
|
||||
id.data = 0;
|
||||
id.waitingThread = 0;
|
||||
code = item->code;
|
||||
id = item->ifdata;
|
||||
MethodInfo *mInfo = (MethodInfo *)id.data;
|
||||
int32 code;
|
||||
ThreadInterfaceData id;
|
||||
if (read_port_etc(eventport, &code, &id, sizeof(id), B_TIMEOUT, timeout) < 0)
|
||||
{
|
||||
is_port_error = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
id.waitingThread = 0;
|
||||
MethodInfo *mInfo = (MethodInfo *)id.data;
|
||||
if (code != 'natv')
|
||||
mInfo->Invoke();
|
||||
if (id.waitingThread != 0)
|
||||
{
|
||||
resume_thread(id.waitingThread);
|
||||
}
|
||||
delete mInfo;
|
||||
|
||||
if (id.waitingThread != 0)
|
||||
resume_thread(id.waitingThread);
|
||||
delete mInfo;
|
||||
return true;
|
||||
}
|
|
@ -44,14 +44,14 @@
|
|||
|
||||
struct ThreadInterfaceData
|
||||
{
|
||||
void *data;
|
||||
thread_id waitingThread;
|
||||
void* data;
|
||||
thread_id waitingThread;
|
||||
};
|
||||
|
||||
struct EventItem
|
||||
{
|
||||
int32 code;
|
||||
ThreadInterfaceData ifdata;
|
||||
int32 code;
|
||||
ThreadInterfaceData ifdata;
|
||||
};
|
||||
|
||||
struct MethodInfo;
|
||||
|
@ -64,17 +64,17 @@ class nsAppShell : public nsBaseAppShell
|
|||
{
|
||||
public:
|
||||
nsAppShell();
|
||||
nsresult Init();
|
||||
nsresult Init();
|
||||
protected:
|
||||
virtual void ScheduleNativeEventCallback();
|
||||
virtual PRBool ProcessNextNativeEvent(PRBool mayWait);
|
||||
virtual ~nsAppShell();
|
||||
virtual void ScheduleNativeEventCallback();
|
||||
virtual PRBool ProcessNextNativeEvent(PRBool mayWait);
|
||||
virtual ~nsAppShell();
|
||||
|
||||
private:
|
||||
port_id eventport;
|
||||
sem_id syncsem;
|
||||
bool is_port_error;
|
||||
void InvokeBeOSMessage(EventItem *item);
|
||||
port_id eventport;
|
||||
volatile bool scheduled;
|
||||
bool is_port_error;
|
||||
bool InvokeBeOSMessage(bigtime_t timeout);
|
||||
};
|
||||
|
||||
#endif // nsAppShell_h__
|
||||
|
|
Загрузка…
Ссылка в новой задаче