mirror of
https://github.com/SFML/SFML.git
synced 2024-11-28 22:31:09 +08:00
Refactored Unix Window implementation.
This commit is contained in:
parent
b758f9a1dd
commit
b2b35d0a43
@ -217,11 +217,10 @@ endif()
|
|||||||
# build the list of external libraries to link
|
# build the list of external libraries to link
|
||||||
if(SFML_OS_WINDOWS)
|
if(SFML_OS_WINDOWS)
|
||||||
list(APPEND WINDOW_EXT_LIBS winmm gdi32)
|
list(APPEND WINDOW_EXT_LIBS winmm gdi32)
|
||||||
elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD)
|
elseif(SFML_OS_LINUX)
|
||||||
list(APPEND WINDOW_EXT_LIBS ${LIBXCB_LIBRARIES} ${UDEV_LIBRARIES})
|
list(APPEND WINDOW_EXT_LIBS ${LIBXCB_LIBRARIES} ${UDEV_LIBRARIES})
|
||||||
if(SFML_OS_FREEBSD)
|
elseif(SFML_OS_FREEBSD)
|
||||||
list(APPEND WINDOW_EXT_LIBS usbhid)
|
list(APPEND WINDOW_EXT_LIBS ${LIBXCB_LIBRARIES} usbhid)
|
||||||
endif()
|
|
||||||
elseif(SFML_OS_MACOSX)
|
elseif(SFML_OS_MACOSX)
|
||||||
list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework AppKit -framework IOKit -framework Carbon")
|
list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework AppKit -framework IOKit -framework Carbon")
|
||||||
elseif(SFML_OS_IOS)
|
elseif(SFML_OS_IOS)
|
||||||
|
@ -101,6 +101,23 @@ xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
xcb_screen_t* XCBDefaultScreen(xcb_connection_t* connection)
|
||||||
|
{
|
||||||
|
assert(connection == XGetXCBConnection(sharedDisplay));
|
||||||
|
return XCBScreenOfDisplay(connection, XDefaultScreen(sharedDisplay));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
xcb_window_t XCBDefaultRootWindow(xcb_connection_t* connection)
|
||||||
|
{
|
||||||
|
assert(connection == XGetXCBConnection(sharedDisplay));
|
||||||
|
xcb_screen_t* screen = XCBScreenOfDisplay(connection, XDefaultScreen(sharedDisplay));
|
||||||
|
if (screen)
|
||||||
|
return screen->root;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -60,7 +60,7 @@ xcb_connection_t* OpenConnection();
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Release a reference to the shared display
|
/// \brief Release a reference to the shared display
|
||||||
///
|
///
|
||||||
/// \param Display to release
|
/// \param display Display to release
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void CloseDisplay(Display* display);
|
void CloseDisplay(Display* display);
|
||||||
@ -68,7 +68,7 @@ void CloseDisplay(Display* display);
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Release a reference to the shared display
|
/// \brief Release a reference to the shared display
|
||||||
///
|
///
|
||||||
/// \param Connection of display to release
|
/// \param connection Connection of display to release
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void CloseConnection(xcb_connection_t* connection);
|
void CloseConnection(xcb_connection_t* connection);
|
||||||
@ -76,13 +76,34 @@ void CloseConnection(xcb_connection_t* connection);
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Get screen of a display by index (equivalent to XScreenOfDisplay)
|
/// \brief Get screen of a display by index (equivalent to XScreenOfDisplay)
|
||||||
///
|
///
|
||||||
/// \param The index of the screen
|
/// \param connection Connection of display
|
||||||
|
/// \param screen_nbr The index of the screen
|
||||||
///
|
///
|
||||||
/// \return Pointer to the screen
|
/// \return Pointer to the screen
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr);
|
xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get default screen of a display (equivalent to XDefaultScreen)
|
||||||
|
///
|
||||||
|
/// \param connection Connection of display
|
||||||
|
///
|
||||||
|
/// \return Pointer to the default screen of the display
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
xcb_screen_t* XCBDefaultScreen(xcb_connection_t* connection);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get default root window of a display (equivalent to XDefaultRootWindow)
|
||||||
|
///
|
||||||
|
/// \param connection Connection of display
|
||||||
|
///
|
||||||
|
/// \return Root window of the display
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
xcb_window_t XCBDefaultRootWindow(xcb_connection_t* connection);
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -189,16 +189,15 @@ void InputImpl::setVirtualKeyboardVisible(bool /*visible*/)
|
|||||||
bool InputImpl::isMouseButtonPressed(Mouse::Button button)
|
bool InputImpl::isMouseButtonPressed(Mouse::Button button)
|
||||||
{
|
{
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
Display* display = OpenDisplay();
|
xcb_connection_t* connection = OpenConnection();
|
||||||
xcb_connection_t* connection = XGetXCBConnection(display);
|
|
||||||
|
|
||||||
// Get pointer mask
|
// Get pointer mask
|
||||||
xcb_query_pointer_reply_t* pointer = xcb_query_pointer_reply(connection, xcb_query_pointer(connection, XDefaultRootWindow(display)), NULL);
|
xcb_query_pointer_reply_t* pointer = xcb_query_pointer_reply(connection, xcb_query_pointer(connection, XCBDefaultRootWindow(connection)), NULL);
|
||||||
uint16_t mask = pointer->mask;
|
uint16_t mask = pointer->mask;
|
||||||
free(pointer);
|
free(pointer);
|
||||||
|
|
||||||
// Close the connection with the X server
|
// Close the connection with the X server
|
||||||
CloseDisplay(display);
|
CloseConnection(connection);
|
||||||
|
|
||||||
switch (button)
|
switch (button)
|
||||||
{
|
{
|
||||||
@ -216,13 +215,12 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button)
|
|||||||
Vector2i InputImpl::getMousePosition()
|
Vector2i InputImpl::getMousePosition()
|
||||||
{
|
{
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
Display* display = OpenDisplay();
|
xcb_connection_t* connection = OpenConnection();
|
||||||
xcb_connection_t* connection = XGetXCBConnection(display);
|
|
||||||
|
|
||||||
xcb_query_pointer_reply_t* pointer = xcb_query_pointer_reply(connection, xcb_query_pointer(connection, XDefaultRootWindow(display)), NULL);
|
xcb_query_pointer_reply_t* pointer = xcb_query_pointer_reply(connection, xcb_query_pointer(connection, XCBDefaultRootWindow(connection)), NULL);
|
||||||
|
|
||||||
// Close the connection with the X server
|
// Close the connection with the X server
|
||||||
CloseDisplay(display);
|
CloseConnection(connection);
|
||||||
|
|
||||||
// Prepare result.
|
// Prepare result.
|
||||||
Vector2i result(pointer->root_x, pointer->root_y);
|
Vector2i result(pointer->root_x, pointer->root_y);
|
||||||
@ -263,14 +261,13 @@ Vector2i InputImpl::getMousePosition(const Window& relativeTo)
|
|||||||
void InputImpl::setMousePosition(const Vector2i& position)
|
void InputImpl::setMousePosition(const Vector2i& position)
|
||||||
{
|
{
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
Display* display = OpenDisplay();
|
xcb_connection_t* connection = OpenConnection();
|
||||||
xcb_connection_t* connection = XGetXCBConnection(display);
|
|
||||||
|
|
||||||
xcb_warp_pointer(connection, None, XDefaultRootWindow(display), 0, 0, 0, 0, position.x, position.y);
|
xcb_warp_pointer(connection, None, XCBDefaultRootWindow(connection), 0, 0, 0, 0, position.x, position.y);
|
||||||
xcb_flush(connection);
|
xcb_flush(connection);
|
||||||
|
|
||||||
// Close the connection with the X server
|
// Close the connection with the X server
|
||||||
CloseDisplay(display);
|
CloseConnection(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,72 +42,80 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
|
|||||||
std::vector<VideoMode> modes;
|
std::vector<VideoMode> modes;
|
||||||
|
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
Display* display = OpenDisplay();
|
xcb_connection_t* connection = OpenConnection();
|
||||||
xcb_connection_t* connection = XGetXCBConnection(display);
|
|
||||||
|
|
||||||
if (display)
|
// Retrieve the default screen
|
||||||
|
xcb_screen_t* screen = XCBDefaultScreen(connection);
|
||||||
|
|
||||||
|
// Check if the XRandR extension is present
|
||||||
|
static const std::string RANDR = "RANDR";
|
||||||
|
xcb_query_extension_reply_t* randr_ext = xcb_query_extension_reply(
|
||||||
|
connection,
|
||||||
|
xcb_query_extension(
|
||||||
|
connection,
|
||||||
|
RANDR.size(),
|
||||||
|
RANDR.c_str()
|
||||||
|
),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (randr_ext->present)
|
||||||
{
|
{
|
||||||
// Check if the XRandR extension is present
|
// Get the current configuration
|
||||||
xcb_query_extension_cookie_t cookie = xcb_query_extension(connection, 5, "RANDR");
|
xcb_generic_error_t* error;
|
||||||
|
xcb_randr_get_screen_info_reply_t* config = xcb_randr_get_screen_info_reply(
|
||||||
|
connection,
|
||||||
|
xcb_randr_get_screen_info(
|
||||||
|
connection,
|
||||||
|
screen->root
|
||||||
|
),
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
|
||||||
// Retrieve the default screen
|
if (!error)
|
||||||
xcb_screen_t* screen = XCBScreenOfDisplay(connection, DefaultScreen(display));
|
|
||||||
|
|
||||||
// Check if the XRandR extension is present
|
|
||||||
xcb_query_extension_reply_t* randr_ext = xcb_query_extension_reply(connection, cookie, NULL);
|
|
||||||
if (randr_ext->present)
|
|
||||||
{
|
{
|
||||||
// Get the current configuration
|
// Get the available screen sizes
|
||||||
xcb_generic_error_t* errors;
|
xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config);
|
||||||
xcb_randr_get_screen_info_reply_t* config = xcb_randr_get_screen_info_reply(
|
if (sizes && (config->nSizes > 0))
|
||||||
connection, xcb_randr_get_screen_info(connection, screen->root), &errors);
|
|
||||||
if (! errors)
|
|
||||||
{
|
{
|
||||||
// Get the available screen sizes
|
// Get the list of supported depths
|
||||||
xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config);
|
xcb_depth_iterator_t iter = xcb_screen_allowed_depths_iterator(screen);
|
||||||
if (sizes && (config->nSizes > 0))
|
// Combine depths and sizes to fill the array of supported modes
|
||||||
|
for (; iter.rem; xcb_depth_next(&iter))
|
||||||
{
|
{
|
||||||
// Get the list of supported depths
|
for (int j = 0; j < config->nSizes; ++j)
|
||||||
xcb_depth_iterator_t iter = xcb_screen_allowed_depths_iterator(screen);
|
|
||||||
// Combine depths and sizes to fill the array of supported modes
|
|
||||||
for (; iter.rem; xcb_depth_next(&iter))
|
|
||||||
{
|
{
|
||||||
for (int j = 0; j < config->nSizes; ++j)
|
// Convert to VideoMode
|
||||||
{
|
VideoMode mode(sizes[j].width, sizes[j].height, iter.data->depth);
|
||||||
// Convert to VideoMode
|
|
||||||
VideoMode mode(sizes[j].width, sizes[j].height, iter.data->depth);
|
|
||||||
|
|
||||||
// Add it only if it is not already in the array
|
// Add it only if it is not already in the array
|
||||||
if (std::find(modes.begin(), modes.end(), mode) == modes.end())
|
if (std::find(modes.begin(), modes.end(), mode) == modes.end())
|
||||||
modes.push_back(mode);
|
modes.push_back(mode);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// Failed to get the screen configuration
|
|
||||||
err() << "Failed to retrieve the screen configuration while trying to get the supported video modes" << std::endl;
|
|
||||||
}
|
|
||||||
// Free the configuration instance
|
|
||||||
free(errors);
|
|
||||||
free(config);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// XRandr extension is not supported: we cannot get the video modes
|
// Failed to get the screen configuration
|
||||||
err() << "Failed to use the XRandR extension while trying to get the supported video modes" << std::endl;
|
err() << "Failed to retrieve the screen configuration while trying to get the supported video modes" << std::endl;
|
||||||
}
|
}
|
||||||
free(randr_ext);
|
|
||||||
// Close the connection with the X server
|
// Free the configuration instance
|
||||||
CloseDisplay(display);
|
free(error);
|
||||||
|
free(config);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We couldn't connect to the X server
|
// XRandr extension is not supported: we cannot get the video modes
|
||||||
err() << "Failed to connect to the X server while trying to get the supported video modes" << std::endl;
|
err() << "Failed to use the XRandR extension while trying to get the supported video modes" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(randr_ext);
|
||||||
|
|
||||||
|
// Close the connection with the X server
|
||||||
|
CloseConnection(connection);
|
||||||
|
|
||||||
return modes;
|
return modes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,59 +126,68 @@ VideoMode VideoModeImpl::getDesktopMode()
|
|||||||
VideoMode desktopMode;
|
VideoMode desktopMode;
|
||||||
|
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
Display* display = OpenDisplay();
|
xcb_connection_t* connection = OpenConnection();
|
||||||
xcb_connection_t* connection = XGetXCBConnection(display);
|
|
||||||
if (display)
|
// Retrieve the default screen
|
||||||
|
xcb_screen_t* screen = XCBDefaultScreen(connection);
|
||||||
|
|
||||||
|
// Check if the XRandR extension is present
|
||||||
|
static const std::string RANDR = "RANDR";
|
||||||
|
xcb_query_extension_reply_t* randr_ext = xcb_query_extension_reply(
|
||||||
|
connection,
|
||||||
|
xcb_query_extension(
|
||||||
|
connection,
|
||||||
|
RANDR.size(),
|
||||||
|
RANDR.c_str()
|
||||||
|
),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (randr_ext->present)
|
||||||
{
|
{
|
||||||
xcb_query_extension_cookie_t cookie = xcb_query_extension(connection, 5, "RANDR");
|
// Get the current configuration
|
||||||
// Retrieve the default screen
|
xcb_generic_error_t* error;
|
||||||
xcb_screen_t* screen = XCBScreenOfDisplay(connection, DefaultScreen(display));
|
xcb_randr_get_screen_info_reply_t* config = xcb_randr_get_screen_info_reply(
|
||||||
|
connection,
|
||||||
|
xcb_randr_get_screen_info(
|
||||||
|
connection,
|
||||||
|
screen->root
|
||||||
|
),
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
|
||||||
// Check if the XRandR extension is present
|
if (!error)
|
||||||
xcb_query_extension_reply_t* randr_ext = xcb_query_extension_reply(connection, cookie, NULL);
|
|
||||||
if (randr_ext->present)
|
|
||||||
{
|
{
|
||||||
// Get the current configuration
|
// Get the current video mode
|
||||||
xcb_generic_error_t* errors;
|
xcb_randr_mode_t currentMode = config->sizeID;
|
||||||
xcb_randr_get_screen_info_reply_t* config =
|
|
||||||
xcb_randr_get_screen_info_reply(
|
|
||||||
connection, xcb_randr_get_screen_info(connection, screen->root), &errors);
|
|
||||||
if (! errors)
|
|
||||||
{
|
|
||||||
// Get the current video mode
|
|
||||||
xcb_randr_mode_t currentMode = config->sizeID;
|
|
||||||
|
|
||||||
// Get the available screen sizes
|
// Get the available screen sizes
|
||||||
int nbSizes = xcb_randr_get_screen_info_sizes_length(config);
|
int nbSizes = xcb_randr_get_screen_info_sizes_length(config);
|
||||||
xcb_randr_screen_size_t* sizes= xcb_randr_get_screen_info_sizes(config);
|
xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config);
|
||||||
if (sizes && (nbSizes > 0))
|
if (sizes && (nbSizes > 0))
|
||||||
desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, screen->root_depth);
|
desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, screen->root_depth);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Failed to get the screen configuration
|
|
||||||
err() << "Failed to retrieve the screen configuration while trying to get the desktop video modes" << std::endl;
|
|
||||||
}
|
|
||||||
// Free the configuration instance
|
|
||||||
free(errors);
|
|
||||||
free(config);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// XRandr extension is not supported: we cannot get the video modes
|
// Failed to get the screen configuration
|
||||||
err() << "Failed to use the XRandR extension while trying to get the desktop video modes" << std::endl;
|
err() << "Failed to retrieve the screen configuration while trying to get the desktop video modes" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(randr_ext);
|
// Free the configuration instance
|
||||||
// Close the connection with the X server
|
free(error);
|
||||||
CloseDisplay(display);
|
free(config);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We couldn't connect to the X server
|
// XRandr extension is not supported: we cannot get the video modes
|
||||||
err() << "Failed to connect to the X server while trying to get the desktop video modes" << std::endl;
|
err() << "Failed to use the XRandR extension while trying to get the desktop video modes" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(randr_ext);
|
||||||
|
|
||||||
|
// Close the connection with the X server
|
||||||
|
CloseConnection(connection);
|
||||||
|
|
||||||
return desktopMode;
|
return desktopMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
#include <xcb/xcb_image.h>
|
#include <xcb/xcb_image.h>
|
||||||
#include <xcb/xcb_util.h>
|
#include <xcb/xcb_util.h>
|
||||||
#include <xcb/randr.h>
|
#include <xcb/randr.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -65,18 +67,22 @@ namespace
|
|||||||
EnterWindowMask | LeaveWindowMask;
|
EnterWindowMask | LeaveWindowMask;
|
||||||
|
|
||||||
// Find the name of the current executable
|
// Find the name of the current executable
|
||||||
void findExecutableName(char* buffer, std::size_t bufferSize)
|
std::string findExecutableName()
|
||||||
{
|
{
|
||||||
//Default fallback name
|
struct stat linkStat;
|
||||||
const char* executableName = "sfml";
|
if (!lstat("/proc/self/exe", &linkStat)) {
|
||||||
std::size_t length = readlink("/proc/self/exe", buffer, bufferSize);
|
std::vector<char> buffer(0, linkStat.st_size + 1);
|
||||||
if ((length > 0) && (length < bufferSize))
|
std::size_t length = readlink("/proc/self/exe", &buffer[0], buffer.size());
|
||||||
{
|
if ((length > 0) && (length < buffer.size()))
|
||||||
// Remove the path to keep the executable name only
|
{
|
||||||
buffer[length] = '\0';
|
// Remove the path to keep the executable name only
|
||||||
executableName = basename(buffer);
|
buffer[length] = '\0';
|
||||||
|
return basename(&buffer[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
std::memmove(buffer, executableName, std::strlen(executableName) + 1);
|
|
||||||
|
//Default fallback name
|
||||||
|
return "sfml";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +106,6 @@ m_useSizeHints(false)
|
|||||||
{
|
{
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
m_display = OpenDisplay();
|
m_display = OpenDisplay();
|
||||||
XSetEventQueueOwner(m_display, XCBOwnsEventQueue);
|
|
||||||
m_connection = XGetXCBConnection(m_display);
|
m_connection = XGetXCBConnection(m_display);
|
||||||
|
|
||||||
if (!m_connection)
|
if (!m_connection)
|
||||||
@ -109,10 +114,8 @@ m_useSizeHints(false)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get connection info.
|
m_screen = XCBDefaultScreen(m_connection);
|
||||||
const xcb_setup_t* setup = xcb_get_setup(m_connection);
|
XSetEventQueueOwner(m_display, XCBOwnsEventQueue);
|
||||||
xcb_screen_iterator_t screenIter = xcb_setup_roots_iterator(setup);
|
|
||||||
m_screen = screenIter.data;
|
|
||||||
|
|
||||||
// Save the window handle
|
// Save the window handle
|
||||||
m_window = handle;
|
m_window = handle;
|
||||||
@ -122,10 +125,12 @@ m_useSizeHints(false)
|
|||||||
// Make sure the window is listening to all the required events
|
// Make sure the window is listening to all the required events
|
||||||
const uint32_t value_list[] = {static_cast<uint32_t>(eventMask)};
|
const uint32_t value_list[] = {static_cast<uint32_t>(eventMask)};
|
||||||
|
|
||||||
xcb_change_window_attributes(m_connection,
|
xcb_change_window_attributes(
|
||||||
m_window,
|
m_connection,
|
||||||
XCB_CW_EVENT_MASK,
|
m_window,
|
||||||
value_list);
|
XCB_CW_EVENT_MASK,
|
||||||
|
value_list
|
||||||
|
);
|
||||||
|
|
||||||
// Do some common initializations
|
// Do some common initializations
|
||||||
initialize();
|
initialize();
|
||||||
@ -148,32 +153,21 @@ m_useSizeHints(false)
|
|||||||
{
|
{
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
m_display = OpenDisplay();
|
m_display = OpenDisplay();
|
||||||
XSetEventQueueOwner(m_display, XCBOwnsEventQueue);
|
|
||||||
m_connection = XGetXCBConnection(m_display);
|
m_connection = XGetXCBConnection(m_display);
|
||||||
|
|
||||||
if (!m_connection)
|
if (!m_connection)
|
||||||
{
|
{
|
||||||
err() << "Failed cast Display object to an XCB connection object" << std::endl;
|
err() << "Failed cast Display object to an XCB connection object" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get connection info.
|
m_screen = XCBDefaultScreen(m_connection);
|
||||||
const xcb_setup_t* setup = xcb_get_setup(m_connection);
|
XSetEventQueueOwner(m_display, XCBOwnsEventQueue);
|
||||||
xcb_screen_iterator_t screenIter = xcb_setup_roots_iterator(setup);
|
|
||||||
m_screen = screenIter.data;
|
|
||||||
|
|
||||||
// Compute position and size
|
// Compute position and size
|
||||||
int left, top;
|
|
||||||
bool fullscreen = (style & Style::Fullscreen) != 0;
|
bool fullscreen = (style & Style::Fullscreen) != 0;
|
||||||
if (!fullscreen)
|
int left = fullscreen ? 0 : (m_screen->width_in_pixels - mode.width) / 2;
|
||||||
{
|
int top = fullscreen ? 0 : (m_screen->height_in_pixels - mode.height) / 2;
|
||||||
left = (m_screen->width_in_pixels - mode.width) / 2;
|
|
||||||
top = (m_screen->height_in_pixels - mode.height) / 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
left = 0;
|
|
||||||
top = 0;
|
|
||||||
}
|
|
||||||
int width = mode.width;
|
int width = mode.width;
|
||||||
int height = mode.height;
|
int height = mode.height;
|
||||||
|
|
||||||
@ -187,20 +181,23 @@ m_useSizeHints(false)
|
|||||||
// Create the window
|
// Create the window
|
||||||
m_window = xcb_generate_id(m_connection);
|
m_window = xcb_generate_id(m_connection);
|
||||||
|
|
||||||
xcb_void_cookie_t cookie = xcb_create_window_checked(
|
xcb_generic_error_t* errptr = xcb_request_check(
|
||||||
m_connection,
|
m_connection,
|
||||||
XCB_COPY_FROM_PARENT,
|
xcb_create_window_checked(
|
||||||
m_window,
|
m_connection,
|
||||||
m_screen->root,
|
XCB_COPY_FROM_PARENT,
|
||||||
left, top,
|
m_window,
|
||||||
width, height,
|
m_screen->root,
|
||||||
0,
|
left, top,
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
width, height,
|
||||||
XCB_COPY_FROM_PARENT,
|
0,
|
||||||
XCB_CW_EVENT_MASK | XCB_CW_OVERRIDE_REDIRECT,
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
value_list);
|
XCB_COPY_FROM_PARENT,
|
||||||
|
XCB_CW_EVENT_MASK | XCB_CW_OVERRIDE_REDIRECT,
|
||||||
|
value_list
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
xcb_generic_error_t* errptr = xcb_request_check(m_connection, cookie);
|
|
||||||
bool createWindowFailed = (errptr != NULL);
|
bool createWindowFailed = (errptr != NULL);
|
||||||
free(errptr);
|
free(errptr);
|
||||||
|
|
||||||
@ -213,19 +210,18 @@ m_useSizeHints(false)
|
|||||||
// Set the window's name
|
// Set the window's name
|
||||||
setTitle(title);
|
setTitle(title);
|
||||||
|
|
||||||
// Set the window's style (tell the windows manager to change our window's decorations and functions according to the requested style)
|
// Set the window's style (tell the window manager to change our window's decorations and functions according to the requested style)
|
||||||
if (!fullscreen)
|
if (!fullscreen)
|
||||||
{
|
{
|
||||||
static const std::string MOTIF_WM_HINTS = "_MOTIF_WM_HINTS";
|
static const std::string MOTIF_WM_HINTS = "_MOTIF_WM_HINTS";
|
||||||
xcb_intern_atom_cookie_t hintsAtomRequest = xcb_intern_atom(
|
|
||||||
m_connection,
|
|
||||||
0,
|
|
||||||
MOTIF_WM_HINTS.size(),
|
|
||||||
MOTIF_WM_HINTS.c_str()
|
|
||||||
);
|
|
||||||
xcb_intern_atom_reply_t* hintsAtomReply = xcb_intern_atom_reply(
|
xcb_intern_atom_reply_t* hintsAtomReply = xcb_intern_atom_reply(
|
||||||
m_connection,
|
m_connection,
|
||||||
hintsAtomRequest,
|
xcb_intern_atom(
|
||||||
|
m_connection,
|
||||||
|
0,
|
||||||
|
MOTIF_WM_HINTS.size(),
|
||||||
|
MOTIF_WM_HINTS.c_str()
|
||||||
|
),
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -279,9 +275,16 @@ m_useSizeHints(false)
|
|||||||
hints.functions |= MWM_FUNC_CLOSE;
|
hints.functions |= MWM_FUNC_CLOSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned char* ptr = reinterpret_cast<const unsigned char*>(&hints);
|
xcb_change_property(
|
||||||
xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, m_window,
|
m_connection,
|
||||||
hintsAtomReply->atom, XCB_ATOM_WM_HINTS, 32, 5, ptr);
|
XCB_PROP_MODE_REPLACE,
|
||||||
|
m_window,
|
||||||
|
hintsAtomReply->atom,
|
||||||
|
XCB_ATOM_WM_HINTS,
|
||||||
|
sizeof(hints.flags) * 8,
|
||||||
|
sizeof(hints) / sizeof(hints.flags),
|
||||||
|
reinterpret_cast<const unsigned char*>(&hints)
|
||||||
|
);
|
||||||
|
|
||||||
free(hintsAtomReply);
|
free(hintsAtomReply);
|
||||||
}
|
}
|
||||||
@ -299,9 +302,8 @@ m_useSizeHints(false)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set the window's WM class (this can be used by window managers)
|
// Set the window's WM class (this can be used by window managers)
|
||||||
char windowClass[512];
|
std::string windowClass = findExecutableName();
|
||||||
findExecutableName(windowClass, sizeof(windowClass));
|
xcb_icccm_set_wm_class_checked(m_connection, m_window, windowClass.size(), windowClass.c_str());
|
||||||
xcb_icccm_set_wm_class_checked(m_connection, m_window, std::strlen(windowClass), windowClass);
|
|
||||||
|
|
||||||
// Do some common initializations
|
// Do some common initializations
|
||||||
initialize();
|
initialize();
|
||||||
@ -309,8 +311,26 @@ m_useSizeHints(false)
|
|||||||
// In fullscreen mode, we must grab keyboard and mouse inputs
|
// In fullscreen mode, we must grab keyboard and mouse inputs
|
||||||
if (fullscreen)
|
if (fullscreen)
|
||||||
{
|
{
|
||||||
xcb_grab_pointer(m_connection, True, m_window, 0, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, m_window, XCB_NONE, XCB_CURRENT_TIME);
|
xcb_grab_pointer(
|
||||||
xcb_grab_keyboard(m_connection, True, m_window, XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
|
m_connection,
|
||||||
|
True,
|
||||||
|
m_window,
|
||||||
|
0,
|
||||||
|
XCB_GRAB_MODE_ASYNC,
|
||||||
|
XCB_GRAB_MODE_ASYNC,
|
||||||
|
m_window,
|
||||||
|
XCB_NONE,
|
||||||
|
XCB_CURRENT_TIME
|
||||||
|
);
|
||||||
|
|
||||||
|
xcb_grab_keyboard(
|
||||||
|
m_connection,
|
||||||
|
True,
|
||||||
|
m_window,
|
||||||
|
XCB_CURRENT_TIME,
|
||||||
|
XCB_GRAB_MODE_ASYNC,
|
||||||
|
XCB_GRAB_MODE_ASYNC
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,7 +442,6 @@ Vector2i WindowImplX11::getPosition() const
|
|||||||
{
|
{
|
||||||
::Window topLevelWindow = m_window;
|
::Window topLevelWindow = m_window;
|
||||||
::Window nextWindow = topLevelWindow;
|
::Window nextWindow = topLevelWindow;
|
||||||
xcb_query_tree_cookie_t treeCookie;
|
|
||||||
xcb_query_tree_reply_t* treeReply = NULL;
|
xcb_query_tree_reply_t* treeReply = NULL;
|
||||||
|
|
||||||
// Get "top level" window, i.e. the window with the root window as its parent.
|
// Get "top level" window, i.e. the window with the root window as its parent.
|
||||||
@ -430,14 +449,19 @@ Vector2i WindowImplX11::getPosition() const
|
|||||||
{
|
{
|
||||||
topLevelWindow = nextWindow;
|
topLevelWindow = nextWindow;
|
||||||
|
|
||||||
treeCookie = xcb_query_tree(m_connection, topLevelWindow);
|
treeReply = xcb_query_tree_reply(m_connection, xcb_query_tree(m_connection, topLevelWindow), NULL);
|
||||||
treeReply = xcb_query_tree_reply(m_connection, treeCookie, NULL);
|
|
||||||
nextWindow = treeReply->parent;
|
nextWindow = treeReply->parent;
|
||||||
free(treeReply);
|
free(treeReply);
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_get_geometry_cookie_t geometryCookie = xcb_get_geometry(m_connection, topLevelWindow);
|
xcb_get_geometry_reply_t* geometryReply = xcb_get_geometry_reply(
|
||||||
xcb_get_geometry_reply_t* geometryReply = xcb_get_geometry_reply(m_connection, geometryCookie, NULL);
|
m_connection,
|
||||||
|
xcb_get_geometry(
|
||||||
|
m_connection,
|
||||||
|
topLevelWindow
|
||||||
|
),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
sf::Vector2i result(geometryReply->x, geometryReply->y);
|
sf::Vector2i result(geometryReply->x, geometryReply->y);
|
||||||
free(geometryReply);
|
free(geometryReply);
|
||||||
|
|
||||||
@ -480,9 +504,12 @@ void WindowImplX11::setSize(const Vector2u& size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t values[] = {size.x, size.y};
|
uint32_t values[] = {size.x, size.y};
|
||||||
xcb_configure_window(m_connection, m_window,
|
xcb_configure_window(
|
||||||
XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
|
m_connection,
|
||||||
values);
|
m_window,
|
||||||
|
XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
|
||||||
|
values
|
||||||
|
);
|
||||||
xcb_flush(m_connection);
|
xcb_flush(m_connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -497,9 +524,16 @@ void WindowImplX11::setTitle(const String& title)
|
|||||||
std::back_inserter( utf8String )
|
std::back_inserter( utf8String )
|
||||||
);
|
);
|
||||||
|
|
||||||
xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, m_window,
|
xcb_change_property(
|
||||||
XCB_ATOM_WM_NAME, XCB_ATOM_STRING,
|
m_connection,
|
||||||
8, utf8String.length(), utf8String.c_str());
|
XCB_PROP_MODE_REPLACE,
|
||||||
|
m_window,
|
||||||
|
XCB_ATOM_WM_NAME,
|
||||||
|
XCB_ATOM_STRING,
|
||||||
|
sizeof(std::basic_string<sf::Uint8>::value_type) * 8,
|
||||||
|
utf8String.length(),
|
||||||
|
utf8String.c_str()
|
||||||
|
);
|
||||||
xcb_flush(m_connection);
|
xcb_flush(m_connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,17 +553,38 @@ void WindowImplX11::setIcon(unsigned int width, unsigned int height, const Uint8
|
|||||||
|
|
||||||
// Create the icon pixmap
|
// Create the icon pixmap
|
||||||
xcb_pixmap_t iconPixmap = xcb_generate_id(m_connection);
|
xcb_pixmap_t iconPixmap = xcb_generate_id(m_connection);
|
||||||
xcb_create_pixmap(m_connection, m_screen->root_depth, iconPixmap, m_screen->root,
|
xcb_create_pixmap(
|
||||||
width, height);
|
m_connection,
|
||||||
|
m_screen->root_depth,
|
||||||
|
iconPixmap,
|
||||||
|
m_screen->root,
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
);
|
||||||
|
|
||||||
xcb_gcontext_t iconGC = xcb_generate_id(m_connection);
|
xcb_gcontext_t iconGC = xcb_generate_id(m_connection);
|
||||||
xcb_create_gc(m_connection, iconGC, iconPixmap, 0, NULL);
|
xcb_create_gc(m_connection, iconGC, iconPixmap, 0, NULL);
|
||||||
xcb_void_cookie_t cookie = xcb_put_image_checked(
|
|
||||||
m_connection, XCB_IMAGE_FORMAT_Z_PIXMAP, iconPixmap, iconGC,
|
xcb_generic_error_t* errptr = xcb_request_check(
|
||||||
width, height, 0, 0, 0, m_screen->root_depth, sizeof(iconPixels), iconPixels);
|
m_connection,
|
||||||
|
xcb_put_image_checked(
|
||||||
|
m_connection,
|
||||||
|
XCB_IMAGE_FORMAT_Z_PIXMAP,
|
||||||
|
iconPixmap,
|
||||||
|
iconGC,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
m_screen->root_depth,
|
||||||
|
sizeof(iconPixels),
|
||||||
|
iconPixels
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
xcb_free_gc(m_connection, iconGC);
|
xcb_free_gc(m_connection, iconGC);
|
||||||
|
|
||||||
xcb_generic_error_t* errptr = xcb_request_check(m_connection, cookie);
|
|
||||||
if (errptr)
|
if (errptr)
|
||||||
{
|
{
|
||||||
err() << "Failed to set the window's icon: Error code " << static_cast<int>(errptr->error_code) << std::endl;
|
err() << "Failed to set the window's icon: Error code " << static_cast<int>(errptr->error_code) << std::endl;
|
||||||
@ -554,7 +609,18 @@ void WindowImplX11::setIcon(unsigned int width, unsigned int height, const Uint8
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xcb_pixmap_t maskPixmap = xcb_create_pixmap_from_bitmap_data(m_connection, m_window, (Uint8*)&maskPixels[0], width, height, 1, 0, 1, NULL);
|
|
||||||
|
xcb_pixmap_t maskPixmap = xcb_create_pixmap_from_bitmap_data(
|
||||||
|
m_connection,
|
||||||
|
m_window,
|
||||||
|
reinterpret_cast<uint8_t*>(&maskPixels[0]),
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
// Send our new icon to the window through the WMHints
|
// Send our new icon to the window through the WMHints
|
||||||
xcb_icccm_wm_hints_t hints;
|
xcb_icccm_wm_hints_t hints;
|
||||||
@ -613,10 +679,14 @@ void WindowImplX11::requestFocus()
|
|||||||
|
|
||||||
// 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
|
||||||
xcb_get_window_attributes_cookie_t attribCookie = xcb_get_window_attributes(m_connection, m_window);
|
xcb_get_window_attributes_reply_t* attributes = xcb_get_window_attributes_reply(
|
||||||
xcb_get_window_attributes_reply_t* attributes = xcb_get_window_attributes_reply(m_connection,
|
m_connection,
|
||||||
attribCookie,
|
xcb_get_window_attributes(
|
||||||
NULL);
|
m_connection,
|
||||||
|
m_window
|
||||||
|
),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
if (!attributes)
|
if (!attributes)
|
||||||
{
|
{
|
||||||
sf::err() << "Failed to check if window is viewable while requesting focus" << std::endl;
|
sf::err() << "Failed to check if window is viewable while requesting focus" << std::endl;
|
||||||
@ -637,9 +707,16 @@ void WindowImplX11::requestFocus()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Get current WM hints.
|
// Get current WM hints.
|
||||||
xcb_get_property_cookie_t hintsCookie = xcb_icccm_get_wm_hints_unchecked(m_connection, m_window);
|
|
||||||
xcb_icccm_wm_hints_t hints;
|
xcb_icccm_wm_hints_t hints;
|
||||||
xcb_icccm_get_wm_hints_reply(m_connection, hintsCookie, &hints, NULL);
|
xcb_icccm_get_wm_hints_reply(
|
||||||
|
m_connection,
|
||||||
|
xcb_icccm_get_wm_hints_unchecked(
|
||||||
|
m_connection,
|
||||||
|
m_window
|
||||||
|
),
|
||||||
|
&hints,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
// Even if no hints were returned, we can simply set the proper flags we need and go on. This is
|
// Even if no hints were returned, we can simply set the proper flags we need and go on. This is
|
||||||
// different from Xlib where XAllocWMHints() has to be called.
|
// different from Xlib where XAllocWMHints() has to be called.
|
||||||
@ -652,13 +729,18 @@ void WindowImplX11::requestFocus()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool WindowImplX11::hasFocus() const
|
bool WindowImplX11::hasFocus() const
|
||||||
{
|
{
|
||||||
xcb_get_input_focus_cookie_t cookie = xcb_get_input_focus_unchecked(m_connection);
|
xcb_get_input_focus_reply_t* reply = xcb_get_input_focus_reply(
|
||||||
xcb_get_input_focus_reply_t* reply = xcb_get_input_focus_reply(m_connection, cookie, NULL);
|
m_connection,
|
||||||
|
xcb_get_input_focus_unchecked(
|
||||||
|
m_connection
|
||||||
|
),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
bool focussed = (reply->focus == m_window);
|
bool focused = (reply->focus == m_window);
|
||||||
free(reply);
|
free(reply);
|
||||||
|
|
||||||
return focussed;
|
return focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -666,17 +748,31 @@ bool WindowImplX11::hasFocus() const
|
|||||||
void WindowImplX11::switchToFullscreen(const VideoMode& mode)
|
void WindowImplX11::switchToFullscreen(const VideoMode& mode)
|
||||||
{
|
{
|
||||||
// Check if the XRandR extension is present
|
// Check if the XRandR extension is present
|
||||||
xcb_query_extension_reply_t* randr_ext =
|
static const std::string RANDR = "RANDR";
|
||||||
xcb_query_extension_reply(m_connection, xcb_query_extension(m_connection, 5, "RANDR"), NULL);
|
xcb_query_extension_reply_t* randr_ext = xcb_query_extension_reply(
|
||||||
|
m_connection,
|
||||||
|
xcb_query_extension(
|
||||||
|
m_connection,
|
||||||
|
RANDR.size(),
|
||||||
|
RANDR.c_str()
|
||||||
|
),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
if (randr_ext->present)
|
if (randr_ext->present)
|
||||||
{
|
{
|
||||||
// Get the current configuration
|
// Get the current configuration
|
||||||
xcb_generic_error_t* errors;
|
xcb_generic_error_t* error;
|
||||||
xcb_randr_get_screen_info_reply_t* config =
|
xcb_randr_get_screen_info_reply_t* config = xcb_randr_get_screen_info_reply(
|
||||||
xcb_randr_get_screen_info_reply(m_connection,
|
m_connection,
|
||||||
xcb_randr_get_screen_info(m_connection, m_screen->root),
|
xcb_randr_get_screen_info(
|
||||||
&errors);
|
m_connection,
|
||||||
if (! errors)
|
m_screen->root
|
||||||
|
),
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!error)
|
||||||
{
|
{
|
||||||
// Save the current video mode before we switch to fullscreen
|
// Save the current video mode before we switch to fullscreen
|
||||||
m_oldVideoMode = config->sizeID;
|
m_oldVideoMode = config->sizeID;
|
||||||
@ -688,14 +784,19 @@ void WindowImplX11::switchToFullscreen(const VideoMode& mode)
|
|||||||
// Search a matching size
|
// Search a matching size
|
||||||
for (int i = 0; i < config->nSizes; ++i)
|
for (int i = 0; i < config->nSizes; ++i)
|
||||||
{
|
{
|
||||||
if ((sizes[i].width == static_cast<int>(mode.width)) && (sizes[i].height == static_cast<int>(mode.height)))
|
if ((sizes[i].width == static_cast<int>(mode.width)) &&
|
||||||
|
(sizes[i].height == static_cast<int>(mode.height)))
|
||||||
{
|
{
|
||||||
// Switch to fullscreen mode
|
// Switch to fullscreen mode
|
||||||
xcb_randr_set_screen_config(m_connection,
|
xcb_randr_set_screen_config(
|
||||||
m_screen->root,
|
m_connection,
|
||||||
config->timestamp,
|
m_screen->root,
|
||||||
config->config_timestamp,
|
config->timestamp,
|
||||||
i, config->rotation, config->rate);
|
config->config_timestamp,
|
||||||
|
i,
|
||||||
|
config->rotation,
|
||||||
|
config->rate
|
||||||
|
);
|
||||||
|
|
||||||
// Set "this" as the current fullscreen window
|
// Set "this" as the current fullscreen window
|
||||||
fullscreenWindow = this;
|
fullscreenWindow = this;
|
||||||
@ -709,14 +810,17 @@ void WindowImplX11::switchToFullscreen(const VideoMode& mode)
|
|||||||
// Failed to get the screen configuration
|
// Failed to get the screen configuration
|
||||||
err() << "Failed to get the current screen configuration for fullscreen mode, switching to window mode" << std::endl;
|
err() << "Failed to get the current screen configuration for fullscreen mode, switching to window mode" << std::endl;
|
||||||
}
|
}
|
||||||
free(errors);
|
|
||||||
|
// Free the configuration instance
|
||||||
|
free(error);
|
||||||
free(config);
|
free(config);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// XRandr extension is not supported: we cannot use fullscreen mode
|
// XRandR extension is not supported: we cannot use fullscreen mode
|
||||||
err() << "Fullscreen is not supported, switching to window mode" << std::endl;
|
err() << "Fullscreen is not supported, switching to window mode" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(randr_ext);
|
free(randr_ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -726,30 +830,26 @@ void WindowImplX11::initialize()
|
|||||||
{
|
{
|
||||||
// Get the atoms for registering the close event
|
// Get the atoms for registering the close event
|
||||||
static const std::string WM_DELETE_WINDOW_NAME = "WM_DELETE_WINDOW";
|
static const std::string WM_DELETE_WINDOW_NAME = "WM_DELETE_WINDOW";
|
||||||
|
|
||||||
xcb_intern_atom_cookie_t deleteWindowAtomRequest = xcb_intern_atom(
|
|
||||||
m_connection,
|
|
||||||
0,
|
|
||||||
WM_DELETE_WINDOW_NAME.size(),
|
|
||||||
WM_DELETE_WINDOW_NAME.c_str()
|
|
||||||
);
|
|
||||||
xcb_intern_atom_reply_t* deleteWindowAtomReply = xcb_intern_atom_reply(
|
xcb_intern_atom_reply_t* deleteWindowAtomReply = xcb_intern_atom_reply(
|
||||||
m_connection,
|
m_connection,
|
||||||
deleteWindowAtomRequest,
|
xcb_intern_atom(
|
||||||
|
m_connection,
|
||||||
|
0,
|
||||||
|
WM_DELETE_WINDOW_NAME.size(),
|
||||||
|
WM_DELETE_WINDOW_NAME.c_str()
|
||||||
|
),
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
static const std::string WM_PROTOCOLS_NAME = "WM_PROTOCOLS";
|
static const std::string WM_PROTOCOLS_NAME = "WM_PROTOCOLS";
|
||||||
|
|
||||||
xcb_intern_atom_cookie_t protocolsAtomRequest = xcb_intern_atom(
|
|
||||||
m_connection,
|
|
||||||
0,
|
|
||||||
WM_PROTOCOLS_NAME.size(),
|
|
||||||
WM_PROTOCOLS_NAME.c_str()
|
|
||||||
);
|
|
||||||
xcb_intern_atom_reply_t* protocolsAtomReply = xcb_intern_atom_reply(
|
xcb_intern_atom_reply_t* protocolsAtomReply = xcb_intern_atom_reply(
|
||||||
m_connection,
|
m_connection,
|
||||||
protocolsAtomRequest,
|
xcb_intern_atom(
|
||||||
|
m_connection,
|
||||||
|
0,
|
||||||
|
WM_PROTOCOLS_NAME.size(),
|
||||||
|
WM_PROTOCOLS_NAME.c_str()
|
||||||
|
),
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -776,18 +876,25 @@ void WindowImplX11::initialize()
|
|||||||
|
|
||||||
// Create the input context
|
// Create the input context
|
||||||
m_inputMethod = XOpenIM(m_display, NULL, NULL, NULL);
|
m_inputMethod = XOpenIM(m_display, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (m_inputMethod)
|
if (m_inputMethod)
|
||||||
{
|
{
|
||||||
m_inputContext = XCreateIC(m_inputMethod,
|
m_inputContext = XCreateIC(
|
||||||
XNClientWindow, m_window,
|
m_inputMethod,
|
||||||
XNFocusWindow, m_window,
|
XNClientWindow,
|
||||||
XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
|
m_window,
|
||||||
(void*)NULL);
|
XNFocusWindow,
|
||||||
|
m_window,
|
||||||
|
XNInputStyle,
|
||||||
|
XIMPreeditNothing | XIMStatusNothing,
|
||||||
|
reinterpret_cast<void*>(NULL)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_inputContext = NULL;
|
m_inputContext = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_inputContext)
|
if (!m_inputContext)
|
||||||
err() << "Failed to create input context for window -- TextEntered event won't be able to return unicode" << std::endl;
|
err() << "Failed to create input context for window -- TextEntered event won't be able to return unicode" << std::endl;
|
||||||
|
|
||||||
@ -815,10 +922,16 @@ void WindowImplX11::createHiddenCursor()
|
|||||||
xcb_create_pixmap(m_connection, 1, cursorPixmap, m_window, 1, 1);
|
xcb_create_pixmap(m_connection, 1, cursorPixmap, m_window, 1, 1);
|
||||||
|
|
||||||
// Create the cursor, using the pixmap as both the shape and the mask of the cursor
|
// Create the cursor, using the pixmap as both the shape and the mask of the cursor
|
||||||
xcb_create_cursor(m_connection, m_hiddenCursor, cursorPixmap, cursorPixmap,
|
xcb_create_cursor(
|
||||||
0, 0, 0, // Fore color
|
m_connection,
|
||||||
0, 0, 0, // Back color
|
m_hiddenCursor,
|
||||||
0, 0);
|
cursorPixmap,
|
||||||
|
cursorPixmap,
|
||||||
|
0, 0, 0, // Foreground RGB color
|
||||||
|
0, 0, 0, // Background RGB color
|
||||||
|
0, // X
|
||||||
|
0 // Y
|
||||||
|
);
|
||||||
|
|
||||||
// We don't need the pixmap any longer, free it
|
// We don't need the pixmap any longer, free it
|
||||||
xcb_free_pixmap(m_connection, cursorPixmap);
|
xcb_free_pixmap(m_connection, cursorPixmap);
|
||||||
@ -832,23 +945,33 @@ void WindowImplX11::cleanup()
|
|||||||
if (fullscreenWindow == this)
|
if (fullscreenWindow == this)
|
||||||
{
|
{
|
||||||
// Get current screen info
|
// Get current screen info
|
||||||
xcb_generic_error_t* errors;
|
xcb_generic_error_t* error;
|
||||||
xcb_randr_get_screen_info_reply_t* config = xcb_randr_get_screen_info_reply(
|
xcb_randr_get_screen_info_reply_t* config = xcb_randr_get_screen_info_reply(
|
||||||
m_connection, xcb_randr_get_screen_info(m_connection, m_screen->root), &errors);
|
m_connection,
|
||||||
if (!errors)
|
xcb_randr_get_screen_info(
|
||||||
|
m_connection,
|
||||||
|
m_screen->root
|
||||||
|
),
|
||||||
|
&error
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!error)
|
||||||
{
|
{
|
||||||
// Reset the video mode
|
// Reset the video mode
|
||||||
xcb_randr_set_screen_config(m_connection,
|
xcb_randr_set_screen_config(
|
||||||
m_screen->root,
|
m_connection,
|
||||||
CurrentTime,
|
m_screen->root,
|
||||||
config->config_timestamp,
|
CurrentTime,
|
||||||
m_oldVideoMode,
|
config->config_timestamp,
|
||||||
config->rotation, config->rate);
|
m_oldVideoMode,
|
||||||
|
config->rotation,
|
||||||
// Free the configuration instance
|
config->rate
|
||||||
free(config);
|
);
|
||||||
}
|
}
|
||||||
free(errors);
|
|
||||||
|
// Free the configuration instance
|
||||||
|
free(error);
|
||||||
|
free(config);
|
||||||
|
|
||||||
// Reset the fullscreen window
|
// Reset the fullscreen window
|
||||||
fullscreenWindow = NULL;
|
fullscreenWindow = NULL;
|
||||||
@ -885,9 +1008,16 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
pushEvent(event);
|
pushEvent(event);
|
||||||
|
|
||||||
// If the window has been previously marked urgent (notification) as a result of a focus request, undo that
|
// If the window has been previously marked urgent (notification) as a result of a focus request, undo that
|
||||||
xcb_get_property_cookie_t hintsCookie = xcb_icccm_get_wm_hints_unchecked(m_connection, m_window);
|
|
||||||
xcb_icccm_wm_hints_t hints;
|
xcb_icccm_wm_hints_t hints;
|
||||||
xcb_icccm_get_wm_hints_reply(m_connection, hintsCookie, &hints, NULL);
|
xcb_icccm_get_wm_hints_reply(
|
||||||
|
m_connection,
|
||||||
|
xcb_icccm_get_wm_hints_unchecked(
|
||||||
|
m_connection,
|
||||||
|
m_window
|
||||||
|
),
|
||||||
|
&hints,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
// Remove urgency (notification) flag from hints
|
// Remove urgency (notification) flag from hints
|
||||||
hints.flags &= ~XUrgencyHint;
|
hints.flags &= ~XUrgencyHint;
|
||||||
@ -949,8 +1079,8 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
XEvent fake_event;
|
XEvent fake_event;
|
||||||
fake_event.type = KeyPress;
|
fake_event.type = KeyPress;
|
||||||
fake_event.xany.display = m_display;
|
fake_event.xany.display = m_display;
|
||||||
fake_event.xany.window = e->event;
|
fake_event.xany.window = e->event;
|
||||||
fake_event.xkey.state = e->state;
|
fake_event.xkey.state = e->state;
|
||||||
fake_event.xkey.keycode = e->detail;
|
fake_event.xkey.keycode = e->detail;
|
||||||
|
|
||||||
XLookupString(&fake_event.xkey, buffer, sizeof(buffer), &symbol, &keyboard);
|
XLookupString(&fake_event.xkey, buffer, sizeof(buffer), &symbol, &keyboard);
|
||||||
@ -974,7 +1104,16 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
{
|
{
|
||||||
Status status;
|
Status status;
|
||||||
Uint8 keyBuffer[16];
|
Uint8 keyBuffer[16];
|
||||||
int length = Xutf8LookupString(m_inputContext, &fake_event.xkey, reinterpret_cast<char*>(keyBuffer), sizeof(keyBuffer), NULL, &status);
|
|
||||||
|
int length = Xutf8LookupString(
|
||||||
|
m_inputContext,
|
||||||
|
&fake_event.xkey,
|
||||||
|
reinterpret_cast<char*>(keyBuffer),
|
||||||
|
sizeof(keyBuffer),
|
||||||
|
NULL,
|
||||||
|
&status
|
||||||
|
);
|
||||||
|
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
{
|
{
|
||||||
Uint32 unicode = 0;
|
Uint32 unicode = 0;
|
||||||
@ -1019,7 +1158,7 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
// has to be converted to an XEvent
|
// has to be converted to an XEvent
|
||||||
XKeyEvent fake_event;
|
XKeyEvent fake_event;
|
||||||
fake_event.display = m_display;
|
fake_event.display = m_display;
|
||||||
fake_event.state = e->state;
|
fake_event.state = e->state;
|
||||||
fake_event.keycode = e->detail;
|
fake_event.keycode = e->detail;
|
||||||
XLookupString(&fake_event, buffer, 32, &symbol, NULL);
|
XLookupString(&fake_event, buffer, 32, &symbol, NULL);
|
||||||
|
|
||||||
@ -1043,8 +1182,11 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
|
|
||||||
// XXX: Why button 8 and 9?
|
// XXX: Why button 8 and 9?
|
||||||
xcb_button_t button = e->detail;
|
xcb_button_t button = e->detail;
|
||||||
if ((button == XCB_BUTTON_INDEX_1) || (button == XCB_BUTTON_INDEX_2)
|
if ((button == XCB_BUTTON_INDEX_1) ||
|
||||||
|| (button == XCB_BUTTON_INDEX_3) || (button == 8) || (button == 9))
|
(button == XCB_BUTTON_INDEX_2) ||
|
||||||
|
(button == XCB_BUTTON_INDEX_3) ||
|
||||||
|
(button == 8) ||
|
||||||
|
(button == 9))
|
||||||
{
|
{
|
||||||
Event event;
|
Event event;
|
||||||
event.type = Event::MouseButtonPressed;
|
event.type = Event::MouseButtonPressed;
|
||||||
@ -1069,8 +1211,11 @@ bool WindowImplX11::processEvent(xcb_generic_event_t* windowEvent)
|
|||||||
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;
|
||||||
if ((button == XCB_BUTTON_INDEX_1) || (button == XCB_BUTTON_INDEX_2)
|
if ((button == XCB_BUTTON_INDEX_1) ||
|
||||||
|| (button == XCB_BUTTON_INDEX_3) || (button == 8) || (button == 9))
|
(button == XCB_BUTTON_INDEX_2) ||
|
||||||
|
(button == XCB_BUTTON_INDEX_3) ||
|
||||||
|
(button == 8) ||
|
||||||
|
(button == 9))
|
||||||
{
|
{
|
||||||
Event event;
|
Event event;
|
||||||
event.type = Event::MouseButtonReleased;
|
event.type = Event::MouseButtonReleased;
|
||||||
|
Loading…
Reference in New Issue
Block a user