client: interactive screen layer

This commit is contained in:
Yaniv Kamay 2009-11-16 17:50:16 +02:00
parent a70110c4e5
commit 3b51087b36
18 changed files with 884 additions and 402 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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 {

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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:

View File

@ -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;
};

View File

@ -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) {}

View File

@ -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)) {

View File

@ -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;}

View File

@ -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;

View File

@ -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()
{

View File

@ -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 &region);
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

View File

@ -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) {

View File

@ -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;

View File

@ -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);

View File

@ -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();
}