31 #include <QtGui/QApplication>
32 #include <QtGui/QBitmap>
33 #include <QDesktopWidget>
34 #include <QtGui/QDialog>
35 #include <QtDBus/QtDBus>
36 #include <QtGui/QX11Info>
37 #include <X11/Xatom.h>
42 #include <X11/extensions/Xfixes.h>
45 class KWindowSystemStaticContainer {
47 KWindowSystemStaticContainer() : d(0) {}
49 KWindowSystemPrivate* d;
56 static
void create_atoms( Display* dpy = QX11Info::display() );
82 class KWindowSystemPrivate
86 KWindowSystemPrivate(
int _what);
89 QList<WId> stackingOrder;
93 StrutData( WId window_,
const NETStrut& strut_,
int desktop_ )
94 : window( window_ ), strut( strut_ ), desktop( desktop_ ) {}
100 QList<StrutData> strutWindows;
101 QList<WId> possibleStrutWindows;
102 bool strutSignalConnected;
103 bool compositingEnabled;
112 bool x11Event( XEvent * ev );
114 void updateStackingOrder();
115 bool removeStrutWindow( WId );
118 KWindowSystemPrivate::KWindowSystemPrivate(
int _what)
123 strutSignalConnected( false ),
128 (void ) qApp->desktop();
132 if ((haveXfixes = XFixesQueryExtension(QX11Info::display(), &xfixesEventBase, &errorBase))) {
134 XFixesSelectSelectionInput(QX11Info::display(), winId(),
net_wm_cm,
135 XFixesSetSelectionOwnerNotifyMask |
136 XFixesSelectionWindowDestroyNotifyMask |
137 XFixesSelectionClientCloseNotifyMask);
138 compositingEnabled = XGetSelectionOwner(QX11Info::display(),
net_wm_cm) !=
None;
147 updateStackingOrder();
150 bool KWindowSystemPrivate::x11Event( XEvent * ev )
155 if ( ev->type == xfixesEventBase + XFixesSelectionNotify && ev->xany.window == winId() ) {
156 XFixesSelectionNotifyEvent *
event =
reinterpret_cast<XFixesSelectionNotifyEvent*
>(ev);
157 bool haveOwner =
event->owner !=
None;
158 if (compositingEnabled != haveOwner) {
159 compositingEnabled = haveOwner;
166 if ( ev->xany.window == QX11Info::appRootWindow() ) {
167 int old_current_desktop = currentDesktop();
168 WId old_active_window = activeWindow();
169 int old_number_of_desktops = numberOfDesktops();
170 bool old_showing_desktop = showingDesktop();
171 unsigned long m[ 5 ];
174 if (( m[ PROTOCOLS ] & CurrentDesktop ) && currentDesktop() != old_current_desktop )
176 if (( m[ PROTOCOLS ] & DesktopViewport ) && mapViewport() && currentDesktop() != old_current_desktop )
178 if (( m[ PROTOCOLS ] & ActiveWindow ) && activeWindow() != old_active_window )
180 if ( m[ PROTOCOLS ] & DesktopNames )
182 if (( m[ PROTOCOLS ] & NumberOfDesktops ) && numberOfDesktops() != old_number_of_desktops )
184 if (( m[ PROTOCOLS ] & DesktopGeometry ) && mapViewport() && numberOfDesktops() != old_number_of_desktops )
186 if ( m[ PROTOCOLS ] & WorkArea )
188 if ( m[ PROTOCOLS ] & ClientListStacking ) {
189 updateStackingOrder();
192 if(( m[ PROTOCOLS2 ] & WM2ShowingDesktop ) && showingDesktop() != old_showing_desktop ) {
195 }
else if ( windows.contains( ev->xany.window ) ){
196 NETWinInfo ni( QX11Info::display(), ev->xany.window, QX11Info::appRootWindow(), 0 );
197 unsigned long dirty[ 2 ];
198 ni.event( ev, dirty, 2 );
199 if ( ev->type ==PropertyNotify ) {
200 if( ev->xproperty.atom == XA_WM_HINTS )
202 else if( ev->xproperty.atom == XA_WM_NAME )
204 else if( ev->xproperty.atom == XA_WM_ICON_NAME )
214 removeStrutWindow( ev->xany.window );
215 if ( !possibleStrutWindows.contains( ev->xany.window ) )
216 possibleStrutWindows.append( ev->xany.window );
222 if ( (dirty[ NETWinInfo::PROTOCOLS ] & NET::WMStrut) != 0 )
230 bool KWindowSystemPrivate::removeStrutWindow( WId w )
232 for( QList< StrutData >::Iterator it = strutWindows.begin();
233 it != strutWindows.end();
235 if( (*it).window == w ) {
236 strutWindows.erase( it );
242 void KWindowSystemPrivate::updateStackingOrder()
244 stackingOrder.clear();
245 for (
int i = 0; i < clientListStackingCount(); i++ )
246 stackingOrder.append( clientListStacking()[i] );
253 if ( (what >= KWindowSystem::INFO_WINDOWS) && !
QWidget::find( w ) )
254 XSelectInput( QX11Info::display(), w, PropertyChangeMask | StructureNotifyMask );
256 bool emit_strutChanged =
false;
258 if( strutSignalConnected ) {
262 strutWindows.append( StrutData( w, strut, info.desktop()));
263 emit_strutChanged =
true;
266 possibleStrutWindows.append( w );
270 if ( emit_strutChanged )
278 bool emit_strutChanged = removeStrutWindow( w );
279 if( strutSignalConnected && possibleStrutWindows.contains( w )) {
280 NETWinInfo info( QX11Info::display(), w, QX11Info::appRootWindow(), NET::WMStrut );
283 emit_strutChanged =
true;
287 possibleStrutWindows.removeAll( w );
288 windows.removeAll( w );
290 if ( emit_strutChanged )
294 bool KWindowSystemPrivate::mapViewport()
301 && ( desktopGeometry( currentDesktop(
true )).width > QApplication::desktop()->width()
302 || desktopGeometry( currentDesktop(
true )).height > QApplication::desktop()->height()))
317 const char* names[max];
318 Atom atoms_return[max];
322 names[n++] =
"_KDE_WM_CHANGE_STATE";
325 names[n++] =
"WM_PROTOCOLS";
328 names[n++] =
"UTF8_STRING";
330 char net_wm_cm_name[ 100 ];
331 sprintf( net_wm_cm_name,
"_NET_WM_CM_S%d", DefaultScreen( dpy ));
333 names[n++] = net_wm_cm_name;
336 XInternAtoms( dpy, const_cast<char**>(names), n,
false, atoms_return );
337 for (
int i = 0; i < n; i++ )
338 *atoms[i] = atoms_return[i];
340 atoms_created = True;
348 memset(&ev, 0,
sizeof(ev));
349 ev.xclient.type = ClientMessage;
350 ev.xclient.window = w;
351 ev.xclient.message_type = a;
352 ev.xclient.format = 32;
353 ev.xclient.data.l[0] = x;
354 ev.xclient.data.l[1] = y;
355 ev.xclient.data.l[2] = z;
356 mask = SubstructureRedirectMask;
357 XSendEvent(QX11Info::display(), QX11Info::appRootWindow(), False, mask, &ev);
362 return &(g_kwmInstanceContainer->kwm);
366 KWindowSystemPrivate* KWindowSystem::s_d_func()
368 return g_kwmInstanceContainer->d;
375 int what = INFO_BASIC;
378 else if( QLatin1String( signal ) == SIGNAL(
strutChanged()))
380 else if( QLatin1String( signal ) == QMetaObject::normalizedSignature(SIGNAL(
windowChanged(WId,
const ulong*))).constData())
382 else if( QLatin1String( signal ) == QMetaObject::normalizedSignature(SIGNAL(
windowChanged(WId,uint))).constData())
384 else if( QLatin1String( signal ) == QMetaObject::normalizedSignature(SIGNAL(
windowChanged(WId))).constData())
389 if( !s_d->strutSignalConnected && qstrcmp( signal, SIGNAL(
strutChanged())) == 0 )
390 s_d->strutSignalConnected =
true;
397 void KWindowSystem::init(
int what)
401 if (what >= INFO_WINDOWS)
409 g_kwmInstanceContainer->d->activate();
411 else if (s_d->what < what)
415 g_kwmInstanceContainer->d->activate();
422 return s_d_func()->windows;
427 return KWindowInfo( win, properties, properties2 );
433 return s_d_func()->windows.contains( w );
439 return s_d_func()->stackingOrder;
444 if (!QX11Info::display())
450 NETPoint p = s_d->desktopViewport( s_d->currentDesktop(
true ));
456 return s_d->currentDesktop(
true );
458 return info.currentDesktop(
true );
463 if (!QX11Info::display())
469 NETSize s = s_d->desktopGeometry( s_d->currentDesktop(
true ));
470 return s.
width / qApp->desktop()->width() * s.
height / qApp->desktop()->height();
475 return s_d->numberOfDesktops(
true );
477 return info.numberOfDesktops(
true );
490 info.setDesktopViewport( s_d->currentDesktop(
true ), p );
494 info.setCurrentDesktop( desktop,
true );
511 info.setDesktop( rinfo.currentDesktop(
true ), true );
526 unsigned int w, h, b, dp;
527 XGetGeometry( QX11Info::display(), win, &dummy, &x, &y, &w, &h, &b, &dp );
529 XTranslateCoordinates( QX11Info::display(), win, QX11Info::appRootWindow(), 0, 0, &x, &y, &dummy );
533 x = x % qApp->desktop()->width();
534 y = y % qApp->desktop()->height();
536 x = x + qApp->desktop()->width();
538 y = y + qApp->desktop()->height();
546 s_d->moveResizeWindowRequest( win, flags, p.x(), p.y(), w, h );
550 info.setDesktop( desktop,
true );
557 return s_d->activeWindow();
559 return info.activeWindow();
566 time = QX11Info::appUserTime();
568 qApp->activeWindow() ? qApp->activeWindow()->winId() : 0 );
575 time = QX11Info::appTime();
589 if( XGetTransientForHint( QX11Info::display(), win, &transient_for ))
590 return transient_for;
597 subwindow->setAttribute( Qt::WA_X11BypassTransientForHint );
598 if( mainwindow != 0 )
599 XSetTransientForHint( QX11Info::display(), subwindow->winId(), mainwindow );
601 XDeleteProperty( QX11Info::display(), subwindow->winId(), XA_WM_TRANSIENT_FOR );
607 XWMHints *hints = XGetWMHints( QX11Info::display(), win );
611 if( hints->flags & WindowGroupHint )
612 window_group = hints->window_group;
613 XFree( reinterpret_cast< char* >( hints ));
629 if( flags &
NETWM ) {
631 NETIcon ni = info.icon( width, height );
634 if ( scale && width > 0 && height > 0 &&img.size() !=
QSize( width, height ) && !img.isNull() )
635 img = img.scaled( width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
637 result = QPixmap::fromImage( img );
644 Pixmap p_mask =
None;
646 XWMHints *hints = XGetWMHints(QX11Info::display(), win );
647 if (hints && (hints->flags & IconPixmapHint)){
648 p = hints->icon_pixmap;
650 if (hints && (hints->flags & IconMaskHint)){
651 p_mask = hints->icon_mask;
658 if ( scale && width > 0 && height > 0 && !pm.isNull()
659 && ( pm.width() != width || pm.height() != height) ){
660 result = QPixmap::fromImage( pm.toImage().scaled( width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) );
673 else if( width < 40 )
681 if( result.isNull() ) {
684 if( XGetClassHint( QX11Info::display(), win, &hint ) ) {
685 QString className = hint.res_class;
689 if( scale && !pm.isNull() )
690 result = QPixmap::fromImage( pm.toImage().scaled( width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) );
694 XFree( hint.res_name );
695 XFree( hint.res_class );
703 if ( result.isNull() ) {
705 KIconLoader::DefaultState,
QStringList(), 0,
true );
706 if( scale && !pm.isNull() )
707 result = QPixmap::fromImage( pm.toImage().scaled( width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) );
719 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), 0 );
720 QImage img = icon.toImage().convertToFormat( QImage::Format_ARGB32 );
724 ni.
data = (
unsigned char *) img.bits();
725 info.setIcon( ni,
true );
726 if ( miniIcon.isNull() )
728 img = miniIcon.toImage().convertToFormat( QImage::Format_ARGB32 );
733 ni.
data = (
unsigned char *) img.bits();
734 info.setIcon( ni,
false );
739 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), 0 );
740 info.setWindowType( windowType );
746 info.setState( state, state );
752 info.setState( 0, state );
763 XIconifyWindow( QX11Info::display(), win, inf.screen() );
773 XMapWindow( QX11Info::display(), win );
780 info.restackRequest( win,
NET::FromTool, None, Above, QX11Info::appUserTime());
782 XRaiseWindow( QX11Info::display(), win );
789 info.restackRequest( win,
NET::FromTool, None, Below, QX11Info::appUserTime());
791 XLowerWindow( QX11Info::display(), win );
796 if( QX11Info::display()) {
798 if (s_d_func()->haveXfixes) {
799 return s_d_func()->compositingEnabled;
802 return XGetSelectionOwner( QX11Info::display(),
net_wm_cm );
805 Display* dpy = XOpenDisplay( NULL );
808 XCloseDisplay( dpy );
816 int desk = (desktop > 0 && desktop <= (int) s_d_func()->numberOfDesktops() ) ? desktop :
currentDesktop();
818 return QApplication::desktop()->geometry();
820 NETRect r = s_d_func()->workArea( desk );
822 return QApplication::desktop()->geometry();
829 init( INFO_WINDOWS );
832 QRect all = QApplication::desktop()->geometry();
836 desktop = s_d->currentDesktop();
838 QList<WId>::ConstIterator it1;
839 for( it1 = s_d->windows.constBegin(); it1 != s_d->windows.constEnd(); ++it1 ) {
841 if(exclude.contains(*it1))
848 QList< KWindowSystemPrivate::StrutData >::Iterator it2 = s_d->strutWindows.begin();
849 for( ; it2 != s_d->strutWindows.end(); ++it2 )
850 if( (*it2).window == *it1 )
853 if( it2 != s_d->strutWindows.end()) {
857 strut = (*it2).strut;
858 }
else if( s_d->possibleStrutWindows.contains( *it1 ) ) {
861 strut = info.strut();
862 s_d->possibleStrutWindows.removeAll( *it1 );
863 s_d->strutWindows.append( KWindowSystemPrivate::StrutData( *it1, info.strut(), info.desktop()));
871 if ( strut.
left > 0 )
872 r.setLeft( r.left() + (int) strut.
left );
874 r.setTop( r.top() + (int) strut.
top );
875 if ( strut.
right > 0 )
876 r.setRight( r.right() - (int) strut.
right );
878 r.setBottom( r.bottom() - (int) strut.
bottom );
890 bool isDesktopSane = (desktop > 0 && desktop <= (int) s_d->numberOfDesktops());
893 if ( name && name[0] )
894 return QString::fromUtf8( name );
896 return i18n(
"Desktop %1", desktop );
907 s_d->setDesktopName( desktop, name.toUtf8().constData() );
912 info.setDesktopName( desktop, name.toUtf8().constData() );
918 return s_d_func()->showingDesktop();
923 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), 0 );
924 info.setUserTime( time );
928 int right_width,
int right_start,
int right_end,
int top_width,
int top_start,
int top_end,
929 int bottom_width,
int bottom_start,
int bottom_end )
931 NETWinInfo info( QX11Info::display(), win, QX11Info::appRootWindow(), 0 );
945 info.setExtendedStrut( strut );
947 oldstrut.
left = left_width;
948 oldstrut.
right = right_width;
949 oldstrut.
top = top_width;
950 oldstrut.
bottom = bottom_width;
951 info.setStrut( oldstrut );
956 int w = XDisplayWidth( QX11Info::display(), DefaultScreen( QX11Info::display()));
957 int h = XDisplayHeight( QX11Info::display(), DefaultScreen( QX11Info::display()));
958 setExtendedStrut( win, left, 0, left != 0 ? w : 0, right, 0, right != 0 ? w : 0,
959 top, 0, top != 0 ? h : 0, bottom, 0, bottom != 0 ? h : 0 );
964 static enum { noidea,
yes,
no } wm_is_1_2_compliant = noidea;
965 if( wm_is_1_2_compliant == noidea ) {
969 return wm_is_1_2_compliant ==
yes;
974 static enum { noidea,
yes,
no } wm_supports_allowed_actions = noidea;
975 if( wm_supports_allowed_actions == noidea ) {
979 return wm_supports_allowed_actions ==
yes;
988 if ( XGetTextProperty( QX11Info::display(), win, &tp, atom ) != 0 && tp.value != NULL ) {
991 if ( tp.encoding == kwm_utf8_string ) {
992 result = QString::fromUtf8 ( (
const char*) tp.value );
993 }
else if ( XmbTextPropertyToTextList( QX11Info::display(), &tp, &text, &count) == Success &&
994 text != NULL && count > 0 ) {
995 result = QString::fromLocal8Bit( text[0] );
996 }
else if ( tp.encoding == XA_STRING )
997 result = QString::fromLocal8Bit( (
const char*) tp.value );
999 XFreeStringList( text );
1007 QDBusInterface(
"org.kde.kwin",
"/KWin",
"org.kde.KWin", QDBusConnection::sessionBus())
1008 .call(
"doNotManage", title);
1019 NETWinInfo info( QX11Info::display(), window, QX11Info::appRootWindow(), 0 );
1020 info.setBlockingCompositing( active );
1028 return s_d->mapViewport();
1045 NETSize s = s_d->desktopGeometry( s_d->currentDesktop(
true ));
1046 QSize vs = qApp->desktop()->size();
1047 int xs = s.
width / vs.width();
1048 int x = p.x() < 0 ? 0 : p.x() >= s.
width ? xs - 1 : p.x() / vs.width();
1049 int ys = s.
height / vs.height();
1050 int y = p.y() < 0 ? 0 : p.y() >= s.
height ? ys - 1 : p.y() / vs.height();
1051 return y * xs + x + 1;
1060 p =
QPoint( p.x() + s_d->desktopViewport( s_d->currentDesktop(
true )).x,
1061 p.y() + s_d->desktopViewport( s_d->currentDesktop(
true )).y );
1062 NETSize s = s_d->desktopGeometry( s_d->currentDesktop(
true ));
1063 QSize vs = qApp->desktop()->size();
1064 int xs = s.
width / vs.width();
1065 int x = p.x() < 0 ? 0 : p.x() >= s.
width ? xs - 1 : p.x() / vs.width();
1066 int ys = s.
height / vs.height();
1067 int y = p.y() < 0 ? 0 : p.y() >= s.
height ? ys - 1 : p.y() / vs.height();
1068 return y * xs + x + 1;
1075 NETSize s = s_d->desktopGeometry( s_d->currentDesktop(
true ));
1076 QSize vs = qApp->desktop()->size();
1077 int xs = s.
width / vs.width();
1078 int ys = s.
height / vs.height();
1079 if( desktop <= 0 || desktop > xs * ys )
1082 QPoint ret( vs.width() * ( desktop % xs ), vs.height() * ( desktop / xs ));
1084 ret =
QPoint( ret.x() - s_d->desktopViewport( s_d->currentDesktop(
true )).x,
1085 ret.y() - s_d->desktopViewport( s_d->currentDesktop(
true )).y );
1086 if( ret.x() >= s.
width )
1087 ret.setX( ret.x() - s.
width );
1089 ret.setX( ret.x() + s.
width );
1090 if( ret.y() >= s.
height )
1091 ret.setY( ret.y() - s.
height );
1093 ret.setY( ret.y() + s.
height );
1102 NETSize s = s_d->desktopGeometry( s_d->currentDesktop(
true ));
1103 NETPoint c = s_d->desktopViewport( s_d->currentDesktop(
true ));
1104 int x = ( pos.x() + c.
x ) % s.
width;
1105 int y = ( pos.y() + c.
y ) % s.
height;
1113 #include "kwindowsystem.moc"