summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-09-02 20:45:12 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2013-09-02 20:45:12 +0100
commitb955622cc25ab12305a572901a8ed0f23896dab3 (patch)
tree0fdd21e3e9969e05e6367b69718effc4b6287fbe /tools
parent5af9d69485a241156c343b67a741bc024e3f6edf (diff)
intel-virtual-ouptput: Filter and rate-limit cursor events
Make sure we are not responding to cursor motion on other screens, by checking for our root window. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'tools')
-rw-r--r--tools/virtual.c223
1 files changed, 133 insertions, 90 deletions
diff --git a/tools/virtual.c b/tools/virtual.c
index 1beccac4..120d9e85 100644
--- a/tools/virtual.c
+++ b/tools/virtual.c
@@ -64,6 +64,7 @@
struct display {
Display *dpy;
struct clone *clone;
+ struct context *ctx;
int damage_event, damage_error;
int xfixes_event, xfixes_error;
@@ -144,11 +145,18 @@ struct context {
int ndisplay;
int nfd;
+ int timer_active;
+
Atom singleton;
char command[1024];
int command_continuation;
};
+static inline int is_power_of_2(unsigned long n)
+{
+ return n && ((n & (n - 1)) == 0);
+}
+
static int xlib_vendor_is_xorg(Display *dpy)
{
const char *const vendor = ServerVendor(dpy);
@@ -249,6 +257,100 @@ can_use_shm(Display *dpy,
return has_shm;
}
+static int timerfd(int hz)
+{
+ struct itimerspec it;
+ int fd;
+
+ fd = timerfd_create(CLOCK_MONOTONIC_COARSE, TFD_NONBLOCK);
+ if (fd < 0)
+ fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
+ if (fd < 0)
+ return -ETIME;
+
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_nsec = 1000000000 / hz;
+ it.it_value = it.it_interval;
+ if (timerfd_settime(fd, 0, &it, NULL) < 0) {
+ close(fd);
+ return -ETIME;
+ }
+
+ return fd;
+}
+
+static int context_init(struct context *ctx)
+{
+ struct pollfd *pfd;
+
+ memset(ctx, 0, sizeof(*ctx));
+
+ ctx->pfd = malloc(2*sizeof(struct pollfd));
+ if (ctx->pfd == NULL)
+ return -ENOMEM;
+
+ ctx->clones = malloc(sizeof(struct clone));
+ if (ctx->clones == NULL)
+ return -ENOMEM;
+
+ ctx->display = malloc(sizeof(struct display));
+ if (ctx->display == NULL)
+ return -ENOMEM;
+
+ pfd = memset(&ctx->pfd[ctx->nfd++], 0, sizeof(struct pollfd));
+ pfd->fd = timerfd(60);
+ if (pfd->fd < 0)
+ return pfd->fd;
+ pfd->events = POLLIN;
+
+ return 0;
+}
+
+static void context_enable_timer(struct context *ctx)
+{
+ uint64_t count;
+
+ DBG(("%s timer active? %d\n", __func__, ctx->timer_active));
+
+ if (ctx->timer_active)
+ return;
+
+ read(ctx->timer, &count, sizeof(count));
+ ctx->timer_active = 1;
+}
+
+static int add_fd(struct context *ctx, int fd)
+{
+ struct pollfd *pfd;
+
+ if (fd < 0)
+ return fd;
+
+ if (is_power_of_2(ctx->nfd)) {
+ ctx->pfd = realloc(ctx->pfd, 2*ctx->nfd*sizeof(struct pollfd));
+ if (ctx->pfd == NULL)
+ return -ENOMEM;
+ }
+
+ pfd = memset(&ctx->pfd[ctx->nfd++], 0, sizeof(struct pollfd));
+ pfd->fd = fd;
+ pfd->events = POLLIN;
+ return 0;
+}
+
+
+static void display_mark_flush(struct display *display)
+{
+ DBG(("%s mark flush (flush=%d)\n",
+ DisplayString(display->dpy), display->flush));
+
+ if (display->flush)
+ return;
+
+ context_enable_timer(display->ctx);
+ display->flush = 1;
+}
+
static int mode_equal(const XRRModeInfo *a, const XRRModeInfo *b)
{
return (a->width == b->width &&
@@ -660,7 +762,7 @@ static int clone_init_xfer(struct clone *clone)
clone->damaged.y1 = clone->src.y;
clone->damaged.y2 = clone->src.y + clone->height;
- clone->dst.display->flush = 1;
+ display_mark_flush(clone->dst.display);
return 0;
}
@@ -925,6 +1027,8 @@ static void display_load_visible_cursor(struct display *display, XFixesCursorIma
static void display_cursor_move(struct display *display, int x, int y, int visible)
{
+ DBG(("%s cursor moved (visible=%d, (%d, %d))\n",
+ DisplayString(display->dpy), visible, x, y));
display->cursor_moved++;
display->cursor_visible += visible;
if (visible) {
@@ -950,7 +1054,7 @@ static void display_flush_cursor(struct display *display)
}
XWarpPointer(display->dpy, None, display->root, 0, 0, 0, 0, x, y);
- display->flush = 1;
+ display_mark_flush(display);
cursor = None;
if (display->cursor_visible)
@@ -1132,7 +1236,7 @@ static void put_dst(struct clone *c, const XRectangle *clip)
c->dst.serial = 0;
}
- c->dst.display->flush = 1;
+ display_mark_flush(c->dst.display);
}
static int clone_paint(struct clone *c)
@@ -1204,10 +1308,17 @@ static void record_callback(XPointer closure, XRecordInterceptData *data)
struct context *ctx = (struct context *)closure;
int n;
+ DBG(("%s\n", __func__));
+
if (data->category == XRecordFromServer) {
const xEvent *e = (const xEvent *)data->data;
- if (e->u.u.type == MotionNotify) {
+ DBG(("%s -- from server, event type %d, root %ld (ours? %d)\n",
+ __func__, e->u.u.type, (long)e->u.keyButtonPointer.root,
+ ctx->display->root == e->u.keyButtonPointer.root));
+
+ if (e->u.u.type == MotionNotify &&
+ e->u.keyButtonPointer.root == ctx->display->root) {
for (n = 0; n < ctx->nclone; n++)
clone_move_cursor(&ctx->clones[n],
e->u.keyButtonPointer.rootX,
@@ -1447,11 +1558,6 @@ static int clone_init_depth(struct clone *clone)
return 0;
}
-static inline int is_power_of_2(unsigned long n)
-{
- return n && ((n & (n - 1)) == 0);
-}
-
static int add_display(struct context *ctx, Display *dpy)
{
struct display *display;
@@ -1479,6 +1585,7 @@ static int add_display(struct context *ctx, Display *dpy)
display = memset(&ctx->display[ctx->ndisplay++], 0, sizeof(struct display));
display->dpy = dpy;
+ display->ctx = ctx;
display->root = DefaultRootWindow(dpy);
display->depth = DefaultDepth(dpy, DefaultScreen(dpy));
@@ -1580,74 +1687,6 @@ static int display_init_damage(struct display *display)
return 0;
}
-static int timerfd(int hz)
-{
- struct itimerspec it;
- int fd;
-
- fd = timerfd_create(CLOCK_MONOTONIC_COARSE, TFD_NONBLOCK);
- if (fd < 0)
- fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
- if (fd < 0)
- return -ETIME;
-
- it.it_interval.tv_sec = 0;
- it.it_interval.tv_nsec = 1000000000 / hz;
- it.it_value = it.it_interval;
- if (timerfd_settime(fd, 0, &it, NULL) < 0) {
- close(fd);
- return -ETIME;
- }
-
- return fd;
-}
-
-static int context_init(struct context *ctx)
-{
- struct pollfd *pfd;
-
- memset(ctx, 0, sizeof(*ctx));
-
- ctx->pfd = malloc(2*sizeof(struct pollfd));
- if (ctx->pfd == NULL)
- return -ENOMEM;
-
- ctx->clones = malloc(sizeof(struct clone));
- if (ctx->clones == NULL)
- return -ENOMEM;
-
- ctx->display = malloc(sizeof(struct display));
- if (ctx->display == NULL)
- return -ENOMEM;
-
- pfd = memset(&ctx->pfd[ctx->nfd++], 0, sizeof(struct pollfd));
- pfd->fd = timerfd(60);
- if (pfd->fd < 0)
- return pfd->fd;
- pfd->events = POLLIN;
-
- return 0;
-}
-
-static int add_fd(struct context *ctx, int fd)
-{
- struct pollfd *pfd;
-
- if (fd < 0)
- return fd;
-
- if (is_power_of_2(ctx->nfd)) {
- ctx->pfd = realloc(ctx->pfd, 2*ctx->nfd*sizeof(struct pollfd));
- if (ctx->pfd == NULL)
- return -ENOMEM;
- }
-
- pfd = memset(&ctx->pfd[ctx->nfd++], 0, sizeof(struct pollfd));
- pfd->fd = fd;
- pfd->events = POLLIN;
- return 0;
-}
-
static void display_init_randr_hpd(struct display *display)
{
int major, minor;
@@ -2148,7 +2187,7 @@ static void display_flush_send(struct display *display)
XSendEvent(display->dpy, display->root, False, 0, (XEvent *)&e);
display->send = 0;
- display->flush = 1;
+ display_mark_flush(display);
}
static void display_flush(struct display *display)
@@ -2203,7 +2242,6 @@ int main(int argc, char **argv)
struct context ctx;
const char *src_name = NULL;
uint64_t count;
- int enable_timer = 0;
int daemonize = 1, bumblebee = 0, all = 0, singleton = 1;
int i, ret, open, fail;
@@ -2346,8 +2384,8 @@ int main(int argc, char **argv)
XEvent e;
int reconfigure = 0;
- DBG(("polling - enable timer? %d, nfd=%d\n", enable_timer, ctx.nfd));
- ret = poll(ctx.pfd + !enable_timer, ctx.nfd - !enable_timer, -1);
+ DBG(("polling - enable timer? %d, nfd=%d\n", ctx.timer_active, ctx.nfd));
+ ret = poll(ctx.pfd + !ctx.timer_active, ctx.nfd - !ctx.timer_active, -1);
if (ret <= 0)
break;
@@ -2368,12 +2406,14 @@ int main(int argc, char **argv)
de->area.x, de->area.y, de->area.width, de->area.height));
for (i = 0; i < ctx.nclone; i++)
clone_damage(&ctx.clones[i], &de->area);
- if (!enable_timer)
- enable_timer = read(ctx.timer, &count, sizeof(count)) > 0;
+ context_enable_timer(&ctx);
damaged++;
} else if (e.type == ctx.display->xfixes_event + XFixesCursorNotify) {
XFixesCursorImage *cur;
+ DBG(("%s cursor changed\n",
+ DisplayString(ctx.display->dpy)));
+
cur = XFixesGetCursorImage(ctx.display->dpy);
if (cur == NULL)
continue;
@@ -2386,8 +2426,7 @@ int main(int argc, char **argv)
DBG(("%s screen changed (reconfigure pending? %d)\n",
DisplayString(ctx.display->dpy), reconfigure));
reconfigure = 1;
- if (!enable_timer)
- enable_timer = read(ctx.timer, &count, sizeof(count)) > 0;
+ context_enable_timer(&ctx);
} else if (e.type == PropertyNotify) {
XPropertyEvent *pe = (XPropertyEvent *)&e;
if (pe->atom == ctx.singleton) {
@@ -2397,6 +2436,9 @@ int main(int argc, char **argv)
} else if (e.type == ClientMessage) {
XClientMessageEvent *cme;
+ DBG(("%s client message\n",
+ DisplayString(ctx.display->dpy)));
+
cme = (XClientMessageEvent *)&e;
if (cme->message_type != ctx.singleton)
continue;
@@ -2447,17 +2489,18 @@ int main(int argc, char **argv)
for (i = 0; i < ctx.nclone; i++)
clone_update(&ctx.clones[i]);
- if (enable_timer && read(ctx.timer, &count, sizeof(count)) > 0 && count > 0) {
+ if (ctx.timer_active && read(ctx.timer, &count, sizeof(count)) > 0 && count > 0) {
+ DBG(("%s timer expired (count=%ld)\n", DisplayString(ctx.display->dpy), (long)count));
ret = 0;
for (i = 0; i < ctx.nclone; i++)
ret |= clone_paint(&ctx.clones[i]);
- enable_timer = ret != 0;
+ ctx.timer_active = ret != 0;
+
+ for (i = 0; i < ctx.ndisplay; i++)
+ display_flush(&ctx.display[i]);
}
XPending(ctx.record);
-
- for (i = 0; i < ctx.ndisplay; i++)
- display_flush(&ctx.display[i]);
}
return EINVAL;