371 lines
11 KiB
C
371 lines
11 KiB
C
/**************************************************************************/
|
|
/* */
|
|
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
|
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
|
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
|
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
|
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
|
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
|
/* */
|
|
/* NXAGENT, 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. */
|
|
/* */
|
|
/**************************************************************************/
|
|
|
|
#include "windowstr.h"
|
|
#include "scrnintstr.h"
|
|
|
|
#include "Agent.h"
|
|
|
|
#include "Xlib.h"
|
|
#include "Xutil.h"
|
|
|
|
#include "Display.h"
|
|
#include "Splash.h"
|
|
#include "Screen.h"
|
|
#include "Windows.h"
|
|
#include "Atoms.h"
|
|
#include "Trap.h"
|
|
#include "Init.h"
|
|
|
|
/*
|
|
* Set here the required log level.
|
|
*/
|
|
|
|
#define PANIC
|
|
#define WARNING
|
|
#undef TEST
|
|
#undef DEBUG
|
|
|
|
#ifndef X2GO
|
|
void nxagentShowSplashWindow(XlibWindow parentWindow) {}
|
|
void nxagentPaintLogo(XlibWindow win, int scale, int width, int height) {}
|
|
void nxagentRemoveSplashWindow(void) {}
|
|
Bool nxagentHaveSplashWindow(void) {return False;}
|
|
#else
|
|
/*
|
|
* Colors used to paint the splash screen.
|
|
*/
|
|
|
|
#define LOGOWHITE 0xffffff
|
|
#define LOGOBLACK 0x000000
|
|
#define LOGODARKGRAY 0x222222
|
|
#define LOGOLIGHTGRAY 0xbbbbbb
|
|
|
|
static XlibPixmap nxagentPixmapLogo;
|
|
static XlibWindow nxagentSplashWindow = None;
|
|
static Bool nxagentWMPassed = False;
|
|
|
|
static void nxagentPaintLogo(XlibWindow win, int scale, int width, int height);
|
|
|
|
void nxagentShowSplashWindow(XlibWindow parentWindow)
|
|
{
|
|
/*
|
|
* Show splash window only when running as X2Go Agent
|
|
*/
|
|
if (!nxagentX2go)
|
|
return;
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "%s: Got called.\n", __func__);
|
|
#endif
|
|
|
|
#ifdef NXAGENT_TIMESTAMP
|
|
{
|
|
extern unsigned long startTime;
|
|
|
|
fprintf(stderr, "%s: Initializing splash start at [%d] milliseconds.\n", __func__,
|
|
GetTimeInMillis() - startTime);
|
|
}
|
|
#endif
|
|
|
|
#ifdef NXAGENT_ONSTART
|
|
XSetSelectionOwner(nxagentDisplay, nxagentReadyAtom, None, CurrentTime);
|
|
#endif
|
|
|
|
nxagentWMPassed = False;
|
|
|
|
XWindowAttributes getAttributes;
|
|
|
|
/*
|
|
* This would cause a GetWindowAttributes and a GetGeometry
|
|
* (asynchronous) reply. We use instead the geometry requested by
|
|
* the user for the agent window.
|
|
*
|
|
* XGetWindowAttributes(nxagentDisplay, parentWindow, &getAttributes);
|
|
*/
|
|
|
|
/*
|
|
* During reconnection we draw the splash over the default window
|
|
* and not over the root window because it would be hidden by other
|
|
* windows.
|
|
*/
|
|
|
|
if (nxagentReconnectTrap)
|
|
{
|
|
getAttributes.x = nxagentOption(RootX);
|
|
getAttributes.y = nxagentOption(RootY);
|
|
}
|
|
else
|
|
{
|
|
getAttributes.x = 0;
|
|
getAttributes.y = 0;
|
|
}
|
|
|
|
getAttributes.width = nxagentOption(RootWidth);
|
|
getAttributes.height = nxagentOption(RootHeight);
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "%s: Going to create new splash window.\n", __func__);
|
|
#endif
|
|
|
|
XSetWindowAttributes attributes = {
|
|
.override_redirect = True,
|
|
.border_pixel = WhitePixel (nxagentDisplay, 0),
|
|
.background_pixel = BlackPixel (nxagentDisplay, 0)
|
|
};
|
|
|
|
nxagentSplashWindow =
|
|
XCreateWindow(nxagentDisplay,
|
|
parentWindow,
|
|
getAttributes.x, getAttributes.y,
|
|
getAttributes.width, getAttributes.height,
|
|
0,
|
|
CopyFromParent, CopyFromParent, CopyFromParent,
|
|
CWOverrideRedirect | CWBorderPixel | CWBackPixel,
|
|
&attributes);
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "%s: Created new splash window with id [0x%lx].\n", __func__,
|
|
nxagentSplashWindow);
|
|
#endif
|
|
|
|
nxagentPaintLogo(nxagentSplashWindow, 1, getAttributes.width, getAttributes.height);
|
|
XMapRaised(nxagentDisplay, nxagentSplashWindow);
|
|
#if 0
|
|
/*
|
|
* should not be required since XMapRaised takes care of that:
|
|
* "The XMapRaised function essentially is similar to XMapWindow in
|
|
* that it maps the window and all of its subwindows that have had
|
|
* map requests. However, it also raises the specified window to
|
|
* the top of the stack."
|
|
*/
|
|
XWindowChanges values = {.stack_mode = Above};
|
|
XConfigureWindow(nxagentDisplay, nxagentSplashWindow, CWStackMode, &values);
|
|
#endif
|
|
|
|
#ifdef NXAGENT_TIMESTAMP
|
|
{
|
|
extern unsigned long startTime;
|
|
fprintf(stderr, "%s: Splash ends [%d] milliseconds.\n", __func__,
|
|
GetTimeInMillis() - startTime);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
Bool nxagentHaveSplashWindow(void)
|
|
{
|
|
return (nxagentSplashWindow != None);
|
|
}
|
|
|
|
void nxagentPaintLogo(XlibWindow win, int scale, int width, int height)
|
|
{
|
|
XlibGC gc = XCreateGC(nxagentDisplay, nxagentSplashWindow, 0, NULL);
|
|
|
|
int depth = DefaultDepth(nxagentDisplay, DefaultScreen(nxagentDisplay));
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "%s: Got called.\n", __func__);
|
|
#endif
|
|
|
|
#ifdef NXAGENT_LOGO_DEBUG
|
|
fprintf(stderr, "%s: begin\n", __func__);
|
|
fprintf(stderr, "%s: gen params are: w=%d h=%d d=%d w=%x b=%x g1=%x g2=%x \n", __func__,
|
|
width, height, depth,
|
|
nxagentLogoWhite, nxagentLogoBlack, nxagentLogoDarkGray, nxagentLogoLightGray);
|
|
#endif
|
|
|
|
int w = width/scale;
|
|
int h = height/scale;
|
|
|
|
int c;
|
|
if (height > width)
|
|
{
|
|
c = w/30;
|
|
}
|
|
else
|
|
{
|
|
c = w/48;
|
|
}
|
|
|
|
XSetFunction(nxagentDisplay, gc, GXcopy);
|
|
XSetFillStyle(nxagentDisplay, gc, FillSolid);
|
|
nxagentPixmapLogo = XCreatePixmap(nxagentDisplay, win, width, height, depth);
|
|
|
|
if (!nxagentPixmapLogo)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (blackRoot)
|
|
{
|
|
XSetForeground(nxagentDisplay, gc, LOGOBLACK);
|
|
XSetBackground(nxagentDisplay, gc, LOGOWHITE);
|
|
}
|
|
else
|
|
{
|
|
XSetForeground(nxagentDisplay, gc, LOGOWHITE);
|
|
XSetBackground(nxagentDisplay, gc, LOGOBLACK);
|
|
}
|
|
|
|
XPoint rect[15];
|
|
rect[0].x = 0; rect[0].y = 0;
|
|
rect[1].x = 0; rect[1].y = height;
|
|
rect[2].x = width; rect[2].y = height;
|
|
rect[3].x = width; rect[3].y = 0;
|
|
|
|
/* paint background */
|
|
XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
|
|
|
|
#ifdef NXAGENT_LOGO_DEBUG
|
|
fprintf(stderr, "%s: filled background\n", __func__);
|
|
#endif
|
|
|
|
if (blackRoot)
|
|
XSetForeground(nxagentDisplay, gc, LOGODARKGRAY);
|
|
else
|
|
XSetForeground(nxagentDisplay, gc, LOGOLIGHTGRAY);
|
|
|
|
|
|
#ifdef NXAGENT_LOGO_DEBUG
|
|
/* mark center */
|
|
XDrawLine(nxagentDisplay, nxagentPixmapLogo, gc, 0, h/2, w, h/2);
|
|
XDrawLine(nxagentDisplay, nxagentPixmapLogo, gc, w/2, 0, w/2, h);
|
|
#endif
|
|
|
|
/*
|
|
* Draw X2GO Logo
|
|
*/
|
|
|
|
#define WX 5 /* width of "X" */
|
|
#define W2 4 /* width of "2" */
|
|
#define WG 4 /* width of "G" */
|
|
#define WO 4 /* width of "O" */
|
|
#define SPC 1 /* width of space between letters */
|
|
#define H 8 /* height of letters */
|
|
|
|
#define TOTALW (WX + SPC + W2 + SPC + WG + SPC + WO) /* total width of logo */
|
|
#define XSTART ((w - (TOTALW * c)) / 2) /* x position of whole logo */
|
|
#define YSTART ((h - (H * c)) / 2) /* y position whole logo */
|
|
|
|
#define X(offset) (XSTART + (offset) * c)
|
|
#define Y(offset) (YSTART + (offset) * c)
|
|
|
|
#define XY(xx,yy) {rect[cnt].x = X(xx); rect[cnt++].y = Y(yy);}
|
|
|
|
int cnt;
|
|
|
|
/*
|
|
* Paint 'X'.
|
|
*/
|
|
|
|
cnt = 0; XY(1,0); XY(0,0); XY(4,8); XY(5,8);
|
|
XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, cnt, Convex, CoordModeOrigin);
|
|
|
|
cnt = 0; XY(4,0); XY(5,0); XY(1,8); XY(0,8);
|
|
XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, cnt, Convex, CoordModeOrigin);
|
|
|
|
/*
|
|
* Paint '2'.
|
|
*/
|
|
|
|
#undef X
|
|
#define X(offset) (XSTART + (SPC + WX + offset) * c)
|
|
|
|
cnt = 0; XY(0,0); XY(4,0); XY(4,3); XY(1,7); XY(4,7); XY(4,8); XY(0,8); XY(0,7); XY(3,3); XY(3,1); XY(1,1); XY(1,2); XY(0,2); XY(0,0);
|
|
XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, cnt, Nonconvex, CoordModeOrigin);
|
|
|
|
/*
|
|
* Paint 'G'.
|
|
*/
|
|
|
|
#undef X
|
|
#define X(offset) (XSTART + (SPC + WX + SPC + W2 + offset) * c)
|
|
|
|
cnt = 0; XY(0,0); XY(4,0); XY(4,2); XY(3,2); XY(3,1); XY(1,1);XY(1,7);
|
|
XY(3,7); XY(3,5); XY(2,5); XY(2,4); XY(4,4); XY(4,8); XY(0,8); XY(0,0);
|
|
XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, cnt, Nonconvex, CoordModeOrigin);
|
|
|
|
/*
|
|
* Paint 'O'.
|
|
*/
|
|
|
|
#undef X
|
|
#define X(offset) (XSTART + (SPC + WX + SPC + W2 + SPC + WG + offset) * c)
|
|
|
|
cnt = 0; XY(0,0); XY(4,0); XY(4,8); XY(0,8); XY(0,1); XY(1,1); XY(1,7); XY(3,7); XY(3,1); XY(0,1); XY(0,0);
|
|
XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, cnt, Nonconvex, CoordModeOrigin);
|
|
|
|
XSetWindowBackgroundPixmap(nxagentDisplay, win, nxagentPixmapLogo);
|
|
|
|
XFreeGC(nxagentDisplay, gc);
|
|
|
|
#ifdef NXAGENT_LOGO_DEBUG
|
|
fprintf(stderr, "%s: end\n", __func__);
|
|
#endif
|
|
}
|
|
|
|
void nxagentRemoveSplashWindow(void)
|
|
{
|
|
if (nxagentWMPassed)
|
|
return;
|
|
|
|
if (nxagentReconnectTrap)
|
|
return;
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "%s: Destroying the splash window.\n", __func__);
|
|
#endif
|
|
|
|
#ifdef NXAGENT_ONSTART
|
|
XSetSelectionOwner(nxagentDisplay, nxagentReadyAtom,
|
|
nxagentDefaultWindows[0], CurrentTime);
|
|
#endif
|
|
|
|
if (nxagentSplashWindow != None)
|
|
{
|
|
XDestroyWindow(nxagentDisplay, nxagentSplashWindow);
|
|
|
|
nxagentSplashWindow = None;
|
|
nxagentRefreshWindows(screenInfo.screens[0]->root);
|
|
|
|
#ifdef NXAGENT_ONSTART
|
|
#ifdef TEST
|
|
fprintf(stderr, "%s: setting the ownership of %s (%d) on window [0x%lx]\n", __func__,
|
|
"NX_CUT_BUFFER_SERVER", (int)serverTransToAgentProperty, nxagentWindow(screenInfo.screens[0]->root));
|
|
#endif
|
|
|
|
XSetSelectionOwner(nxagentDisplay, serverTransToAgentProperty,
|
|
nxagentWindow(screenInfo.screens[0]->root), CurrentTime);
|
|
#endif
|
|
}
|
|
|
|
if (nxagentPixmapLogo)
|
|
{
|
|
XFreePixmap(nxagentDisplay, nxagentPixmapLogo);
|
|
nxagentPixmapLogo = (XlibPixmap) 0;
|
|
}
|
|
}
|
|
#endif /* ifdef X2GO */
|