summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2010-09-13 00:45:13 +0200
committerGerd Hoffmann <kraxel@redhat.com>2010-09-13 01:34:03 +0200
commita94eaa30d4b799d60eefa2bdf2a8a6cdc9c2c60c (patch)
tree3b2c3b90ca1461c6d8388fc19465ec284cb0d794
parentaa564e7bc353f529f17568f49daef57b6138f3da (diff)
mit shm
-rw-r--r--gtk/spice-widget.c104
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;