Handle non-hardware X events correctly with native USER
(removed reference to MESSAGEQUEUE from KERNEL code). Handle Expose events with native USER.
This commit is contained in:
parent
a6ceb0feec
commit
be672fe587
|
@ -130,7 +130,7 @@ static THUNK *firstThunk = NULL;
|
|||
static LRESULT WINAPI THUNK_CallWndProc16( WNDPROC16 proc, HWND16 hwnd,
|
||||
UINT16 msg, WPARAM16 wParam,
|
||||
LPARAM lParam );
|
||||
static void WINAPI THUNK_CallTaskReschedule(void);
|
||||
static BOOL32 WINAPI THUNK_CallTaskReschedule(void);
|
||||
static BOOL32 WINAPI THUNK_WOWCallback16Ex( FARPROC16,DWORD,DWORD,
|
||||
LPVOID,LPDWORD );
|
||||
|
||||
|
@ -309,9 +309,9 @@ static LRESULT WINAPI THUNK_CallWndProc16( WNDPROC16 proc, HWND16 hwnd,
|
|||
/***********************************************************************
|
||||
* THUNK_CallTaskReschedule
|
||||
*/
|
||||
static void WINAPI THUNK_CallTaskReschedule(void)
|
||||
static BOOL32 WINAPI THUNK_CallTaskReschedule(void)
|
||||
{
|
||||
CallTo16_word_(TASK_RescheduleProc);
|
||||
return CallTo16_word_(TASK_RescheduleProc);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ typedef struct
|
|||
{
|
||||
LONG (CALLBACK *CallRegisterShortProc)( CONTEXT *, INT32 );
|
||||
LONG (CALLBACK *CallRegisterLongProc)( CONTEXT *, INT32 );
|
||||
VOID (CALLBACK *CallTaskRescheduleProc)(void);
|
||||
BOOL32 (CALLBACK *CallTaskRescheduleProc)(void);
|
||||
VOID (CALLBACK *CallFrom16WndProc)(void);
|
||||
LRESULT (CALLBACK *CallWndProc)( WNDPROC16, HWND16, UINT16,
|
||||
WPARAM16, LPARAM );
|
||||
|
|
|
@ -71,7 +71,6 @@ typedef struct tagMESSAGEQUEUE
|
|||
#define QS_SMPARAMSFREE 0x4000 /* SendMessage() parameters are available */
|
||||
|
||||
/* Queue flags */
|
||||
#define QUEUE_FLAG_XEVENT 0x0001
|
||||
#define QUEUE_SM_WIN32 0x0002 /* Currently sent message is Win32 */
|
||||
#define QUEUE_SM_UNICODE 0x0004 /* Currently sent message is Unicode */
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ extern HTASK16 TASK_Create( struct _THDB *thdb, struct _NE_MODULE *pModule,
|
|||
extern void TASK_StartTask( HTASK16 hTask );
|
||||
extern void TASK_KillCurrentTask( INT16 exitCode );
|
||||
extern HTASK16 TASK_GetNextTask( HTASK16 hTask );
|
||||
extern void TASK_Reschedule(void);
|
||||
extern BOOL32 TASK_Reschedule(void);
|
||||
extern void TASK_InstallTHHook( THHOOK *pNewThook );
|
||||
|
||||
#endif /* __WINE_TASK_H */
|
||||
|
|
|
@ -653,11 +653,12 @@ void TASK_KillCurrentTask( INT16 exitCode )
|
|||
*
|
||||
* It must not call functions that may yield control.
|
||||
*/
|
||||
void TASK_Reschedule(void)
|
||||
BOOL32 TASK_Reschedule(void)
|
||||
{
|
||||
TDB *pOldTask = NULL, *pNewTask;
|
||||
HTASK16 hTask = 0;
|
||||
STACK16FRAME *newframe16;
|
||||
BOOL32 pending = FALSE;
|
||||
|
||||
/* Get the initial task up and running */
|
||||
if (!hCurrentTask && GetCurrentTask())
|
||||
|
@ -683,7 +684,7 @@ void TASK_Reschedule(void)
|
|||
hCurrentTask = GetCurrentTask();
|
||||
pNewTask = (TDB *)GlobalLock16( hCurrentTask );
|
||||
pNewTask->ss_sp = pNewTask->thdb->cur_stack;
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* NOTE: As we are entered from 16-bit code, we hold the Win16Lock.
|
||||
|
@ -720,7 +721,7 @@ void TASK_Reschedule(void)
|
|||
|
||||
/* extract hardware events only! */
|
||||
|
||||
if (!hTask) EVENT_WaitNetEvent( FALSE, TRUE );
|
||||
if (!hTask) pending = EVENT_WaitNetEvent( FALSE, TRUE );
|
||||
|
||||
while (!hTask)
|
||||
{
|
||||
|
@ -739,6 +740,10 @@ void TASK_Reschedule(void)
|
|||
if (hLockedTask && (hTask != hLockedTask)) hTask = 0;
|
||||
if (hTask) break;
|
||||
|
||||
/* If a non-hardware event is pending, return to TASK_YieldToSystem
|
||||
temporarily to process it safely */
|
||||
if (pending) return TRUE;
|
||||
|
||||
/* No task found, wait for some events to come in */
|
||||
|
||||
/* NOTE: We release the Win16Lock while waiting for events. This is to enable
|
||||
|
@ -747,14 +752,14 @@ void TASK_Reschedule(void)
|
|||
TASK_Reschedule anyway, there should be no re-entrancy problem ... */
|
||||
|
||||
SYSLEVEL_ReleaseWin16Lock();
|
||||
EVENT_WaitNetEvent( TRUE, TRUE );
|
||||
pending = EVENT_WaitNetEvent( TRUE, TRUE );
|
||||
SYSLEVEL_RestoreWin16Lock();
|
||||
}
|
||||
|
||||
if (hTask == hCurrentTask)
|
||||
{
|
||||
TRACE(task, "returning to the current task(%04x)\n", hTask );
|
||||
return; /* Nothing to do */
|
||||
return FALSE; /* Nothing to do */
|
||||
}
|
||||
pNewTask = (TDB *)GlobalLock16( hTask );
|
||||
TRACE(task, "Switching to task %04x (%.8s)\n",
|
||||
|
@ -797,6 +802,8 @@ void TASK_Reschedule(void)
|
|||
pNewTask->ss_sp = pNewTask->thdb->cur_stack;
|
||||
|
||||
SYSLEVEL_RestoreWin16Lock();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -808,27 +815,31 @@ void TASK_Reschedule(void)
|
|||
*/
|
||||
void TASK_YieldToSystem(TDB* pTask)
|
||||
{
|
||||
MESSAGEQUEUE* pQ;
|
||||
|
||||
if ( !THREAD_IsWin16( THREAD_Current() ) )
|
||||
{
|
||||
FIXME(task, "called for Win32 thread (%04x)!\n", THREAD_Current()->teb_sel);
|
||||
return;
|
||||
}
|
||||
|
||||
Callbacks->CallTaskRescheduleProc();
|
||||
if ( Callbacks->CallTaskRescheduleProc() )
|
||||
{
|
||||
/* NOTE: We get here only when no task has an event. This means also
|
||||
the current task, so we shouldn't actually return to the
|
||||
caller here. But, we need to do so, as the EVENT_WaitNetEvent
|
||||
call could lead to a complex series of inter-task SendMessage
|
||||
calls which might leave this task in a state where it again
|
||||
has no event, but where its queue's wakeMask is also reset
|
||||
to zero. Reentering TASK_Reschedule in this state would be
|
||||
suicide. Hence, we do return to the caller after processing
|
||||
non-hardware events. Actually, this should not hurt anyone,
|
||||
as the caller must be WaitEvent, and thus the QUEUE_WaitBits
|
||||
loop in USER. Should there actually be no message pending
|
||||
for this task after processing non-hardware events, that loop
|
||||
will simply return to WaitEvent. */
|
||||
|
||||
if( pTask )
|
||||
{
|
||||
pQ = (MESSAGEQUEUE*)GlobalLock16(pTask->hQueue);
|
||||
if( pQ && pQ->flags & QUEUE_FLAG_XEVENT &&
|
||||
!(pQ->wakeBits & (QS_SENDMESSAGE | QS_SMRESULT)) )
|
||||
{
|
||||
pQ->flags &= ~QUEUE_FLAG_XEVENT;
|
||||
EVENT_WaitNetEvent( FALSE, FALSE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -238,11 +238,15 @@ static BOOL32 WINAPI CALLBACK_CallWOWCallback16Ex(
|
|||
/**********************************************************************
|
||||
* CALLBACK_CallTaskRescheduleProc
|
||||
*/
|
||||
static void WINAPI CALLBACK_CallTaskRescheduleProc( void )
|
||||
static BOOL32 WINAPI CALLBACK_CallTaskRescheduleProc( void )
|
||||
{
|
||||
BOOL32 pending;
|
||||
|
||||
SYSLEVEL_EnterWin16Lock();
|
||||
TASK_Reschedule();
|
||||
pending = TASK_Reschedule();
|
||||
SYSLEVEL_LeaveWin16Lock();
|
||||
|
||||
return pending;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -27,13 +27,10 @@
|
|||
#include "gdi.h"
|
||||
#include "heap.h"
|
||||
#include "queue.h"
|
||||
#include "win.h"
|
||||
#include "class.h"
|
||||
#include "dce.h"
|
||||
#include "message.h"
|
||||
#include "module.h"
|
||||
#include "options.h"
|
||||
#include "queue.h"
|
||||
#include "winpos.h"
|
||||
#include "drive.h"
|
||||
#include "shell.h"
|
||||
|
@ -113,6 +110,10 @@ static void EVENT_GetGeometry( Window win, int *px, int *py,
|
|||
unsigned int *pwidth, unsigned int *pheight );
|
||||
|
||||
|
||||
static BOOL32 (WINAPI *EVENT_RedrawWindow)( HWND32 hwnd, const RECT32 *rectUpdate,
|
||||
HRGN32 hrgnUpdate, UINT32 flags ) = NULL;
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* EVENT_Init
|
||||
*
|
||||
|
@ -166,8 +167,8 @@ BOOL16 X11DRV_EVENT_IsUserIdle(void)
|
|||
* X11DRV_EVENT_WaitNetEvent
|
||||
*
|
||||
* Wait for a network event, optionally sleeping until one arrives.
|
||||
* Return TRUE if an event is pending, FALSE on timeout or error
|
||||
* (for instance lost connection with the server).
|
||||
* Returns TRUE if an event is pending that cannot be processed in
|
||||
* 'peek' mode, FALSE otherwise.
|
||||
*/
|
||||
|
||||
BOOL32 X11DRV_EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek )
|
||||
|
@ -198,7 +199,7 @@ BOOL32 X11DRV_EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek )
|
|||
if (DDE_GetRemoteMessage()) {
|
||||
while(DDE_GetRemoteMessage())
|
||||
;
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
stop_wait_op = STOP_WAIT_X;
|
||||
/* The code up to the next "stop_wait_op = CONT" must be reentrant */
|
||||
|
@ -233,7 +234,10 @@ BOOL32 X11DRV_EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek )
|
|||
WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set );
|
||||
}
|
||||
else /* no X events */
|
||||
return WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set );
|
||||
{
|
||||
WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set );
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if(!pending)
|
||||
{ /* Wait for X11 input. */
|
||||
|
@ -255,19 +259,14 @@ BOOL32 X11DRV_EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek )
|
|||
{
|
||||
LeaveCriticalSection(&X11DRV_CritSection);
|
||||
while(DDE_GetRemoteMessage()) ;
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
XNextEvent( display, &event );
|
||||
|
||||
LeaveCriticalSection(&X11DRV_CritSection);
|
||||
if( peek )
|
||||
{
|
||||
WND* pWnd;
|
||||
MESSAGEQUEUE* pQ;
|
||||
|
||||
|
||||
/* Check only for those events which can be processed
|
||||
* internally. */
|
||||
|
||||
|
@ -277,31 +276,30 @@ BOOL32 X11DRV_EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek )
|
|||
event.type == SelectionRequest || event.type == SelectionClear ||
|
||||
event.type == ClientMessage )
|
||||
{
|
||||
LeaveCriticalSection(&X11DRV_CritSection);
|
||||
EVENT_ProcessEvent( &event );
|
||||
EnterCriticalSection(&X11DRV_CritSection);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TSXFindContext( display, ((XAnyEvent *)&event)->window, winContext,
|
||||
(char **)&pWnd ) || (event.type == NoExpose))
|
||||
pWnd = NULL;
|
||||
if ( event.type == NoExpose )
|
||||
continue;
|
||||
|
||||
if( pWnd )
|
||||
{
|
||||
if( (pQ = (MESSAGEQUEUE*)GlobalLock16(pWnd->hmemTaskQ)) )
|
||||
{
|
||||
pQ->flags |= QUEUE_FLAG_XEVENT;
|
||||
PostEvent(pQ->hTask);
|
||||
TSXPutBackEvent(display, &event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else EVENT_ProcessEvent( &event );
|
||||
EnterCriticalSection(&X11DRV_CritSection);
|
||||
}
|
||||
XPutBackEvent(display, &event);
|
||||
LeaveCriticalSection(&X11DRV_CritSection);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LeaveCriticalSection(&X11DRV_CritSection);
|
||||
EVENT_ProcessEvent( &event );
|
||||
EnterCriticalSection(&X11DRV_CritSection);
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&X11DRV_CritSection);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* EVENT_Synchronize
|
||||
|
@ -396,12 +394,10 @@ static void EVENT_ProcessEvent( XEvent *event )
|
|||
break;
|
||||
|
||||
case Expose:
|
||||
if (!pWnd) return;
|
||||
EVENT_Expose( pWnd, (XExposeEvent *)event );
|
||||
break;
|
||||
|
||||
case GraphicsExpose:
|
||||
if (!pWnd) return;
|
||||
EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
|
||||
break;
|
||||
|
||||
|
@ -613,14 +609,20 @@ static void EVENT_Expose( WND *pWnd, XExposeEvent *event )
|
|||
RECT32 rect;
|
||||
|
||||
/* Make position relative to client area instead of window */
|
||||
rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
|
||||
rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
|
||||
rect.left = event->x - (pWnd? (pWnd->rectClient.left - pWnd->rectWindow.left) : 0);
|
||||
rect.top = event->y - (pWnd? (pWnd->rectClient.top - pWnd->rectWindow.top) : 0);
|
||||
rect.right = rect.left + event->width;
|
||||
rect.bottom = rect.top + event->height;
|
||||
|
||||
PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
|
||||
if ( !EVENT_RedrawWindow )
|
||||
{
|
||||
HMODULE32 hModule = GetModuleHandle32A( "USER32" );
|
||||
EVENT_RedrawWindow = GetProcAddress32( hModule, "RedrawWindow" );
|
||||
}
|
||||
|
||||
EVENT_RedrawWindow( pWnd? pWnd->hwndSelf : 0, &rect, 0,
|
||||
RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
|
||||
(event->count ? 0 : RDW_ERASENOW), 0 );
|
||||
(event->count ? 0 : RDW_ERASENOW) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -635,14 +637,20 @@ static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
|
|||
RECT32 rect;
|
||||
|
||||
/* Make position relative to client area instead of window */
|
||||
rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
|
||||
rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
|
||||
rect.left = event->x - (pWnd? (pWnd->rectClient.left - pWnd->rectWindow.left) : 0);
|
||||
rect.top = event->y - (pWnd? (pWnd->rectClient.top - pWnd->rectWindow.top) : 0);
|
||||
rect.right = rect.left + event->width;
|
||||
rect.bottom = rect.top + event->height;
|
||||
|
||||
PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
|
||||
if ( !EVENT_RedrawWindow )
|
||||
{
|
||||
HMODULE32 hModule = GetModuleHandle32A( "USER32" );
|
||||
EVENT_RedrawWindow = GetProcAddress32( hModule, "RedrawWindow" );
|
||||
}
|
||||
|
||||
EVENT_RedrawWindow( pWnd? pWnd->hwndSelf : 0, &rect, 0,
|
||||
RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
|
||||
(event->count ? 0 : RDW_ERASENOW), 0 );
|
||||
(event->count ? 0 : RDW_ERASENOW) );
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue