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.97 2003/12/18 12:16:30 lunakl 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 #include "config.h"
00036 //#ifndef Q_WS_QWS
00037 #include "kwin.h"
00038 #include "kapplication.h"
00039 
00040 #include <kglobal.h>
00041 #include <kiconloader.h>
00042 #include <kdebug.h>
00043 
00044 #include <kdatastream.h>
00045 #include <klocale.h>
00046 #include <dcopclient.h>
00047 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00048 #include <kstartupinfo.h> // schroder not needed at all ?
00049 #include <kxerrorhandler.h> // schroder
00050 
00051 #include <X11/Xlib.h> // schroder
00052 #include <X11/Xatom.h> // schroder
00053 #include <X11/Xutil.h> // schroder
00054 
00055 #include "netwm.h" // schroder
00056 
00057 static bool atoms_created = false;
00058 extern Atom qt_wm_protocols;
00059 extern Time qt_x_time;
00060 extern Time qt_x_user_time;
00061 
00062 static Atom net_wm_context_help;
00063 static Atom kde_wm_change_state;
00064 static 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 #endif
00087 
00088 /*
00089   Sends a client message to the ROOT window.
00090  */
00091 static void sendClientMessageToRoot(Window w, Atom a, long x, long y = 0, long z = 0 ){
00092 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00093   XEvent ev;
00094   long mask;
00095 
00096   memset(&ev, 0, sizeof(ev));
00097   ev.xclient.type = ClientMessage;
00098   ev.xclient.window = w;
00099   ev.xclient.message_type = a;
00100   ev.xclient.format = 32;
00101   ev.xclient.data.l[0] = x;
00102   ev.xclient.data.l[1] = y;
00103   ev.xclient.data.l[2] = z;
00104   mask = SubstructureRedirectMask;
00105   XSendEvent(qt_xdisplay(), qt_xrootwin(), False, mask, &ev);
00106 #endif
00107 }
00108 
00109 /*
00110   Send a client message to window w
00111  */
00112 static void sendClientMessage(Window w, Atom a, long x){
00113 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00114   XEvent ev;
00115   long mask;
00116 
00117   memset(&ev, 0, sizeof(ev));
00118   ev.xclient.type = ClientMessage;
00119   ev.xclient.window = w;
00120   ev.xclient.message_type = a;
00121   ev.xclient.format = 32;
00122   ev.xclient.data.l[0] = x;
00123   ev.xclient.data.l[1] = CurrentTime;
00124   mask = 0L;
00125   if (w == qt_xrootwin())
00126     mask = SubstructureRedirectMask;        /* magic! */
00127   XSendEvent(qt_xdisplay(), w, False, mask, &ev);
00128 #endif
00129 }
00130 
00131 namespace
00132 {
00133 class ContextWidget : public QWidget
00134 {
00135 public:
00136     ContextWidget();
00137     virtual bool x11Event( XEvent * ev);
00138 };
00139 
00140 ContextWidget::ContextWidget()
00141     : QWidget(0,0)
00142     {
00143 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00144     kwin_net_create_atoms();
00145     kapp->installX11EventFilter( this );
00146     QWhatsThis::enterWhatsThisMode();
00147     QCursor c = *QApplication::overrideCursor();
00148     QWhatsThis::leaveWhatsThisMode();
00149     XGrabPointer( qt_xdisplay(), qt_xrootwin(), true,
00150               (uint)( ButtonPressMask | ButtonReleaseMask |
00151                   PointerMotionMask | EnterWindowMask |
00152                   LeaveWindowMask ),
00153               GrabModeAsync, GrabModeAsync,
00154               None, c.handle(), CurrentTime );
00155     qApp->enter_loop();
00156 #endif
00157     }
00158 
00159 
00160 bool ContextWidget::x11Event( XEvent * ev)
00161     {
00162 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00163     if ( ev->type == ButtonPress && ev->xbutton.button == Button1 ) {
00164         XUngrabPointer( qt_xdisplay(), ev->xbutton.time );
00165         Window root;
00166         Window child = qt_xrootwin();
00167         int root_x, root_y, lx, ly;
00168         uint state;
00169         Window w;
00170         do {
00171         w = child;
00172         XQueryPointer( qt_xdisplay(), w, &root, &child,
00173                    &root_x, &root_y, &lx, &ly, &state );
00174         } while  ( child != None && child != w );
00175 
00176         ::sendClientMessage(w, qt_wm_protocols, net_wm_context_help);
00177         XEvent e = *ev;
00178         e.xbutton.window = w;
00179         e.xbutton.subwindow = w;
00180         e.xbutton.x = lx;
00181         e.xbutton.y = ly;
00182         XSendEvent( qt_xdisplay(), w, true, ButtonPressMask, &e );
00183         qApp->exit_loop();
00184         return true;
00185     }
00186     return false;
00187 #endif
00188     }
00189 } // namespace
00190 
00191 void KWin::invokeContextHelp()
00192 {
00193     ContextWidget w;
00194 }
00195 
00196 void KWin::setSystemTrayWindowFor( WId trayWin, WId forWin )
00197 {
00198 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00199     NETWinInfo info( qt_xdisplay(), trayWin, qt_xrootwin(), 0 );
00200     if ( !forWin )
00201     forWin = qt_xrootwin();
00202     info.setKDESystemTrayWinFor( forWin );
00203 #endif
00204 }
00205 
00206 void KWin::activateWindow( WId win, long time )
00207 {
00208 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00209     NETRootInfo info( qt_xdisplay(), 0 );
00210     if( time == 0 )
00211         time = qt_x_user_time;
00212     info.setActiveWindow( win, NET::FromApplication, time,
00213         kapp->activeWindow() ? kapp->activeWindow()->winId() : 0 );
00214 #endif // Q_WS_X11 ...
00215 }
00216 
00217 void KWin::forceActiveWindow( WId win, long time )
00218 {
00219 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00220     NETRootInfo info( qt_xdisplay(), 0 );
00221     if( time == 0 )
00222         time = qt_x_time;
00223     info.setActiveWindow( win, NET::FromTool, time, 0 );
00224 #endif // Q_WS_X11 ...
00225 }
00226 
00227 void KWin::setActiveWindow( WId win )
00228 {
00229 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00230     NETRootInfo info( qt_xdisplay(), 0 );
00231     info.setActiveWindow( win, NET::FromUnknown, 0, 0 );
00232 #endif
00233 }
00234 
00235 void KWin::demandAttention( WId win, bool set )
00236 {
00237 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00238     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
00239     info.setState( set ? NET::DemandsAttention : 0, NET::DemandsAttention );
00240 #endif
00241 }
00242 
00243 void KWin::setUserTime( WId win, long time )
00244 {
00245 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00246     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
00247     info.setUserTime( time );
00248 #endif
00249 }
00250 
00251 KWin::WindowInfo KWin::windowInfo( WId win, unsigned long properties, unsigned long properties2 )
00252 {
00253     return WindowInfo( win, properties, properties2 );
00254 }
00255 
00256 
00257 WId KWin::transientFor( WId win )
00258 {
00259 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00260     KXErrorHandler handler; // ignore badwindow
00261     Window transient_for = None;
00262     if( XGetTransientForHint( qt_xdisplay(), win, &transient_for ))
00263         return transient_for;
00264     // XGetTransientForHint() did sync
00265     return None;
00266 #else
00267     return 0L;
00268 #endif
00269 }
00270 
00271 WId KWin::groupLeader( WId win )
00272 {
00273 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00274     KXErrorHandler handler; // ignore badwindow
00275     XWMHints *hints = XGetWMHints( qt_xdisplay(), win );
00276     Window window_group = None;
00277     if ( hints )
00278     {
00279         if( hints->flags & WindowGroupHint )
00280             window_group = hints->window_group;
00281         XFree( reinterpret_cast< char* >( hints ));
00282     }
00283     // XGetWMHints() did sync
00284     return window_group;
00285 #else
00286     return 0L;
00287 #endif
00288 }
00289 
00290 // this one is deprecated, KWin::WindowInfo should be used instead
00291 KWin::Info KWin::info( WId win )
00292 {
00293     Info w;
00294 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00295     NETWinInfo inf( qt_xdisplay(), win, qt_xrootwin(),
00296             NET::WMState |
00297             NET::WMStrut |
00298             NET::WMWindowType |
00299             NET::WMName |
00300             NET::WMVisibleName |
00301             NET::WMDesktop |
00302             NET::WMPid |
00303             NET::WMKDEFrameStrut |
00304             NET::XAWMState
00305             );
00306 
00307     w.win = win;
00308     w.state = inf.state();
00309     w.mappingState = inf.mappingState();
00310     w.strut = inf.strut();
00311     w.windowType = inf.windowType();
00312     if ( inf.name() ) {
00313     w.name = QString::fromUtf8( inf.name() );
00314     } else {
00315     char* c = 0;
00316     if ( XFetchName( qt_xdisplay(), win, &c ) != 0 ) {
00317         w.name = QString::fromLocal8Bit( c );
00318         XFree( c );
00319     }
00320     }
00321     if ( inf.visibleName() )
00322     w.visibleName = QString::fromUtf8( inf.visibleName() );
00323     else
00324     w.visibleName = w.name;
00325 
00326     w.desktop = inf.desktop();
00327     w.onAllDesktops = inf.desktop() == NETWinInfo::OnAllDesktops;
00328     w.pid = inf.pid();
00329     NETRect frame, geom;
00330     inf.kdeGeometry( frame, geom );
00331     w.geometry.setRect( geom.pos.x, geom.pos.y, geom.size.width, geom.size.height );
00332     w.frameGeometry.setRect( frame.pos.x, frame.pos.y, frame.size.width, frame.size.height );
00333 #endif
00334     return w;
00335 }
00336 
00337 QPixmap KWin::icon( WId win, int width, int height, bool scale )
00338 {
00339     return icon( win, width, height, scale, NETWM | WMHints | ClassHint | XApp );
00340 }
00341 
00342 
00343 QPixmap KWin::icon( WId win, int width, int height, bool scale, int flags )
00344 {
00345 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00346     KXErrorHandler handler; // ignore badwindow
00347 #endif
00348     QPixmap result;
00349 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00350     if( flags & NETWM ) {
00351         NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMIcon );
00352         NETIcon ni = info.icon( width, height );
00353         if ( ni.data && ni.size.width > 0 && ni.size.height > 0 ) {
00354             QImage img( (uchar*) ni.data, (int) ni.size.width, (int) ni.size.height, 32, 0, 0, QImage::IgnoreEndian );
00355         img.setAlphaBuffer( true );
00356         if ( scale && width > 0 && height > 0 &&img.size() != QSize( width, height ) && !img.isNull() )
00357             img = img.smoothScale( width, height );
00358         if ( !img.isNull() )
00359             result.convertFromImage( img );
00360         return result;
00361         }
00362     }
00363 
00364     if( flags & WMHints ) {
00365         Pixmap p = None;
00366         Pixmap p_mask = None;
00367 
00368         XWMHints *hints = XGetWMHints(qt_xdisplay(), win );
00369         if (hints && (hints->flags & IconPixmapHint)){
00370             p = hints->icon_pixmap;
00371         }
00372         if (hints && (hints->flags & IconMaskHint)){
00373         p_mask = hints->icon_mask;
00374         }
00375         if (hints)
00376         XFree((char*)hints);
00377 
00378         if (p != None){
00379         Window root;
00380         int x, y;
00381         unsigned int w = 0;
00382         unsigned int h = 0;
00383             unsigned int border_w, depth;
00384         XGetGeometry(qt_xdisplay(), p, &root,
00385                  &x, &y, &w, &h, &border_w, &depth);
00386         if (w > 0 && h > 0){
00387             QPixmap pm(w, h, depth);
00388             // Always detach before doing something behind QPixmap's back.
00389             pm.detach();
00390             XCopyArea(qt_xdisplay(), p, pm.handle(),
00391                   qt_xget_temp_gc(qt_xscreen(), depth==1),
00392                   0, 0, w, h, 0, 0);
00393             if (p_mask != None){
00394                 QBitmap bm(w, h);
00395             XCopyArea(qt_xdisplay(), p_mask, bm.handle(),
00396                   qt_xget_temp_gc(qt_xscreen(), true),
00397                   0, 0, w, h, 0, 0);
00398             pm.setMask(bm);
00399             }
00400             if ( scale && width > 0 && height > 0 && !pm.isNull() &&
00401              ( (int) w != width || (int) h != height) ){
00402             result.convertFromImage( pm.convertToImage().smoothScale( width, height ) );
00403             } else {
00404             result = pm;
00405             }
00406         }
00407         }
00408     }
00409 
00410     // Since width can be any arbitrary size, but the icons cannot,
00411     // take the nearest value for best results (ignoring 22 pixel
00412     // icons as they don't exist for apps):
00413     int iconWidth;
00414     if( width < 24 )
00415         iconWidth = 16;
00416     else if( width < 40 )
00417         iconWidth = 32;
00418     else
00419         iconWidth = 48;
00420 
00421     if( flags & ClassHint ) {
00422         // Try to load the icon from the classhint if the app didn't specify
00423         // its own:
00424         if( result.isNull() ) {
00425 
00426         XClassHint  hint;
00427         if( XGetClassHint( qt_xdisplay(), win, &hint ) ) {
00428             QString className = hint.res_class;
00429 
00430             QPixmap pm = KGlobal::instance()->iconLoader()->loadIcon( className.lower(), KIcon::Small, iconWidth,
00431                                           KIcon::DefaultState, 0, true );
00432             if( scale && !pm.isNull() )
00433             result.convertFromImage( pm.convertToImage().smoothScale( width, height ) );
00434             else
00435             result = pm;
00436 
00437             XFree( hint.res_name );
00438             XFree( hint.res_class );
00439         }
00440         }
00441     }
00442 
00443     if( flags & XApp ) {
00444     // If the icon is still a null pixmap, load the 'xapp' icon
00445     // as a last resort:
00446     if ( result.isNull() ) {
00447         QPixmap pm = KGlobal::instance()->iconLoader()->loadIcon(  "xapp", KIcon::Small, iconWidth,
00448                                        KIcon::DefaultState, 0, true );
00449         if( scale && !pm.isNull() )
00450         result.convertFromImage( pm.convertToImage().smoothScale( width, height ) );
00451         else
00452         result = pm;
00453     }
00454     }
00455 #endif
00456     return result;
00457 }
00458 
00459 void KWin::setIcons( WId win, const QPixmap& icon, const QPixmap& miniIcon )
00460 {
00461 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00462     if ( icon.isNull() )
00463     return;
00464     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
00465     QImage img = icon.convertToImage().convertDepth( 32 );
00466     NETIcon ni;
00467     ni.size.width = img.size().width();
00468     ni.size.height = img.size().height();
00469     ni.data = (unsigned char *) img.bits();
00470     info.setIcon( ni, true );
00471     if ( miniIcon.isNull() )
00472     return;
00473     img = miniIcon.convertToImage().convertDepth( 32 );
00474     ni.size.width = img.size().width();
00475     ni.size.height = img.size().height();
00476     ni.data = (unsigned char *) img.bits();
00477     info.setIcon( ni, false );
00478 #endif
00479 }
00480 
00481 void KWin::setType( WId win, NET::WindowType windowType )
00482 {
00483 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00484     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
00485     info.setWindowType( windowType );
00486 #endif
00487 }
00488 
00489 void KWin::setState( WId win, unsigned long state )
00490 {
00491 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00492     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMState );
00493     info.setState( state, state );
00494 #endif
00495 }
00496 
00497 void KWin::clearState( WId win, unsigned long state )
00498 {
00499 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00500     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMState );
00501     info.setState( 0, state );
00502 #endif
00503 }
00504 
00505 void KWin::setOnAllDesktops( WId win, bool b )
00506 {
00507 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00508     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMDesktop );
00509     if ( b )
00510     info.setDesktop( NETWinInfo::OnAllDesktops );
00511     else if ( info.desktop()  == NETWinInfo::OnAllDesktops ) {
00512     NETRootInfo rinfo( qt_xdisplay(), NET::CurrentDesktop );
00513     info.setDesktop( rinfo.currentDesktop() );
00514     }
00515 #endif
00516 }
00517 
00518 void KWin::setOnDesktop( WId win, int desktop )
00519 {
00520 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00521     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMDesktop );
00522     info.setDesktop( desktop );
00523 #endif
00524 }
00525 
00526 void KWin::setStrut( WId win, int left, int right, int top, int bottom )
00527 {
00528 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00529     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
00530     NETStrut strut;
00531     strut.left = left;
00532     strut.right = right;
00533     strut.top = top;
00534     strut.bottom = bottom;
00535     info.setStrut( strut );
00536 #endif
00537 }
00538 
00539 int KWin::currentDesktop()
00540 {
00541 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00542     if (!qt_xdisplay())
00543 #endif
00544       return 1;
00545 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00546     NETRootInfo info( qt_xdisplay(), NET::CurrentDesktop );
00547     return info.currentDesktop();
00548 #endif
00549 }
00550 
00551 int KWin::numberOfDesktops()
00552 {
00553 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00554     if (!qt_xdisplay())
00555 #endif
00556       return 0;
00557 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00558     NETRootInfo info( qt_xdisplay(), NET::NumberOfDesktops );
00559     return info.numberOfDesktops();
00560 #endif
00561 }
00562 
00563 void KWin::setCurrentDesktop( int desktop )
00564 {
00565 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00566     NETRootInfo info( qt_xdisplay(), NET::CurrentDesktop );
00567     info.setCurrentDesktop( desktop );
00568 #endif
00569 }
00570 
00571 
00572 void KWin::iconifyWindow( WId win, bool animation)
00573 {
00574 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00575     if ( !animation )
00576     {
00577         kwin_net_create_atoms();
00578     sendClientMessageToRoot( win, kde_wm_change_state, IconicState, 1 );
00579     }
00580     XIconifyWindow( qt_xdisplay(), win, qt_xscreen() );
00581 #endif
00582 }
00583 
00584 
00585 void KWin::deIconifyWindow( WId win, bool animation )
00586 {
00587 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00588     if ( !animation )
00589     {
00590         kwin_net_create_atoms();
00591     sendClientMessageToRoot( win, kde_wm_change_state, NormalState, 1 );
00592     }
00593     XMapWindow( qt_xdisplay(), win );
00594 #endif
00595 }
00596 
00597 void KWin::raiseWindow( WId win )
00598 {
00599 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00600     NETRootInfo info( qt_xdisplay(), NET::Supported );
00601     if( info.isSupported( NET::WM2RestackWindow ))
00602         info.restackRequest( win, None, Above );
00603     else
00604         XRaiseWindow( qt_xdisplay(), win );
00605 #endif
00606 }
00607 
00608 void KWin::lowerWindow( WId win )
00609 {
00610 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00611     NETRootInfo info( qt_xdisplay(), NET::Supported );
00612     if( info.isSupported( NET::WM2RestackWindow ))
00613         info.restackRequest( win, None, Below );
00614     else
00615         XLowerWindow( qt_xdisplay(), win );
00616 #endif
00617 }
00618 
00619 void KWin::appStarted()
00620 {
00621 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00622     KStartupInfo::appStarted();
00623 #endif
00624 }
00625 
00626 class KWin::WindowInfoPrivate
00627 {
00628     public:
00629     WindowInfoPrivate()
00630 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00631     : info( NULL ) 
00632 #endif
00633     {}
00634 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00635     ~WindowInfoPrivate() { delete info; }
00636     NETWinInfo* info;
00637 #endif
00638     WId win_;
00639     QString name_;
00640         QString iconic_name_;
00641     QRect geometry_;
00642         QRect frame_geometry_;
00643     int ref;
00644         bool valid;
00645     private:
00646     WindowInfoPrivate( const WindowInfoPrivate& );
00647     void operator=( const WindowInfoPrivate& );
00648 };
00649 
00650 // KWin::info() should be updated too if something has to be changed here
00651 KWin::WindowInfo::WindowInfo( WId win, unsigned long properties, unsigned long properties2 )
00652 {
00653 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00654     KXErrorHandler handler;
00655     d = new WindowInfoPrivate;
00656     d->ref = 1;
00657     if( properties == 0 )
00658     properties = NET::WMState |
00659              NET::WMStrut |
00660              NET::WMWindowType |
00661              NET::WMName |
00662              NET::WMVisibleName |
00663                      NET::WMIconName |
00664                      NET::WMVisibleIconName |
00665              NET::WMDesktop |
00666              NET::WMPid |
00667              NET::WMKDEFrameStrut |
00668              NET::XAWMState |
00669                      NET::WMGeometry;
00670     if( properties & NET::WMVisibleIconName )
00671     properties |= NET::WMIconName | NET::WMVisibleName; // force, in case it will be used as a fallback
00672     if( properties & NET::WMVisibleName )
00673     properties |= NET::WMName; // force, in case it will be used as a fallback
00674     properties |= NET::XAWMState; // force to get error detection for valid()
00675     unsigned long props[ 2 ] = { properties, properties2 };
00676     d->info = new NETWinInfo( qt_xdisplay(), win, qt_xrootwin(), props, 2 );
00677     d->win_ = win;
00678     if( properties & NET::WMName ) {
00679         if( d->info->name() && d->info->name()[ 0 ] != '\0' )
00680         d->name_ = QString::fromUtf8( d->info->name() );
00681         else
00682             d->name_ = readNameProperty( win, XA_WM_NAME );
00683     }
00684     if( properties & NET::WMIconName ) {
00685         if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' )
00686             d->iconic_name_ = QString::fromUtf8( d->info->iconName());
00687         else
00688             d->iconic_name_ = readNameProperty( win, XA_WM_ICON_NAME );
00689     }
00690     if( properties & ( NET::WMGeometry | NET::WMKDEFrameStrut )) {
00691         NETRect frame, geom;
00692         d->info->kdeGeometry( frame, geom );
00693         d->geometry_.setRect( geom.pos.x, geom.pos.y, geom.size.width, geom.size.height );
00694         d->frame_geometry_.setRect( frame.pos.x, frame.pos.y, frame.size.width, frame.size.height );
00695     }
00696     d->valid = !handler.error( false ); // no sync - NETWinInfo did roundtrips
00697 #endif
00698 }
00699 
00700 // this one is only to make QValueList<> or similar happy
00701 KWin::WindowInfo::WindowInfo()
00702     : d( NULL )
00703 {
00704 }
00705 
00706 KWin::WindowInfo::~WindowInfo()
00707 {
00708     if( d != NULL ) {
00709     if( --d->ref == 0 ) {
00710         delete d;
00711     }
00712     }
00713 }
00714 
00715 KWin::WindowInfo::WindowInfo( const WindowInfo& wininfo )
00716     : d( wininfo.d )
00717 {
00718     if( d != NULL )
00719     ++d->ref;
00720 }
00721 
00722 KWin::WindowInfo& KWin::WindowInfo::operator=( const WindowInfo& wininfo )
00723 {
00724     if( d != wininfo.d ) {
00725     if( d != NULL )
00726         if( --d->ref == 0 )
00727         delete d;
00728     d = wininfo.d;
00729     if( d != NULL )
00730         ++d->ref;
00731     }
00732     return *this;
00733 }
00734 
00735 bool KWin::WindowInfo::valid( bool withdrawn_is_valid ) const
00736 {
00737     if( !d->valid )
00738         return false;
00739     if( !withdrawn_is_valid && mappingState() == NET::Withdrawn )
00740         return false;
00741     return true;
00742 }
00743 
00744 WId KWin::WindowInfo::win() const
00745 {
00746     return d->win_;
00747 }
00748 
00749 unsigned long KWin::WindowInfo::state() const
00750 {
00751 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00752     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMState ) == 0, 176 )
00753         << "Pass NET::WMState to KWin::windowInfo()" << endl;
00754     return d->info->state();
00755 #else
00756     return 0;
00757 #endif
00758 }
00759 
00760 NET::MappingState KWin::WindowInfo::mappingState() const
00761 {
00762 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00763     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::XAWMState ) == 0, 176 )
00764         << "Pass NET::XAWMState to KWin::windowInfo()" << endl;
00765     return d->info->mappingState();
00766 #else
00767     return 0;
00768 #endif
00769 }
00770 
00771 NETStrut KWin::WindowInfo::strut() const
00772 {
00773 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00774     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMStrut ) == 0, 176 )
00775         << "Pass NET::WMStrut to KWin::windowInfo()" << endl;
00776     return d->info->strut();
00777 #else
00778     NETStrut n;
00779     return n;
00780 #endif
00781 }
00782 
00783 NET::WindowType KWin::WindowInfo::windowType( int supported_types ) const
00784 {
00785 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00786     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMWindowType ) == 0, 176 )
00787         << "Pass NET::WMWindowType to KWin::windowInfo()" << endl;
00788     return d->info->windowType( supported_types );
00789 #else
00790     return 0;
00791 #endif
00792 }
00793 
00794 QString KWin::WindowInfo::visibleNameWithState() const
00795 {
00796     QString s = visibleName();
00797     if ( isMinimized() ) {
00798     s.prepend('(');
00799     s.append(')');
00800     }
00801     return s;
00802 }
00803 
00804 QString KWin::Info::visibleNameWithState() const
00805 {
00806     QString s = visibleName;
00807     if ( isMinimized() ) {
00808     s.prepend('(');
00809     s.append(')');
00810     }
00811     return s;
00812 }
00813 
00814 QString KWin::WindowInfo::visibleName() const
00815 {
00816 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00817     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMVisibleName ) == 0, 176 )
00818         << "Pass NET::WMVisibleName to KWin::windowInfo()" << endl;
00819     return d->info->visibleName() && d->info->visibleName()[ 0 ] != '\0'
00820         ? QString::fromUtf8(d->info->visibleName()) : name();
00821 #else
00822     return QString("name");
00823 #endif
00824 }
00825 
00826 QString KWin::WindowInfo::name() const
00827 {
00828 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00829     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMName ) == 0, 176 )
00830         << "Pass NET::WMName to KWin::windowInfo()" << endl;
00831     return d->name_;
00832 #else
00833     return QString();
00834 #endif
00835 }
00836 
00837 QString KWin::WindowInfo::visibleIconNameWithState() const
00838 {
00839     QString s = visibleIconName();
00840     if ( isMinimized() ) {
00841     s.prepend('(');
00842     s.append(')');
00843     }
00844     return s;
00845 }
00846 
00847 QString KWin::WindowInfo::visibleIconName() const
00848 {
00849 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00850     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMVisibleIconName ) == 0, 176 )
00851         << "Pass NET::WMVisibleIconName to KWin::windowInfo()" << endl;
00852     if( d->info->visibleIconName() && d->info->visibleIconName()[ 0 ] != '\0' )
00853         return QString::fromUtf8( d->info->visibleIconName());
00854     if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' )
00855         return QString::fromUtf8( d->info->iconName());
00856     if( !d->iconic_name_.isEmpty())
00857         return d->iconic_name_;
00858 #endif
00859     return visibleName();
00860 }
00861 
00862 QString KWin::WindowInfo::iconName() const
00863 {
00864 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00865     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMIconName ) == 0, 176 )
00866         << "Pass NET::WMIconName to KWin::windowInfo()" << endl;
00867     if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' )
00868         return QString::fromUtf8( d->info->iconName());
00869     if( !d->iconic_name_.isEmpty())
00870         return d->iconic_name_;
00871 #endif
00872     return name();
00873 }
00874 
00875 bool KWin::WindowInfo::isOnCurrentDesktop() const
00876 {
00877 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00878     return isOnDesktop( KWin::currentDesktop());
00879 #else
00880     return false;
00881 #endif
00882 }
00883 
00884 bool KWin::WindowInfo::isOnDesktop( int desktop ) const
00885 {
00886 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00887     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop ) == 0, 176 )
00888         << "Pass NET::WMDesktop to KWin::windowInfo()" << endl;
00889     return d->info->desktop() == desktop || d->info->desktop() == NET::OnAllDesktops;
00890 #else
00891     return false;
00892 #endif
00893 }
00894 
00895 bool KWin::WindowInfo::onAllDesktops() const
00896 {
00897 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00898     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop ) == 0, 176 )
00899         << "Pass NET::WMDesktop to KWin::windowInfo()" << endl;
00900     return d->info->desktop() == NET::OnAllDesktops;
00901 #else
00902     return false;
00903 #endif
00904 }
00905 
00906 int KWin::WindowInfo::desktop() const
00907 {
00908 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00909     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop ) == 0, 176 )
00910         << "Pass NET::WMDesktop to KWin::windowInfo()" << endl;
00911     return d->info->desktop();
00912 #else
00913     return 1;
00914 #endif
00915 }
00916 
00917 QRect KWin::WindowInfo::geometry() const
00918 {
00919 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00920     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMGeometry ) == 0, 176 )
00921         << "Pass NET::WMGeometry to KWin::windowInfo()" << endl;
00922     return d->geometry_;
00923 #else
00924     return QRect( 100, 100, 200, 200 );;
00925 #endif
00926 }
00927 
00928 QRect KWin::WindowInfo::frameGeometry() const
00929 {
00930     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMKDEFrameStrut ) == 0, 176 )
00931         << "Pass NET::WMKDEFrameStrut to KWin::windowInfo()" << endl;
00932     return d->frame_geometry_;
00933 }
00934 
00935 WId KWin::WindowInfo::transientFor() const
00936 {
00937 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00938     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2TransientFor ) == 0, 176 )
00939         << "Pass NET::WM2TransientFor to KWin::windowInfo()" << endl;
00940     return d->info->transientFor();
00941 #else
00942     return 0;
00943 #endif
00944 }
00945 
00946 WId KWin::WindowInfo::groupLeader() const
00947 {
00948 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00949     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2GroupLeader ) == 0, 176 )
00950         << "Pass NET::WM2GroupLeader to KWin::windowInfo()" << endl;
00951     return d->info->groupLeader();
00952 #else
00953     return 0;
00954 #endif
00955 }
00956 
00957 bool KWin::WindowInfo::actionSupported( NET::Action action ) const
00958 {
00959 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00960     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2AllowedActions ) == 0, 176 )
00961         << "Pass NET::WM2AllowedActions to KWin::windowInfo()" << endl;
00962     if( allowedActionsSupported())
00963         return d->info->allowedActions() & action;
00964     else
00965 #endif
00966         return true; // no idea if it's supported or not -> pretend it is
00967 }
00968 
00969 // see NETWM spec section 7.6
00970 bool KWin::WindowInfo::isMinimized() const
00971 {
00972 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00973     if( mappingState() != NET::Iconic )
00974         return false;
00975     // NETWM 1.2 compliant WM - uses NET::Hidden for minimized windows
00976     if(( state() & NET::Hidden ) != 0
00977     && ( state() & NET::Shaded ) == 0 ) // shaded may have NET::Hidden too
00978         return true;
00979     // older WMs use WithdrawnState for other virtual desktops
00980     // and IconicState only for minimized
00981     return icccmCompliantMappingState() ? false : true;
00982 #else
00983     return false;
00984 #endif
00985 }
00986 
00987 bool KWin::Info::isMinimized() const
00988 {
00989 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00990     if( mappingState != NET::Iconic )
00991         return false;
00992     // NETWM 1.2 compliant WM - uses NET::Hidden for minimized windows
00993     if(( state & NET::Hidden ) != 0
00994     && ( state & NET::Shaded ) == 0 ) // shaded may have NET::Hidden too
00995         return true;
00996     // older WMs use WithdrawnState for other virtual desktops
00997     // and IconicState only for minimized
00998     return icccmCompliantMappingState() ? false : true;
00999 #else
01000     return false;
01001 #endif
01002 }
01003 
01004 bool KWin::Info::isIconified() const
01005 {
01006     return isMinimized();
01007 }
01008 
01009 bool KWin::icccmCompliantMappingState()
01010 {
01011 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01012     static enum { noidea, yes, no } wm_is_1_2_compliant = noidea;
01013     if( wm_is_1_2_compliant == noidea ) {
01014         NETRootInfo info( qt_xdisplay(), NET::Supported );
01015         wm_is_1_2_compliant = info.isSupported( NET::Hidden ) ? yes : no;
01016     }
01017     return wm_is_1_2_compliant == yes;
01018 #else
01019     return false;
01020 #endif
01021 }
01022 
01023 bool KWin::allowedActionsSupported()
01024 {
01025 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01026     static enum { noidea, yes, no } wm_supports_allowed_actions = noidea;
01027     if( wm_supports_allowed_actions == noidea ) {
01028         NETRootInfo info( qt_xdisplay(), NET::Supported );
01029         wm_supports_allowed_actions = info.isSupported( NET::WM2AllowedActions ) ? yes : no;
01030     }
01031     return wm_supports_allowed_actions == yes;
01032 #else
01033     return false;
01034 #endif
01035 }
01036 
01037 QString KWin::readNameProperty( WId win, unsigned long atom )
01038 {
01039 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01040     XTextProperty tp;
01041     char **text = NULL;
01042     int count;
01043 #endif
01044     QString result;
01045 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
01046     if ( XGetTextProperty( qt_xdisplay(), win, &tp, atom ) != 0 && tp.value != NULL ) {
01047         if ( tp.encoding == XA_STRING )
01048             result = QString::fromLocal8Bit( (const char*) tp.value );
01049         else if ( XmbTextPropertyToTextList( qt_xdisplay(), &tp, &text, &count) == Success &&
01050                   text != NULL && count > 0 ) {
01051             result = QString::fromLocal8Bit( text[0] );
01052         }
01053         if( text != NULL )
01054             XFreeStringList( text );
01055         XFree( tp.value );
01056     }
01057 #endif
01058     return result;
01059 }
01060 
01061 //#endif
KDE Logo
This file is part of the documentation for kdecore Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 22 14:23:03 2004 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2003