Mercurial > minori
view dep/animone/src/strategist.cc @ 340:74e2365326c6
dep/animone: add experimental accessibility strategy
I also moved most of the functions out of util/win32.cc, because that
file is meant for things that are shared between the different functions,
and currently that is only wide string conversion helpers.
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Wed, 19 Jun 2024 23:13:55 -0400 |
parents | b1f625b0227c |
children | 886f66775f31 |
line wrap: on
line source
#include <regex> #include <unordered_map> #include "animone.h" #include "animone/a11y.h" #include "animone/fd.h" #include "animone/strategies.h" #include "animone/util.h" /* This file was changed lots from anisthesia. Most notably we don't use classes here * anymore, and we just pass the result vector to different function that append * to the result (which is better imo) */ namespace animone::internal { static bool ApplyWindowTitleFormat(const std::string& format, std::string& title) { if (format.empty()) return false; const std::regex pattern(format); std::smatch match; std::regex_match(title, match, pattern); // Use the first non-empty match result, because the regular expression may // contain multiple sub-expressions. for (size_t i = 1; i < match.size(); ++i) { if (!match.str(i).empty()) { title = match.str(i); return true; } } // Results are empty, but the match was successful if (!match.empty()) { title.clear(); return true; } return true; } static MediaInfoType InferMediaInformationType(const std::string& str) { const std::regex path_pattern(R"(^(?:[A-Za-z]:[/\\]|\\\\)[^<>:"/\\|?*]+)"); return (std::regex_search(str, path_pattern)) ? MediaInfoType::File : MediaInfoType::Unknown; } static bool AddMedia(Result& result, const MediaInfo media_information) { if (media_information.value.empty()) return false; Media media = { .information = {media_information} }; result.media.push_back(std::move(media)); return true; } /* ------------------------------------------------------------------------- */ /* strategies */ static bool ApplyWindowTitleStrategy(std::vector<Result>& results) { bool success = false; for (auto& result : results) { auto title = result.window.text; if (title.empty()) continue; ApplyWindowTitleFormat(result.player.window_title_format, title); success |= AddMedia(result, {InferMediaInformationType(title), title}); } return success; } static bool ApplyOpenFilesStrategy(std::vector<Result>& results) { bool success = false; /* map pids to our results, saves time with open_file_proc */ std::unordered_map<pid_t, Result*> pid_map; std::set<pid_t> pids; for (Result& result : results) { const pid_t pid = result.process.pid; if (!pid) continue; pid_map.insert({pid, &result}); pids.insert(pid); } auto open_file_proc = [&](const OpenFile& file) -> bool { success |= AddMedia(*pid_map[file.pid], {MediaInfoType::File, file.path}); return true; }; EnumerateOpenFiles(pids, open_file_proc); return success; } static bool ApplyAccessibilityStrategy(std::vector<Result>& results) { bool success = false; for (Result& result : results) { auto web_browser_proc = [&result](const WebBrowserInformation& info) { auto value = info.value; switch (info.type) { case WebBrowserInformationType::Address: AddMedia(result, {MediaInfoType::Url, value}); break; case WebBrowserInformationType::Title: ApplyWindowTitleFormat(result.player.window_title_format, value); AddMedia(result, {MediaInfoType::Title, value}); break; case WebBrowserInformationType::Tab: AddMedia(result, {MediaInfoType::Tab, value}); break; } }; success |= GetWebBrowserInformation(result.window, web_browser_proc); } return success; } /* ------------------------------------------------------------------------- */ bool ApplyStrategies(std::vector<Result>& results) { bool success = false; success |= ApplyWindowTitleStrategy(results); success |= ApplyOpenFilesStrategy(results); success |= ApplyAccessibilityStrategy(results); return success; } } // namespace animone::internal