diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 4a92692f5..f7e5942af 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -868,7 +868,7 @@ BOOL xf_pre_connect(freerdp* instance) xfc->WM_DELETE_WINDOW = XInternAtom(xfc->display, "WM_DELETE_WINDOW", False); xfc->WM_STATE = XInternAtom(xfc->display, "WM_STATE", False); - xf_kbd_init(xfc); + xf_keyboard_init(xfc); xfc->clrconv = freerdp_clrconv_new(CLRCONV_ALPHA); @@ -972,10 +972,10 @@ BOOL xf_post_connect(freerdp* instance) ZeroMemory(&gcv, sizeof(gcv)); - if (xfc->modifier_map) - XFreeModifiermap(xfc->modifier_map); + if (xfc->modifierMap) + XFreeModifiermap(xfc->modifierMap); - xfc->modifier_map = XGetModifierMapping(xfc->display); + xfc->modifierMap = XGetModifierMapping(xfc->display); xfc->gc = XCreateGC(xfc->display, xfc->drawable, GCGraphicsExposures, &gcv); xfc->primary = XCreatePixmap(xfc->display, xfc->drawable, xfc->width, xfc->height, xfc->depth); @@ -1161,11 +1161,7 @@ void xf_window_free(xfContext* xfc) { rdpContext* context = (rdpContext*) xfc; - if (xfc->modifier_map) - { - XFreeModifiermap(xfc->modifier_map); - xfc->modifier_map = NULL; - } + xf_keyboard_free(xfc); if (xfc->gc) { @@ -1515,8 +1511,8 @@ void* xf_thread(void* param) */ if (freerdp_focus_required(instance)) { - xf_kbd_focus_in(xfc); - xf_kbd_focus_in(xfc); + xf_keyboard_focus_in(xfc); + xf_keyboard_focus_in(xfc); } if (!async_transport) diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c index 6bd6d561f..d6f0c8dd7 100644 --- a/client/X11/xf_event.c +++ b/client/X11/xf_event.c @@ -87,6 +87,99 @@ const char* const X11_EVENT_STRINGS[] = #define DEBUG_X11_LMS(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) #endif +int xf_event_action_script_init(xfContext* xfc) +{ + int exitCode; + char* xevent; + FILE* actionScript; + char buffer[1024] = { 0 }; + char command[1024] = { 0 }; + + xfc->xevents = ArrayList_New(TRUE); + ArrayList_Object(xfc->xevents)->fnObjectFree = free; + + sprintf_s(command, sizeof(command), "%s xevent", xfc->actionScript); + + actionScript = popen(command, "r"); + + if (actionScript < 0) + return -1; + + while (fgets(buffer, sizeof(buffer), actionScript) != NULL) + { + strtok(buffer, "\n"); + xevent = _strdup(buffer); + ArrayList_Add(xfc->xevents, xevent); + } + + exitCode = pclose(actionScript); + + return 1; +} + +void xf_event_action_script_free(xfContext* xfc) +{ + if (xfc->xevents) + { + ArrayList_Free(xfc->xevents); + xfc->xevents = NULL; + } +} + +int xf_event_execute_action_script(xfContext* xfc, XEvent* event) +{ + int index; + int count; + char* name; + int exitCode; + FILE* actionScript; + BOOL match = FALSE; + const char* xeventName; + char buffer[1024] = { 0 }; + char command[1024] = { 0 }; + + if (!xfc->actionScript) + return 1; + + if (event->type > (sizeof(X11_EVENT_STRINGS) / sizeof(const char*))) + return 1; + + xeventName = X11_EVENT_STRINGS[event->type]; + + count = ArrayList_Count(xfc->xevents); + + for (index = 0; index < count; index++) + { + name = (char*) ArrayList_GetItem(xfc->xevents, index); + + if (_stricmp(name, xeventName) == 0) + { + match = TRUE; + break; + } + } + + if (!match) + return 1; + + sprintf_s(command, sizeof(command), "%s xevent %s %d", + xfc->actionScript, xeventName, (int) xfc->window->handle); + + actionScript = popen(command, "r"); + + if (actionScript < 0) + return -1; + + while (fgets(buffer, sizeof(buffer), actionScript) != NULL) + { + strtok(buffer, "\n"); + } + + exitCode = pclose(actionScript); + + return 1; +} + static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app) { int x, y; @@ -395,34 +488,28 @@ static BOOL xf_event_KeyPress(xfContext* xfc, XEvent* event, BOOL app) XLookupString((XKeyEvent*) event, str, sizeof(str), &keysym, NULL); - xf_kbd_set_keypress(xfc, event->xkey.keycode, keysym); - - if (xfc->fullscreen_toggle && xf_kbd_handle_special_keys(xfc, keysym)) - return TRUE; - - xf_kbd_send_key(xfc, TRUE, event->xkey.keycode); + xf_keyboard_key_press(xfc, event->xkey.keycode, keysym); return TRUE; } static BOOL xf_event_KeyRelease(xfContext* xfc, XEvent* event, BOOL app) { - XEvent next_event; + XEvent nextEvent; if (XPending(xfc->display)) { - ZeroMemory(&next_event, sizeof(next_event)); - XPeekEvent(xfc->display, &next_event); + ZeroMemory(&nextEvent, sizeof(nextEvent)); + XPeekEvent(xfc->display, &nextEvent); - if (next_event.type == KeyPress) + if (nextEvent.type == KeyPress) { - if (next_event.xkey.keycode == event->xkey.keycode) + if (nextEvent.xkey.keycode == event->xkey.keycode) return TRUE; } } - xf_kbd_unset_keypress(xfc, event->xkey.keycode); - xf_kbd_send_key(xfc, FALSE, event->xkey.keycode); + xf_keyboard_key_release(xfc, event->xkey.keycode); return TRUE; } @@ -451,7 +538,7 @@ static BOOL xf_event_FocusIn(xfContext* xfc, XEvent* event, BOOL app) xf_rail_adjust_position(xfc, window); } - xf_kbd_focus_in(xfc); + xf_keyboard_focus_in(xfc); if (!app) xf_cliprdr_check_owner(xfc); @@ -469,7 +556,7 @@ static BOOL xf_event_FocusOut(xfContext* xfc, XEvent* event, BOOL app) if (event->xfocus.mode == NotifyWhileGrabbed) XUngrabKeyboard(xfc->display, CurrentTime); - xf_kbd_clear(xfc); + xf_keyboard_clear(xfc); if (app) xf_rail_send_activate(xfc, event->xany.window, FALSE); @@ -481,10 +568,10 @@ static BOOL xf_event_MappingNotify(xfContext* xfc, XEvent* event, BOOL app) { if (event->xmapping.request == MappingModifier) { - if (xfc->modifier_map) - XFreeModifiermap(xfc->modifier_map); + if (xfc->modifierMap) + XFreeModifiermap(xfc->modifierMap); - xfc->modifier_map = XGetModifierMapping(xfc->display); + xfc->modifierMap = XGetModifierMapping(xfc->display); } return TRUE; @@ -681,7 +768,7 @@ static BOOL xf_event_UnmapNotify(xfContext* xfc, XEvent* event, BOOL app) rdpUpdate* update = xfc->instance->update; rdpRail* rail = ((rdpContext*) xfc)->rail; - xf_kbd_release_all_keypress(xfc); + xf_keyboard_release_all_keypress(xfc); if (!app) { @@ -941,6 +1028,8 @@ BOOL xf_event_process(freerdp* instance, XEvent* event) } } + xf_event_execute_action_script(xfc, event); + if (event->type != MotionNotify) DEBUG_X11("%s Event(%d): wnd=0x%04X", X11_EVENT_STRINGS[event->type], event->type, (UINT32) event->xany.window); diff --git a/client/X11/xf_event.h b/client/X11/xf_event.h index 05d4e3e04..4198ab2f2 100644 --- a/client/X11/xf_event.h +++ b/client/X11/xf_event.h @@ -25,6 +25,9 @@ #include "xf_client.h" #include "xfreerdp.h" +int xf_event_action_script_init(xfContext* xfc); +void xf_event_action_script_free(xfContext* xfc); + BOOL xf_event_process(freerdp* instance, XEvent* event); void xf_event_SendClientEvent(xfContext* xfc, xfWindow* window, Atom atom, unsigned int numArgs, ...); diff --git a/client/X11/xf_input.c b/client/X11/xf_input.c index 8d1adf509..9549bdb3a 100644 --- a/client/X11/xf_input.c +++ b/client/X11/xf_input.c @@ -236,7 +236,6 @@ void xf_input_save_last_event(XGenericEventCookie* cookie) lastEvent.detail = event->detail; lastEvent.event_x = event->event_x; lastEvent.event_y = event->event_y; - } void xf_input_detect_pan(xfContext* xfc) @@ -269,13 +268,10 @@ void xf_input_detect_pan(xfContext* xfc) dist_x = fabs(contacts[0].pos_x - contacts[1].pos_x); dist_y = fabs(contacts[0].pos_y - contacts[1].pos_y); - - - //only pan in x if dist_y is greater than something - if(dist_y > MIN_FINGER_DIST) + + if (dist_y > MIN_FINGER_DIST) { - - if(px_vector > PAN_THRESHOLD) + if (px_vector > PAN_THRESHOLD) { { @@ -293,7 +289,7 @@ void xf_input_detect_pan(xfContext* xfc) py_vector = 0; z_vector = 0; } - else if(px_vector < -PAN_THRESHOLD) + else if (px_vector < -PAN_THRESHOLD) { { PanningChangeEventArgs e; @@ -313,10 +309,10 @@ void xf_input_detect_pan(xfContext* xfc) } - if(dist_x > MIN_FINGER_DIST) + if (dist_x > MIN_FINGER_DIST) { - if(py_vector > PAN_THRESHOLD) + if (py_vector > PAN_THRESHOLD) { { PanningChangeEventArgs e; @@ -333,7 +329,7 @@ void xf_input_detect_pan(xfContext* xfc) py_vector = 0; z_vector = 0; } - else if(py_vector < -PAN_THRESHOLD) + else if (py_vector < -PAN_THRESHOLD) { { PanningChangeEventArgs e; @@ -351,7 +347,6 @@ void xf_input_detect_pan(xfContext* xfc) z_vector = 0; } } - } void xf_input_detect_pinch(xfContext* xfc) @@ -368,7 +363,6 @@ void xf_input_detect_pinch(xfContext* xfc) return; } - /* first calculate the distance */ dist = sqrt(pow(contacts[1].pos_x - contacts[0].last_x, 2.0) + pow(contacts[1].pos_y - contacts[0].last_y, 2.0)); @@ -399,7 +393,6 @@ void xf_input_detect_pinch(xfContext* xfc) z_vector += delta; - lastDist = dist; if (z_vector > ZOOM_THRESHOLD) @@ -451,8 +444,6 @@ void xf_input_detect_pinch(xfContext* xfc) void xf_input_touch_begin(xfContext* xfc, XIDeviceEvent* event) { int i; - if(active_contacts == MAX_CONTACTS) - printf("Houston, we have a problem!\n\n"); for (i = 0; i < MAX_CONTACTS; i++) { @@ -472,6 +463,7 @@ void xf_input_touch_begin(xfContext* xfc, XIDeviceEvent* event) void xf_input_touch_update(xfContext* xfc, XIDeviceEvent* event) { int i; + for (i = 0; i < MAX_CONTACTS; i++) { if (contacts[i].id == event->detail) @@ -493,14 +485,13 @@ void xf_input_touch_update(xfContext* xfc, XIDeviceEvent* event) void xf_input_touch_end(xfContext* xfc, XIDeviceEvent* event) { int i; + for (i = 0; i < MAX_CONTACTS; i++) { if (contacts[i].id == event->detail) { contacts[i].id = 0; contacts[i].count = 0; - //contacts[i].pos_x = (int)event->event_x; - //contacts[i].pos_y = (int)event->event_y; active_contacts--; break;printf("TouchBegin\n"); @@ -733,15 +724,15 @@ void xf_process_rdpei_event(xfContext* xfc, wMessage* event) int xf_input_handle_event(xfContext* xfc, XEvent* event) { #ifdef WITH_XI - //printf("m:%d g:%d\n", (xfc->settings->MultiTouchInput), (xfc->settings->MultiTouchGestures) ); if (xfc->settings->MultiTouchInput) { return xf_input_handle_event_remote(xfc, event); } if (xfc->settings->MultiTouchGestures) + { return xf_input_handle_event_local(xfc, event); - + } #endif return 0; diff --git a/client/X11/xf_keyboard.c b/client/X11/xf_keyboard.c index e6427e190..358b6d099 100644 --- a/client/X11/xf_keyboard.c +++ b/client/X11/xf_keyboard.c @@ -26,6 +26,8 @@ #include #include +#include +#include #include #include @@ -33,66 +35,153 @@ #include +#include "xf_event.h" + #include "xf_keyboard.h" -void xf_kbd_init(xfContext* xfc) +int xf_keyboard_action_script_init(xfContext* xfc) { - xf_kbd_clear(xfc); + int exitCode; + FILE* keyScript; + char* keyCombination; + char buffer[1024] = { 0 }; + char command[1024] = { 0 }; - xfc->keyboard_layout_id = xfc->instance->settings->KeyboardLayout; - xfc->keyboard_layout_id = freerdp_keyboard_init(xfc->keyboard_layout_id); - xfc->instance->settings->KeyboardLayout = xfc->keyboard_layout_id; + if (xfc->actionScript) + { + free(xfc->actionScript); + xfc->actionScript = NULL; + } - if (xfc->modifier_map) - XFreeModifiermap(xfc->modifier_map); + if (PathFileExistsA("/usr/share/freerdp/action.sh")) + xfc->actionScript = _strdup("/usr/share/freerdp/action.sh"); - xfc->modifier_map = XGetModifierMapping(xfc->display); + if (!xfc->actionScript) + return 0; + + xfc->keyCombinations = ArrayList_New(TRUE); + ArrayList_Object(xfc->keyCombinations)->fnObjectFree = free; + + sprintf_s(command, sizeof(command), "%s key", xfc->actionScript); + + keyScript = popen(command, "r"); + + if (keyScript < 0) + { + free(xfc->actionScript); + xfc->actionScript = NULL; + return 0; + } + + while (fgets(buffer, sizeof(buffer), keyScript) != NULL) + { + strtok(buffer, "\n"); + keyCombination = _strdup(buffer); + ArrayList_Add(xfc->keyCombinations, keyCombination); + } + + exitCode = pclose(keyScript); + + xf_event_action_script_init(xfc); + + return 1; } -void xf_kbd_clear(xfContext* xfc) +void xf_keyboard_action_script_free(xfContext* xfc) { - ZeroMemory(xfc->pressed_keys, 256 * sizeof(BOOL)); + xf_event_action_script_free(xfc); + + if (xfc->keyCombinations) + { + ArrayList_Free(xfc->keyCombinations); + xfc->keyCombinations = NULL; + } + + if (xfc->actionScript) + { + free(xfc->actionScript); + xfc->actionScript = NULL; + } } -void xf_kbd_set_keypress(xfContext* xfc, BYTE keycode, KeySym keysym) +void xf_keyboard_init(xfContext* xfc) { - if (keycode >= 8) - xfc->pressed_keys[keycode] = keysym; - else + xf_keyboard_clear(xfc); + + xfc->KeyboardLayout = xfc->instance->settings->KeyboardLayout; + xfc->KeyboardLayout = freerdp_keyboard_init(xfc->KeyboardLayout); + xfc->instance->settings->KeyboardLayout = xfc->KeyboardLayout; + + if (xfc->modifierMap) + XFreeModifiermap(xfc->modifierMap); + + xfc->modifierMap = XGetModifierMapping(xfc->display); + + xf_keyboard_action_script_init(xfc); +} + +void xf_keyboard_free(xfContext* xfc) +{ + if (xfc->modifierMap) + { + XFreeModifiermap(xfc->modifierMap); + xfc->modifierMap = NULL; + } + + xf_keyboard_action_script_free(xfc); +} + +void xf_keyboard_clear(xfContext* xfc) +{ + ZeroMemory(xfc->KeyboardState, 256 * sizeof(BOOL)); +} + +void xf_keyboard_key_press(xfContext* xfc, BYTE keycode, KeySym keysym) +{ + if (keycode < 8) return; -} -void xf_kbd_unset_keypress(xfContext* xfc, BYTE keycode) -{ - if (keycode >= 8) - xfc->pressed_keys[keycode] = NoSymbol; - else + xfc->KeyboardState[keycode] = keysym; + + if (xf_keyboard_handle_special_keys(xfc, keysym)) return; + + xf_keyboard_send_key(xfc, TRUE, keycode); } -void xf_kbd_release_all_keypress(xfContext* xfc) +void xf_keyboard_key_release(xfContext* xfc, BYTE keycode) +{ + if (keycode < 8) + return; + + xfc->KeyboardState[keycode] = NoSymbol; + + xf_keyboard_send_key(xfc, FALSE, keycode); +} + +void xf_keyboard_release_all_keypress(xfContext* xfc) { int keycode; DWORD rdp_scancode; - for (keycode = 0; keycode < ARRAYSIZE(xfc->pressed_keys); keycode++) + for (keycode = 0; keycode < ARRAYSIZE(xfc->KeyboardState); keycode++) { - if (xfc->pressed_keys[keycode] != NoSymbol) + if (xfc->KeyboardState[keycode] != NoSymbol) { rdp_scancode = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(keycode); freerdp_input_send_keyboard_event_ex(xfc->instance->input, FALSE, rdp_scancode); - xfc->pressed_keys[keycode] = NoSymbol; + xfc->KeyboardState[keycode] = NoSymbol; } } } -BOOL xf_kbd_key_pressed(xfContext* xfc, KeySym keysym) +BOOL xf_keyboard_key_pressed(xfContext* xfc, KeySym keysym) { KeyCode keycode = XKeysymToKeycode(xfc->display, keysym); - return (xfc->pressed_keys[keycode] == keysym); + return (xfc->KeyboardState[keycode] == keysym); } -void xf_kbd_send_key(xfContext* xfc, BOOL down, BYTE keycode) +void xf_keyboard_send_key(xfContext* xfc, BOOL down, BYTE keycode) { DWORD rdp_scancode; rdpInput* input; @@ -105,7 +194,7 @@ void xf_kbd_send_key(xfContext* xfc, BOOL down, BYTE keycode) fprintf(stderr, "Unknown key with X keycode 0x%02x\n", keycode); } else if (rdp_scancode == RDP_SCANCODE_PAUSE && - !xf_kbd_key_pressed(xfc, XK_Control_L) && !xf_kbd_key_pressed(xfc, XK_Control_R)) + !xf_keyboard_key_pressed(xfc, XK_Control_L) && !xf_keyboard_key_pressed(xfc, XK_Control_R)) { /* Pause without Ctrl has to be sent as Ctrl + NumLock. */ if (down) @@ -123,13 +212,13 @@ void xf_kbd_send_key(xfContext* xfc, BOOL down, BYTE keycode) if ((rdp_scancode == RDP_SCANCODE_CAPSLOCK) && (down == FALSE)) { UINT32 syncFlags; - syncFlags = xf_kbd_get_toggle_keys_state(xfc); + syncFlags = xf_keyboard_get_toggle_keys_state(xfc); input->SynchronizeEvent(input, syncFlags); } } } -int xf_kbd_read_keyboard_state(xfContext* xfc) +int xf_keyboard_read_keyboard_state(xfContext* xfc) { int dummy; Window wdummy; @@ -145,10 +234,11 @@ int xf_kbd_read_keyboard_state(xfContext* xfc) XQueryPointer(xfc->display, DefaultRootWindow(xfc->display), &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state); } + return state; } -BOOL xf_kbd_get_key_state(xfContext* xfc, int state, int keysym) +BOOL xf_keyboard_get_key_state(xfContext* xfc, int state, int keysym) { int offset; int modifierpos, key, keysymMask = 0; @@ -159,11 +249,11 @@ BOOL xf_kbd_get_key_state(xfContext* xfc, int state, int keysym) for (modifierpos = 0; modifierpos < 8; modifierpos++) { - offset = xfc->modifier_map->max_keypermod * modifierpos; + offset = xfc->modifierMap->max_keypermod * modifierpos; - for (key = 0; key < xfc->modifier_map->max_keypermod; key++) + for (key = 0; key < xfc->modifierMap->max_keypermod; key++) { - if (xfc->modifier_map->modifiermap[offset + key] == keycode) + if (xfc->modifierMap->modifiermap[offset + key] == keycode) { keysymMask |= 1 << modifierpos; } @@ -173,26 +263,26 @@ BOOL xf_kbd_get_key_state(xfContext* xfc, int state, int keysym) return (state & keysymMask) ? TRUE : FALSE; } -int xf_kbd_get_toggle_keys_state(xfContext* xfc) +UINT32 xf_keyboard_get_toggle_keys_state(xfContext* xfc) { int state; - int toggle_keys_state = 0; + UINT32 toggleKeysState = 0; - state = xf_kbd_read_keyboard_state(xfc); + state = xf_keyboard_read_keyboard_state(xfc); - if (xf_kbd_get_key_state(xfc, state, XK_Scroll_Lock)) - toggle_keys_state |= KBD_SYNC_SCROLL_LOCK; - if (xf_kbd_get_key_state(xfc, state, XK_Num_Lock)) - toggle_keys_state |= KBD_SYNC_NUM_LOCK; - if (xf_kbd_get_key_state(xfc, state, XK_Caps_Lock)) - toggle_keys_state |= KBD_SYNC_CAPS_LOCK; - if (xf_kbd_get_key_state(xfc, state, XK_Kana_Lock)) - toggle_keys_state |= KBD_SYNC_KANA_LOCK; + if (xf_keyboard_get_key_state(xfc, state, XK_Scroll_Lock)) + toggleKeysState |= KBD_SYNC_SCROLL_LOCK; + if (xf_keyboard_get_key_state(xfc, state, XK_Num_Lock)) + toggleKeysState |= KBD_SYNC_NUM_LOCK; + if (xf_keyboard_get_key_state(xfc, state, XK_Caps_Lock)) + toggleKeysState |= KBD_SYNC_CAPS_LOCK; + if (xf_keyboard_get_key_state(xfc, state, XK_Kana_Lock)) + toggleKeysState |= KBD_SYNC_KANA_LOCK; - return toggle_keys_state; + return toggleKeysState; } -void xf_kbd_focus_in(xfContext* xfc) +void xf_keyboard_focus_in(xfContext* xfc) { rdpInput* input; UINT32 syncFlags; @@ -200,39 +290,141 @@ void xf_kbd_focus_in(xfContext* xfc) Window wdummy; UINT32 state = 0; - if (xfc->display && xfc->window) - { - input = xfc->instance->input; - syncFlags = xf_kbd_get_toggle_keys_state(xfc); - XQueryPointer(xfc->display, xfc->window->handle, &wdummy, &wdummy, &mouseX, &mouseY, &dummy, &dummy, &state); - input->FocusInEvent(input, syncFlags, mouseX, mouseY); + if (xfc->display && xfc->window) + { + input = xfc->instance->input; + syncFlags = xf_keyboard_get_toggle_keys_state(xfc); + XQueryPointer(xfc->display, xfc->window->handle, &wdummy, &wdummy, &mouseX, &mouseY, &dummy, &dummy, &state); + input->FocusInEvent(input, syncFlags, mouseX, mouseY); } } -BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym) +int xf_keyboard_execute_action_script(xfContext* xfc, XF_MODIFIER_KEYS* mod, KeySym keysym) { + int index; + int count; + int exitCode; + int status = 1; + FILE* keyScript; + const char* keyStr; + BOOL match = FALSE; + char* keyCombination; + char buffer[1024] = { 0 }; + char command[1024] = { 0 }; + char combination[1024] = { 0 }; + + if (!xfc->actionScript) + return 1; + + if ((keysym == XK_Shift_L) || (keysym == XK_Shift_R) || + (keysym == XK_Alt_L) || (keysym == XK_Alt_R) || + (keysym == XK_Control_L) || (keysym == XK_Control_R)) + { + return 1; + } + + keyStr = XKeysymToString(keysym); + + if (mod->Shift) + strcat(combination, "Shift+"); + + if (mod->Ctrl) + strcat(combination, "Ctrl+"); + + if (mod->Alt) + strcat(combination, "Alt+"); + + strcat(combination, keyStr); + + count = ArrayList_Count(xfc->keyCombinations); + + for (index = 0; index < count; index++) + { + keyCombination = (char*) ArrayList_GetItem(xfc->keyCombinations, index); + + if (_stricmp(keyCombination, combination) == 0) + { + match = TRUE; + break; + } + } + + if (!match) + return 1; + + sprintf_s(command, sizeof(command), "%s key %s", + xfc->actionScript, combination); + + keyScript = popen(command, "r"); + + if (keyScript < 0) + return -1; + + while (fgets(buffer, sizeof(buffer), keyScript) != NULL) + { + strtok(buffer, "\n"); + + if (strcmp(buffer, "key-local") == 0) + status = 0; + } + + exitCode = pclose(keyScript); + + return status; +} + +int xk_keyboard_get_modifier_keys(xfContext* xfc, XF_MODIFIER_KEYS* mod) +{ + mod->LeftShift = xf_keyboard_key_pressed(xfc, XK_Shift_L); + mod->RightShift = xf_keyboard_key_pressed(xfc, XK_Shift_R); + mod->Shift = mod->LeftShift || mod->RightShift; + + mod->LeftAlt = xf_keyboard_key_pressed(xfc, XK_Alt_L); + mod->RightAlt = xf_keyboard_key_pressed(xfc, XK_Alt_R); + mod->Alt = mod->LeftAlt || mod->RightAlt; + + mod->LeftCtrl = xf_keyboard_key_pressed(xfc, XK_Control_L); + mod->RightCtrl = xf_keyboard_key_pressed(xfc, XK_Control_R); + mod->Ctrl = mod->LeftCtrl || mod->RightCtrl; + + mod->LeftSuper = xf_keyboard_key_pressed(xfc, XK_Super_L); + mod->RightSuper = xf_keyboard_key_pressed(xfc, XK_Super_R); + mod->Super = mod->LeftSuper || mod->RightSuper; + + return 0; +} + +BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym) +{ + XF_MODIFIER_KEYS mod = { 0 }; + + xk_keyboard_get_modifier_keys(xfc, &mod); + + if (!xf_keyboard_execute_action_script(xfc, &mod, keysym)) + { + return TRUE; + } + if (keysym == XK_Return) { - if ((xf_kbd_key_pressed(xfc, XK_Alt_L) || xf_kbd_key_pressed(xfc, XK_Alt_R)) - && (xf_kbd_key_pressed(xfc, XK_Control_L) || xf_kbd_key_pressed(xfc, XK_Control_R))) + if (mod.Ctrl && mod.Alt) { /* Ctrl-Alt-Enter: toggle full screen */ xf_toggle_fullscreen(xfc); return TRUE; } } - + if (keysym == XK_period) { - if ((xf_kbd_key_pressed(xfc, XK_Alt_L) - || xf_kbd_key_pressed(xfc, XK_Alt_R)) - && (xf_kbd_key_pressed(xfc, XK_Control_L) - || xf_kbd_key_pressed(xfc, - XK_Control_R))) + if (mod.Ctrl && mod.Alt) { - //Zoom in (scale larger) + /* Zoom In (scale larger) */ + double s = xfc->settings->ScalingFactor; + s += 0.1; + if (s > 2.0) s = 2.0; @@ -258,15 +450,14 @@ BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym) if (keysym == XK_comma) { - if ((xf_kbd_key_pressed(xfc, XK_Alt_L) - || xf_kbd_key_pressed(xfc, XK_Alt_R)) - && (xf_kbd_key_pressed(xfc, XK_Control_L) - || xf_kbd_key_pressed(xfc, - XK_Control_R))) + if (mod.Ctrl && mod.Alt) { - //Zoom out (scale smaller) + /* Zoom Out (scale smaller) */ + double s = xfc->settings->ScalingFactor; + s -= 0.1; + if (s < 0.5) s = 0.5; @@ -293,11 +484,7 @@ BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym) if (keysym == XK_KP_4) { - if ((xf_kbd_key_pressed(xfc, XK_Alt_L) - || xf_kbd_key_pressed(xfc, XK_Alt_R)) - && (xf_kbd_key_pressed(xfc, XK_Control_L) - || xf_kbd_key_pressed(xfc, - XK_Control_R))) + if (mod.Ctrl && mod.Alt) { { @@ -315,11 +502,7 @@ BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym) if (keysym == XK_KP_6) { - if ((xf_kbd_key_pressed(xfc, XK_Alt_L) - || xf_kbd_key_pressed(xfc, XK_Alt_R)) - && (xf_kbd_key_pressed(xfc, XK_Control_L) - || xf_kbd_key_pressed(xfc, - XK_Control_R))) + if (mod.Ctrl && mod.Alt) { { @@ -336,11 +519,7 @@ BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym) if (keysym == XK_KP_8) { - if ((xf_kbd_key_pressed(xfc, XK_Alt_L) - || xf_kbd_key_pressed(xfc, XK_Alt_R)) - && (xf_kbd_key_pressed(xfc, XK_Control_L) - || xf_kbd_key_pressed(xfc, - XK_Control_R))) + if (mod.Ctrl && mod.Alt) { { PanningChangeEventArgs e; @@ -356,11 +535,7 @@ BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym) if (keysym == XK_KP_2) { - if ((xf_kbd_key_pressed(xfc, XK_Alt_L) - || xf_kbd_key_pressed(xfc, XK_Alt_R)) - && (xf_kbd_key_pressed(xfc, XK_Control_L) - || xf_kbd_key_pressed(xfc, - XK_Control_R))) + if (mod.Ctrl && mod.Alt) { { PanningChangeEventArgs e; @@ -374,7 +549,6 @@ BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym) } } - return FALSE; } diff --git a/client/X11/xf_keyboard.h b/client/X11/xf_keyboard.h index 0b84efa43..05f9f2c39 100644 --- a/client/X11/xf_keyboard.h +++ b/client/X11/xf_keyboard.h @@ -25,17 +25,37 @@ #include "xf_client.h" #include "xfreerdp.h" -void xf_kbd_init(xfContext* xfc); -void xf_kbd_clear(xfContext* xfc); -void xf_kbd_set_keypress(xfContext* xfc, BYTE keycode, KeySym keysym); -void xf_kbd_unset_keypress(xfContext* xfc, BYTE keycode); -void xf_kbd_release_all_keypress(xfContext* xfc); -BOOL xf_kbd_key_pressed(xfContext* xfc, KeySym keysym); -void xf_kbd_send_key(xfContext* xfc, BOOL down, BYTE keycode); -int xf_kbd_read_keyboard_state(xfContext* xfc); -BOOL xf_kbd_get_key_state(xfContext* xfc, int state, int keysym); -int xf_kbd_get_toggle_keys_state(xfContext* xfc); -void xf_kbd_focus_in(xfContext* xfc); -BOOL xf_kbd_handle_special_keys(xfContext* xfc, KeySym keysym); +#define XF_ACTION_SCRIPT "~/.config/freerdp/action.sh" + +struct _XF_MODIFIER_KEYS +{ + BOOL Shift; + BOOL LeftShift; + BOOL RightShift; + BOOL Alt; + BOOL LeftAlt; + BOOL RightAlt; + BOOL Ctrl; + BOOL LeftCtrl; + BOOL RightCtrl; + BOOL Super; + BOOL LeftSuper; + BOOL RightSuper; +}; +typedef struct _XF_MODIFIER_KEYS XF_MODIFIER_KEYS; + +void xf_keyboard_init(xfContext* xfc); +void xf_keyboard_free(xfContext* xfc); +void xf_keyboard_clear(xfContext* xfc); +void xf_keyboard_key_press(xfContext* xfc, BYTE keycode, KeySym keysym); +void xf_keyboard_key_release(xfContext* xfc, BYTE keycode); +void xf_keyboard_release_all_keypress(xfContext* xfc); +BOOL xf_keyboard_key_pressed(xfContext* xfc, KeySym keysym); +void xf_keyboard_send_key(xfContext* xfc, BOOL down, BYTE keycode); +int xf_keyboard_read_keyboard_state(xfContext* xfc); +BOOL xf_keyboard_get_key_state(xfContext* xfc, int state, int keysym); +UINT32 xf_keyboard_get_toggle_keys_state(xfContext* xfc); +void xf_keyboard_focus_in(xfContext* xfc); +BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym); #endif /* __XF_KEYBOARD_H */ diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index 9cb78b946..aa01ae905 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -125,9 +125,13 @@ struct xf_context BOOL mouse_active; BOOL suppress_output; BOOL fullscreen_toggle; - UINT32 keyboard_layout_id; - BOOL pressed_keys[256]; - XModifierKeymap* modifier_map; + UINT32 KeyboardLayout; + BOOL KeyboardState[256]; + XModifierKeymap* modifierMap; + wArrayList* keyCombinations; + wArrayList* xevents; + char* actionScript; + XSetWindowAttributes attribs; BOOL complex_regions; VIRTUAL_SCREEN vscreen;