Workarounds to re-display windows on MS Windows.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@38367 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
espectador 2015-02-28 02:01:28 +00:00
parent dec8b7b7e4
commit dd0c80e167
4 changed files with 150 additions and 89 deletions

View file

@ -1,3 +1,20 @@
2015-02-27 Germán Arias <germanandre@gmx.es>
* Source/cairo/CairoContext.m (-flushGraphics:):
* Source/cairo/Win32CairoSurface.m (-initWithDevice:): Apply fix
from TestPlant branch to solve problem with windows with backing
store type NSBackingStoreRetained, which are not displayed correclty
on MS Windows. With this fix those windows are displayed as
buffered windows.
* Source/win32/WIN32Server.m (-setWindowdevice:forContext:): The
windows with autodisplay set to NO aren't displayed correctly on
Windows, no matter the backing store type used. And trying to
redisplay these windows here in the server not takes effect. So if
the window have set autodisplay to NO, we change it to YES before
create the window. This problem affects the tooltips, but this
solution is different to the one used in the TestPlant branch.
Because that solution involves changes in the side of GUI.
2014-10-25 Fred Kiefer <FredKiefer@gmx.de>
* Source/cairo/CairoGState.m (-compositeGState:...fraction:):

View file

@ -60,6 +60,8 @@
#elif BUILD_SERVER == SERVER_win32
# include "cairo/Win32CairoGState.h"
# include <windows.h>
# include "win32/WIN32Server.h"
# include "win32/WIN32Geometry.h"
# define _CAIRO_GSTATE_CLASSNAME Win32CairoGState
# ifdef USE_GLITZ
# define _CAIRO_SURFACE_CLASSNAME Win32CairoGlitzSurface
@ -107,6 +109,20 @@
- (void) flushGraphics
{
// FIXME: Why is this here? When is it called?
// Comments added 07/20/2013 to address the above question after
// further debugging cairo/MSwindows non-retained backing store type:
// This is called from NSWindow/flushWindow for the non-retained backing
// store case. This code originally seems to have been added due to the
// non-retained backing store type NOT showing up on XWindows/Cairo
// combination and added this XFlush call to handle this case.
// For MSWindows a similar problem seems to occur. However, the only
// equivalent to XFlush on MSWindows is GdiFlush, which doesn't cause
// the window to re-display properly. So, on MSWindows, the non-retained
// cairo backend surface is currently excluded from the build and we
// handle it as a buffered window expose event for now.
// FIXME: Anyone know how this can be handled/fixed correctly...
#if BUILD_SERVER == SERVER_x11
XFlush([(XGServer *)server xDisplay]);
#elif BUILD_SERVER == SERVER_win32
@ -115,9 +131,16 @@
[CGSTATE GSCurrentSurface: &surface : NULL : NULL];
if ((surface != nil) && ([surface surface] != NULL))
{
cairo_surface_flush([surface surface]);
// Non-retained backing store types currently unsupported on MSWindows...
// Currently handling such windows as buffered and invoking the handle
// expose event processing...
RECT rect;
HWND hwnd = surface->gsDevice;
GetClientRect(hwnd, &rect);
NSRect frame = MSWindowRectToGS((WIN32Server*)GSCurrentServer(), hwnd, rect);
[[self class] handleExposeRect: frame forDriver: surface];
}
#endif // BUILD_SERVER = SERVER_x11
#endif
}

View file

@ -37,101 +37,107 @@
- (id) initWithDevice: (void *)device
{
WIN_INTERN *win = (WIN_INTERN *)GetWindowLong((HWND)device, GWL_USERDATA);
HDC hDC = GetDC((HWND)device);
if (self)
{
WIN_INTERN *win = (WIN_INTERN *)GetWindowLong((HWND)device, GWL_USERDATA);
HDC hDC = GetDC((HWND)device);
// Save/set initial state...
gsDevice = device;
_surface = NULL;
// Save/set initial state...
gsDevice = device;
_surface = NULL;
if (hDC == NULL)
{
NSWarnMLog(@"Win32CairoSurface line: %d : no device context", __LINE__);
if (hDC == NULL)
{
NSWarnMLog(@"Win32CairoSurface line: %d : no device context", __LINE__);
// And deallocate ourselves...
DESTROY(self);
}
else
{
// Create the cairo surfaces...
// NSBackingStoreRetained works like Buffered since 10.5 (See apple docs)...
// NOTE: According to Apple docs NSBackingStoreBuffered should be the only one
// ever used anymore....others are NOT recommended...
if (win && (win->type == NSBackingStoreNonretained))
{
// This is the raw DC surface...
_surface = cairo_win32_surface_create(hDC);
// Check for error...
if (cairo_surface_status(_surface) != CAIRO_STATUS_SUCCESS)
{
// Output the surface create error...
cairo_status_t status = cairo_surface_status(_surface);
NSWarnMLog(@"surface create FAILED - status: %s\n", cairo_status_to_string(status));
// Destroy the initial surface created...
cairo_surface_destroy(_surface);
// And deallocate ourselves...
DESTROY(self);
}
}
// And deallocate ourselves...
DESTROY(self);
}
else
{
NSSize csize = [self size];
// This is the raw DC surface...
cairo_surface_t *window = cairo_win32_surface_create(hDC);
cairo_status_t status = cairo_surface_status(window);
// Check for error...
if (status != CAIRO_STATUS_SUCCESS)
{
// Output the surface create error...
NSWarnMLog(@"surface create FAILED - status: %s\n", cairo_status_to_string(status));
{
// Create the cairo surfaces...
// NSBackingStoreRetained works like Buffered since 10.5 (See apple docs)...
// NOTE: According to Apple docs NSBackingStoreBuffered should be the only one
// ever used anymore....others are NOT recommended...
if (win && (win->type == NSBackingStoreNonretained))
{
// This is the raw DC surface...
_surface = cairo_win32_surface_create(hDC);
// Check for error...
if (cairo_surface_status(_surface) != CAIRO_STATUS_SUCCESS)
{
// Output the surface create error...
cairo_status_t status = cairo_surface_status(_surface);
NSWarnMLog(@"surface create FAILED - status: %s\n", cairo_status_to_string(status));
// And deallocate ourselves...
DESTROY(self);
}
else
{
// and this is the in-memory DC surface...surface owns its DC...
// NOTE: For some reason we get an init sequence with zero width/height,
// which creates problems in the cairo layer. It tries to clear
// the 'similar' surface it's creating, and with a zero width/height
// it incorrectly thinks the clear failed...so we will init with
// a minimum size of 1 for width/height...
_surface = cairo_surface_create_similar(window, CAIRO_CONTENT_COLOR_ALPHA,
MAX(1, csize.width),
MAX(1, csize.height));
status = cairo_surface_status(_surface);
// Destroy the initial surface created...
cairo_surface_destroy(_surface);
// And deallocate ourselves...
DESTROY(self);
// Check for error...
if (status != CAIRO_STATUS_SUCCESS)
{
// Output the surface create error...
NSWarnMLog(@"surface create FAILED - status: %s\n", cairo_status_to_string(status));
// Destroy the surface created...
cairo_surface_destroy(_surface);
// And deallocate ourselves...
DESTROY(self);
}
}
// Release the device context...
ReleaseDC(device, hDC);
}
}
else
{
NSSize csize = [self size];
// Destroy the initial surface created...
cairo_surface_destroy(window);
}
// Release the device context...
ReleaseDC((HWND)device, hDC);
// This is the raw DC surface...
cairo_surface_t *window = cairo_win32_surface_create(hDC);
if (win && self)
{
// We need this for handleExposeEvent in WIN32Server...
win->surface = (void*)self;
}
// Check for error...
if (cairo_surface_status(window) != CAIRO_STATUS_SUCCESS)
{
// Output the surface create error...
cairo_status_t status = cairo_surface_status(window);
NSWarnMLog(@"surface create FAILED - status: %s\n", cairo_status_to_string(status));
// And deallocate ourselves...
DESTROY(self);
}
else
{
// and this is the in-memory DC surface...surface owns its DC...
// NOTE: For some reason we get an init sequence with zero width/height,
// which creates problems in the cairo layer. It tries to clear
// the 'similar' surface it's creating, and with a zero width/height
// it incorrectly thinks the clear failed...so we will init with
// a minimum size of 1 for width/height...
_surface = cairo_surface_create_similar(window, CAIRO_CONTENT_COLOR_ALPHA,
MAX(1, csize.width),
MAX(1, csize.height));
cairo_status_t status = cairo_surface_status(_surface);
// Check for error...
if (status != CAIRO_STATUS_SUCCESS)
{
// Output the surface create error...
NSWarnMLog(@"surface create FAILED - status: %s\n", cairo_status_to_string(status));
// Destroy the surface created...
cairo_surface_destroy(_surface);
// And deallocate ourselves...
DESTROY(self);
}
}
// Destroy the initial surface created...
cairo_surface_destroy(window);
// Release the device context...
ReleaseDC((HWND)device, hDC);
}
if (win && self)
{
// We need this for handleExposeEvent in WIN32Server...
win->surface = (void*)self;
}
}
}
return self;

View file

@ -1705,6 +1705,21 @@ LRESULT CALLBACK windowEnumCallback(HWND hwnd, LPARAM lParam)
NSDebugLLog(@"WTrace", @"windowdevice: %d", winNum);
window = GSWindowWithNumber(winNum);
/* FIXME:
* The windows with autodisplay set to NO aren't displayed correctly on
* Windows, no matter the backing store type used. And trying to redisplay
* these windows here in the server not takes effect. So if the window
* have set autodisplay to NO, we change it to YES before create the window.
* This problem affects the tooltips, but this solution is different to
* the one used in the TestPlant branch. Because that solution involves
* changes in the side of GUI.
*/
if (![window isAutodisplay])
{
[window setAutodisplay: YES];
}
GetClientRect((HWND)winNum, &rect);
h = rect.bottom - rect.top;
[self styleoffsets: &l : &r : &t : &b : [window styleMask]];