wined3d: Unroll SM4+ pixel shader inputs.
[wine.git] / dlls / wineandroid.drv / WineActivity.java
blob3345e18d0b9a58e5eb7d103e759ce55401cd9744
1 /*
2 * WineActivity class
4 * Copyright 2013-2017 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 package org.winehq.wine;
23 import android.app.Activity;
24 import android.app.ProgressDialog;
25 import android.content.Context;
26 import android.content.SharedPreferences;
27 import android.graphics.Rect;
28 import android.graphics.SurfaceTexture;
29 import android.os.Build;
30 import android.os.Bundle;
31 import android.preference.PreferenceManager;
32 import android.util.Log;
33 import android.view.InputDevice;
34 import android.view.KeyEvent;
35 import android.view.MotionEvent;
36 import android.view.Surface;
37 import android.view.TextureView;
38 import android.view.View;
39 import android.view.ViewGroup;
40 import java.io.BufferedReader;
41 import java.io.File;
42 import java.io.FileInputStream;
43 import java.io.FileOutputStream;
44 import java.io.IOException;
45 import java.io.InputStream;
46 import java.io.InputStreamReader;
47 import java.util.ArrayList;
48 import java.util.HashMap;
49 import java.util.Locale;
50 import java.util.Map;
52 public class WineActivity extends Activity
54 private native String wine_init( String[] cmdline, String[] env );
55 public native void wine_desktop_changed( int width, int height );
56 public native void wine_config_changed( int dpi );
57 public native void wine_surface_changed( int hwnd, Surface surface, boolean opengl );
58 public native boolean wine_motion_event( int hwnd, int action, int x, int y, int state, int vscroll );
59 public native boolean wine_keyboard_event( int hwnd, int action, int keycode, int state );
61 private final String LOGTAG = "wine";
62 private ProgressDialog progress_dialog;
64 protected WineWindow desktop_window;
65 protected WineWindow message_window;
67 @Override
68 public void onCreate(Bundle savedInstanceState)
70 super.onCreate( savedInstanceState );
72 requestWindowFeature( android.view.Window.FEATURE_NO_TITLE );
74 new Thread( new Runnable() { public void run() { loadWine( null ); }} ).start();
77 private void loadWine( String cmdline )
79 File bindir = new File( getFilesDir(), Build.CPU_ABI + "/bin" );
80 File libdir = new File( getFilesDir(), Build.CPU_ABI + "/lib" );
81 File dlldir = new File( libdir, "wine" );
82 File prefix = new File( getFilesDir(), "prefix" );
83 File loader = new File( bindir, "wine" );
84 String locale = Locale.getDefault().getLanguage() + "_" +
85 Locale.getDefault().getCountry() + ".UTF-8";
87 copyAssetFiles();
89 HashMap<String,String> env = new HashMap<String,String>();
90 env.put( "WINELOADER", loader.toString() );
91 env.put( "WINEPREFIX", prefix.toString() );
92 env.put( "WINEDLLPATH", dlldir.toString() );
93 env.put( "LD_LIBRARY_PATH", libdir.toString() + ":" + getApplicationInfo().nativeLibraryDir );
94 env.put( "LC_ALL", locale );
95 env.put( "LANG", locale );
96 env.put( "PATH", bindir.toString() + ":" + System.getenv( "PATH" ));
98 if (cmdline == null)
100 if (new File( prefix, "drive_c/winestart.cmd" ).exists()) cmdline = "c:\\winestart.cmd";
101 else cmdline = "wineconsole.exe";
104 String winedebug = readFileString( new File( prefix, "winedebug" ));
105 if (winedebug == null) winedebug = readFileString( new File( getFilesDir(), "winedebug" ));
106 if (winedebug != null)
108 File log = new File( getFilesDir(), "log" );
109 env.put( "WINEDEBUG", winedebug );
110 env.put( "WINEDEBUGLOG", log.toString() );
111 Log.i( LOGTAG, "logging to " + log.toString() );
112 log.delete();
115 createProgressDialog( 0, "Setting up the Windows environment..." );
119 System.loadLibrary( "wine" );
121 catch (java.lang.UnsatisfiedLinkError e)
123 System.load( libdir.toString() + "/libwine.so" );
125 prefix.mkdirs();
127 runWine( cmdline, env );
130 private final void runWine( String cmdline, HashMap<String,String> environ )
132 String[] env = new String[environ.size() * 2];
133 int j = 0;
134 for (Map.Entry<String,String> entry : environ.entrySet())
136 env[j++] = entry.getKey();
137 env[j++] = entry.getValue();
140 String[] cmd = { environ.get( "WINELOADER" ),
141 "explorer.exe",
142 "/desktop=shell,,android",
143 cmdline };
145 String err = wine_init( cmd, env );
146 Log.e( LOGTAG, err );
149 private void createProgressDialog( final int max, final String message )
151 runOnUiThread( new Runnable() { public void run() {
152 if (progress_dialog != null) progress_dialog.dismiss();
153 progress_dialog = new ProgressDialog( WineActivity.this );
154 progress_dialog.setProgressStyle( max > 0 ? ProgressDialog.STYLE_HORIZONTAL
155 : ProgressDialog.STYLE_SPINNER );
156 progress_dialog.setTitle( "Wine" );
157 progress_dialog.setMessage( message );
158 progress_dialog.setCancelable( false );
159 progress_dialog.setMax( max );
160 progress_dialog.show();
161 }});
165 private final boolean isFileWanted( String name )
167 if (name.equals( "files.sum" )) return true;
168 if (name.startsWith( "share/" )) return true;
169 if (name.startsWith( Build.CPU_ABI + "/system/" )) return false;
170 if (name.startsWith( Build.CPU_ABI + "/" )) return true;
171 if (name.startsWith( "x86/" )) return true;
172 return false;
175 private final boolean isFileExecutable( String name )
177 return name.startsWith( Build.CPU_ABI + "/" ) || name.startsWith( "x86/" );
180 private final HashMap<String,String> readMapFromInputStream( InputStream in )
182 HashMap<String,String> map = new HashMap<String,String>();
183 String str;
187 BufferedReader reader = new BufferedReader( new InputStreamReader( in, "UTF-8" ));
188 while ((str = reader.readLine()) != null)
190 String entry[] = str.split( "\\s+", 2 );
191 if (entry.length == 2 && isFileWanted( entry[1] )) map.put( entry[1], entry[0] );
194 catch( IOException e ) { }
195 return map;
198 private final HashMap<String,String> readMapFromDiskFile( String file )
202 return readMapFromInputStream( new FileInputStream( new File( getFilesDir(), file )));
204 catch( IOException e ) { return new HashMap<String,String>(); }
207 private final HashMap<String,String> readMapFromAssetFile( String file )
211 return readMapFromInputStream( getAssets().open( file ) );
213 catch( IOException e ) { return new HashMap<String,String>(); }
216 private final String readFileString( File file )
220 FileInputStream in = new FileInputStream( file );
221 BufferedReader reader = new BufferedReader( new InputStreamReader( in, "UTF-8" ));
222 return reader.readLine();
224 catch( IOException e ) { return null; }
227 private final void copyAssetFile( String src )
229 File dest = new File( getFilesDir(), src );
232 Log.i( LOGTAG, "extracting " + dest );
233 dest.getParentFile().mkdirs();
234 dest.delete();
235 if (dest.createNewFile())
237 InputStream in = getAssets().open( src );
238 FileOutputStream out = new FileOutputStream( dest );
239 int read;
240 byte[] buffer = new byte[65536];
242 while ((read = in.read( buffer )) > 0) out.write( buffer, 0, read );
243 out.close();
244 if (isFileExecutable( src )) dest.setExecutable( true, true );
246 else
247 Log.i( LOGTAG, "Failed to create file " + dest );
249 catch( IOException e )
251 Log.i( LOGTAG, "Failed to copy asset file to " + dest );
252 dest.delete();
256 private final void deleteAssetFile( String src )
258 File dest = new File( getFilesDir(), src );
259 Log.i( LOGTAG, "deleting " + dest );
260 dest.delete();
263 private final void copyAssetFiles()
265 String new_sum = readMapFromAssetFile( "sums.sum" ).get( "files.sum" );
266 if (new_sum == null) return; // no assets
268 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences( this );
269 String old_sum = prefs.getString( "files.sum", "" );
270 if (old_sum.equals( new_sum )) return; // no change
271 prefs.edit().putString( "files.sum", new_sum ).apply();
273 HashMap<String,String> existing_files = readMapFromDiskFile( "files.sum" );
274 HashMap<String,String> new_files = readMapFromAssetFile( "files.sum" );
275 ArrayList<String> copy_files = new ArrayList<String>();
276 copy_files.add( "files.sum" );
278 for (Map.Entry<String, String> entry : new_files.entrySet())
280 String name = entry.getKey();
281 if (!entry.getValue().equals( existing_files.remove( name ))) copy_files.add( name );
284 createProgressDialog( copy_files.size(), "Extracting files..." );
286 for (String name : existing_files.keySet()) deleteAssetFile( name );
288 for (String name : copy_files)
290 copyAssetFile( name );
291 runOnUiThread( new Runnable() { public void run() {
292 progress_dialog.incrementProgressBy( 1 ); }});
297 // Generic Wine window class
300 private HashMap<Integer,WineWindow> win_map = new HashMap<Integer,WineWindow>();
302 protected class WineWindow extends Object
304 static protected final int HWND_MESSAGE = 0xfffffffd;
305 static protected final int SWP_NOZORDER = 0x04;
306 static protected final int WS_VISIBLE = 0x10000000;
308 protected int hwnd;
309 protected int owner;
310 protected int style;
311 protected boolean visible;
312 protected Rect visible_rect;
313 protected Rect client_rect;
314 protected WineWindow parent;
315 protected ArrayList<WineWindow> children;
316 protected Surface window_surface;
317 protected Surface client_surface;
318 protected SurfaceTexture window_surftex;
319 protected SurfaceTexture client_surftex;
320 protected WineWindowGroup window_group;
321 protected WineWindowGroup client_group;
323 public WineWindow( int w, WineWindow parent )
325 Log.i( LOGTAG, String.format( "create hwnd %08x", w ));
326 hwnd = w;
327 owner = 0;
328 style = 0;
329 visible = false;
330 visible_rect = client_rect = new Rect( 0, 0, 0, 0 );
331 this.parent = parent;
332 children = new ArrayList<WineWindow>();
333 win_map.put( w, this );
334 if (parent != null) parent.children.add( this );
337 public void destroy()
339 Log.i( LOGTAG, String.format( "destroy hwnd %08x", hwnd ));
340 visible = false;
341 win_map.remove( this );
342 if (parent != null) parent.children.remove( this );
343 destroy_window_groups();
346 public WineWindowGroup create_window_groups()
348 if (client_group != null) return client_group;
349 window_group = new WineWindowGroup( this );
350 client_group = new WineWindowGroup( this );
351 window_group.addView( client_group );
352 client_group.set_layout( client_rect.left - visible_rect.left,
353 client_rect.top - visible_rect.top,
354 client_rect.right - visible_rect.left,
355 client_rect.bottom - visible_rect.top );
356 if (parent != null)
358 parent.create_window_groups();
359 if (visible) add_view_to_parent();
360 window_group.set_layout( visible_rect.left, visible_rect.top,
361 visible_rect.right, visible_rect.bottom );
363 return client_group;
366 public void destroy_window_groups()
368 if (window_group != null)
370 if (parent != null && parent.client_group != null) remove_view_from_parent();
371 window_group.destroy_view();
373 if (client_group != null) client_group.destroy_view();
374 window_group = null;
375 client_group = null;
378 public View create_whole_view()
380 if (window_group == null) create_window_groups();
381 window_group.create_view( false ).layout( 0, 0, visible_rect.right - visible_rect.left,
382 visible_rect.bottom - visible_rect.top );
383 return window_group;
386 public void create_client_view()
388 if (client_group == null) create_window_groups();
389 Log.i( LOGTAG, String.format( "creating client view %08x %s", hwnd, client_rect ));
390 client_group.create_view( true ).layout( 0, 0, client_rect.right - client_rect.left,
391 client_rect.bottom - client_rect.top );
394 protected void add_view_to_parent()
396 int pos = parent.client_group.getChildCount() - 1;
398 // the content view is always last
399 if (pos >= 0 && parent.client_group.getChildAt( pos ) == parent.client_group.get_content_view()) pos--;
401 for (int i = 0; i < parent.children.size() && pos >= 0; i++)
403 WineWindow child = parent.children.get( i );
404 if (child == this) break;
405 if (!child.visible) continue;
406 if (child == ((WineWindowGroup)parent.client_group.getChildAt( pos )).get_window()) pos--;
408 parent.client_group.addView( window_group, pos + 1 );
411 protected void remove_view_from_parent()
413 parent.client_group.removeView( window_group );
416 protected void set_zorder( WineWindow prev )
418 int pos = -1;
420 parent.children.remove( this );
421 if (prev != null) pos = parent.children.indexOf( prev );
422 parent.children.add( pos + 1, this );
425 protected void sync_views_zorder()
427 int i, j;
429 for (i = parent.children.size() - 1, j = 0; i >= 0; i--)
431 WineWindow child = parent.children.get( i );
432 if (!child.visible) continue;
433 View child_view = parent.client_group.getChildAt( j );
434 if (child_view == parent.client_group.get_content_view()) continue;
435 if (child != ((WineWindowGroup)child_view).get_window()) break;
436 j++;
438 while (i >= 0)
440 WineWindow child = parent.children.get( i-- );
441 if (child.visible) child.window_group.bringToFront();
445 public void pos_changed( int flags, int insert_after, int owner, int style,
446 Rect window_rect, Rect client_rect, Rect visible_rect )
448 boolean was_visible = visible;
449 this.visible_rect = visible_rect;
450 this.client_rect = client_rect;
451 this.style = style;
452 this.owner = owner;
453 visible = (style & WS_VISIBLE) != 0;
455 Log.i( LOGTAG, String.format( "pos changed hwnd %08x after %08x owner %08x style %08x win %s client %s visible %s flags %08x",
456 hwnd, insert_after, owner, style, window_rect, client_rect, visible_rect, flags ));
458 if ((flags & SWP_NOZORDER) == 0 && parent != null) set_zorder( get_window( insert_after ));
460 if (window_group != null)
462 window_group.set_layout( visible_rect.left, visible_rect.top,
463 visible_rect.right, visible_rect.bottom );
464 if (parent != null)
466 if (!was_visible && (style & WS_VISIBLE) != 0) add_view_to_parent();
467 else if (was_visible && (style & WS_VISIBLE) == 0) remove_view_from_parent();
468 else if (visible && (flags & SWP_NOZORDER) == 0) sync_views_zorder();
472 if (client_group != null)
473 client_group.set_layout( client_rect.left - visible_rect.left,
474 client_rect.top - visible_rect.top,
475 client_rect.right - visible_rect.left,
476 client_rect.bottom - visible_rect.top );
479 public void set_parent( WineWindow new_parent )
481 Log.i( LOGTAG, String.format( "set parent hwnd %08x parent %08x -> %08x",
482 hwnd, parent.hwnd, new_parent.hwnd ));
483 if (window_group != null)
485 if (visible) remove_view_from_parent();
486 new_parent.create_window_groups();
487 window_group.set_layout( visible_rect.left, visible_rect.top,
488 visible_rect.right, visible_rect.bottom );
490 parent.children.remove( this );
491 parent = new_parent;
492 parent.children.add( this );
493 if (visible && window_group != null) add_view_to_parent();
496 public int get_hwnd()
498 return hwnd;
501 public void set_surface( SurfaceTexture surftex, boolean is_client )
503 if (is_client)
505 if (surftex == null) client_surface = null;
506 else if (surftex != client_surftex)
508 client_surftex = surftex;
509 client_surface = new Surface( surftex );
511 Log.i( LOGTAG, String.format( "set client surface hwnd %08x %s", hwnd, client_surface ));
512 wine_surface_changed( hwnd, client_surface, true );
514 else
516 if (surftex == null) window_surface = null;
517 else if (surftex != window_surftex)
519 window_surftex = surftex;
520 window_surface = new Surface( surftex );
522 Log.i( LOGTAG, String.format( "set window surface hwnd %08x %s", hwnd, window_surface ));
523 wine_surface_changed( hwnd, window_surface, false );
527 public void get_event_pos( MotionEvent event, int[] pos )
529 pos[0] = Math.round( event.getX() + window_group.getLeft() );
530 pos[1] = Math.round( event.getY() + window_group.getTop() );
535 // Window group for a Wine window, optionally containing a content view
538 protected class WineWindowGroup extends ViewGroup
540 private WineView content_view;
541 private WineWindow win;
543 WineWindowGroup( WineWindow win )
545 super( WineActivity.this );
546 this.win = win;
547 setVisibility( View.VISIBLE );
550 /* wrapper for layout() making sure that the view is not empty */
551 public void set_layout( int left, int top, int right, int bottom )
553 if (right <= left + 1) right = left + 2;
554 if (bottom <= top + 1) bottom = top + 2;
555 layout( left, top, right, bottom );
558 @Override
559 protected void onLayout( boolean changed, int left, int top, int right, int bottom )
561 if (content_view != null) content_view.layout( 0, 0, right - left, bottom - top );
564 public WineView create_view( boolean is_client )
566 if (content_view != null) return content_view;
567 content_view = new WineView( WineActivity.this, win, is_client );
568 addView( content_view );
569 if (!is_client)
571 content_view.setFocusable( true );
572 content_view.setFocusableInTouchMode( true );
574 return content_view;
577 public void destroy_view()
579 if (content_view == null) return;
580 removeView( content_view );
581 content_view = null;
584 public WineView get_content_view()
586 return content_view;
589 public WineWindow get_window()
591 return win;
595 // View used for all Wine windows, backed by a TextureView
597 protected class WineView extends TextureView implements TextureView.SurfaceTextureListener
599 private WineWindow window;
600 private boolean is_client;
602 public WineView( Context c, WineWindow win, boolean client )
604 super( c );
605 window = win;
606 is_client = client;
607 setSurfaceTextureListener( this );
608 setVisibility( VISIBLE );
609 setOpaque( false );
610 setFocusable( true );
611 setFocusableInTouchMode( true );
614 public WineWindow get_window()
616 return window;
619 public void onSurfaceTextureAvailable( SurfaceTexture surftex, int width, int height )
621 Log.i( LOGTAG, String.format( "onSurfaceTextureAvailable win %08x %dx%d %s",
622 window.hwnd, width, height, is_client ? "client" : "whole" ));
623 window.set_surface( surftex, is_client );
626 public void onSurfaceTextureSizeChanged( SurfaceTexture surftex, int width, int height )
628 Log.i( LOGTAG, String.format( "onSurfaceTextureSizeChanged win %08x %dx%d %s",
629 window.hwnd, width, height, is_client ? "client" : "whole" ));
630 window.set_surface( surftex, is_client);
633 public boolean onSurfaceTextureDestroyed( SurfaceTexture surftex )
635 Log.i( LOGTAG, String.format( "onSurfaceTextureDestroyed win %08x %s",
636 window.hwnd, is_client ? "client" : "whole" ));
637 window.set_surface( null, is_client );
638 return false; // hold on to the texture since the app may still be using it
641 public void onSurfaceTextureUpdated(SurfaceTexture surftex)
645 public boolean onGenericMotionEvent( MotionEvent event )
647 if (is_client) return false; // let the whole window handle it
648 if (window.parent != null && window.parent != desktop_window) return false; // let the parent handle it
650 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0)
652 int[] pos = new int[2];
653 window.get_event_pos( event, pos );
654 Log.i( LOGTAG, String.format( "view motion event win %08x action %d pos %d,%d buttons %04x view %d,%d",
655 window.hwnd, event.getAction(), pos[0], pos[1],
656 event.getButtonState(), getLeft(), getTop() ));
657 return wine_motion_event( window.hwnd, event.getAction(), pos[0], pos[1],
658 event.getButtonState(), (int)event.getAxisValue(MotionEvent.AXIS_VSCROLL) );
660 return super.onGenericMotionEvent(event);
663 public boolean onTouchEvent( MotionEvent event )
665 if (is_client) return false; // let the whole window handle it
666 if (window.parent != null && window.parent != desktop_window) return false; // let the parent handle it
668 int[] pos = new int[2];
669 window.get_event_pos( event, pos );
670 Log.i( LOGTAG, String.format( "view touch event win %08x action %d pos %d,%d buttons %04x view %d,%d",
671 window.hwnd, event.getAction(), pos[0], pos[1],
672 event.getButtonState(), getLeft(), getTop() ));
673 return wine_motion_event( window.hwnd, event.getAction(), pos[0], pos[1],
674 event.getButtonState(), 0 );
677 public boolean dispatchKeyEvent( KeyEvent event )
679 Log.i( LOGTAG, String.format( "view key event win %08x action %d keycode %d (%s)",
680 window.hwnd, event.getAction(), event.getKeyCode(),
681 event.keyCodeToString( event.getKeyCode() )));;
682 boolean ret = wine_keyboard_event( window.hwnd, event.getAction(), event.getKeyCode(),
683 event.getMetaState() );
684 if (!ret) ret = super.dispatchKeyEvent(event);
685 return ret;
689 // The top-level desktop view group
691 protected class TopView extends ViewGroup
693 public TopView( Context context, int hwnd )
695 super( context );
696 desktop_window = new WineWindow( hwnd, null );
697 addView( desktop_window.create_whole_view() );
698 desktop_window.client_group.bringToFront();
700 message_window = new WineWindow( WineWindow.HWND_MESSAGE, null );
701 message_window.create_window_groups();
704 @Override
705 protected void onSizeChanged( int width, int height, int old_width, int old_height )
707 Log.i( LOGTAG, String.format( "desktop size %dx%d", width, height ));
708 wine_desktop_changed( width, height );
711 @Override
712 protected void onLayout( boolean changed, int left, int top, int right, int bottom )
714 // nothing to do
718 protected WineWindow get_window( int hwnd )
720 return win_map.get( hwnd );
723 // Entry points for the device driver
725 public void create_desktop_window( int hwnd )
727 Log.i( LOGTAG, String.format( "create desktop view %08x", hwnd ));
728 setContentView( new TopView( this, hwnd ));
729 progress_dialog.dismiss();
730 wine_config_changed( getResources().getConfiguration().densityDpi );
733 public void create_window( int hwnd, boolean opengl, int parent, int pid )
735 WineWindow win = get_window( hwnd );
736 if (win == null)
738 win = new WineWindow( hwnd, get_window( parent ));
739 win.create_window_groups();
740 if (win.parent == desktop_window) win.create_whole_view();
742 if (opengl) win.create_client_view();
745 public void destroy_window( int hwnd )
747 WineWindow win = get_window( hwnd );
748 if (win != null) win.destroy();
751 public void set_window_parent( int hwnd, int parent, int pid )
753 WineWindow win = get_window( hwnd );
754 if (win == null) return;
755 win.set_parent( get_window( parent ));
756 if (win.parent == desktop_window) win.create_whole_view();
759 public void window_pos_changed( int hwnd, int flags, int insert_after, int owner, int style,
760 Rect window_rect, Rect client_rect, Rect visible_rect )
762 WineWindow win = get_window( hwnd );
763 if (win != null)
764 win.pos_changed( flags, insert_after, owner, style, window_rect, client_rect, visible_rect );
767 public void createDesktopWindow( final int hwnd )
769 runOnUiThread( new Runnable() { public void run() { create_desktop_window( hwnd ); }} );
772 public void createWindow( final int hwnd, final boolean opengl, final int parent, final int pid )
774 runOnUiThread( new Runnable() { public void run() { create_window( hwnd, opengl, parent, pid ); }} );
777 public void destroyWindow( final int hwnd )
779 runOnUiThread( new Runnable() { public void run() { destroy_window( hwnd ); }} );
782 public void setParent( final int hwnd, final int parent, final int pid )
784 runOnUiThread( new Runnable() { public void run() { set_window_parent( hwnd, parent, pid ); }} );
787 public void windowPosChanged( final int hwnd, final int flags, final int insert_after,
788 final int owner, final int style,
789 final int window_left, final int window_top,
790 final int window_right, final int window_bottom,
791 final int client_left, final int client_top,
792 final int client_right, final int client_bottom,
793 final int visible_left, final int visible_top,
794 final int visible_right, final int visible_bottom )
796 final Rect window_rect = new Rect( window_left, window_top, window_right, window_bottom );
797 final Rect client_rect = new Rect( client_left, client_top, client_right, client_bottom );
798 final Rect visible_rect = new Rect( visible_left, visible_top, visible_right, visible_bottom );
799 runOnUiThread( new Runnable() {
800 public void run() { window_pos_changed( hwnd, flags, insert_after, owner, style,
801 window_rect, client_rect, visible_rect ); }} );