diff --git a/CMakeLists.txt b/CMakeLists.txt index 690f06a..f7b5d5c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ install(FILES DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" COMPONENT sourcemeta_native) +# TODO(tonygo): hide this in a native macro install(FILES # Install native functions like (native_add_app, native_set_profile) "${CMAKE_CURRENT_SOURCE_DIR}/cmake/native.cmake" diff --git a/cmake/native.cmake b/cmake/native.cmake index 94eee55..08c2187 100644 --- a/cmake/native.cmake +++ b/cmake/native.cmake @@ -153,7 +153,7 @@ endfunction() # function(_native_add_app_win32) - cmake_parse_arguments(NATIVE "" "TARGET;PLATFORM" "SOURCES" ${ARGN}) + cmake_parse_arguments(NATIVE "" "TARGET;PLATFORM" "SOURCES;MODULES" ${ARGN}) add_executable(${NATIVE_TARGET} WIN32 ${NATIVE_SOURCES}) @@ -180,4 +180,20 @@ function(_native_set_profile_win32) target_sources(${NATIVE_PROPERTIES_TARGET} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/resource.rc" ) + + # Iterate over the modules and link them + foreach(module IN LISTS NATIVE_PROPERTIES_MODULES) + _native_link_modules_win32(TARGET ${NATIVE_PROPERTIES_TARGET} MODULE ${module}) + endforeach() +endfunction() + +function(_native_link_modules_win32) + cmake_parse_arguments(NATIVE_MODULE "" "TARGET;MODULE" "" ${ARGN}) + + # Link the module to the target + if(${NATIVE_MODULE_MODULE} STREQUAL "ui/window") + target_link_libraries(${NATIVE_MODULE_TARGET} sourcemeta::native::window::win32) + else() + message(WARNING "Unknown module: ${NATIVE_MODULE_MODULE}") + endif() endfunction() diff --git a/config.cmake.in b/config.cmake.in index 4efff12..9a97d54 100644 --- a/config.cmake.in +++ b/config.cmake.in @@ -8,7 +8,8 @@ list(APPEND COMPONENTS "args_foundation") elseif (WIN32) list(APPEND COMPONENTS - "application_win32") + "application_win32" + "window_win32") endif() # Include the native.cmake file diff --git a/example/hello_world/hello_world.cc b/example/hello_world/hello_world.cc index 7e446a8..140d674 100644 --- a/example/hello_world/hello_world.cc +++ b/example/hello_world/hello_world.cc @@ -1,8 +1,5 @@ #include - -#ifdef __APPLE__ // Temporary until window module is available for windows #include -#endif #include #include @@ -14,20 +11,16 @@ class App : public sourcemeta::native::Application { auto on_ready() -> void override { std::cout << "Ready!" << std::endl; -#ifdef __APPLE__ // Temporary window.size(800, 600); window.show(); -#endif this->exit(); } auto on_error(std::exception_ptr) noexcept -> void override {} -#ifdef __APPLE__ // Temporary private: sourcemeta::native::Window window; -#endif }; NATIVE_RUN(App) diff --git a/src/application/win32/CMakeLists.txt b/src/application/win32/CMakeLists.txt index 97699cf..f1b30fb 100644 --- a/src/application/win32/CMakeLists.txt +++ b/src/application/win32/CMakeLists.txt @@ -5,7 +5,7 @@ noa_library( VARIANT win32 FOLDER "Native/Application" PRIVATE_HEADERS entry.h - SOURCES app_win32.cc delegate_win32.h delegate_win32.cc) + SOURCES app_win32.cc) noa_library_install( NAMESPACE sourcemeta diff --git a/src/application/win32/app_win32.cc b/src/application/win32/app_win32.cc index 809892e..91c28fd 100644 --- a/src/application/win32/app_win32.cc +++ b/src/application/win32/app_win32.cc @@ -2,8 +2,6 @@ #include -#include "delegate_win32.h" - #include #include #include @@ -19,12 +17,7 @@ Application::Application() { instance_ = this; } -Application::~Application() { - if (internal_) { - // DestroyWindow(static_cast(internal_)); - } - instance_ = nullptr; -} +Application::~Application() { instance_ = nullptr; } Application &Application::instance() { assert(instance_); @@ -44,33 +37,6 @@ auto Application::run() noexcept -> int { this->on_error(std::current_exception()); } - const char CLASS_NAME[] = "NativeWin32ApplicationClass"; - - WNDCLASS wc = {}; - wc.lpfnWndProc = AppDelegate::WindowProc; - wc.hInstance = GetModuleHandle(NULL); - wc.lpszClassName = CLASS_NAME; - - if (!RegisterClass(&wc)) { - on_error(std::make_exception_ptr( - std::runtime_error("Failed to register window class"))); - return EXIT_FAILURE; - } - - HWND hwnd = - CreateWindowEx(0, CLASS_NAME, "Win32 Application", WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - NULL, NULL, GetModuleHandle(NULL), NULL); - - if (hwnd == NULL) { - on_error( - std::make_exception_ptr(std::runtime_error("Failed to create window"))); - return EXIT_FAILURE; - } - - internal_ = hwnd; - ShowWindow(hwnd, SW_SHOW); - MSG msg = {}; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); diff --git a/src/application/win32/delegate_win32.cc b/src/application/win32/delegate_win32.cc deleted file mode 100644 index 6b778f7..0000000 --- a/src/application/win32/delegate_win32.cc +++ /dev/null @@ -1,36 +0,0 @@ -#include - -#include - -#include "delegate_win32.h" - -namespace sourcemeta::native { - -LRESULT CALLBACK AppDelegate::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, - LPARAM lParam) { - switch (uMsg) { - case WM_CREATE: - return 0; - case WM_DESTROY: - PostQuitMessage(0); - return 0; - case WM_PAINT: { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hwnd, &ps); - FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1)); - EndPaint(hwnd, &ps); - } - return 0; - } - return DefWindowProc(hwnd, uMsg, wParam, lParam); -} - -auto ApplicationInternals::on_ready() -> void { - sourcemeta::native::Application::instance().on_ready(); -} - -auto ApplicationInternals::on_error(std::exception_ptr error) noexcept -> void { - sourcemeta::native::Application::instance().on_error(error); -} - -} // namespace sourcemeta::native diff --git a/src/application/win32/delegate_win32.h b/src/application/win32/delegate_win32.h deleted file mode 100644 index a6f6582..0000000 --- a/src/application/win32/delegate_win32.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SOURCEMETA_NATIVE_APPLICATION_WIN32_DELEGATE_H -#define SOURCEMETA_NATIVE_APPLICATION_WIN32_DELEGATE_H - -#include -#include - -namespace sourcemeta::native { - -class AppDelegate { -public: - static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, - LPARAM lParam); -}; - -struct ApplicationInternals { - static auto on_ready() -> void; - static auto on_error(std::exception_ptr error) noexcept -> void; -}; - -} // namespace sourcemeta::native - -#endif diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index cbabe65..ca37017 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -1,3 +1 @@ -if(APPLE) - add_subdirectory(window) -endif() +add_subdirectory(window) diff --git a/src/ui/window/CMakeLists.txt b/src/ui/window/CMakeLists.txt index 3ffb82a..2839711 100644 --- a/src/ui/window/CMakeLists.txt +++ b/src/ui/window/CMakeLists.txt @@ -1,3 +1,5 @@ if(APPLE) add_subdirectory(appkit) +elseif(WIN32) + add_subdirectory(win32) endif() diff --git a/src/ui/window/win32/CMakeLists.txt b/src/ui/window/win32/CMakeLists.txt new file mode 100644 index 0000000..5d35bb5 --- /dev/null +++ b/src/ui/window/win32/CMakeLists.txt @@ -0,0 +1,13 @@ +noa_library( + NAMESPACE sourcemeta + PROJECT native + NAME window + VARIANT win32 + FOLDER "Native/Ui/Window" + SOURCES window_win32.cc) + +noa_library_install( + NAMESPACE sourcemeta + PROJECT native + NAME window + VARIANT win32) diff --git a/src/ui/window/win32/window_win32.cc b/src/ui/window/win32/window_win32.cc new file mode 100644 index 0000000..801b4ee --- /dev/null +++ b/src/ui/window/win32/window_win32.cc @@ -0,0 +1,41 @@ +#include +#include + +namespace sourcemeta::native { + +Window::Window() : internal_(nullptr) { + const char CLASS_NAME[] = "NativeWin32WindowClass"; + + WNDCLASS wc = {}; + wc.lpfnWndProc = DefWindowProc; // Use default window procedure for now + wc.hInstance = GetModuleHandle(NULL); + wc.lpszClassName = CLASS_NAME; + RegisterClass(&wc); + + // TODO(tony): add parameter for title + HWND hwnd = + CreateWindowEx(0, CLASS_NAME, "Window Title", WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, // Parent window + NULL, // Menu + GetModuleHandle(NULL), NULL); + + internal_ = hwnd; +} + +Window::~Window() { + if (internal_) { + DestroyWindow(static_cast(internal_)); + } +} + +auto Window::size(const unsigned int width, const unsigned int height) -> void { + SetWindowPos(static_cast(internal_), NULL, 0, 0, // Ignore position + width, height, SWP_NOMOVE | SWP_NOZORDER); +} + +auto Window::show() -> void { + ShowWindow(static_cast(internal_), SW_SHOW); +} + +} // namespace sourcemeta::native