blob: da3e5e5f2ede3738bbdbe4a2d544a1544ca2e2ee [file] [log] [blame]
Dees_Troy51a0e822012-09-05 15:24:24 -04001/*
Dees Troy3be70a82013-10-22 14:25:12 +00002 Copyright 2012 bigbiff/Dees_Troy TeamWin
3 This file is part of TWRP/TeamWin Recovery Project.
4
5 TWRP is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 TWRP is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
17*/
Dees_Troy51a0e822012-09-05 15:24:24 -040018
19#include <linux/input.h>
20#include <pthread.h>
21#include <stdarg.h>
22#include <stdio.h>
23#include <errno.h>
24#include <stdlib.h>
25#include <string.h>
26#include <fcntl.h>
27#include <sys/reboot.h>
28#include <sys/stat.h>
29#include <sys/time.h>
30#include <sys/mman.h>
31#include <sys/types.h>
32#include <sys/ioctl.h>
33#include <sys/mount.h>
34#include <time.h>
35#include <unistd.h>
36#include <stdlib.h>
37
bigbiff bigbiff8a68c312013-02-10 14:28:30 -050038extern "C"
39{
Dees_Troy2673cec2013-04-02 20:22:16 +000040#include "../twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040041#include "../minuitwrp/minui.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040042#include <pixelflinger/pixelflinger.h>
43}
44
45#include "rapidxml.hpp"
46#include "objects.hpp"
47#include "../data.hpp"
48#include "../variables.h"
Dees_Troy5bf43922012-09-07 16:07:55 -040049#include "../partitions.hpp"
bigbiff bigbiff8a68c312013-02-10 14:28:30 -050050#include "../twrp-functions.hpp"
Ethan Yonker03a42f62014-08-08 11:03:51 -050051#include "../openrecoveryscript.hpp"
52#include "../orscmd/orscmd.h"
bigbiff bigbiff8a68c312013-02-10 14:28:30 -050053#include "blanktimer.hpp"
Ethan Yonker04536952015-01-27 08:41:28 -060054#include "../tw_atomic.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040055
Vojtech Boceke5ffcd12014-02-06 21:17:32 +010056// Enable to print render time of each frame to the log file
57//#define PRINT_RENDER_TIME 1
58
Dees_Troy51a0e822012-09-05 15:24:24 -040059const static int CURTAIN_FADE = 32;
60
61using namespace rapidxml;
62
63// Global values
64static gr_surface gCurtain = NULL;
65static int gGuiInitialized = 0;
Ethan Yonker04536952015-01-27 08:41:28 -060066static TWAtomicInt gGuiConsoleRunning;
67static TWAtomicInt gGuiConsoleTerminate;
68static TWAtomicInt gForceRender;
69const int gNoAnimation = 1;
Ethan Yonkere13fa632015-01-27 11:30:03 -060070static int gGuiInputInit = 0;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -050071blanktimer blankTimer;
Ethan Yonkerfd0439e2015-01-14 11:08:13 -060072int ors_read_fd = -1;
Dees_Troy51a0e822012-09-05 15:24:24 -040073
74// Needed by pages.cpp too
75int gGuiRunning = 0;
76
77static int gRecorder = -1;
78
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020079extern "C" void gr_write_frame_to_file(int fd);
Dees_Troy51a0e822012-09-05 15:24:24 -040080
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020081void flip(void)
Dees_Troy51a0e822012-09-05 15:24:24 -040082{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020083 if (gRecorder != -1)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -050084 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020085 timespec time;
86 clock_gettime(CLOCK_MONOTONIC, &time);
87 write(gRecorder, &time, sizeof(timespec));
88 gr_write_frame_to_file(gRecorder);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -050089 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020090 gr_flip();
Dees_Troy51a0e822012-09-05 15:24:24 -040091}
92
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020093void rapidxml::parse_error_handler(const char *what, void *where)
Dees_Troy51a0e822012-09-05 15:24:24 -040094{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020095 fprintf(stderr, "Parser error: %s\n", what);
96 fprintf(stderr, " Start of string: %s\n",(char *) where);
97 LOGERR("Error parsing XML file.\n");
98 //abort();
Dees_Troy51a0e822012-09-05 15:24:24 -040099}
100
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200101static void curtainSet()
Dees_Troy51a0e822012-09-05 15:24:24 -0400102{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200103 gr_color(0, 0, 0, 255);
104 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
Ethan Yonker751a85e2014-12-12 16:59:10 -0600105 gr_blit(gCurtain, 0, 0, gr_get_width(gCurtain), gr_get_height(gCurtain), TW_X_OFFSET, TW_Y_OFFSET);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200106 gr_flip();
Dees_Troy51a0e822012-09-05 15:24:24 -0400107}
108
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200109static void curtainRaise(gr_surface surface)
Dees_Troy51a0e822012-09-05 15:24:24 -0400110{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200111 int sy = 0;
112 int h = gr_get_height(gCurtain) - 1;
113 int w = gr_get_width(gCurtain);
114 int fy = 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400115
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200116 int msw = gr_get_width(surface);
117 int msh = gr_get_height(surface);
118 int CURTAIN_RATE = msh / 30;
Dees_Troy51a0e822012-09-05 15:24:24 -0400119
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200120 if (gNoAnimation == 0)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500121 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200122 for (; h > 0; h -= CURTAIN_RATE, sy += CURTAIN_RATE, fy += CURTAIN_RATE)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500123 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200124 gr_blit(surface, 0, 0, msw, msh, 0, 0);
125 gr_blit(gCurtain, 0, sy, w, h, 0, 0);
126 gr_flip();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500127 }
128 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200129 gr_blit(surface, 0, 0, msw, msh, 0, 0);
130 flip();
Dees_Troy51a0e822012-09-05 15:24:24 -0400131}
132
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200133void curtainClose()
Dees_Troy51a0e822012-09-05 15:24:24 -0400134{
135#if 0
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200136 int w = gr_get_width(gCurtain);
137 int h = 1;
138 int sy = gr_get_height(gCurtain) - 1;
139 int fbh = gr_fb_height();
140 int CURTAIN_RATE = fbh / 30;
Dees_Troy51a0e822012-09-05 15:24:24 -0400141
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200142 if (gNoAnimation == 0)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500143 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200144 for (; h < fbh; h += CURTAIN_RATE, sy -= CURTAIN_RATE)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500145 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200146 gr_blit(gCurtain, 0, sy, w, h, 0, 0);
147 gr_flip();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500148 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200149 gr_blit(gCurtain, 0, 0, gr_get_width(gCurtain),
150 gr_get_height(gCurtain), 0, 0);
151 gr_flip();
Dees_Troy51a0e822012-09-05 15:24:24 -0400152
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200153 if (gRecorder != -1)
154 close(gRecorder);
Dees_Troy51a0e822012-09-05 15:24:24 -0400155
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200156 int fade;
157 for (fade = 16; fade < 255; fade += CURTAIN_FADE)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500158 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200159 gr_blit(gCurtain, 0, 0, gr_get_width(gCurtain),
160 gr_get_height(gCurtain), 0, 0);
161 gr_color(0, 0, 0, fade);
162 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
163 gr_flip();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500164 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200165 gr_color(0, 0, 0, 255);
166 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
167 gr_flip();
Dees_Troy51a0e822012-09-05 15:24:24 -0400168 }
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500169#else
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200170 gr_blit(gCurtain, 0, 0, gr_get_width(gCurtain), gr_get_height(gCurtain), 0, 0);
171 gr_flip();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500172#endif
Dees_Troy51a0e822012-09-05 15:24:24 -0400173}
174
Ethan Yonkere13fa632015-01-27 11:30:03 -0600175void input_init(void)
Dees_Troy51a0e822012-09-05 15:24:24 -0400176{
Ricardo Gomezc9ecd442013-07-05 16:13:52 -0700177#ifndef TW_NO_SCREEN_TIMEOUT
thatfb759d42015-01-11 12:16:53 +0100178 {
179 string seconds;
180 DataManager::GetValue("tw_screen_timeout_secs", seconds);
181 blankTimer.setTime(atoi(seconds.c_str()));
182 blankTimer.resetTimerAndUnblank();
183 }
Ricardo Gomezc9ecd442013-07-05 16:13:52 -0700184#else
thatfb759d42015-01-11 12:16:53 +0100185 LOGINFO("Skipping screen timeout: TW_NO_SCREEN_TIMEOUT is set\n");
Ricardo Gomezc9ecd442013-07-05 16:13:52 -0700186#endif
Ethan Yonkere13fa632015-01-27 11:30:03 -0600187 gGuiInputInit = 1;
188}
Dees_Troy51a0e822012-09-05 15:24:24 -0400189
Ethan Yonkere13fa632015-01-27 11:30:03 -0600190enum touch_status_enum {
191 TS_NONE = 0,
192 TS_TOUCH_AND_HOLD = 1,
193 TS_TOUCH_REPEAT = 2,
194};
195
196enum key_status_enum {
197 KS_NONE = 0,
198 KS_KEY_PRESSED = 1,
199 KS_KEY_REPEAT = 2,
200};
201
202enum action_state_enum {
203 AS_IN_ACTION_AREA = 0,
204 AS_NO_ACTION = 1,
205};
206
207void get_input(int send_drag)
208{
209 static touch_status_enum touch_status = TS_NONE;
210 static key_status_enum key_status = KS_NONE;
211 static int x = 0, y = 0; // x and y coordinates
212 static struct timeval touchStart; // used to track time for long press / key repeat
213 static HardwareKeyboard *kb = PageManager::GetHardwareKeyboard();
214 static MouseCursor *cursor = PageManager::GetMouseCursor();
215 struct input_event ev;
216 static action_state_enum state = AS_NO_ACTION; // 1 means that we've touched in an empty area (no action) while 0 means we've touched a spot with an action
217 int ret = 0; // return value from ev_get
218
219 if (send_drag) {
220 // This allows us to only send one NotifyTouch event per render
221 // cycle to reduce overhead and perceived input latency.
222 static int prevx = 0, prevy = 0; // these track where the last drag notice was so that we don't send duplicate drag notices
223 if (touch_status && (x != prevx || y != prevy)) {
224 prevx = x;
225 prevy = y;
226 if (PageManager::NotifyTouch(TOUCH_DRAG, x, y) > 0)
227 state = AS_NO_ACTION;
228 else
229 state = AS_IN_ACTION_AREA;
230 }
231 return;
232 }
233
234 ret = ev_get(&ev);
235
236 if (ret < 0)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500237 {
Ethan Yonkere13fa632015-01-27 11:30:03 -0600238 // This path means that we did not get any new touch data, but
239 // we do not get new touch data if you press and hold on either
240 // the screen or on a keyboard key or mouse button
241 if (touch_status || key_status) {
242 // touch and key repeat section
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200243 struct timeval curTime;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200244 long mtime, seconds, useconds;
Ethan Yonkere13fa632015-01-27 11:30:03 -0600245 gettimeofday(&curTime, NULL);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200246 seconds = curTime.tv_sec - touchStart.tv_sec;
247 useconds = curTime.tv_usec - touchStart.tv_usec;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200248 mtime = ((seconds) * 1000 + useconds / 1000.0) + 0.5;
Ethan Yonkere13fa632015-01-27 11:30:03 -0600249
250 if (touch_status == TS_TOUCH_AND_HOLD && mtime > 500)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500251 {
Ethan Yonkere13fa632015-01-27 11:30:03 -0600252 touch_status = TS_TOUCH_REPEAT;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200253 gettimeofday(&touchStart, NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400254#ifdef _EVENT_LOGGING
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200255 LOGERR("TOUCH_HOLD: %d,%d\n", x, y);
Dees_Troy51a0e822012-09-05 15:24:24 -0400256#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200257 PageManager::NotifyTouch(TOUCH_HOLD, x, y);
258 blankTimer.resetTimerAndUnblank();
Dees_Troy51a0e822012-09-05 15:24:24 -0400259 }
Ethan Yonkere13fa632015-01-27 11:30:03 -0600260 else if (touch_status == TS_TOUCH_REPEAT && mtime > 100)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500261 {
262#ifdef _EVENT_LOGGING
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200263 LOGERR("TOUCH_REPEAT: %d,%d\n", x, y);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500264#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200265 gettimeofday(&touchStart, NULL);
266 PageManager::NotifyTouch(TOUCH_REPEAT, x, y);
267 blankTimer.resetTimerAndUnblank();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500268 }
Ethan Yonkere13fa632015-01-27 11:30:03 -0600269 else if (key_status == KS_KEY_PRESSED && mtime > 500)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500270 {
271#ifdef _EVENT_LOGGING
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200272 LOGERR("KEY_HOLD: %d,%d\n", x, y);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500273#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200274 gettimeofday(&touchStart, NULL);
Ethan Yonkere13fa632015-01-27 11:30:03 -0600275 key_status = KS_KEY_REPEAT;
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100276 kb->KeyRepeat();
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200277 blankTimer.resetTimerAndUnblank();
Ricardo Gomezc9ecd442013-07-05 16:13:52 -0700278
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500279 }
Ethan Yonkere13fa632015-01-27 11:30:03 -0600280 else if (key_status == KS_KEY_REPEAT && mtime > 100)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500281 {
282#ifdef _EVENT_LOGGING
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200283 LOGERR("KEY_REPEAT: %d,%d\n", x, y);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500284#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200285 gettimeofday(&touchStart, NULL);
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100286 kb->KeyRepeat();
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200287 blankTimer.resetTimerAndUnblank();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500288 }
Ethan Yonkere13fa632015-01-27 11:30:03 -0600289 } else {
290 return; // nothing is pressed so do nothing and exit
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500291 }
Ethan Yonkere13fa632015-01-27 11:30:03 -0600292 }
293 else if (ev.type == EV_ABS)
294 {
295
296 x = ev.value >> 16;
297 y = ev.value & 0xFFFF;
298
299 if (ev.code == 0)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500300 {
Ethan Yonkere13fa632015-01-27 11:30:03 -0600301 if (state == AS_IN_ACTION_AREA)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500302 {
Dees_Troy51a0e822012-09-05 15:24:24 -0400303#ifdef _EVENT_LOGGING
Ethan Yonkere13fa632015-01-27 11:30:03 -0600304 LOGERR("TOUCH_RELEASE: %d,%d\n", x, y);
Dees_Troy51a0e822012-09-05 15:24:24 -0400305#endif
Ethan Yonkere13fa632015-01-27 11:30:03 -0600306 PageManager::NotifyTouch(TOUCH_RELEASE, x, y);
307 blankTimer.resetTimerAndUnblank();
308 }
309 touch_status = TS_NONE;
310 }
311 else
312 {
313 if (!touch_status)
314 {
315 if (x != 0 && y != 0) {
316#ifdef _EVENT_LOGGING
317 LOGERR("TOUCH_START: %d,%d\n", x, y);
318#endif
319 if (PageManager::NotifyTouch(TOUCH_START, x, y) > 0)
320 state = AS_NO_ACTION;
321 else
322 state = AS_IN_ACTION_AREA;
323 touch_status = TS_TOUCH_AND_HOLD;
324 gettimeofday(&touchStart, NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400325 }
Ethan Yonkere13fa632015-01-27 11:30:03 -0600326 blankTimer.resetTimerAndUnblank();
Dees_Troy51a0e822012-09-05 15:24:24 -0400327 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200328 else
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500329 {
Ethan Yonkere13fa632015-01-27 11:30:03 -0600330 if (state == AS_IN_ACTION_AREA)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500331 {
332#ifdef _EVENT_LOGGING
Ethan Yonkere13fa632015-01-27 11:30:03 -0600333 LOGERR("TOUCH_DRAG: %d,%d\n", x, y);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500334#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200335 blankTimer.resetTimerAndUnblank();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500336 }
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +0100337 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500338 }
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500339 }
Ethan Yonkere13fa632015-01-27 11:30:03 -0600340 else if (ev.type == EV_KEY)
341 {
342 // Handle key-press here
343#ifdef _EVENT_LOGGING
344 LOGERR("TOUCH_KEY: %d\n", ev.code);
345#endif
346 // Left mouse button
347 if(ev.code == BTN_LEFT)
348 {
349 // Left mouse button is treated as a touch
350 if(ev.value == 1)
351 {
352 cursor->GetPos(x, y);
353#ifdef _EVENT_LOGGING
354 LOGERR("Mouse TOUCH_START: %d,%d\n", x, y);
355#endif
356 if (PageManager::NotifyTouch(TOUCH_START, x, y) > 0)
357 state = AS_NO_ACTION;
358 else
359 state = AS_IN_ACTION_AREA;
360 touch_status = TS_TOUCH_AND_HOLD;
361 gettimeofday(&touchStart, NULL);
362 }
363 else if(touch_status)
364 {
365 // Left mouse button was previously pressed and now is
366 // being released so send a TOUCH_RELEASE
367 if (state == AS_IN_ACTION_AREA)
368 {
369 cursor->GetPos(x, y);
370
371#ifdef _EVENT_LOGGING
372 LOGERR("Mouse TOUCH_RELEASE: %d,%d\n", x, y);
373#endif
374 PageManager::NotifyTouch(TOUCH_RELEASE, x, y);
375
376 }
377 touch_status = TS_NONE;
378 }
379 }
380 // side mouse button, often used for "back" function
381 else if(ev.code == BTN_SIDE)
382 {
383 if(ev.value == 1)
384 kb->KeyDown(KEY_BACK);
385 else
386 kb->KeyUp(KEY_BACK);
387 } else if (ev.value != 0) {
388 // This is a key press
389 if (kb->KeyDown(ev.code)) {
390 // Key repeat is enabled for this key
391 key_status = KS_KEY_PRESSED;
392 touch_status = TS_NONE;
393 gettimeofday(&touchStart, NULL);
394 blankTimer.resetTimerAndUnblank();
395 } else {
396 key_status = KS_NONE;
397 touch_status = TS_NONE;
398 blankTimer.resetTimerAndUnblank();
399 }
400 } else {
401 // This is a key release
402 kb->KeyUp(ev.code);
403 key_status = KS_NONE;
404 touch_status = TS_NONE;
405 blankTimer.resetTimerAndUnblank();
406 }
407 }
408 else if(ev.type == EV_REL)
409 {
410 // Mouse movement
411#ifdef _EVENT_LOGGING
412 LOGERR("EV_REL %d %d\n", ev.code, ev.value);
413#endif
414 if(ev.code == REL_X)
415 cursor->Move(ev.value, 0);
416 else if(ev.code == REL_Y)
417 cursor->Move(0, ev.value);
418
419 if(touch_status) {
420 cursor->GetPos(x, y);
421#ifdef _EVENT_LOGGING
422 LOGERR("Mouse TOUCH_DRAG: %d, %d\n", x, y);
423#endif
424 key_status = KS_NONE;
425 }
426 }
427 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400428}
429
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600430static void setup_ors_command()
Ethan Yonker03a42f62014-08-08 11:03:51 -0500431{
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600432 ors_read_fd = -1;
Ethan Yonker03a42f62014-08-08 11:03:51 -0500433
434 unlink(ORS_INPUT_FILE);
435 if (mkfifo(ORS_INPUT_FILE, 06660) != 0) {
436 LOGINFO("Unable to mkfifo %s\n", ORS_INPUT_FILE);
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600437 return;
Ethan Yonker03a42f62014-08-08 11:03:51 -0500438 }
439 unlink(ORS_OUTPUT_FILE);
440 if (mkfifo(ORS_OUTPUT_FILE, 06666) != 0) {
441 LOGINFO("Unable to mkfifo %s\n", ORS_OUTPUT_FILE);
442 unlink(ORS_INPUT_FILE);
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600443 return;
Ethan Yonker03a42f62014-08-08 11:03:51 -0500444 }
445
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600446 ors_read_fd = open(ORS_INPUT_FILE, O_RDONLY | O_NONBLOCK);
447 if (ors_read_fd < 0) {
Ethan Yonker03a42f62014-08-08 11:03:51 -0500448 LOGINFO("Unable to open %s\n", ORS_INPUT_FILE);
449 unlink(ORS_INPUT_FILE);
450 unlink(ORS_OUTPUT_FILE);
Ethan Yonker03a42f62014-08-08 11:03:51 -0500451 }
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600452}
Ethan Yonker03a42f62014-08-08 11:03:51 -0500453
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600454static void ors_command_read()
455{
456 FILE* orsout;
457 char command[1024], result[512];
458 int set_page_done = 0, read_ret = 0;
Ethan Yonker03a42f62014-08-08 11:03:51 -0500459
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600460 if ((read_ret = read(ors_read_fd, &command, sizeof(command))) > 0) {
461 command[1022] = '\n';
462 command[1023] = '\0';
463 LOGINFO("Command '%s' received\n", command);
464 orsout = fopen(ORS_OUTPUT_FILE, "w");
465 if (!orsout) {
466 close(ors_read_fd);
467 ors_read_fd = -1;
468 LOGINFO("Unable to fopen %s\n", ORS_OUTPUT_FILE);
469 unlink(ORS_INPUT_FILE);
470 unlink(ORS_OUTPUT_FILE);
471 return;
472 }
473 if (DataManager::GetIntValue("tw_busy") != 0) {
474 strcpy(result, "Failed, operation in progress\n");
475 fprintf(orsout, "%s", result);
476 LOGINFO("Command cannot be performed, operation in progress.\n");
477 } else {
478 if (gui_console_only() == 0) {
479 LOGINFO("Console started successfully\n");
480 gui_set_FILE(orsout);
481 if (strlen(command) > 11 && strncmp(command, "runscript", 9) == 0) {
482 char* filename = command + 11;
483 if (OpenRecoveryScript::copy_script_file(filename) == 0) {
484 LOGERR("Unable to copy script file\n");
485 } else {
Ethan Yonker03a42f62014-08-08 11:03:51 -0500486 OpenRecoveryScript::run_script_file();
487 }
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600488 } else if (strlen(command) > 5 && strncmp(command, "get", 3) == 0) {
489 char* varname = command + 4;
490 string temp;
491 DataManager::GetValue(varname, temp);
492 gui_print("%s = %s\n", varname, temp.c_str());
493 } else if (strlen(command) > 9 && strncmp(command, "decrypt", 7) == 0) {
494 char* pass = command + 8;
495 gui_print("Attempting to decrypt data partition via command line.\n");
496 if (PartitionManager.Decrypt_Device(pass) == 0) {
497 set_page_done = 1;
498 }
499 } else if (OpenRecoveryScript::Insert_ORS_Command(command)) {
500 OpenRecoveryScript::run_script_file();
Ethan Yonker03a42f62014-08-08 11:03:51 -0500501 }
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600502 gui_set_FILE(NULL);
Ethan Yonker04536952015-01-27 08:41:28 -0600503 gGuiConsoleTerminate.set_value(1);
Ethan Yonker03a42f62014-08-08 11:03:51 -0500504 }
Ethan Yonker03a42f62014-08-08 11:03:51 -0500505 }
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600506 fclose(orsout);
507 LOGINFO("Done reading ORS command from command line\n");
508 if (set_page_done) {
509 DataManager::SetValue("tw_page_done", 1);
510 } else {
511 // The select function will return ready to read and the
512 // read function will return errno 19 no such device unless
513 // we set everything up all over again.
514 close(ors_read_fd);
515 setup_ors_command();
516 }
517 } else {
518 LOGINFO("ORS command line read returned an error: %i, %i, %s\n", read_ret, errno, strerror(errno));
Ethan Yonker03a42f62014-08-08 11:03:51 -0500519 }
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600520 return;
Ethan Yonker03a42f62014-08-08 11:03:51 -0500521}
522
Dees_Troy51a0e822012-09-05 15:24:24 -0400523// This special function will return immediately the first time, but then
524// always returns 1/30th of a second (or immediately if called later) from
525// the last time it was called
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200526static void loopTimer(void)
Dees_Troy51a0e822012-09-05 15:24:24 -0400527{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200528 static timespec lastCall;
529 static int initialized = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400530
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200531 if (!initialized)
Dees_Troyc8b199c2012-09-24 11:55:07 -0400532 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200533 clock_gettime(CLOCK_MONOTONIC, &lastCall);
534 initialized = 1;
535 return;
Dees_Troyc8b199c2012-09-24 11:55:07 -0400536 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400537
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200538 do
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500539 {
Ethan Yonkere13fa632015-01-27 11:30:03 -0600540 get_input(0); // get inputs but don't send drag notices
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200541 timespec curTime;
542 clock_gettime(CLOCK_MONOTONIC, &curTime);
Dees_Troy51a0e822012-09-05 15:24:24 -0400543
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200544 timespec diff = TWFunc::timespec_diff(lastCall, curTime);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500545
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200546 // This is really 30 times per second
547 if (diff.tv_sec || diff.tv_nsec > 33333333)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500548 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200549 lastCall = curTime;
Ethan Yonkere13fa632015-01-27 11:30:03 -0600550 get_input(1); // send only drag notices if needed
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200551 return;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500552 }
553
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200554 // We need to sleep some period time microseconds
Ethan Yonkere13fa632015-01-27 11:30:03 -0600555 //unsigned int sleepTime = 33333 -(diff.tv_nsec / 1000);
556 //usleep(sleepTime); // removed so we can scan for input
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200557 } while (1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400558}
559
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600560static int runPages(const char *page_name, const int stop_on_page_done)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500561{
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600562 if (page_name)
563 gui_changePage(page_name);
564
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200565 // Raise the curtain
566 if (gCurtain != NULL)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500567 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200568 gr_surface surface;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500569
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200570 PageManager::Render();
571 gr_get_surface(&surface);
572 curtainRaise(surface);
573 gr_free_surface(surface);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500574 }
575
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200576 gGuiRunning = 1;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500577
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200578 DataManager::SetValue("tw_loaded", 1);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500579
Vojtech Boceke5ffcd12014-02-06 21:17:32 +0100580#ifdef PRINT_RENDER_TIME
581 timespec start, end;
582 int32_t render_t, flip_t;
583#endif
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600584#ifndef TW_OEM_BUILD
585 struct timeval timeout;
586 fd_set fdset;
587 int has_data = 0;
588#endif
Vojtech Boceke5ffcd12014-02-06 21:17:32 +0100589
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200590 for (;;)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500591 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200592 loopTimer();
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600593#ifndef TW_OEM_BUILD
594 if (ors_read_fd > 0) {
595 FD_ZERO(&fdset);
596 FD_SET(ors_read_fd, &fdset);
597 timeout.tv_sec = 0;
598 timeout.tv_usec = 1;
599 has_data = select(ors_read_fd+1, &fdset, NULL, NULL, &timeout);
600 if (has_data > 0) {
601 ors_command_read();
602 }
603 }
604#endif
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500605
Ethan Yonker04536952015-01-27 08:41:28 -0600606 if (gGuiConsoleRunning.get_value()) {
Ethan Yonker03a42f62014-08-08 11:03:51 -0500607 continue;
608 }
609
Ethan Yonker04536952015-01-27 08:41:28 -0600610 if (!gForceRender.get_value())
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500611 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200612 int ret;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500613
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200614 ret = PageManager::Update();
Vojtech Boceke5ffcd12014-02-06 21:17:32 +0100615
616#ifndef PRINT_RENDER_TIME
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200617 if (ret > 1)
618 PageManager::Render();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500619
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200620 if (ret > 0)
621 flip();
Vojtech Boceke5ffcd12014-02-06 21:17:32 +0100622#else
623 if (ret > 1)
624 {
625 clock_gettime(CLOCK_MONOTONIC, &start);
626 PageManager::Render();
627 clock_gettime(CLOCK_MONOTONIC, &end);
628 render_t = TWFunc::timespec_diff_ms(start, end);
629
630 flip();
631 clock_gettime(CLOCK_MONOTONIC, &start);
632 flip_t = TWFunc::timespec_diff_ms(end, start);
633
634 LOGINFO("Render(): %u ms, flip(): %u ms, total: %u ms\n", render_t, flip_t, render_t+flip_t);
635 }
636 else if(ret == 1)
637 flip();
638#endif
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500639 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200640 else
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500641 {
Ethan Yonker04536952015-01-27 08:41:28 -0600642 gForceRender.set_value(0);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200643 PageManager::Render();
644 flip();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500645 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200646
thatfb759d42015-01-11 12:16:53 +0100647 blankTimer.checkForTimeout();
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600648 if (stop_on_page_done && DataManager::GetIntValue("tw_page_done") != 0)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200649 {
650 gui_changePage("main");
Dees_Troy6ef66352013-02-21 08:26:57 -0600651 break;
652 }
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600653 if (DataManager::GetIntValue("tw_gui_done") != 0)
654 break;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500655 }
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600656 if (ors_read_fd > 0)
657 close(ors_read_fd);
658 ors_read_fd = -1;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200659 gGuiRunning = 0;
660 return 0;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500661}
662
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200663int gui_forceRender(void)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500664{
Ethan Yonker04536952015-01-27 08:41:28 -0600665 gForceRender.set_value(1);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200666 return 0;
667}
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500668
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200669int gui_changePage(std::string newPage)
670{
671 LOGINFO("Set page: '%s'\n", newPage.c_str());
672 PageManager::ChangePage(newPage);
Ethan Yonker04536952015-01-27 08:41:28 -0600673 gForceRender.set_value(1);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200674 return 0;
675}
676
677int gui_changeOverlay(std::string overlay)
678{
679 PageManager::ChangeOverlay(overlay);
Ethan Yonker04536952015-01-27 08:41:28 -0600680 gForceRender.set_value(1);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200681 return 0;
682}
683
684int gui_changePackage(std::string newPackage)
685{
686 PageManager::SelectPackage(newPackage);
Ethan Yonker04536952015-01-27 08:41:28 -0600687 gForceRender.set_value(1);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200688 return 0;
689}
690
691std::string gui_parse_text(string inText)
692{
693 // Copied from std::string GUIText::parseText(void)
694 // This function parses text for DataManager values encompassed by %value% in the XML
695 static int counter = 0;
696 std::string str = inText;
697 size_t pos = 0;
698 size_t next = 0, end = 0;
699
700 while (1)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500701 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200702 next = str.find('%', pos);
703 if (next == std::string::npos)
704 return str;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500705
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200706 end = str.find('%', next + 1);
707 if (end == std::string::npos)
708 return str;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500709
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200710 // We have a block of data
711 std::string var = str.substr(next + 1,(end - next) - 1);
712 str.erase(next,(end - next) + 1);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500713
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200714 if (next + 1 == end)
715 str.insert(next, 1, '%');
716 else
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500717 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200718 std::string value;
719 if (DataManager::GetValue(var, value) == 0)
720 str.insert(next, value);
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500721 }
722
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200723 pos = next + 1;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500724 }
725}
726
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200727extern "C" int gui_init(void)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500728{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200729 gr_init();
Dees Troy3454ade2015-01-20 19:21:04 +0000730 std::string curtain_path = TWRES "images/curtain.jpg";
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500731
Dees Troy3454ade2015-01-20 19:21:04 +0000732 if (res_create_surface(curtain_path.c_str(), &gCurtain))
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500733 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200734 printf
Dees Troy3454ade2015-01-20 19:21:04 +0000735 ("Unable to locate '%s'\nDid you set a DEVICE_RESOLUTION in your config files?\n", curtain_path.c_str());
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200736 return -1;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500737 }
738
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200739 curtainSet();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500740
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200741 ev_init();
742 return 0;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500743}
744
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200745extern "C" int gui_loadResources(void)
Dees_Troy51a0e822012-09-05 15:24:24 -0400746{
Ethan Yonker83e82572014-04-04 10:59:28 -0500747#ifndef TW_OEM_BUILD
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200748 int check = 0;
749 DataManager::GetValue(TW_IS_ENCRYPTED, check);
Dees Troy3454ade2015-01-20 19:21:04 +0000750
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200751 if (check)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500752 {
Dees Troy3454ade2015-01-20 19:21:04 +0000753 if (PageManager::LoadPackage("TWRP", TWRES "ui.xml", "decrypt"))
Dees_Troy5bf43922012-09-07 16:07:55 -0400754 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200755 LOGERR("Failed to load base packages.\n");
756 goto error;
Dees_Troy51a0e822012-09-05 15:24:24 -0400757 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200758 else
759 check = 1;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500760 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400761
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200762 if (check == 0 && PageManager::LoadPackage("TWRP", "/script/ui.xml", "main"))
763 {
764 std::string theme_path;
765
766 theme_path = DataManager::GetSettingsStoragePath();
767 if (!PartitionManager.Mount_Settings_Storage(false))
Dees_Troy51a0e822012-09-05 15:24:24 -0400768 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200769 int retry_count = 5;
770 while (retry_count > 0 && !PartitionManager.Mount_Settings_Storage(false))
Dees_Troy51a0e822012-09-05 15:24:24 -0400771 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200772 usleep(500000);
773 retry_count--;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500774 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200775
776 if (!PartitionManager.Mount_Settings_Storage(false))
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500777 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200778 LOGERR("Unable to mount %s during GUI startup.\n",
779 theme_path.c_str());
780 check = 1;
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500781 }
782 }
783
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200784 theme_path += "/TWRP/theme/ui.zip";
785 if (check || PageManager::LoadPackage("TWRP", theme_path, "main"))
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500786 {
Ethan Yonker83e82572014-04-04 10:59:28 -0500787#endif // ifndef TW_OEM_BUILD
Dees Troy3454ade2015-01-20 19:21:04 +0000788 if (PageManager::LoadPackage("TWRP", TWRES "ui.xml", "main"))
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500789 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200790 LOGERR("Failed to load base packages.\n");
791 goto error;
Dees_Troy51a0e822012-09-05 15:24:24 -0400792 }
Ethan Yonker83e82572014-04-04 10:59:28 -0500793#ifndef TW_OEM_BUILD
Dees_Troy51a0e822012-09-05 15:24:24 -0400794 }
795 }
Ethan Yonker83e82572014-04-04 10:59:28 -0500796#endif // ifndef TW_OEM_BUILD
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200797 // Set the default package
798 PageManager::SelectPackage("TWRP");
Dees_Troy51a0e822012-09-05 15:24:24 -0400799
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200800 gGuiInitialized = 1;
801 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400802
803error:
Ethan Yonker83e82572014-04-04 10:59:28 -0500804 LOGERR("An internal error has occurred: unable to load theme.\n");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200805 gGuiInitialized = 0;
806 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400807}
808
Ethan Yonkercf50da52015-01-12 21:59:07 -0600809extern "C" int gui_loadCustomResources(void)
810{
811#ifndef TW_OEM_BUILD
812 if (!PartitionManager.Mount_Settings_Storage(false)) {
813 LOGERR("Unable to mount settings storage during GUI startup.\n");
814 return -1;
815 }
816
817 std::string theme_path = DataManager::GetSettingsStoragePath();
818 theme_path += "/TWRP/theme/ui.zip";
819 // Check for a custom theme
820 if (TWFunc::Path_Exists(theme_path)) {
821 // There is a custom theme, try to load it
822 if (PageManager::ReloadPackage("TWRP", theme_path)) {
823 // Custom theme failed to load, try to load stock theme
Dees Troy3454ade2015-01-20 19:21:04 +0000824 if (PageManager::ReloadPackage("TWRP", TWRES "ui.xml")) {
Ethan Yonkercf50da52015-01-12 21:59:07 -0600825 LOGERR("Failed to load base packages.\n");
826 goto error;
827 }
828 }
829 }
830 // Set the default package
831 PageManager::SelectPackage("TWRP");
832#endif
833 return 0;
834
835error:
836 LOGERR("An internal error has occurred: unable to load theme.\n");
837 gGuiInitialized = 0;
838 return -1;
839}
840
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200841extern "C" int gui_start(void)
Dees_Troy51a0e822012-09-05 15:24:24 -0400842{
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600843 return gui_startPage(NULL, 1, 0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400844}
845
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600846extern "C" int gui_startPage(const char *page_name, const int allow_commands, int stop_on_page_done)
Dees_Troy4bc09ae2013-01-18 17:00:54 +0000847{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200848 if (!gGuiInitialized)
849 return -1;
Dees_Troy4bc09ae2013-01-18 17:00:54 +0000850
Ethan Yonker04536952015-01-27 08:41:28 -0600851 gGuiConsoleTerminate.set_value(1);
Dees_Troy4bc09ae2013-01-18 17:00:54 +0000852
Ethan Yonker04536952015-01-27 08:41:28 -0600853 while (gGuiConsoleRunning.get_value())
Ethan Yonkere13fa632015-01-27 11:30:03 -0600854 usleep(10000);
Dees_Troy4bc09ae2013-01-18 17:00:54 +0000855
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200856 // Set the default package
857 PageManager::SelectPackage("TWRP");
858
Ethan Yonkere13fa632015-01-27 11:30:03 -0600859 if (!gGuiInputInit)
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500860 {
Ethan Yonkere13fa632015-01-27 11:30:03 -0600861 input_init();
Dees_Troy4bc09ae2013-01-18 17:00:54 +0000862 }
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600863#ifndef TW_OEM_BUILD
864 if (allow_commands)
865 {
866 if (ors_read_fd < 0)
867 setup_ors_command();
868 } else {
869 if (ors_read_fd >= 0) {
870 close(ors_read_fd);
871 ors_read_fd = -1;
872 }
873 }
874#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200875 DataManager::SetValue("tw_page_done", 0);
Ethan Yonkerfd0439e2015-01-14 11:08:13 -0600876 return runPages(page_name, stop_on_page_done);
Dees_Troy4bc09ae2013-01-18 17:00:54 +0000877}
878
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200879static void * console_thread(void *cookie)
Dees_Troy51a0e822012-09-05 15:24:24 -0400880{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200881 PageManager::SwitchToConsole();
Dees_Troy51a0e822012-09-05 15:24:24 -0400882
Ethan Yonker04536952015-01-27 08:41:28 -0600883 while (!gGuiConsoleTerminate.get_value())
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500884 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200885 loopTimer();
Dees_Troy51a0e822012-09-05 15:24:24 -0400886
Ethan Yonker04536952015-01-27 08:41:28 -0600887 if (!gForceRender.get_value())
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500888 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200889 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400890
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200891 ret = PageManager::Update();
892 if (ret > 1)
893 PageManager::Render();
Dees_Troy51a0e822012-09-05 15:24:24 -0400894
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200895 if (ret > 0)
896 flip();
Dees_Troy51a0e822012-09-05 15:24:24 -0400897
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200898 if (ret < 0)
899 LOGERR("An update request has failed.\n");
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500900 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200901 else
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500902 {
Ethan Yonker04536952015-01-27 08:41:28 -0600903 gForceRender.set_value(0);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200904 PageManager::Render();
905 flip();
bigbiff bigbiff8a68c312013-02-10 14:28:30 -0500906 }
907 }
Ethan Yonker04536952015-01-27 08:41:28 -0600908 gGuiConsoleRunning.set_value(0);
909 gForceRender.set_value(1); // this will kickstart the GUI to render again
Ethan Yonker03a42f62014-08-08 11:03:51 -0500910 PageManager::EndConsole();
911 LOGINFO("Console stopping\n");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200912 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400913}
914
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200915extern "C" int gui_console_only(void)
Dees_Troy51a0e822012-09-05 15:24:24 -0400916{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200917 if (!gGuiInitialized)
918 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400919
Ethan Yonker04536952015-01-27 08:41:28 -0600920 gGuiConsoleTerminate.set_value(0);
Ethan Yonkerffbd6ff2014-10-22 10:40:40 -0500921
Ethan Yonker04536952015-01-27 08:41:28 -0600922 if (gGuiConsoleRunning.get_value())
Ethan Yonkerffbd6ff2014-10-22 10:40:40 -0500923 return 0;
924
Ethan Yonker04536952015-01-27 08:41:28 -0600925 gGuiConsoleRunning.set_value(1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400926
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200927 // Start by spinning off an input handler.
928 pthread_t t;
929 pthread_create(&t, NULL, console_thread, NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400930
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200931 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400932}