mirror of
https://github.com/SFML/SFML.git
synced 2024-11-29 06:41:05 +08:00
Fixed XCB events being handled by the wrong windows in multi-window applications (#843).
This commit is contained in:
parent
c229877313
commit
bd34935f2a
@ -31,6 +31,8 @@
|
|||||||
#include <SFML/Window/Unix/ScopedXcbPtr.hpp>
|
#include <SFML/Window/Unix/ScopedXcbPtr.hpp>
|
||||||
#include <SFML/System/Utf.hpp>
|
#include <SFML/System/Utf.hpp>
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
|
#include <SFML/System/Mutex.hpp>
|
||||||
|
#include <SFML/System/Lock.hpp>
|
||||||
#include <xcb/xcb_icccm.h>
|
#include <xcb/xcb_icccm.h>
|
||||||
#include <xcb/xcb_image.h>
|
#include <xcb/xcb_image.h>
|
||||||
#include <xcb/randr.h>
|
#include <xcb/randr.h>
|
||||||
@ -55,6 +57,7 @@ namespace
|
|||||||
{
|
{
|
||||||
sf::priv::WindowImplX11* fullscreenWindow = NULL;
|
sf::priv::WindowImplX11* fullscreenWindow = NULL;
|
||||||
std::vector<sf::priv::WindowImplX11*> allWindows;
|
std::vector<sf::priv::WindowImplX11*> allWindows;
|
||||||
|
sf::Mutex allWindowsMutex;
|
||||||
unsigned long eventMask = XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_BUTTON_PRESS |
|
unsigned long eventMask = XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_BUTTON_PRESS |
|
||||||
XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_MOTION |
|
XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_MOTION |
|
||||||
XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_KEY_PRESS |
|
XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_KEY_PRESS |
|
||||||
@ -429,6 +432,7 @@ WindowImplX11::~WindowImplX11()
|
|||||||
CloseDisplay(m_display);
|
CloseDisplay(m_display);
|
||||||
|
|
||||||
// Remove this window from the global list of windows (required for focus request)
|
// Remove this window from the global list of windows (required for focus request)
|
||||||
|
Lock lock(allWindowsMutex);
|
||||||
allWindows.erase(std::find(allWindows.begin(), allWindows.end(), this));
|
allWindows.erase(std::find(allWindows.begin(), allWindows.end(), this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,7 +457,17 @@ void WindowImplX11::processEvents()
|
|||||||
xcb_key_release_event_t* lastKeyReleaseEvent = NULL;
|
xcb_key_release_event_t* lastKeyReleaseEvent = NULL;
|
||||||
uint8_t eventType = 0;
|
uint8_t eventType = 0;
|
||||||
|
|
||||||
while((event = xcb_poll_for_event(m_connection)))
|
if (!m_xcbEvents.empty())
|
||||||
|
{
|
||||||
|
event = m_xcbEvents.front();
|
||||||
|
m_xcbEvents.pop_front();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
event = xcb_poll_for_event(m_connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (event)
|
||||||
{
|
{
|
||||||
eventType = event->response_type & ~0x80;
|
eventType = event->response_type & ~0x80;
|
||||||
|
|
||||||
@ -474,29 +488,45 @@ void WindowImplX11::processEvents()
|
|||||||
// If there's still a key release event held back, process it now.
|
// If there's still a key release event held back, process it now.
|
||||||
if (lastKeyReleaseEvent)
|
if (lastKeyReleaseEvent)
|
||||||
{
|
{
|
||||||
processEvent(reinterpret_cast<xcb_generic_event_t*>(lastKeyReleaseEvent));
|
if (processEvent(reinterpret_cast<xcb_generic_event_t*>(lastKeyReleaseEvent)))
|
||||||
free(lastKeyReleaseEvent);
|
free(lastKeyReleaseEvent);
|
||||||
|
|
||||||
lastKeyReleaseEvent = NULL;
|
lastKeyReleaseEvent = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventType == XCB_KEY_RELEASE)
|
if (eventType == XCB_KEY_RELEASE)
|
||||||
|
{
|
||||||
|
// Check if we're in charge of the key release
|
||||||
|
if (!passEvent(event, reinterpret_cast<xcb_key_release_event_t*>(event)->event))
|
||||||
{
|
{
|
||||||
// Remember this key release event.
|
// Remember this key release event.
|
||||||
lastKeyReleaseEvent = reinterpret_cast<xcb_key_release_event_t*>(event);
|
lastKeyReleaseEvent = reinterpret_cast<xcb_key_release_event_t*>(event);
|
||||||
event = NULL; // For safety reasons.
|
event = NULL; // For safety reasons.
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
processEvent(event);
|
if (processEvent(event))
|
||||||
free(event);
|
free(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_xcbEvents.empty())
|
||||||
|
{
|
||||||
|
event = m_xcbEvents.front();
|
||||||
|
m_xcbEvents.pop_front();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
event = xcb_poll_for_event(m_connection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process any held back release event.
|
// Process any held back release event.
|
||||||
if (lastKeyReleaseEvent)
|
if (lastKeyReleaseEvent)
|
||||||
{
|
{
|
||||||
processEvent(reinterpret_cast<xcb_generic_event_t*>(lastKeyReleaseEvent));
|
if (processEvent(reinterpret_cast<xcb_generic_event_t*>(lastKeyReleaseEvent)))
|
||||||
free(lastKeyReleaseEvent);
|
free(lastKeyReleaseEvent);
|
||||||
|
|
||||||
lastKeyReleaseEvent = NULL;
|
lastKeyReleaseEvent = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -917,6 +947,9 @@ void WindowImplX11::requestFocus()
|
|||||||
// Check the global list of windows to find out whether an SFML window has the focus
|
// Check the global list of windows to find out whether an SFML window has the focus
|
||||||
// Note: can't handle console and other non-SFML windows belonging to the application.
|
// Note: can't handle console and other non-SFML windows belonging to the application.
|
||||||
bool sfmlWindowFocused = false;
|
bool sfmlWindowFocused = false;
|
||||||
|
|
||||||
|
{
|
||||||
|
Lock lock(allWindowsMutex);
|
||||||
for (std::vector<WindowImplX11*>::iterator itr = allWindows.begin(); itr != allWindows.end(); ++itr)
|
for (std::vector<WindowImplX11*>::iterator itr = allWindows.begin(); itr != allWindows.end(); ++itr)
|
||||||
{
|
{
|
||||||
if ((*itr)->hasFocus())
|
if ((*itr)->hasFocus())
|
||||||
@ -925,6 +958,7 @@ void WindowImplX11::requestFocus()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if window is viewable (not on other desktop, ...)
|
// Check if window is viewable (not on other desktop, ...)
|
||||||
// TODO: Check also if minimized
|
// TODO: Check also if minimized
|
||||||
@ -1492,6 +1526,7 @@ void WindowImplX11::initialize()
|
|||||||
xcb_flush(m_connection);
|
xcb_flush(m_connection);
|
||||||
|
|
||||||
// Add this window to the global list of windows (required for focus request)
|
// Add this window to the global list of windows (required for focus request)
|
||||||
|
Lock lock(allWindowsMutex);
|
||||||
allWindows.push_back(this);
|
allWindows.push_back(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1574,6 +1609,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
// Destroy event
|
// Destroy event
|
||||||
case XCB_DESTROY_NOTIFY:
|
case XCB_DESTROY_NOTIFY:
|
||||||
{
|
{
|
||||||
|
if (passEvent(windowEvent, reinterpret_cast<xcb_destroy_notify_event_t*>(windowEvent)->window))
|
||||||
|
return false;
|
||||||
|
|
||||||
// The window is about to be destroyed: we must cleanup resources
|
// The window is about to be destroyed: we must cleanup resources
|
||||||
cleanup();
|
cleanup();
|
||||||
break;
|
break;
|
||||||
@ -1582,6 +1620,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
// Gain focus event
|
// Gain focus event
|
||||||
case XCB_FOCUS_IN:
|
case XCB_FOCUS_IN:
|
||||||
{
|
{
|
||||||
|
if (passEvent(windowEvent, reinterpret_cast<xcb_focus_in_event_t*>(windowEvent)->event))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Update the input context
|
// Update the input context
|
||||||
if (m_inputContext)
|
if (m_inputContext)
|
||||||
XSetICFocus(m_inputContext);
|
XSetICFocus(m_inputContext);
|
||||||
@ -1632,6 +1673,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
// Lost focus event
|
// Lost focus event
|
||||||
case XCB_FOCUS_OUT:
|
case XCB_FOCUS_OUT:
|
||||||
{
|
{
|
||||||
|
if (passEvent(windowEvent, reinterpret_cast<xcb_focus_out_event_t*>(windowEvent)->event))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Update the input context
|
// Update the input context
|
||||||
if (m_inputContext)
|
if (m_inputContext)
|
||||||
XUnsetICFocus(m_inputContext);
|
XUnsetICFocus(m_inputContext);
|
||||||
@ -1645,6 +1689,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
// Resize event
|
// Resize event
|
||||||
case XCB_CONFIGURE_NOTIFY:
|
case XCB_CONFIGURE_NOTIFY:
|
||||||
{
|
{
|
||||||
|
if (passEvent(windowEvent, reinterpret_cast<xcb_configure_notify_event_t*>(windowEvent)->window))
|
||||||
|
return false;
|
||||||
|
|
||||||
xcb_configure_notify_event_t* e = reinterpret_cast<xcb_configure_notify_event_t*>(windowEvent);
|
xcb_configure_notify_event_t* e = reinterpret_cast<xcb_configure_notify_event_t*>(windowEvent);
|
||||||
Event event;
|
Event event;
|
||||||
event.type = Event::Resized;
|
event.type = Event::Resized;
|
||||||
@ -1657,6 +1704,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
// Close event
|
// Close event
|
||||||
case XCB_CLIENT_MESSAGE:
|
case XCB_CLIENT_MESSAGE:
|
||||||
{
|
{
|
||||||
|
if (passEvent(windowEvent, reinterpret_cast<xcb_client_message_event_t*>(windowEvent)->window))
|
||||||
|
return false;
|
||||||
|
|
||||||
xcb_client_message_event_t* e = reinterpret_cast<xcb_client_message_event_t*>(windowEvent);
|
xcb_client_message_event_t* e = reinterpret_cast<xcb_client_message_event_t*>(windowEvent);
|
||||||
|
|
||||||
// Handle window manager protocol messages we support
|
// Handle window manager protocol messages we support
|
||||||
@ -1695,6 +1745,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
// Key down event
|
// Key down event
|
||||||
case XCB_KEY_PRESS:
|
case XCB_KEY_PRESS:
|
||||||
{
|
{
|
||||||
|
if (passEvent(windowEvent, reinterpret_cast<xcb_key_press_event_t*>(windowEvent)->event))
|
||||||
|
return false;
|
||||||
|
|
||||||
xcb_key_press_event_t* e = reinterpret_cast<xcb_key_press_event_t*>(windowEvent);
|
xcb_key_press_event_t* e = reinterpret_cast<xcb_key_press_event_t*>(windowEvent);
|
||||||
|
|
||||||
// Get the keysym of the key that has been pressed
|
// Get the keysym of the key that has been pressed
|
||||||
@ -1776,6 +1829,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
// Key up event
|
// Key up event
|
||||||
case XCB_KEY_RELEASE:
|
case XCB_KEY_RELEASE:
|
||||||
{
|
{
|
||||||
|
if (passEvent(windowEvent, reinterpret_cast<xcb_key_release_event_t*>(windowEvent)->event))
|
||||||
|
return false;
|
||||||
|
|
||||||
xcb_key_release_event_t* e = reinterpret_cast<xcb_key_release_event_t*>(windowEvent);
|
xcb_key_release_event_t* e = reinterpret_cast<xcb_key_release_event_t*>(windowEvent);
|
||||||
|
|
||||||
// Get the keysym of the key that has been pressed
|
// Get the keysym of the key that has been pressed
|
||||||
@ -1806,6 +1862,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
// Mouse button pressed
|
// Mouse button pressed
|
||||||
case XCB_BUTTON_PRESS:
|
case XCB_BUTTON_PRESS:
|
||||||
{
|
{
|
||||||
|
if (passEvent(windowEvent, reinterpret_cast<xcb_button_press_event_t*>(windowEvent)->event))
|
||||||
|
return false;
|
||||||
|
|
||||||
xcb_button_press_event_t* e = reinterpret_cast<xcb_button_press_event_t*>(windowEvent);
|
xcb_button_press_event_t* e = reinterpret_cast<xcb_button_press_event_t*>(windowEvent);
|
||||||
|
|
||||||
// XXX: Why button 8 and 9?
|
// XXX: Why button 8 and 9?
|
||||||
@ -1837,6 +1896,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
// Mouse button released
|
// Mouse button released
|
||||||
case XCB_BUTTON_RELEASE:
|
case XCB_BUTTON_RELEASE:
|
||||||
{
|
{
|
||||||
|
if (passEvent(windowEvent, reinterpret_cast<xcb_button_release_event_t*>(windowEvent)->event))
|
||||||
|
return false;
|
||||||
|
|
||||||
xcb_button_release_event_t* e = reinterpret_cast<xcb_button_press_event_t*>(windowEvent);
|
xcb_button_release_event_t* e = reinterpret_cast<xcb_button_press_event_t*>(windowEvent);
|
||||||
|
|
||||||
xcb_button_t button = e->detail;
|
xcb_button_t button = e->detail;
|
||||||
@ -1891,6 +1953,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
// Mouse moved
|
// Mouse moved
|
||||||
case XCB_MOTION_NOTIFY:
|
case XCB_MOTION_NOTIFY:
|
||||||
{
|
{
|
||||||
|
if (passEvent(windowEvent, reinterpret_cast<xcb_motion_notify_event_t*>(windowEvent)->event))
|
||||||
|
return false;
|
||||||
|
|
||||||
xcb_motion_notify_event_t* e = reinterpret_cast<xcb_motion_notify_event_t*>(windowEvent);
|
xcb_motion_notify_event_t* e = reinterpret_cast<xcb_motion_notify_event_t*>(windowEvent);
|
||||||
Event event;
|
Event event;
|
||||||
event.type = Event::MouseMoved;
|
event.type = Event::MouseMoved;
|
||||||
@ -1903,6 +1968,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
// Mouse entered
|
// Mouse entered
|
||||||
case XCB_ENTER_NOTIFY:
|
case XCB_ENTER_NOTIFY:
|
||||||
{
|
{
|
||||||
|
if (passEvent(windowEvent, reinterpret_cast<xcb_enter_notify_event_t*>(windowEvent)->event))
|
||||||
|
return false;
|
||||||
|
|
||||||
xcb_enter_notify_event_t* enterNotifyEvent = reinterpret_cast<xcb_enter_notify_event_t*>(windowEvent);
|
xcb_enter_notify_event_t* enterNotifyEvent = reinterpret_cast<xcb_enter_notify_event_t*>(windowEvent);
|
||||||
|
|
||||||
if (enterNotifyEvent->mode == NotifyNormal)
|
if (enterNotifyEvent->mode == NotifyNormal)
|
||||||
@ -1917,6 +1985,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
// Mouse left
|
// Mouse left
|
||||||
case XCB_LEAVE_NOTIFY:
|
case XCB_LEAVE_NOTIFY:
|
||||||
{
|
{
|
||||||
|
if (passEvent(windowEvent, reinterpret_cast<xcb_leave_notify_event_t*>(windowEvent)->event))
|
||||||
|
return false;
|
||||||
|
|
||||||
xcb_leave_notify_event_t* leaveNotifyEvent = reinterpret_cast<xcb_leave_notify_event_t*>(windowEvent);
|
xcb_leave_notify_event_t* leaveNotifyEvent = reinterpret_cast<xcb_leave_notify_event_t*>(windowEvent);
|
||||||
|
|
||||||
if (leaveNotifyEvent->mode == NotifyNormal)
|
if (leaveNotifyEvent->mode == NotifyNormal)
|
||||||
@ -1931,6 +2002,9 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
// Parent window changed
|
// Parent window changed
|
||||||
case XCB_REPARENT_NOTIFY:
|
case XCB_REPARENT_NOTIFY:
|
||||||
{
|
{
|
||||||
|
if (passEvent(windowEvent, reinterpret_cast<xcb_reparent_notify_event_t*>(windowEvent)->window))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Catch reparent events to properly apply fullscreen on
|
// Catch reparent events to properly apply fullscreen on
|
||||||
// some "strange" window managers (like Awesome) which
|
// some "strange" window managers (like Awesome) which
|
||||||
// seem to make use of temporary parents during mapping
|
// seem to make use of temporary parents during mapping
|
||||||
@ -1946,6 +2020,33 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool WindowImplX11::passEvent(xcb_generic_event_t* windowEvent, xcb_window_t window)
|
||||||
|
{
|
||||||
|
// Check if this is our event
|
||||||
|
if (window == m_window)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Lock lock(allWindowsMutex);
|
||||||
|
|
||||||
|
// If we are the only window, there is nobody else to pass to
|
||||||
|
if (allWindows.size() == 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (std::vector<sf::priv::WindowImplX11*>::iterator i = allWindows.begin(); i != allWindows.end(); ++i)
|
||||||
|
{
|
||||||
|
if ((*i)->m_window == window)
|
||||||
|
{
|
||||||
|
(*i)->m_xcbEvents.push_back(windowEvent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// It seems nobody wants the event, we'll just handle it ourselves
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Keyboard::Key WindowImplX11::keysymToSF(xcb_keysym_t symbol)
|
Keyboard::Key WindowImplX11::keysymToSF(xcb_keysym_t symbol)
|
||||||
{
|
{
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
#include <SFML/System/String.hpp>
|
#include <SFML/System/String.hpp>
|
||||||
#include <X11/Xlib-xcb.h>
|
#include <X11/Xlib-xcb.h>
|
||||||
#include <xcb/xcb_ewmh.h>
|
#include <xcb/xcb_ewmh.h>
|
||||||
#include <set>
|
#include <deque>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
@ -246,6 +246,17 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool processEvent(xcb_generic_event_t* windowEvent);
|
bool processEvent(xcb_generic_event_t* windowEvent);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Pass an incoming event to another window
|
||||||
|
///
|
||||||
|
/// \param windowEvent Event which is being processed
|
||||||
|
/// \param window Window to pass to
|
||||||
|
///
|
||||||
|
/// \return True if the event was passed to another window, false if it is destined for the current window
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
bool passEvent(xcb_generic_event_t* windowEvent, xcb_window_t window);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Convert a X11 keysym to SFML key code
|
/// \brief Convert a X11 keysym to SFML key code
|
||||||
///
|
///
|
||||||
@ -259,13 +270,14 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
::Window m_window; ///< X11 structure defining our window
|
xcb_window_t m_window; ///< xcb identifier defining our window
|
||||||
::Display* m_display; ///< Pointer to the display
|
::Display* m_display; ///< Pointer to the display
|
||||||
xcb_connection_t* m_connection; ///< Pointer to the xcb connection
|
xcb_connection_t* m_connection; ///< Pointer to the xcb connection
|
||||||
xcb_ewmh_connection_t m_ewmhConnection; ///< xcb EWMH connection
|
xcb_ewmh_connection_t m_ewmhConnection; ///< xcb EWMH connection
|
||||||
xcb_screen_t* m_screen; ///< Screen identifier
|
xcb_screen_t* m_screen; ///< Screen identifier
|
||||||
XIM m_inputMethod; ///< Input method linked to the X display
|
XIM m_inputMethod; ///< Input method linked to the X display
|
||||||
XIC m_inputContext; ///< Input context used to get unicode input in our window
|
XIC m_inputContext; ///< Input context used to get unicode input in our window
|
||||||
|
std::deque<xcb_generic_event_t*> m_xcbEvents; ///< Events that were received in another window's loop
|
||||||
bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
|
bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
|
||||||
Atom m_atomWmProtocols; ///< Atom used to identify WM protocol messages
|
Atom m_atomWmProtocols; ///< Atom used to identify WM protocol messages
|
||||||
Atom m_atomClose; ///< Atom used to identify the close event
|
Atom m_atomClose; ///< Atom used to identify the close event
|
||||||
|
Loading…
Reference in New Issue
Block a user