Logo Search packages:      
Sourcecode: qsynth version File versions  Download package

qsynthSystemTray.cpp

// qsynthSystemTray.cpp
//
/****************************************************************************
   Copyright (C) 2003-2007, rncbc aka Rui Nuno Capela. All rights reserved.

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

*****************************************************************************/

#include "qsynthAbout.h"
#include "qsynthSystemTray.h"

#include <QBitmap>
#include <QPainter>

#ifndef QSYNTH_QT4_SYSTEM_TRAY

#include <QMouseEvent>
#include <QPaintEvent>

#if defined(Q_WS_X11)

#include <QX11Info>

#include <X11/Xatom.h>
#include <X11/Xlib.h>

// System Tray Protocol Specification opcodes.
#define SYSTEM_TRAY_REQUEST_DOCK    0
#define SYSTEM_TRAY_BEGIN_MESSAGE   1
#define SYSTEM_TRAY_CANCEL_MESSAGE  2

#endif      // Q_WS_X11

#endif


//----------------------------------------------------------------------------
// qsynthSystemTray -- Custom system tray widget.

#ifdef QSYNTH_QT4_SYSTEM_TRAY

// Constructor.
qsynthSystemTray::qsynthSystemTray ( QWidget *pParent )
      : QSystemTrayIcon(pParent)
{
      // Set things inherited...
      if (pParent) {
            m_icon = pParent->windowIcon();
            QSystemTrayIcon::setIcon(m_icon);
            QSystemTrayIcon::setToolTip(pParent->windowTitle());
      }

      QObject::connect(this,
            SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
            SLOT(activated(QSystemTrayIcon::ActivationReason)));

      setBackground(Qt::transparent);

      QSystemTrayIcon::show();
}


// Redirect to hide.
void qsynthSystemTray::close (void)
{
      QSystemTrayIcon::hide();
}


// Handle systeam tray activity.
void qsynthSystemTray::activated ( QSystemTrayIcon::ActivationReason reason )
{
      switch (reason) {
      case QSystemTrayIcon::Context:
            emit contextMenuRequested(QCursor::pos());
            break;
      case QSystemTrayIcon::Trigger:
            emit clicked();
            // Fall trhu...
      case QSystemTrayIcon::MiddleClick:
      case QSystemTrayIcon::DoubleClick:
      case QSystemTrayIcon::Unknown:
      default:
            break;
      }
}

#else

// Constructor.
qsynthSystemTray::qsynthSystemTray ( QWidget *pParent )
      : QWidget(pParent, Qt::Window
#if QT_VERSION >= 0x040200
            | Qt::CustomizeWindowHint
#endif
            | Qt::X11BypassWindowManagerHint
            | Qt::FramelessWindowHint
            | Qt::WindowStaysOnTopHint)
{
#if QT_VERSION >= 0x040200
      QWidget::setAttribute(Qt::WA_AlwaysShowToolTips);
#endif
//    QWidget::setAttribute(Qt::WA_NoSystemBackground);

//    QWidget::setBackgroundRole(QPalette::NoRole);
//    QWidget::setAutoFillBackground(true);

      QWidget::setFixedSize(22, 22);
//    QWidget::setMinimumSize(22, 22);

#if defined(Q_WS_X11)

      Display *dpy = QX11Info::display();
      WId trayWin  = winId();

      // System Tray Protocol Specification.
      Screen *screen = XDefaultScreenOfDisplay(dpy);
      int iScreen = XScreenNumberOfScreen(screen);
      char szAtom[32];
      snprintf(szAtom, sizeof(szAtom), "_NET_SYSTEM_TRAY_S%d", iScreen);
      Atom selectionAtom = XInternAtom(dpy, szAtom, false);
      XGrabServer(dpy);
      Window managerWin = XGetSelectionOwner(dpy, selectionAtom);
      if (managerWin != None)
            XSelectInput(dpy, managerWin, StructureNotifyMask);
      XUngrabServer(dpy);
      XFlush(dpy);
      if (managerWin != None) {
            XEvent ev;
            memset(&ev, 0, sizeof(ev));
            ev.xclient.type = ClientMessage;
            ev.xclient.window = managerWin;
            ev.xclient.message_type = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", false);
            ev.xclient.format = 32;
            ev.xclient.data.l[0] = CurrentTime;
            ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
            ev.xclient.data.l[2] = trayWin;
            ev.xclient.data.l[3] = 0;
            ev.xclient.data.l[4] = 0;
            XSendEvent(dpy, managerWin, false, NoEventMask, &ev);
            XSync(dpy, false);
      }

      // Follwing simple KDE specs:
      Atom trayAtom;
      // For older KDE's (hopefully)...
      int data = 1;
      trayAtom = XInternAtom(dpy, "KWM_DOCKWINDOW", false);
      XChangeProperty(dpy, trayWin, trayAtom, trayAtom, 32, PropModeReplace, (unsigned char *) &data, 1);
      // For not so older KDE's...
      WId forWin = pParent ? pParent->topLevelWidget()->winId() : QX11Info::appRootWindow();
      trayAtom = XInternAtom(dpy, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", false);
      XChangeProperty(dpy, trayWin, trayAtom, XA_WINDOW, 32, PropModeReplace, (unsigned char *) &forWin, 1);

#endif      // Q_WS_X11

      // Set things inherited...
      if (pParent) {
            QWidget::setWindowIcon(pParent->windowIcon());
            QWidget::setToolTip(pParent->windowTitle());
      }

      setBackground(Qt::transparent);
}

#endif


// Default destructor.
qsynthSystemTray::~qsynthSystemTray (void)
{
}


// System tray icon/pixmaps update method.
void qsynthSystemTray::updatePixmap (void)
{
      // Renitialize icon as fit...
#ifdef QSYNTH_QT4_SYSTEM_TRAY
      m_pixmap = m_icon.pixmap(22, 22);
#else
      m_pixmap = QWidget::windowIcon().pixmap(QWidget::size());
#endif

    // Merge with the overlay pixmap...
      if (!m_pixmapOverlay.mask().isNull()) {
            QBitmap mask = m_pixmap.mask();
            QPainter(&mask).drawPixmap(0, 0, m_pixmapOverlay.mask());
            m_pixmap.setMask(mask);
            QPainter(&m_pixmap).drawPixmap(0, 0, m_pixmapOverlay);
      }

#ifdef QSYNTH_QT4_SYSTEM_TRAY

      if (m_background != Qt::transparent) {
            QPixmap pixmap(m_pixmap);
            m_pixmap.fill(m_background);
            QPainter(&m_pixmap).drawPixmap(0, 0, pixmap);
      }

    // Setup system tray icon directly...
      QSystemTrayIcon::setIcon(QIcon(m_pixmap));

#else

    // Setup widget drawable pixmap transparency...
      if (!m_pixmap.mask().isNull() && m_background == Qt::transparent) {
            QBitmap mask(m_pixmap.size());
            mask.fill(Qt::color0);
            QBitmap maskPixmap = m_pixmap.mask();
            QPainter(&mask).drawPixmap(
                  (mask.width()  - maskPixmap.width())  / 2,
                  (mask.height() - maskPixmap.height()) / 2,
                  maskPixmap);
            QWidget::setMask(mask);
      } else {
            QWidget::setMask(QBitmap());
      }

      QWidget::update();

#endif
}



// Background mask methods.
void qsynthSystemTray::setBackground ( const QColor& background )
{
      // Set background color, now.
      m_background = background;

#ifndef QSYNTH_QT4_SYSTEM_TRAY

      QPalette pal(QWidget::palette());
      pal.setColor(QWidget::backgroundRole(), m_background);
      QWidget::setPalette(pal);

#endif

      updatePixmap();
}

const QColor& qsynthSystemTray::background (void) const
{
      return m_background;
}


// Set system tray icon overlay.
void qsynthSystemTray::setPixmapOverlay ( const QPixmap& pmOverlay )
{
      m_pixmapOverlay = pmOverlay;

      updatePixmap();
}

const QPixmap& qsynthSystemTray::pixmapOverlay (void) const
{
      return m_pixmapOverlay;
}


#ifndef QSYNTH_QT4_SYSTEM_TRAY

// Self-drawable methods.
void qsynthSystemTray::paintEvent ( QPaintEvent * )
{
      const QRect& rect = QWidget::rect();

      QPainter(this).drawPixmap(
            rect.x() + (rect.width()  - m_pixmap.width())  / 2,
            rect.y() + (rect.height() - m_pixmap.height()) / 2,
            m_pixmap);
}


// Inherited mouse event.
void qsynthSystemTray::mousePressEvent ( QMouseEvent *pMouseEvent )
{
      if (!QWidget::rect().contains(pMouseEvent->pos()))
            return;

      switch (pMouseEvent->button()) {

      case Qt::LeftButton:
            // Toggle parent widget visibility.
            emit clicked();
            break;

      case Qt::RightButton:
            // Just signal we're on to context menu.
            emit contextMenuRequested(pMouseEvent->globalPos());
            break;

      default:
            break;
      }
}

#endif

// end of qsynthSystemTray.cpp

Generated by  Doxygen 1.6.0   Back to index