• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Applets

systemtraywidget.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   systemtraywidget.h                                                    *
00003  *                                                                         *
00004  *   Copyright (C) 2007 Alexander Rodin <rodin.alexander@gmail.com>        *
00005  *   Copyright (C) 2007 Jason Stubbs <jasonbstubbs@gmail.com>              *
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
00021  ***************************************************************************/
00022 
00023 // Own
00024 #include "systemtraywidget.h"
00025 #include "systemtraycontainer.h"
00026 
00027 // Qt
00028 #include <QX11Info>
00029 
00030 // Xlib
00031 #include <X11/Xlib.h>
00032 
00033 namespace
00034 {
00035 enum
00036 {
00037     SYSTEM_TRAY_REQUEST_DOCK,
00038     SYSTEM_TRAY_BEGIN_MESSAGE,
00039     SYSTEM_TRAY_CANCEL_MESSAGE
00040 };
00041 }
00042 
00043 SystemTrayWidget::SystemTrayWidget(QWidget *parent)
00044     : QWidget(parent),
00045     m_orientation(Qt::Horizontal),
00046     m_maxCount(0),
00047     m_nextRow(0),
00048     m_nextColumn(0)
00049 {
00050     m_mainLayout = new QGridLayout(this);
00051 
00052     // Override spacing set by the current style
00053     m_mainLayout->setContentsMargins(0, 0, 0, 0);
00054     m_mainLayout->setSpacing(4);
00055 }
00056 
00057 void SystemTrayWidget::init()
00058 {
00059     Display *display = QX11Info::display();
00060 
00061     m_selectionAtom = XInternAtom(display, "_NET_SYSTEM_TRAY_S" + QByteArray::number(QX11Info::appScreen()), false);
00062     m_opcodeAtom = XInternAtom(display, "_NET_SYSTEM_TRAY_OPCODE", false);
00063     XSetSelectionOwner(display, m_selectionAtom, winId(), CurrentTime);
00064 
00065     if (XGetSelectionOwner(display, m_selectionAtom) == winId()) {
00066         WId root = QX11Info::appRootWindow();
00067         XClientMessageEvent xev;
00068 
00069         xev.type = ClientMessage;
00070         xev.window = root;
00071         xev.message_type = XInternAtom(display, "MANAGER", false);
00072         xev.format = 32;
00073         xev.data.l[0] = CurrentTime;
00074         xev.data.l[1] = m_selectionAtom;
00075         xev.data.l[2] = winId();
00076         xev.data.l[3] = 0;  // manager specific data
00077         xev.data.l[4] = 0;  // manager specific data
00078 
00079         XSendEvent(display, root, false, StructureNotifyMask, (XEvent*)&xev);
00080     }
00081 }
00082 
00083 bool SystemTrayWidget::x11Event(XEvent *event)
00084 {
00085     if (event->type == ClientMessage) {
00086         if (event->xclient.message_type == m_opcodeAtom &&
00087             event->xclient.data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
00088             const WId systemTrayClientId = (WId)event->xclient.data.l[2];
00089             if (systemTrayClientId == 0) {
00090                 return true;
00091             }
00092             foreach(SystemTrayContainer *c, findChildren<SystemTrayContainer*>()) {
00093                 if (c->clientWinId() == systemTrayClientId) {
00094                     return true;
00095                 }
00096             }
00097 
00098             // Set up a SystemTrayContainer for the client
00099             SystemTrayContainer *container = new SystemTrayContainer(this);
00100             connect(container, SIGNAL(destroyed(QObject *)), this, SLOT(relayoutContainers(QObject *)));
00101             connect(container, SIGNAL(clientIsEmbedded()), this, SIGNAL(sizeShouldChange()));
00102             addWidgetToLayout(container);
00103 
00104             container->embedSystemTrayClient(systemTrayClientId);
00105             return true;
00106         }
00107     }
00108     return QWidget::x11Event(event);
00109 }
00110 
00111 void SystemTrayWidget::setOrientation(Qt::Orientation orientation)
00112 {
00113     if (orientation != m_orientation) {
00114         m_orientation = orientation;
00115         relayoutContainers();
00116     }
00117 }
00118 
00119 void SystemTrayWidget::setMaximumSize(QSize s)
00120 {
00121     bool doLayout = (m_orientation == Qt::Horizontal && s.height() != maximumHeight());
00122     doLayout |= (m_orientation == Qt::Vertical && s.width() != maximumWidth());
00123 
00124     QWidget::setMaximumSize(s);
00125     if (doLayout) {
00126         relayoutContainers();
00127     }
00128 }
00129 
00130 void SystemTrayWidget::addWidgetToLayout(QWidget *widget)
00131 {
00132     // Add the widget to the layout
00133     m_mainLayout->setRowMinimumHeight(m_nextRow, 22);
00134     m_mainLayout->setColumnMinimumWidth(m_nextColumn, 22);
00135     widget->resize(22,22);
00136     m_mainLayout->addWidget(widget, m_nextRow, m_nextColumn, 1, 1, Qt::AlignCenter);
00137 
00138     // Figure out where the next widget should go
00139     if (m_orientation == Qt::Horizontal) {
00140         // Calculate the items that fit into a column
00141         m_maxCount = (maximumHeight() + m_mainLayout->spacing()) / (widget->height() + m_mainLayout->spacing()) -1;
00142 
00143         setMinimumSize(QSize(22 * (m_nextColumn + 1) + m_mainLayout->spacing() * m_nextColumn,
00144                              22 * (m_maxCount + 1) + m_mainLayout->spacing() * m_maxCount));
00145 
00146         // Add down then across when horizontal
00147         m_nextRow++;
00148         if (m_nextRow > m_maxCount){
00149             m_nextColumn++;
00150             m_nextRow = 0;
00151         }
00152     } else {
00153         // Calculate the items that fit into a row
00154         m_maxCount = (maximumWidth() + m_mainLayout->spacing()) / (widget->width() + m_mainLayout->spacing()) -1;
00155 
00156         setMinimumSize(QSize(22 * (m_maxCount + 1) + m_mainLayout->spacing() * m_maxCount,
00157                              22 * (m_nextRow + 1) + m_mainLayout->spacing() * m_nextRow));
00158 
00159         // Add across then down when vertical
00160         m_nextColumn++;
00161         if (m_nextColumn > m_maxCount) {
00162             m_nextRow++;
00163             m_nextColumn = 0;
00164         }
00165     }
00166 }
00167 
00168 void SystemTrayWidget::relayoutContainers(QObject *removeContainer)
00169 {
00170     // Pull all widgets from our container, skipping over the one that was just
00171     // deleted
00172     QList<QWidget *> remainingWidgets;
00173     while (QLayoutItem* item = m_mainLayout->takeAt(0)) {
00174         if (item->widget() && item->widget() != removeContainer) {
00175             remainingWidgets.append(item->widget());
00176         }
00177         delete item;
00178     }
00179 
00180     // Reset the widths and heights in our layout to 0 so that the removed
00181     // widget's space isn't kept
00182     // (Why doesn't QGridLayout do this automatically?)
00183     for (int row = 0; row < m_mainLayout->rowCount(); row++) {
00184         m_mainLayout->setRowMinimumHeight(row, 0);
00185     }
00186     for (int column = 0; column < m_mainLayout->columnCount(); column++) {
00187         m_mainLayout->setColumnMinimumWidth(column, 0);
00188     }
00189 
00190     // Re-add remaining widgets
00191     m_maxCount = 0;
00192     m_nextRow = 0;
00193     m_nextColumn = 0;
00194     foreach (QWidget *widget, remainingWidgets) {
00195         addWidgetToLayout(widget);
00196     }
00197 
00198     emit sizeShouldChange();
00199 }
00200 
00201 #include "systemtraywidget.moc"

Applets

Skip menu "Applets"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libplasma
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal