Added initial Mouse pointer lib

Added library to get the mouse pointer with the XFixes
extension and draw it via a sprite.
master
fryshorts 2014-02-09 20:36:52 +01:00
parent 12e1855ebc
commit 820de55ae2
4 changed files with 148 additions and 24 deletions

View File

@ -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})

94
test/linux/xcursor.c Normal file
View File

@ -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);
}

36
test/linux/xcursor.h Normal file
View File

@ -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

View File

@ -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)