Qt: update the Win32 thumbnail after fullscreen
[vlc.git] / 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
36 #include "util/customwidgets.hpp"               // qtEventToVLCKey, QVLCStackedWidget
37 #include "util/qt_dirs.hpp"                     // toNativeSeparators
38
39 #include "components/interface_widgets.hpp"     // bgWidget, videoWidget
40 #include "components/controller.hpp"            // controllers
41 #include "components/playlist/playlist.hpp"     // plWidget
42 #include "dialogs/firstrun.hpp"                 // First Run
43 #include "dialogs/playlist.hpp"                 // PlaylistDialog
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 #include <QMimeData>
55
56 #include <QMenu>
57 #include <QMenuBar>
58 #include <QStatusBar>
59 #include <QLabel>
60 #include <QStackedWidget>
61 #include <QFileInfo>
62
63 #include <vlc_keys.h>                       /* Wheel event */
64 #include <vlc_vout_display.h>               /* vout_thread_t and VOUT_ events */
65
66
67 #if defined(_WIN32) && HAS_QT5
68 #include <QWindow>
69 #include <qpa/qplatformnativeinterface.h>
70 #endif
71
72 // #define DEBUG_INTF
73
74 /* Callback prototypes */
75 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
76                         vlc_value_t old_val, vlc_value_t new_val, void *param );
77 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
78                        vlc_value_t old_val, vlc_value_t new_val, void *param );
79 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
80                        vlc_value_t old_val, vlc_value_t new_val, void *param );
81 static int IntfRaiseMainCB( vlc_object_t *p_this, const char *psz_variable,
82                            vlc_value_t old_val, vlc_value_t new_val,
83                            void *param );
84
85 const QEvent::Type MainInterface::ToolbarsNeedRebuild =
86         (QEvent::Type)QEvent::registerEventType();
87
88 MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
89 {
90     /* Variables initialisation */
91     bgWidget             = NULL;
92     videoWidget          = NULL;
93     playlistWidget       = NULL;
94     stackCentralOldWidget= NULL;
95     sysTray              = NULL;
96     fullscreenControls   = NULL;
97     cryptedLabel         = NULL;
98     controls             = NULL;
99     inputC               = NULL;
100
101     b_hideAfterCreation  = false; // --qt-start-minimized
102     playlistVisible      = false;
103     input_name           = "";
104     b_interfaceFullScreen= false;
105     b_hasPausedWhenMinimized = false;
106     i_kc_offset          = false;
107
108     /* Ask for Privacy */
109     FirstRun::CheckAndRun( this, p_intf );
110
111     /**
112      *  Configuration and settings
113      *  Pre-building of interface
114      **/
115     /* Main settings */
116     setFocusPolicy( Qt::StrongFocus );
117     setAcceptDrops( true );
118     setWindowRole( "vlc-main" );
119     setWindowIcon( QApplication::windowIcon() );
120     setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
121 #ifdef Q_OS_MAC
122     setAttribute( Qt::WA_MacBrushedMetal );
123 #endif
124
125     /* Is video in embedded in the UI or not */
126     b_videoEmbedded = var_InheritBool( p_intf, "embedded-video" );
127
128     /* Does the interface resize to video size or the opposite */
129     b_autoresize = var_InheritBool( p_intf, "qt-video-autoresize" );
130
131     /* Are we in the enhanced always-video mode or not ? */
132     b_minimalView = var_InheritBool( p_intf, "qt-minimal-view" );
133
134     /* Do we want anoying popups or not */
135     i_notificationSetting = var_InheritInteger( p_intf, "qt-notification" );
136
137     /* */
138     b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
139
140     /* Set the other interface settings */
141     settings = getSettings();
142
143 #ifdef _WIN32
144     /* Volume keys */
145     p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
146 #endif
147
148     /* */
149     b_plDocked = getSettings()->value( "MainWindow/pl-dock-status", true ).toBool();
150
151
152     /**************************
153      *  UI and Widgets design
154      **************************/
155     setVLCWindowsTitle();
156
157     /************
158      * Menu Bar *
159      ************/
160     VLCMenuBar::createMenuBar( this, p_intf );
161     CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
162              THEDP, destroyPopupMenu() );
163
164     createMainWidget( settings );
165
166     /**************
167      * Status Bar *
168      **************/
169     createStatusBar();
170     setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );
171
172 #ifdef _WIN32
173     himl = NULL;
174     p_taskbl = NULL;
175     taskbar_wmsg = RegisterWindowMessage(TEXT("TaskbarButtonCreated"));
176 #endif
177
178     /*********************************
179      * Create the Systray Management *
180      *********************************/
181     initSystray();
182
183     /*************************************************************
184      * Connect the input manager to the GUI elements it manages  *
185      * Beware initSystray did some connects on input manager too *
186      *************************************************************/
187     /**
188      * Connects on nameChanged()
189      * Those connects are different because options can impeach them to trigger.
190      **/
191     /* Main Interface statusbar */
192     CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
193              this, setName( const QString& ) );
194     /* and title of the Main Interface*/
195     if( var_InheritBool( p_intf, "qt-name-in-title" ) )
196     {
197         CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
198                  this, setVLCWindowsTitle( const QString& ) );
199     }
200     /* END CONNECTS ON IM */
201
202     /* VideoWidget connects for asynchronous calls */
203     b_videoFullScreen = false;
204     connect( this, SIGNAL(askGetVideo(WId*,int*,int*,unsigned*,unsigned *)),
205              this, SLOT(getVideoSlot(WId*,int*,int*,unsigned*,unsigned*)),
206              Qt::BlockingQueuedConnection );
207     connect( this, SIGNAL(askReleaseVideo( void )),
208              this, SLOT(releaseVideoSlot( void )),
209              Qt::BlockingQueuedConnection );
210     CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
211
212     if( videoWidget )
213     {
214         if( b_autoresize )
215         {
216             CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
217                      this, setVideoSize( unsigned int, unsigned int ) );
218             CONNECT( videoWidget, sizeChanged( int, int ),
219                      this, videoSizeChanged( int,  int ) );
220         }
221         CONNECT( this, askVideoSetFullScreen( bool ),
222                  this, setVideoFullScreen( bool ) );
223     }
224
225     CONNECT( THEDP, toolBarConfUpdated(), this, toolBarConfUpdated() );
226     installEventFilter( this );
227
228     CONNECT( this, askToQuit(), THEDP, quit() );
229
230     CONNECT( this, askBoss(), this, setBoss() );
231     CONNECT( this, askRaise(), this, setRaise() );
232
233     /** END of CONNECTS**/
234
235
236     /************
237      * Callbacks
238      ************/
239     var_AddCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
240     var_AddCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
241     var_AddCallback( p_intf->p_libvlc, "intf-show", IntfRaiseMainCB, p_intf );
242
243     /* Register callback for the intf-popupmenu variable */
244     var_AddCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
245
246
247     /* Final Sizing, restoration and placement of the interface */
248     if( settings->value( "MainWindow/playlist-visible", false ).toBool() )
249         togglePlaylist();
250
251     QVLCTools::restoreWidgetPosition( settings, this, QSize(600, 420) );
252
253     b_interfaceFullScreen = isFullScreen();
254
255     setVisible( !b_hideAfterCreation );
256
257     /* Switch to minimal view if needed, must be called after the show() */
258     if( b_minimalView )
259         toggleMinimalView( true );
260
261     computeMinimumSize();
262 }
263
264 MainInterface::~MainInterface()
265 {
266     /* Unsure we hide the videoWidget before destroying it */
267     if( stackCentralOldWidget == videoWidget )
268         showTab( bgWidget );
269
270     if( videoWidget )
271         releaseVideoSlot();
272
273 #ifdef _WIN32
274     if( himl )
275         ImageList_Destroy( himl );
276     if(p_taskbl)
277         p_taskbl->Release();
278     CoUninitialize();
279 #endif
280
281     /* Be sure to kill the actionsManager... Only used in the MI and control */
282     ActionsManager::killInstance();
283
284     /* Delete the FSC controller */
285     delete fullscreenControls;
286
287     /* Save states */
288
289     settings->beginGroup("MainWindow");
290     settings->setValue( "pl-dock-status", b_plDocked );
291
292     /* Save playlist state */
293     settings->setValue( "playlist-visible", playlistVisible );
294
295     settings->setValue( "adv-controls",
296                         getControlsVisibilityStatus() & CONTROLS_ADVANCED );
297     settings->setValue( "status-bar-visible", b_statusbarVisible );
298
299     /* Save the stackCentralW sizes */
300     settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
301     settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
302     settings->endGroup();
303
304     /* Save this size */
305     QVLCTools::saveWidgetPosition(settings, this);
306
307     /* Unregister callbacks */
308     var_DelCallback( p_intf->p_libvlc, "intf-boss", IntfBossCB, p_intf );
309     var_DelCallback( p_intf->p_libvlc, "intf-show", IntfRaiseMainCB, p_intf );
310     var_DelCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
311     var_DelCallback( p_intf->p_libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
312
313     p_intf->p_sys->p_mi = NULL;
314 }
315
316 void MainInterface::computeMinimumSize()
317 {
318     int minWidth = 80;
319     if( menuBar()->isVisible() )
320         minWidth += controls->sizeHint().width();
321
322     setMinimumWidth( minWidth );
323 }
324
325 /*****************************
326  *   Main UI handling        *
327  *****************************/
328 void MainInterface::recreateToolbars()
329 {
330     bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
331
332     delete controls;
333     delete inputC;
334
335     controls = new ControlsWidget( p_intf, b_adv, this );
336     inputC = new InputControlsWidget( p_intf, this );
337     mainLayout->insertWidget( 2, inputC );
338     mainLayout->insertWidget( settings->value( "MainWindow/ToolbarPos", 0 ).toInt() ? 0: 3,
339                               controls );
340
341     if( fullscreenControls )
342     {
343         delete fullscreenControls;
344         fullscreenControls = new FullscreenControllerWidget( p_intf, this );
345         CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
346                  this, handleKeyPress( QKeyEvent * ) );
347         THEMIM->requestVoutUpdate();
348     }
349
350     setMinimalView( b_minimalView );
351 }
352
353 void MainInterface::reloadPrefs()
354 {
355     i_notificationSetting = var_InheritInteger( p_intf, "qt-notification" );
356     b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
357 #ifdef _WIN32
358     p_intf->p_sys->disable_volume_keys = var_InheritBool( p_intf, "qt-disable-volume-keys" );
359 #endif
360     if( !var_InheritBool( p_intf, "qt-fs-controller" ) && fullscreenControls )
361     {
362         delete fullscreenControls;
363         fullscreenControls = NULL;
364     }
365 }
366
367 void MainInterface::createMainWidget( QSettings *creationSettings )
368 {
369     /* Create the main Widget and the mainLayout */
370     QWidget *main = new QWidget;
371     setCentralWidget( main );
372     mainLayout = new QVBoxLayout( main );
373     main->setContentsMargins( 0, 0, 0, 0 );
374     mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
375
376     /* */
377     stackCentralW = new QVLCStackedWidget( main );
378
379     /* Bg Cone */
380     if ( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY
381          && var_InheritBool( p_intf, "qt-icon-change" ) )
382     {
383         bgWidget = new EasterEggBackgroundWidget( p_intf );
384         CONNECT( this, kc_pressed(), bgWidget, animate() );
385     }
386     else
387         bgWidget = new BackgroundWidget( p_intf );
388
389     stackCentralW->addWidget( bgWidget );
390     if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
391         bgWidget->setWithArt( false );
392     else
393         if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
394             bgWidget->setExpandstoHeight( true );
395
396     /* And video Outputs */
397     if( b_videoEmbedded )
398     {
399         videoWidget = new VideoWidget( p_intf );
400         stackCentralW->addWidget( videoWidget );
401     }
402     mainLayout->insertWidget( 1, stackCentralW );
403
404     stackWidgetsSizes[bgWidget] =
405         creationSettings->value( "MainWindow/bgSize", QSize( 600, 0 ) ).toSize();
406     /* Resize even if no-auto-resize, because we are at creation */
407     resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
408
409     /* Create the CONTROLS Widget */
410     controls = new ControlsWidget( p_intf,
411         creationSettings->value( "MainWindow/adv-controls", false ).toBool(), this );
412     inputC = new InputControlsWidget( p_intf, this );
413
414     mainLayout->insertWidget( 2, inputC );
415     mainLayout->insertWidget(
416         creationSettings->value( "MainWindow/ToolbarPos", 0 ).toInt() ? 0: 3,
417         controls );
418
419     /* Visualisation, disabled for now, they SUCK */
420     #if 0
421     visualSelector = new VisualSelector( p_intf );
422     mainLayout->insertWidget( 0, visualSelector );
423     visualSelector->hide();
424     #endif
425
426
427     /* Enable the popup menu in the MI */
428     main->setContextMenuPolicy( Qt::CustomContextMenu );
429     CONNECT( main, customContextMenuRequested( const QPoint& ),
430              THEDP, setPopupMenu() );
431
432     if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
433         /* Create the FULLSCREEN CONTROLS Widget */
434         if( var_InheritBool( p_intf, "qt-fs-controller" ) )
435         {
436             fullscreenControls = new FullscreenControllerWidget( p_intf, this );
437             CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
438                      this, handleKeyPress( QKeyEvent * ) );
439         }
440 }
441
442 inline void MainInterface::initSystray()
443 {
444     bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
445     bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
446
447     if( var_InheritBool( p_intf, "qt-start-minimized") )
448     {
449         if( b_systrayAvailable )
450         {
451             b_systrayWanted = true;
452             b_hideAfterCreation = true;
453         }
454         else
455             msg_Err( p_intf, "cannot start minimized without system tray bar" );
456     }
457
458     if( b_systrayAvailable && b_systrayWanted )
459         createSystray();
460 }
461
462 inline void MainInterface::createStatusBar()
463 {
464     /****************
465      *  Status Bar  *
466      ****************/
467     /* Widgets Creation*/
468     QStatusBar *statusBarr = statusBar();
469
470     TimeLabel *timeLabel = new TimeLabel( p_intf );
471     nameLabel = new ClickableQLabel();
472     nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
473                                       | Qt::TextSelectableByKeyboard );
474     SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
475
476     /* Styling those labels */
477     timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
478     speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
479     nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
480     timeLabel->setStyleSheet(
481             "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
482     speedLabel->setStyleSheet(
483             "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
484     /* pad both label and its tooltip */
485     nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
486
487     /* and adding those */
488     statusBarr->addWidget( nameLabel, 8 );
489     statusBarr->addPermanentWidget( speedLabel, 0 );
490     statusBarr->addPermanentWidget( timeLabel, 0 );
491
492     CONNECT( nameLabel, doubleClicked(), THEDP, epgDialog() );
493     /* timeLabel behaviour:
494        - double clicking opens the goto time dialog
495        - right-clicking and clicking just toggle between remaining and
496          elapsed time.*/
497     CONNECT( timeLabel, doubleClicked(), THEDP, gotoTimeDialog() );
498
499     CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
500              this, showCryptedLabel( bool ) );
501
502     CONNECT( THEMIM->getIM(), seekRequested( float ),
503              timeLabel, setDisplayPosition( float ) );
504
505     /* This shouldn't be necessary, but for somehow reason, the statusBarr
506        starts at height of 20px and when a text is shown it needs more space.
507        But, as the QMainWindow policy doesn't allow statusBar to change QMW's
508        geometry, we need to force a height. If you have a better idea, please
509        tell me -- jb
510      */
511     statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
512 }
513
514 /**********************************************************************
515  * Handling of sizing of the components
516  **********************************************************************/
517
518 void MainInterface::debug()
519 {
520 #ifdef DEBUG_INTF
521     if( controls ) {
522         msg_Dbg( p_intf, "Controls size: %i - %i", controls->size().height(), controls->size().width() );
523         msg_Dbg( p_intf, "Controls minimumsize: %i - %i", controls->minimumSize().height(), controls->minimumSize().width() );
524         msg_Dbg( p_intf, "Controls sizeHint: %i - %i", controls->sizeHint().height(), controls->sizeHint().width() );
525     }
526
527     msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
528     msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
529     msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
530
531     msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
532     msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
533     msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
534 #endif
535 }
536
537 inline void MainInterface::showVideo() { showTab( videoWidget ); setRaise(); }
538 inline void MainInterface::restoreStackOldWidget()
539             { showTab( stackCentralOldWidget ); }
540
541 inline void MainInterface::showTab( QWidget *widget )
542 {
543     if ( !widget ) widget = bgWidget; /* trying to restore a null oldwidget */
544 #ifdef DEBUG_INTF
545     if ( stackCentralOldWidget )
546         msg_Dbg( p_intf, "Old stackCentralOldWidget %s at index %i",
547                  stackCentralOldWidget->metaObject()->className(),
548                  stackCentralW->indexOf( stackCentralOldWidget ) );
549     msg_Dbg( p_intf, "ShowTab request for %s", widget->metaObject()->className() );
550 #endif
551     /* fixing when the playlist has been undocked after being hidden.
552        restoreStackOldWidget() is called when video stops but
553        stackCentralOldWidget would still be pointing to playlist */
554     if ( widget == playlistWidget && !isPlDocked() )
555         widget = bgWidget;
556
557     stackCentralOldWidget = stackCentralW->currentWidget();
558     stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
559
560     /* If we are playing video, embedded */
561     if( videoWidget && THEMIM->getIM()->hasVideo() )
562     {
563         /* Video -> Playlist */
564         if( videoWidget == stackCentralOldWidget && widget == playlistWidget )
565         {
566             stackCentralW->removeWidget( videoWidget );
567             videoWidget->show(); videoWidget->raise();
568         }
569
570         /* Playlist -> Video */
571         if( playlistWidget == stackCentralOldWidget && widget == videoWidget )
572         {
573             playlistWidget->artContainer->removeWidget( videoWidget );
574             videoWidget->show(); videoWidget->raise();
575             stackCentralW->addWidget( videoWidget );
576         }
577
578         /* Embedded playlist -> Non-embedded playlist */
579         if( bgWidget == stackCentralOldWidget && widget == videoWidget )
580         {
581             /* In rare case when video is started before the interface */
582             if( playlistWidget != NULL )
583                 playlistWidget->artContainer->removeWidget( videoWidget );
584             videoWidget->show(); videoWidget->raise();
585             stackCentralW->addWidget( videoWidget );
586             stackCentralW->setCurrentWidget( videoWidget );
587         }
588     }
589
590     stackCentralW->setCurrentWidget( widget );
591     if( b_autoresize )
592         resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
593
594 #ifdef DEBUG_INTF
595     msg_Dbg( p_intf, "Stack state changed to %s, index %i",
596               stackCentralW->currentWidget()->metaObject()->className(),
597               stackCentralW->currentIndex() );
598     msg_Dbg( p_intf, "New stackCentralOldWidget %s at index %i",
599               stackCentralOldWidget->metaObject()->className(),
600               stackCentralW->indexOf( stackCentralOldWidget ) );
601 #endif
602
603     /* This part is done later, to account for the new pl size */
604     if( videoWidget && THEMIM->getIM()->hasVideo() &&
605         videoWidget == stackCentralOldWidget && widget == playlistWidget )
606     {
607         playlistWidget->artContainer->addWidget( videoWidget );
608         playlistWidget->artContainer->setCurrentWidget( videoWidget );
609     }
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 Qt UI objects,
627  * from the video output thread - only from the Qt 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      * Qt 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 #ifdef _WIN32
747         changeThumbbarButtons( THEMIM->getIM()->playingStatus() );
748 #endif
749     }
750     videoWidget->sync();
751 }
752
753 /* Slot to change the video always-on-top flag.
754  * Emit askVideoOnTop() to invoke this from other thread. */
755 void MainInterface::setVideoOnTop( bool on_top )
756 {
757     Qt::WindowFlags oldflags = windowFlags(), newflags;
758
759     if( on_top )
760         newflags = oldflags | Qt::WindowStaysOnTopHint;
761     else
762         newflags = oldflags & ~Qt::WindowStaysOnTopHint;
763     if( newflags != oldflags && !b_videoFullScreen )
764
765     {
766         setWindowFlags( newflags );
767         show(); /* necessary to apply window flags */
768     }
769 }
770
771 /* Asynchronous call from WindowControl function */
772 int MainInterface::controlVideo( int i_query, va_list args )
773 {
774     switch( i_query )
775     {
776     case VOUT_WINDOW_SET_SIZE:
777     {
778         unsigned int i_width  = va_arg( args, unsigned int );
779         unsigned int i_height = va_arg( args, unsigned int );
780
781         emit askVideoToResize( i_width, i_height );
782         return VLC_SUCCESS;
783     }
784     case VOUT_WINDOW_SET_STATE:
785     {
786         unsigned i_arg = va_arg( args, unsigned );
787         unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
788
789         emit askVideoOnTop( on_top != 0 );
790         return VLC_SUCCESS;
791     }
792     case VOUT_WINDOW_SET_FULLSCREEN:
793     {
794         bool b_fs = va_arg( args, int );
795
796         emit askVideoSetFullScreen( b_fs );
797         return VLC_SUCCESS;
798     }
799     default:
800         msg_Warn( p_intf, "unsupported control query" );
801         return VLC_EGENERIC;
802     }
803 }
804
805 /*****************************************************************************
806  * Playlist, Visualisation and Menus handling
807  *****************************************************************************/
808 /**
809  * Toggle the playlist widget or dialog
810  **/
811 void MainInterface::createPlaylist()
812 {
813     PlaylistDialog *dialog = PlaylistDialog::getInstance( p_intf );
814
815     if( b_plDocked )
816     {
817         playlistWidget = dialog->exportPlaylistWidget();
818         stackCentralW->addWidget( playlistWidget );
819         stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
820     }
821     CONNECT( dialog, visibilityChanged(bool), this, setPlaylistVisibility(bool) );
822 }
823
824 void MainInterface::togglePlaylist()
825 {
826     if( !playlistWidget ) createPlaylist();
827
828     PlaylistDialog *dialog = PlaylistDialog::getInstance( p_intf );
829     if( b_plDocked )
830     {
831         if ( dialog->hasPlaylistWidget() )
832             playlistWidget = dialog->exportPlaylistWidget();
833         /* Playlist is not visible, show it */
834         if( stackCentralW->currentWidget() != playlistWidget )
835         {
836             if( stackCentralW->indexOf( playlistWidget ) == -1 )
837                 stackCentralW->addWidget( playlistWidget );
838             showTab( playlistWidget );
839         }
840         else /* Hide it! */
841         {
842             restoreStackOldWidget();
843         }
844         playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
845     }
846     else
847     {
848         playlistVisible = !playlistVisible;
849         if ( ! dialog->hasPlaylistWidget() )
850             dialog->importPlaylistWidget( playlistWidget );
851         if ( playlistVisible )
852             dialog->show();
853         else
854             dialog->hide();
855     }
856     debug();
857 }
858
859 const Qt::Key MainInterface::kc[10] =
860 {
861     Qt::Key_Up, Qt::Key_Up,
862     Qt::Key_Down, Qt::Key_Down,
863     Qt::Key_Left, Qt::Key_Right, Qt::Key_Left, Qt::Key_Right,
864     Qt::Key_B, Qt::Key_A
865 };
866
867 void MainInterface::dockPlaylist( bool p_docked )
868 {
869     if( b_plDocked == p_docked ) return;
870     /* some extra check */
871     if ( b_plDocked && !playlistWidget ) createPlaylist();
872
873     b_plDocked = p_docked;
874     PlaylistDialog *dialog = PlaylistDialog::getInstance( p_intf );
875
876     if( !p_docked ) /* Previously docked */
877     {
878         playlistVisible = playlistWidget->isVisible();
879         stackCentralW->removeWidget( playlistWidget );
880         dialog->importPlaylistWidget( playlistWidget );
881         if ( playlistVisible ) dialog->show();
882         restoreStackOldWidget();
883     }
884     else /* Previously undocked */
885     {
886         playlistVisible = dialog->isVisible();
887         dialog->hide();
888         playlistWidget = dialog->exportPlaylistWidget();
889         stackCentralW->addWidget( playlistWidget );
890
891         /* If playlist is invisible don't show it */
892         if( playlistVisible ) showTab( playlistWidget );
893     }
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 StandardPLPanel *MainInterface::getPlaylistView()
951 {
952     if( !playlistWidget ) return NULL;
953     else return playlistWidget->mainView;
954 }
955
956 void MainInterface::setStatusBarVisibility( bool b_visible )
957 {
958     statusBar()->setVisible( b_visible );
959     b_statusbarVisible = b_visible;
960     if( controls ) controls->setGripVisible( !b_statusbarVisible );
961 }
962
963
964 void MainInterface::setPlaylistVisibility( bool b_visible )
965 {
966     if( isPlDocked() || THEDP->isDying() || (playlistWidget && playlistWidget->isMinimized() ) )
967         return;
968
969     playlistVisible = b_visible;
970 }
971
972 #if 0
973 void MainInterface::visual()
974 {
975     if( !VISIBLE( visualSelector) )
976     {
977         visualSelector->show();
978         if( !THEMIM->getIM()->hasVideo() )
979         {
980             /* Show the background widget */
981         }
982         visualSelectorEnabled = true;
983     }
984     else
985     {
986         /* Stop any currently running visualization */
987         visualSelector->hide();
988         visualSelectorEnabled = false;
989     }
990 }
991 #endif
992
993 /************************************************************************
994  * Other stuff
995  ************************************************************************/
996 void MainInterface::setName( const QString& name )
997 {
998     input_name = name; /* store it for the QSystray use */
999     /* Display it in the status bar, but also as a Tooltip in case it doesn't
1000        fit in the label */
1001     nameLabel->setText( name );
1002     nameLabel->setToolTip( name );
1003 }
1004
1005 /**
1006  * Give the decorations of the Main Window a correct Name.
1007  * If nothing is given, set it to VLC...
1008  **/
1009 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
1010 {
1011     if( aTitle.isEmpty() )
1012     {
1013         setWindowTitle( qtr( "VLC media player" ) );
1014     }
1015     else
1016     {
1017         setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
1018     }
1019 }
1020
1021 void MainInterface::showCryptedLabel( bool b_show )
1022 {
1023     if( cryptedLabel == NULL )
1024     {
1025         cryptedLabel = new QLabel;
1026         // The lock icon is not the right one for DRM protection/scrambled.
1027         //cryptedLabel->setPixmap( QPixmap( ":/lock" ) );
1028         cryptedLabel->setText( "DRM" );
1029         statusBar()->addWidget( cryptedLabel );
1030     }
1031
1032     cryptedLabel->setVisible( b_show );
1033 }
1034
1035 void MainInterface::showBuffering( float f_cache )
1036 {
1037     QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
1038     statusBar()->showMessage( amount, 1000 );
1039 }
1040
1041 /*****************************************************************************
1042  * Systray Icon and Systray Menu
1043  *****************************************************************************/
1044 /**
1045  * Create a SystemTray icon and a menu that would go with it.
1046  * Connects to a click handler on the icon.
1047  **/
1048 void MainInterface::createSystray()
1049 {
1050     QIcon iconVLC;
1051     if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
1052         iconVLC = QIcon::fromTheme( "vlc-xmas", QIcon( ":/logo/vlc128-xmas.png" ) );
1053     else
1054         iconVLC = QIcon::fromTheme( "vlc", QIcon( ":/logo/vlc256.png" ) );
1055     sysTray = new QSystemTrayIcon( iconVLC, this );
1056     sysTray->setToolTip( qtr( "VLC media player" ));
1057
1058     systrayMenu = new QMenu( qtr( "VLC media player" ), this );
1059     systrayMenu->setIcon( iconVLC );
1060
1061     VLCMenuBar::updateSystrayMenu( this, p_intf, true );
1062     sysTray->show();
1063
1064     CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
1065              this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
1066
1067     /* Connects on nameChanged() */
1068     CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
1069              this, updateSystrayTooltipName( const QString& ) );
1070     /* Connect PLAY_STATUS on the systray */
1071     CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
1072              this, updateSystrayTooltipStatus( int ) );
1073 }
1074
1075 /**
1076  * Updates the Systray Icon's menu and toggle the main interface
1077  */
1078 void MainInterface::toggleUpdateSystrayMenu()
1079 {
1080     /* If hidden, show it */
1081     if( isHidden() )
1082     {
1083         show();
1084         activateWindow();
1085     }
1086     else if( isMinimized() )
1087     {
1088         /* Minimized */
1089         showNormal();
1090         activateWindow();
1091     }
1092     else
1093     {
1094         /* Visible (possibly under other windows) */
1095 #ifdef _WIN32
1096         /* check if any visible window is above vlc in the z-order,
1097          * but ignore the ones always on top
1098          * and the ones which can't be activated */
1099         HWND winId;
1100 #if HAS_QT5
1101         QWindow *window = windowHandle();
1102         winId = static_cast<HWND>(QGuiApplication::platformNativeInterface()->nativeResourceForWindow("handle", window));
1103 #else
1104         winId = internalWinId();
1105 #endif
1106
1107         WINDOWINFO wi;
1108         HWND hwnd;
1109         wi.cbSize = sizeof( WINDOWINFO );
1110         for( hwnd = GetNextWindow( winId, GW_HWNDPREV );
1111                 hwnd && ( !IsWindowVisible( hwnd ) ||
1112                     ( GetWindowInfo( hwnd, &wi ) &&
1113                       (wi.dwExStyle&WS_EX_NOACTIVATE) ) );
1114                 hwnd = GetNextWindow( hwnd, GW_HWNDPREV ) );
1115             if( !hwnd || !GetWindowInfo( hwnd, &wi ) ||
1116                 (wi.dwExStyle&WS_EX_TOPMOST) )
1117             {
1118                 hide();
1119             }
1120             else
1121             {
1122                 activateWindow();
1123             }
1124 #else
1125         hide();
1126 #endif // _WIN32
1127     }
1128     if( sysTray )
1129         VLCMenuBar::updateSystrayMenu( this, p_intf );
1130 }
1131
1132 /* First Item of the systray menu */
1133 void MainInterface::showUpdateSystrayMenu()
1134 {
1135     if( isHidden() )
1136         show();
1137     if( isMinimized() )
1138         showNormal();
1139     activateWindow();
1140
1141     VLCMenuBar::updateSystrayMenu( this, p_intf );
1142 }
1143
1144 /* First Item of the systray menu */
1145 void MainInterface::hideUpdateSystrayMenu()
1146 {
1147     hide();
1148     VLCMenuBar::updateSystrayMenu( this, p_intf );
1149 }
1150
1151 /* Click on systray Icon */
1152 void MainInterface::handleSystrayClick(
1153                                     QSystemTrayIcon::ActivationReason reason )
1154 {
1155     switch( reason )
1156     {
1157         case QSystemTrayIcon::Trigger:
1158         case QSystemTrayIcon::DoubleClick:
1159 #ifdef Q_OS_MAC
1160             VLCMenuBar::updateSystrayMenu( this, p_intf );
1161 #else
1162             toggleUpdateSystrayMenu();
1163 #endif
1164             break;
1165         case QSystemTrayIcon::MiddleClick:
1166             sysTray->showMessage( qtr( "VLC media player" ),
1167                     qtr( "Control menu for the player" ),
1168                     QSystemTrayIcon::Information, 3000 );
1169             break;
1170         default:
1171             break;
1172     }
1173 }
1174
1175 /**
1176  * Updates the name of the systray Icon tooltip.
1177  * Doesn't check if the systray exists, check before you call it.
1178  **/
1179 void MainInterface::updateSystrayTooltipName( const QString& name )
1180 {
1181     if( name.isEmpty() )
1182     {
1183         sysTray->setToolTip( qtr( "VLC media player" ) );
1184     }
1185     else
1186     {
1187         sysTray->setToolTip( name );
1188         if( ( i_notificationSetting == NOTIFICATION_ALWAYS ) ||
1189             ( i_notificationSetting == NOTIFICATION_MINIMIZED && (isMinimized() || isHidden()) ) )
1190         {
1191             sysTray->showMessage( qtr( "VLC media player" ), name,
1192                     QSystemTrayIcon::NoIcon, 3000 );
1193         }
1194     }
1195
1196     VLCMenuBar::updateSystrayMenu( this, p_intf );
1197 }
1198
1199 /**
1200  * Updates the status of the systray Icon tooltip.
1201  * Doesn't check if the systray exists, check before you call it.
1202  **/
1203 void MainInterface::updateSystrayTooltipStatus( int i_status )
1204 {
1205     switch( i_status )
1206     {
1207     case PLAYING_S:
1208         sysTray->setToolTip( input_name );
1209         break;
1210     case PAUSE_S:
1211         sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1212         break;
1213     default:
1214         sysTray->setToolTip( qtr( "VLC media player" ) );
1215         break;
1216     }
1217     VLCMenuBar::updateSystrayMenu( this, p_intf );
1218 }
1219
1220 void MainInterface::changeEvent(QEvent *event)
1221 {
1222     if( event->type() == QEvent::WindowStateChange )
1223     {
1224         QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1225         Qt::WindowStates newState = windowState();
1226         Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1227
1228         if( newState & Qt::WindowMinimized )
1229         {
1230             b_hasPausedWhenMinimized = false;
1231
1232             if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1233                 THEMIM->getIM()->hasVideo() && !THEMIM->getIM()->hasVisualisation() &&
1234                 b_pauseOnMinimize )
1235             {
1236                 b_hasPausedWhenMinimized = true;
1237                 THEMIM->pause();
1238             }
1239         }
1240         else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1241         {
1242             if( b_hasPausedWhenMinimized )
1243             {
1244                 THEMIM->play();
1245             }
1246         }
1247     }
1248
1249     QWidget::changeEvent(event);
1250 }
1251
1252 /************************************************************************
1253  * D&D Events
1254  ************************************************************************/
1255 void MainInterface::dropEvent(QDropEvent *event)
1256 {
1257     dropEventPlay( event, true );
1258 }
1259
1260 /**
1261  * dropEventPlay
1262  *
1263  * Event called if something is dropped onto a VLC window
1264  * \param event the event in question
1265  * \param b_play whether to play the file immediately
1266  * \param b_playlist true to add to playlist, false to add to media library
1267  * \return nothing
1268  */
1269 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play, bool b_playlist )
1270 {
1271     if( event->possibleActions() & ( Qt::CopyAction | Qt::MoveAction | Qt::LinkAction ) )
1272        event->setDropAction( Qt::CopyAction );
1273     else
1274         return;
1275
1276     const QMimeData *mimeData = event->mimeData();
1277
1278     /* D&D of a subtitles file, add it on the fly */
1279     if( mimeData->urls().count() == 1 && THEMIM->getIM()->hasInput() )
1280     {
1281         if( !input_AddSubtitleOSD( THEMIM->getInput(),
1282                  qtu( toNativeSeparators( mimeData->urls()[0].toLocalFile() ) ),
1283                  true, true ) )
1284         {
1285             event->accept();
1286             return;
1287         }
1288     }
1289
1290     bool first = b_play;
1291     foreach( const QUrl &url, mimeData->urls() )
1292     {
1293         if( url.isValid() )
1294         {
1295             QString mrl = toURI( url.toEncoded().constData() );
1296             QFileInfo info( url.toLocalFile() );
1297             if( info.exists() && info.isSymLink() )
1298             {
1299                 QString target = info.symLinkTarget();
1300                 QUrl url;
1301                 if( QFile::exists( target ) )
1302                 {
1303                     url = QUrl::fromLocalFile( target );
1304                 }
1305                 else
1306                 {
1307                     url.setUrl( target );
1308                 }
1309                 mrl = toURI( url.toEncoded().constData() );
1310             }
1311             if( mrl.length() > 0 )
1312             {
1313                 Open::openMRL( p_intf, mrl, first, b_playlist );
1314                 first = false;
1315             }
1316         }
1317     }
1318
1319     /* Browsers give content as text if you dnd the addressbar,
1320        so check if mimedata has valid url in text and use it
1321        if we didn't get any normal Urls()*/
1322     if( !mimeData->hasUrls() && mimeData->hasText() &&
1323         QUrl(mimeData->text()).isValid() )
1324     {
1325         QString mrl = toURI( mimeData->text() );
1326         Open::openMRL( p_intf, mrl, first, b_playlist );
1327     }
1328     event->accept();
1329 }
1330 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1331 {
1332      event->acceptProposedAction();
1333 }
1334 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1335 {
1336      event->acceptProposedAction();
1337 }
1338 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1339 {
1340      event->accept();
1341 }
1342
1343 /************************************************************************
1344  * Events stuff
1345  ************************************************************************/
1346 void MainInterface::keyPressEvent( QKeyEvent *e )
1347 {
1348     handleKeyPress( e );
1349
1350     /* easter eggs sequence handling */
1351     if ( e->key() == kc[ i_kc_offset ] )
1352         i_kc_offset++;
1353     else
1354         i_kc_offset = 0;
1355
1356     if ( i_kc_offset == (sizeof( kc ) / sizeof( Qt::Key )) )
1357     {
1358         i_kc_offset = 0;
1359         emit kc_pressed();
1360     }
1361 }
1362
1363 void MainInterface::handleKeyPress( QKeyEvent *e )
1364 {
1365     if( ( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) ) ||
1366         ( b_minimalView && !b_videoFullScreen && e->key() == Qt::Key_Escape ) )
1367     {
1368         toggleMinimalView( !b_minimalView );
1369         e->accept();
1370     }
1371
1372     int i_vlck = qtEventToVLCKey( e );
1373     if( i_vlck > 0 )
1374     {
1375         var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
1376         e->accept();
1377     }
1378     else
1379         e->ignore();
1380 }
1381
1382 void MainInterface::wheelEvent( QWheelEvent *e )
1383 {
1384     int i_vlckey = qtWheelEventToVLCKey( e );
1385     var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
1386     e->accept();
1387 }
1388
1389 void MainInterface::closeEvent( QCloseEvent *e )
1390 {
1391 //  hide();
1392     emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1393     /* Accept session quit. Otherwise we break the desktop mamager. */
1394     e->accept();
1395 }
1396
1397 bool MainInterface::eventFilter( QObject *obj, QEvent *event )
1398 {
1399     if ( event->type() == MainInterface::ToolbarsNeedRebuild ) {
1400         event->accept();
1401         recreateToolbars();
1402         return true;
1403     } else {
1404         return QObject::eventFilter( obj, event );
1405     }
1406 }
1407
1408 void MainInterface::toolBarConfUpdated()
1409 {
1410     QApplication::postEvent( this, new QEvent( MainInterface::ToolbarsNeedRebuild ) );
1411 }
1412
1413 void MainInterface::setInterfaceFullScreen( bool fs )
1414 {
1415     if( fs )
1416         setWindowState( windowState() | Qt::WindowFullScreen );
1417     else
1418         setWindowState( windowState() & ~Qt::WindowFullScreen );
1419 }
1420 void MainInterface::toggleInterfaceFullScreen()
1421 {
1422     b_interfaceFullScreen = !b_interfaceFullScreen;
1423     if( !b_videoFullScreen )
1424         setInterfaceFullScreen( b_interfaceFullScreen );
1425     emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1426 }
1427
1428 void MainInterface::emitBoss()
1429 {
1430     emit askBoss();
1431 }
1432 void MainInterface::setBoss()
1433 {
1434     THEMIM->pause();
1435     if( sysTray )
1436     {
1437         hide();
1438     }
1439     else
1440     {
1441         showMinimized();
1442     }
1443 }
1444
1445 void MainInterface::emitRaise()
1446 {
1447     emit askRaise();
1448 }
1449 void MainInterface::setRaise()
1450 {
1451     activateWindow();
1452     raise();
1453 }
1454
1455 /*****************************************************************************
1456  * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1457  *  We don't show the menu directly here because we don't want the
1458  *  caller to block for a too long time.
1459  *****************************************************************************/
1460 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
1461                         vlc_value_t old_val, vlc_value_t new_val, void *param )
1462 {
1463     VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1464
1465     intf_thread_t *p_intf = (intf_thread_t *)param;
1466
1467     if( p_intf->pf_show_dialog )
1468     {
1469         p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1470                                 new_val.b_bool, NULL );
1471     }
1472
1473     return VLC_SUCCESS;
1474 }
1475
1476 /*****************************************************************************
1477  * IntfShowCB: callback triggered by the intf-toggle-fscontrol libvlc variable.
1478  *****************************************************************************/
1479 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
1480                        vlc_value_t old_val, vlc_value_t new_val, void *param )
1481 {
1482     VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1483     VLC_UNUSED( new_val );
1484
1485     intf_thread_t *p_intf = (intf_thread_t *)param;
1486     p_intf->p_sys->p_mi->toggleFSC();
1487
1488     /* Show event */
1489      return VLC_SUCCESS;
1490 }
1491
1492 /*****************************************************************************
1493  * IntfRaiseMainCB: callback triggered by the intf-show-main libvlc variable.
1494  *****************************************************************************/
1495 static int IntfRaiseMainCB( vlc_object_t *p_this, const char *psz_variable,
1496                        vlc_value_t old_val, vlc_value_t new_val, void *param )
1497 {
1498     VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1499     VLC_UNUSED( new_val );
1500
1501     intf_thread_t *p_intf = (intf_thread_t *)param;
1502     p_intf->p_sys->p_mi->emitRaise();
1503
1504     return VLC_SUCCESS;
1505 }
1506
1507 /*****************************************************************************
1508  * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1509  *****************************************************************************/
1510 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
1511                        vlc_value_t old_val, vlc_value_t new_val, void *param )
1512 {
1513     VLC_UNUSED( p_this ); VLC_UNUSED( psz_variable ); VLC_UNUSED( old_val );
1514     VLC_UNUSED( new_val );
1515
1516     intf_thread_t *p_intf = (intf_thread_t *)param;
1517     p_intf->p_sys->p_mi->emitBoss();
1518
1519     return VLC_SUCCESS;
1520 }