Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion cmake/documentation.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ endmacro()
function(add_documentation)
set(options)
set(oneValueArgs PROJECT PROJECT_NUMBER OUTPUT_DIRECTORY WORKING_DIRECTORY)
set(multiValueArgs INPUT_DIRECTORY PUBLIC_HEADERS)
set(multiValueArgs INPUT_DIRECTORY PUBLIC_HEADERS EXCLUDE_FILES)
cmake_parse_arguments(DOCUMENTATION "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

if (DOCUMENTATION_PROJECT)
Expand Down Expand Up @@ -81,6 +81,7 @@ function(add_documentation)
set(DOXYGEN_GENERATE_LATEX NO)
set(DOXYGEN_GENERATE_XML YES)
set(DOXYGEN_XML_OUTPUT xml)
set(DOXYGEN_EXCLUDE ${DOCUMENTATION_EXCLUDE_FILES})

configure_file(${PROJECT_SOURCE_DIR}/docs/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
set(doxygenXmlOutputDir ${DOXYGEN_OUTPUT_DIRECTORY}/${DOXYGEN_XML_OUTPUT})
Expand Down Expand Up @@ -139,5 +140,8 @@ if(MORPHEUS_BUILD_DOCUMENTATION)
INPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/examples
INPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/libraries
OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/documentation
EXCLUDE_FILES
${PROJECT_SOURCE_DIR}/libraries/gfx/platform/src/morpheus/gfx/platform/macos/application_delegate.h
${PROJECT_SOURCE_DIR}/libraries/gfx/platform/src/morpheus/gfx/platform/macos/window_delegate.h
)
endif()
3 changes: 3 additions & 0 deletions docs/Doxyfile.in
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,6 @@ GENERATE_XML = @DOXYGEN_GENERATE_XML@
# This tag requires that the tag GENERATE_XML is set to YES.

XML_OUTPUT = @DOXYGEN_XML_OUTPUT@

# Files to exclude from documentation generation.
EXCLUDE = @DOXYGEN_EXCLUDE@
15 changes: 14 additions & 1 deletion libraries/gfx/metal/examples/window/main.cpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
#include <morpheus/application/po/options.hpp>
#include <morpheus/core/conformance/print.hpp>
#include <morpheus/gfx/platform/macos/monitor.hpp>
#include <morpheus/gfx/platform/macos/render_window.hpp>

#include <iostream>

using namespace morpheus;
using namespace morpheus::application::po;
using namespace morpheus::gfx::macos;

int main(int argc, const char * argv[])
{
RenderWindow::Config config;

if (auto const result = parseProgramOptions(argc, argv, HelpDocumentation{}, config)) {
return result.value();
}


// NSLog (@"Window name: %@\nWidth: %ld\nHeight: %ld\nColour Depth: %ld\n", windowName, static_cast<long>(width), static_cast<long>(height), static_cast<long>(colourDepth));
for (const auto& monitors : enumerateMonitors())
{
fmt_ns::print("Monitor: {}\n", monitors);
std::cout.flush(); // Ensure it's not buffered
}

RenderWindow::Config config;
RenderWindow window(config);

while (!window.shouldClose())
{
window.pollEvents();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,17 @@ class RenderWindow : protected gfx::RenderWindow {
//! The colour depth of the pixels of the render target.
[[nodiscard]] std::uint16_t colourDepth() const noexcept { return gfx::RenderTarget::colourDepth(); }

[[nodiscard]] bool shouldClose() const noexcept;


// bool isHidden() const noexcept
// bool isFocus() const noexcept

/// \copydoc gfx::RenderWindow::fullScreen()
[[nodiscard]] bool fullScreen() const noexcept { return gfx::RenderWindow::fullScreen(); }
[[nodiscard]] bool fullScreen() const noexcept
{
return gfx::RenderWindow::fullScreen();
}

[[nodiscard]] bool visible() const noexcept;

Expand All @@ -59,10 +65,14 @@ class RenderWindow : protected gfx::RenderWindow {
/// Access the underlying OS Window handle.
auto getHandle() const noexcept { return mHandle; }

private:
void pollEvents();

private:
class Impl;
std::unique_ptr<Impl> mThis; // The internal implementation.
WindowHandle mHandle;


// Should we use a Windows controller subclass to enable unit testing?
// https://eschatologist.net/blog/?p=10
};
Expand Down
167 changes: 153 additions & 14 deletions libraries/gfx/platform/src/morpheus/gfx/platform/macos/render_window.mm
Original file line number Diff line number Diff line change
@@ -1,34 +1,56 @@

#include <morpheus/core/base/assert.hpp>
#include <morpheus/core/base/exceptions.hpp>
#include <morpheus/gfx/platform/macos/application_delegate.h>
#include <morpheus/gfx/platform/macos/render_window.hpp>
#include <morpheus/gfx/platform/macos/window_delegate.h>

#import "Cocoa/Cocoa.h"

#include <string>

namespace morpheus::gfx::macos
{

RenderWindow::RenderWindow(Config const& config)
: gfx::RenderWindow(config)
{
@autoreleasepool {
class RenderWindow::Impl{
public:
Impl(Config const& config);
Impl(Impl const&) = delete;
Impl(Impl&&) = default;
Impl& operator=(Impl const&) = delete;
Impl& operator=(Impl&&) = default;

if ([NSThread currentThread] != [NSThread mainThread])
{
// See https://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00460.html
throwRuntimeException("Cannot create a window from a worker thread. (OS X limitation)");
}
~Impl();

auto pollEvents() -> void;
auto setTitle(std::string const& title) -> void;

NSString* title = [[NSString alloc] initWithUTF8String:config.windowName.c_str()];
[[nodiscard]] bool shouldClose() const noexcept { return mShouldClose; }

private:
/// All window resoures on MacOS must be create on the main thread, this throw an exception if this is not the case.§
auto throwExceptionIfNotMainThread() -> void;

NSWindow* mHandle = nullptr;
WindowDelegate* mWindowDelegate = nullptr;
// ApplicationDelegate* mApplicationDelegate = nullptr;
bool mShouldClose = false;
};

RenderWindow::Impl::Impl(Config const& config)
: mHandle(nullptr)
, mWindowDelegate([[WindowDelegate alloc] init])
{
@autoreleasepool {
throwExceptionIfNotMainThread();

NSRect frame = NSMakeRect(config.startX, config.startY, config.width, config.height);
NSUInteger styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable;
mHandle = [[NSWindow alloc] initWithContentRect:frame
styleMask:styleMask
backing:NSBackingStoreBuffered
defer:NO];
[(NSWindow *)mHandle setTitle:title];
setTitle(config.windowName);

if (config.fullScreen)
{
Expand All @@ -47,13 +69,107 @@

[(NSWindow *)mHandle setBackgroundColor:[NSColor blackColor]];
// [window setIsVisible:YES];
// [window makeKeyAndOrderFront:windoAw];
// [window makeKeyAndOrderFront:window];

[mHandle setDelegate: mWindowDelegate];
[[NSApplication sharedApplication] finishLaunching];
[NSApp run];
//[(NSWindow *)mHandle setDelegate: [WindowDelegate alloc]];
// [NSApp run];
}
}

RenderWindow::Impl::~Impl()
{
[mHandle release];
[mWindowDelegate release];
// [ApplicationDelegate release];
}

void RenderWindow::Impl::pollEvents()
{
@autoreleasepool {

NSApplication* app = NSApplication.sharedApplication;
NSEvent* event = [app nextEventMatchingMask:NSEventMaskAny
untilDate:[NSDate distantPast]
inMode:NSDefaultRunLoopMode
dequeue:YES];
if (event)
{
[app sendEvent:event];

mShouldClose = [mWindowDelegate shouldClose];
}
}
}

auto RenderWindow::Impl::setTitle(std::string const& title) -> void
{
MORPHEUS_ASSERT(mHandle);

@autoreleasepool {
NSString* titleStr = [[NSString alloc] initWithUTF8String:title.c_str()];
[mHandle setTitle:titleStr];
}
}



auto RenderWindow::Impl::throwExceptionIfNotMainThread() -> void
{
if ([NSThread currentThread] != [NSThread mainThread])
{
// See https://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00460.html
throwRuntimeException("Cannot create a window from a worker thread. (OS X limitation)");
}
}

RenderWindow::RenderWindow(Config const& config)
: gfx::RenderWindow(config)
, mThis(std::make_unique<Impl>(config))
{
// @autoreleasepool {

// if ([NSThread currentThread] != [NSThread mainThread])
// {
// // See https://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00460.html
// throwRuntimeException("Cannot create a window from a worker thread. (OS X limitation)");
// }

// NSString* title = [[NSString alloc] initWithUTF8String:config.windowName.c_str()];

// NSRect frame = NSMakeRect(config.startX, config.startY, config.width, config.height);
// NSUInteger styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable;
// mHandle = [[NSWindow alloc] initWithContentRect:frame
// styleMask:styleMask
// backing:NSBackingStoreBuffered
// defer:NO];
// [(NSWindow *)mHandle setTitle:title];

// if (config.fullScreen)
// {
// [(NSWindow *)mHandle toggleFullScreen:nil];
// }

// if (config.visible)
// {
// [(NSWindow *)mHandle makeKeyAndOrderFront:nil];
// }

// [NSApp setDelegate: [ApplicationDelegate alloc]];
// [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
// [NSApp activateIgnoringOtherApps:YES];


// [(NSWindow *)mHandle setBackgroundColor:[NSColor blackColor]];
// // [window setIsVisible:YES];
// // [window makeKeyAndOrderFront:window];

// // [(NSWindow *)mHandle setDelegate: [WindowDelegate alloc]];
// [[NSApplication sharedApplication] finishLaunching];
// // [NSApp run];
// }
}

RenderWindow::RenderWindow(WindowHandle const window)
: mHandle(window)
{
Expand All @@ -71,9 +187,17 @@
}
}


RenderWindow::RenderWindow(RenderWindow&&) noexcept = default;
RenderWindow& RenderWindow::operator=(RenderWindow&&) noexcept = default;

RenderWindow::~RenderWindow()
{
@autoreleasepool {

// WindowDelegate* delegate = (WindowDelegate*)[(NSWindow*)mHandle delegate];
// [delegate release];

if (mHandle)
{
[(NSWindow *)mHandle close];
Expand All @@ -95,4 +219,19 @@
[(NSWindow*)mHandle makeKeyAndOrderFront:nil];
}

bool RenderWindow::shouldClose() const noexcept
{
return mThis->shouldClose();
}

// bool RenderWindow::fullScreen() const noexcept
// {
// return gfx::RenderWindow::fullScreen();
// }

void RenderWindow::pollEvents()
{
mThis->pollEvents();
}

} // namespace morpheus::gfx::macos
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#import <Cocoa/Cocoa.h>

@interface WindowDelegate : NSResponder<NSWindowDelegate>
@property (nonatomic) BOOL shouldClose;

- (void) windowWillClose:(NSNotification *)notification;
- (void) windowDidMiniaturize:(NSNotification *)notification;
- (void) windowDidDeminiaturize:(NSNotification *)notification;
@end
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
#import <Foundation/Foundation.h>

@implementation WindowDelegate
- (instancetype)init {
self = [super init];
_shouldClose = NO;
return self;
}
- (void)windowWillClose:(NSNotification *)notification {
_shouldClose = YES;
}

- (void) windowDidMiniaturize: (NSNotification *)notification
{

Expand Down
4 changes: 2 additions & 2 deletions libraries/gfx/platform/src/morpheus/gfx/platform/pixel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
namespace morpheus::gfx
{

/*! \enum pixel_format
/*! \enum PixelFormat

*/
enum class pixel_format : std::int32_t
enum class PixelFormat : std::int32_t
{
UNKNOWN,
// VK_FORMAT_R8_UNORM
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <morpheus/gfx/platform/render_target.hpp>

#include <boost/program_options/options_description.hpp>

#include <cstdint>
#include <string>

namespace morpheus::gfx
Expand All @@ -28,10 +30,10 @@ struct WindowConfig
namespace po = boost::program_options;
// clang-format off
options.add_options()
("window-name", po::value(&windowName)->required(), "The title of the Window.")
("width", po::value(&width)->required(), "Width in pixels of the window.")
("height", po::value(&height)->required(), "Height in pixels of the window.")
("colour-depth", po::value(&colourDepth)->required(), "Colour depth in bits per pixel.")
("window-name", po::value(&windowName)->default_value(windowName), "The title of the Window.")
("width", po::value(&width)->default_value(width), "Width in pixels of the window.")
("height", po::value(&height)->default_value(height), "Height in pixels of the window.")
("colour-depth", po::value(&colourDepth)->default_value(colourDepth), "Colour depth in bits per pixel.")
("start-x", po::value(&startX)->default_value(startX), "Starting pixel in the x-dimension for the Window.")
("start-y", po::value(&startY)->default_value(startY), "Starting pixel in the y-dimension for the Window.")
("full-screen", po::value(&fullScreen)->default_value(fullScreen), "Is the window to be started in full screen mode")
Expand Down
Loading