mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-26 22:48:19 +00:00
The activex browser plugin is sending unicode16 text, where as the xpi one is sending utf8 text. After discussing this on irc we've decided that utf8 is what we want to use. So the client (this patch), and the activex will be changed to expect resp. send utf8 text as the title.
935 lines
21 KiB
C++
935 lines
21 KiB
C++
/*
|
|
Copyright (C) 2009 Red Hat, Inc.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include "screen.h"
|
|
#include "application.h"
|
|
#include "screen_layer.h"
|
|
#include "utils.h"
|
|
#include "debug.h"
|
|
#include "monitor.h"
|
|
#include "red_pixmap_sw.h"
|
|
#include "resource.h"
|
|
#include "icon.h"
|
|
|
|
class UpdateEvent: public Event {
|
|
public:
|
|
UpdateEvent(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) {
|
|
screen->update();
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
RedScreen::RedScreen(Application& owner, int id, const std::string& name, int width, int height)
|
|
: _owner (owner)
|
|
, _id (id)
|
|
, _refs (1)
|
|
, _window (*this)
|
|
, _active (false)
|
|
, _full_screen (false)
|
|
, _out_of_sync (false)
|
|
, _frame_area (false)
|
|
, _periodic_update (false)
|
|
, _key_interception (false)
|
|
, _update_by_timer (true)
|
|
, _size_locked (false)
|
|
, _forec_update_timer (0)
|
|
, _update_timer (new UpdateTimer(this))
|
|
, _composit_area (NULL)
|
|
, _update_mark (1)
|
|
, _monitor (NULL)
|
|
, _default_cursor (NULL)
|
|
, _inactive_cursor (NULL)
|
|
, _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);
|
|
_size.x = width;
|
|
_size.y = height;
|
|
_origin.x = _origin.y = 0;
|
|
create_composit_area();
|
|
_window.resize(_size.x, _size.y);
|
|
save_position();
|
|
if ((_default_cursor = Platform::create_default_cursor()) == NULL) {
|
|
THROW("create default cursor failed");
|
|
}
|
|
if ((_inactive_cursor = Platform::create_inactive_cursor()) == NULL) {
|
|
THROW("create inactive cursor failed");
|
|
}
|
|
_window.set_cursor(_default_cursor);
|
|
update_menu();
|
|
AutoRef<Icon> icon(Platform::load_icon(RED_ICON_RES_ID));
|
|
_window.set_icon(*icon);
|
|
_window.start_key_interception();
|
|
}
|
|
|
|
RedScreen::~RedScreen()
|
|
{
|
|
bool captured = is_mouse_captured();
|
|
_window.stop_key_interception();
|
|
relase_mouse();
|
|
destroy_composit_area();
|
|
_owner.deactivate_interval_timer(*_update_timer);
|
|
_owner.on_screen_destroyed(_id, captured);
|
|
region_destroy(&_dirty_region);
|
|
if (_default_cursor) {
|
|
_default_cursor->unref();
|
|
}
|
|
|
|
if (_inactive_cursor) {
|
|
_inactive_cursor->unref();
|
|
}
|
|
}
|
|
|
|
void RedScreen::show(bool activate, RedScreen* pos)
|
|
{
|
|
_window.position_after((pos) ? &pos->_window : NULL);
|
|
show();
|
|
if (activate) {
|
|
_window.activate();
|
|
}
|
|
}
|
|
|
|
RedScreen* RedScreen::ref()
|
|
{
|
|
++_refs;
|
|
return this;
|
|
}
|
|
|
|
void RedScreen::unref()
|
|
{
|
|
if (!--_refs) {
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
void RedScreen::destroy_composit_area()
|
|
{
|
|
if (_composit_area) {
|
|
delete _composit_area;
|
|
_composit_area = NULL;
|
|
}
|
|
}
|
|
|
|
void RedScreen::create_composit_area()
|
|
{
|
|
destroy_composit_area();
|
|
_composit_area = new RedPixmapSw(_size.x, _size.y, _window.get_format(),
|
|
false, &_window);
|
|
}
|
|
|
|
void RedScreen::adjust_window_rect(int x, int y)
|
|
{
|
|
_window.move_and_resize(x, y, _size.x, _size.y);
|
|
}
|
|
|
|
void RedScreen::resize(int width, int height)
|
|
{
|
|
RecurciveLock lock(_update_lock);
|
|
_size.x = width;
|
|
_size.y = height;
|
|
create_composit_area();
|
|
if (_full_screen) {
|
|
bool cuptur = _owner.rearrange_monitors(*this);
|
|
__show_full_screen();
|
|
if (cuptur) {
|
|
capture_mouse();
|
|
}
|
|
} else {
|
|
bool cuptur = is_mouse_captured();
|
|
if (cuptur) {
|
|
relase_mouse();
|
|
}
|
|
_window.resize(_size.x, _size.y);
|
|
if (_active && cuptur) {
|
|
capture_mouse();
|
|
}
|
|
}
|
|
notify_new_size();
|
|
}
|
|
|
|
void RedScreen::lock_size()
|
|
{
|
|
ASSERT(!_size_locked);
|
|
_size_locked = true;
|
|
}
|
|
|
|
void RedScreen::unlock_size()
|
|
{
|
|
_size_locked = false;
|
|
_owner.on_screen_unlocked(*this);
|
|
}
|
|
|
|
void RedScreen::set_name(const std::string& name)
|
|
{
|
|
if (!name.empty()) {
|
|
string_printf(_name, name.c_str(), _id);
|
|
}
|
|
_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);
|
|
int order = layer.z_order();
|
|
|
|
if ((int)_layes.size() < order + 1) {
|
|
_layes.resize(order + 1);
|
|
}
|
|
if (_layes[order]) {
|
|
THROW("layer in use");
|
|
}
|
|
layer.set_screen(this);
|
|
_layes[order] = &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) {
|
|
THROW("not found");
|
|
}
|
|
QRegion layer_area;
|
|
region_clone(&layer_area, &layer.area());
|
|
_layes[order]->set_screen(NULL);
|
|
_layes[order] = NULL;
|
|
lock.unlock();
|
|
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)
|
|
{
|
|
pixman_box32_t *rects;
|
|
int num_rects;
|
|
|
|
rects = pixman_region32_rectangles((pixman_region32_t *)®ion, &num_rects);
|
|
for (int i = 0; i < num_rects; i++) {
|
|
SpiceRect r;
|
|
|
|
r.left = rects[i].x1;
|
|
r.top = rects[i].y1;
|
|
r.right = rects[i].x2;
|
|
r.bottom = rects[i].y2;
|
|
win_dc.copy_pixels(*_composit_area, r.left, r.top, r);
|
|
}
|
|
}
|
|
|
|
void RedScreen::notify_new_size()
|
|
{
|
|
for (int i = 0; i < (int)_layes.size(); i++) {
|
|
if (!_layes[i]) {
|
|
continue;
|
|
}
|
|
_layes[i]->on_size_changed();
|
|
}
|
|
}
|
|
|
|
inline void RedScreen::begin_update(QRegion& direct_rgn, QRegion& composit_rgn,
|
|
QRegion& frame_rgn)
|
|
{
|
|
region_init(&composit_rgn);
|
|
RecurciveLock lock(_update_lock);
|
|
region_clone(&direct_rgn, &_dirty_region);
|
|
region_clear(&_dirty_region);
|
|
_update_mark++;
|
|
lock.unlock();
|
|
|
|
QRegion rect_rgn;
|
|
SpiceRect r;
|
|
r.top = r.left = 0;
|
|
r.right = _size.x;
|
|
r.bottom = _size.y;
|
|
region_init(&rect_rgn);
|
|
region_add(&rect_rgn, &r);
|
|
|
|
if (_frame_area) {
|
|
region_clone(&frame_rgn, &direct_rgn);
|
|
region_exclude(&frame_rgn, &rect_rgn);
|
|
}
|
|
region_and(&direct_rgn, &rect_rgn);
|
|
region_destroy(&rect_rgn);
|
|
|
|
for (int i = _layes.size() - 1; i >= 0; i--) {
|
|
ScreenLayer* layer;
|
|
|
|
if (!(layer = _layes[i])) {
|
|
continue;
|
|
}
|
|
layer->begin_update(direct_rgn, composit_rgn);
|
|
}
|
|
}
|
|
|
|
inline void RedScreen::update_done()
|
|
{
|
|
for (unsigned int i = 0; i < _layes.size(); i++) {
|
|
ScreenLayer* layer;
|
|
|
|
if (!(layer = _layes[i])) {
|
|
continue;
|
|
}
|
|
layer->on_update_completion(_update_mark - 1);
|
|
}
|
|
}
|
|
|
|
inline void RedScreen::update_composit(QRegion& composit_rgn)
|
|
{
|
|
erase_background(*_composit_area, composit_rgn);
|
|
for (int i = 0; i < (int)_layes.size(); i++) {
|
|
ScreenLayer* layer;
|
|
|
|
if (!(layer = _layes[i])) {
|
|
continue;
|
|
}
|
|
QRegion& dest_region = layer->composit_area();
|
|
region_or(&composit_rgn, &dest_region);
|
|
layer->copy_pixels(dest_region, *_composit_area);
|
|
}
|
|
}
|
|
|
|
inline void RedScreen::draw_direct(RedDrawable& win_dc, QRegion& direct_rgn, QRegion& composit_rgn,
|
|
QRegion& frame_rgn)
|
|
{
|
|
erase_background(win_dc, direct_rgn);
|
|
|
|
if (_frame_area) {
|
|
erase_background(win_dc, frame_rgn);
|
|
region_destroy(&frame_rgn);
|
|
}
|
|
|
|
for (int i = 0; i < (int)_layes.size(); i++) {
|
|
ScreenLayer* layer;
|
|
|
|
if (!(layer = _layes[i])) {
|
|
continue;
|
|
}
|
|
QRegion& dest_region = layer->direct_area();
|
|
layer->copy_pixels(dest_region, win_dc);
|
|
}
|
|
}
|
|
|
|
void RedScreen::periodic_update()
|
|
{
|
|
bool need_update;
|
|
RecurciveLock lock(_update_lock);
|
|
if (is_dirty()) {
|
|
need_update = true;
|
|
} else {
|
|
if (!_forec_update_timer) {
|
|
_owner.deactivate_interval_timer(*_update_timer);
|
|
_periodic_update = false;
|
|
}
|
|
need_update = false;
|
|
}
|
|
lock.unlock();
|
|
|
|
if (need_update) {
|
|
if (update_by_interrupt()) {
|
|
interrupt_update();
|
|
} else {
|
|
update();
|
|
}
|
|
}
|
|
}
|
|
|
|
void RedScreen::activate_timer()
|
|
{
|
|
RecurciveLock lock(_update_lock);
|
|
if (_periodic_update) {
|
|
return;
|
|
}
|
|
_periodic_update = true;
|
|
lock.unlock();
|
|
_owner.activate_interval_timer(*_update_timer, 1000 / 30);
|
|
}
|
|
|
|
void RedScreen::update()
|
|
{
|
|
if (is_out_of_sync()) {
|
|
return;
|
|
}
|
|
|
|
QRegion direct_rgn;
|
|
QRegion composit_rgn;
|
|
QRegion frame_rgn;
|
|
|
|
begin_update(direct_rgn, composit_rgn, frame_rgn);
|
|
update_composit(composit_rgn);
|
|
draw_direct(_window, direct_rgn, composit_rgn, frame_rgn);
|
|
composit_to_screen(_window, composit_rgn);
|
|
update_done();
|
|
region_destroy(&direct_rgn);
|
|
region_destroy(&composit_rgn);
|
|
|
|
if (_update_by_timer) {
|
|
activate_timer();
|
|
}
|
|
}
|
|
|
|
bool RedScreen::_invalidate(const SpiceRect& rect, bool urgent, uint64_t& update_mark)
|
|
{
|
|
RecurciveLock lock(_update_lock);
|
|
bool update_triger = !is_dirty() && (urgent || !_periodic_update);
|
|
region_add(&_dirty_region, &rect);
|
|
update_mark = _update_mark;
|
|
return update_triger;
|
|
}
|
|
|
|
uint64_t RedScreen::invalidate(const SpiceRect& rect, bool urgent)
|
|
{
|
|
uint64_t update_mark;
|
|
if (_invalidate(rect, urgent, update_mark)) {
|
|
if (!urgent && _update_by_timer) {
|
|
activate_timer();
|
|
} else {
|
|
if (update_by_interrupt()) {
|
|
interrupt_update();
|
|
} else {
|
|
AutoRef<UpdateEvent> update_event(new UpdateEvent(_id));
|
|
_owner.push_event(*update_event);
|
|
}
|
|
}
|
|
}
|
|
return update_mark;
|
|
}
|
|
|
|
void RedScreen::invalidate(const QRegion ®ion)
|
|
{
|
|
pixman_box32_t *rects, *end;
|
|
int num_rects;
|
|
|
|
rects = pixman_region32_rectangles((pixman_region32_t *)®ion, &num_rects);
|
|
end = rects + num_rects;
|
|
|
|
while (rects != end) {
|
|
SpiceRect r;
|
|
|
|
r.left = rects->x1;
|
|
r.top = rects->y1;
|
|
r.right = rects->x2;
|
|
r.bottom = rects->y2;
|
|
rects++;
|
|
|
|
invalidate(r, false);
|
|
}
|
|
}
|
|
|
|
inline void RedScreen::erase_background(RedDrawable& dc, const QRegion& composit_rgn)
|
|
{
|
|
pixman_box32_t *rects;
|
|
int num_rects;
|
|
|
|
rects = pixman_region32_rectangles((pixman_region32_t *)&composit_rgn, &num_rects);
|
|
for (int i = 0; i < num_rects; i++) {
|
|
SpiceRect r;
|
|
|
|
r.left = rects[i].x1;
|
|
r.top = rects[i].y1;
|
|
r.right = rects[i].x2;
|
|
r.bottom = rects[i].y2;
|
|
|
|
dc.fill_rect(r, 0);
|
|
}
|
|
}
|
|
|
|
void RedScreen::reset_mouse_pos()
|
|
{
|
|
_window.set_mouse_position(_mouse_anchor_point.x, _mouse_anchor_point.y);
|
|
}
|
|
|
|
void RedScreen::capture_mouse()
|
|
{
|
|
if (_mouse_captured || !_window.get_mouse_anchor_point(_mouse_anchor_point)) {
|
|
return;
|
|
}
|
|
|
|
if (_pointer_layer) {
|
|
_pointer_layer->on_pointer_leave();
|
|
_pointer_layer = NULL;
|
|
}
|
|
_pointer_on_screen = false;
|
|
_mouse_captured = true;
|
|
_window.hide_cursor();
|
|
reset_mouse_pos();
|
|
_window.cupture_mouse();
|
|
}
|
|
|
|
void RedScreen::relase_mouse()
|
|
{
|
|
if (!_mouse_captured) {
|
|
return;
|
|
}
|
|
_mouse_captured = false;
|
|
_window.release_mouse();
|
|
update_pointer_layer();
|
|
}
|
|
|
|
void RedScreen::set_cursor(LocalCursor* cursor)
|
|
{
|
|
if (_mouse_captured) {
|
|
return;
|
|
}
|
|
|
|
_window.set_cursor(cursor);
|
|
}
|
|
|
|
void RedScreen::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)
|
|
{
|
|
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_pointer_motion(int x, int y, unsigned int buttons_state)
|
|
{
|
|
if (_mouse_captured) {
|
|
on_mouse_motion(x, y, buttons_state);
|
|
return;
|
|
}
|
|
|
|
_pointer_pos.x = x;
|
|
_pointer_pos.y = y;
|
|
_mouse_botton_state = buttons_state;
|
|
|
|
if (update_pointer_layer() || !_pointer_layer) {
|
|
return;
|
|
}
|
|
|
|
_pointer_layer->on_pointer_motion(x, y, buttons_state);
|
|
}
|
|
|
|
void RedScreen::on_mouse_button_press(SpiceMouseButton button, unsigned int buttons_state)
|
|
{
|
|
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(SpiceMouseButton 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)
|
|
{
|
|
_owner.on_key_down(key);
|
|
}
|
|
|
|
void RedScreen::on_key_release(RedKey key)
|
|
{
|
|
_owner.on_key_up(key);
|
|
}
|
|
|
|
void RedScreen::on_char(uint32_t ch)
|
|
{
|
|
_owner.on_char(ch);
|
|
}
|
|
|
|
void RedScreen::on_deactivate()
|
|
{
|
|
relase_mouse();
|
|
_active = false;
|
|
_owner.on_deactivate_screen(this);
|
|
}
|
|
|
|
void RedScreen::on_activate()
|
|
{
|
|
_active = true;
|
|
_owner.on_activate_screen(this);
|
|
}
|
|
|
|
void RedScreen::on_start_key_interception()
|
|
{
|
|
_key_interception = true;
|
|
_owner.on_start_screen_key_interception(this);
|
|
}
|
|
|
|
void RedScreen::on_stop_key_interception()
|
|
{
|
|
_key_interception = false;
|
|
_owner.on_stop_screen_key_interception(this);
|
|
}
|
|
|
|
void RedScreen::enter_modal_loop()
|
|
{
|
|
_forec_update_timer++;
|
|
activate_timer();
|
|
}
|
|
|
|
void RedScreen::exit_modal_loop()
|
|
{
|
|
ASSERT(_forec_update_timer > 0)
|
|
_forec_update_timer--;
|
|
}
|
|
|
|
void RedScreen::pre_migrate()
|
|
{
|
|
for (int i = 0; i < (int)_layes.size(); i++) {
|
|
if (!_layes[i]) {
|
|
continue;
|
|
}
|
|
_layes[i]->pre_migrate();
|
|
}
|
|
}
|
|
|
|
void RedScreen::post_migrate()
|
|
{
|
|
for (int i = 0; i < (int)_layes.size(); i++) {
|
|
if (!_layes[i]) {
|
|
continue;
|
|
}
|
|
_layes[i]->post_migrate();
|
|
}
|
|
}
|
|
|
|
void RedScreen::exit_full_screen()
|
|
{
|
|
if (!_full_screen) {
|
|
return;
|
|
}
|
|
RecurciveLock lock(_update_lock);
|
|
_window.hide();
|
|
region_clear(&_dirty_region);
|
|
_window.set_type(RedWindow::TYPE_NORMAL);
|
|
adjust_window_rect(_save_pos.x, _save_pos.y);
|
|
_origin.x = _origin.y = 0;
|
|
_window.set_origin(0, 0);
|
|
show();
|
|
_full_screen = false;
|
|
_out_of_sync = false;
|
|
_frame_area = false;
|
|
}
|
|
|
|
void RedScreen::save_position()
|
|
{
|
|
_save_pos = _window.get_position();
|
|
}
|
|
|
|
void RedScreen::__show_full_screen()
|
|
{
|
|
if (!_monitor) {
|
|
hide();
|
|
return;
|
|
}
|
|
SpicePoint position = _monitor->get_position();
|
|
SpicePoint monitor_size = _monitor->get_size();
|
|
_frame_area = false;
|
|
region_clear(&_dirty_region);
|
|
_window.set_type(RedWindow::TYPE_FULLSCREEN);
|
|
_window.move_and_resize(position.x, position.y, monitor_size.x, monitor_size.y);
|
|
|
|
if (!(_out_of_sync = _monitor->is_out_of_sync())) {
|
|
ASSERT(monitor_size.x >= _size.x);
|
|
ASSERT(monitor_size.y >= _size.y);
|
|
_origin.x = (monitor_size.x - _size.x) / 2;
|
|
_origin.y = (monitor_size.y - _size.y) / 2;
|
|
_frame_area = monitor_size.x != _size.x || monitor_size.y != _size.y;
|
|
} else {
|
|
_origin.x = _origin.y = 0;
|
|
}
|
|
_window.set_origin(_origin.x, _origin.y);
|
|
show();
|
|
}
|
|
|
|
void RedScreen::show_full_screen()
|
|
{
|
|
if (_full_screen) {
|
|
return;
|
|
}
|
|
RecurciveLock lock(_update_lock);
|
|
hide();
|
|
save_position();
|
|
_full_screen = true;
|
|
__show_full_screen();
|
|
}
|
|
|
|
void RedScreen::minimize()
|
|
{
|
|
_window.minimize();
|
|
}
|
|
|
|
void RedScreen::position_full_screen(const SpicePoint& position)
|
|
{
|
|
if (!_full_screen) {
|
|
return;
|
|
}
|
|
|
|
_window.move(position.x, position.y);
|
|
}
|
|
|
|
void RedScreen::hide()
|
|
{
|
|
_window.hide();
|
|
}
|
|
|
|
void RedScreen::show()
|
|
{
|
|
RecurciveLock lock(_update_lock);
|
|
_window.show(_monitor ? _monitor->get_screen_id() : 0);
|
|
}
|
|
|
|
void RedScreen::activate()
|
|
{
|
|
_window.activate();
|
|
}
|
|
|
|
void RedScreen::external_show()
|
|
{
|
|
DBG(0, "Entry");
|
|
_window.external_show();
|
|
}
|
|
|
|
void RedScreen::update_menu()
|
|
{
|
|
AutoRef<Menu> menu(_owner.get_app_menu());
|
|
_window.set_menu(*menu);
|
|
}
|
|
|
|
void RedScreen::on_exposed_rect(const SpiceRect& area)
|
|
{
|
|
if (is_out_of_sync()) {
|
|
_window.fill_rect(area, rgb32_make(0xff, 0xff, 0xff));
|
|
return;
|
|
}
|
|
invalidate(area, false);
|
|
}
|
|
|
|
int RedScreen::get_screen_id()
|
|
{
|
|
return _monitor ? _monitor->get_screen_id() : 0;
|
|
}
|
|
|
|
#ifdef USE_OGL
|
|
void RedScreen::untouch_context()
|
|
{
|
|
_window.untouch_context();
|
|
}
|
|
|
|
bool RedScreen::need_recreate_context_gl()
|
|
{
|
|
if (_full_screen) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#endif
|
|
|
|
void RedScreen::set_update_interrupt_trigger(EventSources::Trigger *trigger)
|
|
{
|
|
_update_interrupt_trigger = trigger;
|
|
}
|
|
|
|
bool RedScreen::update_by_interrupt()
|
|
{
|
|
return _update_interrupt_trigger != NULL;
|
|
}
|
|
|
|
void RedScreen::interrupt_update()
|
|
{
|
|
_update_interrupt_trigger->trigger();
|
|
}
|
|
|
|
#ifdef USE_OGL
|
|
void RedScreen::set_type_gl()
|
|
{
|
|
_window.set_type_gl();
|
|
}
|
|
|
|
void RedScreen::unset_type_gl()
|
|
{
|
|
_window.unset_type_gl();
|
|
}
|
|
#endif // USE_OGL
|
|
|