2 #include "vncdisplaythread.h"
3 #include "pipedprocess.h"
9 //#define DEBUG_KEYBOARD
10 //#define DEBUG_VNC_CALLBACKS
13 typedef wxAlphaPixelData PixelData
;
14 // typedef wxPixelFormat<unsigned char, 32, 0, 1, 2> PixelData;
16 DEFINE_EVENT_TYPE(EVT_VNC_UPDATE
)
17 DEFINE_EVENT_TYPE(EVT_VNC_RESIZE
)
19 BEGIN_EVENT_TABLE(VNCPanel
, wxScrolledWindow
)
20 EVT_PAINT(VNCPanel::OnPaint
)
21 EVT_ERASE_BACKGROUND(VNCPanel::OnEraseBackground
)
22 EVT_MOUSE_EVENTS(VNCPanel::OnMouseEvent
)
23 EVT_KEY_DOWN(VNCPanel::OnKeyDown
)
24 EVT_KEY_UP(VNCPanel::OnKeyUp
)
25 EVT_COMMAND(wxID_ANY
,EVT_PROCESS_TERMINATED
,VNCPanel::HandleProcessTermination
)
31 rfbBool
VNCResizeCallback(rfbClient
*client
);
32 void VNCUpdateCallback(rfbClient
* cl
,int x
,int y
,int w
,int h
);
35 VNCPanel::VNCPanel(wxWindow
*parent
,wxString host
,int display
)
36 :wxScrolledWindow(parent
, wxID_ANY
),
38 vncdisplaythread(NULL
),
42 VNCPanel::~VNCPanel(){
46 bool VNCPanel::Connect(int display
){
47 wxLogDebug(wxT("Try to connect to display: %d"),display
);
48 return Connect(wxT(""),display
);
51 bool VNCPanel::Connect(wxString host
,int display
){
52 // 16-bit: vncclient=rfbGetClient(5,3,2);
53 // 24-bit?: vncclient = rfbGetClient(8,3,3);
54 // 32-bit?:vncclient = rfbGetClient(8,3,4);
55 vncclient
= rfbGetClient(8,3,4);
56 // store this instance so we can later use it within the callbacks
57 rfbClientSetClientData(vncclient
, (void *)dummy
, this);
58 vncclient
->serverHost
= strdup("127.0.0.1");
59 vncclient
->serverPort
= display
;
60 vncclient
->MallocFrameBuffer
= VNCResizeCallback
;
61 vncclient
->canHandleNewFBSize
= true;
62 vncclient
->GotFrameBufferUpdate
= VNCUpdateCallback
;
64 if(vncclient
->serverPort
>=0 && vncclient
->serverPort
<5900)
65 vncclient
->serverPort
+=5900;
67 if(!rfbInitClient(vncclient
,NULL
,NULL
)){
69 wxLogDebug(wxT("Could not init vncclient."));
73 vncdisplaythread
= new VNCDisplayThread(this);
74 vncdisplaythread
->Create();
75 vncdisplaythread
->Run();
80 void VNCPanel::Disconnect(){
81 rfbClient
*tmp
= vncclient
;
83 wxLogDebug(wxT("vncclient set to NULL"));
84 if(vncdisplaythread
!= NULL
){
85 vncdisplaythread
->Stop();
86 vncdisplaythread
->Wait();
87 delete vncdisplaythread
;
88 vncdisplaythread
= NULL
;
92 free(tmp
->frameBuffer
);
93 rfbClientCleanup(tmp
);
96 wxLogDebug(wxT("disconnected"));
99 void VNCPanel::HandleProcessTermination(wxCommandEvent
& WXUNUSED(event
)){
103 rfbClient
* VNCPanel::GetVNCClient(){
104 return this->vncclient
;
107 void VNCPanel::VNCUpdateRect(int x
,int y
,int w
,int h
){
108 wxBitmap
*bmp
= VNCGenerateBitmap(x
,y
,w
,h
);
112 dc
.DrawBitmap(*bmp
,x
,y
,false);
116 wxBitmap
* VNCPanel::VNCGenerateBitmap(int x
,int y
,int w
,int h
){
117 // can't draw if the frame buffer doesn't exists yet
118 if(!vncclient
|| !vncclient
->frameBuffer
)
121 // create a bitmap from our pixel data
123 wxLogDebug(wxT("generate bitmap: x:%d y:%d w:%d h:%d"),x
,y
,w
,h
);
125 //wxCriticalSectionLocker locker(lock);
127 wxBitmap
*bmp
= new wxBitmap(w
,h
,vncclient
->format
.bitsPerPixel
);
129 PixelData
data(*bmp
);
131 printf("could not access raw pixel data\n");
135 PixelData::Iterator
p(data
);
137 // unsigned char *rawdata=(unsigned char *)&p.Data();
138 // unsigned char *rawdata=(unsigned char *)p.m_ptr;
140 uint8_t *px
= (uint8_t*)vncclient
->frameBuffer
;
141 // move the pointer to the beginning of the requested area
142 px
+=((vncclient
->width
* y
+ x
) * 4);
143 int offsetx
= ((vncclient
->width
- w
)*4);
144 for( int cy
= 0; cy
< h
; ++cy
)
146 PixelData::Iterator rowStart
= p
;
148 for( int cx
= 0; cx
< w
; ++cx
){
154 ++p
; // same as p.OffsetX(1)
164 rfbBool
VNCPanel::VNCResize(){
168 //wxCriticalSectionLocker locker(lock);
170 if(vncclient
->frameBuffer
)
171 free(vncclient
->frameBuffer
);
173 vncclient
->frameBuffer
= (uint8_t*)malloc(
174 vncclient
->width
* vncclient
->height
*
175 vncclient
->format
.bitsPerPixel
/8
178 wxLogDebug(wxT("VNCResize: w: %d h: %d"),vncclient
->width
,vncclient
->height
);
179 if(vncclient
->frameBuffer
){
180 wxSize
size(vncclient
->width
,vncclient
->height
);
184 GetParent()->GetSizer()->Layout();
186 GetParent()->SetSize(size);
187 GetParent()->SetMinSize(size);
188 GetParent()->SetMaxSize(size);
190 printf("Size adjusted...\n");
194 printf("Could not adjust size\n");
198 void VNCPanel::OnPaint(wxPaintEvent
& WXUNUSED(event
)){
201 printf("OnPaint()\n");
204 // Dimensions of client area in pixels
206 // get the update rect list
207 wxRegionIterator
upd(GetUpdateRegion());
208 wxCriticalSectionLocker
locker(lock
);
215 // it is important that those values are never bigger than
216 // our framebuffer width/height
217 if(x
+ w
> vncclient
->width
|| y
+ h
> vncclient
->height
){
222 //printf(" SendingFrameBufferUpdateRequest(%d,%d,%d,%d)\n",x,y,w,h);
223 SendFramebufferUpdateRequest(vncclient
,x
,y
,w
,h
,false);
224 wxBitmap
*bmp
= VNCGenerateBitmap(x
,y
,w
,h
);
226 dc
.DrawBitmap(*bmp
,x
,y
,false);
234 void VNCPanel::Paint(){
236 // can't draw if the frame buffer doesn't exists yet
239 VNCUpdateRect(0,0,vncclient
->width
,vncclient
->height
);
242 void VNCPanel::OnMouseEvent(wxMouseEvent
& event
){
247 //wxPoint point = event.GetLogicalPosition(wxDC(this));
248 wxPoint point
= event
.GetPosition();
249 if(point
.x
< 0 || point
.y
< 0)
251 // mouse just moving no buttons pressed most common case
254 wxLogDebug(wxT("mouse moving: x:%d y:%d"),point
.x
,point
.y
);
256 SendPointerEvent(vncclient
,point
.x
,point
.y
,0);
262 if(event
.LeftIsDown())
263 button
|= rfbButton1Mask
;
264 if(event
.MiddleIsDown())
265 button
|= rfbButton2Mask
;
266 if(event
.RightIsDown())
267 button
|= rfbButton3Mask
;
270 wxLogDebug(wxT("mouse event: x:%d y:%d button:%d\n"),point
.x
,point
.y
,button
);
272 SendPointerEvent(vncclient
,point
.x
,point
.y
,button
);
275 void VNCPanel::OnKeyDown(wxKeyEvent
& event
){
277 SendKeyEvent(vncclient
,TranslateKeyCode(event
),true);
280 void VNCPanel::OnKeyUp(wxKeyEvent
& event
){
282 SendKeyEvent(vncclient
,TranslateKeyCode(event
),false);
285 rfbKeySym
VNCPanel::TranslateKeyCode(wxKeyEvent
& event
){
288 switch(event
.GetKeyCode()){
289 case WXK_BACK
: k
= XK_BackSpace
; break;
290 case WXK_TAB
: k
= XK_ISO_Left_Tab
; break;
291 case WXK_CLEAR
: k
= XK_Clear
; break;
292 case WXK_RETURN
: k
= XK_Return
; break;
293 case WXK_PAUSE
: k
= XK_Pause
; break;
294 case WXK_ESCAPE
: k
= XK_Escape
; break;
295 case WXK_SPACE
: k
= XK_space
; break;
296 case WXK_DELETE
: k
= XK_Delete
; break;
297 case WXK_NUMPAD0
: k
= XK_KP_0
; break;
298 case WXK_NUMPAD1
: k
= XK_KP_1
; break;
299 case WXK_NUMPAD2
: k
= XK_KP_2
; break;
300 case WXK_NUMPAD3
: k
= XK_KP_3
; break;
301 case WXK_NUMPAD4
: k
= XK_KP_4
; break;
302 case WXK_NUMPAD5
: k
= XK_KP_5
; break;
303 case WXK_NUMPAD6
: k
= XK_KP_6
; break;
304 case WXK_NUMPAD7
: k
= XK_KP_7
; break;
305 case WXK_NUMPAD8
: k
= XK_KP_8
; break;
306 case WXK_NUMPAD9
: k
= XK_KP_9
; break;
307 case WXK_NUMPAD_DECIMAL
: k
= XK_KP_Decimal
; break;
308 case WXK_NUMPAD_DIVIDE
: k
= XK_KP_Divide
; break;
309 case WXK_NUMPAD_MULTIPLY
: k
= XK_KP_Multiply
; break;
310 case WXK_NUMPAD_SUBTRACT
: k
= XK_KP_Subtract
; break;
311 case WXK_NUMPAD_ADD
: k
= XK_KP_Add
; break;
312 case WXK_NUMPAD_ENTER
: k
= XK_KP_Enter
; break;
313 case WXK_NUMPAD_EQUAL
: k
= XK_KP_Equal
; break;
314 case WXK_UP
: k
= XK_Up
; break;
315 case WXK_DOWN
: k
= XK_Down
; break;
316 case WXK_RIGHT
: k
= XK_Right
; break;
317 case WXK_LEFT
: k
= XK_Left
; break;
318 case WXK_INSERT
: k
= XK_Insert
; break;
319 case WXK_HOME
: k
= XK_Home
; break;
320 case WXK_END
: k
= XK_End
; break;
321 case WXK_PAGEUP
: k
= XK_Page_Up
; break;
322 case WXK_PAGEDOWN
: k
= XK_Page_Down
; break;
323 case WXK_F1
: k
= XK_F1
; break;
324 case WXK_F2
: k
= XK_F2
; break;
325 case WXK_F3
: k
= XK_F3
; break;
326 case WXK_F4
: k
= XK_F4
; break;
327 case WXK_F5
: k
= XK_F5
; break;
328 case WXK_F6
: k
= XK_F6
; break;
329 case WXK_F7
: k
= XK_F7
; break;
330 case WXK_F8
: k
= XK_F8
; break;
331 case WXK_F9
: k
= XK_F9
; break;
332 case WXK_F10
: k
= XK_F10
; break;
333 case WXK_F11
: k
= XK_F11
; break;
334 case WXK_F12
: k
= XK_F12
; break;
335 case WXK_F13
: k
= XK_F13
; break;
336 case WXK_F14
: k
= XK_F14
; break;
337 case WXK_F15
: k
= XK_F15
; break;
338 case WXK_NUMLOCK
: k
= XK_Num_Lock
; break;
339 case WXK_CAPITAL
: k
= XK_Caps_Lock
; break;
340 case WXK_SCROLL
: k
= XK_Scroll_Lock
; break;
341 case WXK_SHIFT
: k
= XK_Shift_L
; break;
342 // case SDLK_RSHIFT: k = XK_Shift_R; break;
343 // case SDLK_LSHIFT: k = XK_Shift_L; break;
344 case WXK_CONTROL
: k
= XK_Control_L
; break;
345 // case SDLK_RCTRL: k = XK_Control_R; break;
346 // case SDLK_LCTRL: k = XK_Control_L; break;
347 case WXK_ALT
: k
= XK_Alt_L
; break;
348 // case SDLK_RALT: k = XK_Alt_R; break;
349 // case SDLK_LALT: k = XK_Alt_L; break;
350 // case SDLK_RMETA: k = XK_Meta_R; break;
351 // case SDLK_LMETA: k = XK_Meta_L; break;
352 case WXK_WINDOWS_LEFT
: k
= XK_Super_L
; break; /* left windows key */
353 case WXK_WINDOWS_RIGHT
: k
= XK_Super_R
; break; /* right windows key */
354 // case SDLK_COMPOSE: k = XK_Compose; break;
355 // case SDLK_MODE: k = XK_Mode_switch; break;
356 case WXK_HELP
: k
= XK_Help
; break;
357 case WXK_PRINT
: k
= XK_Print
; break;
358 // case SDLK_SYSREQ: k = XK_Sys_Req; break;
359 // case WXK_PAUSE: k = XK_Break; break;
361 k
= event
.GetKeyCode();
367 rfbKeySym keycode
= event
.GetRawKeyCode();
368 #ifdef DEBUG_KEYBOARD
369 wxLogDebug(wxT("Keycode: %d"),keycode
);
374 inline void VNCPanel::OnEraseBackground(wxEraseEvent
&){};
376 wxCriticalSection
& VNCPanel::GetCriticalSection(){
380 extern "C" void VNCUpdateCallback(rfbClient
* cl
,int x
,int y
,int w
,int h
) {
381 VNCPanel
*panel
= (VNCPanel
*)rfbClientGetClientData(cl
,(void *)dummy
);
383 #ifdef DEBUG_VNC_CALLBACKS
384 wxLogDebug(wxT("VNCUpdate callback: x:%d y:%d w:%d h:%d"),x
,y
,w
,h
);
386 //if(!wxIsMainThread())
387 // wxMutexGuiEnter();
388 panel
->VNCUpdateRect(x
,y
,w
,h
);
389 //if(!wxIsMainThread())
390 // wxMutexGuiLeave();
394 extern "C" rfbBool
VNCResizeCallback(rfbClient
*client
){
395 #ifdef DEBUG_VNC_CALLBACKS
396 wxLogDebug(wxT("VNCResize callback: w:%d h:%d"),client
->width
,client
->height
);
398 VNCPanel
*panel
= (VNCPanel
*)rfbClientGetClientData(client
,(void *)dummy
);
400 //if(!wxIsMainThread())
401 // wxMutexGuiEnter();
402 rfbBool success
= panel
->VNCResize();
403 //if(!wxIsMainThread())
404 // wxMutexGuiLeave();