summaryrefslogtreecommitdiffstats
path: root/kdecore/kwin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdecore/kwin.cpp')
-rw-r--r--kdecore/kwin.cpp1269
1 files changed, 1269 insertions, 0 deletions
diff --git a/kdecore/kwin.cpp b/kdecore/kwin.cpp
new file mode 100644
index 000000000..1e94b99db
--- /dev/null
+++ b/kdecore/kwin.cpp
@@ -0,0 +1,1269 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Matthias Ettrich (ettrich@kde.org)
+
+ $Id$
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef HAVE_SYSENT_H
+#include <sysent.h>
+#endif
+
+#include <kuniqueapplication.h>
+#include <qbitmap.h>
+#include <qimage.h>
+#include <qwhatsthis.h>
+#include <qcstring.h>
+#include <qdialog.h>
+
+#include "config.h"
+#include "kwin.h"
+#include "kapplication.h"
+
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+
+#include <kdatastream.h>
+#include <klocale.h>
+#include <dcopclient.h>
+#include <dcopref.h>
+#ifdef Q_WS_X11
+#include <kstartupinfo.h>
+#include <kxerrorhandler.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+
+#include "netwm.h"
+
+static bool atoms_created = false;
+extern Atom qt_wm_protocols;
+extern Time qt_x_time;
+extern Time qt_x_user_time;
+
+static Atom net_wm_context_help;
+static Atom kde_wm_change_state;
+static Atom kde_wm_window_opacity;
+static Atom kde_wm_window_shadow;
+static Atom kwin_UTF8_STRING;
+static Atom net_wm_cm;
+
+static void kwin_net_create_atoms() {
+ if (!atoms_created){
+ const int max = 20;
+ Atom* atoms[max];
+ const char* names[max];
+ Atom atoms_return[max];
+ int n = 0;
+
+ atoms[n] = &net_wm_context_help;
+ names[n++] = "_NET_WM_CONTEXT_HELP";
+
+ atoms[n] = &kde_wm_change_state;
+ names[n++] = "_KDE_WM_CHANGE_STATE";
+
+ atoms[n] = &kde_wm_window_opacity;
+ names[n++] = (char*) "_KDE_WM_WINDOW_OPACITY";
+
+ atoms[n] = &kde_wm_window_shadow;
+ names[n++] = (char*) "_KDE_WM_WINDOW_SHADOW";
+
+ char net_wm_cm_name[ 100 ];
+ sprintf( net_wm_cm_name, "_NET_WM_CM_S%d", DefaultScreen( qt_xdisplay()));
+ atoms[n] = &net_wm_cm;
+ names[n++] = net_wm_cm_name;
+
+ // we need a const_cast for the shitty X API
+ XInternAtoms( qt_xdisplay(), const_cast<char**>(names), n, false, atoms_return );
+ for (int i = 0; i < n; i++ )
+ *atoms[i] = atoms_return[i];
+
+ atoms_created = True;
+ }
+}
+#endif
+
+/*
+ Sends a client message to the ROOT window.
+ */
+#ifdef Q_WS_X11
+static void sendClientMessageToRoot(Window w, Atom a, long x, long y = 0, long z = 0 ){
+ XEvent ev;
+ long mask;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = w;
+ ev.xclient.message_type = a;
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = x;
+ ev.xclient.data.l[1] = y;
+ ev.xclient.data.l[2] = z;
+ mask = SubstructureRedirectMask;
+ XSendEvent(qt_xdisplay(), qt_xrootwin(), False, mask, &ev);
+}
+#endif
+
+/*
+ Send a client message to window w
+ */
+#ifdef Q_WS_X11
+static void sendClientMessage(Window w, Atom a, long x){
+ XEvent ev;
+ long mask;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.xclient.type = ClientMessage;
+ ev.xclient.window = w;
+ ev.xclient.message_type = a;
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = x;
+ ev.xclient.data.l[1] = CurrentTime;
+ mask = 0L;
+ if (w == qt_xrootwin())
+ mask = SubstructureRedirectMask; /* magic! */
+ XSendEvent(qt_xdisplay(), w, False, mask, &ev);
+}
+#endif
+
+bool KWin::compositingActive()
+{
+#ifdef Q_WS_X11
+ kwin_net_create_atoms();
+ return XGetSelectionOwner( qt_xdisplay(), net_wm_cm ) != None;
+#else
+ return false;
+#endif
+}
+
+#ifdef Q_WS_X11
+namespace
+{
+class ContextWidget : public QWidget
+{
+public:
+ ContextWidget();
+ virtual bool x11Event( XEvent * ev);
+};
+
+ContextWidget::ContextWidget()
+ : QWidget(0,0)
+ {
+ kwin_net_create_atoms();
+ kapp->installX11EventFilter( this );
+ QWhatsThis::enterWhatsThisMode();
+ QCursor c = *QApplication::overrideCursor();
+ QWhatsThis::leaveWhatsThisMode();
+ XGrabPointer( qt_xdisplay(), qt_xrootwin(), true,
+ (uint)( ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask | EnterWindowMask |
+ LeaveWindowMask ),
+ GrabModeAsync, GrabModeAsync,
+ None, c.handle(), CurrentTime );
+ qApp->enter_loop();
+ }
+
+
+bool ContextWidget::x11Event( XEvent * ev)
+ {
+ if ( ev->type == ButtonPress && ev->xbutton.button == Button1 ) {
+ XUngrabPointer( qt_xdisplay(), ev->xbutton.time );
+ Window root;
+ Window child = qt_xrootwin();
+ int root_x, root_y, lx, ly;
+ uint state;
+ Window w;
+ do {
+ w = child;
+ XQueryPointer( qt_xdisplay(), w, &root, &child,
+ &root_x, &root_y, &lx, &ly, &state );
+ } while ( child != None && child != w );
+
+ ::sendClientMessage(w, qt_wm_protocols, net_wm_context_help);
+ XEvent e = *ev;
+ e.xbutton.window = w;
+ e.xbutton.subwindow = w;
+ e.xbutton.x = lx;
+ e.xbutton.y = ly;
+ XSendEvent( qt_xdisplay(), w, true, ButtonPressMask, &e );
+ qApp->exit_loop();
+ return true;
+ }
+ return false;
+ }
+} // namespace
+#endif
+
+void KWin::invokeContextHelp()
+{
+#ifdef Q_WS_X11
+ ContextWidget w;
+#endif
+}
+
+void KWin::setSystemTrayWindowFor( WId trayWin, WId forWin )
+{
+#ifdef Q_WS_X11
+ NETWinInfo info( qt_xdisplay(), trayWin, qt_xrootwin(), 0 );
+ if ( !forWin )
+ forWin = qt_xrootwin();
+ info.setKDESystemTrayWinFor( forWin );
+ NETRootInfo rootinfo( qt_xdisplay(), NET::Supported );
+ if( !rootinfo.isSupported( NET::WMKDESystemTrayWinFor )) {
+ DCOPRef ref( "kded", "kded" );
+ if( !ref.send( "loadModule", QCString( "kdetrayproxy" )))
+ kdWarning( 176 ) << "Loading of kdetrayproxy failed." << endl;
+ }
+#endif
+}
+
+void KWin::activateWindow( WId win, long time )
+{
+#ifdef Q_WS_X11
+ NETRootInfo info( qt_xdisplay(), 0 );
+ if( time == 0 )
+ time = qt_x_user_time;
+ info.setActiveWindow( win, NET::FromApplication, time,
+ kapp->activeWindow() ? kapp->activeWindow()->winId() : 0 );
+#endif // Q_WS_X11 ...
+ KUniqueApplication::setHandleAutoStarted();
+}
+
+void KWin::forceActiveWindow( WId win, long time )
+{
+#ifdef Q_WS_X11
+ NETRootInfo info( qt_xdisplay(), 0 );
+ if( time == 0 )
+ time = qt_x_time;
+ info.setActiveWindow( win, NET::FromTool, time, 0 );
+#endif // Q_WS_X11
+ KUniqueApplication::setHandleAutoStarted();
+}
+
+void KWin::setActiveWindow( WId win )
+{
+#ifdef Q_WS_X11
+ NETRootInfo info( qt_xdisplay(), 0 );
+ info.setActiveWindow( win, NET::FromUnknown, 0, 0 );
+#endif
+ KUniqueApplication::setHandleAutoStarted();
+}
+
+void KWin::demandAttention( WId win, bool set )
+{
+#ifdef Q_WS_X11
+ NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
+ info.setState( set ? NET::DemandsAttention : 0, NET::DemandsAttention );
+#endif
+}
+
+void KWin::setUserTime( WId win, long time )
+{
+#ifdef Q_WS_X11
+ NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
+ info.setUserTime( time );
+#endif
+}
+
+KWin::WindowInfo KWin::windowInfo( WId win, unsigned long properties, unsigned long properties2 )
+{
+ return WindowInfo( win, properties, properties2 );
+}
+
+
+WId KWin::transientFor( WId win )
+{
+#ifdef Q_WS_X11
+ KXErrorHandler handler; // ignore badwindow
+ Window transient_for = None;
+ if( XGetTransientForHint( qt_xdisplay(), win, &transient_for ))
+ return transient_for;
+ // XGetTransientForHint() did sync
+ return None;
+#else
+ return 0L;
+#endif
+}
+
+void KWin::setMainWindow( QWidget* subwindow, WId mainwindow )
+{
+#ifdef Q_WS_X11
+ if( mainwindow != 0 )
+ {
+ /*
+ Grmbl. See QDialog::show(). That should get fixed in Qt somehow.
+ */
+ if( qt_cast< QDialog* >( subwindow ) != NULL
+ && subwindow->parentWidget() == NULL
+ && kapp->mainWidget() != NULL )
+ {
+ kdWarning() << "KWin::setMainWindow(): There either mustn't be kapp->mainWidget(),"
+ " or the dialog must have a non-NULL parent, otherwise Qt will reset the change. Bummer." << endl;
+ }
+ XSetTransientForHint( qt_xdisplay(), subwindow->winId(), mainwindow );
+ }
+ else
+ XDeleteProperty( qt_xdisplay(), subwindow->winId(), XA_WM_TRANSIENT_FOR );
+#endif
+}
+
+WId KWin::groupLeader( WId win )
+{
+#ifdef Q_WS_X11
+ KXErrorHandler handler; // ignore badwindow
+ XWMHints *hints = XGetWMHints( qt_xdisplay(), win );
+ Window window_group = None;
+ if ( hints )
+ {
+ if( hints->flags & WindowGroupHint )
+ window_group = hints->window_group;
+ XFree( reinterpret_cast< char* >( hints ));
+ }
+ // XGetWMHints() did sync
+ return window_group;
+#else
+ return 0L;
+#endif
+}
+
+// this one is deprecated, KWin::WindowInfo should be used instead
+KWin::Info KWin::info( WId win )
+{
+ Info w;
+#ifdef Q_WS_X11
+ NETWinInfo inf( qt_xdisplay(), win, qt_xrootwin(),
+ NET::WMState |
+ NET::WMStrut |
+ NET::WMWindowType |
+ NET::WMName |
+ NET::WMVisibleName |
+ NET::WMDesktop |
+ NET::WMPid |
+ NET::WMKDEFrameStrut |
+ NET::XAWMState
+ );
+
+ w.win = win;
+ w.state = inf.state();
+ w.mappingState = inf.mappingState();
+ w.strut = inf.strut();
+ w.windowType = inf.windowType( -1U );
+ if ( inf.name() ) {
+ w.name = QString::fromUtf8( inf.name() );
+ } else {
+ char* c = 0;
+ if ( XFetchName( qt_xdisplay(), win, &c ) != 0 ) {
+ w.name = QString::fromLocal8Bit( c );
+ XFree( c );
+ }
+ }
+ if ( inf.visibleName() )
+ w.visibleName = QString::fromUtf8( inf.visibleName() );
+ else
+ w.visibleName = w.name;
+
+ w.desktop = inf.desktop();
+ w.onAllDesktops = inf.desktop() == NETWinInfo::OnAllDesktops;
+ w.pid = inf.pid();
+ NETRect frame, geom;
+ inf.kdeGeometry( frame, geom );
+ w.geometry.setRect( geom.pos.x, geom.pos.y, geom.size.width, geom.size.height );
+ w.frameGeometry.setRect( frame.pos.x, frame.pos.y, frame.size.width, frame.size.height );
+#endif
+ return w;
+}
+
+QPixmap KWin::icon( WId win, int width, int height, bool scale )
+{
+ return icon( win, width, height, scale, NETWM | WMHints | ClassHint | XApp );
+}
+
+
+QPixmap KWin::icon( WId win, int width, int height, bool scale, int flags )
+{
+#ifdef Q_WS_X11
+ KXErrorHandler handler; // ignore badwindow
+#endif
+ QPixmap result;
+#ifdef Q_WS_X11
+ if( flags & NETWM ) {
+ NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMIcon );
+ NETIcon ni = info.icon( width, height );
+ if ( ni.data && ni.size.width > 0 && ni.size.height > 0 ) {
+ QImage img( (uchar*) ni.data, (int) ni.size.width, (int) ni.size.height, 32, 0, 0, QImage::IgnoreEndian );
+ img.setAlphaBuffer( true );
+ if ( scale && width > 0 && height > 0 &&img.size() != QSize( width, height ) && !img.isNull() )
+ img = img.smoothScale( width, height );
+ if ( !img.isNull() )
+ result.convertFromImage( img );
+ return result;
+ }
+ }
+
+ if( flags & WMHints ) {
+ Pixmap p = None;
+ Pixmap p_mask = None;
+
+ XWMHints *hints = XGetWMHints(qt_xdisplay(), win );
+ if (hints && (hints->flags & IconPixmapHint)){
+ p = hints->icon_pixmap;
+ }
+ if (hints && (hints->flags & IconMaskHint)){
+ p_mask = hints->icon_mask;
+ }
+ if (hints)
+ XFree((char*)hints);
+
+ if (p != None){
+ Window root;
+ int x, y;
+ unsigned int w = 0;
+ unsigned int h = 0;
+ unsigned int border_w, depth;
+ XGetGeometry(qt_xdisplay(), p, &root,
+ &x, &y, &w, &h, &border_w, &depth);
+ if (w > 0 && h > 0){
+ QPixmap pm(w, h, depth);
+ // Always detach before doing something behind QPixmap's back.
+ pm.detach();
+ XCopyArea(qt_xdisplay(), p, pm.handle(),
+ qt_xget_temp_gc(qt_xscreen(), depth==1),
+ 0, 0, w, h, 0, 0);
+ if (p_mask != None){
+ QBitmap bm(w, h);
+ XCopyArea(qt_xdisplay(), p_mask, bm.handle(),
+ qt_xget_temp_gc(qt_xscreen(), true),
+ 0, 0, w, h, 0, 0);
+ pm.setMask(bm);
+ }
+ if ( scale && width > 0 && height > 0 && !pm.isNull() &&
+ ( (int) w != width || (int) h != height) ){
+ result.convertFromImage( pm.convertToImage().smoothScale( width, height ) );
+ } else {
+ result = pm;
+ }
+ }
+ }
+ }
+
+ // Since width can be any arbitrary size, but the icons cannot,
+ // take the nearest value for best results (ignoring 22 pixel
+ // icons as they don't exist for apps):
+ int iconWidth;
+ if( width < 24 )
+ iconWidth = 16;
+ else if( width < 40 )
+ iconWidth = 32;
+ else
+ iconWidth = 48;
+
+ if( flags & ClassHint ) {
+ // Try to load the icon from the classhint if the app didn't specify
+ // its own:
+ if( result.isNull() ) {
+
+ XClassHint hint;
+ if( XGetClassHint( qt_xdisplay(), win, &hint ) ) {
+ QString className = hint.res_class;
+
+ QPixmap pm = KGlobal::instance()->iconLoader()->loadIcon( className.lower(), KIcon::Small, iconWidth,
+ KIcon::DefaultState, 0, true );
+ if( scale && !pm.isNull() )
+ result.convertFromImage( pm.convertToImage().smoothScale( width, height ) );
+ else
+ result = pm;
+
+ XFree( hint.res_name );
+ XFree( hint.res_class );
+ }
+ }
+ }
+
+ if( flags & XApp ) {
+ // If the icon is still a null pixmap, load the 'xapp' icon
+ // as a last resort:
+ if ( result.isNull() ) {
+ QPixmap pm = KGlobal::instance()->iconLoader()->loadIcon( "xapp", KIcon::Small, iconWidth,
+ KIcon::DefaultState, 0, true );
+ if( scale && !pm.isNull() )
+ result.convertFromImage( pm.convertToImage().smoothScale( width, height ) );
+ else
+ result = pm;
+ }
+ }
+#endif
+ return result;
+}
+
+void KWin::setIcons( WId win, const QPixmap& icon, const QPixmap& miniIcon )
+{
+#ifdef Q_WS_X11
+ if ( icon.isNull() )
+ return;
+ NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
+ QImage img = icon.convertToImage().convertDepth( 32 );
+ NETIcon ni;
+ ni.size.width = img.size().width();
+ ni.size.height = img.size().height();
+ ni.data = (unsigned char *) img.bits();
+ info.setIcon( ni, true );
+ if ( miniIcon.isNull() )
+ return;
+ img = miniIcon.convertToImage().convertDepth( 32 );
+ ni.size.width = img.size().width();
+ ni.size.height = img.size().height();
+ ni.data = (unsigned char *) img.bits();
+ info.setIcon( ni, false );
+#endif
+}
+
+void KWin::setType( WId win, NET::WindowType windowType )
+{
+#ifdef Q_WS_X11
+ NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
+ info.setWindowType( windowType );
+#endif
+}
+
+void KWin::setState( WId win, unsigned long state )
+{
+#ifdef Q_WS_X11
+ NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMState );
+ info.setState( state, state );
+#endif
+}
+
+void KWin::clearState( WId win, unsigned long state )
+{
+#ifdef Q_WS_X11
+ NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMState );
+ info.setState( 0, state );
+#endif
+}
+
+void KWin::setOpacity( WId win, uint percent )
+{
+#ifdef Q_WS_X11
+ kwin_net_create_atoms();
+ if (percent > 99)
+ XDeleteProperty (qt_xdisplay(), win, kde_wm_window_opacity);
+ else
+ {
+ long opacity = long(0xFFFFFFFF/100.0*percent);
+ XChangeProperty(qt_xdisplay(), win, kde_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opacity, 1L);
+ }
+#endif
+}
+
+void KWin::setShadowSize( WId win, uint percent )
+{
+#ifdef Q_WS_X11
+ kwin_net_create_atoms();
+ long shadowSize = long(0xFFFFFFFF/100.0*percent);
+ XChangeProperty(qt_xdisplay(), win, kde_wm_window_shadow, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &shadowSize, 1L);
+#endif
+}
+
+void KWin::setOnAllDesktops( WId win, bool b )
+{
+#ifdef Q_WS_X11
+ NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMDesktop );
+ if ( b )
+ info.setDesktop( NETWinInfo::OnAllDesktops );
+ else if ( info.desktop() == NETWinInfo::OnAllDesktops ) {
+ NETRootInfo rinfo( qt_xdisplay(), NET::CurrentDesktop );
+ info.setDesktop( rinfo.currentDesktop() );
+ }
+#endif
+}
+
+void KWin::setOnDesktop( WId win, int desktop )
+{
+#ifdef Q_WS_X11
+ NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), NET::WMDesktop );
+ info.setDesktop( desktop );
+#endif
+}
+
+void KWin::setExtendedStrut( WId win, int left_width, int left_start, int left_end,
+ int right_width, int right_start, int right_end, int top_width, int top_start, int top_end,
+ int bottom_width, int bottom_start, int bottom_end )
+{
+#ifdef Q_WS_X11
+ NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
+ NETExtendedStrut strut;
+ strut.left_width = left_width;
+ strut.right_width = right_width;
+ strut.top_width = top_width;
+ strut.bottom_width = bottom_width;
+ strut.left_start = left_start;
+ strut.left_end = left_end;
+ strut.right_start = right_start;
+ strut.right_end = right_end;
+ strut.top_start = top_start;
+ strut.top_end = top_end;
+ strut.bottom_start = bottom_start;
+ strut.bottom_end = bottom_end;
+ info.setExtendedStrut( strut );
+#endif
+}
+
+void KWin::setStrut( WId win, int left, int right, int top, int bottom )
+{
+#ifdef Q_WS_X11
+ NETWinInfo info( qt_xdisplay(), win, qt_xrootwin(), 0 );
+ NETStrut strut;
+ strut.left = left;
+ strut.right = right;
+ strut.top = top;
+ strut.bottom = bottom;
+ info.setStrut( strut );
+#endif
+}
+
+int KWin::currentDesktop()
+{
+#ifdef Q_WS_X11
+ if (!qt_xdisplay())
+#endif
+ return 1;
+#ifdef Q_WS_X11
+ NETRootInfo info( qt_xdisplay(), NET::CurrentDesktop );
+ return info.currentDesktop();
+#endif
+}
+
+int KWin::numberOfDesktops()
+{
+#ifdef Q_WS_X11
+ if (!qt_xdisplay())
+#endif
+ return 0;
+#ifdef Q_WS_X11
+ NETRootInfo info( qt_xdisplay(), NET::NumberOfDesktops );
+ return info.numberOfDesktops();
+#endif
+}
+
+void KWin::setCurrentDesktop( int desktop )
+{
+#ifdef Q_WS_X11
+ NETRootInfo info( qt_xdisplay(), NET::CurrentDesktop );
+ info.setCurrentDesktop( desktop );
+#endif
+}
+
+void KWin::setCurrentDesktopViewport( int desktop, QPoint viewport )
+{
+#ifdef Q_WS_X11
+ NETRootInfo info( qt_xdisplay(), NET::CurrentDesktop );
+ NETPoint netview;
+ netview.x = viewport.x();
+ netview.y = viewport.y();
+ info.setDesktopViewport( desktop, netview );
+#endif
+}
+
+void KWin::iconifyWindow( WId win, bool animation)
+{
+#ifdef Q_WS_X11
+ if ( !animation )
+ {
+ kwin_net_create_atoms();
+ sendClientMessageToRoot( win, kde_wm_change_state, IconicState, 1 );
+ }
+ XIconifyWindow( qt_xdisplay(), win, qt_xscreen() );
+#endif
+}
+
+
+void KWin::deIconifyWindow( WId win, bool animation )
+{
+#ifdef Q_WS_X11
+ if ( !animation )
+ {
+ kwin_net_create_atoms();
+ sendClientMessageToRoot( win, kde_wm_change_state, NormalState, 1 );
+ }
+ XMapWindow( qt_xdisplay(), win );
+#endif
+}
+
+void KWin::raiseWindow( WId win )
+{
+#ifdef Q_WS_X11
+ NETRootInfo info( qt_xdisplay(), NET::Supported );
+ if( info.isSupported( NET::WM2RestackWindow ))
+ info.restackRequest( win, None, Above );
+ else
+ XRaiseWindow( qt_xdisplay(), win );
+#endif
+}
+
+void KWin::lowerWindow( WId win )
+{
+#ifdef Q_WS_X11
+ NETRootInfo info( qt_xdisplay(), NET::Supported );
+ if( info.isSupported( NET::WM2RestackWindow ))
+ info.restackRequest( win, None, Below );
+ else
+ XLowerWindow( qt_xdisplay(), win );
+#endif
+}
+
+void KWin::appStarted()
+{
+#ifdef Q_WS_X11
+ KStartupInfo::appStarted();
+#endif
+}
+
+class KWin::WindowInfoPrivate
+{
+ public:
+ WindowInfoPrivate()
+#ifdef Q_WS_X11
+ : info( NULL )
+#endif
+ {}
+#ifdef Q_WS_X11
+ ~WindowInfoPrivate() { delete info; }
+ NETWinInfo* info;
+#endif
+ WId win_;
+ QString name_;
+ QString iconic_name_;
+ QRect geometry_;
+ QRect frame_geometry_;
+ int ref;
+ bool valid;
+ private:
+ WindowInfoPrivate( const WindowInfoPrivate& );
+ void operator=( const WindowInfoPrivate& );
+};
+
+// KWin::info() should be updated too if something has to be changed here
+KWin::WindowInfo::WindowInfo( WId win, unsigned long properties, unsigned long properties2 )
+{
+#ifdef Q_WS_X11
+ KXErrorHandler handler;
+ d = new WindowInfoPrivate;
+ d->ref = 1;
+ if( properties == 0 )
+ properties = NET::WMState |
+ NET::WMStrut |
+ NET::WMWindowType |
+ NET::WMName |
+ NET::WMVisibleName |
+ NET::WMIconName |
+ NET::WMVisibleIconName |
+ NET::WMDesktop |
+ NET::WMPid |
+ NET::WMKDEFrameStrut |
+ NET::XAWMState |
+ NET::WMGeometry;
+ if( properties & NET::WMVisibleIconName )
+ properties |= NET::WMIconName | NET::WMVisibleName; // force, in case it will be used as a fallback
+ if( properties & NET::WMVisibleName )
+ properties |= NET::WMName; // force, in case it will be used as a fallback
+ if( properties2 & NET::WM2ExtendedStrut )
+ properties |= NET::WMStrut; // will be used as fallback
+ properties |= NET::XAWMState; // force to get error detection for valid()
+ unsigned long props[ 2 ] = { properties, properties2 };
+ d->info = new NETWinInfo( qt_xdisplay(), win, qt_xrootwin(), props, 2 );
+ d->win_ = win;
+ if( properties & NET::WMName ) {
+ if( d->info->name() && d->info->name()[ 0 ] != '\0' )
+ d->name_ = QString::fromUtf8( d->info->name() );
+ else
+ d->name_ = readNameProperty( win, XA_WM_NAME );
+ }
+ if( properties & NET::WMIconName ) {
+ if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' )
+ d->iconic_name_ = QString::fromUtf8( d->info->iconName());
+ else
+ d->iconic_name_ = readNameProperty( win, XA_WM_ICON_NAME );
+ }
+ if( properties & ( NET::WMGeometry | NET::WMKDEFrameStrut )) {
+ NETRect frame, geom;
+ d->info->kdeGeometry( frame, geom );
+ d->geometry_.setRect( geom.pos.x, geom.pos.y, geom.size.width, geom.size.height );
+ d->frame_geometry_.setRect( frame.pos.x, frame.pos.y, frame.size.width, frame.size.height );
+ }
+ d->valid = !handler.error( false ); // no sync - NETWinInfo did roundtrips
+#endif
+}
+
+// this one is only to make QValueList<> or similar happy
+KWin::WindowInfo::WindowInfo()
+ : d( NULL )
+{
+}
+
+KWin::WindowInfo::~WindowInfo()
+{
+ if( d != NULL ) {
+ if( --d->ref == 0 ) {
+ delete d;
+ }
+ }
+}
+
+KWin::WindowInfo::WindowInfo( const WindowInfo& wininfo )
+ : d( wininfo.d )
+{
+ if( d != NULL )
+ ++d->ref;
+}
+
+KWin::WindowInfo& KWin::WindowInfo::operator=( const WindowInfo& wininfo )
+{
+ if( d != wininfo.d ) {
+ if( d != NULL )
+ if( --d->ref == 0 )
+ delete d;
+ d = wininfo.d;
+ if( d != NULL )
+ ++d->ref;
+ }
+ return *this;
+}
+
+bool KWin::WindowInfo::valid( bool withdrawn_is_valid ) const
+{
+ if( !d->valid )
+ return false;
+ if( !withdrawn_is_valid && mappingState() == NET::Withdrawn )
+ return false;
+ return true;
+}
+
+WId KWin::WindowInfo::win() const
+{
+ return d->win_;
+}
+
+unsigned long KWin::WindowInfo::state() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMState ) == 0, 176 )
+ << "Pass NET::WMState to KWin::windowInfo()" << endl;
+ return d->info->state();
+#else
+ return 0;
+#endif
+}
+
+NET::MappingState KWin::WindowInfo::mappingState() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::XAWMState ) == 0, 176 )
+ << "Pass NET::XAWMState to KWin::windowInfo()" << endl;
+ return d->info->mappingState();
+#else
+ return NET::Visible;
+#endif
+}
+
+NETExtendedStrut KWin::WindowInfo::extendedStrut() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2ExtendedStrut ) == 0, 176 )
+ << "Pass NET::WM2ExtendedStrut to second argument of KWin::windowInfo()" << endl;
+ NETExtendedStrut ext = d->info->extendedStrut();
+ NETStrut str = d->info->strut();
+ if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0
+ && ( str.left != 0 || str.right != 0 || str.top != 0 || str.bottom != 0 )) {
+ // build extended from simple
+ if( str.left != 0 ) {
+ ext.left_width = str.left;
+ ext.left_start = 0;
+ ext.left_end = XDisplayHeight( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
+ }
+ if( str.right != 0 ) {
+ ext.right_width = str.right;
+ ext.right_start = 0;
+ ext.right_end = XDisplayHeight( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
+ }
+ if( str.top != 0 ) {
+ ext.top_width = str.top;
+ ext.top_start = 0;
+ ext.top_end = XDisplayWidth( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
+ }
+ if( str.bottom != 0 ) {
+ ext.bottom_width = str.bottom;
+ ext.bottom_start = 0;
+ ext.bottom_end = XDisplayWidth( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
+ }
+ }
+ return ext;
+#else
+ NETExtendedStrut n;
+ return n;
+#endif
+}
+
+NETStrut KWin::WindowInfo::strut() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMStrut ) == 0, 176 )
+ << "Pass NET::WMStrut to KWin::windowInfo()" << endl;
+ return d->info->strut();
+#else
+ NETStrut n;
+ return n;
+#endif
+}
+
+NET::WindowType KWin::WindowInfo::windowType( int supported_types ) const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMWindowType ) == 0, 176 )
+ << "Pass NET::WMWindowType to KWin::windowInfo()" << endl;
+ return d->info->windowType( supported_types );
+#else
+ return 0;
+#endif
+}
+
+QString KWin::WindowInfo::visibleNameWithState() const
+{
+ QString s = visibleName();
+ if ( isMinimized() ) {
+ s.prepend('(');
+ s.append(')');
+ }
+ return s;
+}
+
+QString KWin::Info::visibleNameWithState() const
+{
+ QString s = visibleName;
+ if ( isMinimized() ) {
+ s.prepend('(');
+ s.append(')');
+ }
+ return s;
+}
+
+QString KWin::WindowInfo::visibleName() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMVisibleName ) == 0, 176 )
+ << "Pass NET::WMVisibleName to KWin::windowInfo()" << endl;
+ return d->info->visibleName() && d->info->visibleName()[ 0 ] != '\0'
+ ? QString::fromUtf8(d->info->visibleName()) : name();
+#else
+ return QString("name");
+#endif
+}
+
+QString KWin::WindowInfo::name() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMName ) == 0, 176 )
+ << "Pass NET::WMName to KWin::windowInfo()" << endl;
+ return d->name_;
+#else
+ return QString();
+#endif
+}
+
+QString KWin::WindowInfo::visibleIconNameWithState() const
+{
+ QString s = visibleIconName();
+ if ( isMinimized() ) {
+ s.prepend('(');
+ s.append(')');
+ }
+ return s;
+}
+
+QString KWin::WindowInfo::visibleIconName() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMVisibleIconName ) == 0, 176 )
+ << "Pass NET::WMVisibleIconName to KWin::windowInfo()" << endl;
+ if( d->info->visibleIconName() && d->info->visibleIconName()[ 0 ] != '\0' )
+ return QString::fromUtf8( d->info->visibleIconName());
+ if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' )
+ return QString::fromUtf8( d->info->iconName());
+ if( !d->iconic_name_.isEmpty())
+ return d->iconic_name_;
+#endif
+ return visibleName();
+}
+
+QString KWin::WindowInfo::iconName() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMIconName ) == 0, 176 )
+ << "Pass NET::WMIconName to KWin::windowInfo()" << endl;
+ if( d->info->iconName() && d->info->iconName()[ 0 ] != '\0' )
+ return QString::fromUtf8( d->info->iconName());
+ if( !d->iconic_name_.isEmpty())
+ return d->iconic_name_;
+#endif
+ return name();
+}
+
+bool KWin::WindowInfo::isOnCurrentDesktop() const
+{
+#ifdef Q_WS_X11
+ return isOnDesktop( KWin::currentDesktop());
+#else
+ return false;
+#endif
+}
+
+bool KWin::WindowInfo::isOnDesktop( int desktop ) const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop ) == 0, 176 )
+ << "Pass NET::WMDesktop to KWin::windowInfo()" << endl;
+ return d->info->desktop() == desktop || d->info->desktop() == NET::OnAllDesktops;
+#else
+ return false;
+#endif
+}
+
+bool KWin::WindowInfo::onAllDesktops() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop ) == 0, 176 )
+ << "Pass NET::WMDesktop to KWin::windowInfo()" << endl;
+ return d->info->desktop() == NET::OnAllDesktops;
+#else
+ return false;
+#endif
+}
+
+int KWin::WindowInfo::desktop() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMDesktop ) == 0, 176 )
+ << "Pass NET::WMDesktop to KWin::windowInfo()" << endl;
+ return d->info->desktop();
+#else
+ return 1;
+#endif
+}
+
+QRect KWin::WindowInfo::geometry() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMGeometry ) == 0, 176 )
+ << "Pass NET::WMGeometry to KWin::windowInfo()" << endl;
+ return d->geometry_;
+#else
+ return QRect( 100, 100, 200, 200 );
+#endif
+}
+
+QRect KWin::WindowInfo::frameGeometry() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS ] & NET::WMKDEFrameStrut ) == 0, 176 )
+ << "Pass NET::WMKDEFrameStrut to KWin::windowInfo()" << endl;
+ return d->frame_geometry_;
+#else
+ return QRect();
+#endif
+}
+
+WId KWin::WindowInfo::transientFor() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2TransientFor ) == 0, 176 )
+ << "Pass NET::WM2TransientFor to KWin::windowInfo()" << endl;
+ return d->info->transientFor();
+#else
+ return 0;
+#endif
+}
+
+WId KWin::WindowInfo::groupLeader() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2GroupLeader ) == 0, 176 )
+ << "Pass NET::WM2GroupLeader to KWin::windowInfo()" << endl;
+ return d->info->groupLeader();
+#else
+ return 0;
+#endif
+}
+
+QCString KWin::WindowInfo::windowClassClass() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowClass ) == 0, 176 )
+ << "Pass NET::WM2WindowClass to KWin::windowInfo()" << endl;
+ return d->info->windowClassClass();
+#else
+ return 0;
+#endif
+}
+
+QCString KWin::WindowInfo::windowClassName() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowClass ) == 0, 176 )
+ << "Pass NET::WM2WindowClass to KWin::windowInfo()" << endl;
+ return d->info->windowClassName();
+#else
+ return 0;
+#endif
+}
+
+QCString KWin::WindowInfo::windowRole() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2WindowRole ) == 0, 176 )
+ << "Pass NET::WM2WindowRole to KWin::windowInfo()" << endl;
+ return d->info->windowRole();
+#else
+ return 0;
+#endif
+}
+
+QCString KWin::WindowInfo::clientMachine() const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2ClientMachine ) == 0, 176 )
+ << "Pass NET::WM2ClientMachine to KWin::windowInfo()" << endl;
+ return d->info->clientMachine();
+#else
+ return 0;
+#endif
+}
+
+bool KWin::WindowInfo::actionSupported( NET::Action action ) const
+{
+#ifdef Q_WS_X11
+ kdWarning(( d->info->passedProperties()[ NETWinInfo::PROTOCOLS2 ] & NET::WM2AllowedActions ) == 0, 176 )
+ << "Pass NET::WM2AllowedActions to KWin::windowInfo()" << endl;
+ if( allowedActionsSupported())
+ return d->info->allowedActions() & action;
+ else
+#endif
+ return true; // no idea if it's supported or not -> pretend it is
+}
+
+// see NETWM spec section 7.6
+bool KWin::WindowInfo::isMinimized() const
+{
+#ifdef Q_WS_X11
+ if( mappingState() != NET::Iconic )
+ return false;
+ // NETWM 1.2 compliant WM - uses NET::Hidden for minimized windows
+ if(( state() & NET::Hidden ) != 0
+ && ( state() & NET::Shaded ) == 0 ) // shaded may have NET::Hidden too
+ return true;
+ // older WMs use WithdrawnState for other virtual desktops
+ // and IconicState only for minimized
+ return icccmCompliantMappingState() ? false : true;
+#else
+ return false;
+#endif
+}
+
+bool KWin::Info::isMinimized() const
+{
+#ifdef Q_WS_X11
+ if( mappingState != NET::Iconic )
+ return false;
+ // NETWM 1.2 compliant WM - uses NET::Hidden for minimized windows
+ if(( state & NET::Hidden ) != 0
+ && ( state & NET::Shaded ) == 0 ) // shaded may have NET::Hidden too
+ return true;
+ // older WMs use WithdrawnState for other virtual desktops
+ // and IconicState only for minimized
+ return icccmCompliantMappingState() ? false : true;
+#else
+ return false;
+#endif
+}
+
+bool KWin::Info::isIconified() const
+{
+ return isMinimized();
+}
+
+bool KWin::icccmCompliantMappingState()
+{
+#ifdef Q_WS_X11
+ static enum { noidea, yes, no } wm_is_1_2_compliant = noidea;
+ if( wm_is_1_2_compliant == noidea ) {
+ NETRootInfo info( qt_xdisplay(), NET::Supported );
+ wm_is_1_2_compliant = info.isSupported( NET::Hidden ) ? yes : no;
+ }
+ return wm_is_1_2_compliant == yes;
+#else
+ return false;
+#endif
+}
+
+bool KWin::allowedActionsSupported()
+{
+#ifdef Q_WS_X11
+ static enum { noidea, yes, no } wm_supports_allowed_actions = noidea;
+ if( wm_supports_allowed_actions == noidea ) {
+ NETRootInfo info( qt_xdisplay(), NET::Supported );
+ wm_supports_allowed_actions = info.isSupported( NET::WM2AllowedActions ) ? yes : no;
+ }
+ return wm_supports_allowed_actions == yes;
+#else
+ return false;
+#endif
+}
+
+QString KWin::readNameProperty( WId win, unsigned long atom )
+{
+#ifdef Q_WS_X11
+ XTextProperty tp;
+ char **text = NULL;
+ int count;
+#endif
+ QString result;
+#ifdef Q_WS_X11
+ if ( XGetTextProperty( qt_xdisplay(), win, &tp, atom ) != 0 && tp.value != NULL )
+ {
+ if (!kwin_UTF8_STRING)
+ kwin_UTF8_STRING = XInternAtom( qt_xdisplay(), "UTF8_STRING", False);
+
+ if ( tp.encoding == kwin_UTF8_STRING ) {
+ result = QString::fromUtf8 ( (const char*) tp.value );
+ }
+ else if ( XmbTextPropertyToTextList( qt_xdisplay(), &tp, &text, &count) == Success &&
+ text != NULL && count > 0 ) {
+ result = QString::fromLocal8Bit( text[0] );
+ } else if ( tp.encoding == XA_STRING )
+ result = QString::fromLocal8Bit( (const char*) tp.value );
+ if( text != NULL )
+ XFreeStringList( text );
+ XFree( tp.value );
+ }
+#endif
+ return result;
+}
+
+//#endif