+ g_return_if_fail (requisition != NULL);
+
+ gtk_widget_get_preferred_size (widget, requisition, NULL);
+}
+
+/**
+ * gtk_widget_set_window:
+ * @widget: a #GtkWidget
+ * @window: (transfer full): a #GdkWindow
+ *
+ * Sets a widget's window. This function should only be used in a
+ * widget's #GtkWidget::realize implementation. The %window passed is
+ * usually either new window created with gdk_window_new(), or the
+ * window of its parent widget as returned by
+ * gtk_widget_get_parent_window().
+ *
+ * Widgets must indicate whether they will create their own #GdkWindow
+ * by calling gtk_widget_set_has_window(). This is usually done in the
+ * widget's init() function.
+ *
+ * <note><para>This function does not add any reference to @window.</para></note>
+ *
+ * Since: 2.18
+ */
+void
+gtk_widget_set_window (GtkWidget *widget,
+ GdkWindow *window)
+{
+ GtkWidgetPrivate *priv;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
+
+ priv = widget->priv;
+
+ if (priv->window != window)
+ {
+ priv->window = window;
+
+ if (gtk_widget_get_has_window (widget) && window != NULL && !gdk_window_has_native (window))
+ gdk_window_set_opacity (window,
+ priv->norender ? 0 : priv->alpha / 255.0);
+
+ g_object_notify (G_OBJECT (widget), "window");
+ }
+}
+
+/**
+ * gtk_widget_register_window:
+ * @widget: a #GtkWidget
+ * @window: a #GdkWindow
+ *
+ * Registers a #GdkWindow with the widget and sets it up so that
+ * the widget recieves events for it. Call gtk_widget_unregister_window()
+ * when destroying the window.
+ *
+ * Before 3.8 you needed to call gdk_window_set_user_data() directly to set
+ * this up. This is now deprecated and you should use gtk_widget_register_window()
+ * instead. Old code will keep working as is, although some new features like
+ * transparency might not work perfectly.
+ *
+ * Since: 3.8
+ */
+void
+gtk_widget_register_window (GtkWidget *widget,
+ GdkWindow *window)
+{
+ GtkWidgetPrivate *priv;
+ gpointer user_data;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ gdk_window_get_user_data (window, &user_data);
+ g_assert (user_data == NULL);
+
+ priv = widget->priv;
+
+ gdk_window_set_user_data (window, widget);
+ priv->registered_windows = g_list_prepend (priv->registered_windows, window);
+
+ if (priv->window != window && !gdk_window_has_native (window))
+ gdk_window_set_opacity (window,
+ priv->norender_children ? 0.0 : 1.0);
+}
+
+/**
+ * gtk_widget_unregister_window:
+ * @widget: a #GtkWidget
+ * @window: a #GdkWindow
+ *
+ * Unregisters a #GdkWindow from the widget that was previously set up with
+ * gtk_widget_register_window(). You need to call this when the window is
+ * no longer used by the widget, such as when you destroy it.
+ *
+ * Since: 3.8
+ */
+void
+gtk_widget_unregister_window (GtkWidget *widget,
+ GdkWindow *window)
+{
+ GtkWidgetPrivate *priv;
+ gpointer user_data;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ priv = widget->priv;
+
+ gdk_window_get_user_data (window, &user_data);
+ g_assert (user_data == widget);
+ gdk_window_set_user_data (window, NULL);
+ priv->registered_windows = g_list_remove (priv->registered_windows, window);
+}
+
+/**
+ * gtk_widget_get_window:
+ * @widget: a #GtkWidget
+ *
+ * Returns the widget's window if it is realized, %NULL otherwise
+ *
+ * Return value: (transfer none): @widget's window.
+ *
+ * Since: 2.14
+ */
+GdkWindow*
+gtk_widget_get_window (GtkWidget *widget)
+{
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+ return widget->priv->window;
+}
+
+/**
+ * gtk_widget_get_support_multidevice:
+ * @widget: a #GtkWidget
+ *
+ * Returns %TRUE if @widget is multiple pointer aware. See
+ * gtk_widget_set_support_multidevice() for more information.
+ *
+ * Returns: %TRUE if @widget is multidevice aware.
+ **/
+gboolean
+gtk_widget_get_support_multidevice (GtkWidget *widget)
+{
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+
+ return widget->priv->multidevice;
+}
+
+/**
+ * gtk_widget_set_support_multidevice:
+ * @widget: a #GtkWidget
+ * @support_multidevice: %TRUE to support input from multiple devices.
+ *
+ * Enables or disables multiple pointer awareness. If this setting is %TRUE,
+ * @widget will start receiving multiple, per device enter/leave events. Note
+ * that if custom #GdkWindow<!-- -->s are created in #GtkWidget::realize,
+ * gdk_window_set_support_multidevice() will have to be called manually on them.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_widget_set_support_multidevice (GtkWidget *widget,
+ gboolean support_multidevice)
+{
+ GtkWidgetPrivate *priv;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ priv = widget->priv;
+ priv->multidevice = (support_multidevice == TRUE);
+
+ if (gtk_widget_get_realized (widget))
+ gdk_window_set_support_multidevice (priv->window, support_multidevice);
+}
+
+/* There are multiple alpha related sources. First of all the user can specify alpha
+ * in gtk_widget_set_opacity, secondly we can get it from the css opacity. These two
+ * are multiplied together to form the total alpha. Secondly, the user can specify
+ * an opacity group for a widget, which means we must essentially handle it as having alpha.
+ *
+ * We handle opacity in two ways. For a windowed widget, with opacity set but no opacity
+ * group we directly set the opacity of widget->window. This will cause gdk to properly
+ * redirect drawing inside the window to a buffer and do OVER paint_with_alpha.
+ *
+ * However, if the widget is not windowed, or the user specified an opacity group for the
+ * widget we do the opacity handling in the ::draw marshaller for the widget. A naive
+ * implementation of this would break for windowed widgets or descendant widgets with
+ * windows, as these would not be handled by the ::draw signal. To handle this we set
+ * all such gdkwindows as fully transparent and then override gtk_cairo_should_draw_window()
+ * to make the draw signal propagate to *all* child widgets/windows.
+ *
+ * Note: We don't make all child windows fully transparent, we stop at the first one
+ * in each branch when propagating down the hierarchy.
+ */
+
+
+/* This is called when priv->alpha or priv->opacity_group group changes, and should
+ * update priv->norender and GdkWindow opacity for this widget and any children that
+ * needs changing. It is also called whenver the parent changes, the parents
+ * norender_children state changes, or the has_window state of the widget changes.
+ */
+static void
+gtk_widget_propagate_alpha (GtkWidget *widget)
+{
+ GtkWidgetPrivate *priv = widget->priv;
+ GtkWidget *parent;
+ gboolean norender, norender_children;
+ GList *l;
+
+ parent = priv->parent;
+
+ /* Norender affects only windowed widget and means don't render widget->window in the
+ normal fashion.
+ We only set this if the parent has norender_children, because:
+ a) For an opacity group (that does not have a norender_children parent) we still
+ need to render the window or we will never get an expose event.
+ b) For alpha we set the opacity of window->widget directly, so no other
+ work is needed.
+ */
+ norender = (parent != NULL && parent->priv->norender_children);
+
+ /* windows under this widget should not render if:
+ a) This widget has an opacity group
+ b) This widget has alpha and is no-windowed (otherwise we'd set alpha on widget->window)
+ c) This widget has norender but is no-windowed (a windowed widget would "swallow" the norender)
+ */
+ norender_children =
+ priv->opacity_group ||
+ (!gtk_widget_get_has_window (widget) &&
+ ( norender || priv->alpha != 255));
+
+ if (gtk_widget_get_has_window (widget))
+ {
+ if (priv->window != NULL && !gdk_window_has_native (priv->window))
+ gdk_window_set_opacity (priv->window,
+ norender ? 0 : priv->alpha / 255.0);
+ }
+
+ for (l = priv->registered_windows; l != NULL; l = l->next)
+ {
+ GdkWindow *w = l->data;
+ if (w != priv->window && !gdk_window_has_native (w))
+ gdk_window_set_opacity (w, norender_children ? 0.0 : 1.0);
+ }
+
+ priv->norender = norender;
+ if (priv->norender_children != norender_children)
+ {
+ priv->norender_children = norender_children;
+
+ if (GTK_IS_CONTAINER (widget))
+ gtk_container_forall (GTK_CONTAINER (widget), (GtkCallback)gtk_widget_propagate_alpha, NULL);
+ }
+
+ if (gtk_widget_get_realized (widget))
+ gtk_widget_queue_draw (widget);
+}
+
+static void
+gtk_widget_update_alpha (GtkWidget *widget)
+{
+ GtkWidgetPrivate *priv;
+ double opacity;
+ guint8 alpha;
+
+ priv = widget->priv;
+
+ alpha = priv->user_alpha;
+
+ if (priv->context)
+ {
+ opacity =
+ _gtk_css_number_value_get (_gtk_style_context_peek_property (priv->context,
+ GTK_CSS_PROPERTY_OPACITY),
+ 100);
+ opacity = CLAMP (opacity, 0.0, 1.0);
+ alpha = round (priv->user_alpha * opacity);
+ }
+
+ if (alpha == priv->alpha)
+ return;
+
+ priv->alpha = alpha;
+
+ gtk_widget_propagate_alpha (widget);
+
+}
+
+static void
+gtk_widget_set_has_opacity_group (GtkWidget *widget,
+ gboolean has_opacity_group)
+{
+ GtkWidgetPrivate *priv;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));