This serial should be that from a button press/touch down/etc, use
the last implicit grab here, which will presumably be from the same
device that triggered the event.
Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5048
The XDND suggested action is a relic from when the source would control
the action for a drop. With the new GtkDropTarget the target decides
the action (not the source). That means the all of the returned
results from the ::enter and ::motion handlers will be unexpectely
ignored. Prefer to use the preferred action over the x11 suggested action.
Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4259
gdk_x11_drop_update_actions() sets actions to
drop_x11->suggested_action when !drop_x11->xdnd_have_actions
and then sets it again to drop_x11->suggested_action if it is.
If xdnd_have_actions is true use xdnd_actions.
Don't return to the main loop, instead force a run of the paint idle.
The paint idle will know to skip all the phases that aren't requested.
This is critically important becuase gdksurface.c assumes the
FLUSH_EVENTS and RESUME_EVENTS phases are matched, and we cannot
guarantee that if we return to the main loop and let various reentrant
code change the frame clock state.
This would lead to bugs with events being paused and never unpaused
again or even crashes.
Fixes#4941
If we take the early return we don't unscale this at the bottom of the
function, causing wrong coordinates in HiDPI screens.
This bug also affects GTK3 (I noticed this running Firefox tests on X).
The GdkToplevelSize struct already has the concept of "bounds", which
means the largest size a window should reasonably have. It's practically
the equivalent of the monitor the window is intended to be mapped on,
with the "struts" (e.g. panels) cut out. It's used by GTK to use this
information to calculate a default window size that is "lagom" (swedish;
not too large, not too small).
Simplify the API to just return the requirements that the user
has asked for. The rest of the code was undocumented and previously
used as a buggy source for a default value from internal code.
Since the buggy code is now fixed, remove all unnecessary cruft.
There are two reasons for this:
* First, the refactored realize code now makes sure that no
context with unsupported version is ever created.
* Second, this code could bump into false possitives and negatives, since
the user is not requested, nor expected to set_required_version
in any specific order relative to set_allowed_apis. Therefore,
some version could be rejected or accepted based on a set of
allowed apis that the user has not yet correctly configured.
Mimic the behavior of the egl context creation by stablishing
some sane logic for the api and version used. Split the decision
of the type of context (api, legacy) and the creation of a context
of a certain version and all its properties.
By setting and then getting the required version in a context, the code
was not respecting user requirements. Instead, simply get the requested
version by the user clipped by the requirements (display version)
It is useful for backends to get user set preferences while
ensuring the correctness of the result, which will be always
greater or equal than the minimum version provided
Add "stylus" to the list of substrings in a device name that cause it to be recognized
as a GDK_SOURCE_PEN device (previously "wacom", "pen" and "eraser"). Some devices
just use "stylus" in their name, and are otherwise recognized as
GDK_SOURCE_TOUCHSCREEN instead.
Fixes#4394.
When loading cursors at scale, we expect the
cursor images to have a size of scale * size.
If we don't find such images, load them at their
unscaled size and scale them up ourselves.
Without this, cursors will appear in unexpected
sizes depending on scales and themes.
Related: #4746
On Wayland it is a protocol violation to upload buffers with
dimensions that are not an integer multiple of the buffer scale.
Until recently, Mutter did not enforce this. When it started
doing so, some users started seeing crashes in GTK apps because the
cursor theme ended up with e.g. a 15x16 pixel image at scale of 2.
Add a small sanity check for this case.
Not updating shadow size unconditionally would lead to shadow size not
being set on map, which would lead mutter to think that we are a Window
without extents and then become confused when we suddenly set some.
Make sure that doesn't happen by always having shadows set on map, just
like GTK3.
Fixes#4136
There were several mistakes here.
The width of subtextures was set to the width of
the main texture, the data size wasn't properly
calculated, and the preconditions were inverted.
Yay us!
Those property features don't seem to be in use anywhere.
They are redundant since the docs cover the same information
and more. They also created unnecessary translation work.
Closes#4904
Previously, there was an issue with glitching after showing/hiding a
popover that was not also destroyed. This was due to the popover having
an update_freeze_count of zero after hiding the surface.
That resulted in it's toplevel continuously dropping frames such as during
high-frame-rate scrolling in textviews. This problem is much more visible
on high-frame-rate displays such as 120hz/144hz.
With this commit, we freeze the frame clock of the popup until it is
mapped again.
Since GdkTimeCoord stores only axis values, prior to this change,
if a device didn't report GDK_AXIS_X or GDK_AXIS_Y, the history
attached to merged motion events wouldn't contain any positional
information.
Commit 6012276093 already addressed
this issue for devices without tools by storing the event position
in GdkTimeCoord using GDK_AXIS_X and GDK_AXIS_Y and augmenting the
GdkTimeCoord's axis bitmask accordingly.
This change generalizes that workaround to all devices. Note that
if a device DOES report values for GDK_AXIS_X and GDK_AXIS_Y, those
values won't be overwritten.
Closes#4809
When a window is minimized by user action, the `showAndMakeKey` method is not executed when idle. This prevents the window from being un-minimized immediately.
And allow programmatic minimization of a window by un-minimizing them in `_gdk_macos_toplevel_surface_present`
Closes#4811
When given an invalid atom, gdk_x11_get_xatom_name_for_display can
return NULL and trigger a seg in gdk_x11_clipboard_formats_from_atoms.
Check for NULL.
Why I'm seeing a bad atom there is probably a separate question.
https://bugzilla.redhat.com/show_bug.cgi?id=2037786
The call to gdk_win32_clipboard_request_contentformats() can return NULL even
without an error condition being hit (such as when the system clipboard is
empty), so check whether the returned GdkContentFormat pointer is not NULL
before calling gdk_clipboard_claim_remote(), which expects it to be not NULL,
otherwise we face a warning from that funtion and the subsequent
g_object_unref().
This at least partially fixes issue #4796.
WebKit's GTK 4 port can give us textures with an internal format of
GL_RGBA with GL_UNSIGNED_NORMALIZED and a bit-depth of 8. This fixes
warnings for every GdkGLTexture created/delivered to the GskGLRenderer.
The format is essentially the same as GL_RGBA8 since it is normalized
between 0.0..1.0 for 8-bit components.
Fixes#4783
When surface depth switches from non-high-depth to high-depth (or vice
versa) the current surface has to be destroyed before a new one can be
created for this window. eglDestroySurface however was getting passed a
GdkDisplay, rather than the EGLDisplay it expects. As a result the old
surface did not get destroyed and the new surface could not be created
causing rendering to freeze.
Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4773
Add a new GdkScrollUnit enum that represent the
unit of scroll deltas provided by GdkScrollEvent.
The unit is accessible through
gdk_scroll_event_get_unit().
We had code to do it and it never actually got used correctly. This ensures
that the popup services are attached to the parents so that they get proper
stacking orders when displayed. Additionally, it fixes popups from being
shown as their own windows in Exposé.
If we are clicking through the shadow of a window, we need to take special
care to not raise the old window on mouseUp. This is normally done by the
display server for us, so we need to use the proper API that is public to
handle this (rather than CGSSetWindowTags()). Doing so requires us to
dispatch the event to the NSView and then cancel the activcation from
the mouseDown: event there.
If we closed a key window in response to events, we need to denote another
window as the new key window. This is easiest to do from an idle so that
we don't clobber notification pairs of "did resign"/"did become" key
window.
We have a sorted set of surfaces by display server stacking, so we can
take the first one we come across that is already mapped and re-show it
to become key/main.
If we have server-side decorations we might need to request a layout in
response to the resize notification. We don't need to do this in other
cases because we already handle that in the process of doing the resize
(and that code is that way because of delayed delivery of NSNotification).
If we are using NSWindow titled windows, we don't end up waking up the
frame clock when the window is resized on the display server. This ensures
that we do that after getting a notification of resize.
There are cases we might want to consume a NSEvent without creating a
GdkEvent or passing it along to the NSApplication for processing. This
creates a new value we can use and check against to propagate that without
having to do out parameters at the slightly odd invalid pointer value for
a GdkEvent (similar to how MMAP_FAILED is done).
This can get in the way of how we track changes while events are actively
processing. Instead, we may want to delay this until the next main loop
idle and then check to see if we have a main window as the NSNotification
may have come in right after this.
This one can be used for both premultiplied and non-premultiplied alpha
formats, since alpha is always 255. It is useful for opaque PNG upload
on both cairo and GL renderers.
That way, all permutations are possible. Previously it was only useful
in the cairo renderer, which required rgba8 → premultiplied bgra8, while
the GL renderer required rgba8 → premultiplied rgba8. Now both are
available.
This was only useful when building for AArch32 without -mfpu=neon, on
AArch64 or with -mfpu=neon gcc is smart enough to do the auto-
vectorisation, leading to code almost as good as what I wrote in
1fdf5b7cf8.
It appears that NVIDIA does not implement EGL_EXT_swap_buffers_with_damage
on their EGL implementation, but does implement the KHR variant of it.
This checks for a suitable implementation and stores a pointer to the
compatible implementation within the GdkGLContextPrivate struct.
We want to ensure that we recalculate the sort order of windows before
processing the motion. Generally this would be done in response from the
display server in GdkMacosWindow, but I've seen it possible to race there.
We need to handle the case where we might be racing against an incoming
configure event due to how notifications are queued from the display
server. Rather than calling configure (and possibly causing other things
to move around) this just queries the display server directly for the
coordinates that we care about.
Additionally, we can display:NO as we are in control of all the display
process now using CALayer.
We failed to handle the toplevel with transient-for case here which could
cause our X/Y calculations to be off in other areas such as best monitor
detection.
We do actually need the parent frame clock here because it is the way we
ensure that we get layout called for our popup surfaces at the same time
as the parent surface.
This doesn't appear to happen much, but if it does it is nice to setup
the window placement initially. Generally, transient-for is set after
the creation of the toplevel rather than here.
The GdkMacosBuffer object already has storage for tracking the damage
region as it is used in GdkMacosCairoContext to manually copy regions from
the front buffer to the back buffer. This makes the GdkMacosGLContext also
use that field so that we can easily drop old damage regions when the
buffer is lost. This happens during resizes, monitor changes, etc.
This helper is useful to ensure we are consistent with how we keep a
window clamped to the workarea of a monitor when placing windows on
screen. (This does not affect snap-to-edges).
Currently, we have all the plumbing in place so that GTK consumes the
startup notification ID when focusing a window through the xdg-activation
protocol.
This however misses the case that a window might be requested to be
focused with no startup ID (i.e. via interaction with the application,
not through GApplication or other application launching logic).
In this case, we let the application create a token that will be
consumed by itself. The serial used is that from the last
interaction, so the compositor will still be able to do focus prevention
logic if it applies.
Since we already do have a last serial at hand, prefer xdg-activation
all the way over the now stale gtk-shell focusing support. The timestamp
argument becomes unused, but that is a weak argument to prefer the
private protocol over the standard one. The gtk-shell protocol support
is so far left for interaction with older Mutter.
If _gdk_macos_surface_move_resize() was called with various -1 parameters
we really want to avoid changing anything even if we think we know what
the value might be. Otherwise, we risk messing up in-flight operations that
we have not yet been notified of yet.
This improves the chances we place windows in an appropriate location as
they don't et screwed up before window-manager placement.
We need to bring the application to the foreground in multiple ways, and
this call to [NSApp activateIgnoringOtherApps:YES] ensures that we become
foreground before the first window is opened. Otherwise we end up starting
applications in the background.
Fixes#4736
If we are double buffering surfaces with IOSurface then we need to copy
the area that was damaged in the previous frame to the back buffer. This
can be done with IOSurface but we need to hold the read-only lock so that
we don't cause the underlying IOSurface contents to be invalidated.
Additionally, since this is only used in the context of rendering to a
GdkMacosSurface, we know the life-time of the cairo_surface_t and can
simply lock/unlock the IOSurface buffer from begin_frame/end_frame to have
the buffer flushing semantics we want.
To ensure that we don't over damage, we store the damage in begin_frame
(and copy it) and then subtract it from the next frames damage to determine
the smallest amount we need to copy (taking scale factor into account).
We don't care to modify the damage region to swapBuffers because they
already have the right contents and could potentially fall into another
tile anyway and we'd like to avoid damaging that.
Fixes#4735
This can be used to lock a surface for reading to avoid causing the
surface contents to be invalidated. This is needed when reading back from
a front-buffer to the back-buffer as is needed when using Cairo surfaces
to implement something similar to BufferAge.
Previously, a single CVDisplayLink was used to drive updates for all
surfaces across all monitors. It used a 'best guess' rate which would
allow for updates across monitors of mixed rates. This is undesirable for
situations where you might have a 144hz monitor as it does not allow for
reaching up to that frame rate.
Instead, we want to use a per-monitor CVDisplayLink which will fire at the
rate of the monitor down to the level of updates we require. This commit
does just that.
When a surface crosses onto a new monitor, that monitor is used to drive
the GdkFrameClock.
Fixes#4732
Using the mode allows better detection of refresh rate and refresh
interval for the CVDisplayLink bridge to GdkFrameClock. Using it can help
ensure that our 144hz displays can actually reach that rather than falling
back to just 60hz.
This will also need future commits to rework the displaylink source to be
per-monitor.
When the fingers are placed on the touchpad, we get a scroll event with
the phase NSEventPhaseMayBegin. We can use this to synthesize an is_stop
event. This results in the scrolledwindow stopping scroll with stop
gestures.
This can cause another warning as well, however, which should be addressed
from #4730.
Fixes#4733
Windows can end up on different monitors despite having a parent or
transient-for ancestor. We want them to be driven by the CVDisplayLink
for the best-monitor, and so this needs to be unshared.
Currently we're using a display link that is for all active displays which
is just the display server trying to find some timings that try to overlap
as many as possible.
That was fine for a prototype, but we really need to do better for
situations with mixed frame rate (such as 60hz and 120hz promotion
displays). Additionally, the 144hz external monitor I have will never
reach 144hz using the current design.
This is just the first step in changing this, but the goal is to have
one of these attached to each GdkMacosMonitor which we can then use to
thaw surfaces specific to that monitor.
We will eventually be needing additional feedback from the display server
which would be nice to keep away from the rest of GdkMacosDisplay for
cleanliness sake. Particularly for feedback from mission control and other
environment factors that requires private API for proper integration.
Instead of performing keyboard layout substitution whenever we find a matching
entry in the registry, first try to load the original layout and only attempt
substitution when that fails.
See #4724
There may be various reasons that an application could need access to the
underlying NSWindow that is being used to display the GdkMacosSurface
contents. This provides a minimal API to do that without exposing our
implementation details through public API.
As our rendering system is likely to change over time, we very much want
to keep GdkMacosView, GdkMacosLayer, GdkMacosTile, and GdkMacosWindow all
private implementation details which are subject to change.
As this is public API, we are a bit long-winded with the name so it is
clear what is being accessed without polluting symbol names with things
like "ns" as we used to.
When using server-side-decorations, we need to avoid potential cycles with
compute-size as it may not have the new sizing information yet. We can
just short circuit during "live resize" to get that effect.
Fixes poor window resizing from top-left on titled windows.
This doesn't give us appropriate results if we use the window delegate.
Instead, we need to adjust the frame at the same time we change the
style mask so that we end up in the same location.
Previously we had issues on macos where the overshoot would keep showing.
To fix this we need to actually use discrete events instead of the
generated deltas from macOS in the scroll wheel case. Additionally, we need
to drop the kinetic momentum events from macOS and rely on the gtk kinetic
events which are already happening anyway. We also need to submit the
is_stop event for the GDK_SCROLL_SMOOTH case when we detect it.
To keep the discrete scroll events correct, we need to alter the hack in
gtkscrolledwindow.c to use the same path as other platforms except for
when a smooth scroll event is in place. In the future, I would imagine that
this falls into the boundary of high-precision scrolling and would share
the same code paths as other platforms.
With all of these in place, kinetic scrolling with overshoot appears the
same on macOS as other platforms.
When creating new windows, it is better if we create them with a slight
offset to where they were created before so that they are visible to the
user separately from what they might be overshadowing.
This broke with the previous fixes for initial window positioning. We need
the initial positioning so that tails will be displayed correctly when the
popover surface is displayed.
If the size changes, we need to relayout the tiles. Otherwise we can keep
using what we had before. Generally, that shouldn't happen, but the
previous check was failing in a number of ways.
It looks like, particularly on the M1, we might need to double buffer the
contents of the IOSurface<->OpenGL texture bindings. This doesn't appear
to show up on the Intel macbooks I've tried, but I've seen it in the wild
on an M1.
If we have a 2x scale laptop with a 1x scale external display, we would
need to create a new IOSurface for the external display once it crosses
a boundary, otherwise we won't have something capable of displaying
correctly on the second monitor.
This provides a major shift in how we draw both when accelerated OpenGL
as well as software rendering with Cairo. In short, it uses tiles of Core
Animation's CALayer to display contents from an OpenGL or Cairo rendering
so that the window can provide partial damage updates. Partial damage is
not generally available when using OpenGL as the whole buffer is flipped
even if you only submitted a small change using a scissor rect.
Thankfully, this speeds up Cairo rendering a bit too by using IOSurface to
upload contents to the display server. We use the tiling system we do for
OpenGL which reduces overall complexity and differences between them.
A New Buffer
============
GdkMacosBuffer is a wrapper around an IOSurfaceRef. The term buffer was
used because 1) surface is already used and 2) it loosely maps to a
front/back buffer semantic.
However, it appears that IOSurfaceRef contents are being retained in
some fashion (likely in the compositor result) so we can update the same
IOSurfaceRef without flipping as long as we're fast. This appears to be
what Chromium does as well, but Firefox uses two IOSurfaceRef and flips
between them. We would like to avoid two surfaces because it doubles the
GPU VRAM requirements of the application.
Changes to Windows
==================
Previously, the NSWindow would dynamically change between different
types of NSView based on the renderer being used. This is no longer
necessary as we just have a single NSView type, GdkMacosView, which
inherits from GdkMacosBaseView just to keep the tedius stuff separate
from the machinery of GdkMacosView. We can merge those someday if we
are okay with that.
Changes to Views
================
GdkMacosCairoView, GdkMacosCairoSubView, GdkMacosGLView have all been
removed and replaced with GdkMacosView. This new view has a single
CALayer (GdkMacosLayer) attached to it which itself has sublayers.
The contents of the CALayer is populated with an IOSurfaceRef which
we allocated with the GdkMacosSurface. The surface is replaced when
the NSWindow resizes.
Changes to Layers
=================
We now have a dedicated GdkMacosLayer which contains sublayers of
GdkMacosTile. The tile has a maximum size of 128x128 pixels in device
units.
The GdkMacosTile is partitioned by splitting both the transparent
region (window bounds minus opaque area) and then by splitting the
opaque area.
A tile has either translucent contents (and therefore is not opaque) or
has opaque contents (and therefore is opaque). An opaque tile never
contains transparent contents. As such, the opaque tiles contain a black
background so that Core Animation will consider the tile's bounds as
opaque. This can be verified with "Quartz Debug -> Show opaque regions".
Changes to Cairo
================
GTK 4 cannot currently use cairo-quartz because of how CSS borders are
rendered. It simply causes errors in the cairo_quartz_surface_t backend.
Since we are restricted to using cairo_image_surface_t (which happens to
be faster anyway) we can use the IOSurfaceBaseAddress() to obtain a
mapping of the IOSurfaceRef in user-space. It always uses BGRA 32-bit
with alpha channel even if we will discard the alpha channel as that is
necessary to hit the fast paths in other parts of the platform. Note
that while Cairo says CAIRO_FORMAT_ARGB32, it is really 32-bit BGRA on
little-endian as we expect.
OpenGL will render flipped (Quartz Native Co-ordinates) while Cairo
renders with 0,O in the top-left. We could use cairo_translate() and
cairo_scale() to reverse this, but it looks like some cairo things may
not look quite as right if we do so. To reduce the chances of one-off
bugs this continues to draw as Cairo would normally, but instead uses
an CGAffineTransform in the tiles and some CGRect translation when
swapping buffers to get the same effect.
Changes to OpenGL
=================
To simplify things, removal of all NSOpenGL* related components have
been removed and we strictly use the Core GL (CGL*) API. This probably
should have been done long ago anyay.
Most examples found in the browsers to use IOSurfaceRef with OpenGL are
using Legacy GL and there is still work underway to make this fit in
with the rest of how the GSK GL renderer works.
Since IOSurfaceRef bound to a texture/framebuffer will not have a
default framebuffer ID of 0, we needed to add a default framebuffer id
to the GdkGLContext. GskGLRenderer can use this to setup the command
queue in such a way that our IOSurface destination has been
glBindFramebuffer() as if it were the default drawable.
This stuff is pretty slight-of-hand, so where things are and what needs
flushing when and where has been a bit of an experiment to see what
actually works to get synchronization across subsystems.
Efficient Damages
=================
After we draw with Cairo, we unlock the IOSurfaceRef and the contents
are uploaded to the GPU. To make the contents visible to the app,
we must clear the tiles contents with `layer.contents=nil;` and then
re-apply the IOSurfaceRef. Since the buffer has likely not changed, we
only do this if the tile overlaps the damage region.
This gives the effect of having more tightly controlled damage regions
even though updating the layer would damage be the whole window (as it
is with OpenGL/Metal today with the exception of scissor-rect).
This too can be verified usign "Quartz Debug -> Flash screen udpates".
Frame Synchronized Resize
=========================
In GTK 4, we have the ability to perform sizing changes from compute-size
during the layout phase. Since the macOS backend already tracks window
resizes manually, we can avoid doing the setFrame: immediately and instead
do it within the frame clock's layout phase.
Doing so gives us vastly better resize experience as we're more likely to
get the size-change and updated-contents in the same frame on screen. It
makes things feel "connected" in a way they weren't before.
Some additional effort to tweak gravity during the process is also
necessary but we were already doing that in the GTK 4 backend.
Backporting
===========
The design here has made an attempt to make it possible to backport by
keeping GdkMacosBuffer, GdkMacosLayer, and GdkMacosTile fairly
independent. There may be an opportunity to integrate this into GTK 3's
quartz backend with a fair bit of work. Doing so could improve the
situation for applications which are damage-rich such as The GIMP.
There are situations where our "default framebuffer" is not actually
zero, yet we still want to apply a scissor rect.
Generally, 0 is the default framebuffer. But on platforms where we need
to bind a platform-specific feature to a GL_FRAMEBUFFER, we might have a
default that is not 0. For example, on macOS we bind an IOSurfaceRef to
a GL_TEXTURE_RECTANGLE which then is assigned as the backing store for a
framebuffer. This is different than using gsk_gl_renderer_render_texture()
in that we don't want to incur an extra copy to the destination surface
nor do we even have a way to pass a texture_id into render_texture().
Previously, the popover would cause the window to go into the :backdrop
state which is not what we want for consistency with other platforms. This
fixes that by walking up the surface chain when we get notified of
loosing or acquiring "key" input from the display server.
We might have panels with controls in them where the window is running in
another process. The control could have a wrapper window which we would
see from this process. This can happen with the GtkFileChooserNative, but
any NSSavePanel in macOS 10.15+ is out of process (not just sandboxed
applications).
This significantly cleans up how we handle various move-resize, compute-
size, and configure (notification of changes) in the macOS GDK backend.
Originally when prototyping this backend, there were some bits that came
over from the quartz backend and some bits which did not. It got confusing
and so this makes an attempt to knock down all that technical debt.
It is much simpler now in that the GdkMacosSurface makes requests of the
GdkMacosWindow, and the GdkMacosWindow notifies the GdkMacosSurface of
changes that happen.
User resizes are delayed until the next compute-size so that we are much
closer to the layout phase, reducing chances for in-between frames.
This also improves the situation of leaving maximized state so that a
grab and drag feels like you'd expect on other platforms.
I removed the opacity hack we had in before, because that is all coming
out anyway and it's a bit obnoxious to maintain through the async flows
here.
This fixes GTK's NSWindow for toplevels so that they are allowed to enter
fullscreen. We were already handlign the state transitions from the
setStyleMask: halper, but we didn't previously tell the window we are
allowed to transition into that.
There is a bit of a mismatch here in that GTK doesn't have any such flag
that determines if a window is "allowed" by policy to enter fullscreen
since window managers on Linux are free to do that at will.
This more than halves the total runtime of this function since the
previous commit, from 8.36% to 4.02%, and is most likely memory
bandwidth limited on this specific board now.
I tried to do a SSE2 version as well, but couldn’t find any equivalent
of the LD4/ST4 ARM instruction.
On x86 on a Kaby Lake CPU, this makes it go from 6.63% of the total
execution time (loading some PNGs using the cairo backend) down to
3.20%.
On ARM on a Cortex-A7, on the same workload, this makes it go from 57%
to 8.36%.
We want our tracking area to be limited to the input region so that we
don't pass along events outside of them for the window. This improves the
chances we click-out of a popover with a large shadow.
This still doesn't let us pass-through clicks for large shadows on top-
level windows though.
We only should be asserting in static functions. Furthermore, this function
did not need to have GDK_BEGIN_MACOS_ALLOC_POOL as nothing is being
allocated there which would cause pooling to get used.
This needs to handle the boundary case where the value is exactly equal
to the edge of a rectangle (which gdk_rectangle_contains_point() does not
consider to be containing). However, if there is a monitor in the list
that is a better match, we still want to prefer it.
When using an external mouse on MacOS, the scrolling behavior is
reversed from the user's scrolling preference. Additionally, it is
noticeably sluggish.
This commit fixes both issues by negating the deltas and multiplying
them by 32 before constructing a new scroll event. 32 seems to be the
"traditional" scaling factor according to [Druid], but I'm not sure
where that value actually comes from. Regardless, scaling the deltas by
this amount makes scrolling feel a lot more responsive in the GTK demos.
Scrolling with a trackpad is not affected by either issue because it
triggers a different code path that uses more precise deltas, and
already negates them.
[Druid]: https://linebender.gitbook.io/linebender-graphics-wiki/mouse-wheel#external-mouse-wheel-vs-trackpad
Some Windows keymaps have bogus mappings for the Ctrl modifier. !4423 attempted
to fix this by ignoring the Ctrl layer, but that was not enough. We also need to
ignore combinations of Ctrl with other modifiers, i.e. Ctrl + Shift. For example,
Ctrl + Shift + 6 is mapped to the character 0x1E on a US keyboard (but it should
be treated as Ctrl + ^). Basically, always ignore Ctrl unless it is used in
conjunction with Alt, i.e. as part of AltGr.
Related issue: #4667
`free` is defined in `stdlib.h`, see for example
<https://pubs.opengroup.org/onlinepubs/009604499/functions/free.html>. Without
this include compilation can fail with the following error:
```
../gdk/loaders/gdkjpeg.c: In function ‘gdk_save_jpeg’:
../gdk/loaders/gdkjpeg.c:264:7: warning: implicit declaration of function ‘free’ [-Wimplicit-function-declaration]
free (data);
^
../gdk/loaders/gdkjpeg.c:264:7: warning: incompatible implicit declaration of built-in function ‘free’
../gdk/loaders/gdkjpeg.c:264:7: note: include ‘<stdlib.h>’ or provide a declaration of ‘free’
../gdk/loaders/gdkjpeg.c:302:67: error: ‘free’ undeclared (first use in this function)
return g_bytes_new_with_free_func (data, size, (GDestroyNotify) free, NULL);
^
../gdk/loaders/gdkjpeg.c:302:67: note: each undeclared identifier is reported only once for each function it appears in
../gdk/loaders/gdkjpeg.c:303:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
```
We don't want to risk having something really weird come out if we have a
WCG colorspace, so instead only do the performance hack on systems where
the output is likely reasonable.
We will want to eventually just be drawing in the appropriate colorspace,
but that is not available yet.