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 1238 2006-09-25 17:50:57Z 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 TrayIconImpl::TrayIconImpl(const QString &iconFile, const QString &toolTip)
00063 {
00064   setObjectName("trayiconimpl");
00065   setMinimumSize(22, 22);
00066   setMaximumSize(22, 22);
00067   //setBackgroundRole(QPalette::Base);
00068   //setBackgroundRole(QPalette::NoRole);
00069 
00070   Display *dpy = QX11Info::display();
00071   Screen *screen = XDefaultScreenOfDisplay(dpy);
00072   WId trayWin  = winId();
00073 
00074   /* Standard tray window protocol */
00075   int iScreen = XScreenNumberOfScreen(screen);
00076   char szAtom[32];
00077   snprintf(szAtom, sizeof(szAtom), "_NET_SYSTEM_TRAY_S%d", iScreen);
00078   Atom selectionAtom = XInternAtom(dpy, szAtom, false);
00079   XGrabServer(dpy);
00080   Window win = XGetSelectionOwner(dpy, selectionAtom);
00081   if (win != None)
00082       XSelectInput(dpy, win, StructureNotifyMask);
00083   XUngrabServer(dpy);
00084   XFlush(dpy);
00085 
00086   if (win != None) {
00087     XEvent ev;
00088     memset(&ev, 0, sizeof(ev));
00089     ev.xclient.type = ClientMessage;
00090     ev.xclient.window = win;
00091     ev.xclient.message_type = XInternAtom (dpy, "_NET_SYSTEM_TRAY_OPCODE", false);
00092     ev.xclient.format = 32;
00093     ev.xclient.data.l[0] = CurrentTime;
00094     ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
00095     ev.xclient.data.l[2] = trayWin;
00096     ev.xclient.data.l[3] = 0;
00097     ev.xclient.data.l[4] = 0;
00098     XSendEvent(dpy, win, false, NoEventMask, &ev);
00099     XSync(dpy, false);
00100   }
00101 
00102   /* KDE-related */
00103   long data = 0;
00104   Atom dockwindow = XInternAtom(dpy, "KWM_DOCKWINDOW", false);
00105   Atom traywindow = XInternAtom(dpy, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", false);
00106   XChangeProperty(dpy, winId(), dockwindow, dockwindow, 32, PropModeReplace, (uchar*)&data, 1);
00107   XChangeProperty(dpy, winId(), traywindow, XA_WINDOW, 32, PropModeReplace, (uchar*)&data, 1);
00108  
00109   /* Set the initial icon and tooltip */
00110   setIcon(iconFile);
00111   setToolTip(toolTip);
00112 
00113   //setAttribute(Qt::WA_NoBackground);
00114   //XSetWindowBackgroundPixmap(dpy, trayWin, None);
00115 }
00116 
00117 /** Process events when the mouse enters the icon area. */
00118 void 
00119 TrayIconImpl::enterEvent(QEvent *event) 
00120 {
00121     XEvent ev;
00122     memset(&ev, 0, sizeof(ev));
00123     ev.xfocus.display = QX11Info::display();
00124     ev.xfocus.type = FocusIn;
00125     ev.xfocus.window = winId();
00126     ev.xfocus.mode = NotifyNormal;
00127     ev.xfocus.detail = NotifyAncestor;
00128     qApp->x11ProcessEvent(&ev);
00129     QWidget::enterEvent(event);
00130 }
00131 
00132 /** Show the tray icon image. */
00133 void
00134 TrayIconImpl::show()
00135 {
00136   static bool shown = false;
00137   if (!shown) {
00138     /* Sometimes the tray icon on my gnome desktop wouldn't dock and instead
00139      * would appear as its own window. Looking at comments in other projects
00140      * that used tray icons told me that this is a known problem and that gnome
00141      * needs a delay before adding the icon the first time. The hack is to give
00142      * gnome this delay so the icon appears properly docked. */
00143     QTimer::singleShot(250, this, SLOT(show()));
00144     shown = true;
00145   } else {
00146     QLabel::show();
00147   }
00148 }
00149 
00150 /** Hide the tray icon image. */
00151 void
00152 TrayIconImpl::hide()
00153 {
00154   QLabel::hide();
00155 }
00156 
00157 /** Set the tray icon's tooltip. */
00158 void
00159 TrayIconImpl::setToolTip(const QString &toolTip)
00160 {
00161   QLabel::setToolTip(toolTip);
00162 }
00163 
00164 /** Set the tray icon's image. */
00165 void
00166 TrayIconImpl::setIcon(const QString &iconFile)
00167 {
00168   /* Load the pixmap image from the specified resource file */
00169   QPixmap icon(iconFile);
00170   
00171   /* Scale the image to the correct size. */
00172   QPixmap scaledPixmap = icon.scaled(QWidget::size(), 
00173                                      Qt::KeepAspectRatio,
00174                                      Qt::SmoothTransformation);
00175   setPixmap(scaledPixmap);
00176 }
00177 

Generated on Mon Oct 23 20:08:16 2006 for Vidalia by  doxygen 1.5.0