VirtualBox

source: vbox/trunk/src/VBox/Debugger/VBoxDbgBase.cpp

Last change on this file was 101107, checked in by vboxsync, 9 months ago

VBoxDbg: Rewrote the automatic window positioning to make it more flexible and to try keep the console window wide enough for at least 80 columns of text.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.1 KB
RevLine 
[31510]1/* $Id: VBoxDbgBase.cpp 101107 2023-09-13 14:01:58Z vboxsync $ */
2/** @file
3 * VBox Debugger GUI - Base classes.
4 */
5
6/*
[98103]7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
[31510]8 *
[96407]9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
[31510]26 */
27
[57358]28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
[31510]32#define LOG_GROUP LOG_GROUP_DBGG
[76474]33#include <iprt/errcore.h>
[31510]34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <limits.h>
37#include "VBoxDbgBase.h"
38#include "VBoxDbgGui.h"
39
40#include <QApplication>
41#include <QWidgetList>
42
43
44
45VBoxDbgBase::VBoxDbgBase(VBoxDbgGui *a_pDbgGui)
[93468]46 : m_pDbgGui(a_pDbgGui), m_pUVM(NULL), m_pVMM(NULL), m_hGUIThread(RTThreadNativeSelf())
[31510]47{
[63452]48 NOREF(m_pDbgGui); /* shut up warning. */
49
[31510]50 /*
51 * Register
52 */
[44340]53 m_pUVM = a_pDbgGui->getUvmHandle();
[93468]54 m_pVMM = a_pDbgGui->getVMMFunctionTable();
55 if (m_pUVM && m_pVMM)
[31510]56 {
[93468]57 m_pVMM->pfnVMR3RetainUVM(m_pUVM);
[44340]58
[93468]59 int rc = m_pVMM->pfnVMR3AtStateRegister(m_pUVM, atStateChange, this);
[31510]60 AssertRC(rc);
61 }
62}
63
64
65VBoxDbgBase::~VBoxDbgBase()
66{
67 /*
68 * If the VM is still around.
69 */
70 /** @todo need to do some locking here? */
[93468]71 PUVM pUVM = ASMAtomicXchgPtrT(&m_pUVM, NULL, PUVM);
72 PCVMMR3VTABLE pVMM = ASMAtomicXchgPtrT(&m_pVMM, NULL, PCVMMR3VTABLE);
73 if (pUVM && pVMM)
[31510]74 {
[93468]75 int rc = pVMM->pfnVMR3AtStateDeregister(pUVM, atStateChange, this);
[31510]76 AssertRC(rc);
[44340]77
[93468]78 pVMM->pfnVMR3ReleaseUVM(pUVM);
[31510]79 }
80}
81
82
83int
84VBoxDbgBase::stamReset(const QString &rPat)
85{
86 QByteArray Utf8Array = rPat.toUtf8();
87 const char *pszPat = !rPat.isEmpty() ? Utf8Array.constData() : NULL;
[93468]88 PUVM pUVM = m_pUVM;
89 PCVMMR3VTABLE pVMM = m_pVMM;
90 if ( pUVM
91 && pVMM
92 && pVMM->pfnVMR3GetStateU(pUVM) < VMSTATE_DESTROYING)
93 return pVMM->pfnSTAMR3Reset(pUVM, pszPat);
[31510]94 return VERR_INVALID_HANDLE;
95}
96
97
98int
99VBoxDbgBase::stamEnum(const QString &rPat, PFNSTAMR3ENUM pfnEnum, void *pvUser)
100{
101 QByteArray Utf8Array = rPat.toUtf8();
102 const char *pszPat = !rPat.isEmpty() ? Utf8Array.constData() : NULL;
[93468]103 PUVM pUVM = m_pUVM;
104 PCVMMR3VTABLE pVMM = m_pVMM;
105 if ( pUVM
106 && pVMM
107 && pVMM->pfnVMR3GetStateU(pUVM) < VMSTATE_DESTROYING)
108 return pVMM->pfnSTAMR3Enum(pUVM, pszPat, pfnEnum, pvUser);
[31510]109 return VERR_INVALID_HANDLE;
110}
111
112
113int
[86327]114VBoxDbgBase::dbgcCreate(PCDBGCIO pIo, unsigned fFlags)
[31510]115{
[93468]116 PUVM pUVM = m_pUVM;
117 PCVMMR3VTABLE pVMM = m_pVMM;
118 if ( pUVM
119 && pVMM
120 && pVMM->pfnVMR3GetStateU(pUVM) < VMSTATE_DESTROYING)
121 return pVMM->pfnDBGCCreate(pUVM, pIo, fFlags);
[31510]122 return VERR_INVALID_HANDLE;
123}
124
125
126/*static*/ DECLCALLBACK(void)
[93468]127VBoxDbgBase::atStateChange(PUVM pUVM, PCVMMR3VTABLE pVMM, VMSTATE enmState, VMSTATE /*enmOldState*/, void *pvUser)
[31510]128{
[44393]129 VBoxDbgBase *pThis = (VBoxDbgBase *)pvUser; NOREF(pUVM);
[31510]130 switch (enmState)
131 {
132 case VMSTATE_TERMINATED:
[44340]133 {
[31510]134 /** @todo need to do some locking here? */
[93468]135 PUVM pUVM2 = ASMAtomicXchgPtrT(&pThis->m_pUVM, NULL, PUVM);
136 PCVMMR3VTABLE pVMM2 = ASMAtomicXchgPtrT(&pThis->m_pVMM, NULL, PCVMMR3VTABLE);
137 if (pUVM2 && pVMM2)
[44340]138 {
[44393]139 Assert(pUVM2 == pUVM);
[93468]140 Assert(pVMM2 == pVMM);
[31510]141 pThis->sigTerminated();
[93468]142 pVMM->pfnVMR3ReleaseUVM(pUVM2);
[44340]143 }
[31510]144 break;
[44340]145 }
[31510]146
147 case VMSTATE_DESTROYING:
148 pThis->sigDestroying();
149 break;
150
151 default:
152 break;
153 }
[93468]154 RT_NOREF(pVMM);
[31510]155}
156
157
158void
159VBoxDbgBase::sigDestroying()
160{
161}
162
163
164void
165VBoxDbgBase::sigTerminated()
166{
167}
168
169
170
171
172//
173//
174//
175// V B o x D b g B a s e W i n d o w
176// V B o x D b g B a s e W i n d o w
177// V B o x D b g B a s e W i n d o w
178//
179//
180//
181
182unsigned VBoxDbgBaseWindow::m_cxBorder = 0;
183unsigned VBoxDbgBaseWindow::m_cyBorder = 0;
184
185
[77412]186VBoxDbgBaseWindow::VBoxDbgBaseWindow(VBoxDbgGui *a_pDbgGui, QWidget *a_pParent, const char *a_pszTitle)
187 : QWidget(a_pParent, Qt::Window), VBoxDbgBase(a_pDbgGui), m_pszTitle(a_pszTitle), m_fPolished(false)
[101107]188 , m_x(INT_MAX), m_y(INT_MAX), m_cx(0), m_cy(0), m_cxMinHint(0), m_enmAttraction(VBoxDbgBaseWindow::kAttractionVmNone)
[31510]189{
[77412]190 /* Set the title, using the parent one as prefix when possible: */
191 if (!parent())
192 {
193 QString strMachineName = a_pDbgGui->getMachineName();
194 if (strMachineName.isEmpty())
195 setWindowTitle(QString("VBoxDbg - %1").arg(m_pszTitle));
196 else
197 setWindowTitle(QString("%1 - VBoxDbg - %2").arg(strMachineName).arg(m_pszTitle));
198 }
199 else
200 {
201 setWindowTitle(QString("%1 - %2").arg(parentWidget()->windowTitle()).arg(m_pszTitle));
202
203 /* Install an event filter so we can make adjustments when the parent title changes: */
204 parent()->installEventFilter(this);
205 }
[31510]206}
207
208
209VBoxDbgBaseWindow::~VBoxDbgBaseWindow()
210{
211
212}
213
214
215void
216VBoxDbgBaseWindow::vShow()
217{
218 show();
219 /** @todo this ain't working right. HELP! */
220 setWindowState(windowState() & ~Qt::WindowMinimized);
221 //activateWindow();
222 //setFocus();
223 vPolishSizeAndPos();
224}
225
226
227void
228VBoxDbgBaseWindow::vReposition(int a_x, int a_y, unsigned a_cx, unsigned a_cy, bool a_fResize)
229{
[101093]230 /* Don't modify if maximized.
231 We miss the desired size + position here, but never mind for now. */
232 if (!(windowState() & Qt::WindowMaximized))
[31510]233 {
[101093]234 if (a_fResize)
235 {
236 m_cx = a_cx;
237 m_cy = a_cy;
[31510]238
[101107]239 QSize const BorderSize = vGetBorderSize();
[101093]240 resize(a_cx - BorderSize.width(), a_cy - BorderSize.height());
241 }
242
243 m_x = a_x;
244 m_y = a_y;
245 move(a_x, a_y);
[31510]246 }
247}
248
249
[101107]250QSize
251VBoxDbgBaseWindow::vGetBorderSize()
252{
253 QSize BorderSize = frameSize() - size();
254
255#ifdef Q_WS_X11 /* (from the qt gui) */
256 /*
257 * On X11, there is no way to determine frame geometry (including WM
258 * decorations) before the widget is shown for the first time. Stupidly
259 * enumerate other top level widgets to find the thickest frame.
260 */
261 if (BorderSize == QSize(0, 0))
262 {
263 if (!m_cxBorder && !m_cyBorder) /* (only till we're successful) */
264 {
265 int cxExtra = 0;
266 int cyExtra = 0;
267
268 QWidgetList WidgetList = QApplication::topLevelWidgets();
269 for (QListIterator<QWidget *> it(WidgetList); it.hasNext(); )
270 {
271 QWidget *pCurWidget = it.next();
272 if (pCurWidget->isVisible())
273 {
274 int const cxFrame = pCurWidget->frameGeometry().width() - pCurWidget->width();
275 cxExtra = qMax(cxExtra, cxFrame);
276 int const cyFrame = pCurWidget->frameGeometry().height() - pCurWidget->height();
277 cyExtra = qMax(cyExtra, cyFrame);
278 if (cyExtra && cxExtra)
279 break;
280 }
281 }
282
283 if (cxExtra || cyExtra)
284 {
285 m_cxBorder = cxExtra;
286 m_cyBorder = cyExtra;
287 }
288 }
289 BorderSize.setWidth(m_cxBorder);
290 BorderSize.setHeight(m_cyBorder);
291 }
292#endif /* X11 */
293
294 return BorderSize;
295}
296
297
[31510]298bool
299VBoxDbgBaseWindow::event(QEvent *a_pEvt)
300{
301 bool fRc = QWidget::event(a_pEvt);
[85844]302 if ( a_pEvt->type() == QEvent::Paint
303 || a_pEvt->type() == QEvent::UpdateRequest
304 || a_pEvt->type() == QEvent::LayoutRequest) /** @todo Someone with Qt knowledge should figure out how to properly do this. */
305 vPolishSizeAndPos();
[31510]306 return fRc;
307}
308
309
[77412]310bool VBoxDbgBaseWindow::eventFilter(QObject *pWatched, QEvent *pEvent)
311{
312 /* We're only interested in title changes to the parent so we can amend our own title: */
313 if ( pWatched == parent()
314 && pEvent->type() == QEvent::WindowTitleChange)
315 setWindowTitle(QString("%1 - %2").arg(parentWidget()->windowTitle()).arg(m_pszTitle));
316
317 /* Forward to base-class: */
318 return QWidget::eventFilter(pWatched, pEvent);
319}
320
321
[31510]322void
323VBoxDbgBaseWindow::vPolishSizeAndPos()
324{
325 /* Ignore if already done or no size set. */
326 if ( m_fPolished
327 || (m_x == INT_MAX && m_y == INT_MAX))
328 return;
329
[101107]330 if (!m_fPolished && VBoxDbgBaseWindow::vGetBorderSize() != QSize(0,0))
[31510]331 m_fPolished = true;
332
333 vReposition(m_x, m_y, m_cx, m_cy, m_cx || m_cy);
334}
335
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use