views:

16

answers:

1

Hi all,

I am trying to make a socket server that spews mouse move events, in Cocoa.

This thread: http://stackoverflow.com/questions/3134901/mouse-tracking-daemon

has info regarding the mouse event handler, which was really helpful, however, I need to stream these events out via socket.

Using http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Streams/Articles/PollingVersusRunloop.html#//apple_ref/doc/uid/20002275-CJBEDDBG

as as guide was helpful, but I have a disconnect with regard to intersecting the run-loop of the stream with the event handler loop.

All I really want is when I get a mouse move event, to spit it out of the socket. Do I even need a run-loop for the stream? If not, how do I do this??

Thanks for any input!

Chris

A: 

All I really want is when I get a mouse move event, to spit it out of the socket.

From the documentation you linked to:

A potential problem with stream processing is blocking. A thread that is writing to … a stream might have to wait indefinitely until there is … space on the stream to put bytes….

If you simply did a blocking write, you could block forever, hanging your application.

If you simply did a non-blocking write, you may only write part of what you intended to. This will confuse the other side if you don't remember what you have left and try to send it again later.

Enter the run loop. Mouse-move events come in on the run loop, too—you don't need or want a separate run loop. “Intersecting” the two sources of events is exactly what a run loop is for.

You'll want symmetry between your event handlers: Each should either send some bytes or remember some state (using a couple of instance variables for the latter).

In the mouse-moved handler, if you have previously received a has-space-available event and did not have a mouse-moved event to send, send the one you just got. Otherwise, remember the event for later. (Keep only one event at a time—if you get another one, throw the older one away.)

In the has-space-available handler, if you have a mouse-moved event that you have not sent, send it now. Otherwise, remember that you have space available, so you can use it at your next mouse-moved event.

Either way, when you try to write the bytes and only write some of them, remember the bytes and where you left off. You should only start sending a new mouse-moved event after completely sending a previous one.

Note that the solution as I have described it will drop events if you're getting events faster than you can send them out. This is not a problem: If you're getting them faster than you can send them out, and you keep them around until you can send them out, then either they will pile up and tip over (you run out of memory and your app crashes/your app stops working/you bog down the system) or the user will see instances of “catch-up” where the mouse on the receiving end slowly replays all the events as they slowly come in. I say it's better, in your case, to drop events you couldn't send and just let the receiving mouse teleport across space to make up the lost time.

Peter Hosey
Hi Peter,Thanks for the response. Sorry for the delay in replying, I just noticed this in my inbox.I ended up ignoring the run loop, and just writing directly to the socket as I get mouse events. I have an anonymous function attached to an event handler that sends a simple string of the deltaX and deltaY of the mouse.It seems to be working with no lag or performance degradation. However, I will certainly investigate your solution closely for my own edification.Thanks!Chris
Raconteur