Bug 368337

Summary: Consider disabling Qt::WA_OpaquePaintEvent for QSplitterHandle
Product: [Plasma] Breeze Reporter: Elvis Stansvik <elvstone>
Component: QStyleAssignee: Hugo Pereira Da Costa <hugo.pereira.da.costa>
Status: REPORTED ---    
Severity: normal CC: bugseforuns, hugo.pereira.da.costa
Priority: NOR    
Version: 5.5.5   
Target Milestone: ---   
Platform: Ubuntu   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:
Attachments: Test case source code
.pro file to build test case
Screenshot showing the artifact issue
Fusion vs Breeze with handleWidth 4

Description Elvis Stansvik 2016-09-06 13:03:16 UTC
With the attached minimal test case, I get a drawing artifact in the QGLWindow when hovering the splitter handle (see attached screenshot). This happens only with the Breeze style, but not with e.g. Fusion.

I believe it's down to Fusion disabling Qt::WA_OpaquePaintEvent for QSplitterHandle:

    http://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/styles/qfusionstyle.cpp?h=v5.5.1#n3267

Breeze does not do this:

    https://github.com/KDE/breeze/blob/v5.5.5/kstyle/breezestyle.cpp#L236

The attached minimal test case uses a QGLWidget, but I discovered the issue while trying to use a QVTKWidget (from VTK), which does its own native rendering, in a QSplitter.

I'm not sure if my analysis is correct, but if you can confirm the issue, and disabling Qt::WA_OpaquePaintEvent like Fusion does fix it, it would be great if you could do this in Breeze.

Reproducible: Always

Steps to Reproduce:
With the attached test case:

1. qmake
2. make
3. ./splittertest
4. Move the splitter handle a little to the right
5. Hover the splitter handle again with mouse

Actual Results:  
The rect of the splitter handle cursor is filled with the background color (see attached screenshot).

Expected Results:  
Only the shape of the splitter handle cursor should be shown, it should not be filled.

This was with Qt 5.5.1 on Kubuntu 16.05 using kde-style-breeze 4:5.5.5-0ubuntu1.
Comment 1 Elvis Stansvik 2016-09-06 13:04:00 UTC
Created attachment 100952 [details]
Test case source code
Comment 2 Elvis Stansvik 2016-09-06 13:04:34 UTC
Created attachment 100953 [details]
.pro file to build test case
Comment 3 Elvis Stansvik 2016-09-06 13:05:06 UTC
Created attachment 100954 [details]
Screenshot showing the artifact issue
Comment 4 Elvis Stansvik 2016-09-06 13:10:35 UTC
My analysis might not be correct, as I just tried adding

    splitter->handle(1)->setAttribute(Qt::WA_OpaquePaintEvent, false);

to the test case, and the problem remains.

I see there's something called SplitterProxy in Breeze (used under KDE, like I run). Could the bug be in there somewhere?
Comment 5 Hugo Pereira Da Costa 2016-09-06 13:13:43 UTC
Hello, 
thanks for reporting and posting the test case. This is a known issue, unfortunately unrelated to Qt::WA_OpaquePaintEvent

This is related to breeze' "extended splitter" feature (also implemented in oxygen and in some other fancy styles on the web).
The code is in breeze/kstyle/breezesplitterproxy
Basically we increasse the splitter hit region on hover to make it easier to click on, by means of an internal transparent widget, that capture mouse events.
The artifact you see is Qt not being able to properly draw this transparent internal widget on top of a GL widget (it lacks some internal compositing, I guess).
Note that the size of this widget is reduced to 1x1 when you press the mouse (which you also see, as a dot, in your test case).

Bottomline: there is not much we can do about it, except disable the feature ... (or ask qt to fix, which I am not sure is easy)
Comment 6 Elvis Stansvik 2016-09-06 13:34:57 UTC
Okay, I've now confirmed that disabling use of the SplitterProxy, by setting SplitterProxyEnabled to false in the Breeze style config, fixes the issue.

So perhaps the problem is that the splitter proxy does not set Qt::WA_Hover ?
Comment 7 Elvis Stansvik 2016-09-06 13:38:10 UTC
Sorry, posted the above comment before I read your reply.

Thanks for the fast reply, I think I understand what is going on, and I understand the rationale for the proxy (since the default splitter handle is hard to hit).

Hm, I don't know how Qt could work around this. It's quite unfortunate since we're building a product with a VTK widget for visualization, and the target platform is primarily KDE/Plasma desktops, and the proxy splitter feature is enabled by default :/
Comment 8 Hugo Pereira Da Costa 2016-09-06 13:40:59 UTC
what I can try on the style size is to peek from the application what type of widget would be below the proxy before showing it, and disable, when detecting GL (or others that would cause issue). 
I guess I'll give it a shot, using your test app. 
what do you think ?
Comment 9 Elvis Stansvik 2016-09-06 13:51:38 UTC
Ah, that could perhaps work. Though my test case just used QGLWidget because that was an easy way to make a minimal test case. In our real application it's a QVTKWidget [1], and I'm not sure which trickery it uses. I think it's actually a regular QWidget, but with a manually set up OpenGL context "on top" of it. So that might be hard to detect... Also, in our real app, the GL widget is not directly added to the splitter, it's contained in another regular QWidget, so detecting would have to traverse the widget hierarchy I think...

But if it is possible to detect, and you try such a workaround, could you perhaps make it so that the size of this invisible hit area is reduced in size only on the side facing the GL widget (could be both sides)?

On a more philosophical note, I find it strange that in Breeze the splitter handle has no visual appearance. The only way to know it is there is to hover the area and notice that the cursor changes. This means the handleWidth property of QSplitter is not really respected by Breeze. Could a better workaround perhaps be to make the splitter handle have a visual appearance? That would give the user additional guidance when trying to hit it, and perhaps the workaround with the splitter proxy / hidden hit area is then not needed?

[1] https://github.com/Kitware/VTK/blob/master/GUISupport/Qt/QVTKWidget.cxx
Comment 10 Elvis Stansvik 2016-09-06 14:33:15 UTC
Sorry, I was wrong in the above. Breeze does respect handleWidth, but the default is for it to have no width, and unlike Fusion there are no "dots" or marks on the handle to indicate it is a handle. I think if the default in Breeze was to actually have some width (4 px?) on the splitter (and maybe some markers as well), it would be easier to hit due to the visual feedback, and perhaps the invisible hit area would be unnecessary?
Comment 11 Elvis Stansvik 2017-03-26 10:29:01 UTC
As we're using more and more splitters in our application, several of them being having GL windows in them (VTK), this is becoming more and more of a problem.

The problem from the point of view of Breeze is that:

1. If the splitter handle proxy is enabled, we get artifacts (see the test case)

2. If the splitter handle proxy is disabled, it's extremely hard (~1 px hit area?) to grab the splitter handle with the mouse. It's much harder to hit than with e.g. Fusion, where the hit area is several pixels.

Could 2 perhaps be fixed somehow? So that if the proxy is disabled, Breeze could draw the handle slightly larger (visually), like Fusion does? Because as it is, if the proxy is disabled, it's almost impossible to grab the handle. But the artifacts in the GL windows when enabling the proxy are also not acceptable :/
Comment 12 Hugo Pereira Da Costa 2017-03-26 10:32:12 UTC
> Could 2 perhaps be fixed somehow? So that if the proxy is disabled, Breeze
> could draw the handle slightly larger (visually), like Fusion does? Because
> as it is, if the proxy is disabled, it's almost impossible to grab the
> handle. But the artifacts in the GL windows when enabling the proxy are also
> not acceptable :/

the solution you propose for fixing 2/ is acceptable yes. I agree that the 1px handles are unusable without the proxy.
Will do ASAP (but have limited time right now).
Comment 13 Elvis Stansvik 2017-03-26 10:42:59 UTC
Or, I should rather say:

1. With Fusion, setting handleWidth to 4, I get a handle that is 4 visually pixels wide, with a hittable area of 4 pixels.

2. With Breeze (proxy disabled), setting handleWidth to 4, I get a handle that is 6 pixels wide, but with a hittable area that is 4 pixels wide.

To work around the artifact problem, I have to disable the splitter handle proxy. 4 pixels wide is the lowest I want to go for a hittable area, but 6 pixels wide visually is a little too wide.

Could Breeze perhaps be more "compact" when the splitter handle is disabled, such that visual width == hittable width?

I'm attaching a screenshot showing some splitters @ handleWidth 4, in Fusion (in the background) and Breeze (in the foreground).
Comment 14 Elvis Stansvik 2017-03-26 10:44:00 UTC
Created attachment 104740 [details]
Fusion vs Breeze with handleWidth 4
Comment 15 Elvis Stansvik 2017-03-26 10:44:54 UTC
(In reply to Hugo Pereira Da Costa from comment #12)
> > Could 2 perhaps be fixed somehow? So that if the proxy is disabled, Breeze
> > could draw the handle slightly larger (visually), like Fusion does? Because
> > as it is, if the proxy is disabled, it's almost impossible to grab the
> > handle. But the artifacts in the GL windows when enabling the proxy are also
> > not acceptable :/
> 
> the solution you propose for fixing 2/ is acceptable yes. I agree that the
> 1px handles are unusable without the proxy.
> Will do ASAP (but have limited time right now).

Ah, great. No hurry, and our product is Ubuntu Xenial based, so I'll have to live with the Breeze version there. But good to know it'll be improved in the future.
Comment 16 Hugo Pereira Da Costa 2017-03-26 10:52:56 UTC
(In reply to Elvis Stansvik from comment #13)
> Or, I should rather say:
> 
> 1. With Fusion, setting handleWidth to 4, I get a handle that is 4 visually
> pixels wide, with a hittable area of 4 pixels.
> 
> 2. With Breeze (proxy disabled), setting handleWidth to 4, I get a handle
> that is 6 pixels wide, but with a hittable area that is 4 pixels wide.

These extra two pixels are unrelated to the presence of the handle. They are part of the widgets on both sides of the handle, and depend on the widget in used in fact. This wont change (would create many issues elsewhere)
Comment 17 Janet Blackquill 2022-02-24 00:25:51 UTC
*** Bug 444982 has been marked as a duplicate of this bug. ***