Revision: 2665
http://sourceforge.net/p/swingme/code/2665
Author: yuranet
Date: 2022-12-22 17:15:27 +0000 (Thu, 22 Dec 2022)
Log Message:
-----------
fix crash in finalize when getRGB is called in background thread
Modified Paths:
--------------
iOSME/src/javax/microedition/lcdui/Canvas.java
iOSME/src/javax/microedition/lcdui/Display.java
iOSME/src/javax/microedition/lcdui/Image.java
iOSME/src/net/yura/ios/AppController.java
iOSME/src/net/yura/ios/iOSUtil.java
Modified: iOSME/src/javax/microedition/lcdui/Canvas.java
===================================================================
--- iOSME/src/javax/microedition/lcdui/Canvas.java 2022-12-20 11:19:17 UTC (rev 2664)
+++ iOSME/src/javax/microedition/lcdui/Canvas.java 2022-12-22 17:15:27 UTC (rev 2665)
@@ -335,6 +335,7 @@
public void serviceRepaints() {
NSOperationQueue.mainQueue().waitUntilAllOperationsAreFinished();
+ //CoreGraphics.CGContextFlush(canvasView.graphics.getContext());
}
public String getKeyName(int keyCode) {
Modified: iOSME/src/javax/microedition/lcdui/Display.java
===================================================================
--- iOSME/src/javax/microedition/lcdui/Display.java 2022-12-20 11:19:17 UTC (rev 2664)
+++ iOSME/src/javax/microedition/lcdui/Display.java 2022-12-22 17:15:27 UTC (rev 2665)
@@ -150,6 +150,8 @@
}
/**
+ * https://stackoverflow.com/questions/26455880/how-to-make-iphone-vibrate-using-swift
+ *
* @return true if the vibrator can be controlled by the application and this display is in the foreground, false otherwise
*/
public boolean vibrate(int duration) {
Modified: iOSME/src/javax/microedition/lcdui/Image.java
===================================================================
--- iOSME/src/javax/microedition/lcdui/Image.java 2022-12-20 11:19:17 UTC (rev 2664)
+++ iOSME/src/javax/microedition/lcdui/Image.java 2022-12-22 17:15:27 UTC (rev 2665)
@@ -199,13 +199,7 @@
//UIKit.UIGraphicsBeginImageContext(new CGSize(width, height));
//CGContextRef context = UIKit.UIGraphicsGetCurrentContext();
- // we try and create a Context as close as we can to using UIKit.UIGraphicsBeginImageContext(new CGSize(width, height));
- CGColorSpaceRef space = CoreGraphics.CGColorSpaceCreateDeviceRGB();
- // min bytesPerRow is "width * (CoreGraphics.CGColorSpaceGetNumberOfComponents(space) + 1)" passing a value of 0 causes the value to be calculated automatically
- CGContextRef context = CoreGraphics.CGBitmapContextCreate(null, width, height, 8, 0, space, CGBitmapInfo.ByteOrder32Little | CGImageAlphaInfo.PremultipliedFirst);
- CoreGraphics.CGColorSpaceRelease(space);
- CoreGraphics.CGContextTranslateCTM(context, 0, height);
- CoreGraphics.CGContextScaleCTM(context, 1.0, -1.0);
+ CGContextRef context = threadsafeUIGraphicsBeginImageContext(width, height);
//System.out.println("BitmapContext2 BitsPerPixel=" +CoreGraphics.CGBitmapContextGetBitsPerPixel(context) + " BitsPerComponent=" +CoreGraphics.CGBitmapContextGetBitsPerComponent(context) + " BytesPerRow=" +CoreGraphics.CGBitmapContextGetBytesPerRow(context) + " AlphaInfo=" +CoreGraphics.CGBitmapContextGetAlphaInfo(context) + " BitmapInfo=" +CoreGraphics.CGBitmapContextGetBitmapInfo(context));
@@ -217,6 +211,26 @@
return new Image(context);
}
+ /**
+ * we can NEVER use {@link UIKit#UIGraphicsBeginImageContext(CGSize)} as it does not seem to be truly thread safe in MOE
+ */
+ private static CGContextRef threadsafeUIGraphicsBeginImageContext(int width, int height) {
+/* // this does not work in some situations
+ return iOSUtil.callOnMainThread(() -> {
+ UIKit.UIGraphicsBeginImageContext(new CGSize(width, height));
+ return UIKit.UIGraphicsGetCurrentContext();
+ });
+*/
+ // we try and create a Context as close as we can to using UIKit.UIGraphicsBeginImageContext(new CGSize(width, height));
+ CGColorSpaceRef space = CoreGraphics.CGColorSpaceCreateDeviceRGB();
+ // min bytesPerRow is "width * (CoreGraphics.CGColorSpaceGetNumberOfComponents(space) + 1)" passing a value of 0 causes the value to be calculated automatically
+ CGContextRef context = CoreGraphics.CGBitmapContextCreate(null, width, height, 8, 0, space, CGBitmapInfo.ByteOrder32Little | CGImageAlphaInfo.PremultipliedFirst);
+ CoreGraphics.CGColorSpaceRelease(space);
+ CoreGraphics.CGContextTranslateCTM(context, 0, height);
+ CoreGraphics.CGContextScaleCTM(context, 1.0, -1.0);
+ return context;
+ }
+
public static final Image createRGBImage(int[] rgb, int width, int height, boolean processAlpha) {
// TODO not optimum as we first create white image
Image img = createImage(width, height);
@@ -319,14 +333,14 @@
}
private void releaseCGContext() {
- CGContextRef current = UIKit.UIGraphicsGetCurrentContext();
- if (current == null || !current.getPeer().equals(context.getPeer())) {
- UIKit.UIGraphicsPushContext(context);
+ //CGContextRef current = UIKit.UIGraphicsGetCurrentContext();
+ //if (current == null || !current.getPeer().equals(context.getPeer())) {
+ // UIKit.UIGraphicsPushContext(context);
+ //}
+ //UIKit.UIGraphicsEndImageContext(); // this seems to do the same as CGContextRelease, maybe it does something more
+ // has the same effect on memory, and causes a crash if we call CGContextRelease after UIGraphicsEndImageContext
- }
- UIKit.UIGraphicsEndImageContext(); // this seems to do the same as CGContextRelease, maybe it does something more
- // has the same effect on memory, and causes a crash if we call CGContextRelease after UIGraphicsEndImageContext
- //CoreGraphics.CGContextRelease(context);
+ CoreGraphics.CGContextRelease(context);
context = null;
}
@@ -345,6 +359,11 @@
//org.moe.GCUtil.gc(); // force anything still around to be GCed
}
+ /**
+ * WARNING! do NOT try to log {@link #uiImage} from this method, it will crash MOE!
+ * WARNING! do NOT call {@link #toString()} from this method as that toStrings uiImage
+ * WARNING! do NOT try and call {@link #getWidth()} or {@link #getHeight()} either
+ */
@Override
protected void finalize() throws Throwable {
if (context != null) {
@@ -383,13 +402,18 @@
// if the image has already been loaded into the context, do nothing
if (context == null) {
// load the current image into the context
- UIKit.UIGraphicsBeginImageContext(new CGSize(getWidth(), getHeight()));
- context = UIKit.UIGraphicsGetCurrentContext();
+ // this causes crashes when called from background threads if that thread finishes while the image has still not been GCed
+ //UIKit.UIGraphicsBeginImageContext(new CGSize(getWidth(), getHeight()));
+ //context = UIKit.UIGraphicsGetCurrentContext();
+ context = threadsafeUIGraphicsBeginImageContext(getWidth(), getHeight());
+
// this is needed for 9-patches to load correctly
CoreGraphics.CGContextSetInterpolationQuality(context, CGInterpolationQuality.None);
+ UIKit.UIGraphicsPushContext(context);
uiImage.drawAtPoint(CoreGraphics.CGPointZero());
+ UIKit.UIGraphicsPopContext();
}
}
Modified: iOSME/src/net/yura/ios/AppController.java
===================================================================
--- iOSME/src/net/yura/ios/AppController.java 2022-12-20 11:19:17 UTC (rev 2664)
+++ iOSME/src/net/yura/ios/AppController.java 2022-12-22 17:15:27 UTC (rev 2665)
@@ -39,7 +39,19 @@
notificationCenter.addObserverSelectorNameObject(this, new SEL("keyboardWillShow:"), UIKit.UIKeyboardWillShowNotification(), null);
notificationCenter.addObserverSelectorNameObject(this, new SEL("keyboardWillHide:"), UIKit.UIKeyboardWillHideNotification(), null);
notificationCenter.addObserverSelectorNameObject(this, new SEL("keyboardWillChange:"), UIKit.UIKeyboardWillChangeFrameNotification(), null);
-
+/*
+ // uncomment to enable force GC swipe from right to left along the top of the app gesture
+ UISwipeGestureRecognizer swipeLeft = UISwipeGestureRecognizer.alloc().initWithTargetAction(this, new SEL("respondToSwipeGesture:"));
+ swipeLeft.setDirection(UISwipeGestureRecognizerDirection.Left);
+ view().addGestureRecognizer(swipeLeft);
+ swipeLeft.setDelegate(new UIGestureRecognizerDelegate() {
+ @Override
+ public boolean gestureRecognizerShouldBegin(UIGestureRecognizer gestureRecognizer) {
+ CGPoint locationInView = gestureRecognizer.locationInView(view());
+ return locationInView.y() < 44; // DesktopPane.getDesktopPane().minimumTouchTarget
+ }
+ });
+*/
Display display = Display.getDisplay(MIDlet.DEFAULT_MIDLET);
display.setController(this);
}
@@ -58,7 +70,14 @@
public void keyboardWillChange(NSNotification notification) {
setAdditionalSafeAreaInsets(new UIEdgeInsets(0, 0, getAdditionalSafeAreaBottom(notification), 0));
}
-
+/*
+ @Selector("respondToSwipeGesture:")
+ public void respondToSwipeGesture(UIGestureRecognizer recognizer) {
+ System.out.println("########### Debug Swipe detected " + recognizer);
+ GCUtil.gc();
+ Display.getDisplay(MIDlet.DEFAULT_MIDLET).vibrate(1); // AudioToolbox.AudioServicesPlayAlertSound(Enums.kSystemSoundID_Vibrate);
+ }
+*/
private double getAdditionalSafeAreaBottom(NSNotification notification) {
double keyboardHeight = ((NSValue)notification.userInfo().get(UIKit.UIKeyboardFrameEndUserInfoKey())).CGRectValue().size().height();
double bottomPadding = UIApplication.sharedApplication().keyWindow().safeAreaInsets().bottom();
Modified: iOSME/src/net/yura/ios/iOSUtil.java
===================================================================
--- iOSME/src/net/yura/ios/iOSUtil.java 2022-12-20 11:19:17 UTC (rev 2664)
+++ iOSME/src/net/yura/ios/iOSUtil.java 2022-12-22 17:15:27 UTC (rev 2665)
@@ -105,6 +105,14 @@
thing.run();
}
else {
+/*
+ Globals.dispatch_async(Globals.dispatch_get_main_queue(), new Globals.Block_dispatch_async() {
+ @Override
+ public void call_dispatch_async() {
+ thing.run();
+ }
+ });
+*/
NSOperationQueue.mainQueue().addOperationWithBlock(new NSOperationQueue.Block_addOperationWithBlock() {
@Override
public void call_addOperationWithBlock() {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|