Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
native-glass.lens.lensRFB.rfb.c Maven / Gradle / Ivy
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "LensCommon.h"
#include "wm/LensWindowManager.h"
#include "lensRFB.h"
#include "com_sun_glass_events_WindowEvent.h"
#include "com_sun_glass_events_KeyEvent.h"
#include "com_sun_glass_events_MouseEvent.h"
#include "com_sun_glass_events_TouchEvent.h"
#ifdef USE_WRAPPED_VNC
#define PORTRFBAPI
#include "wrapped_rfb.h"
#else
#include
#include
#endif
static jboolean isActive = JNI_FALSE;
//no choice but to cache it, as we can't pass it to client data directly
//because newClientHook is called at arbitrary point by VNC
static JNIEnv *genv;
static rfbClientPtr client = NULL;
static rfbScreenInfoPtr rfbScreen;
typedef struct ClientData {
rfbBool oldButton;
int oldX;
int oldY;
} ClientData;
typedef struct {
int fbKey;
int shiftedfbKey;
int javaKey;
} rfbKeytoJavaKeyPair;
//As we don't have linux input code, we need to hold our own "key map"
// NOTE: RFB sends us "shifted keys" and we kind of need to shift them back...
static rfbKeytoJavaKeyPair keyMap[] = {
{0, 0, com_sun_glass_events_KeyEvent_VK_UNDEFINED},
{XK_Escape, 0, com_sun_glass_events_KeyEvent_VK_ESCAPE},
{XK_a, XK_A, com_sun_glass_events_KeyEvent_VK_A},
{XK_b, XK_B, com_sun_glass_events_KeyEvent_VK_B},
{XK_c, XK_C, com_sun_glass_events_KeyEvent_VK_C},
{XK_d, XK_D, com_sun_glass_events_KeyEvent_VK_D},
{XK_e, XK_E, com_sun_glass_events_KeyEvent_VK_E},
{XK_f, XK_F, com_sun_glass_events_KeyEvent_VK_F},
{XK_g, XK_G, com_sun_glass_events_KeyEvent_VK_G},
{XK_h, XK_H, com_sun_glass_events_KeyEvent_VK_H},
{XK_i, XK_I, com_sun_glass_events_KeyEvent_VK_I},
{XK_j, XK_J, com_sun_glass_events_KeyEvent_VK_J},
{XK_k, XK_K, com_sun_glass_events_KeyEvent_VK_K},
{XK_l, XK_L, com_sun_glass_events_KeyEvent_VK_L},
{XK_m, XK_M, com_sun_glass_events_KeyEvent_VK_M},
{XK_n, XK_N, com_sun_glass_events_KeyEvent_VK_N},
{XK_o, XK_O, com_sun_glass_events_KeyEvent_VK_O},
{XK_p, XK_P, com_sun_glass_events_KeyEvent_VK_P},
{XK_q, XK_Q, com_sun_glass_events_KeyEvent_VK_Q},
{XK_r, XK_R, com_sun_glass_events_KeyEvent_VK_R},
{XK_s, XK_S, com_sun_glass_events_KeyEvent_VK_S},
{XK_t, XK_T, com_sun_glass_events_KeyEvent_VK_T},
{XK_u, XK_U, com_sun_glass_events_KeyEvent_VK_U},
{XK_v, XK_V, com_sun_glass_events_KeyEvent_VK_V},
{XK_w, XK_W, com_sun_glass_events_KeyEvent_VK_W},
{XK_x, XK_X, com_sun_glass_events_KeyEvent_VK_X},
{XK_y, XK_Y, com_sun_glass_events_KeyEvent_VK_Y},
{XK_z, XK_Z, com_sun_glass_events_KeyEvent_VK_Z},
{XK_1, XK_exclam, com_sun_glass_events_KeyEvent_VK_1},
{XK_2, XK_at, com_sun_glass_events_KeyEvent_VK_2},
{XK_3, XK_numbersign, com_sun_glass_events_KeyEvent_VK_3},
{XK_4, XK_dollar, com_sun_glass_events_KeyEvent_VK_4},
{XK_5, XK_percent, com_sun_glass_events_KeyEvent_VK_5},
{XK_6, XK_asciicircum, com_sun_glass_events_KeyEvent_VK_6},
{XK_7, XK_ampersand, com_sun_glass_events_KeyEvent_VK_7},
{XK_8, XK_asterisk, com_sun_glass_events_KeyEvent_VK_8},
{XK_9, XK_parenleft, com_sun_glass_events_KeyEvent_VK_9},
{XK_0, XK_parenright, com_sun_glass_events_KeyEvent_VK_0},
{XK_minus, XK_underscore, com_sun_glass_events_KeyEvent_VK_MINUS},
{XK_equal, XK_plus, com_sun_glass_events_KeyEvent_VK_EQUALS},
{XK_apostrophe, XK_quotedbl, com_sun_glass_events_KeyEvent_VK_QUOTE},
{XK_backslash, XK_bar, com_sun_glass_events_KeyEvent_VK_BACK_SLASH},
{XK_bracketleft, XK_braceleft, com_sun_glass_events_KeyEvent_VK_OPEN_BRACKET},
{XK_bracketright, XK_braceright, com_sun_glass_events_KeyEvent_VK_CLOSE_BRACKET},
{XK_grave, XK_asciitilde, com_sun_glass_events_KeyEvent_VK_BACK_QUOTE},
{XK_semicolon, XK_colon, com_sun_glass_events_KeyEvent_VK_SEMICOLON},
{XK_comma, XK_less, com_sun_glass_events_KeyEvent_VK_COMMA},
{XK_period, XK_greater, com_sun_glass_events_KeyEvent_VK_PERIOD},
{XK_slash, XK_question, com_sun_glass_events_KeyEvent_VK_SLASH},
{XK_Alt_L, 0, com_sun_glass_events_KeyEvent_VK_ALT},
{XK_Caps_Lock, 0, com_sun_glass_events_KeyEvent_VK_CAPS_LOCK},
{XK_space, 0, com_sun_glass_events_KeyEvent_VK_SPACE},
{XK_Shift_R, 0, com_sun_glass_events_KeyEvent_VK_SHIFT},
{XK_Shift_L, 0, com_sun_glass_events_KeyEvent_VK_SHIFT},
{XK_BackSpace, 0, com_sun_glass_events_KeyEvent_VK_BACKSPACE},
{XK_Tab, 0, com_sun_glass_events_KeyEvent_VK_TAB},
{XK_Control_L, 0, com_sun_glass_events_KeyEvent_VK_CONTROL},
{XK_Return, 0, com_sun_glass_events_KeyEvent_VK_ENTER},
{XK_F1, 0, com_sun_glass_events_KeyEvent_VK_F1},
{XK_F2, 0, com_sun_glass_events_KeyEvent_VK_F2},
{XK_F3, 0, com_sun_glass_events_KeyEvent_VK_F3},
{XK_F4, 0, com_sun_glass_events_KeyEvent_VK_F4},
{XK_F5, 0, com_sun_glass_events_KeyEvent_VK_F5},
{XK_F6, 0, com_sun_glass_events_KeyEvent_VK_F6},
{XK_F7, 0, com_sun_glass_events_KeyEvent_VK_F7},
{XK_F8, 0, com_sun_glass_events_KeyEvent_VK_F8},
{XK_F9, 0, com_sun_glass_events_KeyEvent_VK_F9},
{XK_F10, 0, com_sun_glass_events_KeyEvent_VK_F10},
{XK_Num_Lock, 0, com_sun_glass_events_KeyEvent_VK_NUM_LOCK},
{XK_Scroll_Lock, 0, com_sun_glass_events_KeyEvent_VK_SCROLL_LOCK},
{XK_F11, 0, com_sun_glass_events_KeyEvent_VK_F11},
{XK_F12, 0, com_sun_glass_events_KeyEvent_VK_F12},
{XK_KP_0, 0, com_sun_glass_events_KeyEvent_VK_NUMPAD7},
{XK_KP_1, 0, com_sun_glass_events_KeyEvent_VK_NUMPAD1},
{XK_KP_2, 0, com_sun_glass_events_KeyEvent_VK_NUMPAD2},
{XK_KP_3, 0, com_sun_glass_events_KeyEvent_VK_NUMPAD3},
{XK_KP_4, 0, com_sun_glass_events_KeyEvent_VK_NUMPAD4},
{XK_KP_5, 0, com_sun_glass_events_KeyEvent_VK_NUMPAD5},
{XK_KP_6, 0, com_sun_glass_events_KeyEvent_VK_NUMPAD6},
{XK_KP_7, 0, com_sun_glass_events_KeyEvent_VK_NUMPAD7},
{XK_KP_8, 0, com_sun_glass_events_KeyEvent_VK_NUMPAD8},
{XK_KP_9, 0, com_sun_glass_events_KeyEvent_VK_NUMPAD9},
{XK_KP_Add, 0, com_sun_glass_events_KeyEvent_VK_ADD},
{XK_KP_Decimal, 0, com_sun_glass_events_KeyEvent_VK_DECIMAL},
{XK_KP_Subtract, 0, com_sun_glass_events_KeyEvent_VK_SUBTRACT},
{XK_KP_Multiply, 0, com_sun_glass_events_KeyEvent_VK_MULTIPLY},
{XK_KP_Enter, 0, com_sun_glass_events_KeyEvent_VK_ENTER},
{XK_Control_R, 0, com_sun_glass_events_KeyEvent_VK_CONTROL},
{XK_KP_Divide, 0, com_sun_glass_events_KeyEvent_VK_DIVIDE},
{XK_Print, 0, com_sun_glass_events_KeyEvent_VK_PRINTSCREEN},
{XK_Alt_R, 0, com_sun_glass_events_KeyEvent_VK_ALT},
{XK_KP_Home, XK_Home, com_sun_glass_events_KeyEvent_VK_HOME},
{XK_KP_Up, XK_Up, com_sun_glass_events_KeyEvent_VK_UP},
{XK_KP_Page_Up, XK_Page_Up, com_sun_glass_events_KeyEvent_VK_PAGE_UP},
{XK_KP_Left, XK_Left, com_sun_glass_events_KeyEvent_VK_LEFT},
{XK_KP_Right, XK_Right, com_sun_glass_events_KeyEvent_VK_RIGHT},
{XK_KP_End, XK_End, com_sun_glass_events_KeyEvent_VK_END},
{XK_KP_Down, XK_Down, com_sun_glass_events_KeyEvent_VK_DOWN},
{XK_KP_Page_Down, XK_Page_Down, com_sun_glass_events_KeyEvent_VK_PAGE_DOWN},
{XK_KP_Insert, XK_Insert, com_sun_glass_events_KeyEvent_VK_INSERT},
{XK_KP_Delete, 0, com_sun_glass_events_KeyEvent_VK_DELETE},
{XK_Meta_L, 0, com_sun_glass_events_KeyEvent_VK_WINDOWS},
{XK_Meta_R, 0, com_sun_glass_events_KeyEvent_VK_WINDOWS},
{XK_Menu, 0, com_sun_glass_events_KeyEvent_VK_CONTEXT_MENU}
};
//forward declarations
void rfbEventLoop(JNIEnv *env, void *data);
static int rfbGetJavaKeycodeFromPlatformKeyCode(int fbKey);
static enum rfbNewClientAction newclient(rfbClientPtr cl);
static void clientgone(rfbClientPtr cl);
static void rfbHandlePointerEvent(int buttonMask, int x, int y, rfbClientPtr cl);
static void rfbHandleKeyEvent(rfbBool pressed, rfbKeySym key, rfbClientPtr cl);
////// Init
void lens_rfb_init(JNIEnv *env) {
NativeScreen screen = glass_screen_getMainScreen();
char *fb = lens_screen_getFrameBuffer();
if (fb == NULL) {
GLASS_LOG_CONFIG("Platform doesn't support access to frame buffer - no VNC support");
return;
}
#ifdef USE_WRAPPED_VNC
void *rfbhandle = dlopen("libvncserver.so", RTLD_LAZY);
if (rfbhandle) {
_rfbGetScreen = dlsym(rfbhandle, "rfbGetScreen");
_rfbInitServer = dlsym(rfbhandle, "rfbInitServerWithPthreadsAndZRLE");
_rfbShutdownServer = dlsym(rfbhandle, "rfbShutdownServer");
_rfbNewFramebuffer = dlsym(rfbhandle, "rfbNewFramebuffer");
_rfbRunEventLoop = dlsym(rfbhandle, "fbRunEventLoop");
_rfbMarkRectAsModified = dlsym(rfbhandle, "rfbMarkRectAsModified");
_rfbProcessEvents = dlsym(rfbhandle, "rfbProcessEvents");
_rfbIsActive = dlsym(rfbhandle, "rfbIsActive");
}
if (!(_rfbInitServer && _rfbGetScreen)) {
GLASS_LOG_CONFIG("Failed to load symbols from libvncserver.so - - no VNC support");
return;
}
#endif
rfbScreen = rfbGetScreen(0, NULL, screen->width, screen->height, 8, 3, 4);
if (!rfbScreen) {
GLASS_LOG_CONFIG("rfbGetScreen() failed -no VNC support");
return;
}
rfbScreen->desktopName = "JFX";
rfbScreen->frameBuffer = fb;
rfbScreen->alwaysShared = FALSE;
rfbScreen->ptrAddEvent = rfbHandlePointerEvent;
rfbScreen->kbdAddEvent = rfbHandleKeyEvent;
rfbScreen->newClientHook = newclient;
rfbScreen->httpEnableProxyConnect = FALSE;
rfbInitServer(rfbScreen);
//start listen to events
glass_application_request_native_event_loop(env, &rfbEventLoop, NULL);
isActive = JNI_TRUE;
GLASS_LOG_CONFIG("VNC is running");
}
void rfbEventLoop(JNIEnv *env, void *data) {
genv = env;
rfbRunEventLoop(rfbScreen, 100000, FALSE);
}
static enum rfbNewClientAction newclient(rfbClientPtr cl) {
GLASS_LOG_FINE("RFB new client");
cl->clientData = (void *)calloc(sizeof(ClientData), 1);
cl->clientGoneHook = clientgone;
client = cl;
return RFB_CLIENT_ACCEPT;
}
static void clientgone(rfbClientPtr cl) {
GLASS_LOG_FINE("RFB client disconnect");
free(cl->clientData);
client = NULL;
}
void lens_rfb_notifyDirtyRegion(int topLeft_X,
int topLeft_Y,
int buttomRight_X,
int buttomRight_Y) {
if (isActive) {
rfbMarkRectAsModified(rfbScreen, topLeft_X, topLeft_Y,
buttomRight_X, buttomRight_Y);
}
}
//event handling
/**
* Handler function for pointer events. Called by VNC
*
* @param buttonMask event mask
* @param x abs coordinate on screen
* @param y abs coordinate on screen
* @param cl client record
*/
static void rfbHandlePointerEvent(int buttonMask, int x, int y, rfbClientPtr cl) {
GLASS_LOG_FINEST("RFB doptr %x %d,%d env=%p", buttonMask, x, y, genv);
ClientData *cd = cl->clientData;
if (x != cd->oldX || y != cd->oldY) {
cd->oldX = x;
cd->oldY = y;
lens_wm_notifyMotionEvent(genv, x, y, 0, 0);
}
if (buttonMask != cd->oldButton) {
int buttonsChanged = buttonMask ^ cd->oldButton;
int pressed = 0;
int glassMouseButton = 0;
if (buttonsChanged & rfbButton1Mask) {
glassMouseButton = com_sun_glass_events_MouseEvent_BUTTON_LEFT;
pressed = (buttonMask & rfbButton1Mask) == rfbButton1Mask;
} else if (buttonsChanged & rfbButton2Mask) {
glassMouseButton = com_sun_glass_events_MouseEvent_BUTTON_OTHER;
pressed = (buttonMask & rfbButton2Mask) == rfbButton2Mask;
} else if (buttonsChanged & rfbButton3Mask) {
glassMouseButton = com_sun_glass_events_MouseEvent_BUTTON_RIGHT;
pressed = (buttonMask & rfbButton3Mask) == rfbButton3Mask;
}
if (glassMouseButton) {
lens_wm_notifyButtonEvent(genv,
pressed,
glassMouseButton,
x, y);
}
cd->oldButton = buttonMask;
}
rfbDefaultPtrAddEvent(buttonMask, x, y, cl);
}
/**
* Handler function for key events. Called by VNC
*
*
* @param pressed key state
* @param key key code
* @param cl client record
*/
static void rfbHandleKeyEvent(rfbBool pressed, rfbKeySym key, rfbClientPtr cl) {
int jfxKeyCode;
int eventType;
NativeWindow window;
window = glass_window_getFocusedWindow();
if (window == NULL) {
GLASS_LOG_FINE("Skipping event, no focused window");
return;
}
jfxKeyCode = rfbGetJavaKeycodeFromPlatformKeyCode(key);
GLASS_LOG_FINE("Sending KeyEvent: %s", pressed ? "PRESS" : "RELEASE");
glass_application_notifyKeyEvent(genv, window,
(pressed) ?
com_sun_glass_events_KeyEvent_PRESS :
com_sun_glass_events_KeyEvent_RELEASE,
jfxKeyCode,
JNI_FALSE/*rfb doesn't tell us when an event is a repeat*/);
}
static int rfbGetJavaKeycodeFromPlatformKeyCode(int fbKey) {
unsigned int i = 0;
//currently just looping - performance later ..
for (i = 0 ; i < (sizeof(keyMap) / sizeof(rfbKeytoJavaKeyPair)) ; ++i) {
if (keyMap[i].fbKey == fbKey || keyMap[i].shiftedfbKey == fbKey) {
return keyMap[i].javaKey;
}
}
return com_sun_glass_events_KeyEvent_VK_UNDEFINED;
}