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