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
					Matthias Clasen
				
			
				
					committed by
					
						 Matthias Clasen
						Matthias Clasen
					
				
			
			
				
	
			
			
			 Matthias Clasen
						Matthias Clasen
					
				
			
						parent
						
							2447b0365e
						
					
				
				
					commit
					1ad93a683b
				
			| @ -50,6 +50,11 @@ | ||||
| #include <X11/extensions/Xfixes.h> | ||||
| #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_dispose            (GObject            *object); | ||||
| static void   gdk_display_x11_finalize           (GObject            *object); | ||||
| @ -158,8 +163,9 @@ gdk_display_open (const gchar *display_name) | ||||
|   XClassHint *class_hint; | ||||
|   gulong pid; | ||||
|   gint i; | ||||
| #ifdef HAVE_XFIXES | ||||
| #if defined(HAVE_XFIXES) || defined(HAVE_SHAPE_EXT) | ||||
|   gint ignore; | ||||
|   gint maj, min; | ||||
| #endif | ||||
|  | ||||
|   xdisplay = XOpenDisplay (display_name); | ||||
| @ -224,7 +230,20 @@ gdk_display_open (const gchar *display_name) | ||||
|     } | ||||
|   else | ||||
| #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) | ||||
|     XSynchronize (display_x11->xdisplay, True); | ||||
| @ -1237,5 +1256,40 @@ gdk_x11_display_get_user_time (GdkDisplay *display) | ||||
|   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__ | ||||
| #include "gdkaliasdef.c" | ||||
|  | ||||
| @ -83,7 +83,6 @@ const int _gdk_nenvent_masks = sizeof (_gdk_event_mask_table) / sizeof (int); | ||||
| /* Forward declarations */ | ||||
| static void     gdk_window_set_static_win_gravity (GdkWindow  *window, | ||||
| 						   gboolean    on); | ||||
| static gboolean gdk_window_have_shape_ext         (GdkDisplay *display); | ||||
| static gboolean gdk_window_icon_name_set          (GdkWindow  *window); | ||||
| static void     gdk_window_add_colormap_windows   (GdkWindow  *window); | ||||
| static void     set_wm_name                       (GdkDisplay  *display, | ||||
| @ -3686,19 +3685,6 @@ gdk_window_add_colormap_windows (GdkWindow *window) | ||||
|     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.") | ||||
|  | ||||
| /* | ||||
| @ -3706,6 +3692,60 @@ gdk_window_have_shape_ext (GdkDisplay *display) | ||||
|  * If not available, shaped windows will look | ||||
|  * 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: | ||||
|  * @window: a #GdkWindow | ||||
| @ -3733,10 +3773,55 @@ gdk_window_have_shape_ext (GdkDisplay *display) | ||||
| void | ||||
| gdk_window_shape_combine_mask (GdkWindow *window, | ||||
| 			       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; | ||||
|   Pixmap pixmap; | ||||
|   gint xoffset, yoffset; | ||||
|    | ||||
|   g_return_if_fail (GDK_IS_WINDOW (window)); | ||||
| @ -3753,29 +3838,35 @@ gdk_window_shape_combine_mask (GdkWindow *window, | ||||
|       return; | ||||
|     } | ||||
|    | ||||
|   if (gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window))) | ||||
|   if (shape_region == NULL) | ||||
|     { | ||||
|       if (mask) | ||||
| 	{ | ||||
| 	  pixmap = GDK_PIXMAP_XID (mask); | ||||
| 	   | ||||
| 	  private->shaped = TRUE; | ||||
| 	} | ||||
|       else | ||||
| 	{ | ||||
| 	  x = 0; | ||||
| 	  y = 0; | ||||
| 	  pixmap = None; | ||||
|       /* Use NULL mask to unset the shape */ | ||||
|       gdk_window_shape_combine_mask (window, NULL, 0, 0); | ||||
|       return; | ||||
|     } | ||||
|    | ||||
|   if (shape == ShapeBounding | ||||
|       ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)) | ||||
|       : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window))) | ||||
|     { | ||||
|       gint n_rects = 0; | ||||
|       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), | ||||
| 			 GDK_WINDOW_XID (window), | ||||
| 			 ShapeBounding, | ||||
| 			 x, y, | ||||
| 			 pixmap, | ||||
| 			 ShapeSet); | ||||
|       XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window), | ||||
|                                GDK_WINDOW_XID (window), | ||||
|                                shape, | ||||
|                                offset_x, offset_y, | ||||
|                                xrects, n_rects, | ||||
|                                ShapeSet, | ||||
|                                YXBanded); | ||||
|  | ||||
|       g_free (xrects); | ||||
|     } | ||||
| #endif /* HAVE_SHAPE_EXT */ | ||||
| } | ||||
| @ -3810,52 +3901,41 @@ gdk_window_shape_combine_region (GdkWindow *window, | ||||
|                                  gint       offset_x, | ||||
|                                  gint       offset_y) | ||||
| {  | ||||
|   GdkWindowObject *private = (GdkWindowObject *)window; | ||||
|   gint xoffset, yoffset; | ||||
|    | ||||
|   g_return_if_fail (GDK_IS_WINDOW (window)); | ||||
|    | ||||
| #ifdef HAVE_SHAPE_EXT | ||||
|   if (GDK_WINDOW_DESTROYED (window)) | ||||
|     return; | ||||
|   do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding); | ||||
| } | ||||
|  | ||||
|   _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset); | ||||
|  | ||||
|   if (xoffset != 0 || yoffset != 0) | ||||
|     { | ||||
|       WARN_SHAPE_TOO_BIG (); | ||||
|       return; | ||||
|     } | ||||
|    | ||||
|   if (shape_region == NULL) | ||||
|     { | ||||
|       /* Use NULL mask to unset the shape */ | ||||
|       gdk_window_shape_combine_mask (window, NULL, 0, 0); | ||||
|       return; | ||||
|     } | ||||
|    | ||||
|   if (gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window))) | ||||
|     { | ||||
|       gint n_rects = 0; | ||||
|       XRectangle *xrects = NULL; | ||||
|  | ||||
|       private->shaped = TRUE; | ||||
|  | ||||
|       _gdk_region_get_xrectangles (shape_region, | ||||
|                                    0, 0, | ||||
|                                    &xrects, &n_rects); | ||||
|        | ||||
|       XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window), | ||||
|                                GDK_WINDOW_XID (window), | ||||
|                                ShapeBounding, | ||||
|                                offset_x, offset_y, | ||||
|                                xrects, n_rects, | ||||
|                                ShapeSet, | ||||
|                                YXBanded); | ||||
|  | ||||
|       g_free (xrects); | ||||
|     } | ||||
| #endif /* HAVE_SHAPE_EXT */ | ||||
| /** | ||||
|  * gdk_window_input_shape_combine_region: | ||||
|  * @window: a #GdkWindow | ||||
|  * @shape_region: region of window to be non-transparent | ||||
|  * @offset_x: X position of @shape_region in @window coordinates | ||||
|  * @offset_y: Y position of @shape_region in @window coordinates | ||||
|  *  | ||||
|  * Like gdk_window_shape_combine_region(), 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_region (GdkWindow *window, | ||||
| 				       GdkRegion *shape_region, | ||||
| 				       gint       offset_x, | ||||
| 				       gint       offset_y) | ||||
| { | ||||
| #ifdef ShapeInput | ||||
|   do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput); | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -5120,7 +5200,8 @@ gdk_add_rectangles (Display           *disp, | ||||
| static void | ||||
| gdk_propagate_shapes (Display *disp, | ||||
| 		      Window   win, | ||||
| 		      gboolean merge) | ||||
| 		      gboolean merge, | ||||
| 		      int      shape) | ||||
| { | ||||
|   Window              rt, par, *list = NULL; | ||||
|   gint                i, j, num = 0, num_rects = 0; | ||||
| @ -5225,7 +5306,7 @@ gdk_propagate_shapes (Display *disp, | ||||
|       /* set the rects as the shape mask */ | ||||
|       if (rects) | ||||
| 	{ | ||||
| 	  XShapeCombineRectangles (disp, win, ShapeBounding, 0, 0, rects, num_rects, | ||||
| 	  XShapeCombineRectangles (disp, win, shape, 0, 0, rects, num_rects, | ||||
| 				   ShapeSet, YXSorted); | ||||
| 	  g_free (rects); | ||||
| 	} | ||||
| @ -5261,11 +5342,12 @@ gdk_window_set_child_shapes (GdkWindow *window) | ||||
| { | ||||
|   g_return_if_fail (GDK_IS_WINDOW (window)); | ||||
|    | ||||
|    | ||||
| #ifdef HAVE_SHAPE_EXT | ||||
|   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_WINDOW_XID (window), FALSE); | ||||
| 			  GDK_WINDOW_XID (window), FALSE, ShapeBounding); | ||||
| #endif    | ||||
| } | ||||
|  | ||||
| @ -5281,7 +5363,6 @@ gdk_window_set_child_shapes (GdkWindow *window) | ||||
|  * This function is distinct from gdk_window_set_child_shapes() | ||||
|  * because it includes @window's shape mask in the set of shapes to | ||||
|  * be merged. | ||||
|  *  | ||||
|  **/ | ||||
| void | ||||
| gdk_window_merge_child_shapes (GdkWindow *window) | ||||
| @ -5290,12 +5371,69 @@ gdk_window_merge_child_shapes (GdkWindow *window) | ||||
|    | ||||
| #ifdef HAVE_SHAPE_EXT | ||||
|   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_WINDOW_XID (window), TRUE); | ||||
| 			  GDK_WINDOW_XID (window), TRUE, ShapeBounding); | ||||
| #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 | ||||
| gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on) | ||||
| { | ||||
|  | ||||
		Reference in New Issue
	
	Block a user