VirtualBox

source: vbox/trunk/src/VBox/Debugger/VBoxDbgGui.cpp@ 101107

Last change on this file since 101107 was 101107, checked in by vboxsync, 15 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.3 KB
Line 
1/* $Id: VBoxDbgGui.cpp 101107 2023-09-13 14:01:58Z vboxsync $ */
2/** @file
3 * VBox Debugger GUI - The Manager.
4 */
5
6/*
7 * Copyright (C) 2006-2023 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#define VBOX_COM_NO_ATL
34#include <VBox/com/defs.h>
35#include <iprt/errcore.h>
36
37#include "VBoxDbgGui.h"
38#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
39# include <QScreen>
40#else
41# include <QDesktopWidget>
42#endif
43#include <QApplication>
44
45
46
47VBoxDbgGui::VBoxDbgGui() :
48 m_pDbgStats(NULL), m_pDbgConsole(NULL), m_pSession(NULL), m_pConsole(NULL),
49 m_pMachineDebugger(NULL), m_pMachine(NULL), m_pUVM(NULL), m_pVMM(NULL),
50 m_pParent(NULL), m_pMenu(NULL),
51 m_x(0), m_y(0), m_cx(0), m_cy(0), m_xDesktop(0), m_yDesktop(0), m_cxDesktop(0), m_cyDesktop(0)
52{
53
54}
55
56
57int VBoxDbgGui::init(PUVM pUVM, PCVMMR3VTABLE pVMM)
58{
59 /*
60 * Set the VM handle and update the desktop size.
61 */
62 m_pUVM = pUVM; /* Note! This eats the incoming reference to the handle! */
63 m_pVMM = pVMM;
64 updateDesktopSize();
65
66 return VINF_SUCCESS;
67}
68
69
70int VBoxDbgGui::init(ISession *pSession)
71{
72 int rc = VERR_GENERAL_FAILURE;
73
74 /*
75 * Query the VirtualBox interfaces.
76 */
77 m_pSession = pSession;
78 m_pSession->AddRef();
79
80 HRESULT hrc = m_pSession->COMGETTER(Machine)(&m_pMachine);
81 if (SUCCEEDED(hrc))
82 {
83 hrc = m_pSession->COMGETTER(Console)(&m_pConsole);
84 if (SUCCEEDED(hrc))
85 {
86 hrc = m_pConsole->COMGETTER(Debugger)(&m_pMachineDebugger);
87 if (SUCCEEDED(hrc))
88 {
89 /*
90 * Get the VM handle.
91 */
92 LONG64 llUVM = 0;
93 LONG64 llVMMFunctionTable = 0;
94 hrc = m_pMachineDebugger->GetUVMAndVMMFunctionTable((int64_t)VMMR3VTABLE_MAGIC_VERSION,
95 &llVMMFunctionTable, &llUVM);
96 if (SUCCEEDED(hrc))
97 {
98 PUVM pUVM = (PUVM)(intptr_t)llUVM;
99 PCVMMR3VTABLE pVMM = (PCVMMR3VTABLE)(intptr_t)llVMMFunctionTable;
100 rc = init(pUVM, pVMM);
101 if (RT_SUCCESS(rc))
102 return rc;
103
104 pVMM->pfnVMR3ReleaseUVM(pUVM);
105 }
106
107 /* damn, failure! */
108 m_pMachineDebugger->Release();
109 m_pMachineDebugger = NULL;
110 }
111 m_pConsole->Release();
112 m_pConsole = NULL;
113 }
114 m_pMachine->Release();
115 m_pMachine = NULL;
116 }
117
118 return rc;
119}
120
121
122VBoxDbgGui::~VBoxDbgGui()
123{
124 if (m_pDbgStats)
125 {
126 delete m_pDbgStats;
127 m_pDbgStats = NULL;
128 }
129
130 if (m_pDbgConsole)
131 {
132 delete m_pDbgConsole;
133 m_pDbgConsole = NULL;
134 }
135
136 if (m_pMachineDebugger)
137 {
138 m_pMachineDebugger->Release();
139 m_pMachineDebugger = NULL;
140 }
141
142 if (m_pConsole)
143 {
144 m_pConsole->Release();
145 m_pConsole = NULL;
146 }
147
148 if (m_pMachine)
149 {
150 m_pMachine->Release();
151 m_pMachine = NULL;
152 }
153
154 if (m_pSession)
155 {
156 m_pSession->Release();
157 m_pSession = NULL;
158 }
159
160 if (m_pUVM)
161 {
162 Assert(m_pVMM);
163 m_pVMM->pfnVMR3ReleaseUVM(m_pUVM);
164 m_pUVM = NULL;
165 m_pVMM = NULL;
166 }
167}
168
169void
170VBoxDbgGui::setParent(QWidget *pParent)
171{
172 m_pParent = pParent;
173}
174
175
176void
177VBoxDbgGui::setMenu(QMenu *pMenu)
178{
179 m_pMenu = pMenu;
180}
181
182
183int
184VBoxDbgGui::showStatistics(const char *pszFilter, const char *pszExpand)
185{
186 if (!m_pDbgStats)
187 {
188 m_pDbgStats = new VBoxDbgStats(this,
189 pszFilter && *pszFilter ? pszFilter : "*",
190 pszExpand && *pszExpand ? pszExpand : NULL,
191 2, m_pParent);
192 connect(m_pDbgStats, SIGNAL(destroyed(QObject *)), this, SLOT(notifyChildDestroyed(QObject *)));
193 repositionWindowInitial(m_pDbgStats, "DbgStats", VBoxDbgBaseWindow::kAttractionVmRight);
194 }
195
196 m_pDbgStats->vShow();
197 return VINF_SUCCESS;
198}
199
200
201int
202VBoxDbgGui::showConsole()
203{
204 if (!m_pDbgConsole)
205 {
206 IVirtualBox *pVirtualBox = NULL;
207 m_pMachine->COMGETTER(Parent)(&pVirtualBox);
208 m_pDbgConsole = new VBoxDbgConsole(this, m_pParent, pVirtualBox);
209 connect(m_pDbgConsole, SIGNAL(destroyed(QObject *)), this, SLOT(notifyChildDestroyed(QObject *)));
210 repositionWindowInitial(m_pDbgConsole, "DbgConsole", VBoxDbgBaseWindow::kAttractionVmBottom);
211 }
212
213 m_pDbgConsole->vShow();
214 return VINF_SUCCESS;
215}
216
217
218void
219VBoxDbgGui::updateDesktopSize()
220{
221 QRect Rct(0, 0, 1600, 1200);
222#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
223 QScreen *pScreen = QApplication::screenAt(QPoint(m_x, m_y));
224 if (pScreen)
225 Rct = pScreen->availableGeometry();
226#else
227 QDesktopWidget *pDesktop = QApplication::desktop();
228 if (pDesktop)
229 Rct = pDesktop->availableGeometry(QPoint(m_x, m_y));
230#endif
231 m_xDesktop = Rct.x();
232 m_yDesktop = Rct.y();
233 m_cxDesktop = Rct.width();
234 m_cyDesktop = Rct.height();
235}
236
237
238void
239VBoxDbgGui::repositionWindow(VBoxDbgBaseWindow *a_pWindow, bool a_fResize /*=true*/)
240{
241 if (a_pWindow)
242 {
243 VBoxDbgBaseWindow::VBoxDbgAttractionType const enmAttraction = a_pWindow->vGetWindowAttraction();
244 QSize const BorderSize = a_pWindow->vGetBorderSize();
245 unsigned const cxMinHint = RT_MAX(32, a_pWindow->vGetMinWidthHint()) + BorderSize.width();
246 int x, y;
247 unsigned cx, cy;
248 /** @todo take the x,y screen into account rather than the one of the VM
249 * window. also generally consider adjacent screens. */
250 switch (enmAttraction)
251 {
252 case VBoxDbgBaseWindow::kAttractionVmRight:
253 x = m_x + m_cx;
254 y = m_y;
255 cx = m_cxDesktop - m_cx - m_x + m_xDesktop;
256 if (cx > m_cxDesktop || cx < cxMinHint)
257 cx = cxMinHint;
258 cy = m_cyDesktop - m_y + m_yDesktop;
259 break;
260
261 case VBoxDbgBaseWindow::kAttractionVmBottom:
262 x = m_x;
263 y = m_y + m_cy;
264 cx = m_cx;
265 if (cx < cxMinHint)
266 {
267 if (cxMinHint - cx <= unsigned(m_x - m_xDesktop)) /* move it to the left if we have sufficient room. */
268 x -= cxMinHint - cx;
269 else
270 x = m_xDesktop;
271 cx = cxMinHint;
272 }
273 cy = m_cyDesktop - m_cy - m_y + m_yDesktop;
274 break;
275
276 /** @todo implement the other placements when they become selectable. */
277
278 default:
279 return;
280 }
281
282 a_pWindow->vReposition(x, y, cx, cy, a_fResize);
283 }
284}
285
286
287void
288VBoxDbgGui::repositionWindowInitial(VBoxDbgBaseWindow *a_pWindow, const char *a_pszSettings,
289 VBoxDbgBaseWindow::VBoxDbgAttractionType a_enmDefaultAttraction)
290{
291 a_pWindow->vSetWindowAttraction(a_enmDefaultAttraction);
292
293 /** @todo save/restore the attachment type. */
294 RT_NOREF(a_pszSettings);
295
296 repositionWindow(a_pWindow, true /*fResize*/);
297}
298
299
300void
301VBoxDbgGui::adjustRelativePos(int x, int y, unsigned cx, unsigned cy)
302{
303 /* Disregard a width less than 640 since it will mess up the console,
304 but only if previous width was already initialized. */
305 if (cx < 640 && m_cx > 0)
306 cx = m_cx;
307
308 const bool fResize = cx != m_cx || cy != m_cy;
309 const bool fMoved = x != m_x || y != m_y;
310
311 m_x = x;
312 m_y = y;
313 m_cx = cx;
314 m_cy = cy;
315
316 if (fMoved)
317 updateDesktopSize();
318 repositionWindow(m_pDbgConsole, fResize);
319 repositionWindow(m_pDbgStats, fResize);
320}
321
322
323QString
324VBoxDbgGui::getMachineName() const
325{
326 QString strName;
327 AssertReturn(m_pMachine, strName);
328 BSTR bstr;
329 HRESULT hrc = m_pMachine->COMGETTER(Name)(&bstr);
330 if (SUCCEEDED(hrc))
331 {
332#ifndef VBOX_IS_QT6_OR_LATER
333 strName = QString::fromUtf16((const ushort *)bstr);
334#else
335 strName = QString::fromUtf16((const char16_t *)bstr);
336#endif
337 SysFreeString(bstr);
338 }
339 return strName;
340}
341
342
343void
344VBoxDbgGui::notifyChildDestroyed(QObject *pObj)
345{
346 if (m_pDbgStats == pObj)
347 m_pDbgStats = NULL;
348 else if (m_pDbgConsole == pObj)
349 m_pDbgConsole = NULL;
350}
351
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