Compare commits

...

256 Commits

Author SHA1 Message Date
Luca Bacci
5b4d4b17ed WIP 2024-10-10 10:39:15 +02:00
Luca Bacci
be2adb1838 Merge branch 'msys2-switch-to-ucrt64' into 'main'
MSYS2: Switch to UCRT64

See merge request GNOME/gtk!7812
2024-10-10 08:26:45 +00:00
Luca Bacci
0113fdc8d5 Merge branch 'gdk-win32-purge-globals' into 'main'
GDK/Win32: Drop most of the global variables

See merge request GNOME/gtk!7804
2024-10-10 08:26:30 +00:00
Matthias Clasen
53cbc64f41 Merge branch 'alatiera/sysprof-uri' into 'main'
gtkcssprovider: Only add the marker if the file is not null

See merge request GNOME/gtk!7807
2024-10-09 15:40:12 +00:00
Jordan Petridis
83387608ee gtkcssprovider: Use g_file_peek_path to get the uri for the sysprof marker
This avoids an extra allocation.

Additionally avoid calling it if file is already null.
2024-10-09 17:39:08 +03:00
Benjamin Otte
a5b4d2b500 Merge branch 'typo-fix' into 'main'
Fix a typo

Closes #6984

See merge request GNOME/gtk!7816
2024-10-08 23:30:07 +00:00
ARAKHNID
1b83d87cf5 Fix a typo
Closes #6984
2024-10-08 13:41:04 -05:00
Emmanuele Bassi
6c2eb08b07 Merge branch 'wip/chergert/fix-a11y-default-attributes' into 'main'
gtk/accessibletext: handle NULL default values

Closes #7069

See merge request GNOME/gtk!7813
2024-10-08 18:10:26 +00:00
Christian Hergert
ab1c85830c gtk/accessibletext: handle NULL default values
The default implementation for get_default_attributes() returns NULL for
both names and values yet the code which iterates them is assuming they
will never be NULL.

Since the interface implies that if the values are set, they will return
valid strings, make the default implementation do that.

Fixes: #7069
2024-10-08 10:41:19 -07:00
Luca Bacci
d154decbb5 CI/MSYS2: Switch to UCRT64 2024-10-08 14:01:32 +02:00
Luca Bacci
c7705f156a Rework test-msys2.sh a bit 2024-10-08 13:59:43 +02:00
Luca Bacci
20bdb0d7d5 Merge branch 'wgl-updates' into 'main'
WGL: Avoid using swap exchange on NVidia drivers

Closes #7019

See merge request GNOME/gtk!7776
2024-10-08 10:24:02 +00:00
Luca Bacci
f840ae1337 WGL: Avoid using swap method exchange on NVidia drivers
It seems that NVidia sets PFD_SWAP_EXCHANGE / WGL_SWAP_EXCHANGE_ARB
on pixel formats but doesn't guarantee that the backbuffer age is
constantly 2. My guess is that they use swap exchange only to signal
usage of a flip present method.

Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/7019
2024-10-08 11:27:05 +02:00
Benjamin Otte
02feba87f2 Merge branch 'wip/otte/for-main' into 'main'
gpu: Remove warning

See merge request GNOME/gtk!7805
2024-10-07 10:20:37 +00:00
Benjamin Otte
220d7a3d5e picture: Queue a redraw when not resizing
When changing the code to do the resize only when the size changed, I
forgot to queue a draw when the size did not change.

Fixes: 5031f30f28
Related: !7786
2024-10-07 11:35:50 +02:00
Benjamin Otte
39686daa23 gpu: Remove warning
The warning gets triggered by rounding errors.

In particular when using fractional scales, the final tile may end up
not accurately matching the computed final value (in the example I was
debugging it was computing 1 vs 1.00000036 for the final tile index,
but that result computed a 0px wide tile size.
And for that tile size we hit that exit condition.
2024-10-07 11:31:34 +02:00
Chun-wei Fan
b6269a3234 gdkevents-win32.c: Drop AeroSnap global variables
Put them into our GdkWin32Display under an appropriate sub-struct.
2024-10-07 14:37:40 +08:00
Chun-wei Fan
2879f6a99b gdkevents-win32.c: Drop event debug indent global variable
Tuck it as appropriate into our GdkWin32Display.
2024-10-07 14:37:40 +08:00
Chun-wei Fan
03a86b4667 GDK/Win32: Drop global variable on both shifts pressed 2024-10-07 14:37:39 +08:00
Chun-wei Fan
7eb96c39c5 GDK/Win32: Drop global variable tracking IME state
Tuck it into our GdkDisplay structure under an appropriate sub-struct.
2024-10-07 14:37:38 +08:00
Chun-wei Fan
b4c5a7af69 GDK/Win32: Fold pen input global vars into GdkDeviceManagerWin32
This way, we just grab and set the values from there.
2024-10-07 14:37:38 +08:00
Chun-wei Fan
d120aaf6ee GDK/Win32: Drop global variables from GdkKeys implementation
We get to create our GdkKey with a display as a property for free, so
just stuff the default keymap and keymap serial (to track IME state
changes and so) into our GdkWin32Display under an existing sub-struct
that is for holding these items.
2024-10-07 14:37:23 +08:00
Chun-wei Fan
004d787cb2 Gdk/Win32: Drop _gdk_display global variable
On Windows, we really only support a single GdkDisplay, so we can just
make the GdkDisplay that we obtain a property of our GdkDeviceManagerWin32
and GdkWin32Screen objects, and so we can just do away with the global
_gdk_display global variable.

This way, we can also drop the venerable gdkglobals-win32.c source file.
Yay!
2024-10-07 12:07:05 +08:00
Chun-wei Fan
7b554240f3 GDK/Win32: Drop modal surface-related global variables
Tuck them into GdkWin32Display as we track these operations.
2024-10-07 12:01:08 +08:00
Chun-wei Fan
7837f342e9 GdkDeviceManagerWin32: Drop global variables
Tuck the wintab global variables into the GdkDeviceManagerWin32
structure, and initialize and utilize items accordingly.
2024-10-07 12:01:07 +08:00
Chun-wei Fan
236139c78a gdkdisplay-win32.c: Drop debug_indent global variable
Instead, use [Set|Get]WindowLongPtr(), to store and retrieve that
value from the notification window HWND that we are using, as it
is where we are using that value.
2024-10-07 12:01:06 +08:00
Chun-wei Fan
789bb83b5a GDK/Win32: Drop surface tracking global variables
...including the list of modal surfaces and hashes of opened HWNDs for
various surfaces, and tuck them into GdkWin32Display.
2024-10-07 12:00:59 +08:00
Chun-wei Fan
0a65221721 GDK/Win32: Drop global variables in Direct Manipuation code
Tuck them into GdkWin32Display.
2024-10-07 11:56:21 +08:00
Chun-wei Fan
b37947ff20 GDK/Win32: Drop global variables related to GdkDevice
Tuck the _win32_device_manager global variable into GdkWin32Display, and
drop the global variables that have to do with GdkDeviceManagerWin32.

Also improve how we query the WinPointer APIs from user32.dll, so that
we are sure that it is done once and only once.
2024-10-07 11:56:20 +08:00
Chun-wei Fan
0d4f827de8 GDK/Win32: Drop Clipdrop/DND global variables
Tuck the GdkWin32Clipdrop that we create in our GdkWin32Display, and
tuck the other associated global variables into GdkWin32ClipDrop and
GdkWin32Drag, as appropriate.

Also, since we are already registering "GDK_WORKER_THREAD_WAKEUP" as our
custom message to look for in our DND/clipboard ops, only register it
once, not twice, as it's not really necessary to do so since
RegisterWindowMessage() returns the same value for the same identifier
that is being used.,
2024-10-07 11:56:12 +08:00
Chun-wei Fan
1f52048e77 GDK/Win32: Drop global variable to track main thread
Instead, record the current thread in the GdkDisplay, under a structure
for DND items, which will hold other relevant Windows Clipbord/DND global
variables.

Add a new function in gdkdrag-win32.c to check whether the current
thread is (or is not) equivilant to the thread that is initiated when
the GdkDisplay is initialized (which also returns true if there is no
GdkDisplay that is associated with the GdkDrag in question).
2024-10-07 11:54:26 +08:00
Chun-wei Fan
7600d44995 GDK/Win32: Drop _gdk_ignore_input_core global variable
...and fold it into GdkWin32Display under pointer_device_items.
2024-10-07 11:50:21 +08:00
Chun-wei Fan
8bb806cd85 gdkmain-win32.c: Tuck global varianbles into local variables
...and use g_once_init_[enter|leave]() to mark that GDK did or did not
indeed successfully initialize COM and OLE2.
2024-10-07 11:39:04 +08:00
Chun-wei Fan
28aacf3db4 GDK/Win32: Drop input locale global variables
Rename gdkwin32id.c as gdkwin32misc.c.

Fold these items into GdkWin32Display, and also fold gdkproperty-win32.c
and gdkwin32langnoticiation.[c|h] into gdkwin32misc.c and gdkdisplay-win32.h as
appropriate.

This way, we get rid of few more global variables, and these items
should have been initialized (and registered with the system) when we
open a GdkWin32Display anyways.
2024-10-07 11:37:14 +08:00
Chun-wei Fan
95ad05181c gdksurface-win32.c: Drop a global variable
Use the gdk_win32_surface_parent_class that is given to us by
G_DEFINE_TYPE() instead of using a global variable to store up the
parent class of GdkWin32Surface.
2024-10-07 10:28:34 +08:00
Martin
b4a54bb9cb Update Slovenian translation 2024-10-05 18:36:53 +00:00
Matthias Clasen
12dd5be649 Merge branch '3to4-separator' into 'main'
gtk4-builder-tool: Rewrite Gtk{H,V}Seperator

See merge request GNOME/gtk!7800
2024-10-05 14:52:30 +00:00
Guido Günther
c86e45c432 gtk4-builder-tool: Rewrite Gtk{H,V}Seperator
One less UI element to worry about when migrating from GTK3.

Signed-off-by: Guido Günther <agx@sigxcpu.org>
2024-10-05 15:54:49 +02:00
Matthias Clasen
1ad5943cd8 Merge branch 'for-main' into 'main'
image tool: Better color state support

See merge request GNOME/gtk!7799
2024-10-05 13:38:07 +00:00
Matthias Clasen
34c69b2868 build: Don't use / in target names
It is unnecessary, and meson doesn't like it.
2024-10-05 08:55:50 -04:00
Matthias Clasen
28817b4bb2 image tool: Better color state support
Show cicp color states with their tuple.
2024-10-05 08:16:07 -04:00
Matthias Clasen
b0acf2a7a8 Merge branch 'for-main' into 'main'
docs: Update GSK_GPU_DISABLE docs

See merge request GNOME/gtk!7798
2024-10-05 02:05:34 +00:00
Matthias Clasen
32d03a548e Drop some demos
The gtk4-icon-browser and gtk4-constraint-editor demos are basically
unmaintained, and not great showcases for GTK, so lets drop them.
2024-10-04 21:24:11 -04:00
Matthias Clasen
fecadae80c docs: Update GSK_GPU_DISABLE docs
Add `repeat`.
2024-10-04 14:42:38 -04:00
Matthias Clasen
2d1367ccdc Merge branch 'wip/otte/this-looks-correct-but-is-it' into 'main'
listitemfactory: Don't rebind on position or selection changes

See merge request GNOME/gtk!7420
2024-10-04 18:32:08 +00:00
Matthias Clasen
ac1c0d37c6 Merge branch 'gstreamer-no-gl' into 'main'
gstreamer: Fix gl context creation

See merge request GNOME/gtk!7796
2024-10-04 15:57:46 +00:00
Matthias Clasen
ea6bcdbd3d gstreamer: Fix gl context creation
We may not have a surface (since realizing media streams is optional),
so use the display when creating a gl context.
2024-10-04 11:18:48 -04:00
Matthias Clasen
fe83b06eaf Merge branch 'gbsneto/fix-a11y-nonwidget-recurse' into 'main'
atcontext: Only recurse parents for non-widget accessibles

Closes #7058

See merge request GNOME/gtk!7793
2024-10-04 13:19:07 +00:00
Matthias Clasen
be5fd3d89f Merge branch 'gstreamer-no-gl' into 'main'
gstreamer: Make dmabufs work without GL

Closes #7048

See merge request GNOME/gtk!7787
2024-10-04 13:09:42 +00:00
Matthias Clasen
bef38bd9c4 gstreamer: Tweak gl context handling
Just create the context when it is needed.
2024-10-04 08:21:58 -04:00
Georges Basile Stavracas Neto
06f08ea804 atcontext: Only recurse parents for non-widget accessibles
The original intent was to only realize parents recursively for
non-widget accessible objects. The implementation, however, always
try to realize parents. In the case of GtkStackPage, which is a
non-widget accessible with a widget accessible child, this breaks.

Only realize non-widget accessible parents recursively if the
current accessible is not a widget as well.

Closes https://gitlab.gnome.org/GNOME/gtk/-/issues/7058
Fixes 6074a18e3e
2024-10-04 09:19:57 -03:00
Matthias Clasen
79bb805a02 gstreamer: Simplify
Add a uses-gl property to our sink implementation, and use
it in the paintable code. This avoids juggling a second gl
context, with the risk of leaking it.
2024-10-04 07:49:07 -04:00
Matthias Clasen
d70c005021 gstreamer: Improve caps handling
Separate out the caps for dmabuf, gl and memory and add them
when appropriate.
2024-10-04 07:44:20 -04:00
Matthias Clasen
9fc7d8e947 Restructure gtk_gst_paintable_video_renderer_create_video_sink
This code had too many early exits and was leaking GL contexts
and Gstreamer elements. Simplify.
2024-10-04 07:44:20 -04:00
Matthias Clasen
b06ac9826c gstreamer: Use the default display if needed
Calling gtk_media_stream_realize is not mandatory, but we can
still try to make dmabufs happen. Tested by removing the realize
call from GtkVideo and using GDK_DISABLE=gl.
2024-10-04 07:44:20 -04:00
Matthias Clasen
94cacd79f9 gstreamer: Restructure gtk_gst_sink_propose_allocation
Split this clearly into two cases: dmabuf or gl memory.
2024-10-04 07:44:20 -04:00
Matthias Clasen
17d3631605 gstreamer: Make dmabufs work without GL
We only need a display to negotiate dmabuf formats. Pass that
directly, instead of getting the display of the GL context as
we did so far.

With this,

GSK_RENDERER=vulkan GL_DISABLE=gl gtk4-demo --run video_player

still uses dmabufs.

Related: #7048
2024-10-04 07:44:20 -04:00
Matthias Clasen
3b027cf466 Merge branch 'for-main' into 'main'
gpu: Add GSK_GPU_DISABLE=repeat

See merge request GNOME/gtk!7791
2024-10-04 00:48:58 +00:00
Matthias Clasen
5d4f2822d0 Fix testsuite setup
We no longer say GDK_DEBUG=gl-prefer-gl, we say GDK_DISABLE=gles-api.
2024-10-03 20:11:00 -04:00
Benjamin Otte
5a11ee7b9c gpu: Add GSK_GPU_DISABLE=repeat
This is useful for testing of repeat nodes - both performance
and conformance, and potentially even driver issues with GL_REPEAT.

We have code for manual repeating anyway, so adding a flag to force
always using it is easy.
2024-10-03 20:11:00 -04:00
Matthias Clasen
874410129e Merge branch 'fix-scrolled-window-criticals' into 'main'
scrolledwindow: Fix measuring non-overlay, always visible scrollbars

See merge request GNOME/gtk!7790
2024-10-03 17:52:16 +00:00
Sergey Bugaev
2cf1651235 scrolledwindow: Fix measuring non-overlay, always visible scrollbars
The last part of logic in gtk_scrolled_window_measure () that accounted
for scrollbars was handling the hscrollbar first, and vscrollbar second.
For each of them, it looked at the orientation we're being measured in,
and either added or MAX'ed scrollbar's size request into ours (or not,
depending on scrollbar policy and whether overlay scrolling is used).

In case of GTK_ORIENTATION_HORIZONTAL, this resulted in

    // MAX in hscrollbar width.
    minimum_req = MAX (minimum_req, min_scrollbar_width + sborder.left + sborder.right);
    // Add in vscrollbar width.
    minimum_req += min_scrollbar_width;

whereas for GTK_ORIENTATION_VERTICAL, it was

    // Add in hscrollbar height.
    minimum_req += min_scrollbar_height;
    // MAX in vscrollbar height.
    minimum_req = MAX (minimum_req, min_scrollbar_height + sborder.top + sborder.bottom);

The former is correct and the latter is wrong: we should be adding the
size requests of the scrollbars together, and MAX'ing them with the
content size request.

Fix this by refactoring the logic to first handle the MAX'ing, and then
the addition.

This fixes the following criticals:

Gtk-CRITICAL **: 17:26:51.406: Allocation height too small. Tried to allocate 15x31, but GtkScrollbar 0x2a00fac0 needs at least 15x46.

that were happening when all of:
- scrollbar policy was set to ALWAYS,
- overlay scrolling was disabled,
- the scrollable child was really small.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2024-10-03 19:04:15 +03:00
Matthias Clasen
ad2221ce29 Merge branch 'fix-filechooser-crash' into 'main'
window: Fix crash when unexporting unrealized window

See merge request GNOME/gtk!7769
2024-10-03 15:53:44 +00:00
Sergey Bugaev
6dd0be2f06 printdialog: Call gtk_window_unexport_handle
We need to track the handle and properly unexport it.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2024-10-03 17:14:11 +03:00
Sergey Bugaev
2103ab99a5 window: Fix crash when unexporting unrealized window
It is possible that the window gets unrealized while a handle to its
surface is exported. This, naturally, invalidates the handle, so there
is nothing left to unexport. We should just note that and do nothing,
rather than crashing.

Fixes a crash when a portal-backed file dialog parented to a window is
closed after the window it was parented to.

Reported-by: Ivan Molodetskikh <yalterz@gmail.com>
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2024-10-03 17:14:11 +03:00
Sergey Bugaev
d7ab7e9628 window: Fix a typo
Fortunately, it didn't impact string length.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2024-10-03 17:14:11 +03:00
Matthias Clasen
3d7ac47e5e Merge branch 'gbsneto/atspi-socket-realize' into 'main'
atcontext: Always realize non-widget accessibles

See merge request GNOME/gtk!7784
2024-10-03 09:46:40 +00:00
Chun-wei Fan
c373e2c76b Merge branch 'gdk-win32-rename' into 'main'
GDK/Win32: Rename instances of "window" as in the GTK+-3.x-era GdkWindow as appropriate

See merge request GNOME/gtk!7738
2024-10-03 05:44:07 +00:00
Matthias Clasen
ec3b27bb68 Merge branch 'for-main' into 'main'
Don't draw transparent fillers

See merge request GNOME/gtk!7788
2024-10-03 03:43:54 +00:00
Benjamin Otte
5b87dba1a3 Merge branch 'wip/otte/for-main' into 'main'
picture: Only queue_resize() if necessary

See merge request GNOME/gtk!7786
2024-10-03 01:10:53 +00:00
Matthias Clasen
12dcaf1e7a Don't draw transparent fillers
Repeat nodes take child bounds that let us achieve the desired
spacing without resorting to transparent fillers.
2024-10-02 21:05:21 -04:00
Benjamin Otte
5031f30f28 picture: Only queue_resize() if necessary
When setting a new paintable, we don't need to queue_resize() when it's
the same size as the old paintable.

This is especially useful when pictures are used in a listview or
gridview and different rows display images of the same size.
2024-10-03 02:56:12 +02:00
Matthias Clasen
ad465e81aa Merge branch 'for-main' into 'main'
ci: Stop using catch

See merge request GNOME/gtk!7785
2024-10-03 00:41:40 +00:00
Matthias Clasen
39374c7209 gtk4-demo: Make demos standalone
Making the demo windows transient and modal makes gnome-shell
treat them like dialogs, which is not right.
2024-10-02 19:15:31 -04:00
Matthias Clasen
170a1cd941 ci: Stop using catch
It is useful to track down mysterious crashes in ci, but it causes
sporadic test failures, so disable it for now, until we have another
mysterious crash.
2024-10-02 19:15:31 -04:00
Georges Basile Stavracas Neto
6074a18e3e atcontext: Always realize non-widget accessibles
Upon joining the a11y tree. And do so recursively, as long as the parent
is also not a widget.

As for the explanation, please grab a mug of your favorite drink. It's
a little complicated.

GTK realizes AT contexts in 3 situations:

 1. When it's a toplevel, it's realized unconditionally
 2. When the widget is focused
 3. When the accessible is appended to a realized parent

Most importantly, GTK lazily realizes accessibles, and does not realize
child accessibles recursively.

Clearly, conditions 1 and 2 only ever happen for GtkWidgets, which are
accessible objects themselves. These two conditions will handle the vast
majority of cases of apps and platform libraries.

However, there are non-widget accessibles out there. GTK itself offers a
non-widget accessible implementation - GtkAtspiSocket - which is used by
WebKitGTK.

Now, let's look at WebKitGTK use case. It'll demonstrate the problem
nicely.

WebKitGTK creates the GtkAtspiSocket object *after* loading most of the
page. At this point, there are 2 possibilities:

 1. The web view widget is focused. In this case, the AT context of the
    web view is realized, and GTK will realize the GtkAtspiSocket when
    it is added to the a11y tree (condition 3 above).

 2. The web view widget is *not* focused. At some point the user focuses
    the web view, and GTK will realize the AT context of the web view.
    But remember, GTK does not realize child accessibles! That means
    GtkAtspiSocket won't be realized.

This example demonstrates a general problem with non-widget accessibles:
non-widget accessibles cannot trigger conditions 1 and 2, so they're
never realized. The only way they're realized in if they happen to be
added to an already realized accessible (condition 3).

To fix that, the following is proposed: always realize non-widget
accessibles, and also of their non-widget accessible parents. This is
not ideal, of course, as it might generate some D-Bus chattery, but GTK
does not have enough information to realize these objects at more
appropriate times.
2024-10-02 16:07:30 -03:00
Georges Basile Stavracas Neto
5d5b612630 atcontext: Factor out some code
Move the code that realizes an AT context if the parent is realized,
into to a separate function. This will make the next patch easier to
read.

No functional changes.
2024-10-02 14:51:33 -03:00
Matthias Clasen
5942252175 Merge branch 'scrolling-underline-demo' into 'main'
gtk4-demo: Add another scrolling case

See merge request GNOME/gtk!7781
2024-10-02 17:32:22 +00:00
Benjamin Otte
9a3898fe89 Merge branch 'wip/otte/for-main' into 'main'
dmabuf: Change a debug message

See merge request GNOME/gtk!7782
2024-10-02 12:36:02 +00:00
Benjamin Otte
c6a3efaf70 dmabuf: Unify initialization debug messages
... and print if a format is advertised.

We now use the same style of message and use the term "advertise" for
formats that will be available via GdkDisplay::dmabuf-formats and
"supports" for formats the backend pretends it can handle but don't
want to advertise them.
2024-10-02 13:39:48 +02:00
Benjamin Otte
9870234294 dmabuf: Change a debug message
Instead of only printing the advertised dmabuf formats, print all
supported ones. This is now useful information because we will try to
use them when downloading.

Fixes me looking like I don't know what I'm talking about on IRC when
claiming that llvmpipe can't do dmabufs, because it only supports linear
ones and we didn't print those.
2024-10-02 13:39:48 +02:00
Matthias Clasen
64ecb972cf gtk4-demo: Add another scrolling case
Add a case for text with various underlines. In particular error
underlines, since these are more complicated and use repeat nodes
and offscreens.
2024-10-02 07:21:41 -04:00
Matthias Clasen
ded6d400d7 gtk-demo: Make scrolling benchmark resizable
The small window does not really tax our renderer much. Make it
resizable, so we can test fullscreen scrolling.
2024-10-02 07:20:36 -04:00
Chun-wei Fan
979a37d3f7 GDK/Win32: Rename _gdk_win32_get_window_rect()
... to gdk_win32_get_surface_hwnd_rect(), so that things are a bit
clearer.
2024-10-02 12:52:44 +08:00
Chun-wei Fan
270e6165f4 GDK/Win32: Rename GtkShowWindow() to GtkShowSurfaceHWND()
Makes this function a bit clearer on what is being done.
2024-10-02 12:52:44 +08:00
Chun-wei Fan
df51d474fc GDK/Win32: Rename "window" for event handling code
We want to make the distinction between GdkSurface's and native Windows
HWNDs clearer.
2024-10-02 12:52:44 +08:00
Chun-wei Fan
1e0ab6f249 gdkprivate-win32.h: Rename "window" as needed
We want to make the distinction between GdkSurface's and native Windows
HWNDs clearer.
2024-10-02 12:52:44 +08:00
Chun-wei Fan
deb4de6332 gdkvulkancontext-win32.c: Rename "window" as needed
We want to make the distinction between GdkSurface's and native Windows
HWNDs clear, and we don't want to confuse between GdkSurface's and
Vulkan surfaces.
2024-10-02 12:52:44 +08:00
Chun-wei Fan
b4c7dd770c GDK/Win32: Rename "window" for DND/clipboard code
We want to make the distinction between GdkSurface's and native Windows
HWND clearer.
2024-10-02 12:52:44 +08:00
Chun-wei Fan
7488644176 gdkdisplay-win32.c: Rename "window" as appropriate
We want to make the distinction between GDK surfaces and the native
(underlying) Windows HWNDs clearer.
2024-10-02 12:52:44 +08:00
Chun-wei Fan
9ed7cecd42 GDK/Win32: Rename "window" in GdkDevice/GdkDeviceManager code
Make the distinction between GdkSurfaces and the underlying native
Windows HWND clearer in the code and in the comments.
2024-10-02 12:52:44 +08:00
Chun-wei Fan
df36ab3f93 GDK/Win32: Rename "window" items in Cairo context code
Make the distinction between GDK surfaces and native Windows HWNDs
clearer.
2024-10-02 12:52:44 +08:00
Chun-wei Fan
7e4fdea71b GDK/Win32: Rename "window" in gdksurface-win32.* code
In order to help us in our refactoring, make the distinction between Gdk
surfaces and native Win32 HWND clearer in terms of the variables that we
used, and in the comments in the code.

Also, group forward function prototype declarations in one place, and
drop some unneeded items in gdkprivate-win32.h to fold them into
gdksurface-win32.c, as they are only used there.
2024-10-02 12:52:44 +08:00
Matthias Clasen
ea8062e86a Merge branch 'for-main' into 'main'
gsk: Allow Vulkan software rendering as fallback

See merge request GNOME/gtk!7780
2024-10-02 01:31:05 +00:00
Matthias Clasen
c4efe7709b Drop GDK_VULKAN_DEVICE support
We don't need our own mechanism for device selection; mesa has a
Vulkan layer that works perfectly fine for this purpose; just set
MESA_VK_DEVICE_SELECT.
2024-10-01 21:00:16 -04:00
Matthias Clasen
fdea496883 gsk: Allow Vulkan software rendering as fallback
There is no reason to exclude lavapipe when we accept llvmpipe,
and lavapipe has the advantage that it supports dmabufs.
2024-10-01 20:57:49 -04:00
Matthias Clasen
60878e4186 Merge branch 'for-main' into 'main'
gsk: Prefer ngl over cairo

See merge request GNOME/gtk!7779
2024-10-02 00:45:13 +00:00
Matthias Clasen
02297138f3 gsk: Tweak renderer selection debug spew
Print a message for every get_renderer function that returns
FALSE, so the debug spew lets us get a clear picture of what
possibilities were tried.
2024-10-01 20:12:17 -04:00
Benjamin Otte
6603e02beb Merge branch 'wip/otte/for-main' into 'main'
Revert "tools: Drop support for the gl renderer"

See merge request GNOME/gtk!7778
2024-10-01 23:57:20 +00:00
Matthias Clasen
bfb7573810 gsk: Prefer ngl over cairo
Now that the gl renderer is no longer in our fallback sequence, use
ngl instead. With current ngl, llvmpipe is still better than cairo.
2024-10-01 19:42:08 -04:00
Benjamin Otte
6847c3469d testsuite: Keep bounds for clip tests
The hope here is that it makes clip tests more reproducible because the
coordinates in device pixels are still the same as before.
2024-10-02 01:26:24 +02:00
Benjamin Otte
7a1e5b4418 compare-render: Add a KEEP_BOUNDS flag
If that flag is set, we keep the bounds of the original node when
rendering the modified node.

Gets around the replay test having to draw a transparent color node to
ensure the same bounds.
2024-10-02 01:26:24 +02:00
Benjamin Otte
76980e10a0 Revert "tools: Drop support for the gl renderer"
This reverts commit fd02afa2e4.

We don't want to remove the GL renderer from our tools yet, because we
use those tools for manual testing and having it available is useful.

In particular, reinstate the GL renderer for rendernode-tool benchmark.
2024-10-02 01:25:30 +02:00
Matthias Clasen
34f4a06691 Merge branch 'gl-renderer-memorytexture-test' into 'main'
Stop using a gl renderer in the memorytexture text

See merge request GNOME/gtk!7773
2024-10-01 21:29:29 +00:00
Matthias Clasen
2dea5ae958 Merge branch 'for-main' into 'main'
inspector: Plug a  memory leak

See merge request GNOME/gtk!7775
2024-10-01 15:52:05 +00:00
Matthias Clasen
5856716188 inspector: Plug a memory leak
Found by code inspection of all the places where we use texture
builders.
2024-10-01 08:59:52 -04:00
Matthias Clasen
1c4a0dae62 Merge branch 'gst-texture-builder-leak' into 'main'
gst: Don't leak texture builders

See merge request GNOME/gtk!7774
2024-10-01 12:20:48 +00:00
Matthias Clasen
b7fba6298f gst: Don't leak texture builders
Found by code inspection. The leak was introduced in 4707784755.

Might help for #4184
2024-10-01 07:18:32 -04:00
Matthias Clasen
5ce196fe9f Rename memory texture tests from ngl to gl 2024-09-30 21:59:59 -04:00
Matthias Clasen
c31c89c794 Drop gl renderer tests from memory texture test 2024-09-30 21:55:33 -04:00
Matthias Clasen
1eb8c3ea34 tests: Add ngl-released in memory texture test
This is parallel to the gl-released method, but for ngl.
2024-09-30 21:52:16 -04:00
Matthias Clasen
b2414b1ecd Merge branch 'for-main' into 'main'
gtk4-demo: Drop the glshader demos

See merge request GNOME/gtk!7771
2024-10-01 01:47:09 +00:00
Matthias Clasen
fd3dfaf2c3 Merge branch 'dmabuf-import-fixup' into 'main'
gl: Treat internal textures as special case

See merge request GNOME/gtk!7772
2024-10-01 01:46:44 +00:00
Benjamin Otte
43a6c8c5f5 gl: Treat internal textures as special case
Treat external as the normal case, and only try importing dmabufs
as non-external images if their format is on the internal formats
list.

Also add internal linear formats to the internal formats list.

This fixes an issue where AR24:0 dmabufs were imported as external
textures, causing some of the compare tests to fail.
2024-09-30 21:16:41 -04:00
Matthias Clasen
3789191853 docs: Stop mentioning the gl renderer
It is going away.
2024-09-30 19:24:42 -04:00
Matthias Clasen
eb4fb2af0e gsk: Stop falling back to the gl renderer
The GL renderer is going away. For now, it is still possible
to use it explicitly, with GSK_RENDERER=gl.
2024-09-30 19:22:54 -04:00
Matthias Clasen
fd02afa2e4 tools: Drop support for the gl renderer
The GL renderer is going away in 4.18.
2024-09-30 19:22:54 -04:00
Matthias Clasen
55bb77cffc tests: Use the ngl renderer in one more place 2024-09-30 19:22:54 -04:00
Matthias Clasen
119ba5844f testsuite: Drop glshader tests
And drop the gl renderer test here, but add ngl and Vulkan
equivalents.
2024-09-30 19:22:54 -04:00
Matthias Clasen
9b2b5ebb65 gsk: Stop supporting gl shaders
The GL shader code uses the GL renderer for compilation, and that
renderer is going away.
2024-09-30 19:22:54 -04:00
Matthias Clasen
1624455a32 gsk: Use the ngl renderer for serializing to png
This is a step towards dropping the GL renderer.
2024-09-30 18:58:33 -04:00
Matthias Clasen
d483883f38 node-editor: Use NGL for exporting images
This is a step towards dropping the GL renderer.
2024-09-30 18:58:33 -04:00
Matthias Clasen
0dc0bea1d5 gtk4-demo: Drop the glshader demos
The GL renderer will be going away in 4.18, and with that, shader
nodes will stop working for good. It is time to start preparing
for that.
2024-09-30 18:58:33 -04:00
Matthias Clasen
55e31b972c Merge branch 'dmabuf-failable-download' into 'main'
Make gdk_dmabuf_downloader_download failable

See merge request GNOME/gtk!7720
2024-09-30 22:41:57 +00:00
Matthias Clasen
1013874de8 gpu: Drop get_dmabuf_formats
This vfunc is no longer needed.
2024-09-30 18:37:20 -04:00
Matthias Clasen
c397460c11 Drop gdk_dmabuf_downloader_supports
It is not used anymore.
2024-09-30 18:37:20 -04:00
Matthias Clasen
ff0045b8c9 dmabuftexture: Stop having a fixed downloader
Change things from picking a download method at creation time to
trying all methods at download time until one succeeds.
2024-09-30 18:37:20 -04:00
Matthias Clasen
d0b409d349 Make gsk_gpu_frame_download_texture return status
Importing a dmabuf can fail, even if the format is supported
in princicple, In these cases, gsk_gpu_frame_download_texture
will return FALSE.
2024-09-30 18:37:20 -04:00
Matthias Clasen
c0cb10262d Make gdk_dmabuf_download_mmap return status
Make this function return whether it was successful, and only emit
a debug message if we succeeded. In particular, make it return FALSE
if the dmabuf format is not linear.
2024-09-30 18:37:20 -04:00
Matthias Clasen
279a5f7825 Make gdk_dmabuf_downloader_download failable
This will enable us to try multiple downloaders in a row.
2024-09-30 18:37:20 -04:00
Matthias Clasen
6fa87d4f37 gsk renderer: Add a debug message
Add a debug message so we can see what downloaders are used
for dmabufs.
2024-09-30 18:37:20 -04:00
Matthias Clasen
fe35daaf34 Merge branch 'wip/otte/dont-download-the-upload-of-the-download' into 'main'
gpu: Don't use copies for dmabuf downloads

Closes #7046

See merge request GNOME/gtk!7770
2024-09-30 22:30:58 +00:00
Benjamin Otte
c3b836951a gl: ref the previous context
The current context might be the last reference to the context, which
would make it go away when the renderer calls make_current().

See commit 0fa2ae48d4 for a similar case.
2024-09-30 23:54:08 +02:00
Matthias Clasen
ec10f1fe16 gsk: Don't lose context during download
When we use download in the middle of an upload operation (or the
other way around), we may end up making a different GL context
current. The downloader code is reponsible for reestablishing
the previous context when it is done. The old GL renderer was
doing that, NGL wasn't, until now.
2024-09-30 23:49:59 +02:00
Benjamin Otte
ae741a06c0 gpu: Compare fourccs, not GdkMemoryFormat
For dmabufs, the format is not an exact description of the data, it only
gives the closest memory format for a given fourcc.
This of course means that multiple different fourccs may report the same
format.

So when deciding if we need to copy the image to get the right data to
download, we need to check if the fourcc is correct, not if the format
is.

Related: #7046
2024-09-30 22:14:38 +02:00
Benjamin Otte
754c9cb323 gpu: Don't use copies for dmabuf downloads
When we want to download a dmabuf, we want to download the actual
dmabuf.

If we just grab the cached image and use that, we might get the
(reuploaded) copy of the dmabuf. This happens when this renderer
doesn't support downloading this dmabuf but has used it before.

Worse, this is a reentrancy issue, where this renderer is trying to
render the dmabuf and has already scheduled the upload but the upload
has not finished. We will then download from an empty image, which is
very wrong.

The way to check that we have the actual dmabuf is a bit brittle, but it
should work.

Fixes #7046
2024-09-30 19:52:30 +02:00
Benjamin Otte
a3683a080b Merge branch 'wip/otte/global-globals' into 'main'
ngl: Use a single buffer for globals

See merge request GNOME/gtk!7753
2024-09-30 17:09:52 +00:00
Matthias Clasen
0673d74986 Merge branch 'for-main' into 'main'
Cosmetics

See merge request GNOME/gtk!7768
2024-09-30 13:53:51 +00:00
Matthias Clasen
8c46df425e Merge branch 'default-cursor-xdg' into 'main'
wayland: Look for default cursor theme in XDG directories

See merge request GNOME/gtk!7766
2024-09-30 13:27:57 +00:00
Ilya Fedin
ff78e1888b wayland: Look for default cursor theme in XDG directories
Currently it's looked up only in /usr/share what is a problem for non-FHS distros like NixOS
2024-09-30 15:50:11 +04:00
Matthias Clasen
f2f219f304 Cosmetics
Make the debug message match the rest: FORMAT:MODIFIER.
2024-09-30 07:40:48 -04:00
Matthias Clasen
bb46edcc21 dmabuf: Initizalize some memory
I've seen valgrind complain about external_only being uninitialized
after the call, when using llvmpipe. Better be safe than sorry, and
initialize these arrays.
2024-09-30 06:55:57 -04:00
Matthias Clasen
24173e3f93 Cosmetics
No point in having an early return since EGL_NO_IMAGE is what we
want to return anyway.
2024-09-30 06:50:20 -04:00
Anders Jonsson
ec73bcb05b Update Swedish translation
(cherry picked from commit 82f08089f1)
2024-09-29 22:16:13 +00:00
Juliano de Souza Camargo
6c74c9c970 Update Brazilian Portuguese translation
(cherry picked from commit 1610ecbbac)
2024-09-29 16:30:00 +00:00
Matthias Clasen
c9c35ae41d Merge branch 'for-main' into 'main'
testsuite: Don't assert more than guaranteed

See merge request GNOME/gtk!7763
2024-09-29 14:33:35 +00:00
Matthias Clasen
95cea06462 Revamp GDK_VULKAN_DEVICE slightly
Support a "help" value, as we do for other env vars.
2024-09-29 09:54:24 -04:00
Matthias Clasen
d01ca53bde testsuite: Don't assert more than guaranteed
Compositors don't guarantee that there's any physical devices
around to correspond to the input capabilities.

This was found running the tests against mutter headless.
2024-09-29 09:30:56 -04:00
Matthias Clasen
3d3cafefc8 Merge branch 'clear-settings-portal' into 'main'
wayland: Clear settings_portal when going to fallback with no portal settings

See merge request GNOME/gtk!7756
2024-09-29 13:25:15 +00:00
Matthias Clasen
86cdb0ceb2 Merge branch '7040-improve-video-input-stream-error-message' into 'main'
gstmediafile: improve error message when there is an input stream.

Closes #7040

See merge request GNOME/gtk!7747
2024-09-29 13:22:28 +00:00
nee
0c97c86573 gstmediafile: improve error message when there is an input stream.
Previously it was unclear why passing an input stream would crash a video,
unless you went into the source and read it.

This adds a clarifying message that only file based media files are supported.
2024-09-29 13:41:17 +02:00
Benjamin Otte
10fa570195 Merge branch 'wip/otte/for-main' into 'main'
gpu: Consider scissor when intersecting with recangle

Closes #7044

See merge request GNOME/gtk!7762
2024-09-29 04:55:12 +00:00
Benjamin Otte
e18c553457 gpu: Consider scissor when intersecting with recangle
The clip might be different from the scissor due to incompatible
intersections.

But the resulting intersection might be fully clipped, so we should
consider it.

Testsuite with longer explanation attached.

Fixes #7044
2024-09-29 06:29:47 +02:00
Matthias Clasen
187763d286 Merge branch 'for-main' into 'main'
wayland: Bring back the pointer viewporter

See merge request GNOME/gtk!7761
2024-09-29 00:21:36 +00:00
Fran Dieguez
e6ae136de0 Update Galician translation
(cherry picked from commit 8360bfc772)
2024-09-28 21:50:23 +00:00
Matthias Clasen
81efb63073 emojichooser: insert before closing the popover
Doing otherwise risks that the focus is moved back to the entry,
causing everything to be selected, and then replaced by the Emoji
we insert. Which is not the desired effect!
2024-09-28 14:53:12 -04:00
Matthias Clasen
cbadb1ed8e Merge branch 'pointer-viewporter-again' into 'main'
wayland: Bring back the pointer viewporter

See merge request GNOME/gtk!7760
2024-09-28 16:13:06 +00:00
Matthias Clasen
103e98f570 Merge branch 'default-cursor-size' into 'main'
wayland: Use the same default cursor size as gsettings schema

Closes #7043

See merge request GNOME/gtk!7754
2024-09-28 14:32:48 +00:00
Matthias Clasen
3768c751c5 wayland: Improve our cursor size selection
When picking a cursor image size for a given size, look for sizes
that do better when scaled by the viewporter:
- exact size
- twice the size
- closest larger size
- closest size
2024-09-28 10:26:42 -04:00
Matthias Clasen
e42014573a wayland: Bring back the pointer viewporter
This was a thinko in 403da9a2d5. We have the cursor
image in device pixels, but we still need to apply the viewporter
to inform the compositor about the desired pointer size in
application pixels.
2024-09-28 10:01:04 -04:00
Ilya Fedin
a9f1ff471b wayland: Use the same default cursor size as gsettings schema
Fixes: #7043
2024-09-28 16:50:05 +04:00
Ilya Fedin
e26a1bbda9 wayland: Clear settings_portal when going to fallback with no portal settings
All other code paths with goto fallback clear it, this makes the behavior consistent with them
2024-09-28 16:41:13 +04:00
Matthias Clasen
b2ae7a2448 Merge branch 'for-main' into 'main'
Cosmetics

See merge request GNOME/gtk!7751
2024-09-28 01:16:53 +00:00
Matthias Clasen
cb682c759d Cosmetics
No newlines in g_warning.
2024-09-27 20:54:46 -04:00
Benjamin Otte
b154c9caf4 ngL: Use a single buffer for globals
Instead of using glBuffer(Sub)Data() every time we set new globals, fill
a single buffer with all the globals and use glBindBufferRange() on that
buffer to set the current globals.
2024-09-28 02:25:40 +02:00
Matthias Clasen
523fca21e9 Merge branch 'wip/kabus/a11y-present-label' into 'main'
label: Don't set a11y label when role is presentation

See merge request GNOME/gtk!7750
2024-09-27 17:34:39 +00:00
Matthias Clasen
73ddde6eda Merge branch 'cursor-size-again' into 'main'
inspector: Tweak the cursor size control

See merge request GNOME/gtk!7749
2024-09-27 17:29:41 +00:00
Matthias Clasen
403da9a2d5 wayland: Redo cursor loading
Stop using a viewporter to scale cursors. Instead, just pass
the surface scale to the cursor loading code, and take the
buffer dimensions and hotspot that it returns, unchanged.

This avoids problems with cursor themes like Breeze, where
buffer dimensions are different from the nominal cursor size.

Make the cursor loading code take a floating point scale,
and return the closest sized cursor that it can find.
2024-09-27 12:37:25 -04:00
Khalid Abu Shawarib
fb6f211869 label: Don't set a11y label when role is presentation
This resolves issue with labels of model buttons being set to
presentation a11y role but still have a11y label.

See: b7e5a79468/gtk/gtkmodelbutton.c (L1539)
2024-09-27 19:15:41 +03:00
Matthias Clasen
c358606a46 inspector: Tweak the cursor size control
Useful for debugging our cursor loading code.
2024-09-27 12:11:31 -04:00
Matthias Clasen
b7e5a79468 Merge branch 'listbox_tab_behavior' into 'main'
listbox: Introduce tab-behavior property

See merge request GNOME/gtk!7739
2024-09-27 11:42:14 +00:00
Benjamin Otte
06bcb0ee47 Merge branch 'wip/otte/ngl-downloader' into 'main'
Use NGL renderer for dmabuf downloads

See merge request GNOME/gtk!7741
2024-09-26 20:58:01 +00:00
Matthias Clasen
58ce0a39dc dmabuf: Use the ngl downloader
It works, now and is faster than the old GL downloader.

Playing the Barbie trailer @ 4k with hardware decoding but the Cairo
renderer on a 4k screen:

downloader  windowed  fullscreen
GL          12fps     19fps
NGL         16fps     29fps
Vulkan      16fps     29fps
no dmabufs  12fps     19fps
2024-09-26 22:06:18 +02:00
Benjamin Otte
6d3c333208 gpu: Actually ensure a downloadable dmabuf
For some formats, we could not download the dmabuf directly - in
particular YUV formats.
For those, do a copy on the GPU into the correct format.

While we're at it, also check the desired format and colorstate and if
they don't match, do the conversion on the GPU instead of using
gdk_memory_convert().
Reserve the CPU conversion for situations where the GPU doesn't support
the final format - like for example G8A8 (or often also RGB16).
2024-09-26 22:06:18 +02:00
Benjamin Otte
62c3923e5a gpu: Handle all colorstates in cache
Make gsk_gpu_cache_cache_texture_image() API safer by accepting all
color states as input and just not caching the images for colorstates we
don't care about.
2024-09-26 22:06:18 +02:00
Benjamin Otte
3be8b1d927 gpu: Check if the image is cached in right colorstate
This is most likely not a very likely check, but just to be sure, check
if the image exists in the cache in the desired colorstate already.
2024-09-26 22:06:18 +02:00
Benjamin Otte
27a61e221f gpu: Shuffle function arguments
Instead of passing down the depth and extracting format/srgb from it at
the end, extract format/srgb in the nodeprocessor and pass it down.

This allows creating offscreens for weirder formats in the future.
2024-09-26 22:06:18 +02:00
Benjamin Otte
52df3481d6 gpu: Add a gsk_gpu_download_into_op()
... and use it for the dmabuf downloader

Splits the download op into 2 separate ops: One for downloading textures
and one for downloading into preallocated memory.

The download into memory is the fallback for the texture downloading op,
so they need to share code.

But keeping them separate ensures that the different codepaths for
dmabuf download and render_texture() don't get mixed up in weird ways
that potentially call into each other.

By passing the emory down into the op we can also avoid an extra memcpy
which can lead to quite large speedups for big textures.
2024-09-26 22:06:17 +02:00
Benjamin Otte
ccb993d87b gpu: Split out a function
I want to use it from elsewhere in future commits.
2024-09-26 22:06:17 +02:00
Benjamin Otte
5fdaa4a232 gl: Move function
We want to share the texture download function with the renderers, so
they can download textures without needing to wrap them in a
GdkGLTexture.

Move it into gdkglcontext.c for that purpose.
2024-09-26 22:06:17 +02:00
Benjamin Otte
8b166dff74 gltexture: Split out a function
No functional changes
2024-09-26 22:06:17 +02:00
Benjamin Otte
f6b3f321a4 dmabuf: Refactor GPU renderer
We don't want to ever try fallback uploads in the dmabuf path. So
refactor gdk_frame_upload_texture() to have a flag that turns that off.
2024-09-26 22:06:17 +02:00
Benjamin Otte
a314143a83 gpu: Pass color state to download op
Previously we were always implicitly using SRGB, which was correct more
or less by accident.
2024-09-26 22:06:17 +02:00
Benjamin Otte
6c7abf425a Merge branch 'wip/otte/for-main' into 'main'
testsuite: Remove leftover test.in files

See merge request GNOME/gtk!7744
2024-09-26 18:47:49 +00:00
Matthias Clasen
b11e45762b Merge branch 'cursor-update-now' into 'main'
wayland: Make cursor changes effective immediately

Closes #6909

See merge request GNOME/gtk!7745
2024-09-26 18:07:28 +00:00
Benjamin Otte
d041a681a5 Merge branch 'wip/otte/drop-gles2' into 'main'
Drop support for GLES 2 and GL < 3.3

See merge request GNOME/gtk!7743
2024-09-26 17:51:09 +00:00
Matthias Clasen
d22d2f77a6 wayland: Make cursor changes effective immediately
When the cursor theme changes, update the cursors of our surfaces.

Fixes: #6909
2024-09-26 12:53:38 -04:00
Benjamin Otte
7458461d06 gl: Remove unpack-subimage checks
GLES 3.0 supports it unconditionally.
2024-09-26 18:41:13 +02:00
Benjamin Otte
283615936b gl: Remove check for half-float vertex data
All supported versions require it after we dropped support for GLES 2.
2024-09-26 18:41:13 +02:00
Benjamin Otte
2274bca95b gl: Require support for GLsync
It's supported by GL >= 3.2 and GLES >= 3.0 and we require both now.
2024-09-26 18:41:13 +02:00
Benjamin Otte
f8b4deeac0 gdk: Drop support for GL < 3.3
The new renderers need features from GL 3.3 and GLSync is very required
these days, too.

Note that this is about GL proper, not GLES.
2024-09-26 18:41:13 +02:00
Benjamin Otte
afa503c2e0 gl: Remove GLES 2 specific parts of format checks 2024-09-26 18:41:13 +02:00
Benjamin Otte
105f5f1137 gpu: Remove check for GLES 2
GLES 2 is no longer supported.
2024-09-26 18:41:13 +02:00
Benjamin Otte
b83ad60a1f gdk: Drop support for GLES 2
We now require GLES 3.
2024-09-26 18:41:13 +02:00
Benjamin Otte
58b44ebc1c testsuite: Remove GLES 2 tests
We want to drop GLES 2 support.
2024-09-26 18:41:13 +02:00
Benjamin Otte
b598f21506 testsuite: Remove leftover test.in files
We stopped supporting installed tests in 3121f88265 but forgot to remove
these files.
2024-09-26 16:35:47 +00:00
Matthias Clasen
d3c166d511 Merge branch 'for-main' into 'main'
gtk-demo: Stop using g_time_zone_new

See merge request GNOME/gtk!7742
2024-09-26 15:35:06 +00:00
Matthias Clasen
76e93206f3 Stop using G_APPLICATION_FLAGS_NONE
It has been deprecated in favor of G_APPLICATION_DEFAULT_FLAGS.
2024-09-25 22:03:23 -04:00
Matthias Clasen
ecfe47af73 docs: Drop a note about old GLib
We require GLib 2.76 now.
2024-09-25 22:00:38 -04:00
Matthias Clasen
f20ca9067e gtk-demo: Stop using g_time_zone_new
It is deprecated in favor of g_time_zone_new_identifier.
2024-09-25 21:57:49 -04:00
Matthias Clasen
8f3cd4733c Merge branch 'for-main' into 'main'
Stop using g_memdup

See merge request GNOME/gtk!7740
2024-09-26 01:22:23 +00:00
Matthias Clasen
402ee9b39c Tweak the issue template
Ask for more relevant information.
2024-09-26 02:53:54 +02:00
Matthias Clasen
becbf4e1f9 Update the README slightly 2024-09-26 02:53:54 +02:00
Matthias Clasen
67407d5dcf tools: Minor cleanup
No need to register all types here.
2024-09-26 02:53:54 +02:00
Matthias Clasen
fcc0f243cf Stop using g_pattern_match_string
It has been deprecated in favor of g_pattern_spec_match_string.
2024-09-26 02:53:54 +02:00
Matthias Clasen
282dcfa9ac Apply review feedback, mostly formatting. 2024-09-25 11:21:52 +00:00
Matthias Clasen
8c04801f6a Stop using g_memdup
Its deprecated in favor of g_memdup2
2024-09-25 10:56:36 +02:00
Lukáš Tyrychtr
abe2d1cb16 listbox: Introduce tab-behavior property
This is similar to the other tab-behavior properties, and allows
to control how the tabbing behaves in context of a GtkListBox.

It allows to make gnome-initial-setup#216 history, for example.
2024-09-25 10:07:43 +02:00
Benjamin Otte
e407d22b1e Merge branch 'wip/otte/for-main' into 'main'
keynames: Use C types

See merge request GNOME/gtk!7737
2024-09-25 02:07:23 +00:00
Benjamin Otte
37cefde5b0 demo: Unmix argument names 2024-09-25 02:50:22 +02:00
Benjamin Otte
310a4a3bf6 gdk: Fix parameter names
Believe in your self!
2024-09-25 02:50:22 +02:00
Benjamin Otte
e6896aa8dc gpu: Fix argument names 2024-09-25 02:50:22 +02:00
Benjamin Otte
36ce68a3ca textbuffer: includes go before G_BEGIN_DECLS 2024-09-25 02:50:22 +02:00
Benjamin Otte
797343da59 gtkpango: Fix argument names 2024-09-25 02:50:22 +02:00
Benjamin Otte
bd3223d452 testsuite: Add missing headers 2024-09-25 02:50:22 +02:00
Benjamin Otte
87a1a17868 memoryformat: Rename parameter
It's meant to match the prototype.
2024-09-25 02:50:22 +02:00
Benjamin Otte
70f386bd68 keynames: Use C types
Then we don't need to include glib.h
2024-09-25 02:50:22 +02:00
Benjamin Otte
0af89088ba gdk: Include missing header 2024-09-25 02:50:22 +02:00
Benjamin Otte
7342317c31 gdk: Fix parameter names 2024-09-25 02:50:22 +02:00
Benjamin Otte
8d8bd4efba broadway: Fix argument name 2024-09-25 02:50:22 +02:00
Benjamin Otte
0ae3c8968e gdk: Add missing header 2024-09-25 02:50:22 +02:00
Benjamin Otte
5e3f13acd1 filetransferportal: Include missing header 2024-09-25 02:50:22 +02:00
Benjamin Otte
32cdf35583 broadway: Fix argument name 2024-09-25 02:50:22 +02:00
Benjamin Otte
2f670bdc59 demo: Fix typo 2024-09-25 02:50:22 +02:00
Benjamin Otte
8d5660b4ab demo: Fix argument name 2024-09-25 02:50:22 +02:00
Benjamin Otte
2a39f427e1 testsuite: include missing headers 2024-09-25 02:50:22 +02:00
Benjamin Otte
ca86294325 tools: Include missing headers 2024-09-25 02:50:22 +02:00
Benjamin Otte
820ba1ef13 demo: Correct argument name 2024-09-25 02:50:22 +02:00
Benjamin Otte
9507130dbc demo: Unmix argument names 2024-09-25 02:50:22 +02:00
Benjamin Otte
d2dede635b demo: include missing header 2024-09-25 02:50:22 +02:00
Benjamin Otte
5a7fc4054b memoryformat: Fix argument names in prototype 2024-09-25 02:50:22 +02:00
Benjamin Otte
7fe22845e3 Merge branch 'wip/otte/fix-ci' into 'main'
testsuite: Use RGBA8 reference images

See merge request GNOME/gtk!7735
2024-09-24 17:52:55 +00:00
Matthias Clasen
6c9a7cc708 Merge branch 'gtk-find' into 'main'
Add gtk_string_list_find method

See merge request GNOME/gtk!7733
2024-09-24 17:24:10 +00:00
Benjamin Otte
feeca98270 testsuite: Use RGBA8 reference images
Due to a Mesa bug, RGBA16 images aren't properly handled sometimes and
can cause random failures.
In this case, generating the modified reference images for the tests
fails.

Fixes CI breakage.

Related: https://gitlab.freedesktop.org/mesa/mesa/-/issues/11750
2024-09-24 13:57:09 +00:00
taozuhong
7c27241479 Add gtk_string_list_find method
This is a convenience API to find a given string's position.

Test included.
2024-09-24 15:44:04 +02:00
Matthias Clasen
fb73040d70 Merge branch 'for-main' into 'main'
Fix tests for 4.17

See merge request GNOME/gtk!7736
2024-09-24 13:42:25 +00:00
Matthias Clasen
bbe74abf51 Fix tests for 4.17 2024-09-24 14:23:31 +02:00
Matthias Clasen
34bd3fc854 Merge branch 'scale-focus-fix' into 'main'
theme: Fix scale sizing during .fine-tune

See merge request GNOME/gtk!7659
2024-09-24 11:54:21 +00:00
Benjamin Otte
940b5af2a8 Merge branch 'wip/otte/for-main' into 'main'
Revert "dmabuf: Use the ngl downloader"

See merge request GNOME/gtk!7734
2024-09-24 10:05:27 +00:00
Benjamin Otte
0929d77f7f Revert "Fix the ngl downloader"
This reverts commit c7dfb8cb55.
2024-09-24 11:29:59 +02:00
Benjamin Otte
617297ddd7 Revert "gpu: Make gsk_gpu_copy_image available"
This reverts commit 42d26720d6.
2024-09-24 11:29:59 +02:00
Benjamin Otte
67cec180ca Revert "gsk: Make downloaders work fully"
This reverts commit de74fa0836.
2024-09-24 11:29:59 +02:00
Benjamin Otte
bab8f2f976 Revert "dmabuf: Use the ngl downloader"
This reverts commit 97e0f872a2.
2024-09-24 11:29:59 +02:00
Matthias Clasen
4801c3275e Merge branch 'wip/otte/win32-remove-sync' into 'main'
win32: Remove gdk_display_sync()

See merge request GNOME/gtk!7727
2024-09-24 07:03:53 +00:00
Matthias Clasen
39354b3b99 Merge branch 'wip/otte/x11-remove-sync' into 'main'
x11: Remove gdk_display_sync() call

See merge request GNOME/gtk!7728
2024-09-24 07:03:20 +00:00
Matthias Clasen
661e953558 Merge branch 'dmabuf-downloader-investigations' into 'main'
Fix the ngl downloader

See merge request GNOME/gtk!7731
2024-09-24 07:02:09 +00:00
Matthias Clasen
039b97ef9e Start 4.17 2024-09-24 08:42:21 +02:00
Matthias Clasen
97e0f872a2 dmabuf: Use the ngl downloader
It works, now.
2024-09-23 21:14:53 +02:00
Matthias Clasen
de74fa0836 gsk: Make downloaders work fully
Use gsk_gpu_copy_image when necessary to get the image converted
into the right format before downloading it.
2024-09-23 21:14:19 +02:00
Matthias Clasen
42d26720d6 gpu: Make gsk_gpu_copy_image available
This was a static helper in gsknodeprocessor.c, but we want to
use it elsewhere, so make it available.
2024-09-23 21:14:19 +02:00
Matthias Clasen
c7dfb8cb55 Fix the ngl downloader
The image is already associated with the original texture, the
one that the download op creates is purely to hand it to the
downloader, it should not be associated with the image.

This makes the ngl downloader work as well as the vulkan one
(ie rgba dmabufs work, yuv ones don't, since we don't convert
them).
2024-09-23 21:14:08 +02:00
Benjamin Otte
236b6d1cd6 x11: Remove gdk_display_sync() call
This is unnecessary.
Worse, it is reentrant and can cause all sorts of avoc when processing
events halfway through initializing the Vulkan context.

It was introduced in commit e11a6a0e68 but back then GTK was barely
branched for GTK4 and Vulkan drivers were very new, and it looks like an
unnecessary workaround.

Testing did not seem to indicate any issues with just removing it, so
here it goes.

Related: #7022
2024-09-21 18:59:49 +02:00
Benjamin Otte
6e714722c4 win32: Remove gdk_display_sync()
This is unnecessary.
Worse, it is reentrant and causes all sorts of avoc when processing
events halfway through initializing the context.

It only exists because in commit c4244ea1 the win32 Vulkan code was
copy/pasted from another backend.

Related: #7022
2024-09-21 18:19:26 +02:00
Matthijs Velsink
2e2dab9c3d theme: Fix scale sizing during .fine-tune
Using fine-tune on a GtkScale is maybe a little known feature, but it's
also quite wonky. It causes marks, values, and sliders to jump around
when activated. This is because it's implemented with less padding
around the scale and an increased minimum size.

For example a value drawn left or right of a horizontal scale, as then
the height of the scale is the value height plus padding. So fine-tuning
compresses the scale vertically.

We can fix this by adding negative margin on the trough instead, without
any changes to the padding or minimum size of the scale.

Also, because the trough now grows 3px in all directions, the slider has
to do that to, so that margin increases by 3px in all directions
compared to what it was, also for the cases with marks.

One last minor detail is that for vertical scales, fine-tuning causes
the height of the mark indicators to grow, whereas their width should
decrease. That's also fixed.
2024-08-27 22:35:02 +02:00
Matthijs Velsink
a6eea6ba3c theme: Fix positioning of scale values
Commit d58b545f fixed a double counting of value size, but didn't check
whether that actually looked great. It doesn't.

Because the slider has negative margins, we need to add margin to the
value if it's on a side with no marks. If it is on a side with marks,
the scale will make it touch the marks. We therefore apply a mark's size
of margin to have the value be in the same place, with or without marks.
2024-08-27 22:33:54 +02:00
Benjamin Otte
3a8e1c55e1 listitemfactory: Don't rebind on position or selection changes
When the item doesn't change and only the position / selection state,
then the signal list item factory should not emit bind + unbind signals.

This used to work, but probably broke while refactoring for ColumnView
during 4.10.

This caused excessive rebinding when items got inserted at the top of a
list instead of add the end.
2024-07-07 05:38:22 +02:00
267 changed files with 28690 additions and 9561 deletions

View File

@@ -68,7 +68,6 @@ style-check-diff:
- "${CI_PROJECT_DIR}/_build/report-x11.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland_gl.xml"
- "${CI_PROJECT_DIR}/_build/report-wayland_gles2.xml"
- "${CI_PROJECT_DIR}/_build/report-broadway.xml"
name: "gtk-${CI_COMMIT_REF_NAME}"
paths:
@@ -119,8 +118,9 @@ release-build:
script:
- .gitlab-ci/show-info-linux.sh
- mkdir _install
- export PATH="$HOME/.local/bin:${CI_PROJECT_DIR}/_install/bin:$PATH"
- .gitlab-ci/install-meson-project.sh --prefix ${CI_PROJECT_DIR}/_install https://gitlab.gnome.org/jadahl/catch.git main
# don't use catch by default, since it causes sporadic test failures
# - export PATH="$HOME/.local/bin:${CI_PROJECT_DIR}/_install/bin:$PATH"
# - .gitlab-ci/install-meson-project.sh --prefix ${CI_PROJECT_DIR}/_install https://gitlab.gnome.org/jadahl/catch.git main
- meson subprojects download
- meson subprojects update --reset
- meson setup
@@ -135,8 +135,6 @@ release-build:
- PKG_CONFIG_PATH=${CI_PROJECT_DIR}/_install/lib64/pkgconfig:${CI_PROJECT_DIR}/_install/share/pkgconfig meson setup _build_hello examples/hello
- LD_LIBRARY_PATH=${CI_PROJECT_DIR}/_install/lib64 meson compile -C _build_hello
- .gitlab-ci/run-tests.sh _build wayland gtk
# only repeat test runs that are likely affected by test setups
- .gitlab-ci/run-tests.sh _build wayland_gles2 gtk:gdk,gtk:gsk-gl
fedora-clang:
extends: .build-fedora-default
@@ -200,11 +198,11 @@ fedora-mingw64:
- subprojects/libepoxy/
- subprojects/pango/
msys2-mingw64:
msys2-ucrt64:
extends: .mingw-defaults
needs: []
variables:
MSYSTEM: "MINGW64"
MSYSTEM: "UCRT64"
CHERE_INVOKING: "yes"
artifacts:
when: always

View File

@@ -2,12 +2,6 @@
set -e
if [[ "$MSYSTEM" == "MINGW32" ]]; then
export MSYS2_ARCH="i686"
else
export MSYS2_ARCH="x86_64"
fi
# Update everything
pacman --noconfirm -Suy
@@ -15,27 +9,27 @@ pacman --noconfirm -Suy
pacman --noconfirm -S --needed \
base-devel \
git \
mingw-w64-$MSYS2_ARCH-cc \
mingw-w64-$MSYS2_ARCH-ccache \
mingw-w64-$MSYS2_ARCH-pkgconf \
mingw-w64-$MSYS2_ARCH-gobject-introspection \
mingw-w64-$MSYS2_ARCH-meson \
mingw-w64-$MSYS2_ARCH-adwaita-icon-theme \
mingw-w64-$MSYS2_ARCH-atk \
mingw-w64-$MSYS2_ARCH-cairo \
mingw-w64-$MSYS2_ARCH-gdk-pixbuf2 \
mingw-w64-$MSYS2_ARCH-glib2 \
mingw-w64-$MSYS2_ARCH-graphene \
mingw-w64-$MSYS2_ARCH-json-glib \
mingw-w64-$MSYS2_ARCH-libepoxy \
mingw-w64-$MSYS2_ARCH-pango \
mingw-w64-$MSYS2_ARCH-fribidi \
mingw-w64-$MSYS2_ARCH-gst-plugins-bad-libs \
mingw-w64-$MSYS2_ARCH-shared-mime-info \
mingw-w64-$MSYS2_ARCH-python-gobject \
mingw-w64-$MSYS2_ARCH-shaderc \
mingw-w64-$MSYS2_ARCH-vulkan \
mingw-w64-$MSYS2_ARCH-vulkan-headers
${MINGW_PACKAGE_PREFIX}-cc \
${MINGW_PACKAGE_PREFIX}-ccache \
${MINGW_PACKAGE_PREFIX}-pkgconf \
${MINGW_PACKAGE_PREFIX}-gobject-introspection \
${MINGW_PACKAGE_PREFIX}-meson \
${MINGW_PACKAGE_PREFIX}-adwaita-icon-theme \
${MINGW_PACKAGE_PREFIX}-atk \
${MINGW_PACKAGE_PREFIX}-cairo \
${MINGW_PACKAGE_PREFIX}-gdk-pixbuf2 \
${MINGW_PACKAGE_PREFIX}-glib2 \
${MINGW_PACKAGE_PREFIX}-graphene \
${MINGW_PACKAGE_PREFIX}-json-glib \
${MINGW_PACKAGE_PREFIX}-libepoxy \
${MINGW_PACKAGE_PREFIX}-pango \
${MINGW_PACKAGE_PREFIX}-fribidi \
${MINGW_PACKAGE_PREFIX}-gst-plugins-bad-libs \
${MINGW_PACKAGE_PREFIX}-shared-mime-info \
${MINGW_PACKAGE_PREFIX}-python-gobject \
${MINGW_PACKAGE_PREFIX}-shaderc \
${MINGW_PACKAGE_PREFIX}-vulkan \
${MINGW_PACKAGE_PREFIX}-vulkan-headers
mkdir -p _ccache
export CCACHE_BASEDIR="$(pwd)"

View File

@@ -34,7 +34,9 @@
<!--
- Which version of GTK you are using
- What operating system and version
- For Linux, which distribution
- What windowing system (X11 or Wayland)
- What graphics driver / mesa version
- For Linux, which distribution
- If you built GTK yourself, the list of options used to configure the build
-->

2
NEWS
View File

@@ -1,4 +1,4 @@
Overview of Changes in 4.16.3, xx-xx-xxxx
Overview of Changes in 4.17.0, xx-xx-xxxx
=========================================

View File

@@ -136,9 +136,13 @@ In the bug report please include:
- which version of GTK you are using
- what operating system and version
- what windowing system (X11 or Wayland)
- what graphics driver / mesa version
- for Linux, which distribution
- if you built GTK, the list of options used to configure the build
Most of this information can be found in the GTK inspector.
And anything else you think is relevant.
* How to reproduce the bug.

View File

@@ -1,115 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "config.h"
#include "constraint-editor-application.h"
#include "constraint-editor-window.h"
struct _ConstraintEditorApplication
{
GtkApplication parent_instance;
};
G_DEFINE_TYPE(ConstraintEditorApplication, constraint_editor_application, GTK_TYPE_APPLICATION);
static void
constraint_editor_application_init (ConstraintEditorApplication *app)
{
}
static void
quit_activated (GSimpleAction *action,
GVariant *parameter,
gpointer data)
{
g_application_quit (G_APPLICATION (data));
}
static GActionEntry app_entries[] =
{
{ "quit", quit_activated, NULL, NULL, NULL }
};
static void
constraint_editor_application_startup (GApplication *app)
{
const char *quit_accels[2] = { "<Ctrl>Q", NULL };
const char *open_accels[2] = { "<Ctrl>O", NULL };
GtkCssProvider *provider;
G_APPLICATION_CLASS (constraint_editor_application_parent_class)->startup (app);
g_action_map_add_action_entries (G_ACTION_MAP (app),
app_entries, G_N_ELEMENTS (app_entries),
app);
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "app.quit", quit_accels);
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "win.open", open_accels);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/org/gtk/gtk4/constraint-editor/constraint-editor.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
static void
constraint_editor_application_activate (GApplication *app)
{
ConstraintEditorWindow *win;
win = constraint_editor_window_new (CONSTRAINT_EDITOR_APPLICATION (app));
gtk_window_present (GTK_WINDOW (win));
}
static void
constraint_editor_application_open (GApplication *app,
GFile **files,
int n_files,
const char *hint)
{
ConstraintEditorWindow *win;
int i;
for (i = 0; i < n_files; i++)
{
win = constraint_editor_window_new (CONSTRAINT_EDITOR_APPLICATION (app));
constraint_editor_window_load (win, files[i]);
gtk_window_present (GTK_WINDOW (win));
}
}
static void
constraint_editor_application_class_init (ConstraintEditorApplicationClass *class)
{
GApplicationClass *application_class = G_APPLICATION_CLASS (class);
application_class->startup = constraint_editor_application_startup;
application_class->activate = constraint_editor_application_activate;
application_class->open = constraint_editor_application_open;
}
ConstraintEditorApplication *
constraint_editor_application_new (void)
{
return g_object_new (CONSTRAINT_EDITOR_APPLICATION_TYPE,
"application-id", "org.gtk.gtk4.ConstraintEditor",
"flags", G_APPLICATION_HANDLES_OPEN,
NULL);
}

View File

@@ -1,28 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define CONSTRAINT_EDITOR_APPLICATION_TYPE (constraint_editor_application_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintEditorApplication, constraint_editor_application, CONSTRAINT, EDITOR_APPLICATION, GtkApplication)
ConstraintEditorApplication *constraint_editor_application_new (void);

View File

@@ -1,652 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "config.h"
#include "constraint-editor-window.h"
#include "constraint-view.h"
#include "constraint-editor.h"
#include "guide-editor.h"
struct _ConstraintEditorWindow
{
GtkApplicationWindow parent_instance;
GtkWidget *paned;
GtkWidget *view;
GtkWidget *list;
};
G_DEFINE_TYPE(ConstraintEditorWindow, constraint_editor_window, GTK_TYPE_APPLICATION_WINDOW);
static GtkConstraintTarget *
find_target (GListModel *model,
GtkConstraintTarget *orig)
{
const char *name;
const char *model_name;
gpointer item;
int i;
if (orig == NULL)
return NULL;
if (GTK_IS_LABEL (orig))
name = gtk_label_get_label (GTK_LABEL (orig));
else if (GTK_IS_CONSTRAINT_GUIDE (orig))
name = gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (orig));
else
{
g_warning ("Don't know how to handle %s targets", G_OBJECT_TYPE_NAME (orig));
return NULL;
}
for (i = 0; i < g_list_model_get_n_items (model); i++)
{
item = g_list_model_get_item (model, i);
g_object_unref (item);
if (GTK_IS_WIDGET (item))
model_name = gtk_widget_get_name (GTK_WIDGET (item));
else
model_name = gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (item));
if (strcmp (name, model_name) == 0)
return GTK_CONSTRAINT_TARGET (item);
}
g_warning ("Failed to find target '%s'", name);
return NULL;
}
gboolean
constraint_editor_window_load (ConstraintEditorWindow *self,
GFile *file)
{
char *path;
GtkBuilder *builder;
GError *error = NULL;
GtkWidget *view;
GtkLayoutManager *layout;
GtkWidget *child;
const char *name;
gpointer item;
int i;
GListModel *list;
path = g_file_get_path (file);
builder = gtk_builder_new ();
if (!gtk_builder_add_from_file (builder, path, &error))
{
g_print ("Could not load %s: %s", path, error->message);
g_error_free (error);
g_free (path);
g_object_unref (builder);
return FALSE;
}
view = GTK_WIDGET (gtk_builder_get_object (builder, "view"));
if (!GTK_IS_BOX (view))
{
g_print ("Could not load %s: No GtkBox named 'view'", path);
g_free (path);
g_object_unref (builder);
return FALSE;
}
layout = gtk_widget_get_layout_manager (view);
if (!GTK_IS_CONSTRAINT_LAYOUT (layout))
{
g_print ("Could not load %s: Widget 'view' does not use GtkConstraintLayout", path);
g_free (path);
g_object_unref (builder);
return FALSE;
}
for (child = gtk_widget_get_first_child (view);
child;
child = gtk_widget_get_next_sibling (child))
{
if (!GTK_IS_LABEL (child))
{
g_print ("Skipping non-GtkLabel child\n");
continue;
}
name = gtk_label_get_label (GTK_LABEL (child));
constraint_view_add_child (CONSTRAINT_VIEW (self->view), name);
}
list = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (layout));
for (i = 0; i < g_list_model_get_n_items (list); i++)
{
GtkConstraintGuide *guide, *clone;
int w, h;
item = g_list_model_get_item (list, i);
guide = GTK_CONSTRAINT_GUIDE (item);
/* need to clone here, to attach to the right targets */
clone = gtk_constraint_guide_new ();
gtk_constraint_guide_set_name (clone, gtk_constraint_guide_get_name (guide));
gtk_constraint_guide_set_strength (clone, gtk_constraint_guide_get_strength (guide));
gtk_constraint_guide_get_min_size (guide, &w, &h);
gtk_constraint_guide_set_min_size (clone, w, h);
gtk_constraint_guide_get_nat_size (guide, &w, &h);
gtk_constraint_guide_set_nat_size (clone, w, h);
gtk_constraint_guide_get_max_size (guide, &w, &h);
gtk_constraint_guide_set_max_size (clone, w, h);
constraint_view_add_guide (CONSTRAINT_VIEW (self->view), clone);
g_object_unref (guide);
g_object_unref (clone);
}
g_object_unref (list);
list = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (layout));
for (i = 0; i < g_list_model_get_n_items (list); i++)
{
GtkConstraint *constraint;
GtkConstraint *clone;
GtkConstraintTarget *target;
GtkConstraintTarget *source;
GtkConstraintAttribute source_attr;
item = g_list_model_get_item (list, i);
constraint = GTK_CONSTRAINT (item);
target = gtk_constraint_get_target (constraint);
source = gtk_constraint_get_source (constraint);
source_attr = gtk_constraint_get_source_attribute (constraint);
if (source == NULL && source_attr == GTK_CONSTRAINT_ATTRIBUTE_NONE)
clone = gtk_constraint_new_constant (find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), target),
gtk_constraint_get_target_attribute (constraint),
gtk_constraint_get_relation (constraint),
gtk_constraint_get_constant (constraint),
gtk_constraint_get_strength (constraint));
else
clone = gtk_constraint_new (find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), target),
gtk_constraint_get_target_attribute (constraint),
gtk_constraint_get_relation (constraint),
find_target (constraint_view_get_model (CONSTRAINT_VIEW (self->view)), source),
source_attr,
gtk_constraint_get_multiplier (constraint),
gtk_constraint_get_constant (constraint),
gtk_constraint_get_strength (constraint));
constraint_view_add_constraint (CONSTRAINT_VIEW (self->view), clone);
g_object_unref (constraint);
g_object_unref (clone);
}
g_object_unref (list);
g_free (path);
g_object_unref (builder);
return TRUE;
}
static void
open_response_cb (GObject *source,
GAsyncResult *result,
void *user_data)
{
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
ConstraintEditorWindow *self = user_data;
GFile *file;
file = gtk_file_dialog_open_finish (dialog, result, NULL);
if (file)
{
constraint_editor_window_load (self, file);
g_object_unref (file);
}
}
static void
open_cb (GtkWidget *button,
ConstraintEditorWindow *self)
{
GtkFileDialog *dialog;
GFile *cwd;
dialog = gtk_file_dialog_new ();
gtk_file_dialog_set_title (dialog, "Open file");
cwd = g_file_new_for_path (".");
gtk_file_dialog_set_initial_folder (dialog, cwd);
g_object_unref (cwd);
gtk_file_dialog_open (dialog, GTK_WINDOW (self), NULL, open_response_cb, self);
g_object_unref (dialog);
}
static void
serialize_child (GString *str,
int indent,
GtkWidget *child)
{
const char *name;
name = gtk_widget_get_name (child);
g_string_append_printf (str, "%*s<child>\n", indent, "");
g_string_append_printf (str, "%*s <object class=\"GtkLabel\" id=\"%s\">\n", indent, "", name);
g_string_append_printf (str, "%*s <property name=\"label\">%s</property>\n", indent, "", name);
g_string_append_printf (str, "%*s </object>\n", indent, "");
g_string_append_printf (str, "%*s</child>\n", indent, "");
}
static char *
serialize_model (GListModel *list)
{
GString *str = g_string_new ("");
int i;
g_string_append (str, "<interface>\n");
g_string_append (str, " <object class=\"GtkBox\" id=\"view\">\n");
g_string_append (str, " <property name=\"layout-manager\">\n");
g_string_append (str, " <object class=\"GtkConstraintLayout\">\n");
g_string_append (str, " <constraints>\n");
for (i = 0; i < g_list_model_get_n_items (list); i++)
{
gpointer item = g_list_model_get_item (list, i);
g_object_unref (item);
if (GTK_IS_CONSTRAINT (item))
constraint_editor_serialize_constraint (str, 10, GTK_CONSTRAINT (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
guide_editor_serialize_guide (str, 10, GTK_CONSTRAINT_GUIDE (item));
}
g_string_append (str, " </constraints>\n");
g_string_append (str, " </object>\n");
g_string_append (str, " </property>\n");
for (i = 0; i < g_list_model_get_n_items (list); i++)
{
gpointer item = g_list_model_get_item (list, i);
g_object_unref (item);
if (GTK_IS_WIDGET (item))
serialize_child (str, 4, GTK_WIDGET (item));
}
g_string_append (str, " </object>\n");
g_string_append (str, "</interface>\n");
return g_string_free (str, FALSE);
}
static void
save_response_cb (GObject *source,
GAsyncResult *result,
void *user_data)
{
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
ConstraintEditorWindow *self = user_data;
GFile *file;
file = gtk_file_dialog_save_finish (dialog, result, NULL);
if (file)
{
GListModel *model;
char *text;
GError *error = NULL;
model = constraint_view_get_model (CONSTRAINT_VIEW (self->view));
text = serialize_model (model);
g_file_replace_contents (file, text, strlen (text),
NULL, FALSE,
G_FILE_CREATE_NONE,
NULL,
NULL,
&error);
if (error != NULL)
{
GtkAlertDialog *alert;
alert = gtk_alert_dialog_new ("Saving failed");
gtk_alert_dialog_set_detail (alert, error->message);
gtk_alert_dialog_show (alert,
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))));
g_object_unref (alert);
g_error_free (error);
}
g_free (text);
g_object_unref (file);
}
}
static void
save_cb (GtkWidget *button,
ConstraintEditorWindow *self)
{
GtkFileDialog *dialog;
GFile *cwd;
dialog = gtk_file_dialog_new ();
gtk_file_dialog_set_title (dialog, "Save constraints");
cwd = g_file_new_for_path (".");
gtk_file_dialog_set_initial_folder (dialog, cwd);
g_object_unref (cwd);
gtk_file_dialog_save (dialog,
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
NULL,
save_response_cb, self);
g_object_unref (dialog);
}
static void
constraint_editor_window_dispose (GObject *object)
{
gtk_widget_dispose_template (GTK_WIDGET (object), CONSTRAINT_EDITOR_WINDOW_TYPE);
G_OBJECT_CLASS (constraint_editor_window_parent_class)->dispose (object);
}
static int child_counter;
static int guide_counter;
static void
add_child (ConstraintEditorWindow *win)
{
char *name;
child_counter++;
name = g_strdup_printf ("Child %d", child_counter);
constraint_view_add_child (CONSTRAINT_VIEW (win->view), name);
g_free (name);
}
static void
add_guide (ConstraintEditorWindow *win)
{
char *name;
GtkConstraintGuide *guide;
guide_counter++;
name = g_strdup_printf ("Guide %d", guide_counter);
guide = gtk_constraint_guide_new ();
gtk_constraint_guide_set_name (guide, name);
g_free (name);
constraint_view_add_guide (CONSTRAINT_VIEW (win->view), guide);
}
static void
constraint_editor_done (ConstraintEditor *editor,
GtkConstraint *constraint,
ConstraintEditorWindow *win)
{
GtkConstraint *old_constraint;
g_object_get (editor, "constraint", &old_constraint, NULL);
if (old_constraint)
constraint_view_remove_constraint (CONSTRAINT_VIEW (win->view), old_constraint);
constraint_view_add_constraint (CONSTRAINT_VIEW (win->view), constraint);
g_clear_object (&old_constraint);
gtk_window_destroy (GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW)));
}
static void
edit_constraint (ConstraintEditorWindow *win,
GtkConstraint *constraint)
{
GtkWidget *window;
ConstraintEditor *editor;
GListModel *model;
window = gtk_window_new ();
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
if (constraint)
gtk_window_set_title (GTK_WINDOW (window), "Edit Constraint");
else
gtk_window_set_title (GTK_WINDOW (window), "Create Constraint");
model = constraint_view_get_model (CONSTRAINT_VIEW (win->view));
editor = constraint_editor_new (model, constraint);
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (editor));
g_signal_connect (editor, "done", G_CALLBACK (constraint_editor_done), win);
gtk_window_present (GTK_WINDOW (window));
}
static void
add_constraint (ConstraintEditorWindow *win)
{
edit_constraint (win, NULL);
}
static void
guide_editor_done (GuideEditor *editor,
GtkConstraintGuide *guide,
ConstraintEditorWindow *win)
{
gtk_window_destroy (GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW)));
}
static void
edit_guide (ConstraintEditorWindow *win,
GtkConstraintGuide *guide)
{
GtkWidget *window;
GuideEditor *editor;
window = gtk_window_new ();
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_window_set_transient_for (GTK_WINDOW (window), GTK_WINDOW (win));
gtk_window_set_title (GTK_WINDOW (window), "Edit Guide");
editor = guide_editor_new (guide);
gtk_window_set_child (GTK_WINDOW (window), GTK_WIDGET (editor));
g_signal_connect (editor, "done", G_CALLBACK (guide_editor_done), win);
gtk_window_present (GTK_WINDOW (window));
}
static void
row_activated (GtkListBox *list,
GtkListBoxRow *row,
ConstraintEditorWindow *win)
{
GObject *item;
item = G_OBJECT (g_object_get_data (G_OBJECT (row), "item"));
if (GTK_IS_CONSTRAINT (item))
edit_constraint (win, GTK_CONSTRAINT (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
edit_guide (win, GTK_CONSTRAINT_GUIDE (item));
}
static void
constraint_editor_window_class_init (ConstraintEditorWindowClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
g_type_ensure (CONSTRAINT_VIEW_TYPE);
object_class->dispose = constraint_editor_window_dispose;
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/gtk4/constraint-editor/constraint-editor-window.ui");
gtk_widget_class_bind_template_child (widget_class, ConstraintEditorWindow, paned);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditorWindow, view);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditorWindow, list);
gtk_widget_class_bind_template_callback (widget_class, open_cb);
gtk_widget_class_bind_template_callback (widget_class, save_cb);
gtk_widget_class_bind_template_callback (widget_class, add_child);
gtk_widget_class_bind_template_callback (widget_class, add_guide);
gtk_widget_class_bind_template_callback (widget_class, add_constraint);
gtk_widget_class_bind_template_callback (widget_class, row_activated);
}
static void
row_edit (GtkButton *button,
ConstraintEditorWindow *win)
{
GtkWidget *row;
GObject *item;
row = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_LIST_BOX_ROW);
item = (GObject *)g_object_get_data (G_OBJECT (row), "item");
if (GTK_IS_CONSTRAINT (item))
edit_constraint (win, GTK_CONSTRAINT (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
edit_guide (win, GTK_CONSTRAINT_GUIDE (item));
}
static void
mark_constraints_invalid (ConstraintEditorWindow *win,
gpointer removed)
{
GtkWidget *child;
GObject *item;
for (child = gtk_widget_get_first_child (win->list);
child;
child = gtk_widget_get_next_sibling (child))
{
item = (GObject *)g_object_get_data (G_OBJECT (child), "item");
if (GTK_IS_CONSTRAINT (item))
{
GtkConstraint *constraint = GTK_CONSTRAINT (item);
if (gtk_constraint_get_target (constraint) == (GtkConstraintTarget *)removed ||
gtk_constraint_get_source (constraint) == (GtkConstraintTarget *)removed)
{
GtkWidget *button;
button = (GtkWidget *)g_object_get_data (G_OBJECT (child), "edit");
gtk_button_set_icon_name (GTK_BUTTON (button), "dialog-warning-symbolic");
gtk_widget_set_tooltip_text (button, "Constraint is invalid");
}
}
}
}
static void
row_delete (GtkButton *button,
ConstraintEditorWindow *win)
{
GtkWidget *row;
GObject *item;
row = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_LIST_BOX_ROW);
item = (GObject *)g_object_get_data (G_OBJECT (row), "item");
if (GTK_IS_CONSTRAINT (item))
constraint_view_remove_constraint (CONSTRAINT_VIEW (win->view),
GTK_CONSTRAINT (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
{
mark_constraints_invalid (win, item);
constraint_view_remove_guide (CONSTRAINT_VIEW (win->view),
GTK_CONSTRAINT_GUIDE (item));
}
else if (GTK_IS_WIDGET (item))
{
mark_constraints_invalid (win, item);
constraint_view_remove_child (CONSTRAINT_VIEW (win->view),
GTK_WIDGET (item));
}
}
static GtkWidget *
create_widget_func (gpointer item,
gpointer user_data)
{
ConstraintEditorWindow *win = user_data;
const char *name;
char *freeme = NULL;
GtkWidget *row, *box, *label, *button;
if (GTK_IS_WIDGET (item))
name = gtk_widget_get_name (GTK_WIDGET (item));
else if (GTK_IS_CONSTRAINT_GUIDE (item))
name = gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (item));
else if (GTK_IS_CONSTRAINT (item))
name = freeme = constraint_editor_constraint_to_string (GTK_CONSTRAINT (item));
else
name = "";
row = gtk_list_box_row_new ();
g_object_set_data_full (G_OBJECT (row), "item", g_object_ref (item), g_object_unref);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
label = gtk_label_new (name);
if (GTK_IS_WIDGET (item) || GTK_IS_CONSTRAINT_GUIDE (item))
g_object_bind_property (item, "name",
label, "label",
G_BINDING_DEFAULT);
gtk_widget_set_margin_start (label, 10);
gtk_widget_set_margin_end (label, 10);
gtk_widget_set_margin_top (label, 10);
gtk_widget_set_margin_bottom (label, 10);
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_widget_set_hexpand (label, TRUE);
gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), box);
gtk_box_append (GTK_BOX (box), label);
if (GTK_IS_CONSTRAINT (item) || GTK_IS_CONSTRAINT_GUIDE (item))
{
button = gtk_button_new_from_icon_name ("document-edit-symbolic");
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
g_signal_connect (button, "clicked", G_CALLBACK (row_edit), win);
g_object_set_data (G_OBJECT (row), "edit", button);
gtk_box_append (GTK_BOX (box), button);
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
gtk_box_append (GTK_BOX (box), button);
}
else if (GTK_IS_WIDGET (item))
{
button = gtk_button_new_from_icon_name ("edit-delete-symbolic");
gtk_button_set_has_frame (GTK_BUTTON (button), FALSE);
g_signal_connect (button, "clicked", G_CALLBACK (row_delete), win);
gtk_box_append (GTK_BOX (box), button);
}
g_free (freeme);
return row;
}
static void
constraint_editor_window_init (ConstraintEditorWindow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
gtk_list_box_bind_model (GTK_LIST_BOX (self->list),
constraint_view_get_model (CONSTRAINT_VIEW (self->view)),
create_widget_func,
self,
NULL);
}
ConstraintEditorWindow *
constraint_editor_window_new (ConstraintEditorApplication *application)
{
return g_object_new (CONSTRAINT_EDITOR_WINDOW_TYPE,
"application", application,
NULL);
}

View File

@@ -1,34 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#include "constraint-editor-application.h"
#define CONSTRAINT_EDITOR_WINDOW_TYPE (constraint_editor_window_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintEditorWindow, constraint_editor_window, CONSTRAINT, EDITOR_WINDOW, GtkApplicationWindow)
ConstraintEditorWindow * constraint_editor_window_new (ConstraintEditorApplication *application);
gboolean constraint_editor_window_load (ConstraintEditorWindow *self,
GFile *file);

View File

@@ -1,77 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ConstraintEditorWindow" parent="GtkApplicationWindow">
<property name="title" translatable="yes">GTK Constraint Editor</property>
<property name="default-width">1024</property>
<property name="default-height">768</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<child type="start">
<object class="GtkButton">
<property name="icon-name">document-open-symbolic</property>
<property name="tooltip-text">Open ui file</property>
<signal name="clicked" handler="open_cb"/>
</object>
</child>
<child type="start">
<object class="GtkButton">
<property name="icon-name">document-save-symbolic</property>
<property name="tooltip-text">Save to ui file</property>
<signal name="clicked" handler="save_cb"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkPaned" id="paned">
<property name="orientation">horizontal</property>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<child>
<object class="GtkButton">
<property name="label">Add Child</property>
<signal name="clicked" handler="add_child" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label">Add Guide</property>
<signal name="clicked" handler="add_guide" swapped="yes"/>
</object>
</child>
<child>
<object class="GtkButton">
<property name="label">Add Constraint</property>
<signal name="clicked" handler="add_constraint" swapped="yes"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<property name="vscrollbar-policy">automatic</property>
<property name="vexpand">1</property>
<child>
<object class="GtkListBox" id="list">
<property name="show-separators">1</property>
<property name="selection-mode">none</property>
<signal name="row-activated" handler="row_activated"/>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="ConstraintView" id="view">
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,716 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "config.h"
#include "constraint-editor.h"
#include "constraint-view.h"
struct _ConstraintEditor
{
GtkWidget parent_instance;
GtkWidget *grid;
GtkWidget *target;
GtkWidget *target_attr;
GtkWidget *relation;
GtkWidget *source;
GtkWidget *source_attr;
GtkWidget *multiplier;
GtkWidget *constant;
GtkWidget *strength;
GtkWidget *preview;
GtkWidget *button;
GtkConstraint *constraint;
GListModel *model;
gboolean constructed;
};
enum {
PROP_MODEL = 1,
PROP_CONSTRAINT,
LAST_PROP
};
static GParamSpec *pspecs[LAST_PROP];
enum {
DONE,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE(ConstraintEditor, constraint_editor, GTK_TYPE_WIDGET);
static const char *
get_target_name (GtkConstraintTarget *target)
{
if (target == NULL)
return "Super";
else if (GTK_IS_WIDGET (target))
return gtk_widget_get_name (GTK_WIDGET (target));
else if (GTK_IS_CONSTRAINT_GUIDE (target))
return gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (target));
else
return "";
}
static void
constraint_target_combo (GListModel *model,
GtkWidget *combo,
gboolean is_source)
{
GtkStringList *targets;
int i;
targets = gtk_string_list_new (NULL);
gtk_string_list_append (targets, "Super");
if (model)
{
for (i = 0; i < g_list_model_get_n_items (model); i++)
{
GObject *item = g_list_model_get_object (model, i);
if (GTK_IS_CONSTRAINT (item))
continue;
gtk_string_list_append (targets, get_target_name (GTK_CONSTRAINT_TARGET (item)));
g_object_unref (item);
}
}
gtk_drop_down_set_model (GTK_DROP_DOWN (combo), G_LIST_MODEL (targets));
g_object_unref (targets);
}
static gpointer
get_target (GListModel *model,
const char *id)
{
int i;
if (id == NULL)
return NULL;
if (strcmp ("Super", id) == 0)
return NULL;
for (i = 0; i < g_list_model_get_n_items (model); i++)
{
GObject *item = g_list_model_get_object (model, i);
g_object_unref (item);
if (GTK_IS_CONSTRAINT (item))
continue;
else if (GTK_IS_WIDGET (item))
{
if (strcmp (id, gtk_widget_get_name (GTK_WIDGET (item))) == 0)
return item;
}
else if (GTK_IS_CONSTRAINT_GUIDE (item))
{
if (strcmp (id, gtk_constraint_guide_get_name (GTK_CONSTRAINT_GUIDE (item))) == 0)
return item;
}
}
return NULL;
}
static void
select_target (GtkDropDown *combo,
const char *target_name)
{
GListModel *model = gtk_drop_down_get_model (combo);
for (unsigned int i = 0; i < g_list_model_get_n_items (model); i++)
{
GtkStringObject *s = g_list_model_get_item (model, i);
g_object_unref (s);
if (strcmp (target_name, gtk_string_object_get_string (s)) == 0)
{
gtk_drop_down_set_selected (GTK_DROP_DOWN (combo), i);
return;
}
}
}
static GtkConstraintAttribute
get_attr (unsigned int id)
{
switch (id)
{
case 0: return GTK_CONSTRAINT_ATTRIBUTE_NONE;
case 1: return GTK_CONSTRAINT_ATTRIBUTE_LEFT;
case 2: return GTK_CONSTRAINT_ATTRIBUTE_RIGHT;
case 3: return GTK_CONSTRAINT_ATTRIBUTE_TOP;
case 4: return GTK_CONSTRAINT_ATTRIBUTE_BOTTOM;
case 5: return GTK_CONSTRAINT_ATTRIBUTE_START;
case 6: return GTK_CONSTRAINT_ATTRIBUTE_END;
case 7: return GTK_CONSTRAINT_ATTRIBUTE_WIDTH;
case 8: return GTK_CONSTRAINT_ATTRIBUTE_HEIGHT;
case 9: return GTK_CONSTRAINT_ATTRIBUTE_CENTER_X;
case 10: return GTK_CONSTRAINT_ATTRIBUTE_CENTER_Y;
case 11: return GTK_CONSTRAINT_ATTRIBUTE_BASELINE;
default: g_assert_not_reached ();
}
}
static unsigned int
get_attr_id (GtkConstraintAttribute attr)
{
switch (attr)
{
case GTK_CONSTRAINT_ATTRIBUTE_NONE: return 0;
case GTK_CONSTRAINT_ATTRIBUTE_LEFT: return 1;
case GTK_CONSTRAINT_ATTRIBUTE_RIGHT: return 2;
case GTK_CONSTRAINT_ATTRIBUTE_TOP: return 3;
case GTK_CONSTRAINT_ATTRIBUTE_BOTTOM: return 4;
case GTK_CONSTRAINT_ATTRIBUTE_START: return 5;
case GTK_CONSTRAINT_ATTRIBUTE_END: return 6;
case GTK_CONSTRAINT_ATTRIBUTE_WIDTH: return 7;
case GTK_CONSTRAINT_ATTRIBUTE_HEIGHT: return 8;
case GTK_CONSTRAINT_ATTRIBUTE_CENTER_X: return 9;
case GTK_CONSTRAINT_ATTRIBUTE_CENTER_Y: return 10;
case GTK_CONSTRAINT_ATTRIBUTE_BASELINE: return 11;
default: g_assert_not_reached ();
}
}
static const char *
get_attr_nick (GtkConstraintAttribute attr)
{
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_ATTRIBUTE);
GEnumValue *value = g_enum_get_value (class, attr);
const char *nick = value->value_nick;
g_type_class_unref (class);
return nick;
}
static GtkConstraintRelation
get_relation (unsigned int id)
{
switch (id)
{
case 0: return GTK_CONSTRAINT_RELATION_LE;
case 1: return GTK_CONSTRAINT_RELATION_EQ;
case 2: return GTK_CONSTRAINT_RELATION_GE;
default: g_assert_not_reached ();
}
}
static unsigned int
get_relation_id (GtkConstraintRelation relation)
{
switch (relation)
{
case GTK_CONSTRAINT_RELATION_LE: return 0;
case GTK_CONSTRAINT_RELATION_EQ: return 1;
case GTK_CONSTRAINT_RELATION_GE: return 2;
default: g_assert_not_reached ();
}
}
static const char *
get_relation_nick (GtkConstraintRelation relation)
{
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_RELATION);
GEnumValue *value = g_enum_get_value (class, relation);
const char *nick = value->value_nick;
g_type_class_unref (class);
return nick;
}
static const char *
get_relation_display_name (GtkConstraintRelation relation)
{
switch (relation)
{
case GTK_CONSTRAINT_RELATION_LE:
return "";
case GTK_CONSTRAINT_RELATION_EQ:
return "=";
case GTK_CONSTRAINT_RELATION_GE:
return "";
default:
return "?";
}
}
static GtkConstraintStrength
get_strength (unsigned int id)
{
switch (id)
{
case 0: return GTK_CONSTRAINT_STRENGTH_WEAK;
case 1: return GTK_CONSTRAINT_STRENGTH_MEDIUM;
case 2: return GTK_CONSTRAINT_STRENGTH_STRONG;
case 3: return GTK_CONSTRAINT_STRENGTH_REQUIRED;
default: g_assert_not_reached ();
}
}
static unsigned int
get_strength_id (GtkConstraintStrength strength)
{
switch (strength)
{
case GTK_CONSTRAINT_STRENGTH_WEAK: return 0;
case GTK_CONSTRAINT_STRENGTH_MEDIUM: return 1;
case GTK_CONSTRAINT_STRENGTH_STRONG: return 2;
case GTK_CONSTRAINT_STRENGTH_REQUIRED: return 3;
default: g_assert_not_reached ();
}
}
static const char *
get_strength_nick (GtkConstraintStrength strength)
{
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
GEnumValue *value = g_enum_get_value (class, strength);
const char *nick = value->value_nick;
g_type_class_unref (class);
return nick;
}
void
constraint_editor_serialize_constraint (GString *str,
int indent,
GtkConstraint *constraint)
{
const char *target;
const char *target_attr;
const char *relation;
const char *source;
const char *source_attr;
double multiplier;
double constant;
const char *strength;
target = get_target_name (gtk_constraint_get_target (constraint));
target_attr = get_attr_nick (gtk_constraint_get_target_attribute (constraint));
relation = get_relation_nick (gtk_constraint_get_relation (constraint));
source = get_target_name (gtk_constraint_get_source (constraint));
source_attr = get_attr_nick (gtk_constraint_get_source_attribute (constraint));
multiplier = gtk_constraint_get_multiplier (constraint);
constant = gtk_constraint_get_constant (constraint);
strength = get_strength_nick (gtk_constraint_get_strength (constraint));
g_string_append_printf (str, "%*s<constraint target=\"%s\" target-attribute=\"%s\"\n", indent, "", target, target_attr);
g_string_append_printf (str, "%*s relation=\"%s\"\n", indent, "", relation);
if (strcmp (source_attr, "none") != 0)
{
g_string_append_printf (str, "%*s source=\"%s\" source-attribute=\"%s\"\n", indent, "", source, source_attr);
g_string_append_printf (str, "%*s multiplier=\"%g\"\n", indent, "", multiplier);
}
g_string_append_printf (str, "%*s constant=\"%g\"\n", indent, "", constant);
g_string_append_printf (str, "%*s strength=\"%s\" />\n", indent, "", strength);
}
static void
create_constraint (GtkButton *button,
ConstraintEditor *editor)
{
gpointer obj;
gpointer target;
GtkConstraintAttribute target_attr;
gpointer source;
GtkConstraintAttribute source_attr;
GtkConstraintRelation relation;
double multiplier;
double constant;
int strength;
GtkConstraint *constraint;
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->target));
if (obj)
target = get_target (editor->model, gtk_string_object_get_string (GTK_STRING_OBJECT (obj)));
else
target = NULL;
target_attr = get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->target_attr)));
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->source));
if (obj)
source = get_target (editor->model, gtk_string_object_get_string (GTK_STRING_OBJECT (obj)));
else
source = NULL;
source_attr = get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN(editor->source_attr)));
relation = get_relation (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->relation)));
multiplier = g_ascii_strtod (gtk_editable_get_text (GTK_EDITABLE (editor->multiplier)), NULL);
constant = g_ascii_strtod (gtk_editable_get_text (GTK_EDITABLE (editor->constant)), NULL);
strength = get_strength (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->strength)));
constraint = gtk_constraint_new (target, target_attr,
relation,
source, source_attr,
multiplier,
constant,
strength);
g_signal_emit (editor, signals[DONE], 0, constraint);
g_object_unref (constraint);
}
static void
source_attr_changed (ConstraintEditor *editor)
{
if (get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->source_attr))) == GTK_CONSTRAINT_ATTRIBUTE_NONE)
{
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->source), GTK_INVALID_LIST_POSITION);
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "");
gtk_widget_set_sensitive (editor->source, FALSE);
gtk_widget_set_sensitive (editor->multiplier, FALSE);
}
else
{
gtk_widget_set_sensitive (editor->source, TRUE);
gtk_widget_set_sensitive (editor->multiplier, TRUE);
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "1");
}
}
char *
constraint_editor_constraint_to_string (GtkConstraint *constraint)
{
GString *str;
const char *name;
const char *attr;
const char *relation;
double c, m;
str = g_string_new ("");
name = get_target_name (gtk_constraint_get_target (constraint));
attr = get_attr_nick (gtk_constraint_get_target_attribute (constraint));
relation = get_relation_display_name (gtk_constraint_get_relation (constraint));
if (name == NULL)
name = "[ ]";
g_string_append_printf (str, "%s.%s %s ", name, attr, relation);
c = gtk_constraint_get_constant (constraint);
attr = get_attr_nick (gtk_constraint_get_source_attribute (constraint));
if (strcmp (attr, "none") != 0)
{
name = get_target_name (gtk_constraint_get_source (constraint));
m = gtk_constraint_get_multiplier (constraint);
if (name == NULL)
name = "[ ]";
g_string_append_printf (str, "%s.%s", name, attr);
if (m != 1.0)
g_string_append_printf (str, " × %g", m);
if (c > 0.0)
g_string_append_printf (str, " + %g", c);
else if (c < 0.0)
g_string_append_printf (str, " - %g", -c);
}
else
g_string_append_printf (str, "%g", c);
return g_string_free (str, FALSE);
}
static void
update_preview (ConstraintEditor *editor)
{
GString *str;
const char *name;
const char *attr;
const char *relation;
const char *multiplier;
const char *constant;
double c, m;
if (!editor->constructed)
return;
str = g_string_new ("");
name = gtk_string_object_get_string (GTK_STRING_OBJECT (gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->target))));
attr = get_attr_nick (get_attr (gtk_drop_down_get_selected ((GTK_DROP_DOWN (editor->target_attr)))));
relation = get_relation_nick (get_relation (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->relation))));
if (name == NULL)
name = "[ ]";
g_string_append_printf (str, "%s.%s %s ", name, attr, relation);
constant = gtk_editable_get_text (GTK_EDITABLE (editor->constant));
c = g_ascii_strtod (constant, NULL);
attr = get_attr_nick (get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->source_attr))));
if (strcmp (attr, "none") != 0)
{
name = gtk_string_object_get_string (GTK_STRING_OBJECT (gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->source))));
multiplier = gtk_editable_get_text (GTK_EDITABLE (editor->multiplier));
m = g_ascii_strtod (multiplier, NULL);
if (name == NULL)
name = "[ ]";
g_string_append_printf (str, "%s.%s", name, attr);
if (m != 1.0)
g_string_append_printf (str, " × %g", m);
if (c > 0.0)
g_string_append_printf (str, " + %g", c);
else if (c < 0.0)
g_string_append_printf (str, " - %g", -c);
}
else
g_string_append_printf (str, "%g", c);
gtk_label_set_label (GTK_LABEL (editor->preview), str->str);
g_string_free (str, TRUE);
}
static void
update_button (ConstraintEditor *editor)
{
gpointer obj;
const char *target;
const char *source;
GtkConstraintAttribute source_attr = get_attr (gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->source_attr)));
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->target));
target = obj ? gtk_string_object_get_string (GTK_STRING_OBJECT (obj)) : NULL;
obj = gtk_drop_down_get_selected_item (GTK_DROP_DOWN (editor->source));
source = obj ? gtk_string_object_get_string (GTK_STRING_OBJECT (obj)) : NULL;
if (target && (source || (source_attr == GTK_CONSTRAINT_ATTRIBUTE_NONE)))
gtk_widget_set_sensitive (editor->button, TRUE);
else
gtk_widget_set_sensitive (editor->button, FALSE);
}
static void
constraint_editor_init (ConstraintEditor *editor)
{
gtk_widget_init_template (GTK_WIDGET (editor));
}
static void
constraint_editor_constructed (GObject *object)
{
ConstraintEditor *editor = CONSTRAINT_EDITOR (object);
constraint_target_combo (editor->model, editor->target, FALSE);
constraint_target_combo (editor->model, editor->source, TRUE);
if (editor->constraint)
{
GtkConstraintTarget *target;
GtkConstraintAttribute attr;
GtkConstraintRelation relation;
GtkConstraintStrength strength;
char *val;
double multiplier;
double constant;
target = gtk_constraint_get_target (editor->constraint);
select_target (GTK_DROP_DOWN (editor->target), get_target_name (target));
attr = gtk_constraint_get_target_attribute (editor->constraint);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->target_attr), get_attr_id (attr));
target = gtk_constraint_get_source (editor->constraint);
select_target (GTK_DROP_DOWN (editor->source), get_target_name (target));
attr = gtk_constraint_get_source_attribute (editor->constraint);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->source_attr), get_attr_id (attr));
relation = gtk_constraint_get_relation (editor->constraint);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->relation), get_relation_id (relation));
multiplier = gtk_constraint_get_multiplier (editor->constraint);
val = g_strdup_printf ("%g", multiplier);
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), val);
g_free (val);
constant = gtk_constraint_get_constant (editor->constraint);
val = g_strdup_printf ("%g", constant);
gtk_editable_set_text (GTK_EDITABLE (editor->constant), val);
g_free (val);
strength = gtk_constraint_get_strength (editor->constraint);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (strength));
gtk_button_set_label (GTK_BUTTON (editor->button), "Apply");
}
else
{
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->target_attr), get_attr_id (GTK_CONSTRAINT_ATTRIBUTE_LEFT));
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->source_attr), get_attr_id (GTK_CONSTRAINT_ATTRIBUTE_LEFT));
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->relation), get_relation_id (GTK_CONSTRAINT_RELATION_EQ));
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (GTK_CONSTRAINT_STRENGTH_REQUIRED));
gtk_editable_set_text (GTK_EDITABLE (editor->multiplier), "1.0");
gtk_editable_set_text (GTK_EDITABLE (editor->constant), "0.0");
gtk_button_set_label (GTK_BUTTON (editor->button), "Create");
}
editor->constructed = TRUE;
update_preview (editor);
update_button (editor);
}
static void
constraint_editor_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
ConstraintEditor *self = CONSTRAINT_EDITOR (object);
switch (property_id)
{
case PROP_MODEL:
self->model = g_value_dup_object (value);
break;
case PROP_CONSTRAINT:
self->constraint = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
constraint_editor_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
ConstraintEditor *self = CONSTRAINT_EDITOR (object);
switch (property_id)
{
case PROP_MODEL:
g_value_set_object (value, self->model);
break;
case PROP_CONSTRAINT:
g_value_set_object (value, self->constraint);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
constraint_editor_dispose (GObject *object)
{
ConstraintEditor *self = (ConstraintEditor *)object;
g_clear_object (&self->model);
g_clear_object (&self->constraint);
gtk_widget_dispose_template (GTK_WIDGET (object), CONSTRAINT_EDITOR_TYPE);
G_OBJECT_CLASS (constraint_editor_parent_class)->dispose (object);
}
static void
constraint_editor_class_init (ConstraintEditorClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->constructed = constraint_editor_constructed;
object_class->dispose = constraint_editor_dispose;
object_class->set_property = constraint_editor_set_property;
object_class->get_property = constraint_editor_get_property;
pspecs[PROP_CONSTRAINT] =
g_param_spec_object ("constraint", "constraint", "constraint",
GTK_TYPE_CONSTRAINT,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
pspecs[PROP_MODEL] =
g_param_spec_object ("model", "model", "model",
G_TYPE_LIST_MODEL,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, LAST_PROP, pspecs);
signals[DONE] =
g_signal_new ("done",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 1, GTK_TYPE_CONSTRAINT);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/gtk4/constraint-editor/constraint-editor.ui");
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, grid);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, target);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, target_attr);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, relation);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, source);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, source_attr);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, multiplier);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, constant);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, strength);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, preview);
gtk_widget_class_bind_template_child (widget_class, ConstraintEditor, button);
gtk_widget_class_bind_template_callback (widget_class, update_preview);
gtk_widget_class_bind_template_callback (widget_class, update_button);
gtk_widget_class_bind_template_callback (widget_class, create_constraint);
gtk_widget_class_bind_template_callback (widget_class, source_attr_changed);
}
ConstraintEditor *
constraint_editor_new (GListModel *model,
GtkConstraint *constraint)
{
return g_object_new (CONSTRAINT_EDITOR_TYPE,
"model", model,
"constraint", constraint,
NULL);
}

View File

@@ -1,12 +0,0 @@
constraintview {
background: black;
color: white;
}
constraintview .child {
background: red;
}
constraintview .guide {
background: blue;
}

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gtk/gtk4/constraint-editor">
<file preprocess="xml-stripblanks">constraint-editor-window.ui</file>
<file preprocess="xml-stripblanks">constraint-editor.ui</file>
<file preprocess="xml-stripblanks">guide-editor.ui</file>
<file>constraint-editor.css</file>
</gresource>
</gresources>

View File

@@ -1,34 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define CONSTRAINT_EDITOR_TYPE (constraint_editor_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintEditor, constraint_editor, CONSTRAINT, EDITOR, GtkWidget)
ConstraintEditor * constraint_editor_new (GListModel *model,
GtkConstraint *constraint);
void constraint_editor_serialize_constraint (GString *str,
int indent,
GtkConstraint *constraint);
char *constraint_editor_constraint_to_string (GtkConstraint *constraint);

View File

@@ -1,204 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkStringList" id="targets">
<items>
<item>None</item>
<item>Left</item>
<item>Right</item>
<item>Top</item>
<item>Bottom</item>
<item>Start</item>
<item>End</item>
<item>Width</item>
<item>Height</item>
<item>Center X</item>
<item>Center Y</item>
<item>Baseline</item>
</items>
</object>
<template class="ConstraintEditor" parent="GtkWidget">
<child>
<object class="GtkGrid" id="grid">
<property name="margin-start">20</property>
<property name="margin-end">20</property>
<property name="margin-top">20</property>
<property name="margin-bottom">20</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<child>
<object class="GtkLabel">
<property name="label">Target</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkDropDown" id="target">
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
<signal name="notify::selected" handler="update_button" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkDropDown" id="target_attr">
<property name="model">targets</property>
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
<layout>
<property name="column">2</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Relation</property>
<layout>
<property name="column">0</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkDropDown" id="relation">
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
<property name="model">
<object class="GtkStringList">
<items>
<item>≤</item>
<item>=</item>
<item>≥</item>
</items>
</object>
</property>
<layout>
<property name="column">1</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Source</property>
<layout>
<property name="column">0</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkDropDown" id="source">
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
<signal name="notify::selected" handler="update_button" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkDropDown" id="source_attr">
<property name="model">targets</property>
<signal name="notify::selected" handler="update_preview" swapped="yes"/>
<signal name="notify::selected" handler="source_attr_changed" swapped="yes"/>
<signal name="notify::selected" handler="update_button" swapped="yes"/>
<layout>
<property name="column">2</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Multiplier</property>
<layout>
<property name="column">0</property>
<property name="row">4</property>
</layout>
</object>
</child>
<child>
<object class="GtkEntry" id="multiplier">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">4</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Constant</property>
<layout>
<property name="column">0</property>
<property name="row">5</property>
</layout>
</object>
</child>
<child>
<object class="GtkEntry" id="constant">
<signal name="changed" handler="update_preview" swapped="yes"/>
<layout>
<property name="column">1</property>
<property name="row">5</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Strength</property>
<layout>
<property name="column">0</property>
<property name="row">6</property>
</layout>
</object>
</child>
<child>
<object class="GtkDropDown" id="strength">
<property name="model">
<object class="GtkStringList">
<items>
<item>Weak</item>
<item>Medium</item>
<item>Strong</item>
<item>Required</item>
</items>
</object>
</property>
<layout>
<property name="column">1</property>
<property name="row">6</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel" id="preview">
<property name="xalign">0</property>
<layout>
<property name="column">1</property>
<property name="row">7</property>
<property name="column-span">2</property>
</layout>
<attributes>
<attribute name="scale" value="1.44"/>
</attributes>
</object>
</child>
<child>
<object class="GtkButton" id="button">
<property name="label">Create</property>
<signal name="clicked" handler="create_constraint"/>
<layout>
<property name="column">2</property>
<property name="row">8</property>
</layout>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,93 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "constraint-view-child.h"
struct _ConstraintViewChild
{
GObject parent_instance;
char *name;
};
enum {
PROP_NAME = 1,
LAST_PROP
};
static GParamSpec props[LAST_PROP];
G_DEFINE_TYPE (ConstraintViewChild, constraint_view_child, G_TYPE_OBJECT)
static void
constraint_view_child_init (ConstraintViewChild *child)
{
}
static void
constraint_view_child_finalize (GObject *object)
{
ConstraintViewChild *child = CONSTRAINT_VIEW_CHILD (object);
g_free (child->name);
G_OBJECT_CLASS (constraint_view_child_parent_class)->finalize (object);
}
static void
constraint_view_child_set_property (GObject *object,
static void
constraint_view_child_class_init (ConstraintViewChildClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->finalize = constraint_view_child_finalize;
object_class->get_property = constraint_view_child_get_property;
object_class->set_property = constraint_view_child_set_property;
props[PROP_NAME] =
g_param_spec_string ("name", "name", "name",
NULL,
G_PARAM_READWRITE);
g_object_class_install_properties (object_class, LAST_PROP, props);
}
#define CONSTRAINT_VIEW_CHILD_TYPE (constraint_view_get_type ())
G_DECLARE_TYPE (ConstraintViewChild, constraint_view_child, CONSTRAINT, VIEW_CHILD, GObject)
#define CONSTRAINT_VIEW_WIDGET_TYPE (constraint_view_widget_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewWidget, constraint_view_widget, CONSTRAINT, VIEW_WIDGET, ConstraintViewChild)
ConstraintViewWidget * constraint_view_widget_new (void);
#define CONSTRAINT_VIEW_GUIDE_TYPE (constraint_view_guide_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewGuide, constraint_view_guide, CONSTRAINT, VIEW_GUIDE, ConstraintViewChild)
ConstraintViewGuide * constraint_view_guide_new (void);
#define CONSTRAINT_VIEW_CONSTRAINT_TYPE (constraint_view_constraint_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewConstraint, constraint_view_constraint, CONSTRAINT, VIEW_CONSTRAINT, ConstraintViewChild)
ConstraintViewGuide * constraint_view_constraint_new (void);

View File

@@ -1,44 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define CONSTRAINT_VIEW_CHILD_TYPE (constraint_view_get_type ())
G_DECLARE_TYPE (ConstraintViewChild, constraint_view_child, CONSTRAINT, VIEW_CHILD, GObject)
#define CONSTRAINT_VIEW_WIDGET_TYPE (constraint_view_widget_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewWidget, constraint_view_widget, CONSTRAINT, VIEW_WIDGET, ConstraintViewChild)
ConstraintViewWidget * constraint_view_widget_new (void);
#define CONSTRAINT_VIEW_GUIDE_TYPE (constraint_view_guide_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewGuide, constraint_view_guide, CONSTRAINT, VIEW_GUIDE, ConstraintViewChild)
ConstraintViewGuide * constraint_view_guide_new (void);
#define CONSTRAINT_VIEW_CONSTRAINT_TYPE (constraint_view_constraint_get_type ())
G_DECLARE_FINAL_TYPE (ConstraintViewConstraint, constraint_view_constraint, CONSTRAINT, VIEW_CONSTRAINT, ConstraintViewChild)
ConstraintViewGuide * constraint_view_constraint_new (void);

View File

@@ -1,345 +0,0 @@
/* Copyright (C) 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gtk/gtk.h>
#include "constraint-view.h"
struct _ConstraintView
{
GtkWidget parent;
GListModel *model;
GtkWidget *drag_widget;
};
G_DEFINE_TYPE (ConstraintView, constraint_view, GTK_TYPE_WIDGET);
static void
constraint_view_dispose (GObject *object)
{
ConstraintView *view = CONSTRAINT_VIEW (object);
GtkWidget *child;
while ((child = gtk_widget_get_first_child (GTK_WIDGET (view))) != NULL)
gtk_widget_unparent (child);
g_clear_object (&view->model);
G_OBJECT_CLASS (constraint_view_parent_class)->dispose (object);
}
static void
constraint_view_class_init (ConstraintViewClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = constraint_view_dispose;
gtk_widget_class_set_css_name (widget_class, "constraintview");
}
static void
update_weak_position (ConstraintView *self,
GtkWidget *child,
double x,
double y)
{
GtkLayoutManager *manager;
GtkConstraint *constraint;
manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
constraint = (GtkConstraint *)g_object_get_data (G_OBJECT (child), "x-constraint");
if (constraint)
{
gtk_constraint_layout_remove_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "x-constraint", NULL);
}
if (x != -100)
{
constraint = gtk_constraint_new_constant (child,
GTK_CONSTRAINT_ATTRIBUTE_CENTER_X,
GTK_CONSTRAINT_RELATION_EQ,
x,
GTK_CONSTRAINT_STRENGTH_WEAK);
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "x-constraint", constraint);
}
constraint = (GtkConstraint *)g_object_get_data (G_OBJECT (child), "y-constraint");
if (constraint)
{
gtk_constraint_layout_remove_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "y-constraint", NULL);
}
if (y != -100)
{
constraint = gtk_constraint_new_constant (child,
GTK_CONSTRAINT_ATTRIBUTE_CENTER_Y,
GTK_CONSTRAINT_RELATION_EQ,
y,
GTK_CONSTRAINT_STRENGTH_WEAK);
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
g_object_set_data (G_OBJECT (child), "y-constraint", constraint);
}
}
static void
drag_begin (GtkGestureDrag *drag,
double start_x,
double start_y,
ConstraintView *self)
{
GtkWidget *widget;
widget = gtk_widget_pick (GTK_WIDGET (self), start_x, start_y, GTK_PICK_DEFAULT);
if (GTK_IS_LABEL (widget))
{
widget = gtk_widget_get_ancestor (widget, GTK_TYPE_FRAME);
if (widget &&
gtk_widget_get_parent (widget) == (GtkWidget *)self)
{
self->drag_widget = widget;
}
}
}
static void
drag_update (GtkGestureDrag *drag,
double offset_x,
double offset_y,
ConstraintView *self)
{
double x, y;
if (!self->drag_widget)
return;
gtk_gesture_drag_get_start_point (drag, &x, &y);
update_weak_position (self, self->drag_widget, x + offset_x, y + offset_y);
}
static void
drag_end (GtkGestureDrag *drag,
double offset_x,
double offset_y,
ConstraintView *self)
{
self->drag_widget = NULL;
}
static gboolean
omit_internal (gpointer item, gpointer user_data)
{
if (g_object_get_data (G_OBJECT (item), "internal"))
return FALSE;
return TRUE;
}
static void
constraint_view_init (ConstraintView *self)
{
GtkLayoutManager *manager;
GtkEventController *controller;
GListStore *list;
GListModel *all_children;
GListModel *all_constraints;
GListModel *guides;
GListModel *children;
GListModel *constraints;
GtkFilter *filter;
manager = gtk_constraint_layout_new ();
gtk_widget_set_layout_manager (GTK_WIDGET (self), manager);
guides = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (manager));
all_constraints = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (manager));
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_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);
g_list_store_append (list, children);
g_list_store_append (list, guides);
g_list_store_append (list, constraints);
g_object_unref (children);
g_object_unref (guides);
g_object_unref (constraints);
self->model = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (list)));
controller = (GtkEventController *)gtk_gesture_drag_new ();
g_signal_connect (controller, "drag-begin", G_CALLBACK (drag_begin), self);
g_signal_connect (controller, "drag-update", G_CALLBACK (drag_update), self);
g_signal_connect (controller, "drag-end", G_CALLBACK (drag_end), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
}
ConstraintView *
constraint_view_new (void)
{
return g_object_new (CONSTRAINT_VIEW_TYPE, NULL);
}
void
constraint_view_add_child (ConstraintView *view,
const char *name)
{
GtkWidget *frame;
GtkWidget *label;
label = gtk_label_new (name);
frame = gtk_frame_new (NULL);
gtk_widget_add_css_class (frame, "child");
gtk_widget_set_name (frame, name);
gtk_frame_set_child (GTK_FRAME (frame), label);
gtk_widget_set_parent (frame, GTK_WIDGET (view));
update_weak_position (view, frame, 100, 100);
}
void
constraint_view_remove_child (ConstraintView *view,
GtkWidget *child)
{
update_weak_position (view, child, -100, -100);
gtk_widget_unparent (child);
}
void
constraint_view_add_guide (ConstraintView *view,
GtkConstraintGuide *guide)
{
GtkConstraintLayout *layout;
GtkWidget *frame;
GtkWidget *label;
const char *name;
GtkConstraint *constraint;
struct {
const char *name;
GtkConstraintAttribute attr;
} names[] = {
{ "left-constraint", GTK_CONSTRAINT_ATTRIBUTE_LEFT },
{ "top-constraint", GTK_CONSTRAINT_ATTRIBUTE_TOP },
{ "width-constraint", GTK_CONSTRAINT_ATTRIBUTE_WIDTH },
{ "height-constraint", GTK_CONSTRAINT_ATTRIBUTE_HEIGHT },
};
int i;
name = gtk_constraint_guide_get_name (guide);
label = gtk_label_new (name);
g_object_bind_property (guide, "name",
label, "label",
G_BINDING_DEFAULT);
frame = gtk_frame_new (NULL);
gtk_widget_add_css_class (frame, "guide");
g_object_set_data (G_OBJECT (frame), "internal", (char *)"yes");
gtk_frame_set_child (GTK_FRAME (frame), label);
gtk_widget_insert_after (frame, GTK_WIDGET (view), NULL);
g_object_set_data (G_OBJECT (guide), "frame", frame);
layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (view)));
gtk_constraint_layout_add_guide (layout, g_object_ref (guide));
for (i = 0; i < G_N_ELEMENTS (names); i++)
{
constraint = gtk_constraint_new (frame,
names[i].attr,
GTK_CONSTRAINT_RELATION_EQ,
guide,
names[i].attr,
1.0, 0.0,
GTK_CONSTRAINT_STRENGTH_REQUIRED);
g_object_set_data (G_OBJECT (constraint), "internal", (char *)"yes");
gtk_constraint_layout_add_constraint (layout, constraint);
g_object_set_data (G_OBJECT (guide), names[i].name, constraint);
}
update_weak_position (view, frame, 150, 150);
}
void
constraint_view_remove_guide (ConstraintView *view,
GtkConstraintGuide *guide)
{
GtkConstraintLayout *layout;
GtkWidget *frame;
GtkConstraint *constraint;
const char *names[] = {
"left-constraint",
"top-constraint",
"width-constraint",
"height-constraint"
};
int i;
layout = GTK_CONSTRAINT_LAYOUT (gtk_widget_get_layout_manager (GTK_WIDGET (view)));
for (i = 0; i < G_N_ELEMENTS (names); i++)
{
constraint = (GtkConstraint*)g_object_get_data (G_OBJECT (guide), names[i]);
gtk_constraint_layout_remove_constraint (layout, constraint);
}
frame = (GtkWidget *)g_object_get_data (G_OBJECT (guide), "frame");
update_weak_position (view, frame, -100, -100);
gtk_widget_unparent (frame);
gtk_constraint_layout_remove_guide (layout, guide);
}
void
constraint_view_add_constraint (ConstraintView *view,
GtkConstraint *constraint)
{
GtkLayoutManager *manager;
manager = gtk_widget_get_layout_manager (GTK_WIDGET (view));
gtk_constraint_layout_add_constraint (GTK_CONSTRAINT_LAYOUT (manager),
g_object_ref (constraint));
}
void
constraint_view_remove_constraint (ConstraintView *view,
GtkConstraint *constraint)
{
GtkLayoutManager *manager;
manager = gtk_widget_get_layout_manager (GTK_WIDGET (view));
gtk_constraint_layout_remove_constraint (GTK_CONSTRAINT_LAYOUT (manager),
constraint);
}
GListModel *
constraint_view_get_model (ConstraintView *view)
{
return view->model;
}

View File

@@ -1,45 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define CONSTRAINT_VIEW_TYPE (constraint_view_get_type ())
G_MODULE_EXPORT
G_DECLARE_FINAL_TYPE (ConstraintView, constraint_view, CONSTRAINT, VIEW, GtkWidget)
ConstraintView * constraint_view_new (void);
void constraint_view_add_child (ConstraintView *view,
const char *name);
void constraint_view_remove_child (ConstraintView *view,
GtkWidget *child);
void constraint_view_add_guide (ConstraintView *view,
GtkConstraintGuide *guide);
void constraint_view_remove_guide (ConstraintView *view,
GtkConstraintGuide *guide);
void constraint_view_guide_changed (ConstraintView *view,
GtkConstraintGuide *guide);
void constraint_view_add_constraint (ConstraintView *view,
GtkConstraint *constraint);
void constraint_view_remove_constraint (ConstraintView *view,
GtkConstraint *constraint);
GListModel * constraint_view_get_model (ConstraintView *view);

View File

@@ -1,355 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#include "config.h"
#include "guide-editor.h"
struct _GuideEditor
{
GtkWidget parent_instance;
GtkWidget *grid;
GtkWidget *name;
GtkWidget *min_width;
GtkWidget *min_height;
GtkWidget *nat_width;
GtkWidget *nat_height;
GtkWidget *max_width;
GtkWidget *max_height;
GtkWidget *strength;
GtkWidget *button;
GtkConstraintGuide *guide;
gboolean constructed;
};
enum {
PROP_GUIDE = 1,
LAST_PROP
};
static GParamSpec *pspecs[LAST_PROP];
enum {
DONE,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE(GuideEditor, guide_editor, GTK_TYPE_WIDGET);
static GtkConstraintStrength
get_strength (unsigned int id)
{
switch (id)
{
case 0: return GTK_CONSTRAINT_STRENGTH_WEAK;
case 1: return GTK_CONSTRAINT_STRENGTH_MEDIUM;
case 2: return GTK_CONSTRAINT_STRENGTH_STRONG;
case 3: return GTK_CONSTRAINT_STRENGTH_REQUIRED;
default: g_assert_not_reached ();
}
}
static unsigned int
get_strength_id (GtkConstraintStrength strength)
{
switch (strength)
{
case GTK_CONSTRAINT_STRENGTH_WEAK: return 0;
case GTK_CONSTRAINT_STRENGTH_MEDIUM: return 1;
case GTK_CONSTRAINT_STRENGTH_STRONG: return 2;
case GTK_CONSTRAINT_STRENGTH_REQUIRED: return 3;
default: g_assert_not_reached ();
}
}
static const char *
get_strength_nick (GtkConstraintStrength strength)
{
GEnumClass *class = g_type_class_ref (GTK_TYPE_CONSTRAINT_STRENGTH);
GEnumValue *value = g_enum_get_value (class, strength);
const char *nick = value->value_nick;
g_type_class_unref (class);
return nick;
}
void
guide_editor_serialize_guide (GString *str,
int indent,
GtkConstraintGuide *guide)
{
int min_width, min_height;
int nat_width, nat_height;
int max_width, max_height;
const char *name;
const char *strength;
gtk_constraint_guide_get_min_size (guide, &min_width, &min_height);
gtk_constraint_guide_get_nat_size (guide, &nat_width, &nat_height);
gtk_constraint_guide_get_max_size (guide, &max_width, &max_height);
name = gtk_constraint_guide_get_name (guide);
strength = get_strength_nick (gtk_constraint_guide_get_strength (guide));
g_string_append_printf (str, "%*s<guide min-width=\"%d\" min-height=\"%d\"\n", indent, "", min_width, min_height);
g_string_append_printf (str, "%*s nat-width=\"%d\" nat-height=\"%d\"\n", indent, "", nat_width, nat_height);
g_string_append_printf (str, "%*s max-width=\"%d\" max-height=\"%d\"\n", indent, "", max_width, max_height);
g_string_append_printf (str, "%*s name=\"%s\" strength=\"%s\" />\n", indent, "", name, strength);
}
static void
create_guide (GtkButton *button,
GuideEditor *editor)
{
int strength;
const char *name;
int w, h;
GtkConstraintGuide *guide;
unsigned int id;
if (editor->guide)
guide = g_object_ref (editor->guide);
else
guide = gtk_constraint_guide_new ();
name = gtk_editable_get_text (GTK_EDITABLE (editor->name));
gtk_constraint_guide_set_name (guide, name);
w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->min_width));
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->min_height));
gtk_constraint_guide_set_min_size (guide, w, h);
w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->nat_width));
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->nat_height));
gtk_constraint_guide_set_nat_size (guide, w, h);
w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->max_width));
h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (editor->max_height));
gtk_constraint_guide_set_max_size (guide, w, h);
id = gtk_drop_down_get_selected (GTK_DROP_DOWN (editor->strength));
strength = get_strength (id);
gtk_constraint_guide_set_strength (guide, strength);
g_signal_emit (editor, signals[DONE], 0, guide);
g_object_unref (guide);
}
static void
guide_editor_init (GuideEditor *editor)
{
gtk_widget_init_template (GTK_WIDGET (editor));
}
static int guide_counter;
static int
min_input (GtkSpinButton *spin_button,
double *new_val)
{
if (strcmp (gtk_editable_get_text (GTK_EDITABLE (spin_button)), "") == 0)
{
*new_val = 0.0;
return TRUE;
}
return FALSE;
}
static int
max_input (GtkSpinButton *spin_button,
double *new_val)
{
if (strcmp (gtk_editable_get_text (GTK_EDITABLE (spin_button)), "") == 0)
{
*new_val = G_MAXINT;
return TRUE;
}
return FALSE;
}
static void
guide_editor_constructed (GObject *object)
{
GuideEditor *editor = GUIDE_EDITOR (object);
g_signal_connect (editor->min_width, "input", G_CALLBACK (min_input), NULL);
g_signal_connect (editor->min_height, "input", G_CALLBACK (min_input), NULL);
g_signal_connect (editor->max_width, "input", G_CALLBACK (max_input), NULL);
g_signal_connect (editor->max_height, "input", G_CALLBACK (max_input), NULL);
if (editor->guide)
{
GtkConstraintStrength strength;
const char *nick;
int w, h;
nick = gtk_constraint_guide_get_name (editor->guide);
if (nick)
gtk_editable_set_text (GTK_EDITABLE (editor->name), nick);
gtk_constraint_guide_get_min_size (editor->guide, &w, &h);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_width), w);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_height), h);
gtk_constraint_guide_get_nat_size (editor->guide, &w, &h);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_width), w);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_height), h);
gtk_constraint_guide_get_max_size (editor->guide, &w, &h);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_width), w);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_height), h);
strength = gtk_constraint_guide_get_strength (editor->guide);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (strength));
gtk_button_set_label (GTK_BUTTON (editor->button), "Apply");
}
else
{
char *name;
guide_counter++;
name = g_strdup_printf ("Guide %d", guide_counter);
gtk_editable_set_text (GTK_EDITABLE (editor->name), name);
g_free (name);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_width), 0.0);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->min_height), 0.0);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_width), 0.0);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->nat_height), 0.0);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_width), G_MAXINT);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (editor->max_height), G_MAXINT);
gtk_drop_down_set_selected (GTK_DROP_DOWN (editor->strength), get_strength_id (GTK_CONSTRAINT_STRENGTH_MEDIUM));
gtk_button_set_label (GTK_BUTTON (editor->button), "Create");
}
editor->constructed = TRUE;
}
static void
guide_editor_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GuideEditor *self = GUIDE_EDITOR (object);
switch (property_id)
{
case PROP_GUIDE:
self->guide = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
guide_editor_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GuideEditor *self = GUIDE_EDITOR (object);
switch (property_id)
{
case PROP_GUIDE:
g_value_set_object (value, self->guide);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
guide_editor_dispose (GObject *object)
{
GuideEditor *self = (GuideEditor *)object;
g_clear_object (&self->guide);
gtk_widget_dispose_template (GTK_WIDGET (self), GUIDE_EDITOR_TYPE);
G_OBJECT_CLASS (guide_editor_parent_class)->dispose (object);
}
static void
guide_editor_class_init (GuideEditorClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->constructed = guide_editor_constructed;
object_class->dispose = guide_editor_dispose;
object_class->set_property = guide_editor_set_property;
object_class->get_property = guide_editor_get_property;
pspecs[PROP_GUIDE] =
g_param_spec_object ("guide", "guide", "guide",
GTK_TYPE_CONSTRAINT_GUIDE,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, LAST_PROP, pspecs);
signals[DONE] =
g_signal_new ("done",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 1, GTK_TYPE_CONSTRAINT_GUIDE);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/gtk4/constraint-editor/guide-editor.ui");
gtk_widget_class_bind_template_child (widget_class, GuideEditor, grid);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, name);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, min_width);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, min_height);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, nat_width);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, nat_height);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, max_width);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, max_height);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, strength);
gtk_widget_class_bind_template_child (widget_class, GuideEditor, button);
gtk_widget_class_bind_template_callback (widget_class, create_guide);
}
GuideEditor *
guide_editor_new (GtkConstraintGuide *guide)
{
return g_object_new (GUIDE_EDITOR_TYPE,
"guide", guide,
NULL);
}

View File

@@ -1,32 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#pragma once
#include <gtk/gtk.h>
#define GUIDE_EDITOR_TYPE (guide_editor_get_type ())
G_DECLARE_FINAL_TYPE (GuideEditor, guide_editor, GUIDE, EDITOR, GtkWidget)
GuideEditor * guide_editor_new (GtkConstraintGuide *guide);
void guide_editor_serialize_guide (GString *str,
int indent,
GtkConstraintGuide *guide);

View File

@@ -1,201 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkAdjustment" id="min_width_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="min_height_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="nat_width_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="nat_height_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="max_width_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<object class="GtkAdjustment" id="max_height_adj">
<property name="lower">0</property>
<property name="upper">2147483647</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
<property name="page-size">0</property>
</object>
<template class="GuideEditor" parent="GtkWidget">
<child>
<object class="GtkGrid" id="grid">
<property name="margin-start">20</property>
<property name="margin-end">20</property>
<property name="margin-top">20</property>
<property name="margin-bottom">20</property>
<property name="row-spacing">10</property>
<property name="column-spacing">10</property>
<child>
<object class="GtkLabel">
<property name="label">Name</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
</layout>
</object>
</child>
<child>
<object class="GtkEntry" id="name">
<property name="max-width-chars">20</property>
<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="label">Min Size</property>
<layout>
<property name="column">0</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="min_width">
<property name="adjustment">min_width_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">1</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="min_height">
<property name="adjustment">min_height_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">2</property>
<property name="row">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Nat Size</property>
<layout>
<property name="column">0</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="nat_width">
<property name="adjustment">nat_width_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">1</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="nat_height">
<property name="adjustment">nat_height_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">2</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Max Size</property>
<layout>
<property name="column">0</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="max_width">
<property name="adjustment">max_width_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">1</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkSpinButton" id="max_height">
<property name="adjustment">max_height_adj</property>
<property name="max-width-chars">5</property>
<layout>
<property name="column">2</property>
<property name="row">3</property>
</layout>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="label">Strength</property>
<layout>
<property name="column">0</property>
<property name="row">4</property>
</layout>
</object>
</child>
<child>
<object class="GtkDropDown" id="strength">
<property name="model">
<object class="GtkStringList">
<items>
<item>Weak</item>
<item>Medium</item>
<item>Strong</item>
<item>Required</item>
</items>
</object>
</property>
<layout>
<property name="column">1</property>
<property name="row">4</property>
<property name="column-span">2</property>
</layout>
</object>
</child>
<child>
<object class="GtkButton" id="button">
<property name="label">Create</property>
<signal name="clicked" handler="create_guide"/>
<layout>
<property name="column">2</property>
<property name="row">5</property>
</layout>
</object>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -1,28 +0,0 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include <constraint-editor-application.h>
int
main (int argc, char *argv[])
{
return g_application_run (G_APPLICATION (constraint_editor_application_new ()), argc, argv);
}

View File

@@ -1,23 +0,0 @@
constraint_editor_sources = [
'main.c',
'constraint-editor-application.c',
'constraint-editor-window.c',
'constraint-view.c',
'constraint-editor.c',
'guide-editor.c',
]
constraint_editor_resources = gnome.compile_resources('constraint_editor_resources',
'constraint-editor.gresource.xml',
source_dir: meson.current_source_dir(),
)
executable('gtk4-constraint-editor',
sources: [ constraint_editor_sources, constraint_editor_resources, ],
c_args: common_cflags,
dependencies: libgtk_dep,
include_directories: confinc,
win_subsystem: 'windows',
link_args: extra_demo_ldflags,
install: false,
)

22315
demos/gtk-demo/Moby-Dick.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,26 +0,0 @@
uniform float u_time;
void
mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
{
vec2 pos = (fragCoord.xy * 2.0 - resolution.xy)/ min (resolution.x, resolution.y) ;
float t0 = sin ((u_time + 0.00)*1.0);
float t1 = sin ((u_time + 0.30)*0.4);
float t2 = cos ((u_time + 0.23)*0.9);
float t3 = cos ((u_time + 0.41)*0.6);
float t4 = cos ((u_time + 0.11)*0.3);
vec2 p0 = vec2 (t1, t0) ;
vec2 p1 = vec2 (t2, t3) ;
vec2 p2 = vec2 (t4, t3) ;
float r = 1.0/distance (pos, p0);
float g = 1.0/distance (pos, p1);
float b = 1.0/distance (pos, p2);
float sum = r + g + b;
float alpha = 1.0 - pow (1.0/(sum), 40.0)*pow (10.0, 40.0*0.7);
fragColor = vec4 (r*0.5, g*0.5, b*0.5, 1.0) * alpha;
}

View File

@@ -1,226 +0,0 @@
uniform float iTime;
// 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 = floor(nn + 0.5);
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, in vec2 fragCoord, in vec2 resolution, in vec2 uv) {
vec2 q = fragCoord/resolution.xy;
vec2 p = -1.0 + 2.0*q;
p.x *= resolution.x/resolution.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 / resolution.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);
}

View File

@@ -1,27 +0,0 @@
uniform float progress;
uniform sampler2D u_texture1;
uniform sampler2D u_texture2;
vec4 getFromColor (vec2 uv) {
return GskTexture(u_texture1, uv);
}
vec4 getToColor (vec2 uv) {
return GskTexture(u_texture2, uv);
}
// Source: https://gl-transitions.com/editor/crosswarp
// Author: Eke Péter <peterekepeter@gmail.com>
// License: MIT
vec4 transition(vec2 p) {
float x = progress;
x=smoothstep(.0,1.0,(x*2.0+p.x-1.0));
return mix(getFromColor((p-.5)*(1.-x)+.5), getToColor((p-.5)*x+.5), x);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
{
fragColor = transition(uv);
}

View File

@@ -146,21 +146,6 @@
<file>cogs.glsl</file>
<file>glowingstars.glsl</file>
</gresource>
<gresource prefix="/gltransition">
<file>gtkshaderstack.c</file>
<file>gtkshaderstack.h</file>
<file>gtkshaderbin.h</file>
<file>gtkshaderbin.c</file>
<file>gskshaderpaintable.h</file>
<file>gskshaderpaintable.c</file>
<file>wind.glsl</file>
<file>radial.glsl</file>
<file>crosswarp.glsl</file>
<file>kaleidoscope.glsl</file>
<file>cogs2.glsl</file>
<file>ripple.glsl</file>
<file>background.glsl</file>
</gresource>
<gresource prefix="/iconscroll">
<file>iconscroll.ui</file>
</gresource>
@@ -296,7 +281,6 @@
<file>gears.c</file>
<file>gestures.c</file>
<file>glarea.c</file>
<file>gltransition.c</file>
<file>headerbar.c</file>
<file>hypertext.c</file>
<file>iconscroll.c</file>
@@ -457,6 +441,7 @@
<file>portland-rose-thumbnail.png</file>
<file>large-image-thumbnail.png</file>
<file compressed="true">large-image.png</file>
<file compressed="true">Moby-Dick.txt</file>
</gresource>
<gresource prefix="/org/gtk/Demo4/gtk">
<file preprocess="xml-stripblanks">help-overlay.ui</file>

View File

@@ -9,7 +9,6 @@
#include "gtkfishbowl.h"
#include "gtkgears.h"
#include "gskshaderpaintable.h"
#include "nodewidget.h"
#include "graphwidget.h"
@@ -152,46 +151,6 @@ create_switch (void)
return w;
}
static gboolean
update_paintable (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer user_data)
{
GskShaderPaintable *paintable;
gint64 frame_time;
paintable = GSK_SHADER_PAINTABLE (gtk_picture_get_paintable (GTK_PICTURE (widget)));
frame_time = gdk_frame_clock_get_frame_time (frame_clock);
gsk_shader_paintable_update_time (paintable, 0, frame_time);
return G_SOURCE_CONTINUE;
}
static GtkWidget *
create_cogs (void)
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
GtkWidget *picture;
static GskGLShader *cog_shader = NULL;
GdkPaintable *paintable;
if (cog_shader == NULL)
cog_shader = gsk_gl_shader_new_from_resource ("/gltransition/cogs2.glsl");
paintable = gsk_shader_paintable_new (g_object_ref (cog_shader), NULL);
picture = gtk_picture_new_for_paintable (paintable);
gtk_widget_set_size_request (picture, 150, 75);
gtk_widget_add_tick_callback (picture, update_paintable, NULL, NULL);
return picture;
G_GNUC_END_IGNORE_DEPRECATIONS
}
static gboolean
check_cogs (GtkFishbowl *fb)
{
return GSK_IS_GL_RENDERER (gtk_native_get_renderer (gtk_widget_get_native (GTK_WIDGET (fb))));
}
static void
mapped (GtkWidget *w)
{
@@ -241,7 +200,6 @@ static const struct {
{ "Gears", create_gears, NULL },
{ "Switch", create_switch, NULL },
{ "Menubutton", create_menu_button, NULL },
{ "Shader", create_cogs, check_cogs },
{ "Tiger", create_tiger, NULL },
{ "Graph", create_graph, NULL },
};

View File

@@ -276,7 +276,7 @@ gtk_font_plane_class_init (GtkFontPlaneClass *class)
GtkWidget *
gtk_font_plane_new (GtkAdjustment *weight_adj,
GtkAdjustment *width_adj)
GtkAdjustment *width_adj)
{
return g_object_new (GTK_TYPE_FONT_PLANE,
"weight-adjustment", weight_adj,

View File

@@ -55,7 +55,7 @@ struct _GtkFontPlaneClass
GType gtk_font_plane_get_type (void) G_GNUC_CONST;
GtkWidget * gtk_font_plane_new (GtkAdjustment *width_adj,
GtkAdjustment *weight_adj);
GtkWidget * gtk_font_plane_new (GtkAdjustment *weight_adj,
GtkAdjustment *width_adj);
G_END_DECLS

View File

@@ -1,366 +0,0 @@
/* OpenGL/Transitions and Effects
* #Keywords: OpenGL, shader, effect
*
* Create transitions between pages using a custom fragment shader.
*
* The example transitions here are taken from gl-transitions.com, and you
* can edit the shader code itself on the last page of the stack.
*
* The transitions work with arbitrary content. We use images, shaders
* GL areas and plain old widgets to demonstrate this.
*
* The demo also shows some over-the-top effects like wobbly widgets,
* and animated backgrounds.
*/
#include <math.h>
#include <gtk/gtk.h>
#include "gtkshaderstack.h"
#include "gtkshaderbin.h"
#include "gtkshadertoy.h"
#include "gskshaderpaintable.h"
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
static GtkWidget *demo_window = NULL;
static void
close_window (GtkWidget *widget)
{
/* Reset the state */
demo_window = NULL;
}
static void
text_changed (GtkTextBuffer *buffer,
GtkWidget *button)
{
gtk_widget_set_visible (button, TRUE);
}
static void
apply_text (GtkWidget *button,
GtkTextBuffer *buffer)
{
GtkWidget *stack;
GskGLShader *shader;
GtkTextIter start, end;
char *text;
stack = g_object_get_data (G_OBJECT (button), "the-stack");
gtk_text_buffer_get_bounds (buffer, &start, &end);
text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
GBytes *bytes = g_bytes_new_take (text, strlen (text));
shader = gsk_gl_shader_new_from_bytes (bytes);
gtk_shader_stack_set_shader (GTK_SHADER_STACK (stack), shader);
g_object_unref (shader);
g_bytes_unref (bytes);
gtk_widget_set_visible (button, FALSE);
}
static void
go_back (GtkWidget *button,
GtkWidget *stack)
{
gtk_shader_stack_transition (GTK_SHADER_STACK (stack), FALSE);
}
static void
go_forward (GtkWidget *button,
GtkWidget *stack)
{
gtk_shader_stack_transition (GTK_SHADER_STACK (stack), TRUE);
}
static void
clicked_cb (GtkGestureClick *gesture,
guint n_pressed,
double x,
double y,
gpointer data)
{
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
}
static GtkWidget *
ripple_bin_new (void)
{
GtkWidget *bin = gtk_shader_bin_new ();
static GskGLShader *shader = NULL;
if (shader == NULL)
shader = gsk_gl_shader_new_from_resource ("/gltransition/ripple.glsl");
gtk_shader_bin_add_shader (GTK_SHADER_BIN (bin), shader, GTK_STATE_FLAG_PRELIGHT, GTK_STATE_FLAG_PRELIGHT, 20);
return bin;
}
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 gboolean
update_paintable (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer user_data)
{
GskShaderPaintable *paintable;
gint64 frame_time;
paintable = GSK_SHADER_PAINTABLE (gtk_picture_get_paintable (GTK_PICTURE (widget)));
frame_time = gdk_frame_clock_get_frame_time (frame_clock);
gsk_shader_paintable_update_time (paintable, 0, frame_time);
return G_SOURCE_CONTINUE;
}
static GtkWidget *
make_shader_stack (const char *name,
const char *resource_path,
int active_child,
GtkWidget *scale)
{
GtkWidget *stack, *child, *widget, *vbox, *hbox, *bin;
GtkWidget *label, *button, *tv;
GskGLShader *shader;
GObjectClass *class;
GParamSpecFloat *pspec;
GtkAdjustment *adjustment;
GtkTextBuffer *buffer;
GBytes *bytes;
GtkEventController *controller;
GdkPaintable *paintable;
stack = gtk_shader_stack_new ();
shader = gsk_gl_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_blendmodes/ducky.png");
gtk_picture_set_can_shrink (GTK_PICTURE (child), TRUE);
gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child);
shader = gsk_gl_shader_new_from_resource ("/gltransition/cogs2.glsl");
paintable = gsk_shader_paintable_new (shader, NULL);
child = gtk_picture_new_for_paintable (paintable);
gtk_widget_add_tick_callback (child, update_paintable, NULL, NULL);
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 = new_shadertoy ("/shadertoy/neon.glsl");
gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child);
child = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
class = g_type_class_ref (GTK_TYPE_SHADER_STACK);
pspec = G_PARAM_SPEC_FLOAT (g_object_class_find_property (class, "duration"));
adjustment = gtk_range_get_adjustment (GTK_RANGE (scale));
if (gtk_adjustment_get_lower (adjustment) == 0.0 &&
gtk_adjustment_get_upper (adjustment) == 0.0)
{
gtk_adjustment_configure (adjustment,
pspec->default_value,
pspec->minimum,
pspec->maximum,
0.1, 0.5, 0);
}
g_type_class_unref (class);
g_object_bind_property (adjustment, "value",
stack, "duration",
G_BINDING_DEFAULT);
widget = gtk_scrolled_window_new ();
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (widget), TRUE);
gtk_widget_set_hexpand (widget, TRUE);
gtk_widget_set_vexpand (widget, TRUE);
controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (controller), 0);
g_signal_connect (controller, "released", G_CALLBACK (clicked_cb), NULL);
gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_BUBBLE);
gtk_widget_add_controller (GTK_WIDGET (widget), controller);
tv = gtk_text_view_new ();
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (tv), 4);
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (tv), 4);
gtk_text_view_set_top_margin (GTK_TEXT_VIEW (tv), 4);
gtk_text_view_set_bottom_margin (GTK_TEXT_VIEW (tv), 4);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv));
bytes = g_resources_lookup_data (resource_path, 0, NULL);
gtk_text_buffer_set_text (buffer,
(const char *)g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes));
g_bytes_unref (bytes);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (widget), tv);
gtk_box_append (GTK_BOX (child), widget);
gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child);
gtk_shader_stack_set_active (GTK_SHADER_STACK (stack), active_child);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
widget = gtk_center_box_new ();
label = gtk_label_new (name);
gtk_widget_add_css_class (label, "title-4");
gtk_widget_set_size_request (label, -1, 26);
gtk_center_box_set_center_widget (GTK_CENTER_BOX (widget), label);
button = gtk_button_new_from_icon_name ("view-refresh-symbolic");
g_signal_connect (buffer, "changed", G_CALLBACK (text_changed), button);
g_object_set_data (G_OBJECT (button), "the-stack", stack);
g_signal_connect (button, "clicked", G_CALLBACK (apply_text), buffer);
gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
gtk_widget_add_css_class (button, "small");
gtk_widget_set_visible (button, FALSE);
gtk_center_box_set_end_widget (GTK_CENTER_BOX (widget), button);
gtk_box_append (GTK_BOX (vbox), widget);
GtkWidget *bin2 = ripple_bin_new ();
gtk_shader_bin_set_child (GTK_SHADER_BIN (bin2), stack);
gtk_box_append (GTK_BOX (vbox), bin2);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_widget_set_halign (hbox, GTK_ALIGN_CENTER);
gtk_box_append (GTK_BOX (vbox), hbox);
button = gtk_button_new_from_icon_name ("go-previous-symbolic");
g_signal_connect (button, "clicked", G_CALLBACK (go_back), stack);
bin = ripple_bin_new ();
gtk_shader_bin_set_child (GTK_SHADER_BIN (bin), button);
gtk_box_append (GTK_BOX (hbox), bin);
button = gtk_button_new_from_icon_name ("go-next-symbolic");
g_signal_connect (button, "clicked", G_CALLBACK (go_forward), stack);
bin = ripple_bin_new ();
gtk_shader_bin_set_child (GTK_SHADER_BIN (bin), button);
gtk_box_append (GTK_BOX (hbox), bin);
return vbox;
}
static void
remove_provider (gpointer data)
{
GtkStyleProvider *provider = GTK_STYLE_PROVIDER (data);
gtk_style_context_remove_provider_for_display (gdk_display_get_default (), provider);
g_object_unref (provider);
}
static GtkWidget *
create_gltransition_window (GtkWidget *do_widget)
{
GtkWidget *window, *headerbar, *scale, *outer_grid, *grid, *background;
GdkPaintable *paintable;
GtkCssProvider *provider;
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 and Effects");
headerbar = gtk_header_bar_new ();
scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, NULL);
gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE);
gtk_widget_set_size_request (scale, 100, -1);
gtk_widget_set_tooltip_text (scale, "Transition duration");
gtk_header_bar_pack_end (GTK_HEADER_BAR (headerbar), scale);
gtk_window_set_titlebar (GTK_WINDOW (window), headerbar);
gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
outer_grid = gtk_grid_new ();
gtk_window_set_child (GTK_WINDOW (window), outer_grid);
paintable = gsk_shader_paintable_new (gsk_gl_shader_new_from_resource ("/gltransition/background.glsl"), NULL);
background = gtk_picture_new_for_paintable (paintable);
gtk_widget_add_tick_callback (background, update_paintable, NULL, NULL);
gtk_grid_attach (GTK_GRID (outer_grid),
background,
0, 0, 1, 1);
grid = gtk_grid_new ();
gtk_grid_attach (GTK_GRID (outer_grid),
grid,
0, 0, 1, 1);
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_grid_attach (GTK_GRID (grid),
make_shader_stack ("Wind", "/gltransition/wind.glsl", 0, scale),
0, 0, 1, 1);
gtk_grid_attach (GTK_GRID (grid),
make_shader_stack ("Radial", "/gltransition/radial.glsl", 1, scale),
1, 0, 1, 1);
gtk_grid_attach (GTK_GRID (grid),
make_shader_stack ("Crosswarp", "/gltransition/crosswarp.glsl", 2, scale),
0, 1, 1, 1);
gtk_grid_attach (GTK_GRID (grid),
make_shader_stack ("Kaleidoscope", "/gltransition/kaleidoscope.glsl", 3, scale),
1, 1, 1, 1);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_string (provider, "button.small { padding: 0; }");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_set_data_full (G_OBJECT (window), "provider", provider, remove_provider);
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_set_visible (demo_window, TRUE);
else
gtk_window_destroy (GTK_WINDOW (demo_window));
return demo_window;
}
G_GNUC_END_IGNORE_DEPRECATIONS

View File

@@ -1,338 +0,0 @@
/*
* Copyright © 2020 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include <gtk/gtk.h>
#include "gskshaderpaintable.h"
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
/**
* GskShaderPaintable:
*
* `GskShaderPaintable` is an implementation of the `GdkPaintable` interface
* that uses a `GskGLShader` to create pixels.
*
* You can set the uniform data that the shader needs for rendering
* using gsk_shader_paintable_set_args(). This function can
* be called repeatedly to change the uniform data for the next
* snapshot.
*
* Commonly, time is passed to shaders as a float uniform containing
* the elapsed time in seconds. The convenience API
* gsk_shader_paintable_update_time() can be called from a `GtkTickCallback`
* to update the time based on the frame time of the frame clock.
*/
struct _GskShaderPaintable
{
GObject parent_instance;
GskGLShader *shader;
GBytes *args;
gint64 start_time;
};
struct _GskShaderPaintableClass
{
GObjectClass parent_class;
};
enum {
PROP_0,
PROP_SHADER,
PROP_ARGS,
N_PROPS,
};
static GParamSpec *properties[N_PROPS] = { NULL, };
static void
gsk_shader_paintable_paintable_snapshot (GdkPaintable *paintable,
GdkSnapshot *snapshot,
double width,
double height)
{
GskShaderPaintable *self = GSK_SHADER_PAINTABLE (paintable);
gtk_snapshot_push_gl_shader (snapshot, self->shader, &GRAPHENE_RECT_INIT(0, 0, width, height), g_bytes_ref (self->args));
gtk_snapshot_pop (snapshot);
}
static void
gsk_shader_paintable_paintable_init (GdkPaintableInterface *iface)
{
iface->snapshot = gsk_shader_paintable_paintable_snapshot;
}
G_DEFINE_TYPE_EXTENDED (GskShaderPaintable, gsk_shader_paintable, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
gsk_shader_paintable_paintable_init))
static void
gsk_shader_paintable_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GskShaderPaintable *self = GSK_SHADER_PAINTABLE (object);
switch (prop_id)
{
case PROP_SHADER:
gsk_shader_paintable_set_shader (self, g_value_get_object (value));
break;
case PROP_ARGS:
gsk_shader_paintable_set_args (self, g_value_get_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gsk_shader_paintable_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GskShaderPaintable *self = GSK_SHADER_PAINTABLE (object);
switch (prop_id)
{
case PROP_SHADER:
g_value_set_object (value, self->shader);
break;
case PROP_ARGS:
g_value_set_boxed (value, self->args);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gsk_shader_paintable_finalize (GObject *object)
{
GskShaderPaintable *self = GSK_SHADER_PAINTABLE (object);
g_clear_pointer (&self->args, g_bytes_unref);
g_clear_object (&self->shader);
G_OBJECT_CLASS (gsk_shader_paintable_parent_class)->finalize (object);
}
static void
gsk_shader_paintable_class_init (GskShaderPaintableClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = gsk_shader_paintable_get_property;
gobject_class->set_property = gsk_shader_paintable_set_property;
gobject_class->finalize = gsk_shader_paintable_finalize;
properties[PROP_SHADER] =
g_param_spec_object ("shader", "Shader", "The shader",
GSK_TYPE_GL_SHADER,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
properties[PROP_ARGS] =
g_param_spec_boxed ("args", "Arguments", "The uniform arguments",
G_TYPE_BYTES,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
}
static void
gsk_shader_paintable_init (GskShaderPaintable *self)
{
}
/**
* gsk_shader_paintable_new:
* @shader: (transfer full) (nullable): the shader to use
* @data: (transfer full) (nullable): uniform data
*
* Creates a paintable that uses the @shader to create
* pixels. The shader must not require input textures.
* If @data is %NULL, all uniform values are set to zero.
*
* Returns: (transfer full): a new `GskShaderPaintable`
*/
GdkPaintable *
gsk_shader_paintable_new (GskGLShader *shader,
GBytes *data)
{
GdkPaintable *ret;
g_return_val_if_fail (shader == NULL || GSK_IS_GL_SHADER (shader), NULL);
if (shader && !data)
{
int size = gsk_gl_shader_get_args_size (shader);
data = g_bytes_new_take (g_new0 (guchar, size), size);
}
ret = g_object_new (GSK_TYPE_SHADER_PAINTABLE,
"shader", shader,
"args", data,
NULL);
g_clear_object (&shader);
g_clear_pointer (&data, g_bytes_unref);
return ret;
}
/**
* gsk_shader_paintable_set_shader:
* @self: a `GskShaderPaintable`
* @shader: the `GskGLShader` to use
*
* Sets the shader that the paintable will use
* to create pixels. The shader must not require
* input textures.
*/
void
gsk_shader_paintable_set_shader (GskShaderPaintable *self,
GskGLShader *shader)
{
g_return_if_fail (GSK_IS_SHADER_PAINTABLE (self));
g_return_if_fail (shader == NULL || GSK_IS_GL_SHADER (shader));
g_return_if_fail (shader == NULL || gsk_gl_shader_get_n_textures (shader) == 0);
if (!g_set_object (&self->shader, shader))
return;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SHADER]);
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
g_clear_pointer (&self->args, g_bytes_unref);
}
/**
* gsk_shader_paintable_get_shader:
* @self: a `GskShaderPaintable`
*
* Returns the shader that the paintable is using.
*
* Returns: (transfer none): the `GskGLShader` that is used
*/
GskGLShader *
gsk_shader_paintable_get_shader (GskShaderPaintable *self)
{
g_return_val_if_fail (GSK_IS_SHADER_PAINTABLE (self), NULL);
return self->shader;
}
/**
* gsk_shader_paintable_set_args:
* @self: a `GskShaderPaintable`
* @data: Data block with uniform data for the shader
*
* Sets the uniform data that will be passed to the
* shader when rendering. The @data will typically
* be produced by a `GskUniformDataBuilder`.
*
* Note that the @data should be considered immutable
* after it has been passed to this function.
*/
void
gsk_shader_paintable_set_args (GskShaderPaintable *self,
GBytes *data)
{
g_return_if_fail (GSK_IS_SHADER_PAINTABLE (self));
g_return_if_fail (data == NULL || g_bytes_get_size (data) == gsk_gl_shader_get_args_size (self->shader));
g_clear_pointer (&self->args, g_bytes_unref);
if (data)
self->args = g_bytes_ref (data);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ARGS]);
gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
}
/**
* gsk_shader_paintable_get_args:
* @self: a `GskShaderPaintable`
*
* Returns the uniform data set with
* gsk_shader_paintable_get_args().
*
* Returns: (transfer none): the uniform data
*/
GBytes *
gsk_shader_paintable_get_args (GskShaderPaintable *self)
{
g_return_val_if_fail (GSK_IS_SHADER_PAINTABLE (self), NULL);
return self->args;
}
/**
* gsk_shader_paintable_update_time:
* @self: a `GskShaderPaintable`
* @time_idx: the index of the uniform for time in seconds as float
* @frame_time: the current frame time, as returned by `GdkFrameClock`
*
* This function is a convenience wrapper for
* gsk_shader_paintable_set_args() that leaves all
* uniform values unchanged, except for the uniform with
* index @time_idx, which will be set to the elapsed time
* in seconds, since the first call to this function.
*
* This function is usually called from a `GtkTickCallback`.
*/
void
gsk_shader_paintable_update_time (GskShaderPaintable *self,
int time_idx,
gint64 frame_time)
{
GskShaderArgsBuilder *builder;
GBytes *args;
float time;
if (self->start_time == 0)
self->start_time = frame_time;
time = (frame_time - self->start_time) / (float)G_TIME_SPAN_SECOND;
builder = gsk_shader_args_builder_new (self->shader, self->args);
gsk_shader_args_builder_set_float (builder, time_idx, time);
args = gsk_shader_args_builder_free_to_args (builder);
gsk_shader_paintable_set_args (self, args);
g_bytes_unref (args);
}
G_GNUC_END_IGNORE_DEPRECATIONS

View File

@@ -1,47 +0,0 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#pragma once
#include <gdk/gdk.h>
#include <gsk/gsk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
G_BEGIN_DECLS
#define GSK_TYPE_SHADER_PAINTABLE (gsk_shader_paintable_get_type ())
G_DECLARE_FINAL_TYPE (GskShaderPaintable, gsk_shader_paintable, GSK, SHADER_PAINTABLE, GObject)
GdkPaintable * gsk_shader_paintable_new (GskGLShader *shader,
GBytes *data);
GskGLShader * gsk_shader_paintable_get_shader (GskShaderPaintable *self);
void gsk_shader_paintable_set_shader (GskShaderPaintable *self,
GskGLShader *shader);
GBytes * gsk_shader_paintable_get_args (GskShaderPaintable *self);
void gsk_shader_paintable_set_args (GskShaderPaintable *self,
GBytes *data);
void gsk_shader_paintable_update_time (GskShaderPaintable *self,
int time_idx,
gint64 frame_time);
G_END_DECLS
G_GNUC_END_IGNORE_DEPRECATIONS

View File

@@ -55,7 +55,7 @@ void gtk_fishbowl_set_animating (GtkFishbowl *fishbowl,
gboolean animating);
gboolean gtk_fishbowl_get_benchmark (GtkFishbowl *fishbowl);
void gtk_fishbowl_set_benchmark (GtkFishbowl *fishbowl,
gboolean animating);
gboolean benchmark);
double gtk_fishbowl_get_framerate (GtkFishbowl *fishbowl);
gint64 gtk_fishbowl_get_update_delay (GtkFishbowl *fishbowl);
void gtk_fishbowl_set_update_delay (GtkFishbowl *fishbowl,

View File

@@ -1,268 +0,0 @@
#include "gtkshaderbin.h"
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
typedef struct {
GskGLShader *shader;
GtkStateFlags state;
GtkStateFlags state_mask;
float extra_border;
gboolean compiled;
gboolean compiled_ok;
} ShaderInfo;
struct _GtkShaderBin
{
GtkWidget parent_instance;
GtkWidget *child;
ShaderInfo *active_shader;
GPtrArray *shaders;
guint tick_id;
float time;
float mouse_x, mouse_y;
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 (frame_clock);
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_draw (widget);
return G_SOURCE_CONTINUE;
}
static void
motion_cb (GtkEventControllerMotion *controller,
double x,
double y,
GtkShaderBin *self)
{
self->mouse_x = x;
self->mouse_y = y;
}
static void
gtk_shader_bin_init (GtkShaderBin *self)
{
GtkEventController *controller;
self->shaders = g_ptr_array_new_with_free_func ((GDestroyNotify)shader_info_free);
controller = gtk_event_controller_motion_new ();
g_signal_connect (controller, "motion", G_CALLBACK (motion_cb), self);
gtk_widget_add_controller (GTK_WIDGET (self), controller);
}
void
gtk_shader_bin_update_active_shader (GtkShaderBin *self)
{
GtkStateFlags new_state = gtk_widget_get_state_flags (GTK_WIDGET (self));
ShaderInfo *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;
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_draw (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,
float extra_border)
{
ShaderInfo *info = g_new0 (ShaderInfo, 1);
info->shader = g_object_ref (shader);
info->state = state;
info->state_mask = state_mask;
info->extra_border = extra_border;
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)
{
if (!self->active_shader->compiled)
{
GtkNative *native = gtk_widget_get_native (widget);
GskRenderer *renderer = gtk_native_get_renderer (native);
GError *error = NULL;
self->active_shader->compiled = TRUE;
self->active_shader->compiled_ok =
gsk_gl_shader_compile (self->active_shader->shader,
renderer, &error);
if (!self->active_shader->compiled_ok)
{
g_warning ("GtkShaderBin failed to compile shader: %s", error->message);
g_error_free (error);
}
}
if (self->active_shader->compiled_ok)
{
float border = self->active_shader->extra_border;
graphene_vec2_t mouse;
graphene_vec2_init (&mouse, self->mouse_x + border, self->mouse_y + border);
gtk_snapshot_push_gl_shader (snapshot, self->active_shader->shader,
&GRAPHENE_RECT_INIT(-border, -border, width+2*border, height+2*border),
gsk_gl_shader_format_args (self->active_shader->shader,
"u_time", self->time,
"u_mouse", &mouse,
NULL));
gtk_widget_snapshot_child (widget, self->child, snapshot);
gtk_snapshot_gl_shader_pop_texture (snapshot);
gtk_snapshot_pop (snapshot);
return;
}
}
/* Non-shader fallback */
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);
}
G_GNUC_END_IGNORE_DEPRECATIONS

View File

@@ -1,24 +0,0 @@
#pragma once
#include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
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,
float extra_border);
void gtk_shader_bin_set_child (GtkShaderBin *self,
GtkWidget *child);
GtkWidget *gtk_shader_bin_get_child (GtkShaderBin *self);
G_END_DECLS
G_GNUC_END_IGNORE_DEPRECATIONS

View File

@@ -1,365 +0,0 @@
#include "gtkshaderstack.h"
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
struct _GtkShaderStack
{
GtkWidget parent_instance;
GskGLShader *shader;
GPtrArray *children;
int current;
int next;
gboolean backwards;
guint tick_id;
float time;
float duration;
gint64 start_time;
};
struct _GtkShaderStackClass
{
GtkWidgetClass parent_class;
};
enum {
PROP_DURATION = 1,
NUM_PROPERTIES
};
static GParamSpec *properties[NUM_PROPERTIES] = { NULL };
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 void
update_child_visible (GtkShaderStack *self)
{
int i;
for (i = 0; i < self->children->len; i++)
{
GtkWidget *child = g_ptr_array_index (self->children, i);
gtk_widget_set_child_visible (child,
i == self->current || i == self->next);
}
}
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;
update_child_visible (self);
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;
}
if (self->next != -1)
self->current = self->next;
self->next = -1;
update_child_visible (self);
}
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);
}
void
gtk_shader_stack_transition (GtkShaderStack *self,
gboolean forward)
{
stop_transition (self);
self->backwards = !forward;
if (self->backwards)
self->next = (self->current + self->children->len - 1) % self->children->len;
else
self->next = (self->current + 1) % self->children->len;
update_child_visible (self);
start_transition (self);
}
static void
gtk_shader_stack_init (GtkShaderStack *self)
{
self->children = g_ptr_array_new_with_free_func ((GDestroyNotify)gtk_widget_unparent);
self->current = -1;
self->next = -1;
self->backwards = FALSE;
self->duration = 1.0;
}
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
{
GtkNative *native = gtk_widget_get_native (widget);
GskRenderer *renderer = gtk_native_get_renderer (native);
float progress;
next = g_ptr_array_index (self->children, self->next);
progress = self->time / self->duration;
if (self->backwards)
{
GtkWidget *tmp = next;
next = current;
current = tmp;
progress = 1. - progress;
}
if (gsk_gl_shader_compile (self->shader, renderer, NULL))
{
gtk_snapshot_push_gl_shader (snapshot,
self->shader,
&GRAPHENE_RECT_INIT(0, 0, width, height),
gsk_gl_shader_format_args (self->shader,
"progress", progress,
NULL));
gtk_widget_snapshot_child (widget, current, snapshot);
gtk_snapshot_gl_shader_pop_texture (snapshot); /* current child */
gtk_widget_snapshot_child (widget, next, snapshot);
gtk_snapshot_gl_shader_pop_texture (snapshot); /* next child */
gtk_snapshot_pop (snapshot);
}
else
{
/* Non-shader fallback */
gtk_widget_snapshot_child (widget, current, snapshot);
}
}
}
static void
gtk_shader_stack_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkShaderStack *self = GTK_SHADER_STACK (object);
switch (prop_id)
{
case PROP_DURATION:
g_value_set_float (value, self->duration);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_shader_stack_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkShaderStack *self = GTK_SHADER_STACK (object);
switch (prop_id)
{
case PROP_DURATION:
self->duration = g_value_get_float (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
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;
object_class->get_property = gtk_shader_stack_get_property;
object_class->set_property = gtk_shader_stack_set_property;
widget_class->snapshot = gtk_shader_stack_snapshot;
widget_class->measure = gtk_shader_stack_measure;
widget_class->size_allocate = gtk_shader_stack_size_allocate;
properties[PROP_DURATION] =
g_param_spec_float ("duration", "Duration", "Duration",
0.1, 3.0, 1.0,
G_PARAM_READWRITE);
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
}
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;
else
gtk_widget_set_child_visible (child, FALSE);
}
void
gtk_shader_stack_set_active (GtkShaderStack *self,
int index)
{
stop_transition (self);
self->current = MIN (index, self->children->len);
update_child_visible (self);
}
G_GNUC_END_IGNORE_DEPRECATIONS

View File

@@ -1,24 +0,0 @@
#pragma once
#include <gtk/gtk.h>
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
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);
void gtk_shader_stack_transition (GtkShaderStack *self,
gboolean forward);
void gtk_shader_stack_set_active (GtkShaderStack *self,
int index);
G_END_DECLS
G_GNUC_END_IGNORE_DEPRECATIONS

View File

@@ -1,5 +1,7 @@
#pragma once
#include <gdk/gdk.h>
typedef struct _GdkHSLA GdkHSLA;
struct _GdkHSLA {

View File

@@ -13,7 +13,7 @@ static GtkWidget *window = NULL;
static GtkWidget *scrolledwindow;
static int selected;
#define N_WIDGET_TYPES 8
#define N_WIDGET_TYPES 9
static int hincrement = 5;
@@ -73,30 +73,77 @@ populate_icons (void)
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), grid);
}
static char *content;
static gsize content_len;
extern void fontify (const char *format, GtkTextBuffer *buffer);
enum {
PLAIN_TEXT,
HIGHLIGHTED_TEXT,
UNDERLINED_TEXT,
};
static void
populate_text (gboolean highlight)
underlinify (GtkTextBuffer *buffer)
{
GtkTextTagTable *tags;
GtkTextTag *tag[3];
GtkTextIter start, end;
tags = gtk_text_buffer_get_tag_table (buffer);
tag[0] = gtk_text_tag_new ("error");
tag[1] = gtk_text_tag_new ("strikeout");
tag[2] = gtk_text_tag_new ("double");
g_object_set (tag[0], "underline", PANGO_UNDERLINE_ERROR, NULL);
g_object_set (tag[1], "strikethrough", TRUE, NULL);
g_object_set (tag[2],
"underline", PANGO_UNDERLINE_DOUBLE,
"underline-rgba", &(GdkRGBA){0., 1., 1., 1. },
NULL);
gtk_text_tag_table_add (tags, tag[0]);
gtk_text_tag_table_add (tags, tag[1]);
gtk_text_tag_table_add (tags, tag[2]);
gtk_text_buffer_get_start_iter (buffer, &end);
while (TRUE)
{
gtk_text_iter_forward_word_end (&end);
start = end;
gtk_text_iter_backward_word_start (&start);
gtk_text_buffer_apply_tag (buffer, tag[g_random_int_range (0, 3)], &start, &end);
if (!gtk_text_iter_forward_word_ends (&end, 3))
break;
}
}
static void
populate_text (const char *resource, int kind)
{
GtkWidget *textview;
GtkTextBuffer *buffer;
char *content;
gsize content_len;
GBytes *bytes;
if (!content)
{
GBytes *bytes;
bytes = g_resources_lookup_data ("/sources/font_features.c", 0, NULL);
content = g_bytes_unref_to_data (bytes, &content_len);
}
bytes = g_resources_lookup_data (resource, 0, NULL);
content = g_bytes_unref_to_data (bytes, &content_len);
buffer = gtk_text_buffer_new (NULL);
gtk_text_buffer_set_text (buffer, content, (int)content_len);
if (highlight)
fontify ("c", buffer);
switch (kind)
{
case HIGHLIGHTED_TEXT:
fontify ("c", buffer);
break;
case UNDERLINED_TEXT:
underlinify (buffer);
break;
case PLAIN_TEXT:
default:
break;
}
textview = gtk_text_view_new ();
gtk_text_view_set_buffer (GTK_TEXT_VIEW (textview), buffer);
@@ -155,14 +202,6 @@ populate_image (void)
{
GtkWidget *image;
if (!content)
{
GBytes *bytes;
bytes = g_resources_lookup_data ("/sources/font_features.c", 0, NULL);
content = g_bytes_unref_to_data (bytes, &content_len);
}
image = gtk_picture_new_for_resource ("/sliding_puzzle/portland-rose.jpg");
gtk_picture_set_can_shrink (GTK_PICTURE (image), FALSE);
@@ -255,35 +294,40 @@ set_widget_type (int type)
case 1:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling plain text");
populate_text (FALSE);
populate_text ("/sources/font_features.c", PLAIN_TEXT);
break;
case 2:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling complex text");
populate_text (TRUE);
gtk_window_set_title (GTK_WINDOW (window), "Scrolling colored text");
populate_text ("/sources/font_features.c", HIGHLIGHTED_TEXT);
break;
case 3:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling text with underlines");
populate_text ("/org/gtk/Demo4/Moby-Dick.txt", UNDERLINED_TEXT);
break;
case 4:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling text with Emoji");
populate_emoji_text ();
break;
case 4:
case 5:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a big image");
populate_image ();
break;
case 5:
case 6:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a list");
populate_list ();
break;
case 6:
case 7:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a columned list");
populate_list2 ();
break;
case 7:
case 8:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a grid");
populate_grid ();
break;

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window">
<property name="resizable">0</property>
<property name="resizable">1</property>
<property name="default-width">500</property>
<property name="default-height">500</property>
<child type="titlebar">

View File

@@ -1,41 +0,0 @@
uniform float progress;
uniform sampler2D u_texture1;
uniform sampler2D u_texture2;
vec4 getFromColor (vec2 uv) {
return GskTexture(u_texture1, uv);
}
vec4 getToColor (vec2 uv) {
return GskTexture(u_texture2, uv);
}
// Source: https://gl-transitions.com/editor/kaleidoscope
// Author: nwoeanhinnogaehr
// License: MIT
const float speed = 1.0;
const float angle = 1.0;
const float power = 1.5;
vec4 transition(vec2 uv) {
vec2 p = uv.xy / vec2(1.0).xy;
vec2 q = p;
float t = pow(progress, power)*speed;
p = p -0.5;
for (int i = 0; i < 7; i++) {
p = vec2(sin(t)*p.x + cos(t)*p.y, sin(t)*p.y - cos(t)*p.x);
t += angle;
p = abs(mod(p, 2.0) - 1.0);
}
abs(mod(p, 1.0));
return mix(
mix(getFromColor(q), getToColor(q), progress),
mix(getFromColor(p), getToColor(p), progress), 1.0 - 2.0*abs(progress - 0.5));
}
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
{
fragColor = transition(uv);
}

View File

@@ -355,28 +355,28 @@ create_clocks_model (void)
g_list_store_append (result, clock);
g_object_unref (clock);
/* A bunch of timezones with GTK hackers */
clock = gtk_clock_new ("San Francisco", g_time_zone_new ("America/Los_Angeles"));
clock = gtk_clock_new ("San Francisco", g_time_zone_new_identifier ("America/Los_Angeles"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("Xalapa", g_time_zone_new ("America/Mexico_City"));
clock = gtk_clock_new ("Xalapa", g_time_zone_new_identifier ("America/Mexico_City"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("Boston", g_time_zone_new ("America/New_York"));
clock = gtk_clock_new ("Boston", g_time_zone_new_identifier ("America/New_York"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("London", g_time_zone_new ("Europe/London"));
clock = gtk_clock_new ("London", g_time_zone_new_identifier ("Europe/London"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("Berlin", g_time_zone_new ("Europe/Berlin"));
clock = gtk_clock_new ("Berlin", g_time_zone_new_identifier ("Europe/Berlin"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("Moscow", g_time_zone_new ("Europe/Moscow"));
clock = gtk_clock_new ("Moscow", g_time_zone_new_identifier ("Europe/Moscow"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("New Delhi", g_time_zone_new ("Asia/Kolkata"));
clock = gtk_clock_new ("New Delhi", g_time_zone_new_identifier ("Asia/Kolkata"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("Shanghai", g_time_zone_new ("Asia/Shanghai"));
clock = gtk_clock_new ("Shanghai", g_time_zone_new_identifier ("Asia/Shanghai"));
g_list_store_append (result, clock);
g_object_unref (clock);

View File

@@ -156,11 +156,6 @@ gtk_demo_run (GtkDemo *self,
if (result == NULL)
return FALSE;
if (GTK_IS_WINDOW (result))
{
gtk_window_set_transient_for (GTK_WINDOW (result), GTK_WINDOW (window));
gtk_window_set_modal (GTK_WINDOW (result), TRUE);
}
return TRUE;
}
@@ -832,9 +827,6 @@ static gboolean
demo_can_run (GtkWidget *window,
const char *name)
{
if (name != NULL && strcmp (name, "gltransition") == 0)
return GSK_IS_GL_RENDERER (gtk_native_get_renderer (GTK_NATIVE (window)));
return TRUE;
}

View File

@@ -33,7 +33,6 @@ demos = files([
'gears.c',
'gestures.c',
'glarea.c',
'gltransition.c',
'headerbar.c',
'hypertext.c',
'iconscroll.c',
@@ -117,10 +116,7 @@ extra_demo_sources = files([
'gtkfishbowl.c',
'fontplane.c',
'gtkgears.c',
'gtkshaderbin.c',
'gtkshadertoy.c',
'gtkshaderstack.c',
'gskshaderpaintable.c',
'hsla.c',
'puzzlepiece.c',
'bluroverlay.c',

View File

@@ -5,4 +5,4 @@
#define NODE_TYPE_WIDGET (node_widget_get_type ())
G_DECLARE_FINAL_TYPE (NodeWidget, node_widget, NODE, WIDGET, GtkWidget)
GtkWidget * node_widget_new (const char *file);
GtkWidget * node_widget_new (const char *resource);

View File

@@ -1,34 +0,0 @@
uniform float progress;
uniform sampler2D u_texture1;
uniform sampler2D u_texture2;
vec4 getFromColor (vec2 uv) {
return GskTexture(u_texture1, uv);
}
vec4 getToColor (vec2 uv) {
return GskTexture(u_texture2, uv);
}
// Source: https://gl-transitions.com/editor/Radial
// License: MIT
// Author: Xaychru
const float smoothness = 1.0;
const float PI = 3.141592653589;
vec4 transition(vec2 p) {
vec2 rp = p*2.-1.;
return mix(
getToColor(p),
getFromColor(p),
smoothstep(0., smoothness, atan(rp.y,rp.x) - (progress-.5) * PI * 2.5)
);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
{
fragColor = transition(uv);
}

View File

@@ -1,43 +0,0 @@
uniform float u_time;
uniform vec2 u_mouse;
uniform sampler2D u_texture1;
#define PI 3.141592654
float decay(float v, float t)
{
return v * (1.0 / (1.0 + t*t));
}
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
{
// Temporary to loop time every 1 sec
float time = u_time;
// we normalize all the effects according to the min height/width
float size = min(resolution.x, resolution.y);
// Animate one wave over size in 0.3 sec
float wave_speed = size / 0.3;
float wave_length = size / 1.0;
float wave_height = size * 0.1;
vec2 center = u_mouse;
vec2 direction_from_center = fragCoord - center;
float distance_from_center = length(direction_from_center);
/* Normalize direction */
direction_from_center = direction_from_center / distance_from_center;
float propagation_length = time * wave_speed;
float t = (propagation_length - distance_from_center) / wave_length;
float offset_magnitude = 0.0;
if (t > 0.0)
offset_magnitude = decay(wave_height * sin(t * 2.0 * PI), t);
vec2 offset = direction_from_center * min(offset_magnitude, distance_from_center);
vec2 source = fragCoord - offset;
vec2 uv2 = source / resolution;
fragColor = GskTexture(u_texture1, vec2(uv2.x, 1.0-uv2.y));
}

View File

@@ -43,7 +43,7 @@ GtkListItemFactory *
suggestion_entry_get_factory (SuggestionEntry *self);
void suggestion_entry_set_use_filter (SuggestionEntry *self,
gboolean use_ilter);
gboolean use_filter);
gboolean suggestion_entry_get_use_filter (SuggestionEntry *self);
void suggestion_entry_set_expression (SuggestionEntry *self,

View File

@@ -1,33 +0,0 @@
uniform float progress;
uniform sampler2D u_texture1;
uniform sampler2D u_texture2;
vec4 getFromColor (vec2 uv) {
return GskTexture(u_texture1, uv);
}
vec4 getToColor (vec2 uv) {
return GskTexture(u_texture2, uv);
}
// Source: https://gl-transitions.com/editor/wind
// Author: gre
// License: MIT
const float size = 0.2;
float rand(vec2 co) {
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
vec4 transition(vec2 p) {
float r = rand(vec2(0, p.y));
float m = smoothstep(0.0, -size, p.x*(1.0-size) + size*r - (progress * (1.0 + size)));
return mix(getFromColor(p), getToColor(p), m);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord, in vec2 resolution, in vec2 uv)
{
fragColor = transition(uv);
}

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.2 KiB

View File

@@ -1,136 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="org.gtk.IconBrowser4-symbolic.svg"
height="16.03125"
id="svg7384"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
version="1.1"
width="16">
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Gnome Symbolic Icon Theme</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
inkscape:bbox-paths="true"
bordercolor="#666666"
borderopacity="1"
inkscape:current-layer="layer9"
inkscape:cx="-2.5662459"
inkscape:cy="11.558672"
gridtolerance="10"
inkscape:guide-bbox="true"
guidetolerance="10"
id="namedview88"
inkscape:object-nodes="false"
inkscape:object-paths="false"
objecttolerance="10"
pagecolor="#555753"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
showborder="true"
showgrid="false"
showguides="true"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="false"
inkscape:snap-global="true"
inkscape:snap-grids="true"
inkscape:snap-nodes="true"
inkscape:snap-others="false"
inkscape:snap-to-guides="true"
inkscape:window-height="1375"
inkscape:window-maximized="1"
inkscape:window-width="2560"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:zoom="1">
<inkscape:grid
empspacing="2"
enabled="true"
id="grid4866"
originx="-203"
originy="-251.96875"
snapvisiblegridlinesonly="true"
spacingx="1"
spacingy="1"
type="xygrid"
visible="true" />
</sodipodi:namedview>
<title
id="title9167">Gnome Symbolic Icon Theme</title>
<defs
id="defs7386">
<linearGradient
id="linearGradient7212"
osb:paint="solid">
<stop
id="stop7214"
offset="0"
style="stop-color:#000000;stop-opacity:1;" />
</linearGradient>
</defs>
<g
inkscape:groupmode="layer"
id="layer9"
inkscape:label="apps"
style="display:inline"
transform="translate(-444.0002,35)">
<path
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
d="m 457.9846,-27.96875 v -3 h 1 l -3,-3 -3,3 h 1 v 3 z"
id="path2809"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<path
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
d="m 451.9846,-23.96875 v 2 h 1 l 2,2 v -6 l -2,2 z"
id="path2811"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
d="m 455.9846,-24.96875 v 4 c 0,0 1,-1 1,-2 0,-1.31515 -1,-2 -1,-2 z"
id="path2813"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsc" />
<path
style="display:inline;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;enable-background:new"
d="m 457.9846,-25.96875 v 6 c 0,0 1,-1.94591 1,-3 0,-1.05409 -1,-3 -1,-3 z"
id="path2815"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsc" />
<path
inkscape:connector-curvature="0"
style="display:inline;opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;enable-background:new"
d="m 450.53751,-25.96846 c 0.24647,0 0.44708,0.19694 0.44708,0.44708 v 0.0289 c -0.008,3.05189 -2.48438,5.5237 -5.53812,5.5237 h -0.0148 c -0.25145,0 -0.44711,-0.20581 -0.44711,-0.4615 v -0.46152 -0.92302 c 0,-0.25567 0.20581,-0.4615 0.4615,-0.4615 h 0.92302 c 0.25569,0 0.46152,0.20581 0.46152,0.4615 v 0.21634 c 1.18002,-0.41715 2.10674,-1.34386 2.52389,-2.52388 h -0.21635 c -0.25566,0 -0.4615,-0.20581 -0.4615,-0.46152 v -0.92302 c 0,-0.25567 0.20581,-0.4615 0.4615,-0.4615 h 0.46152 0.4615 0.44709 0.0148 0.0148 z"
id="rect5922-7-3" />
<g
id="g904-6"
transform="matrix(0.26785369,0,0,0.26785369,436.44908,-87.00581)"
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:3.73338151;enable-background:new">
<path
sodipodi:nodetypes="csscccssssccccccsccsssssccccccsssss"
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.46676302;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 37,198.00759 c -2.76142,0 -5,2.23858 -5,5 0,2.76142 2.23858,5 5,5 0.89216,0 1.71236,-0.27804 2.4375,-0.6875 l 3.9375,3.6875 -3.9375,3.6875 c -0.72514,-0.40946 -1.54534,-0.6875 -2.4375,-0.6875 -2.76142,0 -5,2.23858 -5,5 0,2.76142 2.23858,5 5,5 2.76142,0 5,-2.23858 5,-5 0,-0.45832 -0.072,-0.89082 -0.1874,-1.3125 l 4.25,-4.125 8.9374,8.4375 h 3 v -2 l -16.1875,-15.6875 c 0.1156,-0.42168 0.1874,-0.85418 0.1874,-1.3125 0,-2.76142 -2.23858,-5 -5,-5 z m 0,3 c 1.10456,0 2,0.89544 2,2 0,1.10456 -0.89544,2 -2,2 -1.10456,0 -2,-0.89544 -2,-2 0,-1.10456 0.89544,-2 2,-2 z m 18,-1 -7.875,7.4375 2.625,2.5625 8.25,-8 v -2 z m -18,17 c 1.10456,0 2,0.89544 2,2 0,1.10456 -0.89544,2 -2,2 -1.10456,0 -2,-0.89544 -2,-2 0,-1.10456 0.89544,-2 2,-2 z"
id="path1079-7" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.1 KiB

View File

@@ -3,9 +3,7 @@
appdata_config = configuration_data()
appdata_config.set('BUILD_VERSION', meson.project_version())
subdir('constraint-editor')
subdir('gtk-demo')
subdir('icon-browser')
subdir('node-editor')
subdir('widget-factory')
subdir('print-editor')

View File

@@ -925,7 +925,7 @@ export_image_response_cb (GObject *source,
GdkTexture *texture;
GskRenderer *renderer;
renderer = gsk_gl_renderer_new ();
renderer = gsk_ngl_renderer_new ();
if (!gsk_renderer_realize_for_display (renderer, gdk_display_get_default (), NULL))
{
g_object_unref (renderer);

View File

@@ -66,10 +66,6 @@ You can compile the program above with GCC using:
gcc $( pkg-config --cflags gtk4 ) -o example-0 example-0.c $( pkg-config --libs gtk4 )
```
**Note**: If the above compilation does not work due to an error regarding `G_APPLICATION_DEFAULT_FLAGS`
this could be due to your OS providing an older version of GLib. For GLib versions older than 2.74 you
will need to replace `G_APPLICATION_DEFAULT_FLAGS` with `G_APPLICATION_FLAGS_NONE` in this example, and
others in this documentation.
For more information on how to compile a GTK application, please
refer to the [Compiling GTK Applications](compiling.html)
section in this reference.

View File

@@ -1,32 +0,0 @@
.. _gtk4-icon-browser(1):
=================
gtk4-icon-browser
=================
-----------------
List themed icons
-----------------
:Version: GTK
:Manual section: 1
:Manual group: GTK commands
SYNOPSIS
--------
| **gtk4-icon-browser** [OPTIONS...]
DESCRIPTION
-----------
``gtk4-icon-browser`` is a utility to explore the icons in the current icon
theme. It shows icons in various sizes, their symbolic variants where available,
as well as a description of the icon and its context.
OPTIONS
-------
``-h, --help``
Show the application help.

View File

@@ -98,7 +98,6 @@ if get_option('build-demos')
[ 'gtk4-demo', '1', ],
[ 'gtk4-demo-application', '1', ],
[ 'gtk4-widget-factory', '1', ],
[ 'gtk4-icon-browser', '1', ],
[ 'gtk4-node-editor', '1', ],
]
endif

View File

@@ -380,13 +380,6 @@ does not support them.
`base-instance`
:GL_EXT_base_instance
### `GDK_VULKAN_DEVICE`
This variable can be set to the index of a Vulkan device to override
the default selection of the device that is used for Vulkan rendering.
The special value `list` can be used to obtain a list of all Vulkan
devices.
### `GDK_VULKAN_DISABLE`
This variable can be set to a list of values, which cause GDK to
@@ -430,14 +423,8 @@ using and the GDK backend supports them:
`cairo`
: Selects the fallback Cairo renderer
`opengl`
: Selects the default OpenGL renderer
`gl`
: Selects the "gl" OpenGL renderer
`ngl`
: Selects the "ngl" OpenGL renderer
: Selects the OpenGL renderer
`vulkan`
: Selects the Vulkan renderer
@@ -487,6 +474,8 @@ disable certain optimizations of the "ngl" and "vulkan" renderer.
`occlusion`
: Disable occlusion culling via opacity tracking
`repeat`
: Repeat drawing operations instead of using offscreen and GL_REPEAT
The special value `all` can be used to turn on all values. The special
value `help` can be used to obtain a list of all supported values.

View File

@@ -49,7 +49,7 @@ main (int argc,
g_chdir (GTK_SRCDIR);
#endif
GtkApplication *app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
GtkApplication *app = gtk_application_new ("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
int status = g_application_run (G_APPLICATION (app), argc, argv);

View File

@@ -173,7 +173,7 @@ main (int argc,
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
app = gtk_application_new ("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);

View File

@@ -60,7 +60,7 @@ main (int argc,
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
app = gtk_application_new ("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);

View File

@@ -37,10 +37,8 @@ main (int argc,
{
GtkApplication *app;
app = gtk_application_new ("org.gtk.Example.GtkSearchBar",
G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate",
G_CALLBACK (activate_cb), NULL);
app = gtk_application_new ("org.gtk.Example.GtkSearchBar", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate_cb), NULL);
return g_application_run (G_APPLICATION (app), argc, argv);
}

View File

@@ -19,7 +19,7 @@ main (int argc,
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
app = gtk_application_new ("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);

View File

@@ -111,7 +111,7 @@ gboolean broadway_server_surface_translate (BroadwayServer *
int dx,
int dy);
guint32 broadway_server_upload_texture (BroadwayServer *server,
GBytes *texture);
GBytes *bytes);
void broadway_server_release_texture (BroadwayServer *server,
guint32 id);
cairo_surface_t * broadway_server_create_surface (int width,

View File

@@ -56,7 +56,7 @@ void _gdk_broadway_surface_translate (GdkSurface *surface,
int dx,
int dy);
gboolean _gdk_broadway_moveresize_handle_event (GdkDisplay *display,
BroadwayInputMsg *msg);
BroadwayInputMsg *event);
gboolean _gdk_broadway_moveresize_configure_done (GdkDisplay *display,
GdkSurface *surface);
void _gdk_broadway_roundtrip_notify (GdkSurface *surface,

View File

@@ -17,6 +17,7 @@
#pragma once
#include <gio/gio.h>
void file_transfer_portal_register (void);

View File

@@ -79,6 +79,6 @@ gdk_cicp_equivalent (const GdkCicp *p1,
return gdk_cicp_equal (&n1, &n2);
}
const GdkCicp * gdk_cicp_params_get_cicp (GdkCicpParams *params);
const GdkCicp * gdk_cicp_params_get_cicp (GdkCicpParams *self);
GdkCicpParams * gdk_cicp_params_new_for_cicp (const GdkCicp *cicp);

View File

@@ -20,6 +20,9 @@
* and tests, and must not include other headers.
*/
#include <glib.h>
#include <math.h>
static inline int
sign (float v)
{

View File

@@ -18,6 +18,8 @@
#pragma once
#include "gdkcolorprivate.h"
#include "gdkcolorstateprivate.h"

View File

@@ -79,8 +79,8 @@ void gdk_color_init_from_rgba (GdkColor *self,
const GdkRGBA *rgba);
void gdk_color_finish (GdkColor *self);
gboolean gdk_color_equal (const GdkColor *color1,
const GdkColor *color2);
gboolean gdk_color_equal (const GdkColor *self,
const GdkColor *other);
gboolean gdk_color_is_clear (const GdkColor *self);
gboolean gdk_color_is_opaque (const GdkColor *self);

View File

@@ -78,7 +78,7 @@ extern GdkDefaultColorState gdk_default_color_states[GDK_COLOR_STATE_N_IDS];
(GdkDefaultColorState *) (c) < &gdk_default_color_states[GDK_COLOR_STATE_N_IDS])
#define GDK_DEFAULT_COLOR_STATE_ID(c) ((GdkColorStateId) (((GdkDefaultColorState *) c) - gdk_default_color_states))
const char * gdk_color_state_get_name (GdkColorState *color_state);
const char * gdk_color_state_get_name (GdkColorState *self);
GdkColorState * gdk_color_state_get_no_srgb_tf (GdkColorState *self);
GdkColorState * gdk_color_state_new_for_cicp (const GdkCicp *cicp,

View File

@@ -117,7 +117,7 @@ struct _GdkDeviceClass
};
void _gdk_device_set_associated_device (GdkDevice *device,
GdkDevice *relative);
GdkDevice *associated);
void _gdk_device_reset_axes (GdkDevice *device);
guint _gdk_device_add_axis (GdkDevice *device,

View File

@@ -436,7 +436,7 @@ gdk_display_dispose (GObject *object)
g_queue_clear (&display->queued_events);
g_clear_pointer (&display->egl_dmabuf_formats, gdk_dmabuf_formats_unref);
g_clear_pointer (&display->egl_external_formats, gdk_dmabuf_formats_unref);
g_clear_pointer (&display->egl_internal_formats, gdk_dmabuf_formats_unref);
#ifdef GDK_RENDERING_VULKAN
if (display->vk_dmabuf_formats)
{
@@ -2002,7 +2002,7 @@ gdk_display_init_dmabuf (GdkDisplay *self)
self->dmabuf_formats = gdk_dmabuf_formats_builder_free_to_formats (builder);
GDK_DISPLAY_DEBUG (self, DMABUF,
"Initialized support for %zu dmabuf formats",
"Initialization finished. Advertising %zu dmabuf formats",
gdk_dmabuf_formats_get_n_formats (self->dmabuf_formats));
}

View File

@@ -137,7 +137,7 @@ struct _GdkDisplay
/* Cached data the EGL dmabuf downloader */
GdkDmabufFormats *egl_dmabuf_formats;
GdkDmabufFormats *egl_external_formats;
GdkDmabufFormats *egl_internal_formats;
};
struct _GdkDisplayClass
@@ -240,15 +240,15 @@ GdkVulkanContext * gdk_display_create_vulkan_context (GdkDisplay *self,
GdkSurface *surface,
GError **error);
GdkGLContext * gdk_display_get_gl_context (GdkDisplay *display);
GdkGLContext * gdk_display_get_gl_context (GdkDisplay *self);
gboolean gdk_display_init_egl (GdkDisplay *display,
gboolean gdk_display_init_egl (GdkDisplay *self,
int /*EGLenum*/ platform,
gpointer native_display,
gboolean allow_any,
GError **error);
gpointer gdk_display_get_egl_display (GdkDisplay *display);
gpointer gdk_display_get_egl_config (GdkDisplay *display,
gpointer gdk_display_get_egl_display (GdkDisplay *self);
gpointer gdk_display_get_egl_config (GdkDisplay *self,
GdkMemoryDepth depth);
void gdk_display_set_rgba (GdkDisplay *display,
@@ -289,7 +289,7 @@ void gdk_display_set_double_click_time (GdkDisplay *display,
void gdk_display_set_double_click_distance (GdkDisplay *display,
guint distance);
void gdk_display_set_cursor_theme (GdkDisplay *display,
const char *theme,
const char *name,
int size);
G_END_DECLS

View File

@@ -2068,7 +2068,7 @@ gdk_dmabuf_get_mmap_formats (void)
continue;
GDK_DEBUG (DMABUF,
"mmap dmabuf format %.4s:%#0" G_GINT64_MODIFIER "x",
"mmap advertises dmabuf format %.4s::%016" G_GINT64_MODIFIER "x",
(char *) &supported_formats[i].fourcc, (guint64) DRM_FORMAT_MOD_LINEAR);
gdk_dmabuf_formats_builder_add_format (builder,
@@ -2082,7 +2082,7 @@ gdk_dmabuf_get_mmap_formats (void)
return formats;
}
static void
static gboolean
gdk_dmabuf_do_download_mmap (GdkTexture *texture,
guchar *data,
gsize stride)
@@ -2093,16 +2093,17 @@ gdk_dmabuf_do_download_mmap (GdkTexture *texture,
gsize sizes[GDK_DMABUF_MAX_PLANES];
gsize needs_unmap[GDK_DMABUF_MAX_PLANES] = { FALSE, };
gsize i, j;
gboolean retval = FALSE;
dmabuf = gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture));
if (dmabuf->modifier != DRM_FORMAT_MOD_LINEAR)
return FALSE;
info = get_drm_format_info (dmabuf->fourcc);
g_return_if_fail (info && info->download);
GDK_DISPLAY_DEBUG (gdk_dmabuf_texture_get_display (GDK_DMABUF_TEXTURE (texture)), DMABUF,
"Using mmap for downloading %dx%d dmabuf (format %.4s:%#" G_GINT64_MODIFIER "x)",
gdk_texture_get_width (texture), gdk_texture_get_height (texture),
(char *)&dmabuf->fourcc, dmabuf->modifier);
if (!info || !info->download)
return FALSE;
for (i = 0; i < dmabuf->n_planes; i++)
{
@@ -2139,14 +2140,21 @@ gdk_dmabuf_do_download_mmap (GdkTexture *texture,
needs_unmap[i] = TRUE;
}
info->download (data,
stride,
gdk_texture_get_format (texture),
gdk_texture_get_width (texture),
gdk_texture_get_height (texture),
dmabuf,
src_data,
sizes);
info->download (data,
stride,
gdk_texture_get_format (texture),
gdk_texture_get_width (texture),
gdk_texture_get_height (texture),
dmabuf,
src_data,
sizes);
retval = TRUE;
GDK_DISPLAY_DEBUG (gdk_dmabuf_texture_get_display (GDK_DMABUF_TEXTURE (texture)), DMABUF,
"Used mmap for downloading %dx%d dmabuf (format %.4s:%#" G_GINT64_MODIFIER "x)",
gdk_texture_get_width (texture), gdk_texture_get_height (texture),
(char *)&dmabuf->fourcc, dmabuf->modifier);
out:
for (i = 0; i < dmabuf->n_planes; i++)
@@ -2159,9 +2167,11 @@ out:
if (gdk_dmabuf_ioctl (dmabuf->planes[i].fd, DMA_BUF_IOCTL_SYNC, &(struct dma_buf_sync) { DMA_BUF_SYNC_END|DMA_BUF_SYNC_READ }) < 0)
g_warning ("Failed to sync dmabuf: %s", g_strerror (errno));
}
return retval;
}
void
gboolean
gdk_dmabuf_download_mmap (GdkTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
@@ -2170,10 +2180,11 @@ gdk_dmabuf_download_mmap (GdkTexture *texture,
{
GdkMemoryFormat src_format = gdk_texture_get_format (texture);
GdkColorState *src_color_state = gdk_texture_get_color_state (texture);
gboolean retval;
if (format == src_format)
{
gdk_dmabuf_do_download_mmap (texture, data, stride);
retval = gdk_dmabuf_do_download_mmap (texture, data, stride);
gdk_memory_convert_color_state (data, stride, format,
src_color_state, color_state,
gdk_texture_get_width (texture),
@@ -2191,7 +2202,7 @@ gdk_dmabuf_download_mmap (GdkTexture *texture,
src_stride = width * gdk_memory_format_bytes_per_pixel (src_format);
src_data = g_new (guchar, src_stride * height);
gdk_dmabuf_do_download_mmap (texture, src_data, src_stride);
retval = gdk_dmabuf_do_download_mmap (texture, src_data, src_stride);
gdk_memory_convert (data, stride, format, color_state,
src_data, src_stride, src_format, src_color_state,
@@ -2199,6 +2210,8 @@ gdk_dmabuf_download_mmap (GdkTexture *texture,
g_free (src_data);
}
return retval;
}
int

View File

@@ -19,19 +19,6 @@ gdk_dmabuf_downloader_close (GdkDmabufDownloader *self)
}
gboolean
gdk_dmabuf_downloader_supports (GdkDmabufDownloader *self,
GdkDmabufTexture *texture,
GError **error)
{
GdkDmabufDownloaderInterface *iface;
g_return_val_if_fail (GDK_IS_DMABUF_DOWNLOADER (self), FALSE);
iface = GDK_DMABUF_DOWNLOADER_GET_IFACE (self);
return iface->supports (self, texture, error);
}
void
gdk_dmabuf_downloader_download (GdkDmabufDownloader *self,
GdkDmabufTexture *texture,
GdkMemoryFormat format,
@@ -41,9 +28,8 @@ gdk_dmabuf_downloader_download (GdkDmabufDownloader *self,
{
GdkDmabufDownloaderInterface *iface;
g_return_if_fail (GDK_IS_DMABUF_DOWNLOADER (self));
g_return_val_if_fail (GDK_IS_DMABUF_DOWNLOADER (self), FALSE);
iface = GDK_DMABUF_DOWNLOADER_GET_IFACE (self);
iface->download (self, texture, format, color_state, data, stride);
return iface->download (self, texture, format, color_state, data, stride);
}

View File

@@ -14,10 +14,7 @@ struct _GdkDmabufDownloaderInterface
GTypeInterface g_iface;
void (* close) (GdkDmabufDownloader *downloader);
gboolean (* supports) (GdkDmabufDownloader *downloader,
GdkDmabufTexture *texture,
GError **error);
void (* download) (GdkDmabufDownloader *downloader,
gboolean (* download) (GdkDmabufDownloader *downloader,
GdkDmabufTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
@@ -25,11 +22,8 @@ struct _GdkDmabufDownloaderInterface
gsize stride);
};
void gdk_dmabuf_downloader_close (GdkDmabufDownloader *downloader);
gboolean gdk_dmabuf_downloader_supports (GdkDmabufDownloader *downloader,
GdkDmabufTexture *texture,
GError **error);
void gdk_dmabuf_downloader_download (GdkDmabufDownloader *downloader,
void gdk_dmabuf_downloader_close (GdkDmabufDownloader *self);
gboolean gdk_dmabuf_downloader_download (GdkDmabufDownloader *downloader,
GdkDmabufTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,

View File

@@ -40,7 +40,7 @@
static gboolean
gdk_dmabuf_egl_downloader_collect_formats (GdkDisplay *display,
GdkDmabufFormatsBuilder *formats,
GdkDmabufFormatsBuilder *external)
GdkDmabufFormatsBuilder *internal)
{
GdkGLContext *context = gdk_display_get_gl_context (display);
EGLDisplay egl_display = gdk_display_get_egl_display (display);
@@ -61,8 +61,8 @@ gdk_dmabuf_egl_downloader_collect_formats (GdkDisplay *display,
eglQueryDmaBufFormatsEXT (egl_display, num_fourccs, fourccs, &num_fourccs);
n_mods = 80;
modifiers = g_new (guint64, n_mods);
external_only = g_new (unsigned int, n_mods);
modifiers = g_new0 (guint64, n_mods);
external_only = g_new0 (unsigned int, n_mods);
for (int i = 0; i < num_fourccs; i++)
{
@@ -94,24 +94,27 @@ gdk_dmabuf_egl_downloader_collect_formats (GdkDisplay *display,
for (int j = 0; j < num_modifiers; j++)
{
/* All linear formats we support are already added my the mmap downloader.
/* All linear formats we support are already advertised by the mmap downloader.
* We don't add external formats, unless we can use them (via GLES)
*/
if (modifiers[j] != DRM_FORMAT_MOD_LINEAR &&
(!external_only[j] || gdk_gl_context_get_use_es (context)))
{
GDK_DISPLAY_DEBUG (display, DMABUF,
"%s EGL dmabuf format %.4s:%#" G_GINT64_MODIFIER "x",
external_only[j] ? "external " : "",
(char *) &fourccs[i],
modifiers[j]);
gboolean advertise = modifiers[j] != DRM_FORMAT_MOD_LINEAR &&
(!external_only[j] || gdk_gl_context_get_use_es (context));
gdk_dmabuf_formats_builder_add_format (formats, fourccs[i], modifiers[j]);
GDK_DISPLAY_DEBUG (display, DMABUF,
"EGL %s %sdmabuf format %.4s::%016" G_GINT64_MODIFIER "x",
advertise ? "advertises" : "supports",
external_only[j] ? "external " : "",
(char *) &fourccs[i],
modifiers[j]);
if (advertise)
gdk_dmabuf_formats_builder_add_format (formats, fourccs[i], modifiers[j]);
if (!external_only[j])
{
gdk_dmabuf_formats_builder_add_format (internal, fourccs[i], modifiers[j]);
all_external = FALSE;
}
if (external_only[j])
gdk_dmabuf_formats_builder_add_format (external, fourccs[i], modifiers[j]);
else
all_external = FALSE;
}
/* Accept implicit modifiers as long as we accept the format at all.
@@ -123,8 +126,8 @@ gdk_dmabuf_egl_downloader_collect_formats (GdkDisplay *display,
*/
if (!all_external || gdk_gl_context_get_use_es (context))
gdk_dmabuf_formats_builder_add_format (formats, fourccs[i], DRM_FORMAT_MOD_INVALID);
if (all_external)
gdk_dmabuf_formats_builder_add_format (external, fourccs[i], DRM_FORMAT_MOD_INVALID);
if (!all_external)
gdk_dmabuf_formats_builder_add_format (internal, fourccs[i], DRM_FORMAT_MOD_INVALID);
}
g_free (modifiers);
@@ -213,7 +216,6 @@ gdk_dmabuf_egl_create_image (GdkDisplay *display,
GDK_DISPLAY_DEBUG (display, DMABUF,
"Creating EGLImage for dmabuf failed: %#x",
eglGetError ());
return 0;
}
return image;
@@ -229,6 +231,7 @@ gdk_dmabuf_egl_create_image (GdkDisplay *display,
typedef struct _GskRenderer GskRenderer;
extern GskRenderer * gsk_gl_renderer_new (void);
extern GskRenderer * gsk_ngl_renderer_new (void);
extern gboolean gsk_renderer_realize_for_display (GskRenderer *renderer,
GdkDisplay *display,
GError **error);
@@ -238,7 +241,7 @@ gdk_dmabuf_egl_init (GdkDisplay *display)
{
#if defined (HAVE_DMABUF) && defined (HAVE_EGL)
GdkDmabufFormatsBuilder *formats;
GdkDmabufFormatsBuilder *external;
GdkDmabufFormatsBuilder *internal;
gboolean retval = FALSE;
GError *error = NULL;
GskRenderer *renderer;
@@ -254,16 +257,16 @@ gdk_dmabuf_egl_init (GdkDisplay *display)
}
formats = gdk_dmabuf_formats_builder_new ();
external = gdk_dmabuf_formats_builder_new ();
internal = gdk_dmabuf_formats_builder_new ();
previous = gdk_gl_context_get_current ();
if (previous)
g_object_ref (previous);
retval = gdk_dmabuf_egl_downloader_collect_formats (display, formats, external);
retval = gdk_dmabuf_egl_downloader_collect_formats (display, formats, internal);
display->egl_dmabuf_formats = gdk_dmabuf_formats_builder_free_to_formats (formats);
display->egl_external_formats = gdk_dmabuf_formats_builder_free_to_formats (external);
display->egl_internal_formats = gdk_dmabuf_formats_builder_free_to_formats (internal);
if (!retval)
{
@@ -272,7 +275,7 @@ gdk_dmabuf_egl_init (GdkDisplay *display)
return;
}
renderer = gsk_gl_renderer_new ();
renderer = gsk_ngl_renderer_new ();
if (!gsk_renderer_realize_for_display (renderer, display, &error))
{

View File

@@ -27,7 +27,7 @@ void gdk_dmabuf_close_fds (GdkDmabuf
#ifdef HAVE_DMABUF
GdkDmabufFormats * gdk_dmabuf_get_mmap_formats (void) G_GNUC_CONST;
void gdk_dmabuf_download_mmap (GdkTexture *texture,
gboolean gdk_dmabuf_download_mmap (GdkTexture *texture,
GdkMemoryFormat format,
GdkColorState *color_state,
guchar *data,

View File

@@ -50,7 +50,6 @@ struct _GdkDmabufTexture
GdkTexture parent_instance;
GdkDisplay *display;
GdkDmabufDownloader *downloader;
GdkDmabuf dmabuf;
@@ -85,7 +84,6 @@ gdk_dmabuf_texture_dispose (GObject *object)
self->destroy = NULL;
}
g_clear_object (&self->downloader);
g_clear_object (&self->display);
G_OBJECT_CLASS (gdk_dmabuf_texture_parent_class)->dispose (object);
@@ -107,16 +105,49 @@ static gboolean
gdk_dmabuf_texture_invoke_callback (gpointer data)
{
Download *download = data;
GdkDisplay *display = download->texture->display;
gdk_dmabuf_downloader_download (download->texture->downloader,
download->texture,
download->format,
download->color_state,
download->data,
download->stride);
if (display->egl_downloader &&
gdk_dmabuf_downloader_download (display->egl_downloader,
download->texture,
download->format,
download->color_state,
download->data,
download->stride))
{
/* Successfully downloaded using EGL */
}
else if (display->vk_downloader &&
gdk_dmabuf_downloader_download (display->vk_downloader,
download->texture,
download->format,
download->color_state,
download->data,
download->stride))
{
/* Successfully downloaded using Vulkan */
}
#ifdef HAVE_DMABUF
else if (gdk_dmabuf_download_mmap (GDK_TEXTURE (download->texture),
download->format,
download->color_state,
download->data,
download->stride))
{
/* Successfully downloaded using mmap */
}
#endif
else
{
const GdkDmabuf *dmabuf = gdk_dmabuf_texture_get_dmabuf (download->texture);
g_critical ("Failed to download %dx%d dmabuf texture (format %.4s:%#" G_GINT64_MODIFIER "x)",
gdk_texture_get_width (GDK_TEXTURE (download->texture)),
gdk_texture_get_height (GDK_TEXTURE (download->texture)),
(char *)&(dmabuf->fourcc), dmabuf->modifier);
}
g_atomic_int_set (&download->spinlock, 1);
return FALSE;
}
@@ -130,14 +161,6 @@ gdk_dmabuf_texture_download (GdkTexture *texture,
GdkDmabufTexture *self = GDK_DMABUF_TEXTURE (texture);
Download download = { self, format, color_state, data, stride, 0 };
if (self->downloader == NULL)
{
#ifdef HAVE_DMABUF
gdk_dmabuf_download_mmap (texture, format, color_state, data, stride);
#endif
return;
}
g_main_context_invoke (NULL, gdk_dmabuf_texture_invoke_callback, &download);
while (g_atomic_int_get (&download.spinlock) == 0);
@@ -232,37 +255,22 @@ gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
: GDK_MEMORY_R8G8B8A8;
}
if (display->egl_downloader)
if (!gdk_dmabuf_formats_contains (display->dmabuf_formats, dmabuf.fourcc, dmabuf.modifier))
{
if (gdk_dmabuf_downloader_supports (display->egl_downloader, self, error))
self->downloader = g_object_ref (display->egl_downloader);
}
if (!self->downloader && display->vk_downloader)
{
g_clear_error (error);
if (gdk_dmabuf_downloader_supports (display->vk_downloader, self, error))
self->downloader = g_object_ref (display->vk_downloader);
}
if (!self->downloader)
{
if (!gdk_dmabuf_formats_contains (gdk_dmabuf_get_mmap_formats (), dmabuf.fourcc, dmabuf.modifier))
{
g_object_unref (self);
return NULL;
}
g_clear_error (error);
g_set_error (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_UNSUPPORTED_FORMAT,
"Unsupported dmabuf format: %.4s:%#" G_GINT64_MODIFIER "x",
(char *) &dmabuf.fourcc, dmabuf.modifier);
g_object_unref (self);
return NULL;
}
GDK_DISPLAY_DEBUG (display, DMABUF,
"Creating dmabuf texture, format %.4s:%#" G_GINT64_MODIFIER "x, %s%u planes, memory format %u, downloader %s",
"Creating dmabuf texture, format %.4s:%#" G_GINT64_MODIFIER "x, %s%u planes, memory format %u",
(char *) &dmabuf.fourcc, dmabuf.modifier,
gdk_dmabuf_texture_builder_get_premultiplied (builder) ? " premultiplied, " : "",
dmabuf.n_planes,
GDK_TEXTURE (self)->format,
self->downloader ? G_OBJECT_TYPE_NAME (self->downloader) : "none");
GDK_TEXTURE (self)->format);
/* Set this only once we know that the texture will be created.
* Otherwise dispose() will run the callback */

View File

@@ -5,9 +5,9 @@
G_BEGIN_DECLS
const GdkDmabuf * gdk_dmabuf_texture_builder_get_dmabuf (GdkDmabufTextureBuilder *builder);
const GdkDmabuf * gdk_dmabuf_texture_builder_get_dmabuf (GdkDmabufTextureBuilder *self);
void gdk_dmabuf_texture_builder_set_dmabuf (GdkDmabufTextureBuilder *builder,
void gdk_dmabuf_texture_builder_set_dmabuf (GdkDmabufTextureBuilder *self,
const GdkDmabuf *dmabuf);
G_END_DECLS

View File

@@ -511,9 +511,9 @@ gdk_draw_context_end_frame (GdkDrawContext *context)
* Use `GskRenderNode` and `GskRenderer`.
*/
const cairo_region_t *
_gdk_draw_context_get_frame_region (GdkDrawContext *context)
_gdk_draw_context_get_frame_region (GdkDrawContext *self)
{
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (context);
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (self);
return priv->frame_region;
}

View File

@@ -82,7 +82,6 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
cairo_surface_t *image;
guint framebuffer;
int alpha_size = 0;
int major, minor, version;
gboolean es_use_bgra = FALSE;
paint_context = gdk_surface_get_paint_gl_context (surface, NULL);
@@ -118,16 +117,6 @@ gdk_cairo_draw_from_gl (cairo_t *cr,
return;
}
gdk_gl_context_get_version (paint_context, &major, &minor);
version = major * 100 + minor;
/* TODO: Use glTexSubImage2D() and do a row-by-row copy to replace
* the GL_UNPACK_ROW_LENGTH support
*/
if (gdk_gl_context_get_use_es (paint_context) &&
!(version >= 300 || gdk_gl_context_has_feature (paint_context, GDK_GL_FEATURE_UNPACK_SUBIMAGE)))
return;
/* TODO: avoid reading back non-required data due to dest clip */
image = cairo_surface_create_similar_image (cairo_get_target (cr),
(alpha_size == 0) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32,

View File

@@ -105,9 +105,6 @@
static const GdkDebugKey gdk_gl_feature_keys[] = {
{ "debug", GDK_GL_FEATURE_DEBUG, "GL_KHR_debug" },
{ "unpack-subimage", GDK_GL_FEATURE_UNPACK_SUBIMAGE, "GL_EXT_unpack_subimage" },
{ "half-float", GDK_GL_FEATURE_VERTEX_HALF_FLOAT, "GL_OES_vertex_half_float" },
{ "sync", GDK_GL_FEATURE_SYNC, "GL_ARB_sync" },
{ "base-instance", GDK_GL_FEATURE_BASE_INSTANCE, "GL_ARB_base_instance" },
{ "buffer-storage", GDK_GL_FEATURE_BUFFER_STORAGE, "GL_EXT_buffer_storage" },
};
@@ -1060,16 +1057,9 @@ gdk_gl_context_get_matching_version (GdkGLContext *context,
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
if (api == GDK_GL_API_GL)
{
if (legacy)
min_version = GDK_GL_MIN_GL_LEGACY_VERSION;
else
min_version = GDK_GL_MIN_GL_VERSION;
}
min_version = GDK_GL_MIN_GL_VERSION;
else
{
min_version = GDK_GL_MIN_GLES_VERSION;
}
min_version = GDK_GL_MIN_GLES_VERSION;
if (gdk_gl_version_greater_equal (&priv->required, &min_version))
*out_version = priv->required;
@@ -1592,38 +1582,35 @@ gdk_gl_context_init_memory_flags (GdkGLContext *self)
priv->memory_flags[GDK_MEMORY_G8A8] = GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
#endif
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
/* GLES 3.0.6 spec, table 3.13 */
priv->memory_flags[GDK_MEMORY_G8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_A8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G8A8_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G8A8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8A8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8X8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16_FLOAT] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_A16_FLOAT] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32_FLOAT] |= GDK_GL_FORMAT_USABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT] |= GDK_GL_FORMAT_USABLE;
priv->memory_flags[GDK_MEMORY_A32_FLOAT] |= GDK_GL_FORMAT_USABLE;
/* no changes in GLES 3.1 spec, table 8.13 */
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
{
/* GLES 3.0.6 spec, table 3.13 */
priv->memory_flags[GDK_MEMORY_G8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_A8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G8A8_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G8A8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8A8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8X8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16_FLOAT] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_A16_FLOAT] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32_FLOAT] |= GDK_GL_FORMAT_USABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT] |= GDK_GL_FORMAT_USABLE;
priv->memory_flags[GDK_MEMORY_A32_FLOAT] |= GDK_GL_FORMAT_USABLE;
/* no changes in GLES 3.1 spec, table 8.13 */
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
{
/* GLES 3.2 spec, table 8.10 */
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT] |= GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_A16_FLOAT] |= GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT] |= GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_A32_FLOAT] |= GDK_GL_FORMAT_RENDERABLE;
}
/* GLES 3.2 spec, table 8.10 */
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT] |= GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_A16_FLOAT] |= GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT] |= GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_A32_FLOAT] |= GDK_GL_FORMAT_RENDERABLE;
}
if (epoxy_has_gl_extension ("GL_OES_rgb8_rgba8"))
@@ -1631,64 +1618,55 @@ gdk_gl_context_init_memory_flags (GdkGLContext *self)
priv->memory_flags[GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8A8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
priv->memory_flags[GDK_MEMORY_R8G8B8X8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8X8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
}
if (epoxy_has_gl_extension ("GL_EXT_abgr"))
{
priv->memory_flags[GDK_MEMORY_A8B8G8R8_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_A8B8G8R8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
priv->memory_flags[GDK_MEMORY_X8B8G8R8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_X8B8G8R8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
}
if (epoxy_has_gl_extension ("GL_EXT_texture_format_BGRA8888"))
{
priv->memory_flags[GDK_MEMORY_B8G8R8A8_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_B8G8R8A8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
priv->memory_flags[GDK_MEMORY_B8G8R8X8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_B8G8R8X8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
}
/* Technically, those extensions are supported on GLES2.
* However, GTK uses the wrong format/type pairs with them, so we don't enable them.
*/
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
if (epoxy_has_gl_extension ("GL_EXT_texture_norm16"))
{
if (epoxy_has_gl_extension ("GL_EXT_texture_norm16"))
{
priv->memory_flags[GDK_MEMORY_R16G16B16A16_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16A16] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G16A16_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G16A16] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G16] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_A16] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
}
if (epoxy_has_gl_extension ("GL_OES_texture_half_float"))
{
GdkGLMemoryFlags flags = GDK_GL_FORMAT_USABLE;
if (epoxy_has_gl_extension ("GL_EXT_color_buffer_half_float"))
flags |= GDK_GL_FORMAT_RENDERABLE;
if (epoxy_has_gl_extension ("GL_OES_texture_half_float_linear"))
flags |= GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] |= flags;
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT] |= flags;
/* disabled for now, see https://gitlab.freedesktop.org/mesa/mesa/-/issues/10378 */
priv->memory_flags[GDK_MEMORY_R16G16B16_FLOAT] |= flags & ~GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_A16_FLOAT] |= flags;
}
if (epoxy_has_gl_extension ("GL_OES_texture_float"))
{
GdkGLMemoryFlags flags = GDK_GL_FORMAT_USABLE;
if (epoxy_has_gl_extension ("GL_EXT_color_buffer_float"))
flags |= GDK_GL_FORMAT_RENDERABLE;
if (epoxy_has_gl_extension ("GL_OES_texture_float_linear"))
flags |= GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] |= flags;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT] |= flags;
priv->memory_flags[GDK_MEMORY_R32G32B32_FLOAT] |= flags & ~GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_A32_FLOAT] |= flags;
}
priv->memory_flags[GDK_MEMORY_R16G16B16A16_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16A16] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G16A16_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G16A16] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G16] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_A16] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
}
if (epoxy_has_gl_extension ("GL_OES_texture_half_float"))
{
GdkGLMemoryFlags flags = GDK_GL_FORMAT_USABLE;
if (epoxy_has_gl_extension ("GL_EXT_color_buffer_half_float"))
flags |= GDK_GL_FORMAT_RENDERABLE;
if (epoxy_has_gl_extension ("GL_OES_texture_half_float_linear"))
flags |= GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] |= flags;
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT] |= flags;
/* disabled for now, see https://gitlab.freedesktop.org/mesa/mesa/-/issues/10378 */
priv->memory_flags[GDK_MEMORY_R16G16B16_FLOAT] |= flags & ~GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_A16_FLOAT] |= flags;
}
if (epoxy_has_gl_extension ("GL_OES_texture_float"))
{
GdkGLMemoryFlags flags = GDK_GL_FORMAT_USABLE;
if (epoxy_has_gl_extension ("GL_EXT_color_buffer_float"))
flags |= GDK_GL_FORMAT_RENDERABLE;
if (epoxy_has_gl_extension ("GL_OES_texture_float_linear"))
flags |= GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] |= flags;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT] |= flags;
priv->memory_flags[GDK_MEMORY_R32G32B32_FLOAT] |= flags & ~GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_A32_FLOAT] |= flags;
}
}
@@ -1703,32 +1681,11 @@ gdk_gl_version_init_epoxy (GdkGLVersion *version)
static GdkGLFeatures
gdk_gl_context_check_features (GdkGLContext *context)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
GdkGLFeatures features = 0;
if (gdk_gl_context_get_use_es (context))
{
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)) ||
epoxy_has_gl_extension ("GL_EXT_unpack_subimage"))
features |= GDK_GL_FEATURE_UNPACK_SUBIMAGE;
}
else
{
features |= GDK_GL_FEATURE_UNPACK_SUBIMAGE;
}
if (epoxy_has_gl_extension ("GL_KHR_debug"))
features |= GDK_GL_FEATURE_DEBUG;
if (gdk_gl_context_check_version (context, "3.0", "3.0") ||
epoxy_has_gl_extension ("GL_OES_vertex_half_float"))
features |= GDK_GL_FEATURE_VERTEX_HALF_FLOAT;
if (gdk_gl_context_check_version (context, "3.2", "3.0") ||
epoxy_has_gl_extension ("GL_ARB_sync") ||
epoxy_has_gl_extension ("GL_APPLE_sync"))
features |= GDK_GL_FEATURE_SYNC;
if (gdk_gl_context_check_version (context, "4.2", "9.9") ||
epoxy_has_gl_extension ("GL_EXT_base_instance") ||
epoxy_has_gl_extension ("GL_ARB_base_instance"))
@@ -2262,59 +2219,26 @@ gdk_gl_context_import_dmabuf (GdkGLContext *self,
gdk_dmabuf_egl_init (display);
if (gdk_dmabuf_formats_contains (display->egl_dmabuf_formats, dmabuf->fourcc, dmabuf->modifier))
if (gdk_dmabuf_formats_contains (display->egl_internal_formats, dmabuf->fourcc, dmabuf->modifier))
{
/* This is the path for modern drivers that support modifiers */
if (!gdk_dmabuf_formats_contains (display->egl_external_formats, dmabuf->fourcc, dmabuf->modifier))
{
texture_id = gdk_gl_context_import_dmabuf_for_target (self,
width, height,
dmabuf,
GL_TEXTURE_2D);
if (texture_id == 0)
{
GDK_DISPLAY_DEBUG (display, DMABUF,
"Import of %dx%d %.4s:%#" G_GINT64_MODIFIER "x dmabuf failed",
width, height,
(char *) &dmabuf->fourcc, dmabuf->modifier);
return 0;
}
GDK_DISPLAY_DEBUG (display, DMABUF,
"Imported %dx%d %.4s:%#" G_GINT64_MODIFIER "x dmabuf as GL_TEXTURE_2D texture",
width, height,
(char *) &dmabuf->fourcc, dmabuf->modifier);
*external = FALSE;
return texture_id;
}
if (!gdk_gl_context_get_use_es (self))
{
GDK_DISPLAY_DEBUG (display, DMABUF,
"Can't import external_only %.4s:%#" G_GINT64_MODIFIER "x outside of GLES",
(char *) &dmabuf->fourcc, dmabuf->modifier);
return 0;
}
texture_id = gdk_gl_context_import_dmabuf_for_target (self,
width, height,
dmabuf,
GL_TEXTURE_EXTERNAL_OES);
GL_TEXTURE_2D);
if (texture_id == 0)
{
GDK_DISPLAY_DEBUG (display, DMABUF,
"Import of external_only %dx%d %.4s:%#" G_GINT64_MODIFIER "x dmabuf failed",
"Import of %dx%d %.4s:%#" G_GINT64_MODIFIER "x dmabuf failed",
width, height,
(char *) &dmabuf->fourcc, dmabuf->modifier);
return 0;
}
GDK_DISPLAY_DEBUG (display, DMABUF,
"Imported %dx%d %.4s:%#" G_GINT64_MODIFIER "x dmabuf as GL_TEXTURE_EXTERNAL_OES texture",
"Imported %dx%d %.4s:%#" G_GINT64_MODIFIER "x dmabuf as GL_TEXTURE_2D texture",
width, height,
(char *) &dmabuf->fourcc, dmabuf->modifier);
*external = TRUE;
*external = FALSE;
return texture_id;
}
else
@@ -2471,3 +2395,277 @@ out:
return FALSE;
#endif
}
static gboolean
gdk_gl_context_find_format (GdkGLContext *self,
GdkMemoryAlpha alpha,
GLint gl_format,
GLint gl_type,
GdkMemoryFormat *out_format)
{
GdkMemoryFormat format;
for (format = 0; format < GDK_MEMORY_N_FORMATS; format++)
{
GLint q_internal_format, q_internal_srgb_format;
GLenum q_format, q_type;
GLint q_swizzle[4];
if (gdk_memory_format_alpha (format) != alpha)
continue;
if (!(gdk_gl_context_get_format_flags (self, format) & GDK_GL_FORMAT_RENDERABLE))
continue;
gdk_memory_format_gl_format (format,
gdk_gl_context_get_use_es (self),
&q_internal_format,
&q_internal_srgb_format,
&q_format,
&q_type,
q_swizzle);
if (q_format != gl_format || q_type != gl_type)
continue;
*out_format = format;
return TRUE;
}
return FALSE;
}
void
gdk_gl_context_download (GdkGLContext *self,
GLuint tex_id,
GdkMemoryFormat tex_format,
GdkColorState *tex_color_state,
guchar *dest_data,
gsize dest_stride,
GdkMemoryFormat dest_format,
GdkColorState *dest_color_state,
gsize width,
gsize height)
{
gsize expected_stride;
GLint gl_internal_format, gl_internal_srgb_format;
GLenum gl_format, gl_type;
GLint gl_swizzle[4];
expected_stride = width * gdk_memory_format_bytes_per_pixel (dest_format);
if (!gdk_gl_context_get_use_es (self) &&
((gdk_gl_context_get_format_flags (self, tex_format) & GDK_GL_FORMAT_USABLE) == GDK_GL_FORMAT_USABLE))
{
gdk_memory_format_gl_format (tex_format,
gdk_gl_context_get_use_es (self),
&gl_internal_format, &gl_internal_srgb_format,
&gl_format, &gl_type, gl_swizzle);
if (dest_stride == expected_stride &&
dest_format == tex_format)
{
glGetTexImage (GL_TEXTURE_2D,
0,
gl_format,
gl_type,
dest_data);
gdk_memory_convert_color_state (dest_data,
dest_stride,
dest_format,
dest_color_state,
tex_color_state,
width,
height);
}
else
{
gsize stride = width * gdk_memory_format_bytes_per_pixel (tex_format);
guchar *pixels = g_malloc_n (stride, height);
glPixelStorei (GL_PACK_ALIGNMENT, 1);
glGetTexImage (GL_TEXTURE_2D,
0,
gl_format,
gl_type,
pixels);
gdk_memory_convert (dest_data,
dest_stride,
dest_format,
dest_color_state,
pixels,
stride,
tex_format,
tex_color_state,
width,
height);
g_free (pixels);
}
}
else
{
GdkMemoryFormat actual_format;
GLenum gl_read_format, gl_read_type;
GLuint fbo;
glGenFramebuffers (1, &fbo);
glBindFramebuffer (GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_id, 0);
if (gdk_gl_context_check_version (self, "4.3", "3.1"))
{
GLint read_format, read_type;
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_FORMAT, &read_format);
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_TYPE, &read_type);
if (gdk_gl_context_find_format (self, gdk_memory_format_alpha (tex_format), read_format, read_type, &actual_format))
{
gl_read_format = read_format;
gl_read_type = read_type;
}
else
{
actual_format = gdk_memory_depth_get_format (gdk_memory_format_get_depth (tex_format, FALSE));
if (gdk_memory_format_alpha (tex_format) == GDK_MEMORY_ALPHA_STRAIGHT)
actual_format = gdk_memory_format_get_straight (actual_format);
gdk_memory_format_gl_format (actual_format,
gdk_gl_context_get_use_es (self),
&gl_internal_format, &gl_internal_srgb_format,
&gl_read_format, &gl_read_type, gl_swizzle);
}
}
else
{
actual_format = gdk_memory_depth_get_format (gdk_memory_format_get_depth (tex_format, FALSE));
if (gdk_memory_format_alpha (tex_format) == GDK_MEMORY_ALPHA_STRAIGHT)
actual_format = gdk_memory_format_get_straight (actual_format);
gdk_memory_format_gl_format (actual_format,
gdk_gl_context_get_use_es (self),
&gl_internal_format, &gl_internal_srgb_format,
&gl_read_format, &gl_read_type, gl_swizzle);
}
if (dest_format == actual_format &&
(dest_stride == expected_stride))
{
glReadPixels (0, 0,
width, height,
gl_read_format,
gl_read_type,
dest_data);
gdk_memory_convert_color_state (dest_data,
dest_stride,
dest_format,
dest_color_state,
tex_color_state,
width,
height);
}
else
{
gsize actual_bpp = gdk_memory_format_bytes_per_pixel (actual_format);
gsize stride = actual_bpp * width;
guchar *pixels = g_malloc_n (stride, height);
glPixelStorei (GL_PACK_ALIGNMENT, 1);
glReadPixels (0, 0,
width, height,
gl_read_format,
gl_read_type,
pixels);
/* Fix up gles inadequacies */
if (gl_read_format == GL_RGBA &&
gl_read_type == GL_UNSIGNED_BYTE &&
(tex_format == GDK_MEMORY_G8A8 ||
tex_format == GDK_MEMORY_G8A8_PREMULTIPLIED ||
tex_format == GDK_MEMORY_G8 ||
tex_format == GDK_MEMORY_A8))
{
for (unsigned int y = 0; y < height; y++)
{
for (unsigned int x = 0; x < width; x++)
{
guchar *data = &pixels[y * stride + x * actual_bpp];
if (tex_format == GDK_MEMORY_G8A8 ||
tex_format == GDK_MEMORY_G8A8_PREMULTIPLIED)
{
data[3] = data[1];
data[1] = data[0];
data[2] = data[0];
}
else if (tex_format == GDK_MEMORY_G8)
{
data[1] = data[0];
data[2] = data[0];
data[3] = 0xff;
}
else if (tex_format == GDK_MEMORY_A8)
{
data[3] = data[0];
data[0] = 0;
data[1] = 0;
data[2] = 0;
}
}
}
}
if (gl_read_format == GL_RGBA &&
gl_read_type == GL_UNSIGNED_SHORT &&
(tex_format == GDK_MEMORY_G16A16 ||
tex_format == GDK_MEMORY_G16A16_PREMULTIPLIED ||
tex_format == GDK_MEMORY_G16 ||
tex_format == GDK_MEMORY_A16))
{
for (unsigned int y = 0; y < height; y++)
{
for (unsigned int x = 0; x < width; x++)
{
guint16 *data = (guint16 *) &pixels[y * stride + x * actual_bpp];
if (tex_format == GDK_MEMORY_G16A16 ||
tex_format == GDK_MEMORY_G16A16_PREMULTIPLIED)
{
data[3] = data[1];
data[1] = data[0];
data[2] = data[0];
}
else if (tex_format == GDK_MEMORY_G16)
{
data[1] = data[0];
data[2] = data[0];
data[3] = 0xffff;
}
else if (tex_format == GDK_MEMORY_A16)
{
data[3] = data[0];
data[0] = 0;
data[1] = 0;
data[2] = 0;
}
}
}
}
gdk_memory_convert (dest_data,
dest_stride,
dest_format,
dest_color_state,
pixels,
stride,
actual_format,
tex_color_state,
width,
height);
g_free (pixels);
}
glBindFramebuffer (GL_FRAMEBUFFER, 0);
glDeleteFramebuffers (1, &fbo);
}
}

View File

@@ -29,11 +29,8 @@ G_BEGIN_DECLS
typedef enum {
GDK_GL_FEATURE_DEBUG = 1 << 0,
GDK_GL_FEATURE_UNPACK_SUBIMAGE = 1 << 1,
GDK_GL_FEATURE_VERTEX_HALF_FLOAT = 1 << 2,
GDK_GL_FEATURE_SYNC = 1 << 3,
GDK_GL_FEATURE_BASE_INSTANCE = 1 << 4,
GDK_GL_FEATURE_BUFFER_STORAGE = 1 << 5,
GDK_GL_FEATURE_BASE_INSTANCE = 1 << 1,
GDK_GL_FEATURE_BUFFER_STORAGE = 1 << 2,
} GdkGLFeatures;
typedef enum {
@@ -133,16 +130,16 @@ void gdk_gl_context_set_version (GdkGLContext
const GdkGLVersion *version);
void gdk_gl_context_set_is_legacy (GdkGLContext *context,
gboolean is_legacy);
gboolean gdk_gl_context_check_gl_version (GdkGLContext *context,
gboolean gdk_gl_context_check_gl_version (GdkGLContext *self,
const GdkGLVersion *gl_version,
const GdkGLVersion *gles_version);
static inline gboolean
gdk_gl_context_check_version (GdkGLContext *context,
gdk_gl_context_check_version (GdkGLContext *self,
const char *gl_version,
const char *gles_version)
{
return gdk_gl_context_check_gl_version (context,
return gdk_gl_context_check_gl_version (self,
gl_version ? &GDK_GL_VERSION_STRING (gl_version) : NULL,
gles_version ? &GDK_GL_VERSION_STRING (gles_version) : NULL);
}
@@ -181,6 +178,17 @@ gboolean gdk_gl_context_has_vertex_arrays (GdkGLContext
double gdk_gl_context_get_scale (GdkGLContext *self);
void gdk_gl_context_download (GdkGLContext *self,
GLuint tex_id,
GdkMemoryFormat tex_format,
GdkColorState *tex_color_state,
guchar *dest_data,
gsize dest_stride,
GdkMemoryFormat dest_format,
GdkColorState *dest_color_state,
gsize width,
gsize height);
guint gdk_gl_context_import_dmabuf (GdkGLContext *self,
int width,
int height,

View File

@@ -151,276 +151,26 @@ struct _Download
gsize stride;
};
static gboolean
gdk_gl_texture_find_format (GdkGLContext *context,
GdkMemoryAlpha alpha,
GLint gl_format,
GLint gl_type,
GdkMemoryFormat *out_format)
{
GdkMemoryFormat format;
for (format = 0; format < GDK_MEMORY_N_FORMATS; format++)
{
GLint q_internal_format, q_internal_srgb_format;
GLenum q_format, q_type;
GLint q_swizzle[4];
if (gdk_memory_format_alpha (format) != alpha)
continue;
if (!(gdk_gl_context_get_format_flags (context, format) & GDK_GL_FORMAT_RENDERABLE))
continue;
gdk_memory_format_gl_format (format,
gdk_gl_context_get_use_es (context),
&q_internal_format,
&q_internal_srgb_format,
&q_format,
&q_type,
q_swizzle);
if (q_format != gl_format || q_type != gl_type)
continue;
*out_format = format;
return TRUE;
}
return FALSE;
}
static inline void
static void
gdk_gl_texture_do_download (GdkGLTexture *self,
GdkGLContext *context,
gpointer download_)
{
GdkTexture *texture = GDK_TEXTURE (self);
GdkMemoryFormat format;
gsize expected_stride;
Download *download = download_;
GLint gl_internal_format, gl_internal_srgb_format;
GLenum gl_format, gl_type;
GLint gl_swizzle[4];
format = gdk_texture_get_format (texture),
expected_stride = texture->width * gdk_memory_format_bytes_per_pixel (download->format);
if (!gdk_gl_context_get_use_es (context) &&
((gdk_gl_context_get_format_flags (context, format) & GDK_GL_FORMAT_USABLE) == GDK_GL_FORMAT_USABLE))
{
gdk_memory_format_gl_format (format,
gdk_gl_context_get_use_es (context),
&gl_internal_format, &gl_internal_srgb_format,
&gl_format, &gl_type, gl_swizzle);
if (download->stride == expected_stride &&
download->format == format)
{
glGetTexImage (GL_TEXTURE_2D,
0,
gl_format,
gl_type,
download->data);
gdk_memory_convert_color_state (download->data,
download->stride,
download->format,
download->color_state,
texture->color_state,
texture->width,
texture->height);
}
else
{
gsize stride = texture->width * gdk_memory_format_bytes_per_pixel (format);
guchar *pixels = g_malloc_n (stride, texture->height);
glPixelStorei (GL_PACK_ALIGNMENT, 1);
glGetTexImage (GL_TEXTURE_2D,
0,
gl_format,
gl_type,
pixels);
gdk_memory_convert (download->data,
download->stride,
download->format,
download->color_state,
pixels,
stride,
format,
texture->color_state,
texture->width,
texture->height);
g_free (pixels);
}
}
else
{
GdkMemoryFormat actual_format;
GLenum gl_read_format, gl_read_type;
GLuint fbo;
glGenFramebuffers (1, &fbo);
glBindFramebuffer (GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->id, 0);
if (gdk_gl_context_check_version (context, "4.3", "3.1"))
{
GLint read_format, read_type;
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_FORMAT, &read_format);
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_TYPE, &read_type);
if (gdk_gl_texture_find_format (context, gdk_memory_format_alpha (format), read_format, read_type, &actual_format))
{
gl_read_format = read_format;
gl_read_type = read_type;
}
else
{
actual_format = gdk_memory_depth_get_format (gdk_memory_format_get_depth (format, FALSE));
if (gdk_memory_format_alpha (format) == GDK_MEMORY_ALPHA_STRAIGHT)
actual_format = gdk_memory_format_get_straight (actual_format);
gdk_memory_format_gl_format (actual_format,
gdk_gl_context_get_use_es (context),
&gl_internal_format, &gl_internal_srgb_format,
&gl_read_format, &gl_read_type, gl_swizzle);
}
}
else
{
actual_format = gdk_memory_depth_get_format (gdk_memory_format_get_depth (format, FALSE));
if (gdk_memory_format_alpha (format) == GDK_MEMORY_ALPHA_STRAIGHT)
actual_format = gdk_memory_format_get_straight (actual_format);
gdk_memory_format_gl_format (actual_format,
gdk_gl_context_get_use_es (context),
&gl_internal_format, &gl_internal_srgb_format,
&gl_read_format, &gl_read_type, gl_swizzle);
}
if (download->format == actual_format &&
(download->stride == expected_stride))
{
glReadPixels (0, 0,
texture->width, texture->height,
gl_read_format,
gl_read_type,
download->data);
gdk_memory_convert_color_state (download->data,
download->stride,
download->format,
download->color_state,
texture->color_state,
texture->width,
texture->height);
}
else
{
gsize actual_bpp = gdk_memory_format_bytes_per_pixel (actual_format);
gsize stride = actual_bpp * texture->width;
guchar *pixels = g_malloc_n (stride, texture->height);
glPixelStorei (GL_PACK_ALIGNMENT, 1);
glReadPixels (0, 0,
texture->width, texture->height,
gl_read_format,
gl_read_type,
pixels);
/* Fix up gles inadequacies */
if (gl_read_format == GL_RGBA &&
gl_read_type == GL_UNSIGNED_BYTE &&
(format == GDK_MEMORY_G8A8 ||
format == GDK_MEMORY_G8A8_PREMULTIPLIED ||
format == GDK_MEMORY_G8 ||
format == GDK_MEMORY_A8))
{
for (unsigned int y = 0; y < texture->height; y++)
{
for (unsigned int x = 0; x < texture->width; x++)
{
guchar *data = &pixels[y * stride + x * actual_bpp];
if (format == GDK_MEMORY_G8A8 ||
format == GDK_MEMORY_G8A8_PREMULTIPLIED)
{
data[3] = data[1];
data[1] = data[0];
data[2] = data[0];
}
else if (format == GDK_MEMORY_G8)
{
data[1] = data[0];
data[2] = data[0];
data[3] = 0xff;
}
else if (format == GDK_MEMORY_A8)
{
data[3] = data[0];
data[0] = 0;
data[1] = 0;
data[2] = 0;
}
}
}
}
if (gl_read_format == GL_RGBA &&
gl_read_type == GL_UNSIGNED_SHORT &&
(format == GDK_MEMORY_G16A16 ||
format == GDK_MEMORY_G16A16_PREMULTIPLIED ||
format == GDK_MEMORY_G16 ||
format == GDK_MEMORY_A16))
{
for (unsigned int y = 0; y < texture->height; y++)
{
for (unsigned int x = 0; x < texture->width; x++)
{
guint16 *data = (guint16 *) &pixels[y * stride + x * actual_bpp];
if (format == GDK_MEMORY_G16A16 ||
format == GDK_MEMORY_G16A16_PREMULTIPLIED)
{
data[3] = data[1];
data[1] = data[0];
data[2] = data[0];
}
else if (format == GDK_MEMORY_G16)
{
data[1] = data[0];
data[2] = data[0];
data[3] = 0xffff;
}
else if (format == GDK_MEMORY_A16)
{
data[3] = data[0];
data[0] = 0;
data[1] = 0;
data[2] = 0;
}
}
}
}
gdk_memory_convert (download->data,
download->stride,
download->format,
download->color_state,
pixels,
stride,
actual_format,
texture->color_state,
texture->width,
texture->height);
g_free (pixels);
}
glBindFramebuffer (GL_FRAMEBUFFER, 0);
glDeleteFramebuffers (1, &fbo);
}
gdk_gl_context_download (context,
gdk_gl_texture_get_id (self),
gdk_texture_get_format (texture),
gdk_texture_get_color_state (texture),
download->data,
download->stride,
download->format,
download->color_state,
gdk_texture_get_width (texture),
gdk_texture_get_height (texture));
}
static void
gdk_gl_texture_download (GdkTexture *texture,
GdkMemoryFormat format,
@@ -527,8 +277,7 @@ gdk_gl_texture_new_from_builder (GdkGLTextureBuilder *builder,
self->id = gdk_gl_texture_builder_get_id (builder);
GDK_TEXTURE (self)->format = gdk_gl_texture_builder_get_format (builder);
self->has_mipmap = gdk_gl_texture_builder_get_has_mipmap (builder);
if (gdk_gl_context_has_feature (self->context, GDK_GL_FEATURE_SYNC))
self->sync = gdk_gl_texture_builder_get_sync (builder);
self->sync = gdk_gl_texture_builder_get_sync (builder);
self->destroy = destroy;
self->data = data;

View File

@@ -33,13 +33,9 @@ G_BEGIN_DECLS
/* Minimum OpenGL versions supported by GTK.
* Backends should make sure to never create a context of a previous version.
*
* The macros refer to OpenGL; OpenGL with OPENGL_COMPATIBILITY_PROFILE_BIT as
* OPENGL_PROFILE_MASK; and OpenGL ES respectively
*/
#define GDK_GL_MIN_GL_VERSION GDK_GL_VERSION_INIT (3, 2)
#define GDK_GL_MIN_GL_LEGACY_VERSION GDK_GL_VERSION_INIT (3, 0)
#define GDK_GL_MIN_GLES_VERSION GDK_GL_VERSION_INIT (2, 0)
#define GDK_GL_MIN_GL_VERSION GDK_GL_VERSION_INIT (3, 3)
#define GDK_GL_MIN_GLES_VERSION GDK_GL_VERSION_INIT (3, 0)
typedef struct _GdkGLVersion GdkGLVersion;
@@ -60,9 +56,6 @@ static const GdkGLVersion supported_gl_versions[] = {
GDK_GL_VERSION_INIT (4, 1),
GDK_GL_VERSION_INIT (4, 0),
GDK_GL_VERSION_INIT (3, 3),
GDK_GL_VERSION_INIT (3, 2),
GDK_GL_VERSION_INIT (3, 1),
GDK_GL_VERSION_INIT (3, 0),
GDK_GL_VERSION_INIT (0, 0)
};
@@ -71,7 +64,6 @@ static const GdkGLVersion supported_gles_versions[] = {
GDK_GL_VERSION_INIT (3, 2),
GDK_GL_VERSION_INIT (3, 1),
GDK_GL_VERSION_INIT (3, 0),
GDK_GL_VERSION_INIT (2, 0),
GDK_GL_VERSION_INIT (0, 0)
};

View File

@@ -2479,8 +2479,8 @@ void
gdk_memory_convert_color_state (guchar *data,
gsize stride,
GdkMemoryFormat format,
GdkColorState *src_cs,
GdkColorState *dest_cs,
GdkColorState *src_color_state,
GdkColorState *dest_color_state,
gsize width,
gsize height)
{
@@ -2488,24 +2488,24 @@ gdk_memory_convert_color_state (guchar *data,
.data = data,
.stride = stride,
.format = format,
.src_cs = src_cs,
.dest_cs = dest_cs,
.src_cs = src_color_state,
.dest_cs = dest_color_state,
.width = width,
.height = height,
};
if (gdk_color_state_equal (src_cs, dest_cs))
if (gdk_color_state_equal (src_color_state, dest_color_state))
return;
if (format == GDK_MEMORY_B8G8R8A8_PREMULTIPLIED &&
src_cs == GDK_COLOR_STATE_SRGB &&
dest_cs == GDK_COLOR_STATE_SRGB_LINEAR)
src_color_state == GDK_COLOR_STATE_SRGB &&
dest_color_state == GDK_COLOR_STATE_SRGB_LINEAR)
{
gdk_parallel_task_run (gdk_memory_convert_color_state_srgb_to_srgb_linear, &mc);
}
else if (format == GDK_MEMORY_B8G8R8A8_PREMULTIPLIED &&
src_cs == GDK_COLOR_STATE_SRGB_LINEAR &&
dest_cs == GDK_COLOR_STATE_SRGB)
src_color_state == GDK_COLOR_STATE_SRGB_LINEAR &&
dest_color_state == GDK_COLOR_STATE_SRGB)
{
gdk_parallel_task_run (gdk_memory_convert_color_state_srgb_linear_to_srgb, &mc);
}

View File

@@ -96,11 +96,11 @@ const char * gdk_memory_format_get_name (GdkMemoryFormat
void gdk_memory_convert (guchar *dest_data,
gsize dest_stride,
GdkMemoryFormat dest_format,
GdkColorState *src_cs,
GdkColorState *dest_cs,
const guchar *src_data,
gsize src_stride,
GdkMemoryFormat src_format,
GdkColorState *dest_cs,
GdkColorState *src_cs,
gsize width,
gsize height);
void gdk_memory_convert_color_state (guchar *data,

View File

@@ -1405,9 +1405,6 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
{
G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
uint32_t i, j, k;
const char *override;
gboolean list_devices;
int first, last;
GdkVulkanFeatures skip_features;
uint32_t n_devices = 0;
@@ -1425,9 +1422,6 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
devices = g_newa (VkPhysicalDevice, n_devices);
GDK_VK_CHECK(vkEnumeratePhysicalDevices, display->vk_instance, &n_devices, devices);
first = 0;
last = n_devices;
skip_features = gdk_parse_debug_var ("GDK_VULKAN_DISABLE",
"GDK_VULKAN_DISABLE can be set to a list of Vulkan features to disable.\n",
gsk_vulkan_feature_keys,
@@ -1435,35 +1429,7 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
if (skip_features & GDK_VULKAN_FEATURE_YCBCR)
skip_features |= GDK_VULKAN_FEATURE_DMABUF;
override = g_getenv ("GDK_VULKAN_DEVICE");
list_devices = FALSE;
if (override)
{
if (g_strcmp0 (override, "list") == 0)
list_devices = TRUE;
else
{
gint64 device_idx;
GError *error2 = NULL;
if (!g_ascii_string_to_signed (override, 10, 0, G_MAXINT, &device_idx, &error2))
{
g_warning ("Failed to parse %s: %s", "GDK_VULKAN_DEVICE", error2->message);
g_error_free (error2);
device_idx = -1;
}
if (device_idx < 0 || device_idx >= n_devices)
g_warning ("%s value out of range, ignoring", "GDK_VULKAN_DEVICE");
else
{
first = device_idx;
last = first + 1;
}
}
}
if (list_devices || GDK_DISPLAY_DEBUG_CHECK (display, VULKAN))
if (GDK_DISPLAY_DEBUG_CHECK (display, VULKAN))
{
for (i = 0; i < n_devices; i++)
{
@@ -1514,7 +1480,7 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
}
}
for (i = first; i < last; i++)
for (i = 0; i < n_devices; i++)
{
GdkVulkanFeatures features, device_features;
uint32_t n_queue_props;
@@ -1530,7 +1496,7 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
{
if (queue_props[j].queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT swapchain_maintenance1_features = {
VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT swapchain_maintenance1_features = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SWAPCHAIN_MAINTENANCE_1_FEATURES_EXT,
.swapchainMaintenance1 = VK_TRUE,
};
@@ -1945,19 +1911,20 @@ gdk_vulkan_init_dmabuf (GdkDisplay *display)
g_warn_if_fail (modifier_props.drmFormatModifierCount < sizeof (modifier_list));
for (j = 0; j < modifier_props.drmFormatModifierCount; j++)
{
gboolean advertise = modifier_list[j].drmFormatModifier != DRM_FORMAT_MOD_LINEAR;
GDK_DISPLAY_DEBUG (display, DMABUF,
"Vulkan supports dmabuf format %.4s::%016llx with %u planes and features 0x%x",
"Vulkan %s dmabuf format %.4s::%016"G_GINT64_MODIFIER"x with %u planes and features 0x%x",
advertise ? "advertises" : "supports",
(char *) &fourcc,
(long long unsigned) modifier_list[j].drmFormatModifier,
modifier_list[j].drmFormatModifier,
modifier_list[j].drmFormatModifierPlaneCount,
modifier_list[j].drmFormatModifierTilingFeatures);
if (modifier_list[j].drmFormatModifier == DRM_FORMAT_MOD_LINEAR)
continue;
gdk_dmabuf_formats_builder_add_format (vulkan_builder,
fourcc,
modifier_list[j].drmFormatModifier);
if (advertise)
gdk_dmabuf_formats_builder_add_format (vulkan_builder,
fourcc,
modifier_list[j].drmFormatModifier);
}
}

View File

@@ -63,8 +63,8 @@ print ";\n\n";
print <<EOT;
typedef struct {
guint keyval;
guint offset;
unsigned int keyval;
unsigned int offset;
} gdk_key;
static const gdk_key gdk_keys_by_keyval[] = {

View File

@@ -208,21 +208,16 @@ wl_cursor_destroy(struct wl_cursor *cursor)
static struct wl_cursor *
wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
const char *name,
unsigned int size,
unsigned int scale)
unsigned int size)
{
char *path;
XcursorImages *images;
struct wl_cursor *cursor;
struct cursor_image *image;
int i, nbytes;
unsigned int load_size;
int load_scale = 1;
load_size = size * scale;
path = g_strconcat (theme->path, "/", name, NULL);
images = xcursor_load_images (path, load_size);
images = xcursor_load_images (path, size);
if (!images)
{
@@ -230,14 +225,6 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
return NULL;
}
if (images->images[0]->width != load_size ||
images->images[0]->height != load_size)
{
xcursor_images_destroy (images);
images = xcursor_load_images (path, size);
load_scale = scale;
}
g_free (path);
cursor = malloc(sizeof *cursor);
@@ -255,7 +242,7 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
}
cursor->name = strdup(name);
cursor->size = load_size;
cursor->size = images->images[0]->size;
for (i = 0; i < images->nimage; i++) {
image = malloc(sizeof *image);
@@ -265,10 +252,10 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
image->theme = theme;
image->buffer = NULL;
image->image.width = images->images[i]->width * load_scale;
image->image.height = images->images[i]->height * load_scale;
image->image.hotspot_x = images->images[i]->xhot * load_scale;
image->image.hotspot_y = images->images[i]->yhot * load_scale;
image->image.width = images->images[i]->width;
image->image.height = images->images[i]->height;
image->image.hotspot_x = images->images[i]->xhot;
image->image.hotspot_y = images->images[i]->yhot;
image->image.delay = images->images[i]->delay;
nbytes = image->image.width * image->image.height * 4;
@@ -278,24 +265,9 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
break;
}
if (load_scale == 1) {
/* copy pixels to shm pool */
memcpy(theme->pool->data + image->offset,
images->images[i]->pixels, nbytes);
}
else {
/* scale image up while copying it */
for (int y = 0; y < image->image.height; y++) {
char *p = theme->pool->data + image->offset + y * image->image.width * 4;
char *q = ((char *)images->images[i]->pixels) + (y / load_scale) * images->images[i]->width * 4;
for (int x = 0; x < image->image.width; x++) {
p[4 * x] = q[4 * (x/load_scale)];
p[4 * x + 1] = q[4 * (x/load_scale) + 1];
p[4 * x + 2] = q[4 * (x/load_scale) + 2];
p[4 * x + 3] = q[4 * (x/load_scale) + 3];
}
}
}
/* copy pixels to shm pool */
memcpy(theme->pool->data + image->offset,
images->images[i]->pixels, nbytes);
cursor->images[i] = (struct wl_cursor_image *) image;
}
cursor->image_count = i;
@@ -316,12 +288,11 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
static void
load_cursor(struct wl_cursor_theme *theme,
const char *name,
unsigned int size,
unsigned int scale)
unsigned int size)
{
struct wl_cursor *cursor;
cursor = wl_cursor_create_from_xcursor_images(theme, name, size, scale);
cursor = wl_cursor_create_from_xcursor_images(theme, name, size);
if (cursor) {
theme->cursor_count++;
@@ -405,12 +376,12 @@ wl_cursor_theme_destroy(struct wl_cursor_theme *theme)
struct wl_cursor *
wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
const char *name,
unsigned int scale)
float scale)
{
unsigned int i;
unsigned int size;
size = theme->size * scale;
size = ceil (theme->size * scale);
for (i = 0; i < theme->cursor_count; i++) {
if (size == theme->cursors[i]->size &&
@@ -418,11 +389,10 @@ wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
return theme->cursors[i];
}
load_cursor (theme, name, theme->size, scale);
load_cursor (theme, name, size);
if (i < theme->cursor_count) {
if (size == theme->cursors[i]->size &&
strcmp (name, theme->cursors[theme->cursor_count - 1]->name) == 0)
if (strcmp (name, theme->cursors[theme->cursor_count - 1]->name) == 0)
return theme->cursors[theme->cursor_count - 1];
}

View File

@@ -59,7 +59,7 @@ wl_cursor_theme_destroy(struct wl_cursor_theme *theme);
struct wl_cursor *
wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
const char *name,
unsigned int scale);
float scale);
struct wl_buffer *
wl_cursor_image_get_buffer(struct wl_cursor_image *image);

View File

@@ -402,6 +402,38 @@ _XcursorFindBestSize (XcursorFileHeader *fileHeader,
if (fileHeader->tocs[n].type != XCURSOR_IMAGE_TYPE)
continue;
thisSize = fileHeader->tocs[n].subtype;
if (thisSize == size)
{
bestSize = size;
nsizes++;
}
}
if (bestSize)
goto done;
for (n = 0; n < fileHeader->ntoc; n++)
{
if (fileHeader->tocs[n].type != XCURSOR_IMAGE_TYPE)
continue;
thisSize = fileHeader->tocs[n].subtype;
if (thisSize == 2 * size)
{
bestSize = 2 * size;
nsizes++;
}
}
if (bestSize)
goto done;
for (n = 0; n < fileHeader->ntoc; n++)
{
if (fileHeader->tocs[n].type != XCURSOR_IMAGE_TYPE)
continue;
thisSize = fileHeader->tocs[n].subtype;
if (thisSize < size)
continue;
if (!bestSize || dist (thisSize, size) < dist (bestSize, size))
{
bestSize = thisSize;
@@ -410,6 +442,25 @@ _XcursorFindBestSize (XcursorFileHeader *fileHeader,
else if (thisSize == bestSize)
nsizes++;
}
if (bestSize)
goto done;
for (n = 0; n < fileHeader->ntoc; n++)
{
if (fileHeader->tocs[n].type != XCURSOR_IMAGE_TYPE)
continue;
thisSize = fileHeader->tocs[n].subtype;
if (!bestSize || dist (thisSize, size) < dist (bestSize, size))
{
bestSize = thisSize;
nsizes = 1;
}
else if (thisSize == bestSize)
nsizes++;
}
done:
*nsizesp = nsizes;
return bestSize;
}

View File

@@ -119,7 +119,7 @@ name_fallback (const char *name)
static struct wl_cursor *
gdk_wayland_cursor_load_for_name (GdkWaylandDisplay *display_wayland,
struct wl_cursor_theme *theme,
int scale,
float scale,
const char *name)
{
struct wl_cursor *c;
@@ -156,7 +156,6 @@ struct wl_buffer *
_gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
GdkCursor *cursor,
double desired_scale,
gboolean use_viewporter,
guint image_index,
int *hotspot_x,
int *hotspot_y,
@@ -169,7 +168,6 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
if (gdk_cursor_get_name (cursor))
{
struct wl_cursor *c;
int scale_factor;
if (g_str_equal (gdk_cursor_get_name (cursor), "none"))
{
@@ -179,12 +177,11 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
return NULL;
}
scale_factor = (int) ceil (desired_scale);
c = gdk_wayland_cursor_load_for_name (display,
display->cursor_theme,
scale_factor,
desired_scale,
gdk_cursor_get_name (cursor));
if (c && c->image_count > 0)
{
struct wl_cursor_image *image;
@@ -199,22 +196,12 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
image = c->images[image_index];
*width = display->cursor_theme_size;
*height = display->cursor_theme_size;
*scale = image->width / (double) *width;
*hotspot_x = image->hotspot_x / scale_factor;
*hotspot_y = image->hotspot_y / scale_factor;
*scale = c->size / (double) display->cursor_theme_size;
if (*scale != scale_factor && !use_viewporter)
{
g_warning (G_STRLOC " cursor image size (%d) not an integer "
"multiple of theme size (%d)", image->width, *width);
*width = image->width;
*height = image->height;
*hotspot_x = image->hotspot_x;
*hotspot_y = image->hotspot_y;
*scale = 1;
}
*width = image->width / *scale;
*height = image->height / *scale;
*hotspot_x = image->hotspot_x / *scale;
*hotspot_y = image->hotspot_y / *scale;
return wl_cursor_image_get_buffer (image);
}
@@ -260,14 +247,11 @@ from_texture:
}
else
{
if (!use_viewporter)
*scale = ceil (desired_scale);
else
*scale = desired_scale;
*scale = desired_scale;
texture = gdk_cursor_get_texture_for_size (cursor,
display->cursor_theme_size,
*scale,
desired_scale,
width,
height,
hotspot_x,
@@ -302,7 +286,6 @@ from_texture:
return _gdk_wayland_cursor_get_buffer (display,
gdk_cursor_get_fallback (cursor),
desired_scale,
use_viewporter,
image_index,
hotspot_x, hotspot_y,
width, height,

View File

@@ -265,22 +265,17 @@ gdk_wayland_device_update_surface_cursor (GdkDevice *device)
guint next_image_index, next_image_delay;
gboolean retval = G_SOURCE_REMOVE;
GdkWaylandTabletData *tablet;
gboolean use_viewport = FALSE;
tablet = gdk_wayland_seat_find_tablet (seat, device);
if (pointer->pointer_surface_viewport &&
g_getenv ("USE_POINTER_VIEWPORT"))
use_viewport = TRUE;
if (pointer->cursor)
{
buffer = _gdk_wayland_cursor_get_buffer (GDK_WAYLAND_DISPLAY (seat->display),
pointer->cursor,
pointer->current_output_scale,
use_viewport,
pointer->cursor_image_index,
&x, &y, &w, &h, &scale);
&x, &y, &w, &h,
&scale);
}
else
{
@@ -317,7 +312,7 @@ gdk_wayland_device_update_surface_cursor (GdkDevice *device)
if (buffer)
{
wl_surface_attach (pointer->pointer_surface, buffer, 0, 0);
if (use_viewport)
if (pointer->pointer_surface_viewport)
{
wp_viewport_set_source (pointer->pointer_surface_viewport,
wl_fixed_from_int (0),
@@ -326,8 +321,6 @@ gdk_wayland_device_update_surface_cursor (GdkDevice *device)
wl_fixed_from_double (h * scale));
wp_viewport_set_destination (pointer->pointer_surface_viewport, w, h);
}
else if (wl_surface_get_version (pointer->pointer_surface) >= WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION)
wl_surface_set_buffer_scale (pointer->pointer_surface, scale);
wl_surface_damage (pointer->pointer_surface, 0, 0, w, h);
wl_surface_commit (pointer->pointer_surface);
}

View File

@@ -43,6 +43,7 @@
#include "gdksurface-wayland.h"
#include "gdksurfaceprivate.h"
#include "gdkdeviceprivate.h"
#include "gdkdevice-wayland-private.h"
#include "gdkkeysprivate.h"
#include "gdkprivate-wayland.h"
#include "gdkcairocontext-wayland.h"
@@ -1130,6 +1131,9 @@ get_cursor_theme (GdkWaylandDisplay *display_wayland,
return theme;
}
if (strcmp (name, "default") != 0)
return get_cursor_theme (display_wayland, "default", size);
/* This may fall back to builtin cursors */
return wl_cursor_theme_create ("/usr/share/icons/default/cursors", size, display_wayland->shm);
}
@@ -1160,6 +1164,7 @@ _gdk_wayland_display_set_cursor_theme (GdkDisplay *display,
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY(display);
struct wl_cursor_theme *theme;
GList *seats;
g_assert (display_wayland);
g_assert (display_wayland->shm);
@@ -1189,6 +1194,15 @@ _gdk_wayland_display_set_cursor_theme (GdkDisplay *display,
g_free (display_wayland->cursor_theme_name);
display_wayland->cursor_theme_name = g_strdup (name);
display_wayland->cursor_theme_size = size;
seats = gdk_display_list_seats (display);
for (GList *l = seats; l; l = l->next)
{
GdkSeat *seat = l->data;
gdk_wayland_device_update_surface_cursor (gdk_seat_get_pointer (seat));
}
g_list_free (seats);
}
struct wl_cursor_theme *
@@ -1216,7 +1230,7 @@ _gdk_wayland_display_load_cursor_theme (GdkWaylandDisplay *display_wayland)
if (gdk_display_get_setting (GDK_DISPLAY (display_wayland), "gtk-cursor-theme-size", &v))
size = g_value_get_int (&v);
else
size = 32;
size = 24;
g_value_unset (&v);
g_value_init (&v, G_TYPE_STRING);
@@ -1750,7 +1764,7 @@ static TranslationEntry translations[] = {
{ FALSE, "org.gnome.desktop.interface", "gtk-theme", "gtk-theme-name" , G_TYPE_STRING, { .s = "Adwaita" } },
{ FALSE, "org.gnome.desktop.interface", "icon-theme", "gtk-icon-theme-name", G_TYPE_STRING, { .s = "gnome" } },
{ FALSE, "org.gnome.desktop.interface", "cursor-theme", "gtk-cursor-theme-name", G_TYPE_STRING, { .s = "Adwaita" } },
{ FALSE, "org.gnome.desktop.interface", "cursor-size", "gtk-cursor-theme-size", G_TYPE_INT, { .i = 32 } },
{ FALSE, "org.gnome.desktop.interface", "cursor-size", "gtk-cursor-theme-size", G_TYPE_INT, { .i = 24 } },
{ FALSE, "org.gnome.desktop.interface", "font-name", "gtk-font-name", G_TYPE_STRING, { .s = "Cantarell 11" } },
{ FALSE, "org.gnome.desktop.interface", "cursor-blink", "gtk-cursor-blink", G_TYPE_BOOLEAN, { .b = TRUE } },
{ FALSE, "org.gnome.desktop.interface", "cursor-blink-time", "gtk-cursor-blink-time", G_TYPE_INT, { .i = 1200 } },
@@ -1994,6 +2008,7 @@ init_settings (GdkDisplay *display)
g_debug ("Received no portal settings");
g_clear_pointer (&iter, g_variant_iter_free);
g_clear_pointer (&ret, g_variant_unref);
g_clear_object (&display_wayland->settings_portal);
goto fallback;
}

View File

@@ -117,7 +117,6 @@ void gdk_wayland_display_system_bell (GdkDisplay *display,
struct wl_buffer *_gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
GdkCursor *cursor,
double desired_scale,
gboolean use_viewporter,
guint image_index,
int *hotspot_x,
int *hotspot_y,

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