1
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
4
* Copyright (C) Nicolas Bruguier 2007-2010 <gandalfn@club-internet.fr>
6
* cairo-compmgr is free softwstribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
11
* cairo-compmgr is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with cairo-compmgr. If not, write to:
18
* The Free Software Foundation, Inc.,
19
* 51 Franklin Street, Fifth Floor
20
* Boston, MA 02110-1301, USA.
25
#include <X11/extensions/Xdamage.h>
26
#include <X11/extensions/Xfixes.h>
30
#include "ccm-debug.h"
31
#include "ccm-pixmap.h"
32
#include "ccm-pixmap-backend.h"
33
#include "ccm-window.h"
34
#include "ccm-screen.h"
35
#include "ccm-display.h"
36
#include "ccm-object.h"
38
CCM_DEFINE_TYPE (CCMPixmap, ccm_pixmap, CCM_TYPE_DRAWABLE);
48
struct _CCMPixmapPrivate
60
#define CCM_PIXMAP_GET_PRIVATE(o) \
61
(G_TYPE_INSTANCE_GET_PRIVATE ((o), CCM_TYPE_PIXMAP, CCMPixmapPrivate))
63
static void ccm_pixmap_bind (CCMPixmap * self);
64
static void ccm_pixmap_release (CCMPixmap * self);
65
static void ccm_pixmap_on_damage (CCMPixmap * self, Damage damage,
66
CCMDisplay * display);
69
ccm_pixmap_set_property (GObject * object, guint prop_id, const GValue * value,
72
CCMPixmap *self = CCM_PIXMAP (object);
78
self->priv->y_invert = g_value_get_boolean (value);
83
self->priv->freeze = g_value_get_boolean (value);
88
self->priv->foreign = g_value_get_boolean (value);
96
ccm_pixmap_get_property (GObject * object, guint prop_id, GValue * value,
99
CCMPixmap *self = CCM_PIXMAP (object);
105
g_value_set_boolean (value, self->priv->y_invert);
110
g_value_set_boolean (value, self->priv->freeze);
115
g_value_set_boolean (value, self->priv->foreign);
124
ccm_pixmap_init (CCMPixmap * self)
126
self->priv = CCM_PIXMAP_GET_PRIVATE (self);
128
self->priv->foreign = FALSE;
129
self->priv->damage = 0;
130
self->priv->y_invert = FALSE;
131
self->priv->freeze = FALSE;
132
self->priv->id_damage = 0;
136
ccm_pixmap_finalize (GObject * object)
138
CCMPixmap *self = CCM_PIXMAP (object);
139
CCMDisplay *display = ccm_drawable_get_display (CCM_DRAWABLE (object));
141
ccm_pixmap_release (self);
143
if (CCM_IS_DISPLAY (display) &&
144
G_OBJECT (display)->ref_count &&
147
XDamageDestroy (CCM_DISPLAY_XDISPLAY (display), self->priv->damage);
148
g_signal_handler_disconnect (display, self->priv->id_damage);
149
self->priv->damage = None;
151
self->priv->y_invert = FALSE;
152
self->priv->freeze = FALSE;
154
if (!self->priv->foreign)
155
XFreePixmap (CCM_DISPLAY_XDISPLAY (display), CCM_PIXMAP_XPIXMAP (self));
157
G_OBJECT_CLASS (ccm_pixmap_parent_class)->finalize (object);
161
ccm_pixmap_class_init (CCMPixmapClass * klass)
163
GObjectClass *object_class = G_OBJECT_CLASS (klass);
165
g_type_class_add_private (klass, sizeof (CCMPixmapPrivate));
167
object_class->set_property = ccm_pixmap_set_property;
168
object_class->get_property = ccm_pixmap_get_property;
171
* CCMPixmap:y_invert:
173
* This property indicate if the pixmap paint is y inverted.
175
g_object_class_install_property (object_class, PROP_Y_INVERT,
176
g_param_spec_boolean ("y_invert",
178
"Get if pixmap is y inverted",
186
* This property locks paint and damage if is true.
188
g_object_class_install_property (object_class, PROP_FREEZE,
189
g_param_spec_boolean ("freeze", "Freeze",
190
"Freeze pixmap damage and repair",
198
* This property indicate the object doesn't owned XPixmap if true.
200
g_object_class_install_property (object_class, PROP_FOREIGN,
201
g_param_spec_boolean ("foreign", "Foreign",
207
object_class->finalize = ccm_pixmap_finalize;
211
ccm_pixmap_bind (CCMPixmap * self)
213
g_return_if_fail (self != NULL);
215
if (CCM_PIXMAP_GET_CLASS (self)->bind)
216
CCM_PIXMAP_GET_CLASS (self)->bind (self);
220
ccm_pixmap_release (CCMPixmap * self)
222
g_return_if_fail (self != NULL);
224
if (CCM_PIXMAP_GET_CLASS (self)->release)
225
CCM_PIXMAP_GET_CLASS (self)->release (self);
229
ccm_pixmap_on_damage (CCMPixmap * self, Damage damage, CCMDisplay * display)
231
g_return_if_fail (self != NULL);
233
if (!self->priv->freeze && self->priv->damage == damage)
235
CCMDisplay *display = ccm_drawable_get_display (CCM_DRAWABLE (self));
236
XserverRegion region =
237
XFixesCreateRegion (CCM_DISPLAY_XDISPLAY (display), NULL, 0);
244
XDamageSubtract (CCM_DISPLAY_XDISPLAY (display), self->priv->damage,
246
rects = XFixesFetchRegion (CCM_DISPLAY_XDISPLAY (display), region,
250
CCMRegion *damaged = ccm_region_new ();
252
for (cpt = 0; cpt < nb_rects; ++cpt)
254
ccm_region_union_with_xrect (damaged, &rects[cpt]);
255
ccm_debug ("PIXMAP DAMAGE %i,%i,%i,%i", rects[cpt].x,
256
rects[cpt].y, rects[cpt].width,
261
ccm_drawable_damage_region (CCM_DRAWABLE (self), damaged);
262
ccm_drawable_repair(CCM_DRAWABLE (self));
263
ccm_region_destroy (damaged);
265
XFixesDestroyRegion (CCM_DISPLAY_XDISPLAY (display), region);
271
ccm_pixmap_register_damage (CCMPixmap * self)
273
g_return_if_fail (self != NULL);
275
CCMDisplay *display = ccm_drawable_get_display (CCM_DRAWABLE (self));
277
self->priv->damage = XDamageCreate (CCM_DISPLAY_XDISPLAY (display),
278
CCM_PIXMAP_XPIXMAP (self),
279
XDamageReportNonEmpty);
280
if (self->priv->damage)
282
XDamageSubtract (CCM_DISPLAY_XDISPLAY (display), self->priv->damage,
285
self->priv->id_damage =
286
g_signal_connect_swapped (display, "damage-event",
287
G_CALLBACK (ccm_pixmap_on_damage), self);
290
self->priv->damage = None;
295
* @drawable: #CCMDrawable
298
* Create a new pixmap
300
* Returns: #CCMPixmap
303
ccm_pixmap_new (CCMDrawable * drawable, Pixmap xpixmap)
305
g_return_val_if_fail (drawable != NULL, NULL);
306
g_return_val_if_fail (xpixmap != None, NULL);
308
CCMScreen *screen = ccm_drawable_get_screen (drawable);
309
Visual *visual = ccm_drawable_get_visual (drawable);
312
g_return_val_if_fail (screen != NULL && visual != None, NULL);
314
self = g_object_new (ccm_pixmap_backend_get_type (screen),
317
"visual", visual, NULL);
319
ccm_drawable_query_geometry (CCM_DRAWABLE (self));
320
if (!ccm_drawable_get_device_geometry (CCM_DRAWABLE (self)))
322
g_object_unref (self);
325
ccm_pixmap_register_damage (self);
326
if (!self->priv->damage)
328
g_object_unref (self);
331
ccm_pixmap_bind (self);
332
ccm_drawable_damage (CCM_DRAWABLE (self));
338
* ccm_pixmap_new_from_visual:
339
* @screen: #CCMScreen
343
* Create a new pixmap for a screen visual
345
* Returns: #CCMPixmap
348
ccm_pixmap_new_from_visual (CCMScreen * screen, Visual * visual, Pixmap xpixmap)
350
g_return_val_if_fail (screen != NULL, NULL);
351
g_return_val_if_fail (visual != NULL, NULL);
352
g_return_val_if_fail (xpixmap != None, NULL);
356
self = g_object_new (ccm_pixmap_backend_get_type (screen),
359
"visual", visual, NULL);
361
ccm_drawable_query_geometry (CCM_DRAWABLE (self));
362
if (!ccm_drawable_get_device_geometry (CCM_DRAWABLE (self)))
364
g_object_unref (self);
367
ccm_pixmap_register_damage (self);
368
if (!self->priv->damage)
370
g_object_unref (self);
373
ccm_pixmap_bind (self);
374
ccm_drawable_damage (CCM_DRAWABLE (self));
380
* ccm_pixmap_image_new:
381
* @drawable: #CCMDrawable
384
* Create a new pixmap which software rendering backend
386
* Returns: #CCMPixmap
389
ccm_pixmap_image_new (CCMDrawable * drawable, Pixmap xpixmap)
391
g_return_val_if_fail (drawable != NULL, NULL);
392
g_return_val_if_fail (xpixmap != None, NULL);
394
CCMScreen *screen = ccm_drawable_get_screen (drawable);
395
Visual *visual = ccm_drawable_get_visual (drawable);
398
g_return_val_if_fail (screen != NULL && visual != None, NULL);
400
self = g_object_new (ccm_pixmap_image_get_type (),
403
"visual", visual, NULL);
405
ccm_drawable_query_geometry (CCM_DRAWABLE (self));
406
ccm_pixmap_register_damage (self);
407
if (!self->priv->damage)
409
g_object_unref (self);
412
ccm_pixmap_bind (self);
413
ccm_drawable_damage (CCM_DRAWABLE (self));
419
ccm_pixmap_get_y_invert (CCMPixmap * self)
421
g_return_val_if_fail (self != NULL, FALSE);
423
return self->priv->y_invert;
427
ccm_pixmap_set_y_invert (CCMPixmap * self, gboolean y_invert)
429
g_return_if_fail (self != NULL);
431
self->priv->y_invert = y_invert;
433
g_object_notify (G_OBJECT (self), "y_invert");
437
ccm_pixmap_get_foreign (CCMPixmap * self)
439
g_return_val_if_fail (self != NULL, FALSE);
441
return self->priv->foreign;
445
ccm_pixmap_set_foreign (CCMPixmap * self, gboolean foreign)
447
g_return_if_fail (self != NULL);
449
self->priv->foreign = foreign;
451
g_object_notify (G_OBJECT (self), "foreign");
455
ccm_pixmap_get_freeze (CCMPixmap * self)
457
g_return_val_if_fail (self != NULL, FALSE);
459
return self->priv->freeze;
463
ccm_pixmap_set_freeze (CCMPixmap * self, gboolean freeze)
465
g_return_if_fail (self != NULL);
467
self->priv->freeze = freeze;
469
g_object_notify (G_OBJECT (self), "freeze");