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