Release 970824
[wine/multimedia.git] / windows / event.c
blob541bd46b4dafaa0b9305191965284cdff6476d62
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 /* EVENT_WaitNetEvent() master fd sets */
73 static fd_set __event_io_set[3];
74 static int __event_max_fd = 0;
75 static int __event_x_connection = 0;
77 static const char * const event_names[] =
79 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
80 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
81 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
82 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
83 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
84 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
85 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
86 "ClientMessage", "MappingNotify"
89 /* Event handlers */
90 static void EVENT_Key( XKeyEvent *event );
91 static void EVENT_ButtonPress( WND *pWnd, XButtonEvent *event );
92 static void EVENT_ButtonRelease( WND *pWnd, XButtonEvent *event );
93 static void EVENT_MotionNotify( WND *pWnd, XMotionEvent *event );
94 static void EVENT_FocusIn( WND *pWnd, XFocusChangeEvent *event );
95 static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event );
96 static void EVENT_Expose( WND *pWnd, XExposeEvent *event );
97 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event );
98 static void EVENT_ConfigureNotify( HWND32 hwnd, XConfigureEvent *event );
99 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event);
100 static void EVENT_SelectionNotify( XSelectionEvent *event);
101 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event);
102 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event );
103 static void EVENT_MapNotify( HWND32 hwnd, XMapEvent *event );
105 /* Usable only with OLVWM - compile option perhaps?
106 static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event );
109 extern void FOCUS_SetXFocus( HWND32 );
110 extern BOOL16 DRAG_QueryUpdate( HWND16, SEGPTR, BOOL32 );
111 extern BOOL32 WINSOCK_HandleIO( int* max_fd, int num_pending, fd_set io_set[3] );
113 /***********************************************************************
114 * EVENT_Init
116 * Initialize network IO.
118 BOOL32 EVENT_Init(void)
120 int i;
121 for( i = 0; i < 3; i++ )
122 FD_ZERO( __event_io_set + i );
124 __event_max_fd = __event_x_connection = ConnectionNumber(display);
125 FD_SET( __event_x_connection, &__event_io_set[EVENT_IO_READ] );
126 __event_max_fd++;
127 return TRUE;
130 /***********************************************************************
131 * EVENT_AddIO
133 void EVENT_AddIO( int fd, int io_type )
135 FD_SET( fd, &__event_io_set[io_type] );
136 if( __event_max_fd <= fd ) __event_max_fd = fd + 1;
139 void EVENT_DeleteIO( int fd, int io_type )
141 FD_CLR( fd, &__event_io_set[io_type] );
144 /***********************************************************************
145 * EVENT_ProcessEvent
147 * Process an X event.
149 void EVENT_ProcessEvent( XEvent *event )
151 WND *pWnd;
153 if (XFindContext( display, event->xany.window, winContext,
154 (char **)&pWnd ) != 0)
155 return; /* Not for a registered window */
157 dprintf_event( stddeb, "Got event %s for hwnd %04x\n",
158 event_names[event->type], pWnd->hwndSelf );
160 switch(event->type)
162 case KeyPress:
163 case KeyRelease:
164 if (InputEnabled)
165 EVENT_Key( (XKeyEvent*)event );
166 break;
168 case ButtonPress:
169 if (InputEnabled)
170 EVENT_ButtonPress( pWnd, (XButtonEvent*)event );
171 break;
173 case ButtonRelease:
174 if (InputEnabled)
175 EVENT_ButtonRelease( pWnd, (XButtonEvent*)event );
176 break;
178 case MotionNotify:
179 /* Wine between two fast machines across the overloaded campus
180 ethernet gets very boged down in MotionEvents. The following
181 simply finds the last motion event in the queue and drops
182 the rest. On a good link events are servered before they build
183 up so this doesn't take place. On a slow link this may cause
184 problems if the event order is important. I'm not yet seen
185 of any problems. Jon 7/6/96.
187 if (InputEnabled)
189 while (XCheckTypedWindowEvent(display,((XAnyEvent *)event)->window,
190 MotionNotify, event));
191 EVENT_MotionNotify( pWnd, (XMotionEvent*)event );
193 break;
195 case FocusIn:
196 EVENT_FocusIn( pWnd, (XFocusChangeEvent*)event );
197 break;
199 case FocusOut:
200 EVENT_FocusOut( pWnd, (XFocusChangeEvent*)event );
201 break;
203 case Expose:
204 EVENT_Expose( pWnd, (XExposeEvent *)event );
205 break;
207 case GraphicsExpose:
208 EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
209 break;
211 case ConfigureNotify:
212 EVENT_ConfigureNotify( pWnd->hwndSelf, (XConfigureEvent*)event );
213 break;
215 case SelectionRequest:
216 EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event );
217 break;
219 case SelectionNotify:
220 EVENT_SelectionNotify( (XSelectionEvent *)event );
221 break;
223 case SelectionClear:
224 EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event );
225 break;
227 case ClientMessage:
228 EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event );
229 break;
231 /* case EnterNotify:
232 * EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
233 * break;
235 case NoExpose:
236 break;
238 /* We get all these because of StructureNotifyMask. */
239 case UnmapNotify:
240 case CirculateNotify:
241 case CreateNotify:
242 case DestroyNotify:
243 case GravityNotify:
244 case ReparentNotify:
245 break;
247 case MapNotify:
248 EVENT_MapNotify( pWnd->hwndSelf, (XMapEvent *)event );
249 break;
251 default:
252 dprintf_event(stddeb, "Unprocessed event %s for hwnd %04x\n",
253 event_names[event->type], pWnd->hwndSelf );
254 break;
259 /***********************************************************************
260 * EVENT_RegisterWindow
262 * Associate an X window to a HWND.
264 void EVENT_RegisterWindow( WND *pWnd )
266 if (wmProtocols == None)
267 wmProtocols = XInternAtom( display, "WM_PROTOCOLS", True );
268 if (wmDeleteWindow == None)
269 wmDeleteWindow = XInternAtom( display, "WM_DELETE_WINDOW", True );
270 if( dndProtocol == None )
271 dndProtocol = XInternAtom( display, "DndProtocol" , False );
272 if( dndSelection == None )
273 dndSelection = XInternAtom( display, "DndSelection" , False );
275 XSetWMProtocols( display, pWnd->window, &wmDeleteWindow, 1 );
277 if (!winContext) winContext = XUniqueContext();
278 XSaveContext( display, pWnd->window, winContext, (char *)pWnd );
281 /***********************************************************************
282 * EVENT_DestroyWindow
284 void EVENT_DestroyWindow( WND *pWnd )
286 XEvent xe;
288 XDeleteContext( display, pWnd->window, winContext );
289 XDestroyWindow( display, pWnd->window );
290 while( XCheckWindowEvent(display, pWnd->window, NoEventMask, &xe) );
293 /***********************************************************************
294 * EVENT_WaitNetEvent
296 * Wait for a network event, optionally sleeping until one arrives.
297 * Return TRUE if an event is pending, FALSE on timeout or error
298 * (for instance lost connection with the server).
300 BOOL32 EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek )
302 XEvent event;
303 LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0;
305 /* Wait for an event or a timeout. If maxWait is -1, we have no timeout;
306 * in this case, we fall through directly to the XNextEvent loop.
309 if ((maxWait != -1) && !XPending(display))
311 int num_pending;
312 struct timeval timeout;
313 fd_set read_set = __event_io_set[EVENT_IO_READ];
314 fd_set write_set = __event_io_set[EVENT_IO_WRITE];
315 fd_set except_set = __event_io_set[EVENT_IO_EXCEPT];
317 timeout.tv_usec = (maxWait % 1000) * 1000;
318 timeout.tv_sec = maxWait / 1000;
320 #ifdef CONFIG_IPC
321 sigsetjmp(env_wait_x, 1);
322 stop_wait_op= CONT;
324 if (DDE_GetRemoteMessage()) {
325 while(DDE_GetRemoteMessage())
327 return TRUE;
329 stop_wait_op = STOP_WAIT_X;
330 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
331 num_pending = select( __event_max_fd, &read_set, NULL, NULL, &timeout );
332 if ( num_pending == 0 )
334 stop_wait_op = CONT;
335 TIMER_ExpireTimers();
336 return FALSE;
338 else stop_wait_op = CONT;
339 #else /* CONFIG_IPC */
340 num_pending = select( __event_max_fd,
341 &read_set, &write_set, &except_set, &timeout );
342 if ( num_pending == 0)
344 /* Timeout or error */
345 TIMER_ExpireTimers();
346 return FALSE;
348 #endif /* CONFIG_IPC */
350 /* Winsock asynchronous services */
352 if( FD_ISSET( __event_x_connection, &read_set) )
354 num_pending--;
355 if( num_pending )
356 WINSOCK_HandleIO( &__event_max_fd, num_pending, __event_io_set );
358 else /* no X events */
359 return WINSOCK_HandleIO( &__event_max_fd, num_pending, __event_io_set );
362 /* Process current X event (and possibly others that occurred in the meantime) */
367 #ifdef CONFIG_IPC
368 if (DDE_GetRemoteMessage())
370 while(DDE_GetRemoteMessage()) ;
371 return TRUE;
373 #endif /* CONFIG_IPC */
375 XNextEvent( display, &event );
377 if( peek )
379 WND* pWnd;
380 MESSAGEQUEUE* pQ;
382 if (XFindContext( display, ((XAnyEvent *)&event)->window, winContext,
383 (char **)&pWnd ) || (event.type == NoExpose))
384 continue;
386 /* Check only for those events which can be processed
387 * internally. */
389 if( event.type == MotionNotify ||
390 event.type == ButtonPress || event.type == ButtonRelease ||
391 event.type == KeyPress || event.type == KeyRelease ||
392 event.type == SelectionRequest || event.type == SelectionClear )
394 EVENT_ProcessEvent( &event );
395 continue;
398 if( pWnd )
399 if( (pQ = (MESSAGEQUEUE*)GlobalLock16(pWnd->hmemTaskQ)) )
401 pQ->flags |= QUEUE_FLAG_XEVENT;
402 PostEvent(pQ->hTask);
403 XPutBackEvent(display, &event);
404 break;
407 else
408 EVENT_ProcessEvent( &event );
410 while (XPending( display ));
411 return TRUE;
415 /***********************************************************************
416 * EVENT_Synchronize
418 * Synchronize with the X server. Should not be used too often.
420 void EVENT_Synchronize()
422 XEvent event;
424 XSync( display, False );
425 while (XPending( display ))
427 XNextEvent( display, &event );
428 EVENT_ProcessEvent( &event );
432 /***********************************************************************
433 * EVENT_QueryZOrder
435 * Try to synchronize internal z-order with the window manager's.
437 static BOOL32 __check_query_condition( WND** pWndA, WND** pWndB )
439 /* return TRUE if we have at least two managed windows */
441 for( *pWndB = NULL; *pWndA; *pWndA = (*pWndA)->next )
442 if( (*pWndA)->flags & WIN_MANAGED &&
443 (*pWndA)->dwStyle & WS_VISIBLE ) break;
444 if( *pWndA )
445 for( *pWndB = (*pWndA)->next; *pWndB; *pWndB = (*pWndB)->next )
446 if( (*pWndB)->flags & WIN_MANAGED &&
447 (*pWndB)->dwStyle & WS_VISIBLE ) break;
448 return ((*pWndB) != NULL);
451 static Window __get_common_ancestor( Window A, Window B,
452 Window** children, unsigned* total )
454 /* find the real root window */
456 Window root, *childrenB;
457 unsigned totalB;
461 if( *children ) XFree( *children );
462 XQueryTree( display, A, &root, &A, children, total );
463 XQueryTree( display, B, &root, &B, &childrenB, &totalB );
464 if( childrenB ) XFree( childrenB );
465 } while( A != B && A && B );
466 return ( A && B ) ? A : 0 ;
469 static Window __get_top_decoration( Window w, Window ancestor )
471 Window* children, root, prev = w, parent = w;
472 unsigned total;
476 w = parent;
477 XQueryTree( display, w, &root, &parent, &children, &total );
478 if( children ) XFree( children );
479 } while( parent && parent != ancestor );
480 dprintf_event( stddeb, "\t%08x -> %08x\n", (unsigned)prev, (unsigned)w );
481 return ( parent ) ? w : 0 ;
484 static unsigned __td_lookup( Window w, Window* list, unsigned max )
486 unsigned i;
487 for( i = 0; i < max; i++ ) if( list[i] == w ) break;
488 return i;
491 static BOOL32 EVENT_QueryZOrder( WND* pWndCheck )
493 BOOL32 bRet = FALSE;
494 HWND32 hwndInsertAfter = HWND_TOP;
495 WND* pWnd, *pWndZ = WIN_GetDesktop()->child;
496 Window w, parent, *children = NULL;
497 unsigned total, check, pos, best;
499 if( !__check_query_condition(&pWndZ, &pWnd) ) return TRUE;
501 parent = __get_common_ancestor( pWndZ->window, pWnd->window,
502 &children, &total );
503 if( parent && children )
505 w = __get_top_decoration( pWndCheck->window, parent );
506 if( w != children[total - 1] )
508 check = __td_lookup( w, children, total );
509 best = total;
510 for( pWnd = pWndZ; pWnd; pWnd = pWnd->next )
512 if( pWnd != pWndCheck )
514 if( !(pWnd->flags & WIN_MANAGED) ||
515 !(w = __get_top_decoration( pWnd->window, parent )) )
516 continue;
517 pos = __td_lookup( w, children, total );
518 if( pos < best && pos > check )
520 best = pos;
521 hwndInsertAfter = pWnd->hwndSelf;
523 if( check - best == 1 ) break;
526 WIN_UnlinkWindow( pWndCheck->hwndSelf );
527 WIN_LinkWindow( pWndCheck->hwndSelf, hwndInsertAfter);
530 if( children ) XFree( children );
531 return bRet;
535 /***********************************************************************
536 * EVENT_XStateToKeyState
538 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
539 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
541 static WORD EVENT_XStateToKeyState( int state )
543 int kstate = 0;
545 if (state & Button1Mask) kstate |= MK_LBUTTON;
546 if (state & Button2Mask) kstate |= MK_MBUTTON;
547 if (state & Button3Mask) kstate |= MK_RBUTTON;
548 if (state & ShiftMask) kstate |= MK_SHIFT;
549 if (state & ControlMask) kstate |= MK_CONTROL;
550 return kstate;
554 /***********************************************************************
555 * EVENT_Expose
557 static void EVENT_Expose( WND *pWnd, XExposeEvent *event )
559 RECT32 rect;
561 /* Make position relative to client area instead of window */
562 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
563 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
564 rect.right = rect.left + event->width;
565 rect.bottom = rect.top + event->height;
567 PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
568 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
569 (event->count ? 0 : RDW_ERASENOW), 0 );
573 /***********************************************************************
574 * EVENT_GraphicsExpose
576 * This is needed when scrolling area is partially obscured
577 * by non-Wine X window.
579 static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
581 RECT32 rect;
583 /* Make position relative to client area instead of window */
584 rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
585 rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
586 rect.right = rect.left + event->width;
587 rect.bottom = rect.top + event->height;
589 PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
590 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
591 (event->count ? 0 : RDW_ERASENOW), 0 );
595 /***********************************************************************
596 * EVENT_Key
598 * Handle a X key event
600 static void EVENT_Key( XKeyEvent *event )
602 KEYBOARD_HandleEvent( event );
606 /***********************************************************************
607 * EVENT_MotionNotify
609 static void EVENT_MotionNotify( WND *pWnd, XMotionEvent *event )
611 hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
612 event->x_root - desktopX, event->y_root - desktopY,
613 event->time - MSG_WineStartTicks, (DWORD)pWnd->hwndSelf );
617 /***********************************************************************
618 * EVENT_DummyMotionNotify
620 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
622 void EVENT_DummyMotionNotify(void)
624 Window root, child;
625 int rootX, rootY, childX, childY;
626 unsigned int state;
628 if (XQueryPointer( display, rootWindow, &root, &child,
629 &rootX, &rootY, &childX, &childY, &state ))
631 hardware_event(WM_MOUSEMOVE, EVENT_XStateToKeyState( state ), 0L,
632 rootX - desktopX, rootY - desktopY, GetTickCount(), 0 );
637 /***********************************************************************
638 * EVENT_ButtonPress
640 static void EVENT_ButtonPress( WND *pWnd, XButtonEvent *event )
642 static WORD messages[NB_BUTTONS] =
643 { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
644 int buttonNum = event->button - 1;
646 if (buttonNum >= NB_BUTTONS) return;
647 if (SwappedButtons) buttonNum = NB_BUTTONS - 1 - buttonNum;
648 MouseButtonsStates[buttonNum] = 0x8000;
649 AsyncMouseButtonsStates[buttonNum] = 0x8000;
650 hardware_event( messages[buttonNum],
651 EVENT_XStateToKeyState( event->state ), 0L,
652 event->x_root - desktopX, event->y_root - desktopY,
653 event->time - MSG_WineStartTicks, (DWORD)pWnd->hwndSelf );
657 /***********************************************************************
658 * EVENT_ButtonRelease
660 static void EVENT_ButtonRelease( WND *pWnd, XButtonEvent *event )
662 static const WORD messages[NB_BUTTONS] =
663 { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
664 int buttonNum = event->button - 1;
666 if (buttonNum >= NB_BUTTONS) return;
667 if (SwappedButtons) buttonNum = NB_BUTTONS - 1 - buttonNum;
668 MouseButtonsStates[buttonNum] = FALSE;
669 hardware_event( messages[buttonNum],
670 EVENT_XStateToKeyState( event->state ), 0L,
671 event->x_root - desktopX, event->y_root - desktopY,
672 event->time - MSG_WineStartTicks, (DWORD)pWnd->hwndSelf );
676 /**********************************************************************
677 * EVENT_FocusIn
679 static void EVENT_FocusIn( WND *pWnd, XFocusChangeEvent *event )
681 if (Options.managed) EVENT_QueryZOrder( pWnd );
683 if (event->detail != NotifyPointer)
685 HWND32 hwnd = pWnd->hwndSelf;
687 if (hwnd != GetActiveWindow32())
688 WINPOS_ChangeActiveWindow( hwnd, FALSE );
689 if ((hwnd != GetFocus32()) && !IsChild32( hwnd, GetFocus32()))
690 SetFocus32( hwnd );
695 /**********************************************************************
696 * EVENT_FocusOut
698 * Note: only top-level override-redirect windows get FocusOut events.
700 static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event )
702 if (event->detail != NotifyPointer)
704 HWND32 hwnd = pWnd->hwndSelf;
706 if (hwnd == GetActiveWindow32())
707 WINPOS_ChangeActiveWindow( 0, FALSE );
708 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32()))
709 SetFocus32( 0 );
713 /**********************************************************************
714 * EVENT_CheckFocus
716 BOOL32 EVENT_CheckFocus(void)
718 WND* pWnd;
719 Window xW;
720 int state;
722 XGetInputFocus(display, &xW, &state);
723 if( xW == None ||
724 XFindContext(display, xW, winContext, (char **)&pWnd) )
725 return FALSE;
726 return TRUE;
729 /**********************************************************************
730 * EVENT_ConfigureNotify
732 * The ConfigureNotify event is only selected on the desktop window
733 * and on top-level windows when the -managed flag is used.
735 static void EVENT_ConfigureNotify( HWND32 hwnd, XConfigureEvent *event )
737 /* FIXME: with -desktop xxx we get this event _before_ desktop
738 * window structure is created. WIN_GetDesktop() check is a hack.
741 if ( !WIN_GetDesktop() || hwnd == GetDesktopWindow32())
743 desktopX = event->x;
744 desktopY = event->y;
746 else
748 WND *wndPtr = WIN_FindWndPtr( hwnd );
749 WINDOWPOS32 winpos;
750 RECT32 newWindowRect, newClientRect;
751 HRGN32 hrgnOldPos, hrgnNewPos;
752 Window above = event->above;
754 if (!wndPtr || !(wndPtr->flags & WIN_MANAGED)) return;
756 /* Fill WINDOWPOS struct */
757 winpos.flags = SWP_NOACTIVATE | SWP_NOZORDER;
758 winpos.hwnd = hwnd;
759 winpos.x = event->x;
760 winpos.y = event->y;
761 winpos.cx = event->width;
762 winpos.cy = event->height;
764 /* Check for unchanged attributes */
765 if(winpos.x == wndPtr->rectWindow.left &&
766 winpos.y == wndPtr->rectWindow.top)
767 winpos.flags |= SWP_NOMOVE;
768 if(winpos.cx == wndPtr->rectWindow.right - wndPtr->rectWindow.left &&
769 winpos.cy == wndPtr->rectWindow.bottom - wndPtr->rectWindow.top)
770 winpos.flags |= SWP_NOSIZE;
772 /* Send WM_WINDOWPOSCHANGING */
773 SendMessage32A( hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
775 /* Calculate new position and size */
776 newWindowRect.left = event->x;
777 newWindowRect.right = event->x + event->width;
778 newWindowRect.top = event->y;
779 newWindowRect.bottom = event->y + event->height;
781 WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
782 &wndPtr->rectWindow, &wndPtr->rectClient,
783 &winpos, &newClientRect );
785 hrgnOldPos = CreateRectRgnIndirect32( &wndPtr->rectWindow );
786 hrgnNewPos = CreateRectRgnIndirect32( &newWindowRect );
787 CombineRgn32( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF );
789 /* Set new size and position */
790 wndPtr->rectWindow = newWindowRect;
791 wndPtr->rectClient = newClientRect;
792 SendMessage32A( hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
794 if( IsWindow32( hwnd ) )
795 if( above == None ) /* absolute bottom */
797 WIN_UnlinkWindow( hwnd );
798 WIN_LinkWindow( hwnd, HWND_BOTTOM);
800 else EVENT_QueryZOrder( wndPtr ); /* try to outsmart window manager */
802 DeleteObject32(hrgnOldPos);
803 DeleteObject32(hrgnNewPos);
808 /***********************************************************************
809 * EVENT_SelectionRequest
811 static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event )
813 XSelectionEvent result;
814 Atom rprop = None;
815 Window request = event->requestor;
817 if(event->target == XA_STRING)
819 HANDLE16 hText;
820 LPSTR text;
821 int size,i,j;
823 rprop = event->property;
825 if(rprop == None) rprop = event->target;
827 if(event->selection!=XA_PRIMARY) rprop = None;
828 else if(!CLIPBOARD_IsPresent(CF_OEMTEXT)) rprop = None;
829 else
831 /* open to make sure that clipboard is available */
833 BOOL32 couldOpen = OpenClipboard32( pWnd->hwndSelf );
834 char* lpstr = 0;
836 hText = GetClipboardData16(CF_TEXT);
837 text = GlobalLock16(hText);
838 size = GlobalSize16(hText);
840 /* remove carriage returns */
842 lpstr = (char*)xmalloc(size--);
843 for(i=0,j=0; i < size && text[i]; i++ )
845 if( text[i] == '\r' &&
846 (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
847 lpstr[j++] = text[i];
849 lpstr[j]='\0';
851 XChangeProperty(display, request, rprop,
852 XA_STRING, 8, PropModeReplace,
853 lpstr, j);
854 free(lpstr);
856 /* close only if we opened before */
858 if(couldOpen) CloseClipboard32();
862 if(rprop == None)
863 dprintf_event(stddeb,"Request for %s ignored\n", XGetAtomName(display,event->target));
865 result.type = SelectionNotify;
866 result.display = display;
867 result.requestor = request;
868 result.selection = event->selection;
869 result.property = rprop;
870 result.target = event->target;
871 result.time = event->time;
872 XSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
876 /***********************************************************************
877 * EVENT_SelectionNotify
879 static void EVENT_SelectionNotify( XSelectionEvent *event )
881 if (event->selection != XA_PRIMARY) return;
883 if (event->target != XA_STRING) CLIPBOARD_ReadSelection( 0, None );
884 else CLIPBOARD_ReadSelection( event->requestor, event->property );
886 dprintf_clipboard(stddeb,"\tSelectionNotify done!\n");
890 /***********************************************************************
891 * EVENT_SelectionClear
893 static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event )
895 if (event->selection != XA_PRIMARY) return;
896 CLIPBOARD_ReleaseSelection( event->window, pWnd->hwndSelf );
900 /**********************************************************************
901 * EVENT_ClientMessage
903 static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event )
905 if (event->message_type != None && event->format == 32)
907 if ((event->message_type == wmProtocols) &&
908 (((Atom) event->data.l[0]) == wmDeleteWindow))
909 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 );
910 else if ( event->message_type == dndProtocol &&
911 (event->data.l[0] == DndFile || event->data.l[0] == DndFiles) )
913 unsigned long data_length;
914 unsigned long aux_long;
915 unsigned char* p_data = NULL;
916 union {
917 Atom atom_aux;
918 POINT32 pt_aux;
919 int i;
920 } u;
921 int x, y;
922 BOOL16 bAccept;
923 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO));
924 LPDRAGINFO lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
925 SEGPTR spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
926 Window w_aux_root, w_aux_child;
927 WND* pDropWnd;
929 if( !lpDragInfo || !spDragInfo ) return;
931 XQueryPointer( display, pWnd->window, &w_aux_root, &w_aux_child,
932 &x, &y, &u.pt_aux.x, &u.pt_aux.y, (unsigned int*)&aux_long);
934 lpDragInfo->hScope = pWnd->hwndSelf;
935 lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y;
937 /* find out drop point and drop window */
938 if( x < 0 || y < 0 ||
939 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
940 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
941 { bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
942 else
944 bAccept = DRAG_QueryUpdate( pWnd->hwndSelf, spDragInfo, TRUE );
945 x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
947 pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
948 GlobalFree16( hDragInfo );
950 if( bAccept )
952 XGetWindowProperty( display, DefaultRootWindow(display),
953 dndSelection, 0, 65535, FALSE,
954 AnyPropertyType, &u.atom_aux, &u.pt_aux.y,
955 &data_length, &aux_long, &p_data);
957 if( !aux_long && p_data) /* don't bother if > 64K */
959 char *p = (char*) p_data;
960 char *p_drop;
962 aux_long = 0;
963 while( *p ) /* calculate buffer size */
965 p_drop = p;
966 if((u.i = *p) != -1 )
967 u.i = DRIVE_FindDriveRoot( (const char **)&p_drop );
968 if( u.i == -1 ) *p = -1; /* mark as "bad" */
969 else
971 INT32 len = GetShortPathName32A( p, NULL, 0 );
972 if (len) aux_long += len + 1;
973 else *p = -1;
975 p += strlen(p) + 1;
977 if( aux_long && aux_long < 65535 )
979 HDROP16 hDrop;
980 LPDROPFILESTRUCT lpDrop;
982 aux_long += sizeof(DROPFILESTRUCT) + 1;
983 hDrop = (HDROP16)GlobalAlloc16( GMEM_SHARE, aux_long );
984 lpDrop = (LPDROPFILESTRUCT) GlobalLock16( hDrop );
986 if( lpDrop )
988 lpDrop->wSize = sizeof(DROPFILESTRUCT);
989 lpDrop->ptMousePos.x = (INT16)x;
990 lpDrop->ptMousePos.y = (INT16)y;
991 lpDrop->fInNonClientArea = (BOOL16)
992 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
993 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
994 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
995 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
996 p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT);
997 p = p_data;
998 while(*p)
1000 if( *p != -1 ) /* use only "good" entries */
1002 GetShortPathName32A( p, p_drop, 65535 );
1003 p_drop += strlen( p_drop ) + 1;
1005 p += strlen(p) + 1;
1007 *p_drop = '\0';
1008 PostMessage16( pWnd->hwndSelf, WM_DROPFILES,
1009 (WPARAM16)hDrop, 0L );
1013 if( p_data ) XFree(p_data);
1015 } /* WS_EX_ACCEPTFILES */
1016 } /* dndProtocol */
1017 else
1018 dprintf_event( stddeb, "unrecognized ClientMessage\n" );
1022 /**********************************************************************
1023 * EVENT_EnterNotify
1025 * Install colormap when Wine window is focused in
1026 * self-managed mode with private colormap
1029 void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event )
1031 if( !Options.managed && rootWindow == DefaultRootWindow(display) &&
1032 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() )
1033 XInstallColormap( display, COLOR_GetColormap() );
1037 /**********************************************************************
1038 * EVENT_MapNotify
1040 void EVENT_MapNotify( HWND32 hWnd, XMapEvent *event )
1042 HWND32 hwndFocus = GetFocus32();
1044 if (hwndFocus && IsChild32( hWnd, hwndFocus ))
1045 FOCUS_SetXFocus( (HWND32)hwndFocus );
1047 return;
1050 /**********************************************************************
1051 * EVENT_Capture
1053 * We need this to be able to generate double click messages
1054 * when menu code captures mouse in the window without CS_DBLCLK style.
1056 HWND32 EVENT_Capture(HWND32 hwnd, INT16 ht)
1058 Window win;
1059 HWND32 capturePrev = captureWnd;
1061 if (!hwnd)
1063 XUngrabPointer(display, CurrentTime );
1064 captureWnd = NULL; captureHT = 0;
1066 else if ((win = WIN_GetXWindow( hwnd )))
1068 WND* wndPtr = WIN_FindWndPtr( hwnd );
1070 if ( wndPtr &&
1071 (XGrabPointer(display, win, False,
1072 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
1073 GrabModeAsync, GrabModeAsync,
1074 None, None, CurrentTime ) == GrabSuccess) )
1076 dprintf_win(stddeb, "SetCapture(0x%04x)\n", hwnd );
1077 captureWnd = hwnd;
1078 captureHT = ht;
1082 if( capturePrev && capturePrev != captureWnd )
1084 WND* wndPtr = WIN_FindWndPtr( capturePrev );
1085 if( wndPtr && (wndPtr->flags & WIN_ISWIN32) )
1086 SendMessage32A( capturePrev, WM_CAPTURECHANGED, 0L, hwnd);
1088 return capturePrev;
1091 /**********************************************************************
1092 * EVENT_GetCaptureInfo
1094 INT16 EVENT_GetCaptureInfo()
1096 return captureHT;
1099 /**********************************************************************
1100 * SetCapture16 (USER.18)
1102 HWND16 WINAPI SetCapture16( HWND16 hwnd )
1104 return (HWND16)EVENT_Capture( hwnd, HTCLIENT );
1108 /**********************************************************************
1109 * SetCapture32 (USER32.463)
1111 HWND32 WINAPI SetCapture32( HWND32 hwnd )
1113 return EVENT_Capture( hwnd, HTCLIENT );
1117 /**********************************************************************
1118 * ReleaseCapture (USER.19) (USER32.438)
1120 void WINAPI ReleaseCapture(void)
1122 dprintf_win(stddeb, "ReleaseCapture() [%04x]\n", captureWnd );
1123 if( captureWnd ) EVENT_Capture( 0, 0 );
1127 /**********************************************************************
1128 * GetCapture16 (USER.236)
1130 HWND16 WINAPI GetCapture16(void)
1132 return captureWnd;
1136 /**********************************************************************
1137 * GetCapture32 (USER32.207)
1139 HWND32 WINAPI GetCapture32(void)
1141 return captureWnd;
1145 /***********************************************************************
1146 * GetMouseEventProc (USER.337)
1148 FARPROC16 WINAPI GetMouseEventProc(void)
1150 HMODULE16 hmodule = GetModuleHandle16("USER");
1151 return MODULE_GetEntryPoint( hmodule,
1152 MODULE_GetOrdinal( hmodule, "Mouse_Event" ) );
1156 /***********************************************************************
1157 * Mouse_Event (USER.299)
1159 void WINAPI Mouse_Event( CONTEXT *context )
1161 /* Register values:
1162 * AX = mouse event
1163 * BX = horizontal displacement if AX & ME_MOVE
1164 * CX = vertical displacement if AX & ME_MOVE
1165 * DX = button state (?)
1166 * SI = mouse event flags (?)
1168 Window root, child;
1169 int rootX, rootY, childX, childY;
1170 unsigned int state;
1172 if (AX_reg(context) & ME_MOVE)
1174 /* We have to actually move the cursor */
1175 XWarpPointer( display, rootWindow, None, 0, 0, 0, 0,
1176 (short)BX_reg(context), (short)CX_reg(context) );
1177 return;
1179 if (!XQueryPointer( display, rootWindow, &root, &child,
1180 &rootX, &rootY, &childX, &childY, &state )) return;
1181 if (AX_reg(context) & ME_LDOWN)
1182 hardware_event( WM_LBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
1183 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1184 if (AX_reg(context) & ME_LUP)
1185 hardware_event( WM_LBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
1186 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1187 if (AX_reg(context) & ME_RDOWN)
1188 hardware_event( WM_RBUTTONDOWN, EVENT_XStateToKeyState( state ), 0L,
1189 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1190 if (AX_reg(context) & ME_RUP)
1191 hardware_event( WM_RBUTTONUP, EVENT_XStateToKeyState( state ), 0L,
1192 rootX - desktopX, rootY - desktopY, GetTickCount(), 0);
1196 /**********************************************************************
1197 * EnableHardwareInput (USER.331)
1199 BOOL16 WINAPI EnableHardwareInput(BOOL16 bEnable)
1201 BOOL16 bOldState = InputEnabled;
1202 dprintf_event(stdnimp,"EnableHardwareInput(%d);\n", bEnable);
1203 InputEnabled = bEnable;
1204 return bOldState;
1208 /***********************************************************************
1209 * SwapMouseButton16 (USER.186)
1211 BOOL16 WINAPI SwapMouseButton16( BOOL16 fSwap )
1213 BOOL16 ret = SwappedButtons;
1214 SwappedButtons = fSwap;
1215 return ret;
1219 /***********************************************************************
1220 * SwapMouseButton32 (USER32.536)
1222 BOOL32 WINAPI SwapMouseButton32( BOOL32 fSwap )
1224 BOOL32 ret = SwappedButtons;
1225 SwappedButtons = fSwap;
1226 return ret;