diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2010-09-13 00:45:13 +0200 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2010-09-13 01:34:03 +0200 |
commit | a94eaa30d4b799d60eefa2bdf2a8a6cdc9c2c60c (patch) | |
tree | 3b2c3b90ca1461c6d8388fc19465ec284cb0d794 | |
parent | aa564e7bc353f529f17568f49daef57b6138f3da (diff) |
mit shm
-rw-r--r-- | gtk/spice-widget.c | 104 |
1 files changed, 87 insertions, 17 deletions
diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c index 30e7919..868bb1f 100644 --- a/gtk/spice-widget.c +++ b/gtk/spice-widget.c @@ -1,6 +1,12 @@ #include "spice-widget.h" #include "vncdisplaykeymap.h" +#include <sys/ipc.h> +#include <sys/shm.h> + +#include <X11/Xlib.h> +#include <X11/extensions/XShm.h> + #include <gdk/gdkx.h> #define SPICE_DISPLAY_GET_PRIVATE(obj) \ @@ -17,9 +23,11 @@ struct spice_display { gint ww, wh, mx, my; bool convert; + bool have_mitshm; Display *dpy; XVisualInfo *vi; XImage *ximage; + XShmSegmentInfo *shminfo; GC gc; SpiceSession *session; @@ -29,11 +37,11 @@ struct spice_display { SpiceChannel *inputs; enum SpiceMouseMode mouse_mode; - int mouse_have_pointer; + bool mouse_have_pointer; - int keyboard_grab_enable; - int keyboard_grab_active; - int keyboard_have_focus; + bool keyboard_grab_enable; + bool keyboard_grab_active; + bool keyboard_have_focus; const guint16 const *keycode_map; size_t keycode_maplen; @@ -50,6 +58,8 @@ enum { static guint signals[SPICE_DISPLAY_LAST_SIGNAL]; #endif +static bool no_mitshm; + /* ---------------------------------------------------------------- */ static struct format_table { @@ -117,6 +127,7 @@ static void spice_display_init(SpiceDisplay *display) d->keycode_map = vnc_display_keymap_gdk2xtkbd_table(&d->keycode_maplen); + d->have_mitshm = true; d->keyboard_grab_enable = true; } @@ -203,13 +214,21 @@ static XVisualInfo *get_visual_default(GtkWidget *widget) &template, &found); } +static int catch_no_mitshm(Display * dpy, XErrorEvent * event) +{ + fprintf(stderr,"WARNING: MIT shared memory extention not available\n"); + no_mitshm = true; + return 0; +} + static int ximage_create(GtkWidget *widget) { - SpiceDisplay *display = SPICE_DISPLAY(widget); - spice_display *d = SPICE_DISPLAY_GET_PRIVATE(display); - GdkDrawable *window = gtk_widget_get_window(widget); - GdkDisplay *gtkdpy = gdk_drawable_get_display(window); - XGCValues gcval = { + SpiceDisplay *display = SPICE_DISPLAY(widget); + spice_display *d = SPICE_DISPLAY_GET_PRIVATE(display); + GdkDrawable *window = gtk_widget_get_window(widget); + GdkDisplay *gtkdpy = gdk_drawable_get_display(window); + void *old_handler = NULL; + XGCValues gcval = { .foreground = 0, .background = 0, }; @@ -228,6 +247,36 @@ static int ximage_create(GtkWidget *widget) d->gc = XCreateGC(d->dpy, gdk_x11_drawable_get_xid(window), GCForeground | GCBackground, &gcval); + + if (d->have_mitshm && d->shmid != -1) { + if (!XShmQueryExtension(d->dpy)) { + goto shm_fail; + } + no_mitshm = false; + old_handler = XSetErrorHandler(catch_no_mitshm); + d->shminfo = spice_new0(XShmSegmentInfo, 1); + d->ximage = XShmCreateImage(d->dpy, d->vi->visual, d->vi->depth, + ZPixmap, d->data, d->shminfo, d->width, d->height); + if (d->ximage == NULL) + goto shm_fail; + d->shminfo->shmaddr = d->data; + d->shminfo->shmid = d->shmid; + d->shminfo->readOnly = false; + XShmAttach(d->dpy, d->shminfo); + XSync(d->dpy, False); + shmctl(d->shmid, IPC_RMID, 0); + if (no_mitshm) + goto shm_fail; + XSetErrorHandler(old_handler); + fprintf(stderr, "%s: mitshm OK\n", __FUNCTION__); + return 0; + } + +shm_fail: + fprintf(stderr, "%s: mitshm FAIL\n", __FUNCTION__); + d->have_mitshm = false; + if (old_handler) + XSetErrorHandler(old_handler); d->ximage = XCreateImage(d->dpy, d->vi->visual, d->vi->depth, ZPixmap, 0, d->data, d->width, d->height, 32, d->stride); return 0; @@ -242,6 +291,11 @@ static void ximage_destroy(GtkWidget *widget) XDestroyImage(d->ximage); d->ximage = NULL; } + if (d->shminfo) { + XShmDetach(d->dpy, d->shminfo); + free(d->shminfo); + d->shminfo = NULL; + } if (d->gc) { XFreeGC(d->dpy, d->gc); d->gc = NULL; @@ -273,11 +327,20 @@ static gboolean expose_event(GtkWidget *widget, GdkEventExpose *expose) expose->area.x + expose->area.width <= d->mx + d->width && expose->area.y + expose->area.height <= d->my + d->height) { /* update is completely inside the guest screen -- blit it */ - XPutImage(d->dpy, gdk_x11_drawable_get_xid(window), - d->gc, d->ximage, - expose->area.x - d->mx, expose->area.y - d->my, - expose->area.x, expose->area.y, - expose->area.width, expose->area.height); + if (d->have_mitshm) { + XShmPutImage(d->dpy, gdk_x11_drawable_get_xid(window), + d->gc, d->ximage, + expose->area.x - d->mx, expose->area.y - d->my, + expose->area.x, expose->area.y, + expose->area.width, expose->area.height, + true); + } else { + XPutImage(d->dpy, gdk_x11_drawable_get_xid(window), + d->gc, d->ximage, + expose->area.x - d->mx, expose->area.y - d->my, + expose->area.x, expose->area.y, + expose->area.width, expose->area.height); + } } else { /* complete window update */ if (d->ww > d->width || d->wh > d->height) { @@ -296,9 +359,16 @@ static gboolean expose_event(GtkWidget *widget, GdkEventExpose *expose) d->ww - d->mx - d->height, d->wh); } } - XPutImage(d->dpy, gdk_x11_drawable_get_xid(window), - d->gc, d->ximage, - 0, 0, d->mx, d->my, d->width, d->height); + if (d->have_mitshm) { + XShmPutImage(d->dpy, gdk_x11_drawable_get_xid(window), + d->gc, d->ximage, + 0, 0, d->mx, d->my, d->width, d->height, + true); + } else { + XPutImage(d->dpy, gdk_x11_drawable_get_xid(window), + d->gc, d->ximage, + 0, 0, d->mx, d->my, d->width, d->height); + } } return true; |