Skip to content

Commit

Permalink
Added Unicode window title support.
Browse files Browse the repository at this point in the history
- 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
Shiz committed Feb 12, 2013
1 parent 9cf259c commit 6bc0776
Show file tree
Hide file tree
Showing 14 changed files with 71 additions and 38 deletions.
2 changes: 1 addition & 1 deletion include/SFML/Graphics/RenderWindow.hpp
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions include/SFML/Window/Window.hpp
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -284,7 +284,7 @@ public :
/// \see setIcon
///
////////////////////////////////////////////////////////////
void setTitle(const std::string& title);
void setTitle(const String& title);

////////////////////////////////////////////////////////////
/// \brief Change the window's icon
Expand Down
2 changes: 1 addition & 1 deletion src/SFML/Graphics/RenderWindow.cpp
Expand Up @@ -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);
Expand Down
22 changes: 19 additions & 3 deletions src/SFML/Window/Linux/WindowImplX11.cpp
Expand Up @@ -35,6 +35,8 @@
#include <X11/extensions/Xrandr.h>
#include <sstream>
#include <vector>
#include <string>
#include <iterator>


////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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());
}


Expand Down
6 changes: 3 additions & 3 deletions src/SFML/Window/Linux/WindowImplX11.hpp
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions src/SFML/Window/OSX/WindowImplCocoa.hpp
Expand Up @@ -31,6 +31,7 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/Event.hpp>
#include <SFML/Window/WindowImpl.hpp>
#include <SFML/System/String.hpp>

////////////////////////////////////////////////////////////
/// Predefine OBJC classes
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions src/SFML/Window/OSX/WindowImplCocoa.mm
Expand Up @@ -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>
Expand Down Expand Up @@ -80,7 +81,7 @@

////////////////////////////////////////////////////////////
WindowImplCocoa::WindowImplCocoa(VideoMode mode,
const std::string& title,
const String& title,
unsigned long style)
: m_showCursor(true)
{
Expand All @@ -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];
}

Expand Down Expand Up @@ -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)];
}


Expand Down
3 changes: 2 additions & 1 deletion src/SFML/Window/OSX/cpp_objc_conversion.h
Expand Up @@ -27,6 +27,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <string>
#include <SFML/System/String.hpp>

#import <Foundation/Foundation.h>

Expand All @@ -35,4 +36,4 @@
///
////////////////////////////////////////////////////////////
NSString* stringToNSString(std::string const& string);

NSString* sfStringToNSString(sf::String const& string);
9 changes: 9 additions & 0 deletions src/SFML/Window/OSX/cpp_objc_conversion.mm
Expand Up @@ -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;
}
22 changes: 14 additions & 8 deletions src/SFML/Window/Win32/WindowImplWin32.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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());
}
}


Expand Down Expand Up @@ -877,3 +882,4 @@ LRESULT CALLBACK WindowImplWin32::globalOnEvent(HWND handle, UINT message, WPARA
} // namespace priv

} // namespace sf

6 changes: 3 additions & 3 deletions src/SFML/Window/Win32/WindowImplWin32.hpp
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions src/SFML/Window/Window.cpp
Expand Up @@ -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)
Expand All @@ -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();
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/SFML/Window/WindowImpl.cpp
Expand Up @@ -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);
}
Expand Down
7 changes: 3 additions & 4 deletions src/SFML/Window/WindowImpl.hpp
Expand Up @@ -30,15 +30,14 @@
////////////////////////////////////////////////////////////
#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>
#include <SFML/Window/VideoMode.hpp>
#include <SFML/Window/WindowHandle.hpp>
#include <queue>
#include <set>
#include <string>


namespace sf
{
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down

5 comments on commit 6bc0776

@Kapho
Copy link

@Kapho Kapho commented on 6bc0776 Mar 4, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Not the same, but similar.

@eXpl0it3r
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link

@Kapho Kapho commented on 6bc0776 Mar 5, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@eXpl0it3r
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.