1 /*
2 * bltWindow.c --
3 *
4 * This module implements additional window functionality for
5 * the BLT toolkit, such as transparent Tk windows,
6 * and reparenting Tk windows.
7 *
8 * Copyright 1991-1998 Lucent Technologies, Inc.
9 *
10 * Permission to use, copy, modify, and distribute this software and
11 * its documentation for any purpose and without fee is hereby
12 * granted, provided that the above copyright notice appear in all
13 * copies and that both that the copyright notice and warranty
14 * disclaimer appear in supporting documentation, and that the names
15 * of Lucent Technologies any of their entities not be used in
16 * advertising or publicity pertaining to distribution of the software
17 * without specific, written prior permission.
18 *
19 * Lucent Technologies disclaims all warranties with regard to this
20 * software, including all implied warranties of merchantability and
21 * fitness. In no event shall Lucent Technologies be liable for any
22 * special, indirect or consequential damages or any damages
23 * whatsoever resulting from loss of use, data or profits, whether in
24 * an action of contract, negligence or other tortuous action, arising
25 * out of or in connection with the use or performance of this
26 * software.
27 */
28
29 #include "bltInt.h"
30
31 #include <X11/Xlib.h>
32 #ifndef WIN32
33 #include <X11/Xproto.h>
34 #endif
35
36 #include <tkInt.h>
37
38 #ifdef XNQueryInputStyle
39 #define TK_USE_INPUT_METHODS
40 #endif
41
42 /*
43 * This defines whether we should try to use XIM over-the-spot style
44 * input. Allow users to override it. It is a much more elegant use
45 * of XIM, but uses a bit more memory.
46 */
47 #ifndef TK_XIM_SPOT
48 # define TK_XIM_SPOT 1
49 #endif
50
51 #ifndef TK_REPARENTED
52 #define TK_REPARENTED 0
53 #endif
54
55 #ifdef WIN32
56 /*
57 *----------------------------------------------------------------------
58 *
59 * GetWindowHandle --
60 *
61 * Returns the XID for the Tk_Window given. Starting in Tk 8.0,
62 * the toplevel widgets are wrapped by another window.
63 * Currently there's no way to get at that window, other than
64 * what is done here: query the X window hierarchy and grab the
65 * parent.
66 *
67 * Results:
68 * Returns the X Window ID of the widget. If it's a toplevel, then
69 * the XID of the wrapper is returned.
70 *
71 *----------------------------------------------------------------------
72 */
73 static HWND
GetWindowHandle(Tk_Window tkwin)74 GetWindowHandle(Tk_Window tkwin)
75 {
76 HWND hWnd;
77 Window window;
78
79 window = Tk_WindowId(tkwin);
80 if (window == None) {
81 Tk_MakeWindowExist(tkwin);
82 }
83 hWnd = Tk_GetHWND(Tk_WindowId(tkwin));
84 #if (TK_MAJOR_VERSION > 4)
85 if (Tk_IsTopLevel(tkwin)) {
86 hWnd = GetParent(hWnd);
87 }
88 #endif /* TK_MAJOR_VERSION > 4 */
89 return hWnd;
90 }
91
92 Window
Blt_GetParent(display,window)93 Blt_GetParent(display, window)
94 Display *display;
95 Window window;
96 {
97 HWND hWnd;
98 hWnd = GetWindowHandle(window);
99 return (Window)hWnd;
100 }
101
102 #else
103
104 Window
Blt_GetParent(display,window)105 Blt_GetParent(display, window)
106 Display *display;
107 Window window;
108 {
109 Window root, parent;
110 Window *dummy;
111 unsigned int count;
112
113 if (XQueryTree(display, window, &root, &parent, &dummy, &count) > 0) {
114 XFree(dummy);
115 return parent;
116 }
117 return None;
118 }
119
120 static Window
GetWindowId(tkwin)121 GetWindowId(tkwin)
122 Tk_Window tkwin;
123 {
124 Window window;
125
126 Tk_MakeWindowExist(tkwin);
127 window = Tk_WindowId(tkwin);
128 #if (TK_MAJOR_VERSION > 4)
129 if (Tk_IsTopLevel(tkwin)) {
130 Window parent;
131
132 parent = Blt_GetParent(Tk_Display(tkwin), window);
133 if (parent != None && parent != XRootWindow(Tk_Display(tkwin), Tk_ScreenNumber(tkwin))) {
134 window = parent;
135 }
136 /*window = parent; */
137 }
138 #endif /* TK_MAJOR_VERSION > 4 */
139 return window;
140 }
141
142 #endif /* WIN32 */
143
144 /*
145 *----------------------------------------------------------------------
146 *
147 * DoConfigureNotify --
148 *
149 * Generate a ConfigureNotify event describing the current
150 * configuration of a window.
151 *
152 * Results:
153 * None.
154 *
155 * Side effects:
156 * An event is generated and processed by Tk_HandleEvent.
157 *
158 *----------------------------------------------------------------------
159 */
160 static void
DoConfigureNotify(winPtr)161 DoConfigureNotify(winPtr)
162 Tk_FakeWin *winPtr; /* Window whose configuration was just
163 * changed. */
164 {
165 XEvent event;
166
167 event.type = ConfigureNotify;
168 event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display);
169 event.xconfigure.send_event = False;
170 event.xconfigure.display = winPtr->display;
171 event.xconfigure.event = winPtr->window;
172 event.xconfigure.window = winPtr->window;
173 event.xconfigure.x = winPtr->changes.x;
174 event.xconfigure.y = winPtr->changes.y;
175 event.xconfigure.width = winPtr->changes.width;
176 event.xconfigure.height = winPtr->changes.height;
177 event.xconfigure.border_width = winPtr->changes.border_width;
178 if (winPtr->changes.stack_mode == Above) {
179 event.xconfigure.above = winPtr->changes.sibling;
180 } else {
181 event.xconfigure.above = None;
182 }
183 event.xconfigure.override_redirect = winPtr->atts.override_redirect;
184 Tk_HandleEvent(&event);
185 }
186
187 /*
188 *--------------------------------------------------------------
189 *
190 * Blt_MakeTransparentWindowExist --
191 *
192 * Similar to Tk_MakeWindowExist but instead creates a
193 * transparent window to block for user events from sibling
194 * windows.
195 *
196 * Differences from Tk_MakeWindowExist.
197 *
198 * 1. This is always a "busy" window. There's never a
199 * platform-specific class procedure to execute instead.
200 * 2. The window is transparent and never will contain children,
201 * so colormap information is irrelevant.
202 *
203 * Results:
204 * None.
205 *
206 * Side effects:
207 * When the procedure returns, the internal window associated
208 * with tkwin is guaranteed to exist. This may require the
209 * window's ancestors to be created too.
210 *
211 *--------------------------------------------------------------
212 */
213 void
Blt_MakeTransparentWindowExist(tkwin,parent,isBusy)214 Blt_MakeTransparentWindowExist(tkwin, parent, isBusy)
215 Tk_Window tkwin; /* Token for window. */
216 Window parent; /* Parent window. */
217 int isBusy; /* */
218 {
219 TkWindow *winPtr = (TkWindow *) tkwin;
220 TkWindow *winPtr2;
221 Tcl_HashEntry *hPtr;
222 int notUsed;
223 TkDisplay *dispPtr;
224 #ifdef WIN32
225 HWND hParent;
226 int style;
227 DWORD exStyle;
228 HWND hWnd;
229 #else
230 long int mask;
231 #endif /* WIN32 */
232
233 if (winPtr->window != None) {
234 return; /* Window already exists. */
235 }
236 #ifdef notdef
237 if ((winPtr->parentPtr == NULL) || (winPtr->flags & TK_TOP_LEVEL)) {
238 parent = XRootWindow(winPtr->display, winPtr->screenNum);
239 /* TODO: Make the entire screen busy */
240 } else {
241 if (Tk_WindowId(winPtr->parentPtr) == None) {
242 Tk_MakeWindowExist((Tk_Window)winPtr->parentPtr);
243 }
244 }
245 #endif
246
247 /* Create a transparent window and put it on top. */
248
249 #ifdef WIN32
250 hParent = (HWND) parent;
251 style = (WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
252 exStyle = (WS_EX_TRANSPARENT | WS_EX_TOPMOST);
253 #define TK_WIN_CHILD_CLASS_NAME "TkChild"
254 hWnd = CreateWindowEx(exStyle, TK_WIN_CHILD_CLASS_NAME, NULL, style,
255 Tk_X(tkwin), Tk_Y(tkwin), Tk_Width(tkwin), Tk_Height(tkwin),
256 hParent, NULL, (HINSTANCE) Tk_GetHINSTANCE(), NULL);
257 winPtr->window = Tk_AttachHWND(tkwin, hWnd);
258 #else
259 mask = (!isBusy) ? 0 : (CWDontPropagate | CWEventMask);
260 /* Ignore the important events while the window is mapped. */
261 #define USER_EVENTS (EnterWindowMask | LeaveWindowMask | KeyPressMask | \
262 KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask)
263 #define PROP_EVENTS (KeyPressMask | KeyReleaseMask | ButtonPressMask | \
264 ButtonReleaseMask | PointerMotionMask)
265
266 winPtr->atts.do_not_propagate_mask = PROP_EVENTS;
267 winPtr->atts.event_mask = USER_EVENTS;
268 winPtr->changes.border_width = 0;
269 winPtr->depth = 0;
270
271 winPtr->window = XCreateWindow(winPtr->display, parent,
272 winPtr->changes.x, winPtr->changes.y,
273 (unsigned)winPtr->changes.width, /* width */
274 (unsigned)winPtr->changes.height, /* height */
275 (unsigned)winPtr->changes.border_width, /* border_width */
276 winPtr->depth, /* depth */
277 InputOnly, /* class */
278 winPtr->visual, /* visual */
279 mask, /* valuemask */
280 &(winPtr->atts) /* attributes */ );
281 #endif /* WIN32 */
282
283 dispPtr = winPtr->dispPtr;
284 hPtr = Tcl_CreateHashEntry(&(dispPtr->winTable), (char *)winPtr->window,
285 ¬Used);
286 Tcl_SetHashValue(hPtr, winPtr);
287 winPtr->dirtyAtts = 0;
288 winPtr->dirtyChanges = 0;
289 #ifdef TK_USE_INPUT_METHODS
290 winPtr->inputContext = NULL;
291 #endif /* TK_USE_INPUT_METHODS */
292 if (!(winPtr->flags & TK_TOP_LEVEL)) {
293 /*
294 * If any siblings higher up in the stacking order have already
295 * been created then move this window to its rightful position
296 * in the stacking order.
297 *
298 * NOTE: this code ignores any changes anyone might have made
299 * to the sibling and stack_mode field of the window's attributes,
300 * so it really isn't safe for these to be manipulated except
301 * by calling Tk_RestackWindow.
302 */
303 for (winPtr2 = winPtr->nextPtr; winPtr2 != NULL;
304 winPtr2 = winPtr2->nextPtr) {
305 if ((winPtr2->window != None) && !(winPtr2->flags & TK_TOP_LEVEL)) {
306 XWindowChanges changes;
307 changes.sibling = winPtr2->window;
308 changes.stack_mode = Below;
309 XConfigureWindow(winPtr->display, winPtr->window,
310 CWSibling | CWStackMode, &changes);
311 break;
312 }
313 }
314 }
315
316 /*
317 * Issue a ConfigureNotify event if there were deferred configuration
318 * changes (but skip it if the window is being deleted; the
319 * ConfigureNotify event could cause problems if we're being called
320 * from Tk_DestroyWindow under some conditions).
321 */
322 if ((winPtr->flags & TK_NEED_CONFIG_NOTIFY)
323 && !(winPtr->flags & TK_ALREADY_DEAD)) {
324 winPtr->flags &= ~TK_NEED_CONFIG_NOTIFY;
325 DoConfigureNotify((Tk_FakeWin *) tkwin);
326 }
327 }
328
329 /*
330 *----------------------------------------------------------------------
331 *
332 * Blt_FindChild --
333 *
334 * Performs a linear search for the named child window in a given
335 * parent window.
336 *
337 * This can be done via Tcl, but not through Tk's C API. It's
338 * simple enough, if you peek into the Tk_Window structure.
339 *
340 * Results:
341 * The child Tk_Window. If the named child can't be found, NULL
342 * is returned.
343 *
344 *----------------------------------------------------------------------
345 */
346
347 /*LINTLIBRARY*/
348 Tk_Window
Blt_FindChild(parent,name)349 Blt_FindChild(parent, name)
350 Tk_Window parent;
351 char *name;
352 {
353 register TkWindow *winPtr;
354 TkWindow *parentPtr = (TkWindow *)parent;
355
356 for (winPtr = parentPtr->childList; winPtr != NULL;
357 winPtr = winPtr->nextPtr) {
358 if (strcmp(name, winPtr->nameUid) == 0) {
359 return (Tk_Window)winPtr;
360 }
361 }
362 return NULL;
363 }
364
365 /*
366 *----------------------------------------------------------------------
367 *
368 * Blt_FirstChildWindow --
369 *
370 * Performs a linear search for the named child window in a given
371 * parent window.
372 *
373 * This can be done via Tcl, but not through Tk's C API. It's
374 * simple enough, if you peek into the Tk_Window structure.
375 *
376 * Results:
377 * The child Tk_Window. If the named child can't be found, NULL
378 * is returned.
379 *
380 *----------------------------------------------------------------------
381 */
382 /*LINTLIBRARY*/
383 Tk_Window
Blt_FirstChild(parent)384 Blt_FirstChild(parent)
385 Tk_Window parent;
386 {
387 TkWindow *parentPtr = (TkWindow *)parent;
388 return (Tk_Window)parentPtr->childList;
389 }
390
391 /*
392 *----------------------------------------------------------------------
393 *
394 * Blt_FindChild --
395 *
396 * Performs a linear search for the named child window in a given
397 * parent window.
398 *
399 * This can be done via Tcl, but not through Tk's C API. It's
400 * simple enough, if you peek into the Tk_Window structure.
401 *
402 * Results:
403 * The child Tk_Window. If the named child can't be found, NULL
404 * is returned.
405 *
406 *----------------------------------------------------------------------
407 */
408
409 /*LINTLIBRARY*/
410 Tk_Window
Blt_NextChild(tkwin)411 Blt_NextChild(tkwin)
412 Tk_Window tkwin;
413 {
414 TkWindow *winPtr = (TkWindow *)tkwin;
415
416 if (winPtr == NULL) {
417 return NULL;
418 }
419 return (Tk_Window)winPtr->nextPtr;
420 }
421
422 /*
423 *----------------------------------------------------------------------
424 *
425 * UnlinkWindow --
426 *
427 * This procedure removes a window from the childList of its
428 * parent.
429 *
430 * Results:
431 * None.
432 *
433 * Side effects:
434 * The window is unlinked from its childList.
435 *
436 *----------------------------------------------------------------------
437 */
438 static void
UnlinkWindow(winPtr)439 UnlinkWindow(winPtr)
440 TkWindow *winPtr; /* Child window to be unlinked. */
441 {
442 TkWindow *prevPtr;
443
444 prevPtr = winPtr->parentPtr->childList;
445 if (prevPtr == winPtr) {
446 winPtr->parentPtr->childList = winPtr->nextPtr;
447 if (winPtr->nextPtr == NULL) {
448 winPtr->parentPtr->lastChildPtr = NULL;
449 }
450 } else {
451 while (prevPtr->nextPtr != winPtr) {
452 prevPtr = prevPtr->nextPtr;
453 if (prevPtr == NULL) {
454 panic("UnlinkWindow couldn't find child in parent");
455 }
456 }
457 prevPtr->nextPtr = winPtr->nextPtr;
458 if (winPtr->nextPtr == NULL) {
459 winPtr->parentPtr->lastChildPtr = prevPtr;
460 }
461 }
462 }
463
464 /*
465 *----------------------------------------------------------------------
466 *
467 * Blt_RelinkWindow --
468 *
469 * Relinks a window into a new parent. The window is unlinked
470 * from its original parent's child list and added onto the end
471 * of the new parent's list.
472 *
473 * FIXME: If the window has focus, the focus should be moved
474 * to an ancestor. Otherwise, Tk becomes confused
475 * about which Toplevel turns on focus for the window.
476 * Right now this is done at the Tcl layer. For example,
477 * see blt::CreateTearoff in tabset.tcl.
478 *
479 * Results:
480 * None.
481 *
482 * Side effects:
483 * The window is unlinked from its childList.
484 *
485 *----------------------------------------------------------------------
486 */
487 void
Blt_RelinkWindow(tkwin,newParent,x,y)488 Blt_RelinkWindow(tkwin, newParent, x, y)
489 Tk_Window tkwin; /* Child window to be linked. */
490 Tk_Window newParent;
491 int x, y;
492 {
493 TkWindow *winPtr, *parentWinPtr;
494
495 if (Blt_ReparentWindow(Tk_Display(tkwin), Tk_WindowId(tkwin),
496 Tk_WindowId(newParent), x, y) != TCL_OK) {
497 return;
498 }
499 winPtr = (TkWindow *)tkwin;
500 parentWinPtr = (TkWindow *)newParent;
501
502 winPtr->flags &= ~TK_REPARENTED;
503 UnlinkWindow(winPtr); /* Remove the window from its parent's list */
504
505 /* Append the window onto the end of the parent's list of children */
506 winPtr->parentPtr = parentWinPtr;
507 winPtr->nextPtr = NULL;
508 if (parentWinPtr->childList == NULL) {
509 parentWinPtr->childList = winPtr;
510 } else {
511 parentWinPtr->lastChildPtr->nextPtr = winPtr;
512 }
513 parentWinPtr->lastChildPtr = winPtr;
514 }
515
516 /*
517 *----------------------------------------------------------------------
518 *
519 * Blt_RelinkWindow --
520 *
521 * Relinks a window into a new parent. The window is unlinked
522 * from its original parent's child list and added onto the end
523 * of the new parent's list.
524 *
525 * FIXME: If the window has focus, the focus should be moved
526 * to an ancestor. Otherwise, Tk becomes confused
527 * about which Toplevel turns on focus for the window.
528 * Right now this is done at the Tcl layer. For example,
529 * see blt::CreateTearoff in tabset.tcl.
530 *
531 * Results:
532 * None.
533 *
534 * Side effects:
535 * The window is unlinked from its childList.
536 *
537 *----------------------------------------------------------------------
538 */
539 void
Blt_RelinkWindow2(tkwin,window,newParent,x,y)540 Blt_RelinkWindow2(tkwin, window, newParent, x, y)
541 Tk_Window tkwin; /* Child window to be linked. */
542 Window window;
543 Tk_Window newParent;
544 int x, y;
545 {
546 #ifdef notdef
547 TkWindow *winPtr, *parentWinPtr;
548 #endif
549 if (Blt_ReparentWindow(Tk_Display(tkwin), window,
550 Tk_WindowId(newParent), x, y) != TCL_OK) {
551 return;
552 }
553 #ifdef notdef
554 winPtr = (TkWindow *)tkwin;
555 parentWinPtr = (TkWindow *)newParent;
556
557 winPtr->flags &= ~TK_REPARENTED;
558 UnlinkWindow(winPtr); /* Remove the window from its parent's list */
559
560 /* Append the window onto the end of the parent's list of children */
561 winPtr->parentPtr = parentWinPtr;
562 winPtr->nextPtr = NULL;
563 if (parentWinPtr->childList == NULL) {
564 parentWinPtr->childList = winPtr;
565 } else {
566 parentWinPtr->lastChildPtr->nextPtr = winPtr;
567 }
568 parentWinPtr->lastChildPtr = winPtr;
569 #endif
570 }
571
572 void
Blt_UnlinkWindow(tkwin)573 Blt_UnlinkWindow(tkwin)
574 Tk_Window tkwin; /* Child window to be linked. */
575 {
576 TkWindow *winPtr;
577 Window root;
578
579 root = XRootWindow(Tk_Display(tkwin), Tk_ScreenNumber(tkwin));
580 if (Blt_ReparentWindow(Tk_Display(tkwin), Tk_WindowId(tkwin),
581 root, 0, 0) != TCL_OK) {
582 return;
583 }
584 winPtr = (TkWindow *)tkwin;
585 winPtr->flags &= ~TK_REPARENTED;
586 #ifdef notdef
587 UnlinkWindow(winPtr); /* Remove the window from its parent's list */
588 #endif
589 }
590
591 /*
592 *----------------------------------------------------------------------
593 *
594 * Blt_Toplevel --
595 *
596 * Climbs up the widget hierarchy to find the top level window of
597 * the window given.
598 *
599 * Results:
600 * Returns the Tk_Window of the toplevel widget.
601 *
602 *----------------------------------------------------------------------
603 */
604 Tk_Window
Blt_Toplevel(tkwin)605 Blt_Toplevel(tkwin)
606 register Tk_Window tkwin;
607 {
608 while (!Tk_IsTopLevel(tkwin)) {
609 tkwin = Tk_Parent(tkwin);
610 }
611 return tkwin;
612 }
613
614 void
Blt_RootCoordinates(tkwin,x,y,rootXPtr,rootYPtr)615 Blt_RootCoordinates(tkwin, x, y, rootXPtr, rootYPtr)
616 Tk_Window tkwin;
617 int x, y;
618 int *rootXPtr, *rootYPtr;
619 {
620 int vx, vy, vw, vh;
621 int rootX, rootY;
622
623 Tk_GetRootCoords(tkwin, &rootX, &rootY);
624 x += rootX;
625 y += rootY;
626 Tk_GetVRootGeometry(tkwin, &vx, &vy, &vw, &vh);
627 x += vx;
628 y += vy;
629 *rootXPtr = x;
630 *rootYPtr = y;
631 }
632
633
634 /* Find the toplevel then */
635 int
Blt_RootX(tkwin)636 Blt_RootX(tkwin)
637 Tk_Window tkwin;
638 {
639 int x;
640
641 for (x = 0; tkwin != NULL; tkwin = Tk_Parent(tkwin)) {
642 x += Tk_X(tkwin) + Tk_Changes(tkwin)->border_width;
643 if (Tk_IsTopLevel(tkwin)) {
644 break;
645 }
646 }
647 return x;
648 }
649
650 int
Blt_RootY(tkwin)651 Blt_RootY(tkwin)
652 Tk_Window tkwin;
653 {
654 int y;
655
656 for (y = 0; tkwin != NULL; tkwin = Tk_Parent(tkwin)) {
657 y += Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width;
658 if (Tk_IsTopLevel(tkwin)) {
659 break;
660 }
661 }
662 return y;
663 }
664
665 #ifdef WIN32
666 /*
667 *----------------------------------------------------------------------
668 *
669 * Blt_GetRealWindowId --
670 *
671 * Returns the XID for the Tk_Window given. Starting in Tk 8.0,
672 * the toplevel widgets are wrapped by another window.
673 * Currently there's no way to get at that window, other than
674 * what is done here: query the X window hierarchy and grab the
675 * parent.
676 *
677 * Results:
678 * Returns the X Window ID of the widget. If it's a toplevel, then
679 * the XID of the wrapper is returned.
680 *
681 *----------------------------------------------------------------------
682 */
683 Window
Blt_GetRealWindowId(Tk_Window tkwin)684 Blt_GetRealWindowId(Tk_Window tkwin)
685 {
686 return (Window) GetWindowHandle(tkwin);
687 }
688
689 /*
690 *----------------------------------------------------------------------
691 *
692 * Blt_GetToplevel --
693 *
694 * Retrieves the toplevel window which is the nearest ancestor of
695 * of the specified window.
696 *
697 * Results:
698 * Returns the toplevel window or NULL if the window has no
699 * ancestor which is a toplevel.
700 *
701 * Side effects:
702 * None.
703 *
704 *----------------------------------------------------------------------
705 */
706 Tk_Window
Blt_GetToplevel(Tk_Window tkwin)707 Blt_GetToplevel(Tk_Window tkwin) /* Window for which the toplevel
708 * should be deterined. */
709 {
710 while (!Tk_IsTopLevel(tkwin)) {
711 tkwin = Tk_Parent(tkwin);
712 if (tkwin == NULL) {
713 return NULL;
714 }
715 }
716 return tkwin;
717 }
718
719 /*
720 *----------------------------------------------------------------------
721 *
722 * Blt_RaiseToLevelWindow --
723 *
724 * Results:
725 * None.
726 *
727 *----------------------------------------------------------------------
728 */
729 void
Blt_RaiseToplevel(Tk_Window tkwin)730 Blt_RaiseToplevel(Tk_Window tkwin)
731 {
732 SetWindowPos(GetWindowHandle(tkwin), HWND_TOP, 0, 0, 0, 0,
733 SWP_NOMOVE | SWP_NOSIZE);
734 }
735
736 /*
737 *----------------------------------------------------------------------
738 *
739 * Blt_MapToplevel --
740 *
741 * Results:
742 * None.
743 *
744 *----------------------------------------------------------------------
745 */
746 void
Blt_MapToplevel(Tk_Window tkwin)747 Blt_MapToplevel(Tk_Window tkwin)
748 {
749 ShowWindow(GetWindowHandle(tkwin), SW_SHOWNORMAL);
750 }
751
752 /*
753 *----------------------------------------------------------------------
754 *
755 * Blt_UnmapToplevel --
756 *
757 * Results:
758 * None.
759 *
760 *----------------------------------------------------------------------
761 */
762 void
Blt_UnmapToplevel(Tk_Window tkwin)763 Blt_UnmapToplevel(Tk_Window tkwin)
764 {
765 ShowWindow(GetWindowHandle(tkwin), SW_HIDE);
766 }
767
768 /*
769 *----------------------------------------------------------------------
770 *
771 * Blt_MoveResizeToplevel --
772 *
773 * Results:
774 * None.
775 *
776 *----------------------------------------------------------------------
777 */
778 void
Blt_MoveResizeToplevel(tkwin,x,y,width,height)779 Blt_MoveResizeToplevel(tkwin, x, y, width, height)
780 Tk_Window tkwin;
781 int x, y, width, height;
782 {
783 SetWindowPos(GetWindowHandle(tkwin), HWND_TOP, x, y, width, height, 0);
784 }
785
786 int
Blt_ReparentWindow(Display * display,Window window,Window newParent,int x,int y)787 Blt_ReparentWindow(
788 Display *display,
789 Window window,
790 Window newParent,
791 int x, int y)
792 {
793 XReparentWindow(display, window, newParent, x, y);
794 return TCL_OK;
795 }
796
797 #else /* WIN32 */
798
799 /*
800 *----------------------------------------------------------------------
801 *
802 * Blt_GetRealWindowId --
803 *
804 * Returns the XID for the Tk_Window given. Starting in Tk 8.0,
805 * the toplevel widgets are wrapped by another window.
806 * Currently there's no way to get at that window, other than
807 * what is done here: query the X window hierarchy and grab the
808 * parent.
809 *
810 * Results:
811 * Returns the X Window ID of the widget. If it's a toplevel, then
812 * the XID of the wrapper is returned.
813 *
814 *----------------------------------------------------------------------
815 */
816 Window
Blt_GetRealWindowId(tkwin)817 Blt_GetRealWindowId(tkwin)
818 Tk_Window tkwin;
819 {
820 return GetWindowId(tkwin);
821 }
822
823 /*
824 *----------------------------------------------------------------------
825 *
826 * Blt_RaiseToplevel --
827 *
828 * Results:
829 * None.
830 *
831 *----------------------------------------------------------------------
832 */
833 void
Blt_RaiseToplevel(tkwin)834 Blt_RaiseToplevel(tkwin)
835 Tk_Window tkwin;
836 {
837 XRaiseWindow(Tk_Display(tkwin), GetWindowId(tkwin));
838 }
839
840 /*
841 *----------------------------------------------------------------------
842 *
843 * Blt_LowerToplevel --
844 *
845 * Results:
846 * None.
847 *
848 *----------------------------------------------------------------------
849 */
850 void
Blt_LowerToplevel(tkwin)851 Blt_LowerToplevel(tkwin)
852 Tk_Window tkwin;
853 {
854 XLowerWindow(Tk_Display(tkwin), GetWindowId(tkwin));
855 }
856
857 /*
858 *----------------------------------------------------------------------
859 *
860 * Blt_ResizeToplevel --
861 *
862 * Results:
863 * None.
864 *
865 *----------------------------------------------------------------------
866 */
867 void
Blt_ResizeToplevel(tkwin,width,height)868 Blt_ResizeToplevel(tkwin, width, height)
869 Tk_Window tkwin;
870 int width, height;
871 {
872 XResizeWindow(Tk_Display(tkwin), GetWindowId(tkwin), width, height);
873 }
874
875 /*
876 *----------------------------------------------------------------------
877 *
878 * Blt_MoveResizeToplevel --
879 *
880 * Results:
881 * None.
882 *
883 *----------------------------------------------------------------------
884 */
885 void
Blt_MoveResizeToplevel(tkwin,x,y,width,height)886 Blt_MoveResizeToplevel(tkwin, x, y, width, height)
887 Tk_Window tkwin;
888 int x, y, width, height;
889 {
890 XMoveResizeWindow(Tk_Display(tkwin), GetWindowId(tkwin), x, y,
891 width, height);
892 }
893
894 /*
895 *----------------------------------------------------------------------
896 *
897 * Blt_ResizeToplevel --
898 *
899 * Results:
900 * None.
901 *
902 *----------------------------------------------------------------------
903 */
904 void
Blt_MoveToplevel(tkwin,x,y)905 Blt_MoveToplevel(tkwin, x, y)
906 Tk_Window tkwin;
907 int x, y;
908 {
909 XMoveWindow(Tk_Display(tkwin), GetWindowId(tkwin), x, y);
910 }
911
912 /*
913 *----------------------------------------------------------------------
914 *
915 * Blt_MapToplevel --
916 *
917 * Results:
918 * None.
919 *
920 *----------------------------------------------------------------------
921 */
922 void
Blt_MapToplevel(tkwin)923 Blt_MapToplevel(tkwin)
924 Tk_Window tkwin;
925 {
926 XMapWindow(Tk_Display(tkwin), GetWindowId(tkwin));
927 }
928
929 /*
930 *----------------------------------------------------------------------
931 *
932 * Blt_UnmapToplevel --
933 *
934 * Results:
935 * None.
936 *
937 *----------------------------------------------------------------------
938 */
939 void
Blt_UnmapToplevel(tkwin)940 Blt_UnmapToplevel(tkwin)
941 Tk_Window tkwin;
942 {
943 XUnmapWindow(Tk_Display(tkwin), GetWindowId(tkwin));
944 }
945
946 /* ARGSUSED */
947 static int
XReparentWindowErrorProc(clientData,errEventPtr)948 XReparentWindowErrorProc(clientData, errEventPtr)
949 ClientData clientData;
950 XErrorEvent *errEventPtr;
951 {
952 int *errorPtr = clientData;
953
954 *errorPtr = TCL_ERROR;
955 return 0;
956 }
957
958 int
Blt_ReparentWindow(display,window,newParent,x,y)959 Blt_ReparentWindow(display, window, newParent, x, y)
960 Display *display;
961 Window window, newParent;
962 int x, y;
963 {
964 Tk_ErrorHandler handler;
965 int result;
966 int any = -1;
967
968 result = TCL_OK;
969 handler = Tk_CreateErrorHandler(display, any, X_ReparentWindow, any,
970 XReparentWindowErrorProc, &result);
971 XReparentWindow(display, window, newParent, x, y);
972 Tk_DeleteErrorHandler(handler);
973 XSync(display, False);
974 return result;
975 }
976
977 #endif /* WIN32 */
978
979 #if (TK_MAJOR_VERSION == 4)
980 #include <bltHash.h>
981 static int initialized = FALSE;
982 static Blt_HashTable windowTable;
983
984 void
Blt_SetWindowInstanceData(tkwin,instanceData)985 Blt_SetWindowInstanceData(tkwin, instanceData)
986 Tk_Window tkwin;
987 ClientData instanceData;
988 {
989 Blt_HashEntry *hPtr;
990 int isNew;
991
992 if (!initialized) {
993 Blt_InitHashTable(&windowTable, BLT_ONE_WORD_KEYS);
994 initialized = TRUE;
995 }
996 hPtr = Blt_CreateHashEntry(&windowTable, (char *)tkwin, &isNew);
997 assert(isNew);
998 Blt_SetHashValue(hPtr, instanceData);
999 }
1000
1001 ClientData
Blt_GetWindowInstanceData(tkwin)1002 Blt_GetWindowInstanceData(tkwin)
1003 Tk_Window tkwin;
1004 {
1005 Blt_HashEntry *hPtr;
1006
1007 hPtr = Blt_FindHashEntry(&windowTable, (char *)tkwin);
1008 if (hPtr == NULL) {
1009 return NULL;
1010 }
1011 return Blt_GetHashValue(hPtr);
1012 }
1013
1014 void
Blt_DeleteWindowInstanceData(tkwin)1015 Blt_DeleteWindowInstanceData(tkwin)
1016 Tk_Window tkwin;
1017 {
1018 Blt_HashEntry *hPtr;
1019
1020 hPtr = Blt_FindHashEntry(&windowTable, (char *)tkwin);
1021 assert(hPtr);
1022 Blt_DeleteHashEntry(&windowTable, hPtr);
1023 }
1024
1025 #else
1026
1027 void
Blt_SetWindowInstanceData(tkwin,instanceData)1028 Blt_SetWindowInstanceData(tkwin, instanceData)
1029 Tk_Window tkwin;
1030 ClientData instanceData;
1031 {
1032 TkWindow *winPtr = (TkWindow *)tkwin;
1033
1034 winPtr->instanceData = instanceData;
1035 }
1036
1037 ClientData
Blt_GetWindowInstanceData(tkwin)1038 Blt_GetWindowInstanceData(tkwin)
1039 Tk_Window tkwin;
1040 {
1041 TkWindow *winPtr = (TkWindow *)tkwin;
1042
1043 return winPtr->instanceData;
1044 }
1045
1046 void
Blt_DeleteWindowInstanceData(tkwin)1047 Blt_DeleteWindowInstanceData(tkwin)
1048 Tk_Window tkwin;
1049 {
1050 }
1051
1052 #endif
1053
1054