|
@ -0,0 +1,13 @@
|
||||||
|
Cursors
|
||||||
|
target:
|
||||||
|
image: targetcursor
|
||||||
|
hot-spot: 9 9
|
||||||
|
horizontal:
|
||||||
|
image: horizontalcursor
|
||||||
|
hot-spot: 9 4
|
||||||
|
vertical:
|
||||||
|
image: verticalcursor
|
||||||
|
hot-spot: 4 9
|
||||||
|
text:
|
||||||
|
image: textcursor
|
||||||
|
hot-spot: 4 9
|
Before Width: | Height: | Size: 230 B After Width: | Height: | Size: 230 B |
Before Width: | Height: | Size: 266 B After Width: | Height: | Size: 266 B |
Before Width: | Height: | Size: 198 B After Width: | Height: | Size: 198 B |
Before Width: | Height: | Size: 238 B After Width: | Height: | Size: 238 B |
|
@ -19,6 +19,8 @@ function init()
|
||||||
g_particles.importParticle('/particles/' .. particle)
|
g_particles.importParticle('/particles/' .. particle)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
g_mouse.loadCursors('/cursors/cursors')
|
||||||
end
|
end
|
||||||
|
|
||||||
function terminate()
|
function terminate()
|
||||||
|
|
|
@ -27,10 +27,10 @@ function UIResizeBorder:onHoverChange(hovered)
|
||||||
if hovered then
|
if hovered then
|
||||||
if g_mouse.isCursorChanged() or g_mouse.isPressed() then return end
|
if g_mouse.isCursorChanged() or g_mouse.isPressed() then return end
|
||||||
if self:getWidth() > self:getHeight() then
|
if self:getWidth() > self:getHeight() then
|
||||||
g_mouse.setVerticalCursor()
|
g_mouse.setCursor('vertical')
|
||||||
self.vertical = true
|
self.vertical = true
|
||||||
else
|
else
|
||||||
g_mouse.setHorizontalCursor()
|
g_mouse.setCursor('horizontal')
|
||||||
self.vertical = false
|
self.vertical = false
|
||||||
end
|
end
|
||||||
self.hovering = true
|
self.hovering = true
|
||||||
|
|
|
@ -14,10 +14,10 @@ function UISplitter:onHoverChange(hovered)
|
||||||
if hovered and (self:canUpdateMargin(margin + 1) ~= margin or self:canUpdateMargin(margin - 1) ~= margin) then
|
if hovered and (self:canUpdateMargin(margin + 1) ~= margin or self:canUpdateMargin(margin - 1) ~= margin) then
|
||||||
if g_mouse.isCursorChanged() or g_mouse.isPressed() then return end
|
if g_mouse.isCursorChanged() or g_mouse.isPressed() then return end
|
||||||
if self:getWidth() > self:getHeight() then
|
if self:getWidth() > self:getHeight() then
|
||||||
g_mouse.setVerticalCursor()
|
g_mouse.setCursor('vertical')
|
||||||
self.vertical = true
|
self.vertical = true
|
||||||
else
|
else
|
||||||
g_mouse.setHorizontalCursor()
|
g_mouse.setCursor('horizontal')
|
||||||
self.vertical = false
|
self.vertical = false
|
||||||
end
|
end
|
||||||
self.hovering = true
|
self.hovering = true
|
||||||
|
|
|
@ -235,7 +235,7 @@ function startChooseItem()
|
||||||
connect(mouseGrabberWidget, { onMouseRelease = onChooseItemMouseRelease })
|
connect(mouseGrabberWidget, { onMouseRelease = onChooseItemMouseRelease })
|
||||||
|
|
||||||
mouseGrabberWidget:grabMouse()
|
mouseGrabberWidget:grabMouse()
|
||||||
g_mouse.setTargetCursor()
|
g_mouse.setCursor('target-cursor')
|
||||||
|
|
||||||
hide()
|
hide()
|
||||||
end
|
end
|
||||||
|
|
|
@ -331,14 +331,14 @@ function startUseWith(thing)
|
||||||
selectedType = 'use'
|
selectedType = 'use'
|
||||||
selectedThing = thing
|
selectedThing = thing
|
||||||
mouseGrabberWidget:grabMouse()
|
mouseGrabberWidget:grabMouse()
|
||||||
g_mouse.setTargetCursor()
|
g_mouse.setCursor('target')
|
||||||
end
|
end
|
||||||
|
|
||||||
function startTradeWith(thing)
|
function startTradeWith(thing)
|
||||||
selectedType = 'trade'
|
selectedType = 'trade'
|
||||||
selectedThing = thing
|
selectedThing = thing
|
||||||
mouseGrabberWidget:grabMouse()
|
mouseGrabberWidget:grabMouse()
|
||||||
g_mouse.setTargetCursor()
|
g_mouse.setCursor('target')
|
||||||
end
|
end
|
||||||
|
|
||||||
function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
||||||
|
|
|
@ -16,7 +16,8 @@ function UIGameMap:onDragEnter(mousePos)
|
||||||
if not thing then return false end
|
if not thing then return false end
|
||||||
|
|
||||||
self.currentDragThing = thing
|
self.currentDragThing = thing
|
||||||
g_mouse.setTargetCursor()
|
|
||||||
|
g_mouse.setCursor('target')
|
||||||
self.allowNextRelease = false
|
self.allowNextRelease = false
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,7 +6,7 @@ function UIItem:onDragEnter(mousePos)
|
||||||
|
|
||||||
self:setBorderWidth(1)
|
self:setBorderWidth(1)
|
||||||
self.currentDragThing = item
|
self.currentDragThing = item
|
||||||
g_mouse.setTargetCursor()
|
g_mouse.setCursor('target')
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#ifdef FW_SOUND
|
#ifdef FW_SOUND
|
||||||
#include <framework/sound/soundmanager.h>
|
#include <framework/sound/soundmanager.h>
|
||||||
|
#include <framework/input/mouse.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GraphicalApplication g_app;
|
GraphicalApplication g_app;
|
||||||
|
@ -48,6 +49,8 @@ void GraphicalApplication::init(std::vector<std::string>& args)
|
||||||
g_window.setOnInputEvent(std::bind(&GraphicalApplication::inputEvent, this, std::placeholders::_1));
|
g_window.setOnInputEvent(std::bind(&GraphicalApplication::inputEvent, this, std::placeholders::_1));
|
||||||
g_window.setOnClose(std::bind(&GraphicalApplication::close, this));
|
g_window.setOnClose(std::bind(&GraphicalApplication::close, this));
|
||||||
|
|
||||||
|
g_mouse.init();
|
||||||
|
|
||||||
// initialize ui
|
// initialize ui
|
||||||
g_ui.init();
|
g_ui.init();
|
||||||
|
|
||||||
|
@ -87,6 +90,8 @@ void GraphicalApplication::terminate()
|
||||||
g_sounds.terminate();
|
g_sounds.terminate();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
g_mouse.terminate();
|
||||||
|
|
||||||
// terminate graphics
|
// terminate graphics
|
||||||
m_foreground = nullptr;
|
m_foreground = nullptr;
|
||||||
g_graphics.terminate();
|
g_graphics.terminate();
|
||||||
|
|
|
@ -23,46 +23,82 @@
|
||||||
#include "mouse.h"
|
#include "mouse.h"
|
||||||
#include <framework/ui/uiwidget.h>
|
#include <framework/ui/uiwidget.h>
|
||||||
#include <framework/platform/platformwindow.h>
|
#include <framework/platform/platformwindow.h>
|
||||||
|
#include <framework/core/resourcemanager.h>
|
||||||
|
|
||||||
Mouse g_mouse;
|
Mouse g_mouse;
|
||||||
|
|
||||||
void Mouse::setTargetCursor()
|
void Mouse::init()
|
||||||
{
|
{
|
||||||
//TODO: configure this in lua
|
|
||||||
g_window.setMouseCursor("/images/cursors/targetcursor", Point(9, 9));
|
|
||||||
m_cursorChanged = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mouse::setHorizontalCursor()
|
void Mouse::terminate()
|
||||||
{
|
{
|
||||||
g_window.setMouseCursor("/images/cursors/horizontal", Point(9, 4));
|
m_cursors.clear();
|
||||||
m_cursorChanged = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mouse::setVerticalCursor()
|
void Mouse::loadCursors(std::string filename)
|
||||||
{
|
{
|
||||||
g_window.setMouseCursor("/images/cursors/vertical", Point(4, 9));
|
filename = g_resources.guessFileType(filename, "otml");
|
||||||
m_cursorChanged = true;
|
try {
|
||||||
|
OTMLDocumentPtr doc = OTMLDocument::parse(filename);
|
||||||
|
OTMLNodePtr cursorsNode = doc->at("Cursors");
|
||||||
|
|
||||||
|
for(const OTMLNodePtr& cursorNode : cursorsNode->children())
|
||||||
|
addCursor(cursorNode->tag(),
|
||||||
|
stdext::resolve_path(cursorNode->valueAt("image"), cursorNode->source()),
|
||||||
|
cursorNode->valueAt<Point>("hot-spot"));
|
||||||
|
} catch(stdext::exception& e) {
|
||||||
|
g_logger.error(stdext::format("unable to load cursors file: %s", e.what()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mouse::setTextCursor()
|
void Mouse::addCursor(const std::string& name, const std::string& file, const Point& hotSpot)
|
||||||
{
|
{
|
||||||
g_window.setMouseCursor("/images/cursors/text", Point(4, 9));
|
int cursorId = g_window.loadMouseCursor(file, hotSpot);
|
||||||
m_cursorChanged = true;
|
if(cursorId >= 0) {
|
||||||
|
m_cursors[name] = cursorId;
|
||||||
|
} else
|
||||||
|
g_logger.error(stdext::format("unable to load cursor %s", name));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mouse::setCursor(const std::string& name)
|
||||||
|
{
|
||||||
|
auto it = m_cursors.find(name);
|
||||||
|
if(it == m_cursors.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int cursorId = it->second;
|
||||||
|
g_window.setMouseCursor(cursorId);
|
||||||
|
m_cursorStack.push_back(cursorId);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mouse::restoreCursor()
|
void Mouse::restoreCursor()
|
||||||
{
|
{
|
||||||
|
if(m_cursorStack.size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_cursorStack.pop_back();
|
||||||
|
if(m_cursorStack.size() > 0)
|
||||||
|
g_window.setMouseCursor(m_cursorStack.back());
|
||||||
|
else
|
||||||
g_window.restoreMouseCursor();
|
g_window.restoreMouseCursor();
|
||||||
m_cursorChanged = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mouse::isCursorChanged()
|
bool Mouse::isCursorChanged()
|
||||||
{
|
{
|
||||||
return m_cursorChanged;
|
return m_cursorStack.size() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mouse::isPressed(Fw::MouseButton mouseButton)
|
bool Mouse::isPressed(Fw::MouseButton mouseButton)
|
||||||
{
|
{
|
||||||
return g_window.isMouseButtonPressed(mouseButton);
|
return g_window.isMouseButtonPressed(mouseButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Mouse::checkStackSize()
|
||||||
|
{
|
||||||
|
if(m_cursorStack.size() > 5) {
|
||||||
|
g_logger.error("mouse cursor stack is too long");
|
||||||
|
m_cursorStack.resize(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,16 +25,21 @@
|
||||||
class Mouse
|
class Mouse
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setTargetCursor();
|
void init();
|
||||||
void setHorizontalCursor();
|
void terminate();
|
||||||
void setVerticalCursor();
|
|
||||||
void setTextCursor();
|
void loadCursors(std::string filename);
|
||||||
|
void addCursor(const std::string& name, const std::string& file, const Point& hotSpot);
|
||||||
|
bool setCursor(const std::string& name);
|
||||||
void restoreCursor();
|
void restoreCursor();
|
||||||
bool isCursorChanged();
|
bool isCursorChanged();
|
||||||
bool isPressed(Fw::MouseButton mouseButton);
|
bool isPressed(Fw::MouseButton mouseButton);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_cursorChanged;
|
void checkStackSize();
|
||||||
|
|
||||||
|
std::map<std::string, int> m_cursors;
|
||||||
|
std::vector<int> m_cursorStack;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Mouse g_mouse;
|
extern Mouse g_mouse;
|
||||||
|
|
|
@ -270,10 +270,9 @@ void Application::registerLuaFunctions()
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
g_lua.registerSingletonClass("g_mouse");
|
g_lua.registerSingletonClass("g_mouse");
|
||||||
g_lua.bindSingletonFunction("g_mouse", "setTargetCursor", &Mouse::setTargetCursor, &g_mouse);
|
g_lua.bindSingletonFunction("g_mouse", "loadCursors", &Mouse::loadCursors, &g_mouse);
|
||||||
g_lua.bindSingletonFunction("g_mouse", "setHorizontalCursor", &Mouse::setHorizontalCursor, &g_mouse);
|
g_lua.bindSingletonFunction("g_mouse", "addCursor", &Mouse::addCursor, &g_mouse);
|
||||||
g_lua.bindSingletonFunction("g_mouse", "setVerticalCursor", &Mouse::setVerticalCursor, &g_mouse);
|
g_lua.bindSingletonFunction("g_mouse", "setCursor", &Mouse::setCursor, &g_mouse);
|
||||||
g_lua.bindSingletonFunction("g_mouse", "setTextCursor", &Mouse::setTextCursor, &g_mouse);
|
|
||||||
g_lua.bindSingletonFunction("g_mouse", "restoreCursor", &Mouse::restoreCursor, &g_mouse);
|
g_lua.bindSingletonFunction("g_mouse", "restoreCursor", &Mouse::restoreCursor, &g_mouse);
|
||||||
g_lua.bindSingletonFunction("g_mouse", "isCursorChanged", &Mouse::isCursorChanged, &g_mouse);
|
g_lua.bindSingletonFunction("g_mouse", "isCursorChanged", &Mouse::isCursorChanged, &g_mouse);
|
||||||
g_lua.bindSingletonFunction("g_mouse", "isPressed", &Mouse::isPressed, &g_mouse);
|
g_lua.bindSingletonFunction("g_mouse", "isPressed", &Mouse::isPressed, &g_mouse);
|
||||||
|
|
|
@ -32,9 +32,32 @@ X11Window window;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <framework/core/clock.h>
|
#include <framework/core/clock.h>
|
||||||
|
#include <framework/graphics/image.h>
|
||||||
|
|
||||||
PlatformWindow& g_window = window;
|
PlatformWindow& g_window = window;
|
||||||
|
|
||||||
|
int PlatformWindow::loadMouseCursor(const std::string& file, const Point& hotSpot)
|
||||||
|
{
|
||||||
|
ImagePtr image = Image::load(file);
|
||||||
|
|
||||||
|
if(!image) {
|
||||||
|
g_logger.traceError(stdext::format("unable to load cursor image file %s", file));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(image->getBpp() != 4) {
|
||||||
|
g_logger.error("the cursor image must have 4 channels");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(image->getWidth() != 32 || image->getHeight() != 32) {
|
||||||
|
g_logger.error("the cursor image must have 32x32 dimension");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return internalLoadMouseCursor(image, hotSpot);
|
||||||
|
}
|
||||||
|
|
||||||
void PlatformWindow::updateUnmaximizedCoords()
|
void PlatformWindow::updateUnmaximizedCoords()
|
||||||
{
|
{
|
||||||
if(!isMaximized() && !isFullscreen()) {
|
if(!isMaximized() && !isFullscreen()) {
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <framework/global.h>
|
#include <framework/global.h>
|
||||||
#include <framework/core/inputevent.h>
|
#include <framework/core/inputevent.h>
|
||||||
#include <framework/core/timer.h>
|
#include <framework/core/timer.h>
|
||||||
|
#include <framework/graphics/declarations.h>
|
||||||
|
|
||||||
//@bindsingleton g_window
|
//@bindsingleton g_window
|
||||||
class PlatformWindow
|
class PlatformWindow
|
||||||
|
@ -48,12 +49,14 @@ public:
|
||||||
virtual void maximize() = 0;
|
virtual void maximize() = 0;
|
||||||
virtual void poll() = 0;
|
virtual void poll() = 0;
|
||||||
virtual void swapBuffers() = 0;
|
virtual void swapBuffers() = 0;
|
||||||
virtual void restoreMouseCursor() = 0;
|
|
||||||
virtual void showMouse() = 0;
|
virtual void showMouse() = 0;
|
||||||
virtual void hideMouse() = 0;
|
virtual void hideMouse() = 0;
|
||||||
virtual void displayFatalError(const std::string& message) { }
|
virtual void displayFatalError(const std::string& message) { }
|
||||||
|
|
||||||
virtual void setMouseCursor(const std::string& file, const Point& hotSpot) = 0;
|
int loadMouseCursor(const std::string& file, const Point& hotSpot);
|
||||||
|
virtual void setMouseCursor(int cursorId) = 0;
|
||||||
|
virtual void restoreMouseCursor() = 0;
|
||||||
|
|
||||||
virtual void setTitle(const std::string& title) = 0;
|
virtual void setTitle(const std::string& title) = 0;
|
||||||
virtual void setMinimumSize(const Size& minimumSize) = 0;
|
virtual void setMinimumSize(const Size& minimumSize) = 0;
|
||||||
virtual void setFullscreen(bool fullscreen) = 0;
|
virtual void setFullscreen(bool fullscreen) = 0;
|
||||||
|
@ -92,6 +95,8 @@ public:
|
||||||
void setOnInputEvent(const OnInputEventCallback& onInputEvent) { m_onInputEvent = onInputEvent; }
|
void setOnInputEvent(const OnInputEventCallback& onInputEvent) { m_onInputEvent = onInputEvent; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual int internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot) = 0;
|
||||||
|
|
||||||
void updateUnmaximizedCoords();
|
void updateUnmaximizedCoords();
|
||||||
|
|
||||||
void processKeyDown(Fw::Key keyCode);
|
void processKeyDown(Fw::Key keyCode);
|
||||||
|
|
|
@ -211,6 +211,16 @@ void WIN32Window::init()
|
||||||
|
|
||||||
void WIN32Window::terminate()
|
void WIN32Window::terminate()
|
||||||
{
|
{
|
||||||
|
SetCursor(NULL);
|
||||||
|
if(m_defaultCursor) {
|
||||||
|
DestroyCursor(m_defaultCursor);
|
||||||
|
m_defaultCursor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(HCURSOR& cursor : m_cursors)
|
||||||
|
DestroyCursor(cursor);
|
||||||
|
m_cursors.clear();
|
||||||
|
|
||||||
internalDestroyGLContext();
|
internalDestroyGLContext();
|
||||||
|
|
||||||
if(m_deviceContext) {
|
if(m_deviceContext) {
|
||||||
|
@ -219,11 +229,6 @@ void WIN32Window::terminate()
|
||||||
m_deviceContext = NULL;
|
m_deviceContext = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_cursor) {
|
|
||||||
DestroyCursor(m_cursor);
|
|
||||||
m_cursor = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_window) {
|
if(m_window) {
|
||||||
if(!DestroyWindow(m_window))
|
if(!DestroyWindow(m_window))
|
||||||
g_logger.error("ERROR: Destroy window failed.");
|
g_logger.error("ERROR: Destroy window failed.");
|
||||||
|
@ -744,16 +749,6 @@ void WIN32Window::swapBuffers()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void WIN32Window::restoreMouseCursor()
|
|
||||||
{
|
|
||||||
if(m_cursor) {
|
|
||||||
DestroyCursor(m_cursor);
|
|
||||||
m_cursor = NULL;
|
|
||||||
SetCursor(m_defaultCursor);
|
|
||||||
ShowCursor(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WIN32Window::showMouse()
|
void WIN32Window::showMouse()
|
||||||
{
|
{
|
||||||
ShowCursor(true);
|
ShowCursor(true);
|
||||||
|
@ -769,28 +764,8 @@ void WIN32Window::displayFatalError(const std::string& message)
|
||||||
MessageBoxW(m_window, stdext::latin1_to_utf16(message).c_str(), L"FATAL ERROR", MB_OK | MB_ICONERROR);
|
MessageBoxW(m_window, stdext::latin1_to_utf16(message).c_str(), L"FATAL ERROR", MB_OK | MB_ICONERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WIN32Window::setMouseCursor(const std::string& file, const Point& hotSpot)
|
int WIN32Window::internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot)
|
||||||
{
|
{
|
||||||
ImagePtr image = Image::load(file);
|
|
||||||
|
|
||||||
if(!image) {
|
|
||||||
g_logger.traceError(stdext::format("unable to load cursor image file %s", file));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(image->getBpp() != 4) {
|
|
||||||
g_logger.error("the cursor image must have 4 channels");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(image->getWidth() != 32 || image->getHeight() != 32) {
|
|
||||||
g_logger.error("the cursor image must have 32x32 dimension");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_cursor != NULL)
|
|
||||||
DestroyCursor(m_cursor);
|
|
||||||
|
|
||||||
int width = image->getWidth();
|
int width = image->getWidth();
|
||||||
int height = image->getHeight();
|
int height = image->getHeight();
|
||||||
int numbits = width * height;
|
int numbits = width * height;
|
||||||
|
@ -808,8 +783,28 @@ void WIN32Window::setMouseCursor(const std::string& file, const Point& hotSpot)
|
||||||
} // otherwise 0xff000000 => black
|
} // otherwise 0xff000000 => black
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cursor = CreateCursor(m_instance, hotSpot.x, hotSpot.y, width, height, &andMask[0], &xorMask[0]);
|
HCURSOR cursor = CreateCursor(m_instance, hotSpot.x, hotSpot.y, width, height, &andMask[0], &xorMask[0]);
|
||||||
|
m_cursors.push_back(cursor);
|
||||||
|
return m_cursors.size()-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WIN32Window::setMouseCursor(int cursorId)
|
||||||
|
{
|
||||||
|
if(cursorId >= (int)m_cursors.size() || cursorId < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_cursor = m_cursors[cursorId];
|
||||||
SetCursor(m_cursor);
|
SetCursor(m_cursor);
|
||||||
|
ShowCursor(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WIN32Window::restoreMouseCursor()
|
||||||
|
{
|
||||||
|
if(m_cursor) {
|
||||||
|
m_cursor = NULL;
|
||||||
|
SetCursor(m_defaultCursor);
|
||||||
|
ShowCursor(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WIN32Window::setTitle(const std::string& title)
|
void WIN32Window::setTitle(const std::string& title)
|
||||||
|
|
|
@ -61,12 +61,13 @@ public:
|
||||||
void maximize();
|
void maximize();
|
||||||
void poll();
|
void poll();
|
||||||
void swapBuffers();
|
void swapBuffers();
|
||||||
void restoreMouseCursor();
|
|
||||||
void showMouse();
|
void showMouse();
|
||||||
void hideMouse();
|
void hideMouse();
|
||||||
void displayFatalError(const std::string& message);
|
void displayFatalError(const std::string& message);
|
||||||
|
|
||||||
void setMouseCursor(const std::string& file, const Point& hotSpot);
|
void setMouseCursor(int cursorId);
|
||||||
|
void restoreMouseCursor();
|
||||||
|
|
||||||
void setTitle(const std::string& title);
|
void setTitle(const std::string& title);
|
||||||
void setMinimumSize(const Size& minimumSize);
|
void setMinimumSize(const Size& minimumSize);
|
||||||
void setFullscreen(bool fullscreen);
|
void setFullscreen(bool fullscreen);
|
||||||
|
@ -78,11 +79,15 @@ public:
|
||||||
std::string getClipboardText();
|
std::string getClipboardText();
|
||||||
std::string getPlatformType();
|
std::string getPlatformType();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Rect getClientRect();
|
Rect getClientRect();
|
||||||
Rect getWindowRect();
|
Rect getWindowRect();
|
||||||
Rect adjustWindowRect(const Rect& rect);
|
Rect adjustWindowRect(const Rect& rect);
|
||||||
|
|
||||||
|
std::vector<HCURSOR> m_cursors;
|
||||||
HWND m_window;
|
HWND m_window;
|
||||||
HINSTANCE m_instance;
|
HINSTANCE m_instance;
|
||||||
HDC m_deviceContext;
|
HDC m_deviceContext;
|
||||||
|
|
|
@ -37,6 +37,7 @@ X11Window::X11Window()
|
||||||
m_rootWindow = 0;
|
m_rootWindow = 0;
|
||||||
m_colormap = 0;
|
m_colormap = 0;
|
||||||
m_cursor = 0;
|
m_cursor = 0;
|
||||||
|
m_hiddenCursor = 0;
|
||||||
m_xim = 0;
|
m_xim = 0;
|
||||||
m_xic = 0;
|
m_xic = 0;
|
||||||
m_screen = 0;
|
m_screen = 0;
|
||||||
|
@ -218,6 +219,20 @@ void X11Window::init()
|
||||||
|
|
||||||
void X11Window::terminate()
|
void X11Window::terminate()
|
||||||
{
|
{
|
||||||
|
if(m_cursor != None) {
|
||||||
|
XUndefineCursor(m_display, m_window);
|
||||||
|
m_cursor = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_hiddenCursor) {
|
||||||
|
XFreeCursor(m_display, m_hiddenCursor);
|
||||||
|
m_hiddenCursor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Cursor cursor : m_cursors)
|
||||||
|
XFreeCursor(m_display, cursor);
|
||||||
|
m_cursors.clear();
|
||||||
|
|
||||||
if(m_window) {
|
if(m_window) {
|
||||||
XDestroyWindow(m_display, m_window);
|
XDestroyWindow(m_display, m_window);
|
||||||
m_window = 0;
|
m_window = 0;
|
||||||
|
@ -842,47 +857,40 @@ void X11Window::hideMouse()
|
||||||
if(m_cursor != None)
|
if(m_cursor != None)
|
||||||
restoreMouseCursor();
|
restoreMouseCursor();
|
||||||
|
|
||||||
|
if(m_hiddenCursor == None) {
|
||||||
char bm[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
char bm[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
Pixmap pix = XCreateBitmapFromData(m_display, m_window, bm, 8, 8);
|
Pixmap pix = XCreateBitmapFromData(m_display, m_window, bm, 8, 8);
|
||||||
XColor black;
|
XColor black;
|
||||||
memset(&black, 0, sizeof(black));
|
memset(&black, 0, sizeof(black));
|
||||||
black.flags = DoRed | DoGreen | DoBlue;
|
black.flags = DoRed | DoGreen | DoBlue;
|
||||||
m_cursor = XCreatePixmapCursor(m_display, pix, pix, &black, &black, 0, 0);
|
m_hiddenCursor = XCreatePixmapCursor(m_display, pix, pix, &black, &black, 0, 0);
|
||||||
XFreePixmap(m_display, pix);
|
XFreePixmap(m_display, pix);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cursor = m_hiddenCursor;
|
||||||
|
XDefineCursor(m_display, m_window, m_cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void X11Window::setMouseCursor(int cursorId)
|
||||||
|
{
|
||||||
|
if(cursorId >= (int)m_cursors.size() || cursorId < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(m_cursor != None)
|
||||||
|
restoreMouseCursor();
|
||||||
|
|
||||||
|
m_cursor = m_cursors[cursorId];
|
||||||
XDefineCursor(m_display, m_window, m_cursor);
|
XDefineCursor(m_display, m_window, m_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void X11Window::restoreMouseCursor()
|
void X11Window::restoreMouseCursor()
|
||||||
{
|
{
|
||||||
XUndefineCursor(m_display, m_window);
|
XUndefineCursor(m_display, m_window);
|
||||||
if(m_cursor != None) {
|
|
||||||
XFreeCursor(m_display, m_cursor);
|
|
||||||
m_cursor = None;
|
m_cursor = None;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void X11Window::setMouseCursor(const std::string& file, const Point& hotSpot)
|
int X11Window::internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot)
|
||||||
{
|
{
|
||||||
ImagePtr image = Image::load(file);
|
|
||||||
|
|
||||||
if(!image) {
|
|
||||||
g_logger.traceError(stdext::format("unable to load image file %s", file));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(image->getBpp() != 4) {
|
|
||||||
g_logger.error("the cursor image must have 4 channels");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(image->getWidth() != 32 || image->getHeight() != 32) {
|
|
||||||
g_logger.error("the cursor image must have 32x32 dimension");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_cursor != None)
|
|
||||||
restoreMouseCursor();
|
|
||||||
|
|
||||||
int width = image->getWidth();
|
int width = image->getWidth();
|
||||||
int height = image->getHeight();
|
int height = image->getHeight();
|
||||||
int numbits = width * height;
|
int numbits = width * height;
|
||||||
|
@ -911,10 +919,12 @@ void X11Window::setMouseCursor(const std::string& file, const Point& hotSpot)
|
||||||
|
|
||||||
Pixmap cp = XCreateBitmapFromData(m_display, m_window, (char*)&mapBits[0], width, height);
|
Pixmap cp = XCreateBitmapFromData(m_display, m_window, (char*)&mapBits[0], width, height);
|
||||||
Pixmap mp = XCreateBitmapFromData(m_display, m_window, (char*)&maskBits[0], width, height);
|
Pixmap mp = XCreateBitmapFromData(m_display, m_window, (char*)&maskBits[0], width, height);
|
||||||
m_cursor = XCreatePixmapCursor(m_display, cp, mp, &fg, &bg, hotSpot.x, hotSpot.y);
|
Cursor cursor = XCreatePixmapCursor(m_display, cp, mp, &fg, &bg, hotSpot.x, hotSpot.y);
|
||||||
XDefineCursor(m_display, m_window, m_cursor);
|
|
||||||
XFreePixmap(m_display, cp);
|
XFreePixmap(m_display, cp);
|
||||||
XFreePixmap(m_display, mp);
|
XFreePixmap(m_display, mp);
|
||||||
|
|
||||||
|
m_cursors.push_back(cursor);
|
||||||
|
return m_cursors.size()-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void X11Window::setTitle(const std::string& title)
|
void X11Window::setTitle(const std::string& title)
|
||||||
|
|
|
@ -63,11 +63,12 @@ public:
|
||||||
void maximize();
|
void maximize();
|
||||||
void poll();
|
void poll();
|
||||||
void swapBuffers();
|
void swapBuffers();
|
||||||
void restoreMouseCursor();
|
|
||||||
void showMouse();
|
void showMouse();
|
||||||
void hideMouse();
|
void hideMouse();
|
||||||
|
|
||||||
void setMouseCursor(const std::string& file, const Point& hotSpot);
|
void setMouseCursor(int cursorId);
|
||||||
|
void restoreMouseCursor();
|
||||||
|
|
||||||
void setTitle(const std::string& title);
|
void setTitle(const std::string& title);
|
||||||
void setMinimumSize(const Size& minimumSize);
|
void setMinimumSize(const Size& minimumSize);
|
||||||
void setFullscreen(bool fullscreen);
|
void setFullscreen(bool fullscreen);
|
||||||
|
@ -79,13 +80,18 @@ public:
|
||||||
std::string getClipboardText();
|
std::string getClipboardText();
|
||||||
std::string getPlatformType();
|
std::string getPlatformType();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int internalLoadMouseCursor(const ImagePtr& image, const Point& hotSpot);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Display *m_display;
|
Display *m_display;
|
||||||
XVisualInfo *m_visual;
|
XVisualInfo *m_visual;
|
||||||
Window m_window;
|
Window m_window;
|
||||||
Window m_rootWindow;
|
Window m_rootWindow;
|
||||||
Colormap m_colormap;
|
Colormap m_colormap;
|
||||||
|
std::vector<Cursor> m_cursors;
|
||||||
Cursor m_cursor;
|
Cursor m_cursor;
|
||||||
|
Cursor m_hiddenCursor;
|
||||||
XIM m_xim;
|
XIM m_xim;
|
||||||
XIC m_xic;
|
XIC m_xic;
|
||||||
int m_screen;
|
int m_screen;
|
||||||
|
|
|
@ -590,7 +590,7 @@ void UITextEdit::onHoverChange(bool hovered)
|
||||||
{
|
{
|
||||||
if(m_changeCursorImage) {
|
if(m_changeCursorImage) {
|
||||||
if(hovered)
|
if(hovered)
|
||||||
g_mouse.setTextCursor();
|
g_mouse.setCursor("text");
|
||||||
else
|
else
|
||||||
g_mouse.restoreCursor();
|
g_mouse.restoreCursor();
|
||||||
}
|
}
|
||||||
|
|