2010-06-24 20:41:28 +02:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
|
|
|
/* Mutter tile-preview marks the area a window will *ehm* snap to */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2010 Florian Müllner
|
|
|
|
*
|
|
|
|
* 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, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
* 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include <cairo.h>
|
|
|
|
|
|
|
|
#include "tile-preview.h"
|
|
|
|
#include "core.h"
|
|
|
|
|
|
|
|
#define OUTLINE_WIDTH 5 /* frame width in non-composite case */
|
|
|
|
|
|
|
|
|
|
|
|
struct _MetaTilePreview {
|
|
|
|
GtkWidget *preview_window;
|
|
|
|
gulong create_serial;
|
|
|
|
|
2010-12-09 14:52:16 +01:00
|
|
|
GdkRGBA *preview_color;
|
2010-06-24 20:41:28 +02:00
|
|
|
|
|
|
|
MetaRectangle tile_rect;
|
|
|
|
};
|
|
|
|
|
2010-09-24 13:30:40 +02:00
|
|
|
static gboolean
|
|
|
|
meta_tile_preview_draw (GtkWidget *widget,
|
|
|
|
cairo_t *cr,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
2010-06-24 20:41:28 +02:00
|
|
|
MetaTilePreview *preview = user_data;
|
|
|
|
|
|
|
|
cairo_set_line_width (cr, 1.0);
|
|
|
|
|
2011-12-12 20:14:44 +01:00
|
|
|
/* Fill the preview area with a transparent color */
|
|
|
|
gdk_cairo_set_source_rgba (cr, preview->preview_color);
|
|
|
|
|
|
|
|
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
|
|
|
cairo_paint (cr);
|
|
|
|
|
|
|
|
/* Use the opaque color for the border */
|
|
|
|
cairo_set_source_rgb (cr,
|
|
|
|
preview->preview_color->red,
|
|
|
|
preview->preview_color->green,
|
|
|
|
preview->preview_color->blue);
|
2010-06-24 20:41:28 +02:00
|
|
|
|
|
|
|
cairo_rectangle (cr,
|
|
|
|
0.5, 0.5,
|
|
|
|
preview->tile_rect.width - 1,
|
|
|
|
preview->tile_rect.height - 1);
|
|
|
|
cairo_stroke (cr);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
MetaTilePreview *
|
2011-12-12 20:14:44 +01:00
|
|
|
meta_tile_preview_new (int screen_number)
|
2010-06-24 20:41:28 +02:00
|
|
|
{
|
|
|
|
MetaTilePreview *preview;
|
|
|
|
GdkScreen *screen;
|
2011-12-12 20:14:44 +01:00
|
|
|
GtkStyleContext *context;
|
|
|
|
GtkWidgetPath *path;
|
|
|
|
guchar selection_alpha = 0xFF;
|
2010-06-24 20:41:28 +02:00
|
|
|
|
|
|
|
screen = gdk_display_get_screen (gdk_display_get_default (), screen_number);
|
|
|
|
|
|
|
|
preview = g_new (MetaTilePreview, 1);
|
|
|
|
|
|
|
|
preview->preview_window = gtk_window_new (GTK_WINDOW_POPUP);
|
|
|
|
|
|
|
|
gtk_window_set_screen (GTK_WINDOW (preview->preview_window), screen);
|
|
|
|
gtk_widget_set_app_paintable (preview->preview_window, TRUE);
|
|
|
|
|
|
|
|
preview->preview_color = NULL;
|
|
|
|
|
|
|
|
preview->tile_rect.x = preview->tile_rect.y = 0;
|
|
|
|
preview->tile_rect.width = preview->tile_rect.height = 0;
|
|
|
|
|
2011-12-12 20:14:44 +01:00
|
|
|
gtk_widget_set_visual (preview->preview_window,
|
|
|
|
gdk_screen_get_rgba_visual (screen));
|
2010-12-09 14:52:16 +01:00
|
|
|
|
2011-12-12 20:14:44 +01:00
|
|
|
path = gtk_widget_path_new ();
|
|
|
|
gtk_widget_path_append_type (path, GTK_TYPE_ICON_VIEW);
|
2010-06-24 20:41:28 +02:00
|
|
|
|
2011-12-12 20:14:44 +01:00
|
|
|
context = gtk_style_context_new ();
|
|
|
|
gtk_style_context_set_path (context, path);
|
|
|
|
gtk_style_context_add_class (context,
|
|
|
|
GTK_STYLE_CLASS_RUBBERBAND);
|
2010-12-09 14:52:16 +01:00
|
|
|
|
2011-12-12 20:14:44 +01:00
|
|
|
gtk_widget_path_free (path);
|
2010-12-09 14:52:16 +01:00
|
|
|
|
2011-12-12 20:14:44 +01:00
|
|
|
gtk_style_context_get (context, GTK_STATE_FLAG_SELECTED,
|
|
|
|
"background-color", &preview->preview_color,
|
|
|
|
NULL);
|
2010-12-09 14:52:16 +01:00
|
|
|
|
2011-12-12 20:14:44 +01:00
|
|
|
/* The background-color for the .rubberband class should probably
|
|
|
|
* contain the correct alpha value - unfortunately, at least for now
|
|
|
|
* it doesn't. Hopefully the following workaround can be removed
|
|
|
|
* when GtkIconView gets ported to GtkStyleContext.
|
|
|
|
*/
|
|
|
|
gtk_style_context_get_style (context,
|
|
|
|
"selection-box-alpha", &selection_alpha,
|
|
|
|
NULL);
|
|
|
|
preview->preview_color->alpha = (double)selection_alpha / 0xFF;
|
2010-12-09 14:52:16 +01:00
|
|
|
|
2011-12-12 20:14:44 +01:00
|
|
|
g_object_unref (context);
|
2010-06-24 20:41:28 +02:00
|
|
|
|
|
|
|
/* We make an assumption that XCreateWindow will be the first operation
|
|
|
|
* when calling gtk_widget_realize() (via gdk_window_new()), or that it
|
|
|
|
* is at least "close enough".
|
|
|
|
*/
|
|
|
|
preview->create_serial = XNextRequest (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
|
|
|
gtk_widget_realize (preview->preview_window);
|
2010-09-24 13:30:40 +02:00
|
|
|
g_signal_connect (preview->preview_window, "draw",
|
|
|
|
G_CALLBACK (meta_tile_preview_draw), preview);
|
2010-06-24 20:41:28 +02:00
|
|
|
|
|
|
|
return preview;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_tile_preview_free (MetaTilePreview *preview)
|
|
|
|
{
|
|
|
|
gtk_widget_destroy (preview->preview_window);
|
|
|
|
|
|
|
|
if (preview->preview_color)
|
2010-12-09 14:52:16 +01:00
|
|
|
gdk_rgba_free (preview->preview_color);
|
2010-06-24 20:41:28 +02:00
|
|
|
|
|
|
|
g_free (preview);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_tile_preview_show (MetaTilePreview *preview,
|
core: Keep track of per pointer/keyboard grabs
There is now a MetaGrabInfo struct, holding all information about
an ongoing grab, there were unfortunately no means of making this
commit smaller, as things are too intertwined to separate it,
On places where it was most obvious, the correct device has been
used (in reaction to events, for example), in other parts, the
private API has been extended to include the MetaDevice (or device
ID for core.h functions), in other places, the virtual core
pointer/keyboard are used out of cluelessness.
2011-06-19 00:55:10 +02:00
|
|
|
MetaDevice *pointer,
|
2010-06-24 20:41:28 +02:00
|
|
|
MetaRectangle *tile_rect)
|
|
|
|
{
|
|
|
|
GdkWindow *window;
|
|
|
|
GdkRectangle old_rect;
|
|
|
|
|
|
|
|
if (gtk_widget_get_visible (preview->preview_window)
|
|
|
|
&& preview->tile_rect.x == tile_rect->x
|
|
|
|
&& preview->tile_rect.y == tile_rect->y
|
|
|
|
&& preview->tile_rect.width == tile_rect->width
|
|
|
|
&& preview->tile_rect.height == tile_rect->height)
|
|
|
|
return; /* nothing to do */
|
|
|
|
|
|
|
|
gtk_widget_show (preview->preview_window);
|
|
|
|
window = gtk_widget_get_window (preview->preview_window);
|
2011-05-20 17:41:19 +02:00
|
|
|
meta_core_lower_beneath_grab_window (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
|
|
|
GDK_WINDOW_XID (window),
|
core: Keep track of per pointer/keyboard grabs
There is now a MetaGrabInfo struct, holding all information about
an ongoing grab, there were unfortunately no means of making this
commit smaller, as things are too intertwined to separate it,
On places where it was most obvious, the correct device has been
used (in reaction to events, for example), in other parts, the
private API has been extended to include the MetaDevice (or device
ID for core.h functions), in other places, the virtual core
pointer/keyboard are used out of cluelessness.
2011-06-19 00:55:10 +02:00
|
|
|
meta_device_get_id (pointer),
|
2011-05-20 17:41:19 +02:00
|
|
|
gtk_get_current_event_time ());
|
2010-06-24 20:41:28 +02:00
|
|
|
|
|
|
|
old_rect.x = old_rect.y = 0;
|
|
|
|
old_rect.width = preview->tile_rect.width;
|
|
|
|
old_rect.height = preview->tile_rect.height;
|
|
|
|
|
|
|
|
gdk_window_invalidate_rect (window, &old_rect, FALSE);
|
|
|
|
|
|
|
|
preview->tile_rect = *tile_rect;
|
|
|
|
|
|
|
|
gdk_window_move_resize (window,
|
|
|
|
preview->tile_rect.x, preview->tile_rect.y,
|
|
|
|
preview->tile_rect.width, preview->tile_rect.height);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_tile_preview_hide (MetaTilePreview *preview)
|
|
|
|
{
|
|
|
|
gtk_widget_hide (preview->preview_window);
|
|
|
|
}
|
|
|
|
|
|
|
|
Window
|
|
|
|
meta_tile_preview_get_xwindow (MetaTilePreview *preview,
|
|
|
|
gulong *create_serial)
|
|
|
|
{
|
|
|
|
GdkWindow *window = gtk_widget_get_window (preview->preview_window);
|
|
|
|
|
|
|
|
if (create_serial)
|
|
|
|
*create_serial = preview->create_serial;
|
|
|
|
|
2010-12-02 15:51:36 +01:00
|
|
|
return GDK_WINDOW_XID (window);
|
2010-06-24 20:41:28 +02:00
|
|
|
}
|