mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-26 14:41:25 +00:00
The process loop is responsible for: 1) waiting for events 2) timers 3) events queue for actions that should be performed in the context of the thread and are pushed from other threads. The benefits: 1) remove duplicity: till now, there was one implementaion of events loop for the channels and another one for the main thread. 2) timers can be executed on each thread and not only on the main thread. 3) events can be pushed to each thread and not only to the main thread. In this commit, only the main thread was modified to use the new process loop.
779 lines
18 KiB
C++
779 lines
18 KiB
C++
/*
|
|
Copyright (C) 2009 Red Hat, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of
|
|
the License, or (at your option) any later version.
|
|
|
|
This program 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. 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_cairo.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;
|
|
};
|
|
|
|
void periodic_update_proc(void *opaque, TimerID timer)
|
|
{
|
|
RedScreen* screen = (RedScreen*)opaque;
|
|
|
|
screen->periodic_update();
|
|
}
|
|
|
|
RedScreen::RedScreen(Application& owner, int id, const std::wstring& name, int width, int height)
|
|
: _owner (owner)
|
|
, _id (id)
|
|
, _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)
|
|
, _forec_update_timer (0)
|
|
, _update_timer (INVALID_TIMER)
|
|
, _composit_area (NULL)
|
|
, _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)
|
|
{
|
|
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();
|
|
_update_timer = Platform::create_interval_timer(periodic_update_proc, this);
|
|
if (_update_timer == INVALID_TIMER) {
|
|
THROW("create timer failed");
|
|
}
|
|
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);
|
|
AutoRef<Menu> menu(_owner.get_app_menu());
|
|
_window.set_menu(*menu);
|
|
AutoRef<Icon> icon(Platform::load_icon(RED_ICON_RES_ID));
|
|
_window.set_icon(*icon);
|
|
}
|
|
|
|
RedScreen::~RedScreen()
|
|
{
|
|
bool captured = is_captured();
|
|
relase_inputs();
|
|
destroy_composit_area();
|
|
Platform::destroy_interval_timer(_update_timer);
|
|
_owner.on_screen_destroyed(_id, captured);
|
|
region_destroy(&_dirty_region);
|
|
if (_default_cursor) {
|
|
_default_cursor->unref();
|
|
}
|
|
if (_active_cursor) {
|
|
_active_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 RedPixmapCairo(_size.x, _size.y, RedPixmap::RGB32,
|
|
false, NULL, NULL);
|
|
}
|
|
|
|
void RedScreen::adjust_window_rect(int x, int y)
|
|
{
|
|
_window.move_and_resize(x, y, _size.x, _size.y);
|
|
}
|
|
|
|
void RedScreen::set_mode(int width, int height, int depth)
|
|
{
|
|
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_inputs();
|
|
}
|
|
} else {
|
|
_window.resize(_size.x, _size.y);
|
|
}
|
|
notify_new_size();
|
|
}
|
|
|
|
void RedScreen::set_name(const std::wstring& name)
|
|
{
|
|
if (!name.empty()) {
|
|
wstring_printf(_name, name.c_str(), _id);
|
|
}
|
|
_window.set_title(_name);
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
void RedScreen::detach_layer(ScreenLayer& layer)
|
|
{
|
|
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();
|
|
}
|
|
|
|
void RedScreen::composit_to_screen(RedDrawable& win_dc, const QRegion& region)
|
|
{
|
|
for (int i = 0; i < (int)region.num_rects; i++) {
|
|
Rect* r = ®ion.rects[i];
|
|
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;
|
|
Rect 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) {
|
|
Platform::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();
|
|
if (!Platform::activate_interval_timer(_update_timer, 1000 / 30)) {
|
|
LOG_WARN("failed");
|
|
}
|
|
}
|
|
|
|
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 Rect& 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 Rect& 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)
|
|
{
|
|
Rect *r = region.rects;
|
|
Rect *end = r + region.num_rects;
|
|
while (r != end) {
|
|
invalidate(*r++, false);
|
|
}
|
|
}
|
|
|
|
inline void RedScreen::erase_background(RedDrawable& dc, const QRegion& composit_rgn)
|
|
{
|
|
for (int i = 0; i < (int)composit_rgn.num_rects; i++) {
|
|
dc.fill_rect(composit_rgn.rects[i], 0);
|
|
}
|
|
}
|
|
|
|
void RedScreen::reset_mouse_pos()
|
|
{
|
|
_window.set_mouse_position(_mouse_anchor_point.x, _mouse_anchor_point.y);
|
|
}
|
|
|
|
void RedScreen::capture_inputs()
|
|
{
|
|
if (_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();
|
|
}
|
|
#ifndef NO_KEY_GRAB
|
|
_window.start_key_interception();
|
|
#endif
|
|
_captured = true;
|
|
}
|
|
|
|
void RedScreen::relase_inputs()
|
|
{
|
|
if (!_captured) {
|
|
return;
|
|
}
|
|
#ifndef NO_KEY_GRAB
|
|
_window.stop_key_interception();
|
|
#endif
|
|
_captured = false;
|
|
_window.release_mouse();
|
|
if (_owner.get_mouse_mode() == RED_MOUSE_MODE_SERVER) {
|
|
_window.set_cursor(_default_cursor);
|
|
}
|
|
}
|
|
|
|
void RedScreen::set_cursor(CursorData* 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();
|
|
}
|
|
}
|
|
_cursor_visible = !!cursor;
|
|
update_active_cursor();
|
|
}
|
|
|
|
void RedScreen::update_active_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();
|
|
}
|
|
}
|
|
}
|
|
|
|
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");
|
|
}
|
|
}
|
|
|
|
void RedScreen::on_button_press(RedButton button, unsigned int buttons_state)
|
|
{
|
|
if (_owner.get_mouse_mode() == RED_MOUSE_MODE_CLIENT &&
|
|
_pointer_location != POINTER_IN_ACTIVE_AREA) {
|
|
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;
|
|
}
|
|
}
|
|
_owner.on_mouse_down(button, buttons_state);
|
|
}
|
|
|
|
void RedScreen::on_button_release(RedButton button, unsigned int buttons_state)
|
|
{
|
|
if (!mouse_is_captured()) {
|
|
if (_owner.get_mouse_mode() == RED_MOUSE_MODE_SERVER) {
|
|
return;
|
|
}
|
|
capture_inputs();
|
|
}
|
|
_owner.on_mouse_up(button, buttons_state);
|
|
}
|
|
|
|
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_deactivate()
|
|
{
|
|
relase_inputs();
|
|
_active = false;
|
|
_owner.on_deactivate_screen(this);
|
|
}
|
|
|
|
void RedScreen::on_activate()
|
|
{
|
|
_active = true;
|
|
_owner.on_activate_screen(this);
|
|
}
|
|
|
|
void RedScreen::on_pointer_enter()
|
|
{
|
|
if (!_frame_area) {
|
|
_pointer_location = POINTER_IN_ACTIVE_AREA;
|
|
update_active_cursor();
|
|
}
|
|
}
|
|
|
|
void RedScreen::on_pointer_leave()
|
|
{
|
|
_pointer_location = POINTER_OUTSIDE_WINDOW;
|
|
}
|
|
|
|
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;
|
|
}
|
|
Point position = _monitor->get_position();
|
|
Point 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 Point& 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::on_exposed_rect(const Rect& 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(EventsLoop::Trigger *trigger)
|
|
{
|
|
_update_interrupt_trigger = trigger;
|
|
}
|
|
|
|
bool RedScreen::update_by_interrupt()
|
|
{
|
|
return _update_interrupt_trigger != NULL;
|
|
}
|
|
|
|
void RedScreen::interrupt_update()
|
|
{
|
|
_update_interrupt_trigger->trigger();
|
|
}
|
|
|
|
void RedScreen::set_type_gl()
|
|
{
|
|
_window.set_type_gl();
|
|
}
|
|
|
|
void RedScreen::unset_type_gl()
|
|
{
|
|
_window.unset_type_gl();
|
|
}
|
|
|