Browse Source

linux-capture: Add xcb cursor helper library

Add a new helper library to handle the mouse cursor using xcb.
Since porting the old library without either keeping legacy code or
breaking the api would have been non-trivial, this is added as a
completely separate implementation. Once all code is ported over to
use this library, the old one can be removed.
fryshorts 10 years ago
parent
commit
172a4d7a52

+ 2 - 0
plugins/linux-capture/CMakeLists.txt

@@ -20,6 +20,7 @@ include_directories(SYSTEM
 set(linux-capture_SOURCES
 	linux-capture.c
 	xcursor.c
+	xcursor-xcb.c
 	xhelpers.c
 	xshm-input.c
 	xcomposite-main.cpp
@@ -28,6 +29,7 @@ set(linux-capture_SOURCES
 )
 set(linux-capture_HEADERS
 	xcursor.h
+	xcursor-xcb.h
 	xhelpers.h
 	xcompcap-main.hpp
 	xcompcap-helper.hpp

+ 114 - 0
plugins/linux-capture/xcursor-xcb.c

@@ -0,0 +1,114 @@
+/*
+Copyright (C) 2014 by Leonhard Oelke <[email protected]>
+
+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/>.
+*/
+
+#include <stdint.h>
+#include <xcb/xfixes.h>
+
+#include <util/bmem.h>
+#include "xcursor-xcb.h"
+
+/*
+ * Create the cursor texture, either by updating if the new cursor has the same
+ * size or by creating a new texture if the size is different
+ */
+static void xcb_xcursor_create(xcb_xcursor_t *data,
+		xcb_xfixes_get_cursor_image_reply_t *xc)
+{
+	uint32_t *pixels = xcb_xfixes_get_cursor_image_cursor_image(xc);
+	if (!pixels)
+		return;
+
+	if (data->tex && data->last_height == xc->width &&
+			data->last_width == xc->height) {
+		gs_texture_set_image(data->tex, (const uint8_t *) pixels,
+			xc->width * sizeof(uint32_t), false);
+	} else {
+		if (data->tex)
+			gs_texture_destroy(data->tex);
+
+		data->tex = gs_texture_create(xc->width, xc->height,
+			GS_BGRA, 1, (const uint8_t **) &pixels, GS_DYNAMIC);
+	}
+
+	data->last_serial = xc->cursor_serial;
+	data->last_width  = xc->width;
+	data->last_height = xc->height;
+}
+
+/**
+ * We need to check for the xfixes version in order to initialize it ?
+ */
+xcb_xcursor_t *xcb_xcursor_init(xcb_connection_t *xcb)
+{
+	xcb_xcursor_t *data = bzalloc(sizeof(xcb_xcursor_t));
+
+	xcb_xfixes_query_version_cookie_t xfix_c;
+
+	xfix_c = xcb_xfixes_query_version_unchecked(xcb,
+			XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION);
+	free(xcb_xfixes_query_version_reply(xcb, xfix_c, NULL));
+
+	return data;
+}
+
+void xcb_xcursor_destroy(xcb_xcursor_t *data)
+{
+	if (data->tex)
+		gs_texture_destroy(data->tex);
+	bfree(data);
+}
+
+void xcb_xcursor_update(xcb_xcursor_t *data,
+		xcb_xfixes_get_cursor_image_reply_t *xc)
+{
+	if (!data || !xc)
+		return;
+
+	if (!data->tex || data->last_serial != xc->cursor_serial)
+		xcb_xcursor_create(data, xc);
+
+	data->x        = xc->x - data->x_org;
+	data->y        = xc->y - data->y_org;
+	data->x_render = data->x - xc->xhot;
+	data->y_render = data->y - xc->yhot;
+}
+
+void xcb_xcursor_render(xcb_xcursor_t *data)
+{
+	if (!data->tex)
+		return;
+
+	gs_effect_t *effect  = gs_get_effect();
+	gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image");
+	gs_effect_set_texture(image, data->tex);
+
+	gs_matrix_push();
+	gs_matrix_translate3f(data->x_render, data->y_render, 0.0f);
+
+	gs_enable_blending(true);
+	gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
+	gs_draw_sprite(data->tex, 0, 0, 0);
+
+	gs_matrix_pop();
+}
+
+void xcb_xcursor_offset(xcb_xcursor_t* data, const int x_org, const int y_org)
+{
+	data->x_org = x_org;
+	data->y_org = y_org;
+}
+

+ 79 - 0
plugins/linux-capture/xcursor-xcb.h

@@ -0,0 +1,79 @@
+/*
+Copyright (C) 2014 by Leonhard Oelke <[email protected]>
+
+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 <obs.h>
+#include <xcb/xfixes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+	unsigned int last_serial;
+	unsigned int last_width;
+	unsigned int last_height;
+	gs_texture_t *tex;
+
+	int          x;
+	int          y;
+	int          x_org;
+	int          y_org;
+	float        x_render;
+	float        y_render;
+} xcb_xcursor_t;
+
+/**
+ * Initializes the xcursor object
+ *
+ * @return NULL on error
+ */
+xcb_xcursor_t *xcb_xcursor_init(xcb_connection_t *xcb);
+
+/**
+ * Destroys the xcursor object
+ * @param data xcursor object
+ */
+void xcb_xcursor_destroy(xcb_xcursor_t *data);
+
+/**
+ * Update the cursor data
+ * @param data xcursor object
+ * @param xc xcb cursor image reply
+ *
+ * @note This needs to be executed within a valid render context
+ *
+ */
+void xcb_xcursor_update(xcb_xcursor_t *data,
+		xcb_xfixes_get_cursor_image_reply_t *xc);
+
+/**
+ * Draw the cursor
+ *
+ * This needs to be executed within a valid render context
+ */
+void xcb_xcursor_render(xcb_xcursor_t *data);
+
+/**
+ * Specify offset for the cursor
+ */
+void xcb_xcursor_offset(xcb_xcursor_t *data, const int x_org, const int y_org);
+
+#ifdef __cplusplus
+}
+#endif