Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / plasma / applets / systemtray / systemtraywidget.cpp
blob40ffb0d22379254e1c2d3ac028f6539b4ac40c47
1 /***************************************************************************
2 * systemtraywidget.h *
3 * *
4 * Copyright (C) 2007 Alexander Rodin <rodin.alexander@gmail.com> *
5 * Copyright (C) 2007 Jason Stubbs <jasonbstubbs@gmail.com> *
6 * *
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. *
11 * *
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. *
16 * *
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 ***************************************************************************/
23 // Own
24 #include "systemtraywidget.h"
25 #include "systemtraycontainer.h"
27 // Qt
28 #include <QX11Info>
30 // Xlib
31 #include <X11/Xlib.h>
33 namespace
35 enum
37 SYSTEM_TRAY_REQUEST_DOCK,
38 SYSTEM_TRAY_BEGIN_MESSAGE,
39 SYSTEM_TRAY_CANCEL_MESSAGE
43 SystemTrayWidget::SystemTrayWidget(QWidget *parent)
44 : QWidget(parent),
45 m_orientation(Qt::Horizontal),
46 m_nextRow(0),
47 m_nextColumn(0)
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);
55 init();
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;
71 xev.window = root;
72 xev.message_type = XInternAtom(display, "MANAGER", false);
73 xev.format = 32;
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 *)));
97 return true;
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) {
120 m_nextColumn++;
121 m_nextRow = 0;
123 m_mainLayout->addWidget(widget, m_nextRow, m_nextColumn);
124 m_nextRow++;
125 } else {
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) {
130 m_nextRow++;
131 m_nextColumn = 0;
133 m_mainLayout->addWidget(widget, m_nextRow, m_nextColumn);
134 m_nextColumn++;
138 void SystemTrayWidget::relayoutContainers(QObject *removeContainer)
140 // Pull all widgets from our container, skipping over the one that was just
141 // deleted
142 QList<QWidget *> remainingWidgets;
143 while (QLayoutItem* item = m_mainLayout->takeAt(0)) {
144 if (item->widget() && item->widget() != removeContainer) {
145 remainingWidgets.append(item->widget());
147 delete item;
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
161 m_nextRow = 0;
162 m_nextColumn = 0;
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"