VirtualBox

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

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

Debugger: destroy the console window on close if the debugger is terminated. Some ready fixes.

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