diff --git a/gui-daemon/xside.c b/gui-daemon/xside.c index 9b4e0cdb..ce72d9b6 100644 --- a/gui-daemon/xside.c +++ b/gui-daemon/xside.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -386,6 +387,7 @@ static void mkghandles(Ghandles * g) char tray_sel_atom_name[64]; int ev_base, err_base; /* ignore */ XWindowAttributes attr; + int i; g->display = XOpenDisplay(NULL); if (!g->display) { @@ -459,6 +461,21 @@ static void mkghandles(Ghandles * g) } /* ignore possible errors */ fchmod(g->inter_appviewer_lock_fd, 0666); + + g->cursors = malloc(sizeof(Cursor) * XC_num_glyphs); + if (!g->cursors) { + perror("malloc"); + exit(1); + } + for (i = 0; i < XC_num_glyphs; i++) { + /* X font cursors have even numbers from 0 up to XC_num_glyphs. + * Fill the rest with None. + */ + if (i % 2 == 0) + g->cursors[i] = XCreateFontCursor(g->display, i); + else + g->cursors[i] = None; + } } /* reload X server parameters, especially after monitor/screen layout change */ @@ -798,6 +815,42 @@ static int evaluate_clipboard_policy(Ghandles * g) { return WEXITSTATUS(status) == 0; } +/* handle VM message: MSG_CURSOR */ +static void handle_cursor(Ghandles *g, struct windowdata *vm_window) +{ + struct msg_cursor untrusted_msg; + int cursor_id; + Cursor cursor; + + read_struct(g->vchan, untrusted_msg); + /* sanitize start */ + if (untrusted_msg.cursor & CURSOR_X11) { + VERIFY(untrusted_msg.cursor < CURSOR_X11_MAX); + cursor_id = untrusted_msg.cursor & ~CURSOR_X11; + } else { + VERIFY(untrusted_msg.cursor == CURSOR_DEFAULT); + cursor_id = -1; + } + /* sanitize end */ + + if (g->log_level > 0) + fprintf(stderr, "handle_cursor, cursor = 0x%x\n", + untrusted_msg.cursor); + + if (cursor_id < 0) + cursor = None; + else { + /* + * Should be true if CURSOR_X11_MAX == CURSOR_X11 + XC_num_glyphs, + * but we don't want a protocol constant to depend on X headers. + */ + assert(cursor_id < XC_num_glyphs); + + cursor = g->cursors[cursor_id]; + } + XDefineCursor(g->display, vm_window->local_winid, cursor); +} + /* check and handle guid-special keys * currently only for inter-vm clipboard copy */ @@ -2660,6 +2713,9 @@ static void handle_message(Ghandles * g) case MSG_WINDOW_DUMP: handle_window_dump(g, vm_window, untrusted_hdr.untrusted_len); break; + case MSG_CURSOR: + handle_cursor(g, vm_window); + break; default: fprintf(stderr, "got unknown msg type %d\n", type); exit(1); diff --git a/gui-daemon/xside.h b/gui-daemon/xside.h index 7971bb65..3f683c1d 100644 --- a/gui-daemon/xside.h +++ b/gui-daemon/xside.h @@ -190,6 +190,7 @@ struct _global_handles { int trayicon_border; /* position of trayicon border - 0 - no border, 1 - at the edges, 2 - 1px from the edges */ bool trayicon_tint_reduce_saturation; /* reduce trayicon saturation by 50% (available only for "tint" mode) */ bool trayicon_tint_whitehack; /* replace white pixels with almost-white 0xfefefe (available only for "tint" mode) */ + Cursor *cursors; /* preloaded cursors (using XCreateFontCursor) */ }; typedef struct _global_handles Ghandles;