8c34841f |
/// Guards
#ifdef GLBACKEND_WXWIDGETS
/// Includes
#include <glbackend_wxwidgets.hpp>
#include <array>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <glbase.hpp>
#include <glbackend.hpp>
// #include <wx/wx.h>
#include <wx/app.h>
#include <wx/defs.h>
#include <wx/display.h>
#include <wx/event.h>
#include <wx/frame.h>
#include <wx/glcanvas.h>
#include <wx/init.h>
#include <wx/platinfo.h>
#include <wx/string.h>
#include <wx/tbarbase.h>
#include <wx/toplevel.h>
#include <wx/utils.h>
#include <wx/version.h>
#include <wx/versioninfo.h>
#include <wx/vidmode.h>
#include <wx/window.h>
#include <wx/windowid.h>
// NOLINTNEXTLINE
#define STR_EXCEPTION GLBase::Exception
#include <str.hpp>
namespace
{
class Canvas : public wxGLCanvas
{
public:
Canvas(
wxWindow * parent,
wxWindowID id,
int const * attribs,
wxPoint const & pos,
wxSize const & size
)
:
wxGLCanvas(parent, id, attribs, pos, size)
{}
protected:
// TODO(rcrnstn): Implement wxWidgets event handling.
// void paint_(wxPaintEvent& event);
// void size_(wxSizeEvent& event);
// void char_(wxKeyEvent& event);
// void mouse_event_(wxMouseEvent& event);
// void exit_(wxCommandEvent& event);
wxDECLARE_EVENT_TABLE(); // NOLINT
};
}
// TODO(rcrnstn): Implement wxWidgets event handling.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
wxBEGIN_EVENT_TABLE(Canvas, wxGLCanvas) // NOLINT
// EVT_PAINT(Canvas::paint_)
wxEND_EVENT_TABLE() // NOLINT
#pragma GCC diagnostic pop
GLBackendWxWidgets::GLBackendWxWidgets(
std::string const & title,
std::array<int, 2> size,
std::array<int, 2> version,
int samples,
bool fullscreen,
bool transparent
)
:
GLBackend(),
app_ {nullptr},
frame_ {nullptr},
canvas_ {nullptr},
context_ {nullptr},
event_loop_{},
time_ {0.0F},
locked_ {false}
{
// Backend init
if (!wxApp::GetInstance())
{
wxDISABLE_DEBUG_SUPPORT();
wxApp::SetInitializerFunction([]()
{
// cppcheck-suppress cstyleCast
return (wxAppConsole *)new wxApp;
});
auto argc = int{0};
auto argv = std::array<char *, 1>{{nullptr}};
if (!wxEntryStart(argc, &argv[0]))
STR_THROW("Failed to initialize wxWidgets.");
app_ = wxApp::GetInstance();
app_->OnInit();
}
// Window options
auto frame_style = long{0}; // NOLINT
frame_style |= wxDEFAULT_FRAME_STYLE; // NOLINT
frame_style &= ~(wxRESIZE_BORDER | wxMAXIMIZE_BOX); // NOLINT
frame_style |= wxWANTS_CHARS; // NOLINT
if (transparent)
{
frame_style &= ~wxDEFAULT_FRAME_STYLE; // NOLINT
frame_style |= wxSTAY_ON_TOP; // NOLINT
}
if (size[0] == 0 || size[1] == 0)
{
auto const mode = wxDisplay(0).GetCurrentMode();
size[0] = mode.GetWidth();
size[1] = mode.GetHeight();
}
size_ = size;
// Context options
auto canvas_attribs = std::vector<int>{};
//NOLINTNEXTLINE
#define GLBACKEND_WXWIDGETS_CANVAS_ATTRIBS_INSERT_(...) \
canvas_attribs.insert(canvas_attribs.end(), __VA_ARGS__);
GLBACKEND_WXWIDGETS_CANVAS_ATTRIBS_INSERT_({
WX_GL_RGBA,
WX_GL_DOUBLEBUFFER,
WX_GL_MIN_RED, 8,
WX_GL_MIN_GREEN, 8,
WX_GL_MIN_BLUE, 8,
WX_GL_MIN_ALPHA, 8,
WX_GL_DEPTH_SIZE, 24,
WX_GL_STENCIL_SIZE, 8,
})
if (samples)
GLBACKEND_WXWIDGETS_CANVAS_ATTRIBS_INSERT_({
WX_GL_SAMPLE_BUFFERS, 1,
WX_GL_SAMPLES, samples,
})
if (version[0])
GLBACKEND_WXWIDGETS_CANVAS_ATTRIBS_INSERT_({
WX_GL_MAJOR_VERSION, version[0],
})
if (version[1])
GLBACKEND_WXWIDGETS_CANVAS_ATTRIBS_INSERT_({
WX_GL_MINOR_VERSION, version[1],
})
if ((version[0] == 3 && version[1] >= 2) || version[0] >= 4) // NOLINT
GLBACKEND_WXWIDGETS_CANVAS_ATTRIBS_INSERT_({
WX_GL_CORE_PROFILE,
})
GLBACKEND_WXWIDGETS_CANVAS_ATTRIBS_INSERT_({
0
});
try
{
// Frame
frame_ = new wxFrame(); // NOLINT
if (transparent)
frame_->SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
frame_->Create(
nullptr,
wxID_ANY,
title,
wxDefaultPosition,
wxDefaultSize,
frame_style
);
frame_->SetClientSize(size[0], size[1]);
if (fullscreen)
frame_->ShowFullScreen(true);
else
frame_->Show(true);
// Canvas
canvas_ = new Canvas{ // NOLINT
frame_,
wxID_ANY,
&canvas_attribs[0],
wxDefaultPosition,
{size[0], size[1]},
};
// Context
context_ = new wxGLContext(canvas_); // NOLINT
events(); // NOLINT
context_->SetCurrent(*canvas_);
init_();
// Lock
if (fullscreen)
lock(true);
}
catch (...)
{
destroy_();
throw;
}
}
GLBackendWxWidgets::~GLBackendWxWidgets()
{
destroy_();
}
std::string GLBackendWxWidgets::debug_info() const
{
auto ostream = std::ostringstream{};
auto version_compiled = wxGetLibraryVersionInfo().GetVersionString();
auto version_linked = wxString(wxVERSION_STRING);
auto os = wxGetOsDescription();
auto port = wxPlatformInfo::Get().GetPortIdName();
debug_info_(ostream, "wxWidgets", {
{"VERSION_COMPILED", version_compiled.ToStdString()},
{"VERSION_LINKED", version_linked .ToStdString()},
{"OS", os .ToStdString()},
{"PORT", port .ToStdString()},
});
ostream << GLBackend::debug_info();
return ostream.str();
}
// TODO(rcrnstn): Implement wxWidgets event handling.
// void GLBackendWxWidgets::paint_(wxPaintEvent& WXUNUSED(event))
// {
// wxPaintDC paint_dc(this);
// if (render_)
// render_();
// }
void GLBackendWxWidgets::destroy_()
{
delete context_;
if (canvas_)
{
lock(false);
canvas_->Destroy();
}
if (frame_)
frame_->Destroy();
events(); // NOLINT
if (app_)
{
app_->OnExit();
wxEntryCleanup();
}
}
/// Guards
#endif
|