Last active
November 27, 2025 05:03
-
-
Save g-l-i-t-c-h-o-r-s-e/4b392c826d82102c486eb0b6f21d9208 to your computer and use it in GitHub Desktop.
Test External Window in QC Plugin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // BasicExternalWindowPlugIn.h | |
| // BasicExternalWindow | |
| // | |
| #import <Quartz/Quartz.h> | |
| @interface BasicExternalWindowPlugIn : QCPlugIn | |
| { | |
| double _tick; | |
| } | |
| // Output: dummy number so QC knows we’re “doing something” | |
| @property (assign) double outputTick; | |
| @end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // BasicExternalWindowPlugIn.m | |
| // BasicExternalWindow | |
| // | |
| #import "BasicExternalWindowPlugIn.h" | |
| #import "BasicExternalWindowController.h" | |
| #define kQCPlugIn_Name @"External Window Test" | |
| #define kQCPlugIn_Description @"Simple QC plug-in that always opens a Cocoa window." | |
| @implementation BasicExternalWindowPlugIn | |
| @dynamic outputTick; | |
| + (NSDictionary *)attributes | |
| { | |
| return @{ | |
| QCPlugInAttributeNameKey : kQCPlugIn_Name, | |
| QCPlugInAttributeDescriptionKey : kQCPlugIn_Description | |
| }; | |
| } | |
| + (NSDictionary *)attributesForPropertyPortWithKey:(NSString *)key | |
| { | |
| if ([key isEqualToString:@"outputTick"]) { | |
| return @{ | |
| QCPortAttributeNameKey : @"Tick" | |
| }; | |
| } | |
| return nil; | |
| } | |
| + (QCPlugInExecutionMode)executionMode | |
| { | |
| // Simple provider (no image output) | |
| return kQCPlugInExecutionModeProvider; | |
| } | |
| + (QCPlugInTimeMode)timeMode | |
| { | |
| // Ask QC to call execute: regularly while the viewer is running | |
| return kQCPlugInTimeModeIdle; | |
| } | |
| + (BOOL)allowsSubpatches | |
| { | |
| return NO; | |
| } | |
| #pragma mark - Lifecycle | |
| - (BOOL)startExecution:(id<QCPlugInContext>)context | |
| { | |
| _tick = 0.0; | |
| NSLog(@"[BasicExternalWindow] startExecution"); | |
| dispatch_async(dispatch_get_main_queue(), ^{ | |
| BasicExternalWindowController *controller = [BasicExternalWindowController sharedController]; | |
| NSLog(@"[BasicExternalWindow] startExecution -> showWindow (unconditional)"); | |
| [controller showWindowFromPlugin:self]; | |
| }); | |
| self.outputTick = _tick; | |
| return YES; | |
| } | |
| - (void)stopExecution:(id<QCPlugInContext>)context | |
| { | |
| NSLog(@"[BasicExternalWindow] stopExecution"); | |
| dispatch_async(dispatch_get_main_queue(), ^{ | |
| [[BasicExternalWindowController sharedController] hideWindow]; | |
| }); | |
| } | |
| #pragma mark - Execution | |
| - (BOOL)execute:(id<QCPlugInContext>)context | |
| atTime:(NSTimeInterval)time | |
| arguments:(NSDictionary *)arguments | |
| { | |
| _tick += 1.0; | |
| self.outputTick = _tick; | |
| // Still log so you can see it's alive | |
| NSLog(@"[BasicExternalWindow] execute: t=%f tick=%f", time, _tick); | |
| return YES; | |
| } | |
| @end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // BasicExternalWindowPlugIn.h | |
| // BasicExternalWindow | |
| // | |
| #import <Quartz/Quartz.h> | |
| @interface BasicExternalWindowPlugIn : QCPlugIn | |
| { | |
| BOOL _lastShow; | |
| double _tick; | |
| } | |
| // Input: show/hide window (default YES) | |
| @property (assign) BOOL inputShowWindow; | |
| // Output: dummy number so QC happily runs execute: | |
| @property (assign) double outputTick; | |
| @end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // BasicExternalWindowPlugIn.m | |
| // BasicExternalWindow | |
| // | |
| #import "BasicExternalWindowPlugIn.h" | |
| #import "BasicExternalWindowController.h" | |
| #define kQCPlugIn_Name @"External Window Test" | |
| #define kQCPlugIn_Description @"Simple QC plug-in that opens a Cocoa window." | |
| @implementation BasicExternalWindowPlugIn | |
| @dynamic inputShowWindow; | |
| @dynamic outputTick; | |
| + (NSDictionary *)attributes | |
| { | |
| return @{ | |
| QCPlugInAttributeNameKey : kQCPlugIn_Name, | |
| QCPlugInAttributeDescriptionKey : kQCPlugIn_Description | |
| }; | |
| } | |
| + (NSDictionary *)attributesForPropertyPortWithKey:(NSString *)key | |
| { | |
| if ([key isEqualToString:@"inputShowWindow"]) { | |
| // Default ON so the window appears as soon as the patch starts | |
| return @{ | |
| QCPortAttributeNameKey : @"Show Window", | |
| QCPortAttributeDefaultValueKey : @YES | |
| }; | |
| } | |
| else if ([key isEqualToString:@"outputTick"]) { | |
| return @{ | |
| QCPortAttributeNameKey : @"Tick" | |
| }; | |
| } | |
| return nil; | |
| } | |
| + (QCPlugInExecutionMode)executionMode | |
| { | |
| // Simple provider (no image output) | |
| return kQCPlugInExecutionModeProvider; | |
| } | |
| + (QCPlugInTimeMode)timeMode | |
| { | |
| // Ask QC to call execute: regularly while the viewer is running | |
| return kQCPlugInTimeModeIdle; | |
| } | |
| + (BOOL)allowsSubpatches | |
| { | |
| return NO; | |
| } | |
| #pragma mark - Lifecycle | |
| - (BOOL)startExecution:(id<QCPlugInContext>)context | |
| { | |
| _tick = 0.0; | |
| _lastShow = YES; | |
| BOOL show = self.inputShowWindow; | |
| NSLog(@"[BasicExternalWindow] startExecution (inputShowWindow=%d)", show); | |
| // For now, ALWAYS force window to show on start so we know the plumbing works | |
| dispatch_async(dispatch_get_main_queue(), ^{ | |
| BasicExternalWindowController *controller = [BasicExternalWindowController sharedController]; | |
| NSLog(@"[BasicExternalWindow] startExecution -> forcing showWindow"); | |
| [controller showWindowFromPlugin:self]; | |
| }); | |
| self.outputTick = _tick; | |
| return YES; | |
| } | |
| - (void)stopExecution:(id<QCPlugInContext>)context | |
| { | |
| NSLog(@"[BasicExternalWindow] stopExecution"); | |
| dispatch_async(dispatch_get_main_queue(), ^{ | |
| [[BasicExternalWindowController sharedController] hideWindow]; | |
| }); | |
| } | |
| #pragma mark - Execution | |
| - (BOOL)execute:(id<QCPlugInContext>)context | |
| atTime:(NSTimeInterval)time | |
| arguments:(NSDictionary *)arguments | |
| { | |
| BOOL show = self.inputShowWindow; | |
| _tick += 1.0; | |
| self.outputTick = _tick; | |
| NSLog(@"[BasicExternalWindow] execute: t=%f inputShowWindow=%d last=%d tick=%f", | |
| time, show, _lastShow, _tick); | |
| if (show != _lastShow) { | |
| NSLog(@"[BasicExternalWindow] execute: detected Show Window change -> %d", show); | |
| _lastShow = show; | |
| dispatch_async(dispatch_get_main_queue(), ^{ | |
| BasicExternalWindowController *controller = [BasicExternalWindowController sharedController]; | |
| if (show) { | |
| NSLog(@"[BasicExternalWindow] -> showWindow (from execute:)"); | |
| [controller showWindowFromPlugin:self]; | |
| } else { | |
| NSLog(@"[BasicExternalWindow] -> hideWindow (from execute:)"); | |
| [controller hideWindow]; | |
| } | |
| }); | |
| } | |
| return YES; | |
| } | |
| @end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment