]> git.sesse.net Git - vlc/blob - modules/gui/qt4/main_interface.cpp
Qt: correctly hide/show the statusBar
[vlc] / modules / gui / qt4 / main_interface.cpp
1 /*****************************************************************************
2  * main_interface.cpp : Main interface
3  ****************************************************************************
4  * Copyright (C) 2006-2010 VideoLAN and AUTHORS
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  *          Jean-Baptiste Kempf <jb@videolan.org>
9  *          Ilkka Ollakka <ileoo@videolan.org>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include "qt4.hpp"
31
32 #include "main_interface.hpp"
33 #include "input_manager.hpp"                    // Creation
34 #include "actions_manager.hpp"                  // killInstance
35 #include "extensions_manager.hpp"               // killInstance
36
37 #include "util/customwidgets.hpp"               // qtEventToVLCKey, QVLCStackedWidget
38 #include "util/qt_dirs.hpp"                     // toNativeSeparators
39
40 #include "components/interface_widgets.hpp"     // bgWidget, videoWidget
41 #include "components/controller.hpp"            // controllers
42 #include "components/playlist/playlist.hpp"     // plWidget
43 #include "dialogs/firstrun.hpp"                 // First Run
44
45 #include "menus.hpp"                            // Menu creation
46 #include "recents.hpp"                          // RecentItems when DnD
47
48 #include <QCloseEvent>
49 #include <QKeyEvent>
50
51 #include <QUrl>
52 #include <QSize>
53 #include <QDate>
54
55 #include <QMenu>
56 #include <QMenuBar>
57 #include <QStatusBar>
58 #include <QLabel>
59 #include <QStackedWidget>
60
61 #include <vlc_keys.h>                       /* Wheel event */
62 #include <vlc_vout_display.h>               /* vout_thread_t and VOUT_ events */
63
64 // #define DEBUG_INTF
65
66 /* Callback prototypes */
67 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
68                         vlc_value_t old_val, vlc_value_t new_val, void *param );
69 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
70                        vlc_value_t old_val, vlc_value_t new_val, void *param );
71
72 MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
73 {
74     /* Variables initialisation */
75     bgWidget             = NULL;
76     videoWidget          = NULL;
77     playlistWidget       = NULL;
78     stackCentralOldWidget= NULL;
79 #ifndef HAVE_MAEMO
80     sysTray              = NULL;
81 #endif
82     fullscreenControls   = NULL;
83     cryptedLabel         = NULL;
84     controls             = NULL;
85     inputC               = NULL;
86
87     b_hideAfterCreation  = false; // --qt-start-minimized
88     playlistVisible      = false;
89     input_name           = "";
90
91
92     /* Ask for Privacy */
93     FirstRun::CheckAndRun( this, p_intf );
94
95     /**
96      *  Configuration and settings
97      *  Pre-building of interface
98      **/
99     /* Main settings */
100     setFocusPolicy( Qt::StrongFocus );
101     setAcceptDrops( true );
102     setWindowRole( "vlc-main" );
103     setWindowIcon( QApplication::windowIcon() );
104     setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
105 #ifdef Q_WS_MAC
106     setAttribute( Qt::WA_MacBrushedMetal );
107 #endif
108
109     /* Is video in embedded in the UI or not */
110     b_videoEmbedded = var_InheritBool( p_intf, "embedded-video" );
111
112     /* Does the interface resize to video size or the opposite */
113     b_autoresize = var_InheritBool( p_intf, "qt-video-autoresize" );
114
115     /* Are we in the enhanced always-video mode or not ? */
116     b_minimalView = var_InheritBool( p_intf, "qt-minimal-view" );
117
118     /* Do we want anoying popups or not */
119     b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
120
121     /* Set the other interface settings */
122     settings = getSettings();
123     settings->beginGroup( "MainWindow" );
124
125 #ifdef WIN32
126     /* Volume keys */
127     p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
128 #endif
129
130     /* */
131     b_plDocked = getSettings()->value( "pl-dock-status", true ).toBool();
132
133     settings->endGroup( );
134
135     /**************
136      * Status Bar *
137      **************/
138     createStatusBar();
139     b_statusbarVisible = getSettings()->value( "status-bar-visible", false ).toBool();
140     statusBar()->setVisible( b_statusbarVisible );
141
142     /**************************
143      *  UI and Widgets design
144      **************************/
145     setVLCWindowsTitle();
146
147     /************
148      * Menu Bar *
149      ************/
150     QVLCMenu::createMenuBar( this, p_intf );
151     CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
152              this, destroyPopupMenu() );
153
154     createMainWidget( settings );
155     /*********************************
156      * Create the Systray Management *
157      *********************************/
158     initSystray();
159
160     /********************
161      * Input Manager    *
162      ********************/
163     MainInputManager::getInstance( p_intf );
164
165 #ifdef WIN32
166     himl = NULL;
167     p_taskbl = NULL;
168     taskbar_wmsg = RegisterWindowMessage("TaskbarButtonCreated");
169 #endif
170
171     /************************************************************
172      * Connect the input manager to the GUI elements it manages *
173      ************************************************************/
174     /**
175      * Connects on nameChanged()
176      * Those connects are different because options can impeach them to trigger.
177      **/
178     /* Main Interface statusbar */
179     CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
180              this, setName( const QString& ) );
181     /* and systray */
182 #ifndef HAVE_MAEMO
183     if( sysTray )
184     {
185         CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
186                  this, updateSystrayTooltipName( const QString& ) );
187     }
188 #endif
189     /* and title of the Main Interface*/
190     if( var_InheritBool( p_intf, "qt-name-in-title" ) )
191     {
192         CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
193                  this, setVLCWindowsTitle( const QString& ) );
194     }
195
196     /**
197      * CONNECTS on PLAY_STATUS
198      **/
199     /* Status on the systray */
200 #ifndef HAVE_MAEMO
201     if( sysTray )
202     {
203         CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
204                  this, updateSystrayTooltipStatus( int ) );
205     }
206 #endif
207
208     /* END CONNECTS ON IM */
209
210     /* VideoWidget connects for asynchronous calls */
211     b_videoFullScreen = false;
212     b_videoOnTop = false;
213     connect( this, SIGNAL(askGetVideo(WId*,int*,int*,unsigned*,unsigned *)),
214              this, SLOT(getVideoSlot(WId*,int*,int*,unsigned*,unsigned*)),
215              Qt::BlockingQueuedConnection );
216     connect( this, SIGNAL(askReleaseVideo( void )),
217              this, SLOT(releaseVideoSlot( void )),
218              Qt::BlockingQueuedConnection );
219     CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
220
221     if( videoWidget )
222     {
223         if( b_autoresize )
224         {
225             CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
226                      this, setVideoSize( unsigned int, unsigned int ) );
227             CONNECT( videoWidget, sizeChanged( int, int ),
228                      this, resizeStack( int,  int ) );
229         }
230         CONNECT( this, askVideoSetFullScreen( bool ),
231                  this, setVideoFullScreen( bool ) );
232     }
233
234     CONNECT( THEDP, toolBarConfUpdated(), this, recreateToolbars() );
235
236     CONNECT( this, askToQuit(), THEDP, quit() );
237
238     /** END of CONNECTS**/
239
240
241     /************
242      * Callbacks
243      ************/
244     var_AddCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
245
246     /* Register callback for the intf-popupmenu variable */
247     var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
248
249     /* Playlist */
250     int i_plVis = settings->value( "MainWindow/playlist-visible", false ).toBool();
251
252     if( i_plVis ) togglePlaylist();
253
254     /**** FINAL SIZING and placement of interface */
255     settings->beginGroup( "MainWindow" );
256     QVLCTools::restoreWidgetPosition( settings, this, QSize(400, 100) );
257     settings->endGroup();
258
259     b_interfaceFullScreen = isFullScreen();
260
261     /* Final sizing and showing */
262     setVisible( !b_hideAfterCreation );
263
264     computeMinimumSize();
265
266     /* Switch to minimal view if needed, must be called after the show() */
267     if( b_minimalView )
268         toggleMinimalView( true );
269
270     b_hasPausedWhenMinimized = false;
271 }
272
273 MainInterface::~MainInterface()
274 {
275     /* Unsure we hide the videoWidget before destroying it */
276     if( stackCentralOldWidget == videoWidget )
277         showTab( bgWidget );
278
279     if( videoWidget )
280         releaseVideoSlot();
281
282 #ifdef WIN32
283     if( himl )
284         ImageList_Destroy( himl );
285     if(p_taskbl)
286         p_taskbl->vt->Release(p_taskbl);
287     CoUninitialize();
288 #endif
289
290     /* Be sure to kill the actionsManager... Only used in the MI and control */
291     ActionsManager::killInstance();
292
293     /* Idem */
294     ExtensionsManager::killInstance();
295
296     /* Delete the FSC controller */
297     delete fullscreenControls;
298
299     /* Save states */
300     settings->beginGroup( "MainWindow" );
301
302     settings->setValue( "pl-dock-status", b_plDocked );
303     /* Save playlist state */
304     if( playlistWidget )
305         settings->setValue( "playlist-visible", playlistVisible );
306
307     settings->setValue( "adv-controls",
308                         getControlsVisibilityStatus() & CONTROLS_ADVANCED );
309     settings->setValue( "status-bar-visible", b_statusbarVisible );
310
311     /* Save the stackCentralW sizes */
312     settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
313     settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
314
315     /* Save this size */
316     QVLCTools::saveWidgetPosition(settings, this);
317
318     settings->endGroup();
319
320     /* Save undocked playlist size */
321     if( playlistWidget && !isPlDocked() )
322         QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
323
324     delete playlistWidget;
325
326     delete statusBar();
327
328     /* Unregister callbacks */
329     var_DelCallback( p_intf->p_libvlc, "intf-show", IntfShowCB, p_intf );
330     var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
331
332     p_intf->p_sys->p_mi = NULL;
333 }
334
335 void MainInterface::computeMinimumSize()
336 {
337     int minWidth = 30;
338     if( menuBar()->isVisible() )
339         minWidth += __MAX( controls->sizeHint().width(), menuBar()->sizeHint().width() );
340
341     setMinimumWidth( minWidth );
342 }
343
344 /*****************************
345  *   Main UI handling        *
346  *****************************/
347 void MainInterface::recreateToolbars()
348 {
349     bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
350
351     settings->beginGroup( "MainWindow" );
352     delete controls;
353     delete inputC;
354
355     controls = new ControlsWidget( p_intf, b_adv, this );
356     inputC = new InputControlsWidget( p_intf, this );
357
358     if( fullscreenControls )
359     {
360         delete fullscreenControls;
361         fullscreenControls = new FullscreenControllerWidget( p_intf, this );
362         CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
363                  this, handleKeyPress( QKeyEvent * ) );
364     }
365     mainLayout->insertWidget( 2, inputC );
366     mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
367                               controls );
368     settings->endGroup();
369 }
370
371 void MainInterface::createMainWidget( QSettings *settings )
372 {
373     /* Create the main Widget and the mainLayout */
374     QWidget *main = new QWidget;
375     setCentralWidget( main );
376     mainLayout = new QVBoxLayout( main );
377     main->setContentsMargins( 0, 0, 0, 0 );
378     mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
379
380     /* */
381     stackCentralW = new QVLCStackedWidget( main );
382
383     /* Bg Cone */
384     bgWidget = new BackgroundWidget( p_intf );
385     stackCentralW->addWidget( bgWidget );
386     if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
387         bgWidget->setWithArt( false );
388     else
389         if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
390             bgWidget->setExpandstoHeight( true );
391
392     /* And video Outputs */
393     if( b_videoEmbedded )
394     {
395         videoWidget = new VideoWidget( p_intf );
396         stackCentralW->addWidget( videoWidget );
397     }
398     mainLayout->insertWidget( 1, stackCentralW );
399
400     settings->beginGroup( "MainWindow" );
401     stackWidgetsSizes[bgWidget] = settings->value( "bgSize", QSize( 400, 0 ) ).toSize();
402     /* Resize even if no-auto-resize, because we are at creation */
403     resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
404
405     /* Create the CONTROLS Widget */
406     controls = new ControlsWidget( p_intf,
407                    settings->value( "adv-controls", false ).toBool(), this );
408     inputC = new InputControlsWidget( p_intf, this );
409
410     mainLayout->insertWidget( 2, inputC );
411     mainLayout->insertWidget( settings->value( "ToolbarPos", 0 ).toInt() ? 0: 3,
412                               controls );
413
414     /* Visualisation, disabled for now, they SUCK */
415     #if 0
416     visualSelector = new VisualSelector( p_intf );
417     mainLayout->insertWidget( 0, visualSelector );
418     visualSelector->hide();
419     #endif
420
421     settings->endGroup();
422
423     /* Enable the popup menu in the MI */
424     main->setContextMenuPolicy( Qt::CustomContextMenu );
425     CONNECT( main, customContextMenuRequested( const QPoint& ),
426              this, popupMenu( const QPoint& ) );
427
428     if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
429         /* Create the FULLSCREEN CONTROLS Widget */
430         if( var_InheritBool( p_intf, "qt-fs-controller" ) )
431         {
432             fullscreenControls = new FullscreenControllerWidget( p_intf, this );
433             CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
434                      this, handleKeyPress( QKeyEvent * ) );
435         }
436 }
437
438 inline void MainInterface::initSystray()
439 {
440 #ifndef HAVE_MAEMO
441     bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
442     bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
443
444     if( var_InheritBool( p_intf, "qt-start-minimized") )
445     {
446         if( b_systrayAvailable )
447         {
448             b_systrayWanted = true;
449             b_hideAfterCreation = true;
450         }
451         else
452             msg_Err( p_intf, "cannot start minimized without system tray bar" );
453     }
454
455     if( b_systrayAvailable && b_systrayWanted )
456         createSystray();
457 #endif
458 }
459
460 inline void MainInterface::createStatusBar()
461 {
462     /****************
463      *  Status Bar  *
464      ****************/
465     /* Widgets Creation*/
466     QStatusBar *statusBarr = statusBar();
467
468     TimeLabel *timeLabel = new TimeLabel( p_intf );
469     nameLabel = new QLabel( this );
470     nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
471                                       | Qt::TextSelectableByKeyboard );
472     SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
473
474     /* Styling those labels */
475     timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
476     speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
477     nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
478     timeLabel->setStyleSheet(
479             "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
480     speedLabel->setStyleSheet(
481             "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
482     /* pad both label and its tooltip */
483     nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
484
485     /* and adding those */
486     statusBarr->addWidget( nameLabel, 8 );
487     statusBarr->addPermanentWidget( speedLabel, 0 );
488     statusBarr->addPermanentWidget( timeLabel, 0 );
489
490     /* timeLabel behaviour:
491        - double clicking opens the goto time dialog
492        - right-clicking and clicking just toggle between remaining and
493          elapsed time.*/
494     CONNECT( timeLabel, timeLabelDoubleClicked(), THEDP, gotoTimeDialog() );
495
496     CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
497              this, showCryptedLabel( bool ) );
498
499     CONNECT( THEMIM->getIM(), seekRequested( float ),
500              timeLabel, setDisplayPosition( float ) );
501
502     /* This shouldn't be necessary, but for somehow reason, the statusBarr
503        starts at height of 20px and when a text is shown it needs more space.
504        But, as the QMainWindow policy doesn't allow statusBar to change QMW's
505        geometry, we need to force a height. If you have a better idea, please
506        tell me -- jb
507      */
508     statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
509 }
510
511 /**********************************************************************
512  * Handling of sizing of the components
513  **********************************************************************/
514
515 void MainInterface::debug()
516 {
517 #ifdef DEBUG_INTF
518     msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
519     msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
520     msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
521
522     msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
523     msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
524     msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
525 #endif
526 }
527
528 inline void MainInterface::showVideo() { showTab( videoWidget ); }
529 inline void MainInterface::restoreStackOldWidget()
530             { showTab( stackCentralOldWidget ); }
531
532 inline void MainInterface::showTab( QWidget *widget )
533 {
534 #ifdef DEBUG_INTF
535     msg_Warn( p_intf, "Old stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
536 #endif
537
538     stackCentralOldWidget = stackCentralW->currentWidget();
539     stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
540
541     stackCentralW->setCurrentWidget( widget );
542     if( b_autoresize )
543         resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
544
545 #ifdef DEBUG_INTF
546     msg_Warn( p_intf, "State change %i",  stackCentralW->currentIndex() );
547     msg_Warn( p_intf, "New stackCentralOldWidget %i", stackCentralW->indexOf( stackCentralOldWidget ) );
548 #endif
549 }
550
551 void MainInterface::destroyPopupMenu()
552 {
553     QVLCMenu::PopupMenu( p_intf, false );
554 }
555
556 void MainInterface::popupMenu( const QPoint &p )
557 {
558     QVLCMenu::PopupMenu( p_intf, true );
559 }
560
561 void MainInterface::toggleFSC()
562 {
563    if( !fullscreenControls ) return;
564
565    IMEvent *eShow = new IMEvent( FullscreenControlToggle_Type, 0 );
566    QApplication::postEvent( fullscreenControls, eShow );
567 }
568
569 /****************************************************************************
570  * Video Handling
571  ****************************************************************************/
572
573 /**
574  * NOTE:
575  * You must not change the state of this object or other Qt4 UI objects,
576  * from the video output thread - only from the Qt4 UI main loop thread.
577  * All window provider queries must be handled through signals or events.
578  * That's why we have all those emit statements...
579  */
580 WId MainInterface::getVideo( int *pi_x, int *pi_y,
581                              unsigned int *pi_width, unsigned int *pi_height )
582 {
583     if( !videoWidget )
584         return 0;
585
586     /* This is a blocking call signal. Results are returned through pointers.
587      * Beware of deadlocks! */
588     WId id;
589     emit askGetVideo( &id, pi_x, pi_y, pi_width, pi_height );
590     return id;
591 }
592
593 void MainInterface::getVideoSlot( WId *p_id, int *pi_x, int *pi_y,
594                                   unsigned *pi_width, unsigned *pi_height )
595 {
596     /* Request the videoWidget */
597     WId ret = videoWidget->request( pi_x, pi_y,
598                                     pi_width, pi_height, !b_autoresize );
599     *p_id = ret;
600     if( ret ) /* The videoWidget is available */
601     {
602         /* Consider the video active now */
603         showVideo();
604
605         /* Ask videoWidget to resize correctly, if we are in normal mode */
606         if( !isFullScreen() && !isMaximized() && b_autoresize )
607             videoWidget->SetSizing( *pi_width, *pi_height );
608     }
609 }
610
611 /* Asynchronous call from the WindowClose function */
612 void MainInterface::releaseVideo( void )
613 {
614     emit askReleaseVideo();
615 }
616
617 /* Function that is CONNECTED to the previous emit */
618 void MainInterface::releaseVideoSlot( void )
619 {
620     /* This function is called when the embedded video window is destroyed,
621      * or in the rare case that the embedded window is still here but the
622      * Qt4 interface exits. */
623     assert( videoWidget );
624     videoWidget->release();
625     setVideoOnTop( false );
626     setVideoFullScreen( false );
627
628     if( stackCentralW->currentWidget() == videoWidget )
629         restoreStackOldWidget();
630
631     /* We don't want to have a blank video to popup */
632     stackCentralOldWidget = bgWidget;
633 }
634
635 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
636 {
637     if( !isFullScreen() && !isMaximized() )
638         videoWidget->SetSizing( w, h );
639 }
640
641 void MainInterface::setVideoFullScreen( bool fs )
642 {
643     b_videoFullScreen = fs;
644     if( fs )
645     {
646         int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
647         /* if user hasn't defined screennumber, or screennumber that is bigger
648          * than current number of screens, take screennumber where current interface
649          * is
650          */
651         if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
652             numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
653
654         QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
655
656         /* To be sure window is on proper-screen in xinerama */
657         if( !screenres.contains( pos() ) )
658         {
659             msg_Dbg( p_intf, "Moving video to correct screen");
660             move( QPoint( screenres.x(), screenres.y() ) );
661         }
662         setMinimalView( true );
663         setInterfaceFullScreen( true );
664     }
665     else
666     {
667         /* TODO do we want to restore screen and position ? (when
668          * qt-fullscreen-screennumber is forced) */
669         setMinimalView( b_minimalView );
670         setInterfaceFullScreen( b_interfaceFullScreen );
671     }
672     videoWidget->sync();
673 }
674
675 /* Slot to change the video always-on-top flag.
676  * Emit askVideoOnTop() to invoke this from other thread. */
677 void MainInterface::setVideoOnTop( bool on_top )
678 {
679     b_videoOnTop = on_top;
680
681     Qt::WindowFlags oldflags = windowFlags(), newflags;
682
683     if( b_videoOnTop )
684         newflags = oldflags | Qt::WindowStaysOnTopHint;
685     else
686         newflags = oldflags & ~Qt::WindowStaysOnTopHint;
687
688     if( newflags != oldflags )
689     {
690         setWindowFlags( newflags );
691         show(); /* necessary to apply window flags */
692     }
693 }
694
695 /* Asynchronous call from WindowControl function */
696 int MainInterface::controlVideo( int i_query, va_list args )
697 {
698     switch( i_query )
699     {
700     case VOUT_WINDOW_SET_SIZE:
701     {
702         unsigned int i_width  = va_arg( args, unsigned int );
703         unsigned int i_height = va_arg( args, unsigned int );
704
705         emit askVideoToResize( i_width, i_height );
706         return VLC_SUCCESS;
707     }
708     case VOUT_WINDOW_SET_STATE:
709     {
710         unsigned i_arg = va_arg( args, unsigned );
711         unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
712
713         emit askVideoOnTop( on_top != 0 );
714         return VLC_SUCCESS;
715     }
716     case VOUT_WINDOW_SET_FULLSCREEN:
717     {
718         bool b_fs = va_arg( args, int );
719
720         emit askVideoSetFullScreen( b_fs );
721         return VLC_SUCCESS;
722     }
723     default:
724         msg_Warn( p_intf, "unsupported control query" );
725         return VLC_EGENERIC;
726     }
727 }
728
729 /*****************************************************************************
730  * Playlist, Visualisation and Menus handling
731  *****************************************************************************/
732 /**
733  * Toggle the playlist widget or dialog
734  **/
735 void MainInterface::createPlaylist()
736 {
737     playlistWidget = new PlaylistWidget( p_intf, this );
738
739     if( b_plDocked )
740     {
741         stackCentralW->addWidget( playlistWidget );
742         stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 500, 250 ) ).toSize();
743     }
744     else
745     {
746 #ifdef WIN32
747         playlistWidget->setParent( NULL );
748 #endif
749         playlistWidget->setWindowFlags( Qt::Window );
750
751         /* This will restore the geometry but will not work for position,
752            because of parenting */
753         QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
754                 playlistWidget, QSize( 600, 300 ) );
755     }
756 }
757
758 void MainInterface::togglePlaylist()
759 {
760     if( !playlistWidget )
761     {
762         createPlaylist();
763     }
764
765     if( b_plDocked )
766     {
767         /* Playlist is not visible, show it */
768         if( stackCentralW->currentWidget() != playlistWidget )
769         {
770             showTab( playlistWidget );
771         }
772         else /* Hide it! */
773         {
774             restoreStackOldWidget();
775         }
776         playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
777     }
778     else
779     {
780 #ifdef WIN32
781         playlistWidget->setParent( NULL );
782 #endif
783         playlistWidget->setWindowFlags( Qt::Window );
784         playlistVisible = !playlistVisible;
785         playlistWidget->setVisible( playlistVisible );
786     }
787     debug();
788 }
789
790 void MainInterface::dockPlaylist( bool p_docked )
791 {
792     if( b_plDocked == p_docked ) return;
793     b_plDocked = p_docked;
794
795     if( !playlistWidget ) return; /* Playlist wasn't created yet */
796     if( !p_docked )
797     {
798         stackCentralW->removeWidget( playlistWidget );
799 #ifdef WIN32
800         playlistWidget->setParent( NULL );
801 #endif
802         playlistWidget->setWindowFlags( Qt::Window );
803         QVLCTools::restoreWidgetPosition( p_intf, "Playlist",
804                 playlistWidget, QSize( 600, 300 ) );
805         playlistWidget->show();
806         restoreStackOldWidget();
807     }
808     else
809     {
810         QVLCTools::saveWidgetPosition( p_intf, "Playlist", playlistWidget );
811         playlistWidget->setWindowFlags( Qt::Widget ); // Probably a Qt bug here
812         // It would be logical that QStackWidget::addWidget reset the flags...
813         stackCentralW->addWidget( playlistWidget );
814         showTab( playlistWidget );
815     }
816     playlistVisible = true;
817 }
818
819 /*
820  * setMinimalView is the private function used by
821  * the SLOT toggleMinimalView and setVideoFullScreen
822  */
823 void MainInterface::setMinimalView( bool b_minimal )
824 {
825     menuBar()->setVisible( !b_minimal );
826     controls->setVisible( !b_minimal );
827     statusBar()->setVisible( !b_minimal && b_statusbarVisible );
828     inputC->setVisible( !b_minimal );
829 }
830
831 /*
832  * This public SLOT is used for moving to minimal View Mode
833  *
834  * If b_minimal is false, then we are normalView
835  */
836 void MainInterface::toggleMinimalView( bool b_minimal )
837 {
838     if( !b_minimalView && b_autoresize ) /* Normal mode */
839     {
840         if( stackCentralW->currentWidget() == bgWidget )
841         {
842             if( stackCentralW->height() < 16 )
843             {
844                 resizeStack( stackCentralW->width(), 100 );
845             }
846         }
847     }
848     b_minimalView = b_minimal;
849     if( !b_videoFullScreen )
850     {
851         setMinimalView( b_minimalView );
852         computeMinimumSize();
853     }
854
855     emit minimalViewToggled( b_minimalView );
856 }
857
858 /* toggling advanced controls buttons */
859 void MainInterface::toggleAdvancedButtons()
860 {
861     controls->toggleAdvanced();
862 //    if( fullscreenControls ) fullscreenControls->toggleAdvanced();
863 }
864
865 /* Get the visibility status of the controls (hidden or not, advanced or not) */
866 int MainInterface::getControlsVisibilityStatus()
867 {
868     if( !controls ) return 0;
869     return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
870                 + CONTROLS_ADVANCED * controls->b_advancedVisible );
871 }
872
873 void MainInterface::setStatusBarVisibility( bool b_visible )
874 {
875     statusBar()->setVisible( b_visible );
876     b_statusbarVisible = b_visible;
877 }
878
879 #if 0
880 void MainInterface::visual()
881 {
882     if( !VISIBLE( visualSelector) )
883     {
884         visualSelector->show();
885         if( !THEMIM->getIM()->hasVideo() )
886         {
887             /* Show the background widget */
888         }
889         visualSelectorEnabled = true;
890     }
891     else
892     {
893         /* Stop any currently running visualization */
894         visualSelector->hide();
895         visualSelectorEnabled = false;
896     }
897 }
898 #endif
899
900 /************************************************************************
901  * Other stuff
902  ************************************************************************/
903 void MainInterface::setName( const QString& name )
904 {
905     input_name = name; /* store it for the QSystray use */
906     /* Display it in the status bar, but also as a Tooltip in case it doesn't
907        fit in the label */
908     nameLabel->setText( name );
909     nameLabel->setToolTip( name );
910 }
911
912 /**
913  * Give the decorations of the Main Window a correct Name.
914  * If nothing is given, set it to VLC...
915  **/
916 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
917 {
918     if( aTitle.isEmpty() )
919     {
920         setWindowTitle( qtr( "VLC media player" ) );
921     }
922     else
923     {
924         setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
925     }
926 }
927
928 void MainInterface::showCryptedLabel( bool b_show )
929 {
930     if( cryptedLabel == NULL )
931     {
932         cryptedLabel = new QLabel;
933         // The lock icon is not the right one for DRM protection/scrambled.
934         //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
935         cryptedLabel->setText( "DRM" );
936         statusBar()->addWidget( cryptedLabel );
937     }
938
939     cryptedLabel->setVisible( b_show );
940 }
941
942 void MainInterface::showBuffering( float f_cache )
943 {
944     QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
945     statusBar()->showMessage( amount, 1000 );
946 }
947
948 /*****************************************************************************
949  * Systray Icon and Systray Menu
950  *****************************************************************************/
951 #ifndef HAVE_MAEMO
952 /**
953  * Create a SystemTray icon and a menu that would go with it.
954  * Connects to a click handler on the icon.
955  **/
956 void MainInterface::createSystray()
957 {
958     QIcon iconVLC;
959     if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
960         iconVLC =  QIcon( ":/logo/vlc128-xmas.png" );
961     else
962         iconVLC =  QIcon( ":/logo/vlc128.png" );
963     sysTray = new QSystemTrayIcon( iconVLC, this );
964     sysTray->setToolTip( qtr( "VLC media player" ));
965
966     systrayMenu = new QMenu( qtr( "VLC media player" ), this );
967     systrayMenu->setIcon( iconVLC );
968
969     QVLCMenu::updateSystrayMenu( this, p_intf, true );
970     sysTray->show();
971
972     CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
973             this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
974 }
975
976 /**
977  * Updates the Systray Icon's menu and toggle the main interface
978  */
979 void MainInterface::toggleUpdateSystrayMenu()
980 {
981     /* If hidden, show it */
982     if( isHidden() )
983     {
984         show();
985         activateWindow();
986     }
987     else if( isMinimized() )
988     {
989         /* Minimized */
990         showNormal();
991         activateWindow();
992     }
993     else
994     {
995         /* Visible (possibly under other windows) */
996 #ifdef WIN32
997         /* check if any visible window is above vlc in the z-order,
998          * but ignore the ones always on top
999          * and the ones which can't be activated */
1000         WINDOWINFO wi;
1001         HWND hwnd;
1002         wi.cbSize = sizeof( WINDOWINFO );
1003         for( hwnd = GetNextWindow( internalWinId(), GW_HWNDPREV );
1004                 hwnd && ( !IsWindowVisible( hwnd ) ||
1005                     ( GetWindowInfo( hwnd, &wi ) &&
1006                       (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1007                 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1008             if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1009                 (wi.dwExStyle&WS_EX_TOPMOST) )
1010             {
1011                 hide();
1012             }
1013             else
1014             {
1015                 activateWindow();
1016             }
1017 #else
1018         hide();
1019 #endif
1020     }
1021     QVLCMenu::updateSystrayMenu( this, p_intf );
1022 }
1023
1024 void MainInterface::showUpdateSystrayMenu()
1025 {
1026     if( isHidden() )
1027         show();
1028     if( isMinimized() )
1029         showNormal();
1030     activateWindow();
1031
1032     QVLCMenu::updateSystrayMenu( this, p_intf );
1033 }
1034
1035 void MainInterface::hideUpdateSystrayMenu()
1036 {
1037     hide();
1038     QVLCMenu::updateSystrayMenu( this, p_intf );
1039 }
1040
1041 void MainInterface::handleSystrayClick(
1042                                     QSystemTrayIcon::ActivationReason reason )
1043 {
1044     switch( reason )
1045     {
1046         case QSystemTrayIcon::Trigger:
1047         case QSystemTrayIcon::DoubleClick:
1048 #ifdef Q_WS_MAC
1049             QVLCMenu::updateSystrayMenu( this, p_intf );
1050 #else
1051             toggleUpdateSystrayMenu();
1052 #endif
1053             break;
1054         case QSystemTrayIcon::MiddleClick:
1055             sysTray->showMessage( qtr( "VLC media player" ),
1056                     qtr( "Control menu for the player" ),
1057                     QSystemTrayIcon::Information, 3000 );
1058             break;
1059         default:
1060             break;
1061     }
1062 }
1063
1064 /**
1065  * Updates the name of the systray Icon tooltip.
1066  * Doesn't check if the systray exists, check before you call it.
1067  **/
1068 void MainInterface::updateSystrayTooltipName( const QString& name )
1069 {
1070     if( name.isEmpty() )
1071     {
1072         sysTray->setToolTip( qtr( "VLC media player" ) );
1073     }
1074     else
1075     {
1076         sysTray->setToolTip( name );
1077         if( b_notificationEnabled && ( isHidden() || isMinimized() ) )
1078         {
1079             sysTray->showMessage( qtr( "VLC media player" ), name,
1080                     QSystemTrayIcon::NoIcon, 3000 );
1081         }
1082     }
1083
1084     QVLCMenu::updateSystrayMenu( this, p_intf );
1085 }
1086
1087 /**
1088  * Updates the status of the systray Icon tooltip.
1089  * Doesn't check if the systray exists, check before you call it.
1090  **/
1091 void MainInterface::updateSystrayTooltipStatus( int i_status )
1092 {
1093     switch( i_status )
1094     {
1095     case PLAYING_S:
1096         sysTray->setToolTip( input_name );
1097         break;
1098     case PAUSE_S:
1099         sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1100         break;
1101     default:
1102         sysTray->setToolTip( qtr( "VLC media player" ) );
1103         break;
1104     }
1105     QVLCMenu::updateSystrayMenu( this, p_intf );
1106 }
1107 #endif
1108
1109 void MainInterface::changeEvent(QEvent *event)
1110 {
1111     if( event->type() == QEvent::WindowStateChange )
1112     {
1113         QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1114         Qt::WindowStates newState = windowState();
1115         Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1116
1117         if( newState & Qt::WindowMinimized )
1118         {
1119             b_hasPausedWhenMinimized = false;
1120
1121             if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1122                 THEMIM->getIM()->hasVideo() &&
1123                 !THEMIM->getIM()->hasVisualisation() &&
1124                 var_InheritBool( p_intf, "qt-pause-minimized" ) )
1125             {
1126                 b_hasPausedWhenMinimized = true;
1127                 THEMIM->pause();
1128             }
1129         }
1130         else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1131         {
1132             if( b_hasPausedWhenMinimized )
1133             {
1134                 THEMIM->play();
1135             }
1136         }
1137     }
1138
1139     QWidget::changeEvent(event);
1140 }
1141
1142 /************************************************************************
1143  * D&D Events
1144  ************************************************************************/
1145 void MainInterface::dropEvent(QDropEvent *event)
1146 {
1147     dropEventPlay( event, true );
1148 }
1149
1150 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play )
1151 {
1152     if( event->possibleActions() & Qt::CopyAction )
1153        event->setDropAction( Qt::CopyAction );
1154     else
1155         return;
1156
1157     const QMimeData *mimeData = event->mimeData();
1158
1159     /* D&D of a subtitles file, add it on the fly */
1160     if( mimeData->urls().size() == 1 && THEMIM->getIM()->hasInput() )
1161     {
1162         if( !input_AddSubtitle( THEMIM->getInput(),
1163                  qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1164                  true ) )
1165         {
1166             event->accept();
1167             return;
1168         }
1169     }
1170
1171     bool first = b_play;
1172     foreach( const QUrl &url, mimeData->urls() )
1173     {
1174         if( url.isValid() )
1175         {
1176             QString mrl = toURI( url.toEncoded().constData() );
1177             playlist_Add( THEPL, qtu(mrl), NULL,
1178                           PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1179                           PLAYLIST_END, true, pl_Unlocked );
1180             first = false;
1181             RecentsMRL::getInstance( p_intf )->addRecent( url.toString() );
1182         }
1183     }
1184
1185     /* Browsers give content as text if you dnd the addressbar,
1186        so check if mimedata has valid url in text and use it
1187        if we didn't get any normal Urls()*/
1188     if( !mimeData->hasUrls() && mimeData->hasText() &&
1189         QUrl(mimeData->text()).isValid() )
1190     {
1191         QString mrl = toURI( mimeData->text() );
1192         playlist_Add( THEPL, qtu(mrl), NULL,
1193                       PLAYLIST_APPEND | (first ? PLAYLIST_GO: PLAYLIST_PREPARSE),
1194                       PLAYLIST_END, true, pl_Unlocked );
1195     }
1196     event->accept();
1197 }
1198 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1199 {
1200      event->acceptProposedAction();
1201 }
1202 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1203 {
1204      event->acceptProposedAction();
1205 }
1206 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1207 {
1208      event->accept();
1209 }
1210
1211 /************************************************************************
1212  * Events stuff
1213  ************************************************************************/
1214 void MainInterface::keyPressEvent( QKeyEvent *e )
1215 {
1216     handleKeyPress( e );
1217 }
1218
1219 void MainInterface::handleKeyPress( QKeyEvent *e )
1220 {
1221     if( ( e->modifiers() &  Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
1222     {
1223         toggleMinimalView( !b_minimalView );
1224         e->accept();
1225     }
1226
1227     int i_vlck = qtEventToVLCKey( e );
1228     if( i_vlck > 0 )
1229     {
1230         var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1231         e->accept();
1232     }
1233     else
1234         e->ignore();
1235 }
1236
1237 void MainInterface::wheelEvent( QWheelEvent *e )
1238 {
1239     int i_vlckey = qtWheelEventToVLCKey( e );
1240     var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1241     e->accept();
1242 }
1243
1244 void MainInterface::closeEvent( QCloseEvent *e )
1245 {
1246     e->ignore();      /* Do not quit */
1247 //  hide();
1248     emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1249 }
1250
1251 void MainInterface::setInterfaceFullScreen( bool fs )
1252 {
1253     if( fs )
1254         setWindowState( windowState() | Qt::WindowFullScreen );
1255     else
1256         setWindowState( windowState() & ~Qt::WindowFullScreen );
1257 }
1258 void MainInterface::toggleInterfaceFullScreen()
1259 {
1260     b_interfaceFullScreen = !b_interfaceFullScreen;
1261     if( !b_videoFullScreen )
1262         setInterfaceFullScreen( b_interfaceFullScreen );
1263     emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1264 }
1265
1266 /*****************************************************************************
1267  * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1268  *  We don't show the menu directly here because we don't want the
1269  *  caller to block for a too long time.
1270  *****************************************************************************/
1271 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1272                         vlc_value_t old_val, vlc_value_t new_val, void *param )
1273 {
1274     intf_thread_t *p_intf = (intf_thread_t *)param;
1275
1276     if( p_intf->pf_show_dialog )
1277     {
1278         p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1279                                 new_val.b_bool, NULL );
1280     }
1281
1282     return VLC_SUCCESS;
1283 }
1284
1285 /*****************************************************************************
1286  * IntfShowCB: callback triggered by the intf-show libvlc variable.
1287  *****************************************************************************/
1288 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1289                        vlc_value_t old_val, vlc_value_t new_val, void *param )
1290 {
1291     intf_thread_t *p_intf = (intf_thread_t *)param;
1292     p_intf->p_sys->p_mi->toggleFSC();
1293
1294     /* Show event */
1295      return VLC_SUCCESS;
1296 }