[libav-devel] [PATCHv2] x11grab: fix drawing cursor in multi-screen setup

Antonio Ospite ao2 at ao2.it
Fri Sep 19 11:35:34 CEST 2014


The paint_mouse_pointer() code uses XFixes to retrieve the cursor
coordinates, but XFixes gives no information about what screen the
pointer is on; this results in always drawing the cursor on the captured
screen even if the mouse pointer was on another screen.

For example, when capturing from screen 1 (i.e. -f x11grab -i ":0.1")
the cursor was being drawn in the captured image even when the mouse
pointer was actually on screen 0, which is wrong and visually confusing.

Use XQueryPointer to check that the pointer is actually on the screen
which is being captured and if it is not, don't draw the cursor.

Also, don't follow the mouse or redraw the region when the pointer is on
another screen.

Signed-off-by: Antonio Ospite <ao2 at ao2.it>
---

Hey Luca, let me know if/when you manage to test this yourself, some more
feedback is always welcome.

Changes since v1:

  - rework the fix to cover the follow_mouse case

I will submit a patch to xcbgrab as soon as time permits.

Thanks,
   Antonio Ospite
   http://ao2.it

 libavdevice/x11grab.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/libavdevice/x11grab.c b/libavdevice/x11grab.c
index 03fd567..2a2a257 100644
--- a/libavdevice/x11grab.c
+++ b/libavdevice/x11grab.c
@@ -470,6 +470,9 @@ static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
     Window root;
     int64_t curtime, delay;
     struct timespec ts;
+    int pointer_x, pointer_y, _;
+    Window w;
+    Bool pointer_on_screen;
 
     /* Calculate the time of the next frame */
     s->time_frame += INT64_C(1000000);
@@ -495,14 +498,13 @@ static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
 
     screen = DefaultScreen(dpy);
     root   = RootWindow(dpy, screen);
-    if (follow_mouse) {
+    pointer_on_screen = XQueryPointer(dpy, root, &w, &w, &pointer_x,
+                                      &pointer_y, &_, &_, &_);
+    if (pointer_on_screen && follow_mouse) {
         int screen_w, screen_h;
-        int pointer_x, pointer_y, _;
-        Window w;
 
         screen_w = DisplayWidth(dpy, screen);
         screen_h = DisplayHeight(dpy, screen);
-        XQueryPointer(dpy, root, &w, &w, &pointer_x, &pointer_y, &_, &_, &_);
         if (follow_mouse == -1) {
             // follow the mouse, put it at center of grabbing region
             x_off += pointer_x - s->width / 2 - x_off;
@@ -529,7 +531,7 @@ static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
                         s->y_off - REGION_WIN_BORDER);
     }
 
-    if (s->show_region) {
+    if (pointer_on_screen && s->show_region) {
         if (s->region_win) {
             XEvent evt = { .type = NoEventMask };
             // Clean up the events, and do the initial draw or redraw.
@@ -551,7 +553,7 @@ static int x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
             av_log(s1, AV_LOG_INFO, "XGetZPixmap() failed\n");
     }
 
-    if (s->draw_mouse)
+    if (pointer_on_screen && s->draw_mouse)
         paint_mouse_pointer(image, s);
 
     return s->frame_size;
-- 
2.1.0



More information about the libav-devel mailing list