Qt: fix position the toolbar above the video (fixes #15306)
[vlc.git] / modules / gui / qt / main_interface.cpp
blobb8f23632994d05b7965c45700ae9ab1985e1efef
1 /*****************************************************************************
2 * main_interface.cpp : Main interface
3 ****************************************************************************
4 * Copyright (C) 2006-2011 VideoLAN and AUTHORS
5 * $Id$
7 * Authors: Clément Stenac <zorglub@videolan.org>
8 * Jean-Baptiste Kempf <jb@videolan.org>
9 * Ilkka Ollakka <ileoo@videolan.org>
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.
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.
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 *****************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
30 #include "qt.hpp"
32 #include "main_interface.hpp"
33 #include "input_manager.hpp" // Creation
34 #include "actions_manager.hpp" // killInstance
36 #include "util/customwidgets.hpp" // qtEventToVLCKey, QVLCStackedWidget
37 #include "util/qt_dirs.hpp" // toNativeSeparators
38 #include "util/imagehelper.hpp"
40 #include "components/interface_widgets.hpp" // bgWidget, videoWidget
41 #include "components/controller.hpp" // controllers
42 #include "components/playlist/playlist.hpp" // plWidget
43 #include "dialogs/firstrun.hpp" // First Run
44 #include "dialogs/playlist.hpp" // PlaylistDialog
46 #include "menus.hpp" // Menu creation
47 #include "recents.hpp" // RecentItems when DnD
49 #include <QCloseEvent>
50 #include <QKeyEvent>
52 #include <QUrl>
53 #include <QSize>
54 #include <QDate>
55 #include <QMimeData>
57 #include <QMenu>
58 #include <QMenuBar>
59 #include <QStatusBar>
60 #include <QLabel>
61 #include <QStackedWidget>
62 #ifdef _WIN32
63 #include <QFileInfo>
64 #endif
66 #if ! HAS_QT510 && defined(QT5_HAS_X11)
67 # include <QX11Info>
68 # include <X11/Xlib.h>
69 #endif
71 #include <QTimer>
73 #include <vlc_actions.h> /* Wheel event */
74 #include <vlc_vout_display.h> /* vout_thread_t and VOUT_ events */
76 // #define DEBUG_INTF
78 /* Callback prototypes */
79 static int PopupMenuCB( 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 IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
82 vlc_value_t old_val, vlc_value_t new_val, void *param );
83 static int IntfBossCB( vlc_object_t *p_this, const char *psz_variable,
84 vlc_value_t old_val, vlc_value_t new_val, void *param );
85 static int IntfRaiseMainCB( vlc_object_t *p_this, const char *psz_variable,
86 vlc_value_t old_val, vlc_value_t new_val,
87 void *param );
89 const QEvent::Type MainInterface::ToolbarsNeedRebuild =
90 (QEvent::Type)QEvent::registerEventType();
92 MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
94 /* Variables initialisation */
95 bgWidget = NULL;
96 videoWidget = NULL;
97 playlistWidget = NULL;
98 stackCentralOldWidget= NULL;
99 sysTray = NULL;
100 fullscreenControls = NULL;
101 cryptedLabel = NULL;
102 controls = NULL;
103 inputC = NULL;
105 b_hideAfterCreation = false; // --qt-start-minimized
106 playlistVisible = false;
107 input_name = "";
108 b_interfaceFullScreen= false;
109 b_hasPausedWhenMinimized = false;
110 i_kc_offset = false;
111 b_maximizedView = false;
113 /* Ask for Privacy */
114 FirstRun::CheckAndRun( this, p_intf );
117 * Configuration and settings
118 * Pre-building of interface
120 /* Main settings */
121 setFocusPolicy( Qt::StrongFocus );
122 setAcceptDrops( true );
123 setWindowRole( "vlc-main" );
124 setWindowIcon( QApplication::windowIcon() );
125 setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
126 #ifdef Q_OS_MAC
127 setAttribute( Qt::WA_MacBrushedMetal );
128 #endif
130 /* Is video in embedded in the UI or not */
131 b_videoEmbedded = var_InheritBool( p_intf, "embedded-video" );
133 /* Does the interface resize to video size or the opposite */
134 b_autoresize = var_InheritBool( p_intf, "qt-video-autoresize" );
136 /* Are we in the enhanced always-video mode or not ? */
137 b_minimalView = var_InheritBool( p_intf, "qt-minimal-view" );
139 /* Do we want anoying popups or not */
140 i_notificationSetting = var_InheritInteger( p_intf, "qt-notification" );
142 /* */
143 b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
145 /* Set the other interface settings */
146 settings = getSettings();
148 /* */
149 b_plDocked = getSettings()->value( "MainWindow/pl-dock-status", true ).toBool();
152 /**************************
153 * UI and Widgets design
154 **************************/
155 setVLCWindowsTitle();
157 /************
158 * Menu Bar *
159 ************/
160 VLCMenuBar::createMenuBar( this, p_intf );
161 CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
162 THEDP, destroyPopupMenu() );
164 createMainWidget( settings );
166 /**************
167 * Status Bar *
168 **************/
169 createStatusBar();
170 setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );
172 /*********************************
173 * Create the Systray Management *
174 *********************************/
175 initSystray();
177 /*************************************************************
178 * Connect the input manager to the GUI elements it manages *
179 * Beware initSystray did some connects on input manager too *
180 *************************************************************/
182 * Connects on nameChanged()
183 * Those connects are different because options can impeach them to trigger.
185 /* Main Interface statusbar */
186 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
187 this, setName( const QString& ) );
188 /* and title of the Main Interface*/
189 if( var_InheritBool( p_intf, "qt-name-in-title" ) )
191 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
192 this, setVLCWindowsTitle( const QString& ) );
194 CONNECT( THEMIM, inputChanged( bool ), this, onInputChanged( bool ) );
196 /* END CONNECTS ON IM */
198 /* VideoWidget connects for asynchronous calls */
199 b_videoFullScreen = false;
200 connect( this, SIGNAL(askGetVideo(struct vout_window_t*, unsigned, unsigned, bool, bool*)),
201 this, SLOT(getVideoSlot(struct vout_window_t*, unsigned, unsigned, bool, bool*)),
202 Qt::BlockingQueuedConnection );
203 connect( this, SIGNAL(askReleaseVideo( void )),
204 this, SLOT(releaseVideoSlot( void )),
205 Qt::BlockingQueuedConnection );
206 CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
208 if( videoWidget )
210 if( b_autoresize )
212 CONNECT( videoWidget, sizeChanged( int, int ),
213 this, videoSizeChanged( int, int ) );
215 CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
216 this, setVideoSize( unsigned int, unsigned int ) );
218 CONNECT( this, askVideoSetFullScreen( bool ),
219 this, setVideoFullScreen( bool ) );
220 CONNECT( this, askHideMouse( bool ),
221 this, setHideMouse( bool ) );
224 CONNECT( THEDP, toolBarConfUpdated(), this, toolBarConfUpdated() );
225 installEventFilter( this );
227 CONNECT( this, askToQuit(), THEDP, quit() );
229 CONNECT( this, askBoss(), this, setBoss() );
230 CONNECT( this, askRaise(), this, setRaise() );
232 /** END of CONNECTS**/
235 /************
236 * Callbacks
237 ************/
238 var_AddCallback( p_intf->obj.libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
239 var_AddCallback( p_intf->obj.libvlc, "intf-boss", IntfBossCB, p_intf );
240 var_AddCallback( p_intf->obj.libvlc, "intf-show", IntfRaiseMainCB, p_intf );
242 /* Register callback for the intf-popupmenu variable */
243 var_AddCallback( p_intf->obj.libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
246 /* Final Sizing, restoration and placement of the interface */
247 if( settings->value( "MainWindow/playlist-visible", false ).toBool() )
248 togglePlaylist();
250 QVLCTools::restoreWidgetPosition( settings, this, QSize(600, 420) );
252 b_interfaceFullScreen = isFullScreen();
254 setVisible( !b_hideAfterCreation );
256 /* Switch to minimal view if needed, must be called after the show() */
257 if( b_minimalView )
258 toggleMinimalView( true );
260 computeMinimumSize();
263 MainInterface::~MainInterface()
265 /* Unsure we hide the videoWidget before destroying it */
266 if( stackCentralOldWidget == videoWidget )
267 showTab( bgWidget );
269 if( videoWidget )
270 releaseVideoSlot();
272 /* Be sure to kill the actionsManager... Only used in the MI and control */
273 ActionsManager::killInstance();
275 /* Delete the FSC controller */
276 delete fullscreenControls;
278 /* Save states */
280 settings->beginGroup("MainWindow");
281 settings->setValue( "pl-dock-status", b_plDocked );
283 /* Save playlist state */
284 settings->setValue( "playlist-visible", playlistVisible );
286 settings->setValue( "adv-controls",
287 getControlsVisibilityStatus() & CONTROLS_ADVANCED );
288 settings->setValue( "status-bar-visible", b_statusbarVisible );
290 /* Save the stackCentralW sizes */
291 settings->setValue( "bgSize", stackWidgetsSizes[bgWidget] );
292 settings->setValue( "playlistSize", stackWidgetsSizes[playlistWidget] );
293 settings->endGroup();
295 /* Save this size */
296 QVLCTools::saveWidgetPosition(settings, this);
298 /* Unregister callbacks */
299 var_DelCallback( p_intf->obj.libvlc, "intf-boss", IntfBossCB, p_intf );
300 var_DelCallback( p_intf->obj.libvlc, "intf-show", IntfRaiseMainCB, p_intf );
301 var_DelCallback( p_intf->obj.libvlc, "intf-toggle-fscontrol", IntfShowCB, p_intf );
302 var_DelCallback( p_intf->obj.libvlc, "intf-popupmenu", PopupMenuCB, p_intf );
304 p_intf->p_sys->p_mi = NULL;
307 void MainInterface::computeMinimumSize()
309 int minWidth = 80;
310 if( menuBar()->isVisible() )
311 minWidth += controls->sizeHint().width();
313 setMinimumWidth( minWidth );
316 /*****************************
317 * Main UI handling *
318 *****************************/
319 void MainInterface::recreateToolbars()
321 bool b_adv = getControlsVisibilityStatus() & CONTROLS_ADVANCED;
323 delete controls;
324 delete inputC;
326 controls = new ControlsWidget( p_intf, b_adv, this );
327 inputC = new InputControlsWidget( p_intf, this );
328 mainLayout->insertWidget( 2, inputC );
329 mainLayout->insertWidget( settings->value( "MainWindow/ToolbarPos", false ).toBool() ? 0: 3,
330 controls );
332 if( fullscreenControls )
334 delete fullscreenControls;
335 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
336 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
337 this, handleKeyPress( QKeyEvent * ) );
338 THEMIM->requestVoutUpdate();
341 setMinimalView( b_minimalView );
344 void MainInterface::reloadPrefs()
346 i_notificationSetting = var_InheritInteger( p_intf, "qt-notification" );
347 b_pauseOnMinimize = var_InheritBool( p_intf, "qt-pause-minimized" );
348 if( !var_InheritBool( p_intf, "qt-fs-controller" ) && fullscreenControls )
350 delete fullscreenControls;
351 fullscreenControls = NULL;
355 void MainInterface::createResumePanel( QWidget *w )
357 resumePanel = new QWidget( w );
358 resumePanel->hide();
359 QHBoxLayout *resumePanelLayout = new QHBoxLayout( resumePanel );
360 resumePanelLayout->setSpacing( 0 ); resumePanelLayout->setMargin( 0 );
362 QLabel *continuePixmapLabel = new QLabel();
363 continuePixmapLabel->setPixmap( ImageHelper::loadSvgToPixmap( ":/menu/help.svg" , fontMetrics().height(), fontMetrics().height()) );
364 continuePixmapLabel->setContentsMargins( 5, 0, 5, 0 );
366 QLabel *continueLabel = new QLabel( qtr( "Do you want to restart the playback where left off?") );
368 QToolButton *cancel = new QToolButton( resumePanel );
369 cancel->setAutoRaise( true );
370 cancel->setText( "X" );
372 QPushButton *ok = new QPushButton( qtr( "&Continue" ) );
374 resumePanelLayout->addWidget( continuePixmapLabel );
375 resumePanelLayout->addWidget( continueLabel );
376 resumePanelLayout->addStretch( 1 );
377 resumePanelLayout->addWidget( ok );
378 resumePanelLayout->addWidget( cancel );
380 resumeTimer = new QTimer( resumePanel );
381 resumeTimer->setSingleShot( true );
382 resumeTimer->setInterval( 6000 );
384 CONNECT( resumeTimer, timeout(), this, hideResumePanel() );
385 CONNECT( cancel, clicked(), this, hideResumePanel() );
386 CONNECT( THEMIM->getIM(), resumePlayback(int64_t), this, showResumePanel(int64_t) );
387 BUTTONACT( ok, resumePlayback() );
389 w->layout()->addWidget( resumePanel );
392 void MainInterface::showResumePanel( int64_t _time ) {
393 int setting = var_InheritInteger( p_intf, "qt-continue" );
395 if( setting == 0 )
396 return;
398 i_resumeTime = _time;
400 if( setting == 2)
401 resumePlayback();
402 else
404 if( !isFullScreen() && !isMaximized() )
405 resizeWindow( width(), height() + resumePanel->height() );
406 resumePanel->setVisible(true);
407 resumeTimer->start();
411 void MainInterface::hideResumePanel()
413 if( resumePanel->isVisible() )
415 if( !isFullScreen() && !isMaximized() )
416 resizeWindow( width(), height() - resumePanel->height() );
417 resumePanel->hide();
418 resumeTimer->stop();
422 void MainInterface::resumePlayback()
424 if( THEMIM->getIM()->hasInput() ) {
425 var_SetInteger( THEMIM->getInput(), "time", i_resumeTime );
427 hideResumePanel();
430 void MainInterface::onInputChanged( bool hasInput )
432 if( hasInput == false )
433 return;
434 int autoRaise = var_InheritInteger( p_intf, "qt-auto-raise" );
435 if ( autoRaise == MainInterface::RAISE_NEVER )
436 return;
437 if( THEMIM->getIM()->hasVideo() == true )
439 if( ( autoRaise & MainInterface::RAISE_VIDEO ) == 0 )
440 return;
442 else if ( ( autoRaise & MainInterface::RAISE_AUDIO ) == 0 )
443 return;
444 emit askRaise();
447 void MainInterface::createMainWidget( QSettings *creationSettings )
449 /* Create the main Widget and the mainLayout */
450 QWidget *main = new QWidget;
451 setCentralWidget( main );
452 mainLayout = new QVBoxLayout( main );
453 main->setContentsMargins( 0, 0, 0, 0 );
454 mainLayout->setSpacing( 0 ); mainLayout->setMargin( 0 );
456 createResumePanel( main );
457 /* */
458 stackCentralW = new QVLCStackedWidget( main );
460 /* Bg Cone */
461 if ( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY
462 && var_InheritBool( p_intf, "qt-icon-change" ) )
464 bgWidget = new EasterEggBackgroundWidget( p_intf );
465 CONNECT( this, kc_pressed(), bgWidget, animate() );
467 else
468 bgWidget = new BackgroundWidget( p_intf );
470 stackCentralW->addWidget( bgWidget );
471 if ( !var_InheritBool( p_intf, "qt-bgcone" ) )
472 bgWidget->setWithArt( false );
473 else
474 if ( var_InheritBool( p_intf, "qt-bgcone-expands" ) )
475 bgWidget->setExpandstoHeight( true );
477 /* And video Outputs */
478 if( b_videoEmbedded )
480 videoWidget = new VideoWidget( p_intf, stackCentralW );
481 stackCentralW->addWidget( videoWidget );
483 mainLayout->insertWidget( 1, stackCentralW );
485 stackWidgetsSizes[bgWidget] =
486 creationSettings->value( "MainWindow/bgSize", QSize( 600, 0 ) ).toSize();
487 /* Resize even if no-auto-resize, because we are at creation */
488 resizeStack( stackWidgetsSizes[bgWidget].width(), stackWidgetsSizes[bgWidget].height() );
490 /* Create the CONTROLS Widget */
491 controls = new ControlsWidget( p_intf,
492 creationSettings->value( "MainWindow/adv-controls", false ).toBool(), this );
493 inputC = new InputControlsWidget( p_intf, this );
495 mainLayout->insertWidget( 2, inputC );
496 mainLayout->insertWidget(
497 creationSettings->value( "MainWindow/ToolbarPos", false ).toBool() ? 0: 3,
498 controls );
500 /* Visualisation, disabled for now, they SUCK */
501 #if 0
502 visualSelector = new VisualSelector( p_intf );
503 mainLayout->insertWidget( 0, visualSelector );
504 visualSelector->hide();
505 #endif
508 /* Enable the popup menu in the MI */
509 main->setContextMenuPolicy( Qt::CustomContextMenu );
510 CONNECT( main, customContextMenuRequested( const QPoint& ),
511 THEDP, setPopupMenu() );
513 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
514 /* Create the FULLSCREEN CONTROLS Widget */
515 if( var_InheritBool( p_intf, "qt-fs-controller" ) )
517 fullscreenControls = new FullscreenControllerWidget( p_intf, this );
518 CONNECT( fullscreenControls, keyPressed( QKeyEvent * ),
519 this, handleKeyPress( QKeyEvent * ) );
523 inline void MainInterface::initSystray()
525 bool b_systrayAvailable = QSystemTrayIcon::isSystemTrayAvailable();
526 bool b_systrayWanted = var_InheritBool( p_intf, "qt-system-tray" );
528 if( var_InheritBool( p_intf, "qt-start-minimized") )
530 if( b_systrayAvailable )
532 b_systrayWanted = true;
533 b_hideAfterCreation = true;
535 else
536 msg_Err( p_intf, "cannot start minimized without system tray bar" );
539 if( b_systrayAvailable && b_systrayWanted )
540 createSystray();
543 inline void MainInterface::createStatusBar()
545 /****************
546 * Status Bar *
547 ****************/
548 /* Widgets Creation*/
549 QStatusBar *statusBarr = statusBar();
551 TimeLabel *timeLabel = new TimeLabel( p_intf );
552 nameLabel = new ClickableQLabel();
553 nameLabel->setTextInteractionFlags( Qt::TextSelectableByMouse
554 | Qt::TextSelectableByKeyboard );
555 SpeedLabel *speedLabel = new SpeedLabel( p_intf, this );
557 /* Styling those labels */
558 timeLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
559 speedLabel->setFrameStyle( QFrame::Sunken | QFrame::Panel );
560 nameLabel->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel);
561 timeLabel->setStyleSheet(
562 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
563 speedLabel->setStyleSheet(
564 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
565 /* pad both label and its tooltip */
566 nameLabel->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
568 /* and adding those */
569 statusBarr->addWidget( nameLabel, 8 );
570 statusBarr->addPermanentWidget( speedLabel, 0 );
571 statusBarr->addPermanentWidget( timeLabel, 0 );
573 CONNECT( nameLabel, doubleClicked(), THEDP, epgDialog() );
574 /* timeLabel behaviour:
575 - double clicking opens the goto time dialog
576 - right-clicking and clicking just toggle between remaining and
577 elapsed time.*/
578 CONNECT( timeLabel, doubleClicked(), THEDP, gotoTimeDialog() );
580 CONNECT( THEMIM->getIM(), encryptionChanged( bool ),
581 this, showCryptedLabel( bool ) );
583 CONNECT( THEMIM->getIM(), seekRequested( float ),
584 timeLabel, setDisplayPosition( float ) );
586 /* This shouldn't be necessary, but for somehow reason, the statusBarr
587 starts at height of 20px and when a text is shown it needs more space.
588 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
589 geometry, we need to force a height. If you have a better idea, please
590 tell me -- jb
592 statusBarr->setFixedHeight( statusBarr->sizeHint().height() + 2 );
595 /**********************************************************************
596 * Handling of sizing of the components
597 **********************************************************************/
599 void MainInterface::debug()
601 #ifdef DEBUG_INTF
602 if( controls ) {
603 msg_Dbg( p_intf, "Controls size: %i - %i", controls->size().height(), controls->size().width() );
604 msg_Dbg( p_intf, "Controls minimumsize: %i - %i", controls->minimumSize().height(), controls->minimumSize().width() );
605 msg_Dbg( p_intf, "Controls sizeHint: %i - %i", controls->sizeHint().height(), controls->sizeHint().width() );
608 msg_Dbg( p_intf, "size: %i - %i", size().height(), size().width() );
609 msg_Dbg( p_intf, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
610 msg_Dbg( p_intf, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
612 msg_Dbg( p_intf, "Stack size: %i - %i", stackCentralW->size().height(), stackCentralW->size().width() );
613 msg_Dbg( p_intf, "Stack sizeHint: %i - %i", stackCentralW->sizeHint().height(), stackCentralW->sizeHint().width() );
614 msg_Dbg( p_intf, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
615 #endif
618 inline void MainInterface::showVideo() { showTab( videoWidget ); }
619 inline void MainInterface::restoreStackOldWidget()
620 { showTab( stackCentralOldWidget ); }
622 inline void MainInterface::showTab( QWidget *widget )
624 if ( !widget ) widget = bgWidget; /* trying to restore a null oldwidget */
625 #ifdef DEBUG_INTF
626 if ( stackCentralOldWidget )
627 msg_Dbg( p_intf, "Old stackCentralOldWidget %s at index %i",
628 stackCentralOldWidget->metaObject()->className(),
629 stackCentralW->indexOf( stackCentralOldWidget ) );
630 msg_Dbg( p_intf, "ShowTab request for %s", widget->metaObject()->className() );
631 #endif
632 /* fixing when the playlist has been undocked after being hidden.
633 restoreStackOldWidget() is called when video stops but
634 stackCentralOldWidget would still be pointing to playlist */
635 if ( widget == playlistWidget && !isPlDocked() )
636 widget = bgWidget;
638 stackCentralOldWidget = stackCentralW->currentWidget();
639 stackWidgetsSizes[stackCentralOldWidget] = stackCentralW->size();
641 /* If we are playing video, embedded */
642 if( videoWidget && THEMIM->getIM()->hasVideo() )
644 /* Video -> Playlist */
645 if( videoWidget == stackCentralOldWidget && widget == playlistWidget )
647 stackCentralW->removeWidget( videoWidget );
648 videoWidget->show(); videoWidget->raise();
651 /* Playlist -> Video */
652 if( playlistWidget == stackCentralOldWidget && widget == videoWidget )
654 playlistWidget->artContainer->removeWidget( videoWidget );
655 videoWidget->show(); videoWidget->raise();
656 stackCentralW->addWidget( videoWidget );
659 /* Embedded playlist -> Non-embedded playlist */
660 if( bgWidget == stackCentralOldWidget && widget == videoWidget )
662 /* In rare case when video is started before the interface */
663 if( playlistWidget != NULL )
664 playlistWidget->artContainer->removeWidget( videoWidget );
665 videoWidget->show(); videoWidget->raise();
666 stackCentralW->addWidget( videoWidget );
667 stackCentralW->setCurrentWidget( videoWidget );
671 stackCentralW->setCurrentWidget( widget );
672 if( b_autoresize )
673 resizeStack( stackWidgetsSizes[widget].width(), stackWidgetsSizes[widget].height() );
675 #ifdef DEBUG_INTF
676 msg_Dbg( p_intf, "Stack state changed to %s, index %i",
677 stackCentralW->currentWidget()->metaObject()->className(),
678 stackCentralW->currentIndex() );
679 msg_Dbg( p_intf, "New stackCentralOldWidget %s at index %i",
680 stackCentralOldWidget->metaObject()->className(),
681 stackCentralW->indexOf( stackCentralOldWidget ) );
682 #endif
684 /* This part is done later, to account for the new pl size */
685 if( videoWidget && THEMIM->getIM()->hasVideo() &&
686 videoWidget == stackCentralOldWidget && widget == playlistWidget )
688 playlistWidget->artContainer->addWidget( videoWidget );
689 playlistWidget->artContainer->setCurrentWidget( videoWidget );
693 void MainInterface::toggleFSC()
695 if( !fullscreenControls ) return;
697 IMEvent *eShow = new IMEvent( IMEvent::FullscreenControlToggle );
698 QApplication::postEvent( fullscreenControls, eShow );
701 /****************************************************************************
702 * Video Handling
703 ****************************************************************************/
706 * NOTE:
707 * You must not change the state of this object or other Qt UI objects,
708 * from the video output thread - only from the Qt UI main loop thread.
709 * All window provider queries must be handled through signals or events.
710 * That's why we have all those emit statements...
712 bool MainInterface::getVideo( struct vout_window_t *p_wnd,
713 unsigned int i_width, unsigned int i_height,
714 bool fullscreen )
716 bool result;
718 /* This is a blocking call signal. Results are stored directly in the
719 * vout_window_t and boolean pointers. Beware of deadlocks! */
720 emit askGetVideo( p_wnd, i_width, i_height, fullscreen, &result );
721 return result;
724 void MainInterface::getVideoSlot( struct vout_window_t *p_wnd,
725 unsigned i_width, unsigned i_height,
726 bool fullscreen, bool *res )
728 /* Hidden or minimized, activate */
729 if( isHidden() || isMinimized() )
730 toggleUpdateSystrayMenu();
732 /* Request the videoWidget */
733 *res = videoWidget->request( p_wnd );
734 if( *res ) /* The videoWidget is available */
736 setVideoFullScreen( fullscreen );
738 /* Consider the video active now */
739 showVideo();
741 /* Ask videoWidget to resize correctly, if we are in normal mode */
742 if( b_autoresize ) {
743 #if HAS_QT56
744 qreal factor = videoWidget->devicePixelRatioF();
746 i_width = qRound( (qreal) i_width / factor );
747 i_height = qRound( (qreal) i_height / factor );
748 #endif
750 videoWidget->setSize( i_width, i_height );
755 /* Asynchronous call from the WindowClose function */
756 void MainInterface::releaseVideo( void )
758 emit askReleaseVideo();
761 /* Function that is CONNECTED to the previous emit */
762 void MainInterface::releaseVideoSlot( void )
764 /* This function is called when the embedded video window is destroyed,
765 * or in the rare case that the embedded window is still here but the
766 * Qt interface exits. */
767 assert( videoWidget );
768 videoWidget->release();
769 setVideoOnTop( false );
770 setVideoFullScreen( false );
771 hideResumePanel();
773 if( stackCentralW->currentWidget() == videoWidget )
774 restoreStackOldWidget();
775 else if( playlistWidget &&
776 playlistWidget->artContainer->currentWidget() == videoWidget )
778 playlistWidget->artContainer->setCurrentIndex( 0 );
779 stackCentralW->addWidget( videoWidget );
782 /* We don't want to have a blank video to popup */
783 stackCentralOldWidget = bgWidget;
786 // The provided size is in physical pixels, coming from the core.
787 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
789 if (!isFullScreen() && !isMaximized() )
791 /* Resize video widget to video size, or keep it at the same
792 * size. Call setSize() either way so that vout_window_ReportSize
793 * will always get called.
794 * If the video size is too large for the screen, resize it
795 * to the screen size.
797 if (b_autoresize)
799 QRect screen = QApplication::desktop()->availableGeometry();
800 #if HAS_QT56
801 float factor = videoWidget->devicePixelRatioF();
802 #else
803 float factor = 1.0f;
804 #endif
805 if( (float)h / factor > screen.height() )
807 w = screen.width();
808 h = screen.height();
809 if( !b_minimalView )
811 if( menuBar()->isVisible() )
812 h -= menuBar()->height();
813 if( controls->isVisible() )
814 h -= controls->height();
815 if( statusBar()->isVisible() )
816 h -= statusBar()->height();
817 if( inputC->isVisible() )
818 h -= inputC->height();
820 h -= style()->pixelMetric(QStyle::PM_TitleBarHeight);
821 h -= style()->pixelMetric(QStyle::PM_LayoutBottomMargin);
822 h -= 2 * style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
824 else
826 // Convert the size in logical pixels
827 w = qRound( (float)w / factor );
828 h = qRound( (float)h / factor );
829 msg_Dbg( p_intf, "Logical video size: %ux%u", w, h );
831 videoWidget->setSize( w, h );
833 else
834 videoWidget->setSize( videoWidget->width(), videoWidget->height() );
838 void MainInterface::videoSizeChanged( int w, int h )
840 if( !playlistWidget || playlistWidget->artContainer->currentWidget() != videoWidget )
841 resizeStack( w, h );
844 void MainInterface::setVideoFullScreen( bool fs )
846 b_videoFullScreen = fs;
847 if( fs )
849 int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
850 /* if user hasn't defined screennumber, or screennumber that is bigger
851 * than current number of screens, take screennumber where current interface
852 * is
854 if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
855 numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
857 QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
859 /* To be sure window is on proper-screen in xinerama */
860 if( !screenres.contains( pos() ) )
862 lastWinPosition = pos();
863 lastWinSize = size();
864 msg_Dbg( p_intf, "Moving video to correct position");
865 move( QPoint( screenres.x(), screenres.y() ) );
868 /* */
869 if( playlistWidget != NULL && playlistWidget->artContainer->currentWidget() == videoWidget )
871 showTab( videoWidget );
874 /* */
875 displayNormalView();
876 setInterfaceFullScreen( true );
878 else
880 setMinimalView( b_minimalView );
881 setInterfaceFullScreen( b_interfaceFullScreen );
882 if( lastWinPosition.isNull() == false )
884 move( lastWinPosition );
885 resizeWindow( lastWinSize.width(), lastWinSize.height() );
886 lastWinPosition = QPoint();
887 lastWinSize = QSize();
891 videoWidget->sync();
894 void MainInterface::setHideMouse( bool hide )
896 videoWidget->setCursor( hide ? Qt::BlankCursor : Qt::ArrowCursor );
899 /* Slot to change the video always-on-top flag.
900 * Emit askVideoOnTop() to invoke this from other thread. */
901 void MainInterface::setVideoOnTop( bool on_top )
903 Qt::WindowFlags oldflags = windowFlags(), newflags;
905 if( on_top )
906 newflags = oldflags | Qt::WindowStaysOnTopHint;
907 else
908 newflags = oldflags & ~Qt::WindowStaysOnTopHint;
909 if( newflags != oldflags && !b_videoFullScreen )
912 setWindowFlags( newflags );
913 show(); /* necessary to apply window flags */
917 /* Asynchronous call from WindowControl function */
918 int MainInterface::controlVideo( int i_query, va_list args )
920 switch( i_query )
922 case VOUT_WINDOW_SET_SIZE:
924 unsigned int i_width = va_arg( args, unsigned int );
925 unsigned int i_height = va_arg( args, unsigned int );
927 emit askVideoToResize( i_width, i_height );
928 return VLC_SUCCESS;
930 case VOUT_WINDOW_SET_STATE:
932 unsigned i_arg = va_arg( args, unsigned );
933 unsigned on_top = i_arg & VOUT_WINDOW_STATE_ABOVE;
935 emit askVideoOnTop( on_top != 0 );
936 return VLC_SUCCESS;
938 case VOUT_WINDOW_SET_FULLSCREEN:
940 bool b_fs = va_arg( args, int );
942 emit askVideoSetFullScreen( b_fs );
943 return VLC_SUCCESS;
945 case VOUT_WINDOW_HIDE_MOUSE:
947 bool b_hide = va_arg( args, int );
949 emit askHideMouse( b_hide );
950 return VLC_SUCCESS;
952 default:
953 msg_Warn( p_intf, "unsupported control query" );
954 return VLC_EGENERIC;
958 /*****************************************************************************
959 * Playlist, Visualisation and Menus handling
960 *****************************************************************************/
962 * Toggle the playlist widget or dialog
964 void MainInterface::createPlaylist()
966 PlaylistDialog *dialog = PlaylistDialog::getInstance( p_intf );
968 if( b_plDocked )
970 playlistWidget = dialog->exportPlaylistWidget();
971 stackCentralW->addWidget( playlistWidget );
972 stackWidgetsSizes[playlistWidget] = settings->value( "playlistSize", QSize( 600, 300 ) ).toSize();
974 CONNECT( dialog, visibilityChanged(bool), this, setPlaylistVisibility(bool) );
977 void MainInterface::togglePlaylist()
979 if( !playlistWidget ) createPlaylist();
981 PlaylistDialog *dialog = PlaylistDialog::getInstance( p_intf );
982 if( b_plDocked )
984 if ( dialog->hasPlaylistWidget() )
985 playlistWidget = dialog->exportPlaylistWidget();
986 /* Playlist is not visible, show it */
987 if( stackCentralW->currentWidget() != playlistWidget )
989 if( stackCentralW->indexOf( playlistWidget ) == -1 )
990 stackCentralW->addWidget( playlistWidget );
991 showTab( playlistWidget );
993 else /* Hide it! */
995 restoreStackOldWidget();
997 playlistVisible = ( stackCentralW->currentWidget() == playlistWidget );
999 else
1001 playlistVisible = !playlistVisible;
1002 if ( ! dialog->hasPlaylistWidget() )
1003 dialog->importPlaylistWidget( playlistWidget );
1004 if ( playlistVisible )
1005 dialog->show();
1006 else
1007 dialog->hide();
1009 debug();
1012 const Qt::Key MainInterface::kc[10] =
1014 Qt::Key_Up, Qt::Key_Up,
1015 Qt::Key_Down, Qt::Key_Down,
1016 Qt::Key_Left, Qt::Key_Right, Qt::Key_Left, Qt::Key_Right,
1017 Qt::Key_B, Qt::Key_A
1020 void MainInterface::dockPlaylist( bool p_docked )
1022 if( b_plDocked == p_docked ) return;
1023 /* some extra check */
1024 if ( b_plDocked && !playlistWidget ) createPlaylist();
1026 b_plDocked = p_docked;
1027 PlaylistDialog *dialog = PlaylistDialog::getInstance( p_intf );
1029 if( !p_docked ) /* Previously docked */
1031 playlistVisible = playlistWidget->isVisible();
1032 stackCentralW->removeWidget( playlistWidget );
1033 dialog->importPlaylistWidget( playlistWidget );
1034 if (THEMIM->getIM()->hasVideo())
1035 showTab(videoWidget);
1036 if ( playlistVisible ) dialog->show();
1038 else /* Previously undocked */
1040 playlistVisible = dialog->isVisible();
1041 dialog->hide();
1042 playlistWidget = dialog->exportPlaylistWidget();
1043 stackCentralW->addWidget( playlistWidget );
1045 /* If playlist is invisible don't show it */
1046 if( playlistVisible ) showTab( playlistWidget );
1051 * displayNormalView is the private function used by
1052 * the SLOT setVideoFullScreen to restore the menuBar
1053 * if minimal view is off
1055 void MainInterface::displayNormalView()
1057 menuBar()->setVisible( false );
1058 controls->setVisible( false );
1059 statusBar()->setVisible( false );
1060 inputC->setVisible( false );
1064 * setMinimalView is the private function used by
1065 * the SLOT toggleMinimalView
1067 void MainInterface::setMinimalView( bool b_minimal )
1069 bool b_menuBarVisible = menuBar()->isVisible();
1070 bool b_controlsVisible = controls->isVisible();
1071 bool b_statusBarVisible = statusBar()->isVisible();
1072 bool b_inputCVisible = inputC->isVisible();
1074 if( !isFullScreen() && !isMaximized() && b_minimal )
1076 int i_heightChange = 0;
1078 if( b_menuBarVisible )
1079 i_heightChange += menuBar()->height();
1080 if( b_controlsVisible )
1081 i_heightChange += controls->height();
1082 if( b_statusBarVisible )
1083 i_heightChange += statusBar()->height();
1084 if( b_inputCVisible )
1085 i_heightChange += inputC->height();
1087 if( i_heightChange != 0 )
1088 resizeWindow( width(), height() - i_heightChange );
1091 menuBar()->setVisible( !b_minimal );
1092 controls->setVisible( !b_minimal );
1093 statusBar()->setVisible( !b_minimal && b_statusbarVisible );
1094 inputC->setVisible( !b_minimal );
1096 if( !isFullScreen() && !isMaximized() && !b_minimal )
1098 int i_heightChange = 0;
1100 if( !b_menuBarVisible && menuBar()->isVisible() )
1101 i_heightChange += menuBar()->height();
1102 if( !b_controlsVisible && controls->isVisible() )
1103 i_heightChange += controls->height();
1104 if( !b_statusBarVisible && statusBar()->isVisible() )
1105 i_heightChange += statusBar()->height();
1106 if( !b_inputCVisible && inputC->isVisible() )
1107 i_heightChange += inputC->height();
1109 if( i_heightChange != 0 )
1110 resizeWindow( width(), height() + i_heightChange );
1115 * This public SLOT is used for moving to minimal View Mode
1117 * If b_minimal is false, then we are normalView
1119 void MainInterface::toggleMinimalView( bool b_minimal )
1121 if( !b_minimalView && b_autoresize ) /* Normal mode */
1123 if( stackCentralW->currentWidget() == bgWidget )
1125 if( stackCentralW->height() < 16 )
1127 resizeStack( stackCentralW->width(), 100 );
1131 b_minimalView = b_minimal;
1132 if( !b_videoFullScreen )
1134 setMinimalView( b_minimalView );
1135 computeMinimumSize();
1138 emit minimalViewToggled( b_minimalView );
1141 /* toggling advanced controls buttons */
1142 void MainInterface::toggleAdvancedButtons()
1144 controls->toggleAdvanced();
1145 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
1148 /* Get the visibility status of the controls (hidden or not, advanced or not) */
1149 int MainInterface::getControlsVisibilityStatus()
1151 if( !controls ) return 0;
1152 return( (controls->isVisible() ? CONTROLS_VISIBLE : CONTROLS_HIDDEN )
1153 + CONTROLS_ADVANCED * controls->b_advancedVisible );
1156 StandardPLPanel *MainInterface::getPlaylistView()
1158 if( !playlistWidget ) return NULL;
1159 else return playlistWidget->mainView;
1162 void MainInterface::setStatusBarVisibility( bool b_visible )
1164 statusBar()->setVisible( b_visible );
1165 b_statusbarVisible = b_visible;
1166 if( controls ) controls->setGripVisible( !b_statusbarVisible );
1170 void MainInterface::setPlaylistVisibility( bool b_visible )
1172 if( isPlDocked() || THEDP->isDying() || (playlistWidget && playlistWidget->isMinimized() ) )
1173 return;
1175 playlistVisible = b_visible;
1178 /************************************************************************
1179 * Other stuff
1180 ************************************************************************/
1181 void MainInterface::setName( const QString& name )
1183 input_name = name; /* store it for the QSystray use */
1184 /* Display it in the status bar, but also as a Tooltip in case it doesn't
1185 fit in the label */
1186 nameLabel->setText( name );
1187 nameLabel->setToolTip( name );
1191 * Give the decorations of the Main Window a correct Name.
1192 * If nothing is given, set it to VLC...
1194 void MainInterface::setVLCWindowsTitle( const QString& aTitle )
1196 if( aTitle.isEmpty() )
1198 setWindowTitle( qtr( "VLC media player" ) );
1200 else
1202 setWindowTitle( aTitle + " - " + qtr( "VLC media player" ) );
1206 void MainInterface::showCryptedLabel( bool b_show )
1208 if( cryptedLabel == NULL )
1210 cryptedLabel = new QLabel;
1211 // The lock icon is not the right one for DRM protection/scrambled.
1212 //cryptedLabel->setPixmap( QPixmap( ":/lock.svg" ) );
1213 cryptedLabel->setText( "DRM" );
1214 statusBar()->addWidget( cryptedLabel );
1217 cryptedLabel->setVisible( b_show );
1220 void MainInterface::showBuffering( float f_cache )
1222 QString amount = QString("Buffering: %1%").arg( (int)(100*f_cache) );
1223 statusBar()->showMessage( amount, 1000 );
1226 /*****************************************************************************
1227 * Systray Icon and Systray Menu
1228 *****************************************************************************/
1230 * Create a SystemTray icon and a menu that would go with it.
1231 * Connects to a click handler on the icon.
1233 void MainInterface::createSystray()
1235 QIcon iconVLC;
1236 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY && var_InheritBool( p_intf, "qt-icon-change" ) )
1237 iconVLC = QIcon::fromTheme( "vlc-xmas", QIcon( ":/logo/vlc128-xmas.png" ) );
1238 else
1239 iconVLC = QIcon::fromTheme( "vlc", QIcon( ":/logo/vlc256.png" ) );
1240 sysTray = new QSystemTrayIcon( iconVLC, this );
1241 sysTray->setToolTip( qtr( "VLC media player" ));
1243 systrayMenu = new QMenu( qtr( "VLC media player" ), this );
1244 systrayMenu->setIcon( iconVLC );
1246 VLCMenuBar::updateSystrayMenu( this, p_intf, true );
1247 sysTray->show();
1249 CONNECT( sysTray, activated( QSystemTrayIcon::ActivationReason ),
1250 this, handleSystrayClick( QSystemTrayIcon::ActivationReason ) );
1252 /* Connects on nameChanged() */
1253 CONNECT( THEMIM->getIM(), nameChanged( const QString& ),
1254 this, updateSystrayTooltipName( const QString& ) );
1255 /* Connect PLAY_STATUS on the systray */
1256 CONNECT( THEMIM->getIM(), playingStatusChanged( int ),
1257 this, updateSystrayTooltipStatus( int ) );
1260 void MainInterface::toggleUpdateSystrayMenuWhenVisible()
1262 hide();
1265 void MainInterface::resizeWindow(int w, int h)
1267 #if ! HAS_QT510 && defined(QT5_HAS_X11)
1268 if( QX11Info::isPlatformX11() )
1270 QSize size(w, h);
1271 size = size.boundedTo(maximumSize()).expandedTo(minimumSize());
1272 /* X11 window managers are not required to accept geometry changes on
1273 * the top-level window. Unfortunately, Qt < 5.10 assumes that the
1274 * change will succeed, and resizes all sub-windows unconditionally.
1275 * By calling XMoveResizeWindow directly, Qt will not see our change
1276 * request until the ConfigureNotify event on success
1277 * and not at all if it is rejected. */
1278 XMoveResizeWindow( QX11Info::display(), winId(),
1279 geometry().x(), geometry().y(),
1280 (unsigned int)size.width(), (unsigned int)size.height());
1281 return;
1283 #endif
1284 resize(w, h);
1288 * Updates the Systray Icon's menu and toggle the main interface
1290 void MainInterface::toggleUpdateSystrayMenu()
1292 /* If hidden, show it */
1293 if( isHidden() )
1295 show();
1296 activateWindow();
1298 else if( isMinimized() )
1300 /* Minimized */
1301 showNormal();
1302 activateWindow();
1304 else
1306 /* Visible (possibly under other windows) */
1307 toggleUpdateSystrayMenuWhenVisible();
1309 if( sysTray )
1310 VLCMenuBar::updateSystrayMenu( this, p_intf );
1313 /* First Item of the systray menu */
1314 void MainInterface::showUpdateSystrayMenu()
1316 if( isHidden() )
1317 show();
1318 if( isMinimized() )
1319 showNormal();
1320 activateWindow();
1322 VLCMenuBar::updateSystrayMenu( this, p_intf );
1325 /* First Item of the systray menu */
1326 void MainInterface::hideUpdateSystrayMenu()
1328 hide();
1329 VLCMenuBar::updateSystrayMenu( this, p_intf );
1332 /* Click on systray Icon */
1333 void MainInterface::handleSystrayClick(
1334 QSystemTrayIcon::ActivationReason reason )
1336 switch( reason )
1338 case QSystemTrayIcon::Trigger:
1339 case QSystemTrayIcon::DoubleClick:
1340 #ifdef Q_OS_MAC
1341 VLCMenuBar::updateSystrayMenu( this, p_intf );
1342 #else
1343 toggleUpdateSystrayMenu();
1344 #endif
1345 break;
1346 case QSystemTrayIcon::MiddleClick:
1347 sysTray->showMessage( qtr( "VLC media player" ),
1348 qtr( "Control menu for the player" ),
1349 QSystemTrayIcon::Information, 3000 );
1350 break;
1351 default:
1352 break;
1357 * Updates the name of the systray Icon tooltip.
1358 * Doesn't check if the systray exists, check before you call it.
1360 void MainInterface::updateSystrayTooltipName( const QString& name )
1362 if( name.isEmpty() )
1364 sysTray->setToolTip( qtr( "VLC media player" ) );
1366 else
1368 sysTray->setToolTip( name );
1369 if( ( i_notificationSetting == NOTIFICATION_ALWAYS ) ||
1370 ( i_notificationSetting == NOTIFICATION_MINIMIZED && (isMinimized() || isHidden()) ) )
1372 sysTray->showMessage( qtr( "VLC media player" ), name,
1373 QSystemTrayIcon::NoIcon, 3000 );
1377 VLCMenuBar::updateSystrayMenu( this, p_intf );
1381 * Updates the status of the systray Icon tooltip.
1382 * Doesn't check if the systray exists, check before you call it.
1384 void MainInterface::updateSystrayTooltipStatus( int i_status )
1386 switch( i_status )
1388 case PLAYING_S:
1389 sysTray->setToolTip( input_name );
1390 break;
1391 case PAUSE_S:
1392 sysTray->setToolTip( input_name + " - " + qtr( "Paused") );
1393 break;
1394 default:
1395 sysTray->setToolTip( qtr( "VLC media player" ) );
1396 break;
1398 VLCMenuBar::updateSystrayMenu( this, p_intf );
1401 void MainInterface::changeEvent(QEvent *event)
1403 if( event->type() == QEvent::WindowStateChange )
1405 QWindowStateChangeEvent *windowStateChangeEvent = static_cast<QWindowStateChangeEvent*>(event);
1406 Qt::WindowStates newState = windowState();
1407 Qt::WindowStates oldState = windowStateChangeEvent->oldState();
1409 /* b_maximizedView stores if the window was maximized before entering fullscreen.
1410 * It is set when entering maximized mode, unset when leaving it to normal mode.
1411 * Upon leaving full screen, if b_maximizedView is set,
1412 * the window should be maximized again. */
1413 if( newState & Qt::WindowMaximized &&
1414 !( oldState & Qt::WindowMaximized ) )
1415 b_maximizedView = true;
1417 if( !( newState & Qt::WindowMaximized ) &&
1418 oldState & Qt::WindowMaximized &&
1419 !b_videoFullScreen )
1420 b_maximizedView = false;
1422 if( !( newState & Qt::WindowFullScreen ) &&
1423 oldState & Qt::WindowFullScreen &&
1424 b_maximizedView )
1426 showMaximized();
1427 return;
1430 if( newState & Qt::WindowMinimized )
1432 b_hasPausedWhenMinimized = false;
1434 if( THEMIM->getIM()->playingStatus() == PLAYING_S &&
1435 THEMIM->getIM()->hasVideo() && !THEMIM->getIM()->hasVisualisation() &&
1436 b_pauseOnMinimize )
1438 b_hasPausedWhenMinimized = true;
1439 THEMIM->pause();
1442 else if( oldState & Qt::WindowMinimized && !( newState & Qt::WindowMinimized ) )
1444 if( b_hasPausedWhenMinimized )
1446 THEMIM->play();
1451 QWidget::changeEvent(event);
1454 /************************************************************************
1455 * D&D Events
1456 ************************************************************************/
1457 void MainInterface::dropEvent(QDropEvent *event)
1459 dropEventPlay( event, true );
1463 * dropEventPlay
1465 * Event called if something is dropped onto a VLC window
1466 * \param event the event in question
1467 * \param b_play whether to play the file immediately
1468 * \param b_playlist true to add to playlist, false to add to media library
1469 * \return nothing
1471 void MainInterface::dropEventPlay( QDropEvent *event, bool b_play, bool b_playlist )
1473 if( event->possibleActions() & ( Qt::CopyAction | Qt::MoveAction | Qt::LinkAction ) )
1474 event->setDropAction( Qt::CopyAction );
1475 else
1476 return;
1478 const QMimeData *mimeData = event->mimeData();
1480 /* D&D of a subtitles file, add it on the fly */
1481 if( mimeData->urls().count() == 1 && THEMIM->getIM()->hasInput() )
1483 if( !input_AddSlave( THEMIM->getInput(), SLAVE_TYPE_SPU,
1484 qtu( mimeData->urls()[0].toString() ), true, true, true ) )
1486 event->accept();
1487 return;
1491 bool first = b_play;
1492 foreach( const QUrl &url, mimeData->urls() )
1494 if( url.isValid() )
1496 QString mrl = toURI( url.toEncoded().constData() );
1497 #ifdef _WIN32
1498 QFileInfo info( url.toLocalFile() );
1499 if( info.exists() && info.isSymLink() )
1501 QString target = info.symLinkTarget();
1502 QUrl url;
1503 if( QFile::exists( target ) )
1505 url = QUrl::fromLocalFile( target );
1507 else
1509 url.setUrl( target );
1511 mrl = toURI( url.toEncoded().constData() );
1513 #endif
1514 if( mrl.length() > 0 )
1516 Open::openMRL( p_intf, mrl, first, b_playlist );
1517 first = false;
1522 /* Browsers give content as text if you dnd the addressbar,
1523 so check if mimedata has valid url in text and use it
1524 if we didn't get any normal Urls()*/
1525 if( !mimeData->hasUrls() && mimeData->hasText() &&
1526 QUrl(mimeData->text()).isValid() )
1528 QString mrl = toURI( mimeData->text() );
1529 Open::openMRL( p_intf, mrl, first, b_playlist );
1531 event->accept();
1533 void MainInterface::dragEnterEvent(QDragEnterEvent *event)
1535 event->acceptProposedAction();
1537 void MainInterface::dragMoveEvent(QDragMoveEvent *event)
1539 event->acceptProposedAction();
1541 void MainInterface::dragLeaveEvent(QDragLeaveEvent *event)
1543 event->accept();
1546 /************************************************************************
1547 * Events stuff
1548 ************************************************************************/
1549 void MainInterface::keyPressEvent( QKeyEvent *e )
1551 handleKeyPress( e );
1553 /* easter eggs sequence handling */
1554 if ( e->key() == kc[ i_kc_offset ] )
1555 i_kc_offset++;
1556 else
1557 i_kc_offset = 0;
1559 if ( i_kc_offset == (sizeof( kc ) / sizeof( Qt::Key )) )
1561 i_kc_offset = 0;
1562 emit kc_pressed();
1566 void MainInterface::handleKeyPress( QKeyEvent *e )
1568 if( ( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) ) ||
1569 ( b_minimalView && !b_videoFullScreen && e->key() == Qt::Key_Escape ) )
1571 toggleMinimalView( !b_minimalView );
1572 e->accept();
1574 else if( ( e->modifiers() & Qt::ControlModifier ) && ( e->key() == Qt::Key_K ) &&
1575 playlistWidget )
1577 playlistWidget->setSearchFieldFocus();
1578 e->accept();
1581 int i_vlck = qtEventToVLCKey( e );
1582 if( i_vlck > 0 )
1584 var_SetInteger( p_intf->obj.libvlc, "key-pressed", i_vlck );
1585 e->accept();
1587 else
1588 e->ignore();
1591 void MainInterface::wheelEvent( QWheelEvent *e )
1593 int i_vlckey = qtWheelEventToVLCKey( e );
1594 var_SetInteger( p_intf->obj.libvlc, "key-pressed", i_vlckey );
1595 e->accept();
1598 void MainInterface::closeEvent( QCloseEvent *e )
1600 // hide();
1601 if ( b_minimalView )
1602 setMinimalView( false );
1603 emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
1604 /* Accept session quit. Otherwise we break the desktop mamager. */
1605 e->accept();
1608 bool MainInterface::eventFilter( QObject *obj, QEvent *event )
1610 if ( event->type() == MainInterface::ToolbarsNeedRebuild ) {
1611 event->accept();
1612 recreateToolbars();
1613 return true;
1614 } else {
1615 return QObject::eventFilter( obj, event );
1619 void MainInterface::toolBarConfUpdated()
1621 QApplication::postEvent( this, new QEvent( MainInterface::ToolbarsNeedRebuild ) );
1624 void MainInterface::setInterfaceFullScreen( bool fs )
1626 if( fs )
1627 setWindowState( windowState() | Qt::WindowFullScreen );
1628 else
1629 setWindowState( windowState() & ~Qt::WindowFullScreen );
1631 void MainInterface::toggleInterfaceFullScreen()
1633 b_interfaceFullScreen = !b_interfaceFullScreen;
1634 if( !b_videoFullScreen )
1635 setInterfaceFullScreen( b_interfaceFullScreen );
1636 emit fullscreenInterfaceToggled( b_interfaceFullScreen );
1639 void MainInterface::emitBoss()
1641 emit askBoss();
1643 void MainInterface::setBoss()
1645 THEMIM->pause();
1646 if( sysTray )
1648 hide();
1650 else
1652 showMinimized();
1656 void MainInterface::emitRaise()
1658 emit askRaise();
1660 void MainInterface::setRaise()
1662 activateWindow();
1663 raise();
1666 /*****************************************************************************
1667 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1668 * We don't show the menu directly here because we don't want the
1669 * caller to block for a too long time.
1670 *****************************************************************************/
1671 static int PopupMenuCB( vlc_object_t *, const char *,
1672 vlc_value_t, vlc_value_t new_val, void *param )
1674 intf_thread_t *p_intf = (intf_thread_t *)param;
1676 if( p_intf->pf_show_dialog )
1678 p_intf->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
1679 new_val.b_bool, NULL );
1682 return VLC_SUCCESS;
1685 /*****************************************************************************
1686 * IntfShowCB: callback triggered by the intf-toggle-fscontrol libvlc variable.
1687 *****************************************************************************/
1688 static int IntfShowCB( vlc_object_t *, const char *,
1689 vlc_value_t, vlc_value_t, void *param )
1691 intf_thread_t *p_intf = (intf_thread_t *)param;
1692 p_intf->p_sys->p_mi->toggleFSC();
1694 /* Show event */
1695 return VLC_SUCCESS;
1698 /*****************************************************************************
1699 * IntfRaiseMainCB: callback triggered by the intf-show-main libvlc variable.
1700 *****************************************************************************/
1701 static int IntfRaiseMainCB( vlc_object_t *, const char *,
1702 vlc_value_t, vlc_value_t, void *param )
1704 intf_thread_t *p_intf = (intf_thread_t *)param;
1705 p_intf->p_sys->p_mi->emitRaise();
1707 return VLC_SUCCESS;
1710 /*****************************************************************************
1711 * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1712 *****************************************************************************/
1713 static int IntfBossCB( vlc_object_t *, const char *,
1714 vlc_value_t, vlc_value_t, void *param )
1716 intf_thread_t *p_intf = (intf_thread_t *)param;
1717 p_intf->p_sys->p_mi->emitBoss();
1719 return VLC_SUCCESS;