dx9screencapsrc: add "cursor" option to draw the cursor

Drawing is done via the GDI drawing functions. The cursor is
converted to a monochrome version before drawing. This is because
the GDI drawing functions seem to have undefined behavior with
cursor images including an alpha channel.

I could not find any other reliable way to draw these alpha
channel cursors without producing unwanted artifacts. These type
of cursors were introduced with Window Vista when run with it's
Aero theme.

Also adjust the cursor coordinates when capturing non-primary
screens via the "monitor" option.

https://bugzilla.gnome.org/show_bug.cgi?id=760172
This commit is contained in:
Florian Zwoch 2016-01-05 18:50:45 +01:00 committed by Sebastian Dröge
parent 898a62c1ac
commit 8960debc24
2 changed files with 49 additions and 0 deletions

View file

@ -61,6 +61,7 @@ enum
{
PROP_0,
PROP_MONITOR,
PROP_SHOW_CURSOR,
PROP_X_POS,
PROP_Y_POS,
PROP_WIDTH,
@ -121,6 +122,11 @@ gst_dx9screencapsrc_class_init (GstDX9ScreenCapSrcClass * klass)
"Which monitor to use (0 = 1st monitor and default)",
0, G_MAXINT, 0, G_PARAM_READWRITE));
g_object_class_install_property (go_class, PROP_SHOW_CURSOR,
g_param_spec_boolean ("cursor", "Show mouse cursor",
"Whether to show mouse cursor (default off)",
FALSE, G_PARAM_READWRITE));
g_object_class_install_property (go_class, PROP_X_POS,
g_param_spec_int ("x", "X",
"Horizontal coordinate of top left corner for the screen capture "
@ -161,6 +167,8 @@ gst_dx9screencapsrc_init (GstDX9ScreenCapSrc * src)
src->capture_h = 0;
src->monitor = 0;
src->show_cursor = FALSE;
src->monitor_info.cbSize = sizeof(MONITORINFO);
gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
@ -204,6 +212,9 @@ gst_dx9screencapsrc_set_property (GObject * object,
case PROP_MONITOR:
src->monitor = g_value_get_int (value);
break;
case PROP_SHOW_CURSOR:
src->show_cursor = g_value_get_boolean (value);
break;
case PROP_X_POS:
src->capture_x = g_value_get_int (value);
break;
@ -232,6 +243,9 @@ gst_dx9screencapsrc_get_property (GObject * object, guint prop_id,
case PROP_MONITOR:
g_value_set_int (value, src->monitor);
break;
case PROP_SHOW_CURSOR:
g_value_set_boolean (value, src->show_cursor);
break;
case PROP_X_POS:
g_value_set_int (value, src->capture_x);
break;
@ -366,6 +380,7 @@ gst_dx9screencapsrc_start (GstBaseSrc * bsrc)
{
GstDX9ScreenCapSrc *src = GST_DX9SCREENCAPSRC (bsrc);
D3DPRESENT_PARAMETERS d3dpp;
HMONITOR monitor;
HRESULT res;
src->frame_number = -1;
@ -395,6 +410,9 @@ gst_dx9screencapsrc_start (GstBaseSrc * bsrc)
if (FAILED (res))
return FALSE;
monitor = IDirect3D9_GetAdapterMonitor (g_d3d9, src->monitor);
GetMonitorInfo (monitor, &src->monitor_info);
return
SUCCEEDED (IDirect3DDevice9_CreateOffscreenPlainSurface (src->d3d9_device,
src->disp_mode.Width, src->disp_mode.Height, D3DFMT_A8R8G8B8,
@ -539,6 +557,35 @@ gst_dx9screencapsrc_create (GstPushSrc * push_src, GstBuffer ** buf)
return GST_FLOW_ERROR;
}
if (src->show_cursor) {
CURSORINFO ci;
ci.cbSize = sizeof (CURSORINFO);
GetCursorInfo (&ci);
if (ci.flags & CURSOR_SHOWING) {
ICONINFO ii;
HDC memDC;
GetIconInfo (ci.hCursor, &ii);
if (SUCCEEDED (IDirect3DSurface9_GetDC (src->surface, &memDC))) {
HCURSOR cursor = CopyImage (ci.hCursor, IMAGE_CURSOR, 0, 0,
LR_MONOCHROME | LR_DEFAULTSIZE);
DrawIcon (memDC,
ci.ptScreenPos.x - ii.xHotspot - src->monitor_info.rcMonitor.left,
ci.ptScreenPos.y - ii.yHotspot - src->monitor_info.rcMonitor.top,
cursor);
DestroyCursor (cursor);
IDirect3DSurface9_ReleaseDC (src->surface, memDC);
}
DeleteObject (ii.hbmColor);
DeleteObject (ii.hbmMask);
}
}
hres =
IDirect3DSurface9_LockRect (src->surface, &locked_rect, &(src->src_rect),
D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY);

View file

@ -55,6 +55,7 @@ struct _GstDX9ScreenCapSrc
gint capture_w;
gint capture_h;
guint monitor;
gboolean show_cursor;
/* Source pad frame rate */
gint rate_numerator;
@ -69,6 +70,7 @@ struct _GstDX9ScreenCapSrc
D3DDISPLAYMODE disp_mode;
IDirect3DSurface9 *surface;
IDirect3DDevice9 *d3d9_device;
MONITORINFO monitor_info;
};
struct _GstDX9ScreenCapSrcClass