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