diff --git a/.gitignore b/.gitignore index 6bc851d..bdd1203 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ fb.pnm fb.raw screen.* output +kobo/ tags tmp *.o diff --git a/docker/Dockerfile.kobo b/docker/Dockerfile.kobo index d99fef3..a728460 100644 --- a/docker/Dockerfile.kobo +++ b/docker/Dockerfile.kobo @@ -1,6 +1,6 @@ -FROM ghcr.io/toltec-dev/python:v1.1 +FROM ghcr.io/toltec-dev/python:v4.0 -RUN pip3 install okp +RUN pip3 install --break-system-packages okp WORKDIR /opt/ RUN apt update diff --git a/scripts/build/build_kobo_root.sh b/scripts/build/build_kobo_root.sh index 151d667..72c9b91 100644 --- a/scripts/build/build_kobo_root.sh +++ b/scripts/build/build_kobo_root.sh @@ -37,6 +37,10 @@ tar_files() { make_remux_sh() { cat > ${PLUGIN_DIR}/bin/remux.sh << REMUX_SH #!/bin/sh +while [ \$(pgrep -f "sh /opt/bin/remux.sh" | wc -l) -gt 2 ]; do + kill \$(pgrep -f "sh /opt/bin/remux.sh" | head -n1) +done +killall remux while true; do sleep 1; /opt/bin/apps/remux; diff --git a/scripts/build/docker_build.sh b/scripts/build/docker_build.sh index 7775699..99537ea 100644 --- a/scripts/build/docker_build.sh +++ b/scripts/build/docker_build.sh @@ -2,10 +2,11 @@ OUTDIR=artifacts PACKAGE="${1}" TARGET=${TARGET:-rm} FBINK=${FBINK} +CROSS_TC=${CROSS_TC:-arm-linux-gnueabihf} mkdir ${OUTDIR} docker run -i --rm -v "${PWD}/${OUTDIR}:/mnt/artifacts" rmkit:${TARGET} /bin/bash << COMMANDS mkdir -p src/build -FBINK=${FBINK} TARGET=${TARGET} make ${PACKAGE} +CROSS_TC=${CROSS_TC} FBINK=${FBINK} TARGET=${TARGET} make ${PACKAGE} mkdir -p /mnt/artifacts/${TARGET}/ cp -r src/build/* /mnt/artifacts/${TARGET}/ chown -R $(id -u):$(id -u) /mnt/artifacts diff --git a/src/remux/launcher.cpy b/src/remux/launcher.cpy index f6c52ee..797c55b 100644 --- a/src/remux/launcher.cpy +++ b/src/remux/launcher.cpy @@ -31,6 +31,8 @@ #define DYNAMIC_BPP #define HAS_ROTATION #define PORTRAIT_ONLY +#define DRAW_APP_BEHIND_MODAL +#define GRAB_INPUT #define USE_GRAYSCALE_32BIT #endif @@ -178,7 +180,7 @@ class AppBackground: public ui::Widget: fb->set_rotation(vfb->rotation) #endif - fb->perform_redraw(true) + fb->perform_redraw(true, true) fb->dirty = 1 class AppDialog: public ui::Pager: @@ -347,8 +349,7 @@ class App: public IApp: ui::set_timeout([=]() { ui::MainLoop::in.unmonitor(ui::MainLoop::in.wacom.fd) }, 10) - if USE_KOREADER_WORKAROUND and CURRENT_APP != "KOReader": - ui::MainLoop::in.ungrab() + ui::MainLoop::in.ungrab() ; app_bg = new AppBackground(0, 0, w, h) diff --git a/src/rmkit/fb/fb.cpy b/src/rmkit/fb/fb.cpy index 2599ed5..2b6103b 100644 --- a/src/rmkit/fb/fb.cpy +++ b/src/rmkit/fb/fb.cpy @@ -135,7 +135,7 @@ namespace framebuffer: // function: redraw_screen // if the framebuffer is dirty, redraws the dirty area // of the framebuffer. - int redraw_screen(bool full_screen=false): + int redraw_screen(bool full_screen=false, bool flash=false): if dirty == 0: return 0 @@ -145,7 +145,10 @@ namespace framebuffer: if dirty_area.y1 == 0 || dirty_area.x1 == 0: return 0 - return self.perform_redraw(full_screen) + return self.perform_redraw(full_screen, flash) + + virtual int perform_redraw(bool, bool): + return 0 virtual int perform_redraw(bool): return 0 @@ -704,7 +707,7 @@ namespace framebuffer: return vinfo.xres, vinfo.yres - int perform_redraw(bool full_screen=false): + int perform_redraw(bool full_screen=false, bool flash=false): um := 0 mxcfb_update_data update_data mxcfb_rect update_rect @@ -781,7 +784,7 @@ namespace framebuffer: virtual tuple get_virtual_size(): return self.width, self.height - int perform_redraw(bool): + int perform_redraw(bool, bool): #ifndef PERF_BUILD msync(self.fbmem, self.byte_size, MS_SYNC) self.save_png() @@ -920,8 +923,9 @@ namespace framebuffer: mem := (remarkable_color*) fbink_get_fb_pointer(self.fd, &size) return mem - int perform_redraw(bool full_screen=false): + int perform_redraw(bool full_screen=false, bool flash=false): config_.wfm_mode = self.waveform_mode + config_.is_flashing = flash if !full_screen: fbink_refresh(self.fd, dirty_area.y0, @@ -931,6 +935,7 @@ namespace framebuffer: &config_) else: fbink_refresh(self.fd, 0, 0, self.display_width, self.height, &config_) + config_.is_flashing = false return 0 void wait_for_redraw(uint32_t update_marker): @@ -979,7 +984,7 @@ namespace framebuffer: return vinfo.xres, vinfo.yres - int perform_redraw(bool full_screen=false): + int perform_redraw(bool full_screen=false, bool flash=false): um := 0 hwtcon_update_data update_data hwtcon_rect update_rect diff --git a/src/rmkit/input/device_id.cpy b/src/rmkit/input/device_id.cpy index b6077b9..a3c8430 100644 --- a/src/rmkit/input/device_id.cpy +++ b/src/rmkit/input/device_id.cpy @@ -27,7 +27,7 @@ // event2: gpio keys // ev_key: home, left, right, power, wakeup namespace input: - enum EV_TYPE { TOUCH, STYLUS, BUTTONS, UNKNOWN, INVALID } + enum EV_TYPE { TOUCH, STYLUS, BUTTONS, GPIO, UNKNOWN, INVALID } static bool check_bit_set(int fd, int type, int i): unsigned long bit[NBITS(KEY_MAX)] ioctl(fd, EVIOCGBIT(type, KEY_MAX), bit); @@ -55,6 +55,9 @@ namespace input: if check_bit_set(fd, EV_KEY, BTN_TOOL_PEN): return TOUCH + if check_bit_set(fd, EV_MSC, MSC_RAW): + return GPIO + return UNKNOWN static bool supports_stylus(int fd): diff --git a/src/rmkit/input/input.cpy b/src/rmkit/input/input.cpy index 293f28c..fa4342b 100644 --- a/src/rmkit/input/input.cpy +++ b/src/rmkit/input/input.cpy @@ -8,6 +8,7 @@ #include "../defines.h" #include "../fb/fb_info.h" +#include "../shared/proc.h" #include "events.h" #include "gestures.h" #include "device_id.h" @@ -100,6 +101,7 @@ namespace input: class Input: private: + ui::TimerPtr ungrab_interval = nullptr; public: int max_fd @@ -109,6 +111,7 @@ namespace input: InputClass wacom InputClass touch InputClass button + InputClass gpio vector all_motion_events vector all_key_events @@ -133,6 +136,20 @@ namespace input: self.open_device("/dev/input/event2") self.open_device("/dev/input/event3") self.open_device("/dev/input/event4") + self.grab() + std::function ungrab_task = [=]() { + debug "UNGRAB_TASK" + vector bins = { "nickel" } + procs := proc::list_procs(bins) + if procs.size() > 0: + debug "UNGRABBING" + self.ungrab() + debug "UNGRABBED" + ui::cancel_timer(ungrab_interval) + else: + debug "RESCHEDULING" + } + ungrab_interval = ui::set_interval(ungrab_task, 500) #else if USE_RESIM: debug "MONITORING RESIM" @@ -155,7 +172,7 @@ namespace input: return void close_devices(): - vector fds = { self.touch, self.wacom, self.button} + vector fds = { self.touch, self.wacom, self.button, self.gpio} for auto in : fds: if in.fd > 0: close(in.fd) @@ -183,6 +200,10 @@ namespace input: self.touch.set_fd(fd) debug "AS TOUCH" break + case GPIO: + debug ": GPIO" + self.gpio.set_fd(fd) + break case INVALID: case UNKNOWN: default: @@ -252,17 +273,11 @@ namespace input: return void grab(): - #ifndef REMARKABLE - return - #endif - for auto fd : { self.touch.fd, self.wacom.fd, self.button.fd }: + for auto fd : { self.touch.fd, self.wacom.fd, self.button.fd, self.gpio.fd }: ioctl(fd, EVIOCGRAB, true) void ungrab(): - #ifndef REMARKABLE - return - #endif - for auto fd : { self.touch.fd, self.wacom.fd, self.button.fd }: + for auto fd : { self.touch.fd, self.wacom.fd, self.button.fd, self.gpio.fd }: ioctl(fd, EVIOCGRAB, false) void check_reopen(): diff --git a/src/rmkit/rmkit.cpy b/src/rmkit/rmkit.cpy index 529bdcb..89e6334 100644 --- a/src/rmkit/rmkit.cpy +++ b/src/rmkit/rmkit.cpy @@ -1,4 +1,7 @@ #include "fb/fb.h" +#ifdef KOBO +#include "../shared/proc.h" // Needed to prevent nickel from grabbing inputs +#endif #include "input/input.h" #include "util/signals.h" #include "ui/ui.h" diff --git a/src/rmkit/ui/task_queue.cpy b/src/rmkit/ui/task_queue.cpy index 61db745..eb1373c 100644 --- a/src/rmkit/ui/task_queue.cpy +++ b/src/rmkit/ui/task_queue.cpy @@ -31,33 +31,45 @@ namespace ui: TaskQueue::wakeup() static void run_tasks(): + task_q.lock() if TaskQueue::tasks.size() == 0: + task_q.unlock() return + task_q.unlock() - thread *th = nullptr - try: - th = new thread([=]() { - count := 4 - while tasks.size() > 0 and count > 0: - count-- - task_q.lock() - t := TaskQueue::tasks.front() - TaskQueue::tasks.pop_front() - task_q.unlock() - + if task_m.try_lock(): + try: + std::thread* th = new thread([=]() { task_m.lock() - t() + debug "TASK THREAD STARTED" + count := 4 + while count > 0: + count-- + task_q.lock() + if tasks.size() == 0: + task_q.unlock() + break + t := TaskQueue::tasks.front() + TaskQueue::tasks.pop_front() + task_q.unlock() + + try: + t() + catch (const std::exception& e): + debug "TASK EXEC EXC", e.what() + debug "TASKS DONE" + TaskQueue::wakeup() task_m.unlock() + }) + th->detach() + task_m.unlock() + catch (const std::exception& e): + debug "NEW THREAD EXC", e.what() TaskQueue::wakeup() - }) - th->detach() - if th != nullptr - delete th - catch (const std::exception& e): - debug "NEW THREAD EXC", e.what() - TaskQueue::wakeup() - + else: + debug "TASK QUEUE WAS RUNNING, NOT RELAUNCHING" + // class: ui::TaskQueue // The task queue is a way of scheduling tasks from side threads to be run