[PATCH] hide VBox VM from desktop taskbar

Discussions related to using the OSE version of VirtualBox.
Post Reply
Technologov
Volunteer
Posts: 3342
Joined: 10. May 2007, 16:59
Location: Israel

[PATCH] hide VBox VM from desktop taskbar

Post by Technologov »

Hi All !

The basic idea, is that at any given time I may have some VMs running in background / Server mode on my workstation, without consuming precious desktop taskbar space, and wanna bring them back into desktop mode later.

While tinkering around with code, I came across interesting X11 feature - Map/Unmap, and immediately recalled -- Wish #6798.
I wrote a patch to exploit this feature on X11 / Linux hosts.

MIT licensed. (as always) :-)
----------------------
update: Klaus, VirtualBox developer, realized the need, but disagrees with the approach. He thinks it needs to be done deeply in the main API, instead of GUI, so patch was rejected.

Besides, it does not work with multi-monitor VMs.
I decided to put it here, in the hope people will find it useful.

UPDATE: Found sister project: RBTray
http://rbtray.sourceforge.net/

--
-Alexey Eromenko "Technologov"
Attachments
vbox-gui-X11-window-hide.zip
PATCH - should be applied vs 4.1.0 code
(3.13 KiB) Downloaded 142 times
Technologov
Volunteer
Posts: 3342
Joined: 10. May 2007, 16:59
Location: Israel

Re: [PATCH] hide VBox VM from desktop taskbar

Post by Technologov »

+ Windows hosts support:

Code: Select all

 bool VBoxGlobal::hideWindow (WId aWId)
...
 #if defined (Q_WS_WIN32)

+result &= !!ShowWindow (aWId, SW_HIDE);
... multi-monitor VMs don't work this way...
Which is the last hint that the approach you're using is a hack which won't do the job in the general case.

The proper solution would be to have a generic window manipulation method which at the same time eliminates the need for having any "window id" information in the API. This was always considered a hack, but we didn't have time to clean it up. Adding more hacks won't be accepted.

One way would be a IDisplay::manipulateWindow(enum WindowOp) method - which can hide/unhide/bring to front/detach/attach/... operations. The association with IDisplay means that it'd always work on all screens associated with a multi-monitor VM. If there's need to make this per screen it simply needs to be moved to IFramebuffer.

This would at the same time allow putting the totally misplaced IMachine::showConsoleWindow method in the context where it should be... it always was performed by the VM process.

Klaus
Perryg
Site Moderator
Posts: 34369
Joined: 6. Sep 2008, 22:55
Primary OS: Linux other
VBox Version: OSE self-compiled
Guest OSses: *NIX

Re: [PATCH] hide VBox VM from desktop taskbar

Post by Perryg »

In Linux you can already start the VM headless without leaving a terminal window open. (nohup)
So Is this for the GUI manager? and does it enable/disable while running?
Technologov
Volunteer
Posts: 3342
Joined: 10. May 2007, 16:59
Location: Israel

Re: [PATCH] hide VBox VM from desktop taskbar

Post by Technologov »

VBoxheadless is *far* from comfortable. Not user-friendly.

>So Is this for the GUI manager? and does it enable/disable while running?
Yes, my way is super-user-friendly and very fast. Just right-lick on VM hide/show buttons.
Perryg
Site Moderator
Posts: 34369
Joined: 6. Sep 2008, 22:55
Primary OS: Linux other
VBox Version: OSE self-compiled
Guest OSses: *NIX

Re: [PATCH] hide VBox VM from desktop taskbar

Post by Perryg »

You might want to run a newer Diff/patch. This one fails on latest from SVN. Maybe 4.1.6 instead of 4.1.0 Beta.??
Here is the reject file.

Code: Select all

--- VBoxGlobal.h	2011-07-15 16:49:08.000000000 -0400
+++ VBoxGlobal.h	2011-07-15 18:38:21.000000000 -0400
@@ -157,6 +157,7 @@
 
     bool processArgs();
 
+    bool hideMachineWindow(CMachine &machine);
     bool switchToMachine(CMachine &machine);
     bool launchMachine(CMachine &machine);
 
@@ -676,6 +677,7 @@
     static QString systemLanguageId();
 
     static bool activateWindow (WId aWId, bool aSwitchDesktop = true);
+    static bool hideWindow (WId aWId);
 
     static QString removeAccelMark (const QString &aText);
 
--- VBoxSelectorWnd.cpp	2011-07-15 16:49:08.000000000 -0400
+++ VBoxSelectorWnd.cpp	2011-07-15 18:25:36.000000000 -0400
@@ -154,6 +154,11 @@
         QSize(32, 32), QSize(16, 16),
         ":/vm_start_32px.png", ":/start_16px.png",
         ":/vm_start_disabled_32px.png", ":/start_dis_16px.png"));
+    mVmHideAction = new QAction(this);
+    mVmHideAction->setIcon(UIIconPool::iconSetFull(
+        QSize(32, 32), QSize(16, 16),
+        ":/vm_discard_32px.png", ":/discard_16px.png",
+        ":/vm_discard_disabled_32px.png", ":/discard_dis_16px.png"));
     mVmDiscardAction = new QAction(this);
     mVmDiscardAction->setIcon(UIIconPool::iconSetFull(
         QSize(32, 32), QSize(16, 16),
@@ -295,6 +300,7 @@
     mVMMenu->addAction(mVmDeleteAction);
     mVMMenu->addSeparator();
     mVMMenu->addAction(mVmStartAction);
+    mVMMenu->addAction(mVmHideAction);
     mVMMenu->addAction(mVmDiscardAction);
     mVMMenu->addAction(mVmPauseAction);
     mVMMenu->addSeparator();
@@ -314,6 +320,7 @@
     mVMCtxtMenu->addAction(mVmDeleteAction);
     mVMCtxtMenu->addSeparator();
     mVMCtxtMenu->addAction(mVmStartAction);
+    mVMCtxtMenu->addAction(mVmHideAction);
     mVMCtxtMenu->addAction(mVmDiscardAction);
     mVMCtxtMenu->addAction(mVmPauseAction);
     mVMCtxtMenu->addSeparator();
@@ -443,6 +450,7 @@
     connect(mVmCloneAction, SIGNAL(triggered()), this, SLOT(vmClone()));
     connect(mVmDeleteAction, SIGNAL(triggered()), this, SLOT(vmDelete()));
     connect(mVmStartAction, SIGNAL(triggered()), this, SLOT(vmStart()));
+    connect(mVmHideAction, SIGNAL(triggered()), this, SLOT(vmHide()));
     connect(mVmDiscardAction, SIGNAL(triggered()), this, SLOT(vmDiscard()));
     connect(mVmPauseAction, SIGNAL(toggled(bool)), this, SLOT(vmPause(bool)));
     connect(mVmRefreshAction, SIGNAL(triggered()), this, SLOT(vmRefresh()));
@@ -807,6 +815,27 @@
     vboxGlobal().launchMachine(machine);
 }
 
+void VBoxSelectorWnd::vmHide(const QString &aUuid /* = QString::null */)
+{
+    QUuid uuid(aUuid);
+    UIVMItem *item = uuid.isNull() ? mVMListView->selectedItem() :
+                       mVMModel->itemById(aUuid);
+
+    AssertMsgReturnVoid(item, ("Item must be always selected here"));
+
+    /* Are we called from the mVMListView's activated() signal? */
+    if (uuid.isNull())
+    {
+        /* We always get here when mVMListView emits the activated() signal,
+         * so we must explicitly check if the action is enabled or not. */
+        if (!mVmHideAction->isEnabled())
+            return;
+    }
+
+    CMachine machine = item->machine();
+    vboxGlobal().hideMachineWindow(machine);
+}
+
 void VBoxSelectorWnd::vmDiscard(const QString &aUuid /* = QString::null */)
 {
     UIVMItem *item = aUuid.isNull() ? mVMListView->selectedItem() :
@@ -1229,6 +1258,10 @@
 
     /* Note: mVmStartAction text is set up in vmListViewCurrentChanged() */
 
+    mVmHideAction->setText(tr("&Hide"));
+    mVmHideAction->setStatusTip(
+        tr("Hide the window of the virtual machine"));
+    
     mVmDiscardAction->setIconText(tr("Discard"));
     mVmDiscardAction->setText(tr("D&iscard Saved State"));
     mVmDiscardAction->setShortcut(gSS->keySequence(UISelectorShortcuts::DiscardVMShortcut));
@@ -1362,6 +1395,7 @@
                 tr("Start the selected virtual machine"));
 
             mVmStartAction->setEnabled(!running);
+            mVmHideAction->setEnabled(false);
         }
         else
         {
@@ -1378,7 +1412,8 @@
 #endif /* QT_MAC_USE_COCOA */
             mVmStartAction->setStatusTip(
                 tr("Switch to the window of the selected virtual machine"));
-
+                
+            mVmHideAction->setEnabled(item->canSwitchTo());
             mVmStartAction->setEnabled(item->canSwitchTo());
         }
 
@@ -1463,6 +1498,7 @@
         mVmConfigAction->setEnabled(false);
         mVmCloneAction->setEnabled(false);
         mVmDeleteAction->setEnabled(item != NULL);
+        mVmHideAction->setEnabled(false);
         mVmDiscardAction->setEnabled(false);
         mVmPauseAction->setEnabled(false);
 
--- VBoxSelectorWnd.h	2011-07-15 16:49:08.000000000 -0400
+++ VBoxSelectorWnd.h	2011-07-15 18:51:08.000000000 -0400
@@ -73,6 +73,7 @@
     void vmClone(const QString & = QString::null);
     void vmDelete(const QString & = QString::null);
     void vmStart(const QString & = QString::null);
+    void vmHide(const QString & = QString::null);
     void vmDiscard(const QString & = QString::null);
     void vmPause(bool, const QString & = QString::null);
     void vmRefresh(const QString & = QString::null);
@@ -98,6 +99,7 @@
     const QAction *vmCloneAction() const { return mVmCloneAction; }
     const QAction *vmDeleteAction() const { return mVmDeleteAction; }
     const QAction *vmStartAction() const { return mVmStartAction; }
+    const QAction *vmHideAction() const { return mVmHideAction; }
     const QAction *vmDiscardAction() const { return mVmDiscardAction; }
     const QAction *vmPauseAction() const { return mVmPauseAction; }
     const QAction *vmRefreshAction() const { return mVmRefreshAction; }
@@ -169,6 +171,7 @@
     QAction *mVmCloneAction;
     QAction *mVmDeleteAction;
     QAction *mVmStartAction;
+    QAction *mVmHideAction;
     QAction *mVmDiscardAction;
     QAction *mVmPauseAction;
     QAction *mVmRefreshAction;
--- VBoxTrayIcon.cpp	2011-07-15 16:49:08.000000000 -0400
+++ VBoxTrayIcon.cpp	2011-07-15 18:19:39.000000000 -0400
@@ -54,6 +54,10 @@
     Assert (mVmStartAction);
     mVmStartAction->setIcon (mParent->vmStartAction()->icon());
 
+    mVmHideAction = new QAction (this);
+    Assert (mVmHideAction);
+    mVmHideAction->setIcon (mParent->vmHideAction()->icon());
+
     mVmDiscardAction = new QAction (this);
     Assert (mVmDiscardAction);
     mVmDiscardAction->setIcon (mParent->vmDiscardAction()->icon());
@@ -116,6 +120,9 @@
     mVmPauseAction->setText (mParent->vmPauseAction()->text());
     mVmPauseAction->setStatusTip (mParent->vmPauseAction()->statusTip());
 
+    mVmHideAction->setText (mParent->vmHideAction()->text());
+    mVmHideAction->setStatusTip (mParent->vmHideAction()->statusTip());
+    
     mVmDiscardAction->setText (mParent->vmDiscardAction()->text());
     mVmDiscardAction->setStatusTip (mParent->vmDiscardAction()->statusTip());
 
@@ -141,6 +148,7 @@
 
     mVmConfigAction->setData (vID);
     mVmDeleteAction->setData (vID);
+    mVmHideAction->setData (vID);
     mVmDiscardAction->setData (vID);
     mVmStartAction->setData (vID);
     mVmPauseAction->setData (vID);
@@ -217,6 +225,7 @@
         /* Disconnect old slot which maybe was connected from another selected sub menu. */
         disconnect (mVmConfigAction, SIGNAL (triggered()), this, SLOT (vmSettings()));
         disconnect (mVmDeleteAction, SIGNAL (triggered()), this, SLOT (vmDelete()));
+        disconnect (mVmHideAction, SIGNAL (triggered()), this, SLOT (vmHide()));
         disconnect (mVmDiscardAction, SIGNAL (triggered()), this, SLOT (vmDiscard()));
         disconnect (mVmStartAction, SIGNAL (triggered()), this, SLOT (vmStart()));
         disconnect (mVmPauseAction, SIGNAL (toggled (bool)), this, SLOT (vmPause (bool)));
@@ -225,6 +234,7 @@
         /* Connect new sub menu with slots. */
         connect (mVmConfigAction, SIGNAL (triggered()), this, SLOT (vmSettings()));
         connect (mVmDeleteAction, SIGNAL (triggered()), this, SLOT (vmDelete()));
+        connect (mVmHideAction, SIGNAL (triggered()), this, SLOT (vmHide()));
         connect (mVmDiscardAction, SIGNAL (triggered()), this, SLOT (vmDiscard()));
         connect (mVmStartAction, SIGNAL (triggered()), this, SLOT (vmStart()));
         connect (mVmPauseAction, SIGNAL (toggled (bool)), this, SLOT (vmPause (bool)));
--- VBoxTrayIcon.h	2011-07-15 16:49:08.000000000 -0400
+++ VBoxTrayIcon.h	2011-07-15 18:15:59.000000000 -0400
@@ -81,6 +81,7 @@
     QAction *mVmConfigAction;
     QAction *mVmDeleteAction;
     QAction *mVmStartAction;
+    QAction *mVmHideAction;
     QAction *mVmDiscardAction;
     QAction *mVmPauseAction;
     QAction *mVmRefreshAction;
Oh and the user friendly part IMHO I disagree with you. I have a start/stop script that I call from a launcher. Easy and it does not require a patch to be run on every update. But that is just my opinion. Now Windows would need this for sure, so maybe someone can figure out how to do that.
sej7278
Volunteer
Posts: 1003
Joined: 5. Sep 2008, 14:40
Primary OS: Debian other
VBox Version: PUEL
Guest OSses: Solaris, Linux, Windows, OS/2, MacOSX, FreeBSD
Contact:

Re: [PATCH] hide VBox VM from desktop taskbar

Post by sej7278 »

one function i've always though virtualbox lacks (and vmware had, dunno if it still does) is the ability to close the window and still keep the vm running. i just picked up on the attach/detach in your quote there.

i mean the actual vm window, not the vbox manager window. essentially switching from gui to headless mode, then you go back to the manager window to switch it back to gui mode if you want.

i would also find that handy for when you want a console window open to see boot messages and don't want to setup a serial pipe, but then once booted you only want to ssh in. as far as i know vboxheadless doesn't provide console messages. that's something that openvz (and i think kvm/xen) does nicely.

but back to your issue - in gnome3 there isn't a desktop taskbar as such, for instance i now have 3 vm's and the manager window open and only see one icon for the active window.
Technologov
Volunteer
Posts: 3342
Joined: 10. May 2007, 16:59
Location: Israel

Re: [PATCH] hide VBox VM from desktop taskbar

Post by Technologov »

Sej: my patch does address your issue.

It hides VM *completely* from desktop. To show it again, you need to use VBox Manager GUI, and double-click on VM.
Post Reply