/[dtapublic]/projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkwinx.c
ViewVC logotype

Annotation of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkwinx.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 25 - (hide annotations) (download)
Sat Oct 8 06:43:03 2016 UTC (7 years, 9 months ago) by dashley
Original Path: sf_code/esrgpcpj/shared/tk_base/tkwinx.c
File MIME type: text/plain
File size: 32044 byte(s)
Initial commit.
1 dashley 25 /* $Header: /IjuScripter, IjuConsole/Source/Tk Base/tkWinX.c 1 1/02/01 3:18a Dtashley $ */
2    
3     /*
4     * tkWinX.c --
5     *
6     * This file contains Windows emulation procedures for X routines.
7     *
8     * Copyright (c) 1995-1996 Sun Microsystems, Inc.
9     * Copyright (c) 1994 Software Research Associates, Inc.
10     * Copyright (c) 1998-2000 by Scriptics Corporation.
11     *
12     * See the file "license.terms" for information on usage and redistribution
13     * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14     *
15     * RCS: @(#) $Id: tkWinX.c,v 1.10 2000/04/19 01:06:51 ericm Exp $
16     */
17    
18     #include "tkWinInt.h"
19    
20     /*
21     * The zmouse.h file includes the definition for WM_MOUSEWHEEL.
22     */
23    
24     #include <zmouse.h>
25    
26     /*
27     * Declarations of static variables used in this file.
28     */
29    
30     static char winScreenName[] = ":0"; /* Default name of windows display. */
31     static HINSTANCE tkInstance; /* Application instance handle. */
32     static int childClassInitialized; /* Registered child class? */
33     static WNDCLASS childClass; /* Window class for child windows. */
34     static int tkPlatformId; /* version of Windows platform */
35    
36     TCL_DECLARE_MUTEX(winXMutex)
37    
38     /*
39     * Thread local storage. Notice that now each thread must have its
40     * own TkDisplay structure, since this structure contains most of
41     * the thread-specific date for threads.
42     */
43     typedef struct ThreadSpecificData {
44     TkDisplay *winDisplay; /* TkDisplay structure that *
45     * represents Windows screen. */
46     int updatingClipboard; /* If 1, we are updating the clipboard */
47     } ThreadSpecificData;
48     static Tcl_ThreadDataKey dataKey;
49    
50     /*
51     * Forward declarations of procedures used in this file.
52     */
53    
54     static void GenerateXEvent _ANSI_ARGS_((HWND hwnd, UINT message,
55     WPARAM wParam, LPARAM lParam));
56     static unsigned int GetState _ANSI_ARGS_((UINT message, WPARAM wParam,
57     LPARAM lParam));
58     static void GetTranslatedKey _ANSI_ARGS_((XKeyEvent *xkey));
59    
60     /*
61     *----------------------------------------------------------------------
62     *
63     * TkGetServerInfo --
64     *
65     * Given a window, this procedure returns information about
66     * the window server for that window. This procedure provides
67     * the guts of the "winfo server" command.
68     *
69     * Results:
70     * None.
71     *
72     * Side effects:
73     * None.
74     *
75     *----------------------------------------------------------------------
76     */
77    
78     void
79     TkGetServerInfo(interp, tkwin)
80     Tcl_Interp *interp; /* The server information is returned in
81     * this interpreter's result. */
82     Tk_Window tkwin; /* Token for window; this selects a
83     * particular display and server. */
84     {
85     char buffer[60];
86     OSVERSIONINFO os;
87    
88     os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
89     GetVersionEx(&os);
90     sprintf(buffer, "Windows %d.%d %d Win32", os.dwMajorVersion,
91     os.dwMinorVersion, os.dwBuildNumber);
92     Tcl_SetResult(interp, buffer, TCL_VOLATILE);
93     }
94    
95     /*
96     *----------------------------------------------------------------------
97     *
98     * Tk_GetHINSTANCE --
99     *
100     * Retrieves the global instance handle used by the Tk library.
101     *
102     * Results:
103     * Returns the global instance handle.
104     *
105     * Side effects:
106     * None.
107     *
108     *----------------------------------------------------------------------
109     */
110    
111     HINSTANCE
112     Tk_GetHINSTANCE()
113     {
114     return tkInstance;
115     }
116    
117     /*
118     *----------------------------------------------------------------------
119     *
120     * TkWinXInit --
121     *
122     * Initialize Xlib emulation layer.
123     *
124     * Results:
125     * None.
126     *
127     * Side effects:
128     * Sets up various data structures.
129     *
130     *----------------------------------------------------------------------
131     */
132    
133     void
134     TkWinXInit(hInstance)
135     HINSTANCE hInstance;
136     {
137     OSVERSIONINFO os;
138    
139     if (childClassInitialized != 0) {
140     return;
141     }
142     childClassInitialized = 1;
143    
144     tkInstance = hInstance;
145    
146     os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
147     GetVersionEx(&os);
148     tkPlatformId = os.dwPlatformId;
149    
150     /*
151     * When threads are enabled, we cannot use CLASSDC because
152     * threads will then write into the same device context.
153     *
154     * This is a hack; we should add a subsystem that manages
155     * device context on a per-thread basis. See also tkWinWm.c,
156     * which also initializes a WNDCLASS structure.
157     */
158    
159     #ifdef TCL_THREADS
160     childClass.style = CS_HREDRAW | CS_VREDRAW;
161     #else
162     childClass.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC;
163     #endif
164    
165     childClass.cbClsExtra = 0;
166     childClass.cbWndExtra = 0;
167     childClass.hInstance = hInstance;
168     childClass.hbrBackground = NULL;
169     childClass.lpszMenuName = NULL;
170    
171     /*
172     * Register the Child window class.
173     */
174    
175     childClass.lpszClassName = TK_WIN_CHILD_CLASS_NAME;
176     childClass.lpfnWndProc = TkWinChildProc;
177     childClass.hIcon = NULL;
178     childClass.hCursor = NULL;
179    
180     if (!RegisterClass(&childClass)) {
181     panic("Unable to register TkChild class");
182     }
183     }
184    
185     /*
186     *----------------------------------------------------------------------
187     *
188     * TkWinXCleanup --
189     *
190     * Removes the registered classes for Tk.
191     *
192     * Results:
193     * None.
194     *
195     * Side effects:
196     * Removes window classes from the system.
197     *
198     *----------------------------------------------------------------------
199     */
200    
201     void
202     TkWinXCleanup(hInstance)
203     HINSTANCE hInstance;
204     {
205     /*
206     * Clean up our own class.
207     */
208    
209     if (childClassInitialized) {
210     childClassInitialized = 0;
211     UnregisterClass(TK_WIN_CHILD_CLASS_NAME, hInstance);
212     }
213    
214     /*
215     * And let the window manager clean up its own class(es).
216     */
217    
218     TkWinWmCleanup(hInstance);
219     }
220    
221     /*
222     *----------------------------------------------------------------------
223     *
224     * TkWinGetPlatformId --
225     *
226     * Determines whether running under NT, 95, or Win32s, to allow
227     * runtime conditional code.
228     *
229     * Results:
230     * The return value is one of:
231     * VER_PLATFORM_WIN32s Win32s on Windows 3.1.
232     * VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95.
233     * VER_PLATFORM_WIN32_NT Win32 on Windows NT
234     *
235     * Side effects:
236     * None.
237     *
238     *----------------------------------------------------------------------
239     */
240    
241     int
242     TkWinGetPlatformId()
243     {
244     return tkPlatformId;
245     }
246    
247     /*
248     *----------------------------------------------------------------------
249     *
250     * TkGetDefaultScreenName --
251     *
252     * Returns the name of the screen that Tk should use during
253     * initialization.
254     *
255     * Results:
256     * Returns a statically allocated string.
257     *
258     * Side effects:
259     * None.
260     *
261     *----------------------------------------------------------------------
262     */
263    
264     char *
265     TkGetDefaultScreenName(interp, screenName)
266     Tcl_Interp *interp; /* Not used. */
267     char *screenName; /* If NULL, use default string. */
268     {
269     if ((screenName == NULL) || (screenName[0] == '\0')) {
270     screenName = winScreenName;
271     }
272     return screenName;
273     }
274    
275     /*
276     *----------------------------------------------------------------------
277     *
278     * TkpOpenDisplay --
279     *
280     * Create the Display structure and fill it with device
281     * specific information.
282     *
283     * Results:
284     * Returns a TkDisplay structure on success or NULL on failure.
285     *
286     * Side effects:
287     * Allocates a new TkDisplay structure.
288     *
289     *----------------------------------------------------------------------
290     */
291    
292     TkDisplay *
293     TkpOpenDisplay(display_name)
294     char *display_name;
295     {
296     Screen *screen;
297     HDC dc;
298     TkWinDrawable *twdPtr;
299     Display *display;
300     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
301     Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
302    
303     if (tsdPtr->winDisplay != NULL) {
304     if (strcmp(tsdPtr->winDisplay->display->display_name, display_name)
305     == 0) {
306     return tsdPtr->winDisplay;
307     } else {
308     return NULL;
309     }
310     }
311    
312     display = (Display *) ckalloc(sizeof(Display));
313     display->display_name = (char *) ckalloc(strlen(display_name)+1);
314     strcpy(display->display_name, display_name);
315    
316     display->cursor_font = 1;
317     display->nscreens = 1;
318     display->request = 1;
319     display->qlen = 0;
320    
321     screen = (Screen *) ckalloc(sizeof(Screen));
322     screen->display = display;
323    
324     dc = GetDC(NULL);
325     screen->width = GetDeviceCaps(dc, HORZRES);
326     screen->height = GetDeviceCaps(dc, VERTRES);
327     screen->mwidth = MulDiv(screen->width, 254,
328     GetDeviceCaps(dc, LOGPIXELSX) * 10);
329     screen->mheight = MulDiv(screen->height, 254,
330     GetDeviceCaps(dc, LOGPIXELSY) * 10);
331    
332     /*
333     * Set up the root window.
334     */
335    
336     twdPtr = (TkWinDrawable*) ckalloc(sizeof(TkWinDrawable));
337     if (twdPtr == NULL) {
338     return None;
339     }
340     twdPtr->type = TWD_WINDOW;
341     twdPtr->window.winPtr = NULL;
342     twdPtr->window.handle = NULL;
343     screen->root = (Window)twdPtr;
344    
345     /*
346     * On windows, when creating a color bitmap, need two pieces of
347     * information: the number of color planes and the number of
348     * pixels per plane. Need to remember both quantities so that
349     * when constructing an HBITMAP for offscreen rendering, we can
350     * specify the correct value for the number of planes. Otherwise
351     * the HBITMAP won't be compatible with the HWND and we'll just
352     * get blank spots copied onto the screen.
353     */
354    
355     screen->ext_data = (XExtData *) GetDeviceCaps(dc, PLANES);
356     screen->root_depth = GetDeviceCaps(dc, BITSPIXEL) * (int) screen->ext_data;
357    
358     screen->root_visual = (Visual *) ckalloc(sizeof(Visual));
359     screen->root_visual->visualid = 0;
360     if (GetDeviceCaps(dc, RASTERCAPS) & RC_PALETTE) {
361     screen->root_visual->map_entries = GetDeviceCaps(dc, SIZEPALETTE);
362     screen->root_visual->class = PseudoColor;
363     screen->root_visual->red_mask = 0x0;
364     screen->root_visual->green_mask = 0x0;
365     screen->root_visual->blue_mask = 0x0;
366     } else {
367     if (screen->root_depth == 4) {
368     screen->root_visual->class = StaticColor;
369     screen->root_visual->map_entries = 16;
370     } else if (screen->root_depth == 8) {
371     screen->root_visual->class = StaticColor;
372     screen->root_visual->map_entries = 256;
373     } else if (screen->root_depth == 12) {
374     screen->root_visual->class = TrueColor;
375     screen->root_visual->map_entries = 32;
376     screen->root_visual->red_mask = 0xf0;
377     screen->root_visual->green_mask = 0xf000;
378     screen->root_visual->blue_mask = 0xf00000;
379     } else if (screen->root_depth == 16) {
380     screen->root_visual->class = TrueColor;
381     screen->root_visual->map_entries = 64;
382     screen->root_visual->red_mask = 0xf8;
383     screen->root_visual->green_mask = 0xfc00;
384     screen->root_visual->blue_mask = 0xf80000;
385     } else if (screen->root_depth >= 24) {
386     screen->root_visual->class = TrueColor;
387     screen->root_visual->map_entries = 256;
388     screen->root_visual->red_mask = 0xff;
389     screen->root_visual->green_mask = 0xff00;
390     screen->root_visual->blue_mask = 0xff0000;
391     }
392     }
393     screen->root_visual->bits_per_rgb = screen->root_depth;
394     ReleaseDC(NULL, dc);
395    
396     /*
397     * Note that these pixel values are not palette relative.
398     */
399    
400     screen->white_pixel = RGB(255, 255, 255);
401     screen->black_pixel = RGB(0, 0, 0);
402    
403     display->screens = screen;
404     display->nscreens = 1;
405     display->default_screen = 0;
406     screen->cmap = XCreateColormap(display, None, screen->root_visual,
407     AllocNone);
408     tsdPtr->winDisplay = (TkDisplay *) ckalloc(sizeof(TkDisplay));
409     tsdPtr->winDisplay->display = display;
410     tsdPtr->updatingClipboard = FALSE;
411     return tsdPtr->winDisplay;
412     }
413    
414     /*
415     *----------------------------------------------------------------------
416     *
417     * TkpCloseDisplay --
418     *
419     * Closes and deallocates a Display structure created with the
420     * TkpOpenDisplay function.
421     *
422     * Results:
423     * None.
424     *
425     * Side effects:
426     * Frees up memory.
427     *
428     *----------------------------------------------------------------------
429     */
430    
431     void
432     TkpCloseDisplay(dispPtr)
433     TkDisplay *dispPtr;
434     {
435     Display *display = dispPtr->display;
436     HWND hwnd;
437     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
438     Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
439    
440     if (dispPtr != tsdPtr->winDisplay) {
441     panic("TkpCloseDisplay: tried to call TkpCloseDisplay on another display");
442     return;
443     }
444    
445     /*
446     * Force the clipboard to be rendered if we are the clipboard owner.
447     */
448    
449     if (dispPtr->clipWindow) {
450     hwnd = Tk_GetHWND(Tk_WindowId(dispPtr->clipWindow));
451     if (GetClipboardOwner() == hwnd) {
452     OpenClipboard(hwnd);
453     EmptyClipboard();
454     TkWinClipboardRender(dispPtr, CF_TEXT);
455     CloseClipboard();
456     }
457     }
458    
459     tsdPtr->winDisplay = NULL;
460    
461     if (display->display_name != (char *) NULL) {
462     ckfree(display->display_name);
463     }
464     if (display->screens != (Screen *) NULL) {
465     if (display->screens->root_visual != NULL) {
466     ckfree((char *) display->screens->root_visual);
467     }
468     if (display->screens->root != None) {
469     ckfree((char *) display->screens->root);
470     }
471     if (display->screens->cmap != None) {
472     XFreeColormap(display, display->screens->cmap);
473     }
474     ckfree((char *) display->screens);
475     }
476     ckfree((char *) display);
477     ckfree((char *) dispPtr);
478     }
479    
480     /*
481     *----------------------------------------------------------------------
482     *
483     * XBell --
484     *
485     * Generate a beep.
486     *
487     * Results:
488     * None.
489     *
490     * Side effects:
491     * Plays a sounds out the system speakers.
492     *
493     *----------------------------------------------------------------------
494     */
495    
496     void
497     XBell(display, percent)
498     Display* display;
499     int percent;
500     {
501     MessageBeep(MB_OK);
502     }
503    
504     /*
505     *----------------------------------------------------------------------
506     *
507     * TkWinChildProc --
508     *
509     * Callback from Windows whenever an event occurs on a child
510     * window.
511     *
512     * Results:
513     * Standard Windows return value.
514     *
515     * Side effects:
516     * May process events off the Tk event queue.
517     *
518     *----------------------------------------------------------------------
519     */
520    
521     LRESULT CALLBACK
522     TkWinChildProc(hwnd, message, wParam, lParam)
523     HWND hwnd;
524     UINT message;
525     WPARAM wParam;
526     LPARAM lParam;
527     {
528     LRESULT result;
529    
530     switch (message) {
531     case WM_SETCURSOR:
532     /*
533     * Short circuit the WM_SETCURSOR message since we set
534     * the cursor elsewhere.
535     */
536    
537     result = TRUE;
538     break;
539    
540     case WM_CREATE:
541     case WM_ERASEBKGND:
542     result = 0;
543     break;
544    
545     case WM_PAINT:
546     GenerateXEvent(hwnd, message, wParam, lParam);
547     result = DefWindowProc(hwnd, message, wParam, lParam);
548     break;
549    
550     case TK_CLAIMFOCUS:
551     case TK_GEOMETRYREQ:
552     case TK_ATTACHWINDOW:
553     case TK_DETACHWINDOW:
554     result = TkWinEmbeddedEventProc(hwnd, message, wParam, lParam);
555     break;
556    
557     default:
558     if (!Tk_TranslateWinEvent(hwnd, message, wParam, lParam,
559     &result)) {
560     result = DefWindowProc(hwnd, message, wParam, lParam);
561     }
562     break;
563     }
564    
565     /*
566     * Handle any newly queued events before returning control to Windows.
567     */
568    
569     Tcl_ServiceAll();
570     return result;
571     }
572    
573     /*
574     *----------------------------------------------------------------------
575     *
576     * Tk_TranslateWinEvent --
577     *
578     * This function is called by widget window procedures to handle
579     * the translation from Win32 events to Tk events.
580     *
581     * Results:
582     * Returns 1 if the event was handled, else 0.
583     *
584     * Side effects:
585     * Depends on the event.
586     *
587     *----------------------------------------------------------------------
588     */
589    
590     int
591     Tk_TranslateWinEvent(hwnd, message, wParam, lParam, resultPtr)
592     HWND hwnd;
593     UINT message;
594     WPARAM wParam;
595     LPARAM lParam;
596     LRESULT *resultPtr;
597     {
598     *resultPtr = 0;
599     switch (message) {
600     case WM_RENDERFORMAT: {
601     TkWindow *winPtr = (TkWindow *) Tk_HWNDToWindow(hwnd);
602     if (winPtr) {
603     TkWinClipboardRender(winPtr->dispPtr, wParam);
604     }
605     return 1;
606     }
607    
608     case WM_COMMAND:
609     case WM_NOTIFY:
610     case WM_VSCROLL:
611     case WM_HSCROLL: {
612     /*
613     * Reflect these messages back to the sender so that they
614     * can be handled by the window proc for the control. Note
615     * that we need to be careful not to reflect a message that
616     * is targeted to this window, or we will loop.
617     */
618    
619     HWND target = (message == WM_NOTIFY)
620     ? ((NMHDR*)lParam)->hwndFrom : (HWND) lParam;
621     if (target && target != hwnd) {
622     *resultPtr = SendMessage(target, message, wParam, lParam);
623     return 1;
624     }
625     break;
626     }
627    
628     case WM_LBUTTONDOWN:
629     case WM_LBUTTONDBLCLK:
630     case WM_MBUTTONDOWN:
631     case WM_MBUTTONDBLCLK:
632     case WM_RBUTTONDOWN:
633     case WM_RBUTTONDBLCLK:
634     case WM_LBUTTONUP:
635     case WM_MBUTTONUP:
636     case WM_RBUTTONUP:
637     case WM_MOUSEMOVE:
638     Tk_PointerEvent(hwnd, (short) LOWORD(lParam),
639     (short) HIWORD(lParam));
640     return 1;
641    
642     case WM_CLOSE:
643     case WM_SETFOCUS:
644     case WM_KILLFOCUS:
645     case WM_DESTROYCLIPBOARD:
646     case WM_CHAR:
647     case WM_SYSKEYDOWN:
648     case WM_SYSKEYUP:
649     case WM_KEYDOWN:
650     case WM_KEYUP:
651     case WM_MOUSEWHEEL:
652     GenerateXEvent(hwnd, message, wParam, lParam);
653     return 1;
654     case WM_MENUCHAR:
655     GenerateXEvent(hwnd, message, wParam, lParam);
656     /* MNC_CLOSE is the only one that looks right. This is a hack. */
657     *resultPtr = MAKELONG (0, MNC_CLOSE);
658     return 1;
659     }
660     return 0;
661     }
662    
663     /*
664     *----------------------------------------------------------------------
665     *
666     * GenerateXEvent --
667     *
668     * This routine generates an X event from the corresponding
669     * Windows event.
670     *
671     * Results:
672     * None.
673     *
674     * Side effects:
675     * Queues one or more X events.
676     *
677     *----------------------------------------------------------------------
678     */
679    
680     static void
681     GenerateXEvent(hwnd, message, wParam, lParam)
682     HWND hwnd;
683     UINT message;
684     WPARAM wParam;
685     LPARAM lParam;
686     {
687     XEvent event;
688     TkWindow *winPtr = (TkWindow *)Tk_HWNDToWindow(hwnd);
689     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
690     Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
691    
692     if (!winPtr || winPtr->window == None) {
693     return;
694     }
695    
696     event.xany.serial = winPtr->display->request++;
697     event.xany.send_event = False;
698     event.xany.display = winPtr->display;
699     event.xany.window = winPtr->window;
700    
701     switch (message) {
702     case WM_PAINT: {
703     PAINTSTRUCT ps;
704    
705     event.type = Expose;
706     BeginPaint(hwnd, &ps);
707     event.xexpose.x = ps.rcPaint.left;
708     event.xexpose.y = ps.rcPaint.top;
709     event.xexpose.width = ps.rcPaint.right - ps.rcPaint.left;
710     event.xexpose.height = ps.rcPaint.bottom - ps.rcPaint.top;
711     EndPaint(hwnd, &ps);
712     event.xexpose.count = 0;
713     break;
714     }
715    
716     case WM_CLOSE:
717     event.type = ClientMessage;
718     event.xclient.message_type =
719     Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS");
720     event.xclient.format = 32;
721     event.xclient.data.l[0] =
722     Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW");
723     break;
724    
725     case WM_SETFOCUS:
726     case WM_KILLFOCUS: {
727     TkWindow *otherWinPtr = (TkWindow *)Tk_HWNDToWindow((HWND) wParam);
728    
729     /*
730     * Compare toplevel windows to avoid reporting focus
731     * changes within the same toplevel.
732     */
733    
734     while (!(winPtr->flags & TK_TOP_LEVEL)) {
735     winPtr = winPtr->parentPtr;
736     if (winPtr == NULL) {
737     return;
738     }
739     }
740     while (otherWinPtr && !(otherWinPtr->flags & TK_TOP_LEVEL)) {
741     otherWinPtr = otherWinPtr->parentPtr;
742     }
743     if (otherWinPtr == winPtr) {
744     return;
745     }
746    
747     event.xany.window = winPtr->window;
748     event.type = (message == WM_SETFOCUS) ? FocusIn : FocusOut;
749     event.xfocus.mode = NotifyNormal;
750     event.xfocus.detail = NotifyNonlinear;
751     break;
752     }
753    
754     case WM_DESTROYCLIPBOARD:
755     if (tsdPtr->updatingClipboard == TRUE) {
756     /*
757     * We want to avoid this event if we are the ones that caused
758     * this event.
759     */
760     return;
761     }
762     event.type = SelectionClear;
763     event.xselectionclear.selection =
764     Tk_InternAtom((Tk_Window)winPtr, "CLIPBOARD");
765     event.xselectionclear.time = TkpGetMS();
766     break;
767    
768     case WM_MOUSEWHEEL:
769     /*
770     * The mouse wheel event is closer to a key event than a
771     * mouse event in that the message is sent to the window
772     * that has focus.
773     */
774    
775     case WM_CHAR:
776     case WM_SYSKEYDOWN:
777     case WM_SYSKEYUP:
778     case WM_KEYDOWN:
779     case WM_KEYUP: {
780     unsigned int state = GetState(message, wParam, lParam);
781     Time time = TkpGetMS();
782     POINT clientPoint;
783     POINTS rootPoint; /* Note: POINT and POINTS are different */
784     DWORD msgPos;
785    
786     /*
787     * Compute the screen and window coordinates of the event.
788     */
789    
790     msgPos = GetMessagePos();
791     rootPoint = MAKEPOINTS(msgPos);
792     clientPoint.x = rootPoint.x;
793     clientPoint.y = rootPoint.y;
794     ScreenToClient(hwnd, &clientPoint);
795    
796     /*
797     * Set up the common event fields.
798     */
799    
800     event.xbutton.root = RootWindow(winPtr->display,
801     winPtr->screenNum);
802     event.xbutton.subwindow = None;
803     event.xbutton.x = clientPoint.x;
804     event.xbutton.y = clientPoint.y;
805     event.xbutton.x_root = rootPoint.x;
806     event.xbutton.y_root = rootPoint.y;
807     event.xbutton.state = state;
808     event.xbutton.time = time;
809     event.xbutton.same_screen = True;
810    
811     /*
812     * Now set up event specific fields.
813     */
814    
815     switch (message) {
816     case WM_MOUSEWHEEL:
817     /*
818     * We have invented a new X event type to handle
819     * this event. It still uses the KeyPress struct.
820     * However, the keycode field has been overloaded
821     * to hold the zDelta of the wheel.
822     */
823    
824     event.type = MouseWheelEvent;
825     event.xany.send_event = -1;
826     event.xkey.keycode = (short) HIWORD(wParam);
827     break;
828     case WM_SYSKEYDOWN:
829     case WM_KEYDOWN:
830     /*
831     * Check for translated characters in the event queue.
832     * Setting xany.send_event to -1 indicates to the
833     * Windows implementation of XLookupString that this
834     * event was generated by windows and that the Windows
835     * extension xkey.trans_chars is filled with the
836     * characters that came from the TranslateMessage
837     * call. If it is not -1, xkey.keycode is the
838     * virtual key being sent programmatically by generic
839     * code.
840     */
841    
842     event.type = KeyPress;
843     event.xany.send_event = -1;
844     event.xkey.keycode = wParam;
845     GetTranslatedKey(&event.xkey);
846     break;
847    
848     case WM_SYSKEYUP:
849     case WM_KEYUP:
850     /*
851     * We don't check for translated characters on keyup
852     * because Tk won't know what to do with them. Instead, we
853     * wait for the WM_CHAR messages which will follow.
854     */
855     event.type = KeyRelease;
856     event.xkey.keycode = wParam;
857     event.xkey.nbytes = 0;
858     break;
859    
860     case WM_CHAR:
861     /*
862     * Synthesize both a KeyPress and a KeyRelease.
863     * Strings generated by Input Method Editor are handled
864     * in the following manner:
865     * 1. A series of WM_KEYDOWN & WM_KEYUP messages that
866     * cause GetTranslatedKey() to be called and return
867     * immediately because the WM_KEYDOWNs have no
868     * associated WM_CHAR messages -- the IME window is
869     * accumulating the characters and translating them
870     * itself. In the "bind" command, you get an event
871     * with a mystery keysym and %A == "" for each
872     * WM_KEYDOWN that actually was meant for the IME.
873     * 2. A WM_KEYDOWN corresponding to the "confirm typing"
874     * character. This causes GetTranslatedKey() to be
875     * called.
876     * 3. A WM_IME_NOTIFY message saying that the IME is
877     * done. A side effect of this message is that
878     * GetTranslatedKey() thinks this means that there
879     * are no WM_CHAR messages and returns immediately.
880     * In the "bind" command, you get an another event
881     * with a mystery keysym and %A == "".
882     * 4. A sequence of WM_CHAR messages that correspond to
883     * the characters in the IME window. A bunch of
884     * simulated KeyPress/KeyRelease events will be
885     * generated, one for each character. Adjacent
886     * WM_CHAR messages may actually specify the high
887     * and low bytes of a multi-byte character -- in that
888     * case the two WM_CHAR messages will be combined into
889     * one event. It is the event-consumer's
890     * responsibility to convert the string returned from
891     * XLookupString from system encoding to UTF-8.
892     * 5. And finally we get the WM_KEYUP for the "confirm
893     * typing" character.
894     */
895    
896     event.type = KeyPress;
897     event.xany.send_event = -1;
898     event.xkey.keycode = 0;
899     event.xkey.nbytes = 1;
900     event.xkey.trans_chars[0] = (char) wParam;
901    
902     if (IsDBCSLeadByte((BYTE) wParam)) {
903     MSG msg;
904    
905     if ((PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) != 0)
906     && (msg.message == WM_CHAR)) {
907     GetMessage(&msg, NULL, 0, 0);
908     event.xkey.nbytes = 2;
909     event.xkey.trans_chars[1] = (char) msg.wParam;
910     }
911     }
912     Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
913     event.type = KeyRelease;
914     break;
915     }
916     break;
917     }
918    
919     default:
920     return;
921     }
922     Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
923     }
924    
925     /*
926     *----------------------------------------------------------------------
927     *
928     * GetState --
929     *
930     * This function constructs a state mask for the mouse buttons
931     * and modifier keys as they were before the event occured.
932     *
933     * Results:
934     * Returns a composite value of all the modifier and button state
935     * flags that were set at the time the event occurred.
936     *
937     * Side effects:
938     * None.
939     *
940     *----------------------------------------------------------------------
941     */
942    
943     static unsigned int
944     GetState(message, wParam, lParam)
945     UINT message; /* Win32 message type */
946     WPARAM wParam; /* wParam of message, used if key message */
947     LPARAM lParam; /* lParam of message, used if key message */
948     {
949     int mask;
950     int prevState; /* 1 if key was previously down */
951     unsigned int state = TkWinGetModifierState();
952    
953     /*
954     * If the event is a key press or release, we check for modifier
955     * keys so we can report the state of the world before the event.
956     */
957    
958     if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN
959     || message == WM_SYSKEYUP || message == WM_KEYUP) {
960     mask = 0;
961     prevState = HIWORD(lParam) & KF_REPEAT;
962     switch(wParam) {
963     case VK_SHIFT:
964     mask = ShiftMask;
965     break;
966     case VK_CONTROL:
967     mask = ControlMask;
968     break;
969     case VK_MENU:
970     mask = ALT_MASK;
971     break;
972     case VK_CAPITAL:
973     if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {
974     mask = LockMask;
975     prevState = ((state & mask) ^ prevState) ? 0 : 1;
976     }
977     break;
978     case VK_NUMLOCK:
979     if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {
980     mask = Mod1Mask;
981     prevState = ((state & mask) ^ prevState) ? 0 : 1;
982     }
983     break;
984     case VK_SCROLL:
985     if (message == WM_SYSKEYDOWN || message == WM_KEYDOWN) {
986     mask = Mod3Mask;
987     prevState = ((state & mask) ^ prevState) ? 0 : 1;
988     }
989     break;
990     }
991     if (prevState) {
992     state |= mask;
993     } else {
994     state &= ~mask;
995     }
996     }
997     return state;
998     }
999    
1000     /*
1001     *----------------------------------------------------------------------
1002     *
1003     * GetTranslatedKey --
1004     *
1005     * Retrieves WM_CHAR messages that are placed on the system queue
1006     * by the TranslateMessage system call and places them in the
1007     * given KeyPress event.
1008     *
1009     * Results:
1010     * Sets the trans_chars and nbytes member of the key event.
1011     *
1012     * Side effects:
1013     * Removes any WM_CHAR messages waiting on the top of the system
1014     * event queue.
1015     *
1016     *----------------------------------------------------------------------
1017     */
1018    
1019     static void
1020     GetTranslatedKey(xkey)
1021     XKeyEvent *xkey;
1022     {
1023     MSG msg;
1024     char buf[XMaxTransChars];
1025    
1026     xkey->nbytes = 0;
1027    
1028     while ((xkey->nbytes < XMaxTransChars)
1029     && PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
1030     if ((msg.message == WM_CHAR) || (msg.message == WM_SYSCHAR)) {
1031     GetMessage(&msg, NULL, 0, 0);
1032    
1033     /*
1034     * If this is a normal character message, we may need to strip
1035     * off the Alt modifier (e.g. Alt-digits). Note that we don't
1036     * want to do this for system messages, because those were
1037     * presumably generated as an Alt-char sequence (e.g. accelerator
1038     * keys).
1039     */
1040    
1041     if ((msg.message == WM_CHAR) && (msg.lParam & 0x20000000)) {
1042     xkey->state = 0;
1043     }
1044     buf[xkey->nbytes] = (char) msg.wParam;
1045     xkey->trans_chars[xkey->nbytes] = (char) msg.wParam;
1046     xkey->nbytes++;
1047     } else {
1048     break;
1049     }
1050     }
1051     }
1052    
1053     /*
1054     *----------------------------------------------------------------------
1055     *
1056     * Tk_FreeXId --
1057     *
1058     * This inteface is not needed under Windows.
1059     *
1060     * Results:
1061     * None.
1062     *
1063     * Side effects:
1064     * None.
1065     *
1066     *----------------------------------------------------------------------
1067     */
1068    
1069     void
1070     Tk_FreeXId(display, xid)
1071     Display *display;
1072     XID xid;
1073     {
1074     }
1075    
1076     /*
1077     *----------------------------------------------------------------------
1078     *
1079     * TkWinResendEvent --
1080     *
1081     * This function converts an X event into a Windows event and
1082     * invokes the specified windo procedure.
1083     *
1084     * Results:
1085     * A standard Windows result.
1086     *
1087     * Side effects:
1088     * Invokes the window procedure
1089     *
1090     *----------------------------------------------------------------------
1091     */
1092    
1093     LRESULT
1094     TkWinResendEvent(wndproc, hwnd, eventPtr)
1095     WNDPROC wndproc;
1096     HWND hwnd;
1097     XEvent *eventPtr;
1098     {
1099     UINT msg;
1100     WPARAM wparam;
1101     LPARAM lparam;
1102    
1103     if (eventPtr->type == ButtonPress) {
1104     switch (eventPtr->xbutton.button) {
1105     case Button1:
1106     msg = WM_LBUTTONDOWN;
1107     wparam = MK_LBUTTON;
1108     break;
1109     case Button2:
1110     msg = WM_MBUTTONDOWN;
1111     wparam = MK_MBUTTON;
1112     break;
1113     case Button3:
1114     msg = WM_RBUTTONDOWN;
1115     wparam = MK_RBUTTON;
1116     break;
1117     default:
1118     return 0;
1119     }
1120     if (eventPtr->xbutton.state & Button1Mask) {
1121     wparam |= MK_LBUTTON;
1122     }
1123     if (eventPtr->xbutton.state & Button2Mask) {
1124     wparam |= MK_MBUTTON;
1125     }
1126     if (eventPtr->xbutton.state & Button3Mask) {
1127     wparam |= MK_RBUTTON;
1128     }
1129     if (eventPtr->xbutton.state & ShiftMask) {
1130     wparam |= MK_SHIFT;
1131     }
1132     if (eventPtr->xbutton.state & ControlMask) {
1133     wparam |= MK_CONTROL;
1134     }
1135     lparam = MAKELPARAM((short) eventPtr->xbutton.x,
1136     (short) eventPtr->xbutton.y);
1137     } else {
1138     return 0;
1139     }
1140     return CallWindowProc(wndproc, hwnd, msg, wparam, lparam);
1141     }
1142    
1143     /*
1144     *----------------------------------------------------------------------
1145     *
1146     * TkpGetMS --
1147     *
1148     * Return a relative time in milliseconds. It doesn't matter
1149     * when the epoch was.
1150     *
1151     * Results:
1152     * Number of milliseconds.
1153     *
1154     * Side effects:
1155     * None.
1156     *
1157     *----------------------------------------------------------------------
1158     */
1159    
1160     unsigned long
1161     TkpGetMS()
1162     {
1163     return GetTickCount();
1164     }
1165    
1166     /*
1167     *----------------------------------------------------------------------
1168     *
1169     * TkWinUpdatingClipboard --
1170     *
1171     *
1172     * Results:
1173     * Number of milliseconds.
1174     *
1175     * Side effects:
1176     * None.
1177     *
1178     *----------------------------------------------------------------------
1179     */
1180    
1181     void
1182     TkWinUpdatingClipboard(int mode)
1183     {
1184     ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
1185     Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
1186    
1187     tsdPtr->updatingClipboard = mode;
1188     }
1189    
1190    
1191     /* $History: tkWinX.c $
1192     *
1193     * ***************** Version 1 *****************
1194     * User: Dtashley Date: 1/02/01 Time: 3:18a
1195     * Created in $/IjuScripter, IjuConsole/Source/Tk Base
1196     * Initial check-in.
1197     */
1198    
1199     /* End of TKWINX.C */

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25