/[dtapublic]/projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkgeometry.c
ViewVC logotype

Annotation of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkgeometry.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (hide annotations) (download)
Fri Oct 14 01:50:00 2016 UTC (7 years, 8 months ago) by dashley
Original Path: projs/trunk/shared_source/tk_base/tkgeometry.c
File MIME type: text/plain
File size: 18354 byte(s)
Move shared source code to commonize.
1 dashley 25 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tk_base/tkgeometry.c,v 1.1.1.1 2001/06/13 05:01:19 dtashley Exp $ */
2    
3     /*
4     * tkGeometry.c --
5     *
6     * This file contains generic Tk code for geometry management
7     * (stuff that's used by all geometry managers).
8     *
9     * Copyright (c) 1990-1994 The Regents of the University of California.
10     * Copyright (c) 1994-1995 Sun Microsystems, Inc.
11     *
12     * See the file "license.terms" for information on usage and redistribution
13     * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14     *
15     * RCS: @(#) $Id: tkgeometry.c,v 1.1.1.1 2001/06/13 05:01:19 dtashley Exp $
16     */
17    
18     #include "tkPort.h"
19     #include "tkInt.h"
20    
21     /*
22     * Data structures of the following type are used by Tk_MaintainGeometry.
23     * For each slave managed by Tk_MaintainGeometry, there is one of these
24     * structures associated with its master.
25     */
26    
27     typedef struct MaintainSlave {
28     Tk_Window slave; /* The slave window being positioned. */
29     Tk_Window master; /* The master that determines slave's
30     * position; it must be a descendant of
31     * slave's parent. */
32     int x, y; /* Desired position of slave relative to
33     * master. */
34     int width, height; /* Desired dimensions of slave. */
35     struct MaintainSlave *nextPtr;
36     /* Next in list of Maintains associated
37     * with master. */
38     } MaintainSlave;
39    
40     /*
41     * For each window that has been specified as a master to
42     * Tk_MaintainGeometry, there is a structure of the following type:
43     */
44    
45     typedef struct MaintainMaster {
46     Tk_Window ancestor; /* The lowest ancestor of this window
47     * for which we have *not* created a
48     * StructureNotify handler. May be the
49     * same as the window itself. */
50     int checkScheduled; /* Non-zero means that there is already a
51     * call to MaintainCheckProc scheduled as
52     * an idle handler. */
53     MaintainSlave *slavePtr; /* First in list of all slaves associated
54     * with this master. */
55     } MaintainMaster;
56    
57     /*
58     * Prototypes for static procedures in this file:
59     */
60    
61     static void MaintainCheckProc _ANSI_ARGS_((ClientData clientData));
62     static void MaintainMasterProc _ANSI_ARGS_((ClientData clientData,
63     XEvent *eventPtr));
64     static void MaintainSlaveProc _ANSI_ARGS_((ClientData clientData,
65     XEvent *eventPtr));
66    
67     /*
68     *--------------------------------------------------------------
69     *
70     * Tk_ManageGeometry --
71     *
72     * Arrange for a particular procedure to manage the geometry
73     * of a given slave window.
74     *
75     * Results:
76     * None.
77     *
78     * Side effects:
79     * Proc becomes the new geometry manager for tkwin, replacing
80     * any previous geometry manager. The geometry manager will
81     * be notified (by calling procedures in *mgrPtr) when interesting
82     * things happen in the future. If there was an existing geometry
83     * manager for tkwin different from the new one, it is notified
84     * by calling its lostSlaveProc.
85     *
86     *--------------------------------------------------------------
87     */
88    
89     void
90     Tk_ManageGeometry(tkwin, mgrPtr, clientData)
91     Tk_Window tkwin; /* Window whose geometry is to
92     * be managed by proc. */
93     Tk_GeomMgr *mgrPtr; /* Static structure describing the
94     * geometry manager. This structure
95     * must never go away. */
96     ClientData clientData; /* Arbitrary one-word argument to
97     * pass to geometry manager procedures. */
98     {
99     register TkWindow *winPtr = (TkWindow *) tkwin;
100    
101     if ((winPtr->geomMgrPtr != NULL) && (mgrPtr != NULL)
102     && ((winPtr->geomMgrPtr != mgrPtr)
103     || (winPtr->geomData != clientData))
104     && (winPtr->geomMgrPtr->lostSlaveProc != NULL)) {
105     (*winPtr->geomMgrPtr->lostSlaveProc)(winPtr->geomData, tkwin);
106     }
107    
108     winPtr->geomMgrPtr = mgrPtr;
109     winPtr->geomData = clientData;
110     }
111    
112     /*
113     *--------------------------------------------------------------
114     *
115     * Tk_GeometryRequest --
116     *
117     * This procedure is invoked by widget code to indicate
118     * its preferences about the size of a window it manages.
119     * In general, widget code should call this procedure
120     * rather than Tk_ResizeWindow.
121     *
122     * Results:
123     * None.
124     *
125     * Side effects:
126     * The geometry manager for tkwin (if any) is invoked to
127     * handle the request. If possible, it will reconfigure
128     * tkwin and/or other windows to satisfy the request. The
129     * caller gets no indication of success or failure, but it
130     * will get X events if the window size was actually
131     * changed.
132     *
133     *--------------------------------------------------------------
134     */
135    
136     void
137     Tk_GeometryRequest(tkwin, reqWidth, reqHeight)
138     Tk_Window tkwin; /* Window that geometry information
139     * pertains to. */
140     int reqWidth, reqHeight; /* Minimum desired dimensions for
141     * window, in pixels. */
142     {
143     register TkWindow *winPtr = (TkWindow *) tkwin;
144    
145     /*
146     * X gets very upset if a window requests a width or height of
147     * zero, so rounds requested sizes up to at least 1.
148     */
149    
150     if (reqWidth <= 0) {
151     reqWidth = 1;
152     }
153     if (reqHeight <= 0) {
154     reqHeight = 1;
155     }
156     if ((reqWidth == winPtr->reqWidth) && (reqHeight == winPtr->reqHeight)) {
157     return;
158     }
159     winPtr->reqWidth = reqWidth;
160     winPtr->reqHeight = reqHeight;
161     if ((winPtr->geomMgrPtr != NULL)
162     && (winPtr->geomMgrPtr->requestProc != NULL)) {
163     (*winPtr->geomMgrPtr->requestProc)(winPtr->geomData, tkwin);
164     }
165     }
166    
167     /*
168     *----------------------------------------------------------------------
169     *
170     * Tk_SetInternalBorder --
171     *
172     * Notify relevant geometry managers that a window has an internal
173     * border of a given width and that child windows should not be
174     * placed on that border.
175     *
176     * Results:
177     * None.
178     *
179     * Side effects:
180     * The border width is recorded for the window, and all geometry
181     * managers of all children are notified so that can re-layout, if
182     * necessary.
183     *
184     *----------------------------------------------------------------------
185     */
186    
187     void
188     Tk_SetInternalBorder(tkwin, width)
189     Tk_Window tkwin; /* Window that will have internal border. */
190     int width; /* Width of internal border, in pixels. */
191     {
192     register TkWindow *winPtr = (TkWindow *) tkwin;
193    
194     if (width == winPtr->internalBorderWidth) {
195     return;
196     }
197     if (width < 0) {
198     width = 0;
199     }
200     winPtr->internalBorderWidth = width;
201    
202     /*
203     * All the slaves for which this is the master window must now be
204     * repositioned to take account of the new internal border width.
205     * To signal all the geometry managers to do this, just resize the
206     * window to its current size. The ConfigureNotify event will
207     * cause geometry managers to recompute everything.
208     */
209    
210     Tk_ResizeWindow(tkwin, Tk_Width(tkwin), Tk_Height(tkwin));
211     }
212    
213     /*
214     *----------------------------------------------------------------------
215     *
216     * Tk_MaintainGeometry --
217     *
218     * This procedure is invoked by geometry managers to handle slaves
219     * whose master's are not their parents. It translates the desired
220     * geometry for the slave into the coordinate system of the parent
221     * and respositions the slave if it isn't already at the right place.
222     * Furthermore, it sets up event handlers so that if the master (or
223     * any of its ancestors up to the slave's parent) is mapped, unmapped,
224     * or moved, then the slave will be adjusted to match.
225     *
226     * Results:
227     * None.
228     *
229     * Side effects:
230     * Event handlers are created and state is allocated to keep track
231     * of slave. Note: if slave was already managed for master by
232     * Tk_MaintainGeometry, then the previous information is replaced
233     * with the new information. The caller must eventually call
234     * Tk_UnmaintainGeometry to eliminate the correspondence (or, the
235     * state is automatically freed when either window is destroyed).
236     *
237     *----------------------------------------------------------------------
238     */
239    
240     void
241     Tk_MaintainGeometry(slave, master, x, y, width, height)
242     Tk_Window slave; /* Slave for geometry management. */
243     Tk_Window master; /* Master for slave; must be a descendant
244     * of slave's parent. */
245     int x, y; /* Desired position of slave within master. */
246     int width, height; /* Desired dimensions for slave. */
247     {
248     Tcl_HashEntry *hPtr;
249     MaintainMaster *masterPtr;
250     register MaintainSlave *slavePtr;
251     int new, map;
252     Tk_Window ancestor, parent;
253     TkDisplay *dispPtr = ((TkWindow *) master)->dispPtr;
254    
255     if (!dispPtr->geomInit) {
256     dispPtr->geomInit = 1;
257     Tcl_InitHashTable(&dispPtr->maintainHashTable, TCL_ONE_WORD_KEYS);
258     }
259    
260     /*
261     * See if there is already a MaintainMaster structure for the master;
262     * if not, then create one.
263     */
264    
265     parent = Tk_Parent(slave);
266     hPtr = Tcl_CreateHashEntry(&dispPtr->maintainHashTable,
267     (char *) master, &new);
268     if (!new) {
269     masterPtr = (MaintainMaster *) Tcl_GetHashValue(hPtr);
270     } else {
271     masterPtr = (MaintainMaster *) ckalloc(sizeof(MaintainMaster));
272     masterPtr->ancestor = master;
273     masterPtr->checkScheduled = 0;
274     masterPtr->slavePtr = NULL;
275     Tcl_SetHashValue(hPtr, masterPtr);
276     }
277    
278     /*
279     * Create a MaintainSlave structure for the slave if there isn't
280     * already one.
281     */
282    
283     for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
284     slavePtr = slavePtr->nextPtr) {
285     if (slavePtr->slave == slave) {
286     goto gotSlave;
287     }
288     }
289     slavePtr = (MaintainSlave *) ckalloc(sizeof(MaintainSlave));
290     slavePtr->slave = slave;
291     slavePtr->master = master;
292     slavePtr->nextPtr = masterPtr->slavePtr;
293     masterPtr->slavePtr = slavePtr;
294     Tk_CreateEventHandler(slave, StructureNotifyMask, MaintainSlaveProc,
295     (ClientData) slavePtr);
296    
297     /*
298     * Make sure that there are event handlers registered for all
299     * the windows between master and slave's parent (including master
300     * but not slave's parent). There may already be handlers for master
301     * and some of its ancestors (masterPtr->ancestor tells how many).
302     */
303    
304     for (ancestor = master; ancestor != parent;
305     ancestor = Tk_Parent(ancestor)) {
306     if (ancestor == masterPtr->ancestor) {
307     Tk_CreateEventHandler(ancestor, StructureNotifyMask,
308     MaintainMasterProc, (ClientData) masterPtr);
309     masterPtr->ancestor = Tk_Parent(ancestor);
310     }
311     }
312    
313     /*
314     * Fill in up-to-date information in the structure, then update the
315     * window if it's not currently in the right place or state.
316     */
317    
318     gotSlave:
319     slavePtr->x = x;
320     slavePtr->y = y;
321     slavePtr->width = width;
322     slavePtr->height = height;
323     map = 1;
324     for (ancestor = slavePtr->master; ; ancestor = Tk_Parent(ancestor)) {
325     if (!Tk_IsMapped(ancestor) && (ancestor != parent)) {
326     map = 0;
327     }
328     if (ancestor == parent) {
329     if ((x != Tk_X(slavePtr->slave))
330     || (y != Tk_Y(slavePtr->slave))
331     || (width != Tk_Width(slavePtr->slave))
332     || (height != Tk_Height(slavePtr->slave))) {
333     Tk_MoveResizeWindow(slavePtr->slave, x, y, width, height);
334     }
335     if (map) {
336     Tk_MapWindow(slavePtr->slave);
337     } else {
338     Tk_UnmapWindow(slavePtr->slave);
339     }
340     break;
341     }
342     x += Tk_X(ancestor) + Tk_Changes(ancestor)->border_width;
343     y += Tk_Y(ancestor) + Tk_Changes(ancestor)->border_width;
344     }
345     }
346    
347     /*
348     *----------------------------------------------------------------------
349     *
350     * Tk_UnmaintainGeometry --
351     *
352     * This procedure cancels a previous Tk_MaintainGeometry call,
353     * so that the relationship between slave and master is no longer
354     * maintained.
355     *
356     * Results:
357     * None.
358     *
359     * Side effects:
360     * The slave is unmapped and state is released, so that slave won't
361     * track master any more. If we weren't previously managing slave
362     * relative to master, then this procedure has no effect.
363     *
364     *----------------------------------------------------------------------
365     */
366    
367     void
368     Tk_UnmaintainGeometry(slave, master)
369     Tk_Window slave; /* Slave for geometry management. */
370     Tk_Window master; /* Master for slave; must be a descendant
371     * of slave's parent. */
372     {
373     Tcl_HashEntry *hPtr;
374     MaintainMaster *masterPtr;
375     register MaintainSlave *slavePtr, *prevPtr;
376     Tk_Window ancestor;
377     TkDisplay *dispPtr = ((TkWindow *) slave)->dispPtr;
378    
379     if (!dispPtr->geomInit) {
380     dispPtr->geomInit = 1;
381     Tcl_InitHashTable(&dispPtr->maintainHashTable, TCL_ONE_WORD_KEYS);
382     }
383    
384     if (!(((TkWindow *) slave)->flags & TK_ALREADY_DEAD)) {
385     Tk_UnmapWindow(slave);
386     }
387     hPtr = Tcl_FindHashEntry(&dispPtr->maintainHashTable, (char *) master);
388     if (hPtr == NULL) {
389     return;
390     }
391     masterPtr = (MaintainMaster *) Tcl_GetHashValue(hPtr);
392     slavePtr = masterPtr->slavePtr;
393     if (slavePtr->slave == slave) {
394     masterPtr->slavePtr = slavePtr->nextPtr;
395     } else {
396     for (prevPtr = slavePtr, slavePtr = slavePtr->nextPtr; ;
397     prevPtr = slavePtr, slavePtr = slavePtr->nextPtr) {
398     if (slavePtr == NULL) {
399     return;
400     }
401     if (slavePtr->slave == slave) {
402     prevPtr->nextPtr = slavePtr->nextPtr;
403     break;
404     }
405     }
406     }
407     Tk_DeleteEventHandler(slavePtr->slave, StructureNotifyMask,
408     MaintainSlaveProc, (ClientData) slavePtr);
409     ckfree((char *) slavePtr);
410     if (masterPtr->slavePtr == NULL) {
411     if (masterPtr->ancestor != NULL) {
412     for (ancestor = master; ; ancestor = Tk_Parent(ancestor)) {
413     Tk_DeleteEventHandler(ancestor, StructureNotifyMask,
414     MaintainMasterProc, (ClientData) masterPtr);
415     if (ancestor == masterPtr->ancestor) {
416     break;
417     }
418     }
419     }
420     if (masterPtr->checkScheduled) {
421     Tcl_CancelIdleCall(MaintainCheckProc, (ClientData) masterPtr);
422     }
423     Tcl_DeleteHashEntry(hPtr);
424     ckfree((char *) masterPtr);
425     }
426     }
427    
428     /*
429     *----------------------------------------------------------------------
430     *
431     * MaintainMasterProc --
432     *
433     * This procedure is invoked by the Tk event dispatcher in
434     * response to StructureNotify events on the master or one
435     * of its ancestors, on behalf of Tk_MaintainGeometry.
436     *
437     * Results:
438     * None.
439     *
440     * Side effects:
441     * It schedules a call to MaintainCheckProc, which will eventually
442     * caused the postions and mapped states to be recalculated for all
443     * the maintained slaves of the master. Or, if the master window is
444     * being deleted then state is cleaned up.
445     *
446     *----------------------------------------------------------------------
447     */
448    
449     static void
450     MaintainMasterProc(clientData, eventPtr)
451     ClientData clientData; /* Pointer to MaintainMaster structure
452     * for the master window. */
453     XEvent *eventPtr; /* Describes what just happened. */
454     {
455     MaintainMaster *masterPtr = (MaintainMaster *) clientData;
456     MaintainSlave *slavePtr;
457     int done;
458    
459     if ((eventPtr->type == ConfigureNotify)
460     || (eventPtr->type == MapNotify)
461     || (eventPtr->type == UnmapNotify)) {
462     if (!masterPtr->checkScheduled) {
463     masterPtr->checkScheduled = 1;
464     Tcl_DoWhenIdle(MaintainCheckProc, (ClientData) masterPtr);
465     }
466     } else if (eventPtr->type == DestroyNotify) {
467     /*
468     * Delete all of the state associated with this master, but
469     * be careful not to use masterPtr after the last slave is
470     * deleted, since its memory will have been freed.
471     */
472    
473     done = 0;
474     do {
475     slavePtr = masterPtr->slavePtr;
476     if (slavePtr->nextPtr == NULL) {
477     done = 1;
478     }
479     Tk_UnmaintainGeometry(slavePtr->slave, slavePtr->master);
480     } while (!done);
481     }
482     }
483    
484     /*
485     *----------------------------------------------------------------------
486     *
487     * MaintainSlaveProc --
488     *
489     * This procedure is invoked by the Tk event dispatcher in
490     * response to StructureNotify events on a slave being managed
491     * by Tk_MaintainGeometry.
492     *
493     * Results:
494     * None.
495     *
496     * Side effects:
497     * If the event is a DestroyNotify event then the Maintain state
498     * and event handlers for this slave are deleted.
499     *
500     *----------------------------------------------------------------------
501     */
502    
503     static void
504     MaintainSlaveProc(clientData, eventPtr)
505     ClientData clientData; /* Pointer to MaintainSlave structure
506     * for master-slave pair. */
507     XEvent *eventPtr; /* Describes what just happened. */
508     {
509     MaintainSlave *slavePtr = (MaintainSlave *) clientData;
510    
511     if (eventPtr->type == DestroyNotify) {
512     Tk_UnmaintainGeometry(slavePtr->slave, slavePtr->master);
513     }
514     }
515    
516     /*
517     *----------------------------------------------------------------------
518     *
519     * MaintainCheckProc --
520     *
521     * This procedure is invoked by the Tk event dispatcher as an
522     * idle handler, when a master or one of its ancestors has been
523     * reconfigured, mapped, or unmapped. Its job is to scan all of
524     * the slaves for the master and reposition them, map them, or
525     * unmap them as needed to maintain their geometry relative to
526     * the master.
527     *
528     * Results:
529     * None.
530     *
531     * Side effects:
532     * Slaves can get repositioned, mapped, or unmapped.
533     *
534     *----------------------------------------------------------------------
535     */
536    
537     static void
538     MaintainCheckProc(clientData)
539     ClientData clientData; /* Pointer to MaintainMaster structure
540     * for the master window. */
541     {
542     MaintainMaster *masterPtr = (MaintainMaster *) clientData;
543     MaintainSlave *slavePtr;
544     Tk_Window ancestor, parent;
545     int x, y, map;
546    
547     masterPtr->checkScheduled = 0;
548     for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
549     slavePtr = slavePtr->nextPtr) {
550     parent = Tk_Parent(slavePtr->slave);
551     x = slavePtr->x;
552     y = slavePtr->y;
553     map = 1;
554     for (ancestor = slavePtr->master; ; ancestor = Tk_Parent(ancestor)) {
555     if (!Tk_IsMapped(ancestor) && (ancestor != parent)) {
556     map = 0;
557     }
558     if (ancestor == parent) {
559     if ((x != Tk_X(slavePtr->slave))
560     || (y != Tk_Y(slavePtr->slave))) {
561     Tk_MoveWindow(slavePtr->slave, x, y);
562     }
563     if (map) {
564     Tk_MapWindow(slavePtr->slave);
565     } else {
566     Tk_UnmapWindow(slavePtr->slave);
567     }
568     break;
569     }
570     x += Tk_X(ancestor) + Tk_Changes(ancestor)->border_width;
571     y += Tk_Y(ancestor) + Tk_Changes(ancestor)->border_width;
572     }
573     }
574     }
575    
576    
577     /* $History: tkGeometry.c $
578     *
579     * ***************** Version 1 *****************
580     * User: Dtashley Date: 1/02/01 Time: 2:47a
581     * Created in $/IjuScripter, IjuConsole/Source/Tk Base
582     * Initial check-in.
583     */
584    
585     /* End of TKGEOMETRY.C */

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25