Quick fix for rdesktop and desktop switching on linux
If you're a bit like me and forced into using Windows for certain applications you're probably using RDP in some way. I usually put my RDP client (rdesktop) on a specific desktop and switch desktops using CTRL-ALT-LEFT and CTRL-ALT-RIGHT. You've probably noticed that it doesn't work unless you use '-K keep window manager key bindings' option. But if you do that you can't use ALT-TAB in Windows. Being really bothered about that I have a very simple patch for that. I'd like to treat CTRL-ALT-LEFT and RIGHT as special keys in rdesktop just like CTRL-ALT-TAB.
This patch is very poor but it can be enhanced easily. The thing with rdesktop is, is it uses XGrabKeyboard which captures all keyboard events and not let them through to the WM. So if rdesktop finds a special key I just added code to pass the event on to the root window. So in this code every special key is send to the WM. This might be a bit too much. But I'm test driving it right now and already very happy.
Here's the patch for xwin.c:2343: (See below for a full diff patch of xwin.c and xkeymap.c)
case KeyPress:
g_last_gesturetime = xevent.xkey.time;
if (g_IC != NULL)
/* Multi_key compatible version */
{
XmbLookupString(g_IC,
&xevent.xkey, str, sizeof(str), &keysym,
&status);
if (!((status##### XLookupKeySym) || (status
XLookupBoth)))
{
error("XmbLookupString failed with status 0x%x\n",
status);
break;
}
}
else
{
/* Plain old XLookupString */
DEBUG_KBD[^1]
[^1]: "\nNo input context, using XLookupString\n";
XLookupString((XKeyEvent *) & xevent,
str, sizeof(str), &keysym, NULL);
}
DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
get_ksname(keysym)));
set_keypress_keysym(xevent.xkey.keycode, keysym);
ev_time = time(NULL);
if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
//patch to send special keys to WM as well
{
XSendEvent(g_display, DefaultRootWindow(g_display), False,
SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
break;
}
//END patch to send special keys to WM as well
xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
ev_time, True, 0);
break;
case KeyRelease:
g_last_gesturetime = xevent.xkey.time;
XLookupString((XKeyEvent *) & xevent, str,
sizeof(str), &keysym, NULL);
DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
get_ksname(keysym)));
keysym = reset_keypress_keysym(xevent.xkey.keycode, keysym);
ev_time = time(NULL);
if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
//patch to send special keys to WM as well
{
XSendEvent(g_display, DefaultRootWindow(g_display), False,
SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
break;
}
//END patch to send special keys to WM as well
xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
ev_time, False, 0);
break;
diff:
Index: xwin.c
############### ===========================
1.-- xwin.c (revision 1696)
+++ xwin.c (working copy)
@@ -2369,7 +2369,13 @@
set_keypress_keysym(xevent.xkey.keycode, keysym);
ev_time = time(NULL);
if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
2. break;
+ //patch to send special keys to WM as well
+ {
+ XSendEvent(g_display, DefaultRootWindow(g_display), False,
+ SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
+ break;
+ }
+ //END patch to send special keys to WM as well
xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
ev_time, True, 0);
@@ -2386,7 +2392,13 @@
keysym = reset_keypress_keysym(xevent.xkey.keycode, keysym);
ev_time = time(NULL);
if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
3. break;
+ //patch to send special keys to WM as well
+ {
+ XSendEvent(g_display, DefaultRootWindow(g_display), False,
+ SubstructureNotifyMask | SubstructureRedirectMask, &xevent);
+ break;
+ }
+ //END patch to send special keys to WM as well
xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
ev_time, False, 0);
Index: xkeymap.c
############### ===========================
4.-- xkeymap.c (revision 1696)
+++ xkeymap.c (working copy)
@@ -622,11 +622,22 @@
/* Inhibit */
return True;
break;
5. case XK_Overlay1_Enable:
6. /* Toggle SeamlessRDP */
7. if (pressed)
8. ui_seamless_toggle();
+ case XK_Left:
+ if [^1]
[^1]: get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R
+ && (get_key_state(state, XK_Control_L)
+ || get_key_state(state, XK_Control_R)))
+ {
+ return True;
+ }
break;
+ case XK_Right:
+ if [^1]
[^1]: get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R
+ && (get_key_state(state, XK_Control_L)
+ || get_key_state(state, XK_Control_R)))
+ {
+ return True;
+ }
+ break;
}
return False;
Bugs: * arrow keys don't work no more in the rdp session