| # kdeui Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# 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

This file is part of the documentation for kdeui Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:20:15 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003