[Libreoffice-commits] .: 2 commits - android/sdremote

Andrzej J.R. Hunt ajrhunt at kemper.freedesktop.org
Tue Aug 14 09:29:45 PDT 2012


 android/sdremote/AndroidManifest.xml                                                       |   11 
 android/sdremote/res/drawable-hdpi/handle_light.9.png                                      |binary
 android/sdremote/res/drawable-hdpi/handle_vertical_default.9.png                           |binary
 android/sdremote/res/drawable-hdpi/handle_vertical_light.9.png                             |binary
 android/sdremote/res/drawable-land/handle.xml                                              |    9 
 android/sdremote/res/drawable-mdpi/handle_vertical_default.9.png                           |binary
 android/sdremote/res/drawable-mdpi/handle_vertical_light.9.png                             |binary
 android/sdremote/res/drawable-xhdpi/handle_vertical_default.9.png                          |binary
 android/sdremote/res/drawable-xhdpi/handle_vertical_light.9.png                            |binary
 android/sdremote/res/drawable/image_loading.png                                            |binary
 android/sdremote/res/layout-land/fragment_presentation.xml                                 |   54 
 android/sdremote/res/layout/activity_pairing.xml                                           |   17 
 android/sdremote/res/layout/activity_startpresentation.xml                                 |   22 
 android/sdremote/res/values/strings.xml                                                    |    4 
 android/sdremote/src/org/libreoffice/impressremote/PairingActivity.java                    |   52 
 android/sdremote/src/org/libreoffice/impressremote/PresentationActivity.java               |  891 +++++-----
 android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java               |  480 ++---
 android/sdremote/src/org/libreoffice/impressremote/SelectorActivity.java                   |   11 
 android/sdremote/src/org/libreoffice/impressremote/StartPresentationActivity.java          |   91 +
 android/sdremote/src/org/libreoffice/impressremote/ThumbnailFragment.java                  |  393 ++--
 android/sdremote/src/org/libreoffice/impressremote/communication/Client.java               |   13 
 android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java |   33 
 android/sdremote/src/org/libreoffice/impressremote/communication/NetworkClient.java        |   11 
 android/sdremote/src/org/libreoffice/impressremote/communication/Receiver.java             |  181 --
 android/sdremote/src/org/libreoffice/impressremote/communication/ServerFinder.java         |   10 
 android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java            |  307 +--
 android/sdremote/src/org/libreoffice/impressremote/communication/TestClient.java           |  197 --
 27 files changed, 1437 insertions(+), 1350 deletions(-)

New commits:
commit 0357b778956a453a700d7b7002a7850071bde70d
Author: Andrzej J.R. Hunt <andrzej at ahunt.org>
Date:   Tue Aug 14 18:27:53 2012 +0200

    Implemented rotation of slideshow view.
    
    Change-Id: Ib518e1609d21463273a00fcf161f20c80eae6a67

diff --git a/android/sdremote/AndroidManifest.xml b/android/sdremote/AndroidManifest.xml
index 1004193..33d194f 100644
--- a/android/sdremote/AndroidManifest.xml
+++ b/android/sdremote/AndroidManifest.xml
@@ -20,21 +20,14 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
-        <activity
-            android:name=".communication.TestClient"
-            android:label="Remote--Direct" >
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
 
         <service android:name=".communication.CommunicationService" >
         </service>
 
         <activity android:name=".PairingActivity" >
         </activity>
+        <activity android:name=".StartPresentationActivity" >
+        </activity>
         <activity
             android:name=".PresentationActivity"
             android:label="@string/title_activity_presentation" >
diff --git a/android/sdremote/res/drawable/image_loading.png b/android/sdremote/res/drawable/image_loading.png
new file mode 100644
index 0000000..24e8ebd
Binary files /dev/null and b/android/sdremote/res/drawable/image_loading.png differ
diff --git a/android/sdremote/res/layout-land/fragment_presentation.xml b/android/sdremote/res/layout-land/fragment_presentation.xml
index 1cdd4d3..66de905 100644
--- a/android/sdremote/res/layout-land/fragment_presentation.xml
+++ b/android/sdremote/res/layout-land/fragment_presentation.xml
@@ -13,8 +13,8 @@
         <pl.polidea.coverflow.CoverFlow
             xmlns:coverflow="http://schemas.android.com/apk/res/org.libreoffice.impressremote"
             android:id="@+id/presentation_coverflow"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
             android:layout_marginTop="5dip"
             coverflow:imageHeight="150dip"
             coverflow:imageWidth="180dip"
@@ -42,8 +42,8 @@
 
     <ScrollView
         android:id="@+id/presentation_scrollview"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" >
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent" >
 
         <WebView
             android:id="@+id/presentation_notes"
diff --git a/android/sdremote/res/layout/activity_startpresentation.xml b/android/sdremote/res/layout/activity_startpresentation.xml
new file mode 100644
index 0000000..25bf55a
--- /dev/null
+++ b/android/sdremote/res/layout/activity_startpresentation.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <TextView
+        android:id="@+id/startpresentation_instruction"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:layout_margin="5dip"
+        android:text="@string/startpresentation_instruction" />
+
+    <Button
+        android:id="@+id/startpresentation_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:text="@string/startpresentation_button" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/android/sdremote/res/values/strings.xml b/android/sdremote/res/values/strings.xml
index c86d5c9..060652c 100644
--- a/android/sdremote/res/values/strings.xml
+++ b/android/sdremote/res/values/strings.xml
@@ -24,7 +24,9 @@
     <string name="wifi">WI-FI</string>
     <string name="selector_noservers">Searching for computers…</string>
     <string name="pairing_instructions_1">In Impress, click on the "Slideshow" menu and select "Impress Remote".</string>
-    <string name="pairing_instructions_2_deviceName">Choose "{1}" as your device.</string>
+    <string name="pairing_instructions_2_deviceName">Choose \"{0}\" as your device.</string>
     <string name="pairing_instructions_3">Then input this PIN:</string>
+    <string name="startpresentation_instruction">No presentation is currently running.</string>
+    <string name="startpresentation_button">Start Presentation</string>
 
 </resources>
\ No newline at end of file
diff --git a/android/sdremote/src/org/libreoffice/impressremote/PairingActivity.java b/android/sdremote/src/org/libreoffice/impressremote/PairingActivity.java
index 9298e43..414bcd4 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/PairingActivity.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/PairingActivity.java
@@ -39,21 +39,12 @@ public class PairingActivity extends Activity {
                         Context.BIND_IMPORTANT);
         mIsBound = true;
 
-        mPinText = (TextView) findViewById(R.id.pairing_pin);
-
         IntentFilter aFilter = new IntentFilter(
                         CommunicationService.MSG_PAIRING_STARTED);
         aFilter.addAction(CommunicationService.MSG_PAIRING_SUCCESSFUL);
         LocalBroadcastManager.getInstance(this).registerReceiver(mListener,
                         aFilter);
 
-        //        mBluetoothContainer = findViewById(R.id.selector_container_bluetooth);
-        //        mBluetoothList = (LinearLayout) findViewById(R.id.selector_list_bluetooth);
-        //        mNetworkContainer = findViewById(R.id.selector_container_network);
-        //        mNetworkList = (LinearLayout) findViewById(R.id.selector_list_network);
-        //        mNoServerLabel = (TextView) findViewById(R.id.selector_label_none);
-        //
-        //        refreshLists();
     }
 
     private ServiceConnection mConnection = new ServiceConnection() {
@@ -61,7 +52,9 @@ public class PairingActivity extends Activity {
         public void onServiceConnected(ComponentName aClassName,
                         IBinder aService) {
             setContentView(R.layout.activity_pairing);
-
+            mPinText = (TextView) findViewById(R.id.pairing_pin);
+            mCommunicationService = ((CommunicationService.CBinder) aService)
+                            .getService();
             ((TextView) findViewById(R.id.pairing_instruction2_deviceName))
                             .setText(MessageFormat
                                             .format(getResources()
@@ -69,8 +62,6 @@ public class PairingActivity extends Activity {
                                                             mCommunicationService
                                                                             .getDeviceName()));
 
-            mCommunicationService = ((CommunicationService.CBinder) aService)
-                            .getService();
             if (mCommunicationService.getState() == State.CONNECTING) {
                 mPinText.setText(mCommunicationService.getPairingPin());
             }
@@ -94,7 +85,9 @@ public class PairingActivity extends Activity {
                 //                refreshLists();
             } else if (aIntent.getAction().equals(
                             CommunicationService.MSG_PAIRING_SUCCESSFUL)) {
-                mPinText.setText("Paired!");
+                Intent nIntent = new Intent(PairingActivity.this,
+                                StartPresentationActivity.class);
+                startActivity(nIntent);
             }
 
         }
diff --git a/android/sdremote/src/org/libreoffice/impressremote/PresentationActivity.java b/android/sdremote/src/org/libreoffice/impressremote/PresentationActivity.java
index c6b80fe..912059d 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/PresentationActivity.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/PresentationActivity.java
@@ -7,7 +7,6 @@ import java.util.TimeZone;
 import org.libreoffice.impressremote.communication.CommunicationService;
 import org.libreoffice.impressremote.communication.SlideShow.Timer;
 
-import android.annotation.SuppressLint;
 import android.app.ActionBar;
 import android.app.Activity;
 import android.app.FragmentManager;
@@ -20,8 +19,6 @@ import android.content.SharedPreferences;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Message;
-import android.os.Messenger;
 import android.preference.PreferenceManager;
 import android.text.format.DateFormat;
 import android.view.KeyEvent;
@@ -38,446 +35,450 @@ import android.widget.TextView;
 import android.widget.ToggleButton;
 
 public class PresentationActivity extends Activity {
-	private CommunicationService mCommunicationService;
-	private boolean mIsBound = false;
-	private FrameLayout mLayout;
-	private FrameLayout mOuterLayout;
-	private ThumbnailFragment mThumbnailFragment;
-	private PresentationFragment mPresentationFragment;
-	private ActionBarManager mActionBarManager;
-
-	@Override
-	public void onCreate(Bundle savedInstanceState) {
-		super.onCreate(savedInstanceState);
-
-		bindService(new Intent(this, CommunicationService.class), mConnection,
-		                Context.BIND_IMPORTANT);
-		mIsBound = true;
-
-		setContentView(R.layout.activity_presentation);
-		mOuterLayout = (FrameLayout) findViewById(R.id.framelayout);
-		mLayout = new InterceptorLayout(this);
-		mOuterLayout.addView(mLayout);
-		mLayout.setId(R.id.presentation_innerFrame);
-		//		((FrameLayout) findViewById(R.id.framelayout)).addView(mLayout);
-		mThumbnailFragment = new ThumbnailFragment();
-		mPresentationFragment = new PresentationFragment();
-
-		FragmentManager fragmentManager = getFragmentManager();
-		FragmentTransaction fragmentTransaction = fragmentManager
-		                .beginTransaction();
-		fragmentTransaction.add(R.id.presentation_innerFrame,
-		                mPresentationFragment, "fragment_presentation");
-		fragmentTransaction.commit();
-	}
-
-	@Override
-	public boolean dispatchKeyEvent(KeyEvent event) {
-		SharedPreferences aPref = PreferenceManager
-		                .getDefaultSharedPreferences(this);
-		boolean aVolumeSwitching = aPref.getBoolean("option_volumeswitching",
-		                false);
-		boolean aRelevantFragmentVisible = mPresentationFragment.isVisible()
-		                || mThumbnailFragment.isVisible();
-		if (aVolumeSwitching && aRelevantFragmentVisible) {
-
-			int action = event.getAction();
-			int keyCode = event.getKeyCode();
-			switch (keyCode) {
-			case KeyEvent.KEYCODE_VOLUME_UP:
-				if (action == KeyEvent.ACTION_UP) {
-					mCommunicationService.getTransmitter().nextTransition();
-				}
-				return true;
-			case KeyEvent.KEYCODE_VOLUME_DOWN:
-				if (action == KeyEvent.ACTION_DOWN) {
-					mCommunicationService.getTransmitter().previousTransition();
-				}
-				return true;
-			}
-		}
-		return super.dispatchKeyEvent(event);
-	}
-
-	private ServiceConnection mConnection = new ServiceConnection() {
-		@Override
-		public void onServiceConnected(ComponentName aClassName,
-		                IBinder aService) {
-			mCommunicationService = ((CommunicationService.CBinder) aService)
-			                .getService();
-			mCommunicationService.setActivityMessenger(mMessenger);
-
-			mPresentationFragment
-			                .setCommunicationService(mCommunicationService);
-			mThumbnailFragment.setCommunicationService(mCommunicationService);
-
-		}
-
-		@Override
-		public void onServiceDisconnected(ComponentName aClassName) {
-			mCommunicationService = null;
-		}
-	};
-
-	final Messenger mMessenger = new Messenger(new MessageHandler());
-
-	@SuppressLint("HandlerLeak")
-	protected class MessageHandler extends Handler {
-		@Override
-		public void handleMessage(Message aMessage) {
-			mPresentationFragment.handleMessage(aMessage);
-			mThumbnailFragment.handleMessage(aMessage);
-		}
-	}
-
-	// ---------------------------------------------- ACTION BAR ---------------
-	@Override
-	public boolean onCreateOptionsMenu(Menu menu) {
-		getMenuInflater().inflate(R.menu.actionbar_presentation, menu);
-		mActionBarManager = new ActionBarManager();
-		return true;
-	}
-
-	@Override
-	public boolean onOptionsItemSelected(MenuItem item) {
-		Intent aIntent;
-		switch (item.getItemId()) {
-		case R.id.actionbar_presentation_submenu_options:
-
-			aIntent = new Intent(this, SettingsActivity.class);
-			startActivity(aIntent);
-			return true;
-		case R.id.actionbar_presentation_submenu_blank:
-			boolean aRelevantFragmentVisible = mPresentationFragment
-			                .isVisible() || mThumbnailFragment.isVisible();
-			if (aRelevantFragmentVisible) {
-
-				BlankScreenFragment aFragment = new BlankScreenFragment(
-				                mCommunicationService);
-
-				FragmentTransaction ft = getFragmentManager()
-				                .beginTransaction();
-				ft.replace(R.id.presentation_innerFrame, aFragment);
-				ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
-				ft.addToBackStack(null);
-				ft.commit();
-			}
-			return true;
-		default:
-			return super.onOptionsItemSelected(item);
-		}
-	}
-
-	private class ActionBarManager implements OnClickListener,
-	                FragmentManager.OnBackStackChangedListener,
-	                TextView.OnEditorActionListener {
-
-		private ToggleButton mTimeLabel;
-		private ToggleButton mThumbnailButton;
-
-		private View mDropdownOptions;
-		private View mDropdownBlank;
-
-		// ------- CLOCKBAR
-		private View mClockBar;
-		private ToggleButton mClockBar_clockButton;
-		private ToggleButton mClockBar_stopwatchButton;
-		private ToggleButton mClockBar_countdownButton;
-
-		// ------- STOPWATCH BAR
-		private View mStopwatchBar;
-		private Button mStopwatchButtonRun;
-		private Button mStopwatchButtonReset;
-
-		// ------- COUNTDOWN BAR
-		private View mCountdownBar;
-		private EditText mCountdownEntry;
-		private Button mCountdownButton;
-
-		private String aTimeFormat = getResources().getString(
-		                R.string.actionbar_timeformat);
-		private String aTimerFormat = getResources().getString(
-		                R.string.actionbar_timerformat);
-		/*
-		 * True if the timer is being used as a timer, false if we are showing a
-		 * clock.
-		 */
-		private boolean mTimerOn = false;
-
-		public ActionBarManager() {
-
-			ActionBar aBar = getActionBar();
-			aBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
-			aBar.setCustomView(R.layout.presentation_actionbar);
-
-			mThumbnailButton = (ToggleButton) aBar.getCustomView()
-			                .findViewById(R.id.actionbar_thumbnailtoggle);
-			mThumbnailButton.setOnClickListener(this);
-
-			mTimeLabel = (ToggleButton) aBar.getCustomView().findViewById(
-			                R.id.actionbar_time);
-			mTimeLabel.setOnClickListener(this);
-
-			setupClockBar();
-
-			getFragmentManager().addOnBackStackChangedListener(this);
-
-			timerHandler.removeCallbacks(timerUpdateThread);
-			timerHandler.postDelayed(timerUpdateThread, 50);
-
-		}
-
-		public void hidePopups() {
-			if (mClockBar.getVisibility() == View.VISIBLE) {
-				mClockBar.setVisibility(View.INVISIBLE);
-				mStopwatchBar.setVisibility(View.INVISIBLE);
-				mCountdownBar.setVisibility(View.INVISIBLE);
-				mTimeLabel.setChecked(false);
-			}
-		}
-
-		private void setupClockBar() {
-			// ClockBar
-			LayoutInflater aInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-			aInflater.inflate(R.layout.presentation_clockbar, mOuterLayout);
-			mClockBar = mOuterLayout.findViewById(R.id.clockbar);
-
-			mClockBar_clockButton = (ToggleButton) mClockBar
-			                .findViewById(R.id.clockbar_toggle_clockmode);
-			mClockBar_stopwatchButton = (ToggleButton) mClockBar
-			                .findViewById(R.id.clockbar_toggle_stopwatchmode);
-			mClockBar_countdownButton = (ToggleButton) mClockBar
-			                .findViewById(R.id.clockbar_toggle_countdownmode);
-			mClockBar_clockButton.setOnClickListener(this);
-			mClockBar_stopwatchButton.setOnClickListener(this);
-			mClockBar_countdownButton.setOnClickListener(this);
-
-			// Stopwatch bar
-			aInflater.inflate(R.layout.presentation_clockbar_stopwatchbar,
-			                mOuterLayout);
-			mStopwatchBar = mOuterLayout
-			                .findViewById(R.id.clockbar_stopwatchbar);
-
-			mStopwatchButtonRun = (Button) mStopwatchBar
-			                .findViewById(R.id.clockbar_stopwatch_run);
-			mStopwatchButtonReset = (Button) mStopwatchBar
-			                .findViewById(R.id.clockbar_stopwatch_reset);
-			mStopwatchButtonRun.setOnClickListener(this);
-			mStopwatchButtonReset.setOnClickListener(this);
-
-			// Countdown bar
-			aInflater.inflate(R.layout.presentation_clockbar_countdownbar,
-			                mOuterLayout);
-			mCountdownBar = mOuterLayout
-			                .findViewById(R.id.clockbar_countdownbar);
-
-			mCountdownEntry = (EditText) mCountdownBar
-			                .findViewById(R.id.clockbar_countdown_time);
-			mCountdownButton = (Button) mCountdownBar
-			                .findViewById(R.id.clockbar_countdown_button);
-			mCountdownButton.setOnClickListener(this);
-			mCountdownEntry.setOnEditorActionListener(this);
-
-			updateClockBar();
-			hidePopups();
-
-		}
-
-		private void updateClockBar() {
-			mClockBar_clockButton.setChecked(!mTimerOn);
-
-			mCountdownBar.setY(mClockBar.getHeight());
-			mStopwatchBar.setY(mClockBar.getHeight());
-
-			boolean aIsCountdown = mCommunicationService.getSlideShow()
-			                .getTimer().isCountdown();
-			// Stopwatch
-			boolean aStopwatchMode = mTimerOn && !aIsCountdown;
-			mClockBar_stopwatchButton.setChecked(aStopwatchMode);
-			mStopwatchBar.setVisibility(aStopwatchMode ? View.VISIBLE
-			                : View.INVISIBLE);
-			mStopwatchBar.bringToFront();
-			if (aStopwatchMode) {
-				Timer aTimer = mCommunicationService.getSlideShow().getTimer();
-				if (aTimer.isRunning()) {
-					mStopwatchButtonRun.setText(R.string.clock_timer_pause);
-					mStopwatchButtonReset.setText(R.string.clock_timer_restart);
-				} else {
-					mStopwatchButtonRun.setText(R.string.clock_timer_start);
-					mStopwatchButtonReset.setText(R.string.clock_timer_reset);
-				}
-			}
-
-			// Countdown
-			boolean aCountdownMode = mTimerOn && aIsCountdown;
-			mClockBar_countdownButton.setChecked(mTimerOn && aIsCountdown);
-			mCountdownBar.setVisibility(mTimerOn && aIsCountdown ? View.VISIBLE
-			                : View.INVISIBLE);
-			mCountdownBar.bringToFront();
-			if (aCountdownMode) {
-				Timer aTimer = mCommunicationService.getSlideShow().getTimer();
-				if (aTimer.isRunning()) {
-					mCountdownButton.setText(R.string.clock_timer_pause);
-				} else {
-					mCountdownButton.setText(R.string.clock_timer_resume);
-				}
-			}
-
-		}
-
-		private Handler timerHandler = new Handler();
-
-		private Thread timerUpdateThread = new Thread() {
-
-			@Override
-			public void run() {
-				//			invalidateOptionsMenu();
-				CharSequence aTimeString;
-				long aTime = mCommunicationService.getSlideShow().getTimer()
-				                .getTimeMillis();
-				if (mTimerOn) {
-					aTimeString = DateFormat.format(aTimerFormat, aTime);
-				} else {
-					aTimeString = DateFormat.format(aTimeFormat,
-					                System.currentTimeMillis());
-				}
-				mTimeLabel.setText(aTimeString);
-				// TODO: set the string
-				timerHandler.postDelayed(this, 50);
-
-			}
-
-		};
-
-		@Override
-		public void onClick(View aSource) {
-			Timer aTimer = mCommunicationService.getSlideShow().getTimer();
-			// --------------------------------- ACTIONBAR BUTTONS -------------
-			if (aSource == mThumbnailButton) {
-				if (!mThumbnailFragment.isVisible()) {
-					FragmentTransaction ft = getFragmentManager()
-					                .beginTransaction();
-					ft.replace(R.id.presentation_innerFrame, mThumbnailFragment);
-					ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
-					ft.addToBackStack(null);
-					ft.commit();
-				} else {
-					getFragmentManager().popBackStack();
-				}
-			} else if (aSource == mTimeLabel) {
-				if (mClockBar.getVisibility() == View.VISIBLE) {
-					hidePopups();
-				} else {
-					mClockBar.setVisibility(View.VISIBLE);
-					updateClockBar();
-					mClockBar.bringToFront();
-				}
-			}
-			// ------------------------------------ CLOCKBAR BUTTONS -----------
-			else if (aSource == mClockBar_clockButton) {
-				mTimerOn = false;
-				updateClockBar();
-			} else if (aSource == mClockBar_stopwatchButton) {
-				mTimerOn = true;
-				if (aTimer.isCountdown()) { // Changing mode.
-					aTimer.reset();
-				}
-				aTimer.setCountdown(false);
-				updateClockBar();
-			} else if (aSource == mClockBar_countdownButton) {
-				mTimerOn = true;
-				if (!aTimer.isCountdown()) { // Changing mode
-					aTimer.reset();
-				}
-				aTimer.setCountdown(true);
-				updateClockBar();
-			}
-			// ------------------------------------- TIMER BUTTONS
-			else if (aSource == mStopwatchButtonRun) {
-				if (aTimer.isRunning()) {
-					aTimer.stopTimer();
-				} else {
-					aTimer.startTimer();
-				}
-				updateClockBar();
-			} else if (aSource == mStopwatchButtonReset) {
-				if (aTimer.isRunning()) {
-					aTimer.reset();
-					aTimer.startTimer();
-				} else {
-					aTimer.reset();
-				}
-				updateClockBar();
-			} else if (aSource == mCountdownButton) {
-				if (aTimer.isRunning()) {
-					aTimer.stopTimer();
-				} else {
-					aTimer.startTimer();
-				}
-				updateClockBar();
-			}
-
-		}
-
-		@Override
-		public void onBackStackChanged() {
-			if (getFragmentManager().getBackStackEntryCount() == 0) {
-				mThumbnailButton.setChecked(false);
-			}
-		}
-
-		@Override
-		public boolean onEditorAction(TextView tv, int aID, KeyEvent aEvent) {
-			if (aEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
-
-				long aTime = 0;
-				try {
-					SimpleDateFormat aFormat = new SimpleDateFormat("HH:mm:ss");
-					aFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
-					aTime = aFormat.parse(mCountdownEntry.getText().toString())
-					                .getTime();
-				} catch (ParseException e) {
-				}
-				if (aTime == 0) {
-					try {
-						SimpleDateFormat aFormat = new SimpleDateFormat("mm:ss");
-						aFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
-						aTime = aFormat.parse(
-						                mCountdownEntry.getText().toString())
-						                .getTime();
-					} catch (ParseException e) {
-					}
-				}
-				mCommunicationService.getSlideShow().getTimer()
-				                .setCountdownTime(aTime);
-				return true;
-			}
-			return false;
-		}
-	}
-
-	/**
-	 * Intermediate layout that catches all touches, used in order to hide
-	 * the clock menu as appropriate.
-	 * @author andy
-	 *
-	 */
-	private class InterceptorLayout extends FrameLayout {
-
-		public InterceptorLayout(Context context) {
-			super(context);
-		}
-
-		@Override
-		public boolean onInterceptTouchEvent(MotionEvent aEvent) {
-			mActionBarManager.hidePopups();
-			return super.onInterceptTouchEvent(aEvent);
-		}
-
-		@Override
-		public boolean onTouchEvent(MotionEvent aEvent) {
-			return super.onTouchEvent(aEvent);
-		}
-
-	}
+    private CommunicationService mCommunicationService;
+    private boolean mIsBound = false;
+    private FrameLayout mLayout;
+    private FrameLayout mOuterLayout;
+    private ThumbnailFragment mThumbnailFragment;
+    private PresentationFragment mPresentationFragment;
+    private ActionBarManager mActionBarManager;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        bindService(new Intent(this, CommunicationService.class), mConnection,
+                        Context.BIND_IMPORTANT);
+        mIsBound = true;
+
+        setContentView(R.layout.activity_presentation);
+        mOuterLayout = (FrameLayout) findViewById(R.id.framelayout);
+        mOuterLayout.removeAllViews();
+        mLayout = new InterceptorLayout(this);
+        mOuterLayout.addView(mLayout);
+        mLayout.setId(R.id.presentation_innerFrame);
+
+        //((FrameLayout) findViewById(R.id.framelayout)).addView(mLayout);
+        mThumbnailFragment = new ThumbnailFragment();
+        mPresentationFragment = new PresentationFragment();
+
+        FragmentManager fragmentManager = getFragmentManager();
+        FragmentTransaction fragmentTransaction = fragmentManager
+                        .beginTransaction();
+        fragmentTransaction.add(R.id.presentation_innerFrame,
+                        mPresentationFragment, "fragment_presentation");
+        fragmentTransaction.commit();
+
+    }
+
+    @Override
+    protected void onDestroy() {
+        mActionBarManager.stop();
+        super.onDestroy();
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        SharedPreferences aPref = PreferenceManager
+                        .getDefaultSharedPreferences(this);
+        boolean aVolumeSwitching = aPref.getBoolean("option_volumeswitching",
+                        false);
+        boolean aRelevantFragmentVisible = mPresentationFragment.isVisible()
+                        || mThumbnailFragment.isVisible();
+        if (aVolumeSwitching && aRelevantFragmentVisible) {
+
+            int action = event.getAction();
+            int keyCode = event.getKeyCode();
+            switch (keyCode) {
+            case KeyEvent.KEYCODE_VOLUME_UP:
+                if (action == KeyEvent.ACTION_UP) {
+                    mCommunicationService.getTransmitter().nextTransition();
+                }
+                return true;
+            case KeyEvent.KEYCODE_VOLUME_DOWN:
+                if (action == KeyEvent.ACTION_DOWN) {
+                    mCommunicationService.getTransmitter().previousTransition();
+                }
+                return true;
+            }
+        }
+        return super.dispatchKeyEvent(event);
+    }
+
+    private ServiceConnection mConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName aClassName,
+                        IBinder aService) {
+            mCommunicationService = ((CommunicationService.CBinder) aService)
+                            .getService();
+
+            mPresentationFragment
+                            .setCommunicationService(mCommunicationService);
+            mThumbnailFragment.setCommunicationService(mCommunicationService);
+
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName aClassName) {
+            mCommunicationService = null;
+        }
+    };
+
+    // ---------------------------------------------- ACTION BAR ---------------
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.actionbar_presentation, menu);
+        mActionBarManager = new ActionBarManager();
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        Intent aIntent;
+        switch (item.getItemId()) {
+        case R.id.actionbar_presentation_submenu_options:
+
+            aIntent = new Intent(this, SettingsActivity.class);
+            startActivity(aIntent);
+            return true;
+        case R.id.actionbar_presentation_submenu_blank:
+            boolean aRelevantFragmentVisible = mPresentationFragment
+                            .isVisible() || mThumbnailFragment.isVisible();
+            if (aRelevantFragmentVisible) {
+
+                BlankScreenFragment aFragment = new BlankScreenFragment(
+                                mCommunicationService);
+
+                FragmentTransaction ft = getFragmentManager()
+                                .beginTransaction();
+                ft.replace(R.id.presentation_innerFrame, aFragment);
+                ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
+                ft.addToBackStack(null);
+                ft.commit();
+            }
+            return true;
+        default:
+            return super.onOptionsItemSelected(item);
+        }
+    }
+
+    private class ActionBarManager implements OnClickListener,
+                    FragmentManager.OnBackStackChangedListener,
+                    TextView.OnEditorActionListener {
+
+        private Handler timerHandler = new Handler();
+
+        private ToggleButton mTimeLabel;
+        private ToggleButton mThumbnailButton;
+
+        private View mDropdownOptions;
+        private View mDropdownBlank;
+
+        // ------- CLOCKBAR
+        private View mClockBar;
+        private ToggleButton mClockBar_clockButton;
+        private ToggleButton mClockBar_stopwatchButton;
+        private ToggleButton mClockBar_countdownButton;
+
+        // ------- STOPWATCH BAR
+        private View mStopwatchBar;
+        private Button mStopwatchButtonRun;
+        private Button mStopwatchButtonReset;
+
+        // ------- COUNTDOWN BAR
+        private View mCountdownBar;
+        private EditText mCountdownEntry;
+        private Button mCountdownButton;
+
+        private String aTimeFormat = getResources().getString(
+                        R.string.actionbar_timeformat);
+        private String aTimerFormat = getResources().getString(
+                        R.string.actionbar_timerformat);
+        /*
+         * True if the timer is being used as a timer, false if we are showing a
+         * clock.
+         */
+        private boolean mTimerOn = false;
+
+        public void stop() {
+            timerHandler.removeCallbacks(timerUpdateThread);
+        }
+
+        public ActionBarManager() {
+
+            ActionBar aBar = getActionBar();
+            aBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
+            aBar.setCustomView(R.layout.presentation_actionbar);
+
+            mThumbnailButton = (ToggleButton) aBar.getCustomView()
+                            .findViewById(R.id.actionbar_thumbnailtoggle);
+            mThumbnailButton.setOnClickListener(this);
+
+            mTimeLabel = (ToggleButton) aBar.getCustomView().findViewById(
+                            R.id.actionbar_time);
+            mTimeLabel.setOnClickListener(this);
+
+            setupClockBar();
+
+            getFragmentManager().addOnBackStackChangedListener(this);
+
+            timerHandler.removeCallbacks(timerUpdateThread);
+            timerHandler.postDelayed(timerUpdateThread, 50);
+
+        }
+
+        public void hidePopups() {
+            if (mClockBar.getVisibility() == View.VISIBLE) {
+                mClockBar.setVisibility(View.INVISIBLE);
+                mStopwatchBar.setVisibility(View.INVISIBLE);
+                mCountdownBar.setVisibility(View.INVISIBLE);
+                mTimeLabel.setChecked(false);
+            }
+        }
+
+        private void setupClockBar() {
+            // ClockBar
+            LayoutInflater aInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            aInflater.inflate(R.layout.presentation_clockbar, mOuterLayout);
+            mClockBar = mOuterLayout.findViewById(R.id.clockbar);
+
+            mClockBar_clockButton = (ToggleButton) mClockBar
+                            .findViewById(R.id.clockbar_toggle_clockmode);
+            mClockBar_stopwatchButton = (ToggleButton) mClockBar
+                            .findViewById(R.id.clockbar_toggle_stopwatchmode);
+            mClockBar_countdownButton = (ToggleButton) mClockBar
+                            .findViewById(R.id.clockbar_toggle_countdownmode);
+            mClockBar_clockButton.setOnClickListener(this);
+            mClockBar_stopwatchButton.setOnClickListener(this);
+            mClockBar_countdownButton.setOnClickListener(this);
+
+            // Stopwatch bar
+            aInflater.inflate(R.layout.presentation_clockbar_stopwatchbar,
+                            mOuterLayout);
+            mStopwatchBar = mOuterLayout
+                            .findViewById(R.id.clockbar_stopwatchbar);
+
+            mStopwatchButtonRun = (Button) mStopwatchBar
+                            .findViewById(R.id.clockbar_stopwatch_run);
+            mStopwatchButtonReset = (Button) mStopwatchBar
+                            .findViewById(R.id.clockbar_stopwatch_reset);
+            mStopwatchButtonRun.setOnClickListener(this);
+            mStopwatchButtonReset.setOnClickListener(this);
+
+            // Countdown bar
+            aInflater.inflate(R.layout.presentation_clockbar_countdownbar,
+                            mOuterLayout);
+            mCountdownBar = mOuterLayout
+                            .findViewById(R.id.clockbar_countdownbar);
+
+            mCountdownEntry = (EditText) mCountdownBar
+                            .findViewById(R.id.clockbar_countdown_time);
+            mCountdownButton = (Button) mCountdownBar
+                            .findViewById(R.id.clockbar_countdown_button);
+            mCountdownButton.setOnClickListener(this);
+            mCountdownEntry.setOnEditorActionListener(this);
+
+            updateClockBar();
+            hidePopups();
+
+        }
+
+        private void updateClockBar() {
+            if (mCommunicationService == null) {
+                return;
+            }
+            mClockBar_clockButton.setChecked(!mTimerOn);
+
+            mCountdownBar.setY(mClockBar.getHeight());
+            mStopwatchBar.setY(mClockBar.getHeight());
+
+            boolean aIsCountdown = mCommunicationService.getSlideShow()
+                            .getTimer().isCountdown();
+            // Stopwatch
+            boolean aStopwatchMode = mTimerOn && !aIsCountdown;
+            mClockBar_stopwatchButton.setChecked(aStopwatchMode);
+            mStopwatchBar.setVisibility(aStopwatchMode ? View.VISIBLE
+                            : View.INVISIBLE);
+            mStopwatchBar.bringToFront();
+            if (aStopwatchMode) {
+                Timer aTimer = mCommunicationService.getSlideShow().getTimer();
+                if (aTimer.isRunning()) {
+                    mStopwatchButtonRun.setText(R.string.clock_timer_pause);
+                    mStopwatchButtonReset.setText(R.string.clock_timer_restart);
+                } else {
+                    mStopwatchButtonRun.setText(R.string.clock_timer_start);
+                    mStopwatchButtonReset.setText(R.string.clock_timer_reset);
+                }
+            }
+
+            // Countdown
+            boolean aCountdownMode = mTimerOn && aIsCountdown;
+            mClockBar_countdownButton.setChecked(mTimerOn && aIsCountdown);
+            mCountdownBar.setVisibility(mTimerOn && aIsCountdown ? View.VISIBLE
+                            : View.INVISIBLE);
+            mCountdownBar.bringToFront();
+            if (aCountdownMode) {
+                Timer aTimer = mCommunicationService.getSlideShow().getTimer();
+                if (aTimer.isRunning()) {
+                    mCountdownButton.setText(R.string.clock_timer_pause);
+                } else {
+                    mCountdownButton.setText(R.string.clock_timer_resume);
+                }
+            }
+
+        }
+
+        private Thread timerUpdateThread = new Thread() {
+
+            @Override
+            public void run() {
+                //invalidateOptionsMenu();
+                CharSequence aTimeString;
+                long aTime = mCommunicationService.getSlideShow().getTimer()
+                                .getTimeMillis();
+                if (mTimerOn) {
+                    aTimeString = DateFormat.format(aTimerFormat, aTime);
+                } else {
+                    aTimeString = DateFormat.format(aTimeFormat,
+                                    System.currentTimeMillis());
+                }
+                mTimeLabel.setText(aTimeString);
+                // TODO: set the string
+                timerHandler.postDelayed(this, 50);
+
+            }
+
+        };
+
+        @Override
+        public void onClick(View aSource) {
+            Timer aTimer = mCommunicationService.getSlideShow().getTimer();
+            // --------------------------------- ACTIONBAR BUTTONS -------------
+            if (aSource == mThumbnailButton) {
+                if (!mThumbnailFragment.isVisible()) {
+                    FragmentTransaction ft = getFragmentManager()
+                                    .beginTransaction();
+                    ft.replace(R.id.presentation_innerFrame, mThumbnailFragment);
+                    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
+                    ft.addToBackStack(null);
+                    ft.commit();
+                } else {
+                    getFragmentManager().popBackStack();
+                }
+            } else if (aSource == mTimeLabel) {
+                if (mClockBar.getVisibility() == View.VISIBLE) {
+                    hidePopups();
+                } else {
+                    mClockBar.setVisibility(View.VISIBLE);
+                    updateClockBar();
+                    mClockBar.bringToFront();
+                }
+            }
+            // ------------------------------------ CLOCKBAR BUTTONS -----------
+            else if (aSource == mClockBar_clockButton) {
+                mTimerOn = false;
+                updateClockBar();
+            } else if (aSource == mClockBar_stopwatchButton) {
+                mTimerOn = true;
+                if (aTimer.isCountdown()) { // Changing mode.
+                    aTimer.reset();
+                }
+                aTimer.setCountdown(false);
+                updateClockBar();
+            } else if (aSource == mClockBar_countdownButton) {
+                mTimerOn = true;
+                if (!aTimer.isCountdown()) { // Changing mode
+                    aTimer.reset();
+                }
+                aTimer.setCountdown(true);
+                updateClockBar();
+            }
+            // ------------------------------------- TIMER BUTTONS
+            else if (aSource == mStopwatchButtonRun) {
+                if (aTimer.isRunning()) {
+                    aTimer.stopTimer();
+                } else {
+                    aTimer.startTimer();
+                }
+                updateClockBar();
+            } else if (aSource == mStopwatchButtonReset) {
+                if (aTimer.isRunning()) {
+                    aTimer.reset();
+                    aTimer.startTimer();
+                } else {
+                    aTimer.reset();
+                }
+                updateClockBar();
+            } else if (aSource == mCountdownButton) {
+                if (aTimer.isRunning()) {
+                    aTimer.stopTimer();
+                } else {
+                    aTimer.startTimer();
+                }
+                updateClockBar();
+            }
+
+        }
+
+        @Override
+        public void onBackStackChanged() {
+            if (getFragmentManager().getBackStackEntryCount() == 0) {
+                mThumbnailButton.setChecked(false);
+            }
+        }
+
+        @Override
+        public boolean onEditorAction(TextView tv, int aID, KeyEvent aEvent) {
+            if (aEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
+
+                long aTime = 0;
+                try {
+                    SimpleDateFormat aFormat = new SimpleDateFormat("HH:mm:ss");
+                    aFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+                    aTime = aFormat.parse(mCountdownEntry.getText().toString())
+                                    .getTime();
+                } catch (ParseException e) {
+                }
+                if (aTime == 0) {
+                    try {
+                        SimpleDateFormat aFormat = new SimpleDateFormat("mm:ss");
+                        aFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+                        aTime = aFormat.parse(
+                                        mCountdownEntry.getText().toString())
+                                        .getTime();
+                    } catch (ParseException e) {
+                    }
+                }
+                mCommunicationService.getSlideShow().getTimer()
+                                .setCountdownTime(aTime);
+                return true;
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Intermediate layout that catches all touches, used in order to hide
+     * the clock menu as appropriate.
+     * @author andy
+     *
+     */
+    private class InterceptorLayout extends FrameLayout {
+
+        public InterceptorLayout(Context context) {
+            super(context);
+        }
+
+        @Override
+        public boolean onInterceptTouchEvent(MotionEvent aEvent) {
+            mActionBarManager.hidePopups();
+            return super.onInterceptTouchEvent(aEvent);
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent aEvent) {
+            return super.onTouchEvent(aEvent);
+        }
+
+    }
 }
diff --git a/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java b/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java
index 9f8d49a..1f9d3dd 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/PresentationFragment.java
@@ -6,7 +6,10 @@ import org.libreoffice.impressremote.communication.SlideShow;
 import pl.polidea.coverflow.AbstractCoverFlowImageAdapter;
 import pl.polidea.coverflow.CoverFlow;
 import android.app.Fragment;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -14,7 +17,7 @@ import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.RectF;
 import android.os.Bundle;
-import android.os.Message;
+import android.support.v4.content.LocalBroadcastManager;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -47,8 +50,8 @@ public class PresentationFragment extends Fragment {
 
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                     Bundle savedInstanceState) {
-        mContext = container.getContext();
-
+        mContext = getActivity().getApplicationContext();
+        container.removeAllViews();
         View v = inflater.inflate(R.layout.fragment_presentation, container,
                         false);
 
@@ -85,9 +88,26 @@ public class PresentationFragment extends Fragment {
             // We need to update the view now
             aAdapter.notifyDataSetChanged();
         }
+
+        IntentFilter aFilter = new IntentFilter(
+                        CommunicationService.MSG_SLIDE_CHANGED);
+        aFilter.addAction(CommunicationService.MSG_SLIDE_NOTES);
+        aFilter.addAction(CommunicationService.MSG_SLIDE_PREVIEW);
+        LocalBroadcastManager
+                        .getInstance(getActivity().getApplicationContext())
+                        .registerReceiver(mListener, aFilter);
         return v;
     }
 
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        LocalBroadcastManager
+                        .getInstance(getActivity().getApplicationContext())
+                        .unregisterReceiver(mListener);
+
+    }
+
     private void updateSlideNumberDisplay() {
         int aSlide = mSlideShow.getCurrentSlide();
         mNumberText.setText((aSlide + 1) + "/" + mSlideShow.getSize());
@@ -204,23 +224,28 @@ public class PresentationFragment extends Fragment {
         updateSlideNumberDisplay();
     }
 
-    public void handleMessage(Message aMessage) {
-        Bundle aData = aMessage.getData();
-        switch (aMessage.what) {
-        case CommunicationService.MSG_SLIDE_CHANGED:
-            int aSlide = aData.getInt("slide_number");
-            mTopView.setSelection(aSlide, true);
-            updateSlideNumberDisplay();
-            break;
-        case CommunicationService.MSG_SLIDE_PREVIEW:
-            int aNSlide = aData.getInt("slide_number");
-            if (mTopView.getSelectedItemPosition() == aNSlide) {
-                // mTopView. // TODO: update the current item
+    private BroadcastReceiver mListener = new BroadcastReceiver() {
+
+        @Override
+        public void onReceive(Context aContext, Intent aIntent) {
+            if (aIntent.getAction().equals(
+                            CommunicationService.MSG_SLIDE_CHANGED)) {
+                int aSlide = aIntent.getExtras().getInt("slide_number");
+                mTopView.setSelection(aSlide, true);
+                updateSlideNumberDisplay();
+            } else if (aIntent.getAction().equals(
+                            CommunicationService.MSG_SLIDE_PREVIEW)) {
+                int aNSlide = aIntent.getExtras().getInt("slide_number");
+                if (mTopView.getSelectedItemPosition() == aNSlide) {
+                    mTopView.setSelection(aNSlide);
+                }
+            } else if (aIntent.getAction().equals(
+                            CommunicationService.MSG_SLIDE_NOTES)) {
+                // TODO: update me
             }
-            break;
 
         }
-    }
+    };
 
     // ------------------------------------------------- THUMBNAIL ADAPTER ----
     protected class ThumbnailAdapter extends AbstractCoverFlowImageAdapter {
diff --git a/android/sdremote/src/org/libreoffice/impressremote/SelectorActivity.java b/android/sdremote/src/org/libreoffice/impressremote/SelectorActivity.java
index a07896f..f6641ed 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/SelectorActivity.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/SelectorActivity.java
@@ -62,6 +62,12 @@ public class SelectorActivity extends Activity {
     }
 
     @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        LocalBroadcastManager.getInstance(this).unregisterReceiver(mListener);
+    }
+
+    @Override
     public void onBackPressed() {
         mCommunicationService.stopFindingServers();
         Intent aIntent = new Intent(this, CommunicationService.class);
diff --git a/android/sdremote/src/org/libreoffice/impressremote/StartPresentationActivity.java b/android/sdremote/src/org/libreoffice/impressremote/StartPresentationActivity.java
new file mode 100644
index 0000000..6868d93
--- /dev/null
+++ b/android/sdremote/src/org/libreoffice/impressremote/StartPresentationActivity.java
@@ -0,0 +1,91 @@
+package org.libreoffice.impressremote;
+
+import org.libreoffice.impressremote.communication.CommunicationService;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.support.v4.content.LocalBroadcastManager;
+import android.view.View;
+import android.view.View.OnClickListener;
+
+public class StartPresentationActivity extends Activity {
+    private CommunicationService mCommunicationService = null;
+    private boolean mIsBound = false;
+
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_startpresentation);
+        bindService(new Intent(this, CommunicationService.class), mConnection,
+                        Context.BIND_IMPORTANT);
+        mIsBound = true;
+
+        IntentFilter aFilter = new IntentFilter(
+                        CommunicationService.MSG_SLIDESHOW_STARTED);
+        LocalBroadcastManager.getInstance(this).registerReceiver(mListener,
+                        aFilter);
+
+        findViewById(R.id.startpresentation_button).setOnClickListener(
+                        mClickListener);
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        LocalBroadcastManager.getInstance(this).unregisterReceiver(mListener);
+    }
+
+    private ServiceConnection mConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName aClassName,
+                        IBinder aService) {
+
+            mCommunicationService = ((CommunicationService.CBinder) aService)
+                            .getService();
+
+            if (mCommunicationService.isSlideShowRunning()) {
+                Intent nIntent = new Intent(StartPresentationActivity.this,
+                                PresentationActivity.class);
+                startActivity(nIntent);
+            }
+
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName aClassName) {
+            mCommunicationService = null;
+        }
+    };
+
+    private OnClickListener mClickListener = new OnClickListener() {
+
+        @Override
+        public void onClick(View v) {
+            if (mCommunicationService != null) {
+                mCommunicationService.getTransmitter().startPresentation();
+            }
+        }
+    };
+
+    private BroadcastReceiver mListener = new BroadcastReceiver() {
+
+        @Override
+        public void onReceive(Context aContext, Intent aIntent) {
+            if (aIntent.getAction().equals(
+                            CommunicationService.MSG_SLIDESHOW_STARTED)) {
+                Intent nIntent = new Intent(StartPresentationActivity.this,
+                                PresentationActivity.class);
+                startActivity(nIntent);
+            }
+
+        }
+    };
+}
diff --git a/android/sdremote/src/org/libreoffice/impressremote/ThumbnailFragment.java b/android/sdremote/src/org/libreoffice/impressremote/ThumbnailFragment.java
index 1de6c01..4dbcaff 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/ThumbnailFragment.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/ThumbnailFragment.java
@@ -12,11 +12,14 @@ import org.libreoffice.impressremote.communication.CommunicationService;
 import org.libreoffice.impressremote.communication.SlideShow;
 
 import android.app.Fragment;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.graphics.Bitmap;
 import android.graphics.Typeface;
 import android.os.Bundle;
-import android.os.Message;
+import android.support.v4.content.LocalBroadcastManager;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -29,194 +32,204 @@ import android.widget.TextView;
 
 public class ThumbnailFragment extends Fragment {
 
-	private CommunicationService mCommunicationService;
-
-	private GridView mGrid;
-	private ImageView mCurrentImage;
-	private TextView mCurrentText;
-
-	private SlideShow mSlideShow;
-	private Context mContext;
-
-	@Override
-	public View onCreateView(LayoutInflater inflater, ViewGroup container,
-	                Bundle savedInstanceState) {
-		// Inflate the layout for this fragment
-		View v = inflater
-		                .inflate(R.layout.fragment_thumbnail, container, false);
-
-		mGrid = (GridView) v.findViewById(R.id.thumbnail_grid);
-
-		mGrid.setOnItemClickListener(new ClickListener());
-		mContext = container.getContext();
-
-		if (mCommunicationService != null && mSlideShow != null) {
-			mGrid.setAdapter(new ThumbnailAdapter(mContext, mSlideShow));
-		}
-
-		return v;
-	}
-
-	@Override
-	public void onDestroyView() {
-		super.onDestroyView();
-		mGrid = null;
-		mContext = null;
-		mCurrentImage = null;
-		mCurrentText = null;
-	}
-
-	@Override
-	public void onCreate(Bundle savedInstanceState) {
-		super.onCreate(savedInstanceState);
-
-	}
-
-	@Override
-	public void onPause() {
-		super.onPause();
-	}
-
-	private void setSelected(int position) {
-		formatUnselected(mCurrentImage, mCurrentText);
-
-		if (mGrid == null) {
-			return;
-		}
-
-		View aV = mGrid.getChildAt(position);
-		if (aV != null) {
-			mCurrentImage = (ImageView) aV.findViewById(R.id.sub_thumbnail);
-			mCurrentText = (TextView) aV.findViewById(R.id.sub_number);
-
-			formatSelected(mCurrentImage, mCurrentText);
-		}
-	}
-
-	private void formatUnselected(ImageView aImage, TextView aText) {
-		if (aImage != null) {
-			aImage.setBackgroundColor(getResources().getColor(
-			                R.color.thumbnail_border));
-		}
-		if (aText != null) {
-			aText.setTypeface(Typeface.create(aText.getTypeface(),
-			                Typeface.NORMAL));
-		}
-	}
-
-	private void formatSelected(ImageView aImage, TextView aText) {
-		if (aImage != null) {
-			aImage.setBackgroundColor(getResources().getColor(
-			                R.color.thumbnail_border_selected));
-		}
-		if (aText != null) {
-			aText.setTypeface(Typeface.create(aText.getTypeface(),
-			                Typeface.BOLD));
-		}
-	}
-
-	// ----------------------------------------------------- CLICK LISTENER ----
-	protected class ClickListener implements AdapterView.OnItemClickListener {
-		public void onItemClick(AdapterView<?> parent, View v, int position,
-		                long id) {
-			if (mCommunicationService != null)
-				mCommunicationService.getTransmitter().gotoSlide(position);
-		}
-	}
-
-	// ---------------------------------------------------- MESSAGE HANDLER ----
-
-	public void setCommunicationService(
-	                CommunicationService aCommunicationService) {
-		mCommunicationService = aCommunicationService;
-		mSlideShow = mCommunicationService.getSlideShow();
-		if (mGrid != null) {
-			mGrid.setAdapter(new ThumbnailAdapter(mContext, mSlideShow));
-		}
-	}
-
-	public void handleMessage(Message aMessage) {
-		if (!isVisible()) {
-			return;
-		}
-
-		Bundle aData = aMessage.getData();
-		switch (aMessage.what) {
-		case CommunicationService.MSG_SLIDE_CHANGED:
-			int aSlide = aData.getInt("slide_number");
-			break;
-		case CommunicationService.MSG_SLIDE_PREVIEW:
-			mGrid.invalidateViews();
-			break;
-
-		}
-	}
-
-	// ------------------------------------------------- THUMBNAIL ADAPTER ----
-	protected class ThumbnailAdapter extends BaseAdapter {
-
-		private Context mContext;
-
-		private SlideShow mSlideShow;
-
-		public ThumbnailAdapter(Context aContext, SlideShow aSlideShow) {
-			mContext = aContext;
-			mSlideShow = aSlideShow;
-		}
-
-		@Override
-		public int getCount() {
-			return mSlideShow.getSize();
-		}
-
-		@Override
-		public Object getItem(int arg0) {
-			return null;
-		}
-
-		@Override
-		public long getItemId(int position) {
-			return 0;
-		}
-
-		@Override
-		public View getView(int position, View convertView, ViewGroup parent) {
-			LayoutInflater aInflater = (LayoutInflater) mContext
-			                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-			View v = aInflater.inflate(R.layout.slide_thumbnail, null);
-
-			ImageView aImage = (ImageView) v.findViewById(R.id.sub_thumbnail);
-			TextView aText = (TextView) v.findViewById(R.id.sub_number);
-
-			// Do the image & number styling
-			int aBorderWidth = getResources().getInteger(
-			                R.integer.thumbnail_border_width);
-			aImage.setPadding(aBorderWidth, aBorderWidth, aBorderWidth,
-			                aBorderWidth);
-
-			if ((mSlideShow != null)
-			                && (position == mSlideShow.getCurrentSlide())) {
-				formatSelected(aImage, aText);
-				mCurrentImage = aImage;
-				mCurrentText = aText;
-			} else {
-				formatUnselected(aImage, aText);
-			}
-
-			Bitmap aBitmap = mSlideShow.getImage(position);
-			// Width
-			int aWidth = (mGrid.getWidth()) / 3 - 20;
-			aImage.setMaxWidth(aWidth);
-			aImage.setScaleType(ScaleType.FIT_CENTER);
-
-			if (aBitmap != null) {
-				aImage.setImageBitmap(aBitmap);
-			}
-
-			aText.setText(String.valueOf(position + 1));
-
-			return v;
-		}
-	}
+    private CommunicationService mCommunicationService;
+
+    private GridView mGrid;
+    private ImageView mCurrentImage;
+    private TextView mCurrentText;
+
+    private SlideShow mSlideShow;
+    private Context mContext;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                    Bundle savedInstanceState) {
+        // Inflate the layout for this fragment
+        container.removeAllViews();
+        View v = inflater
+                        .inflate(R.layout.fragment_thumbnail, container, false);
+
+        mGrid = (GridView) v.findViewById(R.id.thumbnail_grid);
+
+        mGrid.setOnItemClickListener(new ClickListener());
+        mContext = getActivity().getApplicationContext();
+
+        if (mCommunicationService != null && mSlideShow != null) {
+            mGrid.setAdapter(new ThumbnailAdapter(mContext, mSlideShow));
+        }
+
+        IntentFilter aFilter = new IntentFilter(
+                        CommunicationService.MSG_SLIDE_CHANGED);
+        aFilter.addAction(CommunicationService.MSG_SLIDE_PREVIEW);
+        LocalBroadcastManager
+                        .getInstance(getActivity().getApplicationContext())
+                        .registerReceiver(mListener, aFilter);
+
+        return v;
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        LocalBroadcastManager
+                        .getInstance(getActivity().getApplicationContext())
+                        .unregisterReceiver(mListener);
+        mGrid = null;
+        mContext = null;
+        mCurrentImage = null;
+        mCurrentText = null;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+    }
+
+    private void setSelected(int position) {
+        formatUnselected(mCurrentImage, mCurrentText);
+
+        if (mGrid == null) {
+            return;
+        }
+
+        View aV = mGrid.getChildAt(position);
+        if (aV != null) {
+            mCurrentImage = (ImageView) aV.findViewById(R.id.sub_thumbnail);
+            mCurrentText = (TextView) aV.findViewById(R.id.sub_number);
+
+            formatSelected(mCurrentImage, mCurrentText);
+        }
+    }
+
+    private void formatUnselected(ImageView aImage, TextView aText) {
+        if (aImage != null) {
+            aImage.setBackgroundColor(getResources().getColor(
+                            R.color.thumbnail_border));
+        }
+        if (aText != null) {
+            aText.setTypeface(Typeface.create(aText.getTypeface(),
+                            Typeface.NORMAL));
+        }
+    }
+
+    private void formatSelected(ImageView aImage, TextView aText) {
+        if (aImage != null) {
+            aImage.setBackgroundColor(getResources().getColor(
+                            R.color.thumbnail_border_selected));
+        }
+        if (aText != null) {
+            aText.setTypeface(Typeface.create(aText.getTypeface(),
+                            Typeface.BOLD));
+        }
+    }
+
+    // ----------------------------------------------------- CLICK LISTENER ----
+    protected class ClickListener implements AdapterView.OnItemClickListener {
+        public void onItemClick(AdapterView<?> parent, View v, int position,
+                        long id) {
+            if (mCommunicationService != null)
+                mCommunicationService.getTransmitter().gotoSlide(position);
+        }
+    }
+
+    // ---------------------------------------------------- MESSAGE HANDLER ----
+
+    public void setCommunicationService(
+                    CommunicationService aCommunicationService) {
+        mCommunicationService = aCommunicationService;
+        mSlideShow = mCommunicationService.getSlideShow();
+        if (mGrid != null) {
+            mGrid.setAdapter(new ThumbnailAdapter(mContext, mSlideShow));
+        }
+    }
+
+    private BroadcastReceiver mListener = new BroadcastReceiver() {
+
+        @Override
+        public void onReceive(Context aContext, Intent aIntent) {
+            if (aIntent.getAction().equals(
+                            CommunicationService.MSG_SLIDE_CHANGED)) {
+                int aSlide = aIntent.getExtras().getInt("slide_number");
+                setSelected(aSlide);
+            } else if (aIntent.getAction().equals(
+                            CommunicationService.MSG_SLIDE_PREVIEW)) {
+                mGrid.invalidateViews();
+            }
+
+        }
+    };
+
+    // ------------------------------------------------- THUMBNAIL ADAPTER ----
+    protected class ThumbnailAdapter extends BaseAdapter {
+
+        private Context mContext;
+
+        private SlideShow mSlideShow;
+
+        public ThumbnailAdapter(Context aContext, SlideShow aSlideShow) {
+            mContext = aContext;
+            mSlideShow = aSlideShow;
+        }
+
+        @Override
+        public int getCount() {
+            return mSlideShow.getSize();
+        }
+
+        @Override
+        public Object getItem(int arg0) {
+            return null;
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return 0;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            LayoutInflater aInflater = (LayoutInflater) mContext
+                            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            View v = aInflater.inflate(R.layout.slide_thumbnail, null);
+
+            ImageView aImage = (ImageView) v.findViewById(R.id.sub_thumbnail);
+            TextView aText = (TextView) v.findViewById(R.id.sub_number);
+
+            // Do the image & number styling
+            int aBorderWidth = getResources().getInteger(
+                            R.integer.thumbnail_border_width);
+            aImage.setPadding(aBorderWidth, aBorderWidth, aBorderWidth,
+                            aBorderWidth);
+
+            if ((mSlideShow != null)
+                            && (position == mSlideShow.getCurrentSlide())) {
+                formatSelected(aImage, aText);
+                mCurrentImage = aImage;
+                mCurrentText = aText;
+            } else {
+                formatUnselected(aImage, aText);
+            }
+
+            Bitmap aBitmap = mSlideShow.getImage(position);
+            // Width
+            int aWidth = (mGrid.getWidth()) / 3 - 20;
+            aImage.setMaxWidth(aWidth);
+            aImage.setScaleType(ScaleType.FIT_CENTER);
+
+            if (aBitmap != null) {
+                aImage.setImageBitmap(aBitmap);
+            }
+
+            aText.setText(String.valueOf(position + 1));
+
+            return v;
+        }
+    }
 }
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/Client.java b/android/sdremote/src/org/libreoffice/impressremote/communication/Client.java
index 044d38a..81c8893 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/communication/Client.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/communication/Client.java
@@ -34,6 +34,8 @@ public abstract class Client {
     protected OutputStream mOutputStream;
     protected String mPin = "";
 
+    private static Client latestInstance = null;
+
     public abstract void closeConnection();
 
     private Receiver mReceiver;
@@ -42,6 +44,7 @@ public abstract class Client {
 
     public Client(Context aContext) {
         mContext = aContext;
+        latestInstance = this;
     }
 
     public void setReceiver(Receiver aReceiver) {
@@ -77,11 +80,16 @@ public abstract class Client {
             // TODO stream couldn't be opened.
             e1.printStackTrace();
         }
+        latestInstance = null;
 
     }
 
-    public String getPin() {
-        return mPin;
+    public static String getPin() {
+        if (latestInstance != null) {
+            return latestInstance.mPin;
+        } else {
+            return "";
+        }
     }
 
     /**
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java b/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
index 7563494..677028c 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java
@@ -12,7 +12,6 @@ import android.app.Service;
 import android.content.Intent;
 import android.os.Binder;
 import android.os.IBinder;
-import android.os.Messenger;
 
 public class CommunicationService extends Service implements Runnable {
 
@@ -32,10 +31,7 @@ public class CommunicationService extends Service implements Runnable {
     }
 
     public String getPairingPin() {
-        if (mClient != null)
-            return mClient.getPin();
-        else
-            return "";
+        return Client.getPin();
     }
 
     public String getDeviceName() {
@@ -67,6 +63,7 @@ public class CommunicationService extends Service implements Runnable {
                         mState = State.DISCONNECTED;
                     }
                     if (mStateDesired == State.CONNECTED) {
+                        mState = State.CONNECTING;
                         switch (mServerDesired.getProtocol()) {
                         case NETWORK:
                             mClient = new NetworkClient(
@@ -138,10 +135,10 @@ public class CommunicationService extends Service implements Runnable {
 
     private final IBinder mBinder = new CBinder();
 
-    public static final int MSG_SLIDESHOW_STARTED = 1;
-    public static final int MSG_SLIDE_CHANGED = 2;
-    public static final int MSG_SLIDE_PREVIEW = 3;
-    public static final int MSG_SLIDE_NOTES = 4;
+    public static final String MSG_SLIDESHOW_STARTED = "SLIDESHOW_STARTED";
+    public static final String MSG_SLIDE_CHANGED = "SLIDE_CHANGED";
+    public static final String MSG_SLIDE_PREVIEW = "SLIDE_PREVIEW";
+    public static final String MSG_SLIDE_NOTES = "SLIDE_NOTES";
 
     public static final String MSG_SERVERLIST_CHANGED = "SERVERLIST_CHANGED";
     public static final String MSG_PAIRING_STARTED = "PAIRING_STARTED";
@@ -151,14 +148,10 @@ public class CommunicationService extends Service implements Runnable {
 
     private Client mClient;
 
-    private Receiver mReceiver = new Receiver();
+    private Receiver mReceiver = new Receiver(this);
 
     private ServerFinder mFinder = new ServerFinder(this);
 
-    public void setActivityMessenger(Messenger aActivityMessenger) {
-        mReceiver.setActivityMessenger(aActivityMessenger);
-    }
-
     @Override
     public IBinder onBind(Intent intent) {
         // TODO Auto-generated method stub
@@ -201,5 +194,9 @@ public class CommunicationService extends Service implements Runnable {
         return mReceiver.getSlideShow();
     }
 
+    public boolean isSlideShowRunning() {
+        return mReceiver.isSlideShowRunning();
+    }
+
 }
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/Receiver.java b/android/sdremote/src/org/libreoffice/impressremote/communication/Receiver.java
index 1cecd49..a3fe70e 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/communication/Receiver.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/communication/Receiver.java
@@ -10,112 +10,87 @@ package org.libreoffice.impressremote.communication;
 
 import java.util.ArrayList;
 
-import android.os.Bundle;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
+import android.content.Context;
+import android.content.Intent;
+import android.support.v4.content.LocalBroadcastManager;
 import android.util.Base64;
 
 public class Receiver {
 
-	private Messenger mActivityMessenger;
-
-	private SlideShow mSlideShow = new SlideShow();
-
-	public SlideShow getSlideShow() {
-		return mSlideShow;
-	}
-
-	public void setActivityMessenger(Messenger aActivityMessenger) {
-		mActivityMessenger = aActivityMessenger;
-	}
-
-	public void parseCommand(ArrayList<String> aCommand) {
-		if (mActivityMessenger == null) {
-			return;
-		}
-		String aInstruction = aCommand.get(0);
-		if (aInstruction.equals("slideshow_started")) {
-			int aSlideShowlength = Integer.parseInt(aCommand.get(1));
-			int aCurrentSlide = Integer.parseInt(aCommand.get(2));
-			mSlideShow.setLength(aSlideShowlength);
-			mSlideShow.setCurrentSlide(aCurrentSlide);
-
-			Message aMessage = Message.obtain(null,
-			                CommunicationService.MSG_SLIDESHOW_STARTED);
-			Bundle aData = new Bundle();
-			aMessage.setData(aData);
-			try {
-				mActivityMessenger.send(aMessage);
-			} catch (RemoteException e) {
-				// Dead Handler -- i.e. Activity gone.
-			}
-		} else {
-			if (mSlideShow == null)
-				return;
-
-			if (aInstruction.equals("slide_updated")) {
-
-				int aSlideNumber = Integer.parseInt(aCommand.get(1));
-
-				mSlideShow.setCurrentSlide(aSlideNumber);
-
-				Message aMessage = Message.obtain(null,
-				                CommunicationService.MSG_SLIDE_CHANGED);
-				Bundle aData = new Bundle();
-				aData.putInt("slide_number", aSlideNumber);
-				aMessage.setData(aData);
-				try {
-					mActivityMessenger.send(aMessage);
-				} catch (RemoteException e) {
-					// Dead Handler -- i.e. Activity gone.
-				}
-			} else if (aInstruction.equals("slide_preview")) {
-				int aSlideNumber = Integer.parseInt(aCommand.get(1));
-				String aImageString = aCommand.get(2);
-				byte[] aImage = Base64.decode(aImageString, Base64.DEFAULT);
-
-				// Store image internally
-				mSlideShow.putImage(aSlideNumber, aImage);
-
-				// Notify the frontend
-				Message aMessage = Message.obtain(null,
-				                CommunicationService.MSG_SLIDE_PREVIEW);
-				Bundle aData = new Bundle();
-				aData.putInt("slide_number", aSlideNumber);
-				aMessage.setData(aData);
-				try {
-					mActivityMessenger.send(aMessage);
-				} catch (RemoteException e) {
-					// TODO Auto-generated catch block
-					e.printStackTrace();
-				}
-			} else if (aInstruction.equals("slide_notes")) {
-				int aSlideNumber = Integer.parseInt(aCommand.get(1));
-				String aNotes = new String();
-				for (int i = 2; i < aCommand.size(); i++) {
-					aNotes += aCommand.get(i);
-				}
-
-				// Store image internally
-				mSlideShow.putNotes(aSlideNumber, aNotes);
-
-				// Notify the frontend
-				Message aMessage = Message.obtain(null,
-				                CommunicationService.MSG_SLIDE_NOTES);
-				Bundle aData = new Bundle();
-				aData.putInt("slide_number", aSlideNumber);
-				aMessage.setData(aData);
-				try {
-					mActivityMessenger.send(aMessage);
-				} catch (RemoteException e) {
-					// TODO Auto-generated catch block
-					e.printStackTrace();
-				}
-			}
-
-		}
-
-	}
+    public Receiver(Context aContext) {
+        mContext = aContext;
+        mSlideShow = new SlideShow(mContext);
+    }
+
+    private Context mContext;
+
+    private SlideShow mSlideShow;
+
+    public SlideShow getSlideShow() {
+        return mSlideShow;
+    }
+
+    public boolean isSlideShowRunning() {
+        return (mSlideShow.getSize() > 0);
+    }
+
+    public void parseCommand(ArrayList<String> aCommand) {
+        String aInstruction = aCommand.get(0);
+        if (aInstruction.equals("slideshow_started")) {
+            int aSlideShowlength = Integer.parseInt(aCommand.get(1));
+            int aCurrentSlide = Integer.parseInt(aCommand.get(2));
+            mSlideShow.setLength(aSlideShowlength);
+            mSlideShow.setCurrentSlide(aCurrentSlide);
+            Intent aIntent = new Intent(
+                            CommunicationService.MSG_SLIDESHOW_STARTED);
+            LocalBroadcastManager.getInstance(mContext).sendBroadcast(aIntent);
+        } else {
+            if (mSlideShow == null)
+                return;
+
+            if (aInstruction.equals("slide_updated")) {
+
+                int aSlideNumber = Integer.parseInt(aCommand.get(1));
+
+                mSlideShow.setCurrentSlide(aSlideNumber);
+
+                Intent aIntent = new Intent(
+                                CommunicationService.MSG_SLIDE_CHANGED);
+                aIntent.putExtra("slide_number", aSlideNumber);
+                LocalBroadcastManager.getInstance(mContext).sendBroadcast(
+                                aIntent);
+            } else if (aInstruction.equals("slide_preview")) {
+                int aSlideNumber = Integer.parseInt(aCommand.get(1));
+                String aImageString = aCommand.get(2);
+                byte[] aImage = Base64.decode(aImageString, Base64.DEFAULT);
+
+                // Store image internally
+                mSlideShow.putImage(aSlideNumber, aImage);
+
+                Intent aIntent = new Intent(
+                                CommunicationService.MSG_SLIDE_PREVIEW);
+                aIntent.putExtra("slide_number", aSlideNumber);
+                LocalBroadcastManager.getInstance(mContext).sendBroadcast(
+                                aIntent);
+            } else if (aInstruction.equals("slide_notes")) {
+                int aSlideNumber = Integer.parseInt(aCommand.get(1));
+                String aNotes = new String();
+                for (int i = 2; i < aCommand.size(); i++) {
+                    aNotes += aCommand.get(i);
+                }
+
+                // Store image internally
+                mSlideShow.putNotes(aSlideNumber, aNotes);
+
+                Intent aIntent = new Intent(
+                                CommunicationService.MSG_SLIDE_NOTES);
+                aIntent.putExtra("slide_number", aSlideNumber);
+                LocalBroadcastManager.getInstance(mContext).sendBroadcast(
+                                aIntent);
+            }
+
+        }
+
+    }
 }
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java b/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java
index 74f9ba9..cba18cd 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/communication/SlideShow.java
@@ -8,160 +8,169 @@
  */
 package org.libreoffice.impressremote.communication;
 
+import org.libreoffice.impressremote.R;
+
+import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.util.SparseArray;
 
 public class SlideShow {
 
-	private SparseArray<byte[]> mPreviewImages = new SparseArray<byte[]>();
-	private SparseArray<String> mNotes = new SparseArray<String>();
-
-	private int mSize = 0;
-	private int mCurrentSlide = 0;
-
-	protected SlideShow() {
-	}
-
-	protected void setLength(int aSize) {
-		mSize = aSize;
-	}
-
-	public int getSize() {
-		return mSize;
-	}
-
-	public int getCurrentSlide() {
-		return mCurrentSlide;
-	}
-
-	protected void setCurrentSlide(int aSlide) {
-		mCurrentSlide = aSlide;
-	}
-
-	protected void putImage(int aSlide, byte[] aImage) {
-		mPreviewImages.put(aSlide, aImage);
-	}
-
-	public Bitmap getImage(int aSlide) {
-		byte[] aImage = mPreviewImages.get(aSlide);
-		return BitmapFactory.decodeByteArray(aImage, 0, aImage.length);
-	}
-
-	protected void putNotes(int aSlide, String aNotes) {
-		mNotes.put(aSlide, aNotes);
-	}
-
-	public String getNotes(int aSlide) {
-		return mNotes.get(aSlide);
-	}
-
-	// ---------------------------------------------------- TIMER --------------
-	private Timer mTimer = new Timer();
-
-	public Timer getTimer() {
-		return mTimer;
-	}
-
-	public class Timer {
-		/**
-		 * This stores the starting time of the timer if running.
-		 *
-		 * If paused this stores how long the timer was previously running.
-		 */
-		private long aTime = 0;
-
-		private long mCountdownTime = 0;
-
-		private boolean mIsRunning = false;
-
-		private boolean mIsCountdown = false;
-
-		/**
-		 * Set whether this timer should be a normal or a countdown timer.
-		 * @param aIsCountdown
-		 * 		Whether this should be a countdown timer.
-		 */
-		public void setCountdown(boolean aIsCountdown) {
-			mIsCountdown = aIsCountdown;
-			if (mIsRunning) {
-				mIsRunning = false;
-				aTime = 0;
-			}
-		}
-
-		/**
-		 * Set the countdown time. Can be set, and isn't lost, whatever mode
-		 * the timer is running in.
-		 * @param aCountdownTime
-		 * 				The countdown time.
-		 */
-		public void setCountdownTime(long aCountdownTime) {
-			mCountdownTime = aCountdownTime;
-		}
-
-		public long getCountdownTime() {
-			return mCountdownTime;
-		}
-
-		public boolean isCountdown() {
-			return mIsCountdown;
-		}
-
-		public boolean isRunning() {
-			return mIsRunning;
-		}
-
-		/**
-		 * Reset the timer, and stop it it was running.
-		 */
-		public void reset() {
-			mIsRunning = false;
-			aTime = 0;
-		}
-
-		public void startTimer() {
-			if (mIsRunning)
-				return;
-
-			aTime = System.currentTimeMillis() - aTime;
-			mIsRunning = true;
-		}
-
-		public void stopTimer() {
-			if (!mIsRunning)
-				return;
-
-			aTime = System.currentTimeMillis() - aTime;
-			mIsRunning = false;
-		}
-
-		/**
-		 * Get either how long this timer has been running, or how long the
-		 * timer still has left to run.
-		 * @return
-		 */
-		public long getTimeMillis() {
-			long aTimeRunning;
-			// Determine how long we've been going.
-			if (mIsRunning) {
-				aTimeRunning = System.currentTimeMillis() - aTime;
-			} else {
-				aTimeRunning = aTime;
-			}
-			// And give the time going, or time left
-			if (!mIsCountdown) {
-				return aTimeRunning;
-			} else {
-				long aRet = mCountdownTime - aTimeRunning;
-				if (aRet < 0) { // We have completed!
-					mIsRunning = false;
-					aRet = 0;
-				}
-				return aRet;
-			}
-
-		}
-	}
+    private SparseArray<byte[]> mPreviewImages = new SparseArray<byte[]>();
+    private SparseArray<String> mNotes = new SparseArray<String>();
+
+    private int mSize = 0;
+    private int mCurrentSlide = 0;
+    private Context mContext;
+
+    protected SlideShow(Context aContext) {
+        mContext = aContext;
+    }
+
+    protected void setLength(int aSize) {
+        mSize = aSize;
+    }
+
+    public int getSize() {
+        return mSize;
+    }
+
+    public int getCurrentSlide() {
+        return mCurrentSlide;
+    }
+
+    protected void setCurrentSlide(int aSlide) {
+        mCurrentSlide = aSlide;
+    }
+
+    protected void putImage(int aSlide, byte[] aImage) {
+        mPreviewImages.put(aSlide, aImage);
+    }
+
+    public Bitmap getImage(int aSlide) {
+        byte[] aImage = mPreviewImages.get(aSlide);
+        if (aImage == null) {
+            return BitmapFactory.decodeResource(mContext.getResources(),
+                            R.drawable.image_loading);
+        }
+        return BitmapFactory.decodeByteArray(aImage, 0, aImage.length);
+    }
+
+    protected void putNotes(int aSlide, String aNotes) {
+        mNotes.put(aSlide, aNotes);
+    }
+
+    public String getNotes(int aSlide) {
+        return mNotes.get(aSlide);
+    }
+
+    // ---------------------------------------------------- TIMER --------------
+    private Timer mTimer = new Timer();
+
+    public Timer getTimer() {
+        return mTimer;
+    }
+
+    public class Timer {
+        /**
+         * This stores the starting time of the timer if running.
+         *
+         * If paused this stores how long the timer was previously running.
+         */
+        private long aTime = 0;
+
+        private long mCountdownTime = 0;
+
+        private boolean mIsRunning = false;
+
+        private boolean mIsCountdown = false;
+
+        /**
+         * Set whether this timer should be a normal or a countdown timer.
+         * @param aIsCountdown
+         *     Whether this should be a countdown timer.
+         */
+        public void setCountdown(boolean aIsCountdown) {
+            mIsCountdown = aIsCountdown;
+            if (mIsRunning) {
+                mIsRunning = false;
+                aTime = 0;
+            }
+        }
+
+        /**
+         * Set the countdown time. Can be set, and isn't lost, whatever mode
+         * the timer is running in.
+         * @param aCountdownTime
+         *      The countdown time.
+         */
+        public void setCountdownTime(long aCountdownTime) {
+            mCountdownTime = aCountdownTime;
+        }
+
+        public long getCountdownTime() {
+            return mCountdownTime;
+        }
+
+        public boolean isCountdown() {
+            return mIsCountdown;
+        }
+
+        public boolean isRunning() {
+            return mIsRunning;
+        }
+
+        /**
+         * Reset the timer, and stop it it was running.
+         */
+        public void reset() {
+            mIsRunning = false;
+            aTime = 0;
+        }
+
+        public void startTimer() {
+            if (mIsRunning)
+                return;
+
+            aTime = System.currentTimeMillis() - aTime;
+            mIsRunning = true;
+        }
+
+        public void stopTimer() {
+            if (!mIsRunning)
+                return;
+
+            aTime = System.currentTimeMillis() - aTime;
+            mIsRunning = false;
+        }
+
+        /**
+         * Get either how long this timer has been running, or how long the
+         * timer still has left to run.
+         * @return
+         */
+        public long getTimeMillis() {
+            long aTimeRunning;
+            // Determine how long we've been going.
+            if (mIsRunning) {
+                aTimeRunning = System.currentTimeMillis() - aTime;
+            } else {
+                aTimeRunning = aTime;
+            }
+            // And give the time going, or time left
+            if (!mIsCountdown) {
+                return aTimeRunning;
+            } else {
+                long aRet = mCountdownTime - aTimeRunning;
+                if (aRet < 0) { // We have completed!
+                    mIsRunning = false;
+                    aRet = 0;
+                }
+                return aRet;
+            }
+
+        }
+    }
 }
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/TestClient.java b/android/sdremote/src/org/libreoffice/impressremote/communication/TestClient.java
index 662cb50..a63472f 100644
--- a/android/sdremote/src/org/libreoffice/impressremote/communication/TestClient.java
+++ b/android/sdremote/src/org/libreoffice/impressremote/communication/TestClient.java
@@ -1,197 +1,197 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-package org.libreoffice.impressremote.communication;
-
-import org.libreoffice.impressremote.PresentationActivity;
-import org.libreoffice.impressremote.R;
-import org.libreoffice.impressremote.communication.Server.Protocol;
-
-import android.app.Activity;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.graphics.Bitmap;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.Messenger;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-public class TestClient extends Activity {
-
-    private boolean mCurrentPreviewImageMissing = false;
-
-    private boolean mIsBound = false;
-
-    private CommunicationService mCommunicationService;
-
-    final Messenger mMessenger = new Messenger(new MessageHandler());
-
-    /** Called when the activity is first created. */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.testlayout);
-        setupUI();
-
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        doBindService();
-
-    }
-
-    // FIXME: move all necessary code to CommunicationService.onUnbind
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-    }
-
-    @Override
-    public void onBackPressed() {
-        // TODO Auto-generated method stub
-        mCommunicationService.disconnect();
-        stopService(new Intent(this, CommunicationService.class));
-        doUnbindService();
-        finish();
-        super.onBackPressed();
-    }
-
-    @Override
-    protected void onStop() {
-        // TODO Auto-generated method stub
-        super.onStop();
-        // mCommunicationService.disconnect();
-        // stopService(new Intent(this, CommunicationService.class));
-    }
-
-    private ServiceConnection mConnection = new ServiceConnection() {
-        @Override
-        public void onServiceConnected(ComponentName aClassName,
-                        IBinder aService) {
-            mCommunicationService = ((CommunicationService.CBinder) aService)
-                            .getService();
-            mCommunicationService.connectTo(new Server(Protocol.NETWORK,
-                            "10.0.2.2", "TestServer", 0l));
-            mCommunicationService.setActivityMessenger(mMessenger);
-            enableButtons(true);
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName aClassName) {
-            mCommunicationService = null;
-            enableButtons(false);
-        }
-    };
-
-    void doBindService() {
-        Intent aIntent = new Intent(this, CommunicationService.class);
-        startService(aIntent);
-        bindService(aIntent, mConnection, Context.BIND_IMPORTANT);
-        mIsBound = true;
-    }
-
-    void doUnbindService() {
-        mCommunicationService.setActivityMessenger(null);
-        if (mIsBound) {
-            unbindService(mConnection);
-            mIsBound = false;
-        }
-    }
-
-    private Button mButtonNext;
-
-    private Button mButtonPrevious;
-
-    private ImageView mImageView;
-
-    private TextView mSlideLabel;
-
-    private void setupUI() {
-        mButtonNext = (Button) findViewById(R.id.button_next);
-        mButtonPrevious = (Button) findViewById(R.id.button_previous);
-        mImageView = (ImageView) findViewById(R.id.image_preview);
-        mSlideLabel = (TextView) findViewById(R.id.label_curSlide);
-
-        enableButtons(false);
-
-        mButtonNext.setOnClickListener(new OnClickListener() {
-
-            @Override
-            public void onClick(View v) {
-                mCommunicationService.getTransmitter().nextTransition();
-
-            }
-
-        });
-
-        mButtonPrevious.setOnClickListener(new OnClickListener() {
-
-            @Override
-            public void onClick(View v) {
-                mCommunicationService.getTransmitter().previousTransition();
-
-            }
-
-        });
-
-        Button mThumbnailButton = (Button) findViewById(R.id.button_thumbnail);
-
-        mThumbnailButton.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                Intent aIntent = new Intent(TestClient.this,
-                                PresentationActivity.class);
-                startActivity(aIntent);
-            }
-        });
-
-    }
-
-    private void enableButtons(boolean aEnabled) {
-        mButtonNext.setEnabled(aEnabled);
-        mButtonPrevious.setEnabled(aEnabled);
-    }
-
-    class MessageHandler extends Handler {
-        @Override
-        public void handleMessage(Message aMessage) {
-            Bundle aData = aMessage.getData();
-            switch (aMessage.what) {
-            case CommunicationService.MSG_SLIDE_CHANGED:
-                int newSlide = aData.getInt("slide_number");
-                mSlideLabel.setText("Slide " + newSlide);
-                mCurrentPreviewImageMissing = true;
-                // We continue on to try and update the image.
-            case CommunicationService.MSG_SLIDE_PREVIEW:
-                int aSlideNumber = aData.getInt("slide_number");
-                if (mCurrentPreviewImageMissing) {
-                    Bitmap aImage = mCommunicationService.getSlideShow()
-                                    .getImage(aSlideNumber);
-                    if (aImage != null) {
-                        mImageView.setImageBitmap(aImage);
-                        mCurrentPreviewImageMissing = false;
-                    }
-                }
-                break;
-
-            }
-        }
-    }
-}
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file
+///* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+///*
+// * This file is part of the LibreOffice project.
+// *
+// * This Source Code Form is subject to the terms of the Mozilla Public
+// * License, v. 2.0. If a copy of the MPL was not distributed with this
+// * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+// */
+//package org.libreoffice.impressremote.communication;
+//
+//import org.libreoffice.impressremote.PresentationActivity;
+//import org.libreoffice.impressremote.R;
+//import org.libreoffice.impressremote.communication.Server.Protocol;
+//
+//import android.app.Activity;
+//import android.content.ComponentName;
+//import android.content.Context;
+//import android.content.Intent;
+//import android.content.ServiceConnection;
+//import android.graphics.Bitmap;
+//import android.os.Bundle;
+//import android.os.Handler;
+//import android.os.IBinder;
+//import android.os.Message;
+//import android.os.Messenger;
+//import android.view.View;
+//import android.view.View.OnClickListener;
+//import android.widget.Button;
+//import android.widget.ImageView;
+//import android.widget.TextView;
+//
+//public class TestClient extends Activity {
+//
+//    private boolean mCurrentPreviewImageMissing = false;
+//
+//    private boolean mIsBound = false;
+//
+//    private CommunicationService mCommunicationService;
+//
+//    final Messenger mMessenger = new Messenger(new MessageHandler());
+//
+//    /** Called when the activity is first created. */
+//    @Override
+//    public void onCreate(Bundle savedInstanceState) {
+//        super.onCreate(savedInstanceState);
+//        setContentView(R.layout.testlayout);
+//        setupUI();
+//
+//    }
+//
+//    @Override
+//    protected void onResume() {
+//        super.onResume();
+//        doBindService();
+//
+//    }
+//
+//    // FIXME: move all necessary code to CommunicationService.onUnbind
+//
+//    @Override
+//    protected void onPause() {
+//        super.onPause();
+//    }
+//
+//    @Override
+//    public void onBackPressed() {
+//        // TODO Auto-generated method stub
+//        mCommunicationService.disconnect();
+//        stopService(new Intent(this, CommunicationService.class));
+//        doUnbindService();
+//        finish();
+//        super.onBackPressed();
+//    }
+//
+//    @Override
+//    protected void onStop() {
+//        // TODO Auto-generated method stub
+//        super.onStop();
+//        // mCommunicationService.disconnect();
+//        // stopService(new Intent(this, CommunicationService.class));
+//    }
+//
+//    private ServiceConnection mConnection = new ServiceConnection() {
+//        @Override
+//        public void onServiceConnected(ComponentName aClassName,
+//                        IBinder aService) {
+//            mCommunicationService = ((CommunicationService.CBinder) aService)
+//                            .getService();
+//            mCommunicationService.connectTo(new Server(Protocol.NETWORK,
+//                            "10.0.2.2", "TestServer", 0l));
+//            mCommunicationService.setActivityMessenger(mMessenger);
+//            enableButtons(true);
+//        }
+//
+//        @Override
+//        public void onServiceDisconnected(ComponentName aClassName) {
+//            mCommunicationService = null;
+//            enableButtons(false);
+//        }
+//    };
+//
+//    void doBindService() {
+//        Intent aIntent = new Intent(this, CommunicationService.class);
+//        startService(aIntent);
+//        bindService(aIntent, mConnection, Context.BIND_IMPORTANT);
+//        mIsBound = true;
+//    }
+//
+//    void doUnbindService() {
+//        mCommunicationService.setActivityMessenger(null);
+//        if (mIsBound) {
+//            unbindService(mConnection);
+//            mIsBound = false;
+//        }
+//    }
+//
+//    private Button mButtonNext;
+//
+//    private Button mButtonPrevious;
+//
+//    private ImageView mImageView;
+//
+//    private TextView mSlideLabel;
+//
+//    private void setupUI() {
+//        mButtonNext = (Button) findViewById(R.id.button_next);
+//        mButtonPrevious = (Button) findViewById(R.id.button_previous);
+//        mImageView = (ImageView) findViewById(R.id.image_preview);
+//        mSlideLabel = (TextView) findViewById(R.id.label_curSlide);
+//
+//        enableButtons(false);
+//
+//        mButtonNext.setOnClickListener(new OnClickListener() {
+//
+//            @Override
+//            public void onClick(View v) {
+//                mCommunicationService.getTransmitter().nextTransition();
+//
+//            }
+//
+//        });
+//
+//        mButtonPrevious.setOnClickListener(new OnClickListener() {
+//
+//            @Override
+//            public void onClick(View v) {
+//                mCommunicationService.getTransmitter().previousTransition();
+//
+//            }
+//
+//        });
+//
+//        Button mThumbnailButton = (Button) findViewById(R.id.button_thumbnail);
+//
+//        mThumbnailButton.setOnClickListener(new OnClickListener() {
+//            @Override
+//            public void onClick(View v) {
+//                Intent aIntent = new Intent(TestClient.this,
+//                                PresentationActivity.class);
+//                startActivity(aIntent);
+//            }
+//        });
+//
+//    }
+//
+//    private void enableButtons(boolean aEnabled) {
+//        mButtonNext.setEnabled(aEnabled);
+//        mButtonPrevious.setEnabled(aEnabled);
+//    }
+//
+//    class MessageHandler extends Handler {
+//        @Override
+//        public void handleMessage(Message aMessage) {
+//            Bundle aData = aMessage.getData();
+//            switch (aMessage.what) {
+//            case CommunicationService.MSG_SLIDE_CHANGED:
+//                int newSlide = aData.getInt("slide_number");
+//                mSlideLabel.setText("Slide " + newSlide);
+//                mCurrentPreviewImageMissing = true;
+//                // We continue on to try and update the image.
+//            case CommunicationService.MSG_SLIDE_PREVIEW:
+//                int aSlideNumber = aData.getInt("slide_number");
+//                if (mCurrentPreviewImageMissing) {
+//                    Bitmap aImage = mCommunicationService.getSlideShow()
+//                                    .getImage(aSlideNumber);
+//                    if (aImage != null) {
+//                        mImageView.setImageBitmap(aImage);
+//                        mCurrentPreviewImageMissing = false;
+//                    }
+//                }
+//                break;
+//
+//            }
+//        }
+//    }
+//}
+///* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file
commit e02468f6e8b5d15635c2c9986ca249a8254192d1
Author: Andrzej J.R. Hunt <andrzej at ahunt.org>
Date:   Tue Aug 14 12:59:22 2012 +0200

    Added rotation of presentation view.
    
    Change-Id: Iea68b7740c5e7cf9380c91b8b85ff02fd9c11b8e

diff --git a/android/sdremote/res/drawable-hdpi/handle_light.9.png b/android/sdremote/res/drawable-hdpi/handle_light.9.png
index b0d7bef..7d1b1c9 100644
Binary files a/android/sdremote/res/drawable-hdpi/handle_light.9.png and b/android/sdremote/res/drawable-hdpi/handle_light.9.png differ
diff --git a/android/sdremote/res/drawable-hdpi/handle_vertical_default.9.png b/android/sdremote/res/drawable-hdpi/handle_vertical_default.9.png
new file mode 100644
index 0000000..830493c
Binary files /dev/null and b/android/sdremote/res/drawable-hdpi/handle_vertical_default.9.png differ
diff --git a/android/sdremote/res/drawable-hdpi/handle_vertical_light.9.png b/android/sdremote/res/drawable-hdpi/handle_vertical_light.9.png
new file mode 100644
index 0000000..8246c39
Binary files /dev/null and b/android/sdremote/res/drawable-hdpi/handle_vertical_light.9.png differ
diff --git a/android/sdremote/res/drawable-land/handle.xml b/android/sdremote/res/drawable-land/handle.xml
new file mode 100644
index 0000000..3656e83
--- /dev/null
+++ b/android/sdremote/res/drawable-land/handle.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:drawable="@drawable/handle_vertical_light" android:state_activated="true"/>
+    <item android:drawable="@drawable/handle_vertical_light" android:state_pressed="true"/>
+    <item android:drawable="@drawable/handle_vertical_light" android:state_focused="true"/>
+    <item android:drawable="@drawable/handle_vertical_default"/>
+
+</selector>
\ No newline at end of file
diff --git a/android/sdremote/res/drawable-mdpi/handle_vertical_default.9.png b/android/sdremote/res/drawable-mdpi/handle_vertical_default.9.png
new file mode 100644
index 0000000..830493c
Binary files /dev/null and b/android/sdremote/res/drawable-mdpi/handle_vertical_default.9.png differ
diff --git a/android/sdremote/res/drawable-mdpi/handle_vertical_light.9.png b/android/sdremote/res/drawable-mdpi/handle_vertical_light.9.png
new file mode 100644
index 0000000..8246c39
Binary files /dev/null and b/android/sdremote/res/drawable-mdpi/handle_vertical_light.9.png differ
diff --git a/android/sdremote/res/drawable-xhdpi/handle_vertical_default.9.png b/android/sdremote/res/drawable-xhdpi/handle_vertical_default.9.png
new file mode 100644
index 0000000..830493c
Binary files /dev/null and b/android/sdremote/res/drawable-xhdpi/handle_vertical_default.9.png differ
diff --git a/android/sdremote/res/drawable-xhdpi/handle_vertical_light.9.png b/android/sdremote/res/drawable-xhdpi/handle_vertical_light.9.png
new file mode 100644
index 0000000..8246c39
Binary files /dev/null and b/android/sdremote/res/drawable-xhdpi/handle_vertical_light.9.png differ
diff --git a/android/sdremote/res/layout-land/fragment_presentation.xml b/android/sdremote/res/layout-land/fragment_presentation.xml
new file mode 100644
index 0000000..1cdd4d3
--- /dev/null
+++ b/android/sdremote/res/layout-land/fragment_presentation.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/presentation_layout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal" >
+
+    <LinearLayout

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list