4 * This file provides basic window-manipulation procedures,
5 * which are equivalent to procedures in Xlib (and even
6 * invoke them) but also maintain the local Tk_Window
9 * Copyright 1989-1992 Regents of the University of California.
10 * Permission to use, copy, modify, and distribute this
11 * software and its documentation for any purpose and without
12 * fee is hereby granted, provided that the above copyright
13 * notice appear in all copies. The University of California
14 * makes no representations about the suitability of this
15 * software for any purpose. It is provided "as is" without
16 * express or implied warranty.
20 static char rcsid
[] = "$Header: /user6/ouster/wish/RCS/tkWindow.c,v 1.92 92/08/21 11:42:44 ouster Exp $ SPRITE (Berkeley)";
27 * Global absolute file name:
29 char *TK_Library
= TK_LIBRARY
;
32 * Count of open displays.
37 * Count of number of main windows currently open in this process.
40 int tk_NumMainWindows
;
43 * Added by dhopkins for OLPC Micropolis gtk.Socket integration.
46 Window tk_RootWindow
= 0;
49 * List of all displays currently in use.
52 TkDisplay
*tkDisplayList
= NULL
;
55 * Have statics in this module been initialized?
58 static int initialized
= 0;
61 * Context information used to map from X window id's to
62 * TkWindow structures (during event handling, for example):
65 XContext tkWindowContext
;
68 * The variables below hold several uid's that are used in many places
72 Tk_Uid tkDisabledUid
= NULL
;
73 Tk_Uid tkActiveUid
= NULL
;
74 Tk_Uid tkNormalUid
= NULL
;
77 * Default values for "changes" and "atts" fields of TkWindows. Note
78 * that Tk always requests all events for all windows, except StructureNotify
79 * events on internal windows: these events are generated internally.
82 static XWindowChanges defChanges
= {
83 0, 0, 1, 1, 0, 0, Above
85 #define ALL_EVENTS_MASK \
86 KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask| \
87 EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask| \
88 VisibilityChangeMask|SubstructureNotifyMask| \
89 FocusChangeMask|PropertyChangeMask|ColormapChangeMask
90 static XSetWindowAttributes defAtts
= {
91 None
, /* background_pixmap */
92 0, /* background_pixel */
93 CopyFromParent
, /* border_pixmap */
95 ForgetGravity
, /* bit_gravity */
96 NorthWestGravity
, /* win_gravity */
97 NotUseful
, /* backing_store */
98 ~0, /* backing_planes */
99 0, /* backing_pixel */
100 False
, /* save_under */
101 ALL_EVENTS_MASK
, /* event_mask */
102 0, /* do_not_propagate_mask */
103 False
, /* override_redirect */
104 CopyFromParent
, /* colormap */
109 * The following structure defines all of the commands supported by
110 * Tk, and the C procedures that execute them.
114 char *name
; /* Name of command. */
115 int (*cmdProc
) _ANSI_ARGS_((ClientData clientData
, Tcl_Interp
*interp
,
116 int argc
, char **argv
));
117 /* Command procedure. */
122 * Commands that are part of the intrinsics:
125 {"after", Tk_AfterCmd
},
126 {"bind", Tk_BindCmd
},
127 {"destroy", Tk_DestroyCmd
},
128 {"focus", Tk_FocusCmd
},
129 {"grab", Tk_GrabCmd
},
130 {"option", Tk_OptionCmd
},
131 {"pack", Tk_PackCmd
},
132 {"place", Tk_PlaceCmd
},
133 {"selection", Tk_SelectionCmd
},
134 {"tkwait", Tk_TkwaitCmd
},
135 {"update", Tk_UpdateCmd
},
136 {"winfo", Tk_WinfoCmd
},
138 {"accept", Tcp_AcceptCmd
},
139 {"shutdown", Tcp_ShutdownCmd
},
140 {"connect", Tcp_ConnectCmd
},
141 {"filehandler", Tcp_FileHandlerCmd
},
144 * Widget-creation commands.
146 {"button", Tk_ButtonCmd
},
147 {"canvas", Tk_CanvasCmd
},
148 {"checkbutton", Tk_ButtonCmd
},
149 {"entry", Tk_EntryCmd
},
150 {"frame", Tk_FrameCmd
},
151 {"label", Tk_ButtonCmd
},
152 {"listbox", Tk_ListboxCmd
},
153 {"menu", Tk_MenuCmd
},
154 {"menubutton", Tk_MenubuttonCmd
},
155 {"message", Tk_MessageCmd
},
156 {"radiobutton", Tk_ButtonCmd
},
157 {"scale", Tk_ScaleCmd
},
158 {"scrollbar", Tk_ScrollbarCmd
},
159 {"text", Tk_TextCmd
},
160 {"toplevel", Tk_FrameCmd
},
161 {(char *) NULL
, (int (*)(int *, Tcl_Interp
*, int, char **)) NULL
}
165 * Forward declarations to procedures defined later in this file:
168 static Tk_Window CreateTopLevelWindow
_ANSI_ARGS_((Tcl_Interp
*interp
,
169 Tk_Window parent
, char *name
, char *screenName
));
170 static void DoConfigureNotify
_ANSI_ARGS_((TkWindow
*winPtr
));
171 static TkDisplay
* GetScreen
_ANSI_ARGS_((Tcl_Interp
*interp
,
172 char *screenName
, int *screenPtr
));
173 static int NameWindow
_ANSI_ARGS_((Tcl_Interp
*interp
,
174 TkWindow
*winPtr
, TkWindow
*parentPtr
,
176 static TkWindow
* NewWindow
_ANSI_ARGS_((TkDisplay
*dispPtr
,
180 *----------------------------------------------------------------------
182 * CreateTopLevelWindow --
184 * Make a new window that will be at top-level (its parent will
185 * be the root window of a screen).
188 * The return value is a token for the new window, or NULL if
189 * an error prevented the new window from being created. If
190 * NULL is returned, an error message will be left in
194 * A new window structure is allocated locally. An X
195 * window is NOT initially created, but will be created
196 * the first time the window is mapped.
198 *----------------------------------------------------------------------
202 CreateTopLevelWindow (
203 Tcl_Interp
*interp
, /* Interpreter to use for error reporting. */
204 Tk_Window parent
, /* Token for logical parent of new window
205 * (used for naming, options, etc.). May
207 char *name
, /* Name for new window; if parent is
208 * non-NULL, must be unique among parent's
210 char *screenName
/* Name of screen on which to create
211 * window. NULL means use DISPLAY environment
212 * variable to determine. Empty string means
213 * use parent's screen, or DISPLAY if no
217 register TkWindow
*winPtr
;
218 register TkDisplay
*dispPtr
;
223 tkWindowContext
= XUniqueContext();
224 tkActiveUid
= Tk_GetUid("active");
225 tkDisabledUid
= Tk_GetUid("disabled");
226 tkNormalUid
= Tk_GetUid("normal");
229 if ((parent
!= NULL
) && (screenName
!= NULL
) && (screenName
[0] == '\0')) {
230 dispPtr
= ((TkWindow
*) parent
)->dispPtr
;
231 screenId
= Tk_ScreenNumber(parent
);
233 dispPtr
= GetScreen(interp
, screenName
, &screenId
);
234 if (dispPtr
== NULL
) {
235 return (Tk_Window
) NULL
;
239 winPtr
= NewWindow(dispPtr
, screenId
);
242 * Internal windows don't normally ask for StructureNotify events,
243 * since we can generate them internally. However, for top-level
244 * windows we need to as for the events because the window could
245 * be manipulated externally.
248 winPtr
->atts
.event_mask
|= StructureNotifyMask
;
251 * (Need to set the TK_TOP_LEVEL flag immediately here; otherwise
252 * Tk_DestroyWindow will core dump if it is called before the flag
256 winPtr
->flags
|= TK_TOP_LEVEL
;
257 if (parent
!= NULL
) {
258 if (NameWindow(interp
, winPtr
, (TkWindow
*) parent
, name
) != TCL_OK
) {
259 Tk_DestroyWindow((Tk_Window
) winPtr
);
260 return (Tk_Window
) NULL
;
263 TkWmNewWindow(winPtr
);
264 return (Tk_Window
) winPtr
;
268 *----------------------------------------------------------------------
272 * Given a string name for a display-plus-screen, find the
273 * TkDisplay structure for the display and return the screen
277 * The return value is a pointer to information about the display,
278 * or NULL if the display couldn't be opened. In this case, an
279 * error message is left in interp->result. The location at
280 * *screenPtr is overwritten with the screen number parsed from
284 * A new connection is opened to the display if there is no
285 * connection already. A new TkDisplay data structure is also
286 * setup, if necessary.
288 *----------------------------------------------------------------------
293 Tcl_Interp
*interp
, /* Place to leave error message. */
294 char *screenName
, /* Name for screen. NULL or empty means
295 * use DISPLAY envariable. */
296 int *screenPtr
/* Where to store screen number. */
299 register TkDisplay
*dispPtr
;
301 int length
, screenId
;
304 * Separate the screen number from the rest of the display
305 * name. ScreenName is assumed to have the syntax
306 * <display>.<screen> with the dot and the screen being
310 if ((screenName
== NULL
) || (screenName
[0] == '\0')) {
311 screenName
= getenv("DISPLAY");
312 if (screenName
== NULL
) {
314 "no display name and no $DISPLAY environment variable";
315 return (TkDisplay
*) NULL
;
318 length
= strlen(screenName
);
320 p
= screenName
+length
-1;
321 while (isdigit(*p
) && (p
!= screenName
)) {
324 if ((*p
== '.') && (p
[1] != '\0')) {
325 length
= p
- screenName
;
326 screenId
= strtoul(p
+1, (char **) NULL
, 10);
330 * See if we already have a connection to this display. If not,
331 * then open a new connection.
334 for (dispPtr
= tkDisplayList
; ; dispPtr
= dispPtr
->nextPtr
) {
335 if (dispPtr
== NULL
) {
336 Display
*display
= NULL
;
338 display
= XOpenDisplay(screenName
);
340 if (display
== NULL
) {
341 Tcl_AppendResult(interp
, "couldn't connect to display \"",
342 screenName
, "\"", (char *) NULL
);
343 return (TkDisplay
*) NULL
;
345 if (getenv("XSYNCHRONIZE") != NULL
) {
346 XSynchronize(display
, 1);
349 dispPtr
= (TkDisplay
*) ckalloc(sizeof(TkDisplay
));
350 dispPtr
->display
= display
;
351 dispPtr
->nextPtr
= tkDisplayList
;
352 dispPtr
->name
= (char *) ckalloc((unsigned) (length
+1));
353 dispPtr
->lastEventTime
= CurrentTime
;
354 strncpy(dispPtr
->name
, screenName
, length
);
355 dispPtr
->mouseMainPtr
= NULL
;
356 dispPtr
->name
[length
] = '\0';
357 dispPtr
->symsPerCode
= 0;
358 dispPtr
->errorPtr
= NULL
;
359 dispPtr
->deleteCount
= 0;
360 dispPtr
->commWindow
= NULL
;
361 dispPtr
->selectionOwner
= NULL
;
362 dispPtr
->selectionSerial
= 0;
363 dispPtr
->multipleAtom
= None
;
364 dispPtr
->atomInit
= 0;
365 dispPtr
->modeModMask
= 0;
366 dispPtr
->metaModMask
= 0;
367 dispPtr
->altModMask
= 0;
368 dispPtr
->cursorFont
= None
;
369 dispPtr
->grabWinPtr
= NULL
;
370 dispPtr
->ungrabWinPtr
= NULL
;
371 dispPtr
->buttonWinPtr
= NULL
;
372 dispPtr
->pointerWinPtr
= NULL
;
373 dispPtr
->serverWinPtr
= NULL
;
374 dispPtr
->grabFlags
= 0;
375 dispPtr
->focusPtr
= NULL
;
376 tkDisplayList
= dispPtr
;
377 Tk_CreateFileHandler(ConnectionNumber(display
),
378 TK_READABLE
, (void (*)(int *, int)) NULL
,
379 (ClientData
) display
);
382 if ((strncmp(dispPtr
->name
, screenName
, length
) == 0)
383 && (dispPtr
->name
[length
] == '\0')) {
387 if (screenId
>= ScreenCount(dispPtr
->display
)) {
388 sprintf(interp
->result
, "bad screen number \"%d\"", screenId
);
389 return (TkDisplay
*) NULL
;
391 *screenPtr
= screenId
;
396 *--------------------------------------------------------------
400 * This procedure creates and initializes a TkWindow structure.
403 * The return value is a pointer to the new window.
406 * A new window structure is allocated and all its fields are
409 *--------------------------------------------------------------
414 TkDisplay
*dispPtr
, /* Display associated with new window. */
415 int screenNum
/* Index of screen for new window. */
418 register TkWindow
*winPtr
;
420 winPtr
= (TkWindow
*) ckalloc(sizeof(TkWindow
));
421 winPtr
->display
= dispPtr
->display
;
422 winPtr
->dispPtr
= dispPtr
;
423 winPtr
->screenNum
= screenNum
;
424 winPtr
->window
= None
;
425 winPtr
->childList
= NULL
;
426 winPtr
->parentPtr
= NULL
;
427 winPtr
->nextPtr
= NULL
;
428 winPtr
->mainPtr
= NULL
;
429 winPtr
->pathName
= NULL
;
430 winPtr
->nameUid
= NULL
;
431 winPtr
->classUid
= NULL
;
432 winPtr
->changes
= defChanges
;
433 winPtr
->dirtyChanges
= CWX
|CWY
|CWWidth
|CWHeight
|CWBorderWidth
;
434 winPtr
->atts
= defAtts
;
435 winPtr
->dirtyAtts
= CWEventMask
;
437 winPtr
->handlerList
= NULL
;
438 winPtr
->focusProc
= NULL
;
439 winPtr
->focusData
= NULL
;
440 winPtr
->optionLevel
= -1;
441 winPtr
->selHandlerList
= NULL
;
442 winPtr
->selClearProc
= NULL
;
443 winPtr
->selClearData
= NULL
;
444 winPtr
->geomProc
= NULL
;
445 winPtr
->geomData
= NULL
;
446 winPtr
->reqWidth
= winPtr
->reqHeight
= 0;
447 winPtr
->internalBorderWidth
= 0;
448 winPtr
->wmInfoPtr
= NULL
;
453 *----------------------------------------------------------------------
457 * This procedure is invoked to give a window a name and insert
458 * the window into the hierarchy associated with a particular
462 * A standard Tcl return value.
467 *----------------------------------------------------------------------
472 Tcl_Interp
*interp
, /* Interpreter to use for error reporting. */
473 register TkWindow
*winPtr
, /* Window that is to be named and inserted. */
474 TkWindow
*parentPtr
, /* Pointer to logical parent for winPtr
475 * (used for naming, options, etc.). */
476 char *name
/* Name for winPtr; must be unique among
477 * parentPtr's children. */
480 #define FIXED_SIZE 200
481 char staticSpace
[FIXED_SIZE
];
485 int length1
, length2
;
488 * Setup all the stuff except name right away, then do the name stuff
489 * last. This is so that if the name stuff fails, everything else
490 * will be properly initialized (needed to destroy the window cleanly
491 * after the naming failure).
493 winPtr
->parentPtr
= parentPtr
;
494 winPtr
->nextPtr
= parentPtr
->childList
;
495 parentPtr
->childList
= winPtr
;
496 winPtr
->mainPtr
= parentPtr
->mainPtr
;
497 winPtr
->nameUid
= Tk_GetUid(name
);
500 * To permit names of arbitrary length, must be prepared to malloc
501 * a buffer to hold the new path name. To run fast in the common
502 * case where names are short, use a fixed-size buffer on the
506 length1
= strlen(parentPtr
->pathName
);
507 length2
= strlen(name
);
508 if ((length1
+length2
+2) <= FIXED_SIZE
) {
509 pathName
= staticSpace
;
511 pathName
= (char *) ckalloc((unsigned) (length1
+length2
+2));
515 strcpy(pathName
+1, name
);
517 strcpy(pathName
, parentPtr
->pathName
);
518 pathName
[length1
] = '.';
519 strcpy(pathName
+length1
+1, name
);
521 hPtr
= Tcl_CreateHashEntry(&parentPtr
->mainPtr
->nameTable
, pathName
, &new);
522 if (pathName
!= staticSpace
) {
526 Tcl_AppendResult(interp
, "window name \"", name
,
527 "\" already exists in parent", (char *) NULL
);
530 Tcl_SetHashValue(hPtr
, winPtr
);
531 winPtr
->pathName
= Tcl_GetHashKey(&parentPtr
->mainPtr
->nameTable
, hPtr
);
536 *----------------------------------------------------------------------
538 * Tk_CreateMainWindow --
540 * Make a new main window. A main window is a special kind of
541 * top-level window used as the outermost window in an
545 * The return value is a token for the new window, or NULL if
546 * an error prevented the new window from being created. If
547 * NULL is returned, an error message will be left in
551 * A new window structure is allocated locally; "interp" is
552 * associated with the window and registered for "send" commands
553 * under "baseName". BaseName may be extended with an instance
554 * number in the form "#2" if necessary to make it globally
555 * unique. Tk-related commands are bound into interp. An X
556 * window is NOT initially created, but will be created the
557 * first time the window is mapped.
559 *----------------------------------------------------------------------
563 Tk_CreateMainWindow (
564 Tcl_Interp
*interp
, /* Interpreter to use for error reporting. */
565 char *screenName
, /* Name of screen on which to create
566 * window. Empty or NULL string means
567 * use DISPLAY environment variable. */
568 char *baseName
/* Base name for application; usually of the
569 * form "prog instance". */
575 register TkMainInfo
*mainPtr
;
576 register TkWindow
*winPtr
;
577 register TkCmd
*cmdPtr
;
580 * Create the basic TkWindow structure.
583 tkwin
= CreateTopLevelWindow(interp
, (Tk_Window
) NULL
, baseName
,
590 * Create the TkMainInfo structure for this application, and set
591 * up name-related information for the new window.
594 winPtr
= (TkWindow
*) tkwin
;
595 mainPtr
= (TkMainInfo
*) ckalloc(sizeof(TkMainInfo
));
596 mainPtr
->winPtr
= winPtr
;
597 mainPtr
->interp
= interp
;
598 Tcl_InitHashTable(&mainPtr
->nameTable
, TCL_STRING_KEYS
);
599 mainPtr
->bindingTable
= Tk_CreateBindingTable(interp
);
601 /* mainPtr->focusPtr = NULL; */
602 mainPtr
->optionRootPtr
= NULL
;
603 winPtr
->mainPtr
= mainPtr
;
604 hPtr
= Tcl_CreateHashEntry(&mainPtr
->nameTable
, ".", &dummy
);
605 Tcl_SetHashValue(hPtr
, winPtr
);
606 winPtr
->pathName
= Tcl_GetHashKey(&mainPtr
->nameTable
, hPtr
);
609 * Register the interpreter for "send" purposes. If baseName isn't
610 * already unique, find a unique suffix to add to it to make it
611 * unique. Change the window's name to contain the suffix.
614 result
= Tk_RegisterInterp(interp
, baseName
, tkwin
);
615 if (result
== TCL_OK
) {
616 winPtr
->nameUid
= Tk_GetUid(baseName
);
622 sprintf(newName
, "%.100s #%d", baseName
, i
);
623 Tcl_SetResult(interp
, (char *) NULL
, TCL_STATIC
);
624 result
= Tk_RegisterInterp(interp
, newName
, tkwin
);
625 if (result
== TCL_OK
) {
629 Tcl_SetResult(interp
,
630 "couldn't generate unique name to register application",
632 Tk_DestroyWindow(tkwin
);
635 winPtr
->nameUid
= Tk_GetUid(newName
);
639 * Bind in Tk's commands.
642 for (cmdPtr
= commands
; cmdPtr
->name
!= NULL
; cmdPtr
++) {
643 Tcl_CreateCommand(interp
, cmdPtr
->name
, cmdPtr
->cmdProc
,
644 (ClientData
) tkwin
, (void (*)(int *)) NULL
);
648 * Set variables for the intepreter.
651 Tcl_SetVar(interp
, "tk_library", TK_Library
, TCL_GLOBAL_ONLY
);
652 Tcl_SetVar(interp
, "tk_version", TK_VERSION
, TCL_GLOBAL_ONLY
);
653 Tcl_SetVar(interp
, "tkVersion", TK_VERSION
, TCL_GLOBAL_ONLY
);
660 *--------------------------------------------------------------
664 * Create a new internal or top-level window as a child of an
668 * The return value is a token for the new window. This
669 * is not the same as X's token for the window. If an error
670 * occurred in creating the window (e.g. no such display or
671 * screen), then an error message is left in interp->result and
675 * A new window structure is allocated locally. An X
676 * window is not initially created, but will be created
677 * the first time the window is mapped.
679 *--------------------------------------------------------------
684 Tcl_Interp
*interp
, /* Interpreter to use for error reporting.
685 * Interp->result is assumed to be
686 * initialized by the caller. */
687 Tk_Window parent
, /* Token for parent of new window. */
688 char *name
, /* Name for new window. Must be unique
689 * among parent's children. */
690 char *screenName
/* If NULL, new window will be internal on
691 * same screen as its parent. If non-NULL,
692 * gives name of screen on which to create
693 * new window; window will be a top-level
697 TkWindow
*parentPtr
= (TkWindow
*) parent
;
700 if (screenName
== NULL
) {
701 winPtr
= NewWindow(parentPtr
->dispPtr
, parentPtr
->screenNum
);
702 if (NameWindow(interp
, winPtr
, parentPtr
, name
) != TCL_OK
) {
703 Tk_DestroyWindow((Tk_Window
) winPtr
);
706 return (Tk_Window
) winPtr
;
710 * This is a fix for dvx XOpenDisplay... display name conformalization
716 strcpy(dsp
, screenName
);
718 if (len
&& (dsp
[len
-1] == '.'))
721 return CreateTopLevelWindow(interp
, parent
, name
, dsp
);
726 *----------------------------------------------------------------------
728 * Tk_CreateWindowFromPath --
730 * This procedure is similar to Tk_CreateInternalWindow except
731 * that it uses a path name to create the window, rather than
732 * a parent and a child name.
735 * The return value is a token for the new window. This
736 * is not the same as X's token for the window. If an error
737 * occurred in creating the window (e.g. no such display or
738 * screen), then an error message is left in interp->result and
742 * A new window structure is allocated locally. An X
743 * window is not initially created, but will be created
744 * the first time the window is mapped.
746 *----------------------------------------------------------------------
750 Tk_CreateWindowFromPath (
751 Tcl_Interp
*interp
, /* Interpreter to use for error reporting.
752 * Interp->result is assumed to be
753 * initialized by the caller. */
754 Tk_Window tkwin
, /* Token for any window in application
755 * that is to contain new window. */
756 char *pathName
, /* Path name for new window within the
757 * application of tkwin. The parent of
758 * this window must already exist, but
759 * the window itself must not exist. */
760 char *screenName
/* If NULL, new window will be on same
761 * screen as its parent. If non-NULL,
762 * gives name of screen on which to create
763 * new window; window will be a top-level
767 #define FIXED_SPACE 5
768 char fixedSpace
[FIXED_SPACE
+1];
774 * Strip the parent's name out of pathName (it's everything up
775 * to the last dot). There are two tricky parts: (a) must
776 * copy the parent's name somewhere else to avoid modifying
777 * the pathName string (for large names, space for the copy
778 * will have to be malloc'ed); (b) must special-case the
779 * situation where the parent is ".".
782 p
= strrchr(pathName
, '.');
784 Tcl_AppendResult(interp
, "bad window path name \"", pathName
,
785 "\"", (char *) NULL
);
788 numChars
= p
-pathName
;
789 if (numChars
> FIXED_SPACE
) {
790 p
= (char *) ckalloc((unsigned) (numChars
+1));
798 strncpy(p
, pathName
, numChars
);
803 * Find the parent window.
806 parent
= Tk_NameToWindow(interp
, p
, tkwin
);
807 if (p
!= fixedSpace
) {
810 if (parent
== NULL
) {
818 if (screenName
== NULL
) {
819 TkWindow
*parentPtr
= (TkWindow
*) parent
;
822 winPtr
= NewWindow(parentPtr
->dispPtr
, parentPtr
->screenNum
);
823 if (NameWindow(interp
, winPtr
, parentPtr
, pathName
+numChars
+1)
825 Tk_DestroyWindow((Tk_Window
) winPtr
);
828 return (Tk_Window
) winPtr
;
831 return CreateTopLevelWindow(interp
, parent
, pathName
+numChars
+1,
837 *--------------------------------------------------------------
839 * Tk_DestroyWindow --
841 * Destroy an existing window. After this call, the caller
842 * should never again use the token.
848 * The window is deleted, along with all of its children.
849 * Relevant callback procedures are invoked.
851 *--------------------------------------------------------------
856 Tk_Window tkwin
/* Window to destroy. */
859 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
863 * Recursively destroy children. The TK_RECURSIVE_DESTROY
864 * flags means that the child's window needn't be explicitly
865 * destroyed (the destroy of the parent already did it), nor
866 * does it need to be removed from its parent's child list,
867 * since the parent is being destroyed too.
870 while (winPtr
->childList
!= NULL
) {
871 winPtr
->childList
->flags
|= TK_RECURSIVE_DESTROY
;
872 Tk_DestroyWindow((Tk_Window
) winPtr
->childList
);
876 * Generate a DestroyNotify event. In order for the DestroyNotify
877 * event to be processed correctly, need to make sure the window
878 * exists. This is a bit of a kludge, and may be unnecessarily
879 * expensive, but without it no event handlers will get called for
880 * windows that don't exist yet.
883 if (winPtr
->window
== None
) {
884 Tk_MakeWindowExist(tkwin
);
886 winPtr
->flags
|= TK_ALREADY_DEAD
;
887 event
.type
= DestroyNotify
;
888 event
.xdestroywindow
.serial
=
889 LastKnownRequestProcessed(winPtr
->display
);
890 event
.xdestroywindow
.send_event
= False
;
891 event
.xdestroywindow
.display
= winPtr
->display
;
892 event
.xdestroywindow
.event
= winPtr
->window
;
893 event
.xdestroywindow
.window
= winPtr
->window
;
894 Tk_HandleEvent(&event
);
897 * Cleanup the data structures associated with this window.
898 * No need to destroy windows during recursive destroys, since
899 * that will happen automatically when the parent window is
900 * destroyed (not true for top-level windows: must destroy
904 if (winPtr
->window
!= None
) {
905 if (!(winPtr
->flags
& TK_RECURSIVE_DESTROY
)
906 || (winPtr
->flags
& TK_TOP_LEVEL
)) {
907 XDestroyWindow(winPtr
->display
, winPtr
->window
);
909 XDeleteContext(winPtr
->display
, winPtr
->window
, tkWindowContext
);
910 winPtr
->window
= None
;
912 if (winPtr
->parentPtr
!= NULL
) {
913 if (winPtr
->parentPtr
->childList
== winPtr
) {
914 winPtr
->parentPtr
->childList
= winPtr
->nextPtr
;
916 register TkWindow
*winPtr2
;
918 for (winPtr2
= winPtr
->parentPtr
->childList
; ;
919 winPtr2
= winPtr2
->nextPtr
) {
920 if (winPtr2
== NULL
) {
921 panic("Tk_DestroyWindow couldn't find child in parent (deleted twice?)");
924 if (winPtr2
->nextPtr
== winPtr
) {
925 winPtr2
->nextPtr
= winPtr
->nextPtr
;
931 TkEventDeadWindow(winPtr
);
932 TkOptionDeadWindow(winPtr
);
933 TkSelDeadWindow(winPtr
);
934 if (winPtr
->flags
& TK_TOP_LEVEL
) {
935 TkWmDeadWindow(winPtr
);
937 TkGrabDeadWindow(winPtr
);
938 if (winPtr
->mainPtr
!= NULL
) {
939 Tk_DeleteAllBindings(winPtr
->mainPtr
->bindingTable
,
940 (ClientData
) winPtr
->pathName
);
941 if (winPtr
->pathName
!= NULL
) {
942 Tcl_DeleteHashEntry(Tcl_FindHashEntry(&winPtr
->mainPtr
->nameTable
,
945 if (winPtr
->mainPtr
->winPtr
== winPtr
) {
946 register TkCmd
*cmdPtr
;
949 * Deleting a main window. Delete the TkMainInfo structure too
950 * and replace all of Tk's commands with dummy commands that
951 * return errors. Also delete the "send" command to unregister
955 for (cmdPtr
= commands
; cmdPtr
->name
!= NULL
; cmdPtr
++) {
956 Tcl_CreateCommand(winPtr
->mainPtr
->interp
, cmdPtr
->name
,
957 TkDeadAppCmd
, (ClientData
) NULL
, (void (*)(int *)) NULL
);
959 Tcl_CreateCommand(winPtr
->mainPtr
->interp
, "send",
960 TkDeadAppCmd
, (ClientData
) NULL
, (void (*)(int *)) NULL
);
961 Tcl_DeleteHashTable(&winPtr
->mainPtr
->nameTable
);
962 Tk_DeleteBindingTable(winPtr
->mainPtr
->bindingTable
);
963 ckfree((char *) winPtr
->mainPtr
);
967 ckfree((char *) winPtr
);
971 *--------------------------------------------------------------
975 * Map a window within its parent. This may require the
976 * window and/or its parents to actually be created.
982 * The given window will be mapped. Windows may also
985 *--------------------------------------------------------------
990 Tk_Window tkwin
/* Token for window to map. */
993 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
995 if (winPtr
->flags
& TK_MAPPED
) {
998 if (winPtr
->window
== None
) {
999 Tk_MakeWindowExist(tkwin
);
1001 if (winPtr
->flags
& TK_TOP_LEVEL
) {
1002 if (!TkWmMapWindow(winPtr
)) {
1007 * Don't set the mapped flag for top-level windows: TkWmMapWindow
1008 * does it if appropriate (e.g. if the window is going to be non-
1012 winPtr
->flags
|= TK_MAPPED
;
1014 XMapWindow(winPtr
->display
, winPtr
->window
);
1015 if (!(winPtr
->flags
& TK_TOP_LEVEL
)) {
1018 event
.type
= MapNotify
;
1019 event
.xmap
.serial
= LastKnownRequestProcessed(winPtr
->display
);
1020 event
.xmap
.send_event
= False
;
1021 event
.xmap
.display
= winPtr
->display
;
1022 event
.xmap
.event
= winPtr
->window
;
1023 event
.xmap
.window
= winPtr
->window
;
1024 event
.xmap
.override_redirect
= winPtr
->atts
.override_redirect
;
1025 Tk_HandleEvent(&event
);
1030 *--------------------------------------------------------------
1032 * Tk_MakeWindowExist --
1034 * Ensure that a particular window actually exists. This
1035 * procedure shouldn't normally need to be invoked from
1036 * outside the Tk package, but may be needed if someone
1037 * wants to manipulate a window before mapping it.
1043 * When the procedure returns, the X window associated with
1044 * tkwin is guaranteed to exist. This may require the
1045 * window's ancestors to be created also.
1047 *--------------------------------------------------------------
1051 Tk_MakeWindowExist (
1052 Tk_Window tkwin
/* Token for window. */
1055 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1058 if (winPtr
->window
!= None
) {
1062 if (winPtr
->flags
& TK_TOP_LEVEL
) {
1064 * workaround by dhopkins for OLPC Micropolis gtk.Socket integration.
1067 if (tk_RootWindow
) {
1072 XRootWindow(winPtr
->display
, winPtr
->screenNum
);
1076 if (winPtr
->parentPtr
->window
== None
) {
1077 Tk_MakeWindowExist((Tk_Window
) winPtr
->parentPtr
);
1079 parent
= winPtr
->parentPtr
->window
;
1082 /* workaround to support non-default colormaps */
1084 winPtr
->window
= XCreateWindow(winPtr
->display
, parent
,
1085 winPtr
->changes
.x
, winPtr
->changes
.y
,
1086 winPtr
->changes
.width
, winPtr
->changes
.height
,
1087 winPtr
->changes
.border_width
, CopyFromParent
,
1088 InputOutput
, CopyFromParent
, winPtr
->dirtyAtts
,
1091 { Screen
*scr
= ScreenOfDisplay(winPtr
->display
, winPtr
->screenNum
);
1093 winPtr
->dirtyAtts
|= CWColormap
| CWBorderPixmap
;
1094 winPtr
->atts
.colormap
= Tk_DefaultColormap(scr
);
1095 winPtr
->atts
.border_pixmap
= Tk_DefaultPixmap(scr
);
1097 winPtr
->window
= XCreateWindow(winPtr
->display
, parent
,
1098 winPtr
->changes
.x
, winPtr
->changes
.y
,
1099 winPtr
->changes
.width
, winPtr
->changes
.height
,
1100 winPtr
->changes
.border_width
,
1101 Tk_DefaultDepth(scr
),
1103 Tk_DefaultVisual(scr
),
1104 winPtr
->dirtyAtts
, &winPtr
->atts
);
1108 XSaveContext(winPtr
->display
, winPtr
->window
, tkWindowContext
,
1110 winPtr
->dirtyAtts
= 0;
1111 winPtr
->dirtyChanges
&= ~(CWX
|CWY
|CWWidth
|CWHeight
|CWBorderWidth
);
1112 if (winPtr
->dirtyChanges
!= 0) {
1113 XConfigureWindow(winPtr
->display
, winPtr
->window
,
1114 winPtr
->dirtyChanges
, &winPtr
->changes
);
1115 winPtr
->dirtyChanges
= 0;
1119 * Issue a ConfigureNotify event if there were deferred configuration
1123 if (winPtr
->flags
& TK_NEED_CONFIG_NOTIFY
) {
1124 winPtr
->flags
&= ~TK_NEED_CONFIG_NOTIFY
;
1125 DoConfigureNotify(winPtr
);
1130 *--------------------------------------------------------------
1132 * Tk_UnmapWindow, etc. --
1134 * There are several procedures under here, each of which
1135 * mirrors an existing X procedure. In addition to performing
1136 * the functions of the corresponding procedure, each
1137 * procedure also updates the local window structure and
1138 * synthesizes an X event (if the window's structure is being
1139 * managed internally).
1142 * See the manual entries.
1145 * See the manual entries.
1147 *--------------------------------------------------------------
1152 Tk_Window tkwin
/* Token for window to unmap. */
1155 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1157 if (!(winPtr
->flags
& TK_MAPPED
)) {
1160 winPtr
->flags
&= ~TK_MAPPED
;
1161 XUnmapWindow(winPtr
->display
, winPtr
->window
);
1162 if (!(winPtr
->flags
& TK_TOP_LEVEL
)) {
1165 event
.type
= UnmapNotify
;
1166 event
.xunmap
.serial
= LastKnownRequestProcessed(winPtr
->display
);
1167 event
.xunmap
.send_event
= False
;
1168 event
.xunmap
.display
= winPtr
->display
;
1169 event
.xunmap
.event
= winPtr
->window
;
1170 event
.xunmap
.window
= winPtr
->window
;
1171 event
.xunmap
.from_configure
= False
;
1172 Tk_HandleEvent(&event
);
1177 Tk_ConfigureWindow (
1178 Tk_Window tkwin
, /* Window to re-configure. */
1179 unsigned int valueMask
, /* Mask indicating which parts of
1180 * *valuePtr are to be used. */
1181 XWindowChanges
*valuePtr
/* New values. */
1184 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1186 if ((winPtr
->window
== None
) || !(winPtr
->flags
& TK_TOP_LEVEL
)) {
1187 if (valueMask
& CWX
) {
1188 winPtr
->changes
.x
= valuePtr
->x
;
1190 if (valueMask
& CWY
) {
1191 winPtr
->changes
.y
= valuePtr
->y
;
1193 if (valueMask
& CWWidth
) {
1194 winPtr
->changes
.width
= valuePtr
->width
;
1196 if (valueMask
& CWHeight
) {
1197 winPtr
->changes
.height
= valuePtr
->height
;
1199 if (valueMask
& CWBorderWidth
) {
1200 winPtr
->changes
.border_width
= valuePtr
->border_width
;
1202 if (valueMask
& CWSibling
) {
1203 winPtr
->changes
.sibling
= valuePtr
->sibling
;
1205 if (valueMask
& CWStackMode
) {
1206 winPtr
->changes
.stack_mode
= valuePtr
->stack_mode
;
1210 if (winPtr
->window
!= None
) {
1211 XConfigureWindow(winPtr
->display
, winPtr
->window
,
1212 valueMask
, valuePtr
);
1213 if (!(winPtr
->flags
& TK_TOP_LEVEL
)) {
1214 DoConfigureNotify(winPtr
);
1217 winPtr
->dirtyChanges
|= valueMask
;
1218 winPtr
->flags
|= TK_NEED_CONFIG_NOTIFY
;
1224 Tk_Window tkwin
, /* Window to move. */
1226 int y
/* New location for window (within
1230 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1232 if (winPtr
->window
!= None
) {
1233 XMoveWindow(winPtr
->display
, winPtr
->window
, x
, y
);
1234 if (!(winPtr
->flags
& TK_TOP_LEVEL
)) {
1235 winPtr
->changes
.x
= x
;
1236 winPtr
->changes
.y
= y
;
1237 DoConfigureNotify(winPtr
);
1240 winPtr
->changes
.x
= x
;
1241 winPtr
->changes
.y
= y
;
1242 winPtr
->dirtyChanges
|= CWX
|CWY
;
1243 winPtr
->flags
|= TK_NEED_CONFIG_NOTIFY
;
1249 Tk_Window tkwin
, /* Window to resize. */
1251 unsigned int height
/* New dimensions for window. */
1254 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1256 if (winPtr
->window
!= None
) {
1257 XResizeWindow(winPtr
->display
, winPtr
->window
, width
, height
);
1258 if (!(winPtr
->flags
& TK_TOP_LEVEL
)) {
1259 winPtr
->changes
.width
= width
;
1260 winPtr
->changes
.height
= height
;
1261 DoConfigureNotify(winPtr
);
1264 winPtr
->changes
.width
= width
;
1265 winPtr
->changes
.height
= height
;
1266 winPtr
->dirtyChanges
|= CWWidth
|CWHeight
;
1267 winPtr
->flags
|= TK_NEED_CONFIG_NOTIFY
;
1272 Tk_MoveResizeWindow (
1273 Tk_Window tkwin
, /* Window to move and resize. */
1275 int y
, /* New location for window (within
1278 unsigned int height
/* New dimensions for window. */
1281 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1283 if (winPtr
->window
!= None
) {
1284 XMoveResizeWindow(winPtr
->display
, winPtr
->window
,
1285 x
, y
, width
, height
);
1286 if (!(winPtr
->flags
& TK_TOP_LEVEL
)) {
1287 winPtr
->changes
.x
= x
;
1288 winPtr
->changes
.y
= y
;
1289 winPtr
->changes
.width
= width
;
1290 winPtr
->changes
.height
= height
;
1291 DoConfigureNotify(winPtr
);
1294 winPtr
->changes
.x
= x
;
1295 winPtr
->changes
.y
= y
;
1296 winPtr
->changes
.width
= width
;
1297 winPtr
->changes
.height
= height
;
1298 winPtr
->dirtyChanges
|= CWX
|CWY
|CWWidth
|CWHeight
;
1299 winPtr
->flags
|= TK_NEED_CONFIG_NOTIFY
;
1304 Tk_SetWindowBorderWidth (
1305 Tk_Window tkwin
, /* Window to modify. */
1306 int width
/* New border width for window. */
1309 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1311 winPtr
->changes
.border_width
= width
;
1312 if (winPtr
->window
!= None
) {
1313 XSetWindowBorderWidth(winPtr
->display
, winPtr
->window
, width
);
1314 if (!(winPtr
->flags
& TK_TOP_LEVEL
)) {
1315 DoConfigureNotify(winPtr
);
1318 winPtr
->dirtyChanges
|= CWBorderWidth
;
1319 winPtr
->flags
|= TK_NEED_CONFIG_NOTIFY
;
1324 Tk_ChangeWindowAttributes (
1325 Tk_Window tkwin
, /* Window to manipulate. */
1326 unsigned long valueMask
, /* OR'ed combination of bits,
1327 * indicating which fields of
1328 * *attsPtr are to be used. */
1329 register XSetWindowAttributes
*attsPtr
1331 /* New values for some attributes. */
1333 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1335 if (valueMask
& CWBackPixmap
) {
1336 winPtr
->atts
.background_pixmap
= attsPtr
->background_pixmap
;
1338 if (valueMask
& CWBackPixel
) {
1339 winPtr
->atts
.background_pixel
= attsPtr
->background_pixel
;
1341 if (valueMask
& CWBorderPixmap
) {
1342 winPtr
->atts
.border_pixmap
= attsPtr
->border_pixmap
;
1344 if (valueMask
& CWBorderPixel
) {
1345 winPtr
->atts
.border_pixel
= attsPtr
->border_pixel
;
1347 if (valueMask
& CWBitGravity
) {
1348 winPtr
->atts
.bit_gravity
= attsPtr
->bit_gravity
;
1350 if (valueMask
& CWWinGravity
) {
1351 winPtr
->atts
.win_gravity
= attsPtr
->win_gravity
;
1353 if (valueMask
& CWBackingStore
) {
1354 winPtr
->atts
.backing_store
= attsPtr
->backing_store
;
1356 if (valueMask
& CWBackingPlanes
) {
1357 winPtr
->atts
.backing_planes
= attsPtr
->backing_planes
;
1359 if (valueMask
& CWBackingPixel
) {
1360 winPtr
->atts
.backing_pixel
= attsPtr
->backing_pixel
;
1362 if (valueMask
& CWOverrideRedirect
) {
1363 winPtr
->atts
.override_redirect
= attsPtr
->override_redirect
;
1365 if (valueMask
& CWSaveUnder
) {
1366 winPtr
->atts
.save_under
= attsPtr
->save_under
;
1368 if (valueMask
& CWEventMask
) {
1369 winPtr
->atts
.event_mask
= attsPtr
->event_mask
;
1371 if (valueMask
& CWDontPropagate
) {
1372 winPtr
->atts
.do_not_propagate_mask
1373 = attsPtr
->do_not_propagate_mask
;
1375 if (valueMask
& CWColormap
) {
1376 winPtr
->atts
.colormap
= attsPtr
->colormap
;
1378 if (valueMask
& CWCursor
) {
1379 winPtr
->atts
.cursor
= attsPtr
->cursor
;
1382 if (winPtr
->window
!= None
) {
1383 XChangeWindowAttributes(winPtr
->display
, winPtr
->window
,
1384 valueMask
, attsPtr
);
1386 winPtr
->dirtyAtts
|= valueMask
;
1391 Tk_SetWindowBackground (
1392 Tk_Window tkwin
, /* Window to manipulate. */
1393 unsigned long pixel
/* Pixel value to use for
1394 * window's background. */
1397 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1399 winPtr
->atts
.background_pixel
= pixel
;
1401 if (winPtr
->window
!= None
) {
1402 XSetWindowBackground(winPtr
->display
, winPtr
->window
, pixel
);
1404 winPtr
->dirtyAtts
= (winPtr
->dirtyAtts
& ~CWBackPixmap
)
1410 Tk_SetWindowBackgroundPixmap (
1411 Tk_Window tkwin
, /* Window to manipulate. */
1412 Pixmap pixmap
/* Pixmap to use for window's
1416 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1418 winPtr
->atts
.background_pixmap
= pixmap
;
1420 if (winPtr
->window
!= None
) {
1421 XSetWindowBackgroundPixmap(winPtr
->display
,
1422 winPtr
->window
, pixmap
);
1424 winPtr
->dirtyAtts
= (winPtr
->dirtyAtts
& ~CWBackPixel
)
1430 Tk_SetWindowBorder (
1431 Tk_Window tkwin
, /* Window to manipulate. */
1432 unsigned long pixel
/* Pixel value to use for
1433 * window's border. */
1436 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1438 winPtr
->atts
.border_pixel
= pixel
;
1440 if (winPtr
->window
!= None
) {
1441 XSetWindowBorder(winPtr
->display
, winPtr
->window
, pixel
);
1443 winPtr
->dirtyAtts
= (winPtr
->dirtyAtts
& ~CWBorderPixmap
)
1449 Tk_SetWindowBorderPixmap (
1450 Tk_Window tkwin
, /* Window to manipulate. */
1451 Pixmap pixmap
/* Pixmap to use for window's
1455 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1457 winPtr
->atts
.border_pixmap
= pixmap
;
1459 if (winPtr
->window
!= None
) {
1460 XSetWindowBorderPixmap(winPtr
->display
,
1461 winPtr
->window
, pixmap
);
1463 winPtr
->dirtyAtts
= (winPtr
->dirtyAtts
& ~CWBorderPixel
)
1470 Tk_Window tkwin
, /* Window to manipulate. */
1471 Cursor cursor
/* Cursor to use for window (may be None). */
1474 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1476 winPtr
->atts
.cursor
= cursor
;
1478 if (winPtr
->window
!= None
) {
1479 XDefineCursor(winPtr
->display
, winPtr
->window
, cursor
);
1481 winPtr
->dirtyAtts
= winPtr
->dirtyAtts
| CWCursor
;
1487 Tk_Window tkwin
/* Window to manipulate. */
1490 Tk_DefineCursor(tkwin
, None
);
1494 *----------------------------------------------------------------------
1496 * DoConfigureNotify --
1498 * Generate a ConfigureNotify event describing the current
1499 * configuration of a window.
1505 * An event is generated and processed by Tk_HandleEvent.
1507 *----------------------------------------------------------------------
1512 register TkWindow
*winPtr
/* Window whose configuration
1513 * was just changed. */
1518 event
.type
= ConfigureNotify
;
1519 event
.xconfigure
.serial
= LastKnownRequestProcessed(winPtr
->display
);
1520 event
.xconfigure
.send_event
= False
;
1521 event
.xconfigure
.display
= winPtr
->display
;
1522 event
.xconfigure
.event
= winPtr
->window
;
1523 event
.xconfigure
.window
= winPtr
->window
;
1524 event
.xconfigure
.x
= winPtr
->changes
.x
;
1525 event
.xconfigure
.y
= winPtr
->changes
.y
;
1526 event
.xconfigure
.width
= winPtr
->changes
.width
;
1527 event
.xconfigure
.height
= winPtr
->changes
.height
;
1528 event
.xconfigure
.border_width
= winPtr
->changes
.border_width
;
1529 if (winPtr
->changes
.stack_mode
== Above
) {
1530 event
.xconfigure
.above
= winPtr
->changes
.sibling
;
1532 event
.xconfigure
.above
= None
;
1534 event
.xconfigure
.override_redirect
= winPtr
->atts
.override_redirect
;
1535 Tk_HandleEvent(&event
);
1539 *----------------------------------------------------------------------
1543 * This procedure is used to give a window a class.
1549 * A new class is stored for tkwin, replacing any existing
1552 *----------------------------------------------------------------------
1557 Tk_Window tkwin
, /* Token for window to assign class. */
1558 char *className
/* New class for tkwin. */
1561 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1563 winPtr
->classUid
= Tk_GetUid(className
);
1564 if (winPtr
->flags
& TK_TOP_LEVEL
) {
1565 TkWmSetClass(winPtr
);
1570 *----------------------------------------------------------------------
1572 * Tk_NameToWindow --
1574 * Given a string name for a window, this procedure
1575 * returns the token for the window, if there exists a
1576 * window corresponding to the given name.
1579 * The return result is either a token for the window corresponding
1580 * to "name", or else NULL to indicate that there is no such
1581 * window. In this case, an error message is left in interp->result.
1586 *----------------------------------------------------------------------
1591 Tcl_Interp
*interp
, /* Where to report errors. */
1592 char *pathName
, /* Path name of window. */
1593 Tk_Window tkwin
/* Token for window: name is assumed to
1594 * belong to the same main window as tkwin. */
1597 Tcl_HashEntry
*hPtr
;
1599 hPtr
= Tcl_FindHashEntry(&((TkWindow
*) tkwin
)->mainPtr
->nameTable
,
1602 Tcl_AppendResult(interp
, "bad window path name \"",
1603 pathName
, "\"", (char *) NULL
);
1606 return (Tk_Window
) Tcl_GetHashValue(hPtr
);
1610 *----------------------------------------------------------------------
1614 * Return the textual name of a window's display.
1617 * The return value is the string name of the display associated
1623 *----------------------------------------------------------------------
1628 Tk_Window tkwin
/* Window whose display name is desired. */
1631 return ((TkWindow
*) tkwin
)->dispPtr
->name
;