Release 960717
[wine/multimedia.git] / windows / event.c
blobe6a053b5ddb0fa1dd149679a9dee3695dfa43a77
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 <string.h>
12 #include <unistd.h>
13 #include <sys/time.h>
14 #include <sys/types.h>
15 #include <errno.h>
16 #include <X11/keysym.h>
17 #include <X11/Xlib.h>
18 #include <X11/Xresource.h>
19 #include <X11/Xutil.h>
20 #include <X11/Xatom.h>
22 #include "windows.h"
23 #include "gdi.h"
24 #include "heap.h"
25 #include "win.h"
26 #include "class.h"
27 #include "clipboard.h"
28 #include "debugger.h"
29 #include "message.h"
30 #include "module.h"
31 #include "options.h"
32 #include "queue.h"
33 #include "winpos.h"
34 #include "registers.h"
35 #include "stddebug.h"
36 #include "debug.h"
37 #include "dde_proc.h"
40 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
42 /* X context to associate a hwnd to an X window */
43 static XContext winContext = 0;
45 /* State variables */
46 BOOL MouseButtonsStates[NB_BUTTONS];
47 BOOL AsyncMouseButtonsStates[NB_BUTTONS];
48 BYTE KeyStateTable[256];
49 BYTE AsyncKeyStateTable[256];
52 WPARAM lastEventChar = 0; /* this will have to be changed once
53 * ToAscii starts working */
55 static HWND captureWnd = 0;
56 static BOOL InputEnabled = TRUE;
58 /* Keyboard translation tables */
59 static const int special_key[] =
61 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
62 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
63 0, 0, 0, VK_ESCAPE /* FF18 */
66 static const int cursor_key[] =
68 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
69 VK_NEXT, VK_END /* FF50 */
72 static const int misc_key[] =
74 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
75 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
78 static const int keypad_key[] =
80 VK_MENU, VK_NUMLOCK, /* FF7E */
81 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
82 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
83 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
84 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
85 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
86 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
87 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
88 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
89 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
90 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
93 static const int function_key[] =
95 VK_F1, VK_F2, /* FFBE */
96 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
97 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
100 static const int modifier_key[] =
102 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
103 0, 0, /* FFE1 */
104 0, VK_MENU, VK_MENU /* FFE8 */
107 typedef union
109 struct
111 unsigned long count : 16;
112 unsigned long code : 8;
113 unsigned long extended : 1;
114 unsigned long : 2;
115 unsigned long reserved : 2;
116 unsigned long context : 1;
117 unsigned long previous : 1;
118 unsigned long transition : 1;
119 } lp1;
120 unsigned long lp2;
121 } KEYLP;
123 static BOOL KeyDown = FALSE;
125 static const char * const event_names[] =
127 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
128 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
129 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
130 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
131 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
132 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
133 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
134 "ClientMessage", "MappingNotify"
137 /* Event handlers */
138 static void EVENT_key( XKeyEvent *event );
139 static void EVENT_ButtonPress( XButtonEvent *event );
140 static void EVENT_ButtonRelease( XButtonEvent *event );
141 static void EVENT_MotionNotify( XMotionEvent *event );
142 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event );
143 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
144 static void EVENT_Expose( WND *pWnd, XExposeEvent *event );
145 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event );
146 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
147 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event);
148 static void EVENT_SelectionNotify( XSelectionEvent *event);
149 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event);
150 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event );
153 /***********************************************************************
154 * EVENT_ProcessEvent
156 * Process an X event.
158 void EVENT_ProcessEvent( XEvent *event )
160 WND *pWnd;
162 if (XFindContext( display, ((XAnyEvent *)event)->window, winContext,
163 (char **)&pWnd ) != 0)
164 return; /* Not for a registered window */
166 dprintf_event( stddeb, "Got event %s for hwnd %04x\n",
167 event_names[event->type], pWnd->hwndSelf );
169 switch(event->type)
171 case KeyPress:
172 case KeyRelease:
173 EVENT_key( (XKeyEvent*)event );
174 break;
176 case ButtonPress:
177 EVENT_ButtonPress( (XButtonEvent*)event );
178 break;
180 case ButtonRelease:
181 EVENT_ButtonRelease( (XButtonEvent*)event );
182 break;
184 case MotionNotify:
185 /* Wine between two fast machines across the overloaded campus
186 ethernet gets very boged down in MotionEvents. The following
187 simply finds the last motion event in the queue and drops
188 the rest. On a good link events are servered before they build
189 up so this doesn't take place. On a slow link this may cause
190 problems if the event order is important. I'm not yet seen
191 of any problems. Jon 7/6/96.
193 while (XCheckTypedWindowEvent(display, ((XAnyEvent *)event)->window,
194 MotionNotify, event));
195 EVENT_MotionNotify( (XMotionEvent*)event );
196 break;
198 case FocusIn:
199 EVENT_FocusIn( pWnd->hwndSelf, (XFocusChangeEvent*)event );
200 break;
202 case FocusOut:
203 EVENT_FocusOut( pWnd->hwndSelf, (XFocusChangeEvent*)event );
204 break;
206 case Expose:
207 EVENT_Expose( pWnd, (XExposeEvent *)event );
208 break;
210 case GraphicsExpose:
211 EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
212 break;
214 case ConfigureNotify:
215 EVENT_ConfigureNotify( pWnd->hwndSelf, (XConfigureEvent*)event );
216 break;
218 case SelectionRequest:
219 EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event );
220 break;
222 case SelectionNotify:
223 EVENT_SelectionNotify( (XSelectionEvent *)event );
224 break;
226 case SelectionClear:
227 EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event );
228 break;
230 case ClientMessage:
231 EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event );
232 break;
234 case NoExpose:
235 break;
237 default:
238 dprintf_event(stddeb, "Unprocessed event %s for hwnd %04x\n",
239 event_names[event->type], pWnd->hwndSelf );
240 break;
245 /***********************************************************************
246 * EVENT_RegisterWindow
248 * Associate an X window to a HWND.
250 void EVENT_RegisterWindow( WND *pWnd )
252 if (!winContext) winContext = XUniqueContext();
253 XSaveContext( display, pWnd->window, winContext, (char *)pWnd );
257 /***********************************************************************
258 * EVENT_WaitXEvent
260 * Wait for an X event, optionally sleeping until one arrives.
261 * Return TRUE if an event is pending, FALSE on timeout or error
262 * (for instance lost connection with the server).
264 BOOL EVENT_WaitXEvent( BOOL sleep )
266 fd_set read_set;
267 struct timeval timeout;
268 XEvent event;
269 int fd = ConnectionNumber(display);
271 if (!XPending(display))
273 LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0;
275 FD_ZERO( &read_set );
276 FD_SET( fd, &read_set );
278 timeout.tv_usec = (maxWait % 1000) * 1000;
279 timeout.tv_sec = maxWait / 1000;
281 #ifdef CONFIG_IPC
282 sigsetjmp(env_wait_x, 1);
283 stop_wait_op= CONT;
285 if (DDE_GetRemoteMessage()) {
286 while(DDE_GetRemoteMessage())
288 return TRUE;
290 stop_wait_op = STOP_WAIT_X;
291 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
292 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
293 !XPending(display))
295 stop_wait_op = CONT;
296 TIMER_ExpireTimers();
297 return FALSE;
299 else stop_wait_op = CONT;
300 #else /* CONFIG_IPC */
301 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
303 /* Timeout or error */
304 TIMER_ExpireTimers();
305 return FALSE;
307 #endif /* CONFIG_IPC */
311 /* Process the event (and possibly others that occurred in the meantime) */
315 #ifdef CONFIG_IPC
316 if (DDE_GetRemoteMessage())
318 while(DDE_GetRemoteMessage()) ;
319 return TRUE;
321 #endif /* CONFIG_IPC */
323 XNextEvent( display, &event );
324 EVENT_ProcessEvent( &event );
326 while (XPending( display ));
327 return TRUE;
331 /***********************************************************************
332 * EVENT_Synchronize
334 * Synchronize with the X server. Should not be used too often.
336 void EVENT_Synchronize()
338 XEvent event;
340 XSync( display, False );
341 while (XPending( display ))
343 XNextEvent( display, &event );
344 EVENT_ProcessEvent( &event );
349 /***********************************************************************
350 * EVENT_XStateToKeyState
352 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
353 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
355 static WORD EVENT_XStateToKeyState( int state )
357 int kstate = 0;
359 if (state & Button1Mask) kstate |= MK_LBUTTON;
360 if (state & Button2Mask) kstate |= MK_MBUTTON;
361 if (state & Button3Mask) kstate |= MK_RBUTTON;
362 if (state & ShiftMask) kstate |= MK_SHIFT;
363 if (state & ControlMask) kstate |= MK_CONTROL;
364 return kstate;
368 /***********************************************************************
369 * EVENT_Expose
371 static void EVENT_Expose( WND *pWnd, XExposeEvent *event )
373 RECT32 rect;
375 /* Make position relative to client area instead of window */
376 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
377 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
378 rect.right = rect.left + event->width;
379 rect.bottom = rect.top + event->height;
381 RedrawWindow32( pWnd->hwndSelf, &rect, 0,
382 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
383 (event->count ? 0 : RDW_ERASENOW) );
387 /***********************************************************************
388 * EVENT_GraphicsExpose
390 * This is needed when scrolling area is partially obscured
391 * by non-Wine X window.
393 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
395 RECT32 rect;
397 /* Make position relative to client area instead of window */
398 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
399 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
400 rect.right = rect.left + event->width;
401 rect.bottom = rect.top + event->height;
403 RedrawWindow32( pWnd->hwndSelf, &rect, 0,
404 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
405 (event->count ? 0 : RDW_ERASENOW) );
409 /***********************************************************************
410 * EVENT_key
412 * Handle a X key event
414 static void EVENT_key( XKeyEvent *event )
416 char Str[24];
417 XComposeStatus cs;
418 KeySym keysym;
419 WORD vkey = 0;
420 WORD xkey, key_type, key;
421 KEYLP keylp;
422 BOOL extended = FALSE;
424 int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs);
426 Str[ascii_chars] = '\0';
427 dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, ascii chars=%u / %X / '%s'\n",
428 keysym, ascii_chars, Str[0], Str);
430 /* Ctrl-Alt-Return enters the debugger */
431 if ((keysym == XK_Return) && (event->type == KeyPress) &&
432 (event->state & ControlMask) && (event->state & Mod1Mask))
433 DEBUG_EnterDebugger();
435 xkey = LOWORD(keysym);
436 key_type = HIBYTE(xkey);
437 key = LOBYTE(xkey);
438 dprintf_key(stddeb," key_type=%X, key=%X\n", key_type, key);
440 if (key_type == 0xFF) /* non-character key */
442 if (key >= 0x08 && key <= 0x1B) /* special key */
443 vkey = special_key[key - 0x08];
444 else if (key >= 0x50 && key <= 0x57) /* cursor key */
445 vkey = cursor_key[key - 0x50];
446 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
447 vkey = misc_key[key - 0x60];
448 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
450 vkey = keypad_key[key - 0x7E];
451 extended = TRUE;
453 else if (key >= 0xBE && key <= 0xCD) /* function key */
455 vkey = function_key[key - 0xBE];
456 extended = TRUE;
458 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
459 vkey = modifier_key[key - 0xE1];
460 else if (key == 0xFF) /* DEL key */
461 vkey = VK_DELETE;
463 else if (key_type == 0) /* character key */
465 if ( isalnum(key) )
466 vkey = toupper(key); /* convert lc to uc */
467 else if ( isspace(key) )
468 vkey = key; /* XXX approximately */
469 else
470 switch (key) /* the rest... */
472 #define vkcase(k,val) case k: vkey = val; break;
473 #define vkcase2(k1,k2,val) case k1: case k2: vkey = val; break;
475 /* I wish I had a bit-paired keyboard! */
476 vkcase('!','1'); vkcase('@','2'); vkcase('#','3');
477 vkcase('$','4'); vkcase('%','5'); vkcase('^','6');
478 vkcase('&','7'); vkcase('*','8'); vkcase('(','9');
479 vkcase(')','0');
481 vkcase2('`','~',0xc0);
482 vkcase2('-','_',0xbd);
483 vkcase2('=','+',0xbb);
484 vkcase2('[','{',0xdb);
485 vkcase2(']','}',0xdd);
486 vkcase2(';',':',0xba);
487 vkcase2('\'','\"',0xde);
488 vkcase2(',','<',0xbc);
489 vkcase2('.','>',0xbe);
490 vkcase2('/','?',0xbf);
491 vkcase2('\\','|',0xdc);
492 #undef vkcase
493 #undef vkcase2
494 default:
495 fprintf( stderr, "Unknown key! Please report!\n" );
496 vkey = 0; /* whatever */
500 if (event->type == KeyPress)
502 if (!(KeyStateTable[vkey] & 0x80))
503 KeyStateTable[vkey] ^= 0x01;
504 KeyStateTable[vkey] |= 0x80;
505 keylp.lp1.count = 1;
506 keylp.lp1.code = LOBYTE(event->keycode) - 8;
507 keylp.lp1.extended = (extended ? 1 : 0);
508 keylp.lp1.reserved = (ascii_chars ? 1 : 0);
509 keylp.lp1.context = ( (event->state & Mod1Mask) ||
510 (KeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
511 keylp.lp1.previous = (KeyDown ? 0 : 1);
512 keylp.lp1.transition = 0;
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( KeyStateTable[VK_MENU] & 0x80 ? WM_SYSKEYDOWN : WM_KEYDOWN,
517 vkey, keylp.lp2,
518 event->x_root - desktopX, event->y_root - desktopY,
519 event->time, 0 );
520 KeyDown = TRUE;
522 /* Currently we use reserved field in the scan-code byte to
523 * make it possible for TranslateMessage to recognize character keys
524 * and get them from lastEventChar global variable.
526 * ToAscii should handle it.
529 if( ascii_chars ) lastEventChar = Str[0];
531 else
533 UINT sysKey = KeyStateTable[VK_MENU];
535 KeyStateTable[vkey] &= ~0x80;
536 keylp.lp1.count = 1;
537 keylp.lp1.code = LOBYTE(event->keycode) - 8;
538 keylp.lp1.extended = (extended ? 1 : 0);
539 keylp.lp1.reserved = 0;
540 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
541 keylp.lp1.previous = 1;
542 keylp.lp1.transition = 1;
543 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
544 vkey, keylp.lp2 );
545 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
546 hardware_event( sysKey & 0x80 ? WM_SYSKEYUP : WM_KEYUP,
547 vkey, keylp.lp2,
548 event->x_root - desktopX, event->y_root - desktopY,
549 event->time, 0 );
550 KeyDown = FALSE;
555 /***********************************************************************
556 * EVENT_MotionNotify
558 static void EVENT_MotionNotify( XMotionEvent *event )
560 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
561 event->x_root - desktopX, event->y_root - desktopY,
562 event->time, 0 );
566 /***********************************************************************
567 * EVENT_DummyMotionNotify
569 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
571 void EVENT_DummyMotionNotify(void)
573 Window root, child;
574 int rootX, rootY, childX, childY;
575 unsigned int state;
577 if (XQueryPointer( display, rootWindow, &root, &child,
578 &rootX, &rootY, &childX, &childY, &state ))
580 hardware_event(WM_MOUSEMOVE, EVENT_XStateToKeyState( state ), 0L,
581 rootX - desktopX, rootY - desktopY, GetTickCount(), 0 );
586 /***********************************************************************
587 * EVENT_ButtonPress
589 static void EVENT_ButtonPress( XButtonEvent *event )
591 static WORD messages[NB_BUTTONS] =
592 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
593 int buttonNum = event->button - 1;
595 if (buttonNum >= NB_BUTTONS) return;
596 MouseButtonsStates[buttonNum] = 0x8000;
597 AsyncMouseButtonsStates[buttonNum] = 0x8000;
598 hardware_event( messages[buttonNum],
599 EVENT_XStateToKeyState( event->state ), 0L,
600 event->x_root - desktopX, event->y_root - desktopY,
601 event->time, 0 );
605 /***********************************************************************
606 * EVENT_ButtonRelease
608 static void EVENT_ButtonRelease( XButtonEvent *event )
610 static const WORD messages[NB_BUTTONS] =
611 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
612 int buttonNum = event->button - 1;
614 if (buttonNum >= NB_BUTTONS) return;
615 MouseButtonsStates[buttonNum] = FALSE;
616 hardware_event( messages[buttonNum],
617 EVENT_XStateToKeyState( event->state ), 0L,
618 event->x_root - desktopX, event->y_root - desktopY,
619 event->time, 0 );
623 /**********************************************************************
624 * EVENT_FocusIn
626 static void EVENT_FocusIn (HWND hwnd, XFocusChangeEvent *event )
628 if (event->detail == NotifyPointer) return;
629 if (hwnd != GetActiveWindow()) WINPOS_ChangeActiveWindow( hwnd, FALSE );
630 if ((hwnd != GetFocus()) && !IsChild( hwnd, GetFocus())) SetFocus( hwnd );
634 /**********************************************************************
635 * EVENT_FocusOut
637 * Note: only top-level override-redirect windows get FocusOut events.
639 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
641 if (event->detail == NotifyPointer) return;
642 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
643 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 );
647 /**********************************************************************
648 * EVENT_ConfigureNotify
650 * The ConfigureNotify event is only selected on the desktop window
651 * and on top-level windows when the -managed flag is used.
653 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
655 /* FIXME: with -desktop xxx we get this event _before_ desktop
656 * window structure is created. WIN_GetDesktop() check is a hack.
659 if ( !WIN_GetDesktop() || hwnd == GetDesktopWindow())
661 desktopX = event->x;
662 desktopY = event->y;
664 else
666 /* Managed window; most of this code is shamelessly
667 * stolen from SetWindowPos - FIXME: outdated
670 WND *wndPtr;
671 WINDOWPOS16 *winpos;
672 RECT16 newWindowRect, newClientRect;
673 HRGN hrgnOldPos, hrgnNewPos;
675 if (!(wndPtr = WIN_FindWndPtr( hwnd )))
677 dprintf_event(stddeb,"ConfigureNotify: invalid HWND %04x\n",hwnd);
678 return;
681 if (!(winpos = SEGPTR_NEW(WINDOWPOS16))) return;
683 /* Artificial messages - what is this for? */
684 SendMessage16(hwnd, WM_ENTERSIZEMOVE, 0, 0);
685 SendMessage16(hwnd, WM_EXITSIZEMOVE, 0, 0);
687 /* Fill WINDOWPOS struct */
688 winpos->flags = SWP_NOACTIVATE | SWP_NOZORDER;
689 winpos->hwnd = hwnd;
690 winpos->x = event->x;
691 winpos->y = event->y;
692 winpos->cx = event->width;
693 winpos->cy = event->height;
695 /* Check for unchanged attributes */
696 if(winpos->x == wndPtr->rectWindow.left &&
697 winpos->y == wndPtr->rectWindow.top)
698 winpos->flags |= SWP_NOMOVE;
699 if(winpos->cx == wndPtr->rectWindow.right - wndPtr->rectWindow.left &&
700 winpos->cy == wndPtr->rectWindow.bottom - wndPtr->rectWindow.top)
701 winpos->flags |= SWP_NOSIZE;
703 /* Send WM_WINDOWPOSCHANGING */
704 SendMessage16(hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)SEGPTR_GET(winpos));
706 /* Calculate new position and size */
707 newWindowRect.left = event->x;
708 newWindowRect.right = event->x + event->width;
709 newWindowRect.top = event->y;
710 newWindowRect.bottom = event->y + event->height;
712 WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
713 &wndPtr->rectWindow, &wndPtr->rectClient,
714 SEGPTR_GET(winpos), &newClientRect );
716 hrgnOldPos = CreateRectRgnIndirect16( &wndPtr->rectWindow );
717 hrgnNewPos = CreateRectRgnIndirect16( &newWindowRect );
718 CombineRgn( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
720 /* Set new size and position */
721 wndPtr->rectWindow = newWindowRect;
722 wndPtr->rectClient = newClientRect;
723 SendMessage16( hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)SEGPTR_GET(winpos));
724 SEGPTR_FREE(winpos);
726 /* full window drag leaves unrepainted garbage without this */
727 RedrawWindow32( 0, NULL, hrgnOldPos, RDW_INVALIDATE |
728 RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW );
729 DeleteObject(hrgnOldPos);
730 DeleteObject(hrgnNewPos);
735 /***********************************************************************
736 * EVENT_SelectionRequest
738 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event )
740 XSelectionEvent result;
741 Atom rprop = None;
742 Window request = event->requestor;
744 if(event->target == XA_STRING)
746 HANDLE hText;
747 LPSTR text;
749 rprop = event->property;
751 if(rprop == None) rprop = event->target;
753 if(event->selection!=XA_PRIMARY) rprop = None;
754 else if(!CLIPBOARD_IsPresent(CF_TEXT)) rprop = None;
755 else{
756 /* Don't worry if we can't open */
757 BOOL couldOpen=OpenClipboard( pWnd->hwndSelf );
758 hText=GetClipboardData(CF_TEXT);
759 text=GlobalLock16(hText);
760 XChangeProperty(display,request,rprop,XA_STRING,
761 8,PropModeReplace,text,strlen(text));
762 GlobalUnlock16(hText);
763 /* close only if we opened before */
764 if(couldOpen)CloseClipboard();
768 if(rprop==None)
769 dprintf_event(stddeb,"Request for %s ignored\n", XGetAtomName(display,event->target));
771 result.type=SelectionNotify;
772 result.display=display;
773 result.requestor=request;
774 result.selection=event->selection;
775 result.property=rprop;
776 result.target=event->target;
777 result.time=event->time;
778 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
782 /***********************************************************************
783 * EVENT_SelectionNotify
785 static void EVENT_SelectionNotify( XSelectionEvent *event )
787 if (event->selection != XA_PRIMARY) return;
788 if (event->target != XA_STRING) CLIPBOARD_ReadSelection( 0, None );
789 CLIPBOARD_ReadSelection( event->requestor, event->property );
793 /***********************************************************************
794 * EVENT_SelectionClear
796 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event )
798 if (event->selection != XA_PRIMARY) return;
799 CLIPBOARD_ReleaseSelection( pWnd->hwndSelf );
803 /**********************************************************************
804 * EVENT_ClientMessage
806 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event )
808 static Atom wmProtocols = None;
809 static Atom wmDeleteWindow = None;
811 if (wmProtocols == None)
812 wmProtocols = XInternAtom( display, "WM_PROTOCOLS", True );
813 if (wmDeleteWindow == None)
814 wmDeleteWindow = XInternAtom( display, "WM_DELETE_WINDOW", True );
816 if ((event->format != 32) || (event->message_type != wmProtocols) ||
817 (((Atom) event->data.l[0]) != wmDeleteWindow))
819 dprintf_event( stddeb, "unrecognized ClientMessage\n" );
820 return;
822 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 );
826 /**********************************************************************
827 * SetCapture (USER.18)
829 HWND SetCapture( HWND hwnd )
831 Window win;
832 HWND old_capture_wnd = captureWnd;
834 if (!hwnd)
836 ReleaseCapture();
837 return old_capture_wnd;
839 if (!(win = WIN_GetXWindow( hwnd ))) return 0;
840 if (XGrabPointer(display, win, False,
841 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
842 GrabModeAsync, GrabModeAsync,
843 None, None, CurrentTime ) == GrabSuccess)
845 dprintf_win(stddeb, "SetCapture: %04x\n", hwnd);
846 captureWnd = hwnd;
847 return old_capture_wnd;
849 else return 0;
853 /**********************************************************************
854 * ReleaseCapture (USER.19)
856 void ReleaseCapture()
858 if (captureWnd == 0) return;
859 XUngrabPointer( display, CurrentTime );
860 captureWnd = 0;
861 dprintf_win(stddeb, "ReleaseCapture\n");
864 /**********************************************************************
865 * GetCapture (USER.236)
867 HWND GetCapture()
869 return captureWnd;
873 /***********************************************************************
874 * GetMouseEventProc (USER.337)
876 FARPROC16 GetMouseEventProc(void)
878 HMODULE16 hmodule = GetModuleHandle("USER");
879 return MODULE_GetEntryPoint( hmodule,
880 MODULE_GetOrdinal( hmodule, "Mouse_Event" ) );
884 /***********************************************************************
885 * Mouse_Event (USER.299)
887 #ifndef WINELIB
888 void Mouse_Event( SIGCONTEXT *context )
890 /* Register values:
891 * AX = mouse event
892 * BX = horizontal displacement if AX & ME_MOVE
893 * CX = vertical displacement if AX & ME_MOVE
894 * DX = button state (?)
895 * SI = mouse event flags (?)
897 Window root, child;
898 int rootX, rootY, childX, childY;
899 unsigned int state;
901 if (AX_reg(context) & ME_MOVE)
903 /* We have to actually move the cursor */
904 XWarpPointer( display, rootWindow, None, 0, 0, 0, 0,
905 (short)BX_reg(context), (short)CX_reg(context) );
906 return;
908 if (!XQueryPointer( display, rootWindow, &root, &child,
909 &rootX, &rootY, &childX, &childY, &state )) return;
910 if (AX_reg(context) & ME_LDOWN)
911 hardware_event( WM_LBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
912 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
913 if (AX_reg(context) & ME_LUP)
914 hardware_event( WM_LBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
915 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
916 if (AX_reg(context) & ME_RDOWN)
917 hardware_event( WM_RBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
918 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
919 if (AX_reg(context) & ME_RUP)
920 hardware_event( WM_RBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
921 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
923 #endif
926 /**********************************************************************
927 * EnableHardwareInput [USER.331]
929 BOOL EnableHardwareInput(BOOL bEnable)
931 BOOL bOldState = InputEnabled;
932 dprintf_event(stdnimp,"EMPTY STUB !!! EnableHardwareInput(%d);\n", bEnable);
933 InputEnabled = bEnable;
934 return (bOldState && !bEnable);