Bug 294157 - KWin should perform a sync request for a configure request instead of direct action
Summary: KWin should perform a sync request for a configure request instead of direct ...
Status: RESOLVED UNMAINTAINED
Alias: None
Product: kwin
Classification: Plasma
Component: core (show other bugs)
Version: unspecified
Platform: Ubuntu Linux
: NOR wishlist
Target Milestone: ---
Assignee: KWin default assignee
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-02-15 15:35 UTC by aquegg
Modified: 2024-06-06 15:15 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments
Simple programme to illustrate the problem (1.77 KB, text/x-c++src)
2012-02-15 15:35 UTC, aquegg
Details

Note You need to log in before you can comment on or make changes to this bug.
Description aquegg 2012-02-15 15:35:28 UTC
Created attachment 68824 [details]
Simple programme to illustrate the problem

Version:           unspecified (using KDE 4.8.0) 
OS:                Linux

Setting X11 bit_gravity (to prevent flicker during move with resize) does not work with kwin; it works with no window-manager (but other window-managers also have this problem).  StaticGravity & ForgetGravity appear to behave as NorthWestGravity; CenterGravity appears to work correctly when upsizing, but still has some flicker when downsizing.

Reproducible: Always

Steps to Reproduce:
Try the attached programme (build with qmake).  Repeated left-clicks move-resize the window (to observe whether or not there is flicker); right-click to cycle through 4 bit-gravity modes.

Actual Results:  
Flicker evident with all four gravity modes.

Expected Results:  
Per spec. and with no WM, flicker should occur only with NW gravity.
Comment 1 Martin Flöser 2012-02-15 17:50:41 UTC
Moving and resizing at the same time is not possible with KWin. Windows on the other hand should not play window manager. I don't see any advantage in implementing that - especially if as stated no WM does that.

Furthermore I would be surprised if that is an issue with compositing turned on. And anyway: the future is Wayland :-)
Comment 2 aquegg 2012-02-16 06:41:59 UTC
Hello Martin, I'm not sure I understand when you say that moving and resizing at the same time is not possible with KWin—it (QWidget::setGeometry) seems to work in every way other than not honouring bit_gravity.

One application that needs StaticGravity is "ShowImage", an image viewer (
http://kde-apps.org/content/show.php?content=143977).  Logically, the window is not being moved: it's being resized from the centre (commonly performed using CTRL-Mouse-wheel, or "pinch" zooming on a tablet).  ShowImage currently exhibits a lot of flicker when zooming or switching between different-sized images—bad for "User Experience".

Sorry if I wasn't clear earlier: the expected behaviour can be seen when running without a WM; the bug also occurs when running with _some_ other WMs (I had tested two others, both exhibited the bug; interesting, the failure mechanism for these WMs was identical to KWin's—maybe they are using some common ancestral code).  I've since tested with the Sawfish WM, and it behaves correctly for all gravity modes in the test.

Cheers,
Rob
Comment 3 Thomas Lübking 2012-02-16 16:13:13 UTC
He probably meant "by users" - the window is not resized, but issues a configure request. That's a difference ;-)
(Anyway, that's wrong either, resizing against the gravity is a moveResize ;-)

This is however completely irrelevant, the gravity concerning the window manager controls how windows are expanded, it has nothing to do with the content, esp. not on double buffered client painting (all modern toolkits) - the way  the content is layouted (small image with even black border or so) in the window is up to the client, NEVER to the WM.

The Resize "flicker" (glitches) occurs for only one reason:
The WM resizes the window, but the client is not yet up to with it's content.

For resizes induced by the WM, this is covered by the -finall- working XSYNC protocol implementation in KWin and Qt.
If you resize the mentioned application window from the WM (ie. eg. the decoration borders) you'll see no such glitches - at least with the raster graphicssystem (see below) and active compositing.

If the client issues a configure request, KWin however acts instantly. I've just tried compiz which seems to trigger a sync request instead as well. Probably sawfish (not installed) is doing the same - or for your testcase presumingly not paint a decoration background since it's not double reparenting.

Now on the particular client:
-----------------------------
This call: painter.drawImage(startPos, image); is a major issue:
drawImage is halfwise fast on the raster engine *only* not on the native or opengl one, so "showImage --graphicssystem raster ~/blablub.jpg" will do considerably better than "showImage --graphicssystem native ~/blablub.jpg"

The safe way for that viewer would be to
a) use WA_PaintOnScreen, WA_OpaquePaintEvent to avoid double buffering and widget erasing
b) keep the image in a QPixmap buffer
c) intercept the mousewheel, update the pixmap buffer with the rescaled image and trigger the configure request (or direct resize in case of no WM) *after*

I fixed the summary towards the XSYNC on configure requests.
Comment 4 aquegg 2012-02-18 11:32:56 UTC
(In reply to comment #3)
> The safe way for that viewer would be to
> a) use WA_PaintOnScreen, WA_OpaquePaintEvent to avoid double buffering and
> widget erasing
> b) keep the image in a QPixmap buffer
> c) intercept the mousewheel, update the pixmap buffer with the rescaled image
> and trigger the configure request (or direct resize in case of no WM) *after*
> 
> I fixed the summary towards the XSYNC on configure requests.

Updated testcase code per these suggestions (in fact preparing the rescaled image in the constructor):

#include <QApplication>
#include <QPainter>
#include <QWidget>
#include <QX11Info>
#include <X11/Xlib.h>

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);

  struct Widget: public QWidget {
    Widget(): count(0), s(400), r(s*17/80) {
      pixmaps[0] = createTestPixmap();
      pixmaps[1] = pixmaps[0].scaledToWidth(s*7/8, Qt::SmoothTransformation);
      XSetWindowAttributes att; att.bit_gravity = StaticGravity;
      XChangeWindowAttributes(QX11Info::display(), winId(), CWBitGravity, &att);
      setAttribute(Qt::WA_OpaquePaintEvent);
      setAttribute(Qt::WA_PaintOnScreen);
      resize(pixmaps[0].size()), show();
    }
    void mousePressEvent(QMouseEvent *) {
      QRect r(geometry());
      int d0(pixmaps[count&1].height()), d(pixmaps[++count&1].height() - d0);
      setGeometry(r.x() - d/2, r.y() - d/2, r.width() + d, r.height() + d);
    }
    void paintEvent(QPaintEvent *) {
      QPainter p(this);
      p.drawPixmap(0, 0, pixmaps[count & 1]);
      if (!count) p.drawText(2,20,"Click repeatedly; check for resize flicker");
    }
    QPixmap createTestPixmap() {
      QPixmap pixmap(s, s); pixmap.fill("#e0e0e0");
      QPainter p(&pixmap); p.setRenderHint(QPainter::Antialiasing, true);
      p.setPen(QPen(Qt::black, 4, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin));
      for (int j = 2; j > 0; --j) for (int i = 0; i < 6; ++i)
        p.setBrush(QBrush((Qt::GlobalColor)(18 - 6*j + i))),
        p.drawPie(s/2-j*r, s/2-j*r, 2*r*j, 2*r*j, (2*i+5*j)*30*16, 45*16);
      return pixmap;
    }
    int count, s, r;
    QPixmap pixmaps[2];
  } widget;

  return app.exec();
}

Flicker still occurs with KWin, and not with Sawfish.  Not sure if XSYNC can help, but Sawfish shows that it's not strictly necessary.
Comment 5 Thomas Lübking 2012-02-18 22:04:23 UTC
I've no compiled sawfish to take a look ->

a) you're not compositing, are you?

b) the difference is that sawfish is -probably the last- non reparenting WM, it *may* work by aligning the gravity to the parenting frame in kwin 

c) No, the XSYNC extension won't help you around this (w/o compositing anyway)

d) there's naturally no whatsoever flicker in the new demo on any composited desktop
Comment 6 Zamundaaa 2024-06-06 15:15:57 UTC
This bug report doesn't seem relevant anymore, and we won't change the code to allow apps to meddle more in window management either way.