package org.gscript; import org.gscript.process.IProcessCallback; import org.gscript.process.IProcessService; import org.gscript.process.ProcessDescriptor; import org.gscript.process.ProcessService; import org.gscript.process.ProcessState; import org.gscript.settings.ShellProfile; import org.gscript.terminal.EmulatorInput; import org.gscript.terminal.EmulatorScreen; import org.gscript.terminal.ScreenBufferParcelable; import org.gscript.terminal.TerminalEvent; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import com.actionbarsherlock.app.SherlockActivity; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; public class EmulatorActivity extends SherlockActivity implements EmulatorScreen.EmulatorScreenListener, EmulatorInput.EmulatorInputListener { static final String LOG_TAG = "EmulatorActivity"; public static final String EXTRA_DESCRIPTOR = "descriptor"; IProcessService mProcessService; ProcessDescriptor mProcessDescriptor; ShellProfile mProfile; boolean mIsBound; Handler mHandler; EmulatorScreen mEmulatorScreen; EmulatorInput mEmulatorInput; MenuItem mMenuKill; MenuItem mMenuAutoscroll; MenuItem mMenuGestureMode; boolean mMenuKillEnabled; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.activity_emulator); Intent intent = this.getIntent(); mProcessDescriptor = intent.getParcelableExtra(EXTRA_DESCRIPTOR); Uri data; if((data = mProcessDescriptor.getIntent().getData()) != null) { setTitle(data.getLastPathSegment()); } mHandler = new Handler(); mEmulatorScreen = (EmulatorScreen) findViewById(R.id.emulatorScreen); mEmulatorScreen.setEmulatorScreenListener(this); mEmulatorInput = (EmulatorInput) findViewById(R.id.emulatorInput); mEmulatorInput.setEmulatorInputListener(this); bindProcessService(); } @Override public void onDestroy() { super.onDestroy(); /* unbind service */ unbindProcessService(); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = this.getSupportMenuInflater(); inflater.inflate(R.menu.emulator, menu); mMenuAutoscroll = menu.findItem(R.id.menu_emulator_autoscroll); mMenuGestureMode = menu.findItem(R.id.menu_emulator_gesture_mode); mMenuKill = menu.findItem(R.id.menu_emulator_kill); mMenuKill.setEnabled(mMenuKillEnabled); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_emulator_kill: if (mIsBound && mProcessService != null) { try { mProcessService.requestKillProcess(mProcessDescriptor); } catch (RemoteException e) { e.printStackTrace(); } } return true; case R.id.menu_emulator_autoscroll: if (mEmulatorScreen != null) mEmulatorScreen.toggleAutoScrollEnabled(); return true; case R.id.menu_emulator_gesture_mode: if(mEmulatorScreen != null) { mEmulatorScreen.setGestureMode(Math.abs(mEmulatorScreen.getGestureMode()-1)); } return true; case R.id.menu_emulator_softinput: if(mEmulatorInput != null) { mEmulatorInput.toggleSoftInput(); } return true; case R.id.menu_emulator_softinput_additional: if(mEmulatorInput != null) { mEmulatorInput.toggleAdditionalSoftInput(); } return true; default: return super.onOptionsItemSelected(item); } } IProcessCallback.Stub mProcessCallback = new IProcessCallback.Stub() { @Override public void OnProcessStateChanged(ProcessDescriptor pd, int state) throws RemoteException { final int currentState = state; mHandler.post(new Runnable() { @Override public void run() { boolean processActive = ProcessState.isActiveState(currentState); mMenuKillEnabled=processActive; if (mMenuKill != null) mMenuKill.setEnabled(mMenuKillEnabled); mEmulatorScreen.setCursorVisible(processActive); } }); mEmulatorScreen.onProcessEvent(TerminalEvent.SCREEN_UPDATE); } @Override public void OnProcessRegistration(ProcessDescriptor pd, String profile, ScreenBufferParcelable screenBuffer) throws RemoteException { mHandler.post(new RegistrationRunnable(profile, screenBuffer)); } @Override public void OnProcessEvent(ProcessDescriptor pd, int event) throws RemoteException { switch (event) { case TerminalEvent.SCREEN_UPDATE: mEmulatorScreen.onProcessEvent(event); break; case TerminalEvent.SCREEN_RESIZE: mEmulatorScreen.onProcessEvent(event); break; } } }; private ServiceConnection mServiceConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { mProcessService = IProcessService.Stub.asInterface(service); try { if (mProcessService != null) mProcessService.registerProcessCallback(mProcessDescriptor, mProcessCallback); } catch (RemoteException e) { e.printStackTrace(); } } public void onServiceDisconnected(ComponentName className) { mProcessService = null; } }; void bindProcessService() { bindService(new Intent(this, ProcessService.class), mServiceConnection, Context.BIND_AUTO_CREATE); mIsBound = true; } void unbindProcessService() { if (mIsBound) { try { if (mProcessService != null) mProcessService.unregisterProcessCallback( mProcessDescriptor, mProcessCallback); } catch (RemoteException e) { e.printStackTrace(); } unbindService(mServiceConnection); mIsBound = false; } } class RegistrationRunnable implements Runnable { String profile; ScreenBufferParcelable screenBuffer; public RegistrationRunnable(String profile, ScreenBufferParcelable screenBuffer) { this.profile = profile; this.screenBuffer = screenBuffer; } @Override public void run() { /* get shell profile */ mProfile = ShellProfile.forKey( EmulatorActivity.this, profile); /* initialize emulator view */ mEmulatorScreen.initialize(mProfile, screenBuffer); } } /* EmulatorView / EmulatorInput */ @Override public void onEmulatorInput(byte[] b, int length) { if (mIsBound && mProcessService != null) { try { mProcessService.dispatchProcessOutput(mProcessDescriptor, b, 0, length); } catch (RemoteException e) { } } } @Override public void onWindowSizeChangeRequested(int rows, int cols, int width, int height) { if (mIsBound && mProcessService != null) { try { mProcessService.requestWindowSizeChange(mProcessDescriptor, rows, cols, width, height); } catch (RemoteException e) { } } } @Override public void onAutoScrollChanged(boolean enabled) { if (mMenuAutoscroll != null) { if (enabled) { mMenuAutoscroll.setIcon(R.drawable.ic_autoscroll_enabled); } else { mMenuAutoscroll.setIcon(R.drawable.ic_autoscroll_disabled); } } } @Override public void onGestureModeChanged(int mode) { if(mMenuGestureMode != null) { switch(mode) { case EmulatorScreen.GESTURE_MODE_SCROLL: mMenuGestureMode.setTitle(R.string.menu_emulator_cursor_mode); break; case EmulatorScreen.GESTURE_MODE_CURSOR: mMenuGestureMode.setTitle(R.string.menu_emulator_scroll_mode); break; } } } }