kdecore Library API Documentation

kwin.cpp

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