diff -rupN mythtv-0.21.0+fixes18207/programs/mythfrontend/mythfrontend.pro mythtv-sendxkey/programs/mythfrontend/mythfrontend.pro
--- mythtv-0.21.0+fixes18207/programs/mythfrontend/mythfrontend.pro	2008-02-04 03:00:43.000000000 -0600
+++ mythtv-sendxkey/programs/mythfrontend/mythfrontend.pro	2008-09-03 14:13:25.000000000 -0500
@@ -31,7 +31,7 @@ HEADERS += mythappearance.h
 
 SOURCES += main.cpp manualbox.cpp playbackbox.cpp viewscheduled.cpp
 SOURCES += globalsettings.cpp manualschedule.cpp programrecpriority.cpp 
-SOURCES += channelrecpriority.cpp statusbox.cpp networkcontrol.cpp
+SOURCES += channelrecpriority.cpp statusbox.cpp sendxkey.cpp networkcontrol.cpp
 SOURCES += mediarenderer.cpp
 SOURCES += custompriority.cpp
 SOURCES += mythappearance.cpp
diff -rupN mythtv-0.21.0+fixes18207/programs/mythfrontend/networkcontrol.cpp mythtv-sendxkey/programs/mythfrontend/networkcontrol.cpp
--- mythtv-0.21.0+fixes18207/programs/mythfrontend/networkcontrol.cpp	2008-02-24 09:19:20.000000000 -0600
+++ mythtv-sendxkey/programs/mythfrontend/networkcontrol.cpp	2008-09-03 15:46:13.000000000 -0500
@@ -16,6 +16,7 @@ using namespace std;
 #include "remoteutil.h"
 #include "previewgenerator.h"
 #include "compat.h"
+#include "sendxkey.h"
 
 #define LOC QString("NetworkControl: ")
 #define LOC_ERR QString("NetworkControl Error: ")
@@ -184,7 +185,288 @@ NetworkControl::NetworkControl(int port)
     keyMap["f23"]                    = Qt::Key_F23;
     keyMap["f24"]                    = Qt::Key_F24;
 
-    stopCommandThread = false;
+    xkeyMap["BackSpace"] = "BackSpace";
+    xkeyMap["Tab"] = "Tab";
+    xkeyMap["Linefeed"] = "Linefeed";
+    xkeyMap["Clear"] = "Clear";
+    xkeyMap["Return"] = "Return";
+    xkeyMap["Pause"] = "Pause";
+    xkeyMap["Scroll_Lock"] = "Scroll_Lock";
+    xkeyMap["Sys_Req"] = "Sys_Req";
+    xkeyMap["Escape"] = "Escape";
+    xkeyMap["Delete"] = "Delete";
+    xkeyMap["Home"] = "Home";
+    xkeyMap["Left"] = "Left";
+    xkeyMap["Up"] = "Up";
+    xkeyMap["Right"] = "Right";
+    xkeyMap["Down"] = "Down";
+    xkeyMap["Prior"] = "Prior";
+    xkeyMap["Page_Up"] = "Page_Up";
+    xkeyMap["Next"] = "Next";
+    xkeyMap["Page_Down"] = "Page_Down";
+    xkeyMap["End"] = "End";
+    xkeyMap["Begin"] = "Begin";
+    xkeyMap["Select"] = "Select";
+    xkeyMap["Print"] = "Print";
+    xkeyMap["Execute"] = "Execute";
+    xkeyMap["Insert"] = "Insert";
+    xkeyMap["Undo"] = "Undo";
+    xkeyMap["Redo"] = "Redo";
+    xkeyMap["Menu"] = "Menu";
+    xkeyMap["Find"] = "Find";
+    xkeyMap["Cancel"] = "Cancel";
+    xkeyMap["Help"] = "Help";
+    xkeyMap["Break"] = "Break";
+    xkeyMap["Mode_switch"] = "Mode_switch";
+    xkeyMap["script_switch"] = "script_switch";
+    xkeyMap["Num_Lock"] = "Num_Lock";
+    xkeyMap["KP_Space"] = "KP_Space";
+    xkeyMap["KP_Tab"] = "KP_Tab";
+    xkeyMap["KP_Enter"] = "KP_Enter";
+    xkeyMap["KP_F1"] = "KP_F1";
+    xkeyMap["KP_F2"] = "KP_F2";
+    xkeyMap["KP_F3"] = "KP_F3";
+    xkeyMap["KP_F4"] = "KP_F4";
+    xkeyMap["KP_Home"] = "KP_Home";
+    xkeyMap["KP_Left"] = "KP_Left";
+    xkeyMap["KP_Up"] = "KP_Up";
+    xkeyMap["KP_Right"] = "KP_Right";
+    xkeyMap["KP_Down"] = "KP_Down";
+    xkeyMap["KP_Prior"] = "KP_Prior";
+    xkeyMap["KP_Page_Up"] = "KP_Page_Up";
+    xkeyMap["KP_Next"] = "KP_Next";
+    xkeyMap["KP_Page_Down"] = "KP_Page_Down";
+    xkeyMap["KP_End"] = "KP_End";
+    xkeyMap["KP_Begin"] = "KP_Begin";
+    xkeyMap["KP_Insert"] = "KP_Insert";
+    xkeyMap["KP_Delete"] = "KP_Delete";
+    xkeyMap["KP_Equal"] = "KP_Equal";
+    xkeyMap["KP_Multiply"] = "KP_Multiply";
+    xkeyMap["KP_Add"] = "KP_Add";
+    xkeyMap["KP_Separator"] = "KP_Separator";
+    xkeyMap["KP_Subtract"] = "KP_Subtract";
+    xkeyMap["KP_Decimal"] = "KP_Decimal";
+    xkeyMap["KP_Divide"] = "KP_Divide";
+    xkeyMap["KP_0"] = "KP_0";
+    xkeyMap["KP_1"] = "KP_1";
+    xkeyMap["KP_2"] = "KP_2";
+    xkeyMap["KP_3"] = "KP_3";
+    xkeyMap["KP_4"] = "KP_4";
+    xkeyMap["KP_5"] = "KP_5";
+    xkeyMap["KP_6"] = "KP_6";
+    xkeyMap["KP_7"] = "KP_7";
+    xkeyMap["KP_8"] = "KP_8";
+    xkeyMap["KP_9"] = "KP_9";
+    xkeyMap["F1"] = "F1";
+    xkeyMap["F2"] = "F2";
+    xkeyMap["F3"] = "F3";
+    xkeyMap["F4"] = "F4";
+    xkeyMap["F5"] = "F5";
+    xkeyMap["F6"] = "F6";
+    xkeyMap["F7"] = "F7";
+    xkeyMap["F8"] = "F8";
+    xkeyMap["F9"] = "F9";
+    xkeyMap["F10"] = "F10";
+    xkeyMap["F11"] = "F11";
+    xkeyMap["L1"] = "L1";
+    xkeyMap["F12"] = "F12";
+    xkeyMap["L2"] = "L2";
+    xkeyMap["F13"] = "F13";
+    xkeyMap["L3"] = "L3";
+    xkeyMap["F14"] = "F14";
+    xkeyMap["L4"] = "L4";
+    xkeyMap["F15"] = "F15";
+    xkeyMap["L5"] = "L5";
+    xkeyMap["F16"] = "F16";
+    xkeyMap["L6"] = "L6";
+    xkeyMap["F17"] = "F17";
+    xkeyMap["L7"] = "L7";
+    xkeyMap["F18"] = "F18";
+    xkeyMap["L8"] = "L8";
+    xkeyMap["F19"] = "F19";
+    xkeyMap["L9"] = "L9";
+    xkeyMap["F20"] = "F20";
+    xkeyMap["L10"] = "L10";
+    xkeyMap["F21"] = "F21";
+    xkeyMap["R1"] = "R1";
+    xkeyMap["F22"] = "F22";
+    xkeyMap["R2"] = "R2";
+    xkeyMap["F23"] = "F23";
+    xkeyMap["R3"] = "R3";
+    xkeyMap["F24"] = "F24";
+    xkeyMap["R4"] = "R4";
+    xkeyMap["F25"] = "F25";
+    xkeyMap["R5"] = "R5";
+    xkeyMap["F26"] = "F26";
+    xkeyMap["R6"] = "R6";
+    xkeyMap["F27"] = "F27";
+    xkeyMap["R7"] = "R7";
+    xkeyMap["F28"] = "F28";
+    xkeyMap["R8"] = "R8";
+    xkeyMap["F29"] = "F29";
+    xkeyMap["R9"] = "R9";
+    xkeyMap["F30"] = "F30";
+    xkeyMap["R10"] = "R10";
+    xkeyMap["F31"] = "F31";
+    xkeyMap["R11"] = "R11";
+    xkeyMap["F32"] = "F32";
+    xkeyMap["R12"] = "R12";
+    xkeyMap["F33"] = "F33";
+    xkeyMap["R13"] = "R13";
+    xkeyMap["F34"] = "F34";
+    xkeyMap["R14"] = "R14";
+    xkeyMap["F35"] = "F35";
+    xkeyMap["R15"] = "R15";
+    xkeyMap["Shift_L"] = "Shift_L";
+    xkeyMap["Shift_R"] = "Shift_R";
+    xkeyMap["Control_L"] = "Control_L";
+    xkeyMap["Control_R"] = "Control_R";
+    xkeyMap["Caps_Lock"] = "Caps_Lock";
+    xkeyMap["Shift_Lock"] = "Shift_Lock";
+    xkeyMap["Meta_L"] = "Meta_L";
+    xkeyMap["Meta_R"] = "Meta_R";
+    xkeyMap["Alt_L"] = "Alt_L";
+    xkeyMap["Alt_R"] = "Alt_R";
+    xkeyMap["Super_L"] = "Super_L";
+    xkeyMap["Super_R"] = "Super_R";
+    xkeyMap["Hyper_L"] = "Hyper_L";
+    xkeyMap["Hyper_R"] = "Hyper_R";
+    xkeyMap["space"] = "space";
+    xkeyMap["exclam"] = "exclam";
+    xkeyMap["quotedbl"] = "quotedbl";
+    xkeyMap["numbersign"] = "numbersign";
+    xkeyMap["dollar"] = "dollar";
+    xkeyMap["percent"] = "percent";
+    xkeyMap["ampersand"] = "ampersand";
+    xkeyMap["apostrophe"] = "apostrophe";
+    xkeyMap["quoteright"] = "quoteright";
+    xkeyMap["parenleft"] = "parenleft";
+    xkeyMap["parenright"] = "parenright";
+    xkeyMap["asterisk"] = "asterisk";
+    xkeyMap["plus"] = "plus";
+    xkeyMap["comma"] = "comma";
+    xkeyMap["minus"] = "minus";
+    xkeyMap["period"] = "period";
+    xkeyMap["slash"] = "slash";
+    xkeyMap["colon"] = "colon";
+    xkeyMap["semicolon"] = "semicolon";
+    xkeyMap["less"] = "less";
+    xkeyMap["equal"] = "equal";
+    xkeyMap["greater"] = "greater";
+    xkeyMap["question"] = "question";
+    xkeyMap["at"] = "at";
+    xkeyMap["bracketleft"] = "bracketleft";
+    xkeyMap["backslash"] = "backslash";
+    xkeyMap["bracketright"] = "bracketright";
+    xkeyMap["asciicircum"] = "asciicircum";
+    xkeyMap["underscore"] = "underscore";
+    xkeyMap["grave"] = "grave";
+    xkeyMap["quoteleft"] = "quoteleft";
+    xkeyMap["braceleft"] = "braceleft";
+    xkeyMap["bar"] = "bar";
+    xkeyMap["braceright"] = "braceright";
+    xkeyMap["asciitilde"] = "asciitilde";
+    xkeyMap["nobreakspace"] = "nobreakspace";
+    xkeyMap["exclamdown"] = "exclamdown";
+    xkeyMap["cent"] = "cent";
+    xkeyMap["sterling"] = "sterling";
+    xkeyMap["currency"] = "currency";
+    xkeyMap["yen"] = "yen";
+    xkeyMap["brokenbar"] = "brokenbar";
+    xkeyMap["section"] = "section";
+    xkeyMap["diaeresis"] = "diaeresis";
+    xkeyMap["copyright"] = "copyright";
+    xkeyMap["ordfeminine"] = "ordfeminine";
+    xkeyMap["guillemotleft"] = "guillemotleft";
+    xkeyMap["notsign"] = "notsign";
+    xkeyMap["hyphen"] = "hyphen";
+    xkeyMap["registered"] = "registered";
+    xkeyMap["macron"] = "macron";
+    xkeyMap["degree"] = "degree";
+    xkeyMap["plusminus"] = "plusminus";
+    xkeyMap["twosuperior"] = "twosuperior";
+    xkeyMap["threesuperior"] = "threesuperior";
+    xkeyMap["acute"] = "acute";
+    xkeyMap["mu"] = "mu";
+    xkeyMap["paragraph"] = "paragraph";
+    xkeyMap["periodcentered"] = "periodcentered";
+    xkeyMap["cedilla"] = "cedilla";
+    xkeyMap["onesuperior"] = "onesuperior";
+    xkeyMap["masculine"] = "masculine";
+    xkeyMap["guillemotright"] = "guillemotright";
+    xkeyMap["onequarter"] = "onequarter";
+    xkeyMap["onehalf"] = "onehalf";
+    xkeyMap["threequarters"] = "threequarters";
+    xkeyMap["questiondown"] = "questiondown";
+    xkeyMap["Agrave"] = "Agrave";
+    xkeyMap["Aacute"] = "Aacute";
+    xkeyMap["Acircumflex"] = "Acircumflex";
+    xkeyMap["Atilde"] = "Atilde";
+    xkeyMap["Adiaeresis"] = "Adiaeresis";
+    xkeyMap["Aring"] = "Aring";
+    xkeyMap["AE"] = "AE";
+    xkeyMap["Ccedilla"] = "Ccedilla";
+    xkeyMap["Egrave"] = "Egrave";
+    xkeyMap["Eacute"] = "Eacute";
+    xkeyMap["Ecircumflex"] = "Ecircumflex";
+    xkeyMap["Ediaeresis"] = "Ediaeresis";
+    xkeyMap["Igrave"] = "Igrave";
+    xkeyMap["Iacute"] = "Iacute";
+    xkeyMap["Icircumflex"] = "Icircumflex";
+    xkeyMap["Idiaeresis"] = "Idiaeresis";
+    xkeyMap["ETH"] = "ETH";
+    xkeyMap["Eth"] = "Eth";
+    xkeyMap["Ntilde"] = "Ntilde";
+    xkeyMap["Ograve"] = "Ograve";
+    xkeyMap["Oacute"] = "Oacute";
+    xkeyMap["Ocircumflex"] = "Ocircumflex";
+    xkeyMap["Otilde"] = "Otilde";
+    xkeyMap["Odiaeresis"] = "Odiaeresis";
+    xkeyMap["multiply"] = "multiply";
+    xkeyMap["Ooblique"] = "Ooblique";
+    xkeyMap["Ugrave"] = "Ugrave";
+    xkeyMap["Uacute"] = "Uacute";
+    xkeyMap["Ucircumflex"] = "Ucircumflex";
+    xkeyMap["Udiaeresis"] = "Udiaeresis";
+    xkeyMap["Yacute"] = "Yacute";
+    xkeyMap["THORN"] = "THORN";
+    xkeyMap["Thorn"] = "Thorn";
+    xkeyMap["ssharp"] = "ssharp";
+    xkeyMap["agrave"] = "agrave";
+    xkeyMap["aacute"] = "aacute";
+    xkeyMap["acircumflex"] = "acircumflex";
+    xkeyMap["atilde"] = "atilde";
+    xkeyMap["adiaeresis"] = "adiaeresis";
+    xkeyMap["aring"] = "aring";
+    xkeyMap["ae"] = "ae";
+    xkeyMap["ccedilla"] = "ccedilla";
+    xkeyMap["egrave"] = "egrave";
+    xkeyMap["eacute"] = "eacute";
+    xkeyMap["ecircumflex"] = "ecircumflex";
+    xkeyMap["ediaeresis"] = "ediaeresis";
+    xkeyMap["igrave"] = "igrave";
+    xkeyMap["iacute"] = "iacute";
+    xkeyMap["icircumflex"] = "icircumflex";
+    xkeyMap["idiaeresis"] = "idiaeresis";
+    xkeyMap["eth"] = "eth";
+    xkeyMap["ntilde"] = "ntilde";
+    xkeyMap["ograve"] = "ograve";
+    xkeyMap["oacute"] = "oacute";
+    xkeyMap["ocircumflex"] = "ocircumflex";
+    xkeyMap["otilde"] = "otilde";
+    xkeyMap["odiaeresis"] = "odiaeresis";
+    xkeyMap["division"] = "division";
+    xkeyMap["oslash"] = "oslash";
+    xkeyMap["ugrave"] = "ugrave";
+    xkeyMap["uacute"] = "uacute";
+    xkeyMap["ucircumflex"] = "ucircumflex";
+    xkeyMap["udiaeresis"] = "udiaeresis";
+    xkeyMap["yacute"] = "yacute";
+    xkeyMap["thorn"] = "thorn";
+    xkeyMap["ydiaeresis"] = "ydiaeresis";
+
+
+   stopCommandThread = false;
     pthread_create(&command_thread, NULL, CommandThread, this);
 
     gContext->addListener(this);
@@ -247,6 +529,8 @@ void NetworkControl::processNetworkContr
         result = processJump(tokens);
     else if (is_abbrev("key", tokens[0]))
         result = processKey(tokens);
+    else if (is_abbrev("xkey", tokens[0]))
+        result = processKey(tokens, true);
     else if (is_abbrev("play", tokens[0]))
         result = processPlay(tokens);
     else if (is_abbrev("query", tokens[0]))
@@ -390,7 +674,7 @@ QString NetworkControl::processJump(QStr
     return result;
 }
 
-QString NetworkControl::processKey(QStringList tokens)
+QString NetworkControl::processKey(QStringList tokens, bool is_xkey)
 {
     QString result = "OK";
     QKeyEvent *event = NULL;
@@ -414,75 +698,94 @@ QString NetworkControl::processKey(QStri
 
     unsigned int curToken = 1;
     unsigned int tokenLen = 0;
+    int keyCode;
+    int ch;
+    int buttons;
+    QString recombined = "";
     while (curToken < tokens.size())
     {
-        tokenLen = tokens[curToken].length();
-
-        if (tokens[curToken] == "sleep")
-        {
-            sleep(1);
-        }
-        else if (keyMap.contains(tokens[curToken]))
-        {
-            int keyCode = keyMap[tokens[curToken]];
+        if(is_xkey)
+    {
+            recombined += curToken;
+    }
+    else
+    {
+            tokenLen = tokens[curToken].length();
 
-            event = new QKeyEvent(QEvent::KeyPress, keyCode, 0, NoButton);
-            QApplication::postEvent(keyDest, event);
+            if (tokens[curToken] == "sleep")
+            {
+                sleep(1);
+            }
+            else if (keyMap.contains(tokens[curToken]))
+            {
+                int keyCode = keyMap[tokens[curToken]];
 
-            event = new QKeyEvent(QEvent::KeyRelease, keyCode, 0, NoButton);
-            QApplication::postEvent(keyDest, event);
-        }
-        else if (((tokenLen == 1) &&
+                event = new QKeyEvent(QEvent::KeyPress, keyCode, 0, NoButton);
+                QApplication::postEvent(keyDest, event);
+  
+                event = new QKeyEvent(QEvent::KeyRelease, keyCode, 0, NoButton);
+                QApplication::postEvent(keyDest, event);
+           }
+           else if (((tokenLen == 1) &&
                   (tokens[curToken][0].isLetterOrNumber())) ||
                  ((tokenLen >= 1) &&
                   (tokens[curToken].contains("+"))))
-        {
-            QKeySequence a(tokens[curToken]);
-            int keyCode = a[0];
-            int ch = (tokens[curToken].ascii())[tokenLen - 1];
-            int buttons = NoButton;
-
-            if (tokenLen > 1)
             {
-                QStringList tokenParts =
-                    QStringList::split("+", tokens[curToken]);
-
-                unsigned int partNum = 0;
-                while (partNum < (tokenParts.size() - 1))
+                QKeySequence a(tokens[curToken]);
+                keyCode = a[0];
+                ch = (tokens[curToken].ascii())[tokenLen - 1];
+                buttons = NoButton;
+    
+                if (tokenLen > 1)
                 {
-                    if (tokenParts[partNum].upper() == "CTRL")
-                        buttons |= ControlButton;
-                    if (tokenParts[partNum].upper() == "SHIFT")
-                        buttons |= ShiftButton;
-                    if (tokenParts[partNum].upper() == "ALT")
-                        buttons |= AltButton;
-                    if (tokenParts[partNum].upper() == "META")
-                        buttons |= MetaButton;
-
-                    partNum++;
+                    QStringList tokenParts =
+                        QStringList::split("+", tokens[curToken]);
+ 
+                    unsigned int partNum = 0;
+                    while (partNum < (tokenParts.size() - 1))
+                    {
+                        if (tokenParts[partNum].upper() == "CTRL")
+                            buttons |= ControlButton;
+                        if (tokenParts[partNum].upper() == "SHIFT")
+                            buttons |= ShiftButton;
+                        if (tokenParts[partNum].upper() == "ALT")
+                            buttons |= AltButton;
+                        if (tokenParts[partNum].upper() == "META")
+                            buttons |= MetaButton;
+  
+                        partNum++;
+                    }
                 }
+                else
+                {
+                    if (tokens[curToken] == tokens[curToken].upper())
+                        buttons = ShiftButton;
+                }
+
+                event = new QKeyEvent(QEvent::KeyPress, keyCode, ch, buttons,
+                                      tokens[curToken]);
+                QApplication::postEvent(keyDest, event);
+
+                event = new QKeyEvent(QEvent::KeyRelease, keyCode, ch, buttons,
+                                      tokens[curToken]);
+                QApplication::postEvent(keyDest, event);
             }
             else
-            {
-                if (tokens[curToken] == tokens[curToken].upper())
-                    buttons = ShiftButton;
-            }
-
-            event = new QKeyEvent(QEvent::KeyPress, keyCode, ch, buttons,
-                                  tokens[curToken]);
-            QApplication::postEvent(keyDest, event);
-
-            event = new QKeyEvent(QEvent::KeyRelease, keyCode, ch, buttons,
-                                  tokens[curToken]);
-            QApplication::postEvent(keyDest, event);
+                return QString("ERROR: Invalid syntax at '%1', see 'help %2' for "
+                               "usage information")
+                               .arg(tokens[curToken]).arg(tokens[0]);
         }
-        else
-            return QString("ERROR: Invalid syntax at '%1', see 'help %2' for "
-                           "usage information")
-                           .arg(tokens[curToken]).arg(tokens[0]);
-
         curToken++;
     }
+    if(is_xkey)
+    {
+        if (keyMap.contains(tokens[1]) || (tokens[0][0].isLetterOrNumber()))
+            sendxkey(tokens[1].ascii());
+    else
+            return QString("ERROR: Invalid syntax at '%1', see 'help %2' for "
+                               "usage information")
+                               .arg(tokens[curToken]).arg(tokens[0]);
+    }
 
     return result;
 }
@@ -692,6 +995,13 @@ QString NetworkControl::processQuery(QSt
         return listRecordings(tokens[2], tokens[3].upper());
     else if (is_abbrev("recordings", tokens[1]))
         return listRecordings();
+    else if (is_abbrev("focused", tokens[1]))
+    {
+        char *title;
+        get_focused_window(&title);
+        result = QString(title);
+    delete [] title;
+    }
     else
         return QString("ERROR: See 'help %1' for usage information")
                        .arg(tokens[0]);
@@ -733,6 +1043,27 @@ QString NetworkControl::processHelp(QStr
                         it.data() + "\r\n";
         }
     }
+    else if (is_abbrev("xkey", command))
+    {
+        helpText +=
+            "xkey LETTER           - Send the letter key specified\r\n"
+            "xkey NUMBER           - Send the number key specified\r\n"
+            "xkey CODE             - Send one of the following key codes\r\n"
+            "\r\n";
+
+        QMap<QString, QString>::Iterator it;
+        bool first = true;
+        for (it = xkeyMap.begin(); it != xkeyMap.end(); ++it)
+        {
+            if (first)
+                first = false;
+            else
+                helpText += ", ";
+
+            helpText += it.key();
+        }
+        helpText += "\r\n";
+    }
     else if (is_abbrev("key", command))
     {
         helpText +=
@@ -794,7 +1125,8 @@ QString NetworkControl::processHelp(QStr
             "                      - List info about the specified program\r\n"
             "query liveTV          - List current TV schedule\r\n"
             "query liveTV CHANID   - Query current program for specified channel\r\n"
-            "query time            - Query current time on server\r\n";
+            "query time            - Query current time on server\r\n"
+            "query focused         - Returns the name of the focused window\r\n";
     }
     else if (command == "exit")
     {
@@ -813,6 +1145,7 @@ QString NetworkControl::processHelp(QStr
         "---------------\r\n"
         "jump               - Jump to a specified location in Myth\r\n"
         "key                - Send a keypress to the program\r\n"
+        "xkey               - Send a keypress to the focused program\r\n"
         "play               - Playback related commands\r\n"
         "query              - Queries\r\n"
         "exit               - Exit Network Control\r\n"
diff -rupN mythtv-0.21.0+fixes18207/programs/mythfrontend/networkcontrol.h mythtv-sendxkey/programs/mythfrontend/networkcontrol.h
--- mythtv-0.21.0+fixes18207/programs/mythfrontend/networkcontrol.h	2008-01-09 00:42:26.000000000 -0600
+++ mythtv-sendxkey/programs/mythfrontend/networkcontrol.h	2008-09-03 15:39:24.000000000 -0500
@@ -36,7 +36,7 @@ class NetworkControl : public QServerSoc
 
   private:
     QString processJump(QStringList tokens);
-    QString processKey(QStringList tokens);
+    QString processKey(QStringList tokens, bool is_xkey = false);
     QString processLiveTV(QStringList tokens);
     QString processPlay(QStringList tokens);
     QString processQuery(QStringList tokens);
@@ -57,6 +57,7 @@ class NetworkControl : public QServerSoc
     QString answer;
     QMap <QString, QString> jumpMap;
     QMap <QString, int> keyMap;
+    QMap <QString, QString> xkeyMap;
 
     QMutex clientLock;
     QSocket *client;
diff -rupN mythtv-0.21.0+fixes18207/programs/mythfrontend/sendxkey.cpp mythtv-sendxkey/programs/mythfrontend/sendxkey.cpp
--- mythtv-0.21.0+fixes18207/programs/mythfrontend/sendxkey.cpp	1969-12-31 18:00:00.000000000 -0600
+++ mythtv-sendxkey/programs/mythfrontend/sendxkey.cpp	2008-09-03 14:54:14.000000000 -0500
@@ -0,0 +1,168 @@
+/*      $Id: sendxkey.cpp,v 5.6 2001/11/20 15:12:33 ranty Exp $      */
+
+/****************************************************************************
+ ** irxevent.c **************************************************************
+ ****************************************************************************
+ *
+ * sendxkey  - mythfrontend telnet xevent sender
+ *
+ * Based off of sendxirevent by Heinrich Langos  <heinrich@null.net> with
+ * small modifications by Christoph Bartelmus <lirc@bartelmus.de>
+ *
+ * irxevent is based on irexec (Copyright (C) 1998 Trent Piepho)
+ * and irx.c (no copyright notice found)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+struct keymodlist_t {
+        char *name;
+        Mask mask;
+};
+static struct keymodlist_t keymodlist[]=
+{
+  {"SHIFT",   ShiftMask},
+  {"CAPS",    LockMask},
+  {"CTRL",    ControlMask},
+  {"ALT",     Mod1Mask},{"META",    Mod1Mask},
+  {"NUMLOCK", Mod2Mask},
+  {"MOD3",    Mod3Mask},  /* I don't have a clue what key maps to this. */
+  {"MOD4",    Mod4Mask},  /* I don't have a clue what key maps to this. */
+  {"SCRLOCK", Mod5Mask},
+  {NULL,0},
+};
+
+const char *key_delimiter ="-";
+const char *active_window_name ="CurrentWindow";
+
+
+char *progname;
+Display *dpy;
+Window root;
+XEvent xev;
+Window w,subw;
+int initialized = 0;
+
+Time fake_timestamp()
+     /*seems that xfree86 computes the timestamps like this     */
+     /*strange but it relies on the *1000-32bit-wrap-around     */
+     /*if anybody knows exactly how to do it, please contact me */
+{
+  int  tint;
+  struct timeval  tv;
+  struct timezone tz; /* is not used since ages */
+  gettimeofday(&tv,&tz);
+  tint=(int)tv.tv_sec*1000;
+  tint=tint/1000*1000;
+  tint=tint+tv.tv_usec/1000;
+  return (Time)tint;
+}
+
+Window find_window()
+{
+  Window *children,foo;
+  int revert_to_return;
+    XGetInputFocus(dpy, &foo, &revert_to_return);
+    return(foo);
+}
+
+void make_key(const char *keyname,int x, int y,XKeyEvent *xev)
+{
+  char *part, *part2;
+  struct keymodlist_t *kmlptr;
+  char temp[strlen(keyname)];
+  char *ptr = temp;
+  strcpy(temp, keyname);
+  part2= new char[128];
+
+  xev->type = KeyPress;
+  xev->display=dpy;
+  xev->root=root;
+  xev->subwindow = None;
+  xev->time=fake_timestamp();
+  xev->x=x; xev->y=y;
+  xev->x_root=1; xev->y_root=1;
+  xev->same_screen = True;
+
+  xev->state=0;
+  while ((part=strsep(&ptr, key_delimiter)))
+    {
+      part2=strncpy(part2,part,128);
+      kmlptr=keymodlist;
+      while (kmlptr->name)
+    {
+      if (!strcasecmp(kmlptr->name, part))
+        xev->state|=kmlptr->mask;
+      kmlptr++;
+    }
+    } 
+  xev->keycode=XKeysymToKeycode(dpy,XStringToKeysym(part2));
+  delete [] part2;
+  return ;
+}
+
+void init_keysender()
+{
+  dpy=XOpenDisplay(NULL);
+  if(dpy==NULL) {
+    fprintf(stderr,"Can't open DISPLAY.\n");
+    exit(1);
+  }
+  root=RootWindow(dpy,DefaultScreen(dpy));
+}
+
+void get_focused_window(char **window_name)
+{
+  if(!initialized)
+  {
+    initialized = 1;
+    init_keysender();
+  }
+  Window w = find_window();
+  XFetchName(dpy, w, window_name);
+  return;
+}
+
+void sendxkey(const char *keyname)
+{
+  int x = 0;
+  int y = 0;
+  if(!initialized)
+  {
+    initialized = 1;
+    init_keysender();
+  }
+  Window w = find_window();
+
+  make_key(keyname ,x,y,(XKeyEvent*)&xev);
+  xev.xkey.window=w;
+  xev.xkey.subwindow=0;
+
+  XSendEvent(dpy,w,True,KeyPressMask,&xev);
+  xev.type = KeyRelease;
+  usleep(2000);
+  xev.xkey.time = fake_timestamp();
+  XSendEvent(dpy,w,True,KeyReleaseMask,&xev);
+  XSync(dpy,True);
+  return;
+}
diff -rupN mythtv-0.21.0+fixes18207/programs/mythfrontend/sendxkey.h mythtv-sendxkey/programs/mythfrontend/sendxkey.h
--- mythtv-0.21.0+fixes18207/programs/mythfrontend/sendxkey.h	1969-12-31 18:00:00.000000000 -0600
+++ mythtv-sendxkey/programs/mythfrontend/sendxkey.h	2008-09-03 14:41:34.000000000 -0500
@@ -0,0 +1,16 @@
+/****************************************************************************
+ ** irxevent.h **************************************************************
+ ****************************************************************************
+ *
+ * sendxkey  - mythfrontend telnet xevent sender
+ *
+ * Based off of sendxirevent by Heinrich Langos  <heinrich@null.net> with
+ * small modifications by Christoph Bartelmus <lirc@bartelmus.de>
+ *
+ * irxevent is based on irexec (Copyright (C) 1998 Trent Piepho)
+ * and irx.c (no copyright notice found)
+ *
+ */
+
+void sendxkey(const char *keyname);
+void get_focused_window(char **window_name);
