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