18108eb18Smrg/* $Xorg: popup.c,v 1.4 2001/02/09 02:06:01 xorgcvs Exp $ */
28108eb18Smrg
38108eb18Smrg/*
48108eb18Smrg
58108eb18SmrgCopyright 1994, 1998  The Open Group
68108eb18Smrg
78108eb18SmrgPermission to use, copy, modify, distribute, and sell this software and its
88108eb18Smrgdocumentation for any purpose is hereby granted without fee, provided that
98108eb18Smrgthe above copyright notice appear in all copies and that both that
108108eb18Smrgcopyright notice and this permission notice appear in supporting
118108eb18Smrgdocumentation.
128108eb18Smrg
138108eb18SmrgThe above copyright notice and this permission notice shall be included
148108eb18Smrgin all copies or substantial portions of the Software.
158108eb18Smrg
168108eb18SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
178108eb18SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
188108eb18SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
198108eb18SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
208108eb18SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
218108eb18SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
228108eb18SmrgOTHER DEALINGS IN THE SOFTWARE.
238108eb18Smrg
248108eb18SmrgExcept as contained in this notice, the name of The Open Group shall
258108eb18Smrgnot be used in advertising or otherwise to promote the sale, use or
268108eb18Smrgother dealings in this Software without prior written authorization
278108eb18Smrgfrom The Open Group.
288108eb18Smrg
298108eb18Smrg*/
308108eb18Smrg/* $XFree86: xc/programs/xsm/popup.c,v 1.4 2001/01/17 23:46:30 dawes Exp $ */
318108eb18Smrg
328108eb18Smrg#include "xsm.h"
338108eb18Smrg#include <X11/Shell.h>
348108eb18Smrg#include "popup.h"
358108eb18Smrg
368108eb18Smrg
378108eb18Smrgvoid
388108eb18SmrgPopupPopup(Widget parent, Widget popup, Bool transient, Bool first_time,
395977a007Smrg    int offset_x, int offset_y, const _XtString delAction)
408108eb18Smrg{
418108eb18Smrg    if (!transient && !first_time)
428108eb18Smrg    {
438108eb18Smrg	/*
448108eb18Smrg	 * For non-transient windows, if this isn't the first time
458108eb18Smrg	 * it's being popped up, just pop it up in the old position.
468108eb18Smrg	 */
478108eb18Smrg
488108eb18Smrg	XtPopup (popup, XtGrabNone);
498108eb18Smrg	return;
508108eb18Smrg    }
518108eb18Smrg    else
528108eb18Smrg    {
538108eb18Smrg	Position parent_x, parent_y;
548108eb18Smrg	Position root_x, root_y;
558108eb18Smrg	Position popup_x, popup_y;
568108eb18Smrg	Dimension parent_width, parent_height, parent_border;
578108eb18Smrg	Dimension popup_width, popup_height, popup_border;
588108eb18Smrg	char geom[16];
598108eb18Smrg	Bool repos = 0;
608108eb18Smrg
618108eb18Smrg	/*
628108eb18Smrg	 * The window we pop up must be visible on the screen.  We first
638108eb18Smrg	 * try to position it at the desired location (relative to the
648108eb18Smrg	 * parent widget).  Once we are able to compute the popup's
658108eb18Smrg	 * geometry (after it's realized), we can determine if we need
668108eb18Smrg	 * to reposition it.
678108eb18Smrg	 */
688108eb18Smrg
698108eb18Smrg	XtVaGetValues (parent,
708108eb18Smrg	    XtNx, &parent_x,
718108eb18Smrg	    XtNy, &parent_y,
728108eb18Smrg	    XtNwidth, &parent_width,
738108eb18Smrg	    XtNheight, &parent_height,
748108eb18Smrg	    XtNborderWidth, &parent_border,
758108eb18Smrg	    NULL);
768108eb18Smrg
778108eb18Smrg	XtTranslateCoords (parent, parent_x, parent_y, &root_x, &root_y);
788108eb18Smrg
798108eb18Smrg	popup_x = root_x + offset_x;
808108eb18Smrg	popup_y = root_y + offset_y;
818108eb18Smrg
828108eb18Smrg	if (transient)
838108eb18Smrg	{
848108eb18Smrg	    XtVaSetValues (popup,
858108eb18Smrg	        XtNx, popup_x,
868108eb18Smrg	        XtNy, popup_y,
878108eb18Smrg                NULL);
888108eb18Smrg	}
898108eb18Smrg	else
908108eb18Smrg	{
911a650d1eSmrg	    snprintf (geom, sizeof(geom), "+%d+%d", popup_x, popup_y);
928108eb18Smrg
938108eb18Smrg	    XtVaSetValues (popup,
948108eb18Smrg	        XtNgeometry, geom,
958108eb18Smrg                NULL);
968108eb18Smrg	}
978108eb18Smrg
988108eb18Smrg	if (first_time)
998108eb18Smrg	{
1008108eb18Smrg	    /*
1018108eb18Smrg	     * Realize it for the first time
1028108eb18Smrg	     */
1038108eb18Smrg
1048108eb18Smrg	    XtRealizeWidget (popup);
1058108eb18Smrg
1068108eb18Smrg
1078108eb18Smrg	    /*
1088108eb18Smrg	     * Set support for WM_DELETE_WINDOW
1098108eb18Smrg	     */
1108108eb18Smrg
1118108eb18Smrg	    (void) SetWM_DELETE_WINDOW (popup, delAction);
1128108eb18Smrg	}
1138108eb18Smrg
1148108eb18Smrg	/*
1158108eb18Smrg	 * Now make sure it's visible.
1168108eb18Smrg	 */
1178108eb18Smrg
1188108eb18Smrg	XtVaGetValues (popup,
1198108eb18Smrg	    XtNwidth, &popup_width,
1208108eb18Smrg	    XtNheight, &popup_height,
1218108eb18Smrg	    XtNborderWidth, &popup_border,
1228108eb18Smrg	    NULL);
1238108eb18Smrg
1248108eb18Smrg	popup_border <<= 1;
1258108eb18Smrg
1268108eb18Smrg	if ((int) (popup_x + popup_width + popup_border) >
1278108eb18Smrg	    WidthOfScreen (XtScreen (topLevel)))
1288108eb18Smrg	{
1298108eb18Smrg	    popup_x = WidthOfScreen (XtScreen (topLevel)) -
1308108eb18Smrg		popup_width - popup_border - parent_width - parent_border;
1318108eb18Smrg
1328108eb18Smrg	    repos = 1;
1338108eb18Smrg	}
1348108eb18Smrg
1358108eb18Smrg	if ((int) (popup_y + popup_height + popup_border) >
1368108eb18Smrg	    HeightOfScreen (XtScreen (topLevel)))
1378108eb18Smrg	{
1388108eb18Smrg	    popup_y = HeightOfScreen (XtScreen (topLevel)) -
1398108eb18Smrg		popup_height - popup_border - parent_height - parent_border;
1408108eb18Smrg
1418108eb18Smrg	    repos = 1;
1428108eb18Smrg	}
1438108eb18Smrg
1448108eb18Smrg	if (repos)
1458108eb18Smrg	{
1468108eb18Smrg	    if (transient)
1478108eb18Smrg	    {
1488108eb18Smrg		XtVaSetValues (popup,
1498108eb18Smrg	            XtNx, popup_x,
1508108eb18Smrg	            XtNy, popup_y,
1518108eb18Smrg                    NULL);
1528108eb18Smrg	    }
1538108eb18Smrg	    else
1548108eb18Smrg	    {
1558108eb18Smrg		/*
1568108eb18Smrg		 * The only way we can reposition a non-transient
1578108eb18Smrg		 * is by unrealizing it, setting the position, then
1588108eb18Smrg		 * doing a realize.
1598108eb18Smrg		 */
1608108eb18Smrg
1618108eb18Smrg		XtUnrealizeWidget (popup);
1628108eb18Smrg
1631a650d1eSmrg		snprintf (geom, sizeof(geom), "+%d+%d", popup_x, popup_y);
1648108eb18Smrg
1658108eb18Smrg		XtVaSetValues (popup,
1668108eb18Smrg	            XtNgeometry, geom,
1678108eb18Smrg                    NULL);
1688108eb18Smrg
1698108eb18Smrg		XtRealizeWidget (popup);
1708108eb18Smrg
1718108eb18Smrg		(void) SetWM_DELETE_WINDOW (popup, delAction);
1728108eb18Smrg	    }
1738108eb18Smrg	}
1748108eb18Smrg
1758108eb18Smrg	XtPopup (popup, XtGrabNone);
1768108eb18Smrg    }
1778108eb18Smrg}
178