Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2006-105
$eventId
ID of event: wwdc2006
$eventContentId
ID of session without event part: 105
$eventShortId
Shortened ID of event: wwdc06
$year
Year of session: 2006
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC06 • Session 105

HIToolbox State of the Union

Application Technologies • 1:03:13

Take an in-depth look at the latest improvements to the HIToolbox framework in Mac OS X. This session will demonstrate the most recent features including HiDPI - resolution independent views, embedding NSViews within HIViews, 64-bit capable Carbon APIs, and more.

Speakers: Guy Fullerton, Eric Schlegel

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Hello. Welcome to the HIToolbox State of the Union session. My name is Guy Fullerton. As they said, I'm the manager of the high-level toolbox team, and I'll be joined a little bit later on by Eric Schlegel, one of our engineers that I'm sure you've seen over email a bunch.

So the reason I'm up here first is I want to talk a little bit about the future of Carbon UI programming on Mac OS X, specifically the HIToolbox APIs. In short, the future of the HIToolbox is Cocoa, integration. We are adding a lot of features to Leopard to make HIToolbox and the Carbon interface layers play well with Cocoa.

Our plan is to put no new large-scale HIToolbox features in place where those features already exist in Cocoa. What we want Carbon developers to do is start using the various Cocoa views in their Carbon applications, start using the various Cocoa windows in their Carbon applications, and so on.

So my team is focusing most of our energy on doing things like 64-bit resolution independence, but also on putting bridging technologies in place so that you can use these awesome Cocoa features in your Carbon apps. The most important detail is that we're not putting C wrapper APIs out there. You have to use Objective-C to get at this functionality. We're not going to be in the business of wrapping these APIs and having to maintain them.

It's also important to note that we're not completely stopping development on Toolbox. We're not deprecating it. We will put features in place where they make sense. We will continue to put bridges in place. We will fix bugs where we need to. And where we already have a view in HiToolbox that Cocoa has a view for, and where our view lags a little bit behind that view, we'll probably put those mini features in place. A great example of this would be the segmented view. The Cocoa segmented view supports menus in a segment. The Carbon one does not. That's something we would enhance in the Toolbox.

So there's a lot of great reasons to do the Cocoa integration. The main reason is a user level reason. Every time we have parallel implementations of a feature, we get details wrong here and there. The different implementations have different sets of bugs. Sometimes their features work a little bit differently or react a little bit differently to user interaction, and that's a big pain, right? It's a pain as a user because you're used to using a control that works one way, you go into another app and it doesn't quite work the same way. Worse yet, you've got something like Navigation Services in Carbon and NSOpenSave in Cocoa, and there are some fairly glaring behavioral differences between those two, which makes navigating around the system just a pain.

So the other benefit of pushing Cocoa integration is to improve your applications and improve the experience for all users that use your applications. Clearly, by allowing Cocoa integration, your apps can now offer all of this cool Cocoa value to users. You can take advantage of all these features the Cocoa teams have been adding.

But more importantly, we now reduce the number of engineers that we have working on parallel features between the two stacks. And we can spend those engineering resources doing other cool things in one place that your application can get for free. And I'll talk a little bit more about some specifics very soon.

To find out about using Cocoa in Carbon applications, there are a couple points you need to realize, a couple basic things you need to do in your applications. We're going to cover this in more detail in a particular session later in the week. But essentially you need to make sure that the NS application is instantiated properly.

You need to set up an auto-release pool in certain situations, and in very rare but well-defined situations, you need to set up an NS graphics context. Sometimes the graphics context will get set up implicitly based on what you're doing. But we talk about that more in another session.

So the first big way we are pushing Cocoa integration in the Leper Toolbox is by what we call the HICocoa view. The HICoco view is an HIView. It's a Carbon HIView that allows you to embed basically any NSView into your Carbon hierarchy. We've done this a little bit before with the HiWebView, but the HiWebView really wasn't good enough. It was a standalone view that sort of wrapped the WebKit view, but it wasn't very good. Well, the HICoco view is tied directly to the Carbon and Cocoa frameworks. We're making changes to both frameworks to make them play well together, and the Cocoa view is that bridge.

It's important to note that the CocoaView supports compositing windows. We might support non-compositing windows. It's not currently a goal. Supporting non-compositing is often asked for by developers, but we're pushing so much technology out at you this year that requires you to get off of non-compositing mode that I'm not sure I really want to support non-compositing mode in the HICocoaView. For example, 64-bit, no compositing mode. Resolution independence, no compositing mode. So we really would love to avoid having to support compositing mode in the HICocoaView.

So let me show you the Hikoku view in action and give you an idea of what it can do. Can we switch over to the demo machine? Okay, so this is one of our test applications that we are using on Leopard to test the implementation of the HICocoView. Let's go ahead and run this.

And any day now. Sorry, I should have built it in advance. So what you get is a Carbon composited window with a bunch of Carbon controls in it that allow you to choose and manipulate various Cocoa views. So there is an HICoco view up here in the top left-hand corner of the window, and I put it into editing mode so I can actually change the HICoco view size. And that will become useful as I choose different views.

So I've got this HICoco view in the window, and I'm going to tell it to embed a Cocoa push button in the HICoco view. Now you have a Cocoa push button in the window. That's a real live Cocoa push button reacting with COCO's event handling logic and so forth. There's a little bit of a bridge layer with our HIView, but it's basically working.

And of course, you can do various other sorts of controls, the basic controls. But most importantly, you can do controls that we don't have in Carbon. We have a token field editor in Cocoa. We don't have one in Carbon. We had a feature saying we should implement a token field editor in Carbon, but what we found is that the token field editor for Cocoa just works in our HICoco view. So that's how we're going to give Carbon developers a token field. You're going to adopt the Cocoa one.

You can also, let's see, You can throw a web view into a Carbon window and it's a fully functional web view that works better than the

[Transcript missing]

QtKit is the only way to get QuickTime content in 64-bit. There is no Carbon-based movie control. The old Carbon-based QuickTime APIs that can draw a movie into a port don't exist.

So the only way you can get QuickTime content in a 64-bit Carbon app is by using the QtMovie view, and HICocoView facilitates that. So I've got... A movie playing in the Qt movie view sitting inside a Carbon window and it just works. And the audio works too, we just haven't turned it on on the demo machine.

Let's see what else is we're showing. That's probably about it. Okay, so let's go back to slides. So you can see that this works. There are a few rough edges, but we're going to make sure all those rough edges are sanded off by the time we ship Leopard. We want this to be basically a perfect experience. So can we switch back to slides? So the CocoaView is really easy to deal with.

It's just an HIView. If you're used to using HIViews, you're going to be used to using the HICocoaView. We've got a creation API, and we've got a way for you to get and set the NSView associated with that CocoaView. So there's a little bit of a terminology strangeness here. When I refer to the CocoaView, I'm talking about the HICocoaView, the Carbon view that wraps an NSView. And other times I'll be referring to an NSView, which is the actual AppKit-based view.

So once you have an HICocoView, if you need to manipulate various pieces of state on the NSView at wraps, it's generally best to use the HIView and call various APIs on it to set things like activation, visibility, and bounds, and so forth. And the HICocoView automatically propagates those changes to the NSView as appropriate. If you need to actually deal with the NSViews specific functionality, you'll have to use the Objective-C APIs with that NSViews API set as appropriate.

In order to create an HICocoView in IB in the leopard seed, you need to drag out a custom HIView and set its HIView ID. And once you do that at runtime, you can load your NSView into it. We want to expand the IB support by the time Leopard ships, but this is as far as we've gotten in the seed, so just be aware of that.

Our initial goal for the HICocoView was to support three or four different views. Specifically, we wanted a replacement for the HiWebView because it wasn't very good. We wanted to support the PDFView, we knew we needed to support the QTMovieView, and we knew we wanted the token field. And so that's what we were basing our engineering around, is making these four views work rock solid.

So as we were doing our work, we found that, wow, look, basically all the other CocoViews work. Now it's possible you'll find some that don't. If you do, please let us know, write up bugs, we'll try our best to make those work. It's also possible we won't quite be able to make all of them work.

There could potentially be some problems that we just can't solve in our bridge, and what we may have to do in those cases is make some of those NSViews rev to know that they're in a Carbon window and behave a little bit differently, potentially. So if you do find problems, let us know and we can take those steps if we need to.

So there's a couple usage limitations you need to know about. The first is that once you have an HICoco view, the only thing that should be embedded inside of it is an NSView. Don't put any other HIViews in it. It just won't work. That HICoco view and the Carbon compositing draw pipeline expect there to just be an NSView inside.

Of course, that NSView could be a hierarchy of other NSViews. In fact, that's exactly what happens in the WebKit view case, right? The WebKit view is potentially other views and cells for text editing and buttons and so forth. So that's fine. Just make sure that you don't put any other HIViews in your HICoco view.

Now, Cocoa allows you to do a certain amount of multi-threaded drawing, but Carbon's drawing model is inherently single-threaded. Carbon cannot handle drawing on multiple threads. So if your Cocoa view that you want to use draws on multiple threads, that would be a usage limitation. You won't be able to use that with an HI Cocoa view, and that's not something we can fix. We have no plans to take Carbon's entire compositing draw model and making it multi-thread safe.

So before when I said if you want to do state changes to the NSView, you should call some of the state change APIs in the HIView set, and we propagate those as appropriate. Don't do the reverse. If you set the bounds on your NSView, it's not pushed back up to the HIView. It's still respected at the NSView level, right? You can make your NSView bigger, just the HICocoView will be smaller and therefore will clip your NSView. So generally for those kinds of state changes like bounds, call the HIView API. Don't call the NSView API.

We haven't wired up accessibility yet in the seed. This is something we definitely want to do by the time Leopard ships. In fact, we want to make the Carbon-Cocoa accessibility integration story a lot better in a lot of ways, not just at the view level. There are a lot of window integration bugs as a result of bringing up font panels and color pickers in a Carbon app where it just doesn't quite work right in accessibility.

So we want to smooth over all those rough edges. Another way we're really pushing the Cocoa Carbon integration in Leopard is by essentially gutting navigation services. We scraped out all the code underneath it, kept the APIs in place, and just rewrote those APIs on top of the Cocoa NSOpenSavePanel APIs.

We did this mainly for two reasons. One, it's going to make our own lives easier in the long term because we only have one code base to maintain. But from a user perspective, we get rid of all those horrible interaction and parity problems between the two different implementations that behave very differently. So we get rid of a lot of bugs in the process. And that lets our engineers spend more time on doing cool things in OpenSave like, I don't know, adding icon view and various other things that are widely requested features.

So, since we basically reimplemented the Nav Services APIs, your apps, when they run on Leopard, get the Cocoa OpenSave implementation for free. It just happens. Now, that's the default, but there are some caveats. There are some ill-behaved applications that make bad assumptions about Nav Services dialogs. They may assume that the Nav Services dialog has a diddle and the fourth item is the OK button, and they try to manipulate that OK button.

And in stranger situations, they try to navigate down the hierarchy to find the data browser to change the way the data browser acts and various other weird things. Those apps already have a number of different compatibility workarounds put in place for them on the system to maintain those legacy behaviors. If your app has some of those workarounds in place, you're going to get the old Navigation Services implementation.

So, if you are one of those apps, what you want to do is - our developer relations folks have tried to contact you and let you know what you need to change in your code. Change that in your code, deploy with a new version in your application, and you will get the Cocoa-based OpenSave implementation for free. Now, that said, even though you get the Cocoa version for free, you may want to do some explicit adoption. One cool thing we did is take the NavDialog ref address.

That address really is just a pointer to an NSA panel or an NSOpenPanel. You can cast that to one of those two types and start calling Objective-C methods on it if you want to trigger Cocoa functionality. So that's one possible way you could do the kinds of things you used to be doing by hacking the Carbon version. You can just now do it in a clean way using the Cocoa APIs. Guy Fullerton, Eric Schlegel So I already talked a little bit about application compatibility, but there's a few more details.

We are going to add an opt-out mechanism for the automatic usage of the Cocoa OpenSave panel for Leopard. So your application will be able to put something into its bundle that says, "I want the Carbon version for compatibility." So you'll be able to let us know if you find problems that we haven't found. If you do opt out, however, you miss some big pieces of functionality.

The Cocoa OpenSave panel is being revved to support icon view. It's being revved to support better searching and various other cool things. And we're not revving the Carbon implementation and navigation services to support those. So if you opt out, your users don't get any of those cool features.

So, just to restate our Cocoa integration story, this is not a deprecation. Your application will need to use Objective-C to get at this functionality. But the benefit is you'll get all this cool stuff that's in Cocoa. Now we know there's a little bit of a religious war, Carbon versus Cocoa, on the mailing list and so forth.

Our stance internally - we work right next door to the Cocoa team. We're great friends with them, we hang out with them in social events and so forth. And there's no animosity at our level. We don't want there to be animosity on the developer level. What we want developers to think of is that there aren't Cocoa and Carbon applications.

There are Mac OS X applications. And the best Mac OS X applications are going to take advantage of all the APIs on the system wherever there are great APIs. Don't artificially limit yourself to one API set because you want to be Cocoa or you want to be Carbon. Just use the best APIs you can and deliver the best user experience.

So one way you can start doing that now in your applications is if you're already on the path to deliver a partially Cocoa-based Carbon application in the future, one thing you might start doing is implement your custom content as an NSView instead of an HIView and leverage HICocoaView. Embed your NSView in an HICocoaView and deliver that in your application on Leopard. And that gives you a leg up for the future. Now you have an NSView in your hands for when you eventually do move that window to Cocoa. So you'll be in great shape.

It's also very important to note that this is a high priority task for us. We need to make this rock solid in order for there to be any adoption. So any bugs you find, even the most trivial bug that you think we probably already know about, file it anyway. I don't mind getting hundreds of duplicates. What I want to make sure happens is we deliver a rock solid implementation, not something that was a little flaky like the HIMovieView. So please file those bugs.

[Transcript missing]

Thank you, Guy. All right. So that covers some of our Cocoa integration technologies. But we have been busy with a lot of other changes in the toolbox in the past year and a half or so. And I'm going to go over some of the big ticket items here that we've been working on that we'd really like you to take advantage of and be able to adopt in your applications. Here's a quick list of the topics I'm going to cover here. 64-bit, of course, is one of our really big changes in the Leopard HI20.

We have a new API that we've provided in the toolbox that's been covered widely in the conference already so far. And we do have 64-bit implementations of all the HI Toolbox frameworks. Resolution independence, a technology that we introduced first in Tiger, and we're completing that in Leopard. We have a new capability to be able to handle Apple events using Carbon event handlers, which can be handy in certain circumstances.

There's a new API that we provided in the HI Object Manager called HI Object Delegates. We're enabling you to embed HIViews inside menus, which is something that's already been used in a few places in the system, and we're going to make it easier for you to do that in your own applications. We have new support for using files to show image content inside some of the standard views. And finally, there's a new API called TextInputSources that the Text and Graphics group has done, and that's going to be a replacement for a number of deprecated APIs.

So the 64-bit HIToolbox. I think you've probably heard a lot of this if you've been going to the other keynote sessions already. But some of the reasons why we're going to 64-bit, obviously the industry as a whole is going that way. Windows Vista, Windows XP have 64-bit versions, Linux, Alaris. The hardware is continuing to evolve.

We are shipping more and more memory in our baseline configurations. The new Xeon machines can go up to 16 gigabytes of memory, I think. And there are performance advantages. Especially in the x86 ABI, if you compile your Intel application using the 64-bit x86 ABI, you can get improved performance for your code. And also just user demand. As your users try to use larger and larger data sets, you are going to find some performance advantages and your users are going to want your applications to be 64-bit in order to deal with those large data sets.

So we're going to be taking out a lot of old legacy API in the 64-bit HIToolbox. We're really using this as an opportunity to clean up a lot of this old API that came across from classic Mac OS. So non-compositing mode is not available at all in 64-bit HIToolbox. Quick draw, as has already been mentioned, has been removed.

There's no support for CDEFs, for MDEFs, or for WDEFs. The FS spec type in the file manager is no longer supported. Pascal strings are also gone. That's really, you know, very legacy technology there. And using Quick Draw Text or the TextEditManager to draw or edit your text are also not supported in the 64-bit version.

So we're really focusing very tightly on supporting those modern APIs that we've been talking to you about probably for the last five years or so to get you moving on to these modern set of programming interfaces. So compositing mode is the most significant example here, and Quartz. Your 64-bit toolbox application must use compositing mode and it must use Quartz to draw. That's the only interface we're going to support.

You must use custom HIViews to draw your content. That goes right along with compositing mode. You must use FSRefs or you can also use CFURLRefs to identify your files. You must use CFStrings or some other similar type of Unicode-based string API to contain your strings whenever you're passing a string into the toolbox to change the title of a window or a control or anything like that. The only text editing APIs would be MLTE. The text drawing APIs would be ATSUI or the new core text and core font APIs that we're introducing here this year.

And we're also providing a number of new APIs to replace some of the APIs that we've removed. So I'll talk briefly about some of those a little bit later, and we're going to have more APIs introduced after the developers conference that we didn't have time to do yet.

I'll touch briefly on a few legacy APIs that we are still providing. The point here basically to provide these is just to make your lives easier when you're trying to port your applications to 64-bit. We're getting rid of a lot of things that really don't make any sense at all, but we are keeping some just because we want to make your path easier to get over to 64-bit, and we don't want to throw up arbitrary roadblocks in your path. So here are some examples.

The classic event manager, the event record type, wait next event, etc. are still supported if you need them. Of course, we don't recommend that you use any of these. We highly recommend that you use Carbon Events and not the classic event manager, but it's there if you need it.

The dialog manager is still supported. Note that the dialog manager only creates compositing windows, though, in 64-bit since there are no non-compositing windows. The scrap manager is still supported. We have a replacement for that since Tiger or Panther, I can't remember which, Brian will tell me. The pasteboard manager, so we recommend you use the pasteboard manager, but the scrap manager API is there as well.

So developer adoption for 64-bit is really pretty similar to the original Carbon story. The original Carbon story was if you've been keeping up with us, if you're using the Appearance Manager, if you're using more modern APIs, then it's easier. If you're using Nav Services, if you've already converted to Nav Services, then you don't have to get rid of standard file in your application, for example. The 64-bit story is very similar.

If you've been keeping up with all the APIs that we've been talking about over the last few years, then 64-bit is actually not that bad. It's pretty easy to get a modern application running in 64-bit mode. We've done this with several apps, and it's not too hard. If you've got a lot of old API usage in your application still, if you're using non-compositing mode, if you're using Quick Draw to draw, if you're using FS Specs still, which I hope you're not, but if you are, you're going to have a lot of work to do because all those old APIs you have to take out first and replace with the more modern APIs. So, I'm going to go ahead and get started.

So we've got some common types, things defined in MacTypes.h that are now 64-bit compatible. Byte count, byte offset, some other things. Some of the core foundation types have been made 64 bits wide. So as you go through your code to think about what do I need to change to become 64-bit compatible, think about using these types in your code. So, for example, don't use an int to represent a byte count.

Declare your variable as type byte count and then you'll automatically go up to 64 bits when you're compiling for a 64-bit target. Some of the other standard types, UN32, SN32, the obvious ones, well, they say right there in the name, I'm 32-bit, so that's where it still is. Those are still 32 bits wide. So that's another case where you might want to think about.

I have a UN32 value here and I'm using it to represent... The size of this block of memory. Well, that might not be the right type to use. If you're compiling for 64-bit, you might want to change a UN32 variable into a byte count variable, for example. We've also declared a few new types. Briefly, URefCon and SRefCon are two new types that we've declared for use with APIs and callback functions that take RefCon parameters.

And the reason why we're doing that is that in 32-bit mode... Often these APIs and callback functions took RefCon parameters that were typed as maybe a long or an unsigned long or something like that. Or maybe they were even typed as a UN32. Well, obviously, if they're typed as a UN32, that's not going to work in 64-bit mode because a UN32 is still 32 bits wide. And frequently with a RefCon, you want to pass a pointer, let's say, and the pointer needs to scale up to 64 bits.

So we've defined some new types for things that are RefCon parameters and used them widely across the Toolbox API. And that may cause you some compilation issues when you go to adopt 64-bit in your application because you may need to change places where you are, for example, casting a pointer to a UN32 before you pass it into an API as a RefCon. You might want to change that cast to a URefCon instead. And that way you'll avoid truncating the top 32 bits of your pointer. Another type mentioned on this slide is the CGFloat type. And that is a type that is provided by the Core Graphics framework.

In Core Graphics, a lot of the APIs that take a floating point value were previously typed to take a float parameter. And in 64 bits, those parameters are all changed to take a double parameter so that we get some extra precision and resolution there. So instead of going through and putting ifdef's everywhere through the headers, CoreGraphics is just using the CGFloat type, which in 32-bit mode is a float, and in 64-bit mode is a double. And you'll probably want to make a similar change in your code.

Frequently, for example, you might declare an array of floating point values and then pass that array into a Core Graphics API. And you want to make sure that you change the base type of that array to a CGFloat instead of just a float because when you pass that into Core Graphics, CGFloat is going to be expecting an array of doubles in 64-bit mode. And that's what you better provide or you're going to have some trouble.

So I'll go through some of the common managers and point out a few gotchas and some of the API changes that we've made for each one of these. And the Appearance Manager, there is no Quick Draw, as we said. So all of the Appearance Manager APIs that used to draw into a Quick Draw port or in some other way depend on the presence of a port, like the ones that would change the background color of a port, for example. Those have gone. There's no replacement for those.

There's no Quick Draw based Appearance Manager drawing anymore. But we do have the HITHeme API, which we introduced a few releases ago. And the HITHeme API uses CGContext for everything. So that's the one you want to use and that's what you can adopt in both your 32-bit and your 64-bit applications.

One place where we don't have a replacement yet that I'd like to point out is KThemeCurrentPortFont. It says right there in the case that we're going to use the KThemeCurrentPortFont. It's a constant. It depends on the current port. Well, there is no current port. So we're going to be introducing a replacement for this concept that probably passes in maybe a Cortext font or something like that explicitly. That's something that we have not done yet, but we will be doing it after the seed and after the conference.

The Carbon Event Manager. Back in 10.0, we had this API called ToolboxObjects that we provided to let you use Carbon Events to subclass some of the standard controls and windows. And then around 10.2, we came out with the HIObjectManager as sort of a replacement for ToolboxObjects. And in 64-bit mode, we're just taking out ToolboxObjects entirely, and the HIObject API is the preferred and only way to create custom Carbon Event-based objects and to subclass existing objects. So you want to use HIObjectRegister subclass instead of using the ToolboxObject API.

Another set of Carbon Events that's been removed from 64-bit mode that I'll just call out is the various KEventWindowClick something or other region, like KEventWindowClickDragRegion, for example. Those Carbon Events were all originally designed for non-compositing mode. And in fact, they've never been sent for compositing windows. So if you've moved your application to compositing mode, you've probably already figured this out, that these event handlers for these events just aren't being called. In 64-bit, since there is no non-compositing mode at all, we're just taking these constants out of the headers when you compile for 64-bit targets.

So you may have previously been getting by with the KEventWindowClickDrag. You may have previously been getting by with installing handlers for them that were never called if you were using compositing mode. In 64-bit mode, you'll actually get compilation errors if you try to install an event handler for one of these.

The Dialog Manager, as I mentioned, is still there for compatibility and make it a little bit easier to port your applications over. But it does always create compositing windows. Now this has some interesting implications for your application. Compositing windows are also going to use the standard window event handler.

That means that the window event handler is going to grab all the Carbon events that go to that window before they get passed back to the Dialog Manager. So if you're passing in a modal filter event to a modal dialog, you're not going to see any of the mouse downs or key downs or any other events that you might have expected to see there. Those are all going to get picked up by the standard window event handler.

Instead, your modal filter will only get null events. So if you need to actually handle specific events in your dialog, specific user input events, you want to do that by installing Carbon event handlers instead of using a modal filter. And that will work just fine in 32-bit mode as well. Thank you.

Another option that we're providing here is a new flag that you can put in your DLGX resource to specify that you should get a compositing dialog window even in 32-bit mode. Previously, in 32-bit mode, there was no way to create a compositing dialog window. And we're now providing that capability so that if you want to have the same source space that works in both 32-bit and 64-bit, we don't want to have to make you branch your code and handle the non-compositing case for 32-bit and the compositing case for 64-bit. So we're going to let you create compositing dialog windows on both sides if that's useful to you.

[Transcript missing]

The Tech Services Manager, going all the way back to pre-Mac OS X, the Tech Services Manager used to send Apple events to communicate between input methods and applications. Starting in Mac OS X, we introduced a suite of Carbon events, which was the preferred way for TSM to communicate with applications. In 64-bit mode, that's the only way. The Apple events are no longer sent. So if you're using the TSM Apple events, you need to switch off them and use the Carbon events instead.

I mentioned we were introducing some new API to replace some of the API that we've removed. A big chunk of the API that's gone, of course, is Quickdraw. And that includes some other things such as the display manager and the GD handle type. So the modern replacement for all the display manager and GD handle interfaces is the Core Graphics Direct Display API.

So we've introduced a new Carbon Event parameter type called type CGDisplayID, which is a CGDirectDisplayID. And we're using that in a number of Carbon Events that used to take a GD handle. Now you might think that this could cause problems for existing applications that are expecting to see a GD handle in those Carbon Events, but we have an automatic coercion facility in 32-bit mode. So that even though the Carbon Event really contains a CGDirectDisplayID, if you add a new Carbon Event parameter to the GD handle, you can see that the GD handle is not going to be a problem.

So we've introduced a new Carbon Event parameter type called type CGDisplayID, which is a CGDirectDisplayID. And we're using that in a number of Carbon Events that used to take a GD handle. Now you might think that this could cause problems for existing applications that are expecting to see a GD handle in those Carbon Events. But even though the Carbon Event really contains a CGDirectDisplayID, if you ask for a GD handle, we'll convert it to a GD handle and give you that back. So that's the compatibility mode for 32-bit mode.

But for 64-bit mode, there is no GD handle at all. So for best compatibility with 64-bit, you will want to make your application use this type CGDisplayID explicitly and explicitly be able to handle getting a CGDirectDisplayID. So that's the compatibility mode for 32-bit. So that's the compatibility mode for 32-bit mode. So that's the compatibility mode for 32-bit mode. So that's the compatibility mode for 32-bit mode. So that's the compatibility mode for 32-bit mode. So that's the compatibility mode for 32-bit mode. So that's the compatibility mode for display ID back from these Carbon events.

Display Manager also provided an API for registering notifications when the display configuration changed. And we are now providing a Carbon event, which kind of wraps that functionality. That's available in both 32-bit mode and 64-bit mode. So that's KEventSystemDisplayReconfigured, and that'll be sent whenever you get a display change.

There was also some Window Manager API, which used to take a GD handle or return a GD handle, things like finding out which device contained the largest portion of a window or what the positioning bounds on a particular display were in which you could put a window. And we have some new API that now take a CD direct display ID instead.

A few other APIs here that kind of go along with the removal of QuickDraw. The old GetMouse API was return coordinates relative to the current port. Since there's no current port anymore, we can't return coordinates relative to it. So we have a HIGetMousePosition API, which explicitly takes a coordinate space parameter. So you can request the current mouse position in the coordinate space of a view or of a window or in two types of global coordinate spaces.

And also TrackMouseLocation used to return coordinates in the space of the current port. So again, we have a new HIView TrackMouseLocation API, and that will return you coordinates in the coordinate space of a particular view. And it's specifically designed to be used with HIView and compositing windows. years.

So that finishes up my 64-bit presentation and I'm going to hop over to resolution independence. If you were here just an hour ago for Guy's session, some of this will probably be a bit of a review, but I'm going to go over it just for anyone else who hasn't been here for that. So resolution independence, as hopefully you know, is something that we introduced in Tiger originally as a developer-only feature, just a way for you to start playing around with it and to see how well your applications worked.

We're finishing it off in Leopard and we have some significant changes in Leopard. We're at places where we're improving the feature. Most of the standard controls are now using high resolution art instead of the old bit mapped art. We haven't finished this with all the controls yet, so certainly you'll see many places where the standard controls still look a bit blocky when you scale things up, but we will have those done by the time we finish with Leopard.

We do have some resolution independent specific APIs. The HIGetMousePosition API that I just mentioned a minute ago is one of them. That API lets you choose the coordinate space in which you get back the mouse position, so you could get back a mouse position either in pixels, if you need absolute pixel-specific coordinates, or you can also get back the mouse position in points, which is basically pixels divided through by the scaling factor.

We will, after the seed and after the conference, be introducing new APIs that allow you to position and size windows and other objects at the global level using explicit HIRect parameters, for example, that have floating point coordinates. All the existing WindowManager APIs in Carbon, unlike Cocoa, in Carbon the APIs all assume that the coordinates are specified in points, basically.

So that's going to be the default no matter what mode you're running in, and we'll have new APIs that if you need to explicitly specify window coordinates in pixels, you'll need to adopt those new APIs. I'm also going to talk a little bit about policies for art and cursors.

And finally, something that Guy mentioned, last session, is that the application scaled mode that we talked about last year, we've realized it just doesn't make much sense. It's too hard for us to implement properly, and it doesn't fit in with the whole direction that we want you all to go of using compositing mode.

So this application scaled mode, which allowed QuickDraw-based applications to scale their own window content, is no longer supported in Leopard, and after the developers' conference, we're actually just going to remove the constants from the header files entirely. So you'll still see them there right now, but that's going to be gone by the time we ship.

So that leads me into the scaling modes that we do still support. And there are two. The first and the preferred one, the one that we really want you all to adopt, is called framework scaled mode. And this is the mode that you can get if you're using compositing mode in your Windows.

In this mode, the toolbox automatically provides a transform, a core graphics FEN transform on your CG context that's passed to your drawing event so that when you draw, your drawing automatically gets scaled up according to the user interface scaling factor. So this gives you really nice, crisp text because your text is being scaled up by the Windows server.

And if you can revise your artwork, your content to have multiple resolutions, then this will also give you nice, crisp artwork as well. It does require compositing mode and quartz drawing. So in case you haven't figured it out, please use compositing mode. Please draw with quartz. Guy Fullerton, Eric Schlegel So this is the framework that we do still support.

And the other mode is magnified mode. And this is the default that you will get running an unmodified application. And this includes unmodified compositing mode applications. So even if you're already using compositing mode, you still get magnified by default because there might be cases where you still need to make changes to your application to really work well.

So in the magnified mode, the window buffer that your windows draw into is just exactly the same size as the coordinates in points that you're passing in. And then the Windows server just magnifies that content up on the screen when it actually gets displayed. So this gives you blurry text and blurry graphics, but it does maintain compatibility with all the applications that are already out there, especially those that are using Quick Draw.

Another important point to note is that you can mix both of these modes in your application. You don't have to convert everything all at once. You can do this one window at a time. You can take an easy window and convert it to compositing mode, try it out, see how that goes, turn on framework scaling for that mode, and then as you gain more experience with compositing mode and framework scaling, you can gradually move up to the more complex windows and convert those as well.

So the steps to move to a framework scaled window user interface. Compositing mode is the very first one, of course, and also using courts. And then once you've done that, it's pretty simple. There's just a pop-up menu in IB when you create your window in your Nib that specifies use this framework scale mode. You can also do this explicitly by passing in the framework scaled window attribute when you create the window.

And then once you've done that, something to think about as you work through your application code is that we define two different coordinate spaces in the toolbox. One of them is pixel-based, and the other one is what we're calling a 72 DPI coordinate space, although that's a bit of a misnomer because it isn't really a 72 DPI coordinate space. But think of it as a virtual coordinate space.

It's the coordinate space that you get if you take screen pixels and you divide it through by the resolution scaling factor. So this is the compatibility coordinate space that all the existing APIs expect. If you have an API that doesn't take an explicit parameter to specify which coordinate space you want, then it's going to expect virtual coordinates. That maintains compatibility with all of your existing code.

You also have a screen pixel coordinate space which you will be able to adopt explicitly if that's appropriate. And you can go back and forth between these two coordinate spaces using several APIs that we introduced in Tiger. We have APIs for converting points, sizes, and rectangles back and forth between different coordinate spaces. And finally, there are a number of Carbon Events that have parameters that represent global sizes or positions. Something like a K event window bounds change, for example, as the bounds of a window.

Now we have not fully resolved this issue in the toolbox yet, but this is something we're going to be moving towards after the developers conference. We have some new Carbon Event parameters which explicitly specify the semantics that we're going to be using in the toolbox. And we're going to be using the same parameters that are defined by that parameter. So, for example, if we have an HIRect, that HIRect could represent screen pixels, or it could represent virtual coordinates.

And you don't know a priori which one it's going to be. So the policy that we've defined is that by default, all the existing constants for specifying event parameter types represent virtual coordinates. But you will also be able to explicitly ask the Carbon Event Manager to translate from virtual coordinates to pixel coordinates by using some new event parameter types. For example, type HIRectScreenPixel.

If you pass that into GetEventParameter, then the Carbon Event Manager will automatically translate the coordinates from virtual coordinates to screen pixel coordinates and pass them out to you. And in fact, probably what we'll wind up doing is we'll put the highest resolution data, which is basically the screen pixel coordinate values, into the Carbon Event, and then we'll translate the other direction for the compatibility case.

One of the issues that you will definitely need to deal with to make your application resolution independent is creating a lot of new artwork that is scaled up to either a 2x or a 4x scale factor and using that in your application. So there are a couple of ways you can do it.

This slide talks about two of the harder ways and I'm going to talk about an easier way a little bit later. So if you are explicitly passing a CG image ref, for example, into a standard view to specify the image that that view should display, well, you can use ImageIO to get a CG image source ref from your file on disk that has your multiple resolutions of artwork, parse through the various resolutions that are available, compare it to the scaling mode for the window and the scale factor, and figure out which resolution is the best one for you to use, and then you can send that particular CG image ref into the view.

That's a little complicated. But it's perfectly straightforward. Another option, and going along with our Cocoa integration capabilities, is that you will in the future, before we ship Leopard, be able to pass an NSImage into the standard views and use that to specify the image content. And in that case, NSImage is going to automatically figure out which particular resolution you're going to be able to support. That's not provided yet in the seed build, but that's something we're going to be working on.

The third option, which is going to be a little bit easier, which is going to be the easiest one, and which I'll talk about in a little bit more detail later, is that we are providing new capabilities to pass the path or just the name of a file in your resources directory right into a view and say, you know, grab the file from this location on disk and just do the right thing. And that's probably going to be the best solution for the vast majority of people. You'll just create your content, stick it in your resources directory, pass in the path or the file name, and we'll figure out the right resolution to use automatically. automatically.

Another issue that comes up pretty frequently is resolution independent cursors and how do you specify different types of cursor data. Our preferred solution here is to use NSCursor. NSCursor already has the right support for this. There isn't really a lot of value in us creating yet another API to wrap a Cocoa API.

So we are going to point you right at NSCursor and just suggest that you use NSCursor itself. NSCursor also supports 64-bit. We have a sample up on developer.apple.com for showing how to use NSCursor in a Carbon application already. We will be talking about this more in the Cocoa for Carbon Developer session. Please do attend that one as well.

So those were our two biggest features for Leopard and the Toolbox that was 64-bit and resolution independence. I'm going to run over a few smaller features that we've added as well along the way. And the first one is handling Apple events using Carbon Event Handlers. This is actually something that I think it's come up several times on the Carbon development list. Someone will post, "Well, I installed my Apple Event Handler using GetEventHandler, but it's never being called. Why's that?" That's because it doesn't work.

But now it does. We've hooked up some interfaces into the Apple Event Manager so that you can actually call the regular InstallEventHandler API in the Carbon Event Manager. And you can pass in a regular Carbon Event Handler callback function and use that to receive Apple events. In this case, you would be installing your Event Handler on the application target. That's the only place that the event is going to be sent.

And when your application or when run application event loop calls a process Apple event, the Apple event manager will dispatch the Apple event through the normal Apple event dispatching handlers, but before it does that, it gives it back to the toolbox to give us a chance to send it through the Carbon event dispatching chain.

So that's when your handler is going to be called inside AEProcess Apple event. And all you need to do is just pass the Apple event class and kind into install event handler when you're registering your Carbon event handler, and from then on it's basically like you just have a regular Carbon event to handle.

So for example, you can use getEvent parameter on the event ref that your Carbon event handler receives, and that will actually pull event parameters out of the Apple event that is backing up the Carbon event. There are some caveats here. If you are accessing an array parameter from the Apple event, let's say you are handling the Open Document Apple event, and that has a parameter that is an AE list. It's a list of AE desks, and each one contains an FSRef, let's say.

In that case, what you really want to do is you want to pass typeAelist in your first call to getEvent parameter to get out an AE desk list, and then you can use the Apple event manager APIs to pull out each AE desk from that AE list. And in that case, you also need to release the AE desk list afterwards.

There are probably cases where you're going to need to get the original Apple event or the original reply Apple event. So we do also provide some special event parameters to allow you to get that information out. I mentioned here the event parameter name AEVT together with parameter type AppleEvent will get you the original Apple event that was backing up the Carbon event. And you can do the same thing for the reply.

And if you need to put data back into the reply Apple event right now, you cannot use setEvent parameter. That's something I'm going to implement later, but it's not hooked up yet. So in that case, you want to get the reply Apple event out of the Carbon event and then just set data directly into the reply. So we're going to put a sample app up on developer.apple.com after the seed that shows how to use some of this stuff.

HiObjectDelegates is another API that we've added that's part of the HiObjectManager. And it's a little bit reminiscent of some other frameworks. It's a way to add extra behavior onto an existing HiObject without actually subclassing it or installing a bunch of event handlers yourself. So essentially the idea is that you have one HiObject, which we call the target HiObject, and a second HiObject, which we call the delegate.

You install the delegate onto the target. And then the delegate HiObject receives all the Carbon events that are sent to the target HiObject. And so this has some nice advantages over some of the older ways of doing it. Obviously the delegate HI object being an object itself combines all of its data and handlers in one place, provides a nice bit of packaging there.

If you are a client of a delegate, you don't have to know exactly which event handlers the delegate is installing. All you need to do is install the delegate and you're done. Finally, the delegate has the ability to have some control over which order its event handlers are called relative to the target object's event handlers. So you can install the delegate either before or after the handlers that are on the target object. And that guarantees, for example, that the delegate's handlers will always be called before the target object's handlers.

So we're going to use this capability to try to provide some standard delegate objects for you to use in your application. We know that a lot of you would like to bring some degree of Cocoa technology into your application, but we don't want to make you rewrite your entire application in Cocoa.

So what we would like to do is allow you to sort of drop little bits of functionality into your app very simply without having to make you modify the entire application to do it. So we're going to use this specifically for some bridges between Carbon and Cocoa. Before I go into that, I'm going to run briefly over the API.

It's really a very simple API. There's just an add delegate API to install the delegate on the target object, a removal API to remove it, and finally, if you are writing code that's inside the delegate event handler and you want to know what the target object is, there's an HI object get event handler object API which will return you the original target object. Thank you. So let's see here. I'm going to do a quick little demo of how this capability is used in the toolbox. And we have a demo machine with the Intel up here. Let's see, we can close this project.

So I have a basic little Carbon application here. And when I run this Carbon application, Here we have just a little field, a little edit Unicode text field, and nothing special about it. It accepts all sorts of characters being typed into it. But maybe I want to modify my application so that this field only accepts numeric text input. Well, I could do that. I could write some Carbon Event Handlers to handle the various Carbon Events that allow you to filter text input and write all the necessary formatting and analysis code. But it turns out that Cocoa already has this really handy little NSNumericFormatter class.

And so what we've done in the toolbox is we've implemented a delegate that can be installed on a text field that uses the NSNumericFormatter class. And it uses it to determine whether the text being edited is actually in a numeric format. So I'm going to enable a little bit of code here.

What we're doing here, first we're just finding the Edit Text field right there. I'm going to create the delegate object using this class ID here. Currently we don't have any header files that define the delegates we're providing, but we will be providing those header files later. I'll add the delegate to the Edit Text field, release the delegate since it's been retained by HIObjectAddDelegate, rebuild. Thank you. I need #F1. All right. F1. Rebuild again. Let's try this now.

Now we can see that I'm typing on the ASCII characters here. There's nothing coming in, but if I type on the numeric ones, then we can get that. I can only insert a single period because otherwise it would not be using the correct format. So that's an easy way to introduce some Cocoa technology right into your application without having to modify your application to use Cocoa in a big way. Now let's go back to the slides.

So the next thing I want to talk about here is menu item views. This is the ability to embed an HIView directly into a menu. You're already seeing this in the operating system in a number of places. You see it in the finder where it has its label color picker. You see it in the new spotlight help menu where we have an edit field right in the help menu that lets you type into it. And this is also being provided via AppKit via a similar AppKit API.

So the menu manager in this case is going to automatically create your HIView. It's going to automatically position and resize it. It will forward accessibility requests into your view, so your view is considered to be an accessible child of the menu. And it automatically handles keyboard focus as well.

And in this case it's really simple to adopt this because you don't have to do anything special in your HIView to enable it. You basically just implement the getOptimalBounds Carbon event if you aren't already, so that the menu manager knows how big your view wants to be. And then the menu manager takes care of the rest. Finally, if your view needs to resize while the menu is open, you can also send this new Carbon event we've defined, kEventControlOptimalBoundsChanged, and the menu manager will pick that up and resize the menu automatically.

Again, this is a pretty simple API. The interesting thing here is that you don't actually pass an HIView instance itself in to specify the HIView for a menu. You pass the HIView. And then you can see that the view is not visible. And that's because the menu manager may need to create multiple instances of your view if the menu gets displayed, say, as both a pulldown menu and a popup menu.

You might need to find the view -- find the menu item that contains a view at runtime. You can do that with HIView getting closing menu item. And you might need to cancel menu tracking explicitly. And we have HIView cancel menu tracking for that case. So let's do another quick demo of this one. Back to the Intel machine.

So again, this is a very simple standard Carbon application. Looking in the File menu here, note that there's nothing unusual about this particular menu. It's just exactly as it would be in a basic template. This time, let's do this first. Here's a little bit of code to enable using a menu item view for the Page Setup menu item. First, I'll find the Page Setup item.

Now I'm going to create the initialization event that's going to be used by the view I'm going to put in the menu. And in this case I'm just going to set an event parameter in there that specifies the title for that particular view. Then I'm going to make that view use the checkbox.

Make that menu item use the checkbox view. So now, when I run this application, The menu manager will automatically replace the page setup item with a checkbox. And this is fully enabled. You can click on it. You can also use the arrow keys to go up and down and that will put focus on it and then I can use the keyboard to enable and disable that particular check and uncheck that particular item. So that is something that you may find useful in your applications as well. Okay, back to slides.

Something I touched on earlier is the ability to have file-based image view content. That's the capability to pass in the path or the name of a particular file on disk and then the toolbox will automatically load that file and display it in a standard view. So this is supported by a bunch of the standard views already such as the push button, the bevel button, and quite a few others. It's not supported in all of them but we're getting there.

It's also important for resolution independence because you'll be able to pass in the path to a file that has multiple resolutions inside it and then the toolbox will automatically pick the best resolution for display given the current scaling factor. That particular aspect of this feature is not yet supported in the developer's conference seed but we will be implementing that after the developer's conference. And we're also planning some support here for passing in NSImages.

Finally, a brief mention of the Text Input Sources API. This is a new API that is meant for handling various types of input sources such as text input methods, palettes such as character palette, and also ink. And there's a bunch of APIs that are being deprecated in Leopard including parts of the script manager, the keyboard layout manager, and parts of the text services manager.

And the Text Input Sources API is designed to replace all of those. So there's an entire session talking about this. If you deal with text input in your application in a very detailed fashion or if you write text input methods, you definitely want to go see this session.