Application Frameworks • 1:05:45
This session gives an architectural overview of HIToolbox, discussing the newest features, and offering insight into its future directions. Learn how to adopt HITextView (the compositing-savvy, full-featured text editing view), HISearchField, HIColorWell, asynchronous window dragging, automatic interface layout, and Quartz-savvy Aqua drawing primitives. Discover how to implement custom menu content with an HIView.
Speaker: Guy Fullerton
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
My name is Xavier Legro and I'm the Mac OS X evangelist. I work in developer relations and I'd like to welcome you all today to session 409, the new HITooLbox. Last year, if you remember correctly, not in the same room, but you know, it's a bit more south, we introduced HIView, which is a new drawing compositing model for like, you know, drawing controls on Mac OS X. We got a lot of feedback from you guys and we're very happy to present you what we've been doing in the last year.
You have to understand that if you're doing Carbon development and if you're a C/C++ developer on our platform, this technology is very, very important for you. And at one point or other of your development cycle, you have to look at what we're doing with HIView and what we're doing with the new HITooLbox. Because this is really the future of C and C++ development on Mac OS X.
We have a session full of new things and very cool demos. And in order to talk about that, we're going to go directly into the content. I'd like to introduce Guy Fullerton, who is known as well as Guy, who's going to be actually talking about the brand new HIToolbox that we have for you guys. Guy. Thank you.
Thank you Xavier. Get him back. Call him Xavier. So you have to forgive me a little bit. I've been told that there's a Krispy Kreme donut waiting for me back there after I finish the presentation, so I might go a little quickly here. I really, really like donuts.
Can we get the front monitors on so I can see the slides without turning around? If not, I'll just stand back here and I can see this screen. So I'm sure some of you are sitting here wondering, new HIToolbox, why'd they call this session the New HIToolbox? I mean, it's not like the Control Manager APIs have changed fundamentally since 1984. You can still call many manager routines the same way you've always been able to call them. And the contents of MacWindows.h is almost the same as it has been back in 1984.
So why are we calling the session the new HI Toolbox? Well, the reason is that over the past couple years, we've completely rewritten the foundations of HIToolbox. In Jaguar, we introduced HIObject, which is our standard toolbox object model. And every object model, of course, needs some kind of messaging model, and Carbon Events is that messaging model.
And Carbon Events have been around even longer than HIObject. And of course, if you've got objects, you need base handlers and base functionality. And of course, we have that in the form of the standard window handler and the base handlers for controls and applications and menus and things like that.
And so with this foundation in place, what we were able to do is completely rewrite the control manager so that the control system is now HIView. And HIViews are now a full-featured view system that supports a one-pass efficient composited drawing model. So in short, the reason we call this the new HIToolbox is because it's built on a completely modern foundation.
Now, there's a famous saying, to stand still is to regress. And what this means to us on the toolbox is that the world moves kind of fast around us. There's a lot of other things going on. And if we don't at least keep up, and if not move faster than the rest of everybody, we're falling behind.
And so that's actually the reason why we rewrote the foundations of HIToolbox. Because now that we have this modern foundation in place, we can innovate much more quickly than we were able to before. And that's fine for us. Let's put new features out there. But you might be wondering, why do we care? An application that was written back in 1984 that underwent the PowerPC transition and then ported to Carbon still runs about the same on Mac OS X as it did in 1984.
Sure, it's got a new user interface and stuff, but your code can just work the same if you want it to. So what does it really matter if we have a new HIToolbox? Well, the reason is that the new foundation forms the basis of all of our new functionality from here on out.
We have things like the toolbar, which were introduced in Jaguar. And you can't really use the toolbar unless you understand how HIobject and HIView works. And in fact, you can't even customize the toolbar unless you know how to make a custom HIView. Similarly, if you want to put sheets in your application to be truly Aqua-compliant, you need to understand how Carbon events work. So you really need to understand how this foundation works, and you need to start adopting this as soon as you can, so you can bring your applications forward.
Another real benefit of this new foundation is it offers much, much better performance. Compositing view systems are an awful lot faster, more efficient, and even more predictable than the old-school sorts of view systems that we had on Mac OS. But the best point is that sticking with HIToolbox is a very easy, iterative adoption path that allows you to keep using the same, often cross-platform, C and C+ code that you're already used to. So in short, the new HIToolbox is what allows you to take your applications to the next level on Mac OS X.
So with this new foundation in place, we actually did tons more stuff for Panther and HIToolbox than we were able to for Jaguar for previous system releases. And I'm going to talk about an awful lot of stuff. So the real reason I'm going to talk fast is I've got to get all this stuff fit into an hour. It wouldn't surprise me if we go a little bit over. But before I start going into the new features, I want to talk about something else.
When we were implementing Panther, one of our mantras was performance. We really had to look hard at ways we could make the toolbox faster. Performance is the main goal of Panther, you know, it was talked about in other sessions. So we took a good hard look at a number of different facets of the toolbox and did some intelligent things to make it as fast and perform as efficiently as it possibly could. For instance, you know, we send a lot of Carbon events on the system, but if you sample your application, you're not going to see a lot of time spent in Carbon event routines, right? The bulk of the time is spent in your app.
But still, we know the number of Carbon events we're sending out. We know that over the course of a run of an application, there's going to be thousands and thousands of Carbon events getting sent to various objects all over your application. So we need to make sure Carbon events are as lightweight as possible. So we rethought some of the algorithms, rethought some of the data structures, and we put some speed boosts in there, the best of which is that event construction is now twice as fast on Panther as it was on Jaguar.
Now, we took a similar look at HIVU in the compositing view system. We found some ways we could do invalidation of views a little bit better. We found ways of speeding other things up, like doing our vis region calculations in a deferred manner and things like that. And the net result is that now live resize for a fairly typical compositing window that probably has a toolbar and a couple complex views, that's now about 30 to 40 percent faster on Panther than it was on Jaguar.
And it doesn't just affect compositing windows. See, you can see that the window frame is still being drawn, and the title bar is still being drawn. So even though your windows may not yet be compositing, we still draw the window frame and the title bar widgets and all that with compositing.
So these performance improvements we did just at the compositing path even helps your non-compositing windows. Now, it's hard to say exactly how much it helps out non-compositing windows, because it depends greatly on what exactly you draw and how you draw on those windows. But with our test apps, we're seeing up to about a 10 percent performance improvement in library size during, for non-compositing windows.
And of course, these same changes speed up just about anything having to do with the number of views that you have in your library. So, for example, if you're drawing, say, a 10 percent performance improvement in a library, you're going to have to make a 10 percent performance improvement in a library.
So we're going to have to make a 10 percent performance improvement in a library. So, we're going to have to make a 10 percent performance improvement in a library. So, we're going to have to make a 10 percent performance improvement. So, we're going to have to make a 10 percent performance improvement in a library.
So, we're going to have to make a 10 percent performance improvement in a library. So, we're going to have to make a 10 percent performance improvement in a library. So, we're going to have to make a 10 percent performance improvement in a library. So, we're going to have to make a 10 percent performance improvement in a library. So, we're going to have to make a 10 percent performance improvement in a library. So, we're going to have to make a 10 percent performance improvement in a library.
So, we're going to have to make a 10 percent performance improvement in a library. So, we're going to have to make a 10 percent performance improvement in a library. So, we're going to have to make a 10 percent performance improvement in a library. So, we're going ways to enable and disable your items, but we still wanted to make that experience faster for the user. So we tweaked some menu manager algorithms, and now typical menu item manipulation is about 30 to 40 percent faster on Panther as it was on Jaguar.
And of course, we've had a lot of feedback about Data Browser, and some of the complaints is that it's slow in a few areas. So we concentrated on certain algorithms that people were complaining about, and we made Data Browser Item Addition, I think it was about 30 percent faster on Panther, and Data Browser Item Removal and Selection 10 times faster on Panther than it was on Jaguar.
Well, I know you're not here to listen to me pat myself on the back or anything, so let's just jump into the features. And I'd like to start off with HITextView. This got mentioned in other sessions, but HITextView is a A very full-featured compositing text editing view based around MLTE, the Multilingual Text Engine.
It's compositing mode only, so this is another reason why you need to start switching your windows over to compositing mode, so you can adopt a cool feature like this. The reason why we based it on MLTE is because MLTE already had a lot of functionality. It already supports mixed style runs, full Unicode support, so it supports all the language that Mac OS X supports.
It's got advanced typographic features and things like that. And it already integrates with certain standard systems on the system, like the edit and services menu. And right now we're working on support for the font panel. It's not there in the WWDC seed, but it will be there by the time we ship Panther GM.
So MLTE already has this really rich API. It can already do things like insert text into it, associate an MLTE instance with a file, set up styles, do complex manipulations and whatnot. So that allowed us to make the HITextView API very, very small. There's basically two APIs in the HITextView API. The first allows you to create a textview. The second allows you to get the MLTE object out of that textview so you can do manipulations on it.
So the intended usage model is you create your view, you get out the MLTE object, and you call MLTE APIs on it. But the main thing you need to realize is that some MLTE APIs do not work with these MLTE objects that are bound to a view. And the reason for that is because the MLTE API is so huge, and it predates HIView actually, that it does some things that don't make sense in the world of HIView. For instance, there's an MLTE API which allows you to change the bounds of an MLTE object.
Well, we'd much prefer you use the HIView APIs to change the bounds of a given view. So we actually disabled the MLTE APIs that do those things just for these MLTE objects that are bound to HIViews. So as you're perusing the MLTE APIs and you see something, you're going to want to make sure there's not an HIView--an equivalent HIView API instead. And make sure to call that HIView instead--HIVW API instead. Now, another way that we leveraged existing technology to make our textview a lot quicker or to implement our textview a lot quicker was through the use of HIScrollView. The scrollview was something we implemented in Jaguar.
It's an HIView that can manage the scrolling for any arbitrary scrollable canvas. It could be a picture, who knows what. It could be a list. It could be text. And it already does a whole bunch of work. So it's a very, very good tool. And it's a very good tool to work for us. It manages the scrollbars. It'll hide and show the scrollbars appropriately according to the AcroHuman interface guidelines. It'll keep the canvas sized at the right amount and all that.
And it's got a Carbon event protocol that communicates with the canvas itself. So we built the HITextView to understand that protocol and to communicate via that protocol with the scrollview. So that all you need to do is you take a textview, you embed it in a scrollview, and now you've got a scrollable textview.
So here's a very quick example of hi-text-view creation. It's pretty much exactly what you would expect. You create a text view by calling hi-text-view create. It's an hi-view creation API like the ones we introduced in Jaguar, so it'll look real familiar to you. You can pass a frame to it. In this particular example, I did not need to pass a frame, and I'll get to that in a second.
We support some option bits. Right now, there are no option bits that are specific to the hi-text-view, but it just gives us future expandability. But more importantly is the fact that you can pass MLTE option bits into our creation function. That's the TX and frame options parameter. So this TX and frame options parameter allows you to configure the MLTE object with certain creation data to turn on certain behaviors and whatnot. These are all in the normal MLTE headers.
But in this particular example, we didn't need any options. And after you call this routine, of course, you get back your text view. The next thing you need to do is make it visible. Because by default, an hiview is created invisibly. And then the next step is we just take our text view and embed it in a scroll view that we've already created. And then our text view is just working.
Now, more likely than not, you're going to actually need to manipulate your text view in some way via MLTE. So here's a very brief example of how to do that. We've already got our text view created. So we call hitextview get txn object to extract the MLTE object from it.
And let's say we want to associate that MLTE object with a file. So it will display the contents of the file and support revert functionality and things like that. So we build a URL to that file using, you know, the normal APIs. And then we call the textension routine to associate that file with the MLTE object. And that's it. Very, very straightforward.
Now, of course, you can build it in code if you want, but better yet, you can go into IB and build it there, because the IB, the interface builder in Panther, now supports a bunch of the new HIViews. They implemented the ones we introduced in Jaguar, and they've implemented most of the ones we've introduced in Panther. And we're continuing to work with them to make the Carbon experience in interface builder a lot richer. So, this is a good way to go as well.
So another new view that was talked about at the earlier sessions is HISearchField. Search fields are a big part of the Aqua user interface on Panther. They're really convenient for the users and offer a lot of functionality. And our HISearchField supports all the standard behaviors. You know, it's an editable text field, it's got the rounded frame, which indicates that it's a search field, it's got an optional cancel button, it's got an optional pop-up menu, completely customizable menu, and it has an optional descriptive label, which is the little grayed-out text you can see that's in the text field right now that kind of indicates what you're going to be searching.
So here's a very quick example of how you might create one. I'm going to assume you've already created a menu ref. And in fact, I'm going to assume you already know how to handle Carbon events on a menu ref, because this is something you've been able to do for the past couple of years.
It's very straightforward. You build up a menu. You put HI commands in it. You put the K event command process handler on the menu. And then you can react to commands as they get sent out. So we'll assume that's already been done. The next step is to just create our search field. Give it its bounding rectangle. You can set up the attributes. Right now, the only attribute is whether or not you want to cancel button.
In this case, we do want the cancel button. And you hand it your menu. And you give it the descriptive text you want displayed. And you receive back the search field. Now, we also offer APIs so that you can set the attributes and the menu and the descriptive text on the fly later if you need to.
Now once you've set it up, you're going to want to handle events for two things. You want to react to clicks on the cancel widget. And of course, you're going to want to react to the text as the user types it and hits return, so you can actually do the search. There's two Carbon events you need to handle to deal with those two things. The first is keventextaccepted. And the second is keventserchfieldcancelclicked.
You install a handler the way I'm sure you guys already know how to install. And the handler might look something like this. If you receive the text accepted event, you get your search field. You ask for the text out of the search field. You do your search, and you update your interface the way you would normally do that.
And if the cancel button's clicked, you just undo that search. You remove whatever filtering you did and restore your list to its normal state. So the next view I want to talk about is the segment view, or as it was called in other sessions, I think, that switcher thingy. But we prefer the segment view.
So I'm sure everybody's used the segment view in the finder, right? It's a view switcher control. It's like a group of radio buttons. You can choose between icon, list, and column view, and each of those choices is mutually exclusive. So of course, our segment view supports that. But some other uses of segment view have a more momentary behavior.
The best example are the back and forward buttons that you see in Safari and the back and forward buttons you see in the new open and save panels. That's essentially a segment view. It's just got two segments, but each of those two segments is a push button that does back and forward functionality. So of course, the segment view supports that.
The segment view also supports sticky behavior. You can think of that as a checkbox, right? You click it, it stays pressed until you click it again, at which point it pops back up. Now the cool thing is that every segment in a segment view is configurable. You can set the number of segments, and you can set each one up differently. So you could have, for instance, think of like a DVD player control.
You could have a play, pause, record, fast forward, reverse, each of those with a different type of button behavior. And of course, you can customize each of the button contents differently as well. We support icon services, icon refs, CG image refs, which is sort of the preferred format, and text, of course, for those applications that need text-based segment views.
Oh, the last point is that unfortunately we did not get the SegmentView APIs publicized in time for the WWDC build, but we are currently actually using the implementation inside the new nav services. So it is there, it does exist, it's fully functional, it's just the API didn't look quite the way we wanted to for the seed, so we pulled it back. But the API will definitely be in place by the time Panther ships.
So we've got a lot of feedback about Data Browser over the years. It's actually had quite a long lifespan. It's been around since before Mac OS X, because it shipped in CarbonLib. And so we wanted to implement some of the feature requests you've asked for. Now, in Jaguar, our big push was for HIV.
You know, we wanted everybody to get out there and use HIV. And it's this really exciting, cool functionality. So I'm sure everybody raced out, tried it, and then hit a brick wall and went, oh, data browser doesn't support it. I guess I can't use it. I guess I can't use compositing mode.
And yeah, that's true. It is unfortunate. And so that's one of the things we really, really wanted to fix for Panther. So I'm happy to say that now it works in compositing mode. It's pretty darn cool in compositing mode. It's actually a lot faster. Because of the way compositing modes and validation system works, I have to redraw a lot less in data browser when things happen to it than I had to in non-compositing mode.
In fact, just normal data browser API usage got a little bit faster because there were some data browser APIs that would immediately redraw. And so if you did sort of a multi-state change on the data browser, you might get three or four redraws. Whereas now in compositing mode, those four state changes will only be accompanied by one redraw.
But data browser is a really huge API. I got it working in my test tools. We got it working enough for the new nav services and finder in a few places. But I know we didn't quite cover all the bases. So I need your feedback. So those of you who hit the brick wall for adopting compositing in Jaguar, please go try it out. Go let us know if you see any problems in compositing mode with various data types and whatnot. I'd like to have this thing rock solid for Panther, but I need your help to do it. So write up any bugs you see.
So the other thing we added for-- one thing we added for Jaguar, actually, was type selection in column view. And we could actually do type selection for free in column view because there's only one column that's focused at a time, if you will. In ListView, however, if you've got multiple columns, the data browser doesn't know which column to apply the type selecting to. In Finder, it would need to be the name column, but we could make that guess.
We could find the first column that does text, but it's a little fishy. It might not work for every application. So what we decided to do was make it an adoption path thing, which actually gives us a benefit in a second that I'll talk about. When you set up your columns for ListView, you can specify a new property, this KDataBrowser ListView type select column property, which is in control definitions dot H, associate that with one of your columns, and that's the column we'll apply type selection to.
Now, the benefit we got, actually, for making this an adoption path thing is--. Yeah. It prevented us from breaking your existing applications. We know there are some applications out there that filter the incoming text before it hits the data browser. And you could filter it at sort of the wait next event level because up until now, data browser wasn't particularly Carbon event savvy. And so, you know, you could get away with taking an event out of wait next event, filtering it, and then calling data browser with only those key presses you wanted to give to data browser.
Well, when type selection is turned on, in order to do proper Unicode matching with the contents of the type select column, we need to handle our text input via the KEVENT_TEXT_INPUT_CARBON_EVENTS. So that is a difference. When you turn on type select, text input will be grabbed by Data Browser in a different way.
So if you need to do filtering, make sure you filter using the KEVENT_TEXT_INPUT_CARBON_EVENTS or some other similar mechanism. In fact, there are some new events put out by the Text Services Manager that make text filtering in general a lot easier. So take a look at carbon-events.h for that kind of stuff.
So the Appearance Manager was introduced in Mac OS 8. I'm sure most of you are familiar with it. I'm sure some of you have even used it. And it worked great on Mac OS 8. It was really fast. But on Mac OS X, it didn't perform particularly well. And the reason for that is that the Appearance Manager was entirely Quick Draw based. It assumed it was drawing into the current port. That's basically the main Quick Draw basis that it had.
Now, Mac OS X is very Quartz-based. We want to use core graphics all over the place. And in fact, the internals of the Appearance Manager on Mac OS X draw in Quartz. So we had this weird sandwich effect going on in the Appearance Manager where, OK, somebody would call the Appearance Manager, they would have set up their port properly. But before we call our internal stuff, we needed to convert the port information to CG context and make sure to synchronize the clip of the CG context with the Quick Draw clip, and that was just horrifically expensive.
Now, sometimes, after we were done doing our drawing, we needed to call your code back to do label drawing and stuff like that. And that is yet another sort of mode switch where we had to shore up the data structures and make sure everything was right in the Quick Draw world to match the way we'd set it up in the core graphics world. So you had the sandwich of Quick Draw, core graphics in the middle, and Quick Draw on the other side. And that just slowed everything down. So what we did is we took just that center portion, just that Quartz portion, and we exported it as HI-themed drawing primitives.
Now, of course, this is going to give you massive performance increases. In general, we see about a two-time speed boost for an HITHeme API on Panther compared to the equivalent appearance API on Jaguar. So if you can adopt this stuff conditionally in your code for Panther, you're going to see really big speed benefits for those of you who are using the Appearance Manager.
Now, the best thing is that the HITHeme APIs will look really, really familiar. It's virtually an identical usage model, so it should be extraordinarily easy to adopt. And the number one request for the Appearance Manager is, "Give us a way to draw pulsing push buttons, please!" So you can do that through the HITHeme APIs now.
Now, another reason HITHeme is so important is because this is the API set that will allow you to draw all the new Aqua widgets, right? You need to use HITHeme if you want to draw that new tab look and the segment views and things like that. So, you need to get familiar with this and understand how to use it if you need your own drawing primitives.
And lastly, the HITHeme APIs actually lay the foundation for the toolbox and its ability to print. Well, it doesn't print quite yet, but this lays enough groundwork so that we can actually print. Whereas the Appearance Manager APIs simply cannot print by virtue of the way we have to manufacture a context to match the QuickDrop port.
So like I said, it's a very, very familiar usage model, but there are some differences. First, obviously, is that the HITHeme APIs are completely Quartz-savvy. So, no longer will you be able to assume, "Oh, I can set up the current port with a background color and the appearance manager is going to erase to it." No, you have to do your erase beforehand if that's something you need to do, and then call the HITHeme API.
And in fact, the HITHeme API requires that you pass in a core graphics context. So you manufacture one of these core graphics contexts and you can call multiple HITHeme APIs as you need to. The second major difference is the fact that the HITHeme APIs use HIPoint and HIREctangle parameters. And there's two reasons for this.
The first is that since HITHeme is entirely core graphics based, and since core graphics has a floating point based coordinate system, quick draw coordinates, the old quick draw coordinates, which were not floating point, don't really work well in the context of CG. They don't allow maximum flexibility. And so that made it natural to use HIPoint and HIREct. The second reason is that the HITHeme APIs were literally designed so that we could implement our system HIViews like the push button and whatnot. And since they are HIViews, they also use HIPoint and HIREctangle parameters. So it was just a perfectly natural fit.
Now, you guys are all used to drawing with a top left-hand origin. I think that's more comfortable. I'm sure all of you do, too. So, of course, the HITHeme APIs support that model. But if you're doing more PDF-compatible drawing, or if you're trying to do some theme-primitive drawing from a Cocoa application, HITHeme supports a bottom left origin as well, so you can use it from just about anywhere.
So we introduced HIView in Jaguar, and it has a lot of cool new functionality, but we wanted to add something really key to it in Panther, and so we've got something that's kind of exciting, and it's called HIViewLayout. But rather than explain it, I want to give you a brief demo, because I think that'll do a better job showing you what it's all about. So if we could go to the demo machine.
I'm being told I need to talk faster. Something tells me that's not the case. Okay, so this is Rebounder. This is our test tool for the HIV layout stuff, but it's also, we're also going to sort of polish it up and put it out as sample code after the show, but it needs a little bit of work. I mean, for one, we're stretching a push button well beyond the bounds of good taste.
Anyway, so this is basically just a normal window with a push button in it. You can click and track on it, but we've put some Carbon event handlers on the push button so that we can put it into sort of edit mode, right? You can see these little handles get associated with it. And, you know, I can rearrange the push button. We've showed demos like this before.
But that's not the point of this application. The point of this application is it lets us test out all of the HIV view layout stuff. Now, layouts, simply speaking, are just a way to make a view resize or move when a window resizes. You can think of it that way. So for instance, I've got this view A. I can set up a binding, which is the first type of layout that we support. And I can associate that view with the right hand side of the window.
And when I grow the window, the view stays in place just like you'd expect. And you're not limited to just one edge, of course. I can bind it to the bottom of the window. Let's say it's like an OK button. You know, and it's going to stay in the right place. It's all automatic. I just set up some data structures, call an API, and the toolbox will take care of the rest.
Now another cool thing is that you can do sort of arbitrary relationships. I've associated this view A with its parent, the window, but you're not limited to just parent relationships. I can create another view, view B. Let's move it down here next to view A because I like it there. Let's make it a little bit smaller so I'm at least somewhat close to the Aqua Human Interface guidelines. And I'm going to bind that view, I'm going to bind its right edge to the left edge of view A.
And now when I resize the window, you get this sort of cascade of automatic repositioning. Now, of course, I can bind view B to view A's top as well. And so now you've got a really easy way to keep your OK and cancel buttons down in the bottom of the window.
OK. So-- but bindings are just one of the layouts we support, one of the types of relationships we support. Another thing we support is positioning. And you can think of positioning sort of as alignments. And it's an alternative way to do something we've already done in this demo. So I'm going to go ahead and position A horizontally such that it is now right aligned with the window. So it immediately snaps over there. And it's going to stay over there, just like you'd expect. But positionings also support offsets.
So I think the AquaHuman interface guidelines say that the right offset from the edge of the window is 13 pixels. So let me apply an offset to the positioning I've set up. And it'll stay 13 pixels from the edge of the window. Of course, I can do the same thing to the bottom. But before I do that, let me actually turn off the bindings. Do the same thing, position that 13 pixels up from the bottom of the window.
And A is going to stay in the right place, just the way we want. And B is still moving as well, because it's still bound to A, A's movement. But one other cool aspect is that the relationships are one way. So I can actually move B someplace else, and it'll still maintain B's relative offset from A. So it's kind of powerful in that way. You can move your views around and change the layouts, and things still behave the way you'd expect. Okay, so another cool thing you can do with positionings is centering. Let me clear the offsets.
And I can center A. So A is going to stay in the center. Of course, B is still bound to it. B is going to stay right where we want him to be. And if I clear the centering, I can show you the third type of layout we support, and that's scaling.
I can say, all right, let's say for some strange reason I always want view A to be 50% of the width of the window. I can set that up. And let's say for some other strange reason I want it to be 25% the height of the window. That works as well. So now whenever the window's height changes and width changes, A's size changes along with it.
Now probably the coolest part about layouts is you can mix and match them and combine them. So I'm going to leave A's bindings all set up so that he's staying a proportion of the window size. But now I'm also going to say, all right, center him too. And both of those bindings are respected.
So this is really, really powerful. We switched the new navigation services over to using this stuff, got rid of a ton of code in nav, and it not only library sizes faster, but it just makes the code so much easier to maintain. So if we can go back to the slides now, that'd be great.
So, obviously layouts are cool, but there's some other technical reasons why you might want to use these. It's a very rich descriptive language for associating views together. For one, you can do peer relationships like I showed, A to B. You can do parent relationships, A to the window.
But you can even do strange relative relationships. You could do A to its second cousin if you wanted to. We took advantage of this in Navigation Services as well, and it made some of the relay out of the dialogue that we needed to do to support various optional pop-ups and whatnot. It made that super simple.
The other main benefit is that if you let us do the layout for you, not only do you have less code you need to maintain, but we can make sure that our layout code is as efficient as possible, so you don't have to spend time optimizing it, and we can also make sure we do it at the most optimal time, so that we invalidate as little as possible and cause as little of a redraw as possible. This is about all I'm going to talk about in terms of HIView layouts, but session 425 is going to go into quite a bit more detail. So go check that one out.
So the Aqua Human Interface Guidelines give sort of the desired look for simple about boxes. And yeah, it's really simple, but we figured, well, if we can do that for you, why not? So we added the HIAboutBox API to the toolbox for Panther to do simple about boxes.
And of course, it's going to support everything you're looking for in one of these simple about boxes. It gives you the right look. It's going to display your application's name and version and copyright information. And it does that by looking at your application's bundle, which probably already has that information. So we'll just fetch it from there and display it appropriately. But if you want to customize it, there's two different ways you can customize it.
You can either give us a CFDictionary full of strings with well-known keys and say, "Please use this string for the name. Please use this string for the version," and whatnot. And that might actually be useful for plug-ins that want to display in an about box, right? You wouldn't want the plug-in to display in an about box that points at the apps bundle. So you'd supply your own strings. Alternatively to supplying a dictionary, you can point the HIAboutBox API at a strings file and we'll pull the strings out of there. So it makes it easier to localize and whatnot.
Now, if you use runApplicationEventLoop to drive your event loop, the About box will display automatically whenever the default application object receives the HICommandAbout command. So all you need to do to get one of these wired into your apps is just associate that command ID with your About menu item. It will put it up automatically. But if you need to display it manually, like in the case of a plug-in perhaps, or for a WaitNext event-based application, you can call the HIAboutbox command directly if you need to.
Now, the About box is a mode list window in the document layer of your application. And so, you know, the user's going to expect to click between it, so you need to be prepared to deal with that. You need to be sort of prepared for this other window, a window you may not have created to be in your document list.
And the other thing the user's going to need to be able to do is close it. Well, the About box already handles a bunch of Carbon events on itself. It's standard handler-based, so it's going to automatically close if the user clicks on the Close box. But the user's, of course, going to want to close it by choosing the appropriate command from the File menu. And the easiest way to do that is to put the HICommandClose command ID in your Close window, command in your File menu. Did I say command enough? I think so. Anyway, you get the point.
toolbar was another technology we added in jaguar and uh... found the need to add a few things to that as well uh... the toolbar is set up such that it can automatically save its configuration to your preferences and that's really powerful, it means you have to write less code and uh... the user gets the desired experience uh... but there was a small hole in that plan uh... having to do with custom toolbar items there are some custom toolbar items you may have added to your toolbar and those items may have had their own internal state there may be times when that internal state changes uh... without the user doing something explicit and if that happened there was no way for your toolbar item to communicate back to the toolbar and say hey i'm i'm dirty now you need to save me at the next possible chance so it was possible that our automatic saving of configuration data would kinda would lose some configuration every now and again so we added an API to deal with that which is HIToolbarItemConfigDataChanged anytime your internal state changes in a custom item just call this the toolbar will automatically save your configuration configuration.
A lot of people that use toolbars build them up programmatically. Not everybody can use our sort of automatic regeneration from pref technique. But what we found--and in fact, Finder was one of those clients. They built it up manually from their own preferences store. And what we found is it's actually quite slow because the previous APIs only allowed you to programmatically add toolbar items to a toolbar one at a time.
And every time you add a toolbar item to a toolbar, there's a bunch of Carbon events that get sent out so that all the toolbar views in the various windows that use that toolbar know to update. And then each of those toolbar views says, "Oh, I've got a new view in me.
I think I need to relay stuff out, you know, shift stuff around." So that's a lot of work for every single toolbar item. You multiply that times n items and things start slowing down a lot. So we added the HIToolbarSetItemsWithIdentifiers API to allow you to add a whole batch of toolbar items at once to a toolbar. So if you are doing this custom toolbar creation programmatically, make sure to conditionally use this API on panels. So you can see that it's going to speed up your creation, possibly dramatically, depending on how many toolbar items are in it.
So I'm running out of good segues, so I'm just going to say let's talk about the Carbon Event Manager. We added a few APIs. The first is kind of an edge case usage thing. HIMouseTrackingGetParameters is an API that allows you to ask us how we do our sticky menu tracking in sort of an abstract way.
There's some applications out there that want to replicate our sticky menu tracking. You know, perhaps you're doing something menu-like, or you're doing your own custom menu implementation, something, and you need to behave the same. This API allows you to make sure you're behaving the same with respect to all the things the user's configured on the system and all of that user's preferences.
The next API we added is CopyEventAs. In the Carbon Event Manager, we We transform events as they cascade through the system. A raw mouse down becomes a window content click. A window content click might spawn a K-event control click. The control click will spawn a control track, and so on and so on and so on.
And our model generally dictates that an event spawned from another event should have pretty much all the same parameters as the event that spawned it. And if you're trying to replicate that in your own code, or if you're trying to do some, trigger some functionality in the standard window handlers and you want to make sure you're passing the right kind of event to the standard window handler, the copyEventAs function you might find useful. It allows you to take any given event of a certain class and kind and create another event of a different class and kind while still maintaining all the same parameters that the original event had.
Now, another API we added fills a hole and fixes a performance bug at the same time. You know, we're pushing everybody to adopt Carbon events as much as possible, and we've pretty much got all the bases covered, but we found out that some people still need to use Event Avail and Still Down in their applications for various reasons. We just didn't have a sort of Carbon event savvy version of those. And that's fine. I mean, generally those two APIs give you the information you need, but the real problem was that they were kind of performance hogs.
Not only does Event Avail tell you whether or not one of these types of events is available, but it also calls the run loop, which might fire timers, and it may also flush your windows that are dirty, which means that any given call to Event Avail may take a lot more time than you want it to, considering most people use Event Avail in a fairly tight loop.
So, what we did is we implemented AcquireFirstMatchingEventInQueue, which is kind of like a Carbon Event Savvy version of EventAvail, without all the horrendously expensive stuff underneath it. It just synchronizes our queue with the Windows Server's queue and tells you real quick, "Hey, yeah, this event is in the queue.
Here it is. Have fun." It does not do any flushing or anything like that. So you need to look at your code, find all places where you're using EventAvail and still down, and see if you can switch over to AcquireFirstMatchingEventInQueue for Panther. Additionally, it'll make things an awful lot faster. One sort of important thing to note is that you can't do a direct one-to-one replacement from still down to AcquireFirstMatchingEventInQueue. You're probably still going to want to check button because, you know, that's generally the semantics used--that's generally the semantics you desire when you use still down.
So we had some requests from accessibility developers for a way to look at other applications' events. They, for whatever reason, need to watch the key downs and key ups and mouse ups and mouse downs and other similar events as they happen in other applications, generally for accessibility purposes.
So we invented GetEventMonitorTarget, which returns a Carbon Event event target ref that you can put handlers on for these sort of low-level user events. And it only receives the low-level ones. It's not like we're going to give you kEvent1, window activated events and whatnot. It's just the low level layer.
So you can install handlers for the events you want to see in other applications. And your handler in your application will see those events. The first important note is that there are times when the system puts itself in sort of a secure event mode. Password fields are the best example, right? I mean, if the user is typing in a password field, you don't want other applications to see those keyboard input--see a keyboard input. So we will not send you those events.
The other important thing to realize is that Get Event Monitor Target can slow the system down in general. So you only want to use it when you need to. And those of you who need to use it already know who you are. This is not something for general applications out there. And the reason why it slows things down is because normally as the user types and clicks and stuff, the Windows server just sends events to one process.
Well, with Get Event Monitor Target, if another application installs handlers for key ups, key downs, mouse ups, mouse downs, the Windows server is sending two copies out. And not only are there two copies out, but there are two copies out of the entire system. So you can see that the system is slowing down. And that's why you want to use it when you need to.
And those of you who need to use it already know who you are. This is not something for general applications out there. And those of you who need to use it already know who you are. And those of you who need to use it already know who you are. And those of you who need to use it already know who you are. And those of you who need to use it already know who you are.
And those of you who need to use it already know who you are. And those of you who need to use it already know who you are. And those of you who need to use it already know who you are. And that means your application that's in the background normally being quiet and not consuming any resources is suddenly consuming resources, taking away the user's ability to use the program in the front. So don't use this unless you need to. It's very specialized.
Let's jump right into the Menu Manager. The first Menu Manager API we added is CancelMenuTracking. It does just what you'd expect. It cancels the menu tracking. So if you have some kind of need where you want to programmatically stop the user from tracking the menus-- I don't know, maybe you want to put up an alert or do some other UI-- you can now do so programmatically.
And we also send out a pair of Carbon events whenever the menu bar is shown in hidden. This would allow you to-- certain pieces of your interface may want to show or hide appropriately, like your palettes and whatnot, whenever the menu bar is shown in hidden. So you just install handlers for these pair of events on the application event target, listen to it, modify your interface appropriately.
But probably the best feature we added to the menu manager was support for HIView-based menus. Now, coming into Panther, we'd already HIViewified most of the system, right? HIViews are controls, so that was already done. The window manager got changed so that now window frames and whatnot are drawn with compositing views, so that was all in place.
But the big missing piece was the menu manager. And the menu manager was kind of this weird environment where you had a quick draw port that didn't really point to anything besides some buffer of bits that the menu manager managed. And on 9, it would look those to the screen, but on 10, you know, we got some other functionality for free. And MDEFs were confusing, I guess, at best, and hard to do. And therefore, you didn't see a whole lot of custom menus.
Well, HIView-based menus changes all that. Makes menu customization super, super easy. But you just need to know a few fundamental principles. And for those of you who understand HIView already, this is going to be really straightforward. So if you've got HIVs, you need compositing windows. And that means every menu is now drawn in a compositing window, just like you'd expect.
It has the normal view hierarchy of a compositing window. There's sort of a structure view and there's a content view. But there's a few special nuances of a menu view system that you need to be aware of. And the first is the notion of the menu content view.
The menu content view lives inside the window's normal content view. And the menu content view's responsibility is to draw all of the menu items. So of course, we have a standard menu content view for our menus, and that's what draws icon text, command key, and whatnot. Now the window's normal content view is where the menu background gets drawn. In the case of our standard one, we draw those Aqua lines.
And if you're going to write one of these custom menus, you need to be able to find out--you need to be able to go back and forth between views and menus. So we've got two APIs that facilitate that functionality. HIMenuGetContentView says, "All right, given this menu ref, give me the content view that's going to render it." And there's the inverse as well, HIMenuViewGetMenu, which is really useful for inside your custom menu view, right? You need to know which menu to render so you can ask for it with that API.
Now, there's not a lot of custom menus out there because it's hard, but let me give you a little advice on why you might want to make a custom menu and show you a couple examples. Basically, you'd want to do a custom menu to get functionality that isn't already provided by our system menu. That is, to get a menu that's not just, you know, text command keys. Good example of that would be something like the finder. In Panther, the file menu now has a menu item that allows you to change the label of any given finder item.
And that's actually done by a custom HIView that's inserted in that menu implemented by finder. Another example that was shown up here in the center is something like, we call an XY menu. It would be great for like a color sort of palette like we show there, or maybe some kind of tool palette.
And lastly, some menus in our system really aren't menus, right? If you look at the volume menu in the right-hand side of your menu bar, it's got a slider in it. It's not much of a menu, but it displays like one. Guy Fullerton So, if you want to make a custom menu, you to do some functionality like that, you would do it with the custom menu.
Making one is very straightforward if you already understand the architecture. We introduced HIObject in Jaguar. It's the object model. You can derive from base classes, and we provide the base menu content view class as KHIMenuViewClassID. So you derive from that using the HIObject mechanism. Now that you have your object class, you can associate that view class with any given menu, and then when that menu draws, it's going to display with your--it'll actually create an instance of your custom view, and then draw with that custom view. And since it's a normal HIView in a normal compositing window, you can embed other views inside your custom view as you need to. And after you've done that, you just want to handle five fairly straightforward Carbon events.
And in fact, they're very familiar Carbon events that we've already had on the system for a year or so. But the important thing to understand is the protocol the menu manager uses with respect to part codes. So the control manager and HIView often talk in terms of part codes, right? What part of a control was hit? What part of a control is the mouse over? But the menu manager always talks in terms of menu items, and it wants to know the same pieces of information. So the protocol with respect to menu content views is that part codes correspond directly to the equivalent menu item. If you receive an HIView event that's asking for information about part code five, give it information about menu item five.
So the first event you want to handle is KEventControlDraw. And in fact, you wouldn't necessarily even need to handle this if all of your drawing was done by just embedding other HIViews. But the responsibility for KEventControlDraw, or for your content view when it receives this event, is to draw your menu items really straightforward, forward. Draw them however you need to draw them.
But as the user's tracking the mouse over a menu, the menu manager wants one of those items highlighted, of course. So you need to draw that highlighted. The way you find out which item is highlighted is by looking at the focused part of your menu content view. So you can call HIView getFocusedPart. That'll tell you the menu item that's currently highlighted. So you draw that in the inverted manner, or whatever is appropriate for your custom menu.
Now, the second event you want to handle is KEventControl hit test. The menu manager will send this event to your custom menu whenever it needs to find out which item is under the mouse. So all you need to do is look at the coordinate in the event. It's a view relative coordinate.
Figure out which menu item that corresponds to and pass that back in the Carbon event. And similarly, the KEventControl get part region Carbon event will be sent whenever the menu manager needs to know the total area that that menu item occupies visually in the menu. So you look at the incoming part, you build up a region that represents the bounding rectangle for that item, pass it back in the event.
The fourth event is KEventControl Get Optimal Bounds. The menu manager will send this to you sort of early at menu time when it needs to figure out how big your menu would ideally be, right? This is assuming you've got infinite screen real estate. So if you've got an 8,000 item menu, make sure you return a really big rectangle. But the--one thing to note is that your menu may be sized smaller to fit on a screen, just like you'd expect, so you need to be prepared to deal with that.
And the way the menu manager does scrolling, most of it is actually handled automatically for you. But the way it scrolls you is by offsetting your content view's bounds origin appropriately. So in your draw handler, what you can do is look at your bounds origin and constrain drawing appropriately to cover only those items that are visible on the screen, which will speed up your menu a lot, right, if you've got a lot of menu items that aren't displayed. There's no point in drawing those.
So there's one last Carbon event you need to handle, and that's to facilitate scrolling. It's KEventScrollableGitInfo, and we introduced that in Jaguar as part of the HI ScrollView Carbon Event Protocol, but we're leveraging it here. There's about, I think, four or five pieces of data that you need to provide in this event to the menu manager.
Take a look in Carbonevents.h--actually, no, I think that one's in HIView.h--to see what those parameters are. But they describe things like how much of you is visible, how much total of you there is, how much you want to have scrolled every time the user--or sort of in every scroll increment, right, that kind of information. It's really straightforward.
And the rest of the functionality is all going to be taken care of for you by the base menu handling, right? So if you just implement those five Carbon events, you're going to have a custom menu up and running. But there's a few more events you might want to handle for various other reasons, if you need to do further customization or change sort of the default behaviors. So the first of those is KEventMenuCreateFrameView.
This event is sent to your menu content view when it needs--when the menu manager wants to know what the window frame view should look like. This is the thing that actually draws the menu background. By default, the base handler will create a frame view that will draw the normal Aqua line background. But if you want a custom background, like a picture or something, you can handle this event and create your own view and do whatever drawing you need to.
The second event is KEventMenuGitFrameBounds. This event is sent to the ContentView to determine where the total menu area should be displayed globally on screen. Generally, they're going to pop down from the menu bar, but you might have a pop-up button or something, and it needs to position appropriately relative to the item that the caller called pop-up menu select with. So there's a whole bunch of data that gets passed into the GitFrameBounds Carbon event, so you can decide or customize how exactly you want it to be positioned on screen.
Then finally, does the K event menu become scrollable Carbon event? This Carbon event is sent to your content view whenever your content view is a candidate for scrolling. And this will happen whenever your content view represents the sort of leaf-node menu, right, of a series of menus, because that's the one the user can type select in.
So you'll receive this event and you can either block the default scrolling behavior if you don't want any scrolling for some reason, or you can do your own scrolling behavior if you've got really unique needs. You know, maybe you need to scroll horizontally through a menu or something, who knows. And so it comes with a lot of info you can look at.
Generally, you want to--when you receive this event, you're going to want to install a bunch of event handlers on the menu's window so that you can receive other input and whatnot. And then when your menu is no longer a candidate for scrolling, we send the K event menu cease to be scrollable Carbon event to you. And that's where you tear down all the handlers you set up when you became scrollable.
So that's just sort of one technique-- sort of the comprehensive technique for creating a custom menu. But it's certainly not the only technique, right? If you've got a composited window, you can do just about anything with that thing. There's all kinds of Carbon events you can hook into to create views, and you can use existing views on the system, and install Carbon event handlers to handle user interaction and all that stuff.
So there's lots of other techniques. We've got a piece of sample code out there. It went on the website earlier this week, so I suggest you go check that out. It shows, I think, about four different custom menus. In fact, that was the app I used to take the screenshots a few slides back of those custom menus. So it'll show you how to do all three of those custom menus, plus one additional one, which puts a picture as a menu background. So it's really, really good sample code.
Let's jump right into the Window Manager. So the first API we added there is HIWindowChangeClass. Now this is really cool because it allows you to sort of polymorphically change a window from, say, document to floating and back. So you can do some really interesting UI there. You can sort of promote things to a floater, you know, change them around a little bit, so that's really neat. The next API we added is both sort of a technology thing and a convenience thing.
Right now, if you need to programmatically flush a window to the screen, the only way to do that was with the QuickDraw API. And if we're really moving towards Quartz, it doesn't make sense to keep you guys using the QuickDraw API to do the flushing. So now HIWindowFlush allows you to do a flush on just a window ref. You can, you know, completely ignore the implementation details of the fact that there's a port there.
The other benefit is that flush time now in the toolbox is more than just painting the bits to the screen, right? Guy Fullerton We do other interesting things in the context. We have a compositing view system, like right at flush time, we look to see which of your views are dirty, and we tell them to repaint right now, and then we can flush that to the screen. And similarly, window shadows often need to get recalculated right at flush time.
So this HIWindowFlush API is this one-stop shopping API to just say, "Hey, blit this window the way it needs to be blitted now." With the advent of sheets, more and more applications are adopting them and probably the number one piece of feedback we heard about sheets is that you've got a document window, an error happens, you put up a sheet. That document window is still sort of mode-less with respect to the rest of the windows in your app and you might get into a situation where you need to display another sheet on that same document window.
But the Aqua Human Interface Guidelines say, "No, you shouldn't do that." And unfortunately, there's no really good way to find out if you've already got a sheet on your document window. So, HI Window is document modal target is designed to solve that problem. It tells you easily in just a one-stop shopping API for whether or not there's a sheet on your window.
We also have a detached sheet window API which will allow you to create a sheet, display it and then recycle it for display at a later time as opposed to just disposing it and then creating a new sheet later, right? So, this will buy you a little bit in terms of efficiency if you're constantly reusing a particular type of sheet.
We also send out a couple new Carbon events having to do with Windows. You can think of this as a Carbon event hook. KEventAppActiveWindowChanged gets sent out whenever the active window in your application gets changed. So if you need to maintain state or update some UI based on whatever the active window is, you can just install a handler for this event on the application target, and you'll be notified whenever that happens. Now the window manager will automatically take care of rearranging windows on the screen whenever the monitor configuration changes, or whenever the dock moves from the bottom over to the side.
So the window manager will already do that, and it sends events to your application. I think they're KEventWindowConstraint events to each window, so each window can deal with it itself. But if you need a global way to hook into that and replace the window manager's entire batch of functionality, you can now install a handler for KEventAppAvailableWindowBoundsChanged on the application target, and then completely replace the window manager's functionality if you need to.
So we also enriched the existing window transition API. The coolest part now, as you can see, is we now support a genie transition effect. So you can genie whatever you need to whenever you need to. It's not just for coming in and out of the dock. And it'll give you the standard UI for it, so you're going to match the rest of the system. Now, we also came up with a new API called Transition Window with Options. It's going to look very familiar because it's based off the existing transition window API. But some of the options it allows you to customize, it has to do with durations.
You can make, say, a window fade transition as fast or as slow as you want. You can speed up or slow down the genie effect as you need to. And it also supports asynchronous transitions so that you can just call Transition Window with Options. It'll return immediately, and the transition will happen sort of behind your back without you having to block, so you can continue processing.
Now of course, if you're using asynchronous transitions, you probably want to know when the transition's finished. So we have a pair of Carbon events to help you out with that. We have a kEventWindow transition started event. It's sent to the window right when the transition starts, so you can set up any state you need to maintain. And then a kEventWindow transition completed Carbon event when the transition is finished.
Now, performance is not all just about super-duper fast code. Super-duper fast code helps, of course, but it's not the end-all, be-all. Some of it has to do with perceived performance. How fast does your app seem? And one way we facilitate that on Panther is through asynchronous window dragging.
So traditionally on Mac OS, when you wanted to drag a window--sorry, this is on Mac OS X--when you want to drag a window, you click on its title bar, the Windows Server has to send the click event to your application. Your application catches that event, and either you call drag window or the toolbox calls drag window for you, and then the user starts moving the window around.
And there is a slight lag there, right? There's a cross-process message that has to be sent. So if we can actually allow window dragging at the Windows Server level, that process is going to be--we're going to eliminate the cross-process message, and the drag is going to start virtually instantaneously. It's much, much faster perceived performance.
The secondary benefit is that if your app is busy, if you've got the spinning cursor of death, or if you're doing some intense computation and you can't service events very often, the user will still be able to click your window, even if your app is not generally responsive.
Of course, the best part is that it's real easy to turn on. We've got a new window attribute, kWindowAsyncDrag attribute. You can specify that attribute either in Create New Window or Change Window Attributes later if you need to. But there's one very, very important caveat. Because the Windows Server is handling your window dragging, you are not going to receive a steady stream of kEvent window bounds changing events as the window is dragged around. You will get them occasionally, but they will be sort of like a hiccup effect. You'll get them every now and again, sort of as the user pauses.
So if you were relying on kEvent window bounds changing to do some sort of custom window drag gridding, you know, you want it to snap to various locations or snap toolbars together and whatnot, it's not going to work real well with async window dragging. So you've got a couple options there. The first is just don't use async window dragging. You don't have to use it for all the windows in your application. If your interface is better served by that gridding, you know, keep doing that gridding. Don't turn on async for those windows. That's fine.
Alternatively, we do send out a kEvent window drag completed Carbon event whenever a window drag is finished. So one thing you could do is install a handler for that event instead of the bounds changing events. And then let the user drag the window all around the screen wherever. Don't do the sort of live snapping. And then when the drag's finished, you'll get the drag completed event and you can snap the window to the correct location then.
So you've got a couple options there. The other real important thing to realize about asynchronous window dragging is that if you turn this on, you don't want to call drag window when you finally receive the mouse down. Because you will receive that mouse down in your application. And if you turn on async dragging, receive the mouse down, and then call drag window yourself, you're going to get a really weird effect as the window sort of jumps around between two different locations. So make sure to take out your calls to drag window and similar APIs.
So I've talked about an awful lot of stuff, and that's not even it. I mean, we have a couple other sessions for HIToolbox where we talk about entirely other pieces of functionality that we've added. But that shouldn't stop you from going and implementing some of this stuff now. There's a lot of quick and easy things you can do.
You can conditionalize some of your code for Panther such that it uses the HITheme APIs instead of the Appearance Manager. You're going to get a lot of performance boost from that. You can use the replacement for Event Avail and Still Down. You can start adopting the new Aqua widgets, right? Start using that search field. Start using the segment view when it's finally available.
But even more important than that is if you haven't started looking at the new technologies and our underlying foundational technologies, you've got to start looking at that now. More and more of our stuff is only going to work under this new model. You need to start learning about compositing. Try turning on the standard window handler in some of your windows.
You are going to run through some issues. There is a little bit of a code thrash that needs to happen, but it's not a very big code thrash. So go turn those things on. Start iteratively making these improvements to your application so you'll be completely flexible as we throw new technologies out there for you to use.
Now this is something we actually did for the new navigation services for Panther. The old nav was completely dialogue based. It did all the event handling itself except for a few edge cases. Therefore, nav was a really big binary. It did a lot of work. So as part of the new UI, we actually switched navigation services over to using the standard handlers, over to using compositing. And sure, it took us a little bit of time, but the end result was great. We gave much better performance. We got to adopt all the new widgets. We got to use the segment view and whatnot. We got to use data browser and compositing mode.
But the best thing is that we got rid of a lot of code out of nav. The nav binary, which is more now in Panther than it did in Jaguar, is still 10% smaller than it was in Jaguar. So for your applications, that's going to mean quicker download times, less paging that needs to happen when your application is loaded and things like that. So you got to get out there. Start adopting these new technologies and move your applications to the future of Mac OS X. So now I would like to bring back up Xavier to take us through the roadmap and some Q&A.
Good job. All right. We have a couple of things that are very important to understand, and hopefully that will make sense for you guys on what we've been trying to achieve this year with the sessions for Carbon developers. Very important, the data exchange option for Carbon application. We have brand new services for the PACE board.
A new type, which is the UTI, the uniform type identifier that we're going to be talking about. If you're interested in using that, go and see that, because you'll have to use that in Panter. If you need more information about HIView, if you have custom controls and you'd like to take advantage of core graphics and this new compositing view model that we have, please go to the session 425 Carbon, where we'll talk really in detail about HIView and how your application can take advantage of this technology. Two very important sessions this year, we have something specific for optimizing performance for Carbon applications.
We're going to be actually taking you guys through a bunch of steps from networking, file I/O, what you should do with Carbon events, what type of compositing you should use when on what windows. We're going to talk about things like APIs that maybe you should start moving out of, that we should not be using anymore. A very, very good session. We have session 307 that's going to be specifically for Carbon development and Xcode, the new tools we released.
The tools team has made a major effort to actually have the tools integrate very well with what Carbon developers are doing and with HIView, of course. You saw a little bit of that through interface builder, but Xcode has some pretty cool built-in support for debugging Carbon applications as well. Can I add one thing? Hey, David, what's your session number? 4:23? There is one session that is not there, which is session 4:03. Very cool session.
A lot of people, primarily like you know, are in my case, which is you know we all have applications for Mac OS 9 but are using Power Plant. And we have all these different technologies in Carbon to use and we're wondering, well, where should I start? That session is going to be specifically on how to build a modern C/C++ application on Mac OS X.
So you can think of it kind of as a refresher course, if you need to kind of get reminded of what the right way to do things are, you know, to use run application event loop instead of wait next event and things like that. You know, it'll give you the right pointers toward using the modern APIs. It's what makes you know a modern C++ application, C or C++ application on Mac OS X. What should you use? We'll go through a Carbon event, HIV, we have like a bunch of things for that.
I encourage you to assist to that session. I got him back. Should you need any questions, you can contact me at xavieratapple.com. There is always my manager in case I don't answer and I'm in Tahiti or something like that. And John Galenzi is also a really good guy if you have Aqua questions. John Galenzi is actually our user experience technology evangelist.