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 kwin_net_create_atoms();
00549 if (percent > 99)
00550 XDeleteProperty (qt_xdisplay(), win, kde_wm_window_opacity);
00551 else
00552 {
00553 long opacity = long(0xFFFFFFFF/100.0*percent);
00554 XChangeProperty(qt_xdisplay(), win, kde_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opacity, 1L);
00555 }
00556 #endif
00557 }
00558
00559 void KWin::setShadowSize( WId win, uint percent )
00560 {
00561 #ifdef Q_WS_X11
00562 kwin_net_create_atoms();
00563 long shadowSize = long(0xFFFFFFFF/100.0*percent);
00564 XChangeProperty(qt_xdisplay(), win, kde_wm_window_shadow, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &shadowSize, 1L);
00565 #endif
00566 }
00567
00568 void KWin::setOnAllDesktops( WId win, bool b )
00569 {
00570 #ifdef Q_WS_X11
00571 NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMDesktop );
00572 if ( b )
00573 info.setDesktop( NETWinInfo::OnAllDesktops );
00574 else if ( info.desktop() == NETWinInfo::OnAllDesktops ) {
00575 NETRootInfo rinfo( qt_xdisplay(), NET::CurrentDesktop );
00576 info.setDesktop( rinfo.currentDesktop() );
00577 }
00578 #endif
00579 }
00580
00581 void KWin::setOnDesktop( WId win, int desktop )
00582 {
00583 #ifdef Q_WS_X11
00584 NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMDesktop );
00585 info.setDesktop( desktop );
00586 #endif
00587 }
00588
00589 void KWin::setExtendedStrut( WId win, int left_width, int left_start, int left_end,
00590 int right_width, int right_start, int right_end, int top_width, int top_start, int top_end,
00591 int bottom_width, int bottom_start, int bottom_end )
00592 {
00593 #ifdef Q_WS_X11
00594 NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
00595 NETExtendedStrut strut;
00596 strut.left_width = left_width;
00597 strut.right_width = right_width;
00598 strut.top_width = top_width;
00599 strut.bottom_width = bottom_width;
00600 strut.left_start = left_start;
00601 strut.left_end = left_end;
00602 strut.right_start = right_start;
00603 strut.right_end = right_end;
00604 strut.top_start = top_start;
00605 strut.top_end = top_end;
00606 strut.bottom_start = bottom_start;
00607 strut.bottom_end = bottom_end;
00608 info.setExtendedStrut( strut );
00609 #endif
00610 }
00611
00612 void KWin::setStrut( WId win, int left, int right, int top, int bottom )
00613 {
00614 #ifdef Q_WS_X11
00615 NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
00616 NETStrut strut;
00617 strut.left = left;
00618 strut.right = right;
00619 strut.top = top;
00620 strut.bottom = bottom;
00621 info.setStrut( strut );
00622 #endif
00623 }
00624
00625 int KWin::currentDesktop()
00626 {
00627 #ifdef Q_WS_X11
00628 if (!qt_xdisplay())
00629 #endif
00630 return 1;
00631 #ifdef Q_WS_X11
00632 NETRootInfo info( qt_xdisplay(), NET::CurrentDesktop );
00633 return info.currentDesktop();
00634 #endif
00635 }
00636
00637 int KWin::numberOfDesktops()
00638 {
00639 #ifdef Q_WS_X11
00640 if (!qt_xdisplay())
00641 #endif
00642 return 0;
00643 #ifdef Q_WS_X11
00644 NETRootInfo info( qt_xdisplay(), NET::NumberOfDesktops );
00645 return info.numberOfDesktops();
00646 #endif
00647 }
00648
00649 void KWin::setCurrentDesktop( int desktop )
00650 {
00651 #ifdef Q_WS_X11
00652 NETRootInfo info( qt_xdisplay(), NET::CurrentDesktop );
00653 info.setCurrentDesktop( desktop );
00654 #endif
00655 }
00656
00657
00658 void KWin::iconifyWindow( WId win, bool animation)
00659 {
00660 #ifdef Q_WS_X11
00661 if ( !animation )
00662 {
00663 kwin_net_create_atoms();
00664 sendClientMessageToRoot( win, kde_wm_change_state, IconicState, 1 );
00665 }
00666 XIconifyWindow( qt_xdisplay(), win, qt_xscreen() );
00667 #endif
00668 }
00669
00670
00671 void KWin::deIconifyWindow( WId win, bool animation )
00672 {
00673 #ifdef Q_WS_X11
00674 if ( !animation )
00675 {
00676 kwin_net_create_atoms();
00677 sendClientMessageToRoot( win, kde_wm_change_state, NormalState, 1 );
00678 }
00679 XMapWindow( qt_xdisplay(), win );
00680 #endif
00681 }
00682
00683 void KWin::raiseWindow( WId win )
00684 {
00685 #ifdef Q_WS_X11
00686 NETRootInfo info( qt_xdisplay(), NET::Supported );
00687 if( info.isSupported( NET::WM2RestackWindow ))
00688 info.restackRequest( win, None, Above );
00689 else
00690 XRaiseWindow( qt_xdisplay(), win );
00691 #endif
00692 }
00693
00694 void KWin::lowerWindow( WId win )
00695 {
00696 #ifdef Q_WS_X11
00697 NETRootInfo info( qt_xdisplay(), NET::Supported );
00698 if( info.isSupported( NET::WM2RestackWindow ))
00699 info.restackRequest( win, None, Below );
00700 else
00701 XLowerWindow( qt_xdisplay(), win );
00702 #endif
00703 }
00704
00705 void KWin::appStarted()
00706 {
00707 #ifdef Q_WS_X11
00708 KStartupInfo::appStarted();
00709 #endif
00710 }
00711
00712 class KWin::WindowInfoPrivate
00713 {
00714 public:
00715 WindowInfoPrivate()
00716 #ifdef Q_WS_X11
00717 : info( NULL )
00718 #endif
00719 {}
00720 #ifdef Q_WS_X11
00721 ~WindowInfoPrivate() { delete info; }
00722 NETWinInfo* info;
00723 #endif
00724 WId win_;
00725 QString name_;
00726 QString iconic_name_;
00727 QRect geometry_;
00728 QRect frame_geometry_;
00729 int ref;
00730 bool valid;
00731 private:
00732 WindowInfoPrivate( const WindowInfoPrivate& );
00733 void operator=( const WindowInfoPrivate& );
00734 };
00735
00736
00737 KWin::WindowInfo::WindowInfo( WId win, unsigned long properties, unsigned long properties2 )
00738 {
00739 #ifdef Q_WS_X11
00740 KXErrorHandler handler;
00741 d = new WindowInfoPrivate;
00742 d->ref = 1;
00743 if( properties == 0 )
00744 properties = NET::WMState |
00745 NET::WMStrut |
00746 NET::WMWindowType |
00747 NET::WMName |
00748 NET::WMVisibleName |
00749 NET::WMIconName |
00750 NET::WMVisibleIconName |
00751 NET::WMDesktop |
00752 NET::WMPid |
00753 NET::WMKDEFrameStrut |
00754 NET::XAWMState |
00755 NET::WMGeometry;
00756 if( properties & NET::WMVisibleIconName )
00757 properties |= NET::WMIconName | NET::WMVisibleName;
00758 if( properties & NET::WMVisibleName )
00759 properties |= NET::WMName;
00760 if( properties2 & NET::WM2ExtendedStrut )
00761 properties |= NET::WMStrut;
00762 properties |= NET::XAWMState;
00763 unsigned long props[ 2 ] = { properties, properties2 };
00764 d->info = new NETWinInfo( qt_xdisplay(), win, qt_xrootwin(), props, 2 );
00765 d->win_ = win;
00766 if( properties & NET::WMName ) {
00767 if( d->info->name() && d->info->name()[ 0 ] != '\0' )
00768 d->name_ = QString::fromUtf8( d->info->name() );
00769 else
00770 d->name_ = readNameProperty( win, XA_WM_NAME );
00771 }
00772 if( properties & NET::WMIconName ) {
00773 if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' )
00774 d->iconic_name_ = QString::fromUtf8( d->info->iconName());
00775 else
00776 d->iconic_name_ = readNameProperty( win, XA_WM_ICON_NAME );
00777 }
00778 if( properties & ( NET::WMGeometry | NET::WMKDEFrameStrut )) {
00779 NETRect frame, geom;
00780 d->info->kdeGeometry( frame, geom );
00781 d->geometry_.setRect( geom.pos.x, geom.pos.y, geom.size.width, geom.size.height );
00782 d->frame_geometry_.setRect( frame.pos.x, frame.pos.y, frame.size.width, frame.size.height );
00783 }
00784 d->valid = !handler.error( false );
00785 #endif
00786 }
00787
00788
00789 KWin::WindowInfo::WindowInfo()
00790 : d( NULL )
00791 {
00792 }
00793
00794 KWin::WindowInfo::~WindowInfo()
00795 {
00796 if( d != NULL ) {
00797 if( --d->ref == 0 ) {
00798 delete d;
00799 }
00800 }
00801 }
00802
00803 KWin::WindowInfo::WindowInfo( const WindowInfo& wininfo )
00804 : d( wininfo.d )
00805 {
00806 if( d != NULL )
00807 ++d->ref;
00808 }
00809
00810 KWin::WindowInfo& KWin::WindowInfo::operator=( const WindowInfo& wininfo )
00811 {
00812 if( d != wininfo.d ) {
00813 if( d != NULL )
00814 if( --d->ref == 0 )
00815 delete d;
00816 d = wininfo.d;
00817 if( d != NULL )
00818 ++d->ref;
00819 }
00820 return *this;
00821 }
00822
00823 bool KWin::WindowInfo::valid( bool withdrawn_is_valid ) const
00824 {
00825 if( !d->valid )
00826 return false;
00827 if( !withdrawn_is_valid && mappingState() == NET::Withdrawn )
00828 return false;
00829 return true;
00830 }
00831
00832 WId KWin::WindowInfo::win() const
00833 {
00834 return d->win_;
00835 }
00836
00837 unsigned long KWin::WindowInfo::state() const
00838 {
00839 #ifdef Q_WS_X11
00840 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMState ) == 0, 176 )
00841 << "Pass NET::WMState to KWin::windowInfo()" << endl;
00842 return d->info->state();
00843 #else
00844 return 0;
00845 #endif
00846 }
00847
00848 NET::MappingState KWin::WindowInfo::mappingState() const
00849 {
00850 #ifdef Q_WS_X11
00851 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::XAWMState ) == 0, 176 )
00852 << "Pass NET::XAWMState to KWin::windowInfo()" << endl;
00853 return d->info->mappingState();
00854 #else
00855 return NET::Visible;
00856 #endif
00857 }
00858
00859 NETExtendedStrut KWin::WindowInfo::extendedStrut() const
00860 {
00861 #ifdef Q_WS_X11
00862 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2ExtendedStrut ) == 0, 176 )
00863 << "Pass NET::WM2ExtendedStrut to second argument of KWin::windowInfo()" << endl;
00864 NETExtendedStrut ext = d->info->extendedStrut();
00865 NETStrut str = d->info->strut();
00866 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0
00867 && ( str.left != 0 || str.right != 0 || str.top != 0 || str.bottom != 0 )) {
00868
00869 if( str.left != 0 ) {
00870 ext.left_width = str.left;
00871 ext.left_start = 0;
00872 ext.left_end = XDisplayHeight( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00873 }
00874 if( str.right != 0 ) {
00875 ext.right_width = str.right;
00876 ext.right_start = 0;
00877 ext.right_end = XDisplayHeight( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00878 }
00879 if( str.top != 0 ) {
00880 ext.top_width = str.top;
00881 ext.top_start = 0;
00882 ext.top_end = XDisplayWidth( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00883 }
00884 if( str.bottom != 0 ) {
00885 ext.bottom_width = str.bottom;
00886 ext.bottom_start = 0;
00887 ext.bottom_end = XDisplayWidth( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00888 }
00889 }
00890 return ext;
00891 #else
00892 NETExtendedStrut n;
00893 return n;
00894 #endif
00895 }
00896
00897 NETStrut KWin::WindowInfo::strut() const
00898 {
00899 #ifdef Q_WS_X11
00900 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMStrut ) == 0, 176 )
00901 << "Pass NET::WMStrut to KWin::windowInfo()" << endl;
00902 return d->info->strut();
00903 #else
00904 NETStrut n;
00905 return n;
00906 #endif
00907 }
00908
00909 NET::WindowType KWin::WindowInfo::windowType( int supported_types ) const
00910 {
00911 #ifdef Q_WS_X11
00912 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMWindowType ) == 0, 176 )
00913 << "Pass NET::WMWindowType to KWin::windowInfo()" << endl;
00914 return d->info->windowType( supported_types );
00915 #else
00916 return 0;
00917 #endif
00918 }
00919
00920 QString KWin::WindowInfo::visibleNameWithState() const
00921 {
00922 QString s = visibleName();
00923 if ( isMinimized() ) {
00924 s.prepend('(');
00925 s.append(')');
00926 }
00927 return s;
00928 }
00929
00930 QString KWin::Info::visibleNameWithState() const
00931 {
00932 QString s = visibleName;
00933 if ( isMinimized() ) {
00934 s.prepend('(');
00935 s.append(')');
00936 }
00937 return s;
00938 }
00939
00940 QString KWin::WindowInfo::visibleName() const
00941 {
00942 #ifdef Q_WS_X11
00943 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMVisibleName ) == 0, 176 )
00944 << "Pass NET::WMVisibleName to KWin::windowInfo()" << endl;
00945 return d->info->visibleName() && d->info->visibleName()[ 0 ] != '\0'
00946 ? QString::fromUtf8(d->info->visibleName()) : name();
00947 #else
00948 return QString("name");
00949 #endif
00950 }
00951
00952 QString KWin::WindowInfo::name() const
00953 {
00954 #ifdef Q_WS_X11
00955 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMName ) == 0, 176 )
00956 << "Pass NET::WMName to KWin::windowInfo()" << endl;
00957 return d->name_;
00958 #else
00959 return QString();
00960 #endif
00961 }
00962
00963 QString KWin::WindowInfo::visibleIconNameWithState() const
00964 {
00965 QString s = visibleIconName();
00966 if ( isMinimized() ) {
00967 s.prepend('(');
00968 s.append(')');
00969 }
00970 return s;
00971 }
00972
00973 QString KWin::WindowInfo::visibleIconName() const
00974 {
00975 #ifdef Q_WS_X11
00976 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMVisibleIconName ) == 0, 176 )
00977 << "Pass NET::WMVisibleIconName to KWin::windowInfo()" << endl;
00978 if( d->info->visibleIconName() && d->info->visibleIconName()[ 0 ] != '\0' )
00979 return QString::fromUtf8( d->info->visibleIconName());
00980 if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' )
00981 return QString::fromUtf8( d->info->iconName());
00982 if( !d->iconic_name_.isEmpty())
00983 return d->iconic_name_;
00984 #endif
00985 return visibleName();
00986 }
00987
00988 QString KWin::WindowInfo::iconName() const
00989 {
00990 #ifdef Q_WS_X11
00991 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMIconName ) == 0, 176 )
00992 << "Pass NET::WMIconName to KWin::windowInfo()" << endl;
00993 if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' )
00994 return QString::fromUtf8( d->info->iconName());
00995 if( !d->iconic_name_.isEmpty())
00996 return d->iconic_name_;
00997 #endif
00998 return name();
00999 }
01000
01001 bool KWin::WindowInfo::isOnCurrentDesktop() const
01002 {
01003 #ifdef Q_WS_X11
01004 return isOnDesktop( KWin::currentDesktop());
01005 #else
01006 return false;
01007 #endif
01008 }
01009
01010 bool KWin::WindowInfo::isOnDesktop( int desktop ) const
01011 {
01012 #ifdef Q_WS_X11
01013 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop ) == 0, 176 )
01014 << "Pass NET::WMDesktop to KWin::windowInfo()" << endl;
01015 return d->info->desktop() == desktop || d->info->desktop() == NET::OnAllDesktops;
01016 #else
01017 return false;
01018 #endif
01019 }
01020
01021 bool KWin::WindowInfo::onAllDesktops() const
01022 {
01023 #ifdef Q_WS_X11
01024 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop ) == 0, 176 )
01025 << "Pass NET::WMDesktop to KWin::windowInfo()" << endl;
01026 return d->info->desktop() == NET::OnAllDesktops;
01027 #else
01028 return false;
01029 #endif
01030 }
01031
01032 int KWin::WindowInfo::desktop() const
01033 {
01034 #ifdef Q_WS_X11
01035 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop ) == 0, 176 )
01036 << "Pass NET::WMDesktop to KWin::windowInfo()" << endl;
01037 return d->info->desktop();
01038 #else
01039 return 1;
01040 #endif
01041 }
01042
01043 QRect KWin::WindowInfo::geometry() const
01044 {
01045 #ifdef Q_WS_X11
01046 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMGeometry ) == 0, 176 )
01047 << "Pass NET::WMGeometry to KWin::windowInfo()" << endl;
01048 return d->geometry_;
01049 #else
01050 return QRect( 100, 100, 200, 200 );
01051 #endif
01052 }
01053
01054 QRect KWin::WindowInfo::frameGeometry() const
01055 {
01056 #ifdef Q_WS_X11
01057 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMKDEFrameStrut ) == 0, 176 )
01058 << "Pass NET::WMKDEFrameStrut to KWin::windowInfo()" << endl;
01059 return d->frame_geometry_;
01060 #else
01061 return QRect();
01062 #endif
01063 }
01064
01065 WId KWin::WindowInfo::transientFor() const
01066 {
01067 #ifdef Q_WS_X11
01068 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2TransientFor ) == 0, 176 )
01069 << "Pass NET::WM2TransientFor to KWin::windowInfo()" << endl;
01070 return d->info->transientFor();
01071 #else
01072 return 0;
01073 #endif
01074 }
01075
01076 WId KWin::WindowInfo::groupLeader() const
01077 {
01078 #ifdef Q_WS_X11
01079 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2GroupLeader ) == 0, 176 )
01080 << "Pass NET::WM2GroupLeader to KWin::windowInfo()" << endl;
01081 return d->info->groupLeader();
01082 #else
01083 return 0;
01084 #endif
01085 }
01086
01087 QCString KWin::WindowInfo::windowClassClass() const
01088 {
01089 #ifdef Q_WS_X11
01090 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowClass ) == 0, 176 )
01091 << "Pass NET::WM2WindowClass to KWin::windowInfo()" << endl;
01092 return d->info->windowClassClass();
01093 #else
01094 return 0;
01095 #endif
01096 }
01097
01098 QCString KWin::WindowInfo::windowClassName() const
01099 {
01100 #ifdef Q_WS_X11
01101 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowClass ) == 0, 176 )
01102 << "Pass NET::WM2WindowClass to KWin::windowInfo()" << endl;
01103 return d->info->windowClassName();
01104 #else
01105 return 0;
01106 #endif
01107 }
01108
01109 QCString KWin::WindowInfo::windowRole() const
01110 {
01111 #ifdef Q_WS_X11
01112 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowRole ) == 0, 176 )
01113 << "Pass NET::WM2WindowRole to KWin::windowInfo()" << endl;
01114 return d->info->windowRole();
01115 #else
01116 return 0;
01117 #endif
01118 }
01119
01120 QCString KWin::WindowInfo::clientMachine() const
01121 {
01122 #ifdef Q_WS_X11
01123 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2ClientMachine ) == 0, 176 )
01124 << "Pass NET::WM2ClientMachine to KWin::windowInfo()" << endl;
01125 return d->info->clientMachine();
01126 #else
01127 return 0;
01128 #endif
01129 }
01130
01131 bool KWin::WindowInfo::actionSupported( NET::Action action ) const
01132 {
01133 #ifdef Q_WS_X11
01134 kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2AllowedActions ) == 0, 176 )
01135 << "Pass NET::WM2AllowedActions to KWin::windowInfo()" << endl;
01136 if( allowedActionsSupported())
01137 return d->info->allowedActions() & action;
01138 else
01139 #endif
01140 return true;
01141 }
01142
01143
01144 bool KWin::WindowInfo::isMinimized() const
01145 {
01146 #ifdef Q_WS_X11
01147 if( mappingState() != NET::Iconic )
01148 return false;
01149
01150 if(( state() & NET::Hidden ) != 0
01151 && ( state() & NET::Shaded ) == 0 )
01152 return true;
01153
01154
01155 return icccmCompliantMappingState() ? false : true;
01156 #else
01157 return false;
01158 #endif
01159 }
01160
01161 bool KWin::Info::isMinimized() const
01162 {
01163 #ifdef Q_WS_X11
01164 if( mappingState != NET::Iconic )
01165 return false;
01166
01167 if(( state & NET::Hidden ) != 0
01168 && ( state & NET::Shaded ) == 0 )
01169 return true;
01170
01171
01172 return icccmCompliantMappingState() ? false : true;
01173 #else
01174 return false;
01175 #endif
01176 }
01177
01178 bool KWin::Info::isIconified() const
01179 {
01180 return isMinimized();
01181 }
01182
01183 bool KWin::icccmCompliantMappingState()
01184 {
01185 #ifdef Q_WS_X11
01186 static enum { noidea, yes, no } wm_is_1_2_compliant = noidea;
01187 if( wm_is_1_2_compliant == noidea ) {
01188 NETRootInfo info( qt_xdisplay(), NET::Supported );
01189 wm_is_1_2_compliant = info.isSupported( NET::Hidden ) ? yes : no;
01190 }
01191 return wm_is_1_2_compliant == yes;
01192 #else
01193 return false;
01194 #endif
01195 }
01196
01197 bool KWin::allowedActionsSupported()
01198 {
01199 #ifdef Q_WS_X11
01200 static enum { noidea, yes, no } wm_supports_allowed_actions = noidea;
01201 if( wm_supports_allowed_actions == noidea ) {
01202 NETRootInfo info( qt_xdisplay(), NET::Supported );
01203 wm_supports_allowed_actions = info.isSupported( NET::WM2AllowedActions ) ? yes : no;
01204 }
01205 return wm_supports_allowed_actions == yes;
01206 #else
01207 return false;
01208 #endif
01209 }
01210
01211 QString KWin::readNameProperty( WId win, unsigned long atom )
01212 {
01213 #ifdef Q_WS_X11
01214 XTextProperty tp;
01215 char **text = NULL;
01216 int count;
01217 #endif
01218 QString result;
01219 #ifdef Q_WS_X11
01220 if ( XGetTextProperty( qt_xdisplay(), win, &tp, atom ) != 0 && tp.value != NULL ) {
01221 if ( XmbTextPropertyToTextList( qt_xdisplay(), &tp, &text, &count) == Success &&
01222 text != NULL && count > 0 ) {
01223 result = QString::fromLocal8Bit( text[0] );
01224 } else if ( tp.encoding == XA_STRING )
01225 result = QString::fromLocal8Bit( (const char*) tp.value );
01226 if( text != NULL )
01227 XFreeStringList( text );
01228 XFree( tp.value );
01229 }
01230 #endif
01231 return result;
01232 }
01233
01234