-
Notifications
You must be signed in to change notification settings - Fork 62
Support full-screen mode on iOS #201
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -80,9 +80,10 @@ - (void)didRotate:(NSNotification*)notification | |
| [self setNeedsDisplay]; | ||
| } | ||
|
|
||
| - (void)setScreenManager:(TScreenManager*)sm | ||
| - (void)setScreenManager:(TScreenManager*)sm useFullScreen:(BOOL)fullScreen | ||
| { | ||
| mScreenManager = sm; | ||
| useFullScreen = fullScreen; | ||
| [self setNeedsDisplay]; | ||
| } | ||
|
|
||
|
|
@@ -116,14 +117,14 @@ - (void)layoutSubviews | |
| - (void)drawRect:(CGRect)rect | ||
| { | ||
| CGContextRef theContext = UIGraphicsGetCurrentContext(); | ||
| CGRect bounds = [self bounds]; | ||
|
|
||
| if (mScreenManager == NULL) | ||
| { | ||
| // Just fill black | ||
| // Fill with black when no screen manager | ||
| CGFloat black[] = { 0.0, 0.0, 0.0, 1.0 }; | ||
| CGRect frame = [self frame]; | ||
| CGContextSetFillColor(theContext, black); | ||
| CGContextFillRect(theContext, frame); | ||
| CGContextFillRect(theContext, bounds); | ||
| } else | ||
|
Comment on lines
122
to
128
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also set superview background when if (mScreenManager == NULL)
{
+ if (self.superview) self.superview.backgroundColor = [UIColor blackColor];
// Fill with black when no screen manager
CGFloat black[] = { 0.0, 0.0, 0.0, 1.0 };
CGContextSetFillColor(theContext, black);
CGContextFillRect(theContext, bounds);
}🤖 Prompt for AI Agents |
||
| { | ||
| if (mScreenImage == NULL) | ||
|
|
@@ -144,59 +145,91 @@ - (void)drawRect:(CGRect)rect | |
|
|
||
| CGColorSpaceRelease(theColorSpace); | ||
|
|
||
| // CGRect screenBounds = [[UIScreen mainScreen] bounds]; //OLD | ||
| CGRect screenBounds = [self bounds]; | ||
| CGRect r = [self frame]; | ||
|
|
||
| if (screenBounds.size.width > newtonScreenWidth && screenBounds.size.height > newtonScreenHeight) | ||
| { | ||
| if (newtonScreenWidth == newtonScreenHeight) | ||
| if (useFullScreen) { | ||
| // Full screen mode: leave room for border on all sides | ||
| // On iPad with 2x scaling, double the padding to maintain proportions | ||
| CGFloat borderPadding = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 30.0 : 15.0; | ||
| screenImageRect = CGRectInset(bounds, borderPadding, borderPadding); | ||
| } else { | ||
| // Classic mode: letterbox/center the Newton screen with integer scaling | ||
| CGRect screenBounds = bounds; | ||
| CGRect r = bounds; | ||
|
|
||
| if (screenBounds.size.width > newtonScreenWidth && screenBounds.size.height > newtonScreenHeight) | ||
| { | ||
| // Newton screen resolution is square (like 320x320) | ||
|
|
||
| int mod = (int) screenBounds.size.width % newtonScreenWidth; | ||
| r.size.width -= mod; | ||
| r.size.height = r.size.width; | ||
| } else | ||
| { | ||
| // Newton screen resolution is rectangular (like 320x480) | ||
|
|
||
| int wmod = (int) r.size.width % newtonScreenWidth; | ||
| int hmod = (int) r.size.height % newtonScreenHeight; | ||
|
|
||
| if (wmod > hmod) | ||
| if (newtonScreenWidth == newtonScreenHeight) | ||
| { | ||
| r.size.width -= wmod; | ||
|
|
||
| int scale = (int) r.size.width / newtonScreenWidth; | ||
| r.size.height = newtonScreenHeight * scale; | ||
| // Newton screen resolution is square (like 320x320) | ||
| int mod = (int) screenBounds.size.width % newtonScreenWidth; | ||
| r.size.width -= mod; | ||
| r.size.height = r.size.width; | ||
| } else | ||
| { | ||
| r.size.height -= hmod; | ||
|
|
||
| int scale = (int) r.size.height / newtonScreenHeight; | ||
| r.size.width = newtonScreenWidth * scale; | ||
| // Newton screen resolution is rectangular (like 320x480) | ||
| int wmod = (int) r.size.width % newtonScreenWidth; | ||
| int hmod = (int) r.size.height % newtonScreenHeight; | ||
|
|
||
| if (wmod > hmod) | ||
| { | ||
| r.size.width -= wmod; | ||
| int scale = (int) r.size.width / newtonScreenWidth; | ||
| r.size.height = newtonScreenHeight * scale; | ||
| } else | ||
| { | ||
| r.size.height -= hmod; | ||
| int scale = (int) r.size.height / newtonScreenHeight; | ||
| r.size.width = newtonScreenWidth * scale; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Center image on screen | ||
| // Center image on screen | ||
| r.origin.x += (screenBounds.size.width - r.size.width) / 2; | ||
| r.origin.y += (screenBounds.size.height - r.size.height) / 2; | ||
| } | ||
|
|
||
| r.origin.x += (screenBounds.size.width - r.size.width) / 2; | ||
| r.origin.y += (screenBounds.size.height - r.size.height) / 2; | ||
| screenImageRect = r; | ||
| screenImageRect.origin.x = floor(screenImageRect.origin.x); | ||
| screenImageRect.origin.y = floor(screenImageRect.origin.y); | ||
| screenImageRect.size.width = floor(screenImageRect.size.width); | ||
| screenImageRect.size.height = floor(screenImageRect.size.height); | ||
| } | ||
|
Comment on lines
+148
to
195
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fullscreen rect should preserve Newton aspect ratio (avoid subtle stretching). - CGFloat borderPadding = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 30.0 : 15.0;
- screenImageRect = CGRectInset(bounds, borderPadding, borderPadding);
+ CGFloat borderPadding = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 30.0 : 15.0;
+ CGRect avail = CGRectInset(bounds, borderPadding, borderPadding);
+ const CGFloat sx = avail.size.width / (CGFloat)newtonScreenWidth;
+ const CGFloat sy = avail.size.height / (CGFloat)newtonScreenHeight;
+ const CGFloat s = MIN(sx, sy); // aspect-fit
+ CGSize sz = CGSizeMake(floor(newtonScreenWidth * s), floor(newtonScreenHeight * s));
+ screenImageRect = CGRectMake(
+ floor(avail.origin.x + (avail.size.width - sz.width) / 2.0),
+ floor(avail.origin.y + (avail.size.height - sz.height) / 2.0),
+ sz.width, sz.height
+ );🤖 Prompt for AI Agents |
||
|
|
||
| screenImageRect = r; | ||
| screenImageRect.origin.x = floor(screenImageRect.origin.x); | ||
| screenImageRect.origin.y = floor(screenImageRect.origin.y); | ||
| screenImageRect.size.width = floor(screenImageRect.size.width); | ||
| screenImageRect.size.height = floor(screenImageRect.size.height); | ||
| } | ||
|
|
||
| // Draw the background of this view and the superview | ||
| [self drawBackgroundInContext:theContext withBounds:bounds]; | ||
|
|
||
| CGContextSetInterpolationQuality(theContext, kCGInterpolationNone); | ||
| CGContextDrawImage(theContext, screenImageRect, mScreenImage); | ||
| } | ||
| } | ||
|
|
||
| - (void)drawBackgroundInContext:(CGContextRef)context withBounds:(CGRect)bounds | ||
| { | ||
| static UIColor *defaultBgColor = [UIColor colorWithRed:(176/255.0) green:(191/255.0) blue:(169/255.0) alpha:1.0]; | ||
| static UIColor *fullScreenBgColor = [UIColor blackColor]; | ||
|
|
||
| // In classic mode, we use the storyboard's color (a muted green). | ||
| // In full-screen mode, we fill background with black. | ||
| UIColor* bgColor = useFullScreen ? fullScreenBgColor : defaultBgColor; | ||
|
|
||
| if (mScreenManager == NULL || newtonScreenWidth == 0 || newtonScreenHeight == 0) { | ||
| if (self.superview) { | ||
| self.superview.backgroundColor = bgColor; | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| // Set superview background to match (fills safe areas on notched devices) | ||
| if (self.superview) { | ||
| self.superview.backgroundColor = bgColor; | ||
| } | ||
|
|
||
| // Fill the entire view bounds with the background color | ||
| // The Newton screen image will be drawn on top | ||
| CGContextSetFillColorWithColor(context, bgColor.CGColor); | ||
| CGContextFillRect(context, bounds); | ||
| } | ||
|
|
||
| - (void)reset | ||
| { | ||
| mEmulator = NULL; | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -44,16 +44,26 @@ @implementation iEinsteinViewController | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - (void)viewWillAppear:(BOOL)animated | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [super viewWillAppear:animated]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #ifdef USE_STORYBOARDS | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [self initEmulator]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Initialization moved to viewDidLayoutSubviews to ensure correct bounds | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - (void)viewDidAppear:(BOOL)animated | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [super viewDidAppear:animated]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - (void)viewDidLayoutSubviews | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [super viewDidLayoutSubviews]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #ifdef USE_STORYBOARDS | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Only initialize once, after layout is complete so we have correct bounds | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!mEmulatorInitialized) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mEmulatorInitialized = YES; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [self initEmulator]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
44
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix init regression for non-storyboard builds (emulator may never initialize). - (void)viewDidLayoutSubviews
+ (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
-#ifdef USE_STORYBOARDS
// Only initialize once, after layout is complete so we have correct bounds
if (!mEmulatorInitialized) {
mEmulatorInitialized = YES;
[self initEmulator];
}
-#endif
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Action sheet delegate method. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -326,25 +336,60 @@ - (int)initEmulator | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mSoundManager = new TCoreAudioSoundManager(mLog); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // iPad is 1024x768. This size, and some appropriate scaling factors, should be selectable from | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // the 'Settings' panel. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static int widthLUT[] = { 320, 640, 384, 786, 640, 320, 750, 375, 1080, 540 }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static int heightLUT[] = { 480, 960, 512, 1024, 1136, 568, 1134, 567, 1920, 960 }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NSUserDefaults* prefs = [NSUserDefaults standardUserDefaults]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int index = [(NSNumber*) [prefs objectForKey:@"screen_resolution"] intValue]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int newtonScreenWidth = widthLUT[index]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int newtonScreenHeight = heightLUT[index]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #ifdef USE_STORYBOARDS | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // When using storyboards as configured, the einsteinView is a subview of self.view | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // This facilitates other subviews in the future. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| iEinsteinView* einsteinView = self.einsteinView; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // When using NIBs, the einsteinView is self.view | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| iEinsteinView* einsteinView = (iEinsteinView*) [self view]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Determine screen resolution based on use_full_screen setting | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NSUserDefaults* prefs = [NSUserDefaults standardUserDefaults]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BOOL useFullScreen = [(NSNumber*) [prefs objectForKey:@"use_full_screen"] boolValue]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int newtonScreenWidth, newtonScreenHeight; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (useFullScreen) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Full screen mode: use native view bounds for resolution | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CGRect viewBounds = [einsteinView bounds]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Use point dimensions (not pixels) for the Newton resolution. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The Newton is always in portrait orientation internally (width < height). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int viewWidth = (int)viewBounds.size.width; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int viewHeight = (int)viewBounds.size.height; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Ensure width is the smaller dimension (portrait mode for Newton) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (viewWidth < viewHeight) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newtonScreenWidth = viewWidth; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newtonScreenHeight = viewHeight; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newtonScreenWidth = viewHeight; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newtonScreenHeight = viewWidth; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // On iPad, use 2x scaling (halve resolution, scale up when drawing) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newtonScreenWidth /= 2.0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newtonScreenHeight /= 2.0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newtonScreenWidth /= 1.25; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newtonScreenHeight /= 1.25; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Round width to an even number (required for pixel operations) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newtonScreenWidth = (newtonScreenWidth + 1) & ~1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Classic mode: use LUT-based resolution from Settings | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static int widthLUT[] = { 320, 640, 384, 786, 640, 320, 750, 375, 1080, 540 }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static int heightLUT[] = { 480, 960, 512, 1024, 1136, 568, 1134, 567, 1920, 960 }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int index = [(NSNumber*) [prefs objectForKey:@"screen_resolution"] intValue]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newtonScreenWidth = widthLUT[index]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| newtonScreenHeight = heightLUT[index]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Store current settings for change detection | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lastKnownFullScreenMode = useFullScreen; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lastKnownScreenResolution = [(NSNumber*) [prefs objectForKey:@"screen_resolution"] intValue]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+345
to
+392
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clamp - int index = [(NSNumber*) [prefs objectForKey:@"screen_resolution"] intValue];
- newtonScreenWidth = widthLUT[index];
- newtonScreenHeight = heightLUT[index];
+ int index = [(NSNumber*) [prefs objectForKey:@"screen_resolution"] intValue];
+ const int lutSize = (int)(sizeof(widthLUT) / sizeof(widthLUT[0]));
+ if (index < 0) index = 0;
+ if (index >= lutSize) index = lutSize - 1;
+ newtonScreenWidth = widthLUT[index];
+ newtonScreenHeight = heightLUT[index];🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Boolean isLandscape = (newtonScreenWidth > newtonScreenHeight); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mScreenManager = new TIOSScreenManager( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -355,7 +400,7 @@ - (int)initEmulator | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isLandscape); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [einsteinView setScreenManager:mScreenManager]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [einsteinView setScreenManager:mScreenManager useFullScreen:useFullScreen]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Create the printer manager. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mPrinterManager = new TIOSPrinterManager(mLog); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -386,23 +431,31 @@ - (int)initEmulator | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - (void)startEmulator | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // See if screen resolution has changed since last time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Check if screen settings have changed since last time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NSUserDefaults* prefs = [NSUserDefaults standardUserDefaults]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [prefs synchronize]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+434
to
+437
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: Short answer: don't call synchronize — it's unnecessary and deprecated. Use UserDefaults (UserDefaults.standard or UserDefaults(suiteName:)) normally; changes are written asynchronously by the system. For cross-device sync use NSUbiquitousKeyValueStore; for shared-app-group storage use UserDefaults(suiteName:). There is no supported API to forcibly flush writes on iOS — design so you don't depend on immediate disk writes. [1][2][3] Sources:
Remove deprecated The 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BOOL currentFullScreenMode = [(NSNumber*) [prefs objectForKey:@"use_full_screen"] boolValue]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int currentScreenResolution = [(NSNumber*) [prefs objectForKey:@"screen_resolution"] intValue]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (currentScreenResolution != lastKnownScreenResolution) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Reboot emulator | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BOOL needsReset = NO; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (currentFullScreenMode != lastKnownFullScreenMode) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mLog->LogLine("Full screen mode changed by Settings."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| needsReset = YES; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if (!currentFullScreenMode && currentScreenResolution != lastKnownScreenResolution) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Only check resolution change in classic mode (not full screen) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mLog->LogLine("Newton screen resolution changed by Settings."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| needsReset = YES; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (needsReset) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lastKnownFullScreenMode = currentFullScreenMode; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lastKnownScreenResolution = currentScreenResolution; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [self resetEmulator]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Start the thread. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mLog->LogLine("Detaching emulator thread"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [NSThread detachNewThreadSelector:@selector(emulatorThread) toTarget:self withObject:nil]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make
GetImageBuffer()contract explicit (lifetime/thread-safety) and prefer read-only access by default.Returning a raw mutable
KUInt32*leaks internal state: callers can accidentally write into the buffer, hold onto it across resizes/power transitions, or race with emulator rendering. At minimum, document ownership/nullability and whether the pointer can change; ideally expose aconstgetter and add an explicit mutable accessor only if you truly need external writes.📝 Committable suggestion
🤖 Prompt for AI Agents