Support input shapes: (#331070)

2006-02-19  Matthias Clasen  <mclasen@redhat.com>

	Support input shapes:  (#331070)

	* gdk/gdk.symbols:
	* gdk/gdkdisplay.h:
	* gdk/gdkwindow.h:
	* gdk/x11/gdkdisplay-x11.c (gdk_display_supports_shapes)
	(gdk_display_supports_input_shapes): Functions to determine
	if a display supports shaped windows or input shapes.

	* gdk/x11/gdkwindow-x11.c (gdk_window_input_shape_combine_region):
	(gdk_window_input_shape_combine_mask):
	(gdk_window_set_child_input_shapes):
	(gdk_window_merge_child_input_shapes): Input shape versions
	of the window shape API.

	* gtk/gtk.symbols:
	* gtk/gtkwidget.h:
	* gtk/gtkwidget.c (gtk_widget_input_shape_combine_mask):
	New function to set an input shape on a widget.
This commit is contained in:
Matthias Clasen 2006-02-20 01:36:50 +00:00 committed by Matthias Clasen
parent 2447b0365e
commit 1ad93a683b
10 changed files with 423 additions and 105 deletions

View File

@ -1,3 +1,25 @@
2006-02-19 Matthias Clasen <mclasen@redhat.com>
Support input shapes: (#331070)
* gdk/gdk.symbols:
* gdk/gdkdisplay.h:
* gdk/gdkwindow.h:
* gdk/x11/gdkdisplay-x11.c (gdk_display_supports_shapes)
(gdk_display_supports_input_shapes): Functions to determine
if a display supports shaped windows or input shapes.
* gdk/x11/gdkwindow-x11.c (gdk_window_input_shape_combine_region):
(gdk_window_input_shape_combine_mask):
(gdk_window_set_child_input_shapes):
(gdk_window_merge_child_input_shapes): Input shape versions
of the window shape API.
* gtk/gtk.symbols:
* gtk/gtkwidget.h:
* gtk/gtkwidget.c (gtk_widget_input_shape_combine_mask):
New function to set an input shape on a widget.
2006-02-19 Matthias Clasen <mclasen@redhat.com> 2006-02-19 Matthias Clasen <mclasen@redhat.com>
* gtk/gtklinkbutton.c (gtk_link_button_class_init): Fix * gtk/gtklinkbutton.c (gtk_link_button_class_init): Fix

View File

@ -1,3 +1,25 @@
2006-02-19 Matthias Clasen <mclasen@redhat.com>
Support input shapes: (#331070)
* gdk/gdk.symbols:
* gdk/gdkdisplay.h:
* gdk/gdkwindow.h:
* gdk/x11/gdkdisplay-x11.c (gdk_display_supports_shapes)
(gdk_display_supports_input_shapes): Functions to determine
if a display supports shaped windows or input shapes.
* gdk/x11/gdkwindow-x11.c (gdk_window_input_shape_combine_region):
(gdk_window_input_shape_combine_mask):
(gdk_window_set_child_input_shapes):
(gdk_window_merge_child_input_shapes): Input shape versions
of the window shape API.
* gtk/gtk.symbols:
* gtk/gtkwidget.h:
* gtk/gtkwidget.c (gtk_widget_input_shape_combine_mask):
New function to set an input shape on a widget.
2006-02-19 Matthias Clasen <mclasen@redhat.com> 2006-02-19 Matthias Clasen <mclasen@redhat.com>
* gtk/gtklinkbutton.c (gtk_link_button_class_init): Fix * gtk/gtklinkbutton.c (gtk_link_button_class_init): Fix

View File

@ -460,6 +460,8 @@ gdk_display_request_selection_notification
gdk_display_store_clipboard gdk_display_store_clipboard
gdk_display_supports_clipboard_persistence gdk_display_supports_clipboard_persistence
gdk_display_supports_selection_notification gdk_display_supports_selection_notification
gdk_display_supports_shapes
gdk_display_supports_input_shapes
#endif #endif
#endif #endif
@ -728,6 +730,8 @@ gdk_window_get_events
gdk_window_set_events gdk_window_set_events
gdk_window_shape_combine_mask gdk_window_shape_combine_mask
gdk_window_shape_combine_region gdk_window_shape_combine_region
gdk_window_input_shape_combine_mask
gdk_window_input_shape_combine_region
gdk_window_set_override_redirect gdk_window_set_override_redirect
gdk_window_set_accept_focus gdk_window_set_accept_focus
gdk_window_set_focus_on_map gdk_window_set_focus_on_map
@ -751,6 +755,8 @@ gdk_window_set_decorations
gdk_window_set_functions gdk_window_set_functions
gdk_window_set_child_shapes gdk_window_set_child_shapes
gdk_window_merge_child_shapes gdk_window_merge_child_shapes
gdk_window_set_child_input_shapes
gdk_window_merge_child_input_shapes
gdk_window_set_static_gravities gdk_window_set_static_gravities
gdk_window_begin_move_drag gdk_window_begin_move_drag
gdk_window_begin_resize_drag gdk_window_begin_resize_drag

View File

@ -179,6 +179,9 @@ void gdk_display_store_clipboard (GdkDisplay *display,
GdkAtom *targets, GdkAtom *targets,
gint n_targets); gint n_targets);
gboolean gdk_display_supports_shapes (GdkDisplay *display);
gboolean gdk_display_supports_input_shapes (GdkDisplay *display);
G_END_DECLS G_END_DECLS
#endif /* __GDK_DISPLAY_H__ */ #endif /* __GDK_DISPLAY_H__ */

View File

@ -396,6 +396,18 @@ void gdk_window_set_child_shapes (GdkWindow *window);
*/ */
void gdk_window_merge_child_shapes (GdkWindow *window); void gdk_window_merge_child_shapes (GdkWindow *window);
void gdk_window_input_shape_combine_mask (GdkWindow *window,
GdkBitmap *mask,
gint x,
gint y);
void gdk_window_input_shape_combine_region (GdkWindow *window,
GdkRegion *shape_region,
gint offset_x,
gint offset_y);
void gdk_window_set_child_input_shapes (GdkWindow *window);
void gdk_window_merge_child_input_shapes (GdkWindow *window);
/* /*
* Check if a window has been shown, and whether all its * Check if a window has been shown, and whether all its
* parents up to a toplevel have been shown, respectively. * parents up to a toplevel have been shown, respectively.

View File

@ -50,6 +50,11 @@
#include <X11/extensions/Xfixes.h> #include <X11/extensions/Xfixes.h>
#endif #endif
#ifdef HAVE_SHAPE_EXT
#include <X11/extensions/shape.h>
#endif
static void gdk_display_x11_class_init (GdkDisplayX11Class *class); static void gdk_display_x11_class_init (GdkDisplayX11Class *class);
static void gdk_display_x11_dispose (GObject *object); static void gdk_display_x11_dispose (GObject *object);
static void gdk_display_x11_finalize (GObject *object); static void gdk_display_x11_finalize (GObject *object);
@ -158,8 +163,9 @@ gdk_display_open (const gchar *display_name)
XClassHint *class_hint; XClassHint *class_hint;
gulong pid; gulong pid;
gint i; gint i;
#ifdef HAVE_XFIXES #if defined(HAVE_XFIXES) || defined(HAVE_SHAPE_EXT)
gint ignore; gint ignore;
gint maj, min;
#endif #endif
xdisplay = XOpenDisplay (display_name); xdisplay = XOpenDisplay (display_name);
@ -224,7 +230,20 @@ gdk_display_open (const gchar *display_name)
} }
else else
#endif #endif
display_x11->have_xfixes = FALSE; display_x11->have_xfixes = FALSE;
display_x11->have_shapes = FALSE;
display_x11->have_input_shapes = FALSE;
#ifdef HAVE_SHAPE_EXT
if (XShapeQueryExtension (GDK_DISPLAY_XDISPLAY (display), &ignore, &ignore))
{
display_x11->have_shapes = TRUE;
#ifdef ShapeInput
if (XShapeQueryVersion (GDK_DISPLAY_XDISPLAY (display), &maj, &min))
display_x11->have_input_shapes = (maj == 1 && min >= 1);
#endif
}
#endif
if (_gdk_synchronize) if (_gdk_synchronize)
XSynchronize (display_x11->xdisplay, True); XSynchronize (display_x11->xdisplay, True);
@ -1237,5 +1256,40 @@ gdk_x11_display_get_user_time (GdkDisplay *display)
return GDK_DISPLAY_X11 (display)->user_time; return GDK_DISPLAY_X11 (display)->user_time;
} }
/**
* gdk_display_supports_shapes:
* @display: a #GdkDisplay
*
* Returns %TRUE if gdk_window_shape_combine_mask() can
* be used to create shaped windows on @display.
*
* Returns: %TRUE if shaped windows are supported
*
* Since: 2.10
*/
gboolean
gdk_display_supports_shapes (GdkDisplay *display)
{
return GDK_DISPLAY_X11 (display)->have_shapes;
}
/**
* gdk_display_supports_input_shapes:
* @display: a #GdkDisplay
*
* Returns %TRUE if gdk_window_input_shape_combine_mask() can
* be used to modify the input shape of windows on @display.
*
* Returns: %TRUE if windows with modified input shape are supported
*
* Since: 2.10
*/
gboolean
gdk_display_supports_input_shapes (GdkDisplay *display)
{
return GDK_DISPLAY_X11 (display)->have_input_shapes;
}
#define __GDK_DISPLAY_X11_C__ #define __GDK_DISPLAY_X11_C__
#include "gdkaliasdef.c" #include "gdkaliasdef.c"

View File

@ -83,7 +83,6 @@ const int _gdk_nenvent_masks = sizeof (_gdk_event_mask_table) / sizeof (int);
/* Forward declarations */ /* Forward declarations */
static void gdk_window_set_static_win_gravity (GdkWindow *window, static void gdk_window_set_static_win_gravity (GdkWindow *window,
gboolean on); gboolean on);
static gboolean gdk_window_have_shape_ext (GdkDisplay *display);
static gboolean gdk_window_icon_name_set (GdkWindow *window); static gboolean gdk_window_icon_name_set (GdkWindow *window);
static void gdk_window_add_colormap_windows (GdkWindow *window); static void gdk_window_add_colormap_windows (GdkWindow *window);
static void set_wm_name (GdkDisplay *display, static void set_wm_name (GdkDisplay *display,
@ -3686,19 +3685,6 @@ gdk_window_add_colormap_windows (GdkWindow *window)
XFree (old_windows); XFree (old_windows);
} }
static gboolean
gdk_window_have_shape_ext (GdkDisplay *display)
{
#ifdef HAVE_SHAPE_EXT
int ignore;
return XShapeQueryExtension (GDK_DISPLAY_XDISPLAY (display),
&ignore, &ignore);
#else
return 0;
#endif
}
#define WARN_SHAPE_TOO_BIG() g_warning ("GdkWindow is too large to allow the use of shape masks or shape regions.") #define WARN_SHAPE_TOO_BIG() g_warning ("GdkWindow is too large to allow the use of shape masks or shape regions.")
/* /*
@ -3706,6 +3692,60 @@ gdk_window_have_shape_ext (GdkDisplay *display)
* If not available, shaped windows will look * If not available, shaped windows will look
* ugly, but programs still work. Stefan Wille * ugly, but programs still work. Stefan Wille
*/ */
static void
do_shape_combine_mask (GdkWindow *window,
GdkBitmap *mask,
gint x,
gint y,
gint shape)
{
GdkWindowObject *private = (GdkWindowObject *)window;
Pixmap pixmap;
gint xoffset, yoffset;
g_return_if_fail (GDK_IS_WINDOW (window));
#ifdef HAVE_SHAPE_EXT
if (GDK_WINDOW_DESTROYED (window))
return;
_gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
if (xoffset != 0 || yoffset != 0)
{
WARN_SHAPE_TOO_BIG ();
return;
}
if (shape == ShapeBounding
? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
: gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
{
if (mask)
{
pixmap = GDK_PIXMAP_XID (mask);
private->shaped = (shape == ShapeBounding);
}
else
{
x = 0;
y = 0;
pixmap = None;
private->shaped = FALSE;
}
XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
shape,
x, y,
pixmap,
ShapeSet);
}
#endif /* HAVE_SHAPE_EXT */
}
/** /**
* gdk_window_shape_combine_mask: * gdk_window_shape_combine_mask:
* @window: a #GdkWindow * @window: a #GdkWindow
@ -3733,10 +3773,55 @@ gdk_window_have_shape_ext (GdkDisplay *display)
void void
gdk_window_shape_combine_mask (GdkWindow *window, gdk_window_shape_combine_mask (GdkWindow *window,
GdkBitmap *mask, GdkBitmap *mask,
gint x, gint y) gint x,
gint y)
{
do_shape_combine_mask (window, mask, x, y, ShapeBounding);
}
/**
* gdk_window_input_shape_combine_mask:
* @window: a #GdkWindow
* @mask: shape mask
* @x: X position of shape mask with respect to @window
* @y: Y position of shape mask with respect to @window
*
* Like gdk_window_shape_combine_mask(), but the shape applies
* only to event handling. Mouse events which happen while
* the pointer position corresponds to an unset bit in the
* mask will be passed on the window below @window.
*
* An input shape is typically used with RGBA windows.
* The alpha channel of the window defines which pixels are
* invisible and allows for nicely antialiased borders,
* and the input shape controls where the window is
* "clickable".
*
* On the X11 platform, this requires version 1.1 of the
* shape extension.
*
* Since: 2.10
*/
void
gdk_window_input_shape_combine_mask (GdkWindow *window,
GdkBitmap *mask,
gint x,
gint y)
{
#ifdef ShapeInput
do_shape_combine_mask (window, mask, x, y, ShapeInput);
#endif
}
static void
do_shape_combine_region (GdkWindow *window,
GdkRegion *shape_region,
gint offset_x,
gint offset_y,
gint shape)
{ {
GdkWindowObject *private = (GdkWindowObject *)window; GdkWindowObject *private = (GdkWindowObject *)window;
Pixmap pixmap;
gint xoffset, yoffset; gint xoffset, yoffset;
g_return_if_fail (GDK_IS_WINDOW (window)); g_return_if_fail (GDK_IS_WINDOW (window));
@ -3753,29 +3838,35 @@ gdk_window_shape_combine_mask (GdkWindow *window,
return; return;
} }
if (gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window))) if (shape_region == NULL)
{ {
if (mask) /* Use NULL mask to unset the shape */
{ gdk_window_shape_combine_mask (window, NULL, 0, 0);
pixmap = GDK_PIXMAP_XID (mask); return;
}
private->shaped = TRUE;
} if (shape == ShapeBounding
else ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
{ : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
x = 0; {
y = 0; gint n_rects = 0;
pixmap = None; XRectangle *xrects = NULL;
private->shaped = FALSE; private->shaped = shape == ShapeBounding;
}
_gdk_region_get_xrectangles (shape_region,
0, 0,
&xrects, &n_rects);
XShapeCombineMask (GDK_WINDOW_XDISPLAY (window), XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window), GDK_WINDOW_XID (window),
ShapeBounding, shape,
x, y, offset_x, offset_y,
pixmap, xrects, n_rects,
ShapeSet); ShapeSet,
YXBanded);
g_free (xrects);
} }
#endif /* HAVE_SHAPE_EXT */ #endif /* HAVE_SHAPE_EXT */
} }
@ -3810,52 +3901,41 @@ gdk_window_shape_combine_region (GdkWindow *window,
gint offset_x, gint offset_x,
gint offset_y) gint offset_y)
{ {
GdkWindowObject *private = (GdkWindowObject *)window; do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
gint xoffset, yoffset; }
g_return_if_fail (GDK_IS_WINDOW (window));
#ifdef HAVE_SHAPE_EXT
if (GDK_WINDOW_DESTROYED (window))
return;
_gdk_windowing_window_get_offsets (window, &xoffset, &yoffset); /**
* gdk_window_input_shape_combine_region:
if (xoffset != 0 || yoffset != 0) * @window: a #GdkWindow
{ * @shape_region: region of window to be non-transparent
WARN_SHAPE_TOO_BIG (); * @offset_x: X position of @shape_region in @window coordinates
return; * @offset_y: Y position of @shape_region in @window coordinates
} *
* Like gdk_window_shape_combine_region(), but the shape applies
if (shape_region == NULL) * only to event handling. Mouse events which happen while
{ * the pointer position corresponds to an unset bit in the
/* Use NULL mask to unset the shape */ * mask will be passed on the window below @window.
gdk_window_shape_combine_mask (window, NULL, 0, 0); *
return; * An input shape is typically used with RGBA windows.
} * The alpha channel of the window defines which pixels are
* invisible and allows for nicely antialiased borders,
if (gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window))) * and the input shape controls where the window is
{ * "clickable".
gint n_rects = 0; *
XRectangle *xrects = NULL; * On the X11 platform, this requires version 1.1 of the
* shape extension.
private->shaped = TRUE; *
* Since: 2.10
_gdk_region_get_xrectangles (shape_region, */
0, 0, void
&xrects, &n_rects); gdk_window_input_shape_combine_region (GdkWindow *window,
GdkRegion *shape_region,
XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window), gint offset_x,
GDK_WINDOW_XID (window), gint offset_y)
ShapeBounding, {
offset_x, offset_y, #ifdef ShapeInput
xrects, n_rects, do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
ShapeSet, #endif
YXBanded);
g_free (xrects);
}
#endif /* HAVE_SHAPE_EXT */
} }
@ -5120,7 +5200,8 @@ gdk_add_rectangles (Display *disp,
static void static void
gdk_propagate_shapes (Display *disp, gdk_propagate_shapes (Display *disp,
Window win, Window win,
gboolean merge) gboolean merge,
int shape)
{ {
Window rt, par, *list = NULL; Window rt, par, *list = NULL;
gint i, j, num = 0, num_rects = 0; gint i, j, num = 0, num_rects = 0;
@ -5225,7 +5306,7 @@ gdk_propagate_shapes (Display *disp,
/* set the rects as the shape mask */ /* set the rects as the shape mask */
if (rects) if (rects)
{ {
XShapeCombineRectangles (disp, win, ShapeBounding, 0, 0, rects, num_rects, XShapeCombineRectangles (disp, win, shape, 0, 0, rects, num_rects,
ShapeSet, YXSorted); ShapeSet, YXSorted);
g_free (rects); g_free (rects);
} }
@ -5261,11 +5342,12 @@ gdk_window_set_child_shapes (GdkWindow *window)
{ {
g_return_if_fail (GDK_IS_WINDOW (window)); g_return_if_fail (GDK_IS_WINDOW (window));
#ifdef HAVE_SHAPE_EXT #ifdef HAVE_SHAPE_EXT
if (!GDK_WINDOW_DESTROYED (window) && if (!GDK_WINDOW_DESTROYED (window) &&
gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window))) gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window), gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window), FALSE); GDK_WINDOW_XID (window), FALSE, ShapeBounding);
#endif #endif
} }
@ -5281,7 +5363,6 @@ gdk_window_set_child_shapes (GdkWindow *window)
* This function is distinct from gdk_window_set_child_shapes() * This function is distinct from gdk_window_set_child_shapes()
* because it includes @window's shape mask in the set of shapes to * because it includes @window's shape mask in the set of shapes to
* be merged. * be merged.
*
**/ **/
void void
gdk_window_merge_child_shapes (GdkWindow *window) gdk_window_merge_child_shapes (GdkWindow *window)
@ -5290,12 +5371,69 @@ gdk_window_merge_child_shapes (GdkWindow *window)
#ifdef HAVE_SHAPE_EXT #ifdef HAVE_SHAPE_EXT
if (!GDK_WINDOW_DESTROYED (window) && if (!GDK_WINDOW_DESTROYED (window) &&
gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window))) gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window), gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window), TRUE); GDK_WINDOW_XID (window), TRUE, ShapeBounding);
#endif #endif
} }
/**
* gdk_window_set_child_input_shapes:
* @window: a #GdkWindow
*
* Sets the input shape mask of @window to the union of input shape masks
* for all children of @window, ignoring the input shape mask of @window
* itself. Contrast with gdk_window_merge_child_input_shapes() which includes
* the input shape mask of @window in the masks to be merged.
*
* Since: 2.10
**/
void
gdk_window_set_child_input_shapes (GdkWindow *window)
{
g_return_if_fail (GDK_IS_WINDOW (window));
#ifdef HAVE_SHAPE_EXT
#ifdef ShapeInput
if (!GDK_WINDOW_DESTROYED (window) &&
gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window), FALSE, ShapeInput);
#endif
#endif
}
/**
* gdk_window_merge_child_input_shapes:
* @window: a #GdkWindow
*
* Merges the input shape masks for any child windows into the
* input shape mask for @window. i.e. the union of all input masks
* for @window and its children will become the new input mask
* for @window. See gdk_window_input_shape_combine_mask().
*
* This function is distinct from gdk_window_set_child_input_shapes()
* because it includes @window's input shape mask in the set of
* shapes to be merged.
*
* Since: 2.10
**/
void
gdk_window_merge_child_input_shapes (GdkWindow *window)
{
g_return_if_fail (GDK_IS_WINDOW (window));
#ifdef HAVE_SHAPE_EXT
#ifdef ShapeInput
if (!GDK_WINDOW_DESTROYED (window) &&
gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window), TRUE, ShapeInput);
#endif
#endif
}
static void static void
gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on) gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
{ {

View File

@ -3970,6 +3970,7 @@ gtk_widget_set_size_request
gtk_widget_set_state gtk_widget_set_state
gtk_widget_set_style gtk_widget_set_style
gtk_widget_shape_combine_mask gtk_widget_shape_combine_mask
gtk_widget_input_shape_combine_mask
gtk_widget_show gtk_widget_show
gtk_widget_show_all gtk_widget_show_all
gtk_widget_show_now gtk_widget_show_now

View File

@ -250,6 +250,7 @@ static GQuark quark_event_mask = 0;
static GQuark quark_extension_event_mode = 0; static GQuark quark_extension_event_mode = 0;
static GQuark quark_parent_window = 0; static GQuark quark_parent_window = 0;
static GQuark quark_shape_info = 0; static GQuark quark_shape_info = 0;
static GQuark quark_input_shape_info = 0;
static GQuark quark_colormap = 0; static GQuark quark_colormap = 0;
static GQuark quark_pango_context = 0; static GQuark quark_pango_context = 0;
static GQuark quark_rc_style = 0; static GQuark quark_rc_style = 0;
@ -324,6 +325,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
quark_extension_event_mode = g_quark_from_static_string ("gtk-extension-event-mode"); quark_extension_event_mode = g_quark_from_static_string ("gtk-extension-event-mode");
quark_parent_window = g_quark_from_static_string ("gtk-parent-window"); quark_parent_window = g_quark_from_static_string ("gtk-parent-window");
quark_shape_info = g_quark_from_static_string ("gtk-shape-info"); quark_shape_info = g_quark_from_static_string ("gtk-shape-info");
quark_input_shape_info = g_quark_from_static_string ("gtk-input-shape-info");
quark_colormap = g_quark_from_static_string ("gtk-colormap"); quark_colormap = g_quark_from_static_string ("gtk-colormap");
quark_pango_context = g_quark_from_static_string ("gtk-pango-context"); quark_pango_context = g_quark_from_static_string ("gtk-pango-context");
quark_rc_style = g_quark_from_static_string ("gtk-rc-style"); quark_rc_style = g_quark_from_static_string ("gtk-rc-style");
@ -2352,6 +2354,13 @@ gtk_widget_realize (GtkWidget *widget)
shape_info->offset_y); shape_info->offset_y);
} }
shape_info = g_object_get_qdata (G_OBJECT (widget), quark_input_shape_info);
if (shape_info)
gdk_window_input_shape_combine_mask (widget->window,
shape_info->shape_mask,
shape_info->offset_x,
shape_info->offset_y);
if (!GTK_WIDGET_NO_WINDOW (widget)) if (!GTK_WIDGET_NO_WINDOW (widget))
{ {
mode = gtk_widget_get_extension_events (widget); mode = gtk_widget_get_extension_events (widget);
@ -2380,7 +2389,10 @@ gtk_widget_unrealize (GtkWidget *widget)
g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (GTK_IS_WIDGET (widget));
if (GTK_WIDGET_HAS_SHAPE_MASK (widget)) if (GTK_WIDGET_HAS_SHAPE_MASK (widget))
gtk_widget_shape_combine_mask (widget, NULL, -1, -1); gtk_widget_shape_combine_mask (widget, NULL, 0, 0);
if (g_object_get_qdata (G_OBJECT (widget), quark_input_shape_info))
gtk_widget_input_shape_combine_mask (widget, NULL, 0, 0);
if (GTK_WIDGET_REALIZED (widget)) if (GTK_WIDGET_REALIZED (widget))
{ {
@ -2792,8 +2804,6 @@ gtk_widget_queue_shallow_draw (GtkWidget *widget)
GdkRectangle rect; GdkRectangle rect;
GdkRegion *region; GdkRegion *region;
g_return_if_fail (GTK_IS_WIDGET (widget));
if (!GTK_WIDGET_REALIZED (widget)) if (!GTK_WIDGET_REALIZED (widget))
return; return;
@ -3880,7 +3890,7 @@ static void
gtk_widget_reparent_fixup_child (GtkWidget *widget, gtk_widget_reparent_fixup_child (GtkWidget *widget,
gpointer client_data) gpointer client_data)
{ {
g_return_if_fail (client_data != NULL); g_assert (client_data != NULL);
if (GTK_WIDGET_NO_WINDOW (widget)) if (GTK_WIDGET_NO_WINDOW (widget))
{ {
@ -4636,8 +4646,6 @@ gtk_widget_reset_rc_style (GtkWidget *widget)
GtkStyle *new_style = NULL; GtkStyle *new_style = NULL;
gboolean initial_emission; gboolean initial_emission;
g_return_if_fail (GTK_IS_WIDGET (widget));
initial_emission = !GTK_WIDGET_RC_STYLE (widget) && !GTK_WIDGET_USER_STYLE (widget); initial_emission = !GTK_WIDGET_RC_STYLE (widget) && !GTK_WIDGET_USER_STYLE (widget);
GTK_PRIVATE_UNSET_FLAG (widget, GTK_USER_STYLE); GTK_PRIVATE_UNSET_FLAG (widget, GTK_USER_STYLE);
@ -5766,8 +5774,6 @@ gtk_widget_set_usize_internal (GtkWidget *widget,
GtkWidgetAuxInfo *aux_info; GtkWidgetAuxInfo *aux_info;
gboolean changed = FALSE; gboolean changed = FALSE;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_object_freeze_notify (G_OBJECT (widget)); g_object_freeze_notify (G_OBJECT (widget));
aux_info = _gtk_widget_get_aux_info (widget, TRUE); aux_info = _gtk_widget_get_aux_info (widget, TRUE);
@ -5894,9 +5900,7 @@ gtk_widget_set_size_request (GtkWidget *widget,
* gtk_widget_set_size_request(). To get the size a widget will * gtk_widget_set_size_request(). To get the size a widget will
* actually use, call gtk_widget_size_request() instead of * actually use, call gtk_widget_size_request() instead of
* this function. * this function.
*
**/ **/
void void
gtk_widget_get_size_request (GtkWidget *widget, gtk_widget_get_size_request (GtkWidget *widget,
gint *width, gint *width,
@ -5930,7 +5934,6 @@ gtk_widget_get_size_request (GtkWidget *widget,
* mask. This function can't be used with #GTK_NO_WINDOW widgets; * mask. This function can't be used with #GTK_NO_WINDOW widgets;
* to get events on those widgets, place them inside a #GtkEventBox * to get events on those widgets, place them inside a #GtkEventBox
* and receive events on the event box. * and receive events on the event box.
*
**/ **/
void void
gtk_widget_set_events (GtkWidget *widget, gtk_widget_set_events (GtkWidget *widget,
@ -6745,7 +6748,7 @@ gtk_widget_finalize (GObject *object)
static void static void
gtk_widget_real_map (GtkWidget *widget) gtk_widget_real_map (GtkWidget *widget)
{ {
g_return_if_fail (GTK_WIDGET_REALIZED (widget) == TRUE); g_assert (GTK_WIDGET_REALIZED (widget));
if (!GTK_WIDGET_MAPPED (widget)) if (!GTK_WIDGET_MAPPED (widget))
{ {
@ -6787,7 +6790,7 @@ gtk_widget_real_unmap (GtkWidget *widget)
static void static void
gtk_widget_real_realize (GtkWidget *widget) gtk_widget_real_realize (GtkWidget *widget)
{ {
g_return_if_fail (GTK_WIDGET_NO_WINDOW (widget)); g_assert (GTK_WIDGET_NO_WINDOW (widget));
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
if (widget->parent) if (widget->parent)
@ -7046,8 +7049,8 @@ gtk_widget_shape_combine_mask (GtkWidget *widget,
shape_info->offset_x = offset_x; shape_info->offset_x = offset_x;
shape_info->offset_y = offset_y; shape_info->offset_y = offset_y;
/* set shape if widget has a gdk window allready. /* set shape if widget has a gdk window already.
* otherwise the shape is scheduled to be set by gtk_widget_realize. * otherwise the shape is scheduled to be set by gtk_widget_realize().
*/ */
if (widget->window) if (widget->window)
gdk_window_shape_combine_mask (widget->window, shape_mask, gdk_window_shape_combine_mask (widget->window, shape_mask,
@ -7055,6 +7058,59 @@ gtk_widget_shape_combine_mask (GtkWidget *widget,
} }
} }
/**
* gtk_widget_input_shape_combine_mask:
* @widget: a #GtkWidget.
* @shape_mask: shape to be added, or %NULL to remove an existing shape.
* @offset_x: X position of shape mask with respect to @window.
* @offset_y: Y position of shape mask with respect to @window.
*
* Sets an input shape for this widget's GDK window. This allows for
* windows which react to mouse click in a nonrectangular region, see
* gdk_window_input_shape_combine_mask() for more information.
*
* Since: 2.10
**/
void
gtk_widget_input_shape_combine_mask (GtkWidget *widget,
GdkBitmap *shape_mask,
gint offset_x,
gint offset_y)
{
GtkWidgetShapeInfo* shape_info;
g_return_if_fail (GTK_IS_WIDGET (widget));
/* set_shape doesn't work on widgets without gdk window */
g_return_if_fail (!GTK_WIDGET_NO_WINDOW (widget));
if (!shape_mask)
{
if (widget->window)
gdk_window_input_shape_combine_mask (widget->window, NULL, 0, 0);
g_object_set_qdata (G_OBJECT (widget), quark_input_shape_info, NULL);
}
else
{
shape_info = g_slice_new (GtkWidgetShapeInfo);
g_object_set_qdata_full (G_OBJECT (widget), quark_input_shape_info,
shape_info,
(GDestroyNotify) gtk_widget_shape_info_destroy);
shape_info->shape_mask = g_object_ref (shape_mask);
shape_info->offset_x = offset_x;
shape_info->offset_y = offset_y;
/* set shape if widget has a gdk window already.
* otherwise the shape is scheduled to be set by gtk_widget_realize().
*/
if (widget->window)
gdk_window_input_shape_combine_mask (widget->window, shape_mask,
offset_x, offset_y);
}
}
static void static void
gtk_reset_shapes_recurse (GtkWidget *widget, gtk_reset_shapes_recurse (GtkWidget *widget,
GdkWindow *window) GdkWindow *window)

View File

@ -744,6 +744,10 @@ void gtk_widget_shape_combine_mask (GtkWidget *widget,
GdkBitmap *shape_mask, GdkBitmap *shape_mask,
gint offset_x, gint offset_x,
gint offset_y); gint offset_y);
void gtk_widget_input_shape_combine_mask (GtkWidget *widget,
GdkBitmap *shape_mask,
gint offset_x,
gint offset_y);
/* internal function */ /* internal function */
void gtk_widget_reset_shapes (GtkWidget *widget); void gtk_widget_reset_shapes (GtkWidget *widget);