diff --git a/src/libs/qtcreatorcdbext/extensioncontext.cpp b/src/libs/qtcreatorcdbext/extensioncontext.cpp
index 0b97395afe2cee56f1271014d2e7699dfe5bcf83..58d2d7824647d93c136663a896f0aafb46bdda8f 100644
--- a/src/libs/qtcreatorcdbext/extensioncontext.cpp
+++ b/src/libs/qtcreatorcdbext/extensioncontext.cpp
@@ -48,7 +48,7 @@ const char *ExtensionContext::stopReasonKeyC = "reason";
 ExtensionContext::ExtensionContext() :
     m_hookedClient(0),
     m_oldEventCallback(0), m_oldOutputCallback(0),
-    m_creatorEventCallback(0), m_creatorOutputCallback(0)
+    m_creatorEventCallback(0), m_creatorOutputCallback(0), m_stateNotification(true)
 {
 }
 
@@ -81,6 +81,20 @@ void ExtensionContext::hookCallbacks(CIDebugClient *client)
     }
 }
 
+void ExtensionContext::startRecordingOutput()
+{
+    if (m_creatorOutputCallback) {
+        m_creatorOutputCallback->startRecording();
+    } else {
+        report('X', 0, 0, "Error", "ExtensionContext::startRecordingOutput() called with no output hooked.\n");
+    }
+}
+
+std::wstring ExtensionContext::stopRecordingOutput()
+{
+    return m_creatorOutputCallback ? m_creatorOutputCallback->stopRecording() : std::wstring();
+}
+
 void ExtensionContext::setStopReason(const StopReasonMap &r, const std::string &reason)
 {
     m_stopReason = r;
@@ -163,37 +177,41 @@ static inline ExtensionContext::StopReasonMap
 void ExtensionContext::notifyIdle()
 {
     discardSymbolGroup();
-
-    const StopReasonMap stopReasons = completeStopReasons(m_stopReason, executionStatus());
-    m_stopReason.clear();
-    // Format
-    std::ostringstream str;
-    formatGdbmiHash(str, stopReasons);
-    reportLong('E', 0, "session_idle", str.str());
+    if (m_stateNotification) {
+        const StopReasonMap stopReasons = completeStopReasons(m_stopReason, executionStatus());
+        // Format
+        std::ostringstream str;
+        formatGdbmiHash(str, stopReasons);
+        reportLong('E', 0, "session_idle", str.str());
+    }
     m_stopReason.clear();
 }
 
 void ExtensionContext::notifyState(ULONG Notify)
 {
     const ULONG ex = executionStatus();
-    switch (Notify) {
-    case DEBUG_NOTIFY_SESSION_ACTIVE:
-        report('E', 0, 0, "session_active", "%u", ex);
-        break;
-    case DEBUG_NOTIFY_SESSION_ACCESSIBLE: // Meaning, commands accepted
-        report('E', 0, 0, "session_accessible", "%u", ex);
-        break;
-    case DEBUG_NOTIFY_SESSION_INACCESSIBLE:
-        report('E', 0, 0, "session_inaccessible", "%u", ex);
-        break;
-    case DEBUG_NOTIFY_SESSION_INACTIVE:
-        report('E', 0, 0, "session_inactive", "%u", ex);
+    if (m_stateNotification) {
+        switch (Notify) {
+        case DEBUG_NOTIFY_SESSION_ACTIVE:
+            report('E', 0, 0, "session_active", "%u", ex);
+            break;
+        case DEBUG_NOTIFY_SESSION_ACCESSIBLE: // Meaning, commands accepted
+            report('E', 0, 0, "session_accessible", "%u", ex);
+            break;
+        case DEBUG_NOTIFY_SESSION_INACCESSIBLE:
+            report('E', 0, 0, "session_inaccessible", "%u", ex);
+            break;
+        case DEBUG_NOTIFY_SESSION_INACTIVE:
+            report('E', 0, 0, "session_inactive", "%u", ex);
+            break;
+        }
+    }
+    if (Notify == DEBUG_NOTIFY_SESSION_INACTIVE) {
         discardSymbolGroup();
         discardWatchesSymbolGroup();
         // We lost the debuggee, at this point restore output.
         if (ex & DEBUG_STATUS_NO_DEBUGGEE)
             unhookCallbacks();
-        break;
     }
 }
 
@@ -280,6 +298,48 @@ bool ExtensionContext::reportLong(char code, int token, const char *serviceName,
     return true;
 }
 
+bool ExtensionContext::call(const std::string &functionCall,
+                            std::wstring *output,
+                            std::string *errorMessage)
+{
+    if (!m_creatorOutputCallback) {
+        *errorMessage = "Attempt to issue a call with no output hooked.";
+        return false;
+    }
+    // Set up arguments
+    const std::string call = ".call " + functionCall;
+    HRESULT hr = m_control->Execute(DEBUG_OUTCTL_ALL_CLIENTS, call.c_str(), DEBUG_EXECUTE_ECHO);
+    if (FAILED(hr)) {
+        *errorMessage = msgDebugEngineComFailed("Execute", hr);
+        return 0;
+    }
+    // Execute in current thread. TODO: This must not crash, else we are in an inconsistent state
+    // (need to call 'gh', etc.)
+    hr = m_control->Execute(DEBUG_OUTCTL_ALL_CLIENTS, "~. g", DEBUG_EXECUTE_ECHO);
+    if (FAILED(hr)) {
+        *errorMessage = msgDebugEngineComFailed("Execute", hr);
+        return 0;
+    }
+    // Wait until finished
+    startRecordingOutput();
+    m_stateNotification = false;
+    m_control->WaitForEvent(0, INFINITE);
+    *output =  stopRecordingOutput();
+    m_stateNotification = true;
+    // Crude attempt at recovering from a crash: Issue 'gN' (go with exception not handled).
+    const bool crashed = output->find(L"This exception may be expected and handled.") != std::string::npos;
+    if (crashed) {
+        m_stopReason.clear();
+        m_stateNotification = false;
+        hr = m_control->Execute(DEBUG_OUTCTL_ALL_CLIENTS, "~. gN", DEBUG_EXECUTE_ECHO);
+        m_control->WaitForEvent(0, INFINITE);
+        m_stateNotification = true;
+        *errorMessage = "A crash occurred while calling: " + functionCall;
+        return false;
+    }
+    return true;
+}
+
 // Exported C-functions
 extern "C" {
 
diff --git a/src/libs/qtcreatorcdbext/extensioncontext.h b/src/libs/qtcreatorcdbext/extensioncontext.h
index 8ff9807cb7389654a0f97e123fc18c0c6d22ceb8..27a3f76b22e1e33a945098135ed184e5c0951125 100644
--- a/src/libs/qtcreatorcdbext/extensioncontext.h
+++ b/src/libs/qtcreatorcdbext/extensioncontext.h
@@ -42,6 +42,7 @@
 
 class LocalsSymbolGroup;
 class WatchesSymbolGroup;
+class OutputCallback;
 
 // Global singleton with context.
 // Caches a symbolgroup per frame and thread as long as the session is accessible.
@@ -97,6 +98,11 @@ public:
     // Set a stop reason to be reported with the next idle notification (exception).
     void setStopReason(const StopReasonMap &, const std::string &reason = std::string());
 
+    void startRecordingOutput();
+    std::wstring stopRecordingOutput();
+    // Execute a function call and record the output.
+    bool call(const std::string &functionCall, std::wstring *output, std::string *errorMessage);
+
 private:
     bool isInitialized() const;
     void discardSymbolGroup();
@@ -109,9 +115,10 @@ private:
     IDebugEventCallbacks *m_oldEventCallback;
     IDebugOutputCallbacksWide *m_oldOutputCallback;
     IDebugEventCallbacks *m_creatorEventCallback;
-    IDebugOutputCallbacksWide *m_creatorOutputCallback;
+    OutputCallback *m_creatorOutputCallback;
 
     StopReasonMap m_stopReason;
+    bool m_stateNotification;
 };
 
 // Context for extension commands to be instantiated on stack in a command handler.
diff --git a/src/libs/qtcreatorcdbext/gdbmihelpers.cpp b/src/libs/qtcreatorcdbext/gdbmihelpers.cpp
index d36fb6f7cad3043bd6a9e8ced6efa10cebf530cd..6826df9b83ad074f29e43093a07cd38a0f7c3b09 100644
--- a/src/libs/qtcreatorcdbext/gdbmihelpers.cpp
+++ b/src/libs/qtcreatorcdbext/gdbmihelpers.cpp
@@ -35,6 +35,8 @@
 #include "stringutils.h"
 #include "iinterfacepointer.h"
 #include "base64.h"
+#include "symbolgroupvalue.h"
+#include "extensioncontext.h"
 
 #include <vector>
 
@@ -620,3 +622,51 @@ std::string gdbmiStack(CIDebugControl *debugControl,
     str << ']';
     return str.str();
 }
+
+// Find the widget of the application by calling QApplication::widgetAt().
+// Return "Qualified_ClassName:Address"
+
+static inline std::string msgWidgetParseError(std::wstring wo)
+{
+    replace(wo, L'\n', L';');
+    return "Output parse error :" + wStringToString(wo);
+}
+
+std::string widgetAt(const SymbolGroupValueContext &ctx, int x, int y, std::string *errorMessage)
+{
+    typedef SymbolGroupValue::SymbolList SymbolList;
+    // First, resolve symbol since there are ambiguities. Take the first one which is the
+    // overload for (int,int) and call by address instead off name to overcome that.
+    const std::string func = QtInfo::get(ctx).prependQtGuiModule("QApplication::widgetAt");
+    const SymbolList symbols = SymbolGroupValue::resolveSymbol(func.c_str(), ctx, errorMessage);
+    if (symbols.empty())
+        return std::string(); // Not a gui application, likely
+    std::ostringstream callStr;
+    callStr << std::showbase << std::hex << symbols.front().second
+            << std::noshowbase << std::dec << '(' << x << ',' << y << ')';
+    std::wstring wOutput;
+    if (!ExtensionContext::instance().call(callStr.str(), &wOutput, errorMessage))
+        return std::string();
+    // Returns: ".call returns\nclass QWidget * 0x00000000`022bf100\nbla...".
+    // Chop lines in front and after 'class ...' and convert first line.
+    const std::wstring::size_type classPos = wOutput.find(L"class ");
+    if (classPos == std::wstring::npos) {
+        *errorMessage = msgWidgetParseError(wOutput);
+        return std::string();
+    }
+    wOutput.erase(0, classPos + 6);
+    const std::wstring::size_type nlPos = wOutput.find(L'\n');
+    if (nlPos != std::wstring::npos)
+        wOutput.erase(nlPos, wOutput.size() - nlPos);
+    const std::string::size_type addressPos = wOutput.find(L" * 0x");
+    if (addressPos == std::string::npos) {
+        *errorMessage = msgWidgetParseError(wOutput);
+        return std::string();
+    }
+    // "QWidget * 0x00000000`022bf100" -> "QWidget:0x00000000022bf100"
+    wOutput.replace(addressPos, 3, L":");
+    const std::string::size_type sepPos = wOutput.find(L'`');
+    if (sepPos != std::string::npos)
+        wOutput.erase(sepPos, 1);
+    return wStringToString(wOutput);
+}
diff --git a/src/libs/qtcreatorcdbext/gdbmihelpers.h b/src/libs/qtcreatorcdbext/gdbmihelpers.h
index fee71a423137c2928f03893f4adedb0b7e1d49a9..849a05faebbfb9a44d0b6e90ee9e6b633212a96e 100644
--- a/src/libs/qtcreatorcdbext/gdbmihelpers.h
+++ b/src/libs/qtcreatorcdbext/gdbmihelpers.h
@@ -37,6 +37,8 @@
 #include "common.h"
 #include <vector>
 
+struct SymbolGroupValueContext;
+
 /* Various helpers to the extension commands to retrieve debuggee information
  * in suitable formats for the debugger engine. */
 
@@ -159,4 +161,9 @@ std::string gdbmiStack(CIDebugControl *debugControl, CIDebugSymbols *debugSymbol
                        unsigned maxFrames, bool humanReadable,
                        std::string *errorMessage);
 
+// Find the widget of the application at (x,y) by calling QApplication::widgetAt().
+// Return a string of "Qualified_ClassName:Address"
+std::string widgetAt(const SymbolGroupValueContext &ctx,
+                     int x, int y, std::string *errorMessage);
+
 #endif // THREADLIST_H
diff --git a/src/libs/qtcreatorcdbext/outputcallback.cpp b/src/libs/qtcreatorcdbext/outputcallback.cpp
index 63dde47e5ea49e110d23f12970ca67d9828fb436..cb3c57ed114d557436b3112ecc683bf92f31de1c 100644
--- a/src/libs/qtcreatorcdbext/outputcallback.cpp
+++ b/src/libs/qtcreatorcdbext/outputcallback.cpp
@@ -38,7 +38,8 @@
 
 #include <cstring>
 
-OutputCallback::OutputCallback(IDebugOutputCallbacksWide *wrapped) : m_wrapped(wrapped)
+OutputCallback::OutputCallback(IDebugOutputCallbacksWide *wrapped) :
+    m_wrapped(wrapped), m_recording(false)
 {
 }
 
@@ -85,6 +86,9 @@ STDMETHODIMP OutputCallback::Output(
         IN PCWSTR text
         )
 {
+
+    if (m_recording)
+        m_recorded.append(text);
     // Do not unconditionally output ourselves here, as this causes an endless
     // recursion. Suppress prompts (note that sequences of prompts may mess parsing up)
     if (!m_wrapped || mask == DEBUG_OUTPUT_PROMPT)
@@ -100,3 +104,17 @@ STDMETHODIMP OutputCallback::Output(
     ExtensionContext::instance().reportLong('E', 0, "debuggee_output", str.str().c_str());
     return S_OK;
 }
+
+void OutputCallback::startRecording()
+{
+    m_recorded.clear();
+    m_recording = true;
+}
+
+std::wstring OutputCallback::stopRecording()
+{
+    const std::wstring rc = m_recorded;
+    m_recorded.clear();
+    m_recording = false;
+    return rc;
+}
diff --git a/src/libs/qtcreatorcdbext/outputcallback.h b/src/libs/qtcreatorcdbext/outputcallback.h
index 4ba81a218b8ef9cd02bb206e693329855ce914b0..4432ab3821b19cea81cd96470d56f12daccae108 100644
--- a/src/libs/qtcreatorcdbext/outputcallback.h
+++ b/src/libs/qtcreatorcdbext/outputcallback.h
@@ -63,8 +63,13 @@ public:
             IN PCWSTR text
             );
 
+    void startRecording();
+    std::wstring stopRecording();
+
 private:
     IDebugOutputCallbacksWide *m_wrapped;
+    bool m_recording;
+    std::wstring m_recorded;
 };
 
 #endif // DEBUGEVENTOUTPUT_H
diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbext.def b/src/libs/qtcreatorcdbext/qtcreatorcdbext.def
index e8c47d447e82ebb5d2e2d5e3d7ae00ba302c4cb7..bc91011c9b5776c0a7584840023e0df237b6b35c 100644
--- a/src/libs/qtcreatorcdbext/qtcreatorcdbext.def
+++ b/src/libs/qtcreatorcdbext/qtcreatorcdbext.def
@@ -20,4 +20,5 @@ shutdownex
 test
 stack
 addwatch
+widgetat
 KnownStructOutput
diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp
index 706bb055ac03d2a77556268f33f066784b261f3e..ef3fd00ec0abd73c7e9d798dddc2d7b8be5dc2dd 100644
--- a/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp
+++ b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp
@@ -100,6 +100,7 @@ enum Command {
     CmdStack,
     CmdShutdownex,
     CmdAddWatch,
+    CmdWidgetAt,
     CmdTest
 };
 
@@ -155,6 +156,7 @@ static const CommandDescription commandDescriptions[] = {
 {"stack","Prints stack in GDBMI format.","[-t token] [max-frames]"},
 {"shutdownex","Unhooks output callbacks.\nNeeds to be called explicitly only in case of remote debugging.",""},
 {"addwatch","Add watch expression","<iname> <expression>"},
+{"widgetat","Return address of widget at position","<x> <y>"},
 {"test","Testing command","-T type | -w watch-expression"}
 };
 
@@ -943,6 +945,38 @@ extern "C" HRESULT CALLBACK shutdownex(CIDebugClient *, PCSTR)
     return S_OK;
 }
 
+extern "C" HRESULT CALLBACK widgetat(CIDebugClient *client, PCSTR argsIn)
+{
+    ExtensionCommandContext exc(client);
+    int token = 0;
+    std::string widgetAddress;
+    std::string errorMessage;
+
+    do {
+        int x = -1;
+        int y = -1;
+
+        const StringVector tokens = commandTokens<StringVector>(argsIn, &token);
+        if (tokens.size() != 2) {
+            errorMessage = singleLineUsage(commandDescriptions[CmdWidgetAt]);
+            break;
+        }
+        if (!integerFromString(tokens.front(), &x) || !integerFromString(tokens.at(1), &y)) {
+            errorMessage = singleLineUsage(commandDescriptions[CmdWidgetAt]);
+            break;
+        }
+        widgetAddress = widgetAt(SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()),
+                                 x, y, &errorMessage);
+    } while (false);
+
+    if (widgetAddress.empty()) {
+        ExtensionContext::instance().report('N', token, 0, "widgetat", errorMessage.c_str());
+    } else {
+        ExtensionContext::instance().reportLong('R', token, "widgetat", widgetAddress);
+    }
+    return S_OK;
+}
+
 extern "C" HRESULT CALLBACK test(CIDebugClient *client, PCSTR argsIn)
 {
     enum Mode { Invalid, TestType, TestFixWatchExpression };
diff --git a/src/libs/qtcreatorcdbext/symbolgroup.cpp b/src/libs/qtcreatorcdbext/symbolgroup.cpp
index 1b5de07e55007879a61a79afcf2f178c538f3746..6aaa6185a83889c7dc4c8eedd1765e20d619c121 100644
--- a/src/libs/qtcreatorcdbext/symbolgroup.cpp
+++ b/src/libs/qtcreatorcdbext/symbolgroup.cpp
@@ -701,7 +701,6 @@ static bool parseWatchExpression(const std::string &expression,
     for ( ; pos < size ; pos++) {
         const char c = expression.at(pos);
         const WatchExpressionParseState nextState = nextWatchExpressionParseState(state, c, &templateLevel);
-        DebugPrint() <<         c << ' ' << pos << ' ' << state << ' ' << nextState <<  ' ' << templateLevel;
         if (nextState == WEPS_Error)
             return false;
         if (nextState != state && state == WEPS_WithinType)
@@ -767,16 +766,19 @@ bool WatchesSymbolGroup::addWatch(CIDebugSymbols *s, std::string iname, const st
     return true;
 }
 
-// Compile map of current state root-iname->root-expression
+// Compile map of current state root-iname->root-expression (top-level)
 WatchesSymbolGroup::InameExpressionMap
     WatchesSymbolGroup::currentInameExpressionMap() const
 {
+    // Skip additional, expanded nodes
     InameExpressionMap rc;
-    if (unsigned size = unsigned(root()->children().size()))
+    if (unsigned size = unsigned(root()->children().size())) {
         for (unsigned i = 0; i < size; i++) {
             const AbstractSymbolGroupNode *n = root()->childAt(i);
-            rc.insert(InameExpressionMap::value_type(n->iName(), n->name()));
+            if (n->testFlags(SymbolGroupNode::WatchNode))
+                rc.insert(InameExpressionMap::value_type(n->iName(), n->name()));
         }
+    }
     return rc;
 }
 
diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
index ec5fd2b54e192cdfe55cb96186f3ccd445844008..1bcd596ff3dbf0ccd1093fb87f766855c3158d07 100644
--- a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
+++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
@@ -398,7 +398,7 @@ static inline std::string resolveQtSymbol(const char *symbolC,
     std::string defaultPattern = defaultModuleNameC;
     defaultPattern.push_back('!');
     defaultPattern += symbolC;
-    const StringList defaultMatches = SymbolGroupValue::resolveSymbol(defaultPattern.c_str(), ctx);
+    const StringList defaultMatches = SymbolGroupValue::resolveSymbolName(defaultPattern.c_str(), ctx);
     const SubStringPredicate modulePattern(modulePatternC);
     const StringListConstIt defaultIt = std::find_if(defaultMatches.begin(), defaultMatches.end(), modulePattern);
     if (defaultIt !=  defaultMatches.end())
@@ -406,7 +406,7 @@ static inline std::string resolveQtSymbol(const char *symbolC,
     // Fail, now try a search with '*qstrdup' in all modules. This might return several matches
     // like 'QtCored4!qstrdup', 'QGuid4!qstrdup'
     const std::string wildCardPattern = std::string(1, '*') + symbolC;
-    const StringList allMatches = SymbolGroupValue::resolveSymbol(wildCardPattern.c_str(), ctx);
+    const StringList allMatches = SymbolGroupValue::resolveSymbolName(wildCardPattern.c_str(), ctx);
     const StringListConstIt allIt = std::find_if(allMatches.begin(), allMatches.end(), modulePattern);
     return allIt != allMatches.end() ? *allIt : std::string();
 }
@@ -491,12 +491,29 @@ std::ostream &operator<<(std::ostream &os, const QtInfo &i)
 }
 
 std::list<std::string>
+    SymbolGroupValue::resolveSymbolName(const char *pattern,
+                                    const SymbolGroupValueContext &c,
+                                    std::string *errorMessage /* = 0 */)
+{
+    // Extract the names
+    const SymbolList symbols = resolveSymbol(pattern, c, errorMessage);
+    std::list<std::string> rc;
+    if (!symbols.empty()) {
+        const SymbolList::const_iterator cend = symbols.end();
+        for (SymbolList::const_iterator it = symbols.begin(); it != cend; ++it)
+            rc.push_back(it->first);
+    }
+    return rc;
+
+}
+
+SymbolGroupValue::SymbolList
     SymbolGroupValue::resolveSymbol(const char *pattern,
                                     const SymbolGroupValueContext &c,
                                     std::string *errorMessage /* = 0 */)
 {
     enum { bufSize = 2048 };
-    std::list<std::string> rc;
+    std::list<Symbol> rc;
     if (errorMessage)
         errorMessage->clear();
     // Is it an incomplete symbol?
@@ -518,12 +535,13 @@ std::list<std::string>
         return rc;
     }
     char buf[bufSize];
+    ULONG64 offset;
     while (true) {
-        hr = c.symbols->GetNextSymbolMatch(handle, buf, bufSize - 1, 0, 0);
+        hr = c.symbols->GetNextSymbolMatch(handle, buf, bufSize - 1, 0, &offset);
         if (hr == E_NOINTERFACE)
             break;
         if (hr == S_OK)
-            rc.push_back(std::string(buf));
+            rc.push_back(Symbol(std::string(buf), offset));
     }
     c.symbols->EndSymbolMatch(handle);
     return rc;
diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.h b/src/libs/qtcreatorcdbext/symbolgroupvalue.h
index 689a5123404c2bcd73d62b2d88cdc8157bbb5541..3375f3e6b78b631c6a9179b1c26d6175c954e80f 100644
--- a/src/libs/qtcreatorcdbext/symbolgroupvalue.h
+++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.h
@@ -70,6 +70,9 @@ class SymbolGroupValue
     explicit SymbolGroupValue(const std::string &parentError);
 
 public:
+    typedef std::pair<std::string, ULONG64> Symbol;
+    typedef std::list<Symbol> SymbolList;
+
     explicit SymbolGroupValue(SymbolGroupNode *node, const SymbolGroupValueContext &c);
     SymbolGroupValue();
 
@@ -129,9 +132,13 @@ public:
                                    const SymbolGroupValueContext &ctx,
                                    const std::string &currentModule = std::string());
 
-    static std::list<std::string> resolveSymbol(const char *pattern,
-                                                const SymbolGroupValueContext &c,
-                                                std::string *errorMessage = 0);
+    static std::list<std::string> resolveSymbolName(const char *pattern,
+                                                    const SymbolGroupValueContext &c,
+                                                    std::string *errorMessage = 0);
+    static SymbolList resolveSymbol(const char *pattern,
+                                    const SymbolGroupValueContext &c,
+                                    std::string *errorMessage = 0);
+
     static unsigned pointerSize();
     static unsigned intSize();
 
diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp
index 78ec65d5b0477eb2cc0b42fecefa9a537278c5c9..d6d8440035b868bec1b51e97e4f08a29de62808b 100644
--- a/src/plugins/debugger/cdb/cdbengine.cpp
+++ b/src/plugins/debugger/cdb/cdbengine.cpp
@@ -353,7 +353,9 @@ CdbEngine::CdbEngine(const DebuggerStartParameters &sp,
     m_hasDebuggee(false),
     m_elapsedLogTime(0),
     m_sourceStepInto(false),
-    m_wX86BreakpointCount(0)
+    m_wX86BreakpointCount(0),
+    m_watchPointX(0),
+    m_watchPointY(0)
 {
     Utils::SavedAction *assemblerAction = theAssemblerAction();
     m_operateByInstructionPending = assemblerAction->isChecked();
@@ -1443,6 +1445,12 @@ unsigned CdbEngine::examineStopReason(const QByteArray &messageIn,
         *message = tr("Malformed stop response received.");
         return StopReportParseError|StopNotifyStop;
     }
+    // Additional stop messages occurring for debuggee function calls (widgetAt, etc). Just log.
+    if (state() == InferiorStopOk) {
+        *message = QString::fromLatin1("Ignored stop notification from function call (%1).").
+                    arg(QString::fromAscii(reason));
+        return StopReportLog;
+    }
     const int threadId = stopReason.findChild("threadId").data().toInt();
     if (reason == "breakpoint") {
         const int number = stopReason.findChild("breakpointId").data().toInt();
@@ -1511,6 +1519,9 @@ void CdbEngine::handleSessionIdle(const QByteArray &messageBA)
         attemptBreakpointSynchronization();
         doContinueInferior();
         return;
+    case SpecialStopGetWidgetAt:
+        postWidgetAtCommand();
+        return;
     case NoSpecialStop:
         break;
     }
@@ -2112,5 +2123,67 @@ void CdbEngine::postCommandSequence(unsigned mask)
     }
 }
 
+void CdbEngine::handleWidgetAt(const CdbExtensionCommandPtr &reply)
+{
+    bool success = false;
+    QString message;
+    do {
+        if (!reply->success) {
+            message = QString::fromAscii(reply->errorMessage);
+            break;
+        }
+        // Should be "namespace::QWidget:0x555"
+        QString watchExp = QString::fromAscii(reply->reply);
+        const int sepPos = watchExp.lastIndexOf(QLatin1Char(':'));
+        if (sepPos == -1) {
+            message = QString::fromAscii("Invalid output: %1").arg(watchExp);
+            break;
+        }
+        // 0x000 -> nothing found
+        if (!watchExp.mid(sepPos + 1).toULongLong(0, 0)) {
+            message = QString::fromAscii("No widget could be found at %1, %2.").arg(m_watchPointX).arg(m_watchPointY);
+            break;
+        }
+        // Turn into watch expression: "*(namespace::QWidget*)0x555"
+        watchExp.replace(sepPos, 1, QLatin1String("*)"));
+        watchExp.insert(0, QLatin1String("*("));
+        watchHandler()->watchExpression(watchExp);
+        success = true;
+    } while (false);
+    if (!success)
+        showMessage(message, LogWarning);
+    m_watchPointX = m_watchPointY = 0;
+}
+
+void CdbEngine::watchPoint(const QPoint &p)
+{
+    m_watchPointX = p.x();
+    m_watchPointY = p.y();
+    switch (state()) {
+    case InferiorStopOk:
+        postWidgetAtCommand();
+        break;
+    case InferiorRunOk:
+        // "Select Widget to Watch" from a running application is currently not
+        // supported. It could be implemented via SpecialStopGetWidgetAt-mode,
+        // but requires some work as not to confuse the engine by state-change notifications
+        // emitted by the debuggee function call.
+        showMessage(tr("\"Select Widget to Watch\": Please stop the application first."), LogWarning);
+        break;
+    default:
+        showMessage(tr("\"Select Widget to Watch\": Not supported in state '%1'.").
+                    arg(QString::fromAscii(stateName(state()))), LogWarning);
+        break;
+    }
+}
+
+void CdbEngine::postWidgetAtCommand()
+{
+    QByteArray arguments = QByteArray::number(m_watchPointX);
+    arguments.append(' ');
+    arguments.append(QByteArray::number(m_watchPointY));
+    postExtensionCommand("widgetat", arguments, 0, &CdbEngine::handleWidgetAt, 0);
+}
+
 } // namespace Internal
 } // namespace Debugger
diff --git a/src/plugins/debugger/cdb/cdbengine.h b/src/plugins/debugger/cdb/cdbengine.h
index bec8579cd0887ff238183eeef592a55eecb98b76..caf74fad626db820aef2f343f2ccddeee35a2153 100644
--- a/src/plugins/debugger/cdb/cdbengine.h
+++ b/src/plugins/debugger/cdb/cdbengine.h
@@ -89,6 +89,7 @@ public:
     virtual void updateWatchData(const WatchData &data,
                                  const WatchUpdateFlags & flags = WatchUpdateFlags());
     virtual unsigned debuggerCapabilities() const;
+    virtual void watchPoint(const QPoint &);
     virtual void setRegisterValue(int regnr, const QString &value);
 
     virtual void executeStep();
@@ -150,7 +151,12 @@ private slots:
     void operateByInstructionTriggered(bool);
 
 private:
-    enum SpecialStopMode { NoSpecialStop, SpecialStopSynchronizeBreakpoints };
+    enum SpecialStopMode
+    {
+        NoSpecialStop,
+        SpecialStopSynchronizeBreakpoints,
+        SpecialStopGetWidgetAt
+    };
 
     unsigned examineStopReason(const QByteArray &messageIn, QString *message,
                                QString *exceptionBoxMessage);
@@ -166,6 +172,7 @@ private:
     inline bool isCdbProcessRunning() const { return m_process.state() != QProcess::NotRunning; }
     bool canInterruptInferior() const;
     void syncOperateByInstruction(bool operateByInstruction);
+    void postWidgetAtCommand();
 
     // Builtin commands
     void dummyHandler(const CdbBuiltinCommandPtr &);
@@ -182,6 +189,7 @@ private:
     void handleRegisters(const CdbExtensionCommandPtr &reply);
     void handleModules(const CdbExtensionCommandPtr &reply);
     void handleMemory(const CdbExtensionCommandPtr &);
+    void handleWidgetAt(const CdbExtensionCommandPtr &);
 
     QString normalizeFileName(const QString &f);
     void updateLocalVariable(const QByteArray &iname);
@@ -215,6 +223,8 @@ private:
     QByteArray m_extensionMessageBuffer;
     bool m_sourceStepInto;
     unsigned m_wX86BreakpointCount;
+    int m_watchPointX;
+    int m_watchPointY;
 };
 
 } // namespace Internal