You are currently viewing a snapshot of www.mozilla.org taken on April 21, 2008. Most of this content is highly out of date (some pages haven't been updated since the project began in 1998) and exists for historical purposes only. If there are any pages on this archive site that you think should be added back to www.mozilla.org, please file a bug.



Raptor Widget

Files in mozilla/widget/src/os2/
(not yet checked in to mozilla.org cvs)

This is the cross-platform window library. Most of the files and classes (eg. nsEntryField) are small subclasses of the base OS/2 window class, nsWindow. Note that the widgets are grounded in an XP class, nsBaseWidget. The hierarchy looks like this:

       nsISupports
         |
         +---nsIWidget
               |
               +---nsBaseWidget
                     |
                     +---nsWindow
                           |
                           +---nsEntryField   (for example)

The future - XPToolkit

There are several incomplete sections in this library (eg. printing). They are being left incomplete because their future is unclear. Mozilla is adopting a system of drawn widgets; there will be a place for native widgets, but the details are still vague.

See XPToolkit for more.

Managing message queues

In order to do interesting things like create windows, a thread needs to have a HMQ. There are three places in the mozilla code where, independently, PM function is neeed: here, in libwidget; in nsTimerOS2, and in the plevent library. Here is the way in which message queues are to be managed:

  1. When a service needs a message queue, it should first test for there being one for the current thread, using WinQueryQueueInfo.
  2. If there is no queue, create one.
    Otherwise the service should use HMQ_CURRENT.
  3. The service should take no action to destroy any queue it creates.
  4. The exception to this rule is the nsAppShell class. It is the job of nsAppShell to destroy the message queue and shut down PM.
    This a valid thing to do because by the time the nsAppShell shuts down, it is no longer processing its message queue, and so the services which may be using will have stopped working anyhow.

Toolkits and thread management

Not all mozilla threads are PM threads. Some functions in the OS/2 API demand that they are called from PM threads. Indeed, some functions must be called in specific PM threads. So there needs to be a method of re-routing function calls.

This mechanism is contained in the nsToolkit class. Each widget created has a reference to an nsToolkit, which is associated with a thread. There's a set of routines for calling methods (using a callback interface, SwitchToPMThread, which nsWindow implements) and a convenience equivalent of WinSendMsg which doesn't require the caller to be a PM thread.

That said, mozilla isn't too promiscuous in the thread-creation department. Plans for this version seem to be limited to one UI thread plus some more netlib threads (more info). But if things ever change, we will be ready.

HWND basics

nsWindow.cpp is more-or-less an encapsulation of the basic window management sections of the OS/2 API.

All windows are subclassed into a simple window procedure, the nsWindow for that window is looked up, and the ProcessMessage method called.

The HWND to nsWindow mapping is implemented using a hashtable, found in nsWindow.cpp.

Frame windows store a pointer to their nsWindow at QWL_USER in the window words. Their client window handles are stored in the hashtable of windows.

The resizing and moving code is a bit non-obvious and probably contains a few bugs: as in the graphics library, the coordinate system has the origin in the top-left. Because the height of the window is an oft-requested quanitity, the window rectangle (in XP space) is cached in the object. This is updated in the dispatch routines for the PM notification messages as opposed to the site of the Resize method. There's some interesting code (which is, as yet, uncalled) to batch window repositions.

There are some kludges in place to better mimic the behaviour of Win32, so that, for example, windows totally covered by other windows do not receive mouseclick events.

Events

XP events are defined in nsGUIEvent.h. They're pretty straight-forward, though with a few notes:

  • The keycodes (see nsKeyEvent) are occasionally ambiguous; there's a global function in nsWindow.h to convert from a WM_CHAR to the keycode.
    Intl work needed for MBCS input modes.
  • No-one really knows when NS_SIZE and NS_MOVE events should be generated. OS/2's funky coordinate system doesn't help matters, and we could probably do better.

There are a bunch of methods in nsWindow.cpp which deal with setting up for and dispatching events to interested parties.

nsLookAndFeel

The nsILookAndFeel interface is meant to wrap up various platform-specific things, including various system colours.

There are some rather weird entries which have appeared relatively recently, which are used when laying out and aligning form elements.

These could do with verifying.

If components look `a bit wrong', adjusting a value in here is probably the way to go (but see above).

Tooltips

Because Win32 has tooltips built in to the API, tooltips are built in to the nsIWidget interface. The code to manage tooltips is in the nsTooltipManager.cpp file. Note that this doesn't have anything to do with displaying tooltips -- it just sends a notification to the window, which can then act as it likes.

The per-window data-structure could do with optimising (just use a hashtable)

This could well be subsumed into XP code.

Menus

There are separate classes for menu bars, pull-down menus, and popup menus, which all share code in the nsMenuBase class. There is also an nsMenuItem class. In the world of XPToolkit, menus are built up at runtime using these classes. Client applications associate menu listeners with both menu items and menus; when menus appear or menu items are selected, messages are dispatched to the listeners.

Yes, event handling mechansims vary wildly. But that's what makes it so fun.

How we make this work on PM:

nsSwitchToPMThread rerouting isn't hooked up yet.
The code for dispatching menu events is currently in nsWindow.cpp. It should probably be moved to nsFrameWindow.cpp.

Dialog windows

Dialogs aren't, at the moment -- they're just frame windows with a dialog border and a light grey-filled client. This shows up when you create button controls: there's a thin white border around them, which isn't normally present in dialogs.

The problem with using dialogs lies in coordinate systems. A dialog is one window, whose area is made up of a 'client area', a dialog border, and a titlebar. The origin of the client area depends on system settings, but isn't (0,0). This makes it very difficult to draw into dialogs: mozilla expects to be able to draw or lay out controls from the origin over the size of the window.

In practice, the white line doesn't look that bad, and it'll probably go away when the XPToolkit arrives.

Drag and Drop

Currently not implemented. Should be straight-forward, will eventually need a way to get a HBITMAP from an nsIImage. Wrap up the PM structures and everything should just work.


Back to Raptor gfx On to plugins