#if defined(WIN32) || defined(_WIN32) # define WIN32_LEAN_AND_MEAN # include #elif defined(__linux__) # include # include # include #endif #include #include #if defined(WIN32) || defined(_WIN32) # include #elif defined(__linux__) # include #endif #if defined(WIN32) || defined(_WIN32) # define WINCLASS "WinAppWnd" #endif #define SAFE_RELEASE(p) if (p) { p->Release(); p = NULL; } class WinApp { public: WinApp(int width, int height, std::string& window_name) { m_width = width; m_height = height; m_window_name = window_name; #if defined(WIN32) || defined(_WIN32) m_hInstance = ::GetModuleHandle(NULL); #endif } virtual ~WinApp() { #if defined(WIN32) || defined(_WIN32) ::UnregisterClass(WINCLASS, m_hInstance); #endif } int create() { #if defined(WIN32) || defined(_WIN32) WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = &WinApp::StaticWndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = m_hInstance; wcex.hIcon = LoadIcon(0, IDI_APPLICATION); wcex.hCursor = LoadCursor(0, IDC_ARROW); wcex.hbrBackground = 0; wcex.lpszMenuName = 0L; wcex.lpszClassName = WINCLASS; wcex.hIconSm = 0; ATOM wc = ::RegisterClassEx(&wcex); RECT rc = { 0, 0, m_width, m_height }; ::AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false); m_hWnd = ::CreateWindow( (LPCTSTR)wc, m_window_name.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, m_hInstance, (void*)this); if (!m_hWnd) return -1; ::ShowWindow(m_hWnd, SW_SHOW); ::UpdateWindow(m_hWnd); ::SetFocus(m_hWnd); #elif defined(__linux__) m_display = XOpenDisplay(NULL); if (m_display == NULL) { return -1; } m_WM_DELETE_WINDOW = XInternAtom(m_display, "WM_DELETE_WINDOW", False); static GLint visual_attributes[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None }; m_visual_info = glXChooseVisual(m_display, 0, visual_attributes); if (m_visual_info == NULL) { XCloseDisplay(m_display); return -2; } Window root = DefaultRootWindow(m_display); m_event_mask = ExposureMask | KeyPressMask; XSetWindowAttributes window_attributes; window_attributes.colormap = XCreateColormap(m_display, root, m_visual_info->visual, AllocNone); window_attributes.event_mask = m_event_mask; m_window = XCreateWindow( m_display, root, 0, 0, m_width, m_height, 0, m_visual_info->depth, InputOutput, m_visual_info->visual, CWColormap | CWEventMask, &window_attributes); XMapWindow(m_display, m_window); XSetWMProtocols(m_display, m_window, &m_WM_DELETE_WINDOW, 1); XStoreName(m_display, m_window, m_window_name.c_str()); #endif return init(); } virtual void cleanup() { #if defined(WIN32) || defined(_WIN32) ::DestroyWindow(m_hWnd); #elif defined(__linux__) XDestroyWindow(m_display, m_window); XCloseDisplay(m_display); #endif } #if defined(WIN32) || defined(_WIN32) virtual LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) = 0; #endif int run() { #if defined(WIN32) || defined(_WIN32) MSG msg; ::ZeroMemory(&msg, sizeof(msg)); while (msg.message != WM_QUIT) { if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } else { idle(); } } return static_cast(msg.wParam); #elif defined(__linux__) m_end_loop = false; do { XEvent e; if (!XCheckWindowEvent(m_display, m_window, m_event_mask, &e) || !handle_event(e)) { idle(); } } while (!m_end_loop); return 0; #endif } protected: #if defined(WIN32) || defined(_WIN32) static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { WinApp* pWnd; if (message == WM_NCCREATE) { LPCREATESTRUCT pCreateStruct = ((LPCREATESTRUCT)lParam); pWnd = (WinApp*)(pCreateStruct->lpCreateParams); ::SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pWnd); } pWnd = GetObjectFromWindow(hWnd); if (pWnd) return pWnd->WndProc(hWnd, message, wParam, lParam); else return ::DefWindowProc(hWnd, message, wParam, lParam); } inline static WinApp* GetObjectFromWindow(HWND hWnd) { return (WinApp*)::GetWindowLongPtr(hWnd, GWLP_USERDATA); } #endif #if defined(__linux__) virtual int handle_event(XEvent& e) = 0; #endif virtual int init() = 0; virtual int render() = 0; virtual void idle() = 0; #if defined(WIN32) || defined(_WIN32) HINSTANCE m_hInstance; HWND m_hWnd; #elif defined(__linux__) Display* m_display; XVisualInfo* m_visual_info; Window m_window; long m_event_mask; Atom m_WM_DELETE_WINDOW; bool m_end_loop; #endif int m_width; int m_height; std::string m_window_name; };