kdeui Library API Documentation

kdetrayproxy.cpp

00001 /* 00002 * Copyright (C) 2004 Lubos Lunak <l.lunak@kde.org> 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 * 00018 */ 00019 00020 #include "kdetrayproxy.h" 00021 00022 #include <kapplication.h> 00023 #include <kdebug.h> 00024 #include <netwm.h> 00025 #include <X11/Xlib.h> 00026 #include <sys/select.h> 00027 #include <sys/time.h> 00028 #include <sys/types.h> 00029 #include <unistd.h> 00030 #include <assert.h> 00031 00032 KDETrayProxy::KDETrayProxy() 00033 : selection( makeSelectionAtom()) 00034 { 00035 connect( &selection, SIGNAL( newOwner( Window )), SLOT( newOwner( Window ))); 00036 connect( &module, SIGNAL( windowAdded( WId )), SLOT( windowAdded( WId ))); 00037 selection.owner(); 00038 for( QValueList< WId >::ConstIterator it = module.windows().begin(); 00039 it != module.windows().end(); 00040 ++it ) 00041 windowAdded( *it ); 00042 kapp->installX11EventFilter( this ); // XSelectInput( StructureNotifyMask ) on windows is done by KWinModule 00043 // kdDebug() << "Init done" << endl; 00044 } 00045 00046 Atom KDETrayProxy::makeSelectionAtom() 00047 { 00048 return XInternAtom( qt_xdisplay(), "_NET_SYSTEM_TRAY_S" + QCString().setNum( qt_xscreen()), False ); 00049 } 00050 00051 extern Time qt_x_time; 00052 00053 void KDETrayProxy::windowAdded( WId w ) 00054 { 00055 NETWinInfo ni( qt_xdisplay(), w, qt_xrootwin(), NET::WMKDESystemTrayWinFor ); 00056 WId trayWinFor = ni.kdeSystemTrayWinFor(); 00057 if ( !trayWinFor ) // not a KDE tray window 00058 return; 00059 // kdDebug() << "New tray window:" << w << endl; 00060 if( !tray_windows.contains( w )) 00061 tray_windows.append( w ); 00062 withdrawWindow( w ); 00063 // window will be removed from pending_windows when after docked 00064 if( !pending_windows.contains( w )) 00065 pending_windows.append( w ); 00066 docked_windows.remove( w ); 00067 Window owner = selection.owner(); 00068 if( owner == None ) // no tray owner, sorry 00069 { 00070 // kdDebug() << "No owner, left in pending" << endl; 00071 return; 00072 } 00073 dockWindow( w, owner ); 00074 } 00075 00076 void KDETrayProxy::newOwner( Window owner ) 00077 { 00078 // kdDebug() << "New owner:" << owner << endl; 00079 for( QValueList< Window >::ConstIterator it = pending_windows.begin(); 00080 it != pending_windows.end(); 00081 ++it ) 00082 dockWindow( *it, owner ); 00083 // remove from pending_windows only in windowRemoved(), after it's really docked 00084 } 00085 00086 bool KDETrayProxy::x11Event( XEvent* e ) 00087 { 00088 if( tray_windows.isEmpty()) 00089 return false; 00090 if( e->type == DestroyNotify && tray_windows.contains( e->xdestroywindow.window )) 00091 { 00092 tray_windows.remove( e->xdestroywindow.window ); 00093 pending_windows.remove( e->xdestroywindow.window ); 00094 docked_windows.remove( e->xdestroywindow.window ); 00095 } 00096 if( e->type == ReparentNotify && tray_windows.contains( e->xreparent.window )) 00097 { 00098 if( e->xreparent.parent == qt_xrootwin()) 00099 { 00100 if( !docked_windows.contains( e->xreparent.window ) || e->xreparent.serial >= docked_windows[ e->xreparent.window ] ) 00101 { 00102 // kdDebug() << "Window released:" << e->xreparent.window << endl; 00103 docked_windows.remove( e->xreparent.window ); 00104 if( !pending_windows.contains( e->xreparent.window )) 00105 pending_windows.append( e->xreparent.window ); 00106 } 00107 } 00108 else 00109 { 00110 // kdDebug() << "Window away:" << e->xreparent.window << ":" << e->xreparent.parent << endl; 00111 pending_windows.remove( e->xreparent.window ); 00112 } 00113 } 00114 if( e->type == UnmapNotify && tray_windows.contains( e->xunmap.window )) 00115 { 00116 if( docked_windows.contains( e->xunmap.window ) && e->xunmap.serial >= docked_windows[ e->xunmap.window ] ) 00117 { 00118 // kdDebug() << "Window unmapped:" << e->xunmap.window << endl; 00119 XReparentWindow( qt_xdisplay(), e->xunmap.window, qt_xrootwin(), 0, 0 ); 00120 // ReparentNotify will take care of the rest 00121 } 00122 } 00123 return false; 00124 } 00125 00126 void KDETrayProxy::dockWindow( Window w, Window owner ) 00127 { 00128 // kdDebug() << "Docking " << w << " into " << owner << endl; 00129 docked_windows[ w ] = XNextRequest( qt_xdisplay()); 00130 static Atom prop = XInternAtom( qt_xdisplay(), "_XEMBED_INFO", False ); 00131 long data[ 2 ] = { 0, 1 }; 00132 XChangeProperty( qt_xdisplay(), w, prop, prop, 32, PropModeReplace, (unsigned char*)data, 2 ); 00133 XSizeHints hints; 00134 hints.flags = PMinSize | PMaxSize; 00135 hints.min_width = 24; 00136 hints.max_width = 24; 00137 hints.min_height = 24; 00138 hints.max_height = 24; 00139 XSetWMNormalHints( qt_xdisplay(), w, &hints ); 00140 // kxerrorhandler ? 00141 XEvent ev; 00142 memset(&ev, 0, sizeof( ev )); 00143 static Atom atom = XInternAtom( qt_xdisplay(), "_NET_SYSTEM_TRAY_OPCODE", False ); 00144 ev.xclient.type = ClientMessage; 00145 ev.xclient.window = owner; 00146 ev.xclient.message_type = atom; 00147 ev.xclient.format = 32; 00148 ev.xclient.data.l[ 0 ] = qt_x_time; 00149 ev.xclient.data.l[ 1 ] = 0; // SYSTEM_TRAY_REQUEST_DOCK 00150 ev.xclient.data.l[ 2 ] = w; 00151 ev.xclient.data.l[ 3 ] = 0; // unused 00152 ev.xclient.data.l[ 4 ] = 0; // unused 00153 XSendEvent( qt_xdisplay(), owner, False, NoEventMask, &ev ); 00154 } 00155 00156 void KDETrayProxy::withdrawWindow( Window w ) 00157 { 00158 XWithdrawWindow( qt_xdisplay(), w, qt_xscreen()); 00159 static Atom wm_state = XInternAtom( qt_xdisplay(), "WM_STATE", False ); 00160 for(;;) 00161 { 00162 Atom type; 00163 int format; 00164 unsigned long length, after; 00165 unsigned char *data; 00166 int r = XGetWindowProperty( qt_xdisplay(), w, wm_state, 0, 2, 00167 False, AnyPropertyType, &type, &format, 00168 &length, &after, &data ); 00169 bool withdrawn = true; 00170 if ( r == Success && data && format == 32 ) 00171 { 00172 withdrawn = ( *( long* )data == WithdrawnState ); 00173 XFree( (char *)data ); 00174 } 00175 if( withdrawn ) 00176 return; // ---> 00177 struct timeval tm; 00178 tm.tv_sec = 0; 00179 tm.tv_usec = 10 * 1000; // 10ms 00180 select(0, NULL, NULL, NULL, &tm); 00181 } 00182 } 00183 00184 #include "kdetrayproxy.moc" 00185 00186 #if 0 00187 #include <kcmdlineargs.h> 00188 int main( int argc, char* argv[] ) 00189 { 00190 KCmdLineArgs::init( argc, argv, "a", "b", "c", "d" ); 00191 KApplication app( false ); // no styles 00192 app.disableSessionManagement(); 00193 KDETrayProxy proxy; 00194 return app.exec(); 00195 } 00196 #endif
KDE Logo
This file is part of the documentation for kdeui Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 22:56:22 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003