Alexandre Julliard : wineandroid: Add an event queue to support handling Java callbacks in the desktop thread.
Alexandre Julliard
julliard at winehq.org
Wed May 31 16:20:17 CDT 2017
Module: wine
Branch: master
Commit: 5be4a0e38842d2fa241ca769ce4d50e4eb55c68a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=5be4a0e38842d2fa241ca769ce4d50e4eb55c68a
Author: Alexandre Julliard <julliard at winehq.org>
Date: Wed May 31 11:49:12 2017 +0200
wineandroid: Add an event queue to support handling Java callbacks in the desktop thread.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/wineandroid.drv/android.h | 18 ++++
dlls/wineandroid.drv/window.c | 168 ++++++++++++++++++++++++++++++
dlls/wineandroid.drv/wineandroid.drv.spec | 2 +
3 files changed, 188 insertions(+)
diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h
index ab4a431..9fefb11 100644
--- a/dlls/wineandroid.drv/android.h
+++ b/dlls/wineandroid.drv/android.h
@@ -57,6 +57,24 @@ extern void init_monitors( int width, int height ) DECLSPEC_HIDDEN;
/* JNI entry points */
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 jobject wine_get_java_object(void);
diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c
index e7c83b0..cf35215 100644
--- a/dlls/wineandroid.drv/window.c
+++ b/dlls/wineandroid.drv/window.c
@@ -44,6 +44,7 @@
#include "wine/unicode.h"
#include "android.h"
+#include "wine/server.h"
#include "wine/debug.h"
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
*
@@ -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 )
{
+ 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 );
+ 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;
}
diff --git a/dlls/wineandroid.drv/wineandroid.drv.spec b/dlls/wineandroid.drv/wineandroid.drv.spec
index b94c9f8..49402a8 100644
--- a/dlls/wineandroid.drv/wineandroid.drv.spec
+++ b/dlls/wineandroid.drv/wineandroid.drv.spec
@@ -6,6 +6,8 @@
@ cdecl EnumDisplayMonitors(long ptr ptr long) ANDROID_EnumDisplayMonitors
@ cdecl GetMonitorInfo(long ptr) ANDROID_GetMonitorInfo
+@ cdecl CreateWindow(long) ANDROID_CreateWindow
@ 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 WindowPosChanged(long long long ptr ptr ptr ptr ptr) ANDROID_WindowPosChanged
More information about the wine-cvs
mailing list