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