diff --git a/activation.cpp b/activation.cpp index a8e914fbad..9662f324bd 100644 --- a/activation.cpp +++ b/activation.cpp @@ -846,7 +846,7 @@ void Client::startupIdChanged() void Client::updateUrgency() { - if (urgency) + if (info->urgency()) demandAttention(); } diff --git a/client.cpp b/client.cpp index 68fe122126..e58e225d28 100644 --- a/client.cpp +++ b/client.cpp @@ -200,7 +200,6 @@ Client::Client() , delayedMoveResizeTimer(NULL) , m_colormap(XCB_COLORMAP_NONE) , in_group(NULL) - , m_windowGroup(XCB_WINDOW_NONE) , tab_group(NULL) , in_layer(UnknownLayer) , ping_timer(NULL) @@ -268,7 +267,6 @@ Client::Client() noborder = false; app_noborder = false; motif_noborder = false; - urgency = false; ignore_focus_stealing = false; demands_attention = false; check_active_modal = false; @@ -277,7 +275,6 @@ Client::Client() Ptakefocus = 0; Pcontexthelp = 0; Pping = 0; - input = false; skip_pager = false; max_mode = MaximizeRestore; @@ -1110,7 +1107,7 @@ void Client::setShade(ShadeMode mode) QSize s(sizeForClientSize(clientSize())); shade_geometry_change = false; plainResize(s); - if ((shade_mode == ShadeHover || shade_mode == ShadeActivated) && rules()->checkAcceptFocus(input)) + if ((shade_mode == ShadeHover || shade_mode == ShadeActivated) && rules()->checkAcceptFocus(info->input())) setActive(true); if (shade_mode == ShadeHover) { ToplevelList order = workspace()->stackingOrder(); @@ -1762,7 +1759,7 @@ void Client::takeFocus() previous_focus_timestamp = xTime(); previous_client = this; #endif - if (rules()->checkAcceptFocus(input)) + if (rules()->checkAcceptFocus(info->input())) m_client.focus(); else demandAttention(false); // window cannot take input, at least withdraw urgency @@ -2047,25 +2044,6 @@ void Client::setClientShown(bool shown) } } -void Client::getWMHints() -{ - XWMHints* hints = XGetWMHints(display(), window()); - input = true; - m_windowGroup = XCB_WINDOW_NONE; - urgency = false; - if (hints) { - if (hints->flags & InputHint) - input = hints->input; - if (hints->flags & WindowGroupHint) - m_windowGroup = hints->window_group; - urgency = !!(hints->flags & UrgencyHint); // Need boolean, it's a uint bitfield - XFree((char*)hints); - } - checkGroup(); - updateUrgency(); - updateAllowedActions(); // Group affects isMinimizable() -} - void Client::getMotifHints() { bool mgot_noborder, mnoborder, mresize, mmove, mminimize, mmaximize, mclose; @@ -2257,7 +2235,7 @@ bool Client::wantsTabFocus() const bool Client::wantsInput() const { - return rules()->checkAcceptFocus(input || Ptakefocus); + return rules()->checkAcceptFocus(info->input() || Ptakefocus); } bool Client::isSpecialWindow() const diff --git a/client.h b/client.h index 3a15cbbfd4..635dc951a5 100644 --- a/client.h +++ b/client.h @@ -926,7 +926,6 @@ private: uint Ptakefocus : 1;///< Does the window understand the TakeFocus protocol? uint Pcontexthelp : 1; ///< Does the window understand the ContextHelp protocol? uint Pping : 1; ///< Does it support _NET_WM_PING? - uint input : 1; ///< Does the window want input in its wm_hints uint skip_pager : 1; uint skip_switcher : 1; uint motif_may_resize : 1; @@ -939,12 +938,10 @@ private: uint noborder : 1; uint app_noborder : 1; ///< App requested no border via window type, shape extension, etc. uint motif_noborder : 1; ///< App requested no border via Motif WM hints - uint urgency : 1; ///< XWMHints, UrgencyHint uint ignore_focus_stealing : 1; ///< Don't apply focus stealing prevention to this client uint demands_attention : 1; bool blocks_compositing; WindowRules client_rules; - void getWMHints(); void getWindowProtocols(); QIcon m_icon; Qt::CursorShape m_cursor; @@ -964,7 +961,6 @@ private: xcb_colormap_t m_colormap; QString cap_normal, cap_iconic, cap_suffix, cap_deco; Group* in_group; - xcb_window_t m_windowGroup; TabGroup* tab_group; Layer in_layer; QTimer* ping_timer; diff --git a/events.cpp b/events.cpp index 7736e614e1..1192d3e67b 100644 --- a/events.cpp +++ b/events.cpp @@ -601,6 +601,13 @@ bool Client::windowEvent(xcb_generic_event_t *e) if (dirtyProperties2.testFlag(NET::WM2BlockCompositing)) { setBlockingCompositing(info->isBlockingCompositing()); } + if (dirtyProperties2.testFlag(NET::WM2GroupLeader)) { + checkGroup(); + updateAllowedActions(); // Group affects isMinimizable() + } + if (dirtyProperties2.testFlag(NET::WM2Urgency)) { + updateUrgency(); + } } const uint8_t eventType = e->response_type & ~0x80; @@ -851,7 +858,6 @@ void Client::propertyNotifyEvent(xcb_property_notify_event_t *e) readTransient(); break; case XCB_ATOM_WM_HINTS: - getWMHints(); getIcons(); // because KWin::icon() uses WMHints as fallback break; default: diff --git a/group.cpp b/group.cpp index ba144894d3..9f42ad8d57 100644 --- a/group.cpp +++ b/group.cpp @@ -920,15 +920,15 @@ void Client::checkGroup(Group* set_group, bool force) in_group = set_group; in_group->addMember(this); } - } else if (m_windowGroup != XCB_WINDOW_NONE) { - Group* new_group = workspace()->findGroup(m_windowGroup); + } else if (info->groupLeader() != XCB_WINDOW_NONE) { + Group* new_group = workspace()->findGroup(info->groupLeader()); if (transientFor() != NULL && transientFor()->group() != new_group) { // move the window to the right group (e.g. a dialog provided // by different app, but transient for this one, so make it part of that group) new_group = transientFor()->group(); } if (new_group == NULL) // doesn't exist yet - new_group = new Group(m_windowGroup); + new_group = new Group(info->groupLeader()); if (new_group != in_group) { if (in_group != NULL) in_group->removeMember(this); @@ -1030,7 +1030,7 @@ void Client::changeClientLeaderGroup(Group* gr) if (transientFor() != NULL) return; // also don't change the group for window which have group set - if (m_windowGroup) + if (info->groupLeader()) return; checkGroup(gr); // change group } diff --git a/manage.cpp b/manage.cpp index b8c1454ba7..921162bca2 100644 --- a/manage.cpp +++ b/manage.cpp @@ -100,7 +100,10 @@ bool Client::manage(xcb_window_t w, bool isMapped) NET::WM2ExtendedStrut | NET::WM2Opacity | NET::WM2FullscreenMonitors | - NET::WM2FrameOverlap; + NET::WM2FrameOverlap | + NET::WM2GroupLeader | + NET::WM2Urgency | + NET::WM2Input; info = new WinInfo(this, m_client, rootWindow(), properties, properties2); @@ -123,7 +126,12 @@ bool Client::manage(xcb_window_t w, bool isMapped) detectGtkFrameExtents(); detectNoBorder(); fetchIconicName(); - getWMHints(); // Needs to be done before readTransient() because of reading the group + + // Needs to be done before readTransient() because of reading the group + checkGroup(); + updateUrgency(); + updateAllowedActions(); // Group affects isMinimizable() + modal = (info->state() & NET::Modal) != 0; // Needs to be valid before handling groups readTransient(); getIcons(); diff --git a/useractions.cpp b/useractions.cpp index 305930bd26..980a3c548a 100755 --- a/useractions.cpp +++ b/useractions.cpp @@ -1197,7 +1197,7 @@ bool Client::performMouseCommand(Options::MouseCommand command, const QPoint &gl break; case Options::MouseActivateAndRaise: { replay = isActive(); // for clickraise mode - bool mustReplay = !rules()->checkAcceptFocus(input); + bool mustReplay = !rules()->checkAcceptFocus(info->input()); if (mustReplay) { ToplevelList::const_iterator it = workspace()->stackingOrder().constEnd(), begin = workspace()->stackingOrder().constBegin(); @@ -1217,13 +1217,13 @@ bool Client::performMouseCommand(Options::MouseCommand command, const QPoint &gl workspace()->requestFocus(this); workspace()->lowerClient(this); screens()->setCurrent(globalPos); - replay = replay || !rules()->checkAcceptFocus(input); + replay = replay || !rules()->checkAcceptFocus(info->input()); break; case Options::MouseActivate: replay = isActive(); // for clickraise mode workspace()->takeActivity(this, Workspace::ActivityFocus); screens()->setCurrent(globalPos); - replay = replay || !rules()->checkAcceptFocus(input); + replay = replay || !rules()->checkAcceptFocus(info->input()); break; case Options::MouseActivateRaiseAndPassClick: workspace()->takeActivity(this, Workspace::ActivityFocus | Workspace::ActivityRaise);