00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "kwindowsystem.h"
00023
00024 #include <kiconloader.h>
00025 #include <klocale.h>
00026 #include <kuniqueapplication.h>
00027 #include <kdebug.h>
00028 #include <kxerrorhandler.h>
00029 #include <kxutils.h>
00030 #include <netwm.h>
00031 #include <QtGui/QBitmap>
00032 #include <QDesktopWidget>
00033 #include <QtGui/QDialog>
00034 #include <QtDBus/QtDBus>
00035 #include <QtGui/QX11Info>
00036 #include <X11/Xatom.h>
00037
00038 class KWindowSystemStaticContainer {
00039 public:
00040 KWindowSystemStaticContainer() : d(0) {}
00041 KWindowSystem kwm;
00042 KWindowSystemPrivate* d;
00043 };
00044
00045
00046 K_GLOBAL_STATIC(KWindowSystemStaticContainer, g_kwmInstanceContainer)
00047
00048
00049 static unsigned long windows_properties[ 2 ] = { NET::ClientList | NET::ClientListStacking |
00050 NET::Supported |
00051 NET::NumberOfDesktops |
00052 NET::DesktopGeometry |
00053 NET::DesktopViewport |
00054 NET::CurrentDesktop |
00055 NET::DesktopNames |
00056 NET::ActiveWindow |
00057 NET::WorkArea,
00058 NET::WM2ShowingDesktop };
00059
00060
00061
00062 static unsigned long desktop_properties[ 2 ] = { NET::ClientList | NET::ClientListStacking |
00063 NET::Supported |
00064 NET::NumberOfDesktops |
00065 NET::DesktopGeometry |
00066 NET::DesktopViewport |
00067 NET::CurrentDesktop |
00068 NET::DesktopNames |
00069 NET::ActiveWindow |
00070 NET::WorkArea,
00071 NET::WM2ShowingDesktop };
00072
00073 class KWindowSystemPrivate
00074 : public QWidget, public NETRootInfo
00075 {
00076 public:
00077 KWindowSystemPrivate(int _what);
00078 void activate();
00079 QList<WId> windows;
00080 QList<WId> stackingOrder;
00081
00082 struct StrutData
00083 {
00084 StrutData( WId window_, const NETStrut& strut_, int desktop_ )
00085 : window( window_ ), strut( strut_ ), desktop( desktop_ ) {}
00086 StrutData() {}
00087 WId window;
00088 NETStrut strut;
00089 int desktop;
00090 };
00091 QList<StrutData> strutWindows;
00092 QList<WId> possibleStrutWindows;
00093 bool strutSignalConnected;
00094 int what;
00095 bool mapViewport();
00096
00097 void addClient(Window);
00098 void removeClient(Window);
00099
00100 bool x11Event( XEvent * ev );
00101
00102 void updateStackingOrder();
00103 bool removeStrutWindow( WId );
00104 };
00105
00106 KWindowSystemPrivate::KWindowSystemPrivate(int _what)
00107 : QWidget(0),
00108 NETRootInfo( QX11Info::display(),
00109 _what >= KWindowSystem::INFO_WINDOWS ? windows_properties : desktop_properties,
00110 2, -1, false ),
00111 strutSignalConnected( false ),
00112 what( _what )
00113 {
00114 if (kapp)
00115 kapp->installX11EventFilter( this );
00116 (void ) qApp->desktop();
00117 }
00118
00119
00120 void KWindowSystemPrivate::activate()
00121 {
00122 NETRootInfo::activate();
00123 updateStackingOrder();
00124 }
00125
00126 bool KWindowSystemPrivate::x11Event( XEvent * ev )
00127 {
00128 KWindowSystem* s_q = KWindowSystem::self();
00129
00130 if ( ev->xany.window == QX11Info::appRootWindow() ) {
00131 int old_current_desktop = currentDesktop();
00132 WId old_active_window = activeWindow();
00133 int old_number_of_desktops = numberOfDesktops();
00134 bool old_showing_desktop = showingDesktop();
00135 unsigned long m[ 5 ];
00136 NETRootInfo::event( ev, m, 5 );
00137
00138 if (( m[ PROTOCOLS ] & CurrentDesktop ) && currentDesktop() != old_current_desktop )
00139 emit s_q->currentDesktopChanged( currentDesktop() );
00140 if (( m[ PROTOCOLS ] & DesktopViewport ) && mapViewport() && currentDesktop() != old_current_desktop )
00141 emit s_q->currentDesktopChanged( currentDesktop() );
00142 if (( m[ PROTOCOLS ] & ActiveWindow ) && activeWindow() != old_active_window )
00143 emit s_q->activeWindowChanged( activeWindow() );
00144 if ( m[ PROTOCOLS ] & DesktopNames )
00145 emit s_q->desktopNamesChanged();
00146 if (( m[ PROTOCOLS ] & NumberOfDesktops ) && numberOfDesktops() != old_number_of_desktops )
00147 emit s_q->numberOfDesktopsChanged( numberOfDesktops() );
00148 if (( m[ PROTOCOLS ] & DesktopGeometry ) && mapViewport() && numberOfDesktops() != old_number_of_desktops )
00149 emit s_q->numberOfDesktopsChanged( numberOfDesktops() );
00150 if ( m[ PROTOCOLS ] & WorkArea )
00151 emit s_q->workAreaChanged();
00152 if ( m[ PROTOCOLS ] & ClientListStacking ) {
00153 updateStackingOrder();
00154 emit s_q->stackingOrderChanged();
00155 }
00156 if(( m[ PROTOCOLS2 ] & WM2ShowingDesktop ) && showingDesktop() != old_showing_desktop ) {
00157 emit s_q->showingDesktopChanged( showingDesktop());
00158 }
00159 } else if ( windows.contains( ev->xany.window ) ){
00160 NETWinInfo ni( QX11Info::display(), ev->xany.window, QX11Info::appRootWindow(), 0 );
00161 unsigned long dirty[ 2 ];
00162 ni.event( ev, dirty, 2 );
00163 if ( ev->type ==PropertyNotify ) {
00164 if( ev->xproperty.atom == XA_WM_HINTS )
00165 dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMIcon;
00166 else if( ev->xproperty.atom == XA_WM_NAME )
00167 dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMName;
00168 else if( ev->xproperty.atom == XA_WM_ICON_NAME )
00169 dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMIconName;
00170 }
00171 if( mapViewport() && ( dirty[ NETWinInfo::PROTOCOLS ] & NET::WMState ))
00172 dirty[ NETWinInfo::PROTOCOLS ] |= NET::WMDesktop;
00173 if ( (dirty[ NETWinInfo::PROTOCOLS ] & NET::WMStrut) != 0 ) {
00174 removeStrutWindow( ev->xany.window );
00175 if ( !possibleStrutWindows.contains( ev->xany.window ) )
00176 possibleStrutWindows.append( ev->xany.window );
00177 }
00178 if ( dirty[ NETWinInfo::PROTOCOLS ] || dirty[ NETWinInfo::PROTOCOLS2 ] ) {
00179 emit s_q->windowChanged( ev->xany.window );
00180 emit s_q->windowChanged( ev->xany.window, dirty );
00181 emit s_q->windowChanged( ev->xany.window, dirty[ NETWinInfo::PROTOCOLS ] );
00182 if ( (dirty[ NETWinInfo::PROTOCOLS ] & NET::WMStrut) != 0 )
00183 emit s_q->strutChanged();
00184 }
00185 }
00186
00187 return false;
00188 }
00189
00190 bool KWindowSystemPrivate::removeStrutWindow( WId w )
00191 {
00192 for( QList< StrutData >::Iterator it = strutWindows.begin();
00193 it != strutWindows.end();
00194 ++it )
00195 if( (*it).window == w ) {
00196 strutWindows.erase( it );
00197 return true;
00198 }
00199 return false;
00200 }
00201
00202 void KWindowSystemPrivate::updateStackingOrder()
00203 {
00204 stackingOrder.clear();
00205 for ( int i = 0; i < clientListStackingCount(); i++ )
00206 stackingOrder.append( clientListStacking()[i] );
00207 }
00208
00209 void KWindowSystemPrivate::addClient(Window w)
00210 {
00211 KWindowSystem* s_q = KWindowSystem::self();
00212
00213 if ( (what >= KWindowSystem::INFO_WINDOWS) && !QWidget::find( w ) )
00214 XSelectInput( QX11Info::display(), w, PropertyChangeMask | StructureNotifyMask );
00215
00216 bool emit_strutChanged = false;
00217
00218 if( strutSignalConnected ) {
00219 NETWinInfo info( QX11Info::display(), w, QX11Info::appRootWindow(), NET::WMStrut | NET::WMDesktop );
00220 NETStrut strut = info.strut();
00221 if ( strut.left || strut.top || strut.right || strut.bottom ) {
00222 strutWindows.append( StrutData( w, strut, info.desktop()));
00223 emit_strutChanged = true;
00224 }
00225 } else
00226 possibleStrutWindows.append( w );
00227
00228 windows.append( w );
00229 emit s_q->windowAdded( w );
00230 if ( emit_strutChanged )
00231 emit s_q->strutChanged();
00232 }
00233
00234 void KWindowSystemPrivate::removeClient(Window w)
00235 {
00236 KWindowSystem* s_q = KWindowSystem::self();
00237
00238 bool emit_strutChanged = removeStrutWindow( w );
00239 if( strutSignalConnected && possibleStrutWindows.contains( w )) {
00240 NETWinInfo info( QX11Info::display(), w, QX11Info::appRootWindow(), NET::WMStrut );
00241 NETStrut strut = info.strut();
00242 if ( strut.left || strut.top || strut.right || strut.bottom ) {
00243 emit_strutChanged = true;
00244 }
00245 }
00246
00247 possibleStrutWindows.removeAll( w );
00248 windows.removeAll( w );
00249 emit s_q->windowRemoved( w );
00250 if ( emit_strutChanged )
00251 emit s_q->strutChanged();
00252 }
00253
00254 bool KWindowSystemPrivate::mapViewport()
00255 {
00256
00257
00258
00259
00260 if( isSupported( NET::DesktopViewport ) && numberOfDesktops( true ) <= 1
00261 && ( desktopGeometry( currentDesktop( true )).width > QApplication::desktop()->width()
00262 || desktopGeometry( currentDesktop( true )).height > QApplication::desktop()->height()))
00263 return true;
00264 return false;
00265 }
00266
00267 static bool atoms_created = false;
00268
00269 static Atom kde_wm_change_state;
00270 static Atom _wm_protocols;
00271 static Atom kwm_utf8_string;
00272 static Atom net_wm_cm;
00273
00274 static void create_atoms( Display* dpy = QX11Info::display()) {
00275 if (!atoms_created){
00276 const int max = 20;
00277 Atom* atoms[max];
00278 const char* names[max];
00279 Atom atoms_return[max];
00280 int n = 0;
00281
00282 atoms[n] = &kde_wm_change_state;
00283 names[n++] = "_KDE_WM_CHANGE_STATE";
00284
00285 atoms[n] = &_wm_protocols;
00286 names[n++] = "WM_PROTOCOLS";
00287
00288 atoms[n] = &kwm_utf8_string;
00289 names[n++] = "UTF8_STRING";
00290
00291 char net_wm_cm_name[ 100 ];
00292 sprintf( net_wm_cm_name, "_NET_WM_CM_S%d", DefaultScreen( dpy ));
00293 atoms[n] = &net_wm_cm;
00294 names[n++] = net_wm_cm_name;
00295
00296
00297 XInternAtoms( dpy, const_cast<char**>(names), n, false, atoms_return );
00298 for (int i = 0; i < n; i++ )
00299 *atoms[i] = atoms_return[i];
00300
00301 atoms_created = True;
00302 }
00303 }
00304
00305 static void sendClientMessageToRoot(Window w, Atom a, long x, long y = 0, long z = 0 ){
00306 XEvent ev;
00307 long mask;
00308
00309 memset(&ev, 0, sizeof(ev));
00310 ev.xclient.type = ClientMessage;
00311 ev.xclient.window = w;
00312 ev.xclient.message_type = a;
00313 ev.xclient.format = 32;
00314 ev.xclient.data.l[0] = x;
00315 ev.xclient.data.l[1] = y;
00316 ev.xclient.data.l[2] = z;
00317 mask = SubstructureRedirectMask;
00318 XSendEvent(QX11Info::display(), QX11Info::appRootWindow(), False, mask, &ev);
00319 }
00320
00321 KWindowSystem* KWindowSystem::self()
00322 {
00323 return &(g_kwmInstanceContainer->kwm);
00324 }
00325
00326
00327 KWindowSystemPrivate* KWindowSystem::s_d_func()
00328 {
00329 return g_kwmInstanceContainer->d;
00330 }
00331
00332
00333
00334 void KWindowSystem::connectNotify( const char* signal )
00335 {
00336 int what = INFO_BASIC;
00337 if( QLatin1String( signal ) == SIGNAL(workAreaChanged()))
00338 what = INFO_WINDOWS;
00339 else if( QLatin1String( signal ) == SIGNAL(strutChanged()))
00340 what = INFO_WINDOWS;
00341 else if( QLatin1String( signal ) == QMetaObject::normalizedSignature(SIGNAL(windowChanged(WId,const unsigned long*))).constData())
00342 what = INFO_WINDOWS;
00343 else if( QLatin1String( signal ) == QMetaObject::normalizedSignature(SIGNAL(windowChanged(WId,unsigned int))).constData())
00344 what = INFO_WINDOWS;
00345 else if( QLatin1String( signal ) == QMetaObject::normalizedSignature(SIGNAL(windowChanged(WId))).constData())
00346 what = INFO_WINDOWS;
00347
00348 init( what );
00349 KWindowSystemPrivate* const s_d = s_d_func();
00350 if( !s_d->strutSignalConnected && qstrcmp( signal, SIGNAL(strutChanged())) == 0 )
00351 s_d->strutSignalConnected = true;
00352
00353 QObject::connectNotify( signal );
00354 }
00355
00356
00357
00358 void KWindowSystem::init(int what)
00359 {
00360 KWindowSystemPrivate* const s_d = s_d_func();
00361
00362 if (what >= INFO_WINDOWS)
00363 what = INFO_WINDOWS;
00364 else
00365 what = INFO_BASIC;
00366
00367 if ( !s_d )
00368 {
00369 g_kwmInstanceContainer->d = new KWindowSystemPrivate(what);
00370 g_kwmInstanceContainer->d->activate();
00371 }
00372 else if (s_d->what < what)
00373 {
00374 delete s_d;
00375 g_kwmInstanceContainer->d = new KWindowSystemPrivate(what);
00376 g_kwmInstanceContainer->d->activate();
00377 }
00378 }
00379
00380 const QList<WId>& KWindowSystem::windows()
00381 {
00382 init( INFO_BASIC );
00383 return s_d_func()->windows;
00384 }
00385
00386 KWindowInfo KWindowSystem::windowInfo( WId win, unsigned long properties, unsigned long properties2 )
00387 {
00388 return KWindowInfo( win, properties, properties2 );
00389 }
00390
00391 bool KWindowSystem::hasWId(WId w)
00392 {
00393 init( INFO_BASIC );
00394 return s_d_func()->windows.contains( w );
00395 }
00396
00397 QList<WId> KWindowSystem::stackingOrder()
00398 {
00399 init( INFO_BASIC );
00400 return s_d_func()->stackingOrder;
00401 }
00402
00403 int KWindowSystem::currentDesktop()
00404 {
00405 if (!QX11Info::display())
00406 return 1;
00407
00408 if( mapViewport()) {
00409 init( INFO_BASIC );
00410 KWindowSystemPrivate* const s_d = s_d_func();
00411 NETPoint p = s_d->desktopViewport( s_d->currentDesktop( true ));
00412 return viewportToDesktop( QPoint( p.x, p.y ));
00413 }
00414
00415 KWindowSystemPrivate* const s_d = s_d_func();
00416 if( s_d )
00417 return s_d->currentDesktop( true );
00418 NETRootInfo info( QX11Info::display(), NET::CurrentDesktop );
00419 return info.currentDesktop( true );
00420 }
00421
00422 int KWindowSystem::numberOfDesktops()
00423 {
00424 if (!QX11Info::display())
00425 return 1;
00426
00427 if( mapViewport()) {
00428 init( INFO_BASIC );
00429 KWindowSystemPrivate* const s_d = s_d_func();
00430 NETSize s = s_d->desktopGeometry( s_d->currentDesktop( true ));
00431 return s.width / qApp->desktop()->width() * s.height / qApp->desktop()->height();
00432 }
00433
00434 KWindowSystemPrivate* const s_d = s_d_func();
00435 if( s_d )
00436 return s_d->numberOfDesktops( true );
00437 NETRootInfo info( QX11Info::display(), NET::NumberOfDesktops );
00438 return info.numberOfDesktops( true );
00439 }
00440
00441 void KWindowSystem::setCurrentDesktop( int desktop )
00442 {
00443 if( mapViewport()) {
00444 init( INFO_BASIC );
00445 KWindowSystemPrivate* const s_d = s_d_func();
00446 NETRootInfo info( QX11Info::display(), 0 );
00447 QPoint pos = desktopToViewport( desktop, true );
00448 NETPoint p;
00449 p.x = pos.x();
00450 p.y = pos.y();
00451 info.setDesktopViewport( s_d->currentDesktop( true ), p );
00452 return;
00453 }
00454 NETRootInfo info( QX11Info::display(), 0 );
00455 info.setCurrentDesktop( desktop, true );
00456 }
00457
00458 void KWindowSystem::setOnAllDesktops( WId win, bool b )
00459 {
00460 if( mapViewport()) {
00461 if( b )
00462 setState( win, NET::Sticky );
00463 else
00464 clearState( win, NET::Sticky );
00465 return;
00466 }
00467 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), NET::WMDesktop );
00468 if ( b )
00469 info.setDesktop( NETWinInfo::OnAllDesktops, true );
00470 else if ( info.desktop( true ) == NETWinInfo::OnAllDesktops ) {
00471 NETRootInfo rinfo( QX11Info::display(), NET::CurrentDesktop );
00472 info.setDesktop( rinfo.currentDesktop( true ), true );
00473 }
00474 }
00475
00476 void KWindowSystem::setOnDesktop( WId win, int desktop )
00477 {
00478 if( mapViewport()) {
00479 if( desktop == NET::OnAllDesktops )
00480 return setOnAllDesktops( win, true );
00481 else
00482 clearState( win, NET::Sticky );
00483 init( INFO_BASIC );
00484 QPoint p = desktopToViewport( desktop, false );
00485 Window dummy;
00486 int x, y;
00487 unsigned int w, h, b, dp;
00488 XGetGeometry( QX11Info::display(), win, &dummy, &x, &y, &w, &h, &b, &dp );
00489
00490 XTranslateCoordinates( QX11Info::display(), win, QX11Info::appRootWindow(), 0, 0, &x, &y, &dummy );
00491 x += w / 2;
00492 y += h / 2;
00493
00494 x = x % qApp->desktop()->width();
00495 y = y % qApp->desktop()->height();
00496 if( x < 0 )
00497 x = x + qApp->desktop()->width();
00498 if( y < 0 )
00499 y = y + qApp->desktop()->height();
00500 x += p.x();
00501 y += p.y();
00502 x -= w / 2;
00503 y -= h / 2;
00504 p = constrainViewportRelativePosition( QPoint( x, y ));
00505 int flags = ( 0x20 << 12 ) | ( 0x03 << 8 ) | 10;
00506 KWindowSystemPrivate* const s_d = s_d_func();
00507 s_d->moveResizeWindowRequest( win, flags, p.x(), p.y(), w, h );
00508 return;
00509 }
00510 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), NET::WMDesktop );
00511 info.setDesktop( desktop, true );
00512 }
00513
00514 WId KWindowSystem::activeWindow()
00515 {
00516 KWindowSystemPrivate* const s_d = s_d_func();
00517 if( s_d )
00518 return s_d->activeWindow();
00519 NETRootInfo info( QX11Info::display(), NET::ActiveWindow );
00520 return info.activeWindow();
00521 }
00522
00523 void KWindowSystem::activateWindow( WId win, long time )
00524 {
00525 NETRootInfo info( QX11Info::display(), 0 );
00526 if( time == 0 )
00527 time = QX11Info::appUserTime();
00528 info.setActiveWindow( win, NET::FromApplication, time,
00529 qApp->activeWindow() ? qApp->activeWindow()->winId() : 0 );
00530 KUniqueApplication::setHandleAutoStarted();
00531 }
00532
00533 void KWindowSystem::forceActiveWindow( WId win, long time )
00534 {
00535 NETRootInfo info( QX11Info::display(), 0 );
00536 if( time == 0 )
00537 time = QX11Info::appTime();
00538 info.setActiveWindow( win, NET::FromTool, time, 0 );
00539 KUniqueApplication::setHandleAutoStarted();
00540 }
00541
00542 void KWindowSystem::demandAttention( WId win, bool set )
00543 {
00544 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), NET::WMState );
00545 info.setState( set ? NET::DemandsAttention : 0, NET::DemandsAttention );
00546 }
00547
00548 WId KWindowSystem::transientFor( WId win )
00549 {
00550 KXErrorHandler handler;
00551 Window transient_for = None;
00552 if( XGetTransientForHint( QX11Info::display(), win, &transient_for ))
00553 return transient_for;
00554
00555 return None;
00556 }
00557
00558 void KWindowSystem::setMainWindow( QWidget* subwindow, WId mainwindow )
00559 {
00560 subwindow->setAttribute( Qt::WA_X11BypassTransientForHint );
00561 if( mainwindow != 0 )
00562 XSetTransientForHint( QX11Info::display(), subwindow->winId(), mainwindow );
00563 else
00564 XDeleteProperty( QX11Info::display(), subwindow->winId(), XA_WM_TRANSIENT_FOR );
00565 }
00566
00567 WId KWindowSystem::groupLeader( WId win )
00568 {
00569 KXErrorHandler handler;
00570 XWMHints *hints = XGetWMHints( QX11Info::display(), win );
00571 Window window_group = None;
00572 if ( hints )
00573 {
00574 if( hints->flags & WindowGroupHint )
00575 window_group = hints->window_group;
00576 XFree( reinterpret_cast< char* >( hints ));
00577 }
00578
00579 return window_group;
00580 }
00581
00582 QPixmap KWindowSystem::icon( WId win, int width, int height, bool scale )
00583 {
00584 return icon( win, width, height, scale, NETWM | WMHints | ClassHint | XApp );
00585 }
00586
00587
00588 QPixmap KWindowSystem::icon( WId win, int width, int height, bool scale, int flags )
00589 {
00590 KXErrorHandler handler;
00591 QPixmap result;
00592 if( flags & NETWM ) {
00593 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), NET::WMIcon );
00594 NETIcon ni = info.icon( width, height );
00595 if ( ni.data && ni.size.width > 0 && ni.size.height > 0 ) {
00596 QImage img( (uchar*) ni.data, (int) ni.size.width, (int) ni.size.height, QImage::Format_ARGB32 );
00597 if ( scale && width > 0 && height > 0 &&img.size() != QSize( width, height ) && !img.isNull() )
00598 img = img.scaled( width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
00599 if ( !img.isNull() )
00600 result = QPixmap::fromImage( img );
00601 return result;
00602 }
00603 }
00604
00605 if( flags & WMHints ) {
00606 Pixmap p = None;
00607 Pixmap p_mask = None;
00608
00609 XWMHints *hints = XGetWMHints(QX11Info::display(), win );
00610 if (hints && (hints->flags & IconPixmapHint)){
00611 p = hints->icon_pixmap;
00612 }
00613 if (hints && (hints->flags & IconMaskHint)){
00614 p_mask = hints->icon_mask;
00615 }
00616 if (hints)
00617 XFree((char*)hints);
00618
00619 if (p != None){
00620 QPixmap pm = KXUtils::createPixmapFromHandle( p, p_mask );
00621 if ( scale && width > 0 && height > 0 && !pm.isNull()
00622 && ( pm.width() != width || pm.height() != height) ){
00623 result = QPixmap::fromImage( pm.toImage().scaled( width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) );
00624 } else {
00625 result = pm;
00626 }
00627 }
00628 }
00629
00630
00631
00632
00633 int iconWidth;
00634 if( width < 24 )
00635 iconWidth = 16;
00636 else if( width < 40 )
00637 iconWidth = 32;
00638 else
00639 iconWidth = 48;
00640
00641 if( flags & ClassHint ) {
00642
00643
00644 if( result.isNull() ) {
00645
00646 XClassHint hint;
00647 if( XGetClassHint( QX11Info::display(), win, &hint ) ) {
00648 QString className = hint.res_class;
00649
00650 QPixmap pm = KIconLoader::global()->loadIcon( className.toLower(), KIconLoader::Small, iconWidth,
00651 KIconLoader::DefaultState, QStringList(), 0, true );
00652 if( scale && !pm.isNull() )
00653 result = QPixmap::fromImage( pm.toImage().scaled( width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) );
00654 else
00655 result = pm;
00656
00657 XFree( hint.res_name );
00658 XFree( hint.res_class );
00659 }
00660 }
00661 }
00662
00663 if( flags & XApp ) {
00664
00665
00666 if ( result.isNull() ) {
00667 QPixmap pm = KIconLoader::global()->loadIcon( "xorg", KIconLoader::Small, iconWidth,
00668 KIconLoader::DefaultState, QStringList(), 0, true );
00669 if( scale && !pm.isNull() )
00670 result = QPixmap::fromImage( pm.toImage().scaled( width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) );
00671 else
00672 result = pm;
00673 }
00674 }
00675 return result;
00676 }
00677
00678 void KWindowSystem::setIcons( WId win, const QPixmap& icon, const QPixmap& miniIcon )
00679 {
00680 if ( icon.isNull() )
00681 return;
00682 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), 0 );
00683 QImage img = icon.toImage().convertToFormat( QImage::Format_ARGB32 );
00684 NETIcon ni;
00685 ni.size.width = img.size().width();
00686 ni.size.height = img.size().height();
00687 ni.data = (unsigned char *) img.bits();
00688 info.setIcon( ni, true );
00689 if ( miniIcon.isNull() )
00690 return;
00691 img = miniIcon.toImage().convertToFormat( QImage::Format_ARGB32 );
00692 ni.size.width = img.size().width();
00693 ni.size.height = img.size().height();
00694 ni.data = (unsigned char *) img.bits();
00695 info.setIcon( ni, false );
00696 }
00697
00698 void KWindowSystem::setType( WId win, NET::WindowType windowType )
00699 {
00700 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), 0 );
00701 info.setWindowType( windowType );
00702 }
00703
00704 void KWindowSystem::setState( WId win, unsigned long state )
00705 {
00706 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), NET::WMState );
00707 info.setState( state, state );
00708 }
00709
00710 void KWindowSystem::clearState( WId win, unsigned long state )
00711 {
00712 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), NET::WMState );
00713 info.setState( 0, state );
00714 }
00715
00716 void KWindowSystem::minimizeWindow( WId win, bool animation)
00717 {
00718 if ( !animation )
00719 {
00720 create_atoms();
00721 sendClientMessageToRoot( win, kde_wm_change_state, IconicState, 1 );
00722 }
00723 QX11Info inf;
00724 XIconifyWindow( QX11Info::display(), win, inf.screen() );
00725 }
00726
00727 void KWindowSystem::unminimizeWindow( WId win, bool animation )
00728 {
00729 if ( !animation )
00730 {
00731 create_atoms();
00732 sendClientMessageToRoot( win, kde_wm_change_state, NormalState, 1 );
00733 }
00734 XMapWindow( QX11Info::display(), win );
00735 }
00736
00737 void KWindowSystem::raiseWindow( WId win )
00738 {
00739 NETRootInfo info( QX11Info::display(), NET::Supported );
00740 if( info.isSupported( NET::WM2RestackWindow ))
00741 info.restackRequest( win, NET::FromTool, None, Above, QX11Info::appUserTime());
00742 else
00743 XRaiseWindow( QX11Info::display(), win );
00744 }
00745
00746 void KWindowSystem::lowerWindow( WId win )
00747 {
00748 NETRootInfo info( QX11Info::display(), NET::Supported );
00749 if( info.isSupported( NET::WM2RestackWindow ))
00750 info.restackRequest( win, NET::FromTool, None, Below, QX11Info::appUserTime());
00751 else
00752 XLowerWindow( QX11Info::display(), win );
00753 }
00754
00755 bool KWindowSystem::compositingActive()
00756 {
00757 if( QX11Info::display()) {
00758 create_atoms();
00759 return XGetSelectionOwner( QX11Info::display(), net_wm_cm ) != None;
00760 } else {
00761 Display* dpy = XOpenDisplay( NULL );
00762 create_atoms( dpy );
00763 bool ret = XGetSelectionOwner( dpy, net_wm_cm ) != None;
00764 XCloseDisplay( dpy );
00765 return ret;
00766 }
00767 }
00768
00769 QRect KWindowSystem::workArea( int desktop )
00770 {
00771 init( INFO_BASIC );
00772 int desk = (desktop > 0 && desktop <= (int) s_d_func()->numberOfDesktops() ) ? desktop : currentDesktop();
00773 if ( desk <= 0 )
00774 return QApplication::desktop()->geometry();
00775
00776 NETRect r = s_d_func()->workArea( desk );
00777 if( r.size.width <= 0 || r.size.height <= 0 )
00778 return QApplication::desktop()->geometry();
00779
00780 return QRect( r.pos.x, r.pos.y, r.size.width, r.size.height );
00781 }
00782
00783 QRect KWindowSystem::workArea( const QList<WId>& exclude, int desktop )
00784 {
00785 init( INFO_WINDOWS );
00786 KWindowSystemPrivate* const s_d = s_d_func();
00787
00788 QRect all = QApplication::desktop()->geometry();
00789 QRect a = all;
00790
00791 if (desktop == -1)
00792 desktop = s_d->currentDesktop();
00793
00794 QList<WId>::ConstIterator it1;
00795 for( it1 = s_d->windows.constBegin(); it1 != s_d->windows.constEnd(); ++it1 ) {
00796
00797 if(exclude.contains(*it1))
00798 continue;
00799
00800
00801
00802
00803 NETStrut strut;
00804 QList< KWindowSystemPrivate::StrutData >::Iterator it2 = s_d->strutWindows.begin();
00805 for( ; it2 != s_d->strutWindows.end(); ++it2 )
00806 if( (*it2).window == *it1 )
00807 break;
00808
00809 if( it2 != s_d->strutWindows.end()) {
00810 if(!((*it2).desktop == desktop || (*it2).desktop == NETWinInfo::OnAllDesktops ))
00811 continue;
00812
00813 strut = (*it2).strut;
00814 } else if( s_d->possibleStrutWindows.contains( *it1 ) ) {
00815
00816 NETWinInfo info( QX11Info::display(), (*it1), QX11Info::appRootWindow(), NET::WMStrut | NET::WMDesktop);
00817 strut = info.strut();
00818 s_d->possibleStrutWindows.removeAll( *it1 );
00819 s_d->strutWindows.append( KWindowSystemPrivate::StrutData( *it1, info.strut(), info.desktop()));
00820
00821 if( !(info.desktop() == desktop || info.desktop() == NETWinInfo::OnAllDesktops) )
00822 continue;
00823 } else
00824 continue;
00825
00826 QRect r = all;
00827 if ( strut.left > 0 )
00828 r.setLeft( r.left() + (int) strut.left );
00829 if ( strut.top > 0 )
00830 r.setTop( r.top() + (int) strut.top );
00831 if ( strut.right > 0 )
00832 r.setRight( r.right() - (int) strut.right );
00833 if ( strut.bottom > 0 )
00834 r.setBottom( r.bottom() - (int) strut.bottom );
00835
00836 a = a.intersect(r);
00837 }
00838 return a;
00839 }
00840
00841 QString KWindowSystem::desktopName( int desktop )
00842 {
00843 init( INFO_BASIC );
00844 KWindowSystemPrivate* const s_d = s_d_func();
00845
00846 bool isDesktopSane = (desktop > 0 && desktop <= (int) s_d->numberOfDesktops());
00847 const char* name = s_d->desktopName( isDesktopSane ? desktop : currentDesktop() );
00848
00849 if ( name && name[0] )
00850 return QString::fromUtf8( name );
00851
00852 return i18n("Desktop %1", desktop );
00853 }
00854
00855 void KWindowSystem::setDesktopName( int desktop, const QString& name )
00856 {
00857 KWindowSystemPrivate* const s_d = s_d_func();
00858
00859 if (desktop <= 0 || desktop > (int) numberOfDesktops() )
00860 desktop = currentDesktop();
00861
00862 if( s_d ) {
00863 s_d->setDesktopName( desktop, name.toUtf8().constData() );
00864 return;
00865 }
00866
00867 NETRootInfo info( QX11Info::display(), 0 );
00868 info.setDesktopName( desktop, name.toUtf8().constData() );
00869 }
00870
00871 bool KWindowSystem::showingDesktop()
00872 {
00873 init( INFO_BASIC );
00874 return s_d_func()->showingDesktop();
00875 }
00876
00877 void KWindowSystem::setUserTime( WId win, long time )
00878 {
00879 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), 0 );
00880 info.setUserTime( time );
00881 }
00882
00883 void KWindowSystem::setExtendedStrut( WId win, int left_width, int left_start, int left_end,
00884 int right_width, int right_start, int right_end, int top_width, int top_start, int top_end,
00885 int bottom_width, int bottom_start, int bottom_end )
00886 {
00887 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), 0 );
00888 NETExtendedStrut strut;
00889 strut.left_width = left_width;
00890 strut.right_width = right_width;
00891 strut.top_width = top_width;
00892 strut.bottom_width = bottom_width;
00893 strut.left_start = left_start;
00894 strut.left_end = left_end;
00895 strut.right_start = right_start;
00896 strut.right_end = right_end;
00897 strut.top_start = top_start;
00898 strut.top_end = top_end;
00899 strut.bottom_start = bottom_start;
00900 strut.bottom_end = bottom_end;
00901 info.setExtendedStrut( strut );
00902 NETStrut oldstrut;
00903 oldstrut.left = left_width;
00904 oldstrut.right = right_width;
00905 oldstrut.top = top_width;
00906 oldstrut.bottom = bottom_width;
00907 info.setStrut( oldstrut );
00908 }
00909
00910 void KWindowSystem::setStrut( WId win, int left, int right, int top, int bottom )
00911 {
00912 int w = XDisplayWidth( QX11Info::display(), DefaultScreen( QX11Info::display()));
00913 int h = XDisplayHeight( QX11Info::display(), DefaultScreen( QX11Info::display()));
00914 setExtendedStrut( win, left, 0, left != 0 ? w : 0, right, 0, right != 0 ? w : 0,
00915 top, 0, top != 0 ? h : 0, bottom, 0, bottom != 0 ? h : 0 );
00916 }
00917
00918 bool KWindowSystem::icccmCompliantMappingState()
00919 {
00920 static enum { noidea, yes, no } wm_is_1_2_compliant = noidea;
00921 if( wm_is_1_2_compliant == noidea ) {
00922 NETRootInfo info( QX11Info::display(), NET::Supported );
00923 wm_is_1_2_compliant = info.isSupported( NET::Hidden ) ? yes : no;
00924 }
00925 return wm_is_1_2_compliant == yes;
00926 }
00927
00928 bool KWindowSystem::allowedActionsSupported()
00929 {
00930 static enum { noidea, yes, no } wm_supports_allowed_actions = noidea;
00931 if( wm_supports_allowed_actions == noidea ) {
00932 NETRootInfo info( QX11Info::display(), NET::Supported );
00933 wm_supports_allowed_actions = info.isSupported( NET::WM2AllowedActions ) ? yes : no;
00934 }
00935 return wm_supports_allowed_actions == yes;
00936 }
00937
00938 QString KWindowSystem::readNameProperty( WId win, unsigned long atom )
00939 {
00940 XTextProperty tp;
00941 char **text = NULL;
00942 int count;
00943 QString result;
00944 if ( XGetTextProperty( QX11Info::display(), win, &tp, atom ) != 0 && tp.value != NULL ) {
00945 create_atoms();
00946
00947 if ( tp.encoding == kwm_utf8_string ) {
00948 result = QString::fromUtf8 ( (const char*) tp.value );
00949 } else if ( XmbTextPropertyToTextList( QX11Info::display(), &tp, &text, &count) == Success &&
00950 text != NULL && count > 0 ) {
00951 result = QString::fromLocal8Bit( text[0] );
00952 } else if ( tp.encoding == XA_STRING )
00953 result = QString::fromLocal8Bit( (const char*) tp.value );
00954 if( text != NULL )
00955 XFreeStringList( text );
00956 XFree( tp.value );
00957 }
00958 return result;
00959 }
00960
00961 void KWindowSystem::doNotManage( const QString& title )
00962 {
00963 QDBusInterface("org.kde.kwin", "/KWin", "org.kde.KWin", QDBusConnection::sessionBus())
00964 .call("doNotManage", title);
00965 }
00966
00967 bool KWindowSystem::mapViewport()
00968 {
00969 KWindowSystemPrivate* const s_d = s_d_func();
00970 if( s_d )
00971 return s_d->mapViewport();
00972
00973 NETRootInfo infos( QX11Info::display(), NET::Supported );
00974 if( !infos.isSupported( NET::DesktopViewport ))
00975 return false;
00976 NETRootInfo info( QX11Info::display(), NET::NumberOfDesktops | NET::CurrentDesktop | NET::DesktopGeometry );
00977 if( info.numberOfDesktops( true ) <= 1
00978 && ( info.desktopGeometry( info.currentDesktop( true )).width > QApplication::desktop()->width()
00979 || info.desktopGeometry( info.currentDesktop( true )).height > QApplication::desktop()->height()))
00980 return true;
00981 return false;
00982 }
00983
00984 int KWindowSystem::viewportToDesktop( const QPoint& p )
00985 {
00986 init( INFO_BASIC );
00987 KWindowSystemPrivate* const s_d = s_d_func();
00988 NETSize s = s_d->desktopGeometry( s_d->currentDesktop( true ));
00989 QSize vs = qApp->desktop()->size();
00990 int xs = s.width / vs.width();
00991 int x = p.x() < 0 ? 0 : p.x() >= s.width ? xs - 1 : p.x() / vs.width();
00992 int ys = s.height / vs.height();
00993 int y = p.y() < 0 ? 0 : p.y() >= s.height ? ys - 1 : p.y() / vs.height();
00994 return y * xs + x + 1;
00995 }
00996
00997 int KWindowSystem::viewportWindowToDesktop( const QRect& r )
00998 {
00999 init( INFO_BASIC );
01000 KWindowSystemPrivate* const s_d = s_d_func();
01001 QPoint p = r.center();
01002
01003 p = QPoint( p.x() + s_d->desktopViewport( s_d->currentDesktop( true )).x,
01004 p.y() + s_d->desktopViewport( s_d->currentDesktop( true )).y );
01005 NETSize s = s_d->desktopGeometry( s_d->currentDesktop( true ));
01006 QSize vs = qApp->desktop()->size();
01007 int xs = s.width / vs.width();
01008 int x = p.x() < 0 ? 0 : p.x() >= s.width ? xs - 1 : p.x() / vs.width();
01009 int ys = s.height / vs.height();
01010 int y = p.y() < 0 ? 0 : p.y() >= s.height ? ys - 1 : p.y() / vs.height();
01011 return y * xs + x + 1;
01012 }
01013
01014 QPoint KWindowSystem::desktopToViewport( int desktop, bool absolute )
01015 {
01016 init( INFO_BASIC );
01017 KWindowSystemPrivate* const s_d = s_d_func();
01018 NETSize s = s_d->desktopGeometry( s_d->currentDesktop( true ));
01019 QSize vs = qApp->desktop()->size();
01020 int xs = s.width / vs.width();
01021 int ys = s.height / vs.height();
01022 if( desktop <= 0 || desktop > xs * ys )
01023 return QPoint( 0, 0 );
01024 --desktop;
01025 QPoint ret( vs.width() * ( desktop % xs ), vs.height() * ( desktop / xs ));
01026 if( !absolute ) {
01027 ret = QPoint( ret.x() - s_d->desktopViewport( s_d->currentDesktop( true )).x,
01028 ret.y() - s_d->desktopViewport( s_d->currentDesktop( true )).y );
01029 if( ret.x() >= s.width )
01030 ret.setX( ret.x() - s.width );
01031 if( ret.x() < 0 )
01032 ret.setX( ret.x() + s.width );
01033 if( ret.y() >= s.height )
01034 ret.setY( ret.y() - s.height );
01035 if( ret.y() < 0 )
01036 ret.setY( ret.y() + s.height );
01037 }
01038 return ret;
01039 }
01040
01041 QPoint KWindowSystem::constrainViewportRelativePosition( const QPoint& pos )
01042 {
01043 init( INFO_BASIC );
01044 KWindowSystemPrivate* const s_d = s_d_func();
01045 NETSize s = s_d->desktopGeometry( s_d->currentDesktop( true ));
01046 NETPoint c = s_d->desktopViewport( s_d->currentDesktop( true ));
01047 int x = ( pos.x() + c.x ) % s.width;
01048 int y = ( pos.y() + c.y ) % s.height;
01049 if( x < 0 )
01050 x += s.width;
01051 if( y < 0 )
01052 y += s.height;
01053 return QPoint( x - c.x, y - c.y );
01054 }
01055
01056 #include "kwindowsystem.moc"