Otherwise the window (partially) obscured by the other window sometimes fails to update when the obscuring window is moved or destroyed.
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/winex11.drv/bitblt.c | 5 +++++ dlls/winex11.drv/event.c | 1 + 2 files changed, 6 insertions(+)
diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index b530ba7ba6..ac430ef4c0 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -2106,6 +2106,11 @@ HRGN expose_surface( struct window_surface *window_surface, const RECT *rect ) region = 0; } } + else + { + region = (HRGN)1; + } + window_surface->funcs->unlock( window_surface ); return region; } diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 10d71c2cb4..6424790a62 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -941,6 +941,7 @@ static BOOL X11DRV_Expose( HWND hwnd, XEvent *xev ) { surface_region = expose_surface( data->surface, &rect ); if (!surface_region) flags = 0; + else if(surface_region == (HRGN)1) surface_region = NULL; else OffsetRgn( surface_region, data->whole_rect.left - data->client_rect.left, data->whole_rect.top - data->client_rect.top );
I am attaching a standalone test program which reliably shows a problem that the patch is solving in case I enable virtual desktop. Without virtual desktop the problem in this test is either visible or not depending on window manager used. The similar problem can also be reproduced with, e. g., destroying window instead of moving it.
On 4/3/20 15:34, Paul Gofman wrote:
Otherwise the window (partially) obscured by the other window sometimes fails to update when the obscuring window is moved or destroyed.
Signed-off-by: Paul Gofman gofmanp@gmail.com
dlls/winex11.drv/bitblt.c | 5 +++++ dlls/winex11.drv/event.c | 1 + 2 files changed, 6 insertions(+)
diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index b530ba7ba6..ac430ef4c0 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -2106,6 +2106,11 @@ HRGN expose_surface( struct window_surface *window_surface, const RECT *rect ) region = 0; } }
- else
- {
region = (HRGN)1;
- }
- window_surface->funcs->unlock( window_surface ); return region;
} diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 10d71c2cb4..6424790a62 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -941,6 +941,7 @@ static BOOL X11DRV_Expose( HWND hwnd, XEvent *xev ) { surface_region = expose_surface( data->surface, &rect ); if (!surface_region) flags = 0;
else if(surface_region == (HRGN)1) surface_region = NULL; else OffsetRgn( surface_region, data->whole_rect.left - data->client_rect.left, data->whole_rect.top - data->client_rect.top );
Paul Gofman gofmanp@gmail.com writes:
Otherwise the window (partially) obscured by the other window sometimes fails to update when the obscuring window is moved or destroyed.
That's not correct, there shouldn't be any reason to repaint the entire window when the contents are still valid.
Note that not flushing the bits right away is deliberate, that's a performance fix. The window will get repainted when the app waits for a new message.
If you have a real app where this is an issue, the heuristic could maybe be tweaked to catch that case, cf. check_for_driver_events in dlls/user32/message.c.
On 4/6/20 13:23, Alexandre Julliard wrote:
Paul Gofman gofmanp@gmail.com writes:
Otherwise the window (partially) obscured by the other window sometimes fails to update when the obscuring window is moved or destroyed.
That's not correct, there shouldn't be any reason to repaint the entire window when the contents are still valid.
Note that not flushing the bits right away is deliberate, that's a performance fix. The window will get repainted when the app waits for a new message.
If you have a real app where this is an issue, the heuristic could maybe be tweaked to catch that case, cf. check_for_driver_events in dlls/user32/message.c.
I was trying to fix menu glitches in Diablo 1. This particular patch was fixing leftover menu elements (left from previous menu when navigating). The application destroys child window and expects the parent to receive WM_PAINT with appropriate rectangle in PAINTSTRUCT. Tweaking check_for_driver_events() (or otherwise enforcing extra flush_window_surfaces()) helps drawing in my test I attached previously, but not the game. Test program (and the game) still does not receive WM_PAINT event for (partially obscured) parent window. I suppose it fixes the drawing in my test program because the bits of parent window gets restored from x11 image in x11drv_surface_flush(). But Diablo 1 does not draw on GDI surfaces. It uses user32 window management infrastructure and reacts on the window events, but all the actual drawing goes into ddraw primary surface in exclusive fullscreen mode. And it depends on receiving the WM_PAINT event the same way as on Windows to do the necessary updates. I should note that ddraw primary surface drawing currently does not work correctly as the fullscreen window gets obscured by the other windows. I use some WIP workarounds to make exclusive fullscreen mode to work.
So should I maybe think of how to introduce WM_PAINT generation from within check_for_driver_events()? Or leave this for now since exclusive fullscreen mode does not work right anyway at the moment and this is actually a bigger problem?
On 4/6/20 14:49, Paul Gofman wrote:
On 4/6/20 13:23, Alexandre Julliard wrote:
Paul Gofman gofmanp@gmail.com writes:
Otherwise the window (partially) obscured by the other window sometimes fails to update when the obscuring window is moved or destroyed.
That's not correct, there shouldn't be any reason to repaint the entire window when the contents are still valid.
Note that not flushing the bits right away is deliberate, that's a performance fix. The window will get repainted when the app waits for a new message.
If you have a real app where this is an issue, the heuristic could maybe be tweaked to catch that case, cf. check_for_driver_events in dlls/user32/message.c.
I was trying to fix menu glitches in Diablo 1. This particular patch was fixing leftover menu elements (left from previous menu when navigating). The application destroys child window and expects the parent to receive WM_PAINT with appropriate rectangle in PAINTSTRUCT. Tweaking check_for_driver_events() (or otherwise enforcing extra flush_window_surfaces()) helps drawing in my test I attached previously, but not the game. Test program (and the game) still does not receive WM_PAINT event for (partially obscured) parent window. I suppose it fixes the drawing in my test program because the bits of parent window gets restored from x11 image in x11drv_surface_flush(). But Diablo 1 does not draw on GDI surfaces. It uses user32 window management infrastructure and reacts on the window events, but all the actual drawing goes into ddraw primary surface in exclusive fullscreen mode. And it depends on receiving the WM_PAINT event the same way as on Windows to do the necessary updates. I should note that ddraw primary surface drawing currently does not work correctly as the fullscreen window gets obscured by the other windows. I use some WIP workarounds to make exclusive fullscreen mode to work.
So should I maybe think of how to introduce WM_PAINT generation from within check_for_driver_events()? Or leave this for now since exclusive fullscreen mode does not work right anyway at the moment and this is actually a bigger problem?
I have updated the test program to illustrate this. With the updated test programs, the rectangles exposed after moving or deleting obscured window are now filled with blue on Windows. If I force flush_window_surfaces() in Wine, the old window bits are restored and the exposed rectangles stay green.
Paul Gofman gofmanp@gmail.com writes:
On 4/6/20 13:23, Alexandre Julliard wrote:
Paul Gofman gofmanp@gmail.com writes:
Otherwise the window (partially) obscured by the other window sometimes fails to update when the obscuring window is moved or destroyed.
That's not correct, there shouldn't be any reason to repaint the entire window when the contents are still valid.
Note that not flushing the bits right away is deliberate, that's a performance fix. The window will get repainted when the app waits for a new message.
If you have a real app where this is an issue, the heuristic could maybe be tweaked to catch that case, cf. check_for_driver_events in dlls/user32/message.c.
I was trying to fix menu glitches in Diablo 1. This particular patch was fixing leftover menu elements (left from previous menu when navigating). The application destroys child window and expects the parent to receive WM_PAINT with appropriate rectangle in PAINTSTRUCT. Tweaking check_for_driver_events() (or otherwise enforcing extra flush_window_surfaces()) helps drawing in my test I attached previously, but not the game. Test program (and the game) still does not receive WM_PAINT event for (partially obscured) parent window. I suppose it fixes the drawing in my test program because the bits of parent window gets restored from x11 image in x11drv_surface_flush(). But Diablo 1 does not draw on GDI surfaces. It uses user32 window management infrastructure and reacts on the window events, but all the actual drawing goes into ddraw primary surface in exclusive fullscreen mode. And it depends on receiving the WM_PAINT event the same way as on Windows to do the necessary updates. I should note that ddraw primary surface drawing currently does not work correctly as the fullscreen window gets obscured by the other windows. I use some WIP workarounds to make exclusive fullscreen mode to work.
So should I maybe think of how to introduce WM_PAINT generation from within check_for_driver_events()? Or leave this for now since exclusive fullscreen mode does not work right anyway at the moment and this is actually a bigger problem?
If it's not painting to the window surface, then user32 should have been told that. Then the surface won't be used, and expose events will generate WM_PAINT messages.
On 4/6/20 15:13, Alexandre Julliard wrote:
Paul Gofman gofmanp@gmail.com writes:
If it's not painting to the window surface, then user32 should have been told that. Then the surface won't be used, and expose events will generate WM_PAINT messages.
Oh yeah, setting, e. g., client_side_graphics to FALSE in winex11.drv when I am to emulate exclusive fullscreen mode does the trick. Do you mean something like that?
But it won't help my updated test program, which does not involve any ddraw and seem to show that the window just gets WM_PAINT on obscuring window move or delete on Windows. I don't have an example of a real application depending exactly on it though.
Paul Gofman gofmanp@gmail.com writes:
On 4/6/20 15:13, Alexandre Julliard wrote:
Paul Gofman gofmanp@gmail.com writes:
If it's not painting to the window surface, then user32 should have been told that. Then the surface won't be used, and expose events will generate WM_PAINT messages.
Oh yeah, setting, e. g., client_side_graphics to FALSE in winex11.drv when I am to emulate exclusive fullscreen mode does the trick. Do you mean something like that?
Yes, except it should be done by setting a pixel format on the window.
On 4/6/20 16:59, Alexandre Julliard wrote:
Yes, except it should be done by setting a pixel format on the window.
That is already done for the ddraw window itself, but of course not for the other windows (dialogs and its controls) for which the game expects certain _PAINT messages. Do you think we can set pixel format on all the windows owned or created by the application when going exclusive fullscreen mode, or am I missing something? I am not yet sure how that could work for a general case as in theory application could have set some pixel format explicitly on some windows and expect that to be preserved.
Paul Gofman gofmanp@gmail.com writes:
On 4/6/20 16:59, Alexandre Julliard wrote:
Yes, except it should be done by setting a pixel format on the window.
That is already done for the ddraw window itself, but of course not for the other windows (dialogs and its controls) for which the game expects certain _PAINT messages. Do you think we can set pixel format on all the windows owned or created by the application when going exclusive fullscreen mode, or am I missing something? I am not yet sure how that could work for a general case as in theory application could have set some pixel format explicitly on some windows and expect that to be preserved.
If the other windows can't be painted normally, user32 will have to be told about it. The pixel format is the existing mechanism, but if that's not good enough we could add a different one of course.