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>
5
* Carlos Diógenes 2007 <cerdiogenes@gmail.com>
7
* cairo-compmgr is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
12
* cairo-compmgr is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with cairo-compmgr. If not, write to:
19
* The Free Software Foundation, Inc.,
20
* 51 Franklin Street, Fifth Floor
21
* Boston, MA 02110-1301, USA.
26
#include <X11/extensions/Xfixes.h>
28
#include "ccm-debug.h"
29
#include "ccm-config.h"
30
#include "ccm-drawable.h"
31
#include "ccm-window.h"
32
#include "ccm-display.h"
33
#include "ccm-screen.h"
34
#include "ccm-magnifier.h"
35
#include "ccm-keybind.h"
36
#include "ccm-cairo-utils.h"
37
#include "ccm-timeline.h"
40
#define CCM_MAGNIFIER_WINDOW_INFO_WIDTH 30
41
#define CCM_MAGNIFIER_WINDOW_INFO_HEIGHT 7
46
CCM_MAGNIFIER_ZOOM_LEVEL,
47
CCM_MAGNIFIER_ZOOM_QUALITY,
52
CCM_MAGNIFIER_RESTRICT_AREA_X,
53
CCM_MAGNIFIER_RESTRICT_AREA_Y,
54
CCM_MAGNIFIER_RESTRICT_AREA_WIDTH,
55
CCM_MAGNIFIER_RESTRICT_AREA_HEIGHT,
57
CCM_MAGNIFIER_SHORTCUT,
58
CCM_MAGNIFIER_SHADE_DESKTOP,
59
CCM_MAGNIFIER_OPTION_N
62
static const gchar *CCMMagnifierOptionKeys[CCM_MAGNIFIER_OPTION_N] = {
72
"restrict_area_width",
73
"restrict_area_height",
81
CCMPluginOptions parent;
91
cairo_rectangle_t restrict_area;
92
cairo_rectangle_t area;
93
cairo_filter_t quality;
96
} CCMMagnifierOptions;
98
static void ccm_magnifier_screen_iface_init (CCMScreenPluginClass * iface);
99
static void ccm_magnifier_window_iface_init (CCMWindowPluginClass * iface);
100
static void ccm_magnifier_on_option_changed (CCMPlugin * plugin, int index);
101
static void ccm_magnifier_on_new_frame (CCMMagnifier * self, int num_frame,
102
CCMTimeline * timeline);
104
CCM_DEFINE_PLUGIN_WITH_OPTIONS (CCMMagnifier, ccm_magnifier, CCM_TYPE_PLUGIN,
105
CCM_IMPLEMENT_INTERFACE (ccm_magnifier,
106
CCM_TYPE_SCREEN_PLUGIN,
107
ccm_magnifier_screen_iface_init);
108
CCM_IMPLEMENT_INTERFACE (ccm_magnifier,
109
CCM_TYPE_WINDOW_PLUGIN,
110
ccm_magnifier_window_iface_init))
111
struct _CCMMagnifierPrivate
117
cairo_surface_t * surface;
119
CCMKeybind * keybind;
121
cairo_surface_t * surface_window_info;
122
CCMTimeline * timeline;
125
#define CCM_MAGNIFIER_GET_PRIVATE(o) \
126
(G_TYPE_INSTANCE_GET_PRIVATE ((o), CCM_TYPE_MAGNIFIER, CCMMagnifierPrivate))
129
ccm_magnifier_options_init (CCMMagnifierOptions* self)
131
self->enabled = FALSE;
134
self->new_scale = 1.0f;
135
self->quality = CAIRO_FILTER_FAST;
136
self->shortcut = NULL;
138
bzero (&self->area, sizeof (cairo_rectangle_t));
139
bzero (&self->restrict_area, sizeof (cairo_rectangle_t));
143
ccm_magnifier_options_finalize (CCMMagnifierOptions* self)
145
if (self->shortcut) g_free(self->shortcut);
149
ccm_magnifier_options_get_restrict_area (CCMMagnifierOptions* self)
151
GError *error = NULL;
153
gdouble x, y, width, height;
154
CCMDisplay* display = ccm_display_get_default();
155
Screen* screen = ScreenOfDisplay(CCM_DISPLAY_XDISPLAY(display),
156
ccm_plugin_options_get_screen_num(CCM_PLUGIN_OPTIONS(self)));
158
real = ccm_config_get_integer (ccm_plugin_options_get_config(CCM_PLUGIN_OPTIONS(self),
159
CCM_MAGNIFIER_RESTRICT_AREA_WIDTH),
163
g_error_free (error);
169
self->restrict_area.width = screen->width;
174
val = MIN (screen->width, val);
176
ccm_config_set_integer (ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
177
CCM_MAGNIFIER_RESTRICT_AREA_WIDTH),
181
if (self->restrict_area.width != width)
182
self->restrict_area.width = width;
185
real = ccm_config_get_integer (ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
186
CCM_MAGNIFIER_RESTRICT_AREA_HEIGHT),
190
g_error_free (error);
196
self->restrict_area.height = screen->height;
201
val = MIN (screen->height, val);
203
ccm_config_set_integer (ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
204
CCM_MAGNIFIER_RESTRICT_AREA_HEIGHT),
208
if (self->restrict_area.height != height)
209
self->restrict_area.height = height;
212
real = ccm_config_get_integer (ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
213
CCM_MAGNIFIER_RESTRICT_AREA_X),
217
g_error_free (error);
223
self->restrict_area.x = 0;
228
val = MIN (self->restrict_area.width, val);
230
ccm_config_set_integer (ccm_plugin_options_get_config(CCM_PLUGIN_OPTIONS(self),
231
CCM_MAGNIFIER_RESTRICT_AREA_X),
235
if (self->restrict_area.x != x)
236
self->restrict_area.x = x;
239
real = ccm_config_get_integer (ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
240
CCM_MAGNIFIER_RESTRICT_AREA_Y),
244
g_error_free (error);
250
self->restrict_area.y = 0;
255
val = MIN (self->restrict_area.height, val);
257
ccm_config_set_integer (ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
258
CCM_MAGNIFIER_RESTRICT_AREA_Y),
262
if (self->restrict_area.y != y)
263
self->restrict_area.y = y;
268
ccm_magnifier_options_get_size (CCMMagnifierOptions* self)
270
GError *error = NULL;
272
gdouble x, y, width, height;
273
CCMDisplay* display = ccm_display_get_default();
274
Screen* screen = ScreenOfDisplay(CCM_DISPLAY_XDISPLAY(display),
275
ccm_plugin_options_get_screen_num(CCM_PLUGIN_OPTIONS(self)));
280
real = ccm_config_get_integer (ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
281
CCM_MAGNIFIER_WIDTH),
285
g_error_free (error);
289
val = MAX (10, real);
292
ccm_config_set_integer (ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
293
CCM_MAGNIFIER_WIDTH),
296
width = (gdouble) self->restrict_area.width * (gdouble) val / 100.0;
297
if (self->area.width != width)
298
self->area.width = width;
300
real = ccm_config_get_integer (ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
301
CCM_MAGNIFIER_HEIGHT),
305
g_error_free (error);
309
val = MAX (10, real);
311
if (real != val) ccm_config_set_integer (ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
312
CCM_MAGNIFIER_HEIGHT),
315
height = (gdouble) self->restrict_area.height * (gdouble) val / 100.0;
317
if (self->area.height != height)
318
self->area.height = height;
320
real = ccm_config_get_integer (ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
325
g_error_free (error);
331
self->area.x = (self->restrict_area.width - self->area.width) / 2;
336
val = MIN (screen->width, val);
338
ccm_config_set_integer (ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
343
if (self->area.x != x)
347
real = ccm_config_get_integer (ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
352
g_error_free (error);
358
self->area.y = (self->restrict_area.height - self->area.height) / 2;
363
val = MIN (screen->height, val);
365
ccm_config_set_integer (ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
370
if (self->area.y != y)
376
ccm_magnifier_options_changed (CCMMagnifierOptions* self, CCMConfig* config)
378
GError *error = NULL;
380
if (config == ccm_plugin_options_get_config(CCM_PLUGIN_OPTIONS(self),
381
CCM_MAGNIFIER_ENABLE))
383
self->enabled = ccm_config_get_boolean(config, NULL);
385
else if (config == ccm_plugin_options_get_config(CCM_PLUGIN_OPTIONS(self),
386
CCM_MAGNIFIER_ZOOM_LEVEL))
388
gfloat scale, real = ccm_config_get_float (config, &error);
392
g_error_free (error);
393
g_warning ("Error on get magnifier zoom level configuration value");
396
scale = MAX (1.0f, real);
397
scale = MIN (5.0f, scale);
398
if (real != scale) ccm_config_set_float (config, scale, NULL);
400
if (self->new_scale != scale) self->new_scale = scale;
402
else if (config == ccm_plugin_options_get_config(CCM_PLUGIN_OPTIONS(self),
403
CCM_MAGNIFIER_ZOOM_QUALITY))
405
gchar *quality = ccm_config_get_string (config, NULL);
409
if (self->quality != CAIRO_FILTER_FAST)
411
self->quality = CAIRO_FILTER_FAST;
412
ccm_config_set_string (config, "fast", NULL);
417
if (!g_ascii_strcasecmp (quality, "fast") &&
418
self->quality != CAIRO_FILTER_FAST)
420
self->quality = CAIRO_FILTER_FAST;
422
else if (!g_ascii_strcasecmp (quality, "good") &&
423
self->quality != CAIRO_FILTER_GOOD)
425
self->quality = CAIRO_FILTER_GOOD;
427
else if (!g_ascii_strcasecmp (quality, "best") &&
428
self->quality != CAIRO_FILTER_BEST)
430
self->quality = CAIRO_FILTER_BEST;
435
else if (config == ccm_plugin_options_get_config(CCM_PLUGIN_OPTIONS(self),
436
CCM_MAGNIFIER_SHORTCUT))
438
if (self->shortcut) g_free(self->shortcut);
439
self->shortcut = ccm_config_get_string (config, &error);
442
g_error_free (error);
443
g_warning ("Error on get magnifier shortcut configuration value");
444
self->shortcut = g_strdup ("<Super>F12");
447
else if (config == ccm_plugin_options_get_config(CCM_PLUGIN_OPTIONS(self),
448
CCM_MAGNIFIER_SHADE_DESKTOP))
450
self->shade = ccm_config_get_boolean (config, NULL);
452
else if (config == ccm_plugin_options_get_config(CCM_PLUGIN_OPTIONS(self),
453
CCM_MAGNIFIER_BORDER))
455
gint val, real = ccm_config_get_integer (config, NULL);
458
val = MIN (self->area.width, val);
459
val = MIN (self->area.height, val);
460
if (val != real) ccm_config_set_integer (config, val, NULL);
462
if (self->border != val) self->border = val;
464
else if (config == ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
465
CCM_MAGNIFIER_WIDTH) ||
466
config == ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
467
CCM_MAGNIFIER_HEIGHT) ||
468
config == ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
470
config == ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
472
config == ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
473
CCM_MAGNIFIER_RESTRICT_AREA_WIDTH) ||
474
config == ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
475
CCM_MAGNIFIER_RESTRICT_AREA_HEIGHT) ||
476
config == ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
477
CCM_MAGNIFIER_RESTRICT_AREA_X) ||
478
config == ccm_plugin_options_get_config (CCM_PLUGIN_OPTIONS(self),
479
CCM_MAGNIFIER_RESTRICT_AREA_Y))
481
ccm_magnifier_options_get_restrict_area (self);
482
ccm_magnifier_options_get_size (self);
487
ccm_magnifier_init (CCMMagnifier * self)
489
self->priv = CCM_MAGNIFIER_GET_PRIVATE (self);
490
self->priv->screen = NULL;
491
self->priv->x_offset = 0;
492
self->priv->y_offset = 0;
493
self->priv->surface = NULL;
494
self->priv->damaged = NULL;
495
self->priv->keybind = NULL;
497
self->priv->surface_window_info = NULL;
498
self->priv->timeline = NULL;
502
ccm_magnifier_finalize (GObject * object)
504
CCMMagnifier *self = CCM_MAGNIFIER (object);
506
if (self->priv->screen)
507
ccm_plugin_options_unload (CCM_PLUGIN (self));
509
if (self->priv->surface)
510
cairo_surface_destroy (self->priv->surface);
511
self->priv->surface = NULL;
512
if (self->priv->damaged)
513
ccm_region_destroy (self->priv->damaged);
514
self->priv->damaged = NULL;
515
if (self->priv->keybind)
516
g_object_unref (self->priv->keybind);
517
self->priv->keybind = NULL;
518
if (self->priv->surface_window_info)
519
cairo_surface_destroy (self->priv->surface_window_info);
520
self->priv->surface_window_info = NULL;
521
if (self->priv->timeline)
522
g_object_unref (self->priv->timeline);
523
self->priv->timeline = NULL;
525
G_OBJECT_CLASS (ccm_magnifier_parent_class)->finalize (object);
529
ccm_magnifier_class_init (CCMMagnifierClass * klass)
531
GObjectClass *object_class = G_OBJECT_CLASS (klass);
533
g_type_class_add_private (klass, sizeof (CCMMagnifierPrivate));
535
object_class->finalize = ccm_magnifier_finalize;
539
ccm_magnifier_set_enable (CCMMagnifier * self, gboolean enabled)
541
if (ccm_magnifier_get_option (self)->enabled != enabled)
543
ccm_magnifier_get_option (self)->enabled = enabled;
544
if (ccm_magnifier_get_option (self)->enabled)
546
ccm_screen_manage_cursors (self->priv->screen);
547
if (!self->priv->timeline)
549
self->priv->timeline = ccm_timeline_new_for_duration (3500);
550
g_object_set (G_OBJECT (self->priv->timeline), "fps", 30, NULL);
551
g_signal_connect_swapped (self->priv->timeline, "new-frame",
553
(ccm_magnifier_on_new_frame), self);
555
ccm_timeline_rewind (self->priv->timeline);
556
ccm_timeline_start (self->priv->timeline);
560
ccm_screen_unmanage_cursors (self->priv->screen);
561
if (self->priv->surface)
562
cairo_surface_destroy (self->priv->surface);
563
self->priv->surface = NULL;
564
if (self->priv->timeline)
565
ccm_timeline_stop (self->priv->timeline);
571
ccm_magnifier_on_key_press (CCMMagnifier * self)
573
g_return_if_fail (self != NULL);
577
if (ccm_screen_query_pointer (self->priv->screen, NULL, &x, &y))
580
ccm_config_get_boolean (ccm_magnifier_get_config
581
(self, CCM_MAGNIFIER_ENABLE),
583
ccm_config_set_boolean (ccm_magnifier_get_config
584
(self, CCM_MAGNIFIER_ENABLE), !enabled, NULL);
585
ccm_magnifier_set_enable (self, !enabled);
586
ccm_screen_damage (self->priv->screen);
591
ccm_magnifier_on_new_frame (CCMMagnifier * self, int num_frame,
592
CCMTimeline * timeline)
594
gdouble progress = ccm_timeline_get_progress (timeline);
596
if (progress <= 0.25 || progress >= 0.75)
598
cairo_rectangle_t geometry;
602
ccm_magnifier_get_option (self)->restrict_area.width *
603
(CCM_MAGNIFIER_WINDOW_INFO_WIDTH / 100.f);
605
ccm_magnifier_get_option (self)->restrict_area.height *
606
(CCM_MAGNIFIER_WINDOW_INFO_HEIGHT / 100.f);
608
(ccm_magnifier_get_option (self)->restrict_area.width -
612
area = ccm_region_rectangle (&geometry);
613
ccm_screen_damage_region (self->priv->screen, area);
614
ccm_region_destroy (area);
619
ccm_magnifier_get_keybind (CCMMagnifier * self)
621
if (self->priv->keybind)
622
g_object_unref (self->priv->keybind);
624
self->priv->keybind = ccm_keybind_new (self->priv->screen,
625
ccm_magnifier_get_option(self)->shortcut,
628
g_signal_connect_swapped (self->priv->keybind, "key_press",
629
G_CALLBACK (ccm_magnifier_on_key_press), self);
633
ccm_magnifier_get_scale (CCMMagnifier * self)
635
if (ccm_magnifier_get_option(self)->new_scale != ccm_magnifier_get_option(self)->scale)
637
if (self->priv->timeline
638
&& ccm_timeline_is_playing (self->priv->timeline))
640
gdouble progress = ccm_timeline_get_progress (self->priv->timeline);
642
ccm_timeline_advance (self->priv->timeline,
644
ccm_timeline_get_n_frames (self->priv->timeline));
646
else if (ccm_magnifier_get_option (self)->enabled)
648
if (!self->priv->timeline)
650
self->priv->timeline = ccm_timeline_new_for_duration (3500);
651
g_object_set (G_OBJECT (self->priv->timeline), "fps", 30, NULL);
652
g_signal_connect_swapped (self->priv->timeline, "new-frame",
654
(ccm_magnifier_on_new_frame), self);
656
ccm_timeline_start (self->priv->timeline);
657
ccm_timeline_rewind (self->priv->timeline);
659
cairo_surface_destroy (self->priv->surface_window_info);
660
self->priv->surface_window_info = NULL;
665
ccm_magnifier_create_window_info (CCMMagnifier * self)
668
PangoFontDescription *desc;
669
cairo_rectangle_t geometry;
673
CCMWindow *cow = ccm_screen_get_overlay_window (self->priv->screen);
674
cairo_surface_t *surface = ccm_drawable_get_surface (CCM_DRAWABLE (cow));
676
if (self->priv->surface_window_info)
677
cairo_surface_destroy (self->priv->surface_window_info);
679
self->priv->surface_window_info =
680
cairo_surface_create_similar (surface, CAIRO_CONTENT_COLOR_ALPHA,
681
ccm_magnifier_get_option (self)->
682
restrict_area.width *
683
(CCM_MAGNIFIER_WINDOW_INFO_WIDTH / 100.f),
684
ccm_magnifier_get_option (self)->
685
restrict_area.height *
686
(CCM_MAGNIFIER_WINDOW_INFO_HEIGHT /
688
cairo_surface_destroy (surface);
689
context = cairo_create (self->priv->surface_window_info);
690
cairo_set_operator (context, CAIRO_OPERATOR_CLEAR);
691
cairo_paint (context);
692
cairo_set_operator (context, CAIRO_OPERATOR_SOURCE);
695
ccm_magnifier_get_option (self)->restrict_area.width *
696
(CCM_MAGNIFIER_WINDOW_INFO_WIDTH / 100.f), geometry.height =
697
ccm_magnifier_get_option (self)->restrict_area.height *
698
(CCM_MAGNIFIER_WINDOW_INFO_HEIGHT / 100.f), geometry.x = 0, geometry.y =
701
cairo_rectangle_round (context, geometry.x, geometry.y, geometry.width,
703
CAIRO_CORNER_BOTTOMLEFT | CAIRO_CORNER_BOTTOMRIGHT);
704
cairo_set_source_rgba (context, 1.0f, 1.0f, 1.0f, 0.8f);
705
cairo_fill_preserve (context);
706
cairo_set_line_width (context, 2.0f);
707
cairo_set_source_rgba (context, 0.f, 0.f, 0.f, 1.0f);
708
cairo_stroke (context);
710
layout = pango_cairo_create_layout (context);
712
g_strdup_printf ("Zoom level = %i %%",
713
(int) (ccm_magnifier_get_option (self)->new_scale *
715
pango_layout_set_text (layout, text, -1);
717
desc = pango_font_description_from_string ("Sans Bold 18");
718
pango_layout_set_font_description (layout, desc);
719
pango_font_description_free (desc);
720
pango_layout_get_pixel_size (layout, &width, &height);
722
cairo_set_source_rgba (context, 0.0f, 0.0f, 0.0f, 1.0f);
723
pango_cairo_update_layout (context, layout);
724
cairo_move_to (context, (geometry.width - width) / 2.0f,
725
(geometry.height - height) / 2.0f);
726
pango_cairo_show_layout (context, layout);
727
g_object_unref (layout);
728
cairo_destroy (context);
732
ccm_magnifier_paint_window_info (CCMMagnifier * self, cairo_t * context)
734
if (self->priv->timeline && ccm_timeline_is_playing (self->priv->timeline))
736
if (!self->priv->surface_window_info)
738
ccm_magnifier_create_window_info (self);
741
if (self->priv->surface_window_info)
743
cairo_rectangle_t geometry;
744
gdouble progress = ccm_timeline_get_progress (self->priv->timeline);
747
ccm_magnifier_get_option (self)->restrict_area.width *
748
(CCM_MAGNIFIER_WINDOW_INFO_WIDTH / 100.f);
750
ccm_magnifier_get_option (self)->restrict_area.height *
751
(CCM_MAGNIFIER_WINDOW_INFO_HEIGHT / 100.f);
753
(ccm_magnifier_get_option (self)->restrict_area.width -
755
if (progress <= 0.25)
756
geometry.y = -geometry.height * (1 - (progress / 0.25));
757
else if (progress > 0.25 && progress < 0.75)
760
geometry.y = -geometry.height * ((progress - 0.75) / 0.25);
762
cairo_save (context);
763
cairo_translate (context, geometry.x, geometry.y);
764
cairo_set_source_surface (context, self->priv->surface_window_info,
766
cairo_paint (context);
767
cairo_restore (context);
773
ccm_magnifier_on_option_changed (CCMPlugin * plugin, int index)
775
CCMMagnifier *self = CCM_MAGNIFIER (plugin);
779
case CCM_MAGNIFIER_ENABLE:
780
ccm_screen_damage (self->priv->screen);
781
ccm_magnifier_set_enable (self,
782
ccm_magnifier_get_option(self)->enabled);
784
case CCM_MAGNIFIER_ZOOM_LEVEL:
785
ccm_magnifier_get_scale (self);
787
case CCM_MAGNIFIER_ZOOM_QUALITY:
788
ccm_screen_damage (self->priv->screen);
790
case CCM_MAGNIFIER_SHORTCUT:
791
ccm_magnifier_get_keybind (self);
793
case CCM_MAGNIFIER_BORDER:
794
ccm_screen_damage (self->priv->screen);
796
case CCM_MAGNIFIER_SHADE_DESKTOP:
797
ccm_screen_damage (self->priv->screen);
799
case CCM_MAGNIFIER_X:
800
case CCM_MAGNIFIER_Y:
801
case CCM_MAGNIFIER_WIDTH:
802
case CCM_MAGNIFIER_HEIGHT:
803
case CCM_MAGNIFIER_RESTRICT_AREA_X:
804
case CCM_MAGNIFIER_RESTRICT_AREA_Y:
805
case CCM_MAGNIFIER_RESTRICT_AREA_WIDTH:
806
case CCM_MAGNIFIER_RESTRICT_AREA_HEIGHT:
807
if (self->priv->surface)
808
cairo_surface_destroy (self->priv->surface);
809
self->priv->surface = NULL;
810
ccm_screen_damage (self->priv->screen);
818
ccm_magnifier_screen_load_options (CCMScreenPlugin * plugin, CCMScreen * screen)
820
CCMMagnifier *self = CCM_MAGNIFIER (plugin);
822
self->priv->screen = screen;
824
ccm_plugin_options_load (CCM_PLUGIN (self), "magnifier",
825
CCMMagnifierOptionKeys, CCM_MAGNIFIER_OPTION_N,
826
ccm_magnifier_on_option_changed);
828
ccm_screen_plugin_load_options (CCM_SCREEN_PLUGIN_PARENT (plugin), screen);
832
ccm_magnifier_screen_paint (CCMScreenPlugin * plugin, CCMScreen * screen,
835
CCMMagnifier *self = CCM_MAGNIFIER (plugin);
837
gboolean ret = FALSE;
839
if (ccm_magnifier_get_option (self)->enabled && !self->priv->surface)
841
CCMWindow *cow = ccm_screen_get_overlay_window (screen);
842
cairo_surface_t *surface =
843
ccm_drawable_get_surface (CCM_DRAWABLE (cow));
846
self->priv->surface =
847
cairo_surface_create_similar (surface, CAIRO_CONTENT_COLOR,
848
ccm_magnifier_get_option (self)->area.width /
849
ccm_magnifier_get_option (self)->scale,
850
ccm_magnifier_get_option (self)->area.height /
851
ccm_magnifier_get_option (self)->scale);
852
cairo_surface_destroy (surface);
853
ctx = cairo_create (self->priv->surface);
854
cairo_set_operator (ctx, CAIRO_OPERATOR_CLEAR);
859
if (ccm_magnifier_get_option (self)->enabled)
861
CCMRegion *area = ccm_region_rectangle (&ccm_magnifier_get_option (self)->area);
862
cairo_rectangle_t *rects = NULL;
866
ccm_debug ("MAGNIFIER PAINT SCREEN CLIP");
867
cairo_save (context);
870
ccm_region_rectangle (&ccm_magnifier_get_option (self)->
872
ccm_region_subtract (geometry, area);
874
ccm_region_get_rectangles (geometry, &rects, &nb_rects);
875
cairo_set_source_rgba (context, 0.0f, 0.0f, 0.0f, 0.6f);
876
for (cpt = 0; cpt < nb_rects; ++cpt)
877
cairo_rectangle (context, rects[cpt].x, rects[cpt].y,
878
rects[cpt].width, rects[cpt].height);
879
cairo_clip (context);
880
if (rects) cairo_rectangles_free (rects, nb_rects);
881
ccm_region_destroy (area);
882
ccm_region_destroy (geometry);
884
g_object_set (G_OBJECT (self->priv->screen), "buffered_pixmap", FALSE,
886
ccm_debug ("MAGNIFIER PAINT SCREEN");
890
ccm_screen_plugin_paint (CCM_SCREEN_PLUGIN_PARENT (plugin), screen,
893
if (ccm_magnifier_get_option (self)->enabled)
894
cairo_restore (context);
896
if (ret && ccm_magnifier_get_option (self)->enabled)
898
CCMRegion *area = ccm_region_rectangle (&ccm_magnifier_get_option (self)->area);
900
ccm_debug ("MAGNIFIER PAINT SCREEN CONTENT");
902
ccm_screen_remove_damaged_region (self->priv->screen, area);
904
if (ccm_magnifier_get_option (self)->shade)
906
CCMRegion *damaged = ccm_screen_get_damaged (self->priv->screen);
911
cairo_rectangle_t *rects = NULL;
913
ccm_debug ("MAGNIFIER PAINT SCREEN SHADE");
915
cairo_save (context);
916
cairo_rectangle (context,
917
ccm_magnifier_get_option (self)->restrict_area.
919
ccm_magnifier_get_option (self)->restrict_area.
921
ccm_magnifier_get_option (self)->restrict_area.
923
ccm_magnifier_get_option (self)->restrict_area.
925
cairo_clip (context);
926
ccm_region_get_rectangles (damaged, &rects, &nb_rects);
927
cairo_set_source_rgba (context, 0.0f, 0.0f, 0.0f, 0.6f);
928
for (cpt = 0; cpt < nb_rects; ++cpt)
930
cairo_rectangle (context, rects[cpt].x, rects[cpt].y,
931
rects[cpt].width, rects[cpt].height);
932
cairo_fill (context);
934
if (rects) cairo_rectangles_free (rects, nb_rects);
935
cairo_restore (context);
937
cairo_save (context);
938
cairo_rectangle (context, ccm_magnifier_get_option (self)->area.x - 8,
939
ccm_magnifier_get_option (self)->area.y - 8,
940
ccm_magnifier_get_option (self)->area.width + 16, 8);
941
cairo_rectangle (context, ccm_magnifier_get_option (self)->area.x - 8,
942
ccm_magnifier_get_option (self)->area.y +
943
ccm_magnifier_get_option (self)->area.height,
944
ccm_magnifier_get_option (self)->area.width + 16, 8);
945
cairo_rectangle (context, ccm_magnifier_get_option (self)->area.x - 8,
946
ccm_magnifier_get_option (self)->area.y - 8, 8,
947
ccm_magnifier_get_option (self)->area.height + 16);
948
cairo_rectangle (context,
949
ccm_magnifier_get_option (self)->area.x +
950
ccm_magnifier_get_option (self)->area.width,
951
ccm_magnifier_get_option (self)->area.y - 8, 8,
952
ccm_magnifier_get_option (self)->area.height + 16);
953
cairo_clip (context);
955
cairo_set_source_rgba (context, 1.0f, 1.0f, 1.0f, 0.8f);
956
cairo_rectangle_round (context, ccm_magnifier_get_option (self)->area.x - 8,
957
ccm_magnifier_get_option (self)->area.y - 8,
958
ccm_magnifier_get_option (self)->area.width + 16,
959
ccm_magnifier_get_option (self)->area.height + 16, 10.0f,
961
cairo_fill (context);
962
cairo_set_source_rgba (context, 0.0f, 0.0f, 0.0f, 0.9f);
963
cairo_rectangle (context, ccm_magnifier_get_option (self)->area.x - 1,
964
ccm_magnifier_get_option (self)->area.y - 1,
965
ccm_magnifier_get_option (self)->area.width + 2,
966
ccm_magnifier_get_option (self)->area.height + 2);
967
cairo_fill (context);
968
cairo_restore (context);
970
ccm_magnifier_paint_window_info (self, context);
974
if (self->priv->damaged)
977
cairo_rectangle_t *rects = NULL;
978
cairo_pattern_t *pattern;
980
ccm_debug ("MAGNIFIER PAINT SCREEN FILL CONTENT");
982
ccm_screen_add_damaged_region (screen, self->priv->damaged);
984
cairo_save (context);
986
ccm_debug ("MAGNIFIER PAINT SCREEN FILL TRANSLATE SCALE");
988
ccm_region_get_rectangles (self->priv->damaged, &rects, &nb_rects);
989
for (cpt = 0; cpt < nb_rects; ++cpt)
990
cairo_rectangle (context, rects[cpt].x, rects[cpt].y,
991
rects[cpt].width, rects[cpt].height);
992
if (rects) cairo_rectangles_free (rects, nb_rects);
993
cairo_clip (context);
995
ccm_debug ("MAGNIFIER PAINT SCREEN FILL CLIP");
997
cairo_translate (context, ccm_magnifier_get_option (self)->area.x,
998
ccm_magnifier_get_option (self)->area.y);
999
cairo_scale (context, ccm_magnifier_get_option (self)->scale,
1000
ccm_magnifier_get_option (self)->scale);
1001
cairo_set_source_surface (context, self->priv->surface, 0, 0);
1002
pattern = cairo_get_source (context);
1003
cairo_pattern_set_filter (pattern,
1004
ccm_magnifier_get_option (self)->quality);
1005
cairo_paint (context);
1007
ccm_debug ("MAGNIFIER PAINT SCREEN FILL PAINT");
1009
cairo_restore (context);
1011
ccm_region_destroy (self->priv->damaged);
1012
self->priv->damaged = NULL;
1014
ccm_debug ("MAGNIFIER PAINT SCREEN END");
1016
ccm_region_destroy (area);
1019
if (ccm_magnifier_get_option (self)->scale !=
1020
ccm_magnifier_get_option (self)->new_scale)
1022
ccm_magnifier_get_option (self)->scale =
1023
ccm_magnifier_get_option (self)->new_scale;
1024
if (self->priv->surface)
1025
cairo_surface_destroy (self->priv->surface);
1026
self->priv->surface = NULL;
1033
ccm_magnifier_screen_on_cursor_move (CCMScreenPlugin * plugin,
1034
CCMScreen * screen, int x, int y)
1036
CCMMagnifier *self = CCM_MAGNIFIER (plugin);
1038
if (ccm_magnifier_get_option (self)->enabled)
1040
CCMDisplay *display = ccm_screen_get_display (screen);
1042
(CCMCursor *) ccm_display_get_current_cursor (display, FALSE);
1043
gboolean damaged = FALSE;
1047
double width = ccm_cursor_get_width (cursor);
1048
double height = ccm_cursor_get_height (cursor);
1050
if (self->priv->x_offset >
1051
x - ccm_magnifier_get_option (self)->border)
1053
self->priv->x_offset =
1054
MAX (ccm_magnifier_get_option (self)->restrict_area.x,
1055
x - ccm_magnifier_get_option (self)->border);
1058
if (self->priv->y_offset >
1059
y - ccm_magnifier_get_option (self)->border)
1061
self->priv->y_offset =
1062
MAX (ccm_magnifier_get_option (self)->restrict_area.y,
1063
y - ccm_magnifier_get_option (self)->border);
1066
if (self->priv->x_offset +
1067
(ccm_magnifier_get_option (self)->area.width /
1068
ccm_magnifier_get_option (self)->scale) <
1069
x + width + ccm_magnifier_get_option (self)->border)
1071
self->priv->x_offset =
1072
x + ccm_magnifier_get_option (self)->border + width -
1073
(ccm_magnifier_get_option (self)->area.width /
1074
ccm_magnifier_get_option (self)->scale);
1075
if (self->priv->x_offset +
1076
(ccm_magnifier_get_option (self)->area.width /
1077
ccm_magnifier_get_option (self)->scale) >
1078
ccm_magnifier_get_option (self)->restrict_area.width)
1079
self->priv->x_offset =
1080
ccm_magnifier_get_option (self)->restrict_area.width -
1081
(ccm_magnifier_get_option (self)->area.width /
1082
ccm_magnifier_get_option (self)->scale);
1085
if (self->priv->y_offset +
1086
(ccm_magnifier_get_option (self)->area.height /
1087
ccm_magnifier_get_option (self)->scale) <
1088
y + height + ccm_magnifier_get_option (self)->border)
1090
self->priv->y_offset =
1091
y + ccm_magnifier_get_option (self)->border + height -
1092
(ccm_magnifier_get_option (self)->area.height /
1093
ccm_magnifier_get_option (self)->scale);
1094
if (self->priv->y_offset +
1095
(ccm_magnifier_get_option (self)->area.height /
1096
ccm_magnifier_get_option (self)->scale) >
1097
ccm_magnifier_get_option (self)->restrict_area.height)
1098
self->priv->y_offset =
1099
ccm_magnifier_get_option (self)->restrict_area.height -
1100
(ccm_magnifier_get_option (self)->area.height /
1101
ccm_magnifier_get_option (self)->scale);
1109
cairo_rectangle_t area;
1111
area.x = self->priv->x_offset;
1112
area.y = self->priv->y_offset;
1113
area.width = ccm_magnifier_get_option (self)->area.width /
1114
ccm_magnifier_get_option (self)->scale;
1115
area.height = ccm_magnifier_get_option (self)->area.height /
1116
ccm_magnifier_get_option (self)->scale;
1117
damage = ccm_region_rectangle (&area);
1118
ccm_debug ("MAGNIFIER POSITION CHANGED");
1119
ccm_screen_damage_region (self->priv->screen, damage);
1120
ccm_region_destroy (damage);
1124
ccm_screen_plugin_on_cursor_move (CCM_SCREEN_PLUGIN_PARENT (plugin), screen,
1129
ccm_magnifier_screen_paint_cursor (CCMScreenPlugin * plugin, CCMScreen * screen,
1130
cairo_t * context, int x, int y)
1132
CCMMagnifier *self = CCM_MAGNIFIER (plugin);
1133
CCMDisplay *display = ccm_screen_get_display (screen);
1135
(CCMCursor *) ccm_display_get_current_cursor (display, FALSE);
1139
cairo_save (context);
1140
cairo_translate (context, ccm_magnifier_get_option (self)->area.x,
1141
ccm_magnifier_get_option (self)->area.y);
1142
cairo_scale (context, ccm_magnifier_get_option (self)->scale,
1143
ccm_magnifier_get_option (self)->scale);
1144
ccm_cursor_paint (cursor, context, x - self->priv->x_offset,
1145
y - self->priv->y_offset);
1146
cairo_restore (context);
1151
ccm_magnifier_window_paint (CCMWindowPlugin * plugin, CCMWindow * window,
1152
cairo_t * context, cairo_surface_t * surface,
1155
CCMScreen *screen = ccm_drawable_get_screen (CCM_DRAWABLE (window));
1156
CCMMagnifier *self = CCM_MAGNIFIER (_ccm_screen_get_plugin (screen,
1157
CCM_TYPE_MAGNIFIER));
1158
if (ccm_magnifier_get_option (self)->enabled)
1160
CCMRegion *damaged = (CCMRegion*)
1161
ccm_drawable_get_damaged(CCM_DRAWABLE(window));
1165
CCMRegion *area = ccm_region_rectangle (&ccm_magnifier_get_option (self)->area);
1166
CCMRegion *tmp = ccm_region_copy (damaged);
1167
cairo_matrix_t matrix;
1169
cairo_matrix_init_scale (&matrix,
1170
ccm_magnifier_get_option (self)->scale,
1171
ccm_magnifier_get_option (self)->scale);
1172
cairo_matrix_translate (&matrix, -self->priv->x_offset,
1173
-self->priv->y_offset);
1174
ccm_region_transform (tmp, &matrix);
1175
cairo_matrix_init_translate (&matrix, ccm_magnifier_get_option (self)->area.x,
1176
ccm_magnifier_get_option (self)->area.y);
1177
ccm_region_transform (tmp, &matrix);
1178
ccm_region_intersect (tmp, area);
1180
if (!ccm_region_empty (tmp))
1182
cairo_t *ctx = cairo_create (self->priv->surface);
1183
cairo_matrix_t translate;
1185
ccm_debug_window (window, "MAGNIFIER PAINT WINDOW");
1187
if (!self->priv->damaged)
1188
self->priv->damaged = ccm_region_copy (tmp);
1190
ccm_region_union (self->priv->damaged, tmp);
1192
cairo_rectangle (ctx, 0, 0,
1193
ccm_magnifier_get_option (self)->area.width /
1194
ccm_magnifier_get_option (self)->scale,
1195
ccm_magnifier_get_option (self)->area.height /
1196
ccm_magnifier_get_option (self)->scale);
1199
cairo_matrix_init_translate (&translate, -self->priv->x_offset,
1200
-self->priv->y_offset);
1202
cairo_translate (ctx, -self->priv->x_offset, -self->priv->y_offset);
1203
ccm_drawable_get_damage_path (CCM_DRAWABLE (window), ctx);
1206
ccm_window_set_redirect(window, FALSE);
1207
ccm_drawable_push_matrix (CCM_DRAWABLE (window), "CCMMagnifier",
1210
ccm_window_plugin_paint (CCM_WINDOW_PLUGIN_PARENT (plugin), window,
1211
ctx, surface, y_invert);
1212
cairo_destroy (ctx);
1213
ccm_drawable_pop_matrix (CCM_DRAWABLE (window), "CCMMagnifier");
1214
ccm_window_set_redirect(window, TRUE);
1217
ccm_region_destroy (tmp);
1218
ccm_region_destroy (area);
1222
return ccm_window_plugin_paint (CCM_WINDOW_PLUGIN_PARENT (plugin), window,
1223
context, surface, y_invert);
1227
ccm_magnifier_screen_iface_init (CCMScreenPluginClass * iface)
1229
iface->load_options = ccm_magnifier_screen_load_options;
1230
iface->paint = ccm_magnifier_screen_paint;
1231
iface->add_window = NULL;
1232
iface->remove_window = NULL;
1233
iface->damage = NULL;
1234
iface->on_cursor_move = ccm_magnifier_screen_on_cursor_move;
1235
iface->paint_cursor = ccm_magnifier_screen_paint_cursor;
1239
ccm_magnifier_window_iface_init (CCMWindowPluginClass * iface)
1241
iface->load_options = NULL;
1242
iface->query_geometry = NULL;
1243
iface->paint = ccm_magnifier_window_paint;
1245
iface->unmap = NULL;
1246
iface->query_opacity = NULL;
1248
iface->resize = NULL;
1249
iface->set_opaque_region = NULL;
1250
iface->get_origin = NULL;