Initial commit

This commit is contained in:
William McVicar
2023-05-04 22:33:04 +02:00
committed by GitHub
commit 34126c21a2
22 changed files with 849 additions and 0 deletions

148
.clang-format Normal file
View File

@@ -0,0 +1,148 @@
---
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: DontAlign
AlignConsecutiveAssignments: false
AlignConsecutiveBitFields: false
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: false
AlignEscapedNewlines: DontAlign
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: Empty
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: Always
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: true
BeforeWhile: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakAfterJavaFieldAnnotations: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: false
BreakConstructorInitializers: BeforeComma
BreakInheritanceList: BeforeComma
BreakStringLiterals: false
ColumnLimit: 0
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth : 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"Precompiled.hpp"'
Priority: 0
SortPriority: -1
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
- Regex: '.*'
Priority: 1
SortPriority: 0
IncludeIsMainRegex: '(_Test)?$'
IncludeIsMainSourceRegex: ''
IndentCaseBlocks: false
IndentCaseLabels: true
IndentExternBlock: NoIndent
IndentGotoLabels: true
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: true
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 60
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: c++20
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
TypenameMacros: []
UseCRLF: true
UseTab: Always
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE

23
.github/workflows/auto-clang-format.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: auto-clang-format
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: DoozyX/clang-format-lint-action@v0.13
with:
source: '.'
exclude: './third_party ./external'
extensions: 'h,cpp,hpp'
clangFormatVersion: 13
inplace: True
- uses: EndBug/add-and-commit@v4
with:
author_name: Clang Robot
author_email: robot@example.com
message: ':art: Committing clang-format changes'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

117
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,117 @@
name: CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
env:
CLANG_TIDY_VERSION: "13.0.0"
jobs:
build:
runs-on: ${{matrix.os}}
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
build_configuration: [Debug, Release]
compiler: [llvm, gcc]
vcpkg_bootstrap: [bootstrap-vcpkg.sh]
exclude:
- os: windows-latest
vcpkg_bootstrap: bootstrap-vcpkg.sh
include:
- os: 'windows-latest'
triplet: x64-windows
vcpkg_bootstrap: bootstrap-vcpkg.bat
compiler: llvm
build_configuration: Debug
- os: 'windows-latest'
triplet: x64-windows
vcpkg_bootstrap: bootstrap-vcpkg.bat
compiler: llvm
build_configuration: Release
- os: 'windows-latest'
triplet: x64-windows
vcpkg_bootstrap: bootstrap-vcpkg.bat
compiler: gcc
build_configuration: Debug
- os: 'windows-latest'
triplet: x64-windows
vcpkg_bootstrap: bootstrap-vcpkg.bat
compiler: gcc
build_configuration: Release
- os: 'windows-latest'
triplet: x64-windows
vcpkg_bootstrap: bootstrap-vcpkg.bat
compiler: msvc
build_configuration: Debug
- os: 'windows-latest'
triplet: x64-windows
vcpkg_bootstrap: bootstrap-vcpkg.bat
compiler: msvc
build_configuration: Release
- os: 'ubuntu-latest'
triplet: x64-linux
- os: 'macos-latest'
triplet: x64-osx
steps:
- name: checkout
uses: actions/checkout@v3
with:
submodules: true
- name: cache
uses: actions/cache@v3
with:
path: |
~/vcpkg
./build/vcpkg_installed
${{ env.HOME }}/.cache/vcpkg/archives
${{ env.XDG_CACHE_HOME }}/vcpkg/archives
${{ env.LOCALAPPDATA }}\vcpkg\archives
${{ env.APPDATA }}\vcpkg\archives
key: ${{ runner.os }}-${{ matrix.compiler }}-${{ matrix.build_configuration }}-${{ hashFiles('**/CMakeLists.txt') }}-${{ hashFiles('./vcpkg.json')}}
restore-keys: |
${{ runner.os }}-${{ matrix.build_configuration }}-
- name: setup dependencies
uses: aminya/setup-cpp@v1
with:
compiler: ${{ matrix.compiler }}
vcvarsall: ${{ contains(matrix.os, 'windows')}}
cmake: true
vcpkg: true
ccache: true
clangtidy: ${{ env.CLANG_TIDY_VERSION }}
cppcheck: true
- name: Boostrap Vcpkg
run: ${{github.workspace}}/external/vcpkg/${{matrix.vcpkg_bootstrap}} -disableMetrics
- name: Install packaged dependencies
run: ${{github.workspace}}/external/vcpkg/vcpkg install spdlog --triplet ${{matrix.triplet}}
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build_configuration}}
-DCMAKE_TOOLCHAIN_FILE=${{github.workspace}}/external/vcpkg/scripts/buildsystems/vcpkg.cmake
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{matrix.build_configuration}}
- name: Test
working-directory: ${{github.workspace}}/build
run: ctest -C ${{matrix.build_configuration}}

40
.gitignore vendored Normal file
View File

@@ -0,0 +1,40 @@
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# MSVC Specific
*.pdb
*.exp
build/
.vs/
Testing/

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "external/vcpkg"]
path = external/vcpkg
url = https://github.com/Microsoft/vcpkg.git

28
CMakeLists.txt Normal file
View File

@@ -0,0 +1,28 @@
cmake_minimum_required(VERSION 3.23)
project(starter_window VERSION 1.0.0)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED true)
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
OPTION(ENABLE_TESTS "Enable Unit Tests" OFF)
OPTION(ENABLE_ALL_REASONABLE_WARNINGS "Enable all possible reasonable warnings" ON )
OPTION(ENABLE_WARNINGS_AS_ERRORS "Warnings are treated as Errors" ON)
OPTION(ENABLE_STATIC_ANALYSIS "Enable Static Analysis Tools" OFF)
OPTION(ENABLE_SANITIZERS "Enable Sanitizer Tools" OFF)
set(CMAKE_SCRIPTS_DIR ${CMAKE_CURRENT_LIST_DIR}/scripts/cmake)
include(${CMAKE_SCRIPTS_DIR}/compilerwarnings.cmake)
include(${CMAKE_SCRIPTS_DIR}/sanitizers.cmake)
include(${CMAKE_SCRIPTS_DIR}/staticanalysis.cmake)
if (ENABLE_TESTS)
message("-- Unit Testing Enabled")
enable_testing()
add_subdirectory(test)
endif()
add_subdirectory(src)

24
LICENSE Normal file
View File

@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org>

4
README.md Normal file
View File

@@ -0,0 +1,4 @@
# window-starter
[![build](https://github.com/McMassiveNZ/window-starter/actions/workflows/ci.yml/badge.svg)](https://github.com/McMassiveNZ/window-starter/actions/workflows/ci.yml)
A window-starter cpp project which can open a simple window. The project contains boilerplate for CMake, testing and basic CI. Static Analysis, Unit Tests and Sanitizers are off by default

1
external/vcpkg vendored Submodule

Submodule external/vcpkg added at af031ae388

19
scripts/.clang-tidy Normal file
View File

@@ -0,0 +1,19 @@
---
Checks: "*,
-abseil-*,
-altera-*,
-android-*,
-fuchsia-*,
-google-*,
-llvm*,
-modernize-use-trailing-return-type,
-zircon-*,
-readability-else-after-return,
-readability-static-accessed-through-instance,
-readability-avoid-const-params-in-decls,
-cppcoreguidelines-non-private-member-variables-in-classes,
-misc-non-private-member-variables-in-classes,
"
WarningsAsErrors: ''
HeaderFilterRegex: ''
FormatStyle: none

View File

@@ -0,0 +1,106 @@
include_guard()
function( target_enable_warnings _target )
if(MSVC)
target_compile_options(
${_target}
PUBLIC
/W4 # Baseline reasonable warnings
/w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data
/w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
/w14263 # 'function': member function does not override any base class virtual member function
/w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not
# be destructed correctly
/w14287 # 'operator': unsigned/negative constant mismatch
/we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside
# the for-loop scope
/w14296 # 'operator': expression is always 'boolean_value'
/w14311 # 'variable': pointer truncation from 'type1' to 'type2'
/w14545 # expression before comma evaluates to a function which is missing an argument list
/w14546 # function call before comma missing argument list
/w14547 # 'operator': operator before comma has no effect; expected operator with side-effect
/w14549 # 'operator': operator before comma has no effect; did you intend 'operator'?
/w14555 # expression has no effect; expected expression with side- effect
/w14619 # pragma warning: there is no warning number 'number'
/w14640 # Enable warning on thread un-safe static member initialization
/w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior.
/w14905 # wide string literal cast to 'LPSTR'
/w14906 # string literal cast to 'LPWSTR'
/w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied
/permissive- # standards conformance mode for MSVC compiler.
)
elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
target_compile_options(
${_target}
INTERFACE
-Wall
-Wextra # reasonable and standard
-Wextra-semi # Warn about semicolon after in-class function definition.
-Wshadow # warn the user if a variable declaration shadows one from a parent context
-Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps
# catch hard to track down memory errors
-Wold-style-cast # warn for c-style casts
-Wcast-align # warn for potential performance problem casts
-Wunused # warn on anything being unused
-Woverloaded-virtual # warn if you overload (not override) a virtual function
-Wpedantic # warn if non-standard C++ is used
-Wconversion # warn on type conversions that may lose data
-Wsign-conversion # warn on sign conversions
-Wnull-dereference # warn if a null dereference is detected
-Wdouble-promotion # warn if float is implicit promoted to double
-Wformat=2 # warn on security issues around functions that format output (ie printf)
-Wimplicit-fallthrough # warn on statements that fallthrough without an explicit annotation
)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(
${_target}
INTERFACE
-Wall
-Wextra # reasonable and standard
-Wextra-semi # Warn about semicolon after in-class function definition.
-Wshadow # warn the user if a variable declaration shadows one from a parent context
-Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps
# catch hard to track down memory errors
-Wold-style-cast # warn for c-style casts
-Wcast-align # warn for potential performance problem casts
-Wunused # warn on anything being unused
-Woverloaded-virtual # warn if you overload (not override) a virtual function
-Wpedantic # warn if non-standard C++ is used
-Wconversion # warn on type conversions that may lose data
-Wsign-conversion # warn on sign conversions
-Wnull-dereference # warn if a null dereference is detected
-Wdouble-promotion # warn if float is implicit promoted to double
-Wformat=2 # warn on security issues around functions that format output (ie printf)
-Wimplicit-fallthrough # warn on statements that fallthrough without an explicit annotation
-Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist
-Wduplicated-cond # warn if if / else chain has duplicated conditions
-Wduplicated-branches # warn if if / else branches have duplicated code
-Wlogical-op # warn about logical operations being used where bitwise were probably wanted
-Wuseless-cast # warn if you perform a cast to the same type
)
endif()
endfunction()
function(target_warnings_as_errors _target)
if(MSVC)
target_compile_options(
${_target}
PUBLIC
/WX
)
elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
target_compile_options(
${_target}
PUBLIC
-Werror
)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(
${_target}
PUBLIC
-Werror
)
endif()
endfunction()

View File

@@ -0,0 +1,18 @@
include_guard()
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG 58d77fa8070e8cec2dc1ed015d66b454c8d78850 # release-1.12.1
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
set_property(TARGET
gtest
gtest_main
gmock
gmock_main
PROPERTY FOLDER GoogleTest)

View File

@@ -0,0 +1,8 @@
include_guard()
function( target_precompiled_header _target _header _source )
if( MSVC )
set_target_properties( ${_target} PROPERTIES COMPILE_FLAGS "/Yu${_header}" )
set_source_files_properties( ${_source} PROPERTIES COMPILE_FLAGS "/Yc${_header}" )
endif()
endfunction()

View File

@@ -0,0 +1,20 @@
include_guard()
function( target_enable_sanitizers _target )
if( MSVC )
string(FIND "$ENV{PATH}" "$ENV{VSINSTALLDIR}" index_of_vs_install_dir)
if("${index_of_vs_install_dir}" STREQUAL "-1")
message(
SEND_ERROR
"Using MSVC sanitizers requires setting the MSVC environment before building the project. Please manually open the MSVC command prompt and rebuild the project."
)
endif()
target_compile_options(${_target} PUBLIC /fsanitize=address /Zi /INCREMENTAL:NO)
target_link_options(${_target} PUBLIC /INCREMENTAL:NO)
else()
target_compile_options(${_target} INTERFACE -fsanitize=address,leak,undefined)
target_link_options(${_target} INTERFACE -fsanitize=address,leak,undefined)
endif()
endfunction()

View File

@@ -0,0 +1,16 @@
include_guard()
function(target_enable_static_analysis _target)
set(_VS_CLANG_TIDY "false")
find_program(CLANGTIDY clang-tidy)
if(CLANGTIDY)
set(_VS_CLANG_TIDY "true")
endif()
set_target_properties(
${_target}
PROPERTIES
VS_GLOBAL_EnableMicrosoftCodeAnalysis true
VS_GLOBAL_CodeAnalysisRuleSet "AllRules.ruleset"
VS_GLOBAL_EnableClangTidyCodeAnalysis "${_VS_CLANG_TIDY}"
)
endfunction()

47
src/CMakeLists.txt Normal file
View File

@@ -0,0 +1,47 @@
set(current_target starter_window)
set(SOURCE_FILES)
set(STARTER_WINDOW_SRC
main.cpp
window.h
)
source_group("" FILES ${STARTER_WINDOW_SRC})
if(MSVC)
set(PLATFORM_SRC
platform/win32_window.cpp
)
else()
set(PLATFORM_SRC
platform/null_window.cpp
)
endif()
source_group(platform FILES ${PLATFORM_SRC})
list(APPEND SOURCE_FILES ${PLATFORM_SRC})
list(APPEND SOURCE_FILES ${STARTER_WINDOW_SRC})
add_executable(
${current_target}
${SOURCE_FILES}
)
if( ENABLE_ALL_REASONABLE_WARNINGS )
MESSAGE("-- Additional Warnings Enabled")
target_enable_warnings(${current_target})
endif()
if( ENABLE_WARNINGS_AS_ERRORS )
MESSAGE("-- Warnings as Errors")
target_warnings_as_errors(${current_target})
endif()
if( ENABLE_SANITIZERS )
MESSAGE("-- Sanitizers Enabled")
target_enable_sanitizers(${current_target})
endif()
if( ENABLE_STATIC_ANALYSIS )
MESSAGE("-- Static Analysis Enabled")
target_enable_static_analysis(${current_target})
endif()

20
src/main.cpp Normal file
View File

@@ -0,0 +1,20 @@
#include "window.h"
constexpr int CW_USEDEFAULT = 0x80000000;
auto main() -> int
{
auto window = swCreateWindow({
.x = CW_USEDEFAULT,
.y = CW_USEDEFAULT,
.width = CW_USEDEFAULT,
.height = CW_USEDEFAULT,
.name = "Starter Window"
});
while (!window->ShouldClose())
{
window->PumpMessages();
}
}

View File

@@ -0,0 +1,28 @@
#include "../window.h"
namespace starter_window
{
class NullWindowImpl final : public Window
{
public:
NullWindowImpl() = default;
~NullWindowImpl() override = default;
NullWindowImpl(NullWindowImpl&&) = delete;
NullWindowImpl& operator=(NullWindowImpl&&) = delete;
NullWindowImpl(const NullWindowImpl&) = delete;
NullWindowImpl& operator=(const NullWindowImpl&) = delete;
void PumpMessages() override {}
bool ShouldClose() override { return false; }
};
} // namespace starter_window
std::unique_ptr<starter_window::Window> swCreateWindow(starter_window::WindowCreateParams)
{
auto result = std::make_unique<starter_window::NullWindowImpl>();
return result;
}

View File

@@ -0,0 +1,132 @@
#include "../window.h"
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
static LRESULT CALLBACK WindowProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
case WM_PAINT:
{
PAINTSTRUCT ps = {};
HDC hdc = BeginPaint(window, &ps);
FillRect(hdc, &ps.rcPaint, reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1));
EndPaint(window, &ps);
return 0;
}
}
return DefWindowProc(window, message, wParam, lParam);
}
namespace starter_window
{
class Win32WindowImpl final : public Window
{
public:
Win32WindowImpl();
~Win32WindowImpl() override = default;
Win32WindowImpl(const Win32WindowImpl&) = delete;
Win32WindowImpl& operator=(const Win32WindowImpl&) = delete;
bool init(WindowCreateParams params);
void PumpMessages() override;
bool ShouldClose() override;
HINSTANCE hInstance;
HWND hWnd;
bool m_close;
};
Win32WindowImpl::Win32WindowImpl()
: hInstance(GetModuleHandle(NULL))
, hWnd(nullptr)
, m_close(false)
{
}
bool Win32WindowImpl::init(WindowCreateParams params)
{
const char className[] = "Win32WindowImpl";
WNDCLASSEX wc = {};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = className;
if (RegisterClassEx(&wc) == NULL)
{
MessageBox(nullptr, "Call to RegisterClass failed", NULL, MB_OK);
return false;
}
HWND window = CreateWindowEx(
0,
className,
params.name,
WS_OVERLAPPEDWINDOW,
params.x, params.y, params.width, params.height,
NULL,
NULL,
hInstance,
NULL);
if (window == NULL)
{
MessageBox(nullptr, "Call to CreateWindow failed", NULL, MB_OK);
return false;
}
ShowWindow(window, SW_SHOW);
return true;
}
void Win32WindowImpl::PumpMessages()
{
MSG message = {};
if (GetMessage(&message, NULL, 0, 0) != 0)
{
TranslateMessage(&message);
DispatchMessage(&message);
}
else
{
// GetMessage returned WM_QUIT
m_close = true;
}
}
bool Win32WindowImpl::ShouldClose()
{
return m_close;
}
} // namespace starter_window
std::unique_ptr<starter_window::Window> swCreateWindow(starter_window::WindowCreateParams params)
{
auto result = std::make_unique<starter_window::Win32WindowImpl>();
if (result->init(params) == false)
{
result = nullptr;
}
return result;
}

27
src/window.h Normal file
View File

@@ -0,0 +1,27 @@
#pragma once
#include <memory>
namespace starter_window
{
struct WindowCreateParams
{
int x;
int y;
int width;
int height;
const char* name;
};
class Window
{
public:
virtual ~Window() = default;
virtual void PumpMessages() = 0;
virtual bool ShouldClose() = 0;
};
}
std::unique_ptr<starter_window::Window> swCreateWindow(starter_window::WindowCreateParams params);

14
test/CMakeLists.txt Normal file
View File

@@ -0,0 +1,14 @@
include(${CMAKE_SCRIPTS_DIR}/googletest.cmake)
add_executable(
window-starter-test
test_main.cpp
)
target_link_libraries(
window-starter-test
gtest_main
)
include(GoogleTest)
gtest_discover_tests(window-starter-test)

6
test/test_main.cpp Normal file
View File

@@ -0,0 +1,6 @@
#include <gtest/gtest.h>
TEST(testmain, example)
{
EXPECT_EQ(42, 7*6);
}