Added initial Mouse pointer lib
Added library to get the mouse pointer with the XFixes extension and draw it via a sprite.master
parent
12e1855ebc
commit
820de55ae2
|
@ -3,14 +3,15 @@ project(linux)
|
|||
find_package(X11 REQUIRED)
|
||||
|
||||
include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/libobs")
|
||||
#include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/libobs-opengl")
|
||||
|
||||
set(linux_SOURCES
|
||||
linux.c
|
||||
xcursor.c
|
||||
xshm-input.c
|
||||
)
|
||||
set(linux_HEADERS
|
||||
linux.h
|
||||
xcursor.h
|
||||
xshm-input.h
|
||||
)
|
||||
|
||||
|
@ -22,8 +23,7 @@ target_link_libraries(linux
|
|||
libobs
|
||||
${X11_LIBRARIES}
|
||||
${X11_XShm_LIB}
|
||||
${X11_Xfixes_LIB}
|
||||
)
|
||||
|
||||
install_obs_plugin(linux)
|
||||
|
||||
#obs_fixup_install_target(xshm-input PATH ${Libx264_LIBRARIES})
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include "xcursor.h"
|
||||
|
||||
uint32_t *xcursor_pixels(XFixesCursorImage *xc) {
|
||||
int size = xc->width * xc->height;
|
||||
uint32_t *pixels = bmalloc(size * 4);
|
||||
|
||||
// pixel data from XFixes is defined as unsigned long ...
|
||||
// TODO: check why everybody is making a fuss about this
|
||||
for (int i = 0; i < size; ++i)
|
||||
pixels[i] = (uint32_t) xc->pixels[i];
|
||||
|
||||
return pixels;
|
||||
}
|
||||
|
||||
void xcursor_create(xcursor_t *data, XFixesCursorImage *xc) {
|
||||
// get cursor pixel data
|
||||
uint32_t *pixels = xcursor_pixels(xc);
|
||||
|
||||
// if the cursor has the same size as the last one we can simply update
|
||||
if (data->tex
|
||||
&& data->last_height == xc->width
|
||||
&& data->last_width == xc->height) {
|
||||
texture_setimage(data->tex, (void **) pixels, xc->width * 4, False);
|
||||
}
|
||||
else {
|
||||
if (data->tex)
|
||||
texture_destroy(data->tex);
|
||||
|
||||
data->tex = gs_create_texture(
|
||||
xc->width, xc->height,
|
||||
GS_RGBA, 1,
|
||||
(const void **) &pixels,
|
||||
GS_DYNAMIC
|
||||
);
|
||||
}
|
||||
bfree(pixels);
|
||||
|
||||
// set some data
|
||||
data->last_serial = xc->cursor_serial;
|
||||
data->last_width = xc->width;
|
||||
data->last_height = xc->height;
|
||||
}
|
||||
|
||||
xcursor_t *xcursor_init(Display *dpy) {
|
||||
xcursor_t *data = bmalloc(sizeof(xcursor_t));
|
||||
memset(data, 0, sizeof(xcursor_t));
|
||||
|
||||
data->dpy = dpy;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void xcursor_destroy(xcursor_t *data) {
|
||||
if (data->tex)
|
||||
texture_destroy(data->tex);
|
||||
bfree(data);
|
||||
}
|
||||
|
||||
void xcursor_render(xcursor_t *data) {
|
||||
// get cursor data
|
||||
XFixesCursorImage *xc = XFixesGetCursorImage(data->dpy);
|
||||
|
||||
// update cursor if necessary
|
||||
if (!data->tex || data->last_serial != xc->cursor_serial)
|
||||
xcursor_create(data, xc);
|
||||
|
||||
// TODO: why do i need effects ?
|
||||
effect_t effect = gs_geteffect();
|
||||
eparam_t diffuse = effect_getparambyname(effect, "diffuse");
|
||||
|
||||
effect_settexture(effect, diffuse, data->tex);
|
||||
|
||||
gs_matrix_push();
|
||||
|
||||
// move cursor to the right position
|
||||
gs_matrix_translate3f(
|
||||
-1.0 * (xc->x - xc->xhot),
|
||||
-1.0 * (xc->y - xc->yhot),
|
||||
0
|
||||
);
|
||||
|
||||
// blend cursor
|
||||
gs_enable_blending(True);
|
||||
gs_blendfunction(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
|
||||
gs_draw_sprite(data->tex, 0, 0, 0);
|
||||
gs_enable_blending(False);
|
||||
|
||||
gs_matrix_pop();
|
||||
|
||||
XFree(xc);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include <obs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
Display *dpy;
|
||||
unsigned long last_serial;
|
||||
short unsigned int last_width;
|
||||
short unsigned int last_height;
|
||||
texture_t tex;
|
||||
} xcursor_t;
|
||||
|
||||
/**
|
||||
* Initializes the xcursor object
|
||||
*/
|
||||
xcursor_t *xcursor_init(Display *dpy);
|
||||
|
||||
/**
|
||||
* Destroys the xcursor object
|
||||
*/
|
||||
void xcursor_destroy(xcursor_t *data);
|
||||
|
||||
/**
|
||||
* Draw the cursor
|
||||
*
|
||||
* This needs to be executed within a valid render context
|
||||
*/
|
||||
void xcursor_render(xcursor_t *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -4,6 +4,7 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#include "xcursor.h"
|
||||
#include "xshm-input.h"
|
||||
|
||||
struct xshm_data {
|
||||
|
@ -17,6 +18,7 @@ struct xshm_data {
|
|||
XShmSegmentInfo shm_info;
|
||||
XImage *image;
|
||||
texture_t texture;
|
||||
xcursor_t *cursor;
|
||||
};
|
||||
|
||||
const char* xshm_input_getname(const char* locale)
|
||||
|
@ -53,45 +55,36 @@ struct xshm_data *xshm_input_create(const char *settings, obs_source_t source)
|
|||
if (!data->image)
|
||||
goto fail;
|
||||
|
||||
printf("Image size: %dx%d\n", data->image->width, data->image->height);
|
||||
|
||||
// create shared memory
|
||||
data->shm_info.shmid = shmget(IPC_PRIVATE, data->image->bytes_per_line *
|
||||
data->image->height, IPC_CREAT | 0700);
|
||||
if (data->shm_info.shmid < 0) {
|
||||
printf("Failed to create shared memory !\n");
|
||||
if (data->shm_info.shmid < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// attach shared memory
|
||||
data->shm_info.shmaddr = data->image->data
|
||||
= (char *) shmat(data->shm_info.shmid, 0, 0);
|
||||
if (data->shm_info.shmaddr == (char *) -1) {
|
||||
printf("Failed to attach shared memory !\n");
|
||||
if (data->shm_info.shmaddr == (char *) -1)
|
||||
goto fail;
|
||||
}
|
||||
// set shared memory as read only
|
||||
data->shm_info.readOnly = False;
|
||||
|
||||
// attach shm
|
||||
if (!XShmAttach(data->dpy, &data->shm_info)) {
|
||||
printf("Failed to attach to XShm !\n");
|
||||
if (!XShmAttach(data->dpy, &data->shm_info))
|
||||
goto fail;
|
||||
}
|
||||
data->shm_attached = 1;
|
||||
|
||||
// get image
|
||||
if (!XShmGetImage(data->dpy, data->root_window, data->image,
|
||||
0, 0, AllPlanes)) {
|
||||
printf("Failed to get image data !\n");
|
||||
0, 0, AllPlanes))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// create obs texture
|
||||
gs_entercontext(obs_graphics());
|
||||
data->texture = gs_create_texture(data->width, data->height, GS_BGRA, 1,
|
||||
(const void**) &data->image->data,
|
||||
GS_DYNAMIC);
|
||||
data->cursor = xcursor_init(data->dpy);
|
||||
gs_leavecontext();
|
||||
|
||||
if (!data->texture)
|
||||
|
@ -111,6 +104,7 @@ void xshm_input_destroy(struct xshm_data *data)
|
|||
gs_entercontext(obs_graphics());
|
||||
|
||||
texture_destroy(data->texture);
|
||||
xcursor_destroy(data->cursor);
|
||||
|
||||
gs_leavecontext();
|
||||
|
||||
|
@ -148,18 +142,18 @@ uint32_t xshm_input_get_output_flags(struct xshm_data *data)
|
|||
void xshm_input_video_render(struct xshm_data *data, obs_source_t filter_target)
|
||||
{
|
||||
// update texture
|
||||
if (!XShmGetImage(data->dpy, data->root_window, data->image,
|
||||
0, 0, AllPlanes)) {
|
||||
printf("Failed to get image !\n");
|
||||
}
|
||||
XShmGetImage(data->dpy, data->root_window, data->image, 0, 0, AllPlanes);
|
||||
texture_setimage(data->texture, (void *) data->image->data,
|
||||
data->width * 4, False);
|
||||
|
||||
//effect_t effect = gs_geteffect();
|
||||
//eparam_t diffuse = effect_getparambyname(effect, "diffuse");
|
||||
effect_t effect = gs_geteffect();
|
||||
eparam_t diffuse = effect_getparambyname(effect, "diffuse");
|
||||
|
||||
//effect_settexture(effect, diffuse, data->texture);
|
||||
effect_settexture(effect, diffuse, data->texture);
|
||||
gs_draw_sprite(data->texture, 0, 0, 0);
|
||||
|
||||
// render the cursor
|
||||
xcursor_render(data->cursor);
|
||||
}
|
||||
|
||||
uint32_t xshm_input_getwidth(struct xshm_data *data)
|
||||
|
|
Loading…
Reference in New Issue