diff options
Diffstat (limited to 'nxcompshad/Updater.cpp')
-rw-r--r-- | nxcompshad/Updater.cpp | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/nxcompshad/Updater.cpp b/nxcompshad/Updater.cpp new file mode 100644 index 000000000..3f0e6a4da --- /dev/null +++ b/nxcompshad/Updater.cpp @@ -0,0 +1,383 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of Medialogic S.p.A. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/keysym.h> +#include <string.h> + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG +// +#include <stdio.h> +// +#include "Updater.h" +#include "Logger.h" + +Updater::Updater(char *displayName, Display *display) +{ + logTrace("Updater::Updater"); + + displayName_ = displayName; + display_ = display; + closeDisplay_ = false; + image_ = NULL; + updateRegion_ = NULL; + buffer_ = NULL; +} + +Updater::~Updater() +{ + logTrace("Updater::~Updater"); + + if (input_) + { + int removedEvents = input_ -> removeAllEvents(display_); + + logTest("Updater::~Updater", "Removed events in input queue is [%d].", removedEvents); + } + + if (display_) + { + XDestroyWindow(display_, window_); + XFreePixmap(display_, pixmap_); + + if (closeDisplay_) + { + XCloseDisplay(display_); + } + } + + if (image_) + { + image_ -> data = NULL; + + XDestroyImage(image_); + } + + if (updateRegion_) + { + XDestroyRegion(updateRegion_); + } +} + +int Updater::init(int width, int height, char *fb, Input *input) +{ + logTrace("Updater::init"); + + if (fb == NULL || input == NULL || width <= 0 || height <= 0) + { + logError("Updater::init", ESET(EINVAL)); + + return -1; + } + + width_ = width; + height_ = height; + buffer_ = fb; + input_ = input; +/* + if (display_ == NULL) + { + display_ = XOpenDisplay(displayName_); + + closeDisplay_ = true; + + if (display_ == NULL) + { + logError("Updater::init", ESET(ENOMSG)); + + return -1; + } + } +*/ + depth_ = DefaultDepth(display_, DefaultScreen(display_)); + + if (depth_ == 8) bpl_ = width_; + else if (depth_ == 16) bpl_ = width_ * 2; + else bpl_ = width_ * 4; + + logTest("Updater::init", "Server geometry [%d, %d] depth [%d] bpl [%d].", width_, height_, depth_, bpl_); + +/* int bitmap_pad = 8; + + image_ = XCreateImage(display_, DefaultVisual(display_, DefaultScreen(display_)), depth_, ZPixmap, 0, + buffer_, width_, height_, bitmap_pad, 0); + + if (image_ == NULL) + { + logError("Updater::init", ESET(ENOMSG)); + + logTest("Updater::init", "Failed to create default image."); + + return -1; + } + + pixmap_ = XCreatePixmap(display_, DefaultRootWindow(display_), width_, height_, depth_); + + unsigned int mask = CWBackPixmap | CWBorderPixel | CWEventMask; + + XSetWindowAttributes attributes; + + attributes.background_pixmap = pixmap_; + attributes.border_pixel = WhitePixel(display_, DefaultScreen(display_)); + attributes.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask; + + window_ = XCreateWindow(display_, DefaultRootWindow(display_), + 0, 0, width_, height_, 0, depth_, InputOutput, + DefaultVisual(display_, DefaultScreen(display_)), mask, &attributes); + + if (window_ == None) + { + logError("Updater::init", ESET(ENOMSG)); + + return -1; + } + + XSizeHints *size_hints; + + if ((size_hints = XAllocSizeHints()) == NULL) + { + logError("Updater::init", ESET(ENOMEM)); + + return -1; + } + + size_hints -> flags = PMinSize | PMaxSize; + size_hints -> min_width = width_; + size_hints -> max_width = width_; + size_hints -> min_height = height_; + size_hints -> max_height = height_; + + XSetWMNormalHints(display_, window_, size_hints); + + XFree(size_hints); + + Atom deleteWMatom = XInternAtom(display_, "WM_DELETE_WINDOW", 1); + + XSetWMProtocols(display_, window_, &deleteWMatom, 1); + + XMapWindow(display_, window_);*/ + + updateRegion_ = XCreateRegion(); + + logTest("Updater::init", "updateRegion_[%p]", updateRegion_); + return 1; +} + +void Updater::addRegion(Region region) +{ + // + // FIXME: Is this too paranoid ? + // + + if (updateRegion_ == NULL) + { + logError("Updater::addRegion", ESET(EINVAL)); + + return; + } + + XUnionRegion(region, updateRegion_, updateRegion_); +} + +void Updater::update() +{ + logTrace("Updater::update"); + + if (updateRegion_ == NULL) + { + logError("Updater::update", ESET(EINVAL)); + + return; + } + + logTest("Updater::update", "Number of rectangles [%ld].", updateRegion_ -> numRects); + +/* for (; updateRegion_ -> numRects > 0; updateRegion_ -> numRects--) + { + int n = updateRegion_ -> numRects - 1; + + int x = updateRegion_ -> rects[n].x1; + int y = updateRegion_ -> rects[n].y1; + unsigned int width = updateRegion_ -> rects[n].x2 - updateRegion_ -> rects[n].x1; + unsigned int height = updateRegion_ -> rects[n].y2 - updateRegion_ -> rects[n].y1; + + logDebug("Updater::update", "Sending rectangle: [%d, %d, %d, %d].", x, y, width, height); + + // + // We need to update the extents. + // + + int bitmap_pad; + + if (depth_ == 32 || depth_ == 24) + { + bitmap_pad = 32; + } + else if (depth_ == 16) + { + if ((width & 1) == 0) + { + bitmap_pad = 32; + } + else + { + bitmap_pad = 16; + } + } + else if ((width & 3) == 0) + { + bitmap_pad = 32; + } + else if ((width & 1) == 0) + { + bitmap_pad = 16; + } + else + { + bitmap_pad = 8; + }*/ + +/* image_ -> bitmap_pad = bitmap_pad;*/ + + /* NXShadowCorrectColor(x, y, width, height);*/ + +/* XPutImage(display_, pixmap_, DefaultGC(display_, DefaultScreen(display_)), + image_, x, y, x, y, width, height); + + XClearArea(display_, window_, x, y, width, height, 0); + }*/ + + // + // Should we reduces the box vector ? + // + // BOX *box = Xrealloc(updateRegion_ -> rects, + // updateRegion_ -> numRects == 0 ? sizeof(BOX) : + // updateRegion_ -> numRects * sizeof(BOX)); + // + // if (box) + // { + // updateRegion_ -> rects = box; + // updateRegion_ -> size = 1; + // } + // + + if (updateRegion_ -> numRects == 0) + { + updateRegion_ -> extents.x1 = 0; + updateRegion_ -> extents.y1 = 0; + updateRegion_ -> extents.x2 = 0; + updateRegion_ -> extents.y2 = 0; + } + else + { + // + // FIXME: We have to update the region extents. + // + + logTest("Updater::update", "Region extents has not been updated."); + } +} + +void Updater::handleInput() +{ + logTrace("Updater::handleInput"); + + XEvent *event = new XEvent; + + if (event == NULL) + { + logError("Updater::handleInput", ESET(ENOMEM)); + + return; + } + + while (XCheckIfEvent(display_, event, anyEventPredicate, NULL)) + { + switch (event -> type) + { + /* case ClientMessage: + { + Atom wmProtocols = XInternAtom(display_, "WM_PROTOCOLS", 0); + Atom wmDeleteWindow = XInternAtom(display_, "WM_DELETE_WINDOW", 0); + + if (event -> xclient.message_type == wmProtocols && + (Atom)event -> xclient.data.l[0] == wmDeleteWindow) + { + logTest("Updater::handleInput", "Got client message of type WM_PROTOCOLS and value WM_DELETE_WINDOW," + " throwing exception UpdaterClosing."); + + delete event; + + throw UpdaterClosing(); + } + else + { + logTest("Updater::handleInput", "Unexpected client message type [%ld] format [%d] first value [%ld]", + event -> xclient.message_type, event -> xclient.format, event -> xclient.data.l[0]); + } + + break; + }*/ + case KeyPress: + case KeyRelease: + case ButtonPress: + case ButtonRelease: + case MotionNotify: + { + input_ -> pushEvent(display_, event); + + event = new XEvent; + + if (event == NULL) + { + logError("Updater::handleInput", ESET(ENOMEM)); + + return; + } + + break; + } + default: + { + logTest("Updater::handleInput", "Handling unexpected event [%d].", event -> type); + + break; + } + } + } + + delete event; +} + +void Updater::newRegion() +{ + if (updateRegion_ != NULL) + { + XDestroyRegion(updateRegion_); + } + + updateRegion_ = XCreateRegion(); + + logTest("Updater::newRegion", "updateRegion_ [%p].", updateRegion_); +} +// +// Private functions. +// |