wineandroid: Add support for scaling window contents based on DPI.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2018-08-23 11:11:30 +02:00
parent 240edd3fa3
commit e658c73aed
5 changed files with 62 additions and 23 deletions

View File

@ -308,6 +308,7 @@ protected class WineWindow extends Object
protected int hwnd;
protected int owner;
protected int style;
protected float scale;
protected boolean visible;
protected Rect visible_rect;
protected Rect client_rect;
@ -326,6 +327,7 @@ public WineWindow( int w, WineWindow parent )
hwnd = w;
owner = 0;
style = 0;
scale = 1.0f;
visible = false;
visible_rect = client_rect = new Rect( 0, 0, 0, 0 );
this.parent = parent;
@ -378,8 +380,10 @@ public void destroy_window_groups()
public View create_whole_view()
{
if (window_group == null) create_window_groups();
window_group.create_view( false ).layout( 0, 0, visible_rect.right - visible_rect.left,
visible_rect.bottom - visible_rect.top );
window_group.create_view( false ).layout( 0, 0,
Math.round( (visible_rect.right - visible_rect.left) * scale ),
Math.round( (visible_rect.bottom - visible_rect.top) * scale ));
window_group.set_scale( scale );
return window_group;
}
@ -476,10 +480,11 @@ public void pos_changed( int flags, int insert_after, int owner, int style,
client_rect.bottom - visible_rect.top );
}
public void set_parent( WineWindow new_parent )
public void set_parent( WineWindow new_parent, float scale )
{
Log.i( LOGTAG, String.format( "set parent hwnd %08x parent %08x -> %08x",
hwnd, parent.hwnd, new_parent.hwnd ));
this.scale = scale;
if (window_group != null)
{
if (visible) remove_view_from_parent();
@ -526,8 +531,8 @@ else if (surftex != window_surftex)
public void get_event_pos( MotionEvent event, int[] pos )
{
pos[0] = Math.round( event.getX() + window_group.getLeft() );
pos[1] = Math.round( event.getY() + window_group.getTop() );
pos[0] = Math.round( event.getX() * scale + window_group.getLeft() );
pos[1] = Math.round( event.getY() * scale + window_group.getTop() );
}
}
@ -550,6 +555,10 @@ protected class WineWindowGroup extends ViewGroup
/* wrapper for layout() making sure that the view is not empty */
public void set_layout( int left, int top, int right, int bottom )
{
left *= win.scale;
top *= win.scale;
right *= win.scale;
bottom *= win.scale;
if (right <= left + 1) right = left + 2;
if (bottom <= top + 1) bottom = top + 2;
layout( left, top, right, bottom );
@ -561,6 +570,15 @@ protected void onLayout( boolean changed, int left, int top, int right, int bott
if (content_view != null) content_view.layout( 0, 0, right - left, bottom - top );
}
public void set_scale( float scale )
{
if (content_view == null) return;
content_view.setPivotX( 0 );
content_view.setPivotY( 0 );
content_view.setScaleX( scale );
content_view.setScaleY( scale );
}
public WineView create_view( boolean is_client )
{
if (content_view != null) return content_view;
@ -730,12 +748,13 @@ public void create_desktop_window( int hwnd )
wine_config_changed( getResources().getConfiguration().densityDpi );
}
public void create_window( int hwnd, boolean opengl, int parent, int pid )
public void create_window( int hwnd, boolean opengl, int parent, float scale, int pid )
{
WineWindow win = get_window( hwnd );
if (win == null)
{
win = new WineWindow( hwnd, get_window( parent ));
win.scale = scale;
win.create_window_groups();
if (win.parent == desktop_window) win.create_whole_view();
}
@ -748,11 +767,11 @@ public void destroy_window( int hwnd )
if (win != null) win.destroy();
}
public void set_window_parent( int hwnd, int parent, int pid )
public void set_window_parent( int hwnd, int parent, float scale, int pid )
{
WineWindow win = get_window( hwnd );
if (win == null) return;
win.set_parent( get_window( parent ));
win.set_parent( get_window( parent ), scale );
if (win.parent == desktop_window) win.create_whole_view();
}
@ -769,9 +788,9 @@ public void createDesktopWindow( final int hwnd )
runOnUiThread( new Runnable() { public void run() { create_desktop_window( hwnd ); }} );
}
public void createWindow( final int hwnd, final boolean opengl, final int parent, final int pid )
public void createWindow( final int hwnd, final boolean opengl, final int parent, final float scale, final int pid )
{
runOnUiThread( new Runnable() { public void run() { create_window( hwnd, opengl, parent, pid ); }} );
runOnUiThread( new Runnable() { public void run() { create_window( hwnd, opengl, parent, scale, pid ); }} );
}
public void destroyWindow( final int hwnd )
@ -779,9 +798,9 @@ 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 )
public void setParent( final int hwnd, final int parent, final float scale, final int pid )
{
runOnUiThread( new Runnable() { public void run() { set_window_parent( hwnd, parent, pid ); }} );
runOnUiThread( new Runnable() { public void run() { set_window_parent( hwnd, parent, scale, pid ); }} );
}
public void windowPosChanged( final int hwnd, final int flags, final int insert_after,

View File

@ -63,14 +63,14 @@ extern struct opengl_funcs *get_wgl_driver( UINT version ) DECLSPEC_HIDDEN;
extern void start_android_device(void) DECLSPEC_HIDDEN;
extern void register_native_window( HWND hwnd, struct ANativeWindow *win, BOOL client ) DECLSPEC_HIDDEN;
extern struct ANativeWindow *create_ioctl_window( HWND hwnd, BOOL opengl ) DECLSPEC_HIDDEN;
extern struct ANativeWindow *create_ioctl_window( HWND hwnd, BOOL opengl, float scale ) DECLSPEC_HIDDEN;
extern struct ANativeWindow *grab_ioctl_window( struct ANativeWindow *window ) DECLSPEC_HIDDEN;
extern void release_ioctl_window( struct ANativeWindow *window ) DECLSPEC_HIDDEN;
extern void destroy_ioctl_window( HWND hwnd, BOOL opengl ) 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;
extern int ioctl_set_window_parent( HWND hwnd, HWND parent, float scale ) DECLSPEC_HIDDEN;
extern int ioctl_set_capture( HWND hwnd ) DECLSPEC_HIDDEN;

View File

@ -132,6 +132,7 @@ struct ioctl_android_create_window
{
struct ioctl_header hdr;
int parent;
float scale;
};
struct ioctl_android_destroy_window
@ -203,6 +204,7 @@ struct ioctl_android_set_window_parent
{
struct ioctl_header hdr;
int parent;
float scale;
};
struct ioctl_android_set_capture
@ -595,10 +597,10 @@ static NTSTATUS createWindow_ioctl( void *data, DWORD in_size, DWORD out_size, U
TRACE( "hwnd %08x opengl %u parent %08x\n", res->hdr.hwnd, res->hdr.opengl, res->parent );
if (!(object = load_java_method( &method, "createWindow", "(IZII)V" ))) return STATUS_NOT_SUPPORTED;
if (!(object = load_java_method( &method, "createWindow", "(IZIFI)V" ))) return STATUS_NOT_SUPPORTED;
wrap_java_call();
(*jni_env)->CallVoidMethod( jni_env, object, method, res->hdr.hwnd, res->hdr.opengl, res->parent, pid );
(*jni_env)->CallVoidMethod( jni_env, object, method, res->hdr.hwnd, res->hdr.opengl, res->parent, res->scale, pid );
unwrap_java_call();
return STATUS_SUCCESS;
}
@ -891,10 +893,10 @@ static NTSTATUS setWindowParent_ioctl( void *data, DWORD in_size, DWORD out_size
TRACE( "hwnd %08x parent %08x\n", res->hdr.hwnd, res->parent );
if (!(object = load_java_method( &method, "setParent", "(III)V" ))) return STATUS_NOT_SUPPORTED;
if (!(object = load_java_method( &method, "setParent", "(IIFI)V" ))) return STATUS_NOT_SUPPORTED;
wrap_java_call();
(*jni_env)->CallVoidMethod( jni_env, object, method, res->hdr.hwnd, res->parent, pid );
(*jni_env)->CallVoidMethod( jni_env, object, method, res->hdr.hwnd, res->parent, res->scale, pid );
unwrap_java_call();
return STATUS_SUCCESS;
}
@ -1370,7 +1372,7 @@ static int perform( ANativeWindow *window, int operation, ... )
return android_ioctl( IOCTL_PERFORM, &perf, sizeof(perf), NULL, NULL );
}
struct ANativeWindow *create_ioctl_window( HWND hwnd, BOOL opengl )
struct ANativeWindow *create_ioctl_window( HWND hwnd, BOOL opengl, float scale )
{
struct ioctl_android_create_window req;
struct native_win_wrapper *win = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*win) );
@ -1399,6 +1401,7 @@ struct ANativeWindow *create_ioctl_window( HWND hwnd, BOOL opengl )
req.hdr.hwnd = HandleToLong( win->hwnd );
req.hdr.opengl = win->opengl;
req.parent = get_ioctl_win_parent( GetAncestor( hwnd, GA_PARENT ));
req.scale = scale;
android_ioctl( IOCTL_CREATE_WINDOW, &req, sizeof(req), NULL, NULL );
return &win->win;
@ -1452,13 +1455,14 @@ int ioctl_window_pos_changed( HWND hwnd, const RECT *window_rect, const RECT *cl
return android_ioctl( IOCTL_WINDOW_POS_CHANGED, &req, sizeof(req), NULL, NULL );
}
int ioctl_set_window_parent( HWND hwnd, HWND parent )
int ioctl_set_window_parent( HWND hwnd, HWND parent, float scale )
{
struct ioctl_android_set_window_parent req;
req.hdr.hwnd = HandleToLong( hwnd );
req.hdr.opengl = FALSE;
req.parent = get_ioctl_win_parent( parent );
req.scale = scale;
return android_ioctl( IOCTL_SET_WINDOW_PARENT, &req, sizeof(req), NULL, NULL );
}

View File

@ -128,7 +128,7 @@ static struct gl_drawable *create_gl_drawable( HWND hwnd, HDC hdc, int format )
gl->hwnd = hwnd;
gl->hdc = hdc;
gl->format = format;
gl->window = create_ioctl_window( hwnd, TRUE );
gl->window = create_ioctl_window( hwnd, TRUE, 1.0f );
gl->surface = 0;
gl->pbuffer = p_eglCreatePbufferSurface( display, pixel_formats[gl->format - 1].config, attribs );
EnterCriticalSection( &drawable_section );

View File

@ -103,6 +103,21 @@ static inline int get_dib_image_size( const BITMAPINFO *info )
}
/**********************************************************************
* get_win_monitor_dpi
*/
static UINT get_win_monitor_dpi( HWND hwnd )
{
DPI_AWARENESS_CONTEXT context;
UINT ret;
context = SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
ret = GetDpiForSystem(); /* FIXME: get monitor dpi */
SetThreadDpiAwarenessContext( context );
return ret;
}
/***********************************************************************
* alloc_win_data
*/
@ -113,7 +128,8 @@ static struct android_win_data *alloc_win_data( HWND hwnd )
if ((data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data))))
{
data->hwnd = hwnd;
data->window = create_ioctl_window( hwnd, FALSE );
data->window = create_ioctl_window( hwnd, FALSE,
(float)get_win_monitor_dpi( hwnd ) / GetDpiForWindow( hwnd ));
EnterCriticalSection( &win_data_section );
win_data_context[context_idx(hwnd)] = data;
}
@ -1176,7 +1192,7 @@ void CDECL ANDROID_SetParent( HWND hwnd, HWND parent, HWND old_parent )
TRACE( "win %p parent %p -> %p\n", hwnd, old_parent, parent );
data->parent = (parent == GetDesktopWindow()) ? 0 : parent;
ioctl_set_window_parent( hwnd, parent );
ioctl_set_window_parent( hwnd, parent, (float)get_win_monitor_dpi( hwnd ) / GetDpiForWindow( hwnd ));
release_win_data( data );
}