2 * X events handling functions
4 * Copyright 1993 Alexandre Julliard
14 #include <sys/types.h>
16 #include <X11/keysym.h>
18 #include <X11/Xresource.h>
19 #include <X11/Xutil.h>
20 #include <X11/Xatom.h>
29 #include "clipboard.h"
44 #define NB_BUTTONS 3 /* Windows can handle 3 buttons */
46 #define DndNotDnd -1 /* OffiX drag&drop */
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"
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 /***********************************************************************
116 * Initialize network IO.
118 BOOL32
EVENT_Init(void)
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
] );
130 /***********************************************************************
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 /***********************************************************************
147 * Process an X event.
149 void EVENT_ProcessEvent( XEvent
*event
)
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
);
165 EVENT_Key( (XKeyEvent
*)event
);
170 EVENT_ButtonPress( pWnd
, (XButtonEvent
*)event
);
175 EVENT_ButtonRelease( pWnd
, (XButtonEvent
*)event
);
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.
189 while (XCheckTypedWindowEvent(display
,((XAnyEvent
*)event
)->window
,
190 MotionNotify
, event
));
191 EVENT_MotionNotify( pWnd
, (XMotionEvent
*)event
);
196 EVENT_FocusIn( pWnd
, (XFocusChangeEvent
*)event
);
200 EVENT_FocusOut( pWnd
, (XFocusChangeEvent
*)event
);
204 EVENT_Expose( pWnd
, (XExposeEvent
*)event
);
208 EVENT_GraphicsExpose( pWnd
, (XGraphicsExposeEvent
*)event
);
211 case ConfigureNotify
:
212 EVENT_ConfigureNotify( pWnd
->hwndSelf
, (XConfigureEvent
*)event
);
215 case SelectionRequest
:
216 EVENT_SelectionRequest( pWnd
, (XSelectionRequestEvent
*)event
);
219 case SelectionNotify
:
220 EVENT_SelectionNotify( (XSelectionEvent
*)event
);
224 EVENT_SelectionClear( pWnd
, (XSelectionClearEvent
*) event
);
228 EVENT_ClientMessage( pWnd
, (XClientMessageEvent
*) event
);
232 * EVENT_EnterNotify( pWnd, (XCrossingEvent *) event );
238 /* We get all these because of StructureNotifyMask. */
240 case CirculateNotify
:
248 EVENT_MapNotify( pWnd
->hwndSelf
, (XMapEvent
*)event
);
252 dprintf_event(stddeb
, "Unprocessed event %s for hwnd %04x\n",
253 event_names
[event
->type
], pWnd
->hwndSelf
);
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
)
288 XDeleteContext( display
, pWnd
->window
, winContext
);
289 XDestroyWindow( display
, pWnd
->window
);
290 while( XCheckWindowEvent(display
, pWnd
->window
, NoEventMask
, &xe
) );
293 /***********************************************************************
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
)
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
))
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;
321 sigsetjmp(env_wait_x
, 1);
324 if (DDE_GetRemoteMessage()) {
325 while(DDE_GetRemoteMessage())
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 )
335 TIMER_ExpireTimers();
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();
348 #endif /* CONFIG_IPC */
350 /* Winsock asynchronous services */
352 if( FD_ISSET( __event_x_connection
, &read_set
) )
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) */
368 if (DDE_GetRemoteMessage())
370 while(DDE_GetRemoteMessage()) ;
373 #endif /* CONFIG_IPC */
375 XNextEvent( display
, &event
);
382 if (XFindContext( display
, ((XAnyEvent
*)&event
)->window
, winContext
,
383 (char **)&pWnd
) || (event
.type
== NoExpose
))
386 /* Check only for those events which can be processed
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
);
399 if( (pQ
= (MESSAGEQUEUE
*)GlobalLock16(pWnd
->hmemTaskQ
)) )
401 pQ
->flags
|= QUEUE_FLAG_XEVENT
;
402 PostEvent(pQ
->hTask
);
403 XPutBackEvent(display
, &event
);
408 EVENT_ProcessEvent( &event
);
410 while (XPending( display
));
415 /***********************************************************************
418 * Synchronize with the X server. Should not be used too often.
420 void EVENT_Synchronize()
424 XSync( display
, False
);
425 while (XPending( display
))
427 XNextEvent( display
, &event
);
428 EVENT_ProcessEvent( &event
);
432 /***********************************************************************
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;
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
;
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
;
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
)
487 for( i
= 0; i
< max
; i
++ ) if( list
[i
] == w
) break;
491 static BOOL32
EVENT_QueryZOrder( WND
* pWndCheck
)
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
,
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
);
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
)) )
517 pos
= __td_lookup( w
, children
, total
);
518 if( pos
< best
&& pos
> check
)
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
);
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
)
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
;
554 /***********************************************************************
557 static void EVENT_Expose( WND
*pWnd
, XExposeEvent
*event
)
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
)
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 /***********************************************************************
598 * Handle a X key event
600 static void EVENT_Key( XKeyEvent
*event
)
602 KEYBOARD_HandleEvent( event
);
606 /***********************************************************************
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)
625 int rootX
, rootY
, childX
, childY
;
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 /***********************************************************************
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 /**********************************************************************
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()))
695 /**********************************************************************
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()))
713 /**********************************************************************
716 BOOL32
EVENT_CheckFocus(void)
722 XGetInputFocus(display
, &xW
, &state
);
724 XFindContext(display
, xW
, winContext
, (char **)&pWnd
) )
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())
748 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
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
;
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
;
815 Window request
= event
->requestor
;
817 if(event
->target
== XA_STRING
)
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
;
831 /* open to make sure that clipboard is available */
833 BOOL32 couldOpen
= OpenClipboard32( pWnd
->hwndSelf
);
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
];
851 XChangeProperty(display
, request
, rprop
,
852 XA_STRING
, 8, PropModeReplace
,
856 /* close only if we opened before */
858 if(couldOpen
) CloseClipboard32();
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
;
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
;
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; }
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
);
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
;
963 while( *p
) /* calculate buffer size */
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" */
971 INT32 len
= GetShortPathName32A( p
, NULL
, 0 );
972 if (len
) aux_long
+= len
+ 1;
977 if( aux_long
&& aux_long
< 65535 )
980 LPDROPFILESTRUCT lpDrop
;
982 aux_long
+= sizeof(DROPFILESTRUCT
) + 1;
983 hDrop
= (HDROP16
)GlobalAlloc16( GMEM_SHARE
, aux_long
);
984 lpDrop
= (LPDROPFILESTRUCT
) GlobalLock16( hDrop
);
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
);
1000 if( *p
!= -1 ) /* use only "good" entries */
1002 GetShortPathName32A( p
, p_drop
, 65535 );
1003 p_drop
+= strlen( p_drop
) + 1;
1008 PostMessage16( pWnd
->hwndSelf
, WM_DROPFILES
,
1009 (WPARAM16
)hDrop
, 0L );
1013 if( p_data
) XFree(p_data
);
1015 } /* WS_EX_ACCEPTFILES */
1018 dprintf_event( stddeb
, "unrecognized ClientMessage\n" );
1022 /**********************************************************************
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 /**********************************************************************
1040 void EVENT_MapNotify( HWND32 hWnd
, XMapEvent
*event
)
1042 HWND32 hwndFocus
= GetFocus32();
1044 if (hwndFocus
&& IsChild32( hWnd
, hwndFocus
))
1045 FOCUS_SetXFocus( (HWND32
)hwndFocus
);
1050 /**********************************************************************
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
)
1059 HWND32 capturePrev
= captureWnd
;
1063 XUngrabPointer(display
, CurrentTime
);
1064 captureWnd
= NULL
; captureHT
= 0;
1066 else if ((win
= WIN_GetXWindow( hwnd
)))
1068 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
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
);
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
);
1091 /**********************************************************************
1092 * EVENT_GetCaptureInfo
1094 INT16
EVENT_GetCaptureInfo()
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)
1136 /**********************************************************************
1137 * GetCapture32 (USER32.207)
1139 HWND32 WINAPI
GetCapture32(void)
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
)
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 (?)
1169 int rootX
, rootY
, childX
, childY
;
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
) );
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
;
1208 /***********************************************************************
1209 * SwapMouseButton16 (USER.186)
1211 BOOL16 WINAPI
SwapMouseButton16( BOOL16 fSwap
)
1213 BOOL16 ret
= SwappedButtons
;
1214 SwappedButtons
= fSwap
;
1219 /***********************************************************************
1220 * SwapMouseButton32 (USER32.536)
1222 BOOL32 WINAPI
SwapMouseButton32( BOOL32 fSwap
)
1224 BOOL32 ret
= SwappedButtons
;
1225 SwappedButtons
= fSwap
;