[Contents] [Index] [Help] [Retrace] [Browse <] [Browse >]

Menu Verify Handling


by John Orr and Peter Cherna


Menu verify has been a part of Intuition for a long time, so it may
seem a bit odd to see an Amiga Mail article on the subject.
Unfortunately, the ``Intuition Menus'' chapter of the Amiga ROM Kernel
Reference Manual: Libraries is a bit unclear on the subject.  It does
not sufficiently cover why an application would need to use this
feature and how an application should handle it.


Menu Verify

When the user tries to pull down the active window's menu, Intuition
offers applications a chance to prepare for the menu operation.
Intuition delays displaying any menus until the application has
finished its preparations for the menu operation.  This feature is
known as menu verify.

Menu verification works using the IDCMP mechanism.  For an Intuition
screen, when the user triggers Intuition into drawing the menu,
Intuition sends an IDCMP_MENUVERIFY message to every window on that
screen that asked to hear about menu verify events.  Intuition will not
display the menus until it gets back all the IDCMP_MENUVERIFY messages.

If the active window uses menu verification, Intuition gives that
window the option to cancel the menu operation.  This allows the
application to selectively use the menu button to activate the menu or
to perform some other function.

Beginning with V36, Intuition introduced a time out on menu verify
operations.  If the active window's application takes too long to
respond to the IDCMP_MENUVERIFY message, Intuition will cancel the menu
operation.  This feature helps avoid some deadlocks that can occur
while Intuition is waiting on the active window.  This feature applies
only to the active window; Intuition will wait indefinitely for the
IDCMP_MENUVERIFY message from an inactive window.


Reasons to Use Menu Verify

The primary purpose of the menu verify feature is to arbitrate access
to screen resources.  There are really only two screen resources that
an application might need to use directly, the palette and the bitmap.

Some applications need as many pens as possible, so they change the
color values of the pens that Intuition uses to render the menus.  This
can present a problem if the application happens to alter the menu pen
colors so that the menu's foreground color is difficult (if not
impossible) to see against the background color.  The menu items will
be unreadable to the user.

To prevent this problem, the application has to restore the original
pen colors when the user pulls down the menu.  The application can do
this using menu verify.  When the user hits the menu button, Intuition
sends the application a menu verify message.  When the application
receives this message, it restores the menu colors and then returns the
IDCMP_MENUVERIFY message so Intuition can properly render the menus.
When the menu operation is over, Intuition will send a ``conclusion''
IDCMP message.  The ``conclusion'' message is covered later in this
article.

Another reason to use menu verify is to arbitrate rendering access to
an Intuition Screen's bitmap.  While Intuition is displaying the menus,
the application must not render directly to the screen's bitmap because
the application could draw over the menus.  The application must wait
until the menu operation is over to resume rendering.

This raises some important questions.  Why render into a screen's
bitmap (Screen-> RastPort.BitMap)?  Shouldn't I render into a window
instead?

The quick answer is: ``render into a window's rastport instead of
rendering directly into a screen's bitmap''.  Rendering to a window's
rastport offers several advantages over rendering directly to the
screen's bitmap.  The window offers the application efficient clipping,
making the application simpler because it doesn't need to worry about
rendering into rectangular bounds.  The window also supports a layered
display, so the application can ignore the consequences of arbitrating
access to the screen's bitmap.

There are some cases where, arguably, it might be advantageous for an
application to render directly into a screen's bitmap.  Rendering into
a screen's bitmap versus rendering to a window's rastport offers a
slight improvement in performance.  Part of this improvement is due to
the lack of clipping on a screen's bitmap, which the window provides,
so the performance improvement is questionable if you still need to
perform clipping.

One case where an application has to render into a screen's bitmap is
when graphics functions that operate below the layers level.  For
example blitter objects (BOBs) operate below the layers level.  If the
application is operating below the layers level, it can't render to a
windowed display.


Reasons Not to Use Menu Verify

One feature of Intuition menus is that the user can toggle a menu item
between a selected ``checked'' state and an unselected ``unchecked''
state.  Intuition keeps track of the state, so the application only has
to read the state from the MenuItem structure.  In some cases, the
state of the menu item can be affected by something besides the user
performing menu operations, so the application has to explicitly change
the state of the menu item.

Some applications use the menu verify feature as a mechanism for
updating the state of the menu items.  When such an application
receives the IDCMP_MENUVERIFY message, it updates the checked flag of
the menu items and then returns the menu verify message.  Some
applications also use this method to manage the enabled and disabled
state of a menu item.

Although this method works, it should not be necessary to interrupt the
menu event.  Almost all applications should be able to keep their menu
states current using ResetMenuStrip().  It is also possible to use
SetMenuStrip(), but since ResetMenuStrip() is considerably faster than
SetMenuStrip(), ResetMenuStrip() is better.  See the Autodoc for
ResetMenuStrip() for more details.

Some people may think one potential use for menu verify is to assign an
alternative meaning to the right mouse button.  For example, when the
pointer is not within the title bar of a screen, some paint packages
use the right mouse button to paint using the background color.  Using
menu verify, it is possible for a application to intercept the menu
verify event, checking to see if the pointer is within the title bar.
If it isn't, the application cancels the menu event.  After cancelling
the menu event, Intuition will send a right button down event, which
the application can interpret.

This mechanism may work, but it is not very efficient.  There is a
better way to do this using WFLG_RMBTRAP.  This flag is from the Flags
field in the Window structure.  When set, this flag disables menu
operations for the window.  When the user hits the menu button,
Intuition sends the window IDCMP_MOUSEBUTTONS events instead of menu
events.

To use WFLG_RMBTRAP as an alternative to menu verify, the application
tracks mouse movement using IDCMP_MOUSEMOVE.  While the pointer is
outside of the screen's title bar, the application makes sure the
WFLG_RMBTRAP flag is set.   If the user hits the right mouse button
while WFLG_RMBTRAP is set, Intuition sends the application a mouse
button event.  While the pointer is inside the screen's title bar, the
application makes sure the WFLG_RMBTRAP flag is clear.  If the user
hits the right mouse button while WFLG_RMBTRAP is clear, Intuition
generates a normal menu event for the window.

WFLG_RMBTRAP is an exception to most fields in Intuition structures
because it is legal for an application to directly modify this flag.
Note that this change must take place as an atomic operation so that
Exec cannot perform a task switch in the middle of the change.  If you
are unsure your compiler will do this, use a Forbid()/Permit() pair to
prevent a task switch.

There are cases where an application is too busy to handle any menu
event so it needs to prevent menu operations for a while.  This is
another case where menu verify is inappropriate.  A better way to block
menus is to remove the menu with the Intuition function
ClearMenuStrip() and restore it later with ResetMenuStrip().  Another
potentially useful way to block menu operations is using a requester.


Will I Ever Need to Cancel a Menu Operation?

When the active window receives an IDCMP_MENUVERIFY message, it has the
option of cancelling the menu operation.  Although this feature may
have some possible uses, for the moment there is no recommended use for
it.


Handling Menu Verify Events

Typically, an application uses menu verify because the application
needs to know when the menus are down.  This goes for the menus of any
window on the screen, not just the application's window.  When the
application receives its IDCMP_MENUVERIFY message, it performs some
minor processing (restoring menu pen colors, for example) and records
the fact that the display is in a ``menu processing'' state (i.e.
Intuition is going to display the menus).  The application then returns
the menu verify message so Intuition can continue with the menu
operation.  The application cannot utilize the screen's resources until
the menu processing state is over.

There are two types of events that can end the menu processing state.
A cancellation or a menu pick can terminate the menu processing state.

There are several events that can cancel a menu operation.  Some
possibilities include Intuition timing out waiting for an outstanding
IDCMP_MENUVERIFY, the active window cancelling the menu operation, and
Intuition failing to allocate enough resources to display the menus.
The ``Intuition Menus'' chapter of the Amiga ROM Kernel Manual:
Libraries attempts to interpret these causes based on the IDCMP
messages that arrive after the application returns the IDCMP_MENUVERIFY
message.

The book should not have mentioned how to interpret the cause of a menu
cancellation.  The reasoning for the cancellation is not really
relevant.  Trying to interpret the cause of a menu cancellation is a
bad idea (especially if you interpret based on the information in the
book; it's wrong).  The only important fact is that the ``menu
processing'' state has terminated and the application can resume normal
operations.

Any of the following message combinations signify the cancellation of
the ``menu processing'' state:

  o IDCMP_MOUSEBUTTONS (IntuiMessage.Code is equal to MENUUP) only
  o IDCMP_MENUPICK (IntuiMessage.Code is equal to MENUNULL) only
  o IDCMP_MOUSEBUTTONS (IntuiMessage.Code is equal to MENUUP) then
      IDCMP_MENUPICK (IntuiMessage.Code is equal to MENUNULL)
  o IDCMP_MENUPICK (IntuiMessage.Code is equal to MENUNULL) then
      IDCMP_MOUSEBUTTONS (IntuiMessage.Code is equal to MENUUP)

Since the active window can cancel menu operations, the application may
need to determine if its window is the active window.  The application
can do this by examining the IntuiMessage.Code field of the menu verify
message.  If that field is equal to MENUWAITING (defined in
<intuition/intuition.h>) the window is not active.  However, if that
field is equal to MENUHOT (defined in <intuition/intuition.h>) the
window is active and can cancel the menu operation by changing the Code
field of the menu verify message to MENUCANCEL (also defined in
<intuition/intuition.h>).  If the application cancels the menu
operation, Intuition will send the active window an IDCMP_MOUSEBUTTONS
event about the right mouse button.

The following are possible cases signifying that the ``menu
processing'' state is over because the user successfully pulled down
and released the menu (there was no cancellation):

  o IDCMP_MENUPICK (IntuiMessage.Code is equal to the menu code)
  o (spurious) IDCMP_MOUSEBUTTONS (IntuiMessage.Code is equal to MENUUP)
      then IDCMP_MENUPICK (IntuiMessage.Code is equal to the menu code)

Note that the menu code could be MENUNULL if no item was selected.
IDCMP_MENUHELP events have the same meaning as the IDCMP_MENUPICK
messages when it comes to terminating the ``menu processing'' state.

There are rare cases in 3.0 and prior, where Intuition does not send
the application an IDCMP message after the user picks a menu item.  The
result is the application does not know that the ``menu processing''
state is over.  The only notable case is when the user types a menu
keyboard shortcut, and Intuition times out waiting for the application
to respond to the menu verify message.

V40 should fix the lack of a terminating event in those rare cases, as
well as eliminate the spurious IDCMP_MOUSEBUTTONS event that can occur
for successful menu picks.


About Double Menu Requesters

Intuition has a feature that allows an application to put up a special
type of requester when the user double clicks the right mouse button.
This requester is known as a Double Menu Requester.  Unfortunately, the
double menu requester is considered to be inconsistant with the Amiga's
user interface, so using them in any capacity is strongly discouraged.
Using them in conjunction with menu verify is even more strongly
discouraged because they significantly complicate processing menu
verify events.  For this reason, never use double menu requester and
menu verify together!