Very controlled GDIplus startup and shutdown #635 (#679)

Fall back to GDI if GDIplus is not available
This commit is contained in:
Matthias Melcher 2023-02-11 19:14:23 +01:00 committed by GitHub
parent 740c56ce15
commit 5a25641317
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 5 deletions

4
.gitignore vendored
View File

@ -90,3 +90,7 @@ src/xdg-shell-protocol.c
# libdecor/build/demo
# libdecor/build/egl
/out/build/x64-Debug/.cmake/api/v1/query/client-MicrosoftVS/query.json
/out/build/x64-Debug
/CMakeSettings.json
/CppProperties.json

View File

@ -182,7 +182,16 @@ private:
Gdiplus::Color gdiplus_color_;
Gdiplus::Pen *pen_;
Gdiplus::SolidBrush *brush_;
static ULONG_PTR gdiplusToken;
// The code below ensures the a connection to GDIplus is only made once, and that the
// matching connection shutdown is also done exactly once.
enum {
STATE_CLOSED = 0, // no connection, token is invalid
STATE_STARTUP, // attempt to start up, avoid recursions for whatever reason
STATE_OPEN, // connection was successful and the token is valid
STATE_SHUTDOWN // shutting down the gdi connection, avoid possible recursion
};
static int gdiplus_state_; // reflect the state of the GDIplus driver connection
static ULONG_PTR gdiplus_token_; // the token that GDIplus gives to us
public:
Fl_GDIplus_Graphics_Driver();
virtual ~Fl_GDIplus_Graphics_Driver();

View File

@ -53,10 +53,22 @@ int Fl_GDIplus_Graphics_Driver::antialias() {
#if USE_GDIPLUS
ULONG_PTR Fl_GDIplus_Graphics_Driver::gdiplusToken = 0;
int Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_CLOSED;
ULONG_PTR Fl_GDIplus_Graphics_Driver::gdiplus_token_ = 0;
void Fl_GDIplus_Graphics_Driver::shutdown() {
Gdiplus::GdiplusShutdown(Fl_GDIplus_Graphics_Driver::gdiplusToken);
if (gdiplus_state_ == STATE_OPEN) {
gdiplus_state_ = STATE_SHUTDOWN;
Gdiplus::GdiplusShutdown(Fl_GDIplus_Graphics_Driver::gdiplus_token_);
gdiplus_token_ = 0;
gdiplus_state_ = STATE_CLOSED;
} else if (gdiplus_state_ == STATE_CLOSED) {
// Fl::warning("Fl_GDIplus_Graphics_Driver::shutdown() called, but driver is closed.");
} else if (gdiplus_state_ == STATE_SHUTDOWN) {
// Fl::warning("Fl_GDIplus_Graphics_Driver::shutdown() called recursively.");
} else if (gdiplus_state_ == STATE_STARTUP) {
// Fl::warning("Fl_GDIplus_Graphics_Driver::shutdown() called while driver is starting up.");
}
}
#endif

View File

@ -34,8 +34,22 @@ Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
#if USE_GDIPLUS
// Initialize GDI+.
static Gdiplus::GdiplusStartupInput gdiplusStartupInput;
if (Fl_GDIplus_Graphics_Driver::gdiplusToken == 0) {
GdiplusStartup(&Fl_GDIplus_Graphics_Driver::gdiplusToken, &gdiplusStartupInput, NULL);
if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_CLOSED) {
Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_STARTUP;
Gdiplus::Status ret = GdiplusStartup(&Fl_GDIplus_Graphics_Driver::gdiplus_token_, &gdiplusStartupInput, NULL);
if (ret == Gdiplus::Status::Ok) {
Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_OPEN;
} else {
Fl::warning("GdiplusStartup failed with error code %d.", ret);
Fl_GDIplus_Graphics_Driver::gdiplus_state_ = Fl_GDIplus_Graphics_Driver::STATE_CLOSED;
return new Fl_GDI_Graphics_Driver();
}
} else if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_OPEN) {
// Fl::warning("GdiplusStartup() called, but driver is already open.");
} else if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_SHUTDOWN) {
// Fl::warning("GdiplusStartup() called while driver is shutting down.");
} else if (Fl_GDIplus_Graphics_Driver::gdiplus_state_ == Fl_GDIplus_Graphics_Driver::STATE_STARTUP) {
// Fl::warning("GdiplusStartup() called recursively.");
}
Fl_Graphics_Driver *driver = new Fl_GDIplus_Graphics_Driver();
return driver;