Compare commits

...

456 Commits

Author SHA1 Message Date
Matthias Clasen fbd5da7302 inspector: Show the session management protocol
We want the inspector to show all the protocols that we use.
2024-09-02 13:19:43 -04:00
Carlos Garnacho 0b8a9503df gtk: Add blurb for session management in GtkApplication docs 2024-09-02 13:19:43 -04:00
Carlos Garnacho fb1ece0b05 demo: Restore Node Editor window state
Save the session id, and restore the main window position
from previous runs.
2024-09-02 13:19:43 -04:00
Matthias Clasen e2ff30a8dd demo: Redo the application demo
A big point of this demo was to show state saving. So make it use
the new session saving protocol, which can take care of the window
size and state. We still save the color on the client side.
2024-09-02 13:19:43 -04:00
Carlos Garnacho a4ae4e3c64 demo: Make gtk4-demo use session management
Use it as an example of what is to be expected to make your
application windows restore-able between executions, the session
ID is preserved in a setting between runs, so that it's fed to
the GtkApplication on startup. The actual session ID used is likewise
always stored in this setting, for later runs.

The main window gets an identifier within the session, so that its
state may be restored when first mapped.
2024-09-02 13:19:43 -04:00
Carlos Garnacho 2b59509ff2 gtk: Hook up session management in wayland's GtkApplication impl
Make this application impl object handle the integration with the
private GDK/wayland API, so this is hooked up to the xdg-session-management-v1
protocol.

As a nicety, use GtkWindow::hide-on-close to determine whether a window
should be remembered, or immediately forgotten by the session after being
closed.
2024-09-02 13:19:43 -04:00
Carlos Garnacho a4ad19c934 gtk: Add GtkApplication property for session IDs
This API has two "phases":
- An initialization call, calling gtk_application_set_session_id() to
  set a session identifier from previous runs.
- A post-initialization call, to retrieve the session identifier in
  use for this session. This may be the same identifier than previously
  specified, if the session could be recovered, or a brand new one if
  the session is created from scratch.

The storage of this session identifier is left up to the applications,
and could be material for later GNOME session integration with
persistent save states.
2024-09-02 13:19:43 -04:00
Carlos Garnacho f79c181c56 gtk: Add GtkWindow property for session identifiers
This identifier will be used for session management purposes,
and is meant to be stable across executions.
2024-09-02 13:19:43 -04:00
Carlos Garnacho adfc69d501 wayland: Add API to restore GdkToplevels from an ID in the session
Any toplevel may be referred by an ID, that will be used by the compositor
to restore window state for it. Add the glue so that the upper layers
may restore a toplevel from one of these IDs.
2024-09-02 13:19:43 -04:00
Carlos Garnacho a06c412f5f wayland: Get/initialize a xdg_session_v1 object
Add the internal API to let the upper layers define a session
ID (e.g. saved from previous runs), and retrieve the session ID
eventually used (e.g. in case the session is created from scratch).
2024-09-02 13:19:43 -04:00
Carlos Garnacho 27894be982 wayland: Require the xdg-session-management protocol
This is not upstreamed yet, so use an internal xx-session-management
protocol that we can eventually move to use the upstream protocol.
2024-09-02 12:24:35 -04:00
Matthias Clasen 96346f1050 gdk: Add a debug key to disable session management
Add

GDK_DISABLE=session-mgmt

to stop GDK from using the Wayland session management protocol.
2024-09-02 12:24:35 -04:00
Matthias Clasen 5f1ec18550 Merge branch 'popover-menu-resize' into 'main'
MenuSectionBox: Increase priority of separator sync function

Closes #5166

See merge request GNOME/gtk!6699
2024-09-01 14:04:07 +00:00
Matthias Clasen 6b5c5714e5 Merge branch 'gdksurface-broadway-fix' into 'main'
gdk: Add missed compute_size and request_layout vfunc to GdkBroadwaySurface

Closes #4527

See merge request GNOME/gtk!4277
2024-09-01 13:48:22 +00:00
Maxim Zakharov 9a8e5b07ae gdk: Add missed compute_size and request_layout vfunc to GdkBroadwaySurface 2024-09-01 13:48:22 +00:00
Matthias Clasen 3f4cf65686 Merge branch 'fix_model_button_states' into 'main'
a11y: Set expanded states properly when switching to a submenu

See merge request GNOME/gtk!7305
2024-09-01 11:59:47 +00:00
Lukáš Tyrychtr 345eca1efe a11y: Set expanded states properly when switching to a submenu 2024-09-01 11:59:47 +00:00
Matthias Clasen 166afbf8e8 Merge branch 'ebassi/a11y-event-listeners' into 'main'
a11y: Add missing value free function

See merge request GNOME/gtk!7677
2024-09-01 11:20:56 +00:00
Matthias Clasen 9120d1c834 Merge branch 'proper_focus_during_popover_cascaded_popdown' into 'main'
a11y: Ensure the focus lands on the correct element during cascaded popover popdown

See merge request GNOME/gtk!7318
2024-08-31 23:09:04 +00:00
Matthias Clasen 083f9e7723 Merge branch 'numeric-spinbutton-no-emoji' into 'main'
spinbutton: No emoji for numeric input

See merge request GNOME/gtk!7676
2024-08-31 23:04:56 +00:00
Emmanuele Bassi a0cfc6c404 a11y: Turn criticals into debugging messages
It seems we can get spurious de-registrations, so let's avoid spamming
the logs, and also avoid crashes from applications whose maintainer
decided to turn all critical warnings into assertions.
2024-08-31 23:41:21 +01:00
Matthias Clasen edc50c85ef spinbutton: No emoji for numeric input
Continuing from cfc871f031, when a spin button is in numeric mode,
set the no-emoji input hint, since Emoji aren't useful in numeric
input.
2024-08-31 18:23:49 -04:00
Matthias Clasen 4794bc3db6 Remove duplicate semicolon 2024-08-31 22:16:25 +00:00
Lukáš Tyrychtr 2299c02639 a11y: Ensure the focus lands on the correct element during cascaded popover popdown
Previously it ended on the immediate parent of the lowest level popover,
which was not good, as it very likely was some even already hidden widget, or
at least, the a11y machinery thought so.
2024-08-31 22:16:25 +00:00
Emmanuele Bassi ae13a82a9a a11y: Add missing value free function
We allocate the reference counter, so we need to free it.
2024-08-31 22:40:16 +01:00
Matthias Clasen 6c88713f82 Merge branch 'emoji-multi-click' into 'main'
emojichooser: Avoid extra work

Closes #6336

See merge request GNOME/gtk!7675
2024-08-31 21:34:29 +00:00
Matthias Clasen 5c6fedae17 emojichooser: Avoid extra work
When selecting an emoji in the recent section, there is no need
to add it to the recent section again. This avoids a sequence of
unfortunate events, where we reconstruct the entire recent section,
thereby removing the focus child, causing the focus to revert to
the entry, causing the entry to select the entire text. In the
case of Ctrl-clicking to select multiple Emoji, the effect is that
the section Emoji will replace the entire entry text, which is
suprising and unintended.

Fixes: #6336
2024-08-31 16:28:20 -04:00
Hugo Carvalho 5faa1c3d6e Update Portuguese translation 2024-08-31 20:14:46 +00:00
Matthias Clasen 074bcd33be Merge branch 'x11-input-setup-mess' into 'main'
x11: Cosmetics

Closes #6840

See merge request GNOME/gtk!7674
2024-08-31 16:57:55 +00:00
Matthias Clasen 5b6b42b5a9 x11: Fix initialization mess
When prepare_gl fails in the right way (or the wrong way?), we
end up creating the leader window twice, and as a side effect,
creating two instances of the "Virtual core pointer" device, which
is bad news for grabs.

Fixes: #6840
2024-08-31 11:28:52 -04:00
Matthias Clasen ae8a06cdca x11: Cosmetics
Don't return FALSE from a function returning a pointer.
2024-08-31 11:28:52 -04:00
Piotr Drąg c9bbf5820b Update Polish translation 2024-08-31 15:00:38 +02:00
Simon McVittie bb0b764172 Merge branch 'wip/smcv/bug6971' into 'main'
testsuite: Add a suite for tests that require /dev/udmabuf

See merge request GNOME/gtk!7671
2024-08-31 11:53:32 +00:00
Matthias Clasen ae8e9ef650 Merge branch 'vulkan-dnd-offset' into 'main'
vulkan: Use wl_surface_offset

Closes #6972

See merge request GNOME/gtk!7673
2024-08-31 11:47:53 +00:00
Matthias Clasen 8df7ff75bb Merge branch 'radio_role_for_check_button_groups' into 'main'
a11y: Set the correct role for check button groups

See merge request GNOME/gtk!6551
2024-08-31 11:20:16 +00:00
Matthias Clasen bbfd8e0e89 vulkan: Use wl_surface_offset
Call wl_surface_offset in end_frame to apply the offset for drag
surfaces. This matches what the GL draw context already does, and
it fixes drag surfaces jumping at the beginning of the drag.

Fixes: #6972
2024-08-31 07:15:08 -04:00
Matthias Clasen 467212877f Merge branch 'wip/smcv/css-endian' into 'main'
CSS: Fix test failures on 64-bit big-endian machines

See merge request GNOME/gtk!7672
2024-08-31 11:04:45 +00:00
Simon McVittie 204b8857a1 testsuite: Add a suite for tests that require /dev/udmabuf
On GTK's official upstream CI, all Linux runners are meant to have
/dev/udmabuf available, so this should pass. On developer machines or
downstream build environments, this can't be guaranteed (not all kernel
configurations offer that device, and on those that do, an autobuilder
might not have access to it) so make it possible to skip this with
`--no-suite=needs-udmabuf`.

Any future tests that rely on /dev/udmabuf (as opposed to using it for
optional better coverage if available, like replay-node does) can be
aded to the same suite.

Signed-off-by: Simon McVittie <smcv@debian.org>
2024-08-31 10:22:49 +01:00
Simon McVittie a524524ffd gtkcssprovider: Fix sorting of custom property IDs on 64-bit big-endian
This function is used to sort a GPtrArray of "pointers" which are
actually GINT_TO_POINTER (id), so a and b are pointers to pointer-sized
quantities.

Previously it was assuming that both were int-sized quantities,
dereferencing them to get the first sizeof(int) bytes, and then
redundantly casting those bytes to int. However, on a 64-bit big-endian
platform, the first few bytes of a larger-than-int quantity are the
most significant part, in practice 0, causing an out-of-bounds array
access and a crash. This was visible in the
`gtk:css / parser variables.css` automated test.

Bug-Debian: https://bugs.debian.org/1079546
Signed-off-by: Simon McVittie <smcv@debian.org>
2024-08-31 02:26:57 +01:00
Simon McVittie 3ef1f448a3 gtkcssvariableset: Fix listing IDs on big-endian machines
Previously this code assumed that if we have an int stored in a hash
table via GINT_TO_POINTER, we can retrieve the pointer value and treat
its first sizeof(int) bytes as an item to append to a GArray of int.

However, on a 64-bit big-endian system, the first sizeof(int)
bytes of the pointer will be zero, which is not a valid ID for a
GtkCssCustomPropertyPool, causing an out-of-bounds array access and
a crash. This was visible in the `gtk:css / style` automated test.

Bug-Debian: https://bugs.debian.org/1079546
Signed-off-by: Simon McVittie <smcv@debian.org>
2024-08-31 02:04:00 +01:00
Matthias Clasen a5df8f2f35 Merge branch 'dead-hamza-yay' into 'main'
Update a script slightly

Closes #6968

See merge request GNOME/gtk!7670
2024-08-31 00:14:25 +00:00
Emmanuele Bassi b56a8c7f88 Merge branch 'wip/fina/accessible-atspi-fix-error-message' into 'main'
a11y: Consistently use list type for errormessage relation

See merge request GNOME/gtk!7528
2024-08-31 00:08:52 +00:00
Fina Wilke 649782b547 a11y: Consistently use list type for errormessage relation
This more closely matches the spec. This is an API break, however the
atspi backend already assumed that this was a list, and would throw
criticals whenever this relation was set. Therefore it can be assumed
that this relation was not previously in active use.
2024-08-30 20:22:59 +00:00
Matthias Clasen 97245e9baa Merge branch 'ebassi/lazier-a11y' into 'main'
a11y: Watch EventListenerRegistered/Deregistered signals

See merge request GNOME/gtk!7298
2024-08-30 20:17:17 +00:00
Matthias Clasen 0f3c27c8a5 composetable: Handle dead_hamza
A new dead key has been invented.

Fixes: #6968
2024-08-30 16:10:20 -04:00
Matthias Clasen 3273637179 Update keyname tables 2024-08-30 16:03:40 -04:00
Matthias Clasen 1eaa0e9b74 gdkkeysyms.h: Regenerate for libX11 1.8.10 2024-08-30 15:52:58 -04:00
Matthias Clasen 28d1bce2d4 Update a script slightly
Make gdkkeysyms-update.pl use #pragma once, as our headers
do nowadays.
2024-08-30 15:52:14 -04:00
Emmanuele Bassi b8072d8562 a11y: Add a check for sandboxed accessibility bus
When sandboxed, the accessibility bus needs a recent version of Flatpak
and its D-Bus proxy in order to relay event registrations.
2024-08-30 14:24:55 +01:00
Luca Bacci da9886d822 Merge branch 'fix-gdk-win32-display-name' into 'main'
GDK/Win32: Fix gdk_display_get_name()

See merge request GNOME/gtk!7664
2024-08-30 12:32:16 +00:00
Matthias Clasen 747f2e5af6 Merge branch 'demos-window-icons' into 'main'
demos: Set icon for the windows

See merge request GNOME/gtk!7661
2024-08-30 11:14:18 +00:00
Matthias Clasen aeb3ee0969 Merge branch 'update-on-print-comboentry-change' into 'main'
printeroptionwidget: Update on combo-entry change

Closes #6782

See merge request GNOME/gtk!7532
2024-08-30 11:11:55 +00:00
Benjamin Otte e248f1a4b5 Merge branch 'wip/otte/compare-render' into 'main'
Bring compare-render into 21st century

See merge request GNOME/gtk!7648
2024-08-30 11:00:36 +00:00
Daniel Rusek ff9fe6857f Update Czech translation 2024-08-30 09:49:04 +00:00
Emmanuele Bassi 58f2d3fbe7 a11y: Add reference counting to event listeners
Event listeners can register themselves multiple times, and deregister
themselves as well. We need to remove an event listener only if it
dropped all its events.
2024-08-30 09:27:39 +01:00
Emmanuele Bassi d9f75581be a11y: Get event listeners on root registration
We ask the AT-SPI registry for event listeners already registered when
connecting the root object, in case an AT is running.
2024-08-30 09:27:39 +01:00
Emmanuele Bassi 307efe2172 a11y: Do not emit event signals if there are no listeners
Now that we track event listeners, we can skip the accessibility event
emission altogether if we know nothing is on the other side.
2024-08-30 09:27:39 +01:00
Emmanuele Bassi 4ea4dc9176 a11y: Watch EventListenerRegistered/Deregistered signals
Assistive technologies using AT-SPI typically register themselves on the
accessibility bus through the org.a11y.atspi.Registry.RegisterEvent
method, which will emit the EventListenerRegistered signal. We can use
that signal (and its corresponding EventListenerDeregistered sibling) to
know whether there is at least an AT on the other side of the
accessibility bus.
2024-08-30 09:27:39 +01:00
Benjamin Otte fa25015e8c compare-render: Appease clang and MSVC
clang wants consts not initialized from consts.

MSVC can't deal with arrays in initializers.
2024-08-30 06:28:58 +02:00
Benjamin Otte 296b6b1ed5 compare-render: Make the test runner generic
Instead of manually running each of the tests, use a loop and just
invoke the test runner.
2024-08-30 06:28:58 +02:00
Benjamin Otte b88fe301be compare-render: Run clip tests using new runner
This requires adding infrastructure to generate per-test data, so that
the random clip rect can be computed and reused for both test and
reference generation.

So add this infrastructure.
2024-08-30 06:28:58 +02:00
Benjamin Otte ffd836e6f4 compare-render: Run replay tests using new runner 2024-08-30 06:28:58 +02:00
Benjamin Otte 457cf66d0d compare-render: Run mask tests using new runner 2024-08-30 06:28:58 +02:00
Benjamin Otte 36765745a1 compare-render: Run rotate tests using new runner 2024-08-30 06:28:58 +02:00
Benjamin Otte 46c19a3d28 compare-render: Run repeat tests using new runner 2024-08-30 06:28:58 +02:00
Benjamin Otte 6cf928eb6c compare-render: Run flip tests using new runner 2024-08-30 06:28:58 +02:00
Benjamin Otte a0d076f01a compare-render: Run plain tests using new runner
Extend the runner so NULL is accepted as a method to create
reference/test, in which case the unmodified original will be used.
2024-08-30 06:28:58 +02:00
Benjamin Otte 37c744759c compare-render: Add a generic test runner
... and port the colorflip test.

This is so we can factor out generic parts of the code. This allows
making changes easier to those parts, like if we want to introduce
rules for what colorstates and memory depths to do diffs in.
2024-08-30 06:28:58 +02:00
Benjamin Otte 277a05eb8c compare-render: Use consistent naming for files
Instead of the adverb, use the verb term. That matches the argument
passed on the cmdline, so only one string is necessary.
2024-08-30 06:28:58 +02:00
Chun-wei Fan 0376e4668c GDK/Win32: Fix gdk_display_get_name()
We switched to using the Unicode (UTF-16) versions of the Windows API by
default, so we also obtain the display name in UTF-16 form as well.

This updates the implementation in the Windows backend so that we
properly acquire the names that we need in UTF-16, and then convert the
results to UTF-8, which is what we use in GTK/GLib.
2024-08-30 08:47:01 +08:00
Changwoo Ryu 9d5652de64 Update Korean translation 2024-08-29 23:29:49 +00:00
Matthias Clasen bb109b5d9e Merge branch 'matthiasc/for-main' into 'main'
docs: Mention that Broadway is an experiment

See merge request GNOME/gtk!7665
2024-08-29 22:52:39 +00:00
Benjamin Otte d630ddd182 compare-render: Pick colorstate from reference when comparing
When comparing textures, always pick the colorstate from the reference
texture. This allows us to define what color state we expect.

For now, there's no check that the color states are equal, because they
don't really have to be as long as the pixels are.
2024-08-29 20:34:23 +02:00
Benjamin Otte e268041a42 reftest-compare: Respect color states when diffing
Always pick the color state from texture1 and download the data and
generate the diff in that color state.

That now means the order of the 2 arguments matters.
2024-08-29 20:34:23 +02:00
Benjamin Otte f9cbeeeedc reftest-compare: Compare high depth images in high depth
I first tried porting everything to float, but it turns out that that
makes a compare-render run (with all 1520 tests succeeding) 9s slower
so I decided to keep the existing U8 code.

A side benefit is that saving the diff to PNG will continue creating
U8 PNGs.
2024-08-29 20:34:23 +02:00
Benjamin Otte 62542f836f compare-render: Create rotated reference without gdk-pixbuf
We use the renderer to create the reference for the rotate test by
applying the same rotate transform to the reference image instead of the
tested node.

This is somewhat suboptimal because they run very similar codepaths, but
this method works with high bit depth content and different colorstates

This concludes the port away from gdk-pixbuf and means that all rendered
content and reference images can now use high bit depth and colorstates.
2024-08-29 20:34:23 +02:00
Benjamin Otte 6d4c74fdce compare-render: Create masked reference without gdk-pixbuf
We use the renderer to create the reference for the mask test by
rendering the reference clipped.
2024-08-29 20:34:23 +02:00
Benjamin Otte 3dac4a01c6 compare-render: Create colorflipped reference without gdk-pixbuf
We use the renderer to create the reference for the colorflip test by
applying the same colorflip matrix to the reference image instead of the
tested node.

This is somewhat suboptimal because they run very similar codepaths, but
this method works with high bit depth content and different colorstates
2024-08-29 20:34:23 +02:00
Benjamin Otte f598ec00f5 compare-render: Create clipped reference without gdk-pixbuf
We use the renderer to create the reference for the clip test by
applying the same clip node to the reference image instead of the
tested node.

This is somewhat suboptimal because they run very similar codepaths, but
this method works with high bit depth content and different colorstates
2024-08-29 20:34:23 +02:00
Benjamin Otte 6fc18f4b37 compare-render: Create flipped reference without gdk-pixbuf
We use the renderer to create the reference for the flip test by
applying the same transform node to the reference image instead of the
tested node.

This is somewhat suboptimal because they run very similar codepaths, but
this method works with high bit depth content and different colorstates
and the gdk-pixbuf method does not.
2024-08-29 20:34:23 +02:00
Benjamin Otte 8c9f16fa7a compare-render: Create repeated reference without gdk-pixbuf
We use the renderer to create the reference for the repeat test by
applying the same repeat node to the reference image instead of the
tested node.

This is somewhat suboptimal because they run very similar codepaths, but
this method works with high bit depth content and different colorstates
and the gdk-pixbuf method does not.
2024-08-29 20:34:23 +02:00
Benjamin Otte 001ca0a982 compare-render: Split test variant name from extension name
This is preparation for further patches where we want to use a common
codepath for all variants.
2024-08-29 20:34:23 +02:00
Benjamin Otte b23c0248ba compare-render: Don't load reference file twice
Instead, convert from texture to pixbuf.

Ultimately, we want to avoid pixbufs entirely, but we're not there yet.
2024-08-29 20:34:23 +02:00
Benjamin Otte c4c352facc compare-render: Use TAP for the test 2024-08-29 20:34:23 +02:00
Benjamin Otte 30af6d1159 compare-render: Turn into a real test
Use g_test_run() like any other test.
2024-08-29 20:34:23 +02:00
Benjamin Otte 1fac3fe44e compare-render: Compare to reference texture
There's no need to render the original node and compare to its result,
we know that that is equal to the reference image.

Avoids duplicate renderings.
2024-08-29 20:34:23 +02:00
Benjamin Otte 8ac6c08f00 compare-render: Create the reference texture at startup
This allows exiting early when it doesn't exist.
2024-08-29 20:34:23 +02:00
Benjamin Otte 5b62f29b5e compare-render: Rename variables
They conflict with the next commit otherwise.
2024-08-29 20:34:23 +02:00
Benjamin Otte 817cfb09f8 compare-render: Failing to load an image is a failure 2024-08-29 20:34:23 +02:00
Benjamin Otte 8da478ab34 testsuite: Disable a bunch of tests on the GL renderer
We want to generate reference images with the renderers and the GL
renderer can't deal with textures well enough to generate these
reference images.
2024-08-29 20:34:20 +02:00
Matthias Clasen 8d866c5980 docs: Mention that Broadway is an experiment 2024-08-29 07:35:17 -04:00
Jordi Mas 467e622778 Update Catalan translation 2024-08-29 07:13:12 +02:00
Benjamin Otte aa81df921b testsuite: Correct values for red
The value used was for rec2020 (9/14/0/1), not rec2100-pq (9/16/0/1).
2024-08-29 03:01:30 +02:00
Benjamin Otte 328020b241 Merge branch 'wip/otte/for-main' into 'main'
gl: Fix initial EGL context creation on X11

Closes #6964

See merge request GNOME/gtk!7663
2024-08-29 00:36:19 +00:00
Benjamin Otte 41cd0c6f13 gl: Fix initial EGL context creation on X11
After commit 447bc18c48 EGL on X11 broke.

But the handling of the GL context also was quite awkward because it was
unclear who was responsible for ensuring it got reset.

Change that by making gdk_gl_context_clear_current_if_surface() return
the context (with a reference because it might be the last reference) it
had unset, so that after changing EGL properties the code that caused
the clearing can re-make it current.

This moves the responsibility to the actual code that is dealing with
updating properties and frees the outer layers of code from that task.

And that means the X11 EGL code doesn't need to care and the code in the
Wayland backend that did care can be removed.

Related: !7662
Fixes: #6964 on X11
2024-08-29 01:31:47 +02:00
Benjamin Otte db02abe54e Merge branch 'wip/otte/to-make-current-or-not-make-current' into 'main'
wayland: Rework how we handle EGLWindows

Closes #6964

See merge request GNOME/gtk!7662
2024-08-28 18:14:03 +00:00
Benjamin Otte 447bc18c48 wayland: Rework how we handle EGLWindows
This essentially reverts the changes from
c230546a2c but implies new semantics.

Namely, surface-attached contexts can now be bound to EGL_NO_SURFACE if
the windowing system isn't ready yet.

It is the task of the windowing system to make sure the context is
properly rebound when the contents become available.
We ensure this by checking in begin_frame() if we created the EGL window
and if we did, we make_current(). This works because creating the EGL
window creates the EGL surface and that does a clear_current(), so this
is always going to have the desired effect of re-making the current
context.

It is very convoluted though.

Fixes: #6964
Related: https://gitlab.freedesktop.org/mesa/mesa/-/issues/11784
2024-08-28 19:09:45 +02:00
Balló György 283c66251b demos: Set icon for the windows 2024-08-28 17:02:44 +02:00
Luca Bacci 63b68d2f5e Merge branch 'gdk-win32-incremental-rendering-fixes' into 'main'
GdkWin32: Incremental rendering fixes

See merge request GNOME/gtk!7655
2024-08-28 09:30:29 +00:00
Marek Kašík 7e09a5648a Merge branch gtk:main into update-on-print-comboentry-change 2024-08-28 09:12:42 +00:00
Lukáš Tyrychtr 4a0b833548 Apply some review feedback
Namely be sure to set the new role of the widget in all cases
and do it always, even when we need to recreate the AT context.
2024-08-28 10:42:17 +02:00
Lukáš Tyrychtr 86bec01640 a11y: Set the correct role for check button groups
Up-until now, when a group of check boxes was created, they were
still presented as checkboxes, even they semantically were radio buttons.

Note that this approach will not always work, because we're not recreating the
AT context, but it works for the usual pattern where the group is set during
object construction
2024-08-28 10:27:46 +02:00
Matthias Clasen b07a2a968d Merge branch 'wayland-destroy-ordering' into 'main'
wayland: Fix an ordering problem

Closes #6965

See merge request GNOME/gtk!7658
2024-08-28 01:14:45 +00:00
Benjamin Otte 997d553520 Merge branch 'wip/corey/file-chooser-select' into 'main'
Implement set_selection in GtkSingleSelection

See merge request GNOME/gtk!6376
2024-08-28 00:24:51 +00:00
Corey Berla 8eb05850cb single-selection: Don't allow unselecting with autoselect
According to the documentation, when autoselect is TRUE it will
"will disallow unselecting the current item".
2024-08-27 21:18:56 +00:00
Corey Berla 98eaec99ee gtksingleselection: Implement unselect_all
The default implementation of unselect_all calls
set_selection, which SingleSelection does not have
an implementation for (it's unclear what it would
do with multiple selections).  Add a straightforward
implementation for unselect_all.
2024-08-27 21:18:56 +00:00
Matthias Clasen 8fb946f6e8 Merge branch 'scale-hotfix' into 'main'
theme: Fix positioning of scale values (hotfix!)

See merge request GNOME/gtk!7656
2024-08-27 21:07:40 +00:00
Matthias Clasen a10670c991 wayland: Fix an ordering problem
When setting an event queue on a proxy, we should not destroy
the queue before the proxy.

May fix: #6965
2024-08-27 16:35:46 -04:00
Danial Behzadi 48f347e62b Update Persian translation 2024-08-27 10:34:00 +00:00
Matthijs Velsink ed1c047cf2 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 04:47:49 +02:00
Matthias Clasen ea9c2a72d9 Post-release version bump 2024-08-26 19:55:03 -04:00
Matthias Clasen 15edfe4ffa 4.15.6 2024-08-26 19:26:14 -04:00
Benjamin Otte c2698e2be9 Merge branch 'wip/otte/for-main' into 'main'
gpu: Fix memleak in GL dmabuf export

See merge request GNOME/gtk!7652
2024-08-26 21:08:48 +00:00
Benjamin Otte 0defdc4af5 gpu: Plug fd leak in fallback path
If we can't construct a dmabuf texture, we need to clear the dmabuf fd.
2024-08-26 20:31:08 +02:00
Benjamin Otte ea9b47f1b6 gpu: Use common cleanup function
Just simple cleanup, both functions do the same thing.
2024-08-26 20:31:08 +02:00
Benjamin Otte 65c8320a32 gpu: Fix fd leak in GL dmabuf export
The texture ID is not deleted on dmabuf export; a copy is made, the
GskGpuImage retains ownership.

However when doing GL export, the texture *does* take ownership, so we
need the stealing semantics for that case.
2024-08-26 20:31:08 +02:00
Matthias Clasen a7afde2e7d Merge branch 'scale-fixes-2' into 'main'
scale: Fix two more drawing/sizing issues

Closes #5171 and #6639

See merge request GNOME/gtk!7654
2024-08-26 18:04:27 +00:00
Matthias Clasen a876a829e4 Merge branch 'scale-fixes' into 'main'
scale: (Re)fix value alignment again (reverting !6935)

Closes #5171 and #6639

See merge request GNOME/gtk!7651
2024-08-26 18:00:20 +00:00
Luca Bacci f4bd883003 GdkWin32: Try to call _gdk_surface_update_size() only when the size actually changed
Otherwise we adapt Vulkan and OpenGL swap chains a lot and we effectively
disable incremental rendering.

Note that the fix is not complete.
2024-08-26 17:05:19 +02:00
Luca Bacci 0fcdadc531 GdkWin32GLContextWGL: Use the previous frames paint regions kept by GdkGLContext
We do this because:

 a) The parent class (GdkGLContext) already stores the paint regions of
    previous frames, no need to do the same.
 b) The painted region passed to end_frame () includes the backbuffer's
    damage region, so it's not really what we want.

This also fixes a leak of cairo_region_t that I introduced by mistake
in !7418
2024-08-26 17:05:13 +02:00
Matthijs Velsink d58b545ffb scale: Don't apply borders twice for value
The measured size of the range already includes borders that the scale
calculates. This includes the drawn value. So in the measurement of
scale, the size of the value shouldn't just be added to the size of the
scale, as then the size is effectively added twice.

To fix this, we first measure the minimum size of the range. Then, we
determine the minimum size of our scale. Only then do we set the minimum
size to maximum of those two values.
2024-08-26 13:20:21 +02:00
Matthijs Velsink 8ca299e82b scale: Fix GTK_POS_TOP marks and value order
If both marks are set on top, and the value is drawn on top, the value
should be drawn outside the marks for a horizontal scale.

Currently, that order is incorrect, with the marks shifted up and the
value drawn between the slider and the marks.

This fixes that order.
2024-08-26 13:04:23 +02:00
Scrambled 777 a231a2114a Update Hindi translation 2024-08-26 06:03:28 +00:00
Matthias Clasen ab41a549f8 Merge branch 'app_menubar_a11y_label' into 'main'
applicationwindow: set menubar a11y label

See merge request GNOME/gtk!7640
2024-08-25 23:45:23 +00:00
Matthijs Velsink a9997a3af6 scale: Always align value with the trough
We can get the position of the trough from the parent GtkRange class,
and can therefore align directly to that. There is no need to add
symmetry, which can always be added in CSS if needed.

Fixes #5171, #6639
2024-08-25 19:41:25 +02:00
Matthijs Velsink 6d86b16dbe scale: Refactor value allocation logic slightly
This only makes the value allocation logic easier to understand, but
doesn't change anything, apart from not mixing integer and floating
operations anymore which can give a warning under some compiler
settings.
2024-08-25 19:37:38 +02:00
Matthijs Velsink 779d32747d Revert "Merge branch 'scalefix' into 'main'"
This reverts commit 2799632c02, reversing
changes made to 154035e76f.

That MR tried to fix #5171, but by doing a forced symmetry it introduced
another issue for users on Libadwaita, see #6639.

The logic can be much simplified, as the next commits show.
2024-08-25 19:23:54 +02:00
Asier Sarasua Garmendia 83b387e782 Update Basque translation 2024-08-25 06:01:05 +00:00
Benjamin Otte b41fe2e093 Merge branch 'wip/otte/slow-down' into 'main'
CI: Reduce max number of tests to 8/4

See merge request GNOME/gtk!7649
2024-08-25 03:50:54 +00:00
Benjamin Otte 93573218d4 CI: Reduce max number of tests to 8/4
CI is hitting various limits after we started out with 32. In
particular, the default runners hit 90s test timeouts.

And the asan runner runs into max threads limits, so reduce that one to
4 tests max.
2024-08-25 04:57:11 +02:00
Matthias Clasen 076968dc1e Merge branch 'ci-do-less-work' into 'main'
compare-render: Do less work for replay

See merge request GNOME/gtk!7647
2024-08-25 01:39:52 +00:00
Matthias Clasen 5e6cf622e3 compare-render: Do less work for replay
We don't need to render the node, we have a reference image.
2024-08-24 20:11:32 -04:00
Matthias Clasen 90c65e3611 Merge branch 'wip/otte/ci-fixes' into 'main'
CI improvements

See merge request GNOME/gtk!7639
2024-08-24 20:25:30 +00:00
Matthias Clasen afe75aedc2 Merge branch 'dmabufize-experiment' into 'main'
tests: Use dmabufs in compare tests

See merge request GNOME/gtk!7642
2024-08-24 20:25:17 +00:00
Matthias Clasen 8b215a453c Merge branch 'settings_parse_enums' into 'main'
settings: allow parsing enums nicknames from settings.ini

See merge request GNOME/gtk!7641
2024-08-24 17:59:08 +00:00
Matthias Clasen c3329123a3 Merge branch 'matthiasc/for-main' into 'main'
Add a since tag to GDK_TOPLEVEL_STATE_SUSPENDED

See merge request GNOME/gtk!7645
2024-08-24 17:33:23 +00:00
Matthias Clasen 107ef2017c tests: Use dmabufs in compare tests
Make the --replay mode of compare-render randomly turn textures it
finds into dmabuf textures, using /dev/udmabuf.
2024-08-24 13:10:25 -04:00
Matthias Clasen acad180cee Add dmabuf tests that can run in ci
This is a test balloon tests that use /dev/udmabuf to produce
dmabufs that we can use in ci, even if we don't have a GPU.
Currently, the tests we can do are somewhat limited, since mesas
software renderers don't support dmabufs yet.
2024-08-24 13:10:25 -04:00
Benjamin Otte 504ca9c0c8 CI: run tests in a single dbus session
Instead of every test spawning their own dbus, make the tests share the
same server, just like they share their own compositor.

This should speed up things a bit and avoid weird interactions when
multiple dbus processes exist.
2024-08-24 18:36:23 +02:00
Benjamin Otte 2d9f28c0ff CI: Make asan a child of the default fedora build
Effects of that:

1. Keep artifacts
2. Produce a test report
3. Caching for ccache
2024-08-24 18:36:23 +02:00
Benjamin Otte 07b3e8785c CI: Limit maximum number of test processes to 32
There are spurious failures happening in CI runs and I blame those on
too many processes running at the same time overloading either the
compositor we're running against, or causing OOM situations or just
genereally slowing things down and hitting timeout limits.

The choice of 32 is rather arbitrary. I just picked a number that felt
good.
2024-08-24 18:36:23 +02:00
Benjamin Otte 68ef86ac4f wayland: Don't ask dbus about settings we don't care about
When running with default settings, we don't care what dbus thinks about
non-default settings.
2024-08-24 18:36:23 +02:00
Piotr Drąg beb20fb1db Update POTFILES.in and POTFILES.skip 2024-08-24 14:58:15 +02:00
Juliano de Souza Camargo 3a965088a2 Update Brazilian Portuguese translation 2024-08-24 12:55:30 +00:00
Matthias Clasen 89118ee7ba Add a since tag to GDK_TOPLEVEL_STATE_SUSPENDED
We've changed the way we document additions in enums.
2024-08-24 08:38:19 -04:00
Arjan Molenaar 4b5d503cf0 Merge branch 'macos-control-click' into 'main'
macos: Add Ctrl+left-click mapping for context menus

Closes #6724

See merge request GNOME/gtk!7523
2024-08-24 11:42:35 +00:00
Sabri Ünal aeac103fbc Update Turkish translation 2024-08-24 06:44:18 +00:00
Luming Zh cd153e8a53 Update Chinese (China) translation 2024-08-24 04:05:37 +00:00
Benjamin Otte 5369b07eb0 Merge branch 'wip/otte/for-main' into 'main'
vulkan: Don't print errors on vkCreateInstance() failure

Closes #6947

See merge request GNOME/gtk!7643
2024-08-23 21:37:12 +00:00
Benjamin Otte 58f7b966d0 reftests: Make glarea-gl-only test XFAIL
With CI now using udmabufs, we run into bugs in Mesa. So we disable
some tests for now.

https://gitlab.freedesktop.org/mesa/mesa/-/issues/11773 is the bug
report for this one.
2024-08-23 22:53:13 +02:00
Benjamin Otte 4be1d754b7 vulkan: Don't spam stderr on failed Vulkan import
We write a debug message and then handle things using fallback.

Fixes error messages when trying to import incompatible dmabufs.
(in my case: llvmpipe dmabufs into radv)
2024-08-23 22:53:13 +02:00
g.willems c1351fb659 settings: allow parsing enums nicknames from settings.ini
The value of `gtk-font-rendering` currently can't be specified
in "settings.ini", as the parser doesn't handle enums.
Allow reading values by enum nicknames.

Also cleanup obsolete references to rc files.
2024-08-23 21:09:37 +02:00
Benjamin Otte d8926de40e vulkan: Don't print errors on vkCreateInstance() failure
We handle the error case right below with a proper GError, there's no
need to use the fallback error reporting.

Fixes #6947
2024-08-23 20:04:46 +02:00
Benjamin Otte 73c94cf1d6 gpu: Use the shared GL context when creating GL textures
The non-shared context's surface must survive the lifetime of the
GL texture, and when the renderer gets unrealized the surface goes away,
but we cannot guarantee that all GL textures have been destroyed by
then.

So better use a context we know will survive becuase it isn't bound to a
surface.

This is the same fix for NGL as f3ac0535f8
was for GL.
2024-08-23 20:04:46 +02:00
Benjamin Otte c2a637f68a inspector: Add KHR version of swap_buffers_with_damage
Related: #6941
2024-08-23 19:01:05 +02:00
Benjamin Otte 6a986f03b6 gpu: Simplify the blur op a bit
I was looking through it and thought this looks better.

It's also 21 lineas of code less.
2024-08-23 19:01:05 +02:00
Ekaterine Papava a52ae238ab Update Georgian translation 2024-08-23 09:55:42 +00:00
Yuri Chornoivan 8a0d688a61 Update Ukrainian translation 2024-08-23 04:43:09 +00:00
g.willems 3260b8f142 applicationwindow: set menubar a11y label
This fixes a warning from the inspector's accessibility checker.

Users only control the menu model, not the menubar widget,
so this can only be done in gtk.
2024-08-22 22:46:30 +02:00
Jordi Mas i Hernandez dc8e01d469 Update Catalan translation 2024-08-22 18:46:28 +00:00
Matthias Clasen 0105da3238 Merge branch 'main' into 'main'
textbuffer: Clear paste point override from empty middle clicks

Closes #5530

See merge request GNOME/gtk!6811
2024-08-22 18:11:05 +00:00
Yosef Or Boczko 8979515aa4 Update Hebrew translation 2024-08-22 15:41:53 +00:00
Vasil Pupkin a8c827455d Update Belarusian translation 2024-08-22 00:25:24 +00:00
Benjamin Otte 798edf5300 Merge branch 'wip/otte/for-leio' into 'main'
Only run a single renderpass

See merge request GNOME/gtk!7594
2024-08-21 20:11:52 +00:00
Benjamin Otte 54758bee1f gpu: Only run a single renderpass
Instead of running one renderpass per clip region, run one renderpass for
the whole clip extents, and just set the scissor to the individual clip
rects.

This means that we need to use LOAD_OP_LOAD in cases where we don't
redraw the full extents, but nonetheless, the eprformance wins of
avoiding renderpasses are worth it, in particualr on tilers like the
Raspberry Pi or other mobile chips and the Apple M1/2.
2024-08-21 21:13:34 +02:00
Benjamin Otte cfe0da1eed gpu: Add GskGpuLoadOp
We want to differentiate between CLEAR, DONT_CARE and LOAD in the
future, and the current boolean doesn't allow that.

Also implement support for the the different ops in the Vulkan
renderpass code.
2024-08-21 21:13:34 +02:00
Benjamin Otte 1198dc76a4 gpu: Add gsk_gpu_first_node_begin_rendering()
This starts the renderpass at the given scissor rect.

It just splits out the gsk_gpu_render_pass_begin_op() call into a
simpler function, so it's harder to mess up.
2024-08-21 21:13:34 +02:00
Benjamin Otte bed3e9918b gpu: Add GskGpuFirstNodeInfo
Just encapsulate all the data for the add_first_node() call into a
single struct.
2024-08-21 21:13:34 +02:00
Benjamin Otte d76bb2991a gpu: Refactoring: Pull out nodeprocessor
Add gsk_gpu_node_processor_set_scissor() that allows resetting the
nodeprocessor's scissor and clip rectangle.
That in turn allows using the same nodeprocessor instance for all the
rects we draw for the clip region.
2024-08-21 21:13:34 +02:00
Benjamin Otte e962e86fcd gpu: Split out a function
converting an image to any colorstate (not just ccs-capable default
colorstates) can go in its own function.
2024-08-21 21:13:34 +02:00
Benjamin Otte dd59c90842 rendernode: repeeat nodes with empty child bounds are transparent
So they must not copy the fully_opaque flag from the child.

Adapted the testcase that accidentally caught it do now always catch it
by setting a proper background.
2024-08-21 21:13:26 +02:00
Emmanuele Bassi c03720879e Merge branch 'fix-text-a11y-more' into 'main'
a11y: More text interface fixes

Closes #6951

See merge request GNOME/gtk!7638
2024-08-21 16:12:55 +00:00
Matthias Clasen a62787ebb2 a11y: More text interface fixes
The old bytes-vs-chars problem exists in more places.

Fixes: #6951
2024-08-21 11:33:11 -04:00
Matthias Clasen 2a7541342c Merge branch 'migration-docs-fix' into 'main'
docs: Fix various minor typos and improve formatting in the 4-to-5 migration guide

See merge request GNOME/gtk!7637
2024-08-21 15:17:59 +00:00
Philip Withnall f96d6cdb2b docs: Improve code tagging and API cross-reference links in 4-to-5 guide
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2024-08-21 15:03:44 +01:00
Philip Withnall 3ea6ddd321 docs: Improve Unicode usage in 4-to-5 migration guide
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2024-08-21 13:10:29 +01:00
Philip Withnall 17f7d80fcf docs: Fix various minor typos in the 4-to-5 migration guide
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2024-08-21 13:08:14 +01:00
Scrambled 777 e3437c748a Update Hindi translation 2024-08-21 08:57:29 +00:00
Benjamin Otte f1d80727d0 Merge branch 'wip/otte/i-see-dead-textures' into 'main'
gpu: Be more aggressive about GC'ing dead textures

See merge request GNOME/gtk!7636
2024-08-21 08:18:53 +00:00
Benjamin Otte c7fabe2897 gpu: Be more aggressive about GC'ing dead textures
When we encounter many dead textures, we want to GC. Textures can take
up fds (potentially even more than 1) and when we are not collecting
them quickly enough, we may run out of fds.

So GC when more then 50 dead textures exist.

An example for this happening is recent Mesa with llvmpipe udmabuf
support, which takes 2 fds per texture and the test in
testsuite/gdk/memorytexture that creates 800 textures of ~1 pixel each,
which it diligently releases but doesn't GC.

Related: #6917
2024-08-21 09:45:05 +02:00
Chun-wei Fan cc1c3799b6 Merge branch 'wgl-report-damage' into 'main'
GdkWin32GLContextWGL: Add support for incremental rendering

See merge request GNOME/gtk!7418
2024-08-21 02:37:41 +00:00
Martin a196bf1132 Update Slovenian translation 2024-08-20 04:54:07 +00:00
Matthias Clasen 4bcfeebdea Merge branch 'emoji-chooser-size' into 'main'
emojichooser: Resize according to screen height

See merge request GNOME/gtk!7631
2024-08-20 02:02:16 +00:00
Matthias Clasen 740965016f Merge branch 'matthiasc/for-main' into 'main'
Add a GDK_DISABLE env var

See merge request GNOME/gtk!7632
2024-08-20 01:58:54 +00:00
Matthias Clasen 39e6301f42 win32: Adapt to default flag changes
I hope this change does the right thing.
2024-08-19 21:37:49 -04:00
Matthias Clasen fd02c885e9 docs: Remove outdated information
We no longer disable debug flags in non-debug builds.
2024-08-19 20:40:32 -04:00
Matthias Clasen 26a2966a7b gdk: Beef up gdk_parse_debug_var
Add a docstring for the variable itself, and print it as part
of the help message. Update all callers to provide a docstring.
2024-08-19 20:40:32 -04:00
Matthias Clasen 29cfcbdc97 wayland: Respect GDK_DISABLE=color-mgmt
If the color-mgmt feature is disabled, don't use the
xx-color-management-v4 protocol.
2024-08-19 20:40:32 -04:00
Matthias Clasen de62ea96ab Add GDK_DISABLE=color-mgmt
This flag is meant to turn off color management features of GDK.
If this is set, all surfaces will report sRGB as their preferred
color state.
2024-08-19 20:40:32 -04:00
Matthias Clasen 2d230f79a6 Change the offload-disable flag
Move this from GSK_DEBUG=offload-disable to GDK_DISABLE=offload.
2024-08-19 20:40:32 -04:00
Matthias Clasen cde094a0df Add a GDK_DISABLE env var
This is taking over the feature-disabling keys from GDK_DEBUG.
2024-08-19 20:40:32 -04:00
Benjamin Otte 2fb3dc8c90 Merge branch 'wip/otte/for-main' into 'main'
wayland: Create EGL window in make_current() if necessary

Closes #6930

See merge request GNOME/gtk!7633
2024-08-19 23:34:35 +00:00
Benjamin Otte f6a8ba0ccb gpu: The colorstate op doesn't need a colorstates arg
It's using the same colorstate all the time: any premultiplied.

So just hardcode it.
2024-08-20 01:05:20 +02:00
Benjamin Otte f650f96b69 egl: Don't bind to NULL surface unless surfaceless
We need to ensure that an EGL surface exists before we call
eglMakeCurrent() with it. Otherwise we might end up binding to
EGL_NO_SURFACE and then never revising that decision.
Which leads to not rendering to the backbuffer, but into the void.

Fixes X11 rendering being black

Fixes #6930
2024-08-20 01:05:20 +02:00
Benjamin Otte c230546a2c wayland: Create EGL window in make_current() if necessary
We make_current() before begin_frame() so doing it only in begin_frame()
is too late.
2024-08-20 01:05:20 +02:00
Benjamin Otte f3ac0535f8 gl: Use the shared GL context when creating GL textures
the non-shared context's surface must survive the lifetime of the
GL texture, and when the renderer gets unrealized the surface goes away,
but we cannot guarantee that all GL textures have been destroyed by
then.

So better use a context we know will survive becuase it isn't bound to a
surface.
2024-08-20 01:05:20 +02:00
Artur S0 7ce942d3fb Update Russian translation 2024-08-19 14:07:35 +00:00
Mat 56a8e947df emojichooser: Resize according to screen height
Since a4cc95b293, the emoji chooser
can fail to appear on smaller screens, depending on where its parent
widget is located. Stop requesting a fixed height to prevent this
issue.
2024-08-19 08:19:04 +03:00
Chun-wei Fan f592a303e4 Merge branch 'vulkan-win32-fix-resize' into 'main'
gdksurface-win32.c: Call _gdk_surface_update_size() more (fix resizing on Vulkan on certain drivers)

Closes #6565

See merge request GNOME/gtk!7562
2024-08-19 03:53:29 +00:00
Chun-wei Fan e14670d457 gdksurface-win32.c: Call _gdk_surface_update_size() more
The current resizing implementation in the GDK-Win32 backend is not
telling GDK early enough for Vulkan that a resize in the surface (i.e.
HWND) is done, so that GDK can re-create swapchain in time, which is
apparent on nVidia drivers (and AMD drivers that utilize the mailbox
presentation mode on Windows) when the HWND is being enlarged
interactively.

To work around this, bar a refactor in the Windows resizing/presentation
code, is to call _gdk_surface_update_size() when we really did resize
the HWND when we handle queued resizes via SetWindowsPos().

The existing call in gdksurface-win32.c in
_gdk_win32_surface_compute_size() remains required, otherwise the
surface won't display initially.

Thanks to Benjamin Otte for pointing this possibility out.
2024-08-19 11:25:50 +08:00
Matthias Clasen 0acf9caa8e Merge branch 'matthiasc/for-main' into 'main'
node-editor: Make Ctrl-Shift-V undoable

See merge request GNOME/gtk!7629
2024-08-19 02:20:52 +00:00
Matthias Clasen 22860389de node-editor: Make Ctrl-Shift-V undoable 2024-08-18 21:45:25 -04:00
Matthias Clasen 16e764b402 wayland: Use interface names defined by protocol
We don't need to hardcode all the interface names as string literals,
since they come as part of the wl_interface structs in the protocol
bindings we use.
2024-08-18 18:23:18 -04:00
Matthias Clasen 85862c4e22 Merge branch 'matthiasc/for-main' into 'main'
Document new inspector functionality

See merge request GNOME/gtk!7628
2024-08-18 21:37:55 +00:00
Matthias Clasen eb764d43f8 Document new inspector functionality
Mention the new shortcuts for recording.
2024-08-18 17:14:28 -04:00
Matthias Clasen 6b57f596f7 Merge branch 'matthiasc/for-main' into 'main'
inspector: Add event traces

See merge request GNOME/gtk!7627
2024-08-18 21:00:01 +00:00
Matthias Clasen cefaec5d6f node-editor: Add Ctrl-Shift-V
Make Ctrl-Shift-V trigger a 'paste-as-node' action which replaces
the current content with the render node in the clipboard.
2024-08-18 15:44:40 -04:00
Matthias Clasen 29b6eab0ea inspector: Add some shortcuts
While the inspector is open, look for some shortcuts:

Super-r to toggle recording
Super-c to take a screenshot

A screenshot here means just a single-frame recording.
For convenience, we put the recorded frame onto the
clipboard too.
2024-08-18 15:44:40 -04:00
Matthias Clasen 360674f523 inspector: Add a snapshot function
Add a function that records just a single frame, and puts it
on the clipboard.
2024-08-18 15:44:40 -04:00
Matthias Clasen 7900f91e46 widget: Record event traces
Use the newly introduced inspector api to add event traces.
2024-08-18 15:44:40 -04:00
Matthias Clasen e4248503cf inspector: Add event traces
When recording events, make it possible to add 'traces' of the
events journey, and show those in the recorder.
2024-08-18 15:44:40 -04:00
Matthias Clasen 168bab34f7 inspector: Simplify
We can just put the render node on the clipboard directly, no
manual serialization required.
2024-08-18 15:44:40 -04:00
Matthias Clasen 46e7ea8c1e Fix a misleading comment 2024-08-18 15:44:40 -04:00
Matthias Clasen 1ce7de0fb8 Cosmetics 2024-08-18 10:44:38 -04:00
Matthias Clasen d9a0f3cfe2 Merge branch 'matthiasc/for-main' into 'main'
node parser: Move parse_color even earlier

See merge request GNOME/gtk!7625
2024-08-17 23:35:44 +00:00
Matthias Clasen 200cec3321 inspector: Minor GdkRGBA -> GdkColor porting 2024-08-17 18:56:05 -04:00
Matthias Clasen d4e730db0c node parser: Move parse_color even earlier
It will be used by parse_stops in the future, so move it above.

No functional change.
2024-08-17 16:24:20 -04:00
Benjamin Otte ca78d845df Merge branch 'wip/otte/for-main' into 'main'
gsk: Don't print any sRGB color as rgb() or rgba()

See merge request GNOME/gtk!7624
2024-08-17 20:19:01 +00:00
Benjamin Otte 9ff31dd29b testsuite: Improve testcase
This should have gone into !7619 but gitlab managed to finish the CI run
just as I was pushing a new version to the MR with
merge_request.merge_when_pipeline_succeeds and apparently gitlab applied
that to the previous version or something.

So now that MR merged an incomplete version to main. And here's the fix
for that.
2024-08-17 21:31:14 +02:00
Benjamin Otte 0815359a20 Merge branch 'wip/otte/for-main' into 'main'
gsk: Don't print any sRGB color as rgb() or rgba()

See merge request GNOME/gtk!7619
2024-08-17 19:28:07 +00:00
Benjamin Otte 96139a902d gsk: Don't print any sRGB color as rgb() or rgba()
If the color value is not inside the proper range for rgb() or rgba()
values being integers, use color() instead.

Tests added/adapted.
2024-08-17 21:09:25 +02:00
Benjamin Otte a6233ac852 rendernodeparser: Check color values aren't out of range
Use the clamp() API from the previous commit to:

1. Clamp values into range
2. Emit an error if values were out of range

Unlike CSS, which just clamps and doesn't emit an error, we do want to
emit one because we care about colors being correct in our node files.
2024-08-17 18:12:23 +02:00
Matthias Clasen 4e9ebb5299 gdk: Add gdk_color_state_clamp()
Allows clamping values into the correct range to construct valid colors.
2024-08-17 18:12:23 +02:00
Benjamin Otte 585f31fa2e rendernodeparser: Rename function
There's no need to name a function parse_color2() when parse_color()
doesn't exist.
2024-08-17 16:03:46 +02:00
Benjamin Otte 69e7838461 rendernodeparser: Don't have unnecessary forward declarations
Reorders functions to not have them.

No functional changes.
2024-08-17 16:03:46 +02:00
Matthias Clasen 3fe3800b7c Merge branch 'small-scale' into 'main'
monitor: Don't forbid scales < 1

Closes #6928

See merge request GNOME/gtk!7623
2024-08-17 13:22:15 +00:00
Matthias Clasen 491275b444 Merge branch 'radiobutton-focus' into 'main'
checkbutton: Add a 'grouped' style class

Closes #6936

See merge request GNOME/gtk!7622
2024-08-17 12:44:35 +00:00
Matthias Clasen 1cd107d5ab monitor: Don't forbid scales < 1
With fractional scaling, people try out things like 0.75 scaling,
and there's no reason for us to prohibit that from working.

Fixes: #6928
2024-08-17 08:26:55 -04:00
Matthias Clasen 5af2d95bff checkbutton: Add a 'grouped' style class
This will make it easier for themes to style radio buttons
differently from check buttons, since out CSS does not have
:has().

The concrete desire here is to use a different outline for
the focus rectangle.

Update affected tests.

Fixes: #6936
2024-08-17 08:22:54 -04:00
Benjamin Otte 62f5db06a1 Merge branch 'fix-opaque-surface-crash' into 'main'
Avoid a crash in gdk_surface_is_opaque

Closes #6938

See merge request GNOME/gtk!7621
2024-08-17 11:26:27 +00:00
Matthias Clasen e32a12f877 Avoid a crash in gdk_surface_is_opaque
Nothing in gtk calls gdk_surface_set_opaque_region anymore, so
the opaque region will normally be NULL.

Fixes: #6938
2024-08-17 07:03:57 -04:00
Ekaterine Papava 584733f034 Update Georgian translation 2024-08-17 03:49:13 +00:00
Matthias Clasen c3c1819e12 Merge branch 'css-variables-fixes2' into 'main'
css: Set the parent of the variable set earlier

Closes #6881

See merge request GNOME/gtk!7618
2024-08-16 16:52:34 +00:00
Matthias Clasen 3f36ebc6e7 Merge branch 'matthiasc/for-main' into 'main'
textview: Fix a regression in selection drawing

Closes #6931

See merge request GNOME/gtk!7620
2024-08-16 16:06:14 +00:00
Matthias Clasen 4aea2d2e09 css: Don't pass style variables redundantly
The context->variables field is expected by the resolve code to be
the keyframe variables. That code takes the style variables from
context->style anyway, so no need to pass them as context->variables
too. And crucially, the lookup code treats the keyframes variables
differently to the style variables, since it doesn't expect the
hierarchical structure that comes from parent styles. This change
fixes infinite recursion in variable lookup with css like

:root {
  --a: var(--b);
}

.foo {
  --b: var(--a);
  color: var(--a);
}

Test included.

Fixes: #6881
2024-08-16 11:38:56 -04:00
Matthias Clasen 4e9107d4b1 widget: Fail properly in compute_transform
We don't currently support computing transforms across native
boundaries. This could be added by using gdk_popup_get_position_x/y.
For now, just fail in this case.

Related: #6355
2024-08-16 10:07:53 -04:00
Matthias Clasen 7d895720be textview: Fix a regression in selection drawing
We were no longer respecting the text color or the selection being
clear.

Fixes: #6931
2024-08-16 08:44:35 -04:00
Benjamin Otte 323dde2b10 Merge branch 'wip/otte/for-main' into 'main'
wayland: Implement GdkToplevel::decorated

See merge request GNOME/gtk!7617
2024-08-16 00:01:54 +00:00
Benjamin Otte ac16e375c7 wayland: Implement GdkToplevel::decorated
... and use that instead of custom announce_csd/announce_ssd APIs.
2024-08-16 01:38:55 +02:00
Matthias Clasen 31143f9611 Merge branch 'kjellahl/docs-window' into 'main'
docs: Improve gtk_window_set_interactive_debugging() docs

See merge request GNOME/gtk!7614
2024-08-15 16:57:00 +00:00
Matthias Clasen 7da4844dcc Merge branch 'css-variables-crash' into 'main'
css: Fix a crash in variables

Closes #6935

See merge request GNOME/gtk!7615
2024-08-15 15:15:48 +00:00
Matthias Clasen c9e4abcd3a css: Fix a crash in variables
We were not careful enough when checking for reference cycles.

Fixes: #6935

Test included.
2024-08-15 10:16:47 -04:00
Matthias Clasen 6e80fde45f Merge branch 'accessibility-docs-fix' into 'main'
docs: Fix a typo in a code example on the accessibility page

See merge request GNOME/gtk!7616
2024-08-15 13:49:29 +00:00
Philip Withnall d182b133a9 docs: Fix a typo in a code example on the accessibility page
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2024-08-15 14:18:31 +01:00
Matthias Clasen 5e3240a32f Merge branch 'matthiasc/for-main' into 'main'
colorstate: Don't leak names

See merge request GNOME/gtk!7611
2024-08-14 18:06:36 +00:00
Matthias Clasen 436989d745 gsk: Apply the same transfer fixes
These are copied from gdkcolordefs.h.
2024-08-14 13:21:28 -04:00
Matthias Clasen f62606105e Fix up transfer function symmetry
The easiest things trigger the silliest mistakes. Add tests
for various properties we want our transfer functions to have,
such as:
- be inverse of each other
- stay within the defined ranges
- by symmetric around 0
2024-08-14 11:45:25 -04:00
Matthias Clasen 0f85a40a25 colorstate: Plug a leak and allocate less
We don't need to allocate the matrices, but we do neet to free
the name of cicp color states.
2024-08-14 11:00:10 -04:00
Matthias Clasen 16ad1e428f colorstate: Don't leak names
The cicp colorstates allocate their names, so they should free
them too.
2024-08-14 11:00:10 -04:00
Matthias Clasen a6e0028899 Merge branch 'wip/otte/for-kwin' into 'main'
Fix various issues with Kwin git

See merge request GNOME/gtk!7612
2024-08-14 14:58:08 +00:00
Kjell Ahlstedt dc3def1afd docs: Improve gtk_window_set_interactive_debugging() docs
This function is recommended only if you override the default
key shortcuts for the Inspector.
2024-08-14 16:57:55 +02:00
Kjell Ahlstedt a14e426fb5 docs: Improve gtk_window_set_interactive_debugging() docs
This function is recommended only if you override the default
key shortcuts for the inspector.
2024-08-14 15:51:56 +02:00
Bruce Cowan a1a4026867 Update British English translation 2024-08-14 10:27:24 +00:00
Benjamin Otte aff1b88c92 wayland: Work where the primaries have no name
Set primaries without name if supported, when named primaries are not.
But prefer named primaries if available.

This is just an attempt at defensive coding.
2024-08-14 08:30:55 +02:00
Benjamin Otte dc072f881c wayland: Accept primaries/primaries_named interchangably
If we get sent primaries with the values as named primaries, treat them
like named primaries.

Fixes colorstate support on Kwin, which never sends named primaries.
2024-08-14 08:30:55 +02:00
Benjamin Otte 824ccfc562 gpu: Add an assertion
If the wrong color states get passed, we need to figure that out, before
we run shaders with junk values doing god knows what.
2024-08-14 08:30:55 +02:00
Benjamin Otte 8c6e5ca131 subsurface: Fully covered backgrounds don't need to be drawn
If the texture covers all of the black background (like when watching a
1080p stream fullscreen on a 1080p monitor) we don't need a compositor
with single pixel support.

Fixes offloading in Kwin.
2024-08-14 08:30:55 +02:00
Benjamin Otte a7b69ad9b5 subsurface: Don't create a bg_subsurface until we need it
There's a ton of error checking happening that we want to do.

Because it turns out it is not really useful to create a subsurface for
the single pixel buffer when we don't even support single pixel buffers.
2024-08-14 08:30:55 +02:00
Benjamin Otte 3cd25516ab gdk: Improve GDK_DEBUG=linear
Keep a linear and a non-linear rendering colorstate around. That way, we
don't "return self;" from cicp colorstates and then end up with a cicp
ccs.
2024-08-14 08:30:40 +02:00
Benjamin Otte f3c8c5a9c0 Merge branch 'wip/otte/for-main' into 'main'
color: Handle negative values in all transfer functions

See merge request GNOME/gtk!7609
2024-08-13 23:52:32 +00:00
Matthias Clasen 6878200ccf Merge branch 'matthiasc/for-main' into 'main'
drawcontext: Fix up color state ownership

See merge request GNOME/gtk!7608
2024-08-13 21:42:46 +00:00
Matthias Clasen e1fbd52c29 gdk: Handle negative values in all transfer function
Make sure that for all eotfs/oetfs, eotf(x) == -eotf(-x)

In particular, don't pass negative values to pow() and cause
undefined behavior.
2024-08-13 15:47:17 -04:00
Benjamin Otte 79c2df8392 color: Handle negative values in all transfer functions
Make sure that for all eotfs/oetfs, eotf(x) == -eotf(-x)

In particular, don't pass negative values to pow() and cause undefined
behavior.
2024-08-13 20:47:40 +02:00
Scrambled 777 0888402cea Update Hindi translation 2024-08-13 18:38:21 +00:00
Matthias Clasen 3dae3205e7 drawcontext: Fix up color state ownership
begin_frame_full does not return a reference, we assume that the
color state is staying alive for the duration of the frame anyway,
so end_frame simply sets priv->color_state to NULL.
2024-08-13 13:23:20 -04:00
Matthias Clasen 4858122d17 Merge branch 'matthiasc/for-main' into 'main'
icon helper: Fix an argument order mishap

See merge request GNOME/gtk!7606
2024-08-13 16:50:31 +00:00
Matthias Clasen a19023277f icon helper: Fix an argument order mishap
It seems that for a long time, no compiler saw it fit to warn
about this, even though they argument types are not the same.
2024-08-13 10:36:12 -04:00
Emmanuele Bassi 72dc9e3bf1 Merge branch 'fix_popover_docs_typo' into 'main'
docs: Fix popover docs typo

See merge request GNOME/gtk!7605
2024-08-13 12:29:37 +00:00
Mikael Forsberg 5f814cc30a docs: Fix popover docs typo 2024-08-13 13:50:47 +02:00
Martin 23aafbf09f Update Slovenian translation 2024-08-13 05:55:59 +00:00
Matthias Clasen 761dc7cad0 Merge branch 'matthiasc/for-main' into 'main'
testsuite: build fix

See merge request GNOME/gtk!7603
2024-08-13 03:31:47 +00:00
Matthias Clasen f62a873eef inspector: Show color state of surfaces
Put this information in the misc tab for surfaces.
2024-08-12 22:25:08 -04:00
Benjamin Otte 03c99ebc99 Merge branch 'wip/otte/for-matthiasc' into 'main'
vulkan: Round damage rectangles properly

See merge request GNOME/gtk!7602
2024-08-13 00:24:47 +00:00
Matthias Clasen cb339f85b8 testsuite: build fix
The statically linked tests need to have -DGTK_COMPILATION=1
in their cflags.
2024-08-12 19:19:15 -04:00
Benjamin Otte 5d056eabf6 egl: Round damage rectangles properly
We need to round outwards and a 1x1 rectangle with offset 0.5,0.5 should
end up as a 3x3 rectangle with offset 0,0 when rounded, not as a 2x2
rectangle.
2024-08-13 00:36:11 +02:00
Benjamin Otte 4e77667ab8 vulkan: Round damage rectangles properly
We need to round outwards and a 1x1 rectangle with offset 0.5,0.5 should
end up as a 3x3 rectangle with offset 0,0 when rounded, not as a 2x2
rectangle.
2024-08-13 00:36:11 +02:00
Luca Bacci d3e3ddf897 WGL: Report paint region when presenting (SwapBuffers)
Report the paint region to the OpenGL driver, which in turn may
report it to the system compositor (DWM).
2024-08-12 18:56:45 +02:00
Luca Bacci fca983e81e WGL: Report backbuffer's damage to GDK
The backbuffer's damage region is the region of the backbuffer
that doesn't contain up-to-date contents. This is determined
by the backbuffer's age and previous frame's paint regions.

This enables incremental rendering
2024-08-12 18:56:34 +02:00
Luca Bacci b1995d0d77 Merge branch 'gtkshowwin32' into 'main'
Hook up file/URI launching to ShellExecute

See merge request GNOME/gtk!7556
2024-08-12 14:17:27 +00:00
Matthias Clasen 8ccfda4972 Merge branch 'docs-fix' into 'main'
docs: fix since annotation

See merge request GNOME/gtk!7600
2024-08-12 10:14:35 +00:00
Yosef Or Boczko 9a47c0f923 Update Hebrew translation 2024-08-12 09:58:40 +00:00
Sergey Bugaev b33b679b13 Hook up gtk_show_uri_full () to gtk_show_uri_win32 ()
On Windows, always use gtk_show_uri_win32 () instead of going through
GAppInfo.  Hook up gtk_file_launcher_launch () to gtk_show_uri_win32 ()
as well, always extracting the file path (and not a URI) and propagating
the always-ask flag.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2024-08-12 11:18:23 +03:00
Sergey Bugaev 8d41ecff3e Add gtk_show_uri_win32 ()
This is a new internal utility to open/show/launch/execute URIs and
files on Windows, using Windows's native ShellExecuteEx () and
SHOpenWithDialog () APIs.

The advantages this has over using the win32 implementation of
g_app_info_launch_default_for_uri ():

* the implementation here is fairly simple;
* it doesn't involve trying to grok the registry for app / file	type
  registrations (at least not inside GLib/GTK side, the implementations
  of ShellExecuteEx/SHOpenWithDialog presumably do that internally);
* it doesn't require convoluted formatting / escaping of invocation
  command lines that GWin32AppInfo / gspawn-win32 has to do otherwise
  (again, presumably the Windows libraries implement this internally);
* it's certain to end up opening the file/URI the same way other apps
  in the system would;
* it can/will open the native system UI for picking an app in case there
  are multiple options (or when so requested programmatically with the
  always-ask flag), or if there is no app installed that can handle the
  URI scheme / file type;
* it lets us pass the parent window handle, much like the portal APIs;
  presumably Windows would use this for positioning the picking UI, or
  placing the launched app's window;
* presumably, this will properly elevate privileges with a User Access
  Control (UAC) prompt if the app being launched requires administrator
  access; this presumably is impossible with the wspawn* APIs that
  gspawn-win32 uses;
* this has a much better chance to work properly with the win32 app
  isolation (AppContainer) technology.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2024-08-12 11:18:17 +03:00
Jan Willem 85bcf9a366 docs: fix since annotation 2024-08-12 07:05:47 +00:00
Matthias Clasen b27e3631f0 Merge branch 'matthiasc/for-main' into 'main'
colorstate: Avoid a memcpy

See merge request GNOME/gtk!7599
2024-08-11 22:00:03 +00:00
Matthias Clasen 4d5ba0631d colorstate: Avoid a memcpy
We don't need it here, and this call can happen with
values being in memory that is not amenable to fast memcpy.
2024-08-11 16:31:42 -04:00
Matthias Clasen 0f618ae29e Cosmetics 2024-08-11 16:31:35 -04:00
Matthias Clasen 13d415f2f6 Add a comment 2024-08-11 16:31:18 -04:00
Matthias Clasen e7b14ae26e Post-release version bump 2024-08-11 15:52:33 -04:00
Matthias Clasen 07658347a9 4.15.5 2024-08-11 15:43:54 -04:00
Matthias Clasen 0436801a9c Merge branch 'matthiasc/for-main' into 'main'
docs: Mark the docs check as failing

See merge request GNOME/gtk!7598
2024-08-11 19:43:16 +00:00
Matthias Clasen 4da593a3de Merge branch 'printdialog_fix_sporadic_win32_build_failures' into 'main'
printdialog: fix sporadic win32 build failures

See merge request GNOME/gtk!7464
2024-08-11 19:35:32 +00:00
Matthias Clasen f5194bbf83 gdk: Mark the docs check as failing
It complains about get_type functions, which really don't need
or want docs.
2024-08-11 15:03:13 -04:00
Matthias Clasen 15552e5478 docs: Mark the docs check as failing
Despite promises, and after fixing the configuration, the test still
complains about deprecated api not having docs. Not useful.
2024-08-11 15:01:59 -04:00
Matthias Clasen d9616c1993 docs: Try to fix the docs check 2024-08-11 15:00:54 -04:00
Matthias Clasen 5dbce5ce9b docs: Add a missing bit 2024-08-11 14:47:59 -04:00
Matthias Clasen 1f47c36e49 docs: Fix a typo 2024-08-11 14:47:48 -04:00
Benjamin Otte ed05890740 Merge branch 'wip/otte/for-main' into 'main'
gl: Interpolate gradient colors as premultiplied

See merge request GNOME/gtk!7597
2024-08-11 17:41:41 +00:00
Benjamin Otte 68d73dcce5 nodeparser: Handle disallowed values for radial gradients
Make sure the radii are strictly positive.

Also handle the case where start >= end.
We can't really underline that error, because we don't track the
locations of the start/end properties until we know that there's an
error.
So just underline the whole radial gradient declaration.

Test included
2024-08-11 19:07:40 +02:00
Benjamin Otte 9643a21827 gl: Interpolate gradient colors as premultiplied
Tests included
2024-08-11 19:07:40 +02:00
Matthias Clasen 07b64c2f0f Merge branch 'matthiasc/for-main' into 'main'
docs: Updates

See merge request GNOME/gtk!7596
2024-08-11 15:53:11 +00:00
Matthias Clasen 3df3ec2a29 css: Fix a copy-paste error
We want to use the decoration color if has_decoration_color is
TRUE, not if it is FALSE.
2024-08-11 10:02:03 -04:00
Matthias Clasen 0015fda94c docs: Updates
Keep the docs for our debug variables in sync with reality.
2024-08-11 09:02:35 -04:00
Matthias Clasen 589f483e7b NEWS: Updates 2024-08-11 08:50:42 -04:00
Daniel Șerbănescu a77f8c9f62 Update Romanian translation
(cherry picked from commit cfbfaeae01)
2024-08-11 11:14:37 +00:00
Matthias Clasen 1d7aa9e40b Merge branch 'matthiasc/for-main' into 'main'
Small cleanups

See merge request GNOME/gtk!7592
2024-08-11 11:01:58 +00:00
Benjamin Otte 8de4b04819 Merge branch 'wip/otte/for-main' into 'main'
color: NEVER EVER use memcpy() in critical path

See merge request GNOME/gtk!7593
2024-08-11 05:39:26 +00:00
Benjamin Otte 175dba86fd color: NEVER EVER use memcpy() in critical path
Unless there is a very good reason to use memcpy(), don't use it.

Not using it makes the compiler not screw up and waste tons of CPU that
it could have not wasted.

Gets my framerate back from 1250 => 1750 and makes sysprof no longer
report ~40% of render time spent in gsk_gpu_colorize_op().
2024-08-11 06:51:58 +02:00
Matthias Clasen 767b9b9405 Docs: Add the image tool to the list 2024-08-10 22:47:02 -04:00
Matthias Clasen 202a51d9e3 Cosmetics 2024-08-10 22:41:31 -04:00
Matthias Clasen 3014d36a61 Merge branch 'matthiasc/for-main' into 'main'
inspector: Show fine transform categories

See merge request GNOME/gtk!7591
2024-08-11 02:40:25 +00:00
Matthias Clasen d718fda057 memory texture: Fix a memory leak
The callers assumed that gdk_memory_sanitize is transfer full in
both directions, but it wasn't. Make it so.
2024-08-10 22:24:29 -04:00
Matthias Clasen bbb7b365d5 inspector: Show roles for nodes
For some node types, the child nodes play different roles. E.g.
for a mask node, one of the two children is the source, the other
the mask. Show this information in the inspector.
2024-08-10 21:51:06 -04:00
Matthias Clasen 740e485160 NEWS: Updates 2024-08-10 21:09:29 -04:00
Matthias Clasen 5a69127862 inspector: Show fine transform categories
This is information we care about in particular for offloading,
so show it.
2024-08-10 21:08:53 -04:00
Matthias Clasen 798883f21a Merge branch 'css-color-hookup-5' into 'main'
Make non-srgb css colors work for text nodes

See merge request GNOME/gtk!7558
2024-08-10 16:28:31 +00:00
Matthias Clasen bec71a15b4 Merge branch 'matthiasc/for-main' into 'main'
Fix a copy-paste error

See merge request GNOME/gtk!7589
2024-08-10 12:55:32 +00:00
Matthias Clasen c4baf60044 inspector: Rename add_color2_row to add_color_row
The original add_color_row is gone now, so we can rename its
successor back.
2024-08-10 08:16:40 -04:00
Matthias Clasen d32081401f inspector: Show more details for text nodes
Show the color state, and create textures with the full color
information.

The GdkRGBA-based helper functions are no longer used with this
commit and have been dropped.
2024-08-10 08:16:40 -04:00
Matthias Clasen ed119ae246 gtk: Port selection drawing to new apis
Preserve color state information when drawing selections or block
cursors in GtkTextView.
2024-08-10 08:16:40 -04:00
Matthias Clasen 51768d0e16 gtk: Port caret drawing to new apis
Preserve color state information here.
2024-08-10 08:16:40 -04:00
Matthias Clasen 6f1a4e5bb9 gtk: Use the new apis
It is not perfect, since PangoRenderer, GtkTextAppearance and
GtkTextTag all carry colors as PangoColor or GdkRGBA. But at least,
we get glowing foreground colors.
2024-08-10 08:14:23 -04:00
Matthias Clasen e323d2a93e gtk: Add gtk_snapshot_append_text2/layout2
These are private snapshot functions that use the new constructor
to create a text node with a given color state.
2024-08-10 07:48:18 -04:00
Matthias Clasen 23922eebf1 gl: Handle text colors with color states
Since we don't have proper color management here, just convert
any color we meet to sRGB and hope for the best.
2024-08-10 07:48:18 -04:00
Matthias Clasen 92bd85ba30 nodeparser: Support color states in text nodes
Test included.
2024-08-10 07:37:01 -04:00
Matthias Clasen ca7aa30bc5 gsk: Use private text node api 2024-08-10 07:37:01 -04:00
Matthias Clasen d17972427a gsk: Add private text node api
Add a constructor that takes a GdkColor and a corresponding getter.
2024-08-10 07:37:01 -04:00
Matthias Clasen 25f0c81530 Fix a copy-paste error
This was introduced in ea28dc8cff.
2024-08-10 07:11:56 -04:00
Matthias Clasen 4f95d126ba Merge branch 'matthiasc/for-main' into 'main'
gl: Handle box shadow colors with color states

See merge request GNOME/gtk!7588
2024-08-10 03:05:26 +00:00
Matthias Clasen 310196cc59 gl: Handle box shadow colors with color states
Since we don't have proper color management here, just convert
any color we meet to sRGB and hope for the best.
2024-08-09 22:27:57 -04:00
Matthias Clasen 8052bcc69c Updates 2024-08-09 22:11:35 -04:00
Benjamin Otte 04ee41d7b0 Merge branch 'wip/otte/for-main' into 'main'
lots of small things

See merge request GNOME/gtk!7585
2024-08-10 01:10:12 +00:00
Benjamin Otte 23af1cd8ad gpu: When transforming to simpler transform, we might be all clipped
When transforming back from a complex transform to a simpler transform,
the resulting clip might turn out to clip everything, because clips can
grow while transforming, but the scissor rect won't. So when this
process happens, we can end up with an empty clip by transforming:

1. Set a clip that also sets the scissor
2. transform in a way that grows the clip, say rotate(45)
3. modify the clip to shrink it
4. transform in a way that simplifies the transform, say another
   rotate(45)
5. Figure out that this clip and the scissor rect do no longer overlap

Catch this case and avoid drawing anything.
2024-08-10 02:38:13 +02:00
Benjamin Otte 4426194ee6 Merge branch 'css-color-hookup-4' into 'main'
Make non-srgb css colors work for shadows

See merge request GNOME/gtk!7557
2024-08-10 00:36:28 +00:00
Matthias Clasen 92c119e12c testsuite: Replay shadow nodes properly
Use the new apis for this.
2024-08-09 20:17:04 -04:00
Matthias Clasen ff02665407 inspector: Show more shadow node details
Show the color state, and create textures with the full color
information.

With this commit, add_color_row and get_color_texture are no longer
used and have been dropped.
2024-08-09 20:17:04 -04:00
Matthias Clasen d471ed5912 gtk: Use new shadow snapshot apis
Preserve color states from css as much as possible.
2024-08-09 20:17:04 -04:00
Matthias Clasen b92ca5da02 gtk: Add gtk_snapshot_push_shadow2
This is a private snapshot function that uses the new constructor
to create a shadow node with the given color states.
2024-08-09 20:17:04 -04:00
Matthias Clasen 0f7c0f616c nodeparser: Handle shadows with color state
Test included.
2024-08-09 20:09:31 -04:00
Matthias Clasen 5551f30400 gsk: Use private shadow node api 2024-08-09 20:09:31 -04:00
Matthias Clasen 2c10d72fe5 gsk: Add private shadow node api
Add a new GskShadow2 struct that has a GdkColor instead of
a GdkRGBA, and a new constructor and getter to go along with
it.

With this commit, my_color_get_depth is no longer used and
has been dropped.
2024-08-09 20:09:31 -04:00
Matthias Clasen 44fe51247c gsk: Change the blur op api
Pass the ccs, opacity and GdkColor to the op to let it make
decisions about color conversion.

Update the callers.
2024-08-09 20:09:31 -04:00
Matthias Clasen 3a99f1e9f1 gsk: Change the colorize op api
Pass the ccs, opacity and GdkColors to the op to let it make
decisions about color conversion.

Update the callers.
2024-08-09 20:09:30 -04:00
Matthias Clasen d233f0ca3e node parser: Move parse_color2 up
We will use this function more so move it where it belongs.
2024-08-09 20:09:30 -04:00
Matthias Clasen c548bdc3fe css: Add gtk_css_parser_consume_number_or_percentage
This comes in handy in the render node parser.
2024-08-09 20:09:30 -04:00
Benjamin Otte 839d797292 build: Don't set G_SLICE=always-malloc
That environment variable has been gone since GSlice went away in glib
2.76. Which is our minimum requirement.
2024-08-10 01:53:46 +02:00
Benjamin Otte f8a30ddfc1 gdk: Deprecate gdk_surface_set_opaque_region() 2024-08-10 01:40:46 +02:00
Benjamin Otte bb0eb3af45 gtk: Stop calling gdk_window_set_opaque_region()
Now that GDK can figure it out from the rendernode, doing all this work
trying to figure it out is no longer necessary.

Plus, it was sometimes wrong and lead to obscure artifacts.
2024-08-10 01:40:46 +02:00
Benjamin Otte 999d9bc73b gdk: Introduce gdk_surface_is_opaque()
... and use it in the mac backend instead of a hand-rolled version.
2024-08-10 01:40:46 +02:00
Benjamin Otte 16c7003acb gdk: Pass the opaque rect to begin_frame() actually
We know it at begin_frame() time, so if we pass it there instead of
end_frame(), we can use it then to make decisions about opacity.

For example, we could notice that the whole surface is opaque and choose
an RGBx format.
We don't do that yet, but now we could.
2024-08-10 01:40:46 +02:00
Benjamin Otte f64045c229 gdk: Pass the opaque rect on to the opaque region
The opaque rect from the rendernodes are now used to set the opaque
region in the backend.

This means applications can now set a transparent window background and
make indivual parts of their window opaque.
But because this is a best effort method, it is not guaranteed to
succeed in finding all opaque regions, in particular if the rendernodes
used to build it are not straightforward to analyze.
2024-08-10 01:40:46 +02:00
Benjamin Otte 58aebc4447 surface: Put opaque_region in the priv structure
This is in preparation for future patches.
2024-08-10 01:40:46 +02:00
Benjamin Otte 3b3b6036f8 mac: Remove clear optimization
1. We want to get rid of exposing the opaque region

2. Cairo optimizes clearing the whole surface
2024-08-10 01:40:46 +02:00
Benjamin Otte 75748f4ae9 gl: Remove update_area() trick
This is poking into the surface directly, so not a good idea.
And I want to hide that struct in the priv member.

Technically, this code should look at the opaque region, but I am lazy
and the GL renderer is on its way out, so I think it's not worth doing.
2024-08-10 01:40:46 +02:00
Benjamin Otte f90fb68aec gdk: Deprecate public begin/end_frame() APIs
We are using so many internal extra features that it is no longer a good
idea to use these functions.
And they aren't really used anyway.

These extra features are also constantly in flux and rely on internal
APIs, so exposing them would just cause extra pain.
2024-08-10 01:40:45 +02:00
Benjamin Otte 4fa3943e51 gdk: "inline" gdk_draw_context_get_frame_region()
By using the inlining macro trick, we can work around deprecation
warnings from removing this function as a public API, which will happen
in the next commits.
2024-08-10 01:40:45 +02:00
Benjamin Otte 0a92f741b3 vulkan: Remove 2 unneeded return_if_fail() checks
I want to deprecate that function, so getting rid of calls to it sounds
like a good idea.
2024-08-10 01:40:45 +02:00
Benjamin Otte a35f8d52d6 gsk: Clear current context after unrealize()
Make sure both GL renderers don't leave their contexts alive via the
current context, but ensure they dispose of them properly.

Fixes issues when the corresponding GL resources in the surfaces they
were attached to go away.
2024-08-10 01:40:45 +02:00
Benjamin Otte b08ccc0bec ngl: Stop crashing with zink and llvmpipe
We were not calling make_current() early enough anymore after the
Vulkan validation-layer fixes in !7468

Change that by calling it earlier.
2024-08-10 01:40:45 +02:00
Benjamin Otte 523cd0dff7 glcontext: Add a surface_attached flag
GLContexts marked as surface_attached are always attached to the surface
in make_current().
Other contexts continue to only get attached to their surface between
begin_frame() and end_frame().

All our renderer use surface-attached contexts now.
Public API only gives out non-surface-attached contexts.

The benefit here is that we can now choose whenever we want to
call make_current() because it will not cause a re-make_current() if we
call it outside vs inside the begin/end_frame() region.

Or in other words: I want to call make_current() before begin_frame()
without a performance penalty, and now I can.
2024-08-10 01:40:45 +02:00
Benjamin Otte 8ac1806015 gdk: Use begin_frame_full() everywhere
begin_frame() is going to go away, so we should use the "real" function.
2024-08-10 01:40:45 +02:00
Benjamin Otte 0b2275774f gdk: Add gdk_draw_context_end_frame_full()
... and pass the opaque region of the node.

We don't do anything with it yet, this is just the plumbing.

The original function still exists, it passes NULL which is the value
for no opaque region at all.
2024-08-10 01:40:45 +02:00
Benjamin Otte 4fbfe9b041 gsk: Warn about unused result in gsk_render_node_get_opaque_rect()
It's a function to easily forget to check the return value.

In fact I just did that.
2024-08-10 01:40:45 +02:00
Benjamin Otte b6c848d711 x11: Remove special casing from get_damage() call
This function is only ever called while inside a frame, so the check is
not necessary.
2024-08-10 01:40:45 +02:00
Benjamin Otte a467cfd060 inspector: Use a higher priority than USER
We want to override user settings, so make sure we do that.
2024-08-10 01:40:45 +02:00
Benjamin Otte f24be8476e wayland: Clean up after ourselves in the xx-color code
If an image description query is running while the surface gets
destroyed, we were not properly cleaning up, causing the callbacks to be
emitted on freed variables.
2024-08-10 01:40:45 +02:00
Benjamin Otte 904b1815b5 nodeprocessor: Consult scissor after rounded clip
If we apply a rounded clip, we might change the clip in a way that makes
it intersectable with the scissor again, if both had diverged before.

So try and intersect with the clip.
2024-08-10 01:40:45 +02:00
Benjamin Otte d6322c6389 gsk: Switch box shadow nodes to use offsets
Instead of
  float dx;
  float dy;
have a
  graphene_point_t offset;
in the object and in all APIs relating to them.
2024-08-10 01:40:45 +02:00
Benjamin Otte 2ee16e5dd9 gl: Set correct context when disposing GLDriver 2024-08-10 01:40:45 +02:00
Matthias Clasen f846315a6a Merge branch 'matthiasc/for-main' into 'main'
docs: More details for the node format

See merge request GNOME/gtk!7586
2024-08-09 16:46:30 +00:00
Matthias Clasen 5329b7d211 docs: More details for the node format
Add some more details.
2024-08-09 12:16:06 -04:00
Matthias Clasen ac18a665d5 node-format.md: formatting tweaks 2024-08-09 11:54:12 -04:00
Matthias Clasen c492e71aed Merge branch 'css-color-hookup-3' into 'main'
Make non-srgb css colors work for box shadows

See merge request GNOME/gtk!7552
2024-08-08 22:52:12 +00:00
Matthias Clasen 4ea1319c6b Replay inset and outset shadow nodes properly 2024-08-08 16:01:06 -04:00
Matthias Clasen 2aac3c2cc9 inspector: Show more details for box shadow nodes
Show the color state, and create textures with the full color
information.
2024-08-08 16:01:06 -04:00
Matthias Clasen 55d18bdc06 gtk: Use new box shadow snapshot apis
Preserve color states from css as much as possible.
2024-08-08 16:01:06 -04:00
Matthias Clasen abefa0ab00 gtk: Add gtk_snapshot_append_{in,out}set_shadow2
These are private snapshot functions that use the new constructors
to create a box shadow nodes with a given color state.
2024-08-08 16:01:06 -04:00
Matthias Clasen ea28dc8cff nodeparser: Support color states for box shadows
Just switch from parse_color to parse_color2, and apply the
corresponding changes to serialization too.

Test included.
2024-08-08 15:49:55 -04:00
Matthias Clasen d3b9eb7fc8 gsk: Use private box shadow api 2024-08-08 15:43:49 -04:00
Matthias Clasen cdb61923af gsk: Add private box shadow node api
Add a constructor that takes a GdkColor, and a getter for it.
2024-08-08 15:43:49 -04:00
Matthias Clasen 070ddcd14b Change box shadow op api
Pass the ccs, opacity and GdkColor and let the op decide about
color conversions. Update all callers.
2024-08-08 15:43:49 -04:00
Matthias Clasen 355890b421 gsk: Port the cairo blur to GdkColor
Update all callers.
2024-08-08 15:43:49 -04:00
Matthias Clasen d86407f263 Merge branch 'wip/otte/optional-dependencies' into 'main'
gstreamer: Always build dmabuf support

See merge request GNOME/gtk!7201
2024-08-08 19:29:13 +00:00
Benjamin Otte a24a7db72b build: bump GStreamer dep to 1.24.0
Depend on a release version, not a prerelease.
2024-08-08 19:03:31 +00:00
Benjamin Otte 2096a29b06 build: Remove an old workaround
The workaround only triggered in GStreamer < 1.19.1 but we require 1.23
now.
2024-08-08 19:03:31 +00:00
Benjamin Otte ce352b5538 build: Move GStreamer dependency checks
Put them where all the other checks go so that it's easy for people
reading build files to see what GTK depends on.

Also reindent properly.
2024-08-08 19:03:31 +00:00
Benjamin Otte 4bcd2c75cc gstreamer: Require the same version for all GStreamer deps
We don't want people to have different GStramer library versions.

GStreamer now is developed in a monorepo, so the versions are in sync.
2024-08-08 19:03:31 +00:00
Benjamin Otte 3c3bf0192d gstreamer: Always build dmabuf support
I just spent an hour trying to figure out why things don't work. And it
was an optional dependency hidden 3 layers deep in some meson file.

This really has to stop.

And because just like in GTK, GStreamer's dmabuf APIs are always
available (they will just fail on Windows etc), there's no need to have
any conditions.

The only difference is that the GStreamer media backend now requires
GStreamer 1.24.
2024-08-08 19:03:31 +00:00
Benjamin Otte cf84d999d8 dmabuf: Add DRM_FORMAT_MOD_INVALID to our formats
That's gonna be necessary for the next commits.
2024-08-08 19:03:31 +00:00
Matthias Clasen 668628941e Merge branch 'ci-update-f40' into 'main'
ci: Update to Fedora 40

See merge request GNOME/gtk!7583
2024-08-08 19:02:22 +00:00
Matthias Clasen 33f8fa331d fp16: Mark ifuncs as unused to pacify clang
clang in F40 seems to have forgotten what fp16 is, and doesn't
use the resolver functions for anything, and then complains that
they are unused...
2024-08-08 14:40:19 -04:00
Matthias Clasen 7814d1fd75 ci: Fix a Vulkan problem in the F40 image
Drop the powervr Vulkan driver, which otherwise interferes with
proper functioning of our ci.
2024-08-08 14:19:25 -04:00
Matthias Clasen b57c3008a3 ci: Update to Fedora 40
Crucially, this gives us gstreamer 1.24.
2024-08-08 12:57:33 -04:00
Benjamin Otte 99d291eb69 Merge branch 'wip/otte/occlusion' into 'main'
Implement advanced occlusion culling

See merge request GNOME/gtk!7570
2024-08-08 14:22:22 +00:00
Benjamin Otte 8e35398371 Merge branch 'wip/otte/for-main' into 'main'
vulkan: Turn debug messages into warnings

See merge request GNOME/gtk!7579
2024-08-08 04:25:35 +00:00
Benjamin Otte 3313fd4e2b vulkan: Turn debug messages into warnings
Vulkan errors are quire critical, so we want to see them.

Our code is good enough to handle all non-critical errors.
2024-08-08 04:41:16 +02:00
Matthias Clasen 56c02dd7d1 Merge branch 'css-color-hookup-2' into 'main'
Make non-srgb css colors work for borders

See merge request GNOME/gtk!7550
2024-08-07 23:14:35 +00:00
Benjamin Otte 4e4ed1e2d5 gpu: Implement occlusion for subsurface nodes
In the case of no offloading, we want to pass through to the child
(which is likely a big texture doing occlusion).

In the case of punching a hole, we want to punch the hole and not draw
anything behind it, so we start an occlusion pass with transparency.

And in the final case with offloading active, we don't draw anything,
so we don't draw anything.

This should fix concerns about drawing the background behind the video
as mentioned for example in
https://github.com/Rafostar/clapper/issues/343#issuecomment-1445425004
2024-08-07 23:26:03 +02:00
Benjamin Otte 82aa2cb5c2 gpu: Implement add_first_node for debug nodes
As always, we want to have no influence on any results
from these nodes.
2024-08-07 23:26:03 +02:00
Benjamin Otte e9944148d5 gpu: Add GSK_DEBUG=occlusion
Draws a semi-transparent white overlay over all regions that have
been chosen for occlusion.
2024-08-07 23:26:03 +02:00
Benjamin Otte afa4eb7d35 gpu: Make containers check opaque size for early exit
Container nodes save their opaque region, so it's quick to access. Use
that to check if the largest opaque region even qualifies for culling -
and if not, just exit.

Speeds up walking node trees by a lot.
2024-08-07 23:26:03 +02:00
Benjamin Otte 55597d88a4 gpu: Run full check for every clip rect
Now that we can specify the min size for an occlusion pass, we can
specify that we want the full clip rect to be occluded for occlusion to
trigger.

The benefit of this is that for partial redraws we almost
always get the background color to cover the redrawn rectangle, so
occlusion will kick in.
2024-08-07 23:26:03 +02:00
Benjamin Otte ac37b589b6 gpu: Require an occlusion path to be 10% of image
That way we are guaranteed to run <=10 occlusion passes.
2024-08-07 23:26:03 +02:00
Benjamin Otte b9d868b8eb gpu: Pass min occlusion size as argument
That allows as to vary the number. We don't do that yet, but we could
now.
2024-08-07 23:26:03 +02:00
Benjamin Otte 30e5bfcbf0 gpu: Refactor culling function
Split the loop into 2: One for the culling and one for later, once we've
decided to not try culling anymore.
2024-08-07 23:26:03 +02:00
Benjamin Otte 57e21683a6 gpu: Try largest clip rect first
When trying to cull, try culling from the largest rectangle of the
remaining draw region first. That region has the biggest chance of
containing a large area to skip.

As a side effect, we can stop trying to cull once the largest rectangle
isn't big enough anymore to contain anything worth culling.
2024-08-07 23:26:03 +02:00
Benjamin Otte 852ecf7c20 gpu: Consult scissor for clip bounds
When querying clip bounds, also check the scissor rect, because
sometimes that one is tighter than the clip bounds, because the clip
bounds need to track some larger rounded corners.

Makes a few tests harder to break.
2024-08-07 23:26:03 +02:00
Benjamin Otte 5976debfcd gpu: Change how occlusion passes work
Instead of requiring an occlusion pass to cover the whole given scissor
rect, allow using a smaller rect to start the pass.

When starting such a pass, we adjust the scissor rect to the size of
that pass and do not grow it again until the pass is done.
The rectangle subtraction at the end will then take care of subtraction
that rectangle from the remaining pixels.

To not end up with lots of tiny occlusion passes, add a limit for how
small such a pass may be.
For now that limit is arbitrarily chosen at 100k pixels.
2024-08-07 23:26:03 +02:00
Benjamin Otte 08fcba63d0 gpu: Split out a function
gsk_gpu_node_processor_rect_to_device() is a useful function to have,
even if it has to return FALSE sometimes when there is no simple 1:1
mapping - ie when the modelview contains a rotation.
2024-08-07 23:26:03 +02:00
Benjamin Otte 1abe9760ab gpu: Change the way clip rectangles are processed
Instead of just iterating over all the rectangles of the region,
always draw the first rectangle of the region and subtract it when done.

This sounds more complicated, but it will allow us to modify the
rectangle in future commits.
2024-08-07 23:26:03 +02:00
Benjamin Otte 9a4d8453ed gpu: Remove unused argument
the clip is already available via node->scissor so no need to track
that.
2024-08-07 23:26:03 +02:00
Benjamin Otte b637c3e201 gpu: Pass the clip region even further down
We are now handling the region inside the nodeprocessor.
2024-08-07 23:26:03 +02:00
Benjamin Otte 292f54dd60 gpu: Split out render function
Makes the code easier to understand
2024-08-07 23:26:03 +02:00
Benjamin Otte 1328c1409a gpu: Make the region argument transfer full
I want to modify the region while using it, and everybody destroys it
right after, so now there's no need to do a copy.
2024-08-07 23:26:03 +02:00
Benjamin Otte dbeddd4417 gpu: Always pass a clip region to render()
This way, we can remove the code that checks for its existence in that
function, making the code simpler.
2024-08-07 23:26:03 +02:00
Benjamin Otte add5dec4a9 rect: Add another utility function
Add gsk_rect_to_cairo_shrink() to match gsk_rect_to_cairo_grow()
2024-08-07 23:26:03 +02:00
Benjamin Otte 97b51dc070 inspector: Print opaque rect of nodes
Also change the way rectangles are printed by including the bottom right
coordinate, too.

I'm still not sure what the best way is, but at least I no longer get
confused and it has the infos I want.
2024-08-07 23:26:03 +02:00
Benjamin Otte 88c9a30f77 testsuite: Half the runtime of offscreens test
It times out too much in CI.
2024-08-07 23:26:03 +02:00
Marek Kasik 83035c1d4b printeroptionwidget: Maintain cursor position in combo-entry
Maintain cursor position even if the text in the entry has been filtered.
This is achieved by maintaining the same position with respect to
the end of the text buffer as we suppose that the text after the cursor
hasn't changed. This is measured in characters not bytes.

Fixes #6782
2024-08-07 20:26:57 +02:00
Matthias Clasen 50c19a6534 Merge branch 'hdr-content' into 'main'
gsk: Track whether nodes require wide gamut

See merge request GNOME/gtk!7575
2024-08-07 17:34:02 +00:00
Benjamin Otte 5c071cb02e dmabuf: Fix a check
We were comparing with destination stride, not with source stride, and
in rare cases when those were different, this would trigger aborts in
the testsuite.
2024-08-07 19:06:02 +02:00
Matthias Clasen 6edb526561 Merge branch 'plug-gtask-leaks' into 'main'
Plug GTask leaks

See merge request GNOME/gtk!7551
2024-08-07 16:26:52 +00:00
Matthias Clasen ee18156675 gsk: Add gsk_render_node_is_hdr
Add a function that tracks whether a render node's content is
in a wide gamut color state (in practice, that means non-sRGB).

This will be used in render_texture to determine the color
state to use when creating a texture.
2024-08-07 11:14:21 -04:00
Matthias Clasen e70a961ac1 Merge branch 'matthiasc/for-main' into 'main'
memoryformat: Add a debug helper

See merge request GNOME/gtk!7571
2024-08-07 14:51:05 +00:00
Matthias Clasen ffdc8c8f60 gsk: Drop some unused code
Nobody is using gsk_gpu_download_png_op, and we are going to
refactor the download op code.
2024-08-07 08:39:53 -04:00
Matthias Clasen fd78bd3eaf memoryformat: Add a debug helper
I need this often enough that I'll just put it here.
2024-08-07 08:22:05 -04:00
Matthias Clasen f2ccba0988 Merge branch 'wip/test-parser-data-additions' into 'main'
testsuite: add more files to test_data

See merge request GNOME/gtk!7569
2024-08-07 03:30:20 +00:00
Jeremy Bícha 8ee465c630 testsuite: add more files to test_data 2024-08-06 20:28:58 -04:00
Matthias Clasen 31b655c9eb Merge branch 'wip/dont-leak-egl-surface' into 'main'
gdk/surface: Don't leak the EGLSurface

See merge request GNOME/gtk!7568
2024-08-06 22:54:31 +00:00
Jonas Ådahl 7fd65cc3c1 gdk/surface: Don't leak the EGLSurface
Each time we create a new window, we create a new EGLSurface. Each time
we destroy a window, we failed to destroy the EGLSurface, due to passing
a GdkDisplay instead of a EGLDisplay to eglDestroySurface().

This effectively leaked not only the EGL surface metadata, but also the
associated DMA buffers. For applications where one opens and closes many
windows over the lifetime of the application, and where the application
runs for a long time; for example a terminal emulator server, this
causes a significant memory leak, as the memory will only ever be freed
once once the application process itself exits, if ever.

Fix this passing an actual EGLDisplay instead of an GdkDisplay, to
eglDestroySurface().
2024-08-06 23:42:11 +02:00
Jonas Ådahl 8089222fc3 gsk/gpu/downloadop: Include glib-unix.h
It's needed by g_close().
2024-08-06 23:41:46 +02:00
Benjamin Otte 0667bd39fb Merge branch 'wip/otte/for-main' into 'main'
gpu: Consult target colorstate for depth

See merge request GNOME/gtk!7567
2024-08-06 21:07:44 +00:00
Benjamin Otte a4854dfa9e memoryformat: Use "(p)" as premultiplied indicator in names
This matches what the gpu renderer does when printing
colorstates.

It also avoids it printing "S*RGBA8" for the format and instead prints
"SRGBA8(p)" now.
2024-08-06 22:15:17 +02:00
Benjamin Otte 6c54d0a7e2 gpu: Consult target colorstate for depth
When creating images for use with different colorstates, ensure that
they have the depth of that colorstate. Otherwise we might lose accuracy
due to quantization.

Fixes mipmaps in rec2100 being rendered as RGBA8.
2024-08-06 22:15:17 +02:00
Matthias Clasen 341860eb4d Merge branch 'small-fixes' into 'main'
colorstate: Drop xyz for now

See merge request GNOME/gtk!7565
2024-08-06 20:06:38 +00:00
Matthias Clasen 876445f080 inspector: Show color states of textures 2024-08-06 15:38:31 -04:00
Matthias Clasen 03ef6a7719 colorstate: Drop xyz for now
Converting to and from xyz turns out to be more difficult than
expected, depending on what whitepoint you choose, And different
specs choose different whitepoints, so we can't directly map
css xyz to cicp xyz anyway.
2024-08-06 15:38:31 -04:00
Matthias Clasen 2960bb7cb2 Add a compare test for colorstates in borders 2024-08-06 07:35:00 -04:00
Matthias Clasen 161c0f0963 inspector: Show more detail for border nodes
Show the color state, and create textures with the full color
information.
2024-08-06 07:35:00 -04:00
Matthias Clasen 3002591d08 gtk: Use new border snapshot api
Preserve color states from css as much as possible.
2024-08-06 07:35:00 -04:00
Matthias Clasen 1b2b9726f8 gtk: Add gtk_snapshot_append_border2
This is a private snapshot function that uses the new constructor
to create a border node with the given GdkColors.
2024-08-06 07:35:00 -04:00
Matthias Clasen a3691d311b nodeparser: Support color states in border nodes
Test included.
2024-08-06 07:35:00 -04:00
Matthias Clasen 89d449352f testsuite: Replay border nodes properly
Use the new apis for this.
2024-08-06 07:35:00 -04:00
Matthias Clasen e220e6dae7 gsk: Use private border node api
Use the GdkColors returned by this function instead of assuming
the colors of a border node are always sRGB.
2024-08-06 07:35:00 -04:00
Matthias Clasen bd3d1f7715 gsk: Add private border node api
Add a constructor that takes GdkColors, and a getter for those.

To support the existing api, we convert the colors to GdkRGBA
as needed.
2024-08-06 07:35:00 -04:00
Matthias Clasen f3ffa99f6a gsk: Change the border op api
Pass the ccs, opacity and GdkColors to the op to let it make
decisions about color conversion. Also, reorder the offset to
follow the same order as the color ops.

Update the callers.
2024-08-06 07:35:00 -04:00
Sergey Bugaev 85830c059e Plug GTask leaks
The error-prone pattern seems to be:

  GTask *task = g_task_new (...);

  if (condition)
    {
      g_task_return_... (task, ...);
      /* need g_object_unref (task) here! */
      return;
    }

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
2024-08-05 14:38:23 +03:00
Marek Kasik 6435d5083a printeroptionwidget: Update on combo-entry change
Connect to "changed" signal of the entry displayed with combobox
for some options (e.g. watermark text or passcode). This ensures
that the strings are propagated to the printer backend.

Fixes #6782
2024-07-31 16:59:11 +02:00
Arjan Molenaar f0925e4ef2 docs: Update function docs for gdk_event_triggers_context_menu
Include macOS, make code snipper easier identifyable.
2024-07-29 20:07:13 +02:00
Arjan Molenaar df87b1820b macos: Add Ctrl+left-click mapping for context menus
Update GdkEvent.triggers_context_menu to trigger a context menu
on macOS.
2024-07-29 19:59:29 +02:00
Stuart Hayhurst 170f099ce1 textbuffer: Clear paste point override from empty middle clicks
Middle clicking without a selection left a paste point override behind.
This meant actual pastes were going to the location of the middle click,
instead of the cursor

Closes #5530
2024-07-27 12:33:35 +01:00
Luca Bacci ccc6f7c24e GdkWin32: Drop unused variable
We still check whether depth buffer bits must be > 0,
we just don't use that variable anymore.
2024-07-24 15:36:25 +02:00
Luca Bacci 41b21b6634 WGL: Search pixel format with defined swap method (opengl32)
We want to get PFD_SWAP flags as that's required to enable incremental
rendering. However, as documented on MSDN, ChoosePixelFormat ignores
PFD_SWAP flags.

We may get PFD_SWAP flags or not depending on the way the OpenGL driver
orders its pixel formats. While PFD_SWAP flags are very important for
GUI toolkits, they are best avoided by games, as most games render the
scene in its entirety on each frame. Drivers optimized for games tend
to order pixel formats with no PFD_SWAP flags first.

Se we implement our own method to select the best pixel format. We check
for usable pixel formats and assign penalties for each one, until we find
a format with 0 penalty or the sequence ends. Then the best pixel format
is selected.
2024-07-24 15:36:25 +02:00
Luca Bacci b46a900d71 WGL: Search pixel format with defined swap method (arb)
Getting a defined swap method is necessary to enable incremental
rendering. We cannot just add a swap method attribute since
exchange is generally preferred, but is not always available.
Here we try to infer what the driver prefers, then ask for
exchange or copy, in sequence.
2024-07-24 15:35:40 +02:00
g.willems 4fa661b450 printdialog: fix sporadic win32 build failures
Private function `gtk_print_setup_get_printer` unconditionally calls
`gtk_printer_find()`, which does not exist on Win32.

But `gtk_print_setup_get_printer()` is never called either, so usually
that whole code gets optimized out.

Some compilation environment however do not cleanup unused functions,
leading to linker error as `gtk_printer_find()` is not found.

This patch should solve the link issue.
2024-07-15 23:05:13 +02:00
robxnano 4da8d39ec5 MenuSectionBox: Increase priority of separator sync function
This ensures that the separators are made visible before a popover
menu is shown. Previously the menu would jump in size after it
appeared.

Closes https://gitlab.gnome.org/GNOME/gtk/-/issues/5166
2023-12-14 18:57:04 +00:00
306 changed files with 21290 additions and 14070 deletions
+4 -2
View File
@@ -26,7 +26,8 @@ variables:
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled -Dbuild-testsuite=true -Dintrospection=enabled"
MESON_TEST_TIMEOUT_MULTIPLIER: 3
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v49"
MESON_TEST_MAX_PROCESSES: 8
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v52"
workflow:
rules:
@@ -414,11 +415,12 @@ static-scan:
# Run tests with the address sanitizer. We need to turn off introspection
# and f16c, since they are incompatible with asan
asan-build:
image: $FEDORA_IMAGE
extends: .build-fedora-default
tags: [ asan ]
stage: analysis
needs: []
variables:
MESON_TEST_MAX_PROCESSES: 4
script:
- export PATH="$HOME/.local/bin:$PATH"
- CC=clang meson setup
+4 -1
View File
@@ -1,4 +1,4 @@
FROM fedora:39
FROM fedora:40
RUN dnf -y install \
adwaita-icon-theme \
@@ -99,8 +99,11 @@ RUN dnf -y install \
which \
wireplumber \
xorg-x11-server-Xvfb \
&& dnf -y update \
&& dnf clean all
RUN rm /usr/share/vulkan/icd.d/powervr_mesa_icd.x86_64.json
# Enable sudo for wheel users
RUN sed -i -e 's/# %wheel/%wheel/' -e '0,/%wheel/{s/%wheel/# %wheel/}' /etc/sudoers
+10 -4
View File
@@ -8,17 +8,19 @@ builddir=$1
setup=$2
suite=$3
multiplier=${MESON_TEST_TIMEOUT_MULTIPLIER:-1}
n_processes=${MESON_TEST_MAX_PROCESSES:-1}
# Ignore memory leaks lower in dependencies
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0:detect_leaks=0:allocator_may_return_null=1
export G_SLICE=always-malloc
case "${setup}" in
x11*)
xvfb-run -a -s "-screen 0 1024x768x24 -noreset" \
dbus-run-session -- \
xvfb-run -a -s "-screen 0 1024x768x24 -noreset" \
meson test -C ${builddir} \
--quiet \
--timeout-multiplier "${multiplier}" \
--num-processes "${n_processes}" \
--print-errorlogs \
--setup=${setup} \
--suite=${suite//,/ --suite=} \
@@ -40,9 +42,11 @@ case "${setup}" in
compositor=$!
export WAYLAND_DISPLAY=wayland-5
meson test -C ${builddir} \
dbus-run-session -- \
meson test -C ${builddir} \
--quiet \
--timeout-multiplier "${multiplier}" \
--num-processes "${n_processes}" \
--print-errorlogs \
--setup=${setup} \
--suite=${suite//,/ --suite=} \
@@ -63,9 +67,11 @@ case "${setup}" in
server=$!
export BROADWAY_DISPLAY=:5
meson test -C ${builddir} \
dbus-run-session -- \
meson test -C ${builddir} \
--quiet \
--timeout-multiplier "${multiplier}" \
--num-processes "${n_processes}" \
--print-errorlogs \
--setup=${setup} \
--suite=${suite//,/ --suite=} \
+100 -1
View File
@@ -1,6 +1,105 @@
Overview of Changes in 4.15.5, xx-xx-xxxx
Overview of Changes in 4.15.7, xx-xx-xxxx
=========================================
Overview of Changes in 4.15.6, 08-26-2024
=========================================
* GtkCheckButton:
- Add a grouped style class for radio buttons
* GtkScale:
- Fix alignment and positioning problems
* Css:
- Fix crashes in the variable support
* Gsk:
- Make graphics offloading work better with kwin
- Make colorstate transfer functions more robust
- GC dead textures more agressively
- Only use a single render pass per frame
* GL:
- Round damage rectangles properly
- Use the shared context when creating textures
- Fix a file descriptor leak in dmabuf export
* Vulkan:
- Round damage rectangles properly
* Wayland:
- Work with the kwin implementation of xx-color-management-v4
* Windows:
- Make gtk_show_uri use SHOpenWithDialog()
- Enable incremental rendering with WGL
* Macos:
- Open context menus on Ctrl-left click
* Debugging:
- Show color state information in the inspector
- Collect input event traces in the recorder
- Add shortcuts for toggling recording: Super-r
and for screenshots: Super-c
- Split the GDK_DEBUG env var into GDK_DEBUG and GDK_DISABLE
- Add GDK_DISABLE=color-mgmt and GDK_DISABLE=offload
* Tools:
- Add a 'Paste as node' action in gtk4-node-editor
* Translations updates
Basque
Belarusian
Brazilian Portuguese
Chinese (China)
Georgian
Hebrew
Hindi
Russian
Slovenian
Turkish
Ukrainian
Overview of Changes in 4.15.5, 11-08-2024
=========================================
* GtkTextView:
- ADd GtkTextBufferCommitNotify
* CSS:
- Propagate color state information to GSK for many features:
colors, borders, shadows, text
* Gdk:
- Fix an fd leak in the Vulkan code
- Fix a leak of EGLSurfaces and DMA buffers
- Set the opaque region of surfaces automatically based on their content
* Gsk:
- Fix Emoji rendering in Vulkan
- Rework color handling to take color states into account
- Implement more powerful occlusion culling
- Minimize our use of renderpasses
* Macos:
- Fix window transparency
* Debugging:
- The inspector shows details about color states
* Deprecations:
- gdk_draw_context_begin/end_frame
- gdk_surface_set_opaque_region
* Build:
- Require gstreamer 1.24
* Translation updates
Romanian
Overview of Changes in 4.15.4, 30-07-2024
=========================================
+21 -106
View File
@@ -17,11 +17,6 @@ typedef struct {
GtkWidget *menubutton;
GMenuModel *toolmenu;
GtkTextBuffer *buffer;
int width;
int height;
gboolean maximized;
gboolean fullscreen;
} DemoApplicationWindow;
typedef GtkApplicationWindowClass DemoApplicationWindowClass;
@@ -337,6 +332,7 @@ static void
startup (GApplication *app)
{
GtkBuilder *builder;
const char *session_id;
G_APPLICATION_CLASS (demo_application_parent_class)->startup (app);
@@ -347,6 +343,17 @@ startup (GApplication *app)
G_MENU_MODEL (gtk_builder_get_object (builder, "menubar")));
g_object_unref (builder);
session_id = gtk_application_get_current_session_id (GTK_APPLICATION (app));
if (session_id)
{
GSettings *settings = g_settings_new ("org.gtk.Demo4.Application");
g_settings_set_string (settings, "session-id", session_id);
g_object_unref (settings);
}
}
static void
@@ -377,7 +384,7 @@ demo_application_init (DemoApplication *app)
GSettings *settings;
GAction *action;
settings = g_settings_new ("org.gtk.Demo4");
settings = g_settings_new ("org.gtk.Demo4.Application");
g_action_map_add_action_entries (G_ACTION_MAP (app),
app_entries, G_N_ELEMENTS (app_entries),
@@ -399,40 +406,11 @@ demo_application_class_init (DemoApplicationClass *class)
app_class->activate = activate;
}
static void
demo_application_window_store_state (DemoApplicationWindow *win)
{
GSettings *settings;
settings = g_settings_new ("org.gtk.Demo4");
g_settings_set (settings, "window-size", "(ii)", win->width, win->height);
g_settings_set_boolean (settings, "maximized", win->maximized);
g_settings_set_boolean (settings, "fullscreen", win->fullscreen);
g_object_unref (settings);
}
static void
demo_application_window_load_state (DemoApplicationWindow *win)
{
GSettings *settings;
settings = g_settings_new ("org.gtk.Demo4");
g_settings_get (settings, "window-size", "(ii)", &win->width, &win->height);
win->maximized = g_settings_get_boolean (settings, "maximized");
win->fullscreen = g_settings_get_boolean (settings, "fullscreen");
g_object_unref (settings);
}
static void
demo_application_window_init (DemoApplicationWindow *window)
{
GtkWidget *popover;
window->width = -1;
window->height = -1;
window->maximized = FALSE;
window->fullscreen = FALSE;
gtk_widget_init_template (GTK_WIDGET (window));
popover = gtk_popover_menu_new_from_model (window->toolmenu);
@@ -443,77 +421,11 @@ demo_application_window_init (DemoApplicationWindow *window)
window);
}
static void
demo_application_window_constructed (GObject *object)
{
DemoApplicationWindow *window = (DemoApplicationWindow *)object;
demo_application_window_load_state (window);
gtk_window_set_default_size (GTK_WINDOW (window), window->width, window->height);
if (window->maximized)
gtk_window_maximize (GTK_WINDOW (window));
if (window->fullscreen)
gtk_window_fullscreen (GTK_WINDOW (window));
G_OBJECT_CLASS (demo_application_window_parent_class)->constructed (object);
}
static void
demo_application_window_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
DemoApplicationWindow *window = (DemoApplicationWindow *)widget;
GTK_WIDGET_CLASS (demo_application_window_parent_class)->size_allocate (widget,
width,
height,
baseline);
if (!window->maximized && !window->fullscreen)
gtk_window_get_default_size (GTK_WINDOW (window), &window->width, &window->height);
}
static void
surface_state_changed (GtkWidget *widget)
{
DemoApplicationWindow *window = (DemoApplicationWindow *)widget;
GdkToplevelState new_state;
new_state = gdk_toplevel_get_state (GDK_TOPLEVEL (gtk_native_get_surface (GTK_NATIVE (widget))));
window->maximized = (new_state & GDK_TOPLEVEL_STATE_MAXIMIZED) != 0;
window->fullscreen = (new_state & GDK_TOPLEVEL_STATE_FULLSCREEN) != 0;
}
static void
demo_application_window_realize (GtkWidget *widget)
{
GTK_WIDGET_CLASS (demo_application_window_parent_class)->realize (widget);
g_signal_connect_swapped (gtk_native_get_surface (GTK_NATIVE (widget)), "notify::state",
G_CALLBACK (surface_state_changed), widget);
}
static void
demo_application_window_unrealize (GtkWidget *widget)
{
g_signal_handlers_disconnect_by_func (gtk_native_get_surface (GTK_NATIVE (widget)),
surface_state_changed, widget);
GTK_WIDGET_CLASS (demo_application_window_parent_class)->unrealize (widget);
}
static void
demo_application_window_dispose (GObject *object)
{
DemoApplicationWindow *window = (DemoApplicationWindow *)object;
demo_application_window_store_state (window);
gtk_widget_dispose_template (GTK_WIDGET (window), demo_application_window_get_type ());
G_OBJECT_CLASS (demo_application_window_parent_class)->dispose (object);
@@ -525,13 +437,8 @@ demo_application_window_class_init (DemoApplicationWindowClass *class)
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
object_class->constructed = demo_application_window_constructed;
object_class->dispose = demo_application_window_dispose;
widget_class->size_allocate = demo_application_window_size_allocate;
widget_class->realize = demo_application_window_realize;
widget_class->unrealize = demo_application_window_unrealize;
gtk_widget_class_set_template_from_resource (widget_class, "/application_demo/application.ui");
gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, message);
gtk_widget_class_bind_template_child (widget_class, DemoApplicationWindow, infobar);
@@ -548,11 +455,19 @@ int
main (int argc, char *argv[])
{
GtkApplication *app;
GSettings *settings;
char *session_id;
app = GTK_APPLICATION (g_object_new (demo_application_get_type (),
"application-id", "org.gtk.Demo4.App",
"flags", G_APPLICATION_HANDLES_OPEN,
NULL));
settings = g_settings_new ("org.gtk.Demo4.Application");
session_id = g_settings_get_string (settings, "session-id");
gtk_application_set_session_id (app, session_id);
g_free (session_id);
g_object_unref (settings);
return g_application_run (G_APPLICATION (app), 0, NULL);
}
+1
View File
@@ -5,6 +5,7 @@
<property name="default-width">200</property>
<property name="default-height">200</property>
<property name="icon-name">document-open</property>
<property name="session-id">application-main</property>
<child>
<object class="GtkGrid">
<child>
+1 -1
View File
@@ -55,7 +55,7 @@ mode_switch_state_set (GtkSwitch *sw,
{
gtk_widget_set_visible (label, TRUE);
gtk_accessible_update_relation (GTK_ACCESSIBLE (sw),
GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE, label,
GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE, label, NULL,
-1);
gtk_accessible_update_state (GTK_ACCESSIBLE (sw),
GTK_ACCESSIBLE_STATE_INVALID, GTK_ACCESSIBLE_INVALID_TRUE,
+25
View File
@@ -1068,6 +1068,8 @@ command_line (GApplication *app,
window = gtk_application_get_windows (GTK_APPLICATION (app))->data;
gtk_window_set_icon_name (GTK_WINDOW (window), "org.gtk.Demo4");
if (name == NULL)
goto out;
@@ -1138,6 +1140,19 @@ local_options (GApplication *app,
return -1;
}
static void
startup (GApplication *app,
gpointer data)
{
GSettings *settings = data;
const char *session_id;
session_id = gtk_application_get_current_session_id (GTK_APPLICATION (app));
if (session_id)
g_settings_set_string (settings, "session-id", session_id);
}
int
main (int argc, char **argv)
{
@@ -1154,6 +1169,8 @@ main (int argc, char **argv)
{ "app.about", { "F1", NULL } },
{ "app.quit", { "<Control>q", NULL } },
};
GSettings *settings;
char *session_id;
int i;
app = gtk_application_new ("org.gtk.Demo4", G_APPLICATION_NON_UNIQUE|G_APPLICATION_HANDLES_COMMAND_LINE);
@@ -1162,6 +1179,11 @@ main (int argc, char **argv)
app_entries, G_N_ELEMENTS (app_entries),
app);
settings = g_settings_new ("org.gtk.Demo4");
session_id = g_settings_get_string (settings, "session-id");
gtk_application_set_session_id (app, session_id);
g_free (session_id);
for (i = 0; i < G_N_ELEMENTS (accels); i++)
gtk_application_set_accels_for_action (app, accels[i].action_and_target, accels[i].accelerators);
@@ -1173,8 +1195,11 @@ main (int argc, char **argv)
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
g_signal_connect (app, "command-line", G_CALLBACK (command_line), NULL);
g_signal_connect (app, "handle-local-options", G_CALLBACK (local_options), NULL);
g_signal_connect (app, "startup", G_CALLBACK (startup), settings);
g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (settings);
return 0;
}
+1
View File
@@ -19,6 +19,7 @@
<object class="GtkApplicationWindow" id="window">
<property name="default-width">800</property>
<property name="default-height">600</property>
<property name="session-id">main-window</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="headerbar">
<child>
+11 -10
View File
@@ -2,24 +2,25 @@
<schemalist>
<enum id='org.gtk.Demo4.Color'>
<enum id='org.gtk.Demo4.Application.Color'>
<value nick='red' value='0'/>
<value nick='green' value='1'/>
<value nick='blue' value='2'/>
</enum>
<schema id='org.gtk.Demo4' path='/org/gtk/Demo4/'>
<key name='color' enum='org.gtk.Demo4.Color'>
<key name='session-id' type='s'>
<default>''</default>
</key>
</schema>
<schema id='org.gtk.Demo4.Application' path='/org/gtk/Demo4/Application/'>
<key name='color' enum='org.gtk.Demo4.Application.Color'>
<default>'red'</default>
</key>
<key name='window-size' type='(ii)'>
<default>(-1, -1)</default>
</key>
<key name='maximized' type='b'>
<default>false</default>
</key>
<key name='fullscreen' type='b'>
<default>false</default>
<key name='session-id' type='s'>
<default>''</default>
</key>
</schema>
+2
View File
@@ -139,6 +139,8 @@ icon_browser_app_activate (GApplication *app)
if (g_strcmp0 (PROFILE, "devel") == 0)
gtk_widget_add_css_class (GTK_WIDGET (win), "devel");
gtk_window_set_icon_name (GTK_WINDOW (win), "org.gtk.IconBrowser4");
gtk_window_present (GTK_WINDOW (win));
}
+3
View File
@@ -30,6 +30,9 @@ endforeach
# desktop file
install_data('org.gtk.gtk4.NodeEditor.desktop', install_dir: gtk_applicationsdir)
install_data('org.gtk.NodeEditor4.gschema.xml', install_dir: gtk_schemasdir)
gnome.compile_schemas()
# appdata
configure_file(
input: 'org.gtk.gtk4.NodeEditor.appdata.xml.in',
@@ -191,6 +191,16 @@ node_editor_application_startup (GApplication *app)
const char *quit_accels[2] = { "<Ctrl>Q", NULL };
const char *open_accels[2] = { "<Ctrl>O", NULL };
GtkCssProvider *provider;
GSettings *settings;
gchar *session_id;
settings = g_settings_new ("org.gtk.NodeEditor4");
session_id = g_settings_get_string (settings, "session-id");
if (session_id)
{
gtk_application_set_session_id (GTK_APPLICATION (app), session_id);
g_free (session_id);
}
G_APPLICATION_CLASS (node_editor_application_parent_class)->startup (app);
@@ -207,6 +217,9 @@ node_editor_application_startup (GApplication *app)
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_settings_set_string (settings, "session-id",
gtk_application_get_current_session_id (GTK_APPLICATION (app)));
}
static void
@@ -219,6 +232,8 @@ node_editor_application_activate (GApplication *app)
if (g_strcmp0 (PROFILE, "devel") == 0)
gtk_widget_add_css_class (GTK_WIDGET (win), "devel");
gtk_window_set_icon_name (GTK_WINDOW (win), "org.gtk.gtk4.NodeEditor");
gtk_window_present (GTK_WINDOW (win));
}
+58
View File
@@ -1205,6 +1205,19 @@ node_editor_window_add_renderer (NodeEditorWindow *self,
g_object_unref (paintable);
}
static void
update_paste_action (GdkClipboard *clipboard,
GParamSpec *pspec,
gpointer data)
{
GtkWidget *widget = GTK_WIDGET (data);
gboolean has_node;
has_node = gdk_content_formats_contain_mime_type (gdk_clipboard_get_formats (clipboard), "application/x-gtk-render-node");
gtk_widget_action_set_enabled (widget, "paste-node", has_node);
}
static void
node_editor_window_realize (GtkWidget *widget)
{
@@ -1242,6 +1255,7 @@ node_editor_window_realize (GtkWidget *widget)
self->after_paint_handler = g_signal_connect (frameclock, "after-paint",
G_CALLBACK (after_paint), self);
g_signal_connect (gtk_widget_get_clipboard (widget), "notify::formats", G_CALLBACK (update_paste_action), widget);
}
static void
@@ -1251,6 +1265,8 @@ node_editor_window_unrealize (GtkWidget *widget)
GdkFrameClock *frameclock;
guint i;
g_signal_handlers_disconnect_by_func (gtk_widget_get_clipboard (widget), update_paste_action, widget);
frameclock = gtk_widget_get_frame_clock (widget);
g_signal_handler_disconnect (frameclock, self->after_paint_handler);
self->after_paint_handler = 0;
@@ -1615,6 +1631,41 @@ edit_action_cb (GtkWidget *widget,
node_editor_window_edit (self, &start);
}
static void
text_received (GObject *source,
GAsyncResult *result,
gpointer data)
{
GdkClipboard *clipboard = GDK_CLIPBOARD (source);
NodeEditorWindow *self = NODE_EDITOR_WINDOW (data);
char *text;
text = gdk_clipboard_read_text_finish (clipboard, result, NULL);
if (text)
{
GtkTextBuffer *buffer;
GtkTextIter start, end;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self->text_view));
gtk_text_buffer_begin_user_action (buffer);
gtk_text_buffer_get_bounds (buffer, &start, &end);
gtk_text_buffer_delete (buffer, &start, &end);
gtk_text_buffer_insert (buffer, &start, text, -1);
gtk_text_buffer_end_user_action (buffer);
g_free (text);
}
}
static void
paste_node_cb (GtkWidget *widget,
const char *action_name,
GVariant *parameter)
{
GdkClipboard *clipboard = gtk_widget_get_clipboard (widget);
gdk_clipboard_read_text_async (clipboard, NULL, text_received, widget);
}
static void
node_editor_window_set_property (GObject *object,
guint prop_id,
@@ -1727,6 +1778,13 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
action = gtk_named_action_new ("smart-edit");
shortcut = gtk_shortcut_new (trigger, action);
gtk_widget_class_add_shortcut (widget_class, shortcut);
gtk_widget_class_install_action (widget_class, "paste-node", NULL, paste_node_cb);
trigger = gtk_keyval_trigger_new (GDK_KEY_v, GDK_CONTROL_MASK | GDK_SHIFT_MASK);
action = gtk_named_action_new ("paste-node");
shortcut = gtk_shortcut_new (trigger, action);
gtk_widget_class_add_shortcut (widget_class, shortcut);
}
static GtkWidget *
+5
View File
@@ -22,6 +22,10 @@
</menu>
<menu id="extra_menu">
<section>
<item>
<attribute name="label" translatable="yes">Paste _Node</attribute>
<attribute name="action">paste-node</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Assisted _Edit</attribute>
<attribute name="action">smart-edit</attribute>
@@ -105,6 +109,7 @@
<property name="default-width">1024</property>
<property name="default-height">768</property>
<property name="focus-widget">text_view</property>
<property name="session-id">main-window</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<child type="start">
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
<schema id='org.gtk.NodeEditor4' path='/org/gtk/NodeEditor4/'>
<key name='session-id' type='s'>
<default>''</default>
</key>
</schema>
</schemalist>
+1 -1
View File
@@ -798,7 +798,7 @@ activate (GApplication *app)
if (g_strcmp0 (PROFILE, "devel") == 0)
gtk_widget_add_css_class (GTK_WIDGET (main_window), "devel");
gtk_window_set_icon_name (GTK_WINDOW (main_window), "text-editor");
gtk_window_set_icon_name (GTK_WINDOW (main_window), "org.gtk.PrintEditor4");
gtk_window_set_default_size (GTK_WINDOW (main_window), 400, 600);
gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (main_window), TRUE);
update_title (GTK_WINDOW (main_window));
+1
View File
@@ -2241,6 +2241,7 @@ activate (GApplication *app)
if (g_strcmp0 (PROFILE, "devel") == 0)
gtk_widget_add_css_class (GTK_WIDGET (window), "devel");
gtk_window_set_icon_name (window, "org.gtk.WidgetFactory4");
gtk_application_add_window (GTK_APPLICATION (app), window);
g_action_map_add_action_entries (G_ACTION_MAP (window),
win_entries, G_N_ELEMENTS (win_entries),
+1 -1
View File
@@ -38,7 +38,7 @@ if get_option('documentation')
gdk_gir[0],
],
depends: gdk_gir[0],
suite: ['docs'],
suite: ['docs', 'failing'],
)
if x11_enabled
+7 -3
View File
@@ -1,12 +1,16 @@
Title: The Broadway windowing system
Slug: broadway
## Using GTK with Broadway
The GDK Broadway backend provides support for displaying GTK applications in
a web browser, using HTML5 and web sockets.
To run your application in this way, first run the broadway server,
Broadway was written as an experiment and is not the most actively developed
backend. It supports the features that were required of GDK backends in GTK 4.0,
but may not be up-to-date with the latest developments.
## Using GTK with Broadway
To run your application under Broadway, first run the broadway server,
`gtk-broadwayd`, that ships with GTK:
```
+1 -1
View File
@@ -260,4 +260,4 @@ name = "StyleProvider"
hidden = true
[check]
skip_deprecated = true
ignore_deprecated = true
+1 -1
View File
@@ -74,7 +74,7 @@ if get_option('documentation')
gtk_gir[0],
],
depends: gtk_gir[0],
suite: ['docs'],
suite: ['docs', 'failing'],
)
endif
+38 -38
View File
@@ -24,36 +24,36 @@ the motivation and goals of larger API changes.
## Cell renderers are going away
Cell renderers were introduced in GTK 2 to support rendering of
"big data" UIs, in particular treeviews. Over the years, more
"data-like" widgets have started to use them, and cell renderers
big data UIs, in particular treeviews. Over the years, more
data-like widgets have started to use them, and cell renderers
have grown into a shadowy, alternative rendering infrastructure
that duplicates much of what widgets do, while duplicating the
code and adding their own dose of bugs.
In GTK 4, replacement widgets for GtkTreeView, GtkIconView and
GtkComboBox have appeared: GtkListView, GtkColumnView, GtkGridView
and GtkDropDown. For GTK 5, we will take the next step and remove
In GTK 4, replacement widgets for `GtkTreeView`, `GtkIconView` and
`GtkComboBox` have appeared: [class@Gtk.ListView], [class@Gtk.ColumnView], [class@Gtk.GridView]
and [class@Gtk.DropDown]. For GTK 5, we will take the next step and remove
all cell renderer-based widgets.
## Themed rendering APIs are going away
The old GTK 2 era rendering APIs for theme components like
gtk_render_frame() or gtk_render_check() have not been used by
`gtk_render_frame()` or `gtk_render_check()` have not been used by
GTK itself even in later GTK 3, but they have been kept around
for the benefit of "external drawing" users - applications that
for the benefit of external drawing users applications that
want their controls to look like GTK without using widgets.
Supporting this is increasingly getting in the way of making
the GTK CSS machinery fast and correct. One notable problem is
that temporary style changes (using gtk_style_context_save())
that temporary style changes (using `gtk_style_context_save()`)
is breaking animations. Therefore, these APIs will be going away
in GTK 5, together with their more modern GtkSnapshot variants
like gtk_snapshot_render_background() or gtk_snapshot_render_focus().
in GTK 5, together with their more modern [class@Gtk.Snapshot] variants
like `gtk_snapshot_render_background()` or `gtk_snapshot_render_focus()`.
The best way to render parts of your widget using CSS styling
is to use subwidgets. For example, to show a piece of text with
fonts, effects and shadows according to the current CSS style,
use a GtkLabel.
use a [class@Gtk.Label].
If you have a need for custom drawing that fits into the current
(dark or light) theme, e.g. for rendering a graph, you can still
@@ -62,28 +62,28 @@ get the current style foreground color, using
## Local stylesheets are going away
The cascading part of GTK's CSS implementation is complicated by
The cascading part of GTKs CSS implementation is complicated by
the existence of local stylesheets (i.e. those added with
gtk_style_context_add_provider()). And local stylesheets are
`gtk_style_context_add_provider()`). And local stylesheets are
unintuitive in that they do not apply to the whole subtree of
widgets, but just to the one widget where the stylesheet was
added.
GTK 5 will no longer provide this functionality. The recommendations
is to use a global stylesheet (i.e. gtk_style_context_add_provider_for_display())
GTK 5 will no longer provide this functionality. The recommendation
is to use a global stylesheet (i.e. [func@Gtk.StyleContext.add_provider_for_display])
and rely on style classes to make your CSS apply only where desired.
## Non-standard CSS extensions are going away
GTK's CSS machinery has a some non-standard extensions around colors:
named colors with \@define-color and color functions: lighter(), darker(),
shade(), alpha(), mix().
GTKs CSS machinery has a some non-standard extensions around colors:
named colors with `@define-color` and color functions: `lighter()`, `darker()`,
`shade()`, `alpha()`, `mix()`.
GTK now implements equivalent functionality from the CSS specs.
### \@define-color is going away
### `@define-color` is going away
\@define-color should be replaced by custom properties in the :root scope.
`@define-color` should be replaced by custom properties in the `:root` scope.
Instead of
@@ -117,9 +117,9 @@ spec.
### Color expressions are going away
The color functions can all be replaced by combinations of calc() and color-mix().
The color functions can all be replaced by combinations of `calc()` and `color-mix()`.
ligher(c) and darker(c) are just shade(c, 1.3) or shade(c, 0.7), respectively, and
`lighter(c)` and `darker(c)` are just `shade(c, 1.3)` or `shade(c, 0.7)`, respectively, and
thus can be handled the same way as shade in the examples below.
Replace
@@ -164,7 +164,7 @@ d {
Variations of these replacements are possible.
Note that GTK has historically computed mix() and shade() values in the SRGB and HSL
Note that GTK has historically computed `mix()` and `shade()` values in the SRGB and HSL
colorspaces, but using OKLAB instead might yield slightly better results.
For more information about color-mix(), see the
@@ -172,32 +172,32 @@ For more information about color-mix(), see the
## Chooser interfaces are going away
The GtkColorChooser, GtkFontChooser, GtkFileChooser and GtkAppChooser
The `GtkColorChooser`, `GtkFontChooser`, `GtkFileChooser` and `GtkAppChooser`
interfaces and their implementations as dialogs, buttons and widgets
are phased out. The are being replaced by a new family of async APIs
that will be more convenient to use from language bindings, in particular
for languages that have concepts like promises. The new APIs are
[class@Gtk.ColorDialog], [class@Gtk.FontDialog] and [class@Gtk.FileDialog],
There are also equivalents for some of the 'button' widgets:
There are also equivalents for some of the button widgets:
[class@Gtk.ColorDialogButton], [class@Gtk.FontDialogButton].
## GtkMessageDialog is going away
Like the Chooser interfaces, GtkMessageDialog has been replaced by
Like the Chooser interfaces, `GtkMessageDialog` has been replaced by
a new async API that will be more convenient, in particular for
language binding. The new API is [class@Gtk.AlertDialog].
## GtkDialog is going away
After gtk_dialog_run() was removed, the usefulness of GtkDialog
is much reduced, and it has awkward, archaice APIs. Therefore,
After `gtk_dialog_run()` was removed, the usefulness of `GtkDialog`
is much reduced, and it has awkward, archaic APIs. Therefore,
it is dropped. The recommended replacement is to just create
your own window and add buttons as required, either in the header
or elsewhere.
## GtkInfoBar is going away
GtkInfoBar had a dialog API, and with dialogs going away, it was time to
`GtkInfoBar` had a dialog API, and with dialogs going away, it was time to
retire it. If you need such a widget, it is relatively trivial to create one
using a [class@Gtk.Revealer] with labels and buttons.
@@ -205,11 +205,11 @@ Other libraries, such as libadwaita, may provide replacements as well.
## gtk_show_uri is being replaced
Instead of gtk_show_uri(), you should use GtkUriLauncher or GtkFileLauncher.
Instead of `gtk_show_uri()`, you should use [class@Gtk.UriLauncher]or [class@Gtk.FileLauncher].
## GtkStatusbar is going away
This is an oldfashioned widget that does not do all that much anymore, since
This is an old fashioned widget that does not do all that much any more, since
it no longer has a resize handle for the window.
## GtkLockButton and GtkVolumeButton are going away
@@ -217,22 +217,22 @@ it no longer has a resize handle for the window.
These are very specialized widgets that should better live with the application
where they are used.
## Widget size api changes
## Widget size API changes
The functions gtk_widget_get_allocated_width() and gtk_widget_get_allocated_height()
The functions `gtk_widget_get_allocated_width()` and `gtk_widget_get_allocated_height()`
are going away. In most cases, [method@Gtk.Widget.get_width] and [method@Gtk.Widget.get_height]
are suitable replacements. Note that the semantics are slightly different though:
the old functions return the size of the CSS border area, while the new functions return
the size of the widgets content area. In places where this difference matters, you can
use `gtk_widget_compute_bounds (widget, widget, &bounds)` instead.
The function gtk_widget_get_allocation() is also going away. It does not have a direct
The function `gtk_widget_get_allocation()` is also going away. It does not have a direct
replacement, but the previously mentioned alternatives can be used for it too.
The function gtk_widget_get_allocated_baseline() has been renamed to [method@Gtk.Widget.get_baseline].
The function `gtk_widget_get_allocated_baseline()` has been renamed to [method@Gtk.Widget.get_baseline].
## Stop using GdkPixbuf
GTK is moving away from GdkPixbuf as the primary API for transporting image data, in favor
of GdkTexture. APIs that are accepting or returning GdkPixbufs are being replaced by equivalent
APIs using GdkTexture or GdkPaintable objects.
GTK is moving away from `GdkPixbuf` as the primary API for transporting image data, in favor
of [class@Gdk.Texture]. APIs that are accepting or returning `GdkPixbuf`s are being replaced by equivalent
APIs using `GdkTexture` or [iface@Gdk.Paintable] objects.
+61 -15
View File
@@ -6,7 +6,7 @@ The format is a text format that follows the [CSS syntax rules](https://drafts.c
The grammar of a node text representation using [the CSS value definition syntax](https://drafts.csswg.org/css-values-3/#value-defs) looks like this:
document: <@-rule>*<node>*
document: <@-rule>*<node>
@-rule: @cicp "name" { <property>* }
node: container [ "name" ] { <document> } | <node-type> [ "name" ] { <property>* } | "name"
property: <property-name>: <node> | <value> ;
@@ -49,12 +49,16 @@ The following properties can be set for custom color states:
| primaries | `<integer>` | 2 | always |
| transfer | `<integer>` | 2 | always |
| matrix | `<integer>` | 2 | always |
| range | `narrow | full` | full | non-default |
| range | `<range>` | full | non-default |
Note that the primaries, transfer and matrix properties always need
to be specified, since GTK does not allow creating color state objects
with these being set to 2 (== unspecified).
Range can have the following values:
range: narrow | full
# Colors
Colors can be specified with a variation of the modern CSS color syntax:
@@ -66,6 +70,16 @@ The traditional syntax for sRGB colors still works as well:
rgba(<number>, <number>, <number>, <number)
rgb(<number, <number>, <number>)
# Rectangles
Rectangles can be specified just as four integers for x, y, width and height:
rect: <number> <number> <number> <number>
Rounded rectangles use a CSS-like syntax:
rounded-rect: <rect> [ "/" <number>{1,4} [ "/" <number>{1,4} ] ]
# Nodes
### container
@@ -82,6 +96,13 @@ The **container** node is a special node that allows specifying a list of child
Creates a node like `gsk_blend_node_new()` with the given properties.
Possible values for the mode property are:
blend-mode: normal | multiply | screen | overlay | darken |
lighten | color-dodge | color-burn | hard-light |
soft-light | difference | exclusion | color |
hue | saturation | luminosity
### blur
| property | syntax | default | printed |
@@ -201,6 +222,10 @@ Creates a node like `gsk_fill_node_new()` with the given properties.
The default child node is the default color node, but created with the
bounds of the path.
Possible values for the fill-rule property are:
fill-rule: winding | even-odd
### glshader
| property | syntax | default | printed |
@@ -252,6 +277,10 @@ Creates a node like `gsk_linear_gradient_node_new()` with the given properties.
Creates a node like `gsk_mask_node_new()` with the given properties.
Possible values for the mode property are:
mask-mode: alpha | inverted-alpha | luminance | inverted-luminance
### opacity
| property | syntax | default | printed |
@@ -290,11 +319,11 @@ Creates a node like `gsk_radial_gradient_node_new()` with the given properties.
### repeat
| property | syntax | default | printed |
| ----------- | ---------------- | ---------------------- | ----------- |
| bounds | `<rect>` | *bounds of child node* | non-default |
| child | `<node>` | color { } | always |
| child-bounds| `<rect>` | *bounds of child node* | non-default |
| property | syntax | default | printed |
| ------------ | ---------- | ---------------------- | ----------- |
| bounds | `<rect>` | *bounds of child node* | non-default |
| child | `<node>` | color { } | always |
| child-bounds | `<rect>` | *bounds of child node* | non-default |
Creates a node like `gsk_repeat_node_new()` with the given properties.
@@ -361,6 +390,14 @@ Creates a node like `gsk_stroke_node_new()` with the given properties.
The default child node is the default color node, but created with the
stroke bounds of the path.
Possible values for the line-cap property are:
line-cap: butt | round | square
Possible values for the line-join property are:
line-join: miter | round | bevel
### text
| property | syntax | default | printed |
@@ -369,9 +406,9 @@ stroke bounds of the path.
| font | `<string>` `<url>`? | "Cantarell 15px" | always |
| glyphs | `<glyphs>` | "Hello" | always |
| offset | `<point>` | 0 0 | non-default |
| hint-style | `<hint style>` | slight | non-default |
| hint-style | `<hint-style>` | slight | non-default |
| antialias | `<antialias>` | gray | non-default |
| hint-metrics | `<hint metrics>` | off | non-default |
| hint-metrics | `<hint-metrics>` | off | non-default |
Creates a node like `gsk_text_node_new()` with the given properties.
@@ -386,9 +423,17 @@ be specified as well, like this: 40 10 0 0 color.
If the given font does not exist or the given glyphs are invalid for the given
font, an error node will be returned.
Possible values for hint-style are none, slight or full.
Possible value for antialias are none or gray.
Possible value for hint-metrics are on or off.
Possible values for the hint-style property are:
hint-style: none | slight | full
Possible value for the antialias property are:
antialias: none | gray
Possible value for hint-metrics are:
hint-metrics: on | off
### texture
@@ -414,14 +459,15 @@ representation for this texture is `url("data:image/png;base64,iVBORw0KGgoAAAANS
| -------- | ---------------- | ---------------------- | ----------- |
| bounds | `<rect>` | 50 | always |
| texture | `<url>` | *see below* | always |
| filter | `filter` | *see below* | non-default |
| filter | `filter` | linear | non-default |
Creates a node like `gsk_texture_scale_node_new()` with the given properties.
The default texture is a 10x10 checkerboard, just like for texture.
The possible filter values are `linear`, `nearest` and `trilinear`, with
`linear` being the default.
Possible values for the filter property are:
filter: linear | nearest | trilinear
### transform
+68 -40
View File
@@ -19,8 +19,7 @@ be used for end-user configuration and customization.
### `GTK_DEBUG`
This variable can be set to a list of debug options, which cause GTK to
print out different types of debugging information. Some of these options
are only available when GTK has been configured with `-Ddebug=true`.
print out different types of debugging information.
`actions`
: Actions and menu models
@@ -65,7 +64,7 @@ are only available when GTK has been configured with `-Ddebug=true`.
: Layout managers
`accessibility`
: Accessibility state changs
: Accessibility state changes
A number of keys are influencing behavior instead of just logging:
@@ -169,8 +168,7 @@ The `loaders.cache` file is generated by the
### `GDK_DEBUG`
This variable can be set to a list of debug options, which cause GDK to
print out different types of debugging information. Some of these options
are only available when GTK has been configured with `-Ddebug=true`.
print out different types of debugging information.
`misc`
: Miscellaneous information
@@ -223,36 +221,15 @@ A number of options affect behavior instead of logging:
: Force graphics offload for all textures, even when slower. This allows
to debug offloading in the absence of dmabufs.
`gl-disable`
: Disable OpenGL support
`gl-no-fractional`
: Disable fractional scaling for OpenGL.
`gl-debug`
: Insert debugging information in OpenGL
`gl-disable-gl`
: Don't allow the use of OpenGL GL API. This forces GLES to be used
`gl-disable-gles`
: Don't allow the use of OpenGL GLES API. This forces GL to be used
`gl-prefer-gl`
: Prefer OpenGL over OpenGL ES. This was the default behavior before GTK 4.14.
`gl-egl`
: Use an EGL context on X11 or Windows
`gl-glx`
: Use GLX on X11
`gl-wgl`
: Use WGL on Windows
`vulkan-disable`
: Disable Vulkan support
`vulkan-validate`
: Load the Vulkan validation layer, if available
@@ -262,27 +239,26 @@ A number of options affect behavior instead of logging:
`high-depth`
: Use high bit depth rendering if possible
`linear`
: Enable linear rendering
`hdr`
: Force HDR rendering
`no-vsync`
: Repaint instantly (uses 100% CPU with animations)
`dmabuf-disable`
: Disable dmabuf support
The special value `all` can be used to turn on all debug options. The special
value `help` can be used to obtain a list of all supported debug options.
### `GSK_DEBUG`
This variable can be set to a list of debug options, which cause GSK to
print out different types of debugging information. Some of these options
are only available when GTK has been configured with `-Ddebug=true`.
print out different types of debugging information.
`renderer`
: General renderer information
`opengl`
: OpenGL renderer information
`vulkan`
: Check Vulkan errors
@@ -309,12 +285,12 @@ A number of options affect behavior instead of logging:
`staging`
: Use a staging image for texture upload (Vulkan only)
`offload-disable`
: Disable graphics offload to subsurfaces
`cairo`
: Overlay error pattern over cairo drawing (finds fallbacks)
`occlusion`
: Overlay highlight over areas optimized via occlusion culling
The special value `all` can be used to turn on all debug options. The special
value `help` can be used to obtain a list of all supported debug options.
@@ -347,6 +323,44 @@ a `*`, which means: try all remaining backends. The special value
backends. For more information about selecting backends,
see the [func@Gdk.DisplayManager.get] function.
### `GDK_DISABLE`
This variable can be set to a list of values, which cause GDK to
disable certain features.
`gl`
: Disable OpenGL support
`gl-api`
: Don't allow the use of OpenGL GL API. This forces GLES to be used
`gles-api`
: Don't allow the use of OpenGL GLES API. This forces GL to be used
`egl`
: Don't allow the use of an EGL context
`glx`
: Don't allow the use of GLX
`wgl`
: Don't allow the use of WGL
`vulkan`
: Disable Vulkan support
`dmabuf`
: Disable dmabuf support
`offload`
: Disable graphics offload to subsurfaces
`color-mgmt`
: Disable color management
`session-mgmt`
: Disable session management
### `GDK_GL_DISABLE`
This variable can be set to a list of values, which cause GDK to
@@ -461,12 +475,12 @@ using and the GDK backend supports them:
This variable can be set to a list of values, which cause GSK to
disable certain optimizations of the "ngl" and "vulkan" renderer.
`uber`
: Don't use the uber shader
`clear`
: Use shaders instead of vkCmdClearAttachment()/glClear()
`merge`
: USe one vkCmdDraw()/glDrawArrays() per operation
`blit`
: Use shaders instead of vkCmdBlit()/glBlitFramebuffer()
@@ -476,6 +490,13 @@ disable certain optimizations of the "ngl" and "vulkan" renderer.
`mipmap`
: Avoid creating mipmaps
`to-image`
: Don't fast-path creation of images for nodes
`occlusion`
: Disable occlusion culling via opacity tracking
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.
@@ -563,6 +584,12 @@ To enable the GTK inspector, you can use the <kbd>Control</kbd>+<kbd>Shift</kbd>
<kbd>Control</kbd>+<kbd>Shift</kbd>+<kbd>D</kbd> keyboard shortcuts, or
set the `GTK_DEBUG=interactive` environment variable.
After opening the inspector, it listens for a few keyboard shortcuts that
let you use its frame and event recording functionality without moving the
focus away from the application window: <kbd>Super</kbd>+<kbd>R</kbd> turns
the recording on and off, and <kbd>Super</kbd>+<kbd>C</kbd> records a single
frame.
There are a few more environment variables that can be set to influence
how the inspector renders its UI. `GTK_INSPECTOR_DISPLAY` and
`GTK_INSPECTOR_RENDERER` determine the GDK display and the GSK
@@ -573,6 +600,7 @@ the GTK inspector. The keyboard shortcuts can be disabled with the
`enable-inspector-keybinding` key in the `org.gtk.Settings.Debug`
GSettings schema.
## Profiling
GTK supports profiling with sysprof. It exports timing information
+2 -2
View File
@@ -171,7 +171,7 @@ Each relation name is part of the `GtkAccessibleRelation` enumeration.
| %GTK_ACCESSIBLE_RELATION_CONTROLS | “aria-controls” | a list of `GtkAccessible` |
| %GTK_ACCESSIBLE_RELATION_DESCRIBED_BY | “aria-describedby” | a list of `GtkAccessible` |
| %GTK_ACCESSIBLE_RELATION_DETAILS | “aria-details” | a list of `GtkAccessible` |
| %GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE | “aria-errormessage” | `GtkAccessible` |
| %GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE | “aria-errormessage” | a list of `GtkAccessible` |
| %GTK_ACCESSIBLE_RELATION_FLOW_TO | “aria-flowto” | a list of `GtkAccessible` |
| %GTK_ACCESSIBLE_RELATION_LABELLED_BY | “aria-labelledby” | a list of `GtkAccessible` |
| %GTK_ACCESSIBLE_RELATION_OWNS | “aria-owns” | a list of `GtkAccessible` |
@@ -300,7 +300,7 @@ The attributes can also enhance the UI:
```c
gtk_button_set_label (GTK_BUTTON (button), "Download");
gtk_box_append (GTK_BOX (button), button);
gtk_box_append (GTK_BOX (box), button);
gtk_label_set_text (GTK_LABEL (label), "Final report.pdf");
gtk_box_append (GTK_BOX (box), label);
+1
View File
@@ -9,6 +9,7 @@ documentation in the form of man pages.
- [gtk4-demo-application](gtk4-demo-application.html)
- [gtk4-encode-symbolic-svg](gtk4-encode-symbolic-svg.html)
- [gtk4-icon-browser](gtk4-icon-browser.html)
- [gtk4-image-tool](gtk4-image-tool.html)
- [gtk4-launch](gtk4-launch.html)
- [gtk4-node-editor](gtk4-node-editor.html)
- [gtk4-path-tool](gtk4-path-tool.html)
+178 -52
View File
@@ -49,6 +49,135 @@
G_DEFINE_TYPE (GdkBroadwaySurface, gdk_broadway_surface, GDK_TYPE_SURFACE)
static void
gdk_broadway_surface_toplevel_resize (GdkSurface *surface,
int width,
int height);
static void
gdk_broadway_surface_set_geometry_hints (GdkSurface *surface,
const GdkGeometry *geometry,
GdkSurfaceHints geom_mask);
static void
gdk_broadway_surface_move_resize_internal (GdkSurface *surface,
gboolean with_move,
int x,
int y,
int width,
int height);
static void
compute_toplevel_size (GdkSurface *surface,
gboolean resizible,
int *width,
int *height)
{
GdkBroadwaySurface *impl = GDK_BROADWAY_SURFACE (surface);
GdkDisplay *display = gdk_surface_get_display (surface);
GdkMonitor *monitor;
GdkToplevelSize size;
int bounds_width, bounds_height;
GdkGeometry geometry;
GdkSurfaceHints mask;
monitor = gdk_display_get_monitor_at_surface (display, surface);
if (monitor)
{
GdkRectangle monitor_geometry;
gdk_monitor_get_geometry (monitor, &monitor_geometry);
bounds_width = monitor_geometry.width;
bounds_height = monitor_geometry.height;
}
else
{
bounds_width = G_MAXINT;
bounds_height = G_MAXINT;
}
gdk_toplevel_size_init (&size, bounds_width, bounds_height);
gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
g_warn_if_fail (size.width > 0);
g_warn_if_fail (size.height > 0);
*width = size.width;
*height = size.height;
impl->resizible = (impl->resizible && resizible);
if (impl->resizible)
{
geometry.min_width = size.min_width;
geometry.min_height = size.min_height;
mask = GDK_HINT_MIN_SIZE;
}
else
{
geometry.max_width = geometry.min_width = size.width;
geometry.max_height = geometry.min_height = size.height;
mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
}
gdk_broadway_surface_set_geometry_hints (surface, &geometry, mask);
if (!(surface->state & (GDK_TOPLEVEL_STATE_FULLSCREEN |
GDK_TOPLEVEL_STATE_MAXIMIZED |
GDK_TOPLEVEL_STATE_TILED |
GDK_TOPLEVEL_STATE_TOP_TILED |
GDK_TOPLEVEL_STATE_RIGHT_TILED |
GDK_TOPLEVEL_STATE_BOTTOM_TILED |
GDK_TOPLEVEL_STATE_LEFT_TILED |
GDK_TOPLEVEL_STATE_MINIMIZED)))
{
gdk_surface_constrain_size (&geometry, mask,
size.width, size.height,
&size.width, &size.height);
if (impl->last_computed_width != size.width ||
impl->last_computed_height != size.height)
{
*width = size.width;
*height = size.height;
impl->last_computed_width = size.width;
impl->last_computed_height = size.height;
gdk_broadway_surface_toplevel_resize (surface, *width, *height);
}
}
if (size.shadow.is_valid)
{
impl->shadow_left = size.shadow.left;
impl->shadow_right = size.shadow.right;
impl->shadow_top = size.shadow.top;
impl->shadow_bottom = size.shadow.bottom;
}
}
static gboolean
compute_size_idle (gpointer user_data)
{
GdkSurface *surface = user_data;
GdkBroadwaySurface *impl = GDK_BROADWAY_SURFACE (surface);
int width, height;
impl->compute_size_source_id = 0;
compute_toplevel_size (surface, TRUE, &width, &height);
return G_SOURCE_REMOVE;
}
static void
on_frame_clock_after_update (GdkFrameClock *clock,
GdkSurface *surface)
{
GdkBroadwaySurface *impl = GDK_BROADWAY_SURFACE (surface);
if (impl->compute_size_source_id)
{
g_clear_handle_id (&impl->compute_size_source_id, g_source_remove);
compute_size_idle (surface);
}
}
/* We need to flush in an idle rather than AFTER_PAINT, as the clock
is frozen during e.g. surface resizes so the paint will not happen
and the surface resize request is never flushed. */
@@ -112,6 +241,8 @@ connect_frame_clock (GdkSurface *surface)
g_signal_connect (frame_clock, "before-paint",
G_CALLBACK (on_frame_clock_before_paint), surface);
g_signal_connect_after (frame_clock, "update",
G_CALLBACK (on_frame_clock_after_update), surface);
g_signal_connect (frame_clock, "after-paint",
G_CALLBACK (on_frame_clock_after_paint), surface);
}
@@ -123,6 +254,8 @@ disconnect_frame_clock (GdkSurface *surface)
g_signal_handlers_disconnect_by_func (frame_clock,
on_frame_clock_before_paint, surface);
g_signal_handlers_disconnect_by_func (frame_clock,
on_frame_clock_after_update, surface);
g_signal_handlers_disconnect_by_func (frame_clock,
on_frame_clock_after_paint, surface);
}
@@ -137,6 +270,7 @@ gdk_broadway_surface_constructed (GObject *object)
if (!surface->parent)
broadway_display->toplevels = g_list_prepend (broadway_display->toplevels, self);
self->resizible = TRUE;
self->id = _gdk_broadway_server_new_surface (broadway_display->server,
self->root_x,
self->root_y,
@@ -316,6 +450,7 @@ gdk_broadway_surface_hide (GdkSurface *surface)
_gdk_broadway_surface_grab_check_unmap (surface,
_gdk_broadway_server_get_next_serial (broadway_display->server));
g_clear_handle_id (&impl->compute_size_source_id, g_source_remove);
if (_gdk_broadway_server_surface_hide (broadway_display->server, impl->id))
queue_flush (surface);
@@ -1009,6 +1144,8 @@ _gdk_broadway_moveresize_configure_done (GdkDisplay *display,
BroadwayInputMsg *tmp_event;
MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
gdk_surface_request_layout (surface);
if (!mv_resize || surface != mv_resize->moveresize_surface)
return FALSE;
@@ -1168,6 +1305,43 @@ gdk_broadway_surface_beep (GdkSurface *surface)
return FALSE;
}
static void
gdk_broadway_surface_request_layout (GdkSurface *surface)
{
GdkBroadwaySurface *impl = GDK_BROADWAY_SURFACE (surface);
if (!impl->compute_size_source_id &&
GDK_IS_TOPLEVEL (surface))
{
impl->compute_size_source_id = g_idle_add_full (G_PRIORITY_HIGH - 10,
compute_size_idle,
surface,
NULL);
}
}
static gboolean
gdk_broadway_surface_compute_size (GdkSurface *surface)
{
int width, height;
if (GDK_IS_TOPLEVEL (surface))
{
compute_toplevel_size (surface, TRUE, &width, &height);
}
else
{
width = gdk_surface_get_width(surface);
height = gdk_surface_get_height(surface);
gdk_broadway_surface_move_resize_internal (surface, FALSE,
0, 0,
width,
height);
}
return FALSE;
}
static void
gdk_broadway_surface_class_init (GdkBroadwaySurfaceClass *klass)
{
@@ -1187,6 +1361,8 @@ gdk_broadway_surface_class_init (GdkBroadwaySurfaceClass *klass)
impl_class->destroy_notify = gdk_broadway_surface_destroy_notify;
impl_class->drag_begin = _gdk_broadway_surface_drag_begin;
impl_class->get_scale = gdk_broadway_surface_get_scale;
impl_class->request_layout = gdk_broadway_surface_request_layout;
impl_class->compute_size = gdk_broadway_surface_compute_size;
}
#define LAST_PROP 1
@@ -1504,55 +1680,12 @@ gdk_broadway_toplevel_present (GdkToplevel *toplevel,
GdkToplevelLayout *layout)
{
GdkSurface *surface = GDK_SURFACE (toplevel);
GdkBroadwaySurface *impl = GDK_BROADWAY_SURFACE (surface);
GdkDisplay *display = gdk_surface_get_display (surface);
GdkMonitor *monitor;
GdkToplevelSize size;
int bounds_width, bounds_height;
int width, height;
GdkGeometry geometry;
GdkSurfaceHints mask;
gboolean maximize;
gdk_broadway_surface_unminimize (surface);
monitor = gdk_display_get_monitor_at_surface (display, surface);
if (monitor)
{
GdkRectangle monitor_geometry;
gdk_monitor_get_geometry (monitor, &monitor_geometry);
bounds_width = monitor_geometry.width;
bounds_height = monitor_geometry.height;
}
else
{
bounds_width = G_MAXINT;
bounds_height = G_MAXINT;
}
gdk_toplevel_size_init (&size, bounds_width, bounds_height);
gdk_toplevel_notify_compute_size (toplevel, &size);
g_warn_if_fail (size.width > 0);
g_warn_if_fail (size.height > 0);
width = size.width;
height = size.height;
if (gdk_toplevel_layout_get_resizable (layout))
{
geometry.min_width = size.min_width;
geometry.min_height = size.min_height;
mask = GDK_HINT_MIN_SIZE;
}
else
{
geometry.max_width = geometry.min_width = width;
geometry.max_height = geometry.min_height = height;
mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
}
gdk_broadway_surface_set_geometry_hints (surface, &geometry, mask);
gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
gdk_broadway_surface_toplevel_resize (surface, width, height);
compute_toplevel_size (surface, gdk_toplevel_layout_get_resizable (layout), &width, &height);
if (gdk_toplevel_layout_get_maximized (layout, &maximize))
{
@@ -1562,14 +1695,7 @@ gdk_broadway_toplevel_present (GdkToplevel *toplevel,
gdk_broadway_surface_unmaximize (surface);
}
if (size.shadow.is_valid)
{
impl->shadow_left = size.shadow.left;
impl->shadow_right = size.shadow.right;
impl->shadow_top = size.shadow.top;
impl->shadow_bottom = size.shadow.bottom;
}
gdk_surface_request_layout (surface);
show_surface (surface);
}
+7
View File
@@ -76,6 +76,13 @@ struct _GdkBroadwaySurface
int shadow_right;
int shadow_top;
int shadow_bottom;
int last_computed_width;
int last_computed_height;
guint compute_size_source_id;
gboolean resizible;
};
struct _GdkBroadwaySurfaceClass
+38 -17
View File
@@ -133,22 +133,36 @@ static const GdkDebugKey gdk_debug_keys[] = {
{ "portals", GDK_DEBUG_PORTALS, "Force use of portals" },
{ "no-portals", GDK_DEBUG_NO_PORTALS, "Disable use of portals" },
{ "force-offload", GDK_DEBUG_FORCE_OFFLOAD, "Force graphics offload for all textures" },
{ "gl-disable", GDK_DEBUG_GL_DISABLE, "Disable OpenGL support" },
{ "gl-no-fractional", GDK_DEBUG_GL_NO_FRACTIONAL, "Disable fractional scaling for OpenGL" },
{ "gl-debug", GDK_DEBUG_GL_DEBUG, "Insert debugging information in OpenGL" },
{ "gl-disable-gl", GDK_DEBUG_GL_DISABLE_GL, "Only allow OpenGL GLES API" },
{ "gl-disable-gles", GDK_DEBUG_GL_DISABLE_GLES, "Don't allow OpenGL GLES API" },
{ "gl-prefer-gl", GDK_DEBUG_GL_PREFER_GL, "Prefer GL over GLES API" },
{ "gl-egl", GDK_DEBUG_GL_EGL, "Use EGL on X11 or Windows" },
{ "gl-glx", GDK_DEBUG_GL_GLX, "Use GLX on X11" },
{ "gl-wgl", GDK_DEBUG_GL_WGL, "Use WGL on Windows" },
{ "vulkan-disable", GDK_DEBUG_VULKAN_DISABLE, "Disable Vulkan support" },
{ "default-settings",GDK_DEBUG_DEFAULT_SETTINGS, "Force default values for xsettings" },
{ "high-depth", GDK_DEBUG_HIGH_DEPTH, "Use high bit depth rendering if possible" },
{ "no-vsync", GDK_DEBUG_NO_VSYNC, "Repaint instantly (uses 100% CPU with animations)" },
{ "dmabuf-disable", GDK_DEBUG_DMABUF_DISABLE, "Disable dmabuf support" },
};
static const GdkDebugKey gdk_feature_keys[] = {
{ "gl", GDK_FEATURE_OPENGL, "Disable OpenGL support" },
{ "gl-api", GDK_FEATURE_GL_API, "Disable non-GLES GL API" },
{ "gles-api", GDK_FEATURE_GLES_API, "Disable GLES GL API" },
{ "egl", GDK_FEATURE_EGL, "Disable EGL" },
{ "glx", GDK_FEATURE_GLX, "Disable GLX" },
{ "wgl", GDK_FEATURE_WGL, "Disable WGL" },
{ "vulkan", GDK_FEATURE_VULKAN, "Disable Vulkan support" },
{ "dmabuf", GDK_FEATURE_DMABUF, "Disable dmabuf support" },
{ "offload", GDK_FEATURE_OFFLOAD, "Disable graphics offload" },
{ "color-mgmt", GDK_FEATURE_COLOR_MANAGEMENT, "Disable color management" },
{ "session-mgmt", GDK_FEATURE_SESSION_MANAGEMENT, "Disable session management" },
};
static GdkFeatures gdk_features;
gboolean
gdk_has_feature (GdkFeatures features)
{
return (features & gdk_features) == features;
}
#ifdef G_HAS_CONSTRUCTORS
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
@@ -216,6 +230,7 @@ gdk_ensure_resources (void)
guint
gdk_parse_debug_var (const char *variable,
const char *docs,
const GdkDebugKey *keys,
guint nkeys)
{
@@ -276,6 +291,7 @@ gdk_parse_debug_var (const char *variable,
max_width = MAX (max_width, strlen (keys[i].key));
max_width += 4;
fprintf (stderr, "%s\n", docs);
fprintf (stderr, "Supported %s values:\n", variable);
for (i = 0; i < nkeys; i++) {
fprintf (stderr, " %s%*s%s\n", keys[i].key, (int)(max_width - strlen (keys[i].key)), " ", keys[i].help);
@@ -303,21 +319,26 @@ gdk_parse_debug_var (const char *variable,
void
gdk_pre_parse (void)
{
GdkFeatures disabled_features;
gdk_initialized = TRUE;
gdk_ensure_resources ();
_gdk_debug_flags = gdk_parse_debug_var ("GDK_DEBUG",
gdk_debug_keys,
G_N_ELEMENTS (gdk_debug_keys));
"GDK_DEBUG can be set to values that make GDK print out different\n"
"types of debugging information or change the behavior of GDK for\n"
"debugging purposes.\n",
gdk_debug_keys,
G_N_ELEMENTS (gdk_debug_keys));
/* These are global */
if (_gdk_debug_flags & GDK_DEBUG_GL_EGL)
gdk_gl_backend_use (GDK_GL_EGL);
else if (_gdk_debug_flags & GDK_DEBUG_GL_GLX)
gdk_gl_backend_use (GDK_GL_GLX);
else if (_gdk_debug_flags & GDK_DEBUG_GL_WGL)
gdk_gl_backend_use (GDK_GL_WGL);
disabled_features = gdk_parse_debug_var ("GDK_DISABLE",
"GDK_DISABLE can be set to values which cause GDK to disable\n"
"certain features.\n",
gdk_feature_keys,
G_N_ELEMENTS (gdk_feature_keys));
gdk_features = GDK_ALL_FEATURES & ~disabled_features;
#ifndef G_HAS_CONSTRUCTORS
stash_and_unset_environment ();
+2
View File
@@ -82,8 +82,10 @@ gdk_cairo_context_cairo_create (GdkCairoContext *self)
draw_context = GDK_DRAW_CONTEXT (self);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
if (!gdk_draw_context_is_in_frame (draw_context))
return NULL;
G_GNUC_END_IGNORE_DEPRECATIONS
cr = GDK_CAIRO_CONTEXT_GET_CLASS (self)->cairo_create (self);
-1
View File
@@ -168,7 +168,6 @@ gdk_cicp_params_class_init (GdkCicpParamsClass *klass)
* - 5: PAL
* - 6,7: BT.601 / NTSC
* - 9: BT.2020
* - 10: CIE XYZ
* - 12: Display P3
*
* Since: 4.16
+1 -1
View File
@@ -58,7 +58,7 @@ void gdk_cicp_params_set_matrix_coefficients (GdkCicpParams *self,
/**
* GdkCicpRange:
* @GDK_CICP_RANGE_NARROW: The values use the range of 16-235 (for Y) and 16-240 for u and v.
* @GDK_CICO_RANGE_FULL: The values use the full range.
* @GDK_CICP_RANGE_FULL: The values use the full range.
*
* The values of this enumeration describe whether image data uses
* the full range of 8-bit values.
+29 -21
View File
@@ -20,11 +20,17 @@
* and tests, and must not include other headers.
*/
static inline int
sign (float v)
{
return v < 0 ? -1 : 1;
}
static inline float
srgb_oetf (float v)
{
if (v > 0.0031308f)
return 1.055f * powf (v, 1.f / 2.4f) - 0.055f;
if (fabsf (v) > 0.0031308f)
return sign (v) * (1.055f * powf (fabsf (v), 1.f / 2.4f) - 0.055f);
else
return 12.92f * v;
}
@@ -32,8 +38,8 @@ srgb_oetf (float v)
static inline float
srgb_eotf (float v)
{
if (v >= 0.04045f)
return powf (((v + 0.055f) / (1.f + 0.055f)), 2.4f);
if (fabsf (v) >= 0.04045f)
return sign (v) * powf (((fabsf (v) + 0.055f) / (1.f + 0.055f)), 2.4f);
else
return v / 12.92f;
}
@@ -41,25 +47,25 @@ srgb_eotf (float v)
static inline float
gamma22_oetf (float v)
{
return powf (v, 1.f / 2.2f);
return sign (v) * powf (fabsf (v), 1.f / 2.2f);
}
static inline float
gamma22_eotf (float v)
{
return powf (v, 2.2f);
return sign (v) * powf (fabsf (v), 2.2f);
}
static inline float
gamma28_oetf (float v)
{
return powf (v, 1.f / 2.8f);
return sign (v) * powf (fabsf (v), 1.f / 2.8f);
}
static inline float
gamma28_eotf (float v)
{
return powf (v, 2.8f);
return sign (v) * powf (fabsf (v), 2.8f);
}
static inline float
@@ -71,9 +77,10 @@ pq_eotf (float v)
float c2 = 2413.0 / (1 << 7);
float c3 = 2392.0 / (1 << 7);
float x = powf (MAX ((powf (v, minv) - c1), 0) / (c2 - (c3 * (powf (v, minv)))), ninv);
float x = powf (fabsf (v), minv);
x = powf (MAX ((x - c1), 0) / (c2 - (c3 * x)), ninv);
return x * 10000 / 203.0;
return sign (v) * x * 10000 / 203.0;
}
static inline float
@@ -86,7 +93,8 @@ pq_oetf (float v)
float c2 = 2413.0 / (1 << 7);
float c3 = 2392.0 / (1 << 7);
return powf (((c1 + (c2 * powf (x, n))) / (1 + (c3 * powf (x, n)))), m);
x = powf (fabsf (x), n);
return sign (v) * powf (((c1 + (c2 * x)) / (1 + (c3 * x))), m);
}
static inline float
@@ -95,10 +103,10 @@ bt709_eotf (float v)
const float a = 1.099;
const float d = 0.0812;
if (v < d)
if (fabsf (v) < d)
return v / 4.5f;
else
return powf ((v + (a - 1)) / a, 1 / 0.45f);
return sign (v) * powf ((fabsf (v) + (a - 1)) / a, 1 / 0.45f);
}
static inline float
@@ -107,10 +115,10 @@ bt709_oetf (float v)
const float a = 1.099;
const float b = 0.018;
if (v < b)
if (fabsf (v) < b)
return v * 4.5f;
else
return a * powf (v, 0.45f) - (a - 1);
return sign (v) * (a * powf (fabsf (v), 0.45f) - (a - 1));
}
static inline float
@@ -120,10 +128,10 @@ hlg_eotf (float v)
const float b = 0.28466892;
const float c = 0.55991073;
if (v <= 0.5)
return (v * v) / 3;
if (fabsf (v) <= 0.5)
return sign (v) * (v * v) / 3;
else
return (expf ((v - c) / a) + b) / 12.0;
return sign (v) * (expf ((fabsf (v) - c) / a) + b) / 12.0;
}
static inline float
@@ -133,10 +141,10 @@ hlg_oetf (float v)
const float b = 0.28466892;
const float c = 0.55991073;
if (v <= 1/12.0)
return sqrtf (3 * v);
if (fabsf (v) <= 1/12.0)
return sign (v) * sqrtf (3 * fabsf (v));
else
return a * logf (12 * v - b) + c;
return sign (v) * (a * logf (12 * fabsf (v) - b) + c);
}
/* See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
+4 -1
View File
@@ -116,7 +116,10 @@ _gdk_color_to_float (const GdkColor *self,
{
if (gdk_color_state_equal (self->color_state, color_state))
{
memcpy (values, self->values, sizeof (float) * 4);
values[0] = self->values[0];
values[1] = self->values[1];
values[2] = self->values[2];
values[3] = self->values[3];
return;
}
+114 -31
View File
@@ -38,9 +38,9 @@
* Crucially, GTK knows how to convert colors from one color
* state to another.
*
* `GdkColorState objects are immutable and therefore threadsafe.
* `GdkColorState` objects are immutable and therefore threadsafe.
*
* Since 4.16
* Since: 4.16
*/
G_DEFINE_BOXED_TYPE (GdkColorState, gdk_color_state,
@@ -331,6 +331,68 @@ gdk_default_color_state_get_cicp (GdkColorState *color_state)
return &self->cicp;
}
static gboolean
gdk_color_state_check_inf_nan (const float src[4],
float dest[4])
{
if (isnan (src[0]) ||
isnan (src[1]) ||
isnan (src[2]) ||
isnan (src[3]))
{
dest = (float[4]) { 1.0, 0.0, 0.8, 1.0 };
return TRUE;
}
if (isinf (src[0]) ||
isinf (src[1]) ||
isinf (src[2]) ||
isinf (src[3]))
{
dest = (float[4]) { 0.0, 0.8, 1.0, 1.0 };
return TRUE;
}
return FALSE;
}
static void
gdk_color_state_clamp_0_1 (GdkColorState *self,
const float src[4],
float dest[4])
{
if (gdk_color_state_check_inf_nan (src, dest))
return;
dest[0] = CLAMP (src[0], 0.0f, 1.0f);
dest[1] = CLAMP (src[1], 0.0f, 1.0f);
dest[2] = CLAMP (src[2], 0.0f, 1.0f);
dest[3] = CLAMP (src[3], 0.0f, 1.0f);
}
static void
gdk_color_state_clamp_unbounded (GdkColorState *self,
const float src[4],
float dest[4])
{
if (gdk_color_state_check_inf_nan (src, dest))
return;
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = CLAMP (src[3], 0.0f, 1.0f);
}
static void
gdk_default_color_state_clamp (GdkColorState *color_state,
const float in[4],
float out[4])
{
GdkDefaultColorState *self = (GdkDefaultColorState *) color_state;
self->clamp (color_state, in, out);
}
/* }}} */
static const
@@ -342,6 +404,7 @@ GdkColorStateClass GDK_DEFAULT_COLOR_STATE_CLASS = {
.get_convert_to = gdk_default_color_state_get_convert_to,
.get_convert_from = gdk_default_color_state_get_convert_from,
.get_cicp = gdk_default_color_state_get_cicp,
.clamp = gdk_default_color_state_clamp,
};
GdkDefaultColorState gdk_default_color_states[] = {
@@ -350,7 +413,8 @@ GdkDefaultColorState gdk_default_color_states[] = {
.klass = &GDK_DEFAULT_COLOR_STATE_CLASS,
.ref_count = 0,
.depth = GDK_MEMORY_U8_SRGB,
.rendering_color_state = GDK_COLOR_STATE_SRGB_LINEAR,
.rendering_color_state = GDK_COLOR_STATE_SRGB,
.rendering_color_state_linear = GDK_COLOR_STATE_SRGB_LINEAR,
},
.name = "srgb",
.no_srgb = GDK_COLOR_STATE_SRGB_LINEAR,
@@ -359,6 +423,7 @@ GdkDefaultColorState gdk_default_color_states[] = {
[GDK_COLOR_STATE_ID_REC2100_PQ] = gdk_default_srgb_to_rec2100_pq,
[GDK_COLOR_STATE_ID_REC2100_LINEAR] = gdk_default_srgb_to_rec2100_linear,
},
.clamp = gdk_color_state_clamp_0_1,
.cicp = { 1, 13, 0, 1 },
},
[GDK_COLOR_STATE_ID_SRGB_LINEAR] = {
@@ -367,6 +432,7 @@ GdkDefaultColorState gdk_default_color_states[] = {
.ref_count = 0,
.depth = GDK_MEMORY_U8,
.rendering_color_state = GDK_COLOR_STATE_SRGB_LINEAR,
.rendering_color_state_linear = GDK_COLOR_STATE_SRGB_LINEAR,
},
.name = "srgb-linear",
.no_srgb = NULL,
@@ -375,6 +441,7 @@ GdkDefaultColorState gdk_default_color_states[] = {
[GDK_COLOR_STATE_ID_REC2100_PQ] = gdk_default_srgb_linear_to_rec2100_pq,
[GDK_COLOR_STATE_ID_REC2100_LINEAR] = gdk_default_srgb_linear_to_rec2100_linear,
},
.clamp = gdk_color_state_clamp_0_1,
.cicp = { 1, 8, 0, 1 },
},
[GDK_COLOR_STATE_ID_REC2100_PQ] = {
@@ -382,7 +449,8 @@ GdkDefaultColorState gdk_default_color_states[] = {
.klass = &GDK_DEFAULT_COLOR_STATE_CLASS,
.ref_count = 0,
.depth = GDK_MEMORY_FLOAT16,
.rendering_color_state = GDK_COLOR_STATE_REC2100_LINEAR,
.rendering_color_state = GDK_COLOR_STATE_REC2100_PQ,
.rendering_color_state_linear = GDK_COLOR_STATE_REC2100_LINEAR,
},
.name = "rec2100-pq",
.no_srgb = NULL,
@@ -391,6 +459,7 @@ GdkDefaultColorState gdk_default_color_states[] = {
[GDK_COLOR_STATE_ID_SRGB_LINEAR] = gdk_default_rec2100_pq_to_srgb_linear,
[GDK_COLOR_STATE_ID_REC2100_LINEAR] = gdk_default_rec2100_pq_to_rec2100_linear,
},
.clamp = gdk_color_state_clamp_0_1,
.cicp = { 9, 16, 0, 1 },
},
[GDK_COLOR_STATE_ID_REC2100_LINEAR] = {
@@ -399,6 +468,7 @@ GdkDefaultColorState gdk_default_color_states[] = {
.ref_count = 0,
.depth = GDK_MEMORY_FLOAT16,
.rendering_color_state = GDK_COLOR_STATE_REC2100_LINEAR,
.rendering_color_state_linear = GDK_COLOR_STATE_REC2100_LINEAR,
},
.name = "rec2100-linear",
.no_srgb = NULL,
@@ -407,6 +477,7 @@ GdkDefaultColorState gdk_default_color_states[] = {
[GDK_COLOR_STATE_ID_SRGB_LINEAR] = gdk_default_rec2100_linear_to_srgb_linear,
[GDK_COLOR_STATE_ID_REC2100_PQ] = gdk_default_rec2100_linear_to_rec2100_pq,
},
.clamp = gdk_color_state_clamp_unbounded,
.cicp = { 9, 8, 0, 1 },
},
};
@@ -421,15 +492,15 @@ struct _GdkCicpColorState
GdkColorState *no_srgb;
const char *name;
char *name;
GdkTransferFunc eotf;
GdkTransferFunc oetf;
float *to_srgb;
float *to_rec2020;
float *from_srgb;
float *from_rec2020;
float to_srgb[9];
float to_rec2020[9];
float from_srgb[9];
float from_rec2020[9];
GdkCicp cicp;
};
@@ -449,7 +520,6 @@ TRANSFORM(gdk_cicp_from_rec2100_linear, NONE, cicp->from_rec2020, cicp->o
#undef cicp
/* }}} */
/* }}} */
/* {{{ Vfuncs */
@@ -458,14 +528,11 @@ gdk_cicp_color_state_free (GdkColorState *cs)
{
GdkCicpColorState *self = (GdkCicpColorState *) cs;
g_free (self->name);
if (self->no_srgb)
gdk_color_state_unref (self->no_srgb);
g_free (self->to_srgb);
g_free (self->to_rec2020);
g_free (self->from_srgb);
g_free (self->from_rec2020);
g_free (self);
}
@@ -555,7 +622,7 @@ gdk_cicp_color_state_get_cicp (GdkColorState *color_state)
return &self->cicp;
}
/* }}} */
/* }}} */
static const
GdkColorStateClass GDK_CICP_COLOR_STATE_CLASS = {
@@ -566,6 +633,7 @@ GdkColorStateClass GDK_CICP_COLOR_STATE_CLASS = {
.get_convert_to = gdk_cicp_color_state_get_convert_to,
.get_convert_from = gdk_cicp_color_state_get_convert_from,
.get_cicp = gdk_cicp_color_state_get_cicp,
.clamp = gdk_color_state_clamp_0_1,
};
static inline float *
@@ -676,10 +744,6 @@ gdk_color_state_new_for_cicp (const GdkCicp *cicp,
to_xyz = rec2020_to_xyz;
from_xyz = xyz_to_rec2020;
break;
case 10:
to_xyz = identity;
from_xyz = identity;
break;
case 12:
to_xyz = p3_to_xyz;
from_xyz = xyz_to_p3;
@@ -698,7 +762,8 @@ gdk_color_state_new_for_cicp (const GdkCicp *cicp,
self->parent.ref_count = 1;
/* sRGB is special-cased by being a default colorstate */
self->parent.rendering_color_state = GDK_COLOR_STATE_REC2100_LINEAR;
self->parent.rendering_color_state = GDK_COLOR_STATE_REC2100_PQ;
self->parent.rendering_color_state_linear = GDK_COLOR_STATE_REC2100_LINEAR;
self->parent.depth = GDK_MEMORY_FLOAT16;
@@ -707,10 +772,10 @@ gdk_color_state_new_for_cicp (const GdkCicp *cicp,
self->eotf = eotf;
self->oetf = oetf;
self->to_srgb = multiply (g_new (float, 9), xyz_to_srgb, to_xyz);
self->to_rec2020 = multiply (g_new (float, 9), xyz_to_rec2020, to_xyz);
self->from_srgb = multiply (g_new (float, 9), from_xyz, srgb_to_xyz);
self->from_rec2020 = multiply (g_new (float, 9), from_xyz, rec2020_to_xyz);
multiply (self->to_srgb, xyz_to_srgb, to_xyz);
multiply (self->to_rec2020, xyz_to_rec2020, to_xyz);
multiply (self->from_srgb, from_xyz, srgb_to_xyz);
multiply (self->from_rec2020, from_xyz, rec2020_to_xyz);
self->name = g_strdup_printf ("cicp-%u/%u/%u/%u",
cicp->color_primaries,
@@ -720,12 +785,12 @@ gdk_color_state_new_for_cicp (const GdkCicp *cicp,
if (cicp->transfer_function == 13)
{
GdkCicp no_srgb;
memcpy (&no_srgb, cicp, sizeof (GdkCicp));
no_srgb.transfer_function = 8;
self->no_srgb = gdk_color_state_new_for_cicp (&no_srgb, NULL);
self->no_srgb = gdk_color_state_new_for_cicp (&(GdkCicp) {
cicp->color_primaries,
8,
cicp->matrix_coefficients,
cicp->range },
NULL);
}
return (GdkColorState *) self;
@@ -773,6 +838,24 @@ gdk_color_state_get_no_srgb_tf (GdkColorState *self)
return self->klass->get_no_srgb_tf (self);
}
/*< private >
* gdk_color_state_clamp:
* @self: a `GdkColorState`
* @src: the values to clamp
* @dest: (out): location to store the result, may be identical to
* the src argument
*
* Clamps the values to be within the allowed ranges for the given
* color state.
*/
void
gdk_color_state_clamp (GdkColorState *self,
const float src[4],
float dest[4])
{
self->klass->clamp (self, src, dest);
}
/* }}} */
/* vim:set foldmethod=marker expandtab: */
+17 -4
View File
@@ -26,6 +26,7 @@ struct _GdkColorState
GdkMemoryDepth depth;
GdkColorState *rendering_color_state;
GdkColorState *rendering_color_state_linear;
};
/* Note: self may be the source or the target colorstate */
@@ -45,6 +46,9 @@ struct _GdkColorStateClass
GdkFloatColorConvert (* get_convert_from) (GdkColorState *self,
GdkColorState *source);
const GdkCicp * (* get_cicp) (GdkColorState *self);
void (* clamp) (GdkColorState *self,
const float src[4],
float dest[4]);
};
typedef struct _GdkDefaultColorState GdkDefaultColorState;
@@ -56,6 +60,9 @@ struct _GdkDefaultColorState
const char *name;
GdkColorState *no_srgb;
GdkFloatColorConvert convert_to[GDK_COLOR_STATE_N_IDS];
void (* clamp) (GdkColorState *self,
const float src[4],
float dest[4]);
GdkCicp cicp;
};
@@ -77,6 +84,10 @@ GdkColorState * gdk_color_state_get_no_srgb_tf (GdkColorState
GdkColorState * gdk_color_state_new_for_cicp (const GdkCicp *cicp,
GError **error);
void gdk_color_state_clamp (GdkColorState *self,
const float src[4],
float dest[4]);
static inline GdkColorState *
gdk_color_state_get_rendering_color_state (GdkColorState *self)
{
@@ -84,9 +95,9 @@ gdk_color_state_get_rendering_color_state (GdkColorState *self)
self = GDK_COLOR_STATE_REC2100_PQ;
if (!GDK_DEBUG_CHECK (LINEAR))
return self;
return self->rendering_color_state;
return self->rendering_color_state;
return self->rendering_color_state_linear;
}
static inline GdkMemoryDepth
@@ -176,7 +187,10 @@ gdk_color_state_convert_color (GdkColorState *src_cs,
GdkFloatColorConvert convert = NULL;
GdkFloatColorConvert convert2 = NULL;
memcpy (dest, src, sizeof (float) * 4);
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
if (gdk_color_state_equal (src_cs, dest_cs))
return;
@@ -210,4 +224,3 @@ gdk_color_state_from_rgba (GdkColorState *self,
self,
out_color);
}
+26 -15
View File
@@ -44,29 +44,39 @@ typedef enum {
GDK_DEBUG_HDR = 1 << 14,
GDK_DEBUG_PORTALS = 1 << 15,
GDK_DEBUG_NO_PORTALS = 1 << 16,
GDK_DEBUG_GL_DISABLE = 1 << 17,
GDK_DEBUG_GL_NO_FRACTIONAL= 1 << 18,
GDK_DEBUG_FORCE_OFFLOAD = 1 << 19,
GDK_DEBUG_GL_DISABLE_GL = 1 << 20,
GDK_DEBUG_GL_DISABLE_GLES = 1 << 21,
GDK_DEBUG_GL_PREFER_GL = 1 << 22,
GDK_DEBUG_GL_DEBUG = 1 << 23,
GDK_DEBUG_GL_EGL = 1 << 24,
GDK_DEBUG_GL_GLX = 1 << 25,
GDK_DEBUG_GL_WGL = 1 << 26,
GDK_DEBUG_VULKAN_DISABLE = 1 << 27,
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 28,
GDK_DEBUG_HIGH_DEPTH = 1 << 29,
GDK_DEBUG_NO_VSYNC = 1 << 30,
GDK_DEBUG_DMABUF_DISABLE = 1 << 31,
GDK_DEBUG_GL_NO_FRACTIONAL= 1 << 17,
GDK_DEBUG_FORCE_OFFLOAD = 1 << 18,
GDK_DEBUG_GL_PREFER_GL = 1 << 19,
GDK_DEBUG_GL_DEBUG = 1 << 20,
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 21,
GDK_DEBUG_HIGH_DEPTH = 1 << 22,
GDK_DEBUG_NO_VSYNC = 1 << 23,
} GdkDebugFlags;
typedef enum {
GDK_FEATURE_OPENGL = 1 << 0,
GDK_FEATURE_GL_API = 1 << 1,
GDK_FEATURE_GLES_API = 1 << 2,
GDK_FEATURE_EGL = 1 << 3,
GDK_FEATURE_GLX = 1 << 4,
GDK_FEATURE_WGL = 1 << 5,
GDK_FEATURE_VULKAN = 1 << 6,
GDK_FEATURE_DMABUF = 1 << 7,
GDK_FEATURE_OFFLOAD = 1 << 8,
GDK_FEATURE_COLOR_MANAGEMENT = 1 << 9,
GDK_FEATURE_SESSION_MANAGEMENT = 1 << 10,
} GdkFeatures;
#define GDK_ALL_FEATURES ((1 << 11) - 1)
extern guint _gdk_debug_flags;
GdkDebugFlags gdk_display_get_debug_flags (GdkDisplay *display);
void gdk_display_set_debug_flags (GdkDisplay *display,
GdkDebugFlags flags);
gboolean gdk_has_feature (GdkFeatures feature);
static inline void
gdk_debug_message (const char *format, ...) G_GNUC_PRINTF(1, 2);
static inline void
@@ -106,6 +116,7 @@ typedef struct
} GdkDebugKey;
guint gdk_parse_debug_var (const char *variable,
const char *docs,
const GdkDebugKey *keys,
guint nkeys);
+6 -6
View File
@@ -1309,10 +1309,10 @@ gdk_display_create_vulkan_context (GdkDisplay *self,
g_return_val_if_fail (surface == NULL || GDK_IS_SURFACE (surface), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
if (gdk_display_get_debug_flags (self) & GDK_DEBUG_VULKAN_DISABLE)
if (!gdk_has_feature (GDK_FEATURE_VULKAN))
{
g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
_("Vulkan support disabled via GDK_DEBUG"));
_("Vulkan support disabled via GDK_DISABLE"));
return NULL;
}
@@ -1362,11 +1362,11 @@ gdk_display_init_gl (GdkDisplay *self)
before = GDK_PROFILER_CURRENT_TIME;
if (gdk_display_get_debug_flags (self) & GDK_DEBUG_GL_DISABLE)
if (!gdk_has_feature (GDK_FEATURE_OPENGL))
{
g_set_error_literal (&priv->gl_error, GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("GL support disabled via GDK_DEBUG"));
_("OpenGL support disabled via GDK_DISABLE"));
return;
}
@@ -1477,7 +1477,7 @@ gdk_display_create_gl_context (GdkDisplay *self,
if (!gdk_display_prepare_gl (self, error))
return NULL;
return gdk_gl_context_new (self, NULL);
return gdk_gl_context_new (self, NULL, FALSE);
}
/*< private >
@@ -2006,7 +2006,7 @@ gdk_display_init_dmabuf (GdkDisplay *self)
builder = gdk_dmabuf_formats_builder_new ();
#ifdef HAVE_DMABUF
if (!GDK_DISPLAY_DEBUG_CHECK (self, DMABUF_DISABLE))
if (gdk_has_feature (GDK_FEATURE_DMABUF))
{
#ifdef GDK_RENDERING_VULKAN
gdk_display_add_dmabuf_downloader (self, gdk_vulkan_get_dmabuf_downloader (self, builder));
+1 -1
View File
@@ -71,7 +71,7 @@ download_memcpy (guchar *dst_data,
bpp = gdk_memory_format_bytes_per_pixel (dst_format);
src_stride = dmabuf->planes[0].stride;
src_data = src_datas[0] + dmabuf->planes[0].offset;
g_return_if_fail (sizes[0] >= dmabuf->planes[0].offset + gdk_memory_format_min_buffer_size (dst_format, dst_stride, width, height));
g_return_if_fail (sizes[0] >= dmabuf->planes[0].offset + gdk_memory_format_min_buffer_size (dst_format, src_stride, width, height));
if (dst_stride == src_stride)
memcpy (dst_data, src_data, (height - 1) * dst_stride + width * bpp);
+4
View File
@@ -5,6 +5,10 @@
#include <drm_fourcc.h>
#endif
#ifndef DRM_FORMAT_MOD_INVALID
#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
#endif
#ifndef fourcc_code
#define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \
((__u32)(c) << 16) | ((__u32)(d) << 24))
+2 -2
View File
@@ -1063,11 +1063,11 @@ gdk_dmabuf_texture_builder_build (GdkDmabufTextureBuilder *self,
for (i = 0; i < self->dmabuf.n_planes; i++)
g_return_val_if_fail (self->dmabuf.planes[i].fd != -1, NULL);
if (GDK_DISPLAY_DEBUG_CHECK (self->display, DMABUF_DISABLE))
if (!gdk_has_feature (GDK_FEATURE_DMABUF))
{
g_set_error_literal (error,
GDK_DMABUF_ERROR, GDK_DMABUF_ERROR_NOT_AVAILABLE,
"dmabuf support disabled via GDK_DEBUG environment variable");
"dmabuf support disabled via GDK_DISABLE environment variable");
return NULL;
}
+47 -15
View File
@@ -223,6 +223,9 @@ gdk_draw_context_init (GdkDrawContext *self)
*
* Returns: %TRUE if the context is between [method@Gdk.DrawContext.begin_frame]
* and [method@Gdk.DrawContext.end_frame] calls.
*
* Deprecated: 4.16: Drawing directly to the surface is no longer recommended.
* Use `GskRenderNode` and `GskRenderer`.
*/
gboolean
gdk_draw_context_is_in_frame (GdkDrawContext *context)
@@ -313,6 +316,9 @@ gdk_draw_context_get_surface (GdkDrawContext *context)
* gdk_draw_context_begin_frame() and gdk_draw_context_end_frame() via the
* use of [GskRenderer](../gsk4/class.Renderer.html)s, so application code
* does not need to call these functions explicitly.
*
* Deprecated: 4.16: Drawing directly to the surface is no longer recommended.
* Use `GskRenderNode` and `GskRenderer`.
*/
void
gdk_draw_context_begin_frame (GdkDrawContext *context,
@@ -324,11 +330,12 @@ gdk_draw_context_begin_frame (GdkDrawContext *context,
g_return_if_fail (priv->surface != NULL);
g_return_if_fail (region != NULL);
gdk_draw_context_begin_frame_full (context, GDK_MEMORY_U8, region);
gdk_draw_context_begin_frame_full (context, GDK_MEMORY_U8, region, NULL);
}
/*
* @depth: best depth to render in
* @opaque: (nullable): opaque region of the rendering
*
* If the given depth is not `GDK_MEMORY_U8`, GDK will see about providing a
* rendering target that supports a higher bit depth than 8 bits per channel.
@@ -351,9 +358,10 @@ gdk_draw_context_begin_frame (GdkDrawContext *context,
* to choose.
*/
void
gdk_draw_context_begin_frame_full (GdkDrawContext *context,
GdkMemoryDepth depth,
const cairo_region_t *region)
gdk_draw_context_begin_frame_full (GdkDrawContext *context,
GdkMemoryDepth depth,
const cairo_region_t *region,
const graphene_rect_t *opaque)
{
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (context);
@@ -378,19 +386,23 @@ gdk_draw_context_begin_frame_full (GdkDrawContext *context,
return;
}
gdk_surface_set_opaque_rect (priv->surface, opaque);
if (gdk_display_get_debug_flags (priv->display) & GDK_DEBUG_HIGH_DEPTH)
depth = GDK_MEMORY_FLOAT32;
priv->frame_region = cairo_region_copy (region);
priv->surface->paint_context = g_object_ref (context);
g_assert (priv->color_state == NULL);
GDK_DRAW_CONTEXT_GET_CLASS (context)->begin_frame (context,
depth,
priv->frame_region,
&priv->color_state,
&priv->depth);
/* the callback is meant to set them */
/* The callback is meant to set them. Note that it does not return a ref */
g_assert (priv->color_state != NULL);
g_assert (priv->depth < GDK_N_DEPTHS);
@@ -420,6 +432,21 @@ region_get_pixels (cairo_region_t *region)
}
#endif
void
gdk_draw_context_end_frame_full (GdkDrawContext *context)
{
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (context);
GDK_DRAW_CONTEXT_GET_CLASS (context)->end_frame (context, priv->frame_region);
gdk_profiler_set_int_counter (pixels_counter, region_get_pixels (priv->frame_region));
priv->color_state = NULL;
g_clear_pointer (&priv->frame_region, cairo_region_destroy);
g_clear_object (&priv->surface->paint_context);
priv->depth = GDK_N_DEPTHS;
}
/**
* gdk_draw_context_end_frame:
* @context: a `GdkDrawContext`
@@ -432,6 +459,9 @@ region_get_pixels (cairo_region_t *region)
* When using a [class@Gdk.GLContext], this function may call `glFlush()`
* implicitly before returning; it is not recommended to call `glFlush()`
* explicitly before calling this function.
*
* Deprecated: 4.16: Drawing directly to the surface is no longer recommended.
* Use `GskRenderNode` and `GskRenderer`.
*/
void
gdk_draw_context_end_frame (GdkDrawContext *context)
@@ -459,14 +489,7 @@ gdk_draw_context_end_frame (GdkDrawContext *context)
return;
}
GDK_DRAW_CONTEXT_GET_CLASS (context)->end_frame (context, priv->frame_region);
gdk_profiler_set_int_counter (pixels_counter, region_get_pixels (priv->frame_region));
g_clear_pointer (&priv->color_state, gdk_color_state_unref);
g_clear_pointer (&priv->frame_region, cairo_region_destroy);
g_clear_object (&priv->surface->paint_context);
priv->depth = GDK_N_DEPTHS;
gdk_draw_context_end_frame_full (context);
}
/**
@@ -483,15 +506,24 @@ gdk_draw_context_end_frame (GdkDrawContext *context)
* and [method@Gdk.DrawContext.end_frame], %NULL will be returned.
*
* Returns: (transfer none) (nullable): a Cairo region
*
* Deprecated: 4.16: Drawing directly to the surface is no longer recommended.
* Use `GskRenderNode` and `GskRenderer`.
*/
const cairo_region_t *
gdk_draw_context_get_frame_region (GdkDrawContext *context)
_gdk_draw_context_get_frame_region (GdkDrawContext *context)
{
GdkDrawContextPrivate *priv = gdk_draw_context_get_instance_private (context);
return priv->frame_region;
}
const cairo_region_t *
(gdk_draw_context_get_frame_region) (GdkDrawContext *context)
{
g_return_val_if_fail (GDK_IS_DRAW_CONTEXT (context), NULL);
return priv->frame_region;
return _gdk_draw_context_get_frame_region (context);
}
/*<private>
+4 -4
View File
@@ -40,15 +40,15 @@ GdkDisplay * gdk_draw_context_get_display (GdkDrawContext
GDK_AVAILABLE_IN_ALL
GdkSurface * gdk_draw_context_get_surface (GdkDrawContext *context);
GDK_AVAILABLE_IN_ALL
GDK_DEPRECATED_IN_4_16
void gdk_draw_context_begin_frame (GdkDrawContext *context,
const cairo_region_t *region);
GDK_AVAILABLE_IN_ALL
GDK_DEPRECATED_IN_4_16
void gdk_draw_context_end_frame (GdkDrawContext *context);
GDK_AVAILABLE_IN_ALL
GDK_DEPRECATED_IN_4_16
gboolean gdk_draw_context_is_in_frame (GdkDrawContext *context);
GDK_AVAILABLE_IN_ALL
GDK_DEPRECATED_IN_4_16
const cairo_region_t * gdk_draw_context_get_frame_region (GdkDrawContext *context);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkDrawContext, g_object_unref)
+7 -1
View File
@@ -25,6 +25,8 @@
#include "gdkcolorstateprivate.h"
#include "gdkmemoryformatprivate.h"
#include <graphene.h>
G_BEGIN_DECLS
#define GDK_DRAW_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_DRAW_CONTEXT, GdkDrawContextClass))
@@ -57,10 +59,14 @@ void gdk_draw_context_surface_resized (GdkDrawContext
void gdk_draw_context_begin_frame_full (GdkDrawContext *context,
GdkMemoryDepth depth,
const cairo_region_t *region);
const cairo_region_t *region,
const graphene_rect_t *opaque);
void gdk_draw_context_end_frame_full (GdkDrawContext *context);
void gdk_draw_context_empty_frame (GdkDrawContext *context);
#define gdk_draw_context_get_frame_region(...) _gdk_draw_context_get_frame_region(__VA_ARGS__)
const cairo_region_t * _gdk_draw_context_get_frame_region (GdkDrawContext *self);
GdkColorState * gdk_draw_context_get_color_state (GdkDrawContext *self);
GdkMemoryDepth gdk_draw_context_get_depth (GdkDrawContext *self);
+12 -1
View File
@@ -978,9 +978,13 @@ gdk_event_get_axis (GdkEvent *event,
* according to platform conventions.
*
* The right mouse button typically triggers context menus.
* On macOS, Control+left mouse button also triggers.
*
* This function should always be used instead of simply checking for
* event->button == %GDK_BUTTON_SECONDARY.
*
* ```c
* event->button == GDK_BUTTON_SECONDARY
* ```
*
* Returns: %TRUE if the event should trigger a context menu.
*/
@@ -998,6 +1002,13 @@ gdk_event_triggers_context_menu (GdkEvent *event)
if (bevent->button == GDK_BUTTON_SECONDARY &&
! (bevent->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK)))
return TRUE;
#ifdef __APPLE__
if (bevent->button == GDK_BUTTON_PRIMARY &&
(bevent->state & GDK_CONTROL_MASK) &&
! (bevent->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK)))
return TRUE;
#endif
}
return FALSE;
+74 -31
View File
@@ -122,6 +122,7 @@ struct _GdkGLContextPrivate
GdkGLMemoryFlags memory_flags[GDK_MEMORY_N_FORMATS];
GdkGLFeatures features;
guint surface_attached : 1;
guint use_khr_debug : 1;
guint has_debug_output : 1;
guint extensions_checked : 1;
@@ -717,8 +718,8 @@ gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
cairo_region_get_rectangle (painted, i, &rect);
rects[j++] = (int) floor (rect.x * scale);
rects[j++] = (int) floor ((surface_height - rect.height - rect.y) * scale);
rects[j++] = (int) ceil (rect.width * scale);
rects[j++] = (int) ceil (rect.height * scale);
rects[j++] = (int) ceil ((rect.x + rect.width) * scale) - floor (rect.x * scale);
rects[j++] = (int) ceil ((surface_height - rect.y) * scale) - floor ((surface_height - rect.height - rect.y) * scale);
}
priv->eglSwapBuffersWithDamage (gdk_display_get_egl_display (display), egl_surface, rects, n_rects);
g_free (heap_rects);
@@ -829,20 +830,28 @@ gdk_gl_context_init (GdkGLContext *self)
/* Must have called gdk_display_prepare_gl() before */
GdkGLContext *
gdk_gl_context_new (GdkDisplay *display,
GdkSurface *surface)
GdkSurface *surface,
gboolean surface_attached)
{
GdkGLContext *shared;
GdkGLContextPrivate *priv;
GdkGLContext *shared, *result;
g_assert (surface == NULL || display == gdk_surface_get_display (surface));
g_assert (!surface_attached || surface != NULL);
/* assert gdk_display_prepare_gl() had been called */
shared = gdk_display_get_gl_context (display);
g_assert (shared);
return g_object_new (G_OBJECT_TYPE (shared),
"display", display,
"surface", surface,
NULL);
result = g_object_new (G_OBJECT_TYPE (shared),
"display", display,
"surface", surface,
NULL);
priv = gdk_gl_context_get_instance_private (result);
priv->surface_attached = surface_attached;
return result;
}
void
@@ -1319,31 +1328,28 @@ gdk_gl_context_is_api_allowed (GdkGLContext *self,
GError **error)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
GdkDebugFlags flags;
GdkGLAPI allowed_apis;
allowed_apis = priv->allowed_apis;
flags = gdk_display_get_debug_flags (gdk_gl_context_get_display (self));
if (flags & GDK_DEBUG_GL_DISABLE_GLES)
if (!gdk_has_feature (GDK_FEATURE_GLES_API))
{
if (api == GDK_GL_API_GLES)
{
g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
_("OpenGL ES disabled via GDK_DEBUG"));
_("OpenGL ES API disabled via GDK_DISABLE"));
return FALSE;
}
allowed_apis &= ~GDK_GL_API_GLES;
}
if (flags & GDK_DEBUG_GL_DISABLE_GL)
if (!gdk_has_feature (GDK_FEATURE_GL_API))
{
if (api == GDK_GL_API_GL)
{
g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
_("OpenGL disabled via GDK_DEBUG"));
_("OpenGL API disabled via GDK_DISABLE"));
return FALSE;
}
@@ -1770,8 +1776,10 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
supported_features = gdk_gl_context_check_features (context);
disabled_features = gdk_parse_debug_var ("GDK_GL_DISABLE",
gdk_gl_feature_keys,
G_N_ELEMENTS (gdk_gl_feature_keys));
"GDK_GL_DISABLE can be set to values which cause GDK to disable\n"
"certain OpenGL extensions.\n",
gdk_gl_feature_keys,
G_N_ELEMENTS (gdk_gl_feature_keys));
priv->features = supported_features & ~disabled_features;
@@ -1825,12 +1833,22 @@ gdk_gl_context_check_is_current (GdkGLContext *context)
void
gdk_gl_context_make_current (GdkGLContext *context)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
MaskedContext *current, *masked_context;
gboolean surfaceless;
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
surfaceless = !gdk_draw_context_is_in_frame (GDK_DRAW_CONTEXT (context));
if (priv->surface_attached)
{
surfaceless = FALSE;
}
else
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
surfaceless = !gdk_draw_context_is_in_frame (GDK_DRAW_CONTEXT (context));
G_GNUC_END_IGNORE_DEPRECATIONS
}
masked_context = mask_context (context, surfaceless);
current = g_private_get (&thread_current_context);
@@ -2019,8 +2037,11 @@ gdk_gl_context_clear_current (void)
*
* Does a gdk_gl_context_clear_current() if the current context is attached
* to @surface, leaves the current context alone otherwise.
*
* Returns: (nullable) (transfer full): The context that was cleared, so that it can be
* re-made current later
**/
void
GdkGLContext *
gdk_gl_context_clear_current_if_surface (GdkSurface *surface)
{
MaskedContext *current;
@@ -2031,11 +2052,20 @@ gdk_gl_context_clear_current_if_surface (GdkSurface *surface)
GdkGLContext *context = unmask_context (current);
if (gdk_gl_context_get_surface (context) != surface)
return;
return NULL;
g_object_ref (context);
if (GDK_GL_CONTEXT_GET_CLASS (context)->clear_current (context))
g_private_replace (&thread_current_context, NULL);
{
g_private_replace (&thread_current_context, NULL);
return context;
}
g_object_unref (context);
}
return NULL;
}
/**
@@ -2135,17 +2165,30 @@ gboolean
gdk_gl_backend_can_be_used (GdkGLBackend backend_type,
GError **error)
{
if (the_gl_backend_type == GDK_GL_NONE ||
the_gl_backend_type == backend_type)
return TRUE;
if (the_gl_backend_type != GDK_GL_NONE &&
the_gl_backend_type != backend_type)
{
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
/* translators: This is about OpenGL backend names, like
* "Trying to use X11 GLX, but EGL is already in use"
*/
_("Trying to use %s, but %s is already in use"),
gl_backend_names[backend_type],
gl_backend_names[the_gl_backend_type]);
return FALSE;
}
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
/* translators: This is about OpenGL backend names, like
* "Trying to use X11 GLX, but EGL is already in use" */
_("Trying to use %s, but %s is already in use"),
gl_backend_names[backend_type],
gl_backend_names[the_gl_backend_type]);
return FALSE;
if ((backend_type == GDK_GL_EGL && !gdk_has_feature (GDK_FEATURE_EGL)) ||
(backend_type == GDK_GL_GLX && !gdk_has_feature (GDK_FEATURE_GLX)) ||
(backend_type == GDK_GL_WGL && !gdk_has_feature (GDK_FEATURE_WGL)))
{
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
_("Trying to use %s, but it is disabled via GDK_DISABLE"),
gl_backend_names[backend_type]);
return FALSE;
}
return TRUE;
}
/*<private>
+4 -3
View File
@@ -120,10 +120,11 @@ gboolean gdk_gl_backend_can_be_used (GdkGLBackend
GError **error);
void gdk_gl_backend_use (GdkGLBackend backend_type);
void gdk_gl_context_clear_current_if_surface (GdkSurface *surface);
GdkGLContext * gdk_gl_context_clear_current_if_surface (GdkSurface *surface) G_GNUC_WARN_UNUSED_RESULT;
GdkGLContext * gdk_gl_context_new (GdkDisplay *display,
GdkSurface *surface);
GdkGLContext * gdk_gl_context_new (GdkDisplay *display,
GdkSurface *surface,
gboolean surface_attached);
gboolean gdk_gl_context_is_api_allowed (GdkGLContext *self,
GdkGLAPI api,
+1 -4
View File
@@ -96,8 +96,7 @@ print OUT_GDKKEYSYMS<<EOF;
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __GDK_KEYSYMS_H__
#define __GDK_KEYSYMS_H__
#pragma once
EOF
@@ -165,8 +164,6 @@ close IN_XF86KEYSYM;
print OUT_GDKKEYSYMS<<EOF;
#endif /* __GDK_KEYSYMS_H__ */
EOF
printf "We just finished converting keysymdef.h to gdkkeysyms.h\nThank you\n";
+11 -1
View File
@@ -297,8 +297,11 @@
#define GDK_KEY_dead_u 0xfe88
#define GDK_KEY_dead_U 0xfe89
#define GDK_KEY_dead_small_schwa 0xfe8a
#define GDK_KEY_dead_schwa 0xfe8a
#define GDK_KEY_dead_capital_schwa 0xfe8b
#define GDK_KEY_dead_SCHWA 0xfe8b
#define GDK_KEY_dead_greek 0xfe8c
#define GDK_KEY_dead_hamza 0xfe8d
#define GDK_KEY_First_Virtual_Screen 0xfed0
#define GDK_KEY_Prev_Virtual_Screen 0xfed1
#define GDK_KEY_Next_Virtual_Screen 0xfed2
@@ -490,6 +493,7 @@
#define GDK_KEY_copyright 0x0a9
#define GDK_KEY_ordfeminine 0x0aa
#define GDK_KEY_guillemotleft 0x0ab
#define GDK_KEY_guillemetleft 0x0ab
#define GDK_KEY_notsign 0x0ac
#define GDK_KEY_hyphen 0x0ad
#define GDK_KEY_registered 0x0ae
@@ -505,7 +509,9 @@
#define GDK_KEY_cedilla 0x0b8
#define GDK_KEY_onesuperior 0x0b9
#define GDK_KEY_masculine 0x0ba
#define GDK_KEY_ordmasculine 0x0ba
#define GDK_KEY_guillemotright 0x0bb
#define GDK_KEY_guillemetright 0x0bb
#define GDK_KEY_onequarter 0x0bc
#define GDK_KEY_onehalf 0x0bd
#define GDK_KEY_threequarters 0x0be
@@ -1743,6 +1749,11 @@
#define GDK_KEY_ohorn 0x10001a1
#define GDK_KEY_Uhorn 0x10001af
#define GDK_KEY_uhorn 0x10001b0
#define GDK_KEY_combining_tilde 0x1000303
#define GDK_KEY_combining_grave 0x1000300
#define GDK_KEY_combining_acute 0x1000301
#define GDK_KEY_combining_hook 0x1000309
#define GDK_KEY_combining_belowdot 0x1000323
#define GDK_KEY_EcuSign 0x10020a0
#define GDK_KEY_ColonSign 0x10020a1
#define GDK_KEY_CruzeiroSign 0x10020a2
@@ -2313,4 +2324,3 @@
#define GDK_KEY_Prev_VMode 0x1008fe23
#define GDK_KEY_LogWindowTree 0x1008fe24
#define GDK_KEY_LogGrabInfo 0x1008fe25
+17 -9
View File
@@ -358,7 +358,7 @@ struct _GdkMemoryFormatDescription
static const GdkMemoryFormatDescription memory_formats[] = {
[GDK_MEMORY_B8G8R8A8_PREMULTIPLIED] = {
.name = "*BGRA8",
.name = "BGRA8(p)",
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
.premultiplied = GDK_MEMORY_B8G8R8A8_PREMULTIPLIED,
.straight = GDK_MEMORY_B8G8R8A8,
@@ -389,7 +389,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
.from_float = b8g8r8a8_premultiplied_from_float,
},
[GDK_MEMORY_A8R8G8B8_PREMULTIPLIED] = {
.name = "*ARGB8",
.name = "ARGB8(p)",
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
.premultiplied = GDK_MEMORY_A8R8G8B8_PREMULTIPLIED,
.straight = GDK_MEMORY_A8R8G8B8,
@@ -420,7 +420,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
.from_float = a8r8g8b8_premultiplied_from_float,
},
[GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] = {
.name = "*RGBA8",
.name = "RGBA8(p)",
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
.premultiplied = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
.straight = GDK_MEMORY_R8G8B8A8,
@@ -450,7 +450,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
.from_float = r8g8b8a8_premultiplied_from_float,
},
[GDK_MEMORY_A8B8G8R8_PREMULTIPLIED] = {
.name = "*ABGR8",
.name = "ABGR8(p)",
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
.premultiplied = GDK_MEMORY_A8B8G8R8_PREMULTIPLIED,
.straight = GDK_MEMORY_A8B8G8R8,
@@ -828,7 +828,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
.from_float = r16g16b16_from_float,
},
[GDK_MEMORY_R16G16B16A16_PREMULTIPLIED] = {
.name = "*RGBA16",
.name = "RGBA16(p)",
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
.premultiplied = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED,
.straight = GDK_MEMORY_R16G16B16A16,
@@ -927,7 +927,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
.from_float = r16g16b16_float_from_float,
},
[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] = {
.name = "*RGBA16f",
.name = "RGBA16f(p)",
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
.premultiplied = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED,
.straight = GDK_MEMORY_R16G16B16A16_FLOAT,
@@ -1024,7 +1024,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
.from_float = r32g32b32_float_from_float,
},
[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] = {
.name = "*RGBA32f",
.name = "RGBA32f(p)",
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
.premultiplied = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
.straight = GDK_MEMORY_R32G32B32A32_FLOAT,
@@ -1088,7 +1088,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
.from_float = r32g32b32a32_float_from_float,
},
[GDK_MEMORY_G8A8_PREMULTIPLIED] = {
.name = "*GA8",
.name = "GA8(p)",
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
.premultiplied = GDK_MEMORY_G8A8_PREMULTIPLIED,
.straight = GDK_MEMORY_G8A8,
@@ -1181,7 +1181,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
.from_float = g8_from_float,
},
[GDK_MEMORY_G16A16_PREMULTIPLIED] = {
.name = "*GA16",
.name = "GA16(p)",
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
.premultiplied = GDK_MEMORY_G16A16_PREMULTIPLIED,
.straight = GDK_MEMORY_G16A16,
@@ -1524,6 +1524,14 @@ gdk_memory_format_get_depth (GdkMemoryFormat format,
return depth;
}
const char *
gdk_memory_depth_get_name (GdkMemoryDepth depth)
{
const char *names[] = { "none", "u8", "u8-srgb", "u16", "f16", "f32" };
return names[depth];
}
/*<private>
* gdk_memory_depth_merge:
* @depth1: the first depth
+1
View File
@@ -66,6 +66,7 @@ GdkMemoryDepth gdk_memory_depth_merge (GdkMemoryDepth
GdkMemoryDepth depth2) G_GNUC_CONST;
GdkMemoryFormat gdk_memory_depth_get_format (GdkMemoryDepth depth) G_GNUC_CONST;
GdkMemoryFormat gdk_memory_depth_get_alpha_format (GdkMemoryDepth depth) G_GNUC_CONST;
const char * gdk_memory_depth_get_name (GdkMemoryDepth depth);
void gdk_memory_format_gl_format (GdkMemoryFormat format,
gboolean gles,
GLint *out_internal_format,
+4 -2
View File
@@ -111,7 +111,7 @@ gdk_memory_sanitize (GBytes *bytes,
stride % align == 0)
{
*out_stride = stride;
return g_bytes_ref (bytes);
return bytes;
}
bpp = gdk_memory_format_bytes_per_pixel (format);
@@ -122,6 +122,8 @@ gdk_memory_sanitize (GBytes *bytes,
for (y = 0; y < height; y++)
memcpy (copy + y * copy_stride, data + y * stride, bpp * width);
g_bytes_unref (bytes);
*out_stride = copy_stride;
return g_bytes_new_take (copy, copy_stride * height);
}
@@ -197,7 +199,7 @@ gdk_memory_texture_new (int width,
/* needs to be this complex to support subtexture of the bottom right part */
g_return_val_if_fail (g_bytes_get_size (bytes) >= gdk_memory_format_min_buffer_size (format, stride, width, height), NULL);
bytes = gdk_memory_sanitize (bytes, width, height, format, stride, &stride);
bytes = gdk_memory_sanitize (g_bytes_ref (bytes), width, height, format, stride, &stride);
self = g_object_new (GDK_TYPE_MEMORY_TEXTURE,
"width", width,
+1 -1
View File
@@ -649,7 +649,7 @@ void
gdk_monitor_set_scale (GdkMonitor *monitor,
double scale)
{
g_return_if_fail (scale >= 1.);
g_return_if_fail (scale > 0.);
monitor->scale_set = TRUE;
+10
View File
@@ -52,6 +52,16 @@ gdk_rectangle_transform_affine (const GdkRectangle *src,
dest->height = ceilf (MAX (y1, y2)) - dest->y;
}
static inline gboolean
gdk_rectangle_contains (const GdkRectangle *rect,
const GdkRectangle *contained)
{
return contained->x >= rect->x
&& contained->y >= rect->y
&& contained->x + contained->width <= rect->x + rect->width
&& contained->y + contained->height <= rect->y + rect->height;
}
G_END_DECLS
+6
View File
@@ -167,6 +167,12 @@ gdk_subsurface_attach (GdkSubsurface *subsurface,
g_return_val_if_fail (sibling == NULL || GDK_IS_SUBSURFACE (sibling), FALSE);
g_return_val_if_fail (sibling == NULL || sibling->parent == subsurface->parent, FALSE);
/* if the texture fully covers the background, ignore it */
if (background &&
gsk_rect_contains_rect (dest, background) &&
gdk_memory_format_alpha (gdk_texture_get_format (texture)) == GDK_MEMORY_ALPHA_OPAQUE)
background = NULL;
result = GDK_SUBSURFACE_GET_CLASS (subsurface)->attach (subsurface,
texture,
source,
+132 -19
View File
@@ -40,11 +40,13 @@
#include <glib/gi18n-lib.h>
#include "gdkmarshalers.h"
#include "gdkpopupprivate.h"
#include "gdkrectangle.h"
#include "gdkrectangleprivate.h"
#include "gdktoplevelprivate.h"
#include "gdkvulkancontext.h"
#include "gdksubsurfaceprivate.h"
#include "gsk/gskrectprivate.h"
#include <math.h>
#ifdef HAVE_EGL
@@ -75,6 +77,9 @@ struct _GdkSurfacePrivate
GdkMemoryDepth egl_surface_depth;
#endif
cairo_region_t *opaque_region;
cairo_rectangle_int_t opaque_rect; /* This is different from the region */
gpointer widget;
GdkColorState *color_state;
@@ -510,6 +515,12 @@ gdk_surface_real_create_subsurface (GdkSurface *surface)
return NULL;
}
static void
gdk_surface_default_set_opaque_region (GdkSurface *surface,
cairo_region_t *region)
{
}
static void
gdk_surface_constructed (GObject *object)
{
@@ -533,6 +544,7 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
klass->beep = gdk_surface_real_beep;
klass->get_scale = gdk_surface_real_get_scale;
klass->create_subsurface = gdk_surface_real_create_subsurface;
klass->set_opaque_region = gdk_surface_default_set_opaque_region;
/**
* GdkSurface:cursor: (attributes org.gtk.Property.get=gdk_surface_get_cursor org.gtk.Property.set=gdk_surface_set_cursor)
@@ -771,7 +783,7 @@ gdk_surface_finalize (GObject *object)
g_clear_object (&surface->display);
g_clear_pointer (&surface->opaque_region, cairo_region_destroy);
g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
if (surface->parent)
surface->parent->children = g_list_remove (surface->parent->children, surface);
@@ -1124,6 +1136,7 @@ gdk_surface_set_egl_native_window (GdkSurface *self,
{
#ifdef HAVE_EGL
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (self);
GdkGLContext *current = NULL;
/* This checks that all EGL platforms we support conform to the same struct sizes.
* When this ever fails, there will be some fun times happening for whoever tries
@@ -1132,12 +1145,21 @@ gdk_surface_set_egl_native_window (GdkSurface *self,
if (priv->egl_surface != NULL)
{
gdk_gl_context_clear_current_if_surface (self);
eglDestroySurface (gdk_surface_get_display (self), priv->egl_surface);
GdkDisplay *display = gdk_surface_get_display (self);
current = gdk_gl_context_clear_current_if_surface (self);
eglDestroySurface (gdk_display_get_egl_display (display), priv->egl_surface);
priv->egl_surface = NULL;
}
priv->egl_native_window = native_window;
if (current)
{
gdk_gl_context_make_current (current);
g_object_unref (current);
}
}
gpointer /* EGLSurface */
@@ -1157,20 +1179,26 @@ gdk_surface_ensure_egl_surface (GdkSurface *self,
g_return_val_if_fail (priv->egl_native_window != NULL, depth);
if (priv->egl_surface_depth != depth &&
priv->egl_surface != NULL &&
gdk_display_get_egl_config (display, priv->egl_surface_depth) != gdk_display_get_egl_config (display, depth))
if (depth == GDK_MEMORY_NONE)
{
gdk_gl_context_clear_current_if_surface (self);
eglDestroySurface (gdk_display_get_egl_display (display), priv->egl_surface);
priv->egl_surface = NULL;
if (priv->egl_surface_depth == GDK_MEMORY_NONE)
depth = GDK_MEMORY_U8;
else
depth = priv->egl_surface_depth;
}
if (priv->egl_surface == NULL)
if (priv->egl_surface == NULL ||
(priv->egl_surface != NULL &&
gdk_display_get_egl_config (display, priv->egl_surface_depth) != gdk_display_get_egl_config (display, depth)))
{
GdkGLContext *cleared;
EGLint attribs[4];
int i;
cleared = gdk_gl_context_clear_current_if_surface (self);
if (priv->egl_surface != NULL)
eglDestroySurface (gdk_display_get_egl_display (display), priv->egl_surface);
i = 0;
if (depth == GDK_MEMORY_U8_SRGB && display->have_egl_gl_colorspace)
{
@@ -1195,6 +1223,12 @@ gdk_surface_ensure_egl_surface (GdkSurface *self,
NULL);
}
priv->egl_surface_depth = depth;
if (cleared)
{
gdk_gl_context_make_current (cleared);
g_object_unref (cleared);
}
}
return priv->egl_surface_depth;
@@ -1254,7 +1288,7 @@ gdk_surface_create_gl_context (GdkSurface *surface,
if (!gdk_display_prepare_gl (surface->display, error))
return NULL;
return gdk_gl_context_new (surface->display, surface);
return gdk_gl_context_new (surface->display, surface, FALSE);
}
/**
@@ -2631,6 +2665,35 @@ gdk_surface_get_scale (GdkSurface *surface)
return GDK_SURFACE_GET_CLASS (surface)->get_scale (surface);
}
static void
gdk_surface_update_opaque_region (GdkSurface *self)
{
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (self);
cairo_region_t *region;
if (priv->opaque_region == NULL)
{
if (priv->opaque_rect.width <= 0)
region = NULL;
else
region = cairo_region_create_rectangle (&priv->opaque_rect);
}
else
{
if (priv->opaque_rect.width <= 0)
region = cairo_region_reference (priv->opaque_region);
else
{
region = cairo_region_copy (priv->opaque_region);
cairo_region_union_rectangle (region, &priv->opaque_rect);
}
}
GDK_SURFACE_GET_CLASS (self)->set_opaque_region (self, region);
g_clear_pointer (&region, cairo_region_destroy);
}
/**
* gdk_surface_set_opaque_region:
* @surface: a top-level `GdkSurface`
@@ -2652,27 +2715,77 @@ gdk_surface_get_scale (GdkSurface *surface)
* is opaque, as we know where the opaque regions are. If your surface
* background is not opaque, please update this property in your
* [GtkWidgetClass.css_changed](../gtk4/vfunc.Widget.css_changed.html) handler.
*
* Deprecated: 4.16: GDK can figure out the opaque parts of a window itself
* by inspecting the contents that are drawn.
*/
void
gdk_surface_set_opaque_region (GdkSurface *surface,
cairo_region_t *region)
{
GdkSurfaceClass *class;
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (surface);
g_return_if_fail (GDK_IS_SURFACE (surface));
g_return_if_fail (!GDK_SURFACE_DESTROYED (surface));
if (cairo_region_equal (surface->opaque_region, region))
if (cairo_region_equal (priv->opaque_region, region))
return;
g_clear_pointer (&surface->opaque_region, cairo_region_destroy);
g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
if (region != NULL)
surface->opaque_region = cairo_region_reference (region);
priv->opaque_region = cairo_region_reference (region);
class = GDK_SURFACE_GET_CLASS (surface);
if (class->set_opaque_region)
class->set_opaque_region (surface, region);
gdk_surface_update_opaque_region (surface);
}
/* Sets the opaque rect from the rendernode via end_frame() */
void
gdk_surface_set_opaque_rect (GdkSurface *self,
const graphene_rect_t *rect)
{
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (self);
cairo_rectangle_int_t opaque;
if (rect)
gsk_rect_to_cairo_shrink (rect, &opaque);
else
opaque = (cairo_rectangle_int_t) { 0, 0, 0, 0 };
if (gdk_rectangle_equal (&priv->opaque_rect, &opaque))
return;
priv->opaque_rect = opaque;
gdk_surface_update_opaque_region (self);
}
/*
* gdk_surface_is_opaque:
* @self: a surface
*
* Checks if the whole surface is known to be opaque.
* This allows using an RGBx buffer instead of RGBA.
*
* This function works for the currently rendered frame inside
* begin_frame() implementations.
*
* Returns: %TRUE if the whole surface is provably opaque
**/
gboolean
gdk_surface_is_opaque (GdkSurface *self)
{
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (self);
cairo_rectangle_int_t whole = { 0, 0, self->width, self->height };
if (gdk_rectangle_contains (&priv->opaque_rect, &whole))
return TRUE;
if (priv->opaque_region &&
cairo_region_contains_rectangle (priv->opaque_region, &whole) == CAIRO_REGION_OVERLAP_IN)
return TRUE;
return FALSE;
}
void
+1 -1
View File
@@ -125,7 +125,7 @@ void gdk_surface_request_layout (GdkSurface *surface);
GDK_AVAILABLE_IN_ALL
GdkFrameClock* gdk_surface_get_frame_clock (GdkSurface *surface);
GDK_AVAILABLE_IN_ALL
GDK_DEPRECATED_IN_4_16
void gdk_surface_set_opaque_region (GdkSurface *surface,
cairo_region_t *region);
+11 -10
View File
@@ -96,8 +96,6 @@ struct _GdkSurface
GSList *draw_contexts;
GdkDrawContext *paint_context;
cairo_region_t *opaque_region;
GdkSeat *current_shortcuts_inhibited_seat;
GPtrArray *subsurfaces;
@@ -253,14 +251,17 @@ gdk_gravity_flip_vertically (GdkGravity anchor)
g_assert_not_reached ();
}
void _gdk_surface_destroy (GdkSurface *surface,
gboolean foreign_destroy);
void gdk_surface_invalidate_rect (GdkSurface *surface,
const GdkRectangle *rect);
void gdk_surface_invalidate_region (GdkSurface *surface,
const cairo_region_t *region);
void _gdk_surface_clear_update_area (GdkSurface *surface);
void _gdk_surface_update_size (GdkSurface *surface);
void _gdk_surface_destroy (GdkSurface *surface,
gboolean foreign_destroy);
void gdk_surface_invalidate_rect (GdkSurface *surface,
const GdkRectangle *rect);
void gdk_surface_invalidate_region (GdkSurface *surface,
const cairo_region_t *region);
void _gdk_surface_clear_update_area (GdkSurface *surface);
void _gdk_surface_update_size (GdkSurface *surface);
void gdk_surface_set_opaque_rect (GdkSurface *self,
const graphene_rect_t *rect);
gboolean gdk_surface_is_opaque (GdkSurface *self);
GdkGLContext * gdk_surface_get_paint_gl_context (GdkSurface *surface,
GError **error);
+8 -1
View File
@@ -85,7 +85,6 @@ typedef enum
* @GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE: whether the bottom edge is resizable
* @GDK_TOPLEVEL_STATE_LEFT_TILED: whether the left edge is tiled
* @GDK_TOPLEVEL_STATE_LEFT_RESIZABLE: whether the left edge is resizable
* @GDK_TOPLEVEL_STATE_SUSPENDED: the surface is not visible to the user
*
* Specifies the state of a toplevel surface.
*
@@ -95,6 +94,14 @@ typedef enum
* will give an indication of tiledness without any of the per-edge states
* being set.
*/
/**
* GDK_TOPLEVEL_STATE_SUSPENDED:
*
* The surface is not visible to the user.
*
* Since: 4.12
*/
typedef enum
{
GDK_TOPLEVEL_STATE_MINIMIZED = 1 << 0,
+27 -28
View File
@@ -714,8 +714,8 @@ gdk_vulkan_context_end_frame (GdkDrawContext *draw_context,
.layer = 0,
.offset.x = (int) floor (r.x * scale),
.offset.y = (int) floor (r.y * scale),
.extent.width = (int) ceil (r.width * scale),
.extent.height = (int) ceil (r.height * scale),
.extent.width = (int) ceil ((r.x + r.width) * scale) - floor (r.x * scale),
.extent.height = (int) ceil ((r.y + r.height) * scale) - floor (r.y * scale),
};
}
}
@@ -1348,7 +1348,6 @@ gdk_vulkan_context_get_draw_index (GdkVulkanContext *context)
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (context), 0);
g_return_val_if_fail (gdk_draw_context_is_in_frame (GDK_DRAW_CONTEXT (context)), 0);
return priv->draw_index;
}
@@ -1372,7 +1371,6 @@ gdk_vulkan_context_set_draw_semaphore (GdkVulkanContext *context,
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
g_return_if_fail (GDK_IS_VULKAN_CONTEXT (context));
g_return_if_fail (!gdk_draw_context_is_in_frame (GDK_DRAW_CONTEXT (context)));
g_return_if_fail (priv->draw_semaphore == VK_NULL_HANDLE);
priv->draw_semaphore = semaphore;
@@ -1408,8 +1406,9 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
last = n_devices;
skip_features = gdk_parse_debug_var ("GDK_VULKAN_DISABLE",
gsk_vulkan_feature_keys,
G_N_ELEMENTS (gsk_vulkan_feature_keys));
"GDK_VULKAN_DISABLE can be set to a list of Vulkan features to disable.\n",
gsk_vulkan_feature_keys,
G_N_ELEMENTS (gsk_vulkan_feature_keys));
if (skip_features & GDK_VULKAN_FEATURE_YCBCR)
skip_features |= GDK_VULKAN_FEATURE_DMABUF;
@@ -1628,10 +1627,10 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
gboolean have_debug_report = FALSE;
VkResult res;
if (gdk_display_get_debug_flags (display) & GDK_DEBUG_VULKAN_DISABLE)
if (!gdk_has_feature (GDK_FEATURE_VULKAN))
{
g_set_error_literal (error, GDK_VULKAN_ERROR, GDK_VULKAN_ERROR_NOT_AVAILABLE,
_("Vulkan support disabled via GDK_DEBUG"));
_("Vulkan support disabled via GDK_DISABLE"));
return FALSE;
}
@@ -1674,26 +1673,26 @@ gdk_display_create_vulkan_instance (GdkDisplay *display,
g_ptr_array_add (used_extensions, (gpointer) VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
}
res = GDK_VK_CHECK (vkCreateInstance, &(VkInstanceCreateInfo) {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = NULL,
.flags = 0,
.pApplicationInfo = &(VkApplicationInfo) {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = NULL,
.pApplicationName = g_get_application_name (),
.applicationVersion = 0,
.pEngineName = "GTK",
.engineVersion = VK_MAKE_VERSION (GDK_MAJOR_VERSION, GDK_MINOR_VERSION, GDK_MICRO_VERSION),
.apiVersion = VK_API_VERSION_1_3
},
.enabledLayerCount = 0,
.ppEnabledLayerNames = NULL,
.enabledExtensionCount = used_extensions->len,
.ppEnabledExtensionNames = (const char * const *) used_extensions->pdata,
},
NULL,
&display->vk_instance);
res = vkCreateInstance (&(VkInstanceCreateInfo) {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = NULL,
.flags = 0,
.pApplicationInfo = &(VkApplicationInfo) {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = NULL,
.pApplicationName = g_get_application_name (),
.applicationVersion = 0,
.pEngineName = "GTK",
.engineVersion = VK_MAKE_VERSION (GDK_MAJOR_VERSION, GDK_MINOR_VERSION, GDK_MICRO_VERSION),
.apiVersion = VK_API_VERSION_1_3
},
.enabledLayerCount = 0,
.ppEnabledLayerNames = NULL,
.enabledExtensionCount = used_extensions->len,
.ppEnabledExtensionNames = (const char * const *) used_extensions->pdata,
},
NULL,
&display->vk_instance);
g_ptr_array_free (used_extensions, TRUE);
if (res != VK_SUCCESS)
+1 -1
View File
@@ -65,7 +65,7 @@ gdk_vulkan_handle_result (VkResult res,
{
if (res != VK_SUCCESS)
{
GDK_DEBUG (VULKAN, "%s(): %s (%d)", called_function, gdk_vulkan_strerror (res), res);
g_warning ("%s(): %s (%d)", called_function, gdk_vulkan_strerror (res), res);
}
return res;
+6
View File
@@ -1133,6 +1133,7 @@
0x00fe8a dead_small_schwa
0x00fe8b dead_capital_schwa
0x00fe8c dead_greek
0x00fe8d dead_hamza
0x00fea0 ch
0x00fea1 Ch
0x00fea2 CH
@@ -1398,6 +1399,11 @@
0x1000259 schwa
0x1000275 obarred
0x1000292 ezh
0x1000300 combining_grave
0x1000301 combining_acute
0x1000303 combining_tilde
0x1000309 combining_hook
0x1000323 combining_belowdot
0x1000492 Cyrillic_GHE_bar
0x1000493 Cyrillic_ghe_bar
0x1000496 Cyrillic_ZHE_descender
+2293 -2275
View File
File diff suppressed because it is too large Load Diff
+2 -21
View File
@@ -107,32 +107,13 @@ _gdk_macos_cairo_context_cairo_create (GdkCairoContext *cairo_context)
cairo_clip (cr);
}
/* If we have some exposed transparent area in the damage region,
* we need to clear the existing content first to leave an transparent
* area for cairo. We use (surface_bounds or damage)-(opaque) to get
* the smallest set of rectangles we need to clear as it's expensive.
*/
if (!opaque)
{
cairo_region_t *transparent;
cairo_rectangle_int_t r = { 0, 0, width/scale, height/scale };
cairo_save (cr);
if (damage != NULL)
cairo_region_get_extents (damage, &r);
transparent = cairo_region_create_rectangle (&r);
if (surface->opaque_region)
cairo_region_subtract (transparent, surface->opaque_region);
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
cairo_paint (cr);
if (!cairo_region_is_empty (transparent))
{
gdk_cairo_region (cr, transparent);
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
cairo_fill (cr);
}
cairo_region_destroy (transparent);
cairo_restore (cr);
}
+1 -1
View File
@@ -242,7 +242,7 @@ gdk_macos_gl_context_allocate (GdkMacosGLContext *self)
return;
/* Alter to an opaque surface if necessary */
opaque = _gdk_macos_surface_is_opaque (GDK_MACOS_SURFACE (surface));
opaque = gdk_surface_is_opaque (surface);
if (opaque != self->last_opaque)
{
self->last_opaque = !!opaque;
-1
View File
@@ -86,7 +86,6 @@ CGDirectDisplayID _gdk_macos_surface_get_screen_id (GdkMacosSurface
const char *_gdk_macos_surface_get_title (GdkMacosSurface *self);
void _gdk_macos_surface_set_title (GdkMacosSurface *self,
const char *title);
gboolean _gdk_macos_surface_is_opaque (GdkMacosSurface *self);
NSView *_gdk_macos_surface_get_view (GdkMacosSurface *self);
gboolean _gdk_macos_surface_get_modal_hint (GdkMacosSurface *self);
void _gdk_macos_surface_set_modal_hint (GdkMacosSurface *self,
-23
View File
@@ -553,29 +553,6 @@ gdk_macos_surface_init (GdkMacosSurface *self)
self->monitors = g_ptr_array_new_with_free_func (g_object_unref);
}
gboolean
_gdk_macos_surface_is_opaque (GdkMacosSurface *self)
{
GdkSurface *surface = (GdkSurface *)self;
g_return_val_if_fail (GDK_IS_MACOS_SURFACE (self), FALSE);
if (surface->opaque_region != NULL &&
cairo_region_num_rectangles (surface->opaque_region) == 1)
{
cairo_rectangle_int_t extents;
cairo_region_get_extents (surface->opaque_region, &extents);
return (extents.x == 0 &&
extents.y == 0 &&
extents.width == GDK_SURFACE (self)->width &&
extents.height == GDK_SURFACE (self)->height);
}
return FALSE;
}
const char *
_gdk_macos_surface_get_title (GdkMacosSurface *self)
{
+3
View File
@@ -236,6 +236,7 @@ gdk_wayland_clipboard_read_async (GdkClipboard *clipboard,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("No compatible transfer format found"));
g_object_unref (task);
return;
}
/* offer formats should be empty if we have no offer */
@@ -246,6 +247,7 @@ gdk_wayland_clipboard_read_async (GdkClipboard *clipboard,
if (!g_unix_open_pipe (pipe_fd, O_CLOEXEC, &error))
{
g_task_return_error (task, error);
g_object_unref (task);
return;
}
@@ -253,6 +255,7 @@ gdk_wayland_clipboard_read_async (GdkClipboard *clipboard,
stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
close (pipe_fd[1]);
g_task_return_pointer (task, stream, g_object_unref);
g_object_unref (task);
}
static GInputStream *
+131 -28
View File
@@ -61,6 +61,8 @@
#include <wayland/server-decoration-client-protocol.h>
#include "linux-dmabuf-unstable-v1-client-protocol.h"
#include "presentation-time-client-protocol.h"
#include "xx-color-management-v4-client-protocol.h"
#include "xx-session-management-v1-client-protocol.h"
#include "wm-button-layout-translation.h"
@@ -100,6 +102,7 @@
#define NO_XDG_OUTPUT_DONE_SINCE_VERSION 3
#define OUTPUT_VERSION 3
#define XDG_WM_DIALOG_VERSION 1
#define XX_SESSION_MANAGEMENT_VERSION 1
#ifdef HAVE_TOPLEVEL_STATE_SUSPENDED
#define XDG_WM_BASE_VERSION 6
@@ -310,6 +313,46 @@ static const struct org_kde_kwin_server_decoration_manager_listener server_decor
.default_mode = server_decoration_manager_default_mode
};
static void
session_listener_created (void *data,
struct xx_session_v1 *xdg_session_v1,
const char *id)
{
GdkWaylandDisplay *display_wayland = data;
GDK_DEBUG (MISC, "session created: %s", id);
if (g_strcmp0 (display_wayland->session_id, id) != 0)
{
g_clear_pointer (&display_wayland->session_id, g_free);
display_wayland->session_id = g_strdup (id);
}
}
static void
session_listener_restored (void *data,
struct xx_session_v1 *xdg_session_v1)
{
GdkWaylandDisplay *display_wayland = data;
GDK_DEBUG (MISC, "session restored: %s", display_wayland->session_id);
}
static void
session_listener_replaced (void *data,
struct xx_session_v1 *xdg_session_v1)
{
GdkWaylandDisplay *display_wayland = data;
GDK_DEBUG (MISC, "session replaced: %s", display_wayland->session_id);
}
static const struct xx_session_v1_listener xdg_session_listener = {
.created = session_listener_created,
.restored = session_listener_restored,
.replaced = session_listener_replaced,
};
/*
* gdk_wayland_display_prefers_ssd:
* @display: (type GdkWaylandDisplay): a `GdkDisplay`
@@ -352,19 +395,19 @@ gdk_registry_handle_global (void *data,
GDK_DEBUG (MISC, "add global %u, interface %s, version %u", id, interface, version);
if (strcmp (interface, "wl_compositor") == 0)
if (strcmp (interface, wl_compositor_interface.name) == 0)
{
display_wayland->compositor =
wl_registry_bind (display_wayland->wl_registry, id,
&wl_compositor_interface, MIN (version, 6));
}
else if (strcmp (interface, "wl_shm") == 0)
else if (strcmp (interface, wl_shm_interface.name) == 0)
{
display_wayland->shm =
wl_registry_bind (display_wayland->wl_registry, id, &wl_shm_interface, 1);
wl_shm_add_listener (display_wayland->shm, &wl_shm_listener, display_wayland);
}
else if (strcmp (interface, "zwp_linux_dmabuf_v1") == 0 && version >= 4)
else if (strcmp (interface, zwp_linux_dmabuf_v1_interface.name) == 0 && version >= 4)
{
struct zwp_linux_dmabuf_feedback_v1 *feedback;
@@ -376,23 +419,31 @@ gdk_registry_handle_global (void *data,
feedback);
_gdk_wayland_display_async_roundtrip (display_wayland);
}
else if (strcmp (interface, "xdg_wm_base") == 0)
else if (strcmp (interface, xdg_wm_base_interface.name) == 0)
{
display_wayland->xdg_wm_base_id = id;
display_wayland->xdg_wm_base_version = version;
}
else if (strcmp (interface, "zxdg_shell_v6") == 0)
else if (strcmp (interface, zxdg_shell_v6_interface.name) == 0)
{
display_wayland->zxdg_shell_v6_id = id;
}
else if (strcmp (interface, "xdg_wm_dialog_v1") == 0)
else if (strcmp (interface, xdg_wm_dialog_v1_interface.name) == 0)
{
display_wayland->xdg_wm_dialog =
wl_registry_bind (display_wayland->wl_registry, id,
&xdg_wm_dialog_v1_interface,
MIN (version, XDG_WM_DIALOG_VERSION));
}
else if (strcmp (interface, "gtk_shell1") == 0)
else if (strcmp (interface, xx_session_manager_v1_interface.name) == 0 &&
gdk_has_feature (GDK_FEATURE_SESSION_MANAGEMENT))
{
display_wayland->xdg_session_manager =
wl_registry_bind (display_wayland->wl_registry, id,
&xx_session_manager_v1_interface,
MIN (version, XX_SESSION_MANAGEMENT_VERSION));
}
else if (strcmp (interface, gtk_shell1_interface.name) == 0)
{
display_wayland->gtk_shell =
wl_registry_bind (display_wayland->wl_registry, id,
@@ -400,7 +451,7 @@ gdk_registry_handle_global (void *data,
MIN (version, GTK_SHELL1_VERSION));
gdk_wayland_display_set_has_gtk_shell (display_wayland);
}
else if (strcmp (interface, "wl_output") == 0)
else if (strcmp (interface, wl_output_interface.name) == 0)
{
output =
wl_registry_bind (display_wayland->wl_registry, id, &wl_output_interface,
@@ -409,7 +460,7 @@ gdk_registry_handle_global (void *data,
MIN (version, OUTPUT_VERSION));
_gdk_wayland_display_async_roundtrip (display_wayland);
}
else if (strcmp (interface, "wl_seat") == 0)
else if (strcmp (interface, wl_seat_interface.name) == 0)
{
SeatAddedClosure *closure;
static const char *required_device_manager_globals[] = {
@@ -425,67 +476,67 @@ gdk_registry_handle_global (void *data,
closure->version = version;
postpone_on_globals_closure (display_wayland, &closure->base);
}
else if (strcmp (interface, "wl_data_device_manager") == 0)
else if (strcmp (interface, wl_data_device_manager_interface.name) == 0)
{
display_wayland->data_device_manager =
wl_registry_bind (display_wayland->wl_registry, id, &wl_data_device_manager_interface,
MIN (version, 3));
}
else if (strcmp (interface, "wl_subcompositor") == 0)
else if (strcmp (interface, wl_subcompositor_interface.name) == 0)
{
display_wayland->subcompositor =
wl_registry_bind (display_wayland->wl_registry, id, &wl_subcompositor_interface, 1);
}
else if (strcmp (interface, "zwp_pointer_gestures_v1") == 0)
else if (strcmp (interface, zwp_pointer_gestures_v1_interface.name) == 0)
{
display_wayland->pointer_gestures =
wl_registry_bind (display_wayland->wl_registry,
id, &zwp_pointer_gestures_v1_interface,
MIN (version, GDK_ZWP_POINTER_GESTURES_V1_VERSION));
}
else if (strcmp (interface, "zwp_primary_selection_device_manager_v1") == 0)
else if (strcmp (interface, zwp_primary_selection_device_manager_v1_interface.name) == 0)
{
display_wayland->primary_selection_manager =
wl_registry_bind(display_wayland->wl_registry, id,
&zwp_primary_selection_device_manager_v1_interface, 1);
}
else if (strcmp (interface, "zwp_tablet_manager_v2") == 0)
else if (strcmp (interface, zwp_tablet_manager_v2_interface.name) == 0)
{
display_wayland->tablet_manager =
wl_registry_bind(display_wayland->wl_registry, id,
&zwp_tablet_manager_v2_interface, 1);
}
else if (strcmp (interface, "zxdg_exporter_v1") == 0)
else if (strcmp (interface, zxdg_exporter_v1_interface.name) == 0)
{
display_wayland->xdg_exporter =
wl_registry_bind (display_wayland->wl_registry, id,
&zxdg_exporter_v1_interface, 1);
}
else if (strcmp (interface, "zxdg_exporter_v2") == 0)
else if (strcmp (interface, zxdg_exporter_v2_interface.name) == 0)
{
display_wayland->xdg_exporter_v2 =
wl_registry_bind (display_wayland->wl_registry, id,
&zxdg_exporter_v2_interface, 1);
}
else if (strcmp (interface, "zxdg_importer_v1") == 0)
else if (strcmp (interface, zxdg_importer_v1_interface.name) == 0)
{
display_wayland->xdg_importer =
wl_registry_bind (display_wayland->wl_registry, id,
&zxdg_importer_v1_interface, 1);
}
else if (strcmp (interface, "zxdg_importer_v2") == 0)
else if (strcmp (interface, zxdg_importer_v2_interface.name) == 0)
{
display_wayland->xdg_importer_v2 =
wl_registry_bind (display_wayland->wl_registry, id,
&zxdg_importer_v2_interface, 1);
}
else if (strcmp (interface, "zwp_keyboard_shortcuts_inhibit_manager_v1") == 0)
else if (strcmp (interface, zwp_keyboard_shortcuts_inhibit_manager_v1_interface.name) == 0)
{
display_wayland->keyboard_shortcuts_inhibit =
wl_registry_bind (display_wayland->wl_registry, id,
&zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1);
}
else if (strcmp (interface, "org_kde_kwin_server_decoration_manager") == 0)
else if (strcmp (interface, org_kde_kwin_server_decoration_manager_interface.name) == 0)
{
display_wayland->server_decoration_manager =
wl_registry_bind (display_wayland->wl_registry, id,
@@ -494,7 +545,7 @@ gdk_registry_handle_global (void *data,
&server_decoration_listener,
display_wayland);
}
else if (strcmp(interface, "zxdg_output_manager_v1") == 0)
else if (strcmp (interface, zxdg_output_manager_v1_interface.name) == 0)
{
display_wayland->xdg_output_manager =
wl_registry_bind (display_wayland->wl_registry, id,
@@ -503,38 +554,39 @@ gdk_registry_handle_global (void *data,
gdk_wayland_display_init_xdg_output (display_wayland);
_gdk_wayland_display_async_roundtrip (display_wayland);
}
else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0)
else if (strcmp (interface, zwp_idle_inhibit_manager_v1_interface.name) == 0)
{
display_wayland->idle_inhibit_manager =
wl_registry_bind (display_wayland->wl_registry, id,
&zwp_idle_inhibit_manager_v1_interface, 1);
}
else if (strcmp (interface, "xdg_activation_v1") == 0)
else if (strcmp (interface, xdg_activation_v1_interface.name) == 0)
{
display_wayland->xdg_activation =
wl_registry_bind (display_wayland->wl_registry, id,
&xdg_activation_v1_interface, 1);
}
else if (strcmp (interface, "wp_fractional_scale_manager_v1") == 0)
else if (strcmp (interface, wp_fractional_scale_manager_v1_interface.name) == 0)
{
display_wayland->fractional_scale =
wl_registry_bind (display_wayland->wl_registry, id,
&wp_fractional_scale_manager_v1_interface, 1);
}
else if (strcmp (interface, "wp_viewporter") == 0)
else if (strcmp (interface, wp_viewporter_interface.name) == 0)
{
display_wayland->viewporter =
wl_registry_bind (display_wayland->wl_registry, id,
&wp_viewporter_interface, 1);
}
else if (strcmp (interface, "wp_presentation") == 0)
else if (strcmp (interface, wp_presentation_interface.name) == 0)
{
display_wayland->presentation =
wl_registry_bind (display_wayland->wl_registry, id,
&wp_presentation_interface,
MIN (version, 1));
}
else if (strcmp (interface, "xx_color_manager_v4") == 0)
else if (strcmp (interface, xx_color_manager_v4_interface.name) == 0 &&
gdk_has_feature (GDK_FEATURE_COLOR_MANAGEMENT))
{
display_wayland->color = gdk_wayland_color_new (display_wayland, registry, id, version);
}
@@ -765,6 +817,8 @@ gdk_wayland_display_dispose (GObject *object)
g_clear_pointer (&display_wayland->linux_dmabuf, zwp_linux_dmabuf_v1_destroy);
g_clear_pointer (&display_wayland->dmabuf_formats_info, dmabuf_formats_info_free);
g_clear_pointer (&display_wayland->color, gdk_wayland_color_free);
g_clear_pointer (&display_wayland->xdg_session, xx_session_v1_destroy);
g_clear_pointer (&display_wayland->xdg_session_manager, xx_session_manager_v1_destroy);
g_clear_pointer (&display_wayland->shm, wl_shm_destroy);
g_clear_pointer (&display_wayland->wl_registry, wl_registry_destroy);
@@ -1942,7 +1996,8 @@ init_settings (GdkDisplay *display)
GSettings *settings;
int i;
if (gdk_should_use_portal ())
if (gdk_should_use_portal () &&
!(gdk_display_get_debug_flags (display) & GDK_DEBUG_DEFAULT_SETTINGS))
{
GVariant *ret;
GError *error = NULL;
@@ -2806,3 +2861,51 @@ gdk_wayland_display_dispatch_queue (GdkDisplay *display,
_exit (1);
}
}
void
gdk_wayland_display_register_session (GdkDisplay *display,
const char *name)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
GDK_DEBUG (MISC, "register session %s", name);
if (!display_wayland->xdg_session_manager)
return;
g_clear_pointer (&display_wayland->session_id, g_free);
display_wayland->session_id = g_strdup (name);
display_wayland->xdg_session =
xx_session_manager_v1_get_session (display_wayland->xdg_session_manager,
XX_SESSION_MANAGER_V1_REASON_LAUNCH,
name);
xx_session_v1_add_listener (display_wayland->xdg_session,
&xdg_session_listener,
display_wayland);
wl_display_roundtrip (display_wayland->wl_display);
}
void
gdk_wayland_display_unregister_session (GdkDisplay *display)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
if (!display_wayland->xdg_session_manager)
return;
if (display_wayland->xdg_session)
xx_session_v1_remove (display_wayland->xdg_session);
g_clear_pointer (&display_wayland->session_id, g_free);
g_clear_pointer (&display_wayland->xdg_session, xx_session_v1_destroy);
}
const char *
gdk_wayland_display_get_current_session_id (GdkDisplay *display)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
return display_wayland->session_id;
}
+5
View File
@@ -42,6 +42,7 @@
#include <gdk/wayland/presentation-time-client-protocol.h>
#include <gdk/wayland/single-pixel-buffer-v1-client-protocol.h>
#include <gdk/wayland/xdg-dialog-v1-client-protocol.h>
#include <gdk/wayland/xx-session-management-v1-client-protocol.h>
#include <glib.h>
#include <gdk/gdkkeys.h>
@@ -124,6 +125,8 @@ struct _GdkWaylandDisplay
struct wp_viewporter *viewporter;
struct wp_presentation *presentation;
struct wp_single_pixel_buffer_manager_v1 *single_pixel_buffer;
struct xx_session_manager_v1 *xdg_session_manager;
struct xx_session_v1 *xdg_session;
GdkWaylandColor *color;
GList *async_roundtrips;
@@ -153,6 +156,8 @@ struct _GdkWaylandDisplay
GListStore *monitors;
char *session_id;
gint64 last_bell_time_ms;
};
+3
View File
@@ -203,6 +203,7 @@ gdk_wayland_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("No compatible transfer format found"));
g_object_unref (task);
return;
}
@@ -211,6 +212,7 @@ gdk_wayland_drop_read_async (GdkDrop *drop,
if (!g_unix_open_pipe (pipe_fd, O_CLOEXEC, &error))
{
g_task_return_error (task, error);
g_object_unref (task);
return;
}
@@ -218,6 +220,7 @@ gdk_wayland_drop_read_async (GdkDrop *drop,
stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
close (pipe_fd[1]);
g_task_return_pointer (task, stream, g_object_unref);
g_object_unref (task);
}
static GInputStream *
+3
View File
@@ -335,6 +335,7 @@ gdk_wayland_primary_read_async (GdkClipboard *clipboard,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("No compatible transfer format found"));
g_object_unref (task);
return;
}
/* offer formats should be empty if we have no offer */
@@ -345,6 +346,7 @@ gdk_wayland_primary_read_async (GdkClipboard *clipboard,
if (!g_unix_open_pipe (pipe_fd, O_CLOEXEC, &error))
{
g_task_return_error (task, error);
g_object_unref (task);
return;
}
@@ -352,6 +354,7 @@ gdk_wayland_primary_read_async (GdkClipboard *clipboard,
stream = g_unix_input_stream_new (pipe_fd[0], TRUE);
close (pipe_fd[1]);
g_task_return_pointer (task, stream, g_object_unref);
g_object_unref (task);
}
static GInputStream *
+3 -4
View File
@@ -185,8 +185,8 @@ get_dmabuf_wl_buffer (GdkWaylandSubsurface *self,
while (!cd.done)
gdk_wayland_display_dispatch_queue (GDK_DISPLAY (display), event_queue);
wl_event_queue_destroy (event_queue);
zwp_linux_buffer_params_v1_destroy (params);
wl_event_queue_destroy (event_queue);
buffer = cd.buffer;
@@ -491,9 +491,6 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
has_background = self->bg_rect.width > 0 && self->bg_rect.height > 0;
if (has_background)
ensure_bg_surface (self);
if (!scaled_rect_is_integral (dest, 1, &device_rect))
{
GDK_DISPLAY_DEBUG (gdk_surface_get_display (sub->parent), OFFLOAD,
@@ -669,6 +666,8 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
if (has_background)
{
ensure_bg_surface (self);
if (background_changed)
{
wl_subsurface_set_position (self->bg_subsurface, self->bg_rect.x, self->bg_rect.y);
+7 -8
View File
@@ -1451,16 +1451,15 @@ void
gdk_wayland_surface_ensure_wl_egl_window (GdkSurface *surface)
{
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
int width, height;
if (impl->display_server.egl_window == NULL)
{
int width, height;
if (impl->display_server.egl_window != NULL)
return;
get_egl_window_size (surface, &width, &height);
impl->display_server.egl_window =
wl_egl_window_create (impl->display_server.wl_surface, width, height);
gdk_surface_set_egl_native_window (surface, impl->display_server.egl_window);
}
get_egl_window_size (surface, &width, &height);
impl->display_server.egl_window =
wl_egl_window_create (impl->display_server.wl_surface, width, height);
gdk_surface_set_egl_native_window (surface, impl->display_server.egl_window);
}
/* }}} */
+1 -1
View File
@@ -26,6 +26,6 @@
G_BEGIN_DECLS
void gdk_wayland_surface_ensure_wl_egl_window (GdkSurface *surface);
void gdk_wayland_surface_ensure_wl_egl_window (GdkSurface *surface);
G_END_DECLS
@@ -33,9 +33,6 @@ void gdk_wayland_toplevel_set_dbus_properties (GdkToplevel *toplevel,
const char *application_object_path,
const char *unique_bus_name);
void gdk_wayland_toplevel_announce_csd (GdkToplevel *toplevel);
void gdk_wayland_toplevel_announce_ssd (GdkToplevel *toplevel);
gboolean gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel);
void gdk_wayland_toplevel_uninhibit_idle (GdkToplevel *toplevel);
+94 -38
View File
@@ -38,6 +38,7 @@
#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
#include <wayland/xdg-foreign-unstable-v2-client-protocol.h>
#include <wayland/xdg-dialog-v1-client-protocol.h>
#include <wayland/xx-session-management-v1-client-protocol.h>
#include <stdlib.h>
#include <stdio.h>
@@ -126,6 +127,7 @@ struct _GdkWaylandToplevel
struct wl_output *initial_fullscreen_output;
struct wp_presentation_feedback *feedback;
struct xx_toplevel_session_v1 *toplevel_session;
struct {
GdkToplevelState unset_flags;
@@ -141,6 +143,8 @@ struct _GdkWaylandToplevel
gboolean has_bounds;
char *title;
gboolean decorated;
char *session_id;
GdkGeometry geometry_hints;
GdkSurfaceHints geometry_mask;
@@ -818,6 +822,23 @@ create_zxdg_toplevel_v6_resources (GdkWaylandToplevel *toplevel)
toplevel);
}
static void
attempt_restore_toplevel (GdkWaylandToplevel *wayland_toplevel)
{
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (wayland_toplevel));
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
if (display_wayland->xdg_session &&
wayland_toplevel->session_id &&
wayland_toplevel->display_server.xdg_toplevel)
{
wayland_toplevel->toplevel_session =
xx_session_v1_restore_toplevel (display_wayland->xdg_session,
wayland_toplevel->display_server.xdg_toplevel,
wayland_toplevel->session_id);
}
}
static void
gdk_wayland_surface_create_xdg_toplevel (GdkWaylandToplevel *wayland_toplevel)
{
@@ -884,6 +905,8 @@ gdk_wayland_surface_create_xdg_toplevel (GdkWaylandToplevel *wayland_toplevel)
if (!maybe_set_xdg_dialog_modal (wayland_toplevel))
maybe_set_gtk_surface_modal (wayland_toplevel);
attempt_restore_toplevel (wayland_toplevel);
gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "Wayland surface commit", NULL);
wl_surface_commit (wayland_surface->display_server.wl_surface);
}
@@ -1256,6 +1279,32 @@ gdk_wayland_toplevel_set_transient_for (GdkWaylandToplevel *toplevel,
#define LAST_PROP 1
static void
gdk_wayland_toplevel_set_decorated (GdkWaylandToplevel *self,
gboolean decorated)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (self)));
if (self->decorated == decorated)
return;
self->decorated = decorated;
if (display_wayland->server_decoration_manager)
{
if (self->server_decoration == NULL)
self->server_decoration =
org_kde_kwin_server_decoration_manager_create (display_wayland->server_decoration_manager,
gdk_wayland_surface_get_wl_surface (GDK_SURFACE (self)));
org_kde_kwin_server_decoration_request_mode (self->server_decoration,
decorated ? ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER
: ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_CLIENT);
}
g_object_notify (G_OBJECT (self), "decorated");
}
static void
gdk_wayland_toplevel_set_property (GObject *object,
guint prop_id,
@@ -1291,6 +1340,7 @@ gdk_wayland_toplevel_set_property (GObject *object,
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_DECORATED:
gdk_wayland_toplevel_set_decorated (toplevel, g_value_get_boolean (value));
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_DELETABLE:
@@ -1346,6 +1396,7 @@ gdk_wayland_toplevel_get_property (GObject *object,
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_DECORATED:
g_value_set_boolean (value, toplevel->decorated);
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_DELETABLE:
@@ -1380,6 +1431,9 @@ gdk_wayland_toplevel_finalize (GObject *object)
g_free (self->application.application_object_path);
g_free (self->application.unique_bus_name);
g_free (self->session_id);
g_clear_pointer (&self->toplevel_session, xx_toplevel_session_v1_destroy);
g_free (self->title);
g_clear_pointer (&self->shortcuts_inhibitors, g_hash_table_unref);
@@ -2451,44 +2505,6 @@ gdk_wayland_toplevel_set_application_id (GdkToplevel *toplevel,
}
}
void
gdk_wayland_toplevel_announce_csd (GdkToplevel *toplevel)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (toplevel)));
GdkWaylandToplevel *toplevel_wayland;
g_return_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel));
toplevel_wayland = GDK_WAYLAND_TOPLEVEL (toplevel);
if (!display_wayland->server_decoration_manager)
return;
toplevel_wayland->server_decoration =
org_kde_kwin_server_decoration_manager_create (display_wayland->server_decoration_manager,
gdk_wayland_surface_get_wl_surface (GDK_SURFACE (toplevel_wayland)));
if (toplevel_wayland->server_decoration)
org_kde_kwin_server_decoration_request_mode (toplevel_wayland->server_decoration,
ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_CLIENT);
}
void
gdk_wayland_toplevel_announce_ssd (GdkToplevel *toplevel)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (toplevel)));
GdkWaylandToplevel *toplevel_wayland;
g_return_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel));
toplevel_wayland = GDK_WAYLAND_TOPLEVEL (toplevel);
if (!display_wayland->server_decoration_manager)
return;
toplevel_wayland->server_decoration =
org_kde_kwin_server_decoration_manager_create (display_wayland->server_decoration_manager,
gdk_wayland_surface_get_wl_surface (GDK_SURFACE (toplevel_wayland)));
if (toplevel_wayland->server_decoration)
org_kde_kwin_server_decoration_request_mode (toplevel_wayland->server_decoration,
ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER);
}
gboolean
gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel)
{
@@ -2773,5 +2789,45 @@ gdk_wayland_toplevel_set_transient_for_exported (GdkToplevel *toplevel,
return TRUE;
}
void
gdk_wayland_toplevel_set_session_id (GdkToplevel *toplevel,
const char *session_id)
{
GdkWaylandToplevel *wayland_toplevel = GDK_WAYLAND_TOPLEVEL (toplevel);
g_clear_pointer (&wayland_toplevel->session_id, g_free);
wayland_toplevel->session_id = g_strdup (session_id);
}
void
gdk_wayland_toplevel_restore_from_session (GdkToplevel *toplevel)
{
GdkWaylandToplevel *wayland_toplevel = GDK_WAYLAND_TOPLEVEL (toplevel);
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (toplevel));
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
if (display_wayland->xdg_session && wayland_toplevel->display_server.xdg_toplevel)
{
wayland_toplevel->toplevel_session =
xx_session_v1_restore_toplevel (display_wayland->xdg_session,
wayland_toplevel->display_server.xdg_toplevel,
wayland_toplevel->session_id);
}
}
void
gdk_wayland_toplevel_remove_from_session (GdkToplevel *toplevel)
{
GdkWaylandToplevel *wayland_toplevel = GDK_WAYLAND_TOPLEVEL (toplevel);
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (toplevel));
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
if (display_wayland->xdg_session && wayland_toplevel->toplevel_session)
{
xx_toplevel_session_v1_remove (wayland_toplevel->toplevel_session);
wayland_toplevel->toplevel_session = NULL;
}
}
/* }}} */
/* vim:set foldmethod=marker expandtab: */
+6
View File
@@ -64,10 +64,16 @@ gdk_vulkan_context_wayland_end_frame (GdkDrawContext *context,
cairo_region_t *painted)
{
GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context));
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
int dx = impl->pending_buffer_offset_x;
int dy = impl->pending_buffer_offset_y;
gdk_wayland_surface_sync (surface);
gdk_wayland_surface_request_frame (surface);
if (wl_surface_get_version (impl->display_server.wl_surface) >= WL_SURFACE_OFFSET_SINCE_VERSION)
wl_surface_offset (impl->display_server.wl_surface, dx, dy);
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_vulkan_context_parent_class)->end_frame (context, painted);
gdk_wayland_surface_notify_committed (surface);
+108 -16
View File
@@ -1,10 +1,11 @@
#include "config.h"
#include "gdkwaylandcolor-private.h"
#include "gdksurface-wayland-private.h"
#include <gdk/wayland/xx-color-management-v4-client-protocol.h>
static uint primaries_map[] = {
typedef struct _ImageDescription ImageDescription;
static const uint primaries_map[] = {
[XX_COLOR_MANAGER_V4_PRIMARIES_SRGB] = 1,
[XX_COLOR_MANAGER_V4_PRIMARIES_PAL_M] = 4,
[XX_COLOR_MANAGER_V4_PRIMARIES_PAL] = 5,
@@ -33,7 +34,48 @@ cicp_to_wl_primaries (uint cp)
return 0;
}
static uint transfer_map[] = {
static const uint primaries_primaries[][8] = {
[XX_COLOR_MANAGER_V4_PRIMARIES_SRGB] = { 6400, 3300, 3000, 6000, 1500, 600, 3127, 3290 },
[XX_COLOR_MANAGER_V4_PRIMARIES_PAL_M] = { 6700, 3300, 2100, 7100, 1400, 800, 3100, 3160 },
[XX_COLOR_MANAGER_V4_PRIMARIES_PAL] = { 6400, 3300, 2900, 6000, 1500, 600, 3127, 3290 },
[XX_COLOR_MANAGER_V4_PRIMARIES_NTSC] = { 6300, 3400, 3100, 5950, 1550, 700, 3127, 3290 },
[XX_COLOR_MANAGER_V4_PRIMARIES_GENERIC_FILM] = { 2430, 6920, 1450, 490, 6810, 3190, 3100, 3160 },
[XX_COLOR_MANAGER_V4_PRIMARIES_BT2020] = { 7080, 2920, 1700, 7970, 1310, 460, 3127, 3290 },
[XX_COLOR_MANAGER_V4_PRIMARIES_CIE1931_XYZ] = {10000, 0, 0,10000, 0, 0, 3333, 3333 },
[XX_COLOR_MANAGER_V4_PRIMARIES_DCI_P3] = { 6800, 3200, 2650, 6900, 1500, 600, 3140, 3510 },
[XX_COLOR_MANAGER_V4_PRIMARIES_DISPLAY_P3] = { 6800, 3200, 2650, 6900, 1500, 600, 3127, 3290 },
[XX_COLOR_MANAGER_V4_PRIMARIES_ADOBE_RGB] = { 6400, 3300, 2100, 7100, 1500, 600, 3127, 3290 },
};
static const uint *
wl_primaries_to_primaries (enum xx_color_manager_v4_primaries primaries)
{
return primaries_primaries[primaries];
}
static gboolean
primaries_to_wl_primaries (const uint primaries[8],
enum xx_color_manager_v4_primaries *out_primaries)
{
guint i, j;
for (i = 0; i < G_N_ELEMENTS (primaries_primaries); i++)
{
for (j = 0; j < 8; j++)
{
if (primaries[j] != primaries_primaries[i][j])
break;
}
if (j == 8)
{
*out_primaries = i;
return TRUE;
}
}
return FALSE;
}
static const uint transfer_map[] = {
[XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_BT709] = 1,
[XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA22] = 4,
[XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA28] = 5,
@@ -299,7 +341,8 @@ create_image_desc (GdkWaylandColor *color,
primaries = cicp_to_wl_primaries (norm.color_primaries);
tf = cicp_to_wl_transfer (norm.transfer_function);
if ((color->color_manager_supported.primaries & (1 << primaries)) == 0 ||
if (((color->color_manager_supported.primaries & (1 << primaries)) == 0 &&
(color->color_manager_supported.features & (1 << XX_COLOR_MANAGER_V4_FEATURE_SET_PRIMARIES)) == 0) ||
(color->color_manager_supported.transfers & (1 << tf)) == 0)
{
GDK_DEBUG (MISC, "Unsupported color state %s: Primaries or transfer function unsupported",
@@ -315,7 +358,19 @@ create_image_desc (GdkWaylandColor *color,
creator = xx_color_manager_v4_new_parametric_creator (color->color_manager);
xx_image_description_creator_params_v4_set_primaries_named (creator, primaries);
if (color->color_manager_supported.primaries & (1 << primaries))
{
xx_image_description_creator_params_v4_set_primaries_named (creator, primaries);
}
else
{
const uint *p = wl_primaries_to_primaries (primaries);
xx_image_description_creator_params_v4_set_primaries (creator,
p[0], p[1],
p[2], p[3],
p[4], p[5],
p[6], p[7]);
}
xx_image_description_creator_params_v4_set_tf_named (creator, tf);
desc = xx_image_description_creator_params_v4_create (creator);
@@ -394,7 +449,8 @@ gdk_wayland_color_prepare (GdkWaylandColor *color)
if (color->color_manager &&
(!(color->color_manager_supported.features & (1 << XX_COLOR_MANAGER_V4_FEATURE_PARAMETRIC)) ||
!(color->color_manager_supported.transfers & (1 << XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB)) ||
!(color->color_manager_supported.primaries & (1 << XX_COLOR_MANAGER_V4_PRIMARIES_SRGB))))
!((color->color_manager_supported.primaries & (1 << XX_COLOR_MANAGER_V4_PRIMARIES_SRGB)) ||
(color->color_manager_supported.features & (1 << XX_COLOR_MANAGER_V4_FEATURE_SET_PRIMARIES)))))
{
GDK_DEBUG (MISC, "Not using color management: Can't create srgb image description");
@@ -408,7 +464,8 @@ gdk_wayland_color_prepare (GdkWaylandColor *color)
if (color->color_manager_supported.transfers & (1 << XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LINEAR))
create_image_desc (color, GDK_COLOR_STATE_SRGB_LINEAR, FALSE);
if (color->color_manager_supported.primaries & (1 << XX_COLOR_MANAGER_V4_PRIMARIES_BT2020))
if ((color->color_manager_supported.primaries & (1 << XX_COLOR_MANAGER_V4_PRIMARIES_BT2020) ||
(color->color_manager_supported.features & (1 << XX_COLOR_MANAGER_V4_FEATURE_SET_PRIMARIES))))
{
if (color->color_manager_supported.transfers & (1 << XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ))
create_image_desc (color, GDK_COLOR_STATE_REC2100_PQ, FALSE);
@@ -426,11 +483,12 @@ struct _GdkWaylandColorSurface
GdkWaylandColor *color;
struct xx_color_management_surface_v4 *surface;
struct xx_color_management_feedback_surface_v4 *feedback;
ImageDescription *current_desc;
GdkColorStateChanged callback;
gpointer data;
};
typedef struct
struct _ImageDescription
{
GdkWaylandColorSurface *surface;
@@ -460,7 +518,7 @@ typedef struct
unsigned int has_target_luminance : 1;
unsigned int has_target_max_cll : 1;
unsigned int has_target_max_fall : 1;
} ImageDescription;
};
static GdkColorState *
gdk_color_state_from_image_description_bits (ImageDescription *desc)
@@ -480,6 +538,21 @@ gdk_color_state_from_image_description_bits (ImageDescription *desc)
return NULL;
}
static void
gdk_wayland_color_surface_clear_image_desc (GdkWaylandColorSurface *self)
{
ImageDescription *desc = self->current_desc;
if (desc == NULL)
return;
g_clear_pointer (&desc->image_desc, xx_image_description_v4_destroy);
g_clear_pointer (&desc->info, xx_image_description_info_v4_destroy);
g_free (desc);
self->current_desc = NULL;
}
static void
image_desc_info_done (void *data,
struct xx_image_description_info_v4 *info)
@@ -488,6 +561,8 @@ image_desc_info_done (void *data,
GdkWaylandColorSurface *self = desc->surface;
GdkColorState *cs;
g_assert (self->current_desc == desc);
cs = gdk_color_state_from_image_description_bits (desc);
if (cs)
{
@@ -498,7 +573,7 @@ image_desc_info_done (void *data,
else
{
cs = GDK_COLOR_STATE_SRGB;
xx_image_description_v4_destroy (desc->image_desc);
g_clear_pointer (&desc->image_desc, xx_image_description_v4_destroy);
}
if (self->callback)
@@ -506,8 +581,7 @@ image_desc_info_done (void *data,
gdk_color_state_unref (cs);
xx_image_description_info_v4_destroy (desc->info);
g_free (desc);
gdk_wayland_color_surface_clear_image_desc (self);
}
static void
@@ -538,6 +612,9 @@ image_desc_info_primaries (void *data,
desc->b_x = b_x; desc->r_y = b_y;
desc->w_x = w_x; desc->r_y = w_y;
desc->has_primaries = 1;
if (primaries_to_wl_primaries ((uint[]) { r_x, r_y, g_x, g_y, b_x, b_y, w_x, w_y },
&desc->primaries))
desc->has_primaries_named = 1;
}
static void
@@ -546,9 +623,16 @@ image_desc_info_primaries_named (void *data,
uint32_t primaries)
{
ImageDescription *desc = data;
const uint *p;
desc->primaries = primaries;
desc->has_primaries_named = 1;
desc->has_primaries = 1;
p = wl_primaries_to_primaries (primaries);
desc->r_x = p[0]; desc->r_y = p[1];
desc->g_x = p[2]; desc->r_y = p[3];
desc->b_x = p[4]; desc->r_y = p[5];
desc->w_x = p[6]; desc->r_y = p[7];
}
static void
@@ -663,10 +747,11 @@ image_desc_failed (void *data,
ImageDescription *desc = data;
GdkWaylandColorSurface *self = desc->surface;
g_assert (self->current_desc == desc);
self->callback (self, GDK_COLOR_STATE_SRGB, self->data);
xx_image_description_v4_destroy (desc->image_desc);
g_free (desc);
gdk_wayland_color_surface_clear_image_desc (self);
}
static void
@@ -678,13 +763,14 @@ image_desc_ready (void *data,
GdkWaylandColorSurface *self = desc->surface;
GdkColorState *cs;
g_assert (self->current_desc == desc);
cs = g_hash_table_lookup (self->color->id_to_cs, GUINT_TO_POINTER (identity));
if (cs)
{
self->callback (self, cs, self->data);
xx_image_description_v4_destroy (desc->image_desc);
g_free (desc);
gdk_wayland_color_surface_clear_image_desc (self);
return;
}
@@ -709,9 +795,13 @@ preferred_changed (void *data,
if (!self->callback)
return;
/* If there's still an ongoing query, cancel it. It's outdated. */
gdk_wayland_color_surface_clear_image_desc (self);
desc = g_new0 (ImageDescription, 1);
desc->surface = self;
self->current_desc = desc;
desc->image_desc = xx_color_management_feedback_surface_v4_get_preferred (self->feedback);
@@ -749,6 +839,8 @@ gdk_wayland_color_surface_new (GdkWaylandColor *color,
void
gdk_wayland_color_surface_free (GdkWaylandColorSurface *self)
{
gdk_wayland_color_surface_clear_image_desc (self);
xx_color_management_surface_v4_destroy (self->surface);
xx_color_management_feedback_surface_v4_destroy (self->feedback);
+7
View File
@@ -65,5 +65,12 @@ gboolean gdk_wayland_display_query_registry (GdkDisplay *di
GDK_AVAILABLE_IN_4_4
gpointer gdk_wayland_display_get_egl_display (GdkDisplay *display);
void gdk_wayland_display_register_session (GdkDisplay *display,
const char *name);
void gdk_wayland_display_unregister_session (GdkDisplay *display);
const char * gdk_wayland_display_get_current_session_id (GdkDisplay *display);
G_END_DECLS
+7
View File
@@ -67,4 +67,11 @@ GDK_AVAILABLE_IN_ALL
void gdk_wayland_toplevel_set_application_id (GdkToplevel *toplevel,
const char *application_id);
void gdk_wayland_toplevel_set_session_id (GdkToplevel *toplevel,
const char *session_id);
void gdk_wayland_toplevel_restore_from_session (GdkToplevel *toplevel);
void gdk_wayland_toplevel_remove_from_session (GdkToplevel *toplevel);
G_END_DECLS
+5
View File
@@ -151,6 +151,11 @@ proto_sources = [
'stability': 'private',
'version': 4,
},
{
'name': 'xx-session-management',
'stability': 'private',
'version': 1,
},
]
gdk_wayland_gen_headers = []
@@ -0,0 +1,264 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="xx_session_management_v1">
<copyright>
Copyright 2018 Mike Blumenkrantz
Copyright 2018 Samsung Electronics Co., Ltd
Copyright 2018 Red Hat Inc.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
</copyright>
<description summary="Protocol for managing application sessions">
This description provides a high-level overview of the interplay between
the interfaces defined this protocol. For details, see the protocol
specification.
The xx_session_manager protocol declares interfaces necessary to
allow clients to restore toplevel state from previous executions. The
xx_session_manager_v1.get_session request can be used to obtain a
xx_session_v1 resource representing the state of a set of toplevels.
Clients may obtain the session string to use in future calls through
the xx_session_v1.created event. Compositors will use this string
as an identifiable token for future runs, possibly storing data about
the related toplevels in persistent storage.
Toplevels are managed through the xx_session_v1.add_toplevel and
xx_session_toplevel_v1.remove pair of requests. Clients will explicitly
request a toplevel to be restored according to prior state through the
xx_session_v1.restore_toplevel request before the toplevel is mapped.
Warning! The protocol described in this file is currently in the testing
phase. Backward compatible changes may be added together with the
corresponding interface version bump. Backward incompatible changes can
only be done by creating a new major version of the extension.
</description>
<interface name="xx_session_manager_v1" version="1">
<description summary="manage sessions for applications">
The xx_session_manager interface defines base requests for creating and
managing a session for an application. Sessions persist across application
and compositor restarts unless explicitly destroyed. A session is created
for the purpose of maintaining an application's xdg_toplevel surfaces
across compositor or application restarts. The compositor should remember
as many states as possible for surfaces in a given session, but there is
no requirement for which states must be remembered.
</description>
<enum name="error">
<entry name="in_use" summary="a requested session is already in use"
value="1"/>
</enum>
<enum name="reason">
<description summary="reason for getting a session">
The reason may determine in what way a session restores the window
management state of associated toplevels.
For example newly launched applications might be launched on the active
workspace with restored size and position, while a recovered
applications might restore additional state such as active workspace and
stacking order.
</description>
<entry name="launch" value="1">
<description summary="an app is newly launched">
A new app instance is launched, for example from an app launcher.
</description>
</entry>
<entry name="recover" value="2">
<description summary="an app recovered">
A app instance is recovering from for example a compositor or app crash.
</description>
</entry>
<entry name="session_restore" value="3">
<description summary="an app restored">
A app instance is restored, for example part of a restored session, or
restored from having been temporarily terminated due to resource
constraints.
</description>
</entry>
</enum>
<request name="destroy" type="destructor">
<description summary="Destroy this object">
This has no effect other than to destroy the xx_session_manager object.
</description>
</request>
<request name="get_session">
<description summary="create or restore a session">
Create a session object corresponding to either an existing session
identified by the given session identifier string or a new session.
While the session object exists, the session is considered to be "in
use".
If a identifier string represents a session that is currently actively
in use by the the same client, an 'in_use' error is raised. If some
other client is currently using the same session, the new session will
replace managing the associated state.
NULL is passed to initiate a new session. If an id is passed which does
not represent a valid session, the compositor treats it as if NULL had
been passed.
A client is allowed to have any number of in use sessions at the same
time.
</description>
<arg name="id" type="new_id" interface="xx_session_v1"/>
<arg name="reason" type="uint" enum="reason"
summary="reason for session"/>
<arg name="session" type="string"
summary="the session to restore"
allow-null="true"/>
</request>
</interface>
<interface name="xx_session_v1" version="1">
<description summary="A session for an application">
A xx_session_v1 object represents a session for an application. While the
object exists, all surfaces which have been added to the session will
have states stored by the compositor which can be reapplied at a later
time. Two sessions cannot exist for the same identifier string.
States for surfaces added to a session are automatically updated by the
compositor when they are changed.
Surfaces which have been added to a session are automatically removed from
the session if xdg_toplevel.destroy is called for the surface.
</description>
<enum name="error">
<entry name="invalid_restore"
summary="restore cannot be performed after initial toplevel commit"
value="1"/>
<entry name="name_in_use"
summary="toplevel name is already in used"
value="2"/>
<entry name="already_mapped"
summary="toplevel was already mapped when restored"
value="3"/>
</enum>
<request name="destroy" type="destructor">
<description summary="Destroy the session">
Destroy a session object, preserving the current state but not continuing
to make further updates if state changes occur. This makes the associated
xx_toplevel_session_v1 objects inert.
</description>
</request>
<request name="remove" type="destructor">
<description summary="Remove the session">
Remove the session, making it no longer available for restoration. A
compositor should in response to this request remove the data related to
this session from its storage.
</description>
</request>
<request name="add_toplevel">
<description summary="add a new surface to the session">
Attempt to add a given surface to the session. The passed name is used
to identify what window is being restored, and may be used store window
specific state within the session.
Calling this with a toplevel that is already managed by the session with
the same associated will raise an in_use error.
</description>
<arg name="id" type="new_id" interface="xx_toplevel_session_v1"/>
<arg name="toplevel" type="object" interface="xdg_toplevel"/>
<arg name="name" type="string"/>
</request>
<request name="restore_toplevel">
<description summary="restore a surface state">
Inform the compositor that the toplevel associated with the passed name
should have its window management state restored.
Calling this with a toplevel that is already managed by the session with
the same associated will raise an in_use error.
This request must be called prior to the first commit on the associated
wl_surface, otherwise an already_mapped error is raised.
As part of the initial configure sequence, if the toplevel was
successfully restored, a xx_toplevel_session_v1.restored event is
emitted. See the xx_toplevel_session_v1.restored event for further
details.
</description>
<arg name="id" type="new_id" interface="xx_toplevel_session_v1"/>
<arg name="toplevel" type="object" interface="xdg_toplevel"/>
<arg name="name" type="string"/>
</request>
<event name="created">
<description summary="newly-created session id">
Emitted at most once some time after getting a new session object. It
means that no previous state was restored, and a new session was created.
The passed id can be used to restore previous sessions.
</description>
<arg name="id" type="string"/>
</event>
<event name="restored">
<description summary="the session has been restored">
Emitted at most once some time after getting a new session object. It
means that previous state was at least partially restored. The same id
can again be used to restore previous sessions.
</description>
</event>
<event name="replaced">
<description summary="the session has been restored">
Emitted at most once, if the session was taken over by some other
client. When this happens, the session and all its toplevel session
objects become inert, and should be destroyed.
</description>
</event>
</interface>
<interface name="xx_toplevel_session_v1" version="1">
<request name="destroy" type="destructor">
<description summary="Destroy the object">
Destroy the object. This has no effect window management of the
associated toplevel.
</description>
</request>
<request name="remove" type="destructor">
<description summary="remove a surface from the session">
Remove a specified surface from the session and render any corresponding
xx_toplevel_session_v1 object inert. The compositor should remove any
data related to the toplevel in the corresponding session from its internal
storage.
</description>
</request>
<event name="restored">
<description summary="a toplevel's session has been restored">
The "restored" event is emitted prior to the first
xdg_toplevel.configure for the toplevel. It will only be emitted after
xx_session_v1.restore_toplevel, and the initial empty surface state has
been applied, and it indicates that the surface's session is being
restored with this configure event.
</description>
<arg name="surface" type="object" interface="xdg_toplevel"/>
</event>
</interface>
</protocol>
+57 -51
View File
@@ -561,64 +561,70 @@ G_DEFINE_TYPE (GdkWin32Display, gdk_win32_display, GDK_TYPE_DISPLAY)
static const char *
gdk_win32_display_get_name (GdkDisplay *display)
{
HDESK hdesk = GetThreadDesktop (GetCurrentThreadId ());
char dummy;
char *desktop_name;
HWINSTA hwinsta = GetProcessWindowStation ();
char *window_station_name;
DWORD n;
DWORD session_id;
char *display_name;
static const char *display_name_cache = NULL;
typedef BOOL (WINAPI *PFN_ProcessIdToSessionId) (DWORD, DWORD *);
PFN_ProcessIdToSessionId processIdToSessionId;
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
if (display_name_cache != NULL)
return display_name_cache;
n = 0;
GetUserObjectInformation (hdesk, UOI_NAME, &dummy, 0, &n);
if (n == 0)
desktop_name = "Default";
else
if (g_once_init_enter (&display_name_cache))
{
n++;
desktop_name = g_alloca (n + 1);
memset (desktop_name, 0, n + 1);
HDESK hdesk = GetThreadDesktop (GetCurrentThreadId ());
char dummy;
char dummy_dword[11];
wchar_t *desktop_name;
HWINSTA hwinsta = GetProcessWindowStation ();
wchar_t *window_station_name;
DWORD n;
DWORD session_id;
wchar_t *display_name_w;
char *display_name;
size_t wchar_size;
size_t display_name_len = 0;
if (!GetUserObjectInformation (hdesk, UOI_NAME, desktop_name, n, &n))
desktop_name = "Default";
n = 0;
GetUserObjectInformation (hdesk, UOI_NAME, &dummy, 0, &n);
wchar_size = sizeof (wchar_t);
if (n == 0)
desktop_name = L"Default";
else
{
n++;
desktop_name = g_alloca ((n + 1) * wchar_size);
memset (desktop_name, 0, (n + 1) * wchar_size);
if (!GetUserObjectInformation (hdesk, UOI_NAME, desktop_name, n, &n))
desktop_name = L"Default";
}
n = 0;
GetUserObjectInformation (hwinsta, UOI_NAME, &dummy, 0, &n);
if (n == 0)
window_station_name = L"WinSta0";
else
{
n++;
window_station_name = g_alloca ((n + 1) * wchar_size);
memset (window_station_name, 0, (n + 1) * wchar_size);
if (!GetUserObjectInformation (hwinsta, UOI_NAME, window_station_name, n, &n))
window_station_name = L"WinSta0";
}
if (!ProcessIdToSessionId (GetCurrentProcessId (), &session_id))
session_id = 0;
/* display_name is in the form of "%ld\\%s\\%s" */
display_name_len = strlen (itoa (session_id, dummy_dword, 10)) + 1 + wcslen (window_station_name) + 1 + wcslen (desktop_name);
display_name_w = g_alloca ((display_name_len + 1) * wchar_size);
memset (display_name_w, 0, (display_name_len + 1) * wchar_size);
swprintf_s (display_name_w, display_name_len + 1, L"%ld\\%s\\%s", session_id, window_station_name, desktop_name);
display_name = g_utf16_to_utf8 (display_name_w, -1, NULL, NULL, NULL);
GDK_NOTE (MISC, g_print ("gdk_win32_display_get_name: %s\n", display_name));
g_once_init_leave (&display_name_cache, display_name);
}
n = 0;
GetUserObjectInformation (hwinsta, UOI_NAME, &dummy, 0, &n);
if (n == 0)
window_station_name = "WinSta0";
else
{
n++;
window_station_name = g_alloca (n + 1);
memset (window_station_name, 0, n + 1);
if (!GetUserObjectInformation (hwinsta, UOI_NAME, window_station_name, n, &n))
window_station_name = "WinSta0";
}
processIdToSessionId = (PFN_ProcessIdToSessionId) GetProcAddress (GetModuleHandle (L"kernel32.dll"), "ProcessIdToSessionId");
if (!processIdToSessionId || !processIdToSessionId (GetCurrentProcessId (), &session_id))
session_id = 0;
display_name = g_strdup_printf ("%ld\\%s\\%s",
session_id,
window_station_name,
desktop_name);
GDK_NOTE (MISC, g_print ("gdk_win32_display_get_name: %s\n", display_name));
display_name_cache = display_name;
return display_name_cache;
}
@@ -1202,7 +1208,7 @@ gdk_win32_display_init_gl (GdkDisplay *display,
* Disable defaulting to EGL as EGL is used more as a compatibility layer
* on Windows rather than being a native citizen on Windows
*/
if (gdk_display_get_debug_flags (display) & (GDK_DEBUG_GL_EGL|GDK_DEBUG_GL_DISABLE_GL))
if (!gdk_has_feature (GDK_FEATURE_WGL) || !gdk_has_feature (GDK_FEATURE_GL_API))
{
init_gl_hdc = GetDC (display_win32->hwnd);
+1 -1
View File
@@ -134,7 +134,7 @@ struct _GdkWin32Display
guint hasWglEXTSwapControl : 1;
guint hasWglOMLSyncControl : 1;
guint hasWglARBPixelFormat : 1;
guint force_enable_depth_bits : 1;
guint hasGlWINSwapHint : 1;
#ifdef HAVE_EGL
guint hasEglKHRCreateContext : 1;
+9
View File
@@ -1016,6 +1016,7 @@ gdk_win32_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("No compatible transfer format found"));
g_object_unref (task);
g_clear_pointer (&drop_win32->dropfiles_list, g_free);
return;
@@ -1025,6 +1026,7 @@ gdk_win32_drop_read_async (GdkDrop *drop,
drop_win32->dropfiles_list = NULL;
g_object_set_data (G_OBJECT (stream), "gdk-dnd-stream-contenttype", (gpointer) "text/uri-list");
g_task_return_pointer (task, stream, g_object_unref);
g_object_unref (task);
return;
}
@@ -1035,6 +1037,7 @@ gdk_win32_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
_("GDK surface 0x%p is not registered as a drop target"), gdk_drop_get_surface (drop));
g_object_unref (task);
return;
}
@@ -1042,6 +1045,7 @@ gdk_win32_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Target context record 0x%p has no data object"), tctx);
g_object_unref (task);
return;
}
@@ -1061,6 +1065,7 @@ gdk_win32_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("No compatible transfer format found"));
g_object_unref (task);
return;
}
@@ -1080,6 +1085,7 @@ gdk_win32_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
_("IDataObject_GetData (0x%x) failed, returning 0x%lx"), fmt.cfFormat, hr);
g_object_unref (task);
return;
}
@@ -1092,6 +1098,7 @@ gdk_win32_drop_read_async (GdkDrop *drop,
if (data == NULL)
{
ReleaseStgMedium (&storage);
g_object_unref (task);
return;
}
@@ -1112,12 +1119,14 @@ gdk_win32_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Failed to transmute DnD data W32 format 0x%x to %p (%s)"), pair->w32format, pair->contentformat, pair->contentformat);
g_object_unref (task);
return;
}
stream = g_memory_input_stream_new_from_data (data, data_len, g_free);
g_object_set_data (G_OBJECT (stream), "gdk-dnd-stream-contenttype", (gpointer) pair->contentformat);
g_task_return_pointer (task, stream, g_object_unref);
g_object_unref (task);
}
static GInputStream *
+425 -77
View File
@@ -41,12 +41,24 @@
#include <cairo.h>
#include <epoxy/wgl.h>
/* libepoxy doesn't know about GL_WIN_swap_hint */
typedef void (WINAPI *glAddSwapHintRectWIN_t) (GLint, GLint, GLsizei, GLsizei);
struct _GdkWin32GLContextWGL
{
GdkWin32GLContext parent_instance;
HGLRC wgl_context;
guint do_frame_sync : 1;
guint double_buffered : 1;
enum {
SWAP_METHOD_UNDEFINED = 0,
SWAP_METHOD_COPY,
SWAP_METHOD_EXCHANGE,
} swap_method;
glAddSwapHintRectWIN_t ptr_glAddSwapHintRectWIN;
};
typedef struct _GdkWin32GLContextClass GdkWin32GLContextWGLClass;
@@ -80,6 +92,7 @@ gdk_win32_gl_context_wgl_end_frame (GdkDrawContext *draw_context,
GdkWin32GLContextWGL *context_wgl = GDK_WIN32_GL_CONTEXT_WGL (context);
GdkSurface *surface = gdk_gl_context_get_surface (context);
GdkWin32Display *display_win32 = (GDK_WIN32_DISPLAY (gdk_gl_context_get_display (context)));
GdkWin32Surface *surface_win32 = GDK_WIN32_SURFACE (surface);
gboolean can_wait = display_win32->hasWglOMLSyncControl;
HDC hdc;
@@ -90,10 +103,37 @@ gdk_win32_gl_context_wgl_end_frame (GdkDrawContext *draw_context,
gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "win32", "swap buffers");
if (surface != NULL)
hdc = GDK_WIN32_SURFACE (surface)->hdc;
hdc = surface_win32->hdc;
else
hdc = display_win32->dummy_context_wgl.hdc;
/* context->old_updated_area[0] contains this frame's updated region
* (what actually changed since the previous frame) */
if (context_wgl->ptr_glAddSwapHintRectWIN &&
GDK_GL_MAX_TRACKED_BUFFERS >= 1 &&
context->old_updated_area[0])
{
int num_rectangles = cairo_region_num_rectangles (context->old_updated_area[0]);
int scale = surface_win32->surface_scale;
cairo_rectangle_int_t rectangle;
for (int i = 0; i < num_rectangles; i++)
{
cairo_region_get_rectangle (context->old_updated_area[0], i, &rectangle);
/* glAddSwapHintRectWIN works in OpenGL buffer coordinates and uses OpenGL
* conventions. Coordinates are that of the client-area, but the origin is
* at the lower-left corner; rectangles are passed by their lower-left corner
*/
rectangle.y = surface->height - rectangle.y - rectangle.height;
context_wgl->ptr_glAddSwapHintRectWIN (rectangle.x * scale,
rectangle.y * scale,
rectangle.width * scale,
rectangle.height * scale);
}
}
if (context_wgl->do_frame_sync)
{
@@ -121,6 +161,27 @@ gdk_win32_gl_context_wgl_empty_frame (GdkDrawContext *draw_context)
{
}
static cairo_region_t *
gdk_win32_gl_context_wgl_get_damage (GdkGLContext *gl_context)
{
GdkWin32GLContextWGL *self = GDK_WIN32_GL_CONTEXT_WGL (gl_context);
if (!self->double_buffered ||
self->swap_method == SWAP_METHOD_COPY)
{
return cairo_region_create ();
}
if (self->swap_method == SWAP_METHOD_EXCHANGE &&
GDK_GL_MAX_TRACKED_BUFFERS >= 1 &&
gl_context->old_updated_area[0])
{
return cairo_region_reference (gl_context->old_updated_area[0]);
}
return GDK_GL_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->get_damage (gl_context);
}
static void
gdk_win32_gl_context_wgl_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
@@ -133,7 +194,292 @@ gdk_win32_gl_context_wgl_begin_frame (GdkDrawContext *draw_context,
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->begin_frame (draw_context, depth, update_area, out_color_state, out_depth);
}
#define PIXEL_ATTRIBUTES 21
typedef struct {
GArray *array;
guint committed;
} attribs_t;
static void
attribs_init (attribs_t *attribs,
guint reserved)
{
attribs->array = g_array_sized_new (TRUE, FALSE, sizeof (int), reserved);
attribs->committed = 0;
}
static void
attribs_commit (attribs_t *attribs)
{
g_assert_true (attribs->array->len % 2 == 0);
attribs->committed = attribs->array->len;
}
static void
attribs_reset (attribs_t *attribs)
{
g_array_set_size (attribs->array, attribs->committed);
}
static void
attribs_add_bulk (attribs_t *attribs,
const int *array,
int n_elements)
{
g_assert (n_elements >= 0);
g_assert_true (n_elements % 2 == 0);
g_array_append_vals (attribs->array, array, n_elements);
}
static void
attribs_add (attribs_t *attribs,
int key,
int value)
{
int array[2] = {key, value};
attribs_add_bulk (attribs, array, G_N_ELEMENTS (array));
}
static bool
attribs_remove_last (attribs_t *attribs)
{
if (attribs->array->len > attribs->committed)
{
g_array_set_size (attribs->array, attribs->array->len - 1);
return true;
}
return false;
}
static const int *
attribs_data (attribs_t *attribs)
{
return (const int *) attribs->array->data;
}
static void
attribs_fini (attribs_t *attribs)
{
g_array_free (attribs->array, TRUE);
}
#define attribs_add_static_array(attribs, array) \
do attribs_add_bulk (attribs, array, G_N_ELEMENTS (array)); while (0)
static int
find_pixel_format_with_defined_swap_flag (HDC hdc,
int formats[],
UINT count)
{
for (UINT i = 0; i < count; i++)
{
int query = WGL_SWAP_METHOD_ARB;
int value = WGL_SWAP_UNDEFINED_ARB;
SetLastError (0);
if (!wglGetPixelFormatAttribivARB (hdc, formats[i], 0, 1, &query, &value))
{
WIN32_API_FAILED ("wglGetPixelFormatAttribivARB");
continue;
}
if (value != WGL_SWAP_UNDEFINED_ARB)
return formats[i];
}
return 0;
}
static int
choose_pixel_format_arb_attribs (HDC hdc)
{
const int attribs_base[] = {
WGL_DRAW_TO_WINDOW_ARB,
GL_TRUE,
WGL_SUPPORT_OPENGL_ARB,
GL_TRUE,
WGL_DOUBLE_BUFFER_ARB,
GL_TRUE,
WGL_ACCELERATION_ARB,
WGL_FULL_ACCELERATION_ARB,
WGL_PIXEL_TYPE_ARB,
WGL_TYPE_RGBA_ARB,
WGL_COLOR_BITS_ARB,
32,
WGL_ALPHA_BITS_ARB,
8,
};
const int attribs_ancillary_buffers[] = {
WGL_STENCIL_BITS_ARB,
0,
WGL_ACCUM_BITS_ARB,
0,
WGL_DEPTH_BITS_ARB,
0,
};
attribs_t attribs;
int formats[4];
UINT count = 0;
int format = 0;
int saved = 0;
#define EXT_CALL(api, args) \
do { \
memset (formats, 0, sizeof (formats)); \
count = G_N_ELEMENTS (formats); \
\
if (!api args || count > G_N_ELEMENTS (formats)) \
{ \
count = 0; \
} \
} \
while (0)
const guint reserved = G_N_ELEMENTS (attribs_base) +
G_N_ELEMENTS (attribs_ancillary_buffers) +
1;
attribs_init (&attribs, reserved);
attribs_add_static_array (&attribs, attribs_base);
attribs_commit (&attribs);
attribs_add_static_array (&attribs, attribs_ancillary_buffers);
do
{
EXT_CALL (wglChoosePixelFormatARB, (hdc, attribs_data (&attribs), NULL,
G_N_ELEMENTS (formats), formats,
&count));
}
while (count == 0 && attribs_remove_last (&attribs));
if (count == 0)
goto done;
attribs_commit (&attribs);
/* That's an usable pixel format, save it */
saved = formats[0];
/* Do we have a defined swap method? */
format = find_pixel_format_with_defined_swap_flag (hdc, formats, count);
if (format > 0)
goto done;
/* Nope, but we can try to ask for it explicitly */
const int swap_methods[] = {
WGL_SWAP_EXCHANGE_ARB,
WGL_SWAP_COPY_ARB,
};
for (size_t i = 0; i < G_N_ELEMENTS (swap_methods); i++)
{
attribs_add (&attribs, WGL_SWAP_METHOD_ARB, swap_methods[i]);
EXT_CALL (wglChoosePixelFormatARB, (hdc, attribs_data (&attribs), NULL,
G_N_ELEMENTS (formats), formats,
&count));
format = find_pixel_format_with_defined_swap_flag (hdc, formats, count);
if (format > 0)
goto done;
attribs_reset (&attribs);
}
done:
attribs_fini (&attribs);
if (format == 0)
return saved;
return format;
#undef EXT_CALL
}
static int
get_distance (PIXELFORMATDESCRIPTOR *pfd)
{
const DWORD swap_flags = PFD_SWAP_COPY | PFD_SWAP_EXCHANGE;
int is_double_buffered = (pfd->dwFlags & PFD_DOUBLEBUFFER) != 0;
int is_swap_defined = (pfd->dwFlags & swap_flags) != 0;
int is_mono = (pfd->dwFlags & PFD_STEREO) == 0;
int ancillary_bits = pfd->cStencilBits + pfd->cDepthBits + pfd->cAccumBits;
int quality_distance = !is_double_buffered * 1000;
int performance_distance = !is_swap_defined * 200;
int memory_distance = !is_mono + ancillary_bits;
return quality_distance +
performance_distance +
memory_distance;
}
/* ChoosePixelFormat ignored some fields and flags, which makes it
* less useful for GTK. In particular, it ignores the PFD_SWAP flags,
* which are very important for GUI toolkits. Here we implement an
* analog function which is tied to the needs of GTK.
*
* Note that ChoosePixelFormat is not implemented by the ICD, it's
* implemented in OpenGL32.DLL (though the driver can influence the
* outcome by ordering pixel formats in specific ways.
*/
static int
choose_pixel_format_opengl32 (HDC hdc)
{
const DWORD skip_flags = PFD_GENERIC_FORMAT |
PFD_GENERIC_ACCELERATED;
const DWORD required_flags = PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL;
struct {
int index;
int distance;
} best = { 0, 1, }, current;
PIXELFORMATDESCRIPTOR pfd;
int count = DescribePixelFormat (hdc, 1, sizeof (pfd), NULL);
for (current.index = 1; current.index <= count && best.distance > 0; current.index++)
{
if (DescribePixelFormat (hdc, current.index, sizeof (pfd), &pfd) <= 0)
{
WIN32_API_FAILED ("DescribePixelFormat");
return 0;
}
if ((pfd.dwFlags & skip_flags) != 0 ||
(pfd.dwFlags & required_flags) != required_flags)
continue;
if (pfd.iPixelType != PFD_TYPE_RGBA ||
(pfd.cRedBits != 8 || pfd.cGreenBits != 8 ||
pfd.cBlueBits != 8 || pfd.cAlphaBits != 8))
continue;
current.distance = get_distance (&pfd);
if (best.index == 0 || current.distance < best.distance)
best = current;
}
return best.index;
}
static int
get_wgl_pfd (HDC hdc,
@@ -142,58 +488,12 @@ get_wgl_pfd (HDC hdc,
{
int best_pf = 0;
pfd->nSize = sizeof (PIXELFORMATDESCRIPTOR);
if (display_win32->hasWglARBPixelFormat)
{
UINT num_formats;
int colorbits = GetDeviceCaps (hdc, BITSPIXEL);
int i = 0;
int pixelAttribs[PIXEL_ATTRIBUTES];
/* Save up the HDC and HGLRC that we are currently using, to restore back to it when we are done here */
HDC hdc_current = wglGetCurrentDC ();
HGLRC hglrc_current = wglGetCurrentContext ();
/* Update PIXEL_ATTRIBUTES above if any groups are added here! */
pixelAttribs[i++] = WGL_DRAW_TO_WINDOW_ARB;
pixelAttribs[i++] = GL_TRUE;
pixelAttribs[i++] = WGL_SUPPORT_OPENGL_ARB;
pixelAttribs[i++] = GL_TRUE;
pixelAttribs[i++] = WGL_DOUBLE_BUFFER_ARB;
pixelAttribs[i++] = GL_TRUE;
pixelAttribs[i++] = WGL_ACCELERATION_ARB;
pixelAttribs[i++] = WGL_FULL_ACCELERATION_ARB;
pixelAttribs[i++] = WGL_PIXEL_TYPE_ARB;
pixelAttribs[i++] = WGL_TYPE_RGBA_ARB;
pixelAttribs[i++] = WGL_COLOR_BITS_ARB;
pixelAttribs[i++] = colorbits;
pixelAttribs[i++] = WGL_ALPHA_BITS_ARB;
pixelAttribs[i++] = 8;
pixelAttribs[i++] = WGL_STENCIL_BITS_ARB;
pixelAttribs[i++] = 0;
pixelAttribs[i++] = WGL_ACCUM_BITS_ARB;
pixelAttribs[i++] = 0;
if (!display_win32->force_enable_depth_bits)
{
pixelAttribs[i++] = WGL_DEPTH_BITS_ARB;
pixelAttribs[i++] = 0;
}
/* end of "Update PIXEL_ATTRIBUTES above if any groups are added here!" */
pixelAttribs[i++] = 0; /* end of pixelAttribs */
g_assert (i == PIXEL_ATTRIBUTES);
if (!wglMakeCurrent (display_win32->dummy_context_wgl.hdc,
display_win32->dummy_context_wgl.hglrc))
{
@@ -201,38 +501,17 @@ get_wgl_pfd (HDC hdc,
return 0;
}
wglChoosePixelFormatARB (hdc,
pixelAttribs,
NULL,
1,
&best_pf,
&num_formats);
best_pf = choose_pixel_format_arb_attribs (hdc);
/* Go back to the HDC that we were using, since we are done with the dummy HDC and GL Context */
wglMakeCurrent (hdc_current, hglrc_current);
}
else
{
pfd->nVersion = 1;
pfd->dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
pfd->iPixelType = PFD_TYPE_RGBA;
pfd->cColorBits = GetDeviceCaps (hdc, BITSPIXEL);
pfd->cAlphaBits = 8;
pfd->iLayerType = PFD_MAIN_PLANE;
pfd->cAccumBits = 0;
pfd->cStencilBits = 0;
best_pf = choose_pixel_format_opengl32 (hdc);
if (!display_win32->force_enable_depth_bits)
pfd->cDepthBits = 0;
best_pf = ChoosePixelFormat (hdc, pfd);
/* try again if driver enforces depth buffers */
if (best_pf == 0 && !display_win32->force_enable_depth_bits)
{
display_win32->force_enable_depth_bits = TRUE;
get_wgl_pfd (hdc, pfd, display_win32);
}
if (best_pf > 0)
DescribePixelFormat (hdc, best_pf, sizeof (PIXELFORMATDESCRIPTOR), pfd);
}
return best_pf;
@@ -355,6 +634,8 @@ gdk_win32_display_init_wgl (GdkDisplay *display,
epoxy_has_wgl_extension (hdc, "WGL_OML_sync_control");
display_win32->hasWglARBPixelFormat =
epoxy_has_wgl_extension (hdc, "WGL_ARB_pixel_format");
display_win32->hasGlWINSwapHint =
epoxy_has_gl_extension ("GL_WIN_swap_hint");
context = g_object_new (GDK_TYPE_WIN32_GL_CONTEXT_WGL,
"display", display,
@@ -374,13 +655,15 @@ gdk_win32_display_init_wgl (GdkDisplay *display,
"\t* WGL_ARB_pixel_format: %s\n"
"\t* WGL_ARB_create_context: %s\n"
"\t* WGL_EXT_swap_control: %s\n"
"\t* WGL_OML_sync_control: %s\n",
"\t* WGL_OML_sync_control: %s\n"
"\t* GL_WIN_swap_hint: %s\n",
major, minor,
glGetString (GL_VENDOR),
display_win32->hasWglARBPixelFormat ? "yes" : "no",
display_win32->hasWglARBCreateContext ? "yes" : "no",
display_win32->hasWglEXTSwapControl ? "yes" : "no",
display_win32->hasWglOMLSyncControl ? "yes" : "no"));
display_win32->hasWglOMLSyncControl ? "yes" : "no",
display_win32->hasGlWINSwapHint ? "yes" : "no"));
}
wglMakeCurrent (NULL, NULL);
@@ -760,13 +1043,77 @@ gdk_win32_gl_context_wgl_realize (GdkGLContext *context,
if (hglrc == NULL)
return 0;
context_wgl->wgl_context = hglrc;
HDC hdc_current = wglGetCurrentDC ();
HGLRC hglrc_current = wglGetCurrentContext ();
if (wglMakeCurrent (hdc, hglrc))
{
if (display_win32->hasWglARBPixelFormat)
{
/* wglChoosePixelFormatARB should match these attributes exactly
* as requested, according to the spec, but better check anyway */
int query_attribs[] = {
WGL_DOUBLE_BUFFER_ARB,
WGL_SWAP_METHOD_ARB,
};
int query_values[G_N_ELEMENTS (query_attribs)];
memset (query_values, 0, sizeof (query_values));
if (wglGetPixelFormatAttribivARB (hdc, pixel_format, 0, G_N_ELEMENTS (query_attribs), query_attribs, query_values))
{
context_wgl->double_buffered = (query_values[0] == GL_TRUE);
switch (query_values[1])
{
case WGL_SWAP_COPY_ARB:
context_wgl->swap_method = SWAP_METHOD_COPY;
break;
case WGL_SWAP_EXCHANGE_ARB:
context_wgl->swap_method = SWAP_METHOD_EXCHANGE;
break;
default:
context_wgl->swap_method = SWAP_METHOD_UNDEFINED;
break;
}
}
}
else
{
PIXELFORMATDESCRIPTOR pfd = {0};
if (DescribePixelFormat (hdc, pixel_format, sizeof (pfd), &pfd))
{
context_wgl->double_buffered = (pfd.dwFlags & PFD_DOUBLEBUFFER) != 0;
if (pfd.dwFlags & PFD_SWAP_COPY)
context_wgl->swap_method = SWAP_METHOD_COPY;
else if (pfd.dwFlags & PFD_SWAP_EXCHANGE)
context_wgl->swap_method = SWAP_METHOD_EXCHANGE;
else
context_wgl->swap_method = SWAP_METHOD_UNDEFINED;
}
}
if (display_win32->hasGlWINSwapHint)
{
context_wgl->ptr_glAddSwapHintRectWIN = (glAddSwapHintRectWIN_t)
wglGetProcAddress ("glAddSwapHintRectWIN");
}
}
wglMakeCurrent (hdc_current, hglrc_current);
if (context_wgl->swap_method == SWAP_METHOD_UNDEFINED)
g_message ("Unknown swap method");
GDK_NOTE (OPENGL,
g_print ("Created WGL context[%p], pixel_format=%d\n",
hglrc,
pixel_format));
context_wgl->wgl_context = hglrc;
return GDK_GL_API_GL;
}
@@ -836,6 +1183,7 @@ gdk_win32_gl_context_wgl_class_init (GdkWin32GLContextWGLClass *klass)
context_class->make_current = gdk_win32_gl_context_wgl_make_current;
context_class->clear_current = gdk_win32_gl_context_wgl_clear_current;
context_class->is_current = gdk_win32_gl_context_wgl_is_current;
context_class->get_damage = gdk_win32_gl_context_wgl_get_damage;
draw_context_class->begin_frame = gdk_win32_gl_context_wgl_begin_frame;
draw_context_class->end_frame = gdk_win32_gl_context_wgl_end_frame;
+19 -1
View File
@@ -4483,8 +4483,13 @@ _gdk_win32_surface_compute_size (GdkSurface *surface)
if (!impl->drag_move_resize_context.native_move_resize_pending)
{
bool size_changed;
if (GDK_IS_TOPLEVEL (surface) && impl->force_recompute_size)
{
size_changed = width != surface->width ||
height != surface->height;
surface->width = width;
surface->height = height;
gdk_win32_surface_resize (surface, width, height);
@@ -4492,11 +4497,15 @@ _gdk_win32_surface_compute_size (GdkSurface *surface)
}
else
{
size_changed = width != impl->next_layout.configured_width ||
height != impl->next_layout.configured_height;
surface->width = impl->next_layout.configured_width;
surface->height = impl->next_layout.configured_height;
}
_gdk_surface_update_size (surface);
if (size_changed)
_gdk_surface_update_size (surface);
}
return FALSE;
@@ -5080,6 +5089,15 @@ gdk_win32_surface_apply_queued_move_resize (GdkSurface *surface,
GDK_NOTE (EVENTS, g_print (" ... set window position\n"));
/*
* Workaround situations in the current Win32 surface resize code that may have notified GDK
* too late for resizes, which manifests on nVidia drivers (and AMD drivers in mailbox
* presentation mode) running under Vulkan when one interactively enlarges the surface (HWND).
*
* See MR !7562 for more details
*/
_gdk_surface_update_size (surface);
return;
}
+1
View File
@@ -797,6 +797,7 @@ gdk_x11_clipboard_read_async (GdkClipboard *clipboard,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("No compatible transfer format found"));
g_object_unref (task);
return;
}
+7 -4
View File
@@ -1472,7 +1472,7 @@ gdk_x11_display_open (const char *display_name)
}
#endif
/* initialize the display's screens */
/* initialize the display's screens */
display_x11->screen = _gdk_x11_screen_new (display, DefaultScreen (display_x11->xdisplay));
/* If GL is available we want to pick better default/rgba visuals,
@@ -1484,8 +1484,11 @@ gdk_x11_display_open (const char *display_name)
*/
if (!gdk_display_prepare_gl (display, NULL))
{
gdk_x11_display_query_default_visual (display_x11, &display_x11->window_visual, &display_x11->window_depth);
gdk_x11_display_init_leader_surface (display_x11);
if (!display_x11->leader_gdk_surface)
{
gdk_x11_display_query_default_visual (display_x11, &display_x11->window_visual, &display_x11->window_depth);
gdk_x11_display_init_leader_surface (display_x11);
}
}
#ifdef HAVE_XFIXES
@@ -3021,7 +3024,7 @@ gdk_x11_display_init_gl (GdkDisplay *display,
GdkX11Display *self = GDK_X11_DISPLAY (display);
if (!gdk_x11_display_init_gl_backend (self, &self->window_visual, &self->window_depth, error))
return FALSE;
return NULL;
gdk_x11_display_init_leader_surface (self);
+1
View File
@@ -233,6 +233,7 @@ gdk_x11_drop_read_async (GdkDrop *drop,
{
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
_("No compatible transfer format found"));
g_object_unref (task);
return;
}
+7 -17
View File
@@ -84,10 +84,13 @@ gdk_x11_surface_get_glx_drawable (GdkSurface *surface)
void
gdk_x11_surface_destroy_glx_drawable (GdkX11Surface *self)
{
GdkGLContext *context;
if (self->glx_drawable == None)
return;
gdk_gl_context_clear_current_if_surface (GDK_SURFACE (self));
context = gdk_gl_context_clear_current_if_surface (GDK_SURFACE (self));
g_clear_object (&context);
glXDestroyWindow (gdk_x11_display_get_xdisplay (gdk_surface_get_display (GDK_SURFACE (self))),
self->glx_drawable);
@@ -120,20 +123,6 @@ maybe_wait_for_vblank (GdkDisplay *display,
}
}
static GLXDrawable
gdk_x11_gl_context_glx_get_drawable (GdkX11GLContextGLX *self)
{
GdkDrawContext *draw_context = GDK_DRAW_CONTEXT (self);
GdkSurface *surface;
if (gdk_draw_context_is_in_frame (draw_context))
surface = gdk_draw_context_get_surface (draw_context);
else
surface = GDK_X11_DISPLAY (gdk_draw_context_get_display (draw_context))->leader_gdk_surface;
return gdk_x11_surface_get_glx_drawable (surface);
}
static void
gdk_x11_gl_context_glx_end_frame (GdkDrawContext *draw_context,
cairo_region_t *painted)
@@ -318,10 +307,11 @@ gdk_x11_gl_context_glx_get_damage (GdkGLContext *context)
if (display_x11->has_glx_buffer_age)
{
GdkX11GLContextGLX *self = GDK_X11_GL_CONTEXT_GLX (context);
GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context));
gdk_gl_context_make_current (context);
glXQueryDrawable (dpy, gdk_x11_gl_context_glx_get_drawable (self),
glXQueryDrawable (dpy,
gdk_x11_surface_get_glx_drawable (surface),
GLX_BACK_BUFFER_AGE_EXT, &buffer_age);
if (buffer_age > 0 && buffer_age <= GDK_GL_MAX_TRACKED_BUFFERS)
+2 -2
View File
@@ -934,7 +934,7 @@ gsk_broadway_renderer_render (GskRenderer *renderer,
self->node_lookup = g_hash_table_new (g_direct_hash, g_direct_equal);
gdk_draw_context_begin_frame (GDK_DRAW_CONTEXT (self->draw_context), update_area);
gdk_draw_context_begin_frame_full (GDK_DRAW_CONTEXT (self->draw_context), GDK_MEMORY_U8, update_area, NULL);
/* These are owned by the draw context between begin and end, but
cache them here for easier access during the render */
@@ -946,7 +946,7 @@ gsk_broadway_renderer_render (GskRenderer *renderer,
self->nodes = NULL;
self->node_textures = NULL;
gdk_draw_context_end_frame (GDK_DRAW_CONTEXT (self->draw_context));
gdk_draw_context_end_frame_full (GDK_DRAW_CONTEXT (self->draw_context));
if (self->last_node_lookup)
g_hash_table_unref (self->last_node_lookup);
+4 -4
View File
@@ -133,7 +133,7 @@ void half_to_float4 (const guint16 h[4], float f[4]) __attribute__((ifunc ("reso
void float_to_half (const float *f, guint16 *h, int n) __attribute__((ifunc ("resolve_float_to_half")));
void half_to_float (const guint16 *h, float *f, int n) __attribute__((ifunc ("resolve_half_to_float")));
static void * __attribute__ ((no_sanitize_address))
static void * __attribute__ ((no_sanitize_address)) G_GNUC_UNUSED
resolve_float_to_half4 (void)
{
__builtin_cpu_init ();
@@ -143,7 +143,7 @@ resolve_float_to_half4 (void)
return float_to_half4_c;
}
static void * __attribute__ ((no_sanitize_address))
static void * __attribute__ ((no_sanitize_address)) G_GNUC_UNUSED
resolve_half_to_float4 (void)
{
__builtin_cpu_init ();
@@ -153,7 +153,7 @@ resolve_half_to_float4 (void)
return half_to_float4_c;
}
static void * __attribute__ ((no_sanitize_address))
static void * __attribute__ ((no_sanitize_address)) G_GNUC_UNUSED
resolve_float_to_half (void)
{
__builtin_cpu_init ();
@@ -163,7 +163,7 @@ resolve_float_to_half (void)
return float_to_half_c;
}
static void * __attribute__ ((no_sanitize_address))
static void * __attribute__ ((no_sanitize_address)) G_GNUC_UNUSED
resolve_half_to_float (void)
{
__builtin_cpu_init ();
+6 -3
View File
@@ -217,6 +217,9 @@ gsk_gl_driver_dispose (GObject *object)
g_assert (GSK_IS_GL_DRIVER (self));
g_assert (self->in_frame == FALSE);
if (self->shared_command_queue)
gsk_gl_command_queue_make_current (self->shared_command_queue);
#define GSK_GL_NO_UNIFORMS
#define GSK_GL_SHADER_RESOURCE(name)
#define GSK_GL_SHADER_STRING(str)
@@ -1839,14 +1842,14 @@ gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
state = g_new0 (GskGLTextureState, 1);
state->texture_id = texture_id;
state->context = g_object_ref (self->command_queue->context);
if (gdk_gl_context_has_feature (self->command_queue->context, GDK_GL_FEATURE_SYNC))
state->context = g_object_ref (self->shared_command_queue->context);
if (gdk_gl_context_has_feature (self->shared_command_queue->context, GDK_GL_FEATURE_SYNC))
state->sync = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
g_hash_table_steal (self->textures, GUINT_TO_POINTER (texture_id));
builder = gdk_gl_texture_builder_new ();
gdk_gl_texture_builder_set_context (builder, self->command_queue->context);
gdk_gl_texture_builder_set_context (builder, self->shared_command_queue->context);
gdk_gl_texture_builder_set_id (builder, texture_id);
gdk_gl_texture_builder_set_format (builder, format);
gdk_gl_texture_builder_set_width (builder, texture->width);
+17 -69
View File
@@ -192,12 +192,12 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
g_assert (self->context == NULL);
g_assert (self->command_queue == NULL);
if (surface == NULL)
context = gdk_display_create_gl_context (display, error);
else
context = gdk_surface_create_gl_context (surface, error);
if (!gdk_display_prepare_gl (display, error))
goto failure;
if (!context || !gdk_gl_context_realize (context, error))
context = gdk_gl_context_new (display, surface, surface != NULL);
if (!gdk_gl_context_realize (context, error))
goto failure;
api = gdk_gl_context_get_api (context);
@@ -258,6 +258,8 @@ gsk_gl_renderer_unrealize (GskRenderer *renderer)
g_clear_object (&self->driver);
g_clear_object (&self->command_queue);
g_clear_object (&self->context);
gdk_gl_context_clear_current ();
}
static cairo_region_t *
@@ -293,65 +295,6 @@ get_render_region (GdkSurface *surface,
return cairo_region_create_rectangle (&extents);
}
static gboolean
update_area_requires_clear (GdkSurface *surface,
const cairo_region_t *update_area)
{
cairo_rectangle_int_t rect;
guint n_rects;
g_assert (GDK_IS_SURFACE (surface));
/* No opaque region, assume we have to clear */
if (surface->opaque_region == NULL)
return TRUE;
/* If the update_area is the whole surface, then clear it
* because many drivers optimize for this by avoiding extra
* work to reload any contents.
*/
if (update_area == NULL)
return TRUE;
if (cairo_region_num_rectangles (update_area) == 1)
{
cairo_region_get_rectangle (update_area, 0, &rect);
if (rect.x == 0 &&
rect.y == 0 &&
rect.width == surface->width &&
rect.height == surface->height)
return TRUE;
}
/* If the entire surface is opaque, then we can skip clearing
* (with the exception of full surface clearing above).
*/
if (cairo_region_num_rectangles (surface->opaque_region) == 1)
{
cairo_region_get_rectangle (surface->opaque_region, 0, &rect);
if (rect.x == 0 &&
rect.y == 0 &&
rect.width == surface->width &&
rect.height == surface->height)
return FALSE;
}
/* If any update_area rectangle overlaps our transparent
* regions, then we need to clear the area.
*/
n_rects = cairo_region_num_rectangles (update_area);
for (guint i = 0; i < n_rects; i++)
{
cairo_region_get_rectangle (update_area, i, &rect);
if (cairo_region_contains_rectangle (surface->opaque_region, &rect) != CAIRO_REGION_OVERLAP_IN)
return TRUE;
}
return FALSE;
}
static void
gsk_gl_renderer_render (GskRenderer *renderer,
GskRenderNode *root,
@@ -362,7 +305,8 @@ gsk_gl_renderer_render (GskRenderer *renderer,
graphene_rect_t viewport;
GskGLRenderJob *job;
GdkSurface *surface;
gboolean clear_framebuffer;
graphene_rect_t opaque_tmp;
const graphene_rect_t *opaque;
float scale;
g_assert (GSK_IS_GL_RENDERER (renderer));
@@ -382,23 +326,27 @@ gsk_gl_renderer_render (GskRenderer *renderer,
viewport.size.width = gdk_surface_get_width (surface) * scale;
viewport.size.height = gdk_surface_get_height (surface) * scale;
if (gsk_render_node_get_opaque_rect (root, &opaque_tmp))
opaque = &opaque_tmp;
else
opaque = NULL;
gdk_draw_context_begin_frame_full (GDK_DRAW_CONTEXT (self->context),
gsk_render_node_get_preferred_depth (root),
update_area);
update_area,
opaque);
gdk_gl_context_make_current (self->context);
/* Must be called *AFTER* gdk_draw_context_begin_frame() */
render_region = get_render_region (surface, self->context);
clear_framebuffer = update_area_requires_clear (surface, render_region);
gsk_gl_driver_begin_frame (self->driver, self->command_queue);
job = gsk_gl_render_job_new (self->driver, &viewport, scale, render_region, 0, clear_framebuffer);
job = gsk_gl_render_job_new (self->driver, &viewport, scale, render_region, 0, TRUE);
gsk_gl_render_job_render (job, root);
gsk_gl_driver_end_frame (self->driver);
gsk_gl_render_job_free (job);
gdk_draw_context_end_frame (GDK_DRAW_CONTEXT (self->context));
gdk_draw_context_end_frame_full (GDK_DRAW_CONTEXT (self->context));
gsk_gl_driver_after_frame (self->driver);
+22 -8
View File
@@ -2182,6 +2182,10 @@ gsk_gl_render_job_visit_unblurred_inset_shadow_node (GskGLRenderJob *job,
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow)))
{
const GdkRGBA rgba;
gdk_color_to_float (gsk_inset_shadow_node_get_color2 (node), GDK_COLOR_STATE_SRGB, (float *) &rgba);
gsk_gl_program_set_uniform_rounded_rect (job->current_program,
UNIFORM_INSET_SHADOW_OUTLINE_RECT, 0,
&transformed_outline);
@@ -2192,7 +2196,7 @@ gsk_gl_render_job_visit_unblurred_inset_shadow_node (GskGLRenderJob *job,
UNIFORM_INSET_SHADOW_OFFSET, 0,
gsk_inset_shadow_node_get_dx (node),
gsk_inset_shadow_node_get_dy (node));
rgba_to_half (gsk_inset_shadow_node_get_color (node), color);
rgba_to_half (&rgba, color);
gsk_gl_render_job_draw_rect_with_color (job, &node->bounds, color);
gsk_gl_render_job_end_draw (job);
}
@@ -2285,6 +2289,10 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
/* Actual inset shadow outline drawing */
if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, inset_shadow)))
{
const GdkRGBA rgba;
gdk_color_to_float (gsk_inset_shadow_node_get_color2 (node), GDK_COLOR_STATE_SRGB, (float *) &rgba);
gsk_gl_program_set_uniform_rounded_rect (job->current_program,
UNIFORM_INSET_SHADOW_OUTLINE_RECT, 0,
&transformed_outline);
@@ -2295,7 +2303,7 @@ gsk_gl_render_job_visit_blurred_inset_shadow_node (GskGLRenderJob *job,
UNIFORM_INSET_SHADOW_OFFSET, 0,
offset_x * scale_x,
offset_y * scale_y);
rgba_to_half (gsk_inset_shadow_node_get_color (node), color);
rgba_to_half (&rgba, color);
gsk_gl_render_job_draw_with_color (job,
0, 0, texture_width, texture_height,
color);
@@ -2378,6 +2386,7 @@ gsk_gl_render_job_visit_unblurred_outset_shadow_node (GskGLRenderJob *job,
float spread = gsk_outset_shadow_node_get_spread (node);
float dx = gsk_outset_shadow_node_get_dx (node);
float dy = gsk_outset_shadow_node_get_dy (node);
GdkRGBA rgba;
guint16 color[4];
const float edge_sizes[] = { // Top, right, bottom, left
spread - dy, spread + dx, spread + dy, spread - dx
@@ -2389,7 +2398,8 @@ gsk_gl_render_job_visit_unblurred_outset_shadow_node (GskGLRenderJob *job,
{ outline->corner[3].width + spread - dx, outline->corner[3].height + spread + dy },
};
rgba_to_half (gsk_outset_shadow_node_get_color (node), color);
gdk_color_to_float (gsk_outset_shadow_node_get_color2 (node), GDK_COLOR_STATE_SRGB, (float *) &rgba);
rgba_to_half (&rgba, color);
gsk_gl_render_job_translate_rounded_rect (job, outline, &transformed_outline);
@@ -2473,11 +2483,13 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
int blurred_texture_id;
int cached_tid;
gboolean do_slicing;
GdkRGBA rgba;
guint16 color[4];
float half_width = outline->bounds.size.width / 2;
float half_height = outline->bounds.size.height / 2;
rgba_to_half (gsk_outset_shadow_node_get_color (node), color);
gdk_color_to_float (gsk_outset_shadow_node_get_color2 (node), GDK_COLOR_STATE_SRGB, (float *) &rgba);
rgba_to_half (&rgba, color);
/* scaled_outline is the minimal outline we need to draw the given drop shadow,
* enlarged by the spread and offset by the blur radius. */
@@ -4209,10 +4221,12 @@ gsk_gl_render_job_visit_node (GskGLRenderJob *job,
break;
case GSK_TEXT_NODE:
gsk_gl_render_job_visit_text_node (job,
node,
gsk_text_node_get_color (node),
FALSE);
{
GdkRGBA rgba;
gdk_color_to_float (gsk_text_node_get_color2 (node), GDK_COLOR_STATE_SRGB, (float *) &rgba);
gsk_gl_render_job_visit_text_node (job, node, &rgba, FALSE);
}
break;
case GSK_TEXTURE_NODE:
+3 -3
View File
@@ -75,10 +75,10 @@ void main() {
if (offset < next_offset) {
float f = (offset - curr_offset) / (next_offset - curr_offset);
vec4 curr_color = get_color(i);
vec4 next_color = get_color(i + 1);
vec4 curr_color = gsk_scaled_premultiply (get_color(i), u_alpha);
vec4 next_color = gsk_scaled_premultiply (get_color(i + 1), u_alpha);
vec4 color = mix(curr_color, next_color, f);
gskSetScaledOutputColor(gsk_premultiply(color), u_alpha);
gskSetOutputColor(color);
return;
}
}
+3 -3
View File
@@ -97,10 +97,10 @@ void main() {
if (offset < next_offset) {
float f = (offset - curr_offset) / (next_offset - curr_offset);
vec4 curr_color = get_color(i);
vec4 next_color = get_color(i + 1);
vec4 curr_color = gsk_scaled_premultiply (get_color(i), u_alpha);
vec4 next_color = gsk_scaled_premultiply (get_color(i + 1), u_alpha);
vec4 color = mix(curr_color, next_color, f);
gskSetScaledOutputColor(gsk_premultiply (color), u_alpha);
gskSetOutputColor(color);
return;
}
}

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