view dep/animia/src/animia.cc @ 198:bc1ae1810855

dep/animia: switch from using classes to global functions the old idea was ok, but sort of hackish; this method doesn't use classes at all, and this way (especially important!) we can do wayland stuff AND x11 at the same time, which wasn't really possible without stupid workarounds in the other method
author Paper <mrpapersonic@gmail.com>
date Sun, 24 Dec 2023 02:59:42 -0500
parents 0fc126d52de4
children 031a257ee019
line wrap: on
line source

#include "animia.h"
#include "animia/fd.h"
#include "animia/strategies.h"
#include "animia/types.h"
#include "animia/util.h"
#include "animia/win.h"

#include <set>
#include <string>
#include <vector>

namespace animia {

namespace internal {

static bool IsExecutableInList(const Player& player, const std::string& name) {
	std::string stem;
#ifdef WIN32
	if (!util::Stem(name, stem))
#endif
		stem = name;

	for (const auto& pattern : player.executables)
		if (util::CheckPattern(pattern, stem))
			return true;

	return false;
}

static bool IsWindowInList(const Player& player, const std::string& name) {
	for (const auto& pattern : player.windows)
		if (util::CheckPattern(pattern, name))
			return true;

	return false;
}

static bool PlayerHasStrategy(const Player& player, const Strategy& strategy) {
	for (const auto& pstrategy : player.strategies)
		if (pstrategy == strategy)
			return true;

	return false;
}

} // namespace internal

bool GetResults(const std::vector<Player>& players, std::vector<Result>& results) {
	/* Start out with file descriptors. */
	auto process_proc = [&](const Process& process) -> bool {
		for (const auto& player : players) {
			if (!internal::PlayerHasStrategy(player, Strategy::OpenFiles))
				continue;

			if (!internal::IsExecutableInList(player, process.name))
				continue;

			results.push_back({ResultType::Process, player, process, {}, {}});
			break;
		}
		return true;
	};

	if (!internal::EnumerateOpenProcesses(process_proc))
		return false;

	/* Then add our cool windows.
	   Note: X11 is stupid and there's no reliable way to get a PID from a given window.
	         This is because some windows might not even have a process attached to them.
	         We should set the PID of the process if we can get it, but that'll be for when
	         I can actually be arsed to implement the X11 backend. */
	auto window_proc = [&](const Process& process, const Window& window) -> bool {
		for (const auto& player : players) {
			if (!internal::PlayerHasStrategy(player, Strategy::WindowTitle))
				continue;

			if (!internal::IsWindowInList(player, window.class_name))
				continue;

			results.push_back({ResultType::Window, player, process, window, {}});
			break;
		}
		return true;
	};

	if (!internal::EnumerateWindows(window_proc))
		return false;

	return internal::ApplyStrategies(results);
}

} // namespace animia