1 /*****************************************************************************
2 * main_interface.cpp : Main interface
3 ****************************************************************************
4 * Copyright (C) 2006-2011 VideoLAN and AUTHORS
6 * Authors: Clément Stenac <zorglub@videolan.org>
7 * Jean-Baptiste Kempf <jb@videolan.org>
8 * Ilkka Ollakka <ileoo@videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
31 #include "main_interface.hpp"
32 #include "input_manager.hpp" // Creation
33 #include "actions_manager.hpp" // killInstance
34 #include "managers/renderer_manager.hpp"
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>
62 #include <QStackedWidget>
68 #if ! HAS_QT510 && defined(QT5_HAS_X11)
70 # include <X11/Xlib.h>
75 #include <vlc_actions.h> /* Wheel event */
76 #include <vlc_vout_window.h> /* VOUT_ events */
80 /* Callback prototypes */
81 static int PopupMenuCB( 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 IntfShowCB( 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 IntfBossCB( vlc_object_t
*p_this
, const char *psz_variable
,
86 vlc_value_t old_val
, vlc_value_t new_val
, void *param
);
87 static int IntfRaiseMainCB( vlc_object_t
*p_this
, const char *psz_variable
,
88 vlc_value_t old_val
, vlc_value_t new_val
,
91 const QEvent::Type
MainInterface::ToolbarsNeedRebuild
=
92 (QEvent::Type
)QEvent::registerEventType();
94 MainInterface::MainInterface( intf_thread_t
*_p_intf
) : QVLCMW( _p_intf
),
95 videoActive( ATOMIC_FLAG_INIT
)
97 /* Variables initialisation */
100 playlistWidget
= NULL
;
101 stackCentralOldWidget
= NULL
;
102 lastWinScreen
= NULL
;
104 fullscreenControls
= NULL
;
109 b_hideAfterCreation
= false; // --qt-start-minimized
110 playlistVisible
= false;
112 b_interfaceFullScreen
= false;
113 b_hasPausedWhenMinimized
= false;
115 b_maximizedView
= false;
116 b_isWindowTiled
= false;
118 /* Ask for Privacy */
119 FirstRun::CheckAndRun( this, p_intf
);
122 * Configuration and settings
123 * Pre-building of interface
126 setFocusPolicy( Qt::StrongFocus
);
127 setAcceptDrops( true );
128 setWindowRole( "vlc-main" );
129 setWindowIcon( QApplication::windowIcon() );
130 setWindowOpacity( var_InheritFloat( p_intf
, "qt-opacity" ) );
132 /* Does the interface resize to video size or the opposite */
133 b_autoresize
= var_InheritBool( p_intf
, "qt-video-autoresize" );
135 /* Are we in the enhanced always-video mode or not ? */
136 b_minimalView
= var_InheritBool( p_intf
, "qt-minimal-view" );
138 /* Do we want anoying popups or not */
139 i_notificationSetting
= var_InheritInteger( p_intf
, "qt-notification" );
142 b_pauseOnMinimize
= var_InheritBool( p_intf
, "qt-pause-minimized" );
144 /* Set the other interface settings */
145 settings
= getSettings();
148 b_plDocked
= getSettings()->value( "MainWindow/pl-dock-status", true ).toBool();
150 /* Should the UI stays on top of other windows */
151 b_interfaceOnTop
= var_InheritBool( p_intf
, "video-on-top" );
153 #ifdef QT5_HAS_WAYLAND
154 b_hasWayland
= QGuiApplication::platformName()
155 .startsWith(QLatin1String("wayland"), Qt::CaseInsensitive
);
158 /**************************
159 * UI and Widgets design
160 **************************/
161 setVLCWindowsTitle();
166 VLCMenuBar::createMenuBar( this, p_intf
);
167 CONNECT( THEMIM
->getIM(), voutListChanged( vout_thread_t
**, int ),
168 THEDP
, destroyPopupMenu() );
170 createMainWidget( settings
);
176 setStatusBarVisibility( getSettings()->value( "MainWindow/status-bar-visible", false ).toBool() );
178 /*********************************
179 * Create the Systray Management *
180 *********************************/
183 /*************************************************************
184 * Connect the input manager to the GUI elements it manages *
185 * Beware initSystray did some connects on input manager too *
186 *************************************************************/
188 * Connects on nameChanged()
189 * Those connects are different because options can impeach them to trigger.
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" ) )
197 CONNECT( THEMIM
->getIM(), nameChanged( const QString
& ),
198 this, setVLCWindowsTitle( const QString
& ) );
200 CONNECT( THEMIM
, inputChanged( bool ), this, onInputChanged( bool ) );
202 /* END CONNECTS ON IM */
204 /* VideoWidget connects for asynchronous calls */
205 b_videoFullScreen
= false;
206 connect( this, SIGNAL(askGetVideo(struct vout_window_t
*, unsigned, unsigned, bool)),
207 this, SLOT(getVideoSlot(struct vout_window_t
*, unsigned, unsigned, bool)),
208 Qt::BlockingQueuedConnection
);
209 connect( this, SIGNAL(askReleaseVideo( void )),
210 this, SLOT(releaseVideoSlot( void )),
211 Qt::BlockingQueuedConnection
);
212 CONNECT( this, askVideoOnTop(bool), this, setVideoOnTop(bool));
218 CONNECT( videoWidget
, sizeChanged( int, int ),
219 this, videoSizeChanged( int, int ) );
221 CONNECT( this, askVideoToResize( unsigned int, unsigned int ),
222 this, setVideoSize( unsigned int, unsigned int ) );
224 CONNECT( this, askVideoSetFullScreen( bool ),
225 this, setVideoFullScreen( bool ) );
228 CONNECT( THEDP
, toolBarConfUpdated(), this, toolBarConfUpdated() );
229 installEventFilter( this );
231 CONNECT( this, askToQuit(), THEDP
, quit() );
233 CONNECT( this, askBoss(), this, setBoss() );
234 CONNECT( this, askRaise(), this, setRaise() );
237 connect( THEDP
, &DialogsProvider::releaseMouseEvents
, this, &MainInterface::voutReleaseMouseEvents
) ;
238 /** END of CONNECTS**/
244 var_AddCallback( pl_Get(p_intf
), "intf-toggle-fscontrol", IntfShowCB
, p_intf
);
245 var_AddCallback( pl_Get(p_intf
), "intf-boss", IntfBossCB
, p_intf
);
246 var_AddCallback( pl_Get(p_intf
), "intf-show", IntfRaiseMainCB
, p_intf
);
248 /* Register callback for the intf-popupmenu variable */
249 var_AddCallback( pl_Get(p_intf
), "intf-popupmenu", PopupMenuCB
, p_intf
);
252 /* Final Sizing, restoration and placement of the interface */
253 if( settings
->value( "MainWindow/playlist-visible", false ).toBool() )
256 QVLCTools::restoreWidgetPosition( settings
, this, QSize(600, 420) );
258 b_interfaceFullScreen
= isFullScreen();
260 setVisible( !b_hideAfterCreation
);
262 /* Switch to minimal view if needed, must be called after the show() */
264 toggleMinimalView( true );
266 computeMinimumSize();
269 MainInterface::~MainInterface()
271 /* Unsure we hide the videoWidget before destroying it */
272 if( stackCentralOldWidget
== videoWidget
)
278 /* Be sure to kill the actionsManager... Only used in the MI and control */
279 ActionsManager::killInstance();
281 /* Delete the FSC controller */
282 delete fullscreenControls
;
284 RendererManager::killInstance();
288 settings
->beginGroup("MainWindow");
289 settings
->setValue( "pl-dock-status", b_plDocked
);
291 /* Save playlist state */
292 settings
->setValue( "playlist-visible", playlistVisible
);
294 settings
->setValue( "adv-controls",
295 getControlsVisibilityStatus() & CONTROLS_ADVANCED
);
296 settings
->setValue( "status-bar-visible", b_statusbarVisible
);
298 /* Save the stackCentralW sizes */
299 settings
->setValue( "bgSize", stackWidgetsSizes
[bgWidget
] );
300 settings
->setValue( "playlistSize", stackWidgetsSizes
[playlistWidget
] );
301 settings
->endGroup();
304 QVLCTools::saveWidgetPosition(settings
, this);
306 /* Unregister callbacks */
307 var_DelCallback( pl_Get(p_intf
), "intf-boss", IntfBossCB
, p_intf
);
308 var_DelCallback( pl_Get(p_intf
), "intf-show", IntfRaiseMainCB
, p_intf
);
309 var_DelCallback( pl_Get(p_intf
), "intf-toggle-fscontrol", IntfShowCB
, p_intf
);
310 var_DelCallback( pl_Get(p_intf
), "intf-popupmenu", PopupMenuCB
, p_intf
);
312 p_intf
->p_sys
->p_mi
= NULL
;
315 void MainInterface::computeMinimumSize()
318 if( menuBar()->isVisible() )
319 minWidth
+= controls
->sizeHint().width();
321 setMinimumWidth( minWidth
);
324 /*****************************
326 *****************************/
327 void MainInterface::recreateToolbars()
329 bool b_adv
= getControlsVisibilityStatus() & CONTROLS_ADVANCED
;
334 controls
= new ControlsWidget( p_intf
, b_adv
, this );
335 inputC
= new InputControlsWidget( p_intf
, this );
336 mainLayout
->insertWidget( 2, inputC
);
337 mainLayout
->insertWidget( settings
->value( "MainWindow/ToolbarPos", false ).toBool() ? 0: 3,
340 if( fullscreenControls
)
342 delete fullscreenControls
;
343 fullscreenControls
= new FullscreenControllerWidget( p_intf
, this );
344 CONNECT( fullscreenControls
, keyPressed( QKeyEvent
* ),
345 this, handleKeyPress( QKeyEvent
* ) );
346 THEMIM
->requestVoutUpdate();
349 setMinimalView( b_minimalView
);
352 void MainInterface::reloadPrefs()
354 i_notificationSetting
= var_InheritInteger( p_intf
, "qt-notification" );
355 b_pauseOnMinimize
= var_InheritBool( p_intf
, "qt-pause-minimized" );
356 if( !var_InheritBool( p_intf
, "qt-fs-controller" ) && fullscreenControls
)
358 delete fullscreenControls
;
359 fullscreenControls
= NULL
;
363 void MainInterface::createResumePanel( QWidget
*w
)
365 resumePanel
= new QWidget( w
);
367 QHBoxLayout
*resumePanelLayout
= new QHBoxLayout( resumePanel
);
368 resumePanelLayout
->setSpacing( 0 ); resumePanelLayout
->setMargin( 0 );
370 QLabel
*continuePixmapLabel
= new QLabel();
371 continuePixmapLabel
->setPixmap( ImageHelper::loadSvgToPixmap( ":/menu/help.svg" , fontMetrics().height(), fontMetrics().height()) );
372 continuePixmapLabel
->setContentsMargins( 5, 0, 5, 0 );
374 QLabel
*continueLabel
= new QLabel( qtr( "Do you want to restart the playback where left off?") );
376 QToolButton
*cancel
= new QToolButton( resumePanel
);
377 cancel
->setAutoRaise( true );
378 cancel
->setText( "X" );
380 QPushButton
*ok
= new QPushButton( qtr( "&Continue" ) );
382 resumePanelLayout
->addWidget( continuePixmapLabel
);
383 resumePanelLayout
->addWidget( continueLabel
);
384 resumePanelLayout
->addStretch( 1 );
385 resumePanelLayout
->addWidget( ok
);
386 resumePanelLayout
->addWidget( cancel
);
388 resumeTimer
= new QTimer( resumePanel
);
389 resumeTimer
->setSingleShot( true );
390 resumeTimer
->setInterval( 6000 );
392 CONNECT( resumeTimer
, timeout(), this, hideResumePanel() );
393 CONNECT( cancel
, clicked(), this, hideResumePanel() );
394 CONNECT( THEMIM
->getIM(), resumePlayback(vlc_tick_t
), this, showResumePanel(vlc_tick_t
) );
395 BUTTONACT( ok
, resumePlayback() );
397 w
->layout()->addWidget( resumePanel
);
400 void MainInterface::showResumePanel( vlc_tick_t _time
) {
401 int setting
= var_InheritInteger( p_intf
, "qt-continue" );
406 i_resumeTime
= _time
;
412 if( !isFullScreen() && !isMaximized() && !b_isWindowTiled
)
413 resizeWindow( width(), height() + resumePanel
->height() );
414 resumePanel
->setVisible(true);
415 resumeTimer
->start();
419 void MainInterface::hideResumePanel()
421 if( resumePanel
->isVisible() )
423 if( !isFullScreen() && !isMaximized() && !b_isWindowTiled
)
424 resizeWindow( width(), height() - resumePanel
->height() );
430 void MainInterface::resumePlayback()
432 if( THEMIM
->getIM()->hasInput() ) {
433 var_SetInteger( THEMIM
->getInput(), "time", i_resumeTime
);
438 void MainInterface::onInputChanged( bool hasInput
)
440 if( hasInput
== false )
442 int autoRaise
= var_InheritInteger( p_intf
, "qt-auto-raise" );
443 if ( autoRaise
== MainInterface::RAISE_NEVER
)
445 if( THEMIM
->getIM()->hasVideo() == true )
447 if( ( autoRaise
& MainInterface::RAISE_VIDEO
) == 0 )
450 else if ( ( autoRaise
& MainInterface::RAISE_AUDIO
) == 0 )
455 void MainInterface::createMainWidget( QSettings
*creationSettings
)
457 /* Create the main Widget and the mainLayout */
458 QWidget
*main
= new QWidget
;
459 setCentralWidget( main
);
460 mainLayout
= new QVBoxLayout( main
);
461 main
->setContentsMargins( 0, 0, 0, 0 );
462 mainLayout
->setSpacing( 0 ); mainLayout
->setMargin( 0 );
464 createResumePanel( main
);
466 stackCentralW
= new QVLCStackedWidget( main
);
469 if ( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY
470 && var_InheritBool( p_intf
, "qt-icon-change" ) )
472 bgWidget
= new EasterEggBackgroundWidget( p_intf
);
473 CONNECT( this, kc_pressed(), bgWidget
, animate() );
476 bgWidget
= new BackgroundWidget( p_intf
);
478 stackCentralW
->addWidget( bgWidget
);
479 if ( !var_InheritBool( p_intf
, "qt-bgcone" ) )
480 bgWidget
->setWithArt( false );
482 if ( var_InheritBool( p_intf
, "qt-bgcone-expands" ) )
483 bgWidget
->setExpandstoHeight( true );
485 /* And video Outputs */
486 if( var_InheritBool( p_intf
, "embedded-video" ) )
488 videoWidget
= new VideoWidget( p_intf
, stackCentralW
);
489 stackCentralW
->addWidget( videoWidget
);
491 mainLayout
->insertWidget( 1, stackCentralW
);
493 stackWidgetsSizes
[bgWidget
] =
494 creationSettings
->value( "MainWindow/bgSize", QSize( 600, 0 ) ).toSize();
495 /* Resize even if no-auto-resize, because we are at creation */
496 resizeStack( stackWidgetsSizes
[bgWidget
].width(), stackWidgetsSizes
[bgWidget
].height() );
498 /* Create the CONTROLS Widget */
499 controls
= new ControlsWidget( p_intf
,
500 creationSettings
->value( "MainWindow/adv-controls", false ).toBool(), this );
501 inputC
= new InputControlsWidget( p_intf
, this );
503 mainLayout
->insertWidget( 2, inputC
);
504 mainLayout
->insertWidget(
505 creationSettings
->value( "MainWindow/ToolbarPos", false ).toBool() ? 0: 3,
508 /* Visualisation, disabled for now, they SUCK */
510 visualSelector
= new VisualSelector( p_intf
);
511 mainLayout
->insertWidget( 0, visualSelector
);
512 visualSelector
->hide();
516 /* Enable the popup menu in the MI */
517 main
->setContextMenuPolicy( Qt::CustomContextMenu
);
518 CONNECT( main
, customContextMenuRequested( const QPoint
& ),
519 THEDP
, setPopupMenu() );
521 if ( depth() > 8 ) /* 8bit depth has too many issues with opacity */
522 /* Create the FULLSCREEN CONTROLS Widget */
523 if( var_InheritBool( p_intf
, "qt-fs-controller" ) )
525 fullscreenControls
= new FullscreenControllerWidget( p_intf
, this );
526 CONNECT( fullscreenControls
, keyPressed( QKeyEvent
* ),
527 this, handleKeyPress( QKeyEvent
* ) );
530 if ( b_interfaceOnTop
)
531 setWindowFlags( windowFlags() | Qt::WindowStaysOnTopHint
);
534 inline void MainInterface::initSystray()
536 bool b_systrayAvailable
= QSystemTrayIcon::isSystemTrayAvailable();
537 bool b_systrayWanted
= var_InheritBool( p_intf
, "qt-system-tray" );
539 if( var_InheritBool( p_intf
, "qt-start-minimized") )
541 if( b_systrayAvailable
)
543 b_systrayWanted
= true;
544 b_hideAfterCreation
= true;
547 msg_Err( p_intf
, "cannot start minimized without system tray bar" );
550 if( b_systrayAvailable
&& b_systrayWanted
)
554 inline void MainInterface::createStatusBar()
559 /* Widgets Creation*/
560 QStatusBar
*statusBarr
= statusBar();
562 TimeLabel
*timeLabel
= new TimeLabel( p_intf
);
563 nameLabel
= new ClickableQLabel();
564 nameLabel
->setTextInteractionFlags( Qt::TextSelectableByMouse
565 | Qt::TextSelectableByKeyboard
);
566 SpeedLabel
*speedLabel
= new SpeedLabel( p_intf
, this );
568 /* Styling those labels */
569 timeLabel
->setFrameStyle( QFrame::Sunken
| QFrame::Panel
);
570 speedLabel
->setFrameStyle( QFrame::Sunken
| QFrame::Panel
);
571 nameLabel
->setFrameStyle( QFrame::Sunken
| QFrame::StyledPanel
);
572 timeLabel
->setStyleSheet(
573 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
574 speedLabel
->setStyleSheet(
575 "QLabel:hover { background-color: rgba(255, 255, 255, 50%) }" );
576 /* pad both label and its tooltip */
577 nameLabel
->setStyleSheet( "padding-left: 5px; padding-right: 5px;" );
579 /* and adding those */
580 statusBarr
->addWidget( nameLabel
, 8 );
581 statusBarr
->addPermanentWidget( speedLabel
, 0 );
582 statusBarr
->addPermanentWidget( timeLabel
, 0 );
584 CONNECT( nameLabel
, doubleClicked(), THEDP
, epgDialog() );
585 /* timeLabel behaviour:
586 - double clicking opens the goto time dialog
587 - right-clicking and clicking just toggle between remaining and
589 CONNECT( timeLabel
, doubleClicked(), THEDP
, gotoTimeDialog() );
591 CONNECT( THEMIM
->getIM(), encryptionChanged( bool ),
592 this, showCryptedLabel( bool ) );
594 /* This shouldn't be necessary, but for somehow reason, the statusBarr
595 starts at height of 20px and when a text is shown it needs more space.
596 But, as the QMainWindow policy doesn't allow statusBar to change QMW's
597 geometry, we need to force a height. If you have a better idea, please
600 statusBarr
->setFixedHeight( statusBarr
->sizeHint().height() + 2 );
603 /**********************************************************************
604 * Handling of sizing of the components
605 **********************************************************************/
607 void MainInterface::debug()
611 msg_Dbg( p_intf
, "Controls size: %i - %i", controls
->size().height(), controls
->size().width() );
612 msg_Dbg( p_intf
, "Controls minimumsize: %i - %i", controls
->minimumSize().height(), controls
->minimumSize().width() );
613 msg_Dbg( p_intf
, "Controls sizeHint: %i - %i", controls
->sizeHint().height(), controls
->sizeHint().width() );
616 msg_Dbg( p_intf
, "size: %i - %i", size().height(), size().width() );
617 msg_Dbg( p_intf
, "sizeHint: %i - %i", sizeHint().height(), sizeHint().width() );
618 msg_Dbg( p_intf
, "minimumsize: %i - %i", minimumSize().height(), minimumSize().width() );
620 msg_Dbg( p_intf
, "Stack size: %i - %i", stackCentralW
->size().height(), stackCentralW
->size().width() );
621 msg_Dbg( p_intf
, "Stack sizeHint: %i - %i", stackCentralW
->sizeHint().height(), stackCentralW
->sizeHint().width() );
622 msg_Dbg( p_intf
, "Central size: %i - %i", centralWidget()->size().height(), centralWidget()->size().width() );
626 inline void MainInterface::showVideo() { showTab( videoWidget
); }
627 inline void MainInterface::restoreStackOldWidget( bool video_closing
)
628 { showTab( stackCentralOldWidget
, video_closing
); }
630 inline void MainInterface::showTab( QWidget
*widget
, bool video_closing
)
632 if ( !widget
) widget
= bgWidget
; /* trying to restore a null oldwidget */
634 if ( stackCentralOldWidget
)
635 msg_Dbg( p_intf
, "Old stackCentralOldWidget %s at index %i",
636 stackCentralOldWidget
->metaObject()->className(),
637 stackCentralW
->indexOf( stackCentralOldWidget
) );
638 msg_Dbg( p_intf
, "ShowTab request for %s", widget
->metaObject()->className() );
640 if ( stackCentralW
->currentWidget() == widget
)
643 /* fixing when the playlist has been undocked after being hidden.
644 restoreStackOldWidget() is called when video stops but
645 stackCentralOldWidget would still be pointing to playlist */
646 if ( widget
== playlistWidget
&& !isPlDocked() )
649 stackCentralOldWidget
= stackCentralW
->currentWidget();
650 if( !isFullScreen() )
651 stackWidgetsSizes
[stackCentralOldWidget
] = stackCentralW
->size();
653 /* If we are playing video, embedded */
654 if( !video_closing
&& videoWidget
&& THEMIM
->getIM()->hasVideo() )
656 /* Video -> Playlist */
657 if( videoWidget
== stackCentralOldWidget
&& widget
== playlistWidget
)
659 stackCentralW
->removeWidget( videoWidget
);
660 videoWidget
->show(); videoWidget
->raise();
663 /* Playlist -> Video */
664 if( playlistWidget
== stackCentralOldWidget
&& widget
== videoWidget
)
666 playlistWidget
->artContainer
->removeWidget( videoWidget
);
667 videoWidget
->show(); videoWidget
->raise();
668 stackCentralW
->addWidget( videoWidget
);
671 /* Embedded playlist -> Non-embedded playlist */
672 if( bgWidget
== stackCentralOldWidget
&& widget
== videoWidget
)
674 /* In rare case when video is started before the interface */
675 if( playlistWidget
!= NULL
)
676 playlistWidget
->artContainer
->removeWidget( videoWidget
);
677 videoWidget
->show(); videoWidget
->raise();
678 stackCentralW
->addWidget( videoWidget
);
679 stackCentralW
->setCurrentWidget( videoWidget
);
683 stackCentralW
->setCurrentWidget( widget
);
686 QSize size
= stackWidgetsSizes
[widget
];
688 resizeStack( size
.width(), size
.height() );
692 msg_Dbg( p_intf
, "Stack state changed to %s, index %i",
693 stackCentralW
->currentWidget()->metaObject()->className(),
694 stackCentralW
->currentIndex() );
695 msg_Dbg( p_intf
, "New stackCentralOldWidget %s at index %i",
696 stackCentralOldWidget
->metaObject()->className(),
697 stackCentralW
->indexOf( stackCentralOldWidget
) );
700 /* This part is done later, to account for the new pl size */
701 if( !video_closing
&& videoWidget
&& THEMIM
->getIM()->hasVideo() &&
702 videoWidget
== stackCentralOldWidget
&& widget
== playlistWidget
)
704 playlistWidget
->artContainer
->addWidget( videoWidget
);
705 playlistWidget
->artContainer
->setCurrentWidget( videoWidget
);
709 void MainInterface::toggleFSC()
711 if( !fullscreenControls
) return;
713 IMEvent
*eShow
= new IMEvent( IMEvent::FullscreenControlToggle
);
714 QApplication::postEvent( fullscreenControls
, eShow
);
717 /****************************************************************************
719 ****************************************************************************/
723 * You must not change the state of this object or other Qt UI objects,
724 * from the video output thread - only from the Qt UI main loop thread.
725 * All window provider queries must be handled through signals or events.
726 * That's why we have all those emit statements...
728 bool MainInterface::getVideo( struct vout_window_t
*p_wnd
)
730 static const struct vout_window_operations ops
= {
731 MainInterface::enableVideo
,
732 MainInterface::disableVideo
,
733 MainInterface::resizeVideo
,
734 MainInterface::releaseVideo
,
735 MainInterface::requestVideoState
,
736 MainInterface::requestVideoWindowed
,
737 MainInterface::requestVideoFullScreen
,
740 if( videoActive
.test_and_set() )
744 p_wnd
->info
.has_double_click
= true;
749 void MainInterface::getVideoSlot( struct vout_window_t
*p_wnd
,
750 unsigned i_width
, unsigned i_height
,
753 /* Hidden or minimized, activate */
754 if( isHidden() || isMinimized() )
755 toggleUpdateSystrayMenu();
757 /* Request the videoWidget */
760 videoWidget
= new VideoWidget( p_intf
, stackCentralW
);
761 stackCentralW
->addWidget( videoWidget
);
764 videoWidget
->request( p_wnd
);
765 if( true ) /* The videoWidget is available */
767 setVideoFullScreen( fullscreen
);
769 /* Consider the video active now */
772 /* Ask videoWidget to resize correctly, if we are in normal mode */
775 qreal factor
= videoWidget
->devicePixelRatioF();
777 i_width
= qRound( (qreal
) i_width
/ factor
);
778 i_height
= qRound( (qreal
) i_height
/ factor
);
781 videoWidget
->setSize( i_width
, i_height
);
786 /* Function that is CONNECTED to the previous emit */
787 void MainInterface::releaseVideoSlot( void )
789 /* This function is called when the embedded video window is destroyed,
790 * or in the rare case that the embedded window is still here but the
791 * Qt interface exits. */
792 assert( videoWidget
);
793 videoWidget
->release();
794 setVideoOnTop( false );
795 setVideoFullScreen( false );
798 if( stackCentralW
->currentWidget() == videoWidget
)
799 restoreStackOldWidget( true );
800 else if( playlistWidget
&&
801 playlistWidget
->artContainer
->currentWidget() == videoWidget
)
803 playlistWidget
->artContainer
->setCurrentIndex( 0 );
804 stackCentralW
->addWidget( videoWidget
);
807 /* We don't want to have a blank video to popup */
808 stackCentralOldWidget
= bgWidget
;
811 // The provided size is in physical pixels, coming from the core.
812 void MainInterface::setVideoSize( unsigned int w
, unsigned int h
)
814 if (!isFullScreen() && !isMaximized() )
816 /* Resize video widget to video size, or keep it at the same
817 * size. Call setSize() either way so that vout_window_ReportSize
818 * will always get called.
819 * If the video size is too large for the screen, resize it
820 * to the screen size.
824 QRect screen
= QApplication::desktop()->availableGeometry();
826 float factor
= videoWidget
->devicePixelRatioF();
830 if( (float)h
/ factor
> screen
.height() )
836 if( menuBar()->isVisible() )
837 h
-= menuBar()->height();
838 if( controls
->isVisible() )
839 h
-= controls
->height();
840 if( statusBar()->isVisible() )
841 h
-= statusBar()->height();
842 if( inputC
->isVisible() )
843 h
-= inputC
->height();
845 h
-= style()->pixelMetric(QStyle::PM_TitleBarHeight
);
846 h
-= style()->pixelMetric(QStyle::PM_LayoutBottomMargin
);
847 h
-= 2 * style()->pixelMetric(QStyle::PM_DefaultFrameWidth
);
851 // Convert the size in logical pixels
852 w
= qRound( (float)w
/ factor
);
853 h
= qRound( (float)h
/ factor
);
854 msg_Dbg( p_intf
, "Logical video size: %ux%u", w
, h
);
856 videoWidget
->setSize( w
, h
);
859 videoWidget
->setSize( videoWidget
->width(), videoWidget
->height() );
863 void MainInterface::videoSizeChanged( int w
, int h
)
865 if( !playlistWidget
|| playlistWidget
->artContainer
->currentWidget() != videoWidget
)
869 void MainInterface::setVideoFullScreen( bool fs
)
871 b_videoFullScreen
= fs
;
874 int numscreen
= var_InheritInteger( p_intf
, "qt-fullscreen-screennumber" );
876 if ( numscreen
>= 0 && numscreen
< QApplication::desktop()->screenCount() )
878 if( fullscreenControls
)
879 fullscreenControls
->setTargetScreen( numscreen
);
881 QRect screenres
= QApplication::desktop()->screenGeometry( numscreen
);
882 lastWinScreen
= windowHandle()->screen();
883 #ifdef QT5_HAS_WAYLAND
885 windowHandle()->setScreen(QGuiApplication::screens()[numscreen
]);
887 windowHandle()->setScreen(QGuiApplication::screens()[numscreen
]);
890 /* To be sure window is on proper-screen in xinerama */
891 if( !screenres
.contains( pos() ) )
893 lastWinPosition
= pos();
894 lastWinSize
= size();
895 msg_Dbg( p_intf
, "Moving video to correct position");
896 move( QPoint( screenres
.x(), screenres
.y() ) );
900 if( playlistWidget
!= NULL
&& playlistWidget
->artContainer
->currentWidget() == videoWidget
)
901 showTab( videoWidget
);
903 /* we won't be able to get its windowed sized once in fullscreen, so update it now */
904 stackWidgetsSizes
[stackCentralW
->currentWidget()] = stackCentralW
->size();
908 setInterfaceFullScreen( true );
912 setMinimalView( b_minimalView
);
913 setInterfaceFullScreen( b_interfaceFullScreen
);
914 #ifdef QT5_HAS_WAYLAND
915 if( lastWinScreen
!= NULL
&& !b_hasWayland
)
916 windowHandle()->setScreen(lastWinScreen
);
918 if( lastWinScreen
!= NULL
)
919 windowHandle()->setScreen(lastWinScreen
);
921 if( lastWinPosition
.isNull() == false )
923 move( lastWinPosition
);
924 lastWinPosition
= QPoint();
925 if( !pendingResize
.isValid() )
927 resizeWindow( lastWinSize
.width(), lastWinSize
.height() );
928 lastWinSize
= QSize();
931 if( pendingResize
.isValid() )
933 /* apply resize requested while fullscreen was enabled */
934 resizeStack( pendingResize
.width(), pendingResize
.height() );
935 pendingResize
= QSize(); // consume
942 /* Slot to change the video always-on-top flag.
943 * Emit askVideoOnTop() to invoke this from other thread. */
944 void MainInterface::setVideoOnTop( bool on_top
)
946 //don't apply changes if user has already sets its interface on top
947 if ( b_interfaceOnTop
)
950 Qt::WindowFlags oldflags
= windowFlags(), newflags
;
953 newflags
= oldflags
| Qt::WindowStaysOnTopHint
;
955 newflags
= oldflags
& ~Qt::WindowStaysOnTopHint
;
956 if( newflags
!= oldflags
&& !b_videoFullScreen
)
958 setWindowFlags( newflags
);
959 show(); /* necessary to apply window flags */
963 void MainInterface::setInterfaceAlwaysOnTop( bool on_top
)
965 b_interfaceOnTop
= on_top
;
966 Qt::WindowFlags oldflags
= windowFlags(), newflags
;
969 newflags
= oldflags
| Qt::WindowStaysOnTopHint
;
971 newflags
= oldflags
& ~Qt::WindowStaysOnTopHint
;
972 if( newflags
!= oldflags
&& !b_videoFullScreen
)
974 setWindowFlags( newflags
);
975 show(); /* necessary to apply window flags */
979 /* Asynchronous calls for video window contrlos */
980 int MainInterface::enableVideo( vout_window_t
*p_wnd
,
981 const vout_window_cfg_t
*cfg
)
983 MainInterface
*p_mi
= (MainInterface
*)p_wnd
->sys
;
985 msg_Dbg( p_wnd
, "requesting video window..." );
986 /* This is a blocking call signal. Results are stored directly in the
987 * vout_window_t and boolean pointers. Beware of deadlocks! */
988 emit p_mi
->askGetVideo( p_wnd
, cfg
->width
, cfg
->height
,
989 cfg
->is_fullscreen
);
993 void MainInterface::disableVideo( vout_window_t
*p_wnd
)
995 MainInterface
*p_mi
= (MainInterface
*)p_wnd
->sys
;
997 msg_Dbg( p_wnd
, "releasing video..." );
998 emit p_mi
->askReleaseVideo();
1001 void MainInterface::resizeVideo( vout_window_t
*p_wnd
,
1002 unsigned i_width
, unsigned i_height
)
1004 MainInterface
*p_mi
= (MainInterface
*)p_wnd
->sys
;
1006 emit p_mi
->askVideoToResize( i_width
, i_height
);
1009 void MainInterface::requestVideoWindowed( struct vout_window_t
*wnd
)
1011 MainInterface
*p_mi
= (MainInterface
*)wnd
->sys
;
1013 emit p_mi
->askVideoSetFullScreen( false );
1016 void MainInterface::requestVideoFullScreen( vout_window_t
*wnd
, const char * )
1018 MainInterface
*p_mi
= (MainInterface
*)wnd
->sys
;
1020 emit p_mi
->askVideoSetFullScreen( true );
1023 void MainInterface::requestVideoState( vout_window_t
*p_wnd
, unsigned i_arg
)
1025 MainInterface
*p_mi
= (MainInterface
*)p_wnd
->sys
;
1026 bool on_top
= (i_arg
& VOUT_WINDOW_STATE_ABOVE
) != 0;
1028 emit p_mi
->askVideoOnTop( on_top
);
1031 void MainInterface::releaseVideo( vout_window_t
*p_wnd
)
1033 MainInterface
*p_mi
= (MainInterface
*)p_wnd
->sys
;
1035 /* Releasing video (in disableVideo()) was a blocking call.
1036 * The video is no longer active by this point.
1038 p_mi
->videoActive
.clear();
1041 /*****************************************************************************
1042 * Playlist, Visualisation and Menus handling
1043 *****************************************************************************/
1045 * Toggle the playlist widget or dialog
1047 void MainInterface::createPlaylist()
1049 PlaylistDialog
*dialog
= PlaylistDialog::getInstance( p_intf
);
1053 playlistWidget
= dialog
->exportPlaylistWidget();
1054 stackCentralW
->addWidget( playlistWidget
);
1055 stackWidgetsSizes
[playlistWidget
] = settings
->value( "playlistSize", QSize( 600, 300 ) ).toSize();
1057 CONNECT( dialog
, visibilityChanged(bool), this, setPlaylistVisibility(bool) );
1060 void MainInterface::togglePlaylist()
1062 if( !playlistWidget
) createPlaylist();
1064 PlaylistDialog
*dialog
= PlaylistDialog::getInstance( p_intf
);
1067 if ( dialog
->hasPlaylistWidget() )
1068 playlistWidget
= dialog
->exportPlaylistWidget();
1069 /* Playlist is not visible, show it */
1070 if( stackCentralW
->currentWidget() != playlistWidget
)
1072 if( stackCentralW
->indexOf( playlistWidget
) == -1 )
1073 stackCentralW
->addWidget( playlistWidget
);
1074 showTab( playlistWidget
);
1078 restoreStackOldWidget();
1080 playlistVisible
= ( stackCentralW
->currentWidget() == playlistWidget
);
1084 playlistVisible
= !playlistVisible
;
1085 if ( ! dialog
->hasPlaylistWidget() )
1086 dialog
->importPlaylistWidget( playlistWidget
);
1087 if ( playlistVisible
)
1095 const Qt::Key
MainInterface::kc
[10] =
1097 Qt::Key_Up
, Qt::Key_Up
,
1098 Qt::Key_Down
, Qt::Key_Down
,
1099 Qt::Key_Left
, Qt::Key_Right
, Qt::Key_Left
, Qt::Key_Right
,
1100 Qt::Key_B
, Qt::Key_A
1103 void MainInterface::dockPlaylist( bool p_docked
)
1105 if( b_plDocked
== p_docked
) return;
1106 /* some extra check */
1107 if ( b_plDocked
&& !playlistWidget
) createPlaylist();
1109 b_plDocked
= p_docked
;
1110 PlaylistDialog
*dialog
= PlaylistDialog::getInstance( p_intf
);
1112 if( !p_docked
) /* Previously docked */
1114 playlistVisible
= playlistWidget
->isVisible();
1116 /* repositioning the videowidget __before__ exporting the
1117 playlistwidget into the playlist dialog avoids two unneeded
1118 calls to the server in the qt library to reparent the underlying
1119 native window back and forth.
1120 For Wayland, this is mandatory since reparenting is not implemented.
1121 For X11 or Windows, this is just an optimization. */
1122 if ( videoWidget
&& THEMIM
->getIM()->hasVideo() )
1123 showTab(videoWidget
);
1127 /* playlistwidget exported into the playlist dialog */
1128 stackCentralW
->removeWidget( playlistWidget
);
1129 dialog
->importPlaylistWidget( playlistWidget
);
1130 if ( playlistVisible
) dialog
->show();
1132 else /* Previously undocked */
1134 playlistVisible
= dialog
->isVisible() && !( videoWidget
&& THEMIM
->getIM()->hasVideo() );
1136 playlistWidget
= dialog
->exportPlaylistWidget();
1137 stackCentralW
->addWidget( playlistWidget
);
1139 /* If playlist is invisible don't show it */
1140 if( playlistVisible
) showTab( playlistWidget
);
1145 * displayNormalView is the private function used by
1146 * the SLOT setVideoFullScreen to restore the menuBar
1147 * if minimal view is off
1149 void MainInterface::displayNormalView()
1151 menuBar()->setVisible( false );
1152 controls
->setVisible( false );
1153 statusBar()->setVisible( false );
1154 inputC
->setVisible( false );
1158 * setMinimalView is the private function used by
1159 * the SLOT toggleMinimalView
1161 void MainInterface::setMinimalView( bool b_minimal
)
1163 bool b_menuBarVisible
= menuBar()->isVisible();
1164 bool b_controlsVisible
= controls
->isVisible();
1165 bool b_statusBarVisible
= statusBar()->isVisible();
1166 bool b_inputCVisible
= inputC
->isVisible();
1168 if( !isFullScreen() && !isMaximized() && b_minimal
&& !b_isWindowTiled
)
1170 int i_heightChange
= 0;
1172 if( b_menuBarVisible
)
1173 i_heightChange
+= menuBar()->height();
1174 if( b_controlsVisible
)
1175 i_heightChange
+= controls
->height();
1176 if( b_statusBarVisible
)
1177 i_heightChange
+= statusBar()->height();
1178 if( b_inputCVisible
)
1179 i_heightChange
+= inputC
->height();
1181 if( i_heightChange
!= 0 )
1182 resizeWindow( width(), height() - i_heightChange
);
1185 menuBar()->setVisible( !b_minimal
);
1186 controls
->setVisible( !b_minimal
);
1187 statusBar()->setVisible( !b_minimal
&& b_statusbarVisible
);
1188 inputC
->setVisible( !b_minimal
);
1190 if( !isFullScreen() && !isMaximized() && !b_minimal
&& !b_isWindowTiled
)
1192 int i_heightChange
= 0;
1194 if( !b_menuBarVisible
&& menuBar()->isVisible() )
1195 i_heightChange
+= menuBar()->height();
1196 if( !b_controlsVisible
&& controls
->isVisible() )
1197 i_heightChange
+= controls
->height();
1198 if( !b_statusBarVisible
&& statusBar()->isVisible() )
1199 i_heightChange
+= statusBar()->height();
1200 if( !b_inputCVisible
&& inputC
->isVisible() )
1201 i_heightChange
+= inputC
->height();
1203 if( i_heightChange
!= 0 )
1204 resizeWindow( width(), height() + i_heightChange
);
1209 * This public SLOT is used for moving to minimal View Mode
1211 * If b_minimal is false, then we are normalView
1213 void MainInterface::toggleMinimalView( bool b_minimal
)
1215 if( !b_minimalView
&& b_autoresize
) /* Normal mode */
1217 if( stackCentralW
->currentWidget() == bgWidget
)
1219 if( stackCentralW
->height() < 16 )
1221 resizeStack( stackCentralW
->width(), 100 );
1225 b_minimalView
= b_minimal
;
1226 if( !b_videoFullScreen
)
1228 setMinimalView( b_minimalView
);
1229 computeMinimumSize();
1232 emit
minimalViewToggled( b_minimalView
);
1235 /* toggling advanced controls buttons */
1236 void MainInterface::toggleAdvancedButtons()
1238 controls
->toggleAdvanced();
1239 // if( fullscreenControls ) fullscreenControls->toggleAdvanced();
1242 /* Get the visibility status of the controls (hidden or not, advanced or not) */
1243 int MainInterface::getControlsVisibilityStatus()
1245 if( !controls
) return 0;
1246 return( (controls
->isVisible() ? CONTROLS_VISIBLE
: CONTROLS_HIDDEN
)
1247 + CONTROLS_ADVANCED
* controls
->b_advancedVisible
);
1250 StandardPLPanel
*MainInterface::getPlaylistView()
1252 if( !playlistWidget
) return NULL
;
1253 else return playlistWidget
->mainView
;
1256 void MainInterface::setStatusBarVisibility( bool b_visible
)
1258 statusBar()->setVisible( b_visible
);
1259 b_statusbarVisible
= b_visible
;
1260 if( controls
) controls
->setGripVisible( !b_statusbarVisible
);
1264 void MainInterface::setPlaylistVisibility( bool b_visible
)
1266 if( isPlDocked() || THEDP
->isDying() || (playlistWidget
&& playlistWidget
->isMinimized() ) )
1269 playlistVisible
= b_visible
;
1272 /************************************************************************
1274 ************************************************************************/
1275 void MainInterface::setName( const QString
& name
)
1277 input_name
= name
; /* store it for the QSystray use */
1278 /* Display it in the status bar, but also as a Tooltip in case it doesn't
1280 nameLabel
->setText( name
);
1281 nameLabel
->setToolTip( name
);
1285 * Give the decorations of the Main Window a correct Name.
1286 * If nothing is given, set it to VLC...
1288 void MainInterface::setVLCWindowsTitle( const QString
& aTitle
)
1290 if( aTitle
.isEmpty() )
1292 setWindowTitle( qtr( "VLC media player" ) );
1296 setWindowTitle( aTitle
+ " - " + qtr( "VLC media player" ) );
1300 void MainInterface::showCryptedLabel( bool b_show
)
1302 if( cryptedLabel
== NULL
)
1304 cryptedLabel
= new QLabel
;
1305 // The lock icon is not the right one for DRM protection/scrambled.
1306 //cryptedLabel->setPixmap( QPixmap( ":/lock.svg" ) );
1307 cryptedLabel
->setText( "DRM" );
1308 statusBar()->addWidget( cryptedLabel
);
1311 cryptedLabel
->setVisible( b_show
);
1314 void MainInterface::showBuffering( float f_cache
)
1316 QString amount
= QString("Buffering: %1%").arg( (int)(100*f_cache
) );
1317 statusBar()->showMessage( amount
, 1000 );
1320 /*****************************************************************************
1321 * Systray Icon and Systray Menu
1322 *****************************************************************************/
1324 * Create a SystemTray icon and a menu that would go with it.
1325 * Connects to a click handler on the icon.
1327 void MainInterface::createSystray()
1330 if( QDate::currentDate().dayOfYear() >= QT_XMAS_JOKE_DAY
&& var_InheritBool( p_intf
, "qt-icon-change" ) )
1331 iconVLC
= QIcon::fromTheme( "vlc-xmas", QIcon( ":/logo/vlc128-xmas.png" ) );
1333 iconVLC
= QIcon::fromTheme( "vlc", QIcon( ":/logo/vlc256.png" ) );
1334 sysTray
= new QSystemTrayIcon( iconVLC
, this );
1335 sysTray
->setToolTip( qtr( "VLC media player" ));
1337 systrayMenu
= new QMenu( qtr( "VLC media player" ), this );
1338 systrayMenu
->setIcon( iconVLC
);
1340 VLCMenuBar::updateSystrayMenu( this, p_intf
, true );
1343 CONNECT( sysTray
, activated( QSystemTrayIcon::ActivationReason
),
1344 this, handleSystrayClick( QSystemTrayIcon::ActivationReason
) );
1346 /* Connects on nameChanged() */
1347 CONNECT( THEMIM
->getIM(), nameChanged( const QString
& ),
1348 this, updateSystrayTooltipName( const QString
& ) );
1349 /* Connect PLAY_STATUS on the systray */
1350 CONNECT( THEMIM
->getIM(), playingStatusChanged( int ),
1351 this, updateSystrayTooltipStatus( int ) );
1354 void MainInterface::toggleUpdateSystrayMenuWhenVisible()
1359 void MainInterface::resizeWindow(int w
, int h
)
1361 #if ! HAS_QT510 && defined(QT5_HAS_X11)
1362 if( QX11Info::isPlatformX11() )
1365 qreal dpr
= devicePixelRatioF();
1367 qreal dpr
= devicePixelRatio();
1370 size
= size
.boundedTo(maximumSize()).expandedTo(minimumSize());
1371 /* X11 window managers are not required to accept geometry changes on
1372 * the top-level window. Unfortunately, Qt < 5.10 assumes that the
1373 * change will succeed, and resizes all sub-windows unconditionally.
1374 * By calling XMoveResizeWindow directly, Qt will not see our change
1375 * request until the ConfigureNotify event on success
1376 * and not at all if it is rejected. */
1377 XResizeWindow( QX11Info::display(), winId(),
1378 (unsigned int)size
.width() * dpr
, (unsigned int)size
.height() * dpr
);
1386 * Updates the Systray Icon's menu and toggle the main interface
1388 void MainInterface::toggleUpdateSystrayMenu()
1390 /* If hidden, show it */
1396 else if( isMinimized() )
1404 /* Visible (possibly under other windows) */
1405 toggleUpdateSystrayMenuWhenVisible();
1408 VLCMenuBar::updateSystrayMenu( this, p_intf
);
1411 /* First Item of the systray menu */
1412 void MainInterface::showUpdateSystrayMenu()
1420 VLCMenuBar::updateSystrayMenu( this, p_intf
);
1423 /* First Item of the systray menu */
1424 void MainInterface::hideUpdateSystrayMenu()
1427 VLCMenuBar::updateSystrayMenu( this, p_intf
);
1430 /* Click on systray Icon */
1431 void MainInterface::handleSystrayClick(
1432 QSystemTrayIcon::ActivationReason reason
)
1436 case QSystemTrayIcon::Trigger
:
1437 case QSystemTrayIcon::DoubleClick
:
1439 VLCMenuBar::updateSystrayMenu( this, p_intf
);
1441 toggleUpdateSystrayMenu();
1444 case QSystemTrayIcon::MiddleClick
:
1445 sysTray
->showMessage( qtr( "VLC media player" ),
1446 qtr( "Control menu for the player" ),
1447 QSystemTrayIcon::Information
, 3000 );
1455 * Updates the name of the systray Icon tooltip.
1456 * Doesn't check if the systray exists, check before you call it.
1458 void MainInterface::updateSystrayTooltipName( const QString
& name
)
1460 if( name
.isEmpty() )
1462 sysTray
->setToolTip( qtr( "VLC media player" ) );
1466 sysTray
->setToolTip( name
);
1467 if( ( i_notificationSetting
== NOTIFICATION_ALWAYS
) ||
1468 ( i_notificationSetting
== NOTIFICATION_MINIMIZED
&& (isMinimized() || isHidden()) ) )
1470 sysTray
->showMessage( qtr( "VLC media player" ), name
,
1471 QSystemTrayIcon::NoIcon
, 3000 );
1475 VLCMenuBar::updateSystrayMenu( this, p_intf
);
1479 * Updates the status of the systray Icon tooltip.
1480 * Doesn't check if the systray exists, check before you call it.
1482 void MainInterface::updateSystrayTooltipStatus( int i_status
)
1487 sysTray
->setToolTip( input_name
);
1490 sysTray
->setToolTip( input_name
+ " - " + qtr( "Paused") );
1493 sysTray
->setToolTip( qtr( "VLC media player" ) );
1496 VLCMenuBar::updateSystrayMenu( this, p_intf
);
1499 void MainInterface::changeEvent(QEvent
*event
)
1501 if( event
->type() == QEvent::WindowStateChange
)
1503 QWindowStateChangeEvent
*windowStateChangeEvent
= static_cast<QWindowStateChangeEvent
*>(event
);
1504 Qt::WindowStates newState
= windowState();
1505 Qt::WindowStates oldState
= windowStateChangeEvent
->oldState();
1507 /* b_maximizedView stores if the window was maximized before entering fullscreen.
1508 * It is set when entering maximized mode, unset when leaving it to normal mode.
1509 * Upon leaving full screen, if b_maximizedView is set,
1510 * the window should be maximized again. */
1511 if( newState
& Qt::WindowMaximized
&&
1512 !( oldState
& Qt::WindowMaximized
) )
1513 b_maximizedView
= true;
1515 if( !( newState
& Qt::WindowMaximized
) &&
1516 oldState
& Qt::WindowMaximized
&&
1517 !b_videoFullScreen
)
1518 b_maximizedView
= false;
1520 if( !( newState
& Qt::WindowFullScreen
) &&
1521 oldState
& Qt::WindowFullScreen
&&
1528 if( newState
& Qt::WindowMinimized
)
1530 b_hasPausedWhenMinimized
= false;
1532 if( THEMIM
->getIM()->playingStatus() == PLAYING_S
&&
1533 THEMIM
->getIM()->hasVideo() && !THEMIM
->getIM()->hasVisualisation() &&
1536 b_hasPausedWhenMinimized
= true;
1540 else if( oldState
& Qt::WindowMinimized
&& !( newState
& Qt::WindowMinimized
) )
1542 if( b_hasPausedWhenMinimized
)
1549 QWidget::changeEvent(event
);
1552 /************************************************************************
1554 ************************************************************************/
1555 void MainInterface::dropEvent(QDropEvent
*event
)
1557 dropEventPlay( event
, true );
1563 * Event called if something is dropped onto a VLC window
1564 * \param event the event in question
1565 * \param b_play whether to play the file immediately
1568 void MainInterface::dropEventPlay( QDropEvent
*event
, bool b_play
)
1570 if( event
->possibleActions() & ( Qt::CopyAction
| Qt::MoveAction
| Qt::LinkAction
) )
1571 event
->setDropAction( Qt::CopyAction
);
1575 const QMimeData
*mimeData
= event
->mimeData();
1577 /* D&D of a subtitles file, add it on the fly */
1578 if( mimeData
->urls().count() == 1 && THEMIM
->getIM()->hasInput() )
1580 if( !input_AddSlave( THEMIM
->getInput(), SLAVE_TYPE_SPU
,
1581 qtu( mimeData
->urls()[0].toString() ), true, true, true ) )
1588 bool first
= b_play
;
1589 foreach( const QUrl
&url
, mimeData
->urls() )
1593 QString mrl
= toURI( url
.toEncoded().constData() );
1595 QFileInfo
info( url
.toLocalFile() );
1596 if( info
.exists() && info
.isSymLink() )
1598 QString target
= info
.symLinkTarget();
1600 if( QFile::exists( target
) )
1602 url
= QUrl::fromLocalFile( target
);
1606 url
.setUrl( target
);
1608 mrl
= toURI( url
.toEncoded().constData() );
1611 if( mrl
.length() > 0 )
1613 Open::openMRL( p_intf
, mrl
, first
);
1619 /* Browsers give content as text if you dnd the addressbar,
1620 so check if mimedata has valid url in text and use it
1621 if we didn't get any normal Urls()*/
1622 if( !mimeData
->hasUrls() && mimeData
->hasText() &&
1623 QUrl(mimeData
->text()).isValid() )
1625 QString mrl
= toURI( mimeData
->text() );
1626 Open::openMRL( p_intf
, mrl
, first
);
1630 void MainInterface::dragEnterEvent(QDragEnterEvent
*event
)
1632 event
->acceptProposedAction();
1634 void MainInterface::dragMoveEvent(QDragMoveEvent
*event
)
1636 event
->acceptProposedAction();
1638 void MainInterface::dragLeaveEvent(QDragLeaveEvent
*event
)
1643 /************************************************************************
1645 ************************************************************************/
1646 void MainInterface::keyPressEvent( QKeyEvent
*e
)
1648 handleKeyPress( e
);
1650 /* easter eggs sequence handling */
1651 if ( e
->key() == kc
[ i_kc_offset
] )
1656 if ( i_kc_offset
== (sizeof( kc
) / sizeof( Qt::Key
)) )
1663 void MainInterface::handleKeyPress( QKeyEvent
*e
)
1665 if( ( ( e
->modifiers() & Qt::ControlModifier
) && ( e
->key() == Qt::Key_H
) ) ||
1666 ( b_minimalView
&& !b_videoFullScreen
&& e
->key() == Qt::Key_Escape
) )
1668 toggleMinimalView( !b_minimalView
);
1671 else if( ( e
->modifiers() & Qt::ControlModifier
) && ( e
->key() == Qt::Key_K
) &&
1674 playlistWidget
->setSearchFieldFocus();
1678 int i_vlck
= qtEventToVLCKey( e
);
1681 var_SetInteger( p_intf
->obj
.libvlc
, "key-pressed", i_vlck
);
1688 void MainInterface::wheelEvent( QWheelEvent
*e
)
1690 int i_vlckey
= qtWheelEventToVLCKey( e
);
1691 var_SetInteger( p_intf
->obj
.libvlc
, "key-pressed", i_vlckey
);
1695 void MainInterface::closeEvent( QCloseEvent
*e
)
1698 if ( b_minimalView
)
1699 setMinimalView( false );
1700 emit
askToQuit(); /* ask THEDP to quit, so we have a unique method */
1701 /* Accept session quit. Otherwise we break the desktop mamager. */
1705 bool MainInterface::eventFilter( QObject
*obj
, QEvent
*event
)
1707 if ( event
->type() == MainInterface::ToolbarsNeedRebuild
) {
1712 return QObject::eventFilter( obj
, event
);
1716 void MainInterface::toolBarConfUpdated()
1718 QApplication::postEvent( this, new QEvent( MainInterface::ToolbarsNeedRebuild
) );
1721 void MainInterface::setInterfaceFullScreen( bool fs
)
1724 setWindowState( windowState() | Qt::WindowFullScreen
);
1726 setWindowState( windowState() & ~Qt::WindowFullScreen
);
1728 void MainInterface::toggleInterfaceFullScreen()
1730 b_interfaceFullScreen
= !b_interfaceFullScreen
;
1731 if( !b_videoFullScreen
)
1732 setInterfaceFullScreen( b_interfaceFullScreen
);
1733 emit
fullscreenInterfaceToggled( b_interfaceFullScreen
);
1736 void MainInterface::emitBoss()
1740 void MainInterface::setBoss()
1753 void MainInterface::emitRaise()
1757 void MainInterface::setRaise()
1763 void MainInterface::voutReleaseMouseEvents()
1767 QPoint pos
= QCursor::pos();
1768 QPoint localpos
= videoWidget
->mapFromGlobal(pos
);
1769 int buttons
= QApplication::mouseButtons();
1771 while (buttons
!= 0)
1773 if ( (buttons
& 1) != 0 )
1775 QMouseEvent
new_e( QEvent::MouseButtonRelease
, localpos
,
1776 (Qt::MouseButton
)i_button
, (Qt::MouseButton
)i_button
, Qt::NoModifier
);
1777 QApplication::sendEvent(videoWidget
, &new_e
);
1786 /*****************************************************************************
1787 * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
1788 * We don't show the menu directly here because we don't want the
1789 * caller to block for a too long time.
1790 *****************************************************************************/
1791 static int PopupMenuCB( vlc_object_t
*, const char *,
1792 vlc_value_t
, vlc_value_t new_val
, void *param
)
1794 intf_thread_t
*p_intf
= (intf_thread_t
*)param
;
1796 if( p_intf
->pf_show_dialog
)
1798 p_intf
->pf_show_dialog( p_intf
, INTF_DIALOG_POPUPMENU
,
1799 new_val
.b_bool
, NULL
);
1805 /*****************************************************************************
1806 * IntfShowCB: callback triggered by the intf-toggle-fscontrol libvlc variable.
1807 *****************************************************************************/
1808 static int IntfShowCB( vlc_object_t
*, const char *,
1809 vlc_value_t
, vlc_value_t
, void *param
)
1811 intf_thread_t
*p_intf
= (intf_thread_t
*)param
;
1812 p_intf
->p_sys
->p_mi
->toggleFSC();
1818 /*****************************************************************************
1819 * IntfRaiseMainCB: callback triggered by the intf-show-main libvlc variable.
1820 *****************************************************************************/
1821 static int IntfRaiseMainCB( vlc_object_t
*, const char *,
1822 vlc_value_t
, vlc_value_t
, void *param
)
1824 intf_thread_t
*p_intf
= (intf_thread_t
*)param
;
1825 p_intf
->p_sys
->p_mi
->emitRaise();
1830 /*****************************************************************************
1831 * IntfBossCB: callback triggered by the intf-boss libvlc variable.
1832 *****************************************************************************/
1833 static int IntfBossCB( vlc_object_t
*, const char *,
1834 vlc_value_t
, vlc_value_t
, void *param
)
1836 intf_thread_t
*p_intf
= (intf_thread_t
*)param
;
1837 p_intf
->p_sys
->p_mi
->emitBoss();