<commit_before>/*
 * THE NEW CHRONOTEXT TOOLKIT: https://github.com/arielm/new-chronotext-toolkit
 * COPYRIGHT (C) 2012-2014, <NAME> ALL RIGHTS RESERVED.
 *
 * THE FOLLOWING SOURCE-CODE IS DISTRIBUTED UNDER THE MODIFIED BSD LICENSE:
 * https://github.com/arielm/new-chronotext-toolkit/blob/master/LICENSE.md
 */

package org.chronotext.gl;

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;

import java.util.Vector;

import org.chronotext.gl.Touch;
import org.chronotext.Utils;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;

public class GLView extends GLSurfaceView
{
  protected GLRenderer mRenderer;
  protected boolean mDestroyOnDetach;

  protected boolean resumed;
  protected boolean attached;
  protected boolean finishing;
  protected boolean destroyed;

  public GLView(Context context)
  {
    super(context);

    // setEGLContextClientVersion(2);
    // setEGLConfigChooser(8, 8, 8, 8, 0, 0);
    // getHolder().setFormat(PixelFormat.RGBA_8888);

    setEGLContextFactory(new CustomContextFactory(1)); // FIXME: EGL-CONTEXT-CLIENT-VERSION SHOULD NOT BE HARD-CODED
    setPreserveEGLContextOnPause(true);

    /*
     * A GLView IS DESIGNED TO BE ATTACHED UPON ACTIVITY CREATION AND NOT BE
     * DETACHED ANYMORE (IT IS OF-COURSE POSSIBLE TO HIDE/SHOW A GLView ON DEMAND)
     */
    mDestroyOnDetach = true;
  }

  @Override
  public void setRenderer(Renderer renderer)
  {
    if (mRenderer == null)
    {
      super.setRenderer(renderer); // WILL START THE RENDERER'S THREAD
      mRenderer = (GLRenderer) renderer;

      queueEvent(new Runnable()
      {
        public void run()
        {
          mRenderer.performLaunch();
        }
      });
    }
  }

  /*
   * SETTING THIS PARAMETER TO FALSE ALLOWS TO DETACH/ATTACH A GLView ON DEMAND, BUT
   * THE FOLLOWING MUST BE TAKEN IN COUNT:
   *
   * 1) ATTACHING/DETACHING AFTER ACTIVITY CREATION IS CAUSING A VISUAL GLITCH
   *
   * 2) THE RENDERER'S THREAD EXITS UPON VIEW-DETACHMENT, THEREFORE IT IS NOT POSSIBLE
   *    TO RELY ON THE FACT THAT THE THREAD WILL LIVE UP TO ACTIVITY DESTRUCTION
   */
  public void setDestroyOnDetach(boolean destroyOnDetach)
  {
    mDestroyOnDetach = destroyOnDetach;
  }

  @Override
  public void surfaceCreated(SurfaceHolder holder)
  {
    Utils.LOGD("GLView.surfaceCreated"); 
    super.surfaceCreated(holder);
  }

  @Override
  public void surfaceDestroyed(SurfaceHolder holder)
  {
    Utils.LOGD("GLView.surfaceDestroyed"); 
    super.surfaceDestroyed(holder);
  }

  @Override
  public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
  {
    Utils.LOGD("GLView.surfaceChanged: " + width + "x" + height);
    super.surfaceChanged(holder, format, width, height);
  }

  @Override
  public void onWindowFocusChanged(final boolean hasFocus)
  {
    Utils.LOGD("GLView.onWindowFocusChanged: " + hasFocus);
    super.onWindowFocusChanged(hasFocus);
  }

  @Override
  protected void onAttachedToWindow()
  {
    Utils.LOGD("GLView.onAttachedToWindow");

    if (destroyed)
    {
      Utils.LOGE("GLView IS INVALID");
    }
    else
    {
      super.onAttachedToWindow(); // WILL START A NEW RENDERER'S THREAD IF NECESSARY (I.E. WHEN THE GLView IS RE-ATTACHED)
      attached = true;

      queueEvent(new Runnable()
      {
        public void run()
        {
          mRenderer.onAttachedToWindow();
        }
      });
    }
  }

  @Override
  protected void onDetachedFromWindow()
  {
    Utils.LOGD("GLView.onDetachedFromWindow");

    if (attached)
    {
      attached = false; // THE ONLY WAY TO COMMUNICATE WITH THE RENDERER'S THREAD BEFORE IT EXITS
      super.onDetachedFromWindow(); // WILL EXIT THE RENDERER'S THREAD (EVENTS QUEUED RIGHT BEOFRE-OR-AFTER THIS WILL NEVER BE DELIVERED)
    }
  }

  /*
   * RECEIVED ON THE MAIN-THREAD
   */
  @Override
  public void onResume()
  {
    Utils.LOGD("GLView.onResume");

    if (attached && !resumed)
    {
      resumed = true;
      super.onResume();

      queueEvent(new Runnable()
      {
        public void run()
        {
          mRenderer.onResume();
        }
      });
    }
  }

  /*
   * RECEIVED ON THE MAIN-THREAD
   */
  public void onPause()
  {
    Utils.LOGD("GLView.onPause");

    if (attached && resumed)
    {
      resumed = false;
      onPause();

      queueEvent(new Runnable()
      {
        public void run()
        {
          mRenderer.onPause();
        }
      });
    }
  }

  public void onDestroy()
  {
    Utils.LOGD("GLView.onDestroy");
    finishing = true; // COMMUNICATING WITH THE RENDERER'S THREAD BEFORE IT EXITS
  }

  @Override
  public void onVisibilityChanged(View changedView, final int visibility)
  {
    if (attached && (changedView == this))
    {
      queueEvent(new Runnable()
      {
        public void run()
        {
          mRenderer.onVisibilityChanged(visibility);
        }
      });
    }
  }

  @Override
  public boolean onTouchEvent(MotionEvent event)<commit_msg>ANDROID LIFECYCLE REWORK: “PROBLEM 2” SOLVED. IT WAS ALSO OCCURRING ON NEXUS-7 (A REGRESSION INTRODUCED BY THE “OVER COMPLEXIFICATION” WHICH TOOK PLACE EARLIER…) NOTE: IT SEEMS THAT isFinishing() WAS NOT CAUSING ANY PROBLEM. WE COULD THEREFORE BRING-IT BACK AND (RE)CANCEL THE USE OF Activity.onDestroy (WAIT AND SEE…) REGARDING THE “DEFORMATION PROBLEM” (XOOM 1 ONLY): IT LOOKS LIKE IT COULD BE SOLVED BY RE-INTRODUCING “STUFF” WHICH WAS REMOVED TODAY (E.G. SurfaceHolder.setFixedSize(), ETC.)<commit_after>/*
 * THE NEW CHRONOTEXT TOOLKIT: https://github.com/arielm/new-chronotext-toolkit
 * COPYRIGHT (C) 2012-2014, <NAME> ALL RIGHTS RESERVED.
 *
 * THE FOLLOWING SOURCE-CODE IS DISTRIBUTED UNDER THE MODIFIED BSD LICENSE:
 * https://github.com/arielm/new-chronotext-toolkit/blob/master/LICENSE.md
 */

package org.chronotext.gl;

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;

import java.util.Vector;

import org.chronotext.gl.Touch;
import org.chronotext.Utils;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;

public class GLView extends GLSurfaceView
{
  protected GLRenderer mRenderer;
  protected boolean mDestroyOnDetach;

  protected boolean resumed;
  protected boolean attached;
  protected boolean finishing;
  protected boolean destroyed;

  public GLView(Context context)
  {
    super(context);

    // setEGLContextClientVersion(2);
    // setEGLConfigChooser(8, 8, 8, 8, 0, 0);
    // getHolder().setFormat(PixelFormat.RGBA_8888);

    setEGLContextFactory(new CustomContextFactory(1)); // FIXME: EGL-CONTEXT-CLIENT-VERSION SHOULD NOT BE HARD-CODED
    setPreserveEGLContextOnPause(true);

    /*
     * A GLView IS DESIGNED TO BE ATTACHED UPON ACTIVITY CREATION AND NOT BE
     * DETACHED ANYMORE (IT IS OF-COURSE POSSIBLE TO HIDE/SHOW A GLView ON DEMAND)
     */
    mDestroyOnDetach = true;
  }

  @Override
  public void setRenderer(Renderer renderer)
  {
    if (mRenderer == null)
    {
      super.setRenderer(renderer); // WILL START THE RENDERER'S THREAD
      mRenderer = (GLRenderer) renderer;

      queueEvent(new Runnable()
      {
        public void run()
        {
          mRenderer.performLaunch();
        }
      });
    }
  }

  /*
   * SETTING THIS PARAMETER TO FALSE ALLOWS TO DETACH/ATTACH A GLView ON DEMAND, BUT
   * THE FOLLOWING MUST BE TAKEN IN COUNT:
   *
   * 1) ATTACHING/DETACHING AFTER ACTIVITY CREATION IS CAUSING A VISUAL GLITCH
   *
   * 2) THE RENDERER'S THREAD EXITS UPON VIEW-DETACHMENT, THEREFORE IT IS NOT POSSIBLE
   *    TO RELY ON THE FACT THAT THE THREAD WILL LIVE UP TO ACTIVITY DESTRUCTION
   */
  public void setDestroyOnDetach(boolean destroyOnDetach)
  {
    mDestroyOnDetach = destroyOnDetach;
  }

  @Override
  public void surfaceCreated(SurfaceHolder holder)
  {
    Utils.LOGD("GLView.surfaceCreated"); 
    super.surfaceCreated(holder);
  }

  @Override
  public void surfaceDestroyed(SurfaceHolder holder)
  {
    Utils.LOGD("GLView.surfaceDestroyed"); 
    super.surfaceDestroyed(holder);
  }

  @Override
  public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
  {
    Utils.LOGD("GLView.surfaceChanged: " + width + "x" + height);
    super.surfaceChanged(holder, format, width, height);
  }

  @Override
  public void onWindowFocusChanged(final boolean hasFocus)
  {
    Utils.LOGD("GLView.onWindowFocusChanged: " + hasFocus);
    super.onWindowFocusChanged(hasFocus);
  }

  @Override
  protected void onAttachedToWindow()
  {
    Utils.LOGD("GLView.onAttachedToWindow");

    if (destroyed)
    {
      Utils.LOGE("GLView IS INVALID");
    }
    else
    {
      super.onAttachedToWindow(); // WILL START A NEW RENDERER'S THREAD IF NECESSARY (I.E. WHEN THE GLView IS RE-ATTACHED)
      attached = true;

      queueEvent(new Runnable()
      {
        public void run()
        {
          mRenderer.onAttachedToWindow();
        }
      });
    }
  }

  @Override
  protected void onDetachedFromWindow()
  {
    Utils.LOGD("GLView.onDetachedFromWindow");

    if (attached)
    {
      attached = false; // THE ONLY WAY TO COMMUNICATE WITH THE RENDERER'S THREAD BEFORE IT EXITS
      super.onDetachedFromWindow(); // WILL EXIT THE RENDERER'S THREAD (EVENTS QUEUED RIGHT BEOFRE-OR-AFTER THIS WILL NEVER BE DELIVERED)
    }
  }

  /*
   * RECEIVED ON THE MAIN-THREAD
   */
  @Override
  public void onResume()
  {
    Utils.LOGD("GLView.onResume");

    if (destroyed)
    {
      Utils.LOGE("GLView IS INVALID");
    }
    else if (!resumed) // SIMPLE PROTECTION AGAINST SPURIOUS onResume() CALLS
    {
      resumed = true;
      super.onResume();

      queueEvent(new Runnable()
      {
        public void run()
        {
          mRenderer.onResume();
        }
      });
    }
  }

  /*
   * RECEIVED ON THE MAIN-THREAD
   */
  public void onPause()
  {
    Utils.LOGD("GLView.onPause");

    if (destroyed)
    {
      Utils.LOGE("GLView IS INVALID");
    }
    else if (resumed) // SIMPLE PROTECTION AGAINST SPURIOUS onPause() CALLS
    {
      resumed = false;
      onPause();

      queueEvent(new Runnable()
      {
        public void run()
        {
          mRenderer.onPause();
        }
      });
    }
  }

  public void onDestroy()
  {
    Utils.LOGD("GLView.onDestroy");
    finishing = true;
  }

  @Override
  public void onVisibilityChanged(View changedView, final int visibility)
  {
    if (attached && (changedView == this))
    {
      queueEvent(new Runnable()
      {
        public void run()
        {
          mRenderer.onVisibilityChanged(visibility);
        }
      });
    }
  }

  @Override
  public boolean onTouchEvent(MotionEvent event)
{'fraction_non_alphanumeric': 0.09936708860759494, 'fraction_numerical': 0.00461121157323689, 'mean_word_length': 2.8783309957924264, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5887859', 'n_tokens_mistral': 3883, 'n_tokens_neox': 3642, 'n_words': 875}