--- /dev/null
+#include <stdexcept>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/XShm.h>
+#include <X11/Xutil.h>
+#include "display_private.h"
+#include "drawcontext.h"
+#include "window_private.h"
+
+using namespace std;
+
+namespace Msp {
+namespace Graphics {
+
+struct DrawContext::Private
+{
+ XImage *image;
+ bool use_shm;
+ XShmSegmentInfo shminfo;
+};
+
+DrawContext::DrawContext(Window &w):
+ display(w.get_display()),
+ window(w),
+ priv(new Private)
+{
+ DisplayHandle dpy = display.get_private().display;
+
+ priv->use_shm = XShmQueryExtension(dpy);
+
+ XWindowAttributes wa;
+ XGetWindowAttributes(dpy, window.get_private().window, &wa);
+
+ if(priv->use_shm)
+ {
+ priv->image = XShmCreateImage(dpy, wa.visual, wa.depth, ZPixmap, 0, &priv->shminfo, wa.width, wa.height);
+ if(!priv->image)
+ throw runtime_error("XShmCreateImage");
+
+ priv->shminfo.shmid = shmget(IPC_PRIVATE, priv->image->bytes_per_line*priv->image->height, IPC_CREAT|0666);
+ priv->shminfo.shmaddr=priv->image->data = reinterpret_cast<char *>(shmat(priv->shminfo.shmid, 0, 0));
+ priv->shminfo.readOnly = false;
+
+ XShmAttach(dpy, &priv->shminfo);
+
+ XSync(dpy, false);
+ display.check_error();
+ }
+ else
+ {
+ priv->image = XCreateImage(dpy, wa.visual, wa.depth, ZPixmap, 0, 0, wa.width, wa.height, 8, 0);
+ if(!priv->image)
+ throw runtime_error("XCreateImage");
+ priv->image->data = new char[priv->image->bytes_per_line*priv->image->height];
+ }
+}
+
+DrawContext::~DrawContext()
+{
+ if(priv->use_shm)
+ {
+ XShmDetach(display.get_private().display, &priv->shminfo);
+ shmdt(priv->shminfo.shmaddr);
+ shmctl(priv->shminfo.shmid, IPC_RMID, 0);
+ }
+
+ XDestroyImage(priv->image);
+
+ delete priv;
+}
+
+unsigned DrawContext::get_depth() const
+{
+ return priv->image->bits_per_pixel;
+}
+
+unsigned char *DrawContext::get_data()
+{
+ return reinterpret_cast<unsigned char *>(priv->image->data);
+}
+
+void DrawContext::update()
+{
+ DisplayHandle dpy = display.get_private().display;
+ WindowHandle wnd = window.get_private().window;
+
+ GC gc = XCreateGC(dpy, wnd, 0, 0);
+
+ if(priv->use_shm)
+ XShmPutImage(dpy, wnd, gc, priv->image, 0, 0, 0, 0, priv->image->width, priv->image->height, false);
+ else
+ XPutImage(dpy, wnd, gc, priv->image, 0, 0, 0, 0, priv->image->width, priv->image->height);
+
+ XFreeGC(dpy, gc);
+}
+
+} // namespace Graphics
+} // namespace Msp