aboutsummaryrefslogtreecommitdiff
path: root/src/osx
diff options
context:
space:
mode:
Diffstat (limited to 'src/osx')
-rw-r--r--src/osx/CMakeLists.txt11
-rw-r--r--src/osx/Resource.cpp1
-rw-r--r--src/osx/graphics/CMakeLists.txt1
-rw-r--r--src/osx/graphics/quartz/Brush.cpp36
-rw-r--r--src/osx/graphics/quartz/CMakeLists.txt19
-rw-r--r--src/osx/graphics/quartz/Convert.cpp63
-rw-r--r--src/osx/graphics/quartz/Factory.cpp43
-rw-r--r--src/osx/graphics/quartz/Font.cpp30
-rw-r--r--src/osx/graphics/quartz/Geometry.cpp79
-rw-r--r--src/osx/graphics/quartz/Image.cpp58
-rw-r--r--src/osx/graphics/quartz/ImageFactory.cpp109
-rw-r--r--src/osx/graphics/quartz/Painter.cpp230
-rw-r--r--src/osx/graphics/quartz/Resource.cpp1
-rw-r--r--src/osx/graphics/quartz/TextLayout.cpp456
-rw-r--r--src/osx/gui/CMakeLists.txt15
-rw-r--r--src/osx/gui/Clipboard.mm46
-rw-r--r--src/osx/gui/ClipboardPrivate.h27
-rw-r--r--src/osx/gui/Cursor.mm93
-rw-r--r--src/osx/gui/CursorPrivate.h29
-rw-r--r--src/osx/gui/InputMethod.mm84
-rw-r--r--src/osx/gui/InputMethodPrivate.h64
-rw-r--r--src/osx/gui/Keyboard.mm283
-rw-r--r--src/osx/gui/KeyboardPrivate.h9
-rw-r--r--src/osx/gui/Menu.mm180
-rw-r--r--src/osx/gui/MenuPrivate.h65
-rw-r--r--src/osx/gui/Resource.cpp6
-rw-r--r--src/osx/gui/UiApplication.mm260
-rw-r--r--src/osx/gui/Window.mm800
-rw-r--r--src/osx/gui/WindowPrivate.h118
29 files changed, 0 insertions, 3216 deletions
diff --git a/src/osx/CMakeLists.txt b/src/osx/CMakeLists.txt
deleted file mode 100644
index 0a8bb7af..00000000
--- a/src/osx/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-add_library(CruPlatformBaseOsx SHARED
- Resource.cpp
-)
-
-find_library(FOUNDATION Foundation REQUIRED)
-find_library(CORE_FOUNDATION CoreFoundation REQUIRED)
-
-target_link_libraries(CruPlatformBaseOsx PUBLIC CruPlatformBase ${FOUNDATION} ${CORE_FOUNDATION})
-
-add_subdirectory(graphics)
-add_subdirectory(gui)
diff --git a/src/osx/Resource.cpp b/src/osx/Resource.cpp
deleted file mode 100644
index dbf15d48..00000000
--- a/src/osx/Resource.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "cru/osx/Resource.h"
diff --git a/src/osx/graphics/CMakeLists.txt b/src/osx/graphics/CMakeLists.txt
deleted file mode 100644
index 980c2f93..00000000
--- a/src/osx/graphics/CMakeLists.txt
+++ /dev/null
@@ -1 +0,0 @@
-add_subdirectory(quartz)
diff --git a/src/osx/graphics/quartz/Brush.cpp b/src/osx/graphics/quartz/Brush.cpp
deleted file mode 100644
index cfb8f635..00000000
--- a/src/osx/graphics/quartz/Brush.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-#include "cru/osx/graphics/quartz/Brush.h"
-#include "cru/common/String.h"
-#include "cru/common/Format.h"
-
-namespace cru::platform::graphics::osx::quartz {
-QuartzSolidColorBrush::QuartzSolidColorBrush(IGraphicsFactory* graphics_factory,
- const Color& color)
- : QuartzBrush(graphics_factory), color_(color) {
- cg_color_ =
- CGColorCreateGenericRGB(color.GetFloatRed(), color.GetFloatGreen(),
- color.GetFloatBlue(), color.GetFloatAlpha());
- Ensures(cg_color_);
-}
-
-QuartzSolidColorBrush::~QuartzSolidColorBrush() { CGColorRelease(cg_color_); }
-
-void QuartzSolidColorBrush::SetColor(const Color& color) {
- color_ = color;
- CGColorRelease(cg_color_);
- cg_color_ =
- CGColorCreateGenericRGB(color.GetFloatRed(), color.GetFloatGreen(),
- color.GetFloatBlue(), color.GetFloatAlpha());
- Ensures(cg_color_);
-}
-
-void QuartzSolidColorBrush::Select(CGContextRef context) {
- Expects(context);
- Expects(cg_color_);
- CGContextSetStrokeColorWithColor(context, cg_color_);
- CGContextSetFillColorWithColor(context, cg_color_);
-}
-
-String QuartzSolidColorBrush::GetDebugString() {
- return Format(u"QuartzSolidColorBrush(Color: {})", color_);
-}
-} // namespace cru::platform::graphics::osx::quartz
diff --git a/src/osx/graphics/quartz/CMakeLists.txt b/src/osx/graphics/quartz/CMakeLists.txt
deleted file mode 100644
index 1fcaff26..00000000
--- a/src/osx/graphics/quartz/CMakeLists.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-add_library(CruPlatformGraphicsQuartz SHARED
- Brush.cpp
- Convert.cpp
- Factory.cpp
- Font.cpp
- Geometry.cpp
- Image.cpp
- ImageFactory.cpp
- Painter.cpp
- Resource.cpp
- TextLayout.cpp
-)
-
-find_library(CORE_GRAPHICS CoreGraphics REQUIRED)
-find_library(CORE_TEXT CoreText REQUIRED)
-find_library(IMAGE_IO ImageIO REQUIRED)
-
-target_link_libraries(CruPlatformGraphicsQuartz PUBLIC ${CORE_GRAPHICS} ${CORE_TEXT} ${IMAGE_IO})
-target_link_libraries(CruPlatformGraphicsQuartz PUBLIC CruPlatformBaseOsx CruPlatformGraphics)
diff --git a/src/osx/graphics/quartz/Convert.cpp b/src/osx/graphics/quartz/Convert.cpp
deleted file mode 100644
index df62a206..00000000
--- a/src/osx/graphics/quartz/Convert.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-#include "cru/osx/graphics/quartz/Convert.h"
-#include <cstdint>
-
-namespace cru::platform::graphics::osx::quartz {
-
-CGPoint Convert(const Point& point) { return CGPoint{point.x, point.y}; }
-Point Convert(const CGPoint& point) { return Point(point.x, point.y); }
-
-CGSize Convert(const Size& size) { return CGSize{size.width, size.height}; }
-Size Convert(const CGSize& size) { return Size(size.width, size.height); }
-
-CGAffineTransform Convert(const Matrix& matrix) {
- return CGAffineTransformMake(matrix.m11, matrix.m12, matrix.m21, matrix.m22,
- matrix.m31, matrix.m32);
-}
-
-Matrix Convert(const CGAffineTransform& matrix) {
- return Matrix(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
-}
-
-CGRect Convert(const Rect& rect) {
- return CGRect{CGPoint{rect.left, rect.top}, CGSize{rect.width, rect.height}};
-}
-
-Rect Convert(const CGRect& rect) {
- return Rect{static_cast<float>(rect.origin.x),
- static_cast<float>(rect.origin.y),
- static_cast<float>(rect.size.width),
- static_cast<float>(rect.size.height)};
-}
-
-const CGDataProviderSequentialCallbacks kStreamToCGDataProviderCallbacks{
- 1,
- [](void* stream, void* buffer, size_t size) -> size_t {
- return static_cast<io::Stream*>(stream)->Read(
- static_cast<std::byte*>(buffer), size);
- },
- [](void* stream, off_t offset) -> off_t {
- auto s = static_cast<io::Stream*>(stream);
- auto current_position = s->Tell();
- s->Seek(offset, io::Stream::SeekOrigin::Current);
- return s->Tell() - current_position;
- },
- [](void* stream) { static_cast<io::Stream*>(stream)->Rewind(); },
- [](void* stream) {}};
-
-CGDataProviderRef ConvertStreamToCGDataProvider(io::Stream* stream) {
- return CGDataProviderCreateSequential(stream,
- &kStreamToCGDataProviderCallbacks);
-}
-
-const CGDataConsumerCallbacks kStreamToCGDataConsumerCallbacks{
- [](void* info, const void* buffer, size_t count) -> size_t {
- return static_cast<io::Stream*>(info)->Write(
- static_cast<const std::byte*>(buffer), count);
- },
- [](void* info) {}};
-
-CGDataConsumerRef ConvertStreamToCGDataConsumer(io::Stream* stream) {
- return CGDataConsumerCreate(stream, &kStreamToCGDataConsumerCallbacks);
-}
-
-} // namespace cru::platform::graphics::osx::quartz
diff --git a/src/osx/graphics/quartz/Factory.cpp b/src/osx/graphics/quartz/Factory.cpp
deleted file mode 100644
index 283341e5..00000000
--- a/src/osx/graphics/quartz/Factory.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-#include "cru/osx/graphics/quartz/Factory.h"
-
-#include "cru/osx/graphics/quartz/Brush.h"
-#include "cru/osx/graphics/quartz/Font.h"
-#include "cru/osx/graphics/quartz/Geometry.h"
-#include "cru/osx/graphics/quartz/ImageFactory.h"
-#include "cru/osx/graphics/quartz/TextLayout.h"
-#include "cru/platform/Check.h"
-#include "cru/platform/graphics/ImageFactory.h"
-
-#include <memory>
-
-namespace cru::platform::graphics::osx::quartz {
-QuartzGraphicsFactory::QuartzGraphicsFactory()
- : OsxQuartzResource(this), image_factory_(new QuartzImageFactory(this)) {}
-
-QuartzGraphicsFactory::~QuartzGraphicsFactory() {}
-
-std::unique_ptr<ISolidColorBrush>
-QuartzGraphicsFactory::CreateSolidColorBrush() {
- return std::make_unique<QuartzSolidColorBrush>(this, colors::black);
-}
-
-std::unique_ptr<IGeometryBuilder>
-QuartzGraphicsFactory::CreateGeometryBuilder() {
- return std::make_unique<QuartzGeometryBuilder>(this);
-}
-
-std::unique_ptr<IFont> QuartzGraphicsFactory::CreateFont(String font_family,
- float font_size) {
- return std::make_unique<OsxCTFont>(this, font_family, font_size);
-}
-
-std::unique_ptr<ITextLayout> QuartzGraphicsFactory::CreateTextLayout(
- std::shared_ptr<IFont> font, String text) {
- auto f = CheckPlatform<OsxCTFont>(font, GetPlatformId());
- return std::make_unique<OsxCTTextLayout>(this, f, text);
-}
-
-IImageFactory* QuartzGraphicsFactory::GetImageFactory() {
- return image_factory_.get();
-}
-} // namespace cru::platform::graphics::osx::quartz
diff --git a/src/osx/graphics/quartz/Font.cpp b/src/osx/graphics/quartz/Font.cpp
deleted file mode 100644
index a1b8bac2..00000000
--- a/src/osx/graphics/quartz/Font.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#include "cru/osx/graphics/quartz/Font.h"
-
-#include "cru/osx/Convert.h"
-#include "cru/osx/graphics/quartz/Convert.h"
-#include "cru/osx/graphics/quartz/Resource.h"
-
-namespace cru::platform::graphics::osx::quartz {
-using cru::platform::osx::Convert;
-
-OsxCTFont::OsxCTFont(IGraphicsFactory* graphics_factory, const String& name,
- float size)
- : OsxQuartzResource(graphics_factory), name_(name) {
- CFStringRef n = Convert(name);
-
- if (name.empty()) {
- ct_font_ =
- CTFontCreateUIFontForLanguage(kCTFontUIFontSystem, size, nullptr);
- } else {
- ct_font_ = CTFontCreateWithName(n, size, nullptr);
- }
- Ensures(ct_font_);
-
- CFRelease(n);
-}
-
-OsxCTFont::~OsxCTFont() { CFRelease(ct_font_); }
-
-String OsxCTFont::GetFontName() { return name_; }
-float OsxCTFont::GetFontSize() { return CTFontGetSize(ct_font_); }
-} // namespace cru::platform::graphics::osx::quartz
diff --git a/src/osx/graphics/quartz/Geometry.cpp b/src/osx/graphics/quartz/Geometry.cpp
deleted file mode 100644
index c88add87..00000000
--- a/src/osx/graphics/quartz/Geometry.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-#include "cru/osx/graphics/quartz/Geometry.h"
-#include "cru/osx/graphics/quartz/Convert.h"
-
-#include <memory>
-
-namespace cru::platform::graphics::osx::quartz {
-QuartzGeometry::QuartzGeometry(IGraphicsFactory *graphics_factory,
- CGPathRef cg_path)
- : OsxQuartzResource(graphics_factory), cg_path_(cg_path) {}
-
-QuartzGeometry::~QuartzGeometry() { CGPathRelease(cg_path_); }
-
-bool QuartzGeometry::FillContains(const Point &point) {
- return CGPathContainsPoint(cg_path_, nullptr, CGPoint{point.x, point.y},
- kCGPathFill);
-}
-
-Rect QuartzGeometry::GetBounds() {
- auto bounds = CGPathGetPathBoundingBox(cg_path_);
- if (CGRectIsNull(bounds)) return {};
- return Convert(bounds);
-}
-
-std::unique_ptr<IGeometry> QuartzGeometry::Transform(const Matrix &matrix) {
- auto cg_matrix = Convert(matrix);
- auto cg_path = CGPathCreateCopyByTransformingPath(cg_path_, &cg_matrix);
- return std::make_unique<QuartzGeometry>(GetGraphicsFactory(), cg_path);
-}
-
-std::unique_ptr<IGeometry> QuartzGeometry::CreateStrokeGeometry(float width) {
- auto cg_path = CGPathCreateCopyByStrokingPath(
- cg_path_, nullptr, width, kCGLineCapButt, kCGLineJoinMiter, 10);
- return std::make_unique<QuartzGeometry>(GetGraphicsFactory(), cg_path);
-}
-
-QuartzGeometryBuilder::QuartzGeometryBuilder(IGraphicsFactory *graphics_factory)
- : OsxQuartzResource(graphics_factory) {
- cg_mutable_path_ = CGPathCreateMutable();
-}
-
-QuartzGeometryBuilder::~QuartzGeometryBuilder() {
- CGPathRelease(cg_mutable_path_);
-}
-
-Point QuartzGeometryBuilder::GetCurrentPosition() {
- return Convert(CGPathGetCurrentPoint(cg_mutable_path_));
-}
-
-void QuartzGeometryBuilder::MoveTo(const Point &point) {
- CGPathMoveToPoint(cg_mutable_path_, nullptr, point.x, point.y);
-}
-
-void QuartzGeometryBuilder::LineTo(const Point &point) {
- CGPathAddLineToPoint(cg_mutable_path_, nullptr, point.x, point.y);
-}
-
-void QuartzGeometryBuilder::CubicBezierTo(const Point &start_control_point,
- const Point &end_control_point,
- const Point &end_point) {
- CGPathAddCurveToPoint(cg_mutable_path_, nullptr, start_control_point.x,
- start_control_point.y, end_control_point.x,
- end_control_point.y, end_point.x, end_point.y);
-}
-
-void QuartzGeometryBuilder::QuadraticBezierTo(const Point &control_point,
- const Point &end_point) {
- CGPathAddQuadCurveToPoint(cg_mutable_path_, nullptr, control_point.x,
- control_point.y, end_point.x, end_point.y);
-}
-
-void QuartzGeometryBuilder::CloseFigure(bool close) {
- if (close) CGPathCloseSubpath(cg_mutable_path_);
-}
-
-std::unique_ptr<IGeometry> QuartzGeometryBuilder::Build() {
- return std::make_unique<QuartzGeometry>(GetGraphicsFactory(),
- CGPathCreateCopy(cg_mutable_path_));
-}
-} // namespace cru::platform::graphics::osx::quartz
diff --git a/src/osx/graphics/quartz/Image.cpp b/src/osx/graphics/quartz/Image.cpp
deleted file mode 100644
index 28087000..00000000
--- a/src/osx/graphics/quartz/Image.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-#include "cru/osx/graphics/quartz/Image.h"
-#include "cru/common/Exception.h"
-#include "cru/osx/graphics/quartz/Convert.h"
-#include "cru/osx/graphics/quartz/Painter.h"
-
-namespace cru::platform::graphics::osx::quartz {
-QuartzImage::QuartzImage(IGraphicsFactory* graphics_factory,
- IImageFactory* image_factory, CGImageRef image,
- bool auto_release, unsigned char* buffer)
- : OsxQuartzResource(graphics_factory),
- image_factory_(image_factory),
- image_(image),
- auto_release_(auto_release),
- buffer_(buffer) {
- Expects(image);
-}
-
-QuartzImage::~QuartzImage() {
- if (auto_release_) {
- CGImageRelease(image_);
- }
-}
-
-float QuartzImage::GetWidth() { return CGImageGetWidth(image_); }
-
-float QuartzImage::GetHeight() { return CGImageGetHeight(image_); }
-
-std::unique_ptr<IImage> QuartzImage::CreateWithRect(const Rect& rect) {
- auto new_cg_image = CGImageCreateWithImageInRect(image_, Convert(rect));
-
- return std::make_unique<QuartzImage>(GetGraphicsFactory(), image_factory_,
- new_cg_image, true);
-}
-
-std::unique_ptr<IPainter> QuartzImage::CreatePainter() {
- if (!buffer_)
- throw Exception(
- u"Failed to create painter for image because failed to get its "
- u"buffer.");
-
- auto width = CGImageGetWidth(image_);
- auto height = CGImageGetHeight(image_);
- auto bits_per_component = CGImageGetBitsPerComponent(image_);
- auto bytes_per_row = CGImageGetBytesPerRow(image_);
- auto color_space = CGImageGetColorSpace(image_);
- auto bitmap_info = CGImageGetBitmapInfo(image_);
-
- auto cg_context =
- CGBitmapContextCreate(buffer_, width, height, bits_per_component,
- bytes_per_row, color_space, bitmap_info);
-
- return std::make_unique<QuartzCGContextPainter>(
- GetGraphicsFactory(), cg_context, true, Size(width, height),
- [](QuartzCGContextPainter* painter) {
-
- });
-}
-} // namespace cru::platform::graphics::osx::quartz
diff --git a/src/osx/graphics/quartz/ImageFactory.cpp b/src/osx/graphics/quartz/ImageFactory.cpp
deleted file mode 100644
index 5ff262c3..00000000
--- a/src/osx/graphics/quartz/ImageFactory.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-#include "cru/osx/graphics/quartz/ImageFactory.h"
-#include "cru/common/Exception.h"
-#include "cru/common/platform/osx/Convert.h"
-#include "cru/osx/graphics/quartz/Convert.h"
-#include "cru/osx/graphics/quartz/Image.h"
-#include "cru/platform/Check.h"
-#include "cru/platform/graphics/Image.h"
-
-#include <ImageIO/ImageIO.h>
-
-namespace cru::platform::graphics::osx::quartz {
-using cru::platform::osx::Convert;
-
-QuartzImageFactory::QuartzImageFactory(IGraphicsFactory* graphics_factory)
- : OsxQuartzResource(graphics_factory) {}
-
-QuartzImageFactory::~QuartzImageFactory() {}
-
-std::unique_ptr<IImage> QuartzImageFactory::DecodeFromStream(
- io::Stream* stream) {
- CGDataProviderRef data_provider = ConvertStreamToCGDataProvider(stream);
- CGImageSourceRef image_source =
- CGImageSourceCreateWithDataProvider(data_provider, nullptr);
-
- CGImageRef cg_image =
- CGImageSourceCreateImageAtIndex(image_source, 0, nullptr);
-
- CFRelease(image_source);
- CGDataProviderRelease(data_provider);
-
- return std::unique_ptr<IImage>(
- new QuartzImage(GetGraphicsFactory(), this, cg_image, true));
-}
-
-static String GetImageFormatUniformTypeIdentifier(ImageFormat format) {
- switch (format) {
- case ImageFormat::Png:
- return u"public.png";
- case ImageFormat::Jpeg:
- return u"public.jpeg";
- case ImageFormat::Gif:
- return u"com.compuserve.gif";
- default:
- throw Exception(u"Unknown image format.");
- }
-}
-
-void QuartzImageFactory::EncodeToStream(IImage* image, io::Stream* stream,
- ImageFormat format, float quality) {
- if (quality <= 0 || quality > 1) {
- throw Exception(u"Invalid quality value.");
- }
-
- auto quartz_image = CheckPlatform<QuartzImage>(image, GetPlatformId());
- auto cg_image = quartz_image->GetCGImage();
-
- CFStringRef uti = Convert(GetImageFormatUniformTypeIdentifier(format));
- CGDataConsumerRef data_consumer = ConvertStreamToCGDataConsumer(stream);
- CGImageDestinationRef destination =
- CGImageDestinationCreateWithDataConsumer(data_consumer, uti, 1, nullptr);
-
- CFMutableDictionaryRef properties =
- CFDictionaryCreateMutable(nullptr, 0, nullptr, nullptr);
- CFNumberRef quality_wrap =
- CFNumberCreate(nullptr, kCFNumberFloatType, &quality);
- CFDictionaryAddValue(properties, kCGImageDestinationLossyCompressionQuality,
- quality_wrap);
-
- CGImageDestinationAddImage(destination, cg_image, properties);
-
- if (!CGImageDestinationFinalize(destination)) {
- throw Exception(u"Failed to finalize image destination.");
- }
-
- CFRelease(quality_wrap);
- CFRelease(properties);
- CFRelease(destination);
- CFRelease(data_consumer);
- CFRelease(uti);
-}
-
-std::unique_ptr<IImage> QuartzImageFactory::CreateBitmap(int width,
- int height) {
- if (width <= 0) throw Exception(u"Image width should be greater than 0.");
- if (height <= 0) throw Exception(u"Image height should be greater than 0.");
-
- CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB();
-
- const auto buffer_size = width * height * 4;
- auto buffer = new unsigned char[buffer_size]{0};
-
- auto cg_data_provider = CGDataProviderCreateWithData(
- nullptr, buffer, buffer_size,
- [](void* info, const void* data, size_t size) {
- delete[] static_cast<const unsigned char*>(data);
- });
-
- auto cg_image =
- CGImageCreate(width, height, 8, 32, 4 * width, color_space,
- kCGImageAlphaPremultipliedLast, cg_data_provider, nullptr,
- true, kCGRenderingIntentDefault);
-
- CGColorSpaceRelease(color_space);
- CGDataProviderRelease(cg_data_provider);
-
- return std::unique_ptr<IImage>(
- new QuartzImage(GetGraphicsFactory(), this, cg_image, true, buffer));
-}
-} // namespace cru::platform::graphics::osx::quartz
diff --git a/src/osx/graphics/quartz/Painter.cpp b/src/osx/graphics/quartz/Painter.cpp
deleted file mode 100644
index a8c3715a..00000000
--- a/src/osx/graphics/quartz/Painter.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-#include "cru/osx/graphics/quartz/Painter.h"
-
-#include "cru/osx/graphics/quartz/Brush.h"
-#include "cru/osx/graphics/quartz/Convert.h"
-#include "cru/osx/graphics/quartz/Geometry.h"
-#include "cru/osx/graphics/quartz/Image.h"
-#include "cru/osx/graphics/quartz/TextLayout.h"
-#include "cru/platform/Check.h"
-#include "cru/platform/Color.h"
-#include "cru/platform/Exception.h"
-
-namespace cru::platform::graphics::osx::quartz {
-QuartzCGContextPainter::QuartzCGContextPainter(
- IGraphicsFactory* graphics_factory, CGContextRef cg_context,
- bool auto_release, const Size& size,
- std::function<void(QuartzCGContextPainter*)> on_end_draw)
- : OsxQuartzResource(graphics_factory),
- cg_context_(cg_context),
- auto_release_(auto_release),
- size_(size),
- on_end_draw_(std::move(on_end_draw)) {
- Expects(cg_context);
-
- CGContextConcatCTM(cg_context_,
- CGAffineTransformInvert(CGContextGetCTM(cg_context_)));
-
- transform_ = Matrix::Scale(1, -1) * Matrix::Translation(0, size.height);
- CGContextConcatCTM(cg_context_, Convert(transform_));
-}
-
-QuartzCGContextPainter::~QuartzCGContextPainter() {
- DoEndDraw();
- if (auto_release_) {
- CGContextRelease(cg_context_);
- cg_context_ = nullptr;
- }
-}
-
-Matrix QuartzCGContextPainter::GetTransform() { return transform_; }
-
-void QuartzCGContextPainter::SetTransform(const Matrix& matrix) {
- CGContextConcatCTM(cg_context_, Convert(*transform_.Inverted()));
- CGContextConcatCTM(cg_context_, Convert(matrix));
- transform_ = matrix;
-}
-
-void QuartzCGContextPainter::ConcatTransform(const Matrix& matrix) {
- CGContextConcatCTM(cg_context_, Convert(matrix));
- transform_ = matrix * transform_;
-}
-
-void QuartzCGContextPainter::Clear(const Color& color) {
- Validate();
-
- CGContextSetRGBFillColor(cg_context_, color.GetFloatRed(),
- color.GetFloatGreen(), color.GetFloatBlue(),
- color.GetFloatAlpha());
- CGContextFillRect(cg_context_, Convert(Rect{Point{}, size_}));
-}
-
-void QuartzCGContextPainter::DrawLine(const Point& start, const Point& end,
- IBrush* brush, float width) {
- Validate();
-
- CGContextBeginPath(cg_context_);
- CGContextMoveToPoint(cg_context_, start.x, start.y);
- CGContextAddLineToPoint(cg_context_, end.x, end.y);
-
- QuartzBrush* b = CheckPlatform<QuartzBrush>(brush, GetPlatformId());
- b->Select(cg_context_);
- SetLineWidth(width);
-
- CGContextStrokePath(cg_context_);
-}
-
-void QuartzCGContextPainter::StrokeRectangle(const Rect& rectangle,
- IBrush* brush, float width) {
- Validate();
-
- QuartzBrush* b = CheckPlatform<QuartzBrush>(brush, GetPlatformId());
- b->Select(cg_context_);
- CGContextStrokeRectWithWidth(cg_context_, Convert(rectangle), width);
-}
-
-void QuartzCGContextPainter::FillRectangle(const Rect& rectangle,
- IBrush* brush) {
- Validate();
-
- QuartzBrush* b = CheckPlatform<QuartzBrush>(brush, GetPlatformId());
- b->Select(cg_context_);
- CGContextFillRect(cg_context_, Convert(rectangle));
-}
-
-void QuartzCGContextPainter::StrokeEllipse(const Rect& outline_rect,
- IBrush* brush, float width) {
- Validate();
-
- QuartzBrush* b = CheckPlatform<QuartzBrush>(brush, GetPlatformId());
- b->Select(cg_context_);
- SetLineWidth(width);
-
- CGContextStrokeEllipseInRect(cg_context_, Convert(outline_rect));
-}
-
-void QuartzCGContextPainter::FillEllipse(const Rect& outline_rect,
- IBrush* brush) {
- Validate();
-
- QuartzBrush* b = CheckPlatform<QuartzBrush>(brush, GetPlatformId());
- b->Select(cg_context_);
- CGContextFillEllipseInRect(cg_context_, Convert(outline_rect));
-}
-
-void QuartzCGContextPainter::StrokeGeometry(IGeometry* geometry, IBrush* brush,
- float width) {
- Validate();
-
- QuartzGeometry* g = CheckPlatform<QuartzGeometry>(geometry, GetPlatformId());
- QuartzBrush* b = CheckPlatform<QuartzBrush>(brush, GetPlatformId());
-
- b->Select(cg_context_);
- SetLineWidth(width);
-
- CGContextBeginPath(cg_context_);
- CGContextAddPath(cg_context_, g->GetCGPath());
- CGContextStrokePath(cg_context_);
-}
-
-void QuartzCGContextPainter::FillGeometry(IGeometry* geometry, IBrush* brush) {
- Validate();
-
- QuartzGeometry* g = CheckPlatform<QuartzGeometry>(geometry, GetPlatformId());
- QuartzBrush* b = CheckPlatform<QuartzBrush>(brush, GetPlatformId());
-
- b->Select(cg_context_);
- CGContextBeginPath(cg_context_);
- CGContextAddPath(cg_context_, g->GetCGPath());
- CGContextEOFillPath(cg_context_);
-}
-
-void QuartzCGContextPainter::DrawText(const Point& offset,
- ITextLayout* text_layout, IBrush* brush) {
- Validate();
-
- auto tl = CheckPlatform<OsxCTTextLayout>(text_layout, GetPlatformId());
-
- Color color;
-
- if (auto b = dynamic_cast<QuartzSolidColorBrush*>(brush)) {
- color = b->GetColor();
- } else {
- color = colors::black;
- }
-
- Matrix transform = tl->GetTransform();
-
- CGContextSaveGState(cg_context_);
-
- CGContextConcatCTM(cg_context_, Convert(transform * Matrix::Translation(
- offset.x, offset.y)));
-
- auto frame = tl->CreateFrameWithColor(color);
- Ensures(frame);
- CTFrameDraw(frame, cg_context_);
- CFRelease(frame);
-
- CGContextRestoreGState(cg_context_);
-}
-
-void QuartzCGContextPainter::DrawImage(const Point& offset, IImage* image) {
- Validate();
- auto i = CheckPlatform<QuartzImage>(image, GetPlatformId());
-
- auto cg_image = i->GetCGImage();
-
- auto width = CGImageGetWidth(cg_image);
- auto height = CGImageGetHeight(cg_image);
-
- CGContextDrawImage(cg_context_, CGRectMake(offset.x, offset.y, width, height),
- cg_image);
-}
-
-void QuartzCGContextPainter::PushLayer(const Rect& bounds) {
- Validate();
- clip_stack_.push_back(bounds);
- CGContextClipToRect(cg_context_, Convert(bounds));
-}
-
-void QuartzCGContextPainter::PopLayer() {
- Validate();
- clip_stack_.pop_back();
- if (clip_stack_.empty()) {
- CGContextResetClip(cg_context_);
- } else {
- CGContextClipToRect(cg_context_, Convert(clip_stack_.back()));
- }
-}
-
-void QuartzCGContextPainter::PushState() {
- Validate();
- CGContextSaveGState(cg_context_);
-}
-
-void QuartzCGContextPainter::PopState() {
- Validate();
- CGContextRestoreGState(cg_context_);
-}
-
-void QuartzCGContextPainter::EndDraw() { DoEndDraw(); }
-
-void QuartzCGContextPainter::SetLineWidth(float width) {
- if (cg_context_) {
- CGContextSetLineWidth(cg_context_, width);
- }
-}
-
-void QuartzCGContextPainter::DoEndDraw() {
- if (cg_context_) {
- CGContextFlush(cg_context_);
- CGContextSynchronize(cg_context_);
-
- on_end_draw_(this);
- }
-}
-
-void QuartzCGContextPainter::Validate() {
- if (cg_context_ == nullptr)
- throw ReuseException(u"QuartzCGContextPainter has already be released.");
-}
-} // namespace cru::platform::graphics::osx::quartz
diff --git a/src/osx/graphics/quartz/Resource.cpp b/src/osx/graphics/quartz/Resource.cpp
deleted file mode 100644
index 00bd5c94..00000000
--- a/src/osx/graphics/quartz/Resource.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "cru/osx/graphics/quartz/Resource.h"
diff --git a/src/osx/graphics/quartz/TextLayout.cpp b/src/osx/graphics/quartz/TextLayout.cpp
deleted file mode 100644
index 6013efba..00000000
--- a/src/osx/graphics/quartz/TextLayout.cpp
+++ /dev/null
@@ -1,456 +0,0 @@
-#include "cru/osx/graphics/quartz/TextLayout.h"
-#include "cru/common/Base.h"
-#include "cru/common/Format.h"
-#include "cru/common/StringUtil.h"
-#include "cru/osx/Convert.h"
-#include "cru/osx/graphics/quartz/Convert.h"
-#include "cru/osx/graphics/quartz/Resource.h"
-#include "cru/platform/Check.h"
-#include "cru/platform/graphics/Base.h"
-
-#include <algorithm>
-#include <limits>
-
-namespace cru::platform::graphics::osx::quartz {
-using cru::platform::osx::Convert;
-
-OsxCTTextLayout::OsxCTTextLayout(IGraphicsFactory* graphics_factory,
- std::shared_ptr<OsxCTFont> font,
- const String& str)
- : OsxQuartzResource(graphics_factory),
- max_width_(std::numeric_limits<float>::max()),
- max_height_(std::numeric_limits<float>::max()),
- font_(std::move(font)),
- text_(str) {
- Expects(font_);
-
- DoSetText(std::move(text_));
-
- RecreateFrame();
-}
-
-OsxCTTextLayout::~OsxCTTextLayout() {
- ReleaseResource();
- CFRelease(cf_attributed_text_);
-}
-
-void OsxCTTextLayout::SetFont(std::shared_ptr<IFont> font) {
- font_ = CheckPlatform<OsxCTFont>(font, GetPlatformId());
- RecreateFrame();
-}
-
-void OsxCTTextLayout::DoSetText(String text) {
- text_ = std::move(text);
-
- if (text_.empty()) {
- head_empty_line_count_ = 0;
- tail_empty_line_count_ = 1;
-
- actual_text_ = {};
- } else {
- head_empty_line_count_ = 0;
- tail_empty_line_count_ = 0;
-
- for (auto i = text_.cbegin(); i != text_.cend(); ++i) {
- if (*i == u'\n') {
- head_empty_line_count_++;
- } else {
- break;
- }
- }
-
- for (auto i = text_.crbegin(); i != text_.crend(); ++i) {
- if (*i == u'\n') {
- tail_empty_line_count_++;
- } else {
- break;
- }
- }
-
- if (text_.size() == tail_empty_line_count_) {
- head_empty_line_count_ = 1;
- actual_text_ = {};
- } else {
- actual_text_ = String(text_.cbegin() + head_empty_line_count_,
- text_.cend() - tail_empty_line_count_);
- }
- }
-
- CFStringRef s = Convert(actual_text_);
- cf_attributed_text_ = CFAttributedStringCreateMutable(nullptr, 0);
- CFAttributedStringReplaceString(cf_attributed_text_, CFRangeMake(0, 0), s);
- Ensures(cf_attributed_text_);
- CFAttributedStringSetAttribute(
- cf_attributed_text_,
- CFRangeMake(0, CFAttributedStringGetLength(cf_attributed_text_)),
- kCTFontAttributeName, font_->GetCTFont());
- CFRelease(s);
-}
-
-void OsxCTTextLayout::SetText(String new_text) {
- if (new_text == text_) return;
-
- CFRelease(cf_attributed_text_);
- DoSetText(std::move(new_text));
-
- RecreateFrame();
-}
-
-void OsxCTTextLayout::SetMaxWidth(float max_width) {
- max_width_ = max_width;
- RecreateFrame();
-}
-
-void OsxCTTextLayout::SetMaxHeight(float max_height) {
- max_height_ = max_height;
- RecreateFrame();
-}
-
-bool OsxCTTextLayout::IsEditMode() { return edit_mode_; }
-
-void OsxCTTextLayout::SetEditMode(bool enable) {
- edit_mode_ = enable;
- RecreateFrame();
-}
-
-Index OsxCTTextLayout::GetLineIndexFromCharIndex(Index char_index) {
- if (char_index < 0 || char_index >= text_.size()) {
- return -1;
- }
-
- auto line_index = 0;
- for (Index i = 0; i < char_index; ++i) {
- if (text_[i] == u'\n') {
- line_index++;
- }
- }
-
- return line_index;
-}
-
-Index OsxCTTextLayout::GetLineCount() { return line_count_; }
-
-float OsxCTTextLayout::GetLineHeight(Index line_index) {
- if (line_index < 0 || line_index >= line_count_) {
- return 0.0f;
- }
- return line_heights_[line_index];
-}
-
-Rect OsxCTTextLayout::GetTextBounds(bool includingTrailingSpace) {
- if (text_.empty() && edit_mode_) return Rect(0, 0, 0, font_->GetFontSize());
-
- auto result = DoGetTextBoundsIncludingEmptyLines(includingTrailingSpace);
- return Rect(0, 0, result.size.width, result.size.height);
-}
-
-std::vector<Rect> OsxCTTextLayout::TextRangeRect(const TextRange& text_range) {
- if (text_.empty()) return {};
-
- auto tr = text_range;
- tr = text_range.CoerceInto(head_empty_line_count_,
- text_.size() - tail_empty_line_count_);
- tr.position -= head_empty_line_count_;
-
- std::vector<CGRect> results = DoTextRangeRect(tr);
- std::vector<Rect> r;
-
- for (auto& rect : results) {
- r.push_back(transform_.TransformRect(Convert(rect)));
- }
-
- return r;
-}
-
-Rect OsxCTTextLayout::TextSinglePoint(Index position, bool trailing) {
- Expects(position >= 0 && position <= text_.size());
-
- if (text_.empty()) return {0, 0, 0, font_->GetFontSize()};
-
- if (position < head_empty_line_count_) {
- return {0, position * font_->GetFontSize(), 0, font_->GetFontSize()};
- } else if (position > text_.size() - tail_empty_line_count_) {
- return {
- 0,
- static_cast<float>(text_bounds_without_trailing_space_.size.height) +
- (head_empty_line_count_ + position -
- (text_.size() - tail_empty_line_count_) - 1) *
- font_->GetFontSize(),
- 0, font_->GetFontSize()};
- } else {
- auto result =
- DoTextSinglePoint(position - head_empty_line_count_, trailing);
- return transform_.TransformRect(Convert(result));
- }
-}
-
-TextHitTestResult OsxCTTextLayout::HitTest(const Point& point) {
- if (point.y < head_empty_line_count_ * font_->GetFontSize()) {
- if (point.y < 0) {
- return {0, false, false};
- } else {
- for (int i = 1; i <= head_empty_line_count_; ++i) {
- if (point.y < i * font_->GetFontSize()) {
- return {i - 1, false, false};
- }
- }
- }
- }
-
- auto text_bounds = text_bounds_without_trailing_space_;
-
- auto text_height = static_cast<float>(text_bounds.size.height);
- auto th = text_height + head_empty_line_count_ * font_->GetFontSize();
- if (point.y >= th) {
- for (int i = 1; i <= tail_empty_line_count_; ++i) {
- if (point.y < th + i * font_->GetFontSize()) {
- return {text_.size() - (tail_empty_line_count_ - i), false, false};
- }
- }
- return {text_.size(), false, false};
- }
-
- auto p = point;
- p.y -= head_empty_line_count_ * font_->GetFontSize();
- p.y = text_height - p.y;
-
- for (int i = 0; i < line_count_; i++) {
- auto line = lines_[i];
- auto line_origin = line_origins_[i];
-
- auto range = CTLineGetStringRange(line);
-
- CGRect bounds{line_origin.x, line_origin.y - line_descents_[i],
- CTLineGetOffsetForStringIndex(
- line, range.location + range.length, nullptr),
- line_heights_[i]};
-
- bool force_inside = false;
- if (i == 0 && p.y >= bounds.origin.y + bounds.size.height) {
- force_inside = true;
- }
-
- if (i == line_count_ - 1 && p.y < bounds.origin.y) {
- force_inside = true;
- }
-
- if (p.y >= bounds.origin.y || force_inside) {
- auto pp = p;
- pp.y = bounds.origin.y;
- Index po;
- bool inside_text;
-
- if (pp.x < bounds.origin.x) {
- po = actual_text_.IndexFromCodePointToCodeUnit(range.location);
- inside_text = false;
- } else if (pp.x > bounds.origin.x + bounds.size.width) {
- po = actual_text_.IndexFromCodePointToCodeUnit(range.location +
- range.length);
- inside_text = false;
- } else {
- int position = CTLineGetStringIndexForPosition(
- line,
- CGPointMake(pp.x - line_origins_[i].x, pp.y - line_origins_[i].y));
-
- po = actual_text_.IndexFromCodePointToCodeUnit(position);
- inside_text = true;
- }
-
- if (po != 0 &&
- po == actual_text_.IndexFromCodePointToCodeUnit(range.location +
- range.length) &&
- actual_text_[po - 1] == u'\n') {
- --po;
- }
-
- return {po + head_empty_line_count_, false, inside_text};
- }
- }
-
- return TextHitTestResult{0, false, false};
-}
-
-void OsxCTTextLayout::ReleaseResource() {
- line_count_ = 0;
- line_origins_.clear();
- lines_.clear();
- line_ascents_.clear();
- line_descents_.clear();
- line_heights_.clear();
- if (ct_framesetter_) CFRelease(ct_framesetter_);
- if (ct_frame_) CFRelease(ct_frame_);
-}
-
-void OsxCTTextLayout::RecreateFrame() {
- ReleaseResource();
-
- ct_framesetter_ =
- CTFramesetterCreateWithAttributedString(cf_attributed_text_);
- Ensures(ct_framesetter_);
-
- CFRange fit_range;
-
- suggest_height_ =
- CTFramesetterSuggestFrameSizeWithConstraints(
- ct_framesetter_,
- CFRangeMake(0, CFAttributedStringGetLength(cf_attributed_text_)),
- nullptr, CGSizeMake(max_width_, max_height_), &fit_range)
- .height;
-
- auto path = CGPathCreateMutable();
- Ensures(path);
- CGPathAddRect(path, nullptr, CGRectMake(0, 0, max_width_, suggest_height_));
-
- ct_frame_ = CTFramesetterCreateFrame(
- ct_framesetter_,
- CFRangeMake(0, CFAttributedStringGetLength(cf_attributed_text_)), path,
- nullptr);
- Ensures(ct_frame_);
-
- CGPathRelease(path);
-
- const auto lines = CTFrameGetLines(ct_frame_);
- line_count_ = CFArrayGetCount(lines);
- lines_.resize(line_count_);
- line_origins_.resize(line_count_);
- line_ascents_.resize(line_count_);
- line_descents_.resize(line_count_);
- line_heights_.resize(line_count_);
- CTFrameGetLineOrigins(ct_frame_, CFRangeMake(0, 0), line_origins_.data());
- for (int i = 0; i < line_count_; i++) {
- lines_[i] = static_cast<CTLineRef>(CFArrayGetValueAtIndex(lines, i));
- double ascent, descent;
- CTLineGetTypographicBounds(lines_[i], &ascent, &descent, nullptr);
- line_ascents_[i] = static_cast<float>(ascent);
- line_descents_[i] = static_cast<float>(descent);
- line_heights_[i] = line_ascents_[i] + line_descents_[i];
- }
-
- auto bounds = DoGetTextBounds(false);
- text_bounds_without_trailing_space_ = bounds;
- text_bounds_with_trailing_space_ = DoGetTextBounds(true);
-
- auto right = bounds.origin.x + bounds.size.width;
- auto bottom = bounds.origin.y + bounds.size.height;
-
- transform_ =
- Matrix::Translation(-right / 2, -bottom / 2) * Matrix::Scale(1, -1) *
- Matrix::Translation(right / 2, bottom / 2) *
- Matrix::Translation(0, head_empty_line_count_ * font_->GetFontSize());
-}
-
-CTFrameRef OsxCTTextLayout::CreateFrameWithColor(const Color& color) {
- auto path = CGPathCreateMutable();
- CGPathAddRect(path, nullptr, CGRectMake(0, 0, max_width_, suggest_height_));
-
- CGColorRef cg_color =
- CGColorCreateGenericRGB(color.GetFloatRed(), color.GetFloatGreen(),
- color.GetFloatBlue(), color.GetFloatAlpha());
- CFAttributedStringSetAttribute(
- cf_attributed_text_,
- CFRangeMake(0, CFAttributedStringGetLength(cf_attributed_text_)),
- kCTForegroundColorAttributeName, cg_color);
-
- auto frame = CTFramesetterCreateFrame(
- ct_framesetter_,
- CFRangeMake(0, CFAttributedStringGetLength(cf_attributed_text_)), path,
- nullptr);
- Ensures(frame);
-
- CGPathRelease(path);
-
- return frame;
-}
-
-String OsxCTTextLayout::GetDebugString() {
- return Format(u"OsxCTTextLayout(text: {}, size: ({}, {}))", text_, max_width_,
- max_height_);
-}
-
-CGRect OsxCTTextLayout::DoGetTextBounds(bool includingTrailingSpace) {
- if (actual_text_.empty()) return CGRect{};
-
- auto rects = DoTextRangeRect(TextRange{0, actual_text_.size()});
-
- float left = std::numeric_limits<float>::max();
- float bottom = std::numeric_limits<float>::max();
- float right = 0;
- float top = 0;
-
- for (auto& rect : rects) {
- if (rect.origin.x < left) left = rect.origin.x;
- if (rect.origin.y < bottom) bottom = rect.origin.y;
- if (rect.origin.x + rect.size.width > right)
- right = rect.origin.x + rect.size.width;
- if (rect.origin.y + rect.size.height > top)
- top = rect.origin.y + rect.size.height;
- }
-
- return CGRectMake(left, bottom, right - left, top - bottom);
-}
-
-CGRect OsxCTTextLayout::DoGetTextBoundsIncludingEmptyLines(
- bool includingTrailingSpace) {
- auto result = includingTrailingSpace ? text_bounds_with_trailing_space_
- : text_bounds_without_trailing_space_;
-
- result.size.height += head_empty_line_count_ * font_->GetFontSize();
- result.size.height += tail_empty_line_count_ * font_->GetFontSize();
-
- return result;
-}
-
-std::vector<CGRect> OsxCTTextLayout::DoTextRangeRect(
- const TextRange& text_range) {
- const auto r =
- actual_text_.RangeFromCodeUnitToCodePoint(text_range).Normalize();
-
- std::vector<CGRect> results;
-
- for (int i = 0; i < line_count_; i++) {
- auto line = lines_[i];
- auto line_origin = line_origins_[i];
-
- Range range = Convert(CTLineGetStringRange(line));
- range = range.CoerceInto(r.GetStart(), r.GetEnd());
-
- if (range.count) {
- CGRect line_rect{line_origin.x, line_origin.y - line_descents_[i], 0,
- line_heights_[i]};
- float start_offset =
- CTLineGetOffsetForStringIndex(line, range.GetStart(), nullptr);
- float end_offset =
- CTLineGetOffsetForStringIndex(line, range.GetEnd(), nullptr);
- line_rect.origin.x += start_offset;
- line_rect.size.width = end_offset - start_offset;
- results.push_back(line_rect);
- }
- }
-
- return results;
-}
-
-CGRect OsxCTTextLayout::DoTextSinglePoint(Index position, bool trailing) {
- Expects(position >= 0 && position <= actual_text_.size());
-
- if (actual_text_.empty()) return CGRectMake(0, 0, 0, font_->GetFontSize());
-
- position = actual_text_.IndexFromCodeUnitToCodePoint(position);
-
- for (int i = 0; i < line_count_; i++) {
- auto line = lines_[i];
- auto line_origin = line_origins_[i];
-
- CFRange range = CTLineGetStringRange(line);
- if (range.location <= position &&
- position < range.location + range.length ||
- i == line_count_ - 1 && position == range.location + range.length) {
- auto offset = CTLineGetOffsetForStringIndex(line, position, nullptr);
- return CGRectMake(offset + line_origin.x,
- line_origin.y - line_descents_[i], 0, line_heights_[i]);
- }
- }
-
- UnreachableCode();
-}
-} // namespace cru::platform::graphics::osx::quartz
diff --git a/src/osx/gui/CMakeLists.txt b/src/osx/gui/CMakeLists.txt
deleted file mode 100644
index 5442ad15..00000000
--- a/src/osx/gui/CMakeLists.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-add_library(CruPlatformGuiOsx SHARED
- Clipboard.mm
- Cursor.mm
- InputMethod.mm
- Keyboard.mm
- Menu.mm
- Resource.cpp
- UiApplication.mm
- Window.mm
-)
-
-find_library(APPKIT AppKit REQUIRED)
-find_library(UNIFORMTYPEIDENTIFIERS UniformTypeIdentifiers REQUIRED)
-
-target_link_libraries(CruPlatformGuiOsx PUBLIC CruPlatformGui CruPlatformGraphicsQuartz ${APPKIT} ${UNIFORMTYPEIDENTIFIERS})
diff --git a/src/osx/gui/Clipboard.mm b/src/osx/gui/Clipboard.mm
deleted file mode 100644
index 6e3fb076..00000000
--- a/src/osx/gui/Clipboard.mm
+++ /dev/null
@@ -1,46 +0,0 @@
-#include "cru/osx/gui/Clipboard.h"
-#include "ClipboardPrivate.h"
-
-#include "cru/common/log/Logger.h"
-#include "cru/osx/Convert.h"
-
-#include <memory>
-
-namespace cru::platform::gui::osx {
-using cru::platform::osx::Convert;
-
-OsxClipboard::OsxClipboard(cru::platform::gui::IUiApplication* ui_application,
- std::unique_ptr<details::OsxClipboardPrivate> p)
- : OsxGuiResource(ui_application), p_(std::move(p)) {}
-
-OsxClipboard::~OsxClipboard() {}
-
-String OsxClipboard::GetText() { return p_->GetText(); }
-
-void OsxClipboard::SetText(String text) { p_->SetText(text); }
-
-namespace details {
-OsxClipboardPrivate::OsxClipboardPrivate(NSPasteboard* pasteboard) : pasteboard_(pasteboard) {}
-
-OsxClipboardPrivate::~OsxClipboardPrivate() {}
-
-String OsxClipboardPrivate::GetText() {
- auto result = [pasteboard_ readObjectsForClasses:@[ NSString.class ] options:nil];
- if (result == nil) {
- CRU_LOG_WARN(u"Failed to get text from clipboard");
- return u"";
- } else {
- if (result.count == 0) {
- return u"";
- } else {
- return Convert((CFStringRef)result[0]);
- }
- }
-}
-
-void OsxClipboardPrivate::SetText(String text) {
- [pasteboard_ clearContents];
- [pasteboard_ writeObjects:@[ (NSString*)Convert(text) ]];
-}
-}
-} // namespace cru::platform::gui::osx
diff --git a/src/osx/gui/ClipboardPrivate.h b/src/osx/gui/ClipboardPrivate.h
deleted file mode 100644
index 63145a64..00000000
--- a/src/osx/gui/ClipboardPrivate.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#pragma once
-#include "cru/common/Base.h"
-#include "cru/osx/gui/Clipboard.h"
-
-#include <AppKit/AppKit.h>
-
-namespace cru::platform::gui::osx {
-namespace details {
-class OsxClipboardPrivate : public Object {
- CRU_DEFINE_CLASS_LOG_TAG(u"OsxClipboardPrivate")
- public:
- explicit OsxClipboardPrivate(NSPasteboard* pasteboard);
-
- CRU_DELETE_COPY(OsxClipboardPrivate)
- CRU_DELETE_MOVE(OsxClipboardPrivate)
-
- ~OsxClipboardPrivate();
-
- public:
- String GetText();
- void SetText(String text);
-
- private:
- NSPasteboard* pasteboard_;
-};
-} // namespace details
-} // namespace cru::platform::gui::osx
diff --git a/src/osx/gui/Cursor.mm b/src/osx/gui/Cursor.mm
deleted file mode 100644
index 13bdc858..00000000
--- a/src/osx/gui/Cursor.mm
+++ /dev/null
@@ -1,93 +0,0 @@
-#include "cru/osx/gui/Cursor.h"
-#include "CursorPrivate.h"
-
-#include "cru/osx/Exception.h"
-#include "cru/osx/gui/Resource.h"
-#include "cru/platform/gui/Cursor.h"
-#include "cru/platform/gui/UiApplication.h"
-
-#include <memory>
-
-namespace cru::platform::gui::osx {
-namespace details {
-OsxCursorPrivate::OsxCursorPrivate(OsxCursor* cursor, SystemCursorType cursor_type) {
- cursor_ = cursor;
-
- switch (cursor_type) {
- case SystemCursorType::Arrow:
- ns_cursor_ = [NSCursor arrowCursor];
- break;
- case SystemCursorType::Hand:
- ns_cursor_ = [NSCursor pointingHandCursor];
- break;
- case SystemCursorType::IBeam:
- ns_cursor_ = [NSCursor IBeamCursor];
- break;
- default:
- throw Exception(u"Unknown system cursor type.");
- }
-}
-
-OsxCursorPrivate::~OsxCursorPrivate() {}
-}
-
-OsxCursor::OsxCursor(IUiApplication* ui_application, SystemCursorType cursor_type)
- : OsxGuiResource(ui_application) {
- p_ = std::make_unique<details::OsxCursorPrivate>(this, cursor_type);
-}
-
-OsxCursor::~OsxCursor() {}
-
-namespace details {
-class OsxCursorManagerPrivate {
- friend OsxCursorManager;
-
- public:
- explicit OsxCursorManagerPrivate(OsxCursorManager* cursor_manager);
-
- CRU_DELETE_COPY(OsxCursorManagerPrivate)
- CRU_DELETE_MOVE(OsxCursorManagerPrivate)
-
- ~OsxCursorManagerPrivate();
-
- private:
- OsxCursorManager* cursor_manager_;
-
- std::shared_ptr<OsxCursor> arrow_cursor_;
- std::shared_ptr<OsxCursor> hand_cursor_;
- std::shared_ptr<OsxCursor> ibeam_cursor_;
-};
-
-OsxCursorManagerPrivate::OsxCursorManagerPrivate(OsxCursorManager* cursor_manager) {
- cursor_manager_ = cursor_manager;
- arrow_cursor_ =
- std::make_shared<OsxCursor>(cursor_manager->GetUiApplication(), SystemCursorType::Arrow);
- hand_cursor_ =
- std::make_shared<OsxCursor>(cursor_manager->GetUiApplication(), SystemCursorType::Hand);
- ibeam_cursor_ =
- std::make_shared<OsxCursor>(cursor_manager->GetUiApplication(), SystemCursorType::IBeam);
-}
-
-OsxCursorManagerPrivate::~OsxCursorManagerPrivate() {}
-}
-
-OsxCursorManager::OsxCursorManager(IUiApplication* ui_application)
- : OsxGuiResource(ui_application) {
- p_ = std::make_unique<details::OsxCursorManagerPrivate>(this);
-}
-
-OsxCursorManager::~OsxCursorManager() {}
-
-std::shared_ptr<ICursor> OsxCursorManager::GetSystemCursor(SystemCursorType type) {
- switch (type) {
- case SystemCursorType::Arrow:
- return p_->arrow_cursor_;
- case SystemCursorType::Hand:
- return p_->hand_cursor_;
- case SystemCursorType::IBeam:
- return p_->ibeam_cursor_;
- default:
- throw Exception(u"Unknown system cursor type.");
- }
-}
-}
diff --git a/src/osx/gui/CursorPrivate.h b/src/osx/gui/CursorPrivate.h
deleted file mode 100644
index c840e286..00000000
--- a/src/osx/gui/CursorPrivate.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#pragma once
-#include "cru/osx/gui/Cursor.h"
-
-#import <AppKit/NSCursor.h>
-
-namespace cru::platform::gui::osx {
-class OsxWindow;
-
-namespace details {
-class OsxWindowPrivate;
-
-class OsxCursorPrivate {
- friend OsxWindow;
- friend OsxWindowPrivate;
-
- public:
- OsxCursorPrivate(OsxCursor* cursor, SystemCursorType cursor_type);
-
- CRU_DELETE_COPY(OsxCursorPrivate)
- CRU_DELETE_MOVE(OsxCursorPrivate)
-
- ~OsxCursorPrivate();
-
- private:
- OsxCursor* cursor_;
- NSCursor* ns_cursor_;
-};
-} // namespace details
-} // namespace cru::platform::gui::osx
diff --git a/src/osx/gui/InputMethod.mm b/src/osx/gui/InputMethod.mm
deleted file mode 100644
index 2c19c358..00000000
--- a/src/osx/gui/InputMethod.mm
+++ /dev/null
@@ -1,84 +0,0 @@
-#include "cru/osx/gui/InputMethod.h"
-
-#import <AppKit/AppKit.h>
-#include "InputMethodPrivate.h"
-#include "WindowPrivate.h"
-#include "cru/common/log/Logger.h"
-#include "cru/osx/Convert.h"
-#include "cru/osx/gui/Window.h"
-
-namespace cru::platform::gui::osx {
-namespace details {
-OsxInputMethodContextPrivate::OsxInputMethodContextPrivate(
- OsxInputMethodContext* input_method_context, OsxWindow* window) {
- input_method_context_ = input_method_context;
- window_ = window;
-}
-
-OsxInputMethodContextPrivate::~OsxInputMethodContextPrivate() {}
-
-void OsxInputMethodContextPrivate::RaiseCompositionStartEvent() {
- composition_start_event_.Raise(nullptr);
-}
-void OsxInputMethodContextPrivate::RaiseCompositionEndEvent() {
- composition_end_event_.Raise(nullptr);
-}
-void OsxInputMethodContextPrivate::RaiseCompositionEvent() { composition_event_.Raise(nullptr); }
-
-void OsxInputMethodContextPrivate::RaiseTextEvent(StringView text) { text_event_.Raise(text); }
-
-void OsxInputMethodContextPrivate::PerformSel(SEL sel) {
- // [window_->p_->GetNSWindow() performSelector:sel];
-}
-
-void OsxInputMethodContextPrivate::Activate() { is_enabled_ = true; }
-
-void OsxInputMethodContextPrivate::Deactivate() {
- input_method_context_->CompleteComposition();
- is_enabled_ = false;
-}
-}
-
-OsxInputMethodContext::OsxInputMethodContext(OsxWindow* window)
- : OsxGuiResource(window->GetUiApplication()) {
- p_ = std::make_unique<details::OsxInputMethodContextPrivate>(this, window);
-}
-
-OsxInputMethodContext::~OsxInputMethodContext() {}
-
-void OsxInputMethodContext::EnableIME() { p_->Activate(); }
-
-void OsxInputMethodContext::DisableIME() { p_->Deactivate(); }
-
-bool OsxInputMethodContext::ShouldManuallyDrawCompositionText() { return true; }
-
-void OsxInputMethodContext::CompleteComposition() {
- // TODO: Implement this.
-}
-
-void OsxInputMethodContext::CancelComposition() {
- [[NSTextInputContext currentInputContext] discardMarkedText];
-}
-
-CompositionText OsxInputMethodContext::GetCompositionText() { return p_->composition_text_; }
-
-void OsxInputMethodContext::SetCandidateWindowPosition(const Point& point) {
- p_->SetCandidateWindowPosition(point);
-}
-
-IEvent<std::nullptr_t>* OsxInputMethodContext::CompositionStartEvent() {
- return &p_->composition_start_event_;
-}
-
-IEvent<std::nullptr_t>* OsxInputMethodContext::CompositionEndEvent() {
- return &p_->composition_end_event_;
-}
-
-IEvent<std::nullptr_t>* OsxInputMethodContext::CompositionEvent() {
- return &p_->composition_event_;
-}
-
-IEvent<StringView>* OsxInputMethodContext::TextEvent() { return &p_->text_event_; }
-
-bool OsxInputMethodContext::IsEnabled() { return p_->is_enabled_; }
-}
diff --git a/src/osx/gui/InputMethodPrivate.h b/src/osx/gui/InputMethodPrivate.h
deleted file mode 100644
index 1df21b37..00000000
--- a/src/osx/gui/InputMethodPrivate.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#pragma once
-#include "cru/osx/gui/InputMethod.h"
-
-#include <AppKit/AppKit.h>
-
-namespace cru::platform::gui::osx {
-namespace details {
-class OsxInputMethodContextPrivate {
- friend OsxInputMethodContext;
-
- public:
- OsxInputMethodContextPrivate(OsxInputMethodContext* input_method_context,
- OsxWindow* window);
-
- CRU_DELETE_COPY(OsxInputMethodContextPrivate)
- CRU_DELETE_MOVE(OsxInputMethodContextPrivate)
-
- ~OsxInputMethodContextPrivate();
-
- void SetCompositionText(CompositionText composition_text) {
- composition_text_ = std::move(composition_text);
- }
-
- void RaiseCompositionStartEvent();
- void RaiseCompositionEndEvent();
- void RaiseCompositionEvent();
- void RaiseTextEvent(StringView text);
-
- Point GetCandidateWindowPosition() const { return candidate_window_point_; }
- void SetCandidateWindowPosition(const Point& p) {
- candidate_window_point_ = p;
- }
-
- Range GetSelectionRange() const { return selection_range_; }
- void SetSelectionRange(Range selection_range) {
- selection_range_ = selection_range;
- }
-
- void PerformSel(SEL sel);
-
- void Activate();
- void Deactivate();
-
- private:
- OsxWindow* window_;
-
- CompositionText composition_text_;
-
- Range selection_range_;
-
- OsxInputMethodContext* input_method_context_;
-
- // On Osx, this is the text lefttop point on screen.
- Point candidate_window_point_;
-
- Event<std::nullptr_t> composition_start_event_;
- Event<std::nullptr_t> composition_event_;
- Event<std::nullptr_t> composition_end_event_;
- Event<StringView> text_event_;
-
- bool is_enabled_ = false;
-};
-} // namespace details
-} // namespace cru::platform::gui::osx
diff --git a/src/osx/gui/Keyboard.mm b/src/osx/gui/Keyboard.mm
deleted file mode 100644
index 3e78eecb..00000000
--- a/src/osx/gui/Keyboard.mm
+++ /dev/null
@@ -1,283 +0,0 @@
-#include "cru/osx/gui/Keyboard.h"
-
-#import <AppKit/NSText.h>
-#import <Carbon/Carbon.h>
-#import "KeyboardPrivate.h"
-
-namespace cru::platform::gui::osx {
-KeyCode KeyCodeFromOsxToCru(unsigned short n) {
- switch (n) {
-#define CRU_DEFINE_KEYCODE_MAP(osx, cru) \
- case osx: \
- return cru;
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_0, KeyCode::N0)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_1, KeyCode::N1)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_2, KeyCode::N2)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_3, KeyCode::N3)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_4, KeyCode::N4)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_5, KeyCode::N5)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_6, KeyCode::N6)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_7, KeyCode::N7)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_8, KeyCode::N8)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_9, KeyCode::N9)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_A, KeyCode::A)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_B, KeyCode::B)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_C, KeyCode::C)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_D, KeyCode::D)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_E, KeyCode::E)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_F, KeyCode::F)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_G, KeyCode::G)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_H, KeyCode::H)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_I, KeyCode::I)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_J, KeyCode::J)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_K, KeyCode::K)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_L, KeyCode::L)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_M, KeyCode::M)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_N, KeyCode::N)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_O, KeyCode::O)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_P, KeyCode::P)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Q, KeyCode::Q)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_R, KeyCode::R)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_S, KeyCode::S)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_T, KeyCode::T)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_U, KeyCode::U)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_V, KeyCode::V)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_W, KeyCode::W)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_X, KeyCode::X)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Y, KeyCode::Y)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Z, KeyCode::Z)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Comma, KeyCode::Comma)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Period, KeyCode::Period)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Slash, KeyCode::Slash)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Semicolon, KeyCode::Semicolon)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Quote, KeyCode::Quote)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_LeftBracket, KeyCode::LeftSquareBracket)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_RightBracket, KeyCode::RightSquareBracket)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Minus, KeyCode::Minus)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Equal, KeyCode::Equal)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Backslash, KeyCode::BackSlash)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Grave, KeyCode::GraveAccent)
- CRU_DEFINE_KEYCODE_MAP(kVK_Escape, KeyCode::Escape)
- CRU_DEFINE_KEYCODE_MAP(kVK_Tab, KeyCode::Tab)
- CRU_DEFINE_KEYCODE_MAP(kVK_CapsLock, KeyCode::CapsLock)
- CRU_DEFINE_KEYCODE_MAP(kVK_Shift, KeyCode::LeftShift)
- CRU_DEFINE_KEYCODE_MAP(kVK_RightShift, KeyCode::RightShift)
- CRU_DEFINE_KEYCODE_MAP(kVK_Control, KeyCode::LeftCtrl)
- CRU_DEFINE_KEYCODE_MAP(kVK_RightControl, KeyCode::RightCtrl)
- CRU_DEFINE_KEYCODE_MAP(kVK_Option, KeyCode::LeftAlt)
- CRU_DEFINE_KEYCODE_MAP(kVK_RightOption, KeyCode::RightAlt)
- CRU_DEFINE_KEYCODE_MAP(kVK_Command, KeyCode::LeftCommand)
- CRU_DEFINE_KEYCODE_MAP(kVK_RightCommand, KeyCode::RightCommand)
- CRU_DEFINE_KEYCODE_MAP(kVK_Delete, KeyCode::Backspace)
- CRU_DEFINE_KEYCODE_MAP(kVK_Return, KeyCode::Return)
- CRU_DEFINE_KEYCODE_MAP(kVK_ForwardDelete, KeyCode::Delete)
- CRU_DEFINE_KEYCODE_MAP(kVK_Home, KeyCode::Home)
- CRU_DEFINE_KEYCODE_MAP(kVK_End, KeyCode::End)
- CRU_DEFINE_KEYCODE_MAP(kVK_PageUp, KeyCode::PageUp)
- CRU_DEFINE_KEYCODE_MAP(kVK_PageDown, KeyCode::PageDown)
- CRU_DEFINE_KEYCODE_MAP(kVK_LeftArrow, KeyCode::Left)
- CRU_DEFINE_KEYCODE_MAP(kVK_RightArrow, KeyCode::Right)
- CRU_DEFINE_KEYCODE_MAP(kVK_UpArrow, KeyCode::Up)
- CRU_DEFINE_KEYCODE_MAP(kVK_DownArrow, KeyCode::Down)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad0, KeyCode::NumPad0)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad1, KeyCode::NumPad1)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad2, KeyCode::NumPad2)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad3, KeyCode::NumPad3)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad4, KeyCode::NumPad4)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad5, KeyCode::NumPad5)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad6, KeyCode::NumPad6)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad7, KeyCode::NumPad7)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad8, KeyCode::NumPad8)
- CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad9, KeyCode::NumPad9)
- CRU_DEFINE_KEYCODE_MAP(kVK_Space, KeyCode::Space)
- default:
- return KeyCode::Unknown;
- }
-
-#undef CRU_DEFINE_KEYCODE_MAP
-}
-
-unsigned short KeyCodeFromCruToOsx(KeyCode k) {
- switch (k) {
-#define CRU_DEFINE_KEYCODE_MAP(cru, osx) \
- case cru: \
- return osx;
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N0, kVK_ANSI_0)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N1, kVK_ANSI_1)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N2, kVK_ANSI_2)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N3, kVK_ANSI_3)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N4, kVK_ANSI_4)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N5, kVK_ANSI_5)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N6, kVK_ANSI_6)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N7, kVK_ANSI_7)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N8, kVK_ANSI_8)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N9, kVK_ANSI_9)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::A, kVK_ANSI_A)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::B, kVK_ANSI_B)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::C, kVK_ANSI_C)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::D, kVK_ANSI_D)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::E, kVK_ANSI_E)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::F, kVK_ANSI_F)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::G, kVK_ANSI_G)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::H, kVK_ANSI_H)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::I, kVK_ANSI_I)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::J, kVK_ANSI_J)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::K, kVK_ANSI_K)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::L, kVK_ANSI_L)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::M, kVK_ANSI_M)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N, kVK_ANSI_N)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::O, kVK_ANSI_O)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::P, kVK_ANSI_P)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Q, kVK_ANSI_Q)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::R, kVK_ANSI_R)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::S, kVK_ANSI_S)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::T, kVK_ANSI_T)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::U, kVK_ANSI_U)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::V, kVK_ANSI_V)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::W, kVK_ANSI_W)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::X, kVK_ANSI_X)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Y, kVK_ANSI_Y)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Z, kVK_ANSI_Z)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Comma, kVK_ANSI_Comma)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Period, kVK_ANSI_Period)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Slash, kVK_ANSI_Slash)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Semicolon, kVK_ANSI_Semicolon)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Quote, kVK_ANSI_Quote)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::LeftSquareBracket, kVK_ANSI_LeftBracket)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::RightSquareBracket, kVK_ANSI_RightBracket)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Minus, kVK_ANSI_Minus)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Equal, kVK_ANSI_Equal)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::BackSlash, kVK_ANSI_Backslash)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::GraveAccent, kVK_ANSI_Grave)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Escape, kVK_Escape)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Tab, kVK_Tab)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::CapsLock, kVK_CapsLock)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::LeftShift, kVK_Shift)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::RightShift, kVK_RightShift)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::LeftCtrl, kVK_Control)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::RightCtrl, kVK_RightControl)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::LeftAlt, kVK_Option)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::RightAlt, kVK_RightOption)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::LeftCommand, kVK_Command)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::RightCommand, kVK_RightCommand)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Backspace, kVK_Delete)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Return, kVK_Return)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Delete, kVK_ForwardDelete)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Home, kVK_Home)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::End, kVK_End)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::PageUp, kVK_PageUp)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::PageDown, kVK_PageDown)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Left, kVK_LeftArrow)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Right, kVK_RightArrow)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Up, kVK_UpArrow)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Down, kVK_DownArrow)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad0, kVK_ANSI_Keypad0)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad1, kVK_ANSI_Keypad1)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad2, kVK_ANSI_Keypad2)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad3, kVK_ANSI_Keypad3)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad4, kVK_ANSI_Keypad4)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad5, kVK_ANSI_Keypad5)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad6, kVK_ANSI_Keypad6)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad7, kVK_ANSI_Keypad7)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad8, kVK_ANSI_Keypad8)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad9, kVK_ANSI_Keypad9)
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Space, kVK_Space)
- default:
- return 0;
- }
-#undef CRU_DEFINE_KEYCODE_MAP
-}
-
-NSString* ConvertKeyCodeToKeyEquivalent(KeyCode key_code) {
-#define CRU_DEFINE_KEYCODE_MAP(key_code, str) \
- case key_code: \
- return str;
-
- switch (key_code) {
- CRU_DEFINE_KEYCODE_MAP(KeyCode::A, @"a")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::B, @"b")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::C, @"c")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::D, @"d")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::E, @"e")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::F, @"f")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::G, @"g")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::H, @"h")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::I, @"i")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::J, @"j")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::K, @"k")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::L, @"l")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::M, @"m")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N, @"n")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::O, @"o")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::P, @"p")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Q, @"q")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::R, @"r")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::S, @"s")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::T, @"t")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::U, @"u")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::V, @"v")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::W, @"w")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::X, @"x")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Y, @"y")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Z, @"z")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N0, @"0")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N1, @"1")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N2, @"2")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N3, @"3")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N4, @"4")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N5, @"5")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N6, @"6")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N7, @"7")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N8, @"8")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::N9, @"9")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::F1, @"F1")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::F2, @"F2")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::F3, @"F3")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::F4, @"F4")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::F5, @"F5")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::F6, @"F6")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::F7, @"F7")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::F8, @"F8")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::F9, @"F9")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::F10, @"F10")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::F11, @"F11")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::F12, @"F12")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Minus, @"-")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Equal, @"=")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Comma, @",")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Period, @".")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Slash, @"/")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Semicolon, @";")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Quote, @"'")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::LeftSquareBracket, @"[")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::RightSquareBracket, @"]")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::BackSlash, @"\\")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::GraveAccent, @"`")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Return, @"\n")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Escape, @"\e")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Tab, @"\t")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Backspace, @"\x08")
- CRU_DEFINE_KEYCODE_MAP(KeyCode::Delete, @"\x7F")
- default:
- throw Exception(u"Failed to convert key code to key equivalent string.");
- }
-#undef CRU_DEFINE_KEYCODE_MAP
-}
-
-NSEventModifierFlags ConvertKeyModifier(KeyModifier k) {
- NSEventModifierFlags flags = 0;
- if (k & KeyModifiers::shift) {
- flags |= NSEventModifierFlagShift;
- }
- if (k & KeyModifiers::ctrl) {
- flags |= NSEventModifierFlagControl;
- }
- if (k & KeyModifiers::alt) {
- flags |= NSEventModifierFlagOption;
- }
- if (k & KeyModifiers::command) {
- flags |= NSEventModifierFlagCommand;
- }
- return flags;
-}
-}
diff --git a/src/osx/gui/KeyboardPrivate.h b/src/osx/gui/KeyboardPrivate.h
deleted file mode 100644
index b98ea5d4..00000000
--- a/src/osx/gui/KeyboardPrivate.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-#include "cru/osx/gui/Keyboard.h"
-
-#import <AppKit/NSEvent.h>
-
-namespace cru::platform::gui::osx {
-NSString* ConvertKeyCodeToKeyEquivalent(KeyCode key_code);
-NSEventModifierFlags ConvertKeyModifier(KeyModifier k);
-}
diff --git a/src/osx/gui/Menu.mm b/src/osx/gui/Menu.mm
deleted file mode 100644
index 5d0fd4d5..00000000
--- a/src/osx/gui/Menu.mm
+++ /dev/null
@@ -1,180 +0,0 @@
-#include "cru/osx/gui/Menu.h"
-#import "MenuPrivate.h"
-
-#include "KeyboardPrivate.h"
-#include "cru/common/platform/osx/Convert.h"
-
-#import <AppKit/NSApplication.h>
-
-namespace cru::platform::gui::osx {
-using platform::osx::Convert;
-
-namespace {
-std::unique_ptr<OsxMenu> application_menu = nullptr;
-}
-
-namespace details {
-OsxMenuItemPrivate::OsxMenuItemPrivate(OsxMenuItem* d) {
- d_ = d;
- sub_menu_ = new OsxMenu(d->GetUiApplication());
- sub_menu_->p_->SetParentItem(d);
- handler_ = [[CruOsxMenuItemClickHandler alloc] init:this];
-}
-
-OsxMenuItemPrivate::~OsxMenuItemPrivate() { delete sub_menu_; }
-
-void OsxMenuItemPrivate::AttachToNative(NSMenuItem* native_menu_item, bool check_submenu) {
- Expects(sub_menu_);
-
- menu_item_ = native_menu_item;
- [native_menu_item setTarget:handler_];
- [native_menu_item setAction:@selector(handleClick)];
- if (check_submenu && [native_menu_item hasSubmenu]) {
- sub_menu_->p_->AttachToNative([native_menu_item submenu]);
- }
-}
-
-OsxMenuPrivate::OsxMenuPrivate(OsxMenu* d) { d_ = d; }
-
-OsxMenuPrivate::~OsxMenuPrivate() {
- for (auto item : items_) {
- delete item;
- }
-}
-
-void OsxMenuPrivate::AttachToNative(NSMenu* native_menu) {
- menu_ = native_menu;
-
- auto item_count = [native_menu numberOfItems];
- for (int i = 0; i < item_count; i++) {
- auto native_item = [native_menu itemAtIndex:i];
- auto item = new OsxMenuItem(d_->GetUiApplication());
- item->p_->SetParentMenu(d_);
- item->p_->AttachToNative(native_item, true);
- items_.push_back(item);
- }
-}
-}
-
-OsxMenuItem::OsxMenuItem(IUiApplication* ui_application) : OsxGuiResource(ui_application) {
- p_ = new details::OsxMenuItemPrivate(this);
-}
-
-OsxMenuItem::~OsxMenuItem() { delete p_; }
-
-String OsxMenuItem::GetTitle() { return Convert((CFStringRef)[p_->menu_item_ title]); }
-
-void OsxMenuItem::SetTitle(String title) { [p_->menu_item_ setTitle:(NSString*)Convert(title)]; }
-
-bool OsxMenuItem::IsEnabled() { return [p_->menu_item_ isEnabled]; }
-
-void OsxMenuItem::SetEnabled(bool enabled) { [p_->menu_item_ setEnabled:enabled]; }
-
-IMenu* OsxMenuItem::GetParentMenu() { return p_->parent_menu_; }
-
-IMenu* OsxMenuItem::GetSubmenu() { return p_->sub_menu_; }
-
-void OsxMenuItem::SetKeyboardShortcut(KeyCode key, KeyModifier modifiers) {
- [p_->menu_item_ setKeyEquivalent:ConvertKeyCodeToKeyEquivalent(key)];
- [p_->menu_item_ setKeyEquivalentModifierMask:ConvertKeyModifier(modifiers)];
-}
-
-void OsxMenuItem::DeleteKeyboardShortcut() {
- [p_->menu_item_ setKeyEquivalent:@""];
- [p_->menu_item_ setKeyEquivalentModifierMask:0];
-}
-
-void OsxMenuItem::SetOnClickHandler(std::function<void()> handler) {
- p_->on_click_handler_ = std::move(handler);
-}
-
-OsxMenu* OsxMenu::CreateOrGetApplicationMenu(IUiApplication* ui_application) {
- if (application_menu) {
- return application_menu.get();
- }
-
- NSMenu* native_main_menu = [[NSMenu alloc] init];
- [NSApp setMainMenu:native_main_menu];
- [native_main_menu setAutoenablesItems:NO];
-
- application_menu.reset(new OsxMenu(ui_application));
- application_menu->p_->AttachToNative(native_main_menu);
-
- application_menu->CreateItemAt(0);
-
- return application_menu.get();
-}
-
-OsxMenu::OsxMenu(IUiApplication* ui_application) : OsxGuiResource(ui_application) {
- p_ = new details::OsxMenuPrivate(this);
-}
-
-OsxMenu::~OsxMenu() { delete p_; }
-
-IMenuItem* OsxMenu::GetItemAt(int index) {
- if (index < 0 || index >= p_->items_.size()) {
- return nullptr;
- }
-
- return p_->items_[index];
-}
-
-int OsxMenu::GetItemCount() { return p_->items_.size(); }
-
-IMenuItem* OsxMenu::CreateItemAt(int index) {
- if (index < 0) index = 0;
- if (index > p_->items_.size()) index = p_->items_.size();
-
- if (p_->parent_item_ && p_->items_.empty()) {
- Expects(p_->menu_ == nullptr);
- p_->menu_ = [[NSMenu alloc] init];
- [p_->menu_ setAutoenablesItems:NO];
- [p_->parent_item_->p_->GetNative() setSubmenu:p_->menu_];
- }
-
- auto native_item = [[NSMenuItem alloc] init];
- [p_->menu_ insertItem:native_item atIndex:index];
-
- auto item = new OsxMenuItem(GetUiApplication());
- item->p_->SetParentMenu(this);
- item->p_->AttachToNative(native_item, false);
- p_->items_.insert(p_->items_.begin() + index, item);
-
- return item;
-}
-
-void OsxMenu::RemoveItemAt(int index) {
- if (index < 0 || index >= p_->items_.size()) {
- return;
- }
-
- auto item = p_->items_[index];
- [p_->menu_ removeItem:item->p_->GetNative()];
- p_->items_.erase(p_->items_.begin() + index);
-
- delete item;
-
- if (p_->items_.empty() && p_->parent_item_) {
- Expects(p_->menu_ != nullptr);
- [p_->parent_item_->p_->GetNative() setSubmenu:nullptr];
- p_->menu_ = nullptr;
- }
-}
-}
-
-@implementation CruOsxMenuItemClickHandler {
- cru::platform::gui::osx::details::OsxMenuItemPrivate* p_;
-}
-
-- (id)init:(cru::platform::gui::osx::details::OsxMenuItemPrivate*)p {
- p_ = p;
- return self;
-}
-
-- (void)handleClick {
- if (p_->GetOnClickHandler()) {
- p_->GetOnClickHandler()();
- }
-}
-
-@end
diff --git a/src/osx/gui/MenuPrivate.h b/src/osx/gui/MenuPrivate.h
deleted file mode 100644
index d5269312..00000000
--- a/src/osx/gui/MenuPrivate.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#pragma once
-#include "cru/osx/gui/Menu.h"
-
-#import <AppKit/NSMenu.h>
-#import <AppKit/NSMenuItem.h>
-
-@interface CruOsxMenuItemClickHandler : NSObject
-- init:(cru::platform::gui::osx::details::OsxMenuItemPrivate*)p;
-- (void)handleClick;
-@end
-
-namespace cru::platform::gui::osx {
-namespace details {
-
-class OsxMenuItemPrivate {
- friend OsxMenuItem;
-
- public:
- explicit OsxMenuItemPrivate(OsxMenuItem* d);
-
- CRU_DELETE_COPY(OsxMenuItemPrivate)
- CRU_DELETE_MOVE(OsxMenuItemPrivate)
-
- ~OsxMenuItemPrivate();
-
- public:
- NSMenuItem* GetNative() { return menu_item_; }
- void SetParentMenu(OsxMenu* menu) { parent_menu_ = menu; }
- void AttachToNative(NSMenuItem* native_menu_item, bool check_submenu);
-
- const std::function<void()> GetOnClickHandler() const { return on_click_handler_; }
-
- private:
- OsxMenuItem* d_;
- OsxMenu* parent_menu_ = nullptr;
- NSMenuItem* menu_item_ = nullptr;
- OsxMenu* sub_menu_ = nullptr;
- std::function<void()> on_click_handler_;
- CruOsxMenuItemClickHandler* handler_;
-};
-
-class OsxMenuPrivate {
- friend OsxMenu;
-
- public:
- explicit OsxMenuPrivate(OsxMenu* d);
-
- CRU_DELETE_COPY(OsxMenuPrivate)
- CRU_DELETE_MOVE(OsxMenuPrivate)
-
- ~OsxMenuPrivate();
-
- public:
- void SetParentItem(OsxMenuItem* item) { parent_item_ = item; }
- void AttachToNative(NSMenu* native_menu);
-
- private:
- OsxMenu* d_;
- OsxMenuItem* parent_item_ = nullptr;
- NSMenu* menu_ = nullptr;
- std::vector<OsxMenuItem*> items_;
-};
-} // namespace details
-
-} // namespace cru::platform::gui::osx
diff --git a/src/osx/gui/Resource.cpp b/src/osx/gui/Resource.cpp
deleted file mode 100644
index a6be5d75..00000000
--- a/src/osx/gui/Resource.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "cru/osx/gui/Resource.h"
-
-namespace cru::platform::gui::osx {
-OsxGuiResource::OsxGuiResource(IUiApplication* ui_application)
- : ui_application_(ui_application) {}
-} // namespace cru::platform::gui::osx
diff --git a/src/osx/gui/UiApplication.mm b/src/osx/gui/UiApplication.mm
deleted file mode 100644
index 43c49c5c..00000000
--- a/src/osx/gui/UiApplication.mm
+++ /dev/null
@@ -1,260 +0,0 @@
-#include "cru/osx/gui/UiApplication.h"
-
-#include "ClipboardPrivate.h"
-#include "cru/common/log/Logger.h"
-#include "cru/common/platform/osx/Convert.h"
-#include "cru/osx/graphics/quartz/Factory.h"
-#include "cru/osx/gui/Clipboard.h"
-#include "cru/osx/gui/Cursor.h"
-#include "cru/osx/gui/Menu.h"
-#include "cru/osx/gui/Window.h"
-#include "cru/platform/graphics/Factory.h"
-#include "cru/platform/gui/Base.h"
-#include "cru/platform/gui/UiApplication.h"
-#include "cru/platform/gui/Window.h"
-
-#include <AppKit/NSApplication.h>
-#include <Foundation/NSRunLoop.h>
-#include <UniformTypeIdentifiers/UTType.h>
-
-#include <algorithm>
-#include <iterator>
-#include <memory>
-#include <unordered_map>
-#include <vector>
-
-@interface CruAppDelegate : NSObject <NSApplicationDelegate>
-- (id)init:(cru::platform::gui::osx::details::OsxUiApplicationPrivate*)p;
-- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender;
-- (void)applicationWillTerminate:(NSNotification*)notification;
-@end
-
-namespace cru::platform::gui::osx {
-
-using cru::platform::osx::Convert;
-
-namespace details {
-class OsxUiApplicationPrivate {
- friend OsxUiApplication;
-
- public:
- explicit OsxUiApplicationPrivate(OsxUiApplication* osx_ui_application)
- : osx_ui_application_(osx_ui_application) {
- app_delegate_ = [[CruAppDelegate alloc] init:this];
- }
-
- CRU_DELETE_COPY(OsxUiApplicationPrivate)
- CRU_DELETE_MOVE(OsxUiApplicationPrivate)
-
- ~OsxUiApplicationPrivate() = default;
-
- void CallQuitHandlers();
-
- private:
- OsxUiApplication* osx_ui_application_;
- CruAppDelegate* app_delegate_;
- std::vector<std::function<void()>> quit_handlers_;
- bool quit_on_all_window_closed_ = true;
-
- long long current_timer_id_ = 1;
- std::unordered_map<long long, std::function<void()>> next_tick_;
- std::unordered_map<long long, NSTimer*> timers_;
-
- std::vector<OsxWindow*> windows_;
-
- std::unique_ptr<OsxCursorManager> cursor_manager_;
-
- std::unique_ptr<OsxClipboard> clipboard_;
-
- std::unique_ptr<platform::graphics::osx::quartz::QuartzGraphicsFactory> quartz_graphics_factory_;
-};
-
-void OsxUiApplicationPrivate::CallQuitHandlers() {
- for (const auto& handler : quit_handlers_) {
- handler();
- }
-}
-}
-
-OsxUiApplication::OsxUiApplication()
- : OsxGuiResource(this), p_(new details::OsxUiApplicationPrivate(this)) {
- [NSApplication sharedApplication];
-
- [NSApp setDelegate:p_->app_delegate_];
- p_->quartz_graphics_factory_ = std::make_unique<graphics::osx::quartz::QuartzGraphicsFactory>();
- p_->cursor_manager_ = std::make_unique<OsxCursorManager>(this);
- p_->clipboard_ = std::make_unique<OsxClipboard>(
- this, std::make_unique<details::OsxClipboardPrivate>([NSPasteboard generalPasteboard]));
-}
-
-OsxUiApplication::~OsxUiApplication() {}
-
-int OsxUiApplication::Run() {
- [NSApp run];
- return 0;
-}
-
-void OsxUiApplication::RequestQuit(int quit_code) {
- [NSApp terminate:[NSNumber numberWithInteger:quit_code]];
-}
-
-void OsxUiApplication::AddOnQuitHandler(std::function<void()> handler) {
- p_->quit_handlers_.push_back(std::move(handler));
-}
-
-bool OsxUiApplication::IsQuitOnAllWindowClosed() { return p_->quit_on_all_window_closed_; }
-
-void OsxUiApplication::SetQuitOnAllWindowClosed(bool quit_on_all_window_closed) {
- p_->quit_on_all_window_closed_ = quit_on_all_window_closed;
-}
-
-long long OsxUiApplication::SetImmediate(std::function<void()> action) {
- const long long id = p_->current_timer_id_++;
- p_->next_tick_.emplace(id, std::move(action));
-
- [[NSRunLoop mainRunLoop] performBlock:^{
- const auto i = p_->next_tick_.find(id);
- if (i != p_->next_tick_.cend()) {
- i->second();
- }
- p_->next_tick_.erase(i);
- }];
-
- return id;
-}
-
-long long OsxUiApplication::SetTimeout(std::chrono::milliseconds milliseconds,
- std::function<void()> action) {
- long long id = p_->current_timer_id_++;
- p_->timers_.emplace(id, [NSTimer scheduledTimerWithTimeInterval:milliseconds.count() / 1000.0
- repeats:false
- block:^(NSTimer* timer) {
- action();
- p_->timers_.erase(id);
- }]);
-
- return id;
-}
-
-long long OsxUiApplication::SetInterval(std::chrono::milliseconds milliseconds,
- std::function<void()> action) {
- long long id = p_->current_timer_id_++;
- p_->timers_.emplace(id, [NSTimer scheduledTimerWithTimeInterval:milliseconds.count() / 1000.0
- repeats:true
- block:^(NSTimer* timer) {
- action();
- }]);
-
- return id;
-}
-
-void OsxUiApplication::CancelTimer(long long id) {
- p_->next_tick_.erase(id);
- auto i = p_->timers_.find(id);
- if (i != p_->timers_.cend()) {
- [i->second invalidate];
- p_->timers_.erase(i);
- }
-}
-
-std::vector<INativeWindow*> OsxUiApplication::GetAllWindow() {
- std::vector<INativeWindow*> result;
- std::transform(p_->windows_.cbegin(), p_->windows_.cend(), std::back_inserter(result),
- [](OsxWindow* w) { return static_cast<INativeWindow*>(w); });
- return result;
-}
-
-INativeWindow* OsxUiApplication::CreateWindow() {
- auto window = new OsxWindow(this);
- p_->windows_.push_back(window);
- return window;
-}
-
-ICursorManager* OsxUiApplication::GetCursorManager() { return p_->cursor_manager_.get(); }
-
-IClipboard* OsxUiApplication::GetClipboard() { return p_->clipboard_.get(); }
-
-IMenu* OsxUiApplication::GetApplicationMenu() { return OsxMenu::CreateOrGetApplicationMenu(this); }
-
-graphics::IGraphicsFactory* OsxUiApplication::GetGraphicsFactory() {
- return p_->quartz_graphics_factory_.get();
-}
-
-std::optional<String> OsxUiApplication::ShowSaveDialog(SaveDialogOptions options) {
- NSSavePanel* panel = [NSSavePanel savePanel];
- [panel setTitle:(NSString*)Convert(options.title)];
- [panel setPrompt:(NSString*)Convert(options.prompt)];
- [panel setMessage:(NSString*)Convert(options.message)];
-
- NSMutableArray* allowed_content_types = [NSMutableArray array];
-
- for (const auto& file_type : options.allowed_file_types) {
- [allowed_content_types
- addObject:[UTType typeWithFilenameExtension:(NSString*)Convert(file_type)]];
- }
-
- [panel setAllowedContentTypes:allowed_content_types];
- [panel setAllowsOtherFileTypes:options.allow_all_file_types];
-
- auto model_result = [panel runModal];
- if (model_result == NSModalResponseOK) {
- return Convert((CFStringRef)[[panel URL] path]);
- } else {
- return std::nullopt;
- }
-}
-
-std::optional<std::vector<String>> OsxUiApplication::ShowOpenDialog(OpenDialogOptions options) {
- NSOpenPanel* panel = [NSOpenPanel openPanel];
- [panel setTitle:(NSString*)Convert(options.title)];
- [panel setPrompt:(NSString*)Convert(options.prompt)];
- [panel setMessage:(NSString*)Convert(options.message)];
-
- NSMutableArray* allowed_content_types = [NSMutableArray array];
-
- for (const auto& file_type : options.allowed_file_types) {
- [allowed_content_types
- addObject:[UTType typeWithFilenameExtension:(NSString*)Convert(file_type)]];
- }
-
- [panel setAllowedContentTypes:allowed_content_types];
- [panel setAllowsOtherFileTypes:options.allow_all_file_types];
-
- [panel setCanChooseFiles:options.can_choose_files];
- [panel setCanChooseDirectories:options.can_choose_directories];
- [panel setAllowsMultipleSelection:options.allow_mulitple_selection];
-
- auto model_result = [panel runModal];
- if (model_result == NSModalResponseOK) {
- std::vector<String> result;
- for (NSURL* url in [panel URLs]) {
- result.push_back(Convert((CFStringRef)[url path]));
- }
- return result;
- } else {
- return std::nullopt;
- }
-}
-
-void OsxUiApplication::UnregisterWindow(OsxWindow* window) {
- p_->windows_.erase(
- std::remove(p_->windows_.begin(), p_->windows_.end(), static_cast<INativeWindow*>(window)),
- p_->windows_.cend());
-}
-}
-
-@implementation CruAppDelegate {
- cru::platform::gui::osx::details::OsxUiApplicationPrivate* _p;
-}
-
-- (id)init:(cru::platform::gui::osx::details::OsxUiApplicationPrivate*)p {
- _p = p;
- return self;
-}
-- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender {
- return NSApplicationTerminateReply::NSTerminateNow;
-}
-- (void)applicationWillTerminate:(NSNotification*)notification {
- _p->CallQuitHandlers();
-}
-@end
diff --git a/src/osx/gui/Window.mm b/src/osx/gui/Window.mm
deleted file mode 100644
index 8d15ef37..00000000
--- a/src/osx/gui/Window.mm
+++ /dev/null
@@ -1,800 +0,0 @@
-#include "cru/osx/gui/Window.h"
-#include "WindowPrivate.h"
-
-#include "CursorPrivate.h"
-#include "InputMethodPrivate.h"
-#include "cru/common/Range.h"
-#include "cru/common/log/Logger.h"
-#include "cru/osx/Convert.h"
-#include "cru/osx/graphics/quartz/Convert.h"
-#include "cru/osx/graphics/quartz/Painter.h"
-#include "cru/osx/gui/Cursor.h"
-#include "cru/osx/gui/InputMethod.h"
-#include "cru/osx/gui/Keyboard.h"
-#include "cru/osx/gui/Resource.h"
-#include "cru/osx/gui/UiApplication.h"
-#include "cru/platform/Check.h"
-#include "cru/platform/graphics/NullPainter.h"
-#include "cru/platform/gui/TimerHelper.h"
-
-#include <AppKit/AppKit.h>
-#include <Foundation/Foundation.h>
-
-#include <limits>
-#include <memory>
-#include <unordered_set>
-
-namespace {
-constexpr int key_down_debug = 0;
-}
-
-using cru::platform::osx::Convert;
-using cru::platform::graphics::osx::quartz::Convert;
-
-namespace cru::platform::gui::osx {
-namespace {
-inline NSWindowStyleMask CalcWindowStyleMask(WindowStyleFlag flag) {
- return flag & WindowStyleFlags::NoCaptionAndBorder
- ? NSWindowStyleMaskBorderless
- : NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
- NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable;
-}
-}
-
-namespace details {
-OsxWindowPrivate::OsxWindowPrivate(OsxWindow* osx_window) : osx_window_(osx_window) {
- window_delegate_ = [[CruWindowDelegate alloc] init:this];
-
- content_rect_ = {100, 100, 400, 200};
-
- input_method_context_ = std::make_unique<OsxInputMethodContext>(osx_window);
-}
-
-OsxWindowPrivate::~OsxWindowPrivate() {}
-
-void OsxWindowPrivate::OnWindowWillClose() {
- if (window_) destroy_event_.Raise(nullptr);
- window_ = nil;
- CGLayerRelease(draw_layer_);
- draw_layer_ = nullptr;
-
- if (osx_window_->GetUiApplication()->IsQuitOnAllWindowClosed()) {
- const auto& all_window = osx_window_->GetUiApplication()->GetAllWindow();
-
- bool quit = true;
-
- for (auto window : all_window) {
- auto w = CheckPlatform<OsxWindow>(window, osx_window_->GetPlatformId());
- if (w->p_->window_) {
- quit = false;
- break;
- }
- }
-
- if (quit) {
- osx_window_->GetUiApplication()->RequestQuit(0);
- }
- }
-}
-
-void OsxWindowPrivate::OnWindowDidExpose() { osx_window_->RequestRepaint(); }
-void OsxWindowPrivate::OnWindowDidUpdate() {}
-void OsxWindowPrivate::OnWindowDidMove() { content_rect_ = RetrieveContentRect(); }
-
-void OsxWindowPrivate::OnWindowDidResize() {
- content_rect_ = RetrieveContentRect();
-
- auto view = [window_ contentView];
- [view removeTrackingArea:[view trackingAreas][0]];
- auto tracking_area = [[NSTrackingArea alloc]
- initWithRect:CGRectMake(0, 0, content_rect_.width, content_rect_.height)
- options:(NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveAlways)
- owner:view
- userInfo:nil];
- [view addTrackingArea:tracking_area];
-
- CGLayerRelease(draw_layer_);
- draw_layer_ = CreateLayer(Convert(content_rect_.GetSize()));
-
- resize_event_.Raise(osx_window_->GetClientSize());
-
- osx_window_->RequestRepaint();
-}
-
-void OsxWindowPrivate::OnBecomeKeyWindow() { focus_event_.Raise(FocusChangeType::Gain); }
-
-void OsxWindowPrivate::OnResignKeyWindow() { focus_event_.Raise(FocusChangeType::Lose); }
-
-void OsxWindowPrivate::OnMouseEnterLeave(MouseEnterLeaveType type) {
- mouse_enter_leave_event_.Raise(type);
- if (type == MouseEnterLeaveType::Enter) {
- mouse_in_ = true;
- UpdateCursor();
- } else {
- mouse_in_ = false;
- }
-}
-
-void OsxWindowPrivate::OnMouseMove(Point p) { mouse_move_event_.Raise(TransformMousePoint(p)); }
-
-void OsxWindowPrivate::OnMouseDown(MouseButton button, Point p, KeyModifier key_modifier) {
- mouse_down_event_.Raise({button, TransformMousePoint(p), key_modifier});
-}
-
-void OsxWindowPrivate::OnMouseUp(MouseButton button, Point p, KeyModifier key_modifier) {
- mouse_up_event_.Raise({button, TransformMousePoint(p), key_modifier});
-}
-
-void OsxWindowPrivate::OnMouseWheel(float delta, Point p, KeyModifier key_modifier,
- bool horizontal) {
- mouse_wheel_event_.Raise({delta, TransformMousePoint(p), key_modifier, horizontal});
-}
-
-void OsxWindowPrivate::OnKeyDown(KeyCode key, KeyModifier key_modifier) {
- key_down_event_.Raise({key, key_modifier});
-}
-
-void OsxWindowPrivate::OnKeyUp(KeyCode key, KeyModifier key_modifier) {
- key_up_event_.Raise({key, key_modifier});
-}
-
-CGLayerRef OsxWindowPrivate::CreateLayer(const CGSize& size) {
- auto s = size;
- if (s.width == 0) s.width = 1;
- if (s.height == 0) s.height = 1;
-
- auto draw_layer = CGLayerCreateWithContext(nullptr, s, nullptr);
- Ensures(draw_layer);
-
- return draw_layer;
-}
-
-void OsxWindowPrivate::UpdateCursor() {
- auto cursor = cursor_ == nullptr
- ? std::dynamic_pointer_cast<OsxCursor>(
- osx_window_->GetUiApplication()->GetCursorManager()->GetSystemCursor(
- SystemCursorType::Arrow))
- : cursor_;
-
- [cursor->p_->ns_cursor_ set];
-}
-
-Point OsxWindowPrivate::TransformMousePoint(const Point& point) {
- Point r = point;
- r.y = content_rect_.height - r.y;
- return r;
-}
-
-void OsxWindowPrivate::CreateWindow() {
- Expects(!window_);
-
- NSWindowStyleMask style_mask = CalcWindowStyleMask(style_flag_);
- window_ = [[CruWindow alloc] init:this
- contentRect:{0, 0, content_rect_.width, content_rect_.height}
- style:style_mask];
- Ensures(window_);
-
- osx_window_->SetClientRect(content_rect_);
-
- [window_ setDelegate:window_delegate_];
-
- if (parent_) {
- auto parent = CheckPlatform<OsxWindow>(parent_, this->osx_window_->GetPlatformId());
- [window_ setParentWindow:parent->p_->window_];
- }
-
- NSView* content_view = [[CruView alloc] init:this
- input_context_p:input_method_context_->p_.get()
- frame:Rect(Point{}, content_rect_.GetSize())];
-
- [window_ setContentView:content_view];
-
- auto title_str = Convert(title_);
- [window_ setTitle:(NSString*)title_str];
- CFRelease(title_str);
-
- draw_layer_ = CreateLayer(Convert(content_rect_.GetSize()));
-
- create_event_.Raise(nullptr);
-
- osx_window_->RequestRepaint();
-}
-
-Size OsxWindowPrivate::GetScreenSize() {
- auto screen = window_ ? [window_ screen] : [NSScreen mainScreen];
- auto size = [screen frame].size;
- return Convert(size);
-}
-
-Rect OsxWindowPrivate::RetrieveContentRect() {
- NSRect rect = [NSWindow contentRectForFrameRect:[window_ frame]
- styleMask:CalcWindowStyleMask(style_flag_)];
- rect.origin.y = GetScreenSize().height - rect.origin.y - rect.size.height;
- return cru::platform::graphics::osx::quartz::Convert(rect);
-}
-
-}
-
-OsxWindow::OsxWindow(OsxUiApplication* ui_application)
- : OsxGuiResource(ui_application), p_(new details::OsxWindowPrivate(this)) {}
-
-OsxWindow::~OsxWindow() {
- if (p_->window_) {
- [p_->window_ close];
- }
- dynamic_cast<OsxUiApplication*>(GetUiApplication())->UnregisterWindow(this);
-}
-
-void OsxWindow::Close() {
- if (p_->window_) {
- [p_->window_ close];
- }
-}
-
-INativeWindow* OsxWindow::GetParent() { return p_->parent_; }
-
-void OsxWindow::SetParent(INativeWindow* parent) {
- auto p = CheckPlatform<OsxWindow>(parent, GetPlatformId());
-
- p_->parent_ = parent;
-
- if (p_->window_) {
- [p_->window_ setParentWindow:p->p_->window_];
- }
-}
-
-WindowStyleFlag OsxWindow::GetStyleFlag() { return p_->style_flag_; }
-
-void OsxWindow::SetStyleFlag(WindowStyleFlag flag) {
- p_->style_flag_ = flag;
-
- if (p_->window_) {
- [p_->window_ close];
- }
-}
-
-String OsxWindow::GetTitle() { return p_->title_; }
-
-void OsxWindow::SetTitle(String title) {
- p_->title_ = title;
-
- if (p_->window_) {
- auto str = Convert(title);
- [p_->window_ setTitle:(NSString*)str];
- CFRelease(str);
- }
-}
-
-WindowVisibilityType OsxWindow::GetVisibility() {
- if (!p_->window_) return WindowVisibilityType::Hide;
- if ([p_->window_ isMiniaturized]) return WindowVisibilityType::Minimize;
- return [p_->window_ isVisible] ? WindowVisibilityType::Show : WindowVisibilityType::Hide;
-}
-
-void OsxWindow::SetVisibility(WindowVisibilityType visibility) {
- if (p_->window_) {
- if (visibility == WindowVisibilityType::Show) {
- [p_->window_ orderFront:nil];
- p_->visibility_change_event_.Raise(WindowVisibilityType::Show);
- } else if (visibility == WindowVisibilityType::Hide) {
- [p_->window_ orderOut:nil];
- p_->visibility_change_event_.Raise(WindowVisibilityType::Hide);
- } else if (visibility == WindowVisibilityType::Minimize) {
- [p_->window_ miniaturize:nil];
- }
- } else {
- if (visibility == WindowVisibilityType::Show) {
- p_->CreateWindow();
- [p_->window_ orderFront:nil];
- p_->visibility_change_event_.Raise(WindowVisibilityType::Show);
- }
- }
-}
-
-Size OsxWindow::GetClientSize() { return p_->content_rect_.GetSize(); }
-
-void OsxWindow::SetClientSize(const Size& size) {
- if (p_->window_) {
- auto rect = GetClientRect();
- rect.SetSize(size);
- SetClientRect(rect);
- } else {
- p_->content_rect_.SetSize(size);
- }
-}
-
-Rect OsxWindow::GetClientRect() { return p_->content_rect_; }
-
-void OsxWindow::SetClientRect(const Rect& rect) {
- if (p_->window_) {
- auto r = Convert(rect);
- r.origin.y = p_->GetScreenSize().height - r.origin.y - r.size.height;
- r = [NSWindow frameRectForContentRect:r styleMask:CalcWindowStyleMask(p_->style_flag_)];
- [p_->window_ setFrame:r display:false];
- } else {
- p_->content_rect_ = rect;
- }
-}
-
-Rect OsxWindow::GetWindowRect() {
- auto r = Convert(p_->content_rect_);
- r.origin.y = p_->GetScreenSize().height - r.origin.y - r.size.height;
- r = [NSWindow frameRectForContentRect:r styleMask:CalcWindowStyleMask(p_->style_flag_)];
- r.origin.y = p_->GetScreenSize().height - r.origin.y - r.size.height;
- return Convert(r);
-}
-
-void OsxWindow::SetWindowRect(const Rect& rect) {
- auto r = Convert(rect);
- r.origin.y = p_->GetScreenSize().height - r.origin.y - r.size.height;
- r = [NSWindow frameRectForContentRect:r styleMask:CalcWindowStyleMask(p_->style_flag_)];
- r.origin.y = p_->GetScreenSize().height - r.origin.y - r.size.height;
- SetClientRect(Convert(r));
-}
-
-void OsxWindow::RequestRepaint() {
- if (!p_->draw_timer_) {
- p_->draw_timer_ = GetUiApplication()->SetImmediate([this] {
- p_->paint_event_.Raise(nullptr);
- p_->draw_timer_.Release();
- });
- }
-}
-
-std::unique_ptr<graphics::IPainter> OsxWindow::BeginPaint() {
- if (!p_->window_) {
- return std::make_unique<graphics::NullPainter>();
- }
-
- CGContextRef cg_context = CGLayerGetContext(p_->draw_layer_);
-
- return std::make_unique<cru::platform::graphics::osx::quartz::QuartzCGContextPainter>(
- GetUiApplication()->GetGraphicsFactory(), cg_context, false, GetClientSize(),
- [this](graphics::osx::quartz::QuartzCGContextPainter*) {
- [[p_->window_ contentView] setNeedsDisplay:YES];
- });
-}
-
-bool OsxWindow::RequestFocus() {
- if (!p_->window_) return false;
- [p_->window_ makeKeyWindow];
- return true;
-}
-
-Point OsxWindow::GetMousePosition() {
- auto p = [p_->window_ mouseLocationOutsideOfEventStream];
- return Point(p.x, p.y);
-}
-
-bool OsxWindow::CaptureMouse() { return true; }
-
-bool OsxWindow::ReleaseMouse() { return true; }
-
-void OsxWindow::SetCursor(std::shared_ptr<ICursor> cursor) {
- p_->cursor_ = CheckPlatform<OsxCursor>(cursor, GetPlatformId());
- p_->UpdateCursor();
-}
-
-void OsxWindow::SetToForeground() {
- if (!p_->window_) return;
- [p_->window_ makeMainWindow];
- [p_->window_ orderFrontRegardless];
-}
-
-IEvent<std::nullptr_t>* OsxWindow::CreateEvent() { return &p_->create_event_; }
-IEvent<std::nullptr_t>* OsxWindow::DestroyEvent() { return &p_->destroy_event_; }
-IEvent<std::nullptr_t>* OsxWindow::PaintEvent() { return &p_->paint_event_; }
-IEvent<WindowVisibilityType>* OsxWindow::VisibilityChangeEvent() {
- return &p_->visibility_change_event_;
-}
-IEvent<Size>* OsxWindow::ResizeEvent() { return &p_->resize_event_; }
-IEvent<FocusChangeType>* OsxWindow::FocusEvent() { return &p_->focus_event_; }
-IEvent<MouseEnterLeaveType>* OsxWindow::MouseEnterLeaveEvent() {
- return &p_->mouse_enter_leave_event_;
-}
-IEvent<Point>* OsxWindow::MouseMoveEvent() { return &p_->mouse_move_event_; }
-IEvent<NativeMouseButtonEventArgs>* OsxWindow::MouseDownEvent() { return &p_->mouse_down_event_; }
-IEvent<NativeMouseButtonEventArgs>* OsxWindow::MouseUpEvent() { return &p_->mouse_up_event_; }
-IEvent<NativeMouseWheelEventArgs>* OsxWindow::MouseWheelEvent() { return &p_->mouse_wheel_event_; }
-IEvent<NativeKeyEventArgs>* OsxWindow::KeyDownEvent() { return &p_->key_down_event_; }
-IEvent<NativeKeyEventArgs>* OsxWindow::KeyUpEvent() { return &p_->key_up_event_; }
-
-IInputMethodContext* OsxWindow::GetInputMethodContext() { return p_->input_method_context_.get(); }
-}
-
-namespace {
-cru::platform::gui::KeyModifier GetKeyModifier(NSEvent* event) {
- cru::platform::gui::KeyModifier key_modifier;
- if (event.modifierFlags & NSEventModifierFlagControl)
- key_modifier |= cru::platform::gui::KeyModifiers::ctrl;
- if (event.modifierFlags & NSEventModifierFlagOption)
- key_modifier |= cru::platform::gui::KeyModifiers::alt;
- if (event.modifierFlags & NSEventModifierFlagShift)
- key_modifier |= cru::platform::gui::KeyModifiers::shift;
- if (event.modifierFlags & NSEventModifierFlagCommand)
- key_modifier |= cru::platform::gui::KeyModifiers::command;
- return key_modifier;
-}
-}
-
-@implementation CruWindow {
- cru::platform::gui::osx::details::OsxWindowPrivate* _p;
-}
-
-- (instancetype)init:(cru::platform::gui::osx::details::OsxWindowPrivate*)p
- contentRect:(NSRect)contentRect
- style:(NSWindowStyleMask)style {
- [super initWithContentRect:contentRect
- styleMask:style
- backing:NSBackingStoreBuffered
- defer:false];
- _p = p;
-
- [self setAcceptsMouseMovedEvents:YES];
-
- return self;
-}
-
-- (BOOL)canBecomeMainWindow {
- return YES;
-}
-
-- (BOOL)canBecomeKeyWindow {
- return YES;
-}
-@end
-
-@implementation CruView {
- cru::platform::gui::osx::details::OsxWindowPrivate* _p;
- cru::platform::gui::osx::details::OsxInputMethodContextPrivate* _input_context_p;
- NSMutableAttributedString* _input_context_text;
-}
-
-- (instancetype)init:(cru::platform::gui::osx::details::OsxWindowPrivate*)p
- input_context_p:
- (cru::platform::gui::osx::details::OsxInputMethodContextPrivate*)input_context_p
- frame:(cru::platform::Rect)frame {
- [super initWithFrame:cru::platform::graphics::osx::quartz::Convert(frame)];
- _p = p;
- _input_context_p = input_context_p;
-
- auto tracking_area = [[NSTrackingArea alloc]
- initWithRect:Convert(frame)
- options:(NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveAlways)
- owner:self
- userInfo:nil];
- [self addTrackingArea:tracking_area];
-
- return self;
-}
-
-- (void)drawRect:(NSRect)dirtyRect {
- auto cg_context = [[NSGraphicsContext currentContext] CGContext];
- auto layer = _p->GetDrawLayer();
- Ensures(layer);
- CGContextDrawLayerAtPoint(cg_context, CGPointMake(0, 0), layer);
-}
-
-- (BOOL)acceptsFirstResponder {
- return YES;
-}
-
-- (BOOL)canBecomeKeyView {
- return YES;
-}
-
-- (void)mouseMoved:(NSEvent*)event {
- _p->OnMouseMove(cru::platform::Point(event.locationInWindow.x, event.locationInWindow.y));
-}
-
-- (void)mouseDragged:(NSEvent*)event {
- _p->OnMouseMove(cru::platform::Point(event.locationInWindow.x, event.locationInWindow.y));
-}
-
-- (void)rightMouseDragged:(NSEvent*)event {
- _p->OnMouseMove(cru::platform::Point(event.locationInWindow.x, event.locationInWindow.y));
-}
-
-- (void)mouseEntered:(NSEvent*)event {
- _p->OnMouseEnterLeave(cru::platform::gui::MouseEnterLeaveType::Enter);
-}
-
-- (void)mouseExited:(NSEvent*)event {
- _p->OnMouseEnterLeave(cru::platform::gui::MouseEnterLeaveType::Leave);
-}
-
-- (void)mouseDown:(NSEvent*)event {
- [[self window] makeKeyWindow];
-
- auto key_modifier = GetKeyModifier(event);
- cru::platform::Point p(event.locationInWindow.x, event.locationInWindow.y);
-
- _p->OnMouseDown(cru::platform::gui::mouse_buttons::left, p, key_modifier);
-}
-
-- (void)mouseUp:(NSEvent*)event {
- auto key_modifier = GetKeyModifier(event);
- cru::platform::Point p(event.locationInWindow.x, event.locationInWindow.y);
-
- _p->OnMouseUp(cru::platform::gui::mouse_buttons::left, p, key_modifier);
-}
-
-- (void)rightMouseDown:(NSEvent*)event {
- auto key_modifier = GetKeyModifier(event);
- cru::platform::Point p(event.locationInWindow.x, event.locationInWindow.y);
-
- _p->OnMouseDown(cru::platform::gui::mouse_buttons::right, p, key_modifier);
-}
-
-- (void)rightMouseUp:(NSEvent*)event {
- auto key_modifier = GetKeyModifier(event);
- cru::platform::Point p(event.locationInWindow.x, event.locationInWindow.y);
-
- _p->OnMouseUp(cru::platform::gui::mouse_buttons::right, p, key_modifier);
-}
-
-- (void)scrollWheel:(NSEvent*)event {
- auto key_modifier = GetKeyModifier(event);
- cru::platform::Point p(event.locationInWindow.x, event.locationInWindow.y);
-
- if (event.scrollingDeltaY) {
- _p->OnMouseWheel(static_cast<float>(event.scrollingDeltaY), p, key_modifier, false);
- }
-
- if (event.scrollingDeltaX) {
- _p->OnMouseWheel(static_cast<float>(event.scrollingDeltaX), p, key_modifier, true);
- }
-}
-
-namespace {
-using cru::platform::gui::KeyCode;
-const std::unordered_set<KeyCode> input_context_handle_codes{
- KeyCode::A,
- KeyCode::B,
- KeyCode::C,
- KeyCode::D,
- KeyCode::E,
- KeyCode::F,
- KeyCode::G,
- KeyCode::H,
- KeyCode::I,
- KeyCode::J,
- KeyCode::K,
- KeyCode::L,
- KeyCode::M,
- KeyCode::N,
- KeyCode::O,
- KeyCode::P,
- KeyCode::Q,
- KeyCode::R,
- KeyCode::S,
- KeyCode::T,
- KeyCode::U,
- KeyCode::V,
- KeyCode::W,
- KeyCode::X,
- KeyCode::Y,
- KeyCode::Z,
- KeyCode::N0,
- KeyCode::N1,
- KeyCode::N2,
- KeyCode::N3,
- KeyCode::N4,
- KeyCode::N5,
- KeyCode::N6,
- KeyCode::N7,
- KeyCode::N8,
- KeyCode::N9,
- KeyCode::Comma,
- KeyCode::Period,
- KeyCode::Slash,
- KeyCode::Semicolon,
- KeyCode::Quote,
- KeyCode::LeftSquareBracket,
- KeyCode::RightSquareBracket,
- KeyCode::BackSlash,
- KeyCode::Minus,
- KeyCode::Equal,
- KeyCode::GraveAccent,
-};
-}
-
-const std::unordered_set<KeyCode> input_context_handle_codes_when_has_text{
- KeyCode::Backspace, KeyCode::Space, KeyCode::Return, KeyCode::Left,
- KeyCode::Right, KeyCode::Up, KeyCode::Down};
-
-- (void)keyDown:(NSEvent*)event {
- auto key_modifier = GetKeyModifier(event);
-
- bool handled = false;
-
- auto input_context = dynamic_cast<cru::platform::gui::osx::OsxInputMethodContext*>(
- _p->GetWindow()->GetInputMethodContext());
- Ensures(input_context);
-
- auto c = cru::platform::gui::osx::KeyCodeFromOsxToCru(event.keyCode);
-
- if (input_context->IsEnabled()) {
- if (input_context_handle_codes.count(c) &&
- !(key_modifier & ~cru::platform::gui::KeyModifiers::shift)) {
- handled = [[self inputContext] handleEvent:event];
- } else if (input_context_handle_codes_when_has_text.count(c) && !key_modifier) {
- if (!input_context->GetCompositionText().text.empty()) {
- handled = [[self inputContext] handleEvent:event];
- } else {
- if (c == KeyCode::Return) {
- _input_context_p->RaiseTextEvent(u"\n");
- handled = true;
- } else if (c == KeyCode::Space) {
- _input_context_p->RaiseTextEvent(u" ");
- handled = true;
- }
- }
- }
- }
-
- if (!handled) {
- _p->OnKeyDown(c, key_modifier);
- }
-}
-
-- (void)keyUp:(NSEvent*)event {
- // cru::CRU_LOG_DEBUG(u"CruView", u"Recieved key up.");
-
- auto key_modifier = GetKeyModifier(event);
- auto c = cru::platform::gui::osx::KeyCodeFromOsxToCru(event.keyCode);
-
- _p->OnKeyUp(c, key_modifier);
-}
-
-- (BOOL)hasMarkedText {
- return _input_context_text != nil;
-}
-
-- (NSRange)markedRange {
- return _input_context_text == nil ? NSRange{NSNotFound, 0}
- : NSRange{0, [_input_context_text length]};
-}
-
-- (NSRange)selectedRange {
- return NSMakeRange(_input_context_p->GetSelectionRange().position,
- _input_context_p->GetSelectionRange().count);
-}
-
-- (void)setMarkedText:(id)string
- selectedRange:(NSRange)selectedRange
- replacementRange:(NSRange)replacementRange {
- CFStringRef s;
- if ([string isKindOfClass:[NSString class]]) {
- s = (CFStringRef)string;
- } else {
- auto as = (CFAttributedStringRef)string;
- s = CFAttributedStringGetString(as);
- }
-
- auto ss = Convert(s);
-
- // cru::CRU_LOG_DEBUG(u"CruView",
- // u"Received setMarkedText string: {}, selected range: ({}, {}), "
- // u"replacement range: ({}, {}).",
- // ss, selectedRange.location, selectedRange.length, replacementRange.location,
- // replacementRange.length);
-
- if (_input_context_text == nil) {
- _input_context_text = [[NSMutableAttributedString alloc] init];
- _input_context_p->RaiseCompositionStartEvent();
- }
-
- if (replacementRange.location == NSNotFound) replacementRange.location = 0;
-
- [_input_context_text
- replaceCharactersInRange:NSMakeRange(0, [_input_context_text length])
- withAttributedString:[[NSAttributedString alloc] initWithString:(NSString*)s]];
-
- cru::platform::gui::CompositionText composition_text;
- composition_text.text = Convert((CFStringRef)[_input_context_text string]);
- composition_text.selection.position = ss.IndexFromCodePointToCodeUnit(selectedRange.location);
- composition_text.selection.count =
- ss.IndexFromCodePointToCodeUnit(selectedRange.location + selectedRange.length) -
- composition_text.selection.position;
- _input_context_p->SetCompositionText(composition_text);
- _input_context_p->RaiseCompositionEvent();
-}
-
-- (void)unmarkText {
- _input_context_text = nil;
- _input_context_p->RaiseCompositionEndEvent();
-}
-
-- (NSArray<NSAttributedStringKey>*)validAttributesForMarkedText {
- return @[
- (NSString*)kCTUnderlineColorAttributeName, (NSString*)kCTUnderlineStyleAttributeName,
- (NSString*)kCTForegroundColorAttributeName, (NSString*)kCTBackgroundColorAttributeName
- ];
-}
-
-- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range
- actualRange:(NSRangePointer)actualRange {
- cru::Range r(range.location, range.length);
-
- r = r.CoerceInto(0, [_input_context_text length]);
-
- return [_input_context_text attributedSubstringFromRange:NSMakeRange(r.position, r.count)];
-}
-
-- (void)insertText:(id)string replacementRange:(NSRange)replacementRange {
- CFStringRef s;
- if ([string isKindOfClass:[NSString class]]) {
- s = (CFStringRef)string;
- } else {
- auto as = (CFAttributedStringRef)string;
- s = CFAttributedStringGetString(as);
- }
-
- _input_context_text = nil;
- _input_context_p->SetCompositionText(cru::platform::gui::CompositionText());
- cru::String ss = Convert(s);
-
- // cru::CRU_LOG_DEBUG(u"CruView", u"Finish composition: {}, replacement range: ({}, {})", ss,
- // replacementRange.location, replacementRange.length);
-
- _input_context_p->RaiseCompositionEvent();
- _input_context_p->RaiseCompositionEndEvent();
- _input_context_p->RaiseTextEvent(ss);
-}
-
-- (NSUInteger)characterIndexForPoint:(NSPoint)point {
- return NSNotFound;
-}
-
-- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange {
- NSRect result;
- result.origin.x = _input_context_p->GetCandidateWindowPosition().x;
- result.origin.y = _input_context_p->GetCandidateWindowPosition().y;
- result.size.height = 16;
- result.size.width = 0;
- return result;
-}
-
-- (void)doCommandBySelector:(SEL)selector {
- _input_context_p->PerformSel(selector);
-}
-@end
-
-@implementation CruWindowDelegate {
- cru::platform::gui::osx::details::OsxWindowPrivate* _p;
-}
-
-- (id)init:(cru::platform::gui::osx::details::OsxWindowPrivate*)p {
- _p = p;
- return self;
-}
-
-- (void)windowWillClose:(NSNotification*)notification {
- _p->OnWindowWillClose();
-}
-
-- (void)windowDidExpose:(NSNotification*)notification {
- _p->OnWindowDidExpose();
-}
-
-- (void)windowDidUpdate:(NSNotification*)notification {
- _p->OnWindowDidUpdate();
-}
-
-- (void)windowDidMove:(NSNotification*)notification {
- _p->OnWindowDidMove();
-}
-
-- (void)windowDidResize:(NSNotification*)notification {
- _p->OnWindowDidResize();
-}
-
-- (void)windowDidBecomeKey:(NSNotification*)notification {
- _p->OnBecomeKeyWindow();
-}
-
-- (void)windowDidResignKey:(NSNotification*)notification {
- _p->OnResignKeyWindow();
-}
-@end
diff --git a/src/osx/gui/WindowPrivate.h b/src/osx/gui/WindowPrivate.h
deleted file mode 100644
index cdd34246..00000000
--- a/src/osx/gui/WindowPrivate.h
+++ /dev/null
@@ -1,118 +0,0 @@
-#pragma once
-#include "cru/osx/gui/Window.h"
-
-#include "cru/common/Event.h"
-#include "cru/osx/gui/Cursor.h"
-#include "cru/platform/gui/TimerHelper.h"
-#include "cru/platform/gui/Window.h"
-
-#import <AppKit/AppKit.h>
-
-@interface CruWindowDelegate : NSObject <NSWindowDelegate>
-- (id)init:(cru::platform::gui::osx::details::OsxWindowPrivate*)p;
-@end
-
-@interface CruWindow : NSWindow
-- (instancetype)init:(cru::platform::gui::osx::details::OsxWindowPrivate*)p
- contentRect:(NSRect)contentRect
- style:(NSWindowStyleMask)style;
-@end
-
-@interface CruView : NSView <NSTextInputClient>
-- (instancetype)init:(cru::platform::gui::osx::details::OsxWindowPrivate*)p
- input_context_p:
- (cru::platform::gui::osx::details::OsxInputMethodContextPrivate*)input_context_p
- frame:(cru::platform::Rect)frame;
-@end
-
-namespace cru::platform::gui::osx {
-
-namespace details {
-class OsxInputMethodContextPrivate;
-
-class OsxWindowPrivate {
- friend OsxWindow;
- friend OsxInputMethodContextPrivate;
-
- public:
- explicit OsxWindowPrivate(OsxWindow* osx_window);
-
- CRU_DELETE_COPY(OsxWindowPrivate)
- CRU_DELETE_MOVE(OsxWindowPrivate)
-
- ~OsxWindowPrivate();
-
- public:
- void OnMouseEnterLeave(MouseEnterLeaveType type);
- void OnMouseMove(Point p);
- void OnMouseDown(MouseButton button, Point p, KeyModifier key_modifier);
- void OnMouseUp(MouseButton button, Point p, KeyModifier key_modifier);
- void OnMouseWheel(float delta, Point p, KeyModifier key_modifier, bool horizontal);
- void OnKeyDown(KeyCode key, KeyModifier key_modifier);
- void OnKeyUp(KeyCode key, KeyModifier key_modifier);
-
- void OnWindowWillClose();
- void OnWindowDidExpose();
- void OnWindowDidUpdate();
- void OnWindowDidMove();
- void OnWindowDidResize();
- void OnBecomeKeyWindow();
- void OnResignKeyWindow();
-
- CGLayerRef GetDrawLayer() { return draw_layer_; }
-
- OsxWindow* GetWindow() { return osx_window_; }
- NSWindow* GetNSWindow() { return window_; }
-
- private:
- Size GetScreenSize();
-
- void CreateWindow();
-
- void UpdateCursor();
-
- Point TransformMousePoint(const Point& point);
-
- CGLayerRef CreateLayer(const CGSize& size);
-
- Rect RetrieveContentRect();
-
- private:
- OsxWindow* osx_window_;
-
- INativeWindow* parent_ = nullptr;
- WindowStyleFlag style_flag_ = WindowStyleFlag{};
-
- String title_;
-
- Rect content_rect_;
-
- NSWindow* window_ = nil;
- CruWindowDelegate* window_delegate_ = nil;
-
- CGLayerRef draw_layer_ = nullptr;
-
- bool mouse_in_ = false;
-
- std::shared_ptr<OsxCursor> cursor_ = nullptr;
-
- std::unique_ptr<OsxInputMethodContext> input_method_context_;
-
- TimerAutoCanceler draw_timer_;
-
- Event<std::nullptr_t> create_event_;
- Event<std::nullptr_t> destroy_event_;
- Event<std::nullptr_t> paint_event_;
- Event<WindowVisibilityType> visibility_change_event_;
- Event<Size> resize_event_;
- Event<FocusChangeType> focus_event_;
- Event<MouseEnterLeaveType> mouse_enter_leave_event_;
- Event<Point> mouse_move_event_;
- Event<NativeMouseButtonEventArgs> mouse_down_event_;
- Event<NativeMouseButtonEventArgs> mouse_up_event_;
- Event<NativeMouseWheelEventArgs> mouse_wheel_event_;
- Event<NativeKeyEventArgs> key_down_event_;
- Event<NativeKeyEventArgs> key_up_event_;
-};
-} // namespace details
-} // namespace cru::platform::gui::osx