diff --git a/server/X11/CMakeLists.txt b/server/X11/CMakeLists.txt index 11a5cef5f..7b33d86e1 100644 --- a/server/X11/CMakeLists.txt +++ b/server/X11/CMakeLists.txt @@ -21,6 +21,8 @@ include_directories(${X11_INCLUDE_DIRS}) add_executable(xfreerdp-server xf_peer.c + xf_event.c + xf_input.c xf_encode.c xfreerdp.c) @@ -64,3 +66,4 @@ target_link_libraries(xfreerdp-server freerdp-utils) target_link_libraries(xfreerdp-server freerdp-gdi) target_link_libraries(xfreerdp-server freerdp-kbd) target_link_libraries(xfreerdp-server ${X11_LIBRARIES}) + diff --git a/server/X11/xf_event.c b/server/X11/xf_event.c new file mode 100644 index 000000000..c4c9c2295 --- /dev/null +++ b/server/X11/xf_event.c @@ -0,0 +1,100 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * X11 Server Event Handling + * + * Copyright 2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "xf_event.h" + +int xf_is_event_set(xfEventQueue* event_queue) +{ + fd_set rfds; + int num_set; + struct timeval time; + + FD_ZERO(&rfds); + FD_SET(event_queue->pipe_fd[0], &rfds); + memset(&time, 0, sizeof(time)); + num_set = select(event_queue->pipe_fd[0] + 1, &rfds, 0, 0, &time); + + return (num_set == 1); +} + +void xf_signal_event(xfEventQueue* event_queue) +{ + int length; + + length = write(event_queue->pipe_fd[1], "sig", 4); + + if (length != 4) + printf("xf_signal_event: error\n"); +} + +void xf_clear_event(xfEventQueue* event_queue) +{ + int length; + + while (xf_is_event_set(event_queue)) + { + length = read(event_queue->pipe_fd[0], &length, 4); + + if (length != 4) + printf("xf_clear_event: error\n"); + } +} + +xfEventQueue* xf_event_queue_new() +{ + xfEventQueue* event_queue = xnew(xfEventQueue); + + if (event_queue != NULL) + { + event_queue->pipe_fd[0] = -1; + event_queue->pipe_fd[1] = -1; + + event_queue->size = 16; + event_queue->count = 0; + event_queue->events = (xfEvent**) xzalloc(sizeof(xfEvent*) * event_queue->size); + + if (pipe(event_queue->pipe_fd) < 0) + printf("xf_event_queue_new: pipe failed\n"); + } + + return event_queue; +} + +void xf_event_queue_free(xfEventQueue* event_queue) +{ + if (event_queue->pipe_fd[0] != -1) + { + close(event_queue->pipe_fd[0]); + event_queue->pipe_fd[0] = -1; + } + + if (event_queue->pipe_fd[1] != -1) + { + close(event_queue->pipe_fd[1]); + event_queue->pipe_fd[1] = -1; + } +} diff --git a/server/X11/xf_event.h b/server/X11/xf_event.h new file mode 100644 index 000000000..da5aba225 --- /dev/null +++ b/server/X11/xf_event.h @@ -0,0 +1,67 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * X11 Server Event Handling + * + * Copyright 2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __XF_EVENT_H +#define __XF_EVENT_H + +typedef struct xf_event xfEvent; +typedef struct xf_event_queue xfEventQueue; +typedef struct xf_event_region xfEventRegion; + +#include +#include "xfreerdp.h" + +#include "xf_peer.h" + +enum xf_event_type +{ + XF_EVENT_TYPE_REGION +}; + +struct xf_event +{ + int type; +}; + +struct xf_event_queue +{ + int size; + int count; + int pipe_fd[2]; + xfEvent** events; +}; + +struct xf_event_region +{ + int type; + + int x; + int y; + int width; + int height; +}; + +int xf_is_event_set(xfEventQueue* event_queue); +void xf_signal_event(xfEventQueue* event_queue); +void xf_clear_event(xfEventQueue* event_queue); + +xfEventQueue* xf_event_queue_new(); +void xf_event_queue_free(xfEventQueue* event_queue); + +#endif /* __XF_EVENT_H */ diff --git a/server/X11/xf_input.c b/server/X11/xf_input.c new file mode 100644 index 000000000..1784c01c1 --- /dev/null +++ b/server/X11/xf_input.c @@ -0,0 +1,125 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * X11 Server Input + * + * Copyright 2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "xf_input.h" + +void xf_input_synchronize_event(rdpInput* input, uint32 flags) +{ + printf("Client sent a synchronize event (flags:0x%X)\n", flags); +} + +void xf_input_keyboard_event(rdpInput* input, uint16 flags, uint16 code) +{ + unsigned int keycode; + boolean extended = false; + xfPeerContext* xfp = (xfPeerContext*) input->context; + xfInfo* xfi = xfp->info; + + if (flags & KBD_FLAGS_EXTENDED) + extended = true; + + keycode = freerdp_kbd_get_keycode_by_scancode(code, extended); + + if (keycode != 0) + { +#ifdef WITH_XTEST + pthread_mutex_lock(&(xfp->mutex)); + + if (flags & KBD_FLAGS_DOWN) + XTestFakeKeyEvent(xfi->display, keycode, True, 0); + else if (flags & KBD_FLAGS_RELEASE) + XTestFakeKeyEvent(xfi->display, keycode, False, 0); + + pthread_mutex_unlock(&(xfp->mutex)); +#endif + } +} + +void xf_input_unicode_keyboard_event(rdpInput* input, uint16 code) +{ + printf("Client sent a unicode keyboard event (code:0x%X)\n", code); +} + +void xf_input_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y) +{ + int button = 0; + boolean down = false; + xfPeerContext* xfp = (xfPeerContext*) input->context; + xfInfo* xfi = xfp->info; + + pthread_mutex_lock(&(xfp->mutex)); +#ifdef WITH_XTEST + + if (flags & PTR_FLAGS_WHEEL) + { + boolean negative = false; + + if (flags & PTR_FLAGS_WHEEL_NEGATIVE) + negative = true; + + button = (negative) ? 5 : 4; + + XTestFakeButtonEvent(xfi->display, button, True, 0); + XTestFakeButtonEvent(xfi->display, button, False, 0); + } + else + { + if (flags & PTR_FLAGS_MOVE) + XTestFakeMotionEvent(xfi->display, 0, x, y, 0); + + if (flags & PTR_FLAGS_BUTTON1) + button = 1; + else if (flags & PTR_FLAGS_BUTTON2) + button = 3; + else if (flags & PTR_FLAGS_BUTTON3) + button = 2; + + if (flags & PTR_FLAGS_DOWN) + down = true; + + if (button != 0) + XTestFakeButtonEvent(xfi->display, button, down, 0); + } +#endif + pthread_mutex_unlock(&(xfp->mutex)); +} + +void xf_input_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y) +{ + xfPeerContext* xfp = (xfPeerContext*) input->context; + xfInfo* xfi = xfp->info; + + pthread_mutex_lock(&(xfp->mutex)); +#ifdef WITH_XTEST + XTestFakeMotionEvent(xfi->display, 0, x, y, CurrentTime); +#endif + pthread_mutex_unlock(&(xfp->mutex)); +} + +void xf_input_register_callbacks(rdpInput* input) +{ + input->SynchronizeEvent = xf_input_synchronize_event; + input->KeyboardEvent = xf_input_keyboard_event; + input->UnicodeKeyboardEvent = xf_input_unicode_keyboard_event; + input->MouseEvent = xf_input_mouse_event; + input->ExtendedMouseEvent = xf_input_extended_mouse_event; +} diff --git a/server/X11/xf_input.h b/server/X11/xf_input.h new file mode 100644 index 000000000..f19d7005a --- /dev/null +++ b/server/X11/xf_input.h @@ -0,0 +1,34 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * X11 Server Input + * + * Copyright 2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __XF_INPUT_H +#define __XF_INPUT_H + +#include + +#include "xfreerdp.h" + +void xf_input_synchronize_event(rdpInput* input, uint32 flags); +void xf_input_keyboard_event(rdpInput* input, uint16 flags, uint16 code); +void xf_input_unicode_keyboard_event(rdpInput* input, uint16 code); +void xf_input_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y); +void xf_input_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y); +void xf_input_register_callbacks(rdpInput* input); + +#endif /* __XF_INPUT_H */ diff --git a/server/X11/xf_peer.c b/server/X11/xf_peer.c index 1ab33f418..e6c70392c 100644 --- a/server/X11/xf_peer.c +++ b/server/X11/xf_peer.c @@ -37,6 +37,8 @@ extern char* xf_pcap_file; extern boolean xf_pcap_dump_realtime; +#include "xf_event.h" +#include "xf_input.h" #include "xf_encode.h" #include "xf_peer.h" @@ -291,11 +293,7 @@ void xf_peer_init(freerdp_peer* client) xfp = (xfPeerContext*) client->context; - xfp->pipe_fd[0] = -1; - xfp->pipe_fd[1] = -1; - - if (pipe(xfp->pipe_fd) < 0) - printf("xf_peer_init: pipe failed\n"); + xfp->event_queue = xf_event_queue_new(); xfp->thread = 0; xfp->activations = 0; @@ -322,43 +320,6 @@ STREAM* xf_peer_stream_init(xfPeerContext* context) return context->s; } -int xf_is_event_set(xfPeerContext* xfp) -{ - fd_set rfds; - int num_set; - struct timeval time; - - FD_ZERO(&rfds); - FD_SET(xfp->pipe_fd[0], &rfds); - memset(&time, 0, sizeof(time)); - num_set = select(xfp->pipe_fd[0] + 1, &rfds, 0, 0, &time); - - return (num_set == 1); -} - -void xf_signal_event(xfPeerContext* xfp) -{ - int length; - - length = write(xfp->pipe_fd[1], "sig", 4); - - if (length != 4) - printf("xf_signal_event: error\n"); -} - -void xf_clear_event(xfPeerContext* xfp) -{ - int length; - - while (xf_is_event_set(xfp)) - { - length = read(xfp->pipe_fd[0], &length, 4); - - if (length != 4) - printf("xf_clear_event: error\n"); - } -} - void* xf_monitor_graphics(void* param) { xfInfo* xfi; @@ -431,7 +392,7 @@ void* xf_monitor_graphics(void* param) region = xfp->hdc->hwnd->invalid; pthread_mutex_unlock(&(xfp->mutex)); - xf_signal_event(xfp); + xf_signal_event(xfp->event_queue); } else { @@ -597,10 +558,10 @@ boolean xf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount) { xfPeerContext* xfp = (xfPeerContext*) client->context; - if (xfp->pipe_fd[0] == -1) + if (xfp->event_queue->pipe_fd[0] == -1) return true; - rfds[*rcount] = (void *)(long) xfp->pipe_fd[0]; + rfds[*rcount] = (void *)(long) xfp->event_queue->pipe_fd[0]; (*rcount)++; return true; @@ -614,17 +575,14 @@ boolean xf_peer_check_fds(freerdp_peer* client) xfp = (xfPeerContext*) client->context; xfi = xfp->info; - if (xfp->pipe_fd[0] == -1) - return true; - if (xfp->activated == false) return true; - if (xf_is_event_set(xfp)) + if (xf_is_event_set(xfp->event_queue)) { HGDI_RGN region; - xf_clear_event(xfp); + xf_clear_event(xfp->event_queue); region = xfp->hdc->hwnd->invalid; @@ -704,99 +662,6 @@ boolean xf_peer_activate(freerdp_peer* client) return true; } -void xf_peer_synchronize_event(rdpInput* input, uint32 flags) -{ - printf("Client sent a synchronize event (flags:0x%X)\n", flags); -} - -void xf_peer_keyboard_event(rdpInput* input, uint16 flags, uint16 code) -{ - unsigned int keycode; - boolean extended = false; - xfPeerContext* xfp = (xfPeerContext*) input->context; - xfInfo* xfi = xfp->info; - - if (flags & KBD_FLAGS_EXTENDED) - extended = true; - - keycode = freerdp_kbd_get_keycode_by_scancode(code, extended); - - if (keycode != 0) - { -#ifdef WITH_XTEST - pthread_mutex_lock(&(xfp->mutex)); - - if (flags & KBD_FLAGS_DOWN) - XTestFakeKeyEvent(xfi->display, keycode, True, 0); - else if (flags & KBD_FLAGS_RELEASE) - XTestFakeKeyEvent(xfi->display, keycode, False, 0); - - pthread_mutex_unlock(&(xfp->mutex)); -#endif - } -} - -void xf_peer_unicode_keyboard_event(rdpInput* input, uint16 code) -{ - printf("Client sent a unicode keyboard event (code:0x%X)\n", code); -} - -void xf_peer_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y) -{ - int button = 0; - boolean down = false; - xfPeerContext* xfp = (xfPeerContext*) input->context; - xfInfo* xfi = xfp->info; - - pthread_mutex_lock(&(xfp->mutex)); -#ifdef WITH_XTEST - - if (flags & PTR_FLAGS_WHEEL) - { - boolean negative = false; - - if (flags & PTR_FLAGS_WHEEL_NEGATIVE) - negative = true; - - button = (negative) ? 5 : 4; - - XTestFakeButtonEvent(xfi->display, button, True, 0); - XTestFakeButtonEvent(xfi->display, button, False, 0); - } - else - { - if (flags & PTR_FLAGS_MOVE) - XTestFakeMotionEvent(xfi->display, 0, x, y, 0); - - if (flags & PTR_FLAGS_BUTTON1) - button = 1; - else if (flags & PTR_FLAGS_BUTTON2) - button = 3; - else if (flags & PTR_FLAGS_BUTTON3) - button = 2; - - if (flags & PTR_FLAGS_DOWN) - down = true; - - if (button != 0) - XTestFakeButtonEvent(xfi->display, button, down, 0); - } -#endif - pthread_mutex_unlock(&(xfp->mutex)); -} - -void xf_peer_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y) -{ - xfPeerContext* xfp = (xfPeerContext*) input->context; - xfInfo* xfi = xfp->info; - - pthread_mutex_lock(&(xfp->mutex)); -#ifdef WITH_XTEST - XTestFakeMotionEvent(xfi->display, 0, x, y, CurrentTime); -#endif - pthread_mutex_unlock(&(xfp->mutex)); -} - void* xf_peer_main_loop(void* arg) { int i; @@ -840,11 +705,7 @@ void* xf_peer_main_loop(void* arg) client->PostConnect = xf_peer_post_connect; client->Activate = xf_peer_activate; - client->input->SynchronizeEvent = xf_peer_synchronize_event; - client->input->KeyboardEvent = xf_peer_keyboard_event; - client->input->UnicodeKeyboardEvent = xf_peer_unicode_keyboard_event; - client->input->MouseEvent = xf_peer_mouse_event; - client->input->ExtendedMouseEvent = xf_peer_extended_mouse_event; + xf_input_register_callbacks(client->input); client->Initialize(client); diff --git a/server/X11/xf_peer.h b/server/X11/xf_peer.h index e1b774a08..255e20733 100644 --- a/server/X11/xf_peer.h +++ b/server/X11/xf_peer.h @@ -28,6 +28,8 @@ #include #include +typedef struct xf_peer_context xfPeerContext; + #include "xfreerdp.h" struct xf_peer_context @@ -37,7 +39,6 @@ struct xf_peer_context HGDI_DC hdc; STREAM* s; xfInfo* info; - int pipe_fd[2]; boolean activated; RFX_CONTEXT* rfx_context; uint8* capture_buffer; @@ -45,8 +46,8 @@ struct xf_peer_context int activations; STOPWATCH* stopwatch; pthread_mutex_t mutex; + xfEventQueue* event_queue; }; -typedef struct xf_peer_context xfPeerContext; void xf_peer_accepted(freerdp_listener* instance, freerdp_peer* client); diff --git a/server/X11/xfreerdp.h b/server/X11/xfreerdp.h index 335e3dbad..2a6fc2673 100644 --- a/server/X11/xfreerdp.h +++ b/server/X11/xfreerdp.h @@ -38,6 +38,10 @@ #include #endif +typedef struct xf_info xfInfo; + +#include "xf_event.h" + struct xf_info { int bpp; @@ -66,6 +70,5 @@ struct xf_info XserverRegion xdamage_region; #endif }; -typedef struct xf_info xfInfo; #endif /* __XFREERDP_H */