From d62f8088b8cc42417f97a3b5c3f99bf9288593d4 Mon Sep 17 00:00:00 2001
From: dknn <yoann.blein@free.fr>
Date: Mon, 6 Aug 2012 16:40:13 +0200
Subject: Add support for multiple sharing and control in chat view


diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 16b22fe..611f870 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -32,6 +32,7 @@
 #include <Swiften/Elements/DeliveryReceipt.h>
 #include <Swiften/Elements/DeliveryReceiptRequest.h>
 #include <Swift/Controllers/SettingConstants.h>
+#include <Swift/Controllers/ScreenSharing/ScreenSharingController.h>
 
 #include <Swiften/Base/Log.h>
 
@@ -79,6 +80,9 @@ ChatController::ChatController(const JID& self, StanzaChannel* stanzaChannel, IQ
 	chatWindow_->onWhiteboardSessionAccept.connect(boost::bind(&ChatController::handleWhiteboardSessionAccept, this));
 	chatWindow_->onWhiteboardSessionCancel.connect(boost::bind(&ChatController::handleWhiteboardSessionCancel, this));
 	chatWindow_->onWhiteboardWindowShow.connect(boost::bind(&ChatController::handleWhiteboardWindowShow, this));
+	chatWindow_->onScreenSharingAccept.connect(boost::bind(&ChatController::handleScreenSharingAccept, this, _1));
+	chatWindow_->onScreenSharingCancel.connect(boost::bind(&ChatController::handleScreenSharingCancel, this, _1));
+	chatWindow_->onScreenSharingStop.connect(boost::bind(&ChatController::handleScreenSharingStop, this, _1));
 	handleBareJIDCapsChanged(toJID_);
 
 	settings_->onSettingChanged.connect(boost::bind(&ChatController::handleSettingChanged, this, _1));
@@ -269,6 +273,14 @@ void ChatController::handleWhiteboardStateChange(const ChatWindow::WhiteboardSes
 	chatWindow_->setWhiteboardSessionStatus(lastWbID_, state);
 }
 
+void ChatController::handleNewScreenSharingController(ScreenSharingController* ssc)
+{
+	std::string nick = senderDisplayNameFromMessage(ssc->getOtherParty());
+	std::string ssID = ssc->setChatWindow(chatWindow_, nick);
+
+	ssControllers[ssID] = ssc;
+}
+
 void ChatController::handleFileTransferCancel(std::string id) {
 	SWIFT_LOG(debug) << "handleFileTransferCancel(" << id << ")" << std::endl;
 	if (ftControllers.find(id) != ftControllers.end()) {
@@ -313,6 +325,39 @@ void ChatController::handleWhiteboardWindowShow() {
 	eventStream_->send(boost::make_shared<ShowWhiteboardUIEvent>(toJID_));
 }
 
+void ChatController::handleScreenSharingAccept(std::string id)
+{
+	SWIFT_LOG(debug) "handleScreenSharingAccept(" << id << ")" << std::endl;
+	std::map<std::string, ScreenSharingController*>::iterator controller = ssControllers.find(id);
+	if (controller != ssControllers.end()) {
+		controller->second->accept();
+	} else {
+		std::cerr << "unknown screen sharing UI id" << std::endl;
+	}
+}
+
+void ChatController::handleScreenSharingCancel(std::string id)
+{
+	SWIFT_LOG(debug) "handleScreenSharingCancel(" << id << ")" << std::endl;
+	std::map<std::string, ScreenSharingController*>::iterator controller = ssControllers.find(id);
+	if (controller != ssControllers.end()) {
+		controller->second->cancel();
+	} else {
+		std::cerr << "unknown screen sharing UI id" << std::endl;
+	}
+}
+
+void ChatController::handleScreenSharingStop(std::string id)
+{
+	SWIFT_LOG(debug) "handleScreenSharingStop(" << id << ")" << std::endl;
+	std::map<std::string, ScreenSharingController*>::iterator controller = ssControllers.find(id);
+	if (controller != ssControllers.end()) {
+		controller->second->stop();
+	} else {
+		std::cerr << "unknown screen sharing UI id" << std::endl;
+	}
+}
+
 std::string ChatController::senderDisplayNameFromMessage(const JID& from) {
 	return nickResolver_->jidToNick(from);
 }
diff --git a/Swift/Controllers/Chat/ChatController.h b/Swift/Controllers/Chat/ChatController.h
index 66ec37d..6350cbb 100644
--- a/Swift/Controllers/Chat/ChatController.h
+++ b/Swift/Controllers/Chat/ChatController.h
@@ -32,6 +32,7 @@ namespace Swift {
 			virtual void handleNewFileTransferController(FileTransferController* ftc);
 			virtual void handleWhiteboardSessionRequest(bool senderIsSelf);
 			virtual void handleWhiteboardStateChange(const ChatWindow::WhiteboardSessionState state);
+			virtual void handleNewScreenSharingController(ScreenSharingController* ssc);
 			virtual void setContactIsReceivingPresence(bool /*isReceivingPresence*/);
 
 		protected:
@@ -63,6 +64,10 @@ namespace Swift {
 			void handleWhiteboardSessionCancel();
 			void handleWhiteboardWindowShow();
 
+			void handleScreenSharingAccept(std::string id);
+			void handleScreenSharingCancel(std::string id);
+			void handleScreenSharingStop(std::string id);
+
 			void handleSettingChanged(const std::string& settingPath);
 			void checkForDisplayingDisplayReceiptsAlert();
 
@@ -83,6 +88,7 @@ namespace Swift {
 			bool receivingPresenceFromUs_;
 			bool userWantsReceipts_;
 			std::map<std::string, FileTransferController*> ftControllers;
+			std::map<std::string, ScreenSharingController*> ssControllers;
 			SettingsProvider* settings_;
 			std::string lastWbID_;
 	};
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index 48ea006..90c39ac 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -43,6 +43,7 @@
 #include <Swift/Controllers/SettingConstants.h>
 #include <Swiften/Client/StanzaChannel.h>
 #include <Swift/Controllers/WhiteboardManager.h>
+#include <Swift/Controllers/ScreenSharing/ScreenSharingOverview.h>
 #include <Swift/Controllers/ScreenSharing/ScreenSharingController.h>
 #include <Swiften/ScreenSharing/IncomingScreenSharing.h>
 
@@ -72,7 +73,7 @@ ChatsManager::ChatsManager(
 		MUCSearchWindowFactory* mucSearchWindowFactory,
 		ProfileSettingsProvider* profileSettings,
 		FileTransferOverview* ftOverview,
-		ScreenSharingController* ssController,
+		ScreenSharingOverview* ssOverview,
 		XMPPRoster* roster,
 		bool eagleMode,
 		SettingsProvider* settings,
@@ -85,7 +86,7 @@ ChatsManager::ChatsManager(
 			entityCapsProvider_(entityCapsProvider), 
 			mucManager(mucManager),
 			ftOverview_(ftOverview),
-			ssController_(ssController),
+			ssOverview_(ssOverview),
 			roster_(roster),
 			eagleMode_(eagleMode),
 			settings_(settings),
@@ -116,7 +117,7 @@ ChatsManager::ChatsManager(
 	mucSearchController_ = new MUCSearchController(jid_, mucSearchWindowFactory, iqRouter, profileSettings_);
 	mucSearchController_->onMUCSelected.connect(boost::bind(&ChatsManager::handleMUCSelectedAfterSearch, this, _1));
 	ftOverview_->onNewFileTransferController.connect(boost::bind(&ChatsManager::handleNewFileTransferController, this, _1));
-	ssController->onNewIncomingScreenSharing.connect(boost::bind(&ChatsManager::handleNewIncomingScreenSharing, this, _1));
+	ssOverview_->onNewIncomingScreenSharing.connect(boost::bind(&ChatsManager::handleNewIncomingScreenSharing, this, _1));
 	whiteboardManager_->onSessionRequest.connect(boost::bind(&ChatsManager::handleWhiteboardSessionRequest, this, _1, _2));
 	whiteboardManager_->onRequestAccepted.connect(boost::bind(&ChatsManager::handleWhiteboardStateChange, this, _1, ChatWindow::WhiteboardAccepted));
 	whiteboardManager_->onSessionTerminate.connect(boost::bind(&ChatsManager::handleWhiteboardStateChange, this, _1, ChatWindow::WhiteboardTerminated));
@@ -526,7 +527,7 @@ ChatController* ChatsManager::getChatControllerOrFindAnother(const JID &contact)
 
 ChatController* ChatsManager::createNewChatController(const JID& contact) {
 	assert(chatControllers_.find(contact) == chatControllers_.end());
-	ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, mucRegistry_->isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_, eventController_, timerFactory_, entityCapsProvider_, userWantsReceipts_, settings_, historyController_, mucRegistry_);
+	ChatController* controller = new ChatController(jid_, stanzaChannel_, iqRouter_, chatWindowFactory_, contact, nickResolver_, presenceOracle_, avatarManager_, mucRegistry_->isMUC(contact.toBare()), useDelayForLatency_, uiEventStream_, eventController_, timerFactory_, entityCapsProvider_, userWantsReceipts_, settings_);
 	chatControllers_[contact] = controller;
 	controller->setAvailableServerFeatures(serverDiscoInfo_);
 	controller->onActivity.connect(boost::bind(&ChatsManager::handleChatActivity, this, contact, _1, false));
@@ -599,7 +600,7 @@ void ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional
 		if (createAsReservedIfNew) {
 			muc->setCreateAsReservedIfNew();
 		}
-		MUCController* controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_, roster_, historyController_, mucRegistry_);
+		MUCController* controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_, roster_);
 		mucControllers_[mucJID] = controller;
 		controller->setAvailableServerFeatures(serverDiscoInfo_);
 		controller->onUserLeft.connect(boost::bind(&ChatsManager::handleUserLeftMUC, this, controller));
@@ -669,36 +670,13 @@ void ChatsManager::handleNewFileTransferController(FileTransferController* ftc)
 	chatController->activateChatWindow();
 }
 
-void ChatsManager::handleNewIncomingScreenSharing(boost::shared_ptr<IncomingScreenSharing> iss)
+void ChatsManager::handleNewIncomingScreenSharing(ScreenSharingController* ssc)
 {
-	ChatController* chatController = getChatControllerOrCreate(iss->getSender());
-//	chatController->handleNewFileTransferController(ftc);
+	ChatController* chatController = getChatControllerOrCreate(ssc->getOtherParty());
+	chatController->handleNewScreenSharingController(ssc);
 	chatController->activateChatWindow();
 }
 
-void ChatsManager::handleWhiteboardSessionRequest(const JID& contact, bool senderIsSelf) {
-	ChatController* chatController = getChatControllerOrCreate(contact);
-	chatController->handleWhiteboardSessionRequest(senderIsSelf);
-	chatController->activateChatWindow();
-}
-
-void ChatsManager::handleWhiteboardStateChange(const JID& contact, const ChatWindow::WhiteboardSessionState state) {
-	ChatController* chatController = getChatControllerOrCreate(contact);
-	chatController->handleWhiteboardStateChange(state);
-	chatController->activateChatWindow();
-	if (state == ChatWindow::WhiteboardAccepted) {
-		boost::filesystem::path path;
-		JID bareJID = contact.toBare();
-		if (avatarManager_) {
-			path = avatarManager_->getAvatarPath(bareJID);
-		}
-		ChatListWindow::Chat chat(bareJID, nickResolver_->jidToNick(bareJID), "", 0, StatusShow::None, path, false);
- 		chatListWindow_->addWhiteboardSession(chat);
-	} else {
-		chatListWindow_->removeWhiteboardSession(contact.toBare());
-	}
-}
-
 void ChatsManager::handleRecentActivated(const ChatListWindow::Chat& chat) {
 	if (chat.isMUC) {
 		/* FIXME: This means that recents requiring passwords will just flat-out not work */
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index 31006b0..1ef2987 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -50,12 +50,13 @@ namespace Swift {
 	class SettingsProvider;
 	class WhiteboardManager;
 	class HistoryController;
+	class ScreenSharingOverview;
 	class ScreenSharingController;
 	class IncomingScreenSharing;
 	
 	class ChatsManager {
 		public:
-			ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, JoinMUCWindowFactory* joinMUCWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsProvider* entityCapsProvider, MUCManager* mucManager, MUCSearchWindowFactory* mucSearchWindowFactory, ProfileSettingsProvider* profileSettings, FileTransferOverview* ftOverview, ScreenSharingController* ssController, XMPPRoster* roster, bool eagleMode, SettingsProvider* settings, HistoryController* historyController_, WhiteboardManager* whiteboardManager);
+			ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, JoinMUCWindowFactory* joinMUCWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsProvider* entityCapsProvider, MUCManager* mucManager, MUCSearchWindowFactory* mucSearchWindowFactory, ProfileSettingsProvider* profileSettings, FileTransferOverview* ftOverview, ScreenSharingOverview* ssOverview, XMPPRoster* roster, bool eagleMode, SettingsProvider* settings, HistoryController* historyController_, WhiteboardManager* whiteboardManager);
 			virtual ~ChatsManager();
 			void setAvatarManager(AvatarManager* avatarManager);
 			void setOnline(bool enabled);
@@ -77,7 +78,7 @@ namespace Swift {
 			void handleBookmarksReady();
 			void handleChatActivity(const JID& jid, const std::string& activity, bool isMUC);
 			void handleNewFileTransferController(FileTransferController*);
-			void handleNewIncomingScreenSharing(boost::shared_ptr<IncomingScreenSharing> iss);
+			void handleNewIncomingScreenSharing(ScreenSharingController* ssc);
 			void handleWhiteboardSessionRequest(const JID& contact, bool senderIsSelf);
 			void handleWhiteboardStateChange(const JID& contact, const ChatWindow::WhiteboardSessionState state);
 			void appendRecent(const ChatListWindow::Chat& chat);
@@ -133,7 +134,7 @@ namespace Swift {
 			std::list<ChatListWindow::Chat> recentChats_;
 			ProfileSettingsProvider* profileSettings_;
 			FileTransferOverview* ftOverview_;
-			ScreenSharingController* ssController_;
+			ScreenSharingOverview* ssOverview_;
 			XMPPRoster* roster_;
 			bool eagleMode_;
 			bool userWantsReceipts_;
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index 17dab36..5774ea6 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -78,7 +78,7 @@
 #include <Swiften/Client/ClientXMLTracer.h>
 #include <Swift/Controllers/SettingConstants.h>
 #include <Swiften/Client/StanzaChannel.h>
-#include "Swift/Controllers/ScreenSharing/ScreenSharingController.h"
+#include "Swift/Controllers/ScreenSharing/ScreenSharingOverview.h"
 
 namespace Swift {
 
@@ -111,7 +111,7 @@ MainController::MainController(
 			loginWindow_(NULL) ,
 			useDelayForLatency_(useDelayForLatency),
 			ftOverview_(NULL),
-			ssController_(NULL) {
+			ssOverview_(NULL) {
 	storages_ = NULL;
 	certificateStorage_ = NULL;
 	statusTracker_ = NULL;
@@ -239,8 +239,8 @@ void MainController::resetClient() {
 #endif
 	delete ftOverview_;
 	ftOverview_ = NULL;
-	delete ssController_;
-	ssController_ = NULL;
+	delete ssOverview_;
+	ssOverview_ = NULL;
 	delete rosterController_;
 	rosterController_ = NULL;
 	delete eventNotifier_;
@@ -306,8 +306,8 @@ void MainController::handleConnected() {
 		client_->getFileTransferManager()->startListeningOnPort(randomPort);
 		ftOverview_ = new FileTransferOverview(client_->getFileTransferManager());
 		fileTransferListController_->setFileTransferOverview(ftOverview_);
-		ssController_ = new ScreenSharingController(client_->getScreenSharingManager(), uiFactory_, networkFactories_->getTimerFactory());
-		rosterController_ = new RosterController(jid_, client_->getRoster(), client_->getAvatarManager(), uiFactory_, client_->getNickManager(), client_->getNickResolver(), client_->getPresenceOracle(), client_->getSubscriptionManager(), eventController_, uiEventStream_, client_->getIQRouter(), settings_, client_->getEntityCapsProvider(), ftOverview_, ssController_);
+		ssOverview_ = new ScreenSharingOverview(client_->getScreenSharingManager(), uiFactory_, networkFactories_->getTimerFactory());
+		rosterController_ = new RosterController(jid_, client_->getRoster(), client_->getAvatarManager(), uiFactory_, client_->getNickManager(), client_->getNickResolver(), client_->getPresenceOracle(), client_->getSubscriptionManager(), eventController_, uiEventStream_, client_->getIQRouter(), settings_, client_->getEntityCapsProvider(), ftOverview_, ssOverview_);
 		rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2));
 		rosterController_->onSignOutRequest.connect(boost::bind(&MainController::signOut, this));
 		rosterController_->getWindow()->onShowCertificateRequest.connect(boost::bind(&MainController::handleShowCertificateRequest, this));
@@ -323,9 +323,9 @@ void MainController::handleConnected() {
 #ifdef SWIFT_EXPERIMENTAL_HISTORY
 		historyController_ = new HistoryController(storages_->getHistoryStorage());
 		historyViewController_ = new HistoryViewController(jid_, uiEventStream_, historyController_, client_->getNickResolver(), client_->getAvatarManager(), client_->getPresenceOracle(), uiFactory_);
-		chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_, historyController_, whiteboardManager_);
+		chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, ssOverview_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_, historyController_, whiteboardManager_);
 #else
-		chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, ssController_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_, NULL, whiteboardManager_);
+		chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, uiFactory_, uiFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, uiFactory_, useDelayForLatency_, networkFactories_->getTimerFactory(), client_->getMUCRegistry(), client_->getEntityCapsProvider(), client_->getMUCManager(), uiFactory_, profileSettings_, ftOverview_, ssOverview_, client_->getRoster(), !settings_->getSetting(SettingConstants::REMEMBER_RECENT_CHATS), settings_, NULL, whiteboardManager_);
 #endif
 		
 		client_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1));
diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h
index ad8fef2..8b40ce5 100644
--- a/Swift/Controllers/MainController.h
+++ b/Swift/Controllers/MainController.h
@@ -72,6 +72,7 @@ namespace Swift {
 	class FileTransferOverview;
 	class WhiteboardManager;
 	class ScreenSharingController;
+	class ScreenSharingOverview;
 
 	class MainController {
 		public:
@@ -177,6 +178,6 @@ namespace Swift {
 			static const int SecondsToWaitBeforeForceQuitting;
 			FileTransferOverview* ftOverview_;
 			WhiteboardManager* whiteboardManager_;
-			ScreenSharingController* ssController_;
+			ScreenSharingOverview* ssOverview_;
 	};
 }
diff --git a/Swift/Controllers/Roster/RosterController.cpp b/Swift/Controllers/Roster/RosterController.cpp
index 40fd957..dcb5f60 100644
--- a/Swift/Controllers/Roster/RosterController.cpp
+++ b/Swift/Controllers/Roster/RosterController.cpp
@@ -45,15 +45,15 @@
 #include <Swiften/Disco/EntityCapsManager.h>
 #include <Swiften/Jingle/JingleSessionManager.h>
 #include <Swift/Controllers/SettingConstants.h>
-#include "Swift/Controllers/ScreenSharing/ScreenSharingController.h"
+#include "Swift/Controllers/ScreenSharing/ScreenSharingOverview.h"
 
 namespace Swift {
 
 /**
  * The controller does not gain ownership of these parameters.
  */
-RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings, EntityCapsProvider* entityCapsManager, FileTransferOverview* fileTransferOverview, ScreenSharingController *ssController)
-	: myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()), nickManager_(nickManager), nickResolver_(nickResolver), uiEventStream_(uiEventStream), entityCapsManager_(entityCapsManager), ftOverview_(fileTransferOverview), ssController_(ssController) {
+RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings, EntityCapsProvider* entityCapsManager, FileTransferOverview* fileTransferOverview, ScreenSharingOverview* screenSharingOverView)
+	: myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()), nickManager_(nickManager), nickResolver_(nickResolver), uiEventStream_(uiEventStream), entityCapsManager_(entityCapsManager), ftOverview_(fileTransferOverview), ssOverview_(screenSharingOverView) {
 	assert(fileTransferOverview);
 	iqRouter_ = iqRouter;
 	presenceOracle_ = presenceOracle;
@@ -241,8 +241,7 @@ void RosterController::handleUIEvent(boost::shared_ptr<UIEvent> event) {
 		ftOverview_->sendFile(sendFileEvent->getJID(), sendFileEvent->getFilename());
 	}
 	else if (boost::shared_ptr<ShareScreenUIEvent> shareScreenEvent = boost::dynamic_pointer_cast<ShareScreenUIEvent>(event)) {
-		std::cout << "Create sharing: " << ssController_->createOugoingScreenSharing(shareScreenEvent->jid);
-		std::cout << std::endl;
+		ssOverview_->createOugoingScreenSharing(shareScreenEvent->jid);
 	}
 }
 
diff --git a/Swift/Controllers/Roster/RosterController.h b/Swift/Controllers/Roster/RosterController.h
index 2fb642d..57d3017 100644
--- a/Swift/Controllers/Roster/RosterController.h
+++ b/Swift/Controllers/Roster/RosterController.h
@@ -39,11 +39,11 @@ namespace Swift {
 	class NickManager;
 	class EntityCapsProvider;
 	class FileTransferManager;
-	class ScreenSharingController;
+	class ScreenSharingOverview;
 	
 	class RosterController {
 		public:
-			RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter_, SettingsProvider* settings, EntityCapsProvider* entityCapsProvider, FileTransferOverview* fileTransferOverview, ScreenSharingController* ssController);
+			RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter_, SettingsProvider* settings, EntityCapsProvider* entityCapsProvider, FileTransferOverview* fileTransferOverview, ScreenSharingOverview* screenSharingOverView);
 			~RosterController();
 			void showRosterWindow();
 			MainWindow* getWindow() {return mainWindow_;};
@@ -95,7 +95,7 @@ namespace Swift {
 			UIEventStream* uiEventStream_;
 			EntityCapsProvider* entityCapsManager_;
 			FileTransferOverview* ftOverview_;
-			ScreenSharingController* ssController_;
+			ScreenSharingOverview* ssOverview_;
 			
 			boost::bsignals::scoped_connection changeStatusConnection_;
 			boost::bsignals::scoped_connection signOutConnection_;
diff --git a/Swift/Controllers/SConscript b/Swift/Controllers/SConscript
index 2dba9a9..d884baa 100644
--- a/Swift/Controllers/SConscript
+++ b/Swift/Controllers/SConscript
@@ -76,6 +76,7 @@ if env["SCONS_STAGE"] == "build" :
 			"SettingConstants.cpp",
 			"WhiteboardManager.cpp",
 			"ScreenSharing/ScreenSharingController.cpp",
+			"ScreenSharing/ScreenSharingOverview.cpp",
 		])
 
 	env.Append(UNITTEST_SOURCES = [
diff --git a/Swift/Controllers/ScreenSharing/ScreenSharingController.cpp b/Swift/Controllers/ScreenSharing/ScreenSharingController.cpp
index fd3357d..b932765 100644
--- a/Swift/Controllers/ScreenSharing/ScreenSharingController.cpp
+++ b/Swift/Controllers/ScreenSharing/ScreenSharingController.cpp
@@ -12,82 +12,118 @@
 #include <Swiften/ScreenSharing/Image.h>
 #include <Swiften/Network/TimerFactory.h>
 #include <Swiften/Network/Timer.h>
-#include "Swift/QtUI/ScreenSharing/QtDesktopScreenGrabber.h"
+#include "Swift/Controllers/ScreenSharing/DesktopScreenGrabber.h"
 #include "Swift/Controllers/UIInterfaces/RemoteScreenWindowFactory.h"
 #include "Swift/Controllers/UIInterfaces/RemoteScreenWindow.h"
+#include "Swift/Controllers/UIInterfaces/ChatWindow.h"
+#include "Swift/Controllers/Intl.h"
 
 #include <boost/bind.hpp>
 
 namespace Swift {
 
-ScreenSharingController::ScreenSharingController(ScreenSharingManager *screenSharingManager, RemoteScreenWindowFactory* remoteScreenViewerFactory, TimerFactory* timerFactory)
-	: screenSharingManager(screenSharingManager), remoteScreenWindowFactory(remoteScreenViewerFactory), remoteScreenWindow(0),
-	  grabTimer(timerFactory->createTimer(500)), screenGrabber(new QtDesktopScreenGrabber)
+ScreenSharingController::ScreenSharingController(ScreenSharingManager* screenSharingManager, TimerFactory* timerFactory, DesktopScreenGrabber* desktopScreenGrabber, const JID& to)
+	: screenGrabber(desktopScreenGrabber), grabTimer(timerFactory->createTimer(500)), remoteScreenWindowFactory(0),
+	  remoteScreenWindow(0), otherParty(to), incoming(false), chatWindow(0)
 {
-	screenSharingManager->onIncomingScreenSharing.connect(boost::bind(&ScreenSharingController::handleIncomingScreenSharing, this, _1));
-	grabTimer->onTick.connect(boost::bind(&ScreenSharingController::handleGrabTimerTick, this));
+	OutgoingScreenSharing::ref oss = screenSharingManager->createOutgoingScreenSharing(to);
+	if (oss) {
+		oss->onReady.connect(boost::bind(&ScreenSharingController::handleReady, this));
+		oss->onFinished.connect(boost::bind(&ScreenSharingController::handleFinished, this));
+		oss->onStateChange.connect(boost::bind(&ScreenSharingController::handleStateChange, this, _1));
+		const Image& image = screenGrabber->grab();
+		oss->start(image.width, image.height);
+		screenSharing = oss;
+	} else {
+		std::cerr << "Screen sharing not supported!" << std::endl;
+	}
+}
+
+ScreenSharingController::ScreenSharingController(boost::shared_ptr<IncomingScreenSharing> screenSharing, RemoteScreenWindowFactory* remoteScreenWindowFactory)
+	: screenGrabber(0), remoteScreenWindowFactory(remoteScreenWindowFactory), remoteScreenWindow(0),
+	  screenSharing(screenSharing), otherParty(screenSharing->getSender()), incoming(true), chatWindow(0)
+{
+	screenSharing->onFinished.connect(boost::bind(&ScreenSharingController::handleFinished, this));
+	screenSharing->onStateChange.connect(boost::bind(&ScreenSharingController::handleStateChange, this, _1));
 }
 
 ScreenSharingController::~ScreenSharingController()
 {
-	grabTimer->onTick.disconnect(boost::bind(&ScreenSharingController::handleGrabTimerTick, this));
+	screenSharing->onStateChange.disconnect(boost::bind(&ScreenSharingController::handleStateChange, this, _1));
 	delete remoteScreenWindow;
 }
 
-boost::shared_ptr<OutgoingScreenSharing> ScreenSharingController::createOugoingScreenSharing(const JID& to)
+const JID& ScreenSharingController::getOtherParty() const
 {
-	if (!oss) {
-		oss = screenSharingManager->createOutgoingScreenSharing(to);
-		if (oss) {
-			oss->onReady.connect(boost::bind(&ScreenSharingController::handleOssReady, this));
-			oss->onFinished.connect(boost::bind(&ScreenSharingController::handleOutgoingFinished, this));
-			const Image& image = screenGrabber->grab();
-			oss->start(image.width, image.height);
+	return otherParty;
+}
+
+std::string ScreenSharingController::setChatWindow(ChatWindow* wnd, std::string nickname) {
+	chatWindow = wnd;
+	uiID = wnd->addScreenSharing((incoming ? nickname : QT_TRANSLATE_NOOP("", "me")), incoming);
+	return uiID;
+}
+
+void ScreenSharingController::accept()
+{
+	if (incoming) {
+		if (IncomingScreenSharing::ref iss = boost::dynamic_pointer_cast<IncomingScreenSharing>(screenSharing)) {
+			iss->accept();
+			remoteScreenWindow = remoteScreenWindowFactory->createRemoteScreenViewer(iss);
+			remoteScreenWindow->onStopRequest.connect(boost::bind(&ScreenSharingController::handleWindowStopRequest, this));
 		}
-		return oss;
 	}
-	return boost::shared_ptr<OutgoingScreenSharing>();
 }
 
-void ScreenSharingController::handleIncomingScreenSharing(boost::shared_ptr<IncomingScreenSharing> incomingScreenSharing)
+void ScreenSharingController::cancel()
 {
-	if (iss) {
-		incomingScreenSharing->cancel();
-	} else {
-		iss = incomingScreenSharing;
-		iss->accept();
-		iss->onFinished.connect(boost::bind(&ScreenSharingController::handleIncomingFinished, this));
-		remoteScreenWindow = remoteScreenWindowFactory->createRemoteScreenViewer(iss);
-//		onNewIncomingScreenSharing(iss);
-	}
+	screenSharing->cancel();
+}
+
+void ScreenSharingController::stop()
+{
+	screenSharing->stop();
 }
 
 void ScreenSharingController::handleGrabTimerTick()
 {
-	if (oss) {
-		grabTimer->start();
-		oss->addImage(screenGrabber->grab());
+	if (screenSharing) {
+		if (OutgoingScreenSharing::ref oss = boost::dynamic_pointer_cast<OutgoingScreenSharing>(screenSharing)) {
+			grabTimer->start();
+			oss->addImage(screenGrabber->grab());
+		}
+	} else {
+		grabTimer->onTick.disconnect(boost::bind(&ScreenSharingController::handleGrabTimerTick, this));
 	}
 }
 
-void ScreenSharingController::handleOssReady()
+void ScreenSharingController::handleReady()
 {
-	handleGrabTimerTick();
+	if (OutgoingScreenSharing::ref oss = boost::dynamic_pointer_cast<OutgoingScreenSharing>(screenSharing)) {
+		oss->onReady.disconnect(boost::bind(&ScreenSharingController::handleReady, this));
+		grabTimer->onTick.connect(boost::bind(&ScreenSharingController::handleGrabTimerTick, this));
+		handleGrabTimerTick();
+	}
 }
 
-void ScreenSharingController::handleIncomingFinished()
+void ScreenSharingController::handleFinished()
 {
-	iss->onFinished.disconnect(boost::bind(&ScreenSharingController::handleIncomingFinished, this));
-	iss.reset();
+	screenSharing->onFinished.disconnect(boost::bind(&ScreenSharingController::handleFinished, this));
+	screenSharing.reset();
 	delete remoteScreenWindow;
 	remoteScreenWindow = 0;
 }
 
-void ScreenSharingController::handleOutgoingFinished()
+void ScreenSharingController::handleStateChange(ScreenSharing::SCState state)
+{
+	if (chatWindow)
+		chatWindow->setScreenSharingStatus(uiID, state);
+}
+
+void ScreenSharingController::handleWindowStopRequest()
 {
-	oss->onReady.disconnect(boost::bind(&ScreenSharingController::handleOssReady, this));
-	oss->onFinished.disconnect(boost::bind(&ScreenSharingController::handleOutgoingFinished, this));
-	oss.reset();
+	remoteScreenWindow->onStopRequest.disconnect(boost::bind(&ScreenSharingController::handleWindowStopRequest, this));
+	screenSharing->stop();
 }
 
 }
diff --git a/Swift/Controllers/ScreenSharing/ScreenSharingController.h b/Swift/Controllers/ScreenSharing/ScreenSharingController.h
index 6bae132..11b4504 100644
--- a/Swift/Controllers/ScreenSharing/ScreenSharingController.h
+++ b/Swift/Controllers/ScreenSharing/ScreenSharingController.h
@@ -6,46 +6,53 @@
 
 #pragma once
 
-#include <Swiften/Base/boost_bsignals.h>
+#include <Swiften/JID/JID.h>
+#include <Swiften/ScreenSharing/ScreenSharing.h>
 
 #include <boost/shared_ptr.hpp>
 
 namespace Swift {
+	class ScreenSharing;
 	class ScreenSharingManager;
 	class IncomingScreenSharing;
-	class OutgoingScreenSharing;
 	class Timer;
 	class TimerFactory;
 	class DesktopScreenGrabber;
 	class RemoteScreenWindowFactory;
 	class RemoteScreenWindow;
-	class JID;
+	class ChatWindow;
 
 	class ScreenSharingController {
 		public:
-			ScreenSharingController(ScreenSharingManager* screenSharingManager, RemoteScreenWindowFactory* remoteScreenWindowFactory, TimerFactory* timerFactory);
+			ScreenSharingController(ScreenSharingManager* screenSharingManager, TimerFactory* timerFactory, DesktopScreenGrabber* desktopScreenGrabber, const JID& to);
+			ScreenSharingController(boost::shared_ptr<IncomingScreenSharing> screenSharing, RemoteScreenWindowFactory* remoteScreenWindowFactory);
 			~ScreenSharingController();
 
-			boost::shared_ptr<OutgoingScreenSharing> createOugoingScreenSharing(const JID& to);
+			const JID& getOtherParty() const;
 
-		public:
-			boost::signal<void (boost::shared_ptr<IncomingScreenSharing>)> onNewIncomingScreenSharing;
+			std::string setChatWindow(ChatWindow *wnd, std::string nickname);
+
+			void accept();
+			void cancel();
+			void stop();
 
 		private:
-			void handleIncomingScreenSharing(boost::shared_ptr<IncomingScreenSharing> incomingScreenSharing);
 			void handleGrabTimerTick();
-			void handleOssReady();
-			void handleIncomingFinished();
-			void handleOutgoingFinished();
+			void handleReady();
+			void handleFinished();
+			void handleStateChange(ScreenSharing::SCState state);
+			void handleWindowStopRequest();
 
 		private:
-			ScreenSharingManager* screenSharingManager;
+			DesktopScreenGrabber* screenGrabber;
+			boost::shared_ptr<Timer> grabTimer;
 			RemoteScreenWindowFactory* remoteScreenWindowFactory;
-
 			RemoteScreenWindow* remoteScreenWindow;
-			boost::shared_ptr<Timer> grabTimer;
-			DesktopScreenGrabber* screenGrabber;
-			boost::shared_ptr<IncomingScreenSharing> iss;
-			boost::shared_ptr<OutgoingScreenSharing> oss;
+
+			boost::shared_ptr<ScreenSharing> screenSharing;
+			JID otherParty;
+			bool incoming;
+			std::string uiID;
+			ChatWindow* chatWindow;
 	};
 }
diff --git a/Swift/Controllers/ScreenSharing/ScreenSharingOverview.cpp b/Swift/Controllers/ScreenSharing/ScreenSharingOverview.cpp
new file mode 100644
index 0000000..91f75b9
--- /dev/null
+++ b/Swift/Controllers/ScreenSharing/ScreenSharingOverview.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "ScreenSharingOverview.h"
+
+#include "Swift/QtUI/ScreenSharing/QtDesktopScreenGrabber.h"
+#include "Swift/Controllers/ScreenSharing/ScreenSharingController.h"
+#include <Swiften/ScreenSharing/ScreenSharingManager.h>
+
+#include <boost/bind.hpp>
+
+namespace Swift {
+
+ScreenSharingOverview::ScreenSharingOverview(ScreenSharingManager *screenSharingManager, RemoteScreenWindowFactory* remoteScreenViewerFactory, TimerFactory* timerFactory)
+	: screenSharingManager(screenSharingManager), remoteScreenWindowFactory(remoteScreenViewerFactory), timerFactory(timerFactory),
+	  screenGrabber(new QtDesktopScreenGrabber)
+{
+	screenSharingManager->onIncomingScreenSharing.connect(boost::bind(&ScreenSharingOverview::handleIncomingScreenSharing, this, _1));
+}
+
+ScreenSharingOverview::~ScreenSharingOverview()
+{
+	screenSharingManager->onIncomingScreenSharing.disconnect(boost::bind(&ScreenSharingOverview::handleIncomingScreenSharing, this, _1));
+}
+
+void ScreenSharingOverview::createOugoingScreenSharing(const JID& to)
+{
+	ScreenSharingController* ssc = new ScreenSharingController(screenSharingManager, timerFactory, screenGrabber, to);
+	controllers.push_back(ssc);
+	onNewScreenSharingController(ssc);
+}
+
+void ScreenSharingOverview::handleIncomingScreenSharing(boost::shared_ptr<IncomingScreenSharing> incomingScreenSharing)
+{
+	ScreenSharingController* ssc = new ScreenSharingController(incomingScreenSharing, remoteScreenWindowFactory);
+	controllers.push_back(ssc);
+	onNewScreenSharingController(ssc);
+}
+
+}
diff --git a/Swift/Controllers/ScreenSharing/ScreenSharingOverview.h b/Swift/Controllers/ScreenSharing/ScreenSharingOverview.h
new file mode 100644
index 0000000..b43a665
--- /dev/null
+++ b/Swift/Controllers/ScreenSharing/ScreenSharingOverview.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/boost_bsignals.h>
+
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+
+namespace Swift {
+	class ScreenSharingManager;
+	class ScreenSharingController;
+	class IncomingScreenSharing;
+	class TimerFactory;
+	class DesktopScreenGrabber;
+	class RemoteScreenWindowFactory;
+	class JID;
+
+	class ScreenSharingOverview {
+		public:
+			ScreenSharingOverview(ScreenSharingManager* screenSharingManager, RemoteScreenWindowFactory* remoteScreenWindowFactory, TimerFactory* timerFactory);
+			~ScreenSharingOverview();
+
+			void createOugoingScreenSharing(const JID& to);
+
+		public:
+			boost::signal<void (ScreenSharingController*)> onNewScreenSharingController;
+
+		private:
+			void handleIncomingScreenSharing(boost::shared_ptr<IncomingScreenSharing> incomingScreenSharing);
+
+		private:
+			ScreenSharingManager* screenSharingManager;
+			RemoteScreenWindowFactory* remoteScreenWindowFactory;
+			TimerFactory* timerFactory;
+
+			DesktopScreenGrabber* screenGrabber;
+			std::vector<ScreenSharingController*> controllers;
+	};
+}
diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h
index 5db1a54..d54f2aa 100644
--- a/Swift/Controllers/UIInterfaces/ChatWindow.h
+++ b/Swift/Controllers/UIInterfaces/ChatWindow.h
@@ -17,6 +17,7 @@
 #include <Swiften/Elements/ChatState.h>
 #include <Swiften/Elements/Form.h>
 #include <Swiften/Elements/MUCOccupant.h>
+#include <Swiften/ScreenSharing/ScreenSharing.h>
 
 
 namespace Swift {
@@ -59,6 +60,11 @@ namespace Swift {
 			virtual std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes) = 0;
 			virtual void setFileTransferProgress(std::string, const int percentageDone) = 0;
 			virtual void setFileTransferStatus(std::string, const FileTransferState state, const std::string& msg = "") = 0;
+
+			// Screen sharing related stuff
+			virtual std::string addScreenSharing(const std::string& senderName, bool incoming) = 0;
+			virtual void setScreenSharingStatus(std::string, const ScreenSharing::SCState state, const std::string& msg = "") = 0;
+
 			virtual void addMUCInvitation(const std::string& senderName, const JID& jid, const std::string& reason, const std::string& password, bool direct = true) = 0;
 
 			virtual std::string addWhiteboardRequest(bool senderIsSelf) = 0;
@@ -137,6 +143,11 @@ namespace Swift {
 			boost::signal<void (std::string /* id */, std::string /* path */)> onFileTransferAccept;
 			boost::signal<void (std::string /* path */)> onSendFileRequest;
 
+			// Screen sharing related
+			boost::signal<void (std::string /* id */)> onScreenSharingCancel;
+			boost::signal<void (std::string /* id */)> onScreenSharingStop;
+			boost::signal<void (std::string /* id */)> onScreenSharingAccept;
+
 			//Whiteboard related	
 			boost::signal<void ()> onWhiteboardSessionAccept;
 			boost::signal<void ()> onWhiteboardSessionCancel;
diff --git a/Swift/Controllers/UIInterfaces/RemoteScreenWindow.h b/Swift/Controllers/UIInterfaces/RemoteScreenWindow.h
index c31ca91..a5bdb36 100644
--- a/Swift/Controllers/UIInterfaces/RemoteScreenWindow.h
+++ b/Swift/Controllers/UIInterfaces/RemoteScreenWindow.h
@@ -6,6 +6,8 @@
 
 #pragma once
 
+#include <Swiften/Base/boost_bsignals.h>
+
 #include <boost/shared_ptr.hpp>
 
 namespace Swift {
@@ -18,6 +20,9 @@ namespace Swift {
 				: iss(incScreenSharing) {}
 			virtual ~RemoteScreenWindow() {}
 
+		public:
+			boost::signal<void ()> onStopRequest;
+
 		protected:
 			boost::shared_ptr<IncomingScreenSharing> iss;
 	};
diff --git a/Swift/QtUI/QtChatView.cpp b/Swift/QtUI/QtChatView.cpp
index 81820a3..25b786f 100644
--- a/Swift/QtUI/QtChatView.cpp
+++ b/Swift/QtUI/QtChatView.cpp
@@ -444,6 +444,48 @@ void QtChatView::setWhiteboardSessionStatus(QString id, const ChatWindow::Whiteb
 	divElement.setInnerXml(newInnerHTML);
 }
 
+void QtChatView::setScreenSharingStatus(QString id, ScreenSharing::SCState state, const QString& /*msg*/)
+{
+	QWebElement ftElement = findDivElementWithID(document_, id);
+	if (ftElement.isNull()) {
+		SWIFT_LOG(debug) << "Tried to access screen sharing UI via invalid id! id = " << Q2PSTRING(id) << std::endl;
+		return;
+	}
+
+	QString newInnerHTML = "";
+	if (state == ScreenSharing::WaitingForAccept) {
+		newInnerHTML =	tr("Waiting for other side to accept the sharing.") + "<br/>" +
+			QtChatWindow::buildChatWindowButton(tr("Cancel"), QtChatWindow::ButtonScreenSharingCancel, id);
+	}
+	if (state == ScreenSharing::Negotiating) {
+		newInnerHTML =	tr("Negotiating...") + "<br/>" +
+			QtChatWindow::buildChatWindowButton(tr("Cancel"), QtChatWindow::ButtonScreenSharingCancel, id);
+	}
+	if (state == ScreenSharing::Connecting) {
+		newInnerHTML =	tr("Connecting...") + "<br/>" +
+			QtChatWindow::buildChatWindowButton(tr("Cancel"), QtChatWindow::ButtonScreenSharingCancel, id);
+	}
+	if (state == ScreenSharing::BroadCasting) {
+		newInnerHTML =	tr("Broadcasting the desktop...") + "<br/>" +
+			QtChatWindow::buildChatWindowButton(tr("Terminate"), QtChatWindow::ButtonScreenSharingStop, id);
+	}
+	else if (state == ScreenSharing::Receiving) {
+		newInnerHTML =	tr("Receiving desktop from the other party...") + "<br/>" +
+			QtChatWindow::buildChatWindowButton(tr("Terminate"), QtChatWindow::ButtonScreenSharingStop, id);
+	}
+	else if (state == ScreenSharing::Canceled) {
+		newInnerHTML = tr("Sharing has been canceled!");
+	}
+	else if (state == ScreenSharing::Finished) {
+		newInnerHTML = tr("Sharing finished.");
+	}
+	else if (state == ScreenSharing::Failed) {
+		newInnerHTML = tr("Sharing failed.");
+	}
+
+	ftElement.setInnerXml(newInnerHTML);
+}
+
 void QtChatView::setMUCInvitationJoined(QString id) {
 	QWebElement divElement = findElementWithID(document_, "div", id);
 	QWebElement buttonElement = findElementWithID(divElement, "input", "mucinvite");
diff --git a/Swift/QtUI/QtChatView.h b/Swift/QtUI/QtChatView.h
index 9080808..403dec0 100644
--- a/Swift/QtUI/QtChatView.h
+++ b/Swift/QtUI/QtChatView.h
@@ -17,6 +17,7 @@
 #include "ChatSnippet.h"
 
 #include <Swift/Controllers/UIInterfaces/ChatWindow.h>
+#include <Swiften/ScreenSharing/ScreenSharing.h>
 
 class QWebPage;
 class QUrl;
@@ -43,7 +44,8 @@ namespace Swift {
 			QString getLastSentMessage();
 			void addToJSEnvironment(const QString&, QObject*);
 			void setFileTransferProgress(QString id, const int percentageDone);
-			void setFileTransferStatus(QString id, const ChatWindow::FileTransferState state, const QString& msg);
+			void setFileTransferStatus(QString id, const ChatWindow::FileTransferState state, const QString& /*msg*/);
+			void setScreenSharingStatus(QString id, ScreenSharing::SCState state, const QString& msg);
 			void setWhiteboardSessionStatus(QString id, const ChatWindow::WhiteboardSessionState state);
 			void setMUCInvitationJoined(QString id);
 			void showEmoticons(bool show);
diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp
index 314e36c..730195c 100644
--- a/Swift/QtUI/QtChatWindow.cpp
+++ b/Swift/QtUI/QtChatWindow.cpp
@@ -61,6 +61,9 @@ const QString QtChatWindow::ButtonFileTransferCancel = QString("filetransfer-can
 const QString QtChatWindow::ButtonFileTransferSetDescription = QString("filetransfer-setdescription");
 const QString QtChatWindow::ButtonFileTransferSendRequest = QString("filetransfer-sendrequest");
 const QString QtChatWindow::ButtonFileTransferAcceptRequest = QString("filetransfer-acceptrequest");
+const QString QtChatWindow::ButtonScreenSharingCancel = QString("screensharing-cancel");
+const QString QtChatWindow::ButtonScreenSharingStop = QString("screensharing-stop");
+const QString QtChatWindow::ButtonScreenSharingAcceptRequest = QString("screensharing-acceptrequest");
 const QString QtChatWindow::ButtonMUCInvite = QString("mucinvite");
 
 
@@ -685,6 +688,47 @@ void QtChatWindow::setWhiteboardSessionStatus(std::string id, const ChatWindow::
 	messageLog_->setWhiteboardSessionStatus(QString::fromStdString(id), state);
 }
 
+std::string QtChatWindow::addScreenSharing(const std::string& senderName, bool incoming)
+{
+	SWIFT_LOG(debug) << "addScreenSharing" << std::endl;
+	QString ss_id = QString("ft%1").arg(P2QSTRING(boost::lexical_cast<std::string>(idCounter_++)));
+
+	QString htmlString;
+	if (incoming) {
+		htmlString = P2QSTRING(senderName) + " shares his screen with you" + "<br/>" +
+			"<div id='" + ss_id + "'>" +
+				buildChatWindowButton(tr("Accept"), ButtonScreenSharingAcceptRequest, ss_id) +
+				buildChatWindowButton(tr("Cancel"), ButtonScreenSharingCancel, ss_id) +
+			"</div>";
+	} else {
+		htmlString = tr("Sharing screen with ") + contact_ + "<br/>" +
+			"<div id='" + ss_id + "'>" +
+				buildChatWindowButton(tr("Cancel"), ButtonScreenSharingCancel, ss_id) +
+			"</div>";
+	}
+
+	bool appendToPrevious = appendToPreviousCheck(PreviousMessageWasFileTransfer, senderName, !incoming);
+	if (lastLineTracker_.getShouldMoveLastLine()) {
+		/* should this be queued? */
+		messageLog_->addLastSeenLine();
+		/* if the line is added we should break the snippet */
+		appendToPrevious = false;
+	}
+	QString qAvatarPath = "qrc:/icons/avatar.png";
+	std::string id = "ssmessage" + boost::lexical_cast<std::string>(idCounter_++);
+	messageLog_->addMessage(boost::shared_ptr<ChatSnippet>(new MessageSnippet(htmlString, Qt::escape(P2QSTRING(senderName)), B2QDATE(boost::posix_time::second_clock::local_time()), qAvatarPath, !incoming, appendToPrevious, theme_, P2QSTRING(id))));
+
+	previousMessageWasSelf_ = !incoming;
+	previousSenderName_ = P2QSTRING(senderName);
+	previousMessageKind_ = PreviousMessageWasFileTransfer;
+	return Q2PSTRING(ss_id);
+}
+
+void QtChatWindow::setScreenSharingStatus(std::string id, const ScreenSharing::SCState state, const std::string& msg)
+{
+	messageLog_->setScreenSharingStatus(QString::fromStdString(id), state, QString::fromStdString(msg));
+}
+
 void QtChatWindow::handleHTMLButtonClicked(QString id, QString encodedArgument1, QString encodedArgument2, QString encodedArgument3) {
 	QString arg1 = decodeButtonArgument(encodedArgument1);
 	QString arg2 = decodeButtonArgument(encodedArgument2);
@@ -731,6 +775,15 @@ void QtChatWindow::handleHTMLButtonClicked(QString id, QString encodedArgument1,
 		QString id = arg1;
 		onWhiteboardWindowShow();
 	}
+	else if (id.startsWith(ButtonScreenSharingAcceptRequest)) {
+		onScreenSharingAccept(Q2PSTRING(arg1));
+	}
+	else if (id.startsWith(ButtonScreenSharingCancel)) {
+		onScreenSharingCancel(Q2PSTRING(arg1));
+	}
+	else if (id.startsWith(ButtonScreenSharingStop)) {
+		onScreenSharingStop(Q2PSTRING(arg1));
+	}
 	else if (id.startsWith(ButtonMUCInvite)) {
 		QString roomJID = arg1;
 		QString password = arg2;
diff --git a/Swift/QtUI/QtChatWindow.h b/Swift/QtUI/QtChatWindow.h
index 3416b42..d802bf9 100644
--- a/Swift/QtUI/QtChatWindow.h
+++ b/Swift/QtUI/QtChatWindow.h
@@ -80,6 +80,9 @@ namespace Swift {
 			static const QString ButtonFileTransferSetDescription;
 			static const QString ButtonFileTransferSendRequest;
 			static const QString ButtonFileTransferAcceptRequest;
+			static const QString ButtonScreenSharingCancel;
+			static const QString ButtonScreenSharingStop;
+			static const QString ButtonScreenSharingAcceptRequest;
 			static const QString ButtonMUCInvite;
 
 		public:
@@ -96,6 +99,10 @@ namespace Swift {
 			std::string addFileTransfer(const std::string& senderName, bool senderIsSelf, const std::string& filename, const boost::uintmax_t sizeInBytes);
 			void setFileTransferProgress(std::string id, const int percentageDone);
 			void setFileTransferStatus(std::string id, const FileTransferState state, const std::string& msg);
+
+			// Screen sharing related stuff
+			virtual std::string addScreenSharing(const std::string& senderName, bool incoming);
+			virtual void setScreenSharingStatus(std::string id, const ScreenSharing::SCState state, const std::string& msg = "");
 			
 			std::string addWhiteboardRequest(bool senderIsSelf);
 			void setWhiteboardSessionStatus(std::string id, const ChatWindow::WhiteboardSessionState state);
diff --git a/Swift/QtUI/ScreenSharing/QtRemoteScreenWindow.cpp b/Swift/QtUI/ScreenSharing/QtRemoteScreenWindow.cpp
index e6cd291..a1f1a88 100644
--- a/Swift/QtUI/ScreenSharing/QtRemoteScreenWindow.cpp
+++ b/Swift/QtUI/ScreenSharing/QtRemoteScreenWindow.cpp
@@ -8,15 +8,22 @@
 #include "RemoteScreenViewerWidget.h"
 
 #include <QToolBar>
+#include <QVBoxLayout>
 
 #include <Swiften/ScreenSharing/IncomingScreenSharing.h>
 
 namespace Swift {
 
 QtRemoteScreenWindow::QtRemoteScreenWindow(boost::shared_ptr<IncomingScreenSharing> incScreenSharing, QWidget *parent)
-	: QMainWindow(parent), RemoteScreenWindow(incScreenSharing)
+	: QMainWindow(parent), RemoteScreenWindow(incScreenSharing), viewer(new RemoteScreenViewerWidget(iss))
 {
-	setCentralWidget(new RemoteScreenViewerWidget(iss));
+	QVBoxLayout* centralLayout = new QVBoxLayout;
+	centralLayout->addWidget(viewer);
+
+	QWidget* central = new QWidget(this);
+	central->setLayout(centralLayout);
+
+	setCentralWidget(central);
 
 	controlToolBar = addToolBar(tr("Control"));
 	closeAction = controlToolBar->addAction(QIcon::fromTheme("window-close"), tr("&Terminate session"), this, SLOT(handleCloseTriggered()));
@@ -28,7 +35,7 @@ QtRemoteScreenWindow::~QtRemoteScreenWindow()
 
 void QtRemoteScreenWindow::handleCloseTriggered()
 {
-	iss->stop();
+	onStopRequest();
 }
 
 }
diff --git a/Swift/QtUI/ScreenSharing/QtRemoteScreenWindow.h b/Swift/QtUI/ScreenSharing/QtRemoteScreenWindow.h
index 00ac803..d6c783a 100644
--- a/Swift/QtUI/ScreenSharing/QtRemoteScreenWindow.h
+++ b/Swift/QtUI/ScreenSharing/QtRemoteScreenWindow.h
@@ -13,6 +13,7 @@
 class QToolBar;
 
 namespace Swift {
+	class RemoteScreenViewerWidget;
 
 	class QtRemoteScreenWindow : public QMainWindow, public RemoteScreenWindow {
 			Q_OBJECT
@@ -25,6 +26,7 @@ namespace Swift {
 			void handleCloseTriggered();
 
 		private:
+			RemoteScreenViewerWidget* viewer;
 			QAction* closeAction;
 			QToolBar* controlToolBar;
 	};
diff --git a/Swift/QtUI/ScreenSharing/RemoteScreenViewerWidget.cpp b/Swift/QtUI/ScreenSharing/RemoteScreenViewerWidget.cpp
index f601f1b..7bb3f26 100644
--- a/Swift/QtUI/ScreenSharing/RemoteScreenViewerWidget.cpp
+++ b/Swift/QtUI/ScreenSharing/RemoteScreenViewerWidget.cpp
@@ -18,7 +18,7 @@
 namespace Swift {
 
 RemoteScreenViewerWidget::RemoteScreenViewerWidget(boost::shared_ptr<IncomingScreenSharing> incScreenSharing, QWidget *parent) :
-	QWidget(parent), iss(incScreenSharing)
+	QFrame(parent), iss(incScreenSharing)
 {
 	iss->onNewImageReceived.connect(boost::bind(&RemoteScreenViewerWidget::handleNewImageReceived, this, _1));
 }
@@ -28,10 +28,11 @@ RemoteScreenViewerWidget::~RemoteScreenViewerWidget()
 	iss->onNewImageReceived.disconnect(boost::bind(&RemoteScreenViewerWidget::handleNewImageReceived, this, _1));
 }
 
-void RemoteScreenViewerWidget::paintEvent(QPaintEvent *)
+void RemoteScreenViewerWidget::paintEvent(QPaintEvent* event)
 {
-	QPainter painter(this);
+	QFrame::paintEvent(event);
 	if (!pixmap.isNull()) {
+		QPainter painter(this);
 		painter.translate(geometry().center());
 		painter.drawPixmap(-pixmap.rect().center(), pixmap);
 	}
@@ -39,15 +40,20 @@ void RemoteScreenViewerWidget::paintEvent(QPaintEvent *)
 
 void RemoteScreenViewerWidget::resizeEvent(QResizeEvent *event)
 {
-	if (!pixmap.isNull())
-		pixmap = pixmap.scaled(event->size(), Qt::KeepAspectRatio);
-	QWidget::resizeEvent(event);
+	if (!pixmap.isNull()) {
+		int frameWidth2 = frameWidth() * 2;
+		QSize borders(frameWidth2, frameWidth2);
+		pixmap = pixmap.scaled(event->size() - borders, Qt::KeepAspectRatio);
+	}
+	QFrame::resizeEvent(event);
 }
 
 void RemoteScreenViewerWidget::handleNewImageReceived(const Image& image)
 {
 	QImage qImg(image.data.data(), image.width, image.height, QImage::Format_RGB888);
-	pixmap = QPixmap::fromImage(qImg).scaled(size(), Qt::KeepAspectRatio);
+	int frameWidth2 = frameWidth() * 2;
+	QSize borders(frameWidth2, frameWidth2);
+	pixmap = QPixmap::fromImage(qImg).scaled(size() - borders, Qt::KeepAspectRatio);
 	update();
 }
 
diff --git a/Swift/QtUI/ScreenSharing/RemoteScreenViewerWidget.h b/Swift/QtUI/ScreenSharing/RemoteScreenViewerWidget.h
index 622bd26..c074e9f 100644
--- a/Swift/QtUI/ScreenSharing/RemoteScreenViewerWidget.h
+++ b/Swift/QtUI/ScreenSharing/RemoteScreenViewerWidget.h
@@ -6,7 +6,7 @@
 
 #pragma once
 
-#include <QWidget>
+#include <QFrame>
 
 #include <boost/shared_ptr.hpp>
 
@@ -14,15 +14,15 @@ namespace Swift {
 	class IncomingScreenSharing;
 	class Image;
 
-	class RemoteScreenViewerWidget : public QWidget {
+	class RemoteScreenViewerWidget : public QFrame {
 			Q_OBJECT
 		public:
 			RemoteScreenViewerWidget(boost::shared_ptr<IncomingScreenSharing> incScreenSharing, QWidget *parent = 0);
 			~RemoteScreenViewerWidget();
 
 		protected:
-			void paintEvent(QPaintEvent *);
-			void resizeEvent(QResizeEvent *event);
+			void paintEvent(QPaintEvent* event);
+			void resizeEvent(QResizeEvent* event);
 
 		private:
 			void handleNewImageReceived(const Image& image);
diff --git a/Swiften/ScreenSharing/IncomingScreenSharing.cpp b/Swiften/ScreenSharing/IncomingScreenSharing.cpp
index bbbfbad..15574c4 100644
--- a/Swiften/ScreenSharing/IncomingScreenSharing.cpp
+++ b/Swiften/ScreenSharing/IncomingScreenSharing.cpp
@@ -91,6 +91,7 @@ JingleContentID IncomingScreenSharing::getContentID() const
 
 void IncomingScreenSharing::hangleNewImageDecoded(const Image& image)
 {
+	onStateChange(ScreenSharing::Receiving);
 	onNewImageReceived(image);
 }
 
diff --git a/Swiften/ScreenSharing/OutgoingScreenSharing.cpp b/Swiften/ScreenSharing/OutgoingScreenSharing.cpp
index 005e204..7cea50e 100644
--- a/Swiften/ScreenSharing/OutgoingScreenSharing.cpp
+++ b/Swiften/ScreenSharing/OutgoingScreenSharing.cpp
@@ -132,6 +132,7 @@ void OutgoingScreenSharing::startRTPSession()
 		encoder = new VP8Encoder(packetizer, width, height);
 		packetizer->onNewPayloadReady.connect(boost::bind(&OutgoingScreenSharing::handleNewPayloadReady, this, _1, _2));
 		onReady();
+		onStateChange(ScreenSharing::BroadCasting);
 	}
 }
 
-- 
cgit v0.10.2-6-g49f6