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