GEOS SDK TechDocs
|
|
4.3 Positioning Visible Objects
|
5 Working with Visible Object Trees
Input events, what they mean, and how they are generated are discussed fully in the Input chapter. The visible world has some default behavior for handling input messages such as MSG_META_START_SELECT
,
MSG_META_END_SELECT
, and
MSG_META_PTR
. For the most part, however, visible objects that want to respond to input must subclass and handle the input messages that interest them.
Composite objects will automatically pass mouse messages on to the proper child directly under the mouse pointer. Non-composite objects (direct subclasses of
VisClass
) have no special default behavior for input handling.
Note that
VisClass
does not intelligently handle layering of objects. That is, if one object is visibly on top of another object, it will not necessarily receive the input events--the events may be passed to the partially hidden object. This is due to the order in which drawing and mouse events are handled by a visible object's children.
Take the example of a visible composite with two children. Each child draws a filled rectangle covering its bounds; the first child has a width and height of 40, and the second child has a width and height of 20. The composite's declaration shows
...
VCI_comp = LargeChild, SmallChild;
...
Because drawing occurs in the order the children are listed, the small child will be drawn over the large child, as shown in the figure below. If each object can intercept and handle mouse events (e.g.,
MSG_META_START_SELECT
), clicks will never reach the small object without special behavior added to the composite. This is because input events are handled in the same order as drawing; the input event will be given to the first child whose bounds include the event's coordinates.
So, a click event on (10, 10), which is in the middle of the small square, would first be passed to the LargeChild object. The large child would see that the click was within its bounds, and it would take the event. The event would never be handled by the small object.
Therefore, if you need to have overlapping objects which handle user input, you will have to add special features for bounds detection. In the example of the two squares, if neither were to move, the composite could simply pass the event to the small child first and then to the large child, assuming the small child is always on top. If the objects could be moved forward and back so they hide each other, the composite (or the objects themselves) will need some other, more complex, detection behavior.
MSG_META_PTR, MSG_META_START_SELECT, MSG_META_END_SELECT, MSG_META_DRAG_SELECT, MSG_META_DRAG, MSG_META_START_MOVE_COPY, MSG_META_DRAG_MOVE_COPY, MSG_META_START_OTHER, MSG_META_END_OTHER, MSG_META_DRAG_OTHER
Composite objects will automatically pass mouse messages on to the first child directly under the mouse pointer. Non-composite objects (direct subclasses of
VisClass
) have no special default behavior for input handling.
Typically, a visible object that needs to handle mouse input will subclass
MSG_META_START_SELECT
(or one of the other press events such as
MSG_META_START_MOVE_COPY
). This message is sent when the user presses on the "select" mouse button while the pointer is over the object. In this method, the object should grab the mouse (as shown below). When it has the mouse grab, it will receive
MSG_META_PTR
each time the mouse is moved; the object should subclass this message to provide the desired reaction to mouse moves. Finally, when the user releases the select button, the object will receive a
MSG_META_END_SELECT
. At this point, it should release the mouse grab.
Typically, mouse events will arrive with coordinates specified in 16 bits. This is the default graphics space, and it represents a coordinate system more than 25 yards on a side. Nearly all applications will find this graphic system big enough for their uses. However, if you need larger coordinates, you can use the large document space with 32-bit coordinates. To do this, you must set the GVA_WINDOW_COORDINATE_MOUSE_EVENTS in the
GVI_attrs
field of your GenView object and set up your visible objects correctly. For more information on supporting 32-bit graphic spaces with visible objects, see Visible Layers and 32-Bit Graphics
.
MSG_VIS_GRAB_MOUSE, MSG_VIS_FORCE_GRAB_MOUSE, MSG_VIS_GRAB_LARGE_MOUSE, MSG_VIS_FORCE_GRAB_LARGE_MOUSE, MSG_VIS_RELEASE_MOUSE
When an object "grabs the mouse," it requests that the UI send all future mouse events directly to that object. Normally, mouse events will travel down the visible object tree until they reach either the leaf object under the pointer or an object under the pointer that handles them. When an object has the mouse grab, the mouse events will go to the object with the grab regardless of the location of the pointer.
Typically, if an object wants to receive mouse events, it will subclass
MSG_META_START_SELECT
. This message is sent to the object when the pointer is over the object's bounds and the user presses the select button. In this handler, the object grabs the UI's gadget exclusive and then grabs the mouse. A good example of this can be found in the TicTac sample application's handler for
MSG_META_START_SELECT
.
After an object grabs the mouse, it receives all pointer and drag events that occur. These are primarily
MSG_META_PTR
messages, and the object must subclass
MSG_META_PTR
to achieve the proper behavior it wants. When the user lets go of the select button, the object will receive a
MSG_META_END_SELECT
. If it grabbed the mouse (which it probably did if it receives this message), it must relinquish both the gadget exclusive and its mouse grab.
An example of getting and releasing the mouse grab (taken from the TicTac sample application) is shown in Grabbing and Releasing the Mouse . The object subclasses these messages to let the user drag it around the screen.
The UI allows the visible object to get the normal mouse grab by using four different messages. Each of these is detailed below. If you're using a large document (32-bit coordinates), you will use the "large" mouse grabs. Otherwise, the normal mouse grab messages will do.
void MSG_VIS_GRAB_MOUSE();
A visible object sends itself this message (with
@call
) when it wants to acquire the normal mouse grab. The message
MSG_VIS_RELEASE_MOUSE
must be used to relinquish the grab.
Source: Unrestricted.
Destination: Any visible object--typically sent by the object to itself.
Interception: Highly unlikely.
void MSG_VIS_FORCE_GRAB_MOUSE();
A visible object sends itself this message (with
@call
) when it wants to forcibly grab the mouse input. The object will acquire the mouse grab even if another object currently has it; the other object will receive a
MSG_VIS_LOST_GADGET_EXCL
when it loses the mouse by a forced grab. The object must release the grab later with
MSG_VIS_RELEASE_MOUSE
.
Source: Unrestricted.
Destination: Any visible object--typically sent by the object to itself.
Interception: Highly unlikely.
void MSG_VIS_GRAB_LARGE_MOUSE();
A visible object sends itself this message (with
@call
) when it wants to acquire the mouse grab and when it wants 32-bit coordinates. If the object wants 16-bit coordinates, it should use
MSG_VIS_GRAB_MOUSE
, above. The object must relinquish the mouse grab with
MSG_VIS_RELEASE_MOUSE
.
Source: Unrestricted.
Destination: Any visible object--typically sent by the object to itself.
Interception: Highly unlikely.
void MSG_VIS_FORCE_GRAB_LARGE_MOUSE();
A visible object sends itself this message (with
@call
) when it wants to forcibly grab the mouse input and when it wants large (32-bit) input coordinates. If it wants normal (16-bit) coordinates, it should use
MSG_VIS_FORCE_GRAB_MOUSE
, above. The object will acquire the mouse grab even if another object currently has it; the other object will receive a
MSG_VIS_LOST_GADGET_EXCL
when it loses the mouse by a forced grab. The object must release the grab later with
MSG_VIS_RELEASE_MOUSE
.
Source: Unrestricted.
Destination: Any visible object--typically sent by the object to itself.
Interception: Highly unlikely.
void MSG_VIS_VUP_ALTER_INPUT_FLOW(@stack
PointDWord translation,
WindowHandle window,
optr object,
word grapTypeAndFlags);
This message is the primitive employed by the grab/release messages shown above. Objects will rarely use this unless they are large objects (using 32-bit coordinates). Large objects and composites should subclass this message. In the case of a mouse grab, they should add in their 32-bit offset amounts to the translation structure before passing the event on to their superclasses. This will result in large mouse events being properly translated for the duration of the mouse grab.
Source: Unrestricted.
Destination: Any visible object--typically a VisContent which uses a 32-bit graphics space for its children.
Parameters:
translation
The offsets to the origin of the "local" 16-bit graphics space.
window
object
grabTypeAndFlags
VisInputFlowGrabType
, described below; the low byte contains a
VisInputFlowGrabFlags
record, also described below.Return: Nothing.
Interception: Any VisContent object that uses a large graphics space should subclass this method. In the handler, it should apply the stated translation, then call its superclass. Each subsequent mouse event will have the translation applied before being passed on to the composite's children.
Structures:
The types of
VisInputFlowGrabType
are listed below:
VisInputFlowGrabFlags
are listed below:
object
must be passed--if a release, the grab will not be released unless the objects match. Note also that only one object may have the active grab, but many objects may have either passive grab at a given time.void MSG_VIS_RELEASE_MOUSE();
A visible object sends itself this message if it has the mouse grab and wants to release it. Typically, this message will be called in the object's
MSG_META_END_SELECT
handler. It works for both large and small grabs.
Source: Any visible object.
Destination: Any visible object--typically sent by the object to itself.
Interception: Unlikely.
Code Display 15-2 Grabbing and Releasing the Mouse
/* This code display shows the MSG_META_START_SELECT, MSG_META_END_SELECT, * and MSG_VIS_LOST_GADGET_EXCL handlers from the TicTac sample application. * * The sequence of input events and the messages they generate follow the * following basic patterns: * 1. User presses select button * MSG_META_START_SELECT generated, sent to object under mouse pointer * If object under pointer is a game piece, * Game piece grabs gadget exclusive * Game piece grabs mouse * 2. User holds button and drags mouse * MSG_META_DRAG_SELECT generated, sent to object with mouse grab * Game piece sets internal "dragging" flag * Game piece draws outline * MSG_META_PTR messages generated during drag, sent to object with mouse grab * Game piece erases previous outline * Game piece draws new outline at new pointer position * 3. User releases button * MSG_META_END_SELECT generated, sent to object with mouse grab * Game piece releases gadget exclusive (MSG_VIS_RELEASE_GADGET_EXCL) * MSG_VIS_LOST_GADGET_EXCL generated, sent to mouse grab (game piece) * Game piece erases old outline, if any * Game piece moves itself, erases old bounds, draws new bounds * Game piece releases mouse grab (MSG_VIS_RELEASE_MOUSE) */
/*********************************************************************** * MSG_META_START_SELECT for TicTacPieceClass *********************************************************************** * SYNOPSIS: Grabs the mouse and calls for future pointer events. * When the user clickes in the view, TicTacView will pass * the click event to TicTacBoard. Since TicTacBoardClass * does not intercept the event, VisContentClass passes * it on to its child object currently under the pointer. * PARAMETERS: * void (MouseReturnParams *retVal, * word xPosition, word yPosition, word inputState); * * STRATEGY: When the piece object receives this message, it means * it has been clicked on by the user and the mouse button * is still down. The piece must grab the mouse so that it * gets all future mouse events, and it must request that * all future mouse events be sent to it. This ensures * that if the pointer leaves the object's bounds while * the button is still pressed, the piece object will still * receive all the pointer events (otherwise they would be * sent to whatever object was under the new pointer position). ***********************************************************************/
@method TicTacPieceClass, MSG_META_START_SELECT {
/* Grab the gadget exclusive so we're allowed to grab the mouse. */
@call @visParent::MSG_VIS_TAKE_GADGET_EXCL(oself);
/* Grab the mouse. This requests that all future pointer
* events be passed directly to this game piece. */
@call self::MSG_VIS_GRAB_MOUSE();
/* Finally, return that this particular click event has been processed.
* If this flag is not returned, the system will send out the click
* event again. */
retVal->flags = MRF_PROCESSED; /* this event processed */
}
/*********************************************************************** * MSG_META_END_SELECT for TicTacPieceClass *********************************************************************** * SYNOPSIS: This message is received when the selection button has * been released and this game piece had the mouse grab. * All it does is release the gadget exclusive. * PARAMETERS: * void (MouseReturnParams *retVal, * word xPosition, word yPosition, word inputState); ***********************************************************************/
@method TicTacPieceClass, MSG_META_END_SELECT {
@call @visParent::MSG_VIS_RELEASE_GADGET_EXCL(oself);
retVal->flags = MRF_PROCESSED; /* this event processed */
}
/*********************************************************************** * MSG_VIS_LOST_GADGET_EXCL for TicTacPieceClass *********************************************************************** * SYNOPSIS: This message is received when the selection button has * been released and this game piece had the mouse grab. * It first checks to see if the new, proposed bounds are * on the game board. If the bounds are valid, then * it sets the objects VI_bounds field to the new values * and causes the object to erase its original drawing * and draw itself at its new bounds. If the bounds are * not on the game board, it will retain the original bounds * and redraw using them. * PARAMETERS: void (); ***********************************************************************/
@method TicTacPieceClass, MSG_VIS_LOST_GADGET_EXCL {
WindowHandle win; /* window handle of view window */
GStateHandle gstate; /* temporary gstate to draw to */
/* See if piece was being dragged or not. If so, clear the outline. */
if (pself->TTP_dragging) {
/* Get the window handle of the view window and create a * temporary gstate for it to draw to. */
win = @call TicTacView::MSG_GEN_VIEW_GET_WINDOW(); gstate = GrCreateState(win);
/* Set the line color and mode for drawing the outline. */
GrSetLineColor(gstate, CF_INDEX, C_BLACK, 0, 0); GrSetMixMode(gstate, MM_INVERT);
/* Erase outline on screen. */
/* If the game piece type is TTPT_BOX, draw a rectangle * outline. Otherwise draw an ellipse outline. */
if (pself->TTP_pieceType == TTPT_BOX) {
GrDrawRect(gstate, pself->TTP_horizPos, pself->TTP_vertPos,
((pself->TTP_horizPos) + PIECE_WIDTH),
((pself->TTP_vertPos) + PIECE_HEIGHT));
} else {
GrDrawEllipse(gstate, pself->TTP_horizPos, pself->TTP_vertPos,
((pself->TTP_horizPos) + PIECE_WIDTH),
((pself->TTP_vertPos) + PIECE_HEIGHT));
}
/* Check to see if the new bounds are on the game board. If * they are, set the object's bounds to the new values. If * the are not, retain the original values and set the values * to those last stored. */
if (@call TicTacBoard::MSG_TICTAC_VALIDATE_BOUNDS(
((pself->TTP_vertPos) + PIECE_HEIGHT),
((pself->TTP_horizPos) + PIECE_WIDTH),
pself->TTP_vertPos, pself->TTP_horizPos)) {
/* Invalidate the original drawing of the game piece. Send * the VI_bounds rectangle as the parameters because they have * not been changed since the START_SELECT. This message is * the equivalent of calling GrInvalRect() with the same bounds */
@call self::MSG_VIS_BOUNDS_CHANGED(pself->VI_bounds.R_bottom, pself->VI_bounds.R_right, pself->VI_bounds.R_top, pself->VI_bounds.R_left);
/* Set the game piece object's bounds to the new coordinates. */
pself->VI_bounds.R_left = pself->TTP_horizPos; pself->VI_bounds.R_right = (pself->TTP_horizPos) + PIECE_WIDTH; pself->VI_bounds.R_top = pself->TTP_vertPos; pself->VI_bounds.R_bottom = (pself->TTP_vertPos) + PIECE_HEIGHT;
} else {
/* If the bounds are not on the game board, then reset the * current positions to be the original bounds. */
pself->TTP_horizPos = pself->VI_bounds.R_left; pself->TTP_vertPos = pself->VI_bounds.R_top; }
/* Now, the game piece must draw itself at its newly-set * bounds (will draw itself over its original picture if the * new bounds were invalid). */
@call self::MSG_VIS_DRAW(0, gstate);
/* Finally, destroy the temporary gstate used for drawing. */
GrDestroyState(gstate);
/* Clear flag to indicate we are no longer dragging. */
pself->TTP_dragging = FALSE;
}
/* Release the mouse grab now that the move has finished.
* Other objects in the view (other game pieces, for example)
* may now receive pointer, select, and drag events. */
@call self::MSG_VIS_RELEASE_MOUSE(); }
MSG_VIS_ADD_BUTTON_PRE_PASSIVE, MSG_VIS_REMOVE_BUTTON_PRE_PASSIVE, MSG_VIS_ADD_BUTTON_POST_PASSIVE, MSG_VIS_REMOVE_BUTTON_POST_PASSIVE
The type of mouse grab described in the previous section is also known as an "active" mouse grab. An object can also have two other types of mouse grabs: pre-passive and post-passive . While only one object may have the active mouse grab at any given time, any number of objects may have pre- or post-passive grabs on the mouse.
An object with a pre-passive mouse grab receives a copy of the input event before the event goes to its true destination. The copy will be a message of the form
MSG_META_PRE_PASSIVE_...
(e.g., if the event is
MSG_META_PTR
, the pre-passive event is
MSG_META_PRE_PASSIVE_PTR
). All pre-passive events will be handled before the true event is delivered to the object with the active grab. If any of the pre-passive copies of the event is returned with the flag MRF_PREVENT_PASS_THROUGH, the active event will not be sent to its destination. You can use this feature to set up input filters, having an object receive all mouse events pre-passive and filtering out those that should not be delivered. The message
MSG_VIS_REMOVE_BUTTON_PRE_PASSIVE
removes any pre-passive mouse grab from the object.
A post-passive mouse grab is similar to a pre-passive except that the post-passive object receives the event
after
it is sent to its normal destination. The post-passive object will receive a
MSG_META_POST_PASSIVE_...
with the same flags and position information as sent with the input event. An object that has the post-passive grab can release it by sending itself a
MSG_VIS_REMOVE_BUTTON_POST_PASSIVE
.
void MSG_VIS_ADD_BUTTON_PRE_PASSIVE();
A visible object sends itself this message (with
@call
) when it wants to gain a pre-passive mouse grab. The object will receive all subsequent mouse events in the form of
MSG_META_PRE_PASSIVE_...
before
the event's destination object receives them; this message will carry the same input information as passed with the input event. The object should handle
MSG_META_PRE_PASSIVE_...
and, if the event is not to be sent normally to its destination, should return the flag MRF_PREVENT_PASS_THROUGH from that handler. The pre-passive grab will be released when the object sends itself a
MSG_VIS_REMOVE_BUTTON_PRE_PASSIVE
.
Source: Unrestricted.
Destination: Any visible object--typically sent by a visible object to itself when it wants to gain a pre-passive mouse grab.
Interception: Unlikely--Note that the object must, however, intercept any
MSG_META_PRE_PASSIVE...
events it is interested in.
void MSG_VIS_REMOVE_BUTTON_PRE_PASSIVE();
This message removes the pre-passive grab from a visible object.
Source: Unrestricted.
Destination: Any visible object--typically sent by a visible object to itself when it has a pre-passive grab and wants to release it.
Interception: Unlikely.
void MSG_VIS_ADD_BUTTON_POST_PASSIVE();
A visible object sends itself this message (with
@call
) when it wants to gain the post-passive mouse grab. The object will receive all subsequent mouse events in the form of
MSG_META_POST_PASSIVE_...
after
the event's destination object receives them; this message will carry the same input information as passed with the input event. The object should handle the appropriate
MSG_META_POST_PASSIVE_...
to properly receive the events. The post-passive grab will be released when the object receives a
MSG_VIS_REMOVE_BUTTON_POST_PASSIVE
.
Source: Unrestricted.
Destination: Any visible object--typically sent by a visible object to itself when it wants to receive post-passive input events.
Interception: Unlikely--Note that the object must, however, handle any
MSG_META_POST_PASSIVE_...
events it is interested in.
void MSG_VIS_REMOVE_BUTTON_POST_PASSIVE();
This message removes any post-passive mouse grab from the object.
Source: Unrestricted.
Destination: Any visible object--typically sent by a visible object to itself to release a post-passive mouse grab.
Interception: Unlikely.
MSG_VIS_TAKE_GADGET_EXCL, MSG_VIS_RELEASE_GADGET_EXCL, MSG_VIS_LOST_GADGET_EXCL, MSG_VIS_VUP_QUERY_FOCUS_EXCL, MSG_VIS_FUP_QUERY_FOCUS_EXCL, MSG_VIS_VUP_ALLOW_GLOBAL_TRANSFER
The gadget exclusive is a marker in the system used by the UI to indicate which object has exclusive access to input gadget functionality. Only one gadget at a time may have the gadget exclusive, and the gadget exclusive may be forcibly taken from an object by another object (for example, when a system-modal dialog comes up during a drag operation).
At times, an object will force the mouse input to go to a different object from that which has the current active grab. This is done almost exclusively by the Specific UI library and is rarely, if ever, done by applications. Three messages can be used in determining which object has the current "gadget exclusive," or active mouse grab. These are shown below.
In addition, individual objects can get information about the current state of the Focus hierarchy with
MSG_VIS_VUP_QUERY_FOCUS_EXCL
and
MSG_VIS_FUP_QUERY_FOCUS_EXCL
, also shown below.
To deal with a quick-transfer operation, a visible object may also have to use the message
MSG_VIS_VUP_ALLOW_GLOBAL_TRANSFER
. This message may be used to remove the mouse grab from the GenView in which the visible object resides, thereby allowing mouse events to reach other objects outside the view window.
void MSG_VIS_TAKE_GADGET_EXCL(
optr child);
This message causes the passed object to be given the gadget exclusive. Any object currently having the gadget exclusive will subsequently receive a
MSG_VIS_LOST_GADGET_EXCL
. This is used primarily by the Specific UI.
Source: Unrestricted. Typically sent by a visible object that will next grab the mouse.
Destination: Any visible object--normally sent by an object to its visible parent.
Parameters:
child
The optr of the object to which the gadget exclusive will be given (normally the calling object).
Return: Nothing.
Interception: Unlikely.
See Also:
MSG_VIS_GRAB_MOUSE
,
MSG_VIS_LOST_GADGET_EXCL
void MSG_VIS_RELEASE_GADGET_EXCL(
optr child);
This message causes the passed object to release the gadget exclusive. The object specified by
child
will then receive a
MSG_VIS_LOST_GADGET_EXCL
.
Source: Unrestricted. Typically sent by an object that has a mouse grab and expects to release it.
Destination: Any visible object--normally sent by the object to it's parent.
Parameters:
child
The optr of the object which is to lose the gadget exclusive (normally the calling object).
Return: Nothing.
Interception: Unlikely.
See Also:
MSG_VIS_RELEASE_MOUSE
,
MSG_VIS_LOST_GADGET_EXCL
void MSG_VIS_LOST_GADGET_EXCL();
This message, when received, indicates that the recipient has lost its hold on the gadget exclusive. When an object receives this, it should release the active mouse grab, if appropriate.
Source: Unrestricted--typically sent by the UI.
Destination: The visible object losing the gadget exclusive.
Interception: Mouse grabs should be released in this handler.
void MSG_VIS_VUP_QUERY_FOCUS_EXCL(
ObjectAndGrabParams *retValue);
This message queries up the visible hierarchy to find the object having the current focus in the current window. The current window is taken to be the window in which the object receiving the message resides.
Source: Unrestricted.
Destination: Any visible object--typically sent by a visible object to itself to find the focus optr in its window.
Parameters:
retValue
A pointer to an empty
ObjectAndGrabParams
structure, shown below.
Return: The
ObjectAndGrabParams
structure pointed to by
retVal
will be filled with the appropriate data.
Interception: Unlikely.
Structures:
The structure of the
ObjectAndGrabParams
is shown below:
typedef struct {
word OAGP_grabFlags; /* flags */
word OAGP_unused; /* reserved */
optr OAGP_object; /* object with focus */
} ObjectAndGrabParams;
The
OAGP_grabFlags
field contains a record of
HierarchicalGrabFlags
OAGP_object
has the exclusive.void MSG_VIS_FUP_QUERY_FOCUS_EXCL(
ObjectAndGrabParams *retValue);
This message queries the focus hierarchy to see which object has the current focus. The current focus object does not have to be in the caller's visible tree.
Source: Unrestricted.
Destination: Any visible object.
Parameters:
retValue
A pointer to an empty
ObjectAndGrabParams
structure, shown above in the entry for
MSG_VIS_VUP_QUERY_FOCUS_EXCL
.
Return: The
ObjectAndGrabParams
structure pointed to by
retVal
will be filled with the appropriate data.
Interception: Unlikely. This message is not deliverd to all visible objects, rather only those marked as VTF_WIN_GROUP or VTF_IS_INPUT_NODE. If you are implementing a new focus node, and need this message, and are not a window group, you will need to set the VTF_IS_INPUT_NODE bit in your init routine.
Structures: The structure of the
ObjectAndGrabParams
is shown in the entry for
MSG_VIS_VUP_QUERY_FOCUS_EXCL
.
void MSG_VIS_VUP_ALLOW_GLOBAL_TRANSFER();
This message is sent by a visible object to itself when a quick-transfer operation is underway and the pointer has to be allowed to leave the bounds of the object's view window. This message will travel up to the content object, which will indicate to the GenView that the pointer events must be allowed to go to other windows in the system.
Source: Unrestricted.
Destination: Any visible object--typically sent by a visible object to itself when the global transfer must be allowed outside its window.
Interception: Unlikely.
MSG_VIS_VUP_SET_MOUSE_INTERACTION_BOUNDS, MSG_VIS_VUP_GET_MOUSE_STATUS, MSG_VIS_VUP_TERMINATE_ACTIVE_MOUSE_FUNCTION, MSG_VIS_VUP_BUMP_MOUSE
The UI can control the mouse image and events as they occur. Because the UI is based on the visible classes, the messages that control the mouse status are also available to you, though they will probably be of very little utility. These messages are given below.
void MSG_VIS_VUP_SET_MOUSE_INTERACTION_BOUNDS(@stack
int bottom,
int right,
int top,
int left);
A visible object requesting the mouse grab sends this message up the visible tree. This message will be handled by a content object. It indicates a new set of draggable bounds in case the user initiates a drag-scrolling operation. This message is sent automatically when the visible object requests the grab.
Source: A visible object requesting a mouse grab.
Destination: The sender sends this message to itself.
Parameters:
bottom, right, top, left
The four bounds of the new bounding rectangle. Default is the bounds of the object sending the message.
Return: Nothing.
Interception: Unlikely.
word MSG_VIS_VUP_GET_MOUSE_STATUS();
This message is rarely used by any objects outside the UI library. It returns the information passed with the last mouse event. The word return value contains two byte-sized sets of flags. The high byte is a list of the active UI functions, and the low byte represents the current button information.
Source: Unrestricted.
Destination: Any visible object--typically sent by a visible object to itself when it can not locally store the latest mouse information.
Parameters: None.
Return: A word containing two values: The high word is a record of type
UIFunctionsActive
, and the low word is a word of
ButtonInfo
.
Interception: Unlikely.
void MSG_VIS_VUP_TERMINATE_ACTIVE_MOUSE_FUNCTION();
This message is sent by a visible object to itself to terminate any active mouse function, forcing it to be a function of type "other." This message is used only by the Specific UI library in cases where input synchronization problems occur in specific places. Applications should generally not use this message.
Source: A visible object handling active input events.
Destination: Sent by the visible object to itself.
Interception: This message should not be subclassed.
void MSG_VIS_VUP_BUMP_MOUSE(
int xBump,
int yBump);
This message causes the UI to bump the pointer image on the screen by the passed offsets as if the user had moved the mouse. It's unlikely your objects will subclass this message; you may, however, use it to bump the mouse. It is most often used by specific UI objects (menus, scrollers) that make the mouse follow their movements.
Source: Unrestricted.
Destination: Any visible object.
Parameters:
xBump
The horizontal amount to bump the mouse.
yBump
Return: Nothing.
Interception: Unlikely.
MSG_META_GRAB_KBD, MSG_META_FORCE_GRAB_KBD, MSG_META_RELEASE_KBD
The keyboard, like the mouse, may be grabbed by visible objects. Keyboard events arrive in the form
MSG_META_KBD_CHAR
; a single message represents all different types of keyboard events (unlike mouse events, which can be much more diverse).
To grab the keyboard, the visible object should send itself the message
MSG_META_GRAB_KBD
. If the grab should be made in any circumstances, the object should use
MSG_META_FORCE_GRAB_KBD
. To release the keyboard grab, the object should send itself
MSG_META_RELEASE_KBD
.
void MSG_META_GRAB_KBD();
A visible object will send itself this message (using
@call
) when it wants to gain the keyboard grab. To release the grab, it must send itself a
MSG_META_RELEASE_KBD
. If it wants to gain the exclusive regardless of whether another object has it, it should use
MSG_META_FORCE_GRAB_KBD
.
Source: Unrestricted.
Destination: Any visible object--typically sent by a visible object to itself to gain the keyboard grab.
Interception: Unlikely--Note that the object must, however, intercept
MSG_META_KBD_CHAR
to receive the subsequent keyboard events.
void MSG_META_FORCE_GRAB_KBD();
A visible object will send itself this message (using
@call
) when it wants to gain the keyboard grab whether or not another object currently has it. To release the grab, the object must later send itself
MSG_META_RELEASE_KBD
.
Source: Unrestricted.
Destination: Any visible object--typically sent by a visible object to itself to force a keyboard grab.
Interception: Unlikely.
void MSG_META_RELEASE_KBD();
A visible object that has the keyboard grab must send itself this message to release the grab.
Source: Unrestricted.
Destination: Any visible object--typically sent by a visible object to itself to release its keyboard grab.
Interception: Unlikely.
MSG_VIS_QUERY_IF_OBJECT_HANDLES_INK
If a visible object expects and wants Ink input, it should subclass the message
MSG_VIS_QUERY_IF_OBJECT_HANDLES_INK
. This message queries the visible object, which should return specific values based on the current input state and object bounds.
This message has two default handlers; the default
VisClass
handler always returns
false
, indicating that the visible object does not expect Ink input. You can, however, substitute a second default handler for the
VisClass
handler by adding the following line to your Goc file after the object's class definition:
@method VisObjectHandlesInkReply, <YourClass>,
MSG_VIS_QUERY_IF_OBJECT_HANDLES_INK;
This will, in essence, substitute the system-provided routine
VisObjectHandlesInkReply()
for a subclassed message handler. This routine will do the right thing for the object in interacting with the input manager. All subsequent input events will be considered Ink events.
void MSG_VIS_QUERY_IF_OBJECT_HANDLES_INK(
VisCallChildrenInBoundsFrame *data);
This message is subclassed by objects that handle Ink input. See above for directions on handling this message. The parameters are five data words that may be modified and the bounds of a rectangle. This message will be sent to all objects whose bounds fall within the passed rectangle.
Source: Unrestricted.
Destination: Any visible object.
Parameters:
data
A pointer to a
VisCallChildrenInBoundsFrame
structure containing the bounding rectangle and five words of data. This structure is described below.
Return: Three fields of the
VisCallChildrenInBoundsFrame
structure pointed to by
data
will have meaning on return. See the Interception paragraph below to determine whether the return values should be set or not in a subclassed handler.
VCCIBF_data1
VCCIBF_data2
VCCIBF_data3
Interception: If an object wants to receive ink messages, it should do the following things in its handler for this message: First compare the passed
VCCIBF_data3
value with the top bound of the object. Then, if the upper bound of the object is less than the
VCCIBF_data3
value (or if the value in
VCCIBF_data1
is zero), then the object should return the values indicated in the Return paragraph above. Otherwise, if these conditions are not met, it should return with the structures and registers unchanged.
Structures: The
VisCallChildrenInBoundsFrame
structure is shown below:
typedef struct {
word VCCIBF_data1;
word VCCIBF_data2;
word VCCIBF_data3;
word VCCIBF_data4;
word VCCIBF_data5;
/* Five data words as described above */
Rectangle VCCIBF_bounds;
/* bounds must be in the coordinate
* system of the parent of the caller */
} VisCallChildrenInBoundsFrame;
GEOS SDK TechDocs
|
|
4.3 Positioning Visible Objects
|
5 Working with Visible Object Trees