Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added Unicode window title support.

- Changed SFML API to receive an sf::String as the window title instead
  of a std::string (in Window::Window and Window::setTitle).
- Changed RenderWindow and WindowImpl APIs accordingly.
- Changed WindowImplWin32 to use a Unicode window title only if the
  target OS supports it.
- Changed WindowImplCocoa to always use Unicode window titles and added
  a utility function to Window/OSX/cpp_objc_conversion.mm.
- Changed WindowImplX11 to set the Unicode window title as part of the
  _NET_WM_NAME specification, which sadly is not part of the official X
  standard, but the closest anything can get. Still set regular ASCII
  title as fallback.
  • Loading branch information...
commit 6bc077688ea4a624e2a70a856a3a8ab05f413726 1 parent 9cf259c
@Shizmob Shizmob authored
View
2  include/SFML/Graphics/RenderWindow.hpp
@@ -73,7 +73,7 @@ public :
/// \param settings Additional settings for the underlying OpenGL context
///
////////////////////////////////////////////////////////////
- RenderWindow(VideoMode mode, const std::string& title, Uint32 style = Style::Default, const ContextSettings& settings = ContextSettings());
+ RenderWindow(VideoMode mode, const String& title, Uint32 style = Style::Default, const ContextSettings& settings = ContextSettings());
////////////////////////////////////////////////////////////
/// \brief Construct the window from an existing control
View
8 include/SFML/Window/Window.hpp
@@ -37,7 +37,7 @@
#include <SFML/System/Clock.hpp>
#include <SFML/System/Vector2.hpp>
#include <SFML/System/NonCopyable.hpp>
-#include <string>
+#include <SFML/System/String.hpp>
namespace sf
@@ -86,7 +86,7 @@ public :
/// \param settings Additional settings for the underlying OpenGL context
///
////////////////////////////////////////////////////////////
- Window(VideoMode mode, const std::string& title, Uint32 style = Style::Default, const ContextSettings& settings = ContextSettings());
+ Window(VideoMode mode, const String& title, Uint32 style = Style::Default, const ContextSettings& settings = ContextSettings());
////////////////////////////////////////////////////////////
/// \brief Construct the window from an existing control
@@ -125,7 +125,7 @@ public :
/// \param settings Additional settings for the underlying OpenGL context
///
////////////////////////////////////////////////////////////
- void create(VideoMode mode, const std::string& title, Uint32 style = Style::Default, const ContextSettings& settings = ContextSettings());
+ void create(VideoMode mode, const String& title, Uint32 style = Style::Default, const ContextSettings& settings = ContextSettings());
////////////////////////////////////////////////////////////
/// \brief Create (or recreate) the window from an existing control
@@ -284,7 +284,7 @@ public :
/// \see setIcon
///
////////////////////////////////////////////////////////////
- void setTitle(const std::string& title);
+ void setTitle(const String& title);
////////////////////////////////////////////////////////////
/// \brief Change the window's icon
View
2  src/SFML/Graphics/RenderWindow.cpp
@@ -39,7 +39,7 @@ RenderWindow::RenderWindow()
////////////////////////////////////////////////////////////
-RenderWindow::RenderWindow(VideoMode mode, const std::string& title, Uint32 style, const ContextSettings& settings)
+RenderWindow::RenderWindow(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings)
{
// Don't call the base class constructor because it contains virtual function calls
create(mode, title, style, settings);
View
22 src/SFML/Window/Linux/WindowImplX11.cpp
@@ -35,6 +35,8 @@
#include <X11/extensions/Xrandr.h>
#include <sstream>
#include <vector>
+#include <string>
+#include <iterator>
////////////////////////////////////////////////////////////
@@ -91,7 +93,7 @@ m_keyRepeat (true)
////////////////////////////////////////////////////////////
-WindowImplX11::WindowImplX11(VideoMode mode, const std::string& title, unsigned long style) :
+WindowImplX11::WindowImplX11(VideoMode mode, const String& title, unsigned long style) :
m_window (0),
m_inputMethod (NULL),
m_inputContext(NULL),
@@ -313,9 +315,23 @@ void WindowImplX11::setSize(const Vector2u& size)
////////////////////////////////////////////////////////////
-void WindowImplX11::setTitle(const std::string& title)
+void WindowImplX11::setTitle(const String& title)
{
- XStoreName(m_display, m_window, title.c_str());
+ // Bare X11 has no Unicode window title support.
+ // There is however an option to tell the window manager your unicode title via hints.
+
+ // Convert to UTF-8 encoding.
+ std::basic_string<sf::Uint8> utf8Title;
+ std::wstring wideTitle = title.toWideString();
+ sf::Utf8::fromWide(wideTitle.begin(), wideTitle.end(), std::back_inserter(utf8Title));
+
+ Atom wmName = XInternAtom(m_display, "_NET_WM_NAME", False);
+ Atom useUtf8 = XInternAtom(m_display, "UTF8_STRING", False);
+ XChangeProperty(m_display, m_window, wmName, useUtf8, 8,
+ PropModeReplace, utf8Title.c_str(), utf8Title.size());
+
+ // Set the non-Unicode title as a fallback for window managers who don't support _NET_WM_NAME.
+ XStoreName(m_display, m_window, title.toAnsiString().c_str());
}
View
6 src/SFML/Window/Linux/WindowImplX11.hpp
@@ -30,9 +30,9 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/Event.hpp>
#include <SFML/Window/WindowImpl.hpp>
+#include <SFML/System/String.hpp>
#include <X11/Xlib.h>
#include <set>
-#include <string>
namespace sf
@@ -63,7 +63,7 @@ public :
/// \param style Window style (resizable, fixed, or fullscren)
///
////////////////////////////////////////////////////////////
- WindowImplX11(VideoMode mode, const std::string& title, unsigned long style);
+ WindowImplX11(VideoMode mode, const String& title, unsigned long style);
////////////////////////////////////////////////////////////
/// \brief Destructor
@@ -117,7 +117,7 @@ public :
/// \param title New title
///
////////////////////////////////////////////////////////////
- virtual void setTitle(const std::string& title);
+ virtual void setTitle(const String& title);
////////////////////////////////////////////////////////////
/// \brief Change the window's icon
View
5 src/SFML/Window/OSX/WindowImplCocoa.hpp
@@ -31,6 +31,7 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/Event.hpp>
#include <SFML/Window/WindowImpl.hpp>
+#include <SFML/System/String.hpp>
////////////////////////////////////////////////////////////
/// Predefine OBJC classes
@@ -79,7 +80,7 @@ public :
/// \param style Window style (resizable, fixed, or fullscren)
///
////////////////////////////////////////////////////////////
- WindowImplCocoa(VideoMode mode, const std::string& title, unsigned long style);
+ WindowImplCocoa(VideoMode mode, const String& title, unsigned long style);
////////////////////////////////////////////////////////////
/// \brief Destructor
@@ -280,7 +281,7 @@ public :
/// \param title New title
///
////////////////////////////////////////////////////////////
- virtual void setTitle(const std::string& title);
+ virtual void setTitle(const String& title);
////////////////////////////////////////////////////////////
/// \brief Change the window's icon
View
9 src/SFML/Window/OSX/WindowImplCocoa.mm
@@ -28,6 +28,7 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/OSX/WindowImplCocoa.hpp>
#include <SFML/System/Err.hpp>
+#include <SFML/System/String.hpp>
#import <SFML/Window/OSX/SFWindowController.h>
#import <SFML/Window/OSX/SFViewController.h>
@@ -80,7 +81,7 @@
////////////////////////////////////////////////////////////
WindowImplCocoa::WindowImplCocoa(VideoMode mode,
- const std::string& title,
+ const String& title,
unsigned long style)
: m_showCursor(true)
{
@@ -91,7 +92,7 @@
retainPool();
m_delegate = [[SFWindowController alloc] initWithMode:mode andStyle:style];
- [m_delegate changeTitle:stringToNSString(title)];
+ [m_delegate changeTitle:sfStringToNSString(title)];
[m_delegate setRequesterTo:this];
}
@@ -362,9 +363,9 @@
////////////////////////////////////////////////////////////
-void WindowImplCocoa::setTitle(const std::string& title)
+void WindowImplCocoa::setTitle(const String& title)
{
- [m_delegate changeTitle:stringToNSString(title)];
+ [m_delegate changeTitle:sfStringToNSString(title)];
}
View
3  src/SFML/Window/OSX/cpp_objc_conversion.h
@@ -27,6 +27,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <string>
+#include <SFML/System/String.hpp>
#import <Foundation/Foundation.h>
@@ -35,4 +36,4 @@
///
////////////////////////////////////////////////////////////
NSString* stringToNSString(std::string const& string);
-
+NSString* sfStringToNSString(sf::String const& string);
View
9 src/SFML/Window/OSX/cpp_objc_conversion.mm
@@ -40,3 +40,12 @@
return str;
}
+////////////////////////////////////////////////////////////
+NSString* sfStringToNSString(sf::String const& string)
+{
+ sf::Uint32 length = string.getSize() * sizeof(sf::Uint32);
+ const void* data = reinterpret_cast<const void*>(string.getData());
+ NSString* str = [[NSString alloc] initWithBytes:data length:length encoding:NSUTF32LittleEndianStringEncoding];
+
+ return str;
+}
View
22 src/SFML/Window/Win32/WindowImplWin32.cpp
@@ -37,6 +37,7 @@
#include <SFML/Window/WindowStyle.hpp>
#include <GL/gl.h>
#include <SFML/System/Err.hpp>
+#include <SFML/System/Utf.hpp>
#include <vector>
// MinGW lacks the definition of some Win32 constants
@@ -84,7 +85,7 @@ m_resizing (false)
////////////////////////////////////////////////////////////
-WindowImplWin32::WindowImplWin32(VideoMode mode, const std::string& title, Uint32 style) :
+WindowImplWin32::WindowImplWin32(VideoMode mode, const String& title, Uint32 style) :
m_handle (NULL),
m_callback (0),
m_cursor (NULL),
@@ -132,14 +133,11 @@ m_resizing (false)
// Create the window
if (hasUnicodeSupport())
{
- wchar_t wTitle[256];
- int count = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, title.c_str(), static_cast<int>(title.size()), wTitle, sizeof(wTitle) / sizeof(*wTitle));
- wTitle[count] = L'\0';
- m_handle = CreateWindowW(classNameW, wTitle, win32Style, left, top, width, height, NULL, NULL, GetModuleHandle(NULL), this);
+ m_handle = CreateWindowW(classNameW, title.toWideString().c_str(), win32Style, left, top, width, height, NULL, NULL, GetModuleHandle(NULL), this);
}
else
{
- m_handle = CreateWindowA(classNameA, title.c_str(), win32Style, left, top, width, height, NULL, NULL, GetModuleHandle(NULL), this);
+ m_handle = CreateWindowA(classNameA, title.toAnsiString().c_str(), win32Style, left, top, width, height, NULL, NULL, GetModuleHandle(NULL), this);
}
// Switch to fullscreen if requested
@@ -253,9 +251,16 @@ void WindowImplWin32::setSize(const Vector2u& size)
////////////////////////////////////////////////////////////
-void WindowImplWin32::setTitle(const std::string& title)
+void WindowImplWin32::setTitle(const String& title)
{
- SetWindowTextA(m_handle, title.c_str());
+ if (hasUnicodeSupport())
+ {
+ SetWindowTextW(m_handle, title.toWideString().c_str());
+ }
+ else
+ {
+ SetWindowTextA(m_handle, title.toAnsiString().c_str());
+ }
}
@@ -877,3 +882,4 @@ LRESULT CALLBACK WindowImplWin32::globalOnEvent(HWND handle, UINT message, WPARA
} // namespace priv
} // namespace sf
+
View
6 src/SFML/Window/Win32/WindowImplWin32.hpp
@@ -30,8 +30,8 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/Event.hpp>
#include <SFML/Window/WindowImpl.hpp>
+#include <SFML/System/String.hpp>
#include <windows.h>
-#include <string>
namespace sf
@@ -62,7 +62,7 @@ public :
/// \param style Window style
///
////////////////////////////////////////////////////////////
- WindowImplWin32(VideoMode mode, const std::string& title, Uint32 style);
+ WindowImplWin32(VideoMode mode, const String& title, Uint32 style);
////////////////////////////////////////////////////////////
/// \brief Destructor
@@ -116,7 +116,7 @@ public :
/// \param title New title
///
////////////////////////////////////////////////////////////
- virtual void setTitle(const std::string& title);
+ virtual void setTitle(const String& title);
////////////////////////////////////////////////////////////
/// \brief Change the window's icon
View
6 src/SFML/Window/Window.cpp
@@ -51,7 +51,7 @@ m_frameTimeLimit(Time::Zero)
////////////////////////////////////////////////////////////
-Window::Window(VideoMode mode, const std::string& title, Uint32 style, const ContextSettings& settings) :
+Window::Window(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings) :
m_impl (NULL),
m_context (NULL),
m_frameTimeLimit(Time::Zero)
@@ -78,7 +78,7 @@ Window::~Window()
////////////////////////////////////////////////////////////
-void Window::create(VideoMode mode, const std::string& title, Uint32 style, const ContextSettings& settings)
+void Window::create(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings)
{
// Destroy the previous window implementation
close();
@@ -236,7 +236,7 @@ void Window::setSize(const Vector2u size)
////////////////////////////////////////////////////////////
-void Window::setTitle(const std::string& title)
+void Window::setTitle(const String& title)
{
if (m_impl)
m_impl->setTitle(title);
View
2  src/SFML/Window/WindowImpl.cpp
@@ -55,7 +55,7 @@ namespace sf
namespace priv
{
////////////////////////////////////////////////////////////
-WindowImpl* WindowImpl::create(VideoMode mode, const std::string& title, Uint32 style)
+WindowImpl* WindowImpl::create(VideoMode mode, const String& title, Uint32 style)
{
return new WindowImplType(mode, title, style);
}
View
7 src/SFML/Window/WindowImpl.hpp
@@ -30,6 +30,7 @@
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <SFML/System/NonCopyable.hpp>
+#include <SFML/System/String.hpp>
#include <SFML/Window/Event.hpp>
#include <SFML/Window/Joystick.hpp>
#include <SFML/Window/JoystickImpl.hpp>
@@ -37,8 +38,6 @@
#include <SFML/Window/WindowHandle.hpp>
#include <queue>
#include <set>
-#include <string>
-
namespace sf
{
@@ -64,7 +63,7 @@ public :
/// \return Pointer to the created window (don't forget to delete it)
///
////////////////////////////////////////////////////////////
- static WindowImpl* create(VideoMode mode, const std::string& title, Uint32 style);
+ static WindowImpl* create(VideoMode mode, const String& title, Uint32 style);
////////////////////////////////////////////////////////////
/// \brief Create a new window depending on to the current OS
@@ -155,7 +154,7 @@ public :
/// \param title New title
///
////////////////////////////////////////////////////////////
- virtual void setTitle(const std::string& title) = 0;
+ virtual void setTitle(const String& title) = 0;
////////////////////////////////////////////////////////////
/// \brief Change the window's icon

5 comments on commit 6bc0776

@Kapho

Aren't these nearly the exact same changes as this?
#174

Not the same, but similar.

@eXpl0it3r
Owner

Could be but it has the important difference:

But I'm not really interested in partial implementations.

While Shizmob's implementation stretches across all the major platform and has been tested.
Sure some critical points Laurent made on the other pull request might have been ignored here.

Anyways what's your goal by pointing towards the similarities? ;)

@Kapho

I dunno. I'm curious as to why those critical points were ignored here. It seems silly, does it not?

@eXpl0it3r
Owner

By reading the other comments again there aren't many actual critical points. The following two sentences are very generic and maybe Laurent has already thought about them in more detail, but just didn't have time to get around implementing it:

For this task, the main point is to have a good overall design: there are probably other classes/functions that deal with strings and would benefit from Unicode strings. I need to find a global way of handling them in SFML. Then, is sf::String the best solution?

So unless you know more on what Laurent has thought when accepting the pull request, I guess you can't judge whether the points have been thought about or not.
And again the main difference between the pull requests are, that this one is clean, complete and tested, while the other one was quickly done and incomplete.
I still don't quite get what problem you see here...

@LaurentGomila

Fortunately, I sometimes change my mind so that some features end up being actually implemented ;)

In this case, the other functions that deal with strings are mainly (only?) those which take a filename, and supporting unicode filenames is a different story. The choice of the sf::String class for Unicode strings seems to be the best one with the current API, if something changes it won't happen before SFML 3.

So, right now it seems reasonable and realistic to me to apply this modification.

And yes, a complete and tested code makes a huge difference for integration.

Please sign in to comment.
Something went wrong with that request. Please try again.