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 = ( NET::FromTool << 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 if ( img.isNull() )
00693 return;
00694 ni.size.width = img.size().width();
00695 ni.size.height = img.size().height();
00696 ni.data = (unsigned char *) img.bits();
00697 info.setIcon( ni, false );
00698 }
00699
00700 void KWindowSystem::setType( WId win, NET::WindowType windowType )
00701 {
00702 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), 0 );
00703 info.setWindowType( windowType );
00704 }
00705
00706 void KWindowSystem::setState( WId win, unsigned long state )
00707 {
00708 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), NET::WMState );
00709 info.setState( state, state );
00710 }
00711
00712 void KWindowSystem::clearState( WId win, unsigned long state )
00713 {
00714 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), NET::WMState );
00715 info.setState( 0, state );
00716 }
00717
00718 void KWindowSystem::minimizeWindow( WId win, bool animation)
00719 {
00720 if ( !animation )
00721 {
00722 create_atoms();
00723 sendClientMessageToRoot( win, kde_wm_change_state, IconicState, 1 );
00724 }
00725 QX11Info inf;
00726 XIconifyWindow( QX11Info::display(), win, inf.screen() );
00727 }
00728
00729 void KWindowSystem::unminimizeWindow( WId win, bool animation )
00730 {
00731 if ( !animation )
00732 {
00733 create_atoms();
00734 sendClientMessageToRoot( win, kde_wm_change_state, NormalState, 1 );
00735 }
00736 XMapWindow( QX11Info::display(), win );
00737 }
00738
00739 void KWindowSystem::raiseWindow( WId win )
00740 {
00741 NETRootInfo info( QX11Info::display(), NET::Supported );
00742 if( info.isSupported( NET::WM2RestackWindow ))
00743 info.restackRequest( win, NET::FromTool, None, Above, QX11Info::appUserTime());
00744 else
00745 XRaiseWindow( QX11Info::display(), win );
00746 }
00747
00748 void KWindowSystem::lowerWindow( WId win )
00749 {
00750 NETRootInfo info( QX11Info::display(), NET::Supported );
00751 if( info.isSupported( NET::WM2RestackWindow ))
00752 info.restackRequest( win, NET::FromTool, None, Below, QX11Info::appUserTime());
00753 else
00754 XLowerWindow( QX11Info::display(), win );
00755 }
00756
00757 bool KWindowSystem::compositingActive()
00758 {
00759 if( QX11Info::display()) {
00760 create_atoms();
00761 return XGetSelectionOwner( QX11Info::display(), net_wm_cm ) != None;
00762 } else {
00763 Display* dpy = XOpenDisplay( NULL );
00764 create_atoms( dpy );
00765 bool ret = XGetSelectionOwner( dpy, net_wm_cm ) != None;
00766 XCloseDisplay( dpy );
00767 return ret;
00768 }
00769 }
00770
00771 QRect KWindowSystem::workArea( int desktop )
00772 {
00773 init( INFO_BASIC );
00774 int desk = (desktop > 0 && desktop <= (int) s_d_func()->numberOfDesktops() ) ? desktop : currentDesktop();
00775 if ( desk <= 0 )
00776 return QApplication::desktop()->geometry();
00777
00778 NETRect r = s_d_func()->workArea( desk );
00779 if( r.size.width <= 0 || r.size.height <= 0 )
00780 return QApplication::desktop()->geometry();
00781
00782 return QRect( r.pos.x, r.pos.y, r.size.width, r.size.height );
00783 }
00784
00785 QRect KWindowSystem::workArea( const QList<WId>& exclude, int desktop )
00786 {
00787 init( INFO_WINDOWS );
00788 KWindowSystemPrivate* const s_d = s_d_func();
00789
00790 QRect all = QApplication::desktop()->geometry();
00791 QRect a = all;
00792
00793 if (desktop == -1)
00794 desktop = s_d->currentDesktop();
00795
00796 QList<WId>::ConstIterator it1;
00797 for( it1 = s_d->windows.constBegin(); it1 != s_d->windows.constEnd(); ++it1 ) {
00798
00799 if(exclude.contains(*it1))
00800 continue;
00801
00802
00803
00804
00805 NETStrut strut;
00806 QList< KWindowSystemPrivate::StrutData >::Iterator it2 = s_d->strutWindows.begin();
00807 for( ; it2 != s_d->strutWindows.end(); ++it2 )
00808 if( (*it2).window == *it1 )
00809 break;
00810
00811 if( it2 != s_d->strutWindows.end()) {
00812 if(!((*it2).desktop == desktop || (*it2).desktop == NETWinInfo::OnAllDesktops ))
00813 continue;
00814
00815 strut = (*it2).strut;
00816 } else if( s_d->possibleStrutWindows.contains( *it1 ) ) {
00817
00818 NETWinInfo info( QX11Info::display(), (*it1), QX11Info::appRootWindow(), NET::WMStrut | NET::WMDesktop);
00819 strut = info.strut();
00820 s_d->possibleStrutWindows.removeAll( *it1 );
00821 s_d->strutWindows.append( KWindowSystemPrivate::StrutData( *it1, info.strut(), info.desktop()));
00822
00823 if( !(info.desktop() == desktop || info.desktop() == NETWinInfo::OnAllDesktops) )
00824 continue;
00825 } else
00826 continue;
00827
00828 QRect r = all;
00829 if ( strut.left > 0 )
00830 r.setLeft( r.left() + (int) strut.left );
00831 if ( strut.top > 0 )
00832 r.setTop( r.top() + (int) strut.top );
00833 if ( strut.right > 0 )
00834 r.setRight( r.right() - (int) strut.right );
00835 if ( strut.bottom > 0 )
00836 r.setBottom( r.bottom() - (int) strut.bottom );
00837
00838 a = a.intersect(r);
00839 }
00840 return a;
00841 }
00842
00843 QString KWindowSystem::desktopName( int desktop )
00844 {
00845 init( INFO_BASIC );
00846 KWindowSystemPrivate* const s_d = s_d_func();
00847
00848 bool isDesktopSane = (desktop > 0 && desktop <= (int) s_d->numberOfDesktops());
00849 const char* name = s_d->desktopName( isDesktopSane ? desktop : currentDesktop() );
00850
00851 if ( name && name[0] )
00852 return QString::fromUtf8( name );
00853
00854 return i18n("Desktop %1", desktop );
00855 }
00856
00857 void KWindowSystem::setDesktopName( int desktop, const QString& name )
00858 {
00859 KWindowSystemPrivate* const s_d = s_d_func();
00860
00861 if (desktop <= 0 || desktop > (int) numberOfDesktops() )
00862 desktop = currentDesktop();
00863
00864 if( s_d ) {
00865 s_d->setDesktopName( desktop, name.toUtf8().constData() );
00866 return;
00867 }
00868
00869 NETRootInfo info( QX11Info::display(), 0 );
00870 info.setDesktopName( desktop, name.toUtf8().constData() );
00871 }
00872
00873 bool KWindowSystem::showingDesktop()
00874 {
00875 init( INFO_BASIC );
00876 return s_d_func()->showingDesktop();
00877 }
00878
00879 void KWindowSystem::setUserTime( WId win, long time )
00880 {
00881 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), 0 );
00882 info.setUserTime( time );
00883 }
00884
00885 void KWindowSystem::setExtendedStrut( WId win, int left_width, int left_start, int left_end,
00886 int right_width, int right_start, int right_end, int top_width, int top_start, int top_end,
00887 int bottom_width, int bottom_start, int bottom_end )
00888 {
00889 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), 0 );
00890 NETExtendedStrut strut;
00891 strut.left_width = left_width;
00892 strut.right_width = right_width;
00893 strut.top_width = top_width;
00894 strut.bottom_width = bottom_width;
00895 strut.left_start = left_start;
00896 strut.left_end = left_end;
00897 strut.right_start = right_start;
00898 strut.right_end = right_end;
00899 strut.top_start = top_start;
00900 strut.top_end = top_end;
00901 strut.bottom_start = bottom_start;
00902 strut.bottom_end = bottom_end;
00903 info.setExtendedStrut( strut );
00904 NETStrut oldstrut;
00905 oldstrut.left = left_width;
00906 oldstrut.right = right_width;
00907 oldstrut.top = top_width;
00908 oldstrut.bottom = bottom_width;
00909 info.setStrut( oldstrut );
00910 }
00911
00912 void KWindowSystem::setStrut( WId win, int left, int right, int top, int bottom )
00913 {
00914 int w = XDisplayWidth( QX11Info::display(), DefaultScreen( QX11Info::display()));
00915 int h = XDisplayHeight( QX11Info::display(), DefaultScreen( QX11Info::display()));
00916 setExtendedStrut( win, left, 0, left != 0 ? w : 0, right, 0, right != 0 ? w : 0,
00917 top, 0, top != 0 ? h : 0, bottom, 0, bottom != 0 ? h : 0 );
00918 }
00919
00920 bool KWindowSystem::icccmCompliantMappingState()
00921 {
00922 static enum { noidea, yes, no } wm_is_1_2_compliant = noidea;
00923 if( wm_is_1_2_compliant == noidea ) {
00924 NETRootInfo info( QX11Info::display(), NET::Supported );
00925 wm_is_1_2_compliant = info.isSupported( NET::Hidden ) ? yes : no;
00926 }
00927 return wm_is_1_2_compliant == yes;
00928 }
00929
00930 bool KWindowSystem::allowedActionsSupported()
00931 {
00932 static enum { noidea, yes, no } wm_supports_allowed_actions = noidea;
00933 if( wm_supports_allowed_actions == noidea ) {
00934 NETRootInfo info( QX11Info::display(), NET::Supported );
00935 wm_supports_allowed_actions = info.isSupported( NET::WM2AllowedActions ) ? yes : no;
00936 }
00937 return wm_supports_allowed_actions == yes;
00938 }
00939
00940 QString KWindowSystem::readNameProperty( WId win, unsigned long atom )
00941 {
00942 XTextProperty tp;
00943 char **text = NULL;
00944 int count;
00945 QString result;
00946 if ( XGetTextProperty( QX11Info::display(), win, &tp, atom ) != 0 && tp.value != NULL ) {
00947 create_atoms();
00948
00949 if ( tp.encoding == kwm_utf8_string ) {
00950 result = QString::fromUtf8 ( (const char*) tp.value );
00951 } else if ( XmbTextPropertyToTextList( QX11Info::display(), &tp, &text, &count) == Success &&
00952 text != NULL && count > 0 ) {
00953 result = QString::fromLocal8Bit( text[0] );
00954 } else if ( tp.encoding == XA_STRING )
00955 result = QString::fromLocal8Bit( (const char*) tp.value );
00956 if( text != NULL )
00957 XFreeStringList( text );
00958 XFree( tp.value );
00959 }
00960 return result;
00961 }
00962
00963 void KWindowSystem::doNotManage( const QString& title )
00964 {
00965 QDBusInterface("org.kde.kwin", "/KWin", "org.kde.KWin", QDBusConnection::sessionBus())
00966 .call("doNotManage", title);
00967 }
00968
00969 void KWindowSystem::allowExternalProcessWindowActivation( int pid )
00970 {
00971
00972 }
00973
00974
00975 bool KWindowSystem::mapViewport()
00976 {
00977 KWindowSystemPrivate* const s_d = s_d_func();
00978 if( s_d )
00979 return s_d->mapViewport();
00980
00981 NETRootInfo infos( QX11Info::display(), NET::Supported );
00982 if( !infos.isSupported( NET::DesktopViewport ))
00983 return false;
00984 NETRootInfo info( QX11Info::display(), NET::NumberOfDesktops | NET::CurrentDesktop | NET::DesktopGeometry );
00985 if( info.numberOfDesktops( true ) <= 1
00986 && ( info.desktopGeometry( info.currentDesktop( true )).width > QApplication::desktop()->width()
00987 || info.desktopGeometry( info.currentDesktop( true )).height > QApplication::desktop()->height()))
00988 return true;
00989 return false;
00990 }
00991
00992 int KWindowSystem::viewportToDesktop( const QPoint& p )
00993 {
00994 init( INFO_BASIC );
00995 KWindowSystemPrivate* const s_d = s_d_func();
00996 NETSize s = s_d->desktopGeometry( s_d->currentDesktop( true ));
00997 QSize vs = qApp->desktop()->size();
00998 int xs = s.width / vs.width();
00999 int x = p.x() < 0 ? 0 : p.x() >= s.width ? xs - 1 : p.x() / vs.width();
01000 int ys = s.height / vs.height();
01001 int y = p.y() < 0 ? 0 : p.y() >= s.height ? ys - 1 : p.y() / vs.height();
01002 return y * xs + x + 1;
01003 }
01004
01005 int KWindowSystem::viewportWindowToDesktop( const QRect& r )
01006 {
01007 init( INFO_BASIC );
01008 KWindowSystemPrivate* const s_d = s_d_func();
01009 QPoint p = r.center();
01010
01011 p = QPoint( p.x() + s_d->desktopViewport( s_d->currentDesktop( true )).x,
01012 p.y() + s_d->desktopViewport( s_d->currentDesktop( true )).y );
01013 NETSize s = s_d->desktopGeometry( s_d->currentDesktop( true ));
01014 QSize vs = qApp->desktop()->size();
01015 int xs = s.width / vs.width();
01016 int x = p.x() < 0 ? 0 : p.x() >= s.width ? xs - 1 : p.x() / vs.width();
01017 int ys = s.height / vs.height();
01018 int y = p.y() < 0 ? 0 : p.y() >= s.height ? ys - 1 : p.y() / vs.height();
01019 return y * xs + x + 1;
01020 }
01021
01022 QPoint KWindowSystem::desktopToViewport( int desktop, bool absolute )
01023 {
01024 init( INFO_BASIC );
01025 KWindowSystemPrivate* const s_d = s_d_func();
01026 NETSize s = s_d->desktopGeometry( s_d->currentDesktop( true ));
01027 QSize vs = qApp->desktop()->size();
01028 int xs = s.width / vs.width();
01029 int ys = s.height / vs.height();
01030 if( desktop <= 0 || desktop > xs * ys )
01031 return QPoint( 0, 0 );
01032 --desktop;
01033 QPoint ret( vs.width() * ( desktop % xs ), vs.height() * ( desktop / xs ));
01034 if( !absolute ) {
01035 ret = QPoint( ret.x() - s_d->desktopViewport( s_d->currentDesktop( true )).x,
01036 ret.y() - s_d->desktopViewport( s_d->currentDesktop( true )).y );
01037 if( ret.x() >= s.width )
01038 ret.setX( ret.x() - s.width );
01039 if( ret.x() < 0 )
01040 ret.setX( ret.x() + s.width );
01041 if( ret.y() >= s.height )
01042 ret.setY( ret.y() - s.height );
01043 if( ret.y() < 0 )
01044 ret.setY( ret.y() + s.height );
01045 }
01046 return ret;
01047 }
01048
01049 QPoint KWindowSystem::constrainViewportRelativePosition( const QPoint& pos )
01050 {
01051 init( INFO_BASIC );
01052 KWindowSystemPrivate* const s_d = s_d_func();
01053 NETSize s = s_d->desktopGeometry( s_d->currentDesktop( true ));
01054 NETPoint c = s_d->desktopViewport( s_d->currentDesktop( true ));
01055 int x = ( pos.x() + c.x ) % s.width;
01056 int y = ( pos.y() + c.y ) % s.height;
01057 if( x < 0 )
01058 x += s.width;
01059 if( y < 0 )
01060 y += s.height;
01061 return QPoint( x - c.x, y - c.y );
01062 }
01063
01064 #include "kwindowsystem.moc"