1 /***************************************************************************
4 * Copyright (C) 2007 Alexander Rodin <rodin.alexander@gmail.com> *
5 * Copyright (C) 2007 Jason Stubbs <jasonbstubbs@gmail.com> *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
21 ***************************************************************************/
24 #include "systemtraywidget.h"
25 #include "systemtraycontainer.h"
37 SYSTEM_TRAY_REQUEST_DOCK
,
38 SYSTEM_TRAY_BEGIN_MESSAGE
,
39 SYSTEM_TRAY_CANCEL_MESSAGE
43 SystemTrayWidget::SystemTrayWidget(QWidget
*parent
)
45 m_orientation(Qt::Horizontal
),
49 m_mainLayout
= new QGridLayout(this);
51 // Override spacing set by the current style
52 m_mainLayout
->setContentsMargins(0, 0, 0, 0);
53 m_mainLayout
->setSpacing(4);
58 void SystemTrayWidget::init()
60 Display
*display
= QX11Info::display();
62 m_selectionAtom
= XInternAtom(display
, "_NET_SYSTEM_TRAY_S" + QByteArray::number(QX11Info::appScreen()), false);
63 m_opcodeAtom
= XInternAtom(display
, "_NET_SYSTEM_TRAY_OPCODE", false);
64 XSetSelectionOwner(display
, m_selectionAtom
, winId(), CurrentTime
);
66 if (XGetSelectionOwner(display
, m_selectionAtom
) == winId()) {
67 WId root
= QX11Info::appRootWindow();
68 XClientMessageEvent xev
;
70 xev
.type
= ClientMessage
;
72 xev
.message_type
= XInternAtom(display
, "MANAGER", false);
74 xev
.data
.l
[0] = CurrentTime
;
75 xev
.data
.l
[1] = m_selectionAtom
;
76 xev
.data
.l
[2] = winId();
77 xev
.data
.l
[3] = 0; // manager specific data
78 xev
.data
.l
[4] = 0; // manager specific data
80 XSendEvent(display
, root
, false, StructureNotifyMask
, (XEvent
*)&xev
);
84 bool SystemTrayWidget::x11Event(XEvent
*event
)
86 if (event
->type
== ClientMessage
) {
87 if (event
->xclient
.message_type
== m_opcodeAtom
&&
88 event
->xclient
.data
.l
[1] == SYSTEM_TRAY_REQUEST_DOCK
) {
90 // Set up a SystemTrayContainer for the client
91 SystemTrayContainer
*container
= new SystemTrayContainer((WId
)event
->xclient
.data
.l
[2], this);
92 addWidgetToLayout(container
);
94 connect(container
, SIGNAL(clientIsEmbedded()), this, SIGNAL(sizeShouldChange()));
95 connect(container
, SIGNAL(destroyed(QObject
*)), this, SLOT(relayoutContainers(QObject
*)));
100 return QWidget::x11Event(event
);
103 void SystemTrayWidget::setOrientation(Qt::Orientation orientation
)
105 if (orientation
!= m_orientation
) {
106 m_orientation
= orientation
;
107 relayoutContainers();
111 void SystemTrayWidget::addWidgetToLayout(QWidget
*widget
)
113 // Figure out where it should go and add it to our layout
115 if (m_orientation
== Qt::Horizontal
) {
116 // Add down then across when horizontal
117 if (m_nextRow
== m_mainLayout
->rowCount()
118 && m_mainLayout
->minimumSize().height() + m_mainLayout
->spacing()
119 + widget
->minimumHeight() > maximumHeight() - 2 * MARGIN
) {
123 m_mainLayout
->addWidget(widget
, m_nextRow
, m_nextColumn
);
126 // Add across then down when vertical
127 if (m_nextColumn
== m_mainLayout
->columnCount()
128 && m_mainLayout
->minimumSize().width() + m_mainLayout
->spacing()
129 + widget
->minimumWidth() > maximumWidth() - 2 * MARGIN
) {
133 m_mainLayout
->addWidget(widget
, m_nextRow
, m_nextColumn
);
138 void SystemTrayWidget::relayoutContainers(QObject
*removeContainer
)
140 // Pull all widgets from our container, skipping over the one that was just
142 QList
<QWidget
*> remainingWidgets
;
143 while (QLayoutItem
* item
= m_mainLayout
->takeAt(0)) {
144 if (item
->widget() && item
->widget() != removeContainer
) {
145 remainingWidgets
.append(item
->widget());
150 // Reset the widths and heights in our layout to 0 so that the removed
151 // widget's space isn't kept
152 // (Why doesn't QGridLayout do this automatically?)
153 for (int row
= 0; row
< m_mainLayout
->rowCount(); row
++) {
154 m_mainLayout
->setRowMinimumHeight(row
, 0);
156 for (int column
= 0; column
< m_mainLayout
->columnCount(); column
++) {
157 m_mainLayout
->setColumnMinimumWidth(column
, 0);
160 // Re-add remaining widgets
163 foreach (QWidget
*widget
, remainingWidgets
) {
164 addWidgetToLayout(widget
);
167 // Force a layout so that minimumSizeHint() returns the correct value and
168 // signal that our size should change
169 layout()->activate();
170 emit
sizeShouldChange();
173 #include "systemtraywidget.moc"