diff --git a/examples/gg/raven_text_rendering.v b/examples/gg/raven_text_rendering.v index d6378cdb77..a548b7db2f 100644 --- a/examples/gg/raven_text_rendering.v +++ b/examples/gg/raven_text_rendering.v @@ -81,6 +81,7 @@ fn main() { bg_color: bg_color frame_fn: frame font_path: font_path // window_user_ptr: ctx + // native_rendering: true ) app.gg.run() } diff --git a/thirdparty/sokol/sokol_app.h b/thirdparty/sokol/sokol_app.h index dc26fc9f57..ef4ac700b1 100644 --- a/thirdparty/sokol/sokol_app.h +++ b/thirdparty/sokol/sokol_app.h @@ -1569,6 +1569,22 @@ inline void sapp_run(const sapp_desc& desc) { return sapp_run(&desc); } /*== MACOS DECLARATIONS ======================================================*/ #if defined(_SAPP_MACOS) +// __v_ +@interface SokolWindow : NSWindow { +} +@end +@interface MyView2 : NSView +@end + +MyView2* g_view; + +// A custom NSWindow interface to handle events in borderless windows. +@implementation SokolWindow +- (BOOL)canBecomeKeyWindow { return YES; } // needed for NSWindowStyleMaskBorderless +- (BOOL)canBecomeMainWindow { return YES; } +@end +// __v_ + @interface _sapp_macos_app_delegate : NSObject @end @interface _sapp_macos_window : NSWindow @@ -1587,7 +1603,9 @@ inline void sapp_run(const sapp_desc& desc) { return sapp_run(&desc); } typedef struct { uint32_t flags_changed_store; uint8_t mouse_buttons; - NSWindow* window; +// NSWindow* window; +// SokolWindow* window; // __v_ + _sapp_macos_window* window; // __v_ NSTrackingArea* tracking_area; _sapp_macos_app_delegate* app_dlg; _sapp_macos_window_delegate* win_dlg; @@ -2082,6 +2100,9 @@ typedef struct { char window_title[_SAPP_MAX_TITLE_LENGTH]; /* UTF-8 */ wchar_t window_title_wide[_SAPP_MAX_TITLE_LENGTH]; /* UTF-32 or UCS-2 */ sapp_keycode keycodes[SAPP_MAX_KEYCODES]; + + /* V patches */ + bool __v_native_render; /* V patch to allow for native rendering */ } _sapp_t; static _sapp_t _sapp; @@ -2110,6 +2131,9 @@ _SOKOL_PRIVATE void _sapp_call_init(void) { } _SOKOL_PRIVATE void _sapp_call_frame(void) { + if (_sapp.__v_native_render) { + return; + } if (_sapp.init_called && !_sapp.cleanup_called) { if (_sapp.desc.frame_cb) { _sapp.desc.frame_cb(); @@ -2120,6 +2144,21 @@ _SOKOL_PRIVATE void _sapp_call_frame(void) { } } +// __v_ +_SOKOL_PRIVATE void _sapp_call_frame_native(void) { +//puts("_sapp_call_frame_native()"); +//printf("init called=%d cleanup_called=%d\n", _sapp.init_called,_sapp.cleanup_called); + if (_sapp.init_called && !_sapp.cleanup_called) { + if (_sapp.desc.frame_cb) { + _sapp.desc.frame_cb(); + } + else if (_sapp.desc.frame_userdata_cb) { + _sapp.desc.frame_userdata_cb(_sapp.desc.user_data); + } + } +} + + _SOKOL_PRIVATE void _sapp_call_cleanup(void) { if (!_sapp.cleanup_called) { if (_sapp.desc.cleanup_cb) { @@ -2233,6 +2272,7 @@ _SOKOL_PRIVATE void _sapp_init_state(const sapp_desc* desc) { _sapp.dpi_scale = 1.0f; _sapp.fullscreen = _sapp.desc.fullscreen; _sapp.mouse.shown = true; + _sapp.__v_native_render = _sapp.desc.__v_native_render; } _SOKOL_PRIVATE void _sapp_discard_state(void) { @@ -2635,6 +2675,8 @@ _SOKOL_PRIVATE void _sapp_macos_frame(void) { } } +#include "sokol_app2.h" // __v_ + @implementation _sapp_macos_app_delegate - (void)applicationDidFinishLaunching:(NSNotification*)aNotification { _SOKOL_UNUSED(aNotification); @@ -2652,7 +2694,7 @@ _SOKOL_PRIVATE void _sapp_macos_frame(void) { _sapp.framebuffer_height = _sapp.window_height; } _sapp.dpi_scale = (float)_sapp.framebuffer_width / (float) _sapp.window_width; - const NSUInteger style = + const NSUInteger style = _sapp.desc.fullscreen ? NSWindowStyleMaskBorderless : // __v_ NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | @@ -2668,6 +2710,34 @@ _SOKOL_PRIVATE void _sapp_macos_frame(void) { _sapp.macos.window.acceptsMouseMovedEvents = YES; _sapp.macos.window.restorable = YES; + + + // _v__ + _sapp.macos.window.backgroundColor = [NSColor whiteColor]; + + // Quit menu + NSMenu* menu_bar = [[NSMenu alloc] init]; +NSMenuItem* app_menu_item = [[NSMenuItem alloc] init]; +[menu_bar addItem:app_menu_item]; +NSApp.mainMenu = menu_bar; +NSMenu* app_menu = [[NSMenu alloc] init]; +NSString* window_title_as_nsstring = [NSString stringWithUTF8String:_sapp.window_title]; +// `quit_title` memory will be owned by the NSMenuItem, so no need to release it ourselves +NSString* quit_title = [@"Quit " stringByAppendingString:window_title_as_nsstring]; +NSMenuItem* quit_menu_item = [[NSMenuItem alloc] + initWithTitle:quit_title + action:@selector(terminate:) + keyEquivalent:@"q"]; +[app_menu addItem:quit_menu_item]; +app_menu_item.submenu = app_menu; +_SAPP_OBJC_RELEASE( window_title_as_nsstring ); +_SAPP_OBJC_RELEASE( app_menu ); +_SAPP_OBJC_RELEASE( app_menu_item ); +_SAPP_OBJC_RELEASE( menu_bar ); + + + // _v__ + _sapp.macos.win_dlg = [[_sapp_macos_window_delegate alloc] init]; _sapp.macos.window.delegate = _sapp.macos.win_dlg; #if defined(SOKOL_METAL) @@ -2729,16 +2799,48 @@ _SOKOL_PRIVATE void _sapp_macos_frame(void) { timer_obj = nil; #endif _sapp.valid = true; + // __v_ + if (!_sapp.__v_native_render) { if (_sapp.fullscreen) { - /* on GL, this already toggles a rendered frame, so set the valid flag before */ + // on GL, this already toggles a rendered frame, so set the valid flag before [_sapp.macos.window toggleFullScreen:self]; } else { [_sapp.macos.window center]; } + } + // __v C + /////////////////////////////////////////////////////// + // Create a child view for native rendering + if (_sapp.__v_native_render) { + + CGRect wRect = _sapp.macos.window.frame; + NSView *contentView =_sapp.macos.window.contentView; + CGRect cRect = contentView.frame; + + CGRect rect = CGRectMake(wRect.origin.x, wRect.origin.y, cRect.size.width, cRect.size.height); + NSWindow *overlayWindow = [[NSWindow alloc]initWithContentRect:rect + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + //overlayWindow.backgroundColor = [NSColor whiteColor]; + + //overlayWindow.backgroundColor = [[NSColor whiteColor] colorWithAlphaComponent:0]; + [overlayWindow setOpaque:YES]; + [_sapp.macos.window setIgnoresMouseEvents:NO]; + g_view = [[MyView2 alloc] init]; + overlayWindow.contentView = g_view; + + [ contentView addSubview:g_view]; +//[ _sapp.macos.window addChildWindow:overlayWindow ordered:NSWindowAbove]; + [_sapp.macos.window center]; + +} + ////////////////////////////////// + [_sapp.macos.window makeKeyAndOrderFront:nil]; _sapp_macos_update_dimensions(); - [NSEvent setMouseCoalescingEnabled:NO]; +// [NSEvent setMouseCoalescingEnabled:NO]; } - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)sender { @@ -2807,6 +2909,12 @@ _SOKOL_PRIVATE void _sapp_macos_frame(void) { @end @implementation _sapp_macos_window + +// __v_ +- (BOOL)canBecomeKeyWindow { return YES; } // needed for NSWindowStyleMaskBorderless +- (BOOL)canBecomeMainWindow { return YES; } +// __v_ + - (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSWindowStyleMask)style backing:(NSBackingStoreType)backingStoreType @@ -2949,6 +3057,11 @@ _SOKOL_PRIVATE void _sapp_macos_poll_input_events() { - (BOOL)acceptsFirstResponder { return YES; } +- (BOOL)acceptsFirstMouse:(NSEvent *)event { + return YES; +} + + - (void)updateTrackingAreas { if (_sapp.macos.tracking_area != nil) { [self removeTrackingArea:_sapp.macos.tracking_area]; diff --git a/thirdparty/sokol/sokol_app2.h b/thirdparty/sokol/sokol_app2.h index 90e4c71222..7cddcdbb9f 100644 --- a/thirdparty/sokol/sokol_app2.h +++ b/thirdparty/sokol/sokol_app2.h @@ -1,9 +1,16 @@ @implementation MyView2 +int xx = 0; + // Alternative drawRect which calls a frame function with native Cocoa calls - (void)drawRect:(NSRect)rect { - _sapp_call_frame2(); + puts("drawRect()"); + if (xx == 0) { + _sapp_call_init(); + xx = 1; + } + _sapp_call_frame_native(); } //- (BOOL)isOpaque { diff --git a/vlib/gg/gg_darwin.m b/vlib/gg/gg_darwin.m index 6d0671c502..d6bb5a1481 100644 --- a/vlib/gg/gg_darwin.m +++ b/vlib/gg/gg_darwin.m @@ -81,11 +81,9 @@ void darwin_window_refresh() { //[g_view setNeedsDisplay:YES]; // update UI on the main thread TODO separate fn - /* dispatch_async(dispatch_get_main_queue(), ^{ [g_view setNeedsDisplay:YES]; }); - */ //puts("refresh"); //[g_view drawRect:NSMakeRect(0,0,2000,2000)];