trayicon_mac.cpp

Go to the documentation of this file.
00001 /*
00002 **  This file is part of Vidalia, and is subject to the license terms in the
00003 **  LICENSE file, found in the top level directory of this distribution. If you
00004 **  did not receive the LICENSE file with this file, you may obtain it from the
00005 **  Vidalia source package distributed by the Vidalia Project at
00006 **  http://www.vidalia-project.net/. No part of Vidalia, including this file,
00007 **  may be copied, modified, propagated, or distributed except according to the
00008 **  terms described in the LICENSE file.
00009 */
00010 
00011 /*
00012 ** \file trayicon_mac.cpp
00013 ** \version $Id: trayicon_mac.cpp 2362 2008-02-29 04:30:11Z edmanm $
00014 ** \brief Tray icon implementation on OS X (Dock icon)
00015 */
00016 
00017 #include <QApplication>
00018 
00019 #include "trayicon_mac.h"
00020 
00021 
00022 /** Default constructor */
00023 TrayIconImpl::TrayIconImpl(QWidget *parent)
00024   : QWidget(parent)
00025 {
00026   setObjectName("trayiconimpl");
00027   _imageRef = 0;
00028   _shown    = false;
00029 }
00030 
00031 /** Destructor */
00032 TrayIconImpl::~TrayIconImpl()
00033 {
00034   if (_shown) {
00035     hide();
00036   }
00037   if (_imageRef) {
00038     CGImageRelease(_imageRef);
00039   }
00040 }
00041 
00042 /** Callback used by CGDataProviderCreateWithData(). */
00043 void
00044 TrayIconImpl::releaseCallback(void *info, const void *data, size_t size)
00045 {
00046   Q_UNUSED(info);
00047   Q_UNUSED(size);
00048   free((void*)data);
00049 }
00050 
00051 /** Load icon data from the given file and create a CGImageRef. */
00052 CGImageRef
00053 TrayIconImpl::createIconFromFile(FSSpec fileSpec)
00054 {
00055   CGDataProviderRef provider = NULL;
00056   CGImageRef image = NULL;
00057   IconFamilyHandle iconFamily;
00058   
00059   /* Load the icon from the resource bundle */
00060   if (ReadIconFile(&fileSpec, &iconFamily) == noErr) {
00061     int size = 128 * 128 * 4;
00062     Handle rawBitmapdata = NewHandle(size);
00063     GetIconFamilyData(iconFamily, kThumbnail32BitData, rawBitmapdata);
00064     
00065     Handle rawMaskdata = NewHandle(128 * 128);
00066     GetIconFamilyData(iconFamily, kThumbnail8BitMask, rawMaskdata);
00067     
00068     char *data = (char *)malloc(size);
00069     HLock(rawBitmapdata);
00070     HLock(rawMaskdata);
00071     
00072     /* copy mask data into alpha channel */
00073     const char *mask = (const char*) *rawMaskdata;
00074     const char *from = (const char*) *rawBitmapdata;
00075     char *to = data;
00076     
00077     for (int i= 0; i < 128*128; i++) {
00078       from++;
00079       *to++ = *mask++;
00080       *to++ = *from++;
00081       *to++ = *from++;
00082       *to++ = *from++;
00083     }
00084     HUnlock(rawBitmapdata);
00085     HUnlock(rawMaskdata);
00086     
00087     DisposeHandle(rawBitmapdata);
00088     DisposeHandle(rawMaskdata);
00089     
00090     provider = CGDataProviderCreateWithData(NULL, data, size, releaseCallback);
00091     CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
00092     
00093     image = CGImageCreate(128,  // width
00094                           128,  // height
00095                           8,    // Bits per component
00096                           32,   // Bits per pixel
00097                           4 * 128,  // Bytes per row
00098                           cs,
00099                           kCGImageAlphaFirst,
00100                           provider,
00101                           NULL,
00102                           0,
00103                           kCGRenderingIntentDefault);
00104     
00105     CGColorSpaceRelease(cs);
00106     CGDataProviderRelease(provider);
00107   }
00108   return image;
00109 }
00110 
00111 /** Create an icon from the given filename in the application bundle. */
00112 CGImageRef
00113 TrayIconImpl::createIcon(const QString &iconFile)
00114 {
00115   FSRef ref;
00116   CGImageRef image = NULL;
00117   
00118   /* Create a CFStringRef that we can use to build the resource URL */
00119   CFStringRef iconFileRef = CFStringCreateWithCString(NULL, qPrintable(iconFile), 
00120                                                       kCFStringEncodingASCII);
00121   if (!iconFileRef) {
00122     return NULL;
00123   }
00124   
00125   /* Build a URL to the requested .icns in our resource bundle */
00126   CFURLRef url = CFBundleCopyResourceURL(CFBundleGetMainBundle(), 
00127                                          iconFileRef, CFSTR("icns"), NULL);
00128   if (!url) {
00129     return NULL;
00130   }
00131 
00132   /* Try to find the resource in the bundle */
00133   if (CFURLGetFSRef(url, &ref)) {
00134     FSSpec fileSpec;
00135     if (FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, 
00136                          NULL, &fileSpec, NULL) == noErr) {
00137       /* Found it, now create the icon from it */
00138       image = createIconFromFile(fileSpec);
00139     }
00140   }
00141   CFRelease(iconFileRef);
00142   CFRelease(url);
00143   return image;  
00144 }
00145 
00146 /** Show the tray icon image. */
00147 void
00148 TrayIconImpl::show()
00149 {
00150   if (_imageRef) {
00151     CGContextRef ctxRef = BeginCGContextForApplicationDockTile();
00152     if (!ctxRef) {
00153       return;
00154     }
00155     SetApplicationDockTileImage(_imageRef);
00156     EndCGContextForApplicationDockTile(ctxRef);
00157     
00158     _shown = true;
00159   }  
00160 }
00161 
00162 /** Hide the tray icon image. */
00163 void
00164 TrayIconImpl::hide()
00165 {
00166   _shown = false;
00167   
00168   CGContextRef ctxRef = BeginCGContextForApplicationDockTile();
00169   if (!ctxRef) {
00170     return;
00171   }
00172   RestoreApplicationDockTileImage();
00173   EndCGContextForApplicationDockTile(ctxRef);
00174 }
00175 
00176 /** Set the tray icon's tooltip. */
00177 void
00178 TrayIconImpl::setToolTip(const QString &toolTip)
00179 {
00180   /* The dock icon doesn't have a tooltip. */
00181   Q_UNUSED(toolTip);
00182 }
00183 
00184 /** Set the tray icon's image. */
00185 void
00186 TrayIconImpl::setIcon(const QString &iconFile)
00187 {
00188   /* If there was an image set previously, free it before getting the new one */
00189   if (_imageRef) {
00190     CGImageRelease(_imageRef);
00191     _imageRef = 0;
00192   }
00193   
00194   /* Load the icon data from the application bundle */
00195   _imageRef = createIcon(iconFile);
00196   
00197   /* If the icon is to be shown, put it in the dock now. */
00198   if (_imageRef && _shown) {
00199     show();
00200   }
00201 }
00202 

Generated on Tue Jul 7 16:58:27 2009 for Vidalia by  doxygen 1.4.7