diff options
Diffstat (limited to 'plugingui/window.cc')
| -rw-r--r-- | plugingui/window.cc | 409 | 
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:  | 
