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.114 2005/02/01 12:44:02 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 <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     if (percent > 99)
00549         XDeleteProperty (qt_xdisplay(), win, kde_wm_window_opacity);
00550     else
00551     {
00552         long opacity = long(0xFFFFFFFF/100.0*percent);
00553         XChangeProperty(qt_xdisplay(), win, kde_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opacity, 1L);
00554     }
00555 #endif
00556 }
00557 
00558 void KWin::setShadowSize( WId win, uint percent )
00559 {
00560 #ifdef Q_WS_X11
00561     long shadowSize = long(0xFFFFFFFF/100.0*percent);
00562     XChangeProperty(qt_xdisplay(), win, kde_wm_window_shadow, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &shadowSize, 1L);
00563 #endif
00564 }
00565 
00566 void KWin::setOnAllDesktops( WId win, bool b )
00567 {
00568 #ifdef Q_WS_X11
00569     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMDesktop );
00570     if ( b )
00571     info.setDesktop( NETWinInfo::OnAllDesktops );
00572     else if ( info.desktop()  == NETWinInfo::OnAllDesktops ) {
00573     NETRootInfo rinfo( qt_xdisplay(), NET::CurrentDesktop );
00574     info.setDesktop( rinfo.currentDesktop() );
00575     }
00576 #endif
00577 }
00578 
00579 void KWin::setOnDesktop( WId win, int desktop )
00580 {
00581 #ifdef Q_WS_X11
00582     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMDesktop );
00583     info.setDesktop( desktop );
00584 #endif
00585 }
00586 
00587 void KWin::setExtendedStrut( WId win, int left_width, int left_start, int left_end,
00588     int right_width, int right_start, int right_end, int top_width, int top_start, int top_end,
00589     int bottom_width, int bottom_start, int bottom_end )
00590 {
00591 #ifdef Q_WS_X11
00592     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
00593     NETExtendedStrut strut;
00594     strut.left_width = left_width;
00595     strut.right_width = right_width;
00596     strut.top_width = top_width;
00597     strut.bottom_width = bottom_width;
00598     strut.left_start = left_start;
00599     strut.left_end = left_end;
00600     strut.right_start = right_start;
00601     strut.right_end = right_end;
00602     strut.top_start = top_start;
00603     strut.top_end = top_end;
00604     strut.bottom_start = bottom_start;
00605     strut.bottom_end = bottom_end;
00606     info.setExtendedStrut( strut );
00607 #endif
00608 }
00609 
00610 void KWin::setStrut( WId win, int left, int right, int top, int bottom )
00611 {
00612 #ifdef Q_WS_X11
00613     NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
00614     NETStrut strut;
00615     strut.left = left;
00616     strut.right = right;
00617     strut.top = top;
00618     strut.bottom = bottom;
00619     info.setStrut( strut );
00620 #endif
00621 }
00622 
00623 int KWin::currentDesktop()
00624 {
00625 #ifdef Q_WS_X11
00626     if (!qt_xdisplay())
00627 #endif
00628       return 1;
00629 #ifdef Q_WS_X11
00630     NETRootInfo info( qt_xdisplay(), NET::CurrentDesktop );
00631     return info.currentDesktop();
00632 #endif
00633 }
00634 
00635 int KWin::numberOfDesktops()
00636 {
00637 #ifdef Q_WS_X11
00638     if (!qt_xdisplay())
00639 #endif
00640       return 0;
00641 #ifdef Q_WS_X11
00642     NETRootInfo info( qt_xdisplay(), NET::NumberOfDesktops );
00643     return info.numberOfDesktops();
00644 #endif
00645 }
00646 
00647 void KWin::setCurrentDesktop( int desktop )
00648 {
00649 #ifdef Q_WS_X11
00650     NETRootInfo info( qt_xdisplay(), NET::CurrentDesktop );
00651     info.setCurrentDesktop( desktop );
00652 #endif
00653 }
00654 
00655 
00656 void KWin::iconifyWindow( WId win, bool animation)
00657 {
00658 #ifdef Q_WS_X11
00659     if ( !animation )
00660     {
00661         kwin_net_create_atoms();
00662     sendClientMessageToRoot( win, kde_wm_change_state, IconicState, 1 );
00663     }
00664     XIconifyWindow( qt_xdisplay(), win, qt_xscreen() );
00665 #endif
00666 }
00667 
00668 
00669 void KWin::deIconifyWindow( WId win, bool animation )
00670 {
00671 #ifdef Q_WS_X11
00672     if ( !animation )
00673     {
00674         kwin_net_create_atoms();
00675     sendClientMessageToRoot( win, kde_wm_change_state, NormalState, 1 );
00676     }
00677     XMapWindow( qt_xdisplay(), win );
00678 #endif
00679 }
00680 
00681 void KWin::raiseWindow( WId win )
00682 {
00683 #ifdef Q_WS_X11
00684     NETRootInfo info( qt_xdisplay(), NET::Supported );
00685     if( info.isSupported( NET::WM2RestackWindow ))
00686         info.restackRequest( win, None, Above );
00687     else
00688         XRaiseWindow( qt_xdisplay(), win );
00689 #endif
00690 }
00691 
00692 void KWin::lowerWindow( WId win )
00693 {
00694 #ifdef Q_WS_X11
00695     NETRootInfo info( qt_xdisplay(), NET::Supported );
00696     if( info.isSupported( NET::WM2RestackWindow ))
00697         info.restackRequest( win, None, Below );
00698     else
00699         XLowerWindow( qt_xdisplay(), win );
00700 #endif
00701 }
00702 
00703 void KWin::appStarted()
00704 {
00705 #ifdef Q_WS_X11
00706     KStartupInfo::appStarted();
00707 #endif
00708 }
00709 
00710 class KWin::WindowInfoPrivate
00711 {
00712     public:
00713     WindowInfoPrivate()
00714 #ifdef Q_WS_X11
00715     : info( NULL )
00716 #endif
00717     {}
00718 #ifdef Q_WS_X11
00719     ~WindowInfoPrivate() { delete info; }
00720     NETWinInfo* info;
00721 #endif
00722     WId win_;
00723     QString name_;
00724         QString iconic_name_;
00725     QRect geometry_;
00726         QRect frame_geometry_;
00727     int ref;
00728         bool valid;
00729     private:
00730     WindowInfoPrivate( const WindowInfoPrivate& );
00731     void operator=( const WindowInfoPrivate& );
00732 };
00733 
00734 // KWin::info() should be updated too if something has to be changed here
00735 KWin::WindowInfo::WindowInfo( WId win, unsigned long properties, unsigned long properties2 )
00736 {
00737 #ifdef Q_WS_X11
00738     KXErrorHandler handler;
00739     d = new WindowInfoPrivate;
00740     d->ref = 1;
00741     if( properties == 0 )
00742     properties = NET::WMState |
00743              NET::WMStrut |
00744              NET::WMWindowType |
00745              NET::WMName |
00746              NET::WMVisibleName |
00747                      NET::WMIconName |
00748                      NET::WMVisibleIconName |
00749              NET::WMDesktop |
00750              NET::WMPid |
00751              NET::WMKDEFrameStrut |
00752              NET::XAWMState |
00753                      NET::WMGeometry;
00754     if( properties & NET::WMVisibleIconName )
00755     properties |= NET::WMIconName | NET::WMVisibleName; // force, in case it will be used as a fallback
00756     if( properties & NET::WMVisibleName )
00757     properties |= NET::WMName; // force, in case it will be used as a fallback
00758     if( properties2 & NET::WM2ExtendedStrut )
00759         properties |= NET::WMStrut; // will be used as fallback
00760     properties |= NET::XAWMState; // force to get error detection for valid()
00761     unsigned long props[ 2 ] = { properties, properties2 };
00762     d->info = new NETWinInfo( qt_xdisplay(), win, qt_xrootwin(), props, 2 );
00763     d->win_ = win;
00764     if( properties & NET::WMName ) {
00765         if( d->info->name() && d->info->name()[ 0 ] != '\0' )
00766         d->name_ = QString::fromUtf8( d->info->name() );
00767         else
00768             d->name_ = readNameProperty( win, XA_WM_NAME );
00769     }
00770     if( properties & NET::WMIconName ) {
00771         if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' )
00772             d->iconic_name_ = QString::fromUtf8( d->info->iconName());
00773         else
00774             d->iconic_name_ = readNameProperty( win, XA_WM_ICON_NAME );
00775     }
00776     if( properties & ( NET::WMGeometry | NET::WMKDEFrameStrut )) {
00777         NETRect frame, geom;
00778         d->info->kdeGeometry( frame, geom );
00779         d->geometry_.setRect( geom.pos.x, geom.pos.y, geom.size.width, geom.size.height );
00780         d->frame_geometry_.setRect( frame.pos.x, frame.pos.y, frame.size.width, frame.size.height );
00781     }
00782     d->valid = !handler.error( false ); // no sync - NETWinInfo did roundtrips
00783 #endif
00784 }
00785 
00786 // this one is only to make QValueList<> or similar happy
00787 KWin::WindowInfo::WindowInfo()
00788     : d( NULL )
00789 {
00790 }
00791 
00792 KWin::WindowInfo::~WindowInfo()
00793 {
00794     if( d != NULL ) {
00795     if( --d->ref == 0 ) {
00796         delete d;
00797     }
00798     }
00799 }
00800 
00801 KWin::WindowInfo::WindowInfo( const WindowInfo& wininfo )
00802     : d( wininfo.d )
00803 {
00804     if( d != NULL )
00805     ++d->ref;
00806 }
00807 
00808 KWin::WindowInfo& KWin::WindowInfo::operator=( const WindowInfo& wininfo )
00809 {
00810     if( d != wininfo.d ) {
00811     if( d != NULL )
00812         if( --d->ref == 0 )
00813         delete d;
00814     d = wininfo.d;
00815     if( d != NULL )
00816         ++d->ref;
00817     }
00818     return *this;
00819 }
00820 
00821 bool KWin::WindowInfo::valid( bool withdrawn_is_valid ) const
00822 {
00823     if( !d->valid )
00824         return false;
00825     if( !withdrawn_is_valid && mappingState() == NET::Withdrawn )
00826         return false;
00827     return true;
00828 }
00829 
00830 WId KWin::WindowInfo::win() const
00831 {
00832     return d->win_;
00833 }
00834 
00835 unsigned long KWin::WindowInfo::state() const
00836 {
00837 #ifdef Q_WS_X11
00838     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMState ) == 0, 176 )
00839         << "Pass NET::WMState to KWin::windowInfo()" << endl;
00840     return d->info->state();
00841 #else
00842     return 0;
00843 #endif
00844 }
00845 
00846 NET::MappingState KWin::WindowInfo::mappingState() const
00847 {
00848 #ifdef Q_WS_X11
00849     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::XAWMState ) == 0, 176 )
00850         << "Pass NET::XAWMState to KWin::windowInfo()" << endl;
00851     return d->info->mappingState();
00852 #else
00853     return NET::Visible;
00854 #endif
00855 }
00856 
00857 NETExtendedStrut KWin::WindowInfo::extendedStrut() const
00858 {
00859 #ifdef Q_WS_X11
00860     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2ExtendedStrut ) == 0, 176 )
00861         << "Pass NET::WM2ExtendedStrut to second argument of KWin::windowInfo()" << endl;
00862     NETExtendedStrut ext = d->info->extendedStrut();
00863     NETStrut str = d->info->strut();
00864     if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0
00865         && ( str.left != 0 || str.right != 0 || str.top != 0 || str.bottom != 0 )) {
00866         // build extended from simple
00867         if( str.left != 0 ) {
00868             ext.left_width = str.left;
00869             ext.left_start = 0;
00870             ext.left_end = XDisplayHeight( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00871         }
00872         if( str.right != 0 ) {
00873             ext.right_width = str.right;
00874             ext.right_start = 0;
00875             ext.right_end = XDisplayHeight( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00876         }
00877         if( str.top != 0 ) {
00878             ext.top_width = str.top;
00879             ext.top_start = 0;
00880             ext.top_end = XDisplayWidth( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00881         }
00882         if( str.bottom != 0 ) {
00883             ext.bottom_width = str.bottom;
00884             ext.bottom_start = 0;
00885             ext.bottom_end = XDisplayWidth( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00886         }
00887     }
00888     return ext;
00889 #else
00890     NETExtendedStrut n;
00891     return n;
00892 #endif
00893 }
00894 
00895 NETStrut KWin::WindowInfo::strut() const
00896 {
00897 #ifdef Q_WS_X11
00898     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMStrut ) == 0, 176 )
00899         << "Pass NET::WMStrut to KWin::windowInfo()" << endl;
00900     return d->info->strut();
00901 #else
00902     NETStrut n;
00903     return n;
00904 #endif
00905 }
00906 
00907 NET::WindowType KWin::WindowInfo::windowType( int supported_types ) const
00908 {
00909 #ifdef Q_WS_X11
00910     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMWindowType ) == 0, 176 )
00911         << "Pass NET::WMWindowType to KWin::windowInfo()" << endl;
00912     return d->info->windowType( supported_types );
00913 #else
00914     return 0;
00915 #endif
00916 }
00917 
00918 QString KWin::WindowInfo::visibleNameWithState() const
00919 {
00920     QString s = visibleName();
00921     if ( isMinimized() ) {
00922     s.prepend('(');
00923     s.append(')');
00924     }
00925     return s;
00926 }
00927 
00928 QString KWin::Info::visibleNameWithState() const
00929 {
00930     QString s = visibleName;
00931     if ( isMinimized() ) {
00932     s.prepend('(');
00933     s.append(')');
00934     }
00935     return s;
00936 }
00937 
00938 QString KWin::WindowInfo::visibleName() const
00939 {
00940 #ifdef Q_WS_X11
00941     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMVisibleName ) == 0, 176 )
00942         << "Pass NET::WMVisibleName to KWin::windowInfo()" << endl;
00943     return d->info->visibleName() && d->info->visibleName()[ 0 ] != '\0'
00944         ? QString::fromUtf8(d->info->visibleName()) : name();
00945 #else
00946     return QString("name");
00947 #endif
00948 }
00949 
00950 QString KWin::WindowInfo::name() const
00951 {
00952 #ifdef Q_WS_X11
00953     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMName ) == 0, 176 )
00954         << "Pass NET::WMName to KWin::windowInfo()" << endl;
00955     return d->name_;
00956 #else
00957     return QString();
00958 #endif
00959 }
00960 
00961 QString KWin::WindowInfo::visibleIconNameWithState() const
00962 {
00963     QString s = visibleIconName();
00964     if ( isMinimized() ) {
00965     s.prepend('(');
00966     s.append(')');
00967     }
00968     return s;
00969 }
00970 
00971 QString KWin::WindowInfo::visibleIconName() const
00972 {
00973 #ifdef Q_WS_X11
00974     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMVisibleIconName ) == 0, 176 )
00975         << "Pass NET::WMVisibleIconName to KWin::windowInfo()" << endl;
00976     if( d->info->visibleIconName() && d->info->visibleIconName()[ 0 ] != '\0' )
00977         return QString::fromUtf8( d->info->visibleIconName());
00978     if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' )
00979         return QString::fromUtf8( d->info->iconName());
00980     if( !d->iconic_name_.isEmpty())
00981         return d->iconic_name_;
00982 #endif
00983     return visibleName();
00984 }
00985 
00986 QString KWin::WindowInfo::iconName() const
00987 {
00988 #ifdef Q_WS_X11
00989     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMIconName ) == 0, 176 )
00990         << "Pass NET::WMIconName to KWin::windowInfo()" << endl;
00991     if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' )
00992         return QString::fromUtf8( d->info->iconName());
00993     if( !d->iconic_name_.isEmpty())
00994         return d->iconic_name_;
00995 #endif
00996     return name();
00997 }
00998 
00999 bool KWin::WindowInfo::isOnCurrentDesktop() const
01000 {
01001 #ifdef Q_WS_X11
01002     return isOnDesktop( KWin::currentDesktop());
01003 #else
01004     return false;
01005 #endif
01006 }
01007 
01008 bool KWin::WindowInfo::isOnDesktop( int desktop ) const
01009 {
01010 #ifdef Q_WS_X11
01011     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop ) == 0, 176 )
01012         << "Pass NET::WMDesktop to KWin::windowInfo()" << endl;
01013     return d->info->desktop() == desktop || d->info->desktop() == NET::OnAllDesktops;
01014 #else
01015     return false;
01016 #endif
01017 }
01018 
01019 bool KWin::WindowInfo::onAllDesktops() const
01020 {
01021 #ifdef Q_WS_X11
01022     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop ) == 0, 176 )
01023         << "Pass NET::WMDesktop to KWin::windowInfo()" << endl;
01024     return d->info->desktop() == NET::OnAllDesktops;
01025 #else
01026     return false;
01027 #endif
01028 }
01029 
01030 int KWin::WindowInfo::desktop() const
01031 {
01032 #ifdef Q_WS_X11
01033     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop ) == 0, 176 )
01034         << "Pass NET::WMDesktop to KWin::windowInfo()" << endl;
01035     return d->info->desktop();
01036 #else
01037     return 1;
01038 #endif
01039 }
01040 
01041 QRect KWin::WindowInfo::geometry() const
01042 {
01043 #ifdef Q_WS_X11
01044     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMGeometry ) == 0, 176 )
01045         << "Pass NET::WMGeometry to KWin::windowInfo()" << endl;
01046     return d->geometry_;
01047 #else
01048     return QRect( 100, 100, 200, 200 );
01049 #endif
01050 }
01051 
01052 QRect KWin::WindowInfo::frameGeometry() const
01053 {
01054 #ifdef Q_WS_X11
01055     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMKDEFrameStrut ) == 0, 176 )
01056         << "Pass NET::WMKDEFrameStrut to KWin::windowInfo()" << endl;
01057     return d->frame_geometry_;
01058 #else
01059     return QRect();
01060 #endif
01061 }
01062 
01063 WId KWin::WindowInfo::transientFor() const
01064 {
01065 #ifdef Q_WS_X11
01066     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2TransientFor ) == 0, 176 )
01067         << "Pass NET::WM2TransientFor to KWin::windowInfo()" << endl;
01068     return d->info->transientFor();
01069 #else
01070     return 0;
01071 #endif
01072 }
01073 
01074 WId KWin::WindowInfo::groupLeader() const
01075 {
01076 #ifdef Q_WS_X11
01077     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2GroupLeader ) == 0, 176 )
01078         << "Pass NET::WM2GroupLeader to KWin::windowInfo()" << endl;
01079     return d->info->groupLeader();
01080 #else
01081     return 0;
01082 #endif
01083 }
01084 
01085 QCString KWin::WindowInfo::windowClassClass() const
01086 {
01087 #ifdef Q_WS_X11
01088     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowClass ) == 0, 176 )
01089         << "Pass NET::WM2WindowClass to KWin::windowInfo()" << endl;
01090     return d->info->windowClassClass();
01091 #else
01092     return 0;
01093 #endif
01094 }
01095 
01096 QCString KWin::WindowInfo::windowClassName() const
01097 {
01098 #ifdef Q_WS_X11
01099     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowClass ) == 0, 176 )
01100         << "Pass NET::WM2WindowClass to KWin::windowInfo()" << endl;
01101     return d->info->windowClassName();
01102 #else
01103     return 0;
01104 #endif
01105 }
01106 
01107 QCString KWin::WindowInfo::windowRole() const
01108 {
01109 #ifdef Q_WS_X11
01110     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowRole ) == 0, 176 )
01111         << "Pass NET::WM2WindowRole to KWin::windowInfo()" << endl;
01112     return d->info->windowRole();
01113 #else
01114     return 0;
01115 #endif
01116 }
01117 
01118 QCString KWin::WindowInfo::clientMachine() const
01119 {
01120 #ifdef Q_WS_X11
01121     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2ClientMachine ) == 0, 176 )
01122         << "Pass NET::WM2ClientMachine to KWin::windowInfo()" << endl;
01123     return d->info->clientMachine();
01124 #else
01125     return 0;
01126 #endif
01127 }
01128 
01129 bool KWin::WindowInfo::actionSupported( NET::Action action ) const
01130 {
01131 #ifdef Q_WS_X11
01132     kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2AllowedActions ) == 0, 176 )
01133         << "Pass NET::WM2AllowedActions to KWin::windowInfo()" << endl;
01134     if( allowedActionsSupported())
01135         return d->info->allowedActions() & action;
01136     else
01137 #endif
01138         return true; // no idea if it's supported or not -> pretend it is
01139 }
01140 
01141 // see NETWM spec section 7.6
01142 bool KWin::WindowInfo::isMinimized() const
01143 {
01144 #ifdef Q_WS_X11
01145     if( mappingState() != NET::Iconic )
01146         return false;
01147     // NETWM 1.2 compliant WM - uses NET::Hidden for minimized windows
01148     if(( state() & NET::Hidden ) != 0
01149     && ( state() & NET::Shaded ) == 0 ) // shaded may have NET::Hidden too
01150         return true;
01151     // older WMs use WithdrawnState for other virtual desktops
01152     // and IconicState only for minimized
01153     return icccmCompliantMappingState() ? false : true;
01154 #else
01155     return false;
01156 #endif
01157 }
01158 
01159 bool KWin::Info::isMinimized() const
01160 {
01161 #ifdef Q_WS_X11
01162     if( mappingState != NET::Iconic )
01163         return false;
01164     // NETWM 1.2 compliant WM - uses NET::Hidden for minimized windows
01165     if(( state & NET::Hidden ) != 0
01166     && ( state & NET::Shaded ) == 0 ) // shaded may have NET::Hidden too
01167         return true;
01168     // older WMs use WithdrawnState for other virtual desktops
01169     // and IconicState only for minimized
01170     return icccmCompliantMappingState() ? false : true;
01171 #else
01172     return false;
01173 #endif
01174 }
01175 
01176 bool KWin::Info::isIconified() const
01177 {
01178     return isMinimized();
01179 }
01180 
01181 bool KWin::icccmCompliantMappingState()
01182 {
01183 #ifdef Q_WS_X11
01184     static enum { noidea, yes, no } wm_is_1_2_compliant = noidea;
01185     if( wm_is_1_2_compliant == noidea ) {
01186         NETRootInfo info( qt_xdisplay(), NET::Supported );
01187         wm_is_1_2_compliant = info.isSupported( NET::Hidden ) ? yes : no;
01188     }
01189     return wm_is_1_2_compliant == yes;
01190 #else
01191     return false;
01192 #endif
01193 }
01194 
01195 bool KWin::allowedActionsSupported()
01196 {
01197 #ifdef Q_WS_X11
01198     static enum { noidea, yes, no } wm_supports_allowed_actions = noidea;
01199     if( wm_supports_allowed_actions == noidea ) {
01200         NETRootInfo info( qt_xdisplay(), NET::Supported );
01201         wm_supports_allowed_actions = info.isSupported( NET::WM2AllowedActions ) ? yes : no;
01202     }
01203     return wm_supports_allowed_actions == yes;
01204 #else
01205     return false;
01206 #endif
01207 }
01208 
01209 QString KWin::readNameProperty( WId win, unsigned long atom )
01210 {
01211 #ifdef Q_WS_X11
01212     XTextProperty tp;
01213     char **text = NULL;
01214     int count;
01215 #endif
01216     QString result;
01217 #ifdef Q_WS_X11
01218     if ( XGetTextProperty( qt_xdisplay(), win, &tp, atom ) != 0 && tp.value != NULL ) {
01219         if ( XmbTextPropertyToTextList( qt_xdisplay(), &tp, &text, &count) == Success &&
01220                   text != NULL && count > 0 ) {
01221             result = QString::fromLocal8Bit( text[0] );
01222         } else if ( tp.encoding == XA_STRING )
01223             result = QString::fromLocal8Bit( (const char*) tp.value );
01224         if( text != NULL )
01225             XFreeStringList( text );
01226         XFree( tp.value );
01227     }
01228 #endif
01229     return result;
01230 }
01231 
01232 //#endif
KDE Logo
This file is part of the documentation for kdecore Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 7 22:04:24 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003