diff --git a/src/main.cc b/src/main.cc index 306ed9e1a..e7adb1b4a 100644 --- a/src/main.cc +++ b/src/main.cc @@ -243,16 +243,20 @@ void processCommandLine( QCoreApplication * app, GDOptions * result ) int main( int argc, char ** argv ) { #if defined( WITH_X11 ) - // GoldenDict use lots of X11 functions and it currently cannot work - // natively on Wayland. This workaround will force GoldenDict to use - // XWayland. - - if ( qEnvironmentVariableIsEmpty( "GOLDENDICT_FORCE_WAYLAND" ) && !Utils::isWayland() ) { - char * xdg_envc = getenv( "XDG_SESSION_TYPE" ); - QString xdg_session = xdg_envc ? QString::fromLatin1( xdg_envc ) : QString(); - if ( !QString::compare( xdg_session, QString( "wayland" ), Qt::CaseInsensitive ) ) { + // Platform selection: Higher priority to user intention + // 1. Respect QT_QPA_PLATFORM if already set. + // 2. GOLDENDICT_FORCE_XCB forces Xcb (fallback mode). + // 3. GOLDENDICT_FORCE_WAYLAND forces native Wayland. + // 4. By default, we let Qt decide (usually native Wayland on Wayland sessions). + // This improves HiDPI support but might affect some X11-specific features. + + if ( qEnvironmentVariableIsEmpty( "QT_QPA_PLATFORM" ) ) { + if ( qEnvironmentVariableIsSet( "GOLDENDICT_FORCE_XCB" ) ) { setenv( "QT_QPA_PLATFORM", "xcb", 1 ); } + else if ( qEnvironmentVariableIsSet( "GOLDENDICT_FORCE_WAYLAND" ) ) { + setenv( "QT_QPA_PLATFORM", "wayland", 1 ); + } } #endif diff --git a/src/ui/mainwindow.cc b/src/ui/mainwindow.cc index 2cc455ee8..d10d19b5c 100644 --- a/src/ui/mainwindow.cc +++ b/src/ui/mainwindow.cc @@ -2987,7 +2987,7 @@ void MainWindow::toggleMainWindow( bool ensureShow ) void MainWindow::installHotKeys() { #if defined( WITH_X11 ) - if ( !qEnvironmentVariableIsEmpty( "GOLDENDICT_FORCE_WAYLAND" ) || Utils::isWayland() ) { + if ( QGuiApplication::platformName() != "xcb" ) { return; } #endif diff --git a/src/ui/scanpopup.cc b/src/ui/scanpopup.cc index 1e49f0bbb..696b9fa2c 100644 --- a/src/ui/scanpopup.cc +++ b/src/ui/scanpopup.cc @@ -341,18 +341,20 @@ ScanPopup::ScanPopup( QWidget * parent, #endif #ifdef WITH_X11 - scanFlag = new ScanFlag( this ); + if ( QGuiApplication::platformName() == "xcb" ) { + scanFlag = new ScanFlag( this ); - connect( scanFlag, &ScanFlag::requestScanPopup, this, [ this ] { - translateWordFromSelection(); - } ); + connect( scanFlag, &ScanFlag::requestScanPopup, this, [ this ] { + translateWordFromSelection(); + } ); - // Use delay show to prevent popup from showing up while selection is still in progress - // Only certain software has this problem (e.g. Chrome) - selectionDelayTimer.setSingleShot( true ); - selectionDelayTimer.setInterval( cfg.preferences.selectionChangeDelayTimer ); + // Use delay show to prevent popup from showing up while selection is still in progress + // Only certain software has this problem (e.g. Chrome) + selectionDelayTimer.setSingleShot( true ); + selectionDelayTimer.setInterval( cfg.preferences.selectionChangeDelayTimer ); - connect( &selectionDelayTimer, &QTimer::timeout, this, &ScanPopup::translateWordFromSelection ); + connect( &selectionDelayTimer, &QTimer::timeout, this, &ScanPopup::translateWordFromSelection ); + } #endif applyZoomFactor(); @@ -447,7 +449,9 @@ void ScanPopup::refresh() connect( groupList, &GroupComboBox::currentIndexChanged, this, &ScanPopup::currentGroupChanged ); #ifdef WITH_X11 - selectionDelayTimer.setInterval( cfg.preferences.selectionChangeDelayTimer ); + if ( scanFlag ) { + selectionDelayTimer.setInterval( cfg.preferences.selectionChangeDelayTimer ); + } #endif } diff --git a/src/ui/scanpopup.hh b/src/ui/scanpopup.hh index 5d9f8cf56..ebac0b632 100644 --- a/src/ui/scanpopup.hh +++ b/src/ui/scanpopup.hh @@ -146,7 +146,7 @@ private: QFont wordListDefaultFont, translateLineDefaultFont, groupListDefaultFont; #ifdef WITH_X11 - ScanFlag * scanFlag; + ScanFlag * scanFlag = nullptr; #endif bool mouseEnteredOnce = false; diff --git a/website/docs/topic_wayland.md b/website/docs/topic_wayland.md index a15d7615f..6a4450cee 100644 --- a/website/docs/topic_wayland.md +++ b/website/docs/topic_wayland.md @@ -1,16 +1,53 @@ -Environment variable `GOLDENDICT_FORCE_WAYLAND` can be used to force GD to run in Wayland mode, like `env GOLDENDICT_FORCE_WAYLAND=1 goldendict`. +# Wayland Support and Configuration -!!! danger "Don't use unless you know!" - This flag only guarantees GD to run in wayland mode and won't crash, but nothing more. +GoldenDict-ng supports running both natively on **Wayland** and via **XWayland (X11)**. - Enable this will break popup, global hotkeys and probably other things. +Since version 25.12.0, the application defaults to native Wayland on Wayland sessions to provide the best HiDPI and fractional scaling experience. However, due to Wayland's security design, certain features like global hotkeys and screen-grabbing popups may require switching back to X11 mode. -## Current reality +## Mode Selection Hardware -!!! note "Help wanted" - Need help to redesign popup for wayland. +The display mode is determined by environment variables at startup. You can specify your preference using the following flags: -Popup is implemented with `querying mouse cursor's position` and `setting a window's absolute global position`. -Wayland does not support both by design and philosophy. +| Mode | Environment Variable | Best For | +| :--- | :--- | :--- | +| **Native Wayland** (Default) | (None) or `GOLDENDICT_FORCE_WAYLAND=1` | HiDPI screens, smooth scaling, security. | +| **XWayland (X11)** | `GOLDENDICT_FORCE_XCB=1` | Global hotkeys, advanced ScanPopup (ScanFlag). | -Wayland does not support registering global hotkeys until very recently, but a reasonable wayland desktop environment should provide some way to bind keys to commands globally. \ No newline at end of file +### How to Switch + +#### 1. Native Wayland (Default) +By default, the app will try to run as a native Wayland client. If you want to force it explicitly: +```bash +env GOLDENDICT_FORCE_WAYLAND=1 goldendict +``` + +#### 2. XWayland / X11 Mode (Recommended for Hotkeys) +If you need global hotkeys (`Ctrl+C+C` etc.) or the "Scan Flag" feature to work across windows, run the app in X11 mode: +```bash +env GOLDENDICT_FORCE_XCB=1 goldendict +``` + +### Flatpak Configuration +If you are using the Flatpak version, you can use **Flatseal** or the command line to set these variables: +```bash +# Force X11 mode for Flatpak +flatpak override --env=GOLDENDICT_FORCE_XCB=1 io.github.xiaoyifang.goldendict_ng +``` + +--- + +## Technical Comparison + +| Feature | Native Wayland | XWayland (X11) | +| :--- | :---: | :---: | +| **HiDPI / Sharp Text** | ⭐ Excellent | ⚠️ May be blurry | +| **Global Hotkeys** | ❌ Not Supported | ✅ Fully Supported | +| **Scan Flag (Small Flag)** | ❌ Disabled | ✅ Enabled | +| **Window Positioning** | ⚠️ Limited by compositor | ✅ Precise | +| **Input Method (IME)** | ✅ Supported (Qt 6) | ✅ Supported | + +!!! danger "Global Hotkeys on Wayland" + Native Wayland does not allow applications to listen to keyboard events globally. If you rely on `Ctrl+C+C` to trigger lookups from other apps, you **must** use X11 mode (`GOLDENDICT_FORCE_XCB=1`). + +!!! tip "Workaround for Wayland Hotkeys" + Users on KDE or GNOME can manually bind a custom system shortcut to a command that sends a word to GoldenDict, for example: `goldendict "selection"`. \ No newline at end of file