From f1c61bba6934d497a649e17baddf36b60d07d958 Mon Sep 17 00:00:00 2001
From: Lyubomir Marinov <lyubomir.marinov@jitsi.org>
Date: Sun, 23 Nov 2014 17:26:20 +0200
Subject: [PATCH] Fixes issues with JAWTRenderer on Java 7 under OS X. Base on
 contributions by Ingo Bauersachs.

---
 src/native/jawtrenderer/JAWTRenderer.h        |  12 +-
 src/native/jawtrenderer/JAWTRenderer_MacOSX.m | 103 ++++++++++++++++--
 ...jmfext_media_renderer_video_JAWTRenderer.c |  53 +++++++++
 ...jmfext_media_renderer_video_JAWTRenderer.h |  16 +++
 4 files changed, 169 insertions(+), 15 deletions(-)

diff --git a/src/native/jawtrenderer/JAWTRenderer.h b/src/native/jawtrenderer/JAWTRenderer.h
index 53eb8b92..f4bec095 100644
--- a/src/native/jawtrenderer/JAWTRenderer.h
+++ b/src/native/jawtrenderer/JAWTRenderer.h
@@ -8,11 +8,11 @@
 #ifndef _JAWTRENDERER_H_
 #define _JAWTRENDERER_H_
 
-#ifndef __ANDROID__
-    #include <jawt.h>
-#else /* #ifndef __ANDROID__ */
+#ifdef __ANDROID__
     typedef void JAWT_DrawingSurfaceInfo;
-#endif /* #ifndef __ANDROID__ */
+#else /* #ifdef __ANDROID__ */
+    #include <jawt.h>
+#endif /* #ifdef __ANDROID__ */
 #include <jni.h>
 
 #ifndef NULL
@@ -23,6 +23,8 @@
 extern "C" {
 #endif /* #ifdef __cplusplus */
 
+void JAWTRenderer_addNotify
+    (JNIEnv *env, jclass clazz, jlong handle, jobject component);
 void JAWTRenderer_close
     (JNIEnv *env, jclass clazz, jlong handle, jobject component);
 jlong JAWTRenderer_open(JNIEnv *env, jclass clazz, jobject component);
@@ -32,6 +34,8 @@ jboolean JAWTRenderer_paint
 jboolean JAWTRenderer_process
     (JNIEnv *env, jclass clazz,jlong handle, jobject component, jint *data,
         jint length, jint width, jint height);
+void JAWTRenderer_removeNotify
+    (JNIEnv *env, jclass clazz, jlong handle, jobject component);
 
 #ifdef __APPLE__
 jstring JAWTRenderer_sysctlbyname(JNIEnv *env, jstring name);
diff --git a/src/native/jawtrenderer/JAWTRenderer_MacOSX.m b/src/native/jawtrenderer/JAWTRenderer_MacOSX.m
index 51d4e50a..62fa5f4c 100644
--- a/src/native/jawtrenderer/JAWTRenderer_MacOSX.m
+++ b/src/native/jawtrenderer/JAWTRenderer_MacOSX.m
@@ -51,22 +51,42 @@
             forLayerTime:(CFTimeInterval)timeInterval
              displayTime:(const CVTimeStamp *)timeStamp;
 - (id)init;
+- (void)setFrameFromJAWTDrawingSurfaceInfo:(JAWT_DrawingSurfaceInfo *)dsi;
 @end /* JAWTRendererLayer */
 
+/*
+ * JAWT version 1.7 does not define the type JAWT_MacOSXDrawingSurfaceInfo.
+ */
+#ifdef JAWT_VERSION_1_7
+// Legacy NSView-based rendering
+typedef struct JAWT_MacOSXDrawingSurfaceInfo {
+    NSView *cocoaViewRef; // the view is guaranteed to be valid only for the duration of Component.paint method
+}
+JAWT_MacOSXDrawingSurfaceInfo;
+#endif /* #ifdef JAWT_VERSION_1_7 */
+
+void
+JAWTRenderer_addNotify
+    (JNIEnv *env, jclass clazz, jlong handle, jobject component)
+{
+    /* TODO Auto-generated method stub */
+}
+
 void
 JAWTRenderer_close(JNIEnv *env, jclass clazz, jlong handle, jobject component)
 {
-    JAWTRendererLayer **thiz;
-    NSAutoreleasePool *autoreleasePool;
+    JAWTRendererLayer **thiz = (JAWTRendererLayer **) (intptr_t) handle;
+    JAWTRendererLayer *layer = *thiz;
 
-    thiz = (JAWTRendererLayer **) (intptr_t) handle;
-    autoreleasePool = [[NSAutoreleasePool alloc] init];
+    if (layer)
+    {
+        NSAutoreleasePool *autoreleasePool;
 
-    if (*thiz)
-        [*thiz release];
+        autoreleasePool = [[NSAutoreleasePool alloc] init];
+        [layer release];
+        [autoreleasePool release];
+    }
     free(thiz);
-
-    [autoreleasePool release];
 }
 
 jlong
@@ -84,6 +104,7 @@ JAWTRenderer_paint
     JAWTRendererLayer *thizLayer;
     jboolean wantsPaint = JNI_TRUE;
     JAWTRendererLayer **thiz;
+    JAWTRendererLayer *oldThizLayer;
 
     autoreleasePool = [[NSAutoreleasePool alloc] init];
 
@@ -98,14 +119,22 @@ JAWTRenderer_paint
         CALayer *layer = surfaceLayers.layer;
 
         if (layer && [layer isKindOfClass:[JAWTRendererLayer class]])
+        {
             thizLayer = (JAWTRendererLayer *) layer;
+        }
         else
         {
             thizLayer = [JAWTRendererLayer layer];
             if (thizLayer)
+            {
+                [thizLayer setFrameFromJAWTDrawingSurfaceInfo:dsi];
                 surfaceLayers.layer = thizLayer;
+                [thizLayer autorelease];
+            }
             else
+            {
                 wantsPaint = JNI_FALSE;
+            }
         }
     }
     else
@@ -116,17 +145,23 @@ JAWTRenderer_paint
         CALayer *layer = [view layer];
 
         if (layer && [layer isKindOfClass:[JAWTRendererLayer class]])
+        {
             thizLayer = (JAWTRendererLayer *) layer;
+        }
         else
         {
             thizLayer = [JAWTRendererLayer layer];
             if (thizLayer)
             {
+                [thizLayer setFrameFromJAWTDrawingSurfaceInfo:dsi];
                 [view setLayer:thizLayer];
                 [view setWantsLayer:YES];
+                [thizLayer autorelease];
             }
             else
+            {
                 wantsPaint = JNI_FALSE;
+            }
         }
     }
 
@@ -135,10 +170,11 @@ JAWTRenderer_paint
      * native peer of the AWT Canvas that is the component of this JAWTRenderer.
      */
     thiz = (JAWTRendererLayer **) (intptr_t) handle;
-    if (*thiz != thizLayer)
+    oldThizLayer = *thiz;
+    if (oldThizLayer != thizLayer)
     {
-        if (*thiz)
-            [*thiz release];
+        if (oldThizLayer)
+            [oldThizLayer release];
         *thiz = thizLayer;
         if (thizLayer)
             [thizLayer retain];
@@ -250,6 +286,28 @@ JAWTRenderer_process
     return JNI_TRUE;
 }
 
+void
+JAWTRenderer_removeNotify
+    (JNIEnv *env, jclass clazz, jlong handle, jobject component)
+{
+    /*
+     * The AWT Comonent notifies that it is being made undisplayable by
+     * destroying its native screen resource. For an unknown reason, the
+     * JAWTRendererLayer is not automatically removed from its superlayer and
+     * remains visible.
+     */
+    JAWTRendererLayer *thiz = *((JAWTRendererLayer **) (intptr_t) handle);
+
+    if (thiz)
+    {
+    	NSAutoreleasePool *autoreleasePool;
+
+        autoreleasePool = [[NSAutoreleasePool alloc] init];
+        [thiz removeFromSuperlayer];
+        [autoreleasePool release];
+    }
+}
+
 jstring
 JAWTRenderer_sysctlbyname(JNIEnv *env, jstring name)
 {
@@ -270,7 +328,9 @@ JAWTRenderer_sysctlbyname(JNIEnv *env, jstring name)
             {
                 if ((0 == sysctlbyname(_name, _value, &valueLength, NULL, 0))
                         && valueLength)
+                {
                     _value[valueLength] = 0;
+                }
                 else
                 {
                     free(_value);
@@ -279,7 +339,9 @@ JAWTRenderer_sysctlbyname(JNIEnv *env, jstring name)
             }
         }
         else
+        {
             _value = NULL;
+        }
         (*env)->ReleaseStringUTFChars(env, name, _name);
 
         if (_value)
@@ -406,11 +468,13 @@ JAWTRenderer_sysctlbyname(JNIEnv *env, jstring name)
                         == CGLCreateContext(_pixelFormat, NULL, &_glContext)))
         {
             self.asynchronous = YES;
+            self.autoresizingMask = kCALayerNotSizable;
             /*
              * The AWT Canvas that corresponds to this CAOpenGLLayer will ensure
              * that the latter will be displayed on bounds changes.
              */
             self.needsDisplayOnBoundsChange = NO;
+            self.opaque = YES;
         }
         else
         {
@@ -420,4 +484,21 @@ JAWTRenderer_sysctlbyname(JNIEnv *env, jstring name)
     }
     return self;
 }
+
+- (void)setFrameFromJAWTDrawingSurfaceInfo:(JAWT_DrawingSurfaceInfo *)dsi
+{
+    JAWT_Rectangle *jawtrect;
+
+    jawtrect = &(dsi->bounds);
+    if (jawtrect->height > 0 && jawtrect->width > 0)
+    {
+        CGRect cgrect;
+
+        cgrect.origin.x = jawtrect->x;
+        cgrect.origin.y = -(jawtrect->y);
+        cgrect.size.height = jawtrect->height;
+        cgrect.size.width = jawtrect->width;
+        self.frame = cgrect;
+    }
+}
 @end /* JAWTRendererLayer */
diff --git a/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.c b/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.c
index 671f2ab5..90256d5d 100644
--- a/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.c
+++ b/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.c
@@ -8,6 +8,25 @@
 #include "org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.h"
 #include "JAWTRenderer.h"
 
+/*
+ * Class:     org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer
+ * Method:    addNotify
+ * Signature: (JLjava/awt/Component;)V
+ */
+JNIEXPORT void JNICALL
+Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_addNotify
+    (JNIEnv *env, jclass clazz, jlong handle, jobject component)
+{
+#ifdef __APPLE__
+    JAWTRenderer_addNotify(env, clazz, handle, component);
+#endif /* #ifdef __APPLE__ */
+}
+
+/*
+ * Class:     org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer
+ * Method:    close
+ * Signature: (JLjava/awt/Component;)V
+ */
 JNIEXPORT void JNICALL
 Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_close
     (JNIEnv *env, jclass clazz, jlong handle, jobject component)
@@ -15,6 +34,11 @@ Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_close
     JAWTRenderer_close(env, clazz, handle, component);
 }
 
+/*
+ * Class:     org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer
+ * Method:    open
+ * Signature: (Ljava/awt/Component;)J
+ */
 JNIEXPORT jlong JNICALL
 Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_open
     (JNIEnv *env, jclass clazz, jobject component)
@@ -22,6 +46,11 @@ Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_open
     return JAWTRenderer_open(env, clazz, component);
 }
 
+/*
+ * Class:     org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer
+ * Method:    paint
+ * Signature: (JLjava/awt/Component;Ljava/awt/Graphics;I)Z
+ */
 JNIEXPORT jboolean JNICALL
 Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_paint
     (JNIEnv *env, jclass clazz, jlong handle, jobject component, jobject g,
@@ -99,6 +128,11 @@ Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_paint
 #endif /* #ifdef __ANDROID__ */
 }
 
+/*
+ * Class:     org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer
+ * Method:    process
+ * Signature: (JLjava/awt/Component;[IIIII)Z
+ */
 JNIEXPORT jboolean JNICALL
 Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_process
     (JNIEnv *env, jclass clazz, jlong handle, jobject component, jintArray data,
@@ -126,6 +160,25 @@ Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_process
     return processed;
 }
 
+/*
+ * Class:     org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer
+ * Method:    removeNotify
+ * Signature: (JLjava/awt/Component;)V
+ */
+JNIEXPORT void JNICALL
+Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_removeNotify
+    (JNIEnv *env, jclass clazz, jlong handle, jobject component)
+{
+#ifdef __APPLE__
+    JAWTRenderer_removeNotify(env, clazz, handle, component);
+#endif /* #ifdef __APPLE__ */
+}
+
+/*
+ * Class:     org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer
+ * Method:    sysctlbyname
+ * Signature: (Ljava/lang/String;)Ljava/lang/String;
+ */
 JNIEXPORT jstring JNICALL
 Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_sysctlbyname
     (JNIEnv *env, jclass clazz, jstring name)
diff --git a/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.h b/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.h
index 29d983bb..c62658f7 100644
--- a/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.h
+++ b/src/native/jawtrenderer/org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer.h
@@ -7,6 +7,14 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+/*
+ * Class:     org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer
+ * Method:    addNotify
+ * Signature: (JLjava/awt/Component;)V
+ */
+JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_addNotify
+  (JNIEnv *, jclass, jlong, jobject);
+
 /*
  * Class:     org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer
  * Method:    close
@@ -39,6 +47,14 @@ JNIEXPORT jboolean JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_renderer_vi
 JNIEXPORT jboolean JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_process
   (JNIEnv *, jclass, jlong, jobject, jintArray, jint, jint, jint, jint);
 
+/*
+ * Class:     org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer
+ * Method:    removeNotify
+ * Signature: (JLjava/awt/Component;)V
+ */
+JNIEXPORT void JNICALL Java_org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer_removeNotify
+  (JNIEnv *, jclass, jlong, jobject);
+
 /*
  * Class:     org_jitsi_impl_neomedia_jmfext_media_renderer_video_JAWTRenderer
  * Method:    sysctlbyname
-- 
GitLab