OSDN Git Service

Please enter the commit message for your changes. Lines starting
[eos/base.git] / util / src / TclTk / tk8.6.12 / win / tkWinWindow.c
1 /*
2  * tkWinWindow.c --
3  *
4  *      Xlib emulation routines for Windows related to creating, displaying
5  *      and destroying windows.
6  *
7  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
8  *
9  * See the file "license.terms" for information on usage and redistribution of
10  * this file, and for a DISCLAIMER OF ALL WARRANTIES.
11  */
12
13 #include "tkWinInt.h"
14 #include "tkBusy.h"
15
16 typedef struct {
17     int initialized;            /* 0 means table below needs initializing. */
18     Tcl_HashTable windowTable;  /* The windowTable maps from HWND to Tk_Window
19                                  * handles. */
20 } ThreadSpecificData;
21 static Tcl_ThreadDataKey dataKey;
22
23 /*
24  * Forward declarations for functions defined in this file:
25  */
26
27 static void             NotifyVisibility(XEvent *eventPtr, TkWindow *winPtr);
28 \f
29 /*
30  *----------------------------------------------------------------------
31  *
32  * Tk_AttachHWND --
33  *
34  *      This function binds an HWND and a reflection function to the specified
35  *      Tk_Window.
36  *
37  * Results:
38  *      Returns an X Window that encapsulates the HWND.
39  *
40  * Side effects:
41  *      May allocate a new X Window. Also enters the HWND into the global
42  *      window table.
43  *
44  *----------------------------------------------------------------------
45  */
46
47 Window
48 Tk_AttachHWND(
49     Tk_Window tkwin,
50     HWND hwnd)
51 {
52     int new;
53     Tcl_HashEntry *entryPtr;
54     TkWinDrawable *twdPtr = (TkWinDrawable *) Tk_WindowId(tkwin);
55     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
56             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
57
58     if (!tsdPtr->initialized) {
59         Tcl_InitHashTable(&tsdPtr->windowTable, TCL_ONE_WORD_KEYS);
60         tsdPtr->initialized = 1;
61     }
62
63     /*
64      * Allocate a new drawable if necessary. Otherwise, remove the previous
65      * HWND from from the window table.
66      */
67
68     if (twdPtr == NULL) {
69         twdPtr = ckalloc(sizeof(TkWinDrawable));
70         twdPtr->type = TWD_WINDOW;
71         twdPtr->window.winPtr = (TkWindow *) tkwin;
72     } else if (twdPtr->window.handle != NULL) {
73         entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable,
74                 (char *)twdPtr->window.handle);
75         Tcl_DeleteHashEntry(entryPtr);
76     }
77
78     /*
79      * Insert the new HWND into the window table.
80      */
81
82     twdPtr->window.handle = hwnd;
83     entryPtr = Tcl_CreateHashEntry(&tsdPtr->windowTable, (char *)hwnd, &new);
84     Tcl_SetHashValue(entryPtr, tkwin);
85
86     return (Window)twdPtr;
87 }
88 \f
89 /*
90  *----------------------------------------------------------------------
91  *
92  * Tk_HWNDToWindow --
93  *
94  *      This function retrieves a Tk_Window from the window table given an
95  *      HWND.
96  *
97  * Results:
98  *      Returns the matching Tk_Window.
99  *
100  * Side effects:
101  *      None.
102  *
103  *----------------------------------------------------------------------
104  */
105
106 Tk_Window
107 Tk_HWNDToWindow(
108     HWND hwnd)
109 {
110     Tcl_HashEntry *entryPtr;
111     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
112             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
113
114     if (!tsdPtr->initialized) {
115         Tcl_InitHashTable(&tsdPtr->windowTable, TCL_ONE_WORD_KEYS);
116         tsdPtr->initialized = 1;
117     }
118     entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, (char *) hwnd);
119     if (entryPtr != NULL) {
120         return (Tk_Window) Tcl_GetHashValue(entryPtr);
121     }
122     return NULL;
123 }
124 \f
125 /*
126  *----------------------------------------------------------------------
127  *
128  * Tk_GetHWND --
129  *
130  *      This function extracts the HWND from an X Window.
131  *
132  * Results:
133  *      Returns the HWND associated with the Window.
134  *
135  * Side effects:
136  *      None.
137  *
138  *----------------------------------------------------------------------
139  */
140
141 HWND
142 Tk_GetHWND(
143     Window window)
144 {
145     return ((TkWinDrawable *) window)->window.handle;
146 }
147 \f
148 /*
149  *----------------------------------------------------------------------
150  *
151  * TkpPrintWindowId --
152  *
153  *      This routine stores the string representation of the platform
154  *      dependent window handle for an X Window in the given buffer.
155  *
156  * Results:
157  *      Returns the result in the specified buffer.
158  *
159  * Side effects:
160  *      None.
161  *
162  *----------------------------------------------------------------------
163  */
164
165 void
166 TkpPrintWindowId(
167     char *buf,                  /* Pointer to string large enough to hold the
168                                  * hex representation of a pointer. */
169     Window window)              /* Window to be printed into buffer. */
170 {
171     HWND hwnd = (window) ? Tk_GetHWND(window) : 0;
172
173     sprintf(buf, "0x%" TCL_Z_MODIFIER "x", (size_t)hwnd);
174 }
175 \f
176 /*
177  *----------------------------------------------------------------------
178  *
179  * TkpScanWindowId --
180  *
181  *      Given a string which represents the platform dependent window handle,
182  *      produce the X Window id for the window.
183  *
184  * Results:
185  *      The return value is normally TCL_OK; in this case *idPtr will be set
186  *      to the X Window id equivalent to string. If string is improperly
187  *      formed then TCL_ERROR is returned and an error message will be left in
188  *      the interp's result. If the number does not correspond to a Tk Window,
189  *      then *idPtr will be set to None.
190  *
191  * Side effects:
192  *      None.
193  *
194  *----------------------------------------------------------------------
195  */
196
197 int
198 TkpScanWindowId(
199     Tcl_Interp *interp,         /* Interpreter to use for error reporting. */
200     const char *string,         /* String containing a (possibly signed)
201                                  * integer in a form acceptable to strtol. */
202     Window *idPtr)              /* Place to store converted result. */
203 {
204     Tk_Window tkwin;
205     union {
206         HWND hwnd;
207         int number;
208     } win;
209
210     /*
211      * We want sscanf for the 64-bit check, but if that doesn't work, then
212      * Tcl_GetInt manages the error correctly.
213      */
214
215     if (
216 #ifdef _WIN64
217             (sscanf(string, "0x%p", &win.hwnd) != 1) &&
218 #endif
219             Tcl_GetInt(interp, string, &win.number) != TCL_OK) {
220         return TCL_ERROR;
221     }
222
223     tkwin = Tk_HWNDToWindow(win.hwnd);
224     if (tkwin) {
225         *idPtr = Tk_WindowId(tkwin);
226     } else {
227         *idPtr = None;
228     }
229     return TCL_OK;
230 }
231 \f
232 /*
233  *----------------------------------------------------------------------
234  *
235  * TkpMakeWindow --
236  *
237  *      Creates a Windows window object based on the current attributes of the
238  *      specified TkWindow.
239  *
240  * Results:
241  *      Returns a pointer to a new TkWinDrawable cast to a Window.
242  *
243  * Side effects:
244  *      Creates a new window.
245  *
246  *----------------------------------------------------------------------
247  */
248
249 Window
250 TkpMakeWindow(
251     TkWindow *winPtr,
252     Window parent)
253 {
254     HWND parentWin;
255     int style;
256     HWND hwnd;
257
258     if (parent != None) {
259         parentWin = Tk_GetHWND(parent);
260         style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
261     } else {
262         parentWin = NULL;
263         style = WS_POPUP | WS_CLIPCHILDREN;
264     }
265
266     /*
267      * Create the window, then ensure that it is at the top of the stacking
268      * order.
269      */
270
271     hwnd = CreateWindowExW(WS_EX_NOPARENTNOTIFY, TK_WIN_CHILD_CLASS_NAME, NULL,
272             (DWORD) style, Tk_X(winPtr), Tk_Y(winPtr), Tk_Width(winPtr),
273             Tk_Height(winPtr), parentWin, NULL, Tk_GetHINSTANCE(), NULL);
274     SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
275             SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
276     return Tk_AttachHWND((Tk_Window)winPtr, hwnd);
277 }
278 \f
279 /*
280  *----------------------------------------------------------------------
281  *
282  * XDestroyWindow --
283  *
284  *      Destroys the given window.
285  *
286  * Results:
287  *      None.
288  *
289  * Side effects:
290  *      Sends the WM_DESTROY message to the window and then destroys it the
291  *      Win32 resources associated with the window.
292  *
293  *----------------------------------------------------------------------
294  */
295
296 int
297 XDestroyWindow(
298     Display *display,
299     Window w)
300 {
301     Tcl_HashEntry *entryPtr;
302     TkWinDrawable *twdPtr = (TkWinDrawable *)w;
303     TkWindow *winPtr = TkWinGetWinPtr(w);
304     HWND hwnd = Tk_GetHWND(w);
305     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
306             Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
307
308     display->request++;
309
310     /*
311      * Remove references to the window in the pointer module then release the
312      * drawable.
313      */
314
315     TkPointerDeadWindow(winPtr);
316
317     entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, (char*)hwnd);
318     if (entryPtr != NULL) {
319         Tcl_DeleteHashEntry(entryPtr);
320     }
321
322     ckfree(twdPtr);
323
324     /*
325      * Don't bother destroying the window if we are going to destroy the
326      * parent later.
327      */
328
329     if (hwnd != NULL && !(winPtr->flags & TK_DONT_DESTROY_WINDOW)) {
330         DestroyWindow(hwnd);
331     }
332     return Success;
333 }
334 \f
335 /*
336  *----------------------------------------------------------------------
337  *
338  * XMapWindow --
339  *
340  *      Cause the given window to become visible.
341  *
342  * Results:
343  *      None
344  *
345  * Side effects:
346  *      Causes the window state to change, and generates a MapNotify event.
347  *
348  *----------------------------------------------------------------------
349  */
350
351 int
352 XMapWindow(
353     Display *display,
354     Window w)
355 {
356     XEvent event;
357     TkWindow *parentPtr;
358     TkWindow *winPtr = TkWinGetWinPtr(w);
359
360     display->request++;
361
362     ShowWindow(Tk_GetHWND(w), SW_SHOWNORMAL);
363     winPtr->flags |= TK_MAPPED;
364
365     /*
366      * Check to see if this window is visible now. If all of the parent
367      * windows up to the first toplevel are mapped, then this window and its
368      * mapped children have just become visible.
369      */
370
371     if (!(winPtr->flags & TK_TOP_HIERARCHY)) {
372         for (parentPtr = winPtr->parentPtr; ;
373                 parentPtr = parentPtr->parentPtr) {
374             if ((parentPtr == NULL) || !(parentPtr->flags & TK_MAPPED)) {
375                 return Success;
376             }
377             if (parentPtr->flags & TK_TOP_HIERARCHY) {
378                 break;
379             }
380         }
381     } else {
382         event.type = MapNotify;
383         event.xmap.serial = display->request;
384         event.xmap.send_event = False;
385         event.xmap.display = display;
386         event.xmap.event = winPtr->window;
387         event.xmap.window = winPtr->window;
388         event.xmap.override_redirect = winPtr->atts.override_redirect;
389         Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
390     }
391
392     /*
393      * Generate VisibilityNotify events for this window and its mapped
394      * children.
395      */
396
397     event.type = VisibilityNotify;
398     event.xvisibility.serial = display->request;
399     event.xvisibility.send_event = False;
400     event.xvisibility.display = display;
401     event.xvisibility.window = winPtr->window;
402     event.xvisibility.state = VisibilityUnobscured;
403     NotifyVisibility(&event, winPtr);
404     return Success;
405 }
406 \f
407 /*
408  *----------------------------------------------------------------------
409  *
410  * NotifyVisibility --
411  *
412  *      This function recursively notifies the mapped children of the
413  *      specified window of a change in visibility. Note that we don't
414  *      properly report the visibility state, since Windows does not provide
415  *      that info. The eventPtr argument must point to an event that has been
416  *      completely initialized except for the window slot.
417  *
418  * Results:
419  *      None.
420  *
421  * Side effects:
422  *      Generates lots of events.
423  *
424  *----------------------------------------------------------------------
425  */
426
427 static void
428 NotifyVisibility(
429     XEvent *eventPtr,           /* Initialized VisibilityNotify event. */
430     TkWindow *winPtr)           /* Window to notify. */
431 {
432     if (winPtr->atts.event_mask & VisibilityChangeMask) {
433         eventPtr->xvisibility.window = winPtr->window;
434         Tk_QueueWindowEvent(eventPtr, TCL_QUEUE_TAIL);
435     }
436     for (winPtr = winPtr->childList; winPtr != NULL;
437             winPtr = winPtr->nextPtr) {
438         if (winPtr->flags & TK_MAPPED) {
439             NotifyVisibility(eventPtr, winPtr);
440         }
441     }
442 }
443 \f
444 /*
445  *----------------------------------------------------------------------
446  *
447  * XUnmapWindow --
448  *
449  *      Cause the given window to become invisible.
450  *
451  * Results:
452  *      None
453  *
454  * Side effects:
455  *      Causes the window state to change, and generates an UnmapNotify event.
456  *
457  *----------------------------------------------------------------------
458  */
459
460 int
461 XUnmapWindow(
462     Display *display,
463     Window w)
464 {
465     XEvent event;
466     TkWindow *winPtr = TkWinGetWinPtr(w);
467
468     display->request++;
469
470     /*
471      * Bug fix: Don't short circuit this routine based on TK_MAPPED because it
472      * will be cleared before XUnmapWindow is called.
473      */
474
475     ShowWindow(Tk_GetHWND(w), SW_HIDE);
476     winPtr->flags &= ~TK_MAPPED;
477
478     if (winPtr->flags & TK_WIN_MANAGED) {
479         event.type = UnmapNotify;
480         event.xunmap.serial = display->request;
481         event.xunmap.send_event = False;
482         event.xunmap.display = display;
483         event.xunmap.event = winPtr->window;
484         event.xunmap.window = winPtr->window;
485         event.xunmap.from_configure = False;
486         Tk_HandleEvent(&event);
487     }
488     return Success;
489 }
490 \f
491 /*
492  *----------------------------------------------------------------------
493  *
494  * XMoveResizeWindow --
495  *
496  *      Move and resize a window relative to its parent.
497  *
498  * Results:
499  *      None.
500  *
501  * Side effects:
502  *      Repositions and resizes the specified window.
503  *
504  *----------------------------------------------------------------------
505  */
506
507 int
508 XMoveResizeWindow(
509     Display *display,
510     Window w,
511     int x, int y,               /* Position relative to parent. */
512     unsigned int width, unsigned int height)
513 {
514     display->request++;
515     MoveWindow(Tk_GetHWND(w), x, y, (int) width, (int) height, TRUE);
516     return Success;
517 }
518 \f
519 /*
520  *----------------------------------------------------------------------
521  *
522  * XMoveWindow --
523  *
524  *      Move a window relative to its parent.
525  *
526  * Results:
527  *      None.
528  *
529  * Side effects:
530  *      Repositions the specified window.
531  *
532  *----------------------------------------------------------------------
533  */
534
535 int
536 XMoveWindow(
537     Display *display,
538     Window w,
539     int x, int y)               /* Position relative to parent */
540 {
541     TkWindow *winPtr = TkWinGetWinPtr(w);
542
543     display->request++;
544
545     MoveWindow(Tk_GetHWND(w), x, y, winPtr->changes.width,
546             winPtr->changes.height, TRUE);
547     return Success;
548 }
549 \f
550 /*
551  *----------------------------------------------------------------------
552  *
553  * XResizeWindow --
554  *
555  *      Resize a window.
556  *
557  * Results:
558  *      None.
559  *
560  * Side effects:
561  *      Resizes the specified window.
562  *
563  *----------------------------------------------------------------------
564  */
565
566 int
567 XResizeWindow(
568     Display *display,
569     Window w,
570     unsigned int width, unsigned int height)
571 {
572     TkWindow *winPtr = TkWinGetWinPtr(w);
573
574     display->request++;
575
576     MoveWindow(Tk_GetHWND(w), winPtr->changes.x, winPtr->changes.y, (int)width,
577             (int)height, TRUE);
578     return Success;
579 }
580 \f
581 /*
582  *----------------------------------------------------------------------
583  *
584  * XRaiseWindow, XLowerWindow --
585  *
586  *      Change the stacking order of a window.
587  *
588  * Results:
589  *      None.
590  *
591  * Side effects:
592  *      Changes the stacking order of the specified window.
593  *
594  *----------------------------------------------------------------------
595  */
596
597 int
598 XRaiseWindow(
599     Display *display,
600     Window w)
601 {
602     HWND window = Tk_GetHWND(w);
603
604     display->request++;
605     SetWindowPos(window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
606     return Success;
607 }
608
609 int
610 XLowerWindow(
611     Display *display,
612     Window w)
613 {
614     HWND window = Tk_GetHWND(w);
615
616     display->request++;
617     SetWindowPos(window, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
618     return Success;
619 }
620 \f
621 /*
622  *----------------------------------------------------------------------
623  *
624  * XConfigureWindow --
625  *
626  *      Change the size, position, stacking, or border of the specified
627  *      window.
628  *
629  * Results:
630  *      None.
631  *
632  * Side effects:
633  *      Changes the attributes of the specified window. Note that we ignore
634  *      the passed in values and use the values stored in the TkWindow data
635  *      structure.
636  *
637  *----------------------------------------------------------------------
638  */
639
640 int
641 XConfigureWindow(
642     Display *display,
643     Window w,
644     unsigned int valueMask,
645     XWindowChanges *values)
646 {
647     TkWindow *winPtr = TkWinGetWinPtr(w);
648     HWND hwnd = Tk_GetHWND(w);
649
650     display->request++;
651
652     /*
653      * Change the shape and/or position of the window.
654      */
655
656     if (valueMask & (CWX|CWY|CWWidth|CWHeight)) {
657         MoveWindow(hwnd, winPtr->changes.x, winPtr->changes.y,
658                 winPtr->changes.width, winPtr->changes.height, TRUE);
659     }
660
661     /*
662      * Change the stacking order of the window.
663      */
664
665     if (valueMask & CWStackMode) {
666         HWND sibling;
667
668         if ((valueMask & CWSibling) && (values->sibling != None)) {
669             sibling = Tk_GetHWND(values->sibling);
670         } else {
671             sibling = NULL;
672         }
673         TkWinSetWindowPos(hwnd, sibling, values->stack_mode);
674     }
675     return Success;
676 }
677 \f
678 /*
679  *----------------------------------------------------------------------
680  *
681  * XClearWindow --
682  *
683  *      Clears the entire window to the current background color.
684  *
685  * Results:
686  *      None.
687  *
688  * Side effects:
689  *      Erases the current contents of the window.
690  *
691  *----------------------------------------------------------------------
692  */
693
694 int
695 XClearWindow(
696     Display *display,
697     Window w)
698 {
699     RECT rc;
700     HBRUSH brush;
701     HPALETTE oldPalette, palette;
702     TkWindow *winPtr;
703     HWND hwnd = Tk_GetHWND(w);
704     HDC dc = GetDC(hwnd);
705
706     palette = TkWinGetPalette(display->screens[0].cmap);
707     oldPalette = SelectPalette(dc, palette, FALSE);
708
709     display->request++;
710
711     winPtr = TkWinGetWinPtr(w);
712     brush = CreateSolidBrush(winPtr->atts.background_pixel);
713     GetWindowRect(hwnd, &rc);
714     rc.right = rc.right - rc.left;
715     rc.bottom = rc.bottom - rc.top;
716     rc.left = rc.top = 0;
717     FillRect(dc, &rc, brush);
718
719     DeleteObject(brush);
720     SelectPalette(dc, oldPalette, TRUE);
721     ReleaseDC(hwnd, dc);
722     return Success;
723 }
724 \f
725 /*
726  *----------------------------------------------------------------------
727  *
728  * XChangeWindowAttributes --
729  *
730  *      This function is called when the attributes on a window are updated.
731  *      Since Tk maintains all of the window state, the only relevant value is
732  *      the cursor.
733  *
734  * Results:
735  *      None.
736  *
737  * Side effects:
738  *      May cause the mouse position to be updated.
739  *
740  *----------------------------------------------------------------------
741  */
742
743 int
744 XChangeWindowAttributes(
745     Display *display,
746     Window w,
747     unsigned long valueMask,
748     XSetWindowAttributes* attributes)
749 {
750     if (valueMask & CWCursor) {
751         XDefineCursor(display, w, attributes->cursor);
752     }
753     return Success;
754 }
755 \f
756 /*
757  *----------------------------------------------------------------------
758  *
759  * XReparentWindow --
760  *
761  *      TODO: currently placeholder to satisfy Xlib stubs.
762  *
763  * Results:
764  *      None.
765  *
766  * Side effects:
767  *      TODO.
768  *
769  *----------------------------------------------------------------------
770  */
771
772 int
773 XReparentWindow(
774     Display *display,
775     Window w,
776     Window parent,
777     int x,
778     int y)
779 {
780     return BadWindow;
781 }
782 \f
783 /*
784  *----------------------------------------------------------------------
785  *
786  * TkWinSetWindowPos --
787  *
788  *      Adjust the stacking order of a window relative to a second window (or
789  *      NULL).
790  *
791  * Results:
792  *      None.
793  *
794  * Side effects:
795  *      Moves the specified window in the stacking order.
796  *
797  *----------------------------------------------------------------------
798  */
799
800 void
801 TkWinSetWindowPos(
802     HWND hwnd,                  /* Window to restack. */
803     HWND siblingHwnd,           /* Sibling window. */
804     int pos)                    /* One of Above or Below. */
805 {
806     HWND temp;
807
808     /*
809      * Since Windows does not support Above mode, we place the specified
810      * window below the sibling and then swap them.
811      */
812
813     if (siblingHwnd) {
814         if (pos == Above) {
815             SetWindowPos(hwnd, siblingHwnd, 0, 0, 0, 0,
816                     SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
817             temp = hwnd;
818             hwnd = siblingHwnd;
819             siblingHwnd = temp;
820         }
821     } else {
822         siblingHwnd = (pos == Above) ? HWND_TOP : HWND_BOTTOM;
823     }
824
825     SetWindowPos(hwnd, siblingHwnd, 0, 0, 0, 0,
826             SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
827 }
828 \f
829 /*
830  *----------------------------------------------------------------------
831  *
832  * TkpShowBusyWindow --
833  *
834  *      Makes a busy window "appear".
835  *
836  * Results:
837  *      None.
838  *
839  * Side effects:
840  *      Arranges for the busy window to start intercepting events and the
841  *      cursor to change to the configured "hey, I'm busy!" setting.
842  *
843  *----------------------------------------------------------------------
844  */
845
846 void
847 TkpShowBusyWindow(
848     TkBusy busy)
849 {
850     Busy *busyPtr = (Busy *) busy;
851     HWND hWnd;
852     POINT point;
853     Display *display;
854     Window window;
855
856     if (busyPtr->tkBusy != NULL) {
857         Tk_MapWindow(busyPtr->tkBusy);
858         window = Tk_WindowId(busyPtr->tkBusy);
859         display = Tk_Display(busyPtr->tkBusy);
860         hWnd = Tk_GetHWND(window);
861         display->request++;
862         SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
863     }
864
865     /*
866      * Under Win32, cursors aren't associated with windows. Tk fakes this by
867      * watching Motion events on its windows. So Tk will automatically change
868      * the cursor when the pointer enters the Busy window. But Windows does
869      * not immediately change the cursor; it waits for the cursor position to
870      * change or a system call. We need to change the cursor before the
871      * application starts processing, so set the cursor position redundantly
872      * back to the current position.
873      */
874
875     GetCursorPos(&point);
876     TkSetCursorPos(point.x, point.y);
877 }
878 \f
879 /*
880  *----------------------------------------------------------------------
881  *
882  * TkpHideBusyWindow --
883  *
884  *      Makes a busy window "disappear".
885  *
886  * Results:
887  *      None.
888  *
889  * Side effects:
890  *      Arranges for the busy window to stop intercepting events, and the
891  *      cursor to change back to its normal setting.
892  *
893  *----------------------------------------------------------------------
894  */
895
896 void
897 TkpHideBusyWindow(
898     TkBusy busy)
899 {
900     Busy *busyPtr = (Busy *) busy;
901     POINT point;
902
903     if (busyPtr->tkBusy != NULL) {
904         Tk_UnmapWindow(busyPtr->tkBusy);
905     }
906
907     /*
908      * Under Win32, cursors aren't associated with windows. Tk fakes this by
909      * watching Motion events on its windows. So Tk will automatically change
910      * the cursor when the pointer enters the Busy window. But Windows does
911      * not immediately change the cursor: it waits for the cursor position to
912      * change or a system call. We need to change the cursor before the
913      * application starts processing, so set the cursor position redundantly
914      * back to the current position.
915      */
916
917     GetCursorPos(&point);
918     TkSetCursorPos(point.x, point.y);
919 }
920 \f
921 /*
922  *----------------------------------------------------------------------
923  *
924  * TkpMakeTransparentWindowExist --
925  *
926  *      Construct the platform-specific resources for a transparent window.
927  *
928  * Results:
929  *      None.
930  *
931  * Side effects:
932  *      Moves the specified window in the stacking order.
933  *
934  *----------------------------------------------------------------------
935  */
936
937 void
938 TkpMakeTransparentWindowExist(
939     Tk_Window tkwin,            /* Token for window. */
940     Window parent)              /* Parent window. */
941 {
942     TkWindow *winPtr = (TkWindow *) tkwin;
943     HWND hParent = (HWND) parent, hWnd;
944     int style = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
945     DWORD exStyle = WS_EX_TRANSPARENT | WS_EX_TOPMOST;
946
947     hWnd = CreateWindowExW(exStyle, TK_WIN_CHILD_CLASS_NAME, NULL, style,
948             Tk_X(tkwin), Tk_Y(tkwin), Tk_Width(tkwin), Tk_Height(tkwin),
949             hParent, NULL, Tk_GetHINSTANCE(), NULL);
950     winPtr->window = Tk_AttachHWND(tkwin, hWnd);
951 }
952 \f
953 /*
954  *----------------------------------------------------------------------
955  *
956  * TkpCreateBusy --
957  *
958  *      Construct the platform-specific parts of a busy window. Note that this
959  *      postpones the actual creation of the window resource until later.
960  *
961  * Results:
962  *      None.
963  *
964  * Side effects:
965  *      Sets up part of the busy window structure.
966  *
967  *----------------------------------------------------------------------
968  */
969
970 void
971 TkpCreateBusy(
972     Tk_FakeWin *winPtr,
973     Tk_Window tkRef,
974     Window *parentPtr,
975     Tk_Window tkParent,
976     TkBusy busy)
977 {
978     Busy *busyPtr = (Busy *) busy;
979
980     if (winPtr->flags & TK_REPARENTED) {
981         /*
982          * This works around a bug in the implementation of menubars for
983          * non-Macintosh window systems (Win32 and X11). Tk doesn't reset the
984          * pointers to the parent window when the menu is reparented
985          * (winPtr->parentPtr points to the wrong window). We get around this
986          * by determining the parent via the native API calls.
987          */
988
989         HWND hWnd = GetParent(Tk_GetHWND(Tk_WindowId(tkRef)));
990         RECT rect;
991
992         if (GetWindowRect(hWnd, &rect)) {
993             busyPtr->width = rect.right - rect.left;
994             busyPtr->height = rect.bottom - rect.top;
995         }
996     } else {
997         *parentPtr = Tk_WindowId(tkParent);
998         *parentPtr = (Window) Tk_GetHWND(*parentPtr);
999     }
1000 }
1001 \f
1002 /*
1003  * Local Variables:
1004  * mode: c
1005  * c-basic-offset: 4
1006  * fill-column: 78
1007  * End:
1008  */