/[dtapublic]/projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tkgeometry.c
ViewVC logotype

Diff of /projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tkgeometry.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.69  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25