396 lines
9.6 KiB
C++
396 lines
9.6 KiB
C++
/**************************************************************************/
|
|
/* */
|
|
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
|
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
|
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
|
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
|
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
|
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
|
/* */
|
|
/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */
|
|
/* are copyright of the aforementioned persons and companies. */
|
|
/* */
|
|
/* Redistribution and use of the present software is allowed according */
|
|
/* to terms specified in the file LICENSE which comes in the source */
|
|
/* distribution. */
|
|
/* */
|
|
/* All rights reserved. */
|
|
/* */
|
|
/* NOTE: This software has received contributions from various other */
|
|
/* contributors, only the core maintainers and supporters are listed as */
|
|
/* copyright holders. Please contact us, if you feel you should be listed */
|
|
/* as copyright holder, as well. */
|
|
/* */
|
|
/**************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <nx-X11/Xlib.h>
|
|
#include <nx-X11/Xutil.h>
|
|
#include <nx-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.
|
|
//
|