Compare commits
364 Commits
3.99.1
...
matthiasc/
Author | SHA1 | Date | |
---|---|---|---|
|
32335feb48 | ||
|
5ddebaad4d | ||
|
461ce87b52 | ||
|
84add08c36 | ||
|
f7978c784f | ||
|
61ae25d55e | ||
|
a70addb8a5 | ||
|
235de57cd8 | ||
|
975146fc79 | ||
|
6bc46a9a69 | ||
|
9ee7bdf4cb | ||
|
bb402a1f1d | ||
|
02614713da | ||
|
18a5ca257a | ||
|
874b9ef8b0 | ||
|
d89f7fd046 | ||
|
aeeffe27c2 | ||
|
cdc5e83ef2 | ||
|
e927866ed4 | ||
|
4b9e7ac355 | ||
|
bebe0b5c1b | ||
|
2ad9864cdc | ||
|
ec46900f06 | ||
|
93cfa3855c | ||
|
6b708e9b60 | ||
|
6e81573776 | ||
|
dd0da0f3cc | ||
|
48594a2d7a | ||
|
31042bd761 | ||
|
3023a61e1d | ||
|
c1e33056fb | ||
|
57253b0039 | ||
|
84d82dcda9 | ||
|
4e35d56263 | ||
|
a9bf129286 | ||
|
76b7f0ca1c | ||
|
09604eb3eb | ||
|
0485a6c008 | ||
|
169c208b7a | ||
|
7b2c4fdb6a | ||
|
e0b1c3e8b0 | ||
|
6b9622f0da | ||
|
cfd1520a9f | ||
|
79dc25e0b1 | ||
|
1d371db8d8 | ||
|
69d5dc7c9a | ||
|
f938377464 | ||
|
6e14b26622 | ||
|
5d5fbc69a4 | ||
|
a770ab34c4 | ||
|
b8e4240751 | ||
|
2c5a4a799a | ||
|
07b6431afe | ||
|
0c2d00835b | ||
|
dbfc172f6a | ||
|
6a089816fc | ||
|
2886e19772 | ||
|
c08df82d54 | ||
|
ebfb3e771d | ||
|
2881d347d3 | ||
|
66d16049c3 | ||
|
0c6226c20b | ||
|
9267f705ef | ||
|
a8adbfbc9f | ||
|
f00f6e9641 | ||
|
50f373fbc2 | ||
|
f2f0a9ee0e | ||
|
4200936f21 | ||
|
90991a341d | ||
|
1abcd6f304 | ||
|
f87de393b5 | ||
|
35c3a60c08 | ||
|
cf1ed3a72a | ||
|
18e46bd6f8 | ||
|
7082624fd7 | ||
|
25d30011a0 | ||
|
cd60ed4391 | ||
|
a1e21c1acb | ||
|
ba6c14ad34 | ||
|
c6aff910ed | ||
|
d71337513f | ||
|
2741431d6e | ||
|
cc9fe4b354 | ||
|
e4d29ba9fd | ||
|
6f56d8df28 | ||
|
9eb4eef48b | ||
|
e69b623a27 | ||
|
d1a68ac7ba | ||
|
52ba70d549 | ||
|
02aec7f5f4 | ||
|
c766e31e8f | ||
|
a545fa15e4 | ||
|
e669433cde | ||
|
a6f86d9c26 | ||
|
d0f182757a | ||
|
c8f4c8c4f0 | ||
|
87f589f738 | ||
|
27f3600419 | ||
|
40ee7186bf | ||
|
a0422bfe25 | ||
|
67c1600ac2 | ||
|
50400879e0 | ||
|
b20e67dc83 | ||
|
a3dcfafba6 | ||
|
82ce1a9d6b | ||
|
cc6faeab50 | ||
|
aa32613beb | ||
|
6a3e12cfae | ||
|
fc6d621146 | ||
|
37a24711a4 | ||
|
595cc929e6 | ||
|
27e6826860 | ||
|
7a2400c8a1 | ||
|
3c4259393c | ||
|
a201bfd9a5 | ||
|
921f3a6e16 | ||
|
e7c75f04dd | ||
|
7dd819dffc | ||
|
8eab10dabf | ||
|
bd900fe8c9 | ||
|
6a676d527c | ||
|
f125e6234b | ||
|
bcb2861447 | ||
|
962f76ddc9 | ||
|
d45aabb4ec | ||
|
9f03462ffb | ||
|
3b11896581 | ||
|
c66a8cb941 | ||
|
c462f35a5e | ||
|
b166999683 | ||
|
4b589b6afb | ||
|
fedeb51f31 | ||
|
d2faa38eed | ||
|
ff9ca2b68d | ||
|
aa5207b349 | ||
|
2b5b6e0885 | ||
|
93d9a2ceda | ||
|
5ab77e72e2 | ||
|
5a7faa6512 | ||
|
b7d42502ce | ||
|
2d766dff96 | ||
|
e3bab0b766 | ||
|
d3c5c7f4ef | ||
|
f6e4486338 | ||
|
9d6990fdb9 | ||
|
3f1fa66479 | ||
|
8094f757eb | ||
|
d732c869c2 | ||
|
691261c71a | ||
|
fe6f70efe1 | ||
|
cddbc8f1cc | ||
|
a90801e696 | ||
|
f445cc0d70 | ||
|
6cf7b95bec | ||
|
7518fd0d70 | ||
|
30c3a533f4 | ||
|
52304fe7da | ||
|
22257b124a | ||
|
4629182246 | ||
|
c8a9e7fa82 | ||
|
8f593827cf | ||
|
8984fe3c35 | ||
|
fc720b57e2 | ||
|
4cb367a6e2 | ||
|
b534752d5c | ||
|
929a56e53c | ||
|
6ed1c181ee | ||
|
0011a1032d | ||
|
38b71ba292 | ||
|
b5f3ac9718 | ||
|
756c52ef08 | ||
|
9afdb41b6b | ||
|
25bcec5cbb | ||
|
eba5232e35 | ||
|
7ee3439522 | ||
|
71ea619274 | ||
|
f679ba566e | ||
|
2679e29375 | ||
|
e55bdf87b5 | ||
|
c09575d9cb | ||
|
c3b925d696 | ||
|
640856edec | ||
|
1e7fccf46f | ||
|
ff392fbfb6 | ||
|
498cbae95c | ||
|
fa9608fd02 | ||
|
8700e136da | ||
|
2e54810937 | ||
|
93a09a4a6a | ||
|
299b1bd848 | ||
|
1e9a9876d5 | ||
|
1de7440c8c | ||
|
5c87432a0c | ||
|
80e53e704c | ||
|
24bf01dd42 | ||
|
2113f98c5c | ||
|
b9d4654fca | ||
|
7151b1fc31 | ||
|
790733673f | ||
|
aff788e583 | ||
|
d5d4af585d | ||
|
93078e52c0 | ||
|
cee275980a | ||
|
b3aa5ad4f9 | ||
|
9b0b19d335 | ||
|
d47d036663 | ||
|
5c67fe0bc2 | ||
|
1057588a8f | ||
|
75f0b7acaa | ||
|
9a927176df | ||
|
cb5b375f43 | ||
|
dfccaa8831 | ||
|
cc58956dbb | ||
|
0ad10ccf39 | ||
|
8cb03a8cc0 | ||
|
df7cbdfff4 | ||
|
f4b410daa7 | ||
|
b3d3d81c82 | ||
|
3095bccd2e | ||
|
c72b2f6167 | ||
|
3d10b28df4 | ||
|
d6807b966c | ||
|
887d0b7411 | ||
|
3921476504 | ||
|
ae97284409 | ||
|
7cda32d49e | ||
|
fb99bde840 | ||
|
9dc5c6a0f3 | ||
|
107e49002d | ||
|
31a7574544 | ||
|
859df747ac | ||
|
81c835c418 | ||
|
33e633cc5c | ||
|
73b46eafe1 | ||
|
710ef690ec | ||
|
cb2b0688ca | ||
|
45c61fdbe3 | ||
|
ec49b68257 | ||
|
0092a08dfc | ||
|
bab7092a69 | ||
|
3b6941b04b | ||
|
fe429ffc45 | ||
|
d595c6ab12 | ||
|
2738d5bc93 | ||
|
5a8267dfae | ||
|
d03ce22446 | ||
|
350051c56e | ||
|
979ec828d2 | ||
|
99ddb3c927 | ||
|
770910e608 | ||
|
7180bfc288 | ||
|
bc80ed4240 | ||
|
4d45c2669c | ||
|
dd8ca7259f | ||
|
06c866f45e | ||
|
2bd7ed5ebd | ||
|
adc9d91e0e | ||
|
1150c23b0f | ||
|
9b8c175f23 | ||
|
e0134aaf15 | ||
|
bd7aa1782c | ||
|
007c9c6218 | ||
|
8c8baa9aa6 | ||
|
7ae0f56378 | ||
|
3fcf7adb25 | ||
|
8b38d1895c | ||
|
a4ba25f0f8 | ||
|
24389a0ef5 | ||
|
dfabe74c59 | ||
|
716c7b2f21 | ||
|
c74c38ad06 | ||
|
727f25f6da | ||
|
01959e1662 | ||
|
12afc10ec3 | ||
|
2f70279f85 | ||
|
ffc77ca926 | ||
|
021eeedef0 | ||
|
635492b016 | ||
|
bd226cc31e | ||
|
cbd3158d91 | ||
|
982cf0c4d3 | ||
|
d37cb36eb1 | ||
|
e374917c56 | ||
|
1dd4e91fee | ||
|
c1bf9f3b41 | ||
|
8a3621a125 | ||
|
81f84fbe8f | ||
|
60e37d3368 | ||
|
e0cc7b5d86 | ||
|
9843515736 | ||
|
41497aeb8b | ||
|
bb2a0e69f4 | ||
|
f70e37a341 | ||
|
1a445d79c4 | ||
|
925a01162f | ||
|
3bcbb4a7cc | ||
|
a8eae7afaa | ||
|
99a09e0d08 | ||
|
275302a9d5 | ||
|
749d0744da | ||
|
62f7395c77 | ||
|
f7f0bc0369 | ||
|
1896d7f463 | ||
|
927c4abf23 | ||
|
b322ddba5c | ||
|
b25871438d | ||
|
aff3cc6194 | ||
|
f2c4ad0087 | ||
|
a67899870a | ||
|
a0565ea8d9 | ||
|
1d2634e73b | ||
|
18a85998dc | ||
|
c6fee8cee5 | ||
|
dc17cf19b4 | ||
|
df88abb9c4 | ||
|
bba7f444dc | ||
|
6b9db59e62 | ||
|
0077f95ace | ||
|
c770adb918 | ||
|
529b44625d | ||
|
c10636789d | ||
|
8124f5896d | ||
|
28f831ebb0 | ||
|
3ec7a6c861 | ||
|
8da4a02da0 | ||
|
e6d4555b34 | ||
|
f854c2850f | ||
|
d6392c9035 | ||
|
02631d2b6e | ||
|
9cddc36fe2 | ||
|
690d72e696 | ||
|
9dbf81e7d9 | ||
|
0546f09b1d | ||
|
22099ebb05 | ||
|
07ef594be1 | ||
|
d785212706 | ||
|
9b0c2e62ba | ||
|
983f072514 | ||
|
275b95841b | ||
|
7d9bc01797 | ||
|
028644d0ad | ||
|
76e83d3216 | ||
|
002376f837 | ||
|
39d71dbb0a | ||
|
b5e7499bbd | ||
|
fed6ba9bd0 | ||
|
5581f78f41 | ||
|
a97ea17c92 | ||
|
67f259cd1a | ||
|
e5f4459e4b | ||
|
890c7816f0 | ||
|
e25e73c56c | ||
|
8a2b3f0692 | ||
|
1ec4995d14 | ||
|
dd624de8e8 | ||
|
92737b27bf | ||
|
fe50286e14 | ||
|
9d65ee58c9 | ||
|
ad5a78b1e7 | ||
|
cd3a7b416e | ||
|
fc63c6371f | ||
|
d13fa73d04 | ||
|
c6976d6897 | ||
|
6371fca799 |
@@ -48,7 +48,7 @@ if ! pkg-config --atleast-version=2.65.0 glib-2.0; then
|
||||
fi
|
||||
pkg-config --modversion glib-2.0
|
||||
|
||||
if ! pkg-config --atleast-version=1.45.4 pango; then
|
||||
if ! pkg-config --atleast-version=1.47.0 pango; then
|
||||
git clone https://gitlab.gnome.org/GNOME/pango.git _pango
|
||||
meson setup _pango_build _pango
|
||||
meson compile -C _pango_build
|
||||
|
30
AUTHORS
30
AUTHORS
@@ -1,5 +1,5 @@
|
||||
Please do not mail any of the authors listed here
|
||||
asking questions about this version of GTK+.
|
||||
Please do not mail any of the authors listed here
|
||||
asking questions about this version of GTK.
|
||||
|
||||
Original Authors
|
||||
----------------
|
||||
@@ -7,8 +7,8 @@ Peter Mattis <petm@xcf.berkeley.edu>
|
||||
Spencer Kimball <spencer@xcf.berkeley.edu>
|
||||
Josh MacDonald <jmacd@xcf.berkeley.edu>
|
||||
|
||||
The GTK+ Team (in alphabetical order)
|
||||
-------------------------------------
|
||||
The Team that build GTK 2 (in alphabetical order)
|
||||
-------------------------------------------------
|
||||
Shawn T. Amundson <amundson@gtk.org>
|
||||
Jerome Bolliet <bolliet@gtk.org>
|
||||
Damon Chaplin <damon@gtk.org>
|
||||
@@ -28,11 +28,24 @@ Jay Painter <jpaint@gtk.org>
|
||||
Manish Singh <manish@gtk.org>
|
||||
Owen Taylor <otaylor@gtk.org>
|
||||
|
||||
The current team (GTK 3 and 4)
|
||||
------------------------------
|
||||
|
||||
Jonas Ådahl <jadahl@gmail.com>
|
||||
Tim Bäder <mail@baedert.org>
|
||||
Emmanuele Bassi <ebassi@gnome.org>
|
||||
Chun-wei Fan <fanchunwei@src.gnome.org>
|
||||
Matthias Clasen <mclasen@redhat.com>
|
||||
Carlos Garnacho <mrgarnacho@gmail.com>
|
||||
Alexander Larsson <alexl@redhat.com>
|
||||
Benjamin Otte <otte@gnome.org>
|
||||
|
||||
|
||||
There are many others who have contributed patches; we thank them,
|
||||
GTK+ is much better because of them.
|
||||
GTK is much better because of them.
|
||||
|
||||
|
||||
Over time, GTK+ has incorporated some pieces of software which
|
||||
Over time, GTK has incorporated some pieces of software which
|
||||
started as independent projects. We list the original authors here:
|
||||
|
||||
|
||||
@@ -63,3 +76,8 @@ DirectFB backend
|
||||
Denis Oliver Kropp
|
||||
Sven Neumann
|
||||
Mike Emmel
|
||||
|
||||
|
||||
gtkparasite
|
||||
-----------
|
||||
Christian Hammond
|
||||
|
118
NEWS
118
NEWS
@@ -1,3 +1,121 @@
|
||||
Overview of Changes in GTK 3.99.2
|
||||
=================================
|
||||
|
||||
* GtkEntry:
|
||||
- Fix issues with Emoji insertion
|
||||
- Fix issues with dnd
|
||||
- Set correct hotspot for dnd icon
|
||||
|
||||
* GtkPasswordEntry:
|
||||
- Use non-pageable memory
|
||||
|
||||
* GtkSearchEntry:
|
||||
- Don't handle forwarded events twice
|
||||
|
||||
* GtkPasswordEntry:
|
||||
- Add an ::activate signal
|
||||
|
||||
* GtkTextView:
|
||||
- Fix dnd
|
||||
- Improve undo state tracking
|
||||
- Speed rendering in the presence of selections
|
||||
- Make clickable links work again
|
||||
- Fix handling of anchored children
|
||||
|
||||
* GtkRevealer:
|
||||
- Fix clipping issues in the swing transitions
|
||||
|
||||
* GtkColorChooser:
|
||||
- Update the default palette
|
||||
|
||||
* GtkFileChooser:
|
||||
- Fix a crash
|
||||
- Fix setting unlisted filters
|
||||
|
||||
* GtkFontChooser:
|
||||
- Determine sample text based on font coverage
|
||||
- Allow filtering by language
|
||||
|
||||
* GtkStack:
|
||||
- Add gtk_stack_add_child
|
||||
|
||||
* GtkVideo:
|
||||
- Make autoplay work
|
||||
|
||||
* CSS:
|
||||
- Allow more than 64 selectors per rule
|
||||
|
||||
* Adwaita:
|
||||
- Improve gesture graphics
|
||||
- Tweak DND highlight color
|
||||
- Add spacing to .navigation-sidebar
|
||||
|
||||
* GDK:
|
||||
- Add gdk_frame_clock_get_fps
|
||||
|
||||
* GSK:
|
||||
- Add radial gradient nodes
|
||||
|
||||
* GL renderer:
|
||||
- Fix clipping with projective transforms
|
||||
- Use linear interpolation for offscreen rendering
|
||||
with non-axis-aligned transforms
|
||||
- Fix texture caching to avoid size mismatches
|
||||
|
||||
* Vulkan renderer:
|
||||
- Fix swapchain creation
|
||||
|
||||
* Windows:
|
||||
- Fix display of CSD windows
|
||||
|
||||
* Wayland
|
||||
- Always ack configure to avoid jumping windows
|
||||
|
||||
* API cleanups:
|
||||
- Make filter and sorter constructors return exact types
|
||||
- Rename GdkSurfaceState to GdkToplevelState
|
||||
- Remove GdkWaylandSurface::committed
|
||||
- Make Wayland backend api take GdkToplevel
|
||||
|
||||
* Demos:
|
||||
- Bug and crash fixes
|
||||
- Cosmetic improvements for several demos
|
||||
- Improve search in the sidebar
|
||||
- Add a Shadertoy demo
|
||||
- Add an Emblem demo
|
||||
- Add a demo for input validation and error states
|
||||
- Add a demo for context menus
|
||||
- Make gtk-demo demo itself
|
||||
|
||||
* Build:
|
||||
- Fix Vulkan dependency checking
|
||||
- Make sysprof truly optional
|
||||
|
||||
* Translation updates:
|
||||
Basque
|
||||
British English
|
||||
Catalan
|
||||
Croatian
|
||||
Czech
|
||||
Danish
|
||||
French
|
||||
Galician
|
||||
German
|
||||
Hungarian
|
||||
Indonesian
|
||||
Italian
|
||||
Kazakh
|
||||
Latvian
|
||||
Lithuanian
|
||||
Persian
|
||||
Polish
|
||||
Slovak
|
||||
Slovenian
|
||||
Spanish
|
||||
Turkish
|
||||
Ukrainian
|
||||
|
||||
|
||||
Overview of Changes in GTK 3.99.1
|
||||
=================================
|
||||
|
||||
|
@@ -69,6 +69,9 @@
|
||||
/* Define to 1 if you have the `mkstemp' function. */
|
||||
#mesondefine HAVE_MKSTEMP
|
||||
|
||||
/* Define to 1 if you have the `mlock` function. */
|
||||
#mesondefine HAVE_MLOCK
|
||||
|
||||
/* Define to 1 if you have a working `mmap' system call. */
|
||||
#mesondefine HAVE_MMAP
|
||||
|
||||
|
@@ -177,11 +177,11 @@ constraint_view_init (ConstraintView *self)
|
||||
guides = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (manager));
|
||||
|
||||
all_constraints = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (manager));
|
||||
filter = gtk_custom_filter_new (omit_internal, NULL, NULL);
|
||||
filter = GTK_FILTER (gtk_custom_filter_new (omit_internal, NULL, NULL));
|
||||
constraints = (GListModel *)gtk_filter_list_model_new (all_constraints, filter);
|
||||
|
||||
all_children = gtk_widget_observe_children (GTK_WIDGET (self));
|
||||
filter = gtk_custom_filter_new (omit_internal, NULL, NULL);
|
||||
filter = GTK_FILTER (gtk_custom_filter_new (omit_internal, NULL, NULL));
|
||||
children = (GListModel *)gtk_filter_list_model_new (all_children, filter);
|
||||
|
||||
list = g_list_store_new (G_TYPE_LIST_MODEL);
|
||||
|
345
demos/gtk-demo/alienplanet.glsl
Normal file
345
demos/gtk-demo/alienplanet.glsl
Normal file
@@ -0,0 +1,345 @@
|
||||
// Originally from: https://www.shadertoy.com/view/wsjBD3
|
||||
// License CC0: A battered alien planet
|
||||
// Been experimenting with space inspired shaders
|
||||
|
||||
#define PI 3.141592654
|
||||
#define TAU (2.0*PI)
|
||||
|
||||
#define TOLERANCE 0.00001
|
||||
#define MAX_ITER 65
|
||||
#define MIN_DISTANCE 0.01
|
||||
#define MAX_DISTANCE 9.0
|
||||
|
||||
const vec3 skyCol1 = vec3(0.35, 0.45, 0.6);
|
||||
const vec3 skyCol2 = vec3(0.4, 0.7, 1.0);
|
||||
const vec3 skyCol3 = pow(skyCol1, vec3(0.25));
|
||||
const vec3 sunCol1 = vec3(1.0,0.6,0.4);
|
||||
const vec3 sunCol2 = vec3(1.0,0.9,0.7);
|
||||
const vec3 smallSunCol1 = vec3(1.0,0.5,0.25)*0.5;
|
||||
const vec3 smallSunCol2 = vec3(1.0,0.5,0.25)*0.5;
|
||||
const vec3 mountainColor = 1.0*sqrt(vec3(0.95, 0.65, 0.45));
|
||||
const float cellWidth = 1.0;
|
||||
const vec4 planet = vec4(80.0, -20.0, 100.0, 50.0)*1000.0;
|
||||
|
||||
void rot(inout vec2 p, float a) {
|
||||
float c = cos(a);
|
||||
float s = sin(a);
|
||||
p = vec2(p.x*c + p.y*s, -p.x*s + p.y*c);
|
||||
}
|
||||
|
||||
vec2 mod2(inout vec2 p, vec2 size) {
|
||||
vec2 c = floor((p + size*0.5)/size);
|
||||
p = mod(p + size*0.5,size) - size*0.5;
|
||||
return c;
|
||||
}
|
||||
|
||||
float circle(vec2 p, float r) {
|
||||
return length(p) - r;
|
||||
}
|
||||
|
||||
float egg(vec2 p, float ra, float rb) {
|
||||
const float k = sqrt(3.0);
|
||||
p.x = abs(p.x);
|
||||
float r = ra - rb;
|
||||
return ((p.y<0.0) ? length(vec2(p.x, p.y )) - r :
|
||||
(k*(p.x+r)<p.y) ? length(vec2(p.x, p.y-k*r)) :
|
||||
length(vec2(p.x+r,p.y )) - 2.0*r) - rb;
|
||||
}
|
||||
|
||||
vec2 hash(vec2 p) {
|
||||
p = vec2(dot (p, vec2 (127.1, 311.7)), dot (p, vec2 (269.5, 183.3)));
|
||||
return -1. + 2.*fract (sin (p)*43758.5453123);
|
||||
}
|
||||
|
||||
vec2 raySphere(vec3 ro, vec3 rd, vec4 sphere) {
|
||||
vec3 center = sphere.xyz;
|
||||
float radius = sphere.w;
|
||||
vec3 m = ro - center.xyz;
|
||||
float b = dot(m, rd);
|
||||
float c = dot(m, m) - radius*radius;
|
||||
if(c > 0.0 && b > 0.0) return vec2(-1.0, -1.0);
|
||||
float discr = b * b - c;
|
||||
if(discr < 0.0) return vec2(-1.0);
|
||||
float normalMultiplier = 1.0;
|
||||
float s = sqrt(discr);
|
||||
float t0 = -b - s;
|
||||
float t1 = -b + s;;
|
||||
return vec2(t0, t1);
|
||||
}
|
||||
|
||||
float noise1(vec2 p) {
|
||||
vec2 n = mod2(p, vec2(cellWidth));
|
||||
vec2 hh = hash(sqrt(2.0)*(n+1000.0));
|
||||
hh.x *= hh.y;
|
||||
|
||||
float r = 0.225*cellWidth;
|
||||
|
||||
float d = circle(p, 2.0*r);
|
||||
|
||||
float h = hh.x*smoothstep(0.0, r, -d);
|
||||
|
||||
return h*0.25;
|
||||
}
|
||||
|
||||
float noise2(vec2 p) {
|
||||
vec2 n = mod2(p, vec2(cellWidth));
|
||||
vec2 hh = hash(sqrt(2.0)*(n+1000.0));
|
||||
hh.x *= hh.y;
|
||||
|
||||
rot(p, TAU*hh.y);
|
||||
float r = 0.45*cellWidth;
|
||||
|
||||
// float d = circle(p, 1.0*r);
|
||||
float d = egg(p, 0.75*r, 0.5*r*abs(hh.y));
|
||||
|
||||
float h = (hh.x)*smoothstep(0.0, r, -2.0*d);
|
||||
|
||||
return h*0.275;
|
||||
}
|
||||
|
||||
|
||||
float height(vec2 p, float dd, int mx) {
|
||||
const float aa = 0.45;
|
||||
const float ff = 2.03;
|
||||
const float tt = 1.2;
|
||||
const float oo = 3.93;
|
||||
const float near = 0.25;
|
||||
const float far = 0.65;
|
||||
|
||||
float a = 1.0;
|
||||
float o = 0.2;
|
||||
float s = 0.0;
|
||||
float d = 0.0;
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (; i < 4;++i) {
|
||||
float nn = a*noise2(p);
|
||||
s += nn;
|
||||
d += abs(a);
|
||||
p += o;
|
||||
a *= aa;
|
||||
p *= ff;
|
||||
o *= oo;
|
||||
rot(p, tt);
|
||||
}
|
||||
|
||||
float lod = s/d;
|
||||
|
||||
float rdd = dd/MAX_DISTANCE;
|
||||
mx = int(mix(float(4), float(mx), step(rdd, far)));
|
||||
|
||||
for (; i < mx; ++i) {
|
||||
float nn = a*noise1(p);
|
||||
s += nn;
|
||||
d += abs(a);
|
||||
p += o;
|
||||
a *= aa;
|
||||
p *= ff;
|
||||
o *= oo;
|
||||
rot(p, tt);
|
||||
}
|
||||
|
||||
float hid = (s/d);
|
||||
|
||||
return mix(hid, lod, smoothstep(near, far, rdd));
|
||||
}
|
||||
|
||||
float loheight(vec2 p, float d) {
|
||||
return height(p, d, 0);
|
||||
}
|
||||
|
||||
float height(vec2 p, float d) {
|
||||
return height(p, d, 6);
|
||||
}
|
||||
|
||||
float hiheight(vec2 p, float d) {
|
||||
return height(p, d, 8);
|
||||
}
|
||||
|
||||
vec3 normal(vec2 p, float d) {
|
||||
vec2 eps = vec2(0.00125, 0.0);
|
||||
|
||||
vec3 n;
|
||||
|
||||
n.x = (hiheight(p - eps.xy, d) - hiheight(p + eps.xy, d));
|
||||
n.y = 2.0*eps.x;
|
||||
n.z = (hiheight(p - eps.yx, d) - hiheight(p + eps.yx, d));
|
||||
|
||||
return normalize(n);
|
||||
}
|
||||
|
||||
const float stepLength[] = float[](0.9, 0.25);
|
||||
|
||||
|
||||
float march(vec3 ro, vec3 rd, out int max_iter) {
|
||||
float dt = 0.1;
|
||||
float d = MIN_DISTANCE;
|
||||
int currentStep = 0;
|
||||
float lastd = d;
|
||||
for (int i = 0; i < MAX_ITER; ++i)
|
||||
{
|
||||
vec3 p = ro + d*rd;
|
||||
float h = height(p.xz, d);
|
||||
|
||||
if (d > MAX_DISTANCE) {
|
||||
max_iter = i;
|
||||
return MAX_DISTANCE;
|
||||
}
|
||||
|
||||
float hd = p.y - h;
|
||||
|
||||
if (hd < TOLERANCE) {
|
||||
++currentStep;
|
||||
if (currentStep >= stepLength.length()) {
|
||||
max_iter = i;
|
||||
return d;
|
||||
}
|
||||
|
||||
d = lastd;
|
||||
continue;
|
||||
}
|
||||
|
||||
float sl = stepLength[currentStep];
|
||||
|
||||
dt = max(hd, TOLERANCE)*sl + 0.0025*d;
|
||||
lastd = d;
|
||||
d += dt;
|
||||
}
|
||||
|
||||
max_iter = MAX_ITER;
|
||||
return MAX_DISTANCE;
|
||||
}
|
||||
|
||||
vec3 sunDirection() {
|
||||
return normalize(vec3(-0.5, 0.085, 1.0));
|
||||
}
|
||||
|
||||
vec3 smallSunDirection() {
|
||||
return normalize(vec3(-0.2, -0.05, 1.0));
|
||||
}
|
||||
|
||||
float psin(float f) {
|
||||
return 0.5 + 0.5*sin(f);
|
||||
}
|
||||
|
||||
vec3 skyColor(vec3 ro, vec3 rd) {
|
||||
vec3 sunDir = sunDirection();
|
||||
vec3 smallSunDir = smallSunDirection();
|
||||
|
||||
float sunDot = max(dot(rd, sunDir), 0.0);
|
||||
float smallSunDot = max(dot(rd, smallSunDir), 0.0);
|
||||
|
||||
float angle = atan(rd.y, length(rd.xz))*2.0/PI;
|
||||
|
||||
vec3 skyCol = mix(mix(skyCol1, skyCol2, max(0.0, angle)), skyCol3, clamp(-angle*2.0, 0.0, 1.0));
|
||||
|
||||
vec3 sunCol = 0.5*sunCol1*pow(sunDot, 20.0) + 8.0*sunCol2*pow(sunDot, 2000.0);
|
||||
vec3 smallSunCol = 0.5*smallSunCol1*pow(smallSunDot, 200.0) + 8.0*smallSunCol2*pow(smallSunDot, 20000.0);
|
||||
|
||||
vec3 dust = pow(sunCol2*mountainColor, vec3(1.75))*smoothstep(0.05, -0.1, rd.y)*0.5;
|
||||
|
||||
vec2 si = raySphere(ro, rd, planet);
|
||||
|
||||
vec3 planetSurface = ro + si.x*rd;
|
||||
vec3 planetNormal = normalize(planetSurface - planet.xyz);
|
||||
float planetDiff = max(dot(planetNormal, sunDir), 0.0);
|
||||
float planetBorder = max(dot(planetNormal, -rd), 0.0);
|
||||
float planetLat = (planetSurface.x+planetSurface.y)*0.0005;
|
||||
vec3 planetCol = mix(1.3*vec3(0.9, 0.8, 0.7), 0.3*vec3(0.9, 0.8, 0.7), pow(psin(planetLat+1.0)*psin(sqrt(2.0)*planetLat+2.0)*psin(sqrt(3.5)*planetLat+3.0), 0.5));
|
||||
|
||||
vec3 final = vec3(0.0);
|
||||
|
||||
final += step(0.0, si.x)*pow(planetDiff, 0.75)*planetCol*smoothstep(-0.075, 0.0, rd.y)*smoothstep(0.0, 0.1, planetBorder);
|
||||
|
||||
final += skyCol + sunCol + smallSunCol + dust;
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
vec3 getColor(vec3 ro, vec3 rd) {
|
||||
int max_iter = 0;
|
||||
vec3 skyCol = skyColor(ro, rd);
|
||||
vec3 col = vec3(0);
|
||||
|
||||
float d = march(ro, rd, max_iter);
|
||||
|
||||
if (d < MAX_DISTANCE) {
|
||||
vec3 sunDir = sunDirection();
|
||||
vec3 osunDir = sunDir*vec3(-1.0, .0, -1.0);
|
||||
vec3 p = ro + d*rd;
|
||||
|
||||
vec3 normal = normal(p.xz, d);
|
||||
|
||||
float amb = 0.2;
|
||||
|
||||
float dif1 = max(0.0, dot(sunDir, normal));
|
||||
vec3 shd1 = sunCol2*mix(amb, 1.0, pow(dif1, 0.75));
|
||||
|
||||
float dif2 = max(0.0, dot(osunDir, normal));
|
||||
vec3 shd2 = sunCol1*mix(amb, 1.0, pow(dif2, 0.75));
|
||||
|
||||
vec3 ref = reflect(rd, normal);
|
||||
vec3 rcol = skyColor(p, ref);
|
||||
|
||||
col = mountainColor*amb*skyCol3;
|
||||
col += mix(shd1, shd2, -0.5)*mountainColor;
|
||||
float fre = max(dot(normal, -rd), 0.0);
|
||||
fre = pow(1.0 - fre, 5.0);
|
||||
col += rcol*fre*0.5;
|
||||
col += (1.0*p.y);
|
||||
col = tanh(col);
|
||||
col = mix(col, skyCol, smoothstep(0.5*MAX_DISTANCE, 1.0*MAX_DISTANCE, d));
|
||||
|
||||
} else {
|
||||
col = skyCol;
|
||||
}
|
||||
|
||||
// col += vec3(1.1, 0.0, 0.0)* smoothstep(0.25, 1.0,(float(max_iter)/float(MAX_ITER)));
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 getSample1(vec2 p, float time) {
|
||||
float off = 0.5*iTime;
|
||||
|
||||
vec3 ro = vec3(0.5, 1.0-0.25, -2.0 + off);
|
||||
vec3 la = ro + vec3(0.0, -0.30, 2.0);
|
||||
|
||||
vec3 ww = normalize(la - ro);
|
||||
vec3 uu = normalize(cross(vec3(0.0,1.0,0.0), ww));
|
||||
vec3 vv = normalize(cross(ww, uu));
|
||||
vec3 rd = normalize(p.x*uu + p.y*vv + 2.0*ww);
|
||||
|
||||
vec3 col = getColor(ro, rd) ;
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 getSample2(vec2 p, float time) {
|
||||
p.y-=time*0.25;
|
||||
float h = height(p, 0.0);
|
||||
vec3 n = normal(p, 0.0);
|
||||
|
||||
vec3 lp = vec3(10.0, -1.2, 0.0);
|
||||
|
||||
vec3 ld = normalize(vec3(p.x, h, p.y)- lp);
|
||||
|
||||
float d = max(dot(ld, n), 0.0);
|
||||
|
||||
vec3 col = vec3(0.0);
|
||||
|
||||
col = vec3(1.0)*(h+0.1);
|
||||
col += vec3(1.5)*pow(d, 0.75);
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, vec2 fragCoord) {
|
||||
vec2 q = fragCoord.xy/iResolution.xy;
|
||||
vec2 p = -1.0 + 2.0*q;
|
||||
p.x *= iResolution.x/iResolution.y;
|
||||
|
||||
vec3 col = getSample1(p, iTime);
|
||||
|
||||
fragColor = vec4(col, 1.0);
|
||||
}
|
@@ -472,11 +472,11 @@ static void
|
||||
surface_state_changed (GtkWidget *widget)
|
||||
{
|
||||
DemoApplicationWindow *window = (DemoApplicationWindow *)widget;
|
||||
GdkSurfaceState new_state;
|
||||
GdkToplevelState new_state;
|
||||
|
||||
new_state = gdk_toplevel_get_state (GDK_TOPLEVEL (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;
|
||||
window->maximized = (new_state & GDK_TOPLEVEL_STATE_MAXIMIZED) != 0;
|
||||
window->fullscreen = (new_state & GDK_TOPLEVEL_STATE_FULLSCREEN) != 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -1,8 +1,8 @@
|
||||
/* Assistant
|
||||
*
|
||||
* Demonstrates a sample multi-step assistant. Assistants are used to divide
|
||||
* an operation into several simpler sequential steps, and to guide the user
|
||||
* through these steps.
|
||||
* Demonstrates a sample multi-step assistant with GtkAssistant. Assistants
|
||||
* are used to divide an operation into several simpler sequential steps,
|
||||
* and to guide the user through these steps.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
BIN
demos/gtk-demo/bbb.png
Normal file
BIN
demos/gtk-demo/bbb.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
@@ -1,6 +1,8 @@
|
||||
/* Builder
|
||||
* #Keywords: GMenu, GtkPopoverMenuBar, GtkBuilder, GtkStatusBar, toolbar
|
||||
*
|
||||
* Demonstrates an interface loaded from a XML description.
|
||||
* Demonstrates a traditional interface, loaded from a XML description,
|
||||
* and shows how to connect actions to the menu items and toolbar buttons.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
@@ -104,6 +106,7 @@ do_builder (GtkWidget *do_widget)
|
||||
GtkBuilder *builder;
|
||||
GtkWidget *about;
|
||||
GtkWidget *status;
|
||||
GtkEventController *controller;
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/builder/demo.ui");
|
||||
|
||||
@@ -117,6 +120,41 @@ do_builder (GtkWidget *do_widget)
|
||||
window);
|
||||
gtk_widget_insert_action_group (window, "win", actions);
|
||||
|
||||
controller = gtk_shortcut_controller_new ();
|
||||
gtk_shortcut_controller_set_scope (GTK_SHORTCUT_CONTROLLER (controller),
|
||||
GTK_SHORTCUT_SCOPE_GLOBAL);
|
||||
gtk_widget_add_controller (window, controller);
|
||||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
|
||||
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_n, GDK_CONTROL_MASK),
|
||||
gtk_named_action_new ("win.new")));
|
||||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
|
||||
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_o, GDK_CONTROL_MASK),
|
||||
gtk_named_action_new ("win.open")));
|
||||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
|
||||
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_s, GDK_CONTROL_MASK),
|
||||
gtk_named_action_new ("win.save")));
|
||||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
|
||||
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_s, GDK_CONTROL_MASK|GDK_SHIFT_MASK),
|
||||
gtk_named_action_new ("win.save-as")));
|
||||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
|
||||
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_q, GDK_CONTROL_MASK),
|
||||
gtk_named_action_new ("win.quit")));
|
||||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
|
||||
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_c, GDK_CONTROL_MASK),
|
||||
gtk_named_action_new ("win.copy")));
|
||||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
|
||||
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_x, GDK_CONTROL_MASK),
|
||||
gtk_named_action_new ("win.cut")));
|
||||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
|
||||
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_v, GDK_CONTROL_MASK),
|
||||
gtk_named_action_new ("win.paste")));
|
||||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
|
||||
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_F1, 0),
|
||||
gtk_named_action_new ("win.help")));
|
||||
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller),
|
||||
gtk_shortcut_new (gtk_keyval_trigger_new (GDK_KEY_F7, 0),
|
||||
gtk_named_action_new ("win.about")));
|
||||
|
||||
about = GTK_WIDGET (gtk_builder_get_object (builder, "aboutdialog1"));
|
||||
gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (window));
|
||||
gtk_window_set_hide_on_close (GTK_WINDOW (about), TRUE);
|
||||
|
224
demos/gtk-demo/cogs.glsl
Normal file
224
demos/gtk-demo/cogs.glsl
Normal file
@@ -0,0 +1,224 @@
|
||||
// Originally from: https://www.shadertoy.com/view/3ljyDD
|
||||
// License CC0: Hexagonal tiling + cog wheels
|
||||
// Nothing fancy, just hexagonal tiling + cog wheels
|
||||
|
||||
#define PI 3.141592654
|
||||
#define TAU (2.0*PI)
|
||||
#define MROT(a) mat2(cos(a), sin(a), -sin(a), cos(a))
|
||||
|
||||
float hash(in vec2 co) {
|
||||
return fract(sin(dot(co.xy ,vec2(12.9898,58.233))) * 13758.5453);
|
||||
}
|
||||
|
||||
float pcos(float a) {
|
||||
return 0.5 + 0.5*cos(a);
|
||||
}
|
||||
|
||||
void rot(inout vec2 p, float a) {
|
||||
float c = cos(a);
|
||||
float s = sin(a);
|
||||
p = vec2(c*p.x + s*p.y, -s*p.x + c*p.y);
|
||||
}
|
||||
|
||||
float modPolar(inout vec2 p, float repetitions) {
|
||||
float angle = 2.0*PI/repetitions;
|
||||
float a = atan(p.y, p.x) + angle/2.;
|
||||
float r = length(p);
|
||||
float c = floor(a/angle);
|
||||
a = mod(a,angle) - angle/2.;
|
||||
p = vec2(cos(a), sin(a))*r;
|
||||
// For an odd number of repetitions, fix cell index of the cell in -x direction
|
||||
// (cell index would be e.g. -5 and 5 in the two halves of the cell):
|
||||
if (abs(c) >= (repetitions/2.0)) c = abs(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
float pmin(float a, float b, float k) {
|
||||
float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
|
||||
return mix( b, a, h ) - k*h*(1.0-h);
|
||||
}
|
||||
|
||||
const vec2 sz = vec2(1.0, sqrt(3.0));
|
||||
const vec2 hsz = 0.5*sz;
|
||||
const float smallCount = 16.0;
|
||||
|
||||
vec2 hextile(inout vec2 p) {
|
||||
// See Art of Code: Hexagonal Tiling Explained!
|
||||
// https://www.youtube.com/watch?v=VmrIDyYiJBA
|
||||
|
||||
vec2 p1 = mod(p, sz)-hsz;
|
||||
vec2 p2 = mod(p - hsz*1.0, sz)-hsz;
|
||||
vec2 p3 = mix(p2, p1, vec2(length(p1) < length(p2)));
|
||||
vec2 n = p3 - p;
|
||||
p = p3;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
float circle(vec2 p, float r) {
|
||||
return length(p) - r;
|
||||
}
|
||||
|
||||
float box(vec2 p, vec2 b) {
|
||||
vec2 d = abs(p)-b;
|
||||
return length(max(d,0.0)) + min(max(d.x,d.y),0.0);
|
||||
}
|
||||
|
||||
float unevenCapsule(vec2 p, float r1, float r2, float h) {
|
||||
p.x = abs(p.x);
|
||||
float b = (r1-r2)/h;
|
||||
float a = sqrt(1.0-b*b);
|
||||
float k = dot(p,vec2(-b,a));
|
||||
if( k < 0.0 ) return length(p) - r1;
|
||||
if( k > a*h ) return length(p-vec2(0.0,h)) - r2;
|
||||
return dot(p, vec2(a,b) ) - r1;
|
||||
}
|
||||
|
||||
float cogwheel(vec2 p, float innerRadius, float outerRadius, float cogs, float holes) {
|
||||
float cogWidth = 0.25*innerRadius*TAU/cogs;
|
||||
|
||||
float d0 = circle(p, innerRadius);
|
||||
|
||||
vec2 icp = p;
|
||||
modPolar(icp, holes);
|
||||
icp -= vec2(innerRadius*0.55, 0.0);
|
||||
float d1 = circle(icp, innerRadius*0.25);
|
||||
|
||||
vec2 cp = p;
|
||||
modPolar(cp, cogs);
|
||||
cp -= vec2(innerRadius, 0.0);
|
||||
float d2 = unevenCapsule(cp.yx, cogWidth, cogWidth*0.75, (outerRadius-innerRadius));
|
||||
|
||||
float d3 = circle(p, innerRadius*0.20);
|
||||
|
||||
float d = 1E6;
|
||||
d = min(d, d0);
|
||||
d = pmin(d, d2, 0.5*cogWidth);
|
||||
d = min(d, d2);
|
||||
d = max(d, -d1);
|
||||
d = max(d, -d3);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
float ccell1(vec2 p, float r) {
|
||||
float d = 1E6;
|
||||
const float bigCount = 60.0;
|
||||
|
||||
vec2 cp0 = p;
|
||||
rot(cp0, -iTime*TAU/bigCount);
|
||||
float d0 = cogwheel(cp0, 0.36, 0.38, bigCount, 5.0);
|
||||
|
||||
vec2 cp1 = p;
|
||||
float nm = modPolar(cp1, 6.0);
|
||||
|
||||
cp1 -= vec2(0.5, 0.0);
|
||||
rot(cp1, 0.2+TAU*nm/2.0 + iTime*TAU/smallCount);
|
||||
float d1 = cogwheel(cp1, 0.11, 0.125, smallCount, 5.0);
|
||||
|
||||
d = min(d, d0);
|
||||
d = min(d, d1);
|
||||
return d;
|
||||
}
|
||||
|
||||
float ccell2(vec2 p, float r) {
|
||||
float d = 1E6;
|
||||
vec2 cp0 = p;
|
||||
float nm = modPolar(cp0, 6.0);
|
||||
vec2 cp1 = cp0;
|
||||
const float off = 0.275;
|
||||
const float count = smallCount + 2.0;
|
||||
cp0 -= vec2(off, 0.0);
|
||||
rot(cp0, 0.+TAU*nm/2.0 - iTime*TAU/count);
|
||||
float d0 = cogwheel(cp0, 0.09, 0.105, count, 5.0);
|
||||
|
||||
|
||||
cp1 -= vec2(0.5, 0.0);
|
||||
rot(cp1, 0.2+TAU*nm/2.0 + iTime*TAU/smallCount);
|
||||
float d1 = cogwheel(cp1, 0.11, 0.125, smallCount, 5.0);
|
||||
|
||||
float l = length(p);
|
||||
float d2 = l - (off+0.055);
|
||||
float d3 = d2 + 0.020;;
|
||||
|
||||
vec2 tp0 = p;
|
||||
modPolar(tp0, 60.0);
|
||||
tp0.x -= off;
|
||||
float d4 = box(tp0, vec2(0.0125, 0.005));
|
||||
|
||||
float ctime = -(iTime*0.05 + r)*TAU;
|
||||
|
||||
vec2 tp1 = p;
|
||||
rot(tp1, ctime*12.0);
|
||||
tp1.x -= 0.13;
|
||||
float d5 = box(tp1, vec2(0.125, 0.005));
|
||||
|
||||
vec2 tp2 = p;
|
||||
rot(tp2, ctime);
|
||||
tp2.x -= 0.13*0.5;
|
||||
float d6 = box(tp2, vec2(0.125*0.5, 0.0075));
|
||||
|
||||
float d7 = l - 0.025;
|
||||
float d8 = l - 0.0125;
|
||||
|
||||
d = min(d, d0);
|
||||
d = min(d, d1);
|
||||
d = min(d, d2);
|
||||
d = max(d, -d3);
|
||||
d = min(d, d4);
|
||||
d = min(d, d5);
|
||||
d = min(d, d6);
|
||||
d = min(d, d7);
|
||||
d = max(d, -d8);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
float df(vec2 p, float scale, inout vec2 nn) {
|
||||
p /= scale;
|
||||
nn = hextile(p);
|
||||
nn = round(nn);
|
||||
float r = hash(nn);
|
||||
|
||||
float d;;
|
||||
|
||||
if (r < 0.5) {
|
||||
d = ccell1(p, r);
|
||||
} else {
|
||||
d = ccell2(p, r);
|
||||
}
|
||||
|
||||
return d*scale;
|
||||
}
|
||||
|
||||
vec3 postProcess(vec3 col, vec2 q) {
|
||||
//col = saturate(col);
|
||||
col=pow(clamp(col,0.0,1.0),vec3(0.75));
|
||||
col=col*0.6+0.4*col*col*(3.0-2.0*col); // contrast
|
||||
col=mix(col, vec3(dot(col, vec3(0.33))), -0.4); // satuation
|
||||
col*=0.5+0.5*pow(19.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.7); // vigneting
|
||||
return col;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, vec2 fragCoord) {
|
||||
vec2 q = fragCoord/iResolution.xy;
|
||||
vec2 p = -1.0 + 2.0*q;
|
||||
p.x *= iResolution.x/iResolution.y;
|
||||
float tm = iTime*0.1;
|
||||
p += vec2(cos(tm), sin(tm*sqrt(0.5)));
|
||||
float z = mix(0.5, 1.0, pcos(tm*sqrt(0.3)));
|
||||
float aa = 4.0 / iResolution.y;
|
||||
|
||||
vec2 nn = vec2(0.0);
|
||||
float d = df(p, z, nn);
|
||||
|
||||
vec3 col = vec3(160.0)/vec3(255.0);
|
||||
vec3 baseCol = vec3(0.3);
|
||||
vec4 logoCol = vec4(baseCol, 1.0)*smoothstep(-aa, 0.0, -d);
|
||||
col = mix(col, logoCol.xyz, pow(logoCol.w, 8.0));
|
||||
col += 0.4*pow(abs(sin(20.0*d)), 0.6);
|
||||
|
||||
col = postProcess(col, q);
|
||||
|
||||
fragColor = vec4(col, 1.0);
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
/* Combo Boxes
|
||||
* #Keywords: GtkCellRenderer
|
||||
*
|
||||
* The GtkComboBox widget allows to select one option out of a list.
|
||||
* The GtkComboBoxEntry additionally allows the user to enter a value
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Constraints/Simple
|
||||
* #Keywords: GtkLayoutManager
|
||||
*
|
||||
* GtkConstraintLayout provides a layout manager that uses relations
|
||||
* between widgets (also known as "constraints") to compute the position
|
||||
@@ -254,15 +255,11 @@ do_constraints (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
GtkWidget *box, *grid;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Constraints");
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
@@ -272,12 +269,6 @@ do_constraints (GtkWidget *do_widget)
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
gtk_widget_set_vexpand (grid, TRUE);
|
||||
gtk_box_append (GTK_BOX (box), grid);
|
||||
|
||||
button = gtk_button_new_with_label ("Close");
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK (gtk_window_destroy), window);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Constraints/Interactive
|
||||
* #Keywords: GtkConstraintLayout
|
||||
*
|
||||
* Demonstrate how constraints can be updates during user interaction.
|
||||
* The vertical edge between the buttons can be dragged with the mouse.
|
||||
@@ -210,15 +211,11 @@ do_constraints2 (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
GtkWidget *box, *grid;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Constraints");
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
@@ -228,12 +225,6 @@ do_constraints2 (GtkWidget *do_widget)
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
gtk_widget_set_vexpand (grid, TRUE);
|
||||
gtk_box_append (GTK_BOX (box), grid);
|
||||
|
||||
button = gtk_button_new_with_label ("Close");
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK (gtk_window_destroy), window);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
@@ -130,15 +130,11 @@ do_constraints3 (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *header, *box, *grid, *button;
|
||||
GtkWidget *box, *grid;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Constraints");
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
||||
@@ -148,12 +144,6 @@ do_constraints3 (GtkWidget *do_widget)
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
gtk_widget_set_vexpand (grid, TRUE);
|
||||
gtk_box_append (GTK_BOX (box), grid);
|
||||
|
||||
button = gtk_button_new_with_label ("Close");
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
gtk_widget_set_hexpand (grid, TRUE);
|
||||
g_signal_connect_swapped (button, "clicked",
|
||||
G_CALLBACK (gtk_window_destroy), window);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
@@ -1,7 +1,6 @@
|
||||
/* Theming/CSS Accordion
|
||||
*
|
||||
* A simple accordion demo written using CSS transitions and multiple backgrounds
|
||||
*
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
@@ -1,8 +1,7 @@
|
||||
/* Theming/CSS Basics
|
||||
*
|
||||
* Gtk themes are written using CSS. Every widget is build of multiple items
|
||||
* GTK themes are written using CSS. Every widget is build of multiple items
|
||||
* that you can style very similarly to a regular website.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
@@ -1,8 +1,7 @@
|
||||
/* Theming/Multiple Backgrounds
|
||||
*
|
||||
* Gtk themes are written using CSS. Every widget is build of multiple items
|
||||
* GTK themes are written using CSS. Every widget is build of multiple items
|
||||
* that you can style very similarly to a regular website.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
@@ -1,6 +1,7 @@
|
||||
/* Theming/Animated Backgrounds
|
||||
*
|
||||
* This demo is done in honour of the Pixbufs demo further down.
|
||||
* This demo is in honour of a classic Pixbufs demo.
|
||||
*
|
||||
* It is done exclusively with CSS as the background of the window.
|
||||
*/
|
||||
|
||||
|
@@ -46,8 +46,8 @@
|
||||
}
|
||||
|
||||
@keyframes size-the-image {
|
||||
0% { background-size: 96px, 12px, 96px, 12px, 96px, 12px, 96px, 12px, auto }
|
||||
100% { background-size: 12px, 96px, 12px, 96px, 12px, 96px, 12px, 96px, auto }
|
||||
0% { background-size: 96px, 12px, 96px, 12px, 96px, 12px, 96px, 12px, auto; }
|
||||
100% { background-size: 12px, 96px, 12px, 96px, 12px, 96px, 12px, 96px, auto; }
|
||||
}
|
||||
|
||||
window {
|
||||
|
@@ -112,6 +112,9 @@
|
||||
<gresource prefix="/dnd">
|
||||
<file>dnd.css</file>
|
||||
</gresource>
|
||||
<gresource prefix="/errorstates">
|
||||
<file>errorstates.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/fishbowl">
|
||||
<file>fishbowl.ui</file>
|
||||
<file>gtkfishbowl.c</file>
|
||||
@@ -121,6 +124,26 @@
|
||||
<file>gtkgears.c</file>
|
||||
<file>gtkgears.h</file>
|
||||
</gresource>
|
||||
<gresource prefix="/shadertoy">
|
||||
<file>gtkshadertoy.c</file>
|
||||
<file>gtkshadertoy.h</file>
|
||||
<file>alienplanet.glsl</file>
|
||||
<file>mandelbrot.glsl</file>
|
||||
<file>neon.glsl</file>
|
||||
<file>cogs.glsl</file>
|
||||
<file>glowingstars.glsl</file>
|
||||
</gresource>
|
||||
<gresource prefix="/glshader">
|
||||
<file>fire.glsl</file>
|
||||
</gresource>
|
||||
<gresource prefix="/gltransition">
|
||||
<file>gtkshaderstack.c</file>
|
||||
<file>gtkshaderstack.h</file>
|
||||
<file>transition1.glsl</file>
|
||||
<file>transition2.glsl</file>
|
||||
<file>transition3.glsl</file>
|
||||
<file>transition4.glsl</file>
|
||||
</gresource>
|
||||
<gresource prefix="/iconscroll">
|
||||
<file>iconscroll.ui</file>
|
||||
</gresource>
|
||||
@@ -164,6 +187,16 @@
|
||||
<file compressed="true">color.names.txt</file>
|
||||
<file>listview_colors.css</file>
|
||||
</gresource>
|
||||
<gresource prefix="/main">
|
||||
<file>fontify.c</file>
|
||||
<file>fontify.h</file>
|
||||
<file>main.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/menu">
|
||||
<file>demo3widget.c</file>
|
||||
<file>demo3widget.h</file>
|
||||
<file>demo3widget.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/shortcuts">
|
||||
<file>shortcuts.ui</file>
|
||||
<file>shortcuts-builder.ui</file>
|
||||
@@ -187,6 +220,9 @@
|
||||
<file>floppybuddy.gif</file>
|
||||
<file>gtk-logo.webm</file>
|
||||
</gresource>
|
||||
<gresource prefix="/video-player">
|
||||
<file>bbb.png</file>
|
||||
</gresource>
|
||||
<gresource prefix="/sources">
|
||||
<file>application_demo.c</file>
|
||||
<file>assistant.c</file>
|
||||
@@ -210,6 +246,7 @@
|
||||
<file>editable_cells.c</file>
|
||||
<file>entry_completion.c</file>
|
||||
<file>entry_undo.c</file>
|
||||
<file>errorstates.c</file>
|
||||
<file>expander.c</file>
|
||||
<file>filtermodel.c</file>
|
||||
<file>fishbowl.c</file>
|
||||
@@ -221,6 +258,8 @@
|
||||
<file>gears.c</file>
|
||||
<file>gestures.c</file>
|
||||
<file>glarea.c</file>
|
||||
<file>glshader.c</file>
|
||||
<file>gltransition.c</file>
|
||||
<file>headerbar.c</file>
|
||||
<file>hypertext.c</file>
|
||||
<file>iconscroll.c</file>
|
||||
@@ -242,13 +281,16 @@
|
||||
<file>listview_weather.c</file>
|
||||
<file>listview_words.c</file>
|
||||
<file>list_store.c</file>
|
||||
<file>main.c</file>
|
||||
<file>markup.c</file>
|
||||
<file>menu.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_emblem.c</file>
|
||||
<file>paintable_mediastream.c</file>
|
||||
<file>panes.c</file>
|
||||
<file>password_entry.c</file>
|
||||
@@ -260,6 +302,7 @@
|
||||
<file>scale.c</file>
|
||||
<file>search_entry.c</file>
|
||||
<file>search_entry2.c</file>
|
||||
<file>shadertoy.c</file>
|
||||
<file>shortcuts.c</file>
|
||||
<file>shortcut_triggers.c</file>
|
||||
<file>sizegroup.c</file>
|
||||
|
@@ -29,29 +29,24 @@
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_New</attribute>
|
||||
<attribute name="action">win.new</attribute>
|
||||
<attribute name="accel"><Control>n</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Open</attribute>
|
||||
<attribute name="action">win.open</attribute>
|
||||
<attribute name="accel"><Control>o</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Save</attribute>
|
||||
<attribute name="action">win.save</attribute>
|
||||
<attribute name="accel"><Control>s</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Save _As</attribute>
|
||||
<attribute name="action">win.save-as</attribute>
|
||||
<attribute name="accel"><Control>q</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Quit</attribute>
|
||||
<attribute name="action">win.quit</attribute>
|
||||
<attribute name="accel"><Control><Shift>s</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</submenu>
|
||||
@@ -61,17 +56,14 @@
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Copy</attribute>
|
||||
<attribute name="action">win.copy</attribute>
|
||||
<attribute name="accel"><Control>c</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Cut</attribute>
|
||||
<attribute name="action">win.cut</attribute>
|
||||
<attribute name="accel"><Control>x</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Paste</attribute>
|
||||
<attribute name="action">win.paste</attribute>
|
||||
<attribute name="accel"><Control>v</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</submenu>
|
||||
@@ -81,12 +73,10 @@
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Help</attribute>
|
||||
<attribute name="action">win.help</attribute>
|
||||
<attribute name="accel">F1</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_About</attribute>
|
||||
<attribute name="action">win.about</attribute>
|
||||
<attribute name="accel">F7</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</submenu>
|
||||
@@ -110,11 +100,15 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="toolbar1">
|
||||
<style>
|
||||
<class name="toolbar"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<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>
|
||||
<property name="action-name">win.new</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
@@ -122,6 +116,7 @@
|
||||
<property name="label" translatable="yes">Open</property>
|
||||
<property name="tooltip-text" translatable="yes">Open a file</property>
|
||||
<property name="icon-name">document-open</property>
|
||||
<property name="action-name">win.open</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
@@ -129,6 +124,7 @@
|
||||
<property name="label" translatable="yes">Save</property>
|
||||
<property name="tooltip-text" translatable="yes">Save a file</property>
|
||||
<property name="icon-name">document-save</property>
|
||||
<property name="action-name">win.save</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
@@ -139,6 +135,7 @@
|
||||
<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>
|
||||
<property name="action-name">win.copy</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
@@ -146,6 +143,7 @@
|
||||
<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>
|
||||
<property name="action-name">win.cut</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
@@ -153,6 +151,7 @@
|
||||
<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>
|
||||
<property name="action-name">win.paste</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@@ -106,10 +106,10 @@ demo2_layout_allocate (GtkLayoutManager *layout_manager,
|
||||
|
||||
gtk_widget_set_child_visible (child, FALSE);
|
||||
|
||||
graphene_point3d_init (&p1, 0., 0., 1.);
|
||||
graphene_point3d_init (&p1, w, h, 1.);
|
||||
graphene_point3d_init (&p2, w, 0., 1.);
|
||||
graphene_point3d_init (&p3, 0., h, 1.);
|
||||
graphene_point3d_init (&p4, w, h, 1.);
|
||||
graphene_point3d_init (&p3, 0., 0., 1.);
|
||||
graphene_point3d_init (&p4, 0., h, 1.);
|
||||
|
||||
t_1 = RADIANS (map_offset (offset + 10 * j));
|
||||
t_2 = RADIANS (map_offset (offset + 10 * (j + 1)));
|
||||
@@ -129,8 +129,8 @@ demo2_layout_allocate (GtkLayoutManager *layout_manager,
|
||||
|
||||
graphene_point3d_init (&q1, x0 + SX (r, t_1, p_1), y0 + SY (r, t_1, p_1), SZ (r, t_1, p_1));
|
||||
graphene_point3d_init (&q2, x0 + SX (r, t_2, p_1), y0 + SY (r, t_2, p_1), SZ (r, t_2, p_1));
|
||||
graphene_point3d_init (&q3, x0 + SX (r, t_1, p_2), y0 + SY (r, t_1, p_2), SZ (r, t_1, p_2));
|
||||
graphene_point3d_init (&q4, x0 + SX (r, t_2, p_2), y0 + SY (r, t_2, p_2), SZ (r, t_2, p_2));
|
||||
graphene_point3d_init (&q3, x0 + SX (r, t_2, p_2), y0 + SY (r, t_2, p_2), SZ (r, t_2, p_2));
|
||||
graphene_point3d_init (&q4, x0 + SX (r, t_1, p_2), y0 + SY (r, t_1, p_2), SZ (r, t_1, p_2));
|
||||
|
||||
/* Get a matrix that moves p1 -> q1, p2 -> q2, ... */
|
||||
perspective_3d (&p1, &p2, &p3, &p4,
|
||||
|
243
demos/gtk-demo/demo3widget.c
Normal file
243
demos/gtk-demo/demo3widget.c
Normal file
@@ -0,0 +1,243 @@
|
||||
#include <math.h>
|
||||
#include "demo3widget.h"
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_PAINTABLE = 1,
|
||||
PROP_SCALE
|
||||
};
|
||||
|
||||
struct _Demo3Widget
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GdkPaintable *paintable;
|
||||
float scale;
|
||||
|
||||
GtkWidget *menu;
|
||||
};
|
||||
|
||||
struct _Demo3WidgetClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (Demo3Widget, demo3_widget, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
demo3_widget_init (Demo3Widget *self)
|
||||
{
|
||||
self->scale = 1.f;
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static void
|
||||
demo3_widget_dispose (GObject *object)
|
||||
{
|
||||
Demo3Widget *self = DEMO3_WIDGET (object);
|
||||
|
||||
g_clear_object (&self->paintable);
|
||||
g_clear_pointer (&self->menu, gtk_widget_unparent);
|
||||
|
||||
G_OBJECT_CLASS (demo3_widget_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
demo3_widget_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
Demo3Widget *self = DEMO3_WIDGET (widget);
|
||||
int x, y, width, height;
|
||||
double w, h;
|
||||
|
||||
width = gtk_widget_get_width (widget);
|
||||
height = gtk_widget_get_height (widget);
|
||||
|
||||
w = self->scale * gdk_paintable_get_intrinsic_width (self->paintable);
|
||||
h = self->scale * gdk_paintable_get_intrinsic_height (self->paintable);
|
||||
|
||||
x = MAX (0, (width - ceil (w)) / 2);
|
||||
y = MAX (0, (height - ceil (h)) / 2);
|
||||
|
||||
gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
|
||||
gdk_paintable_snapshot (self->paintable, snapshot, w, h);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
demo3_widget_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
Demo3Widget *self = DEMO3_WIDGET (widget);
|
||||
int size;
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
size = gdk_paintable_get_intrinsic_width (self->paintable);
|
||||
else
|
||||
size = gdk_paintable_get_intrinsic_height (self->paintable);
|
||||
|
||||
*minimum = *natural = self->scale * size;
|
||||
}
|
||||
|
||||
static void
|
||||
demo3_widget_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
Demo3Widget *self = DEMO3_WIDGET (widget);
|
||||
|
||||
/* Since we are not using a layout manager (who would do this
|
||||
* for us), we need to allocate a size for our menu by calling
|
||||
* gtk_native_check_resize().
|
||||
*/
|
||||
gtk_native_check_resize (GTK_NATIVE (self->menu));
|
||||
}
|
||||
|
||||
static void
|
||||
demo3_widget_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
Demo3Widget *self = DEMO3_WIDGET (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PAINTABLE:
|
||||
g_clear_object (&self->paintable);
|
||||
self->paintable = g_value_dup_object (value);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (object));
|
||||
break;
|
||||
|
||||
case PROP_SCALE:
|
||||
self->scale = g_value_get_float (value);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (object));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
demo3_widget_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
Demo3Widget *self = DEMO3_WIDGET (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PAINTABLE:
|
||||
g_value_set_object (value, self->paintable);
|
||||
break;
|
||||
|
||||
case PROP_SCALE:
|
||||
g_value_set_float (value, self->scale);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pressed_cb (GtkGestureClick *gesture,
|
||||
guint n_press,
|
||||
double x,
|
||||
double y,
|
||||
Demo3Widget *self)
|
||||
{
|
||||
/* We are placing our menu at the point where
|
||||
* the click happened, before popping it up.
|
||||
*/
|
||||
gtk_popover_set_pointing_to (GTK_POPOVER (self->menu),
|
||||
&(const GdkRectangle){ x, y, 1, 1 });
|
||||
gtk_popover_popup (GTK_POPOVER (self->menu));
|
||||
}
|
||||
|
||||
static void
|
||||
zoom_cb (GtkWidget *widget,
|
||||
const char *action_name,
|
||||
GVariant *parameter)
|
||||
{
|
||||
Demo3Widget *self = DEMO3_WIDGET (widget);
|
||||
float scale;
|
||||
|
||||
if (g_str_equal (action_name, "zoom.in"))
|
||||
scale = MIN (10, self->scale * M_SQRT2);
|
||||
else if (g_str_equal (action_name, "zoom.out"))
|
||||
scale = MAX (0.01, self->scale / M_SQRT2);
|
||||
else
|
||||
scale = 1.0;
|
||||
|
||||
gtk_widget_action_set_enabled (widget, "zoom.in", scale < 10);
|
||||
gtk_widget_action_set_enabled (widget, "zoom.out", scale > 0.01);
|
||||
gtk_widget_action_set_enabled (widget, "zoom.reset", scale != 1);
|
||||
|
||||
g_object_set (widget, "scale", scale, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
demo3_widget_class_init (Demo3WidgetClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
object_class->dispose = demo3_widget_dispose;
|
||||
object_class->set_property = demo3_widget_set_property;
|
||||
object_class->get_property = demo3_widget_get_property;
|
||||
|
||||
widget_class->snapshot = demo3_widget_snapshot;
|
||||
widget_class->measure = demo3_widget_measure;
|
||||
widget_class->size_allocate = demo3_widget_size_allocate;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_PAINTABLE,
|
||||
g_param_spec_object ("paintable", "Paintable", "Paintable",
|
||||
GDK_TYPE_PAINTABLE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_SCALE,
|
||||
g_param_spec_float ("scale", "Scale", "Scale",
|
||||
0.0, 10.0, 1.0,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
/* These are the actions that we are using in the menu */
|
||||
gtk_widget_class_install_action (widget_class, "zoom.in", NULL, zoom_cb);
|
||||
gtk_widget_class_install_action (widget_class, "zoom.out", NULL, zoom_cb);
|
||||
gtk_widget_class_install_action (widget_class, "zoom.reset", NULL, zoom_cb);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/menu/demo3widget.ui");
|
||||
gtk_widget_class_bind_template_child (widget_class, Demo3Widget, menu);
|
||||
gtk_widget_class_bind_template_callback (widget_class, pressed_cb);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
demo3_widget_new (const char *resource)
|
||||
{
|
||||
Demo3Widget *self;
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkPaintable *paintable;
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_resource (resource, NULL);
|
||||
paintable = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (pixbuf));
|
||||
|
||||
self = g_object_new (DEMO3_TYPE_WIDGET, "paintable", paintable, NULL);
|
||||
|
||||
g_object_unref (pixbuf);
|
||||
g_object_unref (paintable);
|
||||
|
||||
return GTK_WIDGET (self);
|
||||
}
|
8
demos/gtk-demo/demo3widget.h
Normal file
8
demos/gtk-demo/demo3widget.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define DEMO3_TYPE_WIDGET (demo3_widget_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (Demo3Widget, demo3_widget, DEMO3, WIDGET, GtkWidget)
|
||||
|
||||
GtkWidget * demo3_widget_new (const char *resource);
|
30
demos/gtk-demo/demo3widget.ui
Normal file
30
demos/gtk-demo/demo3widget.ui
Normal file
@@ -0,0 +1,30 @@
|
||||
<interface>
|
||||
<menu id="model">
|
||||
<item>
|
||||
<attribute name="label">Zoom Out</attribute>
|
||||
<attribute name="action">zoom.out</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label">Zoom In</attribute>
|
||||
<attribute name="action">zoom.in</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label">1∶1</attribute>
|
||||
<attribute name="action">zoom.reset</attribute>
|
||||
</item>
|
||||
</menu>
|
||||
<template class="Demo3Widget">
|
||||
<child>
|
||||
<object class="GtkPopoverMenu" id="menu">
|
||||
<property name="has-arrow">0</property>
|
||||
<property name="menu-model">model</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGestureClick">
|
||||
<property name="button">3</property>
|
||||
<signal name="pressed" handler="pressed_cb"/>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
@@ -1,4 +1,5 @@
|
||||
/* Dialogs
|
||||
* #Keywords: GtkMessageDialog
|
||||
*
|
||||
* Dialogs are used to pop up transient windows for information
|
||||
* and user feedback.
|
||||
|
@@ -1,8 +1,12 @@
|
||||
/* Drag-and-Drop
|
||||
* #Keywords: dnd, menu, popover, gesture
|
||||
*
|
||||
* This demo shows dragging colors and widgets.
|
||||
* The items in this demo can be moved, recolored
|
||||
* and rotated.
|
||||
*
|
||||
* The demo also has an example for creating a
|
||||
* menu-like popover without using a menu model.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Drawing Area
|
||||
* #Keywords: GtkDrawingArea
|
||||
*
|
||||
* GtkDrawingArea is a blank area where you can draw custom displays
|
||||
* of various kinds.
|
||||
|
124
demos/gtk-demo/errorstates.c
Normal file
124
demos/gtk-demo/errorstates.c
Normal file
@@ -0,0 +1,124 @@
|
||||
/* Error states
|
||||
*
|
||||
* GtkLabel and GtkEntry can indicate errors if you set the .error
|
||||
* style class on them.
|
||||
*
|
||||
* This examples shows how this can be used in a dialog for input validation.
|
||||
*
|
||||
* It also shows how pass callbacks and objects to GtkBuilder with
|
||||
* GtkBuilderScope and gtk_builder_expose_object().
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static void
|
||||
validate_more_details (GtkEntry *entry,
|
||||
GParamSpec *pspec,
|
||||
GtkEntry *details)
|
||||
{
|
||||
if (strlen (gtk_editable_get_text (GTK_EDITABLE (entry))) > 0 &&
|
||||
strlen (gtk_editable_get_text (GTK_EDITABLE (details))) == 0)
|
||||
{
|
||||
gtk_widget_set_tooltip_text (GTK_WIDGET (entry), "Must have details first");
|
||||
gtk_widget_add_css_class (GTK_WIDGET (entry), "error");
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_tooltip_text (GTK_WIDGET (entry), "");
|
||||
gtk_widget_remove_css_class (GTK_WIDGET (entry), "error");
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
mode_switch_state_set (GtkSwitch *sw,
|
||||
gboolean state,
|
||||
GtkWidget *scale)
|
||||
{
|
||||
GtkWidget *label;
|
||||
|
||||
label = GTK_WIDGET (g_object_get_data (G_OBJECT (sw), "error_label"));
|
||||
|
||||
if (!state ||
|
||||
(gtk_range_get_value (GTK_RANGE (scale)) > 50))
|
||||
{
|
||||
gtk_widget_hide (label);
|
||||
gtk_switch_set_state (sw, state);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_show (label);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
level_scale_value_changed (GtkRange *range,
|
||||
GtkWidget *sw)
|
||||
{
|
||||
GtkWidget *label;
|
||||
|
||||
label = GTK_WIDGET (g_object_get_data (G_OBJECT (sw), "error_label"));
|
||||
|
||||
if (gtk_switch_get_active (GTK_SWITCH (sw)) &&
|
||||
!gtk_switch_get_state (GTK_SWITCH (sw)) &&
|
||||
(gtk_range_get_value (range) > 50))
|
||||
{
|
||||
gtk_widget_hide (label);
|
||||
gtk_switch_set_state (GTK_SWITCH (sw), TRUE);
|
||||
}
|
||||
else if (gtk_switch_get_state (GTK_SWITCH (sw)) &&
|
||||
(gtk_range_get_value (range) <= 50))
|
||||
{
|
||||
gtk_switch_set_state (GTK_SWITCH (sw), FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_errorstates (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
GtkBuilder *builder;
|
||||
GtkBuilderScope *scope;
|
||||
GtkWidget *sw, *label;
|
||||
|
||||
toplevel = GTK_WIDGET (gtk_widget_get_root (do_widget));
|
||||
|
||||
scope = gtk_builder_cscope_new ();
|
||||
gtk_builder_cscope_add_callback_symbols (GTK_BUILDER_CSCOPE (scope),
|
||||
"validate_more_details", G_CALLBACK (validate_more_details),
|
||||
"mode_switch_state_set", G_CALLBACK (mode_switch_state_set),
|
||||
"level_scale_value_changed", G_CALLBACK (level_scale_value_changed),
|
||||
NULL);
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
gtk_builder_set_scope (builder, scope);
|
||||
gtk_builder_expose_object (builder, "toplevel", G_OBJECT (toplevel));
|
||||
gtk_builder_add_from_resource (builder, "/errorstates/errorstates.ui", NULL);
|
||||
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "dialog"));
|
||||
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
sw = GTK_WIDGET (gtk_builder_get_object (builder, "mode_switch"));
|
||||
label = GTK_WIDGET (gtk_builder_get_object (builder, "error_label"));
|
||||
g_object_set_data (G_OBJECT (sw), "error_label", label);
|
||||
|
||||
g_object_unref (builder);
|
||||
g_object_unref (scope);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
158
demos/gtk-demo/errorstates.ui
Normal file
158
demos/gtk-demo/errorstates.ui
Normal file
@@ -0,0 +1,158 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GtkDialog" id="dialog">
|
||||
<property name="transient-for">toplevel</property>
|
||||
<property name="modal">1</property>
|
||||
<property name="resizable">0</property>
|
||||
<property name="use-header-bar">1</property>
|
||||
<property name="title" translatable="yes">Settings</property>
|
||||
<property name="hide-on-close">1</property>
|
||||
<child internal-child="content_area">
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="row-spacing">10</property>
|
||||
<property name="column-spacing">10</property>
|
||||
<property name="margin-start">20</property>
|
||||
<property name="margin-end">20</property>
|
||||
<property name="margin-top">20</property>
|
||||
<property name="margin-bottom">20</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="label">_Details</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="mnemonic-widget">details_entry</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="details_entry">
|
||||
<property name="valign">baseline</property>
|
||||
<signal name="notify::text" handler="validate_more_details" object="more_details_entry" swapped="yes"/>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">0</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="label">More D_etails</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="mnemonic-widget">more_details_entry</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="more_details_entry">
|
||||
<property name="valign">baseline</property>
|
||||
<signal name="notify::text" handler="validate_more_details" object="details_entry" swapped="no"/>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">1</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="label">_Level</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="mnemonic-widget">level_scale</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScale" id="level_scale">
|
||||
<property name="valign">baseline</property>
|
||||
<property name="draw-value">0</property>
|
||||
<property name="adjustment">
|
||||
<object class="GtkAdjustment">
|
||||
<property name="upper">100</property>
|
||||
<property name="lower">0</property>
|
||||
<property name="value">50</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="page-increment">10</property>
|
||||
</object>
|
||||
</property>
|
||||
<signal name="value-changed" handler="level_scale_value_changed" object="mode_switch" swapped="no"/>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">2</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="label">_Mode</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="mnemonic-widget">mode_switch</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="mode_switch">
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">baseline</property>
|
||||
<signal name="state-set" handler="mode_switch_state_set" object="level_scale" swapped="no"/>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="error_label">
|
||||
<property name="visible">0</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="label">Level too low</property>
|
||||
<style>
|
||||
<class name="error"/>
|
||||
</style>
|
||||
<layout>
|
||||
<property name="column">2</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
@@ -1,4 +1,5 @@
|
||||
/* Tree View/Filter Model
|
||||
* #Keywords: GtkTreeView
|
||||
*
|
||||
* This example demonstrates how GtkTreeModelFilter can be used not
|
||||
* just to show a subset of the rows, but also to compute columns
|
||||
|
72
demos/gtk-demo/fire.glsl
Normal file
72
demos/gtk-demo/fire.glsl
Normal file
@@ -0,0 +1,72 @@
|
||||
/* 2D -> [0..1] random number generator */
|
||||
float random(vec2 st) {
|
||||
return fract(sin(dot(st.xy,
|
||||
vec2(12.9898,78.233))) *
|
||||
43758.5453123);
|
||||
}
|
||||
|
||||
/* Generate a smoothed 2d noise based on random() */
|
||||
float noise(vec2 v) {
|
||||
/* Round point v to integer grid grid */
|
||||
vec2 grid_point = floor(v);
|
||||
/* Randomize in grid corners */
|
||||
float corner1 = random(grid_point);
|
||||
float corner2 = random(grid_point + vec2(1, 0));
|
||||
float corner3 = random(grid_point + vec2(0, 1));
|
||||
float corner4 = random(grid_point + vec2(1, 1));
|
||||
/* Interpolate smoothly between grid points */
|
||||
vec2 fraction = smoothstep(vec2(0.0), vec2(1.0), fract(v));
|
||||
return mix(mix(corner1, corner2, fraction.x),
|
||||
mix(corner3, corner4, fraction.x),
|
||||
fraction.y);
|
||||
}
|
||||
|
||||
/* fractal brownian motion noice, see https://www.iquilezles.org/www/articles/fbm/fbm.htm */
|
||||
float fbm(in vec2 x)
|
||||
{
|
||||
const float octaveScale = 1.9;
|
||||
const float G = 0.5;
|
||||
float f = 1.0;
|
||||
float a = 1.0;
|
||||
float t = 0.0;
|
||||
int numOctaves = 5;
|
||||
for (int i = 0; i < numOctaves; i++) {
|
||||
t += a*noise(f*x);
|
||||
f *= octaveScale;
|
||||
a *= G;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
|
||||
{
|
||||
float time = u_args.x;
|
||||
|
||||
vec2 xy = fragCoord / resolution;
|
||||
|
||||
float zoom = 3.0 - sin(time*0.5)*0.3;
|
||||
|
||||
// Normalize coord to height of widget
|
||||
vec2 p = (vec2 (-resolution.x/2 + fragCoord.x, resolution.y - fragCoord.y) / resolution.yy)* zoom;
|
||||
|
||||
// Use recursive incantations of fbm
|
||||
float q1 = fbm(p - vec2(0.8, 0.3) * time);
|
||||
float q2 = fbm(p - vec2(0.5, 1.3) * time);
|
||||
float r = fbm(2.0*p + vec2(q1,q2) - vec2(0.0, 1.0)*time*10.0 *0.4);
|
||||
|
||||
// Compute intensity, mostly on the bottom
|
||||
float w = 2 * r * p.y;
|
||||
|
||||
// Smooth out left/right side and fade in at start
|
||||
w /= smoothstep(0.0,0.1, xy.x)* smoothstep(0.0,0.1, 1.0-xy.x) * smoothstep(0.0,0.4, time);
|
||||
|
||||
// Compute colors
|
||||
vec3 c = vec3(1.0,.2,.05);
|
||||
vec3 color = 1.0 / (w*w/c + 1.0);
|
||||
|
||||
// Mix in widget
|
||||
vec4 widget = texture(u_source,uv);
|
||||
fragColor = mix(vec4(color,1), widget, 1.0-color.x);
|
||||
}
|
@@ -33,6 +33,9 @@
|
||||
<lookup name="framerate">bowl</lookup>
|
||||
</closure>
|
||||
</binding>
|
||||
<attributes>
|
||||
<attribute name="font-features" value="tnum=1"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Fixed Layout
|
||||
* #Keywords: GtkLayoutManager
|
||||
*
|
||||
* GtkFixed is a container that allows placing and transforming
|
||||
* widgets manually.
|
||||
|
@@ -24,15 +24,29 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
|
||||
GtkTextIter *end)
|
||||
{
|
||||
GtkTextTagTable *table;
|
||||
PangoAttribute *attr;
|
||||
GSList *attrs, *l;
|
||||
GtkTextTag *tag;
|
||||
char name[256];
|
||||
float fg_alpha, bg_alpha;
|
||||
|
||||
table = gtk_text_buffer_get_tag_table (buffer);
|
||||
|
||||
#define STRING_ATTR(pango_attr_name, attr_name) \
|
||||
attr = pango_attr_iterator_get (iter, pango_attr_name); \
|
||||
if (attr) \
|
||||
#define LANGUAGE_ATTR(attr_name) \
|
||||
{ \
|
||||
const char *language = pango_language_to_string (((PangoAttrLanguage*)attr)->value); \
|
||||
g_snprintf (name, 256, "language=%s", language); \
|
||||
tag = gtk_text_tag_table_lookup (table, name); \
|
||||
if (!tag) \
|
||||
{ \
|
||||
tag = gtk_text_tag_new (name); \
|
||||
g_object_set (tag, #attr_name, language, NULL); \
|
||||
gtk_text_tag_table_add (table, tag); \
|
||||
g_object_unref (tag); \
|
||||
} \
|
||||
gtk_text_buffer_apply_tag (buffer, tag, start, end); \
|
||||
}
|
||||
|
||||
#define STRING_ATTR(attr_name) \
|
||||
{ \
|
||||
const char *string = ((PangoAttrString*)attr)->value; \
|
||||
g_snprintf (name, 256, #attr_name "=%s", string); \
|
||||
@@ -47,9 +61,7 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
|
||||
gtk_text_buffer_apply_tag (buffer, tag, start, end); \
|
||||
}
|
||||
|
||||
#define INT_ATTR(pango_attr_name, attr_name) \
|
||||
attr = pango_attr_iterator_get (iter, pango_attr_name); \
|
||||
if (attr) \
|
||||
#define INT_ATTR(attr_name) \
|
||||
{ \
|
||||
int value = ((PangoAttrInt*)attr)->value; \
|
||||
g_snprintf (name, 256, #attr_name "=%d", value); \
|
||||
@@ -64,9 +76,24 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
|
||||
gtk_text_buffer_apply_tag (buffer, tag, start, end); \
|
||||
}
|
||||
|
||||
#define FLOAT_ATTR(pango_attr_name, attr_name) \
|
||||
attr = pango_attr_iterator_get (iter, pango_attr_name); \
|
||||
if (attr) \
|
||||
#define FONT_ATTR(attr_name) \
|
||||
{ \
|
||||
PangoFontDescription *desc = ((PangoAttrFontDesc*)attr)->desc; \
|
||||
char *str = pango_font_description_to_string (desc); \
|
||||
g_snprintf (name, 256, "font-desc=%s", str); \
|
||||
g_free (str); \
|
||||
tag = gtk_text_tag_table_lookup (table, name); \
|
||||
if (!tag) \
|
||||
{ \
|
||||
tag = gtk_text_tag_new (name); \
|
||||
g_object_set (tag, #attr_name, desc, NULL); \
|
||||
gtk_text_tag_table_add (table, tag); \
|
||||
g_object_unref (tag); \
|
||||
} \
|
||||
gtk_text_buffer_apply_tag (buffer, tag, start, end); \
|
||||
}
|
||||
|
||||
#define FLOAT_ATTR(attr_name) \
|
||||
{ \
|
||||
float value = ((PangoAttrFloat*)attr)->value; \
|
||||
g_snprintf (name, 256, #attr_name "=%g", value); \
|
||||
@@ -81,9 +108,7 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
|
||||
gtk_text_buffer_apply_tag (buffer, tag, start, end); \
|
||||
}
|
||||
|
||||
#define RGBA_ATTR(pango_attr_name, attr_name) \
|
||||
attr = pango_attr_iterator_get (iter, pango_attr_name); \
|
||||
if (attr) \
|
||||
#define RGBA_ATTR(attr_name, alpha_value) \
|
||||
{ \
|
||||
PangoColor *color; \
|
||||
GdkRGBA rgba; \
|
||||
@@ -91,7 +116,7 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
|
||||
rgba.red = color->red / 65535.; \
|
||||
rgba.green = color->green / 65535.; \
|
||||
rgba.blue = color->blue / 65535.; \
|
||||
rgba.alpha = 1.; \
|
||||
rgba.alpha = alpha_value; \
|
||||
char *str = gdk_rgba_to_string (&rgba); \
|
||||
g_snprintf (name, 256, #attr_name "=%s", str); \
|
||||
g_free (str); \
|
||||
@@ -106,63 +131,153 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
|
||||
gtk_text_buffer_apply_tag (buffer, tag, start, end); \
|
||||
}
|
||||
|
||||
attr = pango_attr_iterator_get (iter, PANGO_ATTR_LANGUAGE);
|
||||
if (attr)
|
||||
fg_alpha = bg_alpha = 1.;
|
||||
|
||||
attrs = pango_attr_iterator_get_attrs (iter);
|
||||
for (l = attrs; l; l = l->next)
|
||||
{
|
||||
const char *language = pango_language_to_string (((PangoAttrLanguage*)attr)->value);
|
||||
g_snprintf (name, 256, "language=%s", language);
|
||||
tag = gtk_text_tag_table_lookup (table, name);
|
||||
if (!tag)
|
||||
PangoAttribute *attr = l->data;
|
||||
|
||||
switch ((int)attr->klass->type)
|
||||
{
|
||||
tag = gtk_text_tag_new (name);
|
||||
g_object_set (tag, "language", language, NULL);
|
||||
gtk_text_tag_table_add (table, tag);
|
||||
g_object_unref (tag);
|
||||
case PANGO_ATTR_FOREGROUND_ALPHA:
|
||||
fg_alpha = ((PangoAttrInt*)attr)->value / 65535.;
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_BACKGROUND_ALPHA:
|
||||
bg_alpha = ((PangoAttrInt*)attr)->value / 65535.;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
gtk_text_buffer_apply_tag (buffer, tag, start, end);
|
||||
}
|
||||
|
||||
STRING_ATTR (PANGO_ATTR_FAMILY, family)
|
||||
INT_ATTR (PANGO_ATTR_STYLE, style)
|
||||
INT_ATTR (PANGO_ATTR_WEIGHT, weight)
|
||||
INT_ATTR (PANGO_ATTR_VARIANT, variant)
|
||||
INT_ATTR (PANGO_ATTR_STRETCH, stretch)
|
||||
INT_ATTR (PANGO_ATTR_SIZE, size)
|
||||
|
||||
attr = pango_attr_iterator_get (iter, PANGO_ATTR_FONT_DESC);
|
||||
if (attr)
|
||||
for (l = attrs; l; l = l->next)
|
||||
{
|
||||
PangoFontDescription *desc = ((PangoAttrFontDesc*)attr)->desc;
|
||||
char *str = pango_font_description_to_string (desc);
|
||||
g_snprintf (name, 256, "font-desc=%s", str);
|
||||
g_free (str);
|
||||
tag = gtk_text_tag_table_lookup (table, name);
|
||||
if (!tag)
|
||||
PangoAttribute *attr = l->data;
|
||||
|
||||
switch (attr->klass->type)
|
||||
{
|
||||
tag = gtk_text_tag_new (name);
|
||||
g_object_set (tag, "font-desc", desc, NULL);
|
||||
gtk_text_tag_table_add (table, tag);
|
||||
g_object_unref (tag);
|
||||
case PANGO_ATTR_LANGUAGE:
|
||||
LANGUAGE_ATTR (language);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_FAMILY:
|
||||
STRING_ATTR (family);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_STYLE:
|
||||
INT_ATTR (style);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_WEIGHT:
|
||||
INT_ATTR (weight);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_VARIANT:
|
||||
INT_ATTR (variant);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_STRETCH:
|
||||
INT_ATTR (stretch);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_SIZE:
|
||||
INT_ATTR (size);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_FONT_DESC:
|
||||
FONT_ATTR (font-desc);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_FOREGROUND:
|
||||
RGBA_ATTR (foreground_rgba, fg_alpha);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_BACKGROUND:
|
||||
RGBA_ATTR (background_rgba, bg_alpha);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_UNDERLINE:
|
||||
INT_ATTR (underline);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_UNDERLINE_COLOR:
|
||||
RGBA_ATTR (underline_rgba, fg_alpha);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_OVERLINE:
|
||||
INT_ATTR (overline);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_OVERLINE_COLOR:
|
||||
RGBA_ATTR (overline_rgba, fg_alpha);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_STRIKETHROUGH:
|
||||
INT_ATTR (strikethrough);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_STRIKETHROUGH_COLOR:
|
||||
RGBA_ATTR (strikethrough_rgba, fg_alpha);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_RISE:
|
||||
INT_ATTR (rise);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_SCALE:
|
||||
FLOAT_ATTR (scale);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_FALLBACK:
|
||||
INT_ATTR (fallback);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_LETTER_SPACING:
|
||||
INT_ATTR (letter_spacing);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_FONT_FEATURES:
|
||||
STRING_ATTR (font_features);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_ALLOW_BREAKS:
|
||||
INT_ATTR (allow_breaks);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_SHOW:
|
||||
INT_ATTR (show_spaces);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_INSERT_HYPHENS:
|
||||
INT_ATTR (insert_hyphens);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_SHAPE:
|
||||
case PANGO_ATTR_ABSOLUTE_SIZE:
|
||||
case PANGO_ATTR_GRAVITY:
|
||||
case PANGO_ATTR_GRAVITY_HINT:
|
||||
case PANGO_ATTR_FOREGROUND_ALPHA:
|
||||
case PANGO_ATTR_BACKGROUND_ALPHA:
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_INVALID:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
gtk_text_buffer_apply_tag (buffer, tag, start, end);
|
||||
}
|
||||
|
||||
RGBA_ATTR (PANGO_ATTR_FOREGROUND, foreground_rgba)
|
||||
RGBA_ATTR (PANGO_ATTR_BACKGROUND, background_rgba)
|
||||
INT_ATTR (PANGO_ATTR_UNDERLINE, underline)
|
||||
RGBA_ATTR (PANGO_ATTR_UNDERLINE_COLOR, underline_rgba)
|
||||
INT_ATTR (PANGO_ATTR_OVERLINE, overline)
|
||||
RGBA_ATTR (PANGO_ATTR_OVERLINE_COLOR, overline_rgba)
|
||||
INT_ATTR (PANGO_ATTR_STRIKETHROUGH, strikethrough)
|
||||
RGBA_ATTR (PANGO_ATTR_STRIKETHROUGH_COLOR, strikethrough_rgba)
|
||||
INT_ATTR (PANGO_ATTR_RISE, rise)
|
||||
FLOAT_ATTR (PANGO_ATTR_SCALE, scale)
|
||||
INT_ATTR (PANGO_ATTR_FALLBACK, fallback)
|
||||
INT_ATTR (PANGO_ATTR_LETTER_SPACING, letter_spacing)
|
||||
STRING_ATTR (PANGO_ATTR_FONT_FEATURES, font_features)
|
||||
INT_ATTR (PANGO_ATTR_ALLOW_BREAKS, allow_breaks)
|
||||
INT_ATTR (PANGO_ATTR_SHOW, show_spaces)
|
||||
INT_ATTR (PANGO_ATTR_INSERT_HYPHENS, insert_hyphens)
|
||||
g_slist_free_full (attrs, (GDestroyNotify)pango_attribute_destroy);
|
||||
|
||||
#undef LANGUAGE_ATTR
|
||||
#undef STRING_ATTR
|
||||
#undef INT_ATTR
|
||||
#undef FONT_ATTR
|
||||
#undef FLOAT_ATTR
|
||||
#undef RGBA_ATTR
|
||||
}
|
||||
|
||||
typedef struct
|
||||
|
@@ -63,11 +63,15 @@ unit_to (graphene_point3d_t *p1,
|
||||
graphene_matrix_multiply (&s, &u, m);
|
||||
}
|
||||
|
||||
/* Make a 4x4 matrix that maps
|
||||
/* Compute a 4x4 matrix m that maps
|
||||
* p1 -> q1
|
||||
* p2 -> q2
|
||||
* p3 -> q3
|
||||
* p4 -> q4
|
||||
*
|
||||
* This is not in general possible, because projective
|
||||
* transforms preserve coplanarity. But in the cases we
|
||||
* care about here, both sets of points are always coplanar.
|
||||
*/
|
||||
void
|
||||
perspective_3d (graphene_point3d_t *p1,
|
||||
|
@@ -6,6 +6,22 @@ import re
|
||||
import os
|
||||
from collections import *
|
||||
|
||||
def add_quotes(s):
|
||||
return "\"" + s.lower() + "\""
|
||||
|
||||
def wordify(s):
|
||||
return s.strip().rstrip(".,;:")
|
||||
|
||||
def is_keyword(s):
|
||||
if s == "GTK":
|
||||
return False
|
||||
elif s.startswith(("Gtk", "Gdk", "Pango")):
|
||||
return True
|
||||
elif s.startswith("G") and s[1].isupper():
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
out_file = sys.argv[1]
|
||||
in_files = sys.argv[2:]
|
||||
|
||||
@@ -19,13 +35,14 @@ struct _DemoData
|
||||
{
|
||||
const char *name;
|
||||
const char *title;
|
||||
const char **keywords;
|
||||
const char *filename;
|
||||
GDoDemoFunc func;
|
||||
DemoData *children;
|
||||
};
|
||||
"""
|
||||
|
||||
# Demo = namedtuple('Demo', ['name', 'title', 'file', 'func'])
|
||||
# Demo = namedtuple('Demo', ['name', 'title', 'keywords', 'file', 'func'])
|
||||
|
||||
demos = []
|
||||
|
||||
@@ -34,14 +51,17 @@ for demo_file in in_files:
|
||||
demo_name = filename.replace(".c", "")
|
||||
with open(demo_file, 'r', encoding='utf-8') as f:
|
||||
title = f.readline().replace("/*", "").strip()
|
||||
|
||||
keywords = set()
|
||||
line = f.readline().strip();
|
||||
while not line.endswith('*/'):
|
||||
if line.startswith("* #Keywords:"):
|
||||
keywords = keywords.union(set(map(wordify, line.replace ("* #Keywords:", "").strip().split(","))))
|
||||
else:
|
||||
keywords = keywords.union(set(filter(is_keyword, map(wordify, line.replace ("* ", "").split()))))
|
||||
line = f.readline().strip()
|
||||
|
||||
file_output += "GtkWidget *do_" + demo_name + " (GtkWidget *do_widget);\n"
|
||||
# demos += Demo(name = demo_name,
|
||||
# title = title,
|
||||
# file = demo_file,
|
||||
# func = "do_" + title)
|
||||
demos.append((demo_name, title, filename, "do_" + demo_name, -1))
|
||||
demos.append((demo_name, title, keywords, filename, "do_" + demo_name, -1))
|
||||
|
||||
# Generate a List of "Parent names"
|
||||
parents = []
|
||||
@@ -57,7 +77,7 @@ for demo in demos:
|
||||
if not parent_name in parents:
|
||||
parents.append(parent_name)
|
||||
parent_ids.append(parent_index)
|
||||
demos.append(("NULL", parent_name, "NULL", "NULL", parent_index))
|
||||
demos.append(("NULL", parent_name, set(), "NULL", "NULL", parent_index))
|
||||
|
||||
parent_index = parent_index + 1
|
||||
|
||||
@@ -71,8 +91,7 @@ for parent in parents:
|
||||
for child in demos:
|
||||
if child[1].startswith(parent + "/"):
|
||||
title = child[1][child[1].rfind('/') + 1:]
|
||||
file_output += " { \"" + child[0] + "\", \"" + title + "\", \"" + child[2] + "\", " + child[3] + ", NULL },\n"
|
||||
|
||||
file_output += " { \"" + child[0] + "\", \"" + title + "\", " + "(const char*[]) {" + ", ".join(list(map(add_quotes, child[2])) + ["NULL"]) + " }, \"" + child[3] + "\", " + child[4] + ", NULL },\n"
|
||||
|
||||
file_output += " { NULL }\n};\n"
|
||||
i = i + 1
|
||||
@@ -86,9 +105,10 @@ for demo in demos:
|
||||
# Do not generate one of these for demos with a parent demo
|
||||
if "/" not in demo[1]:
|
||||
child_array = "NULL"
|
||||
name = demo[0];
|
||||
title = demo[1];
|
||||
file = demo[2]
|
||||
name = demo[0]
|
||||
title = demo[1]
|
||||
keywords = demo[2]
|
||||
file = demo[3]
|
||||
if name != "NULL":
|
||||
name = "\"" + name + "\""
|
||||
if title != "NULL":
|
||||
@@ -96,9 +116,9 @@ for demo in demos:
|
||||
if file != "NULL":
|
||||
file = "\"" + file + "\""
|
||||
|
||||
if demo[4] != -1:
|
||||
child_array = "child" + str(demo[4])
|
||||
file_output += " { " + name + ", " + title + ", " + file + ", " + demo[3] + ", " + child_array + " },\n"
|
||||
if demo[5] != -1:
|
||||
child_array = "child" + str(demo[5])
|
||||
file_output += " { " + name + ", " + title + ", " + "(const char*[]) {" + ", ".join(list(map(add_quotes, keywords)) + ["NULL"]) + " }, " + file + ", " + demo[4] + ", " + child_array + " },\n"
|
||||
|
||||
file_output += " { NULL }\n};\n"
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Gestures
|
||||
* #Keywords: GtkGesture
|
||||
*
|
||||
* Perform gestures on touchscreens and other input devices. This
|
||||
* demo reacts to long presses and swipes from all devices, plus
|
||||
|
174
demos/gtk-demo/glowingstars.glsl
Normal file
174
demos/gtk-demo/glowingstars.glsl
Normal file
@@ -0,0 +1,174 @@
|
||||
// Originally from: https://www.shadertoy.com/view/ttBcRV
|
||||
// License CC0: Flying through glowing stars
|
||||
// The result of playing around trying to improve an old shader
|
||||
|
||||
#define PI 3.141592654
|
||||
#define TAU (2.0*PI)
|
||||
#define TIME iTime
|
||||
#define RESOLUTION iResolution
|
||||
|
||||
#define LESS(a,b,c) mix(a,b,step(0.,c))
|
||||
#define SABS(x,k) LESS((.5/(k))*(x)*(x)+(k)*.5,abs(x),abs(x)-(k))
|
||||
|
||||
#define MROT(a) mat2(cos(a), sin(a), -sin(a), cos(a))
|
||||
|
||||
vec3 hsv2rgb(vec3 c) {
|
||||
const vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
float hash(in vec3 co) {
|
||||
return fract(sin(dot(co, vec3(12.9898,58.233, 12.9898+58.233))) * 13758.5453);
|
||||
}
|
||||
|
||||
float starn(vec2 p, float r, int n, float m) {
|
||||
// From IQ: https://www.shadertoy.com/view/3tSGDy
|
||||
// https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm
|
||||
|
||||
// Minor tweak to use SABS over abs to smooth inner corners
|
||||
// SABS: https://www.shadertoy.com/view/Ws2SDK
|
||||
|
||||
// next 4 lines can be precomputed for a given shape
|
||||
float an = 3.141593/float(n);
|
||||
float en = 3.141593/m; // m is between 2 and n
|
||||
vec2 acs = vec2(cos(an),sin(an));
|
||||
vec2 ecs = vec2(cos(en),sin(en)); // ecs=vec2(0,1) for regular polygon,
|
||||
|
||||
float bn = mod(atan(p.x,p.y),2.0*an) - an;
|
||||
p = length(p)*vec2(cos(bn),SABS(sin(bn), 0.15));
|
||||
p -= r*acs;
|
||||
p += ecs*clamp( -dot(p,ecs), 0.0, r*acs.y/ecs.y);
|
||||
return length(p)*sign(p.x);
|
||||
}
|
||||
|
||||
vec4 alphaBlend(vec4 back, vec4 front) {
|
||||
vec3 xyz = mix(back.xyz*back.w, front.xyz, front.w);
|
||||
float w = mix(back.w, 1.0, front.w);
|
||||
return vec4(xyz, w);
|
||||
}
|
||||
|
||||
void rot(inout vec2 p, float a) {
|
||||
float c = cos(a);
|
||||
float s = sin(a);
|
||||
p = vec2(c*p.x + s*p.y, -s*p.x + c*p.y);
|
||||
}
|
||||
|
||||
vec3 offset(float z) {
|
||||
float a = z;
|
||||
vec2 p = -0.075*(vec2(cos(a), sin(a*sqrt(2.0))) + vec2(cos(a*sqrt(0.75)), sin(a*sqrt(0.5))));
|
||||
return vec3(p, z);
|
||||
}
|
||||
|
||||
vec3 doffset(float z) {
|
||||
float eps = 0.05;
|
||||
return 0.5*(offset(z + eps) - offset(z - eps))/eps;
|
||||
}
|
||||
|
||||
vec3 ddoffset(float z) {
|
||||
float eps = 0.05;
|
||||
return 0.5*(doffset(z + eps) - doffset(z - eps))/eps;
|
||||
}
|
||||
|
||||
vec4 planeCol(vec3 ro, vec3 rd, float n, vec3 pp) {
|
||||
const float s = 0.5;
|
||||
|
||||
vec2 p = pp.xy;
|
||||
float z = pp.z;
|
||||
vec2 dpy = dFdy(p);
|
||||
float aa = length(dpy);
|
||||
|
||||
p -= (1.0+5.0*(pp.z - ro.z))*offset(z).xy;
|
||||
|
||||
p *= s;
|
||||
float r = hash(vec3(floor(p+0.5), n));
|
||||
p = fract(p+0.5)-0.5;
|
||||
rot(p, ((TAU*r+n)*0.25));
|
||||
float d = starn(p, 0.20, 3 + 2*int(3.0*r), 3.0);
|
||||
d -= 0.06;
|
||||
d/=s;
|
||||
|
||||
float ds = -d+0.03;
|
||||
vec3 cols = hsv2rgb(vec3(337.0/360.0+0.1*sin(n*0.3), 0.8, 0.54+0.2*sin(n*0.3)));
|
||||
float ts = 1.0 - smoothstep(-aa, 0.0, ds);
|
||||
vec4 cs = vec4(cols, ts*0.93);
|
||||
|
||||
float db = abs(d) - (0.06);
|
||||
db = abs(db) - 0.03;
|
||||
db = abs(db) - 0.00;
|
||||
db = max(db, -d+0.03);
|
||||
vec3 colb = vec3(1.0, 0.7, 0.5);
|
||||
float tb = exp(-(db)*30.0*(1.0 - 10.0*aa));
|
||||
vec4 cb = vec4(1.5*colb, tb);
|
||||
|
||||
vec4 ct = alphaBlend(cs, cb);
|
||||
|
||||
return ct;
|
||||
}
|
||||
|
||||
vec3 color(vec3 ww, vec3 uu, vec3 vv, vec3 ro, vec2 p) {
|
||||
vec3 rd = normalize(p.x*uu + p.y*vv + (2.0-tanh(length(p)))*ww);
|
||||
|
||||
vec4 col = vec4(vec3(0.0), 1.0);
|
||||
|
||||
const float planeDist = 1.0;
|
||||
const int furthest = 6;
|
||||
const int fadeFrom = furthest-3;
|
||||
|
||||
float nz = floor(ro.z / planeDist);
|
||||
|
||||
for (int i = furthest; i >= 1; --i) {
|
||||
float pz = planeDist*nz + planeDist*float(i);
|
||||
|
||||
float pd = (pz - ro.z)/rd.z;
|
||||
|
||||
if (pd > 0.0) {
|
||||
vec3 pp = ro + rd*pd;
|
||||
|
||||
vec4 pcol = planeCol(ro, rd, nz+float(i), pp);
|
||||
float fadeIn = 1.0-smoothstep(planeDist*float(fadeFrom), planeDist*float(furthest), pp.z-ro.z);
|
||||
pcol.xyz *= sqrt(fadeIn);
|
||||
|
||||
col = alphaBlend(col, pcol);
|
||||
}
|
||||
}
|
||||
|
||||
return col.xyz*col.w;
|
||||
}
|
||||
|
||||
vec3 postProcess(vec3 col, vec2 q) {
|
||||
col=pow(clamp(col,0.0,1.0),vec3(0.75));
|
||||
col=col*0.6+0.4*col*col*(3.0-2.0*col);
|
||||
col=mix(col, vec3(dot(col, vec3(0.33))), -0.4);
|
||||
col*=0.5+0.5*pow(19.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.7);
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 effect(vec2 p, vec2 q) {
|
||||
float tm = TIME*0.65;
|
||||
|
||||
vec3 ro = offset(tm);
|
||||
vec3 dro = doffset(tm);
|
||||
vec3 ddro = ddoffset(tm);
|
||||
|
||||
vec3 ww = normalize(dro);
|
||||
vec3 uu = normalize(cross(vec3(0.0,1.0,0.0)+1.5*ddro, ww));
|
||||
vec3 vv = normalize(cross(ww, uu));
|
||||
|
||||
vec3 col = color(ww, uu, vv, ro, p);
|
||||
col = postProcess(col, q);
|
||||
|
||||
const float fadeIn = 2.0;
|
||||
|
||||
return col*smoothstep(0.0, fadeIn, TIME);
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, vec2 fragCoord) {
|
||||
vec2 q = fragCoord/RESOLUTION.xy;
|
||||
vec2 p = -1. + 2. * q;
|
||||
p.x *= RESOLUTION.x/RESOLUTION.y;
|
||||
|
||||
vec3 col = effect(p, q);
|
||||
|
||||
fragColor = vec4(col, 1.0);
|
||||
}
|
84
demos/gtk-demo/glshader.c
Normal file
84
demos/gtk-demo/glshader.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/* OpenGL/glshader
|
||||
* #Keywords: OpenGL, shader
|
||||
*
|
||||
* Generate pixels using a custom fragment shader.
|
||||
*
|
||||
* The names of the uniforms are compatible with the shaders on shadertoy.com, so
|
||||
* many of the shaders there work here too.
|
||||
*/
|
||||
#include <math.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtkshaderbin.h"
|
||||
|
||||
static GtkWidget *demo_window = NULL;
|
||||
|
||||
static void
|
||||
close_window (GtkWidget *widget)
|
||||
{
|
||||
/* Reset the state */
|
||||
demo_window = NULL;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
fire_bin_new (void)
|
||||
{
|
||||
GtkWidget *bin = gtk_shader_bin_new ();
|
||||
GBytes *shader_b;
|
||||
GskGLShader *shader;
|
||||
|
||||
shader_b = g_resources_lookup_data ("/glshader/fire.glsl", 0, NULL);
|
||||
shader = gsk_glshader_new ((const char *)g_bytes_get_data (shader_b, NULL));
|
||||
gtk_shader_bin_add_shader (GTK_SHADER_BIN (bin), shader, GTK_STATE_FLAG_PRELIGHT, GTK_STATE_FLAG_PRELIGHT);
|
||||
|
||||
return bin;
|
||||
}
|
||||
|
||||
|
||||
static GtkWidget *
|
||||
create_glshader_window (GtkWidget *do_widget)
|
||||
{
|
||||
GtkWidget *window, *box, *button, *bin;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "glshader");
|
||||
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE);
|
||||
gtk_widget_set_margin_start (box, 12);
|
||||
gtk_widget_set_margin_end (box, 12);
|
||||
gtk_widget_set_margin_top (box, 12);
|
||||
gtk_widget_set_margin_bottom (box, 12);
|
||||
gtk_box_set_spacing (GTK_BOX (box), 6);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
bin = fire_bin_new ();
|
||||
gtk_box_append (GTK_BOX (box), bin);
|
||||
|
||||
button = gtk_button_new_with_label ("Click me");
|
||||
gtk_widget_set_receives_default (button, TRUE);
|
||||
gtk_shader_bin_set_child (GTK_SHADER_BIN (bin), button);
|
||||
|
||||
bin = fire_bin_new ();
|
||||
gtk_box_append (GTK_BOX (box), bin);
|
||||
|
||||
button = gtk_button_new_with_label ("Or me!");
|
||||
gtk_widget_set_receives_default (button, TRUE);
|
||||
gtk_shader_bin_set_child (GTK_SHADER_BIN (bin), button);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_glshader (GtkWidget *do_widget)
|
||||
{
|
||||
if (!demo_window)
|
||||
demo_window = create_glshader_window (do_widget);
|
||||
|
||||
if (!gtk_widget_get_visible (demo_window))
|
||||
gtk_widget_show (demo_window);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (demo_window));
|
||||
|
||||
return demo_window;
|
||||
}
|
113
demos/gtk-demo/gltransition.c
Normal file
113
demos/gtk-demo/gltransition.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/* OpenGL/Transitions
|
||||
* #Keywords: OpenGL, shader
|
||||
*
|
||||
* Create transitions between pages using a custom fragment shader.
|
||||
*
|
||||
* The examples here are taken from gl-transitions.com.
|
||||
*/
|
||||
#include <math.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "gtkshaderstack.h"
|
||||
|
||||
static GtkWidget *demo_window = NULL;
|
||||
|
||||
static void
|
||||
close_window (GtkWidget *widget)
|
||||
{
|
||||
/* Reset the state */
|
||||
demo_window = NULL;
|
||||
}
|
||||
|
||||
static GskGLShader *
|
||||
gsk_shader_new_from_resource (const char *resource_path)
|
||||
{
|
||||
GBytes *shader_b;
|
||||
GskGLShader *shader;
|
||||
|
||||
shader_b = g_resources_lookup_data (resource_path, 0, NULL);
|
||||
shader = gsk_glshader_new ((const char *)g_bytes_get_data (shader_b, NULL));
|
||||
g_bytes_unref (shader_b);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
make_shader_stack (const char *resource_path)
|
||||
{
|
||||
GtkWidget *stack, *child;
|
||||
GskGLShader *shader;
|
||||
|
||||
stack = gtk_shader_stack_new ();
|
||||
shader = gsk_shader_new_from_resource (resource_path);
|
||||
gtk_shader_stack_set_shader (GTK_SHADER_STACK (stack), shader);
|
||||
g_object_unref (shader);
|
||||
|
||||
child = gtk_picture_new_for_resource ("/css_pixbufs/background.jpg");
|
||||
gtk_picture_set_can_shrink (GTK_PICTURE (child), TRUE);
|
||||
gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child);
|
||||
|
||||
child = gtk_picture_new_for_resource ("/transparent/portland-rose.jpg");
|
||||
gtk_picture_set_can_shrink (GTK_PICTURE (child), TRUE);
|
||||
gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child);
|
||||
|
||||
child = gtk_picture_new_for_resource ("/css_blendmodes/ducky.png");
|
||||
gtk_picture_set_can_shrink (GTK_PICTURE (child), TRUE);
|
||||
gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child);
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_gltransition_window (GtkWidget *do_widget)
|
||||
{
|
||||
GtkWidget *window, *grid;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Transitions");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
|
||||
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
gtk_widget_set_halign (grid, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign (grid, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_margin_start (grid, 12);
|
||||
gtk_widget_set_margin_end (grid, 12);
|
||||
gtk_widget_set_margin_top (grid, 12);
|
||||
gtk_widget_set_margin_bottom (grid, 12);
|
||||
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
|
||||
gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
|
||||
gtk_grid_set_row_homogeneous (GTK_GRID (grid), TRUE);
|
||||
gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE);
|
||||
|
||||
gtk_window_set_child (GTK_WINDOW (window), grid);
|
||||
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
make_shader_stack ("/gltransition/transition1.glsl"),
|
||||
0, 0, 1, 1);
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
make_shader_stack ("/gltransition/transition2.glsl"),
|
||||
1, 0, 1, 1);
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
make_shader_stack ("/gltransition/transition3.glsl"),
|
||||
0, 1, 1, 1);
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
make_shader_stack ("/gltransition/transition4.glsl"),
|
||||
1, 1, 1, 1);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_gltransition (GtkWidget *do_widget)
|
||||
{
|
||||
if (!demo_window)
|
||||
demo_window = create_gltransition_window (do_widget);
|
||||
|
||||
if (!gtk_widget_get_visible (demo_window))
|
||||
gtk_widget_show (demo_window);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (demo_window));
|
||||
|
||||
return demo_window;
|
||||
}
|
219
demos/gtk-demo/gtkshaderbin.c
Normal file
219
demos/gtk-demo/gtkshaderbin.c
Normal file
@@ -0,0 +1,219 @@
|
||||
#include "gtkshaderbin.h"
|
||||
|
||||
typedef struct {
|
||||
GskGLShader *shader;
|
||||
GtkStateFlags state;
|
||||
GtkStateFlags state_mask;
|
||||
} ShaderInfo;
|
||||
|
||||
struct _GtkShaderBin
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
GtkWidget *child;
|
||||
GskGLShader *active_shader;
|
||||
GPtrArray *shaders;
|
||||
guint tick_id;
|
||||
float time;
|
||||
gint64 first_frame_time;
|
||||
};
|
||||
|
||||
struct _GtkShaderBinClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkShaderBin, gtk_shader_bin, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
shader_info_free (ShaderInfo *info)
|
||||
{
|
||||
g_object_unref (info->shader);
|
||||
g_free (info);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_bin_finalize (GObject *object)
|
||||
{
|
||||
GtkShaderBin *self = GTK_SHADER_BIN (object);
|
||||
|
||||
g_ptr_array_free (self->shaders, TRUE);
|
||||
|
||||
G_OBJECT_CLASS (gtk_shader_bin_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_bin_dispose (GObject *object)
|
||||
{
|
||||
GtkShaderBin *self = GTK_SHADER_BIN (object);
|
||||
|
||||
g_clear_pointer (&self->child, gtk_widget_unparent);
|
||||
|
||||
G_OBJECT_CLASS (gtk_shader_bin_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_shader_bin_tick (GtkWidget *widget,
|
||||
GdkFrameClock *frame_clock,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkShaderBin *self = GTK_SHADER_BIN (widget);
|
||||
gint64 frame_time;
|
||||
|
||||
frame_time = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
|
||||
if (self->first_frame_time == 0)
|
||||
self->first_frame_time = frame_time;
|
||||
self->time = (frame_time - self->first_frame_time) / (float)G_USEC_PER_SEC;
|
||||
|
||||
gtk_widget_queue_allocate (widget);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_bin_init (GtkShaderBin *self)
|
||||
{
|
||||
self->shaders = g_ptr_array_new_with_free_func ((GDestroyNotify)shader_info_free);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shader_bin_update_active_shader (GtkShaderBin *self)
|
||||
{
|
||||
GtkStateFlags new_state = gtk_widget_get_state_flags (GTK_WIDGET (self));
|
||||
GskGLShader *new_shader = NULL;
|
||||
|
||||
for (int i = 0; i < self->shaders->len; i++)
|
||||
{
|
||||
ShaderInfo *info = g_ptr_array_index (self->shaders, i);
|
||||
|
||||
if ((info->state_mask & new_state) == info->state)
|
||||
{
|
||||
new_shader = info->shader;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->active_shader == new_shader)
|
||||
return;
|
||||
|
||||
self->active_shader = new_shader;
|
||||
self->first_frame_time = 0;
|
||||
|
||||
if (self->active_shader)
|
||||
{
|
||||
if (self->tick_id == 0)
|
||||
self->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self),
|
||||
gtk_shader_bin_tick,
|
||||
NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self->tick_id != 0)
|
||||
{
|
||||
gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->tick_id);
|
||||
self->tick_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_widget_queue_allocate (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_bin_state_flags_changed (GtkWidget *widget,
|
||||
GtkStateFlags previous_state_flags)
|
||||
{
|
||||
GtkShaderBin *self = GTK_SHADER_BIN (widget);
|
||||
|
||||
gtk_shader_bin_update_active_shader (self);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shader_bin_add_shader (GtkShaderBin *self,
|
||||
GskGLShader *shader,
|
||||
GtkStateFlags state,
|
||||
GtkStateFlags state_mask)
|
||||
{
|
||||
ShaderInfo *info = g_new0 (ShaderInfo, 1);
|
||||
info->shader = g_object_ref (shader);
|
||||
info->state = state;
|
||||
info->state_mask = state_mask;
|
||||
|
||||
g_ptr_array_add (self->shaders, info);
|
||||
|
||||
gtk_shader_bin_update_active_shader (self);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shader_bin_set_child (GtkShaderBin *self,
|
||||
GtkWidget *child)
|
||||
{
|
||||
|
||||
if (self->child == child)
|
||||
return;
|
||||
|
||||
g_clear_pointer (&self->child, gtk_widget_unparent);
|
||||
|
||||
if (child)
|
||||
{
|
||||
self->child = child;
|
||||
gtk_widget_set_parent (child, GTK_WIDGET (self));
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_shader_bin_get_child (GtkShaderBin *self)
|
||||
{
|
||||
return self->child;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_bin_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
GtkShaderBin *self = GTK_SHADER_BIN (widget);
|
||||
int width, height;
|
||||
|
||||
width = gtk_widget_get_width (widget);
|
||||
height = gtk_widget_get_height (widget);
|
||||
|
||||
if (self->active_shader)
|
||||
{
|
||||
graphene_vec4_t args;
|
||||
gtk_snapshot_push_glshader (snapshot, self->active_shader,
|
||||
graphene_vec4_init (&args, self->time, 0, 0, 0),
|
||||
&GRAPHENE_RECT_INIT(0, 0, width, height),
|
||||
1);
|
||||
gtk_widget_snapshot_child (widget, self->child, snapshot);
|
||||
gtk_snapshot_pop (snapshot); /* Fallback */
|
||||
gtk_widget_snapshot_child (widget, self->child, snapshot);
|
||||
gtk_snapshot_pop (snapshot); /* Shader node child 1 */
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_snapshot_child (widget, self->child, snapshot);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_bin_class_init (GtkShaderBinClass *class)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = gtk_shader_bin_finalize;
|
||||
object_class->dispose = gtk_shader_bin_dispose;
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
|
||||
|
||||
widget_class->snapshot = gtk_shader_bin_snapshot;
|
||||
widget_class->state_flags_changed = gtk_shader_bin_state_flags_changed;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_shader_bin_new (void)
|
||||
{
|
||||
GtkShaderBin *self;
|
||||
|
||||
self = g_object_new (GTK_TYPE_SHADER_BIN, NULL);
|
||||
|
||||
return GTK_WIDGET (self);
|
||||
}
|
22
demos/gtk-demo/gtkshaderbin.h
Normal file
22
demos/gtk-demo/gtkshaderbin.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef __GTK_SHADER_BIN_H__
|
||||
#define __GTK_SHADER_BIN_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SHADER_BIN (gtk_shader_bin_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkShaderBin, gtk_shader_bin, GTK, SHADER_BIN, GtkWidget)
|
||||
|
||||
GtkWidget *gtk_shader_bin_new (void);
|
||||
void gtk_shader_bin_add_shader (GtkShaderBin *self,
|
||||
GskGLShader *shader,
|
||||
GtkStateFlags state,
|
||||
GtkStateFlags state_mask);
|
||||
void gtk_shader_bin_set_child (GtkShaderBin *self,
|
||||
GtkWidget *child);
|
||||
GtkWidget *gtk_shader_bin_get_child (GtkShaderBin *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SHADER_BIN_H__ */
|
255
demos/gtk-demo/gtkshaderstack.c
Normal file
255
demos/gtk-demo/gtkshaderstack.c
Normal file
@@ -0,0 +1,255 @@
|
||||
#include "gtkshaderstack.h"
|
||||
|
||||
struct _GtkShaderStack
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GskGLShader *shader;
|
||||
GPtrArray *children;
|
||||
int current;
|
||||
int next;
|
||||
|
||||
guint tick_id;
|
||||
float time;
|
||||
float duration;
|
||||
gint64 start_time;
|
||||
};
|
||||
|
||||
struct _GtkShaderStackClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GtkShaderStack, gtk_shader_stack, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
gtk_shader_stack_finalize (GObject *object)
|
||||
{
|
||||
GtkShaderStack *self = GTK_SHADER_STACK (object);
|
||||
|
||||
g_object_unref (self->shader);
|
||||
|
||||
G_OBJECT_CLASS (gtk_shader_stack_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
transition_cb (GtkWidget *widget,
|
||||
GdkFrameClock *clock,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkShaderStack *self = GTK_SHADER_STACK (widget);
|
||||
gint64 frame_time;
|
||||
|
||||
frame_time = gdk_frame_clock_get_frame_time (clock);
|
||||
|
||||
if (self->start_time == 0)
|
||||
self->start_time = frame_time;
|
||||
|
||||
self->time = (frame_time - self->start_time) / (float)G_USEC_PER_SEC;
|
||||
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
if (self->time >= self->duration)
|
||||
{
|
||||
self->current = self->next;
|
||||
self->next = -1;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
else
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
start_transition (GtkShaderStack *self)
|
||||
{
|
||||
self->start_time = 0;
|
||||
self->tick_id = gtk_widget_add_tick_callback (GTK_WIDGET (self),
|
||||
transition_cb,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
stop_transition (GtkShaderStack *self)
|
||||
{
|
||||
if (self->tick_id != 0)
|
||||
{
|
||||
gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->tick_id);
|
||||
self->tick_id = 0;
|
||||
}
|
||||
|
||||
self->next = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_stack_dispose (GObject *object)
|
||||
{
|
||||
GtkShaderStack *self = GTK_SHADER_STACK (object);
|
||||
|
||||
stop_transition (self);
|
||||
|
||||
g_clear_pointer (&self->children, g_ptr_array_unref);
|
||||
|
||||
G_OBJECT_CLASS (gtk_shader_stack_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clicked_cb (GtkGestureClick *gesture,
|
||||
guint n_pressed,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data)
|
||||
{
|
||||
GtkShaderStack *self = GTK_SHADER_STACK (data);
|
||||
|
||||
stop_transition (self);
|
||||
|
||||
self->next = (self->current + 1) % self->children->len;
|
||||
|
||||
start_transition (self);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_stack_init (GtkShaderStack *self)
|
||||
{
|
||||
GtkGesture *gesture;
|
||||
|
||||
self->children = g_ptr_array_new_with_free_func ((GDestroyNotify)gtk_widget_unparent);
|
||||
self->current = -1;
|
||||
self->next = -1;
|
||||
self->duration = 1.0;
|
||||
|
||||
gesture = gtk_gesture_click_new ();
|
||||
g_signal_connect (gesture, "pressed", G_CALLBACK (clicked_cb), self);
|
||||
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_stack_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
GtkShaderStack *self = GTK_SHADER_STACK (widget);
|
||||
int i;
|
||||
|
||||
*minimum = 0;
|
||||
*natural = 0;
|
||||
|
||||
for (i = 0; i < self->children->len; i++)
|
||||
{
|
||||
GtkWidget *child = g_ptr_array_index (self->children, i);
|
||||
int child_min, child_nat;
|
||||
|
||||
if (gtk_widget_get_visible (child))
|
||||
{
|
||||
gtk_widget_measure (child, orientation, for_size, &child_min, &child_nat, NULL, NULL);
|
||||
|
||||
*minimum = MAX (*minimum, child_min);
|
||||
*natural = MAX (*natural, child_nat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_stack_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkShaderStack *self = GTK_SHADER_STACK (widget);
|
||||
GtkAllocation child_allocation;
|
||||
GtkWidget *child;
|
||||
int i;
|
||||
|
||||
child_allocation.x = 0;
|
||||
child_allocation.y = 0;
|
||||
child_allocation.width = width;
|
||||
child_allocation.height = height;
|
||||
|
||||
for (i = 0; i < self->children->len; i++)
|
||||
{
|
||||
child = g_ptr_array_index (self->children, i);
|
||||
if (gtk_widget_get_visible (child))
|
||||
gtk_widget_size_allocate (child, &child_allocation, -1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_stack_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
GtkShaderStack *self = GTK_SHADER_STACK (widget);
|
||||
int width, height;
|
||||
GtkWidget *current, *next;
|
||||
|
||||
width = gtk_widget_get_width (widget);
|
||||
height = gtk_widget_get_height (widget);
|
||||
|
||||
current = g_ptr_array_index (self->children, self->current);
|
||||
|
||||
if (self->next == -1)
|
||||
{
|
||||
gtk_widget_snapshot_child (widget, current, snapshot);
|
||||
}
|
||||
else
|
||||
{
|
||||
graphene_vec4_t args;
|
||||
|
||||
next = g_ptr_array_index (self->children, self->next);
|
||||
|
||||
gtk_snapshot_push_glshader (snapshot, self->shader,
|
||||
graphene_vec4_init (&args, self->time, self->time / self->duration, 0, 0),
|
||||
&GRAPHENE_RECT_INIT(0, 0, width, height),
|
||||
2);
|
||||
gtk_widget_snapshot_child (widget, next, snapshot);
|
||||
gtk_snapshot_pop (snapshot); /* Fallback */
|
||||
gtk_widget_snapshot_child (widget, current, snapshot);
|
||||
gtk_snapshot_pop (snapshot); /* current child */
|
||||
gtk_widget_snapshot_child (widget, next, snapshot);
|
||||
gtk_snapshot_pop (snapshot); /* next child */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shader_stack_class_init (GtkShaderStackClass *class)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->finalize = gtk_shader_stack_finalize;
|
||||
object_class->dispose = gtk_shader_stack_dispose;
|
||||
|
||||
widget_class->snapshot = gtk_shader_stack_snapshot;
|
||||
widget_class->measure = gtk_shader_stack_measure;
|
||||
widget_class->size_allocate = gtk_shader_stack_size_allocate;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_shader_stack_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_SHADER_STACK, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shader_stack_set_shader (GtkShaderStack *self,
|
||||
GskGLShader *shader)
|
||||
{
|
||||
g_set_object (&self->shader, shader);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shader_stack_add_child (GtkShaderStack *self,
|
||||
GtkWidget *child)
|
||||
{
|
||||
g_ptr_array_add (self->children, child);
|
||||
gtk_widget_set_parent (child, GTK_WIDGET (self));
|
||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
||||
|
||||
if (self->current == -1)
|
||||
self->current = 0;
|
||||
}
|
19
demos/gtk-demo/gtkshaderstack.h
Normal file
19
demos/gtk-demo/gtkshaderstack.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef __GTK_SHADER_STACK_H__
|
||||
#define __GTK_SHADER_STACK_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SHADER_STACK (gtk_shader_stack_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkShaderStack, gtk_shader_stack, GTK, SHADER_STACK, GtkWidget)
|
||||
|
||||
GtkWidget * gtk_shader_stack_new (void);
|
||||
void gtk_shader_stack_set_shader (GtkShaderStack *self,
|
||||
GskGLShader *shader);
|
||||
void gtk_shader_stack_add_child (GtkShaderStack *self,
|
||||
GtkWidget *child);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SHADER_STACK_H__ */
|
524
demos/gtk-demo/gtkshadertoy.c
Normal file
524
demos/gtk-demo/gtkshadertoy.c
Normal file
@@ -0,0 +1,524 @@
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
#include "gtkshadertoy.h"
|
||||
|
||||
const char *default_image_shader =
|
||||
"void mainImage(out vec4 fragColor, in vec2 fragCoord) {\n"
|
||||
" // Normalized pixel coordinates (from 0 to 1)\n"
|
||||
" vec2 uv = fragCoord/iResolution.xy;\n"
|
||||
"\n"
|
||||
" // Time varying pixel color\n"
|
||||
" vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));\n"
|
||||
"\n"
|
||||
" if (distance(iMouse.xy, fragCoord.xy) <= 10.0) {\n"
|
||||
" col = vec3(0.0);\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // Output to screen\n"
|
||||
" fragColor = vec4(col,1.0);\n"
|
||||
"}\n";
|
||||
|
||||
const char *shadertoy_vertex_shader =
|
||||
"#version 150 core\n"
|
||||
"\n"
|
||||
"uniform vec3 iResolution;\n"
|
||||
"\n"
|
||||
"in vec2 position;\n"
|
||||
"out vec2 fragCoord;\n"
|
||||
"\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = vec4(position, 0.0, 1.0);\n"
|
||||
"\n"
|
||||
" // Convert from OpenGL coordinate system (with origin in center\n"
|
||||
" // of screen) to Shadertoy/texture coordinate system (with origin\n"
|
||||
" // in lower left corner)\n"
|
||||
" fragCoord = (gl_Position.xy + vec2(1.0)) / vec2(2.0) * iResolution.xy;\n"
|
||||
"}\n";
|
||||
|
||||
const char *fragment_prefix =
|
||||
"#version 150 core\n"
|
||||
"\n"
|
||||
"uniform vec3 iResolution; // viewport resolution (in pixels)\n"
|
||||
"uniform float iTime; // shader playback time (in seconds)\n"
|
||||
"uniform float iTimeDelta; // render time (in seconds)\n"
|
||||
"uniform int iFrame; // shader playback frame\n"
|
||||
"uniform float iChannelTime[4]; // channel playback time (in seconds)\n"
|
||||
"uniform vec3 iChannelResolution[4]; // channel resolution (in pixels)\n"
|
||||
"uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down), zw: click\n"
|
||||
"uniform sampler2D iChannel0;\n"
|
||||
"uniform sampler2D iChannel1;\n"
|
||||
"uniform sampler2D iChannel2;\n"
|
||||
"uniform sampler2D iChannel3;\n"
|
||||
"uniform vec4 iDate; // (year, month, day, time in seconds)\n"
|
||||
"uniform float iSampleRate; // sound sample rate (i.e., 44100)\n"
|
||||
"\n"
|
||||
"in vec2 fragCoord;\n"
|
||||
"out vec4 fragColor;\n";
|
||||
|
||||
|
||||
// Fragment shader suffix
|
||||
const char *fragment_suffix =
|
||||
" void main() {\n"
|
||||
" mainImage(fragColor, fragCoord);\n"
|
||||
" }\n";
|
||||
|
||||
typedef struct {
|
||||
char *image_shader;
|
||||
gboolean image_shader_dirty;
|
||||
|
||||
gboolean error_set;
|
||||
|
||||
/* Vertex buffers */
|
||||
GLuint vao;
|
||||
GLuint buffer;
|
||||
|
||||
/* Active program */
|
||||
GLuint program;
|
||||
|
||||
/* Location of uniforms for program */
|
||||
GLuint resolution_location;
|
||||
GLuint time_location;
|
||||
GLuint timedelta_location;
|
||||
GLuint frame_location;
|
||||
GLuint mouse_location;
|
||||
|
||||
/* Current uniform values */
|
||||
float resolution[3];
|
||||
float time;
|
||||
float timedelta;
|
||||
float mouse[4];
|
||||
int frame;
|
||||
|
||||
/* Animation data */
|
||||
gint64 first_frame_time;
|
||||
gint64 first_frame;
|
||||
guint tick;
|
||||
} GtkShadertoyPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkShadertoy, gtk_shadertoy, GTK_TYPE_GL_AREA)
|
||||
|
||||
static gboolean gtk_shadertoy_render (GtkGLArea *area,
|
||||
GdkGLContext *context);
|
||||
static void gtk_shadertoy_reshape (GtkGLArea *area,
|
||||
int width,
|
||||
int height);
|
||||
static void gtk_shadertoy_realize (GtkWidget *widget);
|
||||
static void gtk_shadertoy_unrealize (GtkWidget *widget);
|
||||
static gboolean gtk_shadertoy_tick (GtkWidget *widget,
|
||||
GdkFrameClock *frame_clock,
|
||||
gpointer user_data);
|
||||
|
||||
GtkWidget *
|
||||
gtk_shadertoy_new (void)
|
||||
{
|
||||
return g_object_new (gtk_shadertoy_get_type (), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
drag_begin_cb (GtkGestureDrag *drag,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkShadertoy *shadertoy = GTK_SHADERTOY (user_data);
|
||||
GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
|
||||
int height = gtk_widget_get_height (GTK_WIDGET (shadertoy));
|
||||
int scale = gtk_widget_get_scale_factor (GTK_WIDGET (shadertoy));
|
||||
|
||||
priv->mouse[0] = x * scale;
|
||||
priv->mouse[1] = (height - y) * scale;
|
||||
priv->mouse[2] = priv->mouse[0];
|
||||
priv->mouse[3] = priv->mouse[1];
|
||||
}
|
||||
|
||||
static void
|
||||
drag_update_cb (GtkGestureDrag *drag,
|
||||
double dx,
|
||||
double dy,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkShadertoy *shadertoy = GTK_SHADERTOY (user_data);
|
||||
GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
|
||||
int width = gtk_widget_get_width (GTK_WIDGET (shadertoy));
|
||||
int height = gtk_widget_get_height (GTK_WIDGET (shadertoy));
|
||||
int scale = gtk_widget_get_scale_factor (GTK_WIDGET (shadertoy));
|
||||
double x, y;
|
||||
|
||||
gtk_gesture_drag_get_start_point (drag, &x, &y);
|
||||
x += dx;
|
||||
y += dy;
|
||||
|
||||
if (x >= 0 && x < width &&
|
||||
y >= 0 && y < height)
|
||||
{
|
||||
priv->mouse[0] = x * scale;
|
||||
priv->mouse[1] = (height - y) * scale;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
drag_end_cb (GtkGestureDrag *drag,
|
||||
gdouble dx,
|
||||
gdouble dy,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkShadertoy *shadertoy = GTK_SHADERTOY (user_data);
|
||||
GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
|
||||
|
||||
priv->mouse[2] = -priv->mouse[2];
|
||||
priv->mouse[3] = -priv->mouse[3];
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shadertoy_init (GtkShadertoy *shadertoy)
|
||||
{
|
||||
GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
|
||||
GtkGesture *drag;
|
||||
|
||||
priv->image_shader = g_strdup (default_image_shader);
|
||||
priv->tick = gtk_widget_add_tick_callback (GTK_WIDGET (shadertoy), gtk_shadertoy_tick, shadertoy, NULL);
|
||||
|
||||
drag = gtk_gesture_drag_new ();
|
||||
gtk_widget_add_controller (GTK_WIDGET (shadertoy), GTK_EVENT_CONTROLLER (drag));
|
||||
g_signal_connect (drag, "drag-begin", (GCallback)drag_begin_cb, shadertoy);
|
||||
g_signal_connect (drag, "drag-update", (GCallback)drag_update_cb, shadertoy);
|
||||
g_signal_connect (drag, "drag-end", (GCallback)drag_end_cb, shadertoy);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shadertoy_finalize (GObject *obj)
|
||||
{
|
||||
GtkShadertoy *shadertoy = GTK_SHADERTOY (obj);
|
||||
GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
|
||||
|
||||
gtk_widget_remove_tick_callback (GTK_WIDGET (shadertoy), priv->tick);
|
||||
g_free (priv->image_shader);
|
||||
|
||||
G_OBJECT_CLASS (gtk_shadertoy_parent_class)->finalize (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shadertoy_class_init (GtkShadertoyClass *klass)
|
||||
{
|
||||
GTK_GL_AREA_CLASS (klass)->render = gtk_shadertoy_render;
|
||||
GTK_GL_AREA_CLASS (klass)->resize = gtk_shadertoy_reshape;
|
||||
|
||||
GTK_WIDGET_CLASS (klass)->realize = gtk_shadertoy_realize;
|
||||
GTK_WIDGET_CLASS (klass)->unrealize = gtk_shadertoy_unrealize;
|
||||
|
||||
G_OBJECT_CLASS (klass)->finalize = gtk_shadertoy_finalize;
|
||||
}
|
||||
|
||||
/* new window size or exposure */
|
||||
static void
|
||||
gtk_shadertoy_reshape (GtkGLArea *area, int width, int height)
|
||||
{
|
||||
GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private ((GtkShadertoy *) area);
|
||||
|
||||
priv->resolution[0] = width;
|
||||
priv->resolution[1] = height;
|
||||
priv->resolution[2] = 1.0; /* screen aspect ratio */
|
||||
|
||||
/* Set the viewport */
|
||||
glViewport (0, 0, (GLint) width, (GLint) height);
|
||||
}
|
||||
|
||||
static GLuint
|
||||
create_shader (int type,
|
||||
const char *src,
|
||||
GError **error)
|
||||
{
|
||||
GLuint shader;
|
||||
int status;
|
||||
|
||||
shader = glCreateShader (type);
|
||||
glShaderSource (shader, 1, &src, NULL);
|
||||
glCompileShader (shader);
|
||||
|
||||
glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
|
||||
if (status == GL_FALSE)
|
||||
{
|
||||
int log_len;
|
||||
char *buffer;
|
||||
|
||||
glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &log_len);
|
||||
|
||||
buffer = g_malloc (log_len + 1);
|
||||
glGetShaderInfoLog (shader, log_len, NULL, buffer);
|
||||
|
||||
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_COMPILATION_FAILED,
|
||||
"Compile failure in %s shader:\n%s",
|
||||
type == GL_VERTEX_SHADER ? "vertex" : "fragment",
|
||||
buffer);
|
||||
|
||||
g_free (buffer);
|
||||
|
||||
glDeleteShader (shader);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
init_shaders (GtkShadertoy *shadertoy,
|
||||
const char *vertex_source,
|
||||
const char *fragment_source,
|
||||
GError **error)
|
||||
{
|
||||
GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
|
||||
GLuint vertex, fragment;
|
||||
GLuint program = 0;
|
||||
int status;
|
||||
gboolean res = TRUE;
|
||||
|
||||
vertex = create_shader (GL_VERTEX_SHADER, vertex_source, error);
|
||||
if (vertex == 0)
|
||||
return FALSE;
|
||||
|
||||
fragment = create_shader (GL_FRAGMENT_SHADER, fragment_source, error);
|
||||
if (fragment == 0)
|
||||
{
|
||||
glDeleteShader (vertex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
program = glCreateProgram ();
|
||||
glAttachShader (program, vertex);
|
||||
glAttachShader (program, fragment);
|
||||
|
||||
glLinkProgram (program);
|
||||
|
||||
glGetProgramiv (program, GL_LINK_STATUS, &status);
|
||||
if (status == GL_FALSE)
|
||||
{
|
||||
int log_len;
|
||||
char *buffer;
|
||||
|
||||
glGetProgramiv (program, GL_INFO_LOG_LENGTH, &log_len);
|
||||
|
||||
buffer = g_malloc (log_len + 1);
|
||||
glGetProgramInfoLog (program, log_len, NULL, buffer);
|
||||
|
||||
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_LINK_FAILED,
|
||||
"Linking failure:\n%s", buffer);
|
||||
res = FALSE;
|
||||
|
||||
g_free (buffer);
|
||||
|
||||
glDeleteProgram (program);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (priv->program != 0)
|
||||
glDeleteProgram (priv->program);
|
||||
|
||||
priv->program = program;
|
||||
priv->resolution_location = glGetUniformLocation (program, "iResolution");
|
||||
priv->time_location = glGetUniformLocation (program, "iTime");
|
||||
priv->timedelta_location = glGetUniformLocation (program, "iTimeDelta");
|
||||
priv->frame_location = glGetUniformLocation (program, "iFrame");
|
||||
priv->mouse_location = glGetUniformLocation (program, "iMouse");
|
||||
|
||||
glDetachShader (program, vertex);
|
||||
glDetachShader (program, fragment);
|
||||
|
||||
out:
|
||||
/* These are now owned by the program and can be deleted */
|
||||
glDeleteShader (vertex);
|
||||
glDeleteShader (fragment);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shadertoy_realize_shader (GtkShadertoy *shadertoy)
|
||||
{
|
||||
GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
|
||||
char *fragment_shader;
|
||||
GError *error = NULL;
|
||||
|
||||
fragment_shader = g_strconcat (fragment_prefix, priv->image_shader, fragment_suffix, NULL);
|
||||
if (!init_shaders (shadertoy, shadertoy_vertex_shader, fragment_shader, &error))
|
||||
{
|
||||
priv->error_set = TRUE;
|
||||
gtk_gl_area_set_error (GTK_GL_AREA (shadertoy), error);
|
||||
g_error_free (error);
|
||||
}
|
||||
g_free (fragment_shader);
|
||||
|
||||
/* Start new shader at time zero */
|
||||
priv->first_frame_time = 0;
|
||||
priv->first_frame = 0;
|
||||
|
||||
priv->image_shader_dirty = FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_shadertoy_render (GtkGLArea *area,
|
||||
GdkGLContext *context)
|
||||
{
|
||||
GtkShadertoy *shadertoy = GTK_SHADERTOY (area);
|
||||
GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
|
||||
|
||||
if (gtk_gl_area_get_error (area) != NULL)
|
||||
return FALSE;
|
||||
|
||||
if (priv->image_shader_dirty)
|
||||
gtk_shadertoy_realize_shader (shadertoy);
|
||||
|
||||
/* Clear the viewport */
|
||||
glClearColor (0.0, 0.0, 0.0, 1.0);
|
||||
glClear (GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glUseProgram (priv->program);
|
||||
|
||||
/* Update uniforms */
|
||||
if (priv->resolution_location != -1)
|
||||
glUniform3fv (priv->resolution_location, 1, priv->resolution);
|
||||
if (priv->time_location != -1)
|
||||
glUniform1f (priv->time_location, priv->time);
|
||||
if (priv->timedelta_location != -1)
|
||||
glUniform1f (priv->timedelta_location, priv->timedelta);
|
||||
if (priv->frame_location != -1)
|
||||
glUniform1i (priv->frame_location, priv->frame);
|
||||
if (priv->mouse_location != -1)
|
||||
glUniform4fv (priv->mouse_location, 1, priv->mouse);
|
||||
|
||||
/* Use the vertices in our buffer */
|
||||
glBindBuffer (GL_ARRAY_BUFFER, priv->buffer);
|
||||
glEnableVertexAttribArray (0);
|
||||
glVertexAttribPointer (0, 4, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
|
||||
glDrawArrays (GL_TRIANGLES, 0, 6);
|
||||
|
||||
/* We finished using the buffers and program */
|
||||
glDisableVertexAttribArray (0);
|
||||
glBindBuffer (GL_ARRAY_BUFFER, 0);
|
||||
glUseProgram (0);
|
||||
|
||||
/* Flush the contents of the pipeline */
|
||||
glFlush ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const char *
|
||||
gtk_shadertoy_get_image_shader (GtkShadertoy *shadertoy)
|
||||
{
|
||||
GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
|
||||
|
||||
return priv->image_shader;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_shadertoy_set_image_shader (GtkShadertoy *shadertoy,
|
||||
const char *shader)
|
||||
{
|
||||
GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
|
||||
|
||||
g_free (priv->image_shader);
|
||||
priv->image_shader = g_strdup (shader);
|
||||
|
||||
/* Don't override error we didn't set it ourselves */
|
||||
if (priv->error_set)
|
||||
{
|
||||
gtk_gl_area_set_error (GTK_GL_AREA (shadertoy), NULL);
|
||||
priv->error_set = FALSE;
|
||||
}
|
||||
priv->image_shader_dirty = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shadertoy_realize (GtkWidget *widget)
|
||||
{
|
||||
GtkGLArea *glarea = GTK_GL_AREA (widget);
|
||||
GtkShadertoy *shadertoy = GTK_SHADERTOY (widget);
|
||||
GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
|
||||
|
||||
/* Draw two triangles across whole screen */
|
||||
const GLfloat vertex_data[] = {
|
||||
-1.0f, -1.0f, 0.f, 1.f,
|
||||
-1.0f, 1.0f, 0.f, 1.f,
|
||||
1.0f, 1.0f, 0.f, 1.f,
|
||||
|
||||
-1.0f, -1.0f, 0.f, 1.f,
|
||||
1.0f, 1.0f, 0.f, 1.f,
|
||||
1.0f, -1.0f, 0.f, 1.f,
|
||||
};
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_shadertoy_parent_class)->realize (widget);
|
||||
|
||||
gtk_gl_area_make_current (glarea);
|
||||
if (gtk_gl_area_get_error (glarea) != NULL)
|
||||
return;
|
||||
|
||||
glGenVertexArrays (1, &priv->vao);
|
||||
glBindVertexArray (priv->vao);
|
||||
|
||||
glGenBuffers (1, &priv->buffer);
|
||||
glBindBuffer (GL_ARRAY_BUFFER, priv->buffer);
|
||||
glBufferData (GL_ARRAY_BUFFER, sizeof (vertex_data), vertex_data, GL_STATIC_DRAW);
|
||||
glBindBuffer (GL_ARRAY_BUFFER, 0);
|
||||
|
||||
gtk_shadertoy_realize_shader (shadertoy);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_shadertoy_unrealize (GtkWidget *widget)
|
||||
{
|
||||
GtkGLArea *glarea = GTK_GL_AREA (widget);
|
||||
GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private ((GtkShadertoy *) widget);
|
||||
|
||||
gtk_gl_area_make_current (glarea);
|
||||
if (gtk_gl_area_get_error (glarea) == NULL)
|
||||
{
|
||||
if (priv->buffer != 0)
|
||||
glDeleteBuffers (1, &priv->buffer);
|
||||
|
||||
if (priv->vao != 0)
|
||||
glDeleteVertexArrays (1, &priv->vao);
|
||||
|
||||
if (priv->program != 0)
|
||||
glDeleteProgram (priv->program);
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_shadertoy_parent_class)->unrealize (widget);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_shadertoy_tick (GtkWidget *widget,
|
||||
GdkFrameClock *frame_clock,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkShadertoy *shadertoy = GTK_SHADERTOY (widget);
|
||||
GtkShadertoyPrivate *priv = gtk_shadertoy_get_instance_private (shadertoy);
|
||||
gint64 frame_time;
|
||||
gint64 frame;
|
||||
float previous_time;
|
||||
|
||||
frame = gdk_frame_clock_get_frame_counter (frame_clock);
|
||||
frame_time = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
|
||||
if (priv->first_frame_time == 0)
|
||||
{
|
||||
priv->first_frame_time = frame_time;
|
||||
priv->first_frame = frame;
|
||||
previous_time = 0;
|
||||
}
|
||||
else
|
||||
previous_time = priv->time;
|
||||
|
||||
priv->time = (frame_time - priv->first_frame_time) / 1000000.0f;
|
||||
priv->frame = frame - priv->first_frame;
|
||||
priv->timedelta = priv->time - previous_time;
|
||||
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
34
demos/gtk-demo/gtkshadertoy.h
Normal file
34
demos/gtk-demo/gtkshadertoy.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef __GTK_SHADERTOY_H__
|
||||
#define __GTK_SHADERTOY_H__
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SHADERTOY (gtk_shadertoy_get_type ())
|
||||
#define GTK_SHADERTOY(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
|
||||
GTK_TYPE_SHADERTOY, \
|
||||
GtkShadertoy))
|
||||
#define GTK_IS_SHADERTOY(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
|
||||
GTK_TYPE_SHADERTOY))
|
||||
|
||||
typedef struct _GtkShadertoy GtkShadertoy;
|
||||
typedef struct _GtkShadertoyClass GtkShadertoyClass;
|
||||
|
||||
struct _GtkShadertoy {
|
||||
GtkGLArea parent;
|
||||
};
|
||||
|
||||
struct _GtkShadertoyClass {
|
||||
GtkGLAreaClass parent_class;
|
||||
};
|
||||
|
||||
GType gtk_shadertoy_get_type (void) G_GNUC_CONST;
|
||||
GtkWidget *gtk_shadertoy_new (void);
|
||||
const char *gtk_shadertoy_get_image_shader (GtkShadertoy *shadertoy);
|
||||
void gtk_shadertoy_set_image_shader (GtkShadertoy *shadertoy,
|
||||
const char *shader);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SHADERTOY_H__ */
|
@@ -1,4 +1,5 @@
|
||||
/* Header Bar
|
||||
* #Keywords: GtkWindowHandle, GtkWindowControls
|
||||
*
|
||||
* GtkHeaderBar is a container that is suitable for implementing
|
||||
* window titlebars. One of its features is that it can position
|
||||
@@ -48,6 +49,7 @@ do_headerbar (GtkWidget *do_widget)
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), box);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), gtk_switch_new ());
|
||||
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
|
||||
|
@@ -1,9 +1,13 @@
|
||||
/* Text View/Hypertext
|
||||
* #Keywords: GtkTextView, GtkTextBuffer
|
||||
*
|
||||
* Usually, tags modify the appearance of text in the view, e.g. making it
|
||||
* bold or colored or underlined. But tags are not restricted to appearance.
|
||||
* They can also affect the behavior of mouse and key presses, as this demo
|
||||
* shows.
|
||||
*
|
||||
* We also demonstrate adding other things to a text view, such as
|
||||
* clickable icons.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
@@ -30,35 +34,103 @@ insert_link (GtkTextBuffer *buffer,
|
||||
gtk_text_buffer_insert_with_tags (buffer, iter, text, -1, tag, NULL);
|
||||
}
|
||||
|
||||
/* Quick-and-dirty text-to-speech for a single word. If you don't hear
|
||||
* anything, you are missing espeak-ng on your system.
|
||||
*/
|
||||
static void
|
||||
say_word (GtkGestureClick *gesture,
|
||||
guint n_press,
|
||||
double x,
|
||||
double y,
|
||||
const char *word)
|
||||
{
|
||||
const char *argv[3];
|
||||
|
||||
argv[0] = "espeak-ng";
|
||||
argv[1] = word;
|
||||
argv[2] = NULL;
|
||||
|
||||
g_spawn_async (NULL, (char **)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Fills the buffer with text and interspersed links. In any real
|
||||
* hypertext app, this method would parse a file to identify the links.
|
||||
*/
|
||||
static void
|
||||
show_page (GtkTextBuffer *buffer,
|
||||
int page)
|
||||
show_page (GtkTextView *text_view,
|
||||
int page)
|
||||
{
|
||||
GtkTextBuffer *buffer;
|
||||
GtkTextIter iter;
|
||||
GtkWidget *child;
|
||||
GtkTextChildAnchor *anchor;
|
||||
GtkEventController *controller;
|
||||
|
||||
buffer = gtk_text_view_get_buffer (text_view);
|
||||
gtk_text_buffer_set_text (buffer, "", 0);
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
|
||||
gtk_text_buffer_begin_irreversible_action (buffer);
|
||||
if (page == 1)
|
||||
{
|
||||
GtkIconPaintable *icon;
|
||||
GtkIconTheme *theme;
|
||||
|
||||
gtk_text_buffer_insert (buffer, &iter, "Some text to show that simple ", -1);
|
||||
insert_link (buffer, &iter, "hyper text", 3);
|
||||
insert_link (buffer, &iter, "hypertext", 3);
|
||||
gtk_text_buffer_insert (buffer, &iter, " can easily be realized with ", -1);
|
||||
insert_link (buffer, &iter, "tags", 2);
|
||||
gtk_text_buffer_insert (buffer, &iter, ".\n", -1);
|
||||
gtk_text_buffer_insert (buffer, &iter,
|
||||
"Of course you can also embed Emoji 😋, "
|
||||
"icons ", -1);
|
||||
|
||||
theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (text_view)));
|
||||
icon = gtk_icon_theme_lookup_icon (theme,
|
||||
"microphone-sensitivity-high-symbolic",
|
||||
NULL,
|
||||
16,
|
||||
1,
|
||||
GTK_TEXT_DIR_LTR,
|
||||
0);
|
||||
gtk_text_buffer_insert_paintable (buffer, &iter, GDK_PAINTABLE (icon));
|
||||
g_object_unref (icon);
|
||||
gtk_text_buffer_insert (buffer, &iter, ", or even widgets ", -1);
|
||||
anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
|
||||
child = gtk_level_bar_new_for_interval (0, 100);
|
||||
gtk_level_bar_set_value (GTK_LEVEL_BAR (child), 50);
|
||||
gtk_widget_set_size_request (child, 100, -1);
|
||||
gtk_text_view_add_child_at_anchor (text_view, child, anchor);
|
||||
gtk_text_buffer_insert (buffer, &iter, ".", -1);
|
||||
}
|
||||
else if (page == 2)
|
||||
{
|
||||
gtk_text_buffer_insert (buffer, &iter,
|
||||
"A tag is an attribute that can be applied to some range of text. "
|
||||
"For example, a tag might be called \"bold\" and make the text inside "
|
||||
"the tag bold. However, the tag concept is more general than that; "
|
||||
"tags don't have to affect appearance. They can instead affect the "
|
||||
"behavior of mouse and key presses, \"lock\" a range of text so the "
|
||||
"user can't edit it, or countless other things.\n", -1);
|
||||
GtkTextTag *tag;
|
||||
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"weight", PANGO_WEIGHT_BOLD,
|
||||
"scale", PANGO_SCALE_X_LARGE,
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "tag", -1, tag, NULL);
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"family", "monospace",
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, " / tag / ", -1, tag, NULL);
|
||||
|
||||
anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
|
||||
child = gtk_image_new_from_icon_name ("audio-volume-high-symbolic");
|
||||
gtk_widget_set_cursor_from_name (child, "pointer");
|
||||
controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
|
||||
g_signal_connect (controller, "pressed", G_CALLBACK (say_word), (gpointer)"tag");
|
||||
gtk_widget_add_controller (child, controller);
|
||||
gtk_text_view_add_child_at_anchor (text_view, child, anchor);
|
||||
|
||||
gtk_text_buffer_insert (buffer, &iter, "\n"
|
||||
"An attribute that can be applied to some range of text. For example, "
|
||||
"a tag might be called “bold” and make the text inside the tag bold.\n"
|
||||
"However, the tag concept is more general than that; "
|
||||
"tags don't have to affect appearance. They can instead affect the "
|
||||
"behavior of mouse and key presses, “lock” a range of text so the "
|
||||
"user can't edit it, or countless other things.\n", -1);
|
||||
insert_link (buffer, &iter, "Go back", 1);
|
||||
}
|
||||
else if (page == 3)
|
||||
@@ -67,11 +139,25 @@ show_page (GtkTextBuffer *buffer,
|
||||
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"weight", PANGO_WEIGHT_BOLD,
|
||||
"scale", PANGO_SCALE_X_LARGE,
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "hypertext:\n", -1, tag, NULL);
|
||||
gtk_text_buffer_insert (buffer, &iter,
|
||||
"machine-readable text that is not sequential but is organized "
|
||||
"so that related items of information are connected.\n", -1);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "hypertext", -1, tag, NULL);
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"family", "monospace",
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, " / ˈhaɪ pərˌtɛkst / ", -1, tag, NULL);
|
||||
|
||||
anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
|
||||
child = gtk_image_new_from_icon_name ("audio-volume-high-symbolic");
|
||||
gtk_widget_set_cursor_from_name (child, "pointer");
|
||||
controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
|
||||
g_signal_connect (controller, "pressed", G_CALLBACK (say_word), (gpointer)"hypertext");
|
||||
gtk_widget_add_controller (child, controller);
|
||||
gtk_text_view_add_child_at_anchor (text_view, child, anchor);
|
||||
|
||||
gtk_text_buffer_insert (buffer, &iter, "\n"
|
||||
"Machine-readable text that is not sequential but is organized "
|
||||
"so that related items of information are connected.\n", -1);
|
||||
insert_link (buffer, &iter, "Go back", 1);
|
||||
}
|
||||
gtk_text_buffer_end_irreversible_action (buffer);
|
||||
@@ -95,7 +181,7 @@ follow_if_link (GtkWidget *text_view,
|
||||
|
||||
if (page != 0)
|
||||
{
|
||||
show_page (gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view)), page);
|
||||
show_page (GTK_TEXT_VIEW (text_view), page);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -162,7 +248,7 @@ released_cb (GtkGestureClick *gesture,
|
||||
if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end))
|
||||
return;
|
||||
|
||||
if (gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view), &iter, x, y))
|
||||
if (gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (text_view), &iter, tx, ty))
|
||||
follow_if_link (text_view, &iter);
|
||||
}
|
||||
|
||||
@@ -172,7 +258,13 @@ motion_cb (GtkEventControllerMotion *controller,
|
||||
double y,
|
||||
GtkTextView *text_view)
|
||||
{
|
||||
set_cursor_if_appropriate (text_view, x, y);
|
||||
int tx, ty;
|
||||
|
||||
gtk_text_view_window_to_buffer_coords (text_view,
|
||||
GTK_TEXT_WINDOW_WIDGET,
|
||||
x, y, &tx, &ty);
|
||||
|
||||
set_cursor_if_appropriate (text_view, tx, ty);
|
||||
}
|
||||
|
||||
static gboolean hovering_over_link = FALSE;
|
||||
@@ -182,9 +274,9 @@ static gboolean hovering_over_link = FALSE;
|
||||
* typically used by web browsers.
|
||||
*/
|
||||
static void
|
||||
set_cursor_if_appropriate (GtkTextView *text_view,
|
||||
int x,
|
||||
int y)
|
||||
set_cursor_if_appropriate (GtkTextView *text_view,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
GSList *tags = NULL, *tagp = NULL;
|
||||
GtkTextIter iter;
|
||||
@@ -236,13 +328,17 @@ do_hypertext (GtkWidget *do_widget)
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Hypertext");
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 450, 450);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 330, 330);
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
view = gtk_text_view_new ();
|
||||
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD);
|
||||
gtk_text_view_set_top_margin (GTK_TEXT_VIEW (view), 20);
|
||||
gtk_text_view_set_bottom_margin (GTK_TEXT_VIEW (view), 20);
|
||||
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 20);
|
||||
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (view), 20);
|
||||
gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (view), 10);
|
||||
controller = gtk_event_controller_key_new ();
|
||||
g_signal_connect (controller, "key-pressed", G_CALLBACK (key_pressed), view);
|
||||
gtk_widget_add_controller (view, controller);
|
||||
@@ -267,7 +363,7 @@ do_hypertext (GtkWidget *do_widget)
|
||||
gtk_window_set_child (GTK_WINDOW (window), sw);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), view);
|
||||
|
||||
show_page (buffer, 1);
|
||||
show_page (GTK_TEXT_VIEW (view), 1);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Benchmark/Scrolling
|
||||
* #Keywords: GtkScrolledWindow
|
||||
*
|
||||
* This demo scrolls a view with various content.
|
||||
*/
|
||||
@@ -255,12 +256,38 @@ iconscroll_prev_clicked_cb (GtkButton *source,
|
||||
set_widget_type (new_index);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_fps (gpointer data)
|
||||
{
|
||||
GtkWidget *label = data;
|
||||
GdkFrameClock *frame_clock;
|
||||
double fps;
|
||||
char *str;
|
||||
|
||||
frame_clock = gtk_widget_get_frame_clock (label);
|
||||
|
||||
fps = gdk_frame_clock_get_fps (frame_clock);
|
||||
str = g_strdup_printf ("%.2f fps", fps);
|
||||
gtk_label_set_label (GTK_LABEL (label), str);
|
||||
g_free (str);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_timeout (gpointer data)
|
||||
{
|
||||
g_source_remove (GPOINTER_TO_UINT (data));
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT GtkWidget *
|
||||
do_iconscroll (GtkWidget *do_widget)
|
||||
{
|
||||
if (!window)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GtkWidget *label;
|
||||
guint id;
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/iconscroll/iconscroll.ui");
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
@@ -274,6 +301,11 @@ do_iconscroll (GtkWidget *do_widget)
|
||||
vadjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "vadjustment"));
|
||||
set_widget_type (0);
|
||||
|
||||
label = GTK_WIDGET (gtk_builder_get_object (builder, "fps_label"));
|
||||
id = g_timeout_add (500, update_fps, label);
|
||||
g_object_set_data_full (G_OBJECT (label), "timeout",
|
||||
GUINT_TO_POINTER (id), remove_timeout);
|
||||
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
|
@@ -25,6 +25,13 @@
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkLabel" id="fps_label">
|
||||
<attributes>
|
||||
<attribute name="font-features" value="tnum=1"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Images
|
||||
* #Keywords: GdkPaintable, GtkWidgetPaintable
|
||||
*
|
||||
* GtkImage and GtkPicture are used to display an image; the image can be
|
||||
* in a number of formats.
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Info Bars
|
||||
* #Keywords: GtkInfoBar
|
||||
*
|
||||
* Info bar widgets are used to report important messages to the user.
|
||||
*/
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Layout Manager/Transition
|
||||
* #Keywords: GtkLayoutManager
|
||||
*
|
||||
* This demo shows a simple example of a custom layout manager
|
||||
* and a widget using it. The layout manager places the children
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Layout Manager/Transformation
|
||||
* #Keywords: GtkLayoutManager, GskTransform
|
||||
*
|
||||
* This demo shows how to use transforms in a nontrivial
|
||||
* way with a custom layout manager. The layout manager places
|
||||
@@ -115,7 +116,7 @@ do_layoutmanager2 (GtkWidget *parent)
|
||||
"media-playback-pause-symbolic",
|
||||
"media-playback-start-symbolic",
|
||||
"media-playback-stop-symbolic",
|
||||
"media-record-symbolic"
|
||||
"media-record-symbolic",
|
||||
"media-seek-backward-symbolic",
|
||||
"media-seek-forward-symbolic",
|
||||
"media-skip-backward-symbolic",
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* The GtkListStore is used to store data in list form, to be used
|
||||
* later on by a GtkTreeView to display it. This demo builds a
|
||||
* simple GtkListStore and displays it.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
@@ -2,7 +2,6 @@
|
||||
*
|
||||
* GtkListBox allows lists with complicated layouts, using
|
||||
* regular widgets supporting sorting and filtering.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Lists/Application launcher
|
||||
* #Keywords: GtkListItemFactory, GListModel
|
||||
*
|
||||
* This demo uses the GtkListView widget as a fancy application launcher.
|
||||
*
|
||||
|
@@ -1,10 +1,11 @@
|
||||
/* Lists/Clocks
|
||||
* #Keywords: GtkGridView, GtkListItemFactory, GListModel
|
||||
*
|
||||
* This demo displays the time in different timezones.
|
||||
*
|
||||
* The goal is to show how to set up expressions that track changes
|
||||
* in objects and make them update widgets. For that, we create a
|
||||
* GtkClock object that updates its time every second and then use
|
||||
* clock object that updates its time every second and then use
|
||||
* various ways to display that time.
|
||||
*
|
||||
* Typically, this will be done using GtkBuilder .ui files with the
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Lists/Colors
|
||||
* #Keywords: GtkSortListModel, GtkMultiSelection
|
||||
*
|
||||
* This demo displays a grid of colors.
|
||||
*
|
||||
@@ -1022,31 +1023,31 @@ do_listview_colors (GtkWidget *do_widget)
|
||||
/* An empty multisorter doesn't do any sorting and the sortmodel is
|
||||
* smart enough to know that.
|
||||
*/
|
||||
sorter = gtk_multi_sorter_new ();
|
||||
sorter = GTK_SORTER (gtk_multi_sorter_new ());
|
||||
set_title (sorter, "Unsorted");
|
||||
g_list_store_append (sorters, sorter);
|
||||
g_object_unref (sorter);
|
||||
|
||||
sorter = gtk_string_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "name"));
|
||||
sorter = GTK_SORTER (gtk_string_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "name")));
|
||||
set_title (sorter, "Name");
|
||||
g_list_store_append (sorters, sorter);
|
||||
g_object_unref (sorter);
|
||||
|
||||
multi_sorter = gtk_multi_sorter_new ();
|
||||
multi_sorter = GTK_SORTER (gtk_multi_sorter_new ());
|
||||
|
||||
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "red"));
|
||||
sorter = GTK_SORTER (gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "red")));
|
||||
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
|
||||
set_title (sorter, "Red");
|
||||
g_list_store_append (sorters, sorter);
|
||||
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
|
||||
|
||||
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "green"));
|
||||
sorter = GTK_SORTER (gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "green")));
|
||||
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
|
||||
set_title (sorter, "Green");
|
||||
g_list_store_append (sorters, sorter);
|
||||
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
|
||||
|
||||
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "blue"));
|
||||
sorter = GTK_SORTER (gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "blue")));
|
||||
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
|
||||
set_title (sorter, "Blue");
|
||||
g_list_store_append (sorters, sorter);
|
||||
@@ -1056,21 +1057,21 @@ do_listview_colors (GtkWidget *do_widget)
|
||||
g_list_store_append (sorters, multi_sorter);
|
||||
g_object_unref (multi_sorter);
|
||||
|
||||
multi_sorter = gtk_multi_sorter_new ();
|
||||
multi_sorter = GTK_SORTER (gtk_multi_sorter_new ());
|
||||
|
||||
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "hue"));
|
||||
sorter = GTK_SORTER (gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "hue")));
|
||||
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
|
||||
set_title (sorter, "Hue");
|
||||
g_list_store_append (sorters, sorter);
|
||||
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
|
||||
|
||||
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "saturation"));
|
||||
sorter = GTK_SORTER (gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "saturation")));
|
||||
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
|
||||
set_title (sorter, "Saturation");
|
||||
g_list_store_append (sorters, sorter);
|
||||
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
|
||||
|
||||
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "value"));
|
||||
sorter = GTK_SORTER (gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "value")));
|
||||
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
|
||||
set_title (sorter, "Value");
|
||||
g_list_store_append (sorters, sorter);
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Lists/File browser
|
||||
* #Keywords: GListModel
|
||||
*
|
||||
* This demo shows off the different layouts that are quickly achievable
|
||||
* with GtkListview and GtkGridView by implementing a file browser with
|
||||
|
@@ -1,7 +1,8 @@
|
||||
/* Lists/Minesweeper
|
||||
* #Keywords: GtkGridView, GListModel, game
|
||||
*
|
||||
* This demo shows how to develop a user interface for small game using a
|
||||
* gridview.
|
||||
* grid view.
|
||||
*
|
||||
* It demonstrates how to use the activate signal and single-press behavior
|
||||
* to implement rather different interaction behavior to a typical list.
|
||||
@@ -428,7 +429,7 @@ sweeper_game_reveal_cell (SweeperGame *self,
|
||||
sweeper_game_check_finished (self);
|
||||
}
|
||||
|
||||
void
|
||||
G_MODULE_EXPORT void
|
||||
minesweeper_cell_clicked_cb (GtkGridView *gridview,
|
||||
guint pos,
|
||||
SweeperGame *game)
|
||||
@@ -436,7 +437,7 @@ minesweeper_cell_clicked_cb (GtkGridView *gridview,
|
||||
sweeper_game_reveal_cell (game, pos);
|
||||
}
|
||||
|
||||
void
|
||||
G_MODULE_EXPORT void
|
||||
minesweeper_new_game_cb (GtkButton *button,
|
||||
SweeperGame *game)
|
||||
{
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Lists/Settings
|
||||
* #Keywords: GtkListItemFactory, GListModel
|
||||
*
|
||||
* This demo shows a settings viewer for GSettings.
|
||||
*
|
||||
@@ -247,7 +248,7 @@ transform_settings_to_keys (GBinding *binding,
|
||||
sort_model = gtk_sort_list_model_new (G_LIST_MODEL (store),
|
||||
g_object_ref (gtk_column_view_get_sorter (GTK_COLUMN_VIEW (data))));
|
||||
|
||||
filter = gtk_string_filter_new (gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name"));
|
||||
filter = GTK_FILTER (gtk_string_filter_new (gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name")));
|
||||
g_set_object (¤t_filter, filter);
|
||||
filter_model = gtk_filter_list_model_new (G_LIST_MODEL (sort_model), filter);
|
||||
|
||||
@@ -417,7 +418,7 @@ do_listview_settings (GtkWidget *do_widget)
|
||||
g_object_unref (selection);
|
||||
|
||||
name_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "name_column"));
|
||||
sorter = gtk_string_sorter_new (gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name"));
|
||||
sorter = GTK_SORTER (gtk_string_sorter_new (gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name")));
|
||||
gtk_column_view_column_set_sorter (name_column, sorter);
|
||||
g_object_unref (sorter);
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Lists/Words
|
||||
* #Keywords: GtkListView, GtkFilterListModel
|
||||
*
|
||||
* This demo shows filtering a long list - of words.
|
||||
*
|
||||
@@ -179,7 +180,7 @@ do_listview_words (GtkWidget *do_widget)
|
||||
}
|
||||
g_object_unref (file);
|
||||
|
||||
filter = gtk_string_filter_new (gtk_property_expression_new (GTK_TYPE_STRING_OBJECT, NULL, "string"));
|
||||
filter = GTK_FILTER (gtk_string_filter_new (gtk_property_expression_new (GTK_TYPE_STRING_OBJECT, NULL, "string")));
|
||||
filter_model = gtk_filter_list_model_new (G_LIST_MODEL (stringlist), filter);
|
||||
gtk_filter_list_model_set_incremental (filter_model, TRUE);
|
||||
|
||||
|
@@ -1,3 +1,17 @@
|
||||
/* GTK Demo
|
||||
*
|
||||
* GTK Demo is a collection of useful examples to demonstrate
|
||||
* GTK widgets and features. It is a useful example in itself.
|
||||
*
|
||||
* You can select examples in the sidebar or search for them by
|
||||
* typing a search term. Double-clicking or hitting the “Run” button
|
||||
* will run the demo. The source code and other resources used in the
|
||||
* demo are shown in this area.
|
||||
*
|
||||
* You can also use the GTK Inspector, available from the menu on the
|
||||
* top right, to poke at the running demos, and see how they are put
|
||||
* together.
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -28,6 +42,7 @@ struct _GtkDemo
|
||||
|
||||
const char *name;
|
||||
const char *title;
|
||||
const char **keywords;
|
||||
const char *filename;
|
||||
GDoDemoFunc func;
|
||||
GListModel *children_model;
|
||||
@@ -38,6 +53,7 @@ enum {
|
||||
PROP_FILENAME,
|
||||
PROP_NAME,
|
||||
PROP_TITLE,
|
||||
PROP_KEYWORDS,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
@@ -70,6 +86,10 @@ gtk_demo_get_property (GObject *object,
|
||||
g_value_set_string (value, self->title);
|
||||
break;
|
||||
|
||||
case PROP_KEYWORDS:
|
||||
g_value_set_boxed (value, self->keywords);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
@@ -100,6 +120,12 @@ static void gtk_demo_class_init (GtkDemoClass *klass)
|
||||
"title",
|
||||
NULL,
|
||||
G_PARAM_READABLE);
|
||||
properties[PROP_KEYWORDS] =
|
||||
g_param_spec_string ("keywords",
|
||||
"keywords",
|
||||
"keywords",
|
||||
NULL,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
@@ -315,12 +341,10 @@ display_text (const char *format,
|
||||
g_assert (g_utf8_validate (g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), NULL));
|
||||
|
||||
textview = gtk_text_view_new ();
|
||||
g_object_set (textview,
|
||||
"left-margin", 20,
|
||||
"right-margin", 20,
|
||||
"top-margin", 20,
|
||||
"bottom-margin", 20,
|
||||
NULL);
|
||||
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (textview), 20);
|
||||
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (textview), 20);
|
||||
gtk_text_view_set_top_margin (GTK_TEXT_VIEW (textview), 20);
|
||||
gtk_text_view_set_bottom_margin (GTK_TEXT_VIEW (textview), 20);
|
||||
gtk_text_view_set_editable (GTK_TEXT_VIEW (textview), FALSE);
|
||||
gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (textview), FALSE);
|
||||
/* Make it a bit nicer for text. */
|
||||
@@ -581,6 +605,9 @@ load_file (const char *demoname,
|
||||
while (g_ascii_isspace (*(p + len - 1)))
|
||||
len--;
|
||||
|
||||
if (*p == '#')
|
||||
break;
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
if (in_para)
|
||||
@@ -656,6 +683,7 @@ selection_cb (GtkSingleSelection *sel,
|
||||
{
|
||||
GtkTreeListRow *row = gtk_single_selection_get_selected_item (sel);
|
||||
GtkDemo *demo;
|
||||
GAction *action;
|
||||
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (notebook), !!row);
|
||||
|
||||
@@ -671,6 +699,9 @@ selection_cb (GtkSingleSelection *sel,
|
||||
if (demo->filename)
|
||||
load_file (demo->name, demo->filename);
|
||||
|
||||
action = g_action_map_lookup_action (G_ACTION_MAP (toplevel), "run");
|
||||
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), demo->func != NULL);
|
||||
|
||||
gtk_window_set_title (GTK_WINDOW (toplevel), demo->title);
|
||||
}
|
||||
|
||||
@@ -688,6 +719,21 @@ filter_demo (GtkDemo *demo)
|
||||
if (g_str_match_string (search_needle[i], demo->title, TRUE))
|
||||
continue;
|
||||
|
||||
if (demo->keywords)
|
||||
{
|
||||
int j;
|
||||
gboolean found = FALSE;
|
||||
|
||||
for (j = 0; !found && demo->keywords[j]; j++)
|
||||
{
|
||||
if (strstr (demo->keywords[j], search_needle[i]))
|
||||
found = TRUE;
|
||||
}
|
||||
|
||||
if (found)
|
||||
continue;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -695,9 +741,11 @@ filter_demo (GtkDemo *demo)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
demo_filter_by_name (GtkTreeListRow *row,
|
||||
GtkFilterListModel *model)
|
||||
demo_filter_by_name (gpointer item,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkTreeListRow *row = item;
|
||||
GtkFilterListModel *model = user_data;
|
||||
GListModel *children;
|
||||
GtkDemo *demo;
|
||||
guint i, n;
|
||||
@@ -756,7 +804,7 @@ demo_search_changed_cb (GtkSearchEntry *entry,
|
||||
g_clear_pointer (&search_needle, g_strfreev);
|
||||
|
||||
if (text && *text)
|
||||
search_needle = g_strsplit (text, " ", 0);
|
||||
search_needle = g_str_tokenize_and_fold (text, NULL, NULL);
|
||||
|
||||
gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT);
|
||||
}
|
||||
@@ -766,14 +814,25 @@ create_demo_model (void)
|
||||
{
|
||||
GListStore *store = g_list_store_new (GTK_TYPE_DEMO);
|
||||
DemoData *demo = gtk_demos;
|
||||
GtkDemo *d;
|
||||
|
||||
d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
|
||||
d->name = "main";
|
||||
d->title = "GTK Demo";
|
||||
d->keywords = NULL;
|
||||
d->filename = "main.c";
|
||||
d->func = NULL;
|
||||
|
||||
g_list_store_append (store, d);
|
||||
|
||||
while (demo->title)
|
||||
{
|
||||
GtkDemo *d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
|
||||
d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
|
||||
DemoData *children = demo->children;
|
||||
|
||||
d->name = demo->name;
|
||||
d->title = demo->title;
|
||||
d->keywords = demo->keywords;
|
||||
d->filename = demo->filename;
|
||||
d->func = demo->func;
|
||||
|
||||
@@ -789,6 +848,7 @@ create_demo_model (void)
|
||||
|
||||
child->name = children->name;
|
||||
child->title = children->title;
|
||||
child->keywords = children->keywords;
|
||||
child->filename = children->filename;
|
||||
child->func = children->func;
|
||||
|
||||
@@ -834,18 +894,16 @@ activate (GApplication *app)
|
||||
GtkWidget *window, *listview, *search_entry, *search_bar;
|
||||
GtkFilterListModel *filter_model;
|
||||
GtkFilter *filter;
|
||||
|
||||
static GActionEntry win_entries[] = {
|
||||
{ "run", activate_run, NULL, NULL, NULL }
|
||||
};
|
||||
GSimpleAction *action;
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/ui/main.ui");
|
||||
|
||||
window = (GtkWidget *)gtk_builder_get_object (builder, "window");
|
||||
gtk_application_add_window (GTK_APPLICATION (app), GTK_WINDOW (window));
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (window),
|
||||
win_entries, G_N_ELEMENTS (win_entries),
|
||||
window);
|
||||
|
||||
action = g_simple_action_new ("run", NULL);
|
||||
g_signal_connect (action, "activate", G_CALLBACK (activate_run), window);
|
||||
g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (action));
|
||||
|
||||
notebook = GTK_WIDGET (gtk_builder_get_object (builder, "notebook"));
|
||||
|
||||
@@ -865,9 +923,10 @@ activate (GApplication *app)
|
||||
NULL,
|
||||
NULL);
|
||||
filter_model = gtk_filter_list_model_new (G_LIST_MODEL (treemodel), NULL);
|
||||
filter = gtk_custom_filter_new ((GtkCustomFilterFunc)demo_filter_by_name, filter_model, NULL);
|
||||
filter = GTK_FILTER (gtk_custom_filter_new (demo_filter_by_name, filter_model, NULL));
|
||||
gtk_filter_list_model_set_filter (filter_model, filter);
|
||||
g_object_unref (filter);
|
||||
|
||||
search_entry = GTK_WIDGET (gtk_builder_get_object (builder, "search-entry"));
|
||||
g_signal_connect (search_entry, "search-changed", G_CALLBACK (demo_search_changed_cb), filter);
|
||||
|
||||
|
@@ -106,8 +106,9 @@
|
||||
<property name="right-margin">20</property>
|
||||
<property name="top-margin">20</property>
|
||||
<property name="bottom-margin">20</property>
|
||||
<property name="pixels-above-lines">2</property>
|
||||
<property name="pixels-below-lines">2</property>
|
||||
<property name="pixels-above-lines">6</property>
|
||||
<property name="pixels-below-lines">6</property>
|
||||
<property name="monospace">0</property>
|
||||
<property name="editable">0</property>
|
||||
<property name="wrap-mode">word</property>
|
||||
<property name="cursor-visible">0</property>
|
||||
|
95
demos/gtk-demo/mandelbrot.glsl
Normal file
95
demos/gtk-demo/mandelbrot.glsl
Normal file
@@ -0,0 +1,95 @@
|
||||
// Originally from: https://www.shadertoy.com/view/wdBfDK
|
||||
// License: CC0
|
||||
|
||||
#define MANDELBROT_ZOOM_START 0.0
|
||||
#define MANDELBROT_ITER 240
|
||||
|
||||
void pR(inout vec2 p, in float a) {
|
||||
p = cos(a)*p + sin(a)*vec2(p.y, -p.x);
|
||||
}
|
||||
|
||||
vec2 pMod2(inout vec2 p, in vec2 size) {
|
||||
vec2 c = floor((p + size*0.5)/size);
|
||||
p = mod(p + size*0.5,size) - size*0.5;
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
vec3 mandelbrot(float time, vec2 p, out float ii) {
|
||||
vec3 col = vec3(0.0);
|
||||
|
||||
float ztime = (time - MANDELBROT_ZOOM_START)*step(MANDELBROT_ZOOM_START, time);
|
||||
|
||||
float zoo = 0.64 + 0.36*cos(.07*ztime);
|
||||
float coa = cos(0.15*(1.0-zoo)*ztime);
|
||||
float sia = sin(0.15*(1.0-zoo)*ztime);
|
||||
zoo = pow(zoo,8.0);
|
||||
vec2 xy = vec2( p.x*coa-p.y*sia, p.x*sia+p.y*coa);
|
||||
vec2 c = vec2(-.745,.186) + xy*zoo;
|
||||
|
||||
const float B = 10.0;
|
||||
float l = 0.0;
|
||||
vec2 z = vec2(0.0);
|
||||
|
||||
vec2 zc = vec2(1.0);
|
||||
|
||||
pR(zc, ztime);
|
||||
|
||||
float d = 1e20;
|
||||
|
||||
int i = 0;
|
||||
|
||||
for(int j = 0; j < MANDELBROT_ITER; ++j) {
|
||||
float re2 = z.x*z.x;
|
||||
float im2 = z.y*z.y;
|
||||
float reim= z.x*z.y;
|
||||
|
||||
if(re2 + im2 > (B*B)) break;
|
||||
|
||||
z = vec2(re2 - im2, 2.0*reim) + c;
|
||||
|
||||
vec2 zm = z;
|
||||
vec2 n = pMod2(zm, vec2(4));
|
||||
vec2 pp = zm - zc;
|
||||
float dd = dot(pp, pp);
|
||||
|
||||
d = min(d, dd);
|
||||
|
||||
l += 1.0;
|
||||
|
||||
i = j;
|
||||
}
|
||||
|
||||
ii = float(i)/float(MANDELBROT_ITER);
|
||||
|
||||
float sl = l - log2(log2(dot(z,z))) + 4.0;
|
||||
|
||||
vec3 dc = vec3(pow(max(1.0 - d, 0.0), 20.0));
|
||||
vec3 gc = 0.5 + 0.5*cos(3.0 + sl*0.15 + vec3(0.1,0.5,0.9));
|
||||
return gc + dc*smoothstep(28.8, 29.0, ztime);
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||
float s = 2.0/iResolution.y;
|
||||
|
||||
vec2 o1 = vec2(1.0/8.0, 3.0/8.0)*s;
|
||||
vec2 o2 = vec2(-3.0/8.0, 1.0/8.0)*s;
|
||||
|
||||
vec2 p = (-iResolution.xy + 2.0*fragCoord.xy)/iResolution.y;
|
||||
float ii = 0.0;
|
||||
vec3 col = mandelbrot(iTime, p+o1, ii);
|
||||
|
||||
// "smart" AA? Is that a good idea?
|
||||
vec2 dii2 = vec2(dFdx(ii), dFdy(ii));
|
||||
float dii = length(dii2);
|
||||
|
||||
if(abs(dii) > 0.01) {
|
||||
col += mandelbrot(iTime, p-o1, ii);
|
||||
col += mandelbrot(iTime, p+o2, ii);
|
||||
col += mandelbrot(iTime, p-o2, ii);
|
||||
col *=0.25;
|
||||
// col = vec3(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
fragColor = vec4(col, 1.0);
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
/* Text View/Markup
|
||||
* #Keywords: GtkTextView
|
||||
*
|
||||
* GtkTextBuffer lets you define your own tags that can influence
|
||||
* text formatting in a variety of ways. In this example, we show
|
||||
@@ -13,9 +14,9 @@ static GtkWidget *view;
|
||||
static GtkWidget *view2;
|
||||
|
||||
static void
|
||||
source_toggled (GtkToggleButton *button)
|
||||
source_toggled (GtkCheckButton *button)
|
||||
{
|
||||
if (gtk_toggle_button_get_active (button))
|
||||
if (gtk_check_button_get_active (button))
|
||||
gtk_stack_set_visible_child_name (GTK_STACK (stack), "source");
|
||||
else
|
||||
{
|
||||
|
47
demos/gtk-demo/menu.c
Normal file
47
demos/gtk-demo/menu.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/* Menu
|
||||
* #Keywords: action, zoom
|
||||
*
|
||||
* Demonstrates how to add a context menu to a custom widget
|
||||
* and connect it with widget actions.
|
||||
*
|
||||
* The custom widget we create here is similar to a GtkPicture,
|
||||
* but allows setting a zoom level for the displayed paintable.
|
||||
*
|
||||
* Our context menu has items to change the zoom level.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "demo3widget.h"
|
||||
|
||||
|
||||
GtkWidget *
|
||||
do_menu (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *sw;
|
||||
GtkWidget *widget;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Menu");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_window_set_child (GTK_WINDOW (window), sw);
|
||||
|
||||
widget = demo3_widget_new ("/transparent/portland-rose.jpg");
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), widget);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
@@ -23,6 +23,7 @@ demos = files([
|
||||
'editable_cells.c',
|
||||
'entry_completion.c',
|
||||
'entry_undo.c',
|
||||
'errorstates.c',
|
||||
'expander.c',
|
||||
'filtermodel.c',
|
||||
'fishbowl.c',
|
||||
@@ -31,6 +32,8 @@ demos = files([
|
||||
'gears.c',
|
||||
'gestures.c',
|
||||
'glarea.c',
|
||||
'glshader.c',
|
||||
'gltransition.c',
|
||||
'headerbar.c',
|
||||
'hypertext.c',
|
||||
'iconscroll.c',
|
||||
@@ -43,6 +46,7 @@ demos = files([
|
||||
'links.c',
|
||||
'listbox.c',
|
||||
'listbox2.c',
|
||||
'menu.c',
|
||||
'flowbox.c',
|
||||
'list_store.c',
|
||||
'listview_applauncher.c',
|
||||
@@ -59,6 +63,7 @@ demos = files([
|
||||
'paint.c',
|
||||
'paintable.c',
|
||||
'paintable_animated.c',
|
||||
'paintable_emblem.c',
|
||||
'paintable_mediastream.c',
|
||||
'panes.c',
|
||||
'password_entry.c',
|
||||
@@ -70,6 +75,7 @@ demos = files([
|
||||
'scale.c',
|
||||
'search_entry.c',
|
||||
'search_entry2.c',
|
||||
'shadertoy.c',
|
||||
'shortcuts.c',
|
||||
'shortcut_triggers.c',
|
||||
'sidebar.c',
|
||||
@@ -98,6 +104,9 @@ extra_demo_sources = files(['main.c',
|
||||
'gtkfishbowl.c',
|
||||
'fontplane.c',
|
||||
'gtkgears.c',
|
||||
'gtkshaderbin.c',
|
||||
'gtkshadertoy.c',
|
||||
'gtkshaderstack.c',
|
||||
'puzzlepiece.c',
|
||||
'bluroverlay.c',
|
||||
'demoimage.c',
|
||||
@@ -108,7 +117,8 @@ extra_demo_sources = files(['main.c',
|
||||
'demo2layout.c',
|
||||
'singular_value_decomposition.c',
|
||||
'four_point_transform.c',
|
||||
'demo2widget.c'])
|
||||
'demo2widget.c',
|
||||
'demo3widget.c'])
|
||||
|
||||
if harfbuzz_dep.found() and pangoft_dep.found()
|
||||
demos += files('font_features.c')
|
||||
|
220
demos/gtk-demo/neon.glsl
Normal file
220
demos/gtk-demo/neon.glsl
Normal file
@@ -0,0 +1,220 @@
|
||||
// Originally from: https://www.shadertoy.com/view/WlByzy
|
||||
// License CC0: Neonwave style road, sun and city
|
||||
// The result of a bit of experimenting with neonwave style colors.
|
||||
|
||||
#define PI 3.141592654
|
||||
#define TAU (2.0*PI)
|
||||
|
||||
#define TIME iTime
|
||||
#define RESOLUTION iResolution
|
||||
|
||||
vec3 hsv2rgb(vec3 c) {
|
||||
const vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
float hash(in float co) {
|
||||
return fract(sin(co*12.9898) * 13758.5453);
|
||||
}
|
||||
|
||||
float hash(in vec2 co) {
|
||||
return fract(sin(dot(co.xy ,vec2(12.9898,58.233))) * 13758.5453);
|
||||
}
|
||||
|
||||
float psin(float a) {
|
||||
return 0.5 + 0.5*sin(a);
|
||||
}
|
||||
|
||||
float mod1(inout float p, float size) {
|
||||
float halfsize = size*0.5;
|
||||
float c = floor((p + halfsize)/size);
|
||||
p = mod(p + halfsize, size) - halfsize;
|
||||
return c;
|
||||
}
|
||||
|
||||
float circle(vec2 p, float r) {
|
||||
return length(p) - r;
|
||||
}
|
||||
|
||||
float box(vec2 p, vec2 b) {
|
||||
vec2 d = abs(p)-b;
|
||||
return length(max(d,0.0)) + min(max(d.x,d.y),0.0);
|
||||
}
|
||||
|
||||
float planex(vec2 p, float w) {
|
||||
return abs(p.y) - w;
|
||||
}
|
||||
|
||||
float planey(vec2 p, float w) {
|
||||
return abs(p.x) - w;
|
||||
}
|
||||
|
||||
float pmin(float a, float b, float k) {
|
||||
float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
|
||||
return mix( b, a, h ) - k*h*(1.0-h);
|
||||
}
|
||||
|
||||
float pmax(float a, float b, float k) {
|
||||
return -pmin(-a, -b, k);
|
||||
}
|
||||
|
||||
float sun(vec2 p) {
|
||||
const float ch = 0.0125;
|
||||
vec2 sp = p;
|
||||
vec2 cp = p;
|
||||
mod1(cp.y, ch*6.0);
|
||||
|
||||
float d0 = circle(sp, 0.5);
|
||||
float d1 = planex(cp, ch);
|
||||
float d2 = p.y+ch*3.0;
|
||||
|
||||
float d = d0;
|
||||
d = pmax(d, -max(d1, d2), ch*2.0);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
float city(vec2 p) {
|
||||
float sd = circle(p, 0.5);
|
||||
float cd = 1E6;
|
||||
|
||||
const float count = 5.0;
|
||||
const float width = 0.1;
|
||||
|
||||
for (float i = 0.0; i < count; ++i) {
|
||||
vec2 pp = p;
|
||||
pp.x += i*width/count;
|
||||
float nn = mod1(pp.x, width);
|
||||
float rr = hash(nn+sqrt(3.0)*i);
|
||||
float dd = box(pp-vec2(0.0, -0.5), vec2(0.02, 0.35*(1.0-smoothstep(0.0, 5.0, abs(nn)))*rr+0.1));
|
||||
cd = min(cd, dd);
|
||||
}
|
||||
|
||||
return max(sd,cd);
|
||||
}
|
||||
vec3 sunEffect(vec2 p) {
|
||||
float aa = 4.0 / RESOLUTION.y;
|
||||
|
||||
vec3 col = vec3(0.1);
|
||||
vec3 skyCol1 = hsv2rgb(vec3(283.0/360.0, 0.83, 0.16));
|
||||
vec3 skyCol2 = hsv2rgb(vec3(297.0/360.0, 0.79, 0.43));
|
||||
col = mix(skyCol1, skyCol2, pow(clamp(0.5*(1.0+p.y+0.1*sin(4.0*p.x+TIME*0.5)), 0.0, 1.0), 4.0));
|
||||
|
||||
p.y -= 0.375;
|
||||
float ds = sun(p);
|
||||
float dc = city(p);
|
||||
|
||||
float dd = circle(p, 0.5);
|
||||
|
||||
vec3 sunCol = mix(vec3(1.0, 1.0, 0.0), vec3(1.0, 0.0, 1.0), clamp(0.5 - 1.0*p.y, 0.0, 1.0));
|
||||
vec3 glareCol = sqrt(sunCol);
|
||||
vec3 cityCol = sunCol*sunCol;
|
||||
|
||||
col += glareCol*(exp(-30.0*ds))*step(0.0, ds);
|
||||
|
||||
|
||||
float t1 = smoothstep(0.0, 0.075, -dd);
|
||||
float t2 = smoothstep(0.0, 0.3, -dd);
|
||||
col = mix(col, sunCol, smoothstep(-aa, 0.0, -ds));
|
||||
col = mix(col, glareCol, smoothstep(-aa, 0.0, -dc)*t1);
|
||||
col += vec3(0.0, 0.25, 0.0)*(exp(-90.0*dc))*step(0.0, dc)*t2;
|
||||
|
||||
// col += 0.3*psin(d*400);
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
float ground(vec2 p) {
|
||||
p.y += TIME*80.0;
|
||||
p *= 0.075;
|
||||
vec2 gp = p;
|
||||
gp = fract(gp) - vec2(0.5);
|
||||
float d0 = abs(gp.x);
|
||||
float d1 = abs(gp.y);
|
||||
float d2 = circle(gp, 0.05);
|
||||
|
||||
const float rw = 2.5;
|
||||
const float sw = 0.0125;
|
||||
|
||||
vec2 rp = p;
|
||||
mod1(rp.y, 12.0);
|
||||
float d3 = abs(rp.x) - rw;
|
||||
float d4 = abs(d3) - sw*2.0;
|
||||
float d5 = box(rp, vec2(sw*2.0, 2.0));
|
||||
vec2 sp = p;
|
||||
mod1(sp.y, 4.0);
|
||||
sp.x = abs(sp.x);
|
||||
sp -= vec2(rw - 0.125, 0.0);
|
||||
float d6 = box(sp, vec2(sw, 1.0));
|
||||
|
||||
float d = d0;
|
||||
d = pmin(d, d1, 0.1);
|
||||
d = max(d, -d3);
|
||||
d = min(d, d4);
|
||||
d = min(d, d5);
|
||||
d = min(d, d6);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
vec3 groundEffect(vec2 p) {
|
||||
vec3 ro = vec3(0.0, 20.0, 0.0);
|
||||
vec3 ww = normalize(vec3(0.0, -0.025, 1.0));
|
||||
vec3 uu = normalize(cross(vec3(0.0,1.0,0.0), ww));
|
||||
vec3 vv = normalize(cross(ww,uu));
|
||||
vec3 rd = normalize(p.x*uu + p.y*vv + 2.5*ww);
|
||||
|
||||
float distg = (-9.0 - ro.y)/rd.y;
|
||||
|
||||
const vec3 shineCol = 0.75*vec3(0.5, 0.75, 1.0);
|
||||
const vec3 gridCol = vec3(1.0);
|
||||
|
||||
vec3 col = vec3(0.0);
|
||||
if (distg > 0.0) {
|
||||
vec3 pg = ro + rd*distg;
|
||||
float aa = length(dFdx(pg))*0.0002*RESOLUTION.x;
|
||||
|
||||
float dg = ground(pg.xz);
|
||||
|
||||
col = mix(col, gridCol, smoothstep(-aa, 0.0, -(dg+0.0175)));
|
||||
col += shineCol*(exp(-10.0*clamp(dg, 0.0, 1.0)));
|
||||
col = clamp(col, 0.0, 1.0);
|
||||
|
||||
// col += 0.3*psin(dg*100);
|
||||
col *= pow(1.0-smoothstep(ro.y*3.0, 220.0+ro.y*2.0, distg), 2.0);
|
||||
}
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 postProcess(vec3 col, vec2 q) {
|
||||
col = clamp(col,0.0,1.0);
|
||||
// col=pow(col,vec3(0.75));
|
||||
col=col*0.6+0.4*col*col*(3.0-2.0*col);
|
||||
col=mix(col, vec3(dot(col, vec3(0.33))), -0.4);
|
||||
col*=0.5+0.5*pow(19.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.7);
|
||||
return col;
|
||||
}
|
||||
|
||||
vec3 effect(vec2 p, vec2 q) {
|
||||
vec3 col = vec3(0.0);
|
||||
|
||||
vec2 off = vec2(0.0, 0.0);
|
||||
|
||||
col += sunEffect(p+off);
|
||||
col += groundEffect(p+off);
|
||||
|
||||
col = postProcess(col, q);
|
||||
return col;
|
||||
}
|
||||
|
||||
void mainImage(out vec4 fragColor, vec2 fragCoord) {
|
||||
vec2 q = fragCoord/iResolution.xy;
|
||||
vec2 p = -1. + 2. * q;
|
||||
p.x *= RESOLUTION.x / RESOLUTION.y;
|
||||
|
||||
vec3 col = effect(p, q);
|
||||
|
||||
fragColor = vec4(col, 1.0);
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
/* Overlay/Interactive Overlay
|
||||
* #Keywords: GtkOverlay
|
||||
*
|
||||
* Shows widgets in static positions over a main widget.
|
||||
*
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Overlay/Decorative Overlay
|
||||
* #Keywords: GtkOverlay
|
||||
*
|
||||
* Another example of an overlay with some decorative
|
||||
* and some interactive controls.
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Printing/Page Setup
|
||||
* #Keywords: GtkPageSetup
|
||||
*
|
||||
* GtkPageSetupUnixDialog can be used if page setup is needed
|
||||
* independent of a full printing dialog.
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Paint
|
||||
* #Keywords: GdkDrawingArea, GtkGesture
|
||||
*
|
||||
* Demonstrates practical handling of drawing tablets in a real world
|
||||
* usecase.
|
||||
|
@@ -48,15 +48,17 @@ void
|
||||
gtk_nuclear_snapshot (GtkSnapshot *snapshot,
|
||||
double width,
|
||||
double height,
|
||||
double rotation)
|
||||
double rotation,
|
||||
gboolean draw_background)
|
||||
{
|
||||
#define RADIUS 0.3
|
||||
cairo_t *cr;
|
||||
double size;
|
||||
|
||||
gtk_snapshot_append_color (snapshot,
|
||||
&(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 },
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
if (draw_background)
|
||||
gtk_snapshot_append_color (snapshot,
|
||||
&(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 },
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
|
||||
size = MIN (width, height);
|
||||
cr = gtk_snapshot_append_cairo (snapshot,
|
||||
@@ -93,7 +95,8 @@ gtk_nuclear_icon_snapshot (GdkPaintable *paintable,
|
||||
|
||||
gtk_nuclear_snapshot (snapshot,
|
||||
width, height,
|
||||
nuclear->rotation);
|
||||
nuclear->rotation,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static GdkPaintableFlags
|
||||
@@ -161,6 +164,7 @@ do_paintable (GtkWidget *do_widget)
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Nuclear Icon");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 300, 200);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
nuclear = gtk_nuclear_icon_new (0.0);
|
||||
image = gtk_image_new_from_paintable (nuclear);
|
||||
|
@@ -6,10 +6,11 @@
|
||||
void gtk_nuclear_snapshot (GtkSnapshot *snapshot,
|
||||
double width,
|
||||
double height,
|
||||
double rotation);
|
||||
double rotation,
|
||||
gboolean draw_background);
|
||||
|
||||
GdkPaintable * gtk_nuclear_icon_new (double rotation);
|
||||
GdkPaintable * gtk_nuclear_animation_new (void);
|
||||
GdkPaintable * gtk_nuclear_animation_new (gboolean draw_background);
|
||||
GtkMediaStream *gtk_nuclear_media_stream_new (void);
|
||||
|
||||
#endif /* __PAINTABLE_H__ */
|
||||
|
@@ -33,6 +33,8 @@ struct _GtkNuclearAnimation
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
gboolean draw_background;
|
||||
|
||||
/* This variable stores the progress of our animation.
|
||||
* We just count upwards until we hit MAX_PROGRESS and
|
||||
* then start from scratch.
|
||||
@@ -64,7 +66,8 @@ gtk_nuclear_animation_snapshot (GdkPaintable *paintable,
|
||||
/* We call the function from the previous example here. */
|
||||
gtk_nuclear_snapshot (snapshot,
|
||||
width, height,
|
||||
2 * G_PI * nuclear->progress / MAX_PROGRESS);
|
||||
2 * G_PI * nuclear->progress / MAX_PROGRESS,
|
||||
nuclear->draw_background);
|
||||
}
|
||||
|
||||
static GdkPaintable *
|
||||
@@ -175,9 +178,15 @@ gtk_nuclear_animation_init (GtkNuclearAnimation *nuclear)
|
||||
|
||||
/* And finally, we add the simple constructor we declared in the header. */
|
||||
GdkPaintable *
|
||||
gtk_nuclear_animation_new (void)
|
||||
gtk_nuclear_animation_new (gboolean draw_background)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_NUCLEAR_ANIMATION, NULL);
|
||||
GtkNuclearAnimation *nuclear;
|
||||
|
||||
nuclear = g_object_new (GTK_TYPE_NUCLEAR_ANIMATION, NULL);
|
||||
|
||||
nuclear->draw_background = draw_background;
|
||||
|
||||
return GDK_PAINTABLE (nuclear);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
@@ -193,8 +202,9 @@ do_paintable_animated (GtkWidget *do_widget)
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Nuclear Animation");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 300, 200);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
nuclear = gtk_nuclear_animation_new ();
|
||||
nuclear = gtk_nuclear_animation_new (TRUE);
|
||||
image = gtk_image_new_from_paintable (nuclear);
|
||||
gtk_window_set_child (GTK_WINDOW (window), image);
|
||||
g_object_unref (nuclear);
|
||||
|
186
demos/gtk-demo/paintable_emblem.c
Normal file
186
demos/gtk-demo/paintable_emblem.c
Normal file
@@ -0,0 +1,186 @@
|
||||
/* Paintable/Emblems
|
||||
*
|
||||
* This demo shows how GdkPaintable can be used to
|
||||
* overlay an emblem on top of an icon. The emblem
|
||||
* can either be another icon, or an arbitrary
|
||||
* paintable.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "paintable.h"
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
#define DEMO_TYPE_ICON (demo_icon_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (DemoIcon, demo_icon, DEMO, ICON, GObject)
|
||||
|
||||
struct _DemoIcon
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GdkPaintable *icon;
|
||||
GdkPaintable *emblem;
|
||||
GdkPaintableFlags flags;
|
||||
};
|
||||
|
||||
struct _DemoIconClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
void
|
||||
demo_icon_snapshot (GdkPaintable *paintable,
|
||||
GtkSnapshot *snapshot,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
DemoIcon *self = DEMO_ICON (paintable);
|
||||
|
||||
gdk_paintable_snapshot (self->icon, snapshot, width, height);
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (0.5 * width, 0));
|
||||
gdk_paintable_snapshot (self->emblem, snapshot, 0.5 * width, 0.5 * height);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
}
|
||||
|
||||
static GdkPaintableFlags
|
||||
demo_icon_get_flags (GdkPaintable *paintable)
|
||||
{
|
||||
DemoIcon *self = DEMO_ICON (paintable);
|
||||
|
||||
return self->flags;
|
||||
}
|
||||
|
||||
static void
|
||||
demo_icon_paintable_init (GdkPaintableInterface *iface)
|
||||
{
|
||||
iface->snapshot = demo_icon_snapshot;
|
||||
iface->get_flags = demo_icon_get_flags;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (DemoIcon, demo_icon, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||
demo_icon_paintable_init))
|
||||
|
||||
static void
|
||||
demo_icon_dispose (GObject *object)
|
||||
{
|
||||
DemoIcon *self = DEMO_ICON (object);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (self->emblem,
|
||||
gdk_paintable_invalidate_contents,
|
||||
self);
|
||||
|
||||
g_clear_object (&self->icon);
|
||||
g_clear_object (&self->emblem);
|
||||
|
||||
G_OBJECT_CLASS (demo_icon_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_icon_class_init (DemoIconClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = demo_icon_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
demo_icon_init (DemoIcon *self)
|
||||
{
|
||||
self->flags = GDK_PAINTABLE_STATIC_SIZE | GDK_PAINTABLE_STATIC_CONTENTS;
|
||||
}
|
||||
|
||||
GdkPaintable *
|
||||
demo_icon_new_with_paintable (const char *icon_name,
|
||||
GdkPaintable *emblem)
|
||||
{
|
||||
GtkIconTheme *theme;
|
||||
GtkIconPaintable *icon;
|
||||
DemoIcon *self;
|
||||
|
||||
theme = gtk_icon_theme_get_for_display (gdk_display_get_default ());
|
||||
|
||||
icon = gtk_icon_theme_lookup_icon (theme,
|
||||
icon_name, NULL,
|
||||
128, 1,
|
||||
GTK_TEXT_DIR_LTR, 0);
|
||||
|
||||
self = g_object_new (DEMO_TYPE_ICON, NULL);
|
||||
|
||||
self->icon = GDK_PAINTABLE (icon);
|
||||
self->emblem = emblem;
|
||||
|
||||
if ((gdk_paintable_get_flags (emblem) & GDK_PAINTABLE_STATIC_CONTENTS) == 0)
|
||||
{
|
||||
self->flags &= ~GDK_PAINTABLE_STATIC_CONTENTS;
|
||||
|
||||
g_signal_connect_swapped (emblem, "invalidate-contents",
|
||||
G_CALLBACK (gdk_paintable_invalidate_contents), self);
|
||||
}
|
||||
|
||||
return GDK_PAINTABLE (self);
|
||||
}
|
||||
|
||||
GdkPaintable *
|
||||
demo_icon_new (const char *icon_name,
|
||||
const char *emblem_name)
|
||||
{
|
||||
GtkIconTheme *theme;
|
||||
GtkIconPaintable *emblem;
|
||||
|
||||
theme = gtk_icon_theme_get_for_display (gdk_display_get_default ());
|
||||
|
||||
emblem = gtk_icon_theme_lookup_icon (theme,
|
||||
emblem_name, NULL,
|
||||
128, 1,
|
||||
GTK_TEXT_DIR_LTR, 0);
|
||||
|
||||
return GDK_PAINTABLE (demo_icon_new_with_paintable (icon_name,
|
||||
GDK_PAINTABLE (emblem)));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_paintable_emblem (GtkWidget *do_widget)
|
||||
{
|
||||
GdkPaintable *icon;
|
||||
GtkWidget *grid;
|
||||
GtkWidget *image;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Emblems");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 300, 200);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
|
||||
icon = demo_icon_new ("folder", "starred");
|
||||
image = gtk_image_new_from_paintable (icon);
|
||||
gtk_widget_set_hexpand (image, TRUE);
|
||||
gtk_widget_set_vexpand (image, TRUE);
|
||||
gtk_grid_attach (GTK_GRID (grid), image, 0, 0, 1, 1);
|
||||
|
||||
icon = demo_icon_new_with_paintable ("drive-multidisk",
|
||||
gtk_nuclear_animation_new (FALSE));
|
||||
image = gtk_image_new_from_paintable (icon);
|
||||
gtk_widget_set_hexpand (image, TRUE);
|
||||
gtk_widget_set_vexpand (image, TRUE);
|
||||
gtk_grid_attach (GTK_GRID (grid), image, 1, 0, 1, 1);
|
||||
|
||||
gtk_window_set_child (GTK_WINDOW (window), grid);
|
||||
g_object_unref (icon);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
||||
|
@@ -74,7 +74,8 @@ gtk_nuclear_media_stream_snapshot (GdkPaintable *paintable,
|
||||
/* We call the function from the previous example here. */
|
||||
gtk_nuclear_snapshot (snapshot,
|
||||
width, height,
|
||||
2 * G_PI * nuclear->progress / DURATION);
|
||||
2 * G_PI * nuclear->progress / DURATION,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static GdkPaintable *
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Peg Solitaire
|
||||
* #Keywords: GtkGridView, game
|
||||
*
|
||||
* This demo demonstrates how to use drag'n'drop to implement peg solitaire.
|
||||
*
|
||||
|
@@ -1,4 +1,6 @@
|
||||
/* Pickers
|
||||
* #Keywords: GtkColorChooser, GtkFontChooser, GtkFileChooser,
|
||||
* #Keywords: GtkApplicationChooser
|
||||
*
|
||||
* These widgets are mainly intended for use in preference dialogs.
|
||||
* They allow to select colors, fonts, files, directories and applications.
|
||||
|
@@ -2,7 +2,6 @@
|
||||
*
|
||||
* GtkPrintOperation offers a simple API to support printing
|
||||
* in a cross-platform way.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
@@ -1,10 +1,10 @@
|
||||
/* Pango/Rotated Text
|
||||
*
|
||||
* This demo shows how to use PangoCairo to draw rotated and transformed
|
||||
* text. The right pane shows a rotated GtkLabel widget.
|
||||
* text. The right pane shows a rotated GtkLabel widget.
|
||||
*
|
||||
* In both cases, a custom PangoCairo shape renderer is installed to draw
|
||||
* a red heard using cairo drawing operations instead of the Unicode heart
|
||||
* a red heart using cairo drawing operations instead of the Unicode heart
|
||||
* character.
|
||||
*/
|
||||
|
||||
|
@@ -1,9 +1,13 @@
|
||||
/* Entry/Delayed Search Entry
|
||||
*
|
||||
* GtkSearchEntry sets up GtkEntries ready for search. Search entries
|
||||
* have their "changed" signal delayed and should be used
|
||||
* when the searched operation is slow such as loads of entries
|
||||
* to search, or online searches.
|
||||
* GtkSearchEntry provides an entry that is ready for search.
|
||||
*
|
||||
* Search entries have their "changed" signal delayed and should
|
||||
* be used when the searched operation is slow such as loads of
|
||||
* entries to search, or online searches.
|
||||
*
|
||||
* GtkSearchBar allows have a hidden search entry that 'springs
|
||||
* into action' upon keyboard input.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
202
demos/gtk-demo/shadertoy.c
Normal file
202
demos/gtk-demo/shadertoy.c
Normal file
@@ -0,0 +1,202 @@
|
||||
/* OpenGL/Shadertoy
|
||||
* #Keywords: GtkGLArea
|
||||
*
|
||||
* Generate pixels using a custom fragment shader.
|
||||
*
|
||||
* The names of the uniforms are compatible with the shaders on shadertoy.com, so
|
||||
* many of the shaders there work here too.
|
||||
*/
|
||||
#include <math.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <epoxy/gl.h>
|
||||
#include "gtkshadertoy.h"
|
||||
|
||||
static GtkWidget *demo_window = NULL;
|
||||
static GtkWidget *shadertoy = NULL;
|
||||
static GtkTextBuffer *textbuffer = NULL;
|
||||
|
||||
static void
|
||||
run (void)
|
||||
{
|
||||
GtkTextIter start, end;
|
||||
char *text;
|
||||
|
||||
gtk_text_buffer_get_bounds (textbuffer, &start, &end);
|
||||
text = gtk_text_buffer_get_text (textbuffer, &start, &end, FALSE);
|
||||
|
||||
gtk_shadertoy_set_image_shader (GTK_SHADERTOY (shadertoy), text);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
static void
|
||||
run_clicked_cb (GtkWidget *button,
|
||||
gpointer user_data)
|
||||
{
|
||||
run ();
|
||||
}
|
||||
|
||||
static void
|
||||
load_clicked_cb (GtkWidget *button,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *path = user_data;
|
||||
GBytes *initial_shader;
|
||||
|
||||
initial_shader = g_resources_lookup_data (path, 0, NULL);
|
||||
gtk_text_buffer_set_text (textbuffer, g_bytes_get_data (initial_shader, NULL), -1);
|
||||
g_bytes_unref (initial_shader);
|
||||
|
||||
run ();
|
||||
}
|
||||
|
||||
static void
|
||||
clear_clicked_cb (GtkWidget *button,
|
||||
gpointer user_data)
|
||||
{
|
||||
gtk_text_buffer_set_text (textbuffer, "", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
close_window (GtkWidget *widget)
|
||||
{
|
||||
/* Reset the state */
|
||||
demo_window = NULL;
|
||||
shadertoy = NULL;
|
||||
textbuffer = NULL;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
new_shadertoy (const char *path)
|
||||
{
|
||||
GBytes *shader;
|
||||
GtkWidget *toy;
|
||||
|
||||
toy = gtk_shadertoy_new ();
|
||||
shader = g_resources_lookup_data (path, 0, NULL);
|
||||
gtk_shadertoy_set_image_shader (GTK_SHADERTOY (toy),
|
||||
g_bytes_get_data (shader, NULL));
|
||||
g_bytes_unref (shader);
|
||||
|
||||
return toy;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
new_button (const char *path)
|
||||
{
|
||||
GtkWidget *button, *toy;
|
||||
|
||||
button = gtk_button_new ();
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (load_clicked_cb), (char *)path);
|
||||
|
||||
toy = new_shadertoy (path);
|
||||
gtk_widget_set_size_request (toy, 64, 36);
|
||||
gtk_button_set_child (GTK_BUTTON (button), toy);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_shadertoy_window (GtkWidget *do_widget)
|
||||
{
|
||||
GtkWidget *window, *box, *hbox, *button, *textview, *sw, *aspect, *centerbox;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Shadertoy");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 690, 740);
|
||||
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE);
|
||||
gtk_widget_set_margin_start (box, 12);
|
||||
gtk_widget_set_margin_end (box, 12);
|
||||
gtk_widget_set_margin_top (box, 12);
|
||||
gtk_widget_set_margin_bottom (box, 12);
|
||||
gtk_box_set_spacing (GTK_BOX (box), 6);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
aspect = gtk_aspect_frame_new (0.5, 0.5, 1.77777, FALSE);
|
||||
gtk_widget_set_hexpand (aspect, TRUE);
|
||||
gtk_widget_set_vexpand (aspect, TRUE);
|
||||
gtk_box_append (GTK_BOX (box), aspect);
|
||||
|
||||
shadertoy = new_shadertoy ("/shadertoy/alienplanet.glsl");
|
||||
gtk_aspect_frame_set_child (GTK_ASPECT_FRAME (aspect), shadertoy);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (sw), 250);
|
||||
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
gtk_widget_set_hexpand (sw, TRUE);
|
||||
gtk_box_append (GTK_BOX (box), sw);
|
||||
|
||||
textview = gtk_text_view_new ();
|
||||
gtk_text_view_set_monospace (GTK_TEXT_VIEW (textview), TRUE);
|
||||
g_object_set (textview,
|
||||
"left-margin", 20,
|
||||
"right-margin", 20,
|
||||
"top-margin", 20,
|
||||
"bottom-margin", 20,
|
||||
NULL);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), textview);
|
||||
|
||||
textbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
|
||||
gtk_text_buffer_set_text (textbuffer,
|
||||
gtk_shadertoy_get_image_shader (GTK_SHADERTOY (shadertoy)),
|
||||
-1);
|
||||
|
||||
centerbox = gtk_center_box_new ();
|
||||
gtk_box_append (GTK_BOX (box), centerbox);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE);
|
||||
gtk_box_set_spacing (GTK_BOX (hbox), 6);
|
||||
gtk_center_box_set_start_widget (GTK_CENTER_BOX (centerbox), hbox);
|
||||
|
||||
button = gtk_button_new_from_icon_name ("view-refresh-symbolic");
|
||||
gtk_widget_set_tooltip_text (button, "Restart the demo");
|
||||
gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (run_clicked_cb), NULL);
|
||||
gtk_box_append (GTK_BOX (hbox), button);
|
||||
|
||||
button = gtk_button_new_from_icon_name ("edit-clear-all-symbolic");
|
||||
gtk_widget_set_tooltip_text (button, "Clear the text view");
|
||||
gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (clear_clicked_cb), NULL);
|
||||
gtk_box_append (GTK_BOX (hbox), button);
|
||||
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, FALSE);
|
||||
gtk_box_set_spacing (GTK_BOX (hbox), 6);
|
||||
gtk_center_box_set_end_widget (GTK_CENTER_BOX (centerbox), hbox);
|
||||
|
||||
button = new_button ("/shadertoy/alienplanet.glsl");
|
||||
gtk_box_append (GTK_BOX (hbox), button);
|
||||
|
||||
button = new_button ("/shadertoy/mandelbrot.glsl");
|
||||
gtk_box_append (GTK_BOX (hbox), button);
|
||||
|
||||
button = new_button ("/shadertoy/neon.glsl");
|
||||
gtk_box_append (GTK_BOX (hbox), button);
|
||||
|
||||
button = new_button ("/shadertoy/cogs.glsl");
|
||||
gtk_box_append (GTK_BOX (hbox), button);
|
||||
|
||||
button = new_button ("/shadertoy/glowingstars.glsl");
|
||||
gtk_box_append (GTK_BOX (hbox), button);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_shadertoy (GtkWidget *do_widget)
|
||||
{
|
||||
if (!demo_window)
|
||||
demo_window = create_shadertoy_window (do_widget);
|
||||
|
||||
if (!gtk_widget_get_visible (demo_window))
|
||||
gtk_widget_show (demo_window);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (demo_window));
|
||||
|
||||
return demo_window;
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
/* Shortcuts
|
||||
* #Keywords: GtkShortcutController
|
||||
*
|
||||
* GtkShortcut is the abstraction used by GTK to handle shortcuts from
|
||||
* keyboard or other input devices.
|
||||
|
@@ -1,9 +1,9 @@
|
||||
/* Stack Sidebar
|
||||
*
|
||||
* GtkStackSidebar provides an automatic sidebar widget to control
|
||||
* navigation of a GtkStack object. This widget automatically updates it
|
||||
* content based on what is presently available in the GtkStack object,
|
||||
* and using the "title" child property to set the display labels.
|
||||
* navigation of a GtkStack object. This widget automatically updates
|
||||
* its content based on what is presently available in the GtkStack
|
||||
* object, and using the "title" child property to set the display labels.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
@@ -37,7 +37,6 @@ do_sidebar (GtkWidget *do_widget)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
|
||||
gtk_widget_set_size_request (window, 500, 350);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_window_set_titlebar (GTK_WINDOW(window), header);
|
||||
|
@@ -11,6 +11,20 @@
|
||||
|
||||
#define MAX_ITERATION_COUNT 30
|
||||
|
||||
/* Perform Householder reduction to bidiagonal form
|
||||
*
|
||||
* Input: Matrix A of size nrows x ncols
|
||||
*
|
||||
* Output: Matrices and vectors such that
|
||||
* A = U*Bidiag(diagonal, superdiagonal)*Vt
|
||||
*
|
||||
* All matrices are allocated by the caller
|
||||
*
|
||||
* Sizes:
|
||||
* A, U: nrows x ncols
|
||||
* diagonal, superdiagonal: ncols
|
||||
* V: ncols x ncols
|
||||
*/
|
||||
static void
|
||||
householder_reduction (double *A,
|
||||
int nrows,
|
||||
@@ -160,6 +174,20 @@ householder_reduction (double *A,
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform Givens reduction
|
||||
*
|
||||
* Input: Matrices such that
|
||||
* A = U*Bidiag(diagonal,superdiagonal)*Vt
|
||||
*
|
||||
* Output: The same, with superdiagonal = 0
|
||||
*
|
||||
* All matrices are allocated by the caller
|
||||
*
|
||||
* Sizes:
|
||||
* U: nrows x ncols
|
||||
* diagonal, superdiagonal: ncols
|
||||
* V: ncols x ncols
|
||||
*/
|
||||
static int
|
||||
givens_reduction (int nrows,
|
||||
int ncols,
|
||||
@@ -298,6 +326,11 @@ givens_reduction (int nrows,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Given a singular value decomposition
|
||||
* of an nrows x ncols matrix A = U*Diag(S)*Vt,
|
||||
* sort the values of S by decreasing value,
|
||||
* permuting V to match.
|
||||
*/
|
||||
static void
|
||||
sort_singular_values (int nrows,
|
||||
int ncols,
|
||||
@@ -339,6 +372,16 @@ sort_singular_values (int nrows,
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute a singular value decomposition of A,
|
||||
* A = U*Diag(S)*Vt
|
||||
*
|
||||
* All matrices are allocated by the caller
|
||||
*
|
||||
* Sizes:
|
||||
* A, U: nrows x ncols
|
||||
* S: ncols
|
||||
* V: ncols x ncols
|
||||
*/
|
||||
int
|
||||
singular_value_decomposition (double *A,
|
||||
int nrows,
|
||||
@@ -364,6 +407,18 @@ singular_value_decomposition (double *A,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a singular value decomposition of A = U*Diag(S)*Vt,
|
||||
* compute the best approximation x to A*x = B.
|
||||
*
|
||||
* All matrices are allocated by the caller
|
||||
*
|
||||
* Sizes:
|
||||
* U: nrows x ncols
|
||||
* S: ncols
|
||||
* V: ncols x ncols
|
||||
* B, x: ncols
|
||||
*/
|
||||
void
|
||||
singular_value_decomposition_solve (double *U,
|
||||
double *S,
|
||||
|
@@ -59,8 +59,8 @@ add_row (GtkGrid *table,
|
||||
}
|
||||
|
||||
static void
|
||||
toggle_grouping (GtkToggleButton *check_button,
|
||||
GtkSizeGroup *size_group)
|
||||
toggle_grouping (GtkCheckButton *check_button,
|
||||
GtkSizeGroup *size_group)
|
||||
{
|
||||
GtkSizeGroupMode new_mode;
|
||||
|
||||
@@ -68,7 +68,7 @@ toggle_grouping (GtkToggleButton *check_button,
|
||||
* here to show the effect of GTK_SIZE_GROUP_HORIZONTAL by
|
||||
* contrast.
|
||||
*/
|
||||
if (gtk_toggle_button_get_active (check_button))
|
||||
if (gtk_check_button_get_active (check_button))
|
||||
new_mode = GTK_SIZE_GROUP_HORIZONTAL;
|
||||
else
|
||||
new_mode = GTK_SIZE_GROUP_NONE;
|
||||
|
@@ -1,8 +1,8 @@
|
||||
/* Sliding Puzzle
|
||||
* #Keywords: GdkPaintable, GdkGesture, game
|
||||
*
|
||||
* This demo demonstrates how to use gestures and paintables to create a
|
||||
* small sliding puzzle game.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
@@ -437,7 +437,7 @@ do_sliding_puzzle (GtkWidget *do_widget)
|
||||
choices = gtk_flow_box_new ();
|
||||
gtk_widget_add_css_class (choices, "view");
|
||||
add_choice (choices, puzzle);
|
||||
add_choice (choices, gtk_nuclear_animation_new ());
|
||||
add_choice (choices, gtk_nuclear_animation_new (TRUE));
|
||||
media = gtk_media_file_new_for_resource ("/images/gtk-logo.webm");
|
||||
gtk_media_stream_set_loop (media, TRUE);
|
||||
gtk_media_stream_set_muted (media, TRUE);
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Spin Buttons
|
||||
* #Keywords: GtkEntry
|
||||
*
|
||||
* GtkSpinButton provides convenient ways to input data
|
||||
* that can be seen as a value in a range. The examples
|
||||
|
@@ -1,7 +1,6 @@
|
||||
/* Spinner
|
||||
*
|
||||
* GtkSpinner allows to show that background activity is on-going.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
@@ -22,18 +22,21 @@ do_tabs (GtkWidget *do_widget)
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Tabs");
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 450, 450);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 330, 330);
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
view = gtk_text_view_new ();
|
||||
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD);
|
||||
gtk_text_view_set_top_margin (GTK_TEXT_VIEW (view), 20);
|
||||
gtk_text_view_set_bottom_margin (GTK_TEXT_VIEW (view), 20);
|
||||
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 20);
|
||||
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (view), 20);
|
||||
|
||||
tabs = pango_tab_array_new (3, TRUE);
|
||||
pango_tab_array_set_tab (tabs, 0, PANGO_TAB_LEFT, 0);
|
||||
pango_tab_array_set_tab (tabs, 1, PANGO_TAB_LEFT, 150);
|
||||
pango_tab_array_set_tab (tabs, 2, PANGO_TAB_LEFT, 300);
|
||||
pango_tab_array_set_tab (tabs, 1, PANGO_TAB_LEFT, 100);
|
||||
pango_tab_array_set_tab (tabs, 2, PANGO_TAB_LEFT, 200);
|
||||
gtk_text_view_set_tabs (GTK_TEXT_VIEW (view), tabs);
|
||||
pango_tab_array_free (tabs);
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
/* Text View/Automatic Scrolling
|
||||
* #Keywords: GtkTextView, GtkScrolledWindow
|
||||
*
|
||||
* This example demonstrates how to use the gravity of
|
||||
* GtkTextMarks to keep a text view scrolled to the bottom
|
||||
|
@@ -26,13 +26,20 @@ do_textundo (GtkWidget *do_widget)
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 450, 450);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 330, 330);
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Undo and Redo");
|
||||
|
||||
view = gtk_text_view_new ();
|
||||
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD);
|
||||
gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (view), 10);
|
||||
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 20);
|
||||
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (view), 20);
|
||||
gtk_text_view_set_top_margin (GTK_TEXT_VIEW (view), 20);
|
||||
gtk_text_view_set_bottom_margin (GTK_TEXT_VIEW (view), 20);
|
||||
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
||||
gtk_text_buffer_set_enable_undo (buffer, TRUE);
|
||||
|
||||
@@ -40,10 +47,13 @@ do_textundo (GtkWidget *do_widget)
|
||||
gtk_text_buffer_begin_irreversible_action (buffer);
|
||||
gtk_text_buffer_get_start_iter (buffer, &iter);
|
||||
gtk_text_buffer_insert (buffer, &iter,
|
||||
"Type to add more text.\n"
|
||||
"Use Primary+Z to undo and Primary+Shift+Z to redo a previously undone action.\n"
|
||||
"\n",
|
||||
-1);
|
||||
"The GtkTextView supports undo and redo through the use of a "
|
||||
"GtkTextBuffer. You can enable or disable undo support using "
|
||||
"gtk_text_buffer_set_enable_undo().\n"
|
||||
"Type to add more text.\n"
|
||||
"Use Control+z to undo and Control+Shift+z or Control+y to "
|
||||
"redo previously undone operations.",
|
||||
-1);
|
||||
gtk_text_buffer_end_irreversible_action (buffer);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
|
@@ -142,7 +142,7 @@ insert_text (GtkTextView *view)
|
||||
32, 1,
|
||||
gtk_widget_get_direction (widget),
|
||||
0);
|
||||
nuclear = gtk_nuclear_animation_new ();
|
||||
nuclear = gtk_nuclear_animation_new (TRUE);
|
||||
|
||||
/* get start of buffer; each insertion will revalidate the
|
||||
* iterator to point to just after the inserted text.
|
||||
|
@@ -10,76 +10,6 @@
|
||||
|
||||
static guint tick_cb;
|
||||
|
||||
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 double
|
||||
frame_clock_get_fps (GdkFrameClock *frame_clock)
|
||||
{
|
||||
GdkFrameTimings *start, *end;
|
||||
gint64 start_counter, end_counter;
|
||||
gint64 start_timestamp, end_timestamp;
|
||||
gint64 interval;
|
||||
|
||||
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 0.0;
|
||||
|
||||
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);
|
||||
}
|
||||
interval = gdk_frame_timings_get_refresh_interval (end);
|
||||
if (interval == 0)
|
||||
{
|
||||
interval = guess_refresh_interval (frame_clock);
|
||||
if (interval == 0)
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return ((double) end_counter - start_counter) * G_USEC_PER_SEC / (end_timestamp - start_timestamp);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
gboolean dark;
|
||||
@@ -116,7 +46,7 @@ change_theme (GtkWidget *widget,
|
||||
{
|
||||
char *fps;
|
||||
|
||||
fps = g_strdup_printf ("%.2f fps", frame_clock_get_fps (frame_clock));
|
||||
fps = g_strdup_printf ("%.2f fps", gdk_frame_clock_get_fps (frame_clock));
|
||||
gtk_label_set_label (GTK_LABEL (label), fps);
|
||||
g_free (fps);
|
||||
}
|
||||
|
@@ -19,7 +19,11 @@
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkLabel" id="fps"/>
|
||||
<object class="GtkLabel" id="fps">
|
||||
<attributes>
|
||||
<attribute name="font-features" value="tnum=1"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user