Opened 14 years ago
Closed 14 years ago
#161 closed defect (fixed)
QWidget and WS_CLIPCHILDREN
Reported by: | KO Myung-Hun | Owned by: | |
---|---|---|---|
Priority: | major | Milestone: | Qt Enhanced |
Component: | QtGui | Version: | 4.6.2 |
Severity: | high | Keywords: | |
Cc: |
Description
Hi/2.
Does QWidget honor WS_CLIPCHILDREN ?
I attached a child window to a QWidget and the window style of QWidget was modified to include WS_CLIPCHILDREN.
Nevertheless, QWidget paints over the child window.
Change History (11)
follow-up: 2 comment:1 by , 14 years ago
comment:2 by , 14 years ago
Replying to dmik:
And I also doubt that changing the WS_CLIPCHILDREN flag on the existing HWND actually affects its behavior (though I never checked that myself).
I confirmed. It works.
What are you trying to do? Embed your own HWND as a child of the top-level QWidget? This should work w/o playing with WS_CLIPCHILDREN and if it doesn't then it's a bug that needs to be fixed. And I guess I know why it doesn't work: in alien mode, WM_PAINT is by far not the only place where widget drawing occurs (Qt has its own paint messages) but child widget clipping area detection is done only in WM_PAINT.
Of course, it works without WS_CLIPCHILDREN. But I want to make sure a parent window does not paint over my window. In practice, without this flag, some window overwrites over my window.
I think that in order to fix the problem we need to call qt_WinProcessWindowObstacles() in QRasterWindowSurface::flush() and in QPMDiveWindowSurface::flush() and set the returned region as the clipping region of the target HPS (or exclude it from the area to be updated in DIVE mode).
Good.
Could you please provide a simple test case that embeds a child HWND to the top-level QWidget? I will look at it when I've got a bit of time (I'm primarily focused on the different project ATM).
Ok. You can use SMPlayer.
- Launch SMPlayer
- Find the hwnd of the movie window of SMPlayer. You can use X-Ray(http://hobbes.nmsu.edu/download/pub/os2/util/wps/xray10.zip)
- Launch the updated MPlayer(http://www.ecomstation.co.kr/komh/testcase/mplayer_test.zip) as the following.
mplayer -wid hwnd_id test.avi
where, hwnd_id is hwnd - 0x80000000.
- And click the right button of mouse to raise the popup menu.
- Clear popup menu
- Now movie window is overwritten.
comment:3 by , 14 years ago
Okay, I performed the test. Here, it looks like r745 fixed this issue. The only thing what I see is that the movie icon located in the center of the movie window gets overwritten -- but that's probably expected (as well as black flashing background when you activate/deactivate the smplayer window) because of the lack of proper clipping as I described above. I will try to fix it now too.
comment:4 by , 14 years ago
In r751, I got the clipping of children working in DIVE mode so that there is no flashing movie window icon/background in the above testcase. Please check how it works for you. Note that there is still one minor redraw problem though which you can see when playing a movie from within SMPlayer (using the same test mplayer executable) -- at the beginning of the playback the movie window gets strangely resized back and forth which causes the main window to resize as well and this leaves a tiny strip right under the movie not redrawn after this resize. This problem goes away if I ignore the vrnDirty flag and reconstruct the visible region at each paint which means that we lack some proper visible region change notification from PM again. I will try to figure that out.
Note that in non-Dive mode, you will still see the flashing background since I didn't apply clipping children to that code path; it will be done later, after I figure out the repaint problem mentioned above.
comment:5 by , 14 years ago
I think I found a trick to fix the not repainted strip after the resize. At least, after r753, I don't see it any more.
comment:6 by , 14 years ago
I've tested with r753. And it works well with DIVE.
But if I set QT_PM_NO_DIVE=1, the overwritten problem still exists.
comment:7 by , 14 years ago
Thank you for testing.
Yes, this is what I wrote in the last paragraph of comment 4. I will apply the fix to this code path when I have more time.
We don't use WS_CLIPCHILDREN at all. The explanation is in qwidget_pm.cpp -- though it's mostly true for Qt3 since in Qt4 we don't fully implement non-rectangular child widgets in native mode (this mode means that each child Qt widget is a separate PM window while in Qt4 by default child widgets are "alien" windows that share the HWND with their top-level ancestor and are copmletely controlled by Qt in all aspects including painting, clipping and z-order, so that no special handling for non-rectangular widgets is needed at all).
And I also doubt that changing the WS_CLIPCHILDREN flag on the existing HWND actually affects its behavior (though I never checked that myself).
What are you trying to do? Embed your own HWND as a child of the top-level QWidget? This should work w/o playing with WS_CLIPCHILDREN and if it doesn't then it's a bug that needs to be fixed. And I guess I know why it doesn't work: in alien mode, WM_PAINT is by far not the only place where widget drawing occurs (Qt has its own paint messages) but child widget clipping area detection is done only in WM_PAINT.
I think that in order to fix the problem we need to call qt_WinProcessWindowObstacles() in QRasterWindowSurface::flush() and in QPMDiveWindowSurface::flush() and set the returned region as the clipping region of the target HPS (or exclude it from the area to be updated in DIVE mode).
Could you please provide a simple test case that embeds a child HWND to the top-level QWidget? I will look at it when I've got a bit of time (I'm primarily focused on the different project ATM).