Skip to content

Commit

Permalink
Removed XCB dependencies (EWMH, ICCCM, Keysyms, Util), added XCB libr…
Browse files Browse the repository at this point in the history
…aries to FindSFML.cmake, fixed checking for X11 library checking for XRandR instead.
  • Loading branch information
binary1248 authored and eXpl0it3r committed Apr 5, 2015
1 parent 3d0ab05 commit 3ec672a
Show file tree
Hide file tree
Showing 7 changed files with 842 additions and 630 deletions.
23 changes: 13 additions & 10 deletions cmake/Modules/FindSFML.cmake
Expand Up @@ -281,22 +281,25 @@ if(SFML_STATIC_LIBRARIES)
if(NOT ${FIND_SFML_WINDOW_COMPONENT} EQUAL -1)

# find libraries
if(FIND_SFML_OS_LINUX)
if(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD)
find_sfml_dependency(X11_LIBRARY "X11" X11)
find_sfml_dependency(XRANDR_LIBRARY "Xrandr" Xrandr)
find_sfml_dependency(UDEV_LIBRARIES "UDev" udev)
find_sfml_dependency(LIBXCB_LIBRARIES "XCB" xcb libxcb)
find_sfml_dependency(X11_XCB_LIBRARY "X11-xcb" X11-xcb libX11-xcb)
find_sfml_dependency(XCB_RANDR_LIBRARY "xcb-randr" xcb-randr libxcb-randr)
find_sfml_dependency(XCB_IMAGE_LIBRARY "xcb-image" xcb-image libxcb-image)
endif()

if(FIND_SFML_OS_LINUX)
find_sfml_dependency(UDEV_LIBRARIES "UDev" udev libudev)
endif()

# update the list
if(FIND_SFML_OS_WINDOWS)
set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "opengl32" "winmm" "gdi32")
elseif(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD)
set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${XRANDR_LIBRARY})
if(FIND_SFML_OS_FREEBSD)
set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "usbhid")
else()
set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} ${UDEV_LIBRARIES})
endif()
elseif(FIND_SFML_OS_LINUX)
set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${LIBXCB_LIBRARIES} ${X11_XCB_LIBRARY} ${XCB_RANDR_LIBRARY} ${XCB_IMAGE_LIBRARY} ${UDEV_LIBRARIES})
elseif(FIND_SFML_OS_FREEBSD)
set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${LIBXCB_LIBRARIES} ${X11_XCB_LIBRARY} ${XCB_RANDR_LIBRARY} ${XCB_IMAGE_LIBRARY} "usbhid")
elseif(FIND_SFML_OS_MACOSX)
set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "-framework OpenGL -framework Foundation -framework AppKit -framework IOKit -framework Carbon")
endif()
Expand Down
10 changes: 5 additions & 5 deletions src/SFML/Window/CMakeLists.txt
Expand Up @@ -190,16 +190,16 @@ endif()
# find external libraries
if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
find_package(X11 REQUIRED)
if(NOT X11_Xrandr_FOUND)
message(FATAL_ERROR "Xrandr library not found")
if(NOT X11_FOUND)
message(FATAL_ERROR "X11 library not found")
endif()
include_directories(${X11_INCLUDE_DIR})
endif()
if(NOT SFML_OPENGL_ES)
find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
find_package(XCB COMPONENTS xlib_xcb icccm image randr util ewmh keysyms REQUIRED)
find_package(XCB COMPONENTS xlib_xcb image randr REQUIRED)
if(NOT LIBXCB_FOUND)
message(FATAL_ERROR "Xcb library not found")
endif()
Expand All @@ -224,9 +224,9 @@ endif()
if(SFML_OS_WINDOWS)
list(APPEND WINDOW_EXT_LIBS winmm gdi32)
elseif(SFML_OS_LINUX)
list(APPEND WINDOW_EXT_LIBS ${LIBXCB_LIBRARIES} ${UDEV_LIBRARIES})
list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${LIBXCB_LIBRARIES} ${UDEV_LIBRARIES})
elseif(SFML_OS_FREEBSD)
list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} ${LIBXCB_LIBRARIES} usbhid)
list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${LIBXCB_LIBRARIES} usbhid)
elseif(SFML_OS_MACOSX)
list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework AppKit -framework IOKit -framework Carbon")
elseif(SFML_OS_IOS)
Expand Down
231 changes: 231 additions & 0 deletions src/SFML/Window/Unix/Display.cpp
Expand Up @@ -27,15 +27,195 @@
////////////////////////////////////////////////////////////
#include <SFML/System/Err.hpp>
#include <SFML/Window/Unix/Display.hpp>
#include <SFML/Window/Unix/ScopedXcbPtr.hpp>
#include <X11/keysym.h>
#include <cassert>
#include <cstdlib>
#include <algorithm>
#include <map>


namespace
{
// The shared display and its reference counter
Display* sharedDisplay = NULL;
unsigned int referenceCount = 0;

typedef std::map<std::string, xcb_atom_t> AtomMap;
AtomMap atoms;

bool mapBuilt = false;
xcb_keycode_t firstKeycode = 255;
xcb_keycode_t lastKeycode = 0;

// We use a simple array instead of a map => constant time lookup
// xcb_keycode_t can only contain 256 distinct values
xcb_keysym_t keysymMap[256];

xcb_keysym_t keysymToLower(xcb_keysym_t keysym)
{
switch(keysym >> 8)
{
// Latin 1
case 0:
{
if ((keysym >= XK_A) && (keysym <= XK_Z))
return keysym + (XK_a - XK_A);
else if ((keysym >= XK_Agrave) && (keysym <= XK_Odiaeresis))
return keysym + (XK_agrave - XK_Agrave);
else if ((keysym >= XK_Ooblique) && (keysym <= XK_Thorn))
return keysym + (XK_oslash - XK_Ooblique);
break;
}

// Latin 2
case 1:
{
if (keysym == XK_Aogonek)
return XK_aogonek;
else if (keysym >= XK_Lstroke && keysym <= XK_Sacute)
return keysym + (XK_lstroke - XK_Lstroke);
else if (keysym >= XK_Scaron && keysym <= XK_Zacute)
return keysym + (XK_scaron - XK_Scaron);
else if (keysym >= XK_Zcaron && keysym <= XK_Zabovedot)
return keysym + (XK_zcaron - XK_Zcaron);
else if (keysym >= XK_Racute && keysym <= XK_Tcedilla)
return keysym + (XK_racute - XK_Racute);
break;
}

// Latin 3
case 2:
{
if (keysym >= XK_Hstroke && keysym <= XK_Hcircumflex)
return keysym + (XK_hstroke - XK_Hstroke);
else if (keysym >= XK_Gbreve && keysym <= XK_Jcircumflex)
return keysym + (XK_gbreve - XK_Gbreve);
else if (keysym >= XK_Cabovedot && keysym <= XK_Scircumflex)
return keysym + (XK_cabovedot - XK_Cabovedot);
break;
}

// Latin 4
case 3:
{
if (keysym >= XK_Rcedilla && keysym <= XK_Tslash)
return keysym + (XK_rcedilla - XK_Rcedilla);
else if (keysym == XK_ENG)
return XK_eng;
else if (keysym >= XK_Amacron && keysym <= XK_Umacron)
return keysym + (XK_amacron - XK_Amacron);
break;
}

// Cyrillic
case 6:
{
if (keysym >= XK_Serbian_DJE && keysym <= XK_Serbian_DZE)
return keysym - (XK_Serbian_DJE - XK_Serbian_dje);
else if (keysym >= XK_Cyrillic_YU && keysym <= XK_Cyrillic_HARDSIGN)
return keysym - (XK_Cyrillic_YU - XK_Cyrillic_yu);
break;
}

// Greek
case 7:
{
if (keysym >= XK_Greek_ALPHAaccent && keysym <= XK_Greek_OMEGAaccent)
return keysym + (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
else if (keysym >= XK_Greek_ALPHA && keysym <= XK_Greek_OMEGA)
return keysym + (XK_Greek_alpha - XK_Greek_ALPHA);
break;
}

// Armenian
case 0x14:
{
if (keysym >= XK_Armenian_AYB && keysym <= XK_Armenian_fe) {
return (keysym | 1);
}
break;
}

default:
{
break;
}
}

return keysym;
}

void buildMap()
{
// Open a connection with the X server
xcb_connection_t* connection = sf::priv::OpenConnection();

firstKeycode = xcb_get_setup(connection)->min_keycode;
lastKeycode = xcb_get_setup(connection)->max_keycode;

sf::priv::ScopedXcbPtr<xcb_generic_error_t> error(NULL);

sf::priv::ScopedXcbPtr<xcb_get_keyboard_mapping_reply_t> keyboardMapping(xcb_get_keyboard_mapping_reply(
connection,
xcb_get_keyboard_mapping(
connection,
firstKeycode,
lastKeycode - firstKeycode + 1
),
&error
));

sf::priv::CloseConnection(connection);

if (error || !keyboardMapping)
{
sf::err() << "Failed to get keyboard mapping" << std::endl;
return;
}

uint8_t keysymsPerKeycode = keyboardMapping->keysyms_per_keycode;

if (!keysymsPerKeycode)
{
sf::err() << "Error: No keysyms per keycode" << std::endl;
return;
}

const xcb_keysym_t* keysyms = xcb_get_keyboard_mapping_keysyms(keyboardMapping.get());

if (!keysyms)
{
sf::err() << "Failed to get keyboard mapping keysyms" << std::endl;
return;
}

xcb_keycode_t range = lastKeycode - firstKeycode + 1;

std::fill(keysymMap, keysymMap + 256, XK_VoidSymbol);

for (xcb_keycode_t i = firstKeycode; ; ++i)
{
const xcb_keysym_t* keysym = &keysyms[(i - firstKeycode) * keysymsPerKeycode];

if ((keysymsPerKeycode == 1) || (keysym[1] == XCB_NO_SYMBOL))
{
keysymMap[i] = keysymToLower(keysym[0]);

if (i == lastKeycode)
break;

continue;
}

keysymMap[i] = keysym[0];

if (i == lastKeycode)
break;
}

mapBuilt = true;
}
}

namespace sf
Expand Down Expand Up @@ -80,13 +260,15 @@ void CloseDisplay(Display* 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)
{
Expand All @@ -101,13 +283,15 @@ xcb_screen_t* XCBScreenOfDisplay(xcb_connection_t* connection, int screen_nbr)
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)
{
Expand All @@ -118,6 +302,53 @@ xcb_window_t XCBDefaultRootWindow(xcb_connection_t* connection)
return 0;
}


////////////////////////////////////////////////////////////
xcb_atom_t getAtom(const std::string& name, bool onlyIfExists)
{
AtomMap::const_iterator iter = atoms.find(name);

if (iter != atoms.end())
return iter->second;

ScopedXcbPtr<xcb_generic_error_t> error(NULL);

xcb_connection_t* connection = OpenConnection();

ScopedXcbPtr<xcb_intern_atom_reply_t> reply(xcb_intern_atom_reply(
connection,
xcb_intern_atom(
connection,
onlyIfExists,
name.size(),
name.c_str()
),
&error
));

CloseConnection(connection);

if (error || !reply)
{
err() << "Failed to get " << name << " atom." << std::endl;
return XCB_ATOM_NONE;
}

atoms[name] = reply->atom;

return reply->atom;
}


////////////////////////////////////////////////////////////
const xcb_keysym_t* getKeysymMap()
{
if (!mapBuilt)
buildMap();

return keysymMap;
}

} // namespace priv

} // namespace sf
23 changes: 23 additions & 0 deletions src/SFML/Window/Unix/Display.hpp
Expand Up @@ -29,6 +29,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <X11/Xlib-xcb.h>
#include <string>


namespace sf
Expand Down Expand Up @@ -104,6 +105,28 @@ xcb_screen_t* XCBDefaultScreen(xcb_connection_t* connection);
////////////////////////////////////////////////////////////
xcb_window_t XCBDefaultRootWindow(xcb_connection_t* connection);

////////////////////////////////////////////////////////////
/// \brief Get the atom with the specified name
///
/// \param name Name of the atom
/// \param onlyIfExists Don't try to create the atom if it doesn't already exist
///
/// \return Atom if it exists or XCB_ATOM_NONE (0) if it doesn't
///
////////////////////////////////////////////////////////////
xcb_atom_t getAtom(const std::string& name, bool onlyIfExists = false);

////////////////////////////////////////////////////////////
/// \brief Get the keycode to keysym map
///
/// Contains 255 values. Use the keycode as the index
/// into the array to retrieve its keysym.
///
/// \return Keycode to keysym map
///
////////////////////////////////////////////////////////////
const xcb_keysym_t* getKeysymMap();

} // namespace priv

} // namespace sf
Expand Down

0 comments on commit 3ec672a

Please sign in to comment.