VisClass: 4.4 Using VisClass: Handling Input

Up: GEOS SDK TechDocs | Up | Prev: 4.3 Positioning Visible Objects | Next: 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.

Mouse Events

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 .

Grabbing the Mouse

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.

MSG_VIS_GRAB_MOUSE

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.

MSG_VIS_FORCE_GRAB_MOUSE

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.

MSG_VIS_GRAB_LARGE_MOUSE

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.

MSG_VIS_FORCE_GRAB_LARGE_MOUSE

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.

MSG_VIS_VUP_ALTER_INPUT_FLOW

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
The handle of the view window associated with this input flow alteration.
object
The optr of the object altering the input flow.
grabTypeAndFlags
The type and flags for the input flow grab affected by this alteration. The high byte contains a record of 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:

VIFGT_ACTIVE
The affected grab type is the active grab.
VIFGT_PRE_PASSIVE
The affected grab type is the pre-passive grab.
VIFGT_POST_PASSIVE
The affected grab type is the post-passive grab.
The flags of VisInputFlowGrabFlags are listed below:
VIFGF_NOT_HERE
Flag set to indicate that the message should not be handled in this method but rather passed up the tree with this flag cleared. It is used to distinguish between requests made by other objects and requests made by an object sent to itself. It also allows an object to redirect the message to another node not in the visible hierarchy by handling the message and passing it in a direction other than up the visible tree. This overrides all the other flags in this record.
VIFGF_FORCE
Flag set if the grab should be forced. Note that both VIFGF_GRAB and VIFGT_ACTIVE must also be specified.
VIFGF_GRAB
Flag set if the grab is being made, clear if the grab is being released. In either case, 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.
VIFGF_KBD
Flag set if action is a keyboard grab or release.
VIFGF_MOUSE
Flag set if action is a mouse grab or release.
VIFGF_LARGE
Flag set if large mouse events are affected by the flow alteration. VIFGF_MOUSE must also be set.
VIFGF_PTR
Flag set if mouse grab and pointer events are requested. If flag clear, only button-related events will be sent. VIFGF_MOUSE must also be set.

MSG_VIS_RELEASE_MOUSE

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();
}

Passive Grabs

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 .

MSG_VIS_ADD_BUTTON_PRE_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.

MSG_VIS_REMOVE_BUTTON_PRE_PASSIVE

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.

MSG_VIS_ADD_BUTTON_POST_PASSIVE

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.

MSG_VIS_REMOVE_BUTTON_POST_PASSIVE

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.

The Gadget Exclusive and Focus Hierarchy

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.

MSG_VIS_TAKE_GADGET_EXCL

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

MSG_VIS_RELEASE_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

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.

MSG_VIS_VUP_QUERY_FOCUS_EXCL

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

, defined in the Input chapter. The allowable flags are

HGF_SYS_EXCL
Indicates this object has the system exclusive.
HGF_APP_EXCL
Indicates this object has the application's exclusive.
HGF_GRAB
Indicates this object wishes to grab the exclusive (if clear, the object wishes to release), when passed as a parameter. In the structure, it merely indicates that the object in OAGP_object has the exclusive.
HGF_OTHER_INFO
Twelve bits used by the specific UI depending on the type of hierarchical grab.

MSG_VIS_FUP_QUERY_FOCUS_EXCL

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 .

MSG_VIS_VUP_ALLOW_GLOBAL_TRANSFER

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.

The Mou se Status

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.

MSG_VIS_VUP_SET_MOUSE_INTERACTION_BOUNDS

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.

MSG_VIS_VUP_GET_MOUSE_STATUS

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.

MSG_VIS_VUP_TERMINATE_ACTIVE_MOUSE_FUNCTION

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.

MSG_VIS_VUP_BUMP_MOUSE

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
The vertical amount to bump the mouse.

Return: Nothing.

Interception: Unlikely.

Keyboard Events

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 .

MSG_META_GRAB_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.

MSG_META_FORCE_GRAB_KBD

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.

MSG_META_RELEASE_KBD

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.

Ink and P en Events

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.

MSG_VIS_QUERY_IF_OBJECT_HANDLES_INK

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
Memory handle of the top object desiring ink.
VCCIBF_data2
Chunk handle of the top object desiring ink.
VCCIBF_data3
Upper bound of the object desiring ink.

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;

Up: GEOS SDK TechDocs | Up | Prev: 4.3 Positioning Visible Objects | Next: 5 Working with Visible Object Trees