]> cvs.zerfleddert.de Git - micropolis/blob - src/tk/tkwindow.c
Add legacy mode inspired by the work of virtuallyfun/tenox7
[micropolis] / src / tk / tkwindow.c
1 /*
2 * tkWindow.c --
3 *
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
7 * structure.
8 *
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.
17 */
18
19 #ifndef lint
20 static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkWindow.c,v 1.92 92/08/21 11:42:44 ouster Exp $ SPRITE (Berkeley)";
21 #endif
22
23 #include "tkconfig.h"
24 #include "tkint.h"
25
26 /*
27 * Global absolute file name:
28 */
29 char *TK_Library = TK_LIBRARY;
30
31 /*
32 * Count of open displays.
33 */
34 int tk_Displays;
35
36 /*
37 * Count of number of main windows currently open in this process.
38 */
39
40 int tk_NumMainWindows;
41
42 /*
43 * Added by dhopkins for OLPC Micropolis gtk.Socket integration.
44 */
45
46 Window tk_RootWindow = 0;
47
48 /*
49 * List of all displays currently in use.
50 */
51
52 TkDisplay *tkDisplayList = NULL;
53
54 /*
55 * Have statics in this module been initialized?
56 */
57
58 static int initialized = 0;
59
60 /*
61 * Context information used to map from X window id's to
62 * TkWindow structures (during event handling, for example):
63 */
64
65 XContext tkWindowContext;
66
67 /*
68 * The variables below hold several uid's that are used in many places
69 * in the toolkit.
70 */
71
72 Tk_Uid tkDisabledUid = NULL;
73 Tk_Uid tkActiveUid = NULL;
74 Tk_Uid tkNormalUid = NULL;
75
76 /*
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.
80 */
81
82 static XWindowChanges defChanges = {
83 0, 0, 1, 1, 0, 0, Above
84 };
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 */
94 0, /* border_pixel */
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 */
105 None /* cursor */
106 };
107
108 /*
109 * The following structure defines all of the commands supported by
110 * Tk, and the C procedures that execute them.
111 */
112
113 typedef struct {
114 char *name; /* Name of command. */
115 int (*cmdProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
116 int argc, char **argv));
117 /* Command procedure. */
118 } TkCmd;
119
120 TkCmd commands[] = {
121 /*
122 * Commands that are part of the intrinsics:
123 */
124
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},
137 {"winfo-setlegacy", Tk_WinfoCmdSetLegacy},
138 {"wm", Tk_WmCmd},
139 {"accept", Tcp_AcceptCmd},
140 {"shutdown", Tcp_ShutdownCmd},
141 {"connect", Tcp_ConnectCmd},
142 {"filehandler", Tcp_FileHandlerCmd},
143
144 /*
145 * Widget-creation commands.
146 */
147 {"button", Tk_ButtonCmd},
148 {"canvas", Tk_CanvasCmd},
149 {"checkbutton", Tk_ButtonCmd},
150 {"entry", Tk_EntryCmd},
151 {"frame", Tk_FrameCmd},
152 {"label", Tk_ButtonCmd},
153 {"listbox", Tk_ListboxCmd},
154 {"menu", Tk_MenuCmd},
155 {"menubutton", Tk_MenubuttonCmd},
156 {"message", Tk_MessageCmd},
157 {"radiobutton", Tk_ButtonCmd},
158 {"scale", Tk_ScaleCmd},
159 {"scrollbar", Tk_ScrollbarCmd},
160 {"text", Tk_TextCmd},
161 {"toplevel", Tk_FrameCmd},
162 {(char *) NULL, (int (*)(int *, Tcl_Interp *, int, char **)) NULL}
163 };
164
165 /*
166 * Forward declarations to procedures defined later in this file:
167 */
168
169 static Tk_Window CreateTopLevelWindow _ANSI_ARGS_((Tcl_Interp *interp,
170 Tk_Window parent, char *name, char *screenName));
171 static void DoConfigureNotify _ANSI_ARGS_((TkWindow *winPtr));
172 static TkDisplay * GetScreen _ANSI_ARGS_((Tcl_Interp *interp,
173 char *screenName, int *screenPtr));
174 static int NameWindow _ANSI_ARGS_((Tcl_Interp *interp,
175 TkWindow *winPtr, TkWindow *parentPtr,
176 char *name));
177 static TkWindow * NewWindow _ANSI_ARGS_((TkDisplay *dispPtr,
178 int screenNum));
179 \f
180 /*
181 *----------------------------------------------------------------------
182 *
183 * CreateTopLevelWindow --
184 *
185 * Make a new window that will be at top-level (its parent will
186 * be the root window of a screen).
187 *
188 * Results:
189 * The return value is a token for the new window, or NULL if
190 * an error prevented the new window from being created. If
191 * NULL is returned, an error message will be left in
192 * interp->result.
193 *
194 * Side effects:
195 * A new window structure is allocated locally. An X
196 * window is NOT initially created, but will be created
197 * the first time the window is mapped.
198 *
199 *----------------------------------------------------------------------
200 */
201
202 static Tk_Window
203 CreateTopLevelWindow (
204 Tcl_Interp *interp, /* Interpreter to use for error reporting. */
205 Tk_Window parent, /* Token for logical parent of new window
206 * (used for naming, options, etc.). May
207 * be NULL. */
208 char *name, /* Name for new window; if parent is
209 * non-NULL, must be unique among parent's
210 * children. */
211 char *screenName /* Name of screen on which to create
212 * window. NULL means use DISPLAY environment
213 * variable to determine. Empty string means
214 * use parent's screen, or DISPLAY if no
215 * parent. */
216 )
217 {
218 register TkWindow *winPtr;
219 register TkDisplay *dispPtr;
220 int screenId;
221
222 if (!initialized) {
223 initialized = 1;
224 tkWindowContext = XUniqueContext();
225 tkActiveUid = Tk_GetUid("active");
226 tkDisabledUid = Tk_GetUid("disabled");
227 tkNormalUid = Tk_GetUid("normal");
228 }
229
230 if ((parent != NULL) && (screenName != NULL) && (screenName[0] == '\0')) {
231 dispPtr = ((TkWindow *) parent)->dispPtr;
232 screenId = Tk_ScreenNumber(parent);
233 } else {
234 dispPtr = GetScreen(interp, screenName, &screenId);
235 if (dispPtr == NULL) {
236 return (Tk_Window) NULL;
237 }
238 }
239
240 winPtr = NewWindow(dispPtr, screenId);
241
242 /*
243 * Internal windows don't normally ask for StructureNotify events,
244 * since we can generate them internally. However, for top-level
245 * windows we need to as for the events because the window could
246 * be manipulated externally.
247 */
248
249 winPtr->atts.event_mask |= StructureNotifyMask;
250
251 /*
252 * (Need to set the TK_TOP_LEVEL flag immediately here; otherwise
253 * Tk_DestroyWindow will core dump if it is called before the flag
254 * has been set.)
255 */
256
257 winPtr->flags |= TK_TOP_LEVEL;
258 if (parent != NULL) {
259 if (NameWindow(interp, winPtr, (TkWindow *) parent, name) != TCL_OK) {
260 Tk_DestroyWindow((Tk_Window) winPtr);
261 return (Tk_Window) NULL;
262 }
263 }
264 TkWmNewWindow(winPtr);
265 return (Tk_Window) winPtr;
266 }
267 \f
268 /*
269 *----------------------------------------------------------------------
270 *
271 * GetScreen --
272 *
273 * Given a string name for a display-plus-screen, find the
274 * TkDisplay structure for the display and return the screen
275 * number too.
276 *
277 * Results:
278 * The return value is a pointer to information about the display,
279 * or NULL if the display couldn't be opened. In this case, an
280 * error message is left in interp->result. The location at
281 * *screenPtr is overwritten with the screen number parsed from
282 * screenName.
283 *
284 * Side effects:
285 * A new connection is opened to the display if there is no
286 * connection already. A new TkDisplay data structure is also
287 * setup, if necessary.
288 *
289 *----------------------------------------------------------------------
290 */
291
292 static TkDisplay *
293 GetScreen (
294 Tcl_Interp *interp, /* Place to leave error message. */
295 char *screenName, /* Name for screen. NULL or empty means
296 * use DISPLAY envariable. */
297 int *screenPtr /* Where to store screen number. */
298 )
299 {
300 register TkDisplay *dispPtr;
301 char *p;
302 int length, screenId;
303
304 /*
305 * Separate the screen number from the rest of the display
306 * name. ScreenName is assumed to have the syntax
307 * <display>.<screen> with the dot and the screen being
308 * optional.
309 */
310
311 if ((screenName == NULL) || (screenName[0] == '\0')) {
312 screenName = getenv("DISPLAY");
313 if (screenName == NULL) {
314 interp->result =
315 "no display name and no $DISPLAY environment variable";
316 return (TkDisplay *) NULL;
317 }
318 }
319 length = strlen(screenName);
320 screenId = 0;
321 p = screenName+length-1;
322 while (isdigit(*p) && (p != screenName)) {
323 p--;
324 }
325 if ((*p == '.') && (p[1] != '\0')) {
326 length = p - screenName;
327 screenId = strtoul(p+1, (char **) NULL, 10);
328 }
329
330 /*
331 * See if we already have a connection to this display. If not,
332 * then open a new connection.
333 */
334
335 for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr) {
336 if (dispPtr == NULL) {
337 Display *display = NULL;
338
339 display = XOpenDisplay(screenName);
340
341 if (display == NULL) {
342 Tcl_AppendResult(interp, "couldn't connect to display \"",
343 screenName, "\"", (char *) NULL);
344 return (TkDisplay *) NULL;
345 }
346 if (getenv("XSYNCHRONIZE") != NULL) {
347 XSynchronize(display, 1);
348 }
349 tk_Displays++;
350 dispPtr = (TkDisplay *) ckalloc(sizeof(TkDisplay));
351 dispPtr->display = display;
352 dispPtr->nextPtr = tkDisplayList;
353 dispPtr->name = (char *) ckalloc((unsigned) (length+1));
354 dispPtr->lastEventTime = CurrentTime;
355 strncpy(dispPtr->name, screenName, length);
356 dispPtr->mouseMainPtr = NULL;
357 dispPtr->name[length] = '\0';
358 dispPtr->symsPerCode = 0;
359 dispPtr->errorPtr = NULL;
360 dispPtr->deleteCount = 0;
361 dispPtr->commWindow = NULL;
362 dispPtr->selectionOwner = NULL;
363 dispPtr->selectionSerial = 0;
364 dispPtr->multipleAtom = None;
365 dispPtr->atomInit = 0;
366 dispPtr->modeModMask = 0;
367 dispPtr->metaModMask = 0;
368 dispPtr->altModMask = 0;
369 dispPtr->cursorFont = None;
370 dispPtr->grabWinPtr = NULL;
371 dispPtr->ungrabWinPtr = NULL;
372 dispPtr->buttonWinPtr = NULL;
373 dispPtr->pointerWinPtr = NULL;
374 dispPtr->serverWinPtr = NULL;
375 dispPtr->grabFlags = 0;
376 dispPtr->focusPtr = NULL;
377 tkDisplayList = dispPtr;
378 Tk_CreateFileHandler(ConnectionNumber(display),
379 TK_READABLE, (void (*)(int *, int)) NULL,
380 (ClientData) display);
381 break;
382 }
383 if ((strncmp(dispPtr->name, screenName, length) == 0)
384 && (dispPtr->name[length] == '\0')) {
385 break;
386 }
387 }
388 if (screenId >= ScreenCount(dispPtr->display)) {
389 sprintf(interp->result, "bad screen number \"%d\"", screenId);
390 return (TkDisplay *) NULL;
391 }
392 *screenPtr = screenId;
393 return dispPtr;
394 }
395 \f
396 /*
397 *--------------------------------------------------------------
398 *
399 * NewWindow --
400 *
401 * This procedure creates and initializes a TkWindow structure.
402 *
403 * Results:
404 * The return value is a pointer to the new window.
405 *
406 * Side effects:
407 * A new window structure is allocated and all its fields are
408 * initialized.
409 *
410 *--------------------------------------------------------------
411 */
412
413 static TkWindow *
414 NewWindow (
415 TkDisplay *dispPtr, /* Display associated with new window. */
416 int screenNum /* Index of screen for new window. */
417 )
418 {
419 register TkWindow *winPtr;
420
421 winPtr = (TkWindow *) ckalloc(sizeof(TkWindow));
422 winPtr->display = dispPtr->display;
423 winPtr->dispPtr = dispPtr;
424 winPtr->screenNum = screenNum;
425 winPtr->window = None;
426 winPtr->childList = NULL;
427 winPtr->parentPtr = NULL;
428 winPtr->nextPtr = NULL;
429 winPtr->mainPtr = NULL;
430 winPtr->pathName = NULL;
431 winPtr->nameUid = NULL;
432 winPtr->classUid = NULL;
433 winPtr->changes = defChanges;
434 winPtr->dirtyChanges = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;
435 winPtr->atts = defAtts;
436 winPtr->dirtyAtts = CWEventMask;
437 winPtr->flags = 0;
438 winPtr->handlerList = NULL;
439 winPtr->focusProc = NULL;
440 winPtr->focusData = NULL;
441 winPtr->optionLevel = -1;
442 winPtr->selHandlerList = NULL;
443 winPtr->selClearProc = NULL;
444 winPtr->selClearData = NULL;
445 winPtr->geomProc = NULL;
446 winPtr->geomData = NULL;
447 winPtr->reqWidth = winPtr->reqHeight = 0;
448 winPtr->internalBorderWidth = 0;
449 winPtr->wmInfoPtr = NULL;
450 return winPtr;
451 }
452 \f
453 /*
454 *----------------------------------------------------------------------
455 *
456 * NameWindow --
457 *
458 * This procedure is invoked to give a window a name and insert
459 * the window into the hierarchy associated with a particular
460 * application.
461 *
462 * Results:
463 * A standard Tcl return value.
464 *
465 * Side effects:
466 * See above.
467 *
468 *----------------------------------------------------------------------
469 */
470
471 static int
472 NameWindow (
473 Tcl_Interp *interp, /* Interpreter to use for error reporting. */
474 register TkWindow *winPtr, /* Window that is to be named and inserted. */
475 TkWindow *parentPtr, /* Pointer to logical parent for winPtr
476 * (used for naming, options, etc.). */
477 char *name /* Name for winPtr; must be unique among
478 * parentPtr's children. */
479 )
480 {
481 #define FIXED_SIZE 200
482 char staticSpace[FIXED_SIZE];
483 char *pathName;
484 int new;
485 Tcl_HashEntry *hPtr;
486 int length1, length2;
487
488 /*
489 * Setup all the stuff except name right away, then do the name stuff
490 * last. This is so that if the name stuff fails, everything else
491 * will be properly initialized (needed to destroy the window cleanly
492 * after the naming failure).
493 */
494 winPtr->parentPtr = parentPtr;
495 winPtr->nextPtr = parentPtr->childList;
496 parentPtr->childList = winPtr;
497 winPtr->mainPtr = parentPtr->mainPtr;
498 winPtr->nameUid = Tk_GetUid(name);
499
500 /*
501 * To permit names of arbitrary length, must be prepared to malloc
502 * a buffer to hold the new path name. To run fast in the common
503 * case where names are short, use a fixed-size buffer on the
504 * stack.
505 */
506
507 length1 = strlen(parentPtr->pathName);
508 length2 = strlen(name);
509 if ((length1+length2+2) <= FIXED_SIZE) {
510 pathName = staticSpace;
511 } else {
512 pathName = (char *) ckalloc((unsigned) (length1+length2+2));
513 }
514 if (length1 == 1) {
515 pathName[0] = '.';
516 strcpy(pathName+1, name);
517 } else {
518 strcpy(pathName, parentPtr->pathName);
519 pathName[length1] = '.';
520 strcpy(pathName+length1+1, name);
521 }
522 hPtr = Tcl_CreateHashEntry(&parentPtr->mainPtr->nameTable, pathName, &new);
523 if (pathName != staticSpace) {
524 ckfree(pathName);
525 }
526 if (!new) {
527 Tcl_AppendResult(interp, "window name \"", name,
528 "\" already exists in parent", (char *) NULL);
529 return TCL_ERROR;
530 }
531 Tcl_SetHashValue(hPtr, winPtr);
532 winPtr->pathName = Tcl_GetHashKey(&parentPtr->mainPtr->nameTable, hPtr);
533 return TCL_OK;
534 }
535 \f
536 /*
537 *----------------------------------------------------------------------
538 *
539 * Tk_CreateMainWindow --
540 *
541 * Make a new main window. A main window is a special kind of
542 * top-level window used as the outermost window in an
543 * application.
544 *
545 * Results:
546 * The return value is a token for the new window, or NULL if
547 * an error prevented the new window from being created. If
548 * NULL is returned, an error message will be left in
549 * interp->result.
550 *
551 * Side effects:
552 * A new window structure is allocated locally; "interp" is
553 * associated with the window and registered for "send" commands
554 * under "baseName". BaseName may be extended with an instance
555 * number in the form "#2" if necessary to make it globally
556 * unique. Tk-related commands are bound into interp. An X
557 * window is NOT initially created, but will be created the
558 * first time the window is mapped.
559 *
560 *----------------------------------------------------------------------
561 */
562
563 Tk_Window
564 Tk_CreateMainWindow (
565 Tcl_Interp *interp, /* Interpreter to use for error reporting. */
566 char *screenName, /* Name of screen on which to create
567 * window. Empty or NULL string means
568 * use DISPLAY environment variable. */
569 char *baseName /* Base name for application; usually of the
570 * form "prog instance". */
571 )
572 {
573 Tk_Window tkwin;
574 int result, dummy;
575 Tcl_HashEntry *hPtr;
576 register TkMainInfo *mainPtr;
577 register TkWindow *winPtr;
578 register TkCmd *cmdPtr;
579
580 /*
581 * Create the basic TkWindow structure.
582 */
583
584 tkwin = CreateTopLevelWindow(interp, (Tk_Window) NULL, baseName,
585 screenName);
586 if (tkwin == NULL) {
587 return NULL;
588 }
589
590 /*
591 * Create the TkMainInfo structure for this application, and set
592 * up name-related information for the new window.
593 */
594
595 winPtr = (TkWindow *) tkwin;
596 mainPtr = (TkMainInfo *) ckalloc(sizeof(TkMainInfo));
597 mainPtr->winPtr = winPtr;
598 mainPtr->interp = interp;
599 Tcl_InitHashTable(&mainPtr->nameTable, TCL_STRING_KEYS);
600 mainPtr->bindingTable = Tk_CreateBindingTable(interp);
601 /* XXX: FOCUS */
602 /* mainPtr->focusPtr = NULL; */
603 mainPtr->optionRootPtr = NULL;
604 winPtr->mainPtr = mainPtr;
605 hPtr = Tcl_CreateHashEntry(&mainPtr->nameTable, ".", &dummy);
606 Tcl_SetHashValue(hPtr, winPtr);
607 winPtr->pathName = Tcl_GetHashKey(&mainPtr->nameTable, hPtr);
608
609 /*
610 * Register the interpreter for "send" purposes. If baseName isn't
611 * already unique, find a unique suffix to add to it to make it
612 * unique. Change the window's name to contain the suffix.
613 */
614
615 result = Tk_RegisterInterp(interp, baseName, tkwin);
616 if (result == TCL_OK) {
617 winPtr->nameUid = Tk_GetUid(baseName);
618 } else {
619 char newName[110];
620 int i;
621
622 for (i = 2; ; i++) {
623 sprintf(newName, "%.100s #%d", baseName, i);
624 Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
625 result = Tk_RegisterInterp(interp, newName, tkwin);
626 if (result == TCL_OK) {
627 break;
628 }
629 if (i >= 100) {
630 Tcl_SetResult(interp,
631 "couldn't generate unique name to register application",
632 TCL_STATIC);
633 Tk_DestroyWindow(tkwin);
634 }
635 }
636 winPtr->nameUid = Tk_GetUid(newName);
637 }
638
639 /*
640 * Bind in Tk's commands.
641 */
642
643 for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
644 Tcl_CreateCommand(interp, cmdPtr->name, cmdPtr->cmdProc,
645 (ClientData) tkwin, (void (*)(int *)) NULL);
646 }
647
648 /*
649 * Set variables for the intepreter.
650 */
651
652 Tcl_SetVar(interp, "tk_library", TK_Library, TCL_GLOBAL_ONLY);
653 Tcl_SetVar(interp, "tk_version", TK_VERSION, TCL_GLOBAL_ONLY);
654 Tcl_SetVar(interp, "tkVersion", TK_VERSION, TCL_GLOBAL_ONLY);
655
656 tk_NumMainWindows++;
657 return tkwin;
658 }
659 \f
660 /*
661 *--------------------------------------------------------------
662 *
663 * Tk_CreateWindow --
664 *
665 * Create a new internal or top-level window as a child of an
666 * existing window.
667 *
668 * Results:
669 * The return value is a token for the new window. This
670 * is not the same as X's token for the window. If an error
671 * occurred in creating the window (e.g. no such display or
672 * screen), then an error message is left in interp->result and
673 * NULL is returned.
674 *
675 * Side effects:
676 * A new window structure is allocated locally. An X
677 * window is not initially created, but will be created
678 * the first time the window is mapped.
679 *
680 *--------------------------------------------------------------
681 */
682
683 Tk_Window
684 Tk_CreateWindow (
685 Tcl_Interp *interp, /* Interpreter to use for error reporting.
686 * Interp->result is assumed to be
687 * initialized by the caller. */
688 Tk_Window parent, /* Token for parent of new window. */
689 char *name, /* Name for new window. Must be unique
690 * among parent's children. */
691 char *screenName /* If NULL, new window will be internal on
692 * same screen as its parent. If non-NULL,
693 * gives name of screen on which to create
694 * new window; window will be a top-level
695 * window. */
696 )
697 {
698 TkWindow *parentPtr = (TkWindow *) parent;
699 TkWindow *winPtr;
700
701 if (screenName == NULL) {
702 winPtr = NewWindow(parentPtr->dispPtr, parentPtr->screenNum);
703 if (NameWindow(interp, winPtr, parentPtr, name) != TCL_OK) {
704 Tk_DestroyWindow((Tk_Window) winPtr);
705 return NULL;
706 } else {
707 return (Tk_Window) winPtr;
708 }
709 } else {
710 /*
711 * This is a fix for dvx XOpenDisplay... display name conformalization
712 * bugs...
713 */
714 char dsp[256];
715 int len;
716
717 strcpy(dsp, screenName);
718 len = strlen(dsp);
719 if (len && (dsp[len -1] == '.'))
720 dsp[len -1] = '\0';
721
722 return CreateTopLevelWindow(interp, parent, name, dsp);
723 }
724 }
725 \f
726 /*
727 *----------------------------------------------------------------------
728 *
729 * Tk_CreateWindowFromPath --
730 *
731 * This procedure is similar to Tk_CreateInternalWindow except
732 * that it uses a path name to create the window, rather than
733 * a parent and a child name.
734 *
735 * Results:
736 * The return value is a token for the new window. This
737 * is not the same as X's token for the window. If an error
738 * occurred in creating the window (e.g. no such display or
739 * screen), then an error message is left in interp->result and
740 * NULL is returned.
741 *
742 * Side effects:
743 * A new window structure is allocated locally. An X
744 * window is not initially created, but will be created
745 * the first time the window is mapped.
746 *
747 *----------------------------------------------------------------------
748 */
749
750 Tk_Window
751 Tk_CreateWindowFromPath (
752 Tcl_Interp *interp, /* Interpreter to use for error reporting.
753 * Interp->result is assumed to be
754 * initialized by the caller. */
755 Tk_Window tkwin, /* Token for any window in application
756 * that is to contain new window. */
757 char *pathName, /* Path name for new window within the
758 * application of tkwin. The parent of
759 * this window must already exist, but
760 * the window itself must not exist. */
761 char *screenName /* If NULL, new window will be on same
762 * screen as its parent. If non-NULL,
763 * gives name of screen on which to create
764 * new window; window will be a top-level
765 * window. */
766 )
767 {
768 #define FIXED_SPACE 5
769 char fixedSpace[FIXED_SPACE+1];
770 char *p;
771 Tk_Window parent;
772 int numChars;
773
774 /*
775 * Strip the parent's name out of pathName (it's everything up
776 * to the last dot). There are two tricky parts: (a) must
777 * copy the parent's name somewhere else to avoid modifying
778 * the pathName string (for large names, space for the copy
779 * will have to be malloc'ed); (b) must special-case the
780 * situation where the parent is ".".
781 */
782
783 p = strrchr(pathName, '.');
784 if (p == NULL) {
785 Tcl_AppendResult(interp, "bad window path name \"", pathName,
786 "\"", (char *) NULL);
787 return NULL;
788 }
789 numChars = p-pathName;
790 if (numChars > FIXED_SPACE) {
791 p = (char *) ckalloc((unsigned) (numChars+1));
792 } else {
793 p = fixedSpace;
794 }
795 if (numChars == 0) {
796 *p = '.';
797 p[1] = '\0';
798 } else {
799 strncpy(p, pathName, numChars);
800 p[numChars] = '\0';
801 }
802
803 /*
804 * Find the parent window.
805 */
806
807 parent = Tk_NameToWindow(interp, p, tkwin);
808 if (p != fixedSpace) {
809 ckfree(p);
810 }
811 if (parent == NULL) {
812 return NULL;
813 }
814
815 /*
816 * Create the window.
817 */
818
819 if (screenName == NULL) {
820 TkWindow *parentPtr = (TkWindow *) parent;
821 TkWindow *winPtr;
822
823 winPtr = NewWindow(parentPtr->dispPtr, parentPtr->screenNum);
824 if (NameWindow(interp, winPtr, parentPtr, pathName+numChars+1)
825 != TCL_OK) {
826 Tk_DestroyWindow((Tk_Window) winPtr);
827 return NULL;
828 } else {
829 return (Tk_Window) winPtr;
830 }
831 } else {
832 return CreateTopLevelWindow(interp, parent, pathName+numChars+1,
833 screenName);
834 }
835 }
836 \f
837 /*
838 *--------------------------------------------------------------
839 *
840 * Tk_DestroyWindow --
841 *
842 * Destroy an existing window. After this call, the caller
843 * should never again use the token.
844 *
845 * Results:
846 * None.
847 *
848 * Side effects:
849 * The window is deleted, along with all of its children.
850 * Relevant callback procedures are invoked.
851 *
852 *--------------------------------------------------------------
853 */
854
855 void
856 Tk_DestroyWindow (
857 Tk_Window tkwin /* Window to destroy. */
858 )
859 {
860 register TkWindow *winPtr = (TkWindow *) tkwin;
861 XEvent event;
862
863 /*
864 * Recursively destroy children. The TK_RECURSIVE_DESTROY
865 * flags means that the child's window needn't be explicitly
866 * destroyed (the destroy of the parent already did it), nor
867 * does it need to be removed from its parent's child list,
868 * since the parent is being destroyed too.
869 */
870
871 while (winPtr->childList != NULL) {
872 winPtr->childList->flags |= TK_RECURSIVE_DESTROY;
873 Tk_DestroyWindow((Tk_Window) winPtr->childList);
874 }
875
876 /*
877 * Generate a DestroyNotify event. In order for the DestroyNotify
878 * event to be processed correctly, need to make sure the window
879 * exists. This is a bit of a kludge, and may be unnecessarily
880 * expensive, but without it no event handlers will get called for
881 * windows that don't exist yet.
882 */
883
884 if (winPtr->window == None) {
885 Tk_MakeWindowExist(tkwin);
886 }
887 winPtr->flags |= TK_ALREADY_DEAD;
888 event.type = DestroyNotify;
889 event.xdestroywindow.serial =
890 LastKnownRequestProcessed(winPtr->display);
891 event.xdestroywindow.send_event = False;
892 event.xdestroywindow.display = winPtr->display;
893 event.xdestroywindow.event = winPtr->window;
894 event.xdestroywindow.window = winPtr->window;
895 Tk_HandleEvent(&event);
896
897 /*
898 * Cleanup the data structures associated with this window.
899 * No need to destroy windows during recursive destroys, since
900 * that will happen automatically when the parent window is
901 * destroyed (not true for top-level windows: must destroy
902 * them explicitly).
903 */
904
905 if (winPtr->window != None) {
906 if (!(winPtr->flags & TK_RECURSIVE_DESTROY)
907 || (winPtr->flags & TK_TOP_LEVEL)) {
908 XDestroyWindow(winPtr->display, winPtr->window);
909 }
910 XDeleteContext(winPtr->display, winPtr->window, tkWindowContext);
911 winPtr->window = None;
912 }
913 if (winPtr->parentPtr != NULL) {
914 if (winPtr->parentPtr->childList == winPtr) {
915 winPtr->parentPtr->childList = winPtr->nextPtr;
916 } else {
917 register TkWindow *winPtr2;
918
919 for (winPtr2 = winPtr->parentPtr->childList; ;
920 winPtr2 = winPtr2->nextPtr) {
921 if (winPtr2 == NULL) {
922 panic("Tk_DestroyWindow couldn't find child in parent (deleted twice?)");
923 break;
924 }
925 if (winPtr2->nextPtr == winPtr) {
926 winPtr2->nextPtr = winPtr->nextPtr;
927 break;
928 }
929 }
930 }
931 }
932 TkEventDeadWindow(winPtr);
933 TkOptionDeadWindow(winPtr);
934 TkSelDeadWindow(winPtr);
935 if (winPtr->flags & TK_TOP_LEVEL) {
936 TkWmDeadWindow(winPtr);
937 }
938 TkGrabDeadWindow(winPtr);
939 if (winPtr->mainPtr != NULL) {
940 Tk_DeleteAllBindings(winPtr->mainPtr->bindingTable,
941 (ClientData) winPtr->pathName);
942 if (winPtr->pathName != NULL) {
943 Tcl_DeleteHashEntry(Tcl_FindHashEntry(&winPtr->mainPtr->nameTable,
944 winPtr->pathName));
945 }
946 if (winPtr->mainPtr->winPtr == winPtr) {
947 register TkCmd *cmdPtr;
948
949 /*
950 * Deleting a main window. Delete the TkMainInfo structure too
951 * and replace all of Tk's commands with dummy commands that
952 * return errors. Also delete the "send" command to unregister
953 * the interpreter.
954 */
955
956 for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
957 Tcl_CreateCommand(winPtr->mainPtr->interp, cmdPtr->name,
958 TkDeadAppCmd, (ClientData) NULL, (void (*)(int *)) NULL);
959 }
960 Tcl_CreateCommand(winPtr->mainPtr->interp, "send",
961 TkDeadAppCmd, (ClientData) NULL, (void (*)(int *)) NULL);
962 Tcl_DeleteHashTable(&winPtr->mainPtr->nameTable);
963 Tk_DeleteBindingTable(winPtr->mainPtr->bindingTable);
964 ckfree((char *) winPtr->mainPtr);
965 tk_NumMainWindows--;
966 }
967 }
968 ckfree((char *) winPtr);
969 }
970 \f
971 /*
972 *--------------------------------------------------------------
973 *
974 * Tk_MapWindow --
975 *
976 * Map a window within its parent. This may require the
977 * window and/or its parents to actually be created.
978 *
979 * Results:
980 * None.
981 *
982 * Side effects:
983 * The given window will be mapped. Windows may also
984 * be created.
985 *
986 *--------------------------------------------------------------
987 */
988
989 void
990 Tk_MapWindow (
991 Tk_Window tkwin /* Token for window to map. */
992 )
993 {
994 register TkWindow *winPtr = (TkWindow *) tkwin;
995
996 if (winPtr->flags & TK_MAPPED) {
997 return;
998 }
999 if (winPtr->window == None) {
1000 Tk_MakeWindowExist(tkwin);
1001 }
1002 if (winPtr->flags & TK_TOP_LEVEL) {
1003 if (!TkWmMapWindow(winPtr)) {
1004 return;
1005 }
1006 } else {
1007 /*
1008 * Don't set the mapped flag for top-level windows: TkWmMapWindow
1009 * does it if appropriate (e.g. if the window is going to be non-
1010 * iconic).
1011 */
1012
1013 winPtr->flags |= TK_MAPPED;
1014 }
1015 XMapWindow(winPtr->display, winPtr->window);
1016 if (!(winPtr->flags & TK_TOP_LEVEL)) {
1017 XEvent event;
1018
1019 event.type = MapNotify;
1020 event.xmap.serial = LastKnownRequestProcessed(winPtr->display);
1021 event.xmap.send_event = False;
1022 event.xmap.display = winPtr->display;
1023 event.xmap.event = winPtr->window;
1024 event.xmap.window = winPtr->window;
1025 event.xmap.override_redirect = winPtr->atts.override_redirect;
1026 Tk_HandleEvent(&event);
1027 }
1028 }
1029 \f
1030 /*
1031 *--------------------------------------------------------------
1032 *
1033 * Tk_MakeWindowExist --
1034 *
1035 * Ensure that a particular window actually exists. This
1036 * procedure shouldn't normally need to be invoked from
1037 * outside the Tk package, but may be needed if someone
1038 * wants to manipulate a window before mapping it.
1039 *
1040 * Results:
1041 * None.
1042 *
1043 * Side effects:
1044 * When the procedure returns, the X window associated with
1045 * tkwin is guaranteed to exist. This may require the
1046 * window's ancestors to be created also.
1047 *
1048 *--------------------------------------------------------------
1049 */
1050
1051 void
1052 Tk_MakeWindowExist (
1053 Tk_Window tkwin /* Token for window. */
1054 )
1055 {
1056 register TkWindow *winPtr = (TkWindow *) tkwin;
1057 Window parent;
1058
1059 if (winPtr->window != None) {
1060 return;
1061 }
1062
1063 if (winPtr->flags & TK_TOP_LEVEL) {
1064 /*
1065 * workaround by dhopkins for OLPC Micropolis gtk.Socket integration.
1066 */
1067
1068 if (tk_RootWindow) {
1069 parent =
1070 tk_RootWindow;
1071 } else {
1072 parent =
1073 XRootWindow(winPtr->display, winPtr->screenNum);
1074 }
1075
1076 } else {
1077 if (winPtr->parentPtr->window == None) {
1078 Tk_MakeWindowExist((Tk_Window) winPtr->parentPtr);
1079 }
1080 parent = winPtr->parentPtr->window;
1081 }
1082
1083 /* workaround to support non-default colormaps */
1084 #if 0
1085 winPtr->window = XCreateWindow(winPtr->display, parent,
1086 winPtr->changes.x, winPtr->changes.y,
1087 winPtr->changes.width, winPtr->changes.height,
1088 winPtr->changes.border_width, CopyFromParent,
1089 InputOutput, CopyFromParent, winPtr->dirtyAtts,
1090 &winPtr->atts);
1091 #else
1092 { Screen *scr = ScreenOfDisplay(winPtr->display, winPtr->screenNum);
1093
1094 winPtr->dirtyAtts |= CWColormap | CWBorderPixmap;
1095 winPtr->atts.colormap = Tk_DefaultColormap(scr);
1096 winPtr->atts.border_pixmap = Tk_DefaultPixmap(scr);
1097
1098 winPtr->window = XCreateWindow(winPtr->display, parent,
1099 winPtr->changes.x, winPtr->changes.y,
1100 winPtr->changes.width, winPtr->changes.height,
1101 winPtr->changes.border_width,
1102 Tk_DefaultDepth(scr),
1103 InputOutput,
1104 Tk_DefaultVisual(scr),
1105 winPtr->dirtyAtts, &winPtr->atts);
1106 }
1107 #endif
1108
1109 XSaveContext(winPtr->display, winPtr->window, tkWindowContext,
1110 (void *) winPtr);
1111 winPtr->dirtyAtts = 0;
1112 winPtr->dirtyChanges &= ~(CWX|CWY|CWWidth|CWHeight|CWBorderWidth);
1113 if (winPtr->dirtyChanges != 0) {
1114 XConfigureWindow(winPtr->display, winPtr->window,
1115 winPtr->dirtyChanges, &winPtr->changes);
1116 winPtr->dirtyChanges = 0;
1117 }
1118
1119 /*
1120 * Issue a ConfigureNotify event if there were deferred configuration
1121 * changes.
1122 */
1123
1124 if (winPtr->flags & TK_NEED_CONFIG_NOTIFY) {
1125 winPtr->flags &= ~TK_NEED_CONFIG_NOTIFY;
1126 DoConfigureNotify(winPtr);
1127 }
1128 }
1129 \f
1130 /*
1131 *--------------------------------------------------------------
1132 *
1133 * Tk_UnmapWindow, etc. --
1134 *
1135 * There are several procedures under here, each of which
1136 * mirrors an existing X procedure. In addition to performing
1137 * the functions of the corresponding procedure, each
1138 * procedure also updates the local window structure and
1139 * synthesizes an X event (if the window's structure is being
1140 * managed internally).
1141 *
1142 * Results:
1143 * See the manual entries.
1144 *
1145 * Side effects:
1146 * See the manual entries.
1147 *
1148 *--------------------------------------------------------------
1149 */
1150
1151 void
1152 Tk_UnmapWindow (
1153 Tk_Window tkwin /* Token for window to unmap. */
1154 )
1155 {
1156 register TkWindow *winPtr = (TkWindow *) tkwin;
1157
1158 if (!(winPtr->flags & TK_MAPPED)) {
1159 return;
1160 }
1161 winPtr->flags &= ~TK_MAPPED;
1162 XUnmapWindow(winPtr->display, winPtr->window);
1163 if (!(winPtr->flags & TK_TOP_LEVEL)) {
1164 XEvent event;
1165
1166 event.type = UnmapNotify;
1167 event.xunmap.serial = LastKnownRequestProcessed(winPtr->display);
1168 event.xunmap.send_event = False;
1169 event.xunmap.display = winPtr->display;
1170 event.xunmap.event = winPtr->window;
1171 event.xunmap.window = winPtr->window;
1172 event.xunmap.from_configure = False;
1173 Tk_HandleEvent(&event);
1174 }
1175 }
1176
1177 void
1178 Tk_ConfigureWindow (
1179 Tk_Window tkwin, /* Window to re-configure. */
1180 unsigned int valueMask, /* Mask indicating which parts of
1181 * *valuePtr are to be used. */
1182 XWindowChanges *valuePtr /* New values. */
1183 )
1184 {
1185 register TkWindow *winPtr = (TkWindow *) tkwin;
1186
1187 if ((winPtr->window == None) || !(winPtr->flags & TK_TOP_LEVEL)) {
1188 if (valueMask & CWX) {
1189 winPtr->changes.x = valuePtr->x;
1190 }
1191 if (valueMask & CWY) {
1192 winPtr->changes.y = valuePtr->y;
1193 }
1194 if (valueMask & CWWidth) {
1195 winPtr->changes.width = valuePtr->width;
1196 }
1197 if (valueMask & CWHeight) {
1198 winPtr->changes.height = valuePtr->height;
1199 }
1200 if (valueMask & CWBorderWidth) {
1201 winPtr->changes.border_width = valuePtr->border_width;
1202 }
1203 if (valueMask & CWSibling) {
1204 winPtr->changes.sibling = valuePtr->sibling;
1205 }
1206 if (valueMask & CWStackMode) {
1207 winPtr->changes.stack_mode = valuePtr->stack_mode;
1208 }
1209 }
1210
1211 if (winPtr->window != None) {
1212 XConfigureWindow(winPtr->display, winPtr->window,
1213 valueMask, valuePtr);
1214 if (!(winPtr->flags & TK_TOP_LEVEL)) {
1215 DoConfigureNotify(winPtr);
1216 }
1217 } else {
1218 winPtr->dirtyChanges |= valueMask;
1219 winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1220 }
1221 }
1222
1223 void
1224 Tk_MoveWindow (
1225 Tk_Window tkwin, /* Window to move. */
1226 int x,
1227 int y /* New location for window (within
1228 * parent). */
1229 )
1230 {
1231 register TkWindow *winPtr = (TkWindow *) tkwin;
1232
1233 if (winPtr->window != None) {
1234 XMoveWindow(winPtr->display, winPtr->window, x, y);
1235 if (!(winPtr->flags & TK_TOP_LEVEL)) {
1236 winPtr->changes.x = x;
1237 winPtr->changes.y = y;
1238 DoConfigureNotify(winPtr);
1239 }
1240 } else {
1241 winPtr->changes.x = x;
1242 winPtr->changes.y = y;
1243 winPtr->dirtyChanges |= CWX|CWY;
1244 winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1245 }
1246 }
1247
1248 void
1249 Tk_ResizeWindow (
1250 Tk_Window tkwin, /* Window to resize. */
1251 unsigned int width,
1252 unsigned int height /* New dimensions for window. */
1253 )
1254 {
1255 register TkWindow *winPtr = (TkWindow *) tkwin;
1256
1257 if (winPtr->window != None) {
1258 XResizeWindow(winPtr->display, winPtr->window, width, height);
1259 if (!(winPtr->flags & TK_TOP_LEVEL)) {
1260 winPtr->changes.width = width;
1261 winPtr->changes.height = height;
1262 DoConfigureNotify(winPtr);
1263 }
1264 } else {
1265 winPtr->changes.width = width;
1266 winPtr->changes.height = height;
1267 winPtr->dirtyChanges |= CWWidth|CWHeight;
1268 winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1269 }
1270 }
1271
1272 void
1273 Tk_MoveResizeWindow (
1274 Tk_Window tkwin, /* Window to move and resize. */
1275 int x,
1276 int y, /* New location for window (within
1277 * parent). */
1278 unsigned int width,
1279 unsigned int height /* New dimensions for window. */
1280 )
1281 {
1282 register TkWindow *winPtr = (TkWindow *) tkwin;
1283
1284 if (winPtr->window != None) {
1285 XMoveResizeWindow(winPtr->display, winPtr->window,
1286 x, y, width, height);
1287 if (!(winPtr->flags & TK_TOP_LEVEL)) {
1288 winPtr->changes.x = x;
1289 winPtr->changes.y = y;
1290 winPtr->changes.width = width;
1291 winPtr->changes.height = height;
1292 DoConfigureNotify(winPtr);
1293 }
1294 } else {
1295 winPtr->changes.x = x;
1296 winPtr->changes.y = y;
1297 winPtr->changes.width = width;
1298 winPtr->changes.height = height;
1299 winPtr->dirtyChanges |= CWX|CWY|CWWidth|CWHeight;
1300 winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1301 }
1302 }
1303
1304 void
1305 Tk_SetWindowBorderWidth (
1306 Tk_Window tkwin, /* Window to modify. */
1307 int width /* New border width for window. */
1308 )
1309 {
1310 register TkWindow *winPtr = (TkWindow *) tkwin;
1311
1312 winPtr->changes.border_width = width;
1313 if (winPtr->window != None) {
1314 XSetWindowBorderWidth(winPtr->display, winPtr->window, width);
1315 if (!(winPtr->flags & TK_TOP_LEVEL)) {
1316 DoConfigureNotify(winPtr);
1317 }
1318 } else {
1319 winPtr->dirtyChanges |= CWBorderWidth;
1320 winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1321 }
1322 }
1323
1324 void
1325 Tk_ChangeWindowAttributes (
1326 Tk_Window tkwin, /* Window to manipulate. */
1327 unsigned long valueMask, /* OR'ed combination of bits,
1328 * indicating which fields of
1329 * *attsPtr are to be used. */
1330 register XSetWindowAttributes *attsPtr
1331 )
1332 /* New values for some attributes. */
1333 {
1334 register TkWindow *winPtr = (TkWindow *) tkwin;
1335
1336 if (valueMask & CWBackPixmap) {
1337 winPtr->atts.background_pixmap = attsPtr->background_pixmap;
1338 }
1339 if (valueMask & CWBackPixel) {
1340 winPtr->atts.background_pixel = attsPtr->background_pixel;
1341 }
1342 if (valueMask & CWBorderPixmap) {
1343 winPtr->atts.border_pixmap = attsPtr->border_pixmap;
1344 }
1345 if (valueMask & CWBorderPixel) {
1346 winPtr->atts.border_pixel = attsPtr->border_pixel;
1347 }
1348 if (valueMask & CWBitGravity) {
1349 winPtr->atts.bit_gravity = attsPtr->bit_gravity;
1350 }
1351 if (valueMask & CWWinGravity) {
1352 winPtr->atts.win_gravity = attsPtr->win_gravity;
1353 }
1354 if (valueMask & CWBackingStore) {
1355 winPtr->atts.backing_store = attsPtr->backing_store;
1356 }
1357 if (valueMask & CWBackingPlanes) {
1358 winPtr->atts.backing_planes = attsPtr->backing_planes;
1359 }
1360 if (valueMask & CWBackingPixel) {
1361 winPtr->atts.backing_pixel = attsPtr->backing_pixel;
1362 }
1363 if (valueMask & CWOverrideRedirect) {
1364 winPtr->atts.override_redirect = attsPtr->override_redirect;
1365 }
1366 if (valueMask & CWSaveUnder) {
1367 winPtr->atts.save_under = attsPtr->save_under;
1368 }
1369 if (valueMask & CWEventMask) {
1370 winPtr->atts.event_mask = attsPtr->event_mask;
1371 }
1372 if (valueMask & CWDontPropagate) {
1373 winPtr->atts.do_not_propagate_mask
1374 = attsPtr->do_not_propagate_mask;
1375 }
1376 if (valueMask & CWColormap) {
1377 winPtr->atts.colormap = attsPtr->colormap;
1378 }
1379 if (valueMask & CWCursor) {
1380 winPtr->atts.cursor = attsPtr->cursor;
1381 }
1382
1383 if (winPtr->window != None) {
1384 XChangeWindowAttributes(winPtr->display, winPtr->window,
1385 valueMask, attsPtr);
1386 } else {
1387 winPtr->dirtyAtts |= valueMask;
1388 }
1389 }
1390
1391 void
1392 Tk_SetWindowBackground (
1393 Tk_Window tkwin, /* Window to manipulate. */
1394 unsigned long pixel /* Pixel value to use for
1395 * window's background. */
1396 )
1397 {
1398 register TkWindow *winPtr = (TkWindow *) tkwin;
1399
1400 winPtr->atts.background_pixel = pixel;
1401
1402 if (winPtr->window != None) {
1403 XSetWindowBackground(winPtr->display, winPtr->window, pixel);
1404 } else {
1405 winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBackPixmap)
1406 | CWBackPixel;
1407 }
1408 }
1409
1410 void
1411 Tk_SetWindowBackgroundPixmap (
1412 Tk_Window tkwin, /* Window to manipulate. */
1413 Pixmap pixmap /* Pixmap to use for window's
1414 * background. */
1415 )
1416 {
1417 register TkWindow *winPtr = (TkWindow *) tkwin;
1418
1419 winPtr->atts.background_pixmap = pixmap;
1420
1421 if (winPtr->window != None) {
1422 XSetWindowBackgroundPixmap(winPtr->display,
1423 winPtr->window, pixmap);
1424 } else {
1425 winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBackPixel)
1426 | CWBackPixmap;
1427 }
1428 }
1429
1430 void
1431 Tk_SetWindowBorder (
1432 Tk_Window tkwin, /* Window to manipulate. */
1433 unsigned long pixel /* Pixel value to use for
1434 * window's border. */
1435 )
1436 {
1437 register TkWindow *winPtr = (TkWindow *) tkwin;
1438
1439 winPtr->atts.border_pixel = pixel;
1440
1441 if (winPtr->window != None) {
1442 XSetWindowBorder(winPtr->display, winPtr->window, pixel);
1443 } else {
1444 winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBorderPixmap)
1445 | CWBorderPixel;
1446 }
1447 }
1448
1449 void
1450 Tk_SetWindowBorderPixmap (
1451 Tk_Window tkwin, /* Window to manipulate. */
1452 Pixmap pixmap /* Pixmap to use for window's
1453 * border. */
1454 )
1455 {
1456 register TkWindow *winPtr = (TkWindow *) tkwin;
1457
1458 winPtr->atts.border_pixmap = pixmap;
1459
1460 if (winPtr->window != None) {
1461 XSetWindowBorderPixmap(winPtr->display,
1462 winPtr->window, pixmap);
1463 } else {
1464 winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBorderPixel)
1465 | CWBorderPixmap;
1466 }
1467 }
1468
1469 void
1470 Tk_DefineCursor (
1471 Tk_Window tkwin, /* Window to manipulate. */
1472 Cursor cursor /* Cursor to use for window (may be None). */
1473 )
1474 {
1475 register TkWindow *winPtr = (TkWindow *) tkwin;
1476
1477 winPtr->atts.cursor = cursor;
1478
1479 if (winPtr->window != None) {
1480 XDefineCursor(winPtr->display, winPtr->window, cursor);
1481 } else {
1482 winPtr->dirtyAtts = winPtr->dirtyAtts | CWCursor;
1483 }
1484 }
1485
1486 void
1487 Tk_UndefineCursor (
1488 Tk_Window tkwin /* Window to manipulate. */
1489 )
1490 {
1491 Tk_DefineCursor(tkwin, None);
1492 }
1493 \f
1494 /*
1495 *----------------------------------------------------------------------
1496 *
1497 * DoConfigureNotify --
1498 *
1499 * Generate a ConfigureNotify event describing the current
1500 * configuration of a window.
1501 *
1502 * Results:
1503 * None.
1504 *
1505 * Side effects:
1506 * An event is generated and processed by Tk_HandleEvent.
1507 *
1508 *----------------------------------------------------------------------
1509 */
1510
1511 static void
1512 DoConfigureNotify (
1513 register TkWindow *winPtr /* Window whose configuration
1514 * was just changed. */
1515 )
1516 {
1517 XEvent event;
1518
1519 event.type = ConfigureNotify;
1520 event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display);
1521 event.xconfigure.send_event = False;
1522 event.xconfigure.display = winPtr->display;
1523 event.xconfigure.event = winPtr->window;
1524 event.xconfigure.window = winPtr->window;
1525 event.xconfigure.x = winPtr->changes.x;
1526 event.xconfigure.y = winPtr->changes.y;
1527 event.xconfigure.width = winPtr->changes.width;
1528 event.xconfigure.height = winPtr->changes.height;
1529 event.xconfigure.border_width = winPtr->changes.border_width;
1530 if (winPtr->changes.stack_mode == Above) {
1531 event.xconfigure.above = winPtr->changes.sibling;
1532 } else {
1533 event.xconfigure.above = None;
1534 }
1535 event.xconfigure.override_redirect = winPtr->atts.override_redirect;
1536 Tk_HandleEvent(&event);
1537 }
1538 \f
1539 /*
1540 *----------------------------------------------------------------------
1541 *
1542 * Tk_SetClass --
1543 *
1544 * This procedure is used to give a window a class.
1545 *
1546 * Results:
1547 * None.
1548 *
1549 * Side effects:
1550 * A new class is stored for tkwin, replacing any existing
1551 * class for it.
1552 *
1553 *----------------------------------------------------------------------
1554 */
1555
1556 void
1557 Tk_SetClass (
1558 Tk_Window tkwin, /* Token for window to assign class. */
1559 char *className /* New class for tkwin. */
1560 )
1561 {
1562 register TkWindow *winPtr = (TkWindow *) tkwin;
1563
1564 winPtr->classUid = Tk_GetUid(className);
1565 if (winPtr->flags & TK_TOP_LEVEL) {
1566 TkWmSetClass(winPtr);
1567 }
1568 }
1569 \f
1570 /*
1571 *----------------------------------------------------------------------
1572 *
1573 * Tk_NameToWindow --
1574 *
1575 * Given a string name for a window, this procedure
1576 * returns the token for the window, if there exists a
1577 * window corresponding to the given name.
1578 *
1579 * Results:
1580 * The return result is either a token for the window corresponding
1581 * to "name", or else NULL to indicate that there is no such
1582 * window. In this case, an error message is left in interp->result.
1583 *
1584 * Side effects:
1585 * None.
1586 *
1587 *----------------------------------------------------------------------
1588 */
1589
1590 Tk_Window
1591 Tk_NameToWindow (
1592 Tcl_Interp *interp, /* Where to report errors. */
1593 char *pathName, /* Path name of window. */
1594 Tk_Window tkwin /* Token for window: name is assumed to
1595 * belong to the same main window as tkwin. */
1596 )
1597 {
1598 Tcl_HashEntry *hPtr;
1599
1600 hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->nameTable,
1601 pathName);
1602 if (hPtr == NULL) {
1603 Tcl_AppendResult(interp, "bad window path name \"",
1604 pathName, "\"", (char *) NULL);
1605 return NULL;
1606 }
1607 return (Tk_Window) Tcl_GetHashValue(hPtr);
1608 }
1609 \f
1610 /*
1611 *----------------------------------------------------------------------
1612 *
1613 * Tk_DisplayName --
1614 *
1615 * Return the textual name of a window's display.
1616 *
1617 * Results:
1618 * The return value is the string name of the display associated
1619 * with tkwin.
1620 *
1621 * Side effects:
1622 * None.
1623 *
1624 *----------------------------------------------------------------------
1625 */
1626
1627 char *
1628 Tk_DisplayName (
1629 Tk_Window tkwin /* Window whose display name is desired. */
1630 )
1631 {
1632 return ((TkWindow *) tkwin)->dispPtr->name;
1633 }
Impressum, Datenschutz