File indexing completed on 2024-12-08 12:25:47

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2007 Laurent Montel <montel@kde.org>
0004     SPDX-FileCopyrightText: 2007 Christian Ehrlicher <ch.ehrlicher@gmx.de>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-or-later
0007 */
0008 
0009 #include "kwindowsystem.h"
0010 
0011 #include <QApplication>
0012 #include <QBitmap>
0013 #include <QDebug>
0014 #include <QDesktopWidget>
0015 #include <QIcon>
0016 #include <QImage>
0017 #include <QLibrary>
0018 #include <QMetaMethod>
0019 #include <QPixmap>
0020 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0021 #include <QtWin>
0022 #endif
0023 
0024 #include <windows.h>
0025 #include <windowsx.h>
0026 
0027 #ifdef _WIN64
0028 #define GCL_HICON GCLP_HICON
0029 #define GCL_HICONSM GCLP_HICONSM
0030 #endif
0031 
0032 // function to register us as taskmanager
0033 #define RSH_UNREGISTER 0
0034 #define RSH_REGISTER 1
0035 #define RSH_TASKMGR 3
0036 typedef bool(WINAPI *PtrRegisterShellHook)(HWND hWnd, DWORD method);
0037 
0038 static PtrRegisterShellHook pRegisterShellHook = 0;
0039 static int WM_SHELLHOOK = -1;
0040 
0041 class KWindowSystemStaticContainer
0042 {
0043 public:
0044     KWindowSystemStaticContainer()
0045         : d(0)
0046     {
0047     }
0048     KWindowSystem kwm;
0049     KWindowSystemPrivate *d;
0050 };
0051 
0052 Q_GLOBAL_STATIC(KWindowSystemStaticContainer, g_kwmInstanceContainer)
0053 
0054 struct InternalWindowInfo {
0055     InternalWindowInfo()
0056     {
0057     }
0058     QPixmap bigIcon;
0059     QPixmap smallIcon;
0060     QString windowName;
0061 };
0062 
0063 class KWindowSystemPrivate : public QWidget
0064 {
0065     friend class KWindowSystem;
0066 
0067 public:
0068     KWindowSystemPrivate(int what);
0069     ~KWindowSystemPrivate();
0070 
0071     static bool CALLBACK EnumWindProc(HWND hwnd, LPARAM lparam);
0072     static void readWindowInfo(HWND hwnd, InternalWindowInfo *winfo);
0073 
0074     void windowAdded(WId wid);
0075     void windowRemoved(WId wid);
0076     void windowActivated(WId wid);
0077     void windowRedraw(WId wid);
0078     void windowFlash(WId wid);
0079     void windowStateChanged(WId wid);
0080     void reloadStackList();
0081     void activate();
0082 
0083 protected:
0084     bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
0085 
0086 private:
0087     bool activated;
0088     int what;
0089     WId fakeHwnd;
0090     QList<WId> stackingOrder;
0091     QMap<WId, InternalWindowInfo> winInfos;
0092 };
0093 
0094 static HBITMAP QPixmapMask2HBitmap(const QPixmap &pix)
0095 {
0096     QBitmap bm = pix.mask();
0097     if (bm.isNull()) {
0098         bm = QBitmap(pix.size());
0099         bm.fill(Qt::color1);
0100     }
0101     QImage im = bm.toImage().convertToFormat(QImage::Format_Mono);
0102     im.invertPixels(); // funny blank'n'white games on windows
0103     int w = im.width();
0104     int h = im.height();
0105     int bpl = ((w + 15) / 16) * 2; // bpl, 16 bit alignment
0106     QByteArray bits(bpl * h, '\0');
0107     for (int y = 0; y < h; y++) {
0108         memcpy(bits.data() + y * bpl, im.scanLine(y), bpl);
0109     }
0110     return CreateBitmap(w, h, 1, 1, bits.constData());
0111 }
0112 
0113 KWindowSystemPrivate::KWindowSystemPrivate(int what)
0114     : QWidget(0)
0115     , activated(false)
0116 {
0117     // i think there is no difference in windows we always load everything
0118     what = KWindowSystem::INFO_WINDOWS;
0119     setVisible(false);
0120 }
0121 
0122 void KWindowSystemPrivate::activate()
0123 {
0124 #if 0
0125     //prevent us from doing the same over and over again
0126     if (activated) {
0127         return;
0128     }
0129     activated = true;
0130 
0131     //resolve winapi stuff
0132     if (!pRegisterShellHook) {
0133         pRegisterShellHook = (PtrRegisterShellHook)QLibrary::resolve("shell32", (LPCSTR)0xb5);
0134     }
0135 
0136     //get the id for the shellhook message
0137     if (WM_SHELLHOOK == -1) {
0138         WM_SHELLHOOK = RegisterWindowMessage(TEXT("SHELLHOOK"));
0139         //qDebug() << "WM_SHELLHOOK:" << WM_SHELLHOOK << winId();
0140     }
0141 
0142     bool shellHookRegistered = false;
0143     if (pRegisterShellHook) {
0144         shellHookRegistered = pRegisterShellHook(winId(), RSH_TASKMGR);
0145     }
0146 
0147     if (!shellHookRegistered)
0148         //use a timer and poll the windows ?
0149     {
0150         qDebug() << "Could not create shellhook to receive WindowManager Events";
0151     }
0152 
0153     //fetch window infos
0154     reloadStackList();
0155 #endif
0156 }
0157 
0158 KWindowSystemPrivate::~KWindowSystemPrivate()
0159 {
0160     if (pRegisterShellHook) {
0161         pRegisterShellHook(reinterpret_cast<HWND>(winId()), RSH_UNREGISTER);
0162     }
0163 }
0164 
0165 /**
0166  *the callback procedure for the invisible ShellHook window
0167  */
0168 bool KWindowSystemPrivate::nativeEvent(const QByteArray &eventType, void *message_, long *result)
0169 {
0170     if (eventType != QByteArrayLiteral("windows_generic_MSG")) {
0171         return QWidget::nativeEvent(eventType, message_, result);
0172     }
0173 
0174     MSG *message = static_cast<MSG *>(message_);
0175 
0176     /*
0177         check winuser.h for the following codes
0178         HSHELL_WINDOWCREATED        1
0179         HSHELL_WINDOWDESTROYED      2
0180         HSHELL_ACTIVATESHELLWINDOW  3
0181         HSHELL_WINDOWACTIVATED      4
0182         HSHELL_GETMINRECT           5
0183         HSHELL_RUDEAPPACTIVATED     32768 + 4 = 32772
0184         HSHELL_REDRAW               6
0185         HSHELL_FLASH                32768 + 6 = 32774
0186         HSHELL_TASKMAN              7
0187         HSHELL_LANGUAGE             8
0188         HSHELL_SYSMENU              9
0189         HSHELL_ENDTASK              10
0190         HSHELL_ACCESSIBILITYSTATE   11
0191         HSHELL_APPCOMMAND           12
0192         HSHELL_WINDOWREPLACED       13
0193         HSHELL_WINDOWREPLACING      14
0194        */
0195     if (message->message == WM_SHELLHOOK) {
0196         //         qDebug() << "what has happened?:" << message->wParam << message->message;
0197 
0198         switch (message->wParam) {
0199         case HSHELL_WINDOWCREATED:
0200             KWindowSystem::s_d_func()->windowAdded(static_cast<WId>(message->lParam));
0201             break;
0202         case HSHELL_WINDOWDESTROYED:
0203             KWindowSystem::s_d_func()->windowRemoved(static_cast<WId>(message->lParam));
0204             break;
0205         case HSHELL_WINDOWACTIVATED:
0206 #ifndef _WIN32_WCE
0207         case HSHELL_RUDEAPPACTIVATED:
0208 #endif
0209             KWindowSystem::s_d_func()->windowActivated(static_cast<WId>(message->lParam));
0210             break;
0211 #ifndef _WIN32_WCE
0212         case HSHELL_GETMINRECT:
0213             KWindowSystem::s_d_func()->windowStateChanged(static_cast<WId>(message->lParam));
0214             break;
0215         case HSHELL_REDRAW: // the caption has changed
0216             KWindowSystem::s_d_func()->windowRedraw(static_cast<WId>(message->lParam));
0217             break;
0218         case HSHELL_FLASH:
0219             KWindowSystem::s_d_func()->windowFlash(static_cast<WId>(message->lParam));
0220             break;
0221 #endif
0222         }
0223     }
0224     return QWidget::nativeEvent(eventType, message_, result);
0225 }
0226 
0227 bool CALLBACK KWindowSystemPrivate::EnumWindProc(HWND hWnd, LPARAM lparam)
0228 {
0229     WId win = reinterpret_cast<WId>(hWnd);
0230     QByteArray windowText = QByteArray((GetWindowTextLength(hWnd) + 1) * sizeof(wchar_t), 0);
0231     GetWindowTextW(hWnd, (LPWSTR)windowText.data(), windowText.size());
0232     DWORD ex_style = GetWindowExStyle(hWnd);
0233     KWindowSystemPrivate *p = KWindowSystem::s_d_func();
0234 
0235     QString add;
0236     if (!QString::fromWCharArray((wchar_t *)windowText.data()).trimmed().isEmpty() && IsWindowVisible(hWnd) && !(ex_style & WS_EX_TOOLWINDOW)
0237         && !GetParent(hWnd) && !GetWindow(hWnd, GW_OWNER) && !p->winInfos.contains(win)) {
0238         //        qDebug()<<"Adding window to windowList " << add + QString(windowText).trimmed();
0239 
0240         InternalWindowInfo winfo;
0241         KWindowSystemPrivate::readWindowInfo(hWnd, &winfo);
0242 
0243         p->stackingOrder.append(win);
0244         p->winInfos.insert(win, winfo);
0245     }
0246     return true;
0247 }
0248 
0249 void KWindowSystemPrivate::readWindowInfo(HWND hWnd, InternalWindowInfo *winfo)
0250 {
0251     QByteArray windowText = QByteArray((GetWindowTextLength(hWnd) + 1) * sizeof(wchar_t), 0);
0252     GetWindowTextW(hWnd, (LPWSTR)windowText.data(), windowText.size());
0253     // maybe use SendMessageTimout here?
0254     QPixmap smallIcon;
0255     HICON hSmallIcon = (HICON)SendMessage(hWnd, WM_GETICON, ICON_SMALL, 0);
0256     // if(!hSmallIcon) hSmallIcon = (HICON)SendMessage(hWnd, WM_GETICON, ICON_SMALL2, 0);
0257     if (!hSmallIcon) {
0258         hSmallIcon = (HICON)SendMessage(hWnd, WM_GETICON, ICON_BIG, 0);
0259     }
0260 #ifndef _WIN32_WCE
0261     if (!hSmallIcon) {
0262         hSmallIcon = (HICON)GetClassLong(hWnd, GCL_HICONSM);
0263     }
0264     if (!hSmallIcon) {
0265         hSmallIcon = (HICON)GetClassLong(hWnd, GCL_HICON);
0266     }
0267 #endif
0268     if (!hSmallIcon) {
0269         hSmallIcon = (HICON)SendMessage(hWnd, WM_QUERYDRAGICON, 0, 0);
0270     }
0271     if (hSmallIcon) {
0272 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0273         smallIcon = QtWin::fromHICON(hSmallIcon);
0274 #else
0275         smallIcon = QPixmap::fromImage(QImage::fromHICON(hSmallIcon));
0276 #endif
0277     }
0278 
0279     QPixmap bigIcon;
0280     HICON hBigIcon = (HICON)SendMessage(hWnd, WM_GETICON, ICON_BIG, 0);
0281     // if(!hBigIcon) hBigIcon = (HICON)SendMessage(hWnd, WM_GETICON, ICON_SMALL2, 0);
0282     if (!hBigIcon) {
0283         hBigIcon = (HICON)SendMessage(hWnd, WM_GETICON, ICON_SMALL, 0);
0284     }
0285 #ifndef _WIN32_WCE
0286     if (!hBigIcon) {
0287         hBigIcon = (HICON)GetClassLong(hWnd, GCL_HICON);
0288     }
0289     if (!hBigIcon) {
0290         hBigIcon = (HICON)GetClassLong(hWnd, GCL_HICONSM);
0291     }
0292 #endif
0293     if (!hBigIcon) {
0294         hBigIcon = (HICON)SendMessage(hWnd, WM_QUERYDRAGICON, 0, 0);
0295     }
0296     if (hBigIcon) {
0297 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0298         bigIcon = QtWin::fromHICON(hBigIcon);
0299 #else
0300         bigIcon = QPixmap::fromImage(QImage::fromHICON(hBigIcon));
0301 #endif
0302     }
0303 
0304     winfo->bigIcon = bigIcon;
0305     winfo->smallIcon = smallIcon;
0306     winfo->windowName = QString::fromWCharArray((wchar_t *)windowText.data()).trimmed();
0307 }
0308 
0309 void KWindowSystemPrivate::windowAdded(WId wid)
0310 {
0311     //     qDebug() << "window added!";
0312     KWindowSystem::s_d_func()->reloadStackList();
0313     Q_EMIT KWindowSystem::self()->windowAdded(wid);
0314     Q_EMIT KWindowSystem::self()->activeWindowChanged(wid);
0315     Q_EMIT KWindowSystem::self()->stackingOrderChanged();
0316 }
0317 
0318 void KWindowSystemPrivate::windowRemoved(WId wid)
0319 {
0320     //     qDebug() << "window removed!";
0321     KWindowSystem::s_d_func()->reloadStackList();
0322     Q_EMIT KWindowSystem::self()->windowRemoved(wid);
0323     Q_EMIT KWindowSystem::self()->stackingOrderChanged();
0324 }
0325 
0326 void KWindowSystemPrivate::windowActivated(WId wid)
0327 {
0328     //     qDebug() << "window activated!";
0329     if (!wid) {
0330         return;
0331     }
0332 
0333     KWindowSystem::s_d_func()->reloadStackList();
0334     Q_EMIT KWindowSystem::self()->activeWindowChanged(wid);
0335     Q_EMIT KWindowSystem::self()->stackingOrderChanged();
0336 }
0337 
0338 void KWindowSystemPrivate::windowRedraw(WId wid)
0339 {
0340     KWindowSystem::s_d_func()->reloadStackList();
0341 }
0342 
0343 void KWindowSystemPrivate::windowFlash(WId wid)
0344 {
0345     // emit KWindowSystem::self()->demandAttention( wid );
0346 }
0347 
0348 void KWindowSystemPrivate::windowStateChanged(WId wid)
0349 {
0350 #if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 80)
0351     Q_EMIT KWindowSystem::self()->windowChanged(wid);
0352 #endif
0353 
0354     Q_EMIT KWindowSystem::self()->windowChanged(wid, NET::Properties{}, NET::Properties2{});
0355 }
0356 
0357 void KWindowSystemPrivate::reloadStackList()
0358 {
0359     KWindowSystem::s_d_func()->stackingOrder.clear();
0360     KWindowSystem::s_d_func()->winInfos.clear();
0361     //    EnumWindows((WNDENUMPROC)EnumWindProc, 0 );
0362 }
0363 
0364 KWindowSystem *KWindowSystem::self()
0365 {
0366     return &(g_kwmInstanceContainer()->kwm);
0367 }
0368 
0369 KWindowSystemPrivate *KWindowSystem::s_d_func()
0370 {
0371     return g_kwmInstanceContainer()->d;
0372 }
0373 
0374 void KWindowSystem::init(int what)
0375 {
0376     KWindowSystemPrivate *const s_d = s_d_func();
0377 
0378     if (what >= INFO_WINDOWS) {
0379         what = INFO_WINDOWS;
0380     } else {
0381         what = INFO_BASIC;
0382     }
0383 
0384     if (!s_d) {
0385         g_kwmInstanceContainer()->d = new KWindowSystemPrivate(what); // invalidates s_d
0386         g_kwmInstanceContainer()->d->activate();
0387     } else if (s_d->what < what) {
0388         delete s_d;
0389         g_kwmInstanceContainer()->d = new KWindowSystemPrivate(what); // invalidates s_d
0390         g_kwmInstanceContainer()->d->activate();
0391     }
0392 }
0393 
0394 bool KWindowSystem::allowedActionsSupported()
0395 {
0396     return false;
0397 }
0398 
0399 int KWindowSystem::currentDesktop()
0400 {
0401     return 1;
0402 }
0403 
0404 int KWindowSystem::numberOfDesktops()
0405 {
0406     return 1;
0407 }
0408 
0409 void KWindowSystem::setMainWindow(QWidget *subwindow, WId mainwindow)
0410 {
0411     SetForegroundWindow(reinterpret_cast<HWND>(subwindow->winId()));
0412 }
0413 
0414 void KWindowSystem::setCurrentDesktop(int desktop)
0415 {
0416     qDebug() << "KWindowSystem::setCurrentDesktop( int desktop ) isn't yet implemented!";
0417     // TODO
0418 }
0419 
0420 void KWindowSystem::setOnAllDesktops(WId win, bool b)
0421 {
0422     qDebug() << "KWindowSystem::setOnAllDesktops( WId win, bool b ) isn't yet implemented!";
0423     // TODO
0424 }
0425 
0426 void KWindowSystem::setOnDesktop(WId win, int desktop)
0427 {
0428     // TODO
0429     qDebug() << "KWindowSystem::setOnDesktop( WId win, int desktop ) isn't yet implemented!";
0430 }
0431 
0432 WId KWindowSystem::activeWindow()
0433 {
0434     return reinterpret_cast<WId>(GetActiveWindow());
0435 }
0436 
0437 void KWindowSystem::activateWindow(WId win, long)
0438 {
0439     SetActiveWindow(reinterpret_cast<HWND>(win));
0440 }
0441 
0442 void KWindowSystem::forceActiveWindow(WId win, long time)
0443 {
0444     HWND hwnd = reinterpret_cast<HWND>(win);
0445     // FIXME restoring a hidden window doesn't work: the window contents just appear white.
0446     // But the mouse cursor still acts as if the widgets were there (e.g. button clicking works),
0447     // which indicates the issue is at the window/backingstore level.
0448     // This is probably a side effect of bypassing Qt's internal window state handling.
0449 #ifndef _WIN32_WCE
0450     if (IsIconic(hwnd) /*|| !IsWindowVisible( win ) */) {
0451         // Do not activate the window as we restore it,
0452         // otherwise the window appears see-through (contents not updated).
0453         ShowWindow(hwnd, SW_SHOWNOACTIVATE);
0454     }
0455 #endif
0456     // Puts the window in front and activates it.
0457     // to bring a window to the front while the user is active in a different application we
0458     // have to attach our self to the current active window
0459     HWND hwndActiveWin = GetForegroundWindow();
0460     int idActive = GetWindowThreadProcessId(hwndActiveWin, nullptr);
0461     if (AttachThreadInput(GetCurrentThreadId(), idActive, TRUE)) {
0462         SetForegroundWindow(hwnd);
0463         SetFocus(hwnd);
0464         AttachThreadInput(GetCurrentThreadId(), idActive, FALSE);
0465     }
0466 }
0467 
0468 #if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 101)
0469 void KWindowSystem::demandAttention(WId win, bool set)
0470 {
0471 // One can not flash a windows in wince
0472 #ifndef _WIN32_WCE
0473     FLASHWINFO fi;
0474     fi.cbSize = sizeof(FLASHWINFO);
0475     fi.hwnd = reinterpret_cast<HWND>(win);
0476     fi.dwFlags = set ? FLASHW_ALL : FLASHW_STOP;
0477     fi.uCount = 5;
0478     fi.dwTimeout = 0;
0479 
0480     FlashWindowEx(&fi);
0481 #endif
0482 }
0483 #endif
0484 
0485 QPixmap KWindowSystem::icon(WId win, int width, int height, bool scale)
0486 {
0487     KWindowSystem::init(INFO_WINDOWS);
0488 
0489     QPixmap pm;
0490     if (KWindowSystem::s_d_func()->winInfos.contains(win)) {
0491         if (width < 24 || height < 24) {
0492             pm = KWindowSystem::s_d_func()->winInfos[win].smallIcon;
0493         } else {
0494             pm = KWindowSystem::s_d_func()->winInfos[win].bigIcon;
0495         }
0496     } else {
0497         qDebug() << "KWindowSystem::icon winid not in winInfos";
0498         UINT size = ICON_BIG;
0499         if (width < 24 || height < 24) {
0500             size = ICON_SMALL;
0501         }
0502         HICON hIcon = (HICON)SendMessage(reinterpret_cast<HWND>(win), WM_GETICON, size, 0);
0503         if (hIcon != nullptr) {
0504 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0505             pm = QtWin::fromHICON(hIcon);
0506 #else
0507             pm = QPixmap::fromImage(QImage::fromHICON(hIcon));
0508 #endif
0509         }
0510     }
0511     if (scale) {
0512         pm = pm.scaled(width, height);
0513     }
0514     return pm;
0515 }
0516 
0517 QPixmap KWindowSystem::icon(WId win, int width, int height, bool scale, int)
0518 {
0519     return icon(win, width, height, scale);
0520 }
0521 
0522 #if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 101)
0523 void KWindowSystem::setIcons(WId win, const QPixmap &icon, const QPixmap &miniIcon)
0524 {
0525     KWindowSystem::init(INFO_WINDOWS);
0526     KWindowSystemPrivate *s_d = s_d_func();
0527 
0528     if (s_d->winInfos.contains(win)) {
0529         // is this safe enough or do i have to refresh() the window infos
0530         s_d->winInfos[win].smallIcon = miniIcon;
0531         s_d->winInfos[win].bigIcon = icon;
0532     }
0533 
0534 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0535     HICON hIconBig = QtWin::toHICON(icon);
0536     HICON hIconSmall = QtWin::toHICON(miniIcon);
0537 #else
0538     HICON hIconBig = icon.toImage().toHICON();
0539     HICON hIconSmall = miniIcon.toImage().toHICON();
0540 #endif
0541 
0542     HWND hwnd = reinterpret_cast<HWND>(win);
0543     hIconBig = (HICON)SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIconBig);
0544     hIconSmall = (HICON)SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSmall);
0545 }
0546 #endif
0547 
0548 void KWindowSystem::setState(WId win, NET::States state)
0549 {
0550     HWND hwnd = reinterpret_cast<HWND>(win);
0551     bool got = false;
0552 #ifndef _WIN32_WCE
0553     if (state & NET::SkipTaskbar) {
0554         got = true;
0555         LONG_PTR lp = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
0556         SetWindowLongPtr(hwnd, GWL_EXSTYLE, lp | WS_EX_TOOLWINDOW);
0557     }
0558 #endif
0559     if (state & NET::KeepAbove) {
0560         got = true;
0561         SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
0562     }
0563     if (state & NET::KeepBelow) {
0564         got = true;
0565         SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
0566     }
0567     if (state & NET::Max) {
0568         got = true;
0569         ShowWindow(hwnd, SW_MAXIMIZE);
0570     }
0571     if (!got) {
0572         qDebug() << "KWindowSystem::setState( WId win, unsigned long state ) isn't yet implemented for the state you requested!";
0573     }
0574 }
0575 
0576 void KWindowSystem::clearState(WId win, NET::States state)
0577 {
0578     bool got = false;
0579     HWND hwnd = reinterpret_cast<HWND>(win);
0580 
0581 #ifndef _WIN32_WCE
0582     if (state & NET::SkipTaskbar) {
0583         got = true;
0584         LONG_PTR lp = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
0585         SetWindowLongPtr(hwnd, GWL_EXSTYLE, lp & ~WS_EX_TOOLWINDOW);
0586     }
0587 #endif
0588     if (state & NET::KeepAbove) {
0589         got = true;
0590         // lets hope this remove the topmost
0591         SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
0592     }
0593     if (state & NET::Max) {
0594         got = true;
0595         ShowWindow(hwnd, SW_RESTORE);
0596     }
0597     if (!got) {
0598         qDebug() << "KWindowSystem::clearState( WId win, unsigned long state ) isn't yet implemented!";
0599     }
0600 }
0601 
0602 void KWindowSystem::minimizeWindow(WId win, bool animation)
0603 {
0604     Q_UNUSED(animation);
0605     ShowWindow(reinterpret_cast<HWND>(win), SW_MINIMIZE);
0606 }
0607 
0608 void KWindowSystem::unminimizeWindow(WId win, bool animation)
0609 {
0610     Q_UNUSED(animation);
0611     ShowWindow(reinterpret_cast<HWND>(win), SW_RESTORE);
0612 }
0613 
0614 void KWindowSystem::raiseWindow(WId win)
0615 {
0616     // to bring a window to the front while the user is active in a different application we
0617     // have to attach our self to the current active window
0618     HWND hwndActiveWin = GetForegroundWindow();
0619     int idActive = GetWindowThreadProcessId(hwndActiveWin, nullptr);
0620     if (AttachThreadInput(GetCurrentThreadId(), idActive, TRUE)) {
0621         SetForegroundWindow(reinterpret_cast<HWND>(win));
0622         AttachThreadInput(GetCurrentThreadId(), idActive, FALSE);
0623     }
0624 }
0625 
0626 void KWindowSystem::lowerWindow(WId win)
0627 {
0628     SetWindowPos(reinterpret_cast<HWND>(win), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); // mhhh?
0629 }
0630 
0631 bool KWindowSystem::compositingActive()
0632 {
0633     return true;
0634 }
0635 
0636 QRect KWindowSystem::workArea(int desktop)
0637 {
0638     return qApp->desktop()->availableGeometry(desktop);
0639 }
0640 
0641 QRect KWindowSystem::workArea(const QList<WId> &exclude, int desktop)
0642 {
0643     // TODO
0644     qDebug() << "QRect KWindowSystem::workArea( const QList<WId>& exclude, int desktop ) isn't yet implemented!";
0645     return QRect();
0646 }
0647 
0648 QString KWindowSystem::desktopName(int desktop)
0649 {
0650     return tr("Desktop %1").arg(desktop);
0651 }
0652 
0653 void KWindowSystem::setDesktopName(int desktop, const QString &name)
0654 {
0655     qDebug() << "KWindowSystem::setDesktopName( int desktop, const QString& name ) isn't yet implemented!";
0656     // TODO
0657 }
0658 
0659 bool KWindowSystem::showingDesktop()
0660 {
0661     return false;
0662 }
0663 
0664 void KWindowSystem::setUserTime(WId win, long time)
0665 {
0666     qDebug() << "KWindowSystem::setUserTime( WId win, long time ) isn't yet implemented!";
0667     // TODO
0668 }
0669 
0670 bool KWindowSystem::icccmCompliantMappingState()
0671 {
0672     return false;
0673 }
0674 
0675 // optimalization - create KWindowSystemPrivate only when needed and only for what is needed
0676 void KWindowSystem::connectNotify(const QMetaMethod &method)
0677 {
0678     int what = INFO_BASIC;
0679     if (method == QMetaMethod::fromSignal(&KWindowSystem::workAreaChanged)) {
0680         what = INFO_WINDOWS;
0681     } else if (method == QMetaMethod::fromSignal(&KWindowSystem::strutChanged)) {
0682         what = INFO_WINDOWS;
0683     } else if (method == QMetaMethod::fromSignal(qOverload<WId, NET::Properties, NET::Properties2>(&KWindowSystem::windowChanged))) {
0684         what = INFO_WINDOWS;
0685     }
0686 #if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 0)
0687     else if (method == QMetaMethod::fromSignal(static_cast<void (KWindowSystem::*)(WId, const ulong *)>(&KWindowSystem::windowChanged))) {
0688         what = INFO_WINDOWS;
0689     } else if (method == QMetaMethod::fromSignal(static_cast<void (KWindowSystem::*)(WId, uint)>(&KWindowSystem::windowChanged))) {
0690         what = INFO_WINDOWS;
0691     }
0692 #endif
0693 #if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 80)
0694     else if (method == QMetaMethod::fromSignal(static_cast<void (KWindowSystem::*)(WId)>(&KWindowSystem::windowChanged))) {
0695         what = INFO_WINDOWS;
0696     }
0697 #endif
0698 
0699     init(what);
0700     QObject::connectNotify(method);
0701 }
0702 
0703 void KWindowSystem::setExtendedStrut(WId win,
0704                                      int left_width,
0705                                      int left_start,
0706                                      int left_end,
0707                                      int right_width,
0708                                      int right_start,
0709                                      int right_end,
0710                                      int top_width,
0711                                      int top_start,
0712                                      int top_end,
0713                                      int bottom_width,
0714                                      int bottom_start,
0715                                      int bottom_end)
0716 {
0717     qDebug() << "KWindowSystem::setExtendedStrut isn't yet implemented!";
0718     // TODO
0719 }
0720 void KWindowSystem::setStrut(WId win, int left, int right, int top, int bottom)
0721 {
0722     qDebug() << "KWindowSystem::setStrut isn't yet implemented!";
0723     // TODO
0724 }
0725 
0726 QString KWindowSystem::readNameProperty(WId window, unsigned long atom)
0727 {
0728     // TODO
0729     qDebug() << "QString KWindowSystem::readNameProperty( WId window, unsigned long atom ) isn't yet implemented!";
0730     return QString();
0731 }
0732 
0733 QList<WId> KWindowSystem::stackingOrder()
0734 {
0735     KWindowSystem::init(INFO_WINDOWS);
0736     return KWindowSystem::s_d_func()->stackingOrder;
0737 }
0738 
0739 const QList<WId> &KWindowSystem::windows()
0740 {
0741     KWindowSystem::init(INFO_WINDOWS);
0742     return KWindowSystem::s_d_func()->stackingOrder;
0743 }
0744 
0745 void KWindowSystem::setType(WId win, NET::WindowType windowType)
0746 {
0747     // TODO
0748     qDebug() << "setType( WId win, NET::WindowType windowType ) isn't yet implemented!";
0749 }
0750 
0751 #if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 0)
0752 KWindowInfo KWindowSystem::windowInfo(WId win, unsigned long properties, unsigned long properties2)
0753 {
0754     KWindowSystem::init(INFO_WINDOWS);
0755     return KWindowInfo(win, properties, properties2);
0756 }
0757 #endif
0758 
0759 bool KWindowSystem::hasWId(WId w)
0760 {
0761     KWindowSystem::init(INFO_WINDOWS);
0762     return KWindowSystem::s_d_func()->winInfos.contains(w);
0763 }
0764 
0765 void KWindowSystem::allowExternalProcessWindowActivation(int pid)
0766 {
0767 #ifndef _WIN32_WCE
0768     AllowSetForegroundWindow(pid == -1 ? ASFW_ANY : pid);
0769 #endif
0770 }
0771 
0772 void KWindowSystem::setBlockingCompositing(WId window, bool active)
0773 {
0774     // TODO
0775     qDebug() << "setBlockingCompositing( WId window, bool active ) isn't yet implemented!";
0776 }
0777 
0778 #include "moc_kwindowsystem.cpp"