mirror of https://github.com/aseprite/aseprite.git
Win32: Add support to convert mouse messages (WM_) to ui::Messages (using she::Events)
On Windows, instead of polling Allegro mouse position/buttons we can use the mouse messages (WM_*) directly to generate she::Events. Those events are received by the ui::Manager and converted to ui::Messages. Maybe this is a possible fix for issue #133 (Wacom tablets don't work properly). Changes: - Don't use jmouse_z() directly (new ui::MouseMessage::wheelDelta() member) - Add ui::_internal_set_mouse_position() to change the jmouse_x/y(0) from the new mouse position received in she::Events. The same for ui::_internal_set_mouse_buttons(). - Modify the ui::Manager to generate mouse events in any case: using old Allegro 4 polling method, or from she::Events.
This commit is contained in:
parent
2e9751fef1
commit
dd2ce20e25
|
@ -215,6 +215,7 @@ if(WIN32)
|
||||||
shlwapi
|
shlwapi
|
||||||
psapi
|
psapi
|
||||||
wininet
|
wininet
|
||||||
|
comctl32
|
||||||
dbghelp
|
dbghelp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -262,7 +262,7 @@ bool StandbyState::onMouseMove(Editor* editor, MouseMessage* msg)
|
||||||
|
|
||||||
bool StandbyState::onMouseWheel(Editor* editor, MouseMessage* msg)
|
bool StandbyState::onMouseWheel(Editor* editor, MouseMessage* msg)
|
||||||
{
|
{
|
||||||
int dz = jmouse_z(1) - jmouse_z(0);
|
int dz = -msg->wheelDelta();
|
||||||
WHEEL_ACTION wheelAction = WHEEL_NONE;
|
WHEEL_ACTION wheelAction = WHEEL_NONE;
|
||||||
bool scrollBigSteps = false;
|
bool scrollBigSteps = false;
|
||||||
|
|
||||||
|
|
|
@ -273,7 +273,7 @@ bool FileList::onProcessMessage(Message* msg)
|
||||||
View* view = View::getView(this);
|
View* view = View::getView(this);
|
||||||
if (view) {
|
if (view) {
|
||||||
gfx::Point scroll = view->getViewScroll();
|
gfx::Point scroll = view->getViewScroll();
|
||||||
scroll.y += (jmouse_z(1)-jmouse_z(0)) * 3*(2+getTextHeight()+2);
|
scroll.y += -static_cast<MouseMessage*>(msg)->wheelDelta() * 3*(2+getTextHeight()+2);
|
||||||
view->setViewScroll(scroll);
|
view->setViewScroll(scroll);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -255,7 +255,7 @@ bool PaletteView::onProcessMessage(Message* msg)
|
||||||
View* view = View::getView(this);
|
View* view = View::getView(this);
|
||||||
if (view) {
|
if (view) {
|
||||||
gfx::Point scroll = view->getViewScroll();
|
gfx::Point scroll = view->getViewScroll();
|
||||||
scroll.y += (jmouse_z(1)-jmouse_z(0)) * 3 * m_boxsize;
|
scroll.y += -static_cast<MouseMessage*>(msg)->wheelDelta() * 3 * m_boxsize;
|
||||||
view->setViewScroll(scroll);
|
view->setViewScroll(scroll);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -286,7 +286,7 @@ bool Tabs::onProcessMessage(Message* msg)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case kMouseWheelMessage: {
|
case kMouseWheelMessage: {
|
||||||
int dx = (jmouse_z(1) - jmouse_z(0)) * getBounds().w/6;
|
int dx = -static_cast<MouseMessage*>(msg)->wheelDelta() * getBounds().w/6;
|
||||||
// setScrollX(m_scrollX+dx);
|
// setScrollX(m_scrollX+dx);
|
||||||
|
|
||||||
m_begScrollX = m_scrollX;
|
m_begScrollX = m_scrollX;
|
||||||
|
|
|
@ -739,7 +739,7 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||||
|
|
||||||
case kMouseWheelMessage:
|
case kMouseWheelMessage:
|
||||||
if (m_document) {
|
if (m_document) {
|
||||||
int dz = jmouse_z(1) - jmouse_z(0);
|
int dz = -static_cast<MouseMessage*>(msg)->wheelDelta();
|
||||||
int dx = 0;
|
int dx = 0;
|
||||||
int dy = 0;
|
int dy = 0;
|
||||||
|
|
||||||
|
|
|
@ -254,7 +254,7 @@ bool ToolBar::onProcessMessage(Message* msg)
|
||||||
MouseMessage* mouseMsg2 = new MouseMessage(
|
MouseMessage* mouseMsg2 = new MouseMessage(
|
||||||
kMouseDownMessage,
|
kMouseDownMessage,
|
||||||
mouseMsg->buttons(),
|
mouseMsg->buttons(),
|
||||||
mouseMsg->position());
|
mouseMsg->position(), 0);
|
||||||
mouseMsg2->addRecipient(strip);
|
mouseMsg2->addRecipient(strip);
|
||||||
getManager()->enqueueMessage(mouseMsg2);
|
getManager()->enqueueMessage(mouseMsg2);
|
||||||
}
|
}
|
||||||
|
@ -712,7 +712,7 @@ bool ToolBar::ToolStrip::onProcessMessage(Message* msg)
|
||||||
MouseMessage* mouseMsg2 = new MouseMessage(
|
MouseMessage* mouseMsg2 = new MouseMessage(
|
||||||
kMouseDownMessage,
|
kMouseDownMessage,
|
||||||
mouseMsg->buttons(),
|
mouseMsg->buttons(),
|
||||||
mouseMsg->position());
|
mouseMsg->position(), 0);
|
||||||
mouseMsg2->addRecipient(bar);
|
mouseMsg2->addRecipient(bar);
|
||||||
getManager()->enqueueMessage(mouseMsg2);
|
getManager()->enqueueMessage(mouseMsg2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,8 @@ namespace she {
|
||||||
enum Capabilities {
|
enum Capabilities {
|
||||||
kMultipleDisplaysCapability = 1,
|
kMultipleDisplaysCapability = 1,
|
||||||
kCanResizeDisplayCapability = 2,
|
kCanResizeDisplayCapability = 2,
|
||||||
kDisplayScaleCapability = 4
|
kDisplayScaleCapability = 4,
|
||||||
|
kMouseEventsCapability = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace she
|
} // namespace she
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#define SHE_EVENT_H_INCLUDED
|
#define SHE_EVENT_H_INCLUDED
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "gfx/point.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -18,6 +20,20 @@ namespace she {
|
||||||
enum Type {
|
enum Type {
|
||||||
None,
|
None,
|
||||||
DropFiles,
|
DropFiles,
|
||||||
|
MouseEnter,
|
||||||
|
MouseLeave,
|
||||||
|
MouseMove,
|
||||||
|
MouseDown,
|
||||||
|
MouseUp,
|
||||||
|
MouseWheel,
|
||||||
|
MouseDoubleClick,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MouseButton {
|
||||||
|
NoneButton,
|
||||||
|
LeftButton,
|
||||||
|
RightButton,
|
||||||
|
MiddleButton
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<std::string> Files;
|
typedef std::vector<std::string> Files;
|
||||||
|
@ -25,14 +41,23 @@ namespace she {
|
||||||
Event() : m_type(None) { }
|
Event() : m_type(None) { }
|
||||||
|
|
||||||
int type() const { return m_type; }
|
int type() const { return m_type; }
|
||||||
void setType(Type type) { m_type = type; }
|
|
||||||
|
|
||||||
const Files& files() const { return m_files; }
|
const Files& files() const { return m_files; }
|
||||||
|
gfx::Point position() const { return m_position; }
|
||||||
|
MouseButton button() const { return m_button; }
|
||||||
|
int delta() const { return m_delta; }
|
||||||
|
|
||||||
|
void setType(Type type) { m_type = type; }
|
||||||
void setFiles(const Files& files) { m_files = files; }
|
void setFiles(const Files& files) { m_files = files; }
|
||||||
|
void setPosition(const gfx::Point& pos) { m_position = pos; }
|
||||||
|
void setButton(MouseButton button) { m_button = button; }
|
||||||
|
void setDelta(int delta) { m_delta = delta; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type m_type;
|
Type m_type;
|
||||||
Files m_files;
|
Files m_files;
|
||||||
|
gfx::Point m_position;
|
||||||
|
MouseButton m_button;
|
||||||
|
int m_delta;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace she
|
} // namespace she
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "she.h"
|
#include "she.h"
|
||||||
|
|
||||||
#include "base/compiler_specific.h"
|
#include "base/compiler_specific.h"
|
||||||
|
#include "base/concurrent_queue.h"
|
||||||
#include "base/string.h"
|
#include "base/string.h"
|
||||||
|
|
||||||
#include <allegro.h>
|
#include <allegro.h>
|
||||||
|
@ -19,6 +20,9 @@
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <winalleg.h>
|
#include <winalleg.h>
|
||||||
|
|
||||||
|
#include <windowsx.h>
|
||||||
|
#include <commctrl.h>
|
||||||
|
|
||||||
#if defined STRICT || defined __GNUC__
|
#if defined STRICT || defined __GNUC__
|
||||||
typedef WNDPROC wndproc_t;
|
typedef WNDPROC wndproc_t;
|
||||||
#else
|
#else
|
||||||
|
@ -36,6 +40,7 @@
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#define DISPLAY_FLAG_FULL_REFRESH 1
|
#define DISPLAY_FLAG_FULL_REFRESH 1
|
||||||
#define DISPLAY_FLAG_WINDOW_RESIZE 2
|
#define DISPLAY_FLAG_WINDOW_RESIZE 2
|
||||||
|
@ -153,20 +158,19 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void getEvent(Event& event) {
|
void getEvent(Event& event) {
|
||||||
if (m_events.size() > 0) {
|
if (!m_events.try_pop(event))
|
||||||
event = m_events[0];
|
|
||||||
m_events.erase(m_events.begin());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
event.setType(Event::None);
|
event.setType(Event::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
void queueEvent(const Event& event) {
|
void queueEvent(const Event& event) {
|
||||||
m_events.push_back(event);
|
m_events.push(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Event> m_events;
|
// We need a concurrent queue because events are generated in one
|
||||||
|
// thread (the thread created by Allegro 4 for the HWND), and
|
||||||
|
// consumed in the other thread (the main/program logic thread).
|
||||||
|
base::concurrent_queue<Event> m_events;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if WIN32
|
#if WIN32
|
||||||
|
@ -174,35 +178,137 @@ namespace {
|
||||||
|
|
||||||
Display* unique_display = NULL;
|
Display* unique_display = NULL;
|
||||||
wndproc_t base_wndproc = NULL;
|
wndproc_t base_wndproc = NULL;
|
||||||
|
bool display_has_mouse = false;
|
||||||
|
int display_scale;
|
||||||
|
|
||||||
|
static void queue_event(Event& ev)
|
||||||
|
{
|
||||||
|
static_cast<Alleg4EventQueue*>(unique_display->getEventQueue())->queueEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
static LRESULT CALLBACK wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
static LRESULT CALLBACK wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||||
{
|
{
|
||||||
switch (msg) {
|
switch (msg) {
|
||||||
|
|
||||||
case WM_DROPFILES:
|
case WM_DROPFILES: {
|
||||||
{
|
HDROP hdrop = (HDROP)(wparam);
|
||||||
HDROP hdrop = (HDROP)(wparam);
|
Event::Files files;
|
||||||
Event::Files files;
|
|
||||||
|
|
||||||
int count = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0);
|
int count = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0);
|
||||||
for (int index=0; index<count; ++index) {
|
for (int index=0; index<count; ++index) {
|
||||||
int length = DragQueryFile(hdrop, index, NULL, 0);
|
int length = DragQueryFile(hdrop, index, NULL, 0);
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
std::vector<TCHAR> str(length+1);
|
std::vector<TCHAR> str(length+1);
|
||||||
DragQueryFile(hdrop, index, &str[0], str.size());
|
DragQueryFile(hdrop, index, &str[0], str.size());
|
||||||
files.push_back(base::to_utf8(&str[0]));
|
files.push_back(base::to_utf8(&str[0]));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DragFinish(hdrop);
|
|
||||||
|
|
||||||
Event ev;
|
|
||||||
ev.setType(Event::DropFiles);
|
|
||||||
ev.setFiles(files);
|
|
||||||
static_cast<Alleg4EventQueue*>(unique_display->getEventQueue())
|
|
||||||
->queueEvent(ev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DragFinish(hdrop);
|
||||||
|
|
||||||
|
Event ev;
|
||||||
|
ev.setType(Event::DropFiles);
|
||||||
|
ev.setFiles(files);
|
||||||
|
queue_event(ev);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_MOUSEMOVE: {
|
||||||
|
Event ev;
|
||||||
|
ev.setPosition(gfx::Point(
|
||||||
|
GET_X_LPARAM(lparam) / display_scale,
|
||||||
|
GET_Y_LPARAM(lparam) / display_scale));
|
||||||
|
|
||||||
|
if (!display_has_mouse) {
|
||||||
|
display_has_mouse = true;
|
||||||
|
|
||||||
|
ev.setType(Event::MouseEnter);
|
||||||
|
queue_event(ev);
|
||||||
|
|
||||||
|
// Track mouse to receive WM_MOUSELEAVE message.
|
||||||
|
TRACKMOUSEEVENT tme;
|
||||||
|
tme.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||||
|
tme.dwFlags = TME_LEAVE;
|
||||||
|
tme.hwndTrack = hwnd;
|
||||||
|
_TrackMouseEvent(&tme);
|
||||||
|
}
|
||||||
|
|
||||||
|
ev.setType(Event::MouseMove);
|
||||||
|
queue_event(ev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_MOUSELEAVE: {
|
||||||
|
display_has_mouse = false;
|
||||||
|
|
||||||
|
Event ev;
|
||||||
|
ev.setType(Event::MouseLeave);
|
||||||
|
queue_event(ev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
case WM_RBUTTONDOWN:
|
||||||
|
case WM_MBUTTONDOWN: {
|
||||||
|
Event ev;
|
||||||
|
ev.setType(Event::MouseDown);
|
||||||
|
ev.setPosition(gfx::Point(
|
||||||
|
GET_X_LPARAM(lparam) / display_scale,
|
||||||
|
GET_Y_LPARAM(lparam) / display_scale));
|
||||||
|
ev.setButton(
|
||||||
|
msg == WM_LBUTTONDOWN ? Event::LeftButton:
|
||||||
|
msg == WM_RBUTTONDOWN ? Event::RightButton:
|
||||||
|
msg == WM_MBUTTONDOWN ? Event::MiddleButton: Event::NoneButton);
|
||||||
|
queue_event(ev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
case WM_RBUTTONUP:
|
||||||
|
case WM_MBUTTONUP: {
|
||||||
|
Event ev;
|
||||||
|
ev.setType(Event::MouseUp);
|
||||||
|
ev.setPosition(gfx::Point(
|
||||||
|
GET_X_LPARAM(lparam) / display_scale,
|
||||||
|
GET_Y_LPARAM(lparam) / display_scale));
|
||||||
|
ev.setButton(
|
||||||
|
msg == WM_LBUTTONUP ? Event::LeftButton:
|
||||||
|
msg == WM_RBUTTONUP ? Event::RightButton:
|
||||||
|
msg == WM_MBUTTONUP ? Event::MiddleButton: Event::NoneButton);
|
||||||
|
queue_event(ev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_LBUTTONDBLCLK:
|
||||||
|
case WM_MBUTTONDBLCLK:
|
||||||
|
case WM_RBUTTONDBLCLK: {
|
||||||
|
Event ev;
|
||||||
|
ev.setType(Event::MouseDoubleClick);
|
||||||
|
ev.setPosition(gfx::Point(
|
||||||
|
GET_X_LPARAM(lparam) / display_scale,
|
||||||
|
GET_Y_LPARAM(lparam) / display_scale));
|
||||||
|
ev.setButton(
|
||||||
|
msg == WM_LBUTTONDBLCLK ? Event::LeftButton:
|
||||||
|
msg == WM_RBUTTONDBLCLK ? Event::RightButton:
|
||||||
|
msg == WM_MBUTTONDBLCLK ? Event::MiddleButton: Event::NoneButton);
|
||||||
|
queue_event(ev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_MOUSEWHEEL: {
|
||||||
|
RECT rc;
|
||||||
|
::GetWindowRect(hwnd, &rc);
|
||||||
|
|
||||||
|
Event ev;
|
||||||
|
ev.setType(Event::MouseWheel);
|
||||||
|
ev.setPosition((gfx::Point(
|
||||||
|
GET_X_LPARAM(lparam),
|
||||||
|
GET_Y_LPARAM(lparam)) - gfx::Point(rc.left, rc.top))
|
||||||
|
/ display_scale);
|
||||||
|
ev.setDelta(((short)HIWORD(wparam)) / WHEEL_DELTA);
|
||||||
|
queue_event(ev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return ::CallWindowProc(base_wndproc, hwnd, msg, wparam, lparam);
|
return ::CallWindowProc(base_wndproc, hwnd, msg, wparam, lparam);
|
||||||
|
@ -306,6 +412,7 @@ public:
|
||||||
|
|
||||||
void setScale(int scale) OVERRIDE {
|
void setScale(int scale) OVERRIDE {
|
||||||
ASSERT(scale >= 1);
|
ASSERT(scale >= 1);
|
||||||
|
display_scale = scale;
|
||||||
|
|
||||||
if (m_scale == scale)
|
if (m_scale == scale)
|
||||||
return;
|
return;
|
||||||
|
@ -403,7 +510,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Capabilities capabilities() const {
|
Capabilities capabilities() const {
|
||||||
return kCanResizeDisplayCapability;
|
return (Capabilities)
|
||||||
|
(kCanResizeDisplayCapability
|
||||||
|
#ifdef WIN32
|
||||||
|
| kMouseEventsCapability
|
||||||
|
#endif
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Display* createDisplay(int width, int height, int scale) {
|
Display* createDisplay(int width, int height, int scale) {
|
||||||
|
|
|
@ -436,8 +436,7 @@ bool ComboBoxEntry::onProcessMessage(Message* msg)
|
||||||
releaseMouse();
|
releaseMouse();
|
||||||
|
|
||||||
MouseMessage mouseMsg2(kMouseDownMessage,
|
MouseMessage mouseMsg2(kMouseDownMessage,
|
||||||
mouseMsg->buttons(),
|
mouseMsg->buttons(), mouseMsg->position(), 0);
|
||||||
mouseMsg->position());
|
|
||||||
pick->sendMessage(&mouseMsg2);
|
pick->sendMessage(&mouseMsg2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ bool IntEntry::onProcessMessage(Message* msg)
|
||||||
|
|
||||||
MouseMessage mouseMsg2(kMouseDownMessage,
|
MouseMessage mouseMsg2(kMouseDownMessage,
|
||||||
mouseMsg->buttons(),
|
mouseMsg->buttons(),
|
||||||
mouseMsg->position());
|
mouseMsg->position(), 0);
|
||||||
m_slider->sendMessage(&mouseMsg2);
|
m_slider->sendMessage(&mouseMsg2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ bool IntEntry::onProcessMessage(Message* msg)
|
||||||
case kMouseWheelMessage:
|
case kMouseWheelMessage:
|
||||||
if (isEnabled()) {
|
if (isEnabled()) {
|
||||||
int oldValue = getValue();
|
int oldValue = getValue();
|
||||||
int newValue = oldValue + jmouse_z(0) - jmouse_z(1);
|
int newValue = oldValue + static_cast<MouseMessage*>(msg)->wheelDelta();
|
||||||
newValue = MID(m_min, newValue, m_max);
|
newValue = MID(m_min, newValue, m_max);
|
||||||
if (newValue != oldValue) {
|
if (newValue != oldValue) {
|
||||||
setValue(newValue);
|
setValue(newValue);
|
||||||
|
|
|
@ -185,7 +185,7 @@ bool ListBox::onProcessMessage(Message* msg)
|
||||||
View* view = View::getView(this);
|
View* view = View::getView(this);
|
||||||
if (view) {
|
if (view) {
|
||||||
gfx::Point scroll = view->getViewScroll();
|
gfx::Point scroll = view->getViewScroll();
|
||||||
scroll.y += (jmouse_z(1) - jmouse_z(0)) * getTextHeight()*3;
|
scroll.y += -static_cast<MouseMessage*>(msg)->wheelDelta() * getTextHeight()*3;
|
||||||
view->setViewScroll(scroll);
|
view->setViewScroll(scroll);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "she/display.h"
|
#include "she/display.h"
|
||||||
#include "she/event.h"
|
#include "she/event.h"
|
||||||
#include "she/event_queue.h"
|
#include "she/event_queue.h"
|
||||||
|
#include "she/system.h"
|
||||||
#include "ui/intern.h"
|
#include "ui/intern.h"
|
||||||
#include "ui/ui.h"
|
#include "ui/ui.h"
|
||||||
|
|
||||||
|
@ -65,6 +66,8 @@ struct Filter
|
||||||
typedef std::list<Message*> Messages;
|
typedef std::list<Message*> Messages;
|
||||||
typedef std::list<Filter*> Filters;
|
typedef std::list<Filter*> Filters;
|
||||||
|
|
||||||
|
static bool mouse_events_from_she;
|
||||||
|
|
||||||
static int double_click_level;
|
static int double_click_level;
|
||||||
static MouseButtons double_click_buttons;
|
static MouseButtons double_click_buttons;
|
||||||
static int double_click_ticks;
|
static int double_click_ticks;
|
||||||
|
@ -114,6 +117,7 @@ Manager::Manager()
|
||||||
, m_clipboard(NULL)
|
, m_clipboard(NULL)
|
||||||
, m_eventQueue(NULL)
|
, m_eventQueue(NULL)
|
||||||
, m_lockedWindow(NULL)
|
, m_lockedWindow(NULL)
|
||||||
|
, m_mouseButtons(kButtonNone)
|
||||||
{
|
{
|
||||||
if (!m_defaultManager) {
|
if (!m_defaultManager) {
|
||||||
// Hook the window close message
|
// Hook the window close message
|
||||||
|
@ -145,8 +149,13 @@ Manager::Manager()
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
|
|
||||||
// Default manager is the first one (and is always visible).
|
// Default manager is the first one (and is always visible).
|
||||||
if (!m_defaultManager)
|
if (!m_defaultManager) {
|
||||||
m_defaultManager = this;
|
m_defaultManager = this;
|
||||||
|
|
||||||
|
mouse_events_from_she =
|
||||||
|
((she::Instance()->capabilities() & she::kMouseEventsCapability)
|
||||||
|
== she::kMouseEventsCapability);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager::~Manager()
|
Manager::~Manager()
|
||||||
|
@ -202,10 +211,6 @@ void Manager::run()
|
||||||
|
|
||||||
bool Manager::generateMessages()
|
bool Manager::generateMessages()
|
||||||
{
|
{
|
||||||
Widget* widget;
|
|
||||||
Widget* window;
|
|
||||||
int c;
|
|
||||||
|
|
||||||
// Poll keyboard
|
// Poll keyboard
|
||||||
poll_keyboard();
|
poll_keyboard();
|
||||||
|
|
||||||
|
@ -223,7 +228,7 @@ bool Manager::generateMessages()
|
||||||
// New windows to show?
|
// New windows to show?
|
||||||
if (!new_windows.empty()) {
|
if (!new_windows.empty()) {
|
||||||
UI_FOREACH_WIDGET(new_windows, it) {
|
UI_FOREACH_WIDGET(new_windows, it) {
|
||||||
window = *it;
|
Widget* window = *it;
|
||||||
|
|
||||||
// Relayout
|
// Relayout
|
||||||
window->layout();
|
window->layout();
|
||||||
|
@ -246,56 +251,46 @@ bool Manager::generateMessages()
|
||||||
new_windows.clear();
|
new_windows.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mouse_events_from_she)
|
||||||
|
generateMouseMessages();
|
||||||
|
|
||||||
|
// Generate Close message when the user press close button on the system window.
|
||||||
|
if (want_close_stage == STAGE_WANT_CLOSE) {
|
||||||
|
want_close_stage = STAGE_NORMAL;
|
||||||
|
|
||||||
|
Message* msg = new Message(kCloseAppMessage);
|
||||||
|
msg->broadcastToChildren(this);
|
||||||
|
enqueueMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
generateKeyMessages();
|
||||||
|
generateMessagesFromSheEvents();
|
||||||
|
|
||||||
|
// Generate messages for timers
|
||||||
|
Timer::pollTimers();
|
||||||
|
|
||||||
|
// Generate redraw events.
|
||||||
|
flushRedraw();
|
||||||
|
|
||||||
|
if (!msg_queue.empty())
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::generateMouseMessages()
|
||||||
|
{
|
||||||
// Update mouse status
|
// Update mouse status
|
||||||
bool mousemove = jmouse_poll();
|
bool mousemove = jmouse_poll();
|
||||||
if (mousemove || !mouse_widget) {
|
|
||||||
// Get the list of widgets to send mouse messages.
|
|
||||||
mouse_widgets_list.clear();
|
|
||||||
broadcastMouseMessage(mouse_widgets_list);
|
|
||||||
|
|
||||||
// Get the widget under the mouse
|
gfx::Point mousePos(gfx::Point(jmouse_x(0), jmouse_y(0)));
|
||||||
widget = NULL;
|
|
||||||
|
|
||||||
UI_FOREACH_WIDGET(mouse_widgets_list, it) {
|
if (mousemove || !mouse_widget)
|
||||||
widget = (*it)->pick(gfx::Point(jmouse_x(0), jmouse_y(0)));
|
handleMouseMove(mousePos, currentMouseButtons(0));
|
||||||
if (widget)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fixup "mouse" flag
|
|
||||||
if (widget != mouse_widget) {
|
|
||||||
if (!widget)
|
|
||||||
freeMouse();
|
|
||||||
else
|
|
||||||
setMouse(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mouse movement
|
|
||||||
if (mousemove) {
|
|
||||||
Widget* dst;
|
|
||||||
|
|
||||||
// Reset double click status
|
|
||||||
double_click_level = DOUBLE_CLICK_NONE;
|
|
||||||
|
|
||||||
if (capture_widget)
|
|
||||||
dst = capture_widget;
|
|
||||||
else
|
|
||||||
dst = mouse_widget;
|
|
||||||
|
|
||||||
// Send the mouse movement message
|
|
||||||
enqueueMessage(newMouseMessage(kMouseMoveMessage, dst,
|
|
||||||
currentMouseButtons(0)));
|
|
||||||
generateSetCursorMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mouse wheel
|
// Mouse wheel
|
||||||
if (jmouse_z(0) != jmouse_z(1)) {
|
if (jmouse_z(0) != jmouse_z(1))
|
||||||
enqueueMessage(newMouseMessage(kMouseWheelMessage,
|
handleMouseWheel(mousePos, currentMouseButtons(0), jmouse_z(0) - jmouse_z(1));
|
||||||
capture_widget ? capture_widget:
|
|
||||||
mouse_widget,
|
|
||||||
currentMouseButtons(0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mouse clicks
|
// Mouse clicks
|
||||||
if (jmouse_b(0) != jmouse_b(1)) {
|
if (jmouse_b(0) != jmouse_b(1)) {
|
||||||
|
@ -359,63 +354,34 @@ bool Manager::generateMessages()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Z order: Send the window to top (only when you click in
|
switch (msgType) {
|
||||||
// a window that aren't the desktop).
|
case kMouseDownMessage:
|
||||||
if (msgType == kMouseDownMessage && !capture_widget && mouse_widget) {
|
handleMouseDown(mousePos, mouseButtons);
|
||||||
// The clicked window
|
break;
|
||||||
Window* window = mouse_widget->getRoot();
|
case kMouseUpMessage:
|
||||||
Manager* win_manager = (window ? window->getManager(): NULL);
|
handleMouseUp(mousePos, mouseButtons);
|
||||||
|
break;
|
||||||
if ((window) &&
|
case kDoubleClickMessage:
|
||||||
// We cannot change Z-order of desktop windows
|
handleMouseDoubleClick(mousePos, mouseButtons);
|
||||||
(!window->isDesktop()) &&
|
break;
|
||||||
// We cannot change Z order of foreground windows because a
|
|
||||||
// foreground window can launch other background windows
|
|
||||||
// which should be kept on top of the foreground one.
|
|
||||||
(!window->isForeground()) &&
|
|
||||||
// If the window is not already the top window of the manager.
|
|
||||||
(window != win_manager->getTopWindow())) {
|
|
||||||
base::ScopedValue<Widget*> scoped(m_lockedWindow, window, NULL);
|
|
||||||
|
|
||||||
// Put it in the top of the list
|
|
||||||
win_manager->removeChild(window);
|
|
||||||
|
|
||||||
if (window->isOnTop())
|
|
||||||
win_manager->insertChild(0, window);
|
|
||||||
else {
|
|
||||||
int pos = (int)win_manager->getChildren().size();
|
|
||||||
UI_FOREACH_WIDGET_BACKWARD(win_manager->getChildren(), it) {
|
|
||||||
if (static_cast<Window*>(*it)->isOnTop())
|
|
||||||
break;
|
|
||||||
|
|
||||||
--pos;
|
|
||||||
}
|
|
||||||
win_manager->insertChild(pos, window);
|
|
||||||
}
|
|
||||||
|
|
||||||
window->invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Put the focus
|
|
||||||
setFocus(mouse_widget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enqueueMessage(newMouseMessage(msgType,
|
|
||||||
capture_widget ? capture_widget:
|
|
||||||
mouse_widget,
|
|
||||||
mouseButtons));
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Generate Close message when the user press close button on the system window.
|
void Manager::generateSetCursorMessage(const gfx::Point& mousePos)
|
||||||
if (want_close_stage == STAGE_WANT_CLOSE) {
|
{
|
||||||
want_close_stage = STAGE_NORMAL;
|
Widget* dst = (capture_widget ? capture_widget: mouse_widget);
|
||||||
|
if (dst)
|
||||||
Message* msg = new Message(kCloseAppMessage);
|
enqueueMessage(newMouseMessage(kSetCursorMessage, dst,
|
||||||
msg->broadcastToChildren(this);
|
mousePos, currentMouseButtons(0)));
|
||||||
enqueueMessage(msg);
|
else
|
||||||
}
|
jmouse_set_cursor(kArrowCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::generateKeyMessages()
|
||||||
|
{
|
||||||
// Generate kKeyDownMessage messages.
|
// Generate kKeyDownMessage messages.
|
||||||
|
int c;
|
||||||
while (keypressed()) {
|
while (keypressed()) {
|
||||||
int scancode;
|
int scancode;
|
||||||
int unicode_char = ureadkey(&scancode);
|
int unicode_char = ureadkey(&scancode);
|
||||||
|
@ -435,7 +401,7 @@ bool Manager::generateMessages()
|
||||||
enqueueMessage(msg);
|
enqueueMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (c=0; c<KEY_MAX; c++) {
|
for (int c=0; c<KEY_MAX; c++) {
|
||||||
if (old_readed_key[c] != key[c]) {
|
if (old_readed_key[c] != key[c]) {
|
||||||
KeyScancode scancode = static_cast<ui::KeyScancode>(c);
|
KeyScancode scancode = static_cast<ui::KeyScancode>(c);
|
||||||
|
|
||||||
|
@ -466,7 +432,20 @@ bool Manager::generateMessages()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static MouseButtons mouse_buttons_from_she_to_ui(const she::Event& sheEvent)
|
||||||
|
{
|
||||||
|
switch (sheEvent.button()) {
|
||||||
|
case she::Event::LeftButton: return kButtonLeft; break;
|
||||||
|
case she::Event::RightButton: return kButtonRight; break;
|
||||||
|
case she::Event::MiddleButton: return kButtonMiddle; break;
|
||||||
|
default: return kButtonNone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::generateMessagesFromSheEvents()
|
||||||
|
{
|
||||||
// Events from "she" layer.
|
// Events from "she" layer.
|
||||||
she::Event sheEvent;
|
she::Event sheEvent;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -476,34 +455,179 @@ bool Manager::generateMessages()
|
||||||
|
|
||||||
switch (sheEvent.type()) {
|
switch (sheEvent.type()) {
|
||||||
|
|
||||||
case she::Event::DropFiles:
|
case she::Event::DropFiles: {
|
||||||
{
|
Message* msg = new DropFilesMessage(sheEvent.files());
|
||||||
Message* msg = new DropFilesMessage(sheEvent.files());
|
msg->addRecipient(this);
|
||||||
msg->addRecipient(this);
|
enqueueMessage(msg);
|
||||||
enqueueMessage(msg);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case she::Event::MouseMove: {
|
||||||
|
if (!mouse_events_from_she)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_internal_set_mouse_position(sheEvent.position());
|
||||||
|
|
||||||
|
handleMouseMove(sheEvent.position(), m_mouseButtons);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case she::Event::MouseDown: {
|
||||||
|
if (!mouse_events_from_she)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MouseButtons pressedButton = mouse_buttons_from_she_to_ui(sheEvent);
|
||||||
|
m_mouseButtons = (MouseButtons)((int)m_mouseButtons | (int)pressedButton);
|
||||||
|
_internal_set_mouse_buttons(m_mouseButtons);
|
||||||
|
|
||||||
|
handleMouseDown(sheEvent.position(), pressedButton);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case she::Event::MouseUp: {
|
||||||
|
if (!mouse_events_from_she)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MouseButtons releasedButton = mouse_buttons_from_she_to_ui(sheEvent);
|
||||||
|
m_mouseButtons = (MouseButtons)((int)m_mouseButtons & ~(int)releasedButton);
|
||||||
|
_internal_set_mouse_buttons(m_mouseButtons);
|
||||||
|
|
||||||
|
handleMouseUp(sheEvent.position(), releasedButton);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case she::Event::MouseDoubleClick: {
|
||||||
|
if (!mouse_events_from_she)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MouseButtons clickedButton = mouse_buttons_from_she_to_ui(sheEvent);
|
||||||
|
handleMouseUp(sheEvent.position(), clickedButton);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case she::Event::MouseWheel: {
|
||||||
|
if (!mouse_events_from_she)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
handleMouseWheel(sheEvent.position(), m_mouseButtons, sheEvent.delta());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Generate messages for timers
|
void Manager::handleMouseMove(const gfx::Point& mousePos, MouseButtons mouseButtons)
|
||||||
Timer::pollTimers();
|
{
|
||||||
|
// Get the list of widgets to send mouse messages.
|
||||||
|
mouse_widgets_list.clear();
|
||||||
|
broadcastMouseMessage(mouse_widgets_list);
|
||||||
|
|
||||||
// Generate redraw events.
|
// Get the widget under the mouse
|
||||||
flushRedraw();
|
Widget* widget = NULL;
|
||||||
|
UI_FOREACH_WIDGET(mouse_widgets_list, it) {
|
||||||
|
widget = (*it)->pick(mousePos);
|
||||||
|
if (widget)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!msg_queue.empty())
|
// Fixup "mouse" flag
|
||||||
return true;
|
if (widget != mouse_widget) {
|
||||||
else
|
if (!widget)
|
||||||
return false;
|
freeMouse();
|
||||||
|
else
|
||||||
|
setMouse(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset double click status
|
||||||
|
double_click_level = DOUBLE_CLICK_NONE;
|
||||||
|
|
||||||
|
// Send the mouse movement message
|
||||||
|
Widget* dst = (capture_widget ? capture_widget: mouse_widget);
|
||||||
|
enqueueMessage(newMouseMessage(kMouseMoveMessage, dst, mousePos, mouseButtons));
|
||||||
|
|
||||||
|
generateSetCursorMessage(mousePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::handleMouseDown(const gfx::Point& mousePos, MouseButtons mouseButtons)
|
||||||
|
{
|
||||||
|
handleWindowZOrder();
|
||||||
|
|
||||||
|
enqueueMessage(newMouseMessage(kMouseDownMessage,
|
||||||
|
(capture_widget ? capture_widget: mouse_widget),
|
||||||
|
mousePos, mouseButtons));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::handleMouseUp(const gfx::Point& mousePos, MouseButtons mouseButtons)
|
||||||
|
{
|
||||||
|
enqueueMessage(newMouseMessage(kMouseUpMessage,
|
||||||
|
(capture_widget ? capture_widget: mouse_widget),
|
||||||
|
mousePos, mouseButtons));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::handleMouseDoubleClick(const gfx::Point& mousePos, MouseButtons mouseButtons)
|
||||||
|
{
|
||||||
|
enqueueMessage(newMouseMessage(kDoubleClickMessage,
|
||||||
|
(capture_widget ? capture_widget: mouse_widget),
|
||||||
|
mousePos, mouseButtons));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::handleMouseWheel(const gfx::Point& mousePos, MouseButtons mouseButtons, int delta)
|
||||||
|
{
|
||||||
|
enqueueMessage(newMouseMessage(kMouseWheelMessage,
|
||||||
|
(capture_widget ? capture_widget: mouse_widget),
|
||||||
|
mousePos, mouseButtons, delta));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handles Z order: Send the window to top (only when you click in a
|
||||||
|
// window that aren't the desktop).
|
||||||
|
void Manager::handleWindowZOrder()
|
||||||
|
{
|
||||||
|
if (capture_widget || !mouse_widget)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// The clicked window
|
||||||
|
Window* window = mouse_widget->getRoot();
|
||||||
|
Manager* win_manager = (window ? window->getManager(): NULL);
|
||||||
|
|
||||||
|
if ((window) &&
|
||||||
|
// We cannot change Z-order of desktop windows
|
||||||
|
(!window->isDesktop()) &&
|
||||||
|
// We cannot change Z order of foreground windows because a
|
||||||
|
// foreground window can launch other background windows
|
||||||
|
// which should be kept on top of the foreground one.
|
||||||
|
(!window->isForeground()) &&
|
||||||
|
// If the window is not already the top window of the manager.
|
||||||
|
(window != win_manager->getTopWindow())) {
|
||||||
|
base::ScopedValue<Widget*> scoped(m_lockedWindow, window, NULL);
|
||||||
|
|
||||||
|
// Put it in the top of the list
|
||||||
|
win_manager->removeChild(window);
|
||||||
|
|
||||||
|
if (window->isOnTop())
|
||||||
|
win_manager->insertChild(0, window);
|
||||||
|
else {
|
||||||
|
int pos = (int)win_manager->getChildren().size();
|
||||||
|
UI_FOREACH_WIDGET_BACKWARD(win_manager->getChildren(), it) {
|
||||||
|
if (static_cast<Window*>(*it)->isOnTop())
|
||||||
|
break;
|
||||||
|
|
||||||
|
--pos;
|
||||||
|
}
|
||||||
|
win_manager->insertChild(pos, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
window->invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put the focus
|
||||||
|
setFocus(mouse_widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::dispatchMessages()
|
void Manager::dispatchMessages()
|
||||||
{
|
{
|
||||||
// Add the "Queue Processing" message for the manager.
|
// Add the "Queue Processing" message for the manager.
|
||||||
enqueueMessage(newMouseMessage(kQueueProcessingMessage, this,
|
enqueueMessage(newMouseMessage(kQueueProcessingMessage, this,
|
||||||
currentMouseButtons(0)));
|
gfx::Point(jmouse_x(0), jmouse_y(0)), currentMouseButtons(0)));
|
||||||
|
|
||||||
pumpQueue();
|
pumpQueue();
|
||||||
}
|
}
|
||||||
|
@ -716,7 +840,7 @@ void Manager::setMouse(Widget* widget)
|
||||||
it = widget_parents.begin();
|
it = widget_parents.begin();
|
||||||
|
|
||||||
Message* msg = newMouseMessage(kMouseEnterMessage, NULL,
|
Message* msg = newMouseMessage(kMouseEnterMessage, NULL,
|
||||||
currentMouseButtons(0));
|
gfx::Point(jmouse_x(0), jmouse_y(0)), currentMouseButtons(0));
|
||||||
|
|
||||||
for (; it != widget_parents.end(); ++it) {
|
for (; it != widget_parents.end(); ++it) {
|
||||||
(*it)->flags |= JI_HASMOUSE;
|
(*it)->flags |= JI_HASMOUSE;
|
||||||
|
@ -724,7 +848,7 @@ void Manager::setMouse(Widget* widget)
|
||||||
}
|
}
|
||||||
|
|
||||||
enqueueMessage(msg);
|
enqueueMessage(msg);
|
||||||
generateSetCursorMessage();
|
generateSetCursorMessage(gfx::Point(jmouse_x(0), jmouse_y(0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1224,22 +1348,6 @@ void Manager::collectGarbage()
|
||||||
Internal routines
|
Internal routines
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
// static
|
|
||||||
void Manager::generateSetCursorMessage()
|
|
||||||
{
|
|
||||||
Widget* dst;
|
|
||||||
if (capture_widget)
|
|
||||||
dst = capture_widget;
|
|
||||||
else
|
|
||||||
dst = mouse_widget;
|
|
||||||
|
|
||||||
if (dst)
|
|
||||||
enqueueMessage(newMouseMessage(kSetCursorMessage, dst,
|
|
||||||
currentMouseButtons(0)));
|
|
||||||
else
|
|
||||||
jmouse_set_cursor(kArrowCursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void Manager::removeWidgetFromRecipients(Widget* widget, Message* msg)
|
void Manager::removeWidgetFromRecipients(Widget* widget, Message* msg)
|
||||||
{
|
{
|
||||||
|
@ -1276,13 +1384,10 @@ Widget* Manager::findMagneticWidget(Widget* widget)
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
Message* Manager::newMouseMessage(MessageType type, Widget* widget,
|
Message* Manager::newMouseMessage(MessageType type,
|
||||||
MouseButtons buttons)
|
Widget* widget, gfx::Point mousePos, MouseButtons buttons, int delta)
|
||||||
{
|
{
|
||||||
Message* msg =
|
Message* msg = new MouseMessage(type, buttons, mousePos, delta);
|
||||||
new MouseMessage(type, buttons,
|
|
||||||
gfx::Point(jmouse_x(0),
|
|
||||||
jmouse_y(0)));
|
|
||||||
|
|
||||||
if (widget != NULL)
|
if (widget != NULL)
|
||||||
msg->addRecipient(widget);
|
msg->addRecipient(widget);
|
||||||
|
|
|
@ -92,14 +92,23 @@ namespace ui {
|
||||||
virtual LayoutIO* onGetLayoutIO();
|
virtual LayoutIO* onGetLayoutIO();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void generateMouseMessages();
|
||||||
|
void generateSetCursorMessage(const gfx::Point& mousePos);
|
||||||
|
void generateKeyMessages();
|
||||||
|
void generateMessagesFromSheEvents();
|
||||||
|
void handleMouseMove(const gfx::Point& mousePos, MouseButtons mouseButtons);
|
||||||
|
void handleMouseDown(const gfx::Point& mousePos, MouseButtons mouseButtons);
|
||||||
|
void handleMouseUp(const gfx::Point& mousePos, MouseButtons mouseButtons);
|
||||||
|
void handleMouseDoubleClick(const gfx::Point& mousePos, MouseButtons mouseButtons);
|
||||||
|
void handleMouseWheel(const gfx::Point& mousePos, MouseButtons mouseButtons, int delta);
|
||||||
|
void handleWindowZOrder();
|
||||||
|
|
||||||
void pumpQueue();
|
void pumpQueue();
|
||||||
void generateSetCursorMessage();
|
|
||||||
static void removeWidgetFromRecipients(Widget* widget, Message* msg);
|
static void removeWidgetFromRecipients(Widget* widget, Message* msg);
|
||||||
static bool someParentIsFocusStop(Widget* widget);
|
static bool someParentIsFocusStop(Widget* widget);
|
||||||
static Widget* findMagneticWidget(Widget* widget);
|
static Widget* findMagneticWidget(Widget* widget);
|
||||||
static Message* newMouseMessage(MessageType type, Widget* destination);
|
static Message* newMouseMessage(MessageType type,
|
||||||
static Message* newMouseMessage(MessageType type, Widget* destination,
|
Widget* widget, gfx::Point mousePos, MouseButtons buttons, int delta = 0);
|
||||||
MouseButtons mouseButtons);
|
|
||||||
static MouseButtons currentMouseButtons(int antique);
|
static MouseButtons currentMouseButtons(int antique);
|
||||||
void broadcastKeyMsg(Message* msg);
|
void broadcastKeyMsg(Message* msg);
|
||||||
|
|
||||||
|
@ -113,6 +122,9 @@ namespace ui {
|
||||||
// This member is used to make freeWidget() a no-op when we
|
// This member is used to make freeWidget() a no-op when we
|
||||||
// restack a window if the user clicks on it.
|
// restack a window if the user clicks on it.
|
||||||
Widget* m_lockedWindow;
|
Widget* m_lockedWindow;
|
||||||
|
|
||||||
|
// Current pressed buttons.
|
||||||
|
MouseButtons m_mouseButtons;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
|
|
@ -101,20 +101,22 @@ namespace ui {
|
||||||
class MouseMessage : public Message
|
class MouseMessage : public Message
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MouseMessage(MessageType type, MouseButtons buttons, const gfx::Point& pos)
|
MouseMessage(MessageType type, MouseButtons buttons, const gfx::Point& pos, int delta)
|
||||||
: Message(type), m_buttons(buttons), m_pos(pos) {
|
: Message(type), m_buttons(buttons), m_pos(pos), m_delta(delta) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseButtons buttons() const { return m_buttons; }
|
MouseButtons buttons() const { return m_buttons; }
|
||||||
bool left() const { return (m_buttons & kButtonLeft) == kButtonLeft; }
|
bool left() const { return (m_buttons & kButtonLeft) == kButtonLeft; }
|
||||||
bool right() const { return (m_buttons & kButtonRight) == kButtonRight; }
|
bool right() const { return (m_buttons & kButtonRight) == kButtonRight; }
|
||||||
bool middle() const { return (m_buttons & kButtonMiddle) == kButtonMiddle; }
|
bool middle() const { return (m_buttons & kButtonMiddle) == kButtonMiddle; }
|
||||||
|
int wheelDelta() const { return m_delta; }
|
||||||
|
|
||||||
const gfx::Point& position() const { return m_pos; }
|
const gfx::Point& position() const { return m_pos; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MouseButtons m_buttons; // Pressed buttons
|
MouseButtons m_buttons; // Pressed buttons
|
||||||
gfx::Point m_pos; // Mouse position
|
gfx::Point m_pos; // Mouse position
|
||||||
|
int m_delta; // Wheel axis variation
|
||||||
};
|
};
|
||||||
|
|
||||||
class TimerMessage : public Message
|
class TimerMessage : public Message
|
||||||
|
|
|
@ -191,7 +191,7 @@ bool Slider::onProcessMessage(Message* msg)
|
||||||
|
|
||||||
case kMouseWheelMessage:
|
case kMouseWheelMessage:
|
||||||
if (isEnabled()) {
|
if (isEnabled()) {
|
||||||
int value = m_value + jmouse_z(0) - jmouse_z(1);
|
int value = m_value + static_cast<MouseMessage*>(msg)->wheelDelta();
|
||||||
|
|
||||||
value = MID(m_min, value, m_max);
|
value = MID(m_min, value, m_max);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "ui/widget.h"
|
#include "ui/widget.h"
|
||||||
|
|
||||||
#include <allegro.h>
|
#include <allegro.h>
|
||||||
#if defined(ALLEGRO_WINDOWS)
|
#if defined(WIN32)
|
||||||
#include <winalleg.h>
|
#include <winalleg.h>
|
||||||
#elif defined(ALLEGRO_UNIX)
|
#elif defined(ALLEGRO_UNIX)
|
||||||
#include <xalleg.h>
|
#include <xalleg.h>
|
||||||
|
@ -46,6 +46,7 @@ volatile int ji_clock = 0;
|
||||||
|
|
||||||
static CursorType mouse_cursor_type = kNoCursor;
|
static CursorType mouse_cursor_type = kNoCursor;
|
||||||
static Cursor* mouse_cursor = NULL;
|
static Cursor* mouse_cursor = NULL;
|
||||||
|
static she::Display* mouse_display = NULL;
|
||||||
static Overlay* mouse_cursor_overlay = NULL;
|
static Overlay* mouse_cursor_overlay = NULL;
|
||||||
|
|
||||||
/* Mouse information (button and position). */
|
/* Mouse information (button and position). */
|
||||||
|
@ -125,6 +126,7 @@ void SetDisplay(she::Display* display)
|
||||||
CursorType cursor = jmouse_get_cursor();
|
CursorType cursor = jmouse_get_cursor();
|
||||||
|
|
||||||
jmouse_set_cursor(kNoCursor);
|
jmouse_set_cursor(kNoCursor);
|
||||||
|
mouse_display = display;
|
||||||
ji_screen = (display ? reinterpret_cast<BITMAP*>(display->getSurface()->nativeHandle()): NULL);
|
ji_screen = (display ? reinterpret_cast<BITMAP*>(display->getSurface()->nativeHandle()): NULL);
|
||||||
ji_screen_w = (ji_screen ? ji_screen->w: 0);
|
ji_screen_w = (ji_screen ? ji_screen->w: 0);
|
||||||
ji_screen_h = (ji_screen ? ji_screen->h: 0);
|
ji_screen_h = (ji_screen ? ji_screen->h: 0);
|
||||||
|
@ -240,6 +242,21 @@ bool jmouse_poll()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _internal_set_mouse_position(const gfx::Point& newPos)
|
||||||
|
{
|
||||||
|
moved = true;
|
||||||
|
m_x[1] = m_x[0];
|
||||||
|
m_y[1] = m_y[0];
|
||||||
|
m_x[0] = newPos.x;
|
||||||
|
m_y[0] = newPos.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _internal_set_mouse_buttons(MouseButtons buttons)
|
||||||
|
{
|
||||||
|
m_b[1] = m_b[0];
|
||||||
|
m_b[0] = buttons;
|
||||||
|
}
|
||||||
|
|
||||||
gfx::Point get_mouse_position()
|
gfx::Point get_mouse_position()
|
||||||
{
|
{
|
||||||
return gfx::Point(jmouse_x(0), jmouse_y(0));
|
return gfx::Point(jmouse_x(0), jmouse_y(0));
|
||||||
|
@ -345,8 +362,8 @@ static void update_mouse_position()
|
||||||
m_y[0] = JI_SCREEN_H * mouse_y / SCREEN_H;
|
m_y[0] = JI_SCREEN_H * mouse_y / SCREEN_H;
|
||||||
|
|
||||||
if (is_windowed_mode()) {
|
if (is_windowed_mode()) {
|
||||||
#ifdef ALLEGRO_WINDOWS
|
#ifdef WIN32
|
||||||
// This help us (in windows) to get mouse feedback when we capture
|
// This help us (on Windows) to get mouse feedback when we capture
|
||||||
// the mouse but we are outside the window.
|
// the mouse but we are outside the window.
|
||||||
POINT pt;
|
POINT pt;
|
||||||
RECT rc;
|
RECT rc;
|
||||||
|
|
|
@ -57,6 +57,9 @@ namespace ui {
|
||||||
|
|
||||||
bool jmouse_poll();
|
bool jmouse_poll();
|
||||||
|
|
||||||
|
void _internal_set_mouse_position(const gfx::Point& newPos);
|
||||||
|
void _internal_set_mouse_buttons(MouseButtons buttons);
|
||||||
|
|
||||||
gfx::Point get_mouse_position();
|
gfx::Point get_mouse_position();
|
||||||
void set_mouse_position(const gfx::Point& newPos);
|
void set_mouse_position(const gfx::Point& newPos);
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,7 @@ bool TextBox::onProcessMessage(Message* msg)
|
||||||
if (view) {
|
if (view) {
|
||||||
gfx::Point scroll = view->getViewScroll();
|
gfx::Point scroll = view->getViewScroll();
|
||||||
|
|
||||||
scroll.y += (jmouse_z(1) - jmouse_z(0)) * getTextHeight()*3;
|
scroll.y += -static_cast<MouseMessage*>(msg)->wheelDelta() * getTextHeight()*3;
|
||||||
|
|
||||||
view->setViewScroll(scroll);
|
view->setViewScroll(scroll);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue