diff --git a/dlls/wineandroid.drv/WineActivity.java b/dlls/wineandroid.drv/WineActivity.java index 50ff0bfdec4..f12de983d39 100644 --- a/dlls/wineandroid.drv/WineActivity.java +++ b/dlls/wineandroid.drv/WineActivity.java @@ -337,6 +337,20 @@ public void pos_changed( int flags, int insert_after, int owner, int style, visible = (style & WS_VISIBLE) != 0; } + public void set_parent( WineWindow new_parent ) + { + Log.i( LOGTAG, String.format( "set parent hwnd %08x parent %08x -> %08x", + hwnd, parent == null ? 0 : parent.hwnd, + new_parent == null ? 0 : new_parent.hwnd )); + parent = new_parent; + if (new_parent == null) + { + window_view = new WineView( WineActivity.this, this ); + window_view.layout( 0, 0, 1, 1 ); // make sure the surface gets created + } + else window_view = null; + } + public int get_hwnd() { return hwnd; @@ -452,6 +466,13 @@ public void destroy_window( int hwnd ) if (win != null) win.destroy(); } + public void set_window_parent( int hwnd, int parent, int pid ) + { + WineWindow win = get_window( hwnd ); + if (win == null) return; + win.set_parent( get_window( parent )); + } + public void window_pos_changed( int hwnd, int flags, int insert_after, int owner, int style, Rect window_rect, Rect client_rect, Rect visible_rect ) { @@ -475,6 +496,11 @@ public void destroyWindow( final int hwnd ) runOnUiThread( new Runnable() { public void run() { destroy_window( hwnd ); }} ); } + public void setParent( final int hwnd, final int parent, final int pid ) + { + runOnUiThread( new Runnable() { public void run() { set_window_parent( hwnd, parent, pid ); }} ); + } + public void windowPosChanged( final int hwnd, final int flags, final int insert_after, final int owner, final int style, final int window_left, final int window_top, diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h index 3c2500e0d1c..f3dd019177b 100644 --- a/dlls/wineandroid.drv/android.h +++ b/dlls/wineandroid.drv/android.h @@ -60,6 +60,7 @@ extern void destroy_ioctl_window( HWND hwnd ) DECLSPEC_HIDDEN; extern int ioctl_window_pos_changed( HWND hwnd, const RECT *window_rect, const RECT *client_rect, const RECT *visible_rect, UINT style, UINT flags, HWND after, HWND owner ) DECLSPEC_HIDDEN; +extern int ioctl_set_window_parent( HWND hwnd, HWND parent ) DECLSPEC_HIDDEN; /************************************************************************** diff --git a/dlls/wineandroid.drv/device.c b/dlls/wineandroid.drv/device.c index 1af59bece13..eafaf0474a0 100644 --- a/dlls/wineandroid.drv/device.c +++ b/dlls/wineandroid.drv/device.c @@ -61,6 +61,7 @@ enum android_ioctl IOCTL_CREATE_WINDOW, IOCTL_DESTROY_WINDOW, IOCTL_WINDOW_POS_CHANGED, + IOCTL_SET_WINDOW_PARENT, IOCTL_DEQUEUE_BUFFER, IOCTL_QUEUE_BUFFER, IOCTL_CANCEL_BUFFER, @@ -188,6 +189,12 @@ struct ioctl_android_set_swap_interval int interval; }; +struct ioctl_android_set_window_parent +{ + struct ioctl_header hdr; + int parent; +}; + static inline BOOL is_in_desktop_process(void) { return thread != NULL; @@ -832,12 +839,35 @@ static NTSTATUS setSwapInterval_ioctl( void *data, DWORD in_size, DWORD out_size return android_error_to_status( ret ); } +static NTSTATUS setWindowParent_ioctl( void *data, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ) +{ + static jmethodID method; + jobject object; + struct ioctl_android_set_window_parent *res = data; + struct native_win_data *win_data; + DWORD pid = current_client_id(); + + if (in_size < sizeof(*res)) return STATUS_INVALID_PARAMETER; + + if (!(win_data = get_ioctl_native_win_data( &res->hdr ))) return STATUS_INVALID_HANDLE; + + TRACE( "hwnd %08x parent %08x\n", res->hdr.hwnd, res->parent ); + + if (!(object = load_java_method( &method, "setParent", "(III)V" ))) return STATUS_NOT_SUPPORTED; + + wrap_java_call(); + (*jni_env)->CallVoidMethod( jni_env, object, method, res->hdr.hwnd, res->parent, pid ); + unwrap_java_call(); + return STATUS_SUCCESS; +} + typedef NTSTATUS (*ioctl_func)( void *in, DWORD in_size, DWORD out_size, ULONG_PTR *ret_size ); static const ioctl_func ioctl_funcs[] = { createWindow_ioctl, /* IOCTL_CREATE_WINDOW */ destroyWindow_ioctl, /* IOCTL_DESTROY_WINDOW */ windowPosChanged_ioctl, /* IOCTL_WINDOW_POS_CHANGED */ + setWindowParent_ioctl, /* IOCTL_SET_WINDOW_PARENT */ dequeueBuffer_ioctl, /* IOCTL_DEQUEUE_BUFFER */ queueBuffer_ioctl, /* IOCTL_QUEUE_BUFFER */ cancelBuffer_ioctl, /* IOCTL_CANCEL_BUFFER */ @@ -1356,3 +1386,12 @@ int ioctl_window_pos_changed( HWND hwnd, const RECT *window_rect, const RECT *cl req.owner = HandleToLong( owner ); return android_ioctl( IOCTL_WINDOW_POS_CHANGED, &req, sizeof(req), NULL, NULL ); } + +int ioctl_set_window_parent( HWND hwnd, HWND parent ) +{ + struct ioctl_android_set_window_parent req; + + req.hdr.hwnd = HandleToLong( hwnd ); + req.parent = parent == GetDesktopWindow() ? 0 : HandleToLong( parent ); + return android_ioctl( IOCTL_SET_WINDOW_PARENT, &req, sizeof(req), NULL, NULL ); +} diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index 94f23e00553..7dff29786ab 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -1015,6 +1015,24 @@ UINT CDECL ANDROID_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ) } +/***************************************************************** + * ANDROID_SetParent + */ +void CDECL ANDROID_SetParent( HWND hwnd, HWND parent, HWND old_parent ) +{ + struct android_win_data *data; + + if (parent == old_parent) return; + if (!(data = get_win_data( hwnd ))) return; + + TRACE( "win %p parent %p -> %p\n", hwnd, old_parent, parent ); + + data->parent = (parent == GetDesktopWindow()) ? 0 : parent; + ioctl_set_window_parent( hwnd, parent ); + release_win_data( data ); +} + + /*********************************************************************** * ANDROID_SetWindowStyle */ diff --git a/dlls/wineandroid.drv/wineandroid.drv.spec b/dlls/wineandroid.drv/wineandroid.drv.spec index ed3138a099a..36052419b0e 100644 --- a/dlls/wineandroid.drv/wineandroid.drv.spec +++ b/dlls/wineandroid.drv/wineandroid.drv.spec @@ -10,6 +10,7 @@ @ cdecl DestroyWindow(long) ANDROID_DestroyWindow @ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) ANDROID_MsgWaitForMultipleObjectsEx @ cdecl SetLayeredWindowAttributes(long long long long) ANDROID_SetLayeredWindowAttributes +@ cdecl SetParent(long long long) ANDROID_SetParent @ cdecl SetWindowRgn(long long long) ANDROID_SetWindowRgn @ cdecl SetWindowStyle(ptr long ptr) ANDROID_SetWindowStyle @ cdecl ShowWindow(long long ptr long) ANDROID_ShowWindow