VirtualBox

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

Last change on this file since 97405 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.7 KB
Line 
1/* $Id: VBoxDbgBase.cpp 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * VBox Debugger GUI - Base classes.
4 */
5
6/*
7 * Copyright (C) 2006-2022 Oracle and/or its affiliates.
8 *
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
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_DBGG
33#include <iprt/errcore.h>
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)
46 : m_pDbgGui(a_pDbgGui), m_pUVM(NULL), m_pVMM(NULL), m_hGUIThread(RTThreadNativeSelf())
47{
48 NOREF(m_pDbgGui); /* shut up warning. */
49
50 /*
51 * Register
52 */
53 m_pUVM = a_pDbgGui->getUvmHandle();
54 m_pVMM = a_pDbgGui->getVMMFunctionTable();
55 if (m_pUVM && m_pVMM)
56 {
57 m_pVMM->pfnVMR3RetainUVM(m_pUVM);
58
59 int rc = m_pVMM->pfnVMR3AtStateRegister(m_pUVM, atStateChange, this);
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? */
71 PUVM pUVM = ASMAtomicXchgPtrT(&m_pUVM, NULL, PUVM);
72 PCVMMR3VTABLE pVMM = ASMAtomicXchgPtrT(&m_pVMM, NULL, PCVMMR3VTABLE);
73 if (pUVM && pVMM)
74 {
75 int rc = pVMM->pfnVMR3AtStateDeregister(pUVM, atStateChange, this);
76 AssertRC(rc);
77
78 pVMM->pfnVMR3ReleaseUVM(pUVM);
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;
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);
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;
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);
109 return VERR_INVALID_HANDLE;
110}
111
112
113int
114VBoxDbgBase::dbgcCreate(PCDBGCIO pIo, unsigned fFlags)
115{
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);
122 return VERR_INVALID_HANDLE;
123}
124
125
126/*static*/ DECLCALLBACK(void)
127VBoxDbgBase::atStateChange(PUVM pUVM, PCVMMR3VTABLE pVMM, VMSTATE enmState, VMSTATE /*enmOldState*/, void *pvUser)
128{
129 VBoxDbgBase *pThis = (VBoxDbgBase *)pvUser; NOREF(pUVM);
130 switch (enmState)
131 {
132 case VMSTATE_TERMINATED:
133 {
134 /** @todo need to do some locking here? */
135 PUVM pUVM2 = ASMAtomicXchgPtrT(&pThis->m_pUVM, NULL, PUVM);
136 PCVMMR3VTABLE pVMM2 = ASMAtomicXchgPtrT(&pThis->m_pVMM, NULL, PCVMMR3VTABLE);
137 if (pUVM2 && pVMM2)
138 {
139 Assert(pUVM2 == pUVM);
140 Assert(pVMM2 == pVMM);
141 pThis->sigTerminated();
142 pVMM->pfnVMR3ReleaseUVM(pUVM2);
143 }
144 break;
145 }
146
147 case VMSTATE_DESTROYING:
148 pThis->sigDestroying();
149 break;
150
151 default:
152 break;
153 }
154 RT_NOREF(pVMM);
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
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)
188 , m_x(INT_MAX), m_y(INT_MAX), m_cx(0), m_cy(0)
189{
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 }
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{
230 if (a_fResize)
231 {
232 m_cx = a_cx;
233 m_cy = a_cy;
234
235 QSize BorderSize = frameSize() - size();
236 if (BorderSize == QSize(0,0))
237 BorderSize = vGuessBorderSizes();
238
239 resize(a_cx - BorderSize.width(), a_cy - BorderSize.height());
240 }
241
242 m_x = a_x;
243 m_y = a_y;
244 move(a_x, a_y);
245}
246
247
248bool
249VBoxDbgBaseWindow::event(QEvent *a_pEvt)
250{
251 bool fRc = QWidget::event(a_pEvt);
252 if ( a_pEvt->type() == QEvent::Paint
253 || a_pEvt->type() == QEvent::UpdateRequest
254 || a_pEvt->type() == QEvent::LayoutRequest) /** @todo Someone with Qt knowledge should figure out how to properly do this. */
255 vPolishSizeAndPos();
256 return fRc;
257}
258
259
260bool VBoxDbgBaseWindow::eventFilter(QObject *pWatched, QEvent *pEvent)
261{
262 /* We're only interested in title changes to the parent so we can amend our own title: */
263 if ( pWatched == parent()
264 && pEvent->type() == QEvent::WindowTitleChange)
265 setWindowTitle(QString("%1 - %2").arg(parentWidget()->windowTitle()).arg(m_pszTitle));
266
267 /* Forward to base-class: */
268 return QWidget::eventFilter(pWatched, pEvent);
269}
270
271
272void
273VBoxDbgBaseWindow::vPolishSizeAndPos()
274{
275 /* Ignore if already done or no size set. */
276 if ( m_fPolished
277 || (m_x == INT_MAX && m_y == INT_MAX))
278 return;
279
280 QSize BorderSize = frameSize() - size();
281 if (BorderSize != QSize(0,0))
282 m_fPolished = true;
283
284 vReposition(m_x, m_y, m_cx, m_cy, m_cx || m_cy);
285}
286
287
288QSize
289VBoxDbgBaseWindow::vGuessBorderSizes()
290{
291#ifdef Q_WS_X11 /* (from the qt gui) */
292 /*
293 * On X11, there is no way to determine frame geometry (including WM
294 * decorations) before the widget is shown for the first time. Stupidly
295 * enumerate other top level widgets to find the thickest frame.
296 */
297 if (!m_cxBorder && !m_cyBorder) /* (only till we're successful) */
298 {
299 int cxExtra = 0;
300 int cyExtra = 0;
301
302 QWidgetList WidgetList = QApplication::topLevelWidgets();
303 for (QListIterator<QWidget *> it(WidgetList); it.hasNext(); )
304 {
305 QWidget *pCurWidget = it.next();
306 if (pCurWidget->isVisible())
307 {
308 int const cxFrame = pCurWidget->frameGeometry().width() - pCurWidget->width();
309 cxExtra = qMax(cxExtra, cxFrame);
310 int const cyFrame = pCurWidget->frameGeometry().height() - pCurWidget->height();
311 cyExtra = qMax(cyExtra, cyFrame);
312 if (cyExtra && cxExtra)
313 break;
314 }
315 }
316
317 if (cxExtra || cyExtra)
318 {
319 m_cxBorder = cxExtra;
320 m_cyBorder = cyExtra;
321 }
322 }
323#endif /* X11 */
324 return QSize(m_cxBorder, m_cyBorder);
325}
326
Note: See TracBrowser for help on using the repository browser.

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