Compare commits
167 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 109593ab18 | |||
| 7b17f6fede | |||
| 060e30de3f | |||
| fc33bf2d1f | |||
| dd5c981b63 | |||
| 9a4c19349e | |||
| 3389ddf6fc | |||
| 341660e056 | |||
| b42bf99b13 | |||
| 18d814d2ce | |||
| 6fce18e1a1 | |||
| cf4226586a | |||
| 0481aa10e7 | |||
| edbaa0964f | |||
| fbefec52a5 | |||
| d59d8b5dd4 | |||
| 87a13fe3d2 | |||
| 2f85443e37 | |||
| 311aa01e01 | |||
| 3bbbe9f71b | |||
| 890b759091 | |||
| d997903d29 | |||
| b097f0a7d8 | |||
| 1b5b1bfd0e | |||
| c94867f8a1 | |||
| dbac377ad2 | |||
| 0638dca29a | |||
| ae68dc7a7d | |||
| 20b4a8b38c | |||
| 65965bed16 | |||
| 630442f31c | |||
| d6dfa41f10 | |||
| 8cf06befc0 | |||
| 128a34fe37 | |||
| 0285919f4a | |||
| 1fed357752 | |||
| ef9863ab63 | |||
| 5cbf6f5fbd | |||
| 15fda18791 | |||
| f7856e887e | |||
| 1b8595b5f2 | |||
| 24754c3259 | |||
| 4dfe2a8aa8 | |||
| ab7507150b | |||
| e657d9d553 | |||
| 36e00ae95e | |||
| f2dff5115f | |||
| a246f8c22a | |||
| 6efa1fc006 | |||
| 3d37f08f38 | |||
| 160f1e581a | |||
| 661e195ffc | |||
| 551ced9ae4 | |||
| 799cb39e08 | |||
| 0615668dd9 | |||
| 1ada7bbc02 | |||
| 81658105f7 | |||
| d9ef734458 | |||
| 73760e5835 | |||
| 5638882dca | |||
| 8da56cef79 | |||
| 64ab82c403 | |||
| 56df49971a | |||
| 0bf136a902 | |||
| 2479d60012 | |||
| 6990f73940 | |||
| 254c27acbe | |||
| 558405e1bc | |||
| f47c376fb1 | |||
| 5679b9a687 | |||
| 24235f61ab | |||
| a44ac75e65 | |||
| 85c8e29d78 | |||
| 8fb797866d | |||
| 96a677e5ca | |||
| 07054ca20d | |||
| 8f6a48832d | |||
| 658588dfe7 | |||
| 480d8aec06 | |||
| 0d91481587 | |||
| 8650980797 | |||
| 2b0d1bca43 | |||
| f7e328e5f7 | |||
| b40743121b | |||
| 93c1353c69 | |||
| 1196380f28 | |||
| 26f99bf20c | |||
| 65d9b7ee86 | |||
| 688f0997f4 | |||
| 430ea05aea | |||
| 17f4211e4f | |||
| ecd6446d08 | |||
| 1540797237 | |||
| 898728fb2d | |||
| fc2b412c0c | |||
| 1ce5327058 | |||
| ad3773b2e1 | |||
| 8619b109cc | |||
| 6ddb61119a | |||
| 492a38c229 | |||
| 181a4bce25 | |||
| 93905a8513 | |||
| 4f06b669c5 | |||
| f3ed3e99c3 | |||
| 4f5a8207bc | |||
| 2f1194c0c1 | |||
| 921eccb459 | |||
| 888b92674f | |||
| 7d354b5084 | |||
| 4238a04c7b | |||
| adb547a147 | |||
| cdcd2bb073 | |||
| 06f790d663 | |||
| c73972f7df | |||
| 8d5f1ae662 | |||
| a3abf0693d | |||
| 7ca24f12d7 | |||
| f68855341e | |||
| 31d9ecb5c3 | |||
| f13e6179e8 | |||
| d279c666a9 | |||
| 7819a5aab9 | |||
| 15300f839e | |||
| 94b0e99be5 | |||
| 8c1d852a84 | |||
| 2738926dcb | |||
| 029ec38e63 | |||
| 2bf1561b48 | |||
| bd44831987 | |||
| ab5d3e756b | |||
| 92f1bdcf45 | |||
| 64b9114d98 | |||
| a1cc809c60 | |||
| 7c19ab66ee | |||
| 7ca528b896 | |||
| 2870f4dbfe | |||
| f14d998c95 | |||
| 34e859a5bc | |||
| 5822a35087 | |||
| a3b73a416e | |||
| d3cecd65a5 | |||
| 470720e11a | |||
| c3f43cf1f2 | |||
| 5251253fc0 | |||
| f5e112fd2d | |||
| 56ee1f3566 | |||
| 4afad781fe | |||
| 8e4c441f78 | |||
| d07cd892e7 | |||
| 44198cc779 | |||
| 4bba279085 | |||
| f454a31caa | |||
| 3863e44360 | |||
| 8566218485 | |||
| 1475575799 | |||
| bc901ffa5a | |||
| b114d45c5f | |||
| 9a1c698070 | |||
| 884088f649 | |||
| ad5c5d477e | |||
| 1513bf4174 | |||
| eacbeb9efd | |||
| 18da852e15 | |||
| 39fbf13fcb | |||
| 9105de9170 | |||
| eeed55d45c | |||
| 3a3b325f8e |
@@ -26,6 +26,7 @@ ccache --show-stats
|
||||
|
||||
xvfb-run -a -s "-screen 0 1024x768x24" \
|
||||
meson test \
|
||||
--timeout-multiplier 2 \
|
||||
--print-errorlogs \
|
||||
--suite=gtk \
|
||||
--no-suite=gtk:gsk \
|
||||
|
||||
@@ -189,6 +189,7 @@
|
||||
<file>paintable_animated.c</file>
|
||||
<file>paintable_mediastream.c</file>
|
||||
<file>panes.c</file>
|
||||
<file>password_entry.c</file>
|
||||
<file>pickers.c</file>
|
||||
<file>pixbufs.c</file>
|
||||
<file>popover.c</file>
|
||||
@@ -206,6 +207,7 @@
|
||||
<file>spinbutton.c</file>
|
||||
<file>spinner.c</file>
|
||||
<file>tabs.c</file>
|
||||
<file>tagged_entry.c</file>
|
||||
<file>textview.c</file>
|
||||
<file>textscroll.c</file>
|
||||
<file>theming_style_classes.c</file>
|
||||
@@ -217,6 +219,9 @@
|
||||
<gresource prefix="/textview">
|
||||
<file>floppybuddy.gif</file>
|
||||
</gresource>
|
||||
<gresource prefix="/tagged_entry">
|
||||
<file>tagstyle.css</file>
|
||||
</gresource>
|
||||
<gresource prefix="/listbox">
|
||||
<file>listbox.ui</file>
|
||||
<file>messages.txt</file>
|
||||
@@ -261,6 +266,10 @@
|
||||
<gresource prefix="/dnd">
|
||||
<file>dnd.css</file>
|
||||
</gresource>
|
||||
<gresource prefix="/tagged_entry">
|
||||
<file>demotaggedentry.c</file>
|
||||
<file>demotaggedentry.h</file>
|
||||
</gresource>
|
||||
<gresource prefix="/org/gtk/Demo">
|
||||
<file>icons/16x16/actions/application-exit.png</file>
|
||||
<file>icons/16x16/actions/document-new.png</file>
|
||||
|
||||
@@ -0,0 +1,493 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2019 Red Hat, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* - Matthias Clasen <mclasen@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "demotaggedentry.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gtk/gtk-a11y.h>
|
||||
|
||||
typedef struct {
|
||||
GtkWidget *box;
|
||||
GtkWidget *entry;
|
||||
} DemoTaggedEntryPrivate;
|
||||
|
||||
static void demo_tagged_entry_editable_init (GtkEditableInterface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (DemoTaggedEntry, demo_tagged_entry, GTK_TYPE_WIDGET,
|
||||
G_ADD_PRIVATE (DemoTaggedEntry)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, demo_tagged_entry_editable_init))
|
||||
|
||||
static void
|
||||
demo_tagged_entry_init (DemoTaggedEntry *entry)
|
||||
{
|
||||
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
|
||||
|
||||
gtk_widget_set_has_surface (GTK_WIDGET (entry), FALSE);
|
||||
|
||||
priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_widget_set_parent (priv->box, GTK_WIDGET (entry));
|
||||
|
||||
priv->entry = gtk_text_new ();
|
||||
gtk_widget_set_hexpand (priv->entry, TRUE);
|
||||
gtk_widget_set_vexpand (priv->entry, TRUE);
|
||||
gtk_widget_set_hexpand (priv->box, FALSE);
|
||||
gtk_widget_set_vexpand (priv->box, FALSE);
|
||||
gtk_container_add (GTK_CONTAINER (priv->box), priv->entry);
|
||||
gtk_editable_init_delegate (GTK_EDITABLE (entry));
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_dispose (GObject *object)
|
||||
{
|
||||
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (object);
|
||||
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
|
||||
|
||||
if (priv->entry)
|
||||
gtk_editable_finish_delegate (GTK_EDITABLE (entry));
|
||||
|
||||
g_clear_pointer (&priv->entry, gtk_widget_unparent);
|
||||
g_clear_pointer (&priv->box, gtk_widget_unparent);
|
||||
|
||||
G_OBJECT_CLASS (demo_tagged_entry_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (demo_tagged_entry_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
if (gtk_editable_delegate_set_property (object, prop_id, value, pspec))
|
||||
return;
|
||||
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
if (gtk_editable_delegate_get_property (object, prop_id, value, pspec))
|
||||
return;
|
||||
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (widget);
|
||||
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
|
||||
|
||||
gtk_widget_measure (priv->box, orientation, for_size,
|
||||
minimum, natural,
|
||||
minimum_baseline, natural_baseline);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (widget);
|
||||
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
|
||||
|
||||
gtk_widget_size_allocate (priv->box,
|
||||
&(GtkAllocation) { 0, 0, width, height },
|
||||
baseline);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_grab_focus (GtkWidget *widget)
|
||||
{
|
||||
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (widget);
|
||||
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
|
||||
|
||||
gtk_widget_grab_focus (priv->entry);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_class_init (DemoTaggedEntryClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->dispose = demo_tagged_entry_dispose;
|
||||
object_class->finalize = demo_tagged_entry_finalize;
|
||||
object_class->get_property = demo_tagged_entry_get_property;
|
||||
object_class->set_property = demo_tagged_entry_set_property;
|
||||
|
||||
widget_class->measure = demo_tagged_entry_measure;
|
||||
widget_class->size_allocate = demo_tagged_entry_size_allocate;
|
||||
widget_class->grab_focus = demo_tagged_entry_grab_focus;
|
||||
|
||||
gtk_editable_install_properties (object_class, 1);
|
||||
|
||||
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ENTRY_ACCESSIBLE);
|
||||
gtk_widget_class_set_css_name (widget_class, "entry");
|
||||
}
|
||||
|
||||
static GtkEditable *
|
||||
demo_tagged_entry_get_delegate (GtkEditable *editable)
|
||||
{
|
||||
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (editable);
|
||||
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
|
||||
|
||||
return GTK_EDITABLE (priv->entry);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_editable_init (GtkEditableInterface *iface)
|
||||
{
|
||||
iface->get_delegate = demo_tagged_entry_get_delegate;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
demo_tagged_entry_new (void)
|
||||
{
|
||||
return GTK_WIDGET (g_object_new (DEMO_TYPE_TAGGED_ENTRY, NULL));
|
||||
}
|
||||
|
||||
void
|
||||
demo_tagged_entry_add_tag (DemoTaggedEntry *entry,
|
||||
GtkWidget *tag)
|
||||
{
|
||||
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
|
||||
|
||||
g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (priv->box), tag);
|
||||
}
|
||||
|
||||
void
|
||||
demo_tagged_entry_insert_tag_after (DemoTaggedEntry *entry,
|
||||
GtkWidget *tag,
|
||||
GtkWidget *sibling)
|
||||
{
|
||||
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
|
||||
|
||||
g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
|
||||
|
||||
if (sibling == NULL)
|
||||
gtk_container_add (GTK_CONTAINER (priv->box), tag);
|
||||
else
|
||||
gtk_box_insert_child_after (GTK_BOX (priv->box), tag, sibling);
|
||||
}
|
||||
|
||||
void
|
||||
demo_tagged_entry_remove_tag (DemoTaggedEntry *entry,
|
||||
GtkWidget *tag)
|
||||
{
|
||||
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
|
||||
|
||||
g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
|
||||
|
||||
gtk_container_remove (GTK_CONTAINER (priv->box), tag);
|
||||
}
|
||||
|
||||
struct _DemoTaggedEntryTag
|
||||
{
|
||||
GtkWidget parent;
|
||||
GtkWidget *box;
|
||||
GtkWidget *label;
|
||||
GtkWidget *button;
|
||||
|
||||
gboolean has_close_button;
|
||||
char *style;
|
||||
};
|
||||
|
||||
struct _DemoTaggedEntryTagClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_LABEL,
|
||||
PROP_HAS_CLOSE_BUTTON,
|
||||
};
|
||||
|
||||
enum {
|
||||
SIGNAL_CLICKED,
|
||||
SIGNAL_BUTTON_CLICKED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
G_DEFINE_TYPE (DemoTaggedEntryTag, demo_tagged_entry_tag, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
on_released (GtkGestureMultiPress *gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
DemoTaggedEntryTag *tag)
|
||||
{
|
||||
g_signal_emit (tag, signals[SIGNAL_CLICKED], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_tag_init (DemoTaggedEntryTag *tag)
|
||||
{
|
||||
GtkGesture *gesture;
|
||||
GtkCssProvider *provider;
|
||||
|
||||
gtk_widget_set_has_surface (GTK_WIDGET (tag), FALSE);
|
||||
|
||||
tag->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_widget_set_parent (tag->box, GTK_WIDGET (tag));
|
||||
tag->label = gtk_label_new ("");
|
||||
gtk_container_add (GTK_CONTAINER (tag->box), tag->label);
|
||||
|
||||
gesture = gtk_gesture_multi_press_new ();
|
||||
g_signal_connect (gesture, "released", G_CALLBACK (on_released), tag);
|
||||
gtk_widget_add_controller (GTK_WIDGET (tag), GTK_EVENT_CONTROLLER (gesture));
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_resource (provider, "/tagged_entry/tagstyle.css");
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
800);
|
||||
g_object_unref (provider);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_tag_dispose (GObject *object)
|
||||
{
|
||||
DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (object);
|
||||
|
||||
g_clear_pointer (&tag->box, gtk_widget_unparent);
|
||||
|
||||
G_OBJECT_CLASS (demo_tagged_entry_tag_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_tag_finalize (GObject *object)
|
||||
{
|
||||
DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (object);
|
||||
|
||||
g_clear_pointer (&tag->box, gtk_widget_unparent);
|
||||
g_clear_pointer (&tag->style, g_free);
|
||||
|
||||
G_OBJECT_CLASS (demo_tagged_entry_tag_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_tag_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LABEL:
|
||||
demo_tagged_entry_tag_set_label (tag, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
case PROP_HAS_CLOSE_BUTTON:
|
||||
demo_tagged_entry_tag_set_has_close_button (tag, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_tag_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LABEL:
|
||||
g_value_set_string (value, demo_tagged_entry_tag_get_label (tag));
|
||||
break;
|
||||
|
||||
case PROP_HAS_CLOSE_BUTTON:
|
||||
g_value_set_boolean (value, demo_tagged_entry_tag_get_has_close_button (tag));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_tag_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (widget);
|
||||
|
||||
gtk_widget_measure (tag->box, orientation, for_size,
|
||||
minimum, natural,
|
||||
minimum_baseline, natural_baseline);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_tag_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (widget);
|
||||
|
||||
gtk_widget_size_allocate (tag->box,
|
||||
&(GtkAllocation) { 0, 0, width, height },
|
||||
baseline);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_tagged_entry_tag_class_init (DemoTaggedEntryTagClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
object_class->dispose = demo_tagged_entry_tag_dispose;
|
||||
object_class->finalize = demo_tagged_entry_tag_finalize;
|
||||
object_class->set_property = demo_tagged_entry_tag_set_property;
|
||||
object_class->get_property = demo_tagged_entry_tag_get_property;
|
||||
|
||||
widget_class->measure = demo_tagged_entry_tag_measure;
|
||||
widget_class->size_allocate = demo_tagged_entry_tag_size_allocate;
|
||||
|
||||
signals[SIGNAL_CLICKED] =
|
||||
g_signal_new ("clicked",
|
||||
DEMO_TYPE_TAGGED_ENTRY_TAG,
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
signals[SIGNAL_BUTTON_CLICKED] =
|
||||
g_signal_new ("button-clicked",
|
||||
DEMO_TYPE_TAGGED_ENTRY_TAG,
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
g_object_class_install_property (object_class, PROP_LABEL,
|
||||
g_param_spec_string ("label", "Label", "Label",
|
||||
NULL, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (object_class, PROP_HAS_CLOSE_BUTTON,
|
||||
g_param_spec_boolean ("has-close-button", "Has close button", "Whether this tag has a close button",
|
||||
FALSE, G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, "tag");
|
||||
}
|
||||
|
||||
DemoTaggedEntryTag *
|
||||
demo_tagged_entry_tag_new (const char *label)
|
||||
{
|
||||
return DEMO_TAGGED_ENTRY_TAG (g_object_new (DEMO_TYPE_TAGGED_ENTRY_TAG,
|
||||
"label", label,
|
||||
NULL));
|
||||
}
|
||||
|
||||
const char *
|
||||
demo_tagged_entry_tag_get_label (DemoTaggedEntryTag *tag)
|
||||
{
|
||||
g_return_val_if_fail (DEMO_IS_TAGGED_ENTRY_TAG (tag), NULL);
|
||||
|
||||
return gtk_label_get_label (GTK_LABEL (tag->label));
|
||||
}
|
||||
|
||||
void
|
||||
demo_tagged_entry_tag_set_label (DemoTaggedEntryTag *tag,
|
||||
const char *label)
|
||||
{
|
||||
g_return_if_fail (DEMO_IS_TAGGED_ENTRY_TAG (tag));
|
||||
|
||||
gtk_label_set_label (GTK_LABEL (tag->label), label);
|
||||
}
|
||||
|
||||
static void
|
||||
on_button_clicked (GtkButton *button,
|
||||
DemoTaggedEntryTag *tag)
|
||||
{
|
||||
g_signal_emit (tag, signals[SIGNAL_BUTTON_CLICKED], 0);
|
||||
}
|
||||
|
||||
void
|
||||
demo_tagged_entry_tag_set_has_close_button (DemoTaggedEntryTag *tag,
|
||||
gboolean has_close_button)
|
||||
{
|
||||
g_return_if_fail (DEMO_IS_TAGGED_ENTRY_TAG (tag));
|
||||
|
||||
if ((tag->button != NULL) == has_close_button)
|
||||
return;
|
||||
|
||||
if (!has_close_button && tag->button)
|
||||
{
|
||||
gtk_container_remove (GTK_CONTAINER (tag->box), tag->button);
|
||||
tag->button = NULL;
|
||||
}
|
||||
else if (has_close_button && tag->button == NULL)
|
||||
{
|
||||
GtkWidget *image;
|
||||
|
||||
image = gtk_image_new_from_icon_name ("window-close-symbolic");
|
||||
tag->button = gtk_button_new ();
|
||||
gtk_container_add (GTK_CONTAINER (tag->button), image);
|
||||
gtk_widget_set_halign (tag->button, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign (tag->button, GTK_ALIGN_CENTER);
|
||||
gtk_button_set_relief (GTK_BUTTON (tag->button), GTK_RELIEF_NONE);
|
||||
gtk_container_add (GTK_CONTAINER (tag->box), tag->button);
|
||||
g_signal_connect (tag->button, "clicked", G_CALLBACK (on_button_clicked), tag);
|
||||
}
|
||||
|
||||
g_object_notify (G_OBJECT (tag), "has-close-button");
|
||||
}
|
||||
|
||||
gboolean
|
||||
demo_tagged_entry_tag_get_has_close_button (DemoTaggedEntryTag *tag)
|
||||
{
|
||||
g_return_val_if_fail (DEMO_IS_TAGGED_ENTRY_TAG (tag), FALSE);
|
||||
|
||||
return tag->button != NULL;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2019 Red Hat, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* - Matthias Clasen <mclasen@redhat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __DEMO_TAGGED_ENTRY_H__
|
||||
#define __DEMO_TAGGED_ENTRY_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define DEMO_TYPE_TAGGED_ENTRY (demo_tagged_entry_get_type ())
|
||||
#define DEMO_TAGGED_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DEMO_TYPE_TAGGED_ENTRY, DemoTaggedEntry))
|
||||
#define DEMO_TAGGED_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DEMO_TYPE_TAGGED_ENTRY, DemoTaggedEntryClass))
|
||||
#define DEMO_IS_TAGGED_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DEMO_TYPE_TAGGED_ENTRY))
|
||||
#define DEMO_IS_TAGGED_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DEMO_TYPE_TAGGED_ENTRY))
|
||||
#define DEMO_TAGGED_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEMO_TYPE_TAGGED_ENTRY, DemoTaggedEntryClass))
|
||||
|
||||
typedef struct _DemoTaggedEntry DemoTaggedEntry;
|
||||
typedef struct _DemoTaggedEntryClass DemoTaggedEntryClass;
|
||||
|
||||
struct _DemoTaggedEntry
|
||||
{
|
||||
GtkWidget parent;
|
||||
};
|
||||
|
||||
struct _DemoTaggedEntryClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
#define DEMO_TYPE_TAGGED_ENTRY_TAG (demo_tagged_entry_tag_get_type ())
|
||||
#define DEMO_TAGGED_ENTRY_TAG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DEMO_TYPE_TAGGED_ENTRY_TAG, DemoTaggedEntryTag))
|
||||
#define DEMO_TAGGED_ENTRY_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DEMO_TYPE_TAGGED_ENTRY_TAG, DemoTaggedEntryTag))
|
||||
#define DEMO_IS_TAGGED_ENTRY_TAG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DEMO_TYPE_TAGGED_ENTRY_TAG))
|
||||
#define DEMO_IS_TAGGED_ENTRY_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DEMO_TYPE_TAGGED_ENTRY_TAG))
|
||||
#define DEMO_TAGGED_ENTRY_TAG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEMO_TYPE_TAGGED_ENTRY_TAG, DemoTaggedEntryTagClass))
|
||||
|
||||
typedef struct _DemoTaggedEntryTag DemoTaggedEntryTag;
|
||||
typedef struct _DemoTaggedEntryTagClass DemoTaggedEntryTagClass;
|
||||
|
||||
|
||||
GType demo_tagged_entry_get_type (void) G_GNUC_CONST;
|
||||
GType demo_tagged_entry_tag_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * demo_tagged_entry_new (void);
|
||||
|
||||
void demo_tagged_entry_add_tag (DemoTaggedEntry *entry,
|
||||
GtkWidget *tag);
|
||||
|
||||
void demo_tagged_entry_insert_tag_after (DemoTaggedEntry *entry,
|
||||
GtkWidget *tag,
|
||||
GtkWidget *sibling);
|
||||
|
||||
void demo_tagged_entry_remove_tag (DemoTaggedEntry *entry,
|
||||
GtkWidget *tag);
|
||||
|
||||
DemoTaggedEntryTag *
|
||||
demo_tagged_entry_tag_new (const char *label);
|
||||
|
||||
const char * demo_tagged_entry_tag_get_label (DemoTaggedEntryTag *tag);
|
||||
|
||||
void demo_tagged_entry_tag_set_label (DemoTaggedEntryTag *tag,
|
||||
const char *label);
|
||||
|
||||
gboolean demo_tagged_entry_tag_get_has_close_button (DemoTaggedEntryTag *tag);
|
||||
|
||||
void demo_tagged_entry_tag_set_has_close_button (DemoTaggedEntryTag *tag,
|
||||
gboolean has_close_button);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __DEMO_TAGGED_ENTRY_H__ */
|
||||
@@ -196,7 +196,7 @@ edit_label_done (GtkWidget *entry, gpointer data)
|
||||
GtkWidget *label;
|
||||
int x, y;
|
||||
|
||||
gtk_container_child_get (GTK_CONTAINER (fixed), entry, "x", &x, "y", &y, NULL);
|
||||
gtk_fixed_get_child_position (GTK_FIXED (fixed), entry, &x, &y);
|
||||
|
||||
label = GTK_WIDGET (g_object_get_data (G_OBJECT (entry), "label"));
|
||||
gtk_label_set_text (GTK_LABEL (label), gtk_editable_get_text (GTK_EDITABLE (entry)));
|
||||
@@ -210,7 +210,7 @@ edit_cb (GtkWidget *child)
|
||||
GtkWidget *fixed = gtk_widget_get_parent (child);
|
||||
int x, y;
|
||||
|
||||
gtk_container_child_get (GTK_CONTAINER (fixed), child, "x", &x, "y", &y, NULL);
|
||||
gtk_fixed_get_child_position (GTK_FIXED (fixed), child, &x, &y);
|
||||
|
||||
if (GTK_IS_LABEL (child))
|
||||
{
|
||||
|
||||
@@ -47,6 +47,7 @@ demos = files([
|
||||
'paintable_animated.c',
|
||||
'paintable_mediastream.c',
|
||||
'panes.c',
|
||||
'password_entry.c',
|
||||
'pickers.c',
|
||||
'pixbufs.c',
|
||||
'popover.c',
|
||||
@@ -64,6 +65,7 @@ demos = files([
|
||||
'spinner.c',
|
||||
'stack.c',
|
||||
'tabs.c',
|
||||
'tagged_entry.c',
|
||||
'textmask.c',
|
||||
'textview.c',
|
||||
'textscroll.c',
|
||||
@@ -75,7 +77,13 @@ demos = files([
|
||||
|
||||
gtkdemo_deps = [ libgtk_dep, ]
|
||||
|
||||
extra_demo_sources = files(['main.c', 'gtkfishbowl.c', 'fontplane.c', 'gtkgears.c', 'puzzlepiece.c', 'bluroverlay.c'])
|
||||
extra_demo_sources = files(['main.c',
|
||||
'gtkfishbowl.c',
|
||||
'fontplane.c',
|
||||
'gtkgears.c',
|
||||
'puzzlepiece.c',
|
||||
'bluroverlay.c',
|
||||
'demotaggedentry.c'])
|
||||
|
||||
if harfbuzz_dep.found() and pangoft_dep.found()
|
||||
demos += files('font_features.c')
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/* Entry/Password Entry
|
||||
*
|
||||
* GtkPasswordEntry provides common functionality of
|
||||
* entries that are used to enter passwords and other
|
||||
* secrets.
|
||||
*
|
||||
* It will display a warning if CapsLock is on, and it
|
||||
* can optionally provide a way to see the text.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static GtkWidget *entry;
|
||||
static GtkWidget *entry2;
|
||||
static GtkWidget *button;
|
||||
|
||||
static void
|
||||
update_button (GObject *object,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
const char *text = gtk_editable_get_text (GTK_EDITABLE (entry));
|
||||
const char *text2 = gtk_editable_get_text (GTK_EDITABLE (entry2));
|
||||
|
||||
gtk_widget_set_sensitive (button,
|
||||
text[0] != '\0' && g_str_equal (text, text2));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_password_entry (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
GtkWidget *box;
|
||||
GtkWidget *header;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Choose a Password");
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
gtk_window_set_deletable (GTK_WINDOW (window), FALSE);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
g_object_set (box, "margin", 18, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
|
||||
entry = gtk_password_entry_new ();
|
||||
gtk_password_entry_set_show_peek_icon (GTK_PASSWORD_ENTRY (entry), TRUE);
|
||||
g_object_set (entry,
|
||||
"placeholder-text", "Password",
|
||||
"activates-default", TRUE,
|
||||
NULL);
|
||||
g_signal_connect (entry, "notify::text", G_CALLBACK (update_button), NULL);
|
||||
gtk_container_add (GTK_CONTAINER (box), entry);
|
||||
|
||||
entry2 = gtk_password_entry_new ();
|
||||
gtk_password_entry_set_show_peek_icon (GTK_PASSWORD_ENTRY (entry2), TRUE);
|
||||
g_object_set (entry2,
|
||||
"placeholder-text", "Confirm",
|
||||
"activates-default", TRUE,
|
||||
NULL);
|
||||
g_signal_connect (entry2, "notify::text", G_CALLBACK (update_button), NULL);
|
||||
gtk_container_add (GTK_CONTAINER (box), entry2);
|
||||
|
||||
button = gtk_button_new_with_mnemonic ("_Done");
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (button), "suggested-action");
|
||||
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
|
||||
gtk_widget_set_sensitive (button, FALSE);
|
||||
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), button);
|
||||
|
||||
gtk_widget_set_can_default (button, TRUE);
|
||||
gtk_window_set_default (GTK_WINDOW (window), button);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/* Entry/Tagged Entry
|
||||
*
|
||||
* This example shows how to build a complex composite
|
||||
* entry using GtkText, outside of GTK.
|
||||
*
|
||||
* This tagged entry can display tags and other widgets
|
||||
* inside the entry area.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "demotaggedentry.h"
|
||||
|
||||
static GtkWidget *spinner = NULL;
|
||||
|
||||
static void
|
||||
closed_cb (DemoTaggedEntryTag *tag, DemoTaggedEntry *entry)
|
||||
{
|
||||
demo_tagged_entry_remove_tag (entry, GTK_WIDGET (tag));
|
||||
}
|
||||
|
||||
static void
|
||||
add_tag (GtkButton *button, DemoTaggedEntry *entry)
|
||||
{
|
||||
DemoTaggedEntryTag *tag;
|
||||
|
||||
tag = demo_tagged_entry_tag_new ("Blue");
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (tag)), "blue");
|
||||
demo_tagged_entry_tag_set_has_close_button (tag, TRUE);
|
||||
g_signal_connect (tag, "button-clicked", G_CALLBACK (closed_cb), entry);
|
||||
|
||||
if (spinner == NULL)
|
||||
demo_tagged_entry_add_tag (entry, GTK_WIDGET (tag));
|
||||
else
|
||||
demo_tagged_entry_insert_tag_after (entry, GTK_WIDGET (tag), gtk_widget_get_prev_sibling (spinner));
|
||||
}
|
||||
|
||||
static void
|
||||
toggle_spinner (GtkCheckButton *button, DemoTaggedEntry *entry)
|
||||
{
|
||||
if (spinner)
|
||||
{
|
||||
demo_tagged_entry_remove_tag (entry, spinner);
|
||||
spinner = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
spinner = gtk_spinner_new ();
|
||||
gtk_spinner_start (GTK_SPINNER (spinner));
|
||||
demo_tagged_entry_add_tag (entry, spinner);
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_tagged_entry (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
GtkWidget *box;
|
||||
GtkWidget *box2;
|
||||
GtkWidget *header;
|
||||
GtkWidget *entry;
|
||||
GtkWidget *button;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "A tagged entry");
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
|
||||
gtk_window_set_deletable (GTK_WINDOW (window), FALSE);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
|
||||
g_object_set (box, "margin", 18, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
|
||||
entry = demo_tagged_entry_new ();
|
||||
gtk_container_add (GTK_CONTAINER (box), entry);
|
||||
|
||||
box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
gtk_widget_set_halign (box2, GTK_ALIGN_END);
|
||||
gtk_container_add (GTK_CONTAINER (box), box2);
|
||||
|
||||
button = gtk_button_new_with_mnemonic ("Add _Tag");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (add_tag), entry);
|
||||
gtk_container_add (GTK_CONTAINER (box2), button);
|
||||
|
||||
button = gtk_check_button_new_with_mnemonic ("_Spinner");
|
||||
g_signal_connect (button, "toggled", G_CALLBACK (toggle_spinner), entry);
|
||||
gtk_container_add (GTK_CONTAINER (box2), button);
|
||||
|
||||
button = gtk_button_new_with_mnemonic ("_Done");
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (button), "suggested-action");
|
||||
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
|
||||
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), button);
|
||||
|
||||
gtk_widget_set_can_default (button, TRUE);
|
||||
gtk_window_set_default (GTK_WINDOW (window), button);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
tag {
|
||||
margin: 4px;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
background: lightskyblue;
|
||||
}
|
||||
tag box {
|
||||
border-spacing: 4px;
|
||||
}
|
||||
tag label,
|
||||
tag image {
|
||||
color: white;
|
||||
}
|
||||
tag button {
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
border: 1px solid white;
|
||||
}
|
||||
@@ -1432,6 +1432,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<object class="GtkOverlay" id="page2">
|
||||
<child type="overlay">
|
||||
<object class="GtkRevealer" id="page2revealer">
|
||||
<property name="transition-type">swing-down</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">start</property>
|
||||
<child>
|
||||
|
||||
@@ -502,7 +502,6 @@ gdk_device_get_has_cursor
|
||||
gdk_device_get_n_axes
|
||||
gdk_device_get_n_keys
|
||||
gdk_device_get_axes
|
||||
gdk_device_warp
|
||||
gdk_device_get_seat
|
||||
|
||||
<SUBSECTION>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
<FILE>GskRenderer</FILE>
|
||||
gsk_renderer_new_for_surface
|
||||
gsk_renderer_get_surface
|
||||
gsk_renderer_get_display
|
||||
gsk_renderer_realize
|
||||
gsk_renderer_unrealize
|
||||
gsk_renderer_is_realized
|
||||
gsk_renderer_render
|
||||
gsk_renderer_render_texture
|
||||
<SUBSECTION Standard>
|
||||
@@ -171,6 +171,7 @@ gsk_transform_rotate
|
||||
gsk_transform_rotate_3d
|
||||
gsk_transform_scale
|
||||
gsk_transform_scale_3d
|
||||
gsk_transform_perspective
|
||||
<SUBSECTION>
|
||||
gsk_transform_equal
|
||||
<SUBSECTION>
|
||||
|
||||
@@ -546,7 +546,7 @@ checkbutton:indeterminate {
|
||||
GTK adds several additional ways to specify colors.
|
||||
</para>
|
||||
|
||||
<literallayout><code>〈gtk color〉 = 〈symbolic color〉 | 〈color expression〉 | 〈win32 color〉</code>
|
||||
<literallayout><code>〈gtk color〉 = 〈symbolic color〉 | 〈color expression〉</code>
|
||||
</literallayout>
|
||||
|
||||
<para>
|
||||
@@ -592,13 +592,6 @@ checkbutton:indeterminate {
|
||||
|
||||
<literallayout><code>〈color expression〉 = lighter( 〈color〉 ) | darker( 〈color〉 ) | shade( 〈color〉, 〈number〉 ) |</code>
|
||||
<code> alpha( 〈color〉, 〈number〉 ) | mix( 〈color〉, 〈color〉, 〈number〉 )</code>
|
||||
</literallayout>
|
||||
|
||||
<para>
|
||||
On Windows, GTK allows to refer to system colors, as follows:
|
||||
</para>
|
||||
|
||||
<literallayout><code>〈win32 color〉 = -gtk-win32-color( 〈name〉, 〈integer〉 )</code>
|
||||
</literallayout>
|
||||
|
||||
</refsect2>
|
||||
@@ -737,7 +730,7 @@ label {
|
||||
GTK extends the CSS syntax for images and also uses it for specifying icons.
|
||||
</para>
|
||||
|
||||
<literallayout><code>〈gtk image〉 = 〈themed icon〉 | 〈scaled image〉 | 〈recolored image〉 | 〈win32 theme part〉</code>
|
||||
<literallayout><code>〈gtk image〉 = 〈themed icon〉 | 〈scaled image〉 | 〈recolored image〉</code>
|
||||
</literallayout>
|
||||
|
||||
<para>
|
||||
@@ -815,13 +808,6 @@ arrow {
|
||||
}
|
||||
]]></programlisting>
|
||||
</example>
|
||||
<para>
|
||||
On Windows, GTK allows to refer to system theme parts as images, as follows:
|
||||
</para>
|
||||
|
||||
<literallayout><code>〈win32 theme part〉 = -gtk-win32-theme-part( 〈name〉, 〈integer〉 〈integer〉</code>
|
||||
<code> [ , [ over( 〈integer〉 〈integer〉 [ , 〈alpha value〉 ]? ) | margins( 〈integer〉{1,4} ) ] ]* )</code>
|
||||
</literallayout>
|
||||
|
||||
</refsect2>
|
||||
|
||||
|
||||
@@ -65,20 +65,6 @@ We use <literallayout> for syntax productions, and each line is put in a <code>
|
||||
not quite the same as the CSS definition of rem.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Whereever a number is allowed, GTK also accepts a Windows-specific
|
||||
theme size:
|
||||
</para>
|
||||
|
||||
<literallayout>
|
||||
<code>〈win32 theme size〉 = 〈win32 size〉 | 〈win32 part size〉</code>
|
||||
<code>〈win32 size〉 = -gtk-win32-size ( 〈theme name〉, 〈metric id〉 )</code>
|
||||
<code>〈win32 part size〉 = [ -gtk-win32-part-width | -gtk-win32-part-height |</code>
|
||||
<code> -gtk-win32-part-border-top | -gtk-win32-part-border-right |</code>
|
||||
<code> -gtk-win32-part-border-bottom | -gtk-win32-part-border-left ]</code>
|
||||
<code> ( 〈theme name〉 , 〈integer〉 , 〈integer〉 )</code>
|
||||
</literallayout>
|
||||
|
||||
<literallayout><code>〈calc expression〉 = calc( 〈calc sum〉 )</code>
|
||||
<code>〈calc sum〉 = 〈calc product〉 [ [ + | - ] 〈calc product〉 ]*</code>
|
||||
<code>〈calc product〉 = 〈calc value〉 [ * 〈calc value〉 | / 〈number〉 ]*</code>
|
||||
|
||||
@@ -100,6 +100,13 @@
|
||||
<xi:include href="xml/gtkfixed.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="LayoutManagers">
|
||||
<title>Layout Managers</title>
|
||||
<xi:include href="xml/gtklayoutmanager.xml" />
|
||||
<xi:include href="xml/gtklayoutchild.xml" />
|
||||
<xi:include href="xml/gtkboxlayout.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="DisplayWidgets">
|
||||
<title>Display Widgets</title>
|
||||
<xi:include href="xml/gtklabel.xml" />
|
||||
|
||||
@@ -995,6 +995,8 @@ gtk_entry_get_type
|
||||
<TITLE>GtkPasswordEntry</TITLE>
|
||||
GtkPasswordEntry
|
||||
gtk_password_entry_new
|
||||
gtk_password_entry_set_show_peek_icon
|
||||
gtk_password_entry_get_show_peek_icon
|
||||
<SUBSECTION Private>
|
||||
gtk_password_entry_get_type
|
||||
</SECTION>
|
||||
@@ -4388,6 +4390,7 @@ gtk_snapshot_rotate
|
||||
gtk_snapshot_rotate_3d
|
||||
gtk_snapshot_scale
|
||||
gtk_snapshot_scale_3d
|
||||
gtk_snapshot_perspective
|
||||
gtk_snapshot_append_node
|
||||
gtk_snapshot_append_cairo
|
||||
gtk_snapshot_append_texture
|
||||
@@ -4587,6 +4590,8 @@ gtk_widget_get_first_child
|
||||
gtk_widget_get_last_child
|
||||
gtk_widget_insert_before
|
||||
gtk_widget_insert_after
|
||||
gtk_widget_set_layout_manager
|
||||
gtk_widget_get_layout_manager
|
||||
|
||||
<SUBSECTION>
|
||||
gtk_widget_get_path
|
||||
@@ -6681,6 +6686,8 @@ gtk_event_controller_scroll_get_type
|
||||
<TITLE>GtkEventControllerMotion</TITLE>
|
||||
GtkEventControllerMotion
|
||||
gtk_event_controller_motion_new
|
||||
gtk_event_controller_motion_get_pointer_origin
|
||||
gtk_event_controller_motion_get_pointer_target
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_EVENT_CONTROLLER_MOTION
|
||||
@@ -6699,6 +6706,12 @@ gtk_event_controller_motion_get_type
|
||||
<TITLE>GtkEventControllerKey</TITLE>
|
||||
GtkEventControllerKey
|
||||
gtk_event_controller_key_new
|
||||
gtk_event_controller_key_set_im_context
|
||||
gtk_event_controller_key_get_im_context
|
||||
gtk_event_controller_key_forward
|
||||
gtk_event_controller_key_get_group
|
||||
gtk_event_controller_key_get_focus_origin
|
||||
gtk_event_controller_key_get_focus_target
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_EVENT_CONTROLLER_KEY
|
||||
@@ -7141,3 +7154,51 @@ gtk_root_get_for_surface
|
||||
<SUBSECTION Private>
|
||||
gtk_root_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtklayoutmanager</FILE>
|
||||
GtkLayoutManager
|
||||
GtkLayoutManagerClass
|
||||
|
||||
gtk_layout_manager_measure
|
||||
gtk_layout_manager_allocate
|
||||
gtk_layout_manager_get_request_mode
|
||||
gtk_layout_manager_get_widget
|
||||
gtk_layout_manager_get_layout_child
|
||||
gtk_layout_manager_layout_changed
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_LAYOUT_MANAGER
|
||||
gtk_layout_manager_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtklayoutchild</FILE>
|
||||
GtkLayoutChild
|
||||
GtkLayoutChildClass
|
||||
|
||||
gtk_layout_child_get_layout_manager
|
||||
gtk_layout_child_get_child_widget
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_LAYOUT_CHILD
|
||||
gtk_layout_child_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkboxlayout</FILE>
|
||||
GtkBoxLayout
|
||||
GtkBoxLayoutClass
|
||||
|
||||
gtk_box_layout_new
|
||||
gtk_box_layout_set_homogeneous
|
||||
gtk_box_layout_get_homogeneous
|
||||
gtk_box_layout_set_spacing
|
||||
gtk_box_layout_get_spacing
|
||||
gtk_box_layout_set_baseline_position
|
||||
gtk_box_layout_get_baseline_position
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_BOX_LAYOUT
|
||||
gtk_box_layout_get_type
|
||||
</SECTION>
|
||||
|
||||
@@ -22,6 +22,9 @@ typedef enum { /* Sync changes with broadway.js */
|
||||
BROADWAY_NODE_CLIP = 10,
|
||||
BROADWAY_NODE_KEEP_ALL = 11,
|
||||
BROADWAY_NODE_KEEP_THIS = 12,
|
||||
BROADWAY_NODE_TRANSLATE = 13,
|
||||
BROADWAY_NODE_DEBUG = 14,
|
||||
BROADWAY_NODE_REUSE = 15,
|
||||
} BroadwayNodeType;
|
||||
|
||||
static const char *broadway_node_type_names[] G_GNUC_UNUSED = {
|
||||
@@ -38,6 +41,8 @@ static const char *broadway_node_type_names[] G_GNUC_UNUSED = {
|
||||
"CLIP",
|
||||
"KEEP_ALL",
|
||||
"KEEP_THIS",
|
||||
"TRANSLATE",
|
||||
"DEBUG",
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
||||
+243
-26
@@ -35,7 +35,6 @@
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
guint32 tag;
|
||||
@@ -126,23 +125,56 @@ struct BroadwaySurface {
|
||||
gint32 transient_for;
|
||||
guint32 texture;
|
||||
BroadwayNode *nodes;
|
||||
GHashTable *node_lookup;
|
||||
};
|
||||
|
||||
struct _BroadwayTexture {
|
||||
grefcount refcount;
|
||||
guint32 id;
|
||||
GBytes *bytes;
|
||||
};
|
||||
|
||||
static void broadway_server_resync_surfaces (BroadwayServer *server);
|
||||
static void send_outstanding_roundtrips (BroadwayServer *server);
|
||||
|
||||
static void broadway_server_ref_texture (BroadwayServer *server,
|
||||
guint32 id);
|
||||
|
||||
static GType broadway_server_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (BroadwayServer, broadway_server, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
broadway_node_free (BroadwayNode *node)
|
||||
broadway_texture_free (BroadwayTexture *texture)
|
||||
{
|
||||
g_bytes_unref (texture->bytes);
|
||||
g_free (texture);
|
||||
}
|
||||
|
||||
static void
|
||||
broadway_node_unref (BroadwayServer *server,
|
||||
BroadwayNode *node)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < node->n_children; i++)
|
||||
broadway_node_free (node->children[i]);
|
||||
|
||||
g_free (node);
|
||||
if (g_ref_count_dec (&node->refcount))
|
||||
{
|
||||
for (i = 0; i < node->n_children; i++)
|
||||
broadway_node_unref (server, node->children[i]);
|
||||
|
||||
if (node->texture_id)
|
||||
broadway_server_release_texture (server, node->texture_id);
|
||||
|
||||
g_free (node);
|
||||
}
|
||||
}
|
||||
|
||||
static BroadwayNode *
|
||||
broadway_node_ref (BroadwayNode *node)
|
||||
{
|
||||
g_ref_count_inc (&node->refcount);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -204,7 +236,7 @@ broadway_server_init (BroadwayServer *server)
|
||||
server->surface_id_hash = g_hash_table_new (NULL, NULL);
|
||||
server->id_counter = 0;
|
||||
server->textures = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
|
||||
(GDestroyNotify)g_bytes_unref);
|
||||
(GDestroyNotify)broadway_texture_free);
|
||||
|
||||
root = g_new0 (BroadwaySurface, 1);
|
||||
root->id = server->id_counter++;
|
||||
@@ -241,10 +273,12 @@ broadway_server_class_init (BroadwayServerClass * class)
|
||||
}
|
||||
|
||||
static void
|
||||
broadway_surface_free (BroadwaySurface *surface)
|
||||
broadway_surface_free (BroadwayServer *server,
|
||||
BroadwaySurface *surface)
|
||||
{
|
||||
if (surface->nodes)
|
||||
broadway_node_free (surface->nodes);
|
||||
broadway_node_unref (server, surface->nodes);
|
||||
g_hash_table_unref (surface->node_lookup);
|
||||
g_free (surface);
|
||||
}
|
||||
|
||||
@@ -1477,7 +1511,7 @@ broadway_server_destroy_surface (BroadwayServer *server,
|
||||
server->surfaces = g_list_remove (server->surfaces, surface);
|
||||
g_hash_table_remove (server->surface_id_hash,
|
||||
GINT_TO_POINTER (id));
|
||||
broadway_surface_free (surface);
|
||||
broadway_surface_free (server, surface);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1605,53 +1639,232 @@ broadway_server_has_client (BroadwayServer *server)
|
||||
return server->output != NULL;
|
||||
}
|
||||
|
||||
#define NODE_SIZE_COLOR 1
|
||||
#define NODE_SIZE_FLOAT 1
|
||||
#define NODE_SIZE_POINT 2
|
||||
#define NODE_SIZE_SIZE 2
|
||||
#define NODE_SIZE_RECT (NODE_SIZE_POINT + NODE_SIZE_SIZE)
|
||||
#define NODE_SIZE_RRECT (NODE_SIZE_RECT + 4 * NODE_SIZE_SIZE)
|
||||
#define NODE_SIZE_COLOR_STOP (NODE_SIZE_FLOAT + NODE_SIZE_COLOR)
|
||||
#define NODE_SIZE_SHADOW (NODE_SIZE_COLOR + 3 * NODE_SIZE_FLOAT)
|
||||
|
||||
static guint32
|
||||
rotl (guint32 value, int shift)
|
||||
{
|
||||
if ((shift &= 32 - 1) == 0)
|
||||
return value;
|
||||
return (value << shift) | (value >> (32 - shift));
|
||||
}
|
||||
|
||||
static BroadwayNode *
|
||||
decode_nodes (BroadwayServer *server,
|
||||
BroadwaySurface *surface,
|
||||
int len,
|
||||
guint32 data[],
|
||||
GHashTable *client_texture_map,
|
||||
int *pos)
|
||||
{
|
||||
BroadwayNode *node;
|
||||
guint32 type, id;
|
||||
guint32 i, n_stops, n_shadows, n_chars;
|
||||
guint32 size, n_children;
|
||||
gint32 texture_offset;
|
||||
guint32 hash;
|
||||
|
||||
g_assert (*pos < len);
|
||||
|
||||
size = 0;
|
||||
n_children = 0;
|
||||
texture_offset = -1;
|
||||
|
||||
type = data[(*pos)++];
|
||||
id = data[(*pos)++];
|
||||
switch (type) {
|
||||
case BROADWAY_NODE_REUSE:
|
||||
node = g_hash_table_lookup (surface->node_lookup, GINT_TO_POINTER(id));
|
||||
g_assert (node != NULL);
|
||||
return broadway_node_ref (node);
|
||||
break;
|
||||
case BROADWAY_NODE_COLOR:
|
||||
size = NODE_SIZE_RECT + NODE_SIZE_COLOR;
|
||||
break;
|
||||
case BROADWAY_NODE_BORDER:
|
||||
size = NODE_SIZE_RRECT + 4 * NODE_SIZE_FLOAT + 4 * NODE_SIZE_COLOR;
|
||||
break;
|
||||
case BROADWAY_NODE_INSET_SHADOW:
|
||||
case BROADWAY_NODE_OUTSET_SHADOW:
|
||||
size = NODE_SIZE_RRECT + NODE_SIZE_COLOR + 4 * NODE_SIZE_FLOAT;
|
||||
break;
|
||||
case BROADWAY_NODE_TEXTURE:
|
||||
texture_offset = 4;
|
||||
size = 5;
|
||||
break;
|
||||
case BROADWAY_NODE_CONTAINER:
|
||||
size = 1;
|
||||
n_children = data[*pos];
|
||||
break;
|
||||
case BROADWAY_NODE_ROUNDED_CLIP:
|
||||
size = NODE_SIZE_RRECT;
|
||||
n_children = 1;
|
||||
break;
|
||||
case BROADWAY_NODE_CLIP:
|
||||
size = NODE_SIZE_RECT;
|
||||
n_children = 1;
|
||||
break;
|
||||
case BROADWAY_NODE_TRANSLATE:
|
||||
size = NODE_SIZE_POINT;
|
||||
n_children = 1;
|
||||
break;
|
||||
case BROADWAY_NODE_LINEAR_GRADIENT:
|
||||
size = NODE_SIZE_RECT + 2 * NODE_SIZE_POINT;
|
||||
n_stops = data[*pos + size++];
|
||||
size += n_stops * NODE_SIZE_COLOR_STOP;
|
||||
break;
|
||||
case BROADWAY_NODE_SHADOW:
|
||||
size = 1;
|
||||
n_shadows = data[*pos];
|
||||
size += n_shadows * NODE_SIZE_SHADOW;
|
||||
n_children = 1;
|
||||
break;
|
||||
case BROADWAY_NODE_OPACITY:
|
||||
size = NODE_SIZE_FLOAT;
|
||||
n_children = 1;
|
||||
break;
|
||||
case BROADWAY_NODE_DEBUG:
|
||||
n_chars = data[*pos];
|
||||
size = 1 + (n_chars + 3) / 4;
|
||||
n_children = 1;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
node = g_malloc (sizeof(BroadwayNode) + (size - 1) * sizeof(guint32) + n_children * sizeof (BroadwayNode *));
|
||||
g_ref_count_init (&node->refcount);
|
||||
node->type = type;
|
||||
node->id = id;
|
||||
node->texture_id = 0;
|
||||
node->n_children = n_children;
|
||||
node->children = (BroadwayNode **)((char *)node + sizeof(BroadwayNode) + (size - 1) * sizeof(guint32));
|
||||
node->n_data = size;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
node->data[i] = data[(*pos)++];
|
||||
if (i == texture_offset)
|
||||
{
|
||||
node->texture_id = GPOINTER_TO_INT (g_hash_table_lookup (client_texture_map, GINT_TO_POINTER (node->data[i])));
|
||||
broadway_server_ref_texture (server, node->texture_id);
|
||||
node->data[i] = node->texture_id;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n_children; i++)
|
||||
node->children[i] = decode_nodes (server, surface, len, data, client_texture_map, pos);
|
||||
|
||||
hash = node->type << 16;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
hash ^= rotl (node->data[i], i);
|
||||
|
||||
for (i = 0; i < n_children; i++)
|
||||
hash ^= rotl (node->children[i]->hash, i);
|
||||
|
||||
node->hash = hash;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static void
|
||||
init_node_lookup (BroadwaySurface *surface,
|
||||
BroadwayNode *node)
|
||||
{
|
||||
int i;
|
||||
|
||||
g_hash_table_insert (surface->node_lookup, GINT_TO_POINTER(node->id), node);
|
||||
for (i = 0; i < node->n_children; i++)
|
||||
init_node_lookup (surface, node->children[i]);
|
||||
}
|
||||
|
||||
/* passes ownership of nodes */
|
||||
void
|
||||
broadway_server_surface_set_nodes (BroadwayServer *server,
|
||||
gint id,
|
||||
BroadwayNode *root)
|
||||
broadway_server_surface_update_nodes (BroadwayServer *server,
|
||||
gint id,
|
||||
guint32 data[],
|
||||
int len,
|
||||
GHashTable *client_texture_map)
|
||||
{
|
||||
BroadwaySurface *surface;
|
||||
int pos = 0;
|
||||
BroadwayNode *root;
|
||||
|
||||
surface = broadway_server_lookup_surface (server, id);
|
||||
if (surface == NULL)
|
||||
return;
|
||||
|
||||
root = decode_nodes (server, surface, len, data, client_texture_map, &pos);
|
||||
|
||||
if (server->output != NULL)
|
||||
broadway_output_surface_set_nodes (server->output, surface->id,
|
||||
root,
|
||||
surface->nodes);
|
||||
|
||||
if (surface->nodes)
|
||||
broadway_node_free (surface->nodes);
|
||||
broadway_node_unref (server, surface->nodes);
|
||||
|
||||
surface->nodes = root;
|
||||
|
||||
g_hash_table_remove_all (surface->node_lookup);
|
||||
|
||||
init_node_lookup (surface, surface->nodes);
|
||||
}
|
||||
|
||||
guint32
|
||||
broadway_server_upload_texture (BroadwayServer *server,
|
||||
GBytes *texture)
|
||||
GBytes *bytes)
|
||||
{
|
||||
guint32 id;
|
||||
BroadwayTexture *texture;
|
||||
|
||||
texture = g_new0 (BroadwayTexture, 1);
|
||||
g_ref_count_init (&texture->refcount);
|
||||
texture->id = ++server->next_texture_id;
|
||||
texture->bytes = g_bytes_ref (bytes);
|
||||
|
||||
id = ++server->next_texture_id;
|
||||
g_hash_table_replace (server->textures,
|
||||
GINT_TO_POINTER (id),
|
||||
g_bytes_ref (texture));
|
||||
GINT_TO_POINTER (texture->id),
|
||||
texture);
|
||||
|
||||
if (server->output)
|
||||
broadway_output_upload_texture (server->output, id, texture);
|
||||
broadway_output_upload_texture (server->output, texture->id, texture->bytes);
|
||||
|
||||
return id;
|
||||
return texture->id;
|
||||
}
|
||||
|
||||
static void
|
||||
broadway_server_ref_texture (BroadwayServer *server,
|
||||
guint32 id)
|
||||
{
|
||||
BroadwayTexture *texture;
|
||||
|
||||
texture = g_hash_table_lookup (server->textures, GINT_TO_POINTER (id));
|
||||
if (texture)
|
||||
g_ref_count_inc (&texture->refcount);
|
||||
}
|
||||
|
||||
void
|
||||
broadway_server_release_texture (BroadwayServer *server,
|
||||
guint32 id)
|
||||
{
|
||||
g_hash_table_remove (server->textures, GINT_TO_POINTER (id));
|
||||
BroadwayTexture *texture;
|
||||
|
||||
if (server->output)
|
||||
broadway_output_release_texture (server->output, id);
|
||||
texture = g_hash_table_lookup (server->textures, GINT_TO_POINTER (id));
|
||||
|
||||
if (texture && g_ref_count_dec (&texture->refcount))
|
||||
{
|
||||
g_hash_table_remove (server->textures, GINT_TO_POINTER (id));
|
||||
|
||||
if (server->output)
|
||||
broadway_output_release_texture (server->output, id);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -1801,6 +2014,7 @@ broadway_server_new_surface (BroadwayServer *server,
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
surface->is_temp = is_temp;
|
||||
surface->node_lookup = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
|
||||
g_hash_table_insert (server->surface_id_hash,
|
||||
GINT_TO_POINTER (surface->id),
|
||||
@@ -1835,9 +2049,12 @@ broadway_server_resync_surfaces (BroadwayServer *server)
|
||||
/* First upload all textures */
|
||||
g_hash_table_iter_init (&iter, server->textures);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
broadway_output_upload_texture (server->output,
|
||||
GPOINTER_TO_INT (key),
|
||||
(GBytes *)value);
|
||||
{
|
||||
BroadwayTexture *texture = value;
|
||||
broadway_output_upload_texture (server->output,
|
||||
GPOINTER_TO_INT (key),
|
||||
texture->bytes);
|
||||
}
|
||||
|
||||
/* Then create all surfaces */
|
||||
for (l = server->surfaces; l != NULL; l = l->next)
|
||||
|
||||
@@ -19,12 +19,16 @@ typedef struct _BroadwayServerClass BroadwayServerClass;
|
||||
#define BROADWAY_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BROADWAY_TYPE_SERVER, BroadwayServerClass))
|
||||
|
||||
typedef struct _BroadwayNode BroadwayNode;
|
||||
typedef struct _BroadwayTexture BroadwayTexture;
|
||||
|
||||
struct _BroadwayNode {
|
||||
grefcount refcount;
|
||||
guint32 type;
|
||||
guint32 id;
|
||||
guint32 hash; /* deep hash */
|
||||
guint32 n_children;
|
||||
BroadwayNode **children;
|
||||
guint32 texture_id;
|
||||
guint32 n_data;
|
||||
guint32 data[1];
|
||||
};
|
||||
@@ -99,9 +103,11 @@ void broadway_server_release_texture (BroadwayServer *
|
||||
guint32 id);
|
||||
cairo_surface_t * broadway_server_create_surface (int width,
|
||||
int height);
|
||||
void broadway_server_surface_set_nodes (BroadwayServer *server,
|
||||
void broadway_server_surface_update_nodes (BroadwayServer *server,
|
||||
gint id,
|
||||
BroadwayNode *root);
|
||||
guint32 data[],
|
||||
int len,
|
||||
GHashTable *client_texture_map);
|
||||
gboolean broadway_server_surface_move_resize (BroadwayServer *server,
|
||||
gint id,
|
||||
gboolean with_move,
|
||||
|
||||
+500
-276
File diff suppressed because it is too large
Load Diff
+3
-116
@@ -215,116 +215,6 @@ get_client_serial (BroadwayClient *client, guint32 daemon_serial)
|
||||
return client_serial;
|
||||
}
|
||||
|
||||
#define NODE_SIZE_COLOR 1
|
||||
#define NODE_SIZE_FLOAT 1
|
||||
#define NODE_SIZE_POINT 2
|
||||
#define NODE_SIZE_SIZE 2
|
||||
#define NODE_SIZE_RECT (NODE_SIZE_POINT + NODE_SIZE_SIZE)
|
||||
#define NODE_SIZE_RRECT (NODE_SIZE_RECT + 4 * NODE_SIZE_SIZE)
|
||||
#define NODE_SIZE_COLOR_STOP (NODE_SIZE_FLOAT + NODE_SIZE_COLOR)
|
||||
#define NODE_SIZE_SHADOW (NODE_SIZE_COLOR + 3 * NODE_SIZE_FLOAT)
|
||||
|
||||
static guint32
|
||||
rotl (guint32 value, int shift)
|
||||
{
|
||||
if ((shift &= 32 - 1) == 0)
|
||||
return value;
|
||||
return (value << shift) | (value >> (32 - shift));
|
||||
}
|
||||
|
||||
static BroadwayNode *
|
||||
decode_nodes (BroadwayClient *client,
|
||||
int len, guint32 data[], int *pos)
|
||||
{
|
||||
BroadwayNode *node;
|
||||
guint32 type;
|
||||
guint32 i, n_stops, n_shadows;
|
||||
guint32 size, n_children;
|
||||
gint32 texture_offset;
|
||||
guint32 hash;
|
||||
|
||||
g_assert (*pos < len);
|
||||
|
||||
size = 0;
|
||||
n_children = 0;
|
||||
texture_offset = -1;
|
||||
|
||||
type = data[(*pos)++];
|
||||
switch (type) {
|
||||
case BROADWAY_NODE_COLOR:
|
||||
size = NODE_SIZE_RECT + NODE_SIZE_COLOR;
|
||||
break;
|
||||
case BROADWAY_NODE_BORDER:
|
||||
size = NODE_SIZE_RRECT + 4 * NODE_SIZE_FLOAT + 4 * NODE_SIZE_COLOR;
|
||||
break;
|
||||
case BROADWAY_NODE_INSET_SHADOW:
|
||||
case BROADWAY_NODE_OUTSET_SHADOW:
|
||||
size = NODE_SIZE_RRECT + NODE_SIZE_COLOR + 4 * NODE_SIZE_FLOAT;
|
||||
break;
|
||||
case BROADWAY_NODE_TEXTURE:
|
||||
texture_offset = 4;
|
||||
size = 5;
|
||||
break;
|
||||
case BROADWAY_NODE_CONTAINER:
|
||||
size = 1;
|
||||
n_children = data[*pos];
|
||||
break;
|
||||
case BROADWAY_NODE_ROUNDED_CLIP:
|
||||
size = NODE_SIZE_RRECT;
|
||||
n_children = 1;
|
||||
break;
|
||||
case BROADWAY_NODE_CLIP:
|
||||
size = NODE_SIZE_RECT;
|
||||
n_children = 1;
|
||||
break;
|
||||
case BROADWAY_NODE_LINEAR_GRADIENT:
|
||||
size = NODE_SIZE_RECT + 2 * NODE_SIZE_POINT;
|
||||
n_stops = data[*pos + size++];
|
||||
size += n_stops * NODE_SIZE_COLOR_STOP;
|
||||
break;
|
||||
case BROADWAY_NODE_SHADOW:
|
||||
size = 1;
|
||||
n_shadows = data[*pos];
|
||||
size += n_shadows * NODE_SIZE_SHADOW;
|
||||
n_children = 1;
|
||||
break;
|
||||
case BROADWAY_NODE_OPACITY:
|
||||
size = NODE_SIZE_FLOAT;
|
||||
n_children = 1;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
node = g_malloc (sizeof(BroadwayNode) + (size - 1) * sizeof(guint32) + n_children * sizeof (BroadwayNode *));
|
||||
node->type = type;
|
||||
node->n_children = n_children;
|
||||
node->children = (BroadwayNode **)((char *)node + sizeof(BroadwayNode) + (size - 1) * sizeof(guint32));
|
||||
node->n_data = size;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
node->data[i] = data[(*pos)++];
|
||||
if (i == texture_offset)
|
||||
node->data[i] = GPOINTER_TO_INT (g_hash_table_lookup (client->textures,
|
||||
GINT_TO_POINTER (node->data[i])));
|
||||
}
|
||||
|
||||
for (i = 0; i < n_children; i++)
|
||||
node->children[i] = decode_nodes (client, len, data, pos);
|
||||
|
||||
hash = node->type << 16;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
hash ^= rotl (node->data[i], i);
|
||||
|
||||
for (i = 0; i < n_children; i++)
|
||||
hash ^= rotl (node->children[i]->hash, i);
|
||||
|
||||
node->hash = hash;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static void
|
||||
client_handle_request (BroadwayClient *client,
|
||||
BroadwayRequest *request)
|
||||
@@ -400,13 +290,10 @@ client_handle_request (BroadwayClient *client,
|
||||
{
|
||||
gsize array_size = request->base.size - sizeof (BroadwayRequestSetNodes) + sizeof(guint32);
|
||||
int n_data = array_size / sizeof(guint32);
|
||||
int pos = 0;
|
||||
BroadwayNode *node;
|
||||
|
||||
node = decode_nodes (client, n_data, request->set_nodes.data, &pos);
|
||||
|
||||
broadway_server_surface_set_nodes (server, request->set_nodes.id,
|
||||
node);
|
||||
broadway_server_surface_update_nodes (server, request->set_nodes.id,
|
||||
request->set_nodes.data, n_data,
|
||||
client->textures);
|
||||
}
|
||||
break;
|
||||
case BROADWAY_REQUEST_UPLOAD_TEXTURE:
|
||||
|
||||
@@ -36,9 +36,6 @@ static void gdk_broadway_device_get_state (GdkDevice *device,
|
||||
static void gdk_broadway_device_set_surface_cursor (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
GdkCursor *cursor);
|
||||
static void gdk_broadway_device_warp (GdkDevice *device,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
static void gdk_broadway_device_query_state (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
GdkSurface **child_surface,
|
||||
@@ -73,7 +70,6 @@ gdk_broadway_device_class_init (GdkBroadwayDeviceClass *klass)
|
||||
device_class->get_history = gdk_broadway_device_get_history;
|
||||
device_class->get_state = gdk_broadway_device_get_state;
|
||||
device_class->set_surface_cursor = gdk_broadway_device_set_surface_cursor;
|
||||
device_class->warp = gdk_broadway_device_warp;
|
||||
device_class->query_state = gdk_broadway_device_query_state;
|
||||
device_class->grab = gdk_broadway_device_grab;
|
||||
device_class->ungrab = gdk_broadway_device_ungrab;
|
||||
@@ -126,13 +122,6 @@ gdk_broadway_device_set_surface_cursor (GdkDevice *device,
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_device_warp (GdkDevice *device,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_device_query_state (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
|
||||
@@ -380,7 +380,7 @@ gdk_broadway_display_ensure_texture (GdkDisplay *display,
|
||||
data = g_new0 (BroadwayTextureData, 1);
|
||||
data->id = id;
|
||||
data->display = g_object_ref (display);
|
||||
g_object_set_data_full (G_OBJECT (texture), "broadway-data", data, (GDestroyNotify)broadway_texture_data_free);
|
||||
g_object_set_data_full (G_OBJECT (texture), "broadway-data", data, (GDestroyNotify)broadway_texture_data_free);
|
||||
}
|
||||
|
||||
return data->id;
|
||||
|
||||
@@ -64,6 +64,8 @@ gdk_broadway_draw_context_end_frame (GdkDrawContext *draw_context,
|
||||
|
||||
g_array_unref (self->nodes);
|
||||
self->nodes = NULL;
|
||||
|
||||
/* We now sent all new texture refs to the daemon via the nodes, so we can drop them here */
|
||||
g_ptr_array_unref (self->node_textures);
|
||||
self->node_textures = NULL;
|
||||
}
|
||||
|
||||
@@ -1232,6 +1232,9 @@ gdk_broadway_surface_begin_resize_drag (GdkSurface *surface,
|
||||
|
||||
mv_resize = get_move_resize_data (gdk_surface_get_display (surface), TRUE);
|
||||
|
||||
if (mv_resize->moveresize_surface != NULL)
|
||||
return; /* already a drag operation in progress */
|
||||
|
||||
mv_resize->is_resize = TRUE;
|
||||
mv_resize->moveresize_button = button;
|
||||
mv_resize->resize_edge = edge;
|
||||
@@ -1272,6 +1275,9 @@ gdk_broadway_surface_begin_move_drag (GdkSurface *surface,
|
||||
|
||||
mv_resize = get_move_resize_data (gdk_surface_get_display (surface), TRUE);
|
||||
|
||||
if (mv_resize->moveresize_surface != NULL)
|
||||
return; /* already a drag operation in progress */
|
||||
|
||||
mv_resize->is_resize = FALSE;
|
||||
mv_resize->moveresize_button = button;
|
||||
mv_resize->moveresize_x = root_x;
|
||||
|
||||
@@ -20,8 +20,6 @@ void gdk_surface_thaw_toplevel_updates (GdkSurface *surface);
|
||||
|
||||
gboolean gdk_surface_supports_edge_constraints (GdkSurface *surface);
|
||||
|
||||
GObject * gdk_event_get_user_data (const GdkEvent *event);
|
||||
|
||||
guint32 gdk_display_get_last_seen_time (GdkDisplay *display);
|
||||
|
||||
void gdk_display_set_double_click_time (GdkDisplay *display,
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
#include "gdk-private.h"
|
||||
|
||||
#include "gdkconstructor.h"
|
||||
|
||||
#ifndef HAVE_XCONVERTCASE
|
||||
#include "gdkkeysyms.h"
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
If G_HAS_CONSTRUCTORS is true then the compiler support *both* constructors and
|
||||
destructors, in a sane way, including e.g. on library unload. If not you're on
|
||||
your own.
|
||||
|
||||
Some compilers need #pragma to handle this, which does not work with macros,
|
||||
so the way you need to use this is (for constructors):
|
||||
|
||||
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
|
||||
#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(my_constructor)
|
||||
#endif
|
||||
G_DEFINE_CONSTRUCTOR(my_constructor)
|
||||
static void my_constructor(void) {
|
||||
...
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __GTK_DOC_IGNORE__
|
||||
|
||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
|
||||
|
||||
#define G_HAS_CONSTRUCTORS 1
|
||||
|
||||
#define G_DEFINE_CONSTRUCTOR(_func) static void __attribute__((constructor)) _func (void);
|
||||
#define G_DEFINE_DESTRUCTOR(_func) static void __attribute__((destructor)) _func (void);
|
||||
|
||||
#elif defined (_MSC_VER) && (_MSC_VER >= 1500)
|
||||
/* Visual studio 2008 and later has _Pragma */
|
||||
|
||||
#define G_HAS_CONSTRUCTORS 1
|
||||
|
||||
/* We do some weird things to avoid the constructors being optimized
|
||||
* away on VS2015 if WholeProgramOptimization is enabled. First we
|
||||
* make a reference to the array from the wrapper to make sure its
|
||||
* references. Then we use a pragma to make sure the wrapper function
|
||||
* symbol is always included at the link stage. Also, the symbols
|
||||
* need to be extern (but not dllexport), even though they are not
|
||||
* really used from another object file.
|
||||
*/
|
||||
|
||||
/* We need to account for differences between the mangling of symbols
|
||||
* for Win32 (x86) and x64 programs, as symbols on Win32 are prefixed
|
||||
* with an underscore but symbols on x64 are not.
|
||||
*/
|
||||
#ifdef _WIN64
|
||||
#define G_MSVC_SYMBOL_PREFIX ""
|
||||
#else
|
||||
#define G_MSVC_SYMBOL_PREFIX "_"
|
||||
#endif
|
||||
|
||||
#define G_DEFINE_CONSTRUCTOR(_func) G_MSVC_CTOR (_func, G_MSVC_SYMBOL_PREFIX)
|
||||
#define G_DEFINE_DESTRUCTOR(_func) G_MSVC_DTOR (_func, G_MSVC_SYMBOL_PREFIX)
|
||||
|
||||
#define G_MSVC_CTOR(_func,_sym_prefix) \
|
||||
static void _func(void); \
|
||||
extern int (* _array ## _func)(void); \
|
||||
int _func ## _wrapper(void) { _func(); g_slist_find (NULL, _array ## _func); return 0; } \
|
||||
__pragma(comment(linker,"/include:" _sym_prefix # _func "_wrapper")) \
|
||||
__pragma(section(".CRT$XCU",read)) \
|
||||
__declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _wrapper;
|
||||
|
||||
#define G_MSVC_DTOR(_func,_sym_prefix) \
|
||||
static void _func(void); \
|
||||
extern int (* _array ## _func)(void); \
|
||||
int _func ## _constructor(void) { atexit (_func); g_slist_find (NULL, _array ## _func); return 0; } \
|
||||
__pragma(comment(linker,"/include:" _sym_prefix # _func "_constructor")) \
|
||||
__pragma(section(".CRT$XCU",read)) \
|
||||
__declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _constructor;
|
||||
|
||||
#elif defined (_MSC_VER)
|
||||
|
||||
#define G_HAS_CONSTRUCTORS 1
|
||||
|
||||
/* Pre Visual studio 2008 must use #pragma section */
|
||||
#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
|
||||
#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
|
||||
|
||||
#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
|
||||
section(".CRT$XCU",read)
|
||||
#define G_DEFINE_CONSTRUCTOR(_func) \
|
||||
static void _func(void); \
|
||||
static int _func ## _wrapper(void) { _func(); return 0; } \
|
||||
__declspec(allocate(".CRT$XCU")) static int (*p)(void) = _func ## _wrapper;
|
||||
|
||||
#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
|
||||
section(".CRT$XCU",read)
|
||||
#define G_DEFINE_DESTRUCTOR(_func) \
|
||||
static void _func(void); \
|
||||
static int _func ## _constructor(void) { atexit (_func); return 0; } \
|
||||
__declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor;
|
||||
|
||||
#elif defined(__SUNPRO_C)
|
||||
|
||||
/* This is not tested, but i believe it should work, based on:
|
||||
* http://opensource.apple.com/source/OpenSSL098/OpenSSL098-35/src/fips/fips_premain.c
|
||||
*/
|
||||
|
||||
#define G_HAS_CONSTRUCTORS 1
|
||||
|
||||
#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
|
||||
#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
|
||||
|
||||
#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
|
||||
init(_func)
|
||||
#define G_DEFINE_CONSTRUCTOR(_func) \
|
||||
static void _func(void);
|
||||
|
||||
#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
|
||||
fini(_func)
|
||||
#define G_DEFINE_DESTRUCTOR(_func) \
|
||||
static void _func(void);
|
||||
|
||||
#else
|
||||
|
||||
/* constructors not supported for this compiler */
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __GTK_DOC_IGNORE__ */
|
||||
@@ -1425,34 +1425,6 @@ gdk_device_ungrab (GdkDevice *device,
|
||||
GDK_DEVICE_GET_CLASS (device)->ungrab (device, time_);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_device_warp:
|
||||
* @device: the device to warp.
|
||||
* @x: the X coordinate of the destination.
|
||||
* @y: the Y coordinate of the destination.
|
||||
*
|
||||
* Warps @device in @display to the point @x,@y,
|
||||
* unless the device is confined to a surface by a grab,
|
||||
* in which case it will be moved
|
||||
* as far as allowed by the grab. Warping the pointer
|
||||
* creates events as if the user had moved the mouse
|
||||
* instantaneously to the destination.
|
||||
*
|
||||
* Note that the pointer should normally be under the
|
||||
* control of the user. This function was added to cover
|
||||
* some rare use cases like keyboard navigation support
|
||||
* for the color picker in the #GtkColorSelectionDialog.
|
||||
**/
|
||||
void
|
||||
gdk_device_warp (GdkDevice *device,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DEVICE (device));
|
||||
|
||||
GDK_DEVICE_GET_CLASS (device)->warp (device, x, y);
|
||||
}
|
||||
|
||||
/* Private API */
|
||||
void
|
||||
_gdk_device_reset_axes (GdkDevice *device)
|
||||
|
||||
@@ -236,11 +236,6 @@ GDK_DEPRECATED_FOR(gdk_seat_ungrab)
|
||||
void gdk_device_ungrab (GdkDevice *device,
|
||||
guint32 time_);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_device_warp (GdkDevice *device,
|
||||
gint x,
|
||||
gint y);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface *gdk_device_get_last_event_surface (GdkDevice *device);
|
||||
|
||||
|
||||
@@ -86,9 +86,6 @@ struct _GdkDeviceClass
|
||||
GdkSurface *surface,
|
||||
GdkCursor *cursor);
|
||||
|
||||
void (* warp) (GdkDevice *device,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
void (* query_state) (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
GdkSurface **child_surface,
|
||||
|
||||
+53
-8
@@ -564,8 +564,8 @@ gdk_event_copy (const GdkEvent *event)
|
||||
g_object_ref (new_event->any.device);
|
||||
if (new_event->any.source_device)
|
||||
g_object_ref (new_event->any.source_device);
|
||||
if (new_event->any.user_data)
|
||||
g_object_ref (new_event->any.user_data);
|
||||
if (new_event->any.target)
|
||||
g_object_ref (new_event->any.target);
|
||||
|
||||
switch ((guint) event->any.type)
|
||||
{
|
||||
@@ -573,6 +573,13 @@ gdk_event_copy (const GdkEvent *event)
|
||||
case GDK_LEAVE_NOTIFY:
|
||||
if (event->crossing.child_surface != NULL)
|
||||
g_object_ref (event->crossing.child_surface);
|
||||
if (event->crossing.related_target)
|
||||
g_object_ref (event->crossing.related_target);
|
||||
break;
|
||||
|
||||
case GDK_FOCUS_CHANGE:
|
||||
if (event->focus_change.related_target)
|
||||
g_object_ref (event->focus_change.related_target);
|
||||
break;
|
||||
|
||||
case GDK_DRAG_ENTER:
|
||||
@@ -634,6 +641,11 @@ gdk_event_finalize (GObject *object)
|
||||
case GDK_ENTER_NOTIFY:
|
||||
case GDK_LEAVE_NOTIFY:
|
||||
g_clear_object (&event->crossing.child_surface);
|
||||
g_clear_object (&event->crossing.related_target);
|
||||
break;
|
||||
|
||||
case GDK_FOCUS_CHANGE:
|
||||
g_clear_object (&event->focus_change.related_target);
|
||||
break;
|
||||
|
||||
case GDK_DRAG_ENTER:
|
||||
@@ -675,7 +687,7 @@ gdk_event_finalize (GObject *object)
|
||||
|
||||
g_clear_object (&event->any.device);
|
||||
g_clear_object (&event->any.source_device);
|
||||
g_clear_object (&event->any.user_data);
|
||||
g_clear_object (&event->any.target);
|
||||
|
||||
G_OBJECT_CLASS (gdk_event_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -1904,16 +1916,39 @@ gdk_event_get_scancode (GdkEvent *event)
|
||||
}
|
||||
|
||||
void
|
||||
gdk_event_set_user_data (GdkEvent *event,
|
||||
GObject *user_data)
|
||||
gdk_event_set_target (GdkEvent *event,
|
||||
GObject *target)
|
||||
{
|
||||
g_set_object (&event->any.user_data, user_data);
|
||||
g_set_object (&event->any.target, target);
|
||||
}
|
||||
|
||||
GObject *
|
||||
gdk_event_get_user_data (const GdkEvent *event)
|
||||
gdk_event_get_target (const GdkEvent *event)
|
||||
{
|
||||
return event->any.user_data;
|
||||
return event->any.target;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_event_set_related_target (GdkEvent *event,
|
||||
GObject *target)
|
||||
{
|
||||
if (event->any.type == GDK_ENTER_NOTIFY ||
|
||||
event->any.type == GDK_LEAVE_NOTIFY)
|
||||
g_set_object (&event->crossing.related_target, target);
|
||||
else if (event->any.type == GDK_FOCUS_CHANGE)
|
||||
g_set_object (&event->focus_change.related_target, target);
|
||||
}
|
||||
|
||||
GObject *
|
||||
gdk_event_get_related_target (const GdkEvent *event)
|
||||
{
|
||||
if (event->any.type == GDK_ENTER_NOTIFY ||
|
||||
event->any.type == GDK_LEAVE_NOTIFY)
|
||||
return event->crossing.related_target;
|
||||
else if (event->any.type == GDK_FOCUS_CHANGE)
|
||||
return event->focus_change.related_target;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1980,6 +2015,11 @@ gdk_event_get_crossing_mode (const GdkEvent *event,
|
||||
*mode = event->crossing.mode;
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->any.type == GDK_FOCUS_CHANGE)
|
||||
{
|
||||
*mode = event->focus_change.mode;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -2006,6 +2046,11 @@ gdk_event_get_crossing_detail (const GdkEvent *event,
|
||||
*detail = event->crossing.detail;
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->any.type == GDK_FOCUS_CHANGE)
|
||||
{
|
||||
*detail = event->focus_change.detail;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+13
-3
@@ -61,7 +61,7 @@ struct _GdkEventAny
|
||||
GdkDevice *device;
|
||||
GdkDevice *source_device;
|
||||
GdkDisplay *display;
|
||||
GObject *user_data;
|
||||
GObject *target;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -303,6 +303,7 @@ struct _GdkEventCrossing
|
||||
GdkNotifyType detail;
|
||||
gboolean focus;
|
||||
guint state;
|
||||
GObject *related_target;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -312,6 +313,8 @@ struct _GdkEventCrossing
|
||||
* @send_event: %TRUE if the event was sent explicitly.
|
||||
* @in: %TRUE if the surface has gained the keyboard focus, %FALSE if
|
||||
* it has lost the focus.
|
||||
* @mode: the crossing mode
|
||||
* @detail: the kind of crossing that happened
|
||||
*
|
||||
* Describes a change of keyboard focus.
|
||||
*/
|
||||
@@ -319,6 +322,9 @@ struct _GdkEventFocus
|
||||
{
|
||||
GdkEventAny any;
|
||||
gint16 in;
|
||||
GdkCrossingMode mode;
|
||||
GdkNotifyType detail;
|
||||
GObject *related_target;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -632,8 +638,12 @@ union _GdkEvent
|
||||
GdkEventPadGroupMode pad_group_mode;
|
||||
};
|
||||
|
||||
void gdk_event_set_user_data (GdkEvent *event,
|
||||
GObject *user_data);
|
||||
void gdk_event_set_target (GdkEvent *event,
|
||||
GObject *user_data);
|
||||
GObject * gdk_event_get_target (const GdkEvent *event);
|
||||
void gdk_event_set_related_target (GdkEvent *event,
|
||||
GObject *user_data);
|
||||
GObject * gdk_event_get_related_target (const GdkEvent *event);
|
||||
|
||||
|
||||
#endif /* __GDK_EVENTS_PRIVATE_H__ */
|
||||
|
||||
@@ -517,13 +517,6 @@ gdk_wayland_device_set_surface_cursor (GdkDevice *device,
|
||||
gdk_wayland_device_update_surface_cursor (device);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_device_warp (GdkDevice *device,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
get_coordinates (GdkDevice *device,
|
||||
double *x,
|
||||
@@ -871,7 +864,6 @@ gdk_wayland_device_class_init (GdkWaylandDeviceClass *klass)
|
||||
device_class->get_history = gdk_wayland_device_get_history;
|
||||
device_class->get_state = gdk_wayland_device_get_state;
|
||||
device_class->set_surface_cursor = gdk_wayland_device_set_surface_cursor;
|
||||
device_class->warp = gdk_wayland_device_warp;
|
||||
device_class->query_state = gdk_wayland_device_query_state;
|
||||
device_class->grab = gdk_wayland_device_grab;
|
||||
device_class->ungrab = gdk_wayland_device_ungrab;
|
||||
|
||||
@@ -112,14 +112,6 @@ gdk_device_virtual_set_surface_cursor (GdkDevice *device,
|
||||
g_set_object (&GDK_SURFACE_IMPL_WIN32 (window->impl)->cursor, win32_hcursor);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_virtual_warp (GdkDevice *device,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
SetCursorPos (x - _gdk_offset_x, y - _gdk_offset_y);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_virtual_query_state (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
@@ -198,7 +190,6 @@ gdk_device_virtual_class_init (GdkDeviceVirtualClass *klass)
|
||||
device_class->get_history = gdk_device_virtual_get_history;
|
||||
device_class->get_state = gdk_device_virtual_get_state;
|
||||
device_class->set_surface_cursor = gdk_device_virtual_set_surface_cursor;
|
||||
device_class->warp = gdk_device_virtual_warp;
|
||||
device_class->query_state = gdk_device_virtual_query_state;
|
||||
device_class->grab = gdk_device_virtual_grab;
|
||||
device_class->ungrab = gdk_device_virtual_ungrab;
|
||||
|
||||
@@ -63,13 +63,6 @@ gdk_device_win32_set_surface_cursor (GdkDevice *device,
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_win32_warp (GdkDevice *device,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
}
|
||||
|
||||
static GdkModifierType
|
||||
get_current_mask (void)
|
||||
{
|
||||
@@ -286,7 +279,6 @@ gdk_device_win32_class_init (GdkDeviceWin32Class *klass)
|
||||
device_class->get_history = gdk_device_win32_get_history;
|
||||
device_class->get_state = gdk_device_win32_get_state;
|
||||
device_class->set_surface_cursor = gdk_device_win32_set_surface_cursor;
|
||||
device_class->warp = gdk_device_win32_warp;
|
||||
device_class->query_state = gdk_device_win32_query_state;
|
||||
device_class->grab = gdk_device_win32_grab;
|
||||
device_class->ungrab = gdk_device_win32_ungrab;
|
||||
|
||||
@@ -99,13 +99,6 @@ gdk_device_wintab_set_surface_cursor (GdkDevice *device,
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_wintab_warp (GdkDevice *device,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_device_wintab_query_state (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
@@ -291,7 +284,6 @@ gdk_device_wintab_class_init (GdkDeviceWintabClass *klass)
|
||||
device_class->get_history = gdk_device_wintab_get_history;
|
||||
device_class->get_state = gdk_device_wintab_get_state;
|
||||
device_class->set_surface_cursor = gdk_device_wintab_set_surface_cursor;
|
||||
device_class->warp = gdk_device_wintab_warp;
|
||||
device_class->query_state = gdk_device_wintab_query_state;
|
||||
device_class->grab = gdk_device_wintab_grab;
|
||||
device_class->ungrab = gdk_device_wintab_ungrab;
|
||||
|
||||
@@ -883,10 +883,7 @@ gdk_input_other_event (GdkDisplay *display,
|
||||
GdkDeviceManagerWin32 *device_manager;
|
||||
GdkDeviceWintab *source_device = NULL;
|
||||
GdkDeviceGrabInfo *last_grab;
|
||||
GdkEventMask masktest;
|
||||
guint key_state;
|
||||
POINT pt;
|
||||
GdkSurfaceImplWin32 *impl;
|
||||
|
||||
PACKET packet;
|
||||
gint root_x, root_y;
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
|
||||
#include <dwmapi.h>
|
||||
|
||||
#include "gdkwin32langnotification.h"
|
||||
|
||||
static int debug_indent = 0;
|
||||
|
||||
/**
|
||||
@@ -536,6 +538,7 @@ _gdk_win32_display_open (const gchar *display_name)
|
||||
NULL);
|
||||
_gdk_device_manager->display = _gdk_display;
|
||||
|
||||
_gdk_win32_lang_notification_init ();
|
||||
_gdk_drag_init ();
|
||||
_gdk_drop_init ();
|
||||
|
||||
@@ -701,6 +704,7 @@ gdk_win32_display_finalize (GObject *object)
|
||||
|
||||
_gdk_win32_display_finalize_cursors (display_win32);
|
||||
_gdk_win32_dnd_exit ();
|
||||
_gdk_win32_lang_notification_exit ();
|
||||
|
||||
g_ptr_array_free (display_win32->monitors, TRUE);
|
||||
|
||||
|
||||
@@ -1840,7 +1840,6 @@ gdk_win32_drag_find_window (GdkDrag *drag,
|
||||
{
|
||||
GdkWin32Drag *drag_win32 = GDK_WIN32_DRAG (drag);
|
||||
find_window_enum_arg a;
|
||||
HWND result;
|
||||
|
||||
g_assert (_win32_main_thread == NULL ||
|
||||
_win32_main_thread == g_thread_self ());
|
||||
@@ -2439,7 +2438,6 @@ gdk_dnd_handle_key_event (GdkDrag *drag,
|
||||
{
|
||||
drag_win32->util_data.last_x += dx;
|
||||
drag_win32->util_data.last_y += dy;
|
||||
gdk_device_warp (pointer, drag_win32->util_data.last_x, drag_win32->util_data.last_y);
|
||||
}
|
||||
|
||||
if (drag_win32->drag_surface)
|
||||
|
||||
@@ -1090,7 +1090,6 @@ static void
|
||||
gdk_win32_drop_finish (GdkDrop *drop,
|
||||
GdkDragAction action)
|
||||
{
|
||||
GdkDrag *drag;
|
||||
GdkWin32Drop *drop_win32 = GDK_WIN32_DROP (drop);
|
||||
|
||||
g_return_if_fail (drop != NULL);
|
||||
@@ -1103,12 +1102,6 @@ gdk_win32_drop_finish (GdkDrop *drop,
|
||||
|
||||
if (drop_win32->protocol == GDK_DRAG_PROTO_OLE2)
|
||||
return;
|
||||
/* FIXME: remove?
|
||||
drag = gdk_drop_get_drag (drop);
|
||||
|
||||
if (drag != NULL)
|
||||
_gdk_win32_local_drag_drop_response (drag, action);
|
||||
*/
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
@@ -1331,7 +1331,6 @@ _gdk_win32_do_emit_configure_event (GdkSurface *window,
|
||||
RECT rect)
|
||||
{
|
||||
GdkSurfaceImplWin32 *impl = GDK_SURFACE_IMPL_WIN32 (window->impl);
|
||||
GdkEvent *event;
|
||||
|
||||
impl->unscaled_width = rect.right - rect.left;
|
||||
impl->unscaled_height = rect.bottom - rect.top;
|
||||
@@ -2113,7 +2112,6 @@ gdk_event_translate (MSG *msg,
|
||||
case WM_INPUTLANGCHANGE:
|
||||
_gdk_input_locale = (HKL) msg->lParam;
|
||||
_gdk_win32_keymap_set_active_layout (GDK_WIN32_KEYMAP (_gdk_win32_display_get_keymap (_gdk_display)), _gdk_input_locale);
|
||||
_gdk_input_locale_is_ime = ImmIsIME (_gdk_input_locale);
|
||||
GetLocaleInfo (MAKELCID (LOWORD (_gdk_input_locale), SORT_DEFAULT),
|
||||
LOCALE_IDEFAULTANSICODEPAGE,
|
||||
buf, sizeof (buf));
|
||||
@@ -2125,6 +2123,20 @@ gdk_event_translate (MSG *msg,
|
||||
(gpointer) msg->lParam, _gdk_input_locale_is_ime ? " (IME)" : "",
|
||||
_gdk_input_codepage));
|
||||
gdk_display_setting_changed (display, "gtk-im-module");
|
||||
|
||||
/* Generate a dummy key event to "nudge" IMContext */
|
||||
event = gdk_event_new (GDK_KEY_PRESS);
|
||||
event->any.surface = window;
|
||||
event->key.time = _gdk_win32_get_next_tick (msg->time);
|
||||
event->key.keyval = GDK_KEY_VoidSymbol;
|
||||
event->key.hardware_keycode = 0;
|
||||
event->key.group = 0;
|
||||
gdk_event_set_scancode (event, 0);
|
||||
gdk_event_set_device (event, device_manager_win32->core_keyboard);
|
||||
gdk_event_set_source_device (event, device_manager_win32->system_keyboard);
|
||||
event->key.is_modifier = FALSE;
|
||||
event->key.state = 0;
|
||||
_gdk_win32_append_event (event);
|
||||
break;
|
||||
|
||||
case WM_SYSKEYUP:
|
||||
|
||||
@@ -39,7 +39,7 @@ HINSTANCE _gdk_app_hmodule;
|
||||
gint _gdk_input_ignore_core;
|
||||
|
||||
HKL _gdk_input_locale;
|
||||
gboolean _gdk_input_locale_is_ime;
|
||||
gboolean _gdk_input_locale_is_ime = FALSE;
|
||||
UINT _gdk_input_codepage;
|
||||
|
||||
gint _gdk_input_ignore_wintab = FALSE;
|
||||
|
||||
@@ -83,7 +83,6 @@ _gdk_win32_surfaceing_init (void)
|
||||
_gdk_display_hdc = CreateDC ("DISPLAY", NULL, NULL, NULL);
|
||||
_gdk_input_locale = GetKeyboardLayout (0);
|
||||
_gdk_win32_keymap_set_active_layout (GDK_WIN32_KEYMAP (_gdk_win32_display_get_keymap (_gdk_display)), _gdk_input_locale);
|
||||
_gdk_input_locale_is_ime = ImmIsIME (_gdk_input_locale);
|
||||
GetLocaleInfo (MAKELCID (LOWORD (_gdk_input_locale), SORT_DEFAULT),
|
||||
LOCALE_IDEFAULTANSICODEPAGE,
|
||||
buf, sizeof (buf));
|
||||
|
||||
@@ -215,9 +215,9 @@ _gdk_win32_get_setting (const gchar *name,
|
||||
else if (strcmp ("gtk-im-module", name) == 0)
|
||||
{
|
||||
if (_gdk_input_locale_is_ime)
|
||||
g_value_set_string (value, "ime");
|
||||
g_value_set_static_string (value, "ime");
|
||||
else
|
||||
g_value_set_string (value, "");
|
||||
g_value_set_static_string (value, "");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1953,19 +1953,6 @@ gdk_surface_win32_get_device_state (GdkSurface *window,
|
||||
return (child != NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_warp_device (GdkDisplay *display,
|
||||
GdkDevice *device,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
g_return_if_fail (display == gdk_display_get_default ());
|
||||
g_return_if_fail (GDK_IS_DEVICE (device));
|
||||
g_return_if_fail (display == gdk_device_get_display (device));
|
||||
|
||||
GDK_DEVICE_GET_CLASS (device)->warp (device, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_surface_set_accept_focus (GdkSurface *window,
|
||||
gboolean accept_focus)
|
||||
@@ -4125,7 +4112,7 @@ setup_drag_move_resize_context (GdkSurface *window,
|
||||
* the titlebar is, if any.
|
||||
*/
|
||||
root_y = wy + wheight / 2;
|
||||
gdk_device_warp (device, root_x, root_y);
|
||||
SetCursorPos (root_x - _gdk_offset_x, root_y - _gdk_offset_y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2019 Руслан Ижбулатов <lrn1986@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define COBJMACROS
|
||||
#include <msctf.h>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include "gdkprivate-win32.h"
|
||||
|
||||
struct _GdkWin32ALPNSink
|
||||
{
|
||||
ITfActiveLanguageProfileNotifySink itf_alpn_sink;
|
||||
|
||||
gint ref_count;
|
||||
};
|
||||
|
||||
typedef struct _GdkWin32ALPNSink GdkWin32ALPNSink;
|
||||
|
||||
static GdkWin32ALPNSink *actlangchangenotify = NULL;
|
||||
static ITfSource *itf_source = NULL;
|
||||
static DWORD actlangchangenotify_id = 0;
|
||||
|
||||
static ULONG STDMETHODCALLTYPE
|
||||
alpn_sink_addref (ITfActiveLanguageProfileNotifySink *This)
|
||||
{
|
||||
GdkWin32ALPNSink *alpn_sink = (GdkWin32ALPNSink *) This;
|
||||
int ref_count = ++alpn_sink->ref_count;
|
||||
|
||||
return ref_count;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
alpn_sink_queryinterface (ITfActiveLanguageProfileNotifySink *This,
|
||||
REFIID riid,
|
||||
LPVOID *ppvObject)
|
||||
{
|
||||
*ppvObject = NULL;
|
||||
|
||||
if (IsEqualGUID (riid, &IID_IUnknown))
|
||||
{
|
||||
ITfActiveLanguageProfileNotifySink_AddRef (This);
|
||||
*ppvObject = This;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (IsEqualGUID (riid, &IID_ITfActiveLanguageProfileNotifySink))
|
||||
{
|
||||
ITfActiveLanguageProfileNotifySink_AddRef (This);
|
||||
*ppvObject = This;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG STDMETHODCALLTYPE
|
||||
alpn_sink_release (ITfActiveLanguageProfileNotifySink *This)
|
||||
{
|
||||
GdkWin32ALPNSink *alpn_sink = (GdkWin32ALPNSink *) This;
|
||||
int ref_count = --alpn_sink->ref_count;
|
||||
|
||||
if (ref_count == 0)
|
||||
{
|
||||
g_free (This);
|
||||
}
|
||||
|
||||
return ref_count;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE
|
||||
alpn_sink_on_activated (ITfActiveLanguageProfileNotifySink *This,
|
||||
REFCLSID clsid,
|
||||
REFGUID guidProfile,
|
||||
BOOL fActivated)
|
||||
{
|
||||
_gdk_input_locale_is_ime = fActivated;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static ITfActiveLanguageProfileNotifySinkVtbl alpn_sink_vtbl = {
|
||||
alpn_sink_queryinterface,
|
||||
alpn_sink_addref,
|
||||
alpn_sink_release,
|
||||
alpn_sink_on_activated,
|
||||
};
|
||||
|
||||
static GdkWin32ALPNSink *
|
||||
alpn_sink_new ()
|
||||
{
|
||||
GdkWin32ALPNSink *result;
|
||||
|
||||
result = g_new0 (GdkWin32ALPNSink, 1);
|
||||
result->itf_alpn_sink.lpVtbl = &alpn_sink_vtbl;
|
||||
result->ref_count = 0;
|
||||
|
||||
ITfActiveLanguageProfileNotifySink_AddRef (&result->itf_alpn_sink);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_gdk_win32_lang_notification_init ()
|
||||
{
|
||||
HRESULT hr;
|
||||
ITfThreadMgr *itf_threadmgr;
|
||||
|
||||
CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
|
||||
|
||||
if (actlangchangenotify != NULL)
|
||||
return;
|
||||
|
||||
hr = CoCreateInstance (&CLSID_TF_ThreadMgr,
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
&IID_ITfThreadMgr,
|
||||
(LPVOID *) &itf_threadmgr);
|
||||
|
||||
if (!SUCCEEDED (hr))
|
||||
return;
|
||||
|
||||
hr = ITfThreadMgr_QueryInterface (itf_threadmgr, &IID_ITfSource, (VOID **) &itf_source);
|
||||
ITfThreadMgr_Release (itf_threadmgr);
|
||||
|
||||
if (!SUCCEEDED (hr))
|
||||
return;
|
||||
|
||||
actlangchangenotify = alpn_sink_new ();
|
||||
|
||||
hr = ITfSource_AdviseSink (itf_source,
|
||||
&IID_ITfActiveLanguageProfileNotifySink,
|
||||
(IUnknown *) actlangchangenotify,
|
||||
&actlangchangenotify_id);
|
||||
|
||||
if (!SUCCEEDED (hr))
|
||||
{
|
||||
ITfActiveLanguageProfileNotifySink_Release (&actlangchangenotify->itf_alpn_sink);
|
||||
actlangchangenotify = NULL;
|
||||
ITfSource_Release (itf_source);
|
||||
itf_source = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_win32_lang_notification_exit ()
|
||||
{
|
||||
if (actlangchangenotify != NULL && itf_source != NULL)
|
||||
{
|
||||
ITfSource_UnadviseSink (itf_source, actlangchangenotify_id);
|
||||
ITfSource_Release (itf_source);
|
||||
ITfActiveLanguageProfileNotifySink_Release (&actlangchangenotify->itf_alpn_sink);
|
||||
}
|
||||
|
||||
CoUninitialize ();
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* gdkwin32langnotification.h
|
||||
*
|
||||
* Copyright 2019 Руслан Ижбулатов <lrn1986@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_WIN32_LANGNOTIFICATION_H__
|
||||
#define __GDK_WIN32_LANGNOTIFICATION_H__
|
||||
|
||||
void _gdk_win32_lang_notification_init (void);
|
||||
void _gdk_win32_lang_notification_exit (void);
|
||||
|
||||
#endif
|
||||
@@ -17,6 +17,7 @@ gdk_win32_sources = files([
|
||||
'gdkglobals-win32.c',
|
||||
'gdkhdataoutputstream-win32.c',
|
||||
'gdkkeys-win32.c',
|
||||
'gdkwin32langnotification.c',
|
||||
'gdkmain-win32.c',
|
||||
'gdkmonitor-win32.c',
|
||||
'gdkproperty-win32.c',
|
||||
|
||||
@@ -52,9 +52,6 @@ static void gdk_x11_device_core_get_state (GdkDevice *device,
|
||||
static void gdk_x11_device_core_set_surface_cursor (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
GdkCursor *cursor);
|
||||
static void gdk_x11_device_core_warp (GdkDevice *device,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
static void gdk_x11_device_core_query_state (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
GdkSurface **child_surface,
|
||||
@@ -88,7 +85,6 @@ gdk_x11_device_core_class_init (GdkX11DeviceCoreClass *klass)
|
||||
device_class->get_history = gdk_x11_device_core_get_history;
|
||||
device_class->get_state = gdk_x11_device_core_get_state;
|
||||
device_class->set_surface_cursor = gdk_x11_device_core_set_surface_cursor;
|
||||
device_class->warp = gdk_x11_device_core_warp;
|
||||
device_class->query_state = gdk_x11_device_core_query_state;
|
||||
device_class->grab = gdk_x11_device_core_grab;
|
||||
device_class->ungrab = gdk_x11_device_core_ungrab;
|
||||
@@ -223,26 +219,6 @@ gdk_x11_device_core_set_surface_cursor (GdkDevice *device,
|
||||
xcursor);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_device_core_warp (GdkDevice *device,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
Display *xdisplay;
|
||||
Window dest;
|
||||
GdkX11Screen *screen;
|
||||
|
||||
display = gdk_device_get_display (device);
|
||||
xdisplay = GDK_DISPLAY_XDISPLAY (display);
|
||||
screen = GDK_X11_DISPLAY (display)->screen;
|
||||
dest = GDK_SCREEN_XROOTWIN (screen);
|
||||
|
||||
XWarpPointer (xdisplay, None, dest, 0, 0, 0, 0,
|
||||
round (x * screen->surface_scale),
|
||||
round (y * screen->surface_scale));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_device_core_query_state (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
|
||||
@@ -77,9 +77,6 @@ static void gdk_x11_device_xi2_get_state (GdkDevice *device,
|
||||
static void gdk_x11_device_xi2_set_surface_cursor (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
GdkCursor *cursor);
|
||||
static void gdk_x11_device_xi2_warp (GdkDevice *device,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
static void gdk_x11_device_xi2_query_state (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
GdkSurface **child_surface,
|
||||
@@ -123,7 +120,6 @@ gdk_x11_device_xi2_class_init (GdkX11DeviceXI2Class *klass)
|
||||
|
||||
device_class->get_state = gdk_x11_device_xi2_get_state;
|
||||
device_class->set_surface_cursor = gdk_x11_device_xi2_set_surface_cursor;
|
||||
device_class->warp = gdk_x11_device_xi2_warp;
|
||||
device_class->query_state = gdk_x11_device_xi2_query_state;
|
||||
device_class->grab = gdk_x11_device_xi2_grab;
|
||||
device_class->ungrab = gdk_x11_device_xi2_ungrab;
|
||||
@@ -292,24 +288,6 @@ gdk_x11_device_xi2_set_surface_cursor (GdkDevice *device,
|
||||
GDK_SURFACE_XID (surface));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_device_xi2_warp (GdkDevice *device,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
GdkX11DeviceXI2 *device_xi2 = GDK_X11_DEVICE_XI2 (device);
|
||||
GdkDisplay *display = gdk_device_get_display (device);
|
||||
GdkX11Screen *screen = GDK_X11_DISPLAY (display)->screen;
|
||||
Window dest = GDK_DISPLAY_XROOTWIN (display);
|
||||
|
||||
XIWarpPointer (GDK_SCREEN_XDISPLAY (screen),
|
||||
device_xi2->device_id,
|
||||
None, dest,
|
||||
0, 0, 0, 0,
|
||||
round (x * screen->surface_scale),
|
||||
round (y * screen->surface_scale));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_device_xi2_query_state (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
|
||||
+15
-1
@@ -41,6 +41,7 @@
|
||||
#include "gdkselectioninputstream-x11.h"
|
||||
#include "gdkselectionoutputstream-x11.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
@@ -2342,9 +2343,22 @@ gdk_dnd_handle_key_event (GdkDrag *drag,
|
||||
|
||||
if (dx != 0 || dy != 0)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
Display *xdisplay;
|
||||
GdkX11Screen *screen;
|
||||
Window dest;
|
||||
|
||||
x11_drag->last_x += dx;
|
||||
x11_drag->last_y += dy;
|
||||
gdk_device_warp (pointer, x11_drag->last_x, x11_drag->last_y);
|
||||
|
||||
display = gdk_event_get_display ((GdkEvent *)event);
|
||||
xdisplay = GDK_DISPLAY_XDISPLAY (display);
|
||||
screen = GDK_X11_DISPLAY (display)->screen;
|
||||
dest = GDK_SCREEN_XROOTWIN (screen);
|
||||
|
||||
XWarpPointer (xdisplay, None, dest, 0, 0, 0, 0,
|
||||
round (x11_drag->last_x * screen->surface_scale),
|
||||
round (x11_drag->last_y * screen->surface_scale));
|
||||
}
|
||||
|
||||
gdk_drag_update (drag, x11_drag->last_x, x11_drag->last_y, state,
|
||||
|
||||
@@ -305,6 +305,12 @@ gdk_event_source_translate_event (GdkX11Display *x11_display,
|
||||
}
|
||||
}
|
||||
|
||||
if (event &&
|
||||
event->any.type == GDK_NOTHING)
|
||||
{
|
||||
g_clear_object (&event);
|
||||
}
|
||||
|
||||
if (event &&
|
||||
(event->any.type == GDK_ENTER_NOTIFY ||
|
||||
event->any.type == GDK_LEAVE_NOTIFY) &&
|
||||
|
||||
@@ -547,6 +547,25 @@ gsk_gl_driver_get_texture_for_pointer (GskGLDriver *self,
|
||||
|
||||
id = GPOINTER_TO_INT (g_hash_table_lookup (self->pointer_textures, pointer));
|
||||
|
||||
if (id != 0)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer value_p;
|
||||
/* Find the texture in self->textures and mark it used */
|
||||
|
||||
g_hash_table_iter_init (&iter, self->textures);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &value_p))
|
||||
{
|
||||
Texture *t = value_p;
|
||||
|
||||
if (t->texture_id == id)
|
||||
{
|
||||
t->in_use = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
@@ -433,12 +433,23 @@ render_fallback_node (GskGLRenderer *self,
|
||||
const int surface_height = ceilf (node->bounds.size.height) * scale;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
int cached_id;
|
||||
int texture_id;
|
||||
|
||||
if (surface_width <= 0 ||
|
||||
surface_height <= 0)
|
||||
return;
|
||||
|
||||
cached_id = gsk_gl_driver_get_texture_for_pointer (self->gl_driver, node);
|
||||
|
||||
if (cached_id != 0)
|
||||
{
|
||||
ops_set_program (builder, &self->blit_program);
|
||||
ops_set_texture (builder, cached_id);
|
||||
ops_draw (builder, vertex_data);
|
||||
return;
|
||||
}
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
surface_width,
|
||||
surface_height);
|
||||
@@ -474,6 +485,8 @@ render_fallback_node (GskGLRenderer *self,
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
gsk_gl_driver_set_texture_for_pointer (self->gl_driver, node, texture_id);
|
||||
|
||||
ops_set_program (builder, &self->blit_program);
|
||||
ops_set_texture (builder, texture_id);
|
||||
ops_draw (builder, vertex_data);
|
||||
|
||||
+377
-447
@@ -4,6 +4,7 @@
|
||||
#include "broadway/gdkprivate-broadway.h"
|
||||
|
||||
#include "gskdebugprivate.h"
|
||||
#include "gsktransformprivate.h"
|
||||
#include "gskrendererprivate.h"
|
||||
#include "gskrendernodeprivate.h"
|
||||
#include "gdk/gdktextureprivate.h"
|
||||
@@ -12,6 +13,16 @@ struct _GskBroadwayRenderer
|
||||
{
|
||||
GskRenderer parent_instance;
|
||||
GdkBroadwayDrawContext *draw_context;
|
||||
guint32 next_node_id;
|
||||
|
||||
/* Set during rendering */
|
||||
GArray *nodes; /* Owned by draw_contex */
|
||||
GPtrArray *node_textures; /* Owned by draw_contex */
|
||||
GHashTable *node_lookup;
|
||||
|
||||
/* Kept from last frame */
|
||||
GHashTable *last_node_lookup;
|
||||
GskRenderNode *last_root; /* Owning refs to the things in last_node_lookup */
|
||||
};
|
||||
|
||||
struct _GskBroadwayRendererClass
|
||||
@@ -71,12 +82,25 @@ gsk_broadway_renderer_render_texture (GskRenderer *renderer,
|
||||
return texture;
|
||||
}
|
||||
|
||||
/* uint32 is sent in native endianness, and then converted to little endian in broadwayd when sending to browser */
|
||||
static void
|
||||
add_uint32 (GArray *nodes, guint32 v)
|
||||
{
|
||||
g_array_append_val (nodes, v);
|
||||
}
|
||||
|
||||
static void
|
||||
add_float (GArray *nodes, float f)
|
||||
{
|
||||
union {
|
||||
float f;
|
||||
guint32 i;
|
||||
} u;
|
||||
|
||||
u.f = f;
|
||||
g_array_append_val (nodes, u.i);
|
||||
}
|
||||
|
||||
static guint32
|
||||
rgba_to_uint32 (const GdkRGBA *rgba)
|
||||
{
|
||||
@@ -96,18 +120,16 @@ add_rgba (GArray *nodes, const GdkRGBA *rgba)
|
||||
}
|
||||
|
||||
static void
|
||||
add_float (GArray *nodes, float f)
|
||||
add_xy (GArray *nodes, float x, float y, float offset_x, float offset_y)
|
||||
{
|
||||
gint32 i = (gint32) (f * 256.0f);
|
||||
guint u = (guint32) i;
|
||||
g_array_append_val (nodes, u);
|
||||
add_float (nodes, x - offset_x);
|
||||
add_float (nodes, y - offset_y);
|
||||
}
|
||||
|
||||
static void
|
||||
add_point (GArray *nodes, const graphene_point_t *point, float offset_x, float offset_y)
|
||||
{
|
||||
add_float (nodes, point->x - offset_x);
|
||||
add_float (nodes, point->y - offset_y);
|
||||
add_xy (nodes, point->x, point->y, offset_x, offset_y);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -140,313 +162,157 @@ add_color_stop (GArray *nodes, const GskColorStop *stop)
|
||||
add_rgba (nodes, &stop->color);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
float_is_int32 (float f)
|
||||
{
|
||||
gint32 i = (gint32)f;
|
||||
float f2 = (float)i;
|
||||
return f2 == f;
|
||||
}
|
||||
|
||||
static GHashTable *gsk_broadway_node_cache;
|
||||
|
||||
typedef struct {
|
||||
GdkTexture *texture;
|
||||
GskRenderNode *node;
|
||||
float off_x;
|
||||
float off_y;
|
||||
} NodeCacheElement;
|
||||
|
||||
static void
|
||||
node_cache_element_free (NodeCacheElement *element)
|
||||
add_string (GArray *nodes, const char *str)
|
||||
{
|
||||
gsk_render_node_unref (element->node);
|
||||
g_free (element);
|
||||
}
|
||||
guint32 len = strlen(str);
|
||||
guint32 v, c;
|
||||
|
||||
static guint
|
||||
glyph_info_hash (const PangoGlyphInfo *info)
|
||||
{
|
||||
return info->glyph ^
|
||||
info->geometry.width << 6 ^
|
||||
info->geometry.x_offset << 12 ^
|
||||
info->geometry.y_offset << 18 ^
|
||||
info->attr.is_cluster_start << 30;
|
||||
}
|
||||
add_uint32 (nodes, len);
|
||||
|
||||
static gboolean
|
||||
glyph_info_equal (const PangoGlyphInfo *a,
|
||||
const PangoGlyphInfo *b)
|
||||
{
|
||||
return
|
||||
a->glyph == b->glyph &&
|
||||
a->geometry.width == b->geometry.width &&
|
||||
a->geometry.x_offset == b->geometry.x_offset &&
|
||||
a->geometry.y_offset == b->geometry.y_offset &&
|
||||
a->attr.is_cluster_start == b->attr.is_cluster_start;
|
||||
}
|
||||
|
||||
static guint
|
||||
hash_matrix (const graphene_matrix_t *matrix)
|
||||
{
|
||||
float m[16];
|
||||
guint h = 0;
|
||||
int i;
|
||||
|
||||
graphene_matrix_to_float (matrix, m);
|
||||
for (i = 0; i < 16; i++)
|
||||
h ^= (guint) m[i];
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
matrix_equal (const graphene_matrix_t *a,
|
||||
const graphene_matrix_t *b)
|
||||
{
|
||||
float ma[16];
|
||||
float mb[16];
|
||||
int i;
|
||||
|
||||
graphene_matrix_to_float (a, ma);
|
||||
graphene_matrix_to_float (b, mb);
|
||||
for (i = 0; i < 16; i++)
|
||||
v = 0;
|
||||
c = 0;
|
||||
while (*str != 0)
|
||||
{
|
||||
if (ma[i] != mb[i])
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
hash_vec4 (const graphene_vec4_t *vec4)
|
||||
{
|
||||
float v[4];
|
||||
guint h = 0;
|
||||
int i;
|
||||
|
||||
graphene_vec4_to_float (vec4, v);
|
||||
for (i = 0; i < 4; i++)
|
||||
h ^= (guint) v[i];
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
vec4_equal (const graphene_vec4_t *a,
|
||||
const graphene_vec4_t *b)
|
||||
{
|
||||
float va[4];
|
||||
float vb[4];
|
||||
int i;
|
||||
|
||||
graphene_vec4_to_float (a, va);
|
||||
graphene_vec4_to_float (b, vb);
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (va[i] != vb[i])
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
node_cache_hash (GskRenderNode *node)
|
||||
{
|
||||
GskRenderNodeType type;
|
||||
guint h;
|
||||
|
||||
type = gsk_render_node_get_node_type (node);
|
||||
h = type << 28;
|
||||
if (type == GSK_TEXT_NODE &&
|
||||
float_is_int32 (gsk_text_node_get_x (node)) &&
|
||||
float_is_int32 (gsk_text_node_get_y (node)))
|
||||
{
|
||||
guint i;
|
||||
const PangoFont *font = gsk_text_node_peek_font (node);
|
||||
guint n_glyphs = gsk_text_node_get_num_glyphs (node);
|
||||
const PangoGlyphInfo *infos = gsk_text_node_peek_glyphs (node);
|
||||
const GdkRGBA *color = gsk_text_node_peek_color (node);
|
||||
|
||||
h ^= g_direct_hash (font) ^ n_glyphs << 16 ^ gdk_rgba_hash (color);
|
||||
for (i = 0; i < n_glyphs; i++)
|
||||
h ^= glyph_info_hash (&infos[i]);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
if (type == GSK_COLOR_MATRIX_NODE &&
|
||||
gsk_render_node_get_node_type (gsk_color_matrix_node_get_child (node)) == GSK_TEXTURE_NODE)
|
||||
{
|
||||
const graphene_matrix_t *matrix = gsk_color_matrix_node_peek_color_matrix (node);
|
||||
const graphene_vec4_t *offset = gsk_color_matrix_node_peek_color_offset (node);
|
||||
GskRenderNode *child = gsk_color_matrix_node_get_child (node);
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (child);
|
||||
|
||||
h ^= g_direct_hash (texture) ^ hash_matrix (matrix) ^ hash_vec4 (offset);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
node_cache_equal (GskRenderNode *a,
|
||||
GskRenderNode *b)
|
||||
{
|
||||
GskRenderNodeType type;
|
||||
|
||||
type = gsk_render_node_get_node_type (a);
|
||||
if (type != gsk_render_node_get_node_type (b))
|
||||
return FALSE;
|
||||
|
||||
if (type == GSK_TEXT_NODE &&
|
||||
float_is_int32 (gsk_text_node_get_x (a)) &&
|
||||
float_is_int32 (gsk_text_node_get_y (a)) &&
|
||||
float_is_int32 (gsk_text_node_get_x (b)) &&
|
||||
float_is_int32 (gsk_text_node_get_y (b)))
|
||||
{
|
||||
const PangoFont *a_font = gsk_text_node_peek_font (a);
|
||||
guint a_n_glyphs = gsk_text_node_get_num_glyphs (a);
|
||||
const PangoGlyphInfo *a_infos = gsk_text_node_peek_glyphs (a);
|
||||
const GdkRGBA *a_color = gsk_text_node_peek_color (a);
|
||||
const PangoFont *b_font = gsk_text_node_peek_font (b);
|
||||
guint b_n_glyphs = gsk_text_node_get_num_glyphs (b);
|
||||
const PangoGlyphInfo *b_infos = gsk_text_node_peek_glyphs (b);
|
||||
const GdkRGBA *b_color = gsk_text_node_peek_color (a);
|
||||
guint i;
|
||||
|
||||
if (a_font != b_font)
|
||||
return FALSE;
|
||||
|
||||
if (a_n_glyphs != b_n_glyphs)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < a_n_glyphs; i++)
|
||||
v |= (*str++) << 8*c++;
|
||||
if (c == 4)
|
||||
{
|
||||
if (!glyph_info_equal (&a_infos[i], &b_infos[i]))
|
||||
return FALSE;
|
||||
add_uint32 (nodes, v);
|
||||
v = 0;
|
||||
c = 0;
|
||||
}
|
||||
|
||||
if (!gdk_rgba_equal (a_color, b_color))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (type == GSK_COLOR_MATRIX_NODE &&
|
||||
gsk_render_node_get_node_type (gsk_color_matrix_node_get_child (a)) == GSK_TEXTURE_NODE &&
|
||||
gsk_render_node_get_node_type (gsk_color_matrix_node_get_child (b)) == GSK_TEXTURE_NODE)
|
||||
{
|
||||
const graphene_matrix_t *a_matrix = gsk_color_matrix_node_peek_color_matrix (a);
|
||||
const graphene_vec4_t *a_offset = gsk_color_matrix_node_peek_color_offset (a);
|
||||
GskRenderNode *a_child = gsk_color_matrix_node_get_child (a);
|
||||
GdkTexture *a_texture = gsk_texture_node_get_texture (a_child);
|
||||
const graphene_matrix_t *b_matrix = gsk_color_matrix_node_peek_color_matrix (b);
|
||||
const graphene_vec4_t *b_offset = gsk_color_matrix_node_peek_color_offset (b);
|
||||
GskRenderNode *b_child = gsk_color_matrix_node_get_child (b);
|
||||
GdkTexture *b_texture = gsk_texture_node_get_texture (b_child);
|
||||
|
||||
if (a_texture != b_texture)
|
||||
return FALSE;
|
||||
|
||||
if (!matrix_equal (a_matrix, b_matrix))
|
||||
return FALSE;
|
||||
|
||||
if (!vec4_equal (a_offset, b_offset))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
node_cache_lookup (GskRenderNode *node,
|
||||
float *off_x, float *off_y)
|
||||
{
|
||||
NodeCacheElement *hit;
|
||||
|
||||
if (gsk_broadway_node_cache == NULL)
|
||||
gsk_broadway_node_cache = g_hash_table_new_full ((GHashFunc)node_cache_hash,
|
||||
(GEqualFunc)node_cache_equal,
|
||||
NULL,
|
||||
(GDestroyNotify)node_cache_element_free);
|
||||
|
||||
hit = g_hash_table_lookup (gsk_broadway_node_cache, node);
|
||||
if (hit)
|
||||
{
|
||||
*off_x = hit->off_x;
|
||||
*off_y = hit->off_y;
|
||||
return g_object_ref (hit->texture);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
if (c != 0)
|
||||
add_uint32 (nodes, v);
|
||||
}
|
||||
|
||||
static void
|
||||
cached_texture_gone (gpointer data,
|
||||
GObject *where_the_object_was)
|
||||
{
|
||||
NodeCacheElement *element = data;
|
||||
g_hash_table_remove (gsk_broadway_node_cache, element->node);
|
||||
}
|
||||
collect_reused_child_nodes (GskRenderer *renderer,
|
||||
GskRenderNode *node);
|
||||
|
||||
static void
|
||||
node_cache_store (GskRenderNode *node,
|
||||
GdkTexture *texture,
|
||||
float off_x,
|
||||
float off_y)
|
||||
collect_reused_node (GskRenderer *renderer,
|
||||
GskRenderNode *node)
|
||||
{
|
||||
GskRenderNodeType type;
|
||||
GskBroadwayRenderer *self = GSK_BROADWAY_RENDERER (renderer);
|
||||
guint32 old_id;
|
||||
|
||||
type = gsk_render_node_get_node_type (node);
|
||||
if ((type == GSK_TEXT_NODE &&
|
||||
float_is_int32 (gsk_text_node_get_x (node)) &&
|
||||
float_is_int32 (gsk_text_node_get_y (node))) ||
|
||||
(type == GSK_COLOR_MATRIX_NODE &&
|
||||
gsk_render_node_get_node_type (gsk_color_matrix_node_get_child (node)) == GSK_TEXTURE_NODE))
|
||||
if (self->last_node_lookup &&
|
||||
(old_id = GPOINTER_TO_INT(g_hash_table_lookup (self->last_node_lookup, node))) != 0)
|
||||
{
|
||||
NodeCacheElement *element = g_new0 (NodeCacheElement, 1);
|
||||
element->texture = texture;
|
||||
element->node = gsk_render_node_ref (node);
|
||||
element->off_x = off_x;
|
||||
element->off_y = off_y;
|
||||
g_object_weak_ref (G_OBJECT (texture), cached_texture_gone, element);
|
||||
g_hash_table_insert (gsk_broadway_node_cache, element->node, element);
|
||||
g_hash_table_insert (self->node_lookup, node, GINT_TO_POINTER (old_id));
|
||||
collect_reused_child_nodes (renderer, node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
collect_reused_child_nodes (GskRenderer *renderer,
|
||||
GskRenderNode *node)
|
||||
{
|
||||
guint i;
|
||||
|
||||
switch (gsk_render_node_get_node_type (node))
|
||||
{
|
||||
case GSK_NOT_A_RENDER_NODE:
|
||||
g_assert_not_reached ();
|
||||
return;
|
||||
|
||||
/* Leaf nodes */
|
||||
|
||||
case GSK_TEXTURE_NODE:
|
||||
case GSK_CAIRO_NODE:
|
||||
case GSK_COLOR_NODE:
|
||||
case GSK_BORDER_NODE:
|
||||
case GSK_OUTSET_SHADOW_NODE:
|
||||
case GSK_INSET_SHADOW_NODE:
|
||||
case GSK_LINEAR_GRADIENT_NODE:
|
||||
|
||||
/* Fallbacks (=> leaf for now */
|
||||
case GSK_COLOR_MATRIX_NODE:
|
||||
case GSK_TEXT_NODE:
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
case GSK_REPEAT_NODE:
|
||||
case GSK_BLEND_NODE:
|
||||
case GSK_CROSS_FADE_NODE:
|
||||
case GSK_BLUR_NODE:
|
||||
|
||||
default:
|
||||
|
||||
break;
|
||||
|
||||
/* Bin nodes */
|
||||
|
||||
case GSK_SHADOW_NODE:
|
||||
collect_reused_node (renderer,
|
||||
gsk_shadow_node_get_child (node));
|
||||
break;
|
||||
|
||||
case GSK_OPACITY_NODE:
|
||||
collect_reused_node (renderer,
|
||||
gsk_opacity_node_get_child (node));
|
||||
break;
|
||||
|
||||
case GSK_ROUNDED_CLIP_NODE:
|
||||
collect_reused_node (renderer,
|
||||
gsk_rounded_clip_node_get_child (node));
|
||||
break;
|
||||
|
||||
case GSK_CLIP_NODE:
|
||||
collect_reused_node (renderer,
|
||||
gsk_clip_node_get_child (node));
|
||||
break;
|
||||
|
||||
case GSK_TRANSFORM_NODE:
|
||||
collect_reused_node (renderer,
|
||||
gsk_transform_node_get_child (node));
|
||||
break;
|
||||
|
||||
case GSK_DEBUG_NODE:
|
||||
collect_reused_node (renderer,
|
||||
gsk_debug_node_get_child (node));
|
||||
break;
|
||||
|
||||
/* Generic nodes */
|
||||
|
||||
case GSK_CONTAINER_NODE:
|
||||
for (i = 0; i < gsk_container_node_get_n_children (node); i++)
|
||||
collect_reused_node (renderer,
|
||||
gsk_container_node_get_child (node, i));
|
||||
break;
|
||||
|
||||
break; /* Fallback */
|
||||
}
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
node_texture_fallback (GskRenderNode *node,
|
||||
float *off_x,
|
||||
float *off_y)
|
||||
static gboolean
|
||||
add_new_node (GskRenderer *renderer,
|
||||
GskRenderNode *node,
|
||||
BroadwayNodeType type)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
int x = floorf (node->bounds.origin.x);
|
||||
int y = floorf (node->bounds.origin.y);
|
||||
int width = ceil (node->bounds.origin.x + node->bounds.size.width) - x;
|
||||
int height = ceil (node->bounds.origin.y + node->bounds.size.height) - y;
|
||||
GdkTexture *texture;
|
||||
GskBroadwayRenderer *self = GSK_BROADWAY_RENDERER (renderer);
|
||||
guint32 id, old_id;
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
|
||||
cr = cairo_create (surface);
|
||||
cairo_translate (cr, -x, -y);
|
||||
gsk_render_node_draw (node, cr);
|
||||
cairo_destroy (cr);
|
||||
if (self->last_node_lookup &&
|
||||
(old_id = GPOINTER_TO_INT (g_hash_table_lookup (self->last_node_lookup, node))) != 0)
|
||||
{
|
||||
add_uint32 (self->nodes, BROADWAY_NODE_REUSE);
|
||||
add_uint32 (self->nodes, old_id);
|
||||
|
||||
texture = gdk_texture_new_for_surface (surface);
|
||||
*off_x = x - node->bounds.origin.x;
|
||||
*off_y = y - node->bounds.origin.y;
|
||||
g_hash_table_insert (self->node_lookup, node, GINT_TO_POINTER(old_id));
|
||||
collect_reused_child_nodes (renderer, node);
|
||||
|
||||
return texture;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
id = ++self->next_node_id;
|
||||
g_hash_table_insert (self->node_lookup, node, GINT_TO_POINTER(id));
|
||||
|
||||
add_uint32 (self->nodes, type);
|
||||
add_uint32 (self->nodes, id);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Note: This tracks the offset so that we can convert
|
||||
@@ -455,13 +321,13 @@ node_texture_fallback (GskRenderNode *node,
|
||||
which is good for re-using subtrees. */
|
||||
static void
|
||||
gsk_broadway_renderer_add_node (GskRenderer *renderer,
|
||||
GArray *nodes,
|
||||
GPtrArray *node_textures,
|
||||
GskRenderNode *node,
|
||||
float offset_x,
|
||||
float offset_y)
|
||||
{
|
||||
GdkDisplay *display = gsk_renderer_get_display (renderer);
|
||||
GdkDisplay *display = gdk_surface_get_display (gsk_renderer_get_surface (renderer));
|
||||
GskBroadwayRenderer *self = GSK_BROADWAY_RENDERER (renderer);
|
||||
GArray *nodes = self->nodes;
|
||||
|
||||
switch (gsk_render_node_get_node_type (node))
|
||||
{
|
||||
@@ -472,191 +338,223 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
|
||||
/* Leaf nodes */
|
||||
|
||||
case GSK_TEXTURE_NODE:
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (node);
|
||||
guint32 texture_id;
|
||||
if (add_new_node (renderer, node, BROADWAY_NODE_TEXTURE))
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (node);
|
||||
guint32 texture_id;
|
||||
|
||||
g_ptr_array_add (node_textures, g_object_ref (texture)); /* Transfers ownership to node_textures */
|
||||
texture_id = gdk_broadway_display_ensure_texture (display, texture);
|
||||
/* No need to add to self->node_textures here, the node will keep it alive until end of frame. */
|
||||
|
||||
add_uint32 (nodes, BROADWAY_NODE_TEXTURE);
|
||||
add_rect (nodes, &node->bounds, offset_x, offset_y);
|
||||
add_uint32 (nodes, texture_id);
|
||||
}
|
||||
texture_id = gdk_broadway_display_ensure_texture (display, texture);
|
||||
|
||||
add_rect (nodes, &node->bounds, offset_x, offset_y);
|
||||
add_uint32 (nodes, texture_id);
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_CAIRO_NODE:
|
||||
{
|
||||
cairo_surface_t *surface = (cairo_surface_t *)gsk_cairo_node_peek_surface (node);
|
||||
cairo_surface_t *image_surface = NULL;
|
||||
GdkTexture *texture;
|
||||
guint32 texture_id;
|
||||
if (add_new_node (renderer, node, BROADWAY_NODE_TEXTURE))
|
||||
{
|
||||
cairo_surface_t *surface = (cairo_surface_t *)gsk_cairo_node_peek_surface (node);
|
||||
cairo_surface_t *image_surface = NULL;
|
||||
GdkTexture *texture;
|
||||
guint32 texture_id;
|
||||
|
||||
if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE)
|
||||
image_surface = cairo_surface_reference (surface);
|
||||
else
|
||||
{
|
||||
cairo_t *cr;
|
||||
image_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
ceilf (node->bounds.size.width),
|
||||
ceilf (node->bounds.size.height));
|
||||
cr = cairo_create (image_surface);
|
||||
cairo_set_source_surface (cr, surface, 0, 0);
|
||||
cairo_rectangle (cr, 0, 0, node->bounds.size.width, node->bounds.size.height);
|
||||
cairo_fill (cr);
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE)
|
||||
image_surface = cairo_surface_reference (surface);
|
||||
else
|
||||
{
|
||||
cairo_t *cr;
|
||||
image_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
ceilf (node->bounds.size.width),
|
||||
ceilf (node->bounds.size.height));
|
||||
cr = cairo_create (image_surface);
|
||||
cairo_set_source_surface (cr, surface, 0, 0);
|
||||
cairo_rectangle (cr, 0, 0, node->bounds.size.width, node->bounds.size.height);
|
||||
cairo_fill (cr);
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
texture = gdk_texture_new_for_surface (image_surface);
|
||||
g_ptr_array_add (node_textures, g_object_ref (texture)); /* Transfers ownership to node_textures */
|
||||
texture_id = gdk_broadway_display_ensure_texture (display, texture);
|
||||
texture = gdk_texture_new_for_surface (image_surface);
|
||||
g_ptr_array_add (self->node_textures, g_object_ref (texture)); /* Transfers ownership to node_textures */
|
||||
texture_id = gdk_broadway_display_ensure_texture (display, texture);
|
||||
|
||||
add_uint32 (nodes, BROADWAY_NODE_TEXTURE);
|
||||
add_rect (nodes, &node->bounds, offset_x, offset_y);
|
||||
add_uint32 (nodes, texture_id);
|
||||
add_rect (nodes, &node->bounds, offset_x, offset_y);
|
||||
add_uint32 (nodes, texture_id);
|
||||
|
||||
cairo_surface_destroy (image_surface);
|
||||
}
|
||||
cairo_surface_destroy (image_surface);
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_COLOR_NODE:
|
||||
{
|
||||
add_uint32 (nodes, BROADWAY_NODE_COLOR);
|
||||
add_rect (nodes, &node->bounds, offset_x, offset_y);
|
||||
add_rgba (nodes, gsk_color_node_peek_color (node));
|
||||
}
|
||||
if (add_new_node (renderer, node, BROADWAY_NODE_COLOR))
|
||||
{
|
||||
add_rect (nodes, &node->bounds, offset_x, offset_y);
|
||||
add_rgba (nodes, gsk_color_node_peek_color (node));
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_BORDER_NODE:
|
||||
{
|
||||
int i;
|
||||
add_uint32 (nodes, BROADWAY_NODE_BORDER);
|
||||
add_rounded_rect (nodes, gsk_border_node_peek_outline (node), offset_x, offset_y);
|
||||
for (i = 0; i < 4; i++)
|
||||
add_float (nodes, gsk_border_node_peek_widths (node)[i]);
|
||||
for (i = 0; i < 4; i++)
|
||||
add_rgba (nodes, &gsk_border_node_peek_colors (node)[i]);
|
||||
}
|
||||
if (add_new_node (renderer, node, BROADWAY_NODE_BORDER))
|
||||
{
|
||||
int i;
|
||||
add_rounded_rect (nodes, gsk_border_node_peek_outline (node), offset_x, offset_y);
|
||||
for (i = 0; i < 4; i++)
|
||||
add_float (nodes, gsk_border_node_peek_widths (node)[i]);
|
||||
for (i = 0; i < 4; i++)
|
||||
add_rgba (nodes, &gsk_border_node_peek_colors (node)[i]);
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_OUTSET_SHADOW_NODE:
|
||||
{
|
||||
add_uint32 (nodes, BROADWAY_NODE_OUTSET_SHADOW);
|
||||
add_rounded_rect (nodes, gsk_outset_shadow_node_peek_outline (node), offset_x, offset_y);
|
||||
add_rgba (nodes, gsk_outset_shadow_node_peek_color (node));
|
||||
add_float (nodes, gsk_outset_shadow_node_get_dx (node));
|
||||
add_float (nodes, gsk_outset_shadow_node_get_dy (node));
|
||||
add_float (nodes, gsk_outset_shadow_node_get_spread (node));
|
||||
add_float (nodes, gsk_outset_shadow_node_get_blur_radius (node));
|
||||
}
|
||||
if (add_new_node (renderer, node, BROADWAY_NODE_OUTSET_SHADOW))
|
||||
{
|
||||
add_rounded_rect (nodes, gsk_outset_shadow_node_peek_outline (node), offset_x, offset_y);
|
||||
add_rgba (nodes, gsk_outset_shadow_node_peek_color (node));
|
||||
add_float (nodes, gsk_outset_shadow_node_get_dx (node));
|
||||
add_float (nodes, gsk_outset_shadow_node_get_dy (node));
|
||||
add_float (nodes, gsk_outset_shadow_node_get_spread (node));
|
||||
add_float (nodes, gsk_outset_shadow_node_get_blur_radius (node));
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_INSET_SHADOW_NODE:
|
||||
{
|
||||
add_uint32 (nodes, BROADWAY_NODE_INSET_SHADOW);
|
||||
add_rounded_rect (nodes, gsk_inset_shadow_node_peek_outline (node), offset_x, offset_y);
|
||||
add_rgba (nodes, gsk_inset_shadow_node_peek_color (node));
|
||||
add_float (nodes, gsk_inset_shadow_node_get_dx (node));
|
||||
add_float (nodes, gsk_inset_shadow_node_get_dy (node));
|
||||
add_float (nodes, gsk_inset_shadow_node_get_spread (node));
|
||||
add_float (nodes, gsk_inset_shadow_node_get_blur_radius (node));
|
||||
}
|
||||
if (add_new_node (renderer, node, BROADWAY_NODE_INSET_SHADOW))
|
||||
{
|
||||
add_rounded_rect (nodes, gsk_inset_shadow_node_peek_outline (node), offset_x, offset_y);
|
||||
add_rgba (nodes, gsk_inset_shadow_node_peek_color (node));
|
||||
add_float (nodes, gsk_inset_shadow_node_get_dx (node));
|
||||
add_float (nodes, gsk_inset_shadow_node_get_dy (node));
|
||||
add_float (nodes, gsk_inset_shadow_node_get_spread (node));
|
||||
add_float (nodes, gsk_inset_shadow_node_get_blur_radius (node));
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_LINEAR_GRADIENT_NODE:
|
||||
{
|
||||
guint i, n;
|
||||
if (add_new_node (renderer, node, BROADWAY_NODE_LINEAR_GRADIENT))
|
||||
{
|
||||
guint i, n;
|
||||
|
||||
add_uint32 (nodes, BROADWAY_NODE_LINEAR_GRADIENT);
|
||||
add_rect (nodes, &node->bounds, offset_x, offset_y);
|
||||
add_point (nodes, gsk_linear_gradient_node_peek_start (node), offset_x, offset_y);
|
||||
add_point (nodes, gsk_linear_gradient_node_peek_end (node), offset_x, offset_y);
|
||||
n = gsk_linear_gradient_node_get_n_color_stops (node);
|
||||
add_uint32 (nodes, n);
|
||||
for (i = 0; i < n; i++)
|
||||
add_color_stop (nodes, &gsk_linear_gradient_node_peek_color_stops (node)[i]);
|
||||
}
|
||||
add_rect (nodes, &node->bounds, offset_x, offset_y);
|
||||
add_point (nodes, gsk_linear_gradient_node_peek_start (node), offset_x, offset_y);
|
||||
add_point (nodes, gsk_linear_gradient_node_peek_end (node), offset_x, offset_y);
|
||||
n = gsk_linear_gradient_node_get_n_color_stops (node);
|
||||
add_uint32 (nodes, n);
|
||||
for (i = 0; i < n; i++)
|
||||
add_color_stop (nodes, &gsk_linear_gradient_node_peek_color_stops (node)[i]);
|
||||
}
|
||||
return;
|
||||
|
||||
/* Bin nodes */
|
||||
|
||||
case GSK_SHADOW_NODE:
|
||||
{
|
||||
gsize i, n_shadows = gsk_shadow_node_get_n_shadows (node);
|
||||
add_uint32 (nodes, BROADWAY_NODE_SHADOW);
|
||||
add_uint32 (nodes, n_shadows);
|
||||
for (i = 0; i < n_shadows; i++)
|
||||
{
|
||||
const GskShadow *shadow = gsk_shadow_node_peek_shadow (node, i);
|
||||
add_rgba (nodes, &shadow->color);
|
||||
add_float (nodes, shadow->dx);
|
||||
add_float (nodes, shadow->dy);
|
||||
add_float (nodes, shadow->radius);
|
||||
}
|
||||
gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
|
||||
gsk_shadow_node_get_child (node),
|
||||
offset_x, offset_y);
|
||||
}
|
||||
if (add_new_node (renderer, node, BROADWAY_NODE_SHADOW))
|
||||
{
|
||||
gsize i, n_shadows = gsk_shadow_node_get_n_shadows (node);
|
||||
|
||||
add_uint32 (nodes, n_shadows);
|
||||
for (i = 0; i < n_shadows; i++)
|
||||
{
|
||||
const GskShadow *shadow = gsk_shadow_node_peek_shadow (node, i);
|
||||
add_rgba (nodes, &shadow->color);
|
||||
add_float (nodes, shadow->dx);
|
||||
add_float (nodes, shadow->dy);
|
||||
add_float (nodes, shadow->radius);
|
||||
}
|
||||
gsk_broadway_renderer_add_node (renderer,
|
||||
gsk_shadow_node_get_child (node),
|
||||
offset_x, offset_y);
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_OPACITY_NODE:
|
||||
{
|
||||
add_uint32 (nodes, BROADWAY_NODE_OPACITY);
|
||||
add_float (nodes, gsk_opacity_node_get_opacity (node));
|
||||
gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
|
||||
gsk_opacity_node_get_child (node),
|
||||
offset_x, offset_y);
|
||||
}
|
||||
if (add_new_node (renderer, node, BROADWAY_NODE_OPACITY))
|
||||
{
|
||||
add_float (nodes, gsk_opacity_node_get_opacity (node));
|
||||
gsk_broadway_renderer_add_node (renderer,
|
||||
gsk_opacity_node_get_child (node),
|
||||
offset_x, offset_y);
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_ROUNDED_CLIP_NODE:
|
||||
{
|
||||
const GskRoundedRect *rclip = gsk_rounded_clip_node_peek_clip (node);
|
||||
add_uint32 (nodes, BROADWAY_NODE_ROUNDED_CLIP);
|
||||
add_rounded_rect (nodes, rclip, offset_x, offset_y);
|
||||
gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
|
||||
gsk_rounded_clip_node_get_child (node),
|
||||
rclip->bounds.origin.x,
|
||||
rclip->bounds.origin.y);
|
||||
}
|
||||
if (add_new_node (renderer, node, BROADWAY_NODE_ROUNDED_CLIP))
|
||||
{
|
||||
const GskRoundedRect *rclip = gsk_rounded_clip_node_peek_clip (node);
|
||||
|
||||
add_rounded_rect (nodes, rclip, offset_x, offset_y);
|
||||
gsk_broadway_renderer_add_node (renderer,
|
||||
gsk_rounded_clip_node_get_child (node),
|
||||
rclip->bounds.origin.x,
|
||||
rclip->bounds.origin.y);
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_CLIP_NODE:
|
||||
if (add_new_node (renderer, node, BROADWAY_NODE_CLIP))
|
||||
{
|
||||
const graphene_rect_t *clip = gsk_clip_node_peek_clip (node);
|
||||
|
||||
add_rect (nodes, clip, offset_x, offset_y);
|
||||
gsk_broadway_renderer_add_node (renderer,
|
||||
gsk_clip_node_get_child (node),
|
||||
clip->origin.x,
|
||||
clip->origin.y);
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_TRANSFORM_NODE:
|
||||
{
|
||||
const graphene_rect_t *clip = gsk_clip_node_peek_clip (node);
|
||||
add_uint32 (nodes, BROADWAY_NODE_CLIP);
|
||||
add_rect (nodes, clip, offset_x, offset_y);
|
||||
gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
|
||||
gsk_clip_node_get_child (node),
|
||||
clip->origin.x,
|
||||
clip->origin.y);
|
||||
GskTransform *transform = gsk_transform_node_get_transform (node);
|
||||
GskTransformCategory category = gsk_transform_get_category (transform);
|
||||
|
||||
if (category >= GSK_TRANSFORM_CATEGORY_2D_TRANSLATE)
|
||||
{
|
||||
if (add_new_node (renderer, node, BROADWAY_NODE_TRANSLATE)) {
|
||||
float dx, dy;
|
||||
gsk_transform_to_translate (transform, &dx, &dy);
|
||||
|
||||
add_xy (nodes, dx, dy, offset_x, offset_y);
|
||||
gsk_broadway_renderer_add_node (renderer,
|
||||
gsk_transform_node_get_child (node),
|
||||
0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fallback to texture for now */
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_DEBUG_NODE:
|
||||
if (add_new_node (renderer, node, BROADWAY_NODE_DEBUG))
|
||||
{
|
||||
const char *message = gsk_debug_node_get_message (node);
|
||||
add_string (nodes, message);
|
||||
gsk_broadway_renderer_add_node (renderer,
|
||||
gsk_debug_node_get_child (node), offset_x, offset_y);
|
||||
}
|
||||
return;
|
||||
|
||||
/* Generic nodes */
|
||||
|
||||
case GSK_CONTAINER_NODE:
|
||||
{
|
||||
guint i;
|
||||
if (add_new_node (renderer, node, BROADWAY_NODE_CONTAINER))
|
||||
{
|
||||
guint i;
|
||||
|
||||
add_uint32 (nodes, BROADWAY_NODE_CONTAINER);
|
||||
add_uint32 (nodes, gsk_container_node_get_n_children (node));
|
||||
|
||||
for (i = 0; i < gsk_container_node_get_n_children (node); i++)
|
||||
gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
|
||||
gsk_container_node_get_child (node, i), offset_x, offset_y);
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_DEBUG_NODE:
|
||||
gsk_broadway_renderer_add_node (renderer, nodes, node_textures,
|
||||
gsk_debug_node_get_child (node), offset_x, offset_y);
|
||||
add_uint32 (nodes, gsk_container_node_get_n_children (node));
|
||||
for (i = 0; i < gsk_container_node_get_n_children (node); i++)
|
||||
gsk_broadway_renderer_add_node (renderer,
|
||||
gsk_container_node_get_child (node, i), offset_x, offset_y);
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_COLOR_MATRIX_NODE:
|
||||
case GSK_TEXT_NODE:
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
case GSK_TRANSFORM_NODE:
|
||||
case GSK_REPEAT_NODE:
|
||||
case GSK_BLEND_NODE:
|
||||
case GSK_CROSS_FADE_NODE:
|
||||
@@ -665,32 +563,33 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
|
||||
break; /* Fallback */
|
||||
}
|
||||
|
||||
{
|
||||
GdkTexture *texture;
|
||||
guint32 texture_id;
|
||||
float t_off_x = 0, t_off_y = 0;
|
||||
if (add_new_node (renderer, node, BROADWAY_NODE_TEXTURE))
|
||||
{
|
||||
GdkTexture *texture;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
guint32 texture_id;
|
||||
int x = floorf (node->bounds.origin.x);
|
||||
int y = floorf (node->bounds.origin.y);
|
||||
int width = ceil (node->bounds.origin.x + node->bounds.size.width) - x;
|
||||
int height = ceil (node->bounds.origin.y + node->bounds.size.height) - y;
|
||||
|
||||
texture = node_cache_lookup (node, &t_off_x, &t_off_y);
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
|
||||
cr = cairo_create (surface);
|
||||
cairo_translate (cr, -x, -y);
|
||||
gsk_render_node_draw (node, cr);
|
||||
cairo_destroy (cr);
|
||||
|
||||
if (!texture)
|
||||
{
|
||||
texture = node_texture_fallback (node, &t_off_x, &t_off_y);
|
||||
#if 0
|
||||
g_print ("Fallback %p for %s\n", texture, node->node_class->type_name);
|
||||
#endif
|
||||
texture = gdk_texture_new_for_surface (surface);
|
||||
g_ptr_array_add (self->node_textures, texture); /* Transfers ownership to node_textures */
|
||||
|
||||
node_cache_store (node, texture, t_off_x, t_off_y);
|
||||
}
|
||||
|
||||
g_ptr_array_add (node_textures, texture); /* Transfers ownership to node_textures */
|
||||
texture_id = gdk_broadway_display_ensure_texture (display, texture);
|
||||
add_uint32 (nodes, BROADWAY_NODE_TEXTURE);
|
||||
add_float (nodes, node->bounds.origin.x + t_off_x - offset_x);
|
||||
add_float (nodes, node->bounds.origin.y + t_off_y - offset_y);
|
||||
add_float (nodes, gdk_texture_get_width (texture));
|
||||
add_float (nodes, gdk_texture_get_height (texture));
|
||||
add_uint32 (nodes, texture_id);
|
||||
}
|
||||
texture_id = gdk_broadway_display_ensure_texture (display, texture);
|
||||
add_float (nodes, x - offset_x);
|
||||
add_float (nodes, y - offset_y);
|
||||
add_float (nodes, gdk_texture_get_width (texture));
|
||||
add_float (nodes, gdk_texture_get_height (texture));
|
||||
add_uint32 (nodes, texture_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -700,9 +599,40 @@ gsk_broadway_renderer_render (GskRenderer *renderer,
|
||||
{
|
||||
GskBroadwayRenderer *self = GSK_BROADWAY_RENDERER (renderer);
|
||||
|
||||
self->node_lookup = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
|
||||
gdk_draw_context_begin_frame (GDK_DRAW_CONTEXT (self->draw_context), update_area);
|
||||
gsk_broadway_renderer_add_node (renderer, self->draw_context->nodes, self->draw_context->node_textures, root, 0, 0);
|
||||
|
||||
/* These are owned by the draw context between begin and end, but
|
||||
cache them here for easier access during the render */
|
||||
self->nodes = self->draw_context->nodes;
|
||||
self->node_textures = self->draw_context->node_textures;
|
||||
|
||||
gsk_broadway_renderer_add_node (renderer, root, 0, 0);
|
||||
|
||||
self->nodes = NULL;
|
||||
self->node_textures = NULL;
|
||||
|
||||
gdk_draw_context_end_frame (GDK_DRAW_CONTEXT (self->draw_context));
|
||||
|
||||
if (self->last_node_lookup)
|
||||
g_hash_table_unref (self->last_node_lookup);
|
||||
self->last_node_lookup = self->node_lookup;
|
||||
self->node_lookup = NULL;
|
||||
|
||||
if (self->last_root)
|
||||
gsk_render_node_unref (self->last_root);
|
||||
self->last_root = gsk_render_node_ref (root);
|
||||
|
||||
if (self->next_node_id > G_MAXUINT32 / 2)
|
||||
{
|
||||
/* We're "near" a wrap of the ids, lets avoid reusing any of
|
||||
* these nodes next frame, then we can reset the id counter
|
||||
* without risk of any old nodes sticking around and conflicting. */
|
||||
|
||||
g_hash_table_remove_all (self->last_node_lookup);
|
||||
self->next_node_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
+1
-1
@@ -176,7 +176,7 @@ typedef enum {
|
||||
* determined.
|
||||
* @GSK_TRANSFORM_CATEGORY_ANY: Analyzing the matrix concluded that it does
|
||||
* not fit in any other category.
|
||||
* @GSK_TRANSFORM_CATEGORY_2D: The matrix is a 3D matrix. This means that
|
||||
* @GSK_TRANSFORM_CATEGORY_3D: The matrix is a 3D matrix. This means that
|
||||
* the w column (the last column) has the values (0, 0, 0, 1).
|
||||
* @GSK_TRANSFORM_CATEGORY_2D: The matrix is a 2D matrix. This is equivalent
|
||||
* to graphene_matrix_is_2d() returning %TRUE. In particular, this
|
||||
|
||||
+15
-85
@@ -68,7 +68,6 @@ typedef struct
|
||||
GdkSurface *surface;
|
||||
GskRenderNode *prev_node;
|
||||
GskRenderNode *root_node;
|
||||
GdkDisplay *display;
|
||||
|
||||
GskProfiler *profiler;
|
||||
|
||||
@@ -80,8 +79,9 @@ typedef struct
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GskRenderer, gsk_renderer, G_TYPE_OBJECT)
|
||||
|
||||
enum {
|
||||
PROP_SURFACE = 1,
|
||||
PROP_DISPLAY,
|
||||
PROP_0,
|
||||
PROP_REALIZED,
|
||||
PROP_SURFACE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
@@ -134,33 +134,10 @@ gsk_renderer_dispose (GObject *gobject)
|
||||
g_assert (!priv->is_realized);
|
||||
|
||||
g_clear_object (&priv->profiler);
|
||||
g_clear_object (&priv->display);
|
||||
|
||||
G_OBJECT_CLASS (gsk_renderer_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_renderer_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GskRenderer *self = GSK_RENDERER (gobject);
|
||||
GskRendererPrivate *priv = gsk_renderer_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DISPLAY:
|
||||
/* Construct-only */
|
||||
priv->display = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_renderer_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
@@ -172,12 +149,12 @@ gsk_renderer_get_property (GObject *gobject,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SURFACE:
|
||||
g_value_set_object (value, priv->surface);
|
||||
case PROP_REALIZED:
|
||||
g_value_set_boolean (value, priv->is_realized);
|
||||
break;
|
||||
|
||||
case PROP_DISPLAY:
|
||||
g_value_set_object (value, priv->display);
|
||||
case PROP_SURFACE:
|
||||
g_value_set_object (value, priv->surface);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -186,23 +163,6 @@ gsk_renderer_get_property (GObject *gobject,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_renderer_constructed (GObject *gobject)
|
||||
{
|
||||
GskRenderer *self = GSK_RENDERER (gobject);
|
||||
GskRendererPrivate *priv = gsk_renderer_get_instance_private (self);
|
||||
|
||||
if (priv->display == NULL)
|
||||
{
|
||||
GdkDisplayManager *manager = gdk_display_manager_get ();
|
||||
|
||||
priv->display = gdk_display_manager_get_default_display (manager);
|
||||
g_assert (priv->display != NULL);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gsk_renderer_parent_class)->constructed (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_renderer_class_init (GskRendererClass *klass)
|
||||
{
|
||||
@@ -213,32 +173,22 @@ gsk_renderer_class_init (GskRendererClass *klass)
|
||||
klass->render = gsk_renderer_real_render;
|
||||
klass->render_texture = gsk_renderer_real_render_texture;
|
||||
|
||||
gobject_class->constructed = gsk_renderer_constructed;
|
||||
gobject_class->set_property = gsk_renderer_set_property;
|
||||
gobject_class->get_property = gsk_renderer_get_property;
|
||||
gobject_class->dispose = gsk_renderer_dispose;
|
||||
|
||||
/**
|
||||
* GskRenderer:display:
|
||||
*
|
||||
* The #GdkDisplay used by the #GskRenderer.
|
||||
*/
|
||||
gsk_renderer_properties[PROP_DISPLAY] =
|
||||
g_param_spec_object ("display",
|
||||
"Display",
|
||||
"The GdkDisplay object used by the renderer",
|
||||
GDK_TYPE_DISPLAY,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
gsk_renderer_properties[PROP_REALIZED] =
|
||||
g_param_spec_boolean ("realized",
|
||||
"Realized",
|
||||
"The renderer has been associated with a surface",
|
||||
FALSE,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
gsk_renderer_properties[PROP_SURFACE] =
|
||||
g_param_spec_object ("surface",
|
||||
"Surface",
|
||||
"The surface associated to the renderer",
|
||||
GDK_TYPE_SURFACE,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, gsk_renderer_properties);
|
||||
}
|
||||
@@ -290,24 +240,6 @@ gsk_renderer_get_root_node (GskRenderer *renderer)
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_renderer_get_display:
|
||||
* @renderer: a #GskRenderer
|
||||
*
|
||||
* Retrieves the #GdkDisplay used when creating the #GskRenderer.
|
||||
*
|
||||
* Returns: (transfer none): a #GdkDisplay
|
||||
*/
|
||||
GdkDisplay *
|
||||
gsk_renderer_get_display (GskRenderer *renderer)
|
||||
{
|
||||
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
|
||||
|
||||
g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
|
||||
|
||||
return priv->display;
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gsk_renderer_is_realized:
|
||||
* @renderer: a #GskRenderer
|
||||
*
|
||||
@@ -674,9 +606,7 @@ gsk_renderer_new_for_surface (GdkSurface *surface)
|
||||
* information to stdout.
|
||||
*/
|
||||
verbose |= renderer_possibilities[i].verbose;
|
||||
renderer = g_object_new (renderer_type,
|
||||
"display", gdk_surface_get_display (surface),
|
||||
NULL);
|
||||
renderer = g_object_new (renderer_type, NULL);
|
||||
|
||||
if (gsk_renderer_realize (renderer, surface, &error))
|
||||
{
|
||||
|
||||
+4
-5
@@ -39,13 +39,10 @@ GDK_AVAILABLE_IN_ALL
|
||||
GType gsk_renderer_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GskRenderer * gsk_renderer_new_for_surface (GdkSurface *surface);
|
||||
GskRenderer * gsk_renderer_new_for_surface (GdkSurface *surface);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface * gsk_renderer_get_surface (GskRenderer *renderer);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay * gsk_renderer_get_display (GskRenderer *renderer);
|
||||
GdkSurface * gsk_renderer_get_surface (GskRenderer *renderer);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gsk_renderer_realize (GskRenderer *renderer,
|
||||
@@ -53,6 +50,8 @@ gboolean gsk_renderer_realize (GskRenderer
|
||||
GError **error);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gsk_renderer_unrealize (GskRenderer *renderer);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gsk_renderer_is_realized (GskRenderer *renderer);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkTexture * gsk_renderer_render_texture (GskRenderer *renderer,
|
||||
|
||||
@@ -51,8 +51,6 @@ struct _GskRendererClass
|
||||
const cairo_region_t *invalid);
|
||||
};
|
||||
|
||||
gboolean gsk_renderer_is_realized (GskRenderer *renderer);
|
||||
|
||||
GskRenderNode * gsk_renderer_get_root_node (GskRenderer *renderer);
|
||||
|
||||
GskProfiler * gsk_renderer_get_profiler (GskRenderer *renderer);
|
||||
|
||||
+14
-1
@@ -2427,6 +2427,19 @@ gsk_transform_node_draw (GskRenderNode *node,
|
||||
gsk_render_node_draw (self->child, cr);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_transform_node_can_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2)
|
||||
{
|
||||
GskTransformNode *self1 = (GskTransformNode *) node1;
|
||||
GskTransformNode *self2 = (GskTransformNode *) node2;
|
||||
|
||||
if (!gsk_transform_equal (self1->transform, self2->transform))
|
||||
return FALSE;
|
||||
|
||||
return gsk_render_node_can_diff (self1->child, self2->child);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_transform_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
@@ -2563,7 +2576,7 @@ static const GskRenderNodeClass GSK_TRANSFORM_NODE_CLASS = {
|
||||
"GskTransformNode",
|
||||
gsk_transform_node_finalize,
|
||||
gsk_transform_node_draw,
|
||||
gsk_render_node_can_diff_true,
|
||||
gsk_transform_node_can_diff,
|
||||
gsk_transform_node_diff,
|
||||
gsk_transform_node_serialize,
|
||||
gsk_transform_node_deserialize
|
||||
|
||||
+116
-5
@@ -1095,6 +1095,120 @@ gsk_transform_scale_3d (GskTransform *next,
|
||||
return &result->parent;
|
||||
}
|
||||
|
||||
/*** PERSPECTIVE ***/
|
||||
|
||||
typedef struct _GskPerspectiveTransform GskPerspectiveTransform;
|
||||
|
||||
struct _GskPerspectiveTransform
|
||||
{
|
||||
GskTransform parent;
|
||||
|
||||
float depth;
|
||||
};
|
||||
|
||||
static void
|
||||
gsk_perspective_transform_finalize (GskTransform *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_perspective_transform_to_matrix (GskTransform *transform,
|
||||
graphene_matrix_t *out_matrix)
|
||||
{
|
||||
GskPerspectiveTransform *self = (GskPerspectiveTransform *) transform;
|
||||
float f[16] = { 1.f, 0.f, 0.f, 0.f,
|
||||
0.f, 1.f, 0.f, 0.f,
|
||||
0.f, 0.f, 1.f, -1.f / self->depth,
|
||||
0.f, 0.f, 0.f, 1.f };
|
||||
|
||||
graphene_matrix_init_from_float (out_matrix, f);
|
||||
}
|
||||
|
||||
|
||||
static GskTransform *
|
||||
gsk_perspective_transform_apply (GskTransform *transform,
|
||||
GskTransform *apply_to)
|
||||
{
|
||||
GskPerspectiveTransform *self = (GskPerspectiveTransform *) transform;
|
||||
|
||||
return gsk_transform_perspective (apply_to, self->depth);
|
||||
}
|
||||
|
||||
static GskTransform *
|
||||
gsk_perspective_transform_invert (GskTransform *transform,
|
||||
GskTransform *next)
|
||||
{
|
||||
GskPerspectiveTransform *self = (GskPerspectiveTransform *) transform;
|
||||
|
||||
return gsk_transform_perspective (next, - self->depth);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_perspective_transform_equal (GskTransform *first_transform,
|
||||
GskTransform *second_transform)
|
||||
{
|
||||
GskPerspectiveTransform *first = (GskPerspectiveTransform *) first_transform;
|
||||
GskPerspectiveTransform *second = (GskPerspectiveTransform *) second_transform;
|
||||
|
||||
return first->depth == second->depth;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_perspective_transform_print (GskTransform *transform,
|
||||
GString *string)
|
||||
{
|
||||
GskPerspectiveTransform *self = (GskPerspectiveTransform *) transform;
|
||||
|
||||
g_string_append (string, "perspective(");
|
||||
string_append_double (string, self->depth);
|
||||
g_string_append (string, ")");
|
||||
}
|
||||
|
||||
static const GskTransformClass GSK_PERSPECTIVE_TRANSFORM_CLASS =
|
||||
{
|
||||
sizeof (GskPerspectiveTransform),
|
||||
"GskPerspectiveTransform",
|
||||
gsk_perspective_transform_finalize,
|
||||
gsk_perspective_transform_to_matrix,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
gsk_perspective_transform_print,
|
||||
gsk_perspective_transform_apply,
|
||||
gsk_perspective_transform_invert,
|
||||
gsk_perspective_transform_equal,
|
||||
};
|
||||
|
||||
/**
|
||||
* gsk_transform_perspective:
|
||||
* @next: (allow-none): the next transform
|
||||
* @depth: distance of the z=0 plane. Lower values give a more
|
||||
* flattened pyramid and therefore a more pronounced
|
||||
* perspective effect.
|
||||
*
|
||||
* Applies a perspective projection transform. This transform
|
||||
* scales points in X and Y based on their Z value, scaling
|
||||
* points with positive Z values away from the origin, and
|
||||
* those with negative Z values towards the origin. Points
|
||||
* on the z=0 plane are unchanged.
|
||||
*
|
||||
* Returns: The new matrix
|
||||
**/
|
||||
GskTransform *
|
||||
gsk_transform_perspective (GskTransform *next,
|
||||
float depth)
|
||||
{
|
||||
GskPerspectiveTransform *result;
|
||||
|
||||
result = gsk_transform_alloc (&GSK_PERSPECTIVE_TRANSFORM_CLASS,
|
||||
GSK_TRANSFORM_CATEGORY_ANY,
|
||||
next);
|
||||
|
||||
result->depth = depth;
|
||||
|
||||
return &result->parent;
|
||||
}
|
||||
|
||||
/*** PUBLIC API ***/
|
||||
|
||||
static void
|
||||
@@ -1225,7 +1339,7 @@ gsk_transform_to_matrix (GskTransform *self,
|
||||
|
||||
/**
|
||||
* gsk_transform_to_2d:
|
||||
* @m: a 2D #GskTransform
|
||||
* @self: a 2D #GskTransform
|
||||
* @out_xx: (out): return location for the xx member
|
||||
* @out_yx: (out): return location for the yx member
|
||||
* @out_xy: (out): return location for the xy member
|
||||
@@ -1250,9 +1364,6 @@ gsk_transform_to_matrix (GskTransform *self,
|
||||
* This function can be used to convert between a #GskTransform
|
||||
* and a matrix type from other 2D drawing libraries, in particular
|
||||
* Cairo.
|
||||
*
|
||||
* Returns: %TRUE if the matrix is compatible with an 2D
|
||||
* transformation matrix.
|
||||
*/
|
||||
void
|
||||
gsk_transform_to_2d (GskTransform *self,
|
||||
@@ -1344,7 +1455,7 @@ gsk_transform_to_affine (GskTransform *self,
|
||||
|
||||
/**
|
||||
* gsk_transform_to_translate:
|
||||
* @m: a #GskTransform
|
||||
* @self: a #GskTransform
|
||||
* @out_dx: (out): return location for the translation
|
||||
* in the x direction
|
||||
* @out_dy: (out): return location for the translation
|
||||
|
||||
@@ -105,6 +105,9 @@ GskTransform * gsk_transform_scale_3d (GskTransform
|
||||
float factor_x,
|
||||
float factor_y,
|
||||
float factor_z);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GskTransform * gsk_transform_perspective (GskTransform *next,
|
||||
float depth);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gsk_transform_transform_bounds (GskTransform *self,
|
||||
|
||||
@@ -367,7 +367,7 @@ static void delete_text_cb (GtkEditable *editable,
|
||||
gint end);
|
||||
|
||||
static gboolean check_for_selection_change (GtkEntryAccessible *entry,
|
||||
GtkEntry *gtk_entry);
|
||||
GtkEditable *editable);
|
||||
|
||||
|
||||
static void atk_editable_text_interface_init (AtkEditableTextIface *iface);
|
||||
@@ -465,56 +465,57 @@ gtk_entry_accessible_notify_gtk (GObject *obj,
|
||||
{
|
||||
GtkWidget *widget;
|
||||
AtkObject* atk_obj;
|
||||
GtkEntry* gtk_entry;
|
||||
GtkEntryAccessible* entry;
|
||||
GtkEntryAccessiblePrivate *priv;
|
||||
|
||||
widget = GTK_WIDGET (obj);
|
||||
atk_obj = gtk_widget_get_accessible (widget);
|
||||
gtk_entry = GTK_ENTRY (widget);
|
||||
entry = GTK_ENTRY_ACCESSIBLE (atk_obj);
|
||||
priv = entry->priv;
|
||||
|
||||
if (g_strcmp0 (pspec->name, "cursor-position") == 0)
|
||||
{
|
||||
if (check_for_selection_change (entry, gtk_entry))
|
||||
if (check_for_selection_change (entry, GTK_EDITABLE (widget)))
|
||||
g_signal_emit_by_name (atk_obj, "text-selection-changed");
|
||||
/*
|
||||
* The entry cursor position has moved so generate the signal.
|
||||
*/
|
||||
g_signal_emit_by_name (atk_obj, "text-caret-moved",
|
||||
entry->priv->cursor_position);
|
||||
gtk_editable_get_position (GTK_EDITABLE (widget)));
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "selection-bound") == 0)
|
||||
{
|
||||
if (check_for_selection_change (entry, gtk_entry))
|
||||
if (check_for_selection_change (entry, GTK_EDITABLE (widget)))
|
||||
g_signal_emit_by_name (atk_obj, "text-selection-changed");
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "editable") == 0)
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "editable") == 0)
|
||||
{
|
||||
gboolean value;
|
||||
|
||||
g_object_get (obj, "editable", &value, NULL);
|
||||
atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE, value);
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "visibility") == 0)
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "visibility") == 0)
|
||||
{
|
||||
gboolean visibility;
|
||||
AtkRole new_role;
|
||||
|
||||
visibility = gtk_entry_get_visibility (gtk_entry);
|
||||
visibility = gtk_entry_get_visibility (GTK_ENTRY (widget));
|
||||
new_role = visibility ? ATK_ROLE_TEXT : ATK_ROLE_PASSWORD_TEXT;
|
||||
atk_object_set_role (atk_obj, new_role);
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "primary-icon-storage-type") == 0)
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "primary-icon-storage-type") == 0)
|
||||
{
|
||||
if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
priv->icons[GTK_ENTRY_ICON_PRIMARY] = gtk_entry_icon_accessible_new (entry, GTK_ENTRY_ICON_PRIMARY);
|
||||
g_signal_emit_by_name (entry, "children-changed::add", 0,
|
||||
priv->icons[GTK_ENTRY_ICON_PRIMARY], NULL);
|
||||
}
|
||||
else if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_PRIMARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
else if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_PRIMARY]));
|
||||
g_signal_emit_by_name (entry, "children-changed::remove", 0,
|
||||
@@ -522,16 +523,17 @@ gtk_entry_accessible_notify_gtk (GObject *obj,
|
||||
g_clear_object (&priv->icons[GTK_ENTRY_ICON_PRIMARY]);
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "secondary-icon-storage-type") == 0)
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "secondary-icon-storage-type") == 0)
|
||||
{
|
||||
gint index = (priv->icons[GTK_ENTRY_ICON_PRIMARY] ? 1 : 0);
|
||||
if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY && !priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
priv->icons[GTK_ENTRY_ICON_SECONDARY] = gtk_entry_icon_accessible_new (entry, GTK_ENTRY_ICON_SECONDARY);
|
||||
g_signal_emit_by_name (entry, "children-changed::add", index,
|
||||
priv->icons[GTK_ENTRY_ICON_SECONDARY], NULL);
|
||||
}
|
||||
else if (gtk_entry_get_icon_storage_type (gtk_entry, GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
else if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY && priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
gtk_entry_icon_accessible_invalidate (GTK_ENTRY_ICON_ACCESSIBLE (priv->icons[GTK_ENTRY_ICON_SECONDARY]));
|
||||
g_signal_emit_by_name (entry, "children-changed::remove", index,
|
||||
@@ -539,100 +541,100 @@ gtk_entry_accessible_notify_gtk (GObject *obj,
|
||||
g_clear_object (&priv->icons[GTK_ENTRY_ICON_SECONDARY]);
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "primary-icon-name") == 0)
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "primary-icon-name") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
const gchar *name;
|
||||
name = gtk_entry_get_icon_name (gtk_entry,
|
||||
GTK_ENTRY_ICON_PRIMARY);
|
||||
name = gtk_entry_get_icon_name (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
|
||||
if (name)
|
||||
atk_object_set_name (priv->icons[GTK_ENTRY_ICON_PRIMARY], name);
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "secondary-icon-name") == 0)
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "secondary-icon-name") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
const gchar *name;
|
||||
name = gtk_entry_get_icon_name (gtk_entry,
|
||||
GTK_ENTRY_ICON_SECONDARY);
|
||||
name = gtk_entry_get_icon_name (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
|
||||
if (name)
|
||||
atk_object_set_name (priv->icons[GTK_ENTRY_ICON_SECONDARY], name);
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "primary-icon-tooltip-text") == 0)
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "primary-icon-tooltip-text") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
gchar *text;
|
||||
text = gtk_entry_get_icon_tooltip_text (gtk_entry,
|
||||
GTK_ENTRY_ICON_PRIMARY);
|
||||
text = gtk_entry_get_icon_tooltip_text (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
|
||||
if (text)
|
||||
{
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY],
|
||||
text);
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY], text);
|
||||
g_free (text);
|
||||
}
|
||||
else
|
||||
{
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY],
|
||||
"");
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_PRIMARY], "");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "secondary-icon-tooltip-text") == 0)
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "secondary-icon-tooltip-text") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
gchar *text;
|
||||
text = gtk_entry_get_icon_tooltip_text (gtk_entry,
|
||||
GTK_ENTRY_ICON_SECONDARY);
|
||||
text = gtk_entry_get_icon_tooltip_text (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
|
||||
if (text)
|
||||
{
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY],
|
||||
text);
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY], text);
|
||||
g_free (text);
|
||||
}
|
||||
else
|
||||
{
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY],
|
||||
"");
|
||||
atk_object_set_description (priv->icons[GTK_ENTRY_ICON_SECONDARY], "");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "primary-icon-activatable") == 0)
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "primary-icon-activatable") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
gboolean on = gtk_entry_get_icon_activatable (gtk_entry, GTK_ENTRY_ICON_PRIMARY);
|
||||
gboolean on = gtk_entry_get_icon_activatable (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
|
||||
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY],
|
||||
ATK_STATE_ENABLED, on);
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "secondary-icon-activatable") == 0)
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "secondary-icon-activatable") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
gboolean on = gtk_entry_get_icon_activatable (gtk_entry, GTK_ENTRY_ICON_SECONDARY);
|
||||
gboolean on = gtk_entry_get_icon_activatable (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
|
||||
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY],
|
||||
ATK_STATE_ENABLED, on);
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "primary-icon-sensitive") == 0)
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "primary-icon-sensitive") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_PRIMARY])
|
||||
{
|
||||
gboolean on = gtk_entry_get_icon_sensitive (gtk_entry, GTK_ENTRY_ICON_PRIMARY);
|
||||
gboolean on = gtk_entry_get_icon_sensitive (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY);
|
||||
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_PRIMARY],
|
||||
ATK_STATE_SENSITIVE, on);
|
||||
}
|
||||
}
|
||||
else if (g_strcmp0 (pspec->name, "secondary-icon-sensitive") == 0)
|
||||
else if (GTK_IS_ENTRY (widget) &&
|
||||
g_strcmp0 (pspec->name, "secondary-icon-sensitive") == 0)
|
||||
{
|
||||
if (priv->icons[GTK_ENTRY_ICON_SECONDARY])
|
||||
{
|
||||
gboolean on = gtk_entry_get_icon_sensitive (gtk_entry, GTK_ENTRY_ICON_SECONDARY);
|
||||
gboolean on = gtk_entry_get_icon_sensitive (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY);
|
||||
atk_object_notify_state_change (priv->icons[GTK_ENTRY_ICON_SECONDARY],
|
||||
ATK_STATE_SENSITIVE, on);
|
||||
}
|
||||
@@ -1450,12 +1452,12 @@ delete_text_cb (GtkEditable *editable,
|
||||
|
||||
static gboolean
|
||||
check_for_selection_change (GtkEntryAccessible *accessible,
|
||||
GtkEntry *entry)
|
||||
GtkEditable *editable)
|
||||
{
|
||||
gboolean ret_val = FALSE;
|
||||
gint start, end;
|
||||
|
||||
if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start, &end))
|
||||
if (gtk_editable_get_selection_bounds (editable, &start, &end))
|
||||
{
|
||||
if (end != accessible->priv->cursor_position ||
|
||||
start != accessible->priv->selection_bound)
|
||||
|
||||
@@ -46,11 +46,6 @@ xml += '\n'
|
||||
for f in get_files('theme/HighContrast/assets', '.svg'):
|
||||
xml += ' <file>theme/HighContrast/assets/{0}</file>\n'.format(f)
|
||||
|
||||
xml += '''
|
||||
<file>theme/win32/gtk-win32-base.css</file>
|
||||
<file>theme/win32/gtk.css</file>
|
||||
'''
|
||||
|
||||
for f in get_files('gesture', '.symbolic.png'):
|
||||
xml += ' <file alias=\'icons/64x64/actions/{0}\'>gesture/{0}</file>\n'.format(f)
|
||||
|
||||
|
||||
@@ -45,8 +45,10 @@
|
||||
#include <gtk/gtkaspectframe.h>
|
||||
#include <gtk/gtkassistant.h>
|
||||
#include <gtk/gtkbin.h>
|
||||
#include <gtk/gtkbinlayout.h>
|
||||
#include <gtk/gtkbindings.h>
|
||||
#include <gtk/gtkborder.h>
|
||||
#include <gtk/gtkboxlayout.h>
|
||||
#include <gtk/gtkbox.h>
|
||||
#include <gtk/gtkbuildable.h>
|
||||
#include <gtk/gtkbuilder.h>
|
||||
@@ -80,6 +82,7 @@
|
||||
#include <gtk/gtkcontainer.h>
|
||||
#include <gtk/gtkcssprovider.h>
|
||||
#include <gtk/gtkcsssection.h>
|
||||
#include <gtk/gtkcustomlayout.h>
|
||||
#include <gtk/gtkdebug.h>
|
||||
#include <gtk/gtkdialog.h>
|
||||
#include <gtk/gtkdnd.h>
|
||||
@@ -98,6 +101,7 @@
|
||||
#include <gtk/gtkeventcontrollerscroll.h>
|
||||
#include <gtk/gtkexpander.h>
|
||||
#include <gtk/gtkfixed.h>
|
||||
#include <gtk/gtkfixedlayout.h>
|
||||
#include <gtk/gtkfilechooser.h>
|
||||
#include <gtk/gtkfilechooserbutton.h>
|
||||
#include <gtk/gtkfilechooserdialog.h>
|
||||
@@ -134,6 +138,8 @@
|
||||
#include <gtk/gtkinfobar.h>
|
||||
#include <gtk/gtklabel.h>
|
||||
#include <gtk/gtklayout.h>
|
||||
#include <gtk/gtklayoutmanager.h>
|
||||
#include <gtk/gtklayoutchild.h>
|
||||
#include <gtk/gtklevelbar.h>
|
||||
#include <gtk/gtklinkbutton.h>
|
||||
#include <gtk/gtklistbox.h>
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "gtksettings.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
#include "gdk/gdkconstructor.h"
|
||||
|
||||
G_DEFINE_TYPE (GtkApplicationImplDBus, gtk_application_impl_dbus, GTK_TYPE_APPLICATION_IMPL)
|
||||
|
||||
#define DBUS_BUS_NAME "org.freedesktop.DBus"
|
||||
|
||||
+4
-3
@@ -74,14 +74,15 @@
|
||||
#include "gtkintl.h"
|
||||
#include "gtkimage.h"
|
||||
#include "gtklabel.h"
|
||||
#include "gtkstack.h"
|
||||
#include "gtklistlistmodelprivate.h"
|
||||
#include "gtkmaplistmodel.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtksettings.h"
|
||||
#include "gtksizegroup.h"
|
||||
#include "gtksizerequest.h"
|
||||
#include "gtkstack.h"
|
||||
#include "gtkstylecontext.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
#include "gtklistlistmodelprivate.h"
|
||||
#include "gtkmaplistmodel.h"
|
||||
|
||||
#include "a11y/gtkwindowaccessible.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/* gtkbinlayout.c: Layout manager for bin-like widgets
|
||||
* Copyright 2019 GNOME Foundation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:gtkbinlayout
|
||||
* @Title: GtkBinLayout
|
||||
* @Short_description: A layout manager for bin-like widgets
|
||||
* @Include: gtk/gtk.h
|
||||
*
|
||||
* GtkBinLayout is a #GtkLayoutManager subclass useful for create "bins" of
|
||||
* widgets. GtkBinLayout will stack each child of a widget on top of each
|
||||
* other, using the #GtkWidget:hexpand, #GtkWidget:vexpand, #GtkWidget:halign,
|
||||
* and #GtkWidget:valign properties of each child to determine where they
|
||||
* should be positioned.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkbinlayout.h"
|
||||
|
||||
#include "gtkwidgetprivate.h"
|
||||
|
||||
struct _GtkBinLayout
|
||||
{
|
||||
GtkLayoutManager parent_instance;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkBinLayout, gtk_bin_layout, GTK_TYPE_LAYOUT_MANAGER)
|
||||
|
||||
static void
|
||||
gtk_bin_layout_measure (GtkLayoutManager *layout_manager,
|
||||
GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
GtkWidget *child;
|
||||
|
||||
for (child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
if (gtk_widget_get_visible (child))
|
||||
{
|
||||
int child_min = 0;
|
||||
int child_nat = 0;
|
||||
int child_min_baseline = -1;
|
||||
int child_nat_baseline = -1;
|
||||
|
||||
gtk_widget_measure (child, orientation, for_size,
|
||||
&child_min, &child_nat,
|
||||
&child_min_baseline, &child_nat_baseline);
|
||||
|
||||
*minimum = MAX (*minimum, child_min);
|
||||
*natural = MAX (*natural, child_nat);
|
||||
|
||||
if (child_min_baseline > -1)
|
||||
*minimum_baseline = MAX (*minimum_baseline, child_min_baseline);
|
||||
if (child_nat_baseline > -1)
|
||||
*natural_baseline = MAX (*natural_baseline, child_nat_baseline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_bin_layout_allocate (GtkLayoutManager *layout_manager,
|
||||
GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkWidget *child;
|
||||
|
||||
for (child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
if (child && gtk_widget_get_visible (child))
|
||||
gtk_widget_allocate (child, width, height, baseline, NULL);
|
||||
}
|
||||
}
|
||||
static void
|
||||
gtk_bin_layout_class_init (GtkBinLayoutClass *klass)
|
||||
{
|
||||
GtkLayoutManagerClass *layout_manager_class = GTK_LAYOUT_MANAGER_CLASS (klass);
|
||||
|
||||
layout_manager_class->measure = gtk_bin_layout_measure;
|
||||
layout_manager_class->allocate = gtk_bin_layout_allocate;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_bin_layout_init (GtkBinLayout *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_bin_layout_new:
|
||||
*
|
||||
* Creates a new #GtkBinLayout instance.
|
||||
*
|
||||
* Returns: the newly created #GtkBinLayout
|
||||
*/
|
||||
GtkLayoutManager *
|
||||
gtk_bin_layout_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_BIN_LAYOUT, NULL);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2012 Red Hat Inc.
|
||||
/* gtkbinlayout.h: Layout manager for bin-like widgets
|
||||
* Copyright 2019 GNOME Foundation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -13,20 +13,19 @@
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Alexander Larsson <alexl@gnome.org>
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef __GTK_CSS_WIN32_SIZE_VALUE_PRIVATE_H__
|
||||
#define __GTK_CSS_WIN32_SIZE_VALUE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssnumbervalueprivate.h"
|
||||
#include <gtk/gtklayoutmanager.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GtkCssValue * gtk_css_win32_size_value_parse (GtkCssParser *parser,
|
||||
GtkCssNumberParseFlags flags);
|
||||
#define GTK_TYPE_BIN_LAYOUT (gtk_bin_layout_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkBinLayout, gtk_bin_layout, GTK, BIN_LAYOUT, GtkLayoutManager)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkLayoutManager * gtk_bin_layout_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_WIN32_SIZE_VALUE_PRIVATE_H__ */
|
||||
+45
-578
@@ -57,6 +57,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkbox.h"
|
||||
#include "gtkboxlayout.h"
|
||||
#include "gtkcsspositionvalueprivate.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkorientable.h"
|
||||
@@ -92,11 +93,6 @@ typedef struct
|
||||
|
||||
static GParamSpec *props[LAST_PROP] = { NULL, };
|
||||
|
||||
static void gtk_box_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline);
|
||||
|
||||
static void gtk_box_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
@@ -116,13 +112,6 @@ static GType gtk_box_child_type (GtkContainer *container);
|
||||
static GtkWidgetPath * gtk_box_get_path_for_child
|
||||
(GtkContainer *container,
|
||||
GtkWidget *child);
|
||||
static void gtk_box_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkBox, gtk_box, GTK_TYPE_CONTAINER,
|
||||
G_ADD_PRIVATE (GtkBox)
|
||||
@@ -138,9 +127,6 @@ gtk_box_class_init (GtkBoxClass *class)
|
||||
object_class->set_property = gtk_box_set_property;
|
||||
object_class->get_property = gtk_box_get_property;
|
||||
|
||||
widget_class->size_allocate = gtk_box_size_allocate;
|
||||
widget_class->measure = gtk_box_measure;
|
||||
|
||||
container_class->add = gtk_box_add;
|
||||
container_class->remove = gtk_box_remove;
|
||||
container_class->forall = gtk_box_forall;
|
||||
@@ -187,6 +173,7 @@ gtk_box_set_property (GObject *object,
|
||||
{
|
||||
GtkBox *box = GTK_BOX (object);
|
||||
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
|
||||
GtkLayoutManager *box_layout = gtk_widget_get_layout_manager (GTK_WIDGET (box));
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
@@ -196,8 +183,9 @@ gtk_box_set_property (GObject *object,
|
||||
if (priv->orientation != orientation)
|
||||
{
|
||||
priv->orientation = orientation;
|
||||
gtk_orientable_set_orientation (GTK_ORIENTABLE (box_layout),
|
||||
priv->orientation);
|
||||
_gtk_orientable_set_style_classes (GTK_ORIENTABLE (box));
|
||||
gtk_widget_queue_resize (GTK_WIDGET (box));
|
||||
g_object_notify (object, "orientation");
|
||||
}
|
||||
}
|
||||
@@ -225,6 +213,7 @@ gtk_box_get_property (GObject *object,
|
||||
{
|
||||
GtkBox *box = GTK_BOX (object);
|
||||
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
|
||||
GtkBoxLayout *box_layout = GTK_BOX_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (box)));
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
@@ -232,13 +221,13 @@ gtk_box_get_property (GObject *object,
|
||||
g_value_set_enum (value, priv->orientation);
|
||||
break;
|
||||
case PROP_SPACING:
|
||||
g_value_set_int (value, priv->spacing);
|
||||
g_value_set_int (value, gtk_box_layout_get_spacing (box_layout));
|
||||
break;
|
||||
case PROP_BASELINE_POSITION:
|
||||
g_value_set_enum (value, priv->baseline_pos);
|
||||
g_value_set_enum (value, gtk_box_layout_get_baseline_position (box_layout));
|
||||
break;
|
||||
case PROP_HOMOGENEOUS:
|
||||
g_value_set_boolean (value, priv->homogeneous);
|
||||
g_value_set_boolean (value, gtk_box_layout_get_homogeneous (box_layout));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
@@ -246,285 +235,6 @@ gtk_box_get_property (GObject *object,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
count_expand_children (GtkBox *box,
|
||||
gint *visible_children,
|
||||
gint *expand_children)
|
||||
{
|
||||
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
|
||||
GtkWidget *child;
|
||||
|
||||
*visible_children = *expand_children = 0;
|
||||
|
||||
for (child = _gtk_widget_get_first_child (GTK_WIDGET (box));
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
if (_gtk_widget_get_visible (child))
|
||||
{
|
||||
*visible_children += 1;
|
||||
|
||||
if (gtk_widget_compute_expand (child, priv->orientation))
|
||||
*expand_children += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
get_spacing (GtkBox *box)
|
||||
{
|
||||
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
|
||||
GtkCssValue *border_spacing;
|
||||
gint css_spacing;
|
||||
|
||||
border_spacing = _gtk_style_context_peek_property (gtk_widget_get_style_context (GTK_WIDGET (box)), GTK_CSS_PROPERTY_BORDER_SPACING);
|
||||
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
css_spacing = _gtk_css_position_value_get_x (border_spacing, 100);
|
||||
else
|
||||
css_spacing = _gtk_css_position_value_get_y (border_spacing, 100);
|
||||
|
||||
return css_spacing + priv->spacing;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_box_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkBox *box = GTK_BOX (widget);
|
||||
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
|
||||
GtkWidget *child;
|
||||
gint nvis_children;
|
||||
gint nexpand_children;
|
||||
GtkTextDirection direction;
|
||||
GtkAllocation child_allocation;
|
||||
GtkRequestedSize *sizes;
|
||||
gint child_minimum_baseline, child_natural_baseline;
|
||||
gint minimum_above, natural_above;
|
||||
gint minimum_below, natural_below;
|
||||
gboolean have_baseline;
|
||||
gint extra_space;
|
||||
gint children_minimum_size = 0;
|
||||
gint size_given_to_child;
|
||||
gint n_extra_widgets = 0; /* Number of widgets that receive 1 extra px */
|
||||
gint x = 0, y = 0, i;
|
||||
gint child_size;
|
||||
gint spacing;
|
||||
|
||||
|
||||
count_expand_children (box, &nvis_children, &nexpand_children);
|
||||
|
||||
/* If there is no visible child, simply return. */
|
||||
if (nvis_children <= 0)
|
||||
return;
|
||||
|
||||
direction = _gtk_widget_get_direction (widget);
|
||||
sizes = g_newa (GtkRequestedSize, nvis_children);
|
||||
spacing = get_spacing (box);
|
||||
|
||||
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
extra_space = width - (nvis_children - 1) * spacing;
|
||||
else
|
||||
extra_space = height - (nvis_children - 1) * spacing;
|
||||
|
||||
have_baseline = FALSE;
|
||||
minimum_above = natural_above = 0;
|
||||
minimum_below = natural_below = 0;
|
||||
|
||||
/* Retrieve desired size for visible children. */
|
||||
for (i = 0, child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
if (!_gtk_widget_get_visible (child))
|
||||
continue;
|
||||
|
||||
gtk_widget_measure (child,
|
||||
priv->orientation,
|
||||
priv->orientation == GTK_ORIENTATION_HORIZONTAL ? height : width,
|
||||
&sizes[i].minimum_size, &sizes[i].natural_size,
|
||||
NULL, NULL);
|
||||
|
||||
children_minimum_size += sizes[i].minimum_size;
|
||||
|
||||
sizes[i].data = child;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (priv->homogeneous)
|
||||
{
|
||||
/* We still need to run the above loop to populate the minimum sizes for
|
||||
* children that aren't going to fill.
|
||||
*/
|
||||
|
||||
size_given_to_child = extra_space / nvis_children;
|
||||
n_extra_widgets = extra_space % nvis_children;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Bring children up to size first */
|
||||
extra_space -= children_minimum_size;
|
||||
extra_space = MAX (0, extra_space);
|
||||
extra_space = gtk_distribute_natural_allocation (extra_space, nvis_children, sizes);
|
||||
|
||||
/* Calculate space which hasn't distributed yet,
|
||||
* and is available for expanding children.
|
||||
*/
|
||||
if (nexpand_children > 0)
|
||||
{
|
||||
size_given_to_child = extra_space / nexpand_children;
|
||||
n_extra_widgets = extra_space % nexpand_children;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_given_to_child = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate child sizes. */
|
||||
for (i = 0, child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
/* If widget is not visible, skip it. */
|
||||
if (!_gtk_widget_get_visible (child))
|
||||
continue;
|
||||
|
||||
/* Assign the child's size. */
|
||||
if (priv->homogeneous)
|
||||
{
|
||||
child_size = size_given_to_child;
|
||||
|
||||
if (n_extra_widgets > 0)
|
||||
{
|
||||
child_size++;
|
||||
n_extra_widgets--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
child_size = sizes[i].minimum_size;
|
||||
|
||||
if (gtk_widget_compute_expand (child, priv->orientation))
|
||||
{
|
||||
child_size += size_given_to_child;
|
||||
|
||||
if (n_extra_widgets > 0)
|
||||
{
|
||||
child_size++;
|
||||
n_extra_widgets--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sizes[i].natural_size = child_size;
|
||||
|
||||
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL &&
|
||||
gtk_widget_get_valign (child) == GTK_ALIGN_BASELINE)
|
||||
{
|
||||
int child_allocation_width;
|
||||
int child_minimum_height, child_natural_height;
|
||||
|
||||
child_allocation_width = child_size;
|
||||
|
||||
child_minimum_baseline = -1;
|
||||
child_natural_baseline = -1;
|
||||
gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL,
|
||||
child_allocation_width,
|
||||
&child_minimum_height, &child_natural_height,
|
||||
&child_minimum_baseline, &child_natural_baseline);
|
||||
|
||||
if (child_minimum_baseline >= 0)
|
||||
{
|
||||
have_baseline = TRUE;
|
||||
minimum_below = MAX (minimum_below, child_minimum_height - child_minimum_baseline);
|
||||
natural_below = MAX (natural_below, child_natural_height - child_natural_baseline);
|
||||
minimum_above = MAX (minimum_above, child_minimum_baseline);
|
||||
natural_above = MAX (natural_above, child_natural_baseline);
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (priv->orientation == GTK_ORIENTATION_VERTICAL)
|
||||
baseline = -1;
|
||||
|
||||
/* we only calculate our own baseline if we don't get one passed from the parent
|
||||
* and any of the child widgets explicitly request one */
|
||||
if (baseline == -1 && have_baseline)
|
||||
{
|
||||
/* TODO: This is purely based on the minimum baseline, when things fit we should
|
||||
use the natural one? */
|
||||
|
||||
switch (priv->baseline_pos)
|
||||
{
|
||||
case GTK_BASELINE_POSITION_TOP:
|
||||
baseline = minimum_above;
|
||||
break;
|
||||
case GTK_BASELINE_POSITION_CENTER:
|
||||
baseline = minimum_above + (height - (minimum_above + minimum_below)) / 2;
|
||||
break;
|
||||
case GTK_BASELINE_POSITION_BOTTOM:
|
||||
baseline = height - minimum_below;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate child positions. */
|
||||
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
child_allocation.y = 0;
|
||||
child_allocation.height = height;
|
||||
x = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
child_allocation.x = 0;
|
||||
child_allocation.width = width;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
for (i = 0, child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
/* If widget is not visible, skip it. */
|
||||
if (!_gtk_widget_get_visible (child))
|
||||
continue;
|
||||
|
||||
child_size = sizes[i].natural_size;
|
||||
|
||||
/* Assign the child's position. */
|
||||
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
child_allocation.width = child_size;
|
||||
child_allocation.x = x;
|
||||
|
||||
x += child_size + spacing;
|
||||
|
||||
if (direction == GTK_TEXT_DIR_RTL)
|
||||
child_allocation.x = width - child_allocation.x - child_allocation.width;
|
||||
|
||||
}
|
||||
else /* (priv->orientation == GTK_ORIENTATION_VERTICAL) */
|
||||
{
|
||||
child_allocation.height = child_size;
|
||||
child_allocation.y = y;
|
||||
|
||||
y += child_size + spacing;
|
||||
}
|
||||
|
||||
gtk_widget_size_allocate (child, &child_allocation, baseline);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static GType
|
||||
gtk_box_child_type (GtkContainer *container)
|
||||
{
|
||||
@@ -630,263 +340,17 @@ gtk_box_get_path_for_child (GtkContainer *container,
|
||||
return path;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_box_compute_size_for_opposing_orientation (GtkBox *box,
|
||||
int for_size,
|
||||
gint *minimum_size,
|
||||
gint *natural_size,
|
||||
gint *minimum_baseline,
|
||||
gint *natural_baseline)
|
||||
{
|
||||
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
|
||||
GtkWidget *widget = GTK_WIDGET (box);
|
||||
GtkWidget *child;
|
||||
gint nvis_children;
|
||||
gint nexpand_children;
|
||||
gint computed_minimum = 0, computed_natural = 0;
|
||||
gint computed_minimum_above = 0, computed_natural_above = 0;
|
||||
gint computed_minimum_below = 0, computed_natural_below = 0;
|
||||
gint computed_minimum_baseline = -1, computed_natural_baseline = -1;
|
||||
GtkRequestedSize *sizes;
|
||||
gint extra_space, size_given_to_child, i;
|
||||
gint children_minimum_size = 0;
|
||||
gint child_size, child_minimum, child_natural;
|
||||
gint child_minimum_baseline, child_natural_baseline;
|
||||
gint n_extra_widgets = 0;
|
||||
gint spacing;
|
||||
gboolean have_baseline;
|
||||
|
||||
count_expand_children (box, &nvis_children, &nexpand_children);
|
||||
|
||||
if (nvis_children <= 0)
|
||||
return;
|
||||
|
||||
spacing = get_spacing (box);
|
||||
sizes = g_newa (GtkRequestedSize, nvis_children);
|
||||
extra_space = MAX (0, for_size - (nvis_children - 1) * spacing);
|
||||
|
||||
/* Retrieve desired size for visible children */
|
||||
for (i = 0, child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
if (_gtk_widget_get_visible (child))
|
||||
{
|
||||
gtk_widget_measure (child,
|
||||
priv->orientation,
|
||||
-1,
|
||||
&sizes[i].minimum_size, &sizes[i].natural_size,
|
||||
NULL, NULL);
|
||||
|
||||
children_minimum_size += sizes[i].minimum_size;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->homogeneous)
|
||||
{
|
||||
/* We still need to run the above loop to populate the minimum sizes for
|
||||
* children that aren't going to fill.
|
||||
*/
|
||||
|
||||
size_given_to_child = extra_space / nvis_children;
|
||||
n_extra_widgets = extra_space % nvis_children;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Bring children up to size first */
|
||||
extra_space -= children_minimum_size;
|
||||
extra_space = MAX (0, extra_space);
|
||||
extra_space = gtk_distribute_natural_allocation (extra_space, nvis_children, sizes);
|
||||
|
||||
/* Calculate space which hasn't distributed yet,
|
||||
* and is available for expanding children.
|
||||
*/
|
||||
if (nexpand_children > 0)
|
||||
{
|
||||
size_given_to_child = extra_space / nexpand_children;
|
||||
n_extra_widgets = extra_space % nexpand_children;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_given_to_child = 0;
|
||||
}
|
||||
}
|
||||
|
||||
have_baseline = FALSE;
|
||||
for (i = 0, child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
/* If widget is not visible, skip it. */
|
||||
if (!_gtk_widget_get_visible (child))
|
||||
continue;
|
||||
|
||||
/* Assign the child's size. */
|
||||
if (priv->homogeneous)
|
||||
{
|
||||
child_size = size_given_to_child;
|
||||
|
||||
if (n_extra_widgets > 0)
|
||||
{
|
||||
child_size++;
|
||||
n_extra_widgets--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
child_size = sizes[i].minimum_size;
|
||||
|
||||
if (gtk_widget_compute_expand (child, priv->orientation))
|
||||
{
|
||||
child_size += size_given_to_child;
|
||||
|
||||
if (n_extra_widgets > 0)
|
||||
{
|
||||
child_size++;
|
||||
n_extra_widgets--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
child_minimum_baseline = child_natural_baseline = -1;
|
||||
/* Assign the child's position. */
|
||||
gtk_widget_measure (child,
|
||||
OPPOSITE_ORIENTATION (priv->orientation),
|
||||
child_size,
|
||||
&child_minimum, &child_natural,
|
||||
&child_minimum_baseline, &child_natural_baseline);
|
||||
|
||||
if (child_minimum_baseline >= 0)
|
||||
{
|
||||
have_baseline = TRUE;
|
||||
computed_minimum_below = MAX (computed_minimum_below, child_minimum - child_minimum_baseline);
|
||||
computed_natural_below = MAX (computed_natural_below, child_natural - child_natural_baseline);
|
||||
computed_minimum_above = MAX (computed_minimum_above, child_minimum_baseline);
|
||||
computed_natural_above = MAX (computed_natural_above, child_natural_baseline);
|
||||
}
|
||||
else
|
||||
{
|
||||
computed_minimum = MAX (computed_minimum, child_minimum);
|
||||
computed_natural = MAX (computed_natural, child_natural);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if (have_baseline)
|
||||
{
|
||||
computed_minimum = MAX (computed_minimum, computed_minimum_below + computed_minimum_above);
|
||||
computed_natural = MAX (computed_natural, computed_natural_below + computed_natural_above);
|
||||
switch (priv->baseline_pos)
|
||||
{
|
||||
case GTK_BASELINE_POSITION_TOP:
|
||||
computed_minimum_baseline = computed_minimum_above;
|
||||
computed_natural_baseline = computed_natural_above;
|
||||
break;
|
||||
case GTK_BASELINE_POSITION_CENTER:
|
||||
computed_minimum_baseline = computed_minimum_above + MAX((computed_minimum - (computed_minimum_above + computed_minimum_below)) / 2, 0);
|
||||
computed_natural_baseline = computed_natural_above + MAX((computed_natural - (computed_natural_above + computed_natural_below)) / 2, 0);
|
||||
break;
|
||||
case GTK_BASELINE_POSITION_BOTTOM:
|
||||
computed_minimum_baseline = computed_minimum - computed_minimum_below;
|
||||
computed_natural_baseline = computed_natural - computed_natural_below;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*minimum_size = computed_minimum;
|
||||
*natural_size = MAX (computed_natural, computed_natural_below + computed_natural_above);
|
||||
|
||||
*minimum_baseline = computed_minimum_baseline;
|
||||
*natural_baseline = computed_natural_baseline;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_box_compute_size_for_orientation (GtkBox *box,
|
||||
int for_size,
|
||||
int *minimum_size,
|
||||
int *natural_size)
|
||||
{
|
||||
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
|
||||
GtkWidget *child;
|
||||
const int spacing = get_spacing (box);
|
||||
int nvis_children = 0;
|
||||
int required_size = 0, required_natural = 0;
|
||||
int largest_child = 0, largest_natural = 0;
|
||||
|
||||
for (child = _gtk_widget_get_first_child (GTK_WIDGET (box));
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
if (_gtk_widget_get_visible (child))
|
||||
{
|
||||
int child_size, child_natural;
|
||||
|
||||
gtk_widget_measure (child,
|
||||
priv->orientation,
|
||||
for_size,
|
||||
&child_size, &child_natural,
|
||||
NULL, NULL);
|
||||
|
||||
largest_child = MAX (largest_child, child_size);
|
||||
largest_natural = MAX (largest_natural, child_natural);
|
||||
|
||||
required_size += child_size;
|
||||
required_natural += child_natural;
|
||||
|
||||
nvis_children += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (nvis_children > 0)
|
||||
{
|
||||
if (priv->homogeneous)
|
||||
{
|
||||
required_size = largest_child * nvis_children;
|
||||
required_natural = largest_natural * nvis_children;
|
||||
}
|
||||
|
||||
required_size += (nvis_children - 1) * spacing;
|
||||
required_natural += (nvis_children - 1) * spacing;
|
||||
}
|
||||
|
||||
*minimum_size = required_size;
|
||||
*natural_size = required_natural;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gtk_box_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
GtkBox *box = GTK_BOX (widget);
|
||||
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
|
||||
|
||||
if (priv->orientation != orientation)
|
||||
gtk_box_compute_size_for_opposing_orientation (box, for_size, minimum, natural, minimum_baseline, natural_baseline);
|
||||
else
|
||||
gtk_box_compute_size_for_orientation (box, for_size, minimum, natural);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_box_init (GtkBox *box)
|
||||
{
|
||||
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
|
||||
GtkLayoutManager *box_layout = gtk_box_layout_new (GTK_ORIENTATION_HORIZONTAL);
|
||||
|
||||
gtk_widget_set_has_surface (GTK_WIDGET (box), FALSE);
|
||||
|
||||
priv->orientation = GTK_ORIENTATION_HORIZONTAL;
|
||||
priv->homogeneous = FALSE;
|
||||
priv->spacing = 0;
|
||||
priv->baseline_pos = GTK_BASELINE_POSITION_CENTER;
|
||||
gtk_widget_set_layout_manager (GTK_WIDGET (box), box_layout);
|
||||
|
||||
priv->orientation = GTK_ORIENTATION_HORIZONTAL;
|
||||
_gtk_orientable_set_style_classes (GTK_ORIENTABLE (box));
|
||||
}
|
||||
|
||||
@@ -905,7 +369,7 @@ gtk_box_new (GtkOrientation orientation,
|
||||
{
|
||||
return g_object_new (GTK_TYPE_BOX,
|
||||
"orientation", orientation,
|
||||
"spacing", spacing,
|
||||
"spacing", spacing,
|
||||
NULL);
|
||||
}
|
||||
|
||||
@@ -923,18 +387,18 @@ void
|
||||
gtk_box_set_homogeneous (GtkBox *box,
|
||||
gboolean homogeneous)
|
||||
{
|
||||
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
|
||||
GtkBoxLayout *box_layout;
|
||||
|
||||
g_return_if_fail (GTK_IS_BOX (box));
|
||||
|
||||
homogeneous = homogeneous != FALSE;
|
||||
homogeneous = !!homogeneous;
|
||||
|
||||
if (priv->homogeneous != homogeneous)
|
||||
{
|
||||
priv->homogeneous = homogeneous;
|
||||
g_object_notify_by_pspec (G_OBJECT (box), props[PROP_HOMOGENEOUS]);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (box));
|
||||
}
|
||||
box_layout = GTK_BOX_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (box)));
|
||||
if (homogeneous == gtk_box_layout_get_homogeneous (box_layout))
|
||||
return;
|
||||
|
||||
gtk_box_layout_set_homogeneous (box_layout, homogeneous);
|
||||
g_object_notify_by_pspec (G_OBJECT (box), props[PROP_HOMOGENEOUS]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -949,11 +413,13 @@ gtk_box_set_homogeneous (GtkBox *box,
|
||||
gboolean
|
||||
gtk_box_get_homogeneous (GtkBox *box)
|
||||
{
|
||||
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
|
||||
GtkLayoutManager *box_layout;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_BOX (box), FALSE);
|
||||
|
||||
return priv->homogeneous;
|
||||
box_layout = gtk_widget_get_layout_manager (GTK_WIDGET (box));
|
||||
|
||||
return gtk_box_layout_get_homogeneous (GTK_BOX_LAYOUT (box_layout));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -968,18 +434,16 @@ void
|
||||
gtk_box_set_spacing (GtkBox *box,
|
||||
gint spacing)
|
||||
{
|
||||
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
|
||||
GtkBoxLayout *box_layout;
|
||||
|
||||
g_return_if_fail (GTK_IS_BOX (box));
|
||||
|
||||
if (priv->spacing != spacing)
|
||||
{
|
||||
priv->spacing = spacing;
|
||||
box_layout = GTK_BOX_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (box)));
|
||||
if (spacing == gtk_box_layout_get_spacing (box_layout))
|
||||
return;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (box), props[PROP_SPACING]);
|
||||
|
||||
gtk_widget_queue_resize (GTK_WIDGET (box));
|
||||
}
|
||||
gtk_box_layout_set_spacing (box_layout, spacing);
|
||||
g_object_notify_by_pspec (G_OBJECT (box), props[PROP_SPACING]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -993,10 +457,13 @@ gtk_box_set_spacing (GtkBox *box,
|
||||
gint
|
||||
gtk_box_get_spacing (GtkBox *box)
|
||||
{
|
||||
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
|
||||
GtkLayoutManager *box_layout;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_BOX (box), 0);
|
||||
|
||||
return priv->spacing;
|
||||
box_layout = gtk_widget_get_layout_manager (GTK_WIDGET (box));
|
||||
|
||||
return gtk_box_layout_get_spacing (GTK_BOX_LAYOUT (box_layout));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1015,18 +482,16 @@ void
|
||||
gtk_box_set_baseline_position (GtkBox *box,
|
||||
GtkBaselinePosition position)
|
||||
{
|
||||
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
|
||||
GtkBoxLayout *box_layout;
|
||||
|
||||
g_return_if_fail (GTK_IS_BOX (box));
|
||||
|
||||
if (priv->baseline_pos != position)
|
||||
{
|
||||
priv->baseline_pos = position;
|
||||
box_layout = GTK_BOX_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (box)));
|
||||
if (position == gtk_box_layout_get_baseline_position (box_layout))
|
||||
return;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (box), props[PROP_BASELINE_POSITION]);
|
||||
|
||||
gtk_widget_queue_resize (GTK_WIDGET (box));
|
||||
}
|
||||
gtk_box_layout_set_baseline_position (box_layout, position);
|
||||
g_object_notify_by_pspec (G_OBJECT (box), props[PROP_BASELINE_POSITION]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1040,11 +505,13 @@ gtk_box_set_baseline_position (GtkBox *box,
|
||||
GtkBaselinePosition
|
||||
gtk_box_get_baseline_position (GtkBox *box)
|
||||
{
|
||||
GtkBoxPrivate *priv = gtk_box_get_instance_private (box);
|
||||
GtkLayoutManager *box_layout;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_BOX (box), GTK_BASELINE_POSITION_CENTER);
|
||||
|
||||
return priv->baseline_pos;
|
||||
box_layout = gtk_widget_get_layout_manager (GTK_WIDGET (box));
|
||||
|
||||
return gtk_box_layout_get_baseline_position (GTK_BOX_LAYOUT (box_layout));
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -0,0 +1,877 @@
|
||||
/* gtkboxlayout.c: Box layout manager
|
||||
*
|
||||
* Copyright 2019 GNOME Foundation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkboxlayout.h"
|
||||
|
||||
#include "gtkcsspositionvalueprivate.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkorientableprivate.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtksizerequest.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
|
||||
/**
|
||||
* SECTION:gtkboxlayout
|
||||
* @Title: GtkBoxLayout
|
||||
* @Short_description: Layout manager for placing all children in a single row or column
|
||||
*
|
||||
* A GtkBoxLayout is a layout manager that arranges the children of any
|
||||
* widget using it into a single row or column, depending on the value
|
||||
* of its #GtkOrientable:orientation property. Within the other dimension
|
||||
* all children all allocated the same size. The GtkBoxLayout will respect
|
||||
* the #GtkWidget:halign and #GtkWidget:valign properties of each child
|
||||
* widget.
|
||||
*
|
||||
* If you want all children to be assigned the same size, you can use
|
||||
* the #GtkBoxLayout:homogeneous property.
|
||||
*
|
||||
* If you want to specify the amount of space placed between each child,
|
||||
* you can use the #GtkBoxLayout:spacing property.
|
||||
*/
|
||||
|
||||
struct _GtkBoxLayout
|
||||
{
|
||||
GtkLayoutManager parent_instance;
|
||||
|
||||
gboolean homogeneous;
|
||||
guint spacing;
|
||||
GtkOrientation orientation;
|
||||
GtkBaselinePosition baseline_position;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkBoxLayout, gtk_box_layout, GTK_TYPE_LAYOUT_MANAGER,
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL))
|
||||
|
||||
enum {
|
||||
PROP_HOMOGENEOUS = 1,
|
||||
PROP_SPACING,
|
||||
PROP_BASELINE_POSITION,
|
||||
|
||||
/* From GtkOrientable */
|
||||
PROP_ORIENTATION,
|
||||
|
||||
N_PROPS = PROP_ORIENTATION
|
||||
};
|
||||
|
||||
static GParamSpec *box_layout_props[N_PROPS];
|
||||
|
||||
static void
|
||||
gtk_box_layout_set_orientation (GtkBoxLayout *self,
|
||||
GtkOrientation orientation)
|
||||
{
|
||||
GtkLayoutManager *layout_manager = GTK_LAYOUT_MANAGER (self);
|
||||
GtkWidget *widget;
|
||||
|
||||
if (self->orientation == orientation)
|
||||
return;
|
||||
|
||||
self->orientation = orientation;
|
||||
|
||||
widget = gtk_layout_manager_get_widget (layout_manager);
|
||||
if (widget != NULL && GTK_IS_ORIENTABLE (widget))
|
||||
_gtk_orientable_set_style_classes (GTK_ORIENTABLE (widget));
|
||||
|
||||
gtk_layout_manager_layout_changed (layout_manager);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_box_layout_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkBoxLayout *self = GTK_BOX_LAYOUT (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_HOMOGENEOUS:
|
||||
gtk_box_layout_set_homogeneous (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_SPACING:
|
||||
gtk_box_layout_set_spacing (self, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
case PROP_BASELINE_POSITION:
|
||||
gtk_box_layout_set_baseline_position (self, g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
case PROP_ORIENTATION:
|
||||
gtk_box_layout_set_orientation (self, g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_box_layout_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkBoxLayout *box_layout = GTK_BOX_LAYOUT (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_HOMOGENEOUS:
|
||||
g_value_set_boolean (value, box_layout->homogeneous);
|
||||
break;
|
||||
|
||||
case PROP_SPACING:
|
||||
g_value_set_int (value, box_layout->spacing);
|
||||
break;
|
||||
|
||||
case PROP_BASELINE_POSITION:
|
||||
g_value_set_enum (value, box_layout->baseline_position);
|
||||
break;
|
||||
|
||||
case PROP_ORIENTATION:
|
||||
g_value_set_enum (value, box_layout->orientation);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
count_expand_children (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
gint *visible_children,
|
||||
gint *expand_children)
|
||||
{
|
||||
GtkWidget *child;
|
||||
|
||||
*visible_children = *expand_children = 0;
|
||||
|
||||
for (child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
if (_gtk_widget_get_visible (child))
|
||||
{
|
||||
*visible_children += 1;
|
||||
|
||||
if (gtk_widget_compute_expand (child, orientation))
|
||||
*expand_children += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
get_spacing (GtkBoxLayout *self,
|
||||
GtkStyleContext *style_context)
|
||||
{
|
||||
GtkCssValue *border_spacing;
|
||||
gint css_spacing;
|
||||
|
||||
border_spacing = _gtk_style_context_peek_property (style_context, GTK_CSS_PROPERTY_BORDER_SPACING);
|
||||
if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
css_spacing = _gtk_css_position_value_get_x (border_spacing, 100);
|
||||
else
|
||||
css_spacing = _gtk_css_position_value_get_y (border_spacing, 100);
|
||||
|
||||
return css_spacing + self->spacing;
|
||||
}
|
||||
|
||||
static GtkSizeRequestMode
|
||||
gtk_box_layout_get_request_mode (GtkLayoutManager *layout_manager,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkBoxLayout *self = GTK_BOX_LAYOUT (layout_manager);
|
||||
|
||||
return self->orientation == GTK_ORIENTATION_HORIZONTAL
|
||||
? GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT
|
||||
: GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_box_layout_compute_size (GtkBoxLayout *self,
|
||||
GtkWidget *widget,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural)
|
||||
{
|
||||
GtkWidget *child;
|
||||
int n_visible_children = 0;
|
||||
int required_min = 0, required_nat = 0;
|
||||
int largest_min = 0, largest_nat = 0;
|
||||
int spacing = get_spacing (self, _gtk_widget_get_style_context (widget));
|
||||
|
||||
for (child = gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
int child_min = 0;
|
||||
int child_nat = 0;
|
||||
|
||||
if (!_gtk_widget_get_visible (child))
|
||||
continue;
|
||||
|
||||
gtk_widget_measure (child, self->orientation,
|
||||
for_size,
|
||||
&child_min, &child_nat,
|
||||
NULL, NULL);
|
||||
|
||||
largest_min = MAX (largest_min, child_min);
|
||||
largest_nat = MAX (largest_nat, child_nat);
|
||||
|
||||
required_min += child_min;
|
||||
required_nat += child_nat;
|
||||
|
||||
n_visible_children += 1;
|
||||
}
|
||||
|
||||
if (n_visible_children > 0)
|
||||
{
|
||||
if (self->homogeneous)
|
||||
{
|
||||
required_min = largest_min * n_visible_children;
|
||||
required_nat = largest_nat * n_visible_children;
|
||||
}
|
||||
|
||||
required_min += (n_visible_children - 1) * spacing;
|
||||
required_nat += (n_visible_children - 1) * spacing;
|
||||
}
|
||||
|
||||
if (minimum != NULL)
|
||||
*minimum = required_min;
|
||||
if (natural != NULL)
|
||||
*natural = required_nat;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_box_layout_compute_opposite_size (GtkBoxLayout *self,
|
||||
GtkWidget *widget,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *min_baseline,
|
||||
int *nat_baseline)
|
||||
{
|
||||
GtkWidget *child;
|
||||
int nvis_children;
|
||||
int nexpand_children;
|
||||
int computed_minimum = 0, computed_natural = 0;
|
||||
int computed_minimum_above = 0, computed_natural_above = 0;
|
||||
int computed_minimum_below = 0, computed_natural_below = 0;
|
||||
int computed_minimum_baseline = -1, computed_natural_baseline = -1;
|
||||
GtkRequestedSize *sizes;
|
||||
int extra_space, size_given_to_child, i;
|
||||
int children_minimum_size = 0;
|
||||
int child_size, child_minimum, child_natural;
|
||||
int child_minimum_baseline, child_natural_baseline;
|
||||
int n_extra_widgets = 0;
|
||||
int spacing;
|
||||
gboolean have_baseline;
|
||||
|
||||
count_expand_children (widget, self->orientation, &nvis_children, &nexpand_children);
|
||||
|
||||
if (nvis_children <= 0)
|
||||
return;
|
||||
|
||||
spacing = get_spacing (self, _gtk_widget_get_style_context (widget));
|
||||
sizes = g_newa (GtkRequestedSize, nvis_children);
|
||||
extra_space = MAX (0, for_size - (nvis_children - 1) * spacing);
|
||||
|
||||
/* Retrieve desired size for visible children */
|
||||
for (i = 0, child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
if (_gtk_widget_get_visible (child))
|
||||
{
|
||||
gtk_widget_measure (child,
|
||||
self->orientation,
|
||||
-1,
|
||||
&sizes[i].minimum_size, &sizes[i].natural_size,
|
||||
NULL, NULL);
|
||||
|
||||
children_minimum_size += sizes[i].minimum_size;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->homogeneous)
|
||||
{
|
||||
/* We still need to run the above loop to populate the minimum sizes for
|
||||
* children that aren't going to fill.
|
||||
*/
|
||||
|
||||
size_given_to_child = extra_space / nvis_children;
|
||||
n_extra_widgets = extra_space % nvis_children;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Bring children up to size first */
|
||||
extra_space -= children_minimum_size;
|
||||
extra_space = MAX (0, extra_space);
|
||||
extra_space = gtk_distribute_natural_allocation (extra_space, nvis_children, sizes);
|
||||
|
||||
/* Calculate space which hasn't distributed yet,
|
||||
* and is available for expanding children.
|
||||
*/
|
||||
if (nexpand_children > 0)
|
||||
{
|
||||
size_given_to_child = extra_space / nexpand_children;
|
||||
n_extra_widgets = extra_space % nexpand_children;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_given_to_child = 0;
|
||||
}
|
||||
}
|
||||
|
||||
have_baseline = FALSE;
|
||||
for (i = 0, child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
/* If widget is not visible, skip it. */
|
||||
if (!_gtk_widget_get_visible (child))
|
||||
continue;
|
||||
|
||||
/* Assign the child's size. */
|
||||
if (self->homogeneous)
|
||||
{
|
||||
child_size = size_given_to_child;
|
||||
|
||||
if (n_extra_widgets > 0)
|
||||
{
|
||||
child_size++;
|
||||
n_extra_widgets--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
child_size = sizes[i].minimum_size;
|
||||
|
||||
if (gtk_widget_compute_expand (child, self->orientation))
|
||||
{
|
||||
child_size += size_given_to_child;
|
||||
|
||||
if (n_extra_widgets > 0)
|
||||
{
|
||||
child_size++;
|
||||
n_extra_widgets--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
child_minimum_baseline = child_natural_baseline = -1;
|
||||
/* Assign the child's position. */
|
||||
gtk_widget_measure (child,
|
||||
OPPOSITE_ORIENTATION (self->orientation),
|
||||
child_size,
|
||||
&child_minimum, &child_natural,
|
||||
&child_minimum_baseline, &child_natural_baseline);
|
||||
|
||||
if (child_minimum_baseline >= 0)
|
||||
{
|
||||
have_baseline = TRUE;
|
||||
computed_minimum_below = MAX (computed_minimum_below, child_minimum - child_minimum_baseline);
|
||||
computed_natural_below = MAX (computed_natural_below, child_natural - child_natural_baseline);
|
||||
computed_minimum_above = MAX (computed_minimum_above, child_minimum_baseline);
|
||||
computed_natural_above = MAX (computed_natural_above, child_natural_baseline);
|
||||
}
|
||||
else
|
||||
{
|
||||
computed_minimum = MAX (computed_minimum, child_minimum);
|
||||
computed_natural = MAX (computed_natural, child_natural);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if (have_baseline)
|
||||
{
|
||||
computed_minimum = MAX (computed_minimum, computed_minimum_below + computed_minimum_above);
|
||||
computed_natural = MAX (computed_natural, computed_natural_below + computed_natural_above);
|
||||
switch (self->baseline_position)
|
||||
{
|
||||
case GTK_BASELINE_POSITION_TOP:
|
||||
computed_minimum_baseline = computed_minimum_above;
|
||||
computed_natural_baseline = computed_natural_above;
|
||||
break;
|
||||
case GTK_BASELINE_POSITION_CENTER:
|
||||
computed_minimum_baseline = computed_minimum_above + MAX((computed_minimum - (computed_minimum_above + computed_minimum_below)) / 2, 0);
|
||||
computed_natural_baseline = computed_natural_above + MAX((computed_natural - (computed_natural_above + computed_natural_below)) / 2, 0);
|
||||
break;
|
||||
case GTK_BASELINE_POSITION_BOTTOM:
|
||||
computed_minimum_baseline = computed_minimum - computed_minimum_below;
|
||||
computed_natural_baseline = computed_natural - computed_natural_below;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (minimum != NULL)
|
||||
*minimum = computed_minimum;
|
||||
if (natural != NULL)
|
||||
*natural = MAX (computed_natural, computed_natural_below + computed_natural_above);
|
||||
|
||||
if (min_baseline != NULL)
|
||||
*min_baseline = computed_minimum_baseline;
|
||||
if (nat_baseline != NULL)
|
||||
*nat_baseline = computed_natural_baseline;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_box_layout_measure (GtkLayoutManager *layout_manager,
|
||||
GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *min_baseline,
|
||||
int *nat_baseline)
|
||||
{
|
||||
GtkBoxLayout *self = GTK_BOX_LAYOUT (layout_manager);
|
||||
|
||||
if (self->orientation != orientation)
|
||||
{
|
||||
gtk_box_layout_compute_opposite_size (self, widget, for_size,
|
||||
minimum, natural,
|
||||
min_baseline, nat_baseline);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_box_layout_compute_size (self, widget, for_size,
|
||||
minimum, natural);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_box_layout_allocate (GtkLayoutManager *layout_manager,
|
||||
GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkBoxLayout *self = GTK_BOX_LAYOUT (layout_manager);
|
||||
GtkWidget *child;
|
||||
gint nvis_children;
|
||||
gint nexpand_children;
|
||||
GtkTextDirection direction;
|
||||
GtkAllocation child_allocation;
|
||||
GtkRequestedSize *sizes;
|
||||
gint child_minimum_baseline, child_natural_baseline;
|
||||
gint minimum_above, natural_above;
|
||||
gint minimum_below, natural_below;
|
||||
gboolean have_baseline;
|
||||
gint extra_space;
|
||||
gint children_minimum_size = 0;
|
||||
gint size_given_to_child;
|
||||
gint n_extra_widgets = 0; /* Number of widgets that receive 1 extra px */
|
||||
gint x = 0, y = 0, i;
|
||||
gint child_size;
|
||||
gint spacing;
|
||||
|
||||
count_expand_children (widget, self->orientation, &nvis_children, &nexpand_children);
|
||||
|
||||
/* If there is no visible child, simply return. */
|
||||
if (nvis_children <= 0)
|
||||
return;
|
||||
|
||||
direction = _gtk_widget_get_direction (widget);
|
||||
sizes = g_newa (GtkRequestedSize, nvis_children);
|
||||
spacing = get_spacing (self, _gtk_widget_get_style_context (widget));
|
||||
|
||||
if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
extra_space = width - (nvis_children - 1) * spacing;
|
||||
else
|
||||
extra_space = height - (nvis_children - 1) * spacing;
|
||||
|
||||
have_baseline = FALSE;
|
||||
minimum_above = natural_above = 0;
|
||||
minimum_below = natural_below = 0;
|
||||
|
||||
/* Retrieve desired size for visible children. */
|
||||
for (i = 0, child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
if (!_gtk_widget_get_visible (child))
|
||||
continue;
|
||||
|
||||
gtk_widget_measure (child,
|
||||
self->orientation,
|
||||
self->orientation == GTK_ORIENTATION_HORIZONTAL ? height : width,
|
||||
&sizes[i].minimum_size, &sizes[i].natural_size,
|
||||
NULL, NULL);
|
||||
|
||||
children_minimum_size += sizes[i].minimum_size;
|
||||
|
||||
sizes[i].data = child;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (self->homogeneous)
|
||||
{
|
||||
/* We still need to run the above loop to populate the minimum sizes for
|
||||
* children that aren't going to fill.
|
||||
*/
|
||||
|
||||
size_given_to_child = extra_space / nvis_children;
|
||||
n_extra_widgets = extra_space % nvis_children;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Bring children up to size first */
|
||||
extra_space -= children_minimum_size;
|
||||
extra_space = MAX (0, extra_space);
|
||||
extra_space = gtk_distribute_natural_allocation (extra_space, nvis_children, sizes);
|
||||
|
||||
/* Calculate space which hasn't distributed yet,
|
||||
* and is available for expanding children.
|
||||
*/
|
||||
if (nexpand_children > 0)
|
||||
{
|
||||
size_given_to_child = extra_space / nexpand_children;
|
||||
n_extra_widgets = extra_space % nexpand_children;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_given_to_child = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate child sizes. */
|
||||
for (i = 0, child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
/* If widget is not visible, skip it. */
|
||||
if (!_gtk_widget_get_visible (child))
|
||||
continue;
|
||||
|
||||
/* Assign the child's size. */
|
||||
if (self->homogeneous)
|
||||
{
|
||||
child_size = size_given_to_child;
|
||||
|
||||
if (n_extra_widgets > 0)
|
||||
{
|
||||
child_size++;
|
||||
n_extra_widgets--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
child_size = sizes[i].minimum_size;
|
||||
|
||||
if (gtk_widget_compute_expand (child, self->orientation))
|
||||
{
|
||||
child_size += size_given_to_child;
|
||||
|
||||
if (n_extra_widgets > 0)
|
||||
{
|
||||
child_size++;
|
||||
n_extra_widgets--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sizes[i].natural_size = child_size;
|
||||
|
||||
if (self->orientation == GTK_ORIENTATION_HORIZONTAL &&
|
||||
gtk_widget_get_valign (child) == GTK_ALIGN_BASELINE)
|
||||
{
|
||||
int child_allocation_width;
|
||||
int child_minimum_height, child_natural_height;
|
||||
|
||||
child_allocation_width = child_size;
|
||||
|
||||
child_minimum_baseline = -1;
|
||||
child_natural_baseline = -1;
|
||||
gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL,
|
||||
child_allocation_width,
|
||||
&child_minimum_height, &child_natural_height,
|
||||
&child_minimum_baseline, &child_natural_baseline);
|
||||
|
||||
if (child_minimum_baseline >= 0)
|
||||
{
|
||||
have_baseline = TRUE;
|
||||
minimum_below = MAX (minimum_below, child_minimum_height - child_minimum_baseline);
|
||||
natural_below = MAX (natural_below, child_natural_height - child_natural_baseline);
|
||||
minimum_above = MAX (minimum_above, child_minimum_baseline);
|
||||
natural_above = MAX (natural_above, child_natural_baseline);
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (self->orientation == GTK_ORIENTATION_VERTICAL)
|
||||
baseline = -1;
|
||||
|
||||
/* we only calculate our own baseline if we don't get one passed from the parent
|
||||
* and any of the child widgets explicitly request one */
|
||||
if (baseline == -1 && have_baseline)
|
||||
{
|
||||
/* TODO: This is purely based on the minimum baseline, when things fit we should
|
||||
use the natural one? */
|
||||
|
||||
switch (self->baseline_position)
|
||||
{
|
||||
case GTK_BASELINE_POSITION_TOP:
|
||||
baseline = minimum_above;
|
||||
break;
|
||||
case GTK_BASELINE_POSITION_CENTER:
|
||||
baseline = minimum_above + (height - (minimum_above + minimum_below)) / 2;
|
||||
break;
|
||||
case GTK_BASELINE_POSITION_BOTTOM:
|
||||
baseline = height - minimum_below;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate child positions. */
|
||||
if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
child_allocation.y = 0;
|
||||
child_allocation.height = height;
|
||||
x = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
child_allocation.x = 0;
|
||||
child_allocation.width = width;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
for (i = 0, child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
/* If widget is not visible, skip it. */
|
||||
if (!_gtk_widget_get_visible (child))
|
||||
continue;
|
||||
|
||||
child_size = sizes[i].natural_size;
|
||||
|
||||
/* Assign the child's position. */
|
||||
if (self->orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
child_allocation.width = child_size;
|
||||
child_allocation.x = x;
|
||||
|
||||
x += child_size + spacing;
|
||||
|
||||
if (direction == GTK_TEXT_DIR_RTL)
|
||||
child_allocation.x = width - child_allocation.x - child_allocation.width;
|
||||
|
||||
}
|
||||
else /* (self->orientation == GTK_ORIENTATION_VERTICAL) */
|
||||
{
|
||||
child_allocation.height = child_size;
|
||||
child_allocation.y = y;
|
||||
|
||||
y += child_size + spacing;
|
||||
}
|
||||
|
||||
gtk_widget_size_allocate (child, &child_allocation, baseline);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_box_layout_class_init (GtkBoxLayoutClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GtkLayoutManagerClass *layout_manager_class = GTK_LAYOUT_MANAGER_CLASS (klass);
|
||||
|
||||
gobject_class->set_property = gtk_box_layout_set_property;
|
||||
gobject_class->get_property = gtk_box_layout_get_property;
|
||||
|
||||
layout_manager_class->get_request_mode = gtk_box_layout_get_request_mode;
|
||||
layout_manager_class->measure = gtk_box_layout_measure;
|
||||
layout_manager_class->allocate = gtk_box_layout_allocate;
|
||||
|
||||
/**
|
||||
* GtkBoxLayout:homogeneous:
|
||||
*
|
||||
* Whether the box layout should distribute the available space
|
||||
* homogeneously among the children of the widget using it as a
|
||||
* layout manager.
|
||||
*/
|
||||
box_layout_props[PROP_HOMOGENEOUS] =
|
||||
g_param_spec_boolean ("homogeneous",
|
||||
P_("Homogeneous"),
|
||||
P_("Distribute space homogeneously"),
|
||||
FALSE,
|
||||
GTK_PARAM_READWRITE |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkBoxLayout:spacing:
|
||||
*
|
||||
* The space between each child of the widget using the box
|
||||
* layout as its layout manager.
|
||||
*/
|
||||
box_layout_props[PROP_SPACING] =
|
||||
g_param_spec_int ("spacing",
|
||||
P_("Spacing"),
|
||||
P_("Spacing between widgets"),
|
||||
0, G_MAXINT, 0,
|
||||
GTK_PARAM_READWRITE |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkBoxLayout:baseline-position:
|
||||
*
|
||||
* The position of the allocated baseline within the extra space
|
||||
* allocated to each child of the widget using a box layout
|
||||
* manager.
|
||||
*
|
||||
* This property is only relevant for horizontal layouts containing
|
||||
* at least one child with a baseline alignment.
|
||||
*/
|
||||
box_layout_props[PROP_BASELINE_POSITION] =
|
||||
g_param_spec_enum ("baseline-position",
|
||||
P_("Baseline position"),
|
||||
P_("The position of the baseline aligned widgets if extra space is available"),
|
||||
GTK_TYPE_BASELINE_POSITION,
|
||||
GTK_BASELINE_POSITION_CENTER,
|
||||
GTK_PARAM_READWRITE |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, box_layout_props);
|
||||
g_object_class_override_property (gobject_class, PROP_ORIENTATION, "orientation");
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_box_layout_init (GtkBoxLayout *self)
|
||||
{
|
||||
self->homogeneous = FALSE;
|
||||
self->spacing = 0;
|
||||
self->orientation = GTK_ORIENTATION_HORIZONTAL;
|
||||
self->baseline_position = GTK_BASELINE_POSITION_CENTER;
|
||||
}
|
||||
|
||||
GtkLayoutManager *
|
||||
gtk_box_layout_new (GtkOrientation orientation)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_BOX_LAYOUT,
|
||||
"orientation", orientation,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_box_layout_set_homogeneous (GtkBoxLayout *box_layout,
|
||||
gboolean homogeneous)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_BOX_LAYOUT (box_layout));
|
||||
|
||||
homogeneous = !!homogeneous;
|
||||
if (box_layout->homogeneous == homogeneous)
|
||||
return;
|
||||
|
||||
box_layout->homogeneous = homogeneous;
|
||||
|
||||
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (box_layout));
|
||||
g_object_notify_by_pspec (G_OBJECT (box_layout), box_layout_props[PROP_HOMOGENEOUS]);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_box_layout_get_homogeneous (GtkBoxLayout *box_layout)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_BOX_LAYOUT (box_layout), FALSE);
|
||||
|
||||
return box_layout->homogeneous;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_box_layout_set_spacing (GtkBoxLayout *box_layout,
|
||||
guint spacing)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_BOX_LAYOUT (box_layout));
|
||||
|
||||
if (box_layout->spacing == spacing)
|
||||
return;
|
||||
|
||||
box_layout->spacing = spacing;
|
||||
|
||||
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (box_layout));
|
||||
g_object_notify_by_pspec (G_OBJECT (box_layout), box_layout_props[PROP_SPACING]);
|
||||
}
|
||||
|
||||
guint
|
||||
gtk_box_layout_get_spacing (GtkBoxLayout *box_layout)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_BOX_LAYOUT (box_layout), 0);
|
||||
|
||||
return box_layout->spacing;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_box_layout_set_baseline_position:
|
||||
* @box_layout: a #GtkBoxLayout
|
||||
* @position: a #GtkBaselinePosition
|
||||
*
|
||||
* Sets the baseline position of a box layout.
|
||||
*
|
||||
* The baseline position affects only horizontal boxes with at least one
|
||||
* baseline aligned child. If there is more vertical space available than
|
||||
* requested, and the baseline is not allocated by the parent then the
|
||||
* given @position is used to allocate the baseline within the extra
|
||||
* space available.
|
||||
*/
|
||||
void
|
||||
gtk_box_layout_set_baseline_position (GtkBoxLayout *box_layout,
|
||||
GtkBaselinePosition position)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_BOX_LAYOUT (box_layout));
|
||||
|
||||
if (box_layout->baseline_position != position)
|
||||
{
|
||||
box_layout->baseline_position = position;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (box_layout), box_layout_props[PROP_BASELINE_POSITION]);
|
||||
|
||||
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (box_layout));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_box_layout_get_baseline_position:
|
||||
* @box_layout: a #GtkBoxLayout
|
||||
*
|
||||
* Gets the value set by gtk_box_layout_set_baseline_position().
|
||||
*
|
||||
* Returns: the baseline position
|
||||
*/
|
||||
GtkBaselinePosition
|
||||
gtk_box_layout_get_baseline_position (GtkBoxLayout *box_layout)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_BOX_LAYOUT (box_layout), GTK_BASELINE_POSITION_CENTER);
|
||||
|
||||
return box_layout->baseline_position;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/* gtkboxlayout.h: Box layout manager
|
||||
*
|
||||
* Copyright 2019 GNOME Foundation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtkenums.h>
|
||||
#include <gtk/gtklayoutmanager.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_BOX_LAYOUT (gtk_box_layout_get_type())
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkBoxLayout, gtk_box_layout, GTK, BOX_LAYOUT, GtkLayoutManager)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkLayoutManager * gtk_box_layout_new (GtkOrientation orientation);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_box_layout_set_homogeneous (GtkBoxLayout *box_layout,
|
||||
gboolean homogeneous);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_box_layout_get_homogeneous (GtkBoxLayout *box_layout);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_box_layout_set_spacing (GtkBoxLayout *box_layout,
|
||||
guint spacing);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
guint gtk_box_layout_get_spacing (GtkBoxLayout *box_layout);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_box_layout_set_baseline_position (GtkBoxLayout *box_layout,
|
||||
GtkBaselinePosition position);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkBaselinePosition gtk_box_layout_get_baseline_position (GtkBoxLayout *box_layout);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -66,6 +66,7 @@
|
||||
#include "gtkmain.h"
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkstylecontext.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
|
||||
#include "a11y/gtkbuttonaccessible.h"
|
||||
|
||||
@@ -295,6 +295,8 @@ static gboolean gtk_calendar_key_controller_key_pressed (GtkEventControllerKey *
|
||||
GdkModifierType state,
|
||||
GtkWidget *widget);
|
||||
static void gtk_calendar_key_controller_focus (GtkEventControllerKey *controller,
|
||||
GdkCrossingMode mode,
|
||||
GdkNotifyType detail,
|
||||
GtkWidget *widget);
|
||||
static void gtk_calendar_grab_notify (GtkWidget *widget,
|
||||
gboolean was_grabbed);
|
||||
@@ -2854,6 +2856,8 @@ gtk_calendar_key_controller_key_pressed (GtkEventControllerKey *controller,
|
||||
|
||||
static void
|
||||
gtk_calendar_key_controller_focus (GtkEventControllerKey *key,
|
||||
GdkCrossingMode mode,
|
||||
GdkNotifyType detail,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkCalendar *calendar = GTK_CALENDAR (widget);
|
||||
|
||||
@@ -352,6 +352,7 @@
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtksnapshot.h"
|
||||
#include "gtkstylecontext.h"
|
||||
|
||||
#include <gobject/gvaluecollector.h>
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtksnapshot.h"
|
||||
#include "gtkstylecontext.h"
|
||||
#include "gtktreeprivate.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "gtkorientable.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtksnapshot.h"
|
||||
#include "gtkstylecontext.h"
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "gtkprivate.h"
|
||||
#include "gtksizerequest.h"
|
||||
#include "gtksnapshot.h"
|
||||
#include "gtkstylecontext.h"
|
||||
#include "gtktreeprivate.h"
|
||||
|
||||
#include "a11y/gtktextcellaccessible.h"
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtksnapshot.h"
|
||||
#include "gtkstylecontext.h"
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtksizegroup.h"
|
||||
#include "gtkstylecontext.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "gtkspinbutton.h"
|
||||
#include "gtkstylecontext.h"
|
||||
#include "gtkeventcontrollerkey.h"
|
||||
#include "gtkroot.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@@ -224,7 +225,7 @@ popup_edit (GtkWidget *widget,
|
||||
{
|
||||
dismiss_current_popup (editor);
|
||||
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (editor));
|
||||
g_set_object (&editor->priv->popdown_focus, gtk_window_get_focus (GTK_WINDOW (toplevel)));
|
||||
g_set_object (&editor->priv->popdown_focus, gtk_root_get_focus (GTK_ROOT (toplevel)));
|
||||
editor->priv->current_popup = popup;
|
||||
editor->priv->popup_position = position;
|
||||
gtk_widget_show (popup);
|
||||
@@ -355,7 +356,6 @@ color_picked (GObject *source,
|
||||
color = gtk_color_picker_pick_finish (picker, res, &error);
|
||||
if (color == NULL)
|
||||
{
|
||||
g_warning ("Picking color failed: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
else
|
||||
|
||||
+14
-21
@@ -35,7 +35,6 @@
|
||||
#include "gtkmodelbutton.h"
|
||||
#include "gtkpopover.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkroundedboxprivate.h"
|
||||
#include "gtksnapshot.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
@@ -43,8 +42,6 @@
|
||||
|
||||
#include "a11y/gtkcolorswatchaccessibleprivate.h"
|
||||
|
||||
#include "gsk/gskroundedrectprivate.h"
|
||||
|
||||
/*
|
||||
* GtkColorSwatch has two CSS nodes, the main one named colorswatch
|
||||
* and a subnode named overlay. The main node gets the .light or .dark
|
||||
@@ -97,30 +94,21 @@ swatch_snapshot (GtkWidget *widget,
|
||||
{
|
||||
GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
|
||||
GtkColorSwatchPrivate *priv = gtk_color_swatch_get_instance_private (swatch);
|
||||
GtkStyleContext *context;
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
|
||||
if (priv->has_color)
|
||||
{
|
||||
cairo_pattern_t *pattern;
|
||||
cairo_matrix_t matrix;
|
||||
GskRoundedRect content_box;
|
||||
|
||||
gtk_rounded_boxes_init_for_style (NULL,
|
||||
NULL,
|
||||
&content_box,
|
||||
gtk_style_context_lookup_style (context),
|
||||
0, 0,
|
||||
gtk_widget_get_width (widget),
|
||||
gtk_widget_get_height (widget));
|
||||
gtk_snapshot_push_rounded_clip (snapshot, &content_box);
|
||||
|
||||
if (priv->use_alpha && !gdk_rgba_is_opaque (&priv->color))
|
||||
{
|
||||
cairo_t *cr;
|
||||
|
||||
cr = gtk_snapshot_append_cairo (snapshot, &content_box.bounds);
|
||||
cr = gtk_snapshot_append_cairo (snapshot,
|
||||
&GRAPHENE_RECT_INIT (
|
||||
0, 0,
|
||||
gtk_widget_get_width (widget),
|
||||
gtk_widget_get_height (widget)));
|
||||
cairo_set_source_rgb (cr, 0.33, 0.33, 0.33);
|
||||
cairo_paint (cr);
|
||||
|
||||
@@ -136,7 +124,10 @@ swatch_snapshot (GtkWidget *widget,
|
||||
|
||||
gtk_snapshot_append_color (snapshot,
|
||||
&priv->color,
|
||||
&content_box.bounds);
|
||||
&GRAPHENE_RECT_INIT (
|
||||
0, 0,
|
||||
gtk_widget_get_width (widget),
|
||||
gtk_widget_get_height (widget)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -146,10 +137,11 @@ swatch_snapshot (GtkWidget *widget,
|
||||
|
||||
gtk_snapshot_append_color (snapshot,
|
||||
&color,
|
||||
&content_box.bounds);
|
||||
&GRAPHENE_RECT_INIT (
|
||||
0, 0,
|
||||
gtk_widget_get_width (widget),
|
||||
gtk_widget_get_height (widget)));
|
||||
}
|
||||
|
||||
gtk_snapshot_pop (snapshot);
|
||||
}
|
||||
|
||||
gtk_widget_snapshot_child (widget, priv->overlay_widget, snapshot);
|
||||
@@ -576,6 +568,7 @@ gtk_color_swatch_init (GtkColorSwatch *swatch)
|
||||
|
||||
gtk_widget_set_can_focus (GTK_WIDGET (swatch), TRUE);
|
||||
gtk_widget_set_has_surface (GTK_WIDGET (swatch), FALSE);
|
||||
gtk_widget_set_overflow (GTK_WIDGET (swatch), GTK_OVERFLOW_HIDDEN);
|
||||
|
||||
gesture = gtk_gesture_long_press_new ();
|
||||
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture),
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#define __GTK_CSS_BOXES_PRIVATE_H__
|
||||
|
||||
#include "gtkcsstypesprivate.h"
|
||||
#include "gtktypes.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
+2
-128
@@ -23,8 +23,6 @@
|
||||
#include "gtkcssstylepropertyprivate.h"
|
||||
#include "gtkhslaprivate.h"
|
||||
#include "gtkstylepropertyprivate.h"
|
||||
#include "gtkwin32drawprivate.h"
|
||||
#include "gtkwin32themeprivate.h"
|
||||
|
||||
#include "gtkprivate.h"
|
||||
|
||||
@@ -34,7 +32,6 @@ typedef enum {
|
||||
COLOR_TYPE_SHADE,
|
||||
COLOR_TYPE_ALPHA,
|
||||
COLOR_TYPE_MIX,
|
||||
COLOR_TYPE_WIN32,
|
||||
COLOR_TYPE_CURRENT_COLOR
|
||||
} ColorType;
|
||||
|
||||
@@ -60,12 +57,6 @@ struct _GtkCssValue
|
||||
GtkCssValue *color2;
|
||||
gdouble factor;
|
||||
} mix;
|
||||
|
||||
struct
|
||||
{
|
||||
GtkWin32Theme *theme;
|
||||
gint id;
|
||||
} win32;
|
||||
} sym_col;
|
||||
};
|
||||
|
||||
@@ -90,9 +81,6 @@ gtk_css_value_color_free (GtkCssValue *color)
|
||||
_gtk_css_value_unref (color->sym_col.mix.color1);
|
||||
_gtk_css_value_unref (color->sym_col.mix.color2);
|
||||
break;
|
||||
case COLOR_TYPE_WIN32:
|
||||
gtk_win32_theme_unref (color->sym_col.win32.theme);
|
||||
break;
|
||||
case COLOR_TYPE_LITERAL:
|
||||
case COLOR_TYPE_CURRENT_COLOR:
|
||||
default:
|
||||
@@ -240,18 +228,6 @@ _gtk_css_color_value_resolve (GtkCssValue *color,
|
||||
value =_gtk_css_rgba_value_new_from_rgba (&res);
|
||||
}
|
||||
|
||||
break;
|
||||
case COLOR_TYPE_WIN32:
|
||||
{
|
||||
GdkRGBA res;
|
||||
|
||||
gtk_win32_theme_get_color (color->sym_col.win32.theme,
|
||||
color->sym_col.win32.id,
|
||||
&res);
|
||||
|
||||
value = _gtk_css_rgba_value_new_from_rgba (&res);
|
||||
}
|
||||
|
||||
break;
|
||||
case COLOR_TYPE_CURRENT_COLOR:
|
||||
if (current)
|
||||
@@ -350,9 +326,6 @@ gtk_css_value_color_equal (const GtkCssValue *value1,
|
||||
value2->sym_col.mix.color1) &&
|
||||
_gtk_css_value_equal (value1->sym_col.mix.color2,
|
||||
value2->sym_col.mix.color2);
|
||||
case COLOR_TYPE_WIN32:
|
||||
return gtk_win32_theme_equal (value1->sym_col.win32.theme, value2->sym_col.win32.theme) &&
|
||||
value1->sym_col.win32.id == value2->sym_col.win32.id;
|
||||
case COLOR_TYPE_CURRENT_COLOR:
|
||||
return TRUE;
|
||||
default:
|
||||
@@ -421,20 +394,6 @@ gtk_css_value_color_print (const GtkCssValue *value,
|
||||
g_string_append (string, ")");
|
||||
}
|
||||
break;
|
||||
case COLOR_TYPE_WIN32:
|
||||
{
|
||||
const char *name;
|
||||
g_string_append (string, GTK_WIN32_THEME_SYMBOLIC_COLOR_NAME"(");
|
||||
gtk_win32_theme_print (value->sym_col.win32.theme, string);
|
||||
g_string_append (string, ", ");
|
||||
name = gtk_win32_get_sys_color_name_for_id (value->sym_col.win32.id);
|
||||
if (name)
|
||||
g_string_append (string, name);
|
||||
else
|
||||
g_string_append_printf (string, "%d", value->sym_col.win32.id);
|
||||
g_string_append (string, ")");
|
||||
}
|
||||
break;
|
||||
case COLOR_TYPE_CURRENT_COLOR:
|
||||
g_string_append (string, "currentColor");
|
||||
break;
|
||||
@@ -543,38 +502,6 @@ _gtk_css_color_value_new_mix (GtkCssValue *color1,
|
||||
return value;
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
gtk_css_color_value_new_win32_for_theme (GtkWin32Theme *theme,
|
||||
gint id)
|
||||
{
|
||||
GtkCssValue *value;
|
||||
|
||||
gtk_internal_return_val_if_fail (theme != NULL, NULL);
|
||||
|
||||
value = _gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_COLOR);
|
||||
value->type = COLOR_TYPE_WIN32;
|
||||
value->sym_col.win32.theme = gtk_win32_theme_ref (theme);
|
||||
value->sym_col.win32.id = id;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_color_value_new_win32 (const gchar *theme_class,
|
||||
gint id)
|
||||
{
|
||||
GtkWin32Theme *theme;
|
||||
GtkCssValue *value;
|
||||
|
||||
gtk_internal_return_val_if_fail (theme_class != NULL, NULL);
|
||||
|
||||
theme = gtk_win32_theme_lookup (theme_class);
|
||||
value = gtk_css_color_value_new_win32_for_theme (theme, id);
|
||||
gtk_win32_theme_unref (theme);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
_gtk_css_color_value_new_current_color (void)
|
||||
{
|
||||
@@ -590,54 +517,9 @@ typedef enum {
|
||||
COLOR_DARKER,
|
||||
COLOR_SHADE,
|
||||
COLOR_ALPHA,
|
||||
COLOR_MIX,
|
||||
COLOR_WIN32
|
||||
COLOR_MIX
|
||||
} ColorParseType;
|
||||
|
||||
static GtkCssValue *
|
||||
gtk_css_color_parse_win32 (GtkCssParser *parser)
|
||||
{
|
||||
GtkCssValue *color;
|
||||
GtkWin32Theme *theme;
|
||||
char *name;
|
||||
int id;
|
||||
|
||||
theme = gtk_win32_theme_parse (parser);
|
||||
if (theme == NULL)
|
||||
return NULL;
|
||||
|
||||
if (! _gtk_css_parser_try (parser, ",", TRUE))
|
||||
{
|
||||
gtk_win32_theme_unref (theme);
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected ','");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
name = _gtk_css_parser_try_ident (parser, TRUE);
|
||||
if (name)
|
||||
{
|
||||
id = gtk_win32_get_sys_color_id_for_name (name);
|
||||
if (id == -1)
|
||||
{
|
||||
_gtk_css_parser_error (parser, "'%s' is not a win32 color name.", name);
|
||||
g_free (name);
|
||||
return NULL;
|
||||
}
|
||||
g_free (name);
|
||||
}
|
||||
else if (!_gtk_css_parser_try_int (parser, &id))
|
||||
{
|
||||
gtk_win32_theme_unref (theme);
|
||||
_gtk_css_parser_error (parser, "Expected a valid integer value");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
color = gtk_css_color_value_new_win32_for_theme (theme, id);
|
||||
gtk_win32_theme_unref (theme);
|
||||
return color;
|
||||
}
|
||||
|
||||
static GtkCssValue *
|
||||
_gtk_css_color_value_parse_function (GtkCssParser *parser,
|
||||
ColorParseType color)
|
||||
@@ -704,12 +586,6 @@ _gtk_css_color_value_parse_function (GtkCssParser *parser,
|
||||
|
||||
value = _gtk_css_color_value_new_literal (&rgba);
|
||||
}
|
||||
else if (color == COLOR_WIN32)
|
||||
{
|
||||
value = gtk_css_color_parse_win32 (parser);
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
child1 = _gtk_css_color_value_parse (parser);
|
||||
@@ -775,7 +651,6 @@ _gtk_css_color_value_parse_function (GtkCssParser *parser,
|
||||
break;
|
||||
case COLOR_RGB:
|
||||
case COLOR_RGBA:
|
||||
case COLOR_WIN32:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
value = NULL;
|
||||
@@ -802,8 +677,7 @@ _gtk_css_color_value_parse (GtkCssParser *parser)
|
||||
GtkCssValue *value;
|
||||
GdkRGBA rgba;
|
||||
guint color;
|
||||
const char *names[] = {"rgba", "rgb", "lighter", "darker", "shade", "alpha", "mix",
|
||||
GTK_WIN32_THEME_SYMBOLIC_COLOR_NAME};
|
||||
const char *names[] = {"rgba", "rgb", "lighter", "darker", "shade", "alpha", "mix"};
|
||||
char *name;
|
||||
|
||||
if (_gtk_css_parser_try (parser, "currentColor", TRUE))
|
||||
|
||||
@@ -37,8 +37,6 @@ GtkCssValue * _gtk_css_color_value_new_alpha (GtkCssValue *color,
|
||||
GtkCssValue * _gtk_css_color_value_new_mix (GtkCssValue *color1,
|
||||
GtkCssValue *color2,
|
||||
gdouble factor);
|
||||
GtkCssValue * _gtk_css_color_value_new_win32 (const gchar *theme_class,
|
||||
gint id);
|
||||
GtkCssValue * _gtk_css_color_value_new_current_color (void);
|
||||
|
||||
GtkCssValue * _gtk_css_color_value_parse (GtkCssParser *parser);
|
||||
|
||||
@@ -254,7 +254,7 @@ gtk_css_ease_value_parse_cubic_bezier (GtkCssParser *parser)
|
||||
static GtkCssValue *
|
||||
gtk_css_ease_value_parse_steps (GtkCssParser *parser)
|
||||
{
|
||||
guint n_steps;
|
||||
int n_steps;
|
||||
gboolean start;
|
||||
|
||||
if (!_gtk_css_parser_try (parser, "(", TRUE))
|
||||
@@ -263,11 +263,16 @@ gtk_css_ease_value_parse_steps (GtkCssParser *parser)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_try_uint (parser, &n_steps))
|
||||
if (!_gtk_css_parser_try_int (parser, &n_steps))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected number of steps");
|
||||
return NULL;
|
||||
}
|
||||
else if (n_steps < 1)
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Number of steps must be > 0");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_gtk_css_parser_try (parser, ",", TRUE))
|
||||
{
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "gtk/gtkcssimagescaledprivate.h"
|
||||
#include "gtk/gtkcssimagerecolorprivate.h"
|
||||
#include "gtk/gtkcssimagefallbackprivate.h"
|
||||
#include "gtk/gtkcssimagewin32private.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (GtkCssImage, _gtk_css_image, G_TYPE_OBJECT)
|
||||
|
||||
@@ -499,7 +498,6 @@ gtk_css_image_get_parser_type (GtkCssParser *parser)
|
||||
{ "-gtk-icontheme", _gtk_css_image_icon_theme_get_type },
|
||||
{ "-gtk-scaled", _gtk_css_image_scaled_get_type },
|
||||
{ "-gtk-recolor", _gtk_css_image_recolor_get_type },
|
||||
{ "-gtk-win32-theme-part", _gtk_css_image_win32_get_type },
|
||||
{ "linear-gradient", _gtk_css_image_linear_get_type },
|
||||
{ "repeating-linear-gradient", _gtk_css_image_linear_get_type },
|
||||
{ "radial-gradient", _gtk_css_image_radial_get_type },
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "gtk/gtkcssparserprivate.h"
|
||||
#include "gtk/gtkcsstypesprivate.h"
|
||||
#include "gtk/gtksnapshot.h"
|
||||
#include "gtk/gtkstyleprovider.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
@@ -1,263 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2011 Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcssimagewin32private.h"
|
||||
|
||||
#include "gtkcssprovider.h"
|
||||
|
||||
G_DEFINE_TYPE (GtkCssImageWin32, _gtk_css_image_win32, GTK_TYPE_CSS_IMAGE)
|
||||
|
||||
static void
|
||||
gtk_css_image_win32_snapshot (GtkCssImage *image,
|
||||
GtkSnapshot *snapshot,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
GtkCssImageWin32 *wimage = GTK_CSS_IMAGE_WIN32 (image);
|
||||
cairo_surface_t *surface;
|
||||
int dx, dy;
|
||||
cairo_t *cr;
|
||||
|
||||
cr = gtk_snapshot_append_cairo (snapshot,
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
|
||||
surface = gtk_win32_theme_create_surface (wimage->theme, wimage->part, wimage->state, wimage->margins,
|
||||
width, height, &dx, &dy);
|
||||
|
||||
if (wimage->state2 >= 0)
|
||||
{
|
||||
cairo_surface_t *surface2;
|
||||
cairo_t *cr2;
|
||||
int dx2, dy2;
|
||||
|
||||
surface2 = gtk_win32_theme_create_surface (wimage->theme, wimage->part2, wimage->state2, wimage->margins,
|
||||
width, height, &dx2, &dy2);
|
||||
|
||||
cr2 = cairo_create (surface);
|
||||
|
||||
cairo_set_source_surface (cr2, surface2, dx2 - dx, dy2-dy);
|
||||
cairo_paint_with_alpha (cr2, wimage->over_alpha);
|
||||
|
||||
cairo_destroy (cr2);
|
||||
|
||||
cairo_surface_destroy (surface2);
|
||||
}
|
||||
|
||||
cairo_set_source_surface (cr, surface, dx, dy);
|
||||
cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_NONE);
|
||||
cairo_rectangle (cr, 0, 0, width, height);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_css_image_win32_parse (GtkCssImage *image,
|
||||
GtkCssParser *parser)
|
||||
{
|
||||
GtkCssImageWin32 *wimage = GTK_CSS_IMAGE_WIN32 (image);
|
||||
|
||||
if (!_gtk_css_parser_try (parser, "-gtk-win32-theme-part", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "'-gtk-win32-theme-part'");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_try (parser, "(", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected '(' after '-gtk-win32-theme-part'");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wimage->theme = gtk_win32_theme_parse (parser);
|
||||
if (wimage->theme == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (! _gtk_css_parser_try (parser, ",", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected ','");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_try_int (parser, &wimage->part))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected a valid integer value");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (! _gtk_css_parser_try (parser, ",", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected ','");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_try_int (parser, &wimage->state))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected a valid integer value");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while ( _gtk_css_parser_try (parser, ",", TRUE))
|
||||
{
|
||||
if ( _gtk_css_parser_try (parser, "over", TRUE))
|
||||
{
|
||||
if (!_gtk_css_parser_try (parser, "(", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected '(' after 'over'");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_try_int (parser, &wimage->part2))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected a valid integer value");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (! _gtk_css_parser_try (parser, ",", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected ','");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_try_int (parser, &wimage->state2))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected a valid integer value");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( _gtk_css_parser_try (parser, ",", TRUE))
|
||||
{
|
||||
if (!_gtk_css_parser_try_double (parser, &wimage->over_alpha))
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected a valid double value");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_try (parser, ")", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected ')' at end of 'over'");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if ( _gtk_css_parser_try (parser, "margins", TRUE))
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!_gtk_css_parser_try (parser, "(", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected '(' after 'margins'");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (!_gtk_css_parser_try_int (parser, &wimage->margins[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
_gtk_css_parser_error (parser, "Expected valid margins");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (i == 1)
|
||||
wimage->margins[1] = wimage->margins[0];
|
||||
if (i <= 2)
|
||||
wimage->margins[2] = wimage->margins[1];
|
||||
if (i <= 3)
|
||||
wimage->margins[3] = wimage->margins[2];
|
||||
|
||||
if (!_gtk_css_parser_try (parser, ")", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected ')' at end of 'margins'");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected identifier");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_gtk_css_parser_try (parser, ")", TRUE))
|
||||
{
|
||||
_gtk_css_parser_error (parser,
|
||||
"Expected ')'");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_win32_print (GtkCssImage *image,
|
||||
GString *string)
|
||||
{
|
||||
GtkCssImageWin32 *wimage = GTK_CSS_IMAGE_WIN32 (image);
|
||||
|
||||
g_string_append (string, "-gtk-win32-theme-part(");
|
||||
gtk_win32_theme_print (wimage->theme, string);
|
||||
g_string_append_printf (string, ", %d, %d)", wimage->part, wimage->state);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_image_win32_finalize (GObject *object)
|
||||
{
|
||||
GtkCssImageWin32 *wimage = GTK_CSS_IMAGE_WIN32 (object);
|
||||
|
||||
if (wimage->theme)
|
||||
gtk_win32_theme_unref (wimage->theme);
|
||||
|
||||
G_OBJECT_CLASS (_gtk_css_image_win32_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_css_image_win32_class_init (GtkCssImageWin32Class *klass)
|
||||
{
|
||||
GtkCssImageClass *image_class = GTK_CSS_IMAGE_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_css_image_win32_finalize;
|
||||
|
||||
image_class->snapshot = gtk_css_image_win32_snapshot;
|
||||
image_class->parse = gtk_css_image_win32_parse;
|
||||
image_class->print = gtk_css_image_win32_print;
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_css_image_win32_init (GtkCssImageWin32 *wimage)
|
||||
{
|
||||
wimage->over_alpha = 1.0;
|
||||
wimage->part2 = -1;
|
||||
wimage->state2 = -1;
|
||||
}
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2011 Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_IMAGE_WIN32_PRIVATE_H__
|
||||
#define __GTK_CSS_IMAGE_WIN32_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcssimageprivate.h"
|
||||
#include "gtk/gtkwin32themeprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_CSS_IMAGE_WIN32 (_gtk_css_image_win32_get_type ())
|
||||
#define GTK_CSS_IMAGE_WIN32(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_IMAGE_WIN32, GtkCssImageWin32))
|
||||
#define GTK_CSS_IMAGE_WIN32_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_IMAGE_WIN32, GtkCssImageWin32Class))
|
||||
#define GTK_IS_CSS_IMAGE_WIN32(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_IMAGE_WIN32))
|
||||
#define GTK_IS_CSS_IMAGE_WIN32_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_IMAGE_WIN32))
|
||||
#define GTK_CSS_IMAGE_WIN32_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_IMAGE_WIN32, GtkCssImageWin32Class))
|
||||
|
||||
typedef struct _GtkCssImageWin32 GtkCssImageWin32;
|
||||
typedef struct _GtkCssImageWin32Class GtkCssImageWin32Class;
|
||||
|
||||
struct _GtkCssImageWin32
|
||||
{
|
||||
GtkCssImage parent;
|
||||
|
||||
int part;
|
||||
int state;
|
||||
|
||||
double over_alpha;
|
||||
int part2;
|
||||
int state2;
|
||||
|
||||
gint margins[4];
|
||||
|
||||
GtkWin32Theme *theme;
|
||||
};
|
||||
|
||||
struct _GtkCssImageWin32Class
|
||||
{
|
||||
GtkCssImageClass parent_class;
|
||||
};
|
||||
|
||||
GType _gtk_css_image_win32_get_type (void) G_GNUC_CONST;
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_IMAGE_WIN32_PRIVATE_H__ */
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "gtkcssstylechangeprivate.h"
|
||||
#include "gtkbitmaskprivate.h"
|
||||
#include "gtkcsstypesprivate.h"
|
||||
#include "gtkstylecontext.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
+1
-17
@@ -21,7 +21,6 @@
|
||||
|
||||
#include "gtkcsscalcvalueprivate.h"
|
||||
#include "gtkcssdimensionvalueprivate.h"
|
||||
#include "gtkcsswin32sizevalueprivate.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
struct _GtkCssValue {
|
||||
@@ -131,14 +130,7 @@ gboolean
|
||||
gtk_css_number_value_can_parse (GtkCssParser *parser)
|
||||
{
|
||||
return _gtk_css_parser_has_number (parser)
|
||||
|| _gtk_css_parser_has_prefix (parser, "calc")
|
||||
|| _gtk_css_parser_has_prefix (parser, "-gtk-win32-size")
|
||||
|| _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-width")
|
||||
|| _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-height")
|
||||
|| _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-top")
|
||||
|| _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-left")
|
||||
|| _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-bottom")
|
||||
|| _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-right");
|
||||
|| _gtk_css_parser_has_prefix (parser, "calc");
|
||||
}
|
||||
|
||||
GtkCssValue *
|
||||
@@ -147,14 +139,6 @@ _gtk_css_number_value_parse (GtkCssParser *parser,
|
||||
{
|
||||
if (_gtk_css_parser_has_prefix (parser, "calc"))
|
||||
return gtk_css_calc_value_parse (parser, flags);
|
||||
if (_gtk_css_parser_has_prefix (parser, "-gtk-win32-size") ||
|
||||
_gtk_css_parser_has_prefix (parser, "-gtk-win32-part-width") ||
|
||||
_gtk_css_parser_has_prefix (parser, "-gtk-win32-part-height") ||
|
||||
_gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-top") ||
|
||||
_gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-left") ||
|
||||
_gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-bottom") ||
|
||||
_gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-right"))
|
||||
return gtk_css_win32_size_value_parse (parser, flags);
|
||||
|
||||
return gtk_css_dimension_value_parse (parser, flags);
|
||||
}
|
||||
|
||||
+7
-143
@@ -202,23 +202,6 @@ _gtk_css_parser_error (GtkCssParser *parser,
|
||||
_gtk_css_parser_take_error (parser, error);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_css_parser_error_full (GtkCssParser *parser,
|
||||
GtkCssProviderError code,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
GError *error;
|
||||
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
error = g_error_new_valist (GTK_CSS_PROVIDER_ERROR,
|
||||
code, format, args);
|
||||
va_end (args);
|
||||
|
||||
_gtk_css_parser_take_error (parser, error);
|
||||
}
|
||||
static gboolean
|
||||
gtk_css_parser_new_line (GtkCssParser *parser)
|
||||
{
|
||||
@@ -298,14 +281,17 @@ _gtk_css_parser_skip_whitespace (GtkCssParser *parser)
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_css_parser_try_len (GtkCssParser *parser,
|
||||
const char *string,
|
||||
gsize string_len,
|
||||
gboolean skip_whitespace)
|
||||
_gtk_css_parser_try (GtkCssParser *parser,
|
||||
const char *string,
|
||||
gboolean skip_whitespace)
|
||||
{
|
||||
gsize string_len;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);
|
||||
g_return_val_if_fail (string != NULL, FALSE);
|
||||
|
||||
string_len = strlen (string);
|
||||
|
||||
if (g_ascii_strncasecmp (parser->data, string, string_len) != 0)
|
||||
return FALSE;
|
||||
|
||||
@@ -579,33 +565,6 @@ _gtk_css_parser_try_int (GtkCssParser *parser,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_css_parser_try_uint (GtkCssParser *parser,
|
||||
guint *value)
|
||||
{
|
||||
guint64 result;
|
||||
char *end;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);
|
||||
g_return_val_if_fail (value != NULL, FALSE);
|
||||
|
||||
errno = 0;
|
||||
result = g_ascii_strtoull (parser->data, &end, 10);
|
||||
if (errno)
|
||||
return FALSE;
|
||||
if (result > G_MAXUINT)
|
||||
return FALSE;
|
||||
if (parser->data == end)
|
||||
return FALSE;
|
||||
|
||||
parser->data = end;
|
||||
*value = result;
|
||||
|
||||
_gtk_css_parser_skip_whitespace (parser);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_css_parser_try_double (GtkCssParser *parser,
|
||||
gdouble *value)
|
||||
@@ -758,71 +717,6 @@ gtk_css_dimension_value_parse (GtkCssParser *parser,
|
||||
return gtk_css_dimension_value_new (value, unit);
|
||||
}
|
||||
|
||||
/* XXX: we should introduce GtkCssLenght that deals with
|
||||
* different kind of units */
|
||||
gboolean
|
||||
_gtk_css_parser_try_length (GtkCssParser *parser,
|
||||
int *value)
|
||||
{
|
||||
if (!_gtk_css_parser_try_int (parser, value))
|
||||
return FALSE;
|
||||
|
||||
/* FIXME: _try_uint skips spaces while the
|
||||
* spec forbids them
|
||||
*/
|
||||
_gtk_css_parser_try (parser, "px", TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_css_parser_try_enum (GtkCssParser *parser,
|
||||
GType enum_type,
|
||||
int *value)
|
||||
{
|
||||
GEnumClass *enum_class;
|
||||
gboolean result;
|
||||
const char *start;
|
||||
char *str;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), FALSE);
|
||||
g_return_val_if_fail (value != NULL, FALSE);
|
||||
|
||||
result = FALSE;
|
||||
|
||||
enum_class = g_type_class_ref (enum_type);
|
||||
|
||||
start = parser->data;
|
||||
|
||||
str = _gtk_css_parser_try_ident (parser, TRUE);
|
||||
if (str == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (enum_class->n_values)
|
||||
{
|
||||
GEnumValue *enum_value;
|
||||
|
||||
for (enum_value = enum_class->values; enum_value->value_name; enum_value++)
|
||||
{
|
||||
if (enum_value->value_nick &&
|
||||
g_ascii_strcasecmp (str, enum_value->value_nick) == 0)
|
||||
{
|
||||
*value = enum_value->value;
|
||||
result = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_free (str);
|
||||
g_type_class_unref (enum_class);
|
||||
|
||||
if (!result)
|
||||
parser->data = start;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_css_parser_try_hash_color (GtkCssParser *parser,
|
||||
GdkRGBA *rgba)
|
||||
@@ -1017,36 +911,6 @@ gtk_css_parser_resync_internal (GtkCssParser *parser,
|
||||
} while (*parser->data);
|
||||
}
|
||||
|
||||
char *
|
||||
_gtk_css_parser_read_value (GtkCssParser *parser)
|
||||
{
|
||||
const char *start;
|
||||
char *result;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CSS_PARSER (parser), NULL);
|
||||
|
||||
start = parser->data;
|
||||
|
||||
/* This needs to be done better */
|
||||
gtk_css_parser_resync_internal (parser, TRUE, FALSE, '}');
|
||||
|
||||
result = g_strndup (start, parser->data - start);
|
||||
if (result)
|
||||
{
|
||||
g_strchomp (result);
|
||||
if (result[0] == 0)
|
||||
{
|
||||
g_free (result);
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == NULL)
|
||||
_gtk_css_parser_error (parser, "Expected a property value");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_css_parser_resync (GtkCssParser *parser,
|
||||
gboolean sync_at_semicolon,
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#ifndef __GTK_CSS_PARSER_PRIVATE_H__
|
||||
#define __GTK_CSS_PARSER_PRIVATE_H__
|
||||
|
||||
#include "gtk/gtkcsstypesprivate.h"
|
||||
#include <gtk/gtkcssprovider.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -40,10 +39,6 @@ void _gtk_css_parser_take_error (GtkCssParser *parser
|
||||
void _gtk_css_parser_error (GtkCssParser *parser,
|
||||
const char *format,
|
||||
...) G_GNUC_PRINTF (2, 3);
|
||||
void _gtk_css_parser_error_full (GtkCssParser *parser,
|
||||
GtkCssProviderError code,
|
||||
const char *format,
|
||||
...) G_GNUC_PRINTF (3, 4);
|
||||
|
||||
guint _gtk_css_parser_get_line (GtkCssParser *parser);
|
||||
guint _gtk_css_parser_get_position (GtkCssParser *parser);
|
||||
@@ -66,10 +61,8 @@ gboolean _gtk_css_parser_is_string (GtkCssParser *parser
|
||||
* however is fine to call if you don’t know yet if the token is a foo or a bar,
|
||||
* you can _try_bar() if try_foo() failed.
|
||||
*/
|
||||
#define _gtk_css_parser_try(p, s, skip) (gtk_css_parser_try_len (p, s, strlen(s), skip))
|
||||
gboolean gtk_css_parser_try_len (GtkCssParser *parser,
|
||||
gboolean _gtk_css_parser_try (GtkCssParser *parser,
|
||||
const char *string,
|
||||
gsize string_len,
|
||||
gboolean skip_whitespace);
|
||||
char * _gtk_css_parser_try_ident (GtkCssParser *parser,
|
||||
gboolean skip_whitespace);
|
||||
@@ -77,21 +70,13 @@ char * _gtk_css_parser_try_name (GtkCssParser *parser
|
||||
gboolean skip_whitespace);
|
||||
gboolean _gtk_css_parser_try_int (GtkCssParser *parser,
|
||||
int *value);
|
||||
gboolean _gtk_css_parser_try_uint (GtkCssParser *parser,
|
||||
guint *value);
|
||||
gboolean _gtk_css_parser_try_double (GtkCssParser *parser,
|
||||
gdouble *value);
|
||||
gboolean _gtk_css_parser_try_length (GtkCssParser *parser,
|
||||
int *value);
|
||||
gboolean _gtk_css_parser_try_enum (GtkCssParser *parser,
|
||||
GType enum_type,
|
||||
int *value);
|
||||
gboolean _gtk_css_parser_try_hash_color (GtkCssParser *parser,
|
||||
GdkRGBA *rgba);
|
||||
|
||||
gboolean _gtk_css_parser_has_number (GtkCssParser *parser);
|
||||
char * _gtk_css_parser_read_string (GtkCssParser *parser);
|
||||
char * _gtk_css_parser_read_value (GtkCssParser *parser);
|
||||
GFile * _gtk_css_parser_read_url (GtkCssParser *parser);
|
||||
|
||||
void _gtk_css_parser_skip_whitespace (GtkCssParser *parser);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <cairo.h>
|
||||
#include <pango/pango.h>
|
||||
|
||||
#include "gtkborder.h"
|
||||
#include "gtktypes.h"
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <cairo.h>
|
||||
#include <pango/pango.h>
|
||||
|
||||
#include "gtkborder.h"
|
||||
#include "gtktypes.h"
|
||||
#include "gtkcssparserprivate.h"
|
||||
#include "gtkcssvalueprivate.h"
|
||||
|
||||
+110
-19
@@ -35,7 +35,8 @@ typedef enum {
|
||||
GTK_CSS_TRANSFORM_SCALE,
|
||||
GTK_CSS_TRANSFORM_SKEW,
|
||||
GTK_CSS_TRANSFORM_SKEW_X,
|
||||
GTK_CSS_TRANSFORM_SKEW_Y
|
||||
GTK_CSS_TRANSFORM_SKEW_Y,
|
||||
GTK_CSS_TRANSFORM_PERSPECTIVE
|
||||
} GtkCssTransformType;
|
||||
|
||||
union _GtkCssTransform {
|
||||
@@ -66,6 +67,10 @@ union _GtkCssTransform {
|
||||
GtkCssTransformType type;
|
||||
GtkCssValue *skew;
|
||||
} skew_x, skew_y;
|
||||
struct {
|
||||
GtkCssTransformType type;
|
||||
GtkCssValue *depth;
|
||||
} perspective;
|
||||
};
|
||||
|
||||
struct _GtkCssValue {
|
||||
@@ -110,6 +115,9 @@ gtk_css_transform_clear (GtkCssTransform *transform)
|
||||
case GTK_CSS_TRANSFORM_SKEW_Y:
|
||||
_gtk_css_value_unref (transform->skew_y.skew);
|
||||
break;
|
||||
case GTK_CSS_TRANSFORM_PERSPECTIVE:
|
||||
_gtk_css_value_unref (transform->perspective.depth);
|
||||
break;
|
||||
case GTK_CSS_TRANSFORM_NONE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
@@ -117,7 +125,7 @@ gtk_css_transform_clear (GtkCssTransform *transform)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
gtk_css_transform_init_identity (GtkCssTransform *transform,
|
||||
GtkCssTransformType type)
|
||||
{
|
||||
@@ -152,13 +160,18 @@ gtk_css_transform_init_identity (GtkCssTransform *transform,
|
||||
case GTK_CSS_TRANSFORM_SKEW_Y:
|
||||
transform->skew_y.skew = _gtk_css_number_value_new (0, GTK_CSS_DEG);
|
||||
break;
|
||||
case GTK_CSS_TRANSFORM_PERSPECTIVE:
|
||||
return FALSE;
|
||||
|
||||
case GTK_CSS_TRANSFORM_NONE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
transform->type = type;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GskTransform *
|
||||
@@ -198,7 +211,7 @@ gtk_css_transform_apply (const GtkCssTransform *transform,
|
||||
_gtk_css_number_value_get (transform->scale.x, 1),
|
||||
_gtk_css_number_value_get (transform->scale.y, 1),
|
||||
_gtk_css_number_value_get (transform->scale.z, 1));
|
||||
break;
|
||||
|
||||
case GTK_CSS_TRANSFORM_SKEW:
|
||||
graphene_matrix_init_skew (&skew,
|
||||
_gtk_css_number_value_get (transform->skew.x, 100) / 180.0f * G_PI,
|
||||
@@ -217,6 +230,10 @@ gtk_css_transform_apply (const GtkCssTransform *transform,
|
||||
_gtk_css_number_value_get (transform->skew_y.skew, 100) / 180.0f * G_PI);
|
||||
return gsk_transform_matrix (next, &skew);
|
||||
|
||||
case GTK_CSS_TRANSFORM_PERSPECTIVE:
|
||||
return gsk_transform_perspective (next,
|
||||
_gtk_css_number_value_get (transform->perspective.depth, 100));
|
||||
|
||||
case GTK_CSS_TRANSFORM_NONE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
@@ -303,6 +320,9 @@ gtk_css_transform_compute (GtkCssTransform *dest,
|
||||
case GTK_CSS_TRANSFORM_SKEW_Y:
|
||||
dest->skew_y.skew = _gtk_css_value_compute (src->skew_y.skew, property_id, provider, style, parent_style);
|
||||
return dest->skew_y.skew == src->skew_y.skew;
|
||||
case GTK_CSS_TRANSFORM_PERSPECTIVE:
|
||||
dest->perspective.depth = _gtk_css_value_compute (src->perspective.depth, property_id, provider, style, parent_style);
|
||||
return dest->perspective.depth == src->perspective.depth;
|
||||
case GTK_CSS_TRANSFORM_NONE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
@@ -389,6 +409,8 @@ gtk_css_transform_equal (const GtkCssTransform *transform1,
|
||||
return _gtk_css_value_equal (transform1->skew_x.skew, transform2->skew_x.skew);
|
||||
case GTK_CSS_TRANSFORM_SKEW_Y:
|
||||
return _gtk_css_value_equal (transform1->skew_y.skew, transform2->skew_y.skew);
|
||||
case GTK_CSS_TRANSFORM_PERSPECTIVE:
|
||||
return _gtk_css_value_equal (transform1->perspective.depth, transform2->perspective.depth);
|
||||
case GTK_CSS_TRANSFORM_NONE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
@@ -416,7 +438,8 @@ gtk_css_value_transform_equal (const GtkCssValue *value1,
|
||||
{
|
||||
GtkCssTransform transform;
|
||||
|
||||
gtk_css_transform_init_identity (&transform, larger->transforms[i].type);
|
||||
if (!gtk_css_transform_init_identity (&transform, larger->transforms[i].type))
|
||||
return FALSE;
|
||||
|
||||
if (!gtk_css_transform_equal (&larger->transforms[i], &transform))
|
||||
{
|
||||
@@ -430,6 +453,38 @@ gtk_css_value_transform_equal (const GtkCssValue *value1,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_transform_transition_default (GtkCssTransform *result,
|
||||
const GtkCssTransform *start,
|
||||
const GtkCssTransform *end,
|
||||
guint property_id,
|
||||
double progress)
|
||||
{
|
||||
graphene_matrix_t start_mat, end_mat;
|
||||
GskTransform *trans;
|
||||
|
||||
result->type = GTK_CSS_TRANSFORM_MATRIX;
|
||||
|
||||
if (start)
|
||||
trans = gtk_css_transform_apply (start, NULL);
|
||||
else
|
||||
trans = NULL;
|
||||
gsk_transform_to_matrix (trans, &start_mat);
|
||||
gsk_transform_unref (trans);
|
||||
|
||||
if (end)
|
||||
trans = gtk_css_transform_apply (end, NULL);
|
||||
else
|
||||
trans = NULL;
|
||||
gsk_transform_to_matrix (trans, &end_mat);
|
||||
gsk_transform_unref (trans);
|
||||
|
||||
graphene_matrix_interpolate (&start_mat,
|
||||
&end_mat,
|
||||
progress,
|
||||
&result->matrix.matrix);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_css_transform_transition (GtkCssTransform *result,
|
||||
const GtkCssTransform *start,
|
||||
@@ -473,6 +528,9 @@ gtk_css_transform_transition (GtkCssTransform *result,
|
||||
case GTK_CSS_TRANSFORM_SKEW_Y:
|
||||
result->skew_y.skew = _gtk_css_value_transition (start->skew_y.skew, end->skew_y.skew, property_id, progress);
|
||||
break;
|
||||
case GTK_CSS_TRANSFORM_PERSPECTIVE:
|
||||
gtk_css_transform_transition_default (result, start, end, property_id, progress);
|
||||
break;
|
||||
case GTK_CSS_TRANSFORM_NONE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
@@ -546,25 +604,45 @@ gtk_css_value_transform_transition (GtkCssValue *start,
|
||||
{
|
||||
GtkCssTransform transform;
|
||||
|
||||
gtk_css_transform_init_identity (&transform, start->transforms[i].type);
|
||||
gtk_css_transform_transition (&result->transforms[i],
|
||||
&start->transforms[i],
|
||||
&transform,
|
||||
property_id,
|
||||
progress);
|
||||
gtk_css_transform_clear (&transform);
|
||||
if (gtk_css_transform_init_identity (&transform, start->transforms[i].type))
|
||||
{
|
||||
gtk_css_transform_transition (&result->transforms[i],
|
||||
&start->transforms[i],
|
||||
&transform,
|
||||
property_id,
|
||||
progress);
|
||||
gtk_css_transform_clear (&transform);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_transform_transition_default (&result->transforms[i],
|
||||
&start->transforms[i],
|
||||
NULL,
|
||||
property_id,
|
||||
progress);
|
||||
}
|
||||
}
|
||||
for (; i < end->n_transforms; i++)
|
||||
{
|
||||
GtkCssTransform transform;
|
||||
|
||||
gtk_css_transform_init_identity (&transform, end->transforms[i].type);
|
||||
gtk_css_transform_transition (&result->transforms[i],
|
||||
&transform,
|
||||
&end->transforms[i],
|
||||
property_id,
|
||||
progress);
|
||||
gtk_css_transform_clear (&transform);
|
||||
if (gtk_css_transform_init_identity (&transform, end->transforms[i].type))
|
||||
{
|
||||
gtk_css_transform_transition (&result->transforms[i],
|
||||
&transform,
|
||||
&end->transforms[i],
|
||||
property_id,
|
||||
progress);
|
||||
gtk_css_transform_clear (&transform);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_transform_transition_default (&result->transforms[i],
|
||||
NULL,
|
||||
&end->transforms[i],
|
||||
property_id,
|
||||
progress);
|
||||
}
|
||||
}
|
||||
|
||||
g_assert (i == MAX (start->n_transforms, end->n_transforms));
|
||||
@@ -678,6 +756,11 @@ gtk_css_transform_print (const GtkCssTransform *transform,
|
||||
_gtk_css_value_print (transform->skew_y.skew, string);
|
||||
g_string_append (string, ")");
|
||||
break;
|
||||
case GTK_CSS_TRANSFORM_PERSPECTIVE:
|
||||
g_string_append (string, "perspective(");
|
||||
_gtk_css_value_print (transform->perspective.depth, string);
|
||||
g_string_append (string, ")");
|
||||
break;
|
||||
case GTK_CSS_TRANSFORM_NONE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
@@ -1046,6 +1129,14 @@ gtk_css_transform_parse (GtkCssTransform *transform,
|
||||
if (transform->skew_y.skew == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
else if (_gtk_css_parser_try (parser, "perspective(", TRUE))
|
||||
{
|
||||
transform->type = GTK_CSS_TRANSFORM_PERSPECTIVE;
|
||||
|
||||
transform->perspective.depth = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
|
||||
if (transform->perspective.depth == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
_gtk_css_parser_error (parser, "unknown syntax for transform");
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gsk/gsk.h>
|
||||
#include <gtk/gtkstylecontext.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
#define __GTK_CSS_VALUE_PRIVATE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "gtkcsstypesprivate.h"
|
||||
#include "gtkstyleprovider.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user