summaryrefslogtreecommitdiff
path: root/src/SFML/Window/Linux
diff options
context:
space:
mode:
Diffstat (limited to 'src/SFML/Window/Linux')
-rw-r--r--src/SFML/Window/Linux/.svn/all-wcprops41
-rw-r--r--src/SFML/Window/Linux/.svn/entries232
-rw-r--r--src/SFML/Window/Linux/.svn/format1
-rw-r--r--src/SFML/Window/Linux/.svn/text-base/Joystick.cpp.svn-base125
-rw-r--r--src/SFML/Window/Linux/.svn/text-base/Joystick.hpp.svn-base92
-rw-r--r--src/SFML/Window/Linux/.svn/text-base/VideoModeSupport.cpp.svn-base135
-rw-r--r--src/SFML/Window/Linux/.svn/text-base/VideoModeSupport.hpp.svn-base69
-rw-r--r--src/SFML/Window/Linux/.svn/text-base/WindowImplX11.cpp.svn-base1222
-rw-r--r--src/SFML/Window/Linux/.svn/text-base/WindowImplX11.hpp.svn-base277
-rw-r--r--[-rwxr-xr-x]src/SFML/Window/Linux/Joystick.cpp4
-rw-r--r--[-rwxr-xr-x]src/SFML/Window/Linux/Joystick.hpp0
-rw-r--r--[-rwxr-xr-x]src/SFML/Window/Linux/VideoModeSupport.cpp0
-rw-r--r--[-rwxr-xr-x]src/SFML/Window/Linux/VideoModeSupport.hpp0
-rw-r--r--[-rwxr-xr-x]src/SFML/Window/Linux/WindowImplX11.cpp191
-rw-r--r--[-rwxr-xr-x]src/SFML/Window/Linux/WindowImplX11.hpp25
15 files changed, 2378 insertions, 36 deletions
diff --git a/src/SFML/Window/Linux/.svn/all-wcprops b/src/SFML/Window/Linux/.svn/all-wcprops
new file mode 100644
index 0000000..87178e6
--- /dev/null
+++ b/src/SFML/Window/Linux/.svn/all-wcprops
@@ -0,0 +1,41 @@
+K 25
+svn:wc:ra_dav:version-url
+V 48
+/svnroot/sfml/!svn/ver/870/src/SFML/Window/Linux
+END
+Joystick.cpp
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/svnroot/sfml/!svn/ver/760/src/SFML/Window/Linux/Joystick.cpp
+END
+WindowImplX11.cpp
+K 25
+svn:wc:ra_dav:version-url
+V 66
+/svnroot/sfml/!svn/ver/870/src/SFML/Window/Linux/WindowImplX11.cpp
+END
+Joystick.hpp
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/svnroot/sfml/!svn/ver/558/src/SFML/Window/Linux/Joystick.hpp
+END
+VideoModeSupport.cpp
+K 25
+svn:wc:ra_dav:version-url
+V 69
+/svnroot/sfml/!svn/ver/220/src/SFML/Window/Linux/VideoModeSupport.cpp
+END
+WindowImplX11.hpp
+K 25
+svn:wc:ra_dav:version-url
+V 66
+/svnroot/sfml/!svn/ver/868/src/SFML/Window/Linux/WindowImplX11.hpp
+END
+VideoModeSupport.hpp
+K 25
+svn:wc:ra_dav:version-url
+V 69
+/svnroot/sfml/!svn/ver/220/src/SFML/Window/Linux/VideoModeSupport.hpp
+END
diff --git a/src/SFML/Window/Linux/.svn/entries b/src/SFML/Window/Linux/.svn/entries
new file mode 100644
index 0000000..bac686f
--- /dev/null
+++ b/src/SFML/Window/Linux/.svn/entries
@@ -0,0 +1,232 @@
+9
+
+dir
+915
+https://sfml.svn.sourceforge.net/svnroot/sfml/src/SFML/Window/Linux
+https://sfml.svn.sourceforge.net/svnroot/sfml
+
+
+
+2008-09-12T13:25:22.116968Z
+870
+laurentgom
+
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+4e206d99-4929-0410-ac5d-dfc041789085
+
+Joystick.cpp
+file
+
+
+
+
+2008-11-01T16:23:42.000000Z
+4222d799b73145f557f7a683bae14a40
+2008-07-11T15:14:47.150571Z
+760
+laurentgom
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4086
+
+WindowImplX11.cpp
+file
+
+
+
+
+2008-11-01T16:23:42.000000Z
+14162cbcff8ae09f1be2496c105a72d5
+2008-09-12T13:25:22.116968Z
+870
+laurentgom
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+45186
+
+Joystick.hpp
+file
+
+
+
+
+2008-11-01T16:23:42.000000Z
+2ff5dd2454d12d3f39b68e7931de5df0
+2008-03-27T11:05:47.823854Z
+558
+laurentgom
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3308
+
+VideoModeSupport.cpp
+file
+
+
+
+
+2008-11-01T16:23:42.000000Z
+79df092b866a3b012cf8586183919cc1
+2007-08-27T22:12:57.225756Z
+220
+laurentgom
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4874
+
+WindowImplX11.hpp
+file
+
+
+
+
+2008-11-01T16:23:42.000000Z
+0b9cbeb52dbd6d159e7a1e9786f97a3e
+2008-09-12T13:12:04.328200Z
+868
+laurentgom
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+11232
+
+VideoModeSupport.hpp
+file
+
+
+
+
+2008-11-01T16:23:42.000000Z
+fa45f722c7b07f04c2f91847ca517c51
+2007-08-27T22:12:57.225756Z
+220
+laurentgom
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2409
+
diff --git a/src/SFML/Window/Linux/.svn/format b/src/SFML/Window/Linux/.svn/format
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/src/SFML/Window/Linux/.svn/format
@@ -0,0 +1 @@
+9
diff --git a/src/SFML/Window/Linux/.svn/text-base/Joystick.cpp.svn-base b/src/SFML/Window/Linux/.svn/text-base/Joystick.cpp.svn-base
new file mode 100644
index 0000000..ba85ccd
--- /dev/null
+++ b/src/SFML/Window/Linux/.svn/text-base/Joystick.cpp.svn-base
@@ -0,0 +1,125 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented;
+// you must not claim that you wrote the original software.
+// If you use this software in a product, an acknowledgment
+// in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such,
+// and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Joystick.hpp>
+#include <linux/joystick.h>
+#include <fcntl.h>
+#include <sstream>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// Initialize the instance and bind it to a physical joystick
+////////////////////////////////////////////////////////////
+void Joystick::Initialize(unsigned int Index)
+{
+ // Initial state
+ myNbAxes = 0;
+ myNbButtons = 0;
+ for (int i = 0; i < Joy::Count; ++i)
+ myState.Axis[i] = 0.f;
+ for (int i = 0; i < JoystickState::MaxButtons; ++i)
+ myState.Buttons[i] = false;
+
+ // Open the joystick handle
+ std::ostringstream oss;
+ oss << "/dev/input/js" << Index;
+ myDescriptor = open(oss.str().c_str(), O_RDONLY);
+ if (myDescriptor > 0)
+ {
+ // Use non-blocking mode
+ fcntl(myDescriptor, F_SETFL, O_NONBLOCK);
+
+ // Get number of axes and buttons
+ char NbAxes, NbButtons;
+ ioctl(myDescriptor, JSIOCGAXES, &NbAxes);
+ ioctl(myDescriptor, JSIOCGBUTTONS, &NbButtons);
+ myNbAxes = NbAxes;
+ myNbButtons = NbButtons;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+/// Update the current joystick and return its new state
+////////////////////////////////////////////////////////////
+JoystickState Joystick::UpdateState()
+{
+ if (myDescriptor > 0)
+ {
+ js_event JoyState;
+ while (read(myDescriptor, &JoyState, sizeof(JoyState)) > 0)
+ {
+ switch (JoyState.type & ~JS_EVENT_INIT)
+ {
+ // An axis has been moved
+ case JS_EVENT_AXIS :
+ {
+ if (JoyState.number < Joy::Count)
+ myState.Axis[JoyState.number] = JoyState.value * 100.f / 32767.f;
+ break;
+ }
+
+ // A button has been pressed
+ case JS_EVENT_BUTTON :
+ {
+ if (JoyState.number < GetButtonsCount())
+ myState.Buttons[JoyState.number] = (JoyState.value != 0);
+ break;
+ }
+ }
+ }
+ }
+
+ return myState;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get the number of axes supported by the joystick
+////////////////////////////////////////////////////////////
+unsigned int Joystick::GetAxesCount() const
+{
+ return myNbAxes;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get the number of buttons supported by the joystick
+////////////////////////////////////////////////////////////
+unsigned int Joystick::GetButtonsCount() const
+{
+ return myNbButtons;
+}
+
+
+} // namespace priv
+
+} // namespace sf
diff --git a/src/SFML/Window/Linux/.svn/text-base/Joystick.hpp.svn-base b/src/SFML/Window/Linux/.svn/text-base/Joystick.hpp.svn-base
new file mode 100644
index 0000000..1c1e4a2
--- /dev/null
+++ b/src/SFML/Window/Linux/.svn/text-base/Joystick.hpp.svn-base
@@ -0,0 +1,92 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented;
+// you must not claim that you wrote the original software.
+// If you use this software in a product, an acknowledgment
+// in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such,
+// and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_JOYSTICKLINUX_HPP
+#define SFML_JOYSTICKLINUX_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// Linux implementation of Joystick
+////////////////////////////////////////////////////////////
+class Joystick
+{
+public :
+
+ ////////////////////////////////////////////////////////////
+ /// Initialize the instance and bind it to a physical joystick
+ ///
+ /// \param Index : Index of the physical joystick to bind to
+ ///
+ ////////////////////////////////////////////////////////////
+ void Initialize(unsigned int Index);
+
+ ////////////////////////////////////////////////////////////
+ /// Update the current joystick and return its new state
+ ///
+ /// \return Current state of the joystick
+ ///
+ ////////////////////////////////////////////////////////////
+ JoystickState UpdateState();
+
+ ////////////////////////////////////////////////////////////
+ /// Get the number of axes supported by the joystick
+ ///
+ /// \return Number of axis
+ ///
+ ////////////////////////////////////////////////////////////
+ unsigned int GetAxesCount() const;
+
+ ////////////////////////////////////////////////////////////
+ /// Get the number of buttons supported by the joystick
+ ///
+ /// \return Number of buttons
+ ///
+ ////////////////////////////////////////////////////////////
+ unsigned int GetButtonsCount() const;
+
+private :
+
+ ////////////////////////////////////////////////////////////
+ // Member data
+ ////////////////////////////////////////////////////////////
+ int myDescriptor; ///< Linux descriptor of the joystick
+ unsigned int myNbAxes; ///< Number of axis supported by the joystick
+ unsigned int myNbButtons; ///< Number of buttons supported by the joystick
+ JoystickState myState; ///< Current state of the joystick
+};
+
+} // namespace priv
+
+} // namespace sf
+
+
+#endif // SFML_JOYSTICKLINUX_HPP
diff --git a/src/SFML/Window/Linux/.svn/text-base/VideoModeSupport.cpp.svn-base b/src/SFML/Window/Linux/.svn/text-base/VideoModeSupport.cpp.svn-base
new file mode 100644
index 0000000..d328702
--- /dev/null
+++ b/src/SFML/Window/Linux/.svn/text-base/VideoModeSupport.cpp.svn-base
@@ -0,0 +1,135 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented;
+// you must not claim that you wrote the original software.
+// If you use this software in a product, an acknowledgment
+// in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such,
+// and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Linux/VideoModeSupport.hpp>
+#include <SFML/Window/Linux/WindowImplX11.hpp>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h>
+#include <algorithm>
+#include <iostream>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// Get supported video modes
+////////////////////////////////////////////////////////////
+void VideoModeSupport::GetSupportedVideoModes(std::vector<VideoMode>& Modes)
+{
+ // First, clear array to fill
+ Modes.clear();
+
+ // Get the display and screen from sfWindowImplUnix
+ WindowImplX11::OpenDisplay(false);
+ Display* Disp = WindowImplX11::ourDisplay;
+ int Screen = WindowImplX11::ourScreen;
+
+ // Check if the XRandR extension is present
+ int Version;
+ if (XQueryExtension(Disp, "RANDR", &Version, &Version, &Version))
+ {
+ // Get the current configuration
+ XRRScreenConfiguration* Config = XRRGetScreenInfo(Disp, RootWindow(Disp, Screen));
+ if (Config)
+ {
+ // Get the available screen sizes
+ int NbSizes;
+ XRRScreenSize* Sizes = XRRConfigSizes(Config, &NbSizes);
+ if (Sizes && (NbSizes > 0))
+ {
+ // Add them to the video modes array
+ for (int i = 0; i < NbSizes; ++i)
+ {
+ // Convert to sfVideoMode
+ VideoMode Mode(Sizes[i].width, Sizes[i].height, 32);
+
+ // Add it only if it is not already in the array
+ if (std::find(Modes.begin(), Modes.end(), Mode) == Modes.end())
+ Modes.push_back(Mode);
+ }
+ }
+
+ // Free the configuration instance
+ XRRFreeScreenConfigInfo(Config);
+ }
+ else
+ {
+ // Failed to get the screen configuration
+ std::cerr << "Failed to get the list of available video modes" << std::endl;
+ }
+ }
+ else
+ {
+ // XRandr extension is not supported : we cannot get the video modes
+ std::cerr << "Failed to get the list of available video modes" << std::endl;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+/// Get current desktop video mode
+////////////////////////////////////////////////////////////
+VideoMode VideoModeSupport::GetDesktopVideoMode()
+{
+ VideoMode DesktopMode;
+
+ // Get the display and screen from sfWindowImplUnix
+ WindowImplX11::OpenDisplay(false);
+ Display* Disp = WindowImplX11::ourDisplay;
+ int Screen = WindowImplX11::ourScreen;
+
+ // Check if the XRandR extension is present
+ int Version;
+ if (XQueryExtension(Disp, "RANDR", &Version, &Version, &Version))
+ {
+ // Get the current configuration
+ XRRScreenConfiguration* Config = XRRGetScreenInfo(Disp, RootWindow(Disp, Screen));
+ if (Config)
+ {
+ // Get the current video mode
+ Rotation CurrentRotation;
+ int CurrentMode = XRRConfigCurrentConfiguration(Config, &CurrentRotation);
+
+ // Get the available screen sizes
+ int NbSizes;
+ XRRScreenSize* Sizes = XRRConfigSizes(Config, &NbSizes);
+ if (Sizes && (NbSizes > 0))
+ DesktopMode = VideoMode(Sizes[CurrentMode].width, Sizes[CurrentMode].height, 32);
+
+ // Free the configuration instance
+ XRRFreeScreenConfigInfo(Config);
+ }
+ }
+
+ return DesktopMode;
+}
+
+} // namespace priv
+
+} // namespace sf
diff --git a/src/SFML/Window/Linux/.svn/text-base/VideoModeSupport.hpp.svn-base b/src/SFML/Window/Linux/.svn/text-base/VideoModeSupport.hpp.svn-base
new file mode 100644
index 0000000..87291fc
--- /dev/null
+++ b/src/SFML/Window/Linux/.svn/text-base/VideoModeSupport.hpp.svn-base
@@ -0,0 +1,69 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented;
+// you must not claim that you wrote the original software.
+// If you use this software in a product, an acknowledgment
+// in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such,
+// and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_VIDEOMODESUPPORTLINUX_HPP
+#define SFML_VIDEOMODESUPPORTLINUX_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/VideoMode.hpp>
+#include <vector>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+/// Linux implementation of VideoModeSupport
+/// Give access to video mode related OS-specific functions
+////////////////////////////////////////////////////////////
+class VideoModeSupport
+{
+public :
+
+ ////////////////////////////////////////////////////////////
+ /// Get supported video modes
+ ///
+ /// \param Modes : Array to fill with available video modes
+ ///
+ ////////////////////////////////////////////////////////////
+ static void GetSupportedVideoModes(std::vector<VideoMode>& Modes);
+
+ ////////////////////////////////////////////////////////////
+ /// Get current desktop video mode
+ ///
+ /// \return Current desktop video mode
+ ///
+ ////////////////////////////////////////////////////////////
+ static VideoMode GetDesktopVideoMode();
+};
+
+} // namespace priv
+
+} // namespace sf
+
+
+#endif // SFML_VIDEOMODESUPPORTLINUX_HPP
diff --git a/src/SFML/Window/Linux/.svn/text-base/WindowImplX11.cpp.svn-base b/src/SFML/Window/Linux/.svn/text-base/WindowImplX11.cpp.svn-base
new file mode 100644
index 0000000..0659089
--- /dev/null
+++ b/src/SFML/Window/Linux/.svn/text-base/WindowImplX11.cpp.svn-base
@@ -0,0 +1,1222 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented;
+// you must not claim that you wrote the original software.
+// If you use this software in a product, an acknowledgment
+// in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such,
+// and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/WindowStyle.hpp> // important to be included first (conflict with None)
+#include <SFML/Window/Linux/WindowImplX11.hpp>
+#include <SFML/Window/glext/glxext.h>
+#include <SFML/Window/glext/glext.h>
+#include <SFML/System/Unicode.hpp>
+#include <X11/keysym.h>
+#include <X11/extensions/Xrandr.h>
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+// Static member data
+////////////////////////////////////////////////////////////
+Display* WindowImplX11::ourDisplay = NULL;
+int WindowImplX11::ourScreen = 0;
+WindowImplX11* WindowImplX11::ourFullscreenWindow = NULL;
+unsigned int WindowImplX11::ourWindowsCount = 0;
+XIM WindowImplX11::ourInputMethod = NULL;
+unsigned long WindowImplX11::ourEventMask = FocusChangeMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
+ PointerMotionMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask |
+ EnterWindowMask | LeaveWindowMask;
+
+
+////////////////////////////////////////////////////////////
+/// Default constructor
+/// (creates a dummy window to provide a valid OpenGL context)
+////////////////////////////////////////////////////////////
+WindowImplX11::WindowImplX11() :
+myWindow (0),
+myIsExternal (false),
+myGLContext (NULL),
+myAtomClose (0),
+myOldVideoMode(-1),
+myHiddenCursor(0),
+myInputContext(NULL),
+myKeyRepeat (true)
+{
+ // Open the display at first call
+ if (!OpenDisplay())
+ return;
+
+ // Use small dimensions
+ myWidth = 1;
+ myHeight = 1;
+
+ // Create the rendering context
+ XVisualInfo Visual;
+ WindowSettings Params(0, 0, 0);
+ if (!CreateContext(VideoMode(myWidth, myHeight, 32), Visual, Params))
+ return;
+
+ // Create a new color map with the chosen visual
+ Colormap ColMap = XCreateColormap(ourDisplay, RootWindow(ourDisplay, ourScreen), Visual.visual, AllocNone);
+
+ // Define the window attributes
+ XSetWindowAttributes Attributes;
+ Attributes.colormap = ColMap;
+
+ // Create a dummy window (disabled and hidden)
+ myWindow = XCreateWindow(ourDisplay,
+ RootWindow(ourDisplay, ourScreen),
+ 0, 0,
+ myWidth, myHeight,
+ 0,
+ Visual.depth,
+ InputOutput,
+ Visual.visual,
+ CWColormap, &Attributes);
+
+ // Don't activate the dummy context by default
+}
+
+
+////////////////////////////////////////////////////////////
+/// Create the window implementation from an existing control
+////////////////////////////////////////////////////////////
+WindowImplX11::WindowImplX11(WindowHandle Handle, WindowSettings& Params) :
+myWindow (0),
+myIsExternal (true),
+myGLContext (NULL),
+myAtomClose (0),
+myOldVideoMode(-1),
+myHiddenCursor(0),
+myInputContext(NULL),
+myKeyRepeat (true)
+{
+ // Open the display at first call
+ if (!OpenDisplay())
+ return;
+
+ // Save the window handle
+ myWindow = Handle;
+
+ if (myWindow)
+ {
+ // Get the window size
+ XWindowAttributes WindowAttributes;
+ if (XGetWindowAttributes(ourDisplay, myWindow, &WindowAttributes) == 0)
+ {
+ std::cerr << "Failed to get the window attributes" << std::endl;
+ return;
+ }
+ myWidth = WindowAttributes.width;
+ myHeight = WindowAttributes.height;
+
+ // Setup the visual infos to match
+ XVisualInfo Template;
+ Template.depth = WindowAttributes.depth;
+ Template.visualid = XVisualIDFromVisual(WindowAttributes.visual);
+ unsigned long Mask = VisualDepthMask | VisualIDMask;
+
+ // Create the rendering context
+ VideoMode Mode(myWidth, myHeight, VideoMode::GetDesktopMode().BitsPerPixel);
+ XVisualInfo Visual;
+ if (!CreateContext(Mode, Visual, Params, Template, Mask))
+ return;
+
+ // Create a new color map with the chosen visual
+ Colormap ColMap = XCreateColormap(ourDisplay, RootWindow(ourDisplay, ourScreen), Visual.visual, AllocNone);
+ XSetWindowColormap(ourDisplay, myWindow, ColMap);
+
+ // Make sure the window is listening to all the requiered events
+ XSelectInput(ourDisplay, myWindow, ourEventMask & ~ButtonPressMask);
+
+ // Do some common initializations
+ Initialize();
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+/// Create the window implementation
+////////////////////////////////////////////////////////////
+WindowImplX11::WindowImplX11(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, WindowSettings& Params) :
+myWindow (0),
+myIsExternal (false),
+myGLContext (NULL),
+myAtomClose (0),
+myOldVideoMode(-1),
+myHiddenCursor(0),
+myInputContext(NULL),
+myKeyRepeat (true)
+{
+ // Open the display at first call
+ if (!OpenDisplay())
+ return;
+
+ // Compute position and size
+ int Left, Top;
+ bool Fullscreen = (WindowStyle & Style::Fullscreen) != 0;
+ if (!Fullscreen)
+ {
+ Left = (DisplayWidth(ourDisplay, ourScreen) - Mode.Width) / 2;
+ Top = (DisplayHeight(ourDisplay, ourScreen) - Mode.Height) / 2;
+ }
+ else
+ {
+ Left = 0;
+ Top = 0;
+ }
+ int Width = myWidth = Mode.Width;
+ int Height = myHeight = Mode.Height;
+
+ // Switch to fullscreen if necessary
+ if (Fullscreen)
+ SwitchToFullscreen(Mode);
+
+ // Create the rendering context
+ XVisualInfo Visual;
+ if (!CreateContext(Mode, Visual, Params))
+ return;
+
+ // Create a new color map with the chosen visual
+ Colormap ColMap = XCreateColormap(ourDisplay, RootWindow(ourDisplay, ourScreen), Visual.visual, AllocNone);
+
+ // Define the window attributes
+ XSetWindowAttributes Attributes;
+ Attributes.event_mask = ourEventMask;
+ Attributes.colormap = ColMap;
+ Attributes.override_redirect = Fullscreen;
+
+ // Create the window
+ myWindow = XCreateWindow(ourDisplay,
+ RootWindow(ourDisplay, ourScreen),
+ Left, Top,
+ Width, Height,
+ 0,
+ Visual.depth,
+ InputOutput,
+ Visual.visual,
+ CWEventMask | CWColormap | CWOverrideRedirect, &Attributes);
+ if (!myWindow)
+ {
+ std::cerr << "Failed to create window" << std::endl;
+ return;
+ }
+
+ // Set the window's name
+ XStoreName(ourDisplay, myWindow, Title.c_str());
+
+ // Set the window's style (tell the windows manager to change our window's decorations and functions according to the requested style)
+ if (!Fullscreen)
+ {
+ Atom WMHintsAtom = XInternAtom(ourDisplay, "_MOTIF_WM_HINTS", false);
+ if (WMHintsAtom)
+ {
+ static const unsigned long MWM_HINTS_FUNCTIONS = 1 << 0;
+ static const unsigned long MWM_HINTS_DECORATIONS = 1 << 1;
+
+ //static const unsigned long MWM_DECOR_ALL = 1 << 0;
+ static const unsigned long MWM_DECOR_BORDER = 1 << 1;
+ static const unsigned long MWM_DECOR_RESIZEH = 1 << 2;
+ static const unsigned long MWM_DECOR_TITLE = 1 << 3;
+ static const unsigned long MWM_DECOR_MENU = 1 << 4;
+ static const unsigned long MWM_DECOR_MINIMIZE = 1 << 5;
+ static const unsigned long MWM_DECOR_MAXIMIZE = 1 << 6;
+
+ //static const unsigned long MWM_FUNC_ALL = 1 << 0;
+ static const unsigned long MWM_FUNC_RESIZE = 1 << 1;
+ static const unsigned long MWM_FUNC_MOVE = 1 << 2;
+ static const unsigned long MWM_FUNC_MINIMIZE = 1 << 3;
+ static const unsigned long MWM_FUNC_MAXIMIZE = 1 << 4;
+ static const unsigned long MWM_FUNC_CLOSE = 1 << 5;
+
+ struct WMHints
+ {
+ unsigned long Flags;
+ unsigned long Functions;
+ unsigned long Decorations;
+ long InputMode;
+ unsigned long State;
+ };
+
+ WMHints Hints;
+ Hints.Flags = MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS;
+ Hints.Decorations = 0;
+ Hints.Functions = 0;
+
+ if (WindowStyle & Style::Titlebar)
+ {
+ Hints.Decorations |= MWM_DECOR_BORDER | MWM_DECOR_TITLE | MWM_DECOR_MINIMIZE | MWM_DECOR_MENU;
+ Hints.Functions |= MWM_FUNC_MOVE | MWM_FUNC_MINIMIZE;
+ }
+ if (WindowStyle & Style::Resize)
+ {
+ Hints.Decorations |= MWM_DECOR_MAXIMIZE | MWM_DECOR_RESIZEH;
+ Hints.Functions |= MWM_FUNC_MAXIMIZE | MWM_FUNC_RESIZE;
+ }
+ if (WindowStyle & Style::Close)
+ {
+ Hints.Decorations |= 0;
+ Hints.Functions |= MWM_FUNC_CLOSE;
+ }
+
+ const unsigned char* HintsPtr = reinterpret_cast<const unsigned char*>(&Hints);
+ XChangeProperty(ourDisplay, myWindow, WMHintsAtom, WMHintsAtom, 32, PropModeReplace, HintsPtr, 5);
+ }
+
+ // This is a hack to force some windows managers to disable resizing
+ if (!(WindowStyle & Style::Resize))
+ {
+ XSizeHints XSizeHints;
+ XSizeHints.flags = PMinSize | PMaxSize;
+ XSizeHints.min_width = XSizeHints.max_width = Width;
+ XSizeHints.min_height = XSizeHints.max_height = Height;
+ XSetWMNormalHints(ourDisplay, myWindow, &XSizeHints);
+ }
+ }
+
+ // Do some common initializations
+ Initialize();
+
+ // In fullscreen mode, we must grab keyboard and mouse inputs
+ if (Fullscreen)
+ {
+ XGrabPointer(ourDisplay, myWindow, true, 0, GrabModeAsync, GrabModeAsync, myWindow, None, CurrentTime);
+ XGrabKeyboard(ourDisplay, myWindow, true, GrabModeAsync, GrabModeAsync, CurrentTime);
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+/// Destructor
+////////////////////////////////////////////////////////////
+WindowImplX11::~WindowImplX11()
+{
+ // Cleanup graphical resources
+ CleanUp();
+
+ // Destroy the input context
+ if (myInputContext)
+ {
+ XDestroyIC(myInputContext);
+ }
+
+ // Destroy the window
+ if (myWindow && !myIsExternal)
+ {
+ XDestroyWindow(ourDisplay, myWindow);
+ XFlush(ourDisplay);
+ }
+
+ // Close the display
+ CloseDisplay();
+}
+
+
+////////////////////////////////////////////////////////////
+/// Check if there's an active context on the current thread
+////////////////////////////////////////////////////////////
+bool WindowImplX11::IsContextActive()
+{
+ return glXGetCurrentContext() != NULL;
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::Display
+////////////////////////////////////////////////////////////
+void WindowImplX11::Display()
+{
+ if (myWindow && myGLContext)
+ glXSwapBuffers(ourDisplay, myWindow);
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::ProcessEvents
+////////////////////////////////////////////////////////////
+void WindowImplX11::ProcessEvents()
+{
+ // Process any event in the queue matching our window
+ XEvent Event;
+ while (XCheckIfEvent(ourDisplay, &Event, &WindowImplX11::CheckEvent, reinterpret_cast<XPointer>(myWindow)))
+ {
+ // Filter repeated key events
+ if (Event.type == KeyRelease)
+ {
+ if (XPending(ourDisplay))
+ {
+ XEvent NextEvent;
+ XPeekEvent(ourDisplay, &NextEvent);
+ if ((NextEvent.type == KeyPress) &&
+ (NextEvent.xkey.keycode == Event.xkey.keycode) &&
+ (NextEvent.xkey.time == Event.xkey.time))
+ {
+ if (!myKeyRepeat)
+ XNextEvent(ourDisplay, &NextEvent);
+ continue;
+ }
+ }
+ }
+
+ ProcessEvent(Event);
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::SetActive
+////////////////////////////////////////////////////////////
+void WindowImplX11::SetActive(bool Active) const
+{
+ if (Active)
+ {
+ if (myWindow && myGLContext && (glXGetCurrentContext() != myGLContext))
+ glXMakeCurrent(ourDisplay, myWindow, myGLContext);
+ }
+ else
+ {
+ if (glXGetCurrentContext() == myGLContext)
+ glXMakeCurrent(ourDisplay, None, NULL);
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::UseVerticalSync
+////////////////////////////////////////////////////////////
+void WindowImplX11::UseVerticalSync(bool Enabled)
+{
+ const GLubyte* ProcAddress = reinterpret_cast<const GLubyte*>("glXSwapIntervalSGI");
+ PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = reinterpret_cast<PFNGLXSWAPINTERVALSGIPROC>(glXGetProcAddress(ProcAddress));
+ if (glXSwapIntervalSGI)
+ glXSwapIntervalSGI(Enabled ? 1 : 0);
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::ShowMouseCursor
+////////////////////////////////////////////////////////////
+void WindowImplX11::ShowMouseCursor(bool Show)
+{
+ XDefineCursor(ourDisplay, myWindow, Show ? None : myHiddenCursor);
+ XFlush(ourDisplay);
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see sfWindowImpl::SetCursorPosition
+////////////////////////////////////////////////////////////
+void WindowImplX11::SetCursorPosition(unsigned int Left, unsigned int Top)
+{
+ XWarpPointer(ourDisplay, None, myWindow, 0, 0, 0, 0, Left, Top);
+ XFlush(ourDisplay);
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see sfWindowImpl::SetPosition
+////////////////////////////////////////////////////////////
+void WindowImplX11::SetPosition(int Left, int Top)
+{
+ XMoveWindow(ourDisplay, myWindow, Left, Top);
+ XFlush(ourDisplay);
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::SetSize
+////////////////////////////////////////////////////////////
+void WindowImplX11::SetSize(unsigned int Width, unsigned int Height)
+{
+ XResizeWindow(ourDisplay, myWindow, Width, Height);
+ XFlush(ourDisplay);
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see sfWindowImpl::Show
+////////////////////////////////////////////////////////////
+void WindowImplX11::Show(bool State)
+{
+ if (State)
+ XMapWindow(ourDisplay, myWindow);
+ else
+ XUnmapWindow(ourDisplay, myWindow);
+
+ XFlush(ourDisplay);
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see sfWindowImpl::EnableKeyRepeat
+////////////////////////////////////////////////////////////
+void WindowImplX11::EnableKeyRepeat(bool Enabled)
+{
+ myKeyRepeat = Enabled;
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::SetIcon
+////////////////////////////////////////////////////////////
+void WindowImplX11::SetIcon(unsigned int Width, unsigned int Height, const Uint8* Pixels)
+{
+ // X11 wants BGRA pixels : swap red and blue channels
+ // Note : this memory will never be freed, but it seems to cause a bug on exit if I do so
+ Uint8* IconPixels = new Uint8[Width * Height * 4];
+ for (std::size_t i = 0; i < Width * Height; ++i)
+ {
+ IconPixels[i * 4 + 0] = Pixels[i * 4 + 2];
+ IconPixels[i * 4 + 1] = Pixels[i * 4 + 1];
+ IconPixels[i * 4 + 2] = Pixels[i * 4 + 0];
+ IconPixels[i * 4 + 3] = Pixels[i * 4 + 3];
+ }
+
+ // Create the icon pixmap
+ Visual* DefVisual = DefaultVisual(ourDisplay, ourScreen);
+ unsigned int DefDepth = DefaultDepth(ourDisplay, ourScreen);
+ XImage* IconImage = XCreateImage(ourDisplay, DefVisual, DefDepth, ZPixmap, 0, (char*)IconPixels, Width, Height, 32, 0);
+ if (!IconImage)
+ {
+ std::cerr << "Failed to set the window's icon" << std::endl;
+ return;
+ }
+ Pixmap IconPixmap = XCreatePixmap(ourDisplay, RootWindow(ourDisplay, ourScreen), Width, Height, DefDepth);
+ XGCValues Values;
+ GC IconGC = XCreateGC(ourDisplay, IconPixmap, 0, &Values);
+ XPutImage(ourDisplay, IconPixmap, IconGC, IconImage, 0, 0, 0, 0, Width, Height);
+ XFreeGC(ourDisplay, IconGC);
+ XDestroyImage(IconImage);
+
+ // Create the mask pixmap (must have 1 bit depth)
+ std::size_t Pitch = (Width + 7) / 8;
+ static std::vector<Uint8> MaskPixels(Pitch * Height, 0);
+ for (std::size_t j = 0; j < Height; ++j)
+ {
+ for (std::size_t i = 0; i < Pitch; ++i)
+ {
+ for (std::size_t k = 0; k < 8; ++k)
+ {
+ if (i * 8 + k < Width)
+ {
+ Uint8 Opacity = (Pixels[(i * 8 + k + j * Width) * 4 + 3] > 0) ? 1 : 0;
+ MaskPixels[i + j * Pitch] |= (Opacity << k);
+ }
+ }
+ }
+ }
+ Pixmap MaskPixmap = XCreatePixmapFromBitmapData(ourDisplay, myWindow, (char*)&MaskPixels[0], Width, Height, 1, 0, 1);
+
+ // Send our new icon to the window through the WMHints
+ XWMHints* Hints = XAllocWMHints();
+ Hints->flags = IconPixmapHint | IconMaskHint;
+ Hints->icon_pixmap = IconPixmap;
+ Hints->icon_mask = MaskPixmap;
+ XSetWMHints(ourDisplay, myWindow, Hints);
+ XFree(Hints);
+
+ XFlush(ourDisplay);
+}
+
+
+////////////////////////////////////////////////////////////
+/// Switch to fullscreen mode
+////////////////////////////////////////////////////////////
+void WindowImplX11::SwitchToFullscreen(const VideoMode& Mode)
+{
+ // Check if the XRandR extension is present
+ int Version;
+ if (XQueryExtension(ourDisplay, "RANDR", &Version, &Version, &Version))
+ {
+ // Get the current configuration
+ XRRScreenConfiguration* Config = XRRGetScreenInfo(ourDisplay, RootWindow(ourDisplay, ourScreen));
+ if (Config)
+ {
+ // Get the current rotation
+ Rotation CurrentRotation;
+ myOldVideoMode = XRRConfigCurrentConfiguration(Config, &CurrentRotation);
+
+ // Get the available screen sizes
+ int NbSizes;
+ XRRScreenSize* Sizes = XRRConfigSizes(Config, &NbSizes);
+ if (Sizes && (NbSizes > 0))
+ {
+ // Search a matching size
+ for (int i = 0; i < NbSizes; ++i)
+ {
+ if ((Sizes[i].width == static_cast<int>(Mode.Width)) && (Sizes[i].height == static_cast<int>(Mode.Height)))
+ {
+ // Switch to fullscreen mode
+ XRRSetScreenConfig(ourDisplay, Config, RootWindow(ourDisplay, ourScreen), i, CurrentRotation, CurrentTime);
+
+ // Set "this" as the current fullscreen window
+ ourFullscreenWindow = this;
+ break;
+ }
+ }
+ }
+
+ // Free the configuration instance
+ XRRFreeScreenConfigInfo(Config);
+ }
+ else
+ {
+ // Failed to get the screen configuration
+ std::cerr << "Failed to get the current screen configuration for fullscreen mode, switching to windiw mode" << std::endl;
+ }
+ }
+ else
+ {
+ // XRandr extension is not supported : we cannot use fullscreen mode
+ std::cerr << "Fullscreen is not supported, switching to window mode" << std::endl;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+/// Create the OpenGL rendering context
+////////////////////////////////////////////////////////////
+bool WindowImplX11::CreateContext(const VideoMode& Mode, XVisualInfo& ChosenVisual, WindowSettings& Params, XVisualInfo Template, unsigned long Mask)
+{
+ // Get all the visuals matching the template
+ Template.screen = ourScreen;
+ int NbVisuals = 0;
+ XVisualInfo* Visuals = XGetVisualInfo(ourDisplay, Mask | VisualScreenMask, &Template, &NbVisuals);
+ if (!Visuals || (NbVisuals == 0))
+ {
+ if (Visuals)
+ XFree(Visuals);
+ std::cerr << "There is no valid visual for the selected screen" << std::endl;
+ return false;
+ }
+
+ // Find the best visual
+ int BestScore = 0xFFFF;
+ XVisualInfo* BestVisual = NULL;
+ while (!BestVisual)
+ {
+ for (int i = 0; i < NbVisuals; ++i)
+ {
+ // Get the current visual attributes
+ int RGBA, DoubleBuffer, Red, Green, Blue, Alpha, Depth, Stencil, MultiSampling, Samples;
+ glXGetConfig(ourDisplay, &Visuals[i], GLX_RGBA, &RGBA);
+ glXGetConfig(ourDisplay, &Visuals[i], GLX_DOUBLEBUFFER, &DoubleBuffer);
+ glXGetConfig(ourDisplay, &Visuals[i], GLX_RED_SIZE, &Red);
+ glXGetConfig(ourDisplay, &Visuals[i], GLX_GREEN_SIZE, &Green);
+ glXGetConfig(ourDisplay, &Visuals[i], GLX_BLUE_SIZE, &Blue);
+ glXGetConfig(ourDisplay, &Visuals[i], GLX_ALPHA_SIZE, &Alpha);
+ glXGetConfig(ourDisplay, &Visuals[i], GLX_DEPTH_SIZE, &Depth);
+ glXGetConfig(ourDisplay, &Visuals[i], GLX_STENCIL_SIZE, &Stencil);
+ glXGetConfig(ourDisplay, &Visuals[i], GLX_SAMPLE_BUFFERS_ARB, &MultiSampling);
+ glXGetConfig(ourDisplay, &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 = EvaluateConfig(Mode, Params, Color, Depth, Stencil, MultiSampling ? Samples : 0);
+
+ // Keep it if it's better than the current best
+ if (Score < BestScore)
+ {
+ BestScore = Score;
+ BestVisual = &Visuals[i];
+ break;
+ }
+ }
+
+ // If no visual has been found, try a lower level of antialiasing
+ if (!BestVisual)
+ {
+ if (Params.AntialiasingLevel > 2)
+ {
+ std::cerr << "Failed to find a pixel format supporting "
+ << Params.AntialiasingLevel << " antialiasing levels ; trying with 2 levels" << std::endl;
+ Params.AntialiasingLevel = 2;
+ }
+ else if (Params.AntialiasingLevel > 0)
+ {
+ std::cerr << "Failed to find a pixel format supporting antialiasing ; antialiasing will be disabled" << std::endl;
+ Params.AntialiasingLevel = 0;
+ }
+ else
+ {
+ std::cerr << "Failed to find a suitable pixel format for the window -- cannot create OpenGL context" << std::endl;
+ return false;
+ }
+ }
+ }
+
+ // Create the OpenGL context
+ myGLContext = glXCreateContext(ourDisplay, BestVisual, glXGetCurrentContext(), true);
+ if (myGLContext == NULL)
+ {
+ std::cerr << "Failed to create an OpenGL context for this window" << std::endl;
+ return false;
+ }
+
+ // Update the creation settings from the chosen format
+ int Depth, Stencil;
+ glXGetConfig(ourDisplay, BestVisual, GLX_DEPTH_SIZE, &Depth);
+ glXGetConfig(ourDisplay, BestVisual, GLX_STENCIL_SIZE, &Stencil);
+ Params.DepthBits = static_cast<unsigned int>(Depth);
+ Params.StencilBits = static_cast<unsigned int>(Stencil);
+
+ // Assign the chosen visual, and free the temporary visuals array
+ ChosenVisual = *BestVisual;
+ XFree(Visuals);
+
+ // Activate the context
+ SetActive(true);
+
+ // Enable multisampling if needed
+ if (Params.AntialiasingLevel > 0)
+ glEnable(GL_MULTISAMPLE_ARB);
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Do some common initializations after the window has been created
+////////////////////////////////////////////////////////////
+void WindowImplX11::Initialize()
+{
+ // Get the atom defining the close event
+ myAtomClose = XInternAtom(ourDisplay, "WM_DELETE_WINDOW", false);
+ XSetWMProtocols(ourDisplay, myWindow, &myAtomClose, 1);
+
+ // Create the input context
+ if (ourInputMethod)
+ {
+ myInputContext = XCreateIC(ourInputMethod,
+ XNClientWindow, myWindow,
+ XNFocusWindow, myWindow,
+ XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
+ NULL);
+
+ if (!myInputContext)
+ std::cerr << "Failed to create input context for window -- TextEntered event won't be able to return unicode" << std::endl;
+ }
+
+ // Show the window
+ XMapWindow(ourDisplay, myWindow);
+ XFlush(ourDisplay);
+
+ // Create the hiden cursor
+ CreateHiddenCursor();
+
+ // Set our context as the current OpenGL context for rendering
+ SetActive();
+
+ // Flush the commands queue
+ XFlush(ourDisplay);
+}
+
+
+////////////////////////////////////////////////////////////
+/// Create a transparent mouse cursor
+////////////////////////////////////////////////////////////
+void WindowImplX11::CreateHiddenCursor()
+{
+ // Create the cursor's pixmap (1x1 pixels)
+ Pixmap CursorPixmap = XCreatePixmap(ourDisplay, myWindow, 1, 1, 1);
+ GC GraphicsContext = XCreateGC(ourDisplay, CursorPixmap, 0, NULL);
+ XDrawPoint(ourDisplay, CursorPixmap, GraphicsContext, 0, 0);
+ XFreeGC(ourDisplay, GraphicsContext);
+
+ // Create the cursor, using the pixmap as both the shape and the mask of the cursor
+ XColor Color;
+ Color.flags = DoRed | DoGreen | DoBlue;
+ Color.red = Color.blue = Color.green = 0;
+ myHiddenCursor = XCreatePixmapCursor(ourDisplay, CursorPixmap, CursorPixmap, &Color, &Color, 0, 0);
+
+ // We don't need the pixmap any longer, free it
+ XFreePixmap(ourDisplay, CursorPixmap);
+}
+
+
+////////////////////////////////////////////////////////////
+/// Cleanup graphical resources attached to the window
+////////////////////////////////////////////////////////////
+void WindowImplX11::CleanUp()
+{
+ // Restore the previous video mode (in case we were running in fullscreen)
+ if (ourFullscreenWindow == this)
+ {
+ // Get current screen info
+ XRRScreenConfiguration* Config = XRRGetScreenInfo(ourDisplay, RootWindow(ourDisplay, ourScreen));
+ if (Config)
+ {
+ // Get the current rotation
+ Rotation CurrentRotation;
+ XRRConfigCurrentConfiguration(Config, &CurrentRotation);
+
+ // Reset the video mode
+ XRRSetScreenConfig(ourDisplay, Config, RootWindow(ourDisplay, ourScreen), myOldVideoMode, CurrentRotation, CurrentTime);
+
+ // Free the configuration instance
+ XRRFreeScreenConfigInfo(Config);
+ }
+
+ // Reset the fullscreen window
+ ourFullscreenWindow = NULL;
+ }
+
+ // Unhide the mouse cursor (in case it was hidden)
+ ShowMouseCursor(true);
+
+ // Destroy the OpenGL context
+ if (myGLContext)
+ {
+ glXDestroyContext(ourDisplay, myGLContext);
+ myGLContext = NULL;
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+/// Filter the received events
+/// (only allow those matching a specific window)
+////////////////////////////////////////////////////////////
+Bool WindowImplX11::CheckEvent(::Display*, XEvent* Event, XPointer UserData)
+{
+ // Just check if the event matches our window
+ return Event->xany.window == reinterpret_cast< ::Window >(UserData);
+}
+
+
+////////////////////////////////////////////////////////////
+/// Process an incoming event from the window
+////////////////////////////////////////////////////////////
+void WindowImplX11::ProcessEvent(XEvent WinEvent)
+{
+ switch (WinEvent.type)
+ {
+ // Destroy event
+ case DestroyNotify :
+ {
+ // The window is about to be destroyed : we must cleanup resources
+ CleanUp();
+ break;
+ }
+
+ // Gain focus event
+ case FocusIn :
+ {
+ // Update the input context
+ if (myInputContext)
+ XSetICFocus(myInputContext);
+
+ Event Evt;
+ Evt.Type = Event::GainedFocus;
+ SendEvent(Evt);
+ break;
+ }
+
+ // Lost focus event
+ case FocusOut :
+ {
+ // Update the input context
+ if (myInputContext)
+ XUnsetICFocus(myInputContext);
+
+ Event Evt;
+ Evt.Type = Event::LostFocus;
+ SendEvent(Evt);
+ break;
+ }
+
+ // Resize event
+ case ConfigureNotify :
+ {
+ if ((WinEvent.xconfigure.width != static_cast<int>(myWidth)) || (WinEvent.xconfigure.height != static_cast<int>(myHeight)))
+ {
+ myWidth = WinEvent.xconfigure.width;
+ myHeight = WinEvent.xconfigure.height;
+
+ Event Evt;
+ Evt.Type = Event::Resized;
+ Evt.Size.Width = myWidth;
+ Evt.Size.Height = myHeight;
+ SendEvent(Evt);
+ }
+ break;
+ }
+
+ // Close event
+ case ClientMessage :
+ {
+ if ((WinEvent.xclient.format == 32) && (WinEvent.xclient.data.l[0]) == static_cast<long>(myAtomClose))
+ {
+ Event Evt;
+ Evt.Type = Event::Closed;
+ SendEvent(Evt);
+ }
+ break;
+ }
+
+ // Key down event
+ case KeyPress :
+ {
+ // Get the keysym of the key that has been pressed
+ static XComposeStatus KeyboardStatus;
+ char Buffer[32];
+ KeySym Sym;
+ XLookupString(&WinEvent.xkey, Buffer, sizeof(Buffer), &Sym, &KeyboardStatus);
+
+ // Fill the event parameters
+ Event Evt;
+ Evt.Type = Event::KeyPressed;
+ Evt.Key.Code = KeysymToSF(Sym);
+ Evt.Key.Alt = WinEvent.xkey.state & Mod1Mask;
+ Evt.Key.Control = WinEvent.xkey.state & ControlMask;
+ Evt.Key.Shift = WinEvent.xkey.state & ShiftMask;
+ SendEvent(Evt);
+
+ // Generate a TextEntered event
+ if (!XFilterEvent(&WinEvent, None))
+ {
+ #ifdef X_HAVE_UTF8_STRING
+ if (myInputContext)
+ {
+ Status ReturnedStatus;
+ Uint8 KeyBuffer[16];
+ int Length = Xutf8LookupString(myInputContext, &WinEvent.xkey, reinterpret_cast<char*>(KeyBuffer), sizeof(KeyBuffer), NULL, &ReturnedStatus);
+ if (Length > 0)
+ {
+ Uint32 Unicode[2]; // just in case, but 1 character should be enough
+ const Uint32* End = Unicode::UTF8ToUTF32(KeyBuffer, KeyBuffer + Length, Unicode);
+
+ if (End > Unicode)
+ {
+ Event TextEvt;
+ TextEvt.Type = Event::TextEntered;
+ TextEvt.Text.Unicode = Unicode[0];
+ SendEvent(TextEvt);
+ }
+ }
+ }
+ else
+ #endif
+ {
+ static XComposeStatus ComposeStatus;
+ char KeyBuffer[16];
+ if (XLookupString(&WinEvent.xkey, KeyBuffer, sizeof(KeyBuffer), NULL, &ComposeStatus))
+ {
+ Event TextEvt;
+ TextEvt.Type = Event::TextEntered;
+ TextEvt.Text.Unicode = static_cast<Uint32>(KeyBuffer[0]);
+ SendEvent(TextEvt);
+ }
+ }
+ }
+
+ break;
+ }
+
+ // Key up event
+ case KeyRelease :
+ {
+ // Get the keysym of the key that has been pressed
+ char Buffer[32];
+ KeySym Sym;
+ XLookupString(&WinEvent.xkey, Buffer, 32, &Sym, NULL);
+
+ // Fill the event parameters
+ Event Evt;
+ Evt.Type = Event::KeyReleased;
+ Evt.Key.Code = KeysymToSF(Sym);
+ Evt.Key.Alt = WinEvent.xkey.state & Mod1Mask;
+ Evt.Key.Control = WinEvent.xkey.state & ControlMask;
+ Evt.Key.Shift = WinEvent.xkey.state & ShiftMask;
+
+ SendEvent(Evt);
+ break;
+ }
+
+ // Mouse button pressed
+ case ButtonPress :
+ {
+ unsigned int Button = WinEvent.xbutton.button;
+ if ((Button == Button1) || (Button == Button2) || (Button == Button3) || (Button == 8) || (Button == 9))
+ {
+ Event Evt;
+ Evt.Type = Event::MouseButtonPressed;
+ Evt.MouseButton.X = WinEvent.xbutton.x;
+ Evt.MouseButton.Y = WinEvent.xbutton.y;
+ switch (Button)
+ {
+ case Button1 : Evt.MouseButton.Button = Mouse::Left; break;
+ case Button2 : Evt.MouseButton.Button = Mouse::Middle; break;
+ case Button3 : Evt.MouseButton.Button = Mouse::Right; break;
+ case 8 : Evt.MouseButton.Button = Mouse::XButton1; break;
+ case 9 : Evt.MouseButton.Button = Mouse::XButton2; break;
+ }
+ SendEvent(Evt);
+ }
+ break;
+ }
+
+ // Mouse button released
+ case ButtonRelease :
+ {
+ unsigned int Button = WinEvent.xbutton.button;
+ if ((Button == Button1) || (Button == Button2) || (Button == Button3) || (Button == 8) || (Button == 9))
+ {
+ Event Evt;
+ Evt.Type = Event::MouseButtonReleased;
+ Evt.MouseButton.X = WinEvent.xbutton.x;
+ Evt.MouseButton.Y = WinEvent.xbutton.y;
+ switch (Button)
+ {
+ case Button1 : Evt.MouseButton.Button = Mouse::Left; break;
+ case Button2 : Evt.MouseButton.Button = Mouse::Middle; break;
+ case Button3 : Evt.MouseButton.Button = Mouse::Right; break;
+ case 8 : Evt.MouseButton.Button = Mouse::XButton1; break;
+ case 9 : Evt.MouseButton.Button = Mouse::XButton2; break;
+ }
+ SendEvent(Evt);
+ }
+ else if ((Button == Button4) || (Button == Button5))
+ {
+ Event Evt;
+ Evt.Type = Event::MouseWheelMoved;
+ Evt.MouseWheel.Delta = WinEvent.xbutton.button == Button4 ? 1 : -1;
+ SendEvent(Evt);
+ }
+ break;
+ }
+
+ // Mouse moved
+ case MotionNotify :
+ {
+ Event Evt;
+ Evt.Type = Event::MouseMoved;
+ Evt.MouseMove.X = WinEvent.xmotion.x;
+ Evt.MouseMove.Y = WinEvent.xmotion.y;
+ SendEvent(Evt);
+ break;
+ }
+
+ // Mouse entered
+ case EnterNotify :
+ {
+ Event Evt;
+ Evt.Type = Event::MouseEntered;
+ SendEvent(Evt);
+ break;
+ }
+
+ // Mouse left
+ case LeaveNotify :
+ {
+ Event Evt;
+ Evt.Type = Event::MouseLeft;
+ SendEvent(Evt);
+ break;
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+/// Convert a X11 keysym to SFML key code
+////////////////////////////////////////////////////////////
+Key::Code WindowImplX11::KeysymToSF(KeySym Sym)
+{
+ // First convert to uppercase (to avoid dealing with two different keysyms for the same key)
+ KeySym Lower, Key;
+ XConvertCase(Sym, &Lower, &Key);
+
+ switch (Key)
+ {
+ case XK_Shift_L : return Key::LShift;
+ case XK_Shift_R : return Key::RShift;
+ case XK_Control_L : return Key::LControl;
+ case XK_Control_R : return Key::RControl;
+ case XK_Alt_L : return Key::LAlt;
+ case XK_Alt_R : return Key::RAlt;
+ case XK_Super_L : return Key::LSystem;
+ case XK_Super_R : return Key::RSystem;
+ case XK_Menu : return Key::Menu;
+ case XK_Escape : return Key::Escape;
+ case XK_semicolon : return Key::SemiColon;
+ case XK_slash : return Key::Slash;
+ case XK_equal : return Key::Equal;
+ case XK_minus : return Key::Dash;
+ case XK_bracketleft : return Key::LBracket;
+ case XK_bracketright : return Key::RBracket;
+ case XK_comma : return Key::Comma;
+ case XK_period : return Key::Period;
+ case XK_dead_acute : return Key::Quote;
+ case XK_backslash : return Key::BackSlash;
+ case XK_dead_grave : return Key::Tilde;
+ case XK_space : return Key::Space;
+ case XK_Return : return Key::Return;
+ case XK_KP_Enter : return Key::Return;
+ case XK_BackSpace : return Key::Back;
+ case XK_Tab : return Key::Tab;
+ case XK_Prior : return Key::PageUp;
+ case XK_Next : return Key::PageDown;
+ case XK_End : return Key::End;
+ case XK_Home : return Key::Home;
+ case XK_Insert : return Key::Insert;
+ case XK_Delete : return Key::Delete;
+ case XK_KP_Add : return Key::Add;
+ case XK_KP_Subtract : return Key::Subtract;
+ case XK_KP_Multiply : return Key::Multiply;
+ case XK_KP_Divide : return Key::Divide;
+ case XK_Pause : return Key::Pause;
+ case XK_F1 : return Key::F1;
+ case XK_F2 : return Key::F2;
+ case XK_F3 : return Key::F3;
+ case XK_F4 : return Key::F4;
+ case XK_F5 : return Key::F5;
+ case XK_F6 : return Key::F6;
+ case XK_F7 : return Key::F7;
+ case XK_F8 : return Key::F8;
+ case XK_F9 : return Key::F9;
+ case XK_F10 : return Key::F10;
+ case XK_F11 : return Key::F11;
+ case XK_F12 : return Key::F12;
+ case XK_F13 : return Key::F13;
+ case XK_F14 : return Key::F14;
+ case XK_F15 : return Key::F15;
+ case XK_Left : return Key::Left;
+ case XK_Right : return Key::Right;
+ case XK_Up : return Key::Up;
+ case XK_Down : return Key::Down;
+ case XK_KP_0 : return Key::Numpad0;
+ case XK_KP_1 : return Key::Numpad1;
+ case XK_KP_2 : return Key::Numpad2;
+ case XK_KP_3 : return Key::Numpad3;
+ case XK_KP_4 : return Key::Numpad4;
+ case XK_KP_5 : return Key::Numpad5;
+ case XK_KP_6 : return Key::Numpad6;
+ case XK_KP_7 : return Key::Numpad7;
+ case XK_KP_8 : return Key::Numpad8;
+ case XK_KP_9 : return Key::Numpad9;
+ case XK_A : return Key::A;
+ case XK_Z : return Key::Z;
+ case XK_E : return Key::E;
+ case XK_R : return Key::R;
+ case XK_T : return Key::T;
+ case XK_Y : return Key::Y;
+ case XK_U : return Key::U;
+ case XK_I : return Key::I;
+ case XK_O : return Key::O;
+ case XK_P : return Key::P;
+ case XK_Q : return Key::Q;
+ case XK_S : return Key::S;
+ case XK_D : return Key::D;
+ case XK_F : return Key::F;
+ case XK_G : return Key::G;
+ case XK_H : return Key::H;
+ case XK_J : return Key::J;
+ case XK_K : return Key::K;
+ case XK_L : return Key::L;
+ case XK_M : return Key::M;
+ case XK_W : return Key::W;
+ case XK_X : return Key::X;
+ case XK_C : return Key::C;
+ case XK_V : return Key::V;
+ case XK_B : return Key::B;
+ case XK_N : return Key::N;
+ case XK_0 : return Key::Num0;
+ case XK_1 : return Key::Num1;
+ case XK_2 : return Key::Num2;
+ case XK_3 : return Key::Num3;
+ case XK_4 : return Key::Num4;
+ case XK_5 : return Key::Num5;
+ case XK_6 : return Key::Num6;
+ case XK_7 : return Key::Num7;
+ case XK_8 : return Key::Num8;
+ case XK_9 : return Key::Num9;
+ }
+
+ return Key::Code(0);
+}
+
+
+////////////////////////////////////////////////////////////
+/// Open the display (if not already done)
+////////////////////////////////////////////////////////////
+bool WindowImplX11::OpenDisplay(bool AddWindow)
+{
+ // If no display has been opened yet, open it
+ if (ourDisplay == NULL)
+ {
+ ourDisplay = XOpenDisplay(NULL);
+ if (ourDisplay)
+ {
+ ourScreen = DefaultScreen(ourDisplay);
+
+ // Get the input method (XIM) object
+ ourInputMethod = XOpenIM(ourDisplay, NULL, NULL, NULL);
+ }
+ else
+ {
+ std::cerr << "Failed to open a connection with the X server" << std::endl;
+ }
+ }
+
+ // Increase the number of windows
+ if (AddWindow)
+ ourWindowsCount++;
+
+ return ourDisplay != NULL;
+}
+
+
+////////////////////////////////////////////////////////////
+/// Close the display
+////////////////////////////////////////////////////////////
+void WindowImplX11::CloseDisplay()
+{
+ // Decrease the number of windows
+ ourWindowsCount--;
+
+ // If all windows have been destroyed, then we can close the display
+ if (ourWindowsCount == 0)
+ {
+ // Close the input method object
+ if (ourInputMethod)
+ XCloseIM(ourInputMethod);
+
+ XCloseDisplay(ourDisplay);
+ ourDisplay = NULL;
+ }
+}
+
+} // namespace priv
+
+} // namespace sf
diff --git a/src/SFML/Window/Linux/.svn/text-base/WindowImplX11.hpp.svn-base b/src/SFML/Window/Linux/.svn/text-base/WindowImplX11.hpp.svn-base
new file mode 100644
index 0000000..b4506fc
--- /dev/null
+++ b/src/SFML/Window/Linux/.svn/text-base/WindowImplX11.hpp.svn-base
@@ -0,0 +1,277 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it freely,
+// subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented;
+// you must not claim that you wrote the original software.
+// If you use this software in a product, an acknowledgment
+// in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such,
+// and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+//
+////////////////////////////////////////////////////////////
+
+#ifndef SFML_WINDOWIMPLX11_HPP
+#define SFML_WINDOWIMPLX11_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Window/Event.hpp>
+#include <SFML/Window/WindowImpl.hpp>
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+#include <set>
+#include <string>
+
+
+namespace sf
+{
+namespace priv
+{
+class VideoModeSupport;
+
+////////////////////////////////////////////////////////////
+/// WindowImplX11 is the Linux (X11) implementation of WindowImpl
+////////////////////////////////////////////////////////////
+class WindowImplX11 : public WindowImpl
+{
+public :
+
+ ////////////////////////////////////////////////////////////
+ /// Default constructor
+ /// (creates a dummy window to provide a valid OpenGL context)
+ ///
+ ////////////////////////////////////////////////////////////
+ WindowImplX11();
+
+ ////////////////////////////////////////////////////////////
+ /// Construct the window implementation from an existing control
+ ///
+ /// \param Handle : Platform-specific handle of the control
+ /// \param Params : Creation settings
+ ///
+ ////////////////////////////////////////////////////////////
+ WindowImplX11(WindowHandle Handle, WindowSettings& Params);
+
+ ////////////////////////////////////////////////////////////
+ /// Create the window implementation
+ ///
+ /// \param Mode : Video mode to use
+ /// \param Title : Title of the window
+ /// \param WindowStyle : Window style (resizable, fixed, or fullscren)
+ /// \param Params : Creation settings
+ ///
+ ////////////////////////////////////////////////////////////
+ WindowImplX11(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, WindowSettings& Params);
+
+ ////////////////////////////////////////////////////////////
+ /// Destructor
+ ///
+ ////////////////////////////////////////////////////////////
+ ~WindowImplX11();
+
+ ////////////////////////////////////////////////////////////
+ /// Check if there's an active context on the current thread
+ ///
+ /// \return True if there's a context bound to the current thread
+ ///
+ ////////////////////////////////////////////////////////////
+ static bool IsContextActive();
+
+private :
+
+ friend class VideoModeSupport;
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::Display
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void Display();
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::ProcessEvents
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void ProcessEvents();
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::SetActive
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void SetActive(bool Active = true) const;
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::UseVerticalSync
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void UseVerticalSync(bool Enabled);
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::ShowMouseCursor
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void ShowMouseCursor(bool Show);
+
+ ////////////////////////////////////////////////////////////
+ /// /see sfWindowImpl::SetCursorPosition
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void SetCursorPosition(unsigned int Left, unsigned int Top);
+
+ ////////////////////////////////////////////////////////////
+ /// /see sfWindowImpl::SetPosition
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void SetPosition(int Left, int Top);
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::SetSize
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void SetSize(unsigned int Width, unsigned int Height);
+
+ ////////////////////////////////////////////////////////////
+ /// /see sfWindowImpl::Show
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void Show(bool State);
+
+ ////////////////////////////////////////////////////////////
+ /// /see sfWindowImpl::EnableKeyRepeat
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void EnableKeyRepeat(bool Enabled);
+
+ ////////////////////////////////////////////////////////////
+ /// /see WindowImpl::SetIcon
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void SetIcon(unsigned int Width, unsigned int Height, const Uint8* Pixels);
+
+ ////////////////////////////////////////////////////////////
+ /// Switch to fullscreen mode
+ ///
+ /// \param Mode : video mode to switch to
+ ///
+ ////////////////////////////////////////////////////////////
+ void SwitchToFullscreen(const VideoMode& Mode);
+
+ ////////////////////////////////////////////////////////////
+ /// Create the OpenGL rendering context
+ ///
+ /// \param Mode : Video mode to use
+ /// \param ChosenVisual : Visual that has been chosen for creating the contexte
+ /// \param Params : Creation parameters
+ /// \param Template : Visual infos to match
+ /// \param Mask : Visual attributes to check in Template
+ ///
+ /// \return True on success, false on error
+ ///
+ ////////////////////////////////////////////////////////////
+ bool CreateContext(const VideoMode& Mode, XVisualInfo& ChosenVisual, WindowSettings& Params, XVisualInfo Template = XVisualInfo(), unsigned long Mask = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// Do some common initializations after the window has been created
+ ///
+ ////////////////////////////////////////////////////////////
+ void Initialize();
+
+ ////////////////////////////////////////////////////////////
+ /// Create a transparent mouse cursor
+ ///
+ ////////////////////////////////////////////////////////////
+ void CreateHiddenCursor();
+
+ ////////////////////////////////////////////////////////////
+ /// Cleanup graphical resources attached to the window
+ ///
+ ////////////////////////////////////////////////////////////
+ void CleanUp();
+
+ ////////////////////////////////////////////////////////////
+ /// Filter the received events
+ /// (only allow those matching a specific window)
+ ///
+ /// \param Event : Event to filter
+ /// \param UserData : Data passed to the function (here : the window to compare)
+ ///
+ /// \return True if the event belongs to the specified window
+ ///
+ ////////////////////////////////////////////////////////////
+ static Bool CheckEvent(::Display*, XEvent* Event, XPointer UserData);
+
+ ////////////////////////////////////////////////////////////
+ /// Process an incoming event from the window
+ ///
+ /// \param WinEvent : Event which has been received
+ ///
+ ////////////////////////////////////////////////////////////
+ void ProcessEvent(XEvent WinEvent);
+
+ ////////////////////////////////////////////////////////////
+ /// Convert a X11 keysym to SFML key code
+ ///
+ /// \param Sym : keysym to convert
+ ///
+ /// \return Corrsponding SFML key code
+ ///
+ ////////////////////////////////////////////////////////////
+ static Key::Code KeysymToSF(KeySym Sym);
+
+ ////////////////////////////////////////////////////////////
+ /// Open the display (if not already done)
+ ///
+ /// \param AddWindow : Tell whether or not we must increase the windows count
+ ///
+ /// \return True if the display is properly opened
+ ///
+ ////////////////////////////////////////////////////////////
+ static bool OpenDisplay(bool AddWindow = true);
+
+ ////////////////////////////////////////////////////////////
+ /// Close the display
+ ///
+ ////////////////////////////////////////////////////////////
+ static void CloseDisplay();
+
+ ////////////////////////////////////////////////////////////
+ // Static member data
+ ////////////////////////////////////////////////////////////
+ static ::Display* ourDisplay; ///< Current opened display
+ static int ourScreen; ///< Default screen on the opened display
+ static WindowImplX11* ourFullscreenWindow; ///< Keep track of the active fullscreen window
+ static unsigned int ourWindowsCount; ///< Number of windows created
+ static unsigned long ourEventMask; ///< Mask defining the events that will be caught by our windows
+ static XIM ourInputMethod; ///< Input object used to get unicode characters from keypress messages
+
+ ////////////////////////////////////////////////////////////
+ // Member data
+ ////////////////////////////////////////////////////////////
+ ::Window myWindow; ///< X11 structure defining our window
+ bool myIsExternal; ///< Tell whether the window has been created externally or by SFML
+ GLXContext myGLContext; ///< OpenGL context attached to the window
+ Atom myAtomClose; ///< Atom used to identify the close event
+ int myOldVideoMode; ///< Video mode in use before we switch to fullscreen
+ Cursor myHiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one
+ XIC myInputContext; ///< Input context used to get unicode input in our window
+ bool myKeyRepeat; ///< Is the KeyRepeat feature enabled ?
+};
+
+} // namespace priv
+
+} // namespace sf
+
+
+#endif // SFML_WINDOWIMPLX11_HPP
diff --git a/src/SFML/Window/Linux/Joystick.cpp b/src/SFML/Window/Linux/Joystick.cpp
index 163db80..ba85ccd 100755..100644
--- a/src/SFML/Window/Linux/Joystick.cpp
+++ b/src/SFML/Window/Linux/Joystick.cpp
@@ -45,7 +45,7 @@ void Joystick::Initialize(unsigned int Index)
myNbButtons = 0;
for (int i = 0; i < Joy::Count; ++i)
myState.Axis[i] = 0.f;
- for (int i = 0; i < 16; ++i)
+ for (int i = 0; i < JoystickState::MaxButtons; ++i)
myState.Buttons[i] = false;
// Open the joystick handle
@@ -90,7 +90,7 @@ JoystickState Joystick::UpdateState()
// A button has been pressed
case JS_EVENT_BUTTON :
{
- if (JoyState.number < 16)
+ if (JoyState.number < GetButtonsCount())
myState.Buttons[JoyState.number] = (JoyState.value != 0);
break;
}
diff --git a/src/SFML/Window/Linux/Joystick.hpp b/src/SFML/Window/Linux/Joystick.hpp
index 1c1e4a2..1c1e4a2 100755..100644
--- a/src/SFML/Window/Linux/Joystick.hpp
+++ b/src/SFML/Window/Linux/Joystick.hpp
diff --git a/src/SFML/Window/Linux/VideoModeSupport.cpp b/src/SFML/Window/Linux/VideoModeSupport.cpp
index d328702..d328702 100755..100644
--- a/src/SFML/Window/Linux/VideoModeSupport.cpp
+++ b/src/SFML/Window/Linux/VideoModeSupport.cpp
diff --git a/src/SFML/Window/Linux/VideoModeSupport.hpp b/src/SFML/Window/Linux/VideoModeSupport.hpp
index 87291fc..87291fc 100755..100644
--- a/src/SFML/Window/Linux/VideoModeSupport.hpp
+++ b/src/SFML/Window/Linux/VideoModeSupport.hpp
diff --git a/src/SFML/Window/Linux/WindowImplX11.cpp b/src/SFML/Window/Linux/WindowImplX11.cpp
index f823424..0659089 100755..100644
--- a/src/SFML/Window/Linux/WindowImplX11.cpp
+++ b/src/SFML/Window/Linux/WindowImplX11.cpp
@@ -29,11 +29,12 @@
#include <SFML/Window/Linux/WindowImplX11.hpp>
#include <SFML/Window/glext/glxext.h>
#include <SFML/Window/glext/glext.h>
+#include <SFML/System/Unicode.hpp>
#include <X11/keysym.h>
-#include <X11/XKBlib.h>
#include <X11/extensions/Xrandr.h>
#include <iostream>
#include <sstream>
+#include <vector>
namespace sf
@@ -47,9 +48,10 @@ Display* WindowImplX11::ourDisplay = NULL;
int WindowImplX11::ourScreen = 0;
WindowImplX11* WindowImplX11::ourFullscreenWindow = NULL;
unsigned int WindowImplX11::ourWindowsCount = 0;
-unsigned long WindowImplX11::ourEventMask = FocusChangeMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
- PointerMotionMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask;
XIM WindowImplX11::ourInputMethod = NULL;
+unsigned long WindowImplX11::ourEventMask = FocusChangeMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
+ PointerMotionMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask |
+ EnterWindowMask | LeaveWindowMask;
////////////////////////////////////////////////////////////
@@ -63,7 +65,8 @@ myGLContext (NULL),
myAtomClose (0),
myOldVideoMode(-1),
myHiddenCursor(0),
-myInputContext(NULL)
+myInputContext(NULL),
+myKeyRepeat (true)
{
// Open the display at first call
if (!OpenDisplay())
@@ -97,8 +100,7 @@ myInputContext(NULL)
Visual.visual,
CWColormap, &Attributes);
- // Set our context as the current OpenGL context for rendering
- SetActive();
+ // Don't activate the dummy context by default
}
@@ -112,7 +114,8 @@ myGLContext (NULL),
myAtomClose (0),
myOldVideoMode(-1),
myHiddenCursor(0),
-myInputContext(NULL)
+myInputContext(NULL),
+myKeyRepeat (true)
{
// Open the display at first call
if (!OpenDisplay())
@@ -168,7 +171,8 @@ myGLContext (NULL),
myAtomClose (0),
myOldVideoMode(-1),
myHiddenCursor(0),
-myInputContext(NULL)
+myInputContext(NULL),
+myKeyRepeat (true)
{
// Open the display at first call
if (!OpenDisplay())
@@ -335,6 +339,15 @@ WindowImplX11::~WindowImplX11()
////////////////////////////////////////////////////////////
+/// Check if there's an active context on the current thread
+////////////////////////////////////////////////////////////
+bool WindowImplX11::IsContextActive()
+{
+ return glXGetCurrentContext() != NULL;
+}
+
+
+////////////////////////////////////////////////////////////
/// /see WindowImpl::Display
////////////////////////////////////////////////////////////
void WindowImplX11::Display()
@@ -352,23 +365,44 @@ void WindowImplX11::ProcessEvents()
// Process any event in the queue matching our window
XEvent Event;
while (XCheckIfEvent(ourDisplay, &Event, &WindowImplX11::CheckEvent, reinterpret_cast<XPointer>(myWindow)))
+ {
+ // Filter repeated key events
+ if (Event.type == KeyRelease)
+ {
+ if (XPending(ourDisplay))
+ {
+ XEvent NextEvent;
+ XPeekEvent(ourDisplay, &NextEvent);
+ if ((NextEvent.type == KeyPress) &&
+ (NextEvent.xkey.keycode == Event.xkey.keycode) &&
+ (NextEvent.xkey.time == Event.xkey.time))
+ {
+ if (!myKeyRepeat)
+ XNextEvent(ourDisplay, &NextEvent);
+ continue;
+ }
+ }
+ }
+
ProcessEvent(Event);
+ }
}
////////////////////////////////////////////////////////////
-/// /see WindowImpl::MakeActive
+/// /see WindowImpl::SetActive
////////////////////////////////////////////////////////////
-void WindowImplX11::MakeActive(bool Active) const
+void WindowImplX11::SetActive(bool Active) const
{
if (Active)
{
- if (myWindow && myGLContext)
+ if (myWindow && myGLContext && (glXGetCurrentContext() != myGLContext))
glXMakeCurrent(ourDisplay, myWindow, myGLContext);
}
else
{
- glXMakeCurrent(ourDisplay, None, NULL);
+ if (glXGetCurrentContext() == myGLContext)
+ glXMakeCurrent(ourDisplay, None, NULL);
}
}
@@ -416,6 +450,16 @@ void WindowImplX11::SetPosition(int Left, int Top)
////////////////////////////////////////////////////////////
+/// /see WindowImpl::SetSize
+////////////////////////////////////////////////////////////
+void WindowImplX11::SetSize(unsigned int Width, unsigned int Height)
+{
+ XResizeWindow(ourDisplay, myWindow, Width, Height);
+ XFlush(ourDisplay);
+}
+
+
+////////////////////////////////////////////////////////////
/// /see sfWindowImpl::Show
////////////////////////////////////////////////////////////
void WindowImplX11::Show(bool State)
@@ -434,10 +478,68 @@ void WindowImplX11::Show(bool State)
////////////////////////////////////////////////////////////
void WindowImplX11::EnableKeyRepeat(bool Enabled)
{
- if (Enabled)
- XAutoRepeatOn(ourDisplay);
- else
- XAutoRepeatOff(ourDisplay);
+ myKeyRepeat = Enabled;
+}
+
+
+////////////////////////////////////////////////////////////
+/// /see WindowImpl::SetIcon
+////////////////////////////////////////////////////////////
+void WindowImplX11::SetIcon(unsigned int Width, unsigned int Height, const Uint8* Pixels)
+{
+ // X11 wants BGRA pixels : swap red and blue channels
+ // Note : this memory will never be freed, but it seems to cause a bug on exit if I do so
+ Uint8* IconPixels = new Uint8[Width * Height * 4];
+ for (std::size_t i = 0; i < Width * Height; ++i)
+ {
+ IconPixels[i * 4 + 0] = Pixels[i * 4 + 2];
+ IconPixels[i * 4 + 1] = Pixels[i * 4 + 1];
+ IconPixels[i * 4 + 2] = Pixels[i * 4 + 0];
+ IconPixels[i * 4 + 3] = Pixels[i * 4 + 3];
+ }
+
+ // Create the icon pixmap
+ Visual* DefVisual = DefaultVisual(ourDisplay, ourScreen);
+ unsigned int DefDepth = DefaultDepth(ourDisplay, ourScreen);
+ XImage* IconImage = XCreateImage(ourDisplay, DefVisual, DefDepth, ZPixmap, 0, (char*)IconPixels, Width, Height, 32, 0);
+ if (!IconImage)
+ {
+ std::cerr << "Failed to set the window's icon" << std::endl;
+ return;
+ }
+ Pixmap IconPixmap = XCreatePixmap(ourDisplay, RootWindow(ourDisplay, ourScreen), Width, Height, DefDepth);
+ XGCValues Values;
+ GC IconGC = XCreateGC(ourDisplay, IconPixmap, 0, &Values);
+ XPutImage(ourDisplay, IconPixmap, IconGC, IconImage, 0, 0, 0, 0, Width, Height);
+ XFreeGC(ourDisplay, IconGC);
+ XDestroyImage(IconImage);
+
+ // Create the mask pixmap (must have 1 bit depth)
+ std::size_t Pitch = (Width + 7) / 8;
+ static std::vector<Uint8> MaskPixels(Pitch * Height, 0);
+ for (std::size_t j = 0; j < Height; ++j)
+ {
+ for (std::size_t i = 0; i < Pitch; ++i)
+ {
+ for (std::size_t k = 0; k < 8; ++k)
+ {
+ if (i * 8 + k < Width)
+ {
+ Uint8 Opacity = (Pixels[(i * 8 + k + j * Width) * 4 + 3] > 0) ? 1 : 0;
+ MaskPixels[i + j * Pitch] |= (Opacity << k);
+ }
+ }
+ }
+ }
+ Pixmap MaskPixmap = XCreatePixmapFromBitmapData(ourDisplay, myWindow, (char*)&MaskPixels[0], Width, Height, 1, 0, 1);
+
+ // Send our new icon to the window through the WMHints
+ XWMHints* Hints = XAllocWMHints();
+ Hints->flags = IconPixmapHint | IconMaskHint;
+ Hints->icon_pixmap = IconPixmap;
+ Hints->icon_mask = MaskPixmap;
+ XSetWMHints(ourDisplay, myWindow, Hints);
+ XFree(Hints);
XFlush(ourDisplay);
}
@@ -592,6 +694,9 @@ bool WindowImplX11::CreateContext(const VideoMode& Mode, XVisualInfo& ChosenVisu
ChosenVisual = *BestVisual;
XFree(Visuals);
+ // Activate the context
+ SetActive(true);
+
// Enable multisampling if needed
if (Params.AntialiasingLevel > 0)
glEnable(GL_MULTISAMPLE_ARB);
@@ -616,8 +721,6 @@ void WindowImplX11::Initialize()
XNClientWindow, myWindow,
XNFocusWindow, myWindow,
XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
- //XNResourceName, "SFML",
- //XNResourceClass, "SFML",
NULL);
if (!myInputContext)
@@ -666,7 +769,7 @@ void WindowImplX11::CreateHiddenCursor()
////////////////////////////////////////////////////////////
void WindowImplX11::CleanUp()
{
- // Restore previous video mode (in case we were running in fullscreen)
+ // Restore the previous video mode (in case we were running in fullscreen)
if (ourFullscreenWindow == this)
{
// Get current screen info
@@ -807,12 +910,19 @@ void WindowImplX11::ProcessEvent(XEvent WinEvent)
{
Status ReturnedStatus;
Uint8 KeyBuffer[16];
- if (Xutf8LookupString(myInputContext, &WinEvent.xkey, reinterpret_cast<char*>(KeyBuffer), sizeof(KeyBuffer), NULL, &ReturnedStatus))
+ int Length = Xutf8LookupString(myInputContext, &WinEvent.xkey, reinterpret_cast<char*>(KeyBuffer), sizeof(KeyBuffer), NULL, &ReturnedStatus);
+ if (Length > 0)
{
- Event TextEvt;
- TextEvt.Type = Event::TextEntered;
- TextEvt.Text.Unicode = UTF8toUTF16(KeyBuffer);
- SendEvent(TextEvt);
+ Uint32 Unicode[2]; // just in case, but 1 character should be enough
+ const Uint32* End = Unicode::UTF8ToUTF32(KeyBuffer, KeyBuffer + Length, Unicode);
+
+ if (End > Unicode)
+ {
+ Event TextEvt;
+ TextEvt.Type = Event::TextEntered;
+ TextEvt.Text.Unicode = Unicode[0];
+ SendEvent(TextEvt);
+ }
}
}
else
@@ -824,7 +934,7 @@ void WindowImplX11::ProcessEvent(XEvent WinEvent)
{
Event TextEvt;
TextEvt.Type = Event::TextEntered;
- TextEvt.Text.Unicode = KeyBuffer[0];
+ TextEvt.Text.Unicode = static_cast<Uint32>(KeyBuffer[0]);
SendEvent(TextEvt);
}
}
@@ -860,7 +970,9 @@ void WindowImplX11::ProcessEvent(XEvent WinEvent)
if ((Button == Button1) || (Button == Button2) || (Button == Button3) || (Button == 8) || (Button == 9))
{
Event Evt;
- Evt.Type = Event::MouseButtonPressed;
+ Evt.Type = Event::MouseButtonPressed;
+ Evt.MouseButton.X = WinEvent.xbutton.x;
+ Evt.MouseButton.Y = WinEvent.xbutton.y;
switch (Button)
{
case Button1 : Evt.MouseButton.Button = Mouse::Left; break;
@@ -881,7 +993,9 @@ void WindowImplX11::ProcessEvent(XEvent WinEvent)
if ((Button == Button1) || (Button == Button2) || (Button == Button3) || (Button == 8) || (Button == 9))
{
Event Evt;
- Evt.Type = Event::MouseButtonReleased;
+ Evt.Type = Event::MouseButtonReleased;
+ Evt.MouseButton.X = WinEvent.xbutton.x;
+ Evt.MouseButton.Y = WinEvent.xbutton.y;
switch (Button)
{
case Button1 : Evt.MouseButton.Button = Mouse::Left; break;
@@ -912,6 +1026,24 @@ void WindowImplX11::ProcessEvent(XEvent WinEvent)
SendEvent(Evt);
break;
}
+
+ // Mouse entered
+ case EnterNotify :
+ {
+ Event Evt;
+ Evt.Type = Event::MouseEntered;
+ SendEvent(Evt);
+ break;
+ }
+
+ // Mouse left
+ case LeaveNotify :
+ {
+ Event Evt;
+ Evt.Type = Event::MouseLeft;
+ SendEvent(Evt);
+ break;
+ }
}
}
@@ -1048,11 +1180,6 @@ bool WindowImplX11::OpenDisplay(bool AddWindow)
{
ourScreen = DefaultScreen(ourDisplay);
- // Disable repetition of KeyRelease events when a key is held down
- Bool Supported;
- XkbSetDetectableAutoRepeat(ourDisplay, True, &Supported);
- XFlush(ourDisplay);
-
// Get the input method (XIM) object
ourInputMethod = XOpenIM(ourDisplay, NULL, NULL, NULL);
}
diff --git a/src/SFML/Window/Linux/WindowImplX11.hpp b/src/SFML/Window/Linux/WindowImplX11.hpp
index 8c31621..b4506fc 100755..100644
--- a/src/SFML/Window/Linux/WindowImplX11.hpp
+++ b/src/SFML/Window/Linux/WindowImplX11.hpp
@@ -82,6 +82,14 @@ public :
////////////////////////////////////////////////////////////
~WindowImplX11();
+ ////////////////////////////////////////////////////////////
+ /// Check if there's an active context on the current thread
+ ///
+ /// \return True if there's a context bound to the current thread
+ ///
+ ////////////////////////////////////////////////////////////
+ static bool IsContextActive();
+
private :
friend class VideoModeSupport;
@@ -99,10 +107,10 @@ private :
virtual void ProcessEvents();
////////////////////////////////////////////////////////////
- /// /see WindowImpl::MakeActive
+ /// /see WindowImpl::SetActive
///
////////////////////////////////////////////////////////////
- virtual void MakeActive(bool Active = true) const;
+ virtual void SetActive(bool Active = true) const;
////////////////////////////////////////////////////////////
/// /see WindowImpl::UseVerticalSync
@@ -129,6 +137,12 @@ private :
virtual void SetPosition(int Left, int Top);
////////////////////////////////////////////////////////////
+ /// /see WindowImpl::SetSize
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void SetSize(unsigned int Width, unsigned int Height);
+
+ ////////////////////////////////////////////////////////////
/// /see sfWindowImpl::Show
///
////////////////////////////////////////////////////////////
@@ -141,6 +155,12 @@ private :
virtual void EnableKeyRepeat(bool Enabled);
////////////////////////////////////////////////////////////
+ /// /see WindowImpl::SetIcon
+ ///
+ ////////////////////////////////////////////////////////////
+ virtual void SetIcon(unsigned int Width, unsigned int Height, const Uint8* Pixels);
+
+ ////////////////////////////////////////////////////////////
/// Switch to fullscreen mode
///
/// \param Mode : video mode to switch to
@@ -246,6 +266,7 @@ private :
int myOldVideoMode; ///< Video mode in use before we switch to fullscreen
Cursor myHiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one
XIC myInputContext; ///< Input context used to get unicode input in our window
+ bool myKeyRepeat; ///< Is the KeyRepeat feature enabled ?
};
} // namespace priv