#include <vncviewer.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/Toggle.h>
static Bool DoBumpScroll();
static void BumpScrollTimerCallback(XtPointer clientData, XtIntervalId *id);
static XtIntervalId timer;
static Bool timerSet = False;
static Bool scrollLeft, scrollRight, scrollUp, scrollDown;
static Position desktopX, desktopY;
static Dimension viewportWidth, viewportHeight;
static Dimension scrollbarWidth, scrollbarHeight;
void
FullScreenOn()
{
Dimension toplevelWidth, toplevelHeight;
Dimension oldViewportWidth, oldViewportHeight, clipWidth, clipHeight;
Position viewportX, viewportY;
appData.fullScreen = True;
if (si.framebufferWidth > dpyWidth || si.framebufferHeight > dpyHeight) {
XtVaSetValues(viewport, XtNforceBars, True, NULL);
XtVaGetValues(viewport, XtNwidth, &oldViewportWidth,
XtNheight, &oldViewportHeight, NULL);
XtVaGetValues(XtNameToWidget(viewport, "clip"),
XtNwidth, &clipWidth, XtNheight, &clipHeight, NULL);
scrollbarWidth = oldViewportWidth - clipWidth;
scrollbarHeight = oldViewportHeight - clipHeight;
if (si.framebufferWidth > dpyWidth) {
viewportWidth = toplevelWidth = dpyWidth + scrollbarWidth;
} else {
viewportWidth = si.framebufferWidth + scrollbarWidth;
toplevelWidth = dpyWidth;
}
if (si.framebufferHeight > dpyHeight) {
viewportHeight = toplevelHeight = dpyHeight + scrollbarHeight;
} else {
viewportHeight = si.framebufferHeight + scrollbarHeight;
toplevelHeight = dpyHeight;
}
} else {
viewportWidth = si.framebufferWidth;
viewportHeight = si.framebufferHeight;
toplevelWidth = dpyWidth;
toplevelHeight = dpyHeight;
}
viewportX = (toplevelWidth - viewportWidth) / 2;
viewportY = (toplevelHeight - viewportHeight) / 2;
XtVaSetValues(toplevel, XtNoverrideRedirect, True, NULL);
XReparentWindow(dpy, XtWindow(toplevel), DefaultRootWindow(dpy), 0, 0);
XSync(dpy, False);
XMoveWindow(dpy, XtWindow(toplevel), 0, 0);
XSync(dpy, False);
XtResizeWidget(toplevel, viewportWidth, viewportHeight, 0);
XtUnmanageChild(viewport);
XtVaSetValues(viewport,
XtNhorizDistance, viewportX,
XtNvertDistance, viewportY,
XtNleft, XtChainLeft,
XtNright, XtChainLeft,
XtNtop, XtChainTop,
XtNbottom, XtChainTop,
NULL);
XtManageChild(viewport);
XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0);
XtVaSetValues(popup, XtNoverrideRedirect, True, NULL);
XSetInputFocus(dpy, DefaultRootWindow(dpy), RevertToPointerRoot,
CurrentTime);
}
void
FullScreenOff()
{
int toplevelWidth = si.framebufferWidth;
int toplevelHeight = si.framebufferHeight;
appData.fullScreen = False;
XtUnmapWidget(toplevel);
XtResizeWidget(toplevel,
viewportWidth - scrollbarWidth,
viewportHeight - scrollbarHeight, 0);
XtResizeWidget(viewport,
viewportWidth - scrollbarWidth,
viewportHeight - scrollbarHeight, 0);
XtVaSetValues(viewport, XtNforceBars, False, NULL);
XtUnmanageChild(viewport);
XtVaSetValues(viewport,
XtNhorizDistance, 0,
XtNvertDistance, 0,
XtNleft, XtChainLeft,
XtNright, XtChainRight,
XtNtop, XtChainTop,
XtNbottom, XtChainBottom,
NULL);
XtManageChild(viewport);
XtVaSetValues(toplevel, XtNoverrideRedirect, False, NULL);
if ((toplevelWidth + appData.wmDecorationWidth) >= dpyWidth)
toplevelWidth = dpyWidth - appData.wmDecorationWidth;
if ((toplevelHeight + appData.wmDecorationHeight) >= dpyHeight)
toplevelHeight = dpyHeight - appData.wmDecorationHeight;
XtResizeWidget(toplevel, toplevelWidth, toplevelHeight, 0);
XtMapWidget(toplevel);
XSync(dpy, False);
XtVaSetValues(popup, XtNoverrideRedirect, False, NULL);
}
void
SetFullScreenState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
{
if (appData.fullScreen)
XtVaSetValues(w, XtNstate, True, NULL);
else
XtVaSetValues(w, XtNstate, False, NULL);
}
void
ToggleFullScreen(Widget w, XEvent *ev, String *params, Cardinal *num_params)
{
if (appData.fullScreen) {
FullScreenOff();
} else {
FullScreenOn();
}
}
void
SetGrabKeyboardState(Widget w, XEvent *ev, String *params, Cardinal *num_params)
{
if (appData.grabKeyboard)
XtVaSetValues(w, XtNstate, True, NULL);
else
XtVaSetValues(w, XtNstate, False, NULL);
}
void
ToggleGrabKeyboard(Widget w, XEvent *ev, String *params, Cardinal *num_params)
{
if (appData.grabKeyboard)
{
XtUngrabKeyboard(desktop, CurrentTime);
appData.grabKeyboard = False;
}
else
{
if (XtGrabKeyboard(desktop, True, GrabModeAsync,
GrabModeAsync, CurrentTime) != GrabSuccess) {
fprintf(stderr, "XtGrabKeyboard() failed.\n");
}
else {
appData.grabKeyboard = True;
}
}
}
Bool
BumpScroll(XEvent *ev)
{
scrollLeft = scrollRight = scrollUp = scrollDown = False;
if (ev->xmotion.x_root >= dpyWidth - 3)
scrollRight = True;
else if (ev->xmotion.x_root <= 2)
scrollLeft = True;
if (ev->xmotion.y_root >= dpyHeight - 3)
scrollDown = True;
else if (ev->xmotion.y_root <= 2)
scrollUp = True;
if (scrollLeft || scrollRight || scrollUp || scrollDown) {
if (timerSet)
return True;
XtVaGetValues(desktop, XtNx, &desktopX, XtNy, &desktopY, NULL);
desktopX = -desktopX;
desktopY = -desktopY;
return DoBumpScroll();
}
if (timerSet) {
XtRemoveTimeOut(timer);
timerSet = False;
}
return False;
}
static Bool
DoBumpScroll()
{
int oldx = desktopX, oldy = desktopY;
if (scrollRight) {
if (desktopX < si.framebufferWidth - dpyWidth) {
desktopX += appData.bumpScrollPixels;
if (desktopX > si.framebufferWidth - dpyWidth)
desktopX = si.framebufferWidth - dpyWidth;
}
} else if (scrollLeft) {
if (desktopX > 0) {
desktopX -= appData.bumpScrollPixels;
if (desktopX < 0)
desktopX = 0;
}
}
if (scrollDown) {
if (desktopY < si.framebufferHeight - dpyHeight) {
desktopY += appData.bumpScrollPixels;
if (desktopY > si.framebufferHeight - dpyHeight)
desktopY = si.framebufferHeight - dpyHeight;
}
} else if (scrollUp) {
if (desktopY > 0) {
desktopY -= appData.bumpScrollPixels;
if (desktopY < 0)
desktopY = 0;
}
}
if (oldx != desktopX || oldy != desktopY) {
XawViewportSetCoordinates(viewport, desktopX, desktopY);
timer = XtAppAddTimeOut(appContext, appData.bumpScrollTime,
BumpScrollTimerCallback, NULL);
timerSet = True;
return True;
}
timerSet = False;
return False;
}
static void
BumpScrollTimerCallback(XtPointer clientData, XtIntervalId *id)
{
DoBumpScroll();
}