diff --git a/mythtv/libs/libmythtv/tv_play.cpp b/mythtv/libs/libmythtv/tv_play.cpp
index d6fcb27..b6d27c9 100644
--- a/mythtv/libs/libmythtv/tv_play.cpp
+++ b/mythtv/libs/libmythtv/tv_play.cpp
@@ -3664,6 +3664,10 @@ bool TV::eventFilter(QObject *o, QEvent *e)
 
     // Intercept keypress events unless they need to be handled by a main UI
     // screen (e.g. GuideGrid, ProgramFinder)
+    QScopedPointer<QEvent> sNewEvent(NULL);
+    if (GetMythMainWindow()->keyLongPressFilter(&e, sNewEvent))
+        return false;
+
     if (QEvent::KeyPress == e->type())
         return ignoreKeyPresses ? false : event(e);
     if (MythGestureEvent::kEventType == e->type())
diff --git a/mythtv/libs/libmythui/mythmainwindow.cpp b/mythtv/libs/libmythui/mythmainwindow.cpp
index 1a60f0b..1a468bf 100644
--- a/mythtv/libs/libmythui/mythmainwindow.cpp
+++ b/mythtv/libs/libmythui/mythmainwindow.cpp
@@ -88,6 +88,7 @@ using namespace std;
 
 #define GESTURE_TIMEOUT 1000
 #define STANDBY_TIMEOUT 90 // Minutes
+#define LONGPRESS_INTERVAL 1000
 
 #define LOC      QString("MythMainWindow: ")
 
@@ -199,7 +200,9 @@ class MythMainWindowPrivate
         disableIdle(false),
         NC(NULL),
         firstinit(true),
-        m_bSavedPOS(false)
+        m_bSavedPOS(false),
+        m_longPressKeyCode(0),
+        m_longPressTime(0)
     {
     }
 
@@ -299,6 +302,9 @@ class MythMainWindowPrivate
         // window aspect
     bool firstinit;
     bool m_bSavedPOS;
+    // Support for long press
+    int m_longPressKeyCode;
+    ulong m_longPressTime;
 };
 
 // Make keynum in QKeyEvent be equivalent to what's in QKeySequence
@@ -1256,7 +1262,7 @@ void MythMainWindow::InitKeys()
     RegisterKey("Global", "ESCAPE", QT_TRANSLATE_NOOP("MythControls",
         "Escape"),                "Esc");
     RegisterKey("Global", "MENU", QT_TRANSLATE_NOOP("MythControls",
-        "Pop-up menu"),             "M");
+        "Pop-up menu"),             "M,Meta+Enter");
     RegisterKey("Global", "INFO", QT_TRANSLATE_NOOP("MythControls",
         "More information"),        "I");
     RegisterKey("Global", "DELETE", QT_TRANSLATE_NOOP("MythControls",
@@ -1386,6 +1392,14 @@ void MythMainWindow::InitKeys()
         "System Exit"),                     "");
     RegisterKey("Main Menu",    "STANDBYMODE",QT_TRANSLATE_NOOP("MythControls",
         "Enter Standby Mode"),              "");
+    RegisterKey("Long Press",    "LONGPRESS1",QT_TRANSLATE_NOOP("MythControls",
+        "Up to 16 Keys that allow Long Press"),      "Enter");
+    RegisterKey("Long Press",    "LONGPRESS2",QT_TRANSLATE_NOOP("MythControls",
+        "Up to 16 Keys that allow Long Press"),      "");
+    RegisterKey("Long Press",    "LONGPRESS3",QT_TRANSLATE_NOOP("MythControls",
+        "Up to 16 Keys that allow Long Press"),      "");
+    RegisterKey("Long Press",    "LONGPRESS4",QT_TRANSLATE_NOOP("MythControls",
+        "Up to 16 Keys that allow Long Press"),      "");
 }
 
 void MythMainWindow::ReloadKeys()
@@ -2162,6 +2176,100 @@ void MythMainWindow::mouseTimeout(void)
         QCoreApplication::postEvent(this, e);
 }
 
+// Return code = true to skip further processing, false to continue
+// sNewEvent: Caller must pass in a QScopedPointer that will be used
+// to delete a new event if one is created.
+bool MythMainWindow::keyLongPressFilter(QEvent **e,
+    QScopedPointer<QEvent> &sNewEvent)
+{
+    QEvent *newEvent = NULL;
+    QKeyEvent *ke = dynamic_cast<QKeyEvent*>(*e);
+    if (!ke)
+        return false;
+    int keycode = ke->key();
+
+    switch ((*e)->type())
+    {
+        case QEvent::KeyPress:
+        {
+            // Check if we are in the middle of a long press
+            if (keycode != 0 && keycode == d->m_longPressKeyCode)
+            {
+                if (ke->timestamp() - d->m_longPressTime < LONGPRESS_INTERVAL
+                    || d->m_longPressTime == 0)
+                {
+                    // waiting for release of key.
+                    return true; // discard the key press
+                }
+                else
+                {
+                    // expired log press - generate long key
+                    newEvent = new QKeyEvent(QEvent::KeyPress, keycode,
+                        ke->modifiers() | Qt::MetaModifier, ke->nativeScanCode(),
+                        ke->nativeVirtualKey(), ke->nativeModifiers(),
+                        ke->text(), false,1);
+                    *e = newEvent;
+                    sNewEvent.reset(newEvent);
+                    d->m_longPressTime = 0;   // indicate we have generated the long press
+                    return false;
+                }
+            }
+            d->m_longPressKeyCode = 0;
+            QStringList actions;
+            bool handled = TranslateKeyPress("Long Press",
+                               ke, actions,false);
+            if (handled)
+            {
+                // This shoudl never happen,, because we passed in false
+                // to say do not process jump points and yet it returned true
+                // to say it processed a jump point.
+                LOG(VB_GUI, LOG_ERR, QString("TranslateKeyPress Long Press Invalid Response"));
+                return true;
+            }
+            if (actions.size()>0 && actions[0].startsWith("LONGPRESS"))
+            {
+                // Beginning of a press
+                d->m_longPressKeyCode = keycode;
+                d->m_longPressTime = ke->timestamp();
+                return true; // discard the key press
+            }
+            break;
+        }
+        case QEvent::KeyRelease:
+        {
+            if (keycode != 0 && keycode == d->m_longPressKeyCode)
+            {
+                if (ke->isAutoRepeat())
+                    return true;
+                if (d->m_longPressTime > 0)
+                {
+                    // short press or non-repeating keyboard - generate key
+                    Qt::KeyboardModifiers modifier = Qt::NoModifier;
+                    if (ke->timestamp() - d->m_longPressTime >= LONGPRESS_INTERVAL)
+                        // non-repeatng keyboard
+                        modifier = Qt::MetaModifier;
+                    newEvent = new QKeyEvent(QEvent::KeyPress, keycode,
+                        ke->modifiers() | modifier, ke->nativeScanCode(),
+                        ke->nativeVirtualKey(), ke->nativeModifiers(),
+                        ke->text(), false,1);
+                    *e = newEvent;
+                    sNewEvent.reset(newEvent);
+                    d->m_longPressKeyCode = 0;
+                    return false;
+                }
+                else
+                {
+                    // end of long press
+                    d->m_longPressKeyCode = 0;
+                    return true;
+                }
+            }
+            break;
+        }
+    }
+    return false;
+}
+
 bool MythMainWindow::eventFilter(QObject *, QEvent *e)
 {
     MythGestureEvent *ge;
@@ -2170,6 +2278,10 @@ bool MythMainWindow::eventFilter(QObject *, QEvent *e)
     if (!d->AllowInput)
         return true;
 
+    QScopedPointer<QEvent> sNewEvent(NULL);
+    if (keyLongPressFilter(&e, sNewEvent))
+        return false;
+
     switch (e->type())
     {
         case QEvent::KeyPress:
diff --git a/mythtv/libs/libmythui/mythmainwindow.h b/mythtv/libs/libmythui/mythmainwindow.h
index 9195982..79424c3 100644
--- a/mythtv/libs/libmythui/mythmainwindow.h
+++ b/mythtv/libs/libmythui/mythmainwindow.h
@@ -54,6 +54,8 @@ class MUI_PUBLIC MythMainWindow : public QWidget
     bool TranslateKeyPress(const QString &context, QKeyEvent *e,
                            QStringList &actions, bool allowJumps = true)
                            MUNUSED_RESULT;
+    bool keyLongPressFilter(QEvent **e,
+        QScopedPointer<QEvent> &sNewEvent);
 
     void ReloadKeys(void);
     void ClearKey(const QString &context, const QString &action);
