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
;
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
;
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
;
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";
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" ));
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() );
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" );
127 runWine( cmdline
, env
);
130 private final void runWine( String cmdline
, HashMap
<String
,String
> environ
)
132 String
[] env
= new String
[environ
.size() * 2];
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" ),
142 "/desktop=shell,,android",
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();
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;
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
>();
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
) { }
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();
235 if (dest
.createNewFile())
237 InputStream in
= getAssets().open( src
);
238 FileOutputStream out
= new FileOutputStream( dest
);
240 byte[] buffer
= new byte[65536];
242 while ((read
= in
.read( buffer
)) > 0) out
.write( buffer
, 0, read
);
244 if (isFileExecutable( src
)) dest
.setExecutable( true, true );
247 Log
.i( LOGTAG
, "Failed to create file " + dest
);
249 catch( IOException e
)
251 Log
.i( LOGTAG
, "Failed to copy asset file to " + dest
);
256 private final void deleteAssetFile( String src
)
258 File dest
= new File( getFilesDir(), src
);
259 Log
.i( LOGTAG
, "deleting " + dest
);
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;
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
));
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
));
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
);
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
);
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();
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
);
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
)
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()
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;
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
;
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
);
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 );
492 parent
.children
.add( this );
493 if (visible
&& window_group
!= null) add_view_to_parent();
496 public int get_hwnd()
501 public void set_surface( SurfaceTexture surftex
, boolean 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 );
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 );
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
);
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
);
571 content_view
.setFocusable( true );
572 content_view
.setFocusableInTouchMode( true );
577 public void destroy_view()
579 if (content_view
== null) return;
580 removeView( content_view
);
584 public WineView
get_content_view()
589 public WineWindow
get_window()
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
)
607 setSurfaceTextureListener( this );
608 setVisibility( VISIBLE
);
610 setFocusable( true );
611 setFocusableInTouchMode( true );
614 public WineWindow
get_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
);
689 // The top-level desktop view group
691 protected class TopView
extends ViewGroup
693 public TopView( Context context
, int hwnd
)
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();
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
);
712 protected void onLayout( boolean changed
, int left
, int top
, int right
, int bottom
)
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
);
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
);
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
); }} );