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

@ -1370,50 +1370,124 @@ download page.</string>
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_11"> <layout class="QVBoxLayout" name="verticalLayout_11">
<item> <item>
<widget class="QGroupBox" name="groupBox_ScanPopupTechnologies"> <layout class="QHBoxLayout" name="horizontalLayout_17">
<property name="title"> <item>
<string>ScanPopup extra technologies</string> <widget class="QGroupBox" name="groupBox_ScanPopupTechnologies">
</property> <property name="title">
<layout class="QVBoxLayout" name="verticalLayout_13"> <string>ScanPopup extra technologies</string>
<item> </property>
<widget class="QCheckBox" name="scanPopupUseIAccessibleEx"> <layout class="QVBoxLayout" name="verticalLayout_13">
<property name="toolTip"> <item>
<string>Try to use IAccessibleEx technology to retrieve word under cursor. <widget class="QCheckBox" name="scanPopupUseIAccessibleEx">
<property name="toolTip">
<string>Try to use IAccessibleEx technology to retrieve word under cursor.
This technology works only with some programs that support it This technology works only with some programs that support it
(for example Internet Explorer 9). (for example Internet Explorer 9).
It is not needed to select this option if you don't use such programs.</string> It is not needed to select this option if you don't use such programs.</string>
</property> </property>
<property name="text"> <property name="text">
<string>Use &amp;IAccessibleEx</string> <string>Use &amp;IAccessibleEx</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QCheckBox" name="scanPopupUseUIAutomation"> <widget class="QCheckBox" name="scanPopupUseUIAutomation">
<property name="toolTip"> <property name="toolTip">
<string>Try to use UI Automation technology to retrieve word under cursor. <string>Try to use UI Automation technology to retrieve word under cursor.
This technology works only with some programs that support it. This technology works only with some programs that support it.
It is not needed to select this option if you don't use such programs.</string> It is not needed to select this option if you don't use such programs.</string>
</property> </property>
<property name="text"> <property name="text">
<string>Use &amp;UIAutomation</string> <string>Use &amp;UIAutomation</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QCheckBox" name="scanPopupUseGDMessage"> <widget class="QCheckBox" name="scanPopupUseGDMessage">
<property name="toolTip"> <property name="toolTip">
<string>Try to use special GoldenDict message to retrieve word under cursor. <string>Try to use special GoldenDict message to retrieve word under cursor.
This technology works only with some programs that support it. This technology works only with some programs that support it.
It is not needed to select this option if you don't use such programs.</string> It is not needed to select this option if you don't use such programs.</string>
</property> </property>
<property name="text"> <property name="text">
<string>Use &amp;GoldenDict message</string> <string>Use &amp;GoldenDict message</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</widget> </widget>
</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> <item>
<layout class="QHBoxLayout" name="horizontalLayout_15"> <layout class="QHBoxLayout" name="horizontalLayout_15">

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);