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