From 172a4d7a5244efa36e44a547e4f42ff283aa7b87 Mon Sep 17 00:00:00 2001 From: fryshorts Date: Sun, 21 Dec 2014 21:33:10 +0100 Subject: [PATCH] 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. --- plugins/linux-capture/CMakeLists.txt | 2 + plugins/linux-capture/xcursor-xcb.c | 114 +++++++++++++++++++++++++++ plugins/linux-capture/xcursor-xcb.h | 79 +++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 plugins/linux-capture/xcursor-xcb.c create mode 100644 plugins/linux-capture/xcursor-xcb.h diff --git a/plugins/linux-capture/CMakeLists.txt b/plugins/linux-capture/CMakeLists.txt index a19716f09..3fb035025 100644 --- a/plugins/linux-capture/CMakeLists.txt +++ b/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 diff --git a/plugins/linux-capture/xcursor-xcb.c b/plugins/linux-capture/xcursor-xcb.c new file mode 100644 index 000000000..fb912181a --- /dev/null +++ b/plugins/linux-capture/xcursor-xcb.c @@ -0,0 +1,114 @@ +/* +Copyright (C) 2014 by Leonhard Oelke + +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 . +*/ + +#include +#include + +#include +#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; +} + diff --git a/plugins/linux-capture/xcursor-xcb.h b/plugins/linux-capture/xcursor-xcb.h new file mode 100644 index 000000000..69561b6aa --- /dev/null +++ b/plugins/linux-capture/xcursor-xcb.h @@ -0,0 +1,79 @@ +/* +Copyright (C) 2014 by Leonhard Oelke + +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 . +*/ + +#pragma once + +#include +#include + +#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