VirtualBox

source: vbox/trunk/src/VBox/Debugger/VBoxDbgConsole.cpp@ 12878

Last change on this file since 12878 was 12878, checked in by vboxsync, 17 years ago

Debugger: log groups and console 'exit' fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.0 KB
Line 
1/* $Id: VBoxDbgConsole.cpp 12878 2008-10-01 21:11:52Z vboxsync $ */
2/** @file
3 * VBox Debugger GUI - Console.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_DBGG
27#include "VBoxDbgConsole.h"
28
29#ifdef VBOXDBG_USE_QT4
30# include <QLabel>
31# include <QApplication>
32# include <QFont>
33# include <QLineEdit>
34# include <QHBoxLayout>
35# include <QAction>
36#else
37# include <qlabel.h>
38# include <qapplication.h>
39# include <qfont.h>
40# include <qtextview.h>
41# include <qlineedit.h>
42#endif
43
44#include <VBox/dbg.h>
45#include <VBox/cfgm.h>
46#include <VBox/err.h>
47
48#include <iprt/thread.h>
49#include <iprt/tcp.h>
50#include <VBox/log.h>
51#include <iprt/assert.h>
52#include <iprt/asm.h>
53#include <iprt/alloc.h>
54#include <iprt/string.h>
55
56
57
58
59/*
60 *
61 * V B o x D b g C o n s o l e O u t p u t
62 * V B o x D b g C o n s o l e O u t p u t
63 * V B o x D b g C o n s o l e O u t p u t
64 *
65 *
66 */
67
68
69VBoxDbgConsoleOutput::VBoxDbgConsoleOutput(QWidget *pParent/* = NULL*/, const char *pszName/* = NULL*/)
70#ifdef VBOXDBG_USE_QT4
71 : QTextEdit(pParent),
72#else
73 : QTextEdit(pParent, pszName),
74#endif
75 m_uCurLine(0), m_uCurPos(0), m_hGUIThread(RTThreadNativeSelf())
76{
77 setReadOnly(true);
78 setUndoRedoEnabled(false);
79#ifdef VBOXDBG_USE_QT4
80 setOverwriteMode(false);
81 setPlainText("");
82 setTextInteractionFlags(Qt::TextBrowserInteraction);
83 setAutoFormatting(QTextEdit::AutoAll);
84 setTabChangesFocus(true);
85 setAcceptRichText(false);
86#else
87 setOverwriteMode(true);
88 setTextFormat(PlainText); /* minimal HTML: setTextFormat(LogText); */
89#endif
90
91#ifdef Q_WS_MAC
92 QFont Font("Monaco", 10, QFont::Normal, FALSE);
93 Font.setStyleStrategy(QFont::NoAntialias);
94#else
95 QFont Font = font();
96 Font.setStyleHint(QFont::TypeWriter);
97 Font.setFamily("Courier [Monotype]");
98#endif
99 setFont(Font);
100
101 /* green on black */
102#ifdef VBOXDBG_USE_QT4
103 QPalette Pal(palette());
104 Pal.setColor(QPalette::All, QPalette::Base, QColor(Qt::black));
105 setPalette(Pal);
106 setTextColor(QColor(qRgb(0, 0xe0, 0)));
107#else
108 setPaper(QBrush(Qt::black));
109 setColor(QColor(qRgb(0, 0xe0, 0)));
110#endif
111 NOREF(pszName);
112}
113
114
115VBoxDbgConsoleOutput::~VBoxDbgConsoleOutput()
116{
117 Assert(m_hGUIThread == RTThreadNativeSelf());
118}
119
120
121void
122VBoxDbgConsoleOutput::appendText(const QString &rStr)
123{
124 Assert(m_hGUIThread == RTThreadNativeSelf());
125
126 if (rStr.isEmpty() || rStr.isNull() || !rStr.length())
127 return;
128
129#ifdef VBOXDBG_USE_QT4
130 /*
131 * Insert all in one go and make sure it's visible.
132 */
133 QTextCursor Cursor = textCursor();
134 if (!Cursor.atEnd())
135 moveCursor(QTextCursor::End); /* make sure we append the text */
136 Cursor.insertText(rStr);
137 ensureCursorVisible();
138#else
139 /*
140 * Insert line by line.
141 */
142 unsigned cch = rStr.length();
143 unsigned iPos = 0;
144 while (iPos < cch)
145 {
146 int iPosNL = rStr.find('\n', iPos);
147 int iPosEnd = iPosNL >= 0 ? iPosNL : cch;
148 if ((unsigned)iPosNL != iPos)
149 {
150 QString Str = rStr.mid(iPos, iPosEnd - iPos);
151 if (m_uCurPos == 0)
152 append(Str);
153 else
154 insertAt(Str, m_uCurLine, m_uCurPos);
155 if (iPosNL >= 0)
156 {
157 m_uCurLine++;
158 m_uCurPos = 0;
159 }
160 else
161 m_uCurPos += Str.length();
162 }
163 else
164 {
165 m_uCurLine++;
166 m_uCurPos = 0;
167 }
168
169 /* next */
170 iPos = iPosEnd + 1;
171 }
172#endif
173}
174
175
176
177
178/*
179 *
180 * V B o x D b g C o n s o l e I n p u t
181 * V B o x D b g C o n s o l e I n p u t
182 * V B o x D b g C o n s o l e I n p u t
183 *
184 *
185 */
186
187
188VBoxDbgConsoleInput::VBoxDbgConsoleInput(QWidget *pParent/* = NULL*/, const char *pszName/* = NULL*/)
189#ifdef VBOXDBG_USE_QT4
190 : QComboBox(pParent),
191#else
192 : QComboBox(true, pParent, pszName),
193#endif
194 m_iBlankItem(0), m_hGUIThread(RTThreadNativeSelf())
195{
196#ifdef VBOXDBG_USE_QT4
197 insertItem(m_iBlankItem, "");
198 setEditable(true);
199 setInsertPolicy(NoInsert);
200 setAutoCompletion(false);
201#else
202 insertItem("", m_iBlankItem);
203 setInsertionPolicy(NoInsertion);
204#endif
205 setMaxCount(50);
206 const QLineEdit *pEdit = lineEdit();
207 if (pEdit)
208 connect(pEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
209
210 NOREF(pszName);
211}
212
213
214VBoxDbgConsoleInput::~VBoxDbgConsoleInput()
215{
216 Assert(m_hGUIThread == RTThreadNativeSelf());
217}
218
219
220void
221VBoxDbgConsoleInput::setLineEdit(QLineEdit *pEdit)
222{
223 Assert(m_hGUIThread == RTThreadNativeSelf());
224 QComboBox::setLineEdit(pEdit);
225 if (lineEdit() == pEdit && pEdit)
226 connect(pEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
227}
228
229
230void
231VBoxDbgConsoleInput::returnPressed()
232{
233 Assert(m_hGUIThread == RTThreadNativeSelf());
234 /* deal with the current command. */
235 QString Str = currentText();
236 emit commandSubmitted(Str);
237
238 /* update the history and clear the entry field */
239#ifdef VBOXDBG_USE_QT4
240 if (itemText(m_iBlankItem - 1) != Str)
241 {
242 setItemText(m_iBlankItem, Str);
243 removeItem(m_iBlankItem - maxCount() - 1);
244 insertItem(++m_iBlankItem, "");
245 }
246
247 clearEditText();
248 setCurrentIndex(m_iBlankItem);
249#else
250 if (text(m_iBlankItem - 1) != Str)
251 {
252 changeItem(Str, m_iBlankItem);
253 removeItem(m_iBlankItem - maxCount() - 1);
254 insertItem("", ++m_iBlankItem);
255 }
256
257 clearEdit();
258 setCurrentItem(m_iBlankItem);
259#endif
260}
261
262
263
264
265
266
267/*
268 *
269 * V B o x D b g C o n s o l e
270 * V B o x D b g C o n s o l e
271 * V B o x D b g C o n s o l e
272 *
273 *
274 */
275
276
277VBoxDbgConsole::VBoxDbgConsole(PVM pVM, QWidget *pParent/* = NULL*/, const char *pszName/* = NULL*/)
278 : VBoxDbgBase(pVM), m_pOutput(NULL), m_pInput(NULL),
279 m_fInputNeedsEnabling(false), m_fInputRestoreFocus(false),
280 m_pszInputBuf(NULL), m_cbInputBuf(0), m_cbInputBufAlloc(0),
281 m_pszOutputBuf(NULL), m_cbOutputBuf(0), m_cbOutputBufAlloc(0),
282 m_pTimer(NULL), m_fUpdatePending(false), m_Thread(NIL_RTTHREAD), m_EventSem(NIL_RTSEMEVENT), m_fTerminate(false)
283{
284#ifdef VBOXDBG_USE_QT4
285 setWindowTitle("VBoxDbg - Console");
286#else
287 setCaption("VBoxDbg - Console");
288#endif
289
290 NOREF(pszName);
291 NOREF(pParent);
292
293 /*
294 * Create the output text box.
295 */
296 m_pOutput = new VBoxDbgConsoleOutput(this);
297
298 /* try figure a suitable size */
299#ifdef VBOXDBG_USE_QT4
300 QLabel *pLabel = new QLabel( "11111111111111111111111111111111111111111111111111111111111111111111111111111112222222222", this);
301#else
302 QLabel *pLabel = new QLabel(NULL, "11111111111111111111111111111111111111111111111111111111111111111111111111111112222222222", this); /// @todo
303#endif
304 pLabel->setFont(m_pOutput->font());
305 QSize Size = pLabel->sizeHint();
306 delete pLabel;
307 Size.setWidth((int)(Size.width() * 1.10));
308 Size.setHeight(Size.width() / 2);
309 resize(Size);
310
311 /*
312 * Create the input combo box (with a label).
313 */
314#ifdef VBOXDBG_USE_QT4
315 QHBoxLayout *pLayout = new QHBoxLayout();
316 //pLayout->setSizeConstraint(QLayout::SetMaximumSize);
317
318 pLabel = new QLabel(" Command ");
319 pLayout->addWidget(pLabel);
320 pLabel->setMaximumSize(pLabel->sizeHint());
321 pLabel->setAlignment(Qt::AlignCenter);
322
323 m_pInput = new VBoxDbgConsoleInput(NULL);
324 pLayout->addWidget(m_pInput);
325 m_pInput->setDuplicatesEnabled(false);
326 connect(m_pInput, SIGNAL(commandSubmitted(const QString &)), this, SLOT(commandSubmitted(const QString &)));
327
328# if 0//def Q_WS_MAC
329 pLabel = new QLabel(" ");
330 pLayout->addWidget(pLabel);
331 pLabel->setMaximumSize(20, m_pInput->sizeHint().height() + 6);
332 pLabel->setMinimumSize(20, m_pInput->sizeHint().height() + 6);
333# endif
334
335 QWidget *pHBox = new QWidget(this);
336 pHBox->setLayout(pLayout);
337
338#else /* QT3 */
339 QHBox *pHBox = new QHBox(this);
340
341 pLabel = new QLabel(NULL, " Command ", pHBox);
342 pLabel->setMaximumSize(pLabel->sizeHint());
343 pLabel->setAlignment(AlignHCenter | AlignVCenter);
344
345 m_pInput = new VBoxDbgConsoleInput(pHBox);
346 m_pInput->setDuplicatesEnabled(false);
347 connect(m_pInput, SIGNAL(commandSubmitted(const QString &)), this, SLOT(commandSubmitted(const QString &)));
348
349# ifdef Q_WS_MAC
350 pLabel = new QLabel(NULL, " ", pHBox); /// @todo
351 pLabel->setMaximumSize(20, m_pInput->sizeHint().height() + 6);
352 pLabel->setMinimumSize(20, m_pInput->sizeHint().height() + 6);
353# endif
354#endif /* QT3 */
355
356#ifdef VBOXDBG_USE_QT4
357 /*
358 * Vertical layout box on the whole widget.
359 */
360 QVBoxLayout *pVLayout = new QVBoxLayout;
361 pVLayout->setSpacing(5);
362 pVLayout->setContentsMargins(0, 0, 0, 0);
363 pVLayout->addWidget(m_pOutput);
364 pVLayout->addWidget(pHBox);
365 setLayout(pVLayout);
366#endif
367
368 /*
369 * The tab order is from input to output, not the otherway around as it is by default.
370 */
371 setTabOrder(m_pInput, m_pOutput);
372
373 /*
374 * Setup the timer.
375 */
376 m_pTimer = new QTimer(this);
377 connect(m_pTimer, SIGNAL(timeout()), SLOT(updateOutput()));
378
379 /*
380 * Init the backend structure.
381 */
382 m_Back.Core.pfnInput = backInput;
383 m_Back.Core.pfnRead = backRead;
384 m_Back.Core.pfnWrite = backWrite;
385 m_Back.pSelf = this;
386
387 /*
388 * Create the critical section, the event semaphore and the debug console thread.
389 */
390 int rc = RTCritSectInit(&m_Lock);
391 AssertRC(rc);
392
393 rc = RTSemEventCreate(&m_EventSem);
394 AssertRC(rc);
395
396 rc = RTThreadCreate(&m_Thread, backThread, this, 0, RTTHREADTYPE_DEBUGGER, RTTHREADFLAGS_WAITABLE, "VBoxDbgC");
397 AssertRC(rc);
398 if (VBOX_FAILURE(rc))
399 m_Thread = NIL_RTTHREAD;
400
401#ifdef VBOXDBG_USE_QT4
402 /*
403 * Shortcuts.
404 */
405 m_pFocusToInput = new QAction("", this);
406 m_pFocusToInput->setShortcut(QKeySequence("Ctrl+L"));
407 addAction(m_pFocusToInput);
408 connect(m_pFocusToInput, SIGNAL(triggered(bool)), this, SLOT(actFocusToInput()));
409
410 m_pFocusToOutput = new QAction("", this);
411 m_pFocusToOutput->setShortcut(QKeySequence("Ctrl+O"));
412 addAction(m_pFocusToOutput);
413 connect(m_pFocusToOutput, SIGNAL(triggered(bool)), this, SLOT(actFocusToOutput()));
414#endif
415}
416
417
418VBoxDbgConsole::~VBoxDbgConsole()
419{
420 Assert(isGUIThread());
421
422 /*
423 * Wait for the thread.
424 */
425 ASMAtomicWriteBool(&m_fTerminate, true);
426 RTSemEventSignal(m_EventSem);
427 if (m_Thread != NIL_RTTHREAD)
428 {
429 int rc = RTThreadWait(m_Thread, 15000, NULL);
430 AssertRC(rc);
431 m_Thread = NIL_RTTHREAD;
432 }
433
434 /*
435 * Free resources.
436 */
437 delete m_pTimer;
438 m_pTimer = NULL;
439 RTCritSectDelete(&m_Lock);
440 RTSemEventDestroy(m_EventSem);
441 m_EventSem = 0;
442 m_pOutput = NULL;
443 m_pInput = NULL;
444 if (m_pszInputBuf)
445 {
446 RTMemFree(m_pszInputBuf);
447 m_pszInputBuf = NULL;
448 }
449 m_cbInputBuf = 0;
450 m_cbInputBufAlloc = 0;
451
452#ifdef VBOXDBG_USE_QT4
453 delete m_pFocusToInput;
454 m_pFocusToInput = NULL;
455 delete m_pFocusToOutput;
456 m_pFocusToOutput = NULL;
457#endif
458}
459
460
461void
462VBoxDbgConsole::commandSubmitted(const QString &rCommand)
463{
464 Assert(isGUIThread());
465
466 lock();
467 RTSemEventSignal(m_EventSem);
468
469#ifdef VBOXDBG_USE_QT4
470 QByteArray Utf8Array = rCommand.toUtf8();
471 const char *psz = Utf8Array.constData();
472#else
473 const char *psz = rCommand;//.utf8();
474#endif
475 size_t cb = strlen(psz);
476
477 /*
478 * Make sure we've got space for the input.
479 */
480 if (cb + m_cbInputBuf >= m_cbInputBufAlloc)
481 {
482 size_t cbNew = RT_ALIGN_Z(cb + m_cbInputBufAlloc + 1, 128);
483 void *pv = RTMemRealloc(m_pszInputBuf, cbNew);
484 if (!pv)
485 {
486 unlock();
487 return;
488 }
489 m_pszInputBuf = (char *)pv;
490 m_cbInputBufAlloc = cbNew;
491 }
492
493 /*
494 * Add the input and output it.
495 */
496 memcpy(m_pszInputBuf + m_cbInputBuf, psz, cb);
497 m_cbInputBuf += cb;
498 m_pszInputBuf[m_cbInputBuf++] = '\n';
499
500 m_pOutput->appendText(rCommand + "\n");
501#ifdef VBOXDBG_USE_QT4
502 m_pOutput->ensureCursorVisible();
503#else
504 m_pOutput->scrollToBottom();
505#endif
506
507 m_fInputRestoreFocus = m_pInput->hasFocus(); /* dirty focus hack */
508 m_fInputNeedsEnabling = true;
509 m_pInput->setEnabled(false);
510
511 Log(("VBoxDbgConsole::commandSubmitted: %s (input-enabled=%RTbool)\n", psz, m_pInput->isEnabled()));
512 unlock();
513}
514
515
516void
517VBoxDbgConsole::updateOutput()
518{
519 Assert(isGUIThread());
520
521 lock();
522 m_fUpdatePending = false;
523 if (m_cbOutputBuf)
524 {
525 m_pOutput->appendText(QString::fromUtf8((const char *)m_pszOutputBuf, m_cbOutputBuf));
526 m_cbOutputBuf = 0;
527 }
528 unlock();
529}
530
531
532/**
533 * Lock the object.
534 */
535void
536VBoxDbgConsole::lock()
537{
538 RTCritSectEnter(&m_Lock);
539}
540
541
542/**
543 * Unlocks the object.
544 */
545void
546VBoxDbgConsole::unlock()
547{
548 RTCritSectLeave(&m_Lock);
549}
550
551
552
553/**
554 * Checks if there is input.
555 *
556 * @returns true if there is input ready.
557 * @returns false if there not input ready.
558 * @param pBack Pointer to VBoxDbgConsole::m_Back.
559 * @param cMillies Number of milliseconds to wait on input data.
560 */
561/*static*/ DECLCALLBACK(bool)
562VBoxDbgConsole::backInput(PDBGCBACK pBack, uint32_t cMillies)
563{
564 VBoxDbgConsole *pThis = VBOXDBGCONSOLE_FROM_DBGCBACK(pBack);
565 pThis->lock();
566
567 bool fRc = true;
568 if (!pThis->m_cbInputBuf)
569 {
570 /*
571 * Questing for input and not finding any means it's done processing
572 * any commands that we've queued. Re-enable the input field if required.
573 */
574 if (pThis->m_fInputNeedsEnabling)
575 {
576 pThis->m_fInputNeedsEnabling = false;
577 QApplication::postEvent(pThis, new VBoxDbgConsoleEvent(VBoxDbgConsoleEvent::kInputEnable));
578 }
579
580 /*
581 * Wait outside the lock for the requested time, then check again.
582 */
583 pThis->unlock();
584 RTSemEventWait(pThis->m_EventSem, cMillies);
585 pThis->lock();
586 fRc = pThis->m_cbInputBuf
587 || ASMAtomicUoReadBool(&pThis->m_fTerminate);
588 }
589
590 pThis->unlock();
591 return fRc;
592}
593
594
595/**
596 * Read input.
597 *
598 * @returns VBox status code.
599 * @param pBack Pointer to VBoxDbgConsole::m_Back.
600 * @param pvBuf Where to put the bytes we read.
601 * @param cbBuf Maximum nymber of bytes to read.
602 * @param pcbRead Where to store the number of bytes actually read.
603 * If NULL the entire buffer must be filled for a
604 * successful return.
605 */
606/*static*/ DECLCALLBACK(int)
607VBoxDbgConsole::backRead(PDBGCBACK pBack, void *pvBuf, size_t cbBuf, size_t *pcbRead)
608{
609 VBoxDbgConsole *pThis = VBOXDBGCONSOLE_FROM_DBGCBACK(pBack);
610 Assert(pcbRead); /** @todo implement this bit */
611 if (pcbRead)
612 *pcbRead = 0;
613
614 pThis->lock();
615 int rc = VINF_SUCCESS;
616 if (!ASMAtomicUoReadBool(&pThis->m_fTerminate))
617 {
618 if (pThis->m_cbInputBuf)
619 {
620 const char *psz = pThis->m_pszInputBuf;
621 size_t cbRead = RT_MIN(pThis->m_cbInputBuf, cbBuf);
622 memcpy(pvBuf, psz, cbRead);
623 psz += cbRead;
624 pThis->m_cbInputBuf -= cbRead;
625 if (*psz)
626 memmove(pThis->m_pszInputBuf, psz, pThis->m_cbInputBuf);
627 pThis->m_pszInputBuf[pThis->m_cbInputBuf] = '\0';
628 *pcbRead = cbRead;
629 }
630 }
631 else
632 rc = VERR_GENERAL_FAILURE;
633 pThis->unlock();
634 return rc;
635}
636
637
638/**
639 * Write (output).
640 *
641 * @returns VBox status code.
642 * @param pBack Pointer to VBoxDbgConsole::m_Back.
643 * @param pvBuf What to write.
644 * @param cbBuf Number of bytes to write.
645 * @param pcbWritten Where to store the number of bytes actually written.
646 * If NULL the entire buffer must be successfully written.
647 */
648/*static*/ DECLCALLBACK(int)
649VBoxDbgConsole::backWrite(PDBGCBACK pBack, const void *pvBuf, size_t cbBuf, size_t *pcbWritten)
650{
651 VBoxDbgConsole *pThis = VBOXDBGCONSOLE_FROM_DBGCBACK(pBack);
652 int rc = VINF_SUCCESS;
653
654 pThis->lock();
655 if (cbBuf + pThis->m_cbOutputBuf >= pThis->m_cbOutputBufAlloc)
656 {
657 size_t cbNew = RT_ALIGN_Z(cbBuf + pThis->m_cbOutputBufAlloc + 1, 1024);
658 void *pv = RTMemRealloc(pThis->m_pszOutputBuf, cbNew);
659 if (!pv)
660 {
661 pThis->unlock();
662 if (pcbWritten)
663 *pcbWritten = 0;
664 return VERR_NO_MEMORY;
665 }
666 pThis->m_pszOutputBuf = (char *)pv;
667 pThis->m_cbOutputBufAlloc = cbNew;
668 }
669
670 /*
671 * Add the output.
672 */
673 memcpy(pThis->m_pszOutputBuf + pThis->m_cbOutputBuf, pvBuf, cbBuf);
674 pThis->m_cbOutputBuf += cbBuf;
675 pThis->m_pszOutputBuf[pThis->m_cbOutputBuf] = '\0';
676 if (pcbWritten)
677 *pcbWritten = cbBuf;
678
679 if (ASMAtomicUoReadBool(&pThis->m_fTerminate))
680 rc = VERR_GENERAL_FAILURE;
681
682 /*
683 * Tell the GUI thread to draw this text.
684 * We cannot do it from here without frequent crashes.
685 */
686 if (!pThis->m_fUpdatePending)
687 QApplication::postEvent(pThis, new VBoxDbgConsoleEvent(VBoxDbgConsoleEvent::kUpdate));
688
689 pThis->unlock();
690
691 return rc;
692}
693
694
695/**
696 * The Debugger Console Thread
697 *
698 * @returns VBox status code (ignored).
699 * @param Thread The thread handle.
700 * @param pvUser Pointer to the VBoxDbgConsole object.s
701 */
702/*static*/ DECLCALLBACK(int)
703VBoxDbgConsole::backThread(RTTHREAD Thread, void *pvUser)
704{
705 VBoxDbgConsole *pThis = (VBoxDbgConsole *)pvUser;
706 LogFlow(("backThread: Thread=%p pvUser=%p\n", (void *)Thread, pvUser));
707
708 NOREF(Thread);
709
710 /*
711 * Create and execute the console.
712 */
713 int rc = pThis->dbgcCreate(&pThis->m_Back.Core, 0);
714 if (!ASMAtomicUoReadBool(&pThis->m_fTerminate))
715 QApplication::postEvent(pThis, new VBoxDbgConsoleEvent(rc == VINF_SUCCESS
716 ? VBoxDbgConsoleEvent::kTerminatedUser
717 : VBoxDbgConsoleEvent::kTerminatedOther));
718 LogFlow(("backThread: returns %Rrc (m_fTerminate=%RTbool)\n", rc, ASMAtomicUoReadBool(&pThis->m_fTerminate)));
719 return rc;
720}
721
722
723bool
724VBoxDbgConsole::event(QEvent *pGenEvent)
725{
726 Assert(isGUIThread());
727 if (pGenEvent->type() == (QEvent::Type)VBoxDbgConsoleEvent::kEventNumber)
728 {
729 VBoxDbgConsoleEvent *pEvent = (VBoxDbgConsoleEvent *)pGenEvent;
730
731 switch (pEvent->command())
732 {
733 /* make update pending. */
734 case VBoxDbgConsoleEvent::kUpdate:
735 lock();
736 if (!m_fUpdatePending)
737 {
738 m_fUpdatePending = true;
739#ifdef VBOXDBG_USE_QT4
740 m_pTimer->setSingleShot(true);
741 m_pTimer->start(10);
742#else
743 m_pTimer->start(10, true /* single shot */);
744#endif
745 }
746 unlock();
747 break;
748
749 /* Re-enable the input field and restore focus. */
750 case VBoxDbgConsoleEvent::kInputEnable:
751 Log(("VBoxDbgConsole: kInputEnable (input-enabled=%RTbool)\n", m_pInput->isEnabled()));
752 m_pInput->setEnabled(true);
753 if ( m_fInputRestoreFocus
754 && !m_pInput->hasFocus())
755 m_pInput->setFocus(); /* this is a hack. */
756 m_fInputRestoreFocus = false;
757 break;
758
759 /* The thread terminated by user command (exit, quit, bye). */
760 case VBoxDbgConsoleEvent::kTerminatedUser:
761 Log(("VBoxDbgConsole: kTerminatedUser (input-enabled=%RTbool)\n", m_pInput->isEnabled()));
762 close();
763 break;
764
765 /* The thread terminated for some unknown reason., disable input */
766 case VBoxDbgConsoleEvent::kTerminatedOther:
767 Log(("VBoxDbgConsole: kTerminatedOther (input-enabled=%RTbool)\n", m_pInput->isEnabled()));
768 m_pInput->setEnabled(false);
769 break;
770
771 /* paranoia */
772 default:
773 AssertMsgFailed(("command=%d\n", pEvent->command()));
774 break;
775 }
776 return true;
777 }
778
779#ifdef VBOXDBG_USE_QT4
780 return QWidget::event(pGenEvent);
781#else
782 return QVBox::event(pGenEvent);
783#endif
784}
785
786
787void
788VBoxDbgConsole::actFocusToInput()
789{
790 if (!m_pInput->hasFocus())
791#ifdef VBOXDBG_USE_QT4
792 m_pInput->setFocus(Qt::ShortcutFocusReason);
793#else
794 m_pInput->setFocus();
795#endif
796}
797
798
799void
800VBoxDbgConsole::actFocusToOutput()
801{
802 if (!m_pOutput->hasFocus())
803#ifdef VBOXDBG_USE_QT4
804 m_pOutput->setFocus(Qt::ShortcutFocusReason);
805#else
806 m_pOutput->setFocus();
807#endif
808}
809
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette