Compare commits

..

64 Commits

Author SHA1 Message Date
Matthias Clasen
31ba72bad2 testsuite: Don't print default styles
This somewhat defeats the point that we want
to verify the regulars styles, not some weird
initial conditions.
2020-01-15 08:06:06 -05:00
Matthias Clasen
911528923f css: Mark the default style in debug dumps
This helps identifying unexpected situations,
since the default style should never be seen
in the wild.
2020-01-15 08:06:06 -05:00
Matthias Clasen
968e21158e css: Don't got to the selector tree for change
The tree is optimized for mimizing the decisions, and
that prevents us from taking advantage of the more exact
superset matching that we can do now. So, instead do what
we used to do for verifiation: use the tree for finding the
superset matches, then just walk the rulesets to collect the
changes.
2020-01-15 08:06:06 -05:00
Matthias Clasen
d0f75d9231 css: Avoid computing change too often
Most of the time when styles need to be recreated,
the name and classes of the css node haven't changed.
In this case, the change value will not either, since
we are computing change under the assumption that
name and classes are unchanged, so there is no need
to recompute the change.
2020-01-15 08:06:06 -05:00
Matthias Clasen
d3d5a03da5 Make the superset matcher more exact
When the superset matcher is built from a node matcher,
we can make the parent or previous matchers be superset
matchers for the corresponding node, with the same
relevant parts. This is more precise than the any matcher
that we were returning previously.
2020-01-15 08:06:06 -05:00
Matthias Clasen
133e39d807 Allow printing css matchers
This can help in debugging css matching.
2020-01-15 02:10:30 -05:00
Matthias Clasen
e94fc900b5 cssmatcher: Add a type enum
For now, this just replaces the is_any boolean
by a type field in the class, and does away with
the unused Superset struct.supserset matcher fixup
2020-01-15 02:10:04 -05:00
Matthias Clasen
cd25da9d1a Add selector statistics to the debug output 2020-01-14 22:26:11 -05:00
Matthias Clasen
e1c2aeaccb css: Drop unsused bitmasks
GtkCssProvider was maintaining bitmasks for the
set properties in each ruleset. The masks are never
used, so drop them.
2020-01-14 21:43:23 -05:00
Matthias Clasen
8b2f5ddecc css: Remove an unused function
_gtk_css_style_property_get_mask_affecting was superseded
by GtkCssStyleChange back in 2015.
2020-01-14 21:43:23 -05:00
Matthias Clasen
0813d787b6 cssstyle: Try harder to skip initial values
Compare values against the computed value of their
properties initial value. This works for fine for
all expect the border-width properties, whose special
handling defeats this.
2020-01-14 21:43:23 -05:00
Matthias Clasen
0edd7ca7ad css: Don't return nonsense when comparing values
Comparing icon theme values for equality is not
very important, but an equal() implementation that
always returns FALSE is nonsense.
2020-01-14 21:43:23 -05:00
Matthias Clasen
55dbc5c4ab testsuite: Update expected output for css style tests
These now include the change values.
2020-01-14 21:43:23 -05:00
Matthias Clasen
5b19617e9a testsuite: Improve --generate support
We don't want annoying spew from GTest when
using --generate, since it interferes with just
piping the output to a text file.
2020-01-14 21:43:23 -05:00
Matthias Clasen
004b5aad72 testsuite: Include change in css style tests
This will help debugging css change tracking.
2020-01-14 21:43:23 -05:00
Matthias Clasen
b930aa8bf5 Add a way to dump css node change values
Add a GTK_STYLE_CONTEXT_PRINT_SHOW_CHANGE flag that
tells gtk_style_context_to_string to include the
change values of nodes in the output. This will
help debugging css change tracking.
2020-01-14 21:43:23 -05:00
Matthias Clasen
e1d6f05061 inspector: Show change in the css node tree
This is useful for debugging why we update to damn much
css on enter/leave.
2020-01-14 21:43:23 -05:00
Matthias Clasen
2b7715a0aa Revert "wip: reimplement css matching from scratch"
This reverts commit 7047a2e9c6f32da068bbfef78c6a4bda2d7d39f2.
2020-01-14 21:43:23 -05:00
Matthias Clasen
d72bebf187 wip: reimplement css matching from scratch
First step: Strip out all optimizations.
2020-01-14 21:43:23 -05:00
Matthias Clasen
6be4347558 quiet a compiler warning in release builds 2020-01-14 21:43:23 -05:00
Matthias Clasen
24a0f83194 Add some css style tests
These are meant to test selectors.
2020-01-14 21:43:23 -05:00
Matthias Clasen
3e9960e06f css: Add gtk_css_style_get_static_style
This lets us avoid poking directly at the GtkCssAnimatedStyle
struct in gtkcssnode.c.
2020-01-14 21:43:23 -05:00
Matthias Clasen
4cf2b87654 Speed up gtk_widget_pick
Add early exits, and avoid as much work as
possible.
2020-01-14 21:43:23 -05:00
Matthias Clasen
a5dc2caa13 Revert "css: Faster matching for simple selectors"
This reverts commit 05f7d68e29.
2020-01-14 16:59:27 -05:00
Matthias Clasen
05f7d68e29 css: Faster matching for simple selectors
Inline simple selectors for node matchers.
A bit ugly, but works.
2020-01-14 15:47:30 -05:00
Matthias Clasen
e9eacdeded css: Implement the superset matcher smarter
Instead of wrapping the individual vfuncs, and having
a branch in the inner loop, rewrite the matcher class.
2020-01-14 15:47:30 -05:00
Matthias Clasen
616c0ab8c5 css: Compute selector tree changes ahead of time
These only depend on the selector tree, so we can
compute them while constructing the tree.
2020-01-14 15:47:30 -05:00
Matthias Clasen
792130437e css: Handle initial values more efficiently
Instead of creating a new values every time we
resolve the initial values for dpi and font family,
keep a css value around for the settings.
2020-01-14 15:47:30 -05:00
Matthias Clasen
0afa486d41 css: Mark transform value as computed
This is not very useful, since transitions generate
a ton of transforms anyway.
2020-01-14 15:47:30 -05:00
Matthias Clasen
6e5f56684d css: Simplify default values
We no longer need to create one-element arrays or
corners with two identical values.
2020-01-14 15:47:30 -05:00
Matthias Clasen
52c7a3672e css: Re-add a lost special case
When the border-style special cases were moved in
c687f485fd, the one for outline-width was lost.

Make the code more compact, and bring the special
case back.
2020-01-14 15:47:30 -05:00
Timm Bäder
cfc7540c3b gl renderer: Render simple border nodes in a simple way
Roughly 80% of the border nodes are just one color and have the same
width on all sides, so we can draw them by uploading just one rect and
not four.
2020-01-14 17:32:59 +01:00
Timm Bäder
0d15eb7d01 numbervalue: Add early-out to multiply()
If the factor is 1, we already know what the result is going to be.
2020-01-14 17:32:59 +01:00
Timm Bäder
6d4cecb0c6 cssnumbervalue: Move early-out code to GtkCssValue
These checks make sense for all css values.
2020-01-14 17:32:59 +01:00
Timm Bäder
ada5ff8a91 cssdimensionvalue: Implement transition()
Instead of falling back to the generic gtk_css_number_value_transition
(which can allocate multiple new css values), just implement this here.
2020-01-14 17:32:59 +01:00
Timm Bäder
940910770a testsuite: Remove an invalid test case 2020-01-14 17:32:59 +01:00
Timm Bäder
3a2d6c58ba Remove GtkCssShadowsValue
Previously, we wrapped all GtkCssShadowValues in a GtkCssShadowsValue,
even if it was just one shadow.
2020-01-14 17:32:55 +01:00
Timm Bäder
bac51a05db cssshadowvalue: Only create 2 shadows values for transitions
This is for cases where we want to transition from "no shadow" to
"shadow", which we need quite a lot.
2020-01-14 15:28:19 +01:00
Timm Bäder
9d3704c62a cssdimensionvalue: Allow transitioning between different units...
... as long as one of the two values is 0.
2020-01-14 15:28:17 +01:00
Timm Bäder
5cdeca2e25 cssvalue: Improve css value accounting output
And make it fully optional behind an #ifdef.
2020-01-14 15:28:15 +01:00
Timm Bäder
d3ad97073b csscolorvalue: check for singletons in new_literal
Gets rid of another ~400 GtkCssValue instances in the widget-factory.
2020-01-12 15:53:26 +01:00
Timm Bäder
c2e680f4f0 cssimage: Add is_computed vfunc
Same semantics as the is_computed field of GtkCssValue
2020-01-11 17:17:27 +01:00
Timm Bäder
ab868a3207 css: Set the is_computed flag for more values
With these changes, we skip roughly 85% of compute() calls during
widget-factory startup
2020-01-11 17:17:27 +01:00
Timm Bäder
ab78c19236 cssvalue: Don't call compute() for already computed css values
As per the previous commit, this is unnecessary.

Even with the small amount of css values we mark as is_computed, we
already skip computing over 60% of them like this during the startup of
the widget factory.
2020-01-11 17:17:27 +01:00
Timm Bäder
a3a71c149e cssvalue: Add is_computed flag
When a css value has "child" css values (e.g. a linear gradient has
several color stop css values) which are all computed (won't change when
compute() is called on them), we want to skip computing the entire
subtree.

Since css values are immutable, we can set the is_computed flag at
construct time.

Since GtkCssValue instances are 0-initialized in _gtk_css_value_alloc,
the default for is_computed it FALSE. This commit only sets it to TRUE
in a few cases, such as various "none" singleton values which will never
change. Later commits will refine this and set it for more values.
2020-01-11 17:17:27 +01:00
Timm Bäder
6b6f0856f0 testsuite: Update css color output 2020-01-11 17:17:27 +01:00
Timm Bäder
c687f485fd css: Move border-width special cases out of GtkCssDimensionValue
Move them to style computation instead, so we don't have them in such a
generic place.
2020-01-11 17:17:25 +01:00
Timm Bäder
a5b2ac73c8 csscolorvalue: Don't copy rgbas when applying function
We get const pointers to the colors, so just use those and unref the
values later.
2020-01-11 12:49:00 +01:00
Timm Bäder
b544f7c6bb gl renderer: Look at shadow color in the outset shadow cache
It would probably be better to not do this and always render the outline
in plain white, then later recolor it but do this for no, just for
correctness.
2020-01-11 12:49:00 +01:00
Timm Bäder
a10c5b74a1 cssimageradial: Avoid computing a new image if it didn't change 2020-01-11 12:49:00 +01:00
Timm Bäder
8af3a86dda cssimageradial: Use array + length instead of GArray
This makes sense since we're not going to change the (amount of) colors
after parsing.
2020-01-11 12:49:00 +01:00
Timm Bäder
11a78a0736 cssimagelinear: Don't compute new image if it didn't change 2020-01-11 12:49:00 +01:00
Timm Bäder
b7d9ec73ec cssimagelinear: Use count+array for the color stops, not GArray
This makse sense but will also make later changes to GtkCssImageLinear
simpler.
2020-01-11 12:48:59 +01:00
Timm Bäder
c1a5221941 cssimagefallback: Don't compute new image if only a color is set
Themes might use e.g. image(red), which is a constant value and will
never change. In that case, the fallback image has ->color set, but not
->images. If that's the case and the computed color is the same as
the one we already have, just return the already existing image.
2020-01-11 12:48:59 +01:00
Timm Bäder
7b40541889 Remove GtkCssRgbaValue
The differenciation between a literal color value and an RGBA value
caused problems in various situations. Just treat the two the same but
don't allow access to the rgba value of a non-literal color value.

This gets rid of around 1.6k rgba values in the widget-factory.
2020-01-11 12:48:59 +01:00
Matthias Clasen
2b9e5bdb4b dump css value stats 2020-01-11 12:48:59 +01:00
Timm Bäder
439238c502 csssshadwovalue: Remove unused function prototype 2020-01-11 12:48:59 +01:00
Timm Bäder
e90c499f2c cssnumbervalue: Add early-outs to transition code
we don't need to do the calculation at all if the progress is 0 or 1
anyway.

We also sometimes transition from 0 to 0 etc., so we can short-circuit
that as well by doing the fast pointer-equality check and relying on the
singletons.
2020-01-11 12:48:59 +01:00
Timm Bäder
a3a31d229b csscornervalue: Accept other values if x == y
Most corners are square, so x == y. In that case, just accept either of
them. This makes the corner value unnecessary.

In fact none of the corner values in the widget-factory are needed, so
this spares us around 500 corner value allocations.

css value stats before:

GtkCssBgSizeValue: 23
GtkCssIdentValue: 25
GtkCssPositionValue: 81
GtkCssCornerValue: 556
GtkCssArrayValue: 143
GtkCssStringValue: 33
GtkCssPaletteValue: 29
GtkCssImageValue: 2765
GtkCssColorValue: 1452
GtkCssFilterValue: 3
GtkCssRgbaValue: 1092
GtkCssShadowValue: 708
GtkCssEaseValue: 33
GtkCssBorderValue: 2
GtkCssTransformValue: 11
GtkCssDimensionValue: 882
GtkCssShadowsValue: 584
SUM: 8428

and after:

GtkCssColorValue: 1452
GtkCssFilterValue: 3
GtkCssRgbaValue: 1092
GtkCssShadowValue: 708
GtkCssEaseValue: 33
GtkCssBorderValue: 2
GtkCssTransformValue: 11
GtkCssDimensionValue: 882
GtkCssShadowsValue: 584
GtkCssBgSizeValue: 23
GtkCssIdentValue: 25
GtkCssPositionValue: 81
GtkCssArrayValue: 143
GtkCssStringValue: 33
GtkCssPaletteValue: 29
GtkCssImageValue: 2765
SUM: 7872

8428 to 7872 is a 556 reduction (6.5%)

asdf
2020-01-11 12:48:59 +01:00
Timm Bäder
65344cc3cf cssarrayvalue: Don't allocate memory when parsing array values
We probably won't find CSS with more than 128 values in array.
2020-01-11 12:48:55 +01:00
Timm Bäder
a26c615305 cssarrayvalue: Allow calling array API on non-arrays
Just allow calling _get_nth() and _get_n_values() on every kind of css
value. This way we can allow all values in places where only array
values would be allowed before.

This spares us around 1000 array values in the widget factory.

css value stats before:

GtkCssFilterValue: 3
GtkCssRgbaValue: 1092
GtkCssShadowValue: 708
GtkCssEaseValue: 33
GtkCssBorderValue: 2
GtkCssTransformValue: 11
GtkCssDimensionValue: 882
GtkCssShadowsValue: 584
GtkCssBgSizeValue: 23
GtkCssIdentValue: 25
GtkCssPositionValue: 81
GtkCssCornerValue: 556
GtkCssArrayValue: 1130
GtkCssStringValue: 33
GtkCssPaletteValue: 29
GtkCssImageValue: 2765
GtkCssColorValue: 1452
SUM: 9415

and after:

GtkCssBgSizeValue: 23
GtkCssIdentValue: 25
GtkCssPositionValue: 81
GtkCssCornerValue: 556
GtkCssArrayValue: 143
GtkCssStringValue: 33
GtkCssPaletteValue: 29
GtkCssImageValue: 2765
GtkCssColorValue: 1452
GtkCssFilterValue: 3
GtkCssRgbaValue: 1092
GtkCssShadowValue: 708
GtkCssEaseValue: 33
GtkCssBorderValue: 2
GtkCssTransformValue: 11
GtkCssDimensionValue: 882
GtkCssShadowsValue: 584
SUM: 8428

9415 to 8428 is a 987 reduction (10.4%)
2020-01-11 08:09:17 +01:00
Timm Bäder
37a559ffe5 cssvalue: Add type names for all classes
This is important to have for debugging and e.g. to print statistics for
the individual css value types
2020-01-11 08:09:17 +01:00
Timm Bäder
5a12448f9a csscolorvalue: Compute alpha/shade/mix of color literals directly
The values of these are never gonna change so we can as well create
literal color values from the resulting colors instead.
2020-01-11 08:09:17 +01:00
Timm Bäder
6b19f493ab csscolorvalue: Don't resolve literal color values 2020-01-11 08:09:16 +01:00
1312 changed files with 75523 additions and 59372 deletions

View File

@@ -1,11 +0,0 @@
# See https://wiki.apertis.org/Guidelines/Coding_conventions#Code_formatting
BasedOnStyle: GNU
AlwaysBreakAfterDefinitionReturnType: All
BreakBeforeBinaryOperators: None
BinPackParameters: false
SpaceAfterCStyleCast: true
# Our column limit is actually 80, but setting that results in clang-format
# making a lot of dubious hanging-indent choices; disable it and assume the
# developer will line wrap appropriately. clang-format will still check
# existing hanging indents.
ColumnLimit: 0

View File

@@ -1,8 +1,7 @@
stages:
- style-check
- build
- deploy
- flatpak
# - deploy
.cache-paths: &cache-paths
paths:
@@ -13,45 +12,16 @@ stages:
- subprojects/libepoxy/
- subprojects/pango/
# Common variables
variables:
COMMON_MESON_FLAGS: "--fatal-meson-warnings --werror"
MESON_TEST_TIMEOUT_MULTIPLIER: 2
.only-default:
only:
- branches
except:
- tags
style-check-diff:
extends: .only-default
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v13
stage: style-check
allow_failure: true
script:
- .gitlab-ci/run-style-check-diff.sh
fedora-x86_64:
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v13
fedora-x86_64: &fedora-x86_64-defaults
image: registry.gitlab.gnome.org/gnome/gtk/master:v8
stage: build
variables:
EXTRA_MESON_FLAGS: "--buildtype=debug --default-library=both"
script:
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS}
-Dx11-backend=true
-Dwayland-backend=true
-Dbroadway-backend=true
-Dvulkan=yes
-Dprofiler=true
_build
- ninja -C _build
- .gitlab-ci/run-tests.sh _build
- bash -x ./.gitlab-ci/test-docker.sh
artifacts:
when: always
reports:
junit:
- "${CI_PROJECT_DIR}/_build/report.xml"
- "${CI_PROJECT_DIR}/_build/report.xml"
name: "gtk-${CI_COMMIT_REF_NAME}"
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
@@ -59,41 +29,14 @@ fedora-x86_64:
- "${CI_PROJECT_DIR}/_build/report.html"
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*.png"
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*.png"
- "${CI_PROJECT_DIR}/_build/testsuite/css/output/*.syscap"
cache:
key: "$CI_JOB_NAME"
<<: *cache-paths
release-build:
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v13
stage: build
fedora-x86_64-staticlibs:
variables:
EXTRA_MESON_FLAGS: "--buildtype=release"
script:
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS}
-Dx11-backend=true
-Dwayland-backend=true
-Dbroadway-backend=true
-Dvulkan=yes
_build
- ninja -C _build
- .gitlab-ci/run-tests.sh _build
artifacts:
when: always
reports:
junit:
- "${CI_PROJECT_DIR}/_build/report.xml"
name: "gtk-${CI_COMMIT_REF_NAME}"
paths:
- "${CI_PROJECT_DIR}/_build/meson-logs"
- "${CI_PROJECT_DIR}/_build/report.xml"
- "${CI_PROJECT_DIR}/_build/report.html"
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*.png"
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*.png"
- "${CI_PROJECT_DIR}/_build/testsuite/css/output/*.syscap"
cache:
key: "$CI_JOB_NAME"
<<: *cache-paths
EXTRA_MESON_FLAGS: "-Ddefault_library=both"
<<: *fedora-x86_64-defaults
.mingw-defaults: &mingw-defaults
stage: build
@@ -115,9 +58,6 @@ msys2-mingw32:
.flatpak-defaults: &flatpak-defaults
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
stage: flatpak
allow_failure: true
tags:
- flatpak
artifacts:
paths:
- "${APPID}-dev.flatpak"
@@ -166,20 +106,19 @@ flatpak-master:icon-browser:
APPID: org.gtk.IconBrowser4
<<: *flatpak-master
pages:
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v13
stage: deploy
variables:
EXTRA_MESON_FLAGS: "--buildtype=release"
script:
- meson ${COMMON_MESON_FLAGS} -Dgtk_doc=true _build
- ninja -C _build gdk4-doc gsk4-doc gtk4-doc
- mkdir -p public/
- mv _build/docs/reference/gdk/html/ public/gdk/
- mv _build/docs/reference/gsk/html/ public/gsk/
- mv _build/docs/reference/gtk/html/ public/gtk/
artifacts:
paths:
- public
only:
- master
#pages:
# image: registry.gitlab.gnome.org/gnome/gtk/master:v6
# stage: deploy
# script:
# - meson -Dgtk_doc=true _build .
# - ninja -C _build
# - ninja -C _build gdk4-doc gsk4-doc gtk4-doc
# - mkdir -p public/
# - mv _build/docs/reference/gtk/html/ public/gtk/
# - mv _build/docs/reference/gdk/html/ public/gdk/
# - mv _build/docs/reference/gsk/html/ public/gsk/
# artifacts:
# paths:
# - public
# only:
# - master

View File

@@ -8,7 +8,6 @@ RUN dnf -y install \
cairo-devel \
cairo-gobject-devel \
ccache \
clang \
colord-devel \
cups-devel \
dbus-daemon \
@@ -24,7 +23,6 @@ RUN dnf -y install \
gettext \
git \
glib2-devel \
glib2-static \
glibc-devel \
glibc-headers \
gobject-introspection-devel \
@@ -63,15 +61,12 @@ RUN dnf -y install \
ninja-build \
pango-devel \
pcre-devel \
pcre-static \
python3 \
python3-jinja2 \
python3-pip \
python3-pygments \
python3-wheel \
redhat-rpm-config \
sassc \
sysprof-devel \
systemtap-sdt-devel \
vulkan-devel \
wayland-devel \
@@ -80,7 +75,7 @@ RUN dnf -y install \
xorg-x11-server-Xvfb \
&& dnf clean all
RUN pip3 install meson==0.52.1
RUN pip3 install meson==0.50.1
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}

View File

@@ -1,38 +0,0 @@
## GTK CI infrastructure
GTK uses different CI images depending on platform and jobs.
The CI images are Docker containers, generated either using `docker` or
`podman`, and pushed to the GitLab [container registry][registry].
Each Docker image has a tag composed of two parts:
- `${image}`: the base image for a given platform, like "fedora" or
"debian-stable"
- `${number}`: an incremental version number, or `latest`
See the [container registry][registry] for the available images for each
branch, as well as their available versions.
### Checklist for Updating a CI image
- [ ] Update the `${image}.Dockerfile` file with the dependencies
- [ ] Run `./run-docker.sh build --base ${image} --base-version ${number}`
- [ ] Run `./run-docker.sh push --base ${image} --base-version ${number}`
once the Docker image is built; you may need to log in by using
`docker login` or `podman login`
- [ ] Update the `image` keys in the `.gitlab-ci.yml` file with the new
image tag
- [ ] Open a merge request with your changes and let it run
### Checklist for Adding a new CI image
- [ ] Write a new `${image}.Dockerfile` with the instructions to set up
a build environment
- [ ] Add the `pip3 install meson` incantation
- [ ] Run `./run-docker.sh build --base ${image} --base-version ${number}`
- [ ] Run `./run-docker.sh push --base ${image} --base-version ${number}`
- [ ] Add the new job to `.gitlab-ci.yml` referencing the image
- [ ] Open a merge request with your changes and let it run
[registry]: https://gitlab.gnome.org/GNOME/gtk/container_registry

View File

@@ -1,133 +0,0 @@
#!/usr/bin/env python3
#
# === clang-format-diff.py - ClangFormat Diff Reformatter ---*- python -*-=== #
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# ===---------------------------------------------------------------------=== #
"""
This script reads input from a unified diff and reformats all the changed
lines. This is useful to reformat all the lines touched by a specific patch.
Example usage for git/svn users:
git diff -U0 --no-color HEAD^ | clang-format-diff.py -p1 -i
svn diff --diff-cmd=diff -x-U0 | clang-format-diff.py -i
"""
from __future__ import absolute_import, division, print_function
import argparse
import difflib
import re
import subprocess
import sys
if sys.version_info.major >= 3:
from io import StringIO
else:
from io import BytesIO as StringIO
def main():
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-i', action='store_true', default=False,
help='apply edits to files instead of displaying a '
'diff')
parser.add_argument('-p', metavar='NUM', default=0,
help='strip the smallest prefix containing P slashes')
parser.add_argument('-regex', metavar='PATTERN', default=None,
help='custom pattern selecting file paths to reformat '
'(case sensitive, overrides -iregex)')
parser.add_argument('-iregex', metavar='PATTERN',
default=r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hh|hpp|m|mm|inc'
r'|js|ts|proto|protodevel|java|cs)',
help='custom pattern selecting file paths to reformat '
'(case insensitive, overridden by -regex)')
parser.add_argument('-sort-includes', action='store_true', default=False,
help='let clang-format sort include blocks')
parser.add_argument('-v', '--verbose', action='store_true',
help='be more verbose, ineffective without -i')
parser.add_argument('-style',
help='formatting style to apply (LLVM, Google, '
'Chromium, Mozilla, WebKit)')
parser.add_argument('-binary', default='clang-format',
help='location of binary to use for clang-format')
args = parser.parse_args()
# Extract changed lines for each file.
filename = None
lines_by_file = {}
for line in sys.stdin:
match = re.search(r'^\+\+\+\ (.*?/){%s}(\S*)' % args.p, line)
if match:
filename = match.group(2)
if filename is None:
continue
if args.regex is not None:
if not re.match('^%s$' % args.regex, filename):
continue
else:
if not re.match('^%s$' % args.iregex, filename, re.IGNORECASE):
continue
match = re.search(r'^@@.*\+(\d+)(,(\d+))?', line)
if match:
start_line = int(match.group(1))
line_count = 1
if match.group(3):
line_count = int(match.group(3))
if line_count == 0:
continue
end_line = start_line + line_count - 1
lines_by_file.setdefault(filename, []).extend(
['-lines', str(start_line) + ':' + str(end_line)])
# Reformat files containing changes in place.
# We need to count amount of bytes generated in the output of
# clang-format-diff. If clang-format-diff doesn't generate any bytes it
# means there is nothing to format.
format_line_counter = 0
for filename, lines in lines_by_file.items():
if args.i and args.verbose:
print('Formatting {}'.format(filename))
command = [args.binary, filename]
if args.i:
command.append('-i')
if args.sort_includes:
command.append('-sort-includes')
command.extend(lines)
if args.style:
command.extend(['-style', args.style])
p = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=None,
stdin=subprocess.PIPE,
universal_newlines=True)
stdout, _ = p.communicate()
if p.returncode != 0:
sys.exit(p.returncode)
if not args.i:
with open(filename) as f:
code = f.readlines()
formatted_code = StringIO(stdout).readlines()
diff = difflib.unified_diff(code, formatted_code,
filename, filename,
'(before formatting)',
'(after formatting)')
diff_string = ''.join(diff)
if diff_string:
format_line_counter += sys.stdout.write(diff_string)
if format_line_counter > 0:
sys.exit(1)
if __name__ == '__main__':
main()

View File

@@ -4,19 +4,20 @@ set -e
appid=$1
builddir=flatpak_app
builddir=app
repodir=repo
flatpak-builder \
--user --disable-rofiles-fuse \
--stop-at=gtk \
${builddir} \
build-aux/flatpak/${appid}.json
flatpak build ${builddir} meson \
--prefix=/app \
--libdir=/app/lib \
--buildtype=release \
flatpak-builder \
--run ${builddir} build-aux/flatpak/${appid}.json \
meson \
--prefix /app \
--libdir /app/lib \
--buildtype debug \
-Dx11-backend=true \
-Dwayland-backend=true \
-Dprint-backends=file \
@@ -24,12 +25,13 @@ flatpak build ${builddir} meson \
-Dbuild-examples=false \
-Dintrospection=false \
-Ddemos=true \
_flatpak_build
flatpak build ${builddir} ninja -C _flatpak_build install
_build .
flatpak-builder \
--run ${builddir} build-aux/flatpak/${appid}.json \
ninja -C _build install
flatpak-builder \
--user --disable-rofiles-fuse \
--finish-only \
--repo=${repodir} \
${builddir} \
@@ -38,5 +40,5 @@ flatpak-builder \
flatpak build-bundle \
${repodir} \
${appid}-dev.flatpak \
--runtime-repo=https://nightly.gnome.org/gnome-nightly.flatpakrepo \
--runtime-repo=https://flathub.org/repo/flathub.flatpakrepo \
${appid}

View File

@@ -138,25 +138,22 @@ ul.images li {
</head>
<body>
<header>
<h1>{{ report.project_name }}/{{ report.branch_name }} :: Test Reports</h1>
<h1>{{ report.project_name }} :: Test Reports</h1>
<div class="report-meta">
<p><strong>Branch:</strong> {{ report.branch_name }}</p>
<p><strong>Date:</strong> <time datetime="{{ report.date.isoformat() }}">{{ report.locale_date }}</time></p>
{% if report.job_id %}<p><strong>Job ID:</strong> {{ report.job_id }}</p>{% endif %}
</div>
</header>
<article>
<section>
<div class="report-meta">
<p><strong>Branch:</strong> {{ report.branch_name }}</p>
<p><strong>Date:</strong> <time datetime="{{ report.date.isoformat() }}">{{ report.locale_date }}</time></p>
{% if report.job_id %}<p><strong>Job ID:</strong> {{ report.job_id }}</p>{% endif %}
</div>
</section>
<section>
<div class="summary">
<h3><a name="summary">Summary</a></h3>
<ul>
<li><strong>Total units:</strong> {{ report.total_units }}</li>
<li><strong>Failed:</strong> {{ report.total_failures }}</li>
<li><strong>Passed:</strong> {{ report.total_successes }}</li>
<li><strong>Passed:</strong> <a href="#passed">{{ report.total_successes }}</a></li>
<li><strong>Failed:</strong> <a href="#failures">{{ report.total_failures }}</a></li>
</ul>
</div>
</section>
@@ -167,56 +164,12 @@ ul.images li {
<h3><a name="results">Suite: {{ suite_result.suite_name }}</a></h3>
<ul>
<li><strong>Units:</strong> {{ suite_result.n_units }}</li>
<li><strong>Failed:</strong> <a href="#{{ suite_result.suite_name }}-failed">{{ suite_result.n_failures }}</a></li>
<li><strong>Passed:</strong> <a href="#{{ suite_result.suite_name }}-passed">{{ suite_result.n_successes }}</a></li>
<li><strong>Passed:</strong> {{ suite_result.n_successes }}</li>
<li><strong>Failed:</strong> {{ suite_result.n_failures }}</li>
</ul>
<div class="failures">
<h4><a name="{{ suite_result.suite_name }}-failed">Failures</a></h4>
<ul class="failed">
{% for failure in suite_result.failures if failure.result in [ 'FAIL', 'UNEXPECTEDPASS' ] %}
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
{% if failure.stdout %}
Output: <pre>{{ failure.stdout }}</pre>
{% endif %}
{% if failure.image_data is defined %}
<ul class="images">
<li><img alt="ref" src="{{ failure.image_data.ref }}" /></li>
<li><img alt="out" src="{{ failure.image_data.out }}" /></li>
<li><img alt="diff" src="{{ failure.image_data.diff }}" /></li>
</ul>
{% endif %}
</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
<h4><a name="{{ suite_result.suite_name }}-timed-out">Timed out</a></h4>
<ul class="failed">
{% for failure in suite_result.failures if failure.result == 'TIMEOUT' %}
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
{% if failure.stdout %}
Output: <pre>{{ failure.stdout }}</pre>
{% endif %}
</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
</div>
<div class="successes">
<h4><a name="{{ suite_result.suite_name }}-skipped">Skipped</a></h4>
<ul>
{% for success in suite_result.successes if success.result == 'SKIP' %}
<li>{{ success.name }} - result: <span class="result skip">{{ success.result }}</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
<h4><a name="{{ suite_result.suite_name }}-passed">Passed</a></h4>
<h4><a name="passed">Passed</a></h4>
<ul class="passed">
{% for success in suite_result.successes if success.result == 'OK' %}
<li>{{ success.name }} - result: <span class="result pass">{{ success.result }}</li>
@@ -225,7 +178,16 @@ ul.images li {
{% endfor %}
</ul>
<h4><a name="{{ suite_result.suite_name }}-expected-fail">Expected failures</a></h4>
<h4><a name="skipped">Skipped</a></h4>
<ul>
{% for success in suite_result.successes if success.result == 'SKIP' %}
<li>{{ success.name }} - result: <span class="result skip">{{ success.result }}</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
<h4><a name="expected-fail">Expected failures</a></h4>
<ul>
{% for success in suite_result.successes if success.result == 'EXPECTEDFAIL' %}
<li><a name="{{ success.name }}">{{ success.name }}</a> - result: <span class="result xfail">{{ success.result }}</span><br/>
@@ -246,6 +208,41 @@ ul.images li {
</ul>
</div>
<div class="failures">
<h4><a name="failed">Failed</a></h4>
<ul class="failed">
{% for failure in suite_result.failures if failure.result == 'FAIL' %}
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
{% if failure.stdout %}
Output: <pre>{{ failure.stdout }}</pre>
{% endif %}
{% if failure.image_data is defined %}
<ul class="images">
<li><img alt="ref" src="{{ failure.image_data.ref }}" /></li>
<li><img alt="out" src="{{ failure.image_data.out }}" /></li>
<li><img alt="diff" src="{{ failure.image_data.diff }}" /></li>
</ul>
{% endif %}
</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
<h4><a name="timed-out">Timed out</a></h4>
<ul class="failed">
{% for failure in suite_result.failures if failure.result == 'TIMEOUT' %}
<li><a name="{{ failure.name }}">{{ failure.name }}</a> - result: <span class="result fail">{{ failure.result }}</span><br/>
{% if failure.stdout %}
Output: <pre>{{ failure.stdout }}</pre>
{% endif %}
</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
</div>
</div>
</section>
{% endfor %}
@@ -331,7 +328,7 @@ for name, units in suites.items():
print('Processing {} suite {}:'.format(project_name, suite_name))
def if_failed(unit):
if unit['result'] in ['FAIL', 'UNEXPECTEDPASS', 'TIMEOUT']:
if unit['result'] in ['FAIL', 'TIMEOUT']:
return True
return False

View File

@@ -51,7 +51,6 @@ for line in args.infile:
duration = data['duration']
return_code = data['returncode']
result = data['result']
log = data['stdout']
unit = {
@@ -59,7 +58,6 @@ for line in args.infile:
'name': unit_name,
'duration': duration,
'returncode': return_code,
'result': result,
'stdout': log,
}
@@ -70,12 +68,12 @@ for name, units in suites.items():
print('Processing suite {} (units: {})'.format(name, len(units)))
def if_failed(unit):
if unit['result'] in ['FAIL', 'UNEXPECTEDPASS', 'TIMEOUT']:
if unit['returncode'] != 0:
return True
return False
def if_succeded(unit):
if unit['result'] in ['OK', 'EXPECTEDFAIL', 'SKIP']:
if unit['returncode'] == 0:
return True
return False

View File

@@ -1,130 +1,11 @@
#!/bin/bash
read_arg() {
# $1 = arg name
# $2 = arg value
# $3 = arg parameter
local rematch='^[^=]*=(.*)$'
if [[ $2 =~ $rematch ]]; then
read "$1" <<< "${BASH_REMATCH[1]}"
else
read "$1" <<< "$3"
# There is no way to shift our callers args, so
# return 1 to indicate they should do it instead.
return 1
fi
}
set -e
build=0
run=0
push=0
list=0
print_help=0
no_login=0
TAG="registry.gitlab.gnome.org/gnome/gtk/master:v7"
while (($# > 0)); do
case "${1%%=*}" in
build) build=1;;
run) run=1;;
push) push=1;;
list) list=1;;
help) print_help=1;;
--base|-b) read_arg base "$@" || shift;;
--base-version) read_arg base_version "$@" || shift;;
--no-login) no_login=1;;
*) echo -e "\e[1;31mERROR\e[0m: Unknown option '$1'"; exit 1;;
esac
shift
done
if [ $print_help == 1 ]; then
echo "$0 - Build and run Docker images"
echo ""
echo "Usage: $0 <command> [options] [basename]"
echo ""
echo "Available commands"
echo ""
echo " build --base=<BASENAME> - Build Docker image <BASENAME>.Dockerfile"
echo " run --base=<BASENAME> - Run Docker image <BASENAME>"
echo " push --base=<BASENAME> - Push Docker image <BASENAME> to the registry"
echo " list - List available images"
echo " help - This help message"
echo ""
exit 0
fi
cd "$(dirname "$0")"
if [ $list == 1 ]; then
echo "Available Docker images:"
for f in *.Dockerfile; do
filename=$( basename -- "$f" )
basename="${filename%.*}"
echo -e " \e[1;39m$basename\e[0m"
done
exit 0
fi
# All commands after this require --base to be set
if [ -z $base ]; then
echo "Usage: $0 <command>"
exit 1
fi
if [ ! -f "$base.Dockerfile" ]; then
echo -e "\e[1;31mERROR\e[0m: Dockerfile for '$base' not found"
exit 1
fi
if [ -z $base_version ]; then
base_version="latest"
else
base_version="v$base_version"
fi
TAG="registry.gitlab.gnome.org/gnome/gtk/${base}:${base_version}"
if [ $build == 1 ]; then
if docker --help |& grep -q podman; then
# Docker is actually implemented by podman, and its OCI output
# is incompatible with some of the dockerd instances on GitLab
# CI runners.
format="--format docker"
else
format=""
fi
echo -e "\e[1;32mBUILDING\e[0m: ${base} as ${TAG}"
sudo docker build \
${format} \
--build-arg HOST_USER_ID="$UID" \
--tag "${TAG}" \
--file "${base}.Dockerfile" .
exit $?
fi
if [ $push == 1 ]; then
echo -e "\e[1;32mPUSHING\e[0m: ${base} as ${TAG}"
if [ $no_login == 0 ]; then
sudo docker login registry.gitlab.gnome.org
fi
sudo docker push $TAG
exit $?
fi
if [ $run == 1 ]; then
echo -e "\e[1;32mRUNNING\e[0m: ${base} as ${TAG}"
sudo docker run \
--rm \
--volume "$(pwd)/..:/home/user/app" \
--workdir "/home/user/app" \
--tty \
--interactive "${TAG}" \
bash
exit $?
fi
sudo docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \
--file "Dockerfile" .
sudo docker run --rm --security-opt label=disable \
--volume "$(pwd)/..:/home/user/app" --workdir "/home/user/app" \
--tty --interactive "${TAG}" bash

View File

@@ -1,34 +0,0 @@
#!/bin/bash
set +e
# We need to add a new remote for the upstream master, since this script could
# be running in a personal fork of the repository which has out of date branches.
git remote add upstream https://gitlab.gnome.org/GNOME/gtk.git
git fetch upstream
# Work out the newest common ancestor between the detached HEAD that this CI job
# has checked out, and the upstream target branch (which will typically be
# `upstream/master` or `upstream/gtk-3-24`).
#
# `${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}` is only defined if were running in
# a merge request pipeline; fall back to `${CI_DEFAULT_BRANCH}` otherwise.
newest_common_ancestor_sha=$(diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent upstream/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}) <(git rev-list --first-parent HEAD) | head -1)
git diff -U0 --no-color "${newest_common_ancestor_sha}" | .gitlab-ci/clang-format-diff.py -binary "clang-format" -p1
# The style check is not infallible. The clang-format configuration cannot
# perfectly describe GTKs coding style: in particular, it cannot align
# function arguments. The documented coding style for GTK takes priority over
# clang-format suggestions. Hopefully we can eventually improve clang-format to
# be configurable enough for our coding style. Thats why this CI check is OK
# to fail: the idea is that people can look through the output and ignore it if
# its wrong. (That situation can also happen if someone touches pre-existing
# badly formatted code and it doesnt make sense to tidy up the wider coding
# style with the changes theyre making.)
echo ""
echo "Note that clang-format output is advisory and cannot always match the"
echo "GTK coding style, documented at:"
echo " https://gitlab.gnome.org/GNOME/gtk/blob/master/docs/CODING-STYLE"
echo "Warnings from this tool can be ignored in favour of the documented "
echo "coding style, or in favour of matching the style of existing"
echo "surrounding code."

View File

@@ -1,34 +0,0 @@
#!/bin/bash
set +x
set +e
srcdir=$( pwd )
builddir=$1
export GDK_BACKEND=x11
xvfb-run -a -s "-screen 0 1024x768x24" \
meson test -C ${builddir} \
--print-errorlogs \
--suite=gtk \
--no-suite=gtk:a11y
# Store the exit code for the CI run, but always
# generate the reports
exit_code=$?
cd ${builddir}
$srcdir/.gitlab-ci/meson-junit-report.py \
--project-name=gtk \
--job-id="${CI_JOB_NAME}" \
--output=report.xml \
meson-logs/testlog.json
$srcdir/.gitlab-ci/meson-html-report.py \
--project-name=gtk \
--job-id="${CI_JOB_NAME}" \
--reftest-output-dir="testsuite/reftests/output" \
--output=report.html \
meson-logs/testlog.json
exit $exit_code

View File

@@ -16,7 +16,6 @@ meson \
-Dwayland-backend=true \
-Dbroadway-backend=true \
-Dvulkan=yes \
-Dprofiler=true \
--werror \
${EXTRA_MESON_FLAGS:-} \
_build $srcdir

80
NEWS
View File

@@ -1,81 +1,3 @@
Overview of Changes in GTK 3.98.0
=================================
While this release gets significantly closer to what we aim for in GTK 4,
there are still a few big items outstanding that we are currently working
on:
- Event controllers for keyboard shortcuts
- Movable popovers
- Row-recycling list and grid views
- Revamped accessibility infrastructure
- Animation API
We will do further 3.98.x snapshots as these land.
*****************
* The DND refactoring has been completed. The GTK API for DND has been turned
into event controllers: GtkDragSource and GtkDropTarget. Support for file
transfers via file transfer portal has been added for both DND and the clipboard.
* Child surfaces have been removed. GDK only supports toplevel and popup surfaces
now. The client-side window implementation has been removed too. On the GTK side,
the GtkNative interface has been introduced for widgets that have their own
surface. This cleanup is not 100% complete yet.
* Global positions and related apis such as gdk_surface_move are no longer available.
* A constraint-based layout manager has been added.
* Many classes have been made explicitly non-subclassable, and the widget hierarchy
has been simplified, by making widgets derive directly from GtkWidget instead of
a container.
* Menu-related changes:
- GtkMenu, GtkMenuBar and related classes have been removed. They are being replaced
by GMenu and popover-based variants. Popover menus can now do traditional, nested
menus, and model buttons show accelerators.
- Context menus are no longer created with ::populate-popup signals, but use menu
models and actions.
- Widget actions can be created in class_init, with gtk_widget_class_install_action.
- GtkToolbar has been removed as well.
* Text-related changed:
- Text cursor blinking has been made smooth.
- GtkTextView is caching rendernodes for the visible text range now, improving the
scrolling performance of text.
- Add a simple undo stack for text edits has been added.
* The native Win32 filechooser backend supports choices.
* GtkTreeView renders tree and grid lines with textures.
* GtkEmojiChooser has been made public.
* GtkGestureMultiPress has been renamed to GtkGestureClick.
* GtkWidget has api to handle style classes: gtk_widget_add_style_class.
This is the first step towards moving away from GtkStyleContext.
* X11-specific changes:
- XI2 is now mandatory
- The xim input method has been removed
* Wayland-specific changes:
- The loading of cursor themes has been improved to load cursors on demand,
and no longer relies on libwayland-cursor.
* The GL renderer is now sharing icon and glyph caches for all surfaces,
and has better support for blurring and shadow rendering.
* Performance-related changes:
- GTK provides profiling information for Sysprof when launched with GTK_TRACE=1.
- Css computation has been optimized
- Css lookups are using a Bloom filter
- Icon loading IO has been moved to a thread
Overview of Changes in GTK+ 3.96.0
==================================
@@ -438,7 +360,7 @@ Overview of Changes in GTK+ 3.92.1, 重庆市
The bulk of the preparation for this release was done during
and after the fantastic GNOME.Asia Summit 2017 in Chongqing, China.
* Drop autotools support. Meson 0.42.1 is now required
* Drop autotools support. Meson 0.42.1 is now required
* Implement most of CSS3 font-variant

View File

@@ -54,36 +54,6 @@
}
]
},
{
"name" : "libsass",
"buildsystem" : "meson",
"builddir" : true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/libsass.git",
"branch" : "meson"
}
]
},
{
"name" : "sassc",
"buildsystem" : "meson",
"builddir" : true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/sassc.git",
"branch" : "meson"
}
]
},
{
"name": "gtk",
"buildsystem": "meson",

View File

@@ -54,36 +54,6 @@
}
]
},
{
"name" : "libsass",
"buildsystem" : "meson",
"builddir" : true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/libsass.git",
"branch" : "meson"
}
]
},
{
"name" : "sassc",
"buildsystem" : "meson",
"builddir" : true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/sassc.git",
"branch" : "meson"
}
]
},
{
"name": "gtk",
"buildsystem": "meson",

View File

@@ -54,36 +54,6 @@
}
]
},
{
"name" : "libsass",
"buildsystem" : "meson",
"builddir" : true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/libsass.git",
"branch" : "meson"
}
]
},
{
"name" : "sassc",
"buildsystem" : "meson",
"builddir" : true,
"config-opts": [
"--libdir=/app/lib"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/lazka/sassc.git",
"branch" : "meson"
}
]
},
{
"name": "gtk",
"buildsystem": "meson",

View File

@@ -221,12 +221,9 @@ open_cb (GtkWidget *button,
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Load",
"_Cancel");
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
GFile *cwd = g_file_new_for_path (".");
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
g_object_unref (cwd);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), self);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
}
@@ -293,20 +290,14 @@ save_response_cb (GtkNativeDialog *dialog,
if (response == GTK_RESPONSE_ACCEPT)
{
GListModel *model;
GFile *file;
char *text;
char *text, *filename;
GError *error = NULL;
model = constraint_view_get_model (CONSTRAINT_VIEW (self->view));
text = serialize_model (model);
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
g_file_replace_contents (file, text, -1,
NULL, FALSE,
G_FILE_CREATE_NONE,
NULL,
NULL,
&error);
if (error != NULL)
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
if (!g_file_set_contents (filename, text, -1, &error))
{
GtkWidget *dialog;
@@ -321,9 +312,7 @@ save_response_cb (GtkNativeDialog *dialog,
gtk_widget_show (dialog);
g_error_free (error);
}
g_free (text);
g_object_unref (file);
g_free (filename);
}
gtk_native_dialog_destroy (dialog);
@@ -340,12 +329,9 @@ save_cb (GtkWidget *button,
GTK_FILE_CHOOSER_ACTION_SAVE,
"_Save",
"_Cancel");
gtk_native_dialog_set_modal (GTK_NATIVE_DIALOG (dialog), TRUE);
GFile *cwd = g_file_new_for_path (".");
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
g_object_unref (cwd);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
g_signal_connect (dialog, "response", G_CALLBACK (save_response_cb), self);
gtk_native_dialog_show (GTK_NATIVE_DIALOG (dialog));
}
@@ -414,7 +400,7 @@ edit_constraint (ConstraintEditorWindow *win,
ConstraintEditor *editor;
GListModel *model;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
if (constraint)
@@ -454,7 +440,7 @@ edit_guide (ConstraintEditorWindow *win,
GtkWidget *window;
GuideEditor *editor;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
gtk_window_set_title (GTK_WINDOW (window), "Edit Guide");

View File

@@ -14,7 +14,7 @@ typedef struct {
GtkWidget *message;
GtkWidget *infobar;
GtkWidget *status;
GtkWidget *menubutton;
GtkWidget *menutool;
GMenuModel *toolmenu;
GtkTextBuffer *buffer;
@@ -428,8 +428,8 @@ demo_application_window_init (DemoApplicationWindow *window)
gtk_widget_init_template (GTK_WIDGET (window));
popover = gtk_popover_menu_new_from_model (window->menubutton, window->toolmenu);
gtk_menu_button_set_popover (GTK_MENU_BUTTON (window->menubutton), popover);
popover = gtk_popover_menu_new_from_model (window->menutool, window->toolmenu);
gtk_menu_tool_button_set_popover (GTK_MENU_TOOL_BUTTON (window->menutool), popover);
g_action_map_add_action_entries (G_ACTION_MAP (window),
win_entries, G_N_ELEMENTS (win_entries),
@@ -528,7 +528,7 @@ demo_application_window_class_init (DemoApplicationWindowClass *class)
gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, infobar);
gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, status);
gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, buffer);
gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, menubutton);
gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, menutool);
gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, toolmenu);
gtk_widget_class_bind_template_callback (widget_class, clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, update_statusbar);

View File

@@ -8,24 +8,27 @@
<child>
<object class="GtkGrid">
<child>
<object class="GtkBox">
<object class="GtkToolbar">
<property name="hexpand">1</property>
<style>
<class name="primary-toolbar"/>
</style>
<child>
<object class="GtkMenuButton" id="menubutton">
<object class="GtkMenuToolButton" id="menutool">
<property name="icon-name">document-open</property>
</object>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="icon-name">application-exit</property>
<property name="action-name">app.quit</property>
</object>
</child>
<child>
<object class="GtkSeparator"/>
<object class="GtkSeparatorToolItem"/>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="icon-name">applications-other</property>
<property name="action-name">win.logo</property>
</object>

View File

@@ -63,6 +63,7 @@ GtkWidget *
do_builder (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
GtkWidget *toolbar;
GActionGroup *actions;
if (!window)
@@ -76,6 +77,9 @@ do_builder (GtkWidget *do_widget)
gtk_widget_get_display (do_widget));
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
toolbar = GTK_WIDGET (gtk_builder_get_object (builder, "toolbar1"));
gtk_style_context_add_class (gtk_widget_get_style_context (toolbar),
"primary-toolbar");
actions = (GActionGroup*)g_simple_action_group_new ();
g_action_map_add_action_entries (G_ACTION_MAP (actions),
win_entries, G_N_ELEMENTS (win_entries),

View File

@@ -98,7 +98,7 @@ get_image_paintable (GtkImage *image)
{
const gchar *icon_name;
GtkIconTheme *icon_theme;
GtkIconPaintable *icon;
GtkIconInfo *icon_info;
switch (gtk_image_get_storage_type (image))
{
@@ -107,15 +107,10 @@ get_image_paintable (GtkImage *image)
case GTK_IMAGE_ICON_NAME:
icon_name = gtk_image_get_icon_name (image);
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (image)));
icon = gtk_icon_theme_lookup_icon (icon_theme,
icon_name,
NULL,
48, 1,
gtk_widget_get_direction (GTK_WIDGET (image)),
0);
if (icon == NULL)
icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon_name, 48, GTK_ICON_LOOKUP_GENERIC_FALLBACK);
if (icon_info == NULL)
return NULL;
return GDK_PAINTABLE (icon);
return gtk_icon_info_load_icon (icon_info, NULL);
default:
g_warning ("Image storage type %d not handled",
gtk_image_get_storage_type (image));
@@ -138,18 +133,23 @@ drag_begin (GtkDragSource *source,
}
}
static void
get_texture (GValue *value,
gpointer data)
{
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (data));
if (GDK_IS_TEXTURE (paintable))
g_value_set_object (value, paintable);
}
static GdkContentProvider *
prepare_drag (GtkDragSource *source,
double x,
double y,
GtkWidget *image)
{
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (image));
if (!GDK_IS_TEXTURE (paintable))
return NULL;
return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, paintable);
return gdk_content_provider_new_with_callback (GDK_TYPE_TEXTURE, get_texture, image);
}
static void
@@ -273,8 +273,9 @@ do_clipboard (GtkWidget *do_widget)
GActionGroup *actions;
GtkDragSource *source;
GtkDropTarget *dest;
GdkContentFormats *formats;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Clipboard");
@@ -341,7 +342,9 @@ do_clipboard (GtkWidget *do_widget)
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
/* accept drops on image */
dest = gtk_drop_target_new (gdk_content_formats_new_for_gtype (GDK_TYPE_TEXTURE), GDK_ACTION_COPY);
formats = gdk_content_formats_new_for_gtype (GDK_TYPE_TEXTURE);
dest = gtk_drop_target_new (formats, GDK_ACTION_COPY);
gdk_content_formats_unref (formats);
g_signal_connect (dest, "drag-drop", G_CALLBACK (drag_drop), image);
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (dest));
@@ -370,7 +373,9 @@ do_clipboard (GtkWidget *do_widget)
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
/* accept drops on image */
dest = gtk_drop_target_new (gdk_content_formats_new_for_gtype (GDK_TYPE_TEXTURE), GDK_ACTION_COPY);
formats = gdk_content_formats_new_for_gtype (GDK_TYPE_TEXTURE);
dest = gtk_drop_target_new (formats, GDK_ACTION_COPY);
gdk_content_formats_unref (formats);
g_signal_connect (dest, "drag-drop", G_CALLBACK (drag_drop), image);
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (dest));

View File

@@ -69,7 +69,7 @@ do_colorsel (GtkWidget *do_widget)
color.green = 0;
color.alpha = 1;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Color Chooser");

View File

@@ -310,7 +310,7 @@ do_combobox (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Combo Boxes");

View File

@@ -255,7 +255,7 @@ do_constraints (GtkWidget *do_widget)
{
GtkWidget *header, *box, *grid, *button;
window = gtk_window_new ();
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 ();

View File

@@ -211,7 +211,7 @@ do_constraints2 (GtkWidget *do_widget)
{
GtkWidget *header, *box, *grid, *button;
window = gtk_window_new ();
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 ();

View File

@@ -131,7 +131,7 @@ do_constraints3 (GtkWidget *do_widget)
{
GtkWidget *header, *box, *grid, *button;
window = gtk_window_new ();
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 ();

View File

@@ -24,7 +24,7 @@ do_css_accordion (GtkWidget *do_widget)
GtkWidget *container, *child;
GtkStyleProvider *provider;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "CSS Accordion");
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
gtk_window_set_default_size (GTK_WINDOW (window), 600, 300);

View File

@@ -72,7 +72,7 @@ do_css_basics (GtkWidget *do_widget)
GtkTextBuffer *text;
GBytes *bytes;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "CSS Basics");
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);

View File

@@ -86,7 +86,7 @@ do_css_multiplebgs (GtkWidget *do_widget)
GtkTextBuffer *text;
GBytes *bytes;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Multiple Backgrounds");
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);

View File

@@ -72,7 +72,7 @@ do_css_pixbufs (GtkWidget *do_widget)
GtkTextBuffer *text;
GBytes *bytes;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Animated Backgrounds");
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);

View File

@@ -62,19 +62,22 @@ GtkWidget *
create_toolbar (void)
{
GtkWidget *toolbar;
GtkWidget *item;
GtkToolItem *item;
toolbar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
toolbar = gtk_toolbar_new ();
gtk_widget_set_valign (toolbar, GTK_ALIGN_CENTER);
item = gtk_button_new_from_icon_name ("go-next");
gtk_container_add (GTK_CONTAINER (toolbar), item);
item = gtk_tool_button_new (NULL, NULL);
gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (item), "go-next");
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
item = gtk_button_new_from_icon_name ("go-previous");
gtk_container_add (GTK_CONTAINER (toolbar), item);
item = gtk_tool_button_new (NULL, NULL);
gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (item), "go-previous");
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
item = gtk_button_new_with_label ("Hello World");
gtk_container_add (GTK_CONTAINER (toolbar), item);
item = gtk_tool_button_new (NULL, "Hello World");
gtk_tool_item_set_is_important (item, TRUE);
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1);
return toolbar;
}
@@ -91,7 +94,7 @@ do_css_shadows (GtkWidget *do_widget)
GtkTextBuffer *text;
GBytes *bytes;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Shadows");
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);

View File

@@ -173,6 +173,7 @@
<file>fishbowl.c</file>
<file>fixed.c</file>
<file>flowbox.c</file>
<file>foreigndrawing.c</file>
<file>font_features.c</file>
<file>fontplane.c</file>
<file>fontrendering.c</file>

View File

@@ -111,52 +111,53 @@
</object>
</child>
<child>
<object class="GtkBox" id="toolbar1">
<object class="GtkToolbar" id="toolbar1">
<child internal-child="accessible">
<object class="AtkObject" id="a11y-toolbar">
<property name="AtkObject::accessible-name">The toolbar</property>
</object>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="label" translatable="yes">New</property>
<property name="tooltip-text" translatable="yes">Create a new file</property>
<property name="icon-name">document-new</property>
</object>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="label" translatable="yes">Open</property>
<property name="tooltip-text" translatable="yes">Open a file</property>
<property name="icon-name">document-open</property>
</object>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="label" translatable="yes">Save</property>
<property name="tooltip-text" translatable="yes">Save a file</property>
<property name="icon-name">document-save</property>
<property name="is-important">1</property>
</object>
</child>
<child>
<object class="GtkSeparator"/>
<object class="GtkSeparatorToolItem"/>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="label" translatable="yes">Copy</property>
<property name="tooltip-text" translatable="yes">Copy selected object into the clipboard</property>
<property name="icon-name">edit-copy</property>
</object>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="label" translatable="yes">Cut</property>
<property name="tooltip-text" translatable="yes">Cut selected object into the clipboard</property>
<property name="icon-name">edit-cut</property>
</object>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="label" translatable="yes">Paste</property>
<property name="tooltip-text" translatable="yes">Paste object from the clipboard</property>
<property name="icon-name">edit-paste</property>

View File

@@ -105,7 +105,7 @@ do_dialog (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Dialogs and Message Boxes");

View File

@@ -356,7 +356,7 @@ do_dnd (GtkWidget *do_widget)
GtkGesture *multipress;
GtkCssProvider *provider;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Drag-and-drop");

View File

@@ -189,7 +189,7 @@ do_drawingarea (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Drawing Area");

View File

@@ -345,7 +345,7 @@ do_editable_cells (GtkWidget *do_widget)
GtkTreeModel *items_model;
GtkTreeModel *numbers_model;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Editable Cells");

View File

@@ -45,7 +45,7 @@ do_entry_completion (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Entry Completion");

View File

@@ -20,7 +20,7 @@ do_entry_undo (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Entry Undo");

View File

@@ -22,11 +22,29 @@ gsize n_icon_names = 0;
static void
init_icon_names (GtkIconTheme *theme)
{
GPtrArray *icons;
GList *l, *icon_list;
if (icon_names)
return;
icon_names = gtk_icon_theme_get_icon_names (theme);
n_icon_names = g_strv_length (icon_names);
icon_list = gtk_icon_theme_list_icons (theme, NULL);
icons = g_ptr_array_new ();
for (l = icon_list; l; l = l->next)
{
if (g_str_has_suffix (l->data, "symbolic"))
continue;
g_ptr_array_add (icons, g_strdup (l->data));
}
n_icon_names = icons->len;
g_ptr_array_add (icons, NULL); /* NULL-terminate the array */
icon_names = (char **) g_ptr_array_free (icons, FALSE);
/* don't free strings, we assigned them to the array */
g_list_free_full (icon_list, g_free);
}
static const char *
@@ -42,10 +60,8 @@ create_icon (void)
{
GtkWidget *image;
image = gtk_image_new ();
image = gtk_image_new_from_icon_name (get_random_icon_name (gtk_icon_theme_get_default ()));
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
gtk_image_set_from_icon_name (GTK_IMAGE (image),
get_random_icon_name (gtk_icon_theme_get_for_display (gtk_widget_get_display (image))));
return image;
}

View File

@@ -124,7 +124,7 @@ create_demo_window (GtkWidget *do_widget)
{
GtkWidget *window, *sw, *fixed, *cube;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Fixed layout");
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);

View File

@@ -719,7 +719,7 @@ do_flowbox (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Flow Box");

View File

@@ -0,0 +1,984 @@
/* Foreign drawing
*
* Many applications can't use GTK widgets, for a variety of reasons,
* but still want their user interface to appear integrated with the
* rest of the desktop, and follow GTK themes. This demo shows how to
* use GtkStyleContext and the gtk_render_ APIs to achieve this.
*
* Note that this is a very simple, non-interactive example.
*/
#include <gtk/gtk.h>
#include <string.h>
static void
append_element (GtkWidgetPath *path,
const char *selector)
{
static const struct {
const char *name;
GtkStateFlags state_flag;
} pseudo_classes[] = {
{ "active", GTK_STATE_FLAG_ACTIVE },
{ "hover", GTK_STATE_FLAG_PRELIGHT },
{ "selected", GTK_STATE_FLAG_SELECTED },
{ "disabled", GTK_STATE_FLAG_INSENSITIVE },
{ "indeterminate", GTK_STATE_FLAG_INCONSISTENT },
{ "focus", GTK_STATE_FLAG_FOCUSED },
{ "backdrop", GTK_STATE_FLAG_BACKDROP },
{ "dir(ltr)", GTK_STATE_FLAG_DIR_LTR },
{ "dir(rtl)", GTK_STATE_FLAG_DIR_RTL },
{ "link", GTK_STATE_FLAG_LINK },
{ "visited", GTK_STATE_FLAG_VISITED },
{ "checked", GTK_STATE_FLAG_CHECKED },
{ "drop(active)", GTK_STATE_FLAG_DROP_ACTIVE }
};
const char *next;
char *name;
char type;
guint i;
next = strpbrk (selector, "#.:");
if (next == NULL)
next = selector + strlen (selector);
name = g_strndup (selector, next - selector);
if (g_ascii_isupper (selector[0]))
{
GType gtype;
gtype = g_type_from_name (name);
if (gtype == G_TYPE_INVALID)
{
g_critical ("Unknown type name `%s'", name);
g_free (name);
return;
}
gtk_widget_path_append_type (path, gtype);
}
else
{
/* Omit type, we're using name */
gtk_widget_path_append_type (path, G_TYPE_NONE);
gtk_widget_path_iter_set_object_name (path, -1, name);
}
g_free (name);
while (*next != '\0')
{
type = *next;
selector = next + 1;
next = strpbrk (selector, "#.:");
if (next == NULL)
next = selector + strlen (selector);
name = g_strndup (selector, next - selector);
switch (type)
{
case '#':
gtk_widget_path_iter_set_name (path, -1, name);
break;
case '.':
gtk_widget_path_iter_add_class (path, -1, name);
break;
case ':':
for (i = 0; i < G_N_ELEMENTS (pseudo_classes); i++)
{
if (g_str_equal (pseudo_classes[i].name, name))
{
gtk_widget_path_iter_set_state (path,
-1,
gtk_widget_path_iter_get_state (path, -1)
| pseudo_classes[i].state_flag);
break;
}
}
if (i == G_N_ELEMENTS (pseudo_classes))
g_critical ("Unknown pseudo-class :%s", name);
break;
default:
g_assert_not_reached ();
break;
}
g_free (name);
}
}
static GtkStyleContext *
create_context_for_path (GtkWidgetPath *path,
GtkStyleContext *parent)
{
GtkStyleContext *context;
context = gtk_style_context_new ();
gtk_style_context_set_path (context, path);
gtk_style_context_set_parent (context, parent);
/* Unfortunately, we have to explicitly set the state again here
* for it to take effect
*/
gtk_style_context_set_state (context, gtk_widget_path_iter_get_state (path, -1));
gtk_widget_path_unref (path);
return context;
}
static GtkStyleContext *
get_style (GtkStyleContext *parent,
const char *selector)
{
GtkWidgetPath *path;
if (parent)
path = gtk_widget_path_copy (gtk_style_context_get_path (parent));
else
path = gtk_widget_path_new ();
append_element (path, selector);
return create_context_for_path (path, parent);
}
static GtkStyleContext *
get_style_with_siblings (GtkStyleContext *parent,
const char *selector,
const char **siblings,
gint position)
{
GtkWidgetPath *path, *siblings_path;
guint i;
if (parent)
path = gtk_widget_path_copy (gtk_style_context_get_path (parent));
else
path = gtk_widget_path_new ();
siblings_path = gtk_widget_path_new ();
for (i = 0; siblings[i]; i++)
append_element (siblings_path, siblings[i]);
gtk_widget_path_append_with_siblings (path, siblings_path, position);
gtk_widget_path_unref (siblings_path);
return create_context_for_path (path, parent);
}
static void
draw_style_common (GtkStyleContext *context,
cairo_t *cr,
gint x,
gint y,
gint width,
gint height,
gint *contents_x,
gint *contents_y,
gint *contents_width,
gint *contents_height)
{
GtkBorder margin, border, padding;
int min_width, min_height;
gtk_style_context_get_margin (context, &margin);
gtk_style_context_get_border (context, &border);
gtk_style_context_get_padding (context, &padding);
gtk_style_context_get (context,
"min-width", &min_width,
"min-height", &min_height,
NULL);
x += margin.left;
y += margin.top;
width -= margin.left + margin.right;
height -= margin.top + margin.bottom;
width = MAX (width, min_width);
height = MAX (height, min_height);
gtk_render_background (context, cr, x, y, width, height);
gtk_render_frame (context, cr, x, y, width, height);
if (contents_x)
*contents_x = x + border.left + padding.left;
if (contents_y)
*contents_y = y + border.top + padding.top;
if (contents_width)
*contents_width = width - border.left - border.right - padding.left - padding.right;
if (contents_height)
*contents_height = height - border.top - border.bottom - padding.top - padding.bottom;
}
static void
query_size (GtkStyleContext *context,
gint *width,
gint *height)
{
GtkBorder margin, border, padding;
int min_width, min_height;
gtk_style_context_get_margin (context, &margin);
gtk_style_context_get_border (context, &border);
gtk_style_context_get_padding (context, &padding);
gtk_style_context_get (context,
"min-width", &min_width,
"min-height", &min_height,
NULL);
min_width += margin.left + margin.right + border.left + border.right + padding.left + padding.right;
min_height += margin.top + margin.bottom + border.top + border.bottom + padding.top + padding.bottom;
if (width)
*width = MAX (*width, min_width);
if (height)
*height = MAX (*height, min_height);
}
static void
draw_menu (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint *height)
{
GtkStyleContext *menu_context;
GtkStyleContext *menuitem_context;
GtkStyleContext *hovermenuitem_context;
GtkStyleContext *hoveredarrowmenuitem_context;
GtkStyleContext *arrowmenuitem_context;
GtkStyleContext *checkmenuitem_context;
GtkStyleContext *disabledarrowmenuitem_context;
GtkStyleContext *disabledcheckmenuitem_context;
GtkStyleContext *radiomenuitem_context;
GtkStyleContext *disablemenuitem_context;
GtkStyleContext *disabledradiomenuitem_context;
GtkStyleContext *separatormenuitem_context;
gint menuitem1_height, menuitem2_height, menuitem3_height, menuitem4_height, menuitem5_height;
gint contents_x, contents_y, contents_width, contents_height;
gint menu_x, menu_y, menu_width, menu_height;
gint arrow_width, arrow_height, arrow_size;
gint toggle_x, toggle_y, toggle_width, toggle_height;
/* This information is taken from the GtkMenu docs, see "CSS nodes" */
menu_context = get_style (gtk_widget_get_style_context(widget), "menu");
hovermenuitem_context = get_style (menu_context, "menuitem:hover");
hoveredarrowmenuitem_context = get_style (hovermenuitem_context, "arrow.right:dir(ltr)");
menuitem_context = get_style (menu_context, "menuitem");
arrowmenuitem_context = get_style (menuitem_context, "arrow:dir(rtl)");
disablemenuitem_context = get_style (menu_context, "menuitem:disabled");
disabledarrowmenuitem_context = get_style (disablemenuitem_context, "arrow:dir(rtl)");
checkmenuitem_context = get_style (menuitem_context, "check:checked");
disabledcheckmenuitem_context = get_style (disablemenuitem_context, "check");
separatormenuitem_context = get_style (menu_context, "separator:disabled");
radiomenuitem_context = get_style (menuitem_context, "radio:checked");
disabledradiomenuitem_context = get_style (disablemenuitem_context, "radio");
*height = 0;
query_size (menu_context, NULL, height);
menuitem1_height = 0;
query_size (hovermenuitem_context, NULL, &menuitem1_height);
query_size (hoveredarrowmenuitem_context, NULL, &menuitem1_height);
*height += menuitem1_height;
menuitem2_height = 0;
query_size (menu_context, NULL, &menuitem5_height);
query_size (menuitem_context, NULL, &menuitem2_height);
query_size (arrowmenuitem_context, NULL, &menuitem2_height);
query_size (disabledarrowmenuitem_context, NULL, &menuitem2_height);
*height += menuitem2_height;
menuitem3_height = 0;
query_size (menu_context, NULL, &menuitem5_height);
query_size (menuitem_context, NULL, &menuitem3_height);
query_size (checkmenuitem_context, NULL, &menuitem3_height);
query_size (disabledcheckmenuitem_context, NULL, &menuitem3_height);
*height += menuitem3_height;
menuitem4_height = 0;
query_size (menu_context, NULL, &menuitem5_height);
query_size (separatormenuitem_context, NULL, &menuitem4_height);
*height += menuitem4_height;
menuitem5_height = 0;
query_size (menu_context, NULL, &menuitem5_height);
query_size (menuitem_context, NULL, &menuitem5_height);
query_size (radiomenuitem_context, NULL, &menuitem5_height);
query_size (disabledradiomenuitem_context, NULL, &menuitem5_height);
*height += menuitem5_height;
draw_style_common (menu_context, cr, x, y, width, *height,
&menu_x, &menu_y, &menu_width, &menu_height);
/* Hovered with right arrow */
gtk_style_context_get (hoveredarrowmenuitem_context,
"min-width", &arrow_width, "min-height", &arrow_height, NULL);
arrow_size = MIN (arrow_width, arrow_height);
draw_style_common (hovermenuitem_context, cr, menu_x, menu_y, menu_width, menuitem1_height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_render_arrow (hoveredarrowmenuitem_context, cr, G_PI / 2,
contents_x + contents_width - arrow_size,
contents_y + (contents_height - arrow_size) / 2, arrow_size);
/* Left arrow sensitive, and right arrow insensitive */
draw_style_common (menuitem_context, cr, menu_x, menu_y + menuitem1_height, menu_width, menuitem2_height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_style_context_get (arrowmenuitem_context,
"min-width", &arrow_width, "min-height", &arrow_height, NULL);
arrow_size = MIN (arrow_width, arrow_height);
gtk_render_arrow (arrowmenuitem_context, cr, G_PI / 2,
contents_x,
contents_y + (contents_height - arrow_size) / 2, arrow_size);
gtk_style_context_get (disabledarrowmenuitem_context,
"min-width", &arrow_width, "min-height", &arrow_height, NULL);
arrow_size = MIN (arrow_width, arrow_height);
gtk_render_arrow (disabledarrowmenuitem_context, cr, G_PI / 2,
contents_x + contents_width - arrow_size,
contents_y + (contents_height - arrow_size) / 2, arrow_size);
/* Left check enabled, sensitive, and right check unchecked, insensitive */
draw_style_common (menuitem_context, cr, menu_x, menu_y + menuitem1_height + menuitem2_height, menu_width, menuitem3_height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_style_context_get (checkmenuitem_context,
"min-width", &toggle_width, "min-height", &toggle_height, NULL);
draw_style_common (checkmenuitem_context, cr,
contents_x,
contents_y,
toggle_width, toggle_height,
&toggle_x, &toggle_y, &toggle_width, &toggle_height);
gtk_render_check (checkmenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);
gtk_style_context_get (disabledcheckmenuitem_context,
"min-width", &toggle_width, "min-height", &toggle_height, NULL);
draw_style_common (disabledcheckmenuitem_context, cr,
contents_x + contents_width - toggle_width,
contents_y,
toggle_width, toggle_height,
&toggle_x, &toggle_y, &toggle_width, &toggle_height);
gtk_render_check (disabledcheckmenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);
/* Separator */
draw_style_common (separatormenuitem_context, cr, menu_x, menu_y + menuitem1_height + menuitem2_height + menuitem3_height,
menu_width, menuitem4_height,
NULL, NULL, NULL, NULL);
/* Left check enabled, sensitive, and right check unchecked, insensitive */
draw_style_common (menuitem_context, cr, menu_x, menu_y + menuitem1_height + menuitem2_height + menuitem3_height + menuitem4_height,
menu_width, menuitem5_height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_style_context_get (radiomenuitem_context,
"min-width", &toggle_width, "min-height", &toggle_height, NULL);
draw_style_common (radiomenuitem_context, cr,
contents_x,
contents_y,
toggle_width, toggle_height,
&toggle_x, &toggle_y, &toggle_width, &toggle_height);
gtk_render_check (radiomenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);
gtk_style_context_get (disabledradiomenuitem_context,
"min-width", &toggle_width, "min-height", &toggle_height, NULL);
draw_style_common (disabledradiomenuitem_context, cr,
contents_x + contents_width - toggle_width,
contents_y,
toggle_width, toggle_height,
&toggle_x, &toggle_y, &toggle_width, &toggle_height);
gtk_render_check (disabledradiomenuitem_context, cr, toggle_x, toggle_y, toggle_width, toggle_height);
g_object_unref (menu_context);
g_object_unref (menuitem_context);
g_object_unref (hovermenuitem_context);
g_object_unref (hoveredarrowmenuitem_context);
g_object_unref (arrowmenuitem_context);
g_object_unref (checkmenuitem_context);
g_object_unref (disabledarrowmenuitem_context);
g_object_unref (disabledcheckmenuitem_context);
g_object_unref (radiomenuitem_context);
g_object_unref (disablemenuitem_context);
g_object_unref (disabledradiomenuitem_context);
g_object_unref (separatormenuitem_context);
}
static void
draw_menubar (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint *height)
{
GtkStyleContext *frame_context;
GtkStyleContext *border_context;
GtkStyleContext *menubar_context;
GtkStyleContext *hovered_menuitem_context;
GtkStyleContext *menuitem_context;
gint contents_x, contents_y, contents_width, contents_height;
gint item_width;
/* Menubar background is the same color as our base background, so use a frame */
frame_context = get_style (NULL, "frame");
border_context = get_style (frame_context, "border");
/* This information is taken from the GtkPopoverMenuBar docs, see "CSS nodes" */
menubar_context = get_style (NULL, "menubar");
hovered_menuitem_context = get_style (menubar_context, "menuitem:hover");
menuitem_context = get_style (menubar_context, "menuitem");
*height = 0;
query_size (frame_context, NULL, height);
query_size (border_context, NULL, height);
query_size (menubar_context, NULL, height);
query_size (hovered_menuitem_context, NULL, height);
query_size (menuitem_context, NULL, height);
draw_style_common (frame_context, cr, x, y, width, *height,
NULL, NULL, NULL, NULL);
draw_style_common (border_context, cr, x, y, width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
draw_style_common (menubar_context, cr, contents_x, contents_y, contents_width, contents_height,
NULL, NULL, NULL, NULL);
item_width = contents_width / 3;
draw_style_common (hovered_menuitem_context, cr, contents_x, contents_y, item_width, contents_height,
NULL, NULL, NULL, NULL);
draw_style_common (menuitem_context, cr, contents_x + item_width * 2, contents_y, item_width, contents_height,
NULL, NULL, NULL, NULL);
g_object_unref (menuitem_context);
g_object_unref (hovered_menuitem_context);
g_object_unref (menubar_context);
g_object_unref (border_context);
g_object_unref (frame_context);
}
static void
draw_notebook (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint height)
{
GtkStyleContext *notebook_context;
GtkStyleContext *header_context;
GtkStyleContext *tabs_context;
GtkStyleContext *tab1_context, *tab2_context;
GtkStyleContext *stack_context;
gint header_height;
gint contents_x, contents_y, contents_width, contents_height;
/* This information is taken from the GtkNotebook docs, see "CSS nodes" */
notebook_context = get_style (NULL, "notebook.frame");
header_context = get_style (notebook_context, "header.top");
tabs_context = get_style (header_context, "tabs");
tab1_context = get_style (tabs_context, "tab:checked");
tab2_context = get_style (tabs_context, "tab:hover");
stack_context = get_style (notebook_context, "stack");
header_height = 0;
query_size (notebook_context, NULL, &header_height);
query_size (header_context, NULL, &header_height);
query_size (tabs_context, NULL, &header_height);
query_size (tab1_context, NULL, &header_height);
query_size (tab2_context, NULL, &header_height);
draw_style_common (notebook_context, cr, x, y, width, height, NULL, NULL, NULL, NULL);
draw_style_common (header_context, cr, x, y, width, header_height, NULL, NULL, NULL, NULL);
draw_style_common (tabs_context, cr, x, y, width, header_height, NULL, NULL, NULL, NULL);
draw_style_common (tab1_context, cr, x, y, width / 2, header_height,
&contents_x, &contents_y, &contents_width, &contents_height);
draw_style_common (tab2_context, cr, x + width / 2, y, width / 2, header_height,
NULL, NULL, NULL, NULL);
draw_style_common (stack_context, cr, x, y + header_height, width,height - header_height,
NULL, NULL, NULL, NULL);
g_object_unref (stack_context);
g_object_unref (tabs_context);
g_object_unref (tab1_context);
g_object_unref (tab2_context);
g_object_unref (header_context);
g_object_unref (notebook_context);
}
static void
draw_horizontal_scrollbar (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint position,
GtkStateFlags state,
gint *height)
{
GtkStyleContext *scrollbar_context;
GtkStyleContext *contents_context;
GtkStyleContext *trough_context;
GtkStyleContext *slider_context;
gint slider_width;
/* This information is taken from the GtkScrollbar docs, see "CSS nodes" */
scrollbar_context = get_style (NULL, "scrollbar.horizontal.bottom");
contents_context = get_style (scrollbar_context, "contents");
trough_context = get_style (contents_context, "trough");
slider_context = get_style (trough_context, "slider");
gtk_style_context_set_state (scrollbar_context, state);
gtk_style_context_set_state (contents_context, state);
gtk_style_context_set_state (trough_context, state);
gtk_style_context_set_state (slider_context, state);
*height = 0;
query_size (scrollbar_context, NULL, height);
query_size (contents_context, NULL, height);
query_size (trough_context, NULL, height);
query_size (slider_context, NULL, height);
gtk_style_context_get (slider_context,
"min-width", &slider_width, NULL);
draw_style_common (scrollbar_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
draw_style_common (contents_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
draw_style_common (trough_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
draw_style_common (slider_context, cr, x + position, y, slider_width, *height, NULL, NULL, NULL, NULL);
g_object_unref (slider_context);
g_object_unref (trough_context);
g_object_unref (contents_context);
g_object_unref (scrollbar_context);
}
static void
draw_text (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint height,
const gchar *text,
GtkStateFlags state)
{
GtkStyleContext *label_context;
GtkStyleContext *selection_context;
GtkStyleContext *context;
PangoLayout *layout;
/* This information is taken from the GtkLabel docs, see "CSS nodes" */
label_context = get_style (NULL, "label.view");
selection_context = get_style (label_context, "selection");
gtk_style_context_set_state (label_context, state);
if (state & GTK_STATE_FLAG_SELECTED)
context = selection_context;
else
context = label_context;
layout = gtk_widget_create_pango_layout (widget, text);
gtk_render_background (context, cr, x, y, width, height);
gtk_render_frame (context, cr, x, y, width, height);
gtk_render_layout (context, cr, x, y, layout);
g_object_unref (layout);
g_object_unref (selection_context);
g_object_unref (label_context);
}
static void
draw_check (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
GtkStateFlags state,
gint *width,
gint *height)
{
GtkStyleContext *button_context;
GtkStyleContext *check_context;
gint contents_x, contents_y, contents_width, contents_height;
/* This information is taken from the GtkCheckButton docs, see "CSS nodes" */
button_context = get_style (NULL, "checkbutton");
check_context = get_style (button_context, "check");
gtk_style_context_set_state (check_context, state);
*width = *height = 0;
query_size (button_context, width, height);
query_size (check_context, width, height);
draw_style_common (button_context, cr, x, y, *width, *height, NULL, NULL, NULL, NULL);
draw_style_common (check_context, cr, x, y, *width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_render_check (check_context, cr, contents_x, contents_y, contents_width, contents_height);
g_object_unref (check_context);
g_object_unref (button_context);
}
static void
draw_radio (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
GtkStateFlags state,
gint *width,
gint *height)
{
GtkStyleContext *button_context;
GtkStyleContext *check_context;
gint contents_x, contents_y, contents_width, contents_height;
/* This information is taken from the GtkRadioButton docs, see "CSS nodes" */
button_context = get_style (NULL, "radiobutton");
check_context = get_style (button_context, "radio");
gtk_style_context_set_state (check_context, state);
*width = *height = 0;
query_size (button_context, width, height);
query_size (check_context, width, height);
draw_style_common (button_context, cr, x, y, *width, *height, NULL, NULL, NULL, NULL);
draw_style_common (check_context, cr, x, y, *width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_render_check (check_context, cr, contents_x, contents_y, contents_width, contents_height);
g_object_unref (check_context);
g_object_unref (button_context);
}
static void
draw_progress (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint position,
gint *height)
{
GtkStyleContext *bar_context;
GtkStyleContext *trough_context;
GtkStyleContext *progress_context;
/* This information is taken from the GtkProgressBar docs, see "CSS nodes" */
bar_context = get_style (NULL, "progressbar.horizontal");
trough_context = get_style (bar_context, "trough");
progress_context = get_style (trough_context, "progress.left");
*height = 0;
query_size (bar_context, NULL, height);
query_size (trough_context, NULL, height);
query_size (progress_context, NULL, height);
draw_style_common (bar_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
draw_style_common (trough_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
draw_style_common (progress_context, cr, x, y, position, *height, NULL, NULL, NULL, NULL);
g_object_unref (progress_context);
g_object_unref (trough_context);
g_object_unref (bar_context);
}
static void
draw_scale (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint position,
gint *height)
{
GtkStyleContext *scale_context;
GtkStyleContext *contents_context;
GtkStyleContext *trough_context;
GtkStyleContext *slider_context;
GtkStyleContext *highlight_context;
gint contents_x, contents_y, contents_width, contents_height;
gint trough_height, slider_height;
scale_context = get_style (NULL, "scale.horizontal");
contents_context = get_style (scale_context, "contents");
trough_context = get_style (contents_context, "trough");
slider_context = get_style (trough_context, "slider");
highlight_context = get_style (trough_context, "highlight.top");
*height = 0;
query_size (scale_context, NULL, height);
query_size (contents_context, NULL, height);
query_size (trough_context, NULL, height);
query_size (slider_context, NULL, height);
query_size (highlight_context, NULL, height);
draw_style_common (scale_context, cr, x, y, width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
draw_style_common (contents_context, cr, contents_x, contents_y, contents_width, contents_height,
&contents_x, &contents_y, &contents_width, &contents_height);
/* Scale trough defines its size querying slider and highlight */
trough_height = 0;
query_size (trough_context, NULL, &trough_height);
slider_height = 0;
query_size (slider_context, NULL, &slider_height);
query_size (highlight_context, NULL, &slider_height);
trough_height += slider_height;
draw_style_common (trough_context, cr, contents_x, contents_y, contents_width, trough_height,
&contents_x, &contents_y, &contents_width, &contents_height);
draw_style_common (highlight_context, cr, contents_x, contents_y,
contents_width / 2, contents_height,
NULL, NULL, NULL, NULL);
draw_style_common (slider_context, cr, contents_x + position, contents_y, contents_height, contents_height,
NULL, NULL, NULL, NULL);
g_object_unref (scale_context);
g_object_unref (contents_context);
g_object_unref (trough_context);
g_object_unref (slider_context);
g_object_unref (highlight_context);
}
static void
draw_combobox (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gboolean has_entry,
gint *height)
{
GtkStyleContext *combo_context;
GtkStyleContext *box_context;
GtkStyleContext *button_context;
GtkStyleContext *button_box_context;
GtkStyleContext *entry_context;
GtkStyleContext *arrow_context;
gint contents_x, contents_y, contents_width, contents_height;
gint button_width;
gint arrow_width, arrow_height, arrow_size;
/* This information is taken from the GtkComboBox docs, see "CSS nodes" */
combo_context = get_style (NULL, "combobox:focus");
box_context = get_style (combo_context, "box.horizontal.linked");
if (has_entry)
{
const char *siblings[3] = { "entry.combo:focus", "button.combo" , NULL };
entry_context = get_style_with_siblings (box_context, "entry.combo:focus", siblings, 0);
button_context = get_style_with_siblings (box_context, "button.combo", siblings, 1);
}
else
{
const char *siblings[2] = { "button.combo" , NULL };
button_context = get_style_with_siblings (box_context, "button.combo", siblings, 0);
}
button_box_context = get_style (button_context, "box.horizontal");
arrow_context = get_style (button_box_context, "arrow");
*height = 0;
query_size (combo_context, NULL, height);
query_size (box_context, NULL, height);
if (has_entry)
query_size (entry_context, NULL, height);
query_size (button_context, NULL, height);
query_size (button_box_context, NULL, height);
query_size (arrow_context, NULL, height);
gtk_style_context_get (arrow_context,
"min-width", &arrow_width, "min-height", &arrow_height, NULL);
arrow_size = MIN (arrow_width, arrow_height);
draw_style_common (combo_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
draw_style_common (box_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
if (has_entry)
{
button_width = *height;
draw_style_common (entry_context, cr, x, y, width - button_width, *height, NULL, NULL, NULL, NULL);
draw_style_common (button_context, cr, x + width - button_width, y, button_width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
}
else
{
button_width = width;
draw_style_common (button_context, cr, x, y, width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
}
draw_style_common (button_box_context, cr, contents_x, contents_y, contents_width, contents_height,
NULL, NULL, NULL, NULL);
draw_style_common (arrow_context, cr, contents_x, contents_y, contents_width, contents_height,
NULL, NULL, NULL, NULL);
gtk_render_arrow (arrow_context, cr, G_PI / 2,
contents_x + contents_width - arrow_size,
contents_y + (contents_height - arrow_size) / 2, arrow_size);
g_object_unref (arrow_context);
if (has_entry)
g_object_unref (entry_context);
g_object_unref (button_context);
g_object_unref (combo_context);
}
static void
draw_spinbutton (GtkWidget *widget,
cairo_t *cr,
gint x,
gint y,
gint width,
gint *height)
{
GtkStyleContext *spin_context;
GtkStyleContext *entry_context;
GtkStyleContext *up_context;
GtkStyleContext *down_context;
GtkIconTheme *icon_theme;
GtkIconInfo *icon_info;
GdkTexture *texture;
gint icon_width, icon_height, icon_size;
gint button_width;
gint contents_x, contents_y, contents_width, contents_height;
/* This information is taken from the GtkSpinButton docs, see "CSS nodes" */
spin_context = get_style (NULL, "spinbutton.horizontal:focus");
entry_context = get_style (spin_context, "entry:focus");
up_context = get_style (spin_context, "button.up:focus:active");
down_context = get_style (spin_context, "button.down:focus");
*height = 0;
query_size (spin_context, NULL, height);
query_size (entry_context, NULL, height);
query_size (up_context, NULL, height);
query_size (down_context, NULL, height);
button_width = *height;
draw_style_common (spin_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
draw_style_common (entry_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (widget));
gtk_style_context_get (up_context,
"min-width", &icon_width, "min-height", &icon_height, NULL);
icon_size = MIN (icon_width, icon_height);
icon_info = gtk_icon_theme_lookup_icon (icon_theme, "list-add-symbolic", icon_size, 0);
texture = GDK_TEXTURE (gtk_icon_info_load_symbolic_for_context (icon_info, up_context, NULL, NULL));
g_object_unref (icon_info);
draw_style_common (up_context, cr, x + width - button_width, y, button_width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_render_icon (up_context, cr, texture, contents_x, contents_y + (contents_height - icon_size) / 2);
g_object_unref (texture);
gtk_style_context_get (down_context,
"min-width", &icon_width, "min-height", &icon_height, NULL);
icon_size = MIN (icon_width, icon_height);
icon_info = gtk_icon_theme_lookup_icon (icon_theme, "list-remove-symbolic", icon_size, 0);
texture = GDK_TEXTURE (gtk_icon_info_load_symbolic_for_context (icon_info, down_context, NULL, NULL));
g_object_unref (icon_info);
draw_style_common (down_context, cr, x + width - 2 * button_width, y, button_width, *height,
&contents_x, &contents_y, &contents_width, &contents_height);
gtk_render_icon (down_context, cr, texture, contents_x, contents_y + (contents_height - icon_size) / 2);
g_object_unref (texture);
g_object_unref (down_context);
g_object_unref (up_context);
g_object_unref (entry_context);
g_object_unref (spin_context);
}
static void
draw_func (GtkDrawingArea *da,
cairo_t *cr,
int width,
int height,
gpointer data)
{
GtkWidget *widget = GTK_WIDGET (da);
gint panewidth;
gint x, y;
panewidth = width / 2;
cairo_rectangle (cr, 0, 0, width, height);
cairo_set_source_rgb (cr, 0.9, 0.9, 0.9);
cairo_fill (cr);
x = y = 10;
draw_horizontal_scrollbar (widget, cr, x, y, panewidth - 20, 30, GTK_STATE_FLAG_NORMAL, &height);
y += height + 8;
draw_horizontal_scrollbar (widget, cr, x, y, panewidth - 20, 40, GTK_STATE_FLAG_PRELIGHT, &height);
y += height + 8;
draw_horizontal_scrollbar (widget, cr, x, y, panewidth - 20, 50, GTK_STATE_FLAG_ACTIVE|GTK_STATE_FLAG_PRELIGHT, &height);
y += height + 8;
draw_text (widget, cr, x, y, panewidth - 20, 20, "Not selected", GTK_STATE_FLAG_NORMAL);
y += 20 + 10;
draw_text (widget, cr, x, y, panewidth - 20, 20, "Selected", GTK_STATE_FLAG_SELECTED);
x = 10;
y += 20 + 10;
draw_check (widget, cr, x, y, GTK_STATE_FLAG_NORMAL, &width, &height);
x += width + 10;
draw_check (widget, cr, x, y, GTK_STATE_FLAG_CHECKED, &width, &height);
x += width + 10;
draw_radio (widget, cr, x, y, GTK_STATE_FLAG_NORMAL, &width, &height);
x += width + 10;
draw_radio (widget, cr, x, y, GTK_STATE_FLAG_CHECKED, &width, &height);
x = 10;
y += height + 10;
draw_progress (widget, cr, x, y, panewidth - 20, 50, &height);
y += height + 10;
draw_scale (widget, cr, x, y, panewidth - 20, 75, &height);
y += height + 20;
draw_notebook (widget, cr, x, y, panewidth - 20, 160);
/* Second column */
x += panewidth;
y = 10;
draw_menu (widget, cr, x, y, panewidth - 20, &height);
y += height + 10;
draw_menubar (widget, cr, x, y, panewidth - 20, &height);
y += height + 20;
draw_spinbutton (widget, cr, x, y, panewidth - 20, &height);
y += height + 30;
draw_combobox (widget, cr, x, y, panewidth - 20, FALSE, &height);
y += height + 10;
draw_combobox (widget, cr, 10 + panewidth, y, panewidth - 20, TRUE, &height);
}
GtkWidget *
do_foreigndrawing (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
if (!window)
{
GtkWidget *box;
GtkWidget *da;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Foreign drawing");
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
gtk_container_add (GTK_CONTAINER (window), box);
da = gtk_drawing_area_new ();
gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), 400);
gtk_drawing_area_set_content_height (GTK_DRAWING_AREA (da), 400);
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), draw_func, NULL, NULL);
gtk_widget_set_hexpand (da, TRUE);
gtk_widget_set_vexpand (da, TRUE);
gtk_container_add (GTK_CONTAINER (box), da);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_widget_destroy (window);
return window;
}

View File

@@ -94,12 +94,9 @@ drawing_area_draw (GtkDrawingArea *area,
cairo_pattern_t *pat;
cairo_matrix_t matrix;
gdouble angle, scale;
gdouble x_center, y_center;
gtk_gesture_get_bounding_box_center (GTK_GESTURE (zoom), &x_center, &y_center);
cairo_get_matrix (cr, &matrix);
cairo_matrix_translate (&matrix, x_center, y_center);
cairo_matrix_translate (&matrix, width / 2, height / 2);
cairo_save (cr);
@@ -146,7 +143,7 @@ do_gestures (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
gtk_window_set_title (GTK_WINDOW (window), "Gestures");
g_signal_connect (window, "destroy",

View File

@@ -389,7 +389,7 @@ create_glarea_window (GtkWidget *do_widget)
GtkWidget *window, *box, *button, *controls;
int i;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "OpenGL Area");
gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);

View File

@@ -23,7 +23,7 @@ do_headerbar (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);

View File

@@ -232,7 +232,7 @@ do_hypertext (GtkWidget *do_widget)
GtkTextBuffer *buffer;
GtkEventController *controller;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Hypertext");
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));

View File

@@ -26,7 +26,7 @@ enum
static GdkPixbuf *file_pixbuf, *folder_pixbuf;
gchar *parent;
GtkWidget *up_button;
GtkToolItem *up_button;
/* Loads the images for the demo and returns whether the operation succeeded */
static void
@@ -188,8 +188,8 @@ item_activated (GtkIconView *icon_view,
}
static void
up_clicked (GtkButton *item,
gpointer user_data)
up_clicked (GtkToolItem *item,
gpointer user_data)
{
GtkListStore *store;
gchar *dir_name;
@@ -209,8 +209,8 @@ up_clicked (GtkButton *item,
}
static void
home_clicked (GtkButton *item,
gpointer user_data)
home_clicked (GtkToolItem *item,
gpointer user_data)
{
GtkListStore *store;
@@ -248,9 +248,9 @@ do_iconview (GtkWidget *do_widget)
GtkListStore *store;
GtkWidget *vbox;
GtkWidget *tool_bar;
GtkWidget *home_button;
GtkToolItem *home_button;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 650, 400);
gtk_window_set_display (GTK_WINDOW (window),
@@ -265,15 +265,23 @@ do_iconview (GtkWidget *do_widget)
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (window), vbox);
tool_bar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
tool_bar = gtk_toolbar_new ();
gtk_container_add (GTK_CONTAINER (vbox), tool_bar);
up_button = gtk_button_new_with_mnemonic ("_Up");
up_button = gtk_tool_button_new (NULL, NULL);
gtk_tool_button_set_label (GTK_TOOL_BUTTON (up_button), _("_Up"));
gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (up_button), TRUE);
gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (up_button), "go-up");
gtk_tool_item_set_is_important (up_button, TRUE);
gtk_widget_set_sensitive (GTK_WIDGET (up_button), FALSE);
gtk_container_add (GTK_CONTAINER (tool_bar), up_button);
gtk_toolbar_insert (GTK_TOOLBAR (tool_bar), up_button, -1);
home_button = gtk_button_new_with_mnemonic ("_Home");
gtk_container_add (GTK_CONTAINER (tool_bar), home_button);
home_button = gtk_tool_button_new (NULL, NULL);
gtk_tool_button_set_label (GTK_TOOL_BUTTON (home_button), _("_Home"));
gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (home_button), TRUE);
gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (home_button), "go-home");
gtk_tool_item_set_is_important (home_button, TRUE);
gtk_toolbar_insert (GTK_TOOLBAR (tool_bar), home_button, -1);
sw = gtk_scrolled_window_new (NULL, NULL);

View File

@@ -106,7 +106,7 @@ do_iconview_edit (GtkWidget *do_widget)
GtkListStore *store;
GtkCellRenderer *renderer;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));

View File

@@ -331,7 +331,7 @@ do_images (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Images");

View File

@@ -53,7 +53,7 @@ do_infobar (GtkWidget *do_widget)
{
actions = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Info Bars");
@@ -70,7 +70,7 @@ do_infobar (GtkWidget *do_widget)
label = gtk_label_new ("This is an info bar with message type GTK_MESSAGE_INFO");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_container_add (GTK_CONTAINER (bar), label);
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
button = gtk_toggle_button_new_with_label ("Message");
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
@@ -82,7 +82,7 @@ do_infobar (GtkWidget *do_widget)
label = gtk_label_new ("This is an info bar with message type GTK_MESSAGE_WARNING");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_container_add (GTK_CONTAINER (bar), label);
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
button = gtk_toggle_button_new_with_label ("Warning");
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
@@ -96,8 +96,7 @@ do_infobar (GtkWidget *do_widget)
label = gtk_label_new ("This is an info bar with message type GTK_MESSAGE_QUESTION");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_container_add (GTK_CONTAINER (bar), label);
gtk_info_bar_set_default_response (GTK_INFO_BAR (bar), GTK_RESPONSE_OK);
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
button = gtk_toggle_button_new_with_label ("Question");
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
@@ -109,7 +108,7 @@ do_infobar (GtkWidget *do_widget)
label = gtk_label_new ("This is an info bar with message type GTK_MESSAGE_ERROR");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_container_add (GTK_CONTAINER (bar), label);
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
button = gtk_toggle_button_new_with_label ("Error");
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
@@ -122,7 +121,7 @@ do_infobar (GtkWidget *do_widget)
label = gtk_label_new ("This is an info bar with message type GTK_MESSAGE_OTHER");
gtk_label_set_wrap (GTK_LABEL (label), TRUE);
gtk_label_set_xalign (GTK_LABEL (label), 0);
gtk_container_add (GTK_CONTAINER (bar), label);
gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (bar))), label);
button = gtk_toggle_button_new_with_label ("Other");
g_object_bind_property (bar, "revealed", button, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);

View File

@@ -52,7 +52,7 @@ do_links (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Links");

View File

@@ -255,7 +255,7 @@ do_list_store (GtkWidget *do_widget)
GtkWidget *treeview;
/* create window, etc */
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "List Store");

View File

@@ -347,7 +347,7 @@ do_listbox (GtkWidget *do_widget)
{
avatar_pixbuf_other = gdk_pixbuf_new_from_resource_at_scale ("/listbox/apple-red.png", 32, 32, FALSE, NULL);
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "List Box");

View File

@@ -28,6 +28,7 @@
<property name="default-width">800</property>
<property name="default-height">600</property>
<property name="title">GTK Demo</property>
<signal name="destroy" handler="gtk_main_quit" swapped="no"/>
<child type="titlebar">
<object class="GtkHeaderBar" id="headerbar">
<property name="show-title-buttons">1</property>

View File

@@ -54,7 +54,7 @@ do_markup (GtkWidget *do_widget)
GtkWidget *header;
GtkWidget *show_source;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_default_size (GTK_WINDOW (window), 450, 450);

View File

@@ -28,6 +28,7 @@ demos = files([
'fishbowl.c',
'fixed.c',
'fontrendering.c',
'foreigndrawing.c',
'gestures.c',
'glarea.c',
'headerbar.c',

View File

@@ -31,7 +31,7 @@ do_overlay (GtkWidget *do_widget)
int i, j;
char *text;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 500, 510);
gtk_window_set_title (GTK_WINDOW (window), "Interactive Overlay");

View File

@@ -35,7 +35,7 @@ do_overlay2 (GtkWidget *do_widget)
GtkTextIter start, end;
GtkAdjustment *adjustment;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 500, 510);
gtk_window_set_title (GTK_WINDOW (window), "Decorative Overlay");

View File

@@ -384,7 +384,7 @@ do_paint (GtkWidget *toplevel)
{
GtkWidget *draw_area, *headerbar, *colorbutton;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
draw_area = drawing_area_new ();
gtk_container_add (GTK_CONTAINER (window), draw_area);

View File

@@ -156,7 +156,7 @@ do_paintable (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Nuclear Icon");

View File

@@ -188,7 +188,7 @@ do_paintable_animated (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Nuclear Animation");

View File

@@ -288,7 +288,7 @@ do_paintable_mediastream (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Nuclear MediaStream");

View File

@@ -146,7 +146,7 @@ do_panes (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));

View File

@@ -36,7 +36,7 @@ do_password_entry (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
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 ();

View File

@@ -14,7 +14,7 @@ do_pickers (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Pickers");
@@ -50,6 +50,7 @@ do_pickers (GtkWidget *do_widget)
gtk_widget_set_hexpand (label, TRUE);
picker = gtk_file_chooser_button_new ("Pick a File",
GTK_FILE_CHOOSER_ACTION_OPEN);
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (picker), FALSE);
gtk_grid_attach (GTK_GRID (table), label, 0, 2, 1, 1);
gtk_grid_attach (GTK_GRID (table), picker, 1, 2, 1, 1);

View File

@@ -174,7 +174,7 @@ do_pixbufs (GtkWidget *do_widget)
{
GError *error;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Pixbufs");

View File

@@ -99,30 +99,27 @@ day_selected_cb (GtkCalendar *calendar,
GtkWidget *popover;
GdkEvent *event;
gdouble x, y;
GtkWidget *widget;
GtkPopoverHolder *holder = GTK_POPOVER_HOLDER (user_data);
event = gtk_get_current_event ();
if (gdk_event_get_event_type (event) != GDK_BUTTON_PRESS)
return;
gdk_event_get_position (event, &x, &y);
widget = gtk_native_get_for_surface (gdk_event_get_surface (event));
gtk_widget_translate_coordinates (widget,
gdk_event_get_coords (event, &x, &y);
gtk_widget_translate_coordinates (gtk_get_event_widget (event),
GTK_WIDGET (calendar),
x, y,
&rect.x, &rect.y);
rect.width = rect.height = 1;
popover = create_popover (GTK_WIDGET (holder),
popover = create_popover (GTK_WIDGET (calendar),
gtk_entry_new (),
GTK_POS_BOTTOM);
gtk_popover_set_pointing_to (GTK_POPOVER (popover), &rect);
gtk_widget_show (popover);
gdk_event_unref (event);
g_object_unref (event);
}
GtkWidget *
@@ -130,12 +127,10 @@ do_popover (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
GtkWidget *popover, *box, *widget;
GtkWidget *entry;
GtkWidget *calendar;
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Popovers");
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 24);
g_object_set (box, "margin", 24, NULL);
@@ -153,13 +148,11 @@ do_popover (GtkWidget *do_widget)
G_CALLBACK (toggle_changed_cb), popover);
gtk_container_add (GTK_CONTAINER (box), widget);
entry = gtk_entry_new ();
widget = gtk_popover_holder_new ();
gtk_popover_holder_set_child (GTK_POPOVER_HOLDER (widget), entry);
widget = gtk_entry_new ();
popover = create_complex_popover (widget, GTK_POS_TOP);
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry),
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (widget),
GTK_ENTRY_ICON_PRIMARY, "edit-find");
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry),
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (widget),
GTK_ENTRY_ICON_SECONDARY, "edit-clear");
g_signal_connect (widget, "icon-press",
@@ -168,11 +161,9 @@ do_popover (GtkWidget *do_widget)
G_CALLBACK (entry_size_allocate_cb), popover);
gtk_container_add (GTK_CONTAINER (box), widget);
calendar = gtk_calendar_new ();
widget = gtk_popover_holder_new ();
gtk_popover_holder_set_child (GTK_POPOVER_HOLDER (widget), calendar);
g_signal_connect (calendar, "day-selected",
G_CALLBACK (day_selected_cb), widget);
widget = gtk_calendar_new ();
g_signal_connect (widget, "day-selected",
G_CALLBACK (day_selected_cb), NULL);
gtk_container_add (GTK_CONTAINER (box), widget);
}

View File

@@ -178,7 +178,7 @@ do_rotated_text (GtkWidget *do_widget)
PangoLayout *layout;
PangoAttrList *attrs;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Rotated Text");

View File

@@ -250,7 +250,7 @@ do_search_entry (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Search Entry");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);

View File

@@ -68,7 +68,7 @@ do_search_entry2 (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Delayed Search Entry");
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (do_widget));
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);

View File

@@ -76,7 +76,7 @@ do_shortcuts (GtkWidget *do_widget)
if (!icons_added)
{
icons_added = TRUE;
gtk_icon_theme_add_resource_path (gtk_icon_theme_get_for_display (gtk_widget_get_display (do_widget)), "/icons");
gtk_icon_theme_add_resource_path (gtk_icon_theme_get_default (), "/icons");
}
g_type_ensure (G_TYPE_FILE_ICON);

View File

@@ -35,7 +35,7 @@ do_sidebar (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_widget_set_size_request (window, 500, 350);

View File

@@ -100,7 +100,7 @@ do_sizegroup (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Size Groups");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);

View File

@@ -462,7 +462,7 @@ do_sliding_puzzle (GtkWidget *do_widget)
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), restart);
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), tweak);
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Sliding Puzzle");

View File

@@ -18,7 +18,7 @@ do_tabs (GtkWidget *do_widget)
GtkTextBuffer *buffer;
PangoTabArray *tabs;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Tabs");
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));

View File

@@ -63,7 +63,7 @@ do_tagged_entry (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
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 ();

View File

@@ -59,7 +59,7 @@ do_textmask (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_widget_set_size_request (window, 400, 200);
gtk_window_set_title (GTK_WINDOW (window), "Text Mask");

View File

@@ -180,7 +180,7 @@ do_textscroll (GtkWidget *do_widget)
{
GtkWidget *hbox;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Automatic Scrolling");
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);

View File

@@ -23,7 +23,7 @@ do_textundo (GtkWidget *do_widget)
GtkTextBuffer *buffer;
GtkTextIter iter;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_default_size (GTK_WINDOW (window),

View File

@@ -9,7 +9,6 @@
#include <gtk/gtk.h>
#include <stdlib.h> /* for exit() */
#include "paintable.h"
static void easter_egg_callback (GtkWidget *button, gpointer data);
@@ -125,24 +124,20 @@ create_tags (GtkTextBuffer *buffer)
}
static void
insert_text (GtkTextView *view)
insert_text (GtkTextBuffer *buffer)
{
GtkWidget *widget = GTK_WIDGET (view);
GtkTextBuffer *buffer = gtk_text_view_get_buffer (view);
GtkTextIter iter;
GtkTextIter start, end;
GdkTexture *texture;
GtkIconTheme *icon_theme;
GtkIconPaintable *icon;
GdkPaintable *nuclear;
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (widget));
icon = gtk_icon_theme_lookup_icon (icon_theme,
"face-cool",
NULL,
32, 1,
gtk_widget_get_direction (widget),
0);
nuclear = gtk_nuclear_animation_new ();
icon_theme = gtk_icon_theme_get_default ();
texture = GDK_TEXTURE (gtk_icon_theme_load_icon (icon_theme,
"gtk3-demo",
32,
GTK_ICON_LOOKUP_GENERIC_FALLBACK,
NULL));
g_assert (texture);
/* get start of buffer; each insertion will revalidate the
* iterator to point to just after the inserted text.
@@ -238,11 +233,9 @@ insert_text (GtkTextView *view)
"heading", NULL);
gtk_text_buffer_insert (buffer, &iter, "The buffer can have images in it: ", -1);
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE (icon));
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE (icon));
gtk_text_buffer_insert_paintable (buffer, &iter, nuclear);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert_texture (buffer, &iter, texture);
gtk_text_buffer_insert (buffer, &iter, " for example.\n\n", -1);
gtk_text_buffer_insert_with_tags_by_name (buffer, &iter, "Spacing. ", -1,
@@ -387,8 +380,7 @@ insert_text (GtkTextView *view)
gtk_text_buffer_end_irreversible_action (buffer);
g_object_unref (icon);
g_object_unref (nuclear);
g_object_unref (texture);
}
static gboolean
@@ -474,7 +466,7 @@ do_textview (GtkWidget *do_widget)
GtkWidget *sw;
GtkTextBuffer *buffer;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_default_size (GTK_WINDOW (window),
@@ -514,7 +506,7 @@ do_textview (GtkWidget *do_widget)
gtk_container_add (GTK_CONTAINER (sw), view2);
create_tags (buffer);
insert_text (GTK_TEXT_VIEW (view1));
insert_text (buffer);
attach_widgets (GTK_TEXT_VIEW (view1));
attach_widgets (GTK_TEXT_VIEW (view2));
@@ -588,7 +580,7 @@ easter_egg_callback (GtkWidget *button,
g_object_unref (buffer);
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,

View File

@@ -135,13 +135,13 @@ clicked (GtkGestureClick *gesture,
gpointer data)
{
GtkWidget *window;
GdkEvent *event;
const GdkEvent *event;
GdkModifierType state;
window = gtk_widget_get_ancestor (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)), GTK_TYPE_WINDOW);
event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), NULL);
state = gdk_event_get_modifier_state (event);
gdk_event_get_state (event, &state);
if (state & GDK_CONTROL_MASK)
{

View File

@@ -15,6 +15,104 @@
<property name="margin">10</property>
<property name="row-spacing">10</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkToolbar">
<property name="hexpand">1</property>
<property name="show-arrow">0</property>
<style>
<class name="primary-toolbar"/>
</style>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Normal</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Active</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Raised</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
<style>
<class name="raised"/>
</style>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Raised Active</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
<property name="active">1</property>
<style>
<class name="raised"/>
</style>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive Active</property>
<property name="use-underline">1</property>
<property name="icon-name">edit-find</property>
<property name="is-important">1</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToolItem">
<child>
<object class="GtkEntry" id="entry1">
<property name="can-focus">1</property>
<property name="width-chars">10</property>
<property name="invisible-char">•</property>
<property name="placeholder-text" translatable="yes">Search...</property>
<property name="secondary-icon-name">edit-find-symbolic</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkToolItem">
<child>
<object class="GtkSwitch" id="switch1">
<property name="can-focus">1</property>
<property name="valign">center</property>
<property name="tooltip_text">Switch it</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="valign">center</property>
@@ -45,6 +143,68 @@
</child>
</object>
</child>
<child>
<object class="GtkToolbar">
<property name="hexpand">1</property>
<property name="toolbar-style">icons</property>
<style>
<class name="inline-toolbar"/>
</style>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Normal</property>
<property name="use-underline">1</property>
<property name="icon-name">list-add-symbolic</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Normal</property>
<property name="use-underline">1</property>
<property name="icon-name">list-add-symbolic</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Active</property>
<property name="use-underline">1</property>
<property name="icon-name">list-remove-symbolic</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Active</property>
<property name="use-underline">1</property>
<property name="icon-name">list-remove-symbolic</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive</property>
<property name="use-underline">1</property>
<property name="icon-name">edit-find-symbolic</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive Active</property>
<property name="use-underline">1</property>
<property name="icon-name">go-up-symbolic</property>
<property name="active">1</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="spacing">10</property>

View File

@@ -4,6 +4,103 @@
<property name="row-spacing">10</property>
<property name="margin">10</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkToolbar">
<property name="hexpand">1</property>
<property name="show-arrow">0</property>
<style>
<class name="primary-toolbar"/>
</style>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Normal</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Active</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Raised</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
<style>
<class name="raised"/>
</style>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Raised Active</property>
<property name="use-underline">1</property>
<property name="is-important">1</property>
<property name="icon-name">edit-find</property>
<property name="active">1</property>
<style>
<class name="raised"/>
</style>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive Active</property>
<property name="use-underline">1</property>
<property name="icon-name">edit-find</property>
<property name="is-important">1</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToolItem">
<child>
<object class="GtkEntry" id="entry1">
<property name="can-focus">1</property>
<property name="invisible-char">•</property>
<property name="placeholder-text" translatable="yes">Search...</property>
<property name="secondary-icon-name">edit-find-symbolic</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkToolItem">
<child>
<object class="GtkSwitch" id="switch1">
<property name="can-focus">1</property>
<property name="valign">center</property>
<property name="tooltip_text">Switch it</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="valign">center</property>
@@ -34,6 +131,68 @@
</child>
</object>
</child>
<child>
<object class="GtkToolbar">
<property name="hexpand">1</property>
<property name="toolbar-style">icons</property>
<style>
<class name="inline-toolbar"/>
</style>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Normal</property>
<property name="use-underline">1</property>
<property name="icon-name">list-add-symbolic</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Normal</property>
<property name="use-underline">1</property>
<property name="icon-name">list-add-symbolic</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Active</property>
<property name="use-underline">1</property>
<property name="icon-name">list-remove-symbolic</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="label" translatable="yes">Active</property>
<property name="use-underline">1</property>
<property name="icon-name">list-remove-symbolic</property>
<property name="active">1</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive</property>
<property name="use-underline">1</property>
<property name="icon-name">edit-find-symbolic</property>
</object>
</child>
<child>
<object class="GtkToggleToolButton">
<property name="homogeneous">1</property>
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insensitive Active</property>
<property name="use-underline">1</property>
<property name="icon-name">go-up-symbolic</property>
<property name="active">1</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="spacing">10</property>

View File

@@ -4,8 +4,8 @@
* with widgets to inform the theme about intended rendering.
*
* This demo shows some common examples where theming features
* of GTK are used for certain effects: primary toolbars
* and linked buttons.
* of GTK are used for certain effects: primary toolbars,
* inline toolbars and linked buttons.
*/
#include <gtk/gtk.h>
@@ -20,7 +20,7 @@ do_theming_style_classes (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Style Classes");

View File

@@ -18,7 +18,7 @@ do_transparent (GtkWidget *do_widget)
GtkWidget *label;
GtkWidget *picture;
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_default_size (GTK_WINDOW (window), 450, 450);

View File

@@ -390,7 +390,7 @@ do_tree_store (GtkWidget *do_widget)
GtkTreeModel *model;
/* create window, etc */
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Tree Store");

View File

@@ -63,7 +63,7 @@ do_video_player (GtkWidget *do_widget)
if (!window)
{
window = gtk_window_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Video Player");

View File

@@ -49,9 +49,7 @@ struct _IconBrowserWindow
GtkWidget *image4;
GtkWidget *image5;
GtkWidget *image6;
GtkWidget *image7;
GtkWidget *image8;
GtkWidget *label8;
GtkWidget *label6;
GtkWidget *description;
};
@@ -62,12 +60,6 @@ struct _IconBrowserWindowClass
G_DEFINE_TYPE(IconBrowserWindow, icon_browser_window, GTK_TYPE_APPLICATION_WINDOW);
static GtkIconTheme *
icon_browser_window_get_icon_theme (IconBrowserWindow *win)
{
return gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (win)));
}
static void
search_text_changed (GtkEntry *entry, IconBrowserWindow *win)
{
@@ -91,7 +83,6 @@ set_image (GtkWidget *image, const gchar *name, gint size)
static void
item_activated (GtkIconView *icon_view, GtkTreePath *path, IconBrowserWindow *win)
{
GtkIconTheme *icon_theme = icon_browser_window_get_icon_theme (win);
GtkTreeIter iter;
gchar *name;
gchar *description;
@@ -108,30 +99,28 @@ item_activated (GtkIconView *icon_view, GtkTreePath *path, IconBrowserWindow *wi
ICON_STORE_DESCRIPTION_COLUMN, &description,
-1);
if (name == NULL || !gtk_icon_theme_has_icon (icon_theme, name))
if (name == NULL || !gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), name))
{
g_free (description);
return;
}
gtk_window_set_title (GTK_WINDOW (win->details), name);
set_image (win->image1, name, 8);
set_image (win->image2, name, 16);
set_image (win->image3, name, 18);
set_image (win->image4, name, 24);
set_image (win->image5, name, 32);
set_image (win->image6, name, 48);
set_image (win->image7, name, 64);
set_image (win->image1, name, 16);
set_image (win->image2, name, 24);
set_image (win->image3, name, 32);
set_image (win->image4, name, 48);
set_image (win->image5, name, 64);
if (win->symbolic)
{
gtk_widget_show (win->image8);
gtk_widget_show (win->label8);
set_image (win->image8, name, 64);
gtk_widget_show (win->image6);
gtk_widget_show (win->label6);
set_image (win->image6, name, 64);
}
else
{
gtk_widget_hide (win->image8);
gtk_widget_hide (win->label8);
gtk_widget_hide (win->image6);
gtk_widget_hide (win->label6);
}
if (description && description[0])
{
@@ -155,19 +144,18 @@ add_icon (IconBrowserWindow *win,
const gchar *description,
const gchar *context)
{
GtkIconTheme *icon_theme = icon_browser_window_get_icon_theme (win);
gchar *regular_name;
gchar *symbolic_name;
regular_name = g_strdup (name);
if (!gtk_icon_theme_has_icon (icon_theme, regular_name))
if (!gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), regular_name))
{
g_free (regular_name);
regular_name = NULL;
}
symbolic_name = g_strconcat (name, "-symbolic", NULL);
if (!gtk_icon_theme_has_icon (icon_theme, symbolic_name))
if (!gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), symbolic_name))
{
g_free (symbolic_name);
symbolic_name = NULL;
@@ -360,7 +348,7 @@ get_image_paintable (GtkImage *image)
{
const gchar *icon_name;
GtkIconTheme *icon_theme;
GtkIconPaintable *icon;
GtkIconInfo *icon_info;
int size;
switch (gtk_image_get_storage_type (image))
@@ -371,15 +359,11 @@ get_image_paintable (GtkImage *image)
icon_name = gtk_image_get_icon_name (image);
size = gtk_image_get_pixel_size (image);
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (image)));
icon = gtk_icon_theme_lookup_icon (icon_theme,
icon_name,
NULL,
size, 1,
gtk_widget_get_direction (GTK_WIDGET (image)),
0);
if (icon == NULL)
icon_info = gtk_icon_theme_lookup_icon (icon_theme, icon_name, size,
GTK_ICON_LOOKUP_FORCE_SIZE | GTK_ICON_LOOKUP_GENERIC_FALLBACK);
if (icon_info == NULL)
return NULL;
return GDK_PAINTABLE (icon);
return gtk_icon_info_load_icon (icon_info, NULL);
default:
g_warning ("Image storage type %d not handled",
gtk_image_get_storage_type (image));
@@ -406,53 +390,43 @@ drag_begin (GtkDragSource *source,
}
}
static GdkContentProvider *
drag_prepare_texture (GtkDragSource *source,
double x,
double y,
GtkWidget *widget)
static void
get_texture (GValue *value,
gpointer data)
{
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (widget));
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (data));
if (!GDK_IS_TEXTURE (paintable))
return NULL;
return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, paintable);
if (GDK_IS_TEXTURE (paintable))
g_value_set_object (value, paintable);
}
static GdkContentProvider *
drag_prepare_file (GtkDragSource *source,
double x,
double y,
GtkWidget *widget)
static void
get_file (GValue *value,
gpointer data)
{
GdkContentProvider *content;
GtkIconTheme *icon_theme;
const char *name;
GtkIconPaintable *info;
GtkIconInfo *info;
GFile *file;
name = gtk_image_get_icon_name (GTK_IMAGE (widget));
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (widget));
name = gtk_image_get_icon_name (GTK_IMAGE (data));
info = gtk_icon_theme_lookup_icon (icon_theme,
name,
NULL,
32, 1,
gtk_widget_get_direction (widget),
0);
content = gdk_content_provider_new_typed (G_TYPE_FILE, gtk_icon_paintable_get_file (info));
info = gtk_icon_theme_lookup_icon (gtk_icon_theme_get_default (), name, -1, 0);
file = g_file_new_for_path (gtk_icon_info_get_filename (info));
g_value_set_object (value, file);
g_object_unref (file);
g_object_unref (info);
return content;
}
static void
setup_image_dnd (GtkWidget *image)
{
GdkContentProvider *content;
GtkDragSource *source;
source = gtk_drag_source_new ();
g_signal_connect (source, "prepare", G_CALLBACK (drag_prepare_texture), image);
content = gdk_content_provider_new_with_callback (GDK_TYPE_TEXTURE, get_texture, image);
gtk_drag_source_set_content (source, content);
g_object_unref (content);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
}
@@ -460,10 +434,14 @@ setup_image_dnd (GtkWidget *image)
static void
setup_scalable_image_dnd (GtkWidget *image)
{
GdkContentProvider *content;
GtkDragSource *source;
source = gtk_drag_source_new ();
g_signal_connect (source, "prepare", G_CALLBACK (drag_prepare_file), image);
content = gdk_content_provider_new_with_callback (G_TYPE_FILE, get_file, image);
gtk_drag_source_set_content (source, content);
g_object_unref (content);
g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source));
}
@@ -487,9 +465,7 @@ icon_browser_window_init (IconBrowserWindow *win)
setup_image_dnd (win->image3);
setup_image_dnd (win->image4);
setup_image_dnd (win->image5);
setup_image_dnd (win->image6);
setup_image_dnd (win->image7);
setup_scalable_image_dnd (win->image8);
setup_scalable_image_dnd (win->image6);
win->contexts = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, context_free);
@@ -546,9 +522,7 @@ icon_browser_window_class_init (IconBrowserWindowClass *class)
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image4);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image5);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image6);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image7);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image8);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, label8);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, label6);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, description);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), search_text_changed);

View File

@@ -53,26 +53,26 @@ drag_data_delete (GtkTreeDragSource *drag_source,
return FALSE;
}
static GdkContentProvider *
static gboolean
drag_data_get (GtkTreeDragSource *drag_source,
GtkTreePath *path)
GtkTreePath *path,
GtkSelectionData *selection)
{
GdkContentProvider *content;
GtkTreeIter iter;
gchar *text;
if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source), &iter, path))
return NULL;
return FALSE;
gtk_tree_model_get (GTK_TREE_MODEL (drag_source), &iter,
ICON_STORE (drag_source)->text_column, &text,
-1);
content = gdk_content_provider_new_typed (G_TYPE_STRING, text);
gtk_selection_data_set_text (selection, text, -1);
g_free (text);
return content;
return TRUE;
}

View File

@@ -198,7 +198,7 @@
<property name="halign">center</property>
<property name="valign">end</property>
<accessibility>
<relation type="labelled-by" target="label5"/>
<relation type="labelled-by" target="label6"/>
</accessibility>
<layout>
<property name="left-attach">5</property>
@@ -206,37 +206,11 @@
</layout>
</object>
</child>
<child>
<object class="GtkImage" id="image7">
<property name="halign">center</property>
<property name="valign">end</property>
<accessibility>
<relation type="labelled-by" target="label5"/>
</accessibility>
<layout>
<property name="left-attach">6</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkImage" id="image8">
<property name="halign">center</property>
<property name="valign">end</property>
<accessibility>
<relation type="labelled-by" target="label6"/>
</accessibility>
<layout>
<property name="left-attach">7</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">8×8</property>
<property name="label">16×16</property>
<style>
<class name="dim-label"/>
</style>
@@ -253,7 +227,7 @@
<object class="GtkLabel" id="label2">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">16×16</property>
<property name="label">24×24</property>
<style>
<class name="dim-label"/>
</style>
@@ -270,7 +244,7 @@
<object class="GtkLabel" id="label3">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">18×18</property>
<property name="label">32×32</property>
<style>
<class name="dim-label"/>
</style>
@@ -287,7 +261,7 @@
<object class="GtkLabel" id="label4">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">24×24</property>
<property name="label">48×48</property>
<style>
<class name="dim-label"/>
</style>
@@ -304,7 +278,7 @@
<object class="GtkLabel" id="label5">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">32×32</property>
<property name="label">64×64</property>
<style>
<class name="dim-label"/>
</style>
@@ -321,7 +295,7 @@
<object class="GtkLabel" id="label6">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">48×48</property>
<property name="label">scalable</property>
<style>
<class name="dim-label"/>
</style>
@@ -334,40 +308,6 @@
</layout>
</object>
</child>
<child>
<object class="GtkLabel" id="label7">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">64×64</property>
<style>
<class name="dim-label"/>
</style>
<accessibility>
<relation type="label-for" target="image7"/>
</accessibility>
<layout>
<property name="left-attach">6</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel" id="label8">
<property name="halign">center</property>
<property name="valign">baseline</property>
<property name="label">scalable</property>
<style>
<class name="dim-label"/>
</style>
<accessibility>
<relation type="label-for" target="image8"/>
</accessibility>
<layout>
<property name="left-attach">7</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
</object>
</child>
<child>

View File

@@ -385,11 +385,7 @@ show_open_filechooser (NodeEditorWindow *self)
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
GFile *cwd = g_file_new_for_path (".");
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
g_object_unref (cwd);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
g_signal_connect (dialog, "response", G_CALLBACK (open_response_cb), self);
gtk_widget_show (dialog);
}
@@ -410,20 +406,13 @@ save_response_cb (GtkWidget *dialog,
if (response == GTK_RESPONSE_ACCEPT)
{
GFile *file;
char *text;
char *text, *filename;
GError *error = NULL;
text = get_current_text (self->text_buffer);
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
g_file_replace_contents (file, text, -1,
NULL, FALSE,
G_FILE_CREATE_NONE,
NULL,
NULL,
&error);
if (error != NULL)
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
if (!g_file_set_contents (filename, text, -1, &error))
{
GtkWidget *dialog;
@@ -438,9 +427,7 @@ save_response_cb (GtkWidget *dialog,
gtk_widget_show (dialog);
g_error_free (error);
}
g_free (text);
g_object_unref (file);
g_free (filename);
}
gtk_widget_destroy (dialog);
@@ -461,11 +448,8 @@ save_cb (GtkWidget *button,
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
GFile *cwd = g_file_new_for_path (".");
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), cwd, NULL);
g_object_unref (cwd);
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), ".");
g_signal_connect (dialog, "response", G_CALLBACK (save_response_cb), self);
gtk_widget_show (dialog);
}
@@ -539,10 +523,10 @@ export_image_response_cb (GtkWidget *dialog,
if (response == GTK_RESPONSE_ACCEPT)
{
GFile *file;
char *filename;
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
if (!gdk_texture_save_to_png (texture, g_file_peek_path (file)))
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
if (!gdk_texture_save_to_png (texture, filename))
{
GtkWidget *message_dialog;
@@ -554,8 +538,7 @@ export_image_response_cb (GtkWidget *dialog,
g_signal_connect (message_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
gtk_widget_show (message_dialog);
}
g_object_unref (file);
g_free (filename);
}
gtk_widget_destroy (dialog);
@@ -582,6 +565,7 @@ export_image_cb (GtkWidget *button,
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
g_signal_connect (dialog, "response", G_CALLBACK (export_image_response_cb), texture);
gtk_widget_show (dialog);
}

View File

@@ -20,8 +20,6 @@
#include "config.h"
#include <stdlib.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
@@ -2002,13 +2000,6 @@ toggle_action (GSimpleAction *action,
g_variant_new_boolean (!g_variant_get_boolean (state)));
}
static gboolean
quit_timeout (gpointer data)
{
exit (0);
return G_SOURCE_REMOVE;
}
int
main (int argc, char *argv[])
{
@@ -2074,9 +2065,6 @@ main (int argc, char *argv[])
g_application_add_main_option (G_APPLICATION (app), "version", 0, 0, G_OPTION_ARG_NONE, "Show program version", NULL);
if (g_getenv ("GTK_DEBUG_AUTO_QUIT"))
g_timeout_add (500, quit_timeout, NULL);
g_signal_connect (app, "handle-local-options", G_CALLBACK (local_options), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);

View File

@@ -1815,26 +1815,26 @@ microphone-sensitivity-medium-symbolic</property>
</object>
</child>
<child>
<object class="GtkBox" id="toolbar">
<object class="GtkToolbar" id="toolbar">
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="label" translatable="yes">New</property>
<property name="icon-name">document-new</property>
<property name="tooltip-text" translatable="yes">Create a new document</property>
</object>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="label" translatable="yes">Save</property>
<property name="icon-name">document-save</property>
<property name="tooltip-text" translatable="yes">Save the current document</property>
</object>
</child>
<child>
<object class="GtkSeparator"/>
<object class="GtkSeparatorToolItem"/>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="label" translatable="yes">Search</property>
<property name="icon-name">edit-find</property>
<property name="action-name">win.search</property>
@@ -1842,7 +1842,7 @@ microphone-sensitivity-medium-symbolic</property>
</object>
</child>
<child>
<object class="GtkButton">
<object class="GtkToolButton">
<property name="sensitive">0</property>
<property name="label" translatable="yes">Insert</property>
<property name="icon-name">insert-image</property>
@@ -2007,26 +2007,27 @@ microphone-sensitivity-medium-symbolic</property>
</object>
</child>
<child>
<object class="GtkBox">
<object class="GtkToolbar">
<property name="toolbar-style">icons</property>
<style>
<class name="linked"/>
<class name="inline-toolbar"/>
</style>
<child>
<object class="GtkButton" id="decrease_button">
<object class="GtkToolButton" id="decrease_button">
<property name="icon-name">zoom-out-symbolic</property>
<property name="tooltip-text">Normal icons</property>
<signal name="clicked" handler="decrease_icon_size" object="iconview1" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkButton" id="increase_button">
<object class="GtkToolButton" id="increase_button">
<property name="icon-name">zoom-in-symbolic</property>
<property name="tooltip-text">Large icons</property>
<signal name="clicked" handler="increase_icon_size" object="iconview1" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkButton" id="reset_button">
<object class="GtkToolButton" id="reset_button">
<property name="icon-name">zoom-original-symbolic</property>
<property name="tooltip-text">Inherited icon size</property>
<signal name="clicked" handler="reset_icon_size" object="iconview1" swapped="yes"/>
@@ -2477,25 +2478,26 @@ microphone-sensitivity-medium-symbolic</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkBox">
<object class="GtkToolbar">
<property name="orientation">vertical</property>
<property name="toolbar-style">icons</property>
<child>
<object class="GtkButton" id="toolbutton1">
<object class="GtkToolButton" id="toolbutton1">
<property name="icon-name">document-open-symbolic</property>
</object>
</child>
<child>
<object class="GtkButton" id="toolbutton2">
<object class="GtkToolButton" id="toolbutton2">
<property name="icon-name">send-to-symbolic</property>
</object>
</child>
<child>
<object class="GtkButton" id="toolbutton3">
<object class="GtkToolButton" id="toolbutton3">
<property name="icon-name">view-fullscreen-symbolic</property>
</object>
</child>
<child>
<object class="GtkButton" id="toolbutton4">
<object class="GtkToolButton" id="toolbutton4">
<property name="icon-name">star-new-symbolic</property>
</object>
</child>
@@ -2555,7 +2557,7 @@ microphone-sensitivity-medium-symbolic</property>
<child>
<object class="GtkOverlay">
<child type="overlay">
<object class="GtkBox" id="totem_like_osd">
<object class="GtkToolbar" id="totem_like_osd">
<property name="visible">0</property>
<property name="opacity">0.9</property>
<property name="margin">20</property>
@@ -2564,36 +2566,48 @@ microphone-sensitivity-medium-symbolic</property>
<class name="osd"/>
</style>
<child>
<object class="GtkBox">
<style>
<class name="linked"/>
</style>
<object class="GtkToolItem">
<child>
<object class="GtkButton">
<property name="icon-name">pan-start-symbolic</property>
</object>
</child>
<child>
<object class="GtkButton">
<property name="icon-name">pan-end-symbolic</property>
<object class="GtkBox">
<style>
<class name="linked"/>
</style>
<child>
<object class="GtkButton">
<property name="icon-name">pan-start-symbolic</property>
</object>
</child>
<child>
<object class="GtkButton">
<property name="icon-name">pan-end-symbolic</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScale">
<property name="hexpand">1</property>
<property name="draw-value">0</property>
<property name="adjustment">adjustment1</property>
<object class="GtkToolItem">
<property name="expand-item">1</property>
<child>
<object class="GtkScale">
<property name="draw-value">0</property>
<property name="adjustment">adjustment1</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkVolumeButton">
<property name="orientation">vertical</property>
<property name="value">.5</property>
<style>
<class name="image-button"/>
</style>
<object class="GtkToolItem">
<child>
<object class="GtkVolumeButton">
<property name="orientation">vertical</property>
<property name="value">.5</property>
<style>
<class name="image-button"/>
</style>
</object>
</child>
</object>
</child>
</object>

60
docs/developers.txt Normal file
View File

@@ -0,0 +1,60 @@
Things to care about when using/programing for GTK
==================================================
This file is meant to collect some frequently triggered failures when
programming for/with Gtk, having the spirit of a developers FAQ.
It is also the correct place to list up things that programmers should
care about in general.
In the hope that this text might be useful to someone,
- Tim Janik <timj@gimp.org>
1998/02/11
Automatic destruction of widgets on removal from parent
-------------------------------------------------------
This is a reference counting issue, you would want to refer
to refcounting.txt on it.
What are all the widget flags about?
------------------------------------
Refer to the file widget_system.txt which covers widget flags and the
resulting invariants in a detailed way.
GdkSurface pointers may be NULL in GdkEvents
-------------------------------------------
The notification nature of the signal mechanism might cause events to
be emitted that have their GdkSurface pointer set to NULL.
This is due to the fact that certain events need to be emitted after the
real GdkSurface of a widget is not any longer pertinent.
It's up to the signal handling function (application) to check for the
window field of the event structure to be != NULL, if it is going to
perform any operations through Gdk calls on it.
Events that a likely to trigger a missing check for the window pointer
currently are (and correspond to the trailing signals):
GDK_SELECTION_CLEAR GtkWidget::selection_clear_event
GDK_FOCUS_CHANGE GtkWidget::focus_in_event
GtkWidget::focus_out_event
Events that are assured to have a valid GdkEvent.any.surface field are
GDK_EXPOSE GtkWidget::expose_event
Writing Gdk functions
---------------------
When writing Gdk functions that operate on GdkSurface structures in any
meaningful sense, that is casting to a GdkSurfacePrivate structure for
access to fields other then GdkSurface.user_data, the programmer is
recommended to check for the GdkSurfacePrivate.destroyed field to be ==
FALSE, especially if the GdkSurfacePrivate.xwindow field is used.
Silent abortion of the Gdk function is the correct behaviour if this
condition isn't met.

205
docs/dnd_internals.txt Normal file
View File

@@ -0,0 +1,205 @@
This document describes some of the internals of the DND handling
code.
Organization
============
The DND code is split between a lowlevel part - gdkdnd.c and a
highlevel part - gtkdnd.c. To put it simply, gdkdnd.c contain the
portions of DND code that are easiest to do in raw X, while gtkdnd.c
contains the portions of DND that are easiest to do with an event loop
and high level selection handling.
Except for a few details of selection handling, most of the
dependencies on the DND protocol are confined to gdkdnd.c.
There are two or three supported protocols - Motif DND,
Xdnd and a pseudo-protocol ROOTWIN, which is used for drops
on root windows that aren't really accepting drops.
gdkdnd.c divides into 4 pieces:
1) Utility functions (finding client windows)
2) Motif specific code (the biggest chunk)
3) Xdnd specific code
4) The public interfaces
The code in gtkdnd.c roughly consists of three parts
1) General utility functions
2) Destination side code
3) Source side code.
Both on the source and dest side, there is some division
between the low level layers and the default handlers,
though they are rather mixed in many cases.
Structures and Memory Management
================================
Information about source sites and drop sites is stored
in the structures GtkSourceSite and GtkDestSite.
Information about in-progress drags and drops is stored
in the structures GtkSourceInfo and GtkDestInfo.
The GtkSourceInfo structure is created when the drag
begins, and persists until the drag either completes
or times out. A pointer to it is stored in
dataset-data for the GdkDragContext, however there
is no ownership. If the SourceInfo is destroyed
before the context, the field is simply cleared.
A GtkDestInfo is attached to each GdkDragContext
that is received for an incoming drag. In contrast
to the SourceInfo the DestInfo is "owned" by the
context, and when the context is destroyed, destroyed.
The GDK API
===========
It is expect that the GDK DND API will never be
used by anything other than the DND code in GTK.
/* Drag and Drop */
GdkDragContext * gdk_drag_context_new (void);
These create and refcount GdkDragContexts in a
straightforward manner.
/* Destination side */
void gdk_drag_status (GdkDragContext *context,
GdkDragAction action,
guint32 time);
void gdk_drag_finish (GdkDragContext *context,
gboolean success,
guint32 time);
GdkAtom gdk_drag_get_selection (GdkDragContext *context);
/* Source side */
GdkDragContext * gdk_drag_begin (GdkSurface *window,
GList *targets,
GdkDragAction actions);
gboolean gdk_drag_get_protocol (guint32 xid,
GdkDragProtocol *protocol);
void gdk_drag_find_window (GdkDragContext *context,
GdkSurface *drag_surface,
gint x_root,
gint y_root,
GdkSurface **dest_surface,
GdkDragProtocol *protocol);
gboolean gdk_drag_motion (GdkDragContext *context,
GdkSurface *dest_surface,
GdkDragProtocol protocol,
gint x_root,
gint y_root,
GdkDragAction action,
guint32 time);
void gdk_drag_drop (GdkDragContext *context,
guint32 time);
void gdk_drag_abort (GdkDragContext *context,
guint32 time);
GdkAtom gdk_drag_get_selection (GdkDragContext *context);
Retrieves the selection that will be used to communicate
the data for the drag context (valid on both source
and dest sides)
Cursors and window hierarchies
==============================
The DND code, when possible (and it isn't possible over
Motif window) uses a shaped window as a drag icon.
Because the cursor may fall inside this window during the
drag, we actually have to figure out which window
the cursor is in _ourselves_ so we can ignore the
drag icon properly. (Oh for OutputOnly windows!)
To avoid obscene amounts of server traffic (which are only
slightly observable locally, but would really kill a
session over a slow link), the code in GDK does
XGetWindowAttributes for every child of the root window at
the beginning of the drag, then selects with
SubstructureNotifyMask on the root window, so that
it can update this list.
It probably would be easier to just reread the entire
list when one of these events occurs, instead of
incrementally updating, but updating the list in
sync was sort of fun code, so I did it that way ;-)
There is also a problem of trying to follow the
mouse cursor as well as possible. Currently, the
code uses PointerMotionHint, and an XQueryPointer
on MotionNotify events. This results in pretty
good syncing, but may result in somewhat poor
accuracy for drops. (Because the coordinates of
the drop are the coordinates when the server receives
the button press, which might actually be before
the XQueryPointer for the previous MotionNotify
event is done.)
Probably better is doing MotionNotify compression
and discarding MotionNotify events when there
are more on the queue before the next ButtonPress/Release.
Proxying
========
A perhaps rather unusual feature of GTK's DND is proxying. A
dest site can be specified as a proxy drop site for another
window. This is most needed for the plug-socket code - the
socket needs to pass on drags to the plug since the original
source only sees toplevel windows. However, it can also be
used as a user visible proxy - i.e., dragging to buttons on
the taskbar.
Internally, when the outer drag enters a proxy dest site, a
new source drag is created, with SourceInfo and
GdkDragContext. From the GDK side, it looks much like a
normal source drag; on the GTK side, most of the code is
disjoint. The need to pass in a specific target window
is the reason why the GDK DND API splits
gdk_drag_find_window() and gdk_drag_motion().
For proxy drags, the GtkDestInfo and GtkSourceInfo for the
drag point at each other.
Because the abstraction of the drag protocol is at the GDK
level, a proxy drag from Motif to Xdnd or vice versa happens
pretty much automatically during the drag, though the
drop can get complicated. For Xdnd <-> Motif,
Motif <-> Xdnd, or Motif <-> Motif drags, it is necessary to
for the Proxy to retrieve the data and pass it on to
the true destination, since either the selection names
differ or (Motif<->Motif), the proxy needs to know
about the XmDRAG_SUCCESS/FAILURE selection targets.
Further Reading:
================
Xdnd:
The spec is at:
http://www.cco.caltech.edu/~jafl/xdnd/
Motif:
The Motif DND protocol is best described in the
Hungry Programmers _Inside Lesstif_ book, available
from:
http://www.igpm.rwth-aachen.de/~albrecht/hungry.html
Harald Albrecht and Mitch Miers have done a far
better job at documenting the DND protocol then
anything the OpenGroup has produced.
Owen Taylor
otaylor@redhat.com
Oct 18, 1998

161
docs/focus_tracking.txt Normal file
View File

@@ -0,0 +1,161 @@
Notational conventions
======================
We have a window W that we are tracking events on. Focus
can be on the following classes of objects
None : defined by X protocol
PointerRoot : defined by X protocol
W : the window itself
Ancestor : An ancestor of W, including W's root window
Descendant : A descendant of W
Other: : A window that is neither an ancestor or
descendant of W
has_pointer(W): the pointer is in W or one of its descendants.
NotifyPointer events
====================
X sends FocusIn or FocusOut events to W with a detail of NotifyPointer
in the following transitions, when the pointer is inside W
Other => Ancestor: FocusIn
Ancestor => {Other,None}: FocusOut
Ancestor => PointerRoot: FocusOut, then FocusIn
{None,W,Descendant,Other} => PointerRoot: FocusIn
PointerRoot => Ancestor: FocusOut, then FocusIn
PointerRoot => {None,W,Descendant,Other} => FocusOut
[ Ignoring keyboard grabs for the moment ]
Basic focus tracking algorithm
==============================
Keystroke events are delivered within W if and only if one of two
predicates hold:
has_focus_window(W): F==W || F==Descendant
has_pointer_focus(W): (F==Ancestor || F==PointerRoot) && has_pointer(W)
These two conditions are mutually exclusive.
has_focus_window(W) is easy to track.
FocusIn: detail != NotifyInferior: Set has_focus_iwndow
FocusOut: detail != NotifyInferior: Clear has_focus_iwndow
has_pointer_focus(W) is harder to track.
We can separate out the transitions from !has_pointer_focus(W) to
has_pointer_focus(W) into four cases:
T1: [(F==W || F==Descendant) => F==Ancestor]; has_pointer(W)
T2: [(F==W || F==Descendant) => F==PointerRoot]; has_pointer(W)
T3: [(F==None || F==Other) => (F==PointerRoot || F==Ancestor)];
has_pointer(W)
T4: [!has_pointer(W) => has_pointer(W)]; (F==Ancestor || F==PointerRoot)
All of these can be tracked by watching events on W.
T1:, we get a FocusOut with a mode of Ancestor or Virtual
We need to separately track has_pointer(W) to distinguish
this from the case where we get these events and !has_pointer(W)
T2, T3: together these are exactly the cases where we get
FocusIn/NotifyPointer.
For T4, we get an EnterNotify with the focus flag set. An
EnterNotify with a focus flag set will also be sent if
F==W, so we have to to explicitly test for that case
using has_focus_window(W)
The transitions from has_pointer_focus(W) to !has_pointer_focus(W)
are exactly the opposite
F1: [(F==W || F==Descendant) <= F==Ancestor]; has_pointer(W)
F2: [(F==W || F==Descendant) <= F==PointerRoot]; has_pointer(W)
F3: [(F==None || F==Other) <= (F==PointerRoot || F==Ancestor)];
has_pointer(W)
F4: [!has_pointer(W) <= has_pointer(W)]; (F==Ancestor || F==PointerRoot)
And can be tracked in the same ways:
F1: we get a FocusIn with a mode of Ancestor or Virtual
We need to separately track has_pointer(W) to distinguish
this from the case we get these events and !has_pointer(W)
F2, F3: together these are exactly the cases where we get
FocusOut/NotifyPointer.
F4: we get an LeaveNotify with the focus flag set. An
LeaveNotify with a focus flag set will also be sent if
F==W, so we have to to explicitly test for that case
using has_focus_window(W).
Modifications for keyboard grabs
================================
The above algorithm ignores keyboard grabs, which also
generate focus events, and needs to be modified somewhat
to take keyboard grabs into effect. The basic idea
is that for has_pointer_focus(W)/has_window_focus(W) we track
them ignoring grabs and ungrabs, and then supplement
that with another predicate has_focus(W) which pays
attention to grabs and ungrabs.
Modification 1:
When tracking has_pointer_focus(W), ignore all Focus
events with a mode of NotifyGrab or NotifyUngrab.
Note that this means that with grabs, we don't perfectly.
track the delivery of keyboard events ... since we think
we are getting events in the case where
has_pointer_focus(W) && !(G == None || G==W || G==descendant)
But the X protocol doesn't provide sufficient information
to do this right... example:
F=Ancestor, G=None => F=Ancestor, G=Ancestor
We stop getting events, but receive no notification.
The case of no window manager and keyboard grabs is pretty
rare in any case.
Modification 2:
When tracking has_focus_window(W), ignore all Focus
events with a mode of NotifyGrab or NotifyUngrab.
Modification 3: instead of calculating focus as
has_focus_window(W) || has_pointer_focus(W)
Calculate it as
has_focus(W) || has_pointer_focus(W)
where has_focus(W) is defined as:
has_focus(W): F==W || F==Descendant || G=W
Tracking has_focus(W) is done by
FocusIn: detail != NotifyInferior, mode != NotifyWhileGrabbed:
set has_focus
FocusOut: detail != NotifyInferior, mode != NotifyWhileGrabbed:
clear has_focus
We still need to track has_focus_window(W) for the T4/F4
transitions.

View File

@@ -44,6 +44,7 @@
<xi:include href="xml/gdkcontentprovider.xml" />
<xi:include href="xml/gdkcontentserializer.xml" />
<xi:include href="xml/gdkcontentdeserializer.xml" />
<xi:include href="xml/properties.xml" />
<xi:include href="xml/gdkapplaunchcontext.xml" />
<xi:include href="xml/pixbufs.xml" />
<xi:include href="xml/pango_interaction.xml" />

View File

@@ -1,4 +1,10 @@
# GdkAtom is an opaque typedef
<TYPEDEF>
<NAME>GdkAtom</NAME>
typedef struct _GdkAtom *GdkAtom;
</TYPEDEF>
<MACRO>
<NAME>GDK_WINDOWING_X11</NAME>
#define GDK_WINDOWING_X11

View File

@@ -94,6 +94,7 @@ gdk_display_get_default_seat
gdk_display_list_seats
gdk_display_get_n_monitors
gdk_display_get_monitor
gdk_display_get_primary_monitor
gdk_display_get_monitor_at_surface
gdk_display_get_clipboard
gdk_display_get_primary_clipboard
@@ -172,10 +173,12 @@ GdkSurfaceType
GdkSurfaceHints
GdkGeometry
GdkGravity
GdkAnchorHints
GdkSurfaceEdge
GdkSurfaceTypeHint
GdkSurfaceState
gdk_surface_new_toplevel
gdk_surface_new_temp
gdk_surface_new_popup
gdk_surface_get_parent
gdk_surface_destroy
@@ -183,6 +186,7 @@ gdk_surface_get_surface_type
gdk_surface_get_display
gdk_surface_show
gdk_surface_show_unraised
gdk_surface_show_with_auto_dismissal
gdk_surface_hide
gdk_surface_is_destroyed
gdk_surface_is_visible
@@ -204,9 +208,7 @@ gdk_surface_set_keep_above
gdk_surface_set_keep_below
gdk_surface_set_opacity
gdk_surface_resize
gdk_surface_present_popup
gdk_surface_get_popup_rect_anchor
gdk_surface_get_popup_surface_anchor
gdk_surface_move_to_rect
gdk_surface_raise
gdk_surface_lower
gdk_surface_restack
@@ -347,6 +349,14 @@ gdk_content_formats_get_type
gdk_content_formats_builder_get_type
</SECTION>
<SECTION>
<TITLE>Properties and Atoms</TITLE>
<FILE>properties</FILE>
GdkAtom
gdk_text_property_to_utf8_list_for_display
gdk_utf8_to_string_target
</SECTION>
<SECTION>
<TITLE>Pango Interaction</TITLE>
<FILE>pango_interaction</FILE>
@@ -358,6 +368,7 @@ gdk_pango_layout_line_get_clip_region
<TITLE>Cairo Interaction</TITLE>
<FILE>cairo_interaction</FILE>
gdk_surface_create_similar_surface
gdk_cairo_get_clip_rectangle
gdk_cairo_set_source_rgba
gdk_cairo_set_source_pixbuf
gdk_cairo_rectangle
@@ -471,7 +482,7 @@ gdk_device_get_history
gdk_device_free_history
GdkTimeCoord
gdk_device_get_axis
gdk_device_get_axis_names
gdk_device_list_axes
gdk_device_get_axis_value
gdk_device_get_last_event_surface
@@ -569,54 +580,61 @@ GDK_BUTTON_MIDDLE
GDK_BUTTON_SECONDARY
<SUBSECTION>
gdk_event_ref
gdk_event_unref
<SUBSECTION>
gdk_event_get_event_type
gdk_event_get_surface
gdk_event_get_device
gdk_event_get_source_device
gdk_event_get_device_tool
gdk_event_get_time
gdk_event_get_display
GdkEventSequence
gdk_event_get_event_sequence
gdk_event_get_modifier_state
gdk_event_get_position
gdk_event_new
gdk_event_copy
gdk_event_get_axes
gdk_event_get_axis
gdk_event_get_pointer_emulated
gdk_button_event_get_button
gdk_scroll_event_get_direction
gdk_scroll_event_get_deltas
gdk_scroll_event_is_stop
gdk_key_event_get_keyval
gdk_key_event_get_keycode
gdk_key_event_get_scancode
gdk_key_event_get_group
gdk_key_event_is_modifier
gdk_focus_event_get_in
gdk_touch_event_get_emulating_pointer
gdk_crossing_event_get_mode
gdk_crossing_event_get_detail
gdk_configure_event_get_size
gdk_touchpad_event_get_gesture_phase
gdk_touchpad_event_get_n_fingers
gdk_touchpad_event_get_deltas
gdk_touchpad_pinch_event_get_angle_delta
gdk_touchpad_pinch_event_get_scale
gdk_pad_button_event_get_button
gdk_pad_axis_event_get_value
gdk_pad_event_get_group_mode
gdk_drag_event_get_drop
gdk_grab_broken_event_get_grab_surface
gdk_event_get_motion_history
<SUBSECTION>
gdk_event_get_button
gdk_event_get_click_count
gdk_event_get_coords
gdk_event_get_keycode
gdk_event_get_keyval
gdk_event_get_scroll_direction
gdk_event_get_scroll_deltas
gdk_event_is_scroll_stop_event
gdk_event_get_state
gdk_event_get_time
gdk_event_get_surface
gdk_event_get_event_type
GdkEventSequence
gdk_event_get_event_sequence
gdk_events_get_angle
gdk_events_get_center
gdk_events_get_distance
gdk_event_triggers_context_menu
gdk_event_get_seat
gdk_event_get_scancode
gdk_event_get_pointer_emulated
gdk_event_get_crossing_detail
gdk_event_get_crossing_mode
gdk_event_get_drop
gdk_event_get_focus_in
gdk_event_get_grab_surface
gdk_event_get_motion_history
gdk_event_get_key_group
gdk_event_get_key_is_modifier
gdk_event_get_pad_axis_value
gdk_event_get_pad_button
gdk_event_get_pad_group_mode
gdk_event_get_touch_emulating_pointer
gdk_event_get_touchpad_angle_delta
gdk_event_get_touchpad_deltas
gdk_event_get_touchpad_gesture_n_fingers
gdk_event_get_touchpad_gesture_phase
gdk_event_get_touchpad_scale
gdk_event_is_sent
<SUBSECTION>
gdk_get_show_events
gdk_set_show_events
gdk_event_set_display
gdk_event_get_display
gdk_event_get_device
gdk_event_set_device
gdk_event_get_source_device
gdk_event_set_source_device
gdk_event_get_device_tool
gdk_event_set_device_tool
<SUBSECTION Standard>
GDK_TYPE_EVENT
@@ -653,31 +671,6 @@ GDK_TYPE_PAINTABLE
gdk_paintable_get_type
</SECTION>
<SECTION>
<FILE>gdkpopuplayout</FILE>
<TITLE>GdkPopupLayout</TITLE>
GdkPopupLayout
GdkAnchorHints
GDK_TYPE_POPUP_LAYOUT
gdk_popup_layout_get_type
gdk_popup_layout_new
gdk_popup_layout_ref
gdk_popup_layout_unref
gdk_popup_layout_copy
gdk_popup_layout_equal
gdk_popup_layout_set_anchor_rect
gdk_popup_layout_get_anchor_rect
gdk_popup_layout_set_rect_anchor
gdk_popup_layout_get_rect_anchor
gdk_popup_layout_set_surface_anchor
gdk_popup_layout_get_surface_anchor
gdk_popup_layout_set_anchor_hints
gdk_popup_layout_get_anchor_hints
gdk_popup_layout_set_offset
gdk_popup_layout_get_offset
</SECTION>
<SECTION>
<TITLE>Textures</TITLE>
<FILE>textures</FILE>
@@ -842,6 +835,8 @@ gdk_x11_surface_set_frame_sync_enabled
gdk_x11_keymap_get_group_for_state
gdk_x11_keymap_key_is_modifier
gdk_x11_visual_get_xvisual
gdk_x11_atom_to_xatom_for_display
gdk_x11_xatom_to_atom_for_display
gdk_x11_get_xatom_by_name_for_display
gdk_x11_get_xatom_name_for_display
gdk_x11_set_sm_client_id
@@ -1132,6 +1127,7 @@ gdk_monitor_get_scale_factor
gdk_monitor_get_refresh_rate
GdkSubpixelLayout
gdk_monitor_get_subpixel_layout
gdk_monitor_is_primary
gdk_monitor_is_valid
<SUBSECTION Standard>
@@ -1208,7 +1204,6 @@ gdk_clipboard_get_type
GdkContentProvider
GdkContentProviderClass
gdk_content_provider_new_for_value
gdk_content_provider_new_typed
gdk_content_provider_new_for_bytes
gdk_content_provider_ref_formats
gdk_content_provider_ref_storable_formats

Some files were not shown because too many files have changed in this diff Show More