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 prefix
= new File( getFilesDir(), "prefix" );
82 File loader
= new File( bindir
, "wine" );
83 String locale
= Locale
.getDefault().getLanguage() + "_" +
84 Locale
.getDefault().getCountry() + ".UTF-8";
88 HashMap
<String
,String
> env
= new HashMap
<String
,String
>();
89 env
.put( "WINELOADER", loader
.toString() );
90 env
.put( "WINEPREFIX", prefix
.toString() );
91 env
.put( "LD_LIBRARY_PATH", libdir
.toString() + ":" + getApplicationInfo().nativeLibraryDir
);
92 env
.put( "LC_ALL", locale
);
93 env
.put( "LANG", locale
);
94 env
.put( "PATH", bindir
.toString() + ":" + System
.getenv( "PATH" ));
98 if (new File( prefix
, "drive_c/winestart.cmd" ).exists()) cmdline
= "c:\\winestart.cmd";
99 else cmdline
= "wineconsole.exe";
102 String winedebug
= readFileString( new File( prefix
, "winedebug" ));
103 if (winedebug
== null) winedebug
= readFileString( new File( getFilesDir(), "winedebug" ));
104 if (winedebug
!= null)
106 File log
= new File( getFilesDir(), "log" );
107 env
.put( "WINEDEBUG", winedebug
);
108 env
.put( "WINEDEBUGLOG", log
.toString() );
109 Log
.i( LOGTAG
, "logging to " + log
.toString() );
113 createProgressDialog( 0, "Setting up the Windows environment..." );
117 System
.loadLibrary( "wine" );
119 catch (java
.lang
.UnsatisfiedLinkError e
)
121 System
.load( libdir
.toString() + "/libwine.so" );
125 runWine( cmdline
, env
);
128 private final void runWine( String cmdline
, HashMap
<String
,String
> environ
)
130 String
[] env
= new String
[environ
.size() * 2];
132 for (Map
.Entry
<String
,String
> entry
: environ
.entrySet())
134 env
[j
++] = entry
.getKey();
135 env
[j
++] = entry
.getValue();
138 String
[] cmd
= { environ
.get( "WINELOADER" ),
140 "/desktop=shell,,android",
143 String err
= wine_init( cmd
, env
);
144 Log
.e( LOGTAG
, err
);
147 private void createProgressDialog( final int max
, final String message
)
149 runOnUiThread( new Runnable() { public void run() {
150 if (progress_dialog
!= null) progress_dialog
.dismiss();
151 progress_dialog
= new ProgressDialog( WineActivity
.this );
152 progress_dialog
.setProgressStyle( max
> 0 ? ProgressDialog
.STYLE_HORIZONTAL
153 : ProgressDialog
.STYLE_SPINNER
);
154 progress_dialog
.setTitle( "Wine" );
155 progress_dialog
.setMessage( message
);
156 progress_dialog
.setCancelable( false );
157 progress_dialog
.setMax( max
);
158 progress_dialog
.show();
163 private final boolean isFileWanted( String name
)
165 if (name
.equals( "files.sum" )) return true;
166 if (name
.startsWith( "share/" )) return true;
167 if (name
.startsWith( Build
.CPU_ABI
+ "/system/" )) return false;
168 if (name
.startsWith( Build
.CPU_ABI
+ "/" )) return true;
169 if (name
.startsWith( "x86/" )) return true;
173 private final boolean isFileExecutable( String name
)
175 return name
.startsWith( Build
.CPU_ABI
+ "/" ) || name
.startsWith( "x86/" );
178 private final HashMap
<String
,String
> readMapFromInputStream( InputStream in
)
180 HashMap
<String
,String
> map
= new HashMap
<String
,String
>();
185 BufferedReader reader
= new BufferedReader( new InputStreamReader( in
, "UTF-8" ));
186 while ((str
= reader
.readLine()) != null)
188 String entry
[] = str
.split( "\\s+", 2 );
189 if (entry
.length
== 2 && isFileWanted( entry
[1] )) map
.put( entry
[1], entry
[0] );
192 catch( IOException e
) { }
196 private final HashMap
<String
,String
> readMapFromDiskFile( String file
)
200 return readMapFromInputStream( new FileInputStream( new File( getFilesDir(), file
)));
202 catch( IOException e
) { return new HashMap
<String
,String
>(); }
205 private final HashMap
<String
,String
> readMapFromAssetFile( String file
)
209 return readMapFromInputStream( getAssets().open( file
) );
211 catch( IOException e
) { return new HashMap
<String
,String
>(); }
214 private final String
readFileString( File file
)
218 FileInputStream in
= new FileInputStream( file
);
219 BufferedReader reader
= new BufferedReader( new InputStreamReader( in
, "UTF-8" ));
220 return reader
.readLine();
222 catch( IOException e
) { return null; }
225 private final void copyAssetFile( String src
)
227 File dest
= new File( getFilesDir(), src
);
230 Log
.i( LOGTAG
, "extracting " + dest
);
231 dest
.getParentFile().mkdirs();
233 if (dest
.createNewFile())
235 InputStream in
= getAssets().open( src
);
236 FileOutputStream out
= new FileOutputStream( dest
);
238 byte[] buffer
= new byte[65536];
240 while ((read
= in
.read( buffer
)) > 0) out
.write( buffer
, 0, read
);
242 if (isFileExecutable( src
)) dest
.setExecutable( true, true );
245 Log
.i( LOGTAG
, "Failed to create file " + dest
);
247 catch( IOException e
)
249 Log
.i( LOGTAG
, "Failed to copy asset file to " + dest
);
254 private final void deleteAssetFile( String src
)
256 File dest
= new File( getFilesDir(), src
);
257 Log
.i( LOGTAG
, "deleting " + dest
);
261 private final void copyAssetFiles()
263 String new_sum
= readMapFromAssetFile( "sums.sum" ).get( "files.sum" );
264 if (new_sum
== null) return; // no assets
266 SharedPreferences prefs
= PreferenceManager
.getDefaultSharedPreferences( this );
267 String old_sum
= prefs
.getString( "files.sum", "" );
268 if (old_sum
.equals( new_sum
)) return; // no change
269 prefs
.edit().putString( "files.sum", new_sum
).apply();
271 HashMap
<String
,String
> existing_files
= readMapFromDiskFile( "files.sum" );
272 HashMap
<String
,String
> new_files
= readMapFromAssetFile( "files.sum" );
273 ArrayList
<String
> copy_files
= new ArrayList
<String
>();
274 copy_files
.add( "files.sum" );
276 for (Map
.Entry
<String
, String
> entry
: new_files
.entrySet())
278 String name
= entry
.getKey();
279 if (!entry
.getValue().equals( existing_files
.remove( name
))) copy_files
.add( name
);
282 createProgressDialog( copy_files
.size(), "Extracting files..." );
284 for (String name
: existing_files
.keySet()) deleteAssetFile( name
);
286 for (String name
: copy_files
)
288 copyAssetFile( name
);
289 runOnUiThread( new Runnable() { public void run() {
290 progress_dialog
.incrementProgressBy( 1 ); }});
295 // Generic Wine window class
298 private HashMap
<Integer
,WineWindow
> win_map
= new HashMap
<Integer
,WineWindow
>();
300 protected class WineWindow
extends Object
302 static protected final int HWND_MESSAGE
= 0xfffffffd;
303 static protected final int SWP_NOZORDER
= 0x04;
304 static protected final int WS_VISIBLE
= 0x10000000;
309 protected boolean visible
;
310 protected Rect visible_rect
;
311 protected Rect client_rect
;
312 protected WineWindow parent
;
313 protected ArrayList
<WineWindow
> children
;
314 protected Surface window_surface
;
315 protected Surface client_surface
;
316 protected SurfaceTexture window_surftex
;
317 protected SurfaceTexture client_surftex
;
318 protected WineWindowGroup window_group
;
319 protected WineWindowGroup client_group
;
321 public WineWindow( int w
, WineWindow parent
)
323 Log
.i( LOGTAG
, String
.format( "create hwnd %08x", w
));
328 visible_rect
= client_rect
= new Rect( 0, 0, 0, 0 );
329 this.parent
= parent
;
330 children
= new ArrayList
<WineWindow
>();
331 win_map
.put( w
, this );
332 if (parent
!= null) parent
.children
.add( this );
335 public void destroy()
337 Log
.i( LOGTAG
, String
.format( "destroy hwnd %08x", hwnd
));
339 win_map
.remove( this );
340 if (parent
!= null) parent
.children
.remove( this );
341 destroy_window_groups();
344 public WineWindowGroup
create_window_groups()
346 if (client_group
!= null) return client_group
;
347 window_group
= new WineWindowGroup( this );
348 client_group
= new WineWindowGroup( this );
349 window_group
.addView( client_group
);
350 client_group
.set_layout( client_rect
.left
- visible_rect
.left
,
351 client_rect
.top
- visible_rect
.top
,
352 client_rect
.right
- visible_rect
.left
,
353 client_rect
.bottom
- visible_rect
.top
);
356 parent
.create_window_groups();
357 if (visible
) add_view_to_parent();
358 window_group
.set_layout( visible_rect
.left
, visible_rect
.top
,
359 visible_rect
.right
, visible_rect
.bottom
);
364 public void destroy_window_groups()
366 if (window_group
!= null)
368 if (parent
!= null && parent
.client_group
!= null) remove_view_from_parent();
369 window_group
.destroy_view();
371 if (client_group
!= null) client_group
.destroy_view();
376 public View
create_whole_view()
378 if (window_group
== null) create_window_groups();
379 window_group
.create_view( false ).layout( 0, 0, visible_rect
.right
- visible_rect
.left
,
380 visible_rect
.bottom
- visible_rect
.top
);
384 public void create_client_view()
386 if (client_group
== null) create_window_groups();
387 Log
.i( LOGTAG
, String
.format( "creating client view %08x %s", hwnd
, client_rect
));
388 client_group
.create_view( true ).layout( 0, 0, client_rect
.right
- client_rect
.left
,
389 client_rect
.bottom
- client_rect
.top
);
392 protected void add_view_to_parent()
394 int pos
= parent
.client_group
.getChildCount() - 1;
396 // the content view is always last
397 if (pos
>= 0 && parent
.client_group
.getChildAt( pos
) == parent
.client_group
.get_content_view()) pos
--;
399 for (int i
= 0; i
< parent
.children
.size() && pos
>= 0; i
++)
401 WineWindow child
= parent
.children
.get( i
);
402 if (child
== this) break;
403 if (!child
.visible
) continue;
404 if (child
== ((WineWindowGroup
)parent
.client_group
.getChildAt( pos
)).get_window()) pos
--;
406 parent
.client_group
.addView( window_group
, pos
+ 1 );
409 protected void remove_view_from_parent()
411 parent
.client_group
.removeView( window_group
);
414 protected void set_zorder( WineWindow prev
)
418 parent
.children
.remove( this );
419 if (prev
!= null) pos
= parent
.children
.indexOf( prev
);
420 parent
.children
.add( pos
+ 1, this );
423 protected void sync_views_zorder()
427 for (i
= parent
.children
.size() - 1, j
= 0; i
>= 0; i
--)
429 WineWindow child
= parent
.children
.get( i
);
430 if (!child
.visible
) continue;
431 View child_view
= parent
.client_group
.getChildAt( j
);
432 if (child_view
== parent
.client_group
.get_content_view()) continue;
433 if (child
!= ((WineWindowGroup
)child_view
).get_window()) break;
438 WineWindow child
= parent
.children
.get( i
-- );
439 if (child
.visible
) child
.window_group
.bringToFront();
443 public void pos_changed( int flags
, int insert_after
, int owner
, int style
,
444 Rect window_rect
, Rect client_rect
, Rect visible_rect
)
446 boolean was_visible
= visible
;
447 this.visible_rect
= visible_rect
;
448 this.client_rect
= client_rect
;
451 visible
= (style
& WS_VISIBLE
) != 0;
453 Log
.i( LOGTAG
, String
.format( "pos changed hwnd %08x after %08x owner %08x style %08x win %s client %s visible %s flags %08x",
454 hwnd
, insert_after
, owner
, style
, window_rect
, client_rect
, visible_rect
, flags
));
456 if ((flags
& SWP_NOZORDER
) == 0 && parent
!= null) set_zorder( get_window( insert_after
));
458 if (window_group
!= null)
460 window_group
.set_layout( visible_rect
.left
, visible_rect
.top
,
461 visible_rect
.right
, visible_rect
.bottom
);
464 if (!was_visible
&& (style
& WS_VISIBLE
) != 0) add_view_to_parent();
465 else if (was_visible
&& (style
& WS_VISIBLE
) == 0) remove_view_from_parent();
466 else if (visible
&& (flags
& SWP_NOZORDER
) == 0) sync_views_zorder();
470 if (client_group
!= null)
471 client_group
.set_layout( client_rect
.left
- visible_rect
.left
,
472 client_rect
.top
- visible_rect
.top
,
473 client_rect
.right
- visible_rect
.left
,
474 client_rect
.bottom
- visible_rect
.top
);
477 public void set_parent( WineWindow new_parent
)
479 Log
.i( LOGTAG
, String
.format( "set parent hwnd %08x parent %08x -> %08x",
480 hwnd
, parent
.hwnd
, new_parent
.hwnd
));
481 if (window_group
!= null)
483 if (visible
) remove_view_from_parent();
484 new_parent
.create_window_groups();
485 window_group
.set_layout( visible_rect
.left
, visible_rect
.top
,
486 visible_rect
.right
, visible_rect
.bottom
);
488 parent
.children
.remove( this );
490 parent
.children
.add( this );
491 if (visible
&& window_group
!= null) add_view_to_parent();
494 public int get_hwnd()
499 public void set_surface( SurfaceTexture surftex
, boolean is_client
)
503 if (surftex
== null) client_surface
= null;
504 else if (surftex
!= client_surftex
)
506 client_surftex
= surftex
;
507 client_surface
= new Surface( surftex
);
509 Log
.i( LOGTAG
, String
.format( "set client surface hwnd %08x %s", hwnd
, client_surface
));
510 wine_surface_changed( hwnd
, client_surface
, true );
514 if (surftex
== null) window_surface
= null;
515 else if (surftex
!= window_surftex
)
517 window_surftex
= surftex
;
518 window_surface
= new Surface( surftex
);
520 Log
.i( LOGTAG
, String
.format( "set window surface hwnd %08x %s", hwnd
, window_surface
));
521 wine_surface_changed( hwnd
, window_surface
, false );
525 public void get_event_pos( MotionEvent event
, int[] pos
)
527 pos
[0] = Math
.round( event
.getX() + window_group
.getLeft() );
528 pos
[1] = Math
.round( event
.getY() + window_group
.getTop() );
533 // Window group for a Wine window, optionally containing a content view
536 protected class WineWindowGroup
extends ViewGroup
538 private WineView content_view
;
539 private WineWindow win
;
541 WineWindowGroup( WineWindow win
)
543 super( WineActivity
.this );
545 setVisibility( View
.VISIBLE
);
548 /* wrapper for layout() making sure that the view is not empty */
549 public void set_layout( int left
, int top
, int right
, int bottom
)
551 if (right
<= left
+ 1) right
= left
+ 2;
552 if (bottom
<= top
+ 1) bottom
= top
+ 2;
553 layout( left
, top
, right
, bottom
);
557 protected void onLayout( boolean changed
, int left
, int top
, int right
, int bottom
)
559 if (content_view
!= null) content_view
.layout( 0, 0, right
- left
, bottom
- top
);
562 public WineView
create_view( boolean is_client
)
564 if (content_view
!= null) return content_view
;
565 content_view
= new WineView( WineActivity
.this, win
, is_client
);
566 addView( content_view
);
569 content_view
.setFocusable( true );
570 content_view
.setFocusableInTouchMode( true );
575 public void destroy_view()
577 if (content_view
== null) return;
578 removeView( content_view
);
582 public WineView
get_content_view()
587 public WineWindow
get_window()
593 // View used for all Wine windows, backed by a TextureView
595 protected class WineView
extends TextureView
implements TextureView
.SurfaceTextureListener
597 private WineWindow window
;
598 private boolean is_client
;
600 public WineView( Context c
, WineWindow win
, boolean client
)
605 setSurfaceTextureListener( this );
606 setVisibility( VISIBLE
);
608 setFocusable( true );
609 setFocusableInTouchMode( true );
612 public WineWindow
get_window()
617 public void onSurfaceTextureAvailable( SurfaceTexture surftex
, int width
, int height
)
619 Log
.i( LOGTAG
, String
.format( "onSurfaceTextureAvailable win %08x %dx%d %s",
620 window
.hwnd
, width
, height
, is_client ?
"client" : "whole" ));
621 window
.set_surface( surftex
, is_client
);
624 public void onSurfaceTextureSizeChanged( SurfaceTexture surftex
, int width
, int height
)
626 Log
.i( LOGTAG
, String
.format( "onSurfaceTextureSizeChanged win %08x %dx%d %s",
627 window
.hwnd
, width
, height
, is_client ?
"client" : "whole" ));
628 window
.set_surface( surftex
, is_client
);
631 public boolean onSurfaceTextureDestroyed( SurfaceTexture surftex
)
633 Log
.i( LOGTAG
, String
.format( "onSurfaceTextureDestroyed win %08x %s",
634 window
.hwnd
, is_client ?
"client" : "whole" ));
635 window
.set_surface( null, is_client
);
636 return false; // hold on to the texture since the app may still be using it
639 public void onSurfaceTextureUpdated(SurfaceTexture surftex
)
643 public boolean onGenericMotionEvent( MotionEvent event
)
645 if (is_client
) return false; // let the whole window handle it
646 if (window
.parent
!= null && window
.parent
!= desktop_window
) return false; // let the parent handle it
648 if ((event
.getSource() & InputDevice
.SOURCE_CLASS_POINTER
) != 0)
650 int[] pos
= new int[2];
651 window
.get_event_pos( event
, pos
);
652 Log
.i( LOGTAG
, String
.format( "view motion event win %08x action %d pos %d,%d buttons %04x view %d,%d",
653 window
.hwnd
, event
.getAction(), pos
[0], pos
[1],
654 event
.getButtonState(), getLeft(), getTop() ));
655 return wine_motion_event( window
.hwnd
, event
.getAction(), pos
[0], pos
[1],
656 event
.getButtonState(), (int)event
.getAxisValue(MotionEvent
.AXIS_VSCROLL
) );
658 return super.onGenericMotionEvent(event
);
661 public boolean onTouchEvent( MotionEvent event
)
663 if (is_client
) return false; // let the whole window handle it
664 if (window
.parent
!= null && window
.parent
!= desktop_window
) return false; // let the parent handle it
666 int[] pos
= new int[2];
667 window
.get_event_pos( event
, pos
);
668 Log
.i( LOGTAG
, String
.format( "view touch event win %08x action %d pos %d,%d buttons %04x view %d,%d",
669 window
.hwnd
, event
.getAction(), pos
[0], pos
[1],
670 event
.getButtonState(), getLeft(), getTop() ));
671 return wine_motion_event( window
.hwnd
, event
.getAction(), pos
[0], pos
[1],
672 event
.getButtonState(), 0 );
675 public boolean dispatchKeyEvent( KeyEvent event
)
677 Log
.i( LOGTAG
, String
.format( "view key event win %08x action %d keycode %d (%s)",
678 window
.hwnd
, event
.getAction(), event
.getKeyCode(),
679 event
.keyCodeToString( event
.getKeyCode() )));;
680 boolean ret
= wine_keyboard_event( window
.hwnd
, event
.getAction(), event
.getKeyCode(),
681 event
.getMetaState() );
682 if (!ret
) ret
= super.dispatchKeyEvent(event
);
687 // The top-level desktop view group
689 protected class TopView
extends ViewGroup
691 public TopView( Context context
, int hwnd
)
694 desktop_window
= new WineWindow( hwnd
, null );
695 addView( desktop_window
.create_whole_view() );
696 desktop_window
.client_group
.bringToFront();
698 message_window
= new WineWindow( WineWindow
.HWND_MESSAGE
, null );
699 message_window
.create_window_groups();
703 protected void onSizeChanged( int width
, int height
, int old_width
, int old_height
)
705 Log
.i( LOGTAG
, String
.format( "desktop size %dx%d", width
, height
));
706 wine_desktop_changed( width
, height
);
710 protected void onLayout( boolean changed
, int left
, int top
, int right
, int bottom
)
716 protected WineWindow
get_window( int hwnd
)
718 return win_map
.get( hwnd
);
721 // Entry points for the device driver
723 public void create_desktop_window( int hwnd
)
725 Log
.i( LOGTAG
, String
.format( "create desktop view %08x", hwnd
));
726 setContentView( new TopView( this, hwnd
));
727 progress_dialog
.dismiss();
728 wine_config_changed( getResources().getConfiguration().densityDpi
);
731 public void create_window( int hwnd
, boolean opengl
, int parent
, int pid
)
733 WineWindow win
= get_window( hwnd
);
736 win
= new WineWindow( hwnd
, get_window( parent
));
737 win
.create_window_groups();
738 if (win
.parent
== desktop_window
) win
.create_whole_view();
740 if (opengl
) win
.create_client_view();
743 public void destroy_window( int hwnd
)
745 WineWindow win
= get_window( hwnd
);
746 if (win
!= null) win
.destroy();
749 public void set_window_parent( int hwnd
, int parent
, int pid
)
751 WineWindow win
= get_window( hwnd
);
752 if (win
== null) return;
753 win
.set_parent( get_window( parent
));
754 if (win
.parent
== desktop_window
) win
.create_whole_view();
757 public void window_pos_changed( int hwnd
, int flags
, int insert_after
, int owner
, int style
,
758 Rect window_rect
, Rect client_rect
, Rect visible_rect
)
760 WineWindow win
= get_window( hwnd
);
762 win
.pos_changed( flags
, insert_after
, owner
, style
, window_rect
, client_rect
, visible_rect
);
765 public void createDesktopWindow( final int hwnd
)
767 runOnUiThread( new Runnable() { public void run() { create_desktop_window( hwnd
); }} );
770 public void createWindow( final int hwnd
, final boolean opengl
, final int parent
, final int pid
)
772 runOnUiThread( new Runnable() { public void run() { create_window( hwnd
, opengl
, parent
, pid
); }} );
775 public void destroyWindow( final int hwnd
)
777 runOnUiThread( new Runnable() { public void run() { destroy_window( hwnd
); }} );
780 public void setParent( final int hwnd
, final int parent
, final int pid
)
782 runOnUiThread( new Runnable() { public void run() { set_window_parent( hwnd
, parent
, pid
); }} );
785 public void windowPosChanged( final int hwnd
, final int flags
, final int insert_after
,
786 final int owner
, final int style
,
787 final int window_left
, final int window_top
,
788 final int window_right
, final int window_bottom
,
789 final int client_left
, final int client_top
,
790 final int client_right
, final int client_bottom
,
791 final int visible_left
, final int visible_top
,
792 final int visible_right
, final int visible_bottom
)
794 final Rect window_rect
= new Rect( window_left
, window_top
, window_right
, window_bottom
);
795 final Rect client_rect
= new Rect( client_left
, client_top
, client_right
, client_bottom
);
796 final Rect visible_rect
= new Rect( visible_left
, visible_top
, visible_right
, visible_bottom
);
797 runOnUiThread( new Runnable() {
798 public void run() { window_pos_changed( hwnd
, flags
, insert_after
, owner
, style
,
799 window_rect
, client_rect
, visible_rect
); }} );