WWDC2001 Session 106

Transcript

Kind: captions
Language: en
thank you welcome to session 106 you
know the carbon Event Manager is one of
the most important technologies that
we've added to carbon because it can
simplify your code make it easier to
write Carbon applications improve your
performance especially on Mac OS 10 and
it's the foundation for most of the
improvements that we are adding to the
toolbox so here to tell you all about it
is the manager of the high level toolbox
team edy Bose that's me all right as
Mark said carpet events is one of the
most important technologies to learn
about as an application developer the
reason for this is that it permeates
everything we do in the toolbox every
one of the toolbox managers like the
window manager menu manager etc deals
with carve events at least in some
respect
it is the Alpha and the Omega so what
you got to learn about here is you can
learn a brief overview of current events
we're gonna try to talk about basic
fundamental principles how it works what
makes it go I will also show you how
easy it is to actually build a carbon
event based application and we'll also
show you some examples of how you can
extend the toolbox via carbon events
so what carbon events is is is a direct
dispatching model events a dispatch
directly to objects in your application
this is in contrast to the wait next
event model where it's up to you to pick
up an event and decide what to do with
it the tool box can do that for you and
with that the tool box can also provide
many many default behaviors all the
things that make a Mac application
behave like a Mac application but your
applications can override those default
behaviors and extend it in ways that
make sense for your app and while we
have a pure carbon event based model you
can also use carbon events in your wait
next event based applications this is to
allow you to actually start installing
handlers and eventually get to a point
where you don't need to call wait next
event anymore so why did we do this well
first off if you remember the event
record structure our friend
it only has a possibility of 16 events
and the reason for this is because
there's only 16 bits in an event mask we
wanted a system where we could send
hundreds of events possibly thousands of
events all different types if you were
to look in Carbon events th right now
you could see hundreds of events already
existing we also wanted to unify
different models that we had we had
event records for receiving events by
your application we also had deaf procs
for Windows controls and menus and we
also had different notification
callbacks that you can install for
whatever they were but each one of these
was different and every time he did
install a new callback or to find a new
callback it had a different API he had
to learn it and it was just mayhem so
what we're trying to do with carbon
events is unify all of that into one
model that's easy to learn it's flexible
and it assumes everything else that
we've ever done this also makes it
simple to write applications not only
because it's a simple model learn it
once you know it but also because
as I mentioned the toolbox provides
default behaviors so you get to write
the code that matters for your
application and lastly we want an API
that would encourage good performance
particularly on Mac OS 10
so I mentioned we're gonna show you how
to build a carbon event based app it's
really simple the easiest way to do that
it's a project builder an interface
builder if you were here for the last
session before this one that was with
interface builder that is really the
star of this duo here and that's what
allows you to throw together a nib file
and just have it run via carbon events
it's what I like to do is actually bring
up somebody to show you how to do that
so here's one of the engineers from
high-level toolbox team guy pull it in
so I'm gonna show you a little bit about
what ed was talking about with respect
to project builder an interface builder
and how they make your life really easy
when you want to make a carbon event
based application project builder
supports a whole bunch of different
types of applications that you can make
I'm going to start off with a nib based
Carbon application
there we go all right so you run the app
and it just works well on a clean system
all the basic handlers are all the basic
event handling is taken care of for you
you can click on the window title bar
and drag your window around you can
resize it you can select things from the
menus and you know you can quit the
application the best part though is the
fact that this all happens with
virtually no code this is just a page of
code this is all that there is in the
application all it does is it opens up
the nib for the app sets up a menu bar
creates a window cleans up after the nib
shows the window and runs the
application run runs the application
event loop and everything else is taken
care of by the carbon of that manager
now let's see
guess I'm playing with fire here I can
open up the nib for this window or for
this application and as you can see it's
just a plain old normal blank window
just like we got in the app and I can
throw some interface elements into there
with interface builder so that's really
cool if you got to see the session right
before this you got to see how much you
can construct of a carbon app I'm gonna
go ahead and throw some edit text fields
in here you know make some a little bit
bigger or maybe put some static text in
there I've got a couple buttons you know
maybe this is gonna be an OK button
change the name to OK and make it the
default button go up here let's say we
want a button that actually quits the
application I can change it to be quit
and I can say you know what to have the
quit command in you save this nib go
back here and I guess if I'm lucky it'll
rebuild and I can run and the interface
just comes up and works I wrote no extra
code this is all just working you can
type into the text fields you can hit
return to flashes the OK button
I don't know if you can see that up
above and the coolest bit since this
quit button has the quick command
associated with it if I click in it the
quick command is propagated to the
application and the default Carbon event
handlers just quickly quit the
application for you so that's just the
very basics of what Carbon events and
interface builder can do for you but
this shows that there's a lot of power
in the system that you can leverage and
it's gonna give you some more details on
how you can leverage that all right so
back in 1984 I
still in high school and this is the way
an application worked essentially
everything was done by the application
and the toolbox was just there for
support
so the application was responsible for
the event loop the application was
responsible for dispatching events and
of course the application did something
with those events in the hint and their
handlers this is the new model the
toolbox is taking a much more active
role in driving an application in this
model the application calls that run
application event loop API you saw and
it takes care of dispatching the events
and all your application needs to be
responsible for is the handlers and
that's where your application lives and
that's where your value is added so as
we saw we have a lot of standard
behaviors that we support in the toolbox
naturally obviously drag Windows around
you can resize them if you had a proxy
icon in the window title we would handle
that automatically for you with regards
to dragging it around we also will
handle contextual menu interception for
you so you don't have to worry about you
know ctrl-click will just tell you a
contextual menu do it and the other
thing is with this model we could
actually handle the contextual menu
click ourselves if you didn't and at
that point we could say well we what we
always want to put up a connectional
menu when this happens and maybe we'll
implement something where we start
putting up a potential menu and then
we'll send you a carmen event saying
alright we're doing a contextual menu
please fill it in here's the menu so
there's a lot of power here obviously
with menus we deal with tracking the
menu bar dealing with command keys we
deal with updating the menu bar as
necessary and what controls will
automatically handle all the tracking
will deal with focus issues and the like
so before I get into the real details I
want to talk in general about how events
flow through the system or at least
through an application with carpet
events at the top of this diagram you
see the event queue and as some event
today below that we have a diagram
representing what the toolbox considers
to be its canonical
containment hierarchy at the bottom we
have the application it is the container
of everything above that we have menus
and windows so the owners of menus and
windows are the application and each
window can own controls and each control
can actually have sub controls based on
our standard control manager control
hierarchy so what happens is an event
comes off the queue and then the toolbox
looks at it and says ok what kind of an
event is it where should it go
for this example we'll say it should go
to the control that's right below it
once it gets into the control and looks
something like this each control has a
target associated with it and this is
the receptor for Anakin for a carbon
event each target can have multiple
event handlers installed on that target
and they're installed in the form of a
stack the last handler installed is
topmost on the stack the last hander
installed is the first handler to get
the events that is how applications
override toolbox behaviors so in this
diagram essentially we have an
application handler at the top called my
handler below that we have a some handle
that was installed by the toolbox
possibly a standard Handler and then
below that we have an object camera and
this can be thought of as the actual def
product that's driving this control so
we're gonna go through a worst case
scenario where nothing wants this event
its unwanted I can feel bad about it so
as this event goes through essentially
we look at each handler see if it was
registered for this event and if it
wasn't we will bypass it or it might be
that the handler receives the event but
decides at this time it doesn't want to
handle it so it basically reports I
haven't handled it so if this happens
for all the handlers it'll just fall
through and out of the object at that
point the toolbox decides where should
it go next and again it uses the
standard containment hierarchy to decide
that so in this case that will go to the
window next
and then if it isn't handle there it
will propagate out to the application
and this is where all unhandled events
will end up now if the application
doesn't handle it it'll actually just
get dropped if you happen to be a wait
next event based app if an event is
unhandled by any of your handles it will
actually be returned through wait next
event as long as it was an event that
could be returned to way next event like
a mouse click okay details the first
thing you need to know is about the
event rack the event ref is the
replacement for the old event record
structure and in grand toolbox tradition
it's opaque you have to use accesses to
get at it each event is identified by a
class and a kind so a mousedown event
would actually have a event class of kay
event class mouse it's a mouse event and
the kind is just some sub event of that
class in this case Mouse down now Mouse
down all by its lonesome just knowing
that the mouse went down isn't very
useful usually you want to know where it
actually happened what the modifier keys
were things like that maybe what button
was pressed and the way we do that is we
have an extensible parameter mechanism
on an event so all of the things I just
mentioned can actually added to the
event as parameters each parameter can
be accessed through some mnemonic name a
constant each parameter can also have a
type so the mouse location is actually
stored as a quick-draw point so we would
actually use a constant representing
that type like type QT point the
important thing about an event ref is
it's not just one way event records were
always something happened Mouse down
window activated it's always past tense
event refs can actually be using a much
more active role you can actually send
an event ref someplace to get
information the recipient of the event
can actually store information in the
event ref so that after you send the
event you can extract the information
out of that one good example
hit testing in a window as I mentioned
we're trying to replace deaf procs with
carbon events and in fact the native
messaging model for windows and controls
and Mac OS 10 is Carbon events we
actually simulate the old proc pointer
based stuff on top of that so when we're
gonna do hit testing what happens is we
get the point we actually send a hit
test Carbon event so the window the
window then turns around says okay this
part was hit stores it in the carpet
event so this way when the sender gets
the event back you can actually see they
can extract that parameter and find out
where the mouse is hit and Carbon events
are extensible extensible to the point
that you can actually create your own
you can use maybe your application
signature or whatever you want as your
event class and then have your own suite
of events which you can send around in
your application the event queue is a
little different in Mac OS 10 under Mac
OS 9 or traditional Mac OS the event
queue is shared among all applications
on 10 that's not the case each
application gets its own event queue
when events come into that application
via the Windows Server they're queued up
in that application event queue however
within an application we take it one
step further in that each MP task can
get its own event queue if you're
running an MP task and on that MP task
you call get current event queue you
will get a private event queue for that
MP task you might hand the QRF for that
queue to some other entity in the
application and then you could start
using that to actually post events
between threads using carbon events now
you might just use MP primitives to do
messaging back and forth but you can
also use carbon events as it adds a much
more expressive method of of events
and contrast all cooperative threads
including the main thread of the
application share one event queue and
that's the main event queue and that is
the queue that receives all the events
from the Windows server as I mentioned
whenever you're waiting on an event
queue for an event this allows timers to
fire
what the heck's a timer well it's the
replacement for the null event
processing mechanism through wait next
event and wait next event if you don't
handle an event you get a null event I
mean if there's no event for your
application you get a null event and
then you decide oh I guess I should
spend some time doing something timers
allow you to just request time
explicitly and as I mentioned they only
will actually execute while you're
waiting on an event queue so these
aren't asynchronous with respect to your
application and not running at interrupt
level or anything like that they're
running a task level you can allocate
memory you can draw you can call the
tool box there at that level the
advantage of a timer is that each object
in your application can ask for its own
share of periodic time if it needs it
and the timers can be disabled so for
example if you have an edit text control
or something which needs to blink the
cursor or perform some animation when
that goes inactive you might want to
disable that you can actually remove the
timer and stop using up that time
because obviously there's nothing to
animate anymore timers can be set to
fire at intervals every half second
every second or they can be one-shot so
you say call me back in 15 seconds
timers can actually fire while the mouse
is down and this is important to note
because you know obviously if you had
we're processing a null event and we're
processing a click so it's a little
different and so this means timers can
actually fire while you're tracking
controls and while you're tracking the
menu bar so it's something to look out
for and Mac os10 finally has a much more
reliable heartbeat Mac OS 9 because it's
cooperatively scheduled you know any one
prot any one application can steal the
processor for any amount of time so you
can't be guarantee
to get a half-second timer firing - much
more reliable on necklace 10 so as we
saw in the example you drive your
application to run application event
loop this is the pure carbon event based
carbon event API whatever I'm trying to
say this is how you've run a comet event
based app once you entered this API you
will not exit until somebody sometimes
the tool box sometimes your own
application calls quit application event
loop and while you're in there that's
what's driving your application the
toolbox then starts pulling events off
the event queue sending them to your
handlers as appropriate alternatively
you can continue to call wait next event
and while you are inside wait next event
events will be dispatched to any
handlers that you have installed and
again this allows you to start
installing handlers even in your wait
next event based application and start
adopting carpet events without having to
go and reconvert your I mean you know
just redo your entire application over
to be a pure carbon event based app so
while we're in run application event
loop or inside wait next event we end up
dispatching events and where they go is
event targets and we saw a picture of
one each target can have a stack of
handlers inside and they're typically
attached the toolbox objects like menus
windows controls we also have some
special targets one of them is called
use a focus target we're going to talk
about that a little bit a little later
the other one is the toolbox dispatcher
whenever one application event loop
pulls an event off the event queue it
just sends it to the toolbox dispatcher
you can actually use this fact to
install a handler on the toolbox
dispatcher to catch every event as it
was being processed so it does have its
uses here and there as I mentioned they
have a stack of event handlers and of
course the event handler is where your
application lives this is where you
receive events it's a simple callback
where you get your events you will only
receive the events that you register for
we don't support wild carding and
a conscious decision with performance in
mind we don't want to start sending out
events to any handler that could
possibly deal with it when you're inside
your event handler you can choose to
actually handle the event meaning do
something with it or not handle it
meaning let it propagate to some other
object which or handler which which does
want it the way it tells the toolbox
whether we handled it or not is by its
result code if your event handler
returns event not handled there that's a
cue to the tool box to say all right
nothing happened here nothing to see
here please move along so it sends the
event off to some other handler if you
returned any other status code event
propagation stops are dead and the event
is discarded and once we leave a target
we do propagation we saw the diagram of
our containment hierarchy that's what we
use to decide where event should go so
if an entire target doesn't handle an
event we decide which target to send it
to next and we redirect it
I mentioned that application target is
where all at all unhandled events end up
now that's not a complete rule there are
events which we will not allowed to
propagate between beyond the target
which we send it and the best example of
those are those events which replace the
old def product messages there's no
point sending a window hit test event to
the application so we only send it to
that window object and I also mentioned
you know how your result code tells the
toolbox how to if we should propagate or
not we call that implicit propagation so
you don't really need to do any action
on yourself to make the event propagate
other than control your result code
however you can do what I term explicit
propagation which is you can actually
say alright I have this event but I want
the toolbox to do its fault processing
right now because I'm going to do
something after it
and you do that through an API called
call next event handler so you would
receive an event just call through
toolbox might do some default behavior
and then you can follow up so you can be
implicit or explicit alright I touched
on user focus the user focus is quite
simply where keyboard events go and you
can get the user focused target by
calling get user focused target back of
Maca was st. we introduced keyboard
focus which is great so you have a
window when you have some concept of
what the focus control is in that window
well from an event model standpoint you
know that's all wonderful and all but
when we get a keyboard event which
window should we even start with so what
we've done is we've created this concept
of user focus which is the combination
of the currently active document window
and any focused control in that window
if the currently active document window
doesn't have a focus control that window
is considered to be the user focus there
are times however when you actually want
to redirect it to some other window
which isn't the currently active
document window
best example would be a floating palette
which accepts some sort of keyboard
input you might want to redirect it
there and you can do so with an API
called set user focus window if you're
using pure carbon events you don't
really have to even worry about that
because the toolbox will manage that for
you automatically user focus along with
being the recipient of the keyboard
events is also the recipient of
h:i commands h:i commands are merely the
extension of the old menu command
concept we introduced in mac OS 8.0 so a
menu command is just a position
independent way of identifying a menu
item traditionally so instead of knowing
that you know when the user selects undo
from the Edit menu it's you know menu ID
129 item 1 all you need all you need to
know is that the command is on
it doesn't matter where it isn't the
minibar as long as you can undo you know
what to do when we were doing all this
carbon event work though we decided it
would be really good if we could share
this with controls as well and he saw an
example of that where we hooked up the
quick command to a control so the H I
command structure is actually little
struct is the encapsulation of that so
inside these structures it has the
command ID as well as information about
where the command came from the
propagation path is a little different
based on whether the command was
originated from a control or from a menu
if from a control we just follow the
standard control hierarchy starting with
the actual control that originated the
command for menus we send the command to
the menu which originated the command
and unhandled at that level we then send
it to the user focus and that is
probably what makes the best sense for
example if you're going to select cut
from the Edit menu the command should
probably go right to that focus control
in the currently active document window
wherever the user focuses basically we
also use h-i commands to deal with menu
item enabling and disabling we talked
about this a little bit more in the
windows and menus talk tomorrow
but essentially whenever menu is about
to be displayed for each item in the
menu we send out kay event command
update status events this is your cue to
actually do something with the command
in the menu you might want to enable it
or disable it if you want to add a check
mark or change its text maybe undo
changes from undo to undo typing it's
completely up to you but we send this
right to the user focus saying I'm about
to show this how should it appear when
the user selects one of these menu items
or clicks the control we send out kay
event command process and that's when
you can deal with the command commands
are actually really useful for doing
simple inter target messaging
so for example you can have a window
with controls in it and the controls in
the window can all have command IDs
associated with it and the window can be
listening to all the commands that the
controls generate so every time you
click a checkbox or drag a slider the
window can actually pick that up and say
oh check box and say that I gotta go do
something it's also important to use the
standard command IDs that we've defined
in carbon events eh whenever possible we
have a whole list of them in there right
now and we're adding more as we speak
but the reason for that is we want to be
able to share the menu bar between the
toolbox in the applications so if the
toolbox has something you know up on
screen at the time and we need to enable
the disable certain menu commands such
as the edit menu we need to be able to
find those by command ID
there comes a time in every applications
life when you have to go modal and
typically we've done that in the passage
with modal dialogue so you called get
your dialogue you bring up your dialogue
and you call modal dialogue and you sit
there until the user hits ok or cancel
or whatever the way to do that in the
carpet event model is to call run app
modal loop for window so you can create
any window you be a nib based resource
base we don't care we just put it up on
screen and you call run that motor loop
for window now at some point somebody
needs to call quit at modal look for
Windows so that you can actually
terminate from the call it's very much
like run application event where you
enter it and you will not exit it until
somebody calls the appropriate quick
call and this is probably good enough
for most most uses especially if you
pure carbon event-based but you might
have an application which has a lot of
legacy code and you can't necessarily do
that you need to drive the event model
yourself or drive to the event loop
while this thing is modal so you can
actually share our modality environment
while driving the events yourself and
you do that with begin and end at modal
State for window and what I mean by our
modal environment is that whenever we
enter this modal state we automatically
take care of display be disabling the
menu bar and then dealing with the click
situation so we don't allow clicks
outside the window that happens to be
modal so by using begin and end up the
modal State for window you can actually
use the toolboxes canonical modality
stuff all right we talked about
performance there are a couple ways that
you can actually tune your app for Mac
OS 10 and I mentioned that Carbon events
help you do that
first thing is timers as opposed to
using wait next event timeouts ideally
you should have your way next event
sleep time set to the maximum it can be
and install timers throughout your
application that actually goes a long
way to helping toward minimize
unnecessary idle time another thing is
tracking lose tracking loops written
traditionally with while still down no
get mouse are very very bad on 10 they
make everything else go slow so what you
need to do is instead use track mouse
location we're actually going to show
you an example of that in a few minutes
another thing is to try to use
notifications whenever possible as
opposed to polling we've gone I mean
we've done a lot of stuff in the carpet
event model to try to send you Carbon
events when certain things happen in
your application or sometimes outside of
your application for example one common
polling situation is pulling the the
process list i wouldnt know when the
process comes and goes well we actually
have carbon events to tell you when that
happens so rather than you sit in there
in some sort of loop or you know instead
of installing a timer to do this every
you know millisecond or something you
can just say you know hey let me know
when an app gets launched or let me know
when an app quits and if you if you have
cases in your application where you need
to do polling and we don't have a
solution please let us know because
we're really trying to add as much in
the in the realm of notifications or
notification events as possible
so we talked about how carbon events is
the native kind of death proc model for
Mac os10 and carbon in general toolbox
objects is what allows us to do this
toolbox objects are effectively an event
handler that you can define and register
with the tool box using register toolbox
object with this you can then in the
window and control managers call create
custom window or create custom control
passing one of these toolbox object reps
that you register and then that handler
that you associated with the toolbox
object will get called to deal with all
the events having to do with def procs
and this is the recommended method for
doing custom controls and windows these
days and then the reason for that is
quite simply this is where we're
spending our time you know Carbon events
is like our future and it's very
flexible carpet event second we can add
parameters and new events you know until
we're blue in the face and the thing is
when we start adding parameters on
existing events you know we could kind
of augment behaviors and things like
that without affecting and the
recipients of those events who maybe
don't care about that parameter yet so
you know we can actually start to send
new parameters while not well and not
breaking basically so that was a lot of
stuff so what I'd like to do now is
actually bring up guy again to show you
a more detailed demo and show you about
a lot more of the power that we have oh
yeah all right cross your fingers for me
so the first demo I want to show has to
do with what ed mentioned about
eliminating polling I've got a small
application here which is based on that
basic carbon app that I showed you
before and I'm running another
application it's on the system which is
a CPU gauge this basic app has just a
normal window in it with a couple of
bevel buttons one of them's good one of
them is bad and this app is almost as
small as the one I showed you before I
added one Carbon event handler to it to
override Mouse tracking for the bad
control and the reason I overrode it is
because the system already does the good
thing with respect to polling the system
when it's about to track the mouse does
not sit in a spin loop it calls track
Mouse location which will block and
which will make sure the CPU doesn't get
used when it's not necessary so what I
did is I overviewed sorry I overrode the
click handling for the bad control and I
have a a while still down loop in the
bad control so if I click on it you can
actually see the CPU just pin out I'm
not even moving the mouse but the CPU is
using up absolutely everything it
possibly can if I was trying to download
something in the background your
download speed will be cut in half you
don't want to be doing this what you
really want to do is either let the
toolbox do the default behavior for you
which as you can see if I click and move
around you know I get a little bit of
CPU usage but if I click and hold it
still I don't get any usage so use track
mouse location if you're currently doing
polling loops now we'll go back to
magnify this time for real
so magnify is an app you may have seen I
think we've shown at previous years it
is a simple application which magnifies
the screen pixels that the mouse happens
to be over and we do this with a timer
magnify updates once every so often
grabbing this the pixels from the screen
and displaying it in the window and it
also has a carbon event handler on the
window to handle window resizing we
always want the magnify window to be
squared just because we're that way so
if even if I move the mouse only
horizontally the window still maintains
its squareness so let me show you oh the
one other thing I want to show you about
magnifier is we also offer a modal
preferences dialog that lets you
configure various things you can change
the zoom level turn off the little info
that gets shown in there or make it
float or not float let's make it not
float for now so let me show you a
little bit of the code and how we do all
that
it's the first thing I want to show you
is how we did the timer timers very
simply are just a croc pointer that you
register with us tell us how often you
want to do something and then when
you're proc pointer is called you get to
do whatever you want to do so here's our
event timer we just called it magnify
event loop timer it receives user data
which is basically like a refcon so if
you have some global state you need to
reference or some per contact state you
need to reference you can receive it
there and our timer goes in there we do
some various things we basically create
a port so we can grab some screen pixels
and we copy bits it to various things
and end up painting it into our window
so it's one thing to write this but you
actually need to install the event oh
you know what didn't want to hide me to
do that the way you install an event
loop timer is you create a upp around
your proc pointer and you pass that upp
in to install event loop timer you tell
it which event loop you want to install
the timer on and typically you're gonna
want to install your timers on the
current event loop and you tell it how
often you want it to fire in this case I
have this timer firing about once every
20 seconds and that's it the only thing
you have to do after that is just run
the event loop and your timer will
automatically fire so next I want to
show you I show you how to write a basic
event handler like I mentioned before we
have a window handler which makes sure
that our window resizing always is
square and just like an event timer this
is a simple callback proc pointer you
receive an event a refcon and when your
callback is called you can extract
parameters from this event in this case
our window extracts the attributes from
this particular event I know that this
handler is only registered for one event
so I can just dive right in to
extracting parameters without looking at
the actual event type but if I wrote a
handler to handle multiple events you'd
actually want to switch over the type of
the type of event you're receiving so a
window bounds change event actually
contains some attributes which tells you
how the bounds are changing when the
window bounds changed the the window
might be resizing or it might just be
moving ie the origin is changing
we only need to do work when the size is
changing so I check the attributes to
make sure we're only gonna do work when
we need to one other thing I want to
point out we have a result code that
we're going to return eventually by
default this result code is event not
handled err so if our handler ends up
doing no work that tells the event
subsystem to just go and do whatever
default processing you would have done
so going back we know that we're
changing size we get the current bounds
out of the event that's the bounds that
the window manager figures you want to
really use but we take them out we don't
really want to use them because we want
to make the balance square so we go
ahead and we do a little bit of effort
to make the bounds square and then we
stuff the current bounds back into the
event and we set our result to no error
no error is an indication that our
handler handled the event don't call any
default handlers just let this event
finish now so our handler exits the
window manager ends up getting the
bounds that we've changed out of the
event and it resizes our window to those
bounds and as you might imagine
installing one of these event handlers
is also very simple
you create a upp for that handler oh I
keep hitting the wrong keys and you call
install window event handler you pass it
a window you pass it the UPP and you
pass it the list of events that you're
interested in for that handler and it
just so happens that I am only
interested in the k1k event window
bounds change event once you do that
your handler is installed and any time
the window manager or whoever might need
to call that handler
whoever anytime someone needs to call
the handler it will be called the last
thing that I want to go into is handling
commands from menus we just so happen to
have the default preferences command
associated with the Preferences item for
our menu and we need to set up a handler
to handle that preferences item and
display the modal dialog so in my main
first thing we do is we enable the
Preferences command because we know we
want to allow the user to select that
and next after we do some more setup we
install an application event handler now
as Edie mentioned when you select a
command from a menu the first place that
command goes is the menu itself menus
don't often handle commands and in this
case our menu does not handle like
commands specifically then the command
will go to the user focus which would be
the window
well our window isn't particularly
particularly interested in it so the
event ends up propagating to the
application and that's where we want to
handle it and we have an application
Handler oh you know I keep hitting that
don't I just as you would expect we pull
out the direct object out of the handle
out of the process command event and it
happens to be of type H I command we
look to see if it's the Preferences
command and if so we do the Preferences
dialog and the Preferences dialog is an
excellent excellent example of how you
would do a modal dialog first we build
the window via and then don't have to
build at the end him you can build it
programmatically or via resources or
however you want to do it we set up a
few controls and then we install a
handler onto the window to handle
commands that are going to be generated
by the controls in that window and
that's the pref handler then we position
it on screen as appropriate and we call
run app load a loop for window now when
one app modal OOP for window eventually
returns we disposed the window we
dispose of the event handler and then we
returned from the Preferences function
so most of this work actually happens
inside the toolbox until our pref
handler gets called and our prep handler
is going to get called for commands
associated with controls in the window
and just like handling menu commands we
extract the direct object out of the
command event take a look at the command
ID and we do various things one of the
interesting things is if we see a
magnification change command we change
our magnification factor and tell the
the actual magnify window to update
itself if it needs to and there's a
couple standard commands for dialogs and
those are khi command ok and khi command
cancel and those have been associated
with the ok and cancel buttons in that
dialogue when we see the OK button
we write out our current settings to the
Preferences and we call quit app mode a
looper window that way run app mode
we'll exit we can ultimately get out of
due preferences and back into the normal
application processing
so this magnify sample code will be
released a sample code on the website
very shortly as soon as we can get it up
there now those are just the basic
concepts for how you'd implement sort of
Carbon event handlers and Carbon event
timers but I want to show you the true
power of Carbon events we have another
application on here called live buttons
now live buttons looks a lot like one of
the earlier apps I built it's just very
simple kind of an ugly dialogue you know
we've got some text fields in here you
know we've got some buttons you can
pretend that this was I don't know some
kind of find dialog so you click search
and it goes off and does something I
mean we're not really doing anything
here we're just animating for fun
we've got an OK button bevel button a
little disclosable area stuff like that
and this is all being run by the toolbox
now the cool thing is live buttons is
set up such that we've installed Carbon
event handlers on all the controls in
this window to intercept clicking and
drawing I can put it into this edit mode
and our handlers that we've installed
know to intercept drawing by drawing
blue frames around each individual
control and intercept clicking by giving
you handles that you can actually resize
the controls and repositions things sort
of live and move my button over here
resize it's the H I designers won't like
it
and I move my bevel button around and do
whatever I want and as soon as you're
done fiddling with it it's live button
sample lets you turn off edit mode and
you're back to normal that's interesting
but I can't there we go
[Applause]
now on previous systems this sort of
functionality would only be possible if
you wrote lots of extra code or patch
the toolbox but with carbon events we
allow you to do things like this in a
clean legal way but Carbon events
certainly aren't limited to just demo
apps if you've got a larger document
based application we can serve your
needs too now this is simpler text this
is sort of a new version of simple text
that we're writing you know as you would
expect thoughts kind of small but you
can type into simpler text and change
the font change the size and things of
that nature but what we also did is we
wired up a font window now the main
simpler text window is is pretty
unintelligent about the rest of the
application it just edits some text and
it happens to process a few events a few
special events the simpler text window
can handle a change font event and they
change font size event a change font
style event so that we can create
another totally independent separate
part of the application to drive this
font palette and wire up functionality
into the font palette that just sends
Carbon events to the main window so I
can change the size over there I don't
know or change it with a pop-up or maybe
change it to bold and let's bring it
back to sixty point and do stuff like
that
now one other kind of cool thing that we
did in this sample is handling some
window events this font palette we set
it up to handle the bounds change Carbon
event to automatically snap it to the
edge of the window I don't know if you
can see that jumping on the big screen
but as I get close it sort of
automatically snaps it there a lot of
applications like to group their
palettes together and you can override
certain Carbon events that way but
that's not the only thing you can you
can do with the balance change event now
balance change events are also good for
handling live resize well we decided to
wire that up too but then you can get
really strange and what if we only
wanted this window to be displayed on a
single monitor and as the user moved it
off you could actually scrunch it up in
very weird ways so you can do that too
there's all kinds of cool things you can
do with Carbon events and a scale very
well I mean they're great for demos
obviously but you can fit them into
large-scale applications you can wire up
a little
bits of new functionality to take
advantage of new toolbox features in
such a way that it doesn't disrupt your
your existing application so it's really
cool I'm gonna hand it back over to Edie
for a couple more words that was pretty
cool stuff now what well item one start
memorizing carpet events th there will
be a test at the end of the conference
there's a lot of stuff in there we have
a lot of documentation in the header
itself to help you along and get you
started
the learning carbon book has some
examples of how to write a carbon event
based application I've submitted an
article to Mac tech which goes into the
stuff in way more detail than we can
talk you know in an hour though and just
start playing with the you know
interface build a project builder start
building carbon event based apps it's
really easy to start you can just create
you know default app is start installing
handles and see what you can do I mean
the little demo where you you know drag
the window to the corner of the screen
and kind of scrunches you know that took
about you know 10 minutes to write so I
mean this stuff is really easy to do and
like I said there's just a lot of
powerful things you can do with not much
code and that means there's much more
time for you to spend doing the stuff
that makes your applications great and
with that I like to bring out mark
Turner again let me just through the
roadmap and QA thanks
[Applause]
Thank You Eddie Wow those were some
kick-ass demos huh Thank You guy okay so
here we are six o'clock Tuesday the next
session you should attend is tomorrow
carbon windows and menus ed will be back
share with you great stuff about windows
and menus obviously and as you can see
the next two controls and appearance
wanted to a good pair of sessions to
catch and finally I really recommend the
carbon performance tuning session coming
up on Thursday if you attended the
keynote or obvious presentation
basically every presentation on Monday
we talked a lot about performance and
how the characteristics of your apps
performance vary whether you're running
on eight or nine and/or Mac OS 10 and so
this carbon performance tuning session
will give you a lot of useful
information on how to tune your app for
Mac OS 10