Release 970509
[wine/multimedia.git] / windows / event.c
blobfa01908939b06f522a2b77f85065a7ae4d275707
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 "winnt.h"
24 #include "gdi.h"
25 #include "heap.h"
26 #include "queue.h"
27 #include "win.h"
28 #include "class.h"
29 #include "clipboard.h"
30 #include "message.h"
31 #include "module.h"
32 #include "options.h"
33 #include "queue.h"
34 #include "winpos.h"
35 #include "drive.h"
36 #include "shell.h"
37 #include "xmalloc.h"
38 #include "keyboard.h"
39 #include "stddebug.h"
40 #include "debug.h"
41 #include "dde_proc.h"
44 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
46 #define DndNotDnd -1 /* OffiX drag&drop */
47 #define DndUnknown 0
48 #define DndRawData 1
49 #define DndFile 2
50 #define DndFiles 3
51 #define DndText 4
52 #define DndDir 5
53 #define DndLink 6
54 #define DndExe 7
56 #define DndEND 8
58 /* X context to associate a hwnd to an X window */
59 static XContext winContext = 0;
61 static INT16 captureHT = HTCLIENT;
62 static HWND32 captureWnd = 0;
63 static BOOL32 InputEnabled = TRUE;
64 static BOOL32 SwappedButtons = FALSE;
66 static Atom wmProtocols = None;
67 static Atom wmDeleteWindow = None;
68 static Atom dndProtocol = None;
69 static Atom dndSelection = None;
71 static const char * const event_names[] =
73 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
74 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
75 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
76 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
77 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
78 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
79 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
80 "ClientMessage", "MappingNotify"
83 /* Event handlers */
84 static void EVENT_Key( XKeyEvent *event );
85 static void EVENT_ButtonPress( WND *pWnd, XButtonEvent *event );
86 static void EVENT_ButtonRelease( WND *pWnd, XButtonEvent *event );
87 static void EVENT_MotionNotify( WND *pWnd, XMotionEvent *event );
88 static void EVENT_FocusIn( WND *pWnd, XFocusChangeEvent *event );
89 static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event );
90 static void EVENT_Expose( WND *pWnd, XExposeEvent *event );
91 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event );
92 static void EVENT_ConfigureNotify( HWND32 hwnd, XConfigureEvent *event );
93 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event);
94 static void EVENT_SelectionNotify( XSelectionEvent *event);
95 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event);
96 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event );
97 static void EVENT_MapNotify( HWND32 hwnd, XMapEvent *event );
99 /* Usable only with OLVWM - compile option perhaps?
100 static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event );
103 extern void FOCUS_SetXFocus( HWND32 );
104 extern BOOL16 DRAG_QueryUpdate( HWND16, SEGPTR, BOOL32 );
106 /***********************************************************************
107 * EVENT_ProcessEvent
109 * Process an X event.
111 void EVENT_ProcessEvent( XEvent *event )
113 WND *pWnd;
115 if (XFindContext( display, event->xany.window, winContext,
116 (char **)&pWnd ) != 0)
117 return; /* Not for a registered window */
119 dprintf_event( stddeb, "Got event %s for hwnd %04x\n",
120 event_names[event->type], pWnd->hwndSelf );
122 switch(event->type)
124 case KeyPress:
125 case KeyRelease:
126 if (InputEnabled)
127 EVENT_Key( (XKeyEvent*)event );
128 break;
130 case ButtonPress:
131 if (InputEnabled)
132 EVENT_ButtonPress( pWnd, (XButtonEvent*)event );
133 break;
135 case ButtonRelease:
136 if (InputEnabled)
137 EVENT_ButtonRelease( pWnd, (XButtonEvent*)event );
138 break;
140 case MotionNotify:
141 /* Wine between two fast machines across the overloaded campus
142 ethernet gets very boged down in MotionEvents. The following
143 simply finds the last motion event in the queue and drops
144 the rest. On a good link events are servered before they build
145 up so this doesn't take place. On a slow link this may cause
146 problems if the event order is important. I'm not yet seen
147 of any problems. Jon 7/6/96.
149 if (InputEnabled)
151 while (XCheckTypedWindowEvent(display,((XAnyEvent *)event)->window,
152 MotionNotify, event));
153 EVENT_MotionNotify( pWnd, (XMotionEvent*)event );
155 break;
157 case FocusIn:
158 EVENT_FocusIn( pWnd, (XFocusChangeEvent*)event );
159 break;
161 case FocusOut:
162 EVENT_FocusOut( pWnd, (XFocusChangeEvent*)event );
163 break;
165 case Expose:
166 EVENT_Expose( pWnd, (XExposeEvent *)event );
167 break;
169 case GraphicsExpose:
170 EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
171 break;
173 case ConfigureNotify:
174 EVENT_ConfigureNotify( pWnd->hwndSelf, (XConfigureEvent*)event );
175 break;
177 case SelectionRequest:
178 EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event );
179 break;
181 case SelectionNotify:
182 EVENT_SelectionNotify( (XSelectionEvent *)event );
183 break;
185 case SelectionClear:
186 EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event );
187 break;
189 case ClientMessage:
190 EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event );
191 break;
193 /* case EnterNotify:
194 * EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
195 * break;
197 case NoExpose:
198 break;
200 /* We get all these because of StructureNotifyMask. */
201 case UnmapNotify:
202 case CirculateNotify:
203 case CreateNotify:
204 case DestroyNotify:
205 case GravityNotify:
206 case ReparentNotify:
207 break;
209 case MapNotify:
210 EVENT_MapNotify( pWnd->hwndSelf, (XMapEvent *)event );
211 break;
213 default:
214 dprintf_event(stddeb, "Unprocessed event %s for hwnd %04x\n",
215 event_names[event->type], pWnd->hwndSelf );
216 break;
221 /***********************************************************************
222 * EVENT_RegisterWindow
224 * Associate an X window to a HWND.
226 void EVENT_RegisterWindow( WND *pWnd )
228 if (wmProtocols == None)
229 wmProtocols = XInternAtom( display, "WM_PROTOCOLS", True );
230 if (wmDeleteWindow == None)
231 wmDeleteWindow = XInternAtom( display, "WM_DELETE_WINDOW", True );
232 if( dndProtocol == None )
233 dndProtocol = XInternAtom( display, "DndProtocol" , False );
234 if( dndSelection == None )
235 dndSelection = XInternAtom( display, "DndSelection" , False );
237 XSetWMProtocols( display, pWnd->window, &wmDeleteWindow, 1 );
239 if (!winContext) winContext = XUniqueContext();
240 XSaveContext( display, pWnd->window, winContext, (char *)pWnd );
243 /***********************************************************************
244 * EVENT_DestroyWindow
246 void EVENT_DestroyWindow( WND *pWnd )
248 XEvent xe;
250 XDeleteContext( display, pWnd->window, winContext );
251 XDestroyWindow( display, pWnd->window );
252 while( XCheckWindowEvent(display, pWnd->window, NoEventMask, &xe) );
255 /***********************************************************************
256 * EVENT_WaitXEvent
258 * Wait for an X event, optionally sleeping until one arrives.
259 * Return TRUE if an event is pending, FALSE on timeout or error
260 * (for instance lost connection with the server).
262 BOOL32 EVENT_WaitXEvent( BOOL32 sleep, BOOL32 peek )
264 XEvent event;
265 LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0;
267 /* Wait for an event or a timeout. If maxWait is -1, we have no timeout;
268 * in this case, we fall through directly to the XNextEvent loop.
271 if ((maxWait != -1) && !XPending(display))
273 fd_set read_set;
274 struct timeval timeout;
275 int fd = ConnectionNumber(display);
277 FD_ZERO( &read_set );
278 FD_SET( fd, &read_set );
280 timeout.tv_usec = (maxWait % 1000) * 1000;
281 timeout.tv_sec = maxWait / 1000;
283 #ifdef CONFIG_IPC
284 sigsetjmp(env_wait_x, 1);
285 stop_wait_op= CONT;
287 if (DDE_GetRemoteMessage()) {
288 while(DDE_GetRemoteMessage())
290 return TRUE;
292 stop_wait_op = STOP_WAIT_X;
293 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
294 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
295 !XPending(display))
297 stop_wait_op = CONT;
298 TIMER_ExpireTimers();
299 return FALSE;
301 else stop_wait_op = CONT;
302 #else /* CONFIG_IPC */
303 if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
305 /* Timeout or error */
306 TIMER_ExpireTimers();
307 return FALSE;
309 #endif /* CONFIG_IPC */
313 /* 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 );
328 if( peek )
330 WND* pWnd;
331 MESSAGEQUEUE* pQ;
333 if (XFindContext( display, ((XAnyEvent *)&event)->window, winContext,
334 (char **)&pWnd ) || (event.type == NoExpose))
335 continue;
337 /* Check only for those events which can be processed
338 * internally. */
340 if( event.type == MotionNotify ||
341 event.type == ButtonPress || event.type == ButtonRelease ||
342 event.type == KeyPress || event.type == KeyRelease ||
343 event.type == SelectionRequest || event.type == SelectionClear )
345 EVENT_ProcessEvent( &event );
346 continue;
349 if( pWnd )
350 if( (pQ = (MESSAGEQUEUE*)GlobalLock16(pWnd->hmemTaskQ)) )
352 pQ->flags |= QUEUE_FLAG_XEVENT;
353 PostEvent(pQ->hTask);
354 XPutBackEvent(display, &event);
355 break;
358 else
359 EVENT_ProcessEvent( &event );
361 while (XPending( display ));
362 return TRUE;
366 /***********************************************************************
367 * EVENT_Synchronize
369 * Synchronize with the X server. Should not be used too often.
371 void EVENT_Synchronize()
373 XEvent event;
375 XSync( display, False );
376 while (XPending( display ))
378 XNextEvent( display, &event );
379 EVENT_ProcessEvent( &event );
383 /***********************************************************************
384 * EVENT_QueryZOrder
386 * Try to synchronize internal z-order with the window manager's.
388 static BOOL32 __check_query_condition( WND** pWndA, WND** pWndB )
390 /* return TRUE if we have at least two managed windows */
392 for( *pWndB = NULL; *pWndA; *pWndA = (*pWndA)->next )
393 if( (*pWndA)->flags & WIN_MANAGED &&
394 (*pWndA)->dwStyle & WS_VISIBLE ) break;
395 if( *pWndA )
396 for( *pWndB = (*pWndA)->next; *pWndB; *pWndB = (*pWndB)->next )
397 if( (*pWndB)->flags & WIN_MANAGED &&
398 (*pWndB)->dwStyle & WS_VISIBLE ) break;
399 return ((*pWndB) != NULL);
402 static Window __get_common_ancestor( Window A, Window B,
403 Window** children, unsigned* total )
405 /* find the real root window */
407 Window root, *childrenB;
408 unsigned totalB;
412 if( *children ) XFree( *children );
413 XQueryTree( display, A, &root, &A, children, total );
414 XQueryTree( display, B, &root, &B, &childrenB, &totalB );
415 if( childrenB ) XFree( childrenB );
416 } while( A != B && A && B );
417 return ( A && B ) ? A : 0 ;
420 static Window __get_top_decoration( Window w, Window ancestor )
422 Window* children, root, prev = w, parent = w;
423 unsigned total;
427 w = parent;
428 XQueryTree( display, w, &root, &parent, &children, &total );
429 if( children ) XFree( children );
430 } while( parent && parent != ancestor );
431 dprintf_event( stddeb, "\t%08x -> %08x\n", (unsigned)prev, (unsigned)w );
432 return ( parent ) ? w : 0 ;
435 static unsigned __td_lookup( Window w, Window* list, unsigned max )
437 unsigned i;
438 for( i = 0; i < max; i++ ) if( list[i] == w ) break;
439 return i;
442 static BOOL32 EVENT_QueryZOrder( WND* pWndCheck )
444 BOOL32 bRet = FALSE;
445 HWND32 hwndInsertAfter = HWND_TOP;
446 WND* pWnd, *pWndZ = WIN_GetDesktop()->child;
447 Window w, parent, *children = NULL;
448 unsigned total, check, pos, best;
450 if( !__check_query_condition(&pWndZ, &pWnd) ) return TRUE;
452 parent = __get_common_ancestor( pWndZ->window, pWnd->window,
453 &children, &total );
454 if( parent )
456 w = __get_top_decoration( pWndCheck->window, parent );
457 if( w != children[total - 1] )
459 check = __td_lookup( w, children, total );
460 best = total;
461 for( pWnd = pWndZ; pWnd; pWnd = pWnd->next )
463 if( pWnd != pWndCheck )
465 if( !(pWnd->flags & WIN_MANAGED) ||
466 !(w = __get_top_decoration( pWnd->window, parent )) )
467 continue;
468 pos = __td_lookup( w, children, total );
469 if( pos < best && pos > check )
471 best = pos;
472 hwndInsertAfter = pWnd->hwndSelf;
474 if( check - best == 1 ) break;
477 WIN_UnlinkWindow( pWndCheck->hwndSelf );
478 WIN_LinkWindow( pWndCheck->hwndSelf, hwndInsertAfter);
481 if( children ) XFree( children );
482 return bRet;
486 /***********************************************************************
487 * EVENT_XStateToKeyState
489 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
490 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
492 static WORD EVENT_XStateToKeyState( int state )
494 int kstate = 0;
496 if (state & Button1Mask) kstate |= MK_LBUTTON;
497 if (state & Button2Mask) kstate |= MK_MBUTTON;
498 if (state & Button3Mask) kstate |= MK_RBUTTON;
499 if (state & ShiftMask) kstate |= MK_SHIFT;
500 if (state & ControlMask) kstate |= MK_CONTROL;
501 return kstate;
505 /***********************************************************************
506 * EVENT_Expose
508 static void EVENT_Expose( WND *pWnd, XExposeEvent *event )
510 RECT32 rect;
512 /* Make position relative to client area instead of window */
513 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
514 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
515 rect.right = rect.left + event->width;
516 rect.bottom = rect.top + event->height;
518 PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
519 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
520 (event->count ? 0 : RDW_ERASENOW), 0 );
524 /***********************************************************************
525 * EVENT_GraphicsExpose
527 * This is needed when scrolling area is partially obscured
528 * by non-Wine X window.
530 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
532 RECT32 rect;
534 /* Make position relative to client area instead of window */
535 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
536 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
537 rect.right = rect.left + event->width;
538 rect.bottom = rect.top + event->height;
540 PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
541 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
542 (event->count ? 0 : RDW_ERASENOW), 0 );
546 /***********************************************************************
547 * EVENT_Key
549 * Handle a X key event
551 static void EVENT_Key( XKeyEvent *event )
553 KEYBOARD_HandleEvent( event );
557 /***********************************************************************
558 * EVENT_MotionNotify
560 static void EVENT_MotionNotify( WND *pWnd, XMotionEvent *event )
562 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
563 event->x_root - desktopX, event->y_root - desktopY,
564 event->time - MSG_WineStartTicks, (DWORD)pWnd->hwndSelf );
568 /***********************************************************************
569 * EVENT_DummyMotionNotify
571 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
573 void EVENT_DummyMotionNotify(void)
575 Window root, child;
576 int rootX, rootY, childX, childY;
577 unsigned int state;
579 if (XQueryPointer( display, rootWindow, &root, &child,
580 &rootX, &rootY, &childX, &childY, &state ))
582 hardware_event(WM_MOUSEMOVE, EVENT_XStateToKeyState( state ), 0L,
583 rootX - desktopX, rootY - desktopY, GetTickCount(), 0 );
588 /***********************************************************************
589 * EVENT_ButtonPress
591 static void EVENT_ButtonPress( WND *pWnd, XButtonEvent *event )
593 static WORD messages[NB_BUTTONS] =
594 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
595 int buttonNum = event->button - 1;
597 if (buttonNum >= NB_BUTTONS) return;
598 if (SwappedButtons) buttonNum = NB_BUTTONS - 1 - buttonNum;
599 MouseButtonsStates[buttonNum] = 0x8000;
600 AsyncMouseButtonsStates[buttonNum] = 0x8000;
601 hardware_event( messages[buttonNum],
602 EVENT_XStateToKeyState( event->state ), 0L,
603 event->x_root - desktopX, event->y_root - desktopY,
604 event->time - MSG_WineStartTicks, (DWORD)pWnd->hwndSelf );
608 /***********************************************************************
609 * EVENT_ButtonRelease
611 static void EVENT_ButtonRelease( WND *pWnd, XButtonEvent *event )
613 static const WORD messages[NB_BUTTONS] =
614 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
615 int buttonNum = event->button - 1;
617 if (buttonNum >= NB_BUTTONS) return;
618 if (SwappedButtons) buttonNum = NB_BUTTONS - 1 - buttonNum;
619 MouseButtonsStates[buttonNum] = FALSE;
620 hardware_event( messages[buttonNum],
621 EVENT_XStateToKeyState( event->state ), 0L,
622 event->x_root - desktopX, event->y_root - desktopY,
623 event->time - MSG_WineStartTicks, (DWORD)pWnd->hwndSelf );
627 /**********************************************************************
628 * EVENT_FocusIn
630 static void EVENT_FocusIn( WND *pWnd, XFocusChangeEvent *event )
632 if (Options.managed) EVENT_QueryZOrder( pWnd );
634 if (event->detail != NotifyPointer)
636 HWND32 hwnd = pWnd->hwndSelf;
638 if (hwnd != GetActiveWindow32())
639 WINPOS_ChangeActiveWindow( hwnd, FALSE );
640 if ((hwnd != GetFocus32()) && !IsChild32( hwnd, GetFocus32()))
641 SetFocus32( hwnd );
646 /**********************************************************************
647 * EVENT_FocusOut
649 * Note: only top-level override-redirect windows get FocusOut events.
651 static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event )
653 if (event->detail != NotifyPointer)
655 HWND32 hwnd = pWnd->hwndSelf;
657 if (hwnd == GetActiveWindow32())
658 WINPOS_ChangeActiveWindow( 0, FALSE );
659 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32()))
660 SetFocus32( 0 );
664 /**********************************************************************
665 * EVENT_CheckFocus
667 BOOL32 EVENT_CheckFocus(void)
669 WND* pWnd;
670 Window xW;
671 int state;
673 XGetInputFocus(display, &xW, &state);
674 if( xW == None ||
675 XFindContext(display, xW, winContext, (char **)&pWnd) )
676 return FALSE;
677 return TRUE;
680 /**********************************************************************
681 * EVENT_ConfigureNotify
683 * The ConfigureNotify event is only selected on the desktop window
684 * and on top-level windows when the -managed flag is used.
686 static void EVENT_ConfigureNotify( HWND32 hwnd, XConfigureEvent *event )
688 /* FIXME: with -desktop xxx we get this event _before_ desktop
689 * window structure is created. WIN_GetDesktop() check is a hack.
692 if ( !WIN_GetDesktop() || hwnd == GetDesktopWindow32())
694 desktopX = event->x;
695 desktopY = event->y;
697 else
699 WND *wndPtr = WIN_FindWndPtr( hwnd );
700 WINDOWPOS16 *winpos;
701 RECT16 newWindowRect, newClientRect;
702 HRGN32 hrgnOldPos, hrgnNewPos;
703 Window above = event->above;
705 if (!wndPtr || !(wndPtr->flags & WIN_MANAGED) ||
706 !(winpos = SEGPTR_NEW(WINDOWPOS16))) return;
708 /* Fill WINDOWPOS struct */
709 winpos->flags = SWP_NOACTIVATE | SWP_NOZORDER;
710 winpos->hwnd = hwnd;
711 winpos->x = event->x;
712 winpos->y = event->y;
713 winpos->cx = event->width;
714 winpos->cy = event->height;
716 /* Check for unchanged attributes */
717 if(winpos->x == wndPtr->rectWindow.left &&
718 winpos->y == wndPtr->rectWindow.top)
719 winpos->flags |= SWP_NOMOVE;
720 if(winpos->cx == wndPtr->rectWindow.right - wndPtr->rectWindow.left &&
721 winpos->cy == wndPtr->rectWindow.bottom - wndPtr->rectWindow.top)
722 winpos->flags |= SWP_NOSIZE;
724 /* Send WM_WINDOWPOSCHANGING */
725 SendMessage16(hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)SEGPTR_GET(winpos));
727 /* Calculate new position and size */
728 newWindowRect.left = event->x;
729 newWindowRect.right = event->x + event->width;
730 newWindowRect.top = event->y;
731 newWindowRect.bottom = event->y + event->height;
733 WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
734 &wndPtr->rectWindow, &wndPtr->rectClient,
735 SEGPTR_GET(winpos), &newClientRect );
737 hrgnOldPos = CreateRectRgnIndirect16( &wndPtr->rectWindow );
738 hrgnNewPos = CreateRectRgnIndirect16( &newWindowRect );
739 CombineRgn32( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
741 /* Set new size and position */
742 wndPtr->rectWindow = newWindowRect;
743 wndPtr->rectClient = newClientRect;
744 SendMessage16( hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)SEGPTR_GET(winpos));
746 SEGPTR_FREE(winpos);
748 if( IsWindow32( hwnd ) )
749 if( above == None ) /* absolute bottom */
751 WIN_UnlinkWindow( hwnd );
752 WIN_LinkWindow( hwnd, HWND_BOTTOM);
754 else EVENT_QueryZOrder( wndPtr ); /* try to outsmart window manager */
756 DeleteObject32(hrgnOldPos);
757 DeleteObject32(hrgnNewPos);
762 /***********************************************************************
763 * EVENT_SelectionRequest
765 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event )
767 XSelectionEvent result;
768 Atom rprop = None;
769 Window request = event->requestor;
771 if(event->target == XA_STRING)
773 HANDLE16 hText;
774 LPSTR text;
775 int size,i,j;
777 rprop = event->property;
779 if(rprop == None) rprop = event->target;
781 if(event->selection!=XA_PRIMARY) rprop = None;
782 else if(!CLIPBOARD_IsPresent(CF_OEMTEXT)) rprop = None;
783 else
785 /* open to make sure that clipboard is available */
787 BOOL32 couldOpen = OpenClipboard32( pWnd->hwndSelf );
788 char* lpstr = 0;
790 hText = GetClipboardData16(CF_TEXT);
791 text = GlobalLock16(hText);
792 size = GlobalSize16(hText);
794 /* remove carriage returns */
796 lpstr = (char*)xmalloc(size--);
797 for(i=0,j=0; i < size && text[i]; i++ )
799 if( text[i] == '\r' &&
800 (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
801 lpstr[j++] = text[i];
803 lpstr[j]='\0';
805 XChangeProperty(display, request, rprop,
806 XA_STRING, 8, PropModeReplace,
807 lpstr, j);
808 free(lpstr);
810 /* close only if we opened before */
812 if(couldOpen) CloseClipboard32();
816 if(rprop==None)
817 dprintf_event(stddeb,"Request for %s ignored\n", XGetAtomName(display,event->target));
819 result.type=SelectionNotify;
820 result.display=display;
821 result.requestor=request;
822 result.selection=event->selection;
823 result.property=rprop;
824 result.target=event->target;
825 result.time=event->time;
826 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
830 /***********************************************************************
831 * EVENT_SelectionNotify
833 static void EVENT_SelectionNotify( XSelectionEvent *event )
835 if (event->selection != XA_PRIMARY) return;
837 if (event->target != XA_STRING) CLIPBOARD_ReadSelection( 0, None );
838 else CLIPBOARD_ReadSelection( event->requestor, event->property );
840 dprintf_clipboard(stddeb,"\tSelectionNotify done!\n");
844 /***********************************************************************
845 * EVENT_SelectionClear
847 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event )
849 if (event->selection != XA_PRIMARY) return;
850 CLIPBOARD_ReleaseSelection( event->window, pWnd->hwndSelf );
854 /**********************************************************************
855 * EVENT_ClientMessage
857 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event )
859 if (event->message_type != None && event->format == 32)
861 if ((event->message_type == wmProtocols) &&
862 (((Atom) event->data.l[0]) == wmDeleteWindow))
863 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 );
864 else if ( event->message_type == dndProtocol &&
865 (event->data.l[0] == DndFile || event->data.l[0] == DndFiles) )
867 unsigned long data_length;
868 unsigned long aux_long;
869 unsigned char* p_data = NULL;
870 union {
871 Atom atom_aux;
872 POINT32 pt_aux;
873 int i;
874 } u;
875 int x, y;
876 BOOL16 bAccept;
877 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO));
878 LPDRAGINFO lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
879 SEGPTR spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
880 Window w_aux_root, w_aux_child;
881 WND* pDropWnd;
883 if( !lpDragInfo || !spDragInfo ) return;
885 XQueryPointer( display, pWnd->window, &w_aux_root, &w_aux_child,
886 &x, &y, &u.pt_aux.x, &u.pt_aux.y, (unsigned int*)&aux_long);
888 lpDragInfo->hScope = pWnd->hwndSelf;
889 lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y;
891 /* find out drop point and drop window */
892 if( x < 0 || y < 0 ||
893 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
894 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
895 { bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
896 else
898 bAccept = DRAG_QueryUpdate( pWnd->hwndSelf, spDragInfo, TRUE );
899 x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
901 pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
902 GlobalFree16( hDragInfo );
904 if( bAccept )
906 XGetWindowProperty( display, DefaultRootWindow(display),
907 dndSelection, 0, 65535, FALSE,
908 AnyPropertyType, &u.atom_aux, &u.pt_aux.y,
909 &data_length, &aux_long, &p_data);
911 if( !aux_long && p_data) /* don't bother if > 64K */
913 char *p = (char*) p_data;
914 char *p_drop;
916 aux_long = 0;
917 while( *p ) /* calculate buffer size */
919 p_drop = p;
920 if((u.i = *p) != -1 )
921 u.i = DRIVE_FindDriveRoot( (const char **)&p_drop );
922 if( u.i == -1 ) *p = -1; /* mark as "bad" */
923 else
925 INT32 len = GetShortPathName32A( p, NULL, 0 );
926 if (len) aux_long += len + 1;
927 else *p = -1;
929 p += strlen(p) + 1;
931 if( aux_long && aux_long < 65535 )
933 HDROP16 hDrop;
934 LPDROPFILESTRUCT lpDrop;
936 aux_long += sizeof(DROPFILESTRUCT) + 1;
937 hDrop = (HDROP16)GlobalAlloc16( GMEM_SHARE, aux_long );
938 lpDrop = (LPDROPFILESTRUCT) GlobalLock16( hDrop );
940 if( lpDrop )
942 lpDrop->wSize = sizeof(DROPFILESTRUCT);
943 lpDrop->ptMousePos.x = (INT16)x;
944 lpDrop->ptMousePos.y = (INT16)y;
945 lpDrop->fInNonClientArea = (BOOL16)
946 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
947 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
948 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
949 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
950 p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT);
951 p = p_data;
952 while(*p)
954 if( *p != -1 ) /* use only "good" entries */
956 GetShortPathName32A( p, p_drop, 65535 );
957 p_drop += strlen( p_drop ) + 1;
959 p += strlen(p) + 1;
961 *p_drop = '\0';
962 PostMessage16( pWnd->hwndSelf, WM_DROPFILES,
963 (WPARAM16)hDrop, 0L );
967 if( p_data ) XFree(p_data);
969 } /* WS_EX_ACCEPTFILES */
970 } /* dndProtocol */
971 else
972 dprintf_event( stddeb, "unrecognized ClientMessage\n" );
976 /**********************************************************************
977 * EVENT_EnterNotify
979 * Install colormap when Wine window is focused in
980 * self-managed mode with private colormap
983 void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event )
985 if( !Options.managed && rootWindow == DefaultRootWindow(display) &&
986 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() )
987 XInstallColormap( display, COLOR_GetColormap() );
991 /**********************************************************************
992 * EVENT_MapNotify
994 void EVENT_MapNotify( HWND32 hWnd, XMapEvent *event )
996 HWND32 hwndFocus = GetFocus32();
998 if (hwndFocus && IsChild32( hWnd, hwndFocus ))
999 FOCUS_SetXFocus( (HWND32)hwndFocus );
1001 return;
1004 /**********************************************************************
1005 * EVENT_Capture
1007 * We need this to be able to generate double click messages
1008 * when menu code captures mouse in the window without CS_DBLCLK style.
1010 HWND32 EVENT_Capture(HWND32 hwnd, INT16 ht)
1012 Window win;
1013 HWND32 capturePrev = captureWnd;
1015 if (!hwnd)
1017 XUngrabPointer(display, CurrentTime );
1018 captureWnd = NULL; captureHT = 0;
1020 else if ((win = WIN_GetXWindow( hwnd )))
1022 WND* wndPtr = WIN_FindWndPtr( hwnd );
1024 if ( wndPtr &&
1025 (XGrabPointer(display, win, False,
1026 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
1027 GrabModeAsync, GrabModeAsync,
1028 None, None, CurrentTime ) == GrabSuccess) )
1030 dprintf_win(stddeb, "SetCapture(0x%04x)\n", hwnd );
1031 captureWnd = hwnd;
1032 captureHT = ht;
1036 if( capturePrev && capturePrev != captureWnd )
1038 WND* wndPtr = WIN_FindWndPtr( capturePrev );
1039 if( wndPtr && (wndPtr->flags & WIN_ISWIN32) )
1040 SendMessage32A( capturePrev, WM_CAPTURECHANGED, 0L, hwnd);
1042 return capturePrev;
1045 /**********************************************************************
1046 * EVENT_GetCaptureInfo
1048 INT16 EVENT_GetCaptureInfo()
1050 return captureHT;
1053 /**********************************************************************
1054 * SetCapture16 (USER.18)
1056 HWND16 SetCapture16( HWND16 hwnd )
1058 return (HWND16)EVENT_Capture( hwnd, HTCLIENT );
1062 /**********************************************************************
1063 * SetCapture32 (USER32.463)
1065 HWND32 SetCapture32( HWND32 hwnd )
1067 return EVENT_Capture( hwnd, HTCLIENT );
1071 /**********************************************************************
1072 * ReleaseCapture (USER.19) (USER32.438)
1074 void ReleaseCapture(void)
1076 dprintf_win(stddeb, "ReleaseCapture() [%04x]\n", captureWnd );
1077 if( captureWnd ) EVENT_Capture( 0, 0 );
1081 /**********************************************************************
1082 * GetCapture16 (USER.236)
1084 HWND16 GetCapture16(void)
1086 return captureWnd;
1090 /**********************************************************************
1091 * GetCapture32 (USER32.207)
1093 HWND32 GetCapture32(void)
1095 return captureWnd;
1099 /***********************************************************************
1100 * GetMouseEventProc (USER.337)
1102 FARPROC16 GetMouseEventProc(void)
1104 HMODULE16 hmodule = GetModuleHandle16("USER");
1105 return MODULE_GetEntryPoint( hmodule,
1106 MODULE_GetOrdinal( hmodule, "Mouse_Event" ) );
1110 /***********************************************************************
1111 * Mouse_Event (USER.299)
1113 void Mouse_Event( CONTEXT *context )
1115 /* Register values:
1116 * AX = mouse event
1117 * BX = horizontal displacement if AX & ME_MOVE
1118 * CX = vertical displacement if AX & ME_MOVE
1119 * DX = button state (?)
1120 * SI = mouse event flags (?)
1122 Window root, child;
1123 int rootX, rootY, childX, childY;
1124 unsigned int state;
1126 if (AX_reg(context) & ME_MOVE)
1128 /* We have to actually move the cursor */
1129 XWarpPointer( display, rootWindow, None, 0, 0, 0, 0,
1130 (short)BX_reg(context), (short)CX_reg(context) );
1131 return;
1133 if (!XQueryPointer( display, rootWindow, &root, &child,
1134 &rootX, &rootY, &childX, &childY, &state )) return;
1135 if (AX_reg(context) & ME_LDOWN)
1136 hardware_event( WM_LBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
1137 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1138 if (AX_reg(context) & ME_LUP)
1139 hardware_event( WM_LBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
1140 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1141 if (AX_reg(context) & ME_RDOWN)
1142 hardware_event( WM_RBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
1143 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1144 if (AX_reg(context) & ME_RUP)
1145 hardware_event( WM_RBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
1146 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1150 /**********************************************************************
1151 * EnableHardwareInput (USER.331)
1153 BOOL16 EnableHardwareInput(BOOL16 bEnable)
1155 BOOL16 bOldState = InputEnabled;
1156 dprintf_event(stdnimp,"EnableHardwareInput(%d);\n", bEnable);
1157 InputEnabled = bEnable;
1158 return bOldState;
1162 /***********************************************************************
1163 * SwapMouseButton16 (USER.186)
1165 BOOL16 SwapMouseButton16( BOOL16 fSwap )
1167 BOOL16 ret = SwappedButtons;
1168 SwappedButtons = fSwap;
1169 return ret;
1173 /***********************************************************************
1174 * SwapMouseButton32 (USER32.536)
1176 BOOL32 SwapMouseButton32( BOOL32 fSwap )
1178 BOOL32 ret = SwappedButtons;
1179 SwappedButtons = fSwap;
1180 return ret;