From 9f311766da4be647acd89ff0ba1e54e813256968 Mon Sep 17 00:00:00 2001
From: Craig Watson <craig@watsons.ch>
Date: Fri, 20 Nov 2015 16:59:08 +0100
Subject: [PATCH 1/4] fixed keyboard switching on Mac OS

---
 src/frameworks/UBPlatformUtils_mac.mm | 32 ++++++++++++++++-----------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/src/frameworks/UBPlatformUtils_mac.mm b/src/frameworks/UBPlatformUtils_mac.mm
index b2623080..531e6fd0 100644
--- a/src/frameworks/UBPlatformUtils_mac.mm
+++ b/src/frameworks/UBPlatformUtils_mac.mm
@@ -533,29 +533,35 @@ QString UBPlatformUtils::urlFromClipboard()
 
 void UBPlatformUtils::SetMacLocaleByIdentifier(const QString& id)
 {
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    @autoreleasepool {
+        // convert id from QString to CFString
+        // TODO: clean this up
+        const QByteArray utf8 = id.toUtf8();
+        const char* cString = utf8.constData();
+        NSString * ns = [[NSString alloc] initWithUTF8String:cString];
 
-    const char * strName = id.toLatin1().data();
+        CFStringRef iName = (__bridge CFStringRef)ns;
 
-    CFStringRef iName = CFStringCreateWithCString(NULL, strName, kCFStringEncodingISOLatin1 );
 
 
-    CFStringRef keys[] = { kTISPropertyInputSourceCategory, kTISPropertyInputSourceID };
-    CFStringRef values[] = { kTISCategoryKeyboardInputSource, iName };
-    CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, 2, NULL, NULL);
+        CFStringRef keys[] = { kTISPropertyInputSourceID };
+        CFStringRef values[] = { iName };
+        CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, 1, NULL, NULL);
 
-    // get list of current enabled keyboard layouts. dict filters the list
-    CFArrayRef kbds = TISCreateInputSourceList(dict, true);
-    if (kbds!=NULL)
-    {
-        if (CFArrayGetCount(kbds)!=0)
-        {
+        // get list of current enabled keyboard layouts. dict filters the list
+        // false specifies that we search only through the active input sources
+        CFArrayRef kbds = TISCreateInputSourceList(dict, false);
+
+        if (kbds && CFArrayGetCount(kbds) == 0)
+            // if not found in the active sources, we search again through all sources installed
+            kbds = TISCreateInputSourceList(dict, true);
+
+        if (kbds && CFArrayGetCount(kbds)!=0) {
             TISInputSourceRef klRef =  (TISInputSourceRef)CFArrayGetValueAtIndex(kbds, 0);
             if (klRef!=NULL)
                 TISSelectInputSource(klRef);
         }
     }
-    [pool drain];
 }
 
 /**

From 007a1e1286ad82b785516357134a8ce48621a7b2 Mon Sep 17 00:00:00 2001
From: Craig Watson <craig@watsons.ch>
Date: Mon, 23 Nov 2015 14:36:43 +0100
Subject: [PATCH 2/4] Cleaned up UBGraphicsMediaItem*

- Removed commented out obsolete code that had been added
- Removed objects that were never used (mAudioOutput, audioFormat etc)
- Re-made changes that had been reverted since commit cdb5633
---
 src/domain/UBGraphicsMediaItem.cpp         | 50 +++-------------------
 src/domain/UBGraphicsMediaItem.h           | 16 -------
 src/domain/UBGraphicsMediaItemDelegate.cpp |  2 +-
 3 files changed, 7 insertions(+), 61 deletions(-)

diff --git a/src/domain/UBGraphicsMediaItem.cpp b/src/domain/UBGraphicsMediaItem.cpp
index 8ae95aec..7d6edabc 100644
--- a/src/domain/UBGraphicsMediaItem.cpp
+++ b/src/domain/UBGraphicsMediaItem.cpp
@@ -50,13 +50,8 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte
     update();
 
 
-    //mMediaObject = new Phonon::MediaObject(this);
     mMediaObject = new QMediaPlayer(this);
 
-    //playlist = new QMediaPlaylist;
-    //mMediaObject->setPlaylist(playlist);
-
-
     QString mediaPath = pMediaFileUrl.toString();
     if ("" == mediaPath)
         mediaPath = pMediaFileUrl.toLocalFile();
@@ -65,50 +60,27 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte
     {
         mMediaType = mediaType_Video;
 
-        //mAudioOutput = new Phonon::AudioOutput(Phonon::VideoCategory, this);
-        QAudioFormat format;  // to define
-        format.setByteOrder(QAudioFormat::LittleEndian);
-        format.setSampleType(QAudioFormat::UnSignedInt);
-
-        //mAudioOutput = new QAudioOutput(format, this);
-        mAudioOutput = new QMediaPlayer;
+        mMediaObject->setNotifyInterval(50);
 
-        //mMediaObject->setTickInterval(50);
-        mMediaObject->setPosition(50);
-
-        //mVideoWidget = new Phonon::VideoWidget(); // owned and destructed by the scene ...
         mVideoWidget = new QVideoWidget(); // owned and destructed by the scene ...
 
-        //Phonon::createPath(mMediaObject, mVideoWidget);
         mMediaObject->setVideoOutput(mVideoWidget);
 
         if(mVideoWidget->sizeHint() == QSize(1,1)){
             mVideoWidget->resize(320,240);
         }
 
-       //mVideoWidget->setMinimumSize(140,26);
         mVideoWidget->setMinimumSize(320,240);
 
         haveLinkedImage = true;
 
 
-        // DEBUGGING VIDEO
-        //*****************
-        qDebug() << "UBGraphicsMediaItem.cpp:" << mVideoWidget << "setMinimumSize(140,26)" ;
     }
     else if (mediaPath.toLower().contains("audios"))
     {
         mMediaType = mediaType_Audio;
 
-        QAudioFormat format;
-        format.setByteOrder(QAudioFormat::LittleEndian);
-        format.setSampleType(QAudioFormat::UnSignedInt);
-
-       // mAudioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
-        //mAudioOutput = new QMediaPlayer(format, this);
-        mAudioOutput = new QMediaPlayer;
-
-        //mMediaObject->setTickInterval(1000);
+        mMediaObject->setNotifyInterval(1000);
         mAudioWidget = new QWidget();
         mAudioWidget->resize(320,26);
         mAudioWidget->setMinimumSize(150,26);
@@ -116,10 +88,6 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte
         haveLinkedImage = false;
     }
 
-    //Phonon::createPath(mMediaObject, mAudioOutput);
-    //mSource = Phonon::MediaSource(pMediaFileUrl);
-
-    //mMediaObject->setCurrentSource(mSource);
      mMediaObject->setMedia(pMediaFileUrl);
 
 
@@ -147,7 +115,7 @@ UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsIte
     setData(UBGraphicsItemData::itemLayerType, QVariant(itemLayerType::ObjectItem)); //Necessary to set if we want z value to be assigned correctly
 
     connect(Delegate(), SIGNAL(showOnDisplayChanged(bool)), this, SLOT(showOnDisplayChanged(bool)));
-    connect(mMediaObject, SIGNAL(hasVideoChanged(bool)), this, SLOT(hasMediaChanged(bool)));
+    connect(mMediaObject, SIGNAL(videoAvailableChanged(bool)), this, SLOT(hasMediaChanged(bool)));
 }
 
 
@@ -192,12 +160,8 @@ QVariant UBGraphicsMediaItem::itemChange(GraphicsItemChange change, const QVaria
                 absoluteMediaFilename = mMediaFileUrl.toLocalFile();
 
             if (absoluteMediaFilename.length() > 0)
-                //mMediaObject->setCurrentSource(QMediaSource(absoluteMediaFilename));
                   mMediaObject->setMedia(QUrl::fromLocalFile(absoluteMediaFilename));
 
-
-
-
         }
     }
 
@@ -230,7 +194,7 @@ void UBGraphicsMediaItem::toggleMute()
 void UBGraphicsMediaItem::setMute(bool bMute)
 {
     mMuted = bMute;
-    mAudioOutput->setMuted(mMuted);
+    mMediaObject->setMuted(mMuted);
     mMutedByUserAction = mMuted;
     sIsMutedByDefault = mMuted;
 }
@@ -240,7 +204,6 @@ void UBGraphicsMediaItem::hasMediaChanged(bool hasMedia)
 {
     if(hasMedia && mMediaObject->isSeekable())
     {
-        //mMediaObject->seek(mInitialPos);
         mMediaObject->setPosition(mInitialPos);
 
         UBGraphicsMediaItemDelegate *med = dynamic_cast<UBGraphicsMediaItemDelegate *>(Delegate());
@@ -268,12 +231,12 @@ void UBGraphicsMediaItem::showOnDisplayChanged(bool shown)
     if (!shown)
     {
         mMuted = true;
-        mAudioOutput->setMuted(mMuted);
+        mMediaObject->setMuted(mMuted);
     }
     else if (!mMutedByUserAction)
     {
         mMuted = false;
-        mAudioOutput->setMuted(mMuted);
+        mMediaObject->setMuted(mMuted);
     }
 }
 
@@ -357,7 +320,6 @@ void UBGraphicsMediaItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
             QPointF eventPos = mapFromScene( event->scenePos());
 
             QPointF translation = eventPos - mouseMovePos;
-            //translate(translation.x(), translation.y());
             setPos(translation.x(), translation.y());
         }
 
diff --git a/src/domain/UBGraphicsMediaItem.h b/src/domain/UBGraphicsMediaItem.h
index 31ea7175..a0e9bcda 100644
--- a/src/domain/UBGraphicsMediaItem.h
+++ b/src/domain/UBGraphicsMediaItem.h
@@ -30,9 +30,6 @@
 
 #include <QtWidgets/QGraphicsView>
 #include "UBGraphicsProxyWidget.h"
-//#include <phonon/AudioOutput>
-//#include <phonon/MediaObject>
-//#include <phonon/VideoWidget>
 
 #include <QAudioOutput>
 #include <QMediaObject>
@@ -73,9 +70,7 @@ public:
 
     virtual void mediaFileUrl(QUrl url){mMediaFileUrl=url;}
 
-    //Phonon::MediaObject* mediaObject() const
     QMediaPlayer* mediaObject() const
-
     {
         return mMediaObject;
     }
@@ -92,9 +87,7 @@ public:
         return mMuted;
     }
 
-   // Phonon::VideoWidget* videoWidget() const
     QVideoWidget* videoWidget() const
-
     {
         return mVideoWidget;
     }
@@ -129,17 +122,8 @@ protected:
     virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
     virtual void clearSource();
 
-    //Phonon::MediaObject *mMediaObject;
-    //Phonon::VideoWidget *mVideoWidget;
-    //Phonon::AudioOutput *mAudioOutput;
-    //Phonon::MediaSource mSource;
-
     QMediaPlayer *mMediaObject;
-    QMediaPlaylist *playlist;
     QVideoWidget *mVideoWidget;
-//    QAudioOutput *mAudioOutput;
-    QMediaPlayer *mAudioOutput;
-    QMediaService *mSource;
 
     QWidget *mAudioWidget;
 
diff --git a/src/domain/UBGraphicsMediaItemDelegate.cpp b/src/domain/UBGraphicsMediaItemDelegate.cpp
index 0c7c0683..2faeb9b8 100644
--- a/src/domain/UBGraphicsMediaItemDelegate.cpp
+++ b/src/domain/UBGraphicsMediaItemDelegate.cpp
@@ -252,7 +252,7 @@ void UBGraphicsMediaItemDelegate::togglePlayPause()
             media->play();
         }
 
-        else if (media->error())
+        if (media->error())
             qDebug() << "Error appeared." << media->errorString();
 
     }

From 5f9d6b9c699664d5be7e29e2335038d9ac7e5b20 Mon Sep 17 00:00:00 2001
From: Craig Watson <craig@watsons.ch>
Date: Mon, 23 Nov 2015 14:48:17 +0100
Subject: [PATCH 3/4] fixed compilation error on Linux due to a bad include

---
 src/frameworks/UBPlatformUtils_linux.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/frameworks/UBPlatformUtils_linux.cpp b/src/frameworks/UBPlatformUtils_linux.cpp
index 17011217..20a68d27 100644
--- a/src/frameworks/UBPlatformUtils_linux.cpp
+++ b/src/frameworks/UBPlatformUtils_linux.cpp
@@ -31,7 +31,6 @@
 #include <QApplication>
 
 #include <unistd.h>
-#include <X11/Xlib.h>
 #include <X11/keysym.h>
 
 #include "frameworks/UBFileSystemUtils.h"

From 20ebdf3cc5033dd1cd295798c102f8f0c6446b90 Mon Sep 17 00:00:00 2001
From: Craig Watson <craig@watsons.ch>
Date: Tue, 24 Nov 2015 14:09:30 +0100
Subject: [PATCH 4/4]  Hide dock and menubar on OSX;

Due to QWidget::showFullScreen having side-effects on OSX (setting the
dock and menubar to autohide, making it impossible to then set them as
hidden), the calls to that method were replaced with
UBPlatformUtils::showFullScreen(QWidget *). This function then calls
QWidget::showMaximized() on OSX, or QWidget::showFullScreen() on Linux
and Windows.

It is currently still impossible to switch smoothly between showing or
hiding the dock on OSX; current behaviour is to hide it all the time,
even in desktop mode.
---
 src/core/UBDisplayManager.cpp                 | 10 ++--
 src/desktop/UBCustomCaptureWindow.cpp         |  3 +-
 src/desktop/UBDesktopAnnotationController.cpp |  2 +-
 src/frameworks/UBPlatformUtils.h              |  1 +
 src/frameworks/UBPlatformUtils_linux.cpp      |  9 +++-
 src/frameworks/UBPlatformUtils_mac.mm         | 47 ++++++++++++++-----
 src/frameworks/UBPlatformUtils_win.cpp        |  7 +++
 7 files changed, 58 insertions(+), 21 deletions(-)

diff --git a/src/core/UBDisplayManager.cpp b/src/core/UBDisplayManager.cpp
index 59e858af..21cb706d 100644
--- a/src/core/UBDisplayManager.cpp
+++ b/src/core/UBDisplayManager.cpp
@@ -158,7 +158,7 @@ void UBDisplayManager::setDisplayWidget(QWidget* pDisplayWidget)
         mDisplayWidget = pDisplayWidget;
         mDisplayWidget->setGeometry(mDesktop->screenGeometry(mDisplayScreenIndex));
         if (UBSettings::settings()->appUseMultiscreen->get().toBool())
-            mDisplayWidget->showFullScreen();
+            UBPlatformUtils::showFullScreen(mDisplayWidget);
     }
 }
 
@@ -209,14 +209,14 @@ void UBDisplayManager::positionScreens()
     {
         mControlWidget->hide();
         mControlWidget->setGeometry(mDesktop->screenGeometry(mControlScreenIndex));
-        mControlWidget->showFullScreen();
+        UBPlatformUtils::showFullScreen(mControlWidget);
     }
 
     if (mDisplayWidget && mDisplayScreenIndex > -1)
     {
         mDisplayWidget->hide();
         mDisplayWidget->setGeometry(mDesktop->screenGeometry(mDisplayScreenIndex));
-        mDisplayWidget->showFullScreen();
+        UBPlatformUtils::showFullScreen(mDisplayWidget);
     }
     else if(mDisplayWidget)
     {
@@ -234,7 +234,7 @@ void UBDisplayManager::positionScreens()
         {
             QWidget* previous = mPreviousDisplayWidgets.at(psi);
             previous->setGeometry(mDesktop->screenGeometry(mPreviousScreenIndexes.at(psi)));
-            previous->showFullScreen();
+            UBPlatformUtils::showFullScreen(previous);
         }
     }
 
@@ -280,7 +280,7 @@ void UBDisplayManager::blackout()
 
     foreach(UBBlackoutWidget *blackoutWidget, mBlackoutWidgets)
     {
-        blackoutWidget->showFullScreen();
+        UBPlatformUtils::showFullScreen(blackoutWidget);
     }
 }
 
diff --git a/src/desktop/UBCustomCaptureWindow.cpp b/src/desktop/UBCustomCaptureWindow.cpp
index 47eafdbe..36e8969b 100644
--- a/src/desktop/UBCustomCaptureWindow.cpp
+++ b/src/desktop/UBCustomCaptureWindow.cpp
@@ -30,6 +30,7 @@
 
 #include "UBCustomCaptureWindow.h"
 
+#include "frameworks/UBPlatformUtils.h"
 #include "gui/UBRubberBand.h"
 
 #include "core/memcheck.h"
@@ -74,7 +75,7 @@ int UBCustomCaptureWindow::execute(const QPixmap &pScreenPixmap)
     int currentScreen = desktop->screenNumber(QCursor::pos());
     setGeometry(desktop->screenGeometry(currentScreen));
 
-    showFullScreen();
+    UBPlatformUtils::showFullScreen(this);
     setWindowOpacity(1.0);
 
     return exec();
diff --git a/src/desktop/UBDesktopAnnotationController.cpp b/src/desktop/UBDesktopAnnotationController.cpp
index 330093fe..879b39e4 100644
--- a/src/desktop/UBDesktopAnnotationController.cpp
+++ b/src/desktop/UBDesktopAnnotationController.cpp
@@ -332,7 +332,7 @@ void UBDesktopAnnotationController::showWindow()
     UBDrawingController::drawingController()->setStylusTool(mDesktopStylusTool);
 
 #ifndef Q_OS_LINUX
-    mTransparentDrawingView->showFullScreen();
+    UBPlatformUtils::showFullScreen(mTransparentDrawingView);
 #else
     // this is necessary to avoid unity to hide the panels
     mTransparentDrawingView->show();
diff --git a/src/frameworks/UBPlatformUtils.h b/src/frameworks/UBPlatformUtils.h
index e0b3f4ff..0b28c7dd 100644
--- a/src/frameworks/UBPlatformUtils.h
+++ b/src/frameworks/UBPlatformUtils.h
@@ -204,6 +204,7 @@ public:
         static QString urlFromClipboard();
         static QStringList availableTranslations();
         static void setFrontProcess();
+        static void showFullScreen(QWidget * pWidget);
 
 #ifdef Q_OS_OSX
         static void SetMacLocaleByIdentifier(const QString& id);
diff --git a/src/frameworks/UBPlatformUtils_linux.cpp b/src/frameworks/UBPlatformUtils_linux.cpp
index 20a68d27..d4b4f690 100644
--- a/src/frameworks/UBPlatformUtils_linux.cpp
+++ b/src/frameworks/UBPlatformUtils_linux.cpp
@@ -429,7 +429,14 @@ QString UBPlatformUtils::urlFromClipboard()
     return qsRet;
 }
 
-
 void UBPlatformUtils::setFrontProcess()
 {
+    // not used in Linux
+}
+
+
+void UBPlatformUtils::showFullScreen(QWidget *pWidget)
+{
+    pWidget->showFullScreen();
 }
+
diff --git a/src/frameworks/UBPlatformUtils_mac.mm b/src/frameworks/UBPlatformUtils_mac.mm
index 531e6fd0..17b87548 100644
--- a/src/frameworks/UBPlatformUtils_mac.mm
+++ b/src/frameworks/UBPlatformUtils_mac.mm
@@ -65,7 +65,7 @@ void UBPlatformUtils::init()
 
     //originalSetSystemUIMode = APEPatchCreate((const void *)SetSystemUIMode, (const void *)emptySetSystemUIMode);
 
-    setDesktopMode(false);
+    //setDesktopMode(false);
 
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
@@ -93,20 +93,24 @@ void UBPlatformUtils::init()
 
 
 void UBPlatformUtils::setDesktopMode(bool desktop)
-{ /*
-#ifndef OS_NEWER_THAN_OR_EQUAL_TO_1010
-    //OSStatus (*functor)(SystemUIMode, SystemUIOptions) = (OSStatus (*)(SystemUIMode, SystemUIOptions))originalSetSystemUIMode;
+{
 
-    if (desktop)
-    {
-        functor(kUIModeNormal, 0);
+    //qDebug() << "setDesktopMode called. desktop = " << desktop;
+
+    @try {
+        // temporarily disabled due to bug: when switching to desktop mode (and calling this),
+        // openboard switches right back to the board mode. clicking again on desktop mode works.
+        /*if (desktop) {
+            [NSApp setPresentationOptions:NSApplicationPresentationAutoHideMenuBar | NSApplicationPresentationAutoHideDock];
+        }
+        else*/
+            [NSApp setPresentationOptions:NSApplicationPresentationHideMenuBar | NSApplicationPresentationHideDock];
     }
-    else
-    {
-        functor(kUIModeAllHidden, 0);
+
+    @catch(NSException * exception) {
+        qDebug() << "Error setting presentation options";
     }
-#endif
-*/
+
 }
 
 
@@ -574,6 +578,23 @@ void UBPlatformUtils::setFrontProcess()
     // activate the application, forcing focus on it
     [app activateWithOptions: NSApplicationActivateIgnoringOtherApps];
 
-    // other option:NSApplicationActivateAllWindows. This won't steal focus from another app, e.g
+    // other option: NSApplicationActivateAllWindows. This won't steal focus from another app, e.g
     // if the user is doing something else while waiting for OpenBoard to load
 }
+
+
+/**
+ * @brief Full-screen a QWidget. Specific behaviour is platform-dependent.
+ * @param pWidget the QWidget to maximize
+ */
+void UBPlatformUtils::showFullScreen(QWidget *pWidget)
+{
+    pWidget->showMaximized();
+
+    /* On OS X, we want to hide the Dock and menu bar (aka "kiosk mode"). Qt's default behaviour
+     * when full-screening a QWidget is to set the dock and menu bar to auto-hide.
+     * Since it is impossible to later set different presentation options (i.e Hide dock & menu bar)
+     * to NSApplication, we have to avoid calling QWidget::showFullScreen on OSX.
+    */
+}
+
diff --git a/src/frameworks/UBPlatformUtils_win.cpp b/src/frameworks/UBPlatformUtils_win.cpp
index ed698a39..1c1f453f 100644
--- a/src/frameworks/UBPlatformUtils_win.cpp
+++ b/src/frameworks/UBPlatformUtils_win.cpp
@@ -427,4 +427,11 @@ QString UBPlatformUtils::urlFromClipboard()
 
 void UBPlatformUtils::setFrontProcess()
 {
+    // not used in Windows
+}
+
+
+void UBPlatformUtils::showFullScreen(QWidget *pWidget)
+{
+    pWidget->showFullScreen();
 }