30
30
31
31
Runtime *runtime = nullptr ;
32
32
33
+ // Pipe file descriptors: g_backPipe[0] is read-end, g_backPipe[1] is write-end
34
+ static int g_backPipe[2 ] = {-1 , -1 };
35
+
33
36
// the sensorTypes corresponding to _sensors[] positions
34
37
constexpr int SENSOR_TYPES[MAX_SENSORS] = {
35
38
ASENSOR_TYPE_ACCELEROMETER,
@@ -106,6 +109,48 @@ void handleCommand(android_app *app, int32_t cmd) {
106
109
}
107
110
}
108
111
112
+ static void pushBackEvent () {
113
+ auto *maEvent = new MAEvent ();
114
+ maEvent->nativeKey = AKEYCODE_BACK;
115
+ maEvent->type = EVENT_TYPE_KEY_PRESSED;
116
+ runtime->pushEvent (maEvent);
117
+ }
118
+
119
+ //
120
+ // Callback registered with ALooper that is triggered when the pipe receives data.
121
+ // This is what wakes the blocked ALooper_pollOnce() and lets us run pushBackEvent().
122
+ //
123
+ static int pipeCallback (int fd, int events, void *data) {
124
+ // clear the byte that woke the pipe, then return 1 to stay registered
125
+ logEntered ();
126
+ char buf[1 ];
127
+ read (fd, buf, 1 );
128
+ pushBackEvent ();
129
+ return 1 ;
130
+ }
131
+
132
+ //
133
+ // Set up the pipe and register its read-end (g_backPipe[0]) with the ALooper.
134
+ // This allows us to wake the looper from Java code by writing to the pipe.
135
+ //
136
+ static void setupBackWakePipe (ALooper *looper) {
137
+ if (pipe (g_backPipe) == 0 ) {
138
+ // Make read-end non-blocking to avoid stalling the loop
139
+ fcntl (g_backPipe[0 ], F_SETFL, O_NONBLOCK);
140
+
141
+ // Register the pipe with the looper so it wakes up when there's input
142
+ ALooper_addFd (looper,
143
+ g_backPipe[0 ], // fd to watch
144
+ 0 , // arbitrary/unused identifier
145
+ ALOOPER_EVENT_INPUT, // watch for input readiness
146
+ pipeCallback, // callback to run on wake
147
+ nullptr ); // no additional data
148
+ trace (" Back pipe registered with looper" );
149
+ } else {
150
+ trace (" Failed to create back pipe" );
151
+ }
152
+ }
153
+
109
154
// see http://stackoverflow.com/questions/15913080
110
155
static void process_input (android_app *app, android_poll_source *source) {
111
156
AInputEvent* event = nullptr ;
@@ -114,12 +159,8 @@ static void process_input(android_app *app, android_poll_source *source) {
114
159
AKeyEvent_getKeyCode (event) == AKEYCODE_BACK) {
115
160
// prevent AInputQueue_preDispatchEvent from attempting to close
116
161
// the keypad here to avoid a crash in android 4.2 + 4.3.
117
- if (AKeyEvent_getAction (event) == AKEY_EVENT_ACTION_DOWN &&
118
- runtime->isActive ()) {
119
- auto *maEvent = new MAEvent ();
120
- maEvent->nativeKey = AKEYCODE_BACK;
121
- maEvent->type = EVENT_TYPE_KEY_PRESSED;
122
- runtime->pushEvent (maEvent);
162
+ if (AKeyEvent_getAction (event) == AKEY_EVENT_ACTION_DOWN && runtime->isActive ()) {
163
+ pushBackEvent ();
123
164
}
124
165
AInputQueue_finishEvent (app->inputQueue , event, true );
125
166
} else if (!AInputQueue_preDispatchEvent (app->inputQueue , event)) {
@@ -128,6 +169,18 @@ static void process_input(android_app *app, android_poll_source *source) {
128
169
}
129
170
}
130
171
172
+ extern " C" JNIEXPORT void JNICALL Java_net_sourceforge_smallbasic_MainActivity_onBack
173
+ (JNIEnv *env, jclass clazz) {
174
+ if (runtime != nullptr ) {
175
+ logEntered ();
176
+ if (g_backPipe[1 ] >= 0 ) {
177
+ // write a placeholder byte to trigger the read and wake ALooper_pollOnce
178
+ char buf = ' x' ;
179
+ write (g_backPipe[1 ], &buf, 1 );
180
+ }
181
+ }
182
+ }
183
+
131
184
// callbacks from MainActivity.java
132
185
extern " C" JNIEXPORT void JNICALL Java_net_sourceforge_smallbasic_MainActivity_onActivityPaused
133
186
(JNIEnv *env, jclass jclazz, jboolean paused) {
@@ -234,6 +287,7 @@ Runtime::Runtime(android_app *app) :
234
287
_looper = ALooper_forThread ();
235
288
_sensorManager = ASensorManager_getInstance ();
236
289
memset (&_sensors, 0 , sizeof (_sensors));
290
+ setupBackWakePipe (_looper);
237
291
}
238
292
239
293
Runtime::~Runtime () {
@@ -1075,4 +1129,3 @@ void osd_beep(void) {
1075
1129
osd_sound (1000 , 30 , 100 , 0 );
1076
1130
osd_sound (500 , 30 , 100 , 0 );
1077
1131
}
1078
-
0 commit comments