From c9d0c35dfb20ccac038954a8ad51690eda919fba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Wed, 25 Apr 2012 22:43:01 +0200
Subject: Clicking the OS X dock brings the app to the front.

Resolves: #501

diff --git a/Swift/QtUI/CocoaApplicationActivateHelper.h b/Swift/QtUI/CocoaApplicationActivateHelper.h
new file mode 100644
index 0000000..c831183
--- /dev/null
+++ b/Swift/QtUI/CocoaApplicationActivateHelper.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2012 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <QObject>
+
+namespace Swift {
+	/**
+	 * This class is here as a workaround for a bug in Qt.
+	 * See Case #501.
+	 */
+	class CocoaApplicationActivateHelper : public QObject {
+		public:
+			CocoaApplicationActivateHelper();
+			~CocoaApplicationActivateHelper();
+
+		private:
+			bool eventFilter(QObject* o, QEvent* e);
+
+		private:
+			class Private;
+			Private* p;
+	};
+}
diff --git a/Swift/QtUI/CocoaApplicationActivateHelper.mm b/Swift/QtUI/CocoaApplicationActivateHelper.mm
new file mode 100644
index 0000000..7c42380
--- /dev/null
+++ b/Swift/QtUI/CocoaApplicationActivateHelper.mm
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "CocoaApplicationActivateHelper.h"
+
+#include <boost/function.hpp>
+#include <Cocoa/Cocoa.h>
+#include <QApplication>
+
+@interface CocoaApplicationActivateHelperDelegate : NSObject {
+}
+- (void) handleActivate: (NSAppleEventDescriptor*) event withReply: (NSAppleEventDescriptor*) reply;
+@end
+
+@implementation CocoaApplicationActivateHelperDelegate
+- (void) handleActivate: (NSAppleEventDescriptor*) event withReply: (NSAppleEventDescriptor*) reply {
+	(void) event; (void) reply;
+	QApplication::postEvent(qApp, new QEvent(QEvent::ApplicationActivate));
+}
+@end
+
+namespace Swift {
+
+struct CocoaApplicationActivateHelper::Private {
+	CocoaApplicationActivateHelperDelegate* delegate;
+	bool initialized;
+};
+
+CocoaApplicationActivateHelper::CocoaApplicationActivateHelper() {
+	p = new Private();
+	p->delegate = [[CocoaApplicationActivateHelperDelegate alloc] init];
+	p->initialized = false;
+	qApp->installEventFilter(this);
+}
+
+CocoaApplicationActivateHelper::~CocoaApplicationActivateHelper() {
+	[[NSAppleEventManager sharedAppleEventManager] removeEventHandlerForEventClass:kCoreEventClass andEventID:kAEReopenApplication];
+	[p->delegate release];
+	delete p;
+}
+
+bool CocoaApplicationActivateHelper::eventFilter(QObject* object, QEvent* event) {
+	if (object == qApp && event->type() == QEvent::ApplicationActivate && !p->initialized) {
+		[[NSAppleEventManager sharedAppleEventManager] setEventHandler:p->delegate andSelector:@selector(handleActivate:withReply:) forEventClass:kCoreEventClass andEventID:kAEReopenApplication];
+		p->initialized = true;
+	}
+	return QObject::eventFilter(object, event);
+}
+
+
+}
\ No newline at end of file
diff --git a/Swift/QtUI/QtLoginWindow.cpp b/Swift/QtUI/QtLoginWindow.cpp
index e7cabf2..53a3be3 100644
--- a/Swift/QtUI/QtLoginWindow.cpp
+++ b/Swift/QtUI/QtLoginWindow.cpp
@@ -217,6 +217,13 @@ QtLoginWindow::QtLoginWindow(UIEventStream* uiEventStream, SettingsProvider* set
 		loginAutomatically_->setChecked(false);
 	}
 
+#ifdef SWIFTEN_PLATFORM_MACOSX
+	// Temporary workaround for case 501. Could be that this code is still
+	// needed when Qt provides a proper fix
+	qApp->installEventFilter(this);
+#endif
+
+
 	this->show();
 }
 
@@ -242,6 +249,15 @@ bool QtLoginWindow::eventFilter(QObject *obj, QEvent *event) {
 			return true;
 		}
 	}
+#ifdef SWIFTEN_PLATFORM_MACOSX
+	// Dock clicked
+	// Temporary workaround for case 501. Could be that this code is still
+	// needed when Qt provides a proper fix
+	if (obj == qApp && event->type() == QEvent::ApplicationActivate && !isVisible()) {
+		bringToFront();
+	}
+#endif
+
 	return QObject::eventFilter(obj, event);
 }
 
@@ -459,11 +475,9 @@ void QtLoginWindow::setMessage(const std::string& message) {
 	}
 }
 
-void QtLoginWindow::bringToFront() {
+void QtLoginWindow::toggleBringToFront() {
 	if (!isVisible()) {
-		window()->showNormal();
-		window()->raise();
-		window()->activateWindow();
+		bringToFront();
 	}
 	else {
 #ifndef Q_WS_MAC
@@ -473,6 +487,12 @@ void QtLoginWindow::bringToFront() {
 	}
 }
 
+void QtLoginWindow::bringToFront() {
+	window()->showNormal();
+	window()->raise();
+	window()->activateWindow();
+}
+
 void QtLoginWindow::hide() {
 	window()->hide();
 }
diff --git a/Swift/QtUI/QtLoginWindow.h b/Swift/QtUI/QtLoginWindow.h
index 1add2f4..8f50a35 100644
--- a/Swift/QtUI/QtLoginWindow.h
+++ b/Swift/QtUI/QtLoginWindow.h
@@ -66,6 +66,7 @@ namespace Swift {
 			void handleToggleNotifications(bool enabled);
 			void handleAbout();
 			void bringToFront();
+			void toggleBringToFront();
 			void handleUsernameTextChanged();
 			void resizeEvent(QResizeEvent* event);
 			void moveEvent(QMoveEvent* event);
diff --git a/Swift/QtUI/QtSwift.h b/Swift/QtUI/QtSwift.h
index 7a49fa7..d30ed7c 100644
--- a/Swift/QtUI/QtSwift.h
+++ b/Swift/QtUI/QtSwift.h
@@ -17,6 +17,7 @@
 #include "QtSettingsProvider.h"
 #if defined(SWIFTEN_PLATFORM_MACOSX)
 #include "SwifTools/Application/CocoaApplication.h"
+#include "CocoaApplicationActivateHelper.h"
 #endif
 #if defined(SWIFTEN_PLATFORM_WINDOWS)
 #include "WindowsNotifier.h"
@@ -83,6 +84,7 @@ namespace Swift {
 			ActualIdleDetector idleDetector_;
 #if defined(SWIFTEN_PLATFORM_MACOSX)
 			CocoaApplication cocoaApplication_;
+			CocoaApplicationActivateHelper cocoaApplicationActivateHelper_;
 #endif
 	};
 }
diff --git a/Swift/QtUI/QtUIFactory.cpp b/Swift/QtUI/QtUIFactory.cpp
index a8b693d..2a50592 100644
--- a/Swift/QtUI/QtUIFactory.cpp
+++ b/Swift/QtUI/QtUIFactory.cpp
@@ -64,7 +64,7 @@ LoginWindow* QtUIFactory::createLoginWindow(UIEventStream* eventStream) {
 	if (netbookSplitter) {
 		netbookSplitter->insertWidget(0, loginWindow);
 	}
-	connect(systemTray, SIGNAL(clicked()), loginWindow, SLOT(bringToFront()));
+	connect(systemTray, SIGNAL(clicked()), loginWindow, SLOT(toggleBringToFront()));
 
 #ifndef SWIFT_MOBILE
 	QVariant loginWindowGeometryVariant = qtOnlySettings->getQSettings()->value("loginWindowGeometry");
diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript
index ab832d6..68a0782 100644
--- a/Swift/QtUI/SConscript
+++ b/Swift/QtUI/SConscript
@@ -172,6 +172,9 @@ if env["PLATFORM"] == "posix" :
 			"QtDBUSURIHandler.cpp",
 	]
 
+if env["PLATFORM"] == "darwin" :
+	sources += ["CocoaApplicationActivateHelper.mm"]
+
 if env["PLATFORM"] == "darwin" or env["PLATFORM"] == "win32" :
   swiftProgram = myenv.Program("Swift", sources)
 else :
-- 
cgit v0.10.2-6-g49f6