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 <qapplication.h>
00030 #include <qbitmap.h>
00031 #include <qimage.h>
00032 #include <qwhatsthis.h>
00033 #include <qcstring.h>
00034
00035 #ifndef Q_WS_QWS
00036 #include "kwin.h"
00037 #include "kapplication.h"
00038
00039 #include <kglobal.h>
00040 #include <kiconloader.h>
00041
00042 #include <kdatastream.h>
00043 #include <klocale.h>
00044 #include <dcopclient.h>
00045 #include <kstartupinfo.h>
00046
00047 #include <X11/Xlib.h>
00048 #include <X11/Xatom.h>
00049 #include <X11/Xutil.h>
00050
00051 #include "netwm.h"
00052
00053 static bool atoms_created = FALSE;
00054 extern Atom qt_wm_protocols;
00055 extern Atom qt_wm_state;
00056
00057
00058 #ifndef None
00059 #define None 0L
00060 #endif
00061
00062 Atom net_wm_context_help;
00063 static Atom kde_wm_change_state;
00064 void kwin_net_create_atoms() {
00065 if (!atoms_created){
00066 const int max = 20;
00067 Atom* atoms[max];
00068 const char* names[max];
00069 Atom atoms_return[max];
00070 int n = 0;
00071
00072 atoms[n] = &net_wm_context_help;
00073 names[n++] = "_NET_WM_CONTEXT_HELP";
00074
00075 atoms[n] = &kde_wm_change_state;
00076 names[n++] = "_KDE_WM_CHANGE_STATE";
00077
00078
00079 XInternAtoms( qt_xdisplay(), const_cast<char**>(names), n, FALSE, atoms_return );
00080 for (int i = 0; i < n; i++ )
00081 *atoms[i] = atoms_return[i];
00082
00083 atoms_created = True;
00084 }
00085 }
00086
00087
00088
00089
00090 static void sendClientMessageToRoot(Window w, Atom a, long x, long y = 0, long z = 0 ){
00091 XEvent ev;
00092 long mask;
00093
00094 memset(&ev, 0, sizeof(ev));
00095 ev.xclient.type = ClientMessage;
00096 ev.xclient.window = w;
00097 ev.xclient.message_type = a;
00098 ev.xclient.format = 32;
00099 ev.xclient.data.l[0] = x;
00100 ev.xclient.data.l[1] = y;
00101 ev.xclient.data.l[2] = z;
00102 mask = SubstructureRedirectMask;
00103 XSendEvent(qt_xdisplay(), qt_xrootwin(), False, mask, &ev);
00104 }
00105
00106
00107
00108
00109 static void sendClientMessage(Window w, Atom a, long x){
00110 XEvent ev;
00111 long mask;
00112
00113 memset(&ev, 0, sizeof(ev));
00114 ev.xclient.type = ClientMessage;
00115 ev.xclient.window = w;
00116 ev.xclient.message_type = a;
00117 ev.xclient.format = 32;
00118 ev.xclient.data.l[0] = x;
00119 ev.xclient.data.l[1] = CurrentTime;
00120 mask = 0L;
00121 if (w == qt_xrootwin())
00122 mask = SubstructureRedirectMask;
00123 XSendEvent(qt_xdisplay(), w, False, mask, &ev);
00124 }
00125
00126 class ContextWidget : public QWidget
00127 {
00128 public:
00129 ContextWidget()
00130 : QWidget(0,0)
00131 {
00132 kwin_net_create_atoms();
00133 kapp->installX11EventFilter( this );
00134 QWhatsThis::enterWhatsThisMode();
00135 QCursor c = *QApplication::overrideCursor();
00136 QWhatsThis::leaveWhatsThisMode();
00137 XGrabPointer( qt_xdisplay(), qt_xrootwin(), TRUE,
00138 (uint)( ButtonPressMask | ButtonReleaseMask |
00139 PointerMotionMask | EnterWindowMask |
00140 LeaveWindowMask ),
00141 GrabModeAsync, GrabModeAsync,
00142 None, c.handle(), CurrentTime );
00143 qApp->enter_loop();
00144 }
00145
00146
00147 bool x11Event( XEvent * ev)
00148 {
00149 if ( ev->type == ButtonPress && ev->xbutton.button == Button1 ) {
00150 XUngrabPointer( qt_xdisplay(), ev->xbutton.time );
00151 Window root;
00152 Window child = qt_xrootwin();
00153 int root_x, root_y, lx, ly;
00154 uint state;
00155 Window w;
00156 do {
00157 w = child;
00158 XQueryPointer( qt_xdisplay(), w, &root, &child,
00159 &root_x, &root_y, &lx, &ly, &state );
00160 } while ( child != None && child != w );
00161
00162 ::sendClientMessage(w, qt_wm_protocols, net_wm_context_help);
00163 XEvent e = *ev;
00164 e.xbutton.window = w;
00165 e.xbutton.subwindow = w;
00166 e.xbutton.x = lx;
00167 e.xbutton.y = ly;
00168 XSendEvent( qt_xdisplay(), w, TRUE, ButtonPressMask, &e );
00169 qApp->exit_loop();
00170 return TRUE;
00171 }
00172 return FALSE;
00173 }
00174 };
00175
00176 void KWin::invokeContextHelp()
00177 {
00178 ContextWidget w;
00179 }
00180
00181 void KWin::setSystemTrayWindowFor( WId trayWin, WId forWin )
00182 {
00183 NETWinInfo info( qt_xdisplay(), trayWin, qt_xrootwin(), 0 );
00184 if ( !forWin )
00185 forWin = qt_xrootwin();
00186 info.setKDESystemTrayWinFor( forWin );
00187 }
00188 void KWin::setActiveWindow( WId win)
00189 {
00190 NETRootInfo info( qt_xdisplay(), 0 );
00191 info.setActiveWindow( win );
00192 }
00193
00194 KWin::Info KWin::info( WId win )
00195 {
00196 Info w;
00197 NETWinInfo inf( qt_xdisplay(), win, qt_xrootwin(),
00198 NET::WMState |
00199 NET::WMStrut |
00200 NET::WMWindowType |
00201 NET::WMName |
00202 NET::WMVisibleName |
00203 NET::WMDesktop |
00204 NET::WMPid |
00205 NET::WMKDEFrameStrut |
00206 NET::XAWMState
00207 );
00208
00209 w.win = win;
00210 w.state = inf.state();
00211 w.mappingState = inf.mappingState();
00212 w.strut = inf.strut();
00213 w.windowType = inf.windowType();
00214 if ( inf.name() ) {
00215 w.name = QString::fromUtf8( inf.name() );
00216 } else {
00217 char* c = 0;
00218 if ( XFetchName( qt_xdisplay(), win, &c ) != 0 ) {
00219 w.name = QString::fromLocal8Bit( c );
00220 XFree( c );
00221 }
00222 }
00223 if ( inf.visibleName() )
00224 w.visibleName = QString::fromUtf8( inf.visibleName() );
00225 else
00226 w.visibleName = w.name;
00227
00228 w.desktop = inf.desktop();
00229 w.onAllDesktops = inf.desktop() == NETWinInfo::OnAllDesktops;
00230 w.pid = inf.pid();
00231 NETRect frame, geom;
00232 inf.kdeGeometry( frame, geom );
00233 w.geometry.setRect( geom.pos.x, geom.pos.y, geom.size.width, geom.size.height );
00234 w.frameGeometry.setRect( frame.pos.x, frame.pos.y, frame.size.width, frame.size.height );
00235 return w;
00236 }
00237
00238 QPixmap KWin::icon( WId win, int width, int height, bool scale )
00239 {
00240 QPixmap result;
00241 NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMIcon );
00242 NETIcon ni = info.icon( width, height );
00243 if ( ni.data && ni.size.width > 0 && ni.size.height > 0 ) {
00244 QImage img( (uchar*) ni.data, (int) ni.size.width, (int) ni.size.height, 32, 0, 0, QImage::IgnoreEndian );
00245 img.setAlphaBuffer( TRUE );
00246 if ( scale && width > 0 && height > 0 &&img.size() != QSize( width, height ) && !img.isNull() )
00247 img = img.smoothScale( width, height );
00248 if ( !img.isNull() )
00249 result.convertFromImage( img );
00250 return result;
00251 }
00252
00253 Pixmap p = None;
00254 Pixmap p_mask = None;
00255
00256 XWMHints *hints = XGetWMHints(qt_xdisplay(), win );
00257 if (hints && (hints->flags & IconPixmapHint)){
00258 p = hints->icon_pixmap;
00259 }
00260 if (hints && (hints->flags & IconMaskHint)){
00261 p_mask = hints->icon_mask;
00262 }
00263 if (hints)
00264 XFree((char*)hints);
00265
00266 if (p != None){
00267 Window root;
00268 int x, y;
00269 unsigned int w = 0;
00270 unsigned int h = 0;
00271 unsigned int border_w, depth;
00272 XGetGeometry(qt_xdisplay(), p, &root,
00273 &x, &y, &w, &h, &border_w, &depth);
00274 if (w > 0 && h > 0){
00275 QPixmap pm(w, h, depth);
00276
00277 pm.detach();
00278 XCopyArea(qt_xdisplay(), p, pm.handle(),
00279 qt_xget_temp_gc(qt_xscreen(), depth==1),
00280 0, 0, w, h, 0, 0);
00281 if (p_mask != None){
00282 QBitmap bm(w, h);
00283 XCopyArea(qt_xdisplay(), p_mask, bm.handle(),
00284 qt_xget_temp_gc(qt_xscreen(), true),
00285 0, 0, w, h, 0, 0);
00286 pm.setMask(bm);
00287 }
00288 if ( scale && width > 0 && height > 0 && !pm.isNull() &&
00289 ( (int) w != width || (int) h != height) ){
00290 result.convertFromImage( pm.convertToImage().smoothScale( width, height ) );
00291 } else {
00292 result = pm;
00293 }
00294 }
00295 }
00296
00297
00298
00299 if( result.isNull() ) {
00300 int iconWidth;
00301
00302
00303
00304
00305 if( width < 24 )
00306 iconWidth = 16;
00307 else if( width < 40 )
00308 iconWidth = 32;
00309 else
00310 iconWidth = 48;
00311
00312 XClassHint hint;
00313 if( XGetClassHint( qt_xdisplay(), win, &hint ) ) {
00314 QString className = hint.res_class;
00315
00316 QPixmap pm = KGlobal::instance()->iconLoader()->loadIcon( className.lower(), KIcon::Small, iconWidth,
00317 KIcon::DefaultState, 0, true );
00318 if( scale && !pm.isNull() )
00319 result.convertFromImage( pm.convertToImage().smoothScale( width, height ) );
00320 else
00321 result = pm;
00322
00323 XFree( hint.res_name );
00324 XFree( hint.res_class );
00325 }
00326
00327
00328
00329 if ( result.isNull() ) {
00330 QPixmap pm = KGlobal::instance()->iconLoader()->loadIcon( "xapp", KIcon::Small, iconWidth,
00331 KIcon::DefaultState, 0, true );
00332 if( scale && !pm.isNull() )
00333 result.convertFromImage( pm.convertToImage().smoothScale( width, height ) );
00334 else
00335 result = pm;
00336 }
00337 }
00338 return result;
00339 }
00340
00341 void KWin::setIcons( WId win, const QPixmap& icon, const QPixmap& miniIcon )
00342 {
00343 if ( icon.isNull() )
00344 return;
00345 NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
00346 QImage img = icon.convertToImage().convertDepth( 32 );
00347 NETIcon ni;
00348 ni.size.width = img.size().width();
00349 ni.size.height = img.size().height();
00350 ni.data = (unsigned char *) img.bits();
00351 info.setIcon( ni, true );
00352 if ( miniIcon.isNull() )
00353 return;
00354 img = miniIcon.convertToImage().convertDepth( 32 );
00355 ni.size.width = img.size().width();
00356 ni.size.height = img.size().height();
00357 ni.data = (unsigned char *) img.bits();
00358 info.setIcon( ni, false );
00359 }
00360
00361 void KWin::setType( WId win, NET::WindowType windowType )
00362 {
00363 NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
00364 info.setWindowType( windowType );
00365 }
00366
00367 void KWin::setState( WId win, unsigned long state )
00368 {
00369 NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMState );
00370 info.setState( state, state );
00371 }
00372
00373 void KWin::clearState( WId win, unsigned long state )
00374 {
00375 NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMState );
00376 info.setState( 0, state );
00377 }
00378
00379 void KWin::setOnAllDesktops( WId win, bool b )
00380 {
00381 NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMDesktop );
00382 if ( b )
00383 info.setDesktop( NETWinInfo::OnAllDesktops );
00384 else if ( info.desktop() == NETWinInfo::OnAllDesktops ) {
00385 NETRootInfo rinfo( qt_xdisplay(), NET::CurrentDesktop );
00386 info.setDesktop( rinfo.currentDesktop() );
00387 }
00388 }
00389
00390 void KWin::setOnDesktop( WId win, int desktop )
00391 {
00392 NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMDesktop );
00393 info.setDesktop( desktop );
00394 }
00395
00396
00397 QString KWin::Info::visibleNameWithState() const
00398 {
00399 QString s = visibleName;
00400 if ( isIconified() ) {
00401 s.prepend('(');
00402 s.append(')');
00403 }
00404 return s;
00405 }
00406
00407
00408 void KWin::setStrut( WId win, int left, int right, int top, int bottom )
00409 {
00410 NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
00411 NETStrut strut;
00412 strut.left = left;
00413 strut.right = right;
00414 strut.top = top;
00415 strut.bottom = bottom;
00416 info.setStrut( strut );
00417 }
00418
00419 int KWin::currentDesktop()
00420 {
00421 if (!qt_xdisplay())
00422 return 0;
00423 NETRootInfo info( qt_xdisplay(), NET::CurrentDesktop );
00424 return info.currentDesktop();
00425 }
00426
00427 int KWin::numberOfDesktops()
00428 {
00429 if (!qt_xdisplay())
00430 return 0;
00431 NETRootInfo info( qt_xdisplay(), NET::NumberOfDesktops );
00432 return info.numberOfDesktops();
00433 }
00434
00435 void KWin::setCurrentDesktop( int desktop )
00436 {
00437 NETRootInfo info( qt_xdisplay(), NET::CurrentDesktop );
00438 info.setCurrentDesktop( desktop );
00439 }
00440
00441
00442 void KWin::iconifyWindow( WId win, bool animation)
00443 {
00444 if ( !animation )
00445 sendClientMessageToRoot( win, kde_wm_change_state, IconicState, 1 );
00446 XIconifyWindow( qt_xdisplay(), win, qt_xscreen() );
00447 }
00448
00449
00450 void KWin::deIconifyWindow( WId win, bool animation )
00451 {
00452 if ( !animation )
00453 sendClientMessageToRoot( win, kde_wm_change_state, NormalState, 1 );
00454 XMapWindow( qt_xdisplay(), win );
00455 }
00456
00457 void KWin::appStarted()
00458 {
00459 KStartupInfo::appStarted();
00460 }
00461
00462
00463 #undef None
00464 #endif