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