Release 960623
[wine.git] / windows / event.c
blob4f421a4cacbe48c9ce1aa01841f3449b76779de1
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 "message.h"
29 #include "module.h"
30 #include "options.h"
31 #include "queue.h"
32 #include "winpos.h"
33 #include "registers.h"
34 #include "stddebug.h"
35 #include "debug.h"
36 #include "dde_proc.h"
39 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
41 /* X context to associate a hwnd to an X window */
42 static XContext winContext = 0;
44 /* State variables */
45 BOOL MouseButtonsStates[NB_BUTTONS];
46 BOOL AsyncMouseButtonsStates[NB_BUTTONS];
47 BYTE KeyStateTable[256];
48 BYTE AsyncKeyStateTable[256];
51 WPARAM lastEventChar = 0; /* this will have to be changed once
52 * ToAscii starts working */
54 static HWND captureWnd = 0;
55 static BOOL InputEnabled = TRUE;
57 /* Keyboard translation tables */
58 static const int special_key[] =
60 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
61 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
62 0, 0, 0, VK_ESCAPE /* FF18 */
65 static const int cursor_key[] =
67 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
68 VK_NEXT, VK_END /* FF50 */
71 static const int misc_key[] =
73 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
74 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
77 static const int keypad_key[] =
79 VK_MENU, VK_NUMLOCK, /* FF7E */
80 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
81 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
82 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
83 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
84 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
85 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
86 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
87 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
88 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
89 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
92 static const int function_key[] =
94 VK_F1, VK_F2, /* FFBE */
95 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
96 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
99 static const int modifier_key[] =
101 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
102 0, 0, /* FFE1 */
103 0, VK_MENU, VK_MENU /* FFE8 */
106 typedef union
108 struct
110 unsigned long count : 16;
111 unsigned long code : 8;
112 unsigned long extended : 1;
113 unsigned long : 2;
114 unsigned long reserved : 2;
115 unsigned long context : 1;
116 unsigned long previous : 1;
117 unsigned long transition : 1;
118 } lp1;
119 unsigned long lp2;
120 } KEYLP;
122 static BOOL KeyDown = FALSE;
124 static const char * const event_names[] =
126 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
127 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
128 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
129 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
130 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
131 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
132 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
133 "ClientMessage", "MappingNotify"
136 /* Event handlers */
137 static void EVENT_key( XKeyEvent *event );
138 static void EVENT_ButtonPress( XButtonEvent *event );
139 static void EVENT_ButtonRelease( XButtonEvent *event );
140 static void EVENT_MotionNotify( XMotionEvent *event );
141 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event );
142 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
143 static void EVENT_Expose( WND *pWnd, XExposeEvent *event );
144 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event );
145 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
146 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event);
147 static void EVENT_SelectionNotify( XSelectionEvent *event);
148 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event);
149 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event );
152 /***********************************************************************
153 * EVENT_ProcessEvent
155 * Process an X event.
157 void EVENT_ProcessEvent( XEvent *event )
159 WND *pWnd;
161 if (XFindContext( display, ((XAnyEvent *)event)->window, winContext,
162 (char **)&pWnd ) != 0)
163 return; /* Not for a registered window */
165 dprintf_event( stddeb, "Got event %s for hwnd %04x\n",
166 event_names[event->type], pWnd->hwndSelf );
168 switch(event->type)
170 case KeyPress:
171 case KeyRelease:
172 EVENT_key( (XKeyEvent*)event );
173 break;
175 case ButtonPress:
176 EVENT_ButtonPress( (XButtonEvent*)event );
177 break;
179 case ButtonRelease:
180 EVENT_ButtonRelease( (XButtonEvent*)event );
181 break;
183 case MotionNotify:
184 /* Wine between two fast machines across the overloaded campus
185 ethernet gets very boged down in MotionEvents. The following
186 simply finds the last motion event in the queue and drops
187 the rest. On a good link events are servered before they build
188 up so this doesn't take place. On a slow link this may cause
189 problems if the event order is important. I'm not yet seen
190 of any problems. Jon 7/6/96.
192 while (XCheckTypedWindowEvent(display, ((XAnyEvent *)event)->window,
193 MotionNotify, event));
194 EVENT_MotionNotify( (XMotionEvent*)event );
195 break;
197 case FocusIn:
198 EVENT_FocusIn( pWnd->hwndSelf, (XFocusChangeEvent*)event );
199 break;
201 case FocusOut:
202 EVENT_FocusOut( pWnd->hwndSelf, (XFocusChangeEvent*)event );
203 break;
205 case Expose:
206 EVENT_Expose( pWnd, (XExposeEvent *)event );
207 break;
209 case GraphicsExpose:
210 EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
211 break;
213 case ConfigureNotify:
214 EVENT_ConfigureNotify( pWnd->hwndSelf, (XConfigureEvent*)event );
215 break;
217 case SelectionRequest:
218 EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event );
219 break;
221 case SelectionNotify:
222 EVENT_SelectionNotify( (XSelectionEvent *)event );
223 break;
225 case SelectionClear:
226 EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event );
227 break;
229 case ClientMessage:
230 EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event );
231 break;
233 case NoExpose:
234 break;
236 default:
237 dprintf_event(stddeb, "Unprocessed event %s for hwnd %04x\n",
238 event_names[event->type], pWnd->hwndSelf );
239 break;
244 /***********************************************************************
245 * EVENT_RegisterWindow
247 * Associate an X window to a HWND.
249 void EVENT_RegisterWindow( WND *pWnd )
251 if (!winContext) winContext = XUniqueContext();
252 XSaveContext( display, pWnd->window, winContext, (char *)pWnd );
256 /***********************************************************************
257 * EVENT_WaitXEvent
259 * Wait for an X event, optionally sleeping until one arrives.
260 * Return TRUE if an event is pending, FALSE on timeout or error
261 * (for instance lost connection with the server).
263 BOOL EVENT_WaitXEvent( BOOL sleep )
265 fd_set read_set;
266 struct timeval timeout;
267 XEvent event;
268 int fd = ConnectionNumber(display);
270 if (!XPending(display))
272 LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0;
274 FD_ZERO( &read_set );
275 FD_SET( fd, &read_set );
277 timeout.tv_usec = (maxWait % 1000) * 1000;
278 timeout.tv_sec = maxWait / 1000;
280 #ifdef CONFIG_IPC
281 sigsetjmp(env_wait_x, 1);
282 stop_wait_op= CONT;
284 if (DDE_GetRemoteMessage()) {
285 while(DDE_GetRemoteMessage())
287 return TRUE;
289 stop_wait_op = STOP_WAIT_X;
290 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
291 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
292 !XPending(display))
294 stop_wait_op = CONT;
295 TIMER_ExpireTimers();
296 return FALSE;
298 else stop_wait_op = CONT;
299 #else /* CONFIG_IPC */
300 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
302 /* Timeout or error */
303 TIMER_ExpireTimers();
304 return FALSE;
306 #endif /* CONFIG_IPC */
310 /* Process the event (and possibly others that occurred in the meantime) */
314 #ifdef CONFIG_IPC
315 if (DDE_GetRemoteMessage())
317 while(DDE_GetRemoteMessage()) ;
318 return TRUE;
320 #endif /* CONFIG_IPC */
322 XNextEvent( display, &event );
323 EVENT_ProcessEvent( &event );
325 while (XPending( display ));
326 return TRUE;
330 /***********************************************************************
331 * EVENT_Synchronize
333 * Synchronize with the X server. Should not be used too often.
335 void EVENT_Synchronize()
337 XEvent event;
339 XSync( display, False );
340 while (XPending( display ))
342 XNextEvent( display, &event );
343 EVENT_ProcessEvent( &event );
348 /***********************************************************************
349 * EVENT_XStateToKeyState
351 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
352 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
354 static WORD EVENT_XStateToKeyState( int state )
356 int kstate = 0;
358 if (state & Button1Mask) kstate |= MK_LBUTTON;
359 if (state & Button2Mask) kstate |= MK_MBUTTON;
360 if (state & Button3Mask) kstate |= MK_RBUTTON;
361 if (state & ShiftMask) kstate |= MK_SHIFT;
362 if (state & ControlMask) kstate |= MK_CONTROL;
363 return kstate;
367 /***********************************************************************
368 * EVENT_Expose
370 static void EVENT_Expose( WND *pWnd, XExposeEvent *event )
372 RECT32 rect;
374 /* Make position relative to client area instead of window */
375 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
376 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
377 rect.right = rect.left + event->width;
378 rect.bottom = rect.top + event->height;
380 RedrawWindow32( pWnd->hwndSelf, &rect, 0,
381 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
382 (event->count ? 0 : RDW_ERASENOW) );
386 /***********************************************************************
387 * EVENT_GraphicsExpose
389 * This is needed when scrolling area is partially obscured
390 * by non-Wine X window.
392 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
394 RECT32 rect;
396 /* Make position relative to client area instead of window */
397 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
398 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
399 rect.right = rect.left + event->width;
400 rect.bottom = rect.top + event->height;
402 RedrawWindow32( pWnd->hwndSelf, &rect, 0,
403 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
404 (event->count ? 0 : RDW_ERASENOW) );
408 /***********************************************************************
409 * EVENT_key
411 * Handle a X key event
413 static void EVENT_key( XKeyEvent *event )
415 char Str[24];
416 XComposeStatus cs;
417 KeySym keysym;
418 WORD vkey = 0;
419 WORD xkey, key_type, key;
420 KEYLP keylp;
421 BOOL extended = FALSE;
423 int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs);
425 Str[ascii_chars] = '\0';
426 dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, ascii chars=%u / %X / '%s'\n",
427 keysym, ascii_chars, Str[0], Str);
429 /* Ctrl-Alt-Return enters the debugger */
430 if ((keysym == XK_Return) && (event->type == KeyPress) &&
431 (event->state & ControlMask) && (event->state & Mod1Mask))
432 DEBUG_EnterDebugger();
434 xkey = LOWORD(keysym);
435 key_type = HIBYTE(xkey);
436 key = LOBYTE(xkey);
437 dprintf_key(stddeb," key_type=%X, key=%X\n", key_type, key);
439 if (key_type == 0xFF) /* non-character key */
441 if (key >= 0x08 && key <= 0x1B) /* special key */
442 vkey = special_key[key - 0x08];
443 else if (key >= 0x50 && key <= 0x57) /* cursor key */
444 vkey = cursor_key[key - 0x50];
445 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
446 vkey = misc_key[key - 0x60];
447 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
449 vkey = keypad_key[key - 0x7E];
450 extended = TRUE;
452 else if (key >= 0xBE && key <= 0xCD) /* function key */
454 vkey = function_key[key - 0xBE];
455 extended = TRUE;
457 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
458 vkey = modifier_key[key - 0xE1];
459 else if (key == 0xFF) /* DEL key */
460 vkey = VK_DELETE;
462 else if (key_type == 0) /* character key */
464 if ( isalnum(key) )
465 vkey = toupper(key); /* convert lower to uppercase */
466 else
467 vkey = 0xbe;
470 if (event->type == KeyPress)
472 if (!(KeyStateTable[vkey] & 0x80))
473 KeyStateTable[vkey] ^= 0x01;
474 KeyStateTable[vkey] |= 0x80;
475 keylp.lp1.count = 1;
476 keylp.lp1.code = LOBYTE(event->keycode) - 8;
477 keylp.lp1.extended = (extended ? 1 : 0);
478 keylp.lp1.reserved = (ascii_chars ? 1 : 0);
479 keylp.lp1.context = ( (event->state & Mod1Mask) ||
480 (KeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
481 keylp.lp1.previous = (KeyDown ? 0 : 1);
482 keylp.lp1.transition = 0;
483 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
484 vkey, keylp.lp2 );
485 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
486 hardware_event( KeyStateTable[VK_MENU] & 0x80 ? WM_SYSKEYDOWN : WM_KEYDOWN,
487 vkey, keylp.lp2,
488 event->x_root - desktopX, event->y_root - desktopY,
489 event->time, 0 );
490 KeyDown = TRUE;
492 /* Currently we use reserved field in the scan-code byte to
493 * make it possible for TranslateMessage to recognize character keys
494 * and get them from lastEventChar global variable.
496 * ToAscii should handle it.
499 if( ascii_chars ) lastEventChar = Str[0];
501 else
503 UINT sysKey = KeyStateTable[VK_MENU];
505 KeyStateTable[vkey] &= ~0x80;
506 keylp.lp1.count = 1;
507 keylp.lp1.code = LOBYTE(event->keycode) - 8;
508 keylp.lp1.extended = (extended ? 1 : 0);
509 keylp.lp1.reserved = 0;
510 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
511 keylp.lp1.previous = 1;
512 keylp.lp1.transition = 1;
513 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
514 vkey, keylp.lp2 );
515 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
516 hardware_event( sysKey & 0x80 ? WM_SYSKEYUP : WM_KEYUP,
517 vkey, keylp.lp2,
518 event->x_root - desktopX, event->y_root - desktopY,
519 event->time, 0 );
520 KeyDown = FALSE;
525 /***********************************************************************
526 * EVENT_MotionNotify
528 static void EVENT_MotionNotify( XMotionEvent *event )
530 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
531 event->x_root - desktopX, event->y_root - desktopY,
532 event->time, 0 );
536 /***********************************************************************
537 * EVENT_DummyMotionNotify
539 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
541 void EVENT_DummyMotionNotify(void)
543 Window root, child;
544 int rootX, rootY, childX, childY;
545 unsigned int state;
547 if (XQueryPointer( display, rootWindow, &root, &child,
548 &rootX, &rootY, &childX, &childY, &state ))
550 hardware_event(WM_MOUSEMOVE, EVENT_XStateToKeyState( state ), 0L,
551 rootX - desktopX, rootY - desktopY, GetTickCount(), 0 );
556 /***********************************************************************
557 * EVENT_ButtonPress
559 static void EVENT_ButtonPress( XButtonEvent *event )
561 static WORD messages[NB_BUTTONS] =
562 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
563 int buttonNum = event->button - 1;
565 if (buttonNum >= NB_BUTTONS) return;
566 MouseButtonsStates[buttonNum] = 0x8000;
567 AsyncMouseButtonsStates[buttonNum] = 0x8000;
568 hardware_event( messages[buttonNum],
569 EVENT_XStateToKeyState( event->state ), 0L,
570 event->x_root - desktopX, event->y_root - desktopY,
571 event->time, 0 );
575 /***********************************************************************
576 * EVENT_ButtonRelease
578 static void EVENT_ButtonRelease( XButtonEvent *event )
580 static const WORD messages[NB_BUTTONS] =
581 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
582 int buttonNum = event->button - 1;
584 if (buttonNum >= NB_BUTTONS) return;
585 MouseButtonsStates[buttonNum] = FALSE;
586 hardware_event( messages[buttonNum],
587 EVENT_XStateToKeyState( event->state ), 0L,
588 event->x_root - desktopX, event->y_root - desktopY,
589 event->time, 0 );
593 /**********************************************************************
594 * EVENT_FocusIn
596 static void EVENT_FocusIn (HWND hwnd, XFocusChangeEvent *event )
598 if (event->detail == NotifyPointer) return;
599 if (hwnd != GetActiveWindow()) WINPOS_ChangeActiveWindow( hwnd, FALSE );
600 if ((hwnd != GetFocus()) && !IsChild( hwnd, GetFocus())) SetFocus( hwnd );
604 /**********************************************************************
605 * EVENT_FocusOut
607 * Note: only top-level override-redirect windows get FocusOut events.
609 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
611 if (event->detail == NotifyPointer) return;
612 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
613 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 );
617 /**********************************************************************
618 * EVENT_ConfigureNotify
620 * The ConfigureNotify event is only selected on the desktop window
621 * and on top-level windows when the -managed flag is used.
623 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
625 /* FIXME: with -desktop xxx we get this event _before_ desktop
626 * window structure is created. WIN_GetDesktop() check is a hack.
629 if ( !WIN_GetDesktop() || hwnd == GetDesktopWindow())
631 desktopX = event->x;
632 desktopY = event->y;
634 else
636 /* Managed window; most of this code is shamelessly
637 * stolen from SetWindowPos - FIXME: outdated
640 WND *wndPtr;
641 WINDOWPOS16 *winpos;
642 RECT16 newWindowRect, newClientRect;
643 HRGN hrgnOldPos, hrgnNewPos;
645 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
647 dprintf_event(stddeb,"ConfigureNotify: invalid HWND %04x\n",hwnd);
648 return;
651 if (!(winpos = SEGPTR_NEW(WINDOWPOS16))) return;
653 /* Artificial messages - what is this for? */
654 SendMessage16(hwnd, WM_ENTERSIZEMOVE, 0, 0);
655 SendMessage16(hwnd, WM_EXITSIZEMOVE, 0, 0);
657 /* Fill WINDOWPOS struct */
658 winpos->flags = SWP_NOACTIVATE | SWP_NOZORDER;
659 winpos->hwnd = hwnd;
660 winpos->x = event->x;
661 winpos->y = event->y;
662 winpos->cx = event->width;
663 winpos->cy = event->height;
665 /* Check for unchanged attributes */
666 if(winpos->x == wndPtr->rectWindow.left &&
667 winpos->y == wndPtr->rectWindow.top)
668 winpos->flags |= SWP_NOMOVE;
669 if(winpos->cx == wndPtr->rectWindow.right - wndPtr->rectWindow.left &&
670 winpos->cy == wndPtr->rectWindow.bottom - wndPtr->rectWindow.top)
671 winpos->flags |= SWP_NOSIZE;
673 /* Send WM_WINDOWPOSCHANGING */
674 SendMessage16(hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)SEGPTR_GET(winpos));
676 /* Calculate new position and size */
677 newWindowRect.left = event->x;
678 newWindowRect.right = event->x + event->width;
679 newWindowRect.top = event->y;
680 newWindowRect.bottom = event->y + event->height;
682 WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
683 &wndPtr->rectWindow, &wndPtr->rectClient,
684 SEGPTR_GET(winpos), &newClientRect );
686 hrgnOldPos = CreateRectRgnIndirect16( &wndPtr->rectWindow );
687 hrgnNewPos = CreateRectRgnIndirect16( &newWindowRect );
688 CombineRgn( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
690 /* Set new size and position */
691 wndPtr->rectWindow = newWindowRect;
692 wndPtr->rectClient = newClientRect;
693 SendMessage16( hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)SEGPTR_GET(winpos));
694 SEGPTR_FREE(winpos);
696 /* full window drag leaves unrepainted garbage without this */
697 RedrawWindow32( 0, NULL, hrgnOldPos, RDW_INVALIDATE |
698 RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW );
699 DeleteObject(hrgnOldPos);
700 DeleteObject(hrgnNewPos);
705 /***********************************************************************
706 * EVENT_SelectionRequest
708 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event )
710 XSelectionEvent result;
711 Atom rprop = None;
712 Window request = event->requestor;
714 if(event->target == XA_STRING)
716 HANDLE hText;
717 LPSTR text;
719 rprop = event->property;
721 if(rprop == None) rprop = event->target;
723 if(event->selection!=XA_PRIMARY) rprop = None;
724 else if(!CLIPBOARD_IsPresent(CF_TEXT)) rprop = None;
725 else{
726 /* Don't worry if we can't open */
727 BOOL couldOpen=OpenClipboard( pWnd->hwndSelf );
728 hText=GetClipboardData(CF_TEXT);
729 text=GlobalLock16(hText);
730 XChangeProperty(display,request,rprop,XA_STRING,
731 8,PropModeReplace,text,strlen(text));
732 GlobalUnlock16(hText);
733 /* close only if we opened before */
734 if(couldOpen)CloseClipboard();
738 if(rprop==None)
739 dprintf_event(stddeb,"Request for %s ignored\n", XGetAtomName(display,event->target));
741 result.type=SelectionNotify;
742 result.display=display;
743 result.requestor=request;
744 result.selection=event->selection;
745 result.property=rprop;
746 result.target=event->target;
747 result.time=event->time;
748 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
752 /***********************************************************************
753 * EVENT_SelectionNotify
755 static void EVENT_SelectionNotify( XSelectionEvent *event )
757 if (event->selection != XA_PRIMARY) return;
758 if (event->target != XA_STRING) CLIPBOARD_ReadSelection( 0, None );
759 CLIPBOARD_ReadSelection( event->requestor, event->property );
763 /***********************************************************************
764 * EVENT_SelectionClear
766 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event )
768 if (event->selection != XA_PRIMARY) return;
769 CLIPBOARD_ReleaseSelection( pWnd->hwndSelf );
773 /**********************************************************************
774 * EVENT_ClientMessage
776 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event )
778 static Atom wmProtocols = None;
779 static Atom wmDeleteWindow = None;
781 if (wmProtocols == None)
782 wmProtocols = XInternAtom( display, "WM_PROTOCOLS", True );
783 if (wmDeleteWindow == None)
784 wmDeleteWindow = XInternAtom( display, "WM_DELETE_WINDOW", True );
786 if ((event->format != 32) || (event->message_type != wmProtocols) ||
787 (((Atom) event->data.l[0]) != wmDeleteWindow))
789 dprintf_event( stddeb, "unrecognized ClientMessage\n" );
790 return;
792 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 );
796 /**********************************************************************
797 * SetCapture (USER.18)
799 HWND SetCapture( HWND hwnd )
801 Window win;
802 HWND old_capture_wnd = captureWnd;
804 if (!hwnd)
806 ReleaseCapture();
807 return old_capture_wnd;
809 if (!(win = WIN_GetXWindow( hwnd ))) return 0;
810 if (XGrabPointer(display, win, False,
811 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
812 GrabModeAsync, GrabModeAsync,
813 None, None, CurrentTime ) == GrabSuccess)
815 dprintf_win(stddeb, "SetCapture: %04x\n", hwnd);
816 captureWnd = hwnd;
817 return old_capture_wnd;
819 else return 0;
823 /**********************************************************************
824 * ReleaseCapture (USER.19)
826 void ReleaseCapture()
828 if (captureWnd == 0) return;
829 XUngrabPointer( display, CurrentTime );
830 captureWnd = 0;
831 dprintf_win(stddeb, "ReleaseCapture\n");
834 /**********************************************************************
835 * GetCapture (USER.236)
837 HWND GetCapture()
839 return captureWnd;
843 /***********************************************************************
844 * GetMouseEventProc (USER.337)
846 FARPROC GetMouseEventProc(void)
848 HMODULE hmodule = GetModuleHandle("USER");
849 return MODULE_GetEntryPoint( hmodule,
850 MODULE_GetOrdinal( hmodule, "Mouse_Event" ) );
854 /***********************************************************************
855 * Mouse_Event (USER.299)
857 #ifndef WINELIB
858 void Mouse_Event( struct sigcontext_struct context )
860 /* Register values:
861 * AX = mouse event
862 * BX = horizontal displacement if AX & ME_MOVE
863 * CX = vertical displacement if AX & ME_MOVE
864 * DX = button state (?)
865 * SI = mouse event flags (?)
867 Window root, child;
868 int rootX, rootY, childX, childY;
869 unsigned int state;
871 if (AX_reg(&context) & ME_MOVE)
873 /* We have to actually move the cursor */
874 XWarpPointer( display, rootWindow, None, 0, 0, 0, 0,
875 (short)BX_reg(&context), (short)CX_reg(&context) );
876 return;
878 if (!XQueryPointer( display, rootWindow, &root, &child,
879 &rootX, &rootY, &childX, &childY, &state )) return;
880 if (AX_reg(&context) & ME_LDOWN)
881 hardware_event( WM_LBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
882 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
883 if (AX_reg(&context) & ME_LUP)
884 hardware_event( WM_LBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
885 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
886 if (AX_reg(&context) & ME_RDOWN)
887 hardware_event( WM_RBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
888 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
889 if (AX_reg(&context) & ME_RUP)
890 hardware_event( WM_RBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
891 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
893 #endif
896 /**********************************************************************
897 * EnableHardwareInput [USER.331]
899 BOOL EnableHardwareInput(BOOL bEnable)
901 BOOL bOldState = InputEnabled;
902 dprintf_event(stdnimp,"EMPTY STUB !!! EnableHardwareInput(%d);\n", bEnable);
903 InputEnabled = bEnable;
904 return (bOldState && !bEnable);