1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
3
/* Mutter tile-preview marks the area a window will *ehm* snap to */
6
* Copyright (C) 2010 Florian Müllner
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public License as
10
* published by the Free Software Foundation; either version 2 of the
11
* License, or (at your option) any later version.
13
* This program is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
29
#include "tile-preview.h"
32
#define OUTLINE_WIDTH 5 /* frame width in non-composite case */
35
struct _MetaTilePreview {
36
GtkWidget *preview_window;
39
GdkColor *preview_color;
42
MetaRectangle tile_rect;
44
gboolean has_alpha: 1;
48
meta_tile_preview_draw (GtkWidget *widget,
52
MetaTilePreview *preview = user_data;
54
cairo_set_line_width (cr, 1.0);
56
if (preview->has_alpha)
58
/* Fill the preview area with a transparent color */
59
cairo_set_source_rgba (cr,
60
(double)preview->preview_color->red / 0xFFFF,
61
(double)preview->preview_color->green / 0xFFFF,
62
(double)preview->preview_color->blue / 0xFFFF,
63
(double)preview->preview_alpha / 0xFF);
65
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
68
/* Use the opaque color for the border */
69
gdk_cairo_set_source_color (cr, preview->preview_color);
73
GtkStyle *style = gtk_widget_get_style (preview->preview_window);
75
gdk_cairo_set_source_color (cr, &style->white);
78
OUTLINE_WIDTH - 0.5, OUTLINE_WIDTH - 0.5,
79
preview->tile_rect.width - 2 * (OUTLINE_WIDTH - 1) - 1,
80
preview->tile_rect.height - 2 * (OUTLINE_WIDTH - 1) - 1);
86
preview->tile_rect.width - 1,
87
preview->tile_rect.height - 1);
94
on_preview_window_style_set (GtkWidget *widget,
98
MetaTilePreview *preview = user_data;
101
style = gtk_rc_get_style_by_paths (gtk_widget_get_settings (widget),
102
"GtkWindow.GtkIconView",
103
"GtkWindow.GtkIconView",
107
g_object_ref (style);
109
style = gtk_style_new ();
111
gtk_style_get (style, GTK_TYPE_ICON_VIEW,
112
"selection-box-color", &preview->preview_color,
113
"selection-box-alpha", &preview->preview_alpha,
115
if (!preview->preview_color)
117
GdkColor selection = style->base[GTK_STATE_SELECTED];
118
preview->preview_color = gdk_color_copy (&selection);
121
g_object_unref (style);
125
meta_tile_preview_new (int screen_number,
128
MetaTilePreview *preview;
131
screen = gdk_display_get_screen (gdk_display_get_default (), screen_number);
133
preview = g_new (MetaTilePreview, 1);
135
preview->preview_window = gtk_window_new (GTK_WINDOW_POPUP);
137
gtk_window_set_screen (GTK_WINDOW (preview->preview_window), screen);
138
gtk_widget_set_app_paintable (preview->preview_window, TRUE);
140
preview->preview_color = NULL;
141
preview->preview_alpha = 0xFF;
143
preview->tile_rect.x = preview->tile_rect.y = 0;
144
preview->tile_rect.width = preview->tile_rect.height = 0;
146
preview->has_alpha = composited &&
147
(gdk_screen_get_rgba_visual (screen) != NULL);
149
if (preview->has_alpha)
151
gtk_widget_set_visual (preview->preview_window,
152
gdk_screen_get_rgba_visual (screen));
154
g_signal_connect (preview->preview_window, "style-set",
155
G_CALLBACK (on_preview_window_style_set), preview);
158
/* We make an assumption that XCreateWindow will be the first operation
159
* when calling gtk_widget_realize() (via gdk_window_new()), or that it
160
* is at least "close enough".
162
preview->create_serial = XNextRequest (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
163
gtk_widget_realize (preview->preview_window);
164
g_signal_connect (preview->preview_window, "draw",
165
G_CALLBACK (meta_tile_preview_draw), preview);
171
meta_tile_preview_free (MetaTilePreview *preview)
173
gtk_widget_destroy (preview->preview_window);
175
if (preview->preview_color)
176
gdk_color_free (preview->preview_color);
182
meta_tile_preview_show (MetaTilePreview *preview,
183
MetaRectangle *tile_rect)
186
GdkRectangle old_rect;
188
if (gtk_widget_get_visible (preview->preview_window)
189
&& preview->tile_rect.x == tile_rect->x
190
&& preview->tile_rect.y == tile_rect->y
191
&& preview->tile_rect.width == tile_rect->width
192
&& preview->tile_rect.height == tile_rect->height)
193
return; /* nothing to do */
195
gtk_widget_show (preview->preview_window);
196
window = gtk_widget_get_window (preview->preview_window);
197
meta_core_lower_beneath_focus_window (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
198
GDK_WINDOW_XWINDOW (window),
199
gtk_get_current_event_time ());
201
old_rect.x = old_rect.y = 0;
202
old_rect.width = preview->tile_rect.width;
203
old_rect.height = preview->tile_rect.height;
205
gdk_window_invalidate_rect (window, &old_rect, FALSE);
207
preview->tile_rect = *tile_rect;
209
gdk_window_move_resize (window,
210
preview->tile_rect.x, preview->tile_rect.y,
211
preview->tile_rect.width, preview->tile_rect.height);
213
if (!preview->has_alpha)
215
cairo_region_t *outer_region, *inner_region;
216
GdkRectangle outer_rect, inner_rect;
219
black = gtk_widget_get_style (preview->preview_window)->black;
220
gdk_window_set_background (window, &black);
222
outer_rect.x = outer_rect.y = 0;
223
outer_rect.width = preview->tile_rect.width;
224
outer_rect.height = preview->tile_rect.height;
226
inner_rect.x = OUTLINE_WIDTH;
227
inner_rect.y = OUTLINE_WIDTH;
228
inner_rect.width = outer_rect.width - 2 * OUTLINE_WIDTH;
229
inner_rect.height = outer_rect.height - 2 * OUTLINE_WIDTH;
231
outer_region = cairo_region_create_rectangle (&outer_rect);
232
inner_region = cairo_region_create_rectangle (&inner_rect);
234
cairo_region_subtract (outer_region, inner_region);
235
cairo_region_destroy (inner_region);
237
gdk_window_shape_combine_region (window, outer_region, 0, 0);
238
cairo_region_destroy (outer_region);
243
meta_tile_preview_hide (MetaTilePreview *preview)
245
gtk_widget_hide (preview->preview_window);
249
meta_tile_preview_get_xwindow (MetaTilePreview *preview,
250
gulong *create_serial)
252
GdkWindow *window = gtk_widget_get_window (preview->preview_window);
255
*create_serial = preview->create_serial;
257
return GDK_WINDOW_XWINDOW (window);