mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-08-12 17:15:21 +00:00
client: interactive screen layer
This commit is contained in:
parent
a70110c4e5
commit
3b51087b36
@ -358,6 +358,22 @@ void Application::remove_inputs_handler(InputsHandler& handler)
|
||||
_inputs_handler = &default_inputs_handler;
|
||||
}
|
||||
|
||||
void Application::capture_mouse()
|
||||
{
|
||||
if (!_active_screen) {
|
||||
return;
|
||||
}
|
||||
_active_screen->capture_mouse();
|
||||
}
|
||||
|
||||
void Application::release_mouse_capture()
|
||||
{
|
||||
if (!_active_screen || !_active_screen->is_mouse_captured()) {
|
||||
return;
|
||||
}
|
||||
_active_screen->relase_mouse();
|
||||
}
|
||||
|
||||
void Application::abort()
|
||||
{
|
||||
Platform::set_event_listener(NULL);
|
||||
@ -402,10 +418,10 @@ RedScreen* Application::find_screen(int id)
|
||||
bool Application::release_capture()
|
||||
{
|
||||
unpress_all();
|
||||
if (!_active_screen || !_active_screen->is_captured()) {
|
||||
if (!_active_screen || !_active_screen->is_mouse_captured()) {
|
||||
return false;
|
||||
}
|
||||
_active_screen->relase_inputs();
|
||||
_active_screen->relase_mouse();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -455,7 +471,7 @@ RedScreen* Application::get_screen(int id)
|
||||
|
||||
if (capture) {
|
||||
_main_screen->activate();
|
||||
_main_screen->capture_inputs();
|
||||
_main_screen->capture_mouse();
|
||||
}
|
||||
} else if (id != 0) {
|
||||
screen->show(false, _main_screen);
|
||||
@ -489,7 +505,7 @@ void Application::on_screen_destroyed(int id, bool was_captured)
|
||||
position_screens();
|
||||
if (capture) {
|
||||
_main_screen->activate();
|
||||
_main_screen->capture_inputs();
|
||||
_main_screen->capture_mouse();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -499,11 +515,6 @@ void Application::on_mouse_motion(int dx, int dy, int buttons_state)
|
||||
_inputs_handler->on_mouse_motion(dx, dy, buttons_state);
|
||||
}
|
||||
|
||||
void Application::on_mouse_position(int x, int y, int buttons_state, int display_id)
|
||||
{
|
||||
_inputs_handler->on_mouse_position(x, y, buttons_state, display_id);
|
||||
}
|
||||
|
||||
void Application::on_mouse_down(int button, int buttons_state)
|
||||
{
|
||||
_inputs_handler->on_mouse_down(button, buttons_state);
|
||||
@ -1084,7 +1095,7 @@ bool Application::rearrange_monitors(RedScreen& screen)
|
||||
if (capture && _main_screen != &screen) {
|
||||
capture = false;
|
||||
_main_screen->activate();
|
||||
_main_screen->capture_inputs();
|
||||
_main_screen->capture_mouse();
|
||||
}
|
||||
return capture;
|
||||
}
|
||||
@ -1194,14 +1205,16 @@ void Application::enter_full_screen()
|
||||
{
|
||||
LOG_INFO("");
|
||||
_changing_screens = true;
|
||||
release_capture();
|
||||
bool capture = release_capture();
|
||||
assign_monitors();
|
||||
hide();
|
||||
prepare_monitors();
|
||||
position_screens();
|
||||
show_full_screen();
|
||||
_main_screen->activate();
|
||||
_main_screen->capture_inputs();
|
||||
if (capture) {
|
||||
_main_screen->capture_mouse();
|
||||
}
|
||||
_changing_screens = false;
|
||||
_full_screen = true;
|
||||
}
|
||||
|
||||
@ -121,12 +121,13 @@ public:
|
||||
|
||||
void set_inputs_handler(InputsHandler& handler);
|
||||
void remove_inputs_handler(InputsHandler& handler);
|
||||
void capture_mouse();
|
||||
void release_mouse_capture();
|
||||
RedScreen* find_screen(int id);
|
||||
RedScreen* get_screen(int id);
|
||||
|
||||
void on_screen_destroyed(int id, bool was_captured);
|
||||
void on_mouse_motion(int dx, int dy, int buttons_state);
|
||||
void on_mouse_position(int x, int y, int buttons_state, int display_id);
|
||||
void on_mouse_down(int button, int buttons_state);
|
||||
void on_mouse_up(int button, int buttons_state);
|
||||
void on_key_down(RedKey key);
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "cursor_channel.h"
|
||||
#include "display_channel.h"
|
||||
#include "cursor.h"
|
||||
#include "red_client.h"
|
||||
#include "application.h"
|
||||
@ -283,165 +284,66 @@ private:
|
||||
uint32_t* _palette;
|
||||
};
|
||||
|
||||
class CursorSetEvent: public Event {
|
||||
class AttachDispayEvent: public Event {
|
||||
public:
|
||||
CursorSetEvent(CursorChannel& channel, CursorData *cursor, int x, int y, bool visable)
|
||||
AttachDispayEvent(CursorChannel& channel)
|
||||
: _channel (channel)
|
||||
, _cursor (cursor->ref())
|
||||
, _x (x)
|
||||
, _y (y)
|
||||
, _visible (visable)
|
||||
{
|
||||
}
|
||||
|
||||
void create_cursor()
|
||||
{
|
||||
CursorData *cursor = *_cursor;
|
||||
CursorOpaque* native_cursor = cursor->get_opaque();
|
||||
class UpdateDisplayChannel: public ForEachChannelFunc {
|
||||
public:
|
||||
UpdateDisplayChannel(CursorChannel& channel)
|
||||
: _channel (channel)
|
||||
{
|
||||
}
|
||||
|
||||
if (native_cursor) {
|
||||
virtual bool operator() (RedChannel& channel)
|
||||
{
|
||||
if (channel.get_type() != RED_CHANNEL_DISPLAY ||
|
||||
channel.get_id() != _channel.get_id()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
_channel.attach_display(&static_cast<DisplayChannel&>(channel));
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
CursorChannel& _channel;
|
||||
};
|
||||
|
||||
virtual void response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
UpdateDisplayChannel func(_channel);
|
||||
_channel.get_client().for_each_channel(func);
|
||||
}
|
||||
|
||||
private:
|
||||
CursorChannel& _channel;
|
||||
};
|
||||
|
||||
class CursorUpdateEvent: public Event {
|
||||
public:
|
||||
CursorUpdateEvent(CursorChannel& channel)
|
||||
: _channel (channel)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
DisplayChannel* display_channel = _channel._display_channel;
|
||||
if (!display_channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (cursor->header().type) {
|
||||
case CURSOR_TYPE_ALPHA:
|
||||
native_cursor = new AlphaCursor(cursor->header(), cursor->data());
|
||||
break;
|
||||
case CURSOR_TYPE_COLOR32:
|
||||
native_cursor = new ColorCursor32(cursor->header(), cursor->data());
|
||||
break;
|
||||
case CURSOR_TYPE_MONO:
|
||||
native_cursor = new MonoCursor(cursor->header(), cursor->data());
|
||||
break;
|
||||
case CURSOR_TYPE_COLOR4:
|
||||
native_cursor = new ColorCursor4(cursor->header(), cursor->data());
|
||||
break;
|
||||
case CURSOR_TYPE_COLOR8:
|
||||
native_cursor = new UnsupportedCursor(cursor->header());
|
||||
break;
|
||||
case CURSOR_TYPE_COLOR16:
|
||||
native_cursor = new ColorCursor16(cursor->header(), cursor->data());
|
||||
break;
|
||||
case CURSOR_TYPE_COLOR24:
|
||||
native_cursor = new UnsupportedCursor(cursor->header());
|
||||
break;
|
||||
default:
|
||||
THROW("invalid curosr type");
|
||||
}
|
||||
cursor->set_opaque(native_cursor);
|
||||
}
|
||||
|
||||
virtual void response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
CursorData *cursor = *_cursor;
|
||||
create_cursor();
|
||||
Lock lock(_channel._update_lock);
|
||||
|
||||
_channel._hot_pos.x = _x;
|
||||
_channel._hot_pos.y = _y;
|
||||
_channel._cursor_visible = _visible;
|
||||
_channel._cursor_rect.left = _x - cursor->header().hot_spot_x;
|
||||
_channel._cursor_rect.right = _channel._cursor_rect.left + cursor->header().width;
|
||||
_channel._cursor_rect.top = _y - cursor->header().hot_spot_y;
|
||||
_channel._cursor_rect.bottom = _channel._cursor_rect.top + cursor->header().height;
|
||||
|
||||
if (static_cast<Application*>(events_loop.get_owner())->get_mouse_mode() ==
|
||||
RED_MOUSE_MODE_CLIENT) {
|
||||
RedScreen* screen = _channel.screen();
|
||||
ASSERT(screen);
|
||||
screen->set_cursor(_visible ? cursor : NULL);
|
||||
} else {
|
||||
if (_visible) {
|
||||
_channel.set_rect_area(_channel._cursor_rect);
|
||||
} else {
|
||||
_channel.clear_area();
|
||||
}
|
||||
if (_channel._cursor_visible) {
|
||||
display_channel->set_cursor(_channel._cursor);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_channel._cursor) {
|
||||
_channel._cursor->unref();
|
||||
}
|
||||
|
||||
_channel._cursor = cursor->ref();
|
||||
}
|
||||
|
||||
private:
|
||||
CursorChannel& _channel;
|
||||
AutoRef<CursorData> _cursor;
|
||||
int _x;
|
||||
int _y;
|
||||
bool _visible;
|
||||
};
|
||||
|
||||
class CursorMoveEvent: public Event {
|
||||
public:
|
||||
CursorMoveEvent(CursorChannel& channel, int x, int y)
|
||||
: _channel (channel)
|
||||
, _x (x)
|
||||
, _y (y)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
_channel._cursor_visible = true;
|
||||
if (static_cast<Application*>(events_loop.get_owner())->get_mouse_mode() ==
|
||||
RED_MOUSE_MODE_CLIENT) {
|
||||
RedScreen* screen = _channel.screen();
|
||||
ASSERT(screen);
|
||||
screen->set_cursor(_channel._cursor);
|
||||
} else {
|
||||
Lock lock(_channel._update_lock);
|
||||
int dx = _x - _channel._hot_pos.x;
|
||||
int dy = _y - _channel._hot_pos.y;
|
||||
_channel._hot_pos.x += dx;
|
||||
_channel._hot_pos.y += dy;
|
||||
_channel._cursor_rect.left += dx;
|
||||
_channel._cursor_rect.right += dx;
|
||||
_channel._cursor_rect.top += dy;
|
||||
_channel._cursor_rect.bottom += dy;
|
||||
lock.unlock();
|
||||
_channel.set_rect_area(_channel._cursor_rect);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
CursorChannel& _channel;
|
||||
int _x;
|
||||
int _y;
|
||||
};
|
||||
|
||||
class CursorHideEvent: public Event {
|
||||
public:
|
||||
CursorHideEvent(CursorChannel& channel): _channel (channel) {}
|
||||
virtual void response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
_channel._cursor_visible = false;
|
||||
if (static_cast<Application*>(events_loop.get_owner())->get_mouse_mode() ==
|
||||
RED_MOUSE_MODE_CLIENT) {
|
||||
RedScreen* screen = _channel.screen();
|
||||
ASSERT(screen);
|
||||
screen->set_cursor(NULL);
|
||||
} else {
|
||||
_channel.clear_area();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
CursorChannel& _channel;
|
||||
};
|
||||
|
||||
class CursorRemoveEvent: public Event {
|
||||
public:
|
||||
CursorRemoveEvent(CursorChannel& channel): _channel (channel) {}
|
||||
virtual void response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
_channel._cursor_visible = false;
|
||||
_channel.clear_area();
|
||||
if (_channel._cursor) {
|
||||
_channel._cursor->unref();
|
||||
_channel._cursor = NULL;
|
||||
}
|
||||
display_channel->hide_cursor();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -454,51 +356,12 @@ public:
|
||||
: MessageHandlerImp<CursorChannel, RED_CURSOR_MESSAGES_END>(channel) {}
|
||||
};
|
||||
|
||||
class CursorModeEvent: public Event {
|
||||
public:
|
||||
CursorModeEvent(CursorChannel& channel): _channel (channel) {}
|
||||
|
||||
virtual void response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
RedScreen* screen = _channel.screen();
|
||||
if (!screen) {
|
||||
return;
|
||||
}
|
||||
if (static_cast<Application*>(events_loop.get_owner())->get_mouse_mode() ==
|
||||
RED_MOUSE_MODE_CLIENT) {
|
||||
_channel.clear_area();
|
||||
screen->set_cursor(_channel._cursor_visible ? _channel._cursor : NULL);
|
||||
} else {
|
||||
if (_channel._cursor_visible && _channel._cursor) {
|
||||
_channel.set_rect_area(_channel._cursor_rect);
|
||||
} else {
|
||||
_channel.clear_area();
|
||||
}
|
||||
}
|
||||
screen->relase_inputs();
|
||||
}
|
||||
|
||||
private:
|
||||
CursorChannel& _channel;
|
||||
};
|
||||
|
||||
CursorModeTrigger::CursorModeTrigger(CursorChannel& channel)
|
||||
: _channel (channel)
|
||||
{
|
||||
}
|
||||
|
||||
void CursorModeTrigger::on_event()
|
||||
{
|
||||
AutoRef<CursorModeEvent> set_event(new CursorModeEvent(_channel));
|
||||
_channel.get_client().push_event(*set_event);
|
||||
}
|
||||
|
||||
CursorChannel::CursorChannel(RedClient& client, uint32_t id)
|
||||
: RedChannel(client, RED_CHANNEL_CURSOR, id, new CursorHandler(*this))
|
||||
, ScreenLayer(SCREEN_LAYER_CURSOR, false)
|
||||
, _cursor (NULL)
|
||||
, _cursor_trigger (*this)
|
||||
, _cursor_visible (false)
|
||||
, _display_channel (NULL)
|
||||
{
|
||||
CursorHandler* handler = static_cast<CursorHandler*>(get_message_handler());
|
||||
|
||||
@ -523,8 +386,6 @@ CursorChannel::CursorChannel(RedClient& client, uint32_t id)
|
||||
handler->set_handler(RED_CURSOR_INVAL_ONE, &CursorChannel::handle_inval_one,
|
||||
sizeof(RedInvalOne));
|
||||
handler->set_handler(RED_CURSOR_INVAL_ALL, &CursorChannel::handle_inval_all, 0);
|
||||
|
||||
get_process_loop().add_trigger(_cursor_trigger);
|
||||
}
|
||||
|
||||
CursorChannel::~CursorChannel()
|
||||
@ -534,6 +395,8 @@ CursorChannel::~CursorChannel()
|
||||
|
||||
void CursorChannel::on_connect()
|
||||
{
|
||||
AutoRef<AttachDispayEvent> attach_event(new AttachDispayEvent(*this));
|
||||
get_client().push_event(*attach_event);
|
||||
}
|
||||
|
||||
void CursorChannel::on_disconnect()
|
||||
@ -546,15 +409,37 @@ void CursorChannel::on_disconnect()
|
||||
detach_from_screen(get_client().get_application());
|
||||
}
|
||||
|
||||
void CursorChannel::update_display_cursor()
|
||||
{
|
||||
if (!_display_channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutoRef<CursorUpdateEvent> update_event(new CursorUpdateEvent(*this));
|
||||
get_client().push_event(*update_event);
|
||||
}
|
||||
|
||||
void CursorChannel::remove_cursor()
|
||||
{
|
||||
AutoRef<CursorRemoveEvent> event(new CursorRemoveEvent(*this));
|
||||
get_client().push_event(*event);
|
||||
Lock lock(_update_lock);
|
||||
_cursor_visible = false;
|
||||
if (_cursor) {
|
||||
_cursor->unref();
|
||||
_cursor = NULL;
|
||||
}
|
||||
lock.unlock();
|
||||
clear_area();
|
||||
update_display_cursor();
|
||||
}
|
||||
|
||||
void CursorChannel::copy_pixels(const QRegion& dest_region, RedDrawable& dest_dc)
|
||||
{
|
||||
Lock lock(_update_lock);
|
||||
|
||||
if (!_cursor_visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)dest_region.num_rects; i++) {
|
||||
ASSERT(_cursor && _cursor->get_opaque());
|
||||
((NaitivCursor*)_cursor->get_opaque())->draw(dest_dc, _cursor_rect.left, _cursor_rect.top,
|
||||
@ -562,6 +447,42 @@ void CursorChannel::copy_pixels(const QRegion& dest_region, RedDrawable& dest_dc
|
||||
}
|
||||
}
|
||||
|
||||
void CursorChannel::create_native_cursor(CursorData* cursor)
|
||||
{
|
||||
CursorOpaque* native_cursor = cursor->get_opaque();
|
||||
|
||||
if (native_cursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (cursor->header().type) {
|
||||
case CURSOR_TYPE_ALPHA:
|
||||
native_cursor = new AlphaCursor(cursor->header(), cursor->data());
|
||||
break;
|
||||
case CURSOR_TYPE_COLOR32:
|
||||
native_cursor = new ColorCursor32(cursor->header(), cursor->data());
|
||||
break;
|
||||
case CURSOR_TYPE_MONO:
|
||||
native_cursor = new MonoCursor(cursor->header(), cursor->data());
|
||||
break;
|
||||
case CURSOR_TYPE_COLOR4:
|
||||
native_cursor = new ColorCursor4(cursor->header(), cursor->data());
|
||||
break;
|
||||
case CURSOR_TYPE_COLOR8:
|
||||
native_cursor = new UnsupportedCursor(cursor->header());
|
||||
break;
|
||||
case CURSOR_TYPE_COLOR16:
|
||||
native_cursor = new ColorCursor16(cursor->header(), cursor->data());
|
||||
break;
|
||||
case CURSOR_TYPE_COLOR24:
|
||||
native_cursor = new UnsupportedCursor(cursor->header());
|
||||
break;
|
||||
default:
|
||||
THROW("invalid curosr type");
|
||||
}
|
||||
cursor->set_opaque(native_cursor);
|
||||
}
|
||||
|
||||
void CursorChannel::set_cursor(RedCursor& red_cursor, int data_size, int x, int y, bool visible)
|
||||
{
|
||||
CursorData *cursor;
|
||||
@ -582,8 +503,53 @@ void CursorChannel::set_cursor(RedCursor& red_cursor, int data_size, int x, int
|
||||
}
|
||||
|
||||
AutoRef<CursorData> cursor_ref(cursor);
|
||||
AutoRef<CursorSetEvent> set_event(new CursorSetEvent(*this, *cursor_ref, x, y, visible));
|
||||
get_client().push_event(*set_event);
|
||||
create_native_cursor(cursor);
|
||||
|
||||
Lock lock(_update_lock);
|
||||
_hot_pos.x = x;
|
||||
_hot_pos.y = y;
|
||||
_cursor_visible = visible;
|
||||
_cursor_rect.left = x - cursor->header().hot_spot_x;
|
||||
_cursor_rect.right = _cursor_rect.left + cursor->header().width;
|
||||
_cursor_rect.top = y - cursor->header().hot_spot_y;
|
||||
_cursor_rect.bottom = _cursor_rect.top + cursor->header().height;
|
||||
|
||||
if (_cursor) {
|
||||
_cursor->unref();
|
||||
}
|
||||
_cursor = cursor->ref();
|
||||
lock.unlock();
|
||||
|
||||
update_display_cursor();
|
||||
|
||||
if (get_client().get_mouse_mode() == RED_MOUSE_MODE_SERVER) {
|
||||
if (_cursor_visible) {
|
||||
set_rect_area(_cursor_rect);
|
||||
} else {
|
||||
clear_area();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CursorChannel::attach_display(DisplayChannel* channel)
|
||||
{
|
||||
if (_display_channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
_display_channel = channel;
|
||||
|
||||
Lock lock(_update_lock);
|
||||
if (!_cursor_visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
_display_channel->set_cursor(_cursor);
|
||||
}
|
||||
|
||||
void CursorChannel::detach_display()
|
||||
{
|
||||
_display_channel = NULL;
|
||||
}
|
||||
|
||||
void CursorChannel::handle_init(RedPeer::InMessage *message)
|
||||
@ -592,7 +558,6 @@ void CursorChannel::handle_init(RedPeer::InMessage *message)
|
||||
attach_to_screen(get_client().get_application(), get_id());
|
||||
remove_cursor();
|
||||
_cursor_cache.clear();
|
||||
set_cursor_mode();
|
||||
set_cursor(init->cursor, message->size() - sizeof(RedCursorInit), init->position.x,
|
||||
init->position.y, init->visible != 0);
|
||||
}
|
||||
@ -614,15 +579,41 @@ void CursorChannel::handle_cursor_set(RedPeer::InMessage* message)
|
||||
void CursorChannel::handle_cursor_move(RedPeer::InMessage* message)
|
||||
{
|
||||
RedCursorMove* move = (RedCursorMove*)message->data();
|
||||
AutoRef<CursorMoveEvent> event(new CursorMoveEvent(*this, move->postition.x,
|
||||
move->postition.y));
|
||||
get_client().push_event(*event);
|
||||
|
||||
if (!_cursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
Lock lock(_update_lock);
|
||||
_cursor_visible = true;
|
||||
int dx = move->postition.x - _hot_pos.x;
|
||||
int dy = move->postition.y - _hot_pos.y;
|
||||
_hot_pos.x += dx;
|
||||
_hot_pos.y += dy;
|
||||
_cursor_rect.left += dx;
|
||||
_cursor_rect.right += dx;
|
||||
_cursor_rect.top += dy;
|
||||
_cursor_rect.bottom += dy;
|
||||
lock.unlock();
|
||||
|
||||
if (get_client().get_mouse_mode() == RED_MOUSE_MODE_SERVER) {
|
||||
set_rect_area(_cursor_rect);
|
||||
return;
|
||||
}
|
||||
|
||||
update_display_cursor();
|
||||
}
|
||||
|
||||
void CursorChannel::handle_cursor_hide(RedPeer::InMessage* message)
|
||||
{
|
||||
AutoRef<CursorHideEvent> event(new CursorHideEvent(*this));
|
||||
get_client().push_event(*event);
|
||||
Lock lock(_update_lock);
|
||||
|
||||
_cursor_visible = false;
|
||||
update_display_cursor();
|
||||
|
||||
if (get_client().get_mouse_mode() == RED_MOUSE_MODE_SERVER) {
|
||||
clear_area();
|
||||
}
|
||||
}
|
||||
|
||||
void CursorChannel::handle_cursor_trail(RedPeer::InMessage* message)
|
||||
@ -642,9 +633,18 @@ void CursorChannel::handle_inval_all(RedPeer::InMessage* message)
|
||||
_cursor_cache.clear();
|
||||
}
|
||||
|
||||
void CursorChannel::set_cursor_mode()
|
||||
void CursorChannel::on_mouse_mode_change()
|
||||
{
|
||||
_cursor_trigger.trigger();
|
||||
Lock lock(_update_lock);
|
||||
|
||||
if (get_client().get_mouse_mode() == RED_MOUSE_MODE_CLIENT) {
|
||||
clear_area();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_cursor_visible) {
|
||||
set_rect_area(_cursor_rect);
|
||||
}
|
||||
}
|
||||
|
||||
class CursorFactory: public ChannelFactory {
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
class ChannelFactory;
|
||||
class CursorChannel;
|
||||
class DisplayChannel;
|
||||
|
||||
class CursorCacheTreat {
|
||||
public:
|
||||
@ -43,28 +44,25 @@ public:
|
||||
|
||||
typedef Cache<CursorData, CursorCacheTreat, 1024> CursorCache;
|
||||
|
||||
class CursorModeTrigger: public EventSources::Trigger {
|
||||
public:
|
||||
CursorModeTrigger(CursorChannel& channel);
|
||||
virtual void on_event();
|
||||
|
||||
private:
|
||||
CursorChannel& _channel;
|
||||
};
|
||||
|
||||
class CursorChannel: public RedChannel, public ScreenLayer {
|
||||
public:
|
||||
CursorChannel(RedClient& client, uint32_t id);
|
||||
virtual ~CursorChannel();
|
||||
|
||||
static ChannelFactory& Factory();
|
||||
void set_cursor_mode();
|
||||
void on_mouse_mode_change();
|
||||
|
||||
void attach_display(DisplayChannel* channel);
|
||||
void detach_display();
|
||||
|
||||
protected:
|
||||
virtual void on_connect();
|
||||
virtual void on_disconnect();
|
||||
|
||||
private:
|
||||
static void create_native_cursor(CursorData* cursor);
|
||||
|
||||
void update_display_cursor();
|
||||
void set_cursor(RedCursor& red_cursor, int data_size, int x, int y, bool visible);
|
||||
void remove_cursor();
|
||||
|
||||
@ -79,21 +77,17 @@ private:
|
||||
void handle_inval_one(RedPeer::InMessage* message);
|
||||
void handle_inval_all(RedPeer::InMessage* message);
|
||||
|
||||
friend class CursorSetEvent;
|
||||
friend class CursorMoveEvent;
|
||||
friend class CursorHideEvent;
|
||||
friend class CursorRemoveEvent;
|
||||
friend class CursorModeTrigger;
|
||||
friend class CursorModeEvent;
|
||||
friend class AttachDispayEvent;
|
||||
friend class CursorUpdateEvent;
|
||||
|
||||
private:
|
||||
CursorCache _cursor_cache;
|
||||
CursorData* _cursor;
|
||||
CursorModeTrigger _cursor_trigger;
|
||||
Point _hot_pos;
|
||||
Rect _cursor_rect;
|
||||
Mutex _update_lock;
|
||||
bool _cursor_visible;
|
||||
DisplayChannel* _display_channel;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -41,6 +41,8 @@
|
||||
#endif
|
||||
#include "platform_utils.h"
|
||||
#include "ffmpeg_inc.h"
|
||||
#include "inputs_channel.h"
|
||||
#include "cursor_channel.h"
|
||||
|
||||
static Mutex avcodec_mutex;
|
||||
|
||||
@ -599,7 +601,7 @@ StreamsTimer::StreamsTimer(DisplayChannel& channel)
|
||||
{
|
||||
}
|
||||
|
||||
void StreamsTimer::response(AbstractProcessLoop &events_loop)
|
||||
void StreamsTimer::response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
_channel.streams_time();
|
||||
}
|
||||
@ -609,13 +611,13 @@ void StreamsTimer::response(AbstractProcessLoop &events_loop)
|
||||
class ResetTimer: public Timer {
|
||||
public:
|
||||
ResetTimer(RedScreen* screen, RedClient& client) : _screen(screen), _client(client) {}
|
||||
virtual void response(AbstractProcessLoop &events_loop);
|
||||
virtual void response(AbstractProcessLoop& events_loop);
|
||||
private:
|
||||
RedScreen* _screen;
|
||||
RedClient& _client;
|
||||
};
|
||||
|
||||
void ResetTimer::response(AbstractProcessLoop &events_loop)
|
||||
void ResetTimer::response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
_screen->unref();
|
||||
_client.deactivate_interval_timer(this);
|
||||
@ -639,6 +641,10 @@ DisplayChannel::DisplayChannel(RedClient& client, uint32_t id,
|
||||
, _update_mark (0)
|
||||
, _streams_timer (new StreamsTimer(*this))
|
||||
, _next_timer_time (0)
|
||||
, _cursor_visibal (false)
|
||||
, _active_pointer (false)
|
||||
, _capture_mouse_mode (false)
|
||||
, _inputs_channel (NULL)
|
||||
, _active_streams (NULL)
|
||||
, _streams_trigger (*this)
|
||||
#ifdef USE_OGL
|
||||
@ -801,6 +807,130 @@ void DisplayChannel::recreate_ogl_context()
|
||||
|
||||
#endif
|
||||
|
||||
void DisplayChannel::update_cursor()
|
||||
{
|
||||
if (!screen() || !_active_pointer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_capture_mouse_mode) {
|
||||
//todo: use special cursor for capture mode
|
||||
AutoRef<LocalCursor> default_cursor(Platform::create_default_cursor());
|
||||
screen()->set_cursor(*default_cursor);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_cursor_visibal || !*_cursor) {
|
||||
screen()->hide_cursor();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!(*_cursor)->get_local()) {
|
||||
AutoRef<LocalCursor> local_cursor(Platform::create_local_cursor(*_cursor));
|
||||
if (*local_cursor == NULL) {
|
||||
THROW("create local cursor failed");
|
||||
}
|
||||
(*_cursor)->set_local(*local_cursor);
|
||||
}
|
||||
screen()->set_cursor((*_cursor)->get_local());
|
||||
}
|
||||
|
||||
void DisplayChannel::set_cursor(CursorData* cursor)
|
||||
{
|
||||
ASSERT(cursor);
|
||||
_cursor.reset(cursor->ref());
|
||||
_cursor_visibal = true;
|
||||
update_cursor();
|
||||
}
|
||||
|
||||
void DisplayChannel::hide_cursor()
|
||||
{
|
||||
_cursor_visibal = false;
|
||||
update_cursor();
|
||||
}
|
||||
|
||||
void DisplayChannel::attach_inputs(InputsChannel* inputs_channel)
|
||||
{
|
||||
if (_inputs_channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
_inputs_channel = inputs_channel;
|
||||
if (_active_pointer && !_capture_mouse_mode) {
|
||||
_inputs_channel->on_mouse_position(_pointer_pos.x, _pointer_pos.y,
|
||||
_buttons_state, get_id());
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayChannel::detach_inputs()
|
||||
{
|
||||
_inputs_channel = NULL;
|
||||
}
|
||||
|
||||
bool DisplayChannel::pointer_test(int x, int y)
|
||||
{
|
||||
return contains_point(x, y);
|
||||
}
|
||||
|
||||
void DisplayChannel::on_pointer_enter(int x, int y, unsigned int buttons_state)
|
||||
{
|
||||
_active_pointer = true;
|
||||
update_cursor();
|
||||
on_pointer_motion(x, y, buttons_state);
|
||||
}
|
||||
|
||||
void DisplayChannel::on_pointer_motion(int x, int y, unsigned int buttons_state)
|
||||
{
|
||||
_pointer_pos.x = x;
|
||||
_pointer_pos.y = y;
|
||||
_buttons_state = buttons_state;
|
||||
if (!_capture_mouse_mode && _inputs_channel) {
|
||||
_inputs_channel->on_mouse_position(x, y, buttons_state, get_id());
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayChannel::on_pointer_leave()
|
||||
{
|
||||
_active_pointer = false;
|
||||
}
|
||||
|
||||
void DisplayChannel::on_mouse_button_press(int button, int buttons_state)
|
||||
{
|
||||
_buttons_state = buttons_state;
|
||||
if (!_capture_mouse_mode && _inputs_channel) {
|
||||
_inputs_channel->on_mouse_down(button, buttons_state);
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayChannel::on_mouse_button_release(int button, int buttons_state)
|
||||
{
|
||||
_buttons_state = buttons_state;
|
||||
if (_capture_mouse_mode) {
|
||||
if (button == REDC_MOUSE_LBUTTON) {
|
||||
get_client().on_mouse_capture_trigger(*screen());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (_inputs_channel) {
|
||||
_inputs_channel->on_mouse_up(button, buttons_state);
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayChannel::set_capture_mode(bool on)
|
||||
{
|
||||
if (_capture_mouse_mode == on) {
|
||||
return;
|
||||
}
|
||||
_capture_mouse_mode = on;
|
||||
update_cursor();
|
||||
if (_inputs_channel && !_capture_mouse_mode && _active_pointer) {
|
||||
_inputs_channel->on_mouse_position(_pointer_pos.x, _pointer_pos.y, _buttons_state,
|
||||
get_id());
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayChannel::update_interrupt()
|
||||
{
|
||||
if (!_canvas.get() || !screen()) {
|
||||
@ -865,6 +995,77 @@ private:
|
||||
DisplayChannel& _channel;
|
||||
};
|
||||
|
||||
class AttachChannelsEvent : public Event {
|
||||
public:
|
||||
AttachChannelsEvent(DisplayChannel& channel) : Event(), _channel (channel) {}
|
||||
|
||||
class AttachChannels: public ForEachChannelFunc {
|
||||
public:
|
||||
AttachChannels(DisplayChannel& channel)
|
||||
: _channel (channel)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool operator() (RedChannel& channel)
|
||||
{
|
||||
if (channel.get_type() == RED_CHANNEL_CURSOR && channel.get_id() == _channel.get_id()) {
|
||||
static_cast<CursorChannel&>(channel).attach_display(&_channel);
|
||||
} else if (channel.get_type() == RED_CHANNEL_INPUTS) {
|
||||
_channel.attach_inputs(&static_cast<InputsChannel&>(channel));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
DisplayChannel& _channel;
|
||||
};
|
||||
|
||||
virtual void response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
uint32_t mouse_mode = _channel.get_client().get_mouse_mode();
|
||||
_channel._capture_mouse_mode = (mouse_mode == RED_MOUSE_MODE_SERVER);
|
||||
AttachChannels for_each_func(_channel);
|
||||
_channel.get_client().for_each_channel(for_each_func);
|
||||
}
|
||||
|
||||
private:
|
||||
DisplayChannel& _channel;
|
||||
};
|
||||
|
||||
class DetachChannelsEvent : public Event {
|
||||
public:
|
||||
DetachChannelsEvent(DisplayChannel& channel) : Event(), _channel (channel) {}
|
||||
|
||||
class DetatchChannels: public ForEachChannelFunc {
|
||||
public:
|
||||
DetatchChannels(DisplayChannel& channel)
|
||||
: _channel (channel)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool operator() (RedChannel& channel)
|
||||
{
|
||||
if (channel.get_type() == RED_CHANNEL_CURSOR && channel.get_id() == _channel.get_id()) {
|
||||
static_cast<CursorChannel&>(channel).detach_display();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
DisplayChannel& _channel;
|
||||
};
|
||||
|
||||
virtual void response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
DetatchChannels for_each_func(_channel);
|
||||
_channel.get_client().for_each_channel(for_each_func);
|
||||
}
|
||||
|
||||
private:
|
||||
DisplayChannel& _channel;
|
||||
};
|
||||
|
||||
void DisplayChannel::on_connect()
|
||||
{
|
||||
Message* message = new Message(REDC_DISPLAY_INIT, sizeof(RedcDisplayInit));
|
||||
@ -874,6 +1075,8 @@ void DisplayChannel::on_connect()
|
||||
init->glz_dictionary_id = 1;
|
||||
init->glz_dictionary_window_size = get_client().get_glz_window_size();
|
||||
post_message(message);
|
||||
AutoRef<AttachChannelsEvent> attach_channels(new AttachChannelsEvent(*this));
|
||||
get_client().push_event(*attach_channels);
|
||||
}
|
||||
|
||||
void DisplayChannel::on_disconnect()
|
||||
@ -885,6 +1088,8 @@ void DisplayChannel::on_disconnect()
|
||||
if (screen()) {
|
||||
screen()->set_update_interrupt_trigger(NULL);
|
||||
}
|
||||
AutoRef<DetachChannelsEvent> detach_channels(new DetachChannelsEvent(*this));
|
||||
get_client().push_event(*detach_channels);
|
||||
detach_from_screen(get_client().get_application());
|
||||
get_client().deactivate_interval_timer(*_streams_timer);
|
||||
AutoRef<SyncEvent> sync_event(new SyncEvent());
|
||||
@ -1030,7 +1235,6 @@ void DisplayChannel::handle_mode(RedPeer::InMessage* message)
|
||||
if (_canvas->get_pixmap_type() == CANVAS_TYPE_GL) {
|
||||
screen()->unset_type_gl();
|
||||
screen()->untouch_context();
|
||||
//glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,8 @@ class RedScreen;
|
||||
class ChannelFactory;
|
||||
class VideoStream;
|
||||
class DisplayChannel;
|
||||
class CursorData;
|
||||
class InputsChannel;
|
||||
|
||||
class StreamsTrigger: public EventSources::Trigger {
|
||||
public:
|
||||
@ -93,6 +95,19 @@ public:
|
||||
virtual void post_migrate();
|
||||
#endif
|
||||
virtual void update_interrupt();
|
||||
void set_cursor(CursorData* cursor);
|
||||
void hide_cursor();
|
||||
void set_capture_mode(bool on);
|
||||
|
||||
virtual bool pointer_test(int x, int y);
|
||||
virtual void on_pointer_enter(int x, int y, unsigned int buttons_state);
|
||||
virtual void on_pointer_motion(int x, int y, unsigned int buttons_state);
|
||||
virtual void on_pointer_leave();
|
||||
virtual void on_mouse_button_press(int button, int buttons_state);
|
||||
virtual void on_mouse_button_release(int button, int buttons_state);
|
||||
|
||||
void attach_inputs(InputsChannel* inputs_channel);
|
||||
void detach_inputs();
|
||||
|
||||
static ChannelFactory& Factory();
|
||||
|
||||
@ -115,6 +130,7 @@ private:
|
||||
void create_canvas(const std::vector<int>& canvas_type, int width, int height,
|
||||
int depth);
|
||||
void destroy_strams();
|
||||
void update_cursor();
|
||||
|
||||
void handle_mode(RedPeer::InMessage* message);
|
||||
void handle_mark(RedPeer::InMessage* message);
|
||||
@ -175,6 +191,15 @@ private:
|
||||
AutoRef<StreamsTimer> _streams_timer;
|
||||
uint32_t _next_timer_time;
|
||||
|
||||
AutoRef<CursorData> _cursor;
|
||||
bool _cursor_visibal;
|
||||
bool _active_pointer;
|
||||
bool _capture_mouse_mode;
|
||||
InputsChannel* _inputs_channel;
|
||||
|
||||
Point _pointer_pos;
|
||||
int _buttons_state;
|
||||
|
||||
std::vector<VideoStream*> _streams;
|
||||
VideoStream* _active_streams;
|
||||
StreamsTrigger _streams_trigger;
|
||||
@ -182,12 +207,15 @@ private:
|
||||
GLInterruptRecreate _gl_interrupt_recreate;
|
||||
#endif
|
||||
InterruptUpdate _interrupt_update;
|
||||
|
||||
friend class SetModeEvent;
|
||||
friend class ActivateTimerEvent;
|
||||
friend class VideoStream;
|
||||
friend class StreamsTrigger;
|
||||
friend class GLInterupt;
|
||||
friend class StreamsTimer;
|
||||
friend class AttachChannelsEvent;
|
||||
friend class DetachChannelsEvent;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include "debug.h"
|
||||
#include "red_client.h"
|
||||
#include "application.h"
|
||||
#include "display_channel.h"
|
||||
|
||||
#define SYNC_REMOTH_MODIFIRES
|
||||
|
||||
@ -28,9 +29,30 @@ class SetInputsHandlerEvent: public Event {
|
||||
public:
|
||||
SetInputsHandlerEvent(InputsChannel& channel) : _channel (channel) {}
|
||||
|
||||
class AttachFunc: public ForEachChannelFunc {
|
||||
public:
|
||||
AttachFunc(InputsChannel& channel)
|
||||
: _channel (channel)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool operator() (RedChannel& channel)
|
||||
{
|
||||
if (channel.get_type() == RED_CHANNEL_DISPLAY) {
|
||||
static_cast<DisplayChannel&>(channel).attach_inputs(&_channel);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
InputsChannel& _channel;
|
||||
};
|
||||
|
||||
virtual void response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
static_cast<Application*>(events_loop.get_owner())->set_inputs_handler(_channel);
|
||||
AttachFunc func(_channel);
|
||||
_channel.get_client().for_each_channel(func);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -56,9 +78,22 @@ class RemoveInputsHandlerEvent: public SyncEvent {
|
||||
public:
|
||||
RemoveInputsHandlerEvent(InputsChannel& channel) : _channel (channel) {}
|
||||
|
||||
class DetachFunc: public ForEachChannelFunc {
|
||||
public:
|
||||
virtual bool operator() (RedChannel& channel)
|
||||
{
|
||||
if (channel.get_type() == RED_CHANNEL_DISPLAY) {
|
||||
static_cast<DisplayChannel&>(channel).detach_inputs();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
virtual void do_response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
static_cast<Application*>(events_loop.get_owner())->remove_inputs_handler(_channel);
|
||||
DetachFunc detach_func;
|
||||
_channel.get_client().for_each_channel(detach_func);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@ -29,13 +29,14 @@ public:
|
||||
virtual ~InputsChannel();
|
||||
|
||||
virtual void on_mouse_motion(int dx, int dy, int buttons_state);
|
||||
virtual void on_mouse_position(int x, int y, int buttons_state, int display_id);
|
||||
virtual void on_mouse_down(int button, int buttons_state);
|
||||
virtual void on_mouse_up(int button, int buttons_state);
|
||||
virtual void on_key_down(uint32_t scan_code);
|
||||
virtual void on_key_up(uint32_t scan_code);
|
||||
virtual void on_focus_in();
|
||||
|
||||
void on_mouse_position(int x, int y, int buttons_state, int display_id);
|
||||
|
||||
static ChannelFactory& Factory();
|
||||
|
||||
protected:
|
||||
@ -69,6 +70,8 @@ private:
|
||||
friend class MotionMessage;
|
||||
friend class PositionMessage;
|
||||
friend class KeyModifiersEvent;
|
||||
friend class SetInputsHandlerEvent;
|
||||
friend class RemoveInputsHandlerEvent;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -23,7 +23,6 @@ class InputsHandler {
|
||||
public:
|
||||
virtual ~InputsHandler() {}
|
||||
virtual void on_mouse_motion(int dx, int dy, int buttons_state) {}
|
||||
virtual void on_mouse_position(int x, int y, int buttons_state, int display_id) {}
|
||||
virtual void on_mouse_down(int button, int buttons_state) {}
|
||||
virtual void on_mouse_up(int button, int buttons_state) {}
|
||||
virtual void on_key_down(uint32_t scan_code) {}
|
||||
|
||||
@ -23,6 +23,48 @@
|
||||
#include "utils.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
class MouseModeEvent: public Event {
|
||||
public:
|
||||
MouseModeEvent(RedClient& client)
|
||||
: _client (client)
|
||||
{
|
||||
}
|
||||
|
||||
class SetModeFunc: public ForEachChannelFunc {
|
||||
public:
|
||||
SetModeFunc(bool capture_mode)
|
||||
: _capture_mode (capture_mode)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool operator() (RedChannel& channel)
|
||||
{
|
||||
if (channel.get_type() == RED_CHANNEL_DISPLAY) {
|
||||
static_cast<DisplayChannel&>(channel).set_capture_mode(_capture_mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
bool _capture_mode;
|
||||
};
|
||||
|
||||
virtual void response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
bool capture_mode = _client.get_mouse_mode() == RED_MOUSE_MODE_SERVER;
|
||||
if (!capture_mode) {
|
||||
_client.get_application().release_mouse_capture();
|
||||
}
|
||||
|
||||
SetModeFunc func(capture_mode);
|
||||
_client.for_each_channel(func);
|
||||
}
|
||||
|
||||
private:
|
||||
RedClient& _client;
|
||||
};
|
||||
|
||||
Migrate::Migrate(RedClient& client)
|
||||
: _client (client)
|
||||
, _running (false)
|
||||
@ -344,6 +386,9 @@ void RedClient::on_disconnect()
|
||||
_agent_msg_data = NULL;
|
||||
_agent_msg_pos = 0;
|
||||
_agent_tokens = 0;
|
||||
AutoRef<SyncEvent> sync_event(new SyncEvent());
|
||||
get_client().push_event(*sync_event);
|
||||
(*sync_event)->wait();
|
||||
}
|
||||
|
||||
void RedClient::delete_channels()
|
||||
@ -357,6 +402,19 @@ void RedClient::delete_channels()
|
||||
}
|
||||
}
|
||||
|
||||
void RedClient::for_each_channel(ForEachChannelFunc& func)
|
||||
{
|
||||
Lock lock(_channels_lock);
|
||||
Channels::iterator iter = _channels.begin();
|
||||
for (; iter != _channels.end() && func(**iter) ;iter++);
|
||||
}
|
||||
|
||||
|
||||
void RedClient::on_mouse_capture_trigger(RedScreen& screen)
|
||||
{
|
||||
_application.capture_mouse();
|
||||
}
|
||||
|
||||
RedPeer::ConnectionOptions::Type RedClient::get_connection_options(uint32_t channel_type)
|
||||
{
|
||||
return _con_opt_map[channel_type];
|
||||
@ -611,9 +669,11 @@ void RedClient::set_mouse_mode(uint32_t supported_modes, uint32_t current_mode)
|
||||
Channels::iterator iter = _channels.begin();
|
||||
for (; iter != _channels.end(); ++iter) {
|
||||
if ((*iter)->get_type() == RED_CHANNEL_CURSOR) {
|
||||
((CursorChannel *)(*iter))->set_cursor_mode();
|
||||
((CursorChannel *)(*iter))->on_mouse_mode_change();
|
||||
}
|
||||
}
|
||||
AutoRef<MouseModeEvent> event(new MouseModeEvent(*this));
|
||||
push_event(*event);
|
||||
}
|
||||
// FIXME: use configured mouse mode (currently, use client mouse mode if supported by server)
|
||||
if ((supported_modes & RED_MOUSE_MODE_CLIENT) && (current_mode != RED_MOUSE_MODE_CLIENT)) {
|
||||
|
||||
@ -118,6 +118,11 @@ class AgentTimer: public Timer {
|
||||
|
||||
typedef std::map< int, RedPeer::ConnectionOptions::Type> PeerConnectionOptMap;
|
||||
|
||||
class ForEachChannelFunc {
|
||||
public:
|
||||
virtual bool operator() (RedChannel& channel) = 0;
|
||||
};
|
||||
|
||||
class RedClient: public RedChannel {
|
||||
public:
|
||||
friend class RedChannel;
|
||||
@ -153,6 +158,8 @@ public:
|
||||
PixmapCache& get_pixmap_cache() {return _pixmap_cache;}
|
||||
uint64_t get_pixmap_cache_size() { return _pixmap_cache_size;}
|
||||
void on_display_mode_change();
|
||||
void for_each_channel(ForEachChannelFunc& func);
|
||||
void on_mouse_capture_trigger(RedScreen& screen);
|
||||
|
||||
GlzDecoderWindow& get_glz_window() {return _glz_window;}
|
||||
int get_glz_window_size() { return _glz_window_size;}
|
||||
|
||||
@ -92,7 +92,7 @@ public:
|
||||
private:
|
||||
void on_focus_in();
|
||||
void on_focus_out();
|
||||
void on_pointer_enter();
|
||||
void on_pointer_enter(int x, int y, unsigned int buttons_state);
|
||||
void on_pointer_leave();
|
||||
|
||||
void do_start_key_interception();
|
||||
@ -117,15 +117,19 @@ class RedWindow::Listener {
|
||||
public:
|
||||
virtual ~Listener() {}
|
||||
virtual void on_exposed_rect(const Rect& area) = 0;
|
||||
virtual void on_mouse_motion(int x, int y, unsigned int buttons_state) = 0;
|
||||
|
||||
virtual void on_pointer_enter(int x, int y, unsigned int buttons_state) = 0;
|
||||
virtual void on_pointer_motion(int x, int y, unsigned int buttons_state) = 0;
|
||||
virtual void on_pointer_leave() = 0;
|
||||
virtual void on_mouse_button_press(RedButton button, unsigned int buttons_state) = 0;
|
||||
virtual void on_mouse_button_release(RedButton button, unsigned int buttons_state) = 0;
|
||||
|
||||
virtual void on_key_press(RedKey key) = 0;
|
||||
virtual void on_key_release(RedKey key) = 0;
|
||||
virtual void on_button_press(RedButton button, unsigned int buttons_state) = 0;
|
||||
virtual void on_button_release(RedButton button, unsigned int buttons_state) = 0;
|
||||
|
||||
virtual void on_deactivate() = 0;
|
||||
virtual void on_activate() = 0;
|
||||
virtual void on_pointer_enter() = 0;
|
||||
virtual void on_pointer_leave() = 0;
|
||||
|
||||
virtual void on_start_key_interception() = 0;
|
||||
virtual void on_stop_key_interception() = 0;
|
||||
virtual void enter_modal_loop() = 0;
|
||||
|
||||
@ -43,6 +43,29 @@ private:
|
||||
int _screen;
|
||||
};
|
||||
|
||||
class LayerChangedEvent: public Event {
|
||||
public:
|
||||
LayerChangedEvent (int screen) : _screen (screen) {}
|
||||
|
||||
virtual void response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
Application* app = static_cast<Application*>(events_loop.get_owner());
|
||||
RedScreen* screen = app->find_screen(_screen);
|
||||
if (screen) {
|
||||
Lock lock(screen->_layer_changed_lock);
|
||||
screen->_active_layer_change_event = false;
|
||||
lock.unlock();
|
||||
if (screen->_pointer_on_screen) {
|
||||
screen->update_pointer_layer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int _screen;
|
||||
};
|
||||
|
||||
|
||||
void UpdateTimer::response(AbstractProcessLoop& events_loop)
|
||||
{
|
||||
_screen->periodic_update();
|
||||
@ -54,11 +77,9 @@ RedScreen::RedScreen(Application& owner, int id, const std::wstring& name, int w
|
||||
, _refs (1)
|
||||
, _window (*this)
|
||||
, _active (false)
|
||||
, _captured (false)
|
||||
, _full_screen (false)
|
||||
, _out_of_sync (false)
|
||||
, _frame_area (false)
|
||||
, _cursor_visible (true)
|
||||
, _periodic_update (false)
|
||||
, _key_interception (false)
|
||||
, _update_by_timer (true)
|
||||
@ -68,11 +89,13 @@ RedScreen::RedScreen(Application& owner, int id, const std::wstring& name, int w
|
||||
, _update_mark (1)
|
||||
, _monitor (NULL)
|
||||
, _default_cursor (NULL)
|
||||
, _active_cursor (NULL)
|
||||
, _inactive_cursor (NULL)
|
||||
, _pointer_location (POINTER_OUTSIDE_WINDOW)
|
||||
, _pixel_format_index (0)
|
||||
, _update_interrupt_trigger (NULL)
|
||||
, _pointer_layer (NULL)
|
||||
, _mouse_captured (false)
|
||||
, _active_layer_change_event (false)
|
||||
, _pointer_on_screen (false)
|
||||
{
|
||||
region_init(&_dirty_region);
|
||||
set_name(name);
|
||||
@ -98,9 +121,9 @@ RedScreen::RedScreen(Application& owner, int id, const std::wstring& name, int w
|
||||
|
||||
RedScreen::~RedScreen()
|
||||
{
|
||||
bool captured = is_captured();
|
||||
bool captured = is_mouse_captured();
|
||||
_window.stop_key_interception();
|
||||
relase_inputs();
|
||||
relase_mouse();
|
||||
destroy_composit_area();
|
||||
_owner.deactivate_interval_timer(*_update_timer);
|
||||
_owner.on_screen_destroyed(_id, captured);
|
||||
@ -108,9 +131,7 @@ RedScreen::~RedScreen()
|
||||
if (_default_cursor) {
|
||||
_default_cursor->unref();
|
||||
}
|
||||
if (_active_cursor) {
|
||||
_active_cursor->unref();
|
||||
}
|
||||
|
||||
if (_inactive_cursor) {
|
||||
_inactive_cursor->unref();
|
||||
}
|
||||
@ -168,7 +189,7 @@ void RedScreen::set_mode(int width, int height, int depth)
|
||||
bool cuptur = _owner.rearrange_monitors(*this);
|
||||
__show_full_screen();
|
||||
if (cuptur) {
|
||||
capture_inputs();
|
||||
capture_mouse();
|
||||
}
|
||||
} else {
|
||||
_window.resize(_size.x, _size.y);
|
||||
@ -184,6 +205,17 @@ void RedScreen::set_name(const std::wstring& name)
|
||||
_window.set_title(_name);
|
||||
}
|
||||
|
||||
void RedScreen::on_layer_changed(ScreenLayer& layer)
|
||||
{
|
||||
Lock lock(_layer_changed_lock);
|
||||
if (_active_layer_change_event) {
|
||||
return;
|
||||
}
|
||||
_active_layer_change_event = true;
|
||||
AutoRef<LayerChangedEvent> change_event(new LayerChangedEvent(_id));
|
||||
_owner.push_event(*change_event);
|
||||
}
|
||||
|
||||
void RedScreen::attach_layer(ScreenLayer& layer)
|
||||
{
|
||||
RecurciveLock lock(_update_lock);
|
||||
@ -200,11 +232,22 @@ void RedScreen::attach_layer(ScreenLayer& layer)
|
||||
ref();
|
||||
lock.unlock();
|
||||
layer.invalidate();
|
||||
if (_pointer_on_screen) {
|
||||
update_pointer_layer();
|
||||
}
|
||||
}
|
||||
|
||||
void RedScreen::detach_layer(ScreenLayer& layer)
|
||||
{
|
||||
bool need_pointer_layer_update = false;
|
||||
if (_pointer_layer == &layer) {
|
||||
_pointer_layer->on_pointer_leave();
|
||||
_pointer_layer = NULL;
|
||||
need_pointer_layer_update = true;
|
||||
}
|
||||
|
||||
RecurciveLock lock(_update_lock);
|
||||
|
||||
int order = layer.z_order();
|
||||
|
||||
if ((int)_layes.size() < order + 1 || _layes[order] != &layer) {
|
||||
@ -218,6 +261,9 @@ void RedScreen::detach_layer(ScreenLayer& layer)
|
||||
invalidate(layer_area);
|
||||
region_destroy(&layer_area);
|
||||
unref();
|
||||
if (need_pointer_layer_update && !update_pointer_layer()) {
|
||||
_window.set_cursor(_inactive_cursor);
|
||||
}
|
||||
}
|
||||
|
||||
void RedScreen::composit_to_screen(RedDrawable& win_dc, const QRegion& region)
|
||||
@ -427,121 +473,180 @@ void RedScreen::reset_mouse_pos()
|
||||
_window.set_mouse_position(_mouse_anchor_point.x, _mouse_anchor_point.y);
|
||||
}
|
||||
|
||||
void RedScreen::capture_inputs()
|
||||
void RedScreen::capture_mouse()
|
||||
{
|
||||
if (_captured || !_window.get_mouse_anchor_point(_mouse_anchor_point)) {
|
||||
if (_mouse_captured || !_window.get_mouse_anchor_point(_mouse_anchor_point)) {
|
||||
return;
|
||||
}
|
||||
if (_owner.get_mouse_mode() == RED_MOUSE_MODE_SERVER) {
|
||||
_window.hide_cursor();
|
||||
reset_mouse_pos();
|
||||
_window.cupture_mouse();
|
||||
|
||||
if (_pointer_layer) {
|
||||
_pointer_layer->on_pointer_leave();
|
||||
_pointer_layer = NULL;
|
||||
}
|
||||
_captured = true;
|
||||
_pointer_on_screen = false;
|
||||
_mouse_captured = true;
|
||||
_window.hide_cursor();
|
||||
reset_mouse_pos();
|
||||
_window.cupture_mouse();
|
||||
}
|
||||
|
||||
void RedScreen::relase_inputs()
|
||||
void RedScreen::relase_mouse()
|
||||
{
|
||||
if (!_captured) {
|
||||
if (!_mouse_captured) {
|
||||
return;
|
||||
}
|
||||
_captured = false;
|
||||
_mouse_captured = false;
|
||||
_window.release_mouse();
|
||||
if (_owner.get_mouse_mode() == RED_MOUSE_MODE_SERVER) {
|
||||
_window.set_cursor(_default_cursor);
|
||||
}
|
||||
update_pointer_layer();
|
||||
}
|
||||
|
||||
void RedScreen::set_cursor(CursorData* cursor)
|
||||
void RedScreen::set_cursor(LocalCursor* cursor)
|
||||
{
|
||||
if (cursor) {
|
||||
if (_active_cursor) {
|
||||
_active_cursor->unref();
|
||||
}
|
||||
if (!cursor->get_local()) {
|
||||
AutoRef<LocalCursor> cur(Platform::create_local_cursor(cursor));
|
||||
if (*cur == NULL) {
|
||||
THROW("create local cursor failed");
|
||||
}
|
||||
cursor->set_local(*cur);
|
||||
_active_cursor = (*cur)->ref();
|
||||
} else {
|
||||
_active_cursor = (cursor->get_local())->ref();
|
||||
}
|
||||
if (_mouse_captured) {
|
||||
return;
|
||||
}
|
||||
_cursor_visible = !!cursor;
|
||||
update_active_cursor();
|
||||
|
||||
_window.set_cursor(cursor);
|
||||
}
|
||||
|
||||
void RedScreen::update_active_cursor()
|
||||
void RedScreen::hide_cursor()
|
||||
{
|
||||
if (_owner.get_mouse_mode() == RED_MOUSE_MODE_CLIENT &&
|
||||
_pointer_location == POINTER_IN_ACTIVE_AREA) {
|
||||
if (_cursor_visible && _active_cursor) {
|
||||
_window.set_cursor(_active_cursor);
|
||||
} else {
|
||||
_window.hide_cursor();
|
||||
_window.hide_cursor();
|
||||
}
|
||||
|
||||
ScreenLayer* RedScreen::find_pointer_layer()
|
||||
{
|
||||
for (int i = _layes.size() - 1; i >= 0; i--) {
|
||||
ScreenLayer* layer;
|
||||
|
||||
if (!(layer = _layes[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (layer->pointer_test(_pointer_pos.x, _pointer_pos.y)) {
|
||||
return layer;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool RedScreen::update_pointer_layer()
|
||||
{
|
||||
ASSERT(!_mouse_captured);
|
||||
|
||||
ScreenLayer* now = find_pointer_layer();
|
||||
|
||||
if (now == _pointer_layer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_pointer_layer) {
|
||||
_pointer_layer->on_pointer_leave();
|
||||
}
|
||||
|
||||
_pointer_layer = find_pointer_layer();
|
||||
|
||||
if (_pointer_layer) {
|
||||
_pointer_layer->on_pointer_enter(_pointer_pos.x, _pointer_pos.y, _mouse_botton_state);
|
||||
} else {
|
||||
set_cursor(_inactive_cursor);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RedScreen::on_pointer_enter(int x, int y, unsigned int buttons_state)
|
||||
{
|
||||
if (_mouse_captured) {
|
||||
return;
|
||||
}
|
||||
|
||||
_pointer_on_screen = true;
|
||||
_pointer_pos.x = x;
|
||||
_pointer_pos.y = y;
|
||||
_mouse_botton_state = buttons_state;
|
||||
|
||||
ScreenLayer* layer = find_pointer_layer();
|
||||
if (!layer) {
|
||||
set_cursor(_inactive_cursor);
|
||||
return;
|
||||
}
|
||||
|
||||
_pointer_layer = layer;
|
||||
_pointer_layer->on_pointer_enter(_pointer_pos.x, _pointer_pos.y, buttons_state);
|
||||
|
||||
if (_full_screen) {
|
||||
/* allowing enterance to key interception mode without
|
||||
requiring the user to press the window
|
||||
*/
|
||||
activate();
|
||||
}
|
||||
}
|
||||
|
||||
void RedScreen::on_mouse_motion(int x, int y, unsigned int buttons_state)
|
||||
{
|
||||
switch (_owner.get_mouse_mode()) {
|
||||
case RED_MOUSE_MODE_CLIENT:
|
||||
if (!_frame_area) {
|
||||
_owner.on_mouse_position(x, y, buttons_state, _id);
|
||||
} else if (x >= 0 && x < _size.x && y >= 0 && y < _size.y) {
|
||||
_owner.on_mouse_position(x, y, buttons_state, _id);
|
||||
if (_pointer_location != POINTER_IN_ACTIVE_AREA) {
|
||||
_pointer_location = POINTER_IN_ACTIVE_AREA;
|
||||
update_active_cursor();
|
||||
}
|
||||
} else if (_pointer_location != POINTER_IN_FRAME_AREA) {
|
||||
_pointer_location = POINTER_IN_FRAME_AREA;
|
||||
_window.set_cursor(_inactive_cursor);
|
||||
}
|
||||
break;
|
||||
case RED_MOUSE_MODE_SERVER:
|
||||
if (_captured && (x != _mouse_anchor_point.x || y != _mouse_anchor_point.y)) {
|
||||
_owner.on_mouse_motion(x - _mouse_anchor_point.x,
|
||||
y - _mouse_anchor_point.y,
|
||||
buttons_state);
|
||||
reset_mouse_pos();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
THROW("invalid mouse mode");
|
||||
if (x != _mouse_anchor_point.x || y != _mouse_anchor_point.y) {
|
||||
_owner.on_mouse_motion(x - _mouse_anchor_point.x,
|
||||
y - _mouse_anchor_point.y,
|
||||
buttons_state);
|
||||
reset_mouse_pos();
|
||||
}
|
||||
}
|
||||
|
||||
void RedScreen::on_button_press(RedButton button, unsigned int buttons_state)
|
||||
void RedScreen::on_pointer_motion(int x, int y, unsigned int buttons_state)
|
||||
{
|
||||
if (_owner.get_mouse_mode() == RED_MOUSE_MODE_CLIENT &&
|
||||
_pointer_location != POINTER_IN_ACTIVE_AREA) {
|
||||
if (_mouse_captured) {
|
||||
on_mouse_motion(x, y, buttons_state);
|
||||
return;
|
||||
}
|
||||
if (!mouse_is_captured()) {
|
||||
if (_owner.get_mouse_mode() == RED_MOUSE_MODE_SERVER && button != REDC_MOUSE_LBUTTON) {
|
||||
return;
|
||||
}
|
||||
capture_inputs();
|
||||
if (_owner.get_mouse_mode() == RED_MOUSE_MODE_SERVER) {
|
||||
return;
|
||||
}
|
||||
|
||||
_pointer_pos.x = x;
|
||||
_pointer_pos.y = y;
|
||||
_mouse_botton_state = buttons_state;
|
||||
|
||||
if (update_pointer_layer() || !_pointer_layer) {
|
||||
return;
|
||||
}
|
||||
_owner.on_mouse_down(button, buttons_state);
|
||||
|
||||
_pointer_layer->on_pointer_motion(x, y, buttons_state);
|
||||
}
|
||||
|
||||
void RedScreen::on_button_release(RedButton button, unsigned int buttons_state)
|
||||
void RedScreen::on_mouse_button_press(RedButton button, unsigned int buttons_state)
|
||||
{
|
||||
if (!mouse_is_captured()) {
|
||||
if (_owner.get_mouse_mode() == RED_MOUSE_MODE_SERVER) {
|
||||
return;
|
||||
}
|
||||
capture_inputs();
|
||||
if (_mouse_captured) {
|
||||
_owner.on_mouse_down(button, buttons_state);
|
||||
return;
|
||||
}
|
||||
_owner.on_mouse_up(button, buttons_state);
|
||||
|
||||
if (!_pointer_layer) {
|
||||
return;
|
||||
}
|
||||
|
||||
_pointer_layer->on_mouse_button_press(button, buttons_state);
|
||||
}
|
||||
|
||||
void RedScreen::on_mouse_button_release(RedButton button, unsigned int buttons_state)
|
||||
{
|
||||
if (_mouse_captured) {
|
||||
_owner.on_mouse_up(button, buttons_state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_pointer_layer) {
|
||||
return;
|
||||
}
|
||||
_pointer_layer->on_mouse_button_release(button, buttons_state);
|
||||
}
|
||||
|
||||
void RedScreen::on_pointer_leave()
|
||||
{
|
||||
ASSERT(!_mouse_captured);
|
||||
|
||||
if (_pointer_layer) {
|
||||
_pointer_layer->on_pointer_leave();
|
||||
_pointer_layer = NULL;
|
||||
}
|
||||
_pointer_on_screen = false;
|
||||
}
|
||||
|
||||
void RedScreen::on_key_press(RedKey key)
|
||||
@ -556,7 +661,7 @@ void RedScreen::on_key_release(RedKey key)
|
||||
|
||||
void RedScreen::on_deactivate()
|
||||
{
|
||||
relase_inputs();
|
||||
relase_mouse();
|
||||
_active = false;
|
||||
_owner.on_deactivate_screen(this);
|
||||
}
|
||||
@ -567,23 +672,6 @@ void RedScreen::on_activate()
|
||||
_owner.on_activate_screen(this);
|
||||
}
|
||||
|
||||
void RedScreen::on_pointer_enter()
|
||||
{
|
||||
if (!_frame_area) {
|
||||
_pointer_location = POINTER_IN_ACTIVE_AREA;
|
||||
update_active_cursor();
|
||||
if (_full_screen) {
|
||||
/* allowing enterance to key interception mode without
|
||||
requiring the user to press the window */
|
||||
activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RedScreen::on_pointer_leave()
|
||||
{
|
||||
_pointer_location = POINTER_OUTSIDE_WINDOW;
|
||||
}
|
||||
|
||||
void RedScreen::on_start_key_interception()
|
||||
{
|
||||
|
||||
@ -57,20 +57,22 @@ public:
|
||||
|
||||
void attach_layer(ScreenLayer& layer);
|
||||
void detach_layer(ScreenLayer& layer);
|
||||
void on_layer_changed(ScreenLayer& layer);
|
||||
void set_mode(int width, int height, int depth);
|
||||
void set_name(const std::wstring& name);
|
||||
uint64_t invalidate(const Rect& rect, bool urgent);
|
||||
void invalidate(const QRegion ®ion);
|
||||
void relase_inputs();
|
||||
void capture_inputs();
|
||||
bool is_captured() { return _captured;}
|
||||
void capture_mouse();
|
||||
void relase_mouse();
|
||||
bool is_mouse_captured() { return _mouse_captured;}
|
||||
bool intercepts_sys_key() { return _key_interception;}
|
||||
Point get_size() { return _size;}
|
||||
bool has_monitor() { return _monitor != 0;}
|
||||
void set_monitor(Monitor *monitor) { _monitor = monitor;}
|
||||
Monitor* get_monitor() { return _monitor;}
|
||||
RedWindow* get_window() { return &_window;}
|
||||
void set_cursor(CursorData* cursor);
|
||||
void set_cursor(LocalCursor* cursor);
|
||||
void hide_cursor();
|
||||
void exit_full_screen();
|
||||
void minimize();
|
||||
void show(bool activate, RedScreen* pos);
|
||||
@ -123,19 +125,23 @@ private:
|
||||
void composit_to_screen(RedDrawable& win_dc, const QRegion& region);
|
||||
|
||||
void reset_mouse_pos();
|
||||
bool mouse_is_captured() { return _captured;}
|
||||
void update_active_cursor();
|
||||
ScreenLayer* find_pointer_layer();
|
||||
bool update_pointer_layer();
|
||||
|
||||
virtual void on_exposed_rect(const Rect& area);
|
||||
virtual void on_mouse_motion(int x, int y, unsigned int buttons_state);
|
||||
virtual void on_pointer_enter(int x, int y, unsigned int buttons_state);
|
||||
virtual void on_pointer_motion(int x, int y, unsigned int buttons_state);
|
||||
virtual void on_pointer_leave();
|
||||
void on_mouse_motion(int x, int y, unsigned int buttons_state);
|
||||
virtual void on_mouse_button_press(RedButton button, unsigned int buttons_state);
|
||||
virtual void on_mouse_button_release(RedButton button, unsigned int buttons_state);
|
||||
|
||||
virtual void on_key_press(RedKey key);
|
||||
virtual void on_key_release(RedKey key);
|
||||
virtual void on_button_press(RedButton button, unsigned int buttons_state);
|
||||
virtual void on_button_release(RedButton button, unsigned int buttons_state);
|
||||
|
||||
virtual void on_deactivate();
|
||||
virtual void on_activate();
|
||||
virtual void on_pointer_enter();
|
||||
virtual void on_pointer_leave();
|
||||
|
||||
virtual void on_start_key_interception();
|
||||
virtual void on_stop_key_interception();
|
||||
virtual void enter_modal_loop();
|
||||
@ -154,11 +160,9 @@ private:
|
||||
QRegion _dirty_region;
|
||||
RecurciveMutex _update_lock;
|
||||
bool _active;
|
||||
bool _captured;
|
||||
bool _full_screen;
|
||||
bool _out_of_sync;
|
||||
bool _frame_area;
|
||||
bool _cursor_visible;
|
||||
bool _periodic_update;
|
||||
bool _key_interception;
|
||||
bool _update_by_timer;
|
||||
@ -174,17 +178,20 @@ private:
|
||||
Monitor* _monitor;
|
||||
|
||||
LocalCursor* _default_cursor;
|
||||
LocalCursor* _active_cursor;
|
||||
LocalCursor* _inactive_cursor;
|
||||
|
||||
enum PointerLocation {
|
||||
POINTER_IN_ACTIVE_AREA,
|
||||
POINTER_IN_FRAME_AREA,
|
||||
POINTER_OUTSIDE_WINDOW,
|
||||
};
|
||||
PointerLocation _pointer_location;
|
||||
int _pixel_format_index;
|
||||
EventSources::Trigger *_update_interrupt_trigger;
|
||||
|
||||
ScreenLayer* _pointer_layer;
|
||||
bool _mouse_captured;
|
||||
Mutex _layer_changed_lock;
|
||||
bool _active_layer_change_event;
|
||||
bool _pointer_on_screen;
|
||||
Point _pointer_pos;
|
||||
unsigned int _mouse_botton_state;
|
||||
|
||||
friend class LayerChangedEvent;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -108,6 +108,13 @@ void ScreenLayer::invalidate()
|
||||
invalidate(_area);
|
||||
}
|
||||
|
||||
void ScreenLayer::notify_changed()
|
||||
{
|
||||
if (_screen) {
|
||||
_screen->on_layer_changed(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenLayer::set_area(const QRegion& area)
|
||||
{
|
||||
Lock lock(_area_lock);
|
||||
@ -115,6 +122,7 @@ void ScreenLayer::set_area(const QRegion& area)
|
||||
region_destroy(&_area);
|
||||
region_clone(&_area, &area);
|
||||
invalidate();
|
||||
notify_changed();
|
||||
}
|
||||
|
||||
void ScreenLayer::clear_area()
|
||||
@ -122,6 +130,7 @@ void ScreenLayer::clear_area()
|
||||
Lock lock(_area_lock);
|
||||
invalidate();
|
||||
region_clear(&_area);
|
||||
notify_changed();
|
||||
}
|
||||
|
||||
void ScreenLayer::set_rect_area(const Rect& r)
|
||||
@ -131,6 +140,7 @@ void ScreenLayer::set_rect_area(const Rect& r)
|
||||
region_clear(&_area);
|
||||
region_add(&_area, &r);
|
||||
invalidate();
|
||||
notify_changed();
|
||||
}
|
||||
|
||||
void ScreenLayer::offset_area(int dx, int dy)
|
||||
@ -139,12 +149,14 @@ void ScreenLayer::offset_area(int dx, int dy)
|
||||
invalidate();
|
||||
region_offset(&_area, dx, dy);
|
||||
invalidate();
|
||||
notify_changed();
|
||||
}
|
||||
|
||||
void ScreenLayer::add_rect_area(const Rect& r)
|
||||
{
|
||||
Lock lock(_area_lock);
|
||||
region_add(&_area, &r);
|
||||
notify_changed();
|
||||
}
|
||||
|
||||
void ScreenLayer::remove_rect_area(const Rect& r)
|
||||
@ -152,6 +164,7 @@ void ScreenLayer::remove_rect_area(const Rect& r)
|
||||
Lock lock(_area_lock);
|
||||
invalidate();
|
||||
region_remove(&_area, &r);
|
||||
notify_changed();
|
||||
}
|
||||
|
||||
void ScreenLayer::begin_update(QRegion& direct_rgn, QRegion& composit_rgn)
|
||||
@ -175,6 +188,12 @@ void ScreenLayer::begin_update(QRegion& direct_rgn, QRegion& composit_rgn)
|
||||
}
|
||||
}
|
||||
|
||||
bool ScreenLayer::contains_point(int x, int y)
|
||||
{
|
||||
Lock lock(_area_lock);
|
||||
return !!region_contains_point(&_area, x, y);
|
||||
}
|
||||
|
||||
void ScreenLayer::attach_to_screen(Application& applicaion, int screen_id)
|
||||
{
|
||||
if (_screen) {
|
||||
|
||||
@ -45,6 +45,7 @@ public:
|
||||
void invalidate();
|
||||
uint64_t invalidate(const Rect& r, bool urgent = false);
|
||||
void invalidate(const QRegion& r);
|
||||
bool contains_point(int x, int y);
|
||||
|
||||
virtual void copy_pixels(const QRegion& dest_region, RedDrawable& dest_dc) {}
|
||||
|
||||
@ -61,8 +62,16 @@ public:
|
||||
|
||||
virtual void on_update_completion(uint64_t mark) {}
|
||||
|
||||
virtual bool pointer_test(int x, int y) { return false;}
|
||||
virtual void on_pointer_enter(int x, int y, unsigned int buttons_state) {}
|
||||
virtual void on_pointer_motion(int x, int y, unsigned int buttons_state) {}
|
||||
virtual void on_pointer_leave() {}
|
||||
virtual void on_mouse_button_press(int button, int buttons_state) {}
|
||||
virtual void on_mouse_button_release(int button, int buttons_state) {}
|
||||
|
||||
private:
|
||||
uint64_t invalidate_rect(const Rect& r, bool urgent);
|
||||
void notify_changed();
|
||||
|
||||
private:
|
||||
RedScreen* _screen;
|
||||
|
||||
@ -116,12 +116,15 @@ LRESULT CALLBACK RedWindow_p::WindowProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
break;
|
||||
}
|
||||
case WM_MOUSEMOVE: {
|
||||
if (!window->_pointer_in_window) {
|
||||
window->on_pointer_enter();
|
||||
}
|
||||
Point origin = window->get_origin();
|
||||
window->get_listener().on_mouse_motion(LOWORD(lParam) - origin.x, HIWORD(lParam) - origin.y,
|
||||
to_red_mouse_state(wParam));
|
||||
int x = LOWORD(lParam) - origin.x;
|
||||
int y = HIWORD(lParam) - origin.y;
|
||||
unsigned int buttons_state = to_red_mouse_state(wParam);
|
||||
if (!window->_pointer_in_window) {
|
||||
window->on_pointer_enter(x, y, buttons_state);
|
||||
} else {
|
||||
window->get_listener().on_pointer_motion(x, y, buttons_state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_MOUSELEAVE:
|
||||
@ -134,34 +137,40 @@ LRESULT CALLBACK RedWindow_p::WindowProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
window->on_focus_out();
|
||||
break;
|
||||
case WM_LBUTTONDOWN:
|
||||
window->get_listener().on_button_press(REDC_MOUSE_LBUTTON, to_red_mouse_state(wParam));
|
||||
window->get_listener().on_mouse_button_press(REDC_MOUSE_LBUTTON,
|
||||
to_red_mouse_state(wParam));
|
||||
break;
|
||||
case WM_LBUTTONUP:
|
||||
window->get_listener().on_button_release(REDC_MOUSE_LBUTTON, to_red_mouse_state(wParam));
|
||||
window->get_listener().on_mouse_button_release(REDC_MOUSE_LBUTTON,
|
||||
to_red_mouse_state(wParam));
|
||||
break;
|
||||
case WM_RBUTTONDOWN:
|
||||
window->get_listener().on_button_press(REDC_MOUSE_RBUTTON, to_red_mouse_state(wParam));
|
||||
window->get_listener().on_mouse_button_press(REDC_MOUSE_RBUTTON,
|
||||
to_red_mouse_state(wParam));
|
||||
break;
|
||||
case WM_RBUTTONUP:
|
||||
window->get_listener().on_button_release(REDC_MOUSE_RBUTTON, to_red_mouse_state(wParam));
|
||||
window->get_listener().on_mouse_button_release(REDC_MOUSE_RBUTTON,
|
||||
to_red_mouse_state(wParam));
|
||||
break;
|
||||
case WM_MBUTTONDOWN:
|
||||
window->get_listener().on_button_press(REDC_MOUSE_MBUTTON, to_red_mouse_state(wParam));
|
||||
window->get_listener().on_mouse_button_press(REDC_MOUSE_MBUTTON,
|
||||
to_red_mouse_state(wParam));
|
||||
break;
|
||||
case WM_MBUTTONUP:
|
||||
window->get_listener().on_button_release(REDC_MOUSE_MBUTTON, to_red_mouse_state(wParam));
|
||||
window->get_listener().on_mouse_button_release(REDC_MOUSE_MBUTTON,
|
||||
to_red_mouse_state(wParam));
|
||||
break;
|
||||
case WM_MOUSEWHEEL:
|
||||
if (HIWORD(wParam) & 0x8000) {
|
||||
window->get_listener().on_button_press(REDC_MOUSE_DBUTTON,
|
||||
to_red_mouse_state(wParam));
|
||||
window->get_listener().on_button_release(REDC_MOUSE_DBUTTON,
|
||||
to_red_mouse_state(wParam));
|
||||
window->get_listener().on_mouse_button_press(REDC_MOUSE_DBUTTON,
|
||||
to_red_mouse_state(wParam));
|
||||
window->get_listener().on_mouse_button_release(REDC_MOUSE_DBUTTON,
|
||||
to_red_mouse_state(wParam));
|
||||
} else {
|
||||
window->get_listener().on_button_press(REDC_MOUSE_UBUTTON,
|
||||
to_red_mouse_state(wParam));
|
||||
window->get_listener().on_button_release(REDC_MOUSE_UBUTTON,
|
||||
to_red_mouse_state(wParam));
|
||||
window->get_listener().on_mouse_button_press(REDC_MOUSE_UBUTTON,
|
||||
to_red_mouse_state(wParam));
|
||||
window->get_listener().on_mouse_button_release(REDC_MOUSE_UBUTTON,
|
||||
to_red_mouse_state(wParam));
|
||||
}
|
||||
break;
|
||||
case WM_SYSKEYDOWN:
|
||||
@ -795,7 +804,7 @@ void RedWindow::on_focus_out()
|
||||
get_listener().on_deactivate();
|
||||
}
|
||||
|
||||
void RedWindow::on_pointer_enter()
|
||||
void RedWindow::on_pointer_enter(int x, int y, unsigned int buttons_state)
|
||||
{
|
||||
if (_pointer_in_window) {
|
||||
return;
|
||||
@ -810,7 +819,7 @@ void RedWindow::on_pointer_enter()
|
||||
while (ShowCursor(FALSE) > -1);
|
||||
}
|
||||
_pointer_in_window = true;
|
||||
_listener.on_pointer_enter();
|
||||
_listener.on_pointer_enter(x, y, buttons_state);
|
||||
|
||||
TRACKMOUSEEVENT tme;
|
||||
tme.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||
|
||||
@ -726,9 +726,9 @@ void RedWindow_p::win_proc(XEvent& event)
|
||||
if (event.xmotion.x >= 0 && event.xmotion.y >= 0 &&
|
||||
event.xmotion.x < size.x && event.xmotion.y < size.y) {
|
||||
Point origin = red_window->get_origin();
|
||||
red_window->get_listener().on_mouse_motion(event.xmotion.x - origin.x,
|
||||
event.xmotion.y - origin.y,
|
||||
to_red_buttons_state(event.xmotion.state));
|
||||
red_window->get_listener().on_pointer_motion(event.xmotion.x - origin.x,
|
||||
event.xmotion.y - origin.y,
|
||||
to_red_buttons_state(event.xmotion.state));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -758,7 +758,7 @@ void RedWindow_p::win_proc(XEvent& event)
|
||||
DBG(0, "ButtonPress: invalid button %u", event.xbutton.button);
|
||||
break;
|
||||
}
|
||||
red_window->get_listener().on_button_press(button, state);
|
||||
red_window->get_listener().on_mouse_button_press(button, state);
|
||||
break;
|
||||
}
|
||||
case ButtonRelease: {
|
||||
@ -768,7 +768,7 @@ void RedWindow_p::win_proc(XEvent& event)
|
||||
DBG(0, "ButtonRelease: invalid button %u", event.xbutton.button);
|
||||
break;
|
||||
}
|
||||
red_window->get_listener().on_button_release(button, state);
|
||||
red_window->get_listener().on_mouse_button_release(button, state);
|
||||
break;
|
||||
}
|
||||
case Expose: {
|
||||
@ -843,7 +843,9 @@ void RedWindow_p::win_proc(XEvent& event)
|
||||
break;
|
||||
case EnterNotify:
|
||||
if (!red_window->_ignore_pointer) {
|
||||
red_window->on_pointer_enter();
|
||||
Point origin = red_window->get_origin();
|
||||
red_window->on_pointer_enter(event.xcrossing.x - origin.x, event.xcrossing.y - origin.y,
|
||||
to_red_buttons_state(event.xmotion.state));
|
||||
} else {
|
||||
red_window->_shadow_pointer_state = true;
|
||||
memcpy(&red_window->_shadow_pointer_event, &event, sizeof(XEvent));
|
||||
@ -1943,13 +1945,13 @@ void RedWindow::on_focus_out()
|
||||
XPlatform::on_focus_out();
|
||||
}
|
||||
|
||||
void RedWindow::on_pointer_enter()
|
||||
void RedWindow::on_pointer_enter(int x, int y, unsigned int buttons_state)
|
||||
{
|
||||
if (_pointer_in_window) {
|
||||
return;
|
||||
}
|
||||
_pointer_in_window = true;
|
||||
_listener.on_pointer_enter();
|
||||
_listener.on_pointer_enter(x, y, buttons_state);
|
||||
if (_focused && _trace_key_interception) {
|
||||
do_start_key_interception();
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user