Blame lib/Xm/Traversal.c

Packit b099d7
/* 
Packit b099d7
 * Motif
Packit b099d7
 *
Packit b099d7
 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are free software; you can
Packit b099d7
 * redistribute them and/or modify them under the terms of the GNU
Packit b099d7
 * Lesser General Public License as published by the Free Software
Packit b099d7
 * Foundation; either version 2 of the License, or (at your option)
Packit b099d7
 * any later version.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are distributed in the hope that
Packit b099d7
 * they will be useful, but WITHOUT ANY WARRANTY; without even the
Packit b099d7
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
Packit b099d7
 * PURPOSE. See the GNU Lesser General Public License for more
Packit b099d7
 * details.
Packit b099d7
 *
Packit b099d7
 * You should have received a copy of the GNU Lesser General Public
Packit b099d7
 * License along with these librararies and programs; if not, write
Packit b099d7
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
Packit b099d7
 * Floor, Boston, MA 02110-1301 USA
Packit b099d7
*/ 
Packit b099d7
/* 
Packit b099d7
 * HISTORY
Packit b099d7
*/ 
Packit b099d7
#ifdef HAVE_CONFIG_H
Packit b099d7
#include <config.h>
Packit b099d7
#endif
Packit b099d7
Packit b099d7
Packit b099d7
#ifdef REV_INFO
Packit b099d7
#ifndef lint
Packit b099d7
static char rcsid[] = "$TOG: Traversal.c /main/20 1999/08/17 11:52:26 vipin $"
Packit b099d7
#endif
Packit b099d7
#endif
Packit b099d7
/* (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */
Packit b099d7
Packit b099d7
#include <Xm/GadgetP.h>
Packit b099d7
#include <Xm/ManagerP.h>
Packit b099d7
#include <Xm/MenuShellP.h>
Packit b099d7
#include <Xm/PrimitiveP.h>
Packit b099d7
#include <Xm/ScrolledWP.h>
Packit b099d7
#include <Xm/TraitP.h>
Packit b099d7
#include <Xm/TravConT.h>
Packit b099d7
#include <Xm/VendorSEP.h>
Packit b099d7
#include <Xm/VirtKeysP.h>
Packit b099d7
#include <Xm/DisplayP.h>
Packit b099d7
#include "BaseClassI.h"
Packit b099d7
#include "CallbackI.h"
Packit b099d7
#include "RepTypeI.h"
Packit b099d7
#include "TravActI.h"
Packit b099d7
#include "TraversalI.h"
Packit b099d7
Packit b099d7
Packit b099d7
/********    Static Function Declarations    ********/
Packit b099d7
Packit b099d7
static Widget FindFirstManaged( 
Packit b099d7
                        Widget wid) ;
Packit b099d7
static Boolean CallTraverseObsured( 
Packit b099d7
                        Widget new_focus,
Packit b099d7
                        XmTraversalDirection dir) ;
Packit b099d7
static Boolean IsTraversable( 
Packit b099d7
                        Widget wid,
Packit b099d7
                        Boolean require_in_view) ;
Packit b099d7
static Widget FindFirstFocus( 
Packit b099d7
                        Widget wid) ;
Packit b099d7
static Boolean CallFocusMoved(Widget		   old,
Packit b099d7
			      Widget		   new_wid,
Packit b099d7
			      XEvent		   *event,
Packit b099d7
			      XmTraversalDirection direction);
Packit b099d7
static Widget RedirectTraversal(Widget		     old_focus,
Packit b099d7
				Widget		     new_focus,
Packit b099d7
				unsigned int	     focus_policy,
Packit b099d7
				XmTraversalDirection direction,
Packit b099d7
				unsigned int	     pass);
Packit b099d7
Packit b099d7
/********    End Static Function Declarations    ********/
Packit b099d7
Packit b099d7
Packit b099d7
XmFocusData 
Packit b099d7
_XmCreateFocusData( void )
Packit b099d7
{
Packit b099d7
  return (XmFocusData) XtCalloc(1, sizeof( XmFocusDataRec)) ;
Packit b099d7
}
Packit b099d7
Packit b099d7
void 
Packit b099d7
_XmDestroyFocusData(
Packit b099d7
        XmFocusData focusData )
Packit b099d7
{
Packit b099d7
  _XmFreeTravGraph( &(focusData->trav_graph)) ;
Packit b099d7
  XtFree((char *) focusData->trav_graph.excl_tab_list) ;
Packit b099d7
  XtFree((char *) focusData) ;
Packit b099d7
}
Packit b099d7
Packit b099d7
void 
Packit b099d7
_XmSetActiveTabGroup(
Packit b099d7
        XmFocusData focusData,
Packit b099d7
        Widget tabGroup )
Packit b099d7
{
Packit b099d7
    focusData->active_tab_group = tabGroup;
Packit b099d7
}
Packit b099d7
Packit b099d7
Widget 
Packit b099d7
_XmGetActiveItem(
Packit b099d7
        Widget w )
Packit b099d7
{
Packit b099d7
  return XmGetFocusWidget( w) ;
Packit b099d7
}
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
void 
Packit b099d7
_XmNavigInitialize(
Packit b099d7
        Widget request,		/* unused */
Packit b099d7
        Widget new_wid,
Packit b099d7
        ArgList args,		/* unused */
Packit b099d7
        Cardinal *num_args )	/* unused */
Packit b099d7
{   
Packit b099d7
  XmFocusData focusData ;
Packit b099d7
Packit b099d7
  if(    (focusData = _XmGetFocusData( new_wid)) != NULL    )
Packit b099d7
    {
Packit b099d7
      XmNavigationType navType = _XmGetNavigationType( new_wid) ;
Packit b099d7
      
Packit b099d7
      if(    navType == XmEXCLUSIVE_TAB_GROUP    )
Packit b099d7
	{
Packit b099d7
	  ++(focusData->trav_graph.exclusive) ;
Packit b099d7
	  _XmTabListAdd( &(focusData->trav_graph), new_wid) ;
Packit b099d7
	}
Packit b099d7
      else
Packit b099d7
	{
Packit b099d7
	  if(    navType == XmSTICKY_TAB_GROUP    )
Packit b099d7
	    {
Packit b099d7
	      _XmTabListAdd( &(focusData->trav_graph), new_wid) ;
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
      if(    focusData->trav_graph.num_entries
Packit b099d7
	 &&  _XmGetNavigability( new_wid)    )
Packit b099d7
	{
Packit b099d7
	  /* If the graph exists, add the new navigable widget.
Packit b099d7
	   */
Packit b099d7
	  _XmTravGraphAdd( &(focusData->trav_graph), new_wid) ;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  /* If the traversal graph doesn't exist, do nothing, since the
Packit b099d7
   * new widget will be picked-up when the graph is needed and created.
Packit b099d7
   */
Packit b099d7
  return ;
Packit b099d7
}
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
Boolean 
Packit b099d7
_XmNavigSetValues(
Packit b099d7
        Widget current,
Packit b099d7
        Widget request,		/* unused */
Packit b099d7
        Widget new_wid,
Packit b099d7
        ArgList args,		/* unused */
Packit b099d7
        Cardinal *num_args )	/* unused */
Packit b099d7
{
Packit b099d7
  /* This routine is called from the SetValues method of Manager,
Packit b099d7
   * Primitive, and Gadget to keep the traversal data structures
Packit b099d7
   * up-to-date in regards to changes in the traversability of widgets.
Packit b099d7
   *
Packit b099d7
   * There are three purposes for this routine:
Packit b099d7
   *
Packit b099d7
   *   1:  Update the traversal graph in response to changes in
Packit b099d7
   *       a widget's resources such that the widget is newly
Packit b099d7
   *       eligible to receive the traversal focus.
Packit b099d7
   *
Packit b099d7
   *   2:  Update the focus data according to changes in
Packit b099d7
   *       the Motif 1.0 "exclusive tab group" behavior.
Packit b099d7
   *
Packit b099d7
   *   3:  If the new widget of the SetValues call is the focus
Packit b099d7
   *       widget and it becomes ineligible to have the focus,
Packit b099d7
   *       then find an alternative to receive the focus (or
Packit b099d7
   *       reset the focus for the hierarchy to the bootstrap
Packit b099d7
   *       condition).
Packit b099d7
   */
Packit b099d7
Packit b099d7
  XmFocusData focusData ;
Packit b099d7
Packit b099d7
  if(    (focusData = _XmGetFocusData( new_wid)) != NULL    )
Packit b099d7
    {
Packit b099d7
      XmTravGraph graph = &(focusData->trav_graph) ;
Packit b099d7
      XmNavigationType newNavType = _XmGetNavigationType( new_wid) ;
Packit b099d7
      XmNavigationType curNavType = _XmGetNavigationType( current) ;
Packit b099d7
      Boolean ChangeInExclusive = FALSE ;
Packit b099d7
Packit b099d7
      if(    curNavType != newNavType    )
Packit b099d7
	{
Packit b099d7
	  if(    (curNavType == XmEXCLUSIVE_TAB_GROUP)
Packit b099d7
	     ||  (newNavType == XmEXCLUSIVE_TAB_GROUP)    )
Packit b099d7
	    {
Packit b099d7
	      /* This widget was "exclusive", now it is not (or vice-versa).
Packit b099d7
	       * Update the value of the focus data "exclusive" field.
Packit b099d7
	       */
Packit b099d7
	      ChangeInExclusive = TRUE ;
Packit b099d7
Packit b099d7
	      if(    newNavType == XmEXCLUSIVE_TAB_GROUP    )
Packit b099d7
		{
Packit b099d7
		  ++(graph->exclusive) ;
Packit b099d7
		}
Packit b099d7
	      else
Packit b099d7
		{
Packit b099d7
		  --(graph->exclusive) ;
Packit b099d7
		}
Packit b099d7
	    }
Packit b099d7
	  if(    (newNavType == XmEXCLUSIVE_TAB_GROUP)
Packit b099d7
	     ||  (newNavType == XmSTICKY_TAB_GROUP)    )
Packit b099d7
	    {
Packit b099d7
	      if(    (curNavType != XmEXCLUSIVE_TAB_GROUP)
Packit b099d7
		 &&  (curNavType != XmSTICKY_TAB_GROUP)    )
Packit b099d7
		{
Packit b099d7
		  _XmTabListAdd( graph, new_wid) ;
Packit b099d7
		}
Packit b099d7
	    }
Packit b099d7
	  else
Packit b099d7
	    {
Packit b099d7
	      if(    (curNavType == XmEXCLUSIVE_TAB_GROUP)
Packit b099d7
		 ||  (curNavType == XmSTICKY_TAB_GROUP)    )
Packit b099d7
		{
Packit b099d7
		  _XmTabListDelete( graph, new_wid) ;
Packit b099d7
		}
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
      if(    XtIsRealized( new_wid)
Packit b099d7
	 &&  (focusData->focus_policy == XmEXPLICIT)    )
Packit b099d7
	{
Packit b099d7
	  if(    graph->num_entries    )
Packit b099d7
	    {
Packit b099d7
	      if(    ChangeInExclusive    )
Packit b099d7
		{
Packit b099d7
		  /* Since widget has changed to/from exlusive tab group
Packit b099d7
		   * behavior, need to re-make the traversal graph (as needed).
Packit b099d7
		   */
Packit b099d7
		  _XmFreeTravGraph( graph) ;
Packit b099d7
		}
Packit b099d7
	      else
Packit b099d7
		{
Packit b099d7
		  XmNavigability cur_nav = _XmGetNavigability( current) ;
Packit b099d7
		  XmNavigability new_nav = _XmGetNavigability( new_wid) ;
Packit b099d7
Packit b099d7
		  if(    !cur_nav  &&  new_nav    )
Packit b099d7
		    {
Packit b099d7
		      /* Newly navigable widget; add it to the
Packit b099d7
		       * traversal graph.
Packit b099d7
		       */
Packit b099d7
		      _XmTravGraphAdd( graph, new_wid) ;
Packit b099d7
		    }
Packit b099d7
		  else
Packit b099d7
		    {
Packit b099d7
		      if(    cur_nav != new_nav    )
Packit b099d7
			{
Packit b099d7
			  /* Navigability changed; need to re-create the
Packit b099d7
			   * graph the next time it is needed.
Packit b099d7
			   */
Packit b099d7
			  _XmFreeTravGraph( graph) ;
Packit b099d7
			}
Packit b099d7
		    }
Packit b099d7
		}
Packit b099d7
	    }
Packit b099d7
	  if(    !(focusData->focus_item)    )
Packit b099d7
	    {
Packit b099d7
	      Widget shell ;
Packit b099d7
Packit b099d7
	      /* CR 5417: Remove (focusData->focalPoint != XmMySelf) test. */
Packit b099d7
	      if(    XmIsTraversable( new_wid)
Packit b099d7
		 &&  (shell = _XmFindTopMostShell( new_wid))
Packit b099d7
		 &&  XmeFocusIsInShell( shell))
Packit b099d7
		{
Packit b099d7
		  /* Hierarchy currently has no focus, and this widget is
Packit b099d7
		   * now traversable, so bootstrap the focus for the hierarchy.
Packit b099d7
		   */
Packit b099d7
		  _XmMgrTraversal( shell, XmTRAVERSE_CURRENT) ;
Packit b099d7
		}
Packit b099d7
	    }
Packit b099d7
	  else
Packit b099d7
	    {
Packit b099d7
	      if(    (focusData->focus_item == new_wid)
Packit b099d7
		 &&  !IsTraversable( new_wid, TRUE)    )
Packit b099d7
		{
Packit b099d7
		  /* The new_wid now has the focus and is no longer
Packit b099d7
		   * traversable, so traverse away from it to the
Packit b099d7
		   * next traversable item.
Packit b099d7
		   */
Packit b099d7
		  Widget new_focus = _XmTraverseAway( graph, new_wid,
Packit b099d7
                                    (focusData->active_tab_group != new_wid)) ;
Packit b099d7
		  if(    !new_focus    )
Packit b099d7
		    {
Packit b099d7
		      /* Could not find another widget eligible to take
Packit b099d7
		       * the focus, so use any widget to re-initialize/clear
Packit b099d7
		       * the focus in the widget hierarchy.
Packit b099d7
		       */
Packit b099d7
		      new_focus = new_wid ;
Packit b099d7
		    }
Packit b099d7
		  _XmMgrTraversal( new_focus, XmTRAVERSE_CURRENT) ;
Packit b099d7
Packit b099d7
		  if(    !XtIsSensitive( new_wid)    )
Packit b099d7
		    {
Packit b099d7
		      /* Since widget has become insensitive, it did not
Packit b099d7
		       * receive the focus-out event.  Call the focus
Packit b099d7
		       * change method directly.
Packit b099d7
		       */
Packit b099d7
		      _XmWidgetFocusChange( new_wid, XmFOCUS_OUT) ;
Packit b099d7
		    }
Packit b099d7
		  return TRUE ;
Packit b099d7
		}
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  return FALSE ;
Packit b099d7
}
Packit b099d7
Packit b099d7
void 
Packit b099d7
XmeNavigChangeManaged(
Packit b099d7
        Widget wid )
Packit b099d7
{   
Packit b099d7
  /* This routine must be called from the ChangeManaged method of
Packit b099d7
   * all composite widgets that may have traversable children.
Packit b099d7
   * This routine checks to see if the focus widget is traversable;
Packit b099d7
   * if it is not, then an alternative traversable widget is found
Packit b099d7
   * or the focus for the hierarchy is reset to the bootstrap condition.
Packit b099d7
   *
Packit b099d7
   * This routine also detects the condition for which there is no
Packit b099d7
   * focus widget in the hierarchy and a newly managed widget is
Packit b099d7
   * now eligible to have the focus; the focus is then initialized.
Packit b099d7
   */
Packit b099d7
  XmFocusData focus_data ;
Packit b099d7
  _XmWidgetToAppContext(wid);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  if(    XtIsRealized( wid)
Packit b099d7
     &&  (focus_data = _XmGetFocusData( wid))
Packit b099d7
     &&  (focus_data->focus_policy == XmEXPLICIT)    )
Packit b099d7
    {
Packit b099d7
      if(    focus_data->focus_item == NULL    )
Packit b099d7
	{
Packit b099d7
	  Widget firstManaged ;
Packit b099d7
Packit b099d7
	  if(    XtIsShell( wid)    )
Packit b099d7
	    {
Packit b099d7
	      if(    focus_data->first_focus == NULL    )
Packit b099d7
		{
Packit b099d7
		  focus_data->first_focus = FindFirstFocus( wid) ;
Packit b099d7
		}
Packit b099d7
	      if(    (firstManaged = FindFirstManaged( wid)) != NULL    )
Packit b099d7
		{
Packit b099d7
		  /* Set bootstrap trigger for hierarchy that
Packit b099d7
		   * has no current focus.
Packit b099d7
		   */
Packit b099d7
		  XtSetKeyboardFocus( wid, firstManaged) ;
Packit b099d7
		}
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
      else
Packit b099d7
	{
Packit b099d7
	  /* If the focus widget is being destroyed, do nothing for now.
Packit b099d7
	   * We need to wait until _XmNavigDestroy is called to initiate
Packit b099d7
	   * the focus change; if we don't defer selection of the focus
Packit b099d7
	   * widget, the Intrinsics-generated focus-out event for the
Packit b099d7
	   * focus widget will go to the newly-selected focus widget
Packit b099d7
	   * (instead of the widget being destroyed, as intended).
Packit b099d7
	   */
Packit b099d7
	  if(    !(focus_data->focus_item->core.being_destroyed)
Packit b099d7
	     &&  !IsTraversable( focus_data->focus_item, TRUE)    )
Packit b099d7
	    {
Packit b099d7
	      Widget new_focus = _XmTraverseAway( &(focus_data->trav_graph),
Packit b099d7
                                     focus_data->focus_item,
Packit b099d7
		                          (focus_data->active_tab_group
Packit b099d7
		                                  != focus_data->focus_item)) ;
Packit b099d7
	      if(    !new_focus    )
Packit b099d7
		{
Packit b099d7
		  new_focus = focus_data->focus_item ;
Packit b099d7
		}
Packit b099d7
        if(new_focus)
Packit b099d7
	      _XmMgrTraversal( new_focus, XmTRAVERSE_CURRENT) ;
Packit b099d7
	    }
Packit b099d7
	} 
Packit b099d7
    }
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
  return ;
Packit b099d7
}
Packit b099d7
Packit b099d7
static Widget
Packit b099d7
FindFirstManaged(
Packit b099d7
	Widget wid)
Packit b099d7
{
Packit b099d7
  if(    XtIsShell( wid)    )
Packit b099d7
    {
Packit b099d7
      unsigned i = 0 ;
Packit b099d7
Packit b099d7
      while(    i < ((CompositeWidget) wid)->composite.num_children    )
Packit b099d7
	{
Packit b099d7
	  if(    XtIsManaged( ((CompositeWidget) wid)
Packit b099d7
				                  ->composite.children[i])    )
Packit b099d7
	    {
Packit b099d7
	      return ((CompositeWidget) wid)->composite.children[i] ;
Packit b099d7
	    }
Packit b099d7
	  ++i ;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  return NULL ;
Packit b099d7
}
Packit b099d7
Packit b099d7
void
Packit b099d7
_XmNavigResize(
Packit b099d7
	Widget wid)
Packit b099d7
{
Packit b099d7
  /* This routine must be called by all composites with (potentially)
Packit b099d7
   * traversable children.  This is generally handled for all managers
Packit b099d7
   * in the resize wrapper routines.
Packit b099d7
   *
Packit b099d7
   * This routine makes sure that the focus widget is always in view,
Packit b099d7
   * either by invoking the XmNtraverseObscurredCallback mechansism
Packit b099d7
   * of Scrolled Window or by finding an alternative focus widget.
Packit b099d7
   */
Packit b099d7
  XmFocusData focus_data ;
Packit b099d7
Packit b099d7
  if(    XtIsRealized( wid)  &&  !XtIsShell( wid)
Packit b099d7
     &&  (focus_data = _XmGetFocusData( wid))    )
Packit b099d7
    {
Packit b099d7
      /* If the focus item is being destroyed, do nothing, since this
Packit b099d7
       * will be handled more appropriately by _XmNavigDestroy().
Packit b099d7
       */
Packit b099d7
      if(    (focus_data->focus_policy == XmEXPLICIT)
Packit b099d7
	 &&  (    !(focus_data->focus_item)
Packit b099d7
	      ||  !((focus_data->focus_item)->core.being_destroyed))    )
Packit b099d7
	{
Packit b099d7
	  if(    !(focus_data->focus_item)    )
Packit b099d7
	    {
Packit b099d7
	      /* Hierarchy has no focus widget; re-initialize/clear the
Packit b099d7
	       * focus, but only if the parent is a managed shell (to
Packit b099d7
	       * avoid premature initialization during XtRealizeWidget).
Packit b099d7
	       */
Packit b099d7
	      Widget parent = XtParent( wid) ;
Packit b099d7
	      Widget firstManaged ;
Packit b099d7
Packit b099d7
	      if(    parent && XtIsShell( parent)
Packit b099d7
		 &&  (firstManaged = FindFirstManaged( parent))    )
Packit b099d7
		{
Packit b099d7
		  /* Set bootstrap trigger for hierarchy that
Packit b099d7
		   * has no current focus.
Packit b099d7
		   */
Packit b099d7
		  XtSetKeyboardFocus( wid, firstManaged) ;
Packit b099d7
		}
Packit b099d7
	    }
Packit b099d7
	  else
Packit b099d7
	    {
Packit b099d7
	      if(    !IsTraversable( focus_data->focus_item, TRUE)    )
Packit b099d7
		{
Packit b099d7
		  /* Widget is not traversable, either because it is not
Packit b099d7
		   * viewable or some other reason.  Test again, this
Packit b099d7
		   * time allowing for obscured traversal.
Packit b099d7
		   *
Packit b099d7
		   * If it is not traversable regardless of the
Packit b099d7
		   * XmNtraverseObscuredCallback, or traversal to the
Packit b099d7
		   * obscured widget fails for some other reason, traverse
Packit b099d7
		   * away from the non-traversable widget.
Packit b099d7
		   */
Packit b099d7
		  if(    !IsTraversable( focus_data->focus_item, FALSE)
Packit b099d7
		     ||  !_XmMgrTraversal( focus_data->focus_item,
Packit b099d7
			                          XmTRAVERSE_CURRENT)    )
Packit b099d7
		    {
Packit b099d7
		      Widget new_focus = _XmTraverseAway(
Packit b099d7
			     &(focus_data->trav_graph), focus_data->focus_item,
Packit b099d7
                                (focus_data->active_tab_group
Packit b099d7
				                  != focus_data->focus_item)) ;
Packit b099d7
		      if(    !new_focus    )
Packit b099d7
			{
Packit b099d7
			  new_focus = focus_data->focus_item ;
Packit b099d7
			}
Packit b099d7
            if(new_focus)
Packit b099d7
		      _XmMgrTraversal( new_focus, XmTRAVERSE_CURRENT) ;
Packit b099d7
		    }
Packit b099d7
		}
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
}
Packit b099d7
Packit b099d7
void 
Packit b099d7
_XmValidateFocus(
Packit b099d7
        Widget wid )
Packit b099d7
{
Packit b099d7
  XmFocusData focus_data = _XmGetFocusData( wid) ;
Packit b099d7
Packit b099d7
  if(    focus_data
Packit b099d7
     &&  (focus_data->focus_policy == XmEXPLICIT)
Packit b099d7
     &&  (focus_data->focus_item != NULL)
Packit b099d7
     &&  !IsTraversable( focus_data->focus_item, TRUE)    )
Packit b099d7
    {
Packit b099d7
      Widget new_focus = _XmTraverseAway( &(focus_data->trav_graph),
Packit b099d7
		                 focus_data->focus_item,
Packit b099d7
                    (focus_data->active_tab_group != focus_data->focus_item)) ;
Packit b099d7
      if(    !new_focus    )
Packit b099d7
	{
Packit b099d7
	  new_focus = wid ;
Packit b099d7
	}
Packit b099d7
      _XmMgrTraversal( new_focus, XmTRAVERSE_CURRENT) ;
Packit b099d7
    }
Packit b099d7
}
Packit b099d7
Packit b099d7
void 
Packit b099d7
_XmNavigDestroy(
Packit b099d7
        Widget wid )
Packit b099d7
{   
Packit b099d7
  /* This routine is used to keep the traversal data up-to-date with
Packit b099d7
   * regards to widgets which are being destroyed.  It must be called
Packit b099d7
   * by all composites that might have traversable children.  The
Packit b099d7
   * DeleteChild method for Manager calls this routine, so its
Packit b099d7
   * subclasses can explicitly chain to its superclasses DeleteChild
Packit b099d7
   * method or call this routine directly.
Packit b099d7
   *
Packit b099d7
   * In addition to finding a new focus widget if it is being
Packit b099d7
   * destroyed, this routine must make sure that there are no
Packit b099d7
   * stale pointers to the widget being destroyed in any of its
Packit b099d7
   * data structures.
Packit b099d7
   */
Packit b099d7
  XmFocusData focusData = _XmGetFocusData( wid) ;
Packit b099d7
Packit b099d7
  if(    focusData    )
Packit b099d7
    {
Packit b099d7
      XmTravGraph trav_list = &(focusData->trav_graph) ;
Packit b099d7
      XmNavigationType navType = _XmGetNavigationType( wid) ;
Packit b099d7
Packit b099d7
      if(    wid == focusData->first_focus    )
Packit b099d7
	{
Packit b099d7
	  focusData->first_focus = NULL ;
Packit b099d7
	}
Packit b099d7
      if(    navType == XmEXCLUSIVE_TAB_GROUP    )
Packit b099d7
	{
Packit b099d7
	  --(trav_list->exclusive) ;
Packit b099d7
	  _XmTabListDelete( trav_list, wid) ;
Packit b099d7
	}
Packit b099d7
      else
Packit b099d7
	{
Packit b099d7
	  if(    navType == XmSTICKY_TAB_GROUP    )
Packit b099d7
	    {
Packit b099d7
	      _XmTabListDelete( trav_list, wid) ;
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
      if(    focusData->focus_item == wid    )
Packit b099d7
	{
Packit b099d7
	  /* The focus widget for this hierarhcy is being destroyed.
Packit b099d7
	   * Traverse away if in explicit mode, or just clear the
Packit b099d7
	   * focus item field.
Packit b099d7
	   */
Packit b099d7
	  Widget new_focus ;
Packit b099d7
Packit b099d7
	  if(    (focusData->focus_policy != XmEXPLICIT)
Packit b099d7
	     ||  (    !(new_focus = _XmTraverseAway( trav_list,
Packit b099d7
				       focusData->focus_item,
Packit b099d7
                                         (focusData->active_tab_group != wid)))
Packit b099d7
		  &&  !(new_focus = _XmFindTopMostShell( wid)))
Packit b099d7
	     ||  !_XmMgrTraversal( new_focus, XmTRAVERSE_CURRENT)    )
Packit b099d7
	    {
Packit b099d7
	      focusData->focus_item = NULL ;
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
      if(    focusData->trav_graph.num_entries    )
Packit b099d7
	{
Packit b099d7
	  _XmTravGraphRemove( trav_list, wid) ;
Packit b099d7
	}
Packit b099d7
      if(    focusData->active_tab_group == wid    )
Packit b099d7
	{
Packit b099d7
	  focusData->active_tab_group = NULL ;
Packit b099d7
	}
Packit b099d7
      if(    focusData->old_focus_item == wid    )
Packit b099d7
	{
Packit b099d7
	  focusData->old_focus_item = NULL ;
Packit b099d7
	}
Packit b099d7
      if(    focusData->pointer_item == wid    )
Packit b099d7
	{
Packit b099d7
	  focusData->pointer_item = NULL ;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  return ;
Packit b099d7
}
Packit b099d7

Packit b099d7
static Boolean
Packit b099d7
CallFocusMoved(Widget		    old,
Packit b099d7
	       Widget		    new_wid,
Packit b099d7
	       XEvent		    *event,
Packit b099d7
	       XmTraversalDirection direction)
Packit b099d7
{
Packit b099d7
  Widget w ;
Packit b099d7
  Widget topShell ;
Packit b099d7
  XtCallbackList callbacks ;
Packit b099d7
  Boolean contin = TRUE ;
Packit b099d7
  
Packit b099d7
  if (old) 
Packit b099d7
    w = old;
Packit b099d7
  else /* if (new_wid) -- if there's no w assignment we're in big trouble! */
Packit b099d7
    w = new_wid;
Packit b099d7
  
Packit b099d7
  topShell 	= (Widget) _XmFindTopMostShell(w);
Packit b099d7
  
Packit b099d7
  /*
Packit b099d7
   * make sure it's a shell that has a vendorExt object
Packit b099d7
   */
Packit b099d7
  if (XmIsVendorShell(topShell))
Packit b099d7
    {
Packit b099d7
      XmWidgetExtData		extData;
Packit b099d7
      XmVendorShellExtObject	vendorExt;
Packit b099d7
      
Packit b099d7
      extData	= _XmGetWidgetExtData(topShell, XmSHELL_EXTENSION);
Packit b099d7
      if(extData==NULL) return (contin);
Packit b099d7
      
Packit b099d7
      if ((vendorExt = (XmVendorShellExtObject) extData->widget) != NULL)
Packit b099d7
	{
Packit b099d7
	  if ((callbacks = vendorExt->vendor.focus_moved_callback) != NULL)
Packit b099d7
	    {
Packit b099d7
	      XmFocusMovedCallbackStruct	callData;
Packit b099d7
	      
Packit b099d7
	      callData.reason		= XmCR_FOCUS_MOVED;
Packit b099d7
	      callData.event		= event;
Packit b099d7
	      callData.cont		= True;
Packit b099d7
	      callData.old_focus	= old;
Packit b099d7
	      callData.new_focus	= new_wid;
Packit b099d7
	      callData.focus_policy	= vendorExt->vendor.focus_policy;
Packit b099d7
	      callData.direction	= direction;
Packit b099d7
	      
Packit b099d7
	      _XmCallCallbackList((Widget) vendorExt, callbacks,
Packit b099d7
				  (XtPointer) &callData);
Packit b099d7
	      contin = callData.cont ;
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  return( contin) ;
Packit b099d7
}
Packit b099d7

Packit b099d7
Boolean
Packit b099d7
_XmCallFocusMoved(
Packit b099d7
        Widget old,
Packit b099d7
        Widget new_wid,
Packit b099d7
        XEvent *event )
Packit b099d7
{
Packit b099d7
  return CallFocusMoved(old, new_wid, event, XmTRAVERSE_CURRENT);
Packit b099d7
}
Packit b099d7
Packit b099d7
Boolean 
Packit b099d7
_XmMgrTraversal(
Packit b099d7
        Widget wid,
Packit b099d7
        XmTraversalDirection direction)
Packit b099d7
{
Packit b099d7
  /* This routine is the workhorse for all traversal activities. */
Packit b099d7
  Widget top_shell ;
Packit b099d7
  Widget old_focus ;
Packit b099d7
  Widget new_focus ;
Packit b099d7
  Widget new_active_tab ;
Packit b099d7
  XmFocusData focus_data;
Packit b099d7
  XmTravGraph trav_list ;
Packit b099d7
  Boolean rtnVal = FALSE ;
Packit b099d7
  XmTraversalDirection local_dir;
Packit b099d7
  XmDisplay dd = (XmDisplay)XmGetXmDisplay(XtDisplay(wid));
Packit b099d7
Packit b099d7
#define traversal_in_progress \
Packit b099d7
   ((XmDisplayInfo *)(dd->display.displayInfo))->traversal_in_progress
Packit b099d7
Packit b099d7
  if(    traversal_in_progress
Packit b099d7
     ||  !(top_shell = _XmFindTopMostShell( wid))
Packit b099d7
     ||  top_shell->core.being_destroyed
Packit b099d7
     ||  !(focus_data = _XmGetFocusData( wid))
Packit b099d7
     ||  (focus_data->focus_policy != XmEXPLICIT)    )
Packit b099d7
    {
Packit b099d7
      return FALSE ;
Packit b099d7
    }
Packit b099d7
  traversal_in_progress = TRUE ;
Packit b099d7
Packit b099d7
  /* Recursive traversal calls can sometimes be generated during
Packit b099d7
   * the handling of focus events and associated callbacks.
Packit b099d7
   * In this version of Motif, recursive calls always fail.
Packit b099d7
   *
Packit b099d7
   * Future enhancements could include the addition of a queue
Packit b099d7
   * for recursive calls; these calls would then be serviced on
Packit b099d7
   * a FIFO basis following the completion of the initial traversal
Packit b099d7
   * processing.  Sequential FIFO processing is essential for
Packit b099d7
   * providing a consistent and predicable environment for
Packit b099d7
   * focus change callbacks and event processing.
Packit b099d7
   */
Packit b099d7
  trav_list = &(focus_data->trav_graph) ;
Packit b099d7
  old_focus = focus_data->focus_item ;
Packit b099d7
Packit b099d7
  if(    (old_focus == NULL)
Packit b099d7
     &&  (wid == top_shell)
Packit b099d7
     &&  focus_data->first_focus
Packit b099d7
     &&  IsTraversable( focus_data->first_focus, TRUE)    )
Packit b099d7
    {
Packit b099d7
      new_focus = focus_data->first_focus ;
Packit b099d7
Packit b099d7
      if (direction == XmTRAVERSE_GLOBALLY_FORWARD)
Packit b099d7
	local_dir = XmTRAVERSE_NEXT_TAB_GROUP;
Packit b099d7
      else if (direction == XmTRAVERSE_GLOBALLY_BACKWARD)
Packit b099d7
	local_dir = XmTRAVERSE_PREV_TAB_GROUP;
Packit b099d7
      else
Packit b099d7
	local_dir = direction;
Packit b099d7
    }
Packit b099d7
  else
Packit b099d7
    {
Packit b099d7
      new_focus = _XmTraverse(trav_list, direction, &local_dir, wid) ;
Packit b099d7
    }
Packit b099d7
Packit b099d7
  new_focus = RedirectTraversal(old_focus, new_focus, 
Packit b099d7
				focus_data->focus_policy, local_dir, 0);
Packit b099d7
Packit b099d7
  if(    new_focus
Packit b099d7
     &&  (new_focus == old_focus)
Packit b099d7
     &&  focus_data->old_focus_item    )
Packit b099d7
    {
Packit b099d7
      /* When traversal does not cause the focus to change
Packit b099d7
       * to a different widget, focus-change events should
Packit b099d7
       * not be generated.  The old_focus_item will be NULL
Packit b099d7
       * when the focus is moving into this shell hierarchy
Packit b099d7
       * from a different shell; in this case, focus-in
Packit b099d7
       * events should be generated below.
Packit b099d7
       */
Packit b099d7
      rtnVal = TRUE ;
Packit b099d7
    }
Packit b099d7
  else if(    new_focus
Packit b099d7
	  &&  (new_active_tab = XmGetTabGroup( new_focus))
Packit b099d7
	  &&  CallFocusMoved(old_focus, new_focus, NULL, local_dir)
Packit b099d7
	  &&  CallTraverseObsured(new_focus, local_dir))
Packit b099d7
    {
Packit b099d7
      /* Set the keyboard focus in two steps; first to None, then
Packit b099d7
       * to the new focus widget.  This will cause appropriate
Packit b099d7
       * focus-in and focus-out events to be generated, even if
Packit b099d7
       * the focus change is between two gadgets.
Packit b099d7
       *
Packit b099d7
       * Note that XtSetKeyboardFocus() generates focus change
Packit b099d7
       * events "in-line", so focus data and manager active_child
Packit b099d7
       * fields are not updated until after the focus-out events have
Packit b099d7
       * been generated and dispatched to the current focus item.
Packit b099d7
       *
Packit b099d7
       * The FocusResetFlag is used to tell event actions procs to
Packit b099d7
       * ignore any focus-in event that might be generated by the
Packit b099d7
       * window manager (which won't like the fact that there the
Packit b099d7
       * focus is now going to point to nobody).
Packit b099d7
       */
Packit b099d7
      _XmSetFocusFlag( top_shell, XmFOCUS_RESET, TRUE) ;
Packit b099d7
      XtSetKeyboardFocus( top_shell, None) ;
Packit b099d7
      _XmSetFocusFlag( top_shell, XmFOCUS_RESET, FALSE) ;
Packit b099d7
Packit b099d7
      _XmClearFocusPath( old_focus) ;
Packit b099d7
Packit b099d7
      focus_data->active_tab_group = new_active_tab ;
Packit b099d7
Packit b099d7
      if(    (new_active_tab != new_focus)
Packit b099d7
	 &&  XmIsManager( new_active_tab)    )
Packit b099d7
	{
Packit b099d7
	  XmManagerWidget manager = (XmManagerWidget) new_active_tab;
Packit b099d7
	  manager->manager.active_child = new_focus;
Packit b099d7
	}
Packit b099d7
      if(    (new_active_tab != XtParent( new_focus))  /* Set above. */
Packit b099d7
	 &&  XmIsManager( XtParent( new_focus))    )
Packit b099d7
	{
Packit b099d7
	  XmManagerWidget manager = (XmManagerWidget) XtParent(new_focus);
Packit b099d7
	  manager->manager.active_child = new_focus ;
Packit b099d7
	}
Packit b099d7
      focus_data->focus_item = new_focus ;
Packit b099d7
      focus_data->old_focus_item = old_focus ? old_focus : new_focus ;
Packit b099d7
Packit b099d7
      /* Setting the focus data and manager active_child fields enables
Packit b099d7
       * focus-in events to be propagated to the new focus widget.
Packit b099d7
       */
Packit b099d7
      XtSetKeyboardFocus( top_shell, new_focus) ;
Packit b099d7
Packit b099d7
      rtnVal = TRUE ;
Packit b099d7
    }
Packit b099d7
  else
Packit b099d7
    {
Packit b099d7
      /* Have failed to traverse to a new widget focus widget.
Packit b099d7
       * If the current focus widget is no longer traversable,
Packit b099d7
       * then reset focus data to its bootstrap state.
Packit b099d7
       */
Packit b099d7
      if(    !old_focus
Packit b099d7
	 ||  !IsTraversable( old_focus, TRUE)    )
Packit b099d7
	{
Packit b099d7
	  Widget firstManaged = FindFirstManaged( top_shell) ;
Packit b099d7
Packit b099d7
	  _XmSetFocusFlag( top_shell, XmFOCUS_RESET, TRUE) ;
Packit b099d7
	  XtSetKeyboardFocus( top_shell, firstManaged) ;
Packit b099d7
	  _XmSetFocusFlag( top_shell, XmFOCUS_RESET, FALSE) ;
Packit b099d7
Packit b099d7
	  _XmClearFocusPath( old_focus) ;
Packit b099d7
	  _XmFreeTravGraph( trav_list) ;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
Packit b099d7
  if(    trav_list->num_entries
Packit b099d7
     &&  (focus_data->focalPoint == XmUnrelated)
Packit b099d7
     &&  (    XmIsVendorShell( top_shell)
Packit b099d7
	 ||  !XmeFocusIsInShell( top_shell))    )
Packit b099d7
    {
Packit b099d7
      /* Free the graversal graph whenever the focus is out of this
Packit b099d7
       * shell hierarchy, so memory use is limited to one traversal
Packit b099d7
       * graph per display.  Since VendorShell has a handler which
Packit b099d7
       * tracks the input focus, all we need to do is look at the
Packit b099d7
       * focusData field.  For MenuShell and others, we need to go
Packit b099d7
       * through the X server to find out where the focus is.
Packit b099d7
       *
Packit b099d7
       * Note the logic of the above conditional; VendorShell is the
Packit b099d7
       * only shell class that maintains the focalPoint field of the
Packit b099d7
       * focus data.  So, if its a VendorShell and focalPoint says
Packit b099d7
       * "unrelated", we have the answer; any other shell and we need
Packit b099d7
       * to call the generic focus test routine.
Packit b099d7
       */
Packit b099d7
      _XmFreeTravGraph( trav_list) ;
Packit b099d7
    }
Packit b099d7
  traversal_in_progress = FALSE ;
Packit b099d7
  return rtnVal ;
Packit b099d7
}
Packit b099d7

Packit b099d7
static Boolean
Packit b099d7
CallTraverseObsured(
Packit b099d7
        Widget new_focus,
Packit b099d7
        XmTraversalDirection dir)
Packit b099d7
{   
Packit b099d7
  Widget prev;
Packit b099d7
  Widget ancestor = new_focus;
Packit b099d7
  XRectangle focus_rect;	/* Area we're trying to make visible. */
Packit b099d7
  XRectangle clip_rect;		/* Area a given ancestor obscures. */
Packit b099d7
  XRectangle view_rect;		/* Temporary intersection of the two. */
Packit b099d7
  XmTraverseObscuredCallbackStruct call_data;
Packit b099d7
  
Packit b099d7
  call_data.reason = XmCR_OBSCURED_TRAVERSAL;
Packit b099d7
  call_data.event = NULL;
Packit b099d7
  call_data.traversal_destination = new_focus;
Packit b099d7
  call_data.direction = dir;
Packit b099d7
  
Packit b099d7
  _XmSetRect(&focus_rect, new_focus);
Packit b099d7
Packit b099d7
  /* Look for ancestors that clip this window. */
Packit b099d7
  for (prev = ancestor;
Packit b099d7
       ((ancestor = XtParent(ancestor)) != NULL) && !XtIsShell(ancestor);
Packit b099d7
       prev = ancestor)
Packit b099d7
    {
Packit b099d7
      /* CR 9705: Special case overlapping work windows. */
Packit b099d7
      if (!_XmIsScrollableClipWidget(ancestor, False, &clip_rect))
Packit b099d7
	_XmSetRect(&clip_rect, ancestor);
Packit b099d7
Packit b099d7
      if (!_XmIntersectionOf(&focus_rect, &clip_rect, &view_rect) ||
Packit b099d7
	  (view_rect.width != focus_rect.width) ||
Packit b099d7
	  (view_rect.height != focus_rect.height))
Packit b099d7
	{
Packit b099d7
	  /* This ancestor clips somebody. */
Packit b099d7
	  Widget sw = _XmIsScrollableClipWidget(prev, True, &focus_rect);
Packit b099d7
	  if (sw != NULL)
Packit b099d7
	    {   
Packit b099d7
	      XtCallbackList callbacks = ((XmScrolledWindowWidget) sw)
Packit b099d7
		->swindow.traverseObscuredCallback;
Packit b099d7
	      XtCallCallbackList(sw, callbacks, (XtPointer) &call_data);
Packit b099d7
Packit b099d7
	      ancestor = sw;
Packit b099d7
	    } 
Packit b099d7
	  else
Packit b099d7
	    {
Packit b099d7
	      _XmIntersectRect(&focus_rect, ancestor, &focus_rect);
Packit b099d7
	    } 
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
Packit b099d7
  return IsTraversable( new_focus, TRUE);
Packit b099d7
}
Packit b099d7

Packit b099d7
void 
Packit b099d7
_XmClearFocusPath(
Packit b099d7
        Widget wid )
Packit b099d7
{
Packit b099d7
  /* This routine should be called whenever the focus of a shell
Packit b099d7
   * hierarchy needs to be reset to the bootstrap condition.
Packit b099d7
   *
Packit b099d7
   * This routine clears the active_child field of all manager
Packit b099d7
   * widget ancestors of the widget argument, and clears other
Packit b099d7
   * focus widget fields of the focus data record.  The clearing
Packit b099d7
   * of the old_focus_item field indicates to the traversal code
Packit b099d7
   * that the focus is not in this shell hierarchy.
Packit b099d7
   */
Packit b099d7
  XmFocusData focus_data ;
Packit b099d7
Packit b099d7
  while(    wid  &&  !XtIsShell( wid)    )
Packit b099d7
    {
Packit b099d7
      if(    XmIsManager( wid)    )
Packit b099d7
	{
Packit b099d7
	  ((XmManagerWidget) wid)->manager.active_child = NULL ;
Packit b099d7
	}
Packit b099d7
      wid = XtParent( wid) ;
Packit b099d7
    }
Packit b099d7
  if(    (focus_data = _XmGetFocusData( wid)) != NULL    )
Packit b099d7
    {
Packit b099d7
      focus_data->focus_item = NULL ;
Packit b099d7
      focus_data->old_focus_item = NULL ;
Packit b099d7
      focus_data->active_tab_group = NULL ;
Packit b099d7
    }
Packit b099d7
}
Packit b099d7
Packit b099d7
Boolean 
Packit b099d7
_XmFocusIsHere(
Packit b099d7
        Widget w )
Packit b099d7
{
Packit b099d7
    XmFocusData focus_data;
Packit b099d7
    Widget	item;
Packit b099d7
Packit b099d7
    if ((focus_data = _XmGetFocusData( w)) &&
Packit b099d7
	(item = focus_data->focus_item))
Packit b099d7
      {
Packit b099d7
	  for (; !XtIsShell(item); item = XtParent(item))
Packit b099d7
	    if (item == w)
Packit b099d7
	      return True;
Packit b099d7
      }
Packit b099d7
    return(False);
Packit b099d7
}
Packit b099d7
Packit b099d7
unsigned char 
Packit b099d7
_XmGetFocusPolicy(
Packit b099d7
        Widget w )
Packit b099d7
{   
Packit b099d7
  Widget topmost_shell ;
Packit b099d7
  
Packit b099d7
  /* Find the topmost shell widget
Packit b099d7
   */
Packit b099d7
  topmost_shell = _XmFindTopMostShell( w) ;
Packit b099d7
  
Packit b099d7
  if(    XtIsVendorShell( topmost_shell)    )
Packit b099d7
    {
Packit b099d7
      XmWidgetExtData xwed = _XmGetWidgetExtData(topmost_shell, XmSHELL_EXTENSION);
Packit b099d7
Packit b099d7
      if(xwed == NULL) return(XmPOINTER);
Packit b099d7
      
Packit b099d7
      return (((XmVendorShellExtObject)
Packit b099d7
	       (xwed)->widget)
Packit b099d7
	      ->vendor.focus_policy) ;
Packit b099d7
    } 
Packit b099d7
  else
Packit b099d7
    {   
Packit b099d7
      if(    XmIsMenuShell( topmost_shell)    )
Packit b099d7
	{   
Packit b099d7
	  return( ((XmMenuShellWidget) topmost_shell)->menu_shell.focus_policy);
Packit b099d7
	} 
Packit b099d7
    } 
Packit b099d7
  return( XmPOINTER) ;
Packit b099d7
}
Packit b099d7
Packit b099d7
Widget 
Packit b099d7
_XmFindTopMostShell(
Packit b099d7
        Widget w )
Packit b099d7
{   
Packit b099d7
  while(    w && !XtIsShell( w)    )
Packit b099d7
    {   
Packit b099d7
      w = XtParent( w) ;
Packit b099d7
    } 
Packit b099d7
  return( w) ;
Packit b099d7
}
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
void 
Packit b099d7
_XmFocusModelChanged(
Packit b099d7
        Widget wid,
Packit b099d7
        XtPointer client_data,	/* unused */
Packit b099d7
        XtPointer call_data )
Packit b099d7
{
Packit b099d7
  /* Invoked by the VendorShell widget, when the focus_policy changes.
Packit b099d7
   * Registered as a callback by both the Manager and Primitive classes,
Packit b099d7
   * when the parent is a VendorShell widget.
Packit b099d7
   */
Packit b099d7
  unsigned char new_focus_policy = (unsigned char)(unsigned long) call_data ;
Packit b099d7
  Widget shell = _XmFindTopMostShell( wid) ;
Packit b099d7
  XmFocusData focus_data = _XmGetFocusData( shell) ;
Packit b099d7
Packit b099d7
  if(    focus_data    )
Packit b099d7
    {
Packit b099d7
      if(    new_focus_policy == XmEXPLICIT    )
Packit b099d7
	{
Packit b099d7
	  Widget new_item = focus_data->pointer_item ;
Packit b099d7
Packit b099d7
	  if(    new_item != NULL    )
Packit b099d7
	    {
Packit b099d7
	      if(    XmIsManager( new_item)
Packit b099d7
		 &&  (((XmManagerWidget) new_item)
Packit b099d7
		                     ->manager.highlighted_widget != NULL)    )
Packit b099d7
		{
Packit b099d7
		  new_item = ((XmManagerWidget) new_item)
Packit b099d7
		                                 ->manager.highlighted_widget ;
Packit b099d7
		}
Packit b099d7
	      _XmWidgetFocusChange( new_item, XmLEAVE) ;
Packit b099d7
	    }
Packit b099d7
	  if(    (new_item == NULL)
Packit b099d7
	     ||  !_XmMgrTraversal( new_item, XmTRAVERSE_CURRENT)    )
Packit b099d7
	    {
Packit b099d7
	      _XmMgrTraversal( shell, XmTRAVERSE_CURRENT) ;
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
      else /* new_focus_policy == XmPOINTER */
Packit b099d7
	{
Packit b099d7
	  if(    focus_data->focus_item    )
Packit b099d7
	    {
Packit b099d7
	      Widget firstManaged = FindFirstManaged( shell) ;
Packit b099d7
Packit b099d7
	      _XmWidgetFocusChange( focus_data->focus_item, XmFOCUS_OUT) ;
Packit b099d7
Packit b099d7
	      _XmClearFocusPath( focus_data->focus_item) ;
Packit b099d7
	      _XmSetFocusFlag( shell, XmFOCUS_RESET, TRUE) ;
Packit b099d7
	      XtSetKeyboardFocus( shell, firstManaged) ;
Packit b099d7
	      _XmSetFocusFlag( shell, XmFOCUS_RESET, FALSE) ;
Packit b099d7
	    }
Packit b099d7
	  _XmFreeTravGraph( &(focus_data->trav_graph)) ;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
XmFocusData
Packit b099d7
_XmGetFocusData (Widget wid)
Packit b099d7
{
Packit b099d7
   /* This function returns a pointer to the focus data associated with the
Packit b099d7
    * topmost shell.  This allows us to treat the location opaquely.
Packit b099d7
    */
Packit b099d7
   while (wid && !XtIsShell (wid))
Packit b099d7
   {
Packit b099d7
      wid = XtParent (wid);
Packit b099d7
   }
Packit b099d7
   if (wid && !(wid->core.being_destroyed))
Packit b099d7
   {
Packit b099d7
      if (XmIsVendorShell (wid))
Packit b099d7
      {
Packit b099d7
         XmWidgetExtData xwed = _XmGetWidgetExtData (wid, XmSHELL_EXTENSION);
Packit b099d7
         XmVendorShellExtObject vse;
Packit b099d7
Packit b099d7
         if (xwed == NULL)
Packit b099d7
            return NULL;
Packit b099d7
         vse = (XmVendorShellExtObject) xwed->widget;
Packit b099d7
         if (vse && vse->vendor.focus_data)
Packit b099d7
         {
Packit b099d7
            vse->vendor.focus_data->focus_policy = vse->vendor.focus_policy;
Packit b099d7
            return vse->vendor.focus_data;
Packit b099d7
         }
Packit b099d7
      }
Packit b099d7
      else
Packit b099d7
      {
Packit b099d7
         if (XmIsMenuShell (wid)
Packit b099d7
             && ((XmMenuShellWidget) wid)->menu_shell.focus_data)
Packit b099d7
         {
Packit b099d7
            ((XmMenuShellWidget) wid)->menu_shell.focus_data->
Packit b099d7
               focus_policy =
Packit b099d7
               ((XmMenuShellWidget) wid)->menu_shell.focus_policy;
Packit b099d7
            return ((XmMenuShellWidget) wid)->menu_shell.focus_data;
Packit b099d7
         }
Packit b099d7
      }
Packit b099d7
   }
Packit b099d7
   return NULL;
Packit b099d7
}
Packit b099d7
Packit b099d7

Packit b099d7
Boolean 
Packit b099d7
_XmComputeVisibilityRect(Widget      w,
Packit b099d7
			 XRectangle *rectPtr,
Packit b099d7
			 Boolean     include_initial_border,
Packit b099d7
			 Boolean     allow_scrolling)
Packit b099d7
{   
Packit b099d7
  /* This function will generate a rectangle describing the portion of 
Packit b099d7
   * the specified widget which is not clipped by any of its ancestors.
Packit b099d7
   * It also verifies that the ancestors are both managed and
Packit b099d7
   * mapped_when_managed.
Packit b099d7
   *
Packit b099d7
   * It will return TRUE if the rectangle returned in rectPtr has a
Packit b099d7
   * non-zero area; it will return FALSE if the widget is not visible.
Packit b099d7
   *
Packit b099d7
   * If allow_scrolling is set and w is the work area child of an
Packit b099d7
   * automatic scrolled window with a non-null XmNtraverseObscuredCallback,
Packit b099d7
   * then the clip window is used as the initial rectangle for w. 
Packit b099d7
   */
Packit b099d7
  Widget sw;
Packit b099d7
  
Packit b099d7
  if (!_XmIsViewable(w))
Packit b099d7
    {   
Packit b099d7
      _XmClearRect(rectPtr);
Packit b099d7
      return False;
Packit b099d7
    }
Packit b099d7
Packit b099d7
  if (allow_scrolling && w && XtParent(w) &&
Packit b099d7
      ((sw = _XmIsScrollableClipWidget(w, True, rectPtr)) != NULL))
Packit b099d7
    {   
Packit b099d7
      w = sw;
Packit b099d7
      
Packit b099d7
      if (!_XmIsViewable(w))
Packit b099d7
        {   
Packit b099d7
	  _XmClearRect(rectPtr);
Packit b099d7
	  return False;
Packit b099d7
	}
Packit b099d7
    } 
Packit b099d7
  else
Packit b099d7
    {
Packit b099d7
      _XmSetRect(rectPtr, w);
Packit b099d7
    } 
Packit b099d7
  
Packit b099d7
  if (include_initial_border)
Packit b099d7
    {
Packit b099d7
      int border = XtBorderWidth(w);
Packit b099d7
Packit b099d7
      rectPtr->x -= border;
Packit b099d7
      rectPtr->y -= border;
Packit b099d7
      rectPtr->width += 2 * border;
Packit b099d7
      rectPtr->height += 2 * border;
Packit b099d7
    }
Packit b099d7
Packit b099d7
  /* Process all widgets, excluding the shell widget. */
Packit b099d7
  while (((w = XtParent(w)) != NULL) && !XtIsShell(w))
Packit b099d7
    {   
Packit b099d7
      if (!_XmIsViewable(w) || !_XmIntersectRect(rectPtr, w, rectPtr))
Packit b099d7
        {   
Packit b099d7
	  _XmClearRect(rectPtr);
Packit b099d7
	  return False;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
Packit b099d7
  return True;
Packit b099d7
}
Packit b099d7

Packit b099d7
Boolean 
Packit b099d7
_XmGetPointVisibility(Widget w,
Packit b099d7
		      int    root_x,
Packit b099d7
		      int    root_y)
Packit b099d7
{
Packit b099d7
  /* Compute whether a point is really visible inside a widget. */
Packit b099d7
  XRectangle rect;
Packit b099d7
Packit b099d7
  if (_XmComputeVisibilityRect(w, &rect, TRUE, FALSE))
Packit b099d7
    {
Packit b099d7
      return ((root_x >= rect.x) && 
Packit b099d7
	      (root_x <  rect.x + (int)rect.width) &&
Packit b099d7
	      (root_y >= rect.y) && 
Packit b099d7
	      (root_y <  rect.y + (int)rect.height));
Packit b099d7
    }
Packit b099d7
Packit b099d7
  return False;
Packit b099d7
}
Packit b099d7

Packit b099d7
void 
Packit b099d7
_XmSetRect(
Packit b099d7
        register XRectangle *rect,
Packit b099d7
        Widget w )
Packit b099d7
{
Packit b099d7
  /* Initialize the rectangle structure to the specified values.
Packit b099d7
   * The widget must be realized.
Packit b099d7
   */
Packit b099d7
   Position x, y;
Packit b099d7
Packit b099d7
   XtTranslateCoords(XtParent(w), w->core.x, w->core.y, &x, &y);
Packit b099d7
   rect->x = x + w->core.border_width;
Packit b099d7
   rect->y = y + w->core.border_width;
Packit b099d7
   rect->width = w->core.width;
Packit b099d7
   rect->height = w->core.height;
Packit b099d7
}
Packit b099d7
Packit b099d7
int 
Packit b099d7
_XmIntersectRect(
Packit b099d7
        register XRectangle *srcRectA,
Packit b099d7
        register Widget widget,
Packit b099d7
        register XRectangle *dstRect )
Packit b099d7
{
Packit b099d7
  /* Intersects the specified rectangle with the rectangle describing the
Packit b099d7
   * passed-in widget.  Returns True if they intersect, or False if they
Packit b099d7
   * do not.
Packit b099d7
   */
Packit b099d7
  XRectangle srcRectB;
Packit b099d7
Packit b099d7
  _XmSetRect(&srcRectB, widget);
Packit b099d7
  
Packit b099d7
  return( (int) _XmIntersectionOf( srcRectA, &srcRectB, dstRect)) ;
Packit b099d7
}
Packit b099d7
Packit b099d7
int 
Packit b099d7
_XmEmptyRect(
Packit b099d7
        register XRectangle *r )
Packit b099d7
{
Packit b099d7
   if (r->width <= 0 || r->height <= 0)
Packit b099d7
      return (TRUE);
Packit b099d7
Packit b099d7
   return (FALSE);
Packit b099d7
}
Packit b099d7
Packit b099d7
void 
Packit b099d7
_XmClearRect(
Packit b099d7
        register XRectangle *r )
Packit b099d7
{
Packit b099d7
   r->x = 0;
Packit b099d7
   r->y = 0;
Packit b099d7
   r->width = 0;
Packit b099d7
   r->height = 0;
Packit b099d7
}
Packit b099d7
Packit b099d7
Boolean
Packit b099d7
_XmIsNavigable( 
Packit b099d7
	Widget wid)
Packit b099d7
{
Packit b099d7
  XmNavigability nav = _XmGetNavigability( wid) ;
Packit b099d7
  if(    (nav != XmTAB_NAVIGABLE)
Packit b099d7
     &&  (nav != XmCONTROL_NAVIGABLE)    )
Packit b099d7
    {
Packit b099d7
      return FALSE ;
Packit b099d7
    }
Packit b099d7
  while(    (wid = XtParent( wid)) && !XtIsShell( wid)    )
Packit b099d7
    {
Packit b099d7
      if(    !_XmGetNavigability( wid)    )
Packit b099d7
	{
Packit b099d7
	  return FALSE ;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  return TRUE ;
Packit b099d7
}
Packit b099d7
Packit b099d7
void
Packit b099d7
_XmWidgetFocusChange(
Packit b099d7
        Widget wid,
Packit b099d7
        XmFocusChange change)
Packit b099d7
{   
Packit b099d7
  XmBaseClassExt *er ;
Packit b099d7
  
Packit b099d7
  if(    XtIsRectObj( wid)
Packit b099d7
     && !wid->core.being_destroyed    )
Packit b099d7
    {   
Packit b099d7
      if(    (er = _XmGetBaseClassExtPtr( XtClass( wid), XmQmotif))
Packit b099d7
	 && (*er)
Packit b099d7
	 && ((*er)->version >= XmBaseClassExtVersion)
Packit b099d7
	 && (*er)->focusChange    )
Packit b099d7
        {   
Packit b099d7
	  (*((*er)->focusChange))( wid, change) ;
Packit b099d7
	} 
Packit b099d7
      else
Packit b099d7
        {   /* From here on is compatibility code.
Packit b099d7
	     */
Packit b099d7
	  WidgetClass wc ;
Packit b099d7
	  
Packit b099d7
	  if(    XmIsPrimitive( wid)    )
Packit b099d7
            {   
Packit b099d7
	      wc = (WidgetClass) &xmPrimitiveClassRec ;
Packit b099d7
	    }
Packit b099d7
	  else if(    XmIsGadget( wid)     )
Packit b099d7
	    {   
Packit b099d7
	      wc = (WidgetClass) &xmGadgetClassRec ;
Packit b099d7
	    } 
Packit b099d7
	  else if(    XmIsManager( wid)    )
Packit b099d7
	    {   
Packit b099d7
	      wc = (WidgetClass) &xmManagerClassRec ;
Packit b099d7
	    } 
Packit b099d7
	  else
Packit b099d7
	    {
Packit b099d7
	      wc = NULL ;
Packit b099d7
	    } 
Packit b099d7
Packit b099d7
	  if(    wc
Packit b099d7
	     && (er = _XmGetBaseClassExtPtr( wc, XmQmotif))
Packit b099d7
	     && (*er)
Packit b099d7
	     && ((*er)->version >= XmBaseClassExtVersion)
Packit b099d7
	     && (*er)->focusChange    )
Packit b099d7
            {   
Packit b099d7
	      (*((*er)->focusChange))( wid, change) ;
Packit b099d7
	    } 
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  return ;
Packit b099d7
} 
Packit b099d7
Packit b099d7
Widget 
Packit b099d7
_XmNavigate(
Packit b099d7
        Widget wid,
Packit b099d7
        XmTraversalDirection direction )
Packit b099d7
{
Packit b099d7
  XmTraversalDirection local_dir;
Packit b099d7
  XmFocusData focus_data;
Packit b099d7
  Widget nav_wid = NULL ;
Packit b099d7
  Widget shell = _XmFindTopMostShell( wid) ;
Packit b099d7
Packit b099d7
  if(    (focus_data = _XmGetFocusData( shell))
Packit b099d7
     &&  (focus_data->focus_policy == XmEXPLICIT)    )
Packit b099d7
    {
Packit b099d7
      XmTravGraph trav_list = &(focus_data->trav_graph) ;
Packit b099d7
Packit b099d7
      nav_wid = _XmTraverse( trav_list, direction, &local_dir, wid) ;
Packit b099d7
Packit b099d7
      nav_wid = RedirectTraversal(focus_data->focus_item, nav_wid, 
Packit b099d7
				  focus_data->focus_policy, local_dir, 0);
Packit b099d7
Packit b099d7
      if(    trav_list->num_entries
Packit b099d7
	 &&  (focus_data->focalPoint == XmUnrelated)
Packit b099d7
	 &&  (    XmIsVendorShell( shell)
Packit b099d7
	      ||  !XmeFocusIsInShell( shell))    )
Packit b099d7
	{
Packit b099d7
	  _XmFreeTravGraph( trav_list) ;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  return nav_wid ;
Packit b099d7
}
Packit b099d7
Packit b099d7
void
Packit b099d7
_XmSetInitialOfTabGroup(
Packit b099d7
	Widget tab_group,
Packit b099d7
	Widget init_focus)
Packit b099d7
{
Packit b099d7
  XmFocusData focus_data ;
Packit b099d7
Packit b099d7
  if(    XmIsManager( tab_group)    )
Packit b099d7
    {
Packit b099d7
      ((XmManagerWidget) tab_group)->manager.initial_focus = init_focus ;
Packit b099d7
    }
Packit b099d7
  if(    (focus_data = _XmGetFocusData( tab_group))
Packit b099d7
     &&  focus_data->trav_graph.num_entries    )
Packit b099d7
    {
Packit b099d7
      _XmSetInitialOfTabGraph( &(focus_data->trav_graph),
Packit b099d7
			      tab_group, init_focus) ;
Packit b099d7
    }
Packit b099d7
}
Packit b099d7
Packit b099d7
static Boolean
Packit b099d7
IsTraversable( 
Packit b099d7
        Widget wid,
Packit b099d7
	Boolean require_in_view)
Packit b099d7
{   
Packit b099d7
  if(    wid
Packit b099d7
     &&  _XmIsNavigable( wid)    )
Packit b099d7
    {
Packit b099d7
      if(    require_in_view    )
Packit b099d7
	{
Packit b099d7
	  return (XmGetVisibility( wid) != XmVISIBILITY_FULLY_OBSCURED) ;
Packit b099d7
	}
Packit b099d7
      else
Packit b099d7
	{
Packit b099d7
	  /* _XmGetEffectiveView() returns the view port in
Packit b099d7
	   * which the widget could be viewed through the use
Packit b099d7
	   * of the XmNtraverseObscuredCallback of ScrolledWindow.
Packit b099d7
	   */
Packit b099d7
	  XRectangle visRect ;
Packit b099d7
Packit b099d7
	  return _XmGetEffectiveView( wid, &visRect) ;
Packit b099d7
	}
Packit b099d7
    } 
Packit b099d7
  return FALSE ;
Packit b099d7
} 
Packit b099d7
Packit b099d7
void
Packit b099d7
_XmResetTravGraph(
Packit b099d7
	Widget wid)
Packit b099d7
{
Packit b099d7
  XmFocusData focus_data = _XmGetFocusData( wid) ;
Packit b099d7
Packit b099d7
  if(    focus_data  &&  focus_data->trav_graph.num_entries    )
Packit b099d7
    {
Packit b099d7
      _XmFreeTravGraph( &(focus_data->trav_graph)) ;
Packit b099d7
    }
Packit b099d7
}
Packit b099d7
Packit b099d7
Boolean
Packit b099d7
XmeFocusIsInShell(
Packit b099d7
        Widget wid)
Packit b099d7
{
Packit b099d7
  Window focus ;
Packit b099d7
  Widget focus_wid ;
Packit b099d7
  Widget shell_of_wid = _XmFindTopMostShell( wid) ;
Packit b099d7
  XmFocusData focus_data ;
Packit b099d7
  int revert ;
Packit b099d7
  _XmWidgetToAppContext(wid);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  if(    XmIsVendorShell( shell_of_wid)
Packit b099d7
     &&  (focus_data = _XmGetFocusData( shell_of_wid))    )
Packit b099d7
    {
Packit b099d7
      if(    focus_data->focalPoint != XmUnrelated    )
Packit b099d7
	{
Packit b099d7
	  _XmAppUnlock(app);
Packit b099d7
	  return TRUE ;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  else
Packit b099d7
    {
Packit b099d7
      XGetInputFocus( XtDisplay( shell_of_wid), &focus, &revert) ;
Packit b099d7
Packit b099d7
      if(    (focus != PointerRoot)
Packit b099d7
	 &&  (focus != None)
Packit b099d7
	 &&  (focus_wid = XtWindowToWidget( XtDisplay( shell_of_wid), focus))
Packit b099d7
	 &&  (shell_of_wid == _XmFindTopMostShell( focus_wid))    )
Packit b099d7
	{
Packit b099d7
	  _XmAppUnlock(app);
Packit b099d7
	  return TRUE ;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
  return FALSE ;
Packit b099d7
}
Packit b099d7
Packit b099d7
Boolean
Packit b099d7
_XmShellIsExclusive(
Packit b099d7
	Widget wid)
Packit b099d7
{
Packit b099d7
  XmFocusData focusData = _XmGetFocusData( wid) ;
Packit b099d7
Packit b099d7
  if(    focusData
Packit b099d7
     &&  focusData->trav_graph.exclusive    )
Packit b099d7
    {
Packit b099d7
      return TRUE ;
Packit b099d7
    }
Packit b099d7
  return FALSE ;
Packit b099d7
}
Packit b099d7
Packit b099d7
static Widget
Packit b099d7
FindFirstFocus(
Packit b099d7
	Widget wid)
Packit b099d7
{
Packit b099d7
  Widget shell = _XmFindTopMostShell( wid) ;
Packit b099d7
Packit b099d7
  return _XmNavigate( shell, XmTRAVERSE_CURRENT) ;
Packit b099d7
}
Packit b099d7
Packit b099d7
Widget
Packit b099d7
_XmGetFirstFocus(
Packit b099d7
	Widget wid)
Packit b099d7
{
Packit b099d7
  XmFocusData focus_data = _XmGetFocusData( wid) ;
Packit b099d7
Packit b099d7
  if(    focus_data    )
Packit b099d7
    {
Packit b099d7
      if(    focus_data->focus_item    )
Packit b099d7
	{
Packit b099d7
	  return focus_data->focus_item ;
Packit b099d7
	}
Packit b099d7
      else
Packit b099d7
	{
Packit b099d7
	  if(    focus_data->first_focus == NULL    )
Packit b099d7
	    {
Packit b099d7
	      focus_data->first_focus = FindFirstFocus( wid) ;
Packit b099d7
	    }
Packit b099d7
          return focus_data->first_focus ;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  return NULL ;
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
/*******************
Packit b099d7
 * Public procedures
Packit b099d7
 *******************/
Packit b099d7
Packit b099d7
Boolean
Packit b099d7
XmIsTraversable( 
Packit b099d7
        Widget wid)
Packit b099d7
{   
Packit b099d7
  Boolean traversable;
Packit b099d7
  _XmWidgetToAppContext(wid);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  traversable = IsTraversable( wid, FALSE) ;
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
  return traversable;
Packit b099d7
}
Packit b099d7
Packit b099d7
XmVisibility
Packit b099d7
XmGetVisibility( 
Packit b099d7
        Widget wid)
Packit b099d7
{   
Packit b099d7
  XRectangle rect ;
Packit b099d7
  Window rootwindow, parent_window, p_window, *children;
Packit b099d7
  unsigned int numchildren;
Packit b099d7
  int i;
Packit b099d7
  Window *windowptr;
Packit b099d7
  _XmWidgetToAppContext(wid);
Packit b099d7
  
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  if(    !wid
Packit b099d7
     || !_XmComputeVisibilityRect(wid, &rect, FALSE, TRUE)    )
Packit b099d7
    {   
Packit b099d7
      _XmAppUnlock(app);
Packit b099d7
      return( XmVISIBILITY_FULLY_OBSCURED) ;
Packit b099d7
    }
Packit b099d7
  if(    (rect.width != XtWidth( wid))
Packit b099d7
     || (rect.height != XtHeight( wid))    )
Packit b099d7
    {   
Packit b099d7
      _XmAppUnlock(app);
Packit b099d7
      return( XmVISIBILITY_PARTIALLY_OBSCURED) ;
Packit b099d7
    }
Packit b099d7
Packit b099d7
  /* Obscurity by siblings */
Packit b099d7
Packit b099d7
  children = NULL;
Packit b099d7
  if (!(parent_window = XtWindow(XtParent(wid))) ||
Packit b099d7
	XQueryTree( XtDisplay(wid), parent_window, &rootwindow, 
Packit b099d7
		&p_window, &children, &numchildren ) == 0)
Packit b099d7
  {
Packit b099d7
        if (children) XFree(children);
Packit b099d7
        _XmAppUnlock(app);
Packit b099d7
        return( XmVISIBILITY_UNOBSCURED) ;
Packit b099d7
  }
Packit b099d7
Packit b099d7
  windowptr = children;
Packit b099d7
Packit b099d7
  /* walk through those which are under the window of interest */
Packit b099d7
  for ( i = 0; i < numchildren; i++ )
Packit b099d7
  {
Packit b099d7
        if ( *windowptr == XtWindow(wid))
Packit b099d7
        {
Packit b099d7
	  break;
Packit b099d7
        }
Packit b099d7
        windowptr++;
Packit b099d7
  }
Packit b099d7
  i++;
Packit b099d7
  windowptr++;
Packit b099d7
Packit b099d7
  /* process windows above the window of interest */
Packit b099d7
  if(i < numchildren) {
Packit b099d7
      XRectangle parent_rect, srcRectB, intersect_rect;
Packit b099d7
      XWindowAttributes window_attributes_return;
Packit b099d7
      Region region = XCreateRegion();
Packit b099d7
      Region tmp_region = XCreateRegion();
Packit b099d7
      Region left_region = XCreateRegion();
Packit b099d7
      XmVisibility value;
Packit b099d7
Packit b099d7
      XUnionRectWithRegion(&rect, region, region);
Packit b099d7
      while(i < numchildren) { 
Packit b099d7
        XGetWindowAttributes(XtDisplay(wid), *windowptr, 
Packit b099d7
				&window_attributes_return);
Packit b099d7
Packit b099d7
        if(window_attributes_return.map_state == IsViewable) {
Packit b099d7
          _XmSetRect(&parent_rect, XtParent(wid));
Packit b099d7
          srcRectB.x = parent_rect.x + window_attributes_return.x 
Packit b099d7
					+ window_attributes_return.border_width;
Packit b099d7
          srcRectB.y = parent_rect.y + window_attributes_return.y 
Packit b099d7
					+ window_attributes_return.border_width;
Packit b099d7
          srcRectB.width = window_attributes_return.width;
Packit b099d7
          srcRectB.height = window_attributes_return.height;
Packit b099d7
Packit b099d7
          /* accumulate all the region covered by siblings */
Packit b099d7
          if(_XmIntersectionOf( &rect, &srcRectB, &intersect_rect)) {
Packit b099d7
            XUnionRectWithRegion(&intersect_rect, tmp_region, tmp_region);
Packit b099d7
          }
Packit b099d7
        }
Packit b099d7
        i++;
Packit b099d7
        windowptr++;
Packit b099d7
     }
Packit b099d7
Packit b099d7
     XSubtractRegion(region, tmp_region, left_region);
Packit b099d7
     if(XEqualRegion(region, left_region)) {
Packit b099d7
	value = XmVISIBILITY_UNOBSCURED;
Packit b099d7
     } else if(XEmptyRegion(left_region)) {
Packit b099d7
	value = XmVISIBILITY_FULLY_OBSCURED;
Packit b099d7
     } else {
Packit b099d7
	value = XmVISIBILITY_PARTIALLY_OBSCURED;
Packit b099d7
     }
Packit b099d7
     XDestroyRegion(region);
Packit b099d7
     XDestroyRegion(tmp_region);
Packit b099d7
     XDestroyRegion(left_region);
Packit b099d7
    if (children) XFree(children);
Packit b099d7
     _XmAppUnlock(app);
Packit b099d7
     return (value);
Packit b099d7
  }
Packit b099d7
  XFree((Window*)children);
Packit b099d7
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
  return( XmVISIBILITY_UNOBSCURED) ;
Packit b099d7
} 
Packit b099d7
Packit b099d7
Widget
Packit b099d7
XmGetTabGroup( 
Packit b099d7
        Widget wid)
Packit b099d7
{   
Packit b099d7
  XmFocusData focus_data ;
Packit b099d7
  Boolean exclusive ;
Packit b099d7
  _XmWidgetToAppContext(wid);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  if(    !wid
Packit b099d7
     || (_XmGetFocusPolicy( wid) != XmEXPLICIT)
Packit b099d7
     || !(focus_data = _XmGetFocusData( wid))    )
Packit b099d7
    {   
Packit b099d7
      _XmAppUnlock(app);
Packit b099d7
      return( NULL) ;
Packit b099d7
    }
Packit b099d7
  exclusive = !!(focus_data->trav_graph.exclusive) ;
Packit b099d7
Packit b099d7
  do
Packit b099d7
    {
Packit b099d7
      XmNavigationType nav_type = _XmGetNavigationType( wid) ;
Packit b099d7
      
Packit b099d7
      if(    (nav_type == XmSTICKY_TAB_GROUP)
Packit b099d7
	 ||  (nav_type == XmEXCLUSIVE_TAB_GROUP)
Packit b099d7
	 ||  (    (nav_type == XmTAB_GROUP)
Packit b099d7
	      &&  !exclusive)    )
Packit b099d7
	{
Packit b099d7
	  _XmAppUnlock(app);
Packit b099d7
	  return( wid) ;
Packit b099d7
	}
Packit b099d7
    } while(    (wid = XtParent( wid)) && !XtIsShell( wid)    ) ;
Packit b099d7
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
  return wid ;
Packit b099d7
}
Packit b099d7
Packit b099d7
Widget
Packit b099d7
XmGetFocusWidget( 
Packit b099d7
        Widget wid)
Packit b099d7
{
Packit b099d7
  Widget focus_wid = NULL ;
Packit b099d7
  XmFocusData focus_data = _XmGetFocusData( wid) ;
Packit b099d7
  _XmWidgetToAppContext(wid);
Packit b099d7
Packit b099d7
  _XmAppLock(app);
Packit b099d7
  if(    focus_data != NULL    )
Packit b099d7
    {   
Packit b099d7
      if(    focus_data->focus_policy == XmEXPLICIT    )
Packit b099d7
        {
Packit b099d7
	  focus_wid = focus_data->focus_item ;
Packit b099d7
	} 
Packit b099d7
      else
Packit b099d7
        {
Packit b099d7
	  focus_wid = focus_data->pointer_item ;
Packit b099d7
Packit b099d7
	  if(    (focus_wid != NULL)
Packit b099d7
	     &&  XmIsManager( focus_wid)
Packit b099d7
	     &&  (((XmManagerWidget) focus_wid)
Packit b099d7
		                     ->manager.highlighted_widget != NULL)    )
Packit b099d7
	    {
Packit b099d7
	      focus_wid = ((XmManagerWidget) focus_wid)
Packit b099d7
		                                 ->manager.highlighted_widget ;
Packit b099d7
	    }
Packit b099d7
	} 
Packit b099d7
    }
Packit b099d7
  _XmAppUnlock(app);
Packit b099d7
  return focus_wid ;
Packit b099d7
}
Packit b099d7
Packit b099d7
Boolean 
Packit b099d7
XmProcessTraversal(
Packit b099d7
        Widget w,
Packit b099d7
        XmTraversalDirection dir)
Packit b099d7
{   
Packit b099d7
  XmFocusData focus_data ;
Packit b099d7
  Boolean ret_val = FALSE;
Packit b099d7
Packit b099d7
  if ( w )
Packit b099d7
  {
Packit b099d7
    _XmWidgetToAppContext(w);
Packit b099d7
Packit b099d7
    _XmAppLock(app);
Packit b099d7
    if(    (focus_data = _XmGetFocusData( w))
Packit b099d7
       &&  (focus_data->focus_policy == XmEXPLICIT)    )
Packit b099d7
      {   
Packit b099d7
        if(    dir != XmTRAVERSE_CURRENT    )
Packit b099d7
          {   
Packit b099d7
	    if(    focus_data->focus_item    )
Packit b099d7
	      {
Packit b099d7
	        w = focus_data->focus_item ;
Packit b099d7
              }
Packit b099d7
	    else
Packit b099d7
	      {
Packit b099d7
	        w = _XmFindTopMostShell( w) ;
Packit b099d7
	      }
Packit b099d7
          }
Packit b099d7
        ret_val = _XmMgrTraversal( w, dir) ;
Packit b099d7
      }
Packit b099d7
    _XmAppUnlock(app);
Packit b099d7
  }
Packit b099d7
  return ret_val;
Packit b099d7
}
Packit b099d7
Packit b099d7
void 
Packit b099d7
XmAddTabGroup(
Packit b099d7
        Widget tabGroup )
Packit b099d7
{
Packit b099d7
    Arg		arg;
Packit b099d7
Packit b099d7
    XtSetArg(arg, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP);
Packit b099d7
    XtSetValues(tabGroup, &arg, 1);
Packit b099d7
}
Packit b099d7
Packit b099d7
void 
Packit b099d7
XmRemoveTabGroup(
Packit b099d7
        Widget w )
Packit b099d7
{
Packit b099d7
  Arg		arg;
Packit b099d7
Packit b099d7
  XtSetArg(arg, XmNnavigationType, XmNONE);
Packit b099d7
  XtSetValues(w, &arg, 1);
Packit b099d7
}
Packit b099d7

Packit b099d7
/*
Packit b099d7
 * Invoke the traversal redirection trait for all ancestors of both
Packit b099d7
 * old_focus and new_focus.  Repeat until concensus is achieved.
Packit b099d7
 */
Packit b099d7
static Widget
Packit b099d7
RedirectTraversal(Widget	       old_focus,
Packit b099d7
		  Widget	       new_focus,
Packit b099d7
		  unsigned int	       focus_policy,
Packit b099d7
		  XmTraversalDirection direction,
Packit b099d7
		  unsigned int	       pass)
Packit b099d7
{
Packit b099d7
  XmTraversalControlTrait trav_trait;
Packit b099d7
  Widget proposal = new_focus;
Packit b099d7
  Widget parent;
Packit b099d7
Packit b099d7
  /* Try not to get into an infinite loop. */
Packit b099d7
  if (pass >= 255)
Packit b099d7
    {
Packit b099d7
      assert(FALSE);
Packit b099d7
      return NULL;
Packit b099d7
    }
Packit b099d7
Packit b099d7
  /* Check ancestors of the old focus. */
Packit b099d7
  for (parent = old_focus; parent != NULL; parent = XtParent(parent))
Packit b099d7
    {
Packit b099d7
      trav_trait = (XmTraversalControlTrait) 
Packit b099d7
	XmeTraitGet((XtPointer) XtClass(parent), XmQTtraversalControl);
Packit b099d7
Packit b099d7
      if (trav_trait && trav_trait->redirect)
Packit b099d7
	{
Packit b099d7
	  proposal = trav_trait->redirect(old_focus, new_focus,
Packit b099d7
					  focus_policy, direction, pass);
Packit b099d7
	  if (proposal != new_focus)
Packit b099d7
	    return RedirectTraversal(old_focus, proposal, 
Packit b099d7
				     focus_policy, direction, pass + 1);
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
Packit b099d7
  /* Check ancestors of the new focus. */
Packit b099d7
  for (parent = new_focus; parent != NULL; parent = XtParent(parent))
Packit b099d7
    {
Packit b099d7
      trav_trait = (XmTraversalControlTrait) 
Packit b099d7
	XmeTraitGet((XtPointer) XtClass(parent), XmQTtraversalControl);
Packit b099d7
Packit b099d7
      if (trav_trait && trav_trait->redirect)
Packit b099d7
	{
Packit b099d7
	  proposal = trav_trait->redirect(old_focus, new_focus,
Packit b099d7
					  focus_policy, direction, pass);
Packit b099d7
	  if (proposal != new_focus)
Packit b099d7
	    return RedirectTraversal(old_focus, proposal, 
Packit b099d7
				     focus_policy, direction, pass + 1);
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
Packit b099d7
  /* Nobody changed our mind. */
Packit b099d7
  return new_focus;
Packit b099d7
}