1 /*****************************************************************************
2 * Controller.cpp : Controller for the main interface
3 ****************************************************************************
4 * Copyright (C) 2006-2008 the VideoLAN team
7 * Authors: 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
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
32 #include "components/controller.hpp"
33 #include "components/controller_widget.hpp"
34 #include "components/interface_widgets.hpp"
36 #include "dialogs_provider.hpp" /* Opening Dialogs */
37 #include "input_manager.hpp"
38 #include "actions_manager.hpp"
40 #include "util/input_slider.hpp" /* InputSlider */
41 #include "util/customwidgets.hpp" /* qEventToKey */
43 #include <QSpacerItem>
44 #include <QToolButton>
45 #include <QHBoxLayout>
46 #include <QSignalMapper>
49 /**********************************************************************
51 **********************************************************************/
54 * This is an abstract Toolbar/Controller
55 * This has helper to create any toolbar, any buttons and to manage the actions
58 AbstractController::AbstractController( intf_thread_t * _p_i, QWidget *_parent )
64 /* Main action provider */
65 toolbarActionsMapper = new QSignalMapper( this );
66 CONNECT( toolbarActionsMapper, mapped( int ),
67 ActionsManager::getInstance( p_intf ), doAction( int ) );
68 CONNECT( THEMIM->getIM(), statusChanged( int ), this, setStatus( int ) );
71 /* Reemit some signals on status Change to activate some buttons */
72 void AbstractController::setStatus( int status )
74 bool b_hasInput = THEMIM->getIM()->hasInput();
75 /* Activate the interface buttons according to the presence of the input */
76 emit inputExists( b_hasInput );
78 emit inputPlaying( status == PLAYING_S );
80 emit inputIsRecordable( b_hasInput &&
81 var_GetBool( THEMIM->getInput(), "can-record" ) );
83 emit inputIsTrickPlayable( b_hasInput &&
84 var_GetBool( THEMIM->getInput(), "can-rewind" ) );
87 /* Generic button setup */
88 void AbstractController::setupButton( QAbstractButton *aButton )
90 static QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
91 sizePolicy.setHorizontalStretch( 0 );
92 sizePolicy.setVerticalStretch( 0 );
94 aButton->setSizePolicy( sizePolicy );
95 aButton->setFixedSize( QSize( 26, 26 ) );
96 aButton->setIconSize( QSize( 20, 20 ) );
97 aButton->setFocusPolicy( Qt::NoFocus );
100 /* Open the generic config line for the toolbar, parse it
101 * and create the widgets accordingly */
102 void AbstractController::parseAndCreate( const QString& config,
103 QBoxLayout *controlLayout )
105 QStringList list = config.split( ";", QString::SkipEmptyParts ) ;
106 for( int i = 0; i < list.size(); i++ )
108 QStringList list2 = list.at( i ).split( "-" );
109 if( list2.size() < 1 )
111 msg_Warn( p_intf, "Parsing error. Report this" );
116 int i_option = WIDGET_NORMAL;
117 buttonType_e i_type = (buttonType_e)list2.at( 0 ).toInt( &ok );
120 msg_Warn( p_intf, "Parsing error 0. Please report this" );
124 if( list2.size() > 1 )
126 i_option = list2.at( 1 ).toInt( &ok );
129 msg_Warn( p_intf, "Parsing error 1. Please report this" );
134 createAndAddWidget( controlLayout, -1, i_type, i_option );
138 void AbstractController::createAndAddWidget( QBoxLayout *controlLayout,
143 /* Special case for SPACERS, who aren't QWidgets */
144 if( i_type == WIDGET_SPACER )
146 controlLayout->insertSpacing( i_index, 16 );
150 if( i_type == WIDGET_SPACER_EXTEND )
152 controlLayout->insertStretch( i_index, 16 );
156 QWidget *widg = createWidget( i_type, i_option );
159 controlLayout->insertWidget( i_index, widg );
163 #define CONNECT_MAP( a ) CONNECT( a, clicked(), toolbarActionsMapper, map() )
164 #define SET_MAPPING( a, b ) toolbarActionsMapper->setMapping( a , b )
165 #define CONNECT_MAP_SET( a, b ) \
168 #define BUTTON_SET_BAR( a_button ) \
169 a_button->setToolTip( qtr( tooltipL[button] ) ); \
170 a_button->setIcon( QIcon( iconL[button] ) );
171 #define BUTTON_SET_BAR2( button, image, tooltip ) \
172 button->setToolTip( tooltip ); \
173 button->setIcon( QIcon( ":/"#image ) );
176 #define ENABLE_ON_VIDEO( a ) \
177 CONNECT( THEMIM->getIM(), voutChanged( bool ), a, setEnabled( bool ) ); \
178 a->setEnabled( THEMIM->getIM()->hasVideo() ); /* TODO: is this necessary? when input is started before the interface? */
180 #define ENABLE_ON_INPUT( a ) \
181 CONNECT( this, inputExists( bool ), a, setEnabled( bool ) ); \
182 a->setEnabled( THEMIM->getIM()->hasInput() ); /* TODO: is this necessary? when input is started before the interface? */
184 QWidget *AbstractController::createWidget( buttonType_e button, int options )
187 bool b_flat = options & WIDGET_FLAT;
188 bool b_big = options & WIDGET_BIG;
189 bool b_shiny = options & WIDGET_SHINY;
190 bool b_special = false;
192 QWidget *widget = NULL;
196 PlayButton *playButton = new PlayButton;
197 setupButton( playButton );
198 BUTTON_SET_BAR( playButton );
199 CONNECT_MAP_SET( playButton, PLAY_ACTION );
200 CONNECT( this, inputPlaying( bool ),
201 playButton, updateButton( bool ));
206 QToolButton *stopButton = new QToolButton;
207 setupButton( stopButton );
208 CONNECT_MAP_SET( stopButton, STOP_ACTION );
209 BUTTON_SET_BAR( stopButton );
214 QToolButton *openButton = new QToolButton;
215 setupButton( openButton );
216 CONNECT_MAP_SET( openButton, OPEN_ACTION );
217 BUTTON_SET_BAR( openButton );
221 case PREVIOUS_BUTTON:{
222 QToolButton *prevButton = new QToolButton;
223 setupButton( prevButton );
224 CONNECT_MAP_SET( prevButton, PREVIOUS_ACTION );
225 BUTTON_SET_BAR( prevButton );
231 QToolButton *nextButton = new QToolButton;
232 setupButton( nextButton );
233 CONNECT_MAP_SET( nextButton, NEXT_ACTION );
234 BUTTON_SET_BAR( nextButton );
239 QToolButton *slowerButton = new QToolButton;
240 setupButton( slowerButton );
241 CONNECT_MAP_SET( slowerButton, SLOWER_ACTION );
242 BUTTON_SET_BAR( slowerButton );
243 ENABLE_ON_INPUT( slowerButton );
244 widget = slowerButton;
248 QToolButton *fasterButton = new QToolButton;
249 setupButton( fasterButton );
250 CONNECT_MAP_SET( fasterButton, FASTER_ACTION );
251 BUTTON_SET_BAR( fasterButton );
252 ENABLE_ON_INPUT( fasterButton );
253 widget = fasterButton;
257 QToolButton *frameButton = new QToolButton;
258 setupButton( frameButton );
259 CONNECT_MAP_SET( frameButton, FRAME_ACTION );
260 BUTTON_SET_BAR( frameButton );
261 ENABLE_ON_VIDEO( frameButton );
262 widget = frameButton;
265 case FULLSCREEN_BUTTON:{
266 QToolButton *fullscreenButton = new QToolButton;
267 setupButton( fullscreenButton );
268 CONNECT_MAP_SET( fullscreenButton, FULLSCREEN_ACTION );
269 BUTTON_SET_BAR( fullscreenButton );
270 ENABLE_ON_VIDEO( fullscreenButton );
271 widget = fullscreenButton;
274 case DEFULLSCREEN_BUTTON:{
275 QToolButton *fullscreenButton = new QToolButton;
276 setupButton( fullscreenButton );
277 CONNECT_MAP_SET( fullscreenButton, FULLSCREEN_ACTION );
278 BUTTON_SET_BAR( fullscreenButton )
279 ENABLE_ON_VIDEO( fullscreenButton );
280 widget = fullscreenButton;
283 case EXTENDED_BUTTON:{
284 QToolButton *extSettingsButton = new QToolButton;
285 setupButton( extSettingsButton );
286 CONNECT_MAP_SET( extSettingsButton, EXTENDED_ACTION );
287 BUTTON_SET_BAR( extSettingsButton )
288 widget = extSettingsButton;
291 case PLAYLIST_BUTTON:{
292 QToolButton *playlistButton = new QToolButton;
293 setupButton( playlistButton );
294 CONNECT_MAP_SET( playlistButton, PLAYLIST_ACTION );
295 BUTTON_SET_BAR( playlistButton );
296 widget = playlistButton;
299 case SNAPSHOT_BUTTON:{
300 QToolButton *snapshotButton = new QToolButton;
301 setupButton( snapshotButton );
302 CONNECT_MAP_SET( snapshotButton, SNAPSHOT_ACTION );
303 BUTTON_SET_BAR( snapshotButton );
304 ENABLE_ON_VIDEO( snapshotButton );
305 widget = snapshotButton;
309 QToolButton *recordButton = new QToolButton;
310 setupButton( recordButton );
311 CONNECT_MAP_SET( recordButton, RECORD_ACTION );
312 BUTTON_SET_BAR( recordButton );
313 ENABLE_ON_INPUT( recordButton );
314 recordButton->setCheckable( true );
315 CONNECT( THEMIM->getIM(), recordingStateChanged( bool ),
316 recordButton, setChecked( bool ) );
317 widget = recordButton;
321 AtoB_Button *ABButton = new AtoB_Button;
322 setupButton( ABButton );
323 ABButton->setShortcut( qtr("Shift+L") );
324 BUTTON_SET_BAR( ABButton );
325 ENABLE_ON_INPUT( ABButton );
326 CONNECT_MAP_SET( ABButton, ATOB_ACTION );
327 CONNECT( THEMIM->getIM(), AtoBchanged( bool, bool),
328 ABButton, setIcons( bool, bool ) );
333 InputSlider *slider = new InputSlider( Qt::Horizontal, NULL );
335 /* Update the position when the IM has changed */
336 CONNECT( THEMIM->getIM(), positionUpdated( float, int, int ),
337 slider, setPosition( float, int, int ) );
338 /* And update the IM, when the position has changed */
339 CONNECT( slider, sliderDragged( float ),
340 THEMIM->getIM(), sliderUpdate( float ) );
345 widget = discFrame();
348 case TELETEXT_BUTTONS:
349 widget = telexFrame();
356 SoundWidget *snd = new SoundWidget( this, p_intf, b_shiny, b_special );
362 TimeLabel *timeLabel = new TimeLabel( p_intf );
368 QFrame *line = new QFrame;
369 line->setFrameShape( QFrame::VLine );
370 line->setFrameShadow( QFrame::Raised );
371 line->setLineWidth( 0 );
372 line->setMidLineWidth( 1 );
376 case ADVANCED_CONTROLLER:
378 advControls = new AdvControlsWidget( p_intf, this );
379 widget = advControls;
382 case REVERSE_BUTTON:{
383 QToolButton *reverseButton = new QToolButton;
384 setupButton( reverseButton );
385 CONNECT_MAP_SET( reverseButton, REVERSE_ACTION );
386 BUTTON_SET_BAR( reverseButton );
387 reverseButton->setCheckable( true );
388 /* You should, of COURSE change this to the correct event,
389 when/if we have one, that tells us if trickplay is possible . */
390 CONNECT( this, inputIsTrickPlayable( bool ), reverseButton, setVisible( bool ) );
391 reverseButton->setVisible( false );
392 widget = reverseButton;
395 case SKIP_BACK_BUTTON: {
396 QToolButton *skipBakButton = new QToolButton;
397 setupButton( skipBakButton );
398 CONNECT_MAP_SET( skipBakButton, SKIP_BACK_ACTION );
399 BUTTON_SET_BAR( skipBakButton );
400 ENABLE_ON_INPUT( skipBakButton );
401 widget = skipBakButton;
404 case SKIP_FW_BUTTON: {
405 QToolButton *skipFwButton = new QToolButton;
406 setupButton( skipFwButton );
407 CONNECT_MAP_SET( skipFwButton, SKIP_FW_ACTION );
408 BUTTON_SET_BAR( skipFwButton );
409 ENABLE_ON_INPUT( skipFwButton );
410 widget = skipFwButton;
414 QToolButton *quitButton = new QToolButton;
415 setupButton( quitButton );
416 CONNECT_MAP_SET( quitButton, QUIT_ACTION );
417 BUTTON_SET_BAR( quitButton );
422 msg_Warn( p_intf, "This should not happen %i", button );
426 /* Customize Buttons */
427 if( b_flat || b_big )
429 QFrame *frame = qobject_cast<QFrame *>(widget);
432 QList<QToolButton *> allTButtons = frame->findChildren<QToolButton *>();
433 for( int i = 0; i < allTButtons.size(); i++ )
434 applyAttributes( allTButtons[i], b_flat, b_big );
438 QToolButton *tmpButton = qobject_cast<QToolButton *>(widget);
440 applyAttributes( tmpButton, b_flat, b_big );
446 void AbstractController::applyAttributes( QToolButton *tmpButton, bool b_flat, bool b_big )
451 tmpButton->setAutoRaise( b_flat );
454 tmpButton->setFixedSize( QSize( 32, 32 ) );
455 tmpButton->setIconSize( QSize( 26, 26 ) );
460 QFrame *AbstractController::discFrame()
462 /** Disc and Menus handling */
463 QFrame *discFrame = new QFrame( this );
465 QHBoxLayout *discLayout = new QHBoxLayout( discFrame );
466 discLayout->setSpacing( 0 ); discLayout->setMargin( 0 );
468 QToolButton *prevSectionButton = new QToolButton( discFrame );
469 setupButton( prevSectionButton );
470 BUTTON_SET_BAR2( prevSectionButton, toolbar/dvd_prev,
471 qtr("Previous Chapter/Title" ) );
472 discLayout->addWidget( prevSectionButton );
474 QToolButton *menuButton = new QToolButton( discFrame );
475 setupButton( menuButton );
476 discLayout->addWidget( menuButton );
477 BUTTON_SET_BAR2( menuButton, toolbar/dvd_menu, qtr( "Menu" ) );
479 QToolButton *nextSectionButton = new QToolButton( discFrame );
480 setupButton( nextSectionButton );
481 discLayout->addWidget( nextSectionButton );
482 BUTTON_SET_BAR2( nextSectionButton, toolbar/dvd_next,
483 qtr("Next Chapter/Title" ) );
485 /* Change the navigation button display when the IM
486 navigation changes */
487 CONNECT( THEMIM->getIM(), titleChanged( bool ),
488 discFrame, setVisible( bool ) );
489 CONNECT( THEMIM->getIM(), chapterChanged( bool ),
490 menuButton, setVisible( bool ) );
491 /* Changes the IM navigation when triggered on the nav buttons */
492 CONNECT( prevSectionButton, clicked(), THEMIM->getIM(),
494 CONNECT( nextSectionButton, clicked(), THEMIM->getIM(),
496 CONNECT( menuButton, clicked(), THEMIM->getIM(),
498 connect( THEMIM->getIM(), SIGNAL( titleChanged( bool ) ),
499 this, SIGNAL( sizeChanged() ) );
504 QFrame *AbstractController::telexFrame()
509 QFrame *telexFrame = new QFrame;
510 QHBoxLayout *telexLayout = new QHBoxLayout( telexFrame );
511 telexLayout->setSpacing( 0 ); telexLayout->setMargin( 0 );
512 CONNECT( THEMIM->getIM(), teletextPossible( bool ),
513 telexFrame, setVisible( bool ) );
514 connect( THEMIM->getIM(), SIGNAL( teletextPossible( bool ) ),
515 this, SIGNAL( sizeChanged() ) );
518 QToolButton *telexOn = new QToolButton;
519 setupButton( telexOn );
520 BUTTON_SET_BAR2( telexOn, toolbar/tv, qtr( "Teletext Activation" ) );
521 telexOn->setEnabled( false );
522 telexOn->setCheckable( true );
524 telexLayout->addWidget( telexOn );
526 /* Teletext Activation and set */
527 CONNECT( telexOn, clicked( bool ),
528 THEMIM->getIM(), activateTeletext( bool ) );
529 CONNECT( THEMIM->getIM(), teletextPossible( bool ),
530 telexOn, setEnabled( bool ) );
532 /* Transparency button */
533 QToolButton *telexTransparent = new QToolButton;
534 setupButton( telexTransparent );
535 BUTTON_SET_BAR2( telexTransparent, toolbar/tvtelx,
536 qtr( "Toggle Transparency " ) );
537 telexTransparent->setEnabled( false );
538 telexTransparent->setCheckable( true );
539 telexLayout->addWidget( telexTransparent );
541 /* Transparency change and set */
542 CONNECT( telexTransparent, clicked( bool ),
543 THEMIM->getIM(), telexSetTransparency( bool ) );
544 CONNECT( THEMIM->getIM(), teletextTransparencyActivated( bool ),
545 telexTransparent, setChecked( bool ) );
549 QSpinBox *telexPage = new QSpinBox( telexFrame );
550 telexPage->setRange( 0, 999 );
551 telexPage->setValue( 100 );
552 telexPage->setAccelerated( true );
553 telexPage->setWrapping( true );
554 telexPage->setAlignment( Qt::AlignRight );
555 telexPage->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum );
556 telexPage->setEnabled( false );
557 telexLayout->addWidget( telexPage );
559 /* Page change and set */
560 CONNECT( telexPage, valueChanged( int ),
561 THEMIM->getIM(), telexSetPage( int ) );
562 CONNECT( THEMIM->getIM(), newTelexPageSet( int ),
563 telexPage, setValue( int ) );
565 CONNECT( THEMIM->getIM(), teletextActivated( bool ), telexPage, setEnabled( bool ) );
566 CONNECT( THEMIM->getIM(), teletextActivated( bool ), telexTransparent, setEnabled( bool ) );
567 CONNECT( THEMIM->getIM(), teletextActivated( bool ), telexOn, setChecked( bool ) );
572 #undef CONNECT_MAP_SET
573 #undef BUTTON_SET_BAR
574 #undef BUTTON_SET_BAR2
575 #undef ENABLE_ON_VIDEO
576 #undef ENABLE_ON_INPUT
578 #include <QHBoxLayout>
579 /*****************************
580 * DA Control Widget !
581 *****************************/
582 ControlsWidget::ControlsWidget( intf_thread_t *_p_i,
585 AbstractController( _p_i, _parent )
587 setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Maximum );
589 /* advanced Controls handling */
590 b_advancedVisible = b_advControls;
592 QVBoxLayout *controlLayout = new QVBoxLayout( this );
593 controlLayout->setLayoutMargins( 6, 4, 6, 2, 5 );
594 controlLayout->setSpacing( 0 );
595 QHBoxLayout *controlLayout1 = new QHBoxLayout;
596 controlLayout1->setSpacing( 0 );
598 QString line1 = getSettings()->value( "MainToolbar1", MAIN_TB1_DEFAULT )
600 parseAndCreate( line1, controlLayout1 );
602 QHBoxLayout *controlLayout2 = new QHBoxLayout;
603 controlLayout2->setSpacing( 0 );
604 QString line2 = getSettings()->value( "MainToolbar2", MAIN_TB2_DEFAULT )
606 parseAndCreate( line2, controlLayout2 );
608 if( !b_advancedVisible && advControls ) advControls->hide();
610 controlLayout->addLayout( controlLayout1 );
611 controlLayout->addLayout( controlLayout2 );
614 ControlsWidget::~ControlsWidget()
617 void ControlsWidget::toggleAdvanced()
619 if( !advControls ) return;
621 if( !b_advancedVisible )
624 b_advancedVisible = true;
629 b_advancedVisible = false;
631 emit advancedControlsToggled( b_advancedVisible );
634 AdvControlsWidget::AdvControlsWidget( intf_thread_t *_p_i, QWidget *_parent ) :
635 AbstractController( _p_i, _parent )
637 controlLayout = new QHBoxLayout( this );
638 controlLayout->setMargin( 0 );
639 controlLayout->setSpacing( 0 );
641 QString line = getSettings()->value( "AdvToolbar", ADV_TB_DEFAULT )
643 parseAndCreate( line, controlLayout );
646 InputControlsWidget::InputControlsWidget( intf_thread_t *_p_i, QWidget *_parent ) :
647 AbstractController( _p_i, _parent )
649 controlLayout = new QHBoxLayout( this );
650 controlLayout->setMargin( 0 );
651 controlLayout->setSpacing( 0 );
653 QString line = getSettings()->value( "InputToolbar", INPT_TB_DEFAULT ).toString();
654 parseAndCreate( line, controlLayout );
656 /**********************************************************************
657 * Fullscrenn control widget
658 **********************************************************************/
659 FullscreenControllerWidget::FullscreenControllerWidget( intf_thread_t *_p_i )
660 : AbstractController( _p_i )
664 b_mouse_over = false;
665 i_mouse_last_move_x = -1;
666 i_mouse_last_move_y = -1;
667 #if HAVE_TRANSPARENCY
668 b_slow_hide_begin = false;
669 i_slow_hide_timeout = 1;
671 b_fullscreen = false;
677 setWindowFlags( Qt::ToolTip );
678 setMinimumWidth( 600 );
680 setFrameShape( QFrame::StyledPanel );
681 setFrameStyle( QFrame::Sunken );
682 setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
684 QVBoxLayout *controlLayout2 = new QVBoxLayout( this );
685 controlLayout2->setLayoutMargins( 4, 6, 4, 2, 5 );
688 InputControlsWidget *inputC = new InputControlsWidget( p_intf, this );
689 controlLayout2->addWidget( inputC );
691 controlLayout = new QHBoxLayout;
692 QString line = getSettings()->value( "MainWindow/FSCtoolbar", FSC_TB_DEFAULT ).toString();
693 parseAndCreate( line, controlLayout );
694 controlLayout2->addLayout( controlLayout );
697 p_hideTimer = new QTimer( this );
698 CONNECT( p_hideTimer, timeout(), this, hideFSC() );
699 p_hideTimer->setSingleShot( true );
701 /* slow hiding timer */
702 #if HAVE_TRANSPARENCY
703 p_slowHideTimer = new QTimer( this );
704 CONNECT( p_slowHideTimer, timeout(), this, slowHideFSC() );
707 adjustSize (); /* need to get real width and height for moving */
710 setWindowOpacity( 0.0 );
716 vlc_mutex_init_recursive( &lock );
718 CONNECT( THEMIM->getIM(), voutListChanged( vout_thread_t **, int ),
719 this, setVoutList( vout_thread_t **, int ) );
722 QPoint pos1 = getSettings()->value( "FullScreen/pos" ).toPoint();
723 int number = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
724 if( QApplication::desktop()->screenGeometry( number ).contains( pos1, true ) )
727 i_screennumber = number;
728 screenRes = QApplication::desktop()->screenGeometry(number);
737 FullscreenControllerWidget::~FullscreenControllerWidget()
739 getSettings()->setValue( "FullScreen/pos", pos() );
740 setVoutList( NULL, 0 );
741 vlc_mutex_destroy( &lock );
744 void FullscreenControllerWidget::centerFSC( int number )
746 screenRes = QApplication::desktop()->screenGeometry(number);
747 /* screen has changed, calculate new position */
748 QPoint pos = QPoint( screenRes.x() + (screenRes.width() / 2) - (width() / 2),
749 screenRes.y() + screenRes.height() - height());
751 i_screennumber = number;
755 * Show fullscreen controller
757 void FullscreenControllerWidget::showFSC()
761 int number = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
763 if( number != i_screennumber ||
764 screenRes != QApplication::desktop()->screenGeometry(number) )
769 // after quiting and going to fs, we need to call show()
775 setWindowOpacity( 1.0 );
781 #if HAVE_TRANSPARENCY
782 setWindowOpacity( DEFAULT_OPACITY );
787 * Hide fullscreen controller
788 * FIXME: under windows it have to be done by moving out of screen
789 * because hide() doesnt work
791 void FullscreenControllerWidget::hideFSC()
795 setWindowOpacity( 0.0 ); // simulate hidding
802 * Plane to hide fullscreen controller
804 void FullscreenControllerWidget::planHideFSC()
806 vlc_mutex_lock( &lock );
807 int i_timeout = i_hide_timeout;
808 vlc_mutex_unlock( &lock );
810 p_hideTimer->start( i_timeout );
812 #if HAVE_TRANSPARENCY
813 b_slow_hide_begin = true;
814 i_slow_hide_timeout = i_timeout;
815 p_slowHideTimer->start( i_slow_hide_timeout / 2 );
820 * Hidding fullscreen controller slowly
821 * Linux: need composite manager
822 * Windows: it is blinking, so it can be enabled by define TRASPARENCY
824 void FullscreenControllerWidget::slowHideFSC()
826 #if HAVE_TRANSPARENCY
827 if( b_slow_hide_begin )
829 b_slow_hide_begin = false;
831 p_slowHideTimer->stop();
832 /* the last part of time divided to 100 pieces */
833 p_slowHideTimer->start( (int)( i_slow_hide_timeout / 2 / ( windowOpacity() * 100 ) ) );
839 if ( windowOpacity() > 0.0 && !b_fscHidden )
841 if ( windowOpacity() > 0.0 )
844 /* we should use 0.01 because of 100 pieces ^^^
845 but than it cannt be done in time */
846 setWindowOpacity( windowOpacity() - 0.02 );
849 if ( windowOpacity() <= 0.0 )
850 p_slowHideTimer->stop();
857 * events: show, hide, start timer for hidding
859 void FullscreenControllerWidget::customEvent( QEvent *event )
863 switch( event->type() )
865 case FullscreenControlToggle_Type:
866 vlc_mutex_lock( &lock );
868 vlc_mutex_unlock( &lock );
884 case FullscreenControlShow_Type:
885 vlc_mutex_lock( &lock );
887 vlc_mutex_unlock( &lock );
890 if( b_fs && b_fscHidden )
892 if( b_fs && !isVisible() )
896 case FullscreenControlHide_Type:
899 case FullscreenControlPlanHide_Type:
900 if( !b_mouse_over ) // Only if the mouse is not over FSC
912 void FullscreenControllerWidget::mouseMoveEvent( QMouseEvent *event )
914 if( event->buttons() == Qt::LeftButton )
916 if( i_mouse_last_x == -1 || i_mouse_last_y == -1 )
919 int i_moveX = event->globalX() - i_mouse_last_x;
920 int i_moveY = event->globalY() - i_mouse_last_y;
922 move( x() + i_moveX, y() + i_moveY );
924 i_mouse_last_x = event->globalX();
925 i_mouse_last_y = event->globalY();
931 * store position of cursor
933 void FullscreenControllerWidget::mousePressEvent( QMouseEvent *event )
935 i_mouse_last_x = event->globalX();
936 i_mouse_last_y = event->globalY();
939 void FullscreenControllerWidget::mouseReleaseEvent( QMouseEvent *event )
946 * On mouse go above FSC
948 void FullscreenControllerWidget::enterEvent( QEvent *event )
953 #if HAVE_TRANSPARENCY
954 p_slowHideTimer->stop();
960 * On mouse go out from FSC
962 void FullscreenControllerWidget::leaveEvent( QEvent *event )
966 b_mouse_over = false;
971 * When you get pressed key, send it to video output
972 * FIXME: clearing focus by clearFocus() to not getting
973 * key press events didnt work
975 void FullscreenControllerWidget::keyPressEvent( QKeyEvent *event )
977 int i_vlck = qtEventToVLCKey( event );
980 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlck );
988 static int FullscreenControllerWidgetFullscreenChanged( vlc_object_t *vlc_object,
989 const char *variable, vlc_value_t old_val,
990 vlc_value_t new_val, void *data )
992 vout_thread_t *p_vout = (vout_thread_t *) vlc_object;
994 msg_Dbg( p_vout, "Qt4: Fullscreen state changed" );
995 FullscreenControllerWidget *p_fs = (FullscreenControllerWidget *)data;
997 p_fs->fullscreenChanged( p_vout, new_val.b_bool, var_GetInteger( p_vout, "mouse-hide-timeout" ) );
1002 static int FullscreenControllerWidgetMouseMoved( vlc_object_t *vlc_object, const char *variable,
1003 vlc_value_t old_val, vlc_value_t new_val,
1006 vout_thread_t *p_vout = (vout_thread_t *)vlc_object;
1007 FullscreenControllerWidget *p_fs = (FullscreenControllerWidget *)data;
1009 /* Get the value from the Vout - Trust the vout more than Qt */
1010 const int i_mousex = var_GetInteger( p_vout, "mouse-x" );
1011 const int i_mousey = var_GetInteger( p_vout, "mouse-y" );
1013 p_fs->mouseChanged( p_vout, i_mousex, i_mousey );
1019 * It is call to update the list of vout handled by the fullscreen controller
1021 void FullscreenControllerWidget::setVoutList( vout_thread_t **pp_vout, int i_vout )
1023 QList<vout_thread_t*> del;
1024 QList<vout_thread_t*> add;
1026 QList<vout_thread_t*> set;
1029 for( int i = 0; i < i_vout; i++ )
1032 /* Vout to remove */
1033 vlc_mutex_lock( &lock );
1034 foreach( vout_thread_t *p_vout, vout )
1036 if( !set.contains( p_vout ) )
1039 vlc_mutex_unlock( &lock );
1041 foreach( vout_thread_t *p_vout, del )
1043 var_DelCallback( p_vout, "fullscreen",
1044 FullscreenControllerWidgetFullscreenChanged, this );
1045 vlc_mutex_lock( &lock );
1046 fullscreenChanged( p_vout, false, 0 );
1047 vout.removeAll( p_vout );
1048 vlc_mutex_unlock( &lock );
1050 vlc_object_release( VLC_OBJECT(p_vout) );
1054 vlc_mutex_lock( &lock );
1055 foreach( vout_thread_t *p_vout, set )
1057 if( !vout.contains( p_vout ) )
1060 vlc_mutex_unlock( &lock );
1062 foreach( vout_thread_t *p_vout, add )
1064 vlc_object_hold( VLC_OBJECT(p_vout) );
1066 vlc_mutex_lock( &lock );
1067 vout.append( p_vout );
1068 var_AddCallback( p_vout, "fullscreen",
1069 FullscreenControllerWidgetFullscreenChanged, this );
1070 /* I miss a add and fire */
1071 fullscreenChanged( p_vout, var_GetBool( p_vout, "fullscreen" ),
1072 var_GetInteger( p_vout, "mouse-hide-timeout" ) );
1073 vlc_mutex_unlock( &lock );
1077 * Register and unregister callback for mouse moving
1079 void FullscreenControllerWidget::fullscreenChanged( vout_thread_t *p_vout,
1080 bool b_fs, int i_timeout )
1082 /* FIXME - multiple vout (ie multiple mouse position ?) and thread safety if multiple vout ? */
1083 msg_Dbg( p_vout, "Qt: Entering Fullscreen" );
1085 vlc_mutex_lock( &lock );
1086 /* Entering fullscreen, register callback */
1087 if( b_fs && !b_fullscreen )
1089 b_fullscreen = true;
1090 i_hide_timeout = i_timeout;
1091 var_AddCallback( p_vout, "mouse-moved",
1092 FullscreenControllerWidgetMouseMoved, this );
1094 /* Quitting fullscreen, unregistering callback */
1095 else if( !b_fs && b_fullscreen )
1097 b_fullscreen = false;
1098 i_hide_timeout = i_timeout;
1099 var_DelCallback( p_vout, "mouse-moved",
1100 FullscreenControllerWidgetMouseMoved, this );
1102 /* Force fs hidding */
1103 IMEvent *eHide = new IMEvent( FullscreenControlHide_Type, 0 );
1104 QApplication::postEvent( this, eHide );
1106 vlc_mutex_unlock( &lock );
1110 * Mouse change callback (show/hide the controller on mouse movement)
1112 void FullscreenControllerWidget::mouseChanged( vout_thread_t *p_vout, int i_mousex, int i_mousey )
1116 /* FIXME - multiple vout (ie multiple mouse position ?) and thread safety if multiple vout ? */
1119 if( ( i_mouse_last_move_x == -1 || i_mouse_last_move_y == -1 ) ||
1120 ( abs( i_mouse_last_move_x - i_mousex ) > 2 ||
1121 abs( i_mouse_last_move_y - i_mousey ) > 2 ) )
1123 i_mouse_last_move_x = i_mousex;
1124 i_mouse_last_move_y = i_mousey;
1131 IMEvent *eShow = new IMEvent( FullscreenControlShow_Type, 0 );
1132 QApplication::postEvent( this, eShow );
1134 /* Plan hide event */
1135 IMEvent *eHide = new IMEvent( FullscreenControlPlanHide_Type, 0 );
1136 QApplication::postEvent( this, eHide );