diff options
Diffstat (limited to 'client/screen_layer.cpp')
-rw-r--r-- | client/screen_layer.cpp | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/client/screen_layer.cpp b/client/screen_layer.cpp new file mode 100644 index 00000000..f521b465 --- /dev/null +++ b/client/screen_layer.cpp @@ -0,0 +1,200 @@ +/* + 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_layer.h" +#include "utils.h" +#include "screen.h" +#include "application.h" +#include "debug.h" + +class AttacheLayerEvent: public SyncEvent { +public: + AttacheLayerEvent(ScreenLayer& layer, int screen_id) : _layer (layer), _screen_id (screen_id) {} + + virtual void do_responce(Application& application); + +private: + ScreenLayer& _layer; + int _screen_id; +}; + +void AttacheLayerEvent::do_responce(Application& application) +{ + AutoRef<RedScreen> screen(application.get_screen(_screen_id)); + (*screen)->attach_layer(_layer); +} + +class DetacheLayerEvent: public SyncEvent { +public: + DetacheLayerEvent(ScreenLayer& _layer) : _layer (_layer) {} + + virtual void do_responce(Application& application); + +private: + ScreenLayer& _layer; +}; + +void DetacheLayerEvent::do_responce(Application& application) +{ + _layer.screen()->detach_layer(_layer); +} + +ScreenLayer::ScreenLayer(int z_order, bool opaque) + : _screen (NULL) + , _z_order (z_order) + , _opaque (opaque) + , _using_ogl (false) +{ + region_init(&_area); + region_init(&_direct_area); + region_init(&_composit_area); +} + +ScreenLayer::~ScreenLayer() +{ + ASSERT(!_screen); + region_destroy(&_area); + region_destroy(&_direct_area); + region_destroy(&_composit_area); +} + +uint64_t ScreenLayer::invalidate_rect(const Rect& r, bool urgent) +{ + return _screen->invalidate(r, urgent); +} + +uint64_t ScreenLayer::invalidate(const Rect& r, bool urgent) +{ + if (!_screen) { + return 0; + } + return invalidate_rect(r, urgent); +} + +void ScreenLayer::invalidate(const QRegion& region) +{ + if (!_screen) { + return; + } + Rect *r = region.rects; + Rect *end = r + region.num_rects; + while (r != end) { + invalidate_rect(*r++, false); + } +} + +void ScreenLayer::invalidate() +{ + invalidate(_area); +} + +void ScreenLayer::set_area(const QRegion& area) +{ + Lock lock(_area_lock); + invalidate(); + region_destroy(&_area); + region_clone(&_area, &area); + invalidate(); +} + +void ScreenLayer::clear_area() +{ + Lock lock(_area_lock); + invalidate(); + region_clear(&_area); +} + +void ScreenLayer::set_rect_area(const Rect& r) +{ + Lock lock(_area_lock); + invalidate(); + region_clear(&_area); + region_add(&_area, &r); + invalidate(); +} + +void ScreenLayer::offset_area(int dx, int dy) +{ + Lock lock(_area_lock); + invalidate(); + region_offset(&_area, dx, dy); + invalidate(); +} + +void ScreenLayer::add_rect_area(const Rect& r) +{ + Lock lock(_area_lock); + region_add(&_area, &r); +} + +void ScreenLayer::remove_rect_area(const Rect& r) +{ + Lock lock(_area_lock); + invalidate(); + region_remove(&_area, &r); +} + +void ScreenLayer::begin_update(QRegion& direct_rgn, QRegion& composit_rgn) +{ + Lock lock(_area_lock); + region_destroy(&_direct_area); + region_clone(&_direct_area, &_area); + region_and(&_direct_area, &direct_rgn); + + region_destroy(&_composit_area); + region_clone(&_composit_area, &_area); + region_and(&_composit_area, &composit_rgn); + + region_exclude(&direct_rgn, &_direct_area); + if (_opaque) { + region_exclude(&composit_rgn, &_composit_area); + } else { + region_or(&composit_rgn, &_direct_area); + region_or(&_composit_area, &_direct_area); + region_clear(&_direct_area); + } +} + +void ScreenLayer::attach_to_screen(Application& applicaion, int screen_id) +{ + if (_screen) { + return; + } + AutoRef<AttacheLayerEvent> event(new AttacheLayerEvent(*this, screen_id)); + applicaion.push_event(*event); + (*event)->wait(); + if (!(*event)->success()) { + THROW("attach failed"); + } + ASSERT(_screen); +} + +void ScreenLayer::detach_from_screen(Application& applicaion) +{ + if (!_screen) { + return; + } + AutoRef<DetacheLayerEvent> event(new DetacheLayerEvent(*this)); + applicaion.push_event(*event); + (*event)->wait(); + if (!(*event)->success()) { + THROW("detach failed"); + } + ASSERT(!_screen); +} + |