Issue 2-1, January 8, 1997

Be Engineering Insights: In Case You Missed It

By Peter Potrebic

Our latest release, DR8, should be in everyone's hands by now. What I'd like to do is point out a few of the subtler changes in DR8 that might otherwise get overlooked. As a developer myself, I know that it's easy to get accustomed to a certain feature set and API, overlooking new and potentially better APIs.

The first change I'd like to discuss deals with view attributes and how they're handled in the BeOS. By view attribute I mean all the various graphical attributes of a view, including high color, low color, pen size, and font. I'd bet that anyone who's ever written a graphical Be application has overridden the BView::AttachedToWindow method in order to set the value of some view attribute. While it might seem natural to initialize these attributes in the view constructor, in releases prior to DR8 this was not possible because a connection to the Application Server was required, and this connection doesn't exist until the view is attached to a window. More than one of you have politely suggested that we could improve our system by eliminating this restriction. We always try to listen and in this case we did: In DR8 I removed this restriction. Now you can set the attributes of a view at any time, even before the view is added to a window.

I'm pointing this out because many folks have probably become accustomed to overriding AttachedToWindow(), so they continue doing so even if there's a simpler way. Breaking that habit ought to make it even easier to program the BeOS. Just set whatever attribute you want in the view constructor. In DR9, as a further improvement, I added a cache for all the attributes. Previously calls like Bounds() and HighColor() required a call to the Application Server. With the cache in place the Application Server isn't needed, so these getter functions are much faster. This means that you don't have to worry about calling too many getters inside of an update, and you don't have to implement your own caching, the system does it for you.

Another new feature in DR8 that I'd like to point out is keyboard navigation. Here at Be we love the mouse, but we also love the keyboard. We've always supported the idea of allowing complete control of the machine via the keyboard, without sacrificing ease of use via the mouse. I might add that a rather influential person at Be has long been the biggest proponent of keyboard navigation (his title is CEO).

Menu bars have been navigable via the keyboard from day one, but it took until DR8 to extend this functionality to include controls. New in DR8 is the ability to navigate the controls in a panel from the keyboard. Here are the basic rules of this UI:

For more information on keyboard navigation, and on getting your own custom control working in this system take a look at the Interface Kit chapter of The Be Book

In DR9 keyboard navigation will be extended to include the notion of groups of controls. With this new feature you'll be able to jump from group to group simply by pressing Control+Tab. This will make it easier to navigate a complex panel with lots of controls. The API for creating a group of controls is very simple. I didn't want to force developers to redo how you're laying out panels, so adding this functionality had to be simple. All you do to create a group is to set the B_NAVIGATE_JUMP flag in the appropriate view. If your group of controls has a common parent view (like a BBox), then simply set the JUMP flag in that parent view. The BBox class defaults to having that flag set. If your group of controls doesn't have a unique parent, then set the JUMP flag in the first control in the group. It's that simple.

I hope this helps you take advantage of some of the new features of DR8 and the upcoming DR9 release.


Be Engineering Insights: BTW, Did We Mention That...

By Don Larkin

Perhaps the most vexing API changes are those that don't present any outward signs of a change: A function has the same name as before, it takes the same set of arguments, and its return type is the same—but it now works somewhat differently than it did in previous releases. We try to keep such changes to a minimum and to highlight them for you when they occur. But because they don't show on the surface, they sometimes slip by unnoticed, even inside Be. Vigilant readers of The Be Book will note that we were slow to catch the fact that in DR8 a 0 timeout meant 0 microseconds, not an infinite period as it did in DR7. Or that the drawing code you invoke between BeginPicture() and EndPicture() no longer is rendered on-screen as the picture is recorded.

One subtle change that went unreported for DR8 affects the run-time type information (RTTI) macros found in the Support Kit. The macros let a program discover type information from an unknown object—say an object stored in a BList or retrieved from a BMessage, or more generally any object (such as the current focus view) returned by a function and typed to a base class. You'd typically use the macros to find whether the object can be typed to a more specific class. The Support Kit currently defines four RTTI macros:

Originally, these macros rested on a class-information system invented by Peter Potrebic and implemented as part of the BeOS. That system was abandoned in DR8 in favor of the RTTI system that's now part of the C++ language and supported by the Metrowerks compiler. The macros didn't change, but the new implementation subtly altered the behavior of two of them—is_kind_of() and cast_as().

The original RTTI system supported two styles of programming with these macros. You could use the cast_as() macro to cast a retrieved object to a target type:

void MyHandler::MessageReceived(BMessage *msg)
{
    MyView *mv;
    . . .
    case WHATEVER:
        mv = cast_as(msg->FindObject("source"), MyView);
        if ( mv )
            mv->DoWhatMyViewsDo();
        break;
    . . .
}

or you could arbitrarily cast the object to a target type and then use the is_kind_of() macro to see if the cast was correct:

void MyHandler::MessageReceived(BMessage *msg)
{
    MyView *mv;
    . . .
    case WHATEVER:
        mv =  (MyView *)msg->FindObject("source");
        if ( mv && is_kind_of(mv, MyView) )
            mv->DoWhatMyViewsDo();
        break;
    . . .
}

This second style is no longer supported and, in fact, should no longer be considered good programming practice. The general rule is that the declared type of an object must _always_ be accurate; an object should be typed only to its own class or to a class that it inherits from. If the declared type isn't accurate, as it may not be when is_kind_of() is called in the code above, the RTTI macros can't be trusted to rescue the situation. In the above example, is_kind_of() will always return TRUE, no matter what the "source" object really is.

In their new guises, both cast_as() and is_kind_of() are based on the C++ dynamic_cast() operator and they reflect its behavior. To talk about its behavior without getting too tongue-tied, let's adopt the following shorthand terms for an object's type:

In the old implementation, the RTTI macros compared the target type only to the object's real type. However, the dynamic_cast() operator considers the real type only if it has to. It first compares the target type to the object's declared type. It assumes that the declared type is accurate (that the object is truly the kind of object it's represented to be) and it summarily handles the obvious cases: If the target type is the same as the declared type or if it's a class that the declared type inherits from, the operation will succeed. Consequently, cast_as() will cast the object to the target type and is_kind_of() will return TRUE, regardless of the object's real type.

In other words, if the target class is above or at the same level as the declared class in the inheritance hierarchy, the real class is ignored. However, you would rarely want to cast an object to a more general type. Typically, you'd want to discover whether it can be cast to a type that's more specific than the declared type. For that, it's necessary to look at the object's real type.

dynamic_cast() considers the real type of the object only if the declared type doesn't match or derive from the target type. It then makes the same sort of comparison between the target and real types that it first attempted between the target and declared types. If the target type is identical to the real type, or if it's a class that the real type derives from, the operation succeeds. If not, it fails.

The dynamic_cast() operator and, by extension, the is_kind_of() and cast_as() macros, will produce reliable results as long as objects are not arbitrarily cast to types that may not be accurate. Despite this restriction, is_kind_of() remains a useful macro. Use it in a way that mirrors how cast_as() works—to check the type of an object _before_ casting it, not afterwards. For example:

void MyHandler::MessageReceived(BMessage *msg)
{
    BObject *obj;
    . . .
    case WHATEVER:
        obj = msg->FindObject("source");
        if ( obj && is_kind_of(obj, MyView) )
            ((MyView *)obj)->DoWhatMyViewsDo();
        break;
    . . .
}

In contrast, the behavior of the class_name() and is_instance_of() macros hasn't changed. They're now based on the C++ typeid() operator, which ignores the declared type of the object and always looks at the real type.

Will the RTTI macros be adjusted again in the future? Probably not. But if a change is made, we'll try to catch it and report it to you at the time.


Be Developer Talk: Steve Sprang

By Steve Sprang

I first became interested in computers when I was in sixth grade. My father had just purchased a Macintosh Plus, and I spent much of my spare time creating wondrous graphics in SuperPaint and throwing rocks at buzzards in Dark Castle. Although I'd been playing with computers since I was six years old—first a Timex Sinclair 1000 and then a Commodore 64 —it was the Plus that showed me what exciting machines computers can be.

Today I'm a computer science major and a Be developer. For me, the BeOS has brought back the thrill of discovering computers all over again. My BeBox has been a source of many an "Oh" and "Ah" since I received it last May. A couple of days after Christmas I received my "BeOS for Power Macintosh" CD. My Power Mac 8500, which I'd neglected since I got my BeBox, has found a new place in my heart. Needless to say, I'm very interested in seeing multiple 604s in one machine.

So far, I've released four BeOS applications. First, there was BeTetris; this was my "get to know the OS" project, but I think it turned out pretty well. Then came AudioDancer, which doesn't seem to work on the Power Macintosh. And lastly, two little demos, Langston's Ant and a slightly- more-advanced-than-Be's QuickCam viewer.

Over winter break I started work on a morphing application, called Metamorph. I need to refine the interface and increase the speed, but you can expect to see a beta release before the end of January. I'm also planning to write a Prolog interpreter. I don't expect there to be a huge demand for such a beast, but I'm personally interested in implementing a language from scratch, and I grew quite fond of Prolog in one of my courses last semester.

Programming for the BeOS has been unbelievably easy. I threw together the core interface for Metamorph in just a few hours. This included loading JPEG images and a drag-and-drop interface for reordering morph sequences. Don't even get me started on how easy it is to implement scroll bars. I almost feel guilty... almost. As a full-time student with limited free time, I really appreciate the ease with which I can turn an idea into a working program.

Well, there you have a brief run-down of my little corner in the Be world.

Programs I have developed for BeOS can be found at: http://www.andrew.cmu.edu/user/sprang/besoft.html

Oh yeah, if I don't get that Be internship I'm hoping for, I wouldn't mind interning for a third-party that "just" develops Be applications. ;)


News From The Front

By William Adams

At its best, computing on the bleeding edge is akin to a religious experience. At its worst, it can leave you disoriented, panting, and disappointed. The bleeding edge is sought by those with a passion to push the limits in the pursuit of performance that can't be found in the mainstream. Both the hacker fringe as well as the unafraid end users seek the bleeding edge as a competitive advantage.

To ride the bleeding edge takes patience, perseverance, and a very thick skin. The end result for the developer is that the bleeding edge turns into the leading edge, and they now have a market into which they can sell a product. The bleeding edge doesn't stay sharp forever. If the bleeding edge doesn't become the leading edge, then it has simply become an also-ran. Not a fertile market for the distribution of new fresh products, but simply a carcass of technologies to be picked at by the rest of the scavengers in the industry. The leading edge too can suffer a similar fate. If it doesn't continue innovation, the leading edge also becomes the backwater of technologies that were.

When I was a youngin, I managed a computer store. This was at a time when the Macintosh was bleeding-edge, innovative technology. I helped host the first Mac Fest at UC Berkeley and sold many thousands of these little mono boxes. People loved them. Compared to the PC of the time, they were bleeding edge, innovative, easy to use, and just plain cute. History is now showing us that the Macintosh and its OS have transitioned from bleeding edge to leading edge, spawning quite a healthy industry around it. The platform has become so successful that there is now a burgeoning clone hardware market. This market is screaming for something that's bleeding edge to show it off.

Several of the Mac clone manufacturers are working on multiprocessor machines with 2 and 4 processors. These are real screamers! As the rest of the mainstream market chases the ever-elusive fastest single CPU, these machines are going to leap from them in performance. At least that's what they hope. The problem is, they don't have the right OS to make them really sing. The MacOS, which they're supposed to be supporting, was never designed for these monsters of computing prowess. These dual and quad megamachines resemble those cute 9" mono Macs as much as man resembles an amoeba. But they're expected to run off the same fuel.

Enter the BeOS. Symmetrical multiprocessing, multithreaded, multi... The BeOS was born for this environment. Be has not produced any machines to date that don't have more than one processor. We can truly say that the BeOS was designed, and more importantly, tested in real usage on multiprocessor machines. The impact of this design and its computational value are just now becoming clearly understood and utilized.

After I did my stint as a computer reseller, I chased a dream to follow the NeXT big thing. I became a NeXTStep developer and followed the rise and fall of yet another bleeding-edge technology. But it never quite panned out. We had some commercial success, but the market just never materialized. This particular bleeding edge didn't quite garner enough popular support, so it didn't make it to the leading edge phase.

The next stop was Taligent. Another bleeding edge, except it sure had a lot of padding! In hindsight I think they just had too much money and not a big enough mandate to ship a product, nor a reasonable platform upon which to ship it. Waiting for Copland and running on AIX just were not good choices. I was able to file a couple of patents for collaborative technologies though, and that can't be all bad.

I feel much more comfortable with the BeOS than with any of the other bleeding-edge platforms of the near past. The company is small. The product is good and growing better all the time. License agreements are in place that will ensure a ready market for developer's wares. And from what I've seen of the new crop of Mac clones, our developers are going to have quite a fertile ground upon which to place their most compute-intensive dream applications. Seeing a well-crafted, multithreaded, interactive 3D walk-through environment running on dual PowerPC 604s at 225 MHz simply makes the mouth water. And no, you can't do this at home with the MacOS!

It's the beginning of the year and I'm waxing poetic about my own past and what I see in the future of my newfound love. I joined Be because the OS kicks and the BeBox rocks. Seeing all the new hardware coming through our doors makes me happier all the time that I made the decision to leave some fading-edge technologies and once again ride the bleeding rail. I hope all our developers will feel the same when they bring their apps up on the new crop of hardware. The experience is nothing short of amazing, and your immediate reaction will be to start burning brain cells trying to figure out what you're going to do with all that newfound power.

See you at Macworld.


Enterprise vs. Multimedia

By Jean-Louis Gassée

In one respect, NeXT has always played a part in Be's life. When we started the company, many sages questioned our viability: Look at NeXT, they've spent hundreds of millions of dollars and couldn't give critical mass to their platform. And now that NeXT is tucked under Apple's wing, the question is updated: How can you survive against the combination of NeXT technology and Apple's market presence?

Let's first address Apple's decision to pick NeXT over Be for the foundation of its future OS. When Apple approached us in June 1996 with a request to look at the BeOS, it became obvious we leveraged Apple's rich heritage of creative media applications. NeXT, on the other hand, had scored points in the marketplace with enterprise-wide, networked, mission-critical, custom-programmed applications. Picking NeXT is an enterprise play for Apple. Compared to NeXT and their more mature product, at this early stage of our life our platform and our company have little to offer in the enterprise market against Windows NT, Sun, or Hewlett-Packard. Our company was founded to address a very different domain: The computing demands of digital media content creators.

We respect Apple's decision and we thank them for having considered the BeOS.

Now what do we do? We continue with our work: Building up the BeOS platform, working with developers and with business partners such as Metrowerks and Power Computing. Half a dozen ex-NeXT employees work at Be. With their help, we've gone back and re-analyzed NEXTSTEP. It is indeed a stable, polished platform, based on UNIX and Display PostScript, with proven custom programming and, more recently, Web tools. Its UNIX and Display Postscript heritage limit its performance in the kind of high-bandwidth, interactive, media-rich applications that are the BeOS' sweet spot. Furthermore, as is typical with workstation operating systems, its performance is less attractive on entry-level PC configurations.

In summary, we have a less mature but more modern, more agile platform; we do well in creative multimedia applications, while Apple's new OS is aimed at the enterprise market.

And we continue to add value to Power Mac hardware, and to the PowerPC in general.

Amateurs of trivia might want to reread the columns I wrote for NeXTWorld and MacWeek (http://www.macweek.com/mw_1049/op_capsule.html). And, going back to the beginning of this column, for us, NeXT eloquently demonstrates that persistence pays off.


BeDevTalk Summary

BeDevTalk is an unmonitored discussion group in which technical information is shared by Be developers and interested parties. In this column, we summarize some of the active threads, listed by their subject lines as they appear, verbatim, in the mail.

To subscribe to BeDevTalk, visit the mailing list page on our web site: http://www.be.com/aboutbe/mailinglists.html.

WEEK 3

Subject: Accessing Preferences

A "preferences server," which would allow distributed access to a user's settings, was proposed and discussed. Also of interest was the discussion of an application registry architecture: When you install an application, how should the system note the new app's existence?

At a slightly lower level, the "granularity" of preference items was debated. One listener suggested that preferences should be class-based. In other words, each C++ class (BApplication among them) could have its own set of preferences.

NEW

Subject: BeOs on a PowerBook 5300?

AKA: Powerbook BeOS must happen

Is a port to the PowerBook crucial? Some folks think it would fill a gaping hole in the Be product line; others feel that Be should wait for a more stable (and more surely supported) portable. Perhaps, it has been suggested, Be should build its own.

Subject: Remote Displays

Regarding remote displays: How difficult would it be (for Be) to allow messages to be sent to Application Servers that are running on remote machines? To what extent will the interface API, which assumes a single, set-in-stone Application Server, have to be altered to allow the identity of the server to change as an app is running (and, potentially, being passed between machines)? Conversely, should remote machines only be used for display (that is, the local Application Server sends data to a remote display, rather than the local "connection object" sending ops to a remote Application Server). What mechanism should be used to deliver environment info to the (remote) machine that will be launching an app (or "receiving" a running app)?

The discussion slid into a request for a good multi-user action game.

Subject: Suggestion: Dictionary/Spell checker database

How about using the database to store a dictionary, thus making spell-checking apps (and the like) easy to write and eminently extensible? Theoretically sound, but it might require too much disk space (120 MB for a 250,000-word dictionary, by one estimate).

So instead, how about a dictionary server that could run over the network? (No objections.)

Subject: Apple, NeXT, Be

Although this thread started out as a rumor mill/soap box, it offered some technical debate over the merits of Objective-C (Next) and C++ (everybody else). Some of the observations:

  • Objective-C isn't a solution to the fragile base class problem (as is sometimes claimed); it works for methods (member functions) but doesn't protect the instance variables (data members).

  • Objective-C's everything-is-virtual attitude makes for poor function call performance (it was claimed). However, pointers to Objective-C methods, which are initially looked up by name, are cached so that performance improves as the cache "warms up."

  • Sending a BeOS C++ BMessage (and waiting for a response) is much slower than calling an Objective-C method. But (it was countered), is this a valid comparison?

Creative Commons License
Legal Notice
This work is licensed under a Creative Commons Attribution-Non commercial-No Derivative Works 3.0 License.