Blame lib/Xm/GrabShell.c

Packit b099d7
/* $XConsortium: GrabShell.c /main/9 1996/08/15 17:12:04 pascale $ */
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
Packit b099d7
#ifdef HAVE_CONFIG_H
Packit b099d7
#include <config.h>
Packit b099d7
#endif
Packit b099d7
Packit b099d7
Packit b099d7
#include "XmI.h"
Packit b099d7
#include <X11/ShellP.h>
Packit b099d7
#include <X11/VendorP.h>
Packit b099d7
#include <X11/cursorfont.h>
Packit b099d7
#include <Xm/DrawP.h>
Packit b099d7
#include <Xm/GrabShellP.h>
Packit b099d7
#include <Xm/MenuUtilP.h>
Packit b099d7
#include <Xm/ScreenP.h>
Packit b099d7
#include <Xm/TransltnsP.h>
Packit b099d7
#include <Xm/VendorSEP.h>
Packit b099d7
#include <Xm/VendorSP.h>
Packit b099d7
#include "ColorI.h"
Packit b099d7
#include "MenuShellI.h"
Packit b099d7
#include "PixConvI.h"
Packit b099d7
#include "UniqueEvnI.h"
Packit b099d7
Packit b099d7
/* Warning messages */
Packit b099d7
Packit b099d7
#define default_translations	_XmGrabShell_translations
Packit b099d7
Packit b099d7
#define Events	(EnterWindowMask | LeaveWindowMask | \
Packit b099d7
		 ButtonPressMask | ButtonReleaseMask)
Packit b099d7
Packit b099d7
/********    Static Function Declarations    ********/
Packit b099d7
#ifdef FIX_1445
Packit b099d7
static void MouseWheel (Widget grabshell,
Packit b099d7
		     XEvent *event,
Packit b099d7
		     String *params,
Packit b099d7
		     Cardinal *num_params);
Packit b099d7
#endif
Packit b099d7
static void BtnUp (Widget grabshell,
Packit b099d7
		     XEvent *event,
Packit b099d7
		     String *params,
Packit b099d7
		     Cardinal *num_params);
Packit b099d7
static void BtnDown (Widget grabshell,
Packit b099d7
		     XEvent *event,
Packit b099d7
		     String *params,
Packit b099d7
		     Cardinal *num_params);
Packit b099d7
static void Popdown (Widget grabshell,
Packit b099d7
		     XEvent *event,
Packit b099d7
		     String *params,
Packit b099d7
		     Cardinal *num_params);
Packit b099d7
static void ClassPartInitialize (WidgetClass wc);
Packit b099d7
static void Initialize (Widget req,
Packit b099d7
			Widget new_w,
Packit b099d7
			ArgList args,
Packit b099d7
			Cardinal *num_args);
Packit b099d7
static Boolean SetValues (Widget cw,
Packit b099d7
			  Widget rw,
Packit b099d7
			  Widget nw,
Packit b099d7
			  ArgList args,
Packit b099d7
			  Cardinal *num_args);
Packit b099d7
static void Resize (Widget wid);
Packit b099d7
static void ChangeManaged (Widget w);
Packit b099d7
static XtGeometryResult GeometryManager( 
Packit b099d7
                        Widget wid,
Packit b099d7
                        XtWidgetGeometry *request,
Packit b099d7
                        XtWidgetGeometry *reply) ;
Packit b099d7
static void Destroy (Widget wid);
Packit b099d7
static void MapNotifyHandler(Widget shell, XtPointer client_data,
Packit b099d7
			     XEvent *, Boolean *);
Packit b099d7
static void _XmFastExpose (Widget widget);
Packit b099d7
static void DrawBorder (Widget widget);
Packit b099d7
static void DoLayout (Widget gs);
Packit b099d7
static void GSAllowEvents(Widget gs, int, Time);
Packit b099d7
Packit b099d7
static int IgnoreXErrors(Display *, XErrorEvent *);
Packit b099d7
Packit b099d7
Packit b099d7
/********    End Static Function Declarations    ********/
Packit b099d7

Packit b099d7
static XtActionsRec actionsList[] = 
Packit b099d7
{
Packit b099d7
  { "GrabShellBtnDown", BtnDown },
Packit b099d7
  { "GrabShellBtnUp",   BtnUp },
Packit b099d7
  { "GrabShellPopdown", Popdown }
Packit b099d7
#ifdef FIX_1445
Packit b099d7
  ,
Packit b099d7
  { "GrabShellMouseWheel", MouseWheel }
Packit b099d7
#endif
Packit b099d7
};
Packit b099d7
Packit b099d7
Packit b099d7
#define Offset(field) (XtOffsetOf(XmGrabShellRec, field))
Packit b099d7
Packit b099d7
static XtResource resources[] =
Packit b099d7
{
Packit b099d7
  {
Packit b099d7
    XmNallowShellResize, XmCAllowShellResize, XmRBoolean, 
Packit b099d7
    sizeof(Boolean), Offset(shell.allow_shell_resize), 
Packit b099d7
    XtRImmediate, (XtPointer)TRUE
Packit b099d7
  },
Packit b099d7
  {
Packit b099d7
    XmNbackground, XmCBackground, XmRPixel, 
Packit b099d7
    sizeof (Pixel), Offset(core.background_pixel),
Packit b099d7
    XmRCallProc, (XtPointer) _XmBackgroundColorDefault
Packit b099d7
  },
Packit b099d7
  {
Packit b099d7
    XmNoverrideRedirect, XmCOverrideRedirect, XmRBoolean, 
Packit b099d7
    sizeof(Boolean), Offset(shell.override_redirect), 
Packit b099d7
    XtRImmediate, (XtPointer)TRUE
Packit b099d7
  },
Packit b099d7
  {
Packit b099d7
    XmNsaveUnder, XmCSaveUnder, XmRBoolean, 
Packit b099d7
    sizeof(Boolean), Offset(shell.save_under), 
Packit b099d7
    XtRImmediate, (XtPointer)FALSE
Packit b099d7
  },
Packit b099d7
  {
Packit b099d7
    XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension, 
Packit b099d7
    sizeof(Dimension), Offset(grab_shell.shadow_thickness), 
Packit b099d7
    XmRImmediate, (XtPointer)2
Packit b099d7
  },
Packit b099d7
  {
Packit b099d7
    XmNtransient, XmCTransient, XmRBoolean, 
Packit b099d7
    sizeof(Boolean), Offset(wm_shell.transient), 
Packit b099d7
    XtRImmediate, (XtPointer)TRUE
Packit b099d7
  },
Packit b099d7
  {
Packit b099d7
    XmNwaitForWm, XmCWaitForWm, XmRBoolean, 
Packit b099d7
    sizeof(Boolean), Offset(wm_shell.wait_for_wm), 
Packit b099d7
    XtRImmediate, (XtPointer)FALSE
Packit b099d7
  },
Packit b099d7
  {
Packit b099d7
    XmNtopShadowColor, XmCTopShadowColor, XmRPixel, 
Packit b099d7
    sizeof(Pixel), Offset(grab_shell.top_shadow_color),
Packit b099d7
    XmRCallProc, (XtPointer) _XmTopShadowColorDefault
Packit b099d7
  },
Packit b099d7
  {
Packit b099d7
    XmNtopShadowPixmap, XmCTopShadowPixmap, XmRNoScalingDynamicPixmap,
Packit b099d7
    sizeof(Pixmap), Offset(grab_shell.top_shadow_pixmap),
Packit b099d7
    XmRCallProc, (XtPointer) _XmTopShadowPixmapDefault
Packit b099d7
  },
Packit b099d7
  {
Packit b099d7
    XmNbottomShadowColor, XmCBottomShadowColor, XmRPixel, 
Packit b099d7
    sizeof(Pixel), Offset(grab_shell.bottom_shadow_color),
Packit b099d7
    XmRCallProc, (XtPointer) _XmBottomShadowColorDefault
Packit b099d7
  },
Packit b099d7
  {
Packit b099d7
    XmNbottomShadowPixmap, XmCBottomShadowPixmap, XmRNoScalingDynamicPixmap,
Packit b099d7
    sizeof(Pixmap), Offset(grab_shell.bottom_shadow_pixmap),
Packit b099d7
    XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP
Packit b099d7
  },
Packit b099d7
  {
Packit b099d7
    XmNgrabStyle, XmCGrabStyle, XmRInt,
Packit b099d7
    sizeof(int), Offset(grab_shell.grab_style),
Packit b099d7
    XmRImmediate, (XtPointer) GrabModeAsync
Packit b099d7
  },
Packit b099d7
  {
Packit b099d7
    XmNownerEvents, XmCOwnerEvents, XmRBoolean,
Packit b099d7
    sizeof(Boolean), Offset(grab_shell.owner_events),
Packit b099d7
    XmRImmediate, (XtPointer) FALSE
Packit b099d7
  }
Packit b099d7
};
Packit b099d7
#undef Offset
Packit b099d7

Packit b099d7
externaldef(xmgrabshellclassrec) XmGrabShellClassRec xmGrabShellClassRec = 
Packit b099d7
{
Packit b099d7
  { /* core class fields */
Packit b099d7
    (WidgetClass) &vendorShellClassRec,	/* superclass		 */
Packit b099d7
    "XmGrabShell",			/* class_name		 */
Packit b099d7
    sizeof (XmGrabShellWidgetRec),	/* widget_size		 */
Packit b099d7
    NULL,				/* class_initialize	 */
Packit b099d7
    ClassPartInitialize,		/* class_part_initialize */
Packit b099d7
    FALSE,				/* class_inited		 */
Packit b099d7
    Initialize,				/* initialize		 */
Packit b099d7
    (XtArgsProc)NULL,			/* initialize_hook	 */
Packit b099d7
    XtInheritRealize,			/* realize		 */
Packit b099d7
    actionsList,			/* actions		 */
Packit b099d7
    XtNumber(actionsList),		/* num_actions		 */
Packit b099d7
    resources,				/* resource list	 */
Packit b099d7
    XtNumber(resources),		/* resource_count	 */
Packit b099d7
    NULLQUARK,				/* xrm_class		 */
Packit b099d7
    True,				/* compress_motion	 */
Packit b099d7
    XtExposeCompressMaximal,		/* compress_exposure	 */
Packit b099d7
    TRUE,				/* compress_enterleave	 */
Packit b099d7
    FALSE,				/* visible_interest	 */
Packit b099d7
    Destroy,				/* destroy		 */
Packit b099d7
    Resize,				/* resize		 */
Packit b099d7
    NULL,				/* expose		 */
Packit b099d7
    SetValues,				/* set_values		 */
Packit b099d7
    (XtArgsFunc)NULL,			/* set_values_hook	 */
Packit b099d7
    XtInheritSetValuesAlmost,		/* set_values_almost	 */
Packit b099d7
    (XtArgsProc)NULL,			/* get_values_hook	 */
Packit b099d7
    (XtAcceptFocusProc)NULL,		/* accept_focus		 */
Packit b099d7
    XtVersion,				/* version		 */
Packit b099d7
    NULL,				/* callback_private	 */
Packit b099d7
    default_translations,		/* tm_table		 */
Packit b099d7
    (XtGeometryHandler)NULL,		/* query_geometry	 */
Packit b099d7
    (XtStringProc)NULL,			/* display_accelerator	 */
Packit b099d7
    NULL,				/* extension		 */
Packit b099d7
  },
Packit b099d7
  { /* composite class fields */
Packit b099d7
    GeometryManager, 		     	/* geometry_manager	 */
Packit b099d7
    ChangeManaged,			/* change_managed	 */
Packit b099d7
    XtInheritInsertChild,		/* insert_child		 */
Packit b099d7
    XtInheritDeleteChild,		/* delete_child		 */
Packit b099d7
    NULL,				/* extension		 */
Packit b099d7
  },
Packit b099d7
  { /* shell class fields */
Packit b099d7
    NULL,				/* extension		 */
Packit b099d7
  },
Packit b099d7
  { /* wmshell class fields */
Packit b099d7
    NULL,				/* extension		 */
Packit b099d7
  },
Packit b099d7
  { /* vendor shell class fields */
Packit b099d7
    NULL,				/* extension		 */
Packit b099d7
  },
Packit b099d7
  { /* grabshell class fields */
Packit b099d7
    NULL,				/* extension		 */ 
Packit b099d7
  },
Packit b099d7
};
Packit b099d7
Packit b099d7
Packit b099d7
externaldef(xmgrabshellwidgetclass) WidgetClass xmGrabShellWidgetClass = 
Packit b099d7
   (WidgetClass) &xmGrabShellClassRec;
Packit b099d7

Packit b099d7
/* ------------- WIDGET CLASS METHODS ---------- */
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * Initialize()
Packit b099d7
 */
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
static void 
Packit b099d7
Initialize(Widget req,		/* unused */
Packit b099d7
	   Widget new_w,
Packit b099d7
	   ArgList args,	/* unused */
Packit b099d7
	   Cardinal *num_args)	/* unused */
Packit b099d7
{
Packit b099d7
  XmGrabShellWidget grabsh = (XmGrabShellWidget)new_w;
Packit b099d7
  
Packit b099d7
  XtAddEventHandler(new_w, StructureNotifyMask, False, MapNotifyHandler, NULL);
Packit b099d7
  
Packit b099d7
  grabsh->grab_shell.unpost_time = (Time) -1;
Packit b099d7
  grabsh->grab_shell.cursor = None;
Packit b099d7
Packit b099d7
  grabsh->grab_shell.top_shadow_GC = 
Packit b099d7
    _XmGetPixmapBasedGC (new_w, 
Packit b099d7
			 grabsh->grab_shell.top_shadow_color,
Packit b099d7
			 grabsh->core.background_pixel,
Packit b099d7
			 grabsh->grab_shell.top_shadow_pixmap);
Packit b099d7
Packit b099d7
  grabsh->grab_shell.bottom_shadow_GC = 
Packit b099d7
    _XmGetPixmapBasedGC (new_w, 
Packit b099d7
			 grabsh->grab_shell.bottom_shadow_color,
Packit b099d7
			 grabsh->core.background_pixel,
Packit b099d7
			 grabsh->grab_shell.bottom_shadow_pixmap);
Packit b099d7
Packit b099d7
  /* CR 6723:  The BtnUp event may arrive before MapNotify. */
Packit b099d7
  grabsh->grab_shell.post_time = XtLastTimestampProcessed(XtDisplay(new_w));
Packit b099d7
Packit b099d7
  /* CR 9920:  Popdown may be requested before MapNotify. */
Packit b099d7
  grabsh->grab_shell.mapped = False;
Packit b099d7
}
Packit b099d7

Packit b099d7
/*
Packit b099d7
 * ClassPartInitialize()
Packit b099d7
 *	Set up the fast subclassing.
Packit b099d7
 */
Packit b099d7
Packit b099d7
static void 
Packit b099d7
ClassPartInitialize(WidgetClass wc)
Packit b099d7
{
Packit b099d7
  _XmFastSubclassInit (wc, XmGRAB_SHELL_BIT);
Packit b099d7
}
Packit b099d7

Packit b099d7
/*
Packit b099d7
 * SetValues()
Packit b099d7
 */
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
static Boolean 
Packit b099d7
SetValues(Widget cw,
Packit b099d7
	  Widget rw,		/* unused */
Packit b099d7
	  Widget nw,
Packit b099d7
	  ArgList args,		/* unused */
Packit b099d7
	  Cardinal *num_args)	/* unused */
Packit b099d7
{
Packit b099d7
  XmGrabShellWidget new_w = (XmGrabShellWidget) nw;
Packit b099d7
  XmGrabShellWidget old_w = (XmGrabShellWidget) cw;
Packit b099d7
  Boolean redisplay = FALSE;
Packit b099d7
  
Packit b099d7
  if (old_w->grab_shell.shadow_thickness != new_w->grab_shell.shadow_thickness)
Packit b099d7
    {
Packit b099d7
      if (XtIsRealized(nw)) {
Packit b099d7
	DoLayout(nw);
Packit b099d7
	redisplay = TRUE;
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
  if ((old_w->grab_shell.top_shadow_color != 
Packit b099d7
       new_w->grab_shell.top_shadow_color) ||
Packit b099d7
      (old_w->grab_shell.top_shadow_pixmap != 
Packit b099d7
       new_w->grab_shell.top_shadow_pixmap))
Packit b099d7
    {
Packit b099d7
      XtReleaseGC (nw, new_w->grab_shell.top_shadow_GC);
Packit b099d7
      new_w->grab_shell.top_shadow_GC = 
Packit b099d7
	_XmGetPixmapBasedGC (nw, 
Packit b099d7
			     new_w->grab_shell.top_shadow_color,
Packit b099d7
			     new_w->core.background_pixel,
Packit b099d7
			     new_w->grab_shell.top_shadow_pixmap);
Packit b099d7
      redisplay = TRUE;
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
  if ((old_w->grab_shell.bottom_shadow_color != 
Packit b099d7
       new_w->grab_shell.bottom_shadow_color) ||
Packit b099d7
      (old_w->grab_shell.bottom_shadow_pixmap != 
Packit b099d7
       new_w->grab_shell.bottom_shadow_pixmap))
Packit b099d7
    {
Packit b099d7
      XtReleaseGC (nw, new_w->grab_shell.bottom_shadow_GC);
Packit b099d7
      new_w->grab_shell.bottom_shadow_GC = 
Packit b099d7
	_XmGetPixmapBasedGC (nw, 
Packit b099d7
			     new_w->grab_shell.bottom_shadow_color,
Packit b099d7
			     new_w->core.background_pixel,
Packit b099d7
			     new_w->grab_shell.bottom_shadow_pixmap);
Packit b099d7
      redisplay = TRUE;
Packit b099d7
    }
Packit b099d7
Packit b099d7
  return redisplay; 
Packit b099d7
}
Packit b099d7

Packit b099d7
/*
Packit b099d7
 * PopupCB()
Packit b099d7
 *	Grabs.
Packit b099d7
 */
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
static void 
Packit b099d7
MapNotifyHandler(Widget shell, XtPointer client_data,
Packit b099d7
		 XEvent *event, Boolean *cont)
Packit b099d7
{
Packit b099d7
  XmGrabShellWidget grabshell = (XmGrabShellWidget)shell; 
Packit b099d7
  Time time;
Packit b099d7
  XErrorHandler old_handler;
Packit b099d7
Packit b099d7
  /* Only handles map events */
Packit b099d7
  if (event -> type != MapNotify) return;
Packit b099d7
  
Packit b099d7
  /* CR 9920:  Popdown may be called before MapNotify. */
Packit b099d7
  grabshell->grab_shell.mapped = True;
Packit b099d7
Packit b099d7
  if (!(time = XtLastTimestampProcessed(XtDisplay(shell))))
Packit b099d7
    time = CurrentTime;
Packit b099d7
  if (grabshell->grab_shell.cursor == None)
Packit b099d7
    grabshell->grab_shell.cursor = 
Packit b099d7
      XCreateFontCursor (XtDisplay(grabshell), XC_arrow);
Packit b099d7
  
Packit b099d7
  _XmFastExpose(shell);
Packit b099d7
  
Packit b099d7
  (void) XtGrabKeyboard(shell, grabshell -> grab_shell.owner_events, 
Packit b099d7
			grabshell -> grab_shell.grab_style,
Packit b099d7
			GrabModeAsync, time);
Packit b099d7
Packit b099d7
  (void) XtGrabPointer(shell, grabshell -> grab_shell.owner_events, 
Packit b099d7
		       Events,
Packit b099d7
		       grabshell -> grab_shell.grab_style,
Packit b099d7
		       GrabModeAsync, None, 
Packit b099d7
		       grabshell->grab_shell.cursor, time);
Packit b099d7
  
Packit b099d7
  GSAllowEvents(shell, SyncPointer, time);
Packit b099d7
Packit b099d7
  /* Fix focus to shell */
Packit b099d7
  XGetInputFocus(XtDisplay(shell), &grabshell->grab_shell.old_focus,
Packit b099d7
		 &grabshell->grab_shell.old_revert_to);
Packit b099d7
  old_handler = XSetErrorHandler(IgnoreXErrors);
Packit b099d7
  XSetInputFocus(XtDisplay(shell), XtWindow(shell), RevertToParent, time);
Packit b099d7
  XSync(XtDisplay(shell), False);
Packit b099d7
  XSetErrorHandler(old_handler);
Packit b099d7
}
Packit b099d7

Packit b099d7
#ifdef FIX_1445
Packit b099d7
static void MouseWheel (Widget w, XEvent *event, String *params, Cardinal *num_params)
Packit b099d7
{
Packit b099d7
	XmGrabShellWidget grabshell = (XmGrabShellWidget) w;
Packit b099d7
	GSAllowEvents(w, SyncPointer, event -> xbutton.time);
Packit b099d7
}
Packit b099d7
#endif
Packit b099d7

Packit b099d7
/* 
Packit b099d7
 * For BtnUp and BtnDown events we need to decide whether to
Packit b099d7
 * popdown the grabshell.  We "see" these if the user presses
Packit b099d7
 * outside the shell.  
Packit b099d7
 *
Packit b099d7
 * To decide,  we call the XmNhasInterestCB to see if our poster
Packit b099d7
 * wants to handle the event.  If our poster does,  we call
Packit b099d7
 * XAllowEvents with REPLAY to get the event to the poster,  otherwise
Packit b099d7
 * we Popdown()
Packit b099d7
 *
Packit b099d7
 */
Packit b099d7
Packit b099d7
static void 
Packit b099d7
BtnUp (Widget w,
Packit b099d7
       XEvent *event,
Packit b099d7
       String *params,
Packit b099d7
       Cardinal *num_params)
Packit b099d7
{
Packit b099d7
  XmGrabShellWidget grabshell = (XmGrabShellWidget) w;
Packit b099d7
  int delta;
Packit b099d7
Packit b099d7
  /* Handle click to post 
Packit b099d7
     we then ignore the event if it occured within the 
Packit b099d7
     click to post time */
Packit b099d7
  delta = event -> xbutton.time - grabshell -> grab_shell.post_time;
Packit b099d7
  if (delta <= XtGetMultiClickTime(XtDisplay(w))) {
Packit b099d7
    GSAllowEvents(w, SyncPointer, event -> xbutton.time);
Packit b099d7
    return;
Packit b099d7
  }
Packit b099d7
Packit b099d7
  Popdown(w, event, params, num_params);
Packit b099d7
}
Packit b099d7
Packit b099d7
static void
Packit b099d7
BtnDown (Widget grabshell,
Packit b099d7
	 XEvent *event,
Packit b099d7
	 String *params,
Packit b099d7
	 Cardinal *num_params)
Packit b099d7
{
Packit b099d7
  int x, y;
Packit b099d7
  Window win;
Packit b099d7
Packit b099d7
  /* Ignore modal cascade replay of event */
Packit b099d7
  if (! _XmIsEventUnique(event)) return;
Packit b099d7
Packit b099d7
  /* Move to grabshell's coordinate system */
Packit b099d7
  XTranslateCoordinates(XtDisplay(grabshell), event -> xbutton.window,
Packit b099d7
			XtWindow(grabshell), 
Packit b099d7
			event -> xbutton.x, event -> xbutton.y,
Packit b099d7
			&x, &y, &win);
Packit b099d7
Packit b099d7
  /* Popdown if outside the shell */
Packit b099d7
  if (x >= 0 && y >= 0 && 
Packit b099d7
      x <= XtWidth(grabshell) && y <= XtHeight(grabshell)) {
Packit b099d7
    GSAllowEvents(grabshell, SyncPointer, event -> xbutton.time);
Packit b099d7
  } else {
Packit b099d7
    Popdown(grabshell, event, params, num_params);
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * Popdown()
Packit b099d7
 *	Popdown a GrabShell widget, also flag it's child as unmanaged.
Packit b099d7
 */
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
static void 
Packit b099d7
Popdown(Widget shell,
Packit b099d7
        XEvent *event,		/* unused */
Packit b099d7
	String *params,
Packit b099d7
	Cardinal *num_params)
Packit b099d7
{
Packit b099d7
  XmScreen screen = (XmScreen) XmGetXmScreen(XtScreen(shell));
Packit b099d7
  XmGrabShellWidget grabshell = (XmGrabShellWidget)shell;
Packit b099d7
  Time time;
Packit b099d7
  
Packit b099d7
  /* Record for replay detection */
Packit b099d7
  if (event && (event->type == ButtonPress || event->type == ButtonRelease)) {
Packit b099d7
    grabshell->grab_shell.unpost_time = event->xbutton.time;
Packit b099d7
  }
Packit b099d7
Packit b099d7
  if (!(time = XtLastTimestampProcessed(XtDisplay(shell))))
Packit b099d7
    time = CurrentTime;
Packit b099d7
Packit b099d7
  /* CR 9920:  Popdown may be called before MapNotify. */
Packit b099d7
  if (grabshell->shell.popped_up && grabshell->grab_shell.mapped)
Packit b099d7
    {
Packit b099d7
      XErrorHandler old_handler;
Packit b099d7
Packit b099d7
      if (screen -> screen.unpostBehavior == XmUNPOST_AND_REPLAY)
Packit b099d7
	GSAllowEvents(shell, ReplayPointer, event ? event->xbutton.time : time);
Packit b099d7
      XtUngrabPointer(shell, time);
Packit b099d7
      XtUngrabKeyboard(shell, time);
Packit b099d7
      _XmPopdown(shell);
Packit b099d7
Packit b099d7
      /* Reset focus to old holder */
Packit b099d7
      old_handler = XSetErrorHandler(IgnoreXErrors);
Packit b099d7
      if (time != CurrentTime) time = time - 1; /* Avoid race in wm */
Packit b099d7
      XSetInputFocus(XtDisplay(shell), grabshell->grab_shell.old_focus,
Packit b099d7
		     grabshell->grab_shell.old_revert_to, time);
Packit b099d7
      XSync(XtDisplay(shell), False);
Packit b099d7
      XSetErrorHandler(old_handler);
Packit b099d7
    }
Packit b099d7
Packit b099d7
  grabshell->grab_shell.mapped = False;
Packit b099d7
}
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * This only calls allow events if we have a sync grab.
Packit b099d7
 */
Packit b099d7
static void 
Packit b099d7
GSAllowEvents(Widget gs, int mode, Time time)
Packit b099d7
{
Packit b099d7
  XmGrabShellWidget grabshell = (XmGrabShellWidget) gs;
Packit b099d7
Packit b099d7
  if (grabshell -> grab_shell.grab_style == GrabModeSync) {
Packit b099d7
    XAllowEvents(XtDisplay(gs), mode, time);
Packit b099d7
  }
Packit b099d7
}
Packit b099d7
Packit b099d7

Packit b099d7
/*
Packit b099d7
 * Destroy()
Packit b099d7
 */
Packit b099d7
Packit b099d7
static void 
Packit b099d7
Destroy(Widget widg)
Packit b099d7
{
Packit b099d7
  XmGrabShellWidget grabshell = (XmGrabShellWidget) widg;
Packit b099d7
  
Packit b099d7
  if (grabshell->grab_shell.cursor != None)
Packit b099d7
    XFreeCursor(XtDisplay(widg), grabshell->grab_shell.cursor);
Packit b099d7
}
Packit b099d7

Packit b099d7
/*
Packit b099d7
 * DoLayout()
Packit b099d7
 */
Packit b099d7
Packit b099d7
static void 
Packit b099d7
DoLayout(Widget wid)
Packit b099d7
{
Packit b099d7
  XmGrabShellWidget gs = (XmGrabShellWidget)wid;
Packit b099d7
  
Packit b099d7
  if (XtIsManaged(gs->composite.children[0])) 
Packit b099d7
    {
Packit b099d7
      Widget childwid = gs->composite.children[0];
Packit b099d7
      Position offset = (gs->grab_shell.shadow_thickness + 
Packit b099d7
			 childwid->core.border_width);
Packit b099d7
      int cw = ((int) gs->core.width) - 2 * offset;
Packit b099d7
      int ch = ((int) gs->core.height) - 2 * offset;
Packit b099d7
      Dimension childW = MAX(1, cw);
Packit b099d7
      Dimension childH = MAX(1, ch);
Packit b099d7
Packit b099d7
      XmeConfigureObject (childwid, offset, offset,
Packit b099d7
			  childW, childH, childwid->core.border_width);
Packit b099d7
    }
Packit b099d7
}
Packit b099d7
	
Packit b099d7
/************************************************************************
Packit b099d7
 *
Packit b099d7
 *  GeometryManager
Packit b099d7
 *
Packit b099d7
 ************************************************************************/
Packit b099d7
/*ARGSUSED*/
Packit b099d7
static XtGeometryResult 
Packit b099d7
GeometryManager(
Packit b099d7
	 Widget wid,
Packit b099d7
	 XtWidgetGeometry *request,
Packit b099d7
	 XtWidgetGeometry *reply ) /* unused */
Packit b099d7
{
Packit b099d7
  XmGrabShellWidget gs = (XmGrabShellWidget) XtParent(wid);
Packit b099d7
  XtWidgetGeometry modified;
Packit b099d7
  int bw;
Packit b099d7
  XtGeometryResult ret_val;
Packit b099d7
Packit b099d7
  /* Copy the existing request */
Packit b099d7
  modified = *request;
Packit b099d7
Packit b099d7
  bw = XtBorderWidth(wid);
Packit b099d7
Packit b099d7
  /* Add shell's shadow thickness and child's borderwidth */
Packit b099d7
  modified.width += 2*bw + 2*gs->grab_shell.shadow_thickness;
Packit b099d7
  modified.height += 2*bw + 2*gs->grab_shell.shadow_thickness;
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  /* Send to vendor shell for final */
Packit b099d7
  ret_val = ((VendorShellClassRec *) vendorShellWidgetClass) -> 
Packit b099d7
	 composite_class.geometry_manager(wid,&modified,reply);
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
  return ret_val;
Packit b099d7
}
Packit b099d7
Packit b099d7

Packit b099d7
/*
Packit b099d7
 * ChangeManaged()
Packit b099d7
 */
Packit b099d7
Packit b099d7
static void 
Packit b099d7
ChangeManaged(Widget wid)
Packit b099d7
{
Packit b099d7
  XmGrabShellWidget gs = (XmGrabShellWidget)wid;
Packit b099d7
  ShellWidget       shell = (ShellWidget)wid;
Packit b099d7
  Dimension         bw = 0;
Packit b099d7
  XtWidgetGeometry  pref, mygeom, replygeom;
Packit b099d7
  XtGeometryResult  result;
Packit b099d7
  Widget	    child;
Packit b099d7
  
Packit b099d7
  mygeom.request_mode = 0;
Packit b099d7
  if (gs->composite.num_children)
Packit b099d7
    {
Packit b099d7
      child = gs->composite.children[0];
Packit b099d7
      if (XtIsManaged(child))
Packit b099d7
	{
Packit b099d7
	  /* Get child's preferred size */
Packit b099d7
	  result = XtQueryGeometry(child, NULL, &pref;;
Packit b099d7
	  
Packit b099d7
	  /* Take whatever they want */
Packit b099d7
	  if (pref.request_mode & CWWidth)
Packit b099d7
	    {
Packit b099d7
	      mygeom.width = pref.width; 
Packit b099d7
	      mygeom.request_mode |=  CWWidth;
Packit b099d7
	    }
Packit b099d7
Packit b099d7
	  if (pref.request_mode & CWHeight)
Packit b099d7
	    {
Packit b099d7
	      mygeom.height = pref.height;
Packit b099d7
	      mygeom.request_mode |=  CWHeight;
Packit b099d7
	    }
Packit b099d7
Packit b099d7
	  if (pref.request_mode & CWBorderWidth)
Packit b099d7
	    bw = pref.border_width;
Packit b099d7
	  else
Packit b099d7
	    bw = child->core.border_width;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
  mygeom.width += 2*bw + 2*gs->grab_shell.shadow_thickness;
Packit b099d7
  mygeom.height += 2*bw + 2*gs->grab_shell.shadow_thickness;
Packit b099d7
  
Packit b099d7
  result = XtMakeGeometryRequest((Widget)shell, &mygeom, &replygeom);
Packit b099d7
  switch (result)
Packit b099d7
    {
Packit b099d7
    case XtGeometryAlmost:
Packit b099d7
      XtMakeGeometryRequest((Widget)shell, &replygeom, NULL);
Packit b099d7
      /* fall through. */
Packit b099d7
    case XtGeometryYes:
Packit b099d7
      DoLayout(wid);
Packit b099d7
      break;
Packit b099d7
    case XtGeometryNo:
Packit b099d7
    case XtGeometryDone:
Packit b099d7
      break;
Packit b099d7
    }
Packit b099d7
}
Packit b099d7

Packit b099d7
/*
Packit b099d7
 * Resize()
Packit b099d7
 */
Packit b099d7
Packit b099d7
static void 
Packit b099d7
Resize(Widget w)
Packit b099d7
{
Packit b099d7
  DoLayout(w);
Packit b099d7
}
Packit b099d7

Packit b099d7
/*
Packit b099d7
 * When using an override redirect window, it is safe to draw to the
Packit b099d7
 * window as soon as you have mapped it; you need not wait for exposure
Packit b099d7
 * events to arrive.  So ... to force shells to post quickly, we will
Packit b099d7
 * redraw all of the items now, and ignore the exposure events we receive
Packit b099d7
 * later.
Packit b099d7
 */
Packit b099d7
Packit b099d7
static void 
Packit b099d7
_XmFastExpose(Widget widg)
Packit b099d7
{
Packit b099d7
  register int i;
Packit b099d7
  register Widget child;
Packit b099d7
  XmGrabShellWidget gs = (XmGrabShellWidget)widg;
Packit b099d7
Packit b099d7
  _XmProcessLock();
Packit b099d7
  (*(XtClass(widg)->core_class.expose)) (widg, NULL, NULL);
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
  
Packit b099d7
  /* Process each windowed child */
Packit b099d7
  for (i = 0; i < gs->composite.num_children; i++)
Packit b099d7
    {
Packit b099d7
      child = gs->composite.children[i];
Packit b099d7
      
Packit b099d7
      if (XtIsWidget(child) && XtIsManaged(child)) {
Packit b099d7
        _XmProcessLock();
Packit b099d7
	(*(XtClass(child)->core_class.expose)) (child, NULL, NULL);
Packit b099d7
	_XmProcessUnlock();
Packit b099d7
      }
Packit b099d7
    }
Packit b099d7
  
Packit b099d7
  XFlush(XtDisplay(widg));
Packit b099d7
  DrawBorder(widg);
Packit b099d7
}
Packit b099d7

Packit b099d7
/*
Packit b099d7
 * DrawBorder()
Packit b099d7
 */
Packit b099d7
Packit b099d7
static void
Packit b099d7
DrawBorder(Widget widg) 
Packit b099d7
{
Packit b099d7
  XmGrabShellWidget gs = (XmGrabShellWidget)widg;
Packit b099d7
  int offset = 0;
Packit b099d7
  
Packit b099d7
  XmeDrawShadows(XtDisplay(widg), XtWindow(widg),
Packit b099d7
		 gs->grab_shell.top_shadow_GC,
Packit b099d7
		 gs->grab_shell.bottom_shadow_GC,
Packit b099d7
		 offset, offset,
Packit b099d7
		 XtWidth(widg) - 2 * offset,
Packit b099d7
		 XtHeight(widg) - 2 * offset,
Packit b099d7
		 gs->grab_shell.shadow_thickness,
Packit b099d7
		 XmSHADOW_OUT);
Packit b099d7
}
Packit b099d7

Packit b099d7
/* 
Packit b099d7
 * IgnoreXErrors()
Packit b099d7
 *	An XErrorHandler that smothers errors.
Packit b099d7
 */
Packit b099d7
Packit b099d7
/*ARGSUSED*/
Packit b099d7
static int
Packit b099d7
IgnoreXErrors(Display *dpy,	/* unused */
Packit b099d7
	      XErrorEvent *event) /* unused */
Packit b099d7
{
Packit b099d7
  return 0;
Packit b099d7
}
Packit b099d7

Packit b099d7
/*******************
Packit b099d7
 * Public Routines *
Packit b099d7
 *******************/
Packit b099d7
Packit b099d7
Widget 
Packit b099d7
XmCreateGrabShell(Widget parent,
Packit b099d7
		  char *name,
Packit b099d7
		  ArgList al,
Packit b099d7
		  Cardinal ac)
Packit b099d7
{
Packit b099d7
  return XtCreatePopupShell(name, xmGrabShellWidgetClass, parent, al, ac);
Packit b099d7
}
Packit b099d7