kdecore Library API Documentation

kwin.cpp

00001 /* This file is part of the KDE libraries
00002     Copyright (C) 1999 Matthias Ettrich (ettrich@kde.org)
00003 
00004     $Id: kwin.cpp,v 1.58.4.1 2003/02/21 16:06:30 wgreven Exp $
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to
00018     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019     Boston, MA 02111-1307, USA.
00020 */
00021 
00022 #include <stdlib.h>
00023 #include <unistd.h>
00024 
00025 #ifdef HAVE_SYSENT_H
00026 #include <sysent.h>
00027 #endif
00028 
00029 #include <qapplication.h>
00030 #include <qbitmap.h>
00031 #include <qimage.h>
00032 #include <qwhatsthis.h>
00033 #include <qcstring.h>
00034 
00035 #ifndef Q_WS_QWS
00036 #include "kwin.h"
00037 #include "kapplication.h"
00038 
00039 #include <kglobal.h>
00040 #include <kiconloader.h>
00041 
00042 #include <kdatastream.h>
00043 #include <klocale.h>
00044 #include <dcopclient.h>
00045 #include <kstartupinfo.h>
00046 
00047 #include <X11/Xlib.h>
00048 #include <X11/Xatom.h>
00049 #include <X11/Xutil.h>
00050 
00051 #include "netwm.h"
00052 
00053 static bool atoms_created = FALSE;
00054 extern Atom qt_wm_protocols;
00055 extern Atom qt_wm_state;
00056 
00057 // Fix for --enable-final. This gets undefined at the end of this file.
00058 #ifndef None
00059 #define None    0L
00060 #endif
00061 
00062 Atom net_wm_context_help;
00063 static Atom kde_wm_change_state;
00064 void kwin_net_create_atoms() {
00065     if (!atoms_created){
00066         const int max = 20;
00067         Atom* atoms[max];
00068         const char* names[max];
00069         Atom atoms_return[max];
00070         int n = 0;
00071 
00072         atoms[n] = &net_wm_context_help;
00073         names[n++] = "_NET_WM_CONTEXT_HELP";
00074 
00075         atoms[n] = &kde_wm_change_state;
00076         names[n++] = "_KDE_WM_CHANGE_STATE";
00077 
00078         // we need a const_cast for the shitty X API
00079         XInternAtoms( qt_xdisplay(), const_cast<char**>(names), n, FALSE, atoms_return );
00080         for (int i = 0; i < n; i++ )
00081             *atoms[i] = atoms_return[i];
00082 
00083         atoms_created = True;
00084     }
00085 }
00086 
00087 /*
00088   Sends a client message to the ROOT window.
00089  */
00090 static void sendClientMessageToRoot(Window w, Atom a, long x, long y = 0, long z = 0 ){
00091   XEvent ev;
00092   long mask;
00093 
00094   memset(&ev, 0, sizeof(ev));
00095   ev.xclient.type = ClientMessage;
00096   ev.xclient.window = w;
00097   ev.xclient.message_type = a;
00098   ev.xclient.format = 32;
00099   ev.xclient.data.l[0] = x;
00100   ev.xclient.data.l[1] = y;
00101   ev.xclient.data.l[2] = z;
00102   mask = SubstructureRedirectMask;
00103   XSendEvent(qt_xdisplay(), qt_xrootwin(), False, mask, &ev);
00104 }
00105 
00106 /*
00107   Send a client message to window w
00108  */
00109 static void sendClientMessage(Window w, Atom a, long x){
00110   XEvent ev;
00111   long mask;
00112 
00113   memset(&ev, 0, sizeof(ev));
00114   ev.xclient.type = ClientMessage;
00115   ev.xclient.window = w;
00116   ev.xclient.message_type = a;
00117   ev.xclient.format = 32;
00118   ev.xclient.data.l[0] = x;
00119   ev.xclient.data.l[1] = CurrentTime;
00120   mask = 0L;
00121   if (w == qt_xrootwin())
00122     mask = SubstructureRedirectMask;        /* magic! */
00123   XSendEvent(qt_xdisplay(), w, False, mask, &ev);
00124 }
00125 
00126 class ContextWidget : public QWidget
00127 {
00128 public:
00129     ContextWidget()
00130         : QWidget(0,0)
00131     {
00132         kwin_net_create_atoms();
00133         kapp->installX11EventFilter( this );
00134         QWhatsThis::enterWhatsThisMode();
00135         QCursor c = *QApplication::overrideCursor();
00136         QWhatsThis::leaveWhatsThisMode();
00137         XGrabPointer( qt_xdisplay(), qt_xrootwin(), TRUE,
00138                       (uint)( ButtonPressMask | ButtonReleaseMask |
00139                               PointerMotionMask | EnterWindowMask |
00140                               LeaveWindowMask ),
00141                       GrabModeAsync, GrabModeAsync,
00142                       None, c.handle(), CurrentTime );
00143         qApp->enter_loop();
00144     }
00145 
00146 
00147     bool x11Event( XEvent * ev)
00148     {
00149         if ( ev->type == ButtonPress && ev->xbutton.button == Button1 ) {
00150             XUngrabPointer( qt_xdisplay(), ev->xbutton.time );
00151             Window root;
00152             Window child = qt_xrootwin();
00153             int root_x, root_y, lx, ly;
00154             uint state;
00155             Window w;
00156             do {
00157                 w = child;
00158                 XQueryPointer( qt_xdisplay(), w, &root, &child,
00159                                &root_x, &root_y, &lx, &ly, &state );
00160             } while  ( child != None && child != w );
00161 
00162             ::sendClientMessage(w, qt_wm_protocols, net_wm_context_help);
00163             XEvent e = *ev;
00164             e.xbutton.window = w;
00165             e.xbutton.subwindow = w;
00166             e.xbutton.x = lx;
00167             e.xbutton.y = ly;
00168             XSendEvent( qt_xdisplay(), w, TRUE, ButtonPressMask, &e );
00169             qApp->exit_loop();
00170             return TRUE;
00171         }
00172         return FALSE;
00173     }
00174 };
00175 
00176 void KWin::invokeContextHelp()
00177 {
00178     ContextWidget w;
00179 }
00180 
00181 void KWin::setSystemTrayWindowFor( WId trayWin, WId forWin )
00182 {
00183     NETWinInfo info( qt_xdisplay(), trayWin, qt_xrootwin(), 0 );
00184     if ( !forWin )
00185         forWin = qt_xrootwin();
00186     info.setKDESystemTrayWinFor( forWin );
00187 }
00188 void KWin::setActiveWindow( WId win)
00189 {
00190     NETRootInfo info( qt_xdisplay(), 0 );
00191     info.setActiveWindow( win );
00192 }
00193 
00194 KWin::Info KWin::info( WId win )
00195 {
00196     Info w;
00197     NETWinInfo inf( qt_xdisplay(), win, qt_xrootwin(),
00198                     NET::WMState |
00199                     NET::WMStrut |
00200                     NET::WMWindowType |
00201                     NET::WMName |
00202                     NET::WMVisibleName |
00203                     NET::WMDesktop |
00204                     NET::WMPid |
00205                     NET::WMKDEFrameStrut |
00206                     NET::XAWMState
00207                     );
00208 
00209     w.win = win;
00210     w.state = inf.state();
00211     w.mappingState = inf.mappingState();
00212     w.strut = inf.strut();
00213     w.windowType = inf.windowType();
00214     if ( inf.name() ) {
00215         w.name = QString::fromUtf8( inf.name() );
00216     } else {
00217         char* c = 0;
00218         if ( XFetchName( qt_xdisplay(), win, &c ) != 0 ) {
00219             w.name = QString::fromLocal8Bit( c );
00220             XFree( c );
00221         }
00222     }
00223     if ( inf.visibleName() )
00224         w.visibleName = QString::fromUtf8( inf.visibleName() );
00225     else
00226         w.visibleName = w.name;
00227 
00228     w.desktop = inf.desktop();
00229     w.onAllDesktops = inf.desktop() == NETWinInfo::OnAllDesktops;
00230     w.pid = inf.pid();
00231     NETRect frame, geom;
00232     inf.kdeGeometry( frame, geom );
00233     w.geometry.setRect( geom.pos.x, geom.pos.y, geom.size.width, geom.size.height );
00234     w.frameGeometry.setRect( frame.pos.x, frame.pos.y, frame.size.width, frame.size.height );
00235     return w;
00236 }
00237 
00238 QPixmap KWin::icon( WId win, int width, int height, bool scale )
00239 {
00240     QPixmap result;
00241     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMIcon );
00242     NETIcon ni = info.icon( width, height );
00243     if ( ni.data && ni.size.width > 0 && ni.size.height > 0 ) {
00244         QImage img( (uchar*) ni.data, (int) ni.size.width, (int) ni.size.height, 32, 0, 0, QImage::IgnoreEndian );
00245         img.setAlphaBuffer( TRUE );
00246         if ( scale && width > 0 && height > 0 &&img.size() != QSize( width, height ) && !img.isNull() )
00247             img = img.smoothScale( width, height );
00248         if ( !img.isNull() )
00249             result.convertFromImage( img );
00250         return result;
00251     }
00252 
00253     Pixmap p = None;
00254     Pixmap p_mask = None;
00255 
00256     XWMHints *hints = XGetWMHints(qt_xdisplay(), win );
00257     if (hints && (hints->flags & IconPixmapHint)){
00258         p = hints->icon_pixmap;
00259     }
00260     if (hints && (hints->flags & IconMaskHint)){
00261         p_mask = hints->icon_mask;
00262     }
00263     if (hints)
00264         XFree((char*)hints);
00265 
00266     if (p != None){
00267         Window root;
00268         int x, y;
00269         unsigned int w = 0;
00270         unsigned int h = 0;
00271         unsigned int border_w, depth;
00272         XGetGeometry(qt_xdisplay(), p, &root,
00273                      &x, &y, &w, &h, &border_w, &depth);
00274         if (w > 0 && h > 0){
00275             QPixmap pm(w, h, depth);
00276             // Always detach before doing something behind QPixmap's back.
00277             pm.detach();
00278             XCopyArea(qt_xdisplay(), p, pm.handle(),
00279                       qt_xget_temp_gc(qt_xscreen(), depth==1),
00280                       0, 0, w, h, 0, 0);
00281             if (p_mask != None){
00282                 QBitmap bm(w, h);
00283                 XCopyArea(qt_xdisplay(), p_mask, bm.handle(),
00284                           qt_xget_temp_gc(qt_xscreen(), true),
00285                           0, 0, w, h, 0, 0);
00286                 pm.setMask(bm);
00287             }
00288             if ( scale && width > 0 && height > 0 && !pm.isNull() &&
00289                  ( (int) w != width || (int) h != height) ){
00290                 result.convertFromImage( pm.convertToImage().smoothScale( width, height ) );
00291             } else {
00292                 result = pm;
00293             }
00294         }
00295     }
00296 
00297     // Try to load the icon from the classhint if the app didn't specify
00298     // its own:
00299     if( result.isNull() ) {
00300         int iconWidth;
00301 
00302             // Since width can be any arbitrary size, but the icons cannot,
00303             // take the nearest value for best results (ignoring 22 pixel
00304             // icons as they don't exist for apps):
00305         if( width < 24 )
00306             iconWidth = 16;
00307         else if( width < 40 )
00308             iconWidth = 32;
00309         else
00310             iconWidth = 48;
00311 
00312         XClassHint      hint;
00313         if( XGetClassHint( qt_xdisplay(), win, &hint ) ) {
00314             QString className = hint.res_class;
00315 
00316             QPixmap pm = KGlobal::instance()->iconLoader()->loadIcon( className.lower(), KIcon::Small, iconWidth,
00317                                                                       KIcon::DefaultState, 0, true );
00318             if( scale && !pm.isNull() )
00319                 result.convertFromImage( pm.convertToImage().smoothScale( width, height ) );
00320             else
00321                 result = pm;
00322 
00323             XFree( hint.res_name );
00324             XFree( hint.res_class );
00325         }
00326 
00327         // If the icon is still a null pixmap, load the 'xapp' icon
00328         // as a last resort:
00329         if ( result.isNull() ) {
00330             QPixmap pm = KGlobal::instance()->iconLoader()->loadIcon(  "xapp", KIcon::Small, iconWidth,
00331                                                                        KIcon::DefaultState, 0, true );
00332             if( scale && !pm.isNull() )
00333                 result.convertFromImage( pm.convertToImage().smoothScale( width, height ) );
00334             else
00335                 result = pm;
00336         }
00337     }
00338     return result;
00339 }
00340 
00341 void KWin::setIcons( WId win, const QPixmap& icon, const QPixmap& miniIcon )
00342 {
00343     if ( icon.isNull() )
00344         return;
00345     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
00346     QImage img = icon.convertToImage().convertDepth( 32 );
00347     NETIcon ni;
00348     ni.size.width = img.size().width();
00349     ni.size.height = img.size().height();
00350     ni.data = (unsigned char *) img.bits();
00351     info.setIcon( ni, true );
00352     if ( miniIcon.isNull() )
00353         return;
00354     img = miniIcon.convertToImage().convertDepth( 32 );
00355     ni.size.width = img.size().width();
00356     ni.size.height = img.size().height();
00357     ni.data = (unsigned char *) img.bits();
00358     info.setIcon( ni, false );
00359 }
00360 
00361 void KWin::setType( WId win, NET::WindowType windowType )
00362 {
00363     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
00364     info.setWindowType( windowType );
00365 }
00366 
00367 void KWin::setState( WId win, unsigned long state )
00368 {
00369     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMState );
00370     info.setState( state, state );
00371 }
00372 
00373 void KWin::clearState( WId win, unsigned long state )
00374 {
00375     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMState );
00376     info.setState( 0, state );
00377 }
00378 
00379 void KWin::setOnAllDesktops( WId win, bool b )
00380 {
00381     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMDesktop );
00382     if ( b )
00383         info.setDesktop( NETWinInfo::OnAllDesktops );
00384     else if ( info.desktop()  == NETWinInfo::OnAllDesktops ) {
00385         NETRootInfo rinfo( qt_xdisplay(), NET::CurrentDesktop );
00386         info.setDesktop( rinfo.currentDesktop() );
00387     }
00388 }
00389 
00390 void KWin::setOnDesktop( WId win, int desktop )
00391 {
00392     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMDesktop );
00393     info.setDesktop( desktop );
00394 }
00395 
00396 
00397 QString KWin::Info::visibleNameWithState() const
00398 {
00399     QString s = visibleName;
00400     if ( isIconified() ) {
00401         s.prepend('(');
00402         s.append(')');
00403     }
00404     return s;
00405 }
00406 
00407 
00408 void KWin::setStrut( WId win, int left, int right, int top, int bottom )
00409 {
00410     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
00411     NETStrut strut;
00412     strut.left = left;
00413     strut.right = right;
00414     strut.top = top;
00415     strut.bottom = bottom;
00416     info.setStrut( strut );
00417 }
00418 
00419 int KWin::currentDesktop()
00420 {
00421     if (!qt_xdisplay())
00422       return 0;
00423     NETRootInfo info( qt_xdisplay(), NET::CurrentDesktop );
00424     return info.currentDesktop();
00425 }
00426 
00427 int KWin::numberOfDesktops()
00428 {
00429     if (!qt_xdisplay())
00430       return 0;
00431     NETRootInfo info( qt_xdisplay(), NET::NumberOfDesktops );
00432     return info.numberOfDesktops();
00433 }
00434 
00435 void KWin::setCurrentDesktop( int desktop )
00436 {
00437     NETRootInfo info( qt_xdisplay(), NET::CurrentDesktop );
00438     info.setCurrentDesktop( desktop );
00439 }
00440 
00441 
00442 void KWin::iconifyWindow( WId win, bool animation)
00443 {
00444     if ( !animation )
00445         sendClientMessageToRoot( win, kde_wm_change_state, IconicState, 1 );
00446     XIconifyWindow( qt_xdisplay(), win, qt_xscreen() );
00447 }
00448 
00449 
00450 void KWin::deIconifyWindow( WId win, bool animation )
00451 {
00452     if ( !animation )
00453         sendClientMessageToRoot( win, kde_wm_change_state, NormalState, 1 );
00454     XMapWindow( qt_xdisplay(), win );
00455 }
00456 
00457 void KWin::appStarted()
00458 {
00459     KStartupInfo::appStarted();
00460 }
00461 
00462 // Fix for --enable-final. This gets defined at the top of this file.
00463 #undef  None
00464 #endif
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 12:46:59 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001