mirror of
https://github.com/SFML/SFML.git
synced 2024-11-28 22:31:09 +08:00
Implemented methods to set the displayed cursor to a system cursor type or custom bitmap image.
This commit is contained in:
parent
bd479c4454
commit
6f5a7d1b1b
@ -56,6 +56,29 @@ class Event;
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
class SFML_WINDOW_API Window : GlResource, NonCopyable
|
class SFML_WINDOW_API Window : GlResource, NonCopyable
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Enumeration of the native system cursor types
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
enum Cursor
|
||||||
|
{
|
||||||
|
Arrow, ///< Arrow cursor (default)
|
||||||
|
ArrowWait, ///< Busy arrow cursor
|
||||||
|
Wait, ///< Busy cursor
|
||||||
|
Text, ///< I-beam, cursor when hovering over a field allowing text entry
|
||||||
|
Hand, ///< Pointing hand cursor
|
||||||
|
SizeHorizontal, ///< Horizontal double arrow cursor
|
||||||
|
SizeVertical, ///< Vertical double arrow cursor
|
||||||
|
SizeTopLeftBottomRight, ///< Double arrow cursor going from top-left to bottom-right
|
||||||
|
SizeBottomLeftTopRight, ///< Double arrow cursor going from bottom-left to top-right
|
||||||
|
SizeAll, ///< Combination of CursorSizeHorizontal and CursorSizeVertical
|
||||||
|
Cross, ///< Crosshair cursor
|
||||||
|
Help, ///< Help cursor
|
||||||
|
NotAllowed ///< Action not allowed cursor
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -361,6 +384,43 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void setMouseCursorGrabbed(bool grabbed);
|
void setMouseCursorGrabbed(bool grabbed);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the displayed cursor to a native system cursor
|
||||||
|
///
|
||||||
|
/// Upon window creation, the arrow cursor is used by default.
|
||||||
|
///
|
||||||
|
/// \param cursor Native system cursor type to display
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void setMouseCursor(Cursor cursor);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the displayed cursor to the provided image
|
||||||
|
///
|
||||||
|
/// \a pixels must be an array of \a width x \a height pixels
|
||||||
|
/// in 32-bit RGBA format. If not, this will cause undefined behavior.
|
||||||
|
///
|
||||||
|
/// If \a pixels is null or either \a width or \a height are 0,
|
||||||
|
/// the current cursor is left unchanged.
|
||||||
|
///
|
||||||
|
/// In addition to specifying the pixel data, you can also
|
||||||
|
/// specify the location of the hotspot of the cursor. The
|
||||||
|
/// hotspot is the pixel coordinate within the cursor image
|
||||||
|
/// which will be located exactly where the mouse pointer
|
||||||
|
/// position is. Any mouse actions that are performed will
|
||||||
|
/// return the window/screen location of the hotspot.
|
||||||
|
///
|
||||||
|
/// Upon window creation, the arrow cursor is used by default.
|
||||||
|
///
|
||||||
|
/// \param pixels Array of pixels of the image
|
||||||
|
/// \param width Width of the image
|
||||||
|
/// \param height Height of the image
|
||||||
|
/// \param hotspotX X location of the hotspot
|
||||||
|
/// \param hotspotY Y location of the hotspot
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void setMouseCursor(const Uint8* pixels, unsigned int width, unsigned int height, Uint16 hotspotX, Uint16 hotspotY);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Enable or disable automatic key-repeat
|
/// \brief Enable or disable automatic key-repeat
|
||||||
///
|
///
|
||||||
|
@ -185,6 +185,20 @@ void WindowImplAndroid::setMouseCursorGrabbed(bool grabbed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void WindowImplAndroid::setMouseCursor(Window::Cursor cursor)
|
||||||
|
{
|
||||||
|
// Not applicable
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void WindowImplAndroid::setMouseCursor(const Uint8* pixels, unsigned int width, unsigned int height, Uint16 hotspotX, Uint16 hotspotY)
|
||||||
|
{
|
||||||
|
// Not applicable
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplAndroid::setKeyRepeatEnabled(bool enabled)
|
void WindowImplAndroid::setKeyRepeatEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
|
@ -154,6 +154,26 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
virtual void setMouseCursorGrabbed(bool grabbed);
|
virtual void setMouseCursorGrabbed(bool grabbed);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the displayed cursor to a native system cursor
|
||||||
|
///
|
||||||
|
/// \param cursor Native system cursor type to display
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void setMouseCursor(Window::Cursor cursor);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the displayed cursor to the provided image
|
||||||
|
///
|
||||||
|
/// \param pixels Array of pixels of the image
|
||||||
|
/// \param width Width of the image
|
||||||
|
/// \param height Height of the image
|
||||||
|
/// \param hotspotX X location of the hotspot
|
||||||
|
/// \param hotspotY Y location of the hotspot
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void setMouseCursor(const Uint8* pixels, unsigned int width, unsigned int height, Uint16 hotspotX, Uint16 hotspotY);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Enable or disable automatic key-repeat
|
/// \brief Enable or disable automatic key-repeat
|
||||||
///
|
///
|
||||||
|
@ -321,6 +321,26 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
virtual void setMouseCursorGrabbed(bool grabbed);
|
virtual void setMouseCursorGrabbed(bool grabbed);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the displayed cursor to a native system cursor
|
||||||
|
///
|
||||||
|
/// \param cursor Native system cursor type to display
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void setMouseCursor(Window::Cursor cursor);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the displayed cursor to the provided image
|
||||||
|
///
|
||||||
|
/// \param pixels Array of pixels of the image
|
||||||
|
/// \param width Width of the image
|
||||||
|
/// \param height Height of the image
|
||||||
|
/// \param hotspotX X location of the hotspot
|
||||||
|
/// \param hotspotY Y location of the hotspot
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void setMouseCursor(const Uint8* pixels, unsigned int width, unsigned int height, Uint16 hotspotX, Uint16 hotspotY);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Enable or disable automatic key-repeat
|
/// \brief Enable or disable automatic key-repeat
|
||||||
///
|
///
|
||||||
|
@ -493,6 +493,20 @@ void WindowImplCocoa::setMouseCursorGrabbed(bool grabbed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void WindowImplCocoa::setMouseCursor(Window::Cursor cursor)
|
||||||
|
{
|
||||||
|
// TODO: Implement OS X cursor setting
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void WindowImplCocoa::setMouseCursor(const Uint8* pixels, unsigned int width, unsigned int height, Uint16 hotspotX, Uint16 hotspotY)
|
||||||
|
{
|
||||||
|
// TODO: Implement OS X cursor setting
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplCocoa::setKeyRepeatEnabled(bool enabled)
|
void WindowImplCocoa::setKeyRepeatEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
#include <SFML/Window/Unix/WindowImplX11.hpp> // important to be included first (conflict with None)
|
||||||
#include <SFML/Window/Unix/GlxContext.hpp>
|
#include <SFML/Window/Unix/GlxContext.hpp>
|
||||||
#include <SFML/Window/Unix/WindowImplX11.hpp>
|
|
||||||
#include <SFML/Window/Unix/Display.hpp>
|
#include <SFML/Window/Unix/Display.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
#include <SFML/System/Mutex.hpp>
|
||||||
#include <SFML/System/Lock.hpp>
|
#include <SFML/System/Lock.hpp>
|
||||||
|
@ -900,6 +900,250 @@ void WindowImplX11::setMouseCursorVisible(bool visible)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void WindowImplX11::setMouseCursor(Window::Cursor cursor)
|
||||||
|
{
|
||||||
|
xcb_cursor_t newCursor = 0;
|
||||||
|
|
||||||
|
xcb_cursor_context_t* cursorContext = NULL;
|
||||||
|
|
||||||
|
if (xcb_cursor_context_new(m_connection, m_screen, &cursorContext) < 0)
|
||||||
|
{
|
||||||
|
err() << "Could not create XCB cursor context" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(cursor)
|
||||||
|
{
|
||||||
|
case Window::Arrow: newCursor = xcb_cursor_load_cursor(cursorContext, "left_ptr"); break;
|
||||||
|
case Window::ArrowWait: newCursor = xcb_cursor_load_cursor(cursorContext, "left_ptr"); break;
|
||||||
|
case Window::Wait: newCursor = xcb_cursor_load_cursor(cursorContext, "watch"); break;
|
||||||
|
case Window::Text: newCursor = xcb_cursor_load_cursor(cursorContext, "xterm"); break;
|
||||||
|
case Window::Hand: newCursor = xcb_cursor_load_cursor(cursorContext, "hand2"); break;
|
||||||
|
case Window::SizeHorizontal: newCursor = xcb_cursor_load_cursor(cursorContext, "sb_h_double_arrow"); break;
|
||||||
|
case Window::SizeVertical: newCursor = xcb_cursor_load_cursor(cursorContext, "sb_v_double_arrow"); break;
|
||||||
|
case Window::SizeTopLeftBottomRight: newCursor = xcb_cursor_load_cursor(cursorContext, "fleur"); break;
|
||||||
|
case Window::SizeBottomLeftTopRight: newCursor = xcb_cursor_load_cursor(cursorContext, "fleur"); break;
|
||||||
|
case Window::SizeAll: newCursor = xcb_cursor_load_cursor(cursorContext, "fleur"); break;
|
||||||
|
case Window::Cross: newCursor = xcb_cursor_load_cursor(cursorContext, "crosshair"); break;
|
||||||
|
case Window::Help: newCursor = xcb_cursor_load_cursor(cursorContext, "question_arrow"); break;
|
||||||
|
case Window::NotAllowed: newCursor = xcb_cursor_load_cursor(cursorContext, "left_ptr"); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_cursor_context_free(cursorContext);
|
||||||
|
|
||||||
|
if (m_loadedCursor)
|
||||||
|
xcb_free_cursor(m_connection, m_loadedCursor);
|
||||||
|
|
||||||
|
if (!newCursor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_loadedCursor = newCursor;
|
||||||
|
|
||||||
|
if (!m_cursor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ScopedXcbPtr<xcb_generic_error_t> changeAttributesError(xcb_request_check(
|
||||||
|
m_connection,
|
||||||
|
xcb_change_window_attributes(
|
||||||
|
m_connection,
|
||||||
|
m_window,
|
||||||
|
XCB_CW_CURSOR,
|
||||||
|
&m_loadedCursor
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
if (changeAttributesError)
|
||||||
|
{
|
||||||
|
err() << "Failed to change window attributes" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cursor = m_loadedCursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void WindowImplX11::setMouseCursor(const Uint8* pixels, unsigned int width, unsigned int height, Uint16 hotspotX, Uint16 hotspotY)
|
||||||
|
{
|
||||||
|
// Get the picture format from XCB
|
||||||
|
ScopedXcbPtr<xcb_render_query_pict_formats_reply_t> pictFormatsreply(xcb_render_query_pict_formats_reply(
|
||||||
|
m_connection,
|
||||||
|
xcb_render_query_pict_formats(
|
||||||
|
m_connection
|
||||||
|
),
|
||||||
|
NULL
|
||||||
|
));
|
||||||
|
|
||||||
|
xcb_render_pictformat_t pictureFormat = xcb_render_util_find_standard_format(pictFormatsreply.get(), XCB_PICT_STANDARD_ARGB_32)->id;
|
||||||
|
|
||||||
|
if (!pictureFormat)
|
||||||
|
{
|
||||||
|
err() << "Failed to get picture format from XCB" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// X11 wants BGRA pixels: swap red and blue channels
|
||||||
|
Uint8 cursorPixels[width * height * 4];
|
||||||
|
for (std::size_t i = 0; i < width * height; ++i)
|
||||||
|
{
|
||||||
|
cursorPixels[i * 4 + 0] = pixels[i * 4 + 2];
|
||||||
|
cursorPixels[i * 4 + 1] = pixels[i * 4 + 1];
|
||||||
|
cursorPixels[i * 4 + 2] = pixels[i * 4 + 0];
|
||||||
|
cursorPixels[i * 4 + 3] = pixels[i * 4 + 3];
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_pixmap_t cursorPixmap = xcb_generate_id(m_connection);
|
||||||
|
ScopedXcbPtr<xcb_generic_error_t> pixmapError(xcb_request_check(
|
||||||
|
m_connection,
|
||||||
|
xcb_create_pixmap(
|
||||||
|
m_connection,
|
||||||
|
32,
|
||||||
|
cursorPixmap,
|
||||||
|
m_window,
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
if (pixmapError)
|
||||||
|
{
|
||||||
|
err() << "Failed to create XCB cursor pixmap" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_gcontext_t cursorGC = xcb_generate_id(m_connection);
|
||||||
|
ScopedXcbPtr<xcb_generic_error_t> gcError(xcb_request_check(
|
||||||
|
m_connection,
|
||||||
|
xcb_create_gc(
|
||||||
|
m_connection,
|
||||||
|
cursorGC,
|
||||||
|
cursorPixmap,
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
if (gcError)
|
||||||
|
{
|
||||||
|
err() << "Failed to create XCB graphics context" << std::endl;
|
||||||
|
xcb_free_pixmap(m_connection, cursorPixmap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_image_t* cursorImage = xcb_image_create_native(
|
||||||
|
m_connection,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
XCB_IMAGE_FORMAT_Z_PIXMAP,
|
||||||
|
32,
|
||||||
|
NULL,
|
||||||
|
width * height * 4,
|
||||||
|
cursorPixels
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!cursorImage)
|
||||||
|
{
|
||||||
|
err() << "Failed to create XCB cursor image" << std::endl;
|
||||||
|
xcb_free_gc(m_connection, cursorGC);
|
||||||
|
xcb_free_pixmap(m_connection, cursorPixmap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedXcbPtr<xcb_generic_error_t> imagePutError(xcb_request_check(
|
||||||
|
m_connection,
|
||||||
|
xcb_image_put(
|
||||||
|
m_connection,
|
||||||
|
cursorPixmap,
|
||||||
|
cursorGC,
|
||||||
|
cursorImage,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
if (imagePutError)
|
||||||
|
{
|
||||||
|
err() << "Failed to put XCB image on the X server" << std::endl;
|
||||||
|
xcb_image_destroy(cursorImage);
|
||||||
|
xcb_free_gc(m_connection, cursorGC);
|
||||||
|
xcb_free_pixmap(m_connection, cursorPixmap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_render_picture_t cursorPicture = xcb_generate_id(m_connection);
|
||||||
|
ScopedXcbPtr<xcb_generic_error_t> createPictureError(xcb_request_check(
|
||||||
|
m_connection,
|
||||||
|
xcb_render_create_picture(
|
||||||
|
m_connection,
|
||||||
|
cursorPicture,
|
||||||
|
cursorPixmap,
|
||||||
|
pictureFormat,
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
if (createPictureError)
|
||||||
|
{
|
||||||
|
err() << "Failed to create XCB cursor picture" << std::endl;
|
||||||
|
xcb_image_destroy(cursorImage);
|
||||||
|
xcb_free_gc(m_connection, cursorGC);
|
||||||
|
xcb_free_pixmap(m_connection, cursorPixmap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_cursor_t newCursor = xcb_generate_id(m_connection);
|
||||||
|
ScopedXcbPtr<xcb_generic_error_t> createCursorError(xcb_request_check(
|
||||||
|
m_connection,
|
||||||
|
xcb_render_create_cursor(
|
||||||
|
m_connection,
|
||||||
|
newCursor,
|
||||||
|
cursorPicture,
|
||||||
|
hotspotX,
|
||||||
|
hotspotY
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
xcb_render_free_picture(m_connection, cursorPicture);
|
||||||
|
xcb_image_destroy(cursorImage);
|
||||||
|
xcb_free_gc(m_connection, cursorGC);
|
||||||
|
xcb_free_pixmap(m_connection, cursorPixmap);
|
||||||
|
|
||||||
|
if (createCursorError)
|
||||||
|
{
|
||||||
|
err() << "Failed to create XCB cursor" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_free_cursor(m_connection, m_loadedCursor);
|
||||||
|
m_loadedCursor = newCursor;
|
||||||
|
|
||||||
|
if (!m_cursor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ScopedXcbPtr<xcb_generic_error_t> changeAttributesError(xcb_request_check(
|
||||||
|
m_connection,
|
||||||
|
xcb_change_window_attributes(
|
||||||
|
m_connection,
|
||||||
|
m_window,
|
||||||
|
XCB_CW_CURSOR,
|
||||||
|
&m_loadedCursor
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
|
if (changeAttributesError)
|
||||||
|
{
|
||||||
|
err() << "Failed to change window attributes" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cursor = m_loadedCursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplX11::setMouseCursorGrabbed(bool grabbed)
|
void WindowImplX11::setMouseCursorGrabbed(bool grabbed)
|
||||||
{
|
{
|
||||||
@ -1306,9 +1550,6 @@ void WindowImplX11::initialize()
|
|||||||
// Raise the window and grab input focus
|
// Raise the window and grab input focus
|
||||||
grabFocus();
|
grabFocus();
|
||||||
|
|
||||||
// Create the hidden cursor
|
|
||||||
createHiddenCursor();
|
|
||||||
|
|
||||||
// Flush the commands queue
|
// Flush the commands queue
|
||||||
XFlush(m_display);
|
XFlush(m_display);
|
||||||
|
|
||||||
|
@ -154,6 +154,26 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
virtual void setMouseCursorGrabbed(bool grabbed);
|
virtual void setMouseCursorGrabbed(bool grabbed);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the displayed cursor to a native system cursor
|
||||||
|
///
|
||||||
|
/// \param cursor Native system cursor type to display
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void setMouseCursor(Window::Cursor cursor);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the displayed cursor to the provided image
|
||||||
|
///
|
||||||
|
/// \param pixels Array of pixels of the image
|
||||||
|
/// \param width Width of the image
|
||||||
|
/// \param height Height of the image
|
||||||
|
/// \param hotspotX X location of the hotspot
|
||||||
|
/// \param hotspotY Y location of the hotspot
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void setMouseCursor(const Uint8* pixels, unsigned int width, unsigned int height, Uint16 hotspotX, Uint16 hotspotY);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Enable or disable automatic key-repeat
|
/// \brief Enable or disable automatic key-repeat
|
||||||
///
|
///
|
||||||
@ -233,12 +253,6 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
/// \brief Create a transparent mouse cursor
|
|
||||||
///
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
void createHiddenCursor();
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Cleanup graphical resources attached to the window
|
/// \brief Cleanup graphical resources attached to the window
|
||||||
///
|
///
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <SFML/System/Utf.hpp>
|
#include <SFML/System/Utf.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
// MinGW lacks the definition of some Win32 constants
|
// MinGW lacks the definition of some Win32 constants
|
||||||
#ifndef XBUTTON1
|
#ifndef XBUTTON1
|
||||||
@ -132,6 +133,7 @@ WindowImplWin32::WindowImplWin32(WindowHandle handle) :
|
|||||||
m_handle (handle),
|
m_handle (handle),
|
||||||
m_callback (0),
|
m_callback (0),
|
||||||
m_cursor (NULL),
|
m_cursor (NULL),
|
||||||
|
m_loadedCursor (NULL),
|
||||||
m_icon (NULL),
|
m_icon (NULL),
|
||||||
m_keyRepeatEnabled(true),
|
m_keyRepeatEnabled(true),
|
||||||
m_lastSize (0, 0),
|
m_lastSize (0, 0),
|
||||||
@ -164,6 +166,7 @@ WindowImplWin32::WindowImplWin32(VideoMode mode, const String& title, Uint32 sty
|
|||||||
m_handle (NULL),
|
m_handle (NULL),
|
||||||
m_callback (0),
|
m_callback (0),
|
||||||
m_cursor (NULL),
|
m_cursor (NULL),
|
||||||
|
m_loadedCursor (NULL),
|
||||||
m_icon (NULL),
|
m_icon (NULL),
|
||||||
m_keyRepeatEnabled(true),
|
m_keyRepeatEnabled(true),
|
||||||
m_lastSize (mode.width, mode.height),
|
m_lastSize (mode.width, mode.height),
|
||||||
@ -238,6 +241,10 @@ m_cursorGrabbed (m_fullscreen)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
WindowImplWin32::~WindowImplWin32()
|
WindowImplWin32::~WindowImplWin32()
|
||||||
{
|
{
|
||||||
|
// Destroy the cursor
|
||||||
|
if (m_loadedCursor)
|
||||||
|
DestroyCursor(m_loadedCursor);
|
||||||
|
|
||||||
// Destroy the custom icon, if any
|
// Destroy the custom icon, if any
|
||||||
if (m_icon)
|
if (m_icon)
|
||||||
DestroyIcon(m_icon);
|
DestroyIcon(m_icon);
|
||||||
@ -389,8 +396,12 @@ void WindowImplWin32::setVisible(bool visible)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplWin32::setMouseCursorVisible(bool visible)
|
void WindowImplWin32::setMouseCursorVisible(bool visible)
|
||||||
{
|
{
|
||||||
|
// Set the default mouse cursor if none has been loaded yet
|
||||||
|
if (!m_loadedCursor)
|
||||||
|
setMouseCursor(Window::Arrow);
|
||||||
|
|
||||||
if (visible)
|
if (visible)
|
||||||
m_cursor = LoadCursorW(NULL, IDC_ARROW);
|
m_cursor = m_loadedCursor;
|
||||||
else
|
else
|
||||||
m_cursor = NULL;
|
m_cursor = NULL;
|
||||||
|
|
||||||
@ -406,6 +417,139 @@ void WindowImplWin32::setMouseCursorGrabbed(bool grabbed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void WindowImplWin32::setMouseCursor(Window::Cursor cursor)
|
||||||
|
{
|
||||||
|
HCURSOR newCursor = NULL;
|
||||||
|
|
||||||
|
switch (cursor)
|
||||||
|
{
|
||||||
|
case Window::Arrow: newCursor = LoadCursor(NULL, IDC_ARROW); break;
|
||||||
|
case Window::ArrowWait: newCursor = LoadCursor(NULL, IDC_APPSTARTING); break;
|
||||||
|
case Window::Wait: newCursor = LoadCursor(NULL, IDC_WAIT); break;
|
||||||
|
case Window::Text: newCursor = LoadCursor(NULL, IDC_IBEAM); break;
|
||||||
|
case Window::Hand: newCursor = LoadCursor(NULL, IDC_HAND); break;
|
||||||
|
case Window::SizeHorizontal: newCursor = LoadCursor(NULL, IDC_SIZEWE); break;
|
||||||
|
case Window::SizeVertical: newCursor = LoadCursor(NULL, IDC_SIZENS); break;
|
||||||
|
case Window::SizeTopLeftBottomRight: newCursor = LoadCursor(NULL, IDC_SIZENWSE); break;
|
||||||
|
case Window::SizeBottomLeftTopRight: newCursor = LoadCursor(NULL, IDC_SIZENESW); break;
|
||||||
|
case Window::SizeAll: newCursor = LoadCursor(NULL, IDC_SIZEALL); break;
|
||||||
|
case Window::Cross: newCursor = LoadCursor(NULL, IDC_CROSS); break;
|
||||||
|
case Window::Help: newCursor = LoadCursor(NULL, IDC_HELP); break;
|
||||||
|
case Window::NotAllowed: newCursor = LoadCursor(NULL, IDC_NO); break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a copy of the shared system cursor that we can destroy later
|
||||||
|
newCursor = CopyCursor(newCursor);
|
||||||
|
|
||||||
|
if (!newCursor)
|
||||||
|
{
|
||||||
|
err() << "Could not create copy of a system cursor" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HCURSOR oldCursor = m_loadedCursor;
|
||||||
|
m_loadedCursor = newCursor;
|
||||||
|
|
||||||
|
if (m_cursor)
|
||||||
|
{
|
||||||
|
m_cursor = m_loadedCursor;
|
||||||
|
SetCursor(m_cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldCursor)
|
||||||
|
DestroyCursor(oldCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void WindowImplWin32::setMouseCursor(const Uint8* pixels, unsigned int width, unsigned int height, Uint16 hotspotX, Uint16 hotspotY)
|
||||||
|
{
|
||||||
|
// Create the bitmap that will hold our color data
|
||||||
|
BITMAPV5HEADER bitmapHeader;
|
||||||
|
std::memset(&bitmapHeader, 0, sizeof(BITMAPV5HEADER));
|
||||||
|
|
||||||
|
bitmapHeader.bV5Size = sizeof(BITMAPV5HEADER);
|
||||||
|
bitmapHeader.bV5Width = width;
|
||||||
|
bitmapHeader.bV5Height = -height; // Negative indicates origin is in upper-left corner
|
||||||
|
bitmapHeader.bV5Planes = 1;
|
||||||
|
bitmapHeader.bV5BitCount = 32;
|
||||||
|
bitmapHeader.bV5Compression = BI_BITFIELDS;
|
||||||
|
bitmapHeader.bV5RedMask = 0x00ff0000;
|
||||||
|
bitmapHeader.bV5GreenMask = 0x0000ff00;
|
||||||
|
bitmapHeader.bV5BlueMask = 0x000000ff;
|
||||||
|
bitmapHeader.bV5AlphaMask = 0xff000000;
|
||||||
|
|
||||||
|
Uint8* bitmapData = NULL;
|
||||||
|
|
||||||
|
HDC screenDC = GetDC(NULL);
|
||||||
|
HBITMAP color = CreateDIBSection(
|
||||||
|
screenDC,
|
||||||
|
reinterpret_cast<const BITMAPINFO*>(&bitmapHeader),
|
||||||
|
DIB_RGB_COLORS,
|
||||||
|
reinterpret_cast<void**>(&bitmapData),
|
||||||
|
NULL,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
ReleaseDC(NULL, screenDC);
|
||||||
|
|
||||||
|
if (!color)
|
||||||
|
{
|
||||||
|
err() << "Failed to create cursor color bitmap" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill our bitmap with the cursor color data
|
||||||
|
std::memcpy(bitmapData, pixels, width * height * 4);
|
||||||
|
|
||||||
|
// Create a dummy mask bitmap (it won't be used)
|
||||||
|
HBITMAP mask = CreateBitmap(width, height, 1, 1, NULL);
|
||||||
|
|
||||||
|
if (!mask)
|
||||||
|
{
|
||||||
|
DeleteObject(color);
|
||||||
|
err() << "Failed to create cursor mask bitmap" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the structure that describes our cursor
|
||||||
|
ICONINFO cursorInfo;
|
||||||
|
std::memset(&cursorInfo, 0, sizeof(ICONINFO));
|
||||||
|
|
||||||
|
cursorInfo.fIcon = FALSE; // This is a cursor and not an icon
|
||||||
|
cursorInfo.xHotspot = hotspotX;
|
||||||
|
cursorInfo.yHotspot = hotspotY;
|
||||||
|
cursorInfo.hbmColor = color;
|
||||||
|
cursorInfo.hbmMask = mask;
|
||||||
|
|
||||||
|
// Create the cursor
|
||||||
|
HCURSOR newCursor = reinterpret_cast<HCURSOR>(CreateIconIndirect(&cursorInfo));
|
||||||
|
|
||||||
|
// The data has been copied into the cursor, so get rid of these
|
||||||
|
DeleteObject(color);
|
||||||
|
DeleteObject(mask);
|
||||||
|
|
||||||
|
if (!newCursor)
|
||||||
|
{
|
||||||
|
err() << "Failed to create cursor from bitmaps" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HCURSOR oldCursor = m_loadedCursor;
|
||||||
|
m_loadedCursor = newCursor;
|
||||||
|
|
||||||
|
if (m_cursor)
|
||||||
|
{
|
||||||
|
m_cursor = m_loadedCursor;
|
||||||
|
SetCursor(m_cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldCursor)
|
||||||
|
DestroyCursor(oldCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplWin32::setKeyRepeatEnabled(bool enabled)
|
void WindowImplWin32::setKeyRepeatEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
|
@ -153,6 +153,26 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
virtual void setMouseCursorGrabbed(bool grabbed);
|
virtual void setMouseCursorGrabbed(bool grabbed);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the displayed cursor to a native system cursor
|
||||||
|
///
|
||||||
|
/// \param cursor Native system cursor type to display
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void setMouseCursor(Window::Cursor cursor);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the displayed cursor to the provided image
|
||||||
|
///
|
||||||
|
/// \param pixels Array of pixels of the image
|
||||||
|
/// \param width Width of the image
|
||||||
|
/// \param height Height of the image
|
||||||
|
/// \param hotspotX X location of the hotspot
|
||||||
|
/// \param hotspotY Y location of the hotspot
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void setMouseCursor(const Uint8* pixels, unsigned int width, unsigned int height, Uint16 hotspotX, Uint16 hotspotY);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Enable or disable automatic key-repeat
|
/// \brief Enable or disable automatic key-repeat
|
||||||
///
|
///
|
||||||
@ -266,7 +286,8 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
HWND m_handle; ///< Win32 handle of the window
|
HWND m_handle; ///< Win32 handle of the window
|
||||||
LONG_PTR m_callback; ///< Stores the original event callback function of the control
|
LONG_PTR m_callback; ///< Stores the original event callback function of the control
|
||||||
HCURSOR m_cursor; ///< The system cursor to display into the window
|
HCURSOR m_cursor; ///< The system cursor currently displayed into the window, NULL if hidden
|
||||||
|
HCURSOR m_loadedCursor; ///< The system cursor selected to be displayed into the window
|
||||||
HICON m_icon; ///< Custom icon assigned to the window
|
HICON m_icon; ///< Custom icon assigned to the window
|
||||||
bool m_keyRepeatEnabled; ///< Automatic key-repeat state for keydown events
|
bool m_keyRepeatEnabled; ///< Automatic key-repeat state for keydown events
|
||||||
Vector2u m_lastSize; ///< The last handled size of the window
|
Vector2u m_lastSize; ///< The last handled size of the window
|
||||||
|
@ -296,6 +296,22 @@ void Window::setMouseCursorGrabbed(bool grabbed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Window::setMouseCursor(Cursor cursor)
|
||||||
|
{
|
||||||
|
if (m_impl)
|
||||||
|
m_impl->setMouseCursor(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Window::setMouseCursor(const Uint8* pixels, unsigned int width, unsigned int height, Uint16 hotspotX, Uint16 hotspotY)
|
||||||
|
{
|
||||||
|
if (m_impl && pixels && width && height)
|
||||||
|
m_impl->setMouseCursor(pixels, width, height, hotspotX, hotspotY);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Window::setKeyRepeatEnabled(bool enabled)
|
void Window::setKeyRepeatEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include <SFML/Window/VideoMode.hpp>
|
#include <SFML/Window/VideoMode.hpp>
|
||||||
#include <SFML/Window/WindowHandle.hpp>
|
#include <SFML/Window/WindowHandle.hpp>
|
||||||
#include <SFML/Window/ContextSettings.hpp>
|
#include <SFML/Window/ContextSettings.hpp>
|
||||||
|
#include <SFML/Window/Window.hpp>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
@ -194,6 +195,26 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
virtual void setMouseCursorGrabbed(bool grabbed) = 0;
|
virtual void setMouseCursorGrabbed(bool grabbed) = 0;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the displayed cursor to a native system cursor
|
||||||
|
///
|
||||||
|
/// \param cursor Native system cursor type to display
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void setMouseCursor(Window::Cursor cursor) = 0;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the displayed cursor to the provided image
|
||||||
|
///
|
||||||
|
/// \param pixels Array of pixels of the image
|
||||||
|
/// \param width Width of the image
|
||||||
|
/// \param height Height of the image
|
||||||
|
/// \param hotspotX X location of the hotspot
|
||||||
|
/// \param hotspotY Y location of the hotspot
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void setMouseCursor(const Uint8* pixels, unsigned int width, unsigned int height, Uint16 hotspotX, Uint16 hotspotY) = 0;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Enable or disable automatic key-repeat
|
/// \brief Enable or disable automatic key-repeat
|
||||||
///
|
///
|
||||||
|
@ -157,6 +157,26 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
virtual void setMouseCursorGrabbed(bool grabbed);
|
virtual void setMouseCursorGrabbed(bool grabbed);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the displayed cursor to a native system cursor
|
||||||
|
///
|
||||||
|
/// \param cursor Native system cursor type to display
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void setMouseCursor(Window::Cursor cursor);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Set the displayed cursor to the provided image
|
||||||
|
///
|
||||||
|
/// \param pixels Array of pixels of the image
|
||||||
|
/// \param width Width of the image
|
||||||
|
/// \param height Height of the image
|
||||||
|
/// \param hotspotX X location of the hotspot
|
||||||
|
/// \param hotspotY Y location of the hotspot
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void setMouseCursor(const Uint8* pixels, unsigned int width, unsigned int height, Uint16 hotspotX, Uint16 hotspotY);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Enable or disable automatic key-repeat
|
/// \brief Enable or disable automatic key-repeat
|
||||||
///
|
///
|
||||||
|
@ -190,6 +190,20 @@ void WindowImplUIKit::setMouseCursorGrabbed(bool grabbed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void WindowImplUIKit::setMouseCursor(Window::Cursor cursor)
|
||||||
|
{
|
||||||
|
// Not applicable
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void WindowImplUIKit::setMouseCursor(const Uint8* pixels, unsigned int width, unsigned int height, Uint16 hotspotX, Uint16 hotspotY)
|
||||||
|
{
|
||||||
|
// Not applicable
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowImplUIKit::setKeyRepeatEnabled(bool enabled)
|
void WindowImplUIKit::setKeyRepeatEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user