[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [ksnapshot/frameworks] /: use XCB to convert native handles
From: Aaron Seigo <aseigo () kde ! org>
Date: 2014-09-15 8:16:03
Message-ID: E1XTRS7-0005kS-Dl () scm ! kde ! org
[Download RAW message or body]
Git commit fb5dde6604b0d82e69ce9912f7188383940609c7 by Aaron Seigo.
Committed on 15/09/2014 at 07:09.
Pushed by aseigo into branch 'frameworks'.
use XCB to convert native handles
adapted from patch by Martin Gräßlin
M +54 -17 CMakeLists.txt
A +31 -0 cmake/modules/FindX11_XCB.cmake
A +238 -0 cmake/modules/FindXCB.cmake
M +10 -4 config-ksnapshot.h.cmake
M +23 -61 ksnapshot.cpp
M +0 -1 ksnapshot.h
A +178 -0 xcb/pixmaphelper.cpp [License: GPL (v2+)]
A +34 -0 xcb/pixmaphelper.h [License: GPL (v2+)]
A +209 -0 xcb/xcbutils.h [License: GPL (v2)]
http://commits.kde.org/ksnapshot/fb5dde6604b0d82e69ce9912f7188383940609c7
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b2f2dc7..69d6fc9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,7 +6,11 @@ set (QT_MIN_VERSION "5.2.0")
#macro_optional_find_package(Kipi)
find_package(ECM 1.1.0 REQUIRED NO_MODULE)
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
+
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules
+ ${CMAKE_MODULE_PATH}
+ ${ECM_MODULE_PATH}
+ ${ECM_KDE_MODULE_DIR})
include(KDEInstallDirs)
include(KDECMakeSettings)
@@ -34,21 +38,22 @@ add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)
find_package(X11)
if (X11_FOUND)
set(HAVE_X11 1)
+endif(X11_FOUND)
- if (X11_Xshape_FOUND)
- set(HAVE_X11_EXTENSIONS_SHAPE_H 1)
- endif (X11_Xshape_FOUND)
+find_package(XCB MODULE COMPONENTS XCB SHAPE XFIXES)
+set_package_properties(XCB PROPERTIES DESCRIPTION "X protocol C-language Binding"
+ URL "http://xcb.freedesktop.org"
+ TYPE OPTIONAL)
+find_package(X11_XCB MODULE)
+set_package_properties(X11_XCB PROPERTIES DESCRIPTION "Xlib/XCB interface library"
+ URL "http://xcb.freedesktop.org"
+ TYPE OPTIONAL)
- if (X11_Xfixes_FOUND)
- set(HAVE_X11_EXTENSIONS_XFIXES_H 1)
- endif (X11_Xfixes_FOUND)
-endif (X11_FOUND)
-#feature_summary(WHAT ENABLED_FEATURES DESCRIPTION "X11 Fixes Extension (xfixes.h)" "Support for \
capturing the cursor" "http://www.x.org/" VAR HAVE_X11_EXTENSIONS_XFIXES_H) \
+#include_directories(${CMAKE_CURRENT_SOURCE_DIR})
if (KIPI_FOUND)
- include_directories(${KIPI_INCLUDE_DIR})
+ include_directories(${KIPI_INCLUDE_DIR})
endif (KIPI_FOUND)
-#macro_log_feature(KIPI_FOUND "KIPI plugins" "Provides various image export features, such as printing, \
emailing and uploading" "http://www.kipi-plugins.org/" FALSE "" "")
configure_file(config-ksnapshot.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-ksnapshot.h)
@@ -65,6 +70,12 @@ set(ksnapshot_file_SRCS
ksnapshotobject.cpp
ksnapshotpreview.cpp)
+if (XCB_XCB_FOUND AND X11_XCB_FOUND)
+ set(ksnapshot_xcb_SRCS
+ # windowgrabber_x11.cpp
+ xcb/pixmaphelper.cpp)
+endif (XCB_XCB_FOUND AND X11_XCB_FOUND)
+
if (KIPI_FOUND)
set(ksnapshot_kipi_SRCS
kipiinterface.cpp
@@ -76,6 +87,7 @@ endif (KIPI_FOUND)
set(ksnapshot_SRCS
main.cpp
ksnapshot.cpp
+ ${ksnapshot_xcb_SRCS}
${ksnapshot_file_SRCS}
${ksnapshot_kipi_SRCS})
@@ -100,11 +112,21 @@ target_link_libraries(ksnapshot
KF5::KIOWidgets
KF5::WindowSystem
KF5::XmlGui
- ${X11_LIBRARIES})
-
-if (X11_Xfixes_FOUND)
- target_link_libraries(ksnapshot ${X11_Xfixes_LIB})
-endif (X11_Xfixes_FOUND)
+ ${X11_LIBRARIES}
+ )
+
+if (X11_XCB_FOUND)
+ target_link_libraries(ksnapshot ${X11_XCB_LIBRARIES})
+endif ()
+if (XCB_XCB_FOUND)
+ target_link_libraries(ksnapshot ${XCB_XCB_LIBRARY})
+endif ()
+if (XCB_SHAPE_FOUND)
+ target_link_libraries(ksnapshot ${XCB_SHAPE_LIBRARY})
+endif ()
+if (XCB_XFIXES_FOUND)
+ target_link_libraries(ksnapshot ${XCB_XFIXES_LIBRARY})
+endif ()
if (KIPI_FOUND)
target_link_libraries(ksnapshot ${KIPI_LIBRARIES})
@@ -129,7 +151,22 @@ target_link_libraries(kbackgroundsnapshot
KF5::I18n
KF5::KIOWidgets
KF5::WindowSystem
- ${X11_LIBRARIES})
+ ${X11_LIBRARIES}
+ )
+
+target_link_libraries(kbackgroundsnapshot ${KDE4_KIO_LIBS})
+
+if (X11_XCB_FOUND)
+ target_link_libraries(kbackgroundsnapshot ${X11_XCB_LIBRARIES})
+endif ()
+
+if (XCB_XCB_FOUND)
+ target_link_libraries(kbackgroundsnapshot ${XCB_XCB_LIBRARY})
+endif ()
+
+if (XCB_SHAPE_FOUND)
+ target_link_libraries(kbackgroundsnapshot ${XCB_SHAPE_LIBRARY})
+endif ()
install(TARGETS kbackgroundsnapshot ${INSTALL_TARGETS_DEFAULT_ARGS})
diff --git a/cmake/modules/FindX11_XCB.cmake b/cmake/modules/FindX11_XCB.cmake
new file mode 100644
index 0000000..e2c18a9
--- /dev/null
+++ b/cmake/modules/FindX11_XCB.cmake
@@ -0,0 +1,31 @@
+# - Try to find libX11-xcb
+# Once done this will define
+#
+# X11_XCB_FOUND - system has libX11-xcb
+# X11_XCB_LIBRARIES - Link these to use libX11-xcb
+# X11_XCB_INCLUDE_DIR - the libX11-xcb include dir
+# X11_XCB_DEFINITIONS - compiler switches required for using libX11-xcb
+
+# Copyright (c) 2011 Fredrik Höglund <fredrik@kde.org>
+# Copyright (c) 2008 Helio Chissini de Castro, <helio@kde.org>
+# Copyright (c) 2007 Matthias Kretz, <kretz@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+IF (NOT WIN32)
+ # use pkg-config to get the directories and then use these values
+ # in the FIND_PATH() and FIND_LIBRARY() calls
+ FIND_PACKAGE(PkgConfig)
+ PKG_CHECK_MODULES(PKG_X11_XCB QUIET x11-xcb)
+
+ SET(X11_XCB_DEFINITIONS ${PKG_X11_XCB_CFLAGS})
+
+ FIND_PATH(X11_XCB_INCLUDE_DIR NAMES X11/Xlib-xcb.h HINTS ${PKG_X11_XCB_INCLUDE_DIRS})
+ FIND_LIBRARY(X11_XCB_LIBRARIES NAMES X11-xcb HINTS ${PKG_X11_XCB_LIBRARY_DIRS})
+
+ include(FindPackageHandleStandardArgs)
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(X11_XCB DEFAULT_MSG X11_XCB_LIBRARIES X11_XCB_INCLUDE_DIR)
+
+ MARK_AS_ADVANCED(X11_XCB_INCLUDE_DIR X11_XCB_LIBRARIES)
+ENDIF (NOT WIN32)
diff --git a/cmake/modules/FindXCB.cmake b/cmake/modules/FindXCB.cmake
new file mode 100644
index 0000000..823d167
--- /dev/null
+++ b/cmake/modules/FindXCB.cmake
@@ -0,0 +1,238 @@
+# Try to find XCB on a Unix system
+#
+# This will define:
+#
+# XCB_FOUND - True if xcb is available
+# XCB_LIBRARIES - Link these to use xcb
+# XCB_INCLUDE_DIRS - Include directory for xcb
+# XCB_DEFINITIONS - Compiler flags for using xcb
+#
+# In addition the following more fine grained variables will be defined:
+#
+# XCB_XCB_FOUND XCB_XCB_INCLUDE_DIR XCB_XCB_LIBRARY
+# XCB_UTIL_FOUND XCB_UTIL_INCLUDE_DIR XCB_UTIL_LIBRARY
+# XCB_COMPOSITE_FOUND XCB_COMPOSITE_INCLUDE_DIR XCB_COMPOSITE_LIBRARY
+# XCB_DAMAGE_FOUND XCB_DAMAGE_INCLUDE_DIR XCB_DAMAGE_LIBRARY
+# XCB_XFIXES_FOUND XCB_XFIXES_INCLUDE_DIR XCB_XFIXES_LIBRARY
+# XCB_RENDER_FOUND XCB_RENDER_INCLUDE_DIR XCB_RENDER_LIBRARY
+# XCB_RANDR_FOUND XCB_RANDR_INCLUDE_DIR XCB_RANDR_LIBRARY
+# XCB_SHAPE_FOUND XCB_SHAPE_INCLUDE_DIR XCB_SHAPE_LIBRARY
+# XCB_DRI2_FOUND XCB_DRI2_INCLUDE_DIR XCB_DRI2_LIBRARY
+# XCB_GLX_FOUND XCB_GLX_INCLUDE_DIR XCB_GLX_LIBRARY
+# XCB_SHM_FOUND XCB_SHM_INCLUDE_DIR XCB_SHM_LIBRARY
+# XCB_XV_FOUND XCB_XV_INCLUDE_DIR XCB_XV_LIBRARY
+# XCB_SYNC_FOUND XCB_SYNC_INCLUDE_DIR XCB_SYNC_LIBRARY
+# XCB_XTEST_FOUND XCB_XTEST_INCLUDE_DIR XCB_XTEST_LIBRARY
+# XCB_ICCCM_FOUND XCB_ICCCM_INCLUDE_DIR XCB_ICCCM_LIBRARY
+# XCB_EWMH_FOUND XCB_EWMH_INCLUDE_DIR XCB_EWMH_LIBRARY
+# XCB_IMAGE_FOUND XCB_IMAGE_INCLUDE_DIR XCB_IMAGE_LIBRARY
+# XCB_RENDERUTIL_FOUND XCB_RENDERUTIL_INCLUDE_DIR XCB_RENDERUTIL_LIBRARY
+# XCB_KEYSYMS_FOUND XCB_KEYSYMS_INCLUDE_DIR XCB_KEYSYMS_LIBRARY
+#
+# Copyright (c) 2011 Fredrik Höglund <fredrik@kde.org>
+# Copyright (c) 2013 Martin Gräßlin <mgraesslin@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+set(knownComponents XCB
+ COMPOSITE
+ DAMAGE
+ DRI2
+ EWMH
+ GLX
+ ICCCM
+ IMAGE
+ KEYSYMS
+ RANDR
+ RENDER
+ RENDERUTIL
+ SHAPE
+ SHM
+ SYNC
+ UTIL
+ XFIXES
+ XTEST
+ XV)
+
+unset(unknownComponents)
+
+set(pkgConfigModules)
+set(requiredComponents)
+
+if (XCB_FIND_COMPONENTS)
+ set(comps ${XCB_FIND_COMPONENTS})
+else()
+ set(comps ${knownComponents})
+endif()
+
+# iterate through the list of requested components, and check that we know them all.
+# If not, fail.
+foreach(comp ${comps})
+ list(FIND knownComponents ${comp} index )
+ if("${index}" STREQUAL "-1")
+ list(APPEND unknownComponents "${comp}")
+ else()
+ if("${comp}" STREQUAL "XCB")
+ list(APPEND pkgConfigModules "xcb")
+ elseif("${comp}" STREQUAL "COMPOSITE")
+ list(APPEND pkgConfigModules "xcb-composite")
+ elseif("${comp}" STREQUAL "DAMAGE")
+ list(APPEND pkgConfigModules "xcb-damage")
+ elseif("${comp}" STREQUAL "DRI2")
+ list(APPEND pkgConfigModules "xcb-dri2")
+ elseif("${comp}" STREQUAL "EWMH")
+ list(APPEND pkgConfigModules "xcb-ewmh")
+ elseif("${comp}" STREQUAL "GLX")
+ list(APPEND pkgConfigModules "xcb-glx")
+ elseif("${comp}" STREQUAL "ICCCM")
+ list(APPEND pkgConfigModules "xcb-icccm")
+ elseif("${comp}" STREQUAL "IMAGE")
+ list(APPEND pkgConfigModules "xcb-image")
+ elseif("${comp}" STREQUAL "KEYSYMS")
+ list(APPEND pkgConfigModules "xcb-keysyms")
+ elseif("${comp}" STREQUAL "RANDR")
+ list(APPEND pkgConfigModules "xcb-randr")
+ elseif("${comp}" STREQUAL "RENDER")
+ list(APPEND pkgConfigModules "xcb-render")
+ elseif("${comp}" STREQUAL "RENDERUTIL")
+ list(APPEND pkgConfigModules "xcb-renderutil")
+ elseif("${comp}" STREQUAL "SHAPE")
+ list(APPEND pkgConfigModules "xcb-shape")
+ elseif("${comp}" STREQUAL "SHM")
+ list(APPEND pkgConfigModules "xcb-shm")
+ elseif("${comp}" STREQUAL "SYNC")
+ list(APPEND pkgConfigModules "xcb-sync")
+ elseif("${comp}" STREQUAL "UTIL")
+ list(APPEND pkgConfigModules "xcb-util")
+ elseif("${comp}" STREQUAL "XFIXES")
+ list(APPEND pkgConfigModules "xcb-xfixes")
+ elseif("${comp}" STREQUAL "XTEST")
+ list(APPEND pkgConfigModules "xcb-xtest")
+ elseif("${comp}" STREQUAL "XV")
+ list(APPEND pkgConfigModules "xcb-xv")
+ endif()
+ endif()
+endforeach()
+
+
+if(DEFINED unknownComponents)
+ set(msgType STATUS)
+ if(XCB_FIND_REQUIRED)
+ set(msgType FATAL_ERROR)
+ endif()
+ if(NOT XCB_FIND_QUIETLY)
+ message(${msgType} "XCB: requested unknown components ${unknownComponents}")
+ endif()
+ return()
+endif()
+
+macro(_XCB_HANDLE_COMPONENT _comp)
+ set(_header )
+ set(_lib )
+ if("${_comp}" STREQUAL "XCB")
+ set(_header "xcb/xcb.h")
+ set(_lib "xcb")
+ elseif("${_comp}" STREQUAL "COMPOSITE")
+ set(_header "xcb/composite.h")
+ set(_lib "xcb-composite")
+ elseif("${_comp}" STREQUAL "DAMAGE")
+ set(_header "xcb/damage.h")
+ set(_lib "xcb-damage")
+ elseif("${_comp}" STREQUAL "DRI2")
+ set(_header "xcb/dri2.h")
+ set(_lib "xcb-dri2")
+ elseif("${_comp}" STREQUAL "EWMH")
+ set(_header "xcb/xcb_ewmh.h")
+ set(_lib "xcb-ewmh")
+ elseif("${_comp}" STREQUAL "GLX")
+ set(_header "xcb/glx.h")
+ set(_lib "xcb-glx")
+ elseif("${_comp}" STREQUAL "ICCCM")
+ set(_header "xcb/xcb_icccm.h")
+ set(_lib "xcb-icccm")
+ elseif("${_comp}" STREQUAL "IMAGE")
+ set(_header "xcb/xcb_image.h")
+ set(_lib "xcb-image")
+ elseif("${_comp}" STREQUAL "KEYSYMS")
+ set(_header "xcb/xcb_keysyms.h")
+ set(_lib "xcb-keysyms")
+ elseif("${_comp}" STREQUAL "RANDR")
+ set(_header "xcb/randr.h")
+ set(_lib "xcb-randr")
+ elseif("${_comp}" STREQUAL "RENDER")
+ set(_header "xcb/render.h")
+ set(_lib "xcb-render")
+ elseif("${_comp}" STREQUAL "RENDERUTIL")
+ set(_header "xcb/xcb_renderutil.h")
+ set(_lib "xcb-render-util")
+ elseif("${_comp}" STREQUAL "SHAPE")
+ set(_header "xcb/shape.h")
+ set(_lib "xcb-shape")
+ elseif("${_comp}" STREQUAL "SHM")
+ set(_header "xcb/shm.h")
+ set(_lib "xcb-shm")
+ elseif("${_comp}" STREQUAL "SYNC")
+ set(_header "xcb/sync.h")
+ set(_lib "xcb-sync")
+ elseif("${_comp}" STREQUAL "UTIL")
+ set(_header "xcb/xcb_util.h")
+ set(_lib "xcb-util")
+ elseif("${_comp}" STREQUAL "XFIXES")
+ set(_header "xcb/xfixes.h")
+ set(_lib "xcb-xfixes")
+ elseif("${_comp}" STREQUAL "XTEST")
+ set(_header "xcb/xtest.h")
+ set(_lib "xcb-xtest")
+ elseif("${_comp}" STREQUAL "XV")
+ set(_header "xcb/xv.h")
+ set(_lib "xcb-xv")
+ endif()
+
+ find_path(XCB_${_comp}_INCLUDE_DIR NAMES ${_header} HINTS ${PKG_XCB_INCLUDE_DIRS})
+ find_library(XCB_${_comp}_LIBRARY NAMES ${_lib} HINTS ${PKG_XCB_LIBRARY_DIRS})
+
+ if(XCB_${_comp}_INCLUDE_DIR AND XCB_${_comp}_LIBRARY)
+ list(APPEND XCB_INCLUDE_DIRS ${XCB_${_comp}_INCLUDE_DIR})
+ list(APPEND XCB_LIBRARIES ${XCB_${_comp}_LIBRARY})
+ if (NOT XCB_FIND_QUIETLY)
+ message(STATUS "XCB[${_comp}]: Found component ${_comp}")
+ endif()
+ endif()
+
+ if(XCB_FIND_REQUIRED_${_comp})
+ list(APPEND requiredComponents XCB_${_comp}_FOUND)
+ endif()
+
+ find_package_handle_standard_args(XCB_${_comp} DEFAULT_MSG XCB_${_comp}_LIBRARY \
XCB_${_comp}_INCLUDE_DIR) +
+ mark_as_advanced(XCB_${_comp}_LIBRARY XCB_${_comp}_INCLUDE_DIR)
+
+ # compatibility for old variable naming
+ set(XCB_${_comp}_INCLUDE_DIRS ${XCB_${_comp}_INCLUDE_DIR})
+ set(XCB_${_comp}_LIBRARIES ${XCB_${_comp}_LIBRARY})
+endmacro()
+
+IF (NOT WIN32)
+ include(FindPackageHandleStandardArgs)
+ # Use pkg-config to get the directories and then use these values
+ # in the FIND_PATH() and FIND_LIBRARY() calls
+ find_package(PkgConfig)
+ pkg_check_modules(PKG_XCB QUIET ${pkgConfigModules})
+
+ set(XCB_DEFINITIONS ${PKG_XCB_CFLAGS})
+
+ foreach(comp ${comps})
+ _xcb_handle_component(${comp})
+ endforeach()
+
+ if(XCB_INCLUDE_DIRS)
+ list(REMOVE_DUPLICATES XCB_INCLUDE_DIRS)
+ endif()
+
+ find_package_handle_standard_args(XCB DEFAULT_MSG XCB_LIBRARIES XCB_INCLUDE_DIRS \
${requiredComponents}) +
+ # compatibility for old variable naming
+ set(XCB_INCLUDE_DIR ${XCB_INCLUDE_DIRS})
+
+ENDIF (NOT WIN32)
diff --git a/config-ksnapshot.h.cmake b/config-ksnapshot.h.cmake
index a70b068..3514dd5 100644
--- a/config-ksnapshot.h.cmake
+++ b/config-ksnapshot.h.cmake
@@ -1,11 +1,17 @@
/* Define to 1 if we are building with X11 */
#cmakedefine01 HAVE_X11
-/* Define to 1 if you have the <X11/extensions/shape.h> header file. */
-#cmakedefine01 HAVE_X11_EXTENSIONS_SHAPE_H
+/* Define to 1 if you have xcb */
+#cmakedefine XCB_XCB_FOUND 1
-/* Define to 1 if you have the <X11/extensions/Xfixes.h> header file. */
-#cmakedefine01 HAVE_X11_EXTENSIONS_XFIXES_H
+/* Define to 1 if you have x11-xcb */
+#cmakedefine X11_XCB_FOUND 1
+
+/* Define to 1 if you have xfixes */
+#cmakedefine XCB_XFIXES_FOUND 1
+
+/* Define to 1 if you have shape */
+#cmakedefine XCB_SHAPE_FOUND 1
/* Define to 1 if you have libkipi */
#cmakedefine KIPI_FOUND
diff --git a/ksnapshot.cpp b/ksnapshot.cpp
index fd9a2ad..2bc458e 100644
--- a/ksnapshot.cpp
+++ b/ksnapshot.cpp
@@ -84,12 +84,16 @@
#include <KAction>
#endif
-#if HAVE_X11_EXTENSIONS_XFIXES_H
-#include <X11/extensions/Xfixes.h>
+#if HAVE_X11
#include <X11/Xatom.h>
+#include <X11/Xlib.h>
#include <QX11Info>
#endif
+#if XCB_XCB_FOUND
+#include <xcb/pixmaphelper.h>
+#endif
+
class KSnapshotWidget : public QWidget, public Ui::KSnapshotWidget
{
public:
@@ -105,8 +109,7 @@ KSnapshot::KSnapshot(QWidget *parent, KSnapshotObject::CaptureMode mode)
: QDialog(parent),
KSnapshotObject(),
m_modified(true),
- m_savedPosition(QPoint(-1, -1)),
- m_haveXFixes(false)
+ m_savedPosition(QPoint(-1, -1))
{
// TEMPORARY Make sure "untitled" enters the string freeze for 4.6,
// as explained in http://lists.kde.org/?l=kde-graphics-devel&m=128942871430175&w=2
@@ -197,32 +200,19 @@ KSnapshot::KSnapshot(QWidget *parent, KSnapshotObject::CaptureMode mode)
KConfigGroup conf(KSharedConfig::openConfig(), "GENERAL");
#ifdef KIPI_FOUND
-#if(KIPI_VERSION >= 0x020000)
- m_pluginLoader = new KIPI::PluginLoader();
- m_pluginLoader->setInterface(new KIPIInterface(this));
- m_pluginLoader->init();
-#else
- m_pluginLoader = new KIPI::PluginLoader(QStringList(), new KIPIInterface(this), "");
-#endif
+ #if(KIPI_VERSION >= 0x020000)
+ m_pluginLoader = new KIPI::PluginLoader();
+ m_pluginLoader->setInterface(new KIPIInterface(this));
+ m_pluginLoader->init();
+ #else
+ m_pluginLoader = new KIPI::PluginLoader(QStringList(), new KIPIInterface(this), "");
+ #endif
#endif
-#if HAVE_X11_EXTENSIONS_XFIXES_H
+#if HAVE_X11
{
- int tmp1, tmp2;
- //Check whether the XFixes extension is available
+ // prevent KWin from animating the window in the compositor
Display *dpy = QX11Info::display();
- if (!XFixesQueryExtension(dpy, &tmp1, &tmp2)) {
- m_snapshotWidget->cbIncludePointer->hide();
- m_snapshotWidget->lblIncludePointer->hide();
- } else {
- m_haveXFixes = true;
- }
-
- // actually not depending on XFixes, but to simplify the ifdefs put here
- // we can safely assume that XFixes is present for this functionality
- // it's supposed to prevent that KWin animates the window in the compositor
- // and XFixes is a requirement for the compositor. So if XFixes is not present
- // KWin cannot be compiled at all.
Atom atom = XInternAtom(dpy, "_KDE_NET_WM_SKIP_CLOSE_ANIMATION", False);
long d = 1;
XChangeProperty(dpy, winId(), atom, XA_CARDINAL, 32,
@@ -620,13 +610,8 @@ void KSnapshot::slotWindowGrabbed(const QPixmap &pix)
void KSnapshot::slotScreenshotReceived(qulonglong handle)
{
-#if HAVE_X11
- //FIXME: there is no fromX11Pixmap anymore and nothing there to replace it
- // may have to write our own thing? want to look around a bit more
- // to see if anyone has beaten us to that. i mean, screen shotting
- // is *not* an uncommon task. Since this comes from kwin, perhaps
- // discuss with kwin developers.
- //slotWindowGrabbed( QPixmap::fromX11Pixmap( handle ) );
+#if XCB_XCB_FOUND
+ slotWindowGrabbed(PixmapHelperXCB::grabWindow(handle));
#else
Q_UNUSED(handle)
#endif
@@ -803,39 +788,16 @@ void KSnapshot::performGrab()
show();
}
-// Uses the X11_EXTENSIONS_XFIXES_H extension to grab the pointer image, and overlays it onto the \
snapshot. +// Grabs the pointer image if there is platform support for it, and overlays it onto the \
snapshot. void KSnapshot::grabPointerImage(int offsetx, int offsety)
{
-#if HAVE_X11_EXTENSIONS_XFIXES_H
- if (!m_haveXFixes || !includePointer()) {
- return;
- }
-
- XFixesCursorImage *xcursorimg = XFixesGetCursorImage(QX11Info::display());
- if (!xcursorimg) {
- return;
- }
-
- //Annoyingly, xfixes specifies the data to be 32bit, but places it in an unsigned long *
- //which can be 64 bit. So we need to iterate over a 64bit structure to put it in a 32bit
- //structure.
- QVarLengthArray< quint32 > pixels(xcursorimg->width * xcursorimg->height);
- for (int i = 0; i < xcursorimg->width * xcursorimg->height; ++i) {
- pixels[i] = xcursorimg->pixels[i] & 0xffffffff;
- }
-
- QImage qcursorimg((uchar *) pixels.data(), xcursorimg->width, xcursorimg->height,
- QImage::Format_ARGB32_Premultiplied);
-
- QPainter painter(&m_snapshot);
- painter.drawImage(QPointF(xcursorimg->x - xcursorimg->xhot - offsetx, xcursorimg->y - xcursorimg \
->yhot - offsety), qcursorimg);
-
- XFree(xcursorimg);
-#else // HAVE_X11_EXTENSIONS_XFIXES_H
+#if XCB_XFIXES_FOUND
+ PixmapHelperXCB::compositePointer(offsetx, offsety, m_snapshot);
+#else
Q_UNUSED(offsetx);
Q_UNUSED(offsety);
return;
-#endif // HAVE_X11_EXTENSIONS_XFIXES_H
+#endif
}
void KSnapshot::setTime(int newTime)
diff --git a/ksnapshot.h b/ksnapshot.h
index 3c71ce9..51836bc 100644
--- a/ksnapshot.h
+++ b/ksnapshot.h
@@ -142,7 +142,6 @@ private:
KSnapshotWidget *m_snapshotWidget;
bool m_modified;
QPoint m_savedPosition;
- bool m_haveXFixes;
bool m_includeAlpha;
QPolygon m_lastFreeRegion;
QRect m_lastRegion;
diff --git a/xcb/pixmaphelper.cpp b/xcb/pixmaphelper.cpp
new file mode 100644
index 0000000..4060e98
--- /dev/null
+++ b/xcb/pixmaphelper.cpp
@@ -0,0 +1,178 @@
+/*
+ Copyright (C) 2013 Martin Gräßlin <mgraesslin@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or ( at your option ) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this library; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "xcb/pixmaphelper.h"
+
+#include <stdint.h>
+
+#include <xcb/xfixes.h>
+
+#include <QPainter>
+
+#include "xcb/xcbutils.h"
+
+namespace PixmapHelperXCB
+{
+
+void compositePointer(int offsetx, int offsety, QPixmap &snapshot)
+{
+ Xcb::ScopedCPointer<xcb_xfixes_get_cursor_image_reply_t> cursor(
+ xcb_xfixes_get_cursor_image_reply(Xcb::connection(),
+ xcb_xfixes_get_cursor_image_unchecked(Xcb::connection()),
+ NULL));
+
+ if (cursor.isNull()) {
+ return;
+ }
+
+ QImage qcursorimg((uchar *) xcb_xfixes_get_cursor_image_cursor_image(cursor.data()),
+ cursor->width, cursor->height,
+ QImage::Format_ARGB32_Premultiplied);
+
+ QPainter painter(&snapshot);
+ painter.drawImage(QPointF(cursor->x - cursor->xhot - offsetx, cursor->y - cursor ->yhot - offsety), \
qcursorimg); +}
+
+QPixmap grabWindow(WId id, int x, int y, int width, int height)
+{
+ xcb_connection_t *c = Xcb::connection();
+ Xcb::WindowGeometry geo(id);
+ if (geo.isNull()) {
+ return QPixmap();
+ }
+ if (width < 0 || width > geo->width) {
+ width = geo->width;
+ }
+ if (width + x > geo->width) {
+ width = width + x - geo->width;
+ }
+ if (height < 0 || height > geo->height) {
+ height = geo->height;
+ }
+ if (height + y > geo->height) {
+ height = height + y - geo->height;
+ }
+ Xcb::ScopedCPointer<xcb_get_image_reply_t> xImage(xcb_get_image_reply(
+ c, xcb_get_image_unchecked(c, XCB_IMAGE_FORMAT_Z_PIXMAP, id, x, y, width, height, ~0), NULL));
+ if (xImage.isNull()) {
+ return QPixmap();
+ }
+ QImage::Format format = QImage::Format_ARGB32_Premultiplied;
+ switch (xImage->depth) {
+ case 1:
+ format = QImage::Format_MonoLSB;
+ break;
+ case 30: {
+ // Qt doesn't have a matching image format. We need to convert manually
+ uint32_t *pixels = reinterpret_cast<uint32_t *>(xcb_get_image_data(xImage.data()));
+ for (uint32_t i = 0; i < xImage.data()->length; ++i) {
+ int r = (pixels[i] >> 22) & 0xff;
+ int g = (pixels[i] >> 12) & 0xff;
+ int b = (pixels[i] >> 2) & 0xff;
+
+ pixels[i] = qRgba(r, g, b, 0xff);
+ }
+ QImage image(reinterpret_cast<uchar *>(pixels), geo->width, geo->height,
+ xcb_get_image_data_length(xImage.data()) / geo->height, \
QImage::Format_ARGB32_Premultiplied); + if (image.isNull()) {
+ return QPixmap();
+ }
+ return QPixmap::fromImage(image);
+ }
+ case 32:
+ format = QImage::Format_ARGB32_Premultiplied;
+ break;
+ default:
+ if (xImage->depth == defaultDepth()) {
+ format = findFormat();
+ if (format == QImage::Format_Invalid) {
+ return QPixmap();
+ }
+ } else {
+ // we don't know
+ return QPixmap();
+ }
+ }
+ QImage image(xcb_get_image_data(xImage.data()), width, height,
+ xcb_get_image_data_length(xImage.data()) / height, format);
+ if (image.isNull()) {
+ return QPixmap();
+ }
+ if (image.format() == QImage::Format_MonoLSB) {
+ // work around an abort in QImage::color
+ image.setColorCount(2);
+ image.setColor(0, QColor(Qt::white).rgb());
+ image.setColor(1, QColor(Qt::black).rgb());
+ }
+ return QPixmap::fromImage(image);
+}
+
+uint8_t defaultDepth()
+{
+ xcb_connection_t *c = Xcb::connection();
+ int screen = QX11Info::appScreen();
+
+ xcb_screen_iterator_t it = xcb_setup_roots_iterator(xcb_get_setup(c));
+ for (; it.rem; --screen, xcb_screen_next(&it)) {
+ if (screen == 0) {
+ return it.data->root_depth;
+ }
+ }
+ return 0;
+}
+
+QImage::Format findFormat()
+{
+ xcb_connection_t *c = Xcb::connection();
+ int screen = QX11Info::appScreen();
+
+ xcb_screen_iterator_t screenIt = xcb_setup_roots_iterator(xcb_get_setup(c));
+ for (; screenIt.rem; --screen, xcb_screen_next(&screenIt)) {
+ if (screen != 0) {
+ continue;
+ }
+ xcb_depth_iterator_t depthIt = xcb_screen_allowed_depths_iterator(screenIt.data);
+ for (; depthIt.rem; xcb_depth_next(&depthIt)) {
+ xcb_visualtype_iterator_t visualIt = xcb_depth_visuals_iterator(depthIt.data);
+ for (; visualIt.rem; xcb_visualtype_next(&visualIt)) {
+ if (screenIt.data->root_visual != visualIt.data->visual_id) {
+ continue;
+ }
+ xcb_visualtype_t *visual = visualIt.data;
+ if ((depthIt.data->depth == 24 || depthIt.data->depth == 32) &&
+ visual->red_mask == 0x00ff0000 &&
+ visual->green_mask == 0x0000ff00 &&
+ visual->blue_mask == 0x000000ff) {
+ return QImage::Format_ARGB32_Premultiplied;
+ }
+ if (depthIt.data->depth == 16 &&
+ visual->red_mask == 0xf800 &&
+ visual->green_mask == 0x07e0 &&
+ visual->blue_mask == 0x001f) {
+ return QImage::Format_RGB16;
+ }
+ break;
+ }
+ }
+ }
+ return QImage::Format_Invalid;
+}
+
+} // namespace PixmapHelperXCB
+
diff --git a/xcb/pixmaphelper.h b/xcb/pixmaphelper.h
new file mode 100644
index 0000000..9dfddff
--- /dev/null
+++ b/xcb/pixmaphelper.h
@@ -0,0 +1,34 @@
+/*
+ Copyright (C) 2013 Martin Gräßlin <mgraesslin@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or ( at your option ) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this library; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef PIXMAPHELPER_XCB_H
+#define PIXMAPHELPER_XCB_H
+
+#include <QPixmap>
+#include <QImage>
+
+namespace PixmapHelperXCB
+{
+ void compositePointer(int offsetX, int offsetY, QPixmap &snapshot);
+ QPixmap grabWindow(WId window, int x = 0, int y = 0, int width = -1, int height = -1);
+
+ uint8_t defaultDepth();
+ QImage::Format findFormat();
+};
+
+#endif
diff --git a/xcb/xcbutils.h b/xcb/xcbutils.h
new file mode 100644
index 0000000..b57b692
--- /dev/null
+++ b/xcb/xcbutils.h
@@ -0,0 +1,209 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2012, 2013 Martin Gräßlin <mgraesslin@kde.org>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*********************************************************************/
+#ifndef XCBUTILS_H
+#define XCBUTILS_H
+
+// Qt
+#include <QScopedPointer>
+#include <QRect>
+#include <QX11Info>
+
+// xcb
+#include <X11/Xlib-xcb.h>
+#include <fixx11h.h>
+#include <xcb/xcb.h>
+
+namespace Xcb
+{
+
+inline xcb_connection_t *connection()
+{
+ return XGetXCBConnection(QX11Info::display());
+}
+
+class ServerGrabber
+{
+public:
+ ServerGrabber() {
+ xcb_grab_server(connection());
+ }
+ ~ServerGrabber() {
+ xcb_ungrab_server(connection());
+ }
+};
+
+template <typename T>
+class ScopedCPointer : public QScopedPointer<T, QScopedPointerPodDeleter>
+{
+public:
+ ScopedCPointer(T *p = 0) : QScopedPointer<T, QScopedPointerPodDeleter>(p) {}
+};
+
+template <typename Reply,
+ typename Cookie,
+ Reply *(*replyFunc)(xcb_connection_t*, Cookie, xcb_generic_error_t**),
+ Cookie (*requestFunc)(xcb_connection_t*, xcb_window_t)>
+class Wrapper
+{
+public:
+ Wrapper()
+ : m_retrieved(false)
+ , m_window(XCB_WINDOW_NONE)
+ , m_reply(NULL)
+ {
+ m_cookie.sequence = 0;
+ }
+ explicit Wrapper(xcb_window_t window)
+ : m_retrieved(false)
+ , m_cookie(requestFunc(connection(), window))
+ , m_window(window)
+ , m_reply(NULL)
+ {
+ }
+ explicit Wrapper(const Wrapper &other)
+ : m_retrieved(other.m_retrieved)
+ , m_cookie(other.m_cookie)
+ , m_window(other.m_window)
+ , m_reply(NULL)
+ {
+ takeFromOther(const_cast<Wrapper&>(other));
+ }
+ virtual ~Wrapper() {
+ cleanup();
+ }
+ inline Wrapper &operator=(const Wrapper &other) {
+ if (this != &other) {
+ // if we had managed a reply, free it
+ cleanup();
+ // copy members
+ m_retrieved = other.m_retrieved;
+ m_cookie = other.m_cookie;
+ m_window = other.m_window;
+ m_reply = other.m_reply;
+ // take over the responsibility for the reply pointer
+ takeFromOther(const_cast<Wrapper&>(other));
+ }
+ return *this;
+ }
+
+ inline const Reply *operator->() {
+ getReply();
+ return m_reply;
+ }
+ inline bool isNull() {
+ getReply();
+ return m_reply == NULL;
+ }
+ inline operator bool() {
+ return !isNull();
+ }
+ inline const Reply *data() {
+ getReply();
+ return m_reply;
+ }
+ inline xcb_window_t window() const {
+ return m_window;
+ }
+ inline bool isRetrieved() const {
+ return m_retrieved;
+ }
+ /**
+ * Returns the value of the reply pointer referenced by this object. The reply pointer of
+ * this object will be reset to null. Calling any method which requires the reply to be valid
+ * will crash.
+ *
+ * Callers of this function take ownership of the pointer.
+ **/
+ inline Reply *take() {
+ getReply();
+ Reply *ret = m_reply;
+ m_reply = NULL;
+ m_window = XCB_WINDOW_NONE;
+ return ret;
+ }
+
+protected:
+ void getReply() {
+ if (m_retrieved || !m_cookie.sequence) {
+ return;
+ }
+ m_reply = replyFunc(connection(), m_cookie, NULL);
+ m_retrieved = true;
+ }
+
+private:
+ inline void cleanup() {
+ if (!m_retrieved && m_cookie.sequence) {
+ xcb_discard_reply(connection(), m_cookie.sequence);
+ } else if (m_reply) {
+ free(m_reply);
+ }
+ }
+ inline void takeFromOther(Wrapper &other) {
+ if (m_retrieved) {
+ m_reply = other.take();
+ } else {
+ //ensure that other object doesn't try to get the reply or discards it in the dtor
+ other.m_retrieved = true;
+ other.m_window = XCB_WINDOW_NONE;
+ }
+ }
+ bool m_retrieved;
+ Cookie m_cookie;
+ xcb_window_t m_window;
+ Reply *m_reply;
+};
+
+typedef Wrapper<xcb_get_window_attributes_reply_t, xcb_get_window_attributes_cookie_t, \
&xcb_get_window_attributes_reply, &xcb_get_window_attributes_unchecked> WindowAttributes; +
+
+class WindowGeometry : public Wrapper<xcb_get_geometry_reply_t, xcb_get_geometry_cookie_t, \
&xcb_get_geometry_reply, &xcb_get_geometry_unchecked> +{
+public:
+ WindowGeometry() : Wrapper<xcb_get_geometry_reply_t, xcb_get_geometry_cookie_t, \
&xcb_get_geometry_reply, &xcb_get_geometry_unchecked>() {} + explicit WindowGeometry(xcb_window_t \
window) : Wrapper<xcb_get_geometry_reply_t, xcb_get_geometry_cookie_t, &xcb_get_geometry_reply, \
&xcb_get_geometry_unchecked>(window) {} +
+ inline QRect rect() {
+ const xcb_get_geometry_reply_t *geometry = data();
+ if (!geometry) {
+ return QRect();
+ }
+ return QRect(geometry->x, geometry->y, geometry->width, geometry->height);
+ }
+};
+
+class Tree : public Wrapper<xcb_query_tree_reply_t, xcb_query_tree_cookie_t, &xcb_query_tree_reply, \
&xcb_query_tree_unchecked> +{
+public:
+ explicit Tree(xcb_window_t window) : Wrapper<xcb_query_tree_reply_t, xcb_query_tree_cookie_t, \
&xcb_query_tree_reply, &xcb_query_tree_unchecked>(window) {} +
+ inline xcb_window_t *children() {
+ return xcb_query_tree_children(data());
+ }
+ inline xcb_window_t parent() {
+ if (isNull())
+ return XCB_WINDOW_NONE;
+ return (*this)->parent;
+ }
+};
+
+} // namespace
+
+#endif
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic