示例#1
0
static void set_key_state(KeyEvent const& event) {
	Window* const window = event.window;
	if (event.action == KeyAction::press) {
		// If state already has KeyAction::release, retain it
		// (it will be cleared by update())
		window->_key_states[
			unsigned_cast(event.code)
		] |= 1 << unsigned_cast(event.action);
	} else if (event.action == KeyAction::release) {
		// Replace state and enqueue clear
		window->_key_states[
			unsigned_cast(event.code)
		] = 1 << unsigned_cast(event.action);
		for (auto const code : window->_key_clear_queue) {
			if (code == event.code) {
				return;
			}
		}
		if (fixed_array::space(window->_key_clear_queue)) {
			fixed_array::push_back(window->_key_clear_queue, event.code);
		} else {
			TOGO_LOGF(
				"input_buffer: warning: discarded key-clear for key %u on window %p\n",
				unsigned_cast(event.code),
				event.window
			);
		}
	}
}
示例#2
0
static void update_input_states(Window* window) {
	for (auto const code : window->_key_clear_queue) {
		window->_key_states[
			unsigned_cast(code)
		] &= ~(1 << unsigned_cast(KeyAction::release));
	}
	fixed_array::clear(window->_key_clear_queue);
	for (auto& state : window->_mouse_button_states) {
		state &= ~(1 << unsigned_cast(MouseButtonAction::release));
	}
}
示例#3
0
文件: Cursor.cpp 项目: komiga/Beard
void
Cursor::col_recalc() noexcept {
	auto const& node = this->node();
	if (0 >= m_col) {
		m_col = 0;
		m_index = 0;
	} else if (node.points() <= unsigned_cast(m_col)) {
		m_col = signed_cast(node.points());
		m_index = signed_cast(node.units());
	} else if (node.singular()) {
		m_index = m_col;
	} else {
		position_type col = 0;
		auto const end = node.cend();
		auto step = node.cbegin(), from = step;
		while (
			from < (step = txt::EncUtils::next(from, end)) &&
			col > m_col
		) {
			from = step;
			++col;
		}
		m_col = col;
		m_index = std::distance(node.cbegin(), from);
	}
}
示例#4
0
文件: Cursor.cpp 项目: komiga/Beard
std::size_t
Cursor::insert(
	char32 const cp
) {
	txt::EncUtils::char_type units[txt::EncUtils::max_units];
	auto const it = txt::EncUtils::encode(
		cp,
		std::begin(units),
		duct::CHAR_NULL
	);
	if (std::begin(units) != it) {
		auto& node = this->node();
		node.m_buffer.insert(node.cbegin() + m_index, std::begin(units), it);
		auto const size = std::distance(std::begin(units), it);
		tree().update_counts(node, size, 1);
		return unsigned_cast(size);
	} else {
		// Invalid code point (ignored)
		return 0u;
	}
}
示例#5
0
int						unsigned_handler(PF *argument, va_list ap)
{
	uintmax_t			n;

	if (argument->spec == 'x' || argument->spec == 'X'
		|| argument->spec == 'u' || argument->spec == 'o'
		|| argument->spec == 'b')
		n = unsigned_cast(argument, ap);
	else
		n = (unsigned long int)va_arg(ap, uintmax_t);
	if (argument->spec == 'o' || argument->spec == 'O')
		argument->arg = fpf_itoa_base(n, 8);
	else if (argument->spec == 'u' || argument->spec == 'U')
		argument->arg = fpf_itoa_base(n, 10);
	else if (argument->spec == 'x')
		argument->arg = fpf_strlower(fpf_itoa_base(n, 16));
	else if (argument->spec == 'b')
		argument->arg = fpf_itoa_base(n, 2);
	else
		argument->arg = fpf_itoa_base(n, 16);
	return (unsigned_helper(argument));
}
示例#6
0
/// Parse program arguments.
///
/// Command-leading options are pushed into k_command_options.
/// Later options to the command are pushed into k_command to retain
/// argument order (sub-options per command stage).
/// Returns true if a command was parsed.
bool parse_args(
	KVS& k_options,
	KVS& k_command_options,
	KVS& k_command,
	signed const argc,
	char const* const argv[]
) {
	kvs::set_type(k_options, KVSType::node);
	kvs::set_type(k_command_options, KVSType::node);
	kvs::set_type(k_command, KVSType::node);
	kvs::clear(k_options);
	kvs::clear(k_command_options);
	kvs::clear(k_command);
	if (argc == 0) {
		return false;
	}
	kvs::set_name(k_options, StringRef{argv[0], cstr_tag{}});

	signed aidx;
	char const* str;
	signed pos;
	signed pos_eq;
	signed num_dashes;
	KVS* k_current = &k_options;
	for (aidx = 1; argc > aidx; ++aidx) {
		str = argv[aidx];
		pos = 0;
		pos_eq = 0;
		num_dashes = 0;
		for (; str[pos] != '\0'; ++pos) {
			if (str[pos] == '-' && num_dashes == pos) {
				++num_dashes;
			} else if (str[pos] == '=') {
				pos_eq = pos;
				break;
			}
		}
		for (; str[pos] != '\0'; ++pos) {
			// Continue to the end of the string (pos becomes size of string)
		}
		if (pos_eq == 0) {
			pos_eq = pos;
		}
		if (num_dashes == pos) {
			// Consists only of dashes
			num_dashes = 0;
		}
		if (num_dashes == 1 || num_dashes == 2) {
			KVS& back = kvs::push_back(
				*k_current,
				KVS{StringRef{str, unsigned_cast(pos_eq)}, null_tag{}}
			);
			if (pos > pos_eq) {
				++pos_eq;
				// TODO: Parse string to typed value
				kvs::string(
					back,
					StringRef{str + pos_eq, unsigned_cast(pos - pos_eq)}
				);
			} else {
				kvs::boolean(back, true);
			}
		} else if (k_current == &k_options) {
			// Command reached; switch to parse leading options
			k_current = &k_command_options;
			kvs::set_name(k_command, StringRef{str, unsigned_cast(pos)});
		} else {
			// Undashed argument to command
			k_current = &k_command;
			kvs::push_back(*k_current, KVS{StringRef{str, unsigned_cast(pos)}});
		}
	}
	return k_current != &k_options;
}
示例#7
0
文件: Cursor.cpp 项目: komiga/Beard
void
Cursor::col_step(
	difference_type const n
) noexcept {
	if (0 == n) {
		return;
	}

	auto const& node = this->node();
	difference_type const dest = m_col + n;
	/*DUCT_DEBUGF(
		"col_step: m_col = %zd, m_index = %zd, dest = %ld, n = %ld, "
		"diff = %zd, abs = %zd",
		m_col, m_index, dest, n,
		dest - m_col,
		std::abs(dest - m_col)
	);*/

	// Recalculate (i.e., count from the beginning) or step
	// depending on the distance from the current column
	if (0 >= dest) {
		m_col = 0;
		m_index = 0;
	} else if (node.points() <= unsigned_cast(dest)) {
		m_col = signed_cast(node.points());
		m_index = signed_cast(node.units());
	} else if (node.singular()) {
		m_col = dest;
		m_index = dest;
	} else if (dest < std::abs(dest - m_col)) {
		m_col = dest;
		col_recalc();
	} else {
		auto const begin = node.cbegin(), end = node.cend();
		auto step = begin + m_index, from = step;
		if (0 > n) {
			// Step backward
			while (
				from > (step = txt::EncUtils::prev(from, begin)) &&
				dest < m_col
			) {
				from = step;
				--m_col;
			}
		} else {
			// Step forward
			while (
				from < (step = txt::EncUtils::next(from, end)) &&
				dest > m_col
			) {
				from = step;
				++m_col;
			}
		}
		m_index = std::distance(begin, from);
		/*DUCT_DEBUGF(
			"  m_col = %zd, m_index = %zd, dist = %ld",
			m_col,
			m_index,
			std::distance(begin, from)
		);*/
	}
}
示例#8
0
/// Poll events.
///
/// Returns true if an event was fetched.
///
/// @warning This must be called on the thread that created the
/// windows.
bool input_buffer::poll(
	InputBuffer& ib,
	InputEventType& type,
	InputEvent const*& event
) {
	if (!ib._buffer._consume_mode) {
		window::process_events(ib);
		if (!object_buffer::empty(ib._buffer)) {
			object_buffer::begin_consume(ib._buffer);
		} else {
			return false;
		}
	} else {
		if (!object_buffer::has_more(ib._buffer)) {
			object_buffer::end_consume(ib._buffer);
			return false;
		}
	}
	void const* vptr = nullptr;
	object_buffer::read(ib._buffer, type, vptr);
	event = static_cast<InputEvent const*>(vptr);
	#if defined(TOGO_TEST_INPUT_BUFFER)
		switch (type) {
		case InputEventType::key:
			TOGO_TEST_LOGF(
				"input event: %p => "
				"key: action = %u  code = %u  mods = %u\n",
				event->window,
				unsigned_cast(event->key.action),
				unsigned_cast(event->key.code),
				unsigned_cast(event->key.mods)
			);
			break;
		case InputEventType::mouse_button:
			TOGO_TEST_LOGF(
				"input event: %p => "
				"mouse_button: action = %u   button = %u\n",
				event->window,
				unsigned_cast(event->mouse_button.action),
				unsigned_cast(event->mouse_button.button)
			);
			break;
		case InputEventType::mouse_motion:
			/*TOGO_TEST_LOGF(
				"input event: %p => "
				"mouse_motion: (%d, %d)\n",
				event->window,
				event->mouse_motion.x, event->mouse_motion.y
			);*/
			break;
		case InputEventType::window_focus:
			TOGO_TEST_LOGF(
				"input event: %p => "
				"window_focus: focused = %s\n",
				event->window,
				event->window_focus.focused ? "true" : "false"
			);
			break;
		case InputEventType::window_close_request:
			TOGO_TEST_LOGF(
				"input event: %p => "
				"window_close_request\n",
				event->window
			);
			break;
		case InputEventType::window_resize:
			TOGO_TEST_LOGF(
				"input event: %p => "
				"window_resize: (%-4u, %-4u) -> (%-4u, %-4u)\n",
				event->window,
				event->window_resize.old_size.width,
				event->window_resize.old_size.height,
				event->window_resize.new_size.width,
				event->window_resize.new_size.height
			);
			break;
		case InputEventType::window_backbuffer_dirtied:
			TOGO_TEST_LOGF(
				"input event: %p => "
				"window_backbuffer_dirtied\n",
				event->window
			);
			break;
		}
	#endif
	switch (type) {
	case InputEventType::key:
		set_key_state(event->key);
		break;

	case InputEventType::mouse_button:
		if (event->mouse_button.action == MouseButtonAction::press) {
			event->window->_mouse_button_states[
				unsigned_cast(event->mouse_button.button)
			] |= 1 << unsigned_cast(event->mouse_button.action);
		} else if (event->mouse_button.action == MouseButtonAction::release) {
			event->window->_mouse_button_states[
				unsigned_cast(event->mouse_button.button)
			]  = 1 << unsigned_cast(event->mouse_button.action);
		}
		break;

	case InputEventType::mouse_motion:
		event->window->_mouse_x = event->mouse_motion.x;
		event->window->_mouse_y = event->mouse_motion.y;
		break;

	default:
		break;
	};
	return true;
}
示例#9
0
文件: types.hpp 项目: komiga/togo
namespace notification {

/**
	@addtogroup lib_platform_notification
	@{
*/

/// Notification type.
enum class Type : unsigned {
	generic,

	/// Indicates that an error has occurred.
	error,

	/// Indicates that the application is persisting (e.g., a background
	/// service/task).
	persisting_process,

	/// Indicates that an alarm has triggered.
	alarm,

	/// Indicates that a message has arrived (e.g., SMS).
	message,

	/// Indicates that the application is playing media.
	media,
};
static constexpr unsigned const c_num_type = unsigned_cast(Type::media) + 1;

/// Notification priority.
enum class Priority : unsigned {
	normal,
	low,
	high,
};
static constexpr unsigned const c_num_priority = unsigned_cast(Priority::high) + 1;

/// Maximum lifetime of a notification in milliseconds (8m74s, 524.287s, 524287ms, 0x7FFFF).
static constexpr signed const MAX_LIFETIME = 0x7FFFF;

struct NotificationImpl;

/// Notification.
struct Notification {
	TOGO_LUA_MARK_USERDATA(Notification);

	u32 _properties;
	NotificationImpl* _impl;

	Notification(Notification&&) = default;
	Notification& operator=(Notification&&) = default;

	Notification(Notification const&) = delete;
	Notification& operator=(Notification const&) = delete;

	Notification(
		StringRef title,
		StringRef body,
		signed lifetime = -1,
		Type type = Type::generic,
		Priority priority = Priority::normal
	);
	~Notification();
};

/** @} */ // end of doc-group lib_platform_notification
} // namespace notification