]> cvs.zerfleddert.de Git - micropolis/blob - src/tk/tkwindow.c
Fixes for compilation with gcc 15
[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 {"wm", Tk_WmCmd},
138 {"accept", Tcp_AcceptCmd},
139 {"shutdown", Tcp_ShutdownCmd},
140 {"connect", Tcp_ConnectCmd},
141 {"filehandler", Tcp_FileHandlerCmd},
142
143 /*
144 * Widget-creation commands.
145 */
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}
162 };
163
164 /*
165 * Forward declarations to procedures defined later in this file:
166 */
167
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,
175 char *name));
176 static TkWindow * NewWindow _ANSI_ARGS_((TkDisplay *dispPtr,
177 int screenNum));
178 \f
179 /*
180 *----------------------------------------------------------------------
181 *
182 * CreateTopLevelWindow --
183 *
184 * Make a new window that will be at top-level (its parent will
185 * be the root window of a screen).
186 *
187 * Results:
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
191 * interp->result.
192 *
193 * Side effects:
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.
197 *
198 *----------------------------------------------------------------------
199 */
200
201 static Tk_Window
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
206 * be NULL. */
207 char *name, /* Name for new window; if parent is
208 * non-NULL, must be unique among parent's
209 * children. */
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
214 * parent. */
215 )
216 {
217 register TkWindow *winPtr;
218 register TkDisplay *dispPtr;
219 int screenId;
220
221 if (!initialized) {
222 initialized = 1;
223 tkWindowContext = XUniqueContext();
224 tkActiveUid = Tk_GetUid("active");
225 tkDisabledUid = Tk_GetUid("disabled");
226 tkNormalUid = Tk_GetUid("normal");
227 }
228
229 if ((parent != NULL) && (screenName != NULL) && (screenName[0] == '\0')) {
230 dispPtr = ((TkWindow *) parent)->dispPtr;
231 screenId = Tk_ScreenNumber(parent);
232 } else {
233 dispPtr = GetScreen(interp, screenName, &screenId);
234 if (dispPtr == NULL) {
235 return (Tk_Window) NULL;
236 }
237 }
238
239 winPtr = NewWindow(dispPtr, screenId);
240
241 /*
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.
246 */
247
248 winPtr->atts.event_mask |= StructureNotifyMask;
249
250 /*
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
253 * has been set.)
254 */
255
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;
261 }
262 }
263 TkWmNewWindow(winPtr);
264 return (Tk_Window) winPtr;
265 }
266 \f
267 /*
268 *----------------------------------------------------------------------
269 *
270 * GetScreen --
271 *
272 * Given a string name for a display-plus-screen, find the
273 * TkDisplay structure for the display and return the screen
274 * number too.
275 *
276 * Results:
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
281 * screenName.
282 *
283 * Side effects:
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.
287 *
288 *----------------------------------------------------------------------
289 */
290
291 static TkDisplay *
292 GetScreen (
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. */
297 )
298 {
299 register TkDisplay *dispPtr;
300 char *p;
301 int length, screenId;
302
303 /*
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
307 * optional.
308 */
309
310 if ((screenName == NULL) || (screenName[0] == '\0')) {
311 screenName = getenv("DISPLAY");
312 if (screenName == NULL) {
313 interp->result =
314 "no display name and no $DISPLAY environment variable";
315 return (TkDisplay *) NULL;
316 }
317 }
318 length = strlen(screenName);
319 screenId = 0;
320 p = screenName+length-1;
321 while (isdigit(*p) && (p != screenName)) {
322 p--;
323 }
324 if ((*p == '.') && (p[1] != '\0')) {
325 length = p - screenName;
326 screenId = strtoul(p+1, (char **) NULL, 10);
327 }
328
329 /*
330 * See if we already have a connection to this display. If not,
331 * then open a new connection.
332 */
333
334 for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr) {
335 if (dispPtr == NULL) {
336 Display *display = NULL;
337
338 display = XOpenDisplay(screenName);
339
340 if (display == NULL) {
341 Tcl_AppendResult(interp, "couldn't connect to display \"",
342 screenName, "\"", (char *) NULL);
343 return (TkDisplay *) NULL;
344 }
345 if (getenv("XSYNCHRONIZE") != NULL) {
346 XSynchronize(display, 1);
347 }
348 tk_Displays++;
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);
380 break;
381 }
382 if ((strncmp(dispPtr->name, screenName, length) == 0)
383 && (dispPtr->name[length] == '\0')) {
384 break;
385 }
386 }
387 if (screenId >= ScreenCount(dispPtr->display)) {
388 sprintf(interp->result, "bad screen number \"%d\"", screenId);
389 return (TkDisplay *) NULL;
390 }
391 *screenPtr = screenId;
392 return dispPtr;
393 }
394 \f
395 /*
396 *--------------------------------------------------------------
397 *
398 * NewWindow --
399 *
400 * This procedure creates and initializes a TkWindow structure.
401 *
402 * Results:
403 * The return value is a pointer to the new window.
404 *
405 * Side effects:
406 * A new window structure is allocated and all its fields are
407 * initialized.
408 *
409 *--------------------------------------------------------------
410 */
411
412 static TkWindow *
413 NewWindow (
414 TkDisplay *dispPtr, /* Display associated with new window. */
415 int screenNum /* Index of screen for new window. */
416 )
417 {
418 register TkWindow *winPtr;
419
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;
436 winPtr->flags = 0;
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;
449 return winPtr;
450 }
451 \f
452 /*
453 *----------------------------------------------------------------------
454 *
455 * NameWindow --
456 *
457 * This procedure is invoked to give a window a name and insert
458 * the window into the hierarchy associated with a particular
459 * application.
460 *
461 * Results:
462 * A standard Tcl return value.
463 *
464 * Side effects:
465 * See above.
466 *
467 *----------------------------------------------------------------------
468 */
469
470 static int
471 NameWindow (
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. */
478 )
479 {
480 #define FIXED_SIZE 200
481 char staticSpace[FIXED_SIZE];
482 char *pathName;
483 int new;
484 Tcl_HashEntry *hPtr;
485 int length1, length2;
486
487 /*
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).
492 */
493 winPtr->parentPtr = parentPtr;
494 winPtr->nextPtr = parentPtr->childList;
495 parentPtr->childList = winPtr;
496 winPtr->mainPtr = parentPtr->mainPtr;
497 winPtr->nameUid = Tk_GetUid(name);
498
499 /*
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
503 * stack.
504 */
505
506 length1 = strlen(parentPtr->pathName);
507 length2 = strlen(name);
508 if ((length1+length2+2) <= FIXED_SIZE) {
509 pathName = staticSpace;
510 } else {
511 pathName = (char *) ckalloc((unsigned) (length1+length2+2));
512 }
513 if (length1 == 1) {
514 pathName[0] = '.';
515 strcpy(pathName+1, name);
516 } else {
517 strcpy(pathName, parentPtr->pathName);
518 pathName[length1] = '.';
519 strcpy(pathName+length1+1, name);
520 }
521 hPtr = Tcl_CreateHashEntry(&parentPtr->mainPtr->nameTable, pathName, &new);
522 if (pathName != staticSpace) {
523 ckfree(pathName);
524 }
525 if (!new) {
526 Tcl_AppendResult(interp, "window name \"", name,
527 "\" already exists in parent", (char *) NULL);
528 return TCL_ERROR;
529 }
530 Tcl_SetHashValue(hPtr, winPtr);
531 winPtr->pathName = Tcl_GetHashKey(&parentPtr->mainPtr->nameTable, hPtr);
532 return TCL_OK;
533 }
534 \f
535 /*
536 *----------------------------------------------------------------------
537 *
538 * Tk_CreateMainWindow --
539 *
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
542 * application.
543 *
544 * Results:
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
548 * interp->result.
549 *
550 * Side effects:
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.
558 *
559 *----------------------------------------------------------------------
560 */
561
562 Tk_Window
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". */
570 )
571 {
572 Tk_Window tkwin;
573 int result, dummy;
574 Tcl_HashEntry *hPtr;
575 register TkMainInfo *mainPtr;
576 register TkWindow *winPtr;
577 register TkCmd *cmdPtr;
578
579 /*
580 * Create the basic TkWindow structure.
581 */
582
583 tkwin = CreateTopLevelWindow(interp, (Tk_Window) NULL, baseName,
584 screenName);
585 if (tkwin == NULL) {
586 return NULL;
587 }
588
589 /*
590 * Create the TkMainInfo structure for this application, and set
591 * up name-related information for the new window.
592 */
593
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);
600 /* XXX: FOCUS */
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);
607
608 /*
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.
612 */
613
614 result = Tk_RegisterInterp(interp, baseName, tkwin);
615 if (result == TCL_OK) {
616 winPtr->nameUid = Tk_GetUid(baseName);
617 } else {
618 char newName[110];
619 int i;
620
621 for (i = 2; ; i++) {
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) {
626 break;
627 }
628 if (i >= 100) {
629 Tcl_SetResult(interp,
630 "couldn't generate unique name to register application",
631 TCL_STATIC);
632 Tk_DestroyWindow(tkwin);
633 }
634 }
635 winPtr->nameUid = Tk_GetUid(newName);
636 }
637
638 /*
639 * Bind in Tk's commands.
640 */
641
642 for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
643 Tcl_CreateCommand(interp, cmdPtr->name, cmdPtr->cmdProc,
644 (ClientData) tkwin, (void (*)(int *)) NULL);
645 }
646
647 /*
648 * Set variables for the intepreter.
649 */
650
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);
654
655 tk_NumMainWindows++;
656 return tkwin;
657 }
658 \f
659 /*
660 *--------------------------------------------------------------
661 *
662 * Tk_CreateWindow --
663 *
664 * Create a new internal or top-level window as a child of an
665 * existing window.
666 *
667 * Results:
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
672 * NULL is returned.
673 *
674 * Side effects:
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.
678 *
679 *--------------------------------------------------------------
680 */
681
682 Tk_Window
683 Tk_CreateWindow (
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
694 * window. */
695 )
696 {
697 TkWindow *parentPtr = (TkWindow *) parent;
698 TkWindow *winPtr;
699
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);
704 return NULL;
705 } else {
706 return (Tk_Window) winPtr;
707 }
708 } else {
709 /*
710 * This is a fix for dvx XOpenDisplay... display name conformalization
711 * bugs...
712 */
713 char dsp[256];
714 int len;
715
716 strcpy(dsp, screenName);
717 len = strlen(dsp);
718 if (len && (dsp[len -1] == '.'))
719 dsp[len -1] = '\0';
720
721 return CreateTopLevelWindow(interp, parent, name, dsp);
722 }
723 }
724 \f
725 /*
726 *----------------------------------------------------------------------
727 *
728 * Tk_CreateWindowFromPath --
729 *
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.
733 *
734 * Results:
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
739 * NULL is returned.
740 *
741 * Side effects:
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.
745 *
746 *----------------------------------------------------------------------
747 */
748
749 Tk_Window
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
764 * window. */
765 )
766 {
767 #define FIXED_SPACE 5
768 char fixedSpace[FIXED_SPACE+1];
769 char *p;
770 Tk_Window parent;
771 int numChars;
772
773 /*
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 ".".
780 */
781
782 p = strrchr(pathName, '.');
783 if (p == NULL) {
784 Tcl_AppendResult(interp, "bad window path name \"", pathName,
785 "\"", (char *) NULL);
786 return NULL;
787 }
788 numChars = p-pathName;
789 if (numChars > FIXED_SPACE) {
790 p = (char *) ckalloc((unsigned) (numChars+1));
791 } else {
792 p = fixedSpace;
793 }
794 if (numChars == 0) {
795 *p = '.';
796 p[1] = '\0';
797 } else {
798 strncpy(p, pathName, numChars);
799 p[numChars] = '\0';
800 }
801
802 /*
803 * Find the parent window.
804 */
805
806 parent = Tk_NameToWindow(interp, p, tkwin);
807 if (p != fixedSpace) {
808 ckfree(p);
809 }
810 if (parent == NULL) {
811 return NULL;
812 }
813
814 /*
815 * Create the window.
816 */
817
818 if (screenName == NULL) {
819 TkWindow *parentPtr = (TkWindow *) parent;
820 TkWindow *winPtr;
821
822 winPtr = NewWindow(parentPtr->dispPtr, parentPtr->screenNum);
823 if (NameWindow(interp, winPtr, parentPtr, pathName+numChars+1)
824 != TCL_OK) {
825 Tk_DestroyWindow((Tk_Window) winPtr);
826 return NULL;
827 } else {
828 return (Tk_Window) winPtr;
829 }
830 } else {
831 return CreateTopLevelWindow(interp, parent, pathName+numChars+1,
832 screenName);
833 }
834 }
835 \f
836 /*
837 *--------------------------------------------------------------
838 *
839 * Tk_DestroyWindow --
840 *
841 * Destroy an existing window. After this call, the caller
842 * should never again use the token.
843 *
844 * Results:
845 * None.
846 *
847 * Side effects:
848 * The window is deleted, along with all of its children.
849 * Relevant callback procedures are invoked.
850 *
851 *--------------------------------------------------------------
852 */
853
854 void
855 Tk_DestroyWindow (
856 Tk_Window tkwin /* Window to destroy. */
857 )
858 {
859 register TkWindow *winPtr = (TkWindow *) tkwin;
860 XEvent event;
861
862 /*
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.
868 */
869
870 while (winPtr->childList != NULL) {
871 winPtr->childList->flags |= TK_RECURSIVE_DESTROY;
872 Tk_DestroyWindow((Tk_Window) winPtr->childList);
873 }
874
875 /*
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.
881 */
882
883 if (winPtr->window == None) {
884 Tk_MakeWindowExist(tkwin);
885 }
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);
895
896 /*
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
901 * them explicitly).
902 */
903
904 if (winPtr->window != None) {
905 if (!(winPtr->flags & TK_RECURSIVE_DESTROY)
906 || (winPtr->flags & TK_TOP_LEVEL)) {
907 XDestroyWindow(winPtr->display, winPtr->window);
908 }
909 XDeleteContext(winPtr->display, winPtr->window, tkWindowContext);
910 winPtr->window = None;
911 }
912 if (winPtr->parentPtr != NULL) {
913 if (winPtr->parentPtr->childList == winPtr) {
914 winPtr->parentPtr->childList = winPtr->nextPtr;
915 } else {
916 register TkWindow *winPtr2;
917
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?)");
922 break;
923 }
924 if (winPtr2->nextPtr == winPtr) {
925 winPtr2->nextPtr = winPtr->nextPtr;
926 break;
927 }
928 }
929 }
930 }
931 TkEventDeadWindow(winPtr);
932 TkOptionDeadWindow(winPtr);
933 TkSelDeadWindow(winPtr);
934 if (winPtr->flags & TK_TOP_LEVEL) {
935 TkWmDeadWindow(winPtr);
936 }
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,
943 winPtr->pathName));
944 }
945 if (winPtr->mainPtr->winPtr == winPtr) {
946 register TkCmd *cmdPtr;
947
948 /*
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
952 * the interpreter.
953 */
954
955 for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
956 Tcl_CreateCommand(winPtr->mainPtr->interp, cmdPtr->name,
957 TkDeadAppCmd, (ClientData) NULL, (void (*)(int *)) NULL);
958 }
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);
964 tk_NumMainWindows--;
965 }
966 }
967 ckfree((char *) winPtr);
968 }
969 \f
970 /*
971 *--------------------------------------------------------------
972 *
973 * Tk_MapWindow --
974 *
975 * Map a window within its parent. This may require the
976 * window and/or its parents to actually be created.
977 *
978 * Results:
979 * None.
980 *
981 * Side effects:
982 * The given window will be mapped. Windows may also
983 * be created.
984 *
985 *--------------------------------------------------------------
986 */
987
988 void
989 Tk_MapWindow (
990 Tk_Window tkwin /* Token for window to map. */
991 )
992 {
993 register TkWindow *winPtr = (TkWindow *) tkwin;
994
995 if (winPtr->flags & TK_MAPPED) {
996 return;
997 }
998 if (winPtr->window == None) {
999 Tk_MakeWindowExist(tkwin);
1000 }
1001 if (winPtr->flags & TK_TOP_LEVEL) {
1002 if (!TkWmMapWindow(winPtr)) {
1003 return;
1004 }
1005 } else {
1006 /*
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-
1009 * iconic).
1010 */
1011
1012 winPtr->flags |= TK_MAPPED;
1013 }
1014 XMapWindow(winPtr->display, winPtr->window);
1015 if (!(winPtr->flags & TK_TOP_LEVEL)) {
1016 XEvent event;
1017
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);
1026 }
1027 }
1028 \f
1029 /*
1030 *--------------------------------------------------------------
1031 *
1032 * Tk_MakeWindowExist --
1033 *
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.
1038 *
1039 * Results:
1040 * None.
1041 *
1042 * Side effects:
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.
1046 *
1047 *--------------------------------------------------------------
1048 */
1049
1050 void
1051 Tk_MakeWindowExist (
1052 Tk_Window tkwin /* Token for window. */
1053 )
1054 {
1055 register TkWindow *winPtr = (TkWindow *) tkwin;
1056 Window parent;
1057
1058 if (winPtr->window != None) {
1059 return;
1060 }
1061
1062 if (winPtr->flags & TK_TOP_LEVEL) {
1063 /*
1064 * workaround by dhopkins for OLPC Micropolis gtk.Socket integration.
1065 */
1066
1067 if (tk_RootWindow) {
1068 parent =
1069 tk_RootWindow;
1070 } else {
1071 parent =
1072 XRootWindow(winPtr->display, winPtr->screenNum);
1073 }
1074
1075 } else {
1076 if (winPtr->parentPtr->window == None) {
1077 Tk_MakeWindowExist((Tk_Window) winPtr->parentPtr);
1078 }
1079 parent = winPtr->parentPtr->window;
1080 }
1081
1082 /* workaround to support non-default colormaps */
1083 #if 0
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,
1089 &winPtr->atts);
1090 #else
1091 { Screen *scr = ScreenOfDisplay(winPtr->display, winPtr->screenNum);
1092
1093 winPtr->dirtyAtts |= CWColormap | CWBorderPixmap;
1094 winPtr->atts.colormap = Tk_DefaultColormap(scr);
1095 winPtr->atts.border_pixmap = Tk_DefaultPixmap(scr);
1096
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),
1102 InputOutput,
1103 Tk_DefaultVisual(scr),
1104 winPtr->dirtyAtts, &winPtr->atts);
1105 }
1106 #endif
1107
1108 XSaveContext(winPtr->display, winPtr->window, tkWindowContext,
1109 (void *) winPtr);
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;
1116 }
1117
1118 /*
1119 * Issue a ConfigureNotify event if there were deferred configuration
1120 * changes.
1121 */
1122
1123 if (winPtr->flags & TK_NEED_CONFIG_NOTIFY) {
1124 winPtr->flags &= ~TK_NEED_CONFIG_NOTIFY;
1125 DoConfigureNotify(winPtr);
1126 }
1127 }
1128 \f
1129 /*
1130 *--------------------------------------------------------------
1131 *
1132 * Tk_UnmapWindow, etc. --
1133 *
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).
1140 *
1141 * Results:
1142 * See the manual entries.
1143 *
1144 * Side effects:
1145 * See the manual entries.
1146 *
1147 *--------------------------------------------------------------
1148 */
1149
1150 void
1151 Tk_UnmapWindow (
1152 Tk_Window tkwin /* Token for window to unmap. */
1153 )
1154 {
1155 register TkWindow *winPtr = (TkWindow *) tkwin;
1156
1157 if (!(winPtr->flags & TK_MAPPED)) {
1158 return;
1159 }
1160 winPtr->flags &= ~TK_MAPPED;
1161 XUnmapWindow(winPtr->display, winPtr->window);
1162 if (!(winPtr->flags & TK_TOP_LEVEL)) {
1163 XEvent event;
1164
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);
1173 }
1174 }
1175
1176 void
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. */
1182 )
1183 {
1184 register TkWindow *winPtr = (TkWindow *) tkwin;
1185
1186 if ((winPtr->window == None) || !(winPtr->flags & TK_TOP_LEVEL)) {
1187 if (valueMask & CWX) {
1188 winPtr->changes.x = valuePtr->x;
1189 }
1190 if (valueMask & CWY) {
1191 winPtr->changes.y = valuePtr->y;
1192 }
1193 if (valueMask & CWWidth) {
1194 winPtr->changes.width = valuePtr->width;
1195 }
1196 if (valueMask & CWHeight) {
1197 winPtr->changes.height = valuePtr->height;
1198 }
1199 if (valueMask & CWBorderWidth) {
1200 winPtr->changes.border_width = valuePtr->border_width;
1201 }
1202 if (valueMask & CWSibling) {
1203 winPtr->changes.sibling = valuePtr->sibling;
1204 }
1205 if (valueMask & CWStackMode) {
1206 winPtr->changes.stack_mode = valuePtr->stack_mode;
1207 }
1208 }
1209
1210 if (winPtr->window != None) {
1211 XConfigureWindow(winPtr->display, winPtr->window,
1212 valueMask, valuePtr);
1213 if (!(winPtr->flags & TK_TOP_LEVEL)) {
1214 DoConfigureNotify(winPtr);
1215 }
1216 } else {
1217 winPtr->dirtyChanges |= valueMask;
1218 winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1219 }
1220 }
1221
1222 void
1223 Tk_MoveWindow (
1224 Tk_Window tkwin, /* Window to move. */
1225 int x,
1226 int y /* New location for window (within
1227 * parent). */
1228 )
1229 {
1230 register TkWindow *winPtr = (TkWindow *) tkwin;
1231
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);
1238 }
1239 } else {
1240 winPtr->changes.x = x;
1241 winPtr->changes.y = y;
1242 winPtr->dirtyChanges |= CWX|CWY;
1243 winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1244 }
1245 }
1246
1247 void
1248 Tk_ResizeWindow (
1249 Tk_Window tkwin, /* Window to resize. */
1250 unsigned int width,
1251 unsigned int height /* New dimensions for window. */
1252 )
1253 {
1254 register TkWindow *winPtr = (TkWindow *) tkwin;
1255
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);
1262 }
1263 } else {
1264 winPtr->changes.width = width;
1265 winPtr->changes.height = height;
1266 winPtr->dirtyChanges |= CWWidth|CWHeight;
1267 winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1268 }
1269 }
1270
1271 void
1272 Tk_MoveResizeWindow (
1273 Tk_Window tkwin, /* Window to move and resize. */
1274 int x,
1275 int y, /* New location for window (within
1276 * parent). */
1277 unsigned int width,
1278 unsigned int height /* New dimensions for window. */
1279 )
1280 {
1281 register TkWindow *winPtr = (TkWindow *) tkwin;
1282
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);
1292 }
1293 } else {
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;
1300 }
1301 }
1302
1303 void
1304 Tk_SetWindowBorderWidth (
1305 Tk_Window tkwin, /* Window to modify. */
1306 int width /* New border width for window. */
1307 )
1308 {
1309 register TkWindow *winPtr = (TkWindow *) tkwin;
1310
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);
1316 }
1317 } else {
1318 winPtr->dirtyChanges |= CWBorderWidth;
1319 winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1320 }
1321 }
1322
1323 void
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
1330 )
1331 /* New values for some attributes. */
1332 {
1333 register TkWindow *winPtr = (TkWindow *) tkwin;
1334
1335 if (valueMask & CWBackPixmap) {
1336 winPtr->atts.background_pixmap = attsPtr->background_pixmap;
1337 }
1338 if (valueMask & CWBackPixel) {
1339 winPtr->atts.background_pixel = attsPtr->background_pixel;
1340 }
1341 if (valueMask & CWBorderPixmap) {
1342 winPtr->atts.border_pixmap = attsPtr->border_pixmap;
1343 }
1344 if (valueMask & CWBorderPixel) {
1345 winPtr->atts.border_pixel = attsPtr->border_pixel;
1346 }
1347 if (valueMask & CWBitGravity) {
1348 winPtr->atts.bit_gravity = attsPtr->bit_gravity;
1349 }
1350 if (valueMask & CWWinGravity) {
1351 winPtr->atts.win_gravity = attsPtr->win_gravity;
1352 }
1353 if (valueMask & CWBackingStore) {
1354 winPtr->atts.backing_store = attsPtr->backing_store;
1355 }
1356 if (valueMask & CWBackingPlanes) {
1357 winPtr->atts.backing_planes = attsPtr->backing_planes;
1358 }
1359 if (valueMask & CWBackingPixel) {
1360 winPtr->atts.backing_pixel = attsPtr->backing_pixel;
1361 }
1362 if (valueMask & CWOverrideRedirect) {
1363 winPtr->atts.override_redirect = attsPtr->override_redirect;
1364 }
1365 if (valueMask & CWSaveUnder) {
1366 winPtr->atts.save_under = attsPtr->save_under;
1367 }
1368 if (valueMask & CWEventMask) {
1369 winPtr->atts.event_mask = attsPtr->event_mask;
1370 }
1371 if (valueMask & CWDontPropagate) {
1372 winPtr->atts.do_not_propagate_mask
1373 = attsPtr->do_not_propagate_mask;
1374 }
1375 if (valueMask & CWColormap) {
1376 winPtr->atts.colormap = attsPtr->colormap;
1377 }
1378 if (valueMask & CWCursor) {
1379 winPtr->atts.cursor = attsPtr->cursor;
1380 }
1381
1382 if (winPtr->window != None) {
1383 XChangeWindowAttributes(winPtr->display, winPtr->window,
1384 valueMask, attsPtr);
1385 } else {
1386 winPtr->dirtyAtts |= valueMask;
1387 }
1388 }
1389
1390 void
1391 Tk_SetWindowBackground (
1392 Tk_Window tkwin, /* Window to manipulate. */
1393 unsigned long pixel /* Pixel value to use for
1394 * window's background. */
1395 )
1396 {
1397 register TkWindow *winPtr = (TkWindow *) tkwin;
1398
1399 winPtr->atts.background_pixel = pixel;
1400
1401 if (winPtr->window != None) {
1402 XSetWindowBackground(winPtr->display, winPtr->window, pixel);
1403 } else {
1404 winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBackPixmap)
1405 | CWBackPixel;
1406 }
1407 }
1408
1409 void
1410 Tk_SetWindowBackgroundPixmap (
1411 Tk_Window tkwin, /* Window to manipulate. */
1412 Pixmap pixmap /* Pixmap to use for window's
1413 * background. */
1414 )
1415 {
1416 register TkWindow *winPtr = (TkWindow *) tkwin;
1417
1418 winPtr->atts.background_pixmap = pixmap;
1419
1420 if (winPtr->window != None) {
1421 XSetWindowBackgroundPixmap(winPtr->display,
1422 winPtr->window, pixmap);
1423 } else {
1424 winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBackPixel)
1425 | CWBackPixmap;
1426 }
1427 }
1428
1429 void
1430 Tk_SetWindowBorder (
1431 Tk_Window tkwin, /* Window to manipulate. */
1432 unsigned long pixel /* Pixel value to use for
1433 * window's border. */
1434 )
1435 {
1436 register TkWindow *winPtr = (TkWindow *) tkwin;
1437
1438 winPtr->atts.border_pixel = pixel;
1439
1440 if (winPtr->window != None) {
1441 XSetWindowBorder(winPtr->display, winPtr->window, pixel);
1442 } else {
1443 winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBorderPixmap)
1444 | CWBorderPixel;
1445 }
1446 }
1447
1448 void
1449 Tk_SetWindowBorderPixmap (
1450 Tk_Window tkwin, /* Window to manipulate. */
1451 Pixmap pixmap /* Pixmap to use for window's
1452 * border. */
1453 )
1454 {
1455 register TkWindow *winPtr = (TkWindow *) tkwin;
1456
1457 winPtr->atts.border_pixmap = pixmap;
1458
1459 if (winPtr->window != None) {
1460 XSetWindowBorderPixmap(winPtr->display,
1461 winPtr->window, pixmap);
1462 } else {
1463 winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBorderPixel)
1464 | CWBorderPixmap;
1465 }
1466 }
1467
1468 void
1469 Tk_DefineCursor (
1470 Tk_Window tkwin, /* Window to manipulate. */
1471 Cursor cursor /* Cursor to use for window (may be None). */
1472 )
1473 {
1474 register TkWindow *winPtr = (TkWindow *) tkwin;
1475
1476 winPtr->atts.cursor = cursor;
1477
1478 if (winPtr->window != None) {
1479 XDefineCursor(winPtr->display, winPtr->window, cursor);
1480 } else {
1481 winPtr->dirtyAtts = winPtr->dirtyAtts | CWCursor;
1482 }
1483 }
1484
1485 void
1486 Tk_UndefineCursor (
1487 Tk_Window tkwin /* Window to manipulate. */
1488 )
1489 {
1490 Tk_DefineCursor(tkwin, None);
1491 }
1492 \f
1493 /*
1494 *----------------------------------------------------------------------
1495 *
1496 * DoConfigureNotify --
1497 *
1498 * Generate a ConfigureNotify event describing the current
1499 * configuration of a window.
1500 *
1501 * Results:
1502 * None.
1503 *
1504 * Side effects:
1505 * An event is generated and processed by Tk_HandleEvent.
1506 *
1507 *----------------------------------------------------------------------
1508 */
1509
1510 static void
1511 DoConfigureNotify (
1512 register TkWindow *winPtr /* Window whose configuration
1513 * was just changed. */
1514 )
1515 {
1516 XEvent event;
1517
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;
1531 } else {
1532 event.xconfigure.above = None;
1533 }
1534 event.xconfigure.override_redirect = winPtr->atts.override_redirect;
1535 Tk_HandleEvent(&event);
1536 }
1537 \f
1538 /*
1539 *----------------------------------------------------------------------
1540 *
1541 * Tk_SetClass --
1542 *
1543 * This procedure is used to give a window a class.
1544 *
1545 * Results:
1546 * None.
1547 *
1548 * Side effects:
1549 * A new class is stored for tkwin, replacing any existing
1550 * class for it.
1551 *
1552 *----------------------------------------------------------------------
1553 */
1554
1555 void
1556 Tk_SetClass (
1557 Tk_Window tkwin, /* Token for window to assign class. */
1558 char *className /* New class for tkwin. */
1559 )
1560 {
1561 register TkWindow *winPtr = (TkWindow *) tkwin;
1562
1563 winPtr->classUid = Tk_GetUid(className);
1564 if (winPtr->flags & TK_TOP_LEVEL) {
1565 TkWmSetClass(winPtr);
1566 }
1567 }
1568 \f
1569 /*
1570 *----------------------------------------------------------------------
1571 *
1572 * Tk_NameToWindow --
1573 *
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.
1577 *
1578 * Results:
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.
1582 *
1583 * Side effects:
1584 * None.
1585 *
1586 *----------------------------------------------------------------------
1587 */
1588
1589 Tk_Window
1590 Tk_NameToWindow (
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. */
1595 )
1596 {
1597 Tcl_HashEntry *hPtr;
1598
1599 hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->nameTable,
1600 pathName);
1601 if (hPtr == NULL) {
1602 Tcl_AppendResult(interp, "bad window path name \"",
1603 pathName, "\"", (char *) NULL);
1604 return NULL;
1605 }
1606 return (Tk_Window) Tcl_GetHashValue(hPtr);
1607 }
1608 \f
1609 /*
1610 *----------------------------------------------------------------------
1611 *
1612 * Tk_DisplayName --
1613 *
1614 * Return the textual name of a window's display.
1615 *
1616 * Results:
1617 * The return value is the string name of the display associated
1618 * with tkwin.
1619 *
1620 * Side effects:
1621 * None.
1622 *
1623 *----------------------------------------------------------------------
1624 */
1625
1626 char *
1627 Tk_DisplayName (
1628 Tk_Window tkwin /* Window whose display name is desired. */
1629 )
1630 {
1631 return ((TkWindow *) tkwin)->dispPtr->name;
1632 }
Impressum, Datenschutz