kdecore Library API Documentation

kwin.cpp

00001 /* This file is part of the KDE libraries 00002 Copyright (C) 1999 Matthias Ettrich (ettrich@kde.org) 00003 00004 $Id: kwin.cpp,v 1.114.2.1 2005/03/29 12:23:43 lunakl Exp $ 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00019 Boston, MA 02111-1307, USA. 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 // we need a const_cast for the shitty X API 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 Sends a client message to the ROOT window. 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 Send a client message to window w 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; /* magic! */ 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 } // namespace 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; // ignore badwindow 00279 Window transient_for = None; 00280 if( XGetTransientForHint( qt_xdisplay(), win, &transient_for )) 00281 return transient_for; 00282 // XGetTransientForHint() did sync 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 Grmbl. See QDialog::show(). That should get fixed in Qt somehow. 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; // ignore badwindow 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 // XGetWMHints() did sync 00324 return window_group; 00325 #else 00326 return 0L; 00327 #endif 00328 } 00329 00330 // this one is deprecated, KWin::WindowInfo should be used instead 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; // ignore badwindow 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 // Always detach before doing something behind QPixmap's back. 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 // Since width can be any arbitrary size, but the icons cannot, 00451 // take the nearest value for best results (ignoring 22 pixel 00452 // icons as they don't exist for apps): 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 // Try to load the icon from the classhint if the app didn't specify 00463 // its own: 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 // If the icon is still a null pixmap, load the 'xapp' icon 00485 // as a last resort: 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 // KWin::info() should be updated too if something has to be changed here 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; // force, in case it will be used as a fallback 00758 if( properties & NET::WMVisibleName ) 00759 properties |= NET::WMName; // force, in case it will be used as a fallback 00760 if( properties2 & NET::WM2ExtendedStrut ) 00761 properties |= NET::WMStrut; // will be used as fallback 00762 properties |= NET::XAWMState; // force to get error detection for valid() 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 ); // no sync - NETWinInfo did roundtrips 00785 #endif 00786 } 00787 00788 // this one is only to make QValueList<> or similar happy 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 // build extended from simple 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; // no idea if it's supported or not -> pretend it is 01141 } 01142 01143 // see NETWM spec section 7.6 01144 bool KWin::WindowInfo::isMinimized() const 01145 { 01146 #ifdef Q_WS_X11 01147 if( mappingState() != NET::Iconic ) 01148 return false; 01149 // NETWM 1.2 compliant WM - uses NET::Hidden for minimized windows 01150 if(( state() & NET::Hidden ) != 0 01151 && ( state() & NET::Shaded ) == 0 ) // shaded may have NET::Hidden too 01152 return true; 01153 // older WMs use WithdrawnState for other virtual desktops 01154 // and IconicState only for minimized 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 // NETWM 1.2 compliant WM - uses NET::Hidden for minimized windows 01167 if(( state & NET::Hidden ) != 0 01168 && ( state & NET::Shaded ) == 0 ) // shaded may have NET::Hidden too 01169 return true; 01170 // older WMs use WithdrawnState for other virtual desktops 01171 // and IconicState only for minimized 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 //#endif
KDE Logo
This file is part of the documentation for kdecore Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 14 00:03:35 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003