For Developers‎ > ‎Design Documents‎ > ‎

Command Dispatch (Mac)

This document covers how toolbar buttons, the main menu bar, and some context menus are hooked up to the back-end Command infrastructure in Chromium on Mac OS X.

Background

The cross-platform (XP) infrastructure uses a CommandUpdater object to represent the enabled state of a set of commands. Each Browser object has a CommandUpdater allowing it to maintain unique state that differs from window to window. User interface views, such as menus or buttons, are responsible for querying the appropriate CommandUpdater "model" to obtain their enabled state.

In addition, Mac OS X has a main menu bar that needs to update based on the front-most window as well as remain functional when there are no windows open (a situation in which Windows and Linux cannot exist). In Cocoa, each user interface view has a target object and a selector action method. When selected, the view sends the action selector to the target object. Item validation (enabling/disabling/etc) is handled by sending the validateUserInterfaceItem: selector up the responder chain for each menu item.

Implementation

There are two ways in which we could have handled command dispatch: each item gets its own unique action selector, or all items share a selector with a different tag. Each approach has its drawbacks, so in the end we decided to go with the latter. Every user interface item (except a few special ones) is given a target of "First Responder" with a selector action of commandDispatch: and the tag of the menu item is the XP id of the command. There is also a commandDispatchUsingKeyModifiers: for dispatching commands that do different things based on the state of modifier keys (for example, command-clicking the "Home" button opens the home page in a new window).

Note that the application delegate maintains its own CommandUpdater for the case where there are no open browser windows. This is the model consulted if no other window is available to handle a given command.

While the main menu bar and a few context menus work this way, many context menus are written to use MenuController, which leverages a shared model for building XP context menus. Due to the requirements of the shared model, its dispatch mechanism is slightly different and not covered in this document.

Validation

When the user clicks the menu bar (or displays a context menu which uses this mechanism), Cocoa calls validateUserInterfaceItem: for all items in the menu bar. Most menu items are handled by the BrowserWindowController which asks its corresponding Browser's CommandUpdater for the enabled state of the command id given by the item's tag. This also handles toggling commands and updating the item's title to match current application state.

In the case of buttons, the relevant controller (such as ToolbarController) registers for changes from the CommandUpdater using a CommandObserverBridge. When one of the relevant commands changes its state, the bridge sends enabledStateChangedForCommand:enabled: allowing the controller to update the enabled state of the button.

Dispatch

When the user clicks a user interface item (button or menu), its action (commandDispatch:) is sent to its target (the responder chain). At that point, we identify the correct BrowserWindowController for command dispatch (the click could be in a background window!) and then call ExecuteCommand() on that controller's Browser object.

Comments