summaryrefslogtreecommitdiffstats
path: root/client/screen.cpp
diff options
context:
space:
mode:
authorYaniv Kamay <ykamay@redhat.com>2009-11-16 17:50:16 +0200
committerYaniv Kamay <ykamay@redhat.com>2009-11-30 18:03:35 +0200
commit3b51087b3656b111886c7397d0ddd499a96f9e2d (patch)
tree21cdb7b0dc282062bd811f65ee295a7074b58275 /client/screen.cpp
parenta70110c4e50aad99de7a844bb78eb868768e7841 (diff)
downloadspice-3b51087b3656b111886c7397d0ddd499a96f9e2d.tar.gz
spice-3b51087b3656b111886c7397d0ddd499a96f9e2d.tar.xz
spice-3b51087b3656b111886c7397d0ddd499a96f9e2d.zip
client: interactive screen layer
Diffstat (limited to 'client/screen.cpp')
-rw-r--r--client/screen.cpp302
1 files changed, 195 insertions, 107 deletions
diff --git a/client/screen.cpp b/client/screen.cpp
index bbc76e75..50905710 100644
--- a/client/screen.cpp
+++ b/client/screen.cpp
@@ -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(LocalCursor* cursor)
+{
+ if (_mouse_captured) {
+ return;
}
+
+ _window.set_cursor(cursor);
+}
+
+void RedScreen::hide_cursor()
+{
+ _window.hide_cursor();
}
-void RedScreen::set_cursor(CursorData* cursor)
+ScreenLayer* RedScreen::find_pointer_layer()
{
- if (cursor) {
- if (_active_cursor) {
- _active_cursor->unref();
+ for (int i = _layes.size() - 1; i >= 0; i--) {
+ ScreenLayer* layer;
+
+ if (!(layer = _layes[i])) {
+ continue;
}
- 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 (layer->pointer_test(_pointer_pos.x, _pointer_pos.y)) {
+ return layer;
}
}
- _cursor_visible = !!cursor;
- update_active_cursor();
+ return NULL;
}
-void RedScreen::update_active_cursor()
+bool RedScreen::update_pointer_layer()
{
- 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();
- }
+ 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;
+ }
+
+ 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;
}
- _owner.on_mouse_up(button, buttons_state);
+
+ 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()
{