Authors: Chris Morgan <cmorgan@wpi.edu>, James Abbatiello <abbejy@wpi.edu>
[wine/multimedia.git] / windows / x11drv / event.c
blob8648324f656a59310105dd34f4c8c0241c52a5a6
1 /*
2 * X11 event driver
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include "config.h"
9 #ifndef X_DISPLAY_MISSING
11 #include <X11/Xatom.h>
12 #include <X11/keysym.h>
13 #include "ts_xlib.h"
14 #include "ts_xresource.h"
15 #include "ts_xutil.h"
17 #include <assert.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include "callback.h"
21 #include "class.h"
22 #include "clipboard.h"
23 #include "dce.h"
24 #include "dde_proc.h"
25 #include "debug.h"
26 #include "drive.h"
27 #include "heap.h"
28 #include "keyboard.h"
29 #include "message.h"
30 #include "mouse.h"
31 #include "options.h"
32 #include "queue.h"
33 #include "shell.h"
34 #include "winpos.h"
35 #include "winsock.h"
36 #include "windef.h"
37 #include "x11drv.h"
39 DECLARE_DEBUG_CHANNEL(event)
40 DECLARE_DEBUG_CHANNEL(win)
42 /* X context to associate a hwnd to an X window */
43 extern XContext winContext;
45 extern Atom wmProtocols;
46 extern Atom wmDeleteWindow;
47 extern Atom dndProtocol;
48 extern Atom dndSelection;
50 extern void X11DRV_KEYBOARD_UpdateState(void);
51 extern void X11DRV_KEYBOARD_HandleEvent(WND *pWnd, XKeyEvent *event);
53 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
55 #define DndNotDnd -1 /* OffiX drag&drop */
56 #define DndUnknown 0
57 #define DndRawData 1
58 #define DndFile 2
59 #define DndFiles 3
60 #define DndText 4
61 #define DndDir 5
62 #define DndLink 6
63 #define DndExe 7
65 #define DndEND 8
67 #define DndURL 128 /* KDE drag&drop */
69 /* EVENT_WaitNetEvent() master fd sets */
71 static fd_set __event_io_set[3];
72 static int __event_max_fd = 0;
73 static int __event_x_connection = 0;
74 static int __wakeup_pipe[2];
76 static const char * const event_names[] =
78 "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
79 "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
80 "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
81 "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
82 "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
83 "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
84 "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
85 "ClientMessage", "MappingNotify"
88 static void EVENT_ProcessEvent( XEvent *event );
90 /* Event handlers */
91 static void EVENT_Key( HWND hWnd, XKeyEvent *event );
92 static void EVENT_ButtonPress( HWND hWnd, XButtonEvent *event );
93 static void EVENT_ButtonRelease( HWND hWnd, XButtonEvent *event );
94 static void EVENT_MotionNotify( HWND hWnd, XMotionEvent *event );
95 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
96 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
97 static void EVENT_Expose( HWND hWnd, XExposeEvent *event );
98 static void EVENT_GraphicsExpose( HWND hWnd, XGraphicsExposeEvent *event );
99 static void EVENT_ConfigureNotify( HWND hWnd, XConfigureEvent *event );
100 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event);
101 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
102 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
103 static void EVENT_MapNotify( HWND pWnd, XMapEvent *event );
104 static void EVENT_UnmapNotify( HWND pWnd, XUnmapEvent *event );
106 /* Usable only with OLVWM - compile option perhaps?
107 static void EVENT_EnterNotify( HWND hWnd, XCrossingEvent *event );
110 static void EVENT_GetGeometry( Window win, int *px, int *py,
111 unsigned int *pwidth, unsigned int *pheight );
114 /***********************************************************************
115 * EVENT_Init
117 * Initialize network IO.
119 BOOL X11DRV_EVENT_Init(void)
121 int i;
122 for( i = 0; i < 3; i++ )
123 FD_ZERO( __event_io_set + i );
125 __event_max_fd = __event_x_connection = ConnectionNumber(display);
126 FD_SET( __event_x_connection, &__event_io_set[EVENT_IO_READ] );
128 /* this pipe is used to be able to wake-up the scheduler(WaitNetEvent) by
129 a 32 bit thread, this will become obsolete when the input thread will be
130 implemented */
131 pipe(__wakeup_pipe);
133 /* make the pipe non-blocking */
134 fcntl(__wakeup_pipe[0], F_SETFL, O_NONBLOCK);
135 fcntl(__wakeup_pipe[1], F_SETFL, O_NONBLOCK);
137 FD_SET( __wakeup_pipe[0], &__event_io_set[EVENT_IO_READ] );
138 if (__wakeup_pipe[0] > __event_max_fd)
139 __event_max_fd = __wakeup_pipe[0];
141 __event_max_fd++;
142 return TRUE;
145 /***********************************************************************
146 * X11DRV_EVENT_AddIO
148 void X11DRV_EVENT_AddIO( int fd, unsigned io_type )
150 FD_SET( fd, &__event_io_set[io_type] );
151 if( __event_max_fd <= fd ) __event_max_fd = fd + 1;
154 /***********************************************************************
155 * X11DRV_EVENT_DeleteIO
157 void X11DRV_EVENT_DeleteIO( int fd, unsigned io_type )
159 FD_CLR( fd, &__event_io_set[io_type] );
162 /***********************************************************************
163 * X11DRV_EVENT_IsUserIdle
165 BOOL16 X11DRV_EVENT_IsUserIdle(void)
167 struct timeval timeout = {0, 0};
168 fd_set check_set;
170 FD_ZERO(&check_set);
171 FD_SET(__event_x_connection, &check_set);
172 if( select(__event_x_connection + 1, &check_set, NULL, NULL, &timeout) > 0 )
173 return TRUE;
174 return FALSE;
178 /***********************************************************************
179 * EVENT_ReadWakeUpPipe
181 * Empty the wake up pipe
183 void EVENT_ReadWakeUpPipe(void)
185 char tmpBuf[10];
186 ssize_t ret;
188 EnterCriticalSection(&X11DRV_CritSection);
190 /* Flush the wake-up pipe, it's just dummy data for waking-up this
191 thread. This will be obsolete when the input thread will be done */
192 while ( (ret = read(__wakeup_pipe[0], &tmpBuf, 10)) == 10 );
194 LeaveCriticalSection(&X11DRV_CritSection);
197 /***********************************************************************
198 * X11DRV_EVENT_WaitNetEvent
200 * Wait for a network event, optionally sleeping until one arrives.
201 * Returns TRUE if an event is pending that cannot be processed in
202 * 'peek' mode, FALSE otherwise.
205 BOOL X11DRV_EVENT_WaitNetEvent( BOOL sleep, BOOL peek )
207 XEvent event;
208 LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0;
209 int pending = TSXPending(display);
211 /* Wait for an event or a timeout. If maxWait is -1, we have no timeout;
212 * in this case, we fall through directly to the XNextEvent loop.
215 if ((maxWait != -1) && !pending)
217 int num_pending;
218 struct timeval timeout;
219 fd_set io_set[3];
221 memcpy( io_set, __event_io_set, sizeof(io_set) );
223 timeout.tv_usec = (maxWait % 1000) * 1000;
224 timeout.tv_sec = maxWait / 1000;
226 #ifdef CONFIG_IPC
227 sigsetjmp(env_wait_x, 1);
228 stop_wait_op= CONT;
230 if (DDE_GetRemoteMessage()) {
231 while(DDE_GetRemoteMessage())
233 return FALSE;
235 stop_wait_op = STOP_WAIT_X;
236 /* The code up to the next "stop_wait_op = CONT" must be reentrant */
237 num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ],
238 &io_set[EVENT_IO_WRITE],
239 &io_set[EVENT_IO_EXCEPT], &timeout );
240 if ( num_pending == 0 )
242 stop_wait_op = CONT;
243 TIMER_ExpireTimers();
244 return FALSE;
246 else stop_wait_op = CONT;
247 #else /* CONFIG_IPC */
248 num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ],
249 &io_set[EVENT_IO_WRITE],
250 &io_set[EVENT_IO_EXCEPT], &timeout );
252 if ( num_pending == 0)
254 /* Timeout or error */
255 TIMER_ExpireTimers();
256 return FALSE;
258 #endif /* CONFIG_IPC */
260 /* Flush the wake-up pipe, it's just dummy data for waking-up this
261 thread. This will be obsolete when the input thread will be done */
262 if ( FD_ISSET( __wakeup_pipe[0], &io_set[EVENT_IO_READ] ) )
264 num_pending--;
265 EVENT_ReadWakeUpPipe();
268 /* Winsock asynchronous services */
270 if( FD_ISSET( __event_x_connection, &io_set[EVENT_IO_READ]) )
272 num_pending--;
273 if( num_pending )
274 WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set );
276 else /* no X events */
278 WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set );
279 return FALSE;
282 else if(!pending)
283 { /* Wait for X11 input. */
284 fd_set set;
285 int max_fd;
287 FD_ZERO(&set);
288 FD_SET(__event_x_connection, &set);
290 /* wait on wake-up pipe also */
291 FD_SET(__wakeup_pipe[0], &set);
292 if (__event_x_connection > __wakeup_pipe[0])
293 max_fd = __event_x_connection + 1;
294 else
295 max_fd = __wakeup_pipe[0] + 1;
297 select(max_fd, &set, 0, 0, 0 );
299 /* Flush the wake-up pipe, it's just dummy data for waking-up this
300 thread. This will be obsolete when the input thread will be done */
301 if ( FD_ISSET( __wakeup_pipe[0], &set ) )
302 EVENT_ReadWakeUpPipe();
305 /* Process current X event (and possibly others that occurred in the meantime) */
307 EnterCriticalSection(&X11DRV_CritSection);
308 while (XPending( display ))
311 #ifdef CONFIG_IPC
312 if (DDE_GetRemoteMessage())
314 LeaveCriticalSection(&X11DRV_CritSection);
315 while(DDE_GetRemoteMessage()) ;
316 return FALSE;
318 #endif /* CONFIG_IPC */
320 XNextEvent( display, &event );
322 if( peek )
324 /* Check only for those events which can be processed
325 * internally. */
327 if( event.type == MotionNotify ||
328 event.type == ButtonPress || event.type == ButtonRelease ||
329 event.type == KeyPress || event.type == KeyRelease ||
330 event.type == SelectionRequest || event.type == SelectionClear ||
331 event.type == ClientMessage )
333 LeaveCriticalSection(&X11DRV_CritSection);
334 EVENT_ProcessEvent( &event );
335 EnterCriticalSection(&X11DRV_CritSection);
336 continue;
339 if ( event.type == NoExpose )
340 continue;
342 XPutBackEvent(display, &event);
343 LeaveCriticalSection(&X11DRV_CritSection);
344 return TRUE;
346 else
348 LeaveCriticalSection(&X11DRV_CritSection);
349 EVENT_ProcessEvent( &event );
350 EnterCriticalSection(&X11DRV_CritSection);
353 LeaveCriticalSection(&X11DRV_CritSection);
355 return FALSE;
358 /***********************************************************************
359 * EVENT_Synchronize
361 * Synchronize with the X server. Should not be used too often.
363 void X11DRV_EVENT_Synchronize()
365 XEvent event;
367 /* Use of the X critical section is needed or we have a small
368 * race between XPending() and XNextEvent().
370 EnterCriticalSection( &X11DRV_CritSection );
371 XSync( display, False );
372 while (XPending( display ))
374 XNextEvent( display, &event );
375 /* unlock X critsection for EVENT_ProcessEvent() might switch tasks */
376 LeaveCriticalSection( &X11DRV_CritSection );
377 EVENT_ProcessEvent( &event );
378 EnterCriticalSection( &X11DRV_CritSection );
380 LeaveCriticalSection( &X11DRV_CritSection );
383 /***********************************************************************
384 * EVENT_ProcessEvent
386 * Process an X event.
388 static void EVENT_ProcessEvent( XEvent *event )
390 WND *pWnd;
391 HWND hWnd;
393 switch (event->type)
395 case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
396 FIXME(event,"Got SelectionNotify - must not happen!\n");
397 /* fall through */
399 /* We get all these because of StructureNotifyMask.
400 This check is placed here to avoid getting error messages below,
401 as X might send some of these even for windows that have already
402 been deleted ... */
403 case CirculateNotify:
404 case CreateNotify:
405 case DestroyNotify:
406 case GravityNotify:
407 case ReparentNotify:
408 return;
411 if ( TSXFindContext( display, event->xany.window, winContext,
412 (char **)&pWnd ) != 0) {
413 if ( event->type == ClientMessage) {
414 /* query window (drag&drop event contains only drag window) */
415 Window root, child;
416 int root_x, root_y, child_x, child_y;
417 unsigned u;
418 TSXQueryPointer( display, X11DRV_GetXRootWindow(), &root, &child,
419 &root_x, &root_y, &child_x, &child_y, &u);
420 if (TSXFindContext( display, child, winContext, (char **)&pWnd ) != 0)
421 return;
422 } else {
423 pWnd = NULL; /* Not for a registered window */
427 WIN_LockWndPtr(pWnd);
429 if(!pWnd)
430 hWnd = 0;
431 else
432 hWnd = pWnd->hwndSelf;
435 if ( !pWnd && event->xany.window != X11DRV_GetXRootWindow() )
436 ERR( event, "Got event %s for unknown Window %08lx\n",
437 event_names[event->type], event->xany.window );
438 else
439 TRACE( event, "Got event %s for hwnd %04x\n",
440 event_names[event->type], hWnd );
442 WIN_ReleaseWndPtr(pWnd);
445 switch(event->type)
447 case KeyPress:
448 case KeyRelease:
449 EVENT_Key( hWnd, (XKeyEvent*)event );
450 break;
452 case ButtonPress:
453 EVENT_ButtonPress( hWnd, (XButtonEvent*)event );
454 break;
456 case ButtonRelease:
457 EVENT_ButtonRelease( hWnd, (XButtonEvent*)event );
458 break;
460 case MotionNotify:
461 /* Wine between two fast machines across the overloaded campus
462 ethernet gets very boged down in MotionEvents. The following
463 simply finds the last motion event in the queue and drops
464 the rest. On a good link events are servered before they build
465 up so this doesn't take place. On a slow link this may cause
466 problems if the event order is important. I'm not yet seen
467 of any problems. Jon 7/6/96.
469 while (TSXCheckTypedWindowEvent(display,((XAnyEvent *)event)->window,
470 MotionNotify, event));
471 EVENT_MotionNotify( hWnd, (XMotionEvent*)event );
472 break;
474 case FocusIn:
475 if (!hWnd) return;
476 EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
477 break;
479 case FocusOut:
480 if (!hWnd) return;
481 EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
482 break;
484 case Expose:
485 EVENT_Expose( hWnd, (XExposeEvent *)event );
486 break;
488 case GraphicsExpose:
489 EVENT_GraphicsExpose( hWnd, (XGraphicsExposeEvent *)event );
490 break;
492 case ConfigureNotify:
493 if (!hWnd) return;
494 EVENT_ConfigureNotify( hWnd, (XConfigureEvent*)event );
495 break;
497 case SelectionRequest:
498 if (!hWnd) return;
499 EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event );
500 break;
502 case SelectionClear:
503 if (!hWnd) return;
504 EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
505 break;
507 case ClientMessage:
508 if (!hWnd) return;
509 EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
510 break;
512 #if 0
513 case EnterNotify:
514 EVENT_EnterNotify( hWnd, (XCrossingEvent *) event );
515 break;
516 #endif
518 case NoExpose:
519 break;
521 case MapNotify:
522 if (!hWnd) return;
523 EVENT_MapNotify( hWnd, (XMapEvent *)event );
524 break;
526 case UnmapNotify:
527 if (!hWnd) return;
528 EVENT_UnmapNotify( hWnd, (XUnmapEvent *)event );
529 break;
531 default:
532 WARN(event, "Unprocessed event %s for hwnd %04x\n",
533 event_names[event->type], hWnd );
534 break;
538 /***********************************************************************
539 * EVENT_QueryZOrder
541 * Synchronize internal z-order with the window manager's.
543 static BOOL __check_query_condition( WND** pWndA, WND** pWndB )
545 /* return TRUE if we have at least two managed windows */
547 for( *pWndB = NULL; *pWndA; *pWndA = (*pWndA)->next )
548 if( (*pWndA)->flags & WIN_MANAGED &&
549 (*pWndA)->dwStyle & WS_VISIBLE ) break;
550 if( *pWndA )
551 for( *pWndB = (*pWndA)->next; *pWndB; *pWndB = (*pWndB)->next )
552 if( (*pWndB)->flags & WIN_MANAGED &&
553 (*pWndB)->dwStyle & WS_VISIBLE ) break;
554 return ((*pWndB) != NULL);
557 static Window __get_common_ancestor( Window A, Window B,
558 Window** children, unsigned* total )
560 /* find the real root window */
562 Window root, *childrenB;
563 unsigned totalB;
567 TSXQueryTree( display, A, &root, &A, children, total );
568 TSXQueryTree( display, B, &root, &B, &childrenB, &totalB );
569 if( childrenB ) TSXFree( childrenB );
570 if( *children ) TSXFree( *children );
571 } while( A != B && A && B );
573 if( A && B )
575 TSXQueryTree( display, A, &root, &B, children, total );
576 return A;
578 return 0 ;
581 static Window __get_top_decoration( Window w, Window ancestor )
583 Window* children, root, prev = w, parent = w;
584 unsigned total;
588 w = parent;
589 TSXQueryTree( display, w, &root, &parent, &children, &total );
590 if( children ) TSXFree( children );
591 } while( parent && parent != ancestor );
592 TRACE(event, "\t%08x -> %08x\n", (unsigned)prev, (unsigned)w );
593 return ( parent ) ? w : 0 ;
596 static unsigned __td_lookup( Window w, Window* list, unsigned max )
598 unsigned i;
599 for( i = max - 1; i >= 0; i-- ) if( list[i] == w ) break;
600 return i;
603 static BOOL EVENT_QueryZOrder( HWND hWndCheck)
605 BOOL bRet = FALSE;
606 HWND hwndInsertAfter = HWND_TOP;
607 WND *pWndCheck = WIN_FindWndPtr(hWndCheck);
608 WND *pDesktop = WIN_GetDesktop();
609 WND *pWnd, *pWndZ = WIN_LockWndPtr(pDesktop->child);
610 Window w, parent, *children = NULL;
611 unsigned total, check, pos, best;
613 if( !__check_query_condition(&pWndZ, &pWnd) )
615 WIN_ReleaseWndPtr(pWndCheck);
616 WIN_ReleaseWndPtr(pDesktop->child);
617 WIN_ReleaseDesktop();
618 return TRUE;
620 WIN_LockWndPtr(pWndZ);
621 WIN_LockWndPtr(pWnd);
622 WIN_ReleaseWndPtr(pDesktop->child);
623 WIN_ReleaseDesktop();
625 parent = __get_common_ancestor( X11DRV_WND_GetXWindow(pWndZ),
626 X11DRV_WND_GetXWindow(pWnd),
627 &children, &total );
628 if( parent && children )
630 /* w is the ancestor if pWndCheck that is a direct descendant of 'parent' */
632 w = __get_top_decoration( X11DRV_WND_GetXWindow(pWndCheck), parent );
634 if( w != children[total-1] ) /* check if at the top */
636 /* X child at index 0 is at the bottom, at index total-1 is at the top */
637 check = __td_lookup( w, children, total );
638 best = total;
640 for( WIN_UpdateWndPtr(&pWnd,pWndZ); pWnd;WIN_UpdateWndPtr(&pWnd,pWnd->next))
642 /* go through all windows in Wine z-order... */
644 if( pWnd != pWndCheck )
646 if( !(pWnd->flags & WIN_MANAGED) ||
647 !(w = __get_top_decoration( X11DRV_WND_GetXWindow(pWnd), parent )) )
648 continue;
649 pos = __td_lookup( w, children, total );
650 if( pos < best && pos > check )
652 /* find a nearest Wine window precedes
653 * pWndCheck in the real z-order... */
654 best = pos;
655 hwndInsertAfter = pWnd->hwndSelf;
657 if( best - check == 1 ) break;
660 /* and link pWndCheck right behind it in the local z-order */
662 WIN_UnlinkWindow( pWndCheck->hwndSelf );
663 WIN_LinkWindow( pWndCheck->hwndSelf, hwndInsertAfter);
665 if( children ) TSXFree( children );
666 WIN_ReleaseWndPtr(pWnd);
667 WIN_ReleaseWndPtr(pWndZ);
668 WIN_ReleaseWndPtr(pWndCheck);
669 return bRet;
672 /***********************************************************************
673 * EVENT_XStateToKeyState
675 * Translate a X event state (Button1Mask, ShiftMask, etc...) to
676 * a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
678 static WORD EVENT_XStateToKeyState( int state )
680 int kstate = 0;
682 if (state & Button1Mask) kstate |= MK_LBUTTON;
683 if (state & Button2Mask) kstate |= MK_MBUTTON;
684 if (state & Button3Mask) kstate |= MK_RBUTTON;
685 if (state & ShiftMask) kstate |= MK_SHIFT;
686 if (state & ControlMask) kstate |= MK_CONTROL;
687 return kstate;
690 /***********************************************************************
691 * X11DRV_EVENT_QueryPointer
693 BOOL X11DRV_EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *state)
695 Window root, child;
696 int rootX, rootY, winX, winY;
697 unsigned int xstate;
699 if (!TSXQueryPointer( display, X11DRV_GetXRootWindow(), &root, &child,
700 &rootX, &rootY, &winX, &winY, &xstate ))
701 return FALSE;
703 if(posX)
704 *posX = (DWORD)winX;
705 if(posY)
706 *posY = (DWORD)winY;
707 if(state)
708 *state = EVENT_XStateToKeyState( xstate );
710 return TRUE;
713 /***********************************************************************
714 * EVENT_Expose
716 static void EVENT_Expose( HWND hWnd, XExposeEvent *event )
718 RECT rect;
720 WND *pWnd = WIN_FindWndPtr(hWnd);
721 /* Make position relative to client area instead of window */
722 rect.left = event->x - (pWnd? (pWnd->rectClient.left - pWnd->rectWindow.left) : 0);
723 rect.top = event->y - (pWnd? (pWnd->rectClient.top - pWnd->rectWindow.top) : 0);
724 rect.right = rect.left + event->width;
725 rect.bottom = rect.top + event->height;
726 WIN_ReleaseWndPtr(pWnd);
728 Callout.RedrawWindow( hWnd, &rect, 0,
729 RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
730 (event->count ? 0 : RDW_ERASENOW) );
734 /***********************************************************************
735 * EVENT_GraphicsExpose
737 * This is needed when scrolling area is partially obscured
738 * by non-Wine X window.
740 static void EVENT_GraphicsExpose( HWND hWnd, XGraphicsExposeEvent *event )
742 RECT rect;
743 WND *pWnd = WIN_FindWndPtr(hWnd);
745 /* Make position relative to client area instead of window */
746 rect.left = event->x - (pWnd? (pWnd->rectClient.left - pWnd->rectWindow.left) : 0);
747 rect.top = event->y - (pWnd? (pWnd->rectClient.top - pWnd->rectWindow.top) : 0);
748 rect.right = rect.left + event->width;
749 rect.bottom = rect.top + event->height;
751 WIN_ReleaseWndPtr(pWnd);
753 Callout.RedrawWindow( hWnd, &rect, 0,
754 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
755 (event->count ? 0 : RDW_ERASENOW) );
759 /***********************************************************************
760 * EVENT_Key
762 * Handle a X key event
764 static void EVENT_Key( HWND hWnd, XKeyEvent *event )
766 WND *pWnd = WIN_FindWndPtr(hWnd);
767 X11DRV_KEYBOARD_HandleEvent( pWnd, event );
768 WIN_ReleaseWndPtr(pWnd);
773 /***********************************************************************
774 * EVENT_MotionNotify
776 static void EVENT_MotionNotify( HWND hWnd, XMotionEvent *event )
778 WND *pWnd = WIN_FindWndPtr(hWnd);
779 int xOffset = pWnd? pWnd->rectWindow.left : 0;
780 int yOffset = pWnd? pWnd->rectWindow.top : 0;
781 WIN_ReleaseWndPtr(pWnd);
783 MOUSE_SendEvent( MOUSEEVENTF_MOVE,
784 xOffset + event->x, yOffset + event->y,
785 EVENT_XStateToKeyState( event->state ),
786 event->time - MSG_WineStartTicks,
787 hWnd);
791 /***********************************************************************
792 * X11DRV_EVENT_DummyMotionNotify
794 * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
796 void X11DRV_EVENT_DummyMotionNotify(void)
798 DWORD winX, winY, state;
800 if ( EVENT_QueryPointer( &winX, &winY, &state ) )
802 MOUSE_SendEvent( MOUSEEVENTF_MOVE, winX, winY, state,
803 GetTickCount(), 0 );
808 /***********************************************************************
809 * EVENT_ButtonPress
811 static void EVENT_ButtonPress( HWND hWnd, XButtonEvent *event )
813 static WORD statusCodes[NB_BUTTONS] =
814 { MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_RIGHTDOWN };
815 int buttonNum = event->button - 1;
817 WND *pWnd = WIN_FindWndPtr(hWnd);
818 int xOffset = pWnd? pWnd->rectWindow.left : 0;
819 int yOffset = pWnd? pWnd->rectWindow.top : 0;
820 WORD keystate;
822 WIN_ReleaseWndPtr(pWnd);
824 if (buttonNum >= NB_BUTTONS) return;
827 * Get the compatible keystate
829 keystate = EVENT_XStateToKeyState( event->state );
832 * Make sure that the state of the button that was just
833 * pressed is "down".
835 switch (buttonNum)
837 case 0:
838 keystate |= MK_LBUTTON;
839 break;
840 case 1:
841 keystate |= MK_MBUTTON;
842 break;
843 case 2:
844 keystate |= MK_RBUTTON;
845 break;
848 MOUSE_SendEvent( statusCodes[buttonNum],
849 xOffset + event->x, yOffset + event->y,
850 keystate,
851 event->time - MSG_WineStartTicks,
852 hWnd);
856 /***********************************************************************
857 * EVENT_ButtonRelease
859 static void EVENT_ButtonRelease( HWND hWnd, XButtonEvent *event )
861 static WORD statusCodes[NB_BUTTONS] =
862 { MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_RIGHTUP };
863 int buttonNum = event->button - 1;
864 WND *pWnd = WIN_FindWndPtr(hWnd);
865 int xOffset = pWnd? pWnd->rectWindow.left : 0;
866 int yOffset = pWnd? pWnd->rectWindow.top : 0;
867 WORD keystate;
869 WIN_ReleaseWndPtr(pWnd);
871 if (buttonNum >= NB_BUTTONS) return;
874 * Get the compatible keystate
876 keystate = EVENT_XStateToKeyState( event->state );
879 * Make sure that the state of the button that was just
880 * released is "up".
882 switch (buttonNum)
884 case 0:
885 keystate &= ~MK_LBUTTON;
886 break;
887 case 1:
888 keystate &= ~MK_MBUTTON;
889 break;
890 case 2:
891 keystate &= ~MK_RBUTTON;
892 break;
895 MOUSE_SendEvent( statusCodes[buttonNum],
896 xOffset + event->x, yOffset + event->y,
897 keystate,
898 event->time - MSG_WineStartTicks,
899 hWnd);
903 /**********************************************************************
904 * EVENT_FocusIn
906 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event )
908 if (Options.managed) EVENT_QueryZOrder( hWnd );
910 if (event->detail != NotifyPointer)
912 if (hWnd != GetActiveWindow())
914 WINPOS_ChangeActiveWindow( hWnd, FALSE );
915 X11DRV_KEYBOARD_UpdateState();
917 if ((hWnd != GetFocus()) && !IsChild( hWnd, GetFocus()))
918 SetFocus( hWnd );
923 /**********************************************************************
924 * EVENT_FocusOut
926 * Note: only top-level override-redirect windows get FocusOut events.
928 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event )
930 if (event->detail != NotifyPointer)
932 if (hWnd == GetActiveWindow())
934 SendMessageA( hWnd, WM_CANCELMODE, 0, 0 );
935 WINPOS_ChangeActiveWindow( 0, FALSE );
937 if ((hWnd == GetFocus()) || IsChild( hWnd, GetFocus()))
938 SetFocus( 0 );
942 /**********************************************************************
943 * X11DRV_EVENT_CheckFocus
945 BOOL X11DRV_EVENT_CheckFocus(void)
947 WND* pWnd;
948 Window xW;
949 int state;
951 TSXGetInputFocus(display, &xW, &state);
952 if( xW == None ||
953 TSXFindContext(display, xW, winContext, (char **)&pWnd) )
954 return FALSE;
955 return TRUE;
958 /**********************************************************************
959 * EVENT_GetGeometry
961 * Helper function for ConfigureNotify handling.
962 * Get the new geometry of a window relative to the root window.
964 static void EVENT_GetGeometry( Window win, int *px, int *py,
965 unsigned int *pwidth, unsigned int *pheight )
967 Window root, parent, *children;
968 int xpos, ypos;
969 unsigned int width, height, border, depth, nb_children;
971 if (!TSXGetGeometry( display, win, &root, px, py, pwidth, pheight,
972 &border, &depth )) return;
973 if (win == X11DRV_GetXRootWindow())
975 *px = *py = 0;
976 return;
979 for (;;)
981 if (!TSXQueryTree(display, win, &root, &parent, &children, &nb_children))
982 return;
983 TSXFree( children );
984 if (parent == X11DRV_GetXRootWindow()) break;
985 win = parent;
986 if (!TSXGetGeometry( display, win, &root, &xpos, &ypos,
987 &width, &height, &border, &depth )) return;
988 *px += xpos;
989 *py += ypos;
994 /**********************************************************************
995 * EVENT_ConfigureNotify
997 * The ConfigureNotify event is only selected on top-level windows
998 * when the -managed flag is used.
1000 static void EVENT_ConfigureNotify( HWND hWnd, XConfigureEvent *event )
1002 WINDOWPOS winpos;
1003 RECT newWindowRect, newClientRect;
1004 RECT oldWindowRect, oldClientRect;
1005 Window above = event->above;
1006 int x, y;
1007 unsigned int width, height;
1009 WND *pWnd = WIN_FindWndPtr(hWnd);
1010 assert (pWnd->flags & WIN_MANAGED);
1012 /* We don't rely on the event geometry info, because it is relative
1013 * to parent and not to root, and it may be wrong (XFree sets x,y to 0,0
1014 * if the window hasn't moved).
1016 EVENT_GetGeometry( event->window, &x, &y, &width, &height );
1018 TRACE(win, "%04x adjusted to (%i,%i)-(%i,%i)\n", pWnd->hwndSelf,
1019 x, y, x + width, y + height );
1021 /* Fill WINDOWPOS struct */
1022 winpos.flags = SWP_NOACTIVATE | SWP_NOZORDER;
1023 winpos.hwnd = hWnd;
1024 winpos.x = x;
1025 winpos.y = y;
1026 winpos.cx = width;
1027 winpos.cy = height;
1029 /* Check for unchanged attributes */
1030 if (winpos.x == pWnd->rectWindow.left && winpos.y == pWnd->rectWindow.top)
1031 winpos.flags |= SWP_NOMOVE;
1032 if ((winpos.cx == pWnd->rectWindow.right - pWnd->rectWindow.left) &&
1033 (winpos.cy == pWnd->rectWindow.bottom - pWnd->rectWindow.top))
1034 winpos.flags |= SWP_NOSIZE;
1035 else
1037 RECT rect;
1039 rect.left = 0;
1040 rect.top = 0;
1041 rect.right = pWnd->rectWindow.right - pWnd->rectWindow.left;
1042 rect.bottom = pWnd->rectWindow.bottom - pWnd->rectWindow.top;
1044 DCE_InvalidateDCE( pWnd, &rect );
1047 /* Send WM_WINDOWPOSCHANGING */
1048 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
1050 if (!IsWindow( winpos.hwnd ))
1052 WIN_ReleaseWndPtr(pWnd);
1053 return;
1056 /* Calculate new position and size */
1057 newWindowRect.left = x;
1058 newWindowRect.right = x + width;
1059 newWindowRect.top = y;
1060 newWindowRect.bottom = y + height;
1062 WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
1063 &pWnd->rectWindow, &pWnd->rectClient,
1064 &winpos, &newClientRect );
1066 if (!IsWindow( winpos.hwnd ))
1068 WIN_ReleaseWndPtr(pWnd);
1069 return;
1072 oldWindowRect = pWnd->rectWindow;
1073 oldClientRect = pWnd->rectClient;
1075 /* Set new size and position */
1076 pWnd->rectWindow = newWindowRect;
1077 pWnd->rectClient = newClientRect;
1079 /* FIXME: Copy valid bits */
1081 if( oldClientRect.top - oldWindowRect.top != newClientRect.top - newWindowRect.top ||
1082 oldClientRect.left - oldWindowRect.left != newClientRect.left - newWindowRect.left )
1083 RedrawWindow( winpos.hwnd, NULL, 0, RDW_FRAME | RDW_ALLCHILDREN |
1084 RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW );
1086 WIN_ReleaseWndPtr(pWnd);
1088 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
1090 if (!IsWindow( winpos.hwnd )) return;
1091 if( above == None ) /* absolute bottom */
1093 WIN_UnlinkWindow( winpos.hwnd );
1094 WIN_LinkWindow( winpos.hwnd, HWND_BOTTOM);
1096 else EVENT_QueryZOrder( hWnd ); /* try to outsmart window manager */
1100 /***********************************************************************
1101 * EVENT_SelectionRequest
1103 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event )
1105 XSelectionEvent result;
1106 Atom rprop = None;
1107 Window request = event->requestor;
1109 if(event->target == XA_STRING)
1111 HANDLE16 hText;
1112 LPSTR text;
1113 int size,i,j;
1115 rprop = event->property;
1117 if( rprop == None )
1118 rprop = event->target;
1120 if( event->selection != XA_PRIMARY )
1121 rprop = None;
1122 else
1123 if( !CLIPBOARD_IsPresent(CF_OEMTEXT) )
1124 rprop = None;
1125 else
1127 /* open to make sure that clipboard is available */
1129 BOOL couldOpen = OpenClipboard( hWnd );
1130 char* lpstr = 0;
1132 hText = GetClipboardData16(CF_TEXT);
1133 text = GlobalLock16(hText);
1134 size = GlobalSize16(hText);
1136 /* remove carriage returns */
1138 lpstr = (char*)HEAP_xalloc( GetProcessHeap(), 0, size-- );
1139 for(i=0,j=0; i < size && text[i]; i++ )
1141 if( text[i] == '\r' &&
1142 (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
1143 lpstr[j++] = text[i];
1145 lpstr[j]='\0';
1147 TSXChangeProperty(display, request, rprop,
1148 XA_STRING, 8, PropModeReplace,
1149 lpstr, j);
1150 HeapFree( GetProcessHeap(), 0, lpstr );
1152 /* close only if we opened before */
1154 if(couldOpen) CloseClipboard();
1158 if( rprop == None)
1159 TRACE(event,"Request for %s ignored\n", TSXGetAtomName(display,event->target));
1161 /* reply to sender */
1163 result.type = SelectionNotify;
1164 result.display = display;
1165 result.requestor = request;
1166 result.selection = event->selection;
1167 result.property = rprop;
1168 result.target = event->target;
1169 result.time = event->time;
1170 TSXSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
1173 /***********************************************************************
1174 * EVENT_SelectionClear
1176 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
1178 if (event->selection != XA_PRIMARY) return;
1179 X11DRV_CLIPBOARD_ReleaseSelection( event->window, hWnd );
1183 /**********************************************************************
1184 * EVENT_DropFromOffix
1186 * don't know if it still works (last Changlog is from 96/11/04)
1188 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
1190 unsigned long data_length;
1191 unsigned long aux_long;
1192 unsigned char* p_data = NULL;
1193 union {
1194 Atom atom_aux;
1195 struct {
1196 int x;
1197 int y;
1198 } pt_aux;
1199 int i;
1200 } u;
1201 int x, y;
1202 BOOL16 bAccept;
1203 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO));
1204 LPDRAGINFO lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
1205 SEGPTR spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
1206 Window w_aux_root, w_aux_child;
1207 WND* pDropWnd;
1208 WND* pWnd;
1210 if( !lpDragInfo || !spDragInfo ) return;
1212 pWnd = WIN_FindWndPtr(hWnd);
1214 TSXQueryPointer( display, X11DRV_WND_GetXWindow(pWnd), &w_aux_root, &w_aux_child,
1215 &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
1216 (unsigned int*)&aux_long);
1218 lpDragInfo->hScope = hWnd;
1219 lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y;
1221 /* find out drop point and drop window */
1222 if( x < 0 || y < 0 ||
1223 x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1224 y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1225 { bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
1226 else
1228 bAccept = DRAG_QueryUpdate( hWnd, spDragInfo, TRUE );
1229 x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
1231 pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
1232 WIN_ReleaseWndPtr(pWnd);
1234 GlobalFree16( hDragInfo );
1236 if( bAccept )
1238 TSXGetWindowProperty( display, DefaultRootWindow(display),
1239 dndSelection, 0, 65535, FALSE,
1240 AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1241 &data_length, &aux_long, &p_data);
1243 if( !aux_long && p_data) /* don't bother if > 64K */
1245 char *p = (char*) p_data;
1246 char *p_drop;
1248 aux_long = 0;
1249 while( *p ) /* calculate buffer size */
1251 p_drop = p;
1252 if((u.i = *p) != -1 )
1253 u.i = DRIVE_FindDriveRoot( (const char **)&p_drop );
1254 if( u.i == -1 ) *p = -1; /* mark as "bad" */
1255 else
1257 INT len = GetShortPathNameA( p, NULL, 0 );
1258 if (len) aux_long += len + 1;
1259 else *p = -1;
1261 p += strlen(p) + 1;
1263 if( aux_long && aux_long < 65535 )
1265 HDROP16 hDrop;
1266 LPDROPFILESTRUCT16 lpDrop;
1268 aux_long += sizeof(DROPFILESTRUCT16) + 1;
1269 hDrop = (HDROP16)GlobalAlloc16( GMEM_SHARE, aux_long );
1270 lpDrop = (LPDROPFILESTRUCT16) GlobalLock16( hDrop );
1272 if( lpDrop )
1274 lpDrop->wSize = sizeof(DROPFILESTRUCT16);
1275 lpDrop->ptMousePos.x = (INT16)x;
1276 lpDrop->ptMousePos.y = (INT16)y;
1277 lpDrop->fInNonClientArea = (BOOL16)
1278 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1279 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1280 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1281 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1282 p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT16);
1283 p = p_data;
1284 while(*p)
1286 if( *p != -1 ) /* use only "good" entries */
1288 GetShortPathNameA( p, p_drop, 65535 );
1289 p_drop += strlen( p_drop ) + 1;
1291 p += strlen(p) + 1;
1293 *p_drop = '\0';
1294 PostMessage16( hWnd, WM_DROPFILES,
1295 (WPARAM16)hDrop, 0L );
1299 if( p_data ) TSXFree(p_data);
1301 } /* WS_EX_ACCEPTFILES */
1303 WIN_ReleaseWndPtr(pDropWnd);
1306 /**********************************************************************
1307 * EVENT_DropURLs
1309 * drop items are separated by \n
1310 * each item is prefixed by its mime type
1312 * event->data.l[3], event->data.l[4] contains drop x,y position
1314 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
1316 WND *pDropWnd;
1317 WND *pWnd;
1318 unsigned long data_length;
1319 unsigned long aux_long, drop_len = 0;
1320 unsigned char *p_data = NULL; /* property data */
1321 char *p_drop = NULL;
1322 char *p, *next;
1323 int x, y, drop32 = FALSE ;
1324 union {
1325 Atom atom_aux;
1326 int i;
1327 Window w_aux;
1328 } u; /* unused */
1329 union {
1330 HDROP16 h16;
1331 HDROP h32;
1332 } hDrop;
1334 pWnd = WIN_FindWndPtr(hWnd);
1335 drop32 = pWnd->flags & WIN_ISWIN32;
1337 if (!(pWnd->dwExStyle & WS_EX_ACCEPTFILES))
1339 WIN_ReleaseWndPtr(pWnd);
1340 return;
1342 WIN_ReleaseWndPtr(pWnd);
1344 TSXGetWindowProperty( display, DefaultRootWindow(display),
1345 dndSelection, 0, 65535, FALSE,
1346 AnyPropertyType, &u.atom_aux, &u.i,
1347 &data_length, &aux_long, &p_data);
1348 if (aux_long)
1349 WARN(event,"property too large, truncated!\n");
1350 TRACE(event,"urls=%s\n", p_data);
1352 if( !aux_long && p_data) { /* don't bother if > 64K */
1353 /* calculate length */
1354 p = p_data;
1355 next = strchr(p, '\n');
1356 while (p) {
1357 if (next) *next=0;
1358 if (strncmp(p,"file:",5) == 0 ) {
1359 INT len = GetShortPathNameA( p+5, NULL, 0 );
1360 if (len) drop_len += len + 1;
1362 if (next) {
1363 *next = '\n';
1364 p = next + 1;
1365 next = strchr(p, '\n');
1366 } else {
1367 p = NULL;
1371 if( drop_len && drop_len < 65535 ) {
1372 TSXQueryPointer( display, X11DRV_GetXRootWindow(), &u.w_aux, &u.w_aux,
1373 &x, &y, &u.i, &u.i, &u.i);
1375 pDropWnd = WIN_FindWndPtr( hWnd );
1377 if (drop32) {
1378 LPDROPFILESTRUCT lpDrop;
1379 drop_len += sizeof(DROPFILESTRUCT) + 1;
1380 hDrop.h32 = (HDROP)GlobalAlloc( GMEM_SHARE, drop_len );
1381 lpDrop = (LPDROPFILESTRUCT) GlobalLock( hDrop.h32 );
1383 if( lpDrop ) {
1384 lpDrop->lSize = sizeof(DROPFILESTRUCT);
1385 lpDrop->ptMousePos.x = (INT)x;
1386 lpDrop->ptMousePos.y = (INT)y;
1387 lpDrop->fInNonClientArea = (BOOL)
1388 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1389 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1390 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1391 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1392 lpDrop->fWideChar = FALSE;
1393 p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT);
1395 } else {
1396 LPDROPFILESTRUCT16 lpDrop;
1397 drop_len += sizeof(DROPFILESTRUCT16) + 1;
1398 hDrop.h16 = (HDROP16)GlobalAlloc16( GMEM_SHARE, drop_len );
1399 lpDrop = (LPDROPFILESTRUCT16) GlobalLock16( hDrop.h16 );
1401 if( lpDrop ) {
1402 lpDrop->wSize = sizeof(DROPFILESTRUCT16);
1403 lpDrop->ptMousePos.x = (INT16)x;
1404 lpDrop->ptMousePos.y = (INT16)y;
1405 lpDrop->fInNonClientArea = (BOOL16)
1406 ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) ||
1407 y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) ||
1408 x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1409 y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1410 p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT16);
1414 /* create message content */
1415 if (p_drop) {
1416 p = p_data;
1417 next = strchr(p, '\n');
1418 while (p) {
1419 if (next) *next=0;
1420 if (strncmp(p,"file:",5) == 0 ) {
1421 INT len = GetShortPathNameA( p+5, p_drop, 65535 );
1422 if (len) {
1423 TRACE(event, "drop file %s as %s\n", p+5, p_drop);
1424 p_drop += len+1;
1425 } else {
1426 WARN(event, "can't convert file %s to dos name \n", p+5);
1428 } else {
1429 WARN(event, "unknown mime type %s\n", p);
1431 if (next) {
1432 *next = '\n';
1433 p = next + 1;
1434 next = strchr(p, '\n');
1435 } else {
1436 p = NULL;
1438 *p_drop = '\0';
1441 if (drop32) {
1442 /* can not use PostMessage32A because it is currently based on
1443 * PostMessage16 and WPARAM32 would be truncated to WPARAM16
1445 GlobalUnlock(hDrop.h32);
1446 SendMessageA( hWnd, WM_DROPFILES,
1447 (WPARAM)hDrop.h32, 0L );
1448 } else {
1449 GlobalUnlock16(hDrop.h16);
1450 PostMessage16( hWnd, WM_DROPFILES,
1451 (WPARAM16)hDrop.h16, 0L );
1454 WIN_ReleaseWndPtr(pDropWnd);
1456 if( p_data ) TSXFree(p_data);
1460 /**********************************************************************
1461 * EVENT_ClientMessage
1463 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
1465 if (event->message_type != None && event->format == 32) {
1466 if ((event->message_type == wmProtocols) &&
1467 (((Atom) event->data.l[0]) == wmDeleteWindow))
1469 /* Ignore the delete window request if the window has been disabled
1470 * and we are in managed mode. This is to disallow applications from
1471 * being closed by the window manager while in a modal state.
1473 BOOL bIsDisabled;
1474 bIsDisabled = GetWindowLongA( hWnd, GWL_STYLE ) & WS_DISABLED;
1476 if ( !Options.managed || !bIsDisabled )
1477 SendMessage16( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
1479 else if ( event->message_type == dndProtocol &&
1480 (event->data.l[0] == DndFile || event->data.l[0] == DndFiles) )
1481 EVENT_DropFromOffiX(hWnd, event);
1482 else if ( event->message_type == dndProtocol &&
1483 event->data.l[0] == DndURL )
1484 EVENT_DropURLs(hWnd, event);
1485 else {
1486 #if 0
1487 /* enable this if you want to see the message */
1488 unsigned char* p_data = NULL;
1489 union {
1490 unsigned long l;
1491 int i;
1492 Atom atom;
1493 } u; /* unused */
1494 TSXGetWindowProperty( display, DefaultRootWindow(display),
1495 dndSelection, 0, 65535, FALSE,
1496 AnyPropertyType, &u.atom, &u.i,
1497 &u.l, &u.l, &p_data);
1498 TRACE(event, "message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1499 event->message_type, event->data.l[0], event->data.l[1],
1500 event->data.l[2], event->data.l[3], event->data.l[4],
1501 p_data);
1502 #endif
1503 TRACE(event, "unrecognized ClientMessage\n" );
1508 /**********************************************************************
1509 * EVENT_EnterNotify
1511 * Install colormap when Wine window is focused in
1512 * self-managed mode with private colormap
1514 #if 0
1515 void EVENT_EnterNotify( HWND hWnd, XCrossingEvent *event )
1517 if( !Options.managed && X11DRV_GetXRootWindow() == DefaultRootWindow(display) &&
1518 (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus() )
1519 TSXInstallColormap( display, X11DRV_PALETTE_GetColormap() );
1521 #endif
1523 /**********************************************************************
1524 * EVENT_MapNotify
1526 void EVENT_MapNotify( HWND hWnd, XMapEvent *event )
1528 HWND hwndFocus = GetFocus();
1529 WND *wndFocus = WIN_FindWndPtr(hwndFocus);
1530 WND *pWnd = WIN_FindWndPtr(hWnd);
1531 if (pWnd->flags & WIN_MANAGED)
1532 pWnd->dwStyle &= ~WS_MINIMIZE;
1533 WIN_ReleaseWndPtr(pWnd);
1535 if (hwndFocus && IsChild( hWnd, hwndFocus ))
1536 X11DRV_WND_SetFocus(wndFocus);
1538 WIN_ReleaseWndPtr(wndFocus);
1540 return;
1544 /**********************************************************************
1545 * EVENT_MapNotify
1547 void EVENT_UnmapNotify( HWND hWnd, XUnmapEvent *event )
1549 WND *pWnd = WIN_FindWndPtr(hWnd);
1550 if (pWnd->flags & WIN_MANAGED)
1552 EndMenu();
1553 pWnd->dwStyle |= WS_MINIMIZE;
1555 WIN_ReleaseWndPtr(pWnd);
1559 /**********************************************************************
1560 * X11DRV_EVENT_Pending
1562 BOOL X11DRV_EVENT_Pending()
1564 return TSXPending(display);
1567 /**********************************************************************
1568 * X11DRV_EVENT_WakeUp
1570 void X11DRV_EVENT_WakeUp(void)
1572 /* wake-up EVENT_WaitNetEvent function, a 32 bit thread post an event
1573 for a 16 bit task */
1574 if (write (__wakeup_pipe[1], "A", 1) != 1)
1575 ERR(event, "unable to write in wakeup_pipe\n");
1579 #endif /* !defined(X_DISPLAY_MISSING) */