mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-27 15:24:05 +00:00
Allow customizing unpinned scan popup window flags on X11 with Qt5
My tests in many desktop environments and window managers indicate that
no single configuration works perfectly in all environments. There are
also behavior differences between Qt::Popup and Qt::Tool flags, which
are not exactly bugs, so I suppose users might subjectively prefer
different options.
Customizing the flags allows the user to prevent unpinned scan popup
window flickering with Qt5 on Linux. In a way adding these options fixes
issue #645, which is: the scan popup window blinks rapidly, barely
noticeably in some applications, such as Calibre ebook-viewer
and Chromium. In this case the scan popup window usually ends up hidden
when selection ends, unless it was finished with a jerk.
I have tested the new options in 9 desktop environments and window
managers: at least one configuration for each eliminates #645 and makes
the scan popup window work the same as with Qt4 in this regard:
the popup window remains visible, text in the popup's translation line
keeps up with the text selection in the external application,
and the selected text is being translated on the fly.
Moreover, for each tested DE/WM, at least one configuration makes
the scan popup window work perfectly as far as I am concerned.
This issue was partially worked around with a 200ms scan popup delay
timer in the recent commit 58e41fe3ce
for the duplicate issue #854. However the timer solution is incomplete
because it requires the user to select text quickly and without delays.
If global mouse selection does not change for 200ms while the left mouse
button is held down, the user will likely not see the scan popup when
(s)he finishes selection, and will have to try selecting again -
hopefully faster this time.
The 200ms delay is no longer critically important after this commit,
but it is still beneficial: the lookup query changes less often,
which in turn reduces article definition update frequency.
So the delay improves the UI (perhaps subjectively) and performance.
This commit is contained in:
parent
d530af7781
commit
15dfdee49f
24
config.cc
24
config.cc
|
@ -128,6 +128,18 @@ bool InternalPlayerBackend::isQtmultimedia() const
|
|||
#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():
|
||||
newTabsOpenAfterCurrentOne( false ),
|
||||
newTabsOpenInBackground( true ),
|
||||
|
@ -158,6 +170,8 @@ Preferences::Preferences():
|
|||
scanPopupUseUIAutomation( true ),
|
||||
scanPopupUseIAccessibleEx( true ),
|
||||
scanPopupUseGDMessage( true ),
|
||||
scanPopupUnpinnedWindowFlags( SPWF_default ),
|
||||
scanPopupUnpinnedBypassWMHint( false ),
|
||||
scanToMainWindow( false ),
|
||||
#ifdef HAVE_X11
|
||||
showScanFlag( false ),
|
||||
|
@ -812,6 +826,8 @@ Class load() throw( exError )
|
|||
c.preferences.scanPopupUseUIAutomation = ( preferences.namedItem( "scanPopupUseUIAutomation" ).toElement().text() == "1" );
|
||||
c.preferences.scanPopupUseIAccessibleEx = ( preferences.namedItem( "scanPopupUseIAccessibleEx" ).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.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" ) );
|
||||
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.appendChild( dd.createTextNode( c.preferences.pronounceOnLoadMain ? "1" : "0" ) );
|
||||
preferences.appendChild( opt );
|
||||
|
|
19
config.hh
19
config.hh
|
@ -225,6 +225,23 @@ private:
|
|||
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
|
||||
struct Preferences
|
||||
{
|
||||
|
@ -263,6 +280,8 @@ struct Preferences
|
|||
bool scanPopupUseUIAutomation;
|
||||
bool scanPopupUseIAccessibleEx;
|
||||
bool scanPopupUseGDMessage;
|
||||
ScanPopupWindowFlags scanPopupUnpinnedWindowFlags;
|
||||
bool scanPopupUnpinnedBypassWMHint;
|
||||
bool scanToMainWindow;
|
||||
#ifdef HAVE_X11
|
||||
bool showScanFlag;
|
||||
|
|
|
@ -191,6 +191,8 @@ Preferences::Preferences( QWidget * parent, Config::Class & cfg_ ):
|
|||
ui.scanPopupUseUIAutomation->setChecked( p.scanPopupUseUIAutomation );
|
||||
ui.scanPopupUseIAccessibleEx->setChecked( p.scanPopupUseIAccessibleEx );
|
||||
ui.scanPopupUseGDMessage->setChecked( p.scanPopupUseGDMessage );
|
||||
ui.scanPopupUnpinnedWindowFlags->setCurrentIndex( p.scanPopupUnpinnedWindowFlags );
|
||||
ui.scanPopupUnpinnedBypassWMHint->setChecked( p.scanPopupUnpinnedBypassWMHint );
|
||||
|
||||
ui.storeHistory->setChecked( p.storeHistory );
|
||||
ui.historyMaxSizeField->setValue( p.maxStringsInHistory );
|
||||
|
@ -232,6 +234,10 @@ Preferences::Preferences( QWidget * parent, Config::Class & cfg_ ):
|
|||
// ui.tabWidget->removeTab( 5 );
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_SPWF_CUSTOMIZATION
|
||||
ui.groupBox_ScanPopupWindowFlags->hide();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_X11
|
||||
ui.showScanFlag->setChecked( p.showScanFlag);
|
||||
#else
|
||||
|
@ -395,6 +401,8 @@ Config::Preferences Preferences::getPreferences()
|
|||
p.scanPopupUseUIAutomation = ui.scanPopupUseUIAutomation->isChecked();
|
||||
p.scanPopupUseIAccessibleEx = ui.scanPopupUseIAccessibleEx->isChecked();
|
||||
p.scanPopupUseGDMessage = ui.scanPopupUseGDMessage->isChecked();
|
||||
p.scanPopupUnpinnedWindowFlags = Config::spwfFromInt( ui.scanPopupUnpinnedWindowFlags->currentIndex() );
|
||||
p.scanPopupUnpinnedBypassWMHint = ui.scanPopupUnpinnedBypassWMHint->isChecked();
|
||||
|
||||
p.storeHistory = ui.storeHistory->isChecked();
|
||||
p.maxStringsInHistory = ui.historyMaxSizeField->text().toUInt();
|
||||
|
@ -543,6 +551,11 @@ void Preferences::showScanFlagToggled( bool b )
|
|||
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 )
|
||||
{
|
||||
if ( b )
|
||||
|
|
|
@ -34,6 +34,7 @@ private slots:
|
|||
void enableScanPopupToggled( bool );
|
||||
void enableScanPopupModifiersToggled( bool );
|
||||
void showScanFlagToggled( bool b );
|
||||
void on_scanPopupUnpinnedWindowFlags_currentIndexChanged( int index );
|
||||
|
||||
void wholeAltClicked( bool );
|
||||
void wholeCtrlClicked( bool );
|
||||
|
|
148
preferences.ui
148
preferences.ui
|
@ -1370,50 +1370,124 @@ download page.</string>
|
|||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_ScanPopupTechnologies">
|
||||
<property name="title">
|
||||
<string>ScanPopup extra technologies</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="scanPopupUseIAccessibleEx">
|
||||
<property name="toolTip">
|
||||
<string>Try to use IAccessibleEx technology to retrieve word under cursor.
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_17">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_ScanPopupTechnologies">
|
||||
<property name="title">
|
||||
<string>ScanPopup extra technologies</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
<item>
|
||||
<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
|
||||
(for example Internet Explorer 9).
|
||||
It is not needed to select this option if you don't use such programs.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use &IAccessibleEx</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="scanPopupUseUIAutomation">
|
||||
<property name="toolTip">
|
||||
<string>Try to use UI Automation technology to retrieve word under cursor.
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use &IAccessibleEx</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="scanPopupUseUIAutomation">
|
||||
<property name="toolTip">
|
||||
<string>Try to use UI Automation technology to retrieve word under cursor.
|
||||
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>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use &UIAutomation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="scanPopupUseGDMessage">
|
||||
<property name="toolTip">
|
||||
<string>Try to use special GoldenDict message to retrieve word under cursor.
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use &UIAutomation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="scanPopupUseGDMessage">
|
||||
<property name="toolTip">
|
||||
<string>Try to use special GoldenDict message to retrieve word under cursor.
|
||||
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>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use &GoldenDict message</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use &GoldenDict message</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</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><default></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>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_15">
|
||||
|
|
44
scanpopup.cc
44
scanpopup.cc
|
@ -24,7 +24,7 @@ using std::wstring;
|
|||
|
||||
/// We use different window flags under Windows and X11 due to slight differences
|
||||
/// 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 ) )
|
||||
Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint
|
||||
|
@ -177,7 +177,7 @@ ScanPopup::ScanPopup( QWidget * parent,
|
|||
else
|
||||
{
|
||||
dictionaryBar.setMovable( false );
|
||||
setWindowFlags( popupWindowFlags );
|
||||
setWindowFlags( unpinnedWindowFlags() );
|
||||
}
|
||||
|
||||
connect( &configEvents, SIGNAL( mutedDictionariesChanged() ),
|
||||
|
@ -387,6 +387,27 @@ void ScanPopup::applyWordsZoomLevel()
|
|||
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()
|
||||
{
|
||||
return translateWordFromClipboard(QClipboard::Clipboard);
|
||||
|
@ -584,6 +605,14 @@ void ScanPopup::engagePopup( bool forcePopup, bool giveFocus )
|
|||
|
||||
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 )
|
||||
{
|
||||
activateWindow();
|
||||
|
@ -608,6 +637,15 @@ void ScanPopup::engagePopup( bool forcePopup, bool giveFocus )
|
|||
activateWindow();
|
||||
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() )
|
||||
setWindowTitle( tr( "%1 - %2" ).arg( elideInputWord(), "GoldenDict" ) );
|
||||
|
@ -973,7 +1011,7 @@ void ScanPopup::pinButtonClicked( bool checked )
|
|||
{
|
||||
ui.onTopButton->setVisible( false );
|
||||
dictionaryBar.setMovable( false );
|
||||
setWindowFlags( popupWindowFlags );
|
||||
setWindowFlags( unpinnedWindowFlags() );
|
||||
|
||||
mouseEnteredOnce = true;
|
||||
}
|
||||
|
|
|
@ -108,6 +108,8 @@ public slots:
|
|||
|
||||
private:
|
||||
|
||||
Qt::WindowFlags unpinnedWindowFlags() const;
|
||||
|
||||
// Translates the word from the clipboard or the clipboard selection
|
||||
void translateWordFromClipboard(QClipboard::Mode m);
|
||||
|
||||
|
|
Loading…
Reference in a new issue