trayicon_x11.cpp

Go to the documentation of this file.
00001 /****************************************************************
00002  *  Vidalia is distributed under the following license:
00003  *
00004  *  Copyright (C) 2006,  Matt Edman, Justin Hipple
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public License
00008  *  as published by the Free Software Foundation; either version 2
00009  *  of the License, or (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, 
00019  *  Boston, MA  02110-1301, USA.
00020  ***************************************************************
00021  * This code is derived from systemtray.cpp from QMPDClient. It is 
00022  * licensed as follows:
00023  *
00024  * QMPDClient - An MPD client written in Qt 4.
00025  * Copyright (C) 2005 Håvard Tautra Knutsen <havtknut@tihlde.org>
00026  *
00027  * This program is free software; you can redistribute it and/or
00028  * modify it under the terms of the GNU General Public License
00029  * as published by the Free Software Foundation; either version 2
00030  * of the License, or (at your option) any later version.
00031  *
00032  * This program is distributed in the hope that it will be useful,
00033  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00034  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00035  * GNU General Public License for more details.
00036  *
00037  * You should have received a copy of the GNU General Public License
00038  * along with this program; if not, write to the Free Software
00039  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00040  */
00041 
00042 /**
00043  * \file trayicon_x11.cpp
00044  * \version $Id: trayicon_x11.cpp 1563 2006-12-26 06:06:04Z edmanm $
00045  * \brief Tray icon implementation on X11
00046  */
00047 
00048 #include "trayicon_x11.h"
00049 
00050 #include <QApplication>
00051 #include <QTimer>
00052 #include <QX11Info>
00053 #include <X11/Xatom.h>
00054 #include <X11/Xlib.h>
00055 
00056 // System Tray Protocol Specification opcodes.
00057 #define SYSTEM_TRAY_REQUEST_DOCK    0
00058 #define SYSTEM_TRAY_BEGIN_MESSAGE   1
00059 #define SYSTEM_TRAY_CANCEL_MESSAGE  2
00060 
00061 
00062 /* Default constructor */
00063 TrayIconImpl::TrayIconImpl()
00064 {
00065   setObjectName("trayiconimpl");
00066   
00067   /* Add this widget to the system notification area */
00068   addToTray();
00069 }
00070 
00071 /** Adds this widget to the system notification area. */
00072 void
00073 TrayIconImpl::addToTray()
00074 {
00075   setMinimumSize(22, 22);
00076   setMaximumSize(22, 22);
00077   //setBackgroundRole(QPalette::Base);
00078   //setBackgroundRole(QPalette::NoRole);
00079 
00080   Display *dpy = QX11Info::display();
00081   Screen *screen = XDefaultScreenOfDisplay(dpy);
00082   WId trayWin  = winId();
00083 
00084   /* Standard tray window protocol */
00085   int iScreen = XScreenNumberOfScreen(screen);
00086   char szAtom[32];
00087   snprintf(szAtom, sizeof(szAtom), "_NET_SYSTEM_TRAY_S%d", iScreen);
00088   Atom selectionAtom = XInternAtom(dpy, szAtom, false);
00089   XGrabServer(dpy);
00090   Window win = XGetSelectionOwner(dpy, selectionAtom);
00091   if (win != None)
00092       XSelectInput(dpy, win, StructureNotifyMask);
00093   XUngrabServer(dpy);
00094   XFlush(dpy);
00095 
00096   if (win != None) {
00097     XEvent ev;
00098     memset(&ev, 0, sizeof(ev));
00099     ev.xclient.type = ClientMessage;
00100     ev.xclient.window = win;
00101     ev.xclient.message_type = XInternAtom (dpy, "_NET_SYSTEM_TRAY_OPCODE", false);
00102     ev.xclient.format = 32;
00103     ev.xclient.data.l[0] = CurrentTime;
00104     ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
00105     ev.xclient.data.l[2] = trayWin;
00106     ev.xclient.data.l[3] = 0;
00107     ev.xclient.data.l[4] = 0;
00108     XSendEvent(dpy, win, false, NoEventMask, &ev);
00109     XSync(dpy, false);
00110   }
00111 
00112   /* KDE-related */
00113   long data = 0;
00114   Atom dockwindow = XInternAtom(dpy, "KWM_DOCKWINDOW", false);
00115   Atom traywindow = XInternAtom(dpy, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", false);
00116   XChangeProperty(dpy, winId(), dockwindow, dockwindow, 32, 
00117                   PropModeReplace, (uchar*)&data, 1);
00118   XChangeProperty(dpy, winId(), traywindow, XA_WINDOW, 32, 
00119                   PropModeReplace, (uchar*)&data, 1);
00120 }
00121 
00122 /** Process events when the mouse enters the icon area. */
00123 void 
00124 TrayIconImpl::enterEvent(QEvent *event) 
00125 {
00126     XEvent ev;
00127     memset(&ev, 0, sizeof(ev));
00128     ev.xfocus.display = QX11Info::display();
00129     ev.xfocus.type = FocusIn;
00130     ev.xfocus.window = winId();
00131     ev.xfocus.mode = NotifyNormal;
00132     ev.xfocus.detail = NotifyAncestor;
00133     qApp->x11ProcessEvent(&ev);
00134     QWidget::enterEvent(event);
00135 }
00136 
00137 /** Show the tray icon image. */
00138 void
00139 TrayIconImpl::show()
00140 {
00141   static bool shown = false;
00142   if (!shown) {
00143     /* Sometimes the tray icon on my gnome desktop wouldn't dock and instead
00144      * would appear as its own window. Looking at comments in other projects
00145      * that used tray icons told me that this is a known problem and that gnome
00146      * needs a delay before adding the icon the first time. The hack is to give
00147      * gnome this delay so the icon appears properly docked. */
00148     QTimer::singleShot(250, this, SLOT(show()));
00149     shown = true;
00150   } else {
00151     QLabel::show();
00152   }
00153 }
00154 
00155 /** Hide the tray icon image. */
00156 void
00157 TrayIconImpl::hide()
00158 {
00159   QLabel::hide();
00160 }
00161 
00162 /** Set the tray icon's tooltip. */
00163 void
00164 TrayIconImpl::setToolTip(const QString &toolTip)
00165 {
00166   QLabel::setToolTip(toolTip);
00167 }
00168 
00169 /** Set the tray icon's image. */
00170 void
00171 TrayIconImpl::setIcon(const QString &iconFile)
00172 {
00173   /* Load the pixmap image from the specified resource file */
00174   QPixmap icon(iconFile);
00175   
00176   /* Scale the image to the correct size. */
00177   QPixmap scaledPixmap = icon.scaled(QWidget::size(), 
00178                                      Qt::KeepAspectRatio,
00179                                      Qt::SmoothTransformation);
00180   setPixmap(scaledPixmap);
00181 }
00182 

Generated on Wed Sep 5 15:49:28 2007 for Vidalia by  doxygen 1.5.3