diff options
Diffstat (limited to 'src/gui/util/qsystemtrayicon_win.cpp')
-rw-r--r-- | src/gui/util/qsystemtrayicon_win.cpp | 748 |
1 files changed, 748 insertions, 0 deletions
diff --git a/src/gui/util/qsystemtrayicon_win.cpp b/src/gui/util/qsystemtrayicon_win.cpp new file mode 100644 index 0000000..84f9de4 --- /dev/null +++ b/src/gui/util/qsystemtrayicon_win.cpp @@ -0,0 +1,748 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsystemtrayicon_p.h" +#ifndef QT_NO_SYSTEMTRAYICON +//#define _WIN32_IE 0x0500 +#define _WIN32_IE 0x0600 //required for NOTIFYICONDATAW_V2_SIZE + +//missing defines for MINGW : +#ifndef NIN_BALLOONTIMEOUT +#define NIN_BALLOONTIMEOUT (WM_USER + 4) +#endif +#ifndef NIN_BALLOONUSERCLICK +#define NIN_BALLOONUSERCLICK (WM_USER + 5) +#endif + +#include <qt_windows.h> +#include <commctrl.h> +#include <shlwapi.h> +#include <QBitmap> +#include <QLibrary> +#include <QApplication> +#include <QToolTip> +#include <QDesktopWidget> +#include <QSettings> + +#if defined(Q_OS_WINCE) && !defined(STANDARDSHELL_UI_MODEL) +# include <streams.h> +#endif + +QT_BEGIN_NAMESPACE + +#if defined(Q_OS_WINCE) +static const UINT q_uNOTIFYICONID = 13; // IDs from 0 to 12 are reserved on WinCE. +#else +static const UINT q_uNOTIFYICONID = 0; +#endif + +static uint MYWM_TASKBARCREATED = 0; +#define MYWM_NOTIFYICON (WM_APP+101) + +typedef BOOL (WINAPI *PtrShell_NotifyIcon)(DWORD,PNOTIFYICONDATA); +static PtrShell_NotifyIcon ptrShell_NotifyIcon = 0; + +static void resolveLibs() +{ + static bool triedResolve = false; +#if defined Q_OS_WINCE + QString libName(QLatin1String("coredll")); + const char* funcName = "Shell_NotifyIcon"; +#else + QString libName(QLatin1String("shell32")); + const char* funcName = "Shell_NotifyIconW"; +#endif + if (!triedResolve) { + QLibrary lib(libName); + triedResolve = true; + ptrShell_NotifyIcon = (PtrShell_NotifyIcon) lib.resolve(funcName); + } +} + +class QSystemTrayIconSys : QWidget +{ +public: + QSystemTrayIconSys(QSystemTrayIcon *object); + ~QSystemTrayIconSys(); + bool winEvent( MSG *m, long *result ); + bool trayMessageA(DWORD msg); + bool trayMessageW(DWORD msg); + bool trayMessage(DWORD msg); + bool iconDrawItem(LPDRAWITEMSTRUCT lpdi); + void setIconContentsW(NOTIFYICONDATAW &data); + void setIconContentsA(NOTIFYICONDATAA &data); + bool showMessageW(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs); + bool showMessageA(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs); + bool allowsMessages(); + bool supportsMessages(); + QRect findIconGeometry(const int a_iButtonID); + QRect findTrayGeometry(); + HBITMAP createIconMask(const QBitmap &bitmap); + void createIcon(); + int detectShellVersion() const; + HICON hIcon; + QPoint globalPos; + QSystemTrayIcon *q; +private: + uint notifyIconSizeW; + uint notifyIconSizeA; + int currentShellVersion; + int maxTipLength; +}; + +// Checks for the shell32 dll version number, since only version +// 5 or later of supports ballon messages +bool QSystemTrayIconSys::allowsMessages() +{ +#ifndef QT_NO_SETTINGS + + QSettings settings(QLatin1String("HKEY_CURRENT_USER\\Software\\Microsoft" + "\\Windows\\CurrentVersion\\Explorer\\Advanced"), QSettings::NativeFormat); + return settings.value(QLatin1String("EnableBalloonTips"), true).toBool(); +#else + return false; +#endif +} + +// Checks for the shell32 dll version number, since only version +// 5 or later of supports ballon messages +bool QSystemTrayIconSys::supportsMessages() +{ +#if NOTIFYICON_VERSION >= 3 + if (currentShellVersion >= 5) + return allowsMessages(); + else +#endif + return false; +} + +//Returns the runtime major version of the shell32 dll +int QSystemTrayIconSys::detectShellVersion() const +{ +#ifndef Q_OS_WINCE + int shellVersion = 4; //NT 4.0 and W95 + DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)QLibrary::resolve( + QLatin1String("shell32"), "DllGetVersion"); + if (pDllGetVersion) + { + DLLVERSIONINFO dvi; + HRESULT hr; + ZeroMemory(&dvi, sizeof(dvi)); + dvi.cbSize = sizeof(dvi); + hr = (*pDllGetVersion)(&dvi); + if (SUCCEEDED(hr)) { + if (dvi.dwMajorVersion >= 5) + { + shellVersion = dvi.dwMajorVersion; + } + } + } + return shellVersion; +#endif + return 4; //No ballonMessages and MaxTipLength = 64 for WindowsCE +} + +QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *object) + : hIcon(0), q(object) +{ + currentShellVersion = detectShellVersion(); + notifyIconSizeA = FIELD_OFFSET(NOTIFYICONDATAA, szTip[64]); // NOTIFYICONDATAA_V1_SIZE + notifyIconSizeW = FIELD_OFFSET(NOTIFYICONDATAW, szTip[64]); // NOTIFYICONDATAW_V1_SIZE; + maxTipLength = 64; + +#if NOTIFYICON_VERSION >= 3 + if (currentShellVersion >=5) { + notifyIconSizeA = FIELD_OFFSET(NOTIFYICONDATAA, guidItem); // NOTIFYICONDATAA_V2_SIZE + notifyIconSizeW = FIELD_OFFSET(NOTIFYICONDATAW, guidItem); // NOTIFYICONDATAW_V2_SIZE; + maxTipLength = 128; + } +#endif + + // For restoring the tray icon after explorer crashes + if (!MYWM_TASKBARCREATED) { + MYWM_TASKBARCREATED = QT_WA_INLINE(RegisterWindowMessageW(L"TaskbarCreated"),RegisterWindowMessageA("TaskbarCreated")); + } +} + +QSystemTrayIconSys::~QSystemTrayIconSys() +{ + if (hIcon) + DestroyIcon(hIcon); +} + +void QSystemTrayIconSys::setIconContentsW(NOTIFYICONDATAW &tnd) +{ + tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP; + tnd.uCallbackMessage = MYWM_NOTIFYICON; + tnd.hIcon = hIcon; + QString tip = q->toolTip(); + + if (!tip.isNull()) { + // Tip is limited to maxTipLength - NULL; lstrcpyn appends a NULL terminator. + tip = tip.left(maxTipLength - 1) + QChar(); +#if defined(Q_OS_WINCE) + wcsncpy(tnd.szTip, reinterpret_cast<const wchar_t *> (tip.utf16()), qMin(tip.length()+1, maxTipLength)); +#else + lstrcpynW(tnd.szTip, (TCHAR*)tip.utf16(), qMin(tip.length()+1, maxTipLength)); +#endif + } +} + +void QSystemTrayIconSys::setIconContentsA(NOTIFYICONDATAA &tnd) +{ + tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP; + tnd.uCallbackMessage = MYWM_NOTIFYICON; + tnd.hIcon = hIcon; + QString tip = q->toolTip(); + + if (!tip.isNull()) { + // Tip is limited to maxTipLength - NULL; lstrcpyn appends a NULL terminator. + tip = tip.left(maxTipLength - 1) + QChar(); +#if defined(Q_OS_WINCE) + strncpy(tnd.szTip, tip.toLocal8Bit().constData(), qMin(tip.length()+1, maxTipLength)); +#else + lstrcpynA(tnd.szTip, tip.toLocal8Bit().constData(), qMin(tip.length()+1, maxTipLength)); +#endif + } +} + +int iconFlag( QSystemTrayIcon::MessageIcon icon ) +{ + int flag = 0; +#if NOTIFYICON_VERSION >= 3 + switch (icon) { + case QSystemTrayIcon::NoIcon: + break; + case QSystemTrayIcon::Critical: + flag = NIIF_ERROR; + break; + case QSystemTrayIcon::Warning: + flag = NIIF_WARNING; + break; + case QSystemTrayIcon::Information: + default : // fall through + flag = NIIF_INFO; + } +#else + Q_UNUSED(icon); +#endif + return flag; +} + +bool QSystemTrayIconSys::showMessageW(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs) +{ +#if NOTIFYICON_VERSION>=3 + NOTIFYICONDATA tnd; + memset(&tnd, 0, notifyIconSizeW); + Q_ASSERT(testAttribute(Qt::WA_WState_Created)); + + setIconContentsW(tnd); +#if defined(Q_OS_WINCE) + wcsncpy(tnd.szInfo, message.utf16(), qMin(message.length() + 1, 256)); + wcsncpy(tnd.szInfoTitle, title.utf16(), qMin(title.length()+1, 64)); +#else + lstrcpynW(tnd.szInfo, (TCHAR*)message.utf16(), qMin(message.length() + 1, 256)); + lstrcpynW(tnd.szInfoTitle, (TCHAR*)title.utf16(), qMin(title.length() + 1, 64)); +#endif + tnd.uID = q_uNOTIFYICONID; + tnd.dwInfoFlags = iconFlag(type); + tnd.cbSize = notifyIconSizeW; + tnd.hWnd = winId(); + tnd.uTimeout = uSecs; + tnd.uFlags = NIF_INFO; + return ptrShell_NotifyIcon(NIM_MODIFY, &tnd); +#else + Q_UNUSED(title); + Q_UNUSED(message); + Q_UNUSED(type); + Q_UNUSED(uSecs); + return false; +#endif +} + +bool QSystemTrayIconSys::showMessageA(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs) +{ +#if NOTIFYICON_VERSION>=3 + NOTIFYICONDATAA tnd; + memset(&tnd, 0, notifyIconSizeA); + Q_ASSERT(testAttribute(Qt::WA_WState_Created)); + + setIconContentsA(tnd); +#if defined(Q_OS_WINCE) + strncpy(tnd.szInfo, message.toLocal8Bit().constData(), qMin(message.length() + 1, 256)); + strncpy(tnd.szInfoTitle, title.toLocal8Bit().constData(), qMin(title.length()+1, 64)); +#else + lstrcpynA(tnd.szInfo, message.toLocal8Bit().constData(), qMin(message.length() + 1, 256)); + lstrcpynA(tnd.szInfoTitle, title.toLocal8Bit().constData(), qMin(title.length() + 1, 64)); +#endif + tnd.uID = q_uNOTIFYICONID; + tnd.dwInfoFlags = iconFlag(type); + tnd.cbSize = notifyIconSizeA; + tnd.hWnd = winId(); + tnd.uTimeout = uSecs; + tnd.uFlags = NIF_INFO; + return Shell_NotifyIconA(NIM_MODIFY, &tnd); +#else + Q_UNUSED(title); + Q_UNUSED(message); + Q_UNUSED(type); + Q_UNUSED(uSecs); + return false; +#endif +} + +bool QSystemTrayIconSys::trayMessageA(DWORD msg) +{ +#if !defined(Q_OS_WINCE) + NOTIFYICONDATAA tnd; + memset(&tnd, 0, notifyIconSizeA); + tnd.uID = q_uNOTIFYICONID; + tnd.cbSize = notifyIconSizeA; + tnd.hWnd = winId(); + Q_ASSERT(testAttribute(Qt::WA_WState_Created)); + + if (msg != NIM_DELETE) { + setIconContentsA(tnd); + } + return Shell_NotifyIconA(msg, &tnd); +#else + Q_UNUSED(msg); + return false; +#endif +} + +bool QSystemTrayIconSys::trayMessageW(DWORD msg) +{ + NOTIFYICONDATAW tnd; + memset(&tnd, 0, notifyIconSizeW); + tnd.uID = q_uNOTIFYICONID; + tnd.cbSize = notifyIconSizeW; + tnd.hWnd = winId(); + Q_ASSERT(testAttribute(Qt::WA_WState_Created)); + + if (msg != NIM_DELETE) { + setIconContentsW(tnd); + } + return ptrShell_NotifyIcon(msg, &tnd); +} + +bool QSystemTrayIconSys::trayMessage(DWORD msg) +{ + resolveLibs(); + if (!(ptrShell_NotifyIcon)) + return false; + + QT_WA({ + return trayMessageW(msg); + }, + { + return trayMessageA(msg); + }); +} + +bool QSystemTrayIconSys::iconDrawItem(LPDRAWITEMSTRUCT lpdi) +{ + if (!hIcon) + return false; + + DrawIconEx(lpdi->hDC, lpdi->rcItem.left, lpdi->rcItem.top, hIcon, 0, 0, 0, 0, DI_NORMAL); + return true; +} + +HBITMAP QSystemTrayIconSys::createIconMask(const QBitmap &bitmap) +{ + QImage bm = bitmap.toImage().convertToFormat(QImage::Format_Mono); + int w = bm.width(); + int h = bm.height(); + int bpl = ((w+15)/16)*2; // bpl, 16 bit alignment + uchar *bits = new uchar[bpl*h]; + bm.invertPixels(); + for (int y=0; y<h; y++) + memcpy(bits+y*bpl, bm.scanLine(y), bpl); + HBITMAP hbm = CreateBitmap(w, h, 1, 1, bits); + delete [] bits; + return hbm; +} + +void QSystemTrayIconSys::createIcon() +{ + hIcon = 0; + QIcon icon = q->icon(); + if (icon.isNull()) + return; + + const int iconSizeX = GetSystemMetrics(SM_CXSMICON); + const int iconSizeY = GetSystemMetrics(SM_CYSMICON); + QSize size = icon.actualSize(QSize(iconSizeX, iconSizeY)); + QPixmap pm = icon.pixmap(size); + if (pm.isNull()) + return; + + QBitmap mask = pm.mask(); + if (mask.isNull()) { + mask = QBitmap(pm.size()); + mask.fill(Qt::color1); + } + + HBITMAP im = createIconMask(mask); + ICONINFO ii; + ii.fIcon = true; + ii.hbmMask = im; + ii.hbmColor = pm.toWinHBITMAP(QPixmap::Alpha); + ii.xHotspot = 0; + ii.yHotspot = 0; + hIcon = CreateIconIndirect(&ii); + + DeleteObject(ii.hbmColor); + DeleteObject(im); +} + +bool QSystemTrayIconSys::winEvent( MSG *m, long *result ) +{ + switch(m->message) { + case WM_CREATE: +#ifdef GWLP_USERDATA + SetWindowLongPtr(winId(), GWLP_USERDATA, (LONG_PTR)((CREATESTRUCTW*)m->lParam)->lpCreateParams); +#else + SetWindowLong(winId(), GWL_USERDATA, (LONG)((CREATESTRUCTW*)m->lParam)->lpCreateParams); +#endif + break; + + case WM_DRAWITEM: + return iconDrawItem((LPDRAWITEMSTRUCT)m->lParam); + + case MYWM_NOTIFYICON: + { + RECT r; + GetWindowRect(winId(), &r); + QEvent *e = 0; + Qt::KeyboardModifiers keys = QApplication::keyboardModifiers(); + QPoint gpos = QCursor::pos(); + + switch (m->lParam) { + case WM_LBUTTONUP: + emit q->activated(QSystemTrayIcon::Trigger); + break; + +#if !defined(Q_OS_WINCE) + case WM_LBUTTONDBLCLK: + emit q->activated(QSystemTrayIcon::DoubleClick); + break; + + case WM_RBUTTONUP: + if (q->contextMenu()) { + q->contextMenu()->popup(gpos); + q->contextMenu()->activateWindow(); + //Must be activated for proper keyboardfocus and menu closing on windows: + } + emit q->activated(QSystemTrayIcon::Context); + break; + + case NIN_BALLOONUSERCLICK: + emit q->messageClicked(); + break; + + case WM_MBUTTONUP: + emit q->activated(QSystemTrayIcon::MiddleClick); + break; +#endif + default: + break; + } + if (e) { + bool res = QApplication::sendEvent(q, e); + delete e; + return res; + } + break; + } + default: + if (m->message == MYWM_TASKBARCREATED) + trayMessage(NIM_ADD); + else + return QWidget::winEvent(m, result); + break; + } + return 0; +} + +void QSystemTrayIconPrivate::install_sys() +{ + Q_Q(QSystemTrayIcon); + if (!sys) { + sys = new QSystemTrayIconSys(q); + sys->createIcon(); + sys->trayMessage(NIM_ADD); + } +} + +//fallback on win 95/98 +QRect QSystemTrayIconSys::findTrayGeometry() +{ + //Use lower right corner as fallback + QPoint brCorner = qApp->desktop()->screenGeometry().bottomRight(); + QRect ret(brCorner.x() - 10, brCorner.y() - 10, 10, 10); +#if defined(Q_OS_WINCE) + HWND trayHandle = FindWindowW(L"Shell_TrayWnd", NULL); +#else + HWND trayHandle = FindWindowA("Shell_TrayWnd", NULL); +#endif + if (trayHandle) { +#if defined(Q_OS_WINCE) + trayHandle = FindWindowW(L"TrayNotifyWnd", NULL); +#else + trayHandle = FindWindowExA(trayHandle, NULL, "TrayNotifyWnd", NULL); +#endif + if (trayHandle) { + RECT r; + if (GetWindowRect(trayHandle, &r)) { + ret = QRect(r.left, r.top, r.right- r.left, r.bottom - r.top); + } + } + } + return ret; +} + +/* +* This function tries to determine the icon geometry from the tray +* +* If it fails an invalid rect is returned. +*/ +QRect QSystemTrayIconSys::findIconGeometry(const int iconId) +{ + QRect ret; + + TBBUTTON buttonData; + DWORD processID = 0; +#if defined(Q_OS_WINCE) + HWND trayHandle = FindWindowW(L"Shell_TrayWnd", NULL); +#else + HWND trayHandle = FindWindowA("Shell_TrayWnd", NULL); +#endif + + //find the toolbar used in the notification area + if (trayHandle) { +#if defined(Q_OS_WINCE) + trayHandle = FindWindowW(L"TrayNotifyWnd", NULL); +#else + trayHandle = FindWindowExA(trayHandle, NULL, "TrayNotifyWnd", NULL); +#endif + if (trayHandle) { +#if defined(Q_OS_WINCE) + HWND hwnd = FindWindowW(L"SysPager", NULL); +#else + HWND hwnd = FindWindowEx(trayHandle, NULL, L"SysPager", NULL); +#endif + if (hwnd) { +#if defined(Q_OS_WINCE) + hwnd = FindWindow(L"ToolbarWindow32", NULL); +#else + hwnd = FindWindowEx(hwnd, NULL, L"ToolbarWindow32", NULL); +#endif + if (hwnd) + trayHandle = hwnd; + } + } + } + + if (!trayHandle) + return ret; + + GetWindowThreadProcessId(trayHandle, &processID); + if (processID <= 0) + return ret; + + HANDLE trayProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ, 0, processID); + if (!trayProcess) + return ret; + + int buttonCount = SendMessage(trayHandle, TB_BUTTONCOUNT, 0, 0); +#if defined(Q_OS_WINCE) + LPVOID data = VirtualAlloc(NULL, sizeof(TBBUTTON), MEM_COMMIT, PAGE_READWRITE); +#else + LPVOID data = VirtualAllocEx(trayProcess, NULL, sizeof(TBBUTTON), MEM_COMMIT, PAGE_READWRITE); +#endif + + if ( buttonCount < 1 || !data ) { + CloseHandle(trayProcess); + return ret; + } + + //search for our icon among all toolbar buttons + for (int toolbarButton = 0; toolbarButton < buttonCount; ++toolbarButton ) { + SIZE_T numBytes = 0; + DWORD appData[2] = { 0, 0 }; + SendMessage(trayHandle, TB_GETBUTTON, toolbarButton , (LPARAM)data); + + if(!ReadProcessMemory(trayProcess, data, &buttonData, sizeof(TBBUTTON), &numBytes)) + continue; + + if(!ReadProcessMemory(trayProcess, (LPVOID) buttonData.dwData, appData, sizeof(appData), &numBytes)) + continue; + + int currentIconId = appData[1]; + HWND currentIconHandle = (HWND) appData[0]; + bool isHidden = buttonData.fsState & TBSTATE_HIDDEN; + + if (currentIconHandle == winId() && + currentIconId == iconId && !isHidden) { + SendMessage(trayHandle, TB_GETITEMRECT, toolbarButton , (LPARAM)data); + RECT iconRect = {0, 0}; + if(ReadProcessMemory(trayProcess, data, &iconRect, sizeof(RECT), &numBytes)) { + MapWindowPoints(trayHandle, NULL, (LPPOINT)&iconRect, 2); + QRect geometry(iconRect.left + 1, iconRect.top + 1, + iconRect.right - iconRect.left - 2, + iconRect.bottom - iconRect.top - 2); + if (geometry.isValid()) + ret = geometry; + break; + } + } + } +#if defined(Q_OS_WINCE) + VirtualFree(data, 0, MEM_RELEASE); +#else + VirtualFreeEx(trayProcess, data, 0, MEM_RELEASE); +#endif + CloseHandle(trayProcess); + return ret; +} + + +void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, int timeOut) +{ + if (!sys || !sys->allowsMessages()) + return; + + uint uSecs = 0; + if ( timeOut < 0) + uSecs = 10000; //10 sec default + else uSecs = (int)timeOut; + + resolveLibs(); + + //message is limited to 255 chars + NULL + QString messageString; + if (message.isEmpty() && !title.isEmpty()) + messageString = QLatin1String(" "); //ensures that the message shows when only title is set + else + messageString = message.left(255) + QChar(); + + //title is limited to 63 chars + NULL + QString titleString = title.left(63) + QChar(); + + if (sys->supportsMessages()) { + QT_WA({ + sys->showMessageW(titleString, messageString, type, (unsigned int)uSecs); + }, { + sys->showMessageA(titleString, messageString, type, (unsigned int)uSecs); + }); + } else { + //use fallbacks + QRect iconPos = sys->findIconGeometry(0); + if (iconPos.isValid()) { + QBalloonTip::showBalloon(type, title, message, sys->q, iconPos.center(), uSecs, true); + } else { + QRect trayRect = sys->findTrayGeometry(); + QBalloonTip::showBalloon(type, title, message, sys->q, QPoint(trayRect.left(), + trayRect.center().y()), uSecs, false); + } + } +} + +QRect QSystemTrayIconPrivate::geometry_sys() const +{ + if (!sys) + return QRect(); + return sys->findIconGeometry(0); +} + +void QSystemTrayIconPrivate::remove_sys() +{ + if (!sys) + return; + + sys->trayMessage(NIM_DELETE); + delete sys; + sys = 0; +} + +void QSystemTrayIconPrivate::updateIcon_sys() +{ + if (!sys) + return; + + HICON hIconToDestroy = sys->hIcon; + + sys->createIcon(); + sys->trayMessage(NIM_MODIFY); + + if (hIconToDestroy) + DestroyIcon(hIconToDestroy); +} + +void QSystemTrayIconPrivate::updateMenu_sys() +{ + +} + +void QSystemTrayIconPrivate::updateToolTip_sys() +{ +#ifdef Q_OS_WINCE + // Calling sys->trayMessage(NIM_MODIFY) on an existing icon is broken on Windows CE. + // So we need to call updateIcon_sys() which creates a new icon handle. + updateIcon_sys(); +#else + if (!sys) + return; + + sys->trayMessage(NIM_MODIFY); +#endif +} + +bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys() +{ + return true; +} + +QT_END_NAMESPACE + +#endif |