Merge branch 'KDE/4.11'
Conflicts: kwin/eglonxbackend.cpp kwin/glxbackend.cpp
This commit is contained in:
commit
3594550b14
9 changed files with 117 additions and 29 deletions
|
@ -2404,7 +2404,7 @@ QRect Client::decorationRect() const
|
|||
}
|
||||
}
|
||||
|
||||
KDecorationDefines::Position Client::titlebarPosition()
|
||||
KDecorationDefines::Position Client::titlebarPosition() const
|
||||
{
|
||||
Position titlePos = PositionCenter; // PositionTop is returned by the default implementation
|
||||
// this will hint errors in the metaobject usage ;-)
|
||||
|
|
2
client.h
2
client.h
|
@ -599,7 +599,7 @@ public:
|
|||
|
||||
bool decorationHasAlpha() const;
|
||||
|
||||
Position titlebarPosition();
|
||||
Position titlebarPosition() const;
|
||||
|
||||
enum CoordinateMode {
|
||||
DecorationRelative, // Relative to the top left corner of the decoration
|
||||
|
|
|
@ -269,7 +269,6 @@ void Compositor::slotCompositingOptionsInitialized()
|
|||
}
|
||||
|
||||
// render at least once
|
||||
compositeTimer.stop();
|
||||
performCompositing();
|
||||
}
|
||||
|
||||
|
@ -533,7 +532,6 @@ void Compositor::addRepaintFull()
|
|||
void Compositor::timerEvent(QTimerEvent *te)
|
||||
{
|
||||
if (te->timerId() == compositeTimer.timerId()) {
|
||||
compositeTimer.stop();
|
||||
performCompositing();
|
||||
} else
|
||||
QObject::timerEvent(te);
|
||||
|
@ -581,10 +579,12 @@ void Compositor::performCompositing()
|
|||
|
||||
if (repaints_region.isEmpty() && !windowRepaintsPending()) {
|
||||
m_scene->idle();
|
||||
m_timeSinceLastVBlank = fpsInterval - (options->vBlankTime() + 1); // means "start now"
|
||||
// Note: It would seem here we should undo suspended unredirect, but when scenes need
|
||||
// it for some reason, e.g. transformations or translucency, the next pass that does not
|
||||
// need this anymore and paints normally will also reset the suspended unredirect.
|
||||
// Otherwise the window would not be painted normally anyway.
|
||||
compositeTimer.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -602,6 +602,8 @@ void Compositor::performCompositing()
|
|||
|
||||
m_timeSinceLastVBlank = m_scene->paint(repaints, windows);
|
||||
|
||||
compositeTimer.stop(); // stop here to ensure *we* cause the next repaint schedule - not some effect through m_scene->paint()
|
||||
|
||||
// Trigger at least one more pass even if there would be nothing to paint, so that scene->idle()
|
||||
// is called the next time. If there would be nothing pending, it will not restart the timer and
|
||||
// scheduleRepaint() would restart it again somewhen later, called from functions that
|
||||
|
@ -661,10 +663,29 @@ void Compositor::setCompositeTimer()
|
|||
waitTime = nanoToMilli(padding - options->vBlankTime());
|
||||
}
|
||||
}
|
||||
else // w/o vsync we just jump to the next demanded tick
|
||||
// the "1" will ensure we don't block out the eventloop - the system's just not faster
|
||||
// "0" would be sufficient, but the compositor isn't the WMs only task
|
||||
waitTime = (m_timeSinceLastVBlank > fpsInterval) ? 1 : nanoToMilli(fpsInterval - m_timeSinceLastVBlank);
|
||||
else { // w/o blocking vsync we just jump to the next demanded tick
|
||||
if (fpsInterval > m_timeSinceLastVBlank) {
|
||||
waitTime = nanoToMilli(fpsInterval - m_timeSinceLastVBlank);
|
||||
if (!waitTime) {
|
||||
waitTime = 1; // will ensure we don't block out the eventloop - the system's just not faster ...
|
||||
}
|
||||
}/* else if (m_scene->syncsToVBlank() && m_timeSinceLastVBlank - fpsInterval < (vBlankInterval<<1)) {
|
||||
// NOTICE - "for later" ------------------------------------------------------------------
|
||||
// It can happen that we push two frames within one refresh cycle.
|
||||
// Swapping will then block even with triple buffering when the GPU does not discard but
|
||||
// queues frames
|
||||
// now here's the mean part: if we take that as "OMG, we're late - next frame ASAP",
|
||||
// there'll immediately be 2 frames in the pipe, swapping will block, we think we're
|
||||
// late ... ewww
|
||||
// so instead we pad to the clock again and add 2ms safety to ensure the pipe is really
|
||||
// free
|
||||
// NOTICE: obviously m_timeSinceLastVBlank can be too big because we're too slow as well
|
||||
// So if this code was enabled, we'd needlessly half the framerate once more (15 instead of 30)
|
||||
waitTime = nanoToMilli(vBlankInterval - (m_timeSinceLastVBlank - fpsInterval)%vBlankInterval) + 2;
|
||||
}*/ else {
|
||||
waitTime = 1; // ... "0" would be sufficient, but the compositor isn't the WMs only task
|
||||
}
|
||||
}
|
||||
compositeTimer.start(qMin(waitTime, 250u), this); // force 4fps minimum
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <kwinglplatform.h>
|
||||
// Qt
|
||||
#include <QDebug>
|
||||
// system
|
||||
#include <unistd.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -320,6 +322,14 @@ SceneOpenGL::TexturePrivate *EglOnXBackend::createBackendTexture(SceneOpenGL::Te
|
|||
|
||||
void EglOnXBackend::prepareRenderingFrame()
|
||||
{
|
||||
if (gs_tripleBufferNeedsDetection) {
|
||||
// the composite timer floors the repaint frequency. This can pollute our triple buffering
|
||||
// detection because the glXSwapBuffers call for the new frame has to wait until the pending
|
||||
// one scanned out.
|
||||
// So we compensate for that by waiting an extra milisecond to give the driver the chance to
|
||||
// fllush the buffer queue
|
||||
usleep(1000);
|
||||
}
|
||||
present();
|
||||
startRenderTimer();
|
||||
eglWaitNative(EGL_CORE_NATIVE_ENGINE);
|
||||
|
|
47
geometry.cpp
47
geometry.cpp
|
@ -395,8 +395,9 @@ QPoint Workspace::adjustClientPosition(Client* c, QPoint pos, bool unrestricted,
|
|||
if (options->windowSnapZone() || !borderSnapZone.isNull() || options->centerSnapZone()) {
|
||||
|
||||
const bool sOWO = options->isSnapOnlyWhenOverlapping();
|
||||
const int screen = screens()->number(pos + c->rect().center());
|
||||
if (maxRect.isNull())
|
||||
maxRect = clientArea(MovementArea, pos + c->rect().center(), c->desktop());
|
||||
maxRect = clientArea(MovementArea, screen, c->desktop());
|
||||
const int xmin = maxRect.left();
|
||||
const int xmax = maxRect.right() + 1; //desk size
|
||||
const int ymin = maxRect.top();
|
||||
|
@ -419,21 +420,25 @@ QPoint Workspace::adjustClientPosition(Client* c, QPoint pos, bool unrestricted,
|
|||
const int snapX = borderSnapZone.width() * snapAdjust; //snap trigger
|
||||
const int snapY = borderSnapZone.height() * snapAdjust;
|
||||
if (snapX || snapY) {
|
||||
QRect geo = c->geometry();
|
||||
const QPoint cp = c->clientPos();
|
||||
const QSize cs = c->geometry().size() - c->clientSize();
|
||||
const QSize cs = geo.size() - c->clientSize();
|
||||
int padding[4] = { cp.x(), cs.width() - cp.x(), cp.y(), cs.height() - cp.y() };
|
||||
|
||||
// snap to titlebar
|
||||
// snap to titlebar / snap to window borders on inner screen edges
|
||||
Position titlePos = c->titlebarPosition();
|
||||
if (titlePos == PositionLeft || (c->maximizeMode() & MaximizeHorizontal))
|
||||
if (padding[0] && (titlePos == PositionLeft || (c->maximizeMode() & MaximizeHorizontal) ||
|
||||
screens()->intersecting(geo.translated(maxRect.x() - (padding[0] + geo.x()), 0)) > 1))
|
||||
padding[0] = 0;
|
||||
if (titlePos == PositionRight || (c->maximizeMode() & MaximizeHorizontal))
|
||||
if (padding[1] && (titlePos == PositionRight || (c->maximizeMode() & MaximizeHorizontal) ||
|
||||
screens()->intersecting(geo.translated(maxRect.right() + padding[1] - geo.right(), 0)) > 1))
|
||||
padding[1] = 0;
|
||||
if (titlePos == PositionTop || (c->maximizeMode() & MaximizeVertical))
|
||||
if (padding[2] && (titlePos == PositionTop || (c->maximizeMode() & MaximizeVertical) ||
|
||||
screens()->intersecting(geo.translated(0, maxRect.y() - (padding[2] + geo.y()))) > 1))
|
||||
padding[2] = 0;
|
||||
if (titlePos == PositionBottom || (c->maximizeMode() & MaximizeVertical))
|
||||
if (padding[3] && (titlePos == PositionBottom || (c->maximizeMode() & MaximizeVertical) ||
|
||||
screens()->intersecting(geo.translated(0, maxRect.bottom() + padding[3] - geo.bottom())) > 1))
|
||||
padding[3] = 0;
|
||||
|
||||
if ((sOWO ? (cx < xmin) : true) && (qAbs(xmin - cx) < snapX)) {
|
||||
deltaX = xmin - cx;
|
||||
nx = xmin - padding[0];
|
||||
|
@ -842,19 +847,19 @@ void Client::keepInArea(QRect area, bool partial)
|
|||
if (area.width() < width() || area.height() < height())
|
||||
resizeWithChecks(qMin(area.width(), width()), qMin(area.height(), height()));
|
||||
}
|
||||
int tx = x(), ty = y();
|
||||
if (geometry().right() > area.right() && width() <= area.width())
|
||||
move(area.right() - width() + 1, y());
|
||||
tx = area.right() - width() + 1;
|
||||
if (geometry().bottom() > area.bottom() && height() <= area.height())
|
||||
move(x(), area.bottom() - height() + 1);
|
||||
ty = area.bottom() - height() + 1;
|
||||
if (!area.contains(geometry().topLeft())) {
|
||||
int tx = x();
|
||||
int ty = y();
|
||||
if (tx < area.x())
|
||||
tx = area.x();
|
||||
if (ty < area.y())
|
||||
ty = area.y();
|
||||
move(tx, ty);
|
||||
}
|
||||
if (tx != x() || ty != y())
|
||||
move(tx, ty);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1480,16 +1485,16 @@ void Client::getWmNormalHints()
|
|||
// update to match restrictions
|
||||
QSize new_size = adjustedSize();
|
||||
if (new_size != size() && !isFullScreen()) {
|
||||
QRect orig_geometry = geometry();
|
||||
QRect origClientGeometry(pos() + clientPos(), clientSize());
|
||||
resizeWithChecks(new_size);
|
||||
if ((!isSpecialWindow() || isToolbar()) && !isFullScreen()) {
|
||||
// try to keep the window in its xinerama screen if possible,
|
||||
// if that fails at least keep it visible somewhere
|
||||
QRect area = workspace()->clientArea(MovementArea, this);
|
||||
if (area.contains(orig_geometry))
|
||||
if (area.contains(origClientGeometry))
|
||||
keepInArea(area);
|
||||
area = workspace()->clientArea(WorkArea, this);
|
||||
if (area.contains(orig_geometry))
|
||||
if (area.contains(origClientGeometry))
|
||||
keepInArea(area);
|
||||
}
|
||||
}
|
||||
|
@ -1671,7 +1676,7 @@ void Client::configureRequest(int value_mask, int rx, int ry, int rw, int rh, in
|
|||
if (newScreen != rules()->checkScreen(newScreen))
|
||||
return; // not allowed by rule
|
||||
|
||||
QRect orig_geometry = geometry();
|
||||
QRect origClientGeometry(pos() + clientPos(), clientSize());
|
||||
GeometryUpdatesBlocker blocker(this);
|
||||
move(new_pos);
|
||||
plainResize(ns);
|
||||
|
@ -1679,7 +1684,7 @@ void Client::configureRequest(int value_mask, int rx, int ry, int rw, int rh, in
|
|||
updateFullScreenHack(QRect(new_pos, QSize(nw, nh)));
|
||||
QRect area = workspace()->clientArea(WorkArea, this);
|
||||
if (!from_tool && (!isSpecialWindow() || isToolbar()) && !isFullScreen()
|
||||
&& area.contains(orig_geometry))
|
||||
&& area.contains(origClientGeometry))
|
||||
keepInArea(area);
|
||||
|
||||
// this is part of the kicker-xinerama-hack... it should be
|
||||
|
@ -1701,7 +1706,7 @@ void Client::configureRequest(int value_mask, int rx, int ry, int rw, int rh, in
|
|||
QSize ns = sizeForClientSize(QSize(nw, nh));
|
||||
|
||||
if (ns != size()) { // don't restore if some app sets its own size again
|
||||
QRect orig_geometry = geometry();
|
||||
QRect origClientGeometry(pos() + clientPos(), clientSize());
|
||||
GeometryUpdatesBlocker blocker(this);
|
||||
int save_gravity = xSizeHint.win_gravity;
|
||||
xSizeHint.win_gravity = gravity;
|
||||
|
@ -1712,10 +1717,10 @@ void Client::configureRequest(int value_mask, int rx, int ry, int rw, int rh, in
|
|||
// try to keep the window in its xinerama screen if possible,
|
||||
// if that fails at least keep it visible somewhere
|
||||
QRect area = workspace()->clientArea(MovementArea, this);
|
||||
if (area.contains(orig_geometry))
|
||||
if (area.contains(origClientGeometry))
|
||||
keepInArea(area);
|
||||
area = workspace()->clientArea(WorkArea, this);
|
||||
if (area.contains(orig_geometry))
|
||||
if (area.contains(origClientGeometry))
|
||||
keepInArea(area);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <kwinglplatform.h>
|
||||
// Qt
|
||||
#include <QDebug>
|
||||
// system
|
||||
#include <unistd.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -492,6 +494,14 @@ SceneOpenGL::TexturePrivate *GlxBackend::createBackendTexture(SceneOpenGL::Textu
|
|||
|
||||
void GlxBackend::prepareRenderingFrame()
|
||||
{
|
||||
if (gs_tripleBufferNeedsDetection) {
|
||||
// the composite timer floors the repaint frequency. This can pollute our triple buffering
|
||||
// detection because the glXSwapBuffers call for the new frame has to wait until the pending
|
||||
// one scanned out.
|
||||
// So we compensate for that by waiting an extra milisecond to give the driver the chance to
|
||||
// fllush the buffer queue
|
||||
usleep(1000);
|
||||
}
|
||||
present();
|
||||
startRenderTimer();
|
||||
glXWaitX();
|
||||
|
|
|
@ -33,6 +33,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "client.h"
|
||||
#include "options.h"
|
||||
#include "rules.h"
|
||||
#include "screens.h"
|
||||
#endif
|
||||
|
||||
namespace KWin
|
||||
|
@ -836,6 +837,13 @@ int Workspace::packPositionLeft(const Client* cl, int oldx, bool left_edge) cons
|
|||
if (oldx <= newx) // try another Xinerama screen
|
||||
newx = clientArea(MaximizeArea,
|
||||
QPoint(cl->geometry().left() - 1, cl->geometry().center().y()), cl->desktop()).left();
|
||||
if (cl->titlebarPosition() != KDecorationDefines::PositionLeft) {
|
||||
QRect geo = cl->geometry();
|
||||
int rgt = newx - cl->clientPos().x();
|
||||
geo.moveRight(rgt);
|
||||
if (screens()->intersecting(geo) < 2)
|
||||
newx = rgt;
|
||||
}
|
||||
if (oldx <= newx)
|
||||
return oldx;
|
||||
for (ClientList::ConstIterator it = clients.constBegin(), end = clients.constEnd(); it != end; ++it) {
|
||||
|
@ -856,6 +864,13 @@ int Workspace::packPositionRight(const Client* cl, int oldx, bool right_edge) co
|
|||
if (oldx >= newx) // try another Xinerama screen
|
||||
newx = clientArea(MaximizeArea,
|
||||
QPoint(cl->geometry().right() + 1, cl->geometry().center().y()), cl->desktop()).right();
|
||||
if (cl->titlebarPosition() != KDecorationDefines::PositionRight) {
|
||||
QRect geo = cl->geometry();
|
||||
int rgt = newx + cl->width() - (cl->clientSize().width() + cl->clientPos().x());
|
||||
geo.moveRight(rgt);
|
||||
if (screens()->intersecting(geo) < 2)
|
||||
newx = rgt;
|
||||
}
|
||||
if (oldx >= newx)
|
||||
return oldx;
|
||||
for (ClientList::ConstIterator it = clients.constBegin(), end = clients.constEnd(); it != end; ++it) {
|
||||
|
@ -876,6 +891,13 @@ int Workspace::packPositionUp(const Client* cl, int oldy, bool top_edge) const
|
|||
if (oldy <= newy) // try another Xinerama screen
|
||||
newy = clientArea(MaximizeArea,
|
||||
QPoint(cl->geometry().center().x(), cl->geometry().top() - 1), cl->desktop()).top();
|
||||
if (cl->titlebarPosition() != KDecorationDefines::PositionTop) {
|
||||
QRect geo = cl->geometry();
|
||||
int top = newy - cl->clientPos().y();
|
||||
geo.moveTop(top);
|
||||
if (screens()->intersecting(geo) < 2)
|
||||
newy = top;
|
||||
}
|
||||
if (oldy <= newy)
|
||||
return oldy;
|
||||
for (ClientList::ConstIterator it = clients.constBegin(), end = clients.constEnd(); it != end; ++it) {
|
||||
|
@ -896,6 +918,13 @@ int Workspace::packPositionDown(const Client* cl, int oldy, bool bottom_edge) co
|
|||
if (oldy >= newy) // try another Xinerama screen
|
||||
newy = clientArea(MaximizeArea,
|
||||
QPoint(cl->geometry().center().x(), cl->geometry().bottom() + 1), cl->desktop()).bottom();
|
||||
if (cl->titlebarPosition() != KDecorationDefines::PositionBottom) {
|
||||
QRect geo = cl->geometry();
|
||||
int btm = newy + cl->height() - (cl->clientSize().height() + cl->clientPos().y());
|
||||
geo.moveBottom(btm);
|
||||
if (screens()->intersecting(geo) < 2)
|
||||
newy = btm;
|
||||
}
|
||||
if (oldy >= newy)
|
||||
return oldy;
|
||||
for (ClientList::ConstIterator it = clients.constBegin(), end = clients.constEnd(); it != end; ++it) {
|
||||
|
|
11
screens.cpp
11
screens.cpp
|
@ -117,6 +117,17 @@ int Screens::current() const
|
|||
return m_current;
|
||||
}
|
||||
|
||||
int Screens::intersecting(const QRect &r) const
|
||||
{
|
||||
int cnt = 0;
|
||||
for (int i = 0; i < count(); ++i) {
|
||||
if (geometry(i).intersects(r)) {
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
DesktopWidgetScreens::DesktopWidgetScreens(QObject *parent)
|
||||
: Screens(parent)
|
||||
, m_desktop(QApplication::desktop())
|
||||
|
|
|
@ -68,6 +68,8 @@ public:
|
|||
|
||||
inline bool isChanging() { return m_changedTimer->isActive(); }
|
||||
|
||||
int intersecting(const QRect &r) const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void reconfigure();
|
||||
|
||||
|
|
Loading…
Reference in a new issue