/**************************************************************************/ /* */ /* Copyright (c) 2001, 2011 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. //