aboutsummaryrefslogtreecommitdiff
path: root/util/fbcompose/plugins/xrender/preview/PreviewPlugin.cc
diff options
context:
space:
mode:
Diffstat (limited to 'util/fbcompose/plugins/xrender/preview/PreviewPlugin.cc')
-rw-r--r--util/fbcompose/plugins/xrender/preview/PreviewPlugin.cc235
1 files changed, 235 insertions, 0 deletions
diff --git a/util/fbcompose/plugins/xrender/preview/PreviewPlugin.cc b/util/fbcompose/plugins/xrender/preview/PreviewPlugin.cc
new file mode 100644
index 0000000..14a0e61
--- /dev/null
+++ b/util/fbcompose/plugins/xrender/preview/PreviewPlugin.cc
@@ -0,0 +1,235 @@
1/** PreviewPlugin.cc file for the fluxbox compositor. */
2
3// Copyright (c) 2011 Gediminas Liktaras (gliktaras at gmail dot com)
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in
13// all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21// THE SOFTWARE.
22
23
24#include "PreviewPlugin.hh"
25
26#include "BaseScreen.hh"
27#include "Exceptions.hh"
28#include "Utility.hh"
29#include "XRenderScreen.hh"
30#include "XRenderWindow.hh"
31
32#include <algorithm>
33#include <iostream>
34
35using namespace FbCompositor;
36
37
38//--- CONSTANTS ----------------------------------------------------------------
39
40/** Maximum height of the preview window. */
41const int MAX_PREVIEW_HEIGHT = 150;
42
43/** Maximum width of the preview window. */
44const int MAX_PREVIEW_WIDTH = 150;
45
46/** Transparency of the preview window. */
47const unsigned int PREVIEW_ALPHA = 200;
48
49/** Time in microseconds until the preview window is shown. */
50const int SLEEP_TIME = 500000;
51
52
53//--- CONSTRUCTORS AND DESTRUCTORS ---------------------------------------------
54
55// Constructor.
56PreviewPlugin::PreviewPlugin(const BaseScreen &screen, const std::vector<FbTk::FbString> &args) :
57 XRenderPlugin(screen, args) {
58
59 unsigned long mask_color = 0x01010101 * PREVIEW_ALPHA;
60 Pixmap mask_pixmap = createSolidPixmap(screen, MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT, mask_color);
61 XRenderPictFormat *pict_format = XRenderFindStandardFormat(display(), PictStandardARGB32);
62 m_mask_picture = new XRenderPicture(xrenderScreen(), pict_format, FilterFast);
63 m_mask_picture->setPixmap(mask_pixmap, true);
64
65 m_previous_damage.width = 0;
66 m_previous_damage.height = 0;
67 m_previous_window = None;
68
69 m_tick_tracker.setTickSize(SLEEP_TIME);
70}
71
72// Destructor.
73PreviewPlugin::~PreviewPlugin() { }
74
75
76
77//--- WINDOW EVENT CALLBACKS ---------------------------------------------------
78
79// Called, whenever a new window is created.
80void PreviewPlugin::windowCreated(const BaseCompWindow &window) {
81 const XRenderWindow &xr_window = dynamic_cast<const XRenderWindow&>(window);
82
83 XRenderPictFormat *pict_format = XRenderFindStandardFormat(display(), PictStandardARGB32);
84 XRenderPicturePtr thumbnail(new XRenderPicture(xrenderScreen(), pict_format, FilterBest));
85
86 Pixmap thumb_pixmap = createSolidPixmap(screen(), MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT);
87 thumbnail->setPixmap(thumb_pixmap, true);
88
89 XRenderRenderingJob job = { PictOpOver, thumbnail, m_mask_picture, 0, 0, 0, 0, 0, 0, 0, 0 };
90
91 PreviewWindowData win_data = { xr_window, job };
92 m_preview_data.insert(std::make_pair(xr_window.window(), win_data));
93}
94
95/** Called, whenever a window is destroyed. */
96void PreviewPlugin::windowDestroyed(const BaseCompWindow &window) {
97 std::map<Window, PreviewWindowData>::iterator it = m_preview_data.find(window.window());
98 if (it != m_preview_data.end()) {
99 m_preview_data.erase(it);
100 }
101}
102
103
104//--- RENDERING ACTIONS --------------------------------------------------------
105
106/** Rectangles that the plugin wishes to damage. */
107const std::vector<XRectangle> &PreviewPlugin::damagedAreas() {
108 m_damaged_areas.clear();
109
110 if ((m_previous_damage.width > 0) && (m_previous_damage.height > 0)) {
111 m_damaged_areas.push_back(m_previous_damage);
112 }
113
114 std::map<Window, PreviewWindowData>::iterator it = m_preview_data.find(screen().currentIconbarItem());
115 if (it != m_preview_data.end()) {
116 Window cur_window = it->first;
117 PreviewWindowData &cur_preview = it->second;
118
119 if ((m_previous_window != cur_window)
120 && (cur_preview.window.contentPicture()->pictureHandle())
121 && (cur_preview.window.maskPicture()->pictureHandle())) {
122 m_previous_window = cur_window;
123 updatePreviewWindowData(cur_preview);
124 }
125
126 updatePreviewWindowPos(cur_preview);
127
128 XRectangle cur_damage = { cur_preview.job.destination_x, cur_preview.job.destination_y,
129 cur_preview.job.width, cur_preview.job.height };
130 m_damaged_areas.push_back(cur_damage);
131 m_previous_damage = cur_damage;
132
133 if (!m_tick_tracker.isRunning()) {
134 m_tick_tracker.start();
135 }
136 } else {
137 m_previous_damage.width = 0;
138 m_previous_damage.height = 0;
139 m_previous_window = None;
140 m_tick_tracker.stop();
141 }
142
143 return m_damaged_areas;
144}
145
146/** Extra rendering actions and jobs. */
147const std::vector<XRenderRenderingJob> &PreviewPlugin::extraRenderingActions() {
148 m_extra_jobs.clear();
149
150 std::map<Window, PreviewWindowData>::iterator it = m_preview_data.find(xrenderScreen().currentIconbarItem());
151 if (it != m_preview_data.end()) {
152 PreviewWindowData &cur_preview = it->second;
153
154 if ((cur_preview.job.source_picture->pictureHandle()) && (m_tick_tracker.totalElapsedTicks() > 0)) {
155 m_extra_jobs.push_back(cur_preview.job);
156 }
157 }
158
159 return m_extra_jobs;
160}
161
162
163//--- INTERNAL FUNCTIONS -------------------------------------------------------
164
165// Update the preview window data.
166void PreviewPlugin::updatePreviewWindowData(PreviewWindowData &win_preview) {
167 double scale_factor = 1.0;
168 scale_factor = std::max(scale_factor, win_preview.window.realWidth() / double(MAX_PREVIEW_WIDTH));
169 scale_factor = std::max(scale_factor, win_preview.window.realHeight() / double(MAX_PREVIEW_HEIGHT));
170
171 int thumbWidth = static_cast<int>(win_preview.window.realWidth() / scale_factor);
172 int thumbHeight = static_cast<int>(win_preview.window.realHeight() / scale_factor);
173
174 win_preview.window.contentPicture()->scalePicture(scale_factor, scale_factor);
175 win_preview.window.maskPicture()->scalePicture(scale_factor, scale_factor);
176
177 XRenderComposite(display(), PictOpSrc,
178 win_preview.window.contentPicture()->pictureHandle(),
179 win_preview.window.maskPicture()->pictureHandle(),
180 win_preview.job.source_picture->pictureHandle(),
181 0, 0, 0, 0, 0, 0, thumbWidth, thumbHeight);
182
183 win_preview.window.contentPicture()->resetPictureTransform();
184 win_preview.window.maskPicture()->resetPictureTransform();
185
186 win_preview.job.width = thumbWidth;
187 win_preview.job.height = thumbHeight;
188}
189
190// Update the preview window position.
191// TODO: Place the preview window on the edge of the toolbar.
192// TODO: Left/Right toolbar orientations.
193void PreviewPlugin::updatePreviewWindowPos(PreviewWindowData &win_preview) {
194 int mouse_pos_x, mouse_pos_y;
195 mousePointerLocation(screen(), mouse_pos_x, mouse_pos_y);
196
197 if (screen().heads().size() > 0) {
198 XRectangle cur_head = screen().heads()[0];
199
200 for (size_t i = 1; i < screen().heads().size(); i++) {
201 XRectangle head = screen().heads()[i];
202 if ((mouse_pos_x >= head.x) && (mouse_pos_y >= head.y)
203 && (mouse_pos_x < (head.x + head.width))
204 && (mouse_pos_y < (head.y + head.height))) {
205 cur_head = head;
206 break;
207 }
208 }
209
210 win_preview.job.destination_x = mouse_pos_x - (win_preview.job.width / 2);
211
212 int mid_head = cur_head.y + (cur_head.height / 2);
213 if (mouse_pos_y < mid_head) {
214 win_preview.job.destination_y = mouse_pos_y + 10;
215 } else {
216 win_preview.job.destination_y = mouse_pos_y - win_preview.job.height - 10;
217 }
218 } else { // But what IF.
219 win_preview.job.destination_x = mouse_pos_x - (win_preview.job.width / 2);
220 win_preview.job.destination_y = mouse_pos_y + 10;
221 }
222}
223
224
225//--- PLUGIN MANAGER FUNCTIONS -------------------------------------------------
226
227// Creates a plugin object.
228extern "C" BasePlugin *createPlugin(const BaseScreen &screen, const std::vector<FbTk::FbString> &args) {
229 return new PreviewPlugin(screen, args);
230}
231
232// Returns the type of the plugin.
233extern "C" FbCompositor::PluginType pluginType() {
234 return Plugin_XRender;
235}