<commit_before>//------------------------------------------------------------------------------
//  raspiInputMgr.cc
//------------------------------------------------------------------------------
#include "Pre.h"
#include "raspiInputMgr.h"
#include "Core/Core.h"
#include "Core/Log.h"
#include "Core/String/StringBuilder.h"
#include "Gfx/Gfx.h"
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/input.h>

namespace Oryol {
namespace _priv {

//------------------------------------------------------------------------------
raspiInputMgr::raspiInputMgr() :
runLoopId(RunLoop::InvalidId),
kbdFd(-1),
mouseFd(-1),
leftShift(false),
rightShift(false),
maxMouseX(0),
maxMouseY(0),
curMouseX(0),
curMouseY(0) {
    // empty
}

//------------------------------------------------------------------------------
raspiInputMgr::~raspiInputMgr() {
    // empty
}

//------------------------------------------------------------------------------
void
raspiInputMgr::setup(const InputSetup& setup) {
    inputMgrBase::setup(setup);
    if (this->openDevices()) {
        if (-1 != this->kbdFd) {
            this->Keyboard.Attached = true;
        }
        if (-1 != this->mouseFd) {
            this->Mouse.Attached = true;
        }
    }
    this->runLoopId = Core::PreRunLoop()->Add([this]() { this->pollInput(); });
}

//------------------------------------------------------------------------------
void
raspiInputMgr::discard() {
    this->closeDevices();
    Core::PostRunLoop()->Remove(this->runLoopId);
    this->runLoopId = RunLoop::InvalidId;
    inputMgrBase::discard();
}

//------------------------------------------------------------------------------
bool
raspiInputMgr::openDevices() {
    o_assert_dbg(-1 == this->kbdFd);
    o_assert_dbg(-1 == this->mouseFd);

    // see http://www.peteronion.org.uk/PiProgs/input.c
    StringBuilder strBuilder;
    const char* dirName = "/dev/input/by-id";
    DIR* dirp = opendir(dirName);
    if (dirp) {
        dirent* dp;
        while (nullptr != (dp = readdir(dirp))) {
            Log::Info("readdir: %s\n", dp->d_name);
            if ((-1 == this->kbdFd) && strstr(dp->d_name, "-event-kbd")) {
                strBuilder.Format(1024, "%s/%s", dirName, dp->d_name);
                this->kbdFd = open(strBuilder.AsCStr(), O_RDONLY|O_NONBLOCK);
            }
            else if ((-1 == this->mouseFd) && strstr(dp->d_name, "-event-mouse")) {
                strBuilder.Format(1024, "%s/%s", dirName, dp->d_name);
                this->mouseFd = open(strBuilder.AsCStr(), O_RDONLY|O_NONBLOCK);<commit_msg>raspiInputMgr: exclusively grab keyboard and mouse<commit_after>//------------------------------------------------------------------------------
//  raspiInputMgr.cc
//------------------------------------------------------------------------------
#include "Pre.h"
#include "raspiInputMgr.h"
#include "Core/Core.h"
#include "Core/Log.h"
#include "Core/String/StringBuilder.h"
#include "Gfx/Gfx.h"
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/input.h>

namespace Oryol {
namespace _priv {

//------------------------------------------------------------------------------
raspiInputMgr::raspiInputMgr() :
runLoopId(RunLoop::InvalidId),
kbdFd(-1),
mouseFd(-1),
leftShift(false),
rightShift(false),
maxMouseX(0),
maxMouseY(0),
curMouseX(0),
curMouseY(0) {
    // empty
}

//------------------------------------------------------------------------------
raspiInputMgr::~raspiInputMgr() {
    // empty
}

//------------------------------------------------------------------------------
void
raspiInputMgr::setup(const InputSetup& setup) {
    inputMgrBase::setup(setup);
    if (this->openDevices()) {
        if (-1 != this->kbdFd) {
            this->Keyboard.Attached = true;
        }
        if (-1 != this->mouseFd) {
            this->Mouse.Attached = true;
        }
    }
    this->runLoopId = Core::PreRunLoop()->Add([this]() { this->pollInput(); });
}

//------------------------------------------------------------------------------
void
raspiInputMgr::discard() {
    this->closeDevices();
    Core::PostRunLoop()->Remove(this->runLoopId);
    this->runLoopId = RunLoop::InvalidId;
    inputMgrBase::discard();
}

//------------------------------------------------------------------------------
bool
raspiInputMgr::openDevices() {
    o_assert_dbg(-1 == this->kbdFd);
    o_assert_dbg(-1 == this->mouseFd);

    // see http://www.peteronion.org.uk/PiProgs/input.c
    StringBuilder strBuilder;
    const char* dirName = "/dev/input/by-id";
    DIR* dirp = opendir(dirName);
    if (dirp) {
        dirent* dp;
        while (nullptr != (dp = readdir(dirp))) {
            Log::Info("readdir: %s\n", dp->d_name);
            if ((-1 == this->kbdFd) && strstr(dp->d_name, "-event-kbd")) {
                strBuilder.Format(1024, "%s/%s", dirName, dp->d_name);
                this->kbdFd = open(strBuilder.AsCStr(), O_RDONLY|O_NONBLOCK);
                if (-1 != this->kbdFd) {
                    ioctl(this->kbdFd, EVIOCGRAB, 1);
                }
            }
            else if ((-1 == this->mouseFd) && strstr(dp->d_name, "-event-mouse")) {
                strBuilder.Format(1024, "%s/%s", dirName, dp->d_name);
                this->mouseFd = open(strBuilder.AsCStr(), O_RDONLY|O_NONBLOCK);
                if (-1 != this->mouseFd) {
                    ioctl(this->mouseFd, EVIOCGRAB, 1);
                }
{'fraction_non_alphanumeric': 0.3488032157865887, 'fraction_numerical': 0.00803946647177051, 'mean_word_length': 1.3966725043782837, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '5312658', 'n_tokens_mistral': 1668, 'n_tokens_neox': 1660, 'n_words': 258}