OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [win/] [tkWinX.c] - Blame information for rev 578

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.