Commit Graph

27 Commits

Author SHA1 Message Date
Christian Hergert
56e2a7e8bb macos: restore unfullscreen frame with style mask
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.
2022-02-24 22:32:43 -08:00
Christian Hergert
8b71cff71d macos: use CALayer and IOSurface for rendering
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.
2022-02-22 12:01:29 -08:00
Matthias Clasen
e9ffe8f212 Merge branch 'wip/chergert/macos-fix-fullscreen' into 'main'
macos: allow windows to enter fullscreen

See merge request GNOME/gtk!4494
2022-02-22 19:36:20 +00:00
Matthias Clasen
d35bac452b Merge branch 'wip/chergert/macos-fix-toplevel-resize' into 'main'
macos: fix configure, move-resize, and compute-size

See merge request GNOME/gtk!4486
2022-02-22 13:10:34 +00:00
Christian Hergert
4c08d1643f macos: fix configure, move-resize, and compute-size
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.
2022-02-18 02:50:46 -08:00
Christian Hergert
592436503c macos: allow windows to enter fullscreen
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.
2022-02-18 01:54:10 -08:00
Christian Hergert
853ef43dae macos: fix keyboard input on popovers
GdkPopup can also become the "key" window (just not the "main" window).
2022-02-16 17:53:59 -08:00
Christian Hergert
8112b49c36 macos: fix unmaximize opacity around edges of window 2022-02-03 19:26:16 -08:00
Benjamin Otte
4e836493cc macos: Don't include gdkinternals.h 2021-09-24 22:50:29 +02:00
Christian Hergert
3fd931d392 macos: implement GdkDrop for macOS
This gets the basic mechanics of the drop portion of DnD working on the
macOS backend. You can drag, for example, from TextEdit into GNOME
Text Editor when using the macOS backend.

Other content formats are supported, and match what is currently
supported by the clipboard backend as the implementation to read
from the pasteboard is shared.

Currently, we look up the GdkDrag for the new GdkDrop. However,
nothing is stashing the drag away for further lookup. More work is
needed on GdkMacosDrag for that to be doable.
2021-06-17 17:26:42 -07:00
Christian Hergert
057bda6cd7 macos: register known clipboard types for drag destination 2021-06-17 13:23:18 -07:00
Christian Hergert
f4f104c9f9 macos: fix typedef on older macOS
On older systems, we don't have a typedef for gravity. They are a NSString
pointer and we can provide that manually just fine.
2021-01-05 13:53:22 -08:00
Christian Hergert
28a6f0df05 macos: handle point conversion on older macOS
On older systems, the availability of some methods seem to be incorrect
based on Apple documentation. This works around the issue by using
the rect conversion on older systems.
2021-01-05 13:52:11 -08:00
Christian Hergert
0236fe80c1 macos: fix macOS build breakage
Fixes breakages due to recent refactoring around sizing changes.
2020-12-08 11:29:31 -08:00
Jonas Ådahl
42679f2903 gdk: Replace all GDK_CONFIGURE usage with GdkSurface::layout
This removes the GDK_CONFIGURE event and all related functions and data
types; it includes untested changes to the MacOSX, Win32 and Broadway
backends.
2020-12-07 20:37:29 +01:00
Christian Hergert
b38d0d7d9e macos: resign main/key when hiding window
This isn't done automatically for us, so we need to synthesize it in
our hide helper.

With this commit, we properly re-focus the new main/key window after
we have closed a transient-for window.
2020-12-02 11:36:38 -08:00
Matthias Clasen
5a77994516 Merge branch 'matthiasc/for-master' into 'master'
Matthiasc/for master

See merge request GNOME/gtk!2760
2020-10-29 18:55:53 +00:00
Matthias Clasen
574a3a456d gdk: Drop GdkPoint from the api
This typedef was not used in any public APIs, and is
only used in the MacOS backend. It is not worth preserving
as public API, move it to the only user.
2020-10-29 14:23:46 -04:00
Christian Hergert
eb809ba425 macos: tweak gravity while resizing
This helps a situation where the window contents has not changed
in time for a drawing. Setting the texture gravity helps that side or
corner to be less jittery while moving.

Ideally, we can get to a point where we are synchronized and keeping
up with drawing fast enough to not need this. That may require some
work to drive frame clocks from drawRect: though.
2020-10-29 10:57:02 -07:00
Christian Hergert
d700cfa2ef macos: break grabs after sending release event 2020-10-14 15:45:50 -07:00
Christian Hergert
58f9413464 macos: track various changes in GDK 2020-10-09 20:02:18 -07:00
Matthias Clasen
929a56e53c Clean up lots of GTK+ -> GTK
Replace most remaining uses of GTK+ in the docs and
user-visible strings by GTK. Also remove some leftover
"Was added in 3.x" sentences from the docs.
2020-09-12 12:01:04 -04:00
Matthias Clasen
93078e52c0 gdk: Rename GdkSurfaceState to GdkToplevelState
That is what it is.

Fixes: #2790
2020-09-10 00:39:03 -04:00
Björn Daase
6315cd977c *: Fix spelling mistakes found by codespell 2020-08-21 15:29:34 +02:00
Jonas Ådahl
c7c71137b2 gdk/monitor: Remove gdk_monitor_work_area and GdkMonitor::work-area
It's not a portable API, so remove it. The corresponding backend
specific functions are still available, if they were implemented, e.g.
gdk_macos_monitor_get_workarea() and gdk_x11_monitor_get_workarea().
2020-07-29 17:57:30 +02:00
Benjamin Otte
d7266b25ba Replace "gint" with "int" 2020-07-25 00:47:36 +02:00
Christian Hergert
9dbf99d91a macos: prototype new GDK backend for macOS
This is fairly substantial rewrite of the GDK backend for quartz and
renamed to macOS to allow for a greenfield implementation.

Many things have come across from the quartz implementation fairly
intact such as the eventloop integration design and discovery of
event windows from the NSEvent.

However much has been changed to fit in with the new GDK design and
how removal of child GdkWindow have been completely eliminated.
Furthermore, the new GdkPopup allows for regular NSWindow to be used
to provide popovers unlike the previous implementation.

The object design more closely follows the ideal for a GDK backend.

Views have been broken out into subclasses so that we can support
multiple GSK renderer paths such as GL and Cairo (and Metal in the
future). However mixed mode GL and Cairo will not be supported. Currently
only the Cairo renderer has been implemented.

A new frame clock implementation using CVDisplayLink provides more
accurate information about when to draw drawing the next frame. Some
testing will need to be done here to understand the power implications
of this.

This implementation has also gained edge snapping for CSD windows. Some
work was also done to ensure that CSD windows have opaque regions
registered with the display server.

     ** This is still very much a work-in-progress **

Some outstanding work that needs to be done:

 - Finish a GL context for macOS and alternate NSView for GL rendering
   (possibly using speciailized CALayer for OpenGL).
 - Input rework to ensure that we don't loose remapping of keys that was
   dropped from GDK during GTK 4 development.
 - Make sure input methods continue to work.
 - Drag-n-Drop is still very much a work in progress
 - High resolution input scrolling needs various work in GDK to land
   first before we can plumb that to NSEvent.
 - gtk/ has a number of things based on GDK_WINDOWING_QUARTZ that need
   to be updated to use the macOS backend.

But this is good enough to start playing with and breaking things which
is what I'd like to see.
2020-07-21 14:45:12 -07:00