xcb: convert last screen to fake when no screen
available for xrandr 1.5 like we did before for xrandr 1.4
(since a094af0017).
Tested with following combination:
* qtbase -DECM_ENABLE_SANITIZERS=address cmake build
* examples/widgets/widgets/wiggly with
ASAN_OPTIONS=verify_asan_link_order=0 env
* xrandr --output LastScreen --off and --auto.
Fixes: QTBUG-96247
Task-number: QTBUG-42985
Change-Id: Idd95d1a3aa057d23e3adb6635dd1acbb2c853497
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
bb10
parent
b2c3b3e8fe
commit
d8f37d94e5
|
|
@ -378,7 +378,8 @@ void QXcbConnection::initializeScreens(bool initialized)
|
|||
}
|
||||
}
|
||||
|
||||
qCDebug(lcQpaScreen) << "primary output is" << qAsConst(m_screens).first()->name();
|
||||
if (!m_screens.isEmpty())
|
||||
qCDebug(lcQpaScreen) << "primary output is" << qAsConst(m_screens).first()->name();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -499,6 +500,8 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int
|
|||
m_virtualDesktops.append(virtualDesktop);
|
||||
}
|
||||
QList<QPlatformScreen*> old = virtualDesktop->m_screens;
|
||||
if (initialized)
|
||||
m_screens.clear();
|
||||
|
||||
QList<QPlatformScreen *> siblings;
|
||||
|
||||
|
|
@ -523,6 +526,7 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int
|
|||
screen = createScreen_monitor(virtualDesktop, monitor_info, monitors_r->timestamp);
|
||||
QHighDpiScaling::updateHighDpiScaling();
|
||||
} else {
|
||||
m_screens << screen;
|
||||
updateScreen_monitor(screen, monitor_info, monitors_r->timestamp);
|
||||
old.removeAll(screen);
|
||||
}
|
||||
|
|
@ -530,14 +534,29 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int
|
|||
|
||||
siblings << screen;
|
||||
|
||||
if (primaryScreenNumber() == xcbScreenNumber) {
|
||||
primaryScreen = screen;
|
||||
primaryScreen->setPrimary(true);
|
||||
}
|
||||
|
||||
xcb_randr_monitor_info_next(&monitor_iter);
|
||||
}
|
||||
|
||||
if (siblings.isEmpty()) {
|
||||
// If there are no XRandR outputs or XRandR extension is missing,
|
||||
// then create a fake/legacy screen.
|
||||
auto screen = new QXcbScreen(this, virtualDesktop, nullptr);
|
||||
qCDebug(lcQpaScreen) << "created fake screen" << screen;
|
||||
QXcbScreen *screen = nullptr;
|
||||
if (initialized && !old.isEmpty()) {
|
||||
// If there are no other screens on the same virtual desktop,
|
||||
// then transform the physical screen into a fake screen.
|
||||
screen = static_cast<QXcbScreen *>(old.takeFirst());
|
||||
const QString nameWas = screen->name();
|
||||
screen->setMonitor(nullptr, XCB_NONE);
|
||||
qCDebug(lcQpaScreen) << "transformed" << nameWas << "to fake" << screen;
|
||||
} else {
|
||||
// If there are no XRandR outputs or XRandR extension is missing,
|
||||
// then create a fake/legacy screen.
|
||||
screen = new QXcbScreen(this, virtualDesktop, nullptr);
|
||||
qCDebug(lcQpaScreen) << "create a fake screen: " << screen;
|
||||
}
|
||||
|
||||
if (primaryScreenNumber() == xcbScreenNumber) {
|
||||
primaryScreen = screen;
|
||||
|
|
@ -548,8 +567,11 @@ void QXcbConnection::initializeScreensFromMonitor(xcb_screen_iterator_t *it, int
|
|||
}
|
||||
|
||||
if (initialized) {
|
||||
for (QPlatformScreen *ps : old)
|
||||
destroyScreen(static_cast<QXcbScreen*>(ps));
|
||||
for (QPlatformScreen *ps : old) {
|
||||
virtualDesktop->removeScreen(ps);
|
||||
qCDebug(lcQpaScreen) << "destroy screen: " << ps;
|
||||
QWindowSystemInterface::handleScreenRemoved(ps);
|
||||
}
|
||||
}
|
||||
|
||||
virtualDesktop->setScreens(std::move(siblings));
|
||||
|
|
|
|||
|
|
@ -622,18 +622,28 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
|
|||
|
||||
void QXcbScreen::setMonitor(xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp_t timestamp)
|
||||
{
|
||||
if (!connection()->isAtLeastXRandR15() || !monitorInfo)
|
||||
if (!connection()->isAtLeastXRandR15())
|
||||
return;
|
||||
|
||||
m_outputs.clear();
|
||||
m_crtcs.clear();
|
||||
|
||||
if (!monitorInfo) {
|
||||
m_monitor = nullptr;
|
||||
m_output = XCB_NONE;
|
||||
m_crtc = XCB_NONE;
|
||||
m_mode = XCB_NONE;
|
||||
m_outputName = defaultName();
|
||||
// TODO: Send an event to the QScreen instance that the screen changed its name
|
||||
return;
|
||||
}
|
||||
|
||||
xcb_randr_select_input(xcb_connection(), screen()->root, true);
|
||||
|
||||
m_monitor = monitorInfo;
|
||||
QRect monitorGeometry = QRect(m_monitor->x, m_monitor->y,
|
||||
m_monitor->width, m_monitor->height);
|
||||
|
||||
m_outputs.clear();
|
||||
m_crtcs.clear();
|
||||
|
||||
int outputCount = xcb_randr_monitor_info_outputs_length(m_monitor);
|
||||
xcb_randr_output_t *outputs = nullptr;
|
||||
if (outputCount) {
|
||||
|
|
@ -702,6 +712,18 @@ void QXcbScreen::setMonitor(xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp
|
|||
m_cursor = new QXcbCursor(connection(), this);
|
||||
}
|
||||
|
||||
QString QXcbScreen::defaultName()
|
||||
{
|
||||
QString name;
|
||||
QByteArray displayName = connection()->displayName();
|
||||
int dotPos = displayName.lastIndexOf('.');
|
||||
if (dotPos != -1)
|
||||
displayName.truncate(dotPos);
|
||||
name = QString::fromLocal8Bit(displayName) + QLatin1Char('.')
|
||||
+ QString::number(m_virtualDesktop->number());
|
||||
return name;
|
||||
}
|
||||
|
||||
QXcbScreen::~QXcbScreen()
|
||||
{
|
||||
delete m_cursor;
|
||||
|
|
@ -714,12 +736,7 @@ QString QXcbScreen::getOutputName(xcb_randr_get_output_info_reply_t *outputInfo)
|
|||
name = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(outputInfo),
|
||||
xcb_randr_get_output_info_name_length(outputInfo));
|
||||
} else {
|
||||
QByteArray displayName = connection()->displayName();
|
||||
int dotPos = displayName.lastIndexOf('.');
|
||||
if (dotPos != -1)
|
||||
displayName.truncate(dotPos);
|
||||
name = QString::fromLocal8Bit(displayName) + QLatin1Char('.')
|
||||
+ QString::number(m_virtualDesktop->number());
|
||||
name = defaultName();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@ public:
|
|||
xcb_randr_get_output_info_reply_t *outputInfo);
|
||||
void setCrtc(xcb_randr_crtc_t crtc) { m_crtc = crtc; }
|
||||
void setMonitor(xcb_randr_monitor_info_t *monitorInfo, xcb_timestamp_t timestamp = XCB_NONE);
|
||||
QString defaultName();
|
||||
|
||||
void windowShown(QXcbWindow *window);
|
||||
QString windowManagerName() const { return m_virtualDesktop->windowManagerName(); }
|
||||
|
|
|
|||
Loading…
Reference in New Issue