kwin.cpp Source File (kdecore Library)

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

# 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

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