Geometry.c revision 444c061a
1/* $Xorg: Geometry.c,v 1.5 2001/02/09 02:03:54 xorgcvs Exp $ */
2
3/***********************************************************
4Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts
5Copyright 1993 by Sun Microsystems, Inc. Mountain View, CA.
6
7                        All Rights Reserved
8
9Permission to use, copy, modify, and distribute this software and its
10documentation for any purpose and without fee is hereby granted,
11provided that the above copyright notice appear in all copies and that
12both that copyright notice and this permission notice appear in
13supporting documentation, and that the names of Digital or Sun not be
14used in advertising or publicity pertaining to distribution of the
15software without specific, written prior permission.
16
17DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
18ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
19DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
20ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
21WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
22ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23SOFTWARE.
24
25SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
26INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
27NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
28ABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
29ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
30PROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
31OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
32THE USE OR PERFORMANCE OF THIS SOFTWARE.
33
34******************************************************************/
35
36/*
37
38Copyright 1987, 1988, 1994, 1998  The Open Group
39
40Permission to use, copy, modify, distribute, and sell this software and its
41documentation for any purpose is hereby granted without fee, provided that
42the above copyright notice appear in all copies and that both that
43copyright notice and this permission notice appear in supporting
44documentation.
45
46The above copyright notice and this permission notice shall be included in
47all copies or substantial portions of the Software.
48
49THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
52OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
53AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
54CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
55
56Except as contained in this notice, the name of The Open Group shall not be
57used in advertising or otherwise to promote the sale, use or other dealings
58in this Software without prior written authorization from The Open Group.
59
60*/
61/* $XFree86: xc/lib/Xt/Geometry.c,v 1.12 2001/12/14 19:56:15 dawes Exp $ */
62
63#ifdef HAVE_CONFIG_H
64#include <config.h>
65#endif
66#include "IntrinsicI.h"
67#include "ShellP.h"
68#include "ShellI.h"
69
70static void ClearRectObjAreas(
71    RectObj r,
72    XWindowChanges* old)
73{
74    Widget pw = _XtWindowedAncestor((Widget)r);
75    int bw2;
76
77    bw2 = old->border_width << 1;
78    XClearArea( XtDisplay(pw), XtWindow(pw),
79		old->x, old->y,
80		old->width + bw2, old->height + bw2,
81		TRUE );
82
83    bw2 = r->rectangle.border_width << 1;
84    XClearArea( XtDisplay(pw), XtWindow(pw),
85		(int)r->rectangle.x, (int)r->rectangle.y,
86		(unsigned int)(r->rectangle.width + bw2),
87	        (unsigned int)(r->rectangle.height + bw2),
88		TRUE );
89}
90
91/*
92 * Internal function used by XtMakeGeometryRequest and XtSetValues.
93 * Returns more data than the public interface.  Does not convert
94 * XtGeometryDone to XtGeometryYes.
95 *
96 * clear_rect_obj - *** RETURNED ***
97 *		    TRUE if the rect obj has been cleared, false otherwise.
98 */
99
100XtGeometryResult
101_XtMakeGeometryRequest (
102    Widget widget,
103    XtWidgetGeometry *request,
104    XtWidgetGeometry *reply,
105    Boolean * clear_rect_obj)
106{
107    XtWidgetGeometry    junk;
108    XtGeometryHandler manager = (XtGeometryHandler) NULL;
109    XtGeometryResult returnCode;
110    Widget parent = widget->core.parent;
111    Boolean managed, parentRealized, rgm = False;
112    XtConfigureHookDataRec req;
113    Widget hookobj;
114
115    *clear_rect_obj = FALSE;
116
117    CALLGEOTAT(_XtGeoTrace(widget,
118	"\"%s\" is making a %sgeometry request to its parent \"%s\".\n",
119		   XtName(widget),
120		   ((request->request_mode & XtCWQueryOnly))? "query only ":"",
121		   (XtParent(widget))?XtName(XtParent(widget)):"Root"));
122    CALLGEOTAT(_XtGeoTab(1));
123
124    if (XtIsShell(widget)) {
125	ShellClassExtension ext;
126	LOCK_PROCESS;
127	for (ext = (ShellClassExtension)((ShellWidgetClass)XtClass(widget))
128		   ->shell_class.extension;
129	     ext != NULL && ext->record_type != NULLQUARK;
130	     ext = (ShellClassExtension)ext->next_extension);
131
132	if (ext != NULL) {
133	    if (  ext->version == XtShellExtensionVersion
134		  && ext->record_size == sizeof(ShellClassExtensionRec)) {
135		manager = ext->root_geometry_manager;
136		rgm = True;
137	    } else {
138		String params[1];
139		Cardinal num_params = 1;
140		params[0] = XtClass(widget)->core_class.class_name;
141		XtAppErrorMsg(XtWidgetToApplicationContext(widget),
142		     "invalidExtension", "xtMakeGeometryRequest",
143		     XtCXtToolkitError,
144		     "widget class %s has invalid ShellClassExtension record",
145		     params, &num_params);
146	    }
147	} else {
148	    XtAppErrorMsg(XtWidgetToApplicationContext(widget),
149			  "internalError", "xtMakeGeometryRequest",
150			  XtCXtToolkitError,
151			  "internal error; ShellClassExtension is NULL",
152			  NULL, NULL);
153	}
154	managed = True;
155	parentRealized = TRUE;
156	UNLOCK_PROCESS;
157    } else /* not shell */ {
158	if (parent == NULL)
159	    XtAppErrorMsg(XtWidgetToApplicationContext(widget),
160			  "invalidParent","xtMakeGeometryRequest",
161			  XtCXtToolkitError,
162			  "non-shell has no parent in XtMakeGeometryRequest",
163			  (String *)NULL, (Cardinal *)NULL);
164
165	managed = XtIsManaged(widget);
166	parentRealized = XtIsRealized(parent);
167	if (XtIsComposite(parent))
168	{
169	    LOCK_PROCESS;
170	    manager = ((CompositeWidgetClass) (parent->core.widget_class))
171		      ->composite_class.geometry_manager;
172	    UNLOCK_PROCESS;
173	}
174    }
175
176#if 0
177    /*
178     * The Xt spec says that these conditions must generate
179     * error messages (not warnings), but many Xt applications
180     * and toolkits (including parts of Xaw, Motif and Netscape)
181     * depend on the previous Xt behaviour.  Thus, these tests
182     * should probably remain disabled.
183     */
184    if (parentRealized && managed) {
185	if (parent && !XtIsComposite(parent))
186	{
187	    /*
188	     * This shouldn't ever happen, we only test for this to pass
189	     * VSW5.  Normally managing the widget will catch this, but VSW5
190	     * does some really screwy stuff to get here.
191	     */
192	    XtAppErrorMsg(XtWidgetToApplicationContext(widget),
193			  "invalidParent", "xtMakeGeometryRequest",
194			  XtCXtToolkitError,
195			  "XtMakeGeometryRequest - parent not composite",
196			  (String *)NULL, (Cardinal *)NULL);
197	}
198	else if (manager == (XtGeometryHandler) NULL)
199	{
200	    XtAppErrorMsg(XtWidgetToApplicationContext(widget),
201			  "invalidGeometryManager","xtMakeGeometryRequest",
202			  XtCXtToolkitError,
203			  "XtMakeGeometryRequest - parent has no geometry manager",
204			  (String *)NULL, (Cardinal *)NULL);
205	}
206    }
207#else
208    if (!manager)
209	managed = False;
210#endif
211
212    if (widget->core.being_destroyed) {
213	CALLGEOTAT(_XtGeoTab(-1));
214	CALLGEOTAT(_XtGeoTrace(widget,
215		       "It is being destroyed, just return XtGeometryNo.\n"));
216	return XtGeometryNo;
217    }
218
219    /* see if requesting anything to change */
220    req.changeMask = 0;
221    if (request->request_mode & CWStackMode
222	&& request->stack_mode != XtSMDontChange) {
223	    req.changeMask |= CWStackMode;
224	    CALLGEOTAT(_XtGeoTrace(widget,
225				   "Asking for a change in StackMode!\n"));
226	    if (request->request_mode & CWSibling) {
227		XtCheckSubclass(request->sibling, rectObjClass,
228				"XtMakeGeometryRequest");
229		req.changeMask |= CWSibling;
230	    }
231    }
232    if (request->request_mode & CWX
233	&& widget->core.x != request->x) {
234	CALLGEOTAT(_XtGeoTrace(widget,
235			       "Asking for a change in x: from %d to %d.\n",
236			       widget->core.x, request->x));
237	req.changeMask |= CWX;
238    }
239    if (request->request_mode & CWY
240	&& widget->core.y != request->y) {
241	CALLGEOTAT(_XtGeoTrace(widget,
242			       "Asking for a change in y: from %d to %d.\n",
243			       widget->core.y, request->y));
244	req.changeMask |= CWY;
245    }
246    if (request->request_mode & CWWidth
247	&& widget->core.width != request->width) {
248	CALLGEOTAT(_XtGeoTrace(widget,"Asking for a change in width: from %d to %d.\n",
249		       widget->core.width, request->width));
250	req.changeMask |= CWWidth;
251    }
252    if (request->request_mode & CWHeight
253	&& widget->core.height != request->height) {
254	CALLGEOTAT(_XtGeoTrace(widget,
255			    "Asking for a change in height: from %d to %d.\n",
256			       widget->core.height, request->height));
257	req.changeMask |= CWHeight;
258    }
259    if (request->request_mode & CWBorderWidth
260	&& widget->core.border_width != request->border_width){
261	CALLGEOTAT(_XtGeoTrace(widget,
262		       "Asking for a change in border_width: from %d to %d.\n",
263		       widget->core.border_width, request->border_width));
264	req.changeMask |= CWBorderWidth;
265    }
266    if (! req.changeMask) {
267	CALLGEOTAT(_XtGeoTrace(widget,
268		       "Asking for nothing new,\n"));
269	CALLGEOTAT(_XtGeoTab(-1));
270	CALLGEOTAT(_XtGeoTrace(widget,
271		       "just return XtGeometryYes.\n"));
272	return XtGeometryYes;
273    }
274    req.changeMask |= (request->request_mode & XtCWQueryOnly);
275
276    if ( !(req.changeMask & XtCWQueryOnly) && XtIsRealized(widget) ) {
277	/* keep record of the current geometry so we know what's changed */
278	req.changes.x = widget->core.x ;
279	req.changes.y = widget->core.y ;
280	req.changes.width = widget->core.width ;
281	req.changes.height = widget->core.height ;
282	req.changes.border_width = widget->core.border_width ;
283    }
284
285    if (!managed || !parentRealized) {
286	CALLGEOTAT(_XtGeoTrace(widget,
287			       "Not Managed or Parent not realized.\n"));
288	/* Don't get parent's manager involved--assume the answer is yes */
289	if (req.changeMask & XtCWQueryOnly) {
290	    /* He was just asking, don't change anything, just tell him yes */
291	    CALLGEOTAT(_XtGeoTrace(widget,"QueryOnly request\n"));
292	    CALLGEOTAT(_XtGeoTab(-1));
293	    CALLGEOTAT(_XtGeoTrace(widget,"just return XtGeometryYes.\n"));
294	    return XtGeometryYes;
295	} else {
296	    CALLGEOTAT(_XtGeoTrace(widget,
297				   "Copy values from request to widget.\n"));
298	    /* copy values from request to widget */
299	    if (request->request_mode & CWX)
300		widget->core.x = request->x;
301	    if (request->request_mode & CWY)
302		widget->core.y = request->y;
303	    if (request->request_mode & CWWidth)
304		widget->core.width = request->width;
305	    if (request->request_mode & CWHeight)
306		widget->core.height = request->height;
307	    if (request->request_mode & CWBorderWidth)
308		widget->core.border_width = request->border_width;
309	    if (!parentRealized) {
310		CALLGEOTAT(_XtGeoTab(-1));
311		CALLGEOTAT(_XtGeoTrace(widget,"and return XtGeometryYes.\n"));
312		return XtGeometryYes;
313	    }
314	    else returnCode = XtGeometryYes;
315	}
316    } else {
317	/* go ask the widget's geometry manager */
318	CALLGEOTAT(_XtGeoTrace(widget,
319			       "Go ask the parent geometry manager.\n"));
320	if (reply == (XtWidgetGeometry *) NULL) {
321	    returnCode = (*manager)(widget, request, &junk);
322	} else {
323	    returnCode = (*manager)(widget, request, reply);
324	}
325    }
326
327    /*
328     * If Unrealized, not a XtGeometryYes, or a query-only then we are done.
329     */
330
331    if ((returnCode != XtGeometryYes) ||
332	(req.changeMask & XtCWQueryOnly) || !XtIsRealized(widget)) {
333
334#ifdef XT_GEO_TATTLER
335	switch(returnCode){
336	case XtGeometryNo:
337	    CALLGEOTAT(_XtGeoTab(-1));
338	    CALLGEOTAT(_XtGeoTrace(widget,"\"%s\" returns XtGeometryNo.\n",
339			  (XtParent(widget))?XtName(XtParent(widget)):"Root"));
340            /* check for no change */
341            break ;
342	case XtGeometryDone:
343	    CALLGEOTAT(_XtGeoTab(-1));
344	    CALLGEOTAT(_XtGeoTrace(widget,"\"%s\" returns XtGeometryDone.\n",
345		        (XtParent(widget))?XtName(XtParent(widget)):"Root"));
346            /* check for no change in queryonly */
347            break ;
348	case XtGeometryAlmost:
349	    CALLGEOTAT(_XtGeoTab(-1));
350	    CALLGEOTAT(_XtGeoTrace(widget,"\"%s\" returns XtGeometryAlmost.\n",
351			 (XtParent(widget))?XtName(XtParent(widget)):"Root"));
352	    CALLGEOTAT(_XtGeoTab(1));
353	    CALLGEOTAT(_XtGeoTrace(widget,"Proposal: width %d height %d.\n",
354			   (reply)?reply->width:junk.width,
355			   (reply)?reply->height:junk.height));
356	    CALLGEOTAT(_XtGeoTab(-1));
357
358            /* check for no change */
359            break ;
360	case XtGeometryYes:
361	    if (req.changeMask & XtCWQueryOnly) {
362		CALLGEOTAT(_XtGeoTrace(widget,
363				"QueryOnly specified, no configuration.\n"));
364	    }
365            if (!XtIsRealized(widget)) {
366		CALLGEOTAT(_XtGeoTrace(widget,
367				 "\"%s\" not realized, no configuration.\n",
368				 XtName(widget)));
369	    }
370	    CALLGEOTAT(_XtGeoTab(-1));
371            CALLGEOTAT(_XtGeoTrace(widget,"\"%s\" returns XtGeometryYes.\n",
372                         (XtParent(widget))?XtName(XtParent(widget)):"Root"));
373	    break ;
374	}
375#endif
376	return returnCode;
377    }
378
379    CALLGEOTAT(_XtGeoTab(-1));
380    CALLGEOTAT(_XtGeoTrace(widget,"\"%s\" returns XtGeometryYes.\n",
381		   (XtParent(widget))?XtName(XtParent(widget)):"Root"));
382
383    if (XtIsWidget(widget)) {	/* reconfigure the window (if needed) */
384
385	if (rgm) return returnCode;
386
387	if (req.changes.x != widget->core.x) {
388 	    req.changeMask |= CWX;
389 	    req.changes.x = widget->core.x;
390	    CALLGEOTAT(_XtGeoTrace(widget,
391				   "x changing to %d\n",widget->core.x));
392 	}
393 	if (req.changes.y != widget->core.y) {
394 	    req.changeMask |= CWY;
395 	    req.changes.y = widget->core.y;
396	    CALLGEOTAT(_XtGeoTrace(widget,
397				   "y changing to %d\n",widget->core.y));
398 	}
399 	if (req.changes.width != widget->core.width) {
400 	    req.changeMask |= CWWidth;
401 	    req.changes.width = widget->core.width;
402	    CALLGEOTAT(_XtGeoTrace(widget,
403				 "width changing to %d\n",widget->core.width));
404 	}
405 	if (req.changes.height != widget->core.height) {
406 	    req.changeMask |= CWHeight;
407 	    req.changes.height = widget->core.height;
408	    CALLGEOTAT(_XtGeoTrace(widget,
409                               "height changing to %d\n",widget->core.height));
410 	}
411 	if (req.changes.border_width != widget->core.border_width) {
412 	    req.changeMask |= CWBorderWidth;
413 	    req.changes.border_width = widget->core.border_width;
414	    CALLGEOTAT(_XtGeoTrace(widget,
415				   "border_width changing to %d\n",
416				   widget->core.border_width));
417 	}
418	if (req.changeMask & CWStackMode) {
419	    req.changes.stack_mode = request->stack_mode;
420	    CALLGEOTAT(_XtGeoTrace(widget,"stack_mode changing\n"));
421	    if (req.changeMask & CWSibling) {
422		if (XtIsWidget(request->sibling))
423		    req.changes.sibling = XtWindow(request->sibling);
424		else
425		    req.changeMask &= ~(CWStackMode | CWSibling);
426	    }
427	}
428
429#ifdef XT_GEO_TATTLER
430        if (req.changeMask) {
431	    CALLGEOTAT(_XtGeoTrace(widget,
432				   "XConfigure \"%s\"'s window.\n",
433				   XtName(widget)));
434	} else {
435	    CALLGEOTAT(_XtGeoTrace(widget,
436			     "No window configuration needed for \"%s\".\n",
437			     XtName(widget)));
438	}
439#endif
440
441	XConfigureWindow(XtDisplay(widget), XtWindow(widget),
442			 req.changeMask, &req.changes);
443    }
444    else {			/* RectObj child of realized Widget */
445	*clear_rect_obj = TRUE;
446	CALLGEOTAT(_XtGeoTrace(widget,
447			       "ClearRectObj on \"%s\".\n",XtName(widget)));
448
449	ClearRectObjAreas((RectObj)widget, &req.changes);
450    }
451    hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));;
452    if (XtHasCallbacks(hookobj, XtNconfigureHook) == XtCallbackHasSome) {
453	req.type = XtHconfigure;
454	req.widget = widget;
455	XtCallCallbackList(hookobj,
456		((HookObject)hookobj)->hooks.confighook_callbacks,
457		(XtPointer)&req);
458    }
459
460    return returnCode;
461} /* _XtMakeGeometryRequest */
462
463
464/* Public routines */
465
466XtGeometryResult XtMakeGeometryRequest (
467    Widget         widget,
468    XtWidgetGeometry *request,
469    XtWidgetGeometry *reply)
470{
471    Boolean junk;
472    XtGeometryResult r;
473    XtGeometryHookDataRec call_data;
474    Widget hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
475    WIDGET_TO_APPCON(widget);
476
477    LOCK_APP(app);
478    if (XtHasCallbacks(hookobj, XtNgeometryHook) == XtCallbackHasSome) {
479	call_data.type = XtHpreGeometry;
480	call_data.widget = widget;
481	call_data.request = request;
482	XtCallCallbackList(hookobj,
483		((HookObject)hookobj)->hooks.geometryhook_callbacks,
484		(XtPointer)&call_data);
485	call_data.result = r =
486	    _XtMakeGeometryRequest(widget, request, reply, &junk);
487	call_data.type = XtHpostGeometry;
488	call_data.reply = reply;
489	XtCallCallbackList(hookobj,
490		((HookObject)hookobj)->hooks.geometryhook_callbacks,
491		(XtPointer)&call_data);
492    } else {
493	r = _XtMakeGeometryRequest(widget, request, reply, &junk);
494    }
495    UNLOCK_APP(app);
496
497    return ((r == XtGeometryDone) ? XtGeometryYes : r);
498}
499
500XtGeometryResult
501XtMakeResizeRequest(
502    Widget	widget,
503    _XtDimension width,
504    _XtDimension height,
505    Dimension	*replyWidth,
506    Dimension	*replyHeight)
507{
508    XtWidgetGeometry request, reply;
509    XtGeometryResult r;
510    XtGeometryHookDataRec call_data;
511    Boolean junk;
512    Widget hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
513    WIDGET_TO_APPCON(widget);
514
515    LOCK_APP(app);
516    request.request_mode = CWWidth | CWHeight;
517    request.width = width;
518    request.height = height;
519
520    if (XtHasCallbacks(hookobj, XtNgeometryHook) == XtCallbackHasSome) {
521	call_data.type = XtHpreGeometry;
522	call_data.widget = widget;
523	call_data.request = &request;
524	XtCallCallbackList(hookobj,
525		((HookObject)hookobj)->hooks.geometryhook_callbacks,
526		(XtPointer)&call_data);
527	call_data.result = r =
528	    _XtMakeGeometryRequest(widget, &request, &reply, &junk);
529	call_data.type = XtHpostGeometry;
530	call_data.reply = &reply;
531	XtCallCallbackList(hookobj,
532		((HookObject)hookobj)->hooks.geometryhook_callbacks,
533		(XtPointer)&call_data);
534    } else {
535	r = _XtMakeGeometryRequest(widget, &request, &reply, &junk);
536    }
537    if (replyWidth != NULL) {
538	if (r == XtGeometryAlmost && reply.request_mode & CWWidth)
539	    *replyWidth = reply.width;
540	else
541	    *replyWidth = width;
542    }
543    if (replyHeight != NULL) {
544	if (r == XtGeometryAlmost && reply.request_mode & CWHeight)
545	    *replyHeight = reply.height;
546	else
547	    *replyHeight = height;
548    }
549    UNLOCK_APP(app);
550    return ((r == XtGeometryDone) ? XtGeometryYes : r);
551} /* XtMakeResizeRequest */
552
553void XtResizeWindow(
554    Widget w)
555{
556    XtConfigureHookDataRec req;
557    Widget hookobj;
558    WIDGET_TO_APPCON(w);
559
560    LOCK_APP(app);
561    if (XtIsRealized(w)) {
562	req.changes.width = w->core.width;
563	req.changes.height = w->core.height;
564	req.changes.border_width = w->core.border_width;
565	req.changeMask = CWWidth | CWHeight | CWBorderWidth;
566	XConfigureWindow(XtDisplay(w), XtWindow(w),
567	    (unsigned) req.changeMask, &req.changes);
568	hookobj = XtHooksOfDisplay(XtDisplayOfObject(w));;
569	if (XtHasCallbacks(hookobj, XtNconfigureHook) == XtCallbackHasSome) {
570	    req.type = XtHconfigure;
571	    req.widget = w;
572	    XtCallCallbackList(hookobj,
573			((HookObject)hookobj)->hooks.confighook_callbacks,
574			(XtPointer)&req);
575	}
576    }
577    UNLOCK_APP(app);
578} /* XtResizeWindow */
579
580void XtResizeWidget(
581    Widget w,
582    _XtDimension width,
583    _XtDimension height,
584    _XtDimension borderWidth)
585{
586    XtConfigureWidget(w, w->core.x, w->core.y, width, height, borderWidth);
587} /* XtResizeWidget */
588
589void XtConfigureWidget(
590    Widget w,
591    _XtPosition x,
592    _XtPosition y,
593    _XtDimension width,
594    _XtDimension height,
595    _XtDimension borderWidth)
596{
597    XtConfigureHookDataRec req;
598    Widget hookobj;
599    XWindowChanges old;
600    WIDGET_TO_APPCON(w);
601
602    CALLGEOTAT(_XtGeoTrace(w,
603                   "\"%s\" is being configured by its parent \"%s\"\n",
604		   XtName(w),
605		   (XtParent(w))?XtName(XtParent(w)):"Root"));
606    CALLGEOTAT(_XtGeoTab(1));
607
608    LOCK_APP(app);
609    req.changeMask = 0;
610    if ((old.x = w->core.x) != x) {
611	CALLGEOTAT(_XtGeoTrace(w,"x move from %d to %d\n",w->core.x, x));
612	req.changes.x = w->core.x = x;
613	req.changeMask |= CWX;
614    }
615
616    if ((old.y = w->core.y) != y) {
617	CALLGEOTAT(_XtGeoTrace(w,"y move from %d to %d\n",w->core.y, y));
618	req.changes.y = w->core.y = y;
619	req.changeMask |= CWY;
620    }
621
622    if ((old.width = w->core.width) != width) {
623	CALLGEOTAT(_XtGeoTrace(w,
624			 "width move from %d to %d\n",w->core.width, width));
625	req.changes.width = w->core.width = width;
626	req.changeMask |= CWWidth;
627    }
628
629    if ((old.height = w->core.height) != height) {
630	CALLGEOTAT(_XtGeoTrace(w,
631		       "height move from %d to %d\n",w->core.height, height));
632	req.changes.height = w->core.height = height;
633	req.changeMask |= CWHeight;
634    }
635
636    if ((old.border_width = w->core.border_width) != borderWidth) {
637	CALLGEOTAT(_XtGeoTrace(w,"border_width move from %d to %d\n",
638		    w->core.border_width,borderWidth ));
639	req.changes.border_width = w->core.border_width = borderWidth;
640	req.changeMask |= CWBorderWidth;
641    }
642
643    if (req.changeMask != 0) {
644	if (XtIsRealized(w)) {
645	    if (XtIsWidget(w)) {
646		CALLGEOTAT(_XtGeoTrace(w,
647                                  "XConfigure \"%s\"'s window\n",XtName(w)));
648		XConfigureWindow(XtDisplay(w), XtWindow(w),
649				 req.changeMask, &req.changes);
650	    } else {
651		CALLGEOTAT(_XtGeoTrace(w,
652			       "ClearRectObj called on \"%s\"\n",XtName(w)));
653		ClearRectObjAreas((RectObj)w, &old);
654	    }
655	}
656	hookobj = XtHooksOfDisplay(XtDisplayOfObject(w));;
657	if (XtHasCallbacks(hookobj, XtNconfigureHook) == XtCallbackHasSome) {
658	    req.type = XtHconfigure;
659	    req.widget = w;
660	    XtCallCallbackList(hookobj,
661			((HookObject)hookobj)->hooks.confighook_callbacks,
662			(XtPointer)&req);
663	}
664	{
665	XtWidgetProc resize;
666
667	LOCK_PROCESS;
668	resize = XtClass(w)->core_class.resize;
669	UNLOCK_PROCESS;
670	if ((req.changeMask & (CWWidth | CWHeight)) &&
671	    resize != (XtWidgetProc) NULL) {
672	    CALLGEOTAT(_XtGeoTrace(w,"Resize proc is called.\n"));
673	    (*resize)(w);
674	 }
675	}
676    } else {
677	CALLGEOTAT(_XtGeoTrace(w,"No change in configuration\n"));
678    }
679
680    CALLGEOTAT(_XtGeoTab(-1));
681    UNLOCK_APP(app);
682} /* XtConfigureWidget */
683
684void XtMoveWidget(
685    Widget w,
686    _XtPosition x,
687    _XtPosition y)
688{
689    XtConfigureWidget(w, x, y, w->core.width, w->core.height,
690		      w->core.border_width);
691} /* XtMoveWidget */
692
693void XtTranslateCoords(
694    register Widget w,
695    _XtPosition x,
696    _XtPosition y,
697    register Position *rootx,	/* return */
698    register Position *rooty)	/* return */
699{
700    Position garbagex, garbagey;
701    XtAppContext app = XtWidgetToApplicationContext(w);
702
703    LOCK_APP(app);
704    if (rootx == NULL) rootx = &garbagex;
705    if (rooty == NULL) rooty = &garbagey;
706
707    *rootx = x;
708    *rooty = y;
709
710    for (; w != NULL && ! XtIsShell(w); w = w->core.parent) {
711	*rootx += w->core.x + w->core.border_width;
712	*rooty += w->core.y + w->core.border_width;
713    }
714
715    if (w == NULL)
716        XtAppWarningMsg(app,
717		"invalidShell","xtTranslateCoords",XtCXtToolkitError,
718                "Widget has no shell ancestor",
719		(String *)NULL, (Cardinal *)NULL);
720    else {
721	Position x, y;
722	_XtShellGetCoordinates( w, &x, &y );
723	*rootx += x + w->core.border_width;
724	*rooty += y + w->core.border_width;
725    }
726    UNLOCK_APP(app);
727}
728
729XtGeometryResult XtQueryGeometry(
730    Widget widget,
731    register XtWidgetGeometry *intended, /* parent's changes; may be NULL */
732    XtWidgetGeometry *reply)	/* child's preferred geometry; never NULL */
733{
734    XtWidgetGeometry null_intended;
735    XtGeometryHandler query;
736    XtGeometryResult result;
737    WIDGET_TO_APPCON(widget);
738
739    CALLGEOTAT(_XtGeoTrace(widget,
740		     "\"%s\" is asking its preferred geometry to \"%s\".\n",
741		     (XtParent(widget))?XtName(XtParent(widget)):"Root",
742		     XtName(widget)));
743    CALLGEOTAT(_XtGeoTab(1));
744
745    LOCK_APP(app);
746    LOCK_PROCESS;
747    query = XtClass(widget)->core_class.query_geometry;
748    UNLOCK_PROCESS;
749    reply->request_mode = 0;
750    if (query != NULL) {
751	if (intended == NULL) {
752	    null_intended.request_mode = 0;
753	    intended = &null_intended;
754#ifdef XT_GEO_TATTLER
755	    CALLGEOTAT(_XtGeoTrace(widget,"without any constraint.\n"));
756	} else {
757	    CALLGEOTAT(_XtGeoTrace(widget,
758				   "with the following constraints:\n"));
759
760	    if (intended->request_mode & CWX) {
761		CALLGEOTAT(_XtGeoTrace(widget," x = %d\n",intended->x));
762	    }
763	    if (intended->request_mode & CWY) {
764		CALLGEOTAT(_XtGeoTrace(widget," y = %d\n",intended->y));
765	    }
766	    if (intended->request_mode & CWWidth) {
767		CALLGEOTAT(_XtGeoTrace(widget,
768				       " width = %d\n",intended->width));
769	    }
770	    if (intended->request_mode & CWHeight) {
771		CALLGEOTAT(_XtGeoTrace(widget,
772				       " height = %d\n",intended->height));
773	    }
774	    if (intended->request_mode & CWBorderWidth) {
775		CALLGEOTAT(_XtGeoTrace(widget,
776			       " border_width = %d\n",intended->border_width));
777	    }
778#endif
779	}
780
781	result = (*query) (widget, intended, reply);
782    }
783    else {
784	CALLGEOTAT(_XtGeoTrace(widget,"\"%s\" has no QueryGeometry proc, return the current state\n",XtName(widget)));
785
786	result = XtGeometryYes;
787    }
788
789#ifdef XT_GEO_TATTLER
790#define FillIn(mask, field) \
791	if (!(reply->request_mode & mask)) {\
792	      reply->field = widget->core.field;\
793	      _XtGeoTrace(widget," using core %s = %d.\n","field",\
794			                               widget->core.field);\
795	} else {\
796	      _XtGeoTrace(widget," replied %s = %d\n","field",\
797			                           reply->field);\
798	}
799#else
800#define FillIn(mask, field) \
801	if (!(reply->request_mode & mask)) reply->field = widget->core.field;
802#endif
803
804    FillIn(CWX, x);
805    FillIn(CWY, y);
806    FillIn(CWWidth, width);
807    FillIn(CWHeight, height);
808    FillIn(CWBorderWidth, border_width);
809
810    CALLGEOTAT(_XtGeoTab(-1));
811#undef FillIn
812
813    if (!(reply->request_mode & CWStackMode))
814	reply->stack_mode = XtSMDontChange;
815    UNLOCK_APP(app);
816    return result;
817}
818