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