Merge pull request #995 from vedgy/x11-fix-unpinned-scan-popup-option

Allow customizing unpinned scan popup window flags on X11 with Qt5
This commit is contained in:
Abs62 2018-04-15 20:49:30 +03:00 committed by GitHub
commit b34ac9630e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 212 additions and 41 deletions

View file

@ -128,6 +128,18 @@ bool InternalPlayerBackend::isQtmultimedia() const
#endif #endif
} }
ScanPopupWindowFlags spwfFromInt( int id )
{
if( id == SPWF_Popup )
return SPWF_Popup;
if( id == SPWF_Tool )
return SPWF_Tool;
if( id != SPWF_default )
gdWarning( "Invalid ScanPopup unpinned window flags: %d\n", id );
return SPWF_default;
}
Preferences::Preferences(): Preferences::Preferences():
newTabsOpenAfterCurrentOne( false ), newTabsOpenAfterCurrentOne( false ),
newTabsOpenInBackground( true ), newTabsOpenInBackground( true ),
@ -158,6 +170,8 @@ Preferences::Preferences():
scanPopupUseUIAutomation( true ), scanPopupUseUIAutomation( true ),
scanPopupUseIAccessibleEx( true ), scanPopupUseIAccessibleEx( true ),
scanPopupUseGDMessage( true ), scanPopupUseGDMessage( true ),
scanPopupUnpinnedWindowFlags( SPWF_default ),
scanPopupUnpinnedBypassWMHint( false ),
scanToMainWindow( false ), scanToMainWindow( false ),
#ifdef HAVE_X11 #ifdef HAVE_X11
showScanFlag( false ), showScanFlag( false ),
@ -812,6 +826,8 @@ Class load() throw( exError )
c.preferences.scanPopupUseUIAutomation = ( preferences.namedItem( "scanPopupUseUIAutomation" ).toElement().text() == "1" ); c.preferences.scanPopupUseUIAutomation = ( preferences.namedItem( "scanPopupUseUIAutomation" ).toElement().text() == "1" );
c.preferences.scanPopupUseIAccessibleEx = ( preferences.namedItem( "scanPopupUseIAccessibleEx" ).toElement().text() == "1" ); c.preferences.scanPopupUseIAccessibleEx = ( preferences.namedItem( "scanPopupUseIAccessibleEx" ).toElement().text() == "1" );
c.preferences.scanPopupUseGDMessage = ( preferences.namedItem( "scanPopupUseGDMessage" ).toElement().text() == "1" ); c.preferences.scanPopupUseGDMessage = ( preferences.namedItem( "scanPopupUseGDMessage" ).toElement().text() == "1" );
c.preferences.scanPopupUnpinnedWindowFlags = spwfFromInt( preferences.namedItem( "scanPopupUnpinnedWindowFlags" ).toElement().text().toInt() );
c.preferences.scanPopupUnpinnedBypassWMHint = ( preferences.namedItem( "scanPopupUnpinnedBypassWMHint" ).toElement().text() == "1" );
c.preferences.pronounceOnLoadMain = ( preferences.namedItem( "pronounceOnLoadMain" ).toElement().text() == "1" ); c.preferences.pronounceOnLoadMain = ( preferences.namedItem( "pronounceOnLoadMain" ).toElement().text() == "1" );
c.preferences.pronounceOnLoadPopup = ( preferences.namedItem( "pronounceOnLoadPopup" ).toElement().text() == "1" ); c.preferences.pronounceOnLoadPopup = ( preferences.namedItem( "pronounceOnLoadPopup" ).toElement().text() == "1" );
@ -1702,6 +1718,14 @@ void save( Class const & c ) throw( exError )
opt.appendChild( dd.createTextNode( c.preferences.scanPopupUseGDMessage ? "1":"0" ) ); opt.appendChild( dd.createTextNode( c.preferences.scanPopupUseGDMessage ? "1":"0" ) );
preferences.appendChild( opt ); preferences.appendChild( opt );
opt = dd.createElement( "scanPopupUnpinnedWindowFlags" );
opt.appendChild( dd.createTextNode( QString::number( c.preferences.scanPopupUnpinnedWindowFlags ) ) );
preferences.appendChild( opt );
opt = dd.createElement( "scanPopupUnpinnedBypassWMHint" );
opt.appendChild( dd.createTextNode( c.preferences.scanPopupUnpinnedBypassWMHint ? "1":"0" ) );
preferences.appendChild( opt );
opt = dd.createElement( "pronounceOnLoadMain" ); opt = dd.createElement( "pronounceOnLoadMain" );
opt.appendChild( dd.createTextNode( c.preferences.pronounceOnLoadMain ? "1" : "0" ) ); opt.appendChild( dd.createTextNode( c.preferences.pronounceOnLoadMain ? "1" : "0" ) );
preferences.appendChild( opt ); preferences.appendChild( opt );

View file

@ -225,6 +225,23 @@ private:
QString name; QString name;
}; };
#if defined( HAVE_X11 ) && QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
// The ScanPopup window flags customization code has been tested
// only in X11 desktop environments and window managers.
// None of the window flags configurations I have tried works perfectly well
// in XFCE with Qt4. Let us enable customization code for Qt5 exclusively to
// avoid regressions with Qt4.
#define ENABLE_SPWF_CUSTOMIZATION
#endif
enum ScanPopupWindowFlags
{
SPWF_default = 0,
SPWF_Popup,
SPWF_Tool
};
ScanPopupWindowFlags spwfFromInt( int id );
/// Various user preferences /// Various user preferences
struct Preferences struct Preferences
{ {
@ -263,6 +280,8 @@ struct Preferences
bool scanPopupUseUIAutomation; bool scanPopupUseUIAutomation;
bool scanPopupUseIAccessibleEx; bool scanPopupUseIAccessibleEx;
bool scanPopupUseGDMessage; bool scanPopupUseGDMessage;
ScanPopupWindowFlags scanPopupUnpinnedWindowFlags;
bool scanPopupUnpinnedBypassWMHint;
bool scanToMainWindow; bool scanToMainWindow;
#ifdef HAVE_X11 #ifdef HAVE_X11
bool showScanFlag; bool showScanFlag;

View file

@ -191,6 +191,8 @@ Preferences::Preferences( QWidget * parent, Config::Class & cfg_ ):
ui.scanPopupUseUIAutomation->setChecked( p.scanPopupUseUIAutomation ); ui.scanPopupUseUIAutomation->setChecked( p.scanPopupUseUIAutomation );
ui.scanPopupUseIAccessibleEx->setChecked( p.scanPopupUseIAccessibleEx ); ui.scanPopupUseIAccessibleEx->setChecked( p.scanPopupUseIAccessibleEx );
ui.scanPopupUseGDMessage->setChecked( p.scanPopupUseGDMessage ); ui.scanPopupUseGDMessage->setChecked( p.scanPopupUseGDMessage );
ui.scanPopupUnpinnedWindowFlags->setCurrentIndex( p.scanPopupUnpinnedWindowFlags );
ui.scanPopupUnpinnedBypassWMHint->setChecked( p.scanPopupUnpinnedBypassWMHint );
ui.storeHistory->setChecked( p.storeHistory ); ui.storeHistory->setChecked( p.storeHistory );
ui.historyMaxSizeField->setValue( p.maxStringsInHistory ); ui.historyMaxSizeField->setValue( p.maxStringsInHistory );
@ -232,6 +234,10 @@ Preferences::Preferences( QWidget * parent, Config::Class & cfg_ ):
// ui.tabWidget->removeTab( 5 ); // ui.tabWidget->removeTab( 5 );
#endif #endif
#ifndef ENABLE_SPWF_CUSTOMIZATION
ui.groupBox_ScanPopupWindowFlags->hide();
#endif
#ifdef HAVE_X11 #ifdef HAVE_X11
ui.showScanFlag->setChecked( p.showScanFlag); ui.showScanFlag->setChecked( p.showScanFlag);
#else #else
@ -395,6 +401,8 @@ Config::Preferences Preferences::getPreferences()
p.scanPopupUseUIAutomation = ui.scanPopupUseUIAutomation->isChecked(); p.scanPopupUseUIAutomation = ui.scanPopupUseUIAutomation->isChecked();
p.scanPopupUseIAccessibleEx = ui.scanPopupUseIAccessibleEx->isChecked(); p.scanPopupUseIAccessibleEx = ui.scanPopupUseIAccessibleEx->isChecked();
p.scanPopupUseGDMessage = ui.scanPopupUseGDMessage->isChecked(); p.scanPopupUseGDMessage = ui.scanPopupUseGDMessage->isChecked();
p.scanPopupUnpinnedWindowFlags = Config::spwfFromInt( ui.scanPopupUnpinnedWindowFlags->currentIndex() );
p.scanPopupUnpinnedBypassWMHint = ui.scanPopupUnpinnedBypassWMHint->isChecked();
p.storeHistory = ui.storeHistory->isChecked(); p.storeHistory = ui.storeHistory->isChecked();
p.maxStringsInHistory = ui.historyMaxSizeField->text().toUInt(); p.maxStringsInHistory = ui.historyMaxSizeField->text().toUInt();
@ -543,6 +551,11 @@ void Preferences::showScanFlagToggled( bool b )
ui.enableScanPopupModifiers->setChecked( false ); ui.enableScanPopupModifiers->setChecked( false );
} }
void Preferences::on_scanPopupUnpinnedWindowFlags_currentIndexChanged( int index )
{
ui.scanPopupUnpinnedBypassWMHint->setEnabled( Config::spwfFromInt( index ) != Config::SPWF_default );
}
void Preferences::wholeAltClicked( bool b ) void Preferences::wholeAltClicked( bool b )
{ {
if ( b ) if ( b )

View file

@ -34,6 +34,7 @@ private slots:
void enableScanPopupToggled( bool ); void enableScanPopupToggled( bool );
void enableScanPopupModifiersToggled( bool ); void enableScanPopupModifiersToggled( bool );
void showScanFlagToggled( bool b ); void showScanFlagToggled( bool b );
void on_scanPopupUnpinnedWindowFlags_currentIndexChanged( int index );
void wholeAltClicked( bool ); void wholeAltClicked( bool );
void wholeCtrlClicked( bool ); void wholeCtrlClicked( bool );

View file

@ -1369,6 +1369,8 @@ download page.</string>
<string>Ad&amp;vanced</string> <string>Ad&amp;vanced</string>
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_11"> <layout class="QVBoxLayout" name="verticalLayout_11">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_17">
<item> <item>
<widget class="QGroupBox" name="groupBox_ScanPopupTechnologies"> <widget class="QGroupBox" name="groupBox_ScanPopupTechnologies">
<property name="title"> <property name="title">
@ -1415,6 +1417,78 @@ It is not needed to select this option if you don't use such programs.</string>
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QGroupBox" name="groupBox_ScanPopupWindowFlags">
<property name="title">
<string>ScanPopup unpinned window flags</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_22">
<item>
<widget class="QComboBox" name="scanPopupUnpinnedWindowFlags">
<property name="toolTip">
<string>Experiment with non-default flags if the unpinned scan popup window misbehaves</string>
</property>
<item>
<property name="text">
<string>&lt;default&gt;</string>
</property>
</item>
<item>
<property name="text">
<string>Popup</string>
</property>
</item>
<item>
<property name="text">
<string>Tool</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QCheckBox" name="scanPopupUnpinnedBypassWMHint">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>This hint can be combined with non-default window flags</string>
</property>
<property name="text">
<string>Bypass window manager hint</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_18">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_13">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_15"> <layout class="QHBoxLayout" name="horizontalLayout_15">
<item> <item>

View file

@ -24,7 +24,7 @@ using std::wstring;
/// We use different window flags under Windows and X11 due to slight differences /// We use different window flags under Windows and X11 due to slight differences
/// in their behavior on those platforms. /// in their behavior on those platforms.
static Qt::WindowFlags popupWindowFlags = static const Qt::WindowFlags defaultUnpinnedWindowFlags =
#if defined (Q_OS_WIN) || ( defined (Q_OS_MAC) && QT_VERSION < QT_VERSION_CHECK( 5, 3, 0 ) ) #if defined (Q_OS_WIN) || ( defined (Q_OS_MAC) && QT_VERSION < QT_VERSION_CHECK( 5, 3, 0 ) )
Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint
@ -177,7 +177,7 @@ ScanPopup::ScanPopup( QWidget * parent,
else else
{ {
dictionaryBar.setMovable( false ); dictionaryBar.setMovable( false );
setWindowFlags( popupWindowFlags ); setWindowFlags( unpinnedWindowFlags() );
} }
connect( &configEvents, SIGNAL( mutedDictionariesChanged() ), connect( &configEvents, SIGNAL( mutedDictionariesChanged() ),
@ -387,6 +387,27 @@ void ScanPopup::applyWordsZoomLevel()
ui.groupList->parentWidget()->layout()->activate(); ui.groupList->parentWidget()->layout()->activate();
} }
Qt::WindowFlags ScanPopup::unpinnedWindowFlags() const
{
#ifdef ENABLE_SPWF_CUSTOMIZATION
const Config::ScanPopupWindowFlags spwf = cfg.preferences.scanPopupUnpinnedWindowFlags;
Qt::WindowFlags result;
if( spwf == Config::SPWF_Popup )
result = Qt::Popup;
else
if( spwf == Config::SPWF_Tool )
result = Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint;
else
return defaultUnpinnedWindowFlags; // Ignore BypassWMHint option.
if( cfg.preferences.scanPopupUnpinnedBypassWMHint )
result |= Qt::X11BypassWindowManagerHint;
return result;
#else
return defaultUnpinnedWindowFlags;
#endif
}
void ScanPopup::translateWordFromClipboard() void ScanPopup::translateWordFromClipboard()
{ {
return translateWordFromClipboard(QClipboard::Clipboard); return translateWordFromClipboard(QClipboard::Clipboard);
@ -584,6 +605,14 @@ void ScanPopup::engagePopup( bool forcePopup, bool giveFocus )
show(); show();
#ifdef ENABLE_SPWF_CUSTOMIZATION
// Ensure that the window always has focus on X11 with Qt::Tool flag.
// This also often prevents the window from disappearing prematurely with Qt::Popup flag,
// especially when combined with Qt::X11BypassWindowManagerHint flag.
if ( !ui.pinButton->isChecked() )
giveFocus = true;
#endif
if ( giveFocus ) if ( giveFocus )
{ {
activateWindow(); activateWindow();
@ -608,6 +637,15 @@ void ScanPopup::engagePopup( bool forcePopup, bool giveFocus )
activateWindow(); activateWindow();
raise(); raise();
} }
#ifdef ENABLE_SPWF_CUSTOMIZATION
else
if ( ( windowFlags() & Qt::Tool ) == Qt::Tool )
{
// Ensure that the window with Qt::Tool flag always has focus on X11.
activateWindow();
raise();
}
#endif
if ( ui.pinButton->isChecked() ) if ( ui.pinButton->isChecked() )
setWindowTitle( tr( "%1 - %2" ).arg( elideInputWord(), "GoldenDict" ) ); setWindowTitle( tr( "%1 - %2" ).arg( elideInputWord(), "GoldenDict" ) );
@ -906,7 +944,7 @@ void ScanPopup::requestWindowFocus()
// One of the rare, actually working workarounds for requesting a user keyboard focus on X11, // One of the rare, actually working workarounds for requesting a user keyboard focus on X11,
// works for Qt::Popup windows, exactly like our Scan Popup (in unpinned state). // works for Qt::Popup windows, exactly like our Scan Popup (in unpinned state).
// Modern window managers actively resist to automatically focus pop-up windows. // Modern window managers actively resist to automatically focus pop-up windows.
#ifdef HAVE_X11 #if defined HAVE_X11 && QT_VERSION < QT_VERSION_CHECK( 5, 0, 0 )
if ( !ui.pinButton->isChecked() ) if ( !ui.pinButton->isChecked() )
{ {
QMenu m( this ); QMenu m( this );
@ -973,7 +1011,7 @@ void ScanPopup::pinButtonClicked( bool checked )
{ {
ui.onTopButton->setVisible( false ); ui.onTopButton->setVisible( false );
dictionaryBar.setMovable( false ); dictionaryBar.setMovable( false );
setWindowFlags( popupWindowFlags ); setWindowFlags( unpinnedWindowFlags() );
mouseEnteredOnce = true; mouseEnteredOnce = true;
} }

View file

@ -108,6 +108,8 @@ public slots:
private: private:
Qt::WindowFlags unpinnedWindowFlags() const;
// Translates the word from the clipboard or the clipboard selection // Translates the word from the clipboard or the clipboard selection
void translateWordFromClipboard(QClipboard::Mode m); void translateWordFromClipboard(QClipboard::Mode m);