diff --git a/backends/wayland/screens_wayland.cpp b/backends/wayland/screens_wayland.cpp index d0c70ddf9e..36c776cb15 100644 --- a/backends/wayland/screens_wayland.cpp +++ b/backends/wayland/screens_wayland.cpp @@ -23,12 +23,9 @@ along with this program. If not, see . #include #include "logging.h" #include "main.h" -#include "xcbutils.h" #include -#include - namespace KWin { @@ -103,159 +100,7 @@ void WaylandScreens::updateCount() return; } setCount(m_geometries.count()); - updateXRandr(); emit changed(); } -namespace RandR -{ -using namespace Xcb; -XCB_WRAPPER(CurrentResources, xcb_randr_get_screen_resources_current, xcb_window_t) -} - -static bool setNewScreenSize(const QSize &size) -{ - auto c = xcb_randr_set_screen_size_checked(connection(), rootWindow(), size.width(), size.height(), 1, 1); - ScopedCPointer error(xcb_request_check(connection(), c)); - if (!error.isNull()) { - qCDebug(KWIN_WAYLAND_BACKEND) << "Error setting screen size: " << error->error_code; - return false; - } - return true; -} - -static xcb_randr_crtc_t getCrtc(const xcb_randr_get_screen_resources_current_reply_t* r) -{ - if (xcb_randr_get_screen_resources_current_crtcs_length(r) == 0) { - qCDebug(KWIN_WAYLAND_BACKEND) << "No CRTCs"; - return XCB_NONE; - } - return xcb_randr_get_screen_resources_current_crtcs(r)[0]; -} - -static xcb_randr_output_t getOutputForCrtc(xcb_randr_crtc_t crtc) -{ - ScopedCPointer info(xcb_randr_get_crtc_info_reply( - connection(), xcb_randr_get_crtc_info(connection(), crtc, XCB_TIME_CURRENT_TIME), nullptr)); - if (info->num_outputs == 0) { - return XCB_NONE; - } - return xcb_randr_get_crtc_info_outputs(info.data())[0]; -} - -static xcb_randr_mode_t createNewMode(const QSize &size) -{ - // need to create the new mode - qCDebug(KWIN_WAYLAND_BACKEND) << "Creating a new mode"; - QString name(QString::number(size.width())); - name.append('x'); - name.append(QString::number(size.height())); - xcb_randr_mode_info_t newInfo; - newInfo.dot_clock = 0; - newInfo.height = size.height(); - newInfo.hskew = 0; - newInfo.hsync_end = 0; - newInfo.hsync_start = 0; - newInfo.htotal = size.width(); - newInfo.id = 0; - newInfo.mode_flags = 0; - newInfo.vsync_end = 0; - newInfo.vsync_start = 0; - newInfo.vtotal = size.height(); - newInfo.width = size.width(); - newInfo.name_len = name.length(); - auto cookie = xcb_randr_create_mode_unchecked(connection(), rootWindow(), newInfo, name.length(), name.toUtf8().constData()); - ScopedCPointer reply(xcb_randr_create_mode_reply(connection(), cookie, nullptr)); - if (!reply.isNull()) { - return reply->mode; - } - return XCB_NONE; -} - -static xcb_randr_mode_t getModeForSize(const QSize &size, const xcb_randr_get_screen_resources_current_reply_t* r) -{ - xcb_randr_mode_info_t *infos = xcb_randr_get_screen_resources_current_modes(r); - const int modeInfoLength = xcb_randr_get_screen_resources_current_modes_length(r); - // check available modes - for (int i = 0; i < modeInfoLength; ++i) { - xcb_randr_mode_info_t modeInfo = infos[i]; - if (modeInfo.width == size.width() && modeInfo.height == size.height()) { - qCDebug(KWIN_WAYLAND_BACKEND) << "Found our required mode"; - return modeInfo.id; - } - } - // did not find our mode, so create it - return createNewMode(size); -} - -static bool addModeToOutput(xcb_randr_output_t output, xcb_randr_mode_t mode) -{ - ScopedCPointer info(xcb_randr_get_output_info_reply(connection(), - xcb_randr_get_output_info(connection(), output, XCB_TIME_CURRENT_TIME), nullptr)); - xcb_randr_mode_t *modes = xcb_randr_get_output_info_modes(info.data()); - for (int i = 0; i < info->num_modes; ++i) { - if (modes[i] == mode) { - return true; - } - } - qCDebug(KWIN_WAYLAND_BACKEND) << "Need to add the mode to output"; - auto c = xcb_randr_add_output_mode_checked(connection(), output, mode); - ScopedCPointer error(xcb_request_check(connection(), c)); - if (!error.isNull()) { - qCDebug(KWIN_WAYLAND_BACKEND) << "Error while adding mode to output: " << error->error_code; - return false; - } - return true; -} - -void WaylandScreens::updateXRandr() -{ - if (kwinApp()->operationMode() == Application::OperationModeXwayland) { - // no need to update, will be done automagically by Xwayland - return; - } - if (!Xcb::Extensions::self()->isRandrAvailable()) { - qCDebug(KWIN_WAYLAND_BACKEND) << "No RandR extension available, cannot sync with X"; - return; - } - QRegion screens; - foreach (const QRect &rect, m_geometries) { - screens = screens.united(rect); - } - const QSize &size = screens.boundingRect().size(); - if (size.isEmpty()) { - return; - } - - RandR::CurrentResources currentResources(rootWindow()); - xcb_randr_crtc_t crtc = getCrtc(currentResources.data()); - if (crtc == XCB_NONE) { - return; - } - xcb_randr_output_t output = getOutputForCrtc(crtc); - if (output == XCB_NONE) { - return; - } - // first disable the first CRTC - xcb_randr_set_crtc_config(connection(), crtc, XCB_TIME_CURRENT_TIME, XCB_TIME_CURRENT_TIME, - 0, 0, XCB_NONE, XCB_RANDR_ROTATION_ROTATE_0, 0, nullptr); - - // then set new screen size - if (!setNewScreenSize(size)) { - return; - } - - xcb_randr_mode_t mode = getModeForSize(size, currentResources.data()); - if (mode == XCB_NONE) { - return; - } - - if (!addModeToOutput(output, mode)) { - return; - } - // enable CRTC again - xcb_randr_set_crtc_config(connection(), crtc, XCB_TIME_CURRENT_TIME, XCB_TIME_CURRENT_TIME, - 0, 0, mode, XCB_RANDR_ROTATION_ROTATE_0, 1, &output); -} - } diff --git a/backends/wayland/screens_wayland.h b/backends/wayland/screens_wayland.h index ae3c05bcd4..fbc2556b97 100644 --- a/backends/wayland/screens_wayland.h +++ b/backends/wayland/screens_wayland.h @@ -44,7 +44,6 @@ public: protected Q_SLOTS: void updateCount() override; private: - void updateXRandr(); Wayland::WaylandBackend *m_backend; QList m_geometries; };