Compare commits
7 Commits
constraint
...
wip/matthi
Author | SHA1 | Date | |
---|---|---|---|
|
083167c3c1 | ||
|
1a7faa5e6b | ||
|
2a4070fa8a | ||
|
aede999309 | ||
|
4ccfe57dc1 | ||
|
5746309b63 | ||
|
4f4e0120ae |
1
.gitignore
vendored
@@ -1 +0,0 @@
|
||||
/subprojects/*/
|
120
.gitlab-ci.yml
@@ -1,120 +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:v6
|
||||
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"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*.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:v6
|
||||
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
|
@@ -1,85 +0,0 @@
|
||||
FROM fedora:30
|
||||
|
||||
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 \
|
||||
dbus-daemon \
|
||||
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-jinja2 \
|
||||
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.1
|
||||
|
||||
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
|
@@ -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}
|
@@ -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}))
|
@@ -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)
|
@@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
TAG="registry.gitlab.gnome.org/gnome/gtk/master:v6"
|
||||
|
||||
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
|
@@ -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
|
@@ -1,54 +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 \
|
||||
-Dx11-backend=false \
|
||||
-Dwayland-backend=false \
|
||||
-Dwin32-backend=true \
|
||||
-Dvulkan=no \
|
||||
--werror \
|
||||
_build
|
||||
unset CCACHE_DISABLE
|
||||
|
||||
ninja -C _build
|
||||
ccache --show-stats
|
@@ -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
|
||||
*written in C* 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
|
||||
-->
|
@@ -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
|
||||
-->
|
270
CONTRIBUTING.md
@@ -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`.
|
||||
|
903
NEWS.pre-2.0
@@ -1,903 +0,0 @@
|
||||
Overview of Changes in GTK+ 2.0.0
|
||||
=================================
|
||||
|
||||
* GtkTreeView fixes [Jonathan Blandford, Kristian Rietveld, Darin Adler]
|
||||
* Build fixes [Anders Carlsson, Tor Lillqvist, Manish Singh]
|
||||
* Bug fixes. [Thomas Leonard, Owen Taylor]
|
||||
|
||||
Overview of Changes in GTK+ 2.0.0 rc1
|
||||
=====================================
|
||||
|
||||
* GtkTreeView fixes [Kristian Rietveld, Jonathan Blandford, Richard Hult]
|
||||
* Text widget fixes [Havoc Pennington]
|
||||
* Efficiency fixes when using Xft [Owen Taylor]
|
||||
* Key handling fixes and other fixes for Win32 [Hans Breuer, Tor Lillqvist]
|
||||
* Try to fix key handling without XKEYBOARD extension [Owen]
|
||||
* Documentation fixes and improvements
|
||||
[Matthias Clasen, Alexey Malyshev, Akira Tagoh, Vitaly Tishkov]
|
||||
* Widget drawing improvements [Soeren Sandmann]
|
||||
* Allow cycling between multiple menu bars with <Control>Tab [Owen]
|
||||
* Try to build libraries with only shared library dependencies on Xft to
|
||||
deal with transition to Xft2 [Owen]
|
||||
* Portability fixes [Owen, Miroslaw Dobrzanski-Neumann]
|
||||
* Don't use red as the default cursor color [Owen]
|
||||
* Bug fixes, bug fixes, bug fixes.
|
||||
|
||||
Other contributors: Darin Adler, Jacob Berkman, Kevin Breit, Hans Breuer,
|
||||
Anders Carlsson, Damon Chaplin, Finlay Dobbie, Jody Goldberg,
|
||||
Andreas J. Guelzow, Scott Guilbeaux, Vlad Harchev, James Henstridge,
|
||||
Tim Janik, Satyajit Kanungo, Charles Kerr, Sergey Kuzminov, Miles Lane,
|
||||
Alexander Larsson, Paolo Maggi, Skip Montaro, Jan Mynarik, Sven Neumann,
|
||||
Padraig O'Briain, Narayani Pattipati, Mark Patton, Havoc Pennington,
|
||||
Ettore Perazzoli, Guillermo S. Romero, Manish Singh, Morten Welinder
|
||||
|
||||
Overview of Changes in GTK+ 1.3.15
|
||||
==================================
|
||||
|
||||
* New stock and improved icon images
|
||||
[Tuomas Kuosmanen, Jakub Steiner, Anders Carlsson]
|
||||
* Widget drawing improvements for check and radio buttons,
|
||||
spinbuttons [Soeren Sandmann]
|
||||
* Clean up module search path algorithm, use GTK_PATH [Owen Taylor]
|
||||
* Add GtkSetting for font name. [Richard Hestilow]
|
||||
* Much improved key matching code, accelerators work independent
|
||||
of group [Owen]
|
||||
* Make mnemonics work for embedded GtkPlug widgets [Owen]
|
||||
* Keynav improvements for GtkTreeView [Kristian Rietveld]
|
||||
* Fix gtk_tree_view_scroll_to_cell() [Jonathan Blandford]
|
||||
* Rename gtk_tree_view_get_iter_root() and gtk_tree_path_new_root()
|
||||
to gtk_tree_view_get_iter_first() and gtk_tree_path_new_first(),
|
||||
add compatibility macros.
|
||||
* GtkTreeView bug fixes [Kristian, Anders, Damon Chaplin]
|
||||
* GtkTextView bug fixes [Havoc Pennington]
|
||||
* Pad class structures for future binary compatibility [Owen]
|
||||
* Tutorial improvements [Sven Neumann, Matthias Clasen]
|
||||
* Fixes for MULTIPLE selection target [Gregory Merchan, Owen]
|
||||
* Fix problems with initial widget size [Owen]
|
||||
* AIX compilation fixes [Miroslaw Dobrzanski-Neumann]
|
||||
* Win32 fixes [Hans Breuer, Tor Lillqvist]
|
||||
* Miscellaneous bug fixes
|
||||
|
||||
Other contributors: David L. Cooper, Eric Fischer, Jody Goldberg,
|
||||
Satajyit Kanungo, Thomas Leonard, Mark Patton, Manish Singh,
|
||||
Nicolas Setton
|
||||
|
||||
Overview of Changes in GTK+ 1.3.14
|
||||
==================================
|
||||
|
||||
* Keyboard focus improvements [Owen Taylor]
|
||||
* Code cleanup [Matthias Clasen, Manish Singh, Darin Adler]
|
||||
* Fix accidentally exported variables [Mark McLoughlin]
|
||||
* GtkTreeView fixes [Jonathan Blandford, Kristian Rietveld, John Harper, Darin]
|
||||
* Default to yellow tooltips [Owen]
|
||||
* RC file fixes for reloading, priorities [Owen, Matthias]
|
||||
* GtkMenu behavior improvements and bug fixes [Owen, Arnaud Charlet]
|
||||
* GtkTextView fixes [Havoc Pennington, Daniel Elstner, Dennis Bjorklund]
|
||||
* Improve keynav for paned widgets, tooltips, spin buttons, notebooks,
|
||||
scrolled windows [Soeren Sandmann, Padraig, Owen]
|
||||
* Add Emacs/Default key themes [Owen]
|
||||
* Win32 fixes [Hans Breuer, Tor Lillqvist]
|
||||
* Ethiopic input methods [Daniel Yacob]
|
||||
* Opaque paned window resizing [Soeren]
|
||||
* Tweak table expansion behavior [Tim Janik]
|
||||
* Fix GtkCalendar focus drawing [Bill Haneman]
|
||||
* Allow themeable cursor thickness [Bill]
|
||||
* Start of fixing of tutorial for GTK+-2.0 [Matthias]
|
||||
* Add a ::adjust-bounds signal to GtkRange to allow spreadsheet style
|
||||
scrollbars. [Jody Goldberg]
|
||||
* Add the ability to turn on multiple selection for GtkFileSel [Manish]
|
||||
* Bug fixes
|
||||
|
||||
Other contributors: Jacob Berkman, Padraig O'Briain, Anders Carlsson,
|
||||
Johan Dahlin, Richard Hult, Stefan Kost, Alex Larsson, Thomas Leonard,
|
||||
Paolo Maggi, Alexey Malyshev, Federico Mena Quintero, Skip Montaro,
|
||||
Sven Neumann, Havoc Pennington, Laszlo Peter, Christian Rose, Joe Shaw,
|
||||
Kevin Vandersloot, Morten Welinder, Peter Williams
|
||||
|
||||
Overview of Changes in GTK+ 1.3.13
|
||||
==================================
|
||||
|
||||
* Tree view fixes. [Kristian Rietveld, Jonathan Blandford, Anders Carlsson]
|
||||
* Tree view support for low-vision themes [Bill Haneman]
|
||||
* Text view bug fixes. [Havoc Pennington]
|
||||
* Win32 fixes and improvements. [Tor Lillqvist, Hans Breuer,
|
||||
Archaeopteryx Software]
|
||||
* Documentation improvements [Matthias Clasen, Havoc Pennington]
|
||||
* Accelerate alpha compositing using RENDER extension if present,
|
||||
and optimize the non-RENDER case a lot. [Owen Taylor]
|
||||
* Add support for "optional keybindings" (action signal returns FALSE) [Owen]
|
||||
* Fixed the infamous changing directory deletes filename bug
|
||||
[Owen and a cast of thousands]
|
||||
* Add mouse cursor hiding for text widgets [Anders Carlsson]
|
||||
* Simple Hangul input module [Yusuke Tabata]
|
||||
* Removed the scary startup warning.
|
||||
* GdkPixbuf pixel handling fixes [Owen, Michael Hore, Jim Cape]
|
||||
* Converted GtkFileSelection and GtkFontSelection to use GtKTreeView widgets
|
||||
instead of the deprecated GtkCList [Owen]
|
||||
* gtkhsv.h was installed by mistake, fixed that. [reported by Ross Burton]
|
||||
* gdk_pixbuf_render_to_drawable() now also handles alpha pixbufs.
|
||||
* Made Gtkimage draw GtkPixmap, GtkImage, GdkPixbuf insensitive, prelighted,
|
||||
etc. [Havoc, Owen]
|
||||
* Marked gtk_item_factory_path_from_widget() G_CONST_RETURN. [Matt Wilson]
|
||||
* gtk_image_menu_item_new_from_stock() now falls back to
|
||||
new_with_mnemonic, for consistency with gtk_button_new_from_stock()
|
||||
[Havoc Pennington]
|
||||
* GdkModifierType is now consistently used for modifier mask parameters
|
||||
[Mark Patton]
|
||||
* gtk_widget_set_accel_path() is now publically exported.
|
||||
|
||||
Other contributors: Darin Adler, Jeffrey Baker, Damon Chaplin, Brian Cameron,
|
||||
Murray Cumming, James Henstridge, Jacob Berkman, Arnaud Charlet, Jeff Franks,
|
||||
Jeff Garzik, Jody Goldberg, Diego Gonzalez, Melvin Hadasht, Raja Harinath,
|
||||
Tim Janik, Mike Kestner, Mathieu Lacage, Alex Larsson, Ryan Lovett,
|
||||
Mark McLoughlin, Sven Neumann, Padraig O'Briain, Xavier Ordoquy, Chris Phelps,
|
||||
Detlef Reichl, Guillermo S. Romero, Federico Mena Quintero, Manish Singh,
|
||||
HideToshi Tajima, Vitaly Tishkov, Jon Trowbridge, Sergey Vlasov.
|
||||
|
||||
Overview of Changes in GTK+ 1.3.12
|
||||
==================================
|
||||
|
||||
* Fix problems with PNG saving [Michael Natterer]
|
||||
* Cleanups of deprecated usages [Sebastian Wilhelmi]
|
||||
* Win32 fixes [Tor Lillqvist]
|
||||
* Documentation improvements [Matthias Clasen, Havoc Pennington,
|
||||
Vitaly Tishkov]
|
||||
* Frame buffer port fixes [Manish Singh]
|
||||
* GtkTextView bug fixes [Havoc Pennington, Chris Phelps]
|
||||
* Menu behavior improvements [Kristian Rietveld]
|
||||
* Make focus line width configurable, focus color work on
|
||||
dark themes. [Bill Haneman, Owen Taylor]
|
||||
* Add state argument to gtk_paint_focus() [Bill]
|
||||
* Added incremental revalidation to tree view, for better apparent speed
|
||||
[Jonathan Blandford]
|
||||
* Remove useless gtk_tree_view_column_cell_event() [Jonathan]
|
||||
* Display XIM status in a separate window [HideToshi Tajima]
|
||||
* Add GDK_DEBUG=nograbs to disable pointer, keyboard grabs [Jacob Berkman]
|
||||
* Add menu of Unicode control characters to GtkEntry, GtkTextView
|
||||
[Dov Grobgeld, Havoc]
|
||||
* Pass key releases along to input methods [Owen]
|
||||
* Many bug fixes
|
||||
|
||||
Other contributors: Darin Adler, Fabrice Bellet, Chris Blizzard,
|
||||
Hans Breuer, Anders Carlsson, Damon Chaplin, Murray Cumming, Jeff Franks,
|
||||
James Henstridge, Tim Janik, Alex Larsson, George Lebl, Kjartan, Maraas,
|
||||
Sven Neumann, Seth Nickell, Padraig O'Briain, Soeren Sandmann, Manish Singh,
|
||||
Matt Wilson
|
||||
|
||||
Overview of Changes in GTK+ 1.3.11
|
||||
==================================
|
||||
|
||||
* Massive rework of accelerator API and implementation (Tim Janik)
|
||||
* Major fixes to resizing and redrawing to eliminate hysteresis
|
||||
and optimize. (Owen Taylor, Soeren Sandmann)
|
||||
* Make many widgets NO_WINDOW to improve appearance and reduce
|
||||
drawing overhead (Owen)
|
||||
* Text view fixes (Havoc Pennington)
|
||||
* Make child widgets in GtkTextView work (Havoc)
|
||||
* GtkTreeModelSort fixage (Jonathan Blandford, Kristian Rietveld)
|
||||
* Clean up GtkTreeView drag and drop support (Owen)
|
||||
* Misc tree view fixes and improvements (Jonathan, Kristian, Anders, Matt Wilson)
|
||||
* Add gtk_window_get/set_focus(), gtk_window_set_default() as public
|
||||
functions (Owen, Damian Ivereigh)
|
||||
* Fixes to GtkPlug/GtkSocket (Michael Meeks, Owen)
|
||||
* Change button ordering in standard dialogs to correspond to
|
||||
GNOME usability project proposal (Gregory Merchan)
|
||||
* Add support for context sensitivity in input methods (Owen)
|
||||
* Hook up gtk_im_context_set_use_preedit() (Hidetoshi Tajima)
|
||||
* Fix gdk_window_scroll() and other aspects of big windows (Owen)
|
||||
* Remove need for X connection for class initialization (Jacob Berkman)
|
||||
* Propagate key events to parents of focused widget (Owen)
|
||||
* Don't export normal GTK+ marshalers, export deprecated compat marshalers (Owen)
|
||||
* Many Win32 Fixes and improvements (Hans Breuer, Tor Lillqvist)
|
||||
* Bug and documentation fixing (Matthias Clasen, Anders Carlsson,
|
||||
Jacob Berkman, others.)
|
||||
|
||||
Other Contributors:
|
||||
Darin Adler, Marius Andreiana, Erwann Chenede, Murray Cumming, Janet Davis,
|
||||
Daniel Egger, Daniel Elstner, Jeff Franks, Alex Larsson, George Lebl,
|
||||
Sergey Kuzminov, Eric Lemings, Arkadiusz Miskiewicz, Padraig O'Briain, Sven Neumann,
|
||||
Kristian Rietveld, Nicolas Setton, Manish Singh, Vitaly Tishkov, Sebastian Wilhelmi,
|
||||
Michael Natterer
|
||||
|
||||
Overview of Changes in GTK+ 1.3.10
|
||||
==================================
|
||||
|
||||
* GtkTextView fixes [Havoc Pennington]
|
||||
* GtkTreeView fixes and improvements [Jonathan Blandford, Kristian,
|
||||
Manish Singh, Joshua Pritikin, Oleg Maiboroda, James Henstridge]
|
||||
* gtkdemo improvements [Kristian Rietveld]
|
||||
* Drag and drop fixes to generic code and widgets
|
||||
[Owen Taylor, Damian Ivereigh]
|
||||
* Documentation improvement [Havoc Pennington, Matthias Clasen]
|
||||
* Spelling fixes [Jacob Berkman]
|
||||
* Move signals to the GtkEditable interface [Kristian]
|
||||
* Further stock image improvements [Jakub Steiner]
|
||||
* Support text chunks for the PGN loader, add gdk_pixbuf_get_option()
|
||||
[Sven Neumann]
|
||||
* Rename gdk_pixbuf_new_from_stream back to new_from_inline [Owen]
|
||||
* Automatically call setlocale(), unless explicitly disabled [Owen]
|
||||
* Property addition to various widgets [Michael Meeks, Owen]
|
||||
* Support building with automake-1.4 [James]
|
||||
* Make GtkRadioButton groups act as a single focus point [Owen]
|
||||
* Move gdk_window_lookup etc. to be cross-platform [Matthias]
|
||||
* Draw spinbuttons variably sized [Kristian]
|
||||
* Separate GdkAtom out from X atoms for compatibility with future
|
||||
multihead changes [Owen]
|
||||
* Require gdk_threads_init() to be explicitly called instead
|
||||
of piggybacking off of g_thread_init(). [Owen]
|
||||
* Improvements to text-view/label/entry popup menus [Damian, Jacob, Owen]
|
||||
* Bug fixes and cleanup [Matthias, others]
|
||||
|
||||
Other Contributors:
|
||||
Mark McLoughin, Mikael Hermansson, Soeren Sandmann, Anders Carlsson,
|
||||
Tim Janik, Murray Cumming, Hidetoshi Tajima, Padraig O'Briain,
|
||||
Hans Breuer, Vitaly Tishkov, Dov Grobgeld
|
||||
|
||||
|
||||
Overview of Changes in GTK+ 1.3.9
|
||||
=================================
|
||||
|
||||
* Add editable text cells to GtkTreeView.
|
||||
Keynav, drawing fixes in GtkTreeView [Jonathan Blandford]
|
||||
* Text widget no longer always has a \n in it. [Havoc Pennington]
|
||||
* Text widget bug fixes [Havoc, Dov Grobgeld, Hidetoshi Tajima]
|
||||
* Allow -1 for width/height in gdk_pixbuf_render_*(). [Matthias Clasen]
|
||||
* Minor fix for major resizing problems in recent releases [Owen Taylor]
|
||||
* Restore ability to set _set properties to TRUE for
|
||||
GtkCellRendererText, GtkTextTag [Owen]
|
||||
* Cursor drawing improvements [Owen]
|
||||
* Win32 fixes [Hans Breuer]
|
||||
* Mark various functions as deprecated or private.
|
||||
* Misc bug fixes, portability fixes, and cleanups.
|
||||
|
||||
Other Contributors:
|
||||
Vitaly Tishkov, Christian Rose, Frank Belew, Jeff Franks, Sven Neumann,
|
||||
Kristian Rietveld, Vitaly Tishkov, Joshua N. Pritikin, Matt Wilson,
|
||||
James Henstridge, Detlef Reichl
|
||||
|
||||
Overview of Changes in GTK+ 1.3.8
|
||||
=================================
|
||||
|
||||
* GtkTreeView and GtkTreeModel API cleanups/improvements [Jrb]
|
||||
* GtkOptionMenu scrollwheel support [Alex]
|
||||
* GtkModule search paths [Owen]
|
||||
* Documenatation updates [Havoc,Jrb]
|
||||
* Major Gdk cleanup [Owen]
|
||||
* Miscellaneous other fixes/cleanups
|
||||
|
||||
Other Contributors:
|
||||
Joshua N Pritikin, Padraig O'Briain, Jakub Steiner, Matthias Clasen,
|
||||
Matt Wilson, James Henstridge
|
||||
|
||||
Overview of Changes in GTK+ 1.3.7
|
||||
=================================
|
||||
|
||||
* Many Pixbuf (loader) improvements [Matthias Clasen, Soeren Sandmann]
|
||||
* Added publically installed utility gdk-pixbuf-csource to generate
|
||||
inlined pixbufs in C source code [Tim Janik]
|
||||
* Optional movement of button children on press [Soeren, Owen Taylor]
|
||||
* Interactive searching in GtkTreeView [Kristian Rietveld]
|
||||
* Sorting/ordering improvements for GtkTreeView [Kris, Jonathan Blandford]
|
||||
* Animation of expander motion for GtkTreeView [Anders Carlsson]
|
||||
* Lots of misc GtkTreeView fixes and improvements [Jonathan]
|
||||
* New/improved stock icons [Jakub Steiner]
|
||||
* Code and API rework for window resizing [Havoc Pennington]
|
||||
* Converted accel groups to GObject [James Henstridge]
|
||||
* More property support improvements
|
||||
* Add facility for "secondary" buttons in
|
||||
GtkButtonBox/GtkDialog [Gregory Merchan]
|
||||
* Disentangled child visability from MAPPED state [Owen]
|
||||
* Plug/Socket improvements and port to the XEMBED protocol [Owen]
|
||||
* Added priorities for styles in RC files,
|
||||
support multiple parse contents [Owen]
|
||||
* Made GdkVisual and GdkDevice GObjects [Alexander Larsson]
|
||||
* Key binding improvements [Havoc]
|
||||
* Added GtkWidget::event-after signal since normal event handling
|
||||
is now aborted as soon as a handler returned TRUE [Tim]
|
||||
* Dnd fixes and improved icon support [Owen]
|
||||
* Removed GtkPacker widget
|
||||
* Fixing missing paired getters/setters [Kris]
|
||||
* Nuked remaining GtkArg cruft, implemented container/child properties [Tim]
|
||||
* Added window grab groups [Owen]
|
||||
* Many frame buffer improvements [Alex]
|
||||
* Win32 fixes and improvements [Hans Breuer]
|
||||
* Warning fixes [Darin Adler]
|
||||
* Miscellaneous bug and API fixes [Matthias et. al]
|
||||
|
||||
Other Contributors:
|
||||
Joshua N Pritikin, Hidetoshi Tajima, Manish Singh, ERDI Gergo, Jens Finke,
|
||||
Chema Celorio, Lee Mallabone, Vitaly Tishkov, Sebastian Wilhelmi,
|
||||
Nicola Girardi, Sven Neumann, Padraig O'Briain, Michael Natterer,
|
||||
Suresh Chandrasekharan, Jonas Borgström, Jay Cox, Michael Meeks,
|
||||
Mathias Hasselmann, Peter Williams, Thomas Broyer, Kjartan Maraas,
|
||||
Joel Becker, Jeff Franks, Brian Cameron, Skip Montanaro
|
||||
|
||||
Overview of Changes in GTK+ 1.3.6
|
||||
=================================
|
||||
|
||||
* Properly renders strikethrough text
|
||||
* win32 fixes
|
||||
* Added "scale" property to GtkTextTag and GtkCellRendererText to do
|
||||
relative font scaling
|
||||
* Added "format_value" signal to GtkScale to reformat value text
|
||||
* framebuffer fixes
|
||||
* Property support added to lots of widgets
|
||||
* Many GtkTreeView new features and API/implementation fixes
|
||||
* Lots of new_with_mnemonic() convenience functions
|
||||
* Change GtkImageMenuItem API to be more consistent/useful
|
||||
* Added lots of new stock items/icons
|
||||
* Rewrote GtkRange/GtkScale/GtkScrollbar, includes support for
|
||||
enabling/disabling extra scrollbar stepper arrows in gtkrc so NeXT
|
||||
themes won't need broken hacks
|
||||
* Convenience API for GtkRange similar to the one added to GtkSpinButton
|
||||
a while back
|
||||
* Make menubar/toolbar work properly with xthickness/ythickness of 1 or 0,
|
||||
and move some attributes from program settings to user settings.
|
||||
Allows nice 1-pixel-bevel themes.
|
||||
* Moved ::focus virtual function from GtkContainer to GtkWidget
|
||||
* Plenty of bug fixes
|
||||
|
||||
Overview of Changes in GTK+ 1.3.5
|
||||
=================================
|
||||
|
||||
* New default theme based on Raleigh theme for 1.2.x.
|
||||
* Dependency on the ATK library added as a step to
|
||||
providing accessibility-enabling interfaces
|
||||
* XEMBED-based GtkPlug/GtkSocket now basically works.
|
||||
* Drag and drop of column headers in GtkTreeView
|
||||
* GtkColorSelector work: hooks for saving and propagating palette, UI tweaks,
|
||||
and API sanitation
|
||||
* Key binding fixes
|
||||
* Configurable padding/spacing in a lot of places
|
||||
* Invisible text in GtkTextView fixed
|
||||
* SHM segments now created with a mode of 0600
|
||||
* Bug fixes
|
||||
|
||||
Overview of Changes in GTK+ 1.3.4
|
||||
=================================
|
||||
|
||||
* Win32 fixes
|
||||
* GtkTreeView improvements and fixes
|
||||
* Fix glib-2.0.m4
|
||||
* Miscellaneous bug fixes
|
||||
|
||||
Overview of Changes in GTK+ 1.3.3
|
||||
=================================
|
||||
|
||||
[ 5600 lines of ChangeLog ]
|
||||
|
||||
* API cleanups
|
||||
* Win32 work (Tor, Hans Breuer)
|
||||
* Focus improvements (Owen)
|
||||
* Frame buffer improvements (Alex)
|
||||
* Work on GtkTextView (Havoc)
|
||||
* Much work on GtkTreeView (Jonathan)
|
||||
* Selectable labels (Havoc)
|
||||
* Converted many arguments to properties (Lee Mallabone, John Margaglione)
|
||||
* Add exact regions to GdkExposeEvent, propagate it. (Alex)
|
||||
* Added ability to have resize grips in status bars (etc.) using
|
||||
_NET_WM_MOVERESIZE protocol. (Havoc)
|
||||
* Added mnemnonic mechanism to make setting underline accelerators
|
||||
much easier. (Alex)
|
||||
* Add per-style property mechanism to allow themes to change
|
||||
geometry parameters. (Tim)
|
||||
* Added global settings mechanisms for settings such as double-click
|
||||
time. (Tim, Owen)
|
||||
* Various support functions for new and old WM properties (Havoc, Alex)
|
||||
* Add TRUE-stops-returns for boolean-returning signals (Ron Steinke)
|
||||
|
||||
Overview of Changes in GTK+ 1.3.2
|
||||
=================================
|
||||
|
||||
GTK Core:
|
||||
|
||||
* New stock-icon and stock-item system. Use themeable pixbufs in
|
||||
dialogs, buttons, etc. [Havoc]
|
||||
* Theme engines reworked to use derivation and new object system. [Owen]
|
||||
* Added GtkClipboard object for simple selection handling. [Owen]
|
||||
* Make GtkEditable an interface, move implementation to GtkOldEditable for
|
||||
compat. [Owen]
|
||||
* Better handling of default directionality. [Robert]
|
||||
* Use GSignal as backend for GtkSignal and other GObject stuff. [Tim]
|
||||
* Move theme engines to GTypePlugin. [Owen]
|
||||
|
||||
GDK:
|
||||
|
||||
* Beginning of implementation of client parts of new window manager spec. [Owen]
|
||||
* Make gdk_drawable_get_image() work with backing store. [Havoc]
|
||||
|
||||
Widgets:
|
||||
|
||||
* New text widget [Havoc]
|
||||
- Adjustable tab handling.
|
||||
- Ability to have scrolling side areas in new text widget for tabs/line numbers.
|
||||
- Many cleanups and small improvements.
|
||||
* Improvements to submenu navigation [Nils Barth/David Santiago] and
|
||||
scrolling menus. [Alex]
|
||||
* Simplification of progress bar API. [Havoc]
|
||||
* Make GtkImage a generic image-display widget. [Havoc]
|
||||
* New GtkTreeView tree widget. Model/view architecture, flexible rendering,
|
||||
large datasets, etc. [Jonathan]
|
||||
* New GtkMessageBox widget for message display. [Havoc]
|
||||
* Allow labels to have contents set from XML-like markup language. [Havoc]
|
||||
* Make dialogs derive from GtkDialog and use stock buttons. [Havoc]
|
||||
|
||||
Internationalization:
|
||||
|
||||
* Proper character set conversion for clipboard/selection. [Owen]
|
||||
* New input method system via loadable modules; support on-the-spot
|
||||
preedit in GtkEntry and new text widget; allow switching input methods
|
||||
on the fly; include modules for XIM and demo Cyrillic-transliteration
|
||||
module. [Owen]
|
||||
* VIQR, Thai, and Inuktitut input methods. [Robert]
|
||||
* Convert po files to UTF-8. [Robert]
|
||||
|
||||
gdk-pixbuf:
|
||||
|
||||
* Full-alpha compositing for gdk-pixbuf on drawable. [Havoc]
|
||||
* Add simple saving to gdk-pixbuf. [David Welton/Havoc]
|
||||
* Add improved error handling with GError to gdk-pixbuf. [Havoc]
|
||||
|
||||
Ports:
|
||||
|
||||
* Much work on Win32 Port. [Tor/Hans]
|
||||
* Much work on Linux-FB Port. [Elliot/Alex]
|
||||
|
||||
Misc:
|
||||
|
||||
* Start of new gtk-demo demo program. [Owen/Jonathan]
|
||||
* Bug fixes and more bug fixes.
|
||||
|
||||
|
||||
Overview of Changes in GTK+ 1.3.1:
|
||||
|
||||
* GTK+ now uses the Pango library for text manipulation. All
|
||||
strings in GTK+ now are in Unicode, languages written
|
||||
from right-to-left, and complex-text languages are now supported.
|
||||
* The gdk-pixbuf library for image loading and manipulation is
|
||||
has been integrated with GTK+.
|
||||
* The GTK+ object system has mostly been moved to GLib, separating
|
||||
it from the GUI code. Many significant enhancements have been
|
||||
made as part of this.
|
||||
* A new text widget is now included. This started as a port
|
||||
of the Tk text widget, and includes such features of the Tk
|
||||
text widget as tags, marks, and unicode text support. It
|
||||
has been enhanced to support model-view operation and the
|
||||
full power of Pango.
|
||||
* The GDK library has been extensively revised to support multiple
|
||||
windowing systems. The only fully functional backend in 1.3.1
|
||||
is the X11 backend, however, ports to Win32, Linux-framebuffer,
|
||||
Nano-X, BeOS, and MacOS exist in various states of completion,
|
||||
and at least some of these will be finished and integrated in
|
||||
before the final GTK+-2.0 release.
|
||||
* 32-bit coordinates are now supported throughout GDK and GTK+
|
||||
(they are emulated where not supported by the windowing system.)
|
||||
* Many minor bug fixes and enhancements. Incompatible changes
|
||||
are documented in docs/Changes-2.0.txt
|
||||
|
||||
Overview of Changes in GTK+ 1.2.8:
|
||||
|
||||
* GNU Make 3.79 bug workaround
|
||||
* FAQ and tutorial updates and improvements
|
||||
* Miscellaneous bug fixes: CList, Calendar, rc-files, FontSelection
|
||||
|
||||
Overview of Changes in GTK+ 1.2.7:
|
||||
|
||||
* More header cleanups.
|
||||
* Fixed activation bug for insensitive widgets.
|
||||
* Locale fixes to RC file parsing code.
|
||||
* Miscellaneous bugfixes for Item Factory, CList, CTree, X Selections,
|
||||
HScale, VScale, Pixmap, Viewport, OptionMenu, Entry and Notebook.
|
||||
* Upgrade to libtool 1.3.4.
|
||||
|
||||
Overview of Changes in GTK+ 1.2.6:
|
||||
|
||||
* container queue_resize fixes
|
||||
* gtk[vh]scale: minor fixups
|
||||
* rename idle to idle_id in testgtk to avoid conflicts with
|
||||
broken libs
|
||||
* More consistent naming of gtkrc files
|
||||
* Added language support: ro, uk
|
||||
|
||||
Overview of Changes in GTK+ 1.2.5:
|
||||
|
||||
* more GtkCTree and GtkWindow bug fixes.
|
||||
* more redraw/resize queue fixes, better expose event
|
||||
discarding code.
|
||||
* more miscellaneous bugs fixed
|
||||
* new configure.in option --disable-rebuilds to completely disable
|
||||
rebuilds of autogenerated sources.
|
||||
* check for 5.002 now, to avoid failing autogeneration build rules due
|
||||
to old perl versions.
|
||||
* fonts (and fontsets) are cached now.
|
||||
* more autogeneration make rules and dependency fixups, we should be
|
||||
save with autogeneration up to make -j12 now ;)
|
||||
* new window position GTK_WIN_POS_CENTER_ALWAYS, which will recenter the
|
||||
GtkWindow on every size change.
|
||||
* major rework of window manager hints handling code, fixed a bunch of
|
||||
races with the new resizing code.
|
||||
* the new wm hints and resizing code is absolutely perfect and bug free now,
|
||||
it only lacks testing ;)
|
||||
* fixed up various rc style memory problems.
|
||||
* gtk_widget_modify_style() now properly changes the style of realized widgets
|
||||
and references the style passed into it. if people worked around this bug,
|
||||
this will introduce a slight memory leak in their code.
|
||||
The code should typically look like:
|
||||
GtkRcStyle *rc_style = gtk_rc_style_new ();
|
||||
[...]
|
||||
gtk_widget_modify_style (widget, rc_style);
|
||||
gtk_rc_style_unref (rc_style);
|
||||
* fix problems with positioning menus offscreen.
|
||||
* GtkText fixes for some crashes and drawing errors.
|
||||
* Better handling for unexpected window destroys in GDK and GTK+.
|
||||
This should make it possible to use a GtkPlug and catch the
|
||||
case where its parent socket is randomly killed.
|
||||
* FAQ updates.
|
||||
* FileSelection i18n patches, RadioButton fixups.
|
||||
* many translation improvements.
|
||||
* miscellaneous other bugs fixed.
|
||||
|
||||
Overview of Changes in GTK+ 1.2.4:
|
||||
|
||||
* DnD improvements (drags can be canceled with Esc now).
|
||||
* suppressed configure event reordering in Gdk.
|
||||
* rewrite of Gtk's configure event handling.
|
||||
* major improvements for the object argument system (Elena Devdariani).
|
||||
* major bugfixes for threading, GtkNotebook, GtkItemFactory, GtkCList and
|
||||
GtkCTree.
|
||||
* tutorial/FAQ updates, new file generation.txt on autogenerated sources.
|
||||
* configure's --with-glib= is "officially" unsupported.
|
||||
* upgrade to libtool 1.3.3.
|
||||
* various buglets fixed.
|
||||
|
||||
Overview of Changes in GTK+ 1.2.3:
|
||||
|
||||
* Upgrade to libtool 1.3
|
||||
* Check for dgettext (for systems with old versions of GNU Gettext)
|
||||
* Many bug fixes (see ChangeLog for details)
|
||||
|
||||
Overview of Changes in GTK+ 1.2.2:
|
||||
|
||||
* Improved Dnd behaviour with Motif applications.
|
||||
* Bug fixes for the Gtk selection code.
|
||||
* Minor bug fixes to the Gdk Atom cache and Dnd code (with --display option).
|
||||
* Bug fixes and leak plugs for the Gdk IM code.
|
||||
* Added gtk_object_get() facility to retrieve object arguments easily.
|
||||
The var args list expects ("arg-name", &value) pairs.
|
||||
* Fixed mapping for GdkInputCondition<->GIOCondition, this should fix
|
||||
problems where closed pipes were no longer signaling GDK_INPUT_READ on
|
||||
systems with a native poll().
|
||||
* Some cleanups to GtkLabel's memory allocation code (shouldn't leak memory
|
||||
anymore).
|
||||
* We don't attempt to lookup xpm color "None" anymore, this should prevent
|
||||
eXodus (commercial X windows server) from popping up a color dialog every
|
||||
time a transparent pixmap is created.
|
||||
* Fixed bug where Gtk timeout/idle handlers would execute without the global
|
||||
Gdk lock being held.
|
||||
* Other minor bug fixes.
|
||||
|
||||
Overview of Changes in GTK+ 1.2.1:
|
||||
|
||||
* Many Bug fixes have been applied to the menu and accelerator code.
|
||||
* GtkItemFactory can "adopt" foreign menu items now and manage their
|
||||
accelerator installation. This is often required to get GtkItemFactory
|
||||
like accelerator propagation between different windows with the same
|
||||
menu hierarchy and for centralized parsing and saving of accelerators.
|
||||
* GtkCList/GtkCTree buttons should always display correctly now.
|
||||
* Miscellaneous other bug fixes.
|
||||
|
||||
What's New in GTK+ 1.2.0 (since 1.0.x):
|
||||
|
||||
* New widgets: GtkFontSelector, GtkPacker, GtkItemFactory, GtkCTree,
|
||||
GtkInvisible, GtkCalendar, GtkLayout, GtkPlug, GtkSocket
|
||||
* Many new features and robustness for existing widgets
|
||||
* Theme support
|
||||
* New DND implementation
|
||||
* Internationalization of standard dialogs
|
||||
* New key binding system
|
||||
* Tearoff menus and menu accelerators
|
||||
* Wide character support for entry and text
|
||||
* Resizing code has been overhauled
|
||||
* Queued redraws of partial areas
|
||||
* Far better support for object arguments
|
||||
* Speed optimizations
|
||||
* Runtime loading of dynamic modules
|
||||
* Support for GLib log domains
|
||||
* Tutorial improvements
|
||||
* A bug fix or two
|
||||
|
||||
Overview of Changes in GTK+ 1.1.16:
|
||||
|
||||
* Major fixes and improvements for handlebox
|
||||
* A change to the way widget->requisition works. Now,
|
||||
widget->requisition is always what the widget requested,
|
||||
unmodified by the usize. See Changes-1.2.txt for details.
|
||||
This correct various bugs with gtk_widget_set_usize().
|
||||
* Fixes for XIM on X11R5 systems
|
||||
* Don't allow cut-and-paste of text in password-style entries
|
||||
* --enable-debug is now on by default for the development release.
|
||||
(When compiling for "production", use --enable-debug=minimum)
|
||||
* Handle systems where Helvetica is not present more gracefully
|
||||
* Fixes for memory leaks
|
||||
* CList and CTree fixes
|
||||
* Bug fixes for drawing problems.
|
||||
* Miscellaneous bug fixes to GtkLabel, GtkCList, GtkCTree,
|
||||
GtkColorsel, Focusing, DND
|
||||
* Tutorial improvements
|
||||
|
||||
Overview of Changes in GTK+ 1.1.15:
|
||||
|
||||
* Tutorial Updates
|
||||
* Added --libs gthread to gtk-config
|
||||
* Bug fixes
|
||||
|
||||
What is new in GTK+ 1.1.14:
|
||||
|
||||
* Additions to docs/Changes-1.2.txt
|
||||
* Just warn when loading theme engine fails
|
||||
* CLAMP GtkScale digits to a meaningful range
|
||||
* GTK_LOCALDIR is now defined in a better fashion
|
||||
* New functions (feature freeze, we know...):
|
||||
gtk_menu_set_title()
|
||||
gtk_toggle_button_get_active()
|
||||
* Some locale fixups in gtkrc code
|
||||
* Fixes to make gtk_radio_button_set_group() keep only
|
||||
one radio button in the group active
|
||||
* Foreign windows are now always treated as viewable; this fixes
|
||||
a problem where updating didn't occur properly in GtkPlug
|
||||
* DND fixes for 64 bit architectures, and for specifying operations
|
||||
with modifier keys.
|
||||
* Major revisions to GtkLayout: avoid having to create window
|
||||
for NO_WINDOW children, adjust allocations of children as
|
||||
scrolled so queued draws work, and a resize is queued instead
|
||||
of allocating directly in a put() or move()
|
||||
|
||||
What is new in GTK+ 1.1.13:
|
||||
|
||||
* Dnd and selection bug fixes and memory purification.
|
||||
* Widget sensitivity fixups.
|
||||
* Tooltips windows are now named "gtk-tooltips" so rc file rules
|
||||
can match tooltips windows. Fixed interaction of tooltips and NO_WINDOW
|
||||
widgets.
|
||||
* Spin buttons now update their values upon value retrieval.
|
||||
* Overhaul of the resizing vs. redrawing logic to reduce redrawing needs
|
||||
a lot. Gtk makes full use of the draw_area coalescing code now, which
|
||||
got minorly improved as well.
|
||||
* Containers map their Gdk windows after their children now to reduce
|
||||
expose event generation.
|
||||
* Gdk event queue fixups, this solves the double-click problems people were
|
||||
recently having.
|
||||
* Account for the fact that GSource's are only properly reentrant from
|
||||
within dispatch(), thus we don't do Gdk event processing from within
|
||||
check() or prepare() anymore.
|
||||
* Rc files feature a bg_pixmap value of "<none>" now.
|
||||
* Improved session management support in Gdk.
|
||||
* Automatic disabling of NLS if no gettext is found should work now.
|
||||
* Removed deprecated functions, docs/Changes-1.2.txt gives an overview.
|
||||
* Gtk+ development now requires GNU autoconf 2.13, GNU automake 1.4
|
||||
and GNU libtool 1.2d.
|
||||
* More bug fixes all over the place.
|
||||
|
||||
What is new in GTK+ 1.1.12:
|
||||
|
||||
* Korean translation added
|
||||
* Fixed memory leaks
|
||||
* A few other bug fixes
|
||||
|
||||
What is new in GTK+ 1.1.11:
|
||||
|
||||
* Dutch, Japanese, Swedish, Polish, and Norwegian translations
|
||||
* Removed deprecated _interp variants: gtk_container_foreach_interp,
|
||||
gtk_idle_add_interp, gtk_timeout_add_interp, gtk_signal_connect_interp
|
||||
* Lots of cast corrections
|
||||
* Many fixes
|
||||
|
||||
What is new in GTK+ 1.1.9:
|
||||
|
||||
* Check for broken glibc 2.0 mb functions and avoid them
|
||||
* Label and Entry display fixes
|
||||
* Move main thread back to GDK, for locking when translating events
|
||||
* Bug fixes
|
||||
|
||||
What is new in GTK+ 1.1.8:
|
||||
|
||||
* Added support for gettext and the localization of the standard
|
||||
dialogs.
|
||||
* Added line-wrapping for the label, and JUSTIFY_FILL
|
||||
* Support reordering via drag and drop in CList and CTree.
|
||||
* Replaced GtkDrawWindow widget with a GTK_USER_DRAW flag
|
||||
* Extended gtkpaned API to support minimum sizes and proportional
|
||||
resizing.
|
||||
* Changed the handling of shared memory segments so as to
|
||||
remove the need for GTK+ to set up signal handlers.
|
||||
* Re-implemented event loop in terms of the event loop
|
||||
that has been added to GLib 1.1.8
|
||||
* Added 'grab_focus' signal to allow keyboard accelerators
|
||||
for entries.
|
||||
* Load locale specific RC files if present.
|
||||
* Bug fixes.
|
||||
|
||||
What is new in GTK+ 1.1.7:
|
||||
|
||||
* Fixed memory mis-allocation in default files code
|
||||
* Various event handling fixes
|
||||
* Wide character support for entry and text
|
||||
* Destroy widgets _after_ propagating unrealize signals through
|
||||
widget hierarchy
|
||||
* Only build XIM-support if available
|
||||
* Tutorial and examples updates
|
||||
* Added gtk_drag_source_unset()
|
||||
|
||||
What is new in GTK+ 1.1.6:
|
||||
|
||||
* The signal system now features emission hooks with special semantics,
|
||||
refer to the ChangeLog for this.
|
||||
* Minor? speedups and memory reductions to the emission handling of the
|
||||
signal system.
|
||||
* _interp() function variants are deprecated now. the corresponding *_full()
|
||||
variants are provided for a long time now.
|
||||
* Dnd abort timeout increased to 10 minutes.
|
||||
* GtkScrolledWindow inherits from GtkBin now.
|
||||
* GTK_POLICY_NEVER is implemented for scrolled windows now.
|
||||
* Lots of API clean ups.
|
||||
* Incremental freezing abilities.
|
||||
* Integrated widgets from the GNOME tree: GtkLayout, GtkPlug and GtkSocket.
|
||||
* New window functions for transient relationship, default size, and
|
||||
geometry hints
|
||||
* Default rc files are now read in (<sysconfdir/etc/gtkrc and ~/.gtkrc)
|
||||
GTK_RC_FILES environment variable and functions are provided to configure
|
||||
this behavior
|
||||
* Read doc/Changes-1.2.txt to properly adapt your code.
|
||||
* Bug Fixes.
|
||||
|
||||
What is new in GTK+ 1.1.5:
|
||||
|
||||
* Theme integration
|
||||
* Widget style modification is now handled through GtkRcStyles
|
||||
* GtkPixmaps now grey out pixmaps when insensitive
|
||||
* Notebook enhancements
|
||||
* Shadow configurability for menubars and handleboxes
|
||||
* DND enhancements
|
||||
* gtkfilesel now supports automounters better
|
||||
* Implementation of expose compression
|
||||
* Queued redraws of partial areas
|
||||
* Scrolledwindow (+Viewport) source incompatibilities, children that are added
|
||||
to a scrolled window don't get an automatic viewport anymore. a convenience
|
||||
function gtk_scrolled_window_add_with_viewport() is supplied for this task
|
||||
* Deprecated functions will now issue a message, informing the programmer about
|
||||
the use of this function. These functions will get removed in future versions
|
||||
* Non-functional functions got removed entirely
|
||||
* gtk_widget_new() and gtk_object_new() will now auto-construct new objects.
|
||||
A new function gtk_object_default_construct() is provided now which should
|
||||
be called after every gtk_type_new() to perform the auto-construction
|
||||
* Improved argument support of several widgets
|
||||
* Bug Fixes
|
||||
|
||||
What is new in GTK+ 1.1.3:
|
||||
|
||||
* GtkCList/GtkCTree now have the ability to:
|
||||
- hide/show individual columns
|
||||
- disable/enable column resizing
|
||||
- set min and max for column widths
|
||||
- set expander style of the ctree
|
||||
- set/get row and cell styles
|
||||
- set spacing between tree expander and cell contents in ctree
|
||||
- toggle auto_resize for columns
|
||||
* Must enhanced DND support, removed old DND code
|
||||
* Idle functions are now implemented via GHook, giving a slight speed
|
||||
improvement
|
||||
* An environment variable GTK_MODULES which takes a colon separated
|
||||
list of module names GTK+ will now automatically load at gtk_init() startup
|
||||
* GtkFontSel now has support for an extra 'base' filter
|
||||
* New function gdk_window_set_root_origin to get the real geometry taking
|
||||
into account window manager offsets
|
||||
* New function gtk_text_set_line_wrap to toggle line wrapping
|
||||
* New function gtk_widget_add_events which safely adds additional
|
||||
events to a widget's event mask
|
||||
* New function gdk_event_get_time to get the timestamp from a generic
|
||||
event
|
||||
* New widget GtkCalendar
|
||||
* New widget GtkInvisible - InputOnly offscreen windows used for reliable
|
||||
pointer grabs and selection handling in DND code
|
||||
* New functions gtk_object_remove_no_notify[_by_id] to remove a certain
|
||||
data portion without invocation of its destroy notifier
|
||||
* gtk_spin_button_construct is now deprecated, use gtk_spin_button_configure
|
||||
instead
|
||||
* gtk_clist_set_border is now deprecated, use gtk_clist_set_shadow_type
|
||||
instead
|
||||
* Removed functions gtk_object_set_data_destroy[_by_id]
|
||||
* Documentation additions/updates
|
||||
* HTML and plain text files are now included in the distribution
|
||||
* Bug fixes, typeness corrections, and general fixups
|
||||
|
||||
What is new in GTK+ 1.1.2:
|
||||
|
||||
* Gtk+ is now featuring runtime loading of dynamic modules via the
|
||||
--gtk-modules= command line switch. such modules have to export a
|
||||
G_MODULE_EXPORT void gtk_module_init (gint *argc, gchar ***argv);
|
||||
function which will be invoked to initialize the module. since such
|
||||
modules may create new widget types, they are always resident.
|
||||
* The tutorial has been updated again.
|
||||
* Changes to menus including tearoff menus and accelerators.
|
||||
* Better support for modal dialogs.
|
||||
* Removed CAN_FOCUS by default from scrollbars and button children of toolbar.
|
||||
* More improvements and fixes for GtkCList and GtkCTree (i.e. row sorting).
|
||||
* GtkCTree rows can be unselectable now.
|
||||
* The GtkCTree API has undergone major renames (see ChangeLog entry from Lars
|
||||
Hamann on Tue Aug 18 00:29:13 1998).
|
||||
* A bunch of varargs functions changed to get va_lists working on systems that
|
||||
implement va_lists as arrays.
|
||||
* Improvements to the gdkrgb code.
|
||||
* Improvements to Gdk color handling so we greatly reduce server traffic and
|
||||
don't leak colors anymore.
|
||||
* Improved internal widget tree iterators (the GtkContainer::foreach signal
|
||||
vanished because of this).
|
||||
* Option menus can have the keyboard focus now.
|
||||
* More fixups to the text widget.
|
||||
* GtkFileSelection should behave much more nicely in combination with AFS now.
|
||||
* Support for label underlining.
|
||||
* Support for GLib 1.1.3 log domains.
|
||||
* Documentation improvements.
|
||||
* Configuration fixes on various platforms.
|
||||
* Miscellaneous fixes to XInput support.
|
||||
* Build with shared library dependencies on Linux
|
||||
* Fix for a major bug in the type systems memory allocation code that could
|
||||
cause random crashes.
|
||||
* Libtool update to version 1.2b.
|
||||
* Lots of bugfixes and cleanups again ;)
|
||||
|
||||
|
||||
What is new in GTK+ 1.1.1:
|
||||
|
||||
* Tutorial updates and additions.
|
||||
* Key binding support for GtkListItems and GtkList.
|
||||
* Extended selection mode and autoscrolling for GtkLists.
|
||||
* A GtkCtree now operates on GtkCTreeNode* structures rather than GList*.
|
||||
* GtkCTreeNodes can now be created from GNode trees.
|
||||
* Bug fixes for GtkNotebook, GtkCList, GtkCombo and GdkWindow reparentation.
|
||||
|
||||
|
||||
What is new in GTK+ 1.1.0:
|
||||
|
||||
* New widget GtkFontSelector.
|
||||
* New featureful progress bar.
|
||||
* New container widget GtkPacker.
|
||||
* New object GtkItemFactory, GtkMenuFactory is deprecated.
|
||||
* New key binding system, configurable via rcfiles, similar to styles.
|
||||
* New widget GtkCTree with drag selections and keyboard movement and
|
||||
and horizontal scrolling. Features also implemented for GtkCList.
|
||||
* Significant speedups to widget creation and destruction through caching
|
||||
colormap and visual queries to the XServer.
|
||||
* Speedups for type creation and especially gtk_type_is_a() checks.
|
||||
* Speedups in signal lookup, creation and emissions and connection handling.
|
||||
* Minor speedups with object data allocation and destruction.
|
||||
* Additions to the signal handling API (e.g. *_emitv).
|
||||
* Support for rc-file reparsing.
|
||||
* Resizing logic is now implemented on container widget basis, rather than
|
||||
for toplevel GtkWindows only.
|
||||
* Buttons support relief styles now.
|
||||
* Some widgets are now allocated through memchunks to behave more memory wise.
|
||||
* Newly included file gtkfeatures.h which defines compatibility macros to
|
||||
test for certain API features upon program compilation.
|
||||
* Child arguments support for container widgets.
|
||||
* Far better support for object arguments, revamp of the underlying
|
||||
mechanism for speed and reusability. Child/object arguments don't
|
||||
need to be preceded by the "GtkType::" portion anymore.
|
||||
* Removed GtkAcceleratorTable in favour of GtkAccelGroup, accelerator display
|
||||
is now performed by a new widget GtkAccelLabel.
|
||||
* Overhaul of the resizing code. Resizing behaviour can now be specified
|
||||
on GtkContainer basis, so the underlying algorithm isn't only available
|
||||
for GtkWindows.
|
||||
* GtkTables are now fully resizable.
|
||||
* The GtkType system now supports an additional base class initialization
|
||||
function.
|
||||
* GtkStyles and key bindings can now be looked up depending on the base
|
||||
types of a widget, through a new keyword `class' in rc files.
|
||||
* GtkButton derives from GtkBin (finally).
|
||||
* More descriptive error messages on rc parsing.
|
||||
* Runtime information is available to query enum/flag definition values.
|
||||
* Upgrade to libtool-1.2
|
||||
* Legions of bug fixes, memory leaks, segfaults, of-by-something errors...
|
||||
including those that already went into the 1.0.x branch.
|
||||
* A big bunch of features and cosmetic fixups that just got lost in
|
||||
the masses of changesonfigure problem when cross-compiling
|
6951
NEWS.pre-3.0
72
README.commits
Normal 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
|
77
README.md
@@ -1,17 +1,15 @@
|
||||
GTK — The GTK toolkit
|
||||
=====================
|
||||
|
||||
[](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.
|
||||
|
||||
|
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -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
build-aux/meson/post-install.sh
Executable 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
|
@@ -24,6 +24,9 @@
|
||||
/* Define to 1 if you have the <crt_externs.h> header file. */
|
||||
#mesondefine HAVE_CRT_EXTERNS_H
|
||||
|
||||
/* Define to 1 if CUPS 1.6 API is available */
|
||||
#mesondefine HAVE_CUPS_API_1_6
|
||||
|
||||
/* Define to 1 if you have the `dcgettext' function. */
|
||||
#mesondefine HAVE_DCGETTEXT
|
||||
|
||||
@@ -38,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
|
||||
|
||||
@@ -53,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
|
||||
|
||||
@@ -131,9 +128,6 @@
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#mesondefine HAVE_SYS_PARAM_H
|
||||
|
||||
/* Have the sysprof-capture library */
|
||||
#mesondefine HAVE_SYSPROF_CAPTURE
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#mesondefine HAVE_SYS_STAT_H
|
||||
|
||||
@@ -244,6 +238,9 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* Define to 1 if XInput 2.0 is available */
|
||||
#mesondefine XINPUT_2
|
||||
|
||||
/* Define to 1 if XInput 2.2 is available */
|
||||
#mesondefine XINPUT_2_2
|
||||
|
||||
@@ -283,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
|
||||
@@ -296,11 +289,3 @@
|
||||
#mesondefine GTK_LIBDIR
|
||||
|
||||
#mesondefine GTK_PRINT_BACKENDS
|
||||
|
||||
#mesondefine HAVE_CAIRO_SCRIPT_INTERPRETER
|
||||
|
||||
#mesondefine HAVE_HARFBUZZ
|
||||
|
||||
#mesondefine HAVE_PANGOFT
|
||||
|
||||
#mesondefine ISO_CODES_PREFIX
|
||||
|
@@ -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,49 +455,36 @@ 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)
|
||||
static gboolean
|
||||
demo_application_window_state_event (GtkWidget *widget,
|
||||
GdkEventWindowState *event)
|
||||
{
|
||||
DemoApplicationWindow *window = (DemoApplicationWindow *)widget;
|
||||
GdkSurfaceState new_state;
|
||||
gboolean res = GDK_EVENT_PROPAGATE;
|
||||
GdkWindowState changed, new_state;
|
||||
|
||||
new_state = gdk_surface_get_state (gtk_native_get_surface (GTK_NATIVE (widget)));
|
||||
window->maximized = (new_state & GDK_SURFACE_STATE_MAXIMIZED) != 0;
|
||||
window->fullscreen = (new_state & GDK_SURFACE_STATE_FULLSCREEN) != 0;
|
||||
}
|
||||
if (GTK_WIDGET_CLASS (demo_application_window_parent_class)->window_state_event)
|
||||
res = GTK_WIDGET_CLASS (demo_application_window_parent_class)->window_state_event (widget, event);
|
||||
|
||||
static void
|
||||
demo_application_window_realize (GtkWidget *widget)
|
||||
{
|
||||
GTK_WIDGET_CLASS (demo_application_window_parent_class)->realize (widget);
|
||||
gdk_event_get_window_state ((GdkEvent *)event, &changed, &new_state);
|
||||
window->maximized = (new_state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
|
||||
window->fullscreen = (new_state & GDK_WINDOW_STATE_FULLSCREEN) != 0;
|
||||
|
||||
g_signal_connect_swapped (gtk_native_get_surface (GTK_NATIVE (widget)), "notify::state",
|
||||
G_CALLBACK (surface_state_changed), widget);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_application_window_unrealize (GtkWidget *widget)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (gtk_native_get_surface (GTK_NATIVE (widget)),
|
||||
surface_state_changed, widget);
|
||||
|
||||
GTK_WIDGET_CLASS (demo_application_window_parent_class)->unrealize (widget);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -519,8 +506,7 @@ demo_application_window_class_init (DemoApplicationWindowClass *class)
|
||||
object_class->constructed = demo_application_window_constructed;
|
||||
|
||||
widget_class->size_allocate = demo_application_window_size_allocate;
|
||||
widget_class->realize = demo_application_window_realize;
|
||||
widget_class->unrealize = demo_application_window_unrealize;
|
||||
widget_class->window_state_event = demo_application_window_state_event;
|
||||
widget_class->destroy = demo_application_window_destroy;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/application_demo/application.ui");
|
||||
@@ -541,7 +527,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));
|
||||
|
||||
|
@@ -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>
|
||||
|
@@ -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,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 3.10 -->
|
||||
<menu id="appmenu">
|
||||
<section>
|
||||
<item>
|
||||
|
@@ -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);
|
||||
@@ -144,11 +144,8 @@ static void
|
||||
create_page4 (GtkWidget *assistant)
|
||||
{
|
||||
progress_bar = gtk_progress_bar_new ();
|
||||
gtk_widget_set_halign (progress_bar, GTK_ALIGN_FILL);
|
||||
gtk_widget_set_halign (progress_bar, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign (progress_bar, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_hexpand (progress_bar, TRUE);
|
||||
gtk_widget_set_margin_start (progress_bar, 40);
|
||||
gtk_widget_set_margin_end (progress_bar, 40);
|
||||
|
||||
gtk_widget_show (progress_bar);
|
||||
gtk_assistant_append_page (GTK_ASSISTANT (assistant), progress_bar);
|
||||
@@ -170,8 +167,8 @@ do_assistant (GtkWidget *do_widget)
|
||||
|
||||
gtk_window_set_default_size (GTK_WINDOW (assistant), -1, 300);
|
||||
|
||||
gtk_window_set_display (GTK_WINDOW (assistant),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_screen (GTK_WINDOW (assistant),
|
||||
gtk_widget_get_screen (do_widget));
|
||||
|
||||
create_page1 (assistant);
|
||||
create_page2 (assistant);
|
||||
|
@@ -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>
|
||||
|
@@ -1,481 +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)
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
@@ -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__ */
|
@@ -61,8 +61,8 @@ do_builder (GtkWidget *do_widget)
|
||||
|
||||
gtk_builder_connect_signals (builder, NULL);
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
toolbar = GTK_WIDGET (gtk_builder_get_object (builder, "toolbar1"));
|
||||
|
127
demos/gtk-demo/button_box.c
Normal 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_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (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;
|
||||
}
|
@@ -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,32 @@ 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_native_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 (GtkGestureClick *gesture,
|
||||
guint n_press,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
gboolean *clicked)
|
||||
static gboolean
|
||||
button_release_event_cb (GtkWidget *widget,
|
||||
GdkEventButton *event,
|
||||
gboolean *clicked)
|
||||
{
|
||||
*clicked = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Asks the user to click on a window, then waits for them click
|
||||
@@ -94,17 +101,19 @@ released_cb (GtkGestureClick *gesture,
|
||||
* window under the pointer, or NULL, if there is none.
|
||||
*/
|
||||
static GtkWidget *
|
||||
query_for_toplevel (GdkDisplay *display,
|
||||
query_for_toplevel (GdkScreen *screen,
|
||||
const char *prompt)
|
||||
{
|
||||
GdkDisplay *display = gdk_screen_get_display (screen);
|
||||
GtkWidget *popup, *label, *frame;
|
||||
GdkCursor *cursor;
|
||||
GtkWidget *toplevel = NULL;
|
||||
GdkDevice *device;
|
||||
|
||||
popup = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
gtk_window_set_display (GTK_WINDOW (popup), display);
|
||||
gtk_window_set_screen (GTK_WINDOW (popup), screen);
|
||||
gtk_window_set_modal (GTK_WINDOW (popup), TRUE);
|
||||
gtk_window_set_position (GTK_WINDOW (popup), GTK_WIN_POS_CENTER);
|
||||
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
|
||||
@@ -115,37 +124,34 @@ query_for_toplevel (GdkDisplay *display,
|
||||
gtk_container_add (GTK_CONTAINER (frame), label);
|
||||
|
||||
gtk_widget_show (popup);
|
||||
cursor = gdk_cursor_new_from_name ("crosshair", NULL);
|
||||
cursor = gdk_cursor_new_from_name (display, "crosshair");
|
||||
device = gtk_get_current_event_device ();
|
||||
|
||||
if (gdk_seat_grab (gdk_device_get_seat (device),
|
||||
gtk_native_get_surface (GTK_NATIVE (popup)),
|
||||
gtk_widget_get_window (popup),
|
||||
GDK_SEAT_CAPABILITY_ALL_POINTING,
|
||||
FALSE, cursor, NULL, NULL, NULL) == GDK_GRAB_SUCCESS)
|
||||
{
|
||||
GtkGesture *gesture = gtk_gesture_click_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, "button-release-event",
|
||||
G_CALLBACK (button_release_event_cb), &clicked);
|
||||
|
||||
/* Process events until clicked is set by our button release event handler.
|
||||
/* Process events until clicked is set by button_release_event_cb.
|
||||
* We pass in may_block=TRUE since we want to wait if there
|
||||
* are no events currently.
|
||||
*/
|
||||
while (!clicked)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
gdk_seat_ungrab (gdk_device_get_seat (device));
|
||||
|
||||
toplevel = find_toplevel_at_pointer (display);
|
||||
toplevel = find_toplevel_at_pointer (gdk_screen_get_display (screen));
|
||||
if (toplevel == popup)
|
||||
toplevel = NULL;
|
||||
}
|
||||
|
||||
g_object_unref (cursor);
|
||||
gtk_widget_destroy (popup);
|
||||
gdk_flush (); /* Really release the grab */
|
||||
|
||||
return toplevel;
|
||||
}
|
||||
@@ -156,17 +162,17 @@ query_for_toplevel (GdkDisplay *display,
|
||||
static void
|
||||
query_change_display (ChangeDisplayInfo *info)
|
||||
{
|
||||
GdkDisplay *display = gtk_widget_get_display (info->window);
|
||||
GdkScreen *screen = gtk_widget_get_screen (info->window);
|
||||
GtkWidget *toplevel;
|
||||
|
||||
toplevel = query_for_toplevel (display,
|
||||
toplevel = query_for_toplevel (screen,
|
||||
"Please select the toplevel\n"
|
||||
"to move to the new display");
|
||||
"to move to the new screen");
|
||||
|
||||
if (toplevel)
|
||||
gtk_window_set_display (GTK_WINDOW (toplevel), info->current_display);
|
||||
gtk_window_set_screen (GTK_WINDOW (toplevel), gdk_display_get_default_screen (info->current_display));
|
||||
else
|
||||
gdk_display_beep (display);
|
||||
gdk_display_beep (gdk_screen_get_display (screen));
|
||||
}
|
||||
|
||||
/* Called when the user clicks on a button in our dialog or
|
||||
@@ -306,7 +312,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);
|
||||
@@ -316,7 +322,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);
|
||||
@@ -356,11 +362,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,
|
||||
@@ -533,10 +539,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);
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* Clipboard
|
||||
*
|
||||
* GdkClipboard is used for clipboard handling. This demo shows how to
|
||||
* GtkClipboard is used for clipboard handling. This demo shows how to
|
||||
* copy and paste text to and from the clipboard.
|
||||
*
|
||||
* It also shows how to transfer images via the clipboard or via
|
||||
@@ -13,104 +13,78 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <string.h>
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
void
|
||||
copy_button_clicked (GtkWidget *button,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkWidget *entry;
|
||||
GdkClipboard *clipboard;
|
||||
GtkClipboard *clipboard;
|
||||
|
||||
entry = GTK_WIDGET (user_data);
|
||||
|
||||
/* Get the clipboard object */
|
||||
clipboard = gtk_widget_get_clipboard (entry);
|
||||
clipboard = gtk_widget_get_clipboard (entry,
|
||||
GDK_SELECTION_CLIPBOARD);
|
||||
|
||||
/* Set clipboard text */
|
||||
gdk_clipboard_set_text (clipboard, gtk_editable_get_text (GTK_EDITABLE (entry)));
|
||||
gtk_clipboard_set_text (clipboard, gtk_entry_get_text (GTK_ENTRY (entry)), -1);
|
||||
}
|
||||
|
||||
void
|
||||
paste_received (GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
paste_received (GtkClipboard *clipboard,
|
||||
const gchar *text,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkClipboard *clipboard;
|
||||
GtkWidget *entry;
|
||||
char *text;
|
||||
GError *error = NULL;
|
||||
|
||||
clipboard = GDK_CLIPBOARD (source_object);
|
||||
entry = GTK_WIDGET (user_data);
|
||||
|
||||
/* Get the resulting text of the read operation */
|
||||
text = gdk_clipboard_read_text_finish (clipboard, result, &error);
|
||||
|
||||
if (text)
|
||||
{
|
||||
/* Set the entry text */
|
||||
gtk_editable_set_text (GTK_EDITABLE (entry), text);
|
||||
g_free (text);
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
|
||||
/* Show an error about why pasting failed.
|
||||
* Usually you probably want to ignore such failures,
|
||||
* but for demonstration purposes, we show the error.
|
||||
*/
|
||||
dialog = gtk_message_dialog_new (GTK_WINDOW (window),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_CLOSE,
|
||||
"Could not paste text: %s",
|
||||
error->message);
|
||||
g_signal_connect (dialog, "response",
|
||||
G_CALLBACK (gtk_widget_destroy), NULL);
|
||||
gtk_widget_show (dialog);
|
||||
|
||||
g_error_free (error);
|
||||
}
|
||||
/* Set the entry text */
|
||||
if(text)
|
||||
gtk_entry_set_text (GTK_ENTRY (entry), text);
|
||||
}
|
||||
|
||||
void
|
||||
paste_button_clicked (GtkWidget *button,
|
||||
gpointer user_data)
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkWidget *entry;
|
||||
GdkClipboard *clipboard;
|
||||
GtkClipboard *clipboard;
|
||||
|
||||
entry = GTK_WIDGET (user_data);
|
||||
|
||||
/* Get the clipboard object */
|
||||
clipboard = gtk_widget_get_clipboard (entry);
|
||||
clipboard = gtk_widget_get_clipboard (entry,
|
||||
GDK_SELECTION_CLIPBOARD);
|
||||
|
||||
/* Request the contents of the clipboard, contents_received will be
|
||||
called when we do get the contents.
|
||||
*/
|
||||
gdk_clipboard_read_text_async (clipboard, NULL, paste_received, entry);
|
||||
gtk_clipboard_request_text (clipboard,
|
||||
paste_received, entry);
|
||||
}
|
||||
|
||||
static GdkPaintable *
|
||||
get_image_paintable (GtkImage *image)
|
||||
static GdkPixbuf *
|
||||
get_image_pixbuf (GtkImage *image)
|
||||
{
|
||||
const gchar *icon_name;
|
||||
GtkIconSize size;
|
||||
GtkIconTheme *icon_theme;
|
||||
GtkIconInfo *icon_info;
|
||||
int width;
|
||||
|
||||
switch (gtk_image_get_storage_type (image))
|
||||
{
|
||||
case GTK_IMAGE_PAINTABLE:
|
||||
return g_object_ref (gtk_image_get_paintable (image));
|
||||
case GTK_IMAGE_PIXBUF:
|
||||
return g_object_ref (gtk_image_get_pixbuf (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));
|
||||
gtk_image_get_icon_name (image, &icon_name, &size);
|
||||
icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (image)));
|
||||
gtk_icon_size_lookup (size, &width, NULL);
|
||||
return gtk_icon_theme_load_icon (icon_theme,
|
||||
icon_name,
|
||||
width,
|
||||
GTK_ICON_LOOKUP_GENERIC_FALLBACK,
|
||||
NULL);
|
||||
default:
|
||||
g_warning ("Image storage type %d not handled",
|
||||
gtk_image_get_storage_type (image));
|
||||
@@ -120,46 +94,48 @@ get_image_paintable (GtkImage *image)
|
||||
|
||||
static void
|
||||
drag_begin (GtkWidget *widget,
|
||||
GdkDrag *drag,
|
||||
GdkDragContext *context,
|
||||
gpointer data)
|
||||
{
|
||||
GdkPaintable *paintable;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
paintable = get_image_paintable (GTK_IMAGE (widget));
|
||||
if (paintable)
|
||||
{
|
||||
gtk_drag_set_icon_paintable (drag, paintable, -2, -2);
|
||||
g_object_unref (paintable);
|
||||
}
|
||||
pixbuf = get_image_pixbuf (GTK_IMAGE (data));
|
||||
gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
|
||||
void
|
||||
drag_data_get (GtkWidget *widget,
|
||||
GdkDrag *drag,
|
||||
GdkDragContext *context,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint time,
|
||||
gpointer data)
|
||||
{
|
||||
GdkPaintable *paintable;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
paintable = get_image_paintable (GTK_IMAGE (widget));
|
||||
if (GDK_IS_TEXTURE (paintable))
|
||||
gtk_selection_data_set_texture (selection_data, GDK_TEXTURE (paintable));
|
||||
pixbuf = get_image_pixbuf (GTK_IMAGE (data));
|
||||
gtk_selection_data_set_pixbuf (selection_data, pixbuf);
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
drag_data_received (GtkWidget *widget,
|
||||
GdkDrop *drop,
|
||||
GdkDragContext *context,
|
||||
gint x,
|
||||
gint y,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info,
|
||||
guint32 time,
|
||||
gpointer data)
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
if (gtk_selection_data_get_length (selection_data) > 0)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
|
||||
texture = gtk_selection_data_get_texture (selection_data);
|
||||
gtk_image_set_from_paintable (GTK_IMAGE (data), GDK_PAINTABLE (texture));
|
||||
g_object_unref (texture);
|
||||
pixbuf = gtk_selection_data_get_pixbuf (selection_data);
|
||||
gtk_image_set_from_pixbuf (GTK_IMAGE (data), pixbuf);
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,86 +143,79 @@ static void
|
||||
copy_image (GtkMenuItem *item,
|
||||
gpointer data)
|
||||
{
|
||||
GdkClipboard *clipboard;
|
||||
GdkPaintable *paintable;
|
||||
GtkClipboard *clipboard;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (data));
|
||||
paintable = get_image_paintable (GTK_IMAGE (data));
|
||||
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
||||
pixbuf = get_image_pixbuf (GTK_IMAGE (data));
|
||||
|
||||
if (GDK_IS_TEXTURE (paintable))
|
||||
gdk_clipboard_set_texture (clipboard, GDK_TEXTURE (paintable));
|
||||
|
||||
if (paintable)
|
||||
g_object_unref (paintable);
|
||||
}
|
||||
|
||||
static void
|
||||
paste_image_received (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
|
||||
texture = gdk_clipboard_read_texture_finish (GDK_CLIPBOARD (source), result, NULL);
|
||||
if (texture == NULL)
|
||||
return;
|
||||
|
||||
gtk_image_set_from_paintable (GTK_IMAGE (data), GDK_PAINTABLE (texture));
|
||||
g_object_unref (texture);
|
||||
gtk_clipboard_set_image (clipboard, pixbuf);
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
paste_image (GtkMenuItem *item,
|
||||
gpointer data)
|
||||
{
|
||||
GdkClipboard *clipboard;
|
||||
GtkClipboard *clipboard;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (data));
|
||||
gdk_clipboard_read_texture_async (clipboard,
|
||||
NULL,
|
||||
paste_image_received,
|
||||
data);
|
||||
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
||||
pixbuf = gtk_clipboard_wait_for_image (clipboard);
|
||||
|
||||
if (pixbuf)
|
||||
{
|
||||
gtk_image_set_from_pixbuf (GTK_IMAGE (data), pixbuf);
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pressed_cb (GtkGesture *gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
GtkWidget *image)
|
||||
static gboolean
|
||||
button_press (GtkWidget *widget,
|
||||
GdkEventButton *event,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *menu;
|
||||
GtkWidget *item;
|
||||
guint button;
|
||||
|
||||
gdk_event_get_button ((GdkEvent *)event, &button);
|
||||
|
||||
if (button != GDK_BUTTON_SECONDARY)
|
||||
return FALSE;
|
||||
|
||||
menu = gtk_menu_new ();
|
||||
|
||||
item = gtk_menu_item_new_with_mnemonic (_("_Copy"));
|
||||
g_signal_connect (item, "activate", G_CALLBACK (copy_image), image);
|
||||
g_signal_connect (item, "activate", G_CALLBACK (copy_image), data);
|
||||
gtk_widget_show (item);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
||||
|
||||
item = gtk_menu_item_new_with_mnemonic (_("_Paste"));
|
||||
g_signal_connect (item, "activate", G_CALLBACK (paste_image), image);
|
||||
g_signal_connect (item, "activate", G_CALLBACK (paste_image), data);
|
||||
gtk_widget_show (item);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
|
||||
|
||||
gtk_menu_popup_at_pointer (GTK_MENU (menu), NULL);
|
||||
gtk_menu_popup_at_pointer (GTK_MENU (menu), (GdkEvent *) event);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_clipboard (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *vbox, *hbox;
|
||||
GtkWidget *label;
|
||||
GtkWidget *entry, *button;
|
||||
GtkWidget *image;
|
||||
GtkGesture *gesture;
|
||||
GtkClipboard *clipboard;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Clipboard");
|
||||
|
||||
g_signal_connect (window, "destroy",
|
||||
@@ -259,52 +228,53 @@ 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");
|
||||
image = gtk_image_new_from_icon_name ("dialog-warning",
|
||||
GTK_ICON_SIZE_BUTTON);
|
||||
gtk_container_add (GTK_CONTAINER (hbox), image);
|
||||
|
||||
/* make image a drag source */
|
||||
gtk_drag_source_set (image, GDK_BUTTON1_MASK, NULL, GDK_ACTION_COPY);
|
||||
gtk_drag_source_set (image, GDK_BUTTON1_MASK, NULL, 0, GDK_ACTION_COPY);
|
||||
gtk_drag_source_add_image_targets (image);
|
||||
g_signal_connect (image, "drag-begin",
|
||||
G_CALLBACK (drag_begin), image);
|
||||
@@ -313,23 +283,22 @@ do_clipboard (GtkWidget *do_widget)
|
||||
|
||||
/* accept drops on image */
|
||||
gtk_drag_dest_set (image, GTK_DEST_DEFAULT_ALL,
|
||||
NULL, GDK_ACTION_COPY);
|
||||
NULL, 0, GDK_ACTION_COPY);
|
||||
gtk_drag_dest_add_image_targets (image);
|
||||
g_signal_connect (image, "drag-data-received",
|
||||
G_CALLBACK (drag_data_received), image);
|
||||
|
||||
/* context menu on image */
|
||||
gesture = gtk_gesture_click_new ();
|
||||
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
|
||||
g_signal_connect (gesture, "pressed", G_CALLBACK (pressed_cb), image);
|
||||
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (gesture));
|
||||
g_signal_connect (image, "button-press-event",
|
||||
G_CALLBACK (button_press), image);
|
||||
|
||||
/* Create the second image */
|
||||
image = gtk_image_new_from_icon_name ("process-stop");
|
||||
image = gtk_image_new_from_icon_name ("process-stop",
|
||||
GTK_ICON_SIZE_BUTTON);
|
||||
gtk_container_add (GTK_CONTAINER (hbox), image);
|
||||
|
||||
/* make image a drag source */
|
||||
gtk_drag_source_set (image, GDK_BUTTON1_MASK, NULL, GDK_ACTION_COPY);
|
||||
gtk_drag_source_set (image, GDK_BUTTON1_MASK, NULL, 0, GDK_ACTION_COPY);
|
||||
gtk_drag_source_add_image_targets (image);
|
||||
g_signal_connect (image, "drag-begin",
|
||||
G_CALLBACK (drag_begin), image);
|
||||
@@ -338,16 +307,18 @@ do_clipboard (GtkWidget *do_widget)
|
||||
|
||||
/* accept drops on image */
|
||||
gtk_drag_dest_set (image, GTK_DEST_DEFAULT_ALL,
|
||||
NULL, GDK_ACTION_COPY);
|
||||
NULL, 0, GDK_ACTION_COPY);
|
||||
gtk_drag_dest_add_image_targets (image);
|
||||
g_signal_connect (image, "drag-data-received",
|
||||
G_CALLBACK (drag_data_received), image);
|
||||
|
||||
/* context menu on image */
|
||||
gesture = gtk_gesture_click_new ();
|
||||
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
|
||||
g_signal_connect (gesture, "pressed", G_CALLBACK (pressed_cb), image);
|
||||
gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (gesture));
|
||||
g_signal_connect (image, "button-press-event",
|
||||
G_CALLBACK (button_press), image);
|
||||
|
||||
/* tell the clipboard manager to make the data persistent */
|
||||
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
||||
gtk_clipboard_set_can_store (clipboard, NULL, 0);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
@@ -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.
|
||||
*/
|
||||
@@ -70,10 +70,9 @@ do_colorsel (GtkWidget *do_widget)
|
||||
color.alpha = 1;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Color Chooser");
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
@@ -88,7 +87,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 +100,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);
|
||||
|
@@ -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;
|
||||
|
||||
@@ -311,8 +311,8 @@ do_combobox (GtkWidget *do_widget)
|
||||
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_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Combo Boxes");
|
||||
|
||||
g_signal_connect (window, "destroy",
|
||||
@@ -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);
|
||||
|
@@ -1,289 +0,0 @@
|
||||
/* Constraints/Simple
|
||||
*
|
||||
* GtkConstraintLayout provides a layout manager that uses relations
|
||||
* between widgets (also known as "constraints") to compute the position
|
||||
* and size of each child.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_DECLARE_FINAL_TYPE (SimpleGrid, simple_grid, SIMPLE, GRID, GtkWidget)
|
||||
|
||||
struct _SimpleGrid
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *button1, *button2;
|
||||
GtkWidget *button3;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (SimpleGrid, simple_grid, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
simple_grid_destroy (GtkWidget *widget)
|
||||
{
|
||||
SimpleGrid *self = SIMPLE_GRID (widget);
|
||||
|
||||
g_clear_pointer (&self->button1, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button2, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button3, gtk_widget_destroy);
|
||||
|
||||
GTK_WIDGET_CLASS (simple_grid_parent_class)->destroy (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
simple_grid_class_init (SimpleGridClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->destroy = simple_grid_destroy;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
|
||||
}
|
||||
|
||||
/* Layout:
|
||||
*
|
||||
* +-------------------------------------+
|
||||
* | +-----------++-------++-----------+ |
|
||||
* | | Child 1 || Space || Child 2 | |
|
||||
* | +-----------++-------++-----------+ |
|
||||
* | +---------------------------------+ |
|
||||
* | | Child 3 | |
|
||||
* | +---------------------------------+ |
|
||||
* +-------------------------------------+
|
||||
*
|
||||
* Constraints:
|
||||
*
|
||||
* super.start = child1.start - 8
|
||||
* child1.width = child2.width
|
||||
* child1.end = space.start
|
||||
* space.end = child2.start
|
||||
* child2.end = super.end - 8
|
||||
* super.start = child3.start - 8
|
||||
* child3.end = super.end - 8
|
||||
* super.top = child1.top - 8
|
||||
* super.top = child2.top - 8
|
||||
* child1.bottom = child3.top - 12
|
||||
* child2.bottom = child3.top - 12
|
||||
* child3.height = child1.height
|
||||
* child3.height = child2.height
|
||||
* child3.bottom = super.bottom - 8
|
||||
*
|
||||
* To add some flexibility, we make the space
|
||||
* stretchable:
|
||||
*
|
||||
* space.width >= 10
|
||||
* space.width = 100
|
||||
* space.width <= 200
|
||||
*/
|
||||
static void
|
||||
build_constraints (SimpleGrid *self,
|
||||
GtkConstraintLayout *manager)
|
||||
{
|
||||
GtkConstraintGuide *guide;
|
||||
|
||||
guide = gtk_constraint_guide_new ();
|
||||
gtk_constraint_guide_set_name (guide, "space");
|
||||
gtk_constraint_guide_set_min_size (guide, 10, 10);
|
||||
gtk_constraint_guide_set_nat_size (guide, 100, 10);
|
||||
gtk_constraint_guide_set_max_size (guide, 200, 20);
|
||||
gtk_constraint_guide_set_strength (guide, GTK_CONSTRAINT_STRENGTH_STRONG);
|
||||
gtk_constraint_layout_add_guide (manager, guide);
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new_constant (GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
|
||||
GTK_CONSTRAINT_RELATION_LE,
|
||||
200.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
guide,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (guide,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-12.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-12.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button1,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button2,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_HEIGHT,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (self->button3,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
}
|
||||
|
||||
static void
|
||||
simple_grid_init (SimpleGrid *self)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
|
||||
self->button1 = gtk_button_new_with_label ("Child 1");
|
||||
gtk_widget_set_parent (self->button1, widget);
|
||||
gtk_widget_set_name (self->button1, "button1");
|
||||
|
||||
self->button2 = gtk_button_new_with_label ("Child 2");
|
||||
gtk_widget_set_parent (self->button2, widget);
|
||||
gtk_widget_set_name (self->button2, "button2");
|
||||
|
||||
self->button3 = gtk_button_new_with_label ("Child 3");
|
||||
gtk_widget_set_parent (self->button3, widget);
|
||||
gtk_widget_set_name (self->button3, "button3");
|
||||
|
||||
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_constraints (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Constraints");
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
|
||||
grid = g_object_new (simple_grid_get_type (), NULL);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
gtk_widget_set_vexpand (grid, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (box), grid);
|
||||
|
||||
button = gtk_button_new_with_label ("Close");
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK (gtk_widget_destroy), window);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
@@ -1,245 +0,0 @@
|
||||
/* Constraints/Interactive
|
||||
*
|
||||
* Demonstrate how constraints can be updates during
|
||||
* user interaction.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_DECLARE_FINAL_TYPE (InteractiveGrid, interactive_grid, INTERACTIVE, GRID, GtkWidget)
|
||||
|
||||
struct _InteractiveGrid
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *button1, *button2;
|
||||
GtkWidget *button3;
|
||||
GtkConstraintGuide *guide;
|
||||
GtkConstraint *constraint;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (InteractiveGrid, interactive_grid, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
interactive_grid_destroy (GtkWidget *widget)
|
||||
{
|
||||
InteractiveGrid *self = INTERACTIVE_GRID (widget);
|
||||
|
||||
g_clear_pointer (&self->button1, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button2, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button3, gtk_widget_destroy);
|
||||
|
||||
GTK_WIDGET_CLASS (interactive_grid_parent_class)->destroy (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
interactive_grid_class_init (InteractiveGridClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->destroy = interactive_grid_destroy;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
build_constraints (InteractiveGrid *self,
|
||||
GtkConstraintLayout *manager)
|
||||
{
|
||||
self->guide = g_object_new (GTK_TYPE_CONSTRAINT_GUIDE, NULL);
|
||||
gtk_constraint_layout_add_guide (manager, self->guide);
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new_constant (GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_WIDTH,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_END,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_START,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button1),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
GTK_CONSTRAINT_TARGET (self->button2),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
gtk_constraint_layout_add_constraint (manager,
|
||||
gtk_constraint_new (GTK_CONSTRAINT_TARGET (self->button3),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
-8.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED));
|
||||
}
|
||||
|
||||
static void
|
||||
drag_cb (GtkGestureDrag *drag,
|
||||
double offset_x,
|
||||
double offset_y,
|
||||
InteractiveGrid *self)
|
||||
{
|
||||
GtkConstraintLayout *layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (self)));
|
||||
double x, y;
|
||||
|
||||
if (self->constraint)
|
||||
{
|
||||
gtk_constraint_layout_remove_constraint (layout, self->constraint);
|
||||
g_clear_object (&self->constraint);
|
||||
}
|
||||
|
||||
gtk_gesture_drag_get_start_point (drag, &x, &y);
|
||||
self->constraint = gtk_constraint_new_constant (GTK_CONSTRAINT_TARGET (self->guide),
|
||||
GTK_CONSTRAINT_ATTRIBUTE_LEFT,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
x + offset_x,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
gtk_constraint_layout_add_constraint (layout, g_object_ref (self->constraint));
|
||||
gtk_widget_queue_allocate (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static void
|
||||
interactive_grid_init (InteractiveGrid *self)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
GtkGesture *drag;
|
||||
|
||||
self->button1 = gtk_button_new_with_label ("Child 1");
|
||||
gtk_widget_set_parent (self->button1, widget);
|
||||
gtk_widget_set_name (self->button1, "button1");
|
||||
|
||||
self->button2 = gtk_button_new_with_label ("Child 2");
|
||||
gtk_widget_set_parent (self->button2, widget);
|
||||
gtk_widget_set_name (self->button2, "button2");
|
||||
|
||||
self->button3 = gtk_button_new_with_label ("Child 3");
|
||||
gtk_widget_set_parent (self->button3, widget);
|
||||
gtk_widget_set_name (self->button3, "button3");
|
||||
|
||||
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
|
||||
|
||||
drag = gtk_gesture_drag_new ();
|
||||
g_signal_connect (drag, "drag-update", G_CALLBACK (drag_cb), self);
|
||||
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (drag));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_constraints2 (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Constraints");
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
|
||||
grid = g_object_new (interactive_grid_get_type (), NULL);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
gtk_widget_set_vexpand (grid, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (box), grid);
|
||||
|
||||
button = gtk_button_new_with_label ("Close");
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK (gtk_widget_destroy), window);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
@@ -1,190 +0,0 @@
|
||||
/* Constraints/Grid
|
||||
*
|
||||
* GtkConstraintLayout lets you define complex layouts
|
||||
* like grids.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ComplexGrid, complex_grid, COMPLEX, GRID, GtkWidget)
|
||||
|
||||
struct _ComplexGrid
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkWidget *button1, *button2, *button3;
|
||||
GtkWidget *button4, *button5;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ComplexGrid, complex_grid, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
complex_grid_destroy (GtkWidget *widget)
|
||||
{
|
||||
ComplexGrid *self = COMPLEX_GRID (widget);
|
||||
|
||||
g_clear_pointer (&self->button1, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button2, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button3, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button4, gtk_widget_destroy);
|
||||
g_clear_pointer (&self->button5, gtk_widget_destroy);
|
||||
|
||||
GTK_WIDGET_CLASS (complex_grid_parent_class)->destroy (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
complex_grid_class_init (ComplexGridClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->destroy = complex_grid_destroy;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
|
||||
}
|
||||
|
||||
/* Layout:
|
||||
*
|
||||
* +--------------------------------------+
|
||||
* | +-----------+ |
|
||||
* | | Child 4 | |
|
||||
* | +-----------+-----------+----------+ |
|
||||
* | | Child 1 | Child 2 | Child 3 | |
|
||||
* | +-----------+-----------+----------+ |
|
||||
* | | Child 5 | |
|
||||
* | +-----------+ |
|
||||
* +--------------------------------------+
|
||||
*
|
||||
*/
|
||||
static void
|
||||
build_constraints (ComplexGrid *self,
|
||||
GtkConstraintLayout *manager)
|
||||
{
|
||||
GtkGridConstraint *constraint;
|
||||
GtkConstraint *s;
|
||||
|
||||
s = gtk_constraint_new (NULL, GTK_CONSTRAINT_ATTRIBUTE_LEFT,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button1, GTK_CONSTRAINT_ATTRIBUTE_LEFT,
|
||||
1.0, 0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
gtk_constraint_layout_add_constraint (manager, s);
|
||||
|
||||
s = gtk_constraint_new (self->button3, GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
NULL, GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
|
||||
1.0, 0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
gtk_constraint_layout_add_constraint (manager, s);
|
||||
|
||||
s = gtk_constraint_new (NULL, GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button4, GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0, 0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
gtk_constraint_layout_add_constraint (manager, s);
|
||||
|
||||
s = gtk_constraint_new (NULL, GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
self->button5, GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0, 0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
gtk_constraint_layout_add_constraint (manager, s);
|
||||
|
||||
constraint = gtk_grid_constraint_new ();
|
||||
g_object_set (constraint, "column-homogeneous", TRUE, NULL);
|
||||
gtk_grid_constraint_add (constraint,
|
||||
self->button1,
|
||||
0, 1, 0, 1);
|
||||
gtk_grid_constraint_add (constraint,
|
||||
self->button2,
|
||||
1, 2, 0, 1);
|
||||
gtk_grid_constraint_add (constraint,
|
||||
self->button3,
|
||||
2, 3, 0, 1);
|
||||
gtk_constraint_layout_add_grid_constraint (manager, constraint);
|
||||
|
||||
constraint = gtk_grid_constraint_new ();
|
||||
g_object_set (constraint, "row-homogeneous", TRUE, NULL);
|
||||
gtk_grid_constraint_add (constraint,
|
||||
self->button4,
|
||||
0, 1, 0, 1);
|
||||
gtk_grid_constraint_add (constraint,
|
||||
self->button2,
|
||||
0, 1, 1, 2);
|
||||
gtk_grid_constraint_add (constraint,
|
||||
self->button5,
|
||||
0, 1, 2, 3);
|
||||
gtk_constraint_layout_add_grid_constraint (manager, constraint);
|
||||
}
|
||||
|
||||
static void
|
||||
complex_grid_init (ComplexGrid *self)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
GtkLayoutManager *manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
|
||||
self->button1 = gtk_button_new_with_label ("Child 1");
|
||||
gtk_widget_set_parent (self->button1, widget);
|
||||
gtk_widget_set_name (self->button1, "button1");
|
||||
|
||||
self->button2 = gtk_button_new_with_label ("Child 2");
|
||||
gtk_widget_set_parent (self->button2, widget);
|
||||
gtk_widget_set_name (self->button2, "button2");
|
||||
|
||||
self->button3 = gtk_button_new_with_label ("Child 3");
|
||||
gtk_widget_set_parent (self->button3, widget);
|
||||
gtk_widget_set_name (self->button3, "button3");
|
||||
|
||||
self->button4 = gtk_button_new_with_label ("Child 4");
|
||||
gtk_widget_set_parent (self->button4, widget);
|
||||
gtk_widget_set_name (self->button4, "button4");
|
||||
|
||||
self->button5 = gtk_button_new_with_label ("Child 5");
|
||||
gtk_widget_set_parent (self->button5, widget);
|
||||
gtk_widget_set_name (self->button5, "button5");
|
||||
|
||||
build_constraints (self, GTK_CONSTRAINT_LAYOUT (manager));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_constraints3 (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Constraints");
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
|
||||
grid = g_object_new (complex_grid_get_type (), NULL);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
gtk_widget_set_vexpand (grid, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (box), grid);
|
||||
|
||||
button = gtk_button_new_with_label ("Close");
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK (gtk_widget_destroy), window);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
@@ -1,355 +0,0 @@
|
||||
/* Constraints/Words
|
||||
*
|
||||
* GtkConstraintLayout lets you define big grids.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define WORDS_TYPE_BASE (words_base_get_type ())
|
||||
#define WORDS_TYPE_GRID (words_grid_get_type ())
|
||||
#define WORDS_TYPE_CONSTRAINT (words_constraint_get_type ())
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
} WordsBase;
|
||||
|
||||
typedef WordsBase WordsGrid;
|
||||
typedef WordsBase WordsConstraint;
|
||||
|
||||
typedef GtkWidgetClass WordsBaseClass;
|
||||
typedef GtkWidgetClass WordsGridClass;
|
||||
typedef GtkWidgetClass WordsConstraintClass;
|
||||
|
||||
G_DEFINE_TYPE (WordsBase, words_base, GTK_TYPE_WIDGET)
|
||||
G_DEFINE_TYPE (WordsGrid, words_grid, WORDS_TYPE_BASE)
|
||||
G_DEFINE_TYPE (WordsConstraint, words_constraint, WORDS_TYPE_BASE)
|
||||
|
||||
static void
|
||||
words_grid_init (WordsGrid *words)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
words_grid_class_init (WordsGridClass *class)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_GRID_LAYOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
words_constraint_init (WordsGrid *words)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
words_constraint_class_init (WordsConstraintClass *class)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_CONSTRAINT_LAYOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
word_base_dispose (GObject *object)
|
||||
{
|
||||
GtkWidget *self = GTK_WIDGET (object);
|
||||
GtkWidget *child;
|
||||
|
||||
while ((child = gtk_widget_get_first_child (self)) != NULL)
|
||||
gtk_widget_unparent (child);
|
||||
|
||||
G_OBJECT_CLASS (words_base_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
words_base_class_init (WordsBaseClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = word_base_dispose;
|
||||
}
|
||||
|
||||
static int num_words = 100;
|
||||
static gboolean use_constraints = FALSE;
|
||||
|
||||
static void
|
||||
read_words (WordsBase *self)
|
||||
{
|
||||
GBytes *data;
|
||||
const char *words;
|
||||
int left, top;
|
||||
GtkWidget *child = NULL;
|
||||
GtkLayoutManager *layout = gtk_widget_get_layout_manager (GTK_WIDGET (self));
|
||||
GtkGridConstraint *grid;
|
||||
GtkConstraint *constraint;
|
||||
int count;
|
||||
int rightmost;
|
||||
GtkWidget *right_child = NULL;
|
||||
gboolean use_constraint = GTK_IS_CONSTRAINT_LAYOUT (layout);
|
||||
|
||||
if (use_constraint)
|
||||
{
|
||||
grid = gtk_grid_constraint_new ();
|
||||
g_object_set (grid,
|
||||
"row-homogeneous", TRUE,
|
||||
"column-homogeneous", FALSE,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_grid_layout_set_row_homogeneous (GTK_GRID_LAYOUT (layout), TRUE);
|
||||
gtk_grid_layout_set_column_homogeneous (GTK_GRID_LAYOUT (layout), FALSE);
|
||||
}
|
||||
|
||||
data = g_resources_lookup_data ("/constraints4/words", 0, NULL);
|
||||
words = g_bytes_get_data (data, NULL);
|
||||
count = 0;
|
||||
|
||||
rightmost = 0;
|
||||
left = 0;
|
||||
top = 0;
|
||||
while (words && words[0])
|
||||
{
|
||||
char *p = strchr (words, '\n');
|
||||
char *word;
|
||||
int len;
|
||||
|
||||
if (p)
|
||||
{
|
||||
word = strndup (words, p - words);
|
||||
words = p + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
word = strdup (words);
|
||||
words = NULL;
|
||||
}
|
||||
|
||||
len = strlen (word);
|
||||
child = gtk_button_new_with_label (word);
|
||||
|
||||
if (left + len > 50)
|
||||
{
|
||||
top++;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
gtk_widget_set_parent (child, GTK_WIDGET (self));
|
||||
|
||||
if (left + len > rightmost)
|
||||
{
|
||||
rightmost = left + len;
|
||||
right_child = child;
|
||||
}
|
||||
|
||||
if (use_constraint)
|
||||
{
|
||||
gtk_grid_constraint_add (grid, child,
|
||||
left, left + len,
|
||||
top, top + 1);
|
||||
if (left == 0 && top == 0)
|
||||
{
|
||||
constraint = gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
child,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_TOP,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
|
||||
constraint);
|
||||
constraint = gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_LEFT,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
child,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_LEFT,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
|
||||
constraint);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkGridLayoutChild *grid_child = GTK_GRID_LAYOUT_CHILD (gtk_layout_manager_get_layout_child (layout, child));
|
||||
|
||||
g_object_set (grid_child,
|
||||
"left-attach", left,
|
||||
"top-attach", top,
|
||||
"column-span", len,
|
||||
"row-span", 1,
|
||||
NULL);
|
||||
}
|
||||
|
||||
left = left + len;
|
||||
count++;
|
||||
|
||||
if (count >= num_words)
|
||||
break;
|
||||
}
|
||||
|
||||
if (use_constraint)
|
||||
{
|
||||
constraint = gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
right_child,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_RIGHT,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
|
||||
constraint);
|
||||
constraint = gtk_constraint_new (NULL,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
GTK_CONSTRAINT_RELATION_EQ,
|
||||
child,
|
||||
GTK_CONSTRAINT_ATTRIBUTE_BOTTOM,
|
||||
1.0,
|
||||
0.0,
|
||||
GTK_CONSTRAINT_STRENGTH_REQUIRED);
|
||||
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (layout),
|
||||
constraint);
|
||||
|
||||
gtk_constraint_layout_add_grid_constraint (GTK_CONSTRAINT_LAYOUT (layout),
|
||||
grid);
|
||||
}
|
||||
|
||||
g_bytes_unref (data);
|
||||
}
|
||||
|
||||
static void
|
||||
words_base_init (WordsBase *self)
|
||||
{
|
||||
read_words (self);
|
||||
}
|
||||
|
||||
static void
|
||||
show_words (GtkWidget *parent)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
GtkWidget *swin;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_transient_for (GTK_WINDOW (window),
|
||||
GTK_WINDOW (gtk_widget_get_root (parent)));
|
||||
gtk_window_set_modal (GTK_WINDOW (window), TRUE);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (header), use_constraints ? "Constraints" : "Grid");
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
|
||||
swin = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
gtk_scrolled_window_set_propagate_natural_width (GTK_SCROLLED_WINDOW (swin), TRUE);
|
||||
gtk_scrolled_window_set_propagate_natural_height (GTK_SCROLLED_WINDOW (swin), TRUE);
|
||||
gtk_widget_set_hexpand (swin, TRUE);
|
||||
gtk_widget_set_vexpand (swin, TRUE);
|
||||
gtk_widget_set_halign (swin, GTK_ALIGN_FILL);
|
||||
gtk_widget_set_valign (swin, GTK_ALIGN_FILL);
|
||||
gtk_container_add (GTK_CONTAINER (box), swin);
|
||||
|
||||
if (use_constraints)
|
||||
grid = g_object_new (WORDS_TYPE_CONSTRAINT, NULL);
|
||||
else
|
||||
grid = g_object_new (WORDS_TYPE_GRID, NULL);
|
||||
|
||||
gtk_widget_set_halign (swin, GTK_ALIGN_START);
|
||||
gtk_widget_set_valign (swin, GTK_ALIGN_START);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (swin), grid);
|
||||
|
||||
button = gtk_button_new_with_label ("Close");
|
||||
gtk_container_add (GTK_CONTAINER (box), button);
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK (gtk_widget_destroy), window);
|
||||
|
||||
gtk_widget_show (window);
|
||||
}
|
||||
|
||||
static void
|
||||
use_constraints_cb (GtkButton *button)
|
||||
{
|
||||
use_constraints = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
|
||||
}
|
||||
|
||||
static void
|
||||
word_count_cb (GtkSpinButton *button)
|
||||
{
|
||||
num_words = gtk_spin_button_get_value_as_int (button);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_constraints4 (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *header, *grid, *button, *label;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_title (GTK_HEADER_BAR (header), "Words");
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
g_object_set (grid,
|
||||
"margin", 12,
|
||||
"row-spacing", 12,
|
||||
"column-spacing", 6,
|
||||
"halign", GTK_ALIGN_FILL,
|
||||
"valign", GTK_ALIGN_FILL,
|
||||
"hexpand", TRUE,
|
||||
"vexpand", TRUE,
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (window), grid);
|
||||
|
||||
label = gtk_label_new ("Constraints:");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 1.0);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
|
||||
button = gtk_check_button_new ();
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (use_constraints_cb), NULL);
|
||||
gtk_grid_attach (GTK_GRID (grid), button, 1, 0, 1, 1);
|
||||
label = gtk_label_new ("Words:");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 1.0);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
|
||||
button = gtk_spin_button_new_with_range (0, 1300, 1);
|
||||
g_signal_connect (button, "value-changed", G_CALLBACK (word_count_cb), NULL);
|
||||
gtk_spin_button_set_value (GTK_SPIN_BUTTON (button), 10);
|
||||
gtk_grid_attach (GTK_GRID (grid), button, 1, 1, 1, 1);
|
||||
|
||||
button = gtk_button_new_with_label ("Show");
|
||||
gtk_widget_set_halign (button, GTK_ALIGN_END);
|
||||
gtk_widget_set_valign (button, GTK_ALIGN_END);
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK (show_words), window);
|
||||
gtk_grid_attach (GTK_GRID (grid), button, 0, 2, 2, 1);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
@@ -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";
|
||||
@@ -50,6 +47,8 @@ css_text_changed (GtkTextBuffer *buffer,
|
||||
text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
|
||||
gtk_css_provider_load_from_data (provider, text, -1);
|
||||
g_free (text);
|
||||
|
||||
gtk_style_context_reset_widgets (gdk_screen_get_default ());
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -28,7 +28,7 @@ struct {
|
||||
{ "Multiply", "multiply" },
|
||||
{ "Normal", "normal" },
|
||||
{ "Overlay", "overlay" },
|
||||
{ "Saturate", "saturation" },
|
||||
{ "Saturate", "saturate" },
|
||||
{ "Screen", "screen" },
|
||||
{ "Soft Light", "soft-light" },
|
||||
{ NULL }
|
||||
@@ -130,9 +130,9 @@ do_css_blendmodes (GtkWidget *do_widget)
|
||||
/* Setup the CSS provider for window */
|
||||
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
|
||||
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
provider,
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
|
||||
provider,
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
|
||||
setup_listbox (builder, provider);
|
||||
}
|
||||
|
@@ -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";
|
||||
@@ -51,6 +47,8 @@ css_text_changed (GtkTextBuffer *buffer,
|
||||
text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
|
||||
gtk_css_provider_load_from_data (provider, text, -1);
|
||||
g_free (text);
|
||||
|
||||
gtk_style_context_reset_widgets (gdk_screen_get_default ());
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -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";
|
||||
@@ -50,6 +46,8 @@ css_text_changed (GtkTextBuffer *buffer,
|
||||
text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
|
||||
gtk_css_provider_load_from_data (provider, text, -1);
|
||||
g_free (text);
|
||||
|
||||
gtk_style_context_reset_widgets (gdk_screen_get_default ());
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -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";
|
||||
@@ -48,6 +45,8 @@ css_text_changed (GtkTextBuffer *buffer,
|
||||
text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
|
||||
gtk_css_provider_load_from_data (provider, text, -1);
|
||||
g_free (text);
|
||||
|
||||
gtk_style_context_reset_widgets (gdk_screen_get_default ());
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -1,44 +1,161 @@
|
||||
/* Cursors
|
||||
*
|
||||
* Demonstrates a useful set of available cursors. The cursors shown here are the ones
|
||||
* defined by CSS, which we assume to be available.
|
||||
*
|
||||
* The example shows creating cursors by name or from an image, with or without a fallback.
|
||||
* Demonstrates a useful set of available cursors.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
static void
|
||||
set_cursor (GtkWidget *button, gpointer data)
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
GdkCursor *cursor = data;
|
||||
GdkWindow *window;
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (button);
|
||||
window = gtk_widget_get_window (toplevel);
|
||||
gdk_window_set_cursor (window, cursor);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
add_section (GtkWidget *box,
|
||||
const gchar *heading)
|
||||
{
|
||||
GtkWidget *label;
|
||||
GtkWidget *section;
|
||||
|
||||
label = gtk_label_new (heading);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
gtk_widget_set_margin_top (label, 10);
|
||||
gtk_widget_set_margin_bottom (label, 10);
|
||||
gtk_box_pack_start (GTK_BOX (box), label);
|
||||
section = gtk_flow_box_new ();
|
||||
gtk_widget_set_halign (section, GTK_ALIGN_START);
|
||||
gtk_flow_box_set_selection_mode (GTK_FLOW_BOX (section), GTK_SELECTION_NONE);
|
||||
gtk_flow_box_set_min_children_per_line (GTK_FLOW_BOX (section), 2);
|
||||
gtk_flow_box_set_max_children_per_line (GTK_FLOW_BOX (section), 20);
|
||||
gtk_box_pack_start (GTK_BOX (box), section);
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
static void
|
||||
on_destroy (gpointer data)
|
||||
add_button (GtkWidget *section,
|
||||
const gchar *css_name)
|
||||
{
|
||||
window = NULL;
|
||||
GtkWidget *image, *button;
|
||||
GdkDisplay *display;
|
||||
GdkCursor *cursor;
|
||||
|
||||
display = gtk_widget_get_display (section);
|
||||
cursor = gdk_cursor_new_from_name (display, css_name);
|
||||
if (cursor == NULL)
|
||||
image = gtk_image_new_from_icon_name ("image-missing", GTK_ICON_SIZE_MENU);
|
||||
else
|
||||
{
|
||||
gchar *path;
|
||||
|
||||
path = g_strdup_printf ("/cursors/%s_cursor.png", css_name);
|
||||
g_strdelimit (path, "-", '_');
|
||||
image = gtk_image_new_from_resource (path);
|
||||
g_free (path);
|
||||
}
|
||||
gtk_widget_set_size_request (image, 32, 32);
|
||||
button = gtk_button_new ();
|
||||
gtk_container_add (GTK_CONTAINER (button), image);
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (button), "image-button");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (set_cursor), cursor);
|
||||
|
||||
gtk_widget_set_tooltip_text (button, css_name);
|
||||
gtk_container_add (GTK_CONTAINER (section), button);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_cursors (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GtkWidget *sw;
|
||||
GtkWidget *box;
|
||||
GtkWidget *section;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Cursors");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 500, 500);
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/cursors/cursors.ui");
|
||||
gtk_builder_connect_signals (builder, NULL);
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (on_destroy), NULL);
|
||||
g_object_set_data_full (G_OBJECT (window), "builder", builder, g_object_unref);
|
||||
G_CALLBACK (gtk_widget_destroyed),
|
||||
&window);
|
||||
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
|
||||
GTK_POLICY_NEVER,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
gtk_container_add (GTK_CONTAINER (window), sw);
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
g_object_set (box,
|
||||
"margin-start", 20,
|
||||
"margin-end", 20,
|
||||
"margin-bottom", 10,
|
||||
NULL);
|
||||
gtk_container_add (GTK_CONTAINER (sw), box);
|
||||
|
||||
section = add_section (box, "General");
|
||||
add_button (section, "default");
|
||||
add_button (section, "none");
|
||||
|
||||
section = add_section (box, "Link & Status");
|
||||
add_button (section, "context-menu");
|
||||
add_button (section, "help");
|
||||
add_button (section, "pointer");
|
||||
add_button (section, "progress");
|
||||
add_button (section, "wait");
|
||||
|
||||
section = add_section (box, "Selection");
|
||||
add_button (section, "cell");
|
||||
add_button (section, "crosshair");
|
||||
add_button (section, "text");
|
||||
add_button (section, "vertical-text");
|
||||
|
||||
section = add_section (box, "Drag & Drop");
|
||||
add_button (section, "alias");
|
||||
add_button (section, "copy");
|
||||
add_button (section, "move");
|
||||
add_button (section, "no-drop");
|
||||
add_button (section, "not-allowed");
|
||||
add_button (section, "grab");
|
||||
add_button (section, "grabbing");
|
||||
|
||||
section = add_section (box, "Resize & Scrolling");
|
||||
add_button (section, "all-scroll");
|
||||
add_button (section, "col-resize");
|
||||
add_button (section, "row-resize");
|
||||
add_button (section, "n-resize");
|
||||
add_button (section, "e-resize");
|
||||
add_button (section, "s-resize");
|
||||
add_button (section, "w-resize");
|
||||
add_button (section, "ne-resize");
|
||||
add_button (section, "nw-resize");
|
||||
add_button (section, "se-resize");
|
||||
add_button (section, "sw-resize");
|
||||
add_button (section, "ew-resize");
|
||||
add_button (section, "ns-resize");
|
||||
add_button (section, "nesw-resize");
|
||||
add_button (section, "nwse-resize");
|
||||
|
||||
section = add_section (box, "Zoom");
|
||||
add_button (section, "zoom-in");
|
||||
add_button (section, "zoom-out");
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
{
|
||||
gtk_widget_destroy (window);
|
||||
}
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
|
||||
return window;
|
||||
}
|
||||
|
BIN
demos/gtk-demo/data/16x16/gtk4-demo-symbolic.symbolic.png
Normal file
After Width: | Height: | Size: 324 B |
BIN
demos/gtk-demo/data/16x16/gtk4-demo.png
Normal file
After Width: | Height: | Size: 874 B |
BIN
demos/gtk-demo/data/22x22/gtk4-demo-symbolic.symbolic.png
Normal file
After Width: | Height: | Size: 437 B |
BIN
demos/gtk-demo/data/22x22/gtk4-demo.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
demos/gtk-demo/data/24x24/gtk4-demo-symbolic.symbolic.png
Normal file
After Width: | Height: | Size: 465 B |
BIN
demos/gtk-demo/data/24x24/gtk4-demo.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
demos/gtk-demo/data/256x256/gtk4-demo-symbolic.symbolic.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
demos/gtk-demo/data/256x256/gtk4-demo.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
demos/gtk-demo/data/32x32/gtk4-demo-symbolic.symbolic.png
Normal file
After Width: | Height: | Size: 581 B |
BIN
demos/gtk-demo/data/32x32/gtk4-demo.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
demos/gtk-demo/data/48x48/gtk4-demo-symbolic.symbolic.png
Normal file
After Width: | Height: | Size: 854 B |
BIN
demos/gtk-demo/data/48x48/gtk4-demo.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
demos/gtk-demo/data/512x512/gtk4-demo-symbolic.symbolic.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
demos/gtk-demo/data/512x512/gtk4-demo.png
Normal file
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 |
2886
demos/gtk-demo/data/source.svg
Normal file
After Width: | Height: | Size: 101 KiB |
29
demos/gtk-demo/data/symbolic-source.svg
Normal 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 |
@@ -12,9 +12,6 @@
|
||||
<gresource prefix="/builder">
|
||||
<file>demo.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/constraints4">
|
||||
<file>words</file>
|
||||
</gresource>
|
||||
<gresource prefix="/css_accordion">
|
||||
<file>css_accordion.css</file>
|
||||
<file>reset.css</file>
|
||||
@@ -40,9 +37,6 @@
|
||||
<gresource prefix="/theming_style_classes">
|
||||
<file>theming.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/themes">
|
||||
<file>themes.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/css_pixbufs">
|
||||
<file alias="gtk.css">css_pixbufs.css</file>
|
||||
<file>cssview.css</file>
|
||||
@@ -63,7 +57,6 @@
|
||||
<file>reset.css</file>
|
||||
</gresource>
|
||||
<gresource prefix="/cursors">
|
||||
<file>cursors.ui</file>
|
||||
<file>alias_cursor.png</file>
|
||||
<file>all_scroll_cursor.png</file>
|
||||
<file>cell_cursor.png</file>
|
||||
@@ -74,7 +67,6 @@
|
||||
<file>default_cursor.png</file>
|
||||
<file>e_resize_cursor.png</file>
|
||||
<file>ew_resize_cursor.png</file>
|
||||
<file>gtk_logo_cursor.png</file>
|
||||
<file>grabbing_cursor.png</file>
|
||||
<file>grab_cursor.png</file>
|
||||
<file>hand_cursor.png</file>
|
||||
@@ -108,8 +100,11 @@
|
||||
<file>gtkfishbowl.h</file>
|
||||
</gresource>
|
||||
<gresource prefix="/iconview">
|
||||
<file>gnome-fs-directory.png</file>
|
||||
<file>gnome-fs-regular.png</file>
|
||||
<file preprocess="to-pixdata">gnome-fs-directory.png</file>
|
||||
<file preprocess="to-pixdata">gnome-fs-regular.png</file>
|
||||
</gresource>
|
||||
<gresource prefix="/stack">
|
||||
<file>stack.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/shortcuts">
|
||||
<file>shortcuts.ui</file>
|
||||
@@ -118,21 +113,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>
|
||||
@@ -149,14 +135,11 @@
|
||||
<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>
|
||||
<file>combobox.c</file>
|
||||
<file>constraints.c</file>
|
||||
<file>constraints2.c</file>
|
||||
<file>constraints3.c</file>
|
||||
<file>constraints4.c</file>
|
||||
<file>css_accordion.c</file>
|
||||
<file>css_basics.c</file>
|
||||
<file>css_blendmodes.c</file>
|
||||
@@ -166,18 +149,17 @@
|
||||
<file>cursors.c</file>
|
||||
<file>dialog.c</file>
|
||||
<file>drawingarea.c</file>
|
||||
<file>dnd.c</file>
|
||||
<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>
|
||||
<file>fontplane.c</file>
|
||||
<file>gestures.c</file>
|
||||
<file>glarea.c</file>
|
||||
<file>headerbar.c</file>
|
||||
@@ -194,13 +176,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>
|
||||
@@ -213,27 +190,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>themes.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>
|
||||
@@ -250,7 +221,6 @@
|
||||
</gresource>
|
||||
<gresource prefix="/font_features">
|
||||
<file>font-features.ui</file>
|
||||
<file>fontplane.c</file>
|
||||
</gresource>
|
||||
<gresource prefix="/spinbutton">
|
||||
<file>spinbutton.ui</file>
|
||||
@@ -262,10 +232,6 @@
|
||||
<file>decor1.png</file>
|
||||
<file>decor2.png</file>
|
||||
</gresource>
|
||||
<gresource prefix="/transparent">
|
||||
<file>portland-rose.jpg</file>
|
||||
<file>bluroverlay.c</file>
|
||||
</gresource>
|
||||
<gresource prefix="/markup">
|
||||
<file>markup.txt</file>
|
||||
</gresource>
|
||||
@@ -275,33 +241,4 @@
|
||||
<gresource prefix="/modelbutton">
|
||||
<file>modelbutton.ui</file>
|
||||
</gresource>
|
||||
<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>
|
||||
|
@@ -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>
|
||||
|
@@ -1,489 +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);
|
||||
|
||||
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 (GtkGestureClick *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;
|
||||
|
||||
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_click_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;
|
||||
}
|
@@ -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__ */
|
@@ -56,20 +56,19 @@ 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);
|
||||
image = gtk_image_new_from_icon_name ("dialog-question", GTK_ICON_SIZE_DIALOG);
|
||||
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 +76,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 +84,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);
|
||||
@@ -106,8 +105,8 @@ do_dialog (GtkWidget *do_widget)
|
||||
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_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Dialogs and Message Boxes");
|
||||
|
||||
g_signal_connect (window, "destroy",
|
||||
@@ -123,29 +122,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);
|
||||
|
@@ -1,378 +0,0 @@
|
||||
/* Drag-and-Drop
|
||||
*
|
||||
* I can't believe its not glade!
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct _GtkDemoWidget GtkDemoWidget;
|
||||
struct _GtkDemoWidget
|
||||
{
|
||||
GType type;
|
||||
union {
|
||||
char *text;
|
||||
gboolean active;
|
||||
};
|
||||
};
|
||||
|
||||
static gpointer
|
||||
copy_demo_widget (gpointer data)
|
||||
{
|
||||
GtkDemoWidget *demo = g_memdup (data, sizeof (GtkDemoWidget));
|
||||
|
||||
if (demo->type == GTK_TYPE_LABEL)
|
||||
demo->text = g_strdup (demo->text);
|
||||
|
||||
return demo;
|
||||
}
|
||||
|
||||
static void
|
||||
free_demo_widget (gpointer data)
|
||||
{
|
||||
GtkDemoWidget *demo = data;
|
||||
|
||||
if (demo->type == GTK_TYPE_LABEL)
|
||||
g_free (demo->text);
|
||||
|
||||
g_free (demo);
|
||||
}
|
||||
|
||||
#define GTK_TYPE_DEMO_WIDGET (gtk_demo_widget_get_type ())
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GtkDemoWidget, gtk_demo_widget, copy_demo_widget, free_demo_widget)
|
||||
|
||||
static GtkDemoWidget *
|
||||
serialize_widget (GtkWidget *widget)
|
||||
{
|
||||
GtkDemoWidget *demo;
|
||||
|
||||
demo = g_new0 (GtkDemoWidget, 1);
|
||||
demo->type = G_OBJECT_TYPE (widget);
|
||||
|
||||
if (GTK_IS_LABEL (widget))
|
||||
{
|
||||
demo->text = g_strdup (gtk_label_get_text (GTK_LABEL (widget)));
|
||||
}
|
||||
else if (GTK_IS_SPINNER (widget))
|
||||
{
|
||||
g_object_get (widget, "active", &demo->active, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_print ("Type %s not supported\n", g_type_name (demo->type));
|
||||
}
|
||||
|
||||
return demo;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
deserialize_widget (GtkDemoWidget *demo)
|
||||
{
|
||||
GtkWidget *widget = NULL;
|
||||
|
||||
if (demo->type == GTK_TYPE_LABEL)
|
||||
{
|
||||
widget = gtk_label_new (demo->text);
|
||||
}
|
||||
else if (demo->type == GTK_TYPE_SPINNER)
|
||||
{
|
||||
widget = g_object_new (demo->type, "active", demo->active, NULL);
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (widget), "demo");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_print ("Type %s not supported\n", g_type_name (demo->type));
|
||||
}
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
static double pos_x, pos_y;
|
||||
|
||||
static void
|
||||
new_label_cb (GtkMenuItem *item,
|
||||
gpointer data)
|
||||
{
|
||||
GtkFixed *fixed = data;
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = gtk_label_new ("Label");
|
||||
gtk_fixed_put (fixed, widget, pos_x, pos_y);
|
||||
}
|
||||
|
||||
static void
|
||||
new_spinner_cb (GtkMenuItem *item,
|
||||
gpointer data)
|
||||
{
|
||||
GtkFixed *fixed = data;
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = gtk_spinner_new ();
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (widget), "demo");
|
||||
gtk_spinner_start (GTK_SPINNER (widget));
|
||||
gtk_fixed_put (fixed, widget, pos_x, pos_y);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_cb (GtkWidget *child)
|
||||
{
|
||||
GdkClipboard *clipboard;
|
||||
GtkDemoWidget *demo;
|
||||
|
||||
g_print ("Copy %s\n", G_OBJECT_TYPE_NAME (child));
|
||||
|
||||
demo = serialize_widget (child);
|
||||
|
||||
clipboard = gdk_display_get_clipboard (gdk_display_get_default ());
|
||||
gdk_clipboard_set (clipboard, GTK_TYPE_DEMO_WIDGET, demo);
|
||||
}
|
||||
|
||||
static void
|
||||
delete_cb (GtkWidget *child)
|
||||
{
|
||||
gtk_widget_destroy (child);
|
||||
}
|
||||
|
||||
static void
|
||||
cut_cb (GtkWidget *child)
|
||||
{
|
||||
copy_cb (child);
|
||||
delete_cb (child);
|
||||
}
|
||||
|
||||
static void
|
||||
value_read (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
GdkClipboard *clipboard = GDK_CLIPBOARD (source);
|
||||
GError *error = NULL;
|
||||
const GValue *value;
|
||||
GtkDemoWidget *demo;
|
||||
GtkWidget *widget = NULL;
|
||||
|
||||
value = gdk_clipboard_read_value_finish (clipboard, res, &error);
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
g_print ("error: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!G_VALUE_HOLDS (value, GTK_TYPE_DEMO_WIDGET))
|
||||
{
|
||||
g_print ("can't handle clipboard contents\n");
|
||||
return;
|
||||
}
|
||||
|
||||
demo = g_value_get_boxed (value);
|
||||
widget = deserialize_widget (demo);
|
||||
|
||||
gtk_fixed_put (GTK_FIXED (data), widget, pos_x, pos_y);
|
||||
}
|
||||
|
||||
static void
|
||||
paste_cb (GtkWidget *fixed)
|
||||
{
|
||||
GdkClipboard *clipboard;
|
||||
|
||||
clipboard = gdk_display_get_clipboard (gdk_display_get_default ());
|
||||
if (gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), GTK_TYPE_DEMO_WIDGET))
|
||||
{
|
||||
g_print ("Paste %s\n", g_type_name (GTK_TYPE_DEMO_WIDGET));
|
||||
gdk_clipboard_read_value_async (clipboard, GTK_TYPE_DEMO_WIDGET, 0, NULL, value_read, fixed);
|
||||
}
|
||||
else
|
||||
g_print ("Don't know how to handle clipboard contents\n");
|
||||
}
|
||||
|
||||
static void
|
||||
edit_label_done (GtkWidget *entry, gpointer data)
|
||||
{
|
||||
GtkWidget *fixed = gtk_widget_get_parent (entry);
|
||||
GtkWidget *label;
|
||||
int x, y;
|
||||
|
||||
gtk_fixed_get_child_position (GTK_FIXED (fixed), entry, &x, &y);
|
||||
|
||||
label = GTK_WIDGET (g_object_get_data (G_OBJECT (entry), "label"));
|
||||
gtk_label_set_text (GTK_LABEL (label), gtk_editable_get_text (GTK_EDITABLE (entry)));
|
||||
|
||||
gtk_widget_destroy (entry);
|
||||
}
|
||||
|
||||
static void
|
||||
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);
|
||||
|
||||
if (GTK_IS_LABEL (child))
|
||||
{
|
||||
GtkWidget *entry = gtk_entry_new ();
|
||||
|
||||
g_object_set_data (G_OBJECT (entry), "label", child);
|
||||
|
||||
gtk_editable_set_text (GTK_EDITABLE (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);
|
||||
}
|
||||
else if (GTK_IS_SPINNER (child))
|
||||
{
|
||||
gboolean active;
|
||||
|
||||
g_object_get (child, "active", &active, NULL);
|
||||
g_object_set (child, "active", !active, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pressed_cb (GtkGesture *gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkWidget *child;
|
||||
|
||||
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
|
||||
child = gtk_widget_pick (widget, x, y, GTK_PICK_DEFAULT);
|
||||
|
||||
if (gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)) == GDK_BUTTON_SECONDARY)
|
||||
{
|
||||
GdkRectangle rect;
|
||||
GtkWidget *menu;
|
||||
GtkWidget *item;
|
||||
GdkClipboard *clipboard;
|
||||
|
||||
pos_x = x;
|
||||
pos_y = y;
|
||||
|
||||
menu = gtk_menu_new ();
|
||||
item = gtk_menu_item_new_with_label ("New Label");
|
||||
g_signal_connect (item, "activate", G_CALLBACK (new_label_cb), widget);
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
item = gtk_menu_item_new_with_label ("New Spinner");
|
||||
g_signal_connect (item, "activate", G_CALLBACK (new_spinner_cb), widget);
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
|
||||
item = gtk_separator_menu_item_new ();
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
|
||||
item = gtk_menu_item_new_with_label ("Edit");
|
||||
gtk_widget_set_sensitive (item, child != NULL && child != widget);
|
||||
g_signal_connect_swapped (item, "activate", G_CALLBACK (edit_cb), child);
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
|
||||
item = gtk_separator_menu_item_new ();
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
|
||||
item = gtk_menu_item_new_with_label ("Cut");
|
||||
gtk_widget_set_sensitive (item, child != NULL && child != widget);
|
||||
g_signal_connect_swapped (item, "activate", G_CALLBACK (cut_cb), child);
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
item = gtk_menu_item_new_with_label ("Copy");
|
||||
gtk_widget_set_sensitive (item, child != NULL && child != widget);
|
||||
g_signal_connect_swapped (item, "activate", G_CALLBACK (copy_cb), child);
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
item = gtk_menu_item_new_with_label ("Paste");
|
||||
clipboard = gdk_display_get_clipboard (gdk_display_get_default ());
|
||||
gtk_widget_set_sensitive (item,
|
||||
gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), GTK_TYPE_DEMO_WIDGET));
|
||||
g_signal_connect_swapped (item, "activate", G_CALLBACK (paste_cb), widget);
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
item = gtk_menu_item_new_with_label ("Delete");
|
||||
gtk_widget_set_sensitive (item, child != NULL && child != widget);
|
||||
g_signal_connect_swapped (item, "activate", G_CALLBACK (delete_cb), child);
|
||||
gtk_container_add (GTK_CONTAINER (menu), item);
|
||||
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
rect.width = 0;
|
||||
rect.height = 0;
|
||||
|
||||
gtk_menu_popup_at_rect (GTK_MENU (menu),
|
||||
gtk_native_get_surface (gtk_widget_get_native (widget)),
|
||||
&rect,
|
||||
GDK_GRAVITY_NORTH_WEST,
|
||||
GDK_GRAVITY_NORTH_WEST,
|
||||
NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
released_cb (GtkGesture *gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkWidget *child;
|
||||
|
||||
widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
|
||||
child = gtk_widget_pick (widget, x, y, 0);
|
||||
|
||||
if (gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)) == GDK_BUTTON_PRIMARY)
|
||||
{
|
||||
if (child != NULL && child != widget)
|
||||
edit_cb (child);
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_dnd (GtkWidget *do_widget)
|
||||
{
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *vbox, *fixed;
|
||||
GtkGesture *multipress;
|
||||
GtkCssProvider *provider;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Drag-and-drop");
|
||||
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
fixed = gtk_fixed_new ();
|
||||
gtk_container_add (GTK_CONTAINER (vbox), fixed);
|
||||
gtk_widget_set_hexpand (fixed, TRUE);
|
||||
gtk_widget_set_vexpand (fixed, TRUE);
|
||||
|
||||
multipress = gtk_gesture_click_new ();
|
||||
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");
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
800);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
return window;
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
spinner.demo {
|
||||
opacity: 1;
|
||||
}
|
@@ -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
|
||||
@@ -20,17 +20,22 @@ static GtkWidget *window = NULL;
|
||||
static cairo_surface_t *surface = NULL;
|
||||
|
||||
/* Create a new surface of the appropriate size to store our scribbles */
|
||||
static void
|
||||
create_surface (GtkWidget *widget)
|
||||
static gboolean
|
||||
scribble_configure_event (GtkWidget *widget,
|
||||
GdkEventConfigure *event,
|
||||
gpointer data)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
cairo_t *cr;
|
||||
|
||||
if (surface)
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
gtk_widget_get_width (widget),
|
||||
gtk_widget_get_height (widget));
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
|
||||
CAIRO_CONTENT_COLOR,
|
||||
allocation.width,
|
||||
allocation.height);
|
||||
|
||||
/* Initialize the surface to white */
|
||||
cr = cairo_create (surface);
|
||||
@@ -39,12 +44,9 @@ create_surface (GtkWidget *widget)
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
scribble_size_allocate (GtkWidget *widget)
|
||||
{
|
||||
create_surface (widget);
|
||||
/* We've handled the configure event, no need for further processing. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Redraw the screen from the surface */
|
||||
@@ -68,11 +70,6 @@ draw_brush (GtkWidget *widget,
|
||||
GdkRectangle update_rect;
|
||||
cairo_t *cr;
|
||||
|
||||
if (surface == NULL ||
|
||||
cairo_image_surface_get_width (surface) != gtk_widget_get_width (widget) ||
|
||||
cairo_image_surface_get_height (surface) != gtk_widget_get_height (widget))
|
||||
create_surface (widget);
|
||||
|
||||
update_rect.x = x - 3;
|
||||
update_rect.y = y - 3;
|
||||
update_rect.width = 6;
|
||||
@@ -86,41 +83,66 @@ draw_brush (GtkWidget *widget,
|
||||
|
||||
cairo_destroy (cr);
|
||||
|
||||
gtk_widget_queue_draw (widget);
|
||||
/* Now invalidate the affected region of the drawing area. */
|
||||
gdk_window_invalidate_rect (gtk_widget_get_window (widget),
|
||||
&update_rect,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
static double start_x;
|
||||
static double start_y;
|
||||
|
||||
static void
|
||||
drag_begin (GtkGestureDrag *gesture,
|
||||
double x,
|
||||
double y,
|
||||
GtkWidget *area)
|
||||
static gboolean
|
||||
scribble_button_press_event (GtkWidget *widget,
|
||||
GdkEventButton *event,
|
||||
gpointer data)
|
||||
{
|
||||
start_x = x;
|
||||
start_y = y;
|
||||
double x, y;
|
||||
guint button;
|
||||
|
||||
draw_brush (area, x, y);
|
||||
if (surface == NULL)
|
||||
return FALSE; /* paranoia check, in case we haven't gotten a configure event */
|
||||
|
||||
gdk_event_get_button ((GdkEvent *)event, &button);
|
||||
gdk_event_get_coords ((GdkEvent *)event, &x, &y);
|
||||
|
||||
if (button == GDK_BUTTON_PRIMARY)
|
||||
draw_brush (widget, x, y);
|
||||
|
||||
/* We've handled the event, stop processing */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
drag_update (GtkGestureDrag *gesture,
|
||||
double x,
|
||||
double y,
|
||||
GtkWidget *area)
|
||||
static gboolean
|
||||
scribble_motion_notify_event (GtkWidget *widget,
|
||||
GdkEventMotion *event,
|
||||
gpointer data)
|
||||
{
|
||||
draw_brush (area, start_x + x, start_y + y);
|
||||
int x, y;
|
||||
GdkModifierType state;
|
||||
|
||||
if (surface == NULL)
|
||||
return FALSE; /* paranoia check, in case we haven't gotten a configure event */
|
||||
|
||||
/* This call is very important; it requests the next motion event.
|
||||
* If you don't call gdk_window_get_pointer() you'll only get
|
||||
* a single motion event. The reason is that we specified
|
||||
* GDK_POINTER_MOTION_HINT_MASK to gtk_widget_set_events().
|
||||
* If we hadn't specified that, we could just use event->x, event->y
|
||||
* as the pointer location. But we'd also get deluged in events.
|
||||
* By requesting the next event as we handle the current one,
|
||||
* we avoid getting a huge number of events faster than we
|
||||
* can cope.
|
||||
*/
|
||||
|
||||
gdk_window_get_device_position (gdk_event_get_window ((GdkEvent *) event),
|
||||
gdk_event_get_device ((GdkEvent *) event),
|
||||
&x, &y, &state);
|
||||
|
||||
if (state & GDK_BUTTON1_MASK)
|
||||
draw_brush (widget, x, y);
|
||||
|
||||
/* We've handled it, stop processing */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
drag_end (GtkGestureDrag *gesture,
|
||||
double x,
|
||||
double y,
|
||||
GtkWidget *area)
|
||||
{
|
||||
draw_brush (area, start_x + x, start_y + y);
|
||||
}
|
||||
|
||||
static void
|
||||
checkerboard_draw (GtkDrawingArea *da,
|
||||
@@ -137,7 +159,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.
|
||||
*/
|
||||
|
||||
@@ -185,13 +207,12 @@ do_drawingarea (GtkWidget *do_widget)
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *da;
|
||||
GtkWidget *label;
|
||||
GtkGesture *drag;
|
||||
|
||||
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_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Drawing Area");
|
||||
|
||||
g_signal_connect (window, "destroy",
|
||||
@@ -208,12 +229,11 @@ 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 +248,11 @@ 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);
|
||||
@@ -241,17 +260,17 @@ do_drawingarea (GtkWidget *do_widget)
|
||||
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), scribble_draw, NULL, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (frame), da);
|
||||
|
||||
g_signal_connect (da, "size-allocate",
|
||||
G_CALLBACK (scribble_size_allocate), NULL);
|
||||
/* Signals used to handle backing surface */
|
||||
|
||||
drag = gtk_gesture_drag_new ();
|
||||
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (drag), GDK_BUTTON_PRIMARY);
|
||||
gtk_widget_add_controller (da, GTK_EVENT_CONTROLLER (drag));
|
||||
g_signal_connect (da,"configure-event",
|
||||
G_CALLBACK (scribble_configure_event), NULL);
|
||||
|
||||
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);
|
||||
/* Event signals */
|
||||
|
||||
g_signal_connect (da, "motion-notify-event",
|
||||
G_CALLBACK (scribble_motion_notify_event), NULL);
|
||||
g_signal_connect (da, "button-press-event",
|
||||
G_CALLBACK (scribble_button_press_event), NULL);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
@@ -346,8 +346,8 @@ do_editable_cells (GtkWidget *do_widget)
|
||||
GtkTreeModel *numbers_model;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Editable Cells");
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
@@ -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 ();
|
||||
@@ -373,7 +373,6 @@ do_editable_cells (GtkWidget *do_widget)
|
||||
|
||||
/* create tree view */
|
||||
treeview = gtk_tree_view_new_with_model (items_model);
|
||||
gtk_widget_set_vexpand (treeview, TRUE);
|
||||
gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
|
||||
GTK_SELECTION_SINGLE);
|
||||
|
||||
@@ -387,17 +386,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);
|
||||
}
|
||||
|
@@ -20,8 +20,8 @@ do_entry_buffer (GtkWidget *do_widget)
|
||||
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_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Entry Buffer");
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
g_signal_connect (window, "destroy",
|
||||
@@ -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);
|
||||
}
|
||||
|
@@ -46,8 +46,8 @@ do_entry_completion (GtkWidget *do_widget)
|
||||
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_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Entry Completion");
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
|
||||
@@ -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
demos/gtk-demo/event_axes.c
Normal 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;
|
||||
}
|
@@ -31,14 +31,13 @@ do_expander (GtkWidget *do_widget)
|
||||
GtkWidget *toplevel;
|
||||
GtkWidget *area;
|
||||
GtkWidget *expander;
|
||||
GtkWidget *label;
|
||||
GtkWidget *sw;
|
||||
GtkWidget *tv;
|
||||
GtkTextBuffer *buffer;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
toplevel = GTK_WIDGET (gtk_widget_get_root (do_widget));
|
||||
toplevel = gtk_widget_get_toplevel (do_widget);
|
||||
window = gtk_message_dialog_new_with_markup (GTK_WINDOW (toplevel),
|
||||
0,
|
||||
GTK_MESSAGE_ERROR,
|
||||
@@ -51,19 +50,13 @@ do_expander (GtkWidget *do_widget)
|
||||
|
||||
area = gtk_message_dialog_get_message_area (GTK_MESSAGE_DIALOG (window));
|
||||
|
||||
label = gtk_widget_get_last_child (area);
|
||||
gtk_label_set_line_wrap (GTK_LABEL (label), FALSE);
|
||||
gtk_widget_set_vexpand (label, FALSE);
|
||||
|
||||
expander = gtk_expander_new ("Details:");
|
||||
gtk_widget_set_vexpand (expander, TRUE);
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (sw), 100);
|
||||
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
|
||||
GTK_POLICY_NEVER,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
gtk_scrolled_window_set_propagate_natural_height (GTK_SCROLLED_WINDOW (sw), TRUE);
|
||||
|
||||
tv = gtk_text_view_new ();
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));
|
||||
@@ -80,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);
|
||||
|
||||
|
@@ -124,8 +124,8 @@ do_filtermodel (GtkWidget *do_widget)
|
||||
builder = gtk_builder_new_from_resource ("/filtermodel/filtermodel.ui");
|
||||
gtk_builder_connect_signals (builder, NULL);
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
|
@@ -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>
|
||||
|
@@ -8,304 +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 void
|
||||
mapped (GtkWidget *w)
|
||||
{
|
||||
gtk_menu_button_popup (GTK_MENU_BUTTON (w));
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_menu_button (void)
|
||||
{
|
||||
GtkWidget *w = gtk_menu_button_new ();
|
||||
GtkWidget *popover = gtk_popover_new (NULL);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (popover), gtk_button_new_with_label ("Hey!"));
|
||||
gtk_popover_set_autohide (GTK_POPOVER (popover), FALSE);
|
||||
gtk_menu_button_set_popover (GTK_MENU_BUTTON (w), popover);
|
||||
g_signal_connect (w, "map", G_CALLBACK (mapped), NULL);
|
||||
|
||||
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 },
|
||||
{ "Menubutton", create_menu_button },
|
||||
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 (gtk_widget_get_root (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]);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
if (suggested_change)
|
||||
*suggested_change = 0;
|
||||
}
|
||||
|
||||
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
|
||||
next_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 >= N_WIDGET_TYPES)
|
||||
new_index = 0;
|
||||
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));
|
||||
}
|
||||
|
||||
void
|
||||
prev_button_clicked_cb (GtkButton *source,
|
||||
gpointer user_data)
|
||||
static gboolean
|
||||
move_fish (GtkWidget *bowl,
|
||||
GdkFrameClock *frame_clock,
|
||||
gpointer info_label)
|
||||
{
|
||||
GtkFishbowl *fishbowl = user_data;
|
||||
int new_index;
|
||||
gint suggested_change = 0;
|
||||
|
||||
do_stats (bowl,
|
||||
info_label,
|
||||
!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (allow_changes)) ? &suggested_change : NULL);
|
||||
|
||||
if (selected_widget_type - 1 < 0)
|
||||
new_index = N_WIDGET_TYPES - 1;
|
||||
else
|
||||
new_index = selected_widget_type - 1;
|
||||
gtk_fishbowl_set_count (GTK_FISHBOWL (bowl),
|
||||
gtk_fishbowl_get_count (GTK_FISHBOWL (bowl)) + suggested_change);
|
||||
stats_update (bowl);
|
||||
|
||||
set_widget_type (fishbowl, new_index);
|
||||
}
|
||||
|
||||
void
|
||||
changes_toggled_cb (GtkToggleButton *button,
|
||||
gpointer user_data)
|
||||
{
|
||||
if (gtk_toggle_button_get_active (button))
|
||||
gtk_button_set_icon_name (GTK_BUTTON (button), "changes-prevent");
|
||||
else
|
||||
gtk_button_set_icon_name (GTK_BUTTON (button), "changes-allow");
|
||||
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),
|
||||
"changes_toggled_cb", G_CALLBACK (changes_toggled_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_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
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_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (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))
|
||||
@@ -313,5 +174,6 @@ do_fishbowl (GtkWidget *do_widget)
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
|
||||
|
||||
return window;
|
||||
}
|
||||
|
@@ -1,57 +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>
|
||||
<property name="default-width">400</property>
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="show-close-button">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-string"/>
|
||||
</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="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>
|
||||
<signal name="notify::active" handler="changes_toggled_cb"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack_type">end</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="changes_prevent">
|
||||
<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>
|
||||
@@ -59,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 | sync-create"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@@ -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;
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -720,8 +720,8 @@ do_flowbox (GtkWidget *do_widget)
|
||||
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_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Flow Box");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
|
||||
|
||||
|
@@ -1,314 +0,0 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2012 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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 "fontplane.h"
|
||||
|
||||
#include "gtk.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_WEIGHT_ADJUSTMENT,
|
||||
PROP_WIDTH_ADJUSTMENT
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkFontPlane, gtk_font_plane, GTK_TYPE_WIDGET)
|
||||
|
||||
static double
|
||||
adjustment_get_normalized_value (GtkAdjustment *adj)
|
||||
{
|
||||
return (gtk_adjustment_get_value (adj) - gtk_adjustment_get_lower (adj)) /
|
||||
(gtk_adjustment_get_upper (adj) - gtk_adjustment_get_lower (adj));
|
||||
}
|
||||
|
||||
static void
|
||||
val_to_xy (GtkFontPlane *plane,
|
||||
gint *x,
|
||||
gint *y)
|
||||
{
|
||||
gdouble u, v;
|
||||
gint width, height;
|
||||
|
||||
width = gtk_widget_get_allocated_width (GTK_WIDGET (plane));
|
||||
height = gtk_widget_get_allocated_height (GTK_WIDGET (plane));
|
||||
|
||||
u = adjustment_get_normalized_value (plane->width_adj);
|
||||
v = adjustment_get_normalized_value (plane->weight_adj);
|
||||
|
||||
*x = CLAMP (width * u, 0, width - 1);
|
||||
*y = CLAMP (height * (1 - v), 0, height - 1);
|
||||
}
|
||||
|
||||
static void
|
||||
plane_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
GtkFontPlane *plane = GTK_FONT_PLANE (widget);
|
||||
gint x, y;
|
||||
gint width, height;
|
||||
cairo_t *cr;
|
||||
|
||||
val_to_xy (plane, &x, &y);
|
||||
width = gtk_widget_get_allocated_width (widget);
|
||||
height = gtk_widget_get_allocated_height (widget);
|
||||
|
||||
cr = gtk_snapshot_append_cairo (snapshot,
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_rectangle (cr, 0, 0, width, height);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_move_to (cr, 0, y + 0.5);
|
||||
cairo_line_to (cr, width, y + 0.5);
|
||||
|
||||
cairo_move_to (cr, x + 0.5, 0);
|
||||
cairo_line_to (cr, x + 0.5, height);
|
||||
|
||||
if (gtk_widget_has_visible_focus (widget))
|
||||
{
|
||||
cairo_set_line_width (cr, 3.0);
|
||||
cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.6);
|
||||
cairo_stroke_preserve (cr);
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.8);
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
cairo_set_source_rgba (cr, 0.8, 0.8, 0.8, 0.8);
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
set_cross_cursor (GtkWidget *widget,
|
||||
gboolean enabled)
|
||||
{
|
||||
if (enabled)
|
||||
gtk_widget_set_cursor_from_name (widget, "crosshair");
|
||||
else
|
||||
gtk_widget_set_cursor (widget, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
adj_changed (GtkFontPlane *plane)
|
||||
{
|
||||
gtk_widget_queue_draw (GTK_WIDGET (plane));
|
||||
}
|
||||
|
||||
static void
|
||||
adjustment_set_normalized_value (GtkAdjustment *adj,
|
||||
double val)
|
||||
{
|
||||
gtk_adjustment_set_value (adj,
|
||||
gtk_adjustment_get_lower (adj) +
|
||||
val * (gtk_adjustment_get_upper (adj) - gtk_adjustment_get_lower (adj)));
|
||||
}
|
||||
|
||||
static void
|
||||
update_value (GtkFontPlane *plane,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (plane);
|
||||
gdouble u, v;
|
||||
|
||||
u = CLAMP (x * (1.0 / gtk_widget_get_allocated_width (widget)), 0, 1);
|
||||
v = CLAMP (1 - y * (1.0 / gtk_widget_get_allocated_height (widget)), 0, 1);
|
||||
|
||||
adjustment_set_normalized_value (plane->width_adj, u);
|
||||
adjustment_set_normalized_value (plane->weight_adj, v);
|
||||
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
hold_action (GtkGestureLongPress *gesture,
|
||||
gdouble x,
|
||||
gdouble y,
|
||||
GtkFontPlane *plane)
|
||||
{
|
||||
gboolean handled;
|
||||
|
||||
g_signal_emit_by_name (plane, "popup-menu", &handled);
|
||||
}
|
||||
|
||||
static void
|
||||
plane_drag_gesture_begin (GtkGestureDrag *gesture,
|
||||
gdouble start_x,
|
||||
gdouble start_y,
|
||||
GtkFontPlane *plane)
|
||||
{
|
||||
guint button;
|
||||
|
||||
button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
|
||||
|
||||
if (button == GDK_BUTTON_SECONDARY)
|
||||
{
|
||||
gboolean handled;
|
||||
|
||||
g_signal_emit_by_name (plane, "popup-menu", &handled);
|
||||
}
|
||||
|
||||
if (button != GDK_BUTTON_PRIMARY)
|
||||
{
|
||||
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
set_cross_cursor (GTK_WIDGET (plane), TRUE);
|
||||
update_value (plane, start_x, start_y);
|
||||
gtk_widget_grab_focus (GTK_WIDGET (plane));
|
||||
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
|
||||
}
|
||||
|
||||
static void
|
||||
plane_drag_gesture_update (GtkGestureDrag *gesture,
|
||||
gdouble offset_x,
|
||||
gdouble offset_y,
|
||||
GtkFontPlane *plane)
|
||||
{
|
||||
gdouble start_x, start_y;
|
||||
|
||||
gtk_gesture_drag_get_start_point (GTK_GESTURE_DRAG (gesture),
|
||||
&start_x, &start_y);
|
||||
update_value (plane, start_x + offset_x, start_y + offset_y);
|
||||
}
|
||||
|
||||
static void
|
||||
plane_drag_gesture_end (GtkGestureDrag *gesture,
|
||||
gdouble offset_x,
|
||||
gdouble offset_y,
|
||||
GtkFontPlane *plane)
|
||||
{
|
||||
set_cross_cursor (GTK_WIDGET (plane), FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_font_plane_init (GtkFontPlane *plane)
|
||||
{
|
||||
GtkGesture *gesture;
|
||||
|
||||
gtk_widget_set_can_focus (GTK_WIDGET (plane), TRUE);
|
||||
|
||||
gesture = gtk_gesture_drag_new ();
|
||||
g_signal_connect (gesture, "drag-begin",
|
||||
G_CALLBACK (plane_drag_gesture_begin), plane);
|
||||
g_signal_connect (gesture, "drag-update",
|
||||
G_CALLBACK (plane_drag_gesture_update), plane);
|
||||
g_signal_connect (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));
|
||||
|
||||
gesture = gtk_gesture_long_press_new ();
|
||||
g_signal_connect (gesture, "pressed",
|
||||
G_CALLBACK (hold_action), plane);
|
||||
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture),
|
||||
TRUE);
|
||||
gtk_widget_add_controller (GTK_WIDGET (plane), GTK_EVENT_CONTROLLER (gesture));
|
||||
}
|
||||
|
||||
static void
|
||||
plane_finalize (GObject *object)
|
||||
{
|
||||
GtkFontPlane *plane = GTK_FONT_PLANE (object);
|
||||
|
||||
g_clear_object (&plane->weight_adj);
|
||||
g_clear_object (&plane->width_adj);
|
||||
|
||||
G_OBJECT_CLASS (gtk_font_plane_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
plane_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFontPlane *plane = GTK_FONT_PLANE (object);
|
||||
GtkAdjustment *adjustment;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_WEIGHT_ADJUSTMENT:
|
||||
adjustment = GTK_ADJUSTMENT (g_value_get_object (value));
|
||||
if (adjustment)
|
||||
{
|
||||
plane->weight_adj = g_object_ref_sink (adjustment);
|
||||
g_signal_connect_swapped (adjustment, "value-changed", G_CALLBACK (adj_changed), plane);
|
||||
}
|
||||
break;
|
||||
case PROP_WIDTH_ADJUSTMENT:
|
||||
adjustment = GTK_ADJUSTMENT (g_value_get_object (value));
|
||||
if (adjustment)
|
||||
{
|
||||
plane->width_adj = g_object_ref_sink (adjustment);
|
||||
g_signal_connect_swapped (adjustment, "value-changed", G_CALLBACK (adj_changed), plane);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_font_plane_class_init (GtkFontPlaneClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
object_class->finalize = plane_finalize;
|
||||
object_class->set_property = plane_set_property;
|
||||
|
||||
widget_class->snapshot = plane_snapshot;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_WEIGHT_ADJUSTMENT,
|
||||
g_param_spec_object ("weight-adjustment",
|
||||
NULL,
|
||||
NULL,
|
||||
GTK_TYPE_ADJUSTMENT,
|
||||
G_PARAM_WRITABLE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_WIDTH_ADJUSTMENT,
|
||||
g_param_spec_object ("width-adjustment",
|
||||
NULL,
|
||||
NULL,
|
||||
GTK_TYPE_ADJUSTMENT,
|
||||
G_PARAM_WRITABLE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_font_plane_new (GtkAdjustment *weight_adj,
|
||||
GtkAdjustment *width_adj)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_FONT_PLANE,
|
||||
"weight-adjustment", weight_adj,
|
||||
"width-adjustment", width_adj,
|
||||
NULL);
|
||||
}
|
@@ -1,64 +0,0 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2012 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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 __GTK_FONT_PLANE_H__
|
||||
#define __GTK_FONT_PLANE_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_FONT_PLANE (gtk_font_plane_get_type ())
|
||||
#define GTK_FONT_PLANE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FONT_PLANE, GtkFontPlane))
|
||||
#define GTK_FONT_PLANE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FONT_PLANE, GtkFontPlaneClass))
|
||||
#define GTK_IS_FONT_PLANE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_COLOR_PLANE))
|
||||
#define GTK_IS_FONT_PLANE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_COLOR_PLANE))
|
||||
#define GTK_FONT_PLANE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FONT_PLANE, GtkFontPlaneClass))
|
||||
|
||||
|
||||
typedef struct _GtkFontPlane GtkFontPlane;
|
||||
typedef struct _GtkFontPlaneClass GtkFontPlaneClass;
|
||||
|
||||
struct _GtkFontPlane
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkAdjustment *weight_adj;
|
||||
GtkAdjustment *width_adj;
|
||||
|
||||
GtkGesture *drag_gesture;
|
||||
};
|
||||
|
||||
struct _GtkFontPlaneClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
void (*_gtk_reserved4) (void);
|
||||
};
|
||||
|
||||
|
||||
GType gtk_font_plane_get_type (void) G_GNUC_CONST;
|
||||
GtkWidget * gtk_font_plane_new (GtkAdjustment *width_adj,
|
||||
GtkAdjustment *weight_adj);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_FONT_PLANE_H__ */
|
@@ -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.
|
||||
@@ -830,7 +830,6 @@ draw_spinbutton (GtkWidget *widget,
|
||||
GtkIconTheme *icon_theme;
|
||||
GtkIconInfo *icon_info;
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkTexture *texture;
|
||||
gint icon_width, icon_height, icon_size;
|
||||
gint button_width;
|
||||
gint contents_x, contents_y, contents_width, contents_height;
|
||||
@@ -851,33 +850,30 @@ draw_spinbutton (GtkWidget *widget,
|
||||
draw_style_common (spin_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
|
||||
draw_style_common (entry_context, cr, x, y, width, *height, NULL, NULL, NULL, NULL);
|
||||
|
||||
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (widget));
|
||||
icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
|
||||
|
||||
gtk_style_context_get (up_context,
|
||||
"min-width", &icon_width, "min-height", &icon_height, NULL);
|
||||
icon_size = MIN (icon_width, icon_height);
|
||||
icon_info = gtk_icon_theme_lookup_icon (icon_theme, "list-add-symbolic", icon_size, 0);
|
||||
pixbuf = gtk_icon_info_load_symbolic_for_context (icon_info, up_context, NULL, NULL);
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
g_object_unref (icon_info);
|
||||
draw_style_common (up_context, cr, x + width - button_width, y, button_width, *height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
gtk_render_icon (up_context, cr, texture, contents_x, contents_y + (contents_height - icon_size) / 2);
|
||||
gtk_render_icon (up_context, cr, pixbuf, contents_x, contents_y + (contents_height - icon_size) / 2);
|
||||
g_object_unref (pixbuf);
|
||||
g_object_unref (texture);
|
||||
|
||||
|
||||
gtk_style_context_get (down_context,
|
||||
"min-width", &icon_width, "min-height", &icon_height, NULL);
|
||||
icon_size = MIN (icon_width, icon_height);
|
||||
icon_info = gtk_icon_theme_lookup_icon (icon_theme, "list-remove-symbolic", icon_size, 0);
|
||||
pixbuf = gtk_icon_info_load_symbolic_for_context (icon_info, down_context, NULL, NULL);
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
g_object_unref (icon_info);
|
||||
draw_style_common (down_context, cr, x + width - 2 * button_width, y, button_width, *height,
|
||||
&contents_x, &contents_y, &contents_width, &contents_height);
|
||||
gtk_render_icon (down_context, cr, texture, contents_x, contents_y + (contents_height - icon_size) / 2);
|
||||
gtk_render_icon (down_context, cr, pixbuf, contents_x, contents_y + (contents_height - icon_size) / 2);
|
||||
g_object_unref (pixbuf);
|
||||
g_object_unref (texture);
|
||||
|
||||
g_object_unref (down_context);
|
||||
g_object_unref (up_context);
|
||||
@@ -964,8 +960,8 @@ do_foreigndrawing (GtkWidget *do_widget)
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Foreign drawing");
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (do_widget));
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
|
164
demos/gtk-demo/geninclude.pl.in
Executable file
@@ -0,0 +1,164 @@
|
||||
#!@PERL@ -w
|
||||
|
||||
print <<EOT;
|
||||
typedef GtkWidget *(*GDoDemoFunc) (GtkWidget *do_widget);
|
||||
|
||||
typedef struct _Demo Demo;
|
||||
|
||||
struct _Demo
|
||||
{
|
||||
gchar *name;
|
||||
gchar *title;
|
||||
gchar *filename;
|
||||
GDoDemoFunc func;
|
||||
Demo *children;
|
||||
};
|
||||
|
||||
EOT
|
||||
|
||||
for $file (@ARGV) {
|
||||
my %demo;
|
||||
|
||||
($basename = $file) =~ s/\.c$//;
|
||||
|
||||
open INFO_FILE, $file or die "Cannot open '$file'\n";
|
||||
$title = <INFO_FILE>;
|
||||
$title =~ s@^\s*/\*\s*@@;
|
||||
$title =~ s@\s*$@@;
|
||||
|
||||
close INFO_FILE;
|
||||
|
||||
print "GtkWidget *do_$basename (GtkWidget *do_widget);\n";
|
||||
|
||||
push @demos, {"name" => $basename, "title" => $title, "file" => $file,
|
||||
"func" => "do_$basename"};
|
||||
}
|
||||
|
||||
# generate a list of 'parent names'
|
||||
foreach $href (@demos) {
|
||||
if ($href->{"title"} =~ m|^([-\w\s]+)/[-\w\s]+$|) {
|
||||
my $parent_name = $1;
|
||||
my $do_next = 0;
|
||||
|
||||
# parent detected
|
||||
if (@parents) {
|
||||
foreach $foo (@parents) {
|
||||
if ($foo eq $parent_name) {
|
||||
$do_next = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($do_next) {
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
push @parents, $parent_name;
|
||||
|
||||
$tmp = (@child_arrays)?($#child_arrays + 1):0;
|
||||
push @child_arrays, "child$tmp";
|
||||
|
||||
push @demos, {"name" => "NULL", "title" => $parent_name, "file" => "NULL",
|
||||
"func" => "NULL"};
|
||||
}
|
||||
}
|
||||
|
||||
if (@parents) {
|
||||
$i = 0;
|
||||
for ($i = 0; $i <= $#parents; $i++) {
|
||||
$first = 1;
|
||||
|
||||
print "\nDemo ", $child_arrays[$i], "[] = {\n";
|
||||
|
||||
$j = 0;
|
||||
for ($j = 0; $j <= $#demos; $j++) {
|
||||
$href = $demos[$j];
|
||||
|
||||
if (!$demos[$j]) {
|
||||
next;
|
||||
}
|
||||
|
||||
if ($demos[$j]{"title"} =~ m|^$parents[$i]/([-\w\s]+)$|) {
|
||||
if ($first) {
|
||||
$first = 0;
|
||||
} else {
|
||||
print ",\n";
|
||||
}
|
||||
|
||||
print qq ( { "$demos[$j]{name}", "$1", "$demos[$j]{file}", $demos[$j]{func}, NULL });
|
||||
|
||||
# hack ... ugly
|
||||
$demos[$j]{"title"} = "foo";
|
||||
}
|
||||
}
|
||||
|
||||
print ",\n";
|
||||
print qq ( { NULL } );
|
||||
print "\n};\n";
|
||||
}
|
||||
}
|
||||
|
||||
# sort @demos
|
||||
@demos_old = @demos;
|
||||
|
||||
@demos = sort {
|
||||
$a->{"title"} cmp $b->{"title"};
|
||||
} @demos_old;
|
||||
|
||||
# sort the child arrays
|
||||
if (@child_arrays) {
|
||||
for ($i = 0; $i <= $#child_arrays; $i++) {
|
||||
@foo_old = @{$child_arrays[$i]};
|
||||
|
||||
@{$child_arrays[$i]} = sort {
|
||||
$a->{"title"} cmp $b->{"title"};
|
||||
} @foo_old;
|
||||
}
|
||||
}
|
||||
|
||||
# toplevel
|
||||
print "\nDemo gtk_demos[] = {\n";
|
||||
|
||||
$first = 1;
|
||||
foreach $href (@demos) {
|
||||
$handled = 0;
|
||||
|
||||
# ugly evil hack
|
||||
if ($href->{title} eq "foo") {
|
||||
next;
|
||||
}
|
||||
|
||||
if ($first) {
|
||||
$first = 0;
|
||||
} else {
|
||||
print ", \n";
|
||||
}
|
||||
|
||||
if (@parents) {
|
||||
for ($i = 0; $i <= $#parents; $i++) {
|
||||
if ($parents[$i] eq $href->{title}) {
|
||||
|
||||
if ($href->{file} eq 'NULL') {
|
||||
print qq ( { NULL, "$href->{title}", NULL, $href->{func}, $child_arrays[$i] });
|
||||
} else {
|
||||
print qq ( { "$href->{name}", "$href->{title}", "$href->{file}", $href->{func}, $child_arrays[$i] });
|
||||
}
|
||||
|
||||
$handled = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($handled) {
|
||||
next;
|
||||
}
|
||||
|
||||
print qq ( { "$href->{name}", "$href->{title}", "$href->{file}", $href->{func}, NULL });
|
||||
}
|
||||
|
||||
print ",\n";
|
||||
print qq ( { NULL } );
|
||||
print "\n};\n";
|
||||
|
||||
exit 0;
|
@@ -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()
|
||||
|
||||
|
||||
|
@@ -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))
|
||||
|
@@ -390,7 +390,7 @@ create_glarea_window (GtkWidget *do_widget)
|
||||
int i;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_screen (GTK_WINDOW (window), gtk_widget_get_screen (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "OpenGL Area");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
|
||||
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
|
||||
|
@@ -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
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -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,24 +45,18 @@ struct _GtkFishbowlChild
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ANIMATING,
|
||||
PROP_BENCHMARK,
|
||||
PROP_COUNT,
|
||||
PROP_FRAMERATE,
|
||||
PROP_FRAMERATE_STRING,
|
||||
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);
|
||||
|
||||
priv->update_delay = G_USEC_PER_SEC;
|
||||
gtk_widget_set_has_window (GTK_WIDGET (fishbowl), FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,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,
|
||||
@@ -108,18 +106,7 @@ gtk_fishbowl_measure (GtkWidget *widget,
|
||||
if (!gtk_widget_get_visible (child->widget))
|
||||
continue;
|
||||
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
gtk_widget_measure (child->widget, orientation, -1, &child_min, &child_nat, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
int min_width;
|
||||
|
||||
gtk_widget_measure (child->widget, GTK_ORIENTATION_HORIZONTAL, -1, &min_width, NULL, NULL, NULL);
|
||||
gtk_widget_measure (child->widget, orientation, min_width, &child_min, &child_nat, NULL, NULL);
|
||||
}
|
||||
gtk_widget_measure (child->widget, orientation, -1, &child_min, &child_nat, NULL, NULL);
|
||||
|
||||
*minimum = MAX (*minimum, child_min);
|
||||
*natural = MAX (*natural, child_nat);
|
||||
@@ -127,10 +114,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);
|
||||
@@ -141,18 +128,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,9 +153,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;
|
||||
|
||||
@@ -188,12 +178,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)
|
||||
@@ -210,8 +201,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]);
|
||||
@@ -220,6 +211,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)
|
||||
{
|
||||
@@ -245,18 +256,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;
|
||||
@@ -277,30 +280,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_FRAMERATE_STRING:
|
||||
{
|
||||
char *s = g_strdup_printf ("%.2f", gtk_fishbowl_get_framerate (fishbowl));
|
||||
g_value_set_string (value, s);
|
||||
g_free (s);
|
||||
}
|
||||
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;
|
||||
@@ -312,6 +295,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;
|
||||
@@ -320,6 +304,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",
|
||||
@@ -327,43 +315,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_FRAMERATE_STRING] =
|
||||
g_param_spec_string ("framerate-string",
|
||||
"Framerate as string",
|
||||
"Framerate as string, with 2 decimals",
|
||||
NULL,
|
||||
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);
|
||||
}
|
||||
@@ -376,58 +334,94 @@ 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_ICON_SIZE_DIALOG);
|
||||
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)
|
||||
{
|
||||
@@ -436,114 +430,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);
|
||||
priv->framerate = ((int)(priv->framerate * 100))/100.0;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_FRAMERATE]);
|
||||
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_FRAMERATE_STRING]);
|
||||
|
||||
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,
|
||||
@@ -554,11 +440,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 */
|
||||
@@ -597,9 +481,6 @@ gtk_fishbowl_tick (GtkWidget *widget,
|
||||
|
||||
gtk_widget_queue_allocate (widget);
|
||||
|
||||
if (do_update)
|
||||
gtk_fishbowl_do_update (fishbowl);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -624,57 +505,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));
|
||||
}
|
||||
|