2 * FreeRDP: A Remote Desktop Protocol Client
5 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 #include <X11/Xutil.h>
23 #include <freerdp/kbd/kbd.h>
24 #include <freerdp/kbd/vkcodes.h>
27 #include "xf_cliprdr.h"
31 static const char* const X11_EVENT_STRINGS[] =
70 void xf_send_mouse_motion_event(rdpInput* input, boolean down, uint32 button, uint16 x, uint16 y)
72 input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
75 boolean xf_event_Expose(xfInfo* xfi, XEvent* event, boolean app)
82 w = event->xexpose.width;
83 h = event->xexpose.height;
87 XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y);
93 rdpRail* rail = ((rdpContext*) xfi->context)->rail;
95 window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window);
99 xfw = (xfWindow*) window->extra;
100 xf_UpdateWindowArea(xfi, xfw, x, y, w, h);
107 boolean xf_event_VisibilityNotify(xfInfo* xfi, XEvent* event, boolean app)
109 xfi->unobscured = event->xvisibility.state == VisibilityUnobscured;
113 boolean xf_event_MotionNotify(xfInfo* xfi, XEvent* event, boolean app)
117 input = xfi->instance->input;
121 if (xfi->mouse_motion != true)
123 if ((event->xmotion.state & (Button1Mask | Button2Mask | Button3Mask)) == 0)
127 input->MouseEvent(input, PTR_FLAGS_MOVE, event->xmotion.x, event->xmotion.y);
130 XSetInputFocus(xfi->display, xfi->window->handle, RevertToPointerRoot, CurrentTime);
132 else if (xfi->mouse_motion == true)
135 int x = event->xmotion.x;
136 int y = event->xmotion.y;
137 rdpRail* rail = ((rdpContext*) xfi->context)->rail;
139 window = window_list_get_by_extra_id(rail->list, (void*) event->xmotion.window);
143 x += window->windowOffsetX;
144 y += window->windowOffsetY;
145 input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
152 boolean xf_event_ButtonPress(xfInfo* xfi, XEvent* event, boolean app)
159 input = xfi->instance->input;
166 switch (event->xbutton.button)
169 x = event->xbutton.x;
170 y = event->xbutton.y;
171 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1;
175 x = event->xbutton.x;
176 y = event->xbutton.y;
177 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3;
181 x = event->xbutton.x;
182 y = event->xbutton.y;
183 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2;
188 flags = PTR_FLAGS_WHEEL | 0x0078;
193 flags = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
207 input->MouseEvent(input, flags, 0, 0);
214 rdpRail* rail = ((rdpContext*) xfi->context)->rail;
216 window = window_list_get_by_extra_id(rail->list, (void*) event->xbutton.window);
220 x += window->windowOffsetX;
221 y += window->windowOffsetY;
225 input->MouseEvent(input, flags, x, y);
232 boolean xf_event_ButtonRelease(xfInfo* xfi, XEvent* event, boolean app)
238 input = xfi->instance->input;
244 switch (event->xbutton.button)
247 x = event->xbutton.x;
248 y = event->xbutton.y;
249 flags = PTR_FLAGS_BUTTON1;
253 x = event->xbutton.x;
254 y = event->xbutton.y;
255 flags = PTR_FLAGS_BUTTON3;
259 x = event->xbutton.x;
260 y = event->xbutton.y;
261 flags = PTR_FLAGS_BUTTON2;
274 rdpRail* rail = ((rdpContext*) xfi->context)->rail;
276 window = window_list_get_by_extra_id(rail->list, (void*) event->xbutton.window);
280 x += window->windowOffsetX;
281 y += window->windowOffsetY;
285 input->MouseEvent(input, flags, x, y);
291 boolean xf_event_KeyPress(xfInfo* xfi, XEvent* event, boolean app)
296 XLookupString((XKeyEvent*) event, str, sizeof(str), &keysym, NULL);
298 xf_kbd_set_keypress(xfi, event->xkey.keycode, keysym);
300 if (xfi->fullscreen_toggle && xf_kbd_handle_special_keys(xfi, keysym))
303 xf_kbd_send_key(xfi, true, event->xkey.keycode);
308 boolean xf_event_KeyRelease(xfInfo* xfi, XEvent* event, boolean app)
312 if (XPending(xfi->display))
314 memset(&next_event, 0, sizeof(next_event));
315 XPeekEvent(xfi->display, &next_event);
317 if (next_event.type == KeyPress)
319 if (next_event.xkey.keycode == event->xkey.keycode)
324 xf_kbd_unset_keypress(xfi, event->xkey.keycode);
325 xf_kbd_send_key(xfi, false, event->xkey.keycode);
330 boolean xf_event_FocusIn(xfInfo* xfi, XEvent* event, boolean app)
332 if (event->xfocus.mode == NotifyGrab)
337 if (xfi->mouse_active && (app != true))
338 XGrabKeyboard(xfi->display, xfi->window->handle, true, GrabModeAsync, GrabModeAsync, CurrentTime);
340 xf_rail_send_activate(xfi, event->xany.window, true);
341 xf_kbd_focus_in(xfi);
343 if (xfi->remote_app != true)
344 xf_cliprdr_check_owner(xfi);
349 boolean xf_event_FocusOut(xfInfo* xfi, XEvent* event, boolean app)
351 if (event->xfocus.mode == NotifyUngrab)
354 xfi->focused = false;
356 if (event->xfocus.mode == NotifyWhileGrabbed)
357 XUngrabKeyboard(xfi->display, CurrentTime);
359 xf_rail_send_activate(xfi, event->xany.window, false);
364 boolean xf_event_MappingNotify(xfInfo* xfi, XEvent* event, boolean app)
366 if (event->xmapping.request == MappingModifier)
368 XFreeModifiermap(xfi->modifier_map);
369 xfi->modifier_map = XGetModifierMapping(xfi->display);
375 boolean xf_event_ClientMessage(xfInfo* xfi, XEvent* event, boolean app)
377 if ((event->xclient.message_type == xfi->WM_PROTOCOLS)
378 && ((Atom) event->xclient.data.l[0] == xfi->WM_DELETE_WINDOW))
383 rdpRail* rail = ((rdpContext*) xfi->context)->rail;
385 window = window_list_get_by_extra_id(rail->list, (void*) event->xclient.window);
389 xf_rail_send_client_system_command(xfi, window->windowId, SC_CLOSE);
403 boolean xf_event_EnterNotify(xfInfo* xfi, XEvent* event, boolean app)
407 xfi->mouse_active = true;
410 XSetInputFocus(xfi->display, xfi->window->handle, RevertToPointerRoot, CurrentTime);
413 XGrabKeyboard(xfi->display, xfi->window->handle, true, GrabModeAsync, GrabModeAsync, CurrentTime);
415 // Keep track of which window has focus so that we can apply pointer updates
418 rdpRail* rail = ((rdpContext*) xfi->context)->rail;
419 window = window_list_get_by_extra_id(rail->list, (void*) event->xexpose.window);
422 xfw = (xfWindow*) window->extra;
430 boolean xf_event_LeaveNotify(xfInfo* xfi, XEvent* event, boolean app)
434 xfi->mouse_active = false;
435 XUngrabKeyboard(xfi->display, CurrentTime);
441 boolean xf_event_ConfigureNotify(xfInfo* xfi, XEvent* event, boolean app)
444 rdpRail* rail = ((rdpContext*) xfi->context)->rail;
446 window = window_list_get_by_extra_id(rail->list, (void*) event->xconfigure.window);
452 uint32 right, bottom;
453 uint32 width, height;
454 xfw = (xfWindow*) window->extra;
456 left = event->xconfigure.x;
457 top = event->xconfigure.y;
458 width = event->xconfigure.width;
459 height = event->xconfigure.height;
460 right = left + width - 1;
461 bottom = top + height - 1;
463 DEBUG_X11_LMS("ConfigureNotify: send_event=%d eventWindow=0x%X window=0x%X above=0x%X rc={l=%d t=%d r=%d b=%d} "
464 "w=%d h=%d override_redirect=%d",
465 event->xconfigure.send_event,
466 (uint32) event->xconfigure.event,
467 (uint32) event->xconfigure.window,
468 (uint32) event->xconfigure.above,
469 left, top, right, bottom, width, height,
470 event->xconfigure.override_redirect);
476 boolean xf_event_MapNotify(xfInfo* xfi, XEvent* event, boolean app)
479 rdpRail* rail = ((rdpContext*) xfi->context)->rail;
484 window = window_list_get_by_extra_id(rail->list, (void*) event->xany.window);
488 /* local restore event */
489 xf_rail_send_client_system_command(xfi, window->windowId, SC_RESTORE);
495 boolean xf_event_SelectionNotify(xfInfo* xfi, XEvent* event, boolean app)
497 if (xfi->remote_app != true)
499 if (xf_cliprdr_process_selection_notify(xfi, event))
506 boolean xf_event_SelectionRequest(xfInfo* xfi, XEvent* event, boolean app)
508 if (xfi->remote_app != true)
510 if (xf_cliprdr_process_selection_request(xfi, event))
517 boolean xf_event_SelectionClear(xfInfo* xfi, XEvent* event, boolean app)
519 if (xfi->remote_app != true)
521 if (xf_cliprdr_process_selection_clear(xfi, event))
528 boolean xf_event_PropertyNotify(xfInfo* xfi, XEvent* event, boolean app)
530 if (xfi->remote_app != true)
532 if (xf_cliprdr_process_property_notify(xfi, event))
539 boolean xf_event_process(freerdp* instance, XEvent* event)
542 boolean status = true;
543 xfInfo* xfi = ((xfContext*) instance->context)->xfi;
545 if (xfi->remote_app == true)
551 if (event->xany.window != xfi->window->handle)
556 if (event->type != MotionNotify)
557 DEBUG_X11("%s Event: wnd=0x%04X", X11_EVENT_STRINGS[event->type], (uint32) event->xany.window);
562 status = xf_event_Expose(xfi, event, app);
565 case VisibilityNotify:
566 status = xf_event_VisibilityNotify(xfi, event, app);
570 status = xf_event_MotionNotify(xfi, event, app);
574 status = xf_event_ButtonPress(xfi, event, app);
578 status = xf_event_ButtonRelease(xfi, event, app);
582 status = xf_event_KeyPress(xfi, event, app);
586 status = xf_event_KeyRelease(xfi, event, app);
590 status = xf_event_FocusIn(xfi, event, app);
594 status = xf_event_FocusOut(xfi, event, app);
598 status = xf_event_EnterNotify(xfi, event, app);
602 status = xf_event_LeaveNotify(xfi, event, app);
611 case ConfigureNotify:
612 status = xf_event_ConfigureNotify(xfi, event, app);
616 status = xf_event_MapNotify(xfi, event, app);
623 status = xf_event_MappingNotify(xfi, event, app);
627 status = xf_event_ClientMessage(xfi, event, app);
630 case SelectionNotify:
631 status = xf_event_SelectionNotify(xfi, event, app);
634 case SelectionRequest:
635 status = xf_event_SelectionRequest(xfi, event, app);
639 status = xf_event_SelectionClear(xfi, event, app);
643 status = xf_event_PropertyNotify(xfi, event, app);
647 DEBUG_X11("xf_event_process unknown event %d", event->type);