wineandroid: Add an event queue to support handling Java callbacks in the desktop thread.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
77d55905b1
commit
5be4a0e388
|
@ -57,6 +57,24 @@ extern void init_monitors( int width, int height ) DECLSPEC_HIDDEN;
|
||||||
/* JNI entry points */
|
/* JNI entry points */
|
||||||
extern void desktop_changed( JNIEnv *env, jobject obj, jint width, jint height ) DECLSPEC_HIDDEN;
|
extern void desktop_changed( JNIEnv *env, jobject obj, jint width, jint height ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
enum event_type
|
||||||
|
{
|
||||||
|
DESKTOP_CHANGED,
|
||||||
|
};
|
||||||
|
|
||||||
|
union event_data
|
||||||
|
{
|
||||||
|
enum event_type type;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
enum event_type type;
|
||||||
|
unsigned int width;
|
||||||
|
unsigned int height;
|
||||||
|
} desktop;
|
||||||
|
};
|
||||||
|
|
||||||
|
int send_event( const union event_data *data );
|
||||||
|
|
||||||
extern JavaVM *wine_get_java_vm(void);
|
extern JavaVM *wine_get_java_vm(void);
|
||||||
extern jobject wine_get_java_object(void);
|
extern jobject wine_get_java_object(void);
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
|
|
||||||
#include "android.h"
|
#include "android.h"
|
||||||
|
#include "wine/server.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(android);
|
WINE_DEFAULT_DEBUG_CHANNEL(android);
|
||||||
|
@ -133,6 +134,35 @@ static void release_win_data( struct android_win_data *data )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Handling of events coming from the Java side */
|
||||||
|
|
||||||
|
struct java_event
|
||||||
|
{
|
||||||
|
struct list entry;
|
||||||
|
union event_data data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct list event_queue = LIST_INIT( event_queue );
|
||||||
|
static struct java_event *current_event;
|
||||||
|
static int event_pipe[2];
|
||||||
|
static DWORD desktop_tid;
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* send_event
|
||||||
|
*/
|
||||||
|
int send_event( const union event_data *data )
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if ((res = write( event_pipe[1], data, sizeof(*data) )) != sizeof(*data))
|
||||||
|
{
|
||||||
|
p__android_log_print( ANDROID_LOG_ERROR, "wine", "failed to send event" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* desktop_changed
|
* desktop_changed
|
||||||
*
|
*
|
||||||
|
@ -140,7 +170,145 @@ static void release_win_data( struct android_win_data *data )
|
||||||
*/
|
*/
|
||||||
void desktop_changed( JNIEnv *env, jobject obj, jint width, jint height )
|
void desktop_changed( JNIEnv *env, jobject obj, jint width, jint height )
|
||||||
{
|
{
|
||||||
|
union event_data data;
|
||||||
|
|
||||||
|
memset( &data, 0, sizeof(data) );
|
||||||
|
data.type = DESKTOP_CHANGED;
|
||||||
|
data.desktop.width = width;
|
||||||
|
data.desktop.height = height;
|
||||||
p__android_log_print( ANDROID_LOG_INFO, "wine", "desktop_changed: %ux%u", width, height );
|
p__android_log_print( ANDROID_LOG_INFO, "wine", "desktop_changed: %ux%u", width, height );
|
||||||
|
send_event( &data );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* init_event_queue
|
||||||
|
*/
|
||||||
|
static void init_event_queue(void)
|
||||||
|
{
|
||||||
|
HANDLE handle;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (pipe2( event_pipe, O_CLOEXEC | O_NONBLOCK ) == -1)
|
||||||
|
{
|
||||||
|
ERR( "could not create data\n" );
|
||||||
|
ExitProcess(1);
|
||||||
|
}
|
||||||
|
if (wine_server_fd_to_handle( event_pipe[0], GENERIC_READ | SYNCHRONIZE, 0, &handle ))
|
||||||
|
{
|
||||||
|
ERR( "Can't allocate handle for event fd\n" );
|
||||||
|
ExitProcess(1);
|
||||||
|
}
|
||||||
|
SERVER_START_REQ( set_queue_fd )
|
||||||
|
{
|
||||||
|
req->handle = wine_server_obj_handle( handle );
|
||||||
|
ret = wine_server_call( req );
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ERR( "Can't store handle for event fd %x\n", ret );
|
||||||
|
ExitProcess(1);
|
||||||
|
}
|
||||||
|
CloseHandle( handle );
|
||||||
|
desktop_tid = GetCurrentThreadId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* pull_events
|
||||||
|
*
|
||||||
|
* Pull events from the event pipe and add them to the queue
|
||||||
|
*/
|
||||||
|
static void pull_events(void)
|
||||||
|
{
|
||||||
|
struct java_event *event;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (!(event = HeapAlloc( GetProcessHeap(), 0, sizeof(*event) ))) break;
|
||||||
|
|
||||||
|
res = read( event_pipe[0], &event->data, sizeof(event->data) );
|
||||||
|
if (res != sizeof(event->data)) break;
|
||||||
|
list_add_tail( &event_queue, &event->entry );
|
||||||
|
}
|
||||||
|
HeapFree( GetProcessHeap(), 0, event );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* process_events
|
||||||
|
*/
|
||||||
|
static int process_events( DWORD mask )
|
||||||
|
{
|
||||||
|
struct java_event *event, *next, *previous;
|
||||||
|
unsigned int count = 0;
|
||||||
|
|
||||||
|
assert( GetCurrentThreadId() == desktop_tid );
|
||||||
|
|
||||||
|
pull_events();
|
||||||
|
|
||||||
|
previous = current_event;
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY_SAFE( event, next, &event_queue, struct java_event, entry )
|
||||||
|
{
|
||||||
|
if (!(mask & QS_SENDMESSAGE)) continue; /* skip it */
|
||||||
|
|
||||||
|
/* remove it first, in case we process events recursively */
|
||||||
|
list_remove( &event->entry );
|
||||||
|
current_event = event;
|
||||||
|
|
||||||
|
switch (event->data.type)
|
||||||
|
{
|
||||||
|
case DESKTOP_CHANGED:
|
||||||
|
TRACE( "DESKTOP_CHANGED %ux%u\n", event->data.desktop.width, event->data.desktop.height );
|
||||||
|
screen_width = event->data.desktop.width;
|
||||||
|
screen_height = event->data.desktop.height;
|
||||||
|
init_monitors( screen_width, screen_height );
|
||||||
|
SetWindowPos( GetDesktopWindow(), 0, 0, 0, screen_width, screen_height,
|
||||||
|
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
FIXME( "got event %u\n", event->data.type );
|
||||||
|
}
|
||||||
|
HeapFree( GetProcessHeap(), 0, event );
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
current_event = previous;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* ANDROID_MsgWaitForMultipleObjectsEx
|
||||||
|
*/
|
||||||
|
DWORD CDECL ANDROID_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
|
||||||
|
DWORD timeout, DWORD mask, DWORD flags )
|
||||||
|
{
|
||||||
|
if (GetCurrentThreadId() == desktop_tid)
|
||||||
|
{
|
||||||
|
/* don't process nested events */
|
||||||
|
if (current_event) mask = 0;
|
||||||
|
if (process_events( mask )) return count - 1;
|
||||||
|
}
|
||||||
|
return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
|
||||||
|
timeout, flags & MWMO_ALERTABLE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* ANDROID_CreateWindow
|
||||||
|
*/
|
||||||
|
BOOL CDECL ANDROID_CreateWindow( HWND hwnd )
|
||||||
|
{
|
||||||
|
TRACE( "%p\n", hwnd );
|
||||||
|
|
||||||
|
if (hwnd == GetDesktopWindow())
|
||||||
|
{
|
||||||
|
init_event_queue();
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
@ cdecl EnumDisplayMonitors(long ptr ptr long) ANDROID_EnumDisplayMonitors
|
@ cdecl EnumDisplayMonitors(long ptr ptr long) ANDROID_EnumDisplayMonitors
|
||||||
@ cdecl GetMonitorInfo(long ptr) ANDROID_GetMonitorInfo
|
@ cdecl GetMonitorInfo(long ptr) ANDROID_GetMonitorInfo
|
||||||
|
@ cdecl CreateWindow(long) ANDROID_CreateWindow
|
||||||
@ cdecl DestroyWindow(long) ANDROID_DestroyWindow
|
@ cdecl DestroyWindow(long) ANDROID_DestroyWindow
|
||||||
|
@ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) ANDROID_MsgWaitForMultipleObjectsEx
|
||||||
@ cdecl WindowPosChanging(long long long ptr ptr ptr ptr) ANDROID_WindowPosChanging
|
@ cdecl WindowPosChanging(long long long ptr ptr ptr ptr) ANDROID_WindowPosChanging
|
||||||
@ cdecl WindowPosChanged(long long long ptr ptr ptr ptr ptr) ANDROID_WindowPosChanged
|
@ cdecl WindowPosChanged(long long long ptr ptr ptr ptr ptr) ANDROID_WindowPosChanged
|
||||||
|
|
Loading…
Reference in New Issue