Compare commits

..

1 Commits

Author SHA1 Message Date
Matthias Clasen fe7d078d5a Flip gl textures when used in the gl renderer 2018-01-17 13:42:19 -05:00
2889 changed files with 305448 additions and 331421 deletions
-1
View File
@@ -1 +0,0 @@
/subprojects/*/
-119
View File
@@ -1,119 +0,0 @@
stages:
- build
- flatpak
- deploy
.cache-paths: &cache-paths
paths:
- _ccache/
- subprojects/gdk-pixbuf/
- subprojects/glib/
- subprojects/graphene/
- subprojects/libepoxy/
- subprojects/pango/
fedora-x86_64:
image: registry.gitlab.gnome.org/gnome/gtk/master:v5
stage: build
script:
- bash -x ./.gitlab-ci/test-docker.sh
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"
cache:
key: "$CI_JOB_NAME"
<<: *cache-paths
.mingw-defaults: &mingw-defaults
stage: build
tags:
- win32
script:
- C:\msys64\usr\bin\pacman --noconfirm -Syyuu
- C:\msys64\usr\bin\bash -lc "bash -x ./.gitlab-ci/test-msys2.sh"
cache:
key: "%CI_JOB_NAME%"
<<: *cache-paths
msys2-mingw32:
variables:
MSYSTEM: "MINGW32"
CHERE_INVOKING: "yes"
<<: *mingw-defaults
.flatpak-defaults: &flatpak-defaults
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
stage: flatpak
artifacts:
paths:
- "${APPID}-dev.flatpak"
expire_in: 1 day
script:
- bash -x ./.gitlab-ci/flatpak-build.sh "${APPID}"
# Manual jobs, for branches and MRs
.flatpak-manual: &flatpak-manual
<<: *flatpak-defaults
when: manual
# Only build Flatpak bundles automatically on master
.flatpak-master: &flatpak-master
<<: *flatpak-defaults
only:
- master
flatpak-manual:demo:
variables:
APPID: org.gtk.Demo4
<<: *flatpak-manual
flatpak-master:demo:
variables:
APPID: org.gtk.Demo4
<<: *flatpak-master
flatpak-manual:widget-factory:
variables:
APPID: org.gtk.WidgetFactory4
<<: *flatpak-manual
flatpak-master:widget-factory:
variables:
APPID: org.gtk.WidgetFactory4
<<: *flatpak-master
flatpak-manual:icon-browser:
variables:
APPID: org.gtk.IconBrowser4
<<: *flatpak-manual
flatpak-master:icon-browser:
variables:
APPID: org.gtk.IconBrowser4
<<: *flatpak-master
pages:
image: registry.gitlab.gnome.org/gnome/gtk/master:v4
stage: deploy
script:
- meson -Ddocumentation=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
-85
View File
@@ -1,85 +0,0 @@
FROM fedora:29
RUN dnf -y install \
hicolor-icon-theme \
adwaita-icon-theme \
atk-devel \
at-spi2-atk-devel \
avahi-gobject-devel \
cairo-devel \
cairo-gobject-devel \
ccache \
colord-devel \
cups-devel \
dejavu-sans-mono-fonts \
desktop-file-utils \
elfutils-libelf-devel \
fribidi-devel \
gcc \
gcc-c++ \
gdk-pixbuf2-devel \
gdk-pixbuf2-modules \
gettext \
git \
glib2-devel \
glibc-devel \
glibc-headers \
gobject-introspection-devel \
graphene-devel \
gstreamer1-devel \
gstreamer1-plugins-good \
gstreamer1-plugins-bad-free-devel \
gstreamer1-plugins-base-devel \
gtk-doc \
iso-codes \
itstool \
json-glib-devel \
lcov \
libattr-devel \
libepoxy-devel \
libffi-devel \
libmount-devel \
librsvg2 \
libselinux-devel \
libXcomposite-devel \
libXcursor-devel \
libXcursor-devel \
libXdamage-devel \
libXfixes-devel \
libXi-devel \
libXinerama-devel \
libxkbcommon-devel \
libXrandr-devel \
libXrender-devel \
libxslt \
mesa-dri-drivers \
mesa-libEGL-devel \
mesa-libwayland-egl-devel \
ninja-build \
pango-devel \
pcre-devel \
python3 \
python3-pip \
python3-wheel \
redhat-rpm-config \
sassc \
systemtap-sdt-devel \
vulkan-devel \
wayland-devel \
wayland-protocols-devel \
which \
xorg-x11-server-Xvfb \
&& dnf clean all
RUN pip3 install meson==0.50.0
RUN pip3 install jinja2
ARG HOST_USER_ID=5555
ENV HOST_USER_ID ${HOST_USER_ID}
RUN useradd -u $HOST_USER_ID -ms /bin/bash user
USER user
WORKDIR /home/user
ENV LANG C.UTF-8
-44
View File
@@ -1,44 +0,0 @@
#!/bin/bash
set -e
appid=$1
builddir=app
repodir=repo
flatpak-builder \
--stop-at=gtk \
${builddir} \
build-aux/flatpak/${appid}.json
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 \
-Dbuild-tests=false \
-Dbuild-examples=false \
-Dintrospection=false \
-Ddemos=true \
_build .
flatpak-builder \
--run ${builddir} build-aux/flatpak/${appid}.json \
ninja -C _build install
flatpak-builder \
--finish-only \
--repo=${repodir} \
${builddir} \
build-aux/flatpak/${appid}.json
flatpak build-bundle \
${repodir} \
${appid}-dev.flatpak \
--runtime-repo=https://flathub.org/repo/flathub.flatpakrepo \
${appid}
-363
View File
@@ -1,363 +0,0 @@
#!/usr/bin/env python3
# Turns a Mason testlog.json file into an HTML report
#
# Copyright 2019 GNOME Foundation
#
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# Original author: Emmanuele Bassi
import argparse
import datetime
import json
import os
import sys
from jinja2 import Template
REPORT_TEMPLATE = '''
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{ report.project_name }} Test Report</title>
<meta charset="utf-8" />
<style type="text/css">
body {
background: white;
color: #333;
font-family: 'Cantarell', sans-serif;
}
h1 {
color: #333333;
font-size: 1.9em;
font-weight: normal;
margin-bottom: 1em;
border-bottom: 1px solid #333333;
}
header {
position: fixed;
padding-bottom: 12px;
margin-bottom: 24px;
background: rgba(255, 255, 255, 0.85);
box-shadow: 0 0 1px rgba(0, 0, 0, 0.15);
z-index: 500;
left: 0;
top: 0;
width: 100%;
color: rgba(0, 0, 0, 0.3);
transform: translateY(0px);
transition: .2s background-color, color;
box-sizing: border-box;
display: block;
visibility: visible;
text-align: center;
}
article {
padding-top: 200px;
margin: 2em;
}
div.report-meta {
width: auto;
border: 1px solid #ccc;
padding: .5em 2em;
color: #3c3c3c;
}
span.result {
font-weight: bold;
}
span.pass {
color: rgb(51, 209, 122);
}
span.skip {
color: rgb(255, 163, 72);
}
span.fail {
color: rgb(224, 27, 36);
}
span.xfail {
color: rgb(163, 71, 186);
}
div.result {
border-top: 1px solid #c0c0c0;
padding-top: 1em;
padding-bottom: 1em;
width: 100%;
}
div.result h4 {
border-bottom: 1px solid #c0c0c0;
margin-bottom: 0.7em;
}
pre {
color: #fafafa;
background-color: black;
border-radius: 6px;
box-shadow: 0px 5px 8px 0px rgba(0, 0, 0, 0.25);
font-family: monospace;
line-height: 1.2em;
border: none;
padding: 10px 1em;
font-size: 0.9em;
overflow: auto;
white-space: pre;
word-break: normal;
word-wrap: normal;
}
ul.passed li {
display: inline;
}
ul.passed li:after {
content: ",";
}
ul.passed li:last-child:after {
content: "";
}
ul.images {
padding-bottom: 1em;
}
ul.images li {
display: inline;
}
</style>
</head>
<body>
<header>
<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="summary">
<h3>Summary</h3>
<ul>
<li><strong>Total units:</strong> {{ report.total_units }}</li>
<li><strong>Passed:</strong> {{ report.total_successes }}</li>
<li><strong>Failed:</strong> {{ report.total_failures }}</li>
</ul>
</div>
</section>
{% for suite_result in report.results_list %}
<section>
<div class="result">
<h3>Suite: {{ suite_result.suite_name }}</h3>
<ul>
<li><strong>Units:</strong> {{ suite_result.n_units }}</li>
<li><strong>Passed:</strong> {{ suite_result.n_successes }}</li>
<li><strong>Failed:</strong> {{ suite_result.n_failures }}</li>
</ul>
<div class="successes">
<h4>Passed</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>
{% else %}
<li>None</li>
{% endfor %}
</ul>
<h4>Skipped</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>Expected failures</h4>
<ul>
{% for success in suite_result.successes if success.result == 'EXPECTEDFAIL' %}
<li>{{ success.name }} - result: <span class="result xfail">{{ success.result }}</span><br/>
{% if success.stdout %}
Output: <pre>{{ success.stdout }}</pre>
{% endif %}
{% if success.image_data is defined %}
<ul class="images">
<li><img alt="ref" src="{{ success.image_data.ref }}" /></li>
<li><img alt="out" src="{{ success.image_data.out }}" /></li>
<li><img alt="diff" src="{{ success.image_data.diff }}" /></li>
</ul>
{% endif %}
</li>
{% else %}
<li>None</li>
{% endfor %}
</ul>
</div>
<div class="failures">
<h4>Failed</h4>
<ul class="failed">
{% for failure in suite_result.failures if failure.result == 'FAIL' %}
<li>{{ failure.name }} - 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>Timed out</h4>
<ul class="failed">
{% for failure in suite_result.failures if failure.result == 'TIMEOUT' %}
<li>{{ failure.name }} - 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 %}
</article>
</body>
</html>
'''
aparser = argparse.ArgumentParser(description='Turns a Meson test log into an HTML report')
aparser.add_argument('--project-name', metavar='NAME',
help='The project name',
default='Unknown')
aparser.add_argument('--job-id', metavar='ID',
help='The job ID for the report',
default=None)
aparser.add_argument('--branch', metavar='NAME',
help='Branch of the project being tested',
default='master')
aparser.add_argument('--output', metavar='FILE',
help='The output HTML file, stdout by default',
type=argparse.FileType('w', encoding='UTF-8'),
default=sys.stdout)
aparser.add_argument('--reftest-suite', metavar='NAME',
help='The name of the reftests suite',
default='reftest')
aparser.add_argument('--reftest-output-dir', metavar='DIR',
help='The output directory for reftests data',
default=None)
aparser.add_argument('infile', metavar='FILE',
help='The input testlog.json, stdin by default',
type=argparse.FileType('r', encoding='UTF-8'),
default=sys.stdin)
args = aparser.parse_args()
outfile = args.output
suites = {}
for line in args.infile:
data = json.loads(line)
(full_suite, unit_name) = data['name'].split(' / ')
(project_name, suite_name) = full_suite.split(':')
unit = {
'project-name': project_name,
'suite': suite_name,
'name': unit_name,
'duration': data['duration'],
'returncode': data['returncode'],
'result': data['result'],
'stdout': data['stdout'],
}
if args.reftest_output_dir is not None and suite_name == args.reftest_suite:
filename = unit_name.split(' ')[1]
basename = os.path.splitext(filename)[0]
image_data = {
'ref': os.path.join(args.reftest_output_dir, '{}.ref.png'.format(basename)),
'out': os.path.join(args.reftest_output_dir, '{}.out.png'.format(basename)),
'diff': os.path.join(args.reftest_output_dir, '{}.diff.png'.format(basename)),
}
unit['image_data'] = image_data
units = suites.setdefault(full_suite, [])
units.append(unit)
report = {}
report['date'] = datetime.datetime.utcnow()
report['locale_date'] = report['date'].strftime("%c")
report['project_name'] = args.project_name
report['job_id'] = args.job_id
report['branch_name'] = args.branch
report['total_successes'] = 0
report['total_failures'] = 0
report['total_units'] = 0
report['results_list'] = []
for name, units in suites.items():
(project_name, suite_name) = name.split(':')
print('Processing {} suite {}:'.format(project_name, suite_name))
def if_failed(unit):
if unit['result'] in ['FAIL', 'TIMEOUT']:
return True
return False
def if_succeded(unit):
if unit['result'] in ['OK', 'EXPECTEDFAIL', 'SKIP']:
return True
return False
successes = list(filter(if_succeded, units))
failures = list(filter(if_failed, units))
n_units = len(units)
n_successes = len(successes)
n_failures = len(failures)
report['total_units'] += n_units
report['total_successes'] += n_successes
report['total_failures'] += n_failures
print(' - {}: {} total, {} pass, {} fail'.format(suite_name, n_units, n_successes, n_failures))
suite_report = {
'suite_name': suite_name,
'n_units': n_units,
'successes': successes,
'n_successes': n_successes,
'failures': failures,
'n_failures': n_failures,
}
report['results_list'].append(suite_report)
template = Template(REPORT_TEMPLATE)
outfile.write(template.render({'report': report}))
-109
View File
@@ -1,109 +0,0 @@
#!/usr/bin/env python3
# Turns a Meson testlog.json file into a JUnit XML report
#
# Copyright 2019 GNOME Foundation
#
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# Original author: Emmanuele Bassi
import argparse
import datetime
import json
import os
import sys
import xml.etree.ElementTree as ET
aparser = argparse.ArgumentParser(description='Turns a Meson test log into a JUnit report')
aparser.add_argument('--project-name', metavar='NAME',
help='The project name',
default='unknown')
aparser.add_argument('--job-id', metavar='ID',
help='The job ID for the report',
default='Unknown')
aparser.add_argument('--branch', metavar='NAME',
help='Branch of the project being tested',
default='master')
aparser.add_argument('--output', metavar='FILE',
help='The output file, stdout by default',
type=argparse.FileType('w', encoding='UTF-8'),
default=sys.stdout)
aparser.add_argument('infile', metavar='FILE',
help='The input testlog.json, stdin by default',
type=argparse.FileType('r', encoding='UTF-8'),
default=sys.stdin)
args = aparser.parse_args()
outfile = args.output
testsuites = ET.Element('testsuites')
testsuites.set('id', '{}/{}'.format(args.job_id, args.branch))
testsuites.set('package', args.project_name)
testsuites.set('timestamp', datetime.datetime.utcnow().isoformat(timespec='minutes'))
suites = {}
for line in args.infile:
data = json.loads(line)
(full_suite, unit_name) = data['name'].split(' / ')
(project_name, suite_name) = full_suite.split(':')
duration = data['duration']
return_code = data['returncode']
log = data['stdout']
unit = {
'suite': suite_name,
'name': unit_name,
'duration': duration,
'returncode': return_code,
'stdout': log,
}
units = suites.setdefault(suite_name, [])
units.append(unit)
for name, units in suites.items():
print('Processing suite {} (units: {})'.format(name, len(units)))
def if_failed(unit):
if unit['returncode'] != 0:
return True
return False
def if_succeded(unit):
if unit['returncode'] == 0:
return True
return False
successes = list(filter(if_succeded, units))
failures = list(filter(if_failed, units))
print(' - {}: {} pass, {} fail'.format(name, len(successes), len(failures)))
testsuite = ET.SubElement(testsuites, 'testsuite')
testsuite.set('name', '{}/{}'.format(args.project_name, name))
testsuite.set('tests', str(len(units)))
testsuite.set('errors', str(len(failures)))
testsuite.set('failures', str(len(failures)))
for unit in successes:
testcase = ET.SubElement(testsuite, 'testcase')
testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
testcase.set('name', unit['name'])
testcase.set('time', str(unit['duration']))
for unit in failures:
testcase = ET.SubElement(testsuite, 'testcase')
testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
testcase.set('name', unit['name'])
testcase.set('time', str(unit['duration']))
failure = ET.SubElement(testcase, 'failure')
failure.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
failure.set('name', unit['name'])
failure.set('type', 'error')
failure.text = unit['stdout']
output = ET.tostring(testsuites, encoding='unicode')
outfile.write(output)
-11
View File
@@ -1,11 +0,0 @@
#!/bin/bash
set -e
TAG="registry.gitlab.gnome.org/gnome/gtk/master:v4"
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
-54
View File
@@ -1,54 +0,0 @@
#!/bin/bash
set -e
srcdir=$(pwd)
mkdir -p _ccache
export CCACHE_BASEDIR="$(pwd)"
export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
ccache --zero-stats
ccache --show-stats
export CCACHE_DISABLE=true
meson \
-Dx11-backend=true \
-Dwayland-backend=true \
-Dbroadway-backend=true \
-Dvulkan=yes \
--werror \
_build $srcdir
unset CCACHE_DISABLE
cd _build
ninja
ccache --show-stats
set +e
xvfb-run -a -s "-screen 0 1024x768x24" \
meson test \
--timeout-multiplier 2 \
--print-errorlogs \
--suite=gtk \
--no-suite=gtk:a11y
# Save the exit code
exit_code=$?
# We always want to run the report generators
$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
-53
View File
@@ -1,53 +0,0 @@
#!/bin/bash
set -e
if [[ "$MSYSTEM" == "MINGW32" ]]; then
export MSYS2_ARCH="i686"
else
export MSYS2_ARCH="x86_64"
fi
# Update everything
pacman --noconfirm -Suy
# Install the required packages
pacman --noconfirm -S --needed \
base-devel \
git \
mingw-w64-$MSYS2_ARCH-toolchain \
mingw-w64-$MSYS2_ARCH-ccache \
mingw-w64-$MSYS2_ARCH-pkg-config \
mingw-w64-$MSYS2_ARCH-gobject-introspection \
mingw-w64-$MSYS2_ARCH-meson \
mingw-w64-$MSYS2_ARCH-adwaita-icon-theme \
mingw-w64-$MSYS2_ARCH-atk \
mingw-w64-$MSYS2_ARCH-cairo \
mingw-w64-$MSYS2_ARCH-gdk-pixbuf2 \
mingw-w64-$MSYS2_ARCH-glib2 \
mingw-w64-$MSYS2_ARCH-graphene \
mingw-w64-$MSYS2_ARCH-json-glib \
mingw-w64-$MSYS2_ARCH-libepoxy \
mingw-w64-$MSYS2_ARCH-pango \
mingw-w64-$MSYS2_ARCH-fribidi \
mingw-w64-$MSYS2_ARCH-gst-plugins-bad \
mingw-w64-$MSYS2_ARCH-shared-mime-info
mkdir -p _ccache
export CCACHE_BASEDIR="$(pwd)"
export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
# Build
ccache --zero-stats
ccache --show-stats
export CCACHE_DISABLE=true
meson \
-Denable-x11-backend=false \
-Denable-wayland-backend=false \
-Denable-win32-backend=true \
-Dvulkan=no \
_build
unset CCACHE_DISABLE
ninja -C _build
ccache --show-stats
-36
View File
@@ -1,36 +0,0 @@
## Steps to reproduce
1. ...
2. ...
3. ...
<!--
You should try and reproduce with the demos applications available
under the `demos` directory, or the test programs in the `tests` directory.
Alternatively, please attach a *small and self-contained* example that
exhibits the issue.
-->
## Current behavior
<!--
Please describe the current behaviour
-->
## Expected outcome
<!--
Please describe the expected outcome
-->
## Version information
<!--
- Which version of GTK you are using
- What operating system and version
- For Linux, which distribution
- If you built GTK yourself, the list of options used to configure the build
-->
## Additional information
<!--
- Screenshots or screen recordings are useful for visual errors
- Please report any warning or message printed on the terminal
-->
-34
View File
@@ -1,34 +0,0 @@
## Steps to reproduce
1. ...
2. ...
3. ...
<!--
You should try and reproduce with the demos applications available
under the `demos` directory, or the test programs in the `tests` directory.
Alternatively, please attach a *small and self-contained* example that
exhibits the issue.
-->
## Version information
<!--
- Which version of GTK you are using
- What operating system and version
- for Linux, which distribution
- If you built GTK yourself, the list of options used to configure the build
-->
## Warnings
<!--
- If the application generates warning messages before crashing please
report them here
-->
## Backtrace
<!--
- Attaching a stack trace obtained using GDB is appreciated; follow the
instructions on the wiki:
https://wiki.gnome.org/Community/GettingInTouch/Bugzilla/GettingTraces
-->
+22 -248
View File
@@ -1,266 +1,40 @@
# Contribution guidelines
If you want to hack on the GTK+ project, you'll need to have the development
tools appropriate for your operating system, including:
Thank you for considering contributing to the GTK project!
These guidelines are meant for new contributors, regardless of their level
of proficiency; following them allows the maintainers of the GTK project to
more effectively evaluate your contribution, and provide prompt feedback to
you. Additionally, by following these guidelines you clearly communicate
that you respect the time and effort that the people developing GTK put into
managing the project.
GTK is a complex free software GUI toolkit, and it would not exist without
contributions from the free and open source software community. There are
many things that we value:
- bug reporting and fixing
- documentation and examples
- tests
- new features
Please, do not use the issue tracker for support questions. If you have
questions on how to use GTK effectively, you can use:
- the `#gtk` IRC channel on irc.gnome.org
- the [gtk](https://mail.gnome.org/mailman/listinfo/gtk-list) mailing list,
for general questions on GTK
- the [gtk-app-devel](https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list)
mailing list, for questions on application development with GTK
- the [gtk-devel](https://mail.gnome.org/mailman/listinfo/gtk-devel-list)
mailing list, for questions on developing GTK itself
You can also look at the GTK tag on [Stack
Overflow](https://stackoverflow.com/questions/tagged/gtk).
The issue tracker is meant to be used for actionable issues only.
## How to report bugs
### Security issues
You should not open a new issue for security related questions.
When in doubt, send an email to the [security](mailto:security@gnome.org)
mailing list.
### Bug reports
If you're reporting a bug make sure to list:
0. which version of GTK are you using?
0. which operating system are you using?
0. the necessary steps to reproduce the issue
0. the expected outcome
0. a description of the behavior; screenshots are also welcome
0. a small, self-contained example exhibiting the behavior; if this
is not available, try reproducing the issue using the GTK examples
or interactive tests
If the issue includes a crash, you should also include:
0. the eventual warnings printed on the terminal
0. a backtrace, obtained with tools such as GDB or LLDB
For small issues, such as:
- spelling/grammar fixes in the documentation
- typo correction
- comment clean ups
- changes to metadata files (CI, `.gitignore`)
- build system changes
- source tree clean ups and reorganizations
You should directly open a merge request instead of filing a new issue.
### Features and enhancements
Feature discussion can be open ended and require high bandwidth channels; if
you are proposing a new feature on the issue tracker, make sure to make
an actionable proposal, and list:
0. what you're trying to achieve
0. prior art, in other toolkits or applications
0. design and theming changes
If you're proposing the integration of new features it helps to have
multiple applications using shared or similar code, especially if they have
iterated over it various times.
Each feature should also come fully documented, and with tests.
## Your first contribution
### Prerequisites
If you want to contribute to the GTK project, you will need to have the
development tools appropriate for your operating system, including:
- Python 3.x
- Meson
- Ninja
- Gettext (19.7 or newer)
- a [C99 compatible compiler](https://wiki.gnome.org/Projects/GLib/CompilerRequirements)
- Python (2.7 or 3.x)
- Meson
- Ninja
- Gettext (19.7 or newer)
- a C99 compatible compiler
Up-to-date instructions about developing GNOME applications and libraries
can be found on [the GNOME Developer Center](https://developer.gnome.org).
can be found here:
The GTK project uses GitLab for code hosting and for tracking issues. More
information about using GitLab can be found [on the GNOME
wiki](https://wiki.gnome.org/GitLab).
https://developer.gnome.org
### Dependencies
Information about using git with GNOME can be found here:
In order to get GTK from Git installed on your system, you need to have the
required versions of all the software dependencies required by GTK; typically,
this means a recent version of GLib, Cairo, Pango, and ATK, as well as the
platform-specific dependencies for the windowing system you are using (Wayland,
X11, Windows, or macOS).
https://wiki.gnome.org/Git
The core dependencies for GTK are:
In order to get Git GTK+ installed on your system, you need to have the
required versions of all the GTK+ dependencies; typically, this means a
recent version of GLib, Cairo, Pango, and ATK.
- [GLib, GObject, and GIO](https://gitlab.gnome.org/GNOME/glib)
- [Cairo](http://cairographics.org)
- [Pango](https://gitlab.gnome.org/GNOME/pango)
- [GdkPixbuf](https://gitlab.gnome.org/GNOME/gdk-pixbuf)
- [Epoxy](https://github.com/anholt/libepoxy)
- [ATK](https://gitlab.gnome.org/GNOME/atk)
- [Graphene](https://github.com/ebassi/graphene)
GTK will attempt to download and build some of these dependencies if it
cannot find them on your system.
Additionally, you may want to look at projects that create a development
environment for you, like [jhbuild](https://wiki.gnome.org/HowDoI/Jhbuild)
and [gvsbuild](https://github.com/wingtk/gvsbuild).
### Getting started
You should start by forking the GTK repository from the GitLab web UI, and
cloning from your fork:
**Note**: if you plan to push changes to back to the master repository and
have a GNOME account, you want to use the following instead:
```sh
$ git clone https://gitlab.gnome.org/yourusername/gtk.git
$ cd gtk
$ git clone ssh://<username>@git.gnome.org/git/gtk+
```
**Note**: if you plan to push changes to back to the main repository and
have a GNOME account, you can skip the fork, and use the following instead:
```sh
$ git clone git@gitlab.gnome.org:GNOME/gtk.git
$ cd gtk
```
To compile the Git version of GTK on your system, you will need to
To compile the Git version of GTK+ on your system, you will need to
configure your build using Meson:
```sh
$ meson _builddir .
$ cd _builddir
$ ninja
```
Typically, you should work on your own branch:
```sh
$ git checkout -b your-branch
```
Once you've finished working on the bug fix or feature, push the branch
to the Git repository and open a new merge request, to let the GTK
maintainers review your contribution.
### Code reviews
Each contribution is reviewed by the core developers of the GTK project.
The [CODE-OWNERS](./docs/CODE-OWNERS) document contains the list of core
contributors to GTK and the areas for which they are responsible; you
should ensure to receive their review and signoff on your changes.
### Commit messages
The expected format for git commit messages is as follows:
```plain
Short explanation of the commit
Longer explanation explaining exactly what's changed, whether any
external or private interfaces changed, what bugs were fixed (with bug
tracker reference if applicable) and so forth. Be concise but not too
brief.
Closes #1234
```
- Always add a brief description of the commit to the _first_ line of
the commit and terminate by two newlines (it will work without the
second newline, but that is not nice for the interfaces).
- First line (the brief description) must only be one sentence and
should start with a capital letter unless it starts with a lowercase
symbol or identifier. Don't use a trailing period either. Don't exceed
72 characters.
- The main description (the body) is normal prose and should use normal
punctuation and capital letters where appropriate. Consider the commit
message as an email sent to the developers (or yourself, six months
down the line) detailing **why** you changed something. There's no need
to specify the **how**: the changes can be inlined.
- When committing code on behalf of others use the `--author` option, e.g.
`git commit -a --author "Joe Coder <joe@coder.org>"` and `--signoff`.
- If your commit is addressing an issue, use the
[GitLab syntax](https://docs.gitlab.com/ce/user/project/issues/automatic_issue_closing.html)
to automatically close the issue when merging the commit with the upstream
repository:
```plain
Closes #1234
Fixes #1234
Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1234
```
- If you have a merge request with multiple commits and none of them
completely fixes an issue, you should add a reference to the issue in
the commit message, e.g. `Bug: #1234`, and use the automatic issue
closing syntax in the description of the merge request.
### Commit access to the GTK repository
GTK is part of the GNOME infrastructure. At the current time, any
person with write access to the GNOME repository can merge changes to
GTK. This is a good thing, in that it encourages many people to work
on GTK, and progress can be made quickly. However, GTK is a fairly
large and complicated project on which many other things depend, so to
avoid unnecessary breakage, and to take advantage of the knowledge
about GTK that has been built up over the years, we'd like to ask
people committing to GTK to follow a few rules:
0. Ask first. If your changes are major, or could possibly break existing
code, you should always ask. If your change is minor and you've been
working on GTK for a while it probably isn't necessary to ask. But when
in doubt, ask. Even if your change is correct, somebody may know a
better way to do things. If you are making changes to GTK, you should
be subscribed to the [gtk-devel](https://mail.gnome.org/mailman/listinfo/gtk-devel-list)
mailing list; this is a good place to ask about intended changes.
The `#gtk` IRC channel on irc.gnome.org is also a good place to find GTK
developers to discuss changes, but if you live outside of the EU/US time
zones, an email to the gtk-devel mailing list is the most certain and
preferred method.
0. Ask _first_.
0. Always write a meaningful commit message. Changes without a sufficient
commit message will be reverted.
0. Never push to the `master` branch, or any stable branches, directly; you
should always go through a merge request, to ensure that the code is
tested on the CI infrastructure at the very least. A merge request is
also the proper place to get a comprehensive code review from the core
developers of GTK.
If you have been contributing to GTK for a while and you don't have commit
access to the repository, you may ask to obtain it following the [GNOME account
process](https://wiki.gnome.org/AccountsTeam/NewAccounts).
For information about submitting patches and pushing changes to Git, see the
`README.md` and `README.commits` files. In particular, don't, under any
circumstances, push anything to Git before reading and understanding
`README.commmits`.
-183
View File
@@ -1,186 +1,3 @@
Overview of Changes in GTK+ 3.96.0
==================================
* DND has been refactored. There are now separate GdkDrag and GdkDrop
objects. This work is still incomplete
* The GDK_SURFACE_SUBSURFACE surface type has been removed.
* Use of child surfaces has been greatly reduced. This work is still
incomplete
* The use of global coordinates in GDK apis has been reduced. This
work is still incomplete
* Events have been simplified and are just used for input
- expose events have been replaced by a GdkSurface::render signal
- configure events have been replaced by a GdkSurface::size-changed signal
- map events have been replaced by a GdkSurface::mapped property
- gdk_event_handler_set has been replaced by a GdkSurface::event signal
- key events no longer contain a string
- events on unmapped widgets are ignored
* Warping the pointer is no longer supported
* The Wayland backend now uses the Settings portal for GtkSettings
* The Wayland input module uses the text-input-unstable-v3 protocol
* The Broadway backend has been rewritten to work well with GSK
* The color chooser has a color picker
* GtkApplication tracks screensaver state and has a ::query-end signal
* The file chooser portal backend supports file filters
* A number of list models have been introduced, for internal use
and as public api:
- GtkMapListModel
- GtkSliceListModel
- GtkSortListModel
- GtkSelectionModel
- GtkSingleSelection
* Support for tabular menus and combo boxes has been dropped
* Key themes are no longer supported
* GtkInvisible has been dropped
* A GtkRoot interface has been added that is currently implemented
just by GtkWindow. This work is incomplete
* GtkWidgets can transform their children using projective linear
transformations. This functionality is available in CSS and
as GskTransform argument to gtk_widget_allocate. GtkFixed is
a container that exposes this functionality. For examples of this,
see the swing transition of GtkRevealer, the rotate transitions
of GtkStack or the Fixed Layout example in gtk-demo.
* GtkEntry functionality has been moved into a new GtkText widget,
the GtkEditable interface has been expanded, and new a new
GtkPasswordEntry widget has been introduced.
* Focus handling has been rewritten, and focus-change event
generation has been unified with crossing events.
* All demos and settings schemas have been renamed to avoid collisions
with GTK3.
* GtkWidget can now use a GtkLayoutManager for size allocation.
Layout managers can optionally use layout children holding layout
properties. GtkBinLayout, GtkBoxLayout, GtkGridLayout, GtkFixedLayout
and GtkCustomLayout are currently available, more layout manager
implementations will appear in the future.
* GtkAssistant, GtkStack and GtkNotebook now have publicly
accessible page objects for their children. The page objects
are also exposed via a list model.
* GtkContainer no longer supports child properties. All existing
child properties have been removed, converted to regular properties,
moved to layout properties or moved to child meta objects.
* A number of X11-specific GtkWindow and GdkSurface apis have been
removed
* GtkBuilder can specify object-valued properties inline.
* The gtk4-builder-tool simplify command has gained a --3to4 option
to convert GTK3 ui files to GTK4.
* The inspector can show child meta objects and layout properties.
Overview of Changes in GTK+ 3.94.0
==================================
* GdkPaintable is a new, powerful abstraction for drawable content.
gtk4-demo has a new "Paint" demo to show some of its capabilities.
* There is support for displaying media, with
GtkVideo
GtkMediaFile
GtkMediaStream
GtkMediaControls
* GtkFontChooser now supports OpenType font variations and features.
* The Ctrl-Shift-E support in the simple IM context has been replaced
by an optional completion popup for Emoji alpha codes. This can be
enabled with the GtkEntry::enable-emoji-completion property.
* Wayland has an input method based on the text protocol now
* Input methods, print backends and media backends have been converted
to GIOModules and extension points, and support for generic loadable
modules has been dropped. Platform im modules are always included.
* GdkWindow has been renamed to GdkSurface.
* Applications can now create their own GtkSnapshot objects for
intermediate rendering.
* Widget event signals have been replaced by event controllers,
and some new event controllers have been introduced for this:
GtkEventControllerMotion
GtkEventControllerKey
GtkGestureStylus
* Event controllers can now be created in .ui files.
* Invalidation tracking has been changed, only gtk_widget_queue_draw is left.
* Observing widget contents and size is now done by using the
GtkWidgetPaintable object instead of connecting to widget signals.
* The GtkWidget::draw signal has been removed, widgets need
to implement GtkWidget::snapshot.
* GdkTexture now has GdkMemoryTexture and GdkGLTexture subclasses.
* The Vulkan support in GDK can now use a particular device that is
specified by the GDK_VULKAN_DEVICE environment variable. use
GDK_VULKAN_DEVICE=list to see them all.
* GTK+ Inspector
- has logging support, and the logging settings have been cleaned up
- has an fps overlay
* Removed APIs and features:
Individual event signals such as ::proximity-in-event
The ::draw signal
threading support
non-platform IM modules
papi and test print backends
GtkPlacesSidebar
GtkRecentChooser
GtkToolPalette
GdkStatus
gtk_true, gtk_false
gtk_widget_show_now
gtk_widget_draw
gtk_render_icon_surface
* Incomplete transitions:
The ::event signal is not still there, but it will be removed
The DND apis are not finalized yet
* Translation updates:
Croatian
Esperanto
Estonian
French
Friulian
Icelandic
Latvian
Polish
Russian
Scottish Gaelic
Spanish
Overview of Changes in GTK+ 3.93.0
==================================
+72
View File
@@ -0,0 +1,72 @@
GTK+ is part of the GNOME git repository. At the current time, any
person with write access to the GNOME repository, can make changes to
GTK+. This is a good thing, in that it encourages many people to work
on GTK+, and progress can be made quickly. However, GTK+ is a fairly
large and complicated package that many other things depend on, so to
avoid unnecessary breakage, and to take advantage of the knowledge
about GTK+ that has been built up over the years, we'd like to ask
people committing to GTK+ to follow a few rules:
0) Ask first. If your changes are major, or could possibly break existing
code, you should always ask. If your change is minor and you've
been working on GTK+ for a while it probably isn't necessary
to ask. But when in doubt, ask. Even if your change is correct,
somebody may know a better way to do things.
If you are making changes to GTK+, you should be subscribed
to gtk-devel-list@gnome.org. (Subscription address:
gtk-devel-list-request@gnome.org.) This is a good place to ask
about intended changes.
#gtk+ on GIMPNet (irc.gimp.org, irc.us.gimp.org, irc.eu.gimp.org, ...)
is also a good place to find GTK+ developers to discuss changes with,
however, email to gtk-devel-list is the most certain and preferred
method.
1) Ask _first_.
2) With git, we no longer maintain a ChangeLog file, but you are expected
to produce a meaningful commit message. Changes without a sufficient
commit message will be reverted. See below for the expected format
of commit messages.
Notes:
* When developing larger features or complicated bug fixes, it is
advisable to work in a branch in your own cloned GTK+ repository.
You may even consider making your repository publically available
so that others can easily test and review your changes.
* The expected format for git commit messages is as follows:
=== begin example commit ===
Short explanation of the commit
Longer explanation explaining exactly what's changed, whether any
external or private interfaces changed, what bugs were fixed (with bug
tracker reference if applicable) and so forth. Be concise but not too brief.
=== end example commit ===
- Always add a brief description of the commit to the _first_ line of
the commit and terminate by two newlines (it will work without the
second newline, but that is not nice for the interfaces).
- First line (the brief description) must only be one sentence and
should start with a capital letter unless it starts with a lowercase
symbol or identifier. Don't use a trailing period either. Don't exceed
72 characters.
- The main description (the body) is normal prose and should use normal
punctuation and capital letters where appropriate. Normally, for patches
sent to a mailing list it's copied from there.
- When committing code on behalf of others use the --author option, e.g.
git commit -a --author "Joe Coder <joe@coder.org>" and --signoff.
Owen Taylor
13 Aug 1998
17 Apr 2001
Matthias Clasen
31 Mar 2009
+44 -33
View File
@@ -1,17 +1,15 @@
GTK — The GTK toolkit
=====================
[![Build Status](https://gitlab.gnome.org/GNOME/gtk/badges/master/build.svg)](https://gitlab.gnome.org/GNOME/gtk/pipelines)
GTK+ — The GTK toolkit
======================
General information
-------------------
GTK is a multi-platform toolkit for creating graphical user interfaces.
Offering a complete set of widgets, GTK is suitable for projects ranging
GTK+ is a multi-platform toolkit for creating graphical user interfaces.
Offering a complete set of widgets, GTK+ is suitable for projects ranging
from small one-off projects to complete application suites.
GTK is free software and part of the GNU Project. However, the
licensing terms for GTK, the GNU LGPL, allow it to be used by all
GTK+ is free software and part of the GNU Project. However, the
licensing terms for GTK+, the GNU LGPL, allow it to be used by all
developers, including those developing proprietary software, without any
license fees or royalties.
@@ -31,18 +29,13 @@ Information about mailing lists can be found at
- http://www.gtk.org/mailing-lists.php
Nightly documentation can be found at
- Gtk: https://gnome.pages.gitlab.gnome.org/gtk/gtk/
- Gdk: https://gnome.pages.gitlab.gnome.org/gtk/gdk/
- Gsk: https://gnome.pages.gitlab.gnome.org/gtk/gsk/
Building and installing
-----------------------
In order to build GTK you will need:
In order to build GTK+ you will need:
- [a C99 compatible compiler](https://wiki.gnome.org/Projects/GLib/CompilerRequirements)
- [Python 3](https://www.python.org/)
- a C99 compatible compiler
- Python 3
- [Meson](http://mesonbuild.com)
- [Ninja](https://ninja-build.org)
@@ -66,10 +59,10 @@ If you are building the X11 backend, you will also need:
- xrender
- xi
- xext
- xfixes
- xcursor
- xdamage
- xcomposite
- xfixes (optional)
- xcursor (optional)
- xdamage (optional)
- xcomposite (optional)
- [atk-bridge-2.0](https://download.gnome.org/sources/at-spi2-atk)
If you are building the Wayland backend, you will also need:
@@ -79,7 +72,7 @@ If you are building the Wayland backend, you will also need:
- Wayland-cursor
- Wayland-EGL
Once you have all the necessary dependencies, you can build GTK by using
Once you have all the necessary dependencies, you can build GTK+ by using
Meson:
```sh
@@ -94,7 +87,7 @@ You can run the test suite using:
$ meson test
```
And, finally, you can install GTK using:
And, finally, you can install GTK+ using:
```
$ sudo ninja install
@@ -112,27 +105,27 @@ Or [online](https://developer.gnome.org/gtk4/stable/gtk-building.html)
How to report bugs
------------------
Bugs should be reported on the [issues page](https://gitlab.gnome.org/GNOME/gtk/issues/new).
Bugs should be reported to the GNOME [bug tracking system](https://bugzilla.gnome.org/enter_bug.cgi?product=gtk%2b).
You will need an account for yourself.
In the bug report please include:
* Information about your system. For instance:
- which version of GTK you are using
- which version of GTK+ you are using
- what operating system and version
- for Linux, which distribution
- if you built GTK, the list of options used to configure the build
- if you built GTK+, the list of options used to configure the build
And anything else you think is relevant.
* How to reproduce the bug.
If you can reproduce it with one of the demo applications that are
built in the demos/ subdirectory, on one of the test programs that
are built in the tests/ subdirectory, that will be most convenient.
Otherwise, please include a short test program that exhibits the
behavior. As a last resort, you can also provide a pointer to a
larger piece of software that can be downloaded.
If you can reproduce it with one of the test programs that are built
in the tests/ subdirectory, that will be most convenient. Otherwise,
please include a short test program that exhibits the behavior.
As a last resort, you can also provide a pointer to a larger piece
of software that can be downloaded.
* If the bug was a crash, the exact text that was printed out
when the crash occurred.
@@ -140,10 +133,28 @@ In the bug report please include:
* Further information such as stack traces may be useful, but
is not necessary.
Contributing
------------
Patches should also be submitted to the bug tracking system. If the patch
fixes an existing bug, add the patch as an attachment to that bug report;
otherwise, enter a new bug report that describes the patch, and attach the
patch to that bug report.
Patches should be in Git-formatted form. You should use `git format-patch`
to generate them. We recommend using [git-bz](http://git.fishsoup.net/man/git-bz.html).
For more information on the recommended workflow, please read
[this wiki page](https://wiki.gnome.org/Git/WorkingWithPatches).
Please, follow the `CODING_STYLE` document in order to conform to GTK+'s
coding style when submitting a code contribution.
Release notes
-------------
The release notes for GTK are part of the migration guide in the API
The release notes for GTK+ are part of the migration guide in the API
reference. See:
- [3.x release notes](https://developer.gnome.org/gtk3/unstable/gtk-migrating-2-to-3.html)
@@ -152,7 +163,7 @@ reference. See:
Licensing terms
---------------
GTK is released under the terms of the GNU Lesser General Public License,
GTK+ is released under the terms of the GNU Lesser General Public License,
version 2.1 or, at your option, any later version, as published by the Free
Software Foundation.
-72
View File
@@ -1,72 +0,0 @@
{
"app-id": "org.gtk.Demo4",
"runtime": "org.gnome.Platform",
"runtime-version": "master",
"sdk": "org.gnome.Sdk",
"command": "gtk4-demo",
"tags": ["devel", "development", "nightly"],
"desktop-file-name-prefix": "(Development) ",
"finish-args": [
"--device=dri",
"--share=ipc",
"--socket=fallback-x11",
"--socket=wayland",
"--talk-name=org.gtk.vfs", "--talk-name=org.gtk.vfs.*"
],
"cleanup": [
"/include",
"/lib/pkgconfig", "/share/pkgconfig",
"/share/aclocal",
"/man", "/share/man", "/share/gtk-doc",
"*.la", ".a",
"/lib/girepository-1.0",
"/share/gir-1.0",
"/share/doc"
],
"modules": [
{
"name" : "wayland",
"buildsystem" : "autotools",
"builddir" : true,
"config-opts" : [
"--disable-documentation"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/wayland-project/wayland.git"
}
]
},
{
"name": "graphene",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib",
"-Dtests=false",
"-Dbenchmarks=false"
],
"sources": [
{
"type": "git",
"url": "https://github.com/ebassi/graphene.git"
}
]
},
{
"name": "gtk",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib"
],
"sources": [
{
"type": "git",
"url": "https://gitlab.gnome.org/GNOME/gtk.git"
}
]
}
]
}
@@ -1,72 +0,0 @@
{
"app-id": "org.gtk.IconBrowser4",
"runtime": "org.gnome.Platform",
"runtime-version": "master",
"sdk": "org.gnome.Sdk",
"command": "gtk4-icon-browser",
"tags": ["devel", "development", "nightly"],
"desktop-file-name-prefix": "(Development) ",
"finish-args": [
"--device=dri",
"--share=ipc",
"--socket=fallback-x11",
"--socket=wayland",
"--talk-name=org.gtk.vfs", "--talk-name=org.gtk.vfs.*"
],
"cleanup": [
"/include",
"/lib/pkgconfig", "/share/pkgconfig",
"/share/aclocal",
"/man", "/share/man", "/share/gtk-doc",
"*.la", ".a",
"/lib/girepository-1.0",
"/share/gir-1.0",
"/share/doc"
],
"modules": [
{
"name" : "wayland",
"buildsystem" : "autotools",
"builddir" : true,
"config-opts" : [
"--disable-documentation"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/wayland-project/wayland.git"
}
]
},
{
"name": "graphene",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib",
"-Dtests=false",
"-Dbenchmarks=false"
],
"sources": [
{
"type": "git",
"url": "https://github.com/ebassi/graphene.git"
}
]
},
{
"name": "gtk",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib"
],
"sources": [
{
"type": "git",
"url": "https://gitlab.gnome.org/GNOME/gtk.git"
}
]
}
]
}
@@ -1,72 +0,0 @@
{
"app-id": "org.gtk.WidgetFactory4",
"runtime": "org.gnome.Platform",
"runtime-version": "master",
"sdk": "org.gnome.Sdk",
"command": "gtk4-widget-factory",
"tags": ["devel", "development", "nightly"],
"desktop-file-name-prefix": "(Development) ",
"finish-args": [
"--device=dri",
"--share=ipc",
"--socket=fallback-x11",
"--socket=wayland",
"--talk-name=org.gtk.vfs", "--talk-name=org.gtk.vfs.*"
],
"cleanup": [
"/include",
"/lib/pkgconfig", "/share/pkgconfig",
"/share/aclocal",
"/man", "/share/man", "/share/gtk-doc",
"*.la", ".a",
"/lib/girepository-1.0",
"/share/gir-1.0",
"/share/doc"
],
"modules": [
{
"name" : "wayland",
"buildsystem" : "autotools",
"builddir" : true,
"config-opts" : [
"--disable-documentation"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/wayland-project/wayland.git"
}
]
},
{
"name": "graphene",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib",
"-Dtests=false",
"-Dbenchmarks=false"
],
"sources": [
{
"type": "git",
"url": "https://github.com/ebassi/graphene.git"
}
]
},
{
"name": "gtk",
"buildsystem": "meson",
"builddir": true,
"config-opts": [
"--libdir=/app/lib"
],
"sources": [
{
"type": "git",
"url": "https://gitlab.gnome.org/GNOME/gtk.git"
}
]
}
]
}
-31
View File
@@ -1,31 +0,0 @@
#!/usr/bin/env python3
import os
import sys
import subprocess
if 'DESTDIR' not in os.environ:
gtk_api_version = sys.argv[1]
gtk_abi_version = sys.argv[2]
gtk_libdir = sys.argv[3]
gtk_datadir = sys.argv[4]
gtk_moduledir = os.path.join(gtk_libdir, 'gtk-' + gtk_api_version, gtk_abi_version)
gtk_printmodule_dir = os.path.join(gtk_moduledir, 'printbackends')
gtk_immodule_dir = os.path.join(gtk_moduledir, 'immodules')
print('Compiling GSettings schemas...')
subprocess.call(['glib-compile-schemas',
os.path.join(gtk_datadir, 'glib-2.0', 'schemas')])
print('Updating icon cache...')
subprocess.call(['gtk4-update-icon-cache', '-q', '-t' ,'-f',
os.path.join(gtk_datadir, 'icons', 'hicolor')])
print('Updating module cache for print backends...')
os.makedirs(gtk_printmodule_dir, exist_ok=True)
subprocess.call(['gio-querymodules', gtk_printmodule_dir])
print('Updating module cache for input methods...')
os.makedirs(gtk_immodule_dir, exist_ok=True)
subprocess.call(['gio-querymodules', gtk_immodule_dir])
+21
View File
@@ -0,0 +1,21 @@
#!/bin/sh
gtk_api_version=$1
gtk_abi_version=$2
gtk_libdir=$3
gtk_datadir=$4
# Package managers set this so we don't need to run
if [ -z "$DESTDIR" ]; then
echo Compiling GSettings schemas...
glib-compile-schemas ${gtk_datadir}/glib-2.0/schemas
echo Updating desktop database...
update-desktop-database -q ${gtk_datadir}/applications
echo Updating icon cache...
gtk-update-icon-cache -q -t -f ${gtk_datadir}/icons/hicolor
echo Updating input method modules cache...
gtk4-query-immodules > ${gtk_libdir}/gtk-${gtk_api_version}/${gtk_abi_version}/immodules.cache
fi
-10
View File
@@ -41,9 +41,6 @@
/* Define to 1 if you have the <dlfcn.h> header file. */
#mesondefine HAVE_DLFCN_H
/* Have the ffmpeg library */
#mesondefine HAVE_FFMPEG
/* Define to 1 if you have the <ftw.h> header file. */
#mesondefine HAVE_FTW_H
@@ -56,9 +53,6 @@
/* Define if gio-unix is available */
#mesondefine HAVE_GIO_UNIX
/* Define if GStreamer support is available */
#mesondefine HAVE_GSTREAMER
/* Define to 1 if you have the `httpGetAuthString' function. */
#mesondefine HAVE_HTTPGETAUTHSTRING
@@ -286,10 +280,6 @@
/* Define to 1 if linux/memfd.h exists */
#mesondefine HAVE_LINUX_MEMFD_H
#mesondefine HAVE_LINUX_INPUT_H
#mesondefine HAVE_DEV_EVDEV_INPUT_H
#mesondefine GTK_SYSCONFDIR
#mesondefine GTK_LOCALEDIR
+25 -27
View File
@@ -200,20 +200,20 @@ activate_about (GSimpleAction *action,
};
gtk_show_about_dialog (GTK_WINDOW (window),
"program-name", "GTK Code Demos",
"version", g_strdup_printf ("%s,\nRunning against GTK %d.%d.%d",
"program-name", "GTK+ Code Demos",
"version", g_strdup_printf ("%s,\nRunning against GTK+ %d.%d.%d",
PACKAGE_VERSION,
gtk_get_major_version (),
gtk_get_minor_version (),
gtk_get_micro_version ()),
"copyright", "(C) 1997-2013 The GTK Team",
"copyright", "(C) 1997-2013 The GTK+ Team",
"license-type", GTK_LICENSE_LGPL_2_1,
"website", "http://www.gtk.org",
"comments", "Program to demonstrate GTK functions.",
"comments", "Program to demonstrate GTK+ functions.",
"authors", authors,
"documenters", documentors,
"logo-icon-name", "org.gtk.Demo4",
"title", "About GTK Code Demos",
"logo-icon-name", "gtk4-demo",
"title", "About GTK+ Code Demos",
NULL);
}
@@ -370,7 +370,7 @@ demo_application_init (DemoApplication *app)
GSettings *settings;
GAction *action;
settings = g_settings_new ("org.gtk.Demo4");
settings = g_settings_new ("org.gtk.Demo");
g_action_map_add_action_entries (G_ACTION_MAP (app),
app_entries, G_N_ELEMENTS (app_entries),
@@ -397,7 +397,7 @@ demo_application_window_store_state (DemoApplicationWindow *win)
{
GSettings *settings;
settings = g_settings_new ("org.gtk.Demo4");
settings = g_settings_new ("org.gtk.Demo");
g_settings_set (settings, "window-size", "(ii)", win->width, win->height);
g_settings_set_boolean (settings, "maximized", win->maximized);
g_settings_set_boolean (settings, "fullscreen", win->fullscreen);
@@ -409,7 +409,7 @@ demo_application_window_load_state (DemoApplicationWindow *win)
{
GSettings *settings;
settings = g_settings_new ("org.gtk.Demo4");
settings = g_settings_new ("org.gtk.Demo");
g_settings_get (settings, "window-size", "(ii)", &win->width, &win->height);
win->maximized = g_settings_get_boolean (settings, "maximized");
win->fullscreen = g_settings_get_boolean (settings, "fullscreen");
@@ -455,31 +455,29 @@ demo_application_window_constructed (GObject *object)
}
static void
demo_application_window_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
demo_application_window_size_allocate (GtkWidget *widget,
const GtkAllocation *allocation,
int baseline,
GtkAllocation *out_clip)
{
DemoApplicationWindow *window = (DemoApplicationWindow *)widget;
GTK_WIDGET_CLASS (demo_application_window_parent_class)->size_allocate (widget,
width,
height,
baseline);
GTK_WIDGET_CLASS (demo_application_window_parent_class)->size_allocate (widget, allocation,
baseline, out_clip);
if (!window->maximized && !window->fullscreen)
gtk_window_get_size (GTK_WINDOW (window), &window->width, &window->height);
}
static void
surface_state_changed (GtkWidget *widget)
window_state_changed (GtkWidget *widget)
{
DemoApplicationWindow *window = (DemoApplicationWindow *)widget;
GdkSurfaceState new_state;
GdkWindowState new_state;
new_state = gdk_surface_get_state (gtk_widget_get_surface (widget));
window->maximized = (new_state & GDK_SURFACE_STATE_MAXIMIZED) != 0;
window->fullscreen = (new_state & GDK_SURFACE_STATE_FULLSCREEN) != 0;
new_state = gdk_window_get_state (gtk_widget_get_window (widget));
window->maximized = (new_state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
window->fullscreen = (new_state & GDK_WINDOW_STATE_FULLSCREEN) != 0;
}
static void
@@ -487,15 +485,15 @@ demo_application_window_realize (GtkWidget *widget)
{
GTK_WIDGET_CLASS (demo_application_window_parent_class)->realize (widget);
g_signal_connect_swapped (gtk_widget_get_surface (widget), "notify::state",
G_CALLBACK (surface_state_changed), widget);
g_signal_connect_swapped (gtk_widget_get_window (widget), "notify::state",
G_CALLBACK (window_state_changed), widget);
}
static void
demo_application_window_unrealize (GtkWidget *widget)
{
g_signal_handlers_disconnect_by_func (gtk_widget_get_surface (widget),
surface_state_changed, widget);
g_signal_handlers_disconnect_by_func (gtk_widget_get_window (widget),
window_state_changed, widget);
GTK_WIDGET_CLASS (demo_application_window_parent_class)->unrealize (widget);
}
@@ -541,7 +539,7 @@ main (int argc, char *argv[])
GtkApplication *app;
app = GTK_APPLICATION (g_object_new (demo_application_get_type (),
"application-id", "org.gtk.Demo4.App",
"application-id", "org.gtk.Demo2",
"flags", G_APPLICATION_HANDLES_OPEN,
NULL));
+31 -19
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0"?>
<interface>
<template class="DemoApplicationWindow" parent="GtkApplicationWindow">
<property name="title" translatable="yes">Application Class</property>
@@ -7,37 +7,44 @@
<property name="icon-name">document-open</property>
<child>
<object class="GtkGrid">
<property name="visible">1</property>
<child>
<object class="GtkToolbar">
<property name="visible">1</property>
<property name="hexpand">1</property>
<style>
<class name="primary-toolbar"/>
</style>
<child>
<object class="GtkMenuToolButton" id="menutool">
<property name="visible">1</property>
<property name="icon-name">document-open</property>
</object>
</child>
<child>
<object class="GtkToolButton">
<property name="visible">1</property>
<property name="icon-name">application-exit</property>
<property name="action-name">app.quit</property>
</object>
</child>
<child>
<object class="GtkSeparatorToolItem"/>
<object class="GtkSeparatorToolItem">
<property name="visible">1</property>
</object>
</child>
<child>
<object class="GtkToolButton">
<property name="visible">1</property>
<property name="icon-name">applications-other</property>
<property name="action-name">win.logo</property>
</object>
</child>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</layout>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkInfoBar" id="infobar">
@@ -47,6 +54,7 @@
<object class="GtkBox" id="content_area">
<child>
<object class="GtkLabel" id="message">
<property name="visible">1</property>
<property name="hexpand">1</property>
</object>
</child>
@@ -56,44 +64,48 @@
<object class="GtkBox">
<child>
<object class="GtkButton">
<property name="visible">1</property>
<property name="valign">center</property>
<property name="label" translatable="yes">_OK</property>
<property name="use-underline">1</property>
<property name="use_underline">1</property>
<signal name="clicked" handler="clicked_cb"/>
</object>
</child>
</object>
</child>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">1</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkTextView">
<property name="visible">1</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<property name="buffer">buffer</property>
</object>
</child>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</layout>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkStatusbar" id="status">
<property name="hexpand">1</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</layout>
<property name="visible">1</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</packing>
</child>
</object>
</child>
+3 -3
View File
@@ -52,7 +52,7 @@ do_application_demo (GtkWidget *toplevel)
if (watch == 0)
watch = g_bus_watch_name (G_BUS_TYPE_SESSION,
"org.gtk.Demo4.App",
"org.gtk.Demo2",
0,
on_name_appeared,
on_name_vanished,
@@ -80,8 +80,8 @@ do_application_demo (GtkWidget *toplevel)
else
{
g_dbus_connection_call_sync (g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL),
"org.gtk.Demo4.App",
"/org/gtk/Demo4/App",
"org.gtk.Demo2",
"/org/gtk/Demo2",
"org.gtk.Actions",
"Activate",
g_variant_new ("(sava{sv})", "quit", NULL, NULL),
+1
View File
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.10 -->
<menu id="appmenu">
<section>
<item>
+4 -4
View File
@@ -80,7 +80,7 @@ on_entry_changed (GtkWidget *widget, gpointer data)
page_number = gtk_assistant_get_current_page (assistant);
current_page = gtk_assistant_get_nth_page (assistant, page_number);
text = gtk_editable_get_text (GTK_EDITABLE (widget));
text = gtk_entry_get_text (GTK_ENTRY (widget));
if (text && *text)
gtk_assistant_set_page_complete (assistant, current_page, TRUE);
@@ -96,12 +96,12 @@ create_page1 (GtkWidget *assistant)
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
label = gtk_label_new ("You must fill out this entry to continue:");
gtk_container_add (GTK_CONTAINER (box), label);
gtk_box_pack_start (GTK_BOX (box), label);
entry = gtk_entry_new ();
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
gtk_widget_set_valign (entry, GTK_ALIGN_CENTER);
gtk_container_add (GTK_CONTAINER (box), entry);
gtk_box_pack_start (GTK_BOX (box), entry);
g_signal_connect (G_OBJECT (entry), "changed",
G_CALLBACK (on_entry_changed), assistant);
@@ -119,7 +119,7 @@ create_page2 (GtkWidget *assistant)
checkbutton = gtk_check_button_new_with_label ("This is optional data, you may continue "
"even if you do not check this");
gtk_container_add (GTK_CONTAINER (box), checkbutton);
gtk_box_pack_start (GTK_BOX (box), checkbutton);
gtk_assistant_append_page (GTK_ASSISTANT (assistant), box);
gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), box, TRUE);
+345 -291
View File
@@ -2,336 +2,390 @@
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="window">
<property name="resizable">0</property>
<property name="can_focus">False</property>
<property name="resizable">False</property>
<property name="title">CSS Blend Modes</property>
<property name="default-width">400</property>
<property name="default-height">300</property>
<property name="default_width">400</property>
<property name="default_height">300</property>
<child>
<object class="GtkGrid">
<property name="row-spacing">12</property>
<property name="column-spacing">12</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">12</property>
<property name="column_spacing">12</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Blend mode:</property>
<property name="xalign">0</property>
<style>
<class name="dim-label"/>
</style>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</layout>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow">
<property name="can-focus">1</property>
<property name="vexpand">1</property>
<property name="shadow-type">in</property>
<property name="min-content-width">150</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="vexpand">True</property>
<property name="shadow_type">in</property>
<property name="min_content_width">150</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkStackSwitcher">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="hexpand">1</property>
<property name="hexpand">True</property>
<property name="stack">stack</property>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</layout>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkStack" id="stack">
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<property name="hhomogeneous">0</property>
<property name="vhomogeneous">0</property>
<property name="transition-type">crossfade</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="hhomogeneous">False</property>
<property name="vhomogeneous">False</property>
<property name="transition_type">crossfade</property>
<child>
<object class="GtkStackPage">
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="hexpand">False</property>
<property name="vexpand">True</property>
<property name="row_spacing">12</property>
<property name="column_spacing">12</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Duck</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Background</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<style>
<class name="duck"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<style>
<class name="gradient"/>
</style>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">
Blended picture</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<style>
<class name="blend0"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="width">2</property>
</packing>
</child>
</object>
<packing>
<property name="name">page0</property>
<property name="title" translatable="yes">Ducky</property>
<property name="child">
<object class="GtkGrid">
<property name="halign">center</property>
<property name="valign">center</property>
<property name="vexpand">1</property>
<property name="row-spacing">12</property>
<property name="column-spacing">12</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Duck</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Background</property>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkImage">
<style>
<class name="duck"/>
</style>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkImage">
<style>
<class name="gradient"/>
</style>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">
Blended picture</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkImage">
<property name="halign">center</property>
<style>
<class name="blend0"/>
</style>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
</object>
</property>
</object>
</packing>
</child>
<child>
<object class="GtkStackPage">
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="hexpand">False</property>
<property name="vexpand">True</property>
<property name="row_spacing">12</property>
<property name="column_spacing">12</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Red</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Blue</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<style>
<class name="red"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<style>
<class name="blue"/>
</style>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">
Blended picture</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<style>
<class name="blend1"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="width">2</property>
</packing>
</child>
</object>
<packing>
<property name="name">page1</property>
<property name="title" translatable="yes">Blends</property>
<property name="child">
<object class="GtkGrid">
<property name="halign">center</property>
<property name="valign">center</property>
<property name="vexpand">1</property>
<property name="row-spacing">12</property>
<property name="column-spacing">12</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Red</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Blue</property>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkImage">
<style>
<class name="red"/>
</style>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkImage">
<style>
<class name="blue"/>
</style>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">
Blended picture</property>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkImage">
<property name="halign">center</property>
<style>
<class name="blend1"/>
</style>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
</object>
</property>
</object>
</packing>
</child>
<child>
<object class="GtkStackPage">
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="row_spacing">6</property>
<property name="column_spacing">12</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<style>
<class name="cyan"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<style>
<class name="magenta"/>
</style>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<style>
<class name="yellow"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<style>
<class name="blend2"/>
</style>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Cyan</property>
<property name="xalign">0</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Magenta</property>
<property name="xalign">0</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Yellow</property>
<property name="xalign">0</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Blended picture</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
</object>
<packing>
<property name="name">page2</property>
<property name="title" translatable="yes">CMYK</property>
<property name="child">
<object class="GtkGrid">
<property name="halign">center</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<property name="row-spacing">6</property>
<property name="column-spacing">12</property>
<child>
<object class="GtkImage">
<style>
<class name="cyan"/>
</style>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkImage">
<style>
<class name="magenta"/>
</style>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkImage">
<style>
<class name="yellow"/>
</style>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkImage">
<property name="halign">center</property>
<style>
<class name="blend2"/>
</style>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Cyan</property>
<property name="xalign">0</property>
<style>
<class name="dim-label"/>
</style>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Magenta</property>
<property name="xalign">0</property>
<style>
<class name="dim-label"/>
</style>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Yellow</property>
<property name="xalign">0</property>
<style>
<class name="dim-label"/>
</style>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Blended picture</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold"></attribute>
</attributes>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</layout>
</object>
</child>
</object>
</property>
</object>
</packing>
</child>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</layout>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
</object>
</child>
<child type="titlebar"/>
<child type="titlebar">
<placeholder/>
</child>
</object>
</interface>
-482
View File
@@ -1,482 +0,0 @@
/*
* bluroverlay.c
* This file is part of gtk
*
* Copyright (C) 2011 - Ignacio Casal Quinteiro, Mike Krüger
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "bluroverlay.h"
/*
* This is a cut-down copy of gtkoverlay.c with a custom snapshot
* function that support a limited form of blur-under.
*/
typedef struct _BlurOverlayChild BlurOverlayChild;
struct _BlurOverlayChild
{
double blur;
};
enum {
GET_CHILD_POSITION,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
static GQuark child_data_quark = 0;
G_DEFINE_TYPE (BlurOverlay, blur_overlay, GTK_TYPE_BIN)
static void
blur_overlay_set_overlay_child (GtkWidget *widget,
BlurOverlayChild *child_data)
{
g_object_set_qdata_full (G_OBJECT (widget), child_data_quark, child_data, g_free);
}
static BlurOverlayChild *
blur_overlay_get_overlay_child (GtkWidget *widget)
{
return (BlurOverlayChild *) g_object_get_qdata (G_OBJECT (widget), child_data_quark);
}
static void
blur_overlay_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkWidget *child;
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
{
int child_min, child_nat, child_min_baseline, child_nat_baseline;
gtk_widget_measure (child,
orientation,
for_size,
&child_min, &child_nat,
&child_min_baseline, &child_nat_baseline);
*minimum = MAX (*minimum, child_min);
*natural = MAX (*natural, child_nat);
if (child_min_baseline > -1)
*minimum_baseline = MAX (*minimum_baseline, child_min_baseline);
if (child_nat_baseline > -1)
*natural_baseline = MAX (*natural_baseline, child_nat_baseline);
}
}
static void
blur_overlay_compute_child_allocation (BlurOverlay *overlay,
GtkWidget *widget,
BlurOverlayChild *child,
GtkAllocation *widget_allocation)
{
GtkAllocation allocation;
gboolean result;
g_signal_emit (overlay, signals[GET_CHILD_POSITION],
0, widget, &allocation, &result);
widget_allocation->x = allocation.x;
widget_allocation->y = allocation.y;
widget_allocation->width = allocation.width;
widget_allocation->height = allocation.height;
}
static GtkAlign
effective_align (GtkAlign align,
GtkTextDirection direction)
{
switch (align)
{
case GTK_ALIGN_START:
return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_END : GTK_ALIGN_START;
case GTK_ALIGN_END:
return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_START : GTK_ALIGN_END;
case GTK_ALIGN_FILL:
case GTK_ALIGN_CENTER:
case GTK_ALIGN_BASELINE:
default:
return align;
}
}
static void
blur_overlay_child_update_style_classes (BlurOverlay *overlay,
GtkWidget *child,
GtkAllocation *child_allocation)
{
int width, height;
GtkAlign valign, halign;
gboolean is_left, is_right, is_top, is_bottom;
gboolean has_left, has_right, has_top, has_bottom;
GtkStyleContext *context;
context = gtk_widget_get_style_context (child);
has_left = gtk_style_context_has_class (context, GTK_STYLE_CLASS_LEFT);
has_right = gtk_style_context_has_class (context, GTK_STYLE_CLASS_RIGHT);
has_top = gtk_style_context_has_class (context, GTK_STYLE_CLASS_TOP);
has_bottom = gtk_style_context_has_class (context, GTK_STYLE_CLASS_BOTTOM);
is_left = is_right = is_top = is_bottom = FALSE;
width = gtk_widget_get_width (GTK_WIDGET (overlay));
height = gtk_widget_get_height (GTK_WIDGET (overlay));
halign = effective_align (gtk_widget_get_halign (child),
gtk_widget_get_direction (child));
if (halign == GTK_ALIGN_START)
is_left = (child_allocation->x == 0);
else if (halign == GTK_ALIGN_END)
is_right = (child_allocation->x + child_allocation->width == width);
valign = gtk_widget_get_valign (child);
if (valign == GTK_ALIGN_START)
is_top = (child_allocation->y == 0);
else if (valign == GTK_ALIGN_END)
is_bottom = (child_allocation->y + child_allocation->height == height);
if (has_left && !is_left)
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_LEFT);
else if (!has_left && is_left)
gtk_style_context_add_class (context, GTK_STYLE_CLASS_LEFT);
if (has_right && !is_right)
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_RIGHT);
else if (!has_right && is_right)
gtk_style_context_add_class (context, GTK_STYLE_CLASS_RIGHT);
if (has_top && !is_top)
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_TOP);
else if (!has_top && is_top)
gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOP);
if (has_bottom && !is_bottom)
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BOTTOM);
else if (!has_bottom && is_bottom)
gtk_style_context_add_class (context, GTK_STYLE_CLASS_BOTTOM);
}
static void
blur_overlay_child_allocate (BlurOverlay *overlay,
GtkWidget *widget,
BlurOverlayChild *child)
{
GtkAllocation child_allocation;
if (!gtk_widget_get_visible (widget))
return;
blur_overlay_compute_child_allocation (overlay, widget, child, &child_allocation);
blur_overlay_child_update_style_classes (overlay, widget, &child_allocation);
gtk_widget_size_allocate (widget, &child_allocation, -1);
}
static void
blur_overlay_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
BlurOverlay *overlay = BLUR_OVERLAY (widget);
GtkWidget *child;
GtkWidget *main_widget;
main_widget = gtk_bin_get_child (GTK_BIN (overlay));
if (main_widget && gtk_widget_get_visible (main_widget))
gtk_widget_size_allocate (main_widget,
&(GtkAllocation) {
0, 0,
width, height
}, -1);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
{
if (child != main_widget)
{
BlurOverlayChild *child_data = blur_overlay_get_overlay_child (child);
blur_overlay_child_allocate (overlay, child, child_data);
}
}
}
static gboolean
blur_overlay_get_child_position (BlurOverlay *overlay,
GtkWidget *widget,
GtkAllocation *alloc)
{
GtkRequisition min, req;
GtkAlign halign;
GtkTextDirection direction;
int width, height;
gtk_widget_get_preferred_size (widget, &min, &req);
width = gtk_widget_get_width (GTK_WIDGET (overlay));
height = gtk_widget_get_height (GTK_WIDGET (overlay));
alloc->x = 0;
alloc->width = MAX (min.width, MIN (width, req.width));
direction = gtk_widget_get_direction (widget);
halign = gtk_widget_get_halign (widget);
switch (effective_align (halign, direction))
{
case GTK_ALIGN_START:
/* nothing to do */
break;
case GTK_ALIGN_FILL:
alloc->width = MAX (alloc->width, width);
break;
case GTK_ALIGN_CENTER:
alloc->x += width / 2 - alloc->width / 2;
break;
case GTK_ALIGN_END:
alloc->x += width - alloc->width;
break;
case GTK_ALIGN_BASELINE:
default:
g_assert_not_reached ();
break;
}
alloc->y = 0;
alloc->height = MAX (min.height, MIN (height, req.height));
switch (gtk_widget_get_valign (widget))
{
case GTK_ALIGN_START:
/* nothing to do */
break;
case GTK_ALIGN_FILL:
alloc->height = MAX (alloc->height, height);
break;
case GTK_ALIGN_CENTER:
alloc->y += height / 2 - alloc->height / 2;
break;
case GTK_ALIGN_END:
alloc->y += height - alloc->height;
break;
case GTK_ALIGN_BASELINE:
default:
g_assert_not_reached ();
break;
}
return TRUE;
}
static void
blur_overlay_add (GtkContainer *container,
GtkWidget *widget)
{
BlurOverlay *overlay = BLUR_OVERLAY (container);
gtk_widget_insert_after (widget, GTK_WIDGET (container), NULL);
overlay->main_widget = widget;
}
static void
blur_overlay_remove (GtkContainer *container,
GtkWidget *widget)
{
BlurOverlay *overlay = BLUR_OVERLAY (container);
gtk_widget_unparent (widget);
if (overlay->main_widget == widget)
overlay->main_widget = NULL;
}
static void
blur_overlay_forall (GtkContainer *overlay,
GtkCallback callback,
gpointer callback_data)
{
GtkWidget *child;
child = gtk_widget_get_first_child (GTK_WIDGET (overlay));
while (child != NULL)
{
GtkWidget *next = gtk_widget_get_next_sibling (child);
(* callback) (child, callback_data);
child = next;
}
}
static void
blur_overlay_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
GtkWidget *main_widget;
GskRenderNode *main_widget_node = NULL;
GtkWidget *child;
GtkAllocation main_alloc;
cairo_region_t *clip = NULL;
int i;
main_widget = BLUR_OVERLAY (widget)->main_widget;
gtk_widget_get_allocation (widget, &main_alloc);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
{
BlurOverlayChild *child_info = blur_overlay_get_overlay_child (child);
double blur = 0;
if (child_info)
blur = child_info->blur;
if (blur > 0)
{
GtkAllocation alloc;
graphene_rect_t bounds;
if (main_widget_node == NULL)
{
GtkSnapshot *child_snapshot;
child_snapshot = gtk_snapshot_new ();
gtk_widget_snapshot_child (widget, main_widget, child_snapshot);
main_widget_node = gtk_snapshot_free_to_node (child_snapshot);
}
gtk_widget_get_allocation (child, &alloc);
graphene_rect_init (&bounds, alloc.x, alloc.y, alloc.width, alloc.height);
gtk_snapshot_push_blur (snapshot, blur);
gtk_snapshot_push_clip (snapshot, &bounds);
gtk_snapshot_append_node (snapshot, main_widget_node);
gtk_snapshot_pop (snapshot);
gtk_snapshot_pop (snapshot);
if (clip == NULL)
{
cairo_rectangle_int_t rect;
rect.x = rect.y = 0;
rect.width = main_alloc.width;
rect.height = main_alloc.height;
clip = cairo_region_create_rectangle (&rect);
}
cairo_region_subtract_rectangle (clip, (cairo_rectangle_int_t *)&alloc);
}
}
if (clip == NULL)
{
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
{
gtk_widget_snapshot_child (widget, child, snapshot);
}
return;
}
for (i = 0; i < cairo_region_num_rectangles (clip); i++)
{
cairo_rectangle_int_t rect;
graphene_rect_t bounds;
cairo_region_get_rectangle (clip, i, &rect);
graphene_rect_init (&bounds, rect.x, rect.y, rect.width, rect.height);
gtk_snapshot_push_clip (snapshot, &bounds);
gtk_snapshot_append_node (snapshot, main_widget_node);
gtk_snapshot_pop (snapshot);
}
cairo_region_destroy (clip);
for (child = gtk_widget_get_first_child (widget);
child != NULL;
child = gtk_widget_get_next_sibling (child))
{
if (child != main_widget)
gtk_widget_snapshot_child (widget, child, snapshot);
}
gsk_render_node_unref (main_widget_node);
}
static void
blur_overlay_class_init (BlurOverlayClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
widget_class->measure = blur_overlay_measure;
widget_class->size_allocate = blur_overlay_size_allocate;
widget_class->snapshot = blur_overlay_snapshot;
container_class->add = blur_overlay_add;
container_class->remove = blur_overlay_remove;
container_class->forall = blur_overlay_forall;
klass->get_child_position = blur_overlay_get_child_position;
signals[GET_CHILD_POSITION] =
g_signal_new ("get-child-position",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (BlurOverlayClass, get_child_position),
g_signal_accumulator_true_handled, NULL,
NULL,
G_TYPE_BOOLEAN, 2,
GTK_TYPE_WIDGET,
GDK_TYPE_RECTANGLE | G_SIGNAL_TYPE_STATIC_SCOPE);
child_data_quark = g_quark_from_static_string ("gtk-overlay-child-data");
gtk_widget_class_set_css_name (widget_class, "overlay");
}
static void
blur_overlay_init (BlurOverlay *overlay)
{
gtk_widget_set_has_surface (GTK_WIDGET (overlay), FALSE);
}
GtkWidget *
blur_overlay_new (void)
{
return g_object_new (BLUR_TYPE_OVERLAY, NULL);
}
void
blur_overlay_add_overlay (BlurOverlay *overlay,
GtkWidget *widget,
double blur)
{
BlurOverlayChild *child = g_new0 (BlurOverlayChild, 1);
gtk_widget_insert_before (widget, GTK_WIDGET (overlay), NULL);
child->blur = blur;
blur_overlay_set_overlay_child (widget, child);
}
-65
View File
@@ -1,65 +0,0 @@
/*
* bluroverlay.h
* This file is part of gtk
*
* Copyright (C) 2011 - Ignacio Casal Quinteiro, Mike Krüger
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BLUR_OVERLAY_H__
#define __BLUR_OVERLAY_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define BLUR_TYPE_OVERLAY (blur_overlay_get_type ())
#define BLUR_OVERLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BLUR_TYPE_OVERLAY, BlurOverlay))
#define BLUR_OVERLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BLUR_TYPE_OVERLAY, BlurOverlayClass))
#define BLUR_IS_OVERLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BLUR_TYPE_OVERLAY))
#define BLUR_IS_OVERLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BLUR_TYPE_OVERLAY))
#define BLUR_OVERLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BLUR_TYPE_OVERLAY, BlurOverlayClass))
typedef struct _BlurOverlay BlurOverlay;
typedef struct _BlurOverlayClass BlurOverlayClass;
struct _BlurOverlay
{
GtkBin parent_instance;
GtkWidget *main_widget;
};
struct _BlurOverlayClass
{
GtkBinClass parent_class;
gboolean (*get_child_position) (BlurOverlay *overlay,
GtkWidget *widget,
GtkAllocation *allocation);
};
GDK_AVAILABLE_IN_ALL
GType blur_overlay_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GtkWidget *blur_overlay_new (void);
GDK_AVAILABLE_IN_ALL
void blur_overlay_add_overlay (BlurOverlay *overlay,
GtkWidget *widget,
double blur);
G_END_DECLS
#endif /* __BLUR_OVERLAY_H__ */
+127
View File
@@ -0,0 +1,127 @@
/* Button Boxes
*
* The Button Box widgets are used to arrange buttons with padding.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
static GtkWidget *
create_bbox (gint horizontal,
char *title,
gint spacing,
gint layout)
{
GtkWidget *frame;
GtkWidget *bbox;
GtkWidget *button;
frame = gtk_frame_new (title);
if (horizontal)
bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
else
bbox = gtk_button_box_new (GTK_ORIENTATION_VERTICAL);
g_object_set (bbox, "margin", 5, NULL);
gtk_container_add (GTK_CONTAINER (frame), bbox);
gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
gtk_box_set_spacing (GTK_BOX (bbox), spacing);
button = gtk_button_new_with_label (_("OK"));
gtk_container_add (GTK_CONTAINER (bbox), button);
button = gtk_button_new_with_label (_("Cancel"));
gtk_container_add (GTK_CONTAINER (bbox), button);
button = gtk_button_new_with_label (_("Help"));
gtk_container_add (GTK_CONTAINER (bbox), button);
return frame;
}
GtkWidget *
do_button_box (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
GtkWidget *main_vbox;
GtkWidget *vbox;
GtkWidget *hbox;
GtkWidget *frame_horz;
GtkWidget *frame_vert;
if (!window)
{
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), "Button Boxes");
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed),
&window);
main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
g_object_set (main_vbox, "margin", 10, NULL);
gtk_container_add (GTK_CONTAINER (window), main_vbox);
frame_horz = gtk_frame_new ("Horizontal Button Boxes");
gtk_widget_set_margin_top (frame_horz, 10);
gtk_widget_set_margin_bottom (frame_horz, 10);
gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
g_object_set (vbox, "margin", 10, NULL);
gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
gtk_box_pack_start (GTK_BOX (vbox),
create_bbox (TRUE, "Spread", 40, GTK_BUTTONBOX_SPREAD));
gtk_box_pack_start (GTK_BOX (vbox),
create_bbox (TRUE, "Edge", 40, GTK_BUTTONBOX_EDGE));
gtk_box_pack_start (GTK_BOX (vbox),
create_bbox (TRUE, "Start", 40, GTK_BUTTONBOX_START));
gtk_box_pack_start (GTK_BOX (vbox),
create_bbox (TRUE, "End", 40, GTK_BUTTONBOX_END));
gtk_box_pack_start (GTK_BOX (vbox),
create_bbox (TRUE, "Center", 40, GTK_BUTTONBOX_CENTER));
gtk_box_pack_start (GTK_BOX (vbox),
create_bbox (TRUE, "Expand", 0, GTK_BUTTONBOX_EXPAND));
frame_vert = gtk_frame_new ("Vertical Button Boxes");
gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
g_object_set (hbox, "margin", 10, NULL);
gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
gtk_box_pack_start (GTK_BOX (hbox),
create_bbox (FALSE, "Spread", 10, GTK_BUTTONBOX_SPREAD));
gtk_box_pack_start (GTK_BOX (hbox),
create_bbox (FALSE, "Edge", 10, GTK_BUTTONBOX_EDGE));
gtk_box_pack_start (GTK_BOX (hbox),
create_bbox (FALSE, "Start", 10, GTK_BUTTONBOX_START));
gtk_box_pack_start (GTK_BOX (hbox),
create_bbox (FALSE, "End", 10, GTK_BUTTONBOX_END));
gtk_box_pack_start (GTK_BOX (hbox),
create_bbox (FALSE, "Center", 10, GTK_BUTTONBOX_CENTER));
gtk_box_pack_start (GTK_BOX (hbox),
create_bbox (FALSE, "Expand", 0, GTK_BUTTONBOX_EXPAND));
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_widget_destroy (window);
return window;
}
+29 -25
View File
@@ -7,7 +7,7 @@
* computers, as long as there is a network connection to the
* computer where the application is running.
*
* Only some of the windowing systems where GTK runs have the
* Only some of the windowing systems where GTK+ runs have the
* concept of multiple displays. (The X Window System is the
* main example.) Other windowing systems can only handle one
* keyboard and mouse, and combine all monitors into
@@ -68,25 +68,33 @@ enum
static GtkWidget *
find_toplevel_at_pointer (GdkDisplay *display)
{
GdkSurface *pointer_window;
GdkWindow *pointer_window;
GtkWidget *widget = NULL;
pointer_window = gdk_device_get_surface_at_position (gtk_get_current_event_device (), NULL, NULL);
pointer_window = gdk_device_get_window_at_position (gtk_get_current_event_device (),
NULL, NULL);
/* The user data field of a GdkWindow is used to store a pointer
* to the widget that created it.
*/
if (pointer_window)
widget = GTK_WIDGET (gtk_root_get_for_surface (pointer_window));
{
gpointer widget_ptr;
gdk_window_get_user_data (pointer_window, &widget_ptr);
widget = widget_ptr;
}
return widget;
return widget ? gtk_widget_get_toplevel (widget) : NULL;
}
static void
released_cb (GtkGestureMultiPress *gesture,
guint n_press,
gdouble x,
gdouble y,
gboolean *clicked)
static gboolean
release_event_cb (GtkWidget *widget,
GdkEvent *event,
gboolean *clicked)
{
*clicked = TRUE;
if (gdk_event_get_event_type (event) == GDK_BUTTON_RELEASE)
*clicked = TRUE;
return TRUE;
}
/* Asks the user to click on a window, then waits for them click
@@ -120,16 +128,14 @@ query_for_toplevel (GdkDisplay *display,
device = gtk_get_current_event_device ();
if (gdk_seat_grab (gdk_device_get_seat (device),
gtk_widget_get_surface (popup),
gtk_widget_get_window (popup),
GDK_SEAT_CAPABILITY_ALL_POINTING,
FALSE, cursor, NULL, NULL, NULL) == GDK_GRAB_SUCCESS)
{
GtkGesture *gesture = gtk_gesture_multi_press_new ();
gboolean clicked = FALSE;
g_signal_connect (gesture, "released",
G_CALLBACK (released_cb), &clicked);
gtk_widget_add_controller (popup, GTK_EVENT_CONTROLLER (gesture));
g_signal_connect (popup, "event",
G_CALLBACK (release_event_cb), &clicked);
/* Process events until clicked is set by our button release event handler.
* We pass in may_block=TRUE since we want to wait if there
@@ -138,8 +144,6 @@ query_for_toplevel (GdkDisplay *display,
while (!clicked)
g_main_context_iteration (NULL, TRUE);
gdk_seat_ungrab (gdk_device_get_seat (device));
toplevel = find_toplevel_at_pointer (display);
if (toplevel == popup)
toplevel = NULL;
@@ -307,7 +311,7 @@ create_frame (ChangeDisplayInfo *info,
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrollwin),
GTK_SHADOW_IN);
gtk_container_add (GTK_CONTAINER (hbox), scrollwin);
gtk_box_pack_start (GTK_BOX (hbox), scrollwin);
*tree_view = gtk_tree_view_new ();
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (*tree_view), FALSE);
@@ -317,7 +321,7 @@ create_frame (ChangeDisplayInfo *info,
gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
*button_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add (GTK_CONTAINER (hbox), *button_vbox);
gtk_box_pack_start (GTK_BOX (hbox), *button_vbox);
if (!info->size_group)
info->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
@@ -357,11 +361,11 @@ create_display_frame (ChangeDisplayInfo *info)
button = left_align_button_new ("_Open...");
g_signal_connect (button, "clicked", G_CALLBACK (open_display_cb), info);
gtk_container_add (GTK_CONTAINER (button_vbox), button);
gtk_box_pack_start (GTK_BOX (button_vbox), button);
button = left_align_button_new ("_Close");
g_signal_connect (button, "clicked", G_CALLBACK (close_display_cb), info);
gtk_container_add (GTK_CONTAINER (button_vbox), button);
gtk_box_pack_start (GTK_BOX (button_vbox), button);
info->display_model = (GtkTreeModel *)gtk_list_store_new (DISPLAY_NUM_COLUMNS,
G_TYPE_STRING,
@@ -534,10 +538,10 @@ do_changedisplay (GtkWidget *do_widget)
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
g_object_set (vbox, "margin", 8, NULL);
gtk_container_add (GTK_CONTAINER (content_area), vbox);
gtk_box_pack_start (GTK_BOX (content_area), vbox);
frame = create_display_frame (info);
gtk_container_add (GTK_CONTAINER (vbox), frame);
gtk_box_pack_start (GTK_BOX (vbox), frame);
initialize_displays (info);
+43 -44
View File
@@ -28,7 +28,7 @@ copy_button_clicked (GtkWidget *button,
clipboard = gtk_widget_get_clipboard (entry);
/* Set clipboard text */
gdk_clipboard_set_text (clipboard, gtk_editable_get_text (GTK_EDITABLE (entry)));
gdk_clipboard_set_text (clipboard, gtk_entry_get_text (GTK_ENTRY (entry)));
}
void
@@ -50,7 +50,7 @@ paste_received (GObject *source_object,
if (text)
{
/* Set the entry text */
gtk_editable_set_text (GTK_EDITABLE (entry), text);
gtk_entry_set_text (GTK_ENTRY (entry), text);
g_free (text);
}
else
@@ -93,8 +93,8 @@ paste_button_clicked (GtkWidget *button,
gdk_clipboard_read_text_async (clipboard, NULL, paste_received, entry);
}
static GdkPaintable *
get_image_paintable (GtkImage *image)
static GdkTexture *
get_image_texture (GtkImage *image)
{
const gchar *icon_name;
GtkIconTheme *icon_theme;
@@ -102,15 +102,15 @@ get_image_paintable (GtkImage *image)
switch (gtk_image_get_storage_type (image))
{
case GTK_IMAGE_PAINTABLE:
return g_object_ref (gtk_image_get_paintable (image));
case GTK_IMAGE_TEXTURE:
return g_object_ref (gtk_image_get_texture (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_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 (gtk_icon_info_load_texture (icon_info));
return gtk_icon_info_load_texture (icon_info);
default:
g_warning ("Image storage type %d not handled",
gtk_image_get_storage_type (image));
@@ -120,37 +120,36 @@ get_image_paintable (GtkImage *image)
static void
drag_begin (GtkWidget *widget,
GdkDrag *drag,
GdkDragContext *context,
gpointer data)
{
GdkPaintable *paintable;
GdkTexture *texture;
paintable = get_image_paintable (GTK_IMAGE (widget));
if (paintable)
{
gtk_drag_set_icon_paintable (drag, paintable, -2, -2);
g_object_unref (paintable);
}
texture = get_image_texture (GTK_IMAGE (widget));
if (texture)
gtk_drag_set_icon_texture (context, texture, -2, -2);
}
void
drag_data_get (GtkWidget *widget,
GdkDrag *drag,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data)
{
GdkPaintable *paintable;
GdkTexture *texture;
paintable = get_image_paintable (GTK_IMAGE (widget));
if (GDK_IS_TEXTURE (paintable))
gtk_selection_data_set_texture (selection_data, GDK_TEXTURE (paintable));
texture = get_image_texture (GTK_IMAGE (widget));
if (texture)
gtk_selection_data_set_texture (selection_data, texture);
}
static void
drag_data_received (GtkWidget *widget,
GdkDrop *drop,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint32 time,
gpointer data)
{
if (gtk_selection_data_get_length (selection_data) > 0)
@@ -158,7 +157,7 @@ drag_data_received (GtkWidget *widget,
GdkTexture *texture;
texture = gtk_selection_data_get_texture (selection_data);
gtk_image_set_from_paintable (GTK_IMAGE (data), GDK_PAINTABLE (texture));
gtk_image_set_from_texture (GTK_IMAGE (data), texture);
g_object_unref (texture);
}
}
@@ -168,16 +167,16 @@ copy_image (GtkMenuItem *item,
gpointer data)
{
GdkClipboard *clipboard;
GdkPaintable *paintable;
GdkTexture *texture;
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (data));
paintable = get_image_paintable (GTK_IMAGE (data));
texture = get_image_texture (GTK_IMAGE (data));
if (GDK_IS_TEXTURE (paintable))
gdk_clipboard_set_texture (clipboard, GDK_TEXTURE (paintable));
if (paintable)
g_object_unref (paintable);
if (texture)
{
gdk_clipboard_set_texture (clipboard, texture);
g_object_unref (texture);
}
}
static void
@@ -191,7 +190,7 @@ paste_image_received (GObject *source,
if (texture == NULL)
return;
gtk_image_set_from_paintable (GTK_IMAGE (data), GDK_PAINTABLE (texture));
gtk_image_set_from_texture (GTK_IMAGE (data), texture);
g_object_unref (texture);
}
@@ -259,45 +258,45 @@ do_clipboard (GtkWidget *do_widget)
label = gtk_label_new ("\"Copy\" will copy the text\nin the entry to the clipboard");
gtk_container_add (GTK_CONTAINER (vbox), label);
gtk_box_pack_start (GTK_BOX (vbox), label);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
g_object_set (hbox, "margin", 8, NULL);
gtk_container_add (GTK_CONTAINER (vbox), hbox);
gtk_box_pack_start (GTK_BOX (vbox), hbox);
/* Create the first entry */
entry = gtk_entry_new ();
gtk_container_add (GTK_CONTAINER (hbox), entry);
gtk_box_pack_start (GTK_BOX (hbox), entry);
/* Create the button */
button = gtk_button_new_with_mnemonic (_("_Copy"));
gtk_container_add (GTK_CONTAINER (hbox), button);
gtk_box_pack_start (GTK_BOX (hbox), button);
g_signal_connect (button, "clicked",
G_CALLBACK (copy_button_clicked), entry);
label = gtk_label_new ("\"Paste\" will paste the text from the clipboard to the entry");
gtk_container_add (GTK_CONTAINER (vbox), label);
gtk_box_pack_start (GTK_BOX (vbox), label);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
g_object_set (hbox, "margin", 8, NULL);
gtk_container_add (GTK_CONTAINER (vbox), hbox);
gtk_box_pack_start (GTK_BOX (vbox), hbox);
/* Create the second entry */
entry = gtk_entry_new ();
gtk_container_add (GTK_CONTAINER (hbox), entry);
gtk_box_pack_start (GTK_BOX (hbox), entry);
/* Create the button */
button = gtk_button_new_with_mnemonic (_("_Paste"));
gtk_container_add (GTK_CONTAINER (hbox), button);
gtk_box_pack_start (GTK_BOX (hbox), button);
g_signal_connect (button, "clicked",
G_CALLBACK (paste_button_clicked), entry);
label = gtk_label_new ("Images can be transferred via the clipboard, too");
gtk_container_add (GTK_CONTAINER (vbox), label);
gtk_box_pack_start (GTK_BOX (vbox), label);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
g_object_set (hbox, "margin", 8, NULL);
gtk_container_add (GTK_CONTAINER (vbox), hbox);
gtk_box_pack_start (GTK_BOX (vbox), hbox);
/* Create the first image */
image = gtk_image_new_from_icon_name ("dialog-warning");
@@ -319,10 +318,10 @@ do_clipboard (GtkWidget *do_widget)
G_CALLBACK (drag_data_received), image);
/* context menu on image */
gesture = gtk_gesture_multi_press_new ();
gesture = gtk_gesture_multi_press_new (image);
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
g_object_set_data_full (G_OBJECT (image), "gesture", gesture, g_object_unref);
g_signal_connect (gesture, "pressed", G_CALLBACK (pressed_cb), image);
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (gesture));
/* Create the second image */
image = gtk_image_new_from_icon_name ("process-stop");
@@ -344,10 +343,10 @@ do_clipboard (GtkWidget *do_widget)
G_CALLBACK (drag_data_received), image);
/* context menu on image */
gesture = gtk_gesture_multi_press_new ();
gesture = gtk_gesture_multi_press_new (image);
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
g_object_set_data_full (G_OBJECT (image), "gesture", gesture, g_object_unref);
g_signal_connect (gesture, "pressed", G_CALLBACK (pressed_cb), image);
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (gesture));
}
if (!gtk_widget_get_visible (window))
+3 -3
View File
@@ -1,7 +1,7 @@
/* Color Chooser
*
* A GtkColorChooser lets the user choose a color. There are several
* implementations of the GtkColorChooser interface in GTK. The
* implementations of the GtkColorChooser interface in GTK+. The
* GtkColorChooserDialog is a prebuilt dialog containing a
* GtkColorChooserWidget.
*/
@@ -88,7 +88,7 @@ do_colorsel (GtkWidget *do_widget)
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_container_add (GTK_CONTAINER (vbox), frame);
gtk_box_pack_start (GTK_BOX (vbox), frame);
da = gtk_drawing_area_new ();
gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), 200);
@@ -101,7 +101,7 @@ do_colorsel (GtkWidget *do_widget)
gtk_widget_set_halign (button, GTK_ALIGN_END);
gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
gtk_container_add (GTK_CONTAINER (vbox), button);
gtk_box_pack_start (GTK_BOX (vbox), button);
g_signal_connect (button, "clicked",
G_CALLBACK (change_color_callback), NULL);
+7 -7
View File
@@ -144,7 +144,7 @@ create_capital_store (void)
{ NULL, "Jackson" },
{ NULL, "Jefferson City" },
{ NULL, "Juneau" },
{ "K - O", NULL },
{ "K - O" },
{ NULL, "Lansing" },
{ NULL, "Lincoln" },
{ NULL, "Little Rock" },
@@ -154,7 +154,7 @@ create_capital_store (void)
{ NULL, "Nashville" },
{ NULL, "Oklahoma City" },
{ NULL, "Olympia" },
{ "P - S", NULL },
{ NULL, "P - S" },
{ NULL, "Phoenix" },
{ NULL, "Pierre" },
{ NULL, "Providence" },
@@ -256,7 +256,7 @@ mask_entry_set_background (MaskEntry *entry)
{
if (entry->mask)
{
if (!g_regex_match_simple (entry->mask, gtk_editable_get_text (GTK_EDITABLE (entry)), 0, 0))
if (!g_regex_match_simple (entry->mask, gtk_entry_get_text (GTK_ENTRY (entry)), 0, 0))
{
PangoAttrList *attrs;
@@ -326,7 +326,7 @@ do_combobox (GtkWidget *do_widget)
* insensitive rows
*/
frame = gtk_frame_new ("Items with icons");
gtk_container_add (GTK_CONTAINER (vbox), frame);
gtk_box_pack_start (GTK_BOX (vbox), frame);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
g_object_set (box, "margin", 5, NULL);
@@ -367,7 +367,7 @@ do_combobox (GtkWidget *do_widget)
/* A combobox demonstrating trees.
*/
frame = gtk_frame_new ("Where are we ?");
gtk_container_add (GTK_CONTAINER (vbox), frame);
gtk_box_pack_start (GTK_BOX (vbox), frame);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
g_object_set (box, "margin", 5, NULL);
@@ -395,7 +395,7 @@ do_combobox (GtkWidget *do_widget)
/* A GtkComboBoxEntry with validation */
frame = gtk_frame_new ("Editable");
gtk_container_add (GTK_CONTAINER (vbox), frame);
gtk_box_pack_start (GTK_BOX (vbox), frame);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
g_object_set (box, "margin", 5, NULL);
@@ -413,7 +413,7 @@ do_combobox (GtkWidget *do_widget)
/* A combobox with string IDs */
frame = gtk_frame_new ("String IDs");
gtk_container_add (GTK_CONTAINER (vbox), frame);
gtk_box_pack_start (GTK_BOX (vbox), frame);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
g_object_set (box, "margin", 5, NULL);
+5 -8
View File
@@ -13,22 +13,19 @@ show_parsing_error (GtkCssProvider *provider,
const GError *error,
GtkTextBuffer *buffer)
{
const GtkCssLocation *start_location, *end_location;
GtkTextIter start, end;
const char *tag_name;
start_location = gtk_css_section_get_start_location (section);
gtk_text_buffer_get_iter_at_line_index (buffer,
&start,
start_location->lines,
start_location->line_bytes);
end_location = gtk_css_section_get_end_location (section);
gtk_css_section_get_start_line (section),
gtk_css_section_get_start_position (section));
gtk_text_buffer_get_iter_at_line_index (buffer,
&end,
end_location->lines,
end_location->line_bytes);
gtk_css_section_get_end_line (section),
gtk_css_section_get_end_position (section));
if (error->domain == GTK_CSS_PARSER_WARNING)
if (g_error_matches (error, GTK_CSS_PROVIDER_ERROR, GTK_CSS_PROVIDER_ERROR_DEPRECATED))
tag_name = "warning";
else
tag_name = "error";
+5 -9
View File
@@ -13,23 +13,19 @@ show_parsing_error (GtkCssProvider *provider,
const GError *error,
GtkTextBuffer *buffer)
{
const GtkCssLocation *start_location, *end_location;
GtkTextIter start, end;
const char *tag_name;
start_location = gtk_css_section_get_start_location (section);
gtk_text_buffer_get_iter_at_line_index (buffer,
&start,
start_location->lines,
start_location->line_bytes);
end_location = gtk_css_section_get_end_location (section);
gtk_css_section_get_start_line (section),
gtk_css_section_get_start_position (section));
gtk_text_buffer_get_iter_at_line_index (buffer,
&end,
end_location->lines,
end_location->line_bytes);
gtk_css_section_get_end_line (section),
gtk_css_section_get_end_position (section));
if (error->domain == GTK_CSS_PARSER_WARNING)
if (g_error_matches (error, GTK_CSS_PROVIDER_ERROR, GTK_CSS_PROVIDER_ERROR_DEPRECATED))
tag_name = "warning";
else
tag_name = "error";
+5 -9
View File
@@ -12,23 +12,19 @@ show_parsing_error (GtkCssProvider *provider,
const GError *error,
GtkTextBuffer *buffer)
{
const GtkCssLocation *start_location, *end_location;
GtkTextIter start, end;
const char *tag_name;
start_location = gtk_css_section_get_start_location (section);
gtk_text_buffer_get_iter_at_line_index (buffer,
&start,
start_location->lines,
start_location->line_bytes);
end_location = gtk_css_section_get_end_location (section);
gtk_css_section_get_start_line (section),
gtk_css_section_get_start_position (section));
gtk_text_buffer_get_iter_at_line_index (buffer,
&end,
end_location->lines,
end_location->line_bytes);
gtk_css_section_get_end_line (section),
gtk_css_section_get_end_position (section));
if (error->domain == GTK_CSS_PARSER_WARNING)
if (g_error_matches (error, GTK_CSS_PROVIDER_ERROR, GTK_CSS_PROVIDER_ERROR_DEPRECATED))
tag_name = "warning";
else
tag_name = "error";
+5 -8
View File
@@ -11,22 +11,19 @@ show_parsing_error (GtkCssProvider *provider,
const GError *error,
GtkTextBuffer *buffer)
{
const GtkCssLocation *start_location, *end_location;
GtkTextIter start, end;
const char *tag_name;
start_location = gtk_css_section_get_start_location (section);
gtk_text_buffer_get_iter_at_line_index (buffer,
&start,
start_location->lines,
start_location->line_bytes);
end_location = gtk_css_section_get_end_location (section);
gtk_css_section_get_start_line (section),
gtk_css_section_get_start_position (section));
gtk_text_buffer_get_iter_at_line_index (buffer,
&end,
end_location->lines,
end_location->line_bytes);
gtk_css_section_get_end_line (section),
gtk_css_section_get_end_position (section));
if (error->domain == GTK_CSS_PARSER_WARNING)
if (g_error_matches (error, GTK_CSS_PROVIDER_ERROR, GTK_CSS_PROVIDER_ERROR_DEPRECATED))
tag_name = "warning";
else
tag_name = "error";
+267 -225
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 874 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128" version="1.0"><defs><linearGradient id="f"><stop offset="0" stop-color="#ff7800"/><stop offset="1" stop-color="#ed333b"/></linearGradient><linearGradient id="e"><stop offset="0" stop-color="#f5c211"/><stop offset="1" stop-color="#33d17a" stop-opacity=".899"/></linearGradient><linearGradient id="d"><stop offset="0" stop-color="#c0bfbc"/><stop offset=".036" stop-color="#fafaf9"/><stop offset=".088" stop-color="#c0bfbc"/><stop offset=".399" stop-color="#d5d5d3"/><stop offset=".491" stop-color="#eaeae9"/><stop offset=".569" stop-color="#a7a5a1"/><stop offset=".966" stop-color="#a9a7a3"/><stop offset="1" stop-color="#fff"/></linearGradient><linearGradient id="a"><stop offset="0" stop-color="#d5d3cf"/><stop offset="1" stop-color="#f6f5f4"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#d5d3cf"/><stop offset="1" stop-color="#949390"/></linearGradient><linearGradient id="c"><stop offset="0" stop-color="#9a9996"/><stop offset="1" stop-color="#77767b"/></linearGradient><linearGradient xlink:href="#d" id="g" x1="-142.049" y1="236.001" x2="-9.951" y2="236.001" gradientUnits="userSpaceOnUse"/><radialGradient xlink:href="#e" id="h" cx="90.974" cy="263.479" fx="90.974" fy="263.479" r="22.703" gradientTransform="matrix(1.90297 -.05506 .0501 1.73133 -89.25 -176.863)" gradientUnits="userSpaceOnUse"/><radialGradient xlink:href="#f" id="i" cx="61.718" cy="270.719" fx="61.718" fy="270.719" r="22.703" gradientTransform="matrix(2.49049 0 0 2.92132 -91.99 -503.52)" gradientUnits="userSpaceOnUse"/></defs><path transform="translate(123.265 -118.118) scale(.7798)" d="M-75.74 161.438a10.997 10.997 0 0 0-5.758 1.468l-55.053 31.785a10.997 10.997 0 0 0-5.498 9.524v63.57a10.997 10.997 0 0 0 5.498 9.524l55.053 31.785a10.997 10.997 0 0 0 10.996 0l55.053-31.785a10.997 10.997 0 0 0 5.498-9.524v-63.57a10.997 10.997 0 0 0-5.498-9.524l-55.053-31.785a10.997 10.997 0 0 0-5.238-1.469z" style="marker:none" fill="url(#g)"/><path style="marker:none" d="M64.203 3.77a8.575 8.575 0 0 0-4.49 1.146l-42.93 24.786a8.575 8.575 0 0 0-4.288 7.427V86.7a8.575 8.575 0 0 0 4.287 7.426l42.93 24.786a8.575 8.575 0 0 0 8.575 0l42.93-24.786a8.575 8.575 0 0 0 4.288-7.426V37.129a8.575 8.575 0 0 0-4.287-7.427L68.288 4.916a8.575 8.575 0 0 0-4.085-1.145z" fill="#fff"/><path style="marker:none" d="M109.869 33.297L64 59.779 18.131 33.297 64 6.814z" fill="#98c1f1"/><path style="marker:none" d="M66.263 287.505l45.35-25.884.056-52.762-45.406 26.215z" fill="url(#h)" transform="translate(0 -172)"/><path d="M61.718 287.34l-45.35-25.885-.056-52.761 45.406 26.215z" style="marker:none" fill="url(#i)" transform="translate(0 -172)"/></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 101 KiB

+29
View File
@@ -0,0 +1,29 @@
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg xmlns:cc='http://creativecommons.org/ns#' xmlns:dc='http://purl.org/dc/elements/1.1/' sodipodi:docname='gtk3-demo-symbolic.svg' height='16.000015' id='svg7384' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' xmlns:osb='http://www.openswatchbook.org/uri/2009/osb' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' xmlns:svg='http://www.w3.org/2000/svg' inkscape:version='0.48.5 r10040' version='1.1' width='16' xmlns='http://www.w3.org/2000/svg'>
<metadata id='metadata90'>
<rdf:RDF>
<cc:Work rdf:about=''>
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/>
<dc:title>Gnome Symbolic Icon Theme</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview inkscape:bbox-paths='true' bordercolor='#666666' borderopacity='1' inkscape:current-layer='layer9' inkscape:cx='-12.5126' inkscape:cy='-0.73412416' gridtolerance='10' inkscape:guide-bbox='true' guidetolerance='10' id='namedview88' inkscape:object-nodes='false' inkscape:object-paths='false' objecttolerance='10' pagecolor='#555753' inkscape:pageopacity='1' inkscape:pageshadow='2' showborder='false' showgrid='false' showguides='true' inkscape:snap-bbox='true' inkscape:snap-bbox-midpoints='false' inkscape:snap-global='true' inkscape:snap-grids='true' inkscape:snap-nodes='true' inkscape:snap-others='false' inkscape:snap-to-guides='true' inkscape:window-height='1375' inkscape:window-maximized='1' inkscape:window-width='2560' inkscape:window-x='0' inkscape:window-y='27' inkscape:zoom='5.6568542'>
<inkscape:grid empspacing='2' enabled='true' id='grid4866' originx='-182.99998px' originy='-251.99998px' snapvisiblegridlinesonly='true' spacingx='1px' spacingy='1px' type='xygrid' visible='true'/>
</sodipodi:namedview>
<title id='title9167'>Gnome Symbolic Icon Theme</title>
<defs id='defs7386'>
<linearGradient id='linearGradient7212' osb:paint='solid'>
<stop id='stop7214' offset='0' style='stop-color:#000000;stop-opacity:1;'/>
</linearGradient>
</defs>
<g inkscape:groupmode='layer' id='layer9' inkscape:label='apps' style='display:inline' transform='translate(-424.00018,35)'>
<rect height='8.0000048' id='rect7866' style='opacity:0.3;color:#000000;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.39999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new' transform='matrix(0.83205029,0.5547002,0,1,0,0)' width='7.2111053' x='510.78668' y='-314.33347'/>
<rect height='8.0000086' id='rect7868' style='opacity:0.5;color:#000000;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.39999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new' transform='matrix(-0.86824295,0.49613928,0,1,0,0)' width='8.0622425' x='-505.61908' y='219.8575'/>
<path inkscape:connector-curvature='0' d='m 431.53145,-28 -5.875,-3.65625 6.8125,-3.34375 6.03125,3 z' id='path7870' sodipodi:nodetypes='ccccc' style='color:#000000;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.39999998;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new'/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

@@ -1,114 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="org.gtk.Demo4-symbolic.svg"
height="16.03125"
id="svg7384"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
version="1.1"
width="16">
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Gnome Symbolic Icon Theme</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
inkscape:bbox-paths="true"
bordercolor="#666666"
borderopacity="1"
inkscape:current-layer="layer9"
inkscape:cx="0.53203442"
inkscape:cy="9.1822592"
gridtolerance="10"
inkscape:guide-bbox="true"
guidetolerance="10"
id="namedview88"
inkscape:object-nodes="false"
inkscape:object-paths="false"
objecttolerance="10"
pagecolor="#555753"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
showborder="true"
showgrid="false"
showguides="true"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="false"
inkscape:snap-global="true"
inkscape:snap-grids="true"
inkscape:snap-nodes="true"
inkscape:snap-others="false"
inkscape:snap-to-guides="true"
inkscape:window-height="1375"
inkscape:window-maximized="1"
inkscape:window-width="2560"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:zoom="1">
<inkscape:grid
empspacing="2"
enabled="true"
id="grid4866"
originx="-203"
originy="-251.96875"
snapvisiblegridlinesonly="true"
spacingx="1"
spacingy="1"
type="xygrid"
visible="true" />
</sodipodi:namedview>
<title
id="title9167">Gnome Symbolic Icon Theme</title>
<defs
id="defs7386">
<linearGradient
id="linearGradient7212"
osb:paint="solid">
<stop
id="stop7214"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
</linearGradient>
</defs>
<g
inkscape:groupmode="layer"
id="layer9"
inkscape:label="apps"
style="display:inline"
transform="translate(-444.0002,35)">
<path
style="display:inline;opacity:0.3;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
d="m 457.97232,-31.569556 -5.96212,3.44224 -5.96215,-3.44224 v 0 l 5.96215,-3.44226 z"
id="path870-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
<path
sodipodi:nodetypes="cccccc"
inkscape:connector-curvature="0"
id="path886-9"
d="m 450.98519,-19.648086 -5.99273,-3.42041 -0.007,-6.97219 v 0 l 6.00018,3.4642 z"
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new" />
<path
style="display:inline;opacity:0.60100002;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
d="m 452.98577,-19.648086 5.99273,-3.42041 0.007,-6.97219 v 0 l -6.00018,3.4642 z"
id="path931"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccc" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.3 KiB

+7 -48
View File
@@ -105,6 +105,9 @@
<file>gnome-fs-directory.png</file>
<file>gnome-fs-regular.png</file>
</gresource>
<gresource prefix="/stack">
<file>stack.ui</file>
</gresource>
<gresource prefix="/shortcuts">
<file>shortcuts.ui</file>
<file>shortcuts-builder.ui</file>
@@ -112,21 +115,12 @@
<file>shortcuts-clocks.ui</file>
<file>shortcuts-boxes.ui</file>
</gresource>
<gresource prefix="/sliding_puzzle">
<file>puzzlepiece.c</file>
<file>puzzlepiece.h</file>
<file>portland-rose.jpg</file>
</gresource>
<gresource prefix="/stack">
<file>stack.ui</file>
</gresource>
<gresource prefix="/revealer">
<file>revealer.ui</file>
</gresource>
<gresource prefix="/images">
<file>alphatest.png</file>
<file>floppybuddy.gif</file>
<file>gtk-logo.webm</file>
</gresource>
<gresource prefix="/pixbufs">
<file>apple-red.png</file>
@@ -143,6 +137,7 @@
<file>application_demo.c</file>
<file>assistant.c</file>
<file>builder.c</file>
<file>button_box.c</file>
<file>changedisplay.c</file>
<file>clipboard.c</file>
<file>colorsel.c</file>
@@ -160,10 +155,11 @@
<file>editable_cells.c</file>
<file>entry_buffer.c</file>
<file>entry_completion.c</file>
<file>event_axes.c</file>
<file>expander.c</file>
<file>filtermodel.c</file>
<file>fishbowl.c</file>
<file>fixed.c</file>
<file>widgetbowl.c</file>
<file>flowbox.c</file>
<file>foreigndrawing.c</file>
<file>font_features.c</file>
@@ -184,13 +180,8 @@
<file>modelbutton.c</file>
<file>overlay.c</file>
<file>overlay2.c</file>
<file>paint.c</file>
<file>pagesetup.c</file>
<file>paintable.c</file>
<file>paintable_animated.c</file>
<file>paintable_mediastream.c</file>
<file>panes.c</file>
<file>password_entry.c</file>
<file>pickers.c</file>
<file>pixbufs.c</file>
<file>popover.c</file>
@@ -203,26 +194,21 @@
<file>shortcuts.c</file>
<file>sizegroup.c</file>
<file>sidebar.c</file>
<file>sliding_puzzle.c</file>
<file>stack.c</file>
<file>spinbutton.c</file>
<file>spinner.c</file>
<file>tabs.c</file>
<file>tagged_entry.c</file>
<file>textview.c</file>
<file>textscroll.c</file>
<file>theming_style_classes.c</file>
<file>toolpalette.c</file>
<file>transparent.c</file>
<file>tree_store.c</file>
<file>textmask.c</file>
<file>video_player.c</file>
</gresource>
<gresource prefix="/textview">
<file>floppybuddy.gif</file>
</gresource>
<gresource prefix="/tagged_entry">
<file>tagstyle.css</file>
</gresource>
<gresource prefix="/listbox">
<file>listbox.ui</file>
<file>messages.txt</file>
@@ -253,7 +239,6 @@
</gresource>
<gresource prefix="/transparent">
<file>portland-rose.jpg</file>
<file>bluroverlay.c</file>
</gresource>
<gresource prefix="/markup">
<file>markup.txt</file>
@@ -267,30 +252,4 @@
<gresource prefix="/dnd">
<file>dnd.css</file>
</gresource>
<gresource prefix="/tagged_entry">
<file>demotaggedentry.c</file>
<file>demotaggedentry.h</file>
</gresource>
<gresource prefix="/fixed">
<file>fixed.css</file>
</gresource>
<gresource prefix="/org/gtk/Demo4">
<file>icons/16x16/actions/application-exit.png</file>
<file>icons/16x16/actions/document-new.png</file>
<file>icons/16x16/actions/document-open.png</file>
<file>icons/16x16/actions/document-save.png</file>
<file>icons/16x16/actions/edit-copy.png</file>
<file>icons/16x16/actions/edit-cut.png</file>
<file>icons/16x16/actions/edit-paste.png</file>
<file>icons/16x16/actions/process-stop.png</file>
<file>icons/16x16/actions/go-home.png</file>
<file>icons/16x16/actions/go-up.png</file>
<file>icons/16x16/actions/mail-send-receive-symbolic.symbolic.png</file>
<file>icons/16x16/actions/view-fullscreen-symbolic.symbolic.png</file>
<file>icons/16x16/actions/document-edit-symbolic.symbolic.png</file>
<file>icons/16x16/emotes/face-cool.png</file>
<file>icons/16x16/emotes/face-laugh-symbolic.symbolic.png</file>
<file>icons/16x16/status/battery-caution-charging-symbolic.symbolic.png</file>
<file>icons/16x16/categories/applications-other.png</file>
</gresource>
</gresources>
+47 -7
View File
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" standalone="no"?>
<!--*- mode: xml -*-->
<interface>
<object class="GtkListStore" id="liststore1">
<columns>
@@ -30,14 +31,16 @@
</accessibility>
</object>
<object class="GtkWindow" id="window1">
<property name="default-height">250</property>
<property name="default-width">440</property>
<property name="default_height">250</property>
<property name="default_width">440</property>
<property name="title" translatable="yes">Builder</property>
<child>
<object class="GtkBox" id="vbox1">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkMenuBar" id="menubar1">
<property name="visible">1</property>
<child internal-child="accessible">
<object class="AtkObject" id="a11y-menubar">
<property name="AtkObject::accessible-name">The menubar</property>
@@ -45,40 +48,48 @@
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">1</property>
<property name="label" translatable="yes">_File</property>
<property name="use-underline">1</property>
<child type="submenu">
<object class="GtkMenu">
<child>
<object class="GtkMenuItem" id="new_item">
<property name="visible">1</property>
<property name="label" translatable="yes">_New</property>
<property name="use-underline">1</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="open_item">
<property name="visible">1</property>
<property name="label" translatable="yes">_Open</property>
<property name="use-underline">1</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="save_item">
<property name="visible">1</property>
<property name="label" translatable="yes">_Save</property>
<property name="use-underline">1</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="save_as_item">
<property name="visible">1</property>
<property name="label" translatable="yes">Save _As</property>
<property name="use-underline">1</property>
<accelerator key="s" modifiers="primary | shift-mask" signal="activate"/>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem"/>
<object class="GtkSeparatorMenuItem">
<property name="visible">1</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="quit_item">
<property name="visible">1</property>
<property name="label" translatable="yes">_Quit</property>
<property name="use-underline">1</property>
<property name="action-name">win.quit</property>
@@ -90,24 +101,28 @@
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">1</property>
<property name="label" translatable="yes">_Edit</property>
<property name="use-underline">1</property>
<child type="submenu">
<object class="GtkMenu">
<child>
<object class="GtkMenuItem" id="copy_item">
<property name="visible">1</property>
<property name="label" translatable="yes">_Copy</property>
<property name="use-underline">1</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="cut_item">
<property name="visible">1</property>
<property name="label" translatable="yes">_Cut</property>
<property name="use-underline">1</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="paste_item">
<property name="visible">1</property>
<property name="label" translatable="yes">_Paste</property>
<property name="use-underline">1</property>
</object>
@@ -118,12 +133,14 @@
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">1</property>
<property name="label" translatable="yes">_Help</property>
<property name="use-underline">1</property>
<child type="submenu">
<object class="GtkMenu">
<child>
<object class="GtkMenuItem" id="help_item">
<property name="visible">1</property>
<property name="label" translatable="yes">_Help</property>
<property name="use-underline">1</property>
<property name="action-name">win.help</property>
@@ -131,6 +148,7 @@
</child>
<child>
<object class="GtkMenuItem" id="about_item">
<property name="visible">1</property>
<property name="label" translatable="yes">_About</property>
<property name="use-underline">1</property>
<property name="action-name">win.about</property>
@@ -144,6 +162,7 @@
</child>
<child>
<object class="GtkToolbar" id="toolbar1">
<property name="visible">1</property>
<child internal-child="accessible">
<object class="AtkObject" id="a11y-toolbar">
<property name="AtkObject::accessible-name">The toolbar</property>
@@ -151,6 +170,7 @@
</child>
<child>
<object class="GtkToolButton">
<property name="visible">1</property>
<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>
@@ -158,6 +178,7 @@
</child>
<child>
<object class="GtkToolButton">
<property name="visible">1</property>
<property name="label" translatable="yes">Open</property>
<property name="tooltip-text" translatable="yes">Open a file</property>
<property name="icon-name">document-open</property>
@@ -165,6 +186,7 @@
</child>
<child>
<object class="GtkToolButton">
<property name="visible">1</property>
<property name="label" translatable="yes">Save</property>
<property name="tooltip-text" translatable="yes">Save a file</property>
<property name="icon-name">document-save</property>
@@ -172,10 +194,13 @@
</object>
</child>
<child>
<object class="GtkSeparatorToolItem"/>
<object class="GtkSeparatorToolItem">
<property name="visible">1</property>
</object>
</child>
<child>
<object class="GtkToolButton">
<property name="visible">1</property>
<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>
@@ -183,6 +208,7 @@
</child>
<child>
<object class="GtkToolButton">
<property name="visible">1</property>
<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>
@@ -190,19 +216,25 @@
</child>
<child>
<object class="GtkToolButton">
<property name="visible">1</property>
<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>
</object>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="shadow-type">in</property>
<property name="shadow_type">in</property>
<property name="visible">1</property>
<property name="expand">1</property>
<child>
<object class="GtkTreeView" id="treeview1">
<property name="visible">1</property>
<property name="model">liststore1</property>
<property name="tooltip-column">3</property>
<child internal-child="accessible">
@@ -249,9 +281,17 @@
</object>
</child>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkStatusbar" id="statusbar1"/>
<object class="GtkStatusbar" id="statusbar1">
<property name="visible">1</property>
</object>
<packing>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
-493
View File
@@ -1,493 +0,0 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2019 Red Hat, Inc.
*
* Authors:
* - Matthias Clasen <mclasen@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "demotaggedentry.h"
#include <gtk/gtk.h>
#include <gtk/gtk-a11y.h>
typedef struct {
GtkWidget *box;
GtkWidget *entry;
} DemoTaggedEntryPrivate;
static void demo_tagged_entry_editable_init (GtkEditableInterface *iface);
G_DEFINE_TYPE_WITH_CODE (DemoTaggedEntry, demo_tagged_entry, GTK_TYPE_WIDGET,
G_ADD_PRIVATE (DemoTaggedEntry)
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, demo_tagged_entry_editable_init))
static void
demo_tagged_entry_init (DemoTaggedEntry *entry)
{
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
gtk_widget_set_has_surface (GTK_WIDGET (entry), FALSE);
priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_parent (priv->box, GTK_WIDGET (entry));
priv->entry = gtk_text_new ();
gtk_widget_set_hexpand (priv->entry, TRUE);
gtk_widget_set_vexpand (priv->entry, TRUE);
gtk_widget_set_hexpand (priv->box, FALSE);
gtk_widget_set_vexpand (priv->box, FALSE);
gtk_container_add (GTK_CONTAINER (priv->box), priv->entry);
gtk_editable_init_delegate (GTK_EDITABLE (entry));
}
static void
demo_tagged_entry_dispose (GObject *object)
{
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (object);
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
if (priv->entry)
gtk_editable_finish_delegate (GTK_EDITABLE (entry));
g_clear_pointer (&priv->entry, gtk_widget_unparent);
g_clear_pointer (&priv->box, gtk_widget_unparent);
G_OBJECT_CLASS (demo_tagged_entry_parent_class)->dispose (object);
}
static void
demo_tagged_entry_finalize (GObject *object)
{
G_OBJECT_CLASS (demo_tagged_entry_parent_class)->finalize (object);
}
static void
demo_tagged_entry_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
if (gtk_editable_delegate_set_property (object, prop_id, value, pspec))
return;
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
static void
demo_tagged_entry_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
if (gtk_editable_delegate_get_property (object, prop_id, value, pspec))
return;
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
static void
demo_tagged_entry_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (widget);
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
gtk_widget_measure (priv->box, orientation, for_size,
minimum, natural,
minimum_baseline, natural_baseline);
}
static void
demo_tagged_entry_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (widget);
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
gtk_widget_size_allocate (priv->box,
&(GtkAllocation) { 0, 0, width, height },
baseline);
}
static void
demo_tagged_entry_grab_focus (GtkWidget *widget)
{
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (widget);
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
gtk_widget_grab_focus (priv->entry);
}
static void
demo_tagged_entry_class_init (DemoTaggedEntryClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = demo_tagged_entry_dispose;
object_class->finalize = demo_tagged_entry_finalize;
object_class->get_property = demo_tagged_entry_get_property;
object_class->set_property = demo_tagged_entry_set_property;
widget_class->measure = demo_tagged_entry_measure;
widget_class->size_allocate = demo_tagged_entry_size_allocate;
widget_class->grab_focus = demo_tagged_entry_grab_focus;
gtk_editable_install_properties (object_class, 1);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ENTRY_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, "entry");
}
static GtkEditable *
demo_tagged_entry_get_delegate (GtkEditable *editable)
{
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (editable);
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
return GTK_EDITABLE (priv->entry);
}
static void
demo_tagged_entry_editable_init (GtkEditableInterface *iface)
{
iface->get_delegate = demo_tagged_entry_get_delegate;
}
GtkWidget *
demo_tagged_entry_new (void)
{
return GTK_WIDGET (g_object_new (DEMO_TYPE_TAGGED_ENTRY, NULL));
}
void
demo_tagged_entry_add_tag (DemoTaggedEntry *entry,
GtkWidget *tag)
{
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
gtk_container_add (GTK_CONTAINER (priv->box), tag);
}
void
demo_tagged_entry_insert_tag_after (DemoTaggedEntry *entry,
GtkWidget *tag,
GtkWidget *sibling)
{
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
if (sibling == NULL)
gtk_container_add (GTK_CONTAINER (priv->box), tag);
else
gtk_box_insert_child_after (GTK_BOX (priv->box), tag, sibling);
}
void
demo_tagged_entry_remove_tag (DemoTaggedEntry *entry,
GtkWidget *tag)
{
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
gtk_container_remove (GTK_CONTAINER (priv->box), tag);
}
struct _DemoTaggedEntryTag
{
GtkWidget parent;
GtkWidget *box;
GtkWidget *label;
GtkWidget *button;
gboolean has_close_button;
char *style;
};
struct _DemoTaggedEntryTagClass
{
GtkWidgetClass parent_class;
};
enum {
PROP_0,
PROP_LABEL,
PROP_HAS_CLOSE_BUTTON,
};
enum {
SIGNAL_CLICKED,
SIGNAL_BUTTON_CLICKED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (DemoTaggedEntryTag, demo_tagged_entry_tag, GTK_TYPE_WIDGET)
static void
on_released (GtkGestureMultiPress *gesture,
int n_press,
double x,
double y,
DemoTaggedEntryTag *tag)
{
g_signal_emit (tag, signals[SIGNAL_CLICKED], 0);
}
static void
demo_tagged_entry_tag_init (DemoTaggedEntryTag *tag)
{
GtkGesture *gesture;
GtkCssProvider *provider;
gtk_widget_set_has_surface (GTK_WIDGET (tag), FALSE);
tag->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_parent (tag->box, GTK_WIDGET (tag));
tag->label = gtk_label_new ("");
gtk_container_add (GTK_CONTAINER (tag->box), tag->label);
gesture = gtk_gesture_multi_press_new ();
g_signal_connect (gesture, "released", G_CALLBACK (on_released), tag);
gtk_widget_add_controller (GTK_WIDGET (tag), GTK_EVENT_CONTROLLER (gesture));
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/tagged_entry/tagstyle.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
800);
g_object_unref (provider);
}
static void
demo_tagged_entry_tag_dispose (GObject *object)
{
DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (object);
g_clear_pointer (&tag->box, gtk_widget_unparent);
G_OBJECT_CLASS (demo_tagged_entry_tag_parent_class)->dispose (object);
}
static void
demo_tagged_entry_tag_finalize (GObject *object)
{
DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (object);
g_clear_pointer (&tag->box, gtk_widget_unparent);
g_clear_pointer (&tag->style, g_free);
G_OBJECT_CLASS (demo_tagged_entry_tag_parent_class)->finalize (object);
}
static void
demo_tagged_entry_tag_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (object);
switch (prop_id)
{
case PROP_LABEL:
demo_tagged_entry_tag_set_label (tag, g_value_get_string (value));
break;
case PROP_HAS_CLOSE_BUTTON:
demo_tagged_entry_tag_set_has_close_button (tag, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
demo_tagged_entry_tag_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (object);
switch (prop_id)
{
case PROP_LABEL:
g_value_set_string (value, demo_tagged_entry_tag_get_label (tag));
break;
case PROP_HAS_CLOSE_BUTTON:
g_value_set_boolean (value, demo_tagged_entry_tag_get_has_close_button (tag));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
demo_tagged_entry_tag_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (widget);
gtk_widget_measure (tag->box, orientation, for_size,
minimum, natural,
minimum_baseline, natural_baseline);
}
static void
demo_tagged_entry_tag_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
DemoTaggedEntryTag *tag = DEMO_TAGGED_ENTRY_TAG (widget);
gtk_widget_size_allocate (tag->box,
&(GtkAllocation) { 0, 0, width, height },
baseline);
}
static void
demo_tagged_entry_tag_class_init (DemoTaggedEntryTagClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->dispose = demo_tagged_entry_tag_dispose;
object_class->finalize = demo_tagged_entry_tag_finalize;
object_class->set_property = demo_tagged_entry_tag_set_property;
object_class->get_property = demo_tagged_entry_tag_get_property;
widget_class->measure = demo_tagged_entry_tag_measure;
widget_class->size_allocate = demo_tagged_entry_tag_size_allocate;
signals[SIGNAL_CLICKED] =
g_signal_new ("clicked",
DEMO_TYPE_TAGGED_ENTRY_TAG,
G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
signals[SIGNAL_BUTTON_CLICKED] =
g_signal_new ("button-clicked",
DEMO_TYPE_TAGGED_ENTRY_TAG,
G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
g_object_class_install_property (object_class, PROP_LABEL,
g_param_spec_string ("label", "Label", "Label",
NULL, G_PARAM_READWRITE));
g_object_class_install_property (object_class, PROP_HAS_CLOSE_BUTTON,
g_param_spec_boolean ("has-close-button", "Has close button", "Whether this tag has a close button",
FALSE, G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
gtk_widget_class_set_css_name (widget_class, "tag");
}
DemoTaggedEntryTag *
demo_tagged_entry_tag_new (const char *label)
{
return DEMO_TAGGED_ENTRY_TAG (g_object_new (DEMO_TYPE_TAGGED_ENTRY_TAG,
"label", label,
NULL));
}
const char *
demo_tagged_entry_tag_get_label (DemoTaggedEntryTag *tag)
{
g_return_val_if_fail (DEMO_IS_TAGGED_ENTRY_TAG (tag), NULL);
return gtk_label_get_label (GTK_LABEL (tag->label));
}
void
demo_tagged_entry_tag_set_label (DemoTaggedEntryTag *tag,
const char *label)
{
g_return_if_fail (DEMO_IS_TAGGED_ENTRY_TAG (tag));
gtk_label_set_label (GTK_LABEL (tag->label), label);
}
static void
on_button_clicked (GtkButton *button,
DemoTaggedEntryTag *tag)
{
g_signal_emit (tag, signals[SIGNAL_BUTTON_CLICKED], 0);
}
void
demo_tagged_entry_tag_set_has_close_button (DemoTaggedEntryTag *tag,
gboolean has_close_button)
{
g_return_if_fail (DEMO_IS_TAGGED_ENTRY_TAG (tag));
if ((tag->button != NULL) == has_close_button)
return;
if (!has_close_button && tag->button)
{
gtk_container_remove (GTK_CONTAINER (tag->box), tag->button);
tag->button = NULL;
}
else if (has_close_button && tag->button == NULL)
{
GtkWidget *image;
image = gtk_image_new_from_icon_name ("window-close-symbolic");
tag->button = gtk_button_new ();
gtk_container_add (GTK_CONTAINER (tag->button), image);
gtk_widget_set_halign (tag->button, GTK_ALIGN_CENTER);
gtk_widget_set_valign (tag->button, GTK_ALIGN_CENTER);
gtk_button_set_relief (GTK_BUTTON (tag->button), GTK_RELIEF_NONE);
gtk_container_add (GTK_CONTAINER (tag->box), tag->button);
g_signal_connect (tag->button, "clicked", G_CALLBACK (on_button_clicked), tag);
}
g_object_notify (G_OBJECT (tag), "has-close-button");
}
gboolean
demo_tagged_entry_tag_get_has_close_button (DemoTaggedEntryTag *tag)
{
g_return_val_if_fail (DEMO_IS_TAGGED_ENTRY_TAG (tag), FALSE);
return tag->button != NULL;
}
-89
View File
@@ -1,89 +0,0 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2019 Red Hat, Inc.
*
* Authors:
* - Matthias Clasen <mclasen@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __DEMO_TAGGED_ENTRY_H__
#define __DEMO_TAGGED_ENTRY_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define DEMO_TYPE_TAGGED_ENTRY (demo_tagged_entry_get_type ())
#define DEMO_TAGGED_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DEMO_TYPE_TAGGED_ENTRY, DemoTaggedEntry))
#define DEMO_TAGGED_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DEMO_TYPE_TAGGED_ENTRY, DemoTaggedEntryClass))
#define DEMO_IS_TAGGED_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DEMO_TYPE_TAGGED_ENTRY))
#define DEMO_IS_TAGGED_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DEMO_TYPE_TAGGED_ENTRY))
#define DEMO_TAGGED_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEMO_TYPE_TAGGED_ENTRY, DemoTaggedEntryClass))
typedef struct _DemoTaggedEntry DemoTaggedEntry;
typedef struct _DemoTaggedEntryClass DemoTaggedEntryClass;
struct _DemoTaggedEntry
{
GtkWidget parent;
};
struct _DemoTaggedEntryClass
{
GtkWidgetClass parent_class;
};
#define DEMO_TYPE_TAGGED_ENTRY_TAG (demo_tagged_entry_tag_get_type ())
#define DEMO_TAGGED_ENTRY_TAG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DEMO_TYPE_TAGGED_ENTRY_TAG, DemoTaggedEntryTag))
#define DEMO_TAGGED_ENTRY_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DEMO_TYPE_TAGGED_ENTRY_TAG, DemoTaggedEntryTag))
#define DEMO_IS_TAGGED_ENTRY_TAG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DEMO_TYPE_TAGGED_ENTRY_TAG))
#define DEMO_IS_TAGGED_ENTRY_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DEMO_TYPE_TAGGED_ENTRY_TAG))
#define DEMO_TAGGED_ENTRY_TAG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEMO_TYPE_TAGGED_ENTRY_TAG, DemoTaggedEntryTagClass))
typedef struct _DemoTaggedEntryTag DemoTaggedEntryTag;
typedef struct _DemoTaggedEntryTagClass DemoTaggedEntryTagClass;
GType demo_tagged_entry_get_type (void) G_GNUC_CONST;
GType demo_tagged_entry_tag_get_type (void) G_GNUC_CONST;
GtkWidget * demo_tagged_entry_new (void);
void demo_tagged_entry_add_tag (DemoTaggedEntry *entry,
GtkWidget *tag);
void demo_tagged_entry_insert_tag_after (DemoTaggedEntry *entry,
GtkWidget *tag,
GtkWidget *sibling);
void demo_tagged_entry_remove_tag (DemoTaggedEntry *entry,
GtkWidget *tag);
DemoTaggedEntryTag *
demo_tagged_entry_tag_new (const char *label);
const char * demo_tagged_entry_tag_get_label (DemoTaggedEntryTag *tag);
void demo_tagged_entry_tag_set_label (DemoTaggedEntryTag *tag,
const char *label);
gboolean demo_tagged_entry_tag_get_has_close_button (DemoTaggedEntryTag *tag);
void demo_tagged_entry_tag_set_has_close_button (DemoTaggedEntryTag *tag,
gboolean has_close_button);
G_END_DECLS
#endif /* __DEMO_TAGGED_ENTRY_H__ */
+14 -14
View File
@@ -56,20 +56,20 @@ interactive_dialog_clicked (GtkButton *button,
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
gtk_container_add (GTK_CONTAINER (content_area), hbox);
gtk_box_pack_start (GTK_BOX (content_area), hbox);
image = gtk_image_new_from_icon_name ("dialog-question");
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
gtk_container_add (GTK_CONTAINER (hbox), image);
gtk_box_pack_start (GTK_BOX (hbox), image);
table = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (table), 4);
gtk_grid_set_column_spacing (GTK_GRID (table), 4);
gtk_container_add (GTK_CONTAINER (hbox), table);
gtk_box_pack_start (GTK_BOX (hbox), table);
label = gtk_label_new_with_mnemonic ("_Entry 1");
gtk_grid_attach (GTK_GRID (table), label, 0, 0, 1, 1);
local_entry1 = gtk_entry_new ();
gtk_editable_set_text (GTK_EDITABLE (local_entry1), gtk_editable_get_text (GTK_EDITABLE (entry1)));
gtk_entry_set_text (GTK_ENTRY (local_entry1), gtk_entry_get_text (GTK_ENTRY (entry1)));
gtk_grid_attach (GTK_GRID (table), local_entry1, 1, 0, 1, 1);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), local_entry1);
@@ -77,7 +77,7 @@ interactive_dialog_clicked (GtkButton *button,
gtk_grid_attach (GTK_GRID (table), label, 0, 1, 1, 1);
local_entry2 = gtk_entry_new ();
gtk_editable_set_text (GTK_EDITABLE (local_entry2), gtk_editable_get_text (GTK_EDITABLE (entry2)));
gtk_entry_set_text (GTK_ENTRY (local_entry2), gtk_entry_get_text (GTK_ENTRY (entry2)));
gtk_grid_attach (GTK_GRID (table), local_entry2, 1, 1, 1, 1);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), local_entry2);
@@ -85,8 +85,8 @@ interactive_dialog_clicked (GtkButton *button,
if (response == GTK_RESPONSE_OK)
{
gtk_editable_set_text (GTK_EDITABLE (entry1), gtk_editable_get_text (GTK_EDITABLE (local_entry1)));
gtk_editable_set_text (GTK_EDITABLE (entry2), gtk_editable_get_text (GTK_EDITABLE (local_entry2)));
gtk_entry_set_text (GTK_ENTRY (entry1), gtk_entry_get_text (GTK_ENTRY (local_entry1)));
gtk_entry_set_text (GTK_ENTRY (entry2), gtk_entry_get_text (GTK_ENTRY (local_entry2)));
}
gtk_widget_destroy (dialog);
@@ -123,29 +123,29 @@ do_dialog (GtkWidget *do_widget)
/* Standard message dialog */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
gtk_container_add (GTK_CONTAINER (vbox), hbox);
gtk_box_pack_start (GTK_BOX (vbox), hbox);
button = gtk_button_new_with_mnemonic ("_Message Dialog");
g_signal_connect (button, "clicked",
G_CALLBACK (message_dialog_clicked), NULL);
gtk_container_add (GTK_CONTAINER (hbox), button);
gtk_box_pack_start (GTK_BOX (hbox), button);
gtk_container_add (GTK_CONTAINER (vbox), gtk_separator_new (GTK_ORIENTATION_HORIZONTAL));
gtk_box_pack_start (GTK_BOX (vbox), gtk_separator_new (GTK_ORIENTATION_HORIZONTAL));
/* Interactive dialog*/
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
gtk_container_add (GTK_CONTAINER (vbox), hbox);
gtk_box_pack_start (GTK_BOX (vbox), hbox);
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
button = gtk_button_new_with_mnemonic ("_Interactive Dialog");
g_signal_connect (button, "clicked",
G_CALLBACK (interactive_dialog_clicked), NULL);
gtk_container_add (GTK_CONTAINER (hbox), vbox2);
gtk_container_add (GTK_CONTAINER (vbox2), button);
gtk_box_pack_start (GTK_BOX (hbox), vbox2);
gtk_box_pack_start (GTK_BOX (vbox2), button);
table = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (table), 4);
gtk_grid_set_column_spacing (GTK_GRID (table), 4);
gtk_container_add (GTK_CONTAINER (hbox), table);
gtk_box_pack_start (GTK_BOX (hbox), table);
label = gtk_label_new_with_mnemonic ("_Entry 1");
gtk_grid_attach (GTK_GRID (table), label, 0, 0, 1, 1);
+9 -10
View File
@@ -196,10 +196,10 @@ edit_label_done (GtkWidget *entry, gpointer data)
GtkWidget *label;
int x, y;
gtk_fixed_get_child_position (GTK_FIXED (fixed), entry, &x, &y);
gtk_container_child_get (GTK_CONTAINER (fixed), entry, "x", &x, "y", &y, NULL);
label = GTK_WIDGET (g_object_get_data (G_OBJECT (entry), "label"));
gtk_label_set_text (GTK_LABEL (label), gtk_editable_get_text (GTK_EDITABLE (entry)));
gtk_label_set_text (GTK_LABEL (label), gtk_entry_get_text (GTK_ENTRY (entry)));
gtk_widget_destroy (entry);
}
@@ -210,7 +210,7 @@ edit_cb (GtkWidget *child)
GtkWidget *fixed = gtk_widget_get_parent (child);
int x, y;
gtk_fixed_get_child_position (GTK_FIXED (fixed), child, &x, &y);
gtk_container_child_get (GTK_CONTAINER (fixed), child, "x", &x, "y", &y, NULL);
if (GTK_IS_LABEL (child))
{
@@ -218,7 +218,7 @@ edit_cb (GtkWidget *child)
g_object_set_data (G_OBJECT (entry), "label", child);
gtk_editable_set_text (GTK_EDITABLE (entry), gtk_label_get_text (GTK_LABEL (child)));
gtk_entry_set_text (GTK_ENTRY (entry), gtk_label_get_text (GTK_LABEL (child)));
g_signal_connect (entry, "activate", G_CALLBACK (edit_label_done), NULL);
gtk_fixed_put (GTK_FIXED (fixed), entry, x, y);
gtk_widget_grab_focus (entry);
@@ -243,7 +243,7 @@ pressed_cb (GtkGesture *gesture,
GtkWidget *child;
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
child = gtk_widget_pick (widget, x, y, GTK_PICK_DEFAULT);
child = gtk_widget_pick (widget, x, y);
if (gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)) == GDK_BUTTON_SECONDARY)
{
@@ -299,7 +299,7 @@ pressed_cb (GtkGesture *gesture,
rect.height = 0;
gtk_menu_popup_at_rect (GTK_MENU (menu),
gtk_widget_get_surface (widget),
gtk_widget_get_window (widget),
&rect,
GDK_GRAVITY_NORTH_WEST,
GDK_GRAVITY_NORTH_WEST,
@@ -320,7 +320,7 @@ released_cb (GtkGesture *gesture,
GtkWidget *child;
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
child = gtk_widget_pick (widget, x, y, 0);
child = gtk_widget_pick (widget, x, y);
if (gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)) == GDK_BUTTON_PRIMARY)
{
@@ -352,15 +352,14 @@ do_dnd (GtkWidget *do_widget)
gtk_container_add (GTK_CONTAINER (window), vbox);
fixed = gtk_fixed_new ();
gtk_container_add (GTK_CONTAINER (vbox), fixed);
gtk_box_pack_start (GTK_BOX (vbox), fixed);
gtk_widget_set_hexpand (fixed, TRUE);
gtk_widget_set_vexpand (fixed, TRUE);
multipress = gtk_gesture_multi_press_new ();
multipress = gtk_gesture_multi_press_new (fixed);
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (multipress), 0);
g_signal_connect (multipress, "pressed", G_CALLBACK (pressed_cb), NULL);
g_signal_connect (multipress, "released", G_CALLBACK (released_cb), NULL);
gtk_widget_add_controller (fixed, GTK_EVENT_CONTROLLER (multipress));
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/dnd/dnd.css");
+10 -11
View File
@@ -4,8 +4,8 @@
* of various kinds.
*
* This demo has two drawing areas. The checkerboard area shows
* how you can just draw something; all you have to do is set a function
* via gtk_drawing_area_set_draw_func(), as shown here.
* how you can just draw something; all you have to do is write
* a signal handler for expose_event, as shown here.
*
* The "scribble" area is a bit more advanced, and shows how to handle
* events such as button presses and mouse motion. Click the mouse
@@ -86,7 +86,7 @@ draw_brush (GtkWidget *widget,
cairo_destroy (cr);
gtk_widget_queue_draw (widget);
gtk_widget_queue_draw_area (widget, update_rect.x, update_rect.y, update_rect.width, update_rect.height);
}
static double start_x;
@@ -137,7 +137,7 @@ checkerboard_draw (GtkDrawingArea *da,
/* At the start of a draw handler, a clip region has been set on
* the Cairo context, and the contents have been cleared to the
* widget's background color. The docs for
* gdk_surface_begin_paint_region() give more details on how this
* gdk_window_begin_paint_region() give more details on how this
* works.
*/
@@ -208,12 +208,12 @@ do_drawingarea (GtkWidget *do_widget)
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label),
"<u>Checkerboard pattern</u>");
gtk_container_add (GTK_CONTAINER (vbox), label);
gtk_box_pack_start (GTK_BOX (vbox), label);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_widget_set_vexpand (frame, TRUE);
gtk_container_add (GTK_CONTAINER (vbox), frame);
gtk_box_pack_start (GTK_BOX (vbox), frame);
da = gtk_drawing_area_new ();
gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), 100);
@@ -228,12 +228,12 @@ do_drawingarea (GtkWidget *do_widget)
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label),
"<u>Scribble area</u>");
gtk_container_add (GTK_CONTAINER (vbox), label);
gtk_box_pack_start (GTK_BOX (vbox), label);
frame = gtk_frame_new (NULL);
gtk_widget_set_vexpand (frame, TRUE);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_container_add (GTK_CONTAINER (vbox), frame);
gtk_box_pack_start (GTK_BOX (vbox), frame);
da = gtk_drawing_area_new ();
gtk_drawing_area_set_content_width (GTK_DRAWING_AREA (da), 100);
@@ -244,14 +244,13 @@ do_drawingarea (GtkWidget *do_widget)
g_signal_connect (da, "size-allocate",
G_CALLBACK (scribble_size_allocate), NULL);
drag = gtk_gesture_drag_new ();
drag = gtk_gesture_drag_new (da);
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (drag), GDK_BUTTON_PRIMARY);
gtk_widget_add_controller (da, GTK_EVENT_CONTROLLER (drag));
g_object_set_data_full (G_OBJECT (da), "drag", drag, g_object_unref);
g_signal_connect (drag, "drag-begin", G_CALLBACK (drag_begin), da);
g_signal_connect (drag, "drag-update", G_CALLBACK (drag_update), da);
g_signal_connect (drag, "drag-end", G_CALLBACK (drag_end), da);
}
if (!gtk_widget_get_visible (window))
+5 -5
View File
@@ -356,7 +356,7 @@ do_editable_cells (GtkWidget *do_widget)
g_object_set (vbox, "margin", 5, NULL);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_container_add (GTK_CONTAINER (vbox),
gtk_box_pack_start (GTK_BOX (vbox),
gtk_label_new ("Shopping list (you can edit the cells!)"));
sw = gtk_scrolled_window_new (NULL, NULL);
@@ -365,7 +365,7 @@ do_editable_cells (GtkWidget *do_widget)
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (vbox), sw);
gtk_box_pack_start (GTK_BOX (vbox), sw);
/* create models */
items_model = create_items_model ();
@@ -387,17 +387,17 @@ do_editable_cells (GtkWidget *do_widget)
/* some buttons */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
gtk_container_add (GTK_CONTAINER (vbox), hbox);
gtk_box_pack_start (GTK_BOX (vbox), hbox);
button = gtk_button_new_with_label ("Add item");
g_signal_connect (button, "clicked",
G_CALLBACK (add_item), treeview);
gtk_container_add (GTK_CONTAINER (hbox), button);
gtk_box_pack_start (GTK_BOX (hbox), button);
button = gtk_button_new_with_label ("Remove item");
g_signal_connect (button, "clicked",
G_CALLBACK (remove_item), treeview);
gtk_container_add (GTK_CONTAINER (hbox), button);
gtk_box_pack_start (GTK_BOX (hbox), button);
gtk_window_set_default_size (GTK_WINDOW (window), 320, 200);
}
+3 -3
View File
@@ -34,19 +34,19 @@ do_entry_buffer (GtkWidget *do_widget)
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label),
"Entries share a buffer. Typing in one is reflected in the other.");
gtk_container_add (GTK_CONTAINER (vbox), label);
gtk_box_pack_start (GTK_BOX (vbox), label);
/* Create a buffer */
buffer = gtk_entry_buffer_new (NULL, 0);
/* Create our first entry */
entry = gtk_entry_new_with_buffer (buffer);
gtk_container_add (GTK_CONTAINER (vbox), entry);
gtk_box_pack_start (GTK_BOX (vbox), entry);
/* Create the second entry */
entry = gtk_entry_new_with_buffer (buffer);
gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
gtk_container_add (GTK_CONTAINER (vbox), entry);
gtk_box_pack_start (GTK_BOX (vbox), entry);
g_object_unref (buffer);
}
+2 -2
View File
@@ -60,11 +60,11 @@ do_entry_completion (GtkWidget *do_widget)
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label), "Completion demo, try writing <b>total</b> or <b>gnome</b> for example.");
gtk_container_add (GTK_CONTAINER (vbox), label);
gtk_box_pack_start (GTK_BOX (vbox), label);
/* Create our entry */
entry = gtk_entry_new ();
gtk_container_add (GTK_CONTAINER (vbox), entry);
gtk_box_pack_start (GTK_BOX (vbox), entry);
/* Create the completion object */
completion = gtk_entry_completion_new ();
+668
View File
@@ -0,0 +1,668 @@
/* Touch and Drawing Tablets
*
* Demonstrates advanced handling of event information from exotic
* input devices.
*
* On one hand, this snippet demonstrates management of drawing tablets,
* those contain additional information for the pointer other than
* X/Y coordinates. Tablet pads events are mapped to actions, which
* are both defined and interpreted by the application.
*
* Input axes are dependent on hardware devices, on linux/unix you
* can see the device axes through xinput list <device>. Each time
* a different hardware device is used to move the pointer, the
* master device will be updated to match the axes it provides,
* these changes can be tracked through GdkDevice::changed, or
* checking gdk_event_get_source_device().
*
* On the other hand, this demo handles basic multitouch events,
* each event coming from an specific touchpoint will contain a
* GdkEventSequence that's unique for its lifetime, so multiple
* touchpoints can be tracked.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
typedef struct {
GdkDevice *last_source;
GdkDeviceTool *last_tool;
gdouble *axes;
GdkRGBA color;
gdouble x;
gdouble y;
} AxesInfo;
typedef struct {
GHashTable *pointer_info; /* GdkDevice -> AxesInfo */
GHashTable *touch_info; /* GdkEventSequence -> AxesInfo */
} EventData;
const gchar *colors[] = {
"black",
"orchid",
"fuchsia",
"indigo",
"thistle",
"sienna",
"azure",
"plum",
"lime",
"navy",
"maroon",
"burlywood"
};
static GtkPadActionEntry pad_actions[] = {
{ GTK_PAD_ACTION_BUTTON, 1, -1, N_("Nuclear strike"), "pad.nuke" },
{ GTK_PAD_ACTION_BUTTON, 2, -1, N_("Release siberian methane reserves"), "pad.heat" },
{ GTK_PAD_ACTION_BUTTON, 3, -1, N_("Release solar flare"), "pad.fry" },
{ GTK_PAD_ACTION_BUTTON, 4, -1, N_("De-stabilize Oort cloud"), "pad.fall" },
{ GTK_PAD_ACTION_BUTTON, 5, -1, N_("Ignite WR-104"), "pad.burst" },
{ GTK_PAD_ACTION_BUTTON, 6, -1, N_("Lart whoever asks about this button"), "pad.lart" },
{ GTK_PAD_ACTION_RING, -1, -1, N_("Earth axial tilt"), "pad.tilt" },
{ GTK_PAD_ACTION_STRIP, -1, -1, N_("Extent of weak nuclear force"), "pad.dissolve" },
};
static const gchar *pad_action_results[] = {
"",
"",
"",
"",
"",
"💫",
"",
""
};
static guint cur_color = 0;
static guint pad_action_timeout_id = 0;
static AxesInfo *
axes_info_new (void)
{
AxesInfo *info;
info = g_new0 (AxesInfo, 1);
gdk_rgba_parse (&info->color, colors[cur_color]);
cur_color = (cur_color + 1) % G_N_ELEMENTS (colors);
return info;
}
static EventData *
event_data_new (void)
{
EventData *data;
data = g_new0 (EventData, 1);
data->pointer_info = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) g_free);
data->touch_info = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) g_free);
return data;
}
static void
event_data_free (EventData *data)
{
g_hash_table_destroy (data->pointer_info);
g_hash_table_destroy (data->touch_info);
g_free (data);
}
static void
update_axes_from_event (GdkEvent *event,
EventData *data)
{
GdkDevice *device, *source_device;
GdkEventSequence *sequence;
GdkDeviceTool *tool;
GdkEventType type;
gdouble x, y;
AxesInfo *info;
device = gdk_event_get_device (event);
source_device = gdk_event_get_source_device (event);
sequence = gdk_event_get_event_sequence (event);
tool = gdk_event_get_device_tool (event);
type = gdk_event_get_event_type (event);
if (type == GDK_TOUCH_END ||
type == GDK_TOUCH_CANCEL)
{
g_hash_table_remove (data->touch_info, sequence);
return;
}
else if (type == GDK_LEAVE_NOTIFY)
{
g_hash_table_remove (data->pointer_info, device);
return;
}
if (!source_device)
return;
if (!sequence)
{
info = g_hash_table_lookup (data->pointer_info, device);
if (!info)
{
info = axes_info_new ();
g_hash_table_insert (data->pointer_info, device, info);
}
}
else
{
info = g_hash_table_lookup (data->touch_info, sequence);
if (!info)
{
info = axes_info_new ();
g_hash_table_insert (data->touch_info, sequence, info);
}
}
if (info->last_source != source_device)
info->last_source = source_device;
if (info->last_tool != tool)
info->last_tool = tool;
g_clear_pointer (&info->axes, g_free);
if (type == GDK_TOUCH_BEGIN ||
type == GDK_TOUCH_UPDATE)
{
gboolean emulating_pointer;
gdk_event_get_touch_emulating_pointer (event, &emulating_pointer);
if (sequence && emulating_pointer)
g_hash_table_remove (data->pointer_info, device);
}
if (type == GDK_MOTION_NOTIFY ||
type == GDK_BUTTON_PRESS ||
type == GDK_BUTTON_RELEASE)
{
gdouble *axes;
guint n_axes;
gdk_event_get_axes (event, &axes, &n_axes);
info->axes = g_memdup (axes, sizeof (double) * n_axes);
}
if (gdk_event_get_coords (event, &x, &y))
{
info->x = x;
info->y = y;
}
}
static gboolean
event_cb (GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
update_axes_from_event (event, user_data);
gtk_widget_queue_draw (widget);
return FALSE;
}
static void
render_arrow (cairo_t *cr,
gdouble x_diff,
gdouble y_diff,
const gchar *label)
{
cairo_save (cr);
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_new_path (cr);
cairo_move_to (cr, 0, 0);
cairo_line_to (cr, x_diff, y_diff);
cairo_stroke (cr);
cairo_move_to (cr, x_diff, y_diff);
cairo_show_text (cr, label);
cairo_restore (cr);
}
static void
draw_axes_info (cairo_t *cr,
AxesInfo *info,
int width,
int height)
{
gdouble pressure, tilt_x, tilt_y, distance, wheel, rotation, slider;
GdkAxisFlags axes = gdk_device_get_axes (info->last_source);
cairo_save (cr);
cairo_set_line_width (cr, 1);
gdk_cairo_set_source_rgba (cr, &info->color);
cairo_move_to (cr, 0, info->y);
cairo_line_to (cr, width, info->y);
cairo_move_to (cr, info->x, 0);
cairo_line_to (cr, info->x, height);
cairo_stroke (cr);
cairo_translate (cr, info->x, info->y);
if (!info->axes)
{
cairo_restore (cr);
return;
}
if (axes & GDK_AXIS_FLAG_PRESSURE)
{
cairo_pattern_t *pattern;
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_PRESSURE,
&pressure);
pattern = cairo_pattern_create_radial (0, 0, 0, 0, 0, 100);
cairo_pattern_add_color_stop_rgba (pattern, pressure, 1, 0, 0, pressure);
cairo_pattern_add_color_stop_rgba (pattern, 1, 0, 0, 1, 0);
cairo_set_source (cr, pattern);
cairo_arc (cr, 0, 0, 100, 0, 2 * G_PI);
cairo_fill (cr);
cairo_pattern_destroy (pattern);
}
if (axes & GDK_AXIS_FLAG_XTILT &&
axes & GDK_AXIS_FLAG_YTILT)
{
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_XTILT,
&tilt_x);
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_YTILT,
&tilt_y);
render_arrow (cr, tilt_x * 100, tilt_y * 100, "Tilt");
}
if (axes & GDK_AXIS_FLAG_DISTANCE)
{
double dashes[] = { 5.0, 5.0 };
cairo_text_extents_t extents;
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_DISTANCE,
&distance);
cairo_save (cr);
cairo_move_to (cr, distance * 100, 0);
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
cairo_set_dash (cr, dashes, 2, 0.0);
cairo_arc (cr, 0, 0, distance * 100, 0, 2 * G_PI);
cairo_stroke (cr);
cairo_move_to (cr, 0, -distance * 100);
cairo_text_extents (cr, "Distance", &extents);
cairo_rel_move_to (cr, -extents.width / 2, 0);
cairo_show_text (cr, "Distance");
cairo_move_to (cr, 0, 0);
cairo_restore (cr);
}
if (axes & GDK_AXIS_FLAG_WHEEL)
{
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_WHEEL,
&wheel);
cairo_save (cr);
cairo_set_line_width (cr, 10);
cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
cairo_new_sub_path (cr);
cairo_arc (cr, 0, 0, 100, 0, wheel * 2 * G_PI);
cairo_stroke (cr);
cairo_restore (cr);
}
if (axes & GDK_AXIS_FLAG_ROTATION)
{
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_ROTATION,
&rotation);
rotation *= 2 * G_PI;
cairo_save (cr);
cairo_rotate (cr, - G_PI / 2);
cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
cairo_set_line_width (cr, 5);
cairo_new_sub_path (cr);
cairo_arc (cr, 0, 0, 100, 0, rotation);
cairo_stroke (cr);
cairo_restore (cr);
}
if (axes & GDK_AXIS_FLAG_SLIDER)
{
cairo_pattern_t *pattern, *mask;
gdk_device_get_axis (info->last_source, info->axes, GDK_AXIS_SLIDER,
&slider);
cairo_save (cr);
cairo_move_to (cr, 0, -10);
cairo_rel_line_to (cr, 0, -50);
cairo_rel_line_to (cr, 10, 0);
cairo_rel_line_to (cr, -5, 50);
cairo_close_path (cr);
cairo_clip_preserve (cr);
pattern = cairo_pattern_create_linear (0, -10, 0, -60);
cairo_pattern_add_color_stop_rgb (pattern, 0, 0, 1, 0);
cairo_pattern_add_color_stop_rgb (pattern, 1, 1, 0, 0);
cairo_set_source (cr, pattern);
cairo_pattern_destroy (pattern);
mask = cairo_pattern_create_linear (0, -10, 0, -60);
cairo_pattern_add_color_stop_rgba (mask, 0, 0, 0, 0, 1);
cairo_pattern_add_color_stop_rgba (mask, slider, 0, 0, 0, 1);
cairo_pattern_add_color_stop_rgba (mask, slider, 0, 0, 0, 0);
cairo_pattern_add_color_stop_rgba (mask, 1, 0, 0, 0, 0);
cairo_mask (cr, mask);
cairo_pattern_destroy (mask);
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_stroke (cr);
cairo_restore (cr);
}
cairo_restore (cr);
}
static const gchar *
tool_type_to_string (GdkDeviceToolType tool_type)
{
switch (tool_type)
{
case GDK_DEVICE_TOOL_TYPE_PEN:
return "Pen";
case GDK_DEVICE_TOOL_TYPE_ERASER:
return "Eraser";
case GDK_DEVICE_TOOL_TYPE_BRUSH:
return "Brush";
case GDK_DEVICE_TOOL_TYPE_PENCIL:
return "Pencil";
case GDK_DEVICE_TOOL_TYPE_AIRBRUSH:
return "Airbrush";
case GDK_DEVICE_TOOL_TYPE_MOUSE:
return "Mouse";
case GDK_DEVICE_TOOL_TYPE_LENS:
return "Lens cursor";
case GDK_DEVICE_TOOL_TYPE_UNKNOWN:
default:
return "Unknown";
}
}
static void
draw_device_info (GtkWidget *widget,
cairo_t *cr,
GdkEventSequence *sequence,
gint *y,
AxesInfo *info)
{
PangoLayout *layout;
GString *string;
gint height;
cairo_save (cr);
string = g_string_new (NULL);
g_string_append_printf (string, "Source: %s",
gdk_device_get_name (info->last_source));
if (sequence)
g_string_append_printf (string, "\nSequence: %d",
GPOINTER_TO_UINT (sequence));
if (info->last_tool)
{
const gchar *tool_type;
guint64 serial;
tool_type = tool_type_to_string (gdk_device_tool_get_tool_type (info->last_tool));
serial = gdk_device_tool_get_serial (info->last_tool);
g_string_append_printf (string, "\nTool: %s", tool_type);
if (serial != 0)
g_string_append_printf (string, ", Serial: %lx", serial);
}
cairo_move_to (cr, 10, *y);
layout = gtk_widget_create_pango_layout (widget, string->str);
pango_cairo_show_layout (cr, layout);
cairo_stroke (cr);
pango_layout_get_pixel_size (layout, NULL, &height);
gdk_cairo_set_source_rgba (cr, &info->color);
cairo_set_line_width (cr, 10);
cairo_move_to (cr, 0, *y);
*y = *y + height;
cairo_line_to (cr, 0, *y);
cairo_stroke (cr);
cairo_restore (cr);
g_object_unref (layout);
g_string_free (string, TRUE);
}
static void
draw_cb (GtkDrawingArea *da,
cairo_t *cr,
int width,
int height,
gpointer user_data)
{
GtkWidget *widget = GTK_WIDGET (da);
EventData *data = user_data;
AxesInfo *info;
GHashTableIter iter;
gpointer key, value;
gint y = 0;
/* Draw Abs info */
g_hash_table_iter_init (&iter, data->pointer_info);
while (g_hash_table_iter_next (&iter, NULL, &value))
{
info = value;
draw_axes_info (cr, info, width, height);
}
g_hash_table_iter_init (&iter, data->touch_info);
while (g_hash_table_iter_next (&iter, NULL, &value))
{
info = value;
draw_axes_info (cr, info, width, height);
}
/* Draw name, color legend and misc data */
g_hash_table_iter_init (&iter, data->pointer_info);
while (g_hash_table_iter_next (&iter, NULL, &value))
{
info = value;
draw_device_info (widget, cr, NULL, &y, info);
}
g_hash_table_iter_init (&iter, data->touch_info);
while (g_hash_table_iter_next (&iter, &key, &value))
{
info = value;
draw_device_info (widget, cr, key, &y, info);
}
}
static void
update_label_text (GtkWidget *label,
const gchar *text)
{
gchar *markup = NULL;
if (text)
markup = g_strdup_printf ("<span font='48.0'>%s</span>", text);
gtk_label_set_markup (GTK_LABEL (label), markup);
g_free (markup);
}
static gboolean
reset_label_text_timeout_cb (gpointer user_data)
{
GtkWidget *label = user_data;
update_label_text (label, NULL);
pad_action_timeout_id = 0;
return G_SOURCE_REMOVE;
}
static void
update_label_and_timeout (GtkWidget *label,
const gchar *text)
{
if (pad_action_timeout_id)
g_source_remove (pad_action_timeout_id);
update_label_text (label, text);
pad_action_timeout_id = g_timeout_add (200, reset_label_text_timeout_cb, label);
}
static void
on_action_activate (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkWidget *label = user_data;
const gchar *result;
gchar *str;
result = g_object_get_data (G_OBJECT (action), "action-result");
if (!parameter)
update_label_and_timeout (label, result);
else
{
str = g_strdup_printf ("%s %.2f", result, g_variant_get_double (parameter));
update_label_and_timeout (label, str);
g_free (str);
}
}
static void
init_pad_controller (GtkWidget *window,
GtkWidget *label)
{
GtkPadController *pad_controller;
GSimpleActionGroup *action_group;
GSimpleAction *action;
gint i;
action_group = g_simple_action_group_new ();
pad_controller = gtk_pad_controller_new (GTK_WINDOW (window),
G_ACTION_GROUP (action_group),
NULL);
for (i = 0; i < G_N_ELEMENTS (pad_actions); i++)
{
if (pad_actions[i].type == GTK_PAD_ACTION_BUTTON)
{
action = g_simple_action_new (pad_actions[i].action_name, NULL);
}
else
{
action = g_simple_action_new_stateful (pad_actions[i].action_name,
G_VARIANT_TYPE_DOUBLE, NULL);
}
g_signal_connect (action, "activate",
G_CALLBACK (on_action_activate), label);
g_object_set_data (G_OBJECT (action), "action-result",
(gpointer) pad_action_results[i]);
g_action_map_add_action (G_ACTION_MAP (action_group), G_ACTION (action));
g_object_unref (action);
}
gtk_pad_controller_set_action_entries (pad_controller, pad_actions,
G_N_ELEMENTS (pad_actions));
g_object_set_data_full (G_OBJECT (window), "pad-controller",
pad_controller, g_object_unref);
g_object_unref (action_group);
}
GtkWidget *
do_event_axes (GtkWidget *toplevel)
{
static GtkWidget *window = NULL;
EventData *event_data;
GtkWidget *label;
GtkWidget *overlay;
GtkWidget *da;
if (!window)
{
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Touch and Drawing Tablets");
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
gtk_widget_set_support_multidevice (window, TRUE);
event_data = event_data_new ();
g_object_set_data_full (G_OBJECT (window), "gtk-demo-event-data",
event_data, (GDestroyNotify) event_data_free);
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_cb, event_data, NULL);
gtk_widget_set_can_focus (da, TRUE);
gtk_widget_grab_focus (da);
g_signal_connect (da, "event",
G_CALLBACK (event_cb), event_data);
label = gtk_label_new ("");
gtk_widget_set_halign (label, GTK_ALIGN_START);
gtk_widget_set_valign (label, GTK_ALIGN_START);
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
overlay = gtk_overlay_new ();
gtk_container_add (GTK_CONTAINER (window), overlay);
gtk_container_add (GTK_CONTAINER (overlay), da);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), label);
init_pad_controller (da, label);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_widget_destroy (window);
return window;
}
+1 -1
View File
@@ -73,7 +73,7 @@ do_expander (GtkWidget *do_widget)
"resize the window. Do it already !", -1);
gtk_container_add (GTK_CONTAINER (sw), tv);
gtk_container_add (GTK_CONTAINER (expander), sw);
gtk_container_add (GTK_CONTAINER (area), expander);
gtk_box_pack_end (GTK_BOX (area), expander);
g_signal_connect (expander, "notify::expanded",
G_CALLBACK (expander_cb), window);
+48 -56
View File
@@ -1,9 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.1 -->
<interface>
<requires lib="gtk+" version="3.16"/>
<object class="GtkListStore" id="liststore1">
<columns>
<!-- column-name width -->
<column type="gint"/>
<!-- column-name height -->
<column type="gint"/>
</columns>
<data>
@@ -31,31 +34,31 @@
<property name="title" translatable="yes">Filter Model</property>
<child>
<object class="GtkGrid" id="grid1">
<property name="visible">1</property>
<property name="margin">10</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<property name="column-homogeneous">1</property>
<property name="row_spacing">10</property>
<property name="column_spacing">10</property>
<property name="column_homogeneous">1</property>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">1</property>
<property name="label" translatable="yes">Original</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold"></attribute>
<attribute name="weight" value="bold"/>
</attributes>
<accessibility>
<relation type="label-for" target="treeview1"/>
</accessibility>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</layout>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkTreeView" id="treeview1">
<property name="can-focus">1</property>
<property name="visible">1</property>
<property name="can_focus">1</property>
<property name="model">liststore1</property>
<property name="headers-clickable">0</property>
<property name="headers_clickable">0</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection1"/>
</child>
@@ -81,20 +84,18 @@
</child>
</object>
</child>
<accessibility>
<relation type="labelled-by" target="label1"/>
</accessibility>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</layout>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkTreeView" id="treeview2">
<property name="can-focus">1</property>
<property name="headers-clickable">0</property>
<property name="search-column">0</property>
<property name="visible">1</property>
<property name="can_focus">1</property>
<property name="headers_clickable">0</property>
<property name="search_column">0</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection3"/>
</child>
@@ -132,52 +133,46 @@
</child>
</object>
</child>
<accessibility>
<relation type="labelled-by" target="label2"/>
</accessibility>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</layout>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">1</property>
<property name="label" translatable="yes">Computed Columns</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold"></attribute>
<attribute name="weight" value="bold"/>
</attributes>
<accessibility>
<relation type="label-for" target="treeview2"/>
</accessibility>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</layout>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">1</property>
<property name="label" translatable="yes">Filtered</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold"></attribute>
<attribute name="weight" value="bold"/>
</attributes>
<accessibility>
<relation type="label-for" target="treeview3"/>
</accessibility>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</layout>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkTreeView" id="treeview3">
<property name="can-focus">1</property>
<property name="headers-clickable">0</property>
<property name="search-column">0</property>
<property name="visible">1</property>
<property name="can_focus">1</property>
<property name="headers_clickable">0</property>
<property name="search_column">0</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection5"/>
</child>
@@ -197,14 +192,11 @@
</child>
</object>
</child>
<accessibility>
<relation type="labelled-by" target="label3"/>
</accessibility>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</layout>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
</packing>
</child>
</object>
</child>
+114 -221
View File
@@ -8,273 +8,165 @@
#include <gtk/gtk.h>
#include "gtkfishbowl.h"
#include "gtkgears.h"
const char *const css =
".blurred-button {"
" box-shadow: 0px 0px 5px 10px rgba(0, 0, 0, 0.5);"
"}"
"";
GtkWidget *allow_changes;
char **icon_names = NULL;
gsize n_icon_names = 0;
#define N_STATS 5
static void
init_icon_names (GtkIconTheme *theme)
{
GPtrArray *icons;
GList *l, *icon_list;
#define STATS_UPDATE_TIME G_USEC_PER_SEC
if (icon_names)
return;
typedef struct _Stats Stats;
struct _Stats {
gint64 last_stats;
gint64 last_frame;
gint last_suggestion;
guint frame_counter_max;
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 *
get_random_icon_name (GtkIconTheme *theme)
{
init_icon_names (theme);
return icon_names[g_random_int_range(0, n_icon_names)];
}
GtkWidget *
create_icon (void)
{
GtkWidget *image;
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);
return image;
}
static GtkWidget *
create_button (void)
{
return gtk_button_new_with_label ("Button");
}
static GtkWidget *
create_blurred_button (void)
{
GtkWidget *w = gtk_button_new ();
gtk_style_context_add_class (gtk_widget_get_style_context (w), "blurred-button");
return w;
}
static GtkWidget *
create_font_button (void)
{
return gtk_font_button_new ();
}
static GtkWidget *
create_level_bar (void)
{
GtkWidget *w = gtk_level_bar_new_for_interval (0, 100);
gtk_level_bar_set_value (GTK_LEVEL_BAR (w), 50);
/* Force them to be a bit larger */
gtk_widget_set_size_request (w, 200, -1);
return w;
}
static GtkWidget *
create_spinner (void)
{
GtkWidget *w = gtk_spinner_new ();
gtk_spinner_start (GTK_SPINNER (w));
return w;
}
static GtkWidget *
create_spinbutton (void)
{
GtkWidget *w = gtk_spin_button_new_with_range (0, 10, 1);
return w;
}
static GtkWidget *
create_label (void)
{
GtkWidget *w = gtk_label_new ("pLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.");
gtk_label_set_line_wrap (GTK_LABEL (w), TRUE);
gtk_label_set_max_width_chars (GTK_LABEL (w), 100);
return w;
}
static GtkWidget *
create_video (void)
{
GtkMediaStream *stream = gtk_media_file_new_for_resource ("/images/gtk-logo.webm");
GtkWidget *w = gtk_picture_new_for_paintable (GDK_PAINTABLE (stream));
gtk_widget_set_size_request (w, 64, 64);
gtk_media_stream_set_loop (stream, TRUE);
gtk_media_stream_play (stream);
g_object_unref (stream);
return w;
}
static GtkWidget *
create_gears (void)
{
GtkWidget *w = gtk_gears_new ();
gtk_widget_set_size_request (w, 100, 100);
return w;
}
static GtkWidget *
create_switch (void)
{
GtkWidget *w = gtk_switch_new ();
gtk_switch_set_state (GTK_SWITCH (w), TRUE);
return w;
}
static const struct {
const char *name;
GtkWidget * (*create_func) (void);
} widget_types[] = {
{ "Icon", create_icon },
{ "Button", create_button },
{ "Blurbutton", create_blurred_button },
{ "Fontbutton", create_font_button },
{ "Levelbar", create_level_bar },
{ "Label", create_label },
{ "Spinner", create_spinner },
{ "Spinbutton", create_spinbutton },
{ "Video", create_video },
{ "Gears", create_gears },
{ "Switch", create_switch },
guint stats_index;
guint frame_counter[N_STATS];
guint item_counter[N_STATS];
};
static int selected_widget_type = -1;
static const int N_WIDGET_TYPES = G_N_ELEMENTS (widget_types);
static Stats *
get_stats (GtkWidget *widget)
{
static GQuark stats_quark = 0;
Stats *stats;
if (G_UNLIKELY (stats_quark == 0))
stats_quark = g_quark_from_static_string ("stats");
stats = g_object_get_qdata (G_OBJECT (widget), stats_quark);
if (stats == NULL)
{
stats = g_new0 (Stats, 1);
g_object_set_qdata_full (G_OBJECT (widget), stats_quark, stats, g_free);
stats->last_frame = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
stats->last_stats = stats->last_frame;
}
return stats;
}
static void
set_widget_type (GtkFishbowl *fishbowl,
int widget_type_index)
do_stats (GtkWidget *widget,
GtkWidget *info_label,
gint *suggested_change)
{
GtkWidget *window, *headerbar;
Stats *stats;
gint64 frame_time;
if (widget_type_index == selected_widget_type)
return;
stats = get_stats (widget);
frame_time = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
selected_widget_type = widget_type_index;
if (stats->last_stats + STATS_UPDATE_TIME < frame_time)
{
char *new_label;
guint i, n_frames;
gtk_fishbowl_set_creation_func (fishbowl,
widget_types[selected_widget_type].create_func);
n_frames = 0;
for (i = 0; i < N_STATS; i++)
{
n_frames += stats->frame_counter[i];
}
new_label = g_strdup_printf ("icons - %.1f fps",
(double) G_USEC_PER_SEC * n_frames
/ (N_STATS * STATS_UPDATE_TIME));
gtk_label_set_label (GTK_LABEL (info_label), new_label);
g_free (new_label);
window = gtk_widget_get_toplevel (GTK_WIDGET (fishbowl));
headerbar = gtk_window_get_titlebar (GTK_WINDOW (window));
gtk_header_bar_set_title (GTK_HEADER_BAR (headerbar),
widget_types[selected_widget_type].name);
}
if (stats->frame_counter[stats->stats_index] >= 19 * stats->frame_counter_max / 20)
{
if (stats->last_suggestion > 0)
stats->last_suggestion *= 2;
else
stats->last_suggestion = 1;
}
else
{
if (stats->last_suggestion < 0)
stats->last_suggestion--;
else
stats->last_suggestion = -1;
stats->last_suggestion = MAX (stats->last_suggestion, 1 - (int) stats->item_counter[stats->stats_index]);
}
void
next_button_clicked_cb (GtkButton *source,
gpointer user_data)
{
GtkFishbowl *fishbowl = user_data;
int new_index;
if (selected_widget_type + 1 >= N_WIDGET_TYPES)
new_index = 0;
stats->stats_index = (stats->stats_index + 1) % N_STATS;
stats->frame_counter[stats->stats_index] = 0;
stats->item_counter[stats->stats_index] = stats->item_counter[(stats->stats_index + N_STATS - 1) % N_STATS];
stats->last_stats = frame_time;
if (suggested_change)
*suggested_change = stats->last_suggestion;
else
stats->last_suggestion = 0;
}
else
new_index = selected_widget_type + 1;
{
if (suggested_change)
*suggested_change = 0;
}
set_widget_type (fishbowl, new_index);
stats->last_frame = frame_time;
stats->frame_counter[stats->stats_index]++;
stats->frame_counter_max = MAX (stats->frame_counter_max, stats->frame_counter[stats->stats_index]);
}
void
prev_button_clicked_cb (GtkButton *source,
gpointer user_data)
static void
stats_update (GtkWidget *widget)
{
GtkFishbowl *fishbowl = user_data;
int new_index;
Stats *stats;
if (selected_widget_type - 1 < 0)
new_index = N_WIDGET_TYPES - 1;
else
new_index = selected_widget_type - 1;
stats = get_stats (widget);
set_widget_type (fishbowl, new_index);
stats->item_counter[stats->stats_index] = gtk_fishbowl_get_count (GTK_FISHBOWL (widget));
}
static gboolean
move_fish (GtkWidget *bowl,
GdkFrameClock *frame_clock,
gpointer info_label)
{
gint suggested_change = 0;
do_stats (bowl,
info_label,
!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (allow_changes)) ? &suggested_change : NULL);
gtk_fishbowl_set_count (GTK_FISHBOWL (bowl),
gtk_fishbowl_get_count (GTK_FISHBOWL (bowl)) + suggested_change);
stats_update (bowl);
return G_SOURCE_CONTINUE;
}
GtkWidget *
do_fishbowl (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
static GtkCssProvider *provider = NULL;
if (provider == NULL)
{
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (provider, css, -1);
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
if (!window)
{
GtkBuilder *builder;
GtkWidget *bowl;
GtkWidget *bowl, *info_label;
g_type_ensure (GTK_TYPE_FISHBOWL);
builder = gtk_builder_new_from_resource ("/fishbowl/fishbowl.ui");
gtk_builder_add_callback_symbols (builder,
"next_button_clicked_cb", G_CALLBACK (next_button_clicked_cb),
"prev_button_clicked_cb", G_CALLBACK (prev_button_clicked_cb),
NULL);
gtk_builder_connect_signals (builder, NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
bowl = GTK_WIDGET (gtk_builder_get_object (builder, "bowl"));
selected_widget_type = -1;
set_widget_type (GTK_FISHBOWL (bowl), 0);
gtk_fishbowl_set_use_icons (GTK_FISHBOWL (bowl), TRUE);
info_label = GTK_WIDGET (gtk_builder_get_object (builder, "info_label"));
allow_changes = GTK_WIDGET (gtk_builder_get_object (builder, "changes_allow"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);
gtk_widget_realize (window);
gtk_widget_add_tick_callback (bowl, move_fish, info_label, NULL);
}
if (!gtk_widget_get_visible (window))
@@ -282,5 +174,6 @@ do_fishbowl (GtkWidget *do_widget)
else
gtk_widget_destroy (window);
return window;
}
+26 -40
View File
@@ -1,63 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.6 -->
<object class="GtkWindow" id="window">
<property name="title" translatable="yes">Fishbowl</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="">
<property name="show-title-buttons">1</property>
<property name="visible">True</property>
<property name="show-title-buttons">True</property>
<child>
<object class="GtkBox">
<style>
<class name="linked"/>
</style>
<child>
<object class="GtkButton">
<property name="icon-name">pan-start-symbolic</property>
<signal name="clicked" handler="prev_button_clicked_cb" object="bowl" swapped="no"/>
</object>
</child>
<child>
<object class="GtkButton">
<property name="icon-name">pan-end-symbolic</property>
<signal name="clicked" handler="next_button_clicked_cb" object="bowl" swapped="no"/>
</object>
</child>
<object class="GtkLabel" id="info_label">
<property name="visible">True</property>
</object>
<packing>
<property name="pack_type">end</property>
</packing>
</child>
<child type="end">
<child>
<object class="GtkLabel">
<property name="label">fps</property>
<property name="visible">True</property>
<property name="label" bind-source="bowl" bind-property="count">0</property>
</object>
<packing>
<property name="pack_type">end</property>
</packing>
</child>
<child type="end">
<object class="GtkLabel">
<property name="label" bind-source="bowl" bind-property="framerate"/>
</object>
</child>
<child type="end">
<object class="GtkLabel">
<property name="label">Icons, </property>
</object>
</child>
<child type="end">
<object class="GtkLabel">
<property name="label" bind-source="bowl" bind-property="count"/>
</object>
</child>
<child type="end">
<child>
<object class="GtkToggleButton" id="changes_allow">
<property name="visible" bind-source="changes_allow" bind-property="active" bind-flags="invert-boolean"/>
<property name="active">False</property>
<property name="visible" bind-source="changes_allow" bind-property="active" bind-flags="invert-boolean">True</property>
<property name="icon-name">changes-allow</property>
<property name="relief">none</property>
</object>
<packing>
<property name="pack_type">end</property>
</packing>
</child>
<child type="end">
<child>
<object class="GtkToggleButton" id="changes_prevent">
<property name="active" bind-source="changes_allow" bind-property="active" bind-flags="bidirectional|invert-boolean"/>
<property name="visible" bind-source="changes_prevent" bind-property="active" bind-flags="invert-boolean"/>
<property name="active" bind-source="changes_allow" bind-property="active" bind-flags="bidirectional|invert-boolean">True</property>
<property name="visible" bind-source="changes_prevent" bind-property="active" bind-flags="invert-boolean">False</property>
<property name="icon-name">changes-prevent</property>
<property name="relief">none</property>
</object>
<packing>
<property name="pack_type">end</property>
</packing>
</child>
</object>
</child>
@@ -65,7 +52,6 @@
<object class="GtkFishbowl" id="bowl">
<property name="visible">True</property>
<property name="animating">True</property>
<property name="benchmark" bind-source="changes_allow" bind-property="active" bind-flags="invert-boolean"/>
</object>
</child>
</object>
-167
View File
@@ -1,167 +0,0 @@
/* Fixed layout
*
* GtkFixed is a container that allows placing and transforming
* widgets manually.
*/
#include <gtk/gtk.h>
/* This enumeration determines the paint order */
enum {
FACE_BACK,
FACE_LEFT,
FACE_BOTTOM,
FACE_RIGHT,
FACE_TOP,
FACE_FRONT,
N_FACES
};
/* Map face widgets to CSS classes */
static struct {
GtkWidget *face;
const char *css_class;
} faces[N_FACES] = {
[FACE_BACK] = { NULL, "back", },
[FACE_LEFT] = { NULL, "left", },
[FACE_RIGHT] = { NULL, "right", },
[FACE_TOP] = { NULL, "top", },
[FACE_BOTTOM] = { NULL, "bottom", },
[FACE_FRONT] = { NULL, "front", },
};
static GtkWidget *
create_faces (void)
{
GtkWidget *fixed = gtk_fixed_new ();
int face_size = 200;
float w, h, d, p;
gtk_widget_set_overflow (fixed, GTK_OVERFLOW_VISIBLE);
w = (float) face_size / 2.f;
h = (float) face_size / 2.f;
d = (float) face_size / 2.f;
p = face_size * 3.f;
for (int i = 0; i < N_FACES; i++)
{
GskTransform *transform = NULL;
/* Add a face */
faces[i].face = gtk_frame_new (NULL);
gtk_widget_set_size_request (faces[i].face, face_size, face_size);
gtk_style_context_add_class (gtk_widget_get_style_context (faces[i].face), faces[i].css_class);
gtk_container_add (GTK_CONTAINER (fixed), faces[i].face);
/* Set up the transformation for each face */
transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (w, h));
transform = gsk_transform_perspective (transform, p);
transform = gsk_transform_rotate_3d (transform, -30.f, graphene_vec3_x_axis ());
transform = gsk_transform_rotate_3d (transform, 135.f, graphene_vec3_y_axis ());
transform = gsk_transform_translate_3d (transform, &GRAPHENE_POINT3D_INIT (0, 0, -face_size / 6.f));
switch (i)
{
case FACE_FRONT:
transform = gsk_transform_rotate_3d (transform, 0.f, graphene_vec3_y_axis ());
break;
case FACE_BACK:
transform = gsk_transform_rotate_3d (transform, -180.f, graphene_vec3_y_axis ());
break;
case FACE_RIGHT:
transform = gsk_transform_rotate_3d (transform, 90.f, graphene_vec3_y_axis ());
break;
case FACE_LEFT:
transform = gsk_transform_rotate_3d (transform, -90.f, graphene_vec3_y_axis ());
break;
case FACE_TOP:
transform = gsk_transform_rotate_3d (transform, 90.f, graphene_vec3_x_axis ());
break;
case FACE_BOTTOM:
transform = gsk_transform_rotate_3d (transform, -90.f, graphene_vec3_x_axis ());
break;
default:
break;
}
transform = gsk_transform_translate_3d (transform, &GRAPHENE_POINT3D_INIT (0, 0, d));
transform = gsk_transform_translate_3d (transform, &GRAPHENE_POINT3D_INIT (-w, -h, 0));
gtk_fixed_set_child_transform (GTK_FIXED (fixed), faces[i].face, transform);
gsk_transform_unref (transform);
}
return fixed;
}
static GtkWidget *demo_window = NULL;
static GtkCssProvider *provider = NULL;
static void
close_window (GtkWidget *widget)
{
/* Reset the state */
for (int i = 0; i < N_FACES; i++)
faces[i].face = NULL;
gtk_style_context_remove_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider));
provider = NULL;
demo_window = NULL;
}
static GtkWidget *
create_demo_window (GtkWidget *do_widget)
{
GtkWidget *window, *sw, *fixed, *cube;
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);
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (window), sw);
fixed = gtk_fixed_new ();
gtk_container_add (GTK_CONTAINER (sw), fixed);
gtk_widget_set_halign (GTK_WIDGET (fixed), GTK_ALIGN_CENTER);
gtk_widget_set_valign (GTK_WIDGET (fixed), GTK_ALIGN_CENTER);
cube = create_faces ();
gtk_container_add (GTK_CONTAINER (fixed), cube);
gtk_widget_set_overflow (fixed, GTK_OVERFLOW_VISIBLE);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/fixed/fixed.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
800);
g_object_unref (provider);
return window;
}
GtkWidget*
do_fixed (GtkWidget *do_widget)
{
if (demo_window == NULL)
demo_window = create_demo_window (do_widget);
if (!gtk_widget_get_visible (demo_window))
gtk_widget_show (demo_window);
else
gtk_widget_destroy (demo_window);
return demo_window;
}
-29
View File
@@ -1,29 +0,0 @@
frame.front {
border: 2px solid white;
background-color: rgba(228, 0, 0, 0.8);
}
frame.back {
border: 2px solid white;
background-color: rgba(228, 0, 0, 0.8);
}
frame.right {
border: 2px solid white;
background-color: rgba(127, 231, 25, 0.8);
}
frame.left {
border: 2px solid white;
background-color: rgba(127, 231, 25, 0.8);
}
frame.top {
border: 2px solid white;
background-color: rgba(114, 159, 207, 0.8);
}
frame.bottom {
border: 2px solid white;
background-color: rgba(114, 159, 207, 0.8);
}
+53 -37
View File
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.1 -->
<interface>
<requires lib="gtk+" version="3.12"/>
<object class="GtkWindow" id="window">
@@ -6,16 +7,19 @@
<property name="default-height">500</property>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="visible">1</property>
<property name="show-title-buttons">1</property>
<property name="title">Font Explorer</property>
<child>
<object class="GtkButton" id="reset">
<property name="visible">1</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
<property name="tooltip-text">Reset</property>
<signal name="clicked" handler="reset" swapped="no"/>
<child>
<object class="GtkImage">
<property name="visible">1</property>
<property name="icon-name">view-refresh-symbolic</property>
</object>
</child>
@@ -25,23 +29,27 @@
</child>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<child>
<object class="GtkScrolledWindow">
<property name="visible">1</property>
<property name="can-focus">1</property>
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkViewport">
<property name="visible">1</property>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="margin">10</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkFontButton" id="font">
<property name="visible">1</property>
<property name="can-focus">1</property>
<property name="receives-default">1</property>
<property name="font">Sans 12</property>
<property name="level">family|style|size|variations|features</property>
<signal name="font-set" handler="font_changed" swapped="no"/>
</object>
</child>
@@ -49,10 +57,11 @@
<object class="GtkExpander">
<child type="label">
<object class="GtkLabel">
<property name="visible">1</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Font Features</property>
<attributes>
<attribute name="weight" value="bold"></attribute>
<attribute name="weight" value="bold"/>
</attributes>
</object>
</child>
@@ -78,17 +87,20 @@
</child>
<child>
<object class="GtkExpander">
<property name="visible">1</property>
<child type="label">
<object class="GtkLabel" id="variations_heading">
<property name="visible">1</property>
<property name="label" translatable="yes">Font Variations</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold"></attribute>
<attribute name="weight" value="bold"/>
</attributes>
</object>
</child>
<child>
<object class="GtkGrid" id="variations_grid">
<property name="visible">1</property>
<property name="column-spacing">10</property>
<property name="row-spacing">10</property>
</object>
@@ -106,6 +118,7 @@
</child>
<child>
<object class="GtkBox">
<property name="visible">1</property>
<property name="orientation">vertical</property>
<property name="hexpand">1</property>
<property name="vexpand">1</property>
@@ -113,41 +126,42 @@
<property name="spacing">20</property>
<child>
<object class="GtkStack" id="stack">
<property name="visible">1</property>
<child>
<object class="GtkStackPage">
<property name="name">label</property>
<property name="child">
<object class="GtkLabel" id="label">
<property name="wrap">1</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="valign">start</property>
<property name="selectable">1</property>
</object>
</property>
<object class="GtkLabel" id="label">
<property name="visible">1</property>
<property name="wrap">1</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="valign">start</property>
<property name="selectable">1</property>
</object>
<packing>
<property name="name">label</property>
</packing>
</child>
<child>
<object class="GtkStackPage">
<property name="name">entry</property>
<property name="child">
<object class="GtkEntry" id="entry">
<property name="text">Grumpy wizards make toxic brew for the evil Queen and Jack. A quick movement of the enemy will jeopardize six gunboats. The job of waxing linoleum frequently peeves chintzy kids. My girl wove six dozen plaid jackets before she quit. Twelve ziggurats quickly jumped a finch box.
<object class="GtkEntry" id="entry">
<property name="visible">1</property>
<property name="text">Grumpy wizards make toxic brew for the evil Queen and Jack. A quick movement of the enemy will jeopardize six gunboats. The job of waxing linoleum frequently peeves chintzy kids. My girl wove six dozen plaid jackets before she quit. Twelve ziggurats quickly jumped a finch box.
Разъяренный чтец эгоистично бьёт пятью жердями шустрого фехтовальщика. Наш банк вчера же выплатил Ф.Я. Эйхгольду комиссию за ценные вещи. Эх, чужак, общий съём цен шляп (юфть) – вдрызг! В чащах юга жил бы цитрус? Да, но фальшивый экземпляр!
Τάχιστη αλώπηξ βαφής ψημένη γη, δρασκελίζει υπέρ νωθρού κυνός</property>
<signal name="activate" handler="stop_edit"/>
<property name="valign">start</property>
<property name="width-chars">50</property>
</object>
</property>
<signal name="key-press-event" handler="entry_key_press"/>
<signal name="activate" handler="stop_edit"/>
<property name="valign">start</property>
<property name="width-chars">50</property>
</object>
<packing>
<property name="name">entry</property>
</packing>
</child>
</object>
</child>
<child>
<object class="GtkLabel" id="settings">
<property name="visible">1</property>
<property name="wrap">1</property>
<property name="xalign">0</property>
<property name="valign">end</property>
@@ -162,20 +176,22 @@
</child>
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">10</property>
<child>
<object class="GtkLabel" id="description">
<property name="wrap">1</property>
<property name="xalign">0</property>
<property name="valign">end</property>
<property name="width-chars">50</property>
<property name="max-width-chars">50</property>
<property name="hexpand">1</property>
<style>
<class name="monospace"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="description">
<property name="visible">1</property>
<property name="wrap">1</property>
<property name="xalign">0</property>
<property name="valign">end</property>
<property name="width-chars">50</property>
<property name="max-width-chars">50</property>
<property name="hexpand">1</property>
<style>
<class name="monospace"/>
</style>
</object>
</child>
<child>
<object class="GtkToggleButton" id="edit_toggle">
<property name="icon-name">document-edit-symbolic</property>
+12 -21
View File
@@ -305,7 +305,7 @@ update_display (void)
char *font_desc;
char *features;
text = gtk_editable_get_text (GTK_EDITABLE (entry));
text = gtk_entry_get_text (GTK_ENTRY (entry));
if (gtk_label_get_selection_bounds (GTK_LABEL (label), &ins, &bound))
{
@@ -495,11 +495,7 @@ update_script_combo (void)
gboolean have_active = FALSE;
lang = gtk_font_chooser_get_language (GTK_FONT_CHOOSER (font));
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
active = hb_ot_tag_from_language (hb_language_from_string (lang, -1));
G_GNUC_END_IGNORE_DEPRECATIONS
g_free (lang);
store = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
@@ -732,7 +728,7 @@ adjustment_changed (GtkAdjustment *adjustment,
char *str;
str = g_strdup_printf ("%g", gtk_adjustment_get_value (adjustment));
gtk_editable_set_text (GTK_EDITABLE (entry), str);
gtk_entry_set_text (GTK_ENTRY (entry), str);
g_free (str);
update_display ();
@@ -745,7 +741,7 @@ entry_activated (GtkEntry *entry,
gdouble value;
gchar *err = NULL;
value = g_strtod (gtk_editable_get_text (GTK_EDITABLE (entry)), &err);
value = g_strtod (gtk_entry_get_text (entry), &err);
if (err != NULL)
gtk_adjustment_set_value (adjustment, value);
}
@@ -825,7 +821,7 @@ add_axis (FT_Var_Axis *ax, FT_Fixed value, int i)
gtk_grid_attach (GTK_GRID (variations_grid), axis_scale, 1, i, 1, 1);
axis_entry = gtk_entry_new ();
gtk_widget_set_valign (axis_entry, GTK_ALIGN_BASELINE);
gtk_editable_set_width_chars (GTK_EDITABLE (axis_entry), 4);
gtk_entry_set_width_chars (GTK_ENTRY (axis_entry), 4);
gtk_grid_attach (GTK_GRID (variations_grid), axis_entry, 2, i, 1, 1);
axis = g_new (Axis, 1);
@@ -1643,7 +1639,7 @@ static char *text;
static void
switch_to_entry (void)
{
text = g_strdup (gtk_editable_get_text (GTK_EDITABLE (entry)));
text = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
gtk_stack_set_visible_child_name (GTK_STACK (stack), "entry");
gtk_widget_grab_focus (entry);
}
@@ -1673,15 +1669,15 @@ stop_edit (void)
}
static gboolean
entry_key_press (GtkEventController *controller,
guint keyval,
guint keycode,
GdkModifierType modifiers,
GtkEntry *entry)
entry_key_press (GtkEntry *entry, GdkEventKey *event)
{
guint keyval;
gdk_event_get_keyval ((GdkEvent *)event, &keyval);
if (keyval == GDK_KEY_Escape)
{
gtk_editable_set_text (GTK_EDITABLE (entry), text);
gtk_entry_set_text (GTK_ENTRY (entry), text);
stop_edit ();
return GDK_EVENT_STOP;
}
@@ -1698,7 +1694,6 @@ do_font_features (GtkWidget *do_widget)
{
GtkBuilder *builder;
GtkWidget *feature_list;
GtkEventController *controller;
builder = gtk_builder_new_from_resource ("/font_features/font-features.ui");
@@ -1708,6 +1703,7 @@ do_font_features (GtkWidget *do_widget)
gtk_builder_add_callback_symbol (builder, "reset", reset_features);
gtk_builder_add_callback_symbol (builder, "stop_edit", G_CALLBACK (stop_edit));
gtk_builder_add_callback_symbol (builder, "toggle_edit", G_CALLBACK (toggle_edit));
gtk_builder_add_callback_symbol (builder, "entry_key_press", G_CALLBACK (entry_key_press));
gtk_builder_connect_signals (builder, NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
@@ -1722,11 +1718,6 @@ do_font_features (GtkWidget *do_widget)
entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry"));
edit_toggle = GTK_WIDGET (gtk_builder_get_object (builder, "edit_toggle"));
controller = gtk_event_controller_key_new ();
g_object_set_data_full (G_OBJECT (entry), "controller", controller, g_object_unref);
g_signal_connect (controller, "key-pressed", G_CALLBACK (entry_key_press), entry);
gtk_widget_add_controller (entry, controller);
add_check_group (feature_list, _("Kerning"), (const char *[]){ "kern", NULL });
add_check_group (feature_list, _("Ligatures"), (const char *[]){ "liga",
"dlig",
+14 -14
View File
@@ -68,7 +68,8 @@ plane_snapshot (GtkWidget *widget,
height = gtk_widget_get_allocated_height (widget);
cr = gtk_snapshot_append_cairo (snapshot,
&GRAPHENE_RECT_INIT (0, 0, width, height));
&GRAPHENE_RECT_INIT (0, 0, width, height),
"FontPlane");
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_rectangle (cr, 0, 0, width, height);
@@ -207,27 +208,23 @@ plane_drag_gesture_end (GtkGestureDrag *gesture,
static void
gtk_font_plane_init (GtkFontPlane *plane)
{
GtkGesture *gesture;
gtk_widget_set_has_surface (GTK_WIDGET (plane), FALSE);
gtk_widget_set_has_window (GTK_WIDGET (plane), FALSE);
gtk_widget_set_can_focus (GTK_WIDGET (plane), TRUE);
gesture = gtk_gesture_drag_new ();
g_signal_connect (gesture, "drag-begin",
plane->drag_gesture = gtk_gesture_drag_new (GTK_WIDGET (plane));
g_signal_connect (plane->drag_gesture, "drag-begin",
G_CALLBACK (plane_drag_gesture_begin), plane);
g_signal_connect (gesture, "drag-update",
g_signal_connect (plane->drag_gesture, "drag-update",
G_CALLBACK (plane_drag_gesture_update), plane);
g_signal_connect (gesture, "drag-end",
g_signal_connect (plane->drag_gesture, "drag-end",
G_CALLBACK (plane_drag_gesture_end), plane);
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), 0);
gtk_widget_add_controller (GTK_WIDGET (plane), GTK_EVENT_CONTROLLER (gesture));
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (plane->drag_gesture), 0);
gesture = gtk_gesture_long_press_new ();
g_signal_connect (gesture, "pressed",
plane->long_press_gesture = gtk_gesture_long_press_new (GTK_WIDGET (plane));
g_signal_connect (plane->long_press_gesture, "pressed",
G_CALLBACK (hold_action), plane);
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture),
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (plane->long_press_gesture),
TRUE);
gtk_widget_add_controller (GTK_WIDGET (plane), GTK_EVENT_CONTROLLER (gesture));
}
static void
@@ -238,6 +235,9 @@ plane_finalize (GObject *object)
g_clear_object (&plane->weight_adj);
g_clear_object (&plane->width_adj);
g_clear_object (&plane->drag_gesture);
g_clear_object (&plane->long_press_gesture);
G_OBJECT_CLASS (gtk_font_plane_parent_class)->finalize (object);
}
+1
View File
@@ -41,6 +41,7 @@ struct _GtkFontPlane
GtkAdjustment *width_adj;
GtkGesture *drag_gesture;
GtkGesture *long_press_gesture;
};
struct _GtkFontPlaneClass
+2 -2
View File
@@ -1,8 +1,8 @@
/* Foreign drawing
*
* Many applications can't use GTK widgets, for a variety of reasons,
* 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
* 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.
+1 -1
View File
@@ -33,7 +33,7 @@ demos = []
for demo_file in in_files:
filename = demo_file[demo_file.rfind('/')+1:]
demo_name = filename.replace(".c", "")
with open(demo_file, 'r', encoding='utf-8') as f:
with open(demo_file, 'r') as f:
title = f.readline().replace("/*", "").strip()
+10 -10
View File
@@ -157,15 +157,16 @@ do_gestures (GtkWidget *do_widget)
NULL, NULL);
/* Swipe */
gesture = gtk_gesture_swipe_new ();
gesture = gtk_gesture_swipe_new (drawing_area);
g_signal_connect (gesture, "swipe",
G_CALLBACK (swipe_gesture_swept), drawing_area);
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture),
GTK_PHASE_BUBBLE);
gtk_widget_add_controller (drawing_area, GTK_EVENT_CONTROLLER (gesture));
g_object_weak_ref (G_OBJECT (drawing_area), (GWeakNotify) g_object_unref, gesture);
/* 3fg swipe for touchpads */
gesture = g_object_new (GTK_TYPE_GESTURE_SWIPE,
"widget", drawing_area,
"n-points", 3,
NULL);
g_signal_connect (gesture, "begin",
@@ -174,34 +175,33 @@ do_gestures (GtkWidget *do_widget)
G_CALLBACK (swipe_gesture_swept), drawing_area);
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture),
GTK_PHASE_BUBBLE);
gtk_widget_add_controller (drawing_area, GTK_EVENT_CONTROLLER (gesture));
g_object_weak_ref (G_OBJECT (drawing_area), (GWeakNotify) g_object_unref, gesture);
/* Long press */
gesture = gtk_gesture_long_press_new ();
gesture = gtk_gesture_long_press_new (drawing_area);
g_signal_connect (gesture, "pressed",
G_CALLBACK (long_press_gesture_pressed), drawing_area);
g_signal_connect (gesture, "end",
G_CALLBACK (long_press_gesture_end), drawing_area);
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture),
GTK_PHASE_BUBBLE);
gtk_widget_add_controller (drawing_area, GTK_EVENT_CONTROLLER (gesture));
g_object_weak_ref (G_OBJECT (drawing_area), (GWeakNotify) g_object_unref, gesture);
/* Rotate */
rotate = gesture = gtk_gesture_rotate_new ();
rotate = gesture = gtk_gesture_rotate_new (drawing_area);
g_signal_connect (gesture, "angle-changed",
G_CALLBACK (rotation_angle_changed), drawing_area);
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture),
GTK_PHASE_BUBBLE);
gtk_widget_add_controller (drawing_area, GTK_EVENT_CONTROLLER (gesture));
g_object_weak_ref (G_OBJECT (drawing_area), (GWeakNotify) g_object_unref, gesture);
/* Zoom */
zoom = gesture = gtk_gesture_zoom_new ();
zoom = gesture = gtk_gesture_zoom_new (drawing_area);
g_signal_connect (gesture, "scale-changed",
G_CALLBACK (zoom_scale_changed), drawing_area);
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture),
GTK_PHASE_BUBBLE);
gtk_widget_add_controller (drawing_area, GTK_EVENT_CONTROLLER (gesture));
g_object_weak_ref (G_OBJECT (drawing_area), (GWeakNotify) g_object_unref, gesture);
}
if (!gtk_widget_get_visible (window))
Binary file not shown.
@@ -1,8 +1,8 @@
[Desktop Entry]
Name=GTK Demo
Comment=GTK code examples and demonstrations
Name=GTK+ Demo
Comment=GTK+ code examples and demonstrations
Exec=gtk4-demo
Icon=org.gtk.Demo4
Icon=gtk4-demo
Terminal=false
Type=Application
StartupNotify=true
+124 -262
View File
@@ -24,18 +24,13 @@ typedef struct _GtkFishbowlChild GtkFishbowlChild;
struct _GtkFishbowlPrivate
{
GtkFishCreationFunc creation_func;
GList *children;
guint count;
gint64 last_frame_time;
gint64 update_delay;
guint tick_id;
double framerate;
int last_benchmark_change;
guint benchmark : 1;
guint use_icons: 1;
};
struct _GtkFishbowlChild
@@ -50,25 +45,18 @@ struct _GtkFishbowlChild
enum {
PROP_0,
PROP_ANIMATING,
PROP_BENCHMARK,
PROP_COUNT,
PROP_FRAMERATE,
PROP_UPDATE_DELAY,
NUM_PROPERTIES
};
static GParamSpec *props[NUM_PROPERTIES] = { NULL, };
G_DEFINE_TYPE_WITH_PRIVATE (GtkFishbowl, gtk_fishbowl, GTK_TYPE_WIDGET)
G_DEFINE_TYPE_WITH_PRIVATE (GtkFishbowl, gtk_fishbowl, GTK_TYPE_CONTAINER)
static void
gtk_fishbowl_init (GtkFishbowl *fishbowl)
{
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
gtk_widget_set_has_surface (GTK_WIDGET (fishbowl), FALSE);
priv->update_delay = G_USEC_PER_SEC;
gtk_widget_set_has_window (GTK_WIDGET (fishbowl), FALSE);
}
/**
@@ -84,6 +72,15 @@ gtk_fishbowl_new (void)
return g_object_new (GTK_TYPE_FISHBOWL, NULL);
}
void
gtk_fishbowl_set_use_icons (GtkFishbowl *fishbowl,
gboolean use_icons)
{
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
priv->use_icons = use_icons;
}
static void
gtk_fishbowl_measure (GtkWidget *widget,
GtkOrientation orientation,
@@ -128,10 +125,10 @@ gtk_fishbowl_measure (GtkWidget *widget,
}
static void
gtk_fishbowl_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
gtk_fishbowl_size_allocate (GtkWidget *widget,
const GtkAllocation *allocation,
int baseline,
GtkAllocation *out_clip)
{
GtkFishbowl *fishbowl = GTK_FISHBOWL (widget);
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
@@ -142,18 +139,20 @@ gtk_fishbowl_size_allocate (GtkWidget *widget,
for (children = priv->children; children; children = children->next)
{
GtkAllocation child_clip;
child = children->data;
if (!gtk_widget_get_visible (child->widget))
continue;
gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
child_allocation.x = round (child->x * (width - child_requisition.width));
child_allocation.y = round (child->y * (height - child_requisition.height));
child_allocation.x = allocation->x + round (child->x * (allocation->width - child_requisition.width));
child_allocation.y = allocation->y + round (child->y * (allocation->height - child_requisition.height));
child_allocation.width = child_requisition.width;
child_allocation.height = child_requisition.height;
gtk_widget_size_allocate (child->widget, &child_allocation, -1);
gtk_widget_size_allocate (child->widget, &child_allocation, -1, &child_clip);
}
}
@@ -165,9 +164,10 @@ new_speed (void)
}
static void
gtk_fishbowl_add (GtkFishbowl *fishbowl,
GtkWidget *widget)
gtk_fishbowl_add (GtkContainer *container,
GtkWidget *widget)
{
GtkFishbowl *fishbowl = GTK_FISHBOWL (container);
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
GtkFishbowlChild *child_info;
@@ -189,12 +189,13 @@ gtk_fishbowl_add (GtkFishbowl *fishbowl,
}
static void
gtk_fishbowl_remove (GtkFishbowl *fishbowl,
GtkWidget *widget)
gtk_fishbowl_remove (GtkContainer *container,
GtkWidget *widget)
{
GtkFishbowl *fishbowl = GTK_FISHBOWL (container);
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
GtkFishbowlChild *child;
GtkWidget *widget_bowl = GTK_WIDGET (fishbowl);
GtkWidget *widget_container = GTK_WIDGET (container);
GList *children;
for (children = priv->children; children; children = children->next)
@@ -211,8 +212,8 @@ gtk_fishbowl_remove (GtkFishbowl *fishbowl,
g_list_free (children);
g_free (child);
if (was_visible && gtk_widget_get_visible (widget_bowl))
gtk_widget_queue_resize (widget_bowl);
if (was_visible && gtk_widget_get_visible (widget_container))
gtk_widget_queue_resize (widget_container);
priv->count--;
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_COUNT]);
@@ -221,6 +222,26 @@ gtk_fishbowl_remove (GtkFishbowl *fishbowl,
}
}
static void
gtk_fishbowl_forall (GtkContainer *container,
GtkCallback callback,
gpointer callback_data)
{
GtkFishbowl *fishbowl = GTK_FISHBOWL (container);
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
GtkFishbowlChild *child;
GList *children;
children = priv->children;
while (children)
{
child = children->data;
children = children->next;
(* callback) (child->widget, callback_data);
}
}
static void
gtk_fishbowl_dispose (GObject *object)
{
@@ -246,18 +267,10 @@ gtk_fishbowl_set_property (GObject *object,
gtk_fishbowl_set_animating (fishbowl, g_value_get_boolean (value));
break;
case PROP_BENCHMARK:
gtk_fishbowl_set_benchmark (fishbowl, g_value_get_boolean (value));
break;
case PROP_COUNT:
gtk_fishbowl_set_count (fishbowl, g_value_get_uint (value));
break;
case PROP_UPDATE_DELAY:
gtk_fishbowl_set_update_delay (fishbowl, g_value_get_int64 (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -278,22 +291,10 @@ gtk_fishbowl_get_property (GObject *object,
g_value_set_boolean (value, gtk_fishbowl_get_animating (fishbowl));
break;
case PROP_BENCHMARK:
g_value_set_boolean (value, gtk_fishbowl_get_benchmark (fishbowl));
break;
case PROP_COUNT:
g_value_set_uint (value, gtk_fishbowl_get_count (fishbowl));
break;
case PROP_FRAMERATE:
g_value_set_double (value, gtk_fishbowl_get_framerate (fishbowl));
break;
case PROP_UPDATE_DELAY:
g_value_set_int64 (value, gtk_fishbowl_get_update_delay (fishbowl));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -305,6 +306,7 @@ gtk_fishbowl_class_init (GtkFishbowlClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
object_class->dispose = gtk_fishbowl_dispose;
object_class->set_property = gtk_fishbowl_set_property;
@@ -313,6 +315,10 @@ gtk_fishbowl_class_init (GtkFishbowlClass *klass)
widget_class->measure = gtk_fishbowl_measure;
widget_class->size_allocate = gtk_fishbowl_size_allocate;
container_class->add = gtk_fishbowl_add;
container_class->remove = gtk_fishbowl_remove;
container_class->forall = gtk_fishbowl_forall;
props[PROP_ANIMATING] =
g_param_spec_boolean ("animating",
"animating",
@@ -320,36 +326,13 @@ gtk_fishbowl_class_init (GtkFishbowlClass *klass)
FALSE,
G_PARAM_READWRITE);
props[PROP_BENCHMARK] =
g_param_spec_boolean ("benchmark",
"Benchmark",
"Adapt the count property to hit the maximum framerate",
FALSE,
G_PARAM_READWRITE);
props[PROP_COUNT] =
g_param_spec_uint ("count",
"Count",
"Number of widgets",
0, G_MAXUINT,
0,
G_PARAM_READWRITE);
props[PROP_FRAMERATE] =
g_param_spec_double ("framerate",
"Framerate",
"Framerate of this widget in frames per second",
0, G_MAXDOUBLE,
0,
G_PARAM_READABLE);
props[PROP_UPDATE_DELAY] =
g_param_spec_int64 ("update-delay",
"Update delay",
"Number of usecs between updates",
0, G_MAXINT64,
G_USEC_PER_SEC,
G_PARAM_READWRITE);
G_PARAM_READABLE);
g_object_class_install_properties (object_class, NUM_PROPERTIES, props);
}
@@ -362,58 +345,96 @@ gtk_fishbowl_get_count (GtkFishbowl *fishbowl)
return priv->count;
}
char **icon_names = NULL;
gsize n_icon_names = 0;
static void
init_icon_names (GtkIconTheme *theme)
{
GPtrArray *icons;
GList *l, *icon_list;
if (icon_names)
return;
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 *
get_random_icon_name (GtkIconTheme *theme)
{
init_icon_names (theme);
return icon_names[g_random_int_range(0, n_icon_names)];
}
static GType
get_random_widget_type ()
{
GType types[] = {
GTK_TYPE_SWITCH,
GTK_TYPE_BUTTON,
GTK_TYPE_ENTRY,
GTK_TYPE_SPIN_BUTTON,
GTK_TYPE_FONT_BUTTON,
GTK_TYPE_SCROLLBAR,
GTK_TYPE_SCALE,
GTK_TYPE_LEVEL_BAR,
GTK_TYPE_PROGRESS_BAR,
GTK_TYPE_RADIO_BUTTON,
GTK_TYPE_CHECK_BUTTON
};
return types[g_random_int_range (0, G_N_ELEMENTS (types))];
}
void
gtk_fishbowl_set_count (GtkFishbowl *fishbowl,
guint count)
{
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
if (priv->count == count)
return;
g_object_freeze_notify (G_OBJECT (fishbowl));
while (priv->count > count)
{
gtk_fishbowl_remove (fishbowl, gtk_widget_get_first_child (GTK_WIDGET (fishbowl)));
gtk_container_remove (GTK_CONTAINER (fishbowl),
((GtkFishbowlChild *) priv->children->data)->widget);
}
while (priv->count < count)
{
GtkWidget *new_widget;
new_widget = priv->creation_func ();
if (priv->use_icons)
{
new_widget = gtk_image_new_from_icon_name (get_random_icon_name (gtk_icon_theme_get_default ()));
gtk_image_set_icon_size (GTK_IMAGE (new_widget), GTK_ICON_SIZE_LARGE);
}
else
new_widget = g_object_new (get_random_widget_type (), NULL);
gtk_fishbowl_add (fishbowl, new_widget);
gtk_container_add (GTK_CONTAINER (fishbowl), new_widget);
}
g_object_thaw_notify (G_OBJECT (fishbowl));
}
gboolean
gtk_fishbowl_get_benchmark (GtkFishbowl *fishbowl)
{
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
return priv->benchmark;
}
void
gtk_fishbowl_set_benchmark (GtkFishbowl *fishbowl,
gboolean benchmark)
{
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
if (priv->benchmark == benchmark)
return;
priv->benchmark = benchmark;
if (!benchmark)
priv->last_benchmark_change = 0;
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_BENCHMARK]);
}
gboolean
gtk_fishbowl_get_animating (GtkFishbowl *fishbowl)
{
@@ -422,111 +443,6 @@ gtk_fishbowl_get_animating (GtkFishbowl *fishbowl)
return priv->tick_id != 0;
}
static gint64
guess_refresh_interval (GdkFrameClock *frame_clock)
{
gint64 interval;
gint64 i;
interval = G_MAXINT64;
for (i = gdk_frame_clock_get_history_start (frame_clock);
i < gdk_frame_clock_get_frame_counter (frame_clock);
i++)
{
GdkFrameTimings *t, *before;
gint64 ts, before_ts;
t = gdk_frame_clock_get_timings (frame_clock, i);
before = gdk_frame_clock_get_timings (frame_clock, i - 1);
if (t == NULL || before == NULL)
continue;
ts = gdk_frame_timings_get_frame_time (t);
before_ts = gdk_frame_timings_get_frame_time (before);
if (ts == 0 || before_ts == 0)
continue;
interval = MIN (interval, ts - before_ts);
}
if (interval == G_MAXINT64)
return 0;
return interval;
}
static void
gtk_fishbowl_do_update (GtkFishbowl *fishbowl)
{
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
GdkFrameClock *frame_clock;
GdkFrameTimings *start, *end;
gint64 start_counter, end_counter;
gint64 n_frames, expected_frames;
gint64 start_timestamp, end_timestamp;
gint64 interval;
frame_clock = gtk_widget_get_frame_clock (GTK_WIDGET (fishbowl));
if (frame_clock == NULL)
return;
start_counter = gdk_frame_clock_get_history_start (frame_clock);
end_counter = gdk_frame_clock_get_frame_counter (frame_clock);
start = gdk_frame_clock_get_timings (frame_clock, start_counter);
for (end = gdk_frame_clock_get_timings (frame_clock, end_counter);
end_counter > start_counter && end != NULL && !gdk_frame_timings_get_complete (end);
end = gdk_frame_clock_get_timings (frame_clock, end_counter))
end_counter--;
if (end_counter - start_counter < 4)
return;
start_timestamp = gdk_frame_timings_get_presentation_time (start);
end_timestamp = gdk_frame_timings_get_presentation_time (end);
if (start_timestamp == 0 || end_timestamp == 0)
{
start_timestamp = gdk_frame_timings_get_frame_time (start);
end_timestamp = gdk_frame_timings_get_frame_time (end);
}
n_frames = end_counter - start_counter;
priv->framerate = ((double) n_frames) * G_USEC_PER_SEC / (end_timestamp - start_timestamp);
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_FRAMERATE]);
if (!priv->benchmark)
return;
interval = gdk_frame_timings_get_refresh_interval (end);
if (interval == 0)
{
interval = guess_refresh_interval (frame_clock);
if (interval == 0)
return;
}
expected_frames = round ((double) (end_timestamp - start_timestamp) / interval);
if (n_frames >= expected_frames)
{
if (priv->last_benchmark_change > 0)
priv->last_benchmark_change *= 2;
else
priv->last_benchmark_change = 1;
}
else if (n_frames + 1 < expected_frames)
{
if (priv->last_benchmark_change < 0)
priv->last_benchmark_change--;
else
priv->last_benchmark_change = -1;
}
else
{
priv->last_benchmark_change = 0;
}
gtk_fishbowl_set_count (fishbowl, MAX (1, (int) priv->count + priv->last_benchmark_change));
}
static gboolean
gtk_fishbowl_tick (GtkWidget *widget,
GdkFrameClock *frame_clock,
@@ -537,11 +453,9 @@ gtk_fishbowl_tick (GtkWidget *widget,
GtkFishbowlChild *child;
GList *l;
gint64 frame_time, elapsed;
gboolean do_update;
frame_time = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
elapsed = frame_time - priv->last_frame_time;
do_update = frame_time / priv->update_delay != priv->last_frame_time / priv->update_delay;
priv->last_frame_time = frame_time;
/* last frame was 0, so we're just starting to animate */
@@ -580,9 +494,6 @@ gtk_fishbowl_tick (GtkWidget *widget,
gtk_widget_queue_allocate (widget);
if (do_update)
gtk_fishbowl_do_update (fishbowl);
return G_SOURCE_CONTINUE;
}
@@ -607,57 +518,8 @@ gtk_fishbowl_set_animating (GtkFishbowl *fishbowl,
priv->last_frame_time = 0;
gtk_widget_remove_tick_callback (GTK_WIDGET (fishbowl), priv->tick_id);
priv->tick_id = 0;
priv->framerate = 0;
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_FRAMERATE]);
}
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_ANIMATING]);
}
double
gtk_fishbowl_get_framerate (GtkFishbowl *fishbowl)
{
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
return priv->framerate;
}
gint64
gtk_fishbowl_get_update_delay (GtkFishbowl *fishbowl)
{
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
return priv->update_delay;
}
void
gtk_fishbowl_set_update_delay (GtkFishbowl *fishbowl,
gint64 update_delay)
{
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
if (priv->update_delay == update_delay)
return;
priv->update_delay = update_delay;
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_UPDATE_DELAY]);
}
void
gtk_fishbowl_set_creation_func (GtkFishbowl *fishbowl,
GtkFishCreationFunc creation_func)
{
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
g_object_freeze_notify (G_OBJECT (fishbowl));
gtk_fishbowl_set_count (fishbowl, 0);
priv->last_benchmark_change = 0;
priv->creation_func = creation_func;
gtk_fishbowl_set_count (fishbowl, 1);
g_object_thaw_notify (G_OBJECT (fishbowl));
}
+5 -13
View File
@@ -32,37 +32,29 @@ G_BEGIN_DECLS
typedef struct _GtkFishbowl GtkFishbowl;
typedef struct _GtkFishbowlClass GtkFishbowlClass;
typedef GtkWidget * (* GtkFishCreationFunc) (void);
struct _GtkFishbowl
{
GtkWidget parent;
GtkContainer container;
};
struct _GtkFishbowlClass
{
GtkWidgetClass parent_class;
GtkContainerClass parent_class;
};
GType gtk_fishbowl_get_type (void) G_GNUC_CONST;
GtkWidget* gtk_fishbowl_new (void);
void gtk_fishbowl_set_use_icons (GtkFishbowl *fishbowl,
gboolean use_icons);
guint gtk_fishbowl_get_count (GtkFishbowl *fishbowl);
void gtk_fishbowl_set_count (GtkFishbowl *fishbowl,
guint count);
gboolean gtk_fishbowl_get_animating (GtkFishbowl *fishbowl);
void gtk_fishbowl_set_animating (GtkFishbowl *fishbowl,
gboolean animating);
gboolean gtk_fishbowl_get_benchmark (GtkFishbowl *fishbowl);
void gtk_fishbowl_set_benchmark (GtkFishbowl *fishbowl,
gboolean animating);
double gtk_fishbowl_get_framerate (GtkFishbowl *fishbowl);
gint64 gtk_fishbowl_get_update_delay (GtkFishbowl *fishbowl);
void gtk_fishbowl_set_update_delay (GtkFishbowl *fishbowl,
gint64 update_delay);
void gtk_fishbowl_set_creation_func (GtkFishbowl *fishbowl,
GtkFishCreationFunc creation_func);
G_END_DECLS
-960
View File
@@ -1,960 +0,0 @@
/* The rendering code in here is taken from es2gears, which has the
* following copyright notice:
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Ported to GLES2.
* Kristian Høgsberg <krh@bitplanet.net>
* May 3, 2010
*
* Improve GLES2 port:
* * Refactor gear drawing.
* * Use correct normals for surfaces.
* * Improve shader.
* * Use perspective projection transformation.
* * Add FPS count.
* * Add comments.
* Alexandros Frantzis <alexandros.frantzis@linaro.org>
* Jul 13, 2010
*/
#include "config.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <epoxy/gl.h>
#include "gtkgears.h"
#define STRIPS_PER_TOOTH 7
#define VERTICES_PER_TOOTH 34
#define GEAR_VERTEX_STRIDE 6
#ifndef HAVE_SINCOS
static void
sincos (double x, double *_sin, double *_cos)
{
*_sin = sin (x);
*_cos = cos (x);
}
#endif
/**
* Struct describing the vertices in triangle strip
*/
struct vertex_strip {
/** The first vertex in the strip */
GLint first;
/** The number of consecutive vertices in the strip after the first */
GLint count;
};
/* Each vertex consist of GEAR_VERTEX_STRIDE GLfloat attributes */
typedef GLfloat GearVertex[GEAR_VERTEX_STRIDE];
/**
* Struct representing a gear.
*/
struct gear {
/** The array of vertices comprising the gear */
GearVertex *vertices;
/** The number of vertices comprising the gear */
int nvertices;
/** The array of triangle strips comprising the gear */
struct vertex_strip *strips;
/** The number of triangle strips comprising the gear */
int nstrips;
};
typedef struct {
/* The view rotation [x, y, z] */
GLfloat view_rot[GTK_GEARS_N_AXIS];
/* The Vertex Array Object */
GLuint vao;
/* The shader program */
GLuint program;
/* The gears */
struct gear *gear1;
struct gear *gear2;
struct gear *gear3;
/** The Vertex Buffer Object holding the vertices in the graphics card */
GLuint gear_vbo[3];
/** The location of the shader uniforms */
GLuint ModelViewProjectionMatrix_location;
GLuint NormalMatrix_location;
GLuint LightSourcePosition_location;
GLuint MaterialColor_location;
/* The current gear rotation angle */
GLfloat angle;
/* The projection matrix */
GLfloat ProjectionMatrix[16];
/* The direction of the directional light for the scene */
GLfloat LightSourcePosition[4];
gint64 first_frame_time;
guint tick;
GtkLabel *fps_label;
} GtkGearsPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GtkGears, gtk_gears, GTK_TYPE_GL_AREA)
static gboolean gtk_gears_render (GtkGLArea *area,
GdkGLContext *context);
static void gtk_gears_reshape (GtkGLArea *area,
int width,
int height);
static void gtk_gears_realize (GtkWidget *widget);
static void gtk_gears_unrealize (GtkWidget *widget);
static gboolean gtk_gears_tick (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer user_data);
static void destroy_gear (struct gear *g);
GtkWidget *
gtk_gears_new (void)
{
return g_object_new (gtk_gears_get_type (),
"has-depth-buffer", TRUE,
NULL);
}
static void
gtk_gears_init (GtkGears *gears)
{
GtkGearsPrivate *priv = gtk_gears_get_instance_private (gears);
priv->view_rot[GTK_GEARS_X_AXIS] = 20.0;
priv->view_rot[GTK_GEARS_Y_AXIS] = 30.0;
priv->view_rot[GTK_GEARS_Z_AXIS] = 20.0;
priv->LightSourcePosition[0] = 5.0;
priv->LightSourcePosition[1] = 5.0;
priv->LightSourcePosition[2] = 10.0;
priv->LightSourcePosition[3] = 1.0;
priv->tick = gtk_widget_add_tick_callback (GTK_WIDGET (gears), gtk_gears_tick, gears, NULL);
}
static void
gtk_gears_finalize (GObject *obj)
{
GtkGears *gears = GTK_GEARS (obj);
GtkGearsPrivate *priv = gtk_gears_get_instance_private (gears);
gtk_widget_remove_tick_callback (GTK_WIDGET (gears), priv->tick);
g_clear_object (&priv->fps_label);
g_clear_pointer (&priv->gear1, destroy_gear);
g_clear_pointer (&priv->gear2, destroy_gear);
g_clear_pointer (&priv->gear3, destroy_gear);
G_OBJECT_CLASS (gtk_gears_parent_class)->finalize (obj);
}
static void
gtk_gears_class_init (GtkGearsClass *klass)
{
GTK_GL_AREA_CLASS (klass)->render = gtk_gears_render;
GTK_GL_AREA_CLASS (klass)->resize = gtk_gears_reshape;
GTK_WIDGET_CLASS (klass)->realize = gtk_gears_realize;
GTK_WIDGET_CLASS (klass)->unrealize = gtk_gears_unrealize;
G_OBJECT_CLASS (klass)->finalize = gtk_gears_finalize;
}
/*
* Fills a gear vertex.
*
* @param v the vertex to fill
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coortinate
* @param n pointer to the normal table
*
* @return the operation error code
*/
static GearVertex *
vert (GearVertex *v,
GLfloat x,
GLfloat y,
GLfloat z,
GLfloat n[3])
{
v[0][0] = x;
v[0][1] = y;
v[0][2] = z;
v[0][3] = n[0];
v[0][4] = n[1];
v[0][5] = n[2];
return v + 1;
}
static void
destroy_gear (struct gear *g)
{
g_free (g->strips);
g_free (g);
}
/**
* Create a gear wheel.
*
* @param inner_radius radius of hole at center
* @param outer_radius radius at center of teeth
* @param width width of gear
* @param teeth number of teeth
* @param tooth_depth depth of tooth
*
* @return pointer to the constructed struct gear
*/
static struct gear *
create_gear (GLfloat inner_radius,
GLfloat outer_radius,
GLfloat width,
GLint teeth,
GLfloat tooth_depth)
{
GLfloat r0, r1, r2;
GLfloat da;
GearVertex *v;
struct gear *gear;
double s[5], c[5];
GLfloat normal[3];
int cur_strip = 0;
int i;
/* Allocate memory for the gear */
gear = g_malloc (sizeof *gear);
/* Calculate the radii used in the gear */
r0 = inner_radius;
r1 = outer_radius - tooth_depth / 2.0;
r2 = outer_radius + tooth_depth / 2.0;
da = 2.0 * M_PI / teeth / 4.0;
/* Allocate memory for the triangle strip information */
gear->nstrips = STRIPS_PER_TOOTH * teeth;
gear->strips = g_malloc0_n (gear->nstrips, sizeof (*gear->strips));
/* Allocate memory for the vertices */
gear->vertices = g_malloc0_n (VERTICES_PER_TOOTH * teeth, sizeof(*gear->vertices));
v = gear->vertices;
for (i = 0; i < teeth; i++) {
/* A set of macros for making the creation of the gears easier */
#define GEAR_POINT(p, r, da) do { p.x = (r) * c[(da)]; p.y = (r) * s[(da)]; } while(0)
#define SET_NORMAL(x, y, z) do { \
normal[0] = (x); normal[1] = (y); normal[2] = (z); \
} while(0)
#define GEAR_VERT(v, point, sign) vert((v), p[(point)].x, p[(point)].y, (sign) * width * 0.5, normal)
#define START_STRIP do { \
gear->strips[cur_strip].first = v - gear->vertices; \
} while(0);
#define END_STRIP do { \
int _tmp = (v - gear->vertices); \
gear->strips[cur_strip].count = _tmp - gear->strips[cur_strip].first; \
cur_strip++; \
} while (0)
#define QUAD_WITH_NORMAL(p1, p2) do { \
SET_NORMAL((p[(p1)].y - p[(p2)].y), -(p[(p1)].x - p[(p2)].x), 0); \
v = GEAR_VERT(v, (p1), -1); \
v = GEAR_VERT(v, (p1), 1); \
v = GEAR_VERT(v, (p2), -1); \
v = GEAR_VERT(v, (p2), 1); \
} while(0)
struct point {
GLfloat x;
GLfloat y;
};
/* Create the 7 points (only x,y coords) used to draw a tooth */
struct point p[7];
/* Calculate needed sin/cos for varius angles */
sincos(i * 2.0 * G_PI / teeth + da * 0, &s[0], &c[0]);
sincos(i * 2.0 * M_PI / teeth + da * 1, &s[1], &c[1]);
sincos(i * 2.0 * M_PI / teeth + da * 2, &s[2], &c[2]);
sincos(i * 2.0 * M_PI / teeth + da * 3, &s[3], &c[3]);
sincos(i * 2.0 * M_PI / teeth + da * 4, &s[4], &c[4]);
GEAR_POINT(p[0], r2, 1);
GEAR_POINT(p[1], r2, 2);
GEAR_POINT(p[2], r1, 0);
GEAR_POINT(p[3], r1, 3);
GEAR_POINT(p[4], r0, 0);
GEAR_POINT(p[5], r1, 4);
GEAR_POINT(p[6], r0, 4);
/* Front face */
START_STRIP;
SET_NORMAL(0, 0, 1.0);
v = GEAR_VERT(v, 0, +1);
v = GEAR_VERT(v, 1, +1);
v = GEAR_VERT(v, 2, +1);
v = GEAR_VERT(v, 3, +1);
v = GEAR_VERT(v, 4, +1);
v = GEAR_VERT(v, 5, +1);
v = GEAR_VERT(v, 6, +1);
END_STRIP;
/* Inner face */
START_STRIP;
QUAD_WITH_NORMAL(4, 6);
END_STRIP;
/* Back face */
START_STRIP;
SET_NORMAL(0, 0, -1.0);
v = GEAR_VERT(v, 6, -1);
v = GEAR_VERT(v, 5, -1);
v = GEAR_VERT(v, 4, -1);
v = GEAR_VERT(v, 3, -1);
v = GEAR_VERT(v, 2, -1);
v = GEAR_VERT(v, 1, -1);
v = GEAR_VERT(v, 0, -1);
END_STRIP;
/* Outer face */
START_STRIP;
QUAD_WITH_NORMAL(0, 2);
END_STRIP;
START_STRIP;
QUAD_WITH_NORMAL(1, 0);
END_STRIP;
START_STRIP;
QUAD_WITH_NORMAL(3, 1);
END_STRIP;
START_STRIP;
QUAD_WITH_NORMAL(5, 3);
END_STRIP;
}
gear->nvertices = (v - gear->vertices);
return gear;
}
/**
* Multiplies two 4x4 matrices.
*
* The result is stored in matrix m.
*
* @param m the first matrix to multiply
* @param n the second matrix to multiply
*/
static void
multiply (GLfloat *m, const GLfloat *n)
{
GLfloat tmp[16];
const GLfloat *row, *column;
div_t d;
int i, j;
for (i = 0; i < 16; i++) {
tmp[i] = 0;
d = div(i, 4);
row = n + d.quot * 4;
column = m + d.rem;
for (j = 0; j < 4; j++)
tmp[i] += row[j] * column[j * 4];
}
memcpy(m, &tmp, sizeof tmp);
}
/**
* Rotates a 4x4 matrix.
*
* @param[in,out] m the matrix to rotate
* @param angle the angle to rotate
* @param x the x component of the direction to rotate to
* @param y the y component of the direction to rotate to
* @param z the z component of the direction to rotate to
*/
static void
rotate(GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
{
double s = sin (angle);
double c = cos (angle);
GLfloat r[16] = {
x * x * (1 - c) + c, y * x * (1 - c) + z * s, x * z * (1 - c) - y * s, 0,
x * y * (1 - c) - z * s, y * y * (1 - c) + c, y * z * (1 - c) + x * s, 0,
x * z * (1 - c) + y * s, y * z * (1 - c) - x * s, z * z * (1 - c) + c, 0,
0, 0, 0, 1
};
multiply(m, r);
}
/**
* Translates a 4x4 matrix.
*
* @param[in,out] m the matrix to translate
* @param x the x component of the direction to translate to
* @param y the y component of the direction to translate to
* @param z the z component of the direction to translate to
*/
static void
translate(GLfloat *m, GLfloat x, GLfloat y, GLfloat z)
{
GLfloat t[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 };
multiply(m, t);
}
/**
* Creates an identity 4x4 matrix.
*
* @param m the matrix make an identity matrix
*/
static void
identity(GLfloat *m)
{
GLfloat t[16] = {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
};
memcpy(m, t, sizeof(t));
}
/**
* Transposes a 4x4 matrix.
*
* @param m the matrix to transpose
*/
static void
transpose(GLfloat *m)
{
GLfloat t[16] = {
m[0], m[4], m[8], m[12],
m[1], m[5], m[9], m[13],
m[2], m[6], m[10], m[14],
m[3], m[7], m[11], m[15]};
memcpy(m, t, sizeof(t));
}
/**
* Inverts a 4x4 matrix.
*
* This function can currently handle only pure translation-rotation matrices.
* Read http://www.gamedev.net/community/forums/topic.asp?topic_id=425118
* for an explanation.
*/
static void
invert(GLfloat *m)
{
GLfloat t[16];
identity(t);
// Extract and invert the translation part 't'. The inverse of a
// translation matrix can be calculated by negating the translation
// coordinates.
t[12] = -m[12]; t[13] = -m[13]; t[14] = -m[14];
// Invert the rotation part 'r'. The inverse of a rotation matrix is
// equal to its transpose.
m[12] = m[13] = m[14] = 0;
transpose(m);
// inv(m) = inv(r) * inv(t)
multiply(m, t);
}
/**
* Calculate a perspective projection transformation.
*
* @param m the matrix to save the transformation in
* @param fovy the field of view in the y direction
* @param aspect the view aspect ratio
* @param zNear the near clipping plane
* @param zFar the far clipping plane
*/
void perspective(GLfloat *m, GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
{
GLfloat tmp[16];
double sine, cosine, cotangent, deltaZ;
GLfloat radians = fovy / 2 * M_PI / 180;
identity(tmp);
deltaZ = zFar - zNear;
sincos(radians, &sine, &cosine);
if ((deltaZ == 0) || (sine == 0) || (aspect == 0))
return;
cotangent = cosine / sine;
tmp[0] = cotangent / aspect;
tmp[5] = cotangent;
tmp[10] = -(zFar + zNear) / deltaZ;
tmp[11] = -1;
tmp[14] = -2 * zNear * zFar / deltaZ;
tmp[15] = 0;
memcpy(m, tmp, sizeof(tmp));
}
/**
* Draws a gear.
*
* @param gear the gear to draw
* @param transform the current transformation matrix
* @param x the x position to draw the gear at
* @param y the y position to draw the gear at
* @param angle the rotation angle of the gear
* @param color the color of the gear
*/
static void
draw_gear(GtkGears *self,
struct gear *gear,
GLuint gear_vbo,
GLfloat *transform,
GLfloat x,
GLfloat y,
GLfloat angle,
const GLfloat color[4])
{
GtkGearsPrivate *priv = gtk_gears_get_instance_private (self);
GLfloat model_view[16];
GLfloat normal_matrix[16];
GLfloat model_view_projection[16];
int n;
/* Translate and rotate the gear */
memcpy(model_view, transform, sizeof (model_view));
translate(model_view, x, y, 0);
rotate(model_view, 2 * G_PI * angle / 360.0, 0, 0, 1);
/* Create and set the ModelViewProjectionMatrix */
memcpy(model_view_projection, priv->ProjectionMatrix, sizeof(model_view_projection));
multiply(model_view_projection, model_view);
glUniformMatrix4fv(priv->ModelViewProjectionMatrix_location, 1, GL_FALSE,
model_view_projection);
/*
* Create and set the NormalMatrix. It's the inverse transpose of the
* ModelView matrix.
*/
memcpy(normal_matrix, model_view, sizeof (normal_matrix));
invert(normal_matrix);
transpose(normal_matrix);
glUniformMatrix4fv(priv->NormalMatrix_location, 1, GL_FALSE, normal_matrix);
/* Set the gear color */
glUniform4fv(priv->MaterialColor_location, 1, color);
/* Set the vertex buffer object to use */
glBindBuffer(GL_ARRAY_BUFFER, gear_vbo);
/* Set up the position of the attributes in the vertex buffer object */
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), NULL);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLfloat *) 0 + 3);
/* Enable the attributes */
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
/* Draw the triangle strips that comprise the gear */
for (n = 0; n < gear->nstrips; n++) {
glDrawArrays(GL_TRIANGLE_STRIP, gear->strips[n].first, gear->strips[n].count);
}
/* Disable the attributes */
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
}
/* new window size or exposure */
static void
gtk_gears_reshape (GtkGLArea *area, int width, int height)
{
GtkGearsPrivate *priv = gtk_gears_get_instance_private ((GtkGears *) area);
/* Update the projection matrix */
perspective (priv->ProjectionMatrix, 60.0, width / (float)height, 1.0, 1024.0);
/* Set the viewport */
glViewport (0, 0, (GLint) width, (GLint) height);
}
static gboolean
gtk_gears_render (GtkGLArea *area,
GdkGLContext *context)
{
static const GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
static const GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
static const GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
GtkGears *self = GTK_GEARS (area);
GtkGearsPrivate *priv = gtk_gears_get_instance_private (self);
GLfloat transform[16];
identity (transform);
glClearColor (0.0, 0.0, 0.0, 0.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* Translate and rotate the view */
translate (transform, 0, 0, -20);
rotate (transform, 2 * G_PI * priv->view_rot[0] / 360.0, 1, 0, 0);
rotate (transform, 2 * G_PI * priv->view_rot[1] / 360.0, 0, 1, 0);
rotate (transform, 2 * G_PI * priv->view_rot[2] / 360.0, 0, 0, 1);
/* Draw the gears */
draw_gear (self, priv->gear1, priv->gear_vbo[0], transform, -3.0, -2.0, priv->angle, red);
draw_gear (self, priv->gear2, priv->gear_vbo[1], transform, 3.1, -2.0, -2 * priv->angle - 9.0, green);
draw_gear (self, priv->gear3, priv->gear_vbo[2], transform, -3.1, 4.2, -2 * priv->angle - 25.0, blue);
return TRUE;
}
static const char vertex_shader_gl[] =
"#version 150\n"
"\n"
"in vec3 position;\n"
"in vec3 normal;\n"
"\n"
"uniform mat4 ModelViewProjectionMatrix;\n"
"uniform mat4 NormalMatrix;\n"
"uniform vec4 LightSourcePosition;\n"
"uniform vec4 MaterialColor;\n"
"\n"
"smooth out vec4 Color;\n"
"\n"
"void main(void)\n"
"{\n"
" // Transform the normal to eye coordinates\n"
" vec3 N = normalize(vec3(NormalMatrix * vec4(normal, 1.0)));\n"
"\n"
" // The LightSourcePosition is actually its direction for directional light\n"
" vec3 L = normalize(LightSourcePosition.xyz);\n"
"\n"
" // Multiply the diffuse value by the vertex color (which is fixed in this case)\n"
" // to get the actual color that we will use to draw this vertex with\n"
" float diffuse = max(dot(N, L), 0.0);\n"
" Color = diffuse * MaterialColor;\n"
"\n"
" // Transform the position to clip coordinates\n"
" gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0);\n"
"}";
static const char fragment_shader_gl[] =
"#version 150\n"
"\n"
"smooth in vec4 Color;\n"
"\n"
"void main(void)\n"
"{\n"
" gl_FragColor = Color;\n"
"}";
static const char vertex_shader_gles[] =
"attribute vec3 position;\n"
"attribute vec3 normal;\n"
"\n"
"uniform mat4 ModelViewProjectionMatrix;\n"
"uniform mat4 NormalMatrix;\n"
"uniform vec4 LightSourcePosition;\n"
"uniform vec4 MaterialColor;\n"
"\n"
"varying vec4 Color;\n"
"\n"
"void main(void)\n"
"{\n"
" // Transform the normal to eye coordinates\n"
" vec3 N = normalize(vec3(NormalMatrix * vec4(normal, 1.0)));\n"
"\n"
" // The LightSourcePosition is actually its direction for directional light\n"
" vec3 L = normalize(LightSourcePosition.xyz);\n"
"\n"
" // Multiply the diffuse value by the vertex color (which is fixed in this case)\n"
" // to get the actual color that we will use to draw this vertex with\n"
" float diffuse = max(dot(N, L), 0.0);\n"
" Color = diffuse * MaterialColor;\n"
"\n"
" // Transform the position to clip coordinates\n"
" gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0);\n"
"}";
static const char fragment_shader_gles[] =
"precision mediump float;\n"
"varying vec4 Color;\n"
"\n"
"void main(void)\n"
"{\n"
" gl_FragColor = Color;\n"
"}";
static void
gtk_gears_realize (GtkWidget *widget)
{
GtkGLArea *glarea = GTK_GL_AREA (widget);
GtkGears *gears = GTK_GEARS (widget);
GtkGearsPrivate *priv = gtk_gears_get_instance_private (gears);
GdkGLContext *context;
GLuint vao, v, f, program;
const char *p;
char msg[512];
GTK_WIDGET_CLASS (gtk_gears_parent_class)->realize (widget);
gtk_gl_area_make_current (glarea);
if (gtk_gl_area_get_error (glarea) != NULL)
return;
context = gtk_gl_area_get_context (glarea);
glEnable (GL_CULL_FACE);
glEnable (GL_DEPTH_TEST);
/* Create the VAO */
glGenVertexArrays (1, &vao);
glBindVertexArray (vao);
priv->vao = vao;
/* Compile the vertex shader */
if (gdk_gl_context_get_use_es (context))
p = vertex_shader_gles;
else
p = vertex_shader_gl;
v = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(v, 1, &p, NULL);
glCompileShader(v);
glGetShaderInfoLog(v, sizeof msg, NULL, msg);
g_print ("vertex shader info: %s\n", msg);
/* Compile the fragment shader */
if (gdk_gl_context_get_use_es (context))
p = fragment_shader_gles;
else
p = fragment_shader_gl;
f = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(f, 1, &p, NULL);
glCompileShader(f);
glGetShaderInfoLog(f, sizeof msg, NULL, msg);
g_print ("fragment shader info: %s\n", msg);
/* Create and link the shader program */
program = glCreateProgram();
glAttachShader(program, v);
glAttachShader(program, f);
glBindAttribLocation(program, 0, "position");
glBindAttribLocation(program, 1, "normal");
glLinkProgram(program);
glGetProgramInfoLog(program, sizeof msg, NULL, msg);
g_print ("program info: %s\n", msg);
glDeleteShader (v);
glDeleteShader (f);
/* Enable the shaders */
glUseProgram(program);
priv->program = program;
/* Get the locations of the uniforms so we can access them */
priv->ModelViewProjectionMatrix_location = glGetUniformLocation(program, "ModelViewProjectionMatrix");
priv->NormalMatrix_location = glGetUniformLocation(program, "NormalMatrix");
priv->LightSourcePosition_location = glGetUniformLocation(program, "LightSourcePosition");
priv->MaterialColor_location = glGetUniformLocation(program, "MaterialColor");
/* Set the LightSourcePosition uniform which is constant throught the program */
glUniform4fv(priv->LightSourcePosition_location, 1, priv->LightSourcePosition);
/* make the gears */
priv->gear1 = create_gear(1.0, 4.0, 1.0, 20, 0.7);
/* Store the vertices in a vertex buffer object (VBO) */
glGenBuffers (1, &(priv->gear_vbo[0]));
glBindBuffer (GL_ARRAY_BUFFER, priv->gear_vbo[0]);
glBufferData (GL_ARRAY_BUFFER,
priv->gear1->nvertices * sizeof(GearVertex),
priv->gear1->vertices,
GL_STATIC_DRAW);
priv->gear2 = create_gear(0.5, 2.0, 2.0, 10, 0.7);
glGenBuffers (1, &(priv->gear_vbo[1]));
glBindBuffer (GL_ARRAY_BUFFER, priv->gear_vbo[1]);
glBufferData (GL_ARRAY_BUFFER,
priv->gear2->nvertices * sizeof(GearVertex),
priv->gear2->vertices,
GL_STATIC_DRAW);
priv->gear3 = create_gear(1.3, 2.0, 0.5, 10, 0.7);
glGenBuffers (1, &(priv->gear_vbo[2]));
glBindBuffer (GL_ARRAY_BUFFER, priv->gear_vbo[2]);
glBufferData (GL_ARRAY_BUFFER,
priv->gear3->nvertices * sizeof(GearVertex),
priv->gear3->vertices,
GL_STATIC_DRAW);
}
static void
gtk_gears_unrealize (GtkWidget *widget)
{
GtkGLArea *glarea = GTK_GL_AREA (widget);
GtkGearsPrivate *priv = gtk_gears_get_instance_private ((GtkGears *) widget);
gtk_gl_area_make_current (glarea);
if (gtk_gl_area_get_error (glarea) != NULL)
return;
/* Release the resources associated with OpenGL */
if (priv->gear_vbo[0] != 0)
glDeleteBuffers (1, &(priv->gear_vbo[0]));
if (priv->gear_vbo[1] != 0)
glDeleteBuffers (1, &(priv->gear_vbo[1]));
if (priv->gear_vbo[2] != 0)
glDeleteBuffers (1, &(priv->gear_vbo[2]));
if (priv->vao != 0)
glDeleteVertexArrays (1, &priv->vao);
if (priv->program != 0)
glDeleteProgram (priv->program);
priv->ModelViewProjectionMatrix_location = 0;
priv->NormalMatrix_location = 0;
priv->LightSourcePosition_location = 0;
priv->MaterialColor_location = 0;
GTK_WIDGET_CLASS (gtk_gears_parent_class)->unrealize (widget);
}
static gboolean
gtk_gears_tick (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer user_data)
{
GtkGears *gears = GTK_GEARS (widget);
GtkGearsPrivate *priv = gtk_gears_get_instance_private (gears);
GdkFrameTimings *timings, *previous_timings;
gint64 previous_frame_time = 0;
gint64 frame_time;
gint64 history_start, history_len;
gint64 frame;
char *s;
frame = gdk_frame_clock_get_frame_counter (frame_clock);
frame_time = gdk_frame_clock_get_frame_time (frame_clock);
if (priv->first_frame_time == 0)
{
/* No need for changes on first frame */
priv->first_frame_time = frame_time;
if (priv->fps_label)
gtk_label_set_label (priv->fps_label, "FPS: ---");
return G_SOURCE_CONTINUE;
}
/* glxgears advances 70 degrees per second, so do the same */
priv->angle = fmod ((frame_time - priv->first_frame_time) / (double)G_USEC_PER_SEC * 70.0, 360.0);
gtk_widget_queue_draw (widget);
history_start = gdk_frame_clock_get_history_start (frame_clock);
if (priv->fps_label && frame % 60 == 0)
{
history_len = frame - history_start;
if (history_len > 0)
{
previous_timings = gdk_frame_clock_get_timings (frame_clock, frame - history_len);
previous_frame_time = gdk_frame_timings_get_frame_time (previous_timings);
s = g_strdup_printf ("FPS: %-4.1f", (G_USEC_PER_SEC * history_len) / (double)(frame_time - previous_frame_time));
gtk_label_set_label (priv->fps_label, s);
g_free (s);
}
}
timings = gdk_frame_clock_get_current_timings (frame_clock);
previous_timings = gdk_frame_clock_get_timings (frame_clock,
gdk_frame_timings_get_frame_counter (timings) - 1);
if (previous_timings != NULL)
previous_frame_time = gdk_frame_timings_get_frame_time (previous_timings);
return G_SOURCE_CONTINUE;
}
void
gtk_gears_set_axis (GtkGears *gears, int axis, double value)
{
GtkGearsPrivate *priv = gtk_gears_get_instance_private (gears);
if (axis < 0 || axis >= GTK_GEARS_N_AXIS)
return;
priv->view_rot[axis] = value;
gtk_widget_queue_draw (GTK_WIDGET (gears));
}
double
gtk_gears_get_axis (GtkGears *gears, int axis)
{
GtkGearsPrivate *priv = gtk_gears_get_instance_private (gears);
if (axis < 0 || axis >= GTK_GEARS_N_AXIS)
return 0.0;
return priv->view_rot[axis];
}
void
gtk_gears_set_fps_label (GtkGears *gears, GtkLabel *label)
{
GtkGearsPrivate *priv = gtk_gears_get_instance_private (gears);
if (label)
g_object_ref (label);
g_clear_object (&priv->fps_label);
priv->fps_label = label;
}
-48
View File
@@ -1,48 +0,0 @@
#ifndef __GTK_GEARS_H__
#define __GTK_GEARS_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
enum {
GTK_GEARS_X_AXIS,
GTK_GEARS_Y_AXIS,
GTK_GEARS_Z_AXIS,
GTK_GEARS_N_AXIS
};
#define GTK_TYPE_GEARS (gtk_gears_get_type ())
#define GTK_GEARS(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
GTK_TYPE_GEARS, \
GtkGears))
#define GTK_IS_GEARS(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
GTK_TYPE_GEARS))
typedef struct _GtkGears GtkGears;
typedef struct _GtkGearsClass GtkGearsClass;
struct _GtkGears {
GtkGLArea parent;
};
struct _GtkGearsClass {
GtkGLAreaClass parent_class;
};
GType gtk_gears_get_type (void) G_GNUC_CONST;
GtkWidget *gtk_gears_new (void);
void gtk_gears_set_axis (GtkGears *gears,
int axis,
double value);
double gtk_gears_get_axis (GtkGears *gears,
int axis);
void gtk_gears_set_fps_label (GtkGears *gears,
GtkLabel *label);
G_END_DECLS
#endif /* __GTK_GEARS_H__ */
+42 -39
View File
@@ -105,14 +105,14 @@ follow_if_link (GtkWidget *text_view,
/* Links can be activated by pressing Enter.
*/
static gboolean
key_pressed (GtkEventController *controller,
guint keyval,
guint keycode,
GdkModifierType modifiers,
GtkWidget *text_view)
key_press_event (GtkWidget *text_view,
GdkEventKey *event)
{
GtkTextIter iter;
GtkTextBuffer *buffer;
guint keyval;
gdk_event_get_keyval ((GdkEvent *)event, &keyval);
switch (keyval)
{
@@ -128,49 +128,62 @@ key_pressed (GtkEventController *controller,
break;
}
return GDK_EVENT_PROPAGATE;
return FALSE;
}
static void set_cursor_if_appropriate (GtkTextView *text_view,
gint x,
gint y);
static void
released_cb (GtkGestureMultiPress *gesture,
guint n_press,
gdouble x,
gdouble y,
GtkWidget *text_view)
/* Links can also be activated by clicking or tapping.
*/
static gboolean
event_cb (GtkWidget *text_view,
GdkEvent *ev)
{
GtkTextIter start, end, iter;
GtkTextBuffer *buffer;
int tx, ty;
gdouble ex, ey;
int x, y;
GdkEventType type;
if (gtk_gesture_single_get_button (GTK_GESTURE_SINGLE (gesture)) > 1)
return;
type = gdk_event_get_event_type (ev);
gdk_event_get_coords (ev, &ex, &ey);
gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (text_view),
GTK_TEXT_WINDOW_WIDGET,
x, y, &tx, &ty);
ex, ey, &x, &y);
if (type == GDK_BUTTON_RELEASE)
{
guint button;
gdk_event_get_button (ev, &button);
if (button != GDK_BUTTON_PRIMARY)
return FALSE;
}
else if (type == GDK_MOTION_NOTIFY)
{
set_cursor_if_appropriate (GTK_TEXT_VIEW (text_view), x, y);
return FALSE;
}
else if (type == GDK_TOUCH_END)
{
}
else
return FALSE;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
/* we shouldn't follow a link if the user has selected something */
gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end))
return;
return FALSE;
if (gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view), &iter, x, y))
follow_if_link (text_view, &iter);
}
static void
motion_cb (GtkEventControllerMotion *controller,
gdouble x,
gdouble y,
GtkTextView *text_view)
{
set_cursor_if_appropriate (text_view, x, y);
return TRUE;
}
static gboolean hovering_over_link = FALSE;
@@ -228,7 +241,6 @@ do_hypertext (GtkWidget *do_widget)
GtkWidget *view;
GtkWidget *sw;
GtkTextBuffer *buffer;
GtkEventController *controller;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Hypertext");
@@ -243,19 +255,10 @@ do_hypertext (GtkWidget *do_widget)
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD);
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 20);
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (view), 20);
controller = gtk_event_controller_key_new ();
g_signal_connect (controller, "key-pressed", G_CALLBACK (key_pressed), view);
gtk_widget_add_controller (view, controller);
controller = GTK_EVENT_CONTROLLER (gtk_gesture_multi_press_new ());
g_signal_connect (controller, "released",
G_CALLBACK (released_cb), view);
gtk_widget_add_controller (view, controller);
controller = gtk_event_controller_motion_new ();
g_signal_connect (controller, "motion",
G_CALLBACK (motion_cb), view);
gtk_widget_add_controller (view, controller);
g_signal_connect (view, "key-press-event",
G_CALLBACK (key_press_event), NULL);
g_signal_connect (view, "event",
G_CALLBACK (event_cb), NULL);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 330 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 422 B

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