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