Changeset View
Changeset View
Standalone View
Standalone View
client.cpp
Show First 20 Lines • Show All 80 Lines • ▼ Show 20 Line(s) | |||||
81 | // | 81 | // | ||
82 | // Destroying a client: | 82 | // Destroying a client: | ||
83 | // - destroyClient() - only when the window itself has been destroyed | 83 | // - destroyClient() - only when the window itself has been destroyed | ||
84 | // - releaseWindow() - the window is kept, only the client itself is destroyed | 84 | // - releaseWindow() - the window is kept, only the client itself is destroyed | ||
85 | 85 | | |||
86 | /** | 86 | /** | ||
87 | * \class Client client.h | 87 | * \class Client client.h | ||
88 | * \brief The Client class encapsulates a window decoration frame. | 88 | * \brief The Client class encapsulates a window decoration frame. | ||
89 | */ | 89 | **/ | ||
90 | 90 | | |||
91 | /** | 91 | /** | ||
92 | * This ctor is "dumb" - it only initializes data. All the real initialization | 92 | * This ctor is "dumb" - it only initializes data. All the real initialization | ||
93 | * is done in manage(). | 93 | * is done in manage(). | ||
94 | */ | 94 | **/ | ||
95 | Client::Client() | 95 | Client::Client() | ||
96 | : AbstractClient() | 96 | : AbstractClient() | ||
97 | , m_client() | 97 | , m_client() | ||
98 | , m_wrapper() | 98 | , m_wrapper() | ||
99 | , m_frame() | 99 | , m_frame() | ||
100 | , m_activityUpdatesBlocked(false) | 100 | , m_activityUpdatesBlocked(false) | ||
101 | , m_blockedActivityUpdatesRequireTransients(false) | 101 | , m_blockedActivityUpdatesRequireTransients(false) | ||
102 | , m_moveResizeGrabWindow() | 102 | , m_moveResizeGrabWindow() | ||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Line(s) | 178 | else | |||
179 | m_client.deleteProperty(atoms->kde_net_wm_tab_group); | 179 | m_client.deleteProperty(atoms->kde_net_wm_tab_group); | ||
180 | }); | 180 | }); | ||
181 | 181 | | |||
182 | // SELI TODO: Initialize xsizehints?? | 182 | // SELI TODO: Initialize xsizehints?? | ||
183 | } | 183 | } | ||
184 | 184 | | |||
185 | /** | 185 | /** | ||
186 | * "Dumb" destructor. | 186 | * "Dumb" destructor. | ||
187 | */ | 187 | **/ | ||
188 | Client::~Client() | 188 | Client::~Client() | ||
189 | { | 189 | { | ||
190 | if (m_killHelperPID && !::kill(m_killHelperPID, 0)) { // means the process is alive | 190 | if (m_killHelperPID && !::kill(m_killHelperPID, 0)) { // means the process is alive | ||
191 | ::kill(m_killHelperPID, SIGTERM); | 191 | ::kill(m_killHelperPID, SIGTERM); | ||
192 | m_killHelperPID = 0; | 192 | m_killHelperPID = 0; | ||
193 | } | 193 | } | ||
194 | //SWrapper::Client::clientRelease(this); | 194 | //SWrapper::Client::clientRelease(this); | ||
195 | if (syncRequest.alarm != XCB_NONE) | 195 | if (syncRequest.alarm != XCB_NONE) | ||
Show All 11 Lines | |||||
207 | // Use destroyClient() or releaseWindow(), Client instances cannot be deleted directly | 207 | // Use destroyClient() or releaseWindow(), Client instances cannot be deleted directly | ||
208 | void Client::deleteClient(Client* c) | 208 | void Client::deleteClient(Client* c) | ||
209 | { | 209 | { | ||
210 | delete c; | 210 | delete c; | ||
211 | } | 211 | } | ||
212 | 212 | | |||
213 | /** | 213 | /** | ||
214 | * Releases the window. The client has done its job and the window is still existing. | 214 | * Releases the window. The client has done its job and the window is still existing. | ||
215 | */ | 215 | **/ | ||
216 | void Client::releaseWindow(bool on_shutdown) | 216 | void Client::releaseWindow(bool on_shutdown) | ||
217 | { | 217 | { | ||
218 | assert(!deleting); | 218 | assert(!deleting); | ||
219 | deleting = true; | 219 | deleting = true; | ||
220 | destroyWindowManagementInterface(); | 220 | destroyWindowManagementInterface(); | ||
221 | Deleted* del = NULL; | 221 | Deleted* del = NULL; | ||
222 | if (!on_shutdown) { | 222 | if (!on_shutdown) { | ||
223 | del = Deleted::create(this); | 223 | del = Deleted::create(this); | ||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Line(s) | |||||
277 | } | 277 | } | ||
278 | deleteClient(this); | 278 | deleteClient(this); | ||
279 | ungrabXServer(); | 279 | ungrabXServer(); | ||
280 | } | 280 | } | ||
281 | 281 | | |||
282 | /** | 282 | /** | ||
283 | * Like releaseWindow(), but this one is called when the window has been already destroyed | 283 | * Like releaseWindow(), but this one is called when the window has been already destroyed | ||
284 | * (E.g. The application closed it) | 284 | * (E.g. The application closed it) | ||
285 | */ | 285 | **/ | ||
286 | void Client::destroyClient() | 286 | void Client::destroyClient() | ||
287 | { | 287 | { | ||
288 | assert(!deleting); | 288 | assert(!deleting); | ||
289 | deleting = true; | 289 | deleting = true; | ||
290 | destroyWindowManagementInterface(); | 290 | destroyWindowManagementInterface(); | ||
291 | Deleted* del = Deleted::create(this); | 291 | Deleted* del = Deleted::create(this); | ||
292 | if (isMoveResize()) | 292 | if (isMoveResize()) | ||
293 | emit clientFinishUserMovedResized(this); | 293 | emit clientFinishUserMovedResized(this); | ||
▲ Show 20 Lines • Show All 268 Lines • ▼ Show 20 Line(s) | |||||
562 | } | 562 | } | ||
563 | 563 | | |||
564 | /** | 564 | /** | ||
565 | * Resizes the decoration, and makes sure the decoration widget gets resize event | 565 | * Resizes the decoration, and makes sure the decoration widget gets resize event | ||
566 | * even if the size hasn't changed. This is needed to make sure the decoration | 566 | * even if the size hasn't changed. This is needed to make sure the decoration | ||
567 | * re-layouts (e.g. when maximization state changes, | 567 | * re-layouts (e.g. when maximization state changes, | ||
568 | * the decoration may alter some borders, but the actual size | 568 | * the decoration may alter some borders, but the actual size | ||
569 | * of the decoration stays the same). | 569 | * of the decoration stays the same). | ||
570 | */ | 570 | **/ | ||
571 | void Client::resizeDecoration() | 571 | void Client::resizeDecoration() | ||
572 | { | 572 | { | ||
573 | triggerDecorationRepaint(); | 573 | triggerDecorationRepaint(); | ||
574 | updateInputWindow(); | 574 | updateInputWindow(); | ||
575 | } | 575 | } | ||
576 | 576 | | |||
577 | bool Client::noBorder() const | 577 | bool Client::noBorder() const | ||
578 | { | 578 | { | ||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Line(s) | 679 | { | |||
680 | if (hidden == hide) | 680 | if (hidden == hide) | ||
681 | return; | 681 | return; | ||
682 | hidden = hide; | 682 | hidden = hide; | ||
683 | updateVisibility(); | 683 | updateVisibility(); | ||
684 | } | 684 | } | ||
685 | 685 | | |||
686 | /** | 686 | /** | ||
687 | * Returns whether the window is minimizable or not | 687 | * Returns whether the window is minimizable or not | ||
688 | */ | 688 | **/ | ||
689 | bool Client::isMinimizable() const | 689 | bool Client::isMinimizable() const | ||
690 | { | 690 | { | ||
691 | if (isSpecialWindow() && !isTransient()) | 691 | if (isSpecialWindow() && !isTransient()) | ||
692 | return false; | 692 | return false; | ||
693 | if (!rules()->checkMinimize(true)) | 693 | if (!rules()->checkMinimize(true)) | ||
694 | return false; | 694 | return false; | ||
695 | 695 | | |||
696 | if (isTransient()) { | 696 | if (isTransient()) { | ||
▲ Show 20 Lines • Show All 223 Lines • ▼ Show 20 Line(s) | 884 | { | |||
920 | } | 920 | } | ||
921 | internalShow(); | 921 | internalShow(); | ||
922 | } | 922 | } | ||
923 | 923 | | |||
924 | 924 | | |||
925 | /** | 925 | /** | ||
926 | * Sets the client window's mapping state. Possible values are | 926 | * Sets the client window's mapping state. Possible values are | ||
927 | * WithdrawnState, IconicState, NormalState. | 927 | * WithdrawnState, IconicState, NormalState. | ||
928 | */ | 928 | **/ | ||
929 | void Client::exportMappingState(int s) | 929 | void Client::exportMappingState(int s) | ||
930 | { | 930 | { | ||
931 | assert(m_client != XCB_WINDOW_NONE); | 931 | assert(m_client != XCB_WINDOW_NONE); | ||
932 | assert(!deleting || s == WithdrawnState); | 932 | assert(!deleting || s == WithdrawnState); | ||
933 | if (s == WithdrawnState) { | 933 | if (s == WithdrawnState) { | ||
934 | m_client.deleteProperty(atoms->wm_state); | 934 | m_client.deleteProperty(atoms->wm_state); | ||
935 | return; | 935 | return; | ||
936 | } | 936 | } | ||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Line(s) | 976 | { | |||
988 | addWorkspaceRepaint(visibleRect()); | 988 | addWorkspaceRepaint(visibleRect()); | ||
989 | workspace()->clientHidden(this); | 989 | workspace()->clientHidden(this); | ||
990 | } | 990 | } | ||
991 | 991 | | |||
992 | /** | 992 | /** | ||
993 | * Maps (shows) the client. Note that it is mapping state of the frame, | 993 | * Maps (shows) the client. Note that it is mapping state of the frame, | ||
994 | * not necessarily the client window itself (i.e. a shaded window is here | 994 | * not necessarily the client window itself (i.e. a shaded window is here | ||
995 | * considered mapped, even though it is in IconicState). | 995 | * considered mapped, even though it is in IconicState). | ||
996 | */ | 996 | **/ | ||
997 | void Client::map() | 997 | void Client::map() | ||
998 | { | 998 | { | ||
999 | // XComposite invalidates backing pixmaps on unmap (minimize, different | 999 | // XComposite invalidates backing pixmaps on unmap (minimize, different | ||
1000 | // virtual desktop, etc.). We kept the last known good pixmap around | 1000 | // virtual desktop, etc.). We kept the last known good pixmap around | ||
1001 | // for use in effects, but now we want to have access to the new pixmap | 1001 | // for use in effects, but now we want to have access to the new pixmap | ||
1002 | if (compositing()) | 1002 | if (compositing()) | ||
1003 | discardWindowPixmap(); | 1003 | discardWindowPixmap(); | ||
1004 | m_frame.map(); | 1004 | m_frame.map(); | ||
1005 | if (!isShade()) { | 1005 | if (!isShade()) { | ||
1006 | m_wrapper.map(); | 1006 | m_wrapper.map(); | ||
1007 | m_client.map(); | 1007 | m_client.map(); | ||
1008 | m_decoInputExtent.map(); | 1008 | m_decoInputExtent.map(); | ||
1009 | exportMappingState(NormalState); | 1009 | exportMappingState(NormalState); | ||
1010 | } else | 1010 | } else | ||
1011 | exportMappingState(IconicState); | 1011 | exportMappingState(IconicState); | ||
1012 | addLayerRepaint(visibleRect()); | 1012 | addLayerRepaint(visibleRect()); | ||
1013 | } | 1013 | } | ||
1014 | 1014 | | |||
1015 | /** | 1015 | /** | ||
1016 | * Unmaps the client. Again, this is about the frame. | 1016 | * Unmaps the client. Again, this is about the frame. | ||
1017 | */ | 1017 | **/ | ||
1018 | void Client::unmap() | 1018 | void Client::unmap() | ||
1019 | { | 1019 | { | ||
1020 | // Here it may look like a race condition, as some other client might try to unmap | 1020 | // Here it may look like a race condition, as some other client might try to unmap | ||
1021 | // the window between these two XSelectInput() calls. However, they're supposed to | 1021 | // the window between these two XSelectInput() calls. However, they're supposed to | ||
1022 | // use XWithdrawWindow(), which also sends a synthetic event to the root window, | 1022 | // use XWithdrawWindow(), which also sends a synthetic event to the root window, | ||
1023 | // which won't be missed, so this shouldn't be a problem. The chance the real UnmapNotify | 1023 | // which won't be missed, so this shouldn't be a problem. The chance the real UnmapNotify | ||
1024 | // will be missed is also very minimal, so I don't think it's needed to grab the server | 1024 | // will be missed is also very minimal, so I don't think it's needed to grab the server | ||
1025 | // here. | 1025 | // here. | ||
Show All 11 Lines | |||||
1037 | * there wouldn't be any previews of windows that are minimized or on another | 1037 | * there wouldn't be any previews of windows that are minimized or on another | ||
1038 | * virtual desktop. Therefore rawHide() actually keeps such windows mapped. | 1038 | * virtual desktop. Therefore rawHide() actually keeps such windows mapped. | ||
1039 | * However special care needs to be taken so that such windows don't interfere. | 1039 | * However special care needs to be taken so that such windows don't interfere. | ||
1040 | * Therefore they're put very low in the stacking order and they have input shape | 1040 | * Therefore they're put very low in the stacking order and they have input shape | ||
1041 | * set to none, which hopefully is enough. If there's no input shape available, | 1041 | * set to none, which hopefully is enough. If there's no input shape available, | ||
1042 | * then it's hoped that there will be some other desktop above it *shrug*. | 1042 | * then it's hoped that there will be some other desktop above it *shrug*. | ||
1043 | * Using normal shape would be better, but that'd affect other things, e.g. painting | 1043 | * Using normal shape would be better, but that'd affect other things, e.g. painting | ||
1044 | * of the actual preview. | 1044 | * of the actual preview. | ||
1045 | */ | 1045 | **/ | ||
1046 | void Client::updateHiddenPreview() | 1046 | void Client::updateHiddenPreview() | ||
1047 | { | 1047 | { | ||
1048 | if (hiddenPreview()) { | 1048 | if (hiddenPreview()) { | ||
1049 | workspace()->forceRestacking(); | 1049 | workspace()->forceRestacking(); | ||
1050 | if (Xcb::Extensions::self()->isShapeInputAvailable()) { | 1050 | if (Xcb::Extensions::self()->isShapeInputAvailable()) { | ||
1051 | xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, | 1051 | xcb_shape_rectangles(connection(), XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, | ||
1052 | XCB_CLIP_ORDERING_UNSORTED, frameId(), 0, 0, 0, NULL); | 1052 | XCB_CLIP_ORDERING_UNSORTED, frameId(), 0, 0, 0, NULL); | ||
1053 | } | 1053 | } | ||
Show All 21 Lines | 1074 | if (w == rootWindow()) { | |||
1075 | eventMask = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; // Magic! | 1075 | eventMask = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; // Magic! | ||
1076 | } | 1076 | } | ||
1077 | xcb_send_event(connection(), false, w, eventMask, reinterpret_cast<const char*>(&ev)); | 1077 | xcb_send_event(connection(), false, w, eventMask, reinterpret_cast<const char*>(&ev)); | ||
1078 | xcb_flush(connection()); | 1078 | xcb_flush(connection()); | ||
1079 | } | 1079 | } | ||
1080 | 1080 | | |||
1081 | /** | 1081 | /** | ||
1082 | * Returns whether the window may be closed (have a close button) | 1082 | * Returns whether the window may be closed (have a close button) | ||
1083 | */ | 1083 | **/ | ||
1084 | bool Client::isCloseable() const | 1084 | bool Client::isCloseable() const | ||
1085 | { | 1085 | { | ||
1086 | return rules()->checkCloseable(m_motif.close() && !isSpecialWindow()); | 1086 | return rules()->checkCloseable(m_motif.close() && !isSpecialWindow()); | ||
1087 | } | 1087 | } | ||
1088 | 1088 | | |||
1089 | /** | 1089 | /** | ||
1090 | * Closes the window by either sending a delete_window message or using XKill. | 1090 | * Closes the window by either sending a delete_window message or using XKill. | ||
1091 | */ | 1091 | **/ | ||
1092 | void Client::closeWindow() | 1092 | void Client::closeWindow() | ||
1093 | { | 1093 | { | ||
1094 | if (!isCloseable()) | 1094 | if (!isCloseable()) | ||
1095 | return; | 1095 | return; | ||
1096 | 1096 | | |||
1097 | // Update user time, because the window may create a confirming dialog. | 1097 | // Update user time, because the window may create a confirming dialog. | ||
1098 | updateUserTime(); | 1098 | updateUserTime(); | ||
1099 | 1099 | | |||
1100 | if (info->supportsProtocol(NET::DeleteWindowProtocol)) { | 1100 | if (info->supportsProtocol(NET::DeleteWindowProtocol)) { | ||
1101 | sendClientMessage(window(), atoms->wm_protocols, atoms->wm_delete_window); | 1101 | sendClientMessage(window(), atoms->wm_protocols, atoms->wm_delete_window); | ||
1102 | pingWindow(); | 1102 | pingWindow(); | ||
1103 | } else // Client will not react on wm_delete_window. We have not choice | 1103 | } else // Client will not react on wm_delete_window. We have not choice | ||
1104 | // but destroy his connection to the XServer. | 1104 | // but destroy his connection to the XServer. | ||
1105 | killWindow(); | 1105 | killWindow(); | ||
1106 | } | 1106 | } | ||
1107 | 1107 | | |||
1108 | 1108 | | |||
1109 | /** | 1109 | /** | ||
1110 | * Kills the window via XKill | 1110 | * Kills the window via XKill | ||
1111 | */ | 1111 | **/ | ||
1112 | void Client::killWindow() | 1112 | void Client::killWindow() | ||
1113 | { | 1113 | { | ||
1114 | qCDebug(KWIN_CORE) << "Client::killWindow():" << caption(); | 1114 | qCDebug(KWIN_CORE) << "Client::killWindow():" << caption(); | ||
1115 | killProcess(false); | 1115 | killProcess(false); | ||
1116 | m_client.kill(); // Always kill this client at the server | 1116 | m_client.kill(); // Always kill this client at the server | ||
1117 | destroyClient(); | 1117 | destroyClient(); | ||
1118 | } | 1118 | } | ||
1119 | 1119 | | |||
1120 | /** | 1120 | /** | ||
1121 | * Send a ping to the window using _NET_WM_PING if possible if it | 1121 | * Send a ping to the window using _NET_WM_PING if possible if it | ||
1122 | * doesn't respond within a reasonable time, it will be killed. | 1122 | * doesn't respond within a reasonable time, it will be killed. | ||
1123 | */ | 1123 | **/ | ||
1124 | void Client::pingWindow() | 1124 | void Client::pingWindow() | ||
1125 | { | 1125 | { | ||
1126 | if (!info->supportsProtocol(NET::PingProtocol)) | 1126 | if (!info->supportsProtocol(NET::PingProtocol)) | ||
1127 | return; // Can't ping :( | 1127 | return; // Can't ping :( | ||
1128 | if (options->killPingTimeout() == 0) | 1128 | if (options->killPingTimeout() == 0) | ||
1129 | return; // Turned off | 1129 | return; // Turned off | ||
1130 | if (ping_timer != NULL) | 1130 | if (ping_timer != NULL) | ||
1131 | return; // Pinging already | 1131 | return; // Pinging already | ||
▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Line(s) | |||||
1227 | } | 1227 | } | ||
1228 | 1228 | | |||
1229 | /** | 1229 | /** | ||
1230 | * Sets whether the client is on @p activity. | 1230 | * Sets whether the client is on @p activity. | ||
1231 | * If you remove it from its last activity, then it's on all activities. | 1231 | * If you remove it from its last activity, then it's on all activities. | ||
1232 | * | 1232 | * | ||
1233 | * Note: If it was on all activities and you try to remove it from one, nothing will happen; | 1233 | * Note: If it was on all activities and you try to remove it from one, nothing will happen; | ||
1234 | * I don't think that's an important enough use case to handle here. | 1234 | * I don't think that's an important enough use case to handle here. | ||
1235 | */ | 1235 | **/ | ||
1236 | void Client::setOnActivity(const QString &activity, bool enable) | 1236 | void Client::setOnActivity(const QString &activity, bool enable) | ||
1237 | { | 1237 | { | ||
1238 | #ifdef KWIN_BUILD_ACTIVITIES | 1238 | #ifdef KWIN_BUILD_ACTIVITIES | ||
1239 | if (! Activities::self()) { | 1239 | if (! Activities::self()) { | ||
1240 | return; | 1240 | return; | ||
1241 | } | 1241 | } | ||
1242 | QStringList newActivitiesList = activities(); | 1242 | QStringList newActivitiesList = activities(); | ||
1243 | if (newActivitiesList.contains(activity) == enable) //nothing to do | 1243 | if (newActivitiesList.contains(activity) == enable) //nothing to do | ||
Show All 9 Lines | |||||
1253 | #else | 1253 | #else | ||
1254 | Q_UNUSED(activity) | 1254 | Q_UNUSED(activity) | ||
1255 | Q_UNUSED(enable) | 1255 | Q_UNUSED(enable) | ||
1256 | #endif | 1256 | #endif | ||
1257 | } | 1257 | } | ||
1258 | 1258 | | |||
1259 | /** | 1259 | /** | ||
1260 | * set exactly which activities this client is on | 1260 | * set exactly which activities this client is on | ||
1261 | */ | 1261 | **/ | ||
1262 | void Client::setOnActivities(QStringList newActivitiesList) | 1262 | void Client::setOnActivities(QStringList newActivitiesList) | ||
1263 | { | 1263 | { | ||
1264 | #ifdef KWIN_BUILD_ACTIVITIES | 1264 | #ifdef KWIN_BUILD_ACTIVITIES | ||
1265 | if (!Activities::self()) { | 1265 | if (!Activities::self()) { | ||
1266 | return; | 1266 | return; | ||
1267 | } | 1267 | } | ||
1268 | QString joinedActivitiesList = newActivitiesList.join(QStringLiteral(",")); | 1268 | QString joinedActivitiesList = newActivitiesList.join(QStringLiteral(",")); | ||
1269 | joinedActivitiesList = rules()->checkActivity(joinedActivitiesList, false); | 1269 | joinedActivitiesList = rules()->checkActivity(joinedActivitiesList, false); | ||
Show All 40 Lines | 1308 | } else { | |||
1310 | --m_activityUpdatesBlocked; | 1310 | --m_activityUpdatesBlocked; | ||
1311 | if (!m_activityUpdatesBlocked) | 1311 | if (!m_activityUpdatesBlocked) | ||
1312 | updateActivities(m_blockedActivityUpdatesRequireTransients); | 1312 | updateActivities(m_blockedActivityUpdatesRequireTransients); | ||
1313 | } | 1313 | } | ||
1314 | } | 1314 | } | ||
1315 | 1315 | | |||
1316 | /** | 1316 | /** | ||
1317 | * update after activities changed | 1317 | * update after activities changed | ||
1318 | */ | 1318 | **/ | ||
1319 | void Client::updateActivities(bool includeTransients) | 1319 | void Client::updateActivities(bool includeTransients) | ||
1320 | { | 1320 | { | ||
1321 | if (m_activityUpdatesBlocked) { | 1321 | if (m_activityUpdatesBlocked) { | ||
1322 | m_blockedActivityUpdatesRequireTransients |= includeTransients; | 1322 | m_blockedActivityUpdatesRequireTransients |= includeTransients; | ||
1323 | return; | 1323 | return; | ||
1324 | } | 1324 | } | ||
1325 | emit activitiesChanged(this); | 1325 | emit activitiesChanged(this); | ||
1326 | m_blockedActivityUpdatesRequireTransients = false; // reset | 1326 | m_blockedActivityUpdatesRequireTransients = false; // reset | ||
1327 | FocusChain::self()->update(this, FocusChain::MakeFirst); | 1327 | FocusChain::self()->update(this, FocusChain::MakeFirst); | ||
1328 | updateVisibility(); | 1328 | updateVisibility(); | ||
1329 | updateWindowRules(Rules::Activity); | 1329 | updateWindowRules(Rules::Activity); | ||
1330 | 1330 | | |||
1331 | // Update states of all other windows in this group | 1331 | // Update states of all other windows in this group | ||
1332 | if (tabGroup()) | 1332 | if (tabGroup()) | ||
1333 | tabGroup()->updateStates(this, TabGroup::Activity); | 1333 | tabGroup()->updateStates(this, TabGroup::Activity); | ||
1334 | } | 1334 | } | ||
1335 | 1335 | | |||
1336 | /** | 1336 | /** | ||
1337 | * Returns the list of activities the client window is on. | 1337 | * Returns the list of activities the client window is on. | ||
1338 | * if it's on all activities, the list will be empty. | 1338 | * if it's on all activities, the list will be empty. | ||
1339 | * Don't use this, use isOnActivity() and friends (from class Toplevel) | 1339 | * Don't use this, use isOnActivity() and friends (from class Toplevel) | ||
1340 | */ | 1340 | **/ | ||
1341 | QStringList Client::activities() const | 1341 | QStringList Client::activities() const | ||
1342 | { | 1342 | { | ||
1343 | if (sessionActivityOverride) { | 1343 | if (sessionActivityOverride) { | ||
1344 | return QStringList(); | 1344 | return QStringList(); | ||
1345 | } | 1345 | } | ||
1346 | return activityList; | 1346 | return activityList; | ||
1347 | } | 1347 | } | ||
1348 | 1348 | | |||
1349 | /** | 1349 | /** | ||
1350 | * if @p on is true, sets on all activities. | 1350 | * if @p on is true, sets on all activities. | ||
1351 | * if it's false, sets it to only be on the current activity | 1351 | * if it's false, sets it to only be on the current activity | ||
1352 | */ | 1352 | **/ | ||
1353 | void Client::setOnAllActivities(bool on) | 1353 | void Client::setOnAllActivities(bool on) | ||
1354 | { | 1354 | { | ||
1355 | #ifdef KWIN_BUILD_ACTIVITIES | 1355 | #ifdef KWIN_BUILD_ACTIVITIES | ||
1356 | if (on == isOnAllActivities()) | 1356 | if (on == isOnAllActivities()) | ||
1357 | return; | 1357 | return; | ||
1358 | if (on) { | 1358 | if (on) { | ||
1359 | setOnActivities(QStringList()); | 1359 | setOnActivities(QStringList()); | ||
1360 | 1360 | | |||
1361 | } else { | 1361 | } else { | ||
1362 | setOnActivity(Activities::self()->current(), true); | 1362 | setOnActivity(Activities::self()->current(), true); | ||
1363 | } | 1363 | } | ||
1364 | #else | 1364 | #else | ||
1365 | Q_UNUSED(on) | 1365 | Q_UNUSED(on) | ||
1366 | #endif | 1366 | #endif | ||
1367 | } | 1367 | } | ||
1368 | 1368 | | |||
1369 | /** | 1369 | /** | ||
1370 | * Performs the actual focusing of the window using XSetInputFocus and WM_TAKE_FOCUS | 1370 | * Performs the actual focusing of the window using XSetInputFocus and WM_TAKE_FOCUS | ||
1371 | */ | 1371 | **/ | ||
1372 | void Client::takeFocus() | 1372 | void Client::takeFocus() | ||
1373 | { | 1373 | { | ||
1374 | if (rules()->checkAcceptFocus(info->input())) | 1374 | if (rules()->checkAcceptFocus(info->input())) | ||
1375 | m_client.focus(); | 1375 | m_client.focus(); | ||
1376 | else | 1376 | else | ||
1377 | demandAttention(false); // window cannot take input, at least withdraw urgency | 1377 | demandAttention(false); // window cannot take input, at least withdraw urgency | ||
1378 | if (info->supportsProtocol(NET::TakeFocusProtocol)) { | 1378 | if (info->supportsProtocol(NET::TakeFocusProtocol)) { | ||
1379 | sendClientMessage(window(), atoms->wm_protocols, atoms->wm_take_focus, 0, 0, 0, XCB_CURRENT_TIME); | 1379 | sendClientMessage(window(), atoms->wm_protocols, atoms->wm_take_focus, 0, 0, 0, XCB_CURRENT_TIME); | ||
Show All 14 Lines | |||||
1394 | } | 1394 | } | ||
1395 | 1395 | | |||
1396 | /** | 1396 | /** | ||
1397 | * Returns whether the window provides context help or not. If it does, | 1397 | * Returns whether the window provides context help or not. If it does, | ||
1398 | * you should show a help menu item or a help button like '?' and call | 1398 | * you should show a help menu item or a help button like '?' and call | ||
1399 | * contextHelp() if this is invoked. | 1399 | * contextHelp() if this is invoked. | ||
1400 | * | 1400 | * | ||
1401 | * \sa contextHelp() | 1401 | * \sa contextHelp() | ||
1402 | */ | 1402 | **/ | ||
1403 | bool Client::providesContextHelp() const | 1403 | bool Client::providesContextHelp() const | ||
1404 | { | 1404 | { | ||
1405 | return info->supportsProtocol(NET::ContextHelpProtocol); | 1405 | return info->supportsProtocol(NET::ContextHelpProtocol); | ||
1406 | } | 1406 | } | ||
1407 | 1407 | | |||
1408 | /** | 1408 | /** | ||
1409 | * Invokes context help on the window. Only works if the window | 1409 | * Invokes context help on the window. Only works if the window | ||
1410 | * actually provides context help. | 1410 | * actually provides context help. | ||
1411 | * | 1411 | * | ||
1412 | * \sa providesContextHelp() | 1412 | * \sa providesContextHelp() | ||
1413 | */ | 1413 | **/ | ||
1414 | void Client::showContextHelp() | 1414 | void Client::showContextHelp() | ||
1415 | { | 1415 | { | ||
1416 | if (info->supportsProtocol(NET::ContextHelpProtocol)) { | 1416 | if (info->supportsProtocol(NET::ContextHelpProtocol)) { | ||
1417 | sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_context_help); | 1417 | sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_context_help); | ||
1418 | } | 1418 | } | ||
1419 | } | 1419 | } | ||
1420 | 1420 | | |||
1421 | /** | 1421 | /** | ||
1422 | * Fetches the window's caption (WM_NAME property). It will be | 1422 | * Fetches the window's caption (WM_NAME property). It will be | ||
1423 | * stored in the client's caption(). | 1423 | * stored in the client's caption(). | ||
1424 | */ | 1424 | **/ | ||
1425 | void Client::fetchName() | 1425 | void Client::fetchName() | ||
1426 | { | 1426 | { | ||
1427 | setCaption(readName()); | 1427 | setCaption(readName()); | ||
1428 | } | 1428 | } | ||
1429 | 1429 | | |||
1430 | static inline QString readNameProperty(xcb_window_t w, xcb_atom_t atom) | 1430 | static inline QString readNameProperty(xcb_window_t w, xcb_atom_t atom) | ||
1431 | { | 1431 | { | ||
1432 | const auto cookie = xcb_icccm_get_text_property_unchecked(connection(), w, atom); | 1432 | const auto cookie = xcb_icccm_get_text_property_unchecked(connection(), w, atom); | ||
▲ Show 20 Lines • Show All 226 Lines • ▼ Show 20 Line(s) | 1652 | } else { | |||
1659 | xcb_sync_change_alarm_aux(c, syncRequest.alarm, XCB_SYNC_CA_DELTA | XCB_SYNC_CA_VALUE, &value); | 1659 | xcb_sync_change_alarm_aux(c, syncRequest.alarm, XCB_SYNC_CA_DELTA | XCB_SYNC_CA_VALUE, &value); | ||
1660 | } | 1660 | } | ||
1661 | } | 1661 | } | ||
1662 | } | 1662 | } | ||
1663 | } | 1663 | } | ||
1664 | 1664 | | |||
1665 | /** | 1665 | /** | ||
1666 | * Send the client a _NET_SYNC_REQUEST | 1666 | * Send the client a _NET_SYNC_REQUEST | ||
1667 | */ | 1667 | **/ | ||
1668 | void Client::sendSyncRequest() | 1668 | void Client::sendSyncRequest() | ||
1669 | { | 1669 | { | ||
1670 | if (syncRequest.counter == XCB_NONE || syncRequest.isPending) | 1670 | if (syncRequest.counter == XCB_NONE || syncRequest.isPending) | ||
1671 | return; // do NOT, NEVER send a sync request when there's one on the stack. the clients will just stop respoding. FOREVER! ... | 1671 | return; // do NOT, NEVER send a sync request when there's one on the stack. the clients will just stop respoding. FOREVER! ... | ||
1672 | 1672 | | |||
1673 | if (!syncRequest.failsafeTimeout) { | 1673 | if (!syncRequest.failsafeTimeout) { | ||
1674 | syncRequest.failsafeTimeout = new QTimer(this); | 1674 | syncRequest.failsafeTimeout = new QTimer(this); | ||
1675 | connect(syncRequest.failsafeTimeout, &QTimer::timeout, this, | 1675 | connect(syncRequest.failsafeTimeout, &QTimer::timeout, this, | ||
▲ Show 20 Lines • Show All 430 Lines • Show Last 20 Lines |