[mac-lisp-ide] Re: ideas and issues

Duncan Rose duncan at robotcat.demon.co.uk
Sun Feb 1 14:58:24 UTC 2004


On Saturday, January 31, 2004, at 10:19 AM, Duncan Rose wrote:

>
> On Saturday, January 31, 2004, at 12:23 AM, Timothy Moore wrote:
>
>>
>> On Jan 31, 2004, at 12:34 AM, Duncan Rose wrote:
>>
>>> I think (hope) that the event loop requirements won't be *too* much 
>>> of an issue. Any threads in an application can be sent events, its 
>>> just that the run loop needs to be manually started for any threads 
>>> that aren't the main thread. I'll hopefully have a proof of this by 
>>> the end of the weekend.
>> The main issue is that window system events are delivered only to the 
>> main thread and really have to be handled there too. AIUI.
>>
>
> I'm not sure what AIUI means 8-)  And I'm also not sure in this 
> context what "window system" events means... but under the assumption 
> we're talking about any events generated by the window system, I think 
> that these events get delivered to any thread that is running an event 
> loop (i.e. that has an executing run loop). I'll talk about this a 
> little more since I now consider we're back on topic for any threaded 
> GUI work in Cocoa, which will include any IDE we write irrespective of 
> whether it uses CLIM.
>
> I'll split the events into "send to object" and "send to thread" 
> events. Many mouse events (mouse left / right / other down and up, 
> scroll wheel, drag events) are sent directly to the NSView over which 
> they occurred, irrespective of the thread in which they are running 
> and irrespective of whether that thread has an executing run loop. My 
> experimental back end already responds to those (although I am only 
> passing mouse down / up events onto the rest of McCLIM at the moment).
>
> I think that many of the window events (exposed, resized, zoomed, 
> etc.) are sent to the target window (or to its delegate, at least) 
> irrespective of whether the NSWindow is running in the main thread or 
> has an executing event loop, but I have yet to write handlers for any 
> of these (this is my task for the w/end), so I'm not so sure on this 
> one.
>

I've looked at this in more detail now and can confirm that these 
window notifications get sent to the window's delegate irrespective of 
run loop and threading issues.

> Other events are distributed to the main thread by default (I assume 
> at the moment that key down / up and mouse moved events (which have to 
> be explicitly enabled for the window(s) that want them) fall into this 
> category) but can be requested by any thread by it (the thread) 
> starting a run loop.
>

And I can debunk this. Now that I've fixed a little bit of brain-damage 
in the back end, key events and mouse motion events are sent direct to 
the NSWindow, again irrespective of run loop and threading issues.

> Run loops can only be started by threads that *COCOA* recognises as 
> multithreaded. OpenMCL spins off posix threads (as is to be expected) 
> which can't by default execute run loops until the application informs 
> the window server that it is a multithreaded Cocoa app, by creating an 
> NSThread instance (which is free to immediately exit without doing 
> anything). The application (and any threads of that application) is 
> then considered to be multiprocessing and threads that do not have 
> executing run loops can start them and process any events in the event 
> queue.
>
> If you're interested, here's the code I use for getting Cocoa to 
> recognise my app as a threaded app in my toy back end:
>
>   (unless (ccl::send (ccl::@class ns-thread) 'is-multi-threaded)
>     (ccl::send (ccl::@class ns-thread)
>                    :DETACH-NEW-THREAD-SELECTOR (ccl::get-selector-for 
> "setHiddenUntilMouseMoves:")
>                    :TO-TARGET (ccl::@class "NSCursor")
>                    :WITH-OBJECT nil))
>
> I hope you appreciate the inconsistent usage of @class (an example of 
> the lossage in the code ATM) 8-)
>

The above may be generally true (or maybe not), but I've now taken this 
code out of my back end and its behaviour is unchanged. So I now *do 
not* think that run loops or threading is an issue for Cocoa GUIs.

The general structure of the back end I'm working on as it stands is as 
follows:

   1. Click on the natty bundle icon (making use of the Bosco bundle 
from Mikel)
   2. the application delegate does a 
(clim-listener:run-listener-process) in the 
application-did-finish-launching, running CLIM as a separate process
   3. All the CLIM infrastructure gubbins gets started, including 
running the CLIM event loop in yet another thread

When the NSApplication receives events, it distributes them to the 
NSWindow and NSView subclasses I defined in my McCLIM back end. I think 
that these calls are made in a different thread again, but I could be 
wrong. However, I can only assume that even though the window instances 
are created in a different thread to the main thread, they are still 
added to the main thread's responder chain.

So at the moment, all I can say is: I don't understand quite what's 
going on or why, but things seem to be working.

> The thing I'm not clear on at the moment, but that I hopefully will be 
> sure about in a couple of days, is a) whether this works at all 8-), 
> and b) whether this can cause events to be passed to multiple handlers 
> (e.g. if my NSView or NSWindow is tied up being drawn when key events 
> arrive in the window server queue, will the main threads run loop get 
> to pull them off the queue before the run loop I started for the 
> thread managing the view / window can do so? Or can *both* run loops 
> consume the event (sounds dodgy if so). Or is the event handling in 
> Cocoa clever enough to know that the thread in which the window / view 
> is running has a run loop started, and ensure that only it gets those 
> events?
>

I suspect that any run loop can process any events that are of an input 
type the run loop is sensitive to. The listener is event driven as far 
as the back end is concerned, which means there's nowhere in the back 
end that gets run on a regular enough basis to run a run loop. I did 
try the run loop approach yesterday, but couldn't get it to run in the 
same thread that was running when mouse down events were handled. This 
seems not to matter though when all the events *do* get delivered to 
where I want them delivered.

> So I still have a ways to go to understand all this properly, but I'm 
> hoping I'll be done (with working (poor quality!) code and everything) 
> exploring this enough for my needs RSN.

Whilst I can't say my understanding of all this is improving much, I 
can say that things seem to be working - and that is enough for me for 
the time being. The only remaining unknown is whether other McCLIM 
apps, when started from the listener, will behave wrt events. Time will 
tell 8-)

(I'm also going to experiment with running McCLIM apps after doing a 
(require "cocoa") from openmcl rather than from the Bosco bundle; just 
to see if it works. I'd be willing to bet at the moment that it will 
work).

-Duncan

>
>>
>> http://www.nhplace.com/kent/PS/Ambitious.html
>>
>
> Thanks for the reference, now I just need to read it and think it over 
> 8-)
>
> -Duncan
>
>> Here are the key points. As the user types input, the lisp code is 
>> calling read-char or whatever. So the input is "live;" for example as 
>> soon as the user finishes one argument of a command the prompt for 
>> the next argument can be output. So how can the user edit input? If 
>> the user backs the cursor up and makes a change, the editor throws 
>> out to a catch tag and restarts the function that was reading input.  
>> Now that function sees the edited input...
>>
>> Tim
>>
>





More information about the Mac-lisp-ide mailing list