问题
Currently I am in charge of developing a (C++) window class for a little project; the goal is to keep dependencies at a bare minimum. The implementation for Win32/WinAPI works as supposed, however, I am struggling when it comes to Linux/XCB.
I am aware, that I am able to check the "_NET_WM_STATE" property, however, the documentation doesn't specify any event, which would occur when the window is being maximized or minimized. The Extended Window Manager Hints specification doesn't seem to define a event either.
So, how would one intercept the Maximize/Minimize event?
EDIT: My code looks basically like that, but doesn't work: (By doesn't work, I mean the if-condition below is never met.)
// xcb_generic_event_t* msg;
// xcb_intern_atom_reply_t* wmStateMinimized;
case XCB_PROPERTY_NOTIFY: {
xcb_property_notify_event_t* data{reinterpret_cast<xcb_property_notify_event_t*>(msg)};
if(data->atom == wmStateMinimized->atom)
eventQueue.emplace(Event::Minimized);
} break;
I have also checked the atoms the event provides me. They differ from the atom provided by 'wmStateMinimized', altough the atom for 'wmStateMinimized' is provided by the window manager.
EDIT 2: Ok, the xcb_property_notify_event_t supplies the atom that has been change, not the value it self. So the if should look like this then:
if(data->atom == wmState->atom)
Gotta figure out, how to retrieve the value properly.
回答1:
So, after 3 hours I finally figured it out. This solution snippet assumes, that you already have queried the atoms:
- _NET_WM_STATE
- _NET_WM_STATE_HIDDEN
- _NET_WM_STATE_MAXIMIZED_VERT
- _NET_WM_STATE_MAXIMIZED_HORZ
They are being stored in the following atoms:
xcb_atom_t wmState;
xcb_atom_t wmStateHidden;
xcb_atom_t wmStateMaxVert;
xcb_atom_t wmStateMaxHorz;
This snippet does as well assume, that you have specified
XCB_EVENT_MASK_PROPERTY_CHANGE
for the window, in order to actually get notified about property changes.
So, let's pretend we're in the Event Loop now:
case XCB_PROPERTY_NOTIFY: {
xcb_property_notify_event_t* data{reinterpret_cast<xcb_property_notify_event_t*>(msg)};
if(data->atom == wmState){ // the WM_STATE property was changed.
// Now we need the value.
// Therefore I implemented an auxiliary function.
if(internal::getAtomValue(connection, window, wmState) == wmStateHidden)
// Handle Events here:
eventQueue.emplace(Event::Minimized);
else{
xcb_atom_t value{internal::getAtomValue(connection, window, wmState)};
if((value == wmStateMaxVert) || (value == wmStateMaxHorz))
// Handle Event here
eventQueue.emplace(Event::Maximized);
}
}
} break;
The auxiliary function 'internal::getAtomValue' works as following:
xcb_get_property_cookie_t cookie{xcb_get_property(connection, false, window, atom, XCB_ATOM_ATOM, 0, 32)};
xcb_generic_error_t* err{nullptr};
xcb_get_property_reply_t reply{xcb_get_property_reply(connection, cookie, &err);
xcb_atom_t* value{reinterpret_cast<xcb_atom_t*>(xcb_get_property_value(reply))};
I hope that this solution concept proof and correct. May it serve as an reference for everyone, who needs to work with XCB.
P.S.: These Snippets were stripped down from my original source. It might contain Typos.
来源:https://stackoverflow.com/questions/37568142/what-event-is-used-for-maximizing-minimizing