wineandroid: Create window groups inside every window to support a client area.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2017-06-22 19:38:36 +02:00
parent f77bbd45d6
commit cd2b41a2b4
2 changed files with 160 additions and 33 deletions

View File

@ -61,6 +61,8 @@ public class WineActivity extends Activity
private final String LOGTAG = "wine"; private final String LOGTAG = "wine";
private ProgressDialog progress_dialog; private ProgressDialog progress_dialog;
protected WineWindow desktop_window;
@Override @Override
public void onCreate(Bundle savedInstanceState) public void onCreate(Bundle savedInstanceState)
{ {
@ -297,9 +299,10 @@ protected class WineWindow extends Object
protected Rect visible_rect; protected Rect visible_rect;
protected Rect client_rect; protected Rect client_rect;
protected WineWindow parent; protected WineWindow parent;
protected WineView window_view;
protected Surface window_surface; protected Surface window_surface;
protected Surface client_surface; protected Surface client_surface;
protected WineWindowGroup window_group;
protected WineWindowGroup client_group;
public WineWindow( int w, WineWindow parent ) public WineWindow( int w, WineWindow parent )
{ {
@ -311,20 +314,63 @@ public WineWindow( int w, WineWindow parent )
visible_rect = client_rect = new Rect( 0, 0, 0, 0 ); visible_rect = client_rect = new Rect( 0, 0, 0, 0 );
this.parent = parent; this.parent = parent;
win_map.put( w, this ); win_map.put( w, this );
if (parent == null)
{
window_view = new WineView( WineActivity.this, this, false );
window_view.layout( 0, 0, 1, 1 ); // make sure the surface gets created
}
} }
public void destroy() public void destroy()
{ {
Log.i( LOGTAG, String.format( "destroy hwnd %08x", hwnd )); Log.i( LOGTAG, String.format( "destroy hwnd %08x", hwnd ));
if (visible && window_view != null) top_view.removeView( window_view );
visible = false; visible = false;
window_view = null;
win_map.remove( this ); win_map.remove( this );
destroy_window_groups();
}
public WineWindowGroup create_window_groups()
{
if (client_group != null) return client_group;
window_group = new WineWindowGroup();
client_group = new WineWindowGroup();
window_group.addView( client_group );
client_group.set_layout( client_rect.left - visible_rect.left,
client_rect.top - visible_rect.top,
client_rect.right - visible_rect.left,
client_rect.bottom - visible_rect.top );
if (parent != null)
{
WineWindowGroup parent_group = parent.create_window_groups();
if (visible) parent_group.addView( window_group );
window_group.set_layout( visible_rect.left, visible_rect.top,
visible_rect.right, visible_rect.bottom );
window_group.bringToFront();
}
return client_group;
}
public void destroy_window_groups()
{
if (window_group != null)
{
if (parent != null) parent.client_group.removeView( window_group );
window_group.destroy_view();
}
if (client_group != null) client_group.destroy_view();
window_group = null;
client_group = null;
}
public View create_whole_view()
{
if (window_group == null) create_window_groups();
window_group.create_view( this, false ).layout( 0, 0, visible_rect.right - visible_rect.left,
visible_rect.bottom - visible_rect.top );
return window_group;
}
public void create_client_view()
{
if (client_group == null) create_window_groups();
Log.i( "wine", String.format( "creating client view %08x %s", hwnd, client_rect ));
client_group.create_view( this, true ).layout( 0, 0, client_rect.right - client_rect.left,
client_rect.bottom - client_rect.top );
} }
public void pos_changed( int flags, int insert_after, int owner, int style, public void pos_changed( int flags, int insert_after, int owner, int style,
@ -337,27 +383,42 @@ public void pos_changed( int flags, int insert_after, int owner, int style,
Log.i( LOGTAG, String.format( "pos changed hwnd %08x after %08x owner %08x style %08x win %s client %s visible %s flags %08x", Log.i( LOGTAG, String.format( "pos changed hwnd %08x after %08x owner %08x style %08x win %s client %s visible %s flags %08x",
hwnd, insert_after, owner, style, window_rect, client_rect, visible_rect, flags )); hwnd, insert_after, owner, style, window_rect, client_rect, visible_rect, flags ));
if (parent == null) if (window_group != null)
{ {
window_view.layout( visible_rect.left, visible_rect.top, visible_rect.right, visible_rect.bottom ); window_group.set_layout( visible_rect.left, visible_rect.top,
if (!visible && (style & WS_VISIBLE) != 0) top_view.addView( window_view ); visible_rect.right, visible_rect.bottom );
else if (visible && (style & WS_VISIBLE) == 0) top_view.removeView( window_view ); if (parent != null)
{
if (!visible && (style & WS_VISIBLE) != 0)
parent.client_group.addView( window_group );
else if (visible && (style & WS_VISIBLE) == 0)
parent.client_group.removeView( window_group );
}
} }
if (client_group != null)
client_group.set_layout( client_rect.left - visible_rect.left,
client_rect.top - visible_rect.top,
client_rect.right - visible_rect.left,
client_rect.bottom - visible_rect.top );
visible = (style & WS_VISIBLE) != 0; visible = (style & WS_VISIBLE) != 0;
} }
public void set_parent( WineWindow new_parent ) public void set_parent( WineWindow new_parent )
{ {
Log.i( LOGTAG, String.format( "set parent hwnd %08x parent %08x -> %08x", Log.i( LOGTAG, String.format( "set parent hwnd %08x parent %08x -> %08x",
hwnd, parent == null ? 0 : parent.hwnd, hwnd, parent.hwnd, new_parent.hwnd ));
new_parent == null ? 0 : new_parent.hwnd )); if (window_group != null)
parent = new_parent;
if (new_parent == null)
{ {
window_view = new WineView( WineActivity.this, this, false ); if (visible) parent.client_group.removeView( window_group );
window_view.layout( 0, 0, 1, 1 ); // make sure the surface gets created WineWindowGroup parent_group = new_parent.create_window_groups();
if (visible) parent_group.addView( window_group );
window_group.set_layout( visible_rect.left, visible_rect.top,
visible_rect.right, visible_rect.bottom );
window_group.bringToFront();
} }
else window_view = null; parent = new_parent;
} }
public int get_hwnd() public int get_hwnd()
@ -385,8 +446,70 @@ public void set_surface( SurfaceTexture surftex, boolean is_client )
public void get_event_pos( MotionEvent event, int[] pos ) public void get_event_pos( MotionEvent event, int[] pos )
{ {
pos[0] = Math.round( event.getX() + window_view.getLeft() ); pos[0] = Math.round( event.getX() + window_group.getLeft() );
pos[1] = Math.round( event.getY() + window_view.getTop() ); pos[1] = Math.round( event.getY() + window_group.getTop() );
}
}
//
// Window group for a Wine window, optionally containing a content view
//
protected class WineWindowGroup extends ViewGroup
{
private WineView content_view;
private WineWindow win;
WineWindowGroup()
{
super( WineActivity.this );
setVisibility( View.VISIBLE );
}
/* wrapper for layout() making sure that the view is not empty */
public void set_layout( int left, int top, int right, int bottom )
{
if (right <= left + 1) right = left + 2;
if (bottom <= top + 1) bottom = top + 2;
layout( left, top, right, bottom );
}
@Override
protected void onLayout( boolean changed, int left, int top, int right, int bottom )
{
if (content_view != null) content_view.layout( 0, 0, right - left, bottom - top );
}
public WineView create_view( WineWindow win, boolean is_client )
{
if (content_view != null) return content_view;
content_view = new WineView( WineActivity.this, win, is_client );
addView( content_view );
this.win = win;
if (!is_client)
{
content_view.setFocusable( true );
content_view.setFocusableInTouchMode( true );
}
return content_view;
}
public void destroy_view()
{
if (content_view == null) return;
removeView( content_view );
content_view = null;
win = null;
}
public WineView get_content_view()
{
return content_view;
}
public WineWindow get_window()
{
return win;
} }
} }
@ -443,7 +566,7 @@ public void onSurfaceTextureUpdated(SurfaceTexture surftex)
public boolean onGenericMotionEvent( MotionEvent event ) public boolean onGenericMotionEvent( MotionEvent event )
{ {
if (is_client) return false; // let the whole window handle it if (is_client) return false; // let the whole window handle it
if (window.parent != null) return false; // let the parent handle it if (window.parent != null && window.parent != desktop_window) return false; // let the parent handle it
if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0)
{ {
@ -461,7 +584,7 @@ public boolean onGenericMotionEvent( MotionEvent event )
public boolean onTouchEvent( MotionEvent event ) public boolean onTouchEvent( MotionEvent event )
{ {
if (is_client) return false; // let the whole window handle it if (is_client) return false; // let the whole window handle it
if (window.parent != null) return false; // let the parent handle it if (window.parent != null && window.parent != desktop_window) return false; // let the parent handle it
int[] pos = new int[2]; int[] pos = new int[2];
window.get_event_pos( event, pos ); window.get_event_pos( event, pos );
@ -488,12 +611,12 @@ public boolean dispatchKeyEvent( KeyEvent event )
protected class TopView extends ViewGroup protected class TopView extends ViewGroup
{ {
private int desktop_hwnd;
public TopView( Context context, int hwnd ) public TopView( Context context, int hwnd )
{ {
super( context ); super( context );
desktop_hwnd = hwnd; desktop_window = new WineWindow( hwnd, null );
addView( desktop_window.create_whole_view() );
desktop_window.client_group.bringToFront();
} }
@Override @Override
@ -510,8 +633,6 @@ protected void onLayout( boolean changed, int left, int top, int right, int bott
} }
} }
protected TopView top_view;
protected WineWindow get_window( int hwnd ) protected WineWindow get_window( int hwnd )
{ {
return win_map.get( hwnd ); return win_map.get( hwnd );
@ -522,8 +643,7 @@ protected WineWindow get_window( int hwnd )
public void create_desktop_window( int hwnd ) public void create_desktop_window( int hwnd )
{ {
Log.i( LOGTAG, String.format( "create desktop view %08x", hwnd )); Log.i( LOGTAG, String.format( "create desktop view %08x", hwnd ));
top_view = new TopView( this, hwnd ); setContentView( new TopView( this, hwnd ));
setContentView( top_view );
progress_dialog.dismiss(); progress_dialog.dismiss();
wine_config_changed( getResources().getConfiguration().densityDpi ); wine_config_changed( getResources().getConfiguration().densityDpi );
} }
@ -531,7 +651,13 @@ public void create_desktop_window( int hwnd )
public void create_window( int hwnd, boolean opengl, int parent, int pid ) public void create_window( int hwnd, boolean opengl, int parent, int pid )
{ {
WineWindow win = get_window( hwnd ); WineWindow win = get_window( hwnd );
if (win == null) win = new WineWindow( hwnd, get_window( parent )); if (win == null)
{
win = new WineWindow( hwnd, get_window( parent ));
win.create_window_groups();
if (win.parent == desktop_window) win.create_whole_view();
}
if (opengl) win.create_client_view();
} }
public void destroy_window( int hwnd ) public void destroy_window( int hwnd )
@ -545,6 +671,7 @@ public void set_window_parent( int hwnd, int parent, int pid )
WineWindow win = get_window( hwnd ); WineWindow win = get_window( hwnd );
if (win == null) return; if (win == null) return;
win.set_parent( get_window( parent )); win.set_parent( get_window( parent ));
if (win.parent == desktop_window) win.create_whole_view();
} }
public void window_pos_changed( int hwnd, int flags, int insert_after, int owner, int style, public void window_pos_changed( int hwnd, int flags, int insert_after, int owner, int style,

View File

@ -1378,7 +1378,7 @@ struct ANativeWindow *create_ioctl_window( HWND hwnd, BOOL opengl )
req.hdr.hwnd = HandleToLong( win->hwnd ); req.hdr.hwnd = HandleToLong( win->hwnd );
req.hdr.opengl = win->opengl; req.hdr.opengl = win->opengl;
req.parent = parent == GetDesktopWindow() ? 0 : HandleToLong( parent ); req.parent = HandleToLong( parent );
android_ioctl( IOCTL_CREATE_WINDOW, &req, sizeof(req), NULL, NULL ); android_ioctl( IOCTL_CREATE_WINDOW, &req, sizeof(req), NULL, NULL );
return &win->win; return &win->win;
@ -1438,7 +1438,7 @@ int ioctl_set_window_parent( HWND hwnd, HWND parent )
req.hdr.hwnd = HandleToLong( hwnd ); req.hdr.hwnd = HandleToLong( hwnd );
req.hdr.opengl = FALSE; req.hdr.opengl = FALSE;
req.parent = parent == GetDesktopWindow() ? 0 : HandleToLong( parent ); req.parent = HandleToLong( parent );
return android_ioctl( IOCTL_SET_WINDOW_PARENT, &req, sizeof(req), NULL, NULL ); return android_ioctl( IOCTL_SET_WINDOW_PARENT, &req, sizeof(req), NULL, NULL );
} }