summaryrefslogtreecommitdiff
path: root/plugingui/window.cc
diff options
context:
space:
mode:
Diffstat (limited to 'plugingui/window.cc')
-rw-r--r--plugingui/window.cc409
1 files changed, 404 insertions, 5 deletions
diff --git a/plugingui/window.cc b/plugingui/window.cc
index db302a5..3c6a816 100644
--- a/plugingui/window.cc
+++ b/plugingui/window.cc
@@ -26,19 +26,418 @@
*/
#include "window.h"
-#include "globalcontext.h"
-#include "widgetcontext.h"
-
#include "painter.h"
-_Window::_Window(GlobalContext *gctx) : Widget(gctx, 0)
+#include "img_back.h"
+
+#ifdef X11
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#endif/*X11*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+
+GUI::Window *gwindow = NULL;
+
+#ifdef WIN32
+// Delared in eventhandler.cc
+LRESULT CALLBACK dialogProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
+#endif/*WIN32*/
+
+GUI::Window::Window(GlobalContext *gctx)
+ : Widget(NULL), wpixbuf(640, 200)
+{
+ gwindow = this;
+
+ this->gctx = gctx;
+
+ _x = _y = 100;
+ _width = wpixbuf.width;
+ _height = wpixbuf.height;
+
+ refcount = 0;
+ _keyboardFocus = this;
+ _buttonDownFocus = NULL;
+
+#ifdef X11
+ buffer = NULL;
+
+ // Get some colors
+ int blackColor = BlackPixel(gctx->display, DefaultScreen(gctx->display));
+
+ ::Window w = DefaultRootWindow(gctx->display);
+
+ // Create the window
+ xwindow = XCreateSimpleWindow(gctx->display,
+ w, _x, _y, _width, _height, 0,
+ blackColor, blackColor);
+
+ XSelectInput(gctx->display, xwindow,
+ StructureNotifyMask |
+ PointerMotionMask |
+ ButtonPressMask |
+ ButtonReleaseMask |
+ KeyPressMask |
+ KeyReleaseMask|
+ ExposureMask |
+ StructureNotifyMask |
+ SubstructureNotifyMask);
+
+ // register interest in the delete window message
+ gctx->wmDeleteMessage = XInternAtom(gctx->display, "WM_DELETE_WINDOW", false);
+ XSetWMProtocols(gctx->display, xwindow, &gctx->wmDeleteMessage, 1);
+
+ // "Map" the window (that is, make it appear on the screen)
+ XMapWindow(gctx->display, xwindow);
+
+ // Create a "Graphics Context"
+ gc = XCreateGC(gctx->display, xwindow, 0, NULL);
+#endif/*X11*/
+
+#ifdef WIN32
+ WNDCLASSEX wcex;
+ WNDID wndId;
+
+ gctx->m_hwnd = 0;
+ gctx->m_className = NULL;
+
+ memset(&wcex, 0, sizeof(wcex));
+
+ //Time to register a window class.
+ //Generic flags and everything. cbWndExtra is the size of a pointer to an
+ // object - we need this in the wndproc handler.
+
+ wcex.cbSize = sizeof(WNDCLASSEX);
+ wcex.style = 0;//class_style;
+ wcex.lpfnWndProc = (WNDPROC)dialogProc;
+ wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
+ // Set data:
+ wcex.cbWndExtra = sizeof(EventHandler*); // Size of data.
+ wcex.hInstance = GetModuleHandle(NULL);
+
+ // if(ex_style && WS_EX_TRANSPARENT == WS_EX_TRANSPARENT) {
+ // wcex.hbrBackground = NULL;
+ // } else {
+ wcex.hbrBackground = NULL;//(HBRUSH) COLOR_BACKGROUND + 1;
+ // }
+
+ wcex.lpszClassName = gctx->m_className = strdup("DrumGizmoClass");
+
+ RegisterClassEx(&wcex);
+
+ /*
+ if(parent) {
+ style = style | WS_CHILD;
+ wndId = parent->getWndId();
+ } else {
+ */
+ //style = style | WS_OVERLAPPEDWINDOW;
+ wndId = 0;
+ // }
+
+ gctx->m_hwnd = CreateWindowEx(NULL/*ex_style*/, gctx->m_className,
+ "DGBasisWidget",
+ (WS_OVERLAPPEDWINDOW | WS_VISIBLE),
+ _x, _y, _width, _height, wndId, NULL,
+ GetModuleHandle(NULL), NULL);
+
+ SetWindowLong(gctx->m_hwnd, GWL_USERDATA, (LONG)gctx->eventhandler);
+#endif/*WIN32*/
+}
+
+GUI::Window::~Window()
+{
+#ifdef X11
+ XDestroyWindow(gctx->display, xwindow);
+ //gctx->widgets.erase(window);
+#endif/*X11*/
+
+#ifdef WIN32
+ UnregisterClass(gctx->m_className, GetModuleHandle(NULL));
+ free(gctx->m_className);
+#endif/*WIN32*/
+}
+
+void GUI::Window::repaintEvent(GUI::RepaintEvent *e)
+{
+ Painter p(this);
+ p.drawImage(0, 0, (struct __img__*)&img_back);
+}
+
+void GUI::Window::resize(size_t width, size_t height)
+{
+ // printf("Window::resize(%d, %d)\n", width, height);
+
+#ifdef X11
+ XResizeWindow(gctx->display, xwindow, width, height);
+#endif/*X11*/
+
+#ifdef WIN32
+ SetWindowPos(gctx->m_hwnd, NULL, -1, -1, (int)width, (int)height + 27,
+ SWP_NOMOVE);
+#endif/*WIN32*/
+
+ Widget::resize(width, height);
+}
+
+void GUI::Window::move(size_t x, size_t y)
+{
+#ifdef X11
+ XMoveWindow(gctx->display, xwindow, x, y);
+#endif/*X11*/
+
+#ifdef WIN32
+ SetWindowPos(gctx->m_hwnd, NULL, (int)x, (int)y, -1, -1, SWP_NOSIZE);
+#endif/*WIN32*/
+
+ // Make sure widget corrds are updated.
+ Widget::move(x, y);
+}
+
+size_t GUI::Window::x() { return _x; }
+size_t GUI::Window::y() { return _y; }
+size_t GUI::Window::width() { return _width; }
+size_t GUI::Window::height() { return _height; }
+
+void GUI::Window::show()
{
+ repaint_r(NULL);
+#ifdef X11
+ XMapWindow(gctx->display, xwindow);
+#endif/*X11*/
+
+#ifdef WIN32
+ ShowWindow(gctx->m_hwnd, SW_SHOW);
+#endif/*WIN32*/
}
-void _Window::repaint(RepaintEvent *e)
+void GUI::Window::hide()
{
+#ifdef X11
+ XUnmapWindow(gctx->display, xwindow);
+#endif/*X11*/
+
+#ifdef WIN32
+ ShowWindow(gctx->m_hwnd, SW_HIDE);
+#endif/*WIN32*/
}
+GUI::Window *GUI::Window::window()
+{
+ return this;
+}
+
+void GUI::Window::beginPaint()
+{
+ refcount++;
+ // printf("beginPaint(%d)\n", refcount);
+}
+
+void GUI::Window::endPaint()
+{
+ // printf("endPaint(%d)\n", refcount);
+ if(refcount) refcount--;
+
+ if(!refcount) {
+ updateBuffer();
+#ifdef X11
+ //XSendEvent(gctx->display, window, false, ExposureMask, event_send)
+#endif/*X11*/
+ redraw();
+ }
+}
+
+#ifdef X11
+static int get_byte_order (void)
+{
+ union {
+ char c[sizeof(short)];
+ short s;
+ } order;
+
+ order.s = 1;
+ if ((1 == order.c[0])) {
+ return LSBFirst;
+ } else {
+ return MSBFirst;
+ }
+}
+
+static XImage *create_image_from_buffer(Display *dis, int screen,
+ unsigned char *buf,
+ int width, int height)
+{
+ int depth;
+ XImage *img = NULL;
+ Visual *vis;
+ double rRatio;
+ double gRatio;
+ double bRatio;
+ int outIndex = 0;
+ int i;
+ int numBufBytes = (3 * (width * height));
+
+ depth = DefaultDepth(dis, screen);
+ vis = DefaultVisual(dis, screen);
+
+ rRatio = vis->red_mask / 255.0;
+ gRatio = vis->green_mask / 255.0;
+ bRatio = vis->blue_mask / 255.0;
+
+ if (depth >= 24) {
+ size_t numNewBufBytes = (4 * (width * height));
+ u_int32_t *newBuf = (u_int32_t *)malloc (numNewBufBytes);
+
+ for (i = 0; i < numBufBytes; ++i) {
+ unsigned int r, g, b;
+ r = (buf[i] * rRatio);
+ ++i;
+ g = (buf[i] * gRatio);
+ ++i;
+ b = (buf[i] * bRatio);
+
+ r &= vis->red_mask;
+ g &= vis->green_mask;
+ b &= vis->blue_mask;
+
+ newBuf[outIndex] = r | g | b;
+ ++outIndex;
+ }
+
+ img = XCreateImage (dis,
+ CopyFromParent, depth,
+ ZPixmap, 0,
+ (char *) newBuf,
+ width, height,
+ 32, 0
+ );
+
+ } else if (depth >= 15) {
+ size_t numNewBufBytes = (2 * (width * height));
+ u_int16_t *newBuf = (u_int16_t *)malloc (numNewBufBytes);
+
+ for (i = 0; i < numBufBytes; ++i) {
+ unsigned int r, g, b;
+
+ r = (buf[i] * rRatio);
+ ++i;
+ g = (buf[i] * gRatio);
+ ++i;
+ b = (buf[i] * bRatio);
+
+ r &= vis->red_mask;
+ g &= vis->green_mask;
+ b &= vis->blue_mask;
+
+ newBuf[outIndex] = r | g | b;
+ ++outIndex;
+ }
+
+ img = XCreateImage(dis, CopyFromParent, depth, ZPixmap, 0, (char *) newBuf,
+ width, height, 16, 0);
+ } else {
+ //fprintf (stderr, "This program does not support displays with a depth less than 15.");
+ return NULL;
+ }
+
+ XInitImage (img);
+ /*Set the client's byte order, so that XPutImage knows what to do with the data.*/
+ /*The default in a new X image is the server's format, which may not be what we want.*/
+ if ((LSBFirst == get_byte_order ())) {
+ img->byte_order = LSBFirst;
+ } else {
+ img->byte_order = MSBFirst;
+ }
+
+ /*The bitmap_bit_order doesn't matter with ZPixmap images.*/
+ img->bitmap_bit_order = MSBFirst;
+
+ return img;
+}
+#endif/*X11*/
+
+void GUI::Window::updateBuffer()
+{
+ // printf("updateBuffer w:%d h:%d\n", width(), height());
+
+ memset(wpixbuf.buf, 0, wpixbuf.width * wpixbuf.height * 3);
+
+ std::vector<PixelBufferAlpha *> pl = getPixelBuffers();
+ std::vector<PixelBufferAlpha *>::iterator pli = pl.begin();
+ while(pli != pl.end()) {
+ PixelBufferAlpha *pb = *pli;
+ // printf("Buffer idx %d (%d %d) [%d %d]\n", pb->idx, pb->x, pb->y,
+ // pb->width, pb->height);
+ for(size_t x = 0; x < pb->width; x++) {
+ for(size_t y = 0; y < pb->height; y++) {
+ unsigned char r,g,b,a;
+ pb->pixel(x,y,&r,&g,&b,&a);
+ wpixbuf.setPixel(x + pb->x, y + pb->y, r, g, b, a);
+ }
+ }
+ pli++;
+ }
+
+#ifdef X11
+ if(buffer) XDestroyImage(buffer);
+ buffer =
+ create_image_from_buffer(gctx->display, DefaultScreen(gctx->display),
+ wpixbuf.buf, wpixbuf.width, wpixbuf.height);
+#endif/*X11*/
+}
+
+void GUI::Window::resized(size_t w, size_t h)
+{
+ _width = w;
+ _height = h;
+ wpixbuf.realloc(w, h);
+ updateBuffer();
+
+ pixbuf.realloc(w, h);
+ repaintEvent(NULL);
+}
+
+void GUI::Window::redraw()
+{
+#ifdef X11
+ // http://stackoverflow.com/questions/6384987/load-image-onto-a-window-using-xlib
+ if(buffer == NULL) updateBuffer();
+ XPutImage(gctx->display, xwindow, gc, buffer, 0, 0, 0, 0, width(), height());
+ XFlush(gctx->display);
+#endif/*X11*/
+
+#ifdef WIN32
+ RedrawWindow(gctx->m_hwnd, NULL, NULL, RDW_ERASE|RDW_INVALIDATE);
+ UpdateWindow(gctx->m_hwnd);
+#endif/*WIN32*/
+}
+
+GUI::Widget *GUI::Window::keyboardFocus()
+{
+ return _keyboardFocus;
+}
+
+void GUI::Window::setKeyboardFocus(GUI::Widget *widget)
+{
+ _keyboardFocus = widget;
+ repaint_r(NULL);
+}
+
+GUI::Widget *GUI::Window::buttonDownFocus()
+{
+ return _buttonDownFocus;
+}
+
+void GUI::Window::setButtonDownFocus(GUI::Widget *widget)
+{
+ _buttonDownFocus = widget;
+ // repaint_r(NULL);
+}
+
+
#ifdef TEST_WINDOW
//Additional dependency files
//deps: