Win7: add support for the taskbar's "oh, look, it's shiny" buttons. We need prettier...
authorGeoffroy Couprie <geal@videolan.org>
Wed, 19 Aug 2009 22:05:17 +0000 (00:05 +0200)
committerGeoffroy Couprie <geal@videolan.org>
Wed, 19 Aug 2009 22:09:33 +0000 (00:09 +0200)
modules/gui/qt4/main_interface.cpp
modules/gui/qt4/main_interface.hpp
modules/gui/qt4/qt4.cpp
modules/gui/qt4/util/qvlcapp.hpp

index a4f6da2..ea7d0cc 100644 (file)
 #include <QGroupBox>
 #include <QPushButton>
 
+#ifdef WIN32
+ #include <vlc_windows_interfaces.h>
+ #include <QBitmap>
+#endif
+
 #include <assert.h>
 
 #include <vlc_keys.h> /* Wheel event */
@@ -281,6 +286,84 @@ MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
     updateGeometry();
     resize( sizeHint() );
 
+#ifdef WIN32
+    /*Here is the code for the taskbar thumb buttons
+    FIXME:We need pretty buttons in 16x16 px that are handled correctly by masks in Qt
+    FIXME:the play button's picture doesn't changed to pause when clicked
+    */
+    OSVERSIONINFO winVer;
+    winVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+    if( GetVersionEx(&winVer) && winVer.dwMajorVersion > 5 && winVer.dwMajorVersion > 0 )
+    {
+        if(himl = ImageList_Create( 15, //cx
+                                    18, //cy
+                                    ILC_COLOR,//flags
+                                    4,//initial nb of images
+                                    0//nb of images that can be added
+                                    ))
+        {
+            QPixmap img   = QPixmap(":/toolbar/previous_b");
+            QPixmap img2  = QPixmap(":/toolbar/pause_b");
+            QPixmap img3  = QPixmap(":/toolbar/play_b");
+            QPixmap img4  = QPixmap(":/toolbar/next_b");
+            QBitmap mask  = img.createMaskFromColor(Qt::transparent);
+            QBitmap mask2 = img2.createMaskFromColor(Qt::transparent);
+            QBitmap mask3 = img3.createMaskFromColor(Qt::transparent);
+            QBitmap mask4 = img4.createMaskFromColor(Qt::transparent);
+
+            if(-1 == ImageList_Add(himl, img.toWinHBITMAP(QPixmap::PremultipliedAlpha),mask.toWinHBITMAP()))
+                msg_Err( p_intf, "ImageList_Add failed" );
+            if(-1 == ImageList_Add(himl, img2.toWinHBITMAP(QPixmap::PremultipliedAlpha),mask2.toWinHBITMAP()))
+                msg_Err( p_intf, "ImageList_Add failed" );
+            if(-1 == ImageList_Add(himl, img3.toWinHBITMAP(QPixmap::PremultipliedAlpha),mask3.toWinHBITMAP()))
+                msg_Err( p_intf, "ImageList_Add failed" );
+            if(-1 == ImageList_Add(himl, img4.toWinHBITMAP(QPixmap::PremultipliedAlpha),mask4.toWinHBITMAP()))
+                msg_Err( p_intf, "ImageList_Add failed" );
+        }
+
+        CoInitialize( 0 );
+
+        if( S_OK == CoCreateInstance( &clsid_ITaskbarList,
+                    NULL, CLSCTX_INPROC_SERVER,
+                    &IID_ITaskbarList3,
+                    (void **)&p_taskbl) )
+        {
+            p_taskbl->vt->HrInit(p_taskbl);
+
+            int msg_value = RegisterWindowMessage("TaskbarButtonCreated");
+            //msg_Info( p_intf, "msg value: %04x", msg_value );
+
+            // Define an array of two buttons. These buttons provide images through an 
+            // image list and also provide tooltips.
+            DWORD dwMask = THB_BITMAP | THB_FLAGS;
+
+            THUMBBUTTON thbButtons[2];
+            thbButtons[0].dwMask = dwMask;
+            thbButtons[0].iId = 0;
+            thbButtons[0].iBitmap = 0;
+            thbButtons[0].dwFlags = THBF_HIDDEN;
+
+            thbButtons[1].dwMask = dwMask;
+            thbButtons[1].iId = 1;
+            thbButtons[1].iBitmap = 2;
+            thbButtons[1].dwFlags = THBF_HIDDEN;
+
+            thbButtons[2].dwMask = dwMask;
+            thbButtons[2].iId = 2;
+            thbButtons[2].iBitmap = 3;
+            thbButtons[2].dwFlags = THBF_HIDDEN;
+
+            HRESULT hr = p_taskbl->vt->ThumbBarSetImageList(p_taskbl, GetForegroundWindow(), himl );
+            if(S_OK != hr)
+                msg_Err( p_intf, "ThumbBarSetImageList failed with error %08x", hr );
+            if(S_OK != p_taskbl->vt->ThumbBarAddButtons(p_taskbl, GetForegroundWindow(), 3, thbButtons))
+                msg_Err( p_intf, "ThumbBarAddButtons failed with error %08x", GetLastError() );
+
+        }
+        CONNECT( THEMIM->getIM(), statusChanged( int ), this, changeThumbbarButtons( int ) );
+    }
+#endif
+
 }
 
 MainInterface::~MainInterface()
@@ -299,6 +382,13 @@ MainInterface::~MainInterface()
         delete playlistWidget;
     }
 
+#ifdef WIN32
+    ImageList_Destroy( himl );
+    if(p_taskbl)
+        p_taskbl->vt->Release(p_taskbl);
+    CoUninitialize();
+#endif
+
     /* Be sure to kill the actionsManager... FIXME */
     ActionsManager::killInstance();
 
@@ -1284,6 +1374,65 @@ void MainInterface::toggleFullScreen( void )
 
 }
 
+//moc doesn't know about #ifdef, so we have to build this method for every platform
+void MainInterface::changeThumbbarButtons( int i_status)
+{
+#ifdef WIN32
+    // Define an array of two buttons. These buttons provide images through an
+    // image list and also provide tooltips.
+    DWORD dwMask = THB_BITMAP | THB_FLAGS;
+
+    THUMBBUTTON thbButtons[3];
+    //prev
+    thbButtons[0].dwMask = dwMask;
+    thbButtons[0].iId = 0;
+    thbButtons[0].iBitmap = 0;
+
+    //play/pause
+    thbButtons[1].dwMask = dwMask;
+    thbButtons[1].iId = 1;
+
+    //next
+    thbButtons[2].dwMask = dwMask;
+    thbButtons[2].iId = 2;
+    thbButtons[2].iBitmap = 3;
+
+    switch( i_status )
+    {
+        case  0:
+        case  END_S:
+            {
+                thbButtons[0].dwFlags = THBF_HIDDEN;
+                thbButtons[1].dwFlags = THBF_HIDDEN;
+                thbButtons[2].dwFlags = THBF_HIDDEN;
+                break;
+            }
+        case PLAYING_S:
+            {
+                thbButtons[0].dwFlags = THBF_ENABLED;
+                thbButtons[1].dwFlags = THBF_ENABLED;
+                thbButtons[2].dwFlags = THBF_ENABLED;
+                thbButtons[1].iBitmap = 1;
+                break;
+            }
+        case PAUSE_S:
+            {
+                //thbButtons[0].dwFlags = THBF_ENABLED;
+                //thbButtons[1].dwFlags = THBF_ENABLED;
+                //thbButtons[2].dwFlags = THBF_ENABLED;
+                thbButtons[1].iBitmap = 2;
+                break;
+            }
+    }
+
+    HRESULT hr =  p_taskbl->vt->ThumbBarUpdateButtons(p_taskbl, GetForegroundWindow(), 3, thbButtons);
+    if(S_OK != hr)
+        msg_Err( p_intf, "ThumbBarUpdateButtons failed with error %08x", hr );
+#else
+    ;
+#endif
+}
+
 /*****************************************************************************
  * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
  *  We don't show the menu directly here because we don't want the
index 274d4a9..e2458c9 100644 (file)
@@ -29,6 +29,9 @@
 
 #include "util/qvlcframe.hpp"
 #include "components/preferences_widgets.hpp" /* First Start */
+#ifdef WIN32
+ #include <vlc_windows_interfaces.h>
+#endif
 
 #include <QSystemTrayIcon>
 
@@ -147,6 +150,11 @@ private:
     QLabel              *nameLabel;
     QLabel              *cryptedLabel;
 
+#ifdef WIN32
+    HIMAGELIST himl;
+    LPTASKBARLIST3 p_taskbl;
+#endif
+
 public slots:
     void undockPlaylist();
     void dockPlaylist( pl_dock_e i_pos = PL_BOTTOM );
@@ -157,6 +165,7 @@ public slots:
     void toggleFullScreen();
     void toggleFSC();
     void popupMenu( const QPoint& );
+    void changeThumbbarButtons( int );
 
     /* Manage the Video Functions from the vout threads */
     void getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
index 06dea24..a6b44c3 100644 (file)
@@ -359,7 +359,11 @@ static void *Thread( void *obj )
         argv[argc] = NULL;
     }
 #endif
+#ifdef WIN32
+    QVLCApp app( p_intf, argc, argv );
+#else
     QVLCApp app( argc, argv );
+#endif
     p_intf->p_sys->p_app = &app;
 
 
index f43c1b5..525e979 100644 (file)
 
 #if defined(Q_WS_WIN)
 #   include <windows.h>
+#   include <vlc_common.h>
+#   include <vlc_interface.h>
+#   include "qt4.hpp"
+#   include "input_manager.hpp"
 #endif
 
 class QVLCApp : public QApplication
@@ -37,10 +41,20 @@ class QVLCApp : public QApplication
     Q_OBJECT
 
 public:
+#ifdef WIN32
+    QVLCApp( intf_thread_t *p_intf, int & argc, char ** argv ) : QApplication( argc, argv, true )
+    {
+        connect( this, SIGNAL(quitSignal()), this, SLOT(quit()) );
+        CONNECT( this, playPauseSignal(), THEMIM, togglePlayPause() );
+        CONNECT( this, prevSignal(), THEMIM, prev() );
+        CONNECT( this, nextSignal(), THEMIM, next() );
+    }
+#else
     QVLCApp( int & argc, char ** argv ) : QApplication( argc, argv, true )
     {
         connect( this, SIGNAL(quitSignal()), this, SLOT(quit()) );
     }
+#endif
 
     static void triggerQuit()
     {
@@ -58,6 +72,7 @@ public:
 #endif
 
 #if defined(Q_WS_WIN)
+#define THBN_CLICKED        0x1800
 protected:
     virtual bool winEventFilter( MSG *msg, long *result )
     {
@@ -67,6 +82,25 @@ protected:
                 DefWindowProc( msg->hwnd, msg->message,
                                msg->wParam, msg->lParam );
                 break;
+            case 0xC0C2: /* TaskbarButtonCreated */
+                break;
+            case WM_COMMAND:
+                if (HIWORD(msg->wParam) == THBN_CLICKED)
+                {
+                    switch(LOWORD(msg->wParam))
+                    {
+                        case 0:
+                            emit prevSignal();
+                            break;
+                        case 1:
+                            emit playPauseSignal();
+                            break;
+                        case 2:
+                            emit nextSignal();
+                            break;
+                    }
+                }
+                break;
         }
         return false;
     }
@@ -75,6 +109,9 @@ protected:
 
 signals:
     void quitSignal();
+    void playPauseSignal();
+    void prevSignal();
+    void nextSignal();
 
 };