home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 3
/
Meeting_Pearls_III.iso
/
Pearls
/
debug
/
Monitor
/
MonIDCMP
/
MonIDCMP.doc
< prev
next >
Wrap
Text File
|
1987-10-31
|
13KB
|
262 lines
OVERVIEW:
MonIDCMP lets you monitor the IntuiMessages that pass through any IDCMP
window. It prints the IntuiMessage class, mouse coordinates, qualifier
values, and other useful information when appropriate. For instance, if
a GADGETDOWN message is reported, the GadgetID, GadgetType, GadgetFlags, and
IntuiText are printed; if the gadget is a PROPGADGET, its Pot and Body values
also are displayed. This is a useful tool for debugging applications, for
determining exactly what messages arrive and when, and for snooping into the
inner workings of other programs.
HOW TO USE MONIDCMP:
To use MonIDCMP you need to know the title of the window you want to monitor
and the title of the screen where that window can be found. Usually you can
read the window title from the window itself. If this is not possible,
then use the command:
1> MonIDCMP LIST WINDOWS
This will list each of the screens together with their associated windows.
The titles are enclosed in quotes so that any leading or training spaces are
apparent.
Once you have identified the window and screen you want to use, you can begin
monitoring it by typing MONIDCMP followed by the window name and screen title.
If either the window title or screen title includes spaces, then you should
put double quotes (") around it. If the window is on the Workbench Screen,
then you don't need to specifiy the screen title.
For example, if you want to monitor the window called MyWindow on the Workbench
Screen, then you should type
1> MonIDCMP MyWindow "Workbench Screen"
or simply
1> MonIDCMP MyWindow
To monitor the window called 'Input Window' on the screen 'Test Screen', type:
1> MonIDCMP "Input Window" "Test Screen"
If MonIDCMP can't find the window or screen that you specified, it will tell
you. Use the MONIDCMP LIST WINDOWS command to get a list of windows that you
can monitor. The case of the letters does not matter (upper- and lower-case
are treated as the same).
When MonIDCMP finds the window you specified, it will print its version number
and a message that tells you that the monitor is installed and how to stop
it. Once the monitor is installed, any IntuiMessages that arrive in the
monitored window will be displayed in the CLI window.
When you are done using MonIDCMP, click in the CLI window where it is running
and press CTRL-C. MonIDCMP should tell you that it has stopped monitoring the
window.
If MonIDCMP detects a CLOSEWINDOW IntuiMessage for the monitored window, it
expects the window to close so it stops monitoring the window without your
having to press CTRL-C. Note that this ONLY occurs when a CLOSWINDOW message
arrives. If the window is closed for some other reason (e.g., you chose QUIT
from a menu), MonIDCMP won't know about it, and you will have to cancel
MonIDCMP using CTRL-C.
OUTPUT RE-DIRECTION:
MonIDCMP can produce a lot of output which may move too fast for you to see,
or you may want a permanent copy of the IDCMP activity saved for future
reference. In either of these cases, you can re-direct the output from
MonIDCMP to a file (or to a printer) via the standard CLI command-line
output re-direction. For example:
1> MonIDCMP >RAM:WB Workbench
would monitor the Workbench window (on the Workbench Screen) but send the
output to the file RAM:WB. Output re-direction can also be an important tool
during situations that may cause deadlocks due to layer locking (see CAUTIONS
below).
EVENT MASKS:
Sometimes you are only interested in a particular type of IntuiMessage, for
example, you may only want to know about gadget and mouse events even though
the window is reporting menu picks, size changes and disk events as well. To
do this you use the MASK option of the MonIDCMP command. The mask is the
bitwise OR of all the IntuiMessage classes that you want to see. For
instance, GADGETUP is 0x40, GADGETDOWN is 0x20 and MOUSEBUTTONS is 0x8, so
the mask we would use for our example above would be 0x68. The mask value
follows the word MASK on the command line and must precede the window name:
1> MonIDCMP MASK 68 Workbench
The mask value is assumed to be in HEX. The class codes are listed in the
file intuition/intuition.h (right after the struct IntuiMessage definition).
Note that MonIDCMP does not alter the IDCMPFlags field of the monitored
window, so the messages actually displayed will only be those that are in both
the MASK and the window's IDCMPFlags field. MonIDCMP does not call
ModifyIDCMP() to include message additional classes that you specify in MASK.
DISPLAY FORMATS:
MonIDCMP displays the message class, mouse coordinates and qualifiers (if any)
for each message it receives. The mouse coordinates are shown in decimal.
The qualifier field is shown in HEX, with translations of the important
bits (shift, ALT, CTRL and Amiga keys, key repeat, numeric pad, and button
status; L means Left, R means Right, M means Middle (for future compatibility -
see inputevent.h), and C means CapsLock).
The following classes include additional information:
Gadgets: The GadgetID, gadget text (if any), GadgetType, and GadgetFlags are
shown (the ID is in decimal, the flags are in HEX). If the gadget is a
STRGADGET, the data stored in the StringInfo buffer also is printed. If the
gadget is a PROPGADGET, the Pot and Body values are displayed (in decimal), as
well as the KNOBHIT status, for the gadget's direction(s) of movement.
Menus: The menu code is displayed and the translated MENUNUM, ITEMNUM and
SUBNUM, as are the menu title, item text (if ITEMTEXT is set) and subitem text
(if ITEMTEXT is set). If there were multiple menu-item selections during the
menu pick (i.e., the user clicked the left button while still holding the
right), these data are displayed for each item chosen.
Mouse Buttons: SELECTUP, SELECTDOWN, MENUUP or MENUDOWN is displayed.
Raw Keys: The raw key value is shown and whether the key was pressed or
released. A simple translation to a keyboard key is performed and displayed.
Since the RAWKEY events include information for mapping dead keys (that
produce diacritical markings), the previous key and qualifiers (if any) are
displayed as well.
Vanilla Keys: the ASCII code and character are displayed.
TECHNICAL NOTES:
MonIDCMP works by taking over the monitored window's UserPort message port.
The message port structure includes (among other things) a pointer to a task
to be signalled when a message arrives and a the signal number to use.
MonIDCMP substitutes a pointer to itself in the message port's mp_SigTask
field so that it is signalled rather than the monitored process. When
MonIDCMP receives a signal from the message port, it traverses the list of
messags that has arrived (stored in the mp_MsgList field, which is an Exec
List of Exec Node structures which are at the tops of the IntuiMessages that
have arrived in the UserPort) and prints the contents of the messages. Once
this is done, it calls Signal() to signal the original task that messages have
arrived in the port. That task then does normal GetMsg() and ReplyMsg() calls
to get and reply to the messages, and is unaware that we "peeked" at the
messages ahead of it.
New messages can arrive in the UserPort at any time, however, even when there
are already messages there. In order to prevent us from re-printing messages
that we have already seen, we must mark the messages somehow so that we can
distinguish new messaged from old ones. To do this MonIDCMP sets the high bit
in the ln_Type field (normally NT_MESSAGE) of the Node structure at the top of
each IntuiMessage as it prints it. This is kind of Kludgy, but it does not
seem to annoy GetMsg() or ReplyMsg() or Intuition, so it seems a useful
device. The important point is that it is reset to NT_MESSAGE every time
Intuition posts a new message, so even though Intuition re-uses the same
memory areas for it's messages, our flag bit is reset automatically (this is
not true of the other, un-used fields of the Node structure, so I had to use
the ln_Type field).
Another method would have been to take over the reply ports for each message
as it came in, and reset the flags ourselves, but this seems needlessly
complicated, and causes some other problems as well.
Once we signal the monitored task that messages are ready, it will read ALL
the messages from the UserPort, including any that arrive while it is
processing the others. In order to prevent us from missing these messages, we
must run at a higher priority than the monitored process; that way, even if
the monitored process is running (i.e., it is not in a Wait() call), as soon
as a new message arrives, we will pre-empt it and can process the new message
without worrying about the other process taking it before we get the chance to
see it. MonIDCMP takes care of setting the priority so that it is one higher
than that of the monitored process and resetting it when it is done.
Note that this method of monitoring message ports is not restricted to window
UserPorts and IntuiMessages. It can be used with any type of message port
provided you know where to look for it and you know the formats of the
messages it will contain. The UserPort fits both these critera perfectly:
it is at a fixed position within the window structure (which we can find from
screens, which we can find from IntuitionBase) and it has a well-defined
set of messages that are easy to display.
CAUTIONS:
More than one window in a screen can have the same name. Currenly, MonIDCMP
will monitor the FIRST window that matches the one you supply (here "first"
means first as it is displayed by the MonIDCMP LIST WINDOWS command).
MonIDCMP does not provide a method for specifying other windows with the
same name (you would have to close the first one in order to monitor the
second, etc.).
Since MonIDCMP prints the contents of the messages BEFORE the monitored
process can act on them, it is possible for MonIDCMP to cause a deadlock
situation. For instance, suppose a program locks the screen's layers, and
then waits for mouse moves or a mouse button up message. When MonIDCMP
is signalled by one of these events, it attempts to display messages to that
effect on the screen; but since the layers are locked, it can't do it, so it
waits for the layers to be unlocked. The program will not unlock the layers,
however, until after it receives the button up message. This produces a
deadlock, and the two processes hang. For example, this appears to be what
happens if you monitor the Workbench window and try to move a disk icon.
To get arround this problem, simply re-direct the MonIDCMP output into a
file. The locked layers will not inhibit writing to the file, so no deadlock
will occur and processing can continue. This is the only safe way to monitor
the Workbench.
MonIDCMP relies on the fact that it runs at a higher priority than the process
that it is monitoring. This assures it that it will pre-empt the monitored
process when new messages arrive, hence it will not be able to miss any
messages. If the monitored process calls Forbid() or Disable(), however, or
if it changes its priority, this may cause MonIDCMP to miss whole blocks of
messages, particularly the kind that come in pairs (INACTIVEWINDOW and
ACTIVEWINDOW, MENUUP and MENUPICK, etc). Be careful when monitoring processes
of this kind.
MonIDCMP can seriously impact program timing (i.e., double-click testing,
PROPGADGET updating, etc). Programs that use IntuiTicks for timing or that
respond to MOUSEMOVE events will be slowed down considerably. Color changing
sliders will react sluggishly, for instance. Re-directing MonIDCMP output to
a RAM: file will help.
Note that this time dealy can cause a decrease in the amount of available free
memory. If IntuiMessages are not replied to quickly enough, Intuition will
AllocMem() space for new ones as they arrive, but will not de-allocate them
until the window to which they were posted is closed. This will happen when
lots of MOUSEMOVE events come in and MonIDCMP takes time to print them, for
instance. To avoid this problem, use the MASK option to eliminate MOUSEMOVE
and INTUITICKS messages.
COMPILING AND LINKING MONIDCMP:
I used Lattice C to produce MonIDCMP, but I tried to make it as compatible
with Manx as possible. I do not own the Manx compiler, however, so I can not
test it out. I suspect that any adjustments will be minor.
For Lattice C (v3.10) I just do:
1> LC -L -dLATTICE MonIDCMP
That should do it.
AUTHOR:
Davide P. Cervone
University of Rochester Computing Center DPVC@UORDBV.BITNET
Taylor Hall dpvc@tut.cc.rochester.EDU
Rochester, New York dpvc@ur-tut.UUCP
(716)275-2811
Copyright (c) 1987 by Davide P. Cervone, all rights reserved.