]> git.lyx.org Git - lyx.git/commitdiff
Fix paste of selection to (unfocused) external applications
authorEnrico Forestieri <forenr@lyx.org>
Sun, 10 Jul 2016 17:31:32 +0000 (19:31 +0200)
committerEnrico Forestieri <forenr@lyx.org>
Sun, 10 Jul 2016 17:31:32 +0000 (19:31 +0200)
With both Qt4 and Qt5, when using a click-to-focus policy, the first
attempt to paste a selection by middle mouse in an external application
which has no focus may fail. It is not clear why this succeeds for some
applications and fails for others, but refreshing the timestamp of the
selection request cures the issue. The cmake part is by Kornel.

See also this thread:
http://thread.gmane.org/gmane.editors.lyx.devel/162491

CMakeLists.txt
config/qt4.m4
development/cmake/ConfigureChecks.cmake
src/frontends/qt4/GuiApplication.cpp

index 76cbdde85aee56c7929c85b6bed922af637b71fe..74d0ac89526e79e328f8a6882c8173a329d46ef9 100644 (file)
@@ -925,11 +925,6 @@ endif()
 include(${LYX_CMAKE_DIR}/ConfigureChecks.cmake)
 configure_file(${LYX_CMAKE_DIR}/configCompiler.h.cmake ${TOP_BINARY_DIR}/configCompiler.h)
 
-set(QPA_XCB)
-if(Qt5X11Extras_FOUND AND QT_USES_X11)
-  # QPA_XCB is only valid if QT5+X11
-  set(QPA_XCB 1)
-endif()
 configure_file(${LYX_CMAKE_DIR}/config.h.cmake ${TOP_BINARY_DIR}/config.h)
 
 if(QTVERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+).*")
index 0e357a44de7f449349be8bf1e53c2c041d2fd36c..f39c0ed67ef612f9570649e964d85ccb63e7706f 100644 (file)
@@ -172,18 +172,30 @@ AC_DEFUN([QT_DO_IT_ALL],
        [AC_MSG_ERROR([LyX requires at least version $1 of Qt. Only version $QTLIB_VERSION has been found.])
        ])
 
+       save_CPPFLAGS=$CPPFLAGS
+       AC_MSG_CHECKING([whether Qt uses the X Window system])
+       CPPFLAGS="$save_CPPFLAGS $QT_CORE_INCLUDES"
        if test x$USE_QT5 = xyes ; then
-         save_CPPFLAGS=$CPPFLAGS
-         AC_MSG_CHECKING([whether Qt uses the X Window system])
-         CPPFLAGS="$save_CPPFLAGS $QT_CORE_INCLUDES"
          AC_EGREP_CPP(xcb,
            [#include <qconfig.h>
            QT_QPA_DEFAULT_PLATFORM_NAME],
            [AC_MSG_RESULT(yes)
             AC_DEFINE(QPA_XCB, 1, [Define if Qt uses the X Window System])],
            [AC_MSG_RESULT(no)])
-         CPPFLAGS=$save_CPPFLAGS
+       else
+         AC_PREPROC_IFELSE([AC_LANG_SOURCE([
+           [#include <qglobal.h>],
+           [#ifndef Q_WS_X11],
+           [#error Fail],
+           [#endif]])],
+           qt_use_x11=yes,
+           qt_use_x11=no)
+         AC_MSG_RESULT($qt_use_x11)
+         if test "x$qt_use_x11" = "xyes"; then
+           QT_LIB="$QT_LIB -lX11"
+         fi
        fi
+       CPPFLAGS=$save_CPPFLAGS
 
        QT_FIND_TOOL([QT_MOC], [moc])
        QT_FIND_TOOL([QT_UIC], [uic])
@@ -209,6 +221,13 @@ AC_DEFUN([QT_DO_PKG_CONFIG],
        if test "x$USE_QT5" != "xno" ; then
                qt_corelibs="Qt5Core"
                qt_guilibs="Qt5Core Qt5Concurrent Qt5Gui Qt5Svg Qt5Widgets"
+               lyx_use_x11extras=false
+               PKG_CHECK_EXISTS(Qt5X11Extras, [lyx_use_x11extras=true], [])
+               if $lyx_use_x11extras; then
+                       qt_guilibs="$qt_guilibs Qt5X11Extras xcb"
+                       AC_DEFINE(HAVE_QT5_X11_EXTRAS, 1,
+                               [Define if you have the Qt5X11Extras module])
+               fi
                lyx_use_winextras=false
                PKG_CHECK_EXISTS(Qt5WinExtras, [lyx_use_winextras=true], [])
                if $lyx_use_winextras; then
index 46d3f809b73e754ff280e72745380cee971bb230..c9c7b74b87a4f2b43dd0c9795af1bb37c3a98917 100644 (file)
@@ -12,6 +12,7 @@ include(CheckFunctionExists)
 include(CheckLibraryExists)
 include(CheckTypeSize)
 include(CheckCXXSourceCompiles)
+include(CheckCXXSourceRuns)
 include(MacroBoolTo01)
 include(TestBigEndian)
 
@@ -197,7 +198,30 @@ else()
   endif()
 endif()
 
+set(QPA_XCB)
+set(HAVE_QT5_X11_EXTRAS)
 if(LYX_USE_QT MATCHES "QT5")
+
+  set(CMAKE_REQUIRED_INCLUDES ${Qt5Core_INCLUDE_DIRS})
+  set(CMAKE_REQUIRED_FLAGS)
+  #message(STATUS "Qt5Core_INCLUDE_DIRS = ${Qt5Core_INCLUDE_DIRS}")
+  check_cxx_source_runs(
+    "
+    #include <QtCore/qconfig.h>
+    #include <string>
+    using namespace std;
+    string a(QT_QPA_DEFAULT_PLATFORM_NAME);
+    int main(int argc, char **argv)
+    {
+      if (a.compare(\"xcb\") == 0)
+       return(0);
+      else
+       return 1;
+    }
+    "
+    QT_USES_X11)
+  set(QPA_XCB ${QT_USES_X11})
+
   if (Qt5X11Extras_FOUND)
     get_target_property(_x11extra_prop Qt5::X11Extras IMPORTED_CONFIGURATIONS)
     get_target_property(_x11extra_link_libraries Qt5::X11Extras IMPORTED_LOCATION_${_x11extra_prop})
@@ -215,7 +239,8 @@ if(LYX_USE_QT MATCHES "QT5")
               bool isX11 = QX11Info::isPlatformX11();
             }
             "
-    QT_USES_X11)
+      QT_HAS_X11_EXTRAS)
+    set(HAVE_QT5_X11_EXTRAS ${QT_HAS_X11_EXTRAS})
   endif()
   if (Qt5WinExtras_FOUND)
     get_target_property(_winextra_prop Qt5::WinExtras IMPORTED_CONFIGURATIONS)
index 65862079a3afb329cc77ee816dc65be007b18817..ef945c9e8c6b091da84e2044973a409e7bb4d339 100644 (file)
 #ifdef Q_WS_X11
 #include <X11/Xatom.h>
 #include <X11/Xlib.h>
+#include <QX11Info>
 #undef CursorShape
 #undef None
 #elif defined(QPA_XCB)
 #include <xcb/xcb.h>
+#ifdef HAVE_QT5_X11_EXTRAS
+#include <QtX11Extras/QX11Info>
+#endif
 #endif
 
 #if (QT_VERSION < 0x050000) || (QT_VERSION >= 0x050400)
@@ -3130,8 +3134,26 @@ bool GuiApplication::x11EventFilter(XEvent * xev)
                BufferView * bv = current_view_->currentBufferView();
                if (bv) {
                        docstring const sel = bv->requestSelection();
-                       if (!sel.empty())
+                       if (!sel.empty()) {
                                d->selection_.put(sel);
+                               // Refresh the selection request timestamp.
+                               // We have to do this by ourselves as Qt seems
+                               // not doing that, maybe because of our
+                               // "persistent selection" implementation
+                               // (see comments in GuiSelection.cpp).
+                               XSelectionEvent nev;
+                               nev.type = SelectionNotify;
+                               nev.display = xev->xselectionrequest.display;
+                               nev.requestor = xev->xselectionrequest.requestor;
+                               nev.selection = xev->xselectionrequest.selection;
+                               nev.target = xev->xselectionrequest.target;
+                               nev.property = 0L; // None
+                               nev.time = CurrentTime;
+                               XSendEvent(QX11Info::display(),
+                                       nev.requestor, False, 0,
+                                       reinterpret_cast<XEvent *>(&nev));
+                               return true;
+                       }
                }
                break;
        }
@@ -3166,8 +3188,29 @@ bool GuiApplication::nativeEventFilter(const QByteArray & eventType,
                BufferView * bv = current_view_->currentBufferView();
                if (bv) {
                        docstring const sel = bv->requestSelection();
-                       if (!sel.empty())
+                       if (!sel.empty()) {
                                d->selection_.put(sel);
+#ifdef HAVE_QT5_X11_EXTRAS
+                               // Refresh the selection request timestamp.
+                               // We have to do this by ourselves as Qt seems
+                               // not doing that, maybe because of our
+                               // "persistent selection" implementation
+                               // (see comments in GuiSelection.cpp).
+                               xcb_selection_notify_event_t nev;
+                               nev.response_type = XCB_SELECTION_NOTIFY;
+                               nev.requestor = srev->requestor;
+                               nev.selection = srev->selection;
+                               nev.target = srev->target;
+                               nev.property = XCB_NONE;
+                               nev.time = XCB_CURRENT_TIME;
+                               xcb_connection_t * con = QX11Info::connection();
+                               xcb_send_event(con, 0, srev->requestor,
+                                       XCB_EVENT_MASK_NO_EVENT,
+                                       reinterpret_cast<char const *>(&nev));
+                               xcb_flush(con);
+#endif
+                               return true;
+                       }
                }
                break;
        }