mirror of
https://github.com/SFML/SFML.git
synced 2024-11-28 22:31:09 +08:00
Merge branch 'feature/xcb'
This commit is contained in:
commit
b7c0af3a58
97
cmake/Modules/FindXCB.cmake
Normal file
97
cmake/Modules/FindXCB.cmake
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
# Try to find libxcb
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Once done this will define:
|
||||||
|
# LIBXCB_FOUND - True if xcb was found
|
||||||
|
# LIBXCB_INCLUDE_DIRS - Directories containing the headers
|
||||||
|
# LIBXCB_LIBRARIES - List of libraries to link to
|
||||||
|
#
|
||||||
|
# Also for each requested component:
|
||||||
|
# LIBXCB_${UPPER_COMPONENT_NAME}_FOUND
|
||||||
|
# LIBXCB_${UPPER_COMPONENT_NAME}_INCLUDE_DIRS
|
||||||
|
# LIBXCB_${UPPER_COMPONENT_NAME}_LIBRARIES
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
IF(NOT WIN32)
|
||||||
|
IF(LIBXCB_LIBRARIES AND LIBXCB_INCLUDE_DIR)
|
||||||
|
set(XCB_FIND_QUIETLY TRUE)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# Find xcb
|
||||||
|
FIND_PATH(LIBXCB_INCLUDE_DIR xcb/xcb.h)
|
||||||
|
FIND_LIBRARY(LIBXCB_LIBRARY NAMES xcb libxcb)
|
||||||
|
|
||||||
|
# Add xcb info to LIBXCB_LIBRARIES and LIBXCB_INCLUDE_DIRS
|
||||||
|
SET(LIBXCB_LIBRARIES ${LIBXCB_LIBRARY})
|
||||||
|
SET(LIBXCB_INCLUDE_DIRS ${LIBXCB_INCLUDE_DIR})
|
||||||
|
|
||||||
|
find_package_handle_standard_args(LIBXCB DEFAULT_MSG
|
||||||
|
LIBXCB_LIBRARY LIBXCB_INCLUDE_DIR)
|
||||||
|
|
||||||
|
mark_as_advanced(LIBXCB_LIBRARY LIBXCB_INCLUDE_DIR)
|
||||||
|
|
||||||
|
# Check whether we should search for XLIB_XCB
|
||||||
|
set(FIND_XLIB_XCB FALSE)
|
||||||
|
FOREACH(XCB_COMPONENT ${XCB_FIND_COMPONENTS})
|
||||||
|
# Generate upper string of the component name
|
||||||
|
string(TOUPPER ${XCB_COMPONENT} XCB_COMPONENT_UPPER)
|
||||||
|
|
||||||
|
IF(${XCB_COMPONENT_UPPER} MATCHES "XLIB_XCB")
|
||||||
|
set(FIND_XLIB_XCB TRUE)
|
||||||
|
ELSE()
|
||||||
|
# XCB_COMPONENTS is generated to be a copy of XCB_FIND_COMPONENTS
|
||||||
|
# without XLIB_XCB (for later component search)
|
||||||
|
set(XCB_COMPONENTS ${XCB_COMPONENTS} ${XCB_COMPONENT})
|
||||||
|
ENDIF()
|
||||||
|
ENDFOREACH()
|
||||||
|
|
||||||
|
# Find XLIB_XCB if requested
|
||||||
|
IF(FIND_XLIB_XCB)
|
||||||
|
FIND_PATH(XLIB_XCB_INCLUDE_DIR X11/Xlib-xcb.h)
|
||||||
|
FIND_LIBRARY(XLIB_XCB_LIBRARY NAMES X11-xcb libX11-xcb)
|
||||||
|
|
||||||
|
SET(XLIB_XCB_LIBRARIES ${XLIB_XCB_LIBRARY})
|
||||||
|
SET(XLIB_XCB_INCLUDE_DIRS ${XLIB_XCB_INCLUDE_DIR})
|
||||||
|
|
||||||
|
find_package_handle_standard_args(XLIB_XCB DEFAULT_MSG
|
||||||
|
XLIB_XCB_LIBRARY LIBXCB_INCLUDE_DIR)
|
||||||
|
|
||||||
|
mark_as_advanced(XLIB_XCB_LIBRARY XLIB_XCB_INCLUDE_DIR)
|
||||||
|
|
||||||
|
# Add xlib_xcb info to LIBXCB_LIBRARIES and LIBXCB_INCLUDE_DIRS
|
||||||
|
set(LIBXCB_LIBRARIES ${LIBXCB_LIBRARIES} ${XLIB_XCB_LIBRARIES})
|
||||||
|
set(LIBXCB_INCLUDE_DIRS ${LIBXCB_INCLUDE_DIRS} ${XLIB_XCB_INCLUDE_DIR})
|
||||||
|
|
||||||
|
if(NOT XLIB_XCB_FOUND)
|
||||||
|
message(FATAL_ERROR "XlibXcb library not found")
|
||||||
|
endif()
|
||||||
|
ELSE()
|
||||||
|
# Add component name to the component list
|
||||||
|
set(${XCB_COMPONENTS} ${XCB_FIND_COMPONENTS})
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
# Loop through requested xcb components (does not contain xlib_xcb)
|
||||||
|
FOREACH(XCB_COMPONENT ${XCB_COMPONENTS})
|
||||||
|
# Generate lower and upper string of the component name
|
||||||
|
string(TOLOWER ${XCB_COMPONENT} XCB_COMPONENT_LOWER)
|
||||||
|
string(TOUPPER ${XCB_COMPONENT} XCB_COMPONENT_UPPER)
|
||||||
|
|
||||||
|
# Find the specific component
|
||||||
|
FIND_LIBRARY(LIBXCB_${XCB_COMPONENT_UPPER}_LIBRARY
|
||||||
|
NAMES libxcb-${XCB_COMPONENT_LOWER} xcb-${XCB_COMPONENT_LOWER})
|
||||||
|
|
||||||
|
find_package_handle_standard_args(LIBXCB_${XCB_COMPONENT_UPPER} DEFAULT_MSG
|
||||||
|
LIBXCB_${XCB_COMPONENT_UPPER}_LIBRARY LIBXCB_INCLUDE_DIR)
|
||||||
|
|
||||||
|
mark_as_advanced(LIBXCB_${XCB_COMPONENT_UPPER}_LIBRARY)
|
||||||
|
|
||||||
|
# Append the component's library path to LIBXCB_LIBRARIES
|
||||||
|
set(LIBXCB_LIBRARIES ${LIBXCB_LIBRARIES} ${LIBXCB_${XCB_COMPONENT_UPPER}_LIBRARY})
|
||||||
|
|
||||||
|
if(NOT LIBXCB_${XCB_COMPONENT_UPPER}_FOUND)
|
||||||
|
message(FATAL_ERROR "xcb-${XCB_COMPONENT_LOWER} not found")
|
||||||
|
endif()
|
||||||
|
ENDFOREACH()
|
||||||
|
|
||||||
|
endif()
|
@ -3,7 +3,8 @@
|
|||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Window.hpp>
|
#include <SFML/Window.hpp>
|
||||||
#include <X11/Xlib.h>
|
#include <SFML/System/Err.hpp>
|
||||||
|
#include <X11/Xlib-xcb.h>
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#include <GL/glu.h>
|
#include <GL/glu.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -55,9 +56,9 @@ void draw(sf::Window& window, float elapsedTime)
|
|||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glTranslatef(0.f, 0.f, -200.f);
|
glTranslatef(0.f, 0.f, -200.f);
|
||||||
glRotatef(elapsedTime * 0.05f, 1.f, 0.f, 0.f);
|
glRotatef(elapsedTime * 10.f, 1.f, 0.f, 0.f);
|
||||||
glRotatef(elapsedTime * 0.03f, 0.f, 1.f, 0.f);
|
glRotatef(elapsedTime * 6.f, 0.f, 1.f, 0.f);
|
||||||
glRotatef(elapsedTime * 0.09f, 0.f, 0.f, 1.f);
|
glRotatef(elapsedTime * 18.f, 0.f, 0.f, 1.f);
|
||||||
|
|
||||||
// Draw a cube
|
// Draw a cube
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
@ -115,85 +116,104 @@ int main()
|
|||||||
if (!display)
|
if (!display)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
// Get the default screen
|
// Get the XCB connection for the opened display.
|
||||||
int screen = DefaultScreen(display);
|
xcb_connection_t* xcbConnection = XGetXCBConnection(display);
|
||||||
|
|
||||||
// Let's create the main window
|
if (!xcbConnection)
|
||||||
XSetWindowAttributes attributes;
|
{
|
||||||
attributes.background_pixel = BlackPixel(display, screen);
|
sf::err() << "Failed to get the XCB connection for opened display." << std::endl;
|
||||||
attributes.event_mask = KeyPressMask;
|
|
||||||
Window window = XCreateWindow(display, RootWindow(display, screen),
|
|
||||||
0, 0, 650, 330, 0,
|
|
||||||
DefaultDepth(display, screen),
|
|
||||||
InputOutput,
|
|
||||||
DefaultVisual(display, screen),
|
|
||||||
CWBackPixel | CWEventMask, &attributes);
|
|
||||||
if (!window)
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
// Set the window's name
|
// Get XCB screen.
|
||||||
XStoreName(display, window , "SFML Window");
|
const xcb_setup_t* xcbSetup = xcb_get_setup(xcbConnection);
|
||||||
|
xcb_screen_iterator_t xcbScreenIter = xcb_setup_roots_iterator(xcbSetup);
|
||||||
|
xcb_screen_t* screen = xcbScreenIter.data;
|
||||||
|
|
||||||
// Let's create the windows which will serve as containers for our SFML views
|
if (!screen)
|
||||||
Window view1 = XCreateWindow(display, window,
|
{
|
||||||
10, 10, 310, 310, 0,
|
sf::err() << "Failed to get the XCB screen." << std::endl;
|
||||||
DefaultDepth(display, screen),
|
return EXIT_FAILURE;
|
||||||
InputOutput,
|
}
|
||||||
DefaultVisual(display, screen),
|
|
||||||
0, NULL);
|
|
||||||
Window view2 = XCreateWindow(display, window,
|
|
||||||
330, 10, 310, 310, 0,
|
|
||||||
DefaultDepth(display, screen),
|
|
||||||
InputOutput,
|
|
||||||
DefaultVisual(display, screen),
|
|
||||||
0, NULL);
|
|
||||||
|
|
||||||
// Show our windows
|
// Generate the XCB window IDs.
|
||||||
XMapWindow(display, window);
|
xcb_window_t rootWindowId = xcb_generate_id(xcbConnection);
|
||||||
XFlush(display);
|
xcb_window_t view1WindowId = xcb_generate_id(xcbConnection);
|
||||||
|
xcb_window_t view2WindowId = xcb_generate_id(xcbConnection);
|
||||||
|
|
||||||
|
// Create the root window with a black background.
|
||||||
|
uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
|
||||||
|
uint32_t attributes[2] = {screen->black_pixel, XCB_EVENT_MASK_KEY_PRESS};
|
||||||
|
|
||||||
|
xcb_create_window(xcbConnection,
|
||||||
|
XCB_COPY_FROM_PARENT,
|
||||||
|
rootWindowId,
|
||||||
|
screen->root,
|
||||||
|
0, 0, 650, 330,
|
||||||
|
0,
|
||||||
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
|
screen->root_visual,
|
||||||
|
mask, attributes);
|
||||||
|
|
||||||
|
// Create windows for the SFML views.
|
||||||
|
xcb_create_window(xcbConnection,
|
||||||
|
XCB_COPY_FROM_PARENT,
|
||||||
|
view1WindowId,
|
||||||
|
rootWindowId,
|
||||||
|
10, 10, 310, 310,
|
||||||
|
0,
|
||||||
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
|
screen->root_visual,
|
||||||
|
mask, attributes);
|
||||||
|
|
||||||
|
xcb_create_window(xcbConnection,
|
||||||
|
XCB_COPY_FROM_PARENT,
|
||||||
|
view2WindowId,
|
||||||
|
rootWindowId,
|
||||||
|
330, 10, 310, 310,
|
||||||
|
0,
|
||||||
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
|
screen->root_visual,
|
||||||
|
mask, attributes);
|
||||||
|
|
||||||
|
// Map windows to screen.
|
||||||
|
xcb_map_window(xcbConnection, rootWindowId);
|
||||||
|
xcb_map_window(xcbConnection, view1WindowId);
|
||||||
|
xcb_map_window(xcbConnection, view2WindowId);
|
||||||
|
|
||||||
|
// Flush commands.
|
||||||
|
xcb_flush(xcbConnection);
|
||||||
|
|
||||||
// Create our SFML views
|
// Create our SFML views
|
||||||
sf::Window SFMLView1(view1);
|
sf::Window sfmlView1(view1WindowId);
|
||||||
sf::Window SFMLView2(view2);
|
sf::Window sfmlView2(view2WindowId);
|
||||||
|
|
||||||
// Create a clock for measuring elapsed time
|
// Create a clock for measuring elapsed time
|
||||||
sf::Clock clock;
|
sf::Clock clock;
|
||||||
|
|
||||||
// Initialize our views
|
// Initialize our views
|
||||||
initialize(SFMLView1);
|
initialize(sfmlView1);
|
||||||
initialize(SFMLView2);
|
initialize(sfmlView2);
|
||||||
|
|
||||||
// Start the event loop
|
// Start the event loop
|
||||||
bool running = true;
|
bool running = true;
|
||||||
|
xcb_generic_event_t* event = NULL;
|
||||||
|
|
||||||
while (running)
|
while (running)
|
||||||
{
|
{
|
||||||
while (XPending(display))
|
while ((event = xcb_poll_for_event(xcbConnection)))
|
||||||
{
|
{
|
||||||
// Get the next pending event
|
running = false;
|
||||||
XEvent event;
|
|
||||||
XNextEvent(display, &event);
|
|
||||||
|
|
||||||
// Process it
|
|
||||||
switch (event.type)
|
|
||||||
{
|
|
||||||
// Any key is pressed: quit
|
|
||||||
case KeyPress:
|
|
||||||
running = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw something into our views
|
// Draw something into our views
|
||||||
draw(SFMLView1, clock.getElapsedTime().asSeconds());
|
draw(sfmlView1, clock.getElapsedTime().asSeconds());
|
||||||
draw(SFMLView2, clock.getElapsedTime().asSeconds() * 0.3f);
|
draw(sfmlView2, clock.getElapsedTime().asSeconds() * 0.3f);
|
||||||
|
|
||||||
// Display the views on screen
|
// Display the views on screen
|
||||||
SFMLView1.display();
|
sfmlView1.display();
|
||||||
SFMLView2.display();
|
sfmlView2.display();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the display
|
|
||||||
XCloseDisplay(display);
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -193,11 +193,11 @@ if(NOT SFML_OPENGL_ES)
|
|||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
include_directories(${OPENGL_INCLUDE_DIR})
|
include_directories(${OPENGL_INCLUDE_DIR})
|
||||||
if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
|
if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
|
||||||
find_package(X11 REQUIRED)
|
find_package(XCB COMPONENTS xlib_xcb icccm image randr util REQUIRED)
|
||||||
if(NOT X11_Xrandr_FOUND)
|
if(NOT LIBXCB_FOUND)
|
||||||
message(FATAL_ERROR "Xrandr library not found")
|
message(FATAL_ERROR "Xcb library not found")
|
||||||
endif()
|
endif()
|
||||||
include_directories(${X11_INCLUDE_DIR})
|
include_directories(${LIBXCB_INCLUDE_DIRS})
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
if(SFML_OPENGL_ES AND SFML_OS_LINUX)
|
if(SFML_OPENGL_ES AND SFML_OS_LINUX)
|
||||||
@ -217,10 +217,11 @@ 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)
|
elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD)
|
||||||
list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} ${UDEV_LIBRARIES})
|
list(APPEND WINDOW_EXT_LIBS ${LIBXCB_LIBRARIES} ${UDEV_LIBRARIES})
|
||||||
elseif(SFML_OS_FREEBSD)
|
if(SFML_OS_FREEBSD)
|
||||||
list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} usbhid)
|
list(APPEND WINDOW_EXT_LIBS 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)
|
||||||
|
@ -63,6 +63,13 @@ Display* OpenDisplay()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
xcb_connection_t* OpenConnection()
|
||||||
|
{
|
||||||
|
return XGetXCBConnection(OpenDisplay());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void CloseDisplay(Display* display)
|
void CloseDisplay(Display* display)
|
||||||
{
|
{
|
||||||
@ -73,6 +80,27 @@ void CloseDisplay(Display* display)
|
|||||||
XCloseDisplay(display);
|
XCloseDisplay(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void CloseConnection(xcb_connection_t* connection)
|
||||||
|
{
|
||||||
|
assert(connection == XGetXCBConnection(sharedDisplay));
|
||||||
|
return CloseDisplay(sharedDisplay);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr)
|
||||||
|
{
|
||||||
|
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(connection));
|
||||||
|
|
||||||
|
for (; iter.rem; --screen_nbr, xcb_screen_next (&iter))
|
||||||
|
{
|
||||||
|
if (screen_nbr == 0)
|
||||||
|
return iter.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib-xcb.h>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
@ -47,13 +47,42 @@ namespace priv
|
|||||||
Display* OpenDisplay();
|
Display* OpenDisplay();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Release a reference to the shared
|
/// \brief Get the xcb connection of the shared Display
|
||||||
///
|
///
|
||||||
/// \param display Display to release
|
/// This function increments the reference count of the display,
|
||||||
|
/// it must be matched with a call to CloseDisplay.
|
||||||
|
///
|
||||||
|
/// \return Pointer to the shared connection
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
xcb_connection_t* OpenConnection();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Release a reference to the shared display
|
||||||
|
///
|
||||||
|
/// \param Display to release
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void CloseDisplay(Display* display);
|
void CloseDisplay(Display* display);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Release a reference to the shared display
|
||||||
|
///
|
||||||
|
/// \param Connection of display to release
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void CloseConnection(xcb_connection_t* connection);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Get screen of a display by index (equivalent to XScreenOfDisplay)
|
||||||
|
///
|
||||||
|
/// \param The index of the screen
|
||||||
|
///
|
||||||
|
/// \return Pointer to the screen
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr);
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -44,18 +44,22 @@ m_ownsWindow(true)
|
|||||||
{
|
{
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
m_display = OpenDisplay();
|
m_display = OpenDisplay();
|
||||||
|
m_connection = XGetXCBConnection(m_display);
|
||||||
|
|
||||||
// Create a dummy window (disabled and hidden)
|
// Create a dummy window (disabled and hidden)
|
||||||
int screen = DefaultScreen(m_display);
|
xcb_screen_t* screen = XCBScreenOfDisplay(m_connection, DefaultScreen(m_display));
|
||||||
m_window = XCreateWindow(m_display,
|
m_window = xcb_generate_id(m_connection);
|
||||||
RootWindow(m_display, screen),
|
xcb_create_window(
|
||||||
0, 0,
|
m_connection,
|
||||||
1, 1,
|
screen->root_depth,
|
||||||
0,
|
m_window, screen->root,
|
||||||
DefaultDepth(m_display, screen),
|
0, 0,
|
||||||
InputOutput,
|
1, 1,
|
||||||
DefaultVisual(m_display, screen),
|
0,
|
||||||
0, NULL);
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
|
screen->root_visual,
|
||||||
|
0, NULL
|
||||||
|
);
|
||||||
|
|
||||||
// Create the context
|
// Create the context
|
||||||
createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings());
|
createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings());
|
||||||
@ -71,6 +75,7 @@ m_ownsWindow(false)
|
|||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
// (important: must be the same display as the owner window)
|
// (important: must be the same display as the owner window)
|
||||||
m_display = OpenDisplay();
|
m_display = OpenDisplay();
|
||||||
|
m_connection = XGetXCBConnection(m_display);
|
||||||
|
|
||||||
// Get the owner window and its device context
|
// Get the owner window and its device context
|
||||||
m_window = static_cast< ::Window>(owner->getSystemHandle());
|
m_window = static_cast< ::Window>(owner->getSystemHandle());
|
||||||
@ -89,18 +94,22 @@ m_ownsWindow(true)
|
|||||||
{
|
{
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
m_display = OpenDisplay();
|
m_display = OpenDisplay();
|
||||||
|
m_connection = XGetXCBConnection(m_display);
|
||||||
|
|
||||||
// Create the hidden window
|
// Create the hidden window
|
||||||
int screen = DefaultScreen(m_display);
|
xcb_screen_t* screen = XCBScreenOfDisplay(m_connection, DefaultScreen(m_display));
|
||||||
m_window = XCreateWindow(m_display,
|
m_window = xcb_generate_id(m_connection);
|
||||||
RootWindow(m_display, screen),
|
xcb_create_window(
|
||||||
0, 0,
|
m_connection,
|
||||||
width, height,
|
screen->root_depth,
|
||||||
0,
|
m_window, screen->root,
|
||||||
DefaultDepth(m_display, screen),
|
0, 0,
|
||||||
InputOutput,
|
width, height,
|
||||||
DefaultVisual(m_display, screen),
|
0,
|
||||||
0, NULL);
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
|
screen->root_visual,
|
||||||
|
0, NULL
|
||||||
|
);
|
||||||
|
|
||||||
// Create the context
|
// Create the context
|
||||||
createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, settings);
|
createContext(shared, VideoMode::getDesktopMode().bitsPerPixel, settings);
|
||||||
@ -121,8 +130,8 @@ GlxContext::~GlxContext()
|
|||||||
// Destroy the window if we own it
|
// Destroy the window if we own it
|
||||||
if (m_window && m_ownsWindow)
|
if (m_window && m_ownsWindow)
|
||||||
{
|
{
|
||||||
XDestroyWindow(m_display, m_window);
|
xcb_destroy_window(m_connection, m_window);
|
||||||
XFlush(m_display);
|
xcb_flush(m_connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the connection with the X server
|
// Close the connection with the X server
|
||||||
@ -211,26 +220,88 @@ XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings)
|
void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings)
|
||||||
{
|
{
|
||||||
XVisualInfo* visualInfo = NULL;
|
|
||||||
|
|
||||||
// Save the creation settings
|
// Save the creation settings
|
||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
|
|
||||||
|
// Get the attributes of the target window
|
||||||
|
XWindowAttributes windowAttributes;
|
||||||
|
if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0)
|
||||||
|
{
|
||||||
|
err() << "Failed to get the window attributes" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the visual infos to match
|
||||||
|
XVisualInfo tpl;
|
||||||
|
tpl.depth = windowAttributes.depth;
|
||||||
|
tpl.visualid = XVisualIDFromVisual(windowAttributes.visual);
|
||||||
|
tpl.screen = DefaultScreen(m_display);
|
||||||
|
|
||||||
|
// Get all the visuals matching the template
|
||||||
|
int nbVisuals = 0;
|
||||||
|
XVisualInfo* visuals = XGetVisualInfo(m_display, VisualDepthMask | VisualIDMask | VisualScreenMask, &tpl, &nbVisuals);
|
||||||
|
if (!visuals || (nbVisuals == 0))
|
||||||
|
{
|
||||||
|
if (visuals)
|
||||||
|
XFree(visuals);
|
||||||
|
err() << "There is no valid visual for the selected screen" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the best visual
|
||||||
|
int bestScore = 0xFFFF;
|
||||||
|
XVisualInfo* bestVisual = NULL;
|
||||||
|
for (int i = 0; i < nbVisuals; ++i)
|
||||||
|
{
|
||||||
|
// Get the current visual attributes
|
||||||
|
int RGBA, doubleBuffer, red, green, blue, alpha, depth, stencil, multiSampling, samples;
|
||||||
|
glXGetConfig(m_display, &visuals[i], GLX_RGBA, &RGBA);
|
||||||
|
glXGetConfig(m_display, &visuals[i], GLX_DOUBLEBUFFER, &doubleBuffer);
|
||||||
|
glXGetConfig(m_display, &visuals[i], GLX_RED_SIZE, &red);
|
||||||
|
glXGetConfig(m_display, &visuals[i], GLX_GREEN_SIZE, &green);
|
||||||
|
glXGetConfig(m_display, &visuals[i], GLX_BLUE_SIZE, &blue);
|
||||||
|
glXGetConfig(m_display, &visuals[i], GLX_ALPHA_SIZE, &alpha);
|
||||||
|
glXGetConfig(m_display, &visuals[i], GLX_DEPTH_SIZE, &depth);
|
||||||
|
glXGetConfig(m_display, &visuals[i], GLX_STENCIL_SIZE, &stencil);
|
||||||
|
glXGetConfig(m_display, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling);
|
||||||
|
glXGetConfig(m_display, &visuals[i], GLX_SAMPLES_ARB, &samples);
|
||||||
|
|
||||||
|
// First check the mandatory parameters
|
||||||
|
if ((RGBA == 0) || (doubleBuffer == 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Evaluate the current configuration
|
||||||
|
int color = red + green + blue + alpha;
|
||||||
|
int score = evaluateFormat(bitsPerPixel, m_settings, color, depth, stencil, multiSampling ? samples : 0);
|
||||||
|
|
||||||
|
// Keep it if it's better than the current best
|
||||||
|
if (score < bestScore)
|
||||||
|
{
|
||||||
|
bestScore = score;
|
||||||
|
bestVisual = &visuals[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure that we have found a visual
|
||||||
|
if (!bestVisual)
|
||||||
|
{
|
||||||
|
err() << "Failed to find a suitable pixel format for the window -- cannot create OpenGL context" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the context to share display lists with
|
// Get the context to share display lists with
|
||||||
GLXContext toShare = shared ? shared->m_context : NULL;
|
GLXContext toShare = shared ? shared->m_context : NULL;
|
||||||
|
|
||||||
// Create the OpenGL context -- first try context versions >= 3.0 if it is requested (they require special code)
|
// Create the OpenGL context -- first try context versions >= 3.0 if it is requested (they require special code)
|
||||||
if (m_settings.majorVersion >= 3)
|
while (!m_context && (m_settings.majorVersion >= 3))
|
||||||
{
|
{
|
||||||
const GLubyte* name = reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB");
|
const GLubyte* name = reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB");
|
||||||
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>(glXGetProcAddress(name));
|
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>(glXGetProcAddress(name));
|
||||||
if (glXCreateContextAttribsARB)
|
if (glXCreateContextAttribsARB)
|
||||||
{
|
{
|
||||||
// Select a GLXFB config that matches the requested context settings
|
|
||||||
int nbConfigs = 0;
|
int nbConfigs = 0;
|
||||||
int fbAttributes[] =
|
int fbAttributes[] =
|
||||||
{
|
{
|
||||||
@ -250,43 +321,38 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), fbAttributes, &nbConfigs);
|
GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), fbAttributes, &nbConfigs);
|
||||||
|
|
||||||
if (configs && nbConfigs)
|
if (configs && nbConfigs)
|
||||||
{
|
{
|
||||||
while (!m_context && (m_settings.majorVersion >= 3))
|
// Create the context
|
||||||
|
int attributes[] =
|
||||||
{
|
{
|
||||||
// Create the context
|
GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion),
|
||||||
int attributes[] =
|
GLX_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion),
|
||||||
{
|
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||||
GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion),
|
0, 0
|
||||||
GLX_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion),
|
};
|
||||||
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
m_context = glXCreateContextAttribsARB(m_display, configs[0], toShare, true, attributes);
|
||||||
0, 0
|
}
|
||||||
};
|
|
||||||
m_context = glXCreateContextAttribsARB(m_display, configs[0], toShare, true, attributes);
|
|
||||||
|
|
||||||
if (m_context)
|
if (configs)
|
||||||
{
|
|
||||||
// Ok: retrieve the config's visual
|
|
||||||
visualInfo = glXGetVisualFromFBConfig(m_display, configs[0]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If we couldn't create the context, lower the version number and try again -- stop at 3.0
|
|
||||||
// Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care
|
|
||||||
if (m_settings.minorVersion > 0)
|
|
||||||
{
|
|
||||||
// If the minor version is not 0, we decrease it and try again
|
|
||||||
m_settings.minorVersion--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If the minor version is 0, we decrease the major version
|
|
||||||
m_settings.majorVersion--;
|
|
||||||
m_settings.minorVersion = 9;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
XFree(configs);
|
XFree(configs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we couldn't create the context, lower the version number and try again -- stop at 3.0
|
||||||
|
// Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care
|
||||||
|
if (!m_context)
|
||||||
|
{
|
||||||
|
if (m_settings.minorVersion > 0)
|
||||||
|
{
|
||||||
|
// If the minor version is not 0, we decrease it and try again
|
||||||
|
m_settings.minorVersion--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the minor version is 0, we decrease the major version
|
||||||
|
m_settings.majorVersion--;
|
||||||
|
m_settings.minorVersion = 9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,23 +364,7 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co
|
|||||||
m_settings.majorVersion = 2;
|
m_settings.majorVersion = 2;
|
||||||
m_settings.minorVersion = 0;
|
m_settings.minorVersion = 0;
|
||||||
|
|
||||||
// Retrieve the attributes of the target window
|
m_context = glXCreateContext(m_display, bestVisual, toShare, true);
|
||||||
XWindowAttributes windowAttributes;
|
|
||||||
if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0)
|
|
||||||
{
|
|
||||||
err() << "Failed to get the window attributes" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get its visual
|
|
||||||
XVisualInfo tpl;
|
|
||||||
tpl.screen = DefaultScreen(m_display);
|
|
||||||
tpl.visualid = XVisualIDFromVisual(windowAttributes.visual);
|
|
||||||
int nbVisuals = 0;
|
|
||||||
visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals);
|
|
||||||
|
|
||||||
// Create the context, using the target window's visual
|
|
||||||
m_context = glXCreateContext(m_display, visualInfo, toShare, true);
|
|
||||||
if (!m_context)
|
if (!m_context)
|
||||||
{
|
{
|
||||||
err() << "Failed to create an OpenGL context for this window" << std::endl;
|
err() << "Failed to create an OpenGL context for this window" << std::endl;
|
||||||
@ -324,16 +374,21 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co
|
|||||||
|
|
||||||
// Update the creation settings from the chosen format
|
// Update the creation settings from the chosen format
|
||||||
int depth, stencil, multiSampling, samples;
|
int depth, stencil, multiSampling, samples;
|
||||||
glXGetConfig(m_display, visualInfo, GLX_DEPTH_SIZE, &depth);
|
glXGetConfig(m_display, bestVisual, GLX_DEPTH_SIZE, &depth);
|
||||||
glXGetConfig(m_display, visualInfo, GLX_STENCIL_SIZE, &stencil);
|
glXGetConfig(m_display, bestVisual, GLX_STENCIL_SIZE, &stencil);
|
||||||
glXGetConfig(m_display, visualInfo, GLX_SAMPLE_BUFFERS_ARB, &multiSampling);
|
glXGetConfig(m_display, bestVisual, GLX_SAMPLE_BUFFERS_ARB, &multiSampling);
|
||||||
glXGetConfig(m_display, visualInfo, GLX_SAMPLES_ARB, &samples);
|
glXGetConfig(m_display, bestVisual, GLX_SAMPLES_ARB, &samples);
|
||||||
m_settings.depthBits = static_cast<unsigned int>(depth);
|
m_settings.depthBits = static_cast<unsigned int>(depth);
|
||||||
m_settings.stencilBits = static_cast<unsigned int>(stencil);
|
m_settings.stencilBits = static_cast<unsigned int>(stencil);
|
||||||
m_settings.antialiasingLevel = multiSampling ? samples : 0;
|
m_settings.antialiasingLevel = multiSampling ? samples : 0;
|
||||||
|
|
||||||
// Free the visual info
|
// Change the target window's colormap so that it matches the context's one
|
||||||
XFree(visualInfo);
|
::Window root = RootWindow(m_display, DefaultScreen(m_display));
|
||||||
|
Colormap colorMap = XCreateColormap(m_display, root, bestVisual->visual, AllocNone);
|
||||||
|
XSetWindowColormap(m_display, m_window, colorMap);
|
||||||
|
|
||||||
|
// Free the temporary visuals array
|
||||||
|
XFree(visuals);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Window/GlContext.hpp>
|
#include <SFML/Window/GlContext.hpp>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib-xcb.h>
|
||||||
#include <GL/glx.h>
|
#include <GL/glx.h>
|
||||||
|
|
||||||
|
|
||||||
@ -135,10 +135,11 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
::Display* m_display; ///< Connection to the X server
|
::Display* m_display; ///< Connection to the X server
|
||||||
::Window m_window; ///< Window to which the context is attached
|
::Window m_window; ///< Window to which the context is attached
|
||||||
GLXContext m_context; ///< OpenGL context
|
xcb_connection_t* m_connection; ///< Pointer to the xcb connection
|
||||||
bool m_ownsWindow; ///< Do we own the window associated to the context?
|
GLXContext m_context; ///< OpenGL context
|
||||||
|
bool m_ownsWindow; ///< Do we own the window associated to the context?
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
@ -28,8 +28,9 @@
|
|||||||
#include <SFML/Window/Unix/InputImpl.hpp>
|
#include <SFML/Window/Unix/InputImpl.hpp>
|
||||||
#include <SFML/Window/Window.hpp>
|
#include <SFML/Window/Window.hpp>
|
||||||
#include <SFML/Window/Unix/Display.hpp>
|
#include <SFML/Window/Unix/Display.hpp>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib-xcb.h>
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
@ -149,20 +150,23 @@ bool InputImpl::isKeyPressed(Keyboard::Key key)
|
|||||||
|
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
Display* display = OpenDisplay();
|
Display* display = OpenDisplay();
|
||||||
|
xcb_connection_t* connection = XGetXCBConnection(display);
|
||||||
|
|
||||||
// Convert to keycode
|
// Convert to keycode
|
||||||
KeyCode keycode = XKeysymToKeycode(display, keysym);
|
KeyCode keycode = XKeysymToKeycode(display, keysym);
|
||||||
if (keycode != 0)
|
if (keycode != 0)
|
||||||
{
|
{
|
||||||
// Get the whole keyboard state
|
// Get the whole keyboard state
|
||||||
char keys[32];
|
xcb_query_keymap_reply_t* keymap = xcb_query_keymap_reply(connection, xcb_query_keymap(connection), NULL);
|
||||||
XQueryKeymap(display, keys);
|
|
||||||
|
|
||||||
// Close the connection with the X server
|
// Close the connection with the X server
|
||||||
CloseDisplay(display);
|
CloseDisplay(display);
|
||||||
|
|
||||||
// Check our keycode
|
// Check our keycode
|
||||||
return (keys[keycode / 8] & (1 << (keycode % 8))) != 0;
|
bool isPressed = (keymap->keys[keycode / 8] & (1 << (keycode % 8))) != 0;
|
||||||
|
|
||||||
|
free(keymap);
|
||||||
|
return isPressed;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -175,7 +179,7 @@ bool InputImpl::isKeyPressed(Keyboard::Key key)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void InputImpl::setVirtualKeyboardVisible(bool visible)
|
void InputImpl::setVirtualKeyboardVisible(bool /*visible*/)
|
||||||
{
|
{
|
||||||
// Not applicable
|
// Not applicable
|
||||||
}
|
}
|
||||||
@ -186,29 +190,28 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button)
|
|||||||
{
|
{
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
Display* display = OpenDisplay();
|
Display* display = OpenDisplay();
|
||||||
|
xcb_connection_t* connection = XGetXCBConnection(display);
|
||||||
|
|
||||||
// we don't care about these but they are required
|
// Get pointer mask
|
||||||
::Window root, child;
|
xcb_query_pointer_reply_t* pointer = xcb_query_pointer_reply(connection, xcb_query_pointer(connection, XDefaultRootWindow(display)), NULL);
|
||||||
int wx, wy;
|
|
||||||
int gx, gy;
|
|
||||||
|
|
||||||
unsigned int buttons = 0;
|
|
||||||
XQueryPointer(display, DefaultRootWindow(display), &root, &child, &gx, &gy, &wx, &wy, &buttons);
|
|
||||||
|
|
||||||
// Close the connection with the X server
|
// Close the connection with the X server
|
||||||
CloseDisplay(display);
|
CloseDisplay(display);
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
switch (button)
|
switch (button)
|
||||||
{
|
{
|
||||||
case Mouse::Left: return buttons & Button1Mask;
|
case Mouse::Left: result = pointer->mask & XCB_BUTTON_MASK_1;
|
||||||
case Mouse::Right: return buttons & Button3Mask;
|
case Mouse::Right: result = pointer->mask & XCB_BUTTON_MASK_3;
|
||||||
case Mouse::Middle: return buttons & Button2Mask;
|
case Mouse::Middle: result = pointer->mask & XCB_BUTTON_MASK_2;
|
||||||
case Mouse::XButton1: return false; // not supported by X
|
case Mouse::XButton1: // not supported by X
|
||||||
case Mouse::XButton2: return false; // not supported by X
|
case Mouse::XButton2: // not supported by X
|
||||||
default: return false;
|
default: result = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
free(pointer);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -217,20 +220,18 @@ Vector2i InputImpl::getMousePosition()
|
|||||||
{
|
{
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
Display* display = OpenDisplay();
|
Display* display = OpenDisplay();
|
||||||
|
xcb_connection_t* connection = XGetXCBConnection(display);
|
||||||
|
|
||||||
// we don't care about these but they are required
|
xcb_query_pointer_reply_t* pointer = xcb_query_pointer_reply(connection, xcb_query_pointer(connection, XDefaultRootWindow(display)), NULL);
|
||||||
::Window root, child;
|
|
||||||
int x, y;
|
|
||||||
unsigned int buttons;
|
|
||||||
|
|
||||||
int gx = 0;
|
|
||||||
int gy = 0;
|
|
||||||
XQueryPointer(display, DefaultRootWindow(display), &root, &child, &gx, &gy, &x, &y, &buttons);
|
|
||||||
|
|
||||||
// Close the connection with the X server
|
// Close the connection with the X server
|
||||||
CloseDisplay(display);
|
CloseDisplay(display);
|
||||||
|
|
||||||
return Vector2i(gx, gy);
|
// Prepare result.
|
||||||
|
Vector2i result(pointer->root_x, pointer->root_y);
|
||||||
|
free(pointer);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -241,21 +242,18 @@ Vector2i InputImpl::getMousePosition(const Window& relativeTo)
|
|||||||
if (handle)
|
if (handle)
|
||||||
{
|
{
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
Display* display = OpenDisplay();
|
xcb_connection_t* connection = OpenConnection();
|
||||||
|
|
||||||
// we don't care about these but they are required
|
xcb_query_pointer_reply_t* pointer = xcb_query_pointer_reply(connection, xcb_query_pointer(connection, handle), NULL);
|
||||||
::Window root, child;
|
|
||||||
int gx, gy;
|
|
||||||
unsigned int buttons;
|
|
||||||
|
|
||||||
int x = 0;
|
|
||||||
int y = 0;
|
|
||||||
XQueryPointer(display, handle, &root, &child, &gx, &gy, &x, &y, &buttons);
|
|
||||||
|
|
||||||
// Close the connection with the X server
|
// Close the connection with the X server
|
||||||
CloseDisplay(display);
|
CloseConnection(connection);
|
||||||
|
|
||||||
return Vector2i(x, y);
|
// Prepare result.
|
||||||
|
Vector2i result(pointer->win_x, pointer->win_y);
|
||||||
|
free(pointer);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -269,9 +267,10 @@ void InputImpl::setMousePosition(const Vector2i& position)
|
|||||||
{
|
{
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
Display* display = OpenDisplay();
|
Display* display = OpenDisplay();
|
||||||
|
xcb_connection_t* connection = XGetXCBConnection(display);
|
||||||
|
|
||||||
XWarpPointer(display, None, DefaultRootWindow(display), 0, 0, 0, 0, position.x, position.y);
|
xcb_warp_pointer(connection, None, XDefaultRootWindow(display), 0, 0, 0, 0, position.x, position.y);
|
||||||
XFlush(display);
|
xcb_flush(connection);
|
||||||
|
|
||||||
// Close the connection with the X server
|
// Close the connection with the X server
|
||||||
CloseDisplay(display);
|
CloseDisplay(display);
|
||||||
@ -282,17 +281,17 @@ void InputImpl::setMousePosition(const Vector2i& position)
|
|||||||
void InputImpl::setMousePosition(const Vector2i& position, const Window& relativeTo)
|
void InputImpl::setMousePosition(const Vector2i& position, const Window& relativeTo)
|
||||||
{
|
{
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
Display* display = OpenDisplay();
|
xcb_connection_t* connection = OpenConnection();
|
||||||
|
|
||||||
WindowHandle handle = relativeTo.getSystemHandle();
|
WindowHandle handle = relativeTo.getSystemHandle();
|
||||||
if (handle)
|
if (handle)
|
||||||
{
|
{
|
||||||
XWarpPointer(display, None, handle, 0, 0, 0, 0, position.x, position.y);
|
xcb_warp_pointer(connection, None, handle, 0, 0, 0, 0, position.x, position.y);
|
||||||
XFlush(display);
|
xcb_flush(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the connection with the X server
|
// Close the connection with the X server
|
||||||
CloseDisplay(display);
|
CloseConnection(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,8 +28,7 @@
|
|||||||
#include <SFML/Window/VideoModeImpl.hpp>
|
#include <SFML/Window/VideoModeImpl.hpp>
|
||||||
#include <SFML/Window/Unix/Display.hpp>
|
#include <SFML/Window/Unix/Display.hpp>
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <X11/Xlib.h>
|
#include <xcb/randr.h>
|
||||||
#include <X11/extensions/Xrandr.h>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
@ -44,63 +43,62 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
|
|||||||
|
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
Display* display = OpenDisplay();
|
Display* display = OpenDisplay();
|
||||||
|
xcb_connection_t* connection = XGetXCBConnection(display);
|
||||||
|
|
||||||
if (display)
|
if (display)
|
||||||
{
|
{
|
||||||
// Retrieve the default screen number
|
// Check if the XRandR extension is present
|
||||||
int screen = DefaultScreen(display);
|
xcb_query_extension_cookie_t cookie = xcb_query_extension(connection, 5, "RANDR");
|
||||||
|
|
||||||
|
// Retrieve the default screen
|
||||||
|
xcb_screen_t* screen = XCBScreenOfDisplay(connection, DefaultScreen(display));
|
||||||
|
|
||||||
// Check if the XRandR extension is present
|
// Check if the XRandR extension is present
|
||||||
int version;
|
xcb_query_extension_reply_t* randr_ext = xcb_query_extension_reply(connection, cookie, NULL);
|
||||||
if (XQueryExtension(display, "RANDR", &version, &version, &version))
|
if (randr_ext->present)
|
||||||
{
|
{
|
||||||
// Get the current configuration
|
// Get the current configuration
|
||||||
XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen));
|
xcb_generic_error_t* errors;
|
||||||
if (config)
|
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 available screen sizes
|
// Get the available screen sizes
|
||||||
int nbSizes;
|
xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config);
|
||||||
XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes);
|
if (sizes && (config->nSizes > 0))
|
||||||
if (sizes && (nbSizes > 0))
|
|
||||||
{
|
{
|
||||||
// Get the list of supported depths
|
// Get the list of supported depths
|
||||||
int nbDepths = 0;
|
xcb_depth_iterator_t iter = xcb_screen_allowed_depths_iterator(screen);
|
||||||
int* depths = XListDepths(display, screen, &nbDepths);
|
// Combine depths and sizes to fill the array of supported modes
|
||||||
if (depths && (nbDepths > 0))
|
for (; iter.rem; xcb_depth_next(&iter))
|
||||||
{
|
{
|
||||||
// Combine depths and sizes to fill the array of supported modes
|
for (int j = 0; j < config->nSizes; ++j)
|
||||||
for (int i = 0; i < nbDepths; ++i)
|
|
||||||
{
|
{
|
||||||
for (int j = 0; j < nbSizes; ++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, depths[i]);
|
|
||||||
|
|
||||||
// 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);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free the array of depths
|
|
||||||
XFree(depths);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free the configuration instance
|
|
||||||
XRRFreeScreenConfigInfo(config);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Failed to get the screen configuration
|
// Failed to get the screen configuration
|
||||||
err() << "Failed to retrieve the screen configuration 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 the configuration instance
|
||||||
|
free(errors);
|
||||||
|
free(config);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// XRandr extension is not supported: we cannot get the video modes
|
// XRandr extension is not supported: we cannot get the video modes
|
||||||
err() << "Failed to use the XRandR extension 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
|
// Close the connection with the X server
|
||||||
CloseDisplay(display);
|
CloseDisplay(display);
|
||||||
}
|
}
|
||||||
@ -121,37 +119,41 @@ VideoMode VideoModeImpl::getDesktopMode()
|
|||||||
|
|
||||||
// Open a connection with the X server
|
// Open a connection with the X server
|
||||||
Display* display = OpenDisplay();
|
Display* display = OpenDisplay();
|
||||||
|
xcb_connection_t* connection = XGetXCBConnection(display);
|
||||||
if (display)
|
if (display)
|
||||||
{
|
{
|
||||||
// Retrieve the default screen number
|
xcb_query_extension_cookie_t cookie = xcb_query_extension(connection, 5, "RANDR");
|
||||||
int screen = DefaultScreen(display);
|
// Retrieve the default screen
|
||||||
|
xcb_screen_t* screen = XCBScreenOfDisplay(connection, DefaultScreen(display));
|
||||||
|
|
||||||
// Check if the XRandR extension is present
|
// Check if the XRandR extension is present
|
||||||
int version;
|
xcb_query_extension_reply_t* randr_ext = xcb_query_extension_reply(connection, cookie, NULL);
|
||||||
if (XQueryExtension(display, "RANDR", &version, &version, &version))
|
if (randr_ext->present)
|
||||||
{
|
{
|
||||||
// Get the current configuration
|
// Get the current configuration
|
||||||
XRRScreenConfiguration* config = XRRGetScreenInfo(display, RootWindow(display, screen));
|
xcb_generic_error_t* errors;
|
||||||
if (config)
|
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
|
// Get the current video mode
|
||||||
Rotation currentRotation;
|
xcb_randr_mode_t currentMode = config->sizeID;
|
||||||
int currentMode = XRRConfigCurrentConfiguration(config, ¤tRotation);
|
|
||||||
|
|
||||||
// Get the available screen sizes
|
// Get the available screen sizes
|
||||||
int nbSizes;
|
int nbSizes = xcb_randr_get_screen_info_sizes_length(config);
|
||||||
XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes);
|
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, DefaultDepth(display, screen));
|
desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, screen->root_depth);
|
||||||
|
|
||||||
// Free the configuration instance
|
|
||||||
XRRFreeScreenConfigInfo(config);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Failed to get the screen configuration
|
// Failed to get the screen configuration
|
||||||
err() << "Failed to retrieve the screen configuration 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 the configuration instance
|
||||||
|
free(errors);
|
||||||
|
free(config);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -159,6 +161,7 @@ VideoMode VideoModeImpl::getDesktopMode()
|
|||||||
err() << "Failed to use the XRandR extension 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
|
// Close the connection with the X server
|
||||||
CloseDisplay(display);
|
CloseDisplay(display);
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -31,7 +31,7 @@
|
|||||||
#include <SFML/Window/Event.hpp>
|
#include <SFML/Window/Event.hpp>
|
||||||
#include <SFML/Window/WindowImpl.hpp>
|
#include <SFML/Window/WindowImpl.hpp>
|
||||||
#include <SFML/System/String.hpp>
|
#include <SFML/System/String.hpp>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib-xcb.h>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
|
|
||||||
@ -213,7 +213,7 @@ private:
|
|||||||
/// \return True if the event was processed, false if it was discarded
|
/// \return True if the event was processed, false if it was discarded
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool processEvent(XEvent windowEvent);
|
bool processEvent(xcb_generic_event_t *windowEvent);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Convert a X11 keysym to SFML key code
|
/// \brief Convert a X11 keysym to SFML key code
|
||||||
@ -223,23 +223,24 @@ private:
|
|||||||
/// \return Corresponding SFML key code
|
/// \return Corresponding SFML key code
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static Keyboard::Key keysymToSF(KeySym symbol);
|
static Keyboard::Key keysymToSF(xcb_keysym_t symbol);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
::Window m_window; ///< X11 structure defining our window
|
::Window m_window; ///< X11 structure defining our window
|
||||||
::Display* m_display; ///< Pointer to the display
|
::Display* m_display; ///< Pointer to the display
|
||||||
int m_screen; ///< Screen identifier
|
xcb_connection_t* m_connection; ///< Pointer to the xcb connection
|
||||||
XIM m_inputMethod; ///< Input method linked to the X display
|
xcb_screen_t* m_screen; ///< Screen identifier
|
||||||
XIC m_inputContext; ///< Input context used to get Unicode input in our window
|
XIM m_inputMethod; ///< Input method linked to the X display
|
||||||
bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
|
XIC m_inputContext; ///< Input context used to get unicode input in our window
|
||||||
Atom m_atomClose; ///< Atom used to identify the close event
|
bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
|
||||||
int m_oldVideoMode; ///< Video mode in use before we switch to fullscreen
|
Atom m_atomClose; ///< Atom used to identify the close event
|
||||||
Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hiding, we must create a transparent one
|
int m_oldVideoMode; ///< Video mode in use before we switch to fullscreen
|
||||||
bool m_keyRepeat; ///< Is the KeyRepeat feature enabled?
|
Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one
|
||||||
Vector2i m_previousSize; ///< Previous size of the window, to find if a ConfigureNotify event is a resize event (could be a move event only)
|
bool m_keyRepeat; ///< Is the KeyRepeat feature enabled?
|
||||||
bool m_useSizeHints; ///< Is the size of the window fixed with size hints?
|
Vector2i m_previousSize; ///< Previous size of the window, to find if a ConfigureNotify event is a resize event (could be a move event only)
|
||||||
|
bool m_useSizeHints; ///< Is the size of the window fixed with size hints?
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
Loading…
Reference in New Issue
Block a user