Files
nx-libs/nxcompshad/src/Updater.cpp
2025-08-08 20:00:36 +02:00

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.
//