Example #1
0
func (m *mainLoop) loop(init chan<- struct{}) {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	looper := C.ALooper_prepare(C.ALOOPER_PREPARE_ALLOW_NON_CALLBACKS)
	if looper == nil {
		panic("ALooper_prepare returned nil")
	}
	m.looper = looper
	init <- struct{}{}
	for {
		select {
		case <-m.quit:
			if m.renderState != nil && m.renderState.ctx != egl.Context(unsafe.Pointer(nil)) {
				if !egl.MakeCurrent(m.renderState.disp, egl.Surface(unsafe.Pointer(nil)), egl.Surface(unsafe.Pointer(nil)), egl.Context(unsafe.Pointer(nil))) {
					panic("Error: eglMakeCurrent() failed\n")
				}
			}
			m.ack <- struct{}{}
			break
		case <-m.resume:
			m.running = true
			m.ack <- struct{}{}
		case <-m.pause:
			m.running = false
			m.width, m.height = 0, 0
			m.ack <- struct{}{}
		case m.focused = <-m.focus:
			m.width, m.height = 0, 0
			m.ack <- struct{}{}
		case m.renderState = <-m.render:
			m.ack <- struct{}{}
		case inputQ := <-m.input:
			if inputQ != nil {
				C.AInputQueue_attachLooper(inputQ, m.looper, LOOPER_ID_INPUT, nil, nil)
			} else {
				C.AInputQueue_detachLooper(m.inputQ)
			}
			m.inputQ = inputQ
			m.ack <- struct{}{}
		default:
			m.frame()
		}
	}
}
Example #2
0
// The loop handles native input events.
func androidEventLoopFunc(event chan interface{}, looperCh chan *C.ALooper) loop.LoopFunc {
	return func(l loop.Loop) error {
		var inputQueue *C.AInputQueue
		runtime.LockOSThread()
		defer runtime.UnlockOSThread()

		looper := C.ALooper_prepare(C.ALOOPER_PREPARE_ALLOW_NON_CALLBACKS)
		if looper == nil {
			Fatalf("ALooper_prepare returned nil")
		}

		looperCh <- looper

		for {
			select {
			case untypedEvent := <-event:
				switch event := untypedEvent.(type) {
				case inputQueueCreatedEvent:
					inputQueue = (*C.AInputQueue)(event.inputQueue)
					C.AInputQueue_attachLooper(inputQueue, looper, LOOPER_ID_INPUT, nil, nil)
				case inputQueueDestroyedEvent:
					inputQueue = (*C.AInputQueue)(event.inputQueue)
					C.AInputQueue_detachLooper(inputQueue)
				}
			default:
				if inputQueue != nil {
					ident := C.ALooper_pollAll(-1, nil, nil, nil)
					switch ident {
					case LOOPER_ID_INPUT:
						processInput(inputQueue)
					case C.ALOOPER_POLL_ERROR:
						Fatalf("ALooper_pollAll returned ALOOPER_POLL_ERROR\n")
					}
				}
			}
		}
	}
}
Example #3
0
func runInputQueue(vm, jniEnv, ctx uintptr) error {
	env := (*C.JNIEnv)(unsafe.Pointer(jniEnv)) // not a Go heap pointer

	// Android loopers select on OS file descriptors, not Go channels, so we
	// translate the inputQueue channel to an ALooper_wake call.
	l := C.ALooper_prepare(C.ALOOPER_PREPARE_ALLOW_NON_CALLBACKS)
	pending := make(chan *C.AInputQueue, 1)
	go func() {
		for q := range inputQueue {
			pending <- q
			C.ALooper_wake(l)
		}
	}()

	var q *C.AInputQueue
	for {
		if C.ALooper_pollAll(-1, nil, nil, nil) == C.ALOOPER_POLL_WAKE {
			select {
			default:
			case p := <-pending:
				if q != nil {
					processEvents(env, q)
					C.AInputQueue_detachLooper(q)
				}
				q = p
				if q != nil {
					C.AInputQueue_attachLooper(q, l, 0, nil, nil)
				}
				inputQueueDone <- struct{}{}
			}
		}
		if q != nil {
			processEvents(env, q)
		}
	}
}