Move struts logic to AbstractClient
parent
4b978bb403
commit
a9fd5ac19f
|
@ -1446,6 +1446,22 @@ void AbstractClient::performMoveResize()
|
|||
emit clientStepUserMovedResized(this, moveResizeGeom);
|
||||
}
|
||||
|
||||
StrutRect AbstractClient::strutRect(StrutArea area) const
|
||||
{
|
||||
Q_UNUSED(area)
|
||||
return StrutRect();
|
||||
}
|
||||
|
||||
StrutRects AbstractClient::strutRects() const
|
||||
{
|
||||
StrutRects region;
|
||||
region += strutRect(StrutAreaTop);
|
||||
region += strutRect(StrutAreaRight);
|
||||
region += strutRect(StrutAreaBottom);
|
||||
region += strutRect(StrutAreaLeft);
|
||||
return region;
|
||||
}
|
||||
|
||||
bool AbstractClient::hasStrut() const
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -686,6 +686,8 @@ public:
|
|||
return m_moveResize.cursor;
|
||||
}
|
||||
|
||||
virtual StrutRect strutRect(StrutArea area) const;
|
||||
StrutRects strutRects() const;
|
||||
virtual bool hasStrut() const;
|
||||
|
||||
void setModal(bool modal);
|
||||
|
|
175
workspace.cpp
175
workspace.cpp
|
@ -1968,6 +1968,80 @@ void Workspace::saveOldScreenSizes()
|
|||
oldscreensizes.append( screens()->geometry( i ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the window has a strut that expands through the invisible area of
|
||||
* an xinerama setup where the monitors are not the same resolution.
|
||||
*/
|
||||
static bool hasOffscreenXineramaStrut(AbstractClient *client)
|
||||
{
|
||||
// Get strut as a QRegion
|
||||
QRegion region;
|
||||
region += client->strutRect(StrutAreaTop);
|
||||
region += client->strutRect(StrutAreaRight);
|
||||
region += client->strutRect(StrutAreaBottom);
|
||||
region += client->strutRect(StrutAreaLeft);
|
||||
|
||||
// Remove all visible areas so that only the invisible remain
|
||||
for (int i = 0; i < screens()->count(); i ++) {
|
||||
region -= screens()->geometry(i);
|
||||
}
|
||||
|
||||
// If there's anything left then we have an offscreen strut
|
||||
return !region.isEmpty();
|
||||
}
|
||||
|
||||
QRect Workspace::adjustClientArea(AbstractClient *client, const QRect &area) const
|
||||
{
|
||||
QRect adjustedArea = area;
|
||||
|
||||
QRect strutLeft = client->strutRect(StrutAreaLeft);
|
||||
QRect strutRight = client->strutRect(StrutAreaRight);
|
||||
QRect strutTop = client->strutRect(StrutAreaTop);
|
||||
QRect strutBottom = client->strutRect(StrutAreaBottom);
|
||||
|
||||
QRect screenArea = clientArea(ScreenArea, client);
|
||||
// HACK: workarea handling is not xinerama aware, so if this strut
|
||||
// reserves place at a xinerama edge that's inside the virtual screen,
|
||||
// ignore the strut for workspace setting.
|
||||
if (area == QRect(QPoint(0, 0), screens()->displaySize())) {
|
||||
if (strutLeft.left() < screenArea.left()) {
|
||||
strutLeft = QRect();
|
||||
}
|
||||
if (strutRight.right() > screenArea.right()) {
|
||||
strutRight = QRect();
|
||||
}
|
||||
if (strutTop.top() < screenArea.top()) {
|
||||
strutTop = QRect();
|
||||
}
|
||||
if (strutBottom.bottom() < screenArea.bottom()) {
|
||||
strutBottom = QRect();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle struts at xinerama edges that are inside the virtual screen.
|
||||
// They're given in virtual screen coordinates, make them affect only
|
||||
// their xinerama screen.
|
||||
strutLeft.setLeft(qMax(strutLeft.left(), screenArea.left()));
|
||||
strutRight.setRight(qMin(strutRight.right(), screenArea.right()));
|
||||
strutTop.setTop(qMax(strutTop.top(), screenArea.top()));
|
||||
strutBottom.setBottom(qMin(strutBottom.bottom(), screenArea.bottom()));
|
||||
|
||||
if (strutLeft.intersects(area)) {
|
||||
adjustedArea.setLeft(strutLeft.right() + 1);
|
||||
}
|
||||
if (strutRight.intersects(area)) {
|
||||
adjustedArea.setRight(strutRight.left() - 1);
|
||||
}
|
||||
if (strutTop.intersects(area)) {
|
||||
adjustedArea.setTop(strutTop.bottom() + 1);
|
||||
}
|
||||
if (strutBottom.intersects(area)) {
|
||||
adjustedArea.setBottom(strutBottom.top() - 1);
|
||||
}
|
||||
|
||||
return adjustedArea;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current client areas according to the current clients.
|
||||
*
|
||||
|
@ -2007,10 +2081,11 @@ void Workspace::updateClientArea(bool force)
|
|||
iS ++)
|
||||
new_sareas[ i ][ iS ] = screens[ iS ];
|
||||
}
|
||||
for (auto it = clients.constBegin(); it != clients.constEnd(); ++it) {
|
||||
if (!(*it)->hasStrut())
|
||||
for (AbstractClient *client : qAsConst(m_allClients)) {
|
||||
if (!client->hasStrut()) {
|
||||
continue;
|
||||
QRect r = (*it)->adjustedClientArea(desktopArea, desktopArea);
|
||||
}
|
||||
QRect r = adjustClientArea(client, desktopArea);
|
||||
// sanity check that a strut doesn't exclude a complete screen geometry
|
||||
// this is a violation to EWMH, as KWin just ignores the strut
|
||||
for (int i = 0; i < Screens::self()->count(); i++) {
|
||||
|
@ -2020,8 +2095,8 @@ void Workspace::updateClientArea(bool force)
|
|||
break;
|
||||
}
|
||||
}
|
||||
StrutRects strutRegion = (*it)->strutRects();
|
||||
const QRect clientsScreenRect = KWin::screens()->geometry((*it)->screen());
|
||||
StrutRects strutRegion = client->strutRects();
|
||||
const QRect clientsScreenRect = KWin::screens()->geometry(client->screen());
|
||||
for (auto strut = strutRegion.begin(); strut != strutRegion.end(); strut++) {
|
||||
*strut = StrutRect((*strut).intersected(clientsScreenRect), (*strut).area());
|
||||
}
|
||||
|
@ -2032,20 +2107,20 @@ void Workspace::updateClientArea(bool force)
|
|||
// This goes against the EWMH description of the work area but it is a toss up between
|
||||
// having unusable sections of the screen (Which can be quite large with newer monitors)
|
||||
// or having some content appear offscreen (Relatively rare compared to other).
|
||||
bool hasOffscreenXineramaStrut = (*it)->hasOffscreenXineramaStrut();
|
||||
bool hasOffscreenStrut = hasOffscreenXineramaStrut(client);
|
||||
|
||||
if ((*it)->isOnAllDesktops()) {
|
||||
if (client->isOnAllDesktops()) {
|
||||
for (int i = 1;
|
||||
i <= numberOfDesktops;
|
||||
++i) {
|
||||
if (!hasOffscreenXineramaStrut)
|
||||
if (!hasOffscreenStrut)
|
||||
new_wareas[ i ] = new_wareas[ i ].intersected(r);
|
||||
new_rmoveareas[ i ] += strutRegion;
|
||||
for (int iS = 0;
|
||||
iS < nscreens;
|
||||
iS ++) {
|
||||
const auto geo = new_sareas[ i ][ iS ].intersected(
|
||||
(*it)->adjustedClientArea(desktopArea, screens[ iS ]));
|
||||
adjustClientArea(client, screens[ iS ]));
|
||||
// ignore the geometry if it results in the screen getting removed completely
|
||||
if (!geo.isEmpty()) {
|
||||
new_sareas[ i ][ iS ] = geo;
|
||||
|
@ -2053,92 +2128,22 @@ void Workspace::updateClientArea(bool force)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (!hasOffscreenXineramaStrut)
|
||||
new_wareas[(*it)->desktop()] = new_wareas[(*it)->desktop()].intersected(r);
|
||||
new_rmoveareas[(*it)->desktop()] += strutRegion;
|
||||
if (!hasOffscreenStrut)
|
||||
new_wareas[client->desktop()] = new_wareas[client->desktop()].intersected(r);
|
||||
new_rmoveareas[client->desktop()] += strutRegion;
|
||||
for (int iS = 0;
|
||||
iS < nscreens;
|
||||
iS ++) {
|
||||
// qDebug() << "adjusting new_sarea: " << screens[ iS ];
|
||||
const auto geo = new_sareas[(*it)->desktop()][ iS ].intersected(
|
||||
(*it)->adjustedClientArea(desktopArea, screens[ iS ]));
|
||||
const auto geo = new_sareas[client->desktop()][ iS ].intersected(
|
||||
adjustClientArea(client, screens[ iS ]));
|
||||
// ignore the geometry if it results in the screen getting removed completely
|
||||
if (!geo.isEmpty()) {
|
||||
new_sareas[(*it)->desktop()][ iS ] = geo;
|
||||
new_sareas[client->desktop()][ iS ] = geo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (waylandServer()) {
|
||||
auto updateStrutsForWaylandClient = [&] (AbstractClient *c) {
|
||||
// assuming that only docks have "struts" and that all docks have a strut
|
||||
if (!c->hasStrut()) {
|
||||
return;
|
||||
}
|
||||
auto margins = [c] (const QRect &geometry) {
|
||||
QMargins margins;
|
||||
if (!geometry.intersects(c->frameGeometry())) {
|
||||
return margins;
|
||||
}
|
||||
// figure out which areas of the overall screen setup it borders
|
||||
const bool left = c->frameGeometry().left() == geometry.left();
|
||||
const bool right = c->frameGeometry().right() == geometry.right();
|
||||
const bool top = c->frameGeometry().top() == geometry.top();
|
||||
const bool bottom = c->frameGeometry().bottom() == geometry.bottom();
|
||||
const bool horizontal = c->frameGeometry().width() >= c->frameGeometry().height();
|
||||
if (left && ((!top && !bottom) || !horizontal)) {
|
||||
margins.setLeft(c->frameGeometry().width());
|
||||
}
|
||||
if (right && ((!top && !bottom) || !horizontal)) {
|
||||
margins.setRight(c->frameGeometry().width());
|
||||
}
|
||||
if (top && ((!left && !right) || horizontal)) {
|
||||
margins.setTop(c->frameGeometry().height());
|
||||
}
|
||||
if (bottom && ((!left && !right) || horizontal)) {
|
||||
margins.setBottom(c->frameGeometry().height());
|
||||
}
|
||||
return margins;
|
||||
};
|
||||
auto marginsToStrutArea = [] (const QMargins &margins) {
|
||||
if (margins.left() != 0) {
|
||||
return StrutAreaLeft;
|
||||
}
|
||||
if (margins.right() != 0) {
|
||||
return StrutAreaRight;
|
||||
}
|
||||
if (margins.top() != 0) {
|
||||
return StrutAreaTop;
|
||||
}
|
||||
if (margins.bottom() != 0) {
|
||||
return StrutAreaBottom;
|
||||
}
|
||||
return StrutAreaInvalid;
|
||||
};
|
||||
const auto strut = margins(KWin::screens()->geometry(c->screen()));
|
||||
const StrutRects strutRegion = StrutRects{StrutRect(c->frameGeometry(), marginsToStrutArea(strut))};
|
||||
QRect r = desktopArea - margins(KWin::screens()->geometry());
|
||||
if (c->isOnAllDesktops()) {
|
||||
for (int i = 1; i <= numberOfDesktops; ++i) {
|
||||
new_wareas[ i ] = new_wareas[ i ].intersected(r);
|
||||
for (int iS = 0; iS < nscreens; ++iS) {
|
||||
new_sareas[ i ][ iS ] = new_sareas[ i ][ iS ].intersected(screens[iS] - margins(screens[iS]));
|
||||
}
|
||||
new_rmoveareas[ i ] += strutRegion;
|
||||
}
|
||||
} else {
|
||||
new_wareas[c->desktop()] = new_wareas[c->desktop()].intersected(r);
|
||||
for (int iS = 0; iS < nscreens; iS++) {
|
||||
new_sareas[c->desktop()][ iS ] = new_sareas[c->desktop()][ iS ].intersected(screens[iS] - margins(screens[iS]));
|
||||
}
|
||||
new_rmoveareas[ c->desktop() ] += strutRegion;
|
||||
}
|
||||
};
|
||||
const auto clients = waylandServer()->clients();
|
||||
for (auto c : clients) {
|
||||
updateStrutsForWaylandClient(c);
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
for (int i = 1;
|
||||
i <= numberOfDesktops();
|
||||
|
|
|
@ -183,6 +183,7 @@ public:
|
|||
*/
|
||||
void setMoveResizeClient(AbstractClient* c);
|
||||
|
||||
QRect adjustClientArea(AbstractClient *client, const QRect &area) const;
|
||||
QPoint adjustClientPosition(AbstractClient* c, QPoint pos, bool unrestricted, double snapAdjust = 1.0);
|
||||
QRect adjustClientSize(AbstractClient* c, QRect moveResizeGeom, int mode);
|
||||
void raiseClient(AbstractClient* c, bool nogroup = false);
|
||||
|
|
101
x11client.cpp
101
x11client.cpp
|
@ -4798,80 +4798,6 @@ void X11Client::doPerformMoveResize()
|
|||
} // (leads to sync request races in some clients)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns \a area with the client's strut taken into account.
|
||||
*
|
||||
* Used from Workspace in updateClientArea.
|
||||
*/
|
||||
// TODO move to Workspace?
|
||||
|
||||
QRect X11Client::adjustedClientArea(const QRect &desktopArea, const QRect& area) const
|
||||
{
|
||||
QRect r = area;
|
||||
NETExtendedStrut str = strut();
|
||||
QRect stareaL = QRect(
|
||||
0,
|
||||
str . left_start,
|
||||
str . left_width,
|
||||
str . left_end - str . left_start + 1);
|
||||
QRect stareaR = QRect(
|
||||
desktopArea . right() - str . right_width + 1,
|
||||
str . right_start,
|
||||
str . right_width,
|
||||
str . right_end - str . right_start + 1);
|
||||
QRect stareaT = QRect(
|
||||
str . top_start,
|
||||
0,
|
||||
str . top_end - str . top_start + 1,
|
||||
str . top_width);
|
||||
QRect stareaB = QRect(
|
||||
str . bottom_start,
|
||||
desktopArea . bottom() - str . bottom_width + 1,
|
||||
str . bottom_end - str . bottom_start + 1,
|
||||
str . bottom_width);
|
||||
|
||||
QRect screenarea = workspace()->clientArea(ScreenArea, this);
|
||||
// HACK: workarea handling is not xinerama aware, so if this strut
|
||||
// reserves place at a xinerama edge that's inside the virtual screen,
|
||||
// ignore the strut for workspace setting.
|
||||
if (area == QRect(QPoint(0, 0), screens()->displaySize())) {
|
||||
if (stareaL.left() < screenarea.left())
|
||||
stareaL = QRect();
|
||||
if (stareaR.right() > screenarea.right())
|
||||
stareaR = QRect();
|
||||
if (stareaT.top() < screenarea.top())
|
||||
stareaT = QRect();
|
||||
if (stareaB.bottom() < screenarea.bottom())
|
||||
stareaB = QRect();
|
||||
}
|
||||
// Handle struts at xinerama edges that are inside the virtual screen.
|
||||
// They're given in virtual screen coordinates, make them affect only
|
||||
// their xinerama screen.
|
||||
stareaL.setLeft(qMax(stareaL.left(), screenarea.left()));
|
||||
stareaR.setRight(qMin(stareaR.right(), screenarea.right()));
|
||||
stareaT.setTop(qMax(stareaT.top(), screenarea.top()));
|
||||
stareaB.setBottom(qMin(stareaB.bottom(), screenarea.bottom()));
|
||||
|
||||
if (stareaL . intersects(area)) {
|
||||
// qDebug() << "Moving left of: " << r << " to " << stareaL.right() + 1;
|
||||
r . setLeft(stareaL . right() + 1);
|
||||
}
|
||||
if (stareaR . intersects(area)) {
|
||||
// qDebug() << "Moving right of: " << r << " to " << stareaR.left() - 1;
|
||||
r . setRight(stareaR . left() - 1);
|
||||
}
|
||||
if (stareaT . intersects(area)) {
|
||||
// qDebug() << "Moving top of: " << r << " to " << stareaT.bottom() + 1;
|
||||
r . setTop(stareaT . bottom() + 1);
|
||||
}
|
||||
if (stareaB . intersects(area)) {
|
||||
// qDebug() << "Moving bottom of: " << r << " to " << stareaB.top() - 1;
|
||||
r . setBottom(stareaB . top() - 1);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
NETExtendedStrut X11Client::strut() const
|
||||
{
|
||||
NETExtendedStrut ext = info->extendedStrut();
|
||||
|
@ -4944,16 +4870,6 @@ StrutRect X11Client::strutRect(StrutArea area) const
|
|||
return StrutRect(); // Null rect
|
||||
}
|
||||
|
||||
StrutRects X11Client::strutRects() const
|
||||
{
|
||||
StrutRects region;
|
||||
region += strutRect(StrutAreaTop);
|
||||
region += strutRect(StrutAreaRight);
|
||||
region += strutRect(StrutAreaBottom);
|
||||
region += strutRect(StrutAreaLeft);
|
||||
return region;
|
||||
}
|
||||
|
||||
bool X11Client::hasStrut() const
|
||||
{
|
||||
NETExtendedStrut ext = strut();
|
||||
|
@ -4962,23 +4878,6 @@ bool X11Client::hasStrut() const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool X11Client::hasOffscreenXineramaStrut() const
|
||||
{
|
||||
// Get strut as a QRegion
|
||||
QRegion region;
|
||||
region += strutRect(StrutAreaTop);
|
||||
region += strutRect(StrutAreaRight);
|
||||
region += strutRect(StrutAreaBottom);
|
||||
region += strutRect(StrutAreaLeft);
|
||||
|
||||
// Remove all visible areas so that only the invisible remain
|
||||
for (int i = 0; i < screens()->count(); i ++)
|
||||
region -= screens()->geometry(i);
|
||||
|
||||
// If there's anything left then we have an offscreen strut
|
||||
return !region.isEmpty();
|
||||
}
|
||||
|
||||
void X11Client::applyWindowRules()
|
||||
{
|
||||
AbstractClient::applyWindowRules();
|
||||
|
|
12
x11client.h
12
x11client.h
|
@ -187,8 +187,6 @@ public:
|
|||
|
||||
bool providesContextHelp() const override;
|
||||
|
||||
QRect adjustedClientArea(const QRect& desktop, const QRect& area) const;
|
||||
|
||||
xcb_colormap_t colormap() const;
|
||||
|
||||
/// Updates visibility depending on being shaded, virtual desktop, etc.
|
||||
|
@ -237,8 +235,8 @@ public:
|
|||
void killWindow() override;
|
||||
void showContextHelp() override;
|
||||
void checkActiveModal();
|
||||
StrutRect strutRect(StrutArea area) const;
|
||||
StrutRects strutRects() const;
|
||||
|
||||
StrutRect strutRect(StrutArea area) const override;
|
||||
bool hasStrut() const override;
|
||||
|
||||
/**
|
||||
|
@ -249,12 +247,6 @@ public:
|
|||
*/
|
||||
void setClientShown(bool shown) override;
|
||||
|
||||
/**
|
||||
* Whether or not the window has a strut that expands through the invisible area of
|
||||
* an xinerama setup where the monitors are not the same resolution.
|
||||
*/
|
||||
bool hasOffscreenXineramaStrut() const;
|
||||
|
||||
QRect transparentRect() const override;
|
||||
|
||||
bool isClientSideDecorated() const;
|
||||
|
|
|
@ -851,6 +851,47 @@ bool XdgToplevelClient::supportsWindowRules() const
|
|||
return !m_plasmaShellSurface;
|
||||
}
|
||||
|
||||
StrutRect XdgToplevelClient::strutRect(StrutArea area) const
|
||||
{
|
||||
if (!hasStrut()) {
|
||||
return StrutRect();
|
||||
}
|
||||
|
||||
const QRect windowRect = frameGeometry();
|
||||
const QRect outputRect = screens()->geometry(screen());
|
||||
|
||||
const bool left = windowRect.left() == outputRect.left();
|
||||
const bool right = windowRect.right() == outputRect.right();
|
||||
const bool top = windowRect.top() == outputRect.top();
|
||||
const bool bottom = windowRect.bottom() == outputRect.bottom();
|
||||
const bool horizontal = width() >= height();
|
||||
|
||||
switch (area) {
|
||||
case StrutAreaTop:
|
||||
if (top && ((!left && !right) || horizontal)) {
|
||||
return StrutRect(windowRect, StrutAreaTop);
|
||||
}
|
||||
return StrutRect();
|
||||
case StrutAreaRight:
|
||||
if (right && ((!top && !bottom) || !horizontal)) {
|
||||
return StrutRect(windowRect, StrutAreaRight);
|
||||
}
|
||||
return StrutRect();
|
||||
case StrutAreaBottom:
|
||||
if (bottom && ((!left && !right) || horizontal)) {
|
||||
return StrutRect(windowRect, StrutAreaBottom);
|
||||
}
|
||||
return StrutRect();
|
||||
case StrutAreaLeft:
|
||||
if (left && ((!top && !bottom) || !horizontal)) {
|
||||
return StrutRect(windowRect, StrutAreaLeft);
|
||||
}
|
||||
return StrutRect();
|
||||
default:
|
||||
return StrutRect();
|
||||
}
|
||||
}
|
||||
|
||||
bool XdgToplevelClient::hasStrut() const
|
||||
{
|
||||
if (!isShown(true)) {
|
||||
|
|
|
@ -152,6 +152,7 @@ public:
|
|||
bool takeFocus() override;
|
||||
bool wantsInput() const override;
|
||||
bool dockWantsInput() const override;
|
||||
StrutRect strutRect(StrutArea area) const override;
|
||||
bool hasStrut() const override;
|
||||
void showOnScreenEdge() override;
|
||||
void setFullScreen(bool set, bool user) override;
|
||||
|
|
Loading…
Reference in New Issue