File indexing completed on 2024-10-13 10:45:59
0001 /* 0002 SPDX-License-Identifier: GPL-2.0-only 0003 SPDX-FileCopyrightText: 1999-2001 Lubos Lunak <l.lunak@kde.org> 0004 */ 0005 0006 #define _WINDOWS_CPP_ 0007 0008 #include "windows_handler.h" 0009 0010 #include "windows_helper/window_selection_list.h" 0011 #include "windows_helper/window_selection_rules.h" 0012 0013 #include <QRegExp> 0014 0015 #include <QDebug> 0016 #include <kconfig.h> 0017 #include <kconfiggroup.h> 0018 #include <klocale.h> 0019 #include <kwindowsystem.h> 0020 0021 #include "khotkeysglobal.h" 0022 0023 #include <QX11Info> 0024 #include <X11/Xlib.h> 0025 #include <X11/Xutil.h> 0026 0027 namespace KHotKeys 0028 { 0029 // WindowsHandler 0030 0031 WindowsHandler::WindowsHandler(bool enable_signal_P, QObject *parent_P) 0032 : QObject(parent_P) 0033 , signals_enabled(enable_signal_P) 0034 , _action_window(0) 0035 , m_isX11(QX11Info::isPlatformX11()) 0036 { 0037 if (signals_enabled) { 0038 connect(KWindowSystem::self(), SIGNAL(windowAdded(WId)), SLOT(window_added_slot(WId))); 0039 connect(KWindowSystem::self(), SIGNAL(windowRemoved(WId)), SLOT(window_removed_slot(WId))); 0040 connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), SLOT(active_window_changed_slot(WId))); 0041 } 0042 } 0043 0044 WindowsHandler::~WindowsHandler() 0045 { 0046 } 0047 0048 void WindowsHandler::window_added_slot(WId window_P) 0049 { 0050 if (signals_enabled) 0051 emit window_added(window_P); 0052 // CHECKME tyhle i dalsi by asi mely jit nastavit, jestli aktivuji vsechny, nebo jen jeden 0053 // pripojeny slot ( stejne jako u Kdb, kde by to take melo jit nastavit ) 0054 } 0055 0056 void WindowsHandler::window_removed_slot(WId window_P) 0057 { 0058 if (signals_enabled) 0059 emit window_removed(window_P); 0060 if (window_P == _action_window) 0061 _action_window = 0; 0062 } 0063 0064 void WindowsHandler::active_window_changed_slot(WId window_P) 0065 { 0066 if (signals_enabled) 0067 emit active_window_changed(window_P); 0068 } 0069 0070 void WindowsHandler::window_changed_slot(WId window_P) 0071 { 0072 if (signals_enabled) 0073 emit window_changed(window_P); 0074 } 0075 0076 void WindowsHandler::window_changed_slot(WId window_P, unsigned int flags_P) 0077 { 0078 if (signals_enabled) 0079 emit window_changed(window_P, flags_P); 0080 } 0081 0082 QString WindowsHandler::get_window_role(WId id_P) 0083 { 0084 // TODO this is probably just a hack 0085 return KWindowInfo(id_P, {}, NET::WM2WindowRole).windowRole(); 0086 } 0087 0088 QString WindowsHandler::get_window_class(WId id_P) 0089 { 0090 if (!m_isX11) { 0091 return QString(); 0092 } 0093 XClassHint hints_ret; 0094 if (XGetClassHint(QX11Info::display(), id_P, &hints_ret) == 0) // 0 means error 0095 return ""; 0096 QString ret(hints_ret.res_name); 0097 ret += ' '; 0098 ret += hints_ret.res_class; 0099 XFree(hints_ret.res_name); 0100 XFree(hints_ret.res_class); 0101 return ret; 0102 } 0103 0104 WId WindowsHandler::active_window() 0105 { 0106 return KWindowSystem::activeWindow(); 0107 } 0108 0109 WId WindowsHandler::action_window() 0110 { 0111 return _action_window; 0112 } 0113 0114 void WindowsHandler::set_action_window(WId window_P) 0115 { 0116 _action_window = window_P; 0117 } 0118 0119 WId WindowsHandler::find_window(const Windowdef_list *window_P) 0120 { 0121 const QList<WId> windows = KWindowSystem::windows(); 0122 for (auto it = windows.begin(); it != windows.end(); ++it) { 0123 Window_data tmp(*it); 0124 if (window_P->match(tmp)) 0125 return *it; 0126 } 0127 return None; 0128 } 0129 0130 WId WindowsHandler::window_at_position(int x, int y) 0131 { 0132 if (!QX11Info::isPlatformX11()) { 0133 return 0; 0134 } 0135 Window child, dummy; 0136 Window parent = QX11Info::appRootWindow(); 0137 Atom wm_state = XInternAtom(QX11Info::display(), "WM_STATE", False); 0138 for (int i = 0; i < 10; ++i) { 0139 int destx, desty; 0140 // find child at that position 0141 if (!XTranslateCoordinates(QX11Info::display(), parent, parent, x, y, &destx, &desty, &child) || child == None) 0142 return 0; 0143 // and now transform coordinates to the child 0144 if (!XTranslateCoordinates(QX11Info::display(), parent, child, x, y, &destx, &desty, &dummy)) 0145 return 0; 0146 x = destx; 0147 y = desty; 0148 Atom type; 0149 int format; 0150 unsigned long nitems, after; 0151 unsigned char *prop; 0152 if (XGetWindowProperty(QX11Info::display(), child, wm_state, 0, 0, False, AnyPropertyType, &type, &format, &nitems, &after, &prop) == Success) { 0153 if (prop != nullptr) 0154 XFree(prop); 0155 if (type != None) 0156 return child; 0157 } 0158 parent = child; 0159 } 0160 return 0; 0161 } 0162 0163 void WindowsHandler::activate_window(WId id_P) 0164 { 0165 KWindowSystem::forceActiveWindow(id_P); 0166 } 0167 0168 // Window_data 0169 0170 Window_data::Window_data(WId id_P) 0171 : type(NET::Unknown) 0172 { 0173 KWindowInfo kwin_info(id_P, NET::WMName | NET::WMWindowType); // TODO optimize 0174 if (kwin_info.valid()) { 0175 title = kwin_info.name(); 0176 role = windows_handler->get_window_role(id_P); 0177 wclass = windows_handler->get_window_class(id_P); 0178 type = kwin_info.windowType(SUPPORTED_WINDOW_TYPES_MASK); 0179 if (type == NET::Override) // HACK consider non-NETWM fullscreens to be normal too 0180 type = NET::Normal; 0181 if (type == NET::Unknown) 0182 type = NET::Normal; 0183 } 0184 } 0185 0186 } // namespace KHotKeys 0187 0188 #include "moc_windows_handler.cpp"