From 26cf4688c2aea98a99dbcb06b0bdab9fdfadb754 Mon Sep 17 00:00:00 2001
From: kc5nra <jrb@turrettech.com>
Date: Sun, 14 Sep 2014 15:31:57 -0500
Subject: [PATCH] Add interaction support to libobs

---
 libobs/CMakeLists.txt    |  1 +
 libobs/obs-interaction.h | 56 ++++++++++++++++++++++++++++++++
 libobs/obs-source.c      | 70 ++++++++++++++++++++++++++++++++++++++++
 libobs/obs-source.h      | 62 +++++++++++++++++++++++++++++++++++
 libobs/obs.h             | 22 +++++++++++++
 5 files changed, 211 insertions(+)
 create mode 100644 libobs/obs-interaction.h

diff --git a/libobs/CMakeLists.txt b/libobs/CMakeLists.txt
index d0c807935..b66e98f2d 100644
--- a/libobs/CMakeLists.txt
+++ b/libobs/CMakeLists.txt
@@ -222,6 +222,7 @@ set(libobs_libobs_HEADERS
 	obs-ui.h
 	obs-properties.h
 	obs-data.h
+	obs-interaction.h
 	obs-module.h
 	obs-scene.h
 	obs-source.h
diff --git a/libobs/obs-interaction.h b/libobs/obs-interaction.h
new file mode 100644
index 000000000..d213df216
--- /dev/null
+++ b/libobs/obs-interaction.h
@@ -0,0 +1,56 @@
+/******************************************************************************
+ Copyright (C) 2014 by Hugh Bailey <obs.jim@gmail.com>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ ******************************************************************************/
+
+#pragma once
+
+#include "util/c99defs.h"
+
+enum obs_interaction_flags {
+	INTERACT_NONE          = 0,
+	INTERACT_CAPS_KEY      = 1,
+	INTERACT_SHIFT_KEY     = 1 << 1,
+	INTERACT_CONTROL_KEY   = 1 << 2,
+	INTERACT_ALT_KEY       = 1 << 3,
+	INTERACT_MOUSE_LEFT    = 1 << 4,
+	INTERACT_MOUSE_MIDDLE  = 1 << 5,
+	INTERACT_MOUSE_RIGHT   = 1 << 6,
+	INTERACT_COMMAND_KEY   = 1 << 7,
+	INTERACT_NUMLOCK_KEY   = 1 << 8,
+	INTERACT_IS_KEY_PAD    = 1 << 9,
+	INTERACT_IS_LEFT       = 1 << 10,
+	INTERACT_IS_RIGHT      = 1 << 11
+};
+
+enum obs_mouse_button_type {
+	MOUSE_LEFT,
+	MOUSE_MIDDLE,
+	MOUSE_RIGHT
+};
+
+struct obs_mouse_event {
+	uint32_t            modifiers;
+	int32_t             x;
+	int32_t             y;
+};
+
+struct obs_key_event {
+	uint32_t            modifiers;
+	char                *text;
+	uint32_t            native_modifiers;
+	uint32_t            native_scancode;
+	uint32_t            native_vkey;
+};
diff --git a/libobs/obs-source.c b/libobs/obs-source.c
index eb1f61d42..6b0015b87 100644
--- a/libobs/obs-source.c
+++ b/libobs/obs-source.c
@@ -389,6 +389,76 @@ void obs_source_update(obs_source_t source, obs_data_t settings)
 	}
 }
 
+void obs_source_send_mouse_click(obs_source_t source,
+		const struct obs_mouse_event *event,
+		int32_t type, bool mouse_up,
+		uint32_t click_count)
+{
+	if (!source)
+		return;
+
+	if (source->info.output_flags & OBS_SOURCE_INTERACTION) {
+		if (source->info.mouse_click) {
+			source->info.mouse_click(source->context.data,
+					event, type, mouse_up, click_count);
+		}
+	}
+}
+
+void obs_source_send_mouse_move(obs_source_t source,
+		const struct obs_mouse_event *event, bool mouse_leave)
+{
+	if (!source)
+		return;
+
+	if (source->info.output_flags & OBS_SOURCE_INTERACTION) {
+		if (source->info.mouse_move) {
+			source->info.mouse_move(source->context.data,
+					event, mouse_leave);
+		}
+	}
+}
+
+void obs_source_send_mouse_wheel(obs_source_t source,
+		const struct obs_mouse_event *event, int x_delta, int y_delta)
+{
+	if (!source)
+		return;
+
+	if (source->info.output_flags & OBS_SOURCE_INTERACTION) {
+		if (source->info.mouse_wheel) {
+			source->info.mouse_wheel(source->context.data,
+					event, x_delta, y_delta);
+		}
+	}
+}
+
+void obs_source_send_focus(obs_source_t source, bool focus)
+{
+	if (!source)
+		return;
+
+	if (source->info.output_flags & OBS_SOURCE_INTERACTION) {
+		if (source->info.focus) {
+			source->info.focus(source->context.data, focus);
+		}
+	}
+}
+
+void obs_source_send_key_click(obs_source_t source,
+		const struct obs_key_event *event, bool key_up)
+{
+	if (!source)
+		return;
+
+	if (source->info.output_flags & OBS_SOURCE_INTERACTION) {
+		if (source->info.key_click) {
+			source->info.key_click(source->context.data, event,
+					key_up);
+		}
+	}
+}
+
 static void activate_source(obs_source_t source)
 {
 	if (source->context.data && source->info.activate)
diff --git a/libobs/obs-source.h b/libobs/obs-source.h
index 20636a7b0..9bdccd375 100644
--- a/libobs/obs-source.h
+++ b/libobs/obs-source.h
@@ -88,6 +88,14 @@ enum obs_source_type {
  */
 #define OBS_SOURCE_COLOR_MATRIX (1<<4)
 
+/**
+ * Source supports interaction.
+ * 
+ * When this is used, the source will receive interaction events
+ * if they provide the necessary callbacks in the source definition structure.
+ */
+#define OBS_SOURCE_INTERACTION (1<<5)
+
 /** @} */
 
 typedef void (*obs_source_enum_proc_t)(obs_source_t parent, obs_source_t child,
@@ -283,6 +291,60 @@ struct obs_source_info {
 	 * @param  settings  Settings
 	 */
 	void (*load)(void *data, obs_data_t settings);
+
+	/**
+	 * Called when interacting with a source and a mouse-down or mouse-up
+	 * occurs.
+	 * 
+	 * @param data         Source data
+	 * @param event        Mouse event properties
+	 * @param type         Mouse button pushed
+	 * @param mouse_up     Mouse event type (true if mouse-up)
+	 * @param click_count  Mouse click count (1 for single click, etc.)
+	 */
+	void (*mouse_click)(void *data,
+			const struct obs_mouse_event *event,
+			int32_t type, bool mouse_up, uint32_t click_count);
+	/**
+	 * Called when interacting with a source and a mouse-move occurs.
+	 *
+	 * @param data         Source data
+	 * @param event        Mouse event properties
+	 * @param mouse_leave  Mouse leave state (true if mouse left source)
+	 */
+	void (*mouse_move)(void *data,
+			const struct obs_mouse_event *event, bool mouse_leave);
+
+	/**
+	 * Called when interacting with a source and a mouse-wheel occurs.
+	 *
+	 * @param data         Source data
+	 * @param event        Mouse event properties
+	 * @param x_delta      Movement delta in the horizontal direction
+	 * @param y_delta      Movement delta in the vertical direction
+	 */
+	void (*mouse_wheel)(void *data,
+			const struct obs_mouse_event *event, int x_delta,
+			int y_delta);
+	/**
+	 * Called when interacting with a source and gain focus/lost focus event
+	 * occurs.
+	 *
+	 * @param data         Source data
+	 * @param focus        Focus state (true if focus gained)
+	 */
+	void (*focus)(void *data, bool focus);
+
+	/**
+	 * Called when interacting with a source and a key-up or key-down
+	 * occurs.
+	 *
+	 * @param data         Source data
+	 * @param event        Key event properties
+	 * @param focus        Key event type (true if mouse-up)
+	 */
+	void (*key_click)(void *data, const struct obs_key_event *event,
+			bool key_up);
 };
 
 EXPORT void obs_register_source_s(const struct obs_source_info *info,
diff --git a/libobs/obs.h b/libobs/obs.h
index e54f5a059..8bbe8b2e5 100644
--- a/libobs/obs.h
+++ b/libobs/obs.h
@@ -33,6 +33,7 @@
 #include "obs-data.h"
 #include "obs-ui.h"
 #include "obs-properties.h"
+#include "obs-interaction.h"
 
 struct matrix4;
 
@@ -751,6 +752,27 @@ EXPORT void obs_source_add_child(obs_source_t parent, obs_source_t child);
  */
 EXPORT void obs_source_remove_child(obs_source_t parent, obs_source_t child);
 
+/** Sends a mouse down/up event to a source */
+EXPORT void obs_source_send_mouse_click(obs_source_t source,
+		const struct obs_mouse_event *event,
+		int32_t type, bool mouse_up,
+		uint32_t click_count);
+
+/** Sends a mouse move event to a source. */
+EXPORT void obs_source_send_mouse_move(obs_source_t source,
+		const struct obs_mouse_event *event, bool mouse_leave);
+
+/** Sends a mouse wheel event to a source */
+EXPORT void obs_source_send_mouse_wheel(obs_source_t source,
+		const struct obs_mouse_event *event, int x_delta, int y_delta);
+
+/** Sends a got-focus or lost-focus event to a source */
+EXPORT void obs_source_send_focus(obs_source_t source, bool focus);
+
+/** Sends a key up/down event to a source */
+EXPORT void obs_source_send_key_click(obs_source_t source,
+		const struct obs_key_event *event, bool key_up);
+
 /** Begins transition frame.  Sets all transitioning volume values to 0.0f. */
 EXPORT void obs_transition_begin_frame(obs_source_t transition);
 
-- 
GitLab