Release 960928
[wine/multimedia.git] / windows / event.c
blob77532ea780581798aeef1ca47051d1bf6f482969
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 "queue.h"
26 #include "win.h"
27 #include "class.h"
28 #include "clipboard.h"
29 #include "debugger.h"
30 #include "message.h"
31 #include "module.h"
32 #include "options.h"
33 #include "queue.h"
34 #include "winpos.h"
35 #include "registers.h"
36 #include "xmalloc.h"
37 #include "stddebug.h"
38 #include "debug.h"
39 #include "dde_proc.h"
41 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
43 /* X context to associate a hwnd to an X window */
44 static XContext winContext = 0;
46 /* State variables */
47 BOOL MouseButtonsStates[NB_BUTTONS];
48 BOOL AsyncMouseButtonsStates[NB_BUTTONS];
49 BYTE KeyStateTable[256];
50 BYTE AsyncKeyStateTable[256];
53 WPARAM lastEventChar = 0; /* this will have to be changed once
54 * ToAscii starts working */
56 static HWND32 captureWnd = 0;
57 static BOOL32 InputEnabled = TRUE;
59 /* Keyboard translation tables */
60 static const int special_key[] =
62 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
63 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
64 0, 0, 0, VK_ESCAPE /* FF18 */
67 static const int cursor_key[] =
69 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
70 VK_NEXT, VK_END /* FF50 */
73 static const int misc_key[] =
75 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
76 VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */
79 static const int keypad_key[] =
81 VK_MENU, VK_NUMLOCK, /* FF7E */
82 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
83 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
84 0, 0, 0, 0, 0, 0, 0, 0, /* FF90 */
85 0, 0, 0, 0, 0, 0, 0, 0, /* FF98 */
86 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
87 0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
88 VK_DECIMAL, VK_DIVIDE, /* FFA8 */
89 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
90 VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
91 VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
94 static const int function_key[] =
96 VK_F1, VK_F2, /* FFBE */
97 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
98 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
101 static const int modifier_key[] =
103 VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
104 0, 0, /* FFE1 */
105 0, VK_MENU, VK_MENU /* FFE8 */
108 typedef union
110 struct
112 unsigned long count : 16;
113 unsigned long code : 8;
114 unsigned long extended : 1;
115 unsigned long : 2;
116 unsigned long reserved : 2;
117 unsigned long context : 1;
118 unsigned long previous : 1;
119 unsigned long transition : 1;
120 } lp1;
121 unsigned long lp2;
122 } KEYLP;
124 static BOOL KeyDown = FALSE;
126 static const char * const event_names[] =
128 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
129 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
130 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
131 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
132 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
133 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
134 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
135 "ClientMessage", "MappingNotify"
138 /* Event handlers */
139 static void EVENT_key( XKeyEvent *event );
140 static void EVENT_ButtonPress( XButtonEvent *event );
141 static void EVENT_ButtonRelease( XButtonEvent *event );
142 static void EVENT_MotionNotify( XMotionEvent *event );
143 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event );
144 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
145 static void EVENT_Expose( WND *pWnd, XExposeEvent *event );
146 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event );
147 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
148 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event);
149 static void EVENT_SelectionNotify( XSelectionEvent *event);
150 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event);
151 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event );
152 static void EVENT_MapNotify( HWND hwnd, XMapEvent *event );
154 /* Usable only with OLVWM - compile option perhaps?
155 static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event );
158 /***********************************************************************
159 * EVENT_ProcessEvent
161 * Process an X event.
163 void EVENT_ProcessEvent( XEvent *event )
165 WND *pWnd;
167 if (XFindContext( display, ((XAnyEvent *)event)->window, winContext,
168 (char **)&pWnd ) != 0)
169 return; /* Not for a registered window */
171 dprintf_event( stddeb, "Got event %s for hwnd %04x\n",
172 event_names[event->type], pWnd->hwndSelf );
174 switch(event->type)
176 case KeyPress:
177 case KeyRelease:
178 if (InputEnabled)
179 EVENT_key( (XKeyEvent*)event );
180 break;
182 case ButtonPress:
183 if (InputEnabled)
184 EVENT_ButtonPress( (XButtonEvent*)event );
185 break;
187 case ButtonRelease:
188 if (InputEnabled)
189 EVENT_ButtonRelease( (XButtonEvent*)event );
190 break;
192 case MotionNotify:
193 /* Wine between two fast machines across the overloaded campus
194 ethernet gets very boged down in MotionEvents. The following
195 simply finds the last motion event in the queue and drops
196 the rest. On a good link events are servered before they build
197 up so this doesn't take place. On a slow link this may cause
198 problems if the event order is important. I'm not yet seen
199 of any problems. Jon 7/6/96.
201 if (InputEnabled)
203 while (XCheckTypedWindowEvent(display,((XAnyEvent *)event)->window,
204 MotionNotify, event));
205 EVENT_MotionNotify( (XMotionEvent*)event );
207 break;
209 case FocusIn:
210 EVENT_FocusIn( pWnd->hwndSelf, (XFocusChangeEvent*)event );
211 break;
213 case FocusOut:
214 EVENT_FocusOut( pWnd->hwndSelf, (XFocusChangeEvent*)event );
215 break;
217 case Expose:
218 EVENT_Expose( pWnd, (XExposeEvent *)event );
219 break;
221 case GraphicsExpose:
222 EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
223 break;
225 case ConfigureNotify:
226 EVENT_ConfigureNotify( pWnd->hwndSelf, (XConfigureEvent*)event );
227 break;
229 case SelectionRequest:
230 EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event );
231 break;
233 case SelectionNotify:
234 EVENT_SelectionNotify( (XSelectionEvent *)event );
235 break;
237 case SelectionClear:
238 EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event );
239 break;
241 case ClientMessage:
242 EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event );
243 break;
245 /* case EnterNotify:
246 * EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
247 * break;
249 case NoExpose:
250 break;
252 /* We get all these because of StructureNotifyMask. */
253 case UnmapNotify:
254 case CirculateNotify:
255 case CreateNotify:
256 case DestroyNotify:
257 case GravityNotify:
258 case ReparentNotify:
259 break;
261 case MapNotify:
262 EVENT_MapNotify( pWnd->hwndSelf, (XMapEvent *)event );
263 break;
265 default:
266 dprintf_event(stddeb, "Unprocessed event %s for hwnd %04x\n",
267 event_names[event->type], pWnd->hwndSelf );
268 break;
273 /***********************************************************************
274 * EVENT_RegisterWindow
276 * Associate an X window to a HWND.
278 void EVENT_RegisterWindow( WND *pWnd )
280 if (!winContext) winContext = XUniqueContext();
281 XSaveContext( display, pWnd->window, winContext, (char *)pWnd );
285 /***********************************************************************
286 * EVENT_WaitXEvent
288 * Wait for an X event, optionally sleeping until one arrives.
289 * Return TRUE if an event is pending, FALSE on timeout or error
290 * (for instance lost connection with the server).
292 BOOL32 EVENT_WaitXEvent( BOOL32 sleep, BOOL32 peek )
294 fd_set read_set;
295 struct timeval timeout;
296 XEvent event;
297 int fd = ConnectionNumber(display);
299 if (!XPending(display))
301 LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0;
303 FD_ZERO( &read_set );
304 FD_SET( fd, &read_set );
306 timeout.tv_usec = (maxWait % 1000) * 1000;
307 timeout.tv_sec = maxWait / 1000;
309 #ifdef CONFIG_IPC
310 sigsetjmp(env_wait_x, 1);
311 stop_wait_op= CONT;
313 if (DDE_GetRemoteMessage()) {
314 while(DDE_GetRemoteMessage())
316 return TRUE;
318 stop_wait_op = STOP_WAIT_X;
319 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
320 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
321 !XPending(display))
323 stop_wait_op = CONT;
324 TIMER_ExpireTimers();
325 return FALSE;
327 else stop_wait_op = CONT;
328 #else /* CONFIG_IPC */
329 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
331 /* Timeout or error */
332 TIMER_ExpireTimers();
333 return FALSE;
335 #endif /* CONFIG_IPC */
339 /* Process the event (and possibly others that occurred in the meantime) */
344 #ifdef CONFIG_IPC
345 if (DDE_GetRemoteMessage())
347 while(DDE_GetRemoteMessage()) ;
348 return TRUE;
350 #endif /* CONFIG_IPC */
352 XNextEvent( display, &event );
354 if( peek )
356 WND* pWnd;
357 MESSAGEQUEUE* pQ;
359 if( XFindContext( display, ((XAnyEvent *)&event)->window, winContext, (char **)&pWnd)
360 || event.type == NoExpose )
361 continue;
363 /* check for the "safe" hardware events */
365 if( event.type == MotionNotify ||
366 event.type == ButtonPress || event.type == ButtonRelease ||
367 event.type == KeyPress || event.type == KeyRelease ||
368 event.type == SelectionRequest || event.type == SelectionClear )
370 EVENT_ProcessEvent( &event );
371 continue;
374 if( pWnd )
375 if( (pQ = (MESSAGEQUEUE*)GlobalLock16(pWnd->hmemTaskQ)) )
377 pQ->flags |= QUEUE_FLAG_XEVENT;
378 PostEvent(pQ->hTask);
379 XPutBackEvent(display, &event);
380 break;
383 else
384 EVENT_ProcessEvent( &event );
386 while (XPending( display ));
387 return TRUE;
391 /***********************************************************************
392 * EVENT_Synchronize
394 * Synchronize with the X server. Should not be used too often.
396 void EVENT_Synchronize()
398 XEvent event;
400 XSync( display, False );
401 while (XPending( display ))
403 XNextEvent( display, &event );
404 EVENT_ProcessEvent( &event );
409 /***********************************************************************
410 * EVENT_XStateToKeyState
412 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
413 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
415 static WORD EVENT_XStateToKeyState( int state )
417 int kstate = 0;
419 if (state & Button1Mask) kstate |= MK_LBUTTON;
420 if (state & Button2Mask) kstate |= MK_MBUTTON;
421 if (state & Button3Mask) kstate |= MK_RBUTTON;
422 if (state & ShiftMask) kstate |= MK_SHIFT;
423 if (state & ControlMask) kstate |= MK_CONTROL;
424 return kstate;
428 /***********************************************************************
429 * EVENT_Expose
431 static void EVENT_Expose( WND *pWnd, XExposeEvent *event )
433 RECT32 rect;
435 /* Make position relative to client area instead of window */
436 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
437 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
438 rect.right = rect.left + event->width;
439 rect.bottom = rect.top + event->height;
441 PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
442 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
443 (event->count ? 0 : RDW_ERASENOW), 0 );
447 /***********************************************************************
448 * EVENT_GraphicsExpose
450 * This is needed when scrolling area is partially obscured
451 * by non-Wine X window.
453 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
455 RECT32 rect;
457 /* Make position relative to client area instead of window */
458 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
459 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
460 rect.right = rect.left + event->width;
461 rect.bottom = rect.top + event->height;
463 PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
464 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
465 (event->count ? 0 : RDW_ERASENOW), 0 );
469 /***********************************************************************
470 * EVENT_key
472 * Handle a X key event
474 static void EVENT_key( XKeyEvent *event )
476 char Str[24];
477 XComposeStatus cs;
478 KeySym keysym;
479 WORD vkey = 0;
480 WORD xkey, key_type, key;
481 KEYLP keylp;
482 BOOL extended = FALSE;
484 int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs);
486 Str[ascii_chars] = '\0';
487 dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, ascii chars=%u / %X / '%s'\n",
488 keysym, ascii_chars, Str[0], Str);
490 /* Ctrl-Alt-Return enters the debugger */
491 if ((keysym == XK_Return) && (event->type == KeyPress) &&
492 (event->state & ControlMask) && (event->state & Mod1Mask))
493 DEBUG_EnterDebugger();
495 xkey = LOWORD(keysym);
496 key_type = HIBYTE(xkey);
497 key = LOBYTE(xkey);
498 dprintf_key(stddeb," key_type=%X, key=%X\n", key_type, key);
500 if (key_type == 0xFF) /* non-character key */
502 if (key >= 0x08 && key <= 0x1B) /* special key */
503 vkey = special_key[key - 0x08];
504 else if (key >= 0x50 && key <= 0x57) /* cursor key */
505 vkey = cursor_key[key - 0x50];
506 else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */
507 vkey = misc_key[key - 0x60];
508 else if (key >= 0x7E && key <= 0xB9) /* keypad key */
510 vkey = keypad_key[key - 0x7E];
511 extended = TRUE;
513 else if (key >= 0xBE && key <= 0xCD) /* function key */
515 vkey = function_key[key - 0xBE];
516 extended = TRUE;
518 else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
519 vkey = modifier_key[key - 0xE1];
520 else if (key == 0xFF) /* DEL key */
521 vkey = VK_DELETE;
523 else if (key_type == 0) /* character key */
525 if ( isalnum(key) )
526 vkey = toupper(key); /* convert lc to uc */
527 else if ( isspace(key) )
528 vkey = key; /* XXX approximately */
529 else
530 switch (key) /* the rest... */
532 #define vkcase(k,val) case k: vkey = val; break;
533 #define vkcase2(k1,k2,val) case k1: case k2: vkey = val; break;
535 /* I wish I had a bit-paired keyboard! */
536 vkcase('!','1'); vkcase('@','2'); vkcase('#','3');
537 vkcase('$','4'); vkcase('%','5'); vkcase('^','6');
538 vkcase('&','7'); vkcase('*','8'); vkcase('(','9');
539 vkcase(')','0');
541 vkcase2('`','~',0xc0);
542 vkcase2('-','_',0xbd);
543 vkcase2('=','+',0xbb);
544 vkcase2('[','{',0xdb);
545 vkcase2(']','}',0xdd);
546 vkcase2(';',':',0xba);
547 vkcase2('\'','\"',0xde);
548 vkcase2(',','<',0xbc);
549 vkcase2('.','>',0xbe);
550 vkcase2('/','?',0xbf);
551 vkcase2('\\','|',0xdc);
552 #undef vkcase
553 #undef vkcase2
554 default:
555 fprintf( stderr, "Unknown key! Please report!\n" );
556 vkey = 0; /* whatever */
560 if (event->type == KeyPress)
562 if (!(KeyStateTable[vkey] & 0x80))
563 KeyStateTable[vkey] ^= 0x01;
564 KeyStateTable[vkey] |= 0x80;
565 keylp.lp1.count = 1;
566 keylp.lp1.code = LOBYTE(event->keycode) - 8;
567 keylp.lp1.extended = (extended ? 1 : 0);
568 keylp.lp1.reserved = (ascii_chars ? 1 : 0);
569 keylp.lp1.context = ( (event->state & Mod1Mask) ||
570 (KeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
571 keylp.lp1.previous = (KeyDown ? 0 : 1);
572 keylp.lp1.transition = 0;
573 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
574 vkey, keylp.lp2 );
575 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
576 hardware_event( KeyStateTable[VK_MENU] & 0x80 ? WM_SYSKEYDOWN : WM_KEYDOWN,
577 vkey, keylp.lp2,
578 event->x_root - desktopX, event->y_root - desktopY,
579 event->time - MSG_WineStartTicks, 0 );
580 KeyDown = TRUE;
582 /* Currently we use reserved field in the scan-code byte to
583 * make it possible for TranslateMessage to recognize character keys
584 * and get them from lastEventChar global variable.
586 * ToAscii should handle it.
589 if( ascii_chars ) lastEventChar = Str[0];
591 else
593 UINT sysKey = KeyStateTable[VK_MENU];
595 KeyStateTable[vkey] &= ~0x80;
596 keylp.lp1.count = 1;
597 keylp.lp1.code = LOBYTE(event->keycode) - 8;
598 keylp.lp1.extended = (extended ? 1 : 0);
599 keylp.lp1.reserved = 0;
600 keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
601 keylp.lp1.previous = 1;
602 keylp.lp1.transition = 1;
603 dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
604 vkey, keylp.lp2 );
605 dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
606 hardware_event( sysKey & 0x80 ? WM_SYSKEYUP : WM_KEYUP,
607 vkey, keylp.lp2,
608 event->x_root - desktopX, event->y_root - desktopY,
609 event->time - MSG_WineStartTicks, 0 );
610 KeyDown = FALSE;
615 /***********************************************************************
616 * EVENT_MotionNotify
618 static void EVENT_MotionNotify( XMotionEvent *event )
620 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
621 event->x_root - desktopX, event->y_root - desktopY,
622 event->time - MSG_WineStartTicks, 0 );
626 /***********************************************************************
627 * EVENT_DummyMotionNotify
629 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
631 void EVENT_DummyMotionNotify(void)
633 Window root, child;
634 int rootX, rootY, childX, childY;
635 unsigned int state;
637 if (XQueryPointer( display, rootWindow, &root, &child,
638 &rootX, &rootY, &childX, &childY, &state ))
640 hardware_event(WM_MOUSEMOVE, EVENT_XStateToKeyState( state ), 0L,
641 rootX - desktopX, rootY - desktopY, GetTickCount(), 0 );
646 /***********************************************************************
647 * EVENT_ButtonPress
649 static void EVENT_ButtonPress( XButtonEvent *event )
651 static WORD messages[NB_BUTTONS] =
652 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
653 int buttonNum = event->button - 1;
655 if (buttonNum >= NB_BUTTONS) return;
656 MouseButtonsStates[buttonNum] = 0x8000;
657 AsyncMouseButtonsStates[buttonNum] = 0x8000;
658 hardware_event( messages[buttonNum],
659 EVENT_XStateToKeyState( event->state ), 0L,
660 event->x_root - desktopX, event->y_root - desktopY,
661 event->time - MSG_WineStartTicks, 0 );
665 /***********************************************************************
666 * EVENT_ButtonRelease
668 static void EVENT_ButtonRelease( XButtonEvent *event )
670 static const WORD messages[NB_BUTTONS] =
671 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
672 int buttonNum = event->button - 1;
674 if (buttonNum >= NB_BUTTONS) return;
675 MouseButtonsStates[buttonNum] = FALSE;
676 hardware_event( messages[buttonNum],
677 EVENT_XStateToKeyState( event->state ), 0L,
678 event->x_root - desktopX, event->y_root - desktopY,
679 event->time - MSG_WineStartTicks, 0 );
683 /**********************************************************************
684 * EVENT_FocusIn
686 static void EVENT_FocusIn (HWND hwnd, XFocusChangeEvent *event )
688 if (event->detail == NotifyPointer) return;
689 if (hwnd != GetActiveWindow()) WINPOS_ChangeActiveWindow( hwnd, FALSE );
690 if ((hwnd != GetFocus32()) && !IsChild( hwnd, GetFocus32()))
691 SetFocus32( hwnd );
695 /**********************************************************************
696 * EVENT_FocusOut
698 * Note: only top-level override-redirect windows get FocusOut events.
700 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
702 if (event->detail == NotifyPointer) return;
703 if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
704 if ((hwnd == GetFocus32()) || IsChild( hwnd, GetFocus32()))
705 SetFocus32( 0 );
709 /**********************************************************************
710 * EVENT_ConfigureNotify
712 * The ConfigureNotify event is only selected on the desktop window
713 * and on top-level windows when the -managed flag is used.
715 static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
717 /* FIXME: with -desktop xxx we get this event _before_ desktop
718 * window structure is created. WIN_GetDesktop() check is a hack.
721 if ( !WIN_GetDesktop() || hwnd == GetDesktopWindow32())
723 desktopX = event->x;
724 desktopY = event->y;
726 else
728 WND *wndPtr;
729 WINDOWPOS16 *winpos;
730 RECT16 newWindowRect, newClientRect;
731 HRGN hrgnOldPos, hrgnNewPos;
733 if (!(wndPtr = WIN_FindWndPtr( hwnd )) ||
734 !(wndPtr->flags & WIN_MANAGED) )
735 return;
737 if (!(winpos = SEGPTR_NEW(WINDOWPOS16))) return;
739 /* XTranslateCoordinates(display, event->window, rootWindow,
740 event->x, event->y, &event->x, &event->y, &child);
743 /* Fill WINDOWPOS struct */
744 winpos->flags = SWP_NOACTIVATE | SWP_NOZORDER;
745 winpos->hwnd = hwnd;
746 winpos->x = event->x;
747 winpos->y = event->y;
748 winpos->cx = event->width;
749 winpos->cy = event->height;
751 /* Check for unchanged attributes */
752 if(winpos->x == wndPtr->rectWindow.left &&
753 winpos->y == wndPtr->rectWindow.top)
754 winpos->flags |= SWP_NOMOVE;
755 if(winpos->cx == wndPtr->rectWindow.right - wndPtr->rectWindow.left &&
756 winpos->cy == wndPtr->rectWindow.bottom - wndPtr->rectWindow.top)
757 winpos->flags |= SWP_NOSIZE;
759 /* Send WM_WINDOWPOSCHANGING */
760 SendMessage16(hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)SEGPTR_GET(winpos));
762 /* Calculate new position and size */
763 newWindowRect.left = event->x;
764 newWindowRect.right = event->x + event->width;
765 newWindowRect.top = event->y;
766 newWindowRect.bottom = event->y + event->height;
768 WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
769 &wndPtr->rectWindow, &wndPtr->rectClient,
770 SEGPTR_GET(winpos), &newClientRect );
772 hrgnOldPos = CreateRectRgnIndirect16( &wndPtr->rectWindow );
773 hrgnNewPos = CreateRectRgnIndirect16( &newWindowRect );
774 CombineRgn( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
776 /* Set new size and position */
777 wndPtr->rectWindow = newWindowRect;
778 wndPtr->rectClient = newClientRect;
779 SendMessage16( hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)SEGPTR_GET(winpos));
780 SEGPTR_FREE(winpos);
782 /* full window drag leaves unrepainted garbage without this */
783 PAINT_RedrawWindow( 0, NULL, hrgnOldPos, RDW_INVALIDATE |
784 RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW,
785 RDW_C_USEHRGN );
786 DeleteObject(hrgnOldPos);
787 DeleteObject(hrgnNewPos);
792 /***********************************************************************
793 * EVENT_SelectionRequest
795 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event )
797 XSelectionEvent result;
798 Atom rprop = None;
799 Window request = event->requestor;
801 if(event->target == XA_STRING)
803 HANDLE hText;
804 LPSTR text;
805 int size,i,j;
807 rprop = event->property;
809 if(rprop == None) rprop = event->target;
811 if(event->selection!=XA_PRIMARY) rprop = None;
812 else if(!CLIPBOARD_IsPresent(CF_OEMTEXT)) rprop = None;
813 else
815 /* open to make sure that clipboard is available */
817 BOOL couldOpen = OpenClipboard( pWnd->hwndSelf );
818 char* lpstr = 0;
820 hText = GetClipboardData(CF_TEXT);
821 text = GlobalLock16(hText);
822 size = GlobalSize16(hText);
824 /* remove carriage returns */
826 lpstr = (char*)xmalloc(size--);
827 for(i=0,j=0; i < size; i++ )
829 if( text[i] == '\r' && text[i+1] == '\n' ) continue;
830 lpstr[j++] = text[i];
831 if( text[i] == '\0' ) break;
833 lpstr[j]='\0';
835 XChangeProperty(display, request, rprop,
836 XA_STRING, 8, PropModeReplace,
837 lpstr, j);
838 free(lpstr);
840 /* close only if we opened before */
842 if(couldOpen) CloseClipboard();
846 if(rprop==None)
847 dprintf_event(stddeb,"Request for %s ignored\n", XGetAtomName(display,event->target));
849 result.type=SelectionNotify;
850 result.display=display;
851 result.requestor=request;
852 result.selection=event->selection;
853 result.property=rprop;
854 result.target=event->target;
855 result.time=event->time;
856 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
860 /***********************************************************************
861 * EVENT_SelectionNotify
863 static void EVENT_SelectionNotify( XSelectionEvent *event )
865 if (event->selection != XA_PRIMARY) return;
867 if (event->target != XA_STRING) CLIPBOARD_ReadSelection( 0, None );
868 else CLIPBOARD_ReadSelection( event->requestor, event->property );
870 dprintf_clipboard(stddeb,"\tSelectionNotify done!\n");
874 /***********************************************************************
875 * EVENT_SelectionClear
877 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event )
879 if (event->selection != XA_PRIMARY) return;
880 CLIPBOARD_ReleaseSelection( event->window, pWnd->hwndSelf );
884 /**********************************************************************
885 * EVENT_ClientMessage
887 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event )
889 static Atom wmProtocols = None;
890 static Atom wmDeleteWindow = None;
892 if (wmProtocols == None)
893 wmProtocols = XInternAtom( display, "WM_PROTOCOLS", True );
894 if (wmDeleteWindow == None)
895 wmDeleteWindow = XInternAtom( display, "WM_DELETE_WINDOW", True );
897 if ((event->format != 32) || (event->message_type != wmProtocols) ||
898 (((Atom) event->data.l[0]) != wmDeleteWindow))
900 dprintf_event( stddeb, "unrecognized ClientMessage\n" );
901 return;
903 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 );
906 /**********************************************************************
907 * EVENT_EnterNotify
909 * Install colormap when Wine window is focused in
910 * self-managed mode with private colormap
913 void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event )
915 if( !Options.managed && rootWindow == DefaultRootWindow(display) &&
916 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() )
917 XInstallColormap( display, COLOR_GetColormap() );
921 extern void FOCUS_SetXFocus( HWND32 );
923 /**********************************************************************
924 * EVENT_MapNotify
926 void EVENT_MapNotify( HWND hWnd, XMapEvent *event )
928 HWND32 hwndFocus = GetFocus32();
930 if (hwndFocus && IsChild( hWnd, hwndFocus ))
931 FOCUS_SetXFocus( (HWND32)hwndFocus );
933 return;
937 /**********************************************************************
938 * SetCapture16 (USER.18)
940 HWND16 SetCapture16( HWND16 hwnd )
942 return (HWND16)SetCapture32( hwnd );
946 /**********************************************************************
947 * SetCapture32 (USER32.463)
949 HWND32 SetCapture32( HWND32 hwnd )
951 Window win;
952 HWND32 old_capture_wnd = captureWnd;
954 if (!hwnd)
956 ReleaseCapture();
957 return old_capture_wnd;
959 if (!(win = WIN_GetXWindow( hwnd ))) return 0;
960 if (XGrabPointer(display, win, False,
961 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
962 GrabModeAsync, GrabModeAsync,
963 None, None, CurrentTime ) == GrabSuccess)
965 dprintf_win(stddeb, "SetCapture: %04x\n", hwnd);
966 captureWnd = hwnd;
967 return old_capture_wnd;
969 else return 0;
973 /**********************************************************************
974 * ReleaseCapture (USER.19) (USER32.438)
976 void ReleaseCapture(void)
978 if (captureWnd == 0) return;
979 XUngrabPointer( display, CurrentTime );
980 captureWnd = 0;
981 dprintf_win(stddeb, "ReleaseCapture\n");
985 /**********************************************************************
986 * GetCapture16 (USER.236)
988 HWND16 GetCapture16(void)
990 return (HWND16)captureWnd;
994 /**********************************************************************
995 * GetCapture32 (USER32.207)
997 HWND32 GetCapture32(void)
999 return captureWnd;
1003 /***********************************************************************
1004 * GetMouseEventProc (USER.337)
1006 FARPROC16 GetMouseEventProc(void)
1008 HMODULE16 hmodule = GetModuleHandle("USER");
1009 return MODULE_GetEntryPoint( hmodule,
1010 MODULE_GetOrdinal( hmodule, "Mouse_Event" ) );
1014 /***********************************************************************
1015 * Mouse_Event (USER.299)
1017 #ifndef WINELIB
1018 void Mouse_Event( SIGCONTEXT *context )
1020 /* Register values:
1021 * AX = mouse event
1022 * BX = horizontal displacement if AX & ME_MOVE
1023 * CX = vertical displacement if AX & ME_MOVE
1024 * DX = button state (?)
1025 * SI = mouse event flags (?)
1027 Window root, child;
1028 int rootX, rootY, childX, childY;
1029 unsigned int state;
1031 if (AX_reg(context) & ME_MOVE)
1033 /* We have to actually move the cursor */
1034 XWarpPointer( display, rootWindow, None, 0, 0, 0, 0,
1035 (short)BX_reg(context), (short)CX_reg(context) );
1036 return;
1038 if (!XQueryPointer( display, rootWindow, &root, &child,
1039 &rootX, &rootY, &childX, &childY, &state )) return;
1040 if (AX_reg(context) & ME_LDOWN)
1041 hardware_event( WM_LBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
1042 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1043 if (AX_reg(context) & ME_LUP)
1044 hardware_event( WM_LBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
1045 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1046 if (AX_reg(context) & ME_RDOWN)
1047 hardware_event( WM_RBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
1048 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1049 if (AX_reg(context) & ME_RUP)
1050 hardware_event( WM_RBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
1051 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1053 #endif
1056 /**********************************************************************
1057 * EnableHardwareInput (USER.331)
1059 BOOL16 EnableHardwareInput(BOOL16 bEnable)
1061 BOOL16 bOldState = InputEnabled;
1062 dprintf_event(stdnimp,"EnableHardwareInput(%d);\n", bEnable);
1063 InputEnabled = bEnable;
1064 return bOldState;