systemtray.cpp
00001 /*************************************************************************** 00002 copyright (C) 2003 Adam Geitgey <adam@rootnode.org> 00003 2003 Sven Leiber <s.leiber@web.de> 00004 2000-2001 Matthias Ettrich <ettrich@kde.org> 00005 2000-2001 Matthias Elter <elter@kde.org> 00006 2001 Carsten Pfeiffer <pfeiffer@kde.org> 00007 2001 Martijn Klingens <mklingens@yahoo.com> 00008 ***************************************************************************/ 00009 00010 /*************************************************************************** 00011 * * 00012 * This program is free software; you can redistribute it and/or modify * 00013 * it under the terms of the GNU General Public License as published by * 00014 * the Free Software Foundation; either version 2 of the License, or * 00015 * (at your option) any later version. * 00016 * * 00017 ***************************************************************************/ 00018 00019 #include "systemtray.h" 00020 00021 00022 #include <tqobject.h> 00023 #include <kiconloader.h> 00024 #include <klocale.h> 00025 #include <kwinmodule.h> 00026 #include <kmessagebox.h> 00027 #include <kdebug.h> 00028 #include <kwin.h> 00029 00030 #include <tqpopupmenu.h> 00031 #include <tqdragobject.h> 00032 #include <tqlayout.h> 00033 #include <tqstringlist.h> 00034 #include <tqpixmap.h> 00035 00036 #include <X11/Xlib.h> 00037 00038 Systemtray::Systemtray(TQWidget* parent) 00039 : TQWidget(parent,0,0) 00040 { 00041 setBackgroundOrigin(ParentOrigin); 00042 setBackgroundMode(FixedPixmap); 00043 m_Wins.setAutoDelete(true); 00044 } 00045 00046 00047 Systemtray::~Systemtray() 00048 { 00049 m_Wins.clear(); 00050 } 00051 00052 int Systemtray::getTraySize() { 00053 00054 return (int) kwin_module->systemTrayWindows().size(); 00055 } 00056 00057 void Systemtray::updateBackgroundPixmap ( const TQPixmap & pixmap) { 00058 QXEmbed *emb; 00059 setPaletteBackgroundPixmap (pixmap); 00060 for (emb = m_Wins.first(); emb != 0L; emb = m_Wins.next()) { 00061 00062 //Stupid stupid stupid work around for annoying bug 00063 //QXEmbed ignores setBackgroundOrigin(AncestorOrigin).... 00064 TQPixmap bug = TQPixmap(emb->size()); 00065 bitBlt(TQT_TQPAINTDEVICE(&bug), 0, 0, TQT_TQPAINTDEVICE(const_cast<TQPixmap*>(&pixmap)), emb->parentWidget()->x()+emb->x(), emb->parentWidget()->y()+emb->y(), emb->width(), emb->height(),TQt::CopyROP, false); 00066 emb->setPaletteBackgroundPixmap (bug); 00067 00068 } 00069 00070 TQPoint topPoint = mapToGlobal(TQPoint(0,0)); 00071 Window hack = XCreateSimpleWindow(qt_xdisplay(), winId(), 0,0, width(), height(), 0, 0, 0); 00072 XRaiseWindow(qt_xdisplay(), hack); 00073 XMapWindow(qt_xdisplay(), hack); 00074 XUnmapWindow(qt_xdisplay(), hack); 00075 XDestroyWindow(qt_xdisplay(), hack); 00076 } 00077 00078 void Systemtray::initSystray( void ) 00079 { 00080 bool existing = false; 00081 //bool content = false; 00082 Display *display = qt_xdisplay(); 00083 no_of_systray_windows = 0; 00084 00085 kwin_module = new KWinModule(); 00086 systemTrayWindows = kwin_module->systemTrayWindows(); 00087 TQValueList<WId>::ConstIterator end(systemTrayWindows.end()); 00088 for (TQValueList<WId>::ConstIterator it = systemTrayWindows.begin(); it!=end; ++it) 00089 { 00090 no_of_systray_windows++; 00091 QXEmbed *emb; 00092 00093 emb = new QXEmbed(this); 00094 emb->setBackgroundMode(FixedPixmap); 00095 00096 emb->setAutoDelete(false); 00097 00098 connect(emb, TQT_SIGNAL(embeddedWindowDestroyed()), TQT_SLOT(updateTrayWindows())); 00099 00100 m_Wins.append(emb); 00101 00102 emb->embed(*it); 00103 emb->resize(24, 24); 00104 emb->show(); 00105 existing = true; 00106 } 00107 00108 updateTrayWindows(); 00109 00110 connect(kwin_module, TQT_SIGNAL(systemTrayWindowAdded(WId)), TQT_SLOT(systemTrayWindowAdded(WId))); 00111 connect(kwin_module, TQT_SIGNAL(systemTrayWindowRemoved(WId)), TQT_SLOT(systemTrayWindowRemoved(WId))); 00112 00113 TQCString screenstr; 00114 screenstr.setNum(qt_xscreen()); 00115 TQCString trayatom = "_NET_SYSTEM_TRAY_S" + screenstr; 00116 00117 net_system_tray_selection = XInternAtom( display, trayatom, false ); 00118 net_system_tray_opcode = XInternAtom( display, "_NET_SYSTEM_TRAY_OPCODE", false ); 00119 00120 // Acquire system tray 00121 XSetSelectionOwner( display, 00122 net_system_tray_selection, 00123 winId(), 00124 CurrentTime ); 00125 00126 WId root = qt_xrootwin(); 00127 00128 if (XGetSelectionOwner(display, net_system_tray_selection) == winId()) 00129 { 00130 XClientMessageEvent xev; 00131 00132 xev.type = ClientMessage; 00133 xev.window = root; 00134 00135 xev.message_type = XInternAtom(display, "MANAGER", false); 00136 xev.format = 32; 00137 00138 xev.data.l[0] = CurrentTime; 00139 xev.data.l[1] = net_system_tray_selection; 00140 xev.data.l[2] = winId(); 00141 xev.data.l[3] = 0; /* Manager specific data */ 00142 xev.data.l[4] = 0; /* Manager specific data */ 00143 00144 XSendEvent( display, root, false, StructureNotifyMask, (XEvent *)&xev ); 00145 } 00146 } 00147 00148 void Systemtray::updateTrayWindows( void ) 00149 { 00150 QXEmbed *emb; 00151 00152 emb = m_Wins.first(); 00153 while ((emb = m_Wins.current()) != 0L) 00154 { 00155 WId wid = emb->embeddedWinId(); 00156 if ((wid == 0) || !kwin_module->systemTrayWindows().contains(wid) ) 00157 m_Wins.remove(emb); 00158 else 00159 m_Wins.next(); 00160 } 00161 layoutSystray(); 00162 } 00163 void Systemtray::layoutSystray() 00164 { 00165 int i = 0, a = 0; 00166 00167 QXEmbed* emb; 00168 int x = 0; 00169 int count = 0; 00170 00171 //How many systray icons can fit on a line? 00172 int aa = width() / 24; 00173 00174 if(aa < 1) 00175 { 00176 /* The place is to small to display a icon we make than one line with 00177 icons that we display at the top */ 00178 aa = 1; 00179 } 00180 00181 for (emb = m_Wins.first(); emb != 0L; emb = m_Wins.next()) { 00182 x = 2+i*24; 00183 00184 emb->move(a*24, x); 00185 a++; 00186 00187 if(a+1 > aa) { 00188 a = 0; 00189 i++; 00190 } 00191 00192 count++; 00193 emb->repaint(); 00194 } 00195 } 00196 00197 void Systemtray::systemTrayWindowAdded( WId w ) 00198 { 00199 //bool content = false; 00200 QXEmbed *emb; 00201 no_of_systray_windows++; 00202 emit updated(); 00203 00204 emb = new QXEmbed(this); 00205 00206 emb->setAutoDelete(false); 00207 //emb->setBackgroundMode(X11ParentRelative); 00208 emb->setBackgroundMode(FixedPixmap); 00209 connect(emb, TQT_SIGNAL(embeddedWindowDestroyed()), TQT_SLOT(updateTrayWindows())); 00210 m_Wins.append(emb); 00211 00212 emb->embed(w); 00213 emb->resize(24, 24); 00214 emb->show(); 00215 00216 layoutSystray(); 00217 } 00218 00219 void Systemtray::systemTrayWindowRemoved(WId) 00220 { 00221 no_of_systray_windows--; 00222 emit updated(); 00223 updateTrayWindows(); 00224 } 00225 00226 int Systemtray::getCurrentWindowCount() 00227 { 00228 return no_of_systray_windows; 00229 } 00230 00231 #include "systemtray.moc"