Release 960606
[wine/multimedia.git] / windows / event.c
blobce75d90aac744fd32f1d47d35f2417e54823ea84
1 /*
2 * X events handling functions
3 *
4 * Copyright 1993 Alexandre Julliard
5 *
6 */
8 #include <ctype.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <unistd.h>
12 #include <sys/time.h>
13 #include <sys/types.h>
14 #include <errno.h>
15 #include <X11/keysym.h>
16 #include <X11/Xlib.h>
17 #include <X11/Xresource.h>
18 #include <X11/Xutil.h>
19 #include <X11/Xatom.h>
21 #include "windows.h"
22 #include "gdi.h"
23 #include "heap.h"
24 #include "win.h"
25 #include "class.h"
26 #include "clipboard.h"
27 #include "debugger.h"
28 #include "module.h"
29 #include "options.h"
30 #include "queue.h"
31 #include "winpos.h"
32 #include "registers.h"
33 #include "stddebug.h"
34 #include "debug.h"
35 #include "dde_proc.h"
38 #ifdef ndef
39 #ifndef FamilyAmoeba
40 typedef char *XPointer;
41 #endif
42 #endif
44 #ifdef WHO_NEEDS_DIRTY_HACKS
45 #ifdef sparc
46 /* Dirty hack to compile with Sun's OpenWindows */
47 typedef char *XPointer;
48 #endif
49 #endif
51 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
53 /* X context to associate a hwnd to an X window */
54 static XContext winContext = 0;
56 /* State variables */
57 BOOL MouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
58 BOOL AsyncMouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
59 BYTE KeyStateTable[256];
60 BYTE AsyncKeyStateTable[256];
63 WPARAM lastEventChar = 0; /* this will have to be changed once
64 * ToAscii starts working */
66 static HWND captureWnd = 0;
67 static BOOL InputEnabled = TRUE;
69 /* Keyboard translation tables */
70 static int special_key[] =
72 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
73 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
74 0, 0, 0, VK_ESCAPE /* FF18 */
77 static cursor_key[] =
79 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
80 VK_NEXT, VK_END /* FF50 */
83 static misc_key[] =
85 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
86 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
89 static keypad_key[] =
91 VK_MENU, VK_NUMLOCK, /* FF7E */
92 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
93 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
94 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
95 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
96 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
97 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
98 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
99 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
100 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
101 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
104 static function_key[] =
106 VK_F1, VK_F2, /* FFBE */
107 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
108 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
111 static modifier_key[] =
113 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
114 0, 0, /* FFE1 */
115 0, VK_MENU, VK_MENU /* FFE8 */
118 typedef union
120 struct
122 unsigned long count : 16;
123 unsigned long code : 8;
124 unsigned long extended : 1;
125 unsigned long : 2;
126 unsigned long reserved : 2;
127 unsigned long context : 1;
128 unsigned long previous : 1;
129 unsigned long transition : 1;
130 } lp1;
131 unsigned long lp2;
132 } KEYLP;
134 static BOOL KeyDown = FALSE;
136 static const char *event_names[] =
138 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
139 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
140 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
141 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
142 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
143 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
144 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
145 "ClientMessage", "MappingNotify"
148 /* Event handlers */
149 static void EVENT_key( XKeyEvent *event );
150 static void EVENT_ButtonPress( XButtonEvent *event );
151 static void EVENT_ButtonRelease( XButtonEvent *event );
152 static void EVENT_MotionNotify( XMotionEvent *event );
153 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event );
154 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
155 static void EVENT_Expose( HWND hwnd, XExposeEvent *event );
156 static void EVENT_GraphicsExpose( HWND hwnd, XGraphicsExposeEvent *event );
157 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
158 static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event);
159 static void EVENT_SelectionNotify( HWND hwnd, XSelectionEvent *event);
160 static void EVENT_SelectionClear( HWND hwnd, XSelectionClearEvent *event);
161 static void EVENT_ClientMessage( HWND hwnd, XClientMessageEvent *event );
164 /***********************************************************************
165 * EVENT_ProcessEvent
167 * Process an X event.
169 void EVENT_ProcessEvent( XEvent *event )
171 HWND hwnd;
172 XPointer ptr;
174 XFindContext( display, ((XAnyEvent *)event)->window, winContext, &ptr );
175 hwnd = (HWND) (int)ptr;
177 dprintf_event(stddeb, "Got event %s for hwnd %04x\n",
178 event_names[event->type], hwnd );
180 switch(event->type)
182 case KeyPress:
183 case KeyRelease:
184 EVENT_key( (XKeyEvent*)event );
185 break;
187 case ButtonPress:
188 EVENT_ButtonPress( (XButtonEvent*)event );
189 break;
191 case ButtonRelease:
192 EVENT_ButtonRelease( (XButtonEvent*)event );
193 break;
195 case MotionNotify:
196 /* Wine between two fast machines across the overloaded campus
197 ethernet gets very boged down in MotionEvents. The following
198 simply finds the last motion event in the queue and drops
199 the rest. On a good link events are servered before they build
200 up so this doesn't take place. On a slow link this may cause
201 problems if the event order is important. I'm not yet seen
202 of any problems. Jon 7/6/96.
204 while (XCheckTypedWindowEvent(display, ((XAnyEvent *)event)->window,
205 MotionNotify, event));
206 EVENT_MotionNotify( (XMotionEvent*)event );
207 break;
209 case FocusIn:
210 EVENT_FocusIn( hwnd, (XFocusChangeEvent*)event );
211 break;
213 case FocusOut:
214 EVENT_FocusOut( hwnd, (XFocusChangeEvent*)event );
215 break;
217 case Expose:
218 EVENT_Expose( hwnd, (XExposeEvent*)event );
219 break;
221 case ConfigureNotify:
222 EVENT_ConfigureNotify( hwnd, (XConfigureEvent*)event );
223 break;
225 case SelectionRequest:
226 EVENT_SelectionRequest( hwnd, (XSelectionRequestEvent*)event );
227 break;
229 case SelectionNotify:
230 EVENT_SelectionNotify( hwnd, (XSelectionEvent*)event );
231 break;
233 case SelectionClear:
234 EVENT_SelectionClear( hwnd, (XSelectionClearEvent*) event );
235 break;
237 case ClientMessage:
238 EVENT_ClientMessage( hwnd, (XClientMessageEvent *) event );
239 break;
241 case GraphicsExpose:
242 EVENT_GraphicsExpose( hwnd, (XGraphicsExposeEvent *) event );
244 case NoExpose:
245 break;
247 default:
248 dprintf_event(stddeb, "Unprocessed event %s for hwnd %04x\n",
249 event_names[event->type], hwnd );
250 break;
255 /***********************************************************************
256 * EVENT_RegisterWindow
258 * Associate an X window to a HWND.
260 void EVENT_RegisterWindow( Window w, HWND hwnd )
262 if (!winContext) winContext = XUniqueContext();
263 XSaveContext( display, w, winContext, (XPointer)(int)hwnd );
267 /***********************************************************************
268 * EVENT_WaitXEvent
270 * Wait for an X event, but at most maxWait milliseconds (-1 for no timeout).
271 * Return TRUE if an event is pending, FALSE on timeout or error
272 * (for instance lost connection with the server).
274 BOOL EVENT_WaitXEvent( LONG maxWait )
276 fd_set read_set;
277 struct timeval timeout;
278 XEvent event;
279 int fd = ConnectionNumber(display);
281 if (!XPending(display) && (maxWait != -1))
283 FD_ZERO( &read_set );
284 FD_SET( fd, &read_set );
286 timeout.tv_usec = (maxWait % 1000) * 1000;
287 timeout.tv_sec = maxWait / 1000;
289 #ifdef CONFIG_IPC
290 sigsetjmp(env_wait_x, 1);
291 stop_wait_op= CONT;
293 if (DDE_GetRemoteMessage()) {
294 while(DDE_GetRemoteMessage())
296 return TRUE;
298 stop_wait_op= STOP_WAIT_X;
299 /* The code up to the next "stop_wait_op= CONT" must be reentrant */
300 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
301 !XPending(display)) {
302 stop_wait_op= CONT;
303 return FALSE;
304 } else {
305 stop_wait_op= CONT;
307 #else /* CONFIG_IPC */
308 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
309 return FALSE; /* Timeout or error */
310 #endif /* CONFIG_IPC */
314 /* Process the event (and possibly others that occurred in the meantime) */
318 #ifdef CONFIG_IPC
319 if (DDE_GetRemoteMessage())
321 while(DDE_GetRemoteMessage()) ;
322 return TRUE;
324 #endif /* CONFIG_IPC */
326 XNextEvent( display, &event );
327 EVENT_ProcessEvent( &event );
329 while (XPending( display ));
330 return TRUE;
334 /***********************************************************************
335 * EVENT_Synchronize
337 * Synchronize with the X server. Should not be used too often.
339 void EVENT_Synchronize()
341 XEvent event;
343 XSync( display, False );
344 while (XPending( display ))
346 XNextEvent( display, &event );
347 EVENT_ProcessEvent( &event );
352 /***********************************************************************
353 * EVENT_XStateToKeyState
355 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
356 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
358 static WORD EVENT_XStateToKeyState( int state )
360 int kstate = 0;
362 if (state & Button1Mask) kstate |= MK_LBUTTON;
363 if (state & Button2Mask) kstate |= MK_MBUTTON;
364 if (state & Button3Mask) kstate |= MK_RBUTTON;
365 if (state & ShiftMask) kstate |= MK_SHIFT;
366 if (state & ControlMask) kstate |= MK_CONTROL;
367 return kstate;
371 /***********************************************************************
372 * EVENT_Expose
374 static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
376 RECT32 rect;
377 WND * wndPtr = WIN_FindWndPtr( hwnd );
378 if (!wndPtr) return;
380 /* Make position relative to client area instead of window */
381 rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
382 rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
383 rect.right = rect.left + event->width;
384 rect.bottom = rect.top + event->height;
386 RedrawWindow32( hwnd, &rect, 0,
387 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
388 (event->count ? 0 : RDW_ERASENOW) );
392 /***********************************************************************
393 * EVENT_GraphicsExpose
394 * This is needed when scrolling area is partially obscured
395 * by non-Wine X window.
397 static void EVENT_GraphicsExpose( HWND hwnd, XGraphicsExposeEvent *event )
399 RECT16 rect;
400 WND * wndPtr = WIN_FindWndPtr( hwnd );
401 if (!wndPtr) return;
403 /* Make position relative to client area instead of window */
404 rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
405 rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
406 rect.right = rect.left + event->width;
407 rect.bottom = rect.top + event->height;
409 RedrawWindow16( hwnd, &rect, 0,
410 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
411 (event->count ? 0 : RDW_ERASENOW) );
415 /***********************************************************************
416 * EVENT_key
418 * Handle a X key event
420 static void EVENT_key( XKeyEvent *event )
422 char Str[24];
423 XComposeStatus cs;
424 KeySym keysym;
425 WORD vkey = 0;
426 WORD xkey, key_type, key;
427 KEYLP keylp;
428 BOOL extended = FALSE;
430 int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs);
432 Str[ascii_chars] = '\0';
433 dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, ascii chars=%u / %X / '%s'\n",
434 keysym, ascii_chars, Str[0], Str);
436 /* Ctrl-Alt-Return enters the debugger */
437 if ((keysym == XK_Return) && (event->type == KeyPress) &&
438 (event->state & ControlMask) && (event->state & Mod1Mask))
439 DEBUG_EnterDebugger();
441 xkey = LOWORD(keysym);
442 key_type = HIBYTE(xkey);
443 key = LOBYTE(xkey);
444 dprintf_key(stddeb," key_type=%X, key=%X\n", key_type, key);
446 if (key_type == 0xFF) /* non-character key */
448 if (key >= 0x08 && key <= 0x1B) /* special key */
449 vkey = special_key[key - 0x08];
450 else if (key >= 0x50 && key <= 0x57) /* cursor key */
451 vkey = cursor_key[key - 0x50];
452 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
453 vkey = misc_key[key - 0x60];
454 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
456 vkey = keypad_key[key - 0x7E];
457 extended = TRUE;
459 else if (key >= 0xBE && key <= 0xCD) /* function key */
461 vkey = function_key[key - 0xBE];
462 extended = TRUE;
464 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
465 vkey = modifier_key[key - 0xE1];
466 else if (key == 0xFF) /* DEL key */
467 vkey = VK_DELETE;
469 else if (key_type == 0) /* character key */
471 if ( isalnum(key) )
472 vkey = toupper(key); /* convert lower to uppercase */
473 else
474 vkey = 0xbe;
477 if (event->type == KeyPress)
479 if (!(KeyStateTable[vkey] & 0x80))
480 KeyStateTable[vkey] ^= 0x01;
481 KeyStateTable[vkey] |= 0x80;
482 keylp.lp1.count = 1;
483 keylp.lp1.code = LOBYTE(event->keycode) - 8;
484 keylp.lp1.extended = (extended ? 1 : 0);
485 keylp.lp1.reserved = (ascii_chars ? 1 : 0);
486 keylp.lp1.context = ( (event->state & Mod1Mask) ||
487 (KeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
488 keylp.lp1.previous = (KeyDown ? 0 : 1);
489 keylp.lp1.transition = 0;
490 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
491 vkey, keylp.lp2 );
492 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
493 hardware_event( KeyStateTable[VK_MENU] & 0x80 ? WM_SYSKEYDOWN : WM_KEYDOWN,
494 vkey, keylp.lp2,
495 event->x_root - desktopX, event->y_root - desktopY,
496 event->time, 0 );
497 KeyDown = TRUE;
499 /* Currently we use reserved field in the scan-code byte to
500 * make it possible for TranslateMessage to recognize character keys
501 * and get them from lastEventChar global variable.
503 * ToAscii should handle it.
506 if( ascii_chars ) lastEventChar = Str[0];
508 else
510 UINT sysKey = KeyStateTable[VK_MENU];
512 KeyStateTable[vkey] &= ~0x80;
513 keylp.lp1.count = 1;
514 keylp.lp1.code = LOBYTE(event->keycode) - 8;
515 keylp.lp1.extended = (extended ? 1 : 0);
516 keylp.lp1.reserved = 0;
517 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
518 keylp.lp1.previous = 1;
519 keylp.lp1.transition = 1;
520 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
521 vkey, keylp.lp2 );
522 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
523 hardware_event( sysKey & 0x80 ? WM_SYSKEYUP : WM_KEYUP,
524 vkey, keylp.lp2,
525 event->x_root - desktopX, event->y_root - desktopY,
526 event->time, 0 );
527 KeyDown = FALSE;
532 /***********************************************************************
533 * EVENT_MotionNotify
535 static void EVENT_MotionNotify( XMotionEvent *event )
537 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
538 event->x_root - desktopX, event->y_root - desktopY,
539 event->time, 0 );
543 /***********************************************************************
544 * EVENT_DummyMotionNotify
546 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
548 void EVENT_DummyMotionNotify(void)
550 Window root, child;
551 int rootX, rootY, childX, childY;
552 unsigned int state;
554 if (XQueryPointer( display, rootWindow, &root, &child,
555 &rootX, &rootY, &childX, &childY, &state ))
557 hardware_event(WM_MOUSEMOVE, EVENT_XStateToKeyState( state ), 0L,
558 rootX - desktopX, rootY - desktopY, GetTickCount(), 0 );
563 /***********************************************************************
564 * EVENT_ButtonPress
566 static void EVENT_ButtonPress( XButtonEvent *event )
568 static WORD messages[NB_BUTTONS] =
569 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
570 int buttonNum = event->button - 1;
572 if (buttonNum >= NB_BUTTONS) return;
573 MouseButtonsStates[buttonNum] = 0x8000;
574 AsyncMouseButtonsStates[buttonNum] = 0x8000;
575 hardware_event( messages[buttonNum],
576 EVENT_XStateToKeyState( event->state ), 0L,
577 event->x_root - desktopX, event->y_root - desktopY,
578 event->time, 0 );
582 /***********************************************************************
583 * EVENT_ButtonRelease
585 static void EVENT_ButtonRelease( XButtonEvent *event )
587 static const WORD messages[NB_BUTTONS] =
588 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
589 int buttonNum = event->button - 1;
591 if (buttonNum >= NB_BUTTONS) return;
592 MouseButtonsStates[buttonNum] = FALSE;
593 hardware_event( messages[buttonNum],
594 EVENT_XStateToKeyState( event->state ), 0L,
595 event->x_root - desktopX, event->y_root - desktopY,
596 event->time, 0 );
600 /**********************************************************************
601 * EVENT_FocusIn
603 static void EVENT_FocusIn (HWND hwnd, XFocusChangeEvent *event )
605 if (event->detail == NotifyPointer) return;
606 if (hwnd != GetActiveWindow()) WINPOS_ChangeActiveWindow( hwnd, FALSE );
607 if ((hwnd != GetFocus()) && !IsChild( hwnd, GetFocus())) SetFocus( hwnd );
611 /**********************************************************************
612 * EVENT_FocusOut
614 * Note: only top-level override-redirect windows get FocusOut events.
616 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
618 if (event->detail == NotifyPointer) return;
619 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
620 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 );
624 /**********************************************************************
625 * EVENT_ConfigureNotify
627 * The ConfigureNotify event is only selected on the desktop window
628 * and on top-level windows when the -managed flag is used.
630 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
632 /* FIXME: with -desktop xxx we get this event _before_ desktop
633 * window structure is created. WIN_GetDesktop() check is a hack.
636 if ( !WIN_GetDesktop() || hwnd == GetDesktopWindow())
638 desktopX = event->x;
639 desktopY = event->y;
641 else
643 /* Managed window; most of this code is shamelessly
644 * stolen from SetWindowPos - FIXME: outdated
647 WND *wndPtr;
648 WINDOWPOS16 *winpos;
649 RECT16 newWindowRect, newClientRect;
650 HRGN hrgnOldPos, hrgnNewPos;
652 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
654 dprintf_event(stddeb,"ConfigureNotify: invalid HWND %04x\n",hwnd);
655 return;
658 if (!(winpos = SEGPTR_NEW(WINDOWPOS16))) return;
660 /* Artificial messages - what is this for? */
661 SendMessage16(hwnd, WM_ENTERSIZEMOVE, 0, 0);
662 SendMessage16(hwnd, WM_EXITSIZEMOVE, 0, 0);
664 /* Fill WINDOWPOS struct */
665 winpos->flags = SWP_NOACTIVATE | SWP_NOZORDER;
666 winpos->hwnd = hwnd;
667 winpos->x = event->x;
668 winpos->y = event->y;
669 winpos->cx = event->width;
670 winpos->cy = event->height;
672 /* Check for unchanged attributes */
673 if(winpos->x == wndPtr->rectWindow.left &&
674 winpos->y == wndPtr->rectWindow.top)
675 winpos->flags |= SWP_NOMOVE;
676 if(winpos->cx == wndPtr->rectWindow.right - wndPtr->rectWindow.left &&
677 winpos->cy == wndPtr->rectWindow.bottom - wndPtr->rectWindow.top)
678 winpos->flags |= SWP_NOSIZE;
680 /* Send WM_WINDOWPOSCHANGING */
681 SendMessage16(hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)SEGPTR_GET(winpos));
683 /* Calculate new position and size */
684 newWindowRect.left = event->x;
685 newWindowRect.right = event->x + event->width;
686 newWindowRect.top = event->y;
687 newWindowRect.bottom = event->y + event->height;
689 WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
690 &wndPtr->rectWindow, &wndPtr->rectClient,
691 SEGPTR_GET(winpos), &newClientRect );
693 hrgnOldPos = CreateRectRgnIndirect16( &wndPtr->rectWindow );
694 hrgnNewPos = CreateRectRgnIndirect16( &newWindowRect );
695 CombineRgn( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
697 /* Set new size and position */
698 wndPtr->rectWindow = newWindowRect;
699 wndPtr->rectClient = newClientRect;
700 SendMessage16( hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)SEGPTR_GET(winpos));
701 SEGPTR_FREE(winpos);
703 /* full window drag leaves unrepainted garbage without this */
704 RedrawWindow32( 0, NULL, hrgnOldPos, RDW_INVALIDATE |
705 RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW );
706 DeleteObject(hrgnOldPos);
707 DeleteObject(hrgnNewPos);
712 /***********************************************************************
713 * EVENT_SelectionRequest
715 static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event )
717 XSelectionEvent result;
718 Atom rprop = None;
719 Window request = event->requestor;
721 if(event->target == XA_STRING)
723 HANDLE hText;
724 LPSTR text;
726 rprop = event->property;
728 if(rprop == None) rprop = event->target;
730 if(event->selection!=XA_PRIMARY) rprop = None;
731 else if(!CLIPBOARD_IsPresent(CF_TEXT)) rprop = None;
732 else{
733 /* Don't worry if we can't open */
734 BOOL couldOpen=OpenClipboard(hwnd);
735 hText=GetClipboardData(CF_TEXT);
736 text=GlobalLock16(hText);
737 XChangeProperty(display,request,rprop,XA_STRING,
738 8,PropModeReplace,text,strlen(text));
739 GlobalUnlock16(hText);
740 /* close only if we opened before */
741 if(couldOpen)CloseClipboard();
745 if(rprop==None)
746 dprintf_event(stddeb,"Request for %s ignored\n", XGetAtomName(display,event->target));
748 result.type=SelectionNotify;
749 result.display=display;
750 result.requestor=request;
751 result.selection=event->selection;
752 result.property=rprop;
753 result.target=event->target;
754 result.time=event->time;
755 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
759 /***********************************************************************
760 * EVENT_SelectionNotify
762 static void EVENT_SelectionNotify(HWND hwnd, XSelectionEvent *event)
764 if(event->selection!=XA_PRIMARY)return;
765 if(event->target!=XA_STRING)CLIPBOARD_ReadSelection(0,None);
766 CLIPBOARD_ReadSelection(event->requestor,event->property);
770 /***********************************************************************
771 * EVENT_SelectionClear
773 static void EVENT_SelectionClear(HWND hwnd, XSelectionClearEvent *event)
775 if(event->selection!=XA_PRIMARY)return;
776 CLIPBOARD_ReleaseSelection(hwnd);
780 /**********************************************************************
781 * EVENT_ClientMessage
783 static void EVENT_ClientMessage (HWND hwnd, XClientMessageEvent *event )
785 static Atom wmProtocols = None;
786 static Atom wmDeleteWindow = None;
788 if (wmProtocols == None)
789 wmProtocols = XInternAtom( display, "WM_PROTOCOLS", True );
790 if (wmDeleteWindow == None)
791 wmDeleteWindow = XInternAtom( display, "WM_DELETE_WINDOW", True );
793 if ((event->format != 32) || (event->message_type != wmProtocols) ||
794 (((Atom) event->data.l[0]) != wmDeleteWindow))
796 dprintf_event( stddeb, "unrecognized ClientMessage\n" );
797 return;
799 SendMessage16( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
803 /**********************************************************************
804 * SetCapture (USER.18)
806 HWND SetCapture( HWND hwnd )
808 Window win;
809 HWND old_capture_wnd = captureWnd;
811 if (!hwnd)
813 ReleaseCapture();
814 return old_capture_wnd;
816 if (!(win = WIN_GetXWindow( hwnd ))) return 0;
817 if (XGrabPointer(display, win, False,
818 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
819 GrabModeAsync, GrabModeAsync,
820 None, None, CurrentTime ) == GrabSuccess)
822 dprintf_win(stddeb, "SetCapture: %04x\n", hwnd);
823 captureWnd = hwnd;
824 return old_capture_wnd;
826 else return 0;
830 /**********************************************************************
831 * ReleaseCapture (USER.19)
833 void ReleaseCapture()
835 if (captureWnd == 0) return;
836 XUngrabPointer( display, CurrentTime );
837 captureWnd = 0;
838 dprintf_win(stddeb, "ReleaseCapture\n");
841 /**********************************************************************
842 * GetCapture (USER.236)
844 HWND GetCapture()
846 return captureWnd;
850 /***********************************************************************
851 * GetMouseEventProc (USER.337)
853 FARPROC GetMouseEventProc(void)
855 HMODULE hmodule = GetModuleHandle("USER");
856 return MODULE_GetEntryPoint( hmodule,
857 MODULE_GetOrdinal( hmodule, "Mouse_Event" ) );
861 /***********************************************************************
862 * Mouse_Event (USER.299)
864 #ifndef WINELIB
865 void Mouse_Event( struct sigcontext_struct context )
867 /* Register values:
868 * AX = mouse event
869 * BX = horizontal displacement if AX & ME_MOVE
870 * CX = vertical displacement if AX & ME_MOVE
871 * DX = button state (?)
872 * SI = mouse event flags (?)
874 Window root, child;
875 int rootX, rootY, childX, childY;
876 unsigned int state;
878 if (AX_reg(&context) & ME_MOVE)
880 /* We have to actually move the cursor */
881 XWarpPointer( display, rootWindow, None, 0, 0, 0, 0,
882 (short)BX_reg(&context), (short)CX_reg(&context) );
883 return;
885 if (!XQueryPointer( display, rootWindow, &root, &child,
886 &rootX, &rootY, &childX, &childY, &state )) return;
887 if (AX_reg(&context) & ME_LDOWN)
888 hardware_event( WM_LBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
889 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
890 if (AX_reg(&context) & ME_LUP)
891 hardware_event( WM_LBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
892 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
893 if (AX_reg(&context) & ME_RDOWN)
894 hardware_event( WM_RBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
895 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
896 if (AX_reg(&context) & ME_RUP)
897 hardware_event( WM_RBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
898 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
900 #endif
903 /**********************************************************************
904 * EnableHardwareInput [USER.331]
906 BOOL EnableHardwareInput(BOOL bEnable)
908 BOOL bOldState = InputEnabled;
909 dprintf_event(stdnimp,"EMPTY STUB !!! EnableHardwareInput(%d);\n", bEnable);
910 InputEnabled = bEnable;
911 return (bOldState && !bEnable);