gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: about RunLoop, joystick support and so on


From: Xavier Glattard
Subject: Re: about RunLoop, joystick support and so on
Date: Tue, 13 Feb 2007 11:03:57 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

Richard Frith-Macdonald <richard <at> tiptree.demon.co.uk> writes:

> On 11 Feb 2007, at 19:18, Xavier Glattard wrote:
> (...)
> No, in fact both backends use the runloop and both use  
> GSRunLoopWatcher which works perfectly.  The fact that both backends  
> at certain points chose to poll their respective message queues  
> without asking the runloop to tell them whether there is anything  
> available does not imply anything about

You're right : it works ! 
Well... most of the time.
GNUstep is not perfect. For instance it can't manage properly a intensive use of
performers or events, neither w32 nor x11 (see my openGL test tool).

I had to read the code many times to get an idea of how it works.
And finally I wonder *why* it works ! ;-)

As Fred says Win32 backend code is actually very strange. The X11 backend is far
better (cleaner) but needs some work. And the shared code could be improved.

> (...)
> Actually I'm *hoping* that Apple will release something to specify  
> clearly how an NSStream subclass (other than those subclasses Apple  
> provide of course) can be tied in to an NSRunLoop.  Such an API would  
> be able to take the place of GSRunLoopWatcher.  Without that API you  
> can't write new subclasses of NSStream and get their event handing  
> code called when an event becomes available, you can only base code  
> on existing NSStream implementations.

All you have to do to subclass NSStream is at Apple: look at NSStream,
NSOutputStream ans NSInputStream reference pages.

> eg. if your joystick driver provides an interface like a file (normal  
> on unix and quite common on windows) then you can probably just open  
> an input stream using the relevant file device, but if the joystick  
> has to be accessed signals or shared memory then you have to use the  
> GSRunLoopWatcher api directly.

I would have to subclass NSInputStream to tell it to get the data from the
memory/signal/system call instead of a file. That's all.

What does a GSRLWatcher that a NSStream doesnt ?
The  only difference I see is that GWRLWatcher handles _blocks_ of bytes while
NSStream handles _streams_ of bytes.

> (...)
> > Something like that :
> >
> >                  |-- GSWin32EventStream <GSBackendEventStream>
> > NSInputStream <--|
> >                  |-- GSX11EventStream   <GSBackendEventStream>
> >
> > [GSDisplayServer -eventStream] would be called by NSApp to get a
> > NSInputStream<GSBackendEventStream>. Then NSApp would register  
> > itself as the
> > delegate of this NSStream and schedule it in the runLoop.
> >
> > A GSX11EventStream would get the event with XPending/XNextEvent  
> > when the runLoop
> > polls, then translate it into a NSEvent and send it back to the loop.
> > A GSWin32EventStream would get the event from another NSStream  
> > (which would only
> > select the window message from PeekMessage), then translate and  
> > send it back to
> > the loop.
> >
> > Not so simple ? Yeah probably 
> 
> That sounds quite nice, 

Thanks :o)

> but basically it's reorganising the incoming  
> half of the GSDisplayServer so that instead of adding events to the  
> application's event queue directly, it provides  a stream of NSEvent  
> objects for the application to put in the event queue itsself.  In  
> both cases the internal workings would need to be pretty much the  
> same ...
> 1. ask the runloop to inform the GSDisplayServer instance when there  
> is data available
No : the NSApp needs the data. The server knows if data is available.

> 2. when data is available, pull it off the X event queue or windows  
> message queue
No : the server pull off the event and give it when asked

> 3. make sense of the data, generating the corresponding NSEvent  
> object or objects (if any)
Yes.

> 4. add the event to the event queue (current implementation) or store  
> the event in memory owned by a stream object and trigger an event  
> handler in the NSApplication code so that the NSApplication can read  
> the event from the stream and put it in the event queue.
Yes and no : NSApp needs no event queue.

> If different sources of NSEvents were going to be used by lots of  
> different pieces of code, the encapsulation of all the work inside a  
> stream interface would be really useful/clean/simple.  However, in  
> practice we have a single source of events for a display server, and  
> all those events go into the application's event queue and are pulled  
> out of that queue by the code which needs the events, 

But the application has to handle many other events than those get from the GUI
: timers and performers. And socket/network messages, and so on.

> and this model  
> of operation is inherent in the AppKit/GUI API.   So I don't think  
> wrapping events in an NSStream subclass before putting them in the  
> event queue is any help.

NSStream is only a better GSWatcher. That's not the main problem.

The integration of NSStream in the NSRunLoop code might be a good opportunity to
make some other changes and simplifications in the event management code.

Here is my 2cts suggestion.

At least i think the DispathMessage/windowProcedure should be hidden in a more
abstract mechanism. Without the window procedure the win32 backend would be more
like the x11 one, and with enough abstraction (that NSStream might gives) some
more code could be shared.

The use of NSRunLoop could also be extended. For instance [GSDisplayServer
-getEventMatching...] contains its own loop : NSEvents are first got from a
queue owned by the server, then the runLoop is asked for timers and performers.
The event queue of the server is filled earlier by a message from the runLoop to
receivedEvent. I think the runLoop should manage all this and the server should
only have to be an interface with the GUI system (isPendingEvent, getEvent,
dot.). As the events got from the system have to be translated and and filtered,
the server have to manage a queue.

Here is roughly what's in my head :

 NSApplication  NSRunLoop  GSEventStream  GSEventServer  NSWindow
    ---           ---          ---            ---         ---
     |
     |eventStream
     |---------------------------------------->|
     |
     |setDelegate: self
     |------------------------->|
     |
     |scheduleInRunLoop
     |------------------------->|
     |
     |acceptInput
     |------------>|
                   |hasBytesAvailable
                   |----------->|DPSPendingEvent (?)
                   |            |------------->|
                   |            |              |isQueueEmpty
                   |            |              |----\
                   |            |              |<---/
                   |            |              |
                   |            |              |fillEventQueue
                   |            |              |----\
                   |            |                   |
                   |            |              |<---/
                   |            |              |
                   |            |              |idPendingEvent (*)
                   |            |              |----\  PeekMessage
                   |            |              |<---/   or XPendingEvent
                   |            |              |
                   |            |              |getAndDecodeSystemEvent (*)
                   |            |              |----\  GetMessage    
                   |            |              |<---/   or XNextEvent
                   |            |              |
                   |            |              |enqueueEvent
                   |            |              |----\
                   |            |              |<---/
 stream:handleEvent|
     |<------------|
     |           (...)
     |read
     |------------------------->|DPSGetEvent 
     |                          |------------->|
     |                          |              |dequeueEvent
     |                          |              |----\
     |                          |              |<---/
     |sendEvent
     |---------------------------------------------------->|


(*) Only two methods are specific to the underlying system. -getAndDecode is the
 main part.

The runLoop wouldn't know anything of the backend : it'd only have to manage
streams.
The server wouldn't know anything of the runLoop nor the NSApp : it'd only have
to manage the events from the system.

Ideally the real server shouldn't know anything of the AppKit but what is
included in GSDisplayServer.h. But that would only be true in a Perfect 
World(tm)
Some bad examples in X11 backend :
  [NSApp deactivate]
  [NSApp mainMenu]
In the w32 backend :
  [NSApp terminate: nil]
  use some Panels, includes NSText, NSMenu, NSTextField, ...
  get many notifications from NSApp
   ....
I know : the backend does this because it needs to do this. But It should not
need to do this. The 2 backends are so different that their behaviors are realy
different sometimes. Most of this should be done by NSApp.

....

I know... I just come here and start to criticize :-p
But i only want to help because I like GNUstep :-)
My ideas are probably not perfect, but i'd be happy to talk about all that again
and again. And help to do job.

Regards

Xavier









reply via email to

[Prev in Thread] Current Thread [Next in Thread]