x11: Drop support for multi-head

The main reason to drop multi-head support is that it has been simply
unmaintained for many many years. When implementing a feature, we don't
even bother checking if multi-head is broken, KCMs don't handle
multihead, window management features are written for Xinerama. KWin
is optimized for Xinerama-like operation mode in general, which is
provided out of the box.

If you use multihead for esoteric gpu stuff, consider using kwin_wayland!
This commit is contained in:
Vlad Zahorodnii 2022-07-18 17:31:38 +03:00
parent 80fb713787
commit 4dd9b0f15b
9 changed files with 16 additions and 151 deletions

View file

@ -207,16 +207,14 @@ bool X11StandalonePlatform::requiresCompositing() const
bool X11StandalonePlatform::openGLCompositingIsBroken() const bool X11StandalonePlatform::openGLCompositingIsBroken() const
{ {
const QString unsafeKey(QLatin1String("OpenGLIsUnsafe") + (kwinApp()->isX11MultiHead() ? QString::number(kwinApp()->x11ScreenNumber()) : QString())); return KConfigGroup(kwinApp()->config(), "Compositing").readEntry(QLatin1String("OpenGLIsUnsafe"), false);
return KConfigGroup(kwinApp()->config(), "Compositing").readEntry(unsafeKey, false);
} }
QString X11StandalonePlatform::compositingNotPossibleReason() const QString X11StandalonePlatform::compositingNotPossibleReason() const
{ {
// first off, check whether we figured that we'll crash on detection because of a buggy driver // first off, check whether we figured that we'll crash on detection because of a buggy driver
KConfigGroup gl_workaround_group(kwinApp()->config(), "Compositing"); KConfigGroup gl_workaround_group(kwinApp()->config(), "Compositing");
const QString unsafeKey(QLatin1String("OpenGLIsUnsafe") + (kwinApp()->isX11MultiHead() ? QString::number(kwinApp()->x11ScreenNumber()) : QString())); if (gl_workaround_group.readEntry("Backend", "OpenGL") == QLatin1String("OpenGL") && gl_workaround_group.readEntry(QLatin1String("OpenGLIsUnsafe"), false)) {
if (gl_workaround_group.readEntry("Backend", "OpenGL") == QLatin1String("OpenGL") && gl_workaround_group.readEntry(unsafeKey, false)) {
return i18n("<b>OpenGL compositing (the default) has crashed KWin in the past.</b><br>" return i18n("<b>OpenGL compositing (the default) has crashed KWin in the past.</b><br>"
"This was most likely due to a driver bug." "This was most likely due to a driver bug."
"<p>If you think that you have meanwhile upgraded to a stable driver,<br>" "<p>If you think that you have meanwhile upgraded to a stable driver,<br>"
@ -236,10 +234,9 @@ bool X11StandalonePlatform::compositingPossible() const
{ {
// first off, check whether we figured that we'll crash on detection because of a buggy driver // first off, check whether we figured that we'll crash on detection because of a buggy driver
KConfigGroup gl_workaround_group(kwinApp()->config(), "Compositing"); KConfigGroup gl_workaround_group(kwinApp()->config(), "Compositing");
const QString unsafeKey(QLatin1String("OpenGLIsUnsafe") + (kwinApp()->isX11MultiHead() ? QString::number(kwinApp()->x11ScreenNumber()) : QString())); if (gl_workaround_group.readEntry("Backend", "OpenGL") == QLatin1String("OpenGL") && gl_workaround_group.readEntry(QLatin1String("OpenGLIsUnsafe"), false)) {
if (gl_workaround_group.readEntry("Backend", "OpenGL") == QLatin1String("OpenGL") && gl_workaround_group.readEntry(unsafeKey, false)) {
qCWarning(KWIN_X11STANDALONE) << "Compositing disabled: video driver seems unstable. If you think it's a false positive, please remove " qCWarning(KWIN_X11STANDALONE) << "Compositing disabled: video driver seems unstable. If you think it's a false positive, please remove "
<< unsafeKey << " from [Compositing] in kwinrc and restart kwin."; << "OpenGLIsUnsafe from [Compositing] in kwinrc and restart kwin.";
return false; return false;
} }
@ -270,11 +267,10 @@ bool X11StandalonePlatform::hasGlx()
void X11StandalonePlatform::createOpenGLSafePoint(OpenGLSafePoint safePoint) void X11StandalonePlatform::createOpenGLSafePoint(OpenGLSafePoint safePoint)
{ {
const QString unsafeKey(QLatin1String("OpenGLIsUnsafe") + (kwinApp()->isX11MultiHead() ? QString::number(kwinApp()->x11ScreenNumber()) : QString()));
auto group = KConfigGroup(kwinApp()->config(), "Compositing"); auto group = KConfigGroup(kwinApp()->config(), "Compositing");
switch (safePoint) { switch (safePoint) {
case OpenGLSafePoint::PreInit: case OpenGLSafePoint::PreInit:
group.writeEntry(unsafeKey, true); group.writeEntry(QLatin1String("OpenGLIsUnsafe"), true);
group.sync(); group.sync();
// Deliberately continue with PreFrame // Deliberately continue with PreFrame
Q_FALLTHROUGH(); Q_FALLTHROUGH();
@ -293,9 +289,8 @@ void X11StandalonePlatform::createOpenGLSafePoint(OpenGLSafePoint safePoint)
connect( connect(
m_openGLFreezeProtection, &QTimer::timeout, m_openGLFreezeProtection, m_openGLFreezeProtection, &QTimer::timeout, m_openGLFreezeProtection,
[configName] { [configName] {
const QString unsafeKey(QLatin1String("OpenGLIsUnsafe") + (kwinApp()->isX11MultiHead() ? QString::number(kwinApp()->x11ScreenNumber()) : QString()));
auto group = KConfigGroup(KSharedConfig::openConfig(configName), "Compositing"); auto group = KConfigGroup(KSharedConfig::openConfig(configName), "Compositing");
group.writeEntry(unsafeKey, true); group.writeEntry(QLatin1String("OpenGLIsUnsafe"), true);
group.sync(); group.sync();
KCrash::setDrKonqiEnabled(false); KCrash::setDrKonqiEnabled(false);
qFatal("Freeze in OpenGL initialization detected"); qFatal("Freeze in OpenGL initialization detected");
@ -307,7 +302,7 @@ void X11StandalonePlatform::createOpenGLSafePoint(OpenGLSafePoint safePoint)
} }
break; break;
case OpenGLSafePoint::PostInit: case OpenGLSafePoint::PostInit:
group.writeEntry(unsafeKey, false); group.writeEntry(QLatin1String("OpenGLIsUnsafe"), false);
group.sync(); group.sync();
// Deliberately continue with PostFrame // Deliberately continue with PostFrame
Q_FALLTHROUGH(); Q_FALLTHROUGH();

View file

@ -70,11 +70,6 @@ Q_DECLARE_METATYPE(KWin::X11Compositor::SuspendReason)
namespace KWin namespace KWin
{ {
// See main.cpp:
extern int screen_number;
extern bool is_multihead;
Compositor *Compositor::s_compositor = nullptr; Compositor *Compositor::s_compositor = nullptr;
Compositor *Compositor::self() Compositor *Compositor::self()
{ {

View file

@ -46,10 +46,6 @@ DBusInterface::DBusInterface(QObject *parent)
QDBusConnection dbus = QDBusConnection::sessionBus(); QDBusConnection dbus = QDBusConnection::sessionBus();
dbus.registerObject(QStringLiteral("/KWin"), this); dbus.registerObject(QStringLiteral("/KWin"), this);
const QByteArray dBusSuffix = qgetenv("KWIN_DBUS_SERVICE_SUFFIX");
if (!dBusSuffix.isNull()) {
m_serviceName = m_serviceName + QLatin1Char('.') + dBusSuffix;
}
dbus.registerService(m_serviceName); dbus.registerService(m_serviceName);
dbus.connect(QString(), QStringLiteral("/KWin"), QStringLiteral("org.kde.KWin"), QStringLiteral("reloadConfig"), dbus.connect(QString(), QStringLiteral("/KWin"), QStringLiteral("org.kde.KWin"), QStringLiteral("reloadConfig"),
Workspace::self(), SLOT(slotReloadConfig())); Workspace::self(), SLOT(slotReloadConfig()));

View file

@ -64,20 +64,9 @@ Options *options;
Atoms *atoms; Atoms *atoms;
int screen_number = -1; int screen_number = -1;
bool is_multihead = false;
int Application::crashes = 0; int Application::crashes = 0;
bool Application::isX11MultiHead()
{
return is_multihead;
}
void Application::setX11MultiHead(bool multiHead)
{
is_multihead = multiHead;
}
void Application::setX11ScreenNumber(int screenNumber) void Application::setX11ScreenNumber(int screenNumber)
{ {
screen_number = screenNumber; screen_number = screenNumber;

View file

@ -157,14 +157,6 @@ public:
* Sets the X11 screen number of this KWin instance to @p screenNumber. * Sets the X11 screen number of this KWin instance to @p screenNumber.
*/ */
static void setX11ScreenNumber(int screenNumber); static void setX11ScreenNumber(int screenNumber);
/**
* @returns whether this is a multi head setup on X11.
*/
static bool isX11MultiHead();
/**
* Sets whether this is a multi head setup on X11.
*/
static void setX11MultiHead(bool multiHead);
/** /**
* @returns the X11 root window. * @returns the X11 root window.

View file

@ -355,64 +355,6 @@ int main(int argc, char *argv[])
KWin::Application::setupMalloc(); KWin::Application::setupMalloc();
KWin::Application::setupLocalizedString(); KWin::Application::setupLocalizedString();
int primaryScreen = 0;
xcb_connection_t *c = xcb_connect(nullptr, &primaryScreen);
if (!c || xcb_connection_has_error(c)) {
fprintf(stderr, "%s: FATAL ERROR while trying to open display %s\n",
argv[0], qgetenv("DISPLAY").constData());
exit(1);
}
const int number_of_screens = xcb_setup_roots_length(xcb_get_setup(c));
xcb_disconnect(c);
c = nullptr;
// multi head
auto isMultiHead = []() -> bool {
QByteArray multiHead = qgetenv("KDE_MULTIHEAD");
if (!multiHead.isEmpty()) {
return (multiHead.toLower() == "true");
}
return true;
};
if (number_of_screens != 1 && isMultiHead()) {
KWin::Application::setX11MultiHead(true);
KWin::Application::setX11ScreenNumber(primaryScreen);
int pos; // Temporarily needed to reconstruct DISPLAY var if multi-head
QByteArray display_name = qgetenv("DISPLAY");
if ((pos = display_name.lastIndexOf('.')) != -1) {
display_name.remove(pos, 10); // 10 is enough to be sure we removed ".s"
}
for (int i = 0; i < number_of_screens; i++) {
// If execution doesn't pass by here, then kwin
// acts exactly as previously
if (i != KWin::Application::x11ScreenNumber() && fork() == 0) {
KWin::Application::setX11ScreenNumber(i);
QByteArray dBusSuffix = qgetenv("KWIN_DBUS_SERVICE_SUFFIX");
if (!dBusSuffix.isNull()) {
dBusSuffix.append(".");
}
dBusSuffix.append(QByteArrayLiteral("head-")).append(QByteArray::number(i));
qputenv("KWIN_DBUS_SERVICE_SUFFIX", dBusSuffix);
// Break here because we are the child process, we don't
// want to fork() anymore
break;
}
}
// In the next statement, display_name shouldn't contain a screen
// number. If it had it, it was removed at the "pos" check
const QString envir = QStringLiteral("DISPLAY=%1.%2")
.arg(display_name.data())
.arg(KWin::Application::x11ScreenNumber());
if (putenv(strdup(envir.toLatin1().constData()))) {
fprintf(stderr, "%s: WARNING: unable to set DISPLAY environment variable\n", argv[0]);
perror("putenv()");
}
}
if (signal(SIGTERM, KWin::sighandler) == SIG_IGN) { if (signal(SIGTERM, KWin::sighandler) == SIG_IGN) {
signal(SIGTERM, SIG_IGN); signal(SIGTERM, SIG_IGN);
} }

View file

@ -1036,7 +1036,7 @@ static bool areModKeysDepressed(const QKeySequence &seq)
void TabBox::navigatingThroughWindows(bool forward, const QKeySequence &shortcut, TabBoxMode mode) void TabBox::navigatingThroughWindows(bool forward, const QKeySequence &shortcut, TabBoxMode mode)
{ {
if (!m_ready || isGrabbed() || !Workspace::self()->isOnCurrentHead()) { if (!m_ready || isGrabbed()) {
return; return;
} }
if (!options->focusPolicyIsReasonable()) { if (!options->focusPolicyIsReasonable()) {
@ -1098,7 +1098,7 @@ void TabBox::slotWalkBackThroughCurrentAppWindowsAlternative()
void TabBox::slotWalkThroughDesktops() void TabBox::slotWalkThroughDesktops()
{ {
if (!m_ready || isGrabbed() || !Workspace::self()->isOnCurrentHead()) { if (!m_ready || isGrabbed()) {
return; return;
} }
if (areModKeysDepressed(m_cutWalkThroughDesktops)) { if (areModKeysDepressed(m_cutWalkThroughDesktops)) {
@ -1112,7 +1112,7 @@ void TabBox::slotWalkThroughDesktops()
void TabBox::slotWalkBackThroughDesktops() void TabBox::slotWalkBackThroughDesktops()
{ {
if (!m_ready || isGrabbed() || !Workspace::self()->isOnCurrentHead()) { if (!m_ready || isGrabbed()) {
return; return;
} }
if (areModKeysDepressed(m_cutWalkThroughDesktopsReverse)) { if (areModKeysDepressed(m_cutWalkThroughDesktopsReverse)) {
@ -1126,7 +1126,7 @@ void TabBox::slotWalkBackThroughDesktops()
void TabBox::slotWalkThroughDesktopList() void TabBox::slotWalkThroughDesktopList()
{ {
if (!m_ready || isGrabbed() || !Workspace::self()->isOnCurrentHead()) { if (!m_ready || isGrabbed()) {
return; return;
} }
if (areModKeysDepressed(m_cutWalkThroughDesktopList)) { if (areModKeysDepressed(m_cutWalkThroughDesktopList)) {
@ -1140,7 +1140,7 @@ void TabBox::slotWalkThroughDesktopList()
void TabBox::slotWalkBackThroughDesktopList() void TabBox::slotWalkBackThroughDesktopList()
{ {
if (!m_ready || isGrabbed() || !Workspace::self()->isOnCurrentHead()) { if (!m_ready || isGrabbed()) {
return; return;
} }
if (areModKeysDepressed(m_cutWalkThroughDesktopListReverse)) { if (areModKeysDepressed(m_cutWalkThroughDesktopListReverse)) {

View file

@ -66,9 +66,6 @@
namespace KWin namespace KWin
{ {
extern int screen_number;
extern bool is_multihead;
X11EventFilterContainer::X11EventFilterContainer(X11EventFilter *filter) X11EventFilterContainer::X11EventFilterContainer(X11EventFilter *filter)
: m_filter(filter) : m_filter(filter)
{ {
@ -1295,34 +1292,6 @@ void Workspace::sendWindowToDesktop(Window *window, int desk, bool dont_activate
updateClientArea(); updateClientArea();
} }
/**
* checks whether the X Window with the input focus is on our X11 screen
* if the window cannot be determined or inspected, resturn depends on whether there's actually
* more than one screen
*
* this is NOT in any way related to XRandR multiscreen
*
*/
extern bool is_multihead; // main.cpp
bool Workspace::isOnCurrentHead()
{
if (!is_multihead) {
return true;
}
Xcb::CurrentInput currentInput;
if (currentInput.window() == XCB_WINDOW_NONE) {
return !is_multihead;
}
Xcb::WindowGeometry geometry(currentInput.window());
if (geometry.isNull()) { // should not happen
return !is_multihead;
}
return kwinApp()->x11RootWindow() == geometry->root;
}
void Workspace::sendWindowToOutput(Window *window, Output *output) void Workspace::sendWindowToOutput(Window *window, Output *output)
{ {
window->sendToOutput(output); window->sendToOutput(output);
@ -1560,13 +1529,6 @@ QString Workspace::supportInformation() const
} }
support.append(QStringLiteral("\nScreens\n")); support.append(QStringLiteral("\nScreens\n"));
support.append(QStringLiteral("=======\n")); support.append(QStringLiteral("=======\n"));
support.append(QStringLiteral("Multi-Head: "));
if (is_multihead) {
support.append(QStringLiteral("yes\n"));
support.append(QStringLiteral("Head: %1\n").arg(screen_number));
} else {
support.append(QStringLiteral("no\n"));
}
support.append(QStringLiteral("Active screen follows mouse: ")); support.append(QStringLiteral("Active screen follows mouse: "));
if (options->activeMouseScreen()) { if (options->activeMouseScreen()) {
support.append(QStringLiteral(" yes\n")); support.append(QStringLiteral(" yes\n"));
@ -2238,11 +2200,6 @@ QRectF Workspace::clientArea(clientAreaOption opt, const Output *output, const V
QRectF workArea; QRectF workArea;
QRectF screenArea; QRectF screenArea;
const Output *effectiveOutput = output;
if (is_multihead) {
effectiveOutput = xineramaIndexToOutput(screen_number);
}
if (auto desktopIt = m_screenAreas.constFind(desktop); desktopIt != m_screenAreas.constEnd()) { if (auto desktopIt = m_screenAreas.constFind(desktop); desktopIt != m_screenAreas.constEnd()) {
if (auto outputIt = desktopIt->constFind(output); outputIt != desktopIt->constEnd()) { if (auto outputIt = desktopIt->constFind(output); outputIt != desktopIt->constEnd()) {
screenArea = *outputIt; screenArea = *outputIt;
@ -2250,12 +2207,12 @@ QRectF Workspace::clientArea(clientAreaOption opt, const Output *output, const V
} }
if (screenArea.isNull()) { // screens may be missing during KWin initialization or screen config changes if (screenArea.isNull()) { // screens may be missing during KWin initialization or screen config changes
screenArea = effectiveOutput->geometry(); screenArea = output->geometry();
} }
workArea = m_workAreas.value(desktop); workArea = m_workAreas.value(desktop);
if (workArea.isNull()) { if (workArea.isNull()) {
workArea = is_multihead ? effectiveOutput->geometry() : m_geometry; workArea = m_geometry;
} }
switch (opt) { switch (opt) {
@ -2266,9 +2223,9 @@ QRectF Workspace::clientArea(clientAreaOption opt, const Output *output, const V
case FullScreenArea: case FullScreenArea:
case MovementArea: case MovementArea:
case ScreenArea: case ScreenArea:
return effectiveOutput->geometry(); return output->geometry();
case WorkArea: case WorkArea:
return is_multihead ? screenArea : workArea; return workArea;
case FullArea: case FullArea:
return m_geometry; return m_geometry;
default: default:

View file

@ -268,7 +268,6 @@ private:
// Unsorted // Unsorted
public: public:
bool isOnCurrentHead();
// True when performing Workspace::updateClientArea(). // True when performing Workspace::updateClientArea().
// The calls below are valid only in that case. // The calls below are valid only in that case.
bool inUpdateClientArea() const; bool inUpdateClientArea() const;