Compare commits

..

424 Commits

Author SHA1 Message Date
Matthias Clasen
5cb7e60c73 Add tests for gdk_content_formats_parse
Add a test that checks we can roundtrip things through
gdk_content_formats_parse and gdk_content_formats_to_string.
2021-07-26 15:55:34 -04:00
Matthias Clasen
f9194042f4 Add tests for GdkContentFormats
This isn't super-extensive yet, but its a start.
2021-07-26 15:55:34 -04:00
Matthias Clasen
5c4aba4b9c Merge branch 'wip/compose-parser' into 'master'
Clean up the GtkComposeTable api

See merge request GNOME/gtk!3746
2021-07-26 11:51:14 +00:00
Matthias Clasen
39005461c5 4.3.2 2021-07-24 22:04:49 -04:00
Matthias Clasen
4dc4c00267 Merge branch 'misc-speedups' into 'master'
ngl: Speed up clipping calculations a bit

See merge request GNOME/gtk!3784
2021-07-25 02:03:46 +00:00
Matthias Clasen
d76460343a sizerequest: Simplify some code
Avoid some repeated MAX().
2021-07-24 18:49:41 -04:00
Matthias Clasen
0d8dd0c664 sizerequest: Keep branches in sync
There are some unintentional differences between
the path that uses a layout manager, and the path
that uses widget vfuncs. Sync them up.
2021-07-24 18:49:41 -04:00
Matthias Clasen
ee6491f717 widget: Avoid some unnecessary back-and-forth casting
Avoid some unnecessary casting and a redundant early exit.
2021-07-24 18:49:27 -04:00
Matthias Clasen
7044951dab widget: Avoid GObject data for action muxer
Most widget have an action muxer now, so just
store it in GtkWidgetPrivate.
2021-07-24 18:48:10 -04:00
Matthias Clasen
98986a25f9 layoutmanager: Avoid some overhead
Use inline getters for some things.
2021-07-24 18:48:10 -04:00
Matthias Clasen
ae3e586714 gridlayout: Avoid some unnecessary overhead
Use inline functions for some things.
2021-07-24 18:48:10 -04:00
Matthias Clasen
0ef12193f9 gsk: Optimize gsk_transform_to...
Optimize these functions for the common cases.
2021-07-24 18:48:10 -04:00
Matthias Clasen
b695ef9168 gsk: Add a shortcut for a common transform case
Add a private getter for the translation part of a
transform node, to avoid pulling it out of the transform
over and over.
2021-07-24 18:48:09 -04:00
Matthias Clasen
7fb1389648 gsk: Add a private getter for container children
No need to get them one-by-one, in our inner loop.
2021-07-24 18:48:09 -04:00
Matthias Clasen
f88efb811b ngl: Reduce type checking overhead
No need to be very careful here, these are entirely
internal types.
2021-07-24 18:48:09 -04:00
Matthias Clasen
466d33ca69 ngl: Speed up clipping calculations a bit
Exit as early as possible from intersect_rounded_rectilinear.
2021-07-24 18:48:09 -04:00
Piotr Drąg
d44ce1987d Update POTFILES.in 2021-07-24 14:38:51 +02:00
Emmanuele Bassi
527b2c5ab1 Merge branch 'no-pposition' into 'master'
gdk/x11: Do not set PPosition hint

See merge request GNOME/gtk!3781
2021-07-24 11:45:00 +00:00
Florian Müllner
4d0c2997cf gdk/x11: Do not set PPosition hint
It is good practice for (floating) window managers to respect explicit
position hints from clients (as long as the window wouldn't end up
off-screen etc.).

Before commit 13d3afa56e, GTK had a flag for setting the PPosition hint,
but now does so unconditionally. However the real intention is to *not*
request a fixed position, so don't do that.
2021-07-24 06:32:16 +02:00
Matthias Clasen
6f04ec9dae Merge branch 'wip/exalm/gtktext-selection-fix' into 'master'
text: Use the widget y coordinate for gestures

See merge request GNOME/gtk!3780
2021-07-23 20:29:07 +00:00
Alexander Mikhaylenko
00cc99818d text: Use the widget y coordinate for gestures
Currently we use layout coordinates and widget height when determining
where a click or drag has happened. If the widget has top padding (which it
does inside a GtkEntry, for example), the area where it's possible to select
text is shifted down, so the part of GtkText above the layout is not counted
as the draggable area and instead the equal area below the widget is counted.

Since GtkText is always single-line, there's no need to do any of that and
we can use widget coordinates. Then the draggable area matches the widget
and the problems goes away.
2021-07-23 23:37:36 +05:00
Matthias Clasen
e51fdc1c9b Merge branch 'stack-page-name' into 'master'
stack: GtkStackPage:name is not construct-only

Closes #4109

See merge request GNOME/gtk!3778
2021-07-23 14:25:29 +00:00
Matthias Clasen
8d5ef4ab30 Merge branch 'matthiasc/for-master' into 'master'
Cosmetics

See merge request GNOME/gtk!3779
2021-07-22 21:22:55 +00:00
Matthias Clasen
7bdda15b86 Cosmetics
Fix a comment typo.
2021-07-22 17:03:08 -04:00
Matthias Clasen
4c41ef8de3 stack: GtkStackPage:name is not construct-only
We have a setter for this property, so we clearly
weren't serious when we marked it as construct-only.

Fixes: #4109
2021-07-22 16:55:15 -04:00
Matthias Clasen
7aec3b0fa1 Merge branch 'startup-profiling' into 'master'
Add more sysprof marks

See merge request GNOME/gtk!3777
2021-07-22 19:20:22 +00:00
Matthias Clasen
fce23c981b Add more sysprof marks
Add a few more marks during gtk_init to figure out where
our startup time goes, and avoid the sysprof initialization
from distorting the first mark.
2021-07-22 14:47:02 -04:00
Matthias Clasen
351819b570 Merge branch 'startup-profiling' into 'master'
Add more sysprof marks

See merge request GNOME/gtk!3776
2021-07-22 17:04:27 +00:00
Matthias Clasen
a10b1b7341 Add more sysprof marks
Add a few more marks during gtk_init to figure out where
our startup time goes, and avoid the sysprof initialization
from distorting the first mark.
2021-07-22 12:51:32 -04:00
Benjamin Otte
02c6226741 Merge branch 'wip/otte/gleanup' into 'master'
reorganize GDK's GL code

See merge request GNOME/gtk!3726
2021-07-22 14:51:05 +00:00
Benjamin Otte
620ccdabb5 glx: Get rid fo DrawableInfo
Store the frame counter in the surface, where it belongs.
2021-07-22 16:28:16 +02:00
Chun-wei Fan
4b12dc6547 gdkdisplay-win32.c: Don't call ReleaseDC() unnecessarily
The dummy Win32 window that we use to capture display change events and
to create dummy WGL contexts was created with CS_OWNDC, so we really do
not need to (and should not) call ReleaseDC() on the HDC that we
obtained from it, so drop these calls.
2021-07-22 16:28:16 +02:00
Chun-wei Fan
bd69d7e23f GDK-Win32: init_gl(): Default to WGL for now
Since the shaders need to be updated for using with GLES (libANGLE at
least), default to WGL for now.  Unfortunately it is not that common for
Windows to have GLES support, in which the easiest way to obtain such
support is via Google's libANGLE.
2021-07-22 16:28:16 +02:00
Chun-wei Fan
8648486400 GDK-Win32: Fixup, and cleanup WGL HDC handling
It turns out that the problem of the WGL window not drawing was due to
the fact that I messed up where I placed SwapBuffers() during the
conversion... doh:|

At the same time, stop storing the HDC in the GdkWin32GLContextWGL, but
instead always create it along the surface we created, so that it is ready
for use for operating with WGL when we are not dealing with "surfaceless"
contexts.  If we are dealing with "surfaceless" contexts, just use the
HDC of the dummy window that we created when we created the
Gdk(Win32)Display.

WGL contexts should now be in working order at this point.
2021-07-22 16:28:16 +02:00
Chun-wei Fan
6c00117119 Split out WGL/EGL stuff and simplify things
This commit attempts to split GdkWin32GLContext into two parts, one for
WGL and the other for EGL (ANGLE), and attempts to simplify things a
bit, by:

*  We are already creating a Win32 window to capture display changes,
   so we can just use that to act as our dummy window that we use to
   find out the pixel format that the system supports for WGL.  We also
   use it to obtain the dummy legacy WGL context that we will always
   require to create our more advanced Core WGL contexts.

*  Like what is done in X11, store up the WGL pixel format or the
   EGLConfig in our GdkWin32Display.

*  Ensure we do not create the dummy WGL context unnecessarily.

In this way, we can successfully create the WGL/EGL contexts, however
there are some issues at this point:

*  For WGL, the code successfully initializes and realizes the WGL
   Contexts, but for some reason things became invisible.  When running
   gtk4-demo, this can be verified by seeing the mouse cursor changing
   when moved to spots where one can resize the window, although they
   were invisible.

*  For EGL, the code initializes EGL but could not realize the EGL
   context as shaders failed to compile.  It seems like the shader issue
   is definitely outside the scope of this MR.
2021-07-22 16:28:16 +02:00
Benjamin Otte
9c4c4eaaa1 gl: Fix issue with EGL + nvidia
nvidia sets the default draw buffer to GL_NONE if EGL contexts are
initially bound to EGL_NO_SURFACE which is exactly what we are doing. So
bind them to GL_BACK when drawing, as they should be.

See https://phabricator.services.mozilla.com/D118743 for a discussion
about EGL_NO_CONTEXT and draw buffers.
2021-07-22 16:28:16 +02:00
Chun-wei Fan
969b3257a7 GDK: Add debug option for WGL usage
This way, one can force using WGL on Windows even if EGL support was
enabled.  Also update the help text for gl-egl as it will apply for
Windows, albeit a bit later.
2021-07-22 16:28:16 +02:00
Chun-wei Fan
65c6af31e1 GDK-Win32: Move some functions out of gdkglcontext-win32.c
We want these to be out of the way as we split between WGL and EGL/ANGLE
GL contexts, so that they don't get in the way.
2021-07-22 16:28:16 +02:00
Benjamin Otte
6b8bc83420 display: Move GL selection code into gdkdisplay-x11.c
This has the benefit that we can refactor it and make sure we deal with
GdkDisplay::init_gl() not being called at all because
GDK_DEBUG=gl-disable had been specified.
2021-07-22 16:28:16 +02:00
Benjamin Otte
30aaab5c6c x11: Move code from GdkGLContextX11
It's not used there, but both backends have independent
immplementationgs for it.

I want to get rid of GdkGLContextX11 and moving code from it is the
first step.
2021-07-22 16:28:16 +02:00
Benjamin Otte
72e2a46c05 inspector: Add support for displaying GL errors
Also, no need to show a GL version if GL isn't available.
2021-07-22 16:27:32 +02:00
Benjamin Otte
e06e0e8555 gdk: Move GL context construction to GdkGLContext
Now that we have the display's context to hook into, we can use it to
construct other GL contexts and don't need a GdkSurface vfunc anymore.

This has the added benefit that backends can have different GdkGLContext
classes on the display and get new GLContexts generated from them, so
we get multiple GL backend support per GDK backend for free.

I originally wanted to make this a vfunc on GdkGLContextClass, but
it turns out all the abckends would just call g_object_new() anyway.
2021-07-22 16:27:32 +02:00
Benjamin Otte
9f1d6e1f44 gl: Move vfunc
Instead of
  Display::make_gl_context_current()
we now have
  GLContext::clear_current()
  GLContext::make_current()

This fits better with the backends (we can actually implement
clearCurrent on macOS now) and makes it easier to implement different GL
backends for backends (like EGL/GLX on X11).

We also pass a surfaceless boolean to make_current() so the calling code
can decide if a surface needs to be bound or not, because the backends
were all doing whatever, which was very counterproductive.
2021-07-22 16:27:32 +02:00
Benjamin Otte
15ed1a329e gl: Require EGL_KHR_surfaceless_context with egl
The code to create and manage a fake egl surface to bind to is
complex and completely untested because everyone seems to support this
extension.

nvidia and Mesa do support it and according to Mesa devs, adding support
in a new driver is rather simple and Mesa drivers gain that feature
automatically, so all future drivers shoould have it.
2021-07-22 16:27:31 +02:00
Benjamin Otte
505436340b gdk: Get rid of paint contexts
... or more exactly: Only use paint contexts with
gdk_cairo_draw_from_gl().

Instead of paint contexts being the only contexts who call swapBuffer(),
any context can be used for this, when it's used with
begin_frame()/end_frame().

This removes 2 features:

1. We no longer need a big sharing hierarchy. All contexts are now
   shared with gdk_display_get_gl_context().
2. There is no longer a difference between attached and non-attached
   contexts. All contexts work the same way.
2021-07-22 16:27:31 +02:00
Benjamin Otte
a27434a8a7 gl: Store the context::in-frame state in the current context
Do not treat the context as already current when the value
of context::in-frame changes.

This is so we can bind to EGL_NO_SURFACE if context::in-frame == false
and to context::surface if context::in-frame == true.

This allows getting rid of the attached property in future commits.
2021-07-22 16:27:31 +02:00
Benjamin Otte
2c987861a6 gl: Deprecate gdk_gl_context_get_shared_context()
It's not used anymore. And in particular we do want to keep the display
context private, so we're not gonna return it from this function.
2021-07-22 16:27:31 +02:00
Benjamin Otte
c7320df0c9 gdk: Add gdk_gl_context_is_shared()
... and use it in the GL renderers.
2021-07-22 16:27:31 +02:00
Benjamin Otte
dd666e4fe4 ngl: Store the shared driver in the display
... instead of some random GL context.
2021-07-22 16:23:56 +02:00
Benjamin Otte
e4f0418003 gdk: Require EGL version 1.4 across the board
Mesa currently ships 1.5.
2021-07-22 16:23:56 +02:00
Benjamin Otte
430b6f8fb1 gdk: Add GdkDisplay::init_gl vfunc
The vfunc is called to initialize GL and it returns a "base" context
that GDK then uses as the context all others are shared with. So the GL
context share tree now looks like:

+ context from init_gl
  - context1
  - context2
  ...

So this is a flat tree now, the complexity is gone.

The only caveat is that backends now need to create a GL context when
initializing GL so some refactoring was needed.

Two new functions have been added:

* gdk_display_prepare_gl()
  This is public API and can be used to ensure that GL has been
  initialized or if not, retrieve an error to display (or debug-print).
* gdk_display_get_gl_context()
  This is a private function to retrieve the base context from
  init_gl(). It replaces gdk_surface_get_shared_data_context().
2021-07-22 16:23:56 +02:00
Benjamin Otte
ba3e80cbfa wayland: Don't pass GL config to get_egl_surface()
There's only one GL config.
2021-07-22 16:23:56 +02:00
Benjamin Otte
7cd4282bad wayland: Move fbconfig into the display
Create it during init and then reuse it for all contexts.

While doing that, also improve error reporting - that's not used yet but
will in later commits.
2021-07-22 16:23:56 +02:00
Benjamin Otte
01e9fa9adb gdk: Allow GdkDrawContext with a %NULL surface
This is not used yet, but it allows surfaceless GL contexts.

For that purpose, we need to make the display a construct-only property,
so that it can be set when the surface isn't.

This adds a bunch of very picky checks in the constructor so nothing bad
can happen.
2021-07-22 16:23:56 +02:00
Benjamin Otte
581e01b2da gdk: Add a private struct to GdkDisplay
... and move some members from the GdkDisplay struct.

We've always wanted to add one to isolate the display from the backends
a bit more, but so far it's never happened.

Now that I'm about to add more data to GdkDisplay, it's a good excuse to
start.
2021-07-22 16:23:56 +02:00
Benjamin Otte
5a3b4de1b7 x11: Redo choice between EGL and GLX
We try EGL first, but are very picky about what we accept.
If that fails, we try to go with GLX instead.
And if that also fails, we try EGL again, but this time accept anything.

The idea here is that EGL is the preferred method going forward, but GLX is
the tried and tested method that we know works. So if we detect issues with
EGL, we want to avoid using it in favor of GLX.

Also add a GDK_DEBUG=gl-egl option to force EGL at all costs and not try
GLX.
2021-07-22 16:23:56 +02:00
Benjamin Otte
74288eceaf x11: Properly record the error when initializing GL
That way, we can give a useful error message when things break down for
users.

These error messages could still be improved in places (like looking at
the actual EGL error codes), but that seemed overkill.
2021-07-22 16:23:56 +02:00
Benjamin Otte
37ba057128 x11: Do not call glXQueryExtension()
epoxy does that already.
2021-07-22 16:23:56 +02:00
Benjamin Otte
6d5ba9590b x11: Get Visual from EGL directly
Query the EGL_VISUAL_ID from the egl Config and select a config with the
matching Visual.

This is currently broken on Mesa because it does not expose any RGBA
X Visuals in any EGL config, so we always end up with opaque Windows.

https://gitlab.freedesktop.org/mesa/mesa/-/issues/149
2021-07-22 16:23:56 +02:00
Benjamin Otte
215f792851 x11: Store the GLX drawable in the surface
Also, stop using a dummy window for unattached GL contexts and instead
use the display's leader surface.

Again, this mirrors EGL.
2021-07-22 16:23:56 +02:00
Benjamin Otte
1c55b32879 x11: Use single GLX fbconfig and store it in the display
This mirrors the code for the EGL config.
2021-07-22 16:23:56 +02:00
Benjamin Otte
82eb947f41 x11: Remove glx version check
We only work with GLX >= 1.3 anyway, so don't explicitly check for it
and pretend to do something else that doesn't work otherwise.
2021-07-22 16:06:06 +02:00
Benjamin Otte
485dae9f25 x11: Remove unused struct member
We don't care if the GL context is direct at all.
2021-07-22 16:06:06 +02:00
Benjamin Otte
eb3423312f Revert "x11: Always fall back to GLX on NVIDIA"
This reverts commit c35a6725b9.

This approach doesn't work because if NVIDIA doesn't work for EGL, the
EGL implementation won't be provided by NVIDIA, so checking the vendor
doesn't work.
2021-07-22 16:06:06 +02:00
Benjamin Otte
04c2093d5c x11: Remove the dummy surface
Instead, use the display's "leader surface" when no surface is required,
because we have it lying around.

Really, we want to use EGL_NO_SURFACE, but if that's not supported...
2021-07-22 16:06:06 +02:00
Benjamin Otte
ccd5992a83 x11: Remove GdkVisual
It's not used anymore.
2021-07-22 16:06:06 +02:00
Benjamin Otte
ca8d9fbe0b x11: Rework Visual selection
Instead of going via GdkVisual, doing a preselection and letting the GL
initialization improve it, let the GL initialization pick an X Visual
directly using X Visual code directly.

The code should select the same visuals as before as it tries to apply
the same logic, but it's a rewrite, so I expect I messed something up.
2021-07-22 16:06:06 +02:00
Benjamin Otte
62bac44a21 glx: Remove Visual cache
1. We're using EGL most of the time anyway, so if we wanted to cache
   things, we'd need to port it there.
2. Our GL handling is massively configurable, so determining when to use
   the cache and when not is a challenge.
3. It makes startup nondeterministic and depend on whether a GTK4 app
   has previously been started on this display and nobody thinks about
   that when debugging.
4. The only benefit of the caching is delaying GL initialization - which
   made sense in GTK3 where almost no app used GL but doesn't make sense
   in GTK4 where almost every app uses GL.

So unless I find a big benefit to reintroducing it, this cache will be
gone for good.
2021-07-22 16:06:05 +02:00
Benjamin Otte
0ddd06113d x11: Move GL init code into the GL context
No functional changes, just shuffling code.
2021-07-22 16:06:05 +02:00
Benjamin Otte
b1fbc2ef24 x11: Store the EGL surface in the GdkSurfaceX11
Avoids having to use private data, though the benefit is somewhat
limited as we still have to put the destructor in the egl code and can't
just put it in gdk_surface_x11_finalize().
2021-07-22 16:06:05 +02:00
Benjamin Otte
c787fe7ecb x11: Store the EGL config in the display
We only have one config, because we use the same Visual everywhere.
Store this config in the GdkDisplayX11 struct for easy access.

Also do this on initialize, because if creating the config fails, we
want to switch to GLX instead of failing to do GL at all.

This also simplifies a lot of code as we can share Visual, Colormap, etc
across surfaces.
2021-07-22 16:06:05 +02:00
Benjamin Otte
bdb49720be x11: Move the EGL display into the private struct
There's no need to use g_object_set_data() for it.

We can also stop caching it elsewhere because we know the display has
it.

And finally, we can remove the display->have_egl boolean and use
display->egl_display != NULL instead. We initialize the display at
startup, so that variable is the perfect indicator.
2021-07-22 16:06:05 +02:00
Benjamin Otte
1d448a2b8a x11: Pass the display, not the screen
Screens are on their way out.
2021-07-22 16:06:05 +02:00
Benjamin Otte
c5df081904 x11: Simplify code
These variables were a lot more important in GTK3, but now we just want
to pass them through to X.
2021-07-22 16:06:05 +02:00
Benjamin Otte
8a2f3e1fe5 x11: Move function call
The GLX visual selection is GLX specific, so it can be handled by the GLX
code.

There should be no reordering here, the call was just moved.
2021-07-22 16:06:05 +02:00
Benjamin Otte
8dfc627e46 glx: Don't initialize GLX multiple times.
Either it is initialized or it isn't.
2021-07-22 16:06:05 +02:00
Benjamin Otte
0fce30070f x11: Initialize GL at startup
We need to initialize GL to select the Visual we are going to use for
all our Windows.

As the Visual needs to be known before we know if we are even gonna use
GL later, we can't avoid initializing it.

Note that this previously happened, too. It was just hidden behind the
GdkScreen initialization.
2021-07-22 16:06:05 +02:00
Benjamin Otte
8bfe82f686 x11: Don't share cached GLX visuals with GTK3
We don't want to bind ourselves to GTK3 - both because we don't want to
accidentally cause bugs in a different codebase and because we want to
deviate from it.

While doing so, also store visuals as visuals and not as integers.
And only store one Visual because GTK4 only uses one visual.

And then remove the code that is leftover for dealing with the
compatibility Visual for GTK3.

PS: I'm kinda proud of my STRINGIFY_WITHOUT_BRACKETS hack.
2021-07-22 16:06:05 +02:00
Benjamin Otte
7d32ec51e7 x11: Reorder code
Initialize the GL visuals from gdkdisplay.c so the call into the GL
stack isn't hidden in gdkvisual.c

This is relevant for further commits.
2021-07-22 16:06:05 +02:00
Benjamin Otte
5784f8c2f9 x11: Stop reordering visuals
The old code was ordering visuals by depth, but considering that these
days we either use the default visual or a 32bit RGBA visual, that
reordering does not have an effect anymore.

In theory, the only effect is that the GLX Visual selection might select
a different replacement Visual when it checks for improved GL Visuals, but
even there I can't come up with a case where that matters, because
again, the visuals are only reordered by depth and we want to keep the
depth.

In any case, make this a separate commit so bisecting can find this
problem if it ever shows up.
2021-07-22 16:06:05 +02:00
Benjamin Otte
74e01ddec5 x11: Remove unused function
Now that we can't create extra GdkX11Screens anymore, this also means
that there is exactly 1 GdkX11Screen per GdkX11Display.
2021-07-22 16:06:05 +02:00
Benjamin Otte
1347573139 x11: Move code where it belongs
Instead of the display telling the screen to tell the visuals to tell
the display to initialize itself, just init the display directly.

What a concept.
2021-07-22 16:06:05 +02:00
Benjamin Otte
f2b41e708d build: Build demos before tools
That's a sneaky trick so my edit/compile/test cycle goes faster:
I usually use demos for testing so the tools don't have to be linked for
me to start testing.
2021-07-22 16:06:05 +02:00
Matthias Clasen
a5555943ed Merge branch 'destroy-pointer-gestures' into 'master'
gdk/wayland: Clean up gestures if pointer capability is withdrawn

See merge request GNOME/gtk!3697
2021-07-21 21:33:53 +00:00
Vlad Zahorodnii
2c023cdaed gdk/wayland: Clean up gestures if pointer capability is withdrawn
If the pointer capability is added, pointer swipe and pinch gestures
will be created. However, if the pointer capability is removed, the
gesture objects won't be destroyed.

If the pointer capability is removed and added several times in a row,
for example due to plugging and unplugging physical mouse, this can lead
to leaking the old gesture objects.

In order to prevent that, this change makes the seat destroy swipe and
pinch gestures when the pointer capability is withdrawn.
2021-07-21 20:52:16 +03:00
Matthias Clasen
bcc7028640 Merge branch 'sync-icons' into 'master'
Sync included icons from adwaita-icon-theme

See merge request GNOME/gtk!3773
2021-07-21 17:49:15 +00:00
Matthias Clasen
bdee75cd0f Sync included icons from adwaita-icon-theme
Make sure we stay in sync with the Adwaita.
2021-07-20 17:26:59 -04:00
Matthias Clasen
94eb3d7ac0 Merge branch 'wip/otte/build' into 'master'
Streamline build configuration

See merge request GNOME/gtk!3391
2021-07-20 18:25:59 +00:00
Benjamin Otte
0ae2acfb1a x11: Remove XComposite
It's only used during DND to allow use of the root window's cow window
as a DND target, because apparently gnome-shell used to think that was a
great idea to DND to the overview.

Somebody complain to gnome-shell devs about it not being a good idea if
they want it fixed.
Potentially using Wayland is a better idea though.

This reverts 85ae875dcb

Related: https://bugzilla.gnome.org/show_bug.cgi?id=601731
2021-07-20 14:00:25 -04:00
Benjamin Otte
afc5f46ca9 x11: Remove unused headers 2021-07-20 14:00:25 -04:00
Benjamin Otte
e544c891ca build: Make all X11 extensions mandatory
It's not 2011 anymore, and we shouldn't randomly build one of 10.000
different combinations of X11 backends (I counted the possibilities) but
exactly the one we expect people to use.
2021-07-20 14:00:25 -04:00
Benjamin Otte
af0c95c11a build: Remove sassc option
Instead, ensure that sassc is made madatory on git builds (because
it is, we don't ship CSS files anymore) and not even looked for in
release builds (because do ship CSS files there).
2021-07-20 14:00:25 -04:00
Benjamin Otte
4d5dc18a57 build: disable Vulkan by default
We don't want people to build Vulkan support when they just want to get
GTK built.

This is in particular true for GTK as a CI subproject or for people
using jhbuild.

Worse, just having Vulkan support compiled in tends to cause crashes
in the Inspector, even if you are not using it.
2021-07-20 14:00:25 -04:00
Benjamin Otte
9f6fb161e2 build: Set proper defaults for media backends
GTK supports webm playback, which means a backend should always be
compiled.

The ffmpeg backend however is incomplete (no audio) and as such, we
don't want people to end up with it accidentally.

Since we don't want to drag an entire gstreamer build into our ci
on MacOs or msvc, explicitly disable the gstreame media backend there.
2021-07-20 14:00:25 -04:00
Matthias Clasen
3883a98771 Merge branch 'fix-dialog-docs' into 'master'
gtk/builder: Port example to GTK 4

See merge request GNOME/gtk!3772
2021-07-20 12:54:55 +00:00
Yuri Chornoivan
9b44965f13 Update Ukrainian translation 2021-07-20 12:08:13 +00:00
Maximiliano Sandoval R
aa6a9de6ba gtk/builder: Port example to GTK 4 2021-07-20 13:22:08 +02:00
Matthias Clasen
8669e8a498 Merge branch 'tooltip-hig' into 'master'
password_entry: Header Capitalization on tooltip

See merge request GNOME/gtk!3771
2021-07-20 11:17:36 +00:00
Maximiliano Sandoval R
ead31db096 password_entry: Header Capitalization on tooltip
See https://teams.pages.gitlab.gnome.org/Design/hig-www/feedback/tooltips.html
2021-07-20 13:00:05 +02:00
Matthias Clasen
69fda941c7 Merge branch 'win32.hidpi.cleanup' into 'master'
GDK-Win32: Clean up HiDPI support and WGL slightly

Closes #3796

See merge request GNOME/gtk!3767
2021-07-20 02:43:43 +00:00
Matthias Clasen
67c9e7a4a8 Merge branch 'ci-default-settings-4' into 'master'
reftests: Enforce default settings

See merge request GNOME/gtk!3769
2021-07-19 18:36:11 +00:00
Matthias Clasen
4e4f57e091 reftests: Enforce default settings
Set all settings to their default values, so we
are less dependent on the environment to be set
up just right. In particular, this fixes animations
being disabled when we happen to run in a vm.
2021-07-19 13:26:32 -04:00
Chun-wei Fan
ac64d2d910 GDK-Win32: Clean up HiDPI support and WGL a bit
Make _gdk_win32_display_get_monitor_scale_factor() less complex, by:

*  Drop the preceding underscore.

*  Dropping an unused parameter.

*  Using a GdkSurface instead of a HWND, as the HWND that we pass into
   this function might have been taken from a GdkSurface, which are now
   always created with CS_OWNDC.  This means if a GdkSurface was passed
   in, we ensure that we only acquire the DC from the HWND once, and do
   not attempt to call ReleaseDC() on it.

*  Store the HDC that we acquire from the GdkSurface's HWND into the
   surface, and use that as the HDC we need for our GdkGLContext.

*  Drop the gl_hwnd from GdkWin32Display, as that is really should be
   stored in the GdkSurface.

*  For functions that were updated, name GdkWin32Display variables as
   display_win32 and GdkSurface variables as surface, to unify things.

*  Stop calling ReleaseDC() on the HDC that we use for OpenGL, since
   they were acquired from HWND's created with CS_OWNDC.
2021-07-19 18:30:42 +08:00
Chun-wei Fan
49a76257cd gdksurface-win32.c: Create all surfaces with CS_OWNDC
We want to ensure that we have things set up properly for drag surfaces
as well.
2021-07-19 17:36:54 +08:00
Matthias Clasen
77829cf3ed Merge branch 'pango-main' into 'master'
Use pango from the main branch

See merge request GNOME/gtk!3762
2021-07-17 13:05:42 +00:00
Yuri Chornoivan
4d10ab3d35 Update Ukrainian translation 2021-07-17 05:34:21 +00:00
Matthias Clasen
e609ede597 Use pango from the main branch
Change the Pango subproject to use the main branch.

This depends on
https://gitlab.gnome.org/GNOME/pango/-/merge_requests/379
2021-07-16 13:19:22 -04:00
Benjamin Otte
2ba69abe39 Merge branch 'wip/otte/for-master' into 'master'
cssimagecrossfade: Don't abort() when failing to parse image

Closes #4101

See merge request GNOME/gtk!3758
2021-07-16 16:26:23 +00:00
Benjamin Otte
a76f515569 cssimagecrossfade: Don't abort() when failing to parse image
The code wasn't checking if parsing an image failed and just returning
success.

Testcase from bug is attached.

Fixes #4101
2021-07-16 17:50:09 +02:00
Matthias Clasen
a663b8c313 Merge branch 'fix-negative-scales' into 'master'
ngl: Handle negative scales

Closes #4096

See merge request GNOME/gtk!3755
2021-07-16 11:59:47 +00:00
Matthias Clasen
f66fa16bd1 Merge branch 'metainfo' into 'master'
metadata: Fix license identifiers and appdata

See merge request GNOME/gtk!3757
2021-07-16 11:14:09 +00:00
Matthias Clasen
8390363abe testsuite: Avoid negative scales with gl renderer
The fix in 1c90bb522e was only for the ngl renderer,
so don't use the test with the gl renderer, until it is
fixed as well.
2021-07-16 07:11:20 -04:00
Matthias Clasen
6ff85d287a Merge branch 'wip/chergert/fix-texthistory-insert' into 'master'
texthistory: fix calculation of n_chars

See merge request GNOME/gtk!3756
2021-07-16 11:04:21 +00:00
Maximiliano Sandoval R
94c2072be8 meson: Use a valid SPDX identifier
See https://mesonbuild.com/Reference-manual.html#license
2021-07-16 11:14:46 +02:00
Maximiliano Sandoval R
64b9d53472 appdata: Use launchable rather than id
<id> should be used for the component id and <launchable> for the
desktop file.
2021-07-16 11:14:46 +02:00
Maximiliano Sandoval R
a5e7b92c5d appdata: Add content_rating
https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html#tag-content_rating
2021-07-16 11:14:42 +02:00
Maximiliano Sandoval R
2da9ba63e2 appdata: Use correct SPDX license identifier
Following
https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html#tag-project_license,
for the complete list of identifiers see https://spdx.org/licenses/
2021-07-16 11:09:28 +02:00
Christian Hergert
5d02a8f5db texthistory: fix calculation of n_chars
This should be the number of characters, not the end position. This fixes
an issue where we wouldn't coalesce insert actions together.
2021-07-15 21:26:30 -07:00
Benjamin Otte
834d3749c6 testsuite: Add test for crasher
Test for the crasher in !4096
2021-07-15 23:43:28 +02:00
Matthias Clasen
1c90bb522e ngl: Handle negative scales
Scale factors can be negative, but we were not
looking out for that, triggering an assertion when
trying to create a render target with negative
width of height. Avoid that.

Fixes: #4096
2021-07-15 16:40:13 -04:00
Matthias Clasen
b70b058b66 Merge branch 'transparent-optimizations' into 'master'
snapshot: Handle transparent opacity nodes correctly

See merge request GNOME/gtk!3754
2021-07-15 18:39:48 +00:00
Matthias Clasen
b99beeb552 Merge branch 'wip/baedert/for-master' into 'master'
snapshot: Replace trivial gradients with color nodes

See merge request GNOME/gtk!3753
2021-07-15 18:31:22 +00:00
Matthias Clasen
c799452973 ngl: Do nothing for transparent text nodes
Like the previous commit - a transparent text node
will not produce any visible pixels, so bail out early.
2021-07-15 13:18:23 -04:00
Matthias Clasen
fd48afb77d ngl: Do nothing for transparent color nodes
No need to send commands to the GPU to render transparency.
2021-07-15 13:18:23 -04:00
Matthias Clasen
aaa68954c3 snapshot: Handle transparent opacity nodes correctly
Eliding totally transparent content from the node tree is
not 100% correct, since filters can make things visible, so
we need to at least preserve the bounds. We can do that by
creating a transparent color node.
2021-07-15 13:18:23 -04:00
Timm Bäder
433233258b snapshot: Only compute start and end point if we have to
If the linear gradient results in a color node, we don't need the start
and end point. Only declare and compute it if we need to.
2021-07-15 16:52:38 +02:00
Timm Bäder
3eed61deba snapshot: Replace trivial gradients with color nodes
Extend this to all existing gradient types
2021-07-15 16:51:17 +02:00
Matthias Clasen
87e2a02e0c composetable: Rewrite Compose files if necessary
Apply heuristics to avoid breaking users existing configurations
with the change to not always add the default sequences.

If we find a cache that was generated before 4.4, and the Compose
file does not have an include, and doesn't contain so many sequences
that it is probably a copy of the system one, we take steps to keep
things working, and thell the user about it.
2021-07-15 09:30:09 -04:00
Matthias Clasen
264d592012 composetable: Keep the number of sequences
And print it out in tests.

Update all tests for this.
2021-07-15 09:30:01 -04:00
Matthias Clasen
0ad5094119 Remove some leftover debug code 2021-07-15 09:30:01 -04:00
Benjamin Otte
67952a9142 Merge branch 'wip/otte/for-master' into 'master'
rendernodeparser: Don't use %g when writing file

See merge request GNOME/gtk!3752
2021-07-14 18:46:36 +00:00
Benjamin Otte
ca3d942b9b rendernodeparser: Remove leftover debug prints 2021-07-14 20:19:40 +02:00
Benjamin Otte
5470a1344d rendernodeparser: Don't use %g when writing file
%g is locale dependent and can add "," where "." should be. Use
string_append_double() instead.
2021-07-14 20:18:44 +02:00
Matthias Clasen
4390f8102b imcontext: Improve the docs
Add more details about supported input methods.
2021-07-13 22:03:23 -04:00
Matthias Clasen
92129a2011 imcontext: Simplify checking compose seqs
Add the builtin table to the list of tables, and
remove the duplicated code that checks builtin
sequences separately.
2021-07-13 22:03:23 -04:00
Matthias Clasen
54dffa07f3 composetable: Drop GtkComposeTableCompact
All tables use the compact format now, and we generate
caches in that format too. Bump the cache version to 3
for this.

Replace the python script for generating the builtin table
by a small C program using the same code to generate the data
for the builtin table. This drops the restriction on only
generating a single character in the builtin sequences.
2021-07-13 22:03:23 -04:00
Matthias Clasen
1cff4bb27a composetable: Ignore length 1 sequences
It turns out that the X11 Compose file has some
length 1 sequences which are not interesting to us.
2021-07-13 22:02:33 -04:00
Matthias Clasen
8087250476 imcontext: Replace the builtin sequences
When we find a Compose file, replace the builtin
sequences with the table we found. This matches the
semantics described in Compose(5), and makes it possible
to drop unwanted sequences from the builtin table.

It is slight change of behavior for users with existing
Compose files. To match the previous behavior, you have
to add

include "%L"

to your Compose file, to keep the builtin sequences in
addition to your own.
2021-07-13 22:02:33 -04:00
Matthias Clasen
485dc052ca composetable: Allow removing sequences
Interpret an empty string as value in the Compose
file to mean: Remove this sequence.

Tests included.
2021-07-13 22:02:33 -04:00
Matthias Clasen
45d39c2802 composetable: Switch to using a hash table
This lets us naturally replace matching sequences
while parsing. That means that the semantics are now
"last one wins" if the parser sees multiple entries
for the same sequence.

Add a testcase that checks the new replacement semantics.
2021-07-13 22:02:33 -04:00
Matthias Clasen
3b4b1c6878 composetable: Reinterpret %L
When we see include "%L" in a Compose file, use the
builtin sequences. We no longer filter out duplicates
wrt. to the builtin sequences.
2021-07-13 22:02:33 -04:00
Matthias Clasen
ff4f07d76f composetable: Handle substitutions in includes
Hande the %H, %L, %S substitutions that are described
in Compose(7).

Test included.
2021-07-13 22:02:33 -04:00
Matthias Clasen
fb6c8cd466 composetable: Handle includes
This adds the mechanics for parsing include lines in
Compose files. We do detect and prevent cycles.

Tests included.
2021-07-13 22:02:33 -04:00
Matthias Clasen
8464b0484f composetable: Move code into the parser
This is just code reshuffling.
2021-07-13 22:02:33 -04:00
Matthias Clasen
bee58fd09d composetable: Introduce a parser struct
This will be used in the following commits to
beef up Compose file parsing.
2021-07-13 22:02:33 -04:00
Matthias Clasen
d25557a5ef Clean up the GtkComposeTable api
Keep the list of composetables private to GtkIMContextSimple,
and just have an api that creates new GtkComposeTables, either
from a file or from data.

Update tests to use the new api.
2021-07-13 22:02:33 -04:00
Matthias Clasen
da3ca6604b gtk-demo: Add a slider to the menu example
This is a fun way to show that we can scale fast.
2021-07-13 22:02:33 -04:00
Matthias Clasen
74cba6c3b2 Add a simple Javascript example
This shows how to use a layout manager in a widget,
implemented in javascript. The example sets up the
environment for running from the toplevel dir, assuming
that the build dir is called 'build'.
2021-07-13 22:02:33 -04:00
Emmanuele Bassi
c09718b731 Merge branch 'doc-fixes' into 'master'
doc: Syntax fixes

See merge request GNOME/gtk!3751
2021-07-13 23:43:06 +00:00
Marco Melorio
eacfa2a966 doc: Syntax fixes 2021-07-13 22:53:19 +00:00
Matthias Clasen
e7f228e240 Merge branch 'fp16-tests' into 'master'
ngl: Make the C half-float implementation accessible

See merge request GNOME/gtk!3748
2021-07-13 13:38:21 +00:00
Matthias Clasen
fab82a7c25 tests: Add some fp16 tests 2021-07-13 09:03:49 -04:00
Matthias Clasen
fc9c34897a ngl: Make the C half-float implementation accessible
Make this accessible for tests.
2021-07-13 09:03:49 -04:00
Emmanuele Bassi
28cdd3f497 Merge branch 'gi-fixes' into 'master'
Various introspection fixes

See merge request GNOME/gtk!3747
2021-07-13 11:21:20 +00:00
Marc-André Lureau
a009e26e95 gtk: fix GtkPasswordEntryBuffer introspection
Move the source file to public_sources list, and fix tag annotation.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
2021-07-13 15:03:09 +04:00
Marc-André Lureau
ab908c23f4 Add GtkMenuButton:primary Since: annotation
Property added in commit a74420bc1a.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
2021-07-13 11:31:09 +04:00
Marc-André Lureau
ae21f66fe5 Add GTK_DEBUG_ICONFALLBACK Since: 4.2 annotation
Introduced in commit 6f82408056.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
2021-07-13 11:26:39 +04:00
Rafael Fontenelle
2d092ea280 Update Brazilian Portuguese translation
(cherry picked from commit c7a7fc4de6)
2021-07-10 19:30:32 +00:00
Rafael Fontenelle
0f9d39cdfd Update Brazilian Portuguese translation
(cherry picked from commit 72c3026764)
2021-07-10 17:14:31 +00:00
Matthias Clasen
a64087d481 Merge branch 'activatable-buttons' into 'master'
menubutton: Make menu buttons activatable again

Closes #4079

See merge request GNOME/gtk!3728
2021-07-10 12:59:39 +00:00
Matthias Clasen
c85f3f4942 Merge branch 'wip/chergert/fix-4094' into 'master'
joinedmenu: add helper to join menus instead of nesting

Closes #4094

See merge request GNOME/gtk!3739
2021-07-09 19:29:41 +00:00
Matthias Clasen
d7553279ff Merge branch 'gdkkeys-m' into 'master'
[master] gdkkeys-win32.c: fix initialisation of key_state in update_keymap

See merge request GNOME/gtk!3742
2021-07-09 10:58:23 +00:00
Matthias Clasen
c86631b8a9 Merge branch 'dynamic-typelib-path' into 'master'
build: Get typelib dir dynamically using gobject-introspection dependency

See merge request GNOME/gtk!3737
2021-07-09 10:57:37 +00:00
Matthias Clasen
c1af63de9b Merge branch 'invisible-char-fix' into 'master'
textbtree: Initialize to zero the tags counting array

See merge request GNOME/gtk!3740
2021-07-09 10:56:51 +00:00
Jeremy Tan
2784b03b2d gdkkeys-win32.c: fix initialisation of key_state in update_keymap
It apparently worked by chance in the past, but now causes e.g.
alphanumeric characters to be interpreted as half-width katakana
when using the Japanese IME.
2021-07-09 12:46:49 +08:00
Marco Trevisan (Treviño)
10bdf8c645 textbtree: Initialize to zero the tags counting array
We're using the tag contents array to count the number of invisible tags
set but we always increase it without being initialized.

This may lead to unexpected behavior when traversing them and it's
causing a reliable failure in the textiter tests under s390x.

So, memset that area content to 0 once allocated. It's not needed to do
the same for the tags themselves as we always assign them.

 Conditional jump or move depends on uninitialised value(s)
   at 0x4CFAA00: _gtk_text_btree_char_is_invisible (gtktextbtree.c:2569)
   by 0x4B8A1BB: find_visible_by_log_attrs (gtktextiter.c:3244)
   by 0x10E93D: check_backward_visible_word_start (textiter.c:484)
   by 0x10E93D: test_visible_word_boundaries (textiter.c:523)
   by 0x533288F: g_test_run_suite (in /usr/lib/s390x-linux-gnu/libglib-2.0.so.0)
   by 0x53328E7: g_test_run (in /usr/lib/s390x-linux-gnu/libglib-2.0.so.0)
   by 0x109CC1: main (textiter.c:807)
2021-07-09 03:48:40 +02:00
Christian Hergert
d63d9b2319 joinedmenu: add helper to join menus instead of nesting
In many cases, we have an "extra-menu" property that is used to allow
applications to join menus into the native menu for the widget. Previously,
this was done by nesting that menu in a section.

Doing so increases the complexity of the rules for GtkMenuTracker as you
may want different handling from inside of the section vs toplevel
sections.

If instead we synthetically glue the menus together, we have a much more
natural joining of menus as the application developer would expect for
their menu.

This also ports GtkLabel, GtkText, GtkPasswordEntry, and GtkTextView to
use the joined menu helper.

The joined menu helper comes originally from GNOME Builder and has had
extensive use there.

Fixes #4094
2021-07-08 14:16:06 -07:00
Marco Trevisan (Treviño)
d5f2b69d0c build: Get typelib dir dynamically using gobject-introspection dependency
We hardcoded the typelib directory for only an arch (and a distro),
while we can just get it from gobject-introspection pkg config if tests
are enabled.
2021-07-08 04:59:10 +02:00
Matthias Clasen
6818eee859 Merge branch 'wip/exalm/scroll-touch' into 'master'
scrolledwindow: Don't check drag threshold when already scrolling

See merge request GNOME/gtk!3735
2021-07-07 21:37:58 +00:00
Matthias Clasen
e7f1398d85 Merge branch 'text-cursor-extents' into 'master'
text: Add API to compute cursor extents

See merge request GNOME/gtk!3734
2021-07-07 21:37:14 +00:00
Matthias Clasen
880c01f8cc Merge branch 'wl-since' into 'master'
Add missing "Since: 4.X" doc tags

See merge request GNOME/gtk!3736
2021-07-07 21:36:13 +00:00
Marc-André Lureau
337c5e5e59 Add missing "Since: 4.X" tags
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
2021-07-07 23:35:38 +04:00
Florian Müllner
af52ea78c6 text: Add API to compute cursor extents
The extents that correspond to the strong/weak cursor at a given
character position can be used for example to point a popover to
text in the widget.
2021-07-07 19:33:12 +02:00
Alexander Mikhaylenko
fe633d9ef9 scrolledwindow: Don't check drag threshold when already scrolling
Checkout the drag threshold only makes sense when starting a scroll, after
that it just adds jumps when trying to scroll back and forth.
2021-07-07 19:39:06 +05:00
Matthias Clasen
e6cce283a7 Merge branch 'matthiasc/for-master' into 'master'
gtk-demo: Add a slider to the menu example

See merge request GNOME/gtk!3733
2021-07-06 00:23:30 +00:00
Matthias Clasen
c920236c54 gtk-demo: Add a slider to the menu example
This is a fun way to show that we can scale fast.
2021-07-05 19:31:54 -04:00
Matthias Clasen
6f86b4d220 Merge branch 'js-example' into 'master'
Add a simple Javascript example

See merge request GNOME/gtk!3731
2021-07-05 20:24:30 +00:00
Matthias Clasen
a085e174c5 Merge branch 'wip/remove-cloudprint' into 'master'
Remove Google Cloud Print backend

See merge request GNOME/gtk!3729
2021-07-05 20:21:52 +00:00
Florentina Mușat
d3c08789a3 Update Romanian translation
(cherry picked from commit 6ff90954dc)
2021-07-05 20:02:15 +00:00
Florentina Mușat
630488210b Update Romanian translation
(cherry picked from commit e5bd6312be)
2021-07-05 19:47:50 +00:00
Matthias Clasen
873f6ccfea Add a simple Javascript example
This shows how to use a layout manager in a widget,
implemented in javascript. The example sets up the
environment for running from the toplevel dir, assuming
that the build dir is called 'build'.
2021-07-05 13:48:51 -04:00
Patrick Griffis
af15f5d004 Remove Google Cloud Print backend
This service was shut down at the start of 2021.

This helpfully removes any dependency on json-glib, librest (and libsoup).
2021-07-05 10:54:16 -05:00
Matthias Clasen
f328175e2f appchooserbutton: Make buttons activatable again
The activation is simply forwarded to the combobox
within.
2021-07-05 10:10:44 -04:00
Matthias Clasen
fc65d6393a colorbutton: Make color buttons activatable again
The activation is simply forwarded to the toggle button
within.
2021-07-05 10:10:19 -04:00
Matthias Clasen
271afb7eab font button: Make font buttons activatable again
The activation is simply forwarded to the toggle button
within.
2021-07-05 10:09:43 -04:00
Matthias Clasen
76133dbea7 menubutton: Make menu buttons activatable again
The activation is simply forwarded to the toggle button
within.

Fixes: #4079
2021-07-05 10:08:43 -04:00
Matthias Clasen
6efe31e6f5 Merge branch 'master' into 'master'
gdk: fix gtk app startup with 'g_value_set_boxed: assertion...

See merge request GNOME/gtk!3714
2021-07-05 02:45:54 +00:00
Matthias Clasen
9885bedb7d Merge branch 'matthiasc/for-master' into 'master'
widget-factory: Add a default button

Closes #3975

See merge request GNOME/gtk!3725
2021-07-04 13:46:13 +00:00
Matthias Clasen
b6edb517e4 Merge branch 'placeholder-visibility' into 'master'
text: Update placeholder visibility more often

Closes #4066

See merge request GNOME/gtk!3724
2021-07-04 03:14:38 +00:00
Matthias Clasen
f023695f31 docs: Fix various link formatting
Make links that gi-docgen can undestand.

Fixes: #3975
2021-07-03 23:11:48 -04:00
Matthias Clasen
749ea8c30c widget-factory: Add a default button
Mark one of the buttons in the message dialog
as default, so we can see how the default appears
visually.
2021-07-03 23:01:14 -04:00
Matthias Clasen
c79f289d67 text: Update placeholder visibility more often
We need to update the visibility of the placeholder
label when we create it, otherwise we can end up
with placeholder text on top of entry content.

Fixes: #4066
2021-07-03 22:15:38 -04:00
Matthias Clasen
e516ce428a Merge branch 'fix-filechooser-critical' into 'master'
filechooser: Avoid a critical

Closes #4077

See merge request GNOME/gtk!3722
2021-07-03 21:48:41 +00:00
Matthias Clasen
1ae259aecb Merge branch 'man-page-improvement' into 'master'
docs: Improve the gtk4-launch man page

Closes #4081

See merge request GNOME/gtk!3723
2021-07-03 19:51:39 +00:00
Matthias Clasen
c609e2fef9 docs: Improve the gtk4-launch man page
Be more precise about where desktop files are found.

Fixes: #4081
2021-07-03 15:23:36 -04:00
Matthias Clasen
8ff9c851ce filechooser: Avoid a critical
This was showing up when calling some filechooser api on
a native filechooser, where we use a filechooser dialog
behind the scenes, but it does not have focus.

Fixes: #4077
2021-07-03 15:15:06 -04:00
Matthias Clasen
5ef2b9fd54 Merge branch 'matthiasc/for-master' into 'master'
Cosmetics

See merge request GNOME/gtk!3721
2021-07-03 13:40:23 +00:00
Matthias Clasen
511dc7a182 Merge branch 'fix-gir' into 'master'
meson: Fix generate_gir() dependencies

See merge request GNOME/gtk!3701
2021-07-03 13:35:22 +00:00
Matthias Clasen
c668586caf Merge branch 'scrolling-menus' into 'master'
popovermenu: Scroll when necessary

See merge request GNOME/gtk!3717
2021-07-03 13:31:23 +00:00
Benjamin Otte
390447862a Merge branch 'rerename-mediastream' into 'master'
mediastream: Rename apis one more time

See merge request GNOME/gtk!3720
2021-07-03 13:28:35 +00:00
Matthias Clasen
7f2648a013 Cosmetics
Amend LD_PRELOAD instead of replacing it, so you can just
point it at the right libgtk-4.so while running squares.py
from elsewhere.
2021-07-03 09:10:27 -04:00
Matthias Clasen
3227aa2c45 mediastream: Rename apis one more time
Before we end up with names that we are unhappy with,
rename things one more time, and update all callers.
2021-07-03 09:05:33 -04:00
Matthias Clasen
c88dc98b7c Merge branch 'python-example' into 'master'
Add a simple python example

See merge request GNOME/gtk!3719
2021-07-03 02:03:16 +00:00
Matthias Clasen
ed5b42071c Add a simple python example
This shows how to do custom drawing in a widget,
implemented in python. The example sets up the
environment for running from the toplevel dir,
assuming that the build dir is called 'build'.
2021-07-02 21:31:32 -04:00
Matthias Clasen
804d9ee828 popovermenu: Scroll when necessary
Add a scrolled window to GtkPopoverMenu, so we can scroll
long menus when there is not enough room.
2021-07-02 13:19:02 -04:00
Matthias Clasen
a90f721b74 Merge branch 'wip/baedert/wat' into 'master'
gtkffmediafile: Fix deprecated API usage

See merge request GNOME/gtk!3716
2021-07-02 17:00:41 +00:00
Timm Bäder
106417ada7 gtkffmediafile: Fix deprecated API usage 2021-07-02 18:41:55 +02:00
hudeng
fd0d3283e0 gdk: fix gtk app startup with 'g_value_set_boxed: assertion G_VALUE_HOLDS_BOXED (value) failed error message' when xsettings use 'XSETTINGS_TYPE_COLOR' type 2021-07-02 17:23:56 +08:00
Matthias Clasen
3e63e683a9 Merge branch 'text-undo-test' into 'master'
Add another text history test

See merge request GNOME/gtk!3713
2021-07-01 22:25:18 +00:00
Matthias Clasen
e415f25c8f Add another text history test
Add a tests that checks we group undo actions as expected
when the user is typing.
2021-07-01 18:08:05 -04:00
Matthias Clasen
e596e1fa7d Merge branch 'wip/chergert/fix-texthistory-grouping' into 'master'
texthistory: hoist single actions from group

Closes gnome-text-editor#97

See merge request GNOME/gtk!3711
2021-07-01 14:17:25 +00:00
Christian Hergert
d8ab2e6d03 texthistory: hoist single actions from group
In many cases across GtkTextBuffer, we end up with operations performed
inside of a begin/end user action. Those can be coalesced into a single
sub-action within the group, and hoisted out of the group. Doing so
increases the chances that we chain similar actions together for words.

Additionally, this fixes an issue introduced in
6179886b14 for #3977 where GNOME Text Editor
started to group all possible actions into a single group.

Fixes GNOME/gnome-text-editor#97
2021-06-30 16:40:54 -07:00
Benjamin Otte
e9d3d3e3cf icontheme: Fix binding annotation 2021-06-30 18:55:25 +00:00
Matthias Clasen
3a5983e387 Merge branch 'wayland-cursor-theme' into 'master'
wayland: Look for cursor themes in $HOME

Closes #4080

See merge request GNOME/gtk!3708
2021-06-29 22:17:49 +00:00
Matthias Clasen
4efb661ae6 wayland: Look for cursor themes in $HOME
We should look in the same places that libXcursor does,
so add $XDG_DATA_HOME/icons and $HOME/.icons to the list.

Fixes: #4080
2021-06-29 16:57:15 -04:00
Matthias Clasen
bcdb9c937c Merge branch 'more-vbo-overflow' into 'master'
gsk: Use the right limit for batch size

See merge request GNOME/gtk!3707
2021-06-29 20:36:42 +00:00
Matthias Clasen
f45c0b9609 gsk: Another vbo_size overflow fix
We can overflow vbo_size not just by batching
too much, but also by producing humongous text
nodes. Split them up.
2021-06-29 15:22:40 -04:00
Matthias Clasen
9ea162034a gsk: Use the right limit for batch size
We use 16 bits, so G_MAXINT16 is one bit short.
Just make it explicit as 0xffff.
2021-06-29 15:21:45 -04:00
Matthias Clasen
192e779db2 Merge branch 'hello-world-fixup' into 'master'
Update hello-world.c

See merge request GNOME/gtk!3706
2021-06-29 16:59:45 +00:00
Matthias Clasen
bda7557783 Update hello-world.c
Simplify the code a bit and make the window
match the existing screenshot.
2021-06-29 08:01:37 -04:00
Matthias Clasen
dc50c7539a Merge branch 'avoid-batch-size-overflow' into 'master'
Revert "gsk: Respect max element vertices limitation"

See merge request GNOME/gtk!3704
2021-06-28 21:35:15 +00:00
Matthias Clasen
bf97dfd998 Merge branch 'wip/exalm/buttons' into 'master'
GtkMenuButton icon+arrow support + fixes

Closes #3501

See merge request GNOME/gtk!3694
2021-06-28 19:10:57 +00:00
Matthias Clasen
c7f4131402 Merge branch 'gtklistitemfactory-autocleanup' into 'master'
gtk: Define the GtkListItemFactory autocleanup func

See merge request GNOME/gtk!3703
2021-06-28 19:10:04 +00:00
Matthias Clasen
bd5e5beee0 gsk: Don't overflow vbo_count
We use 16 bits to store vbo_count, so we can't create
batches that have more than 65535 vertices. Pay attention
to that limit when merging batches.
2021-06-28 15:00:41 -04:00
Matthias Clasen
7a493f151d Revert "gsk: Respect max element vertices limitation"
This reverts commit f58fc6b22e.
2021-06-28 14:50:58 -04:00
Adrien Plazas
0ea73c384f gtk: Define the GtkListItemFactory autocleanup func 2021-06-28 14:01:57 +02:00
Emmanuele Bassi
d8c416e8b2 Merge branch 'ebassi/issues-4076' into 'master'
docs: Use code blocks for inline XML

Closes #4076

See merge request GNOME/gtk!3702
2021-06-27 15:10:15 +00:00
Emmanuele Bassi
9bf3724d25 docs: Use code blocks for inline XML
Otherwise the markdown renderer will just ignore them.

Fixes: #4076
2021-06-27 15:25:18 +01:00
Hugo Carvalho
fd49d39184 Update Portuguese translation
(cherry picked from commit a9c68757b5)
2021-06-27 09:45:19 +00:00
Xavier Claessens
0fd790eb8d Meson: Only g-ir-scanner warnings fatal when buit with -Dwerror=true
Also fix deprecation warning that requires using fatal_warnings kwarg
from Meson 0.55.0.

Fixes: #4072.
2021-06-25 11:38:11 -04:00
Xavier Claessens
b18e95d6b3 meson: Fix generate_gir() dependencies
There is no need to search for gir variables into subprojects, they are
part of dependencies objects, meson will find them there.
2021-06-25 10:08:36 -04:00
Alexander Mikhaylenko
47b5c68df4 menubutton: Don't hardcode label<->arrow spacing
This should come from the theme instead, as it does for icon<->arrow.
2021-06-24 23:13:01 +05:00
Alexander Mikhaylenko
ac3b246858 menubutton: Add a way to always show arrow with image buttons
Make sure the button still has the .image-button style class with an icon,
also add it to the initial state with only an arrow. Add a new
.arrow-button style class for the icon+arrow state so it's possible to
style it.

Remove spacing from the label+arrow variant to match, re-add it from the
stylesheet for both.

Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/3501
2021-06-24 23:12:26 +05:00
Alexander Mikhaylenko
51a754547e menubutton: Remove a random g_return_if_fail()
There's already one above.
2021-06-24 23:11:57 +05:00
Alexander Mikhaylenko
76df60db2b menubutton: Reset label when setting icon name and vice versa
Match GtkButton.
2021-06-24 23:06:46 +05:00
Alexander Mikhaylenko
f3befe530b button: Reset style classes when setting arbitrary children
Don't leave leftover .image-button or .text-button.
2021-06-24 23:06:46 +05:00
Matthias Clasen
59d4333e23 Merge branch 'wip/sadiq/reveal-controls-on-touch' into 'master'
video: Reveal controls on tap

See merge request GNOME/gtk!3648
2021-06-24 15:11:33 +00:00
Matthias Clasen
92177d9663 Merge branch 'wip/chergert/gdk-macos-gdkdrop' into 'master'
GdkDrop suport for macOS backend

See merge request GNOME/gtk!3683
2021-06-24 15:03:19 +00:00
Matthias Clasen
6a29b64850 Merge branch 'dnd-fixes' into 'master'
dnd: Add another assertion

See merge request GNOME/gtk!3689
2021-06-24 15:01:29 +00:00
Matthias Clasen
73cb60d053 Merge branch 'ebassi/filechooser-no-trash' into 'master'
Never show the Trash in the FileChooserWidget side bar

Closes #674

See merge request GNOME/gtk!3692
2021-06-24 14:59:43 +00:00
Matthias Clasen
47bd998e94 Merge branch 'checkbutton-release-outside' into 'master'
checkbutton: Match GtkButton behavior

Closes #4061

See merge request GNOME/gtk!3691
2021-06-24 14:58:42 +00:00
Matthias Clasen
e2cfa7bd11 Merge branch 'fix_tests_testdnd' into 'master'
make testdnd trashcan work again

See merge request GNOME/gtk!3700
2021-06-24 14:54:32 +00:00
Matthias Clasen
006633082d Merge branch 'macos-input-method' into 'master'
macos: fix the position of curosr of input method for macos.

Closes #4063

See merge request GNOME/gtk!3699
2021-06-24 14:50:59 +00:00
Caolán McNamara
bbf7454fc9 make testdnd trashcan work again
so that dragging into the 'trashcan' is detected
2021-06-23 15:09:44 +01:00
Emmanuele Bassi
85cb5509c4 Merge branch 'gtklistitem-autocleanup' into 'master'
gtk: Define the GtkListItem autocleanup func

See merge request GNOME/gtk!3698
2021-06-23 13:09:28 +00:00
Emmanuele Bassi
0e29f52841 Merge branch 'migration_patch' into 'master'
Add section about `gtk_widget_set_app_paintable`

Closes #4007

See merge request GNOME/gtk!3641
2021-06-23 13:08:07 +00:00
Jaap aarts
02893e37d3 Add section about gtk_widget_set_app_paintable 2021-06-23 13:08:06 +00:00
Zhi
1dbb5188ba macos: fix the position of curosr of input method for macos.
In the refactoring from GdkWindow to GdkSurface, GtkWidget no longer
corresponds to a GdkSurface. We have to calculate the relative position
from GtkWidget to the GdkSurface.

Closes #4063.
2021-06-22 22:57:34 +08:00
Adrien Plazas
a4d35ace78 gtk: Define the GtkListItem autocleanup func 2021-06-22 09:43:16 +02:00
Carlos Garnacho
981a638b01 Merge branch 'fix-pointer-gestures-kde-plasma' into 'master'
gdk/wayland: Fix pointer-gestures version selection

See merge request GNOME/gtk!3693
2021-06-21 21:35:06 +00:00
Vlad Zahorodnii
3969d8b028 gdk/wayland: Fix pointer-gestures version selection
version == GDK_ZWP_POINTER_GESTURES_V1_VERSION will fail if the
compositor implements version 2 of pointer-gestures-v1.
2021-06-21 09:51:45 +03:00
Emmanuele Bassi
889709213e Never show the Trash in the FileChooserWidget side bar
The Trash is a special location: files cannot be copied or moved, there,
and the file selection dialog is not able to restore files from the
Trash.

Fixes: #674
2021-06-20 15:44:22 +01:00
Emmanuele Bassi
333a92bcff Revert "Never show the Trash in the FileChooserWidget side bar"
This reverts commit cd39e417e1.
2021-06-20 15:41:43 +01:00
Emmanuele Bassi
cd39e417e1 Never show the Trash in the FileChooserWidget side bar
The Trash is a special location: files cannot be copied or moved, there,
and the file selection dialog is not able to restore files from the
Trash.

Fixes: #674
2021-06-20 15:39:41 +01:00
Matthias Clasen
1cebf406aa docs: Fix a typo 2021-06-19 14:14:57 -07:00
Matthias Clasen
d7915fbca8 docs: Add a section about Drag-and-Drop 2021-06-19 14:14:57 -07:00
Matthias Clasen
9169315cc1 Merge branch 'wip/chergert/textview-access-to-contexts' into 'master'
textview: give application developers access to RTL and LTR context

See merge request GNOME/gtk!3690
2021-06-19 20:36:44 +00:00
Matthias Clasen
3b70cd3226 checkbutton: Match GtkButton behavior
When leaving the widget before releasing the button,
we should not activate the checkbutton, to match the
way GtkButton behaves.

Fixes: #4061
2021-06-19 13:30:31 -07:00
Christian Hergert
a6101f0181 textview: give application developers access to RTL and LTR context
This allows developers to modify the pango context that is used when
rendering text within the text view.

Such access can be useful to alter how rounding occurs with API such as
pango_context_set_round_glyph_positions() and is needed by GtkSourceView
for proper placement of glyphs within the overview map.
2021-06-19 12:28:18 -07:00
Matthias Clasen
92c6485adf docs: Tweak wording
Instead of drag'n'drop, say drag-and-drop. That is easier
to read, and less unclear on the markdown syntax implications.
2021-06-19 08:03:47 -07:00
Matthias Clasen
4df9314039 wayland: Fix some dnd corner case
We must call gdk_drag_drop_done() when the drag ends,
successfully or not. Without this, we get an unwarranted
emission of ::cancel after a successful drop.

Since only the first call to gdk_drag_drop_done() is taking
effect, it is safe to call as a fallback, after emitting
::dnd-finished. If the application connects to that signal
and calls gdk_drag_drop_done() itself, its call will take
precedence.

This matches what the X11 implementation does.
2021-06-19 08:03:21 -07:00
Matthias Clasen
c8ad4d5deb dnd: Add another assertion
Assert that gdk_drop_finish() is called after the
drop is performed.
2021-06-19 07:50:41 -07:00
Matthias Clasen
13a2db2238 Merge branch 'fix-3798' into 'master'
GDK-Win32: Fix drag surface positioning (issue #3798)

Closes #3798

See merge request GNOME/gtk!3659
2021-06-18 17:31:51 +00:00
Matthias Clasen
e8f9fb0f86 Merge branch 'gsk-big-batches' into 'master'
ci: Build Broadway on MacOS

See merge request GNOME/gtk!3686
2021-06-18 17:00:58 +00:00
Matthias Clasen
634bd2de48 Merge branch 'matthiasc/for-master' into 'master'
ci: Build Broadway on MacOS

See merge request GNOME/gtk!3685
2021-06-18 14:09:49 +00:00
Matthias Clasen
f58fc6b22e gsk: Respect max element vertices limitation
We are pretty good at batching commands now, and we can easily
produce batches that exceed the maximum number of elements per
draw call that the hw can handle. Query that number, and respect
it when merging batches.

This fixes the rendering of the overview map in GtkSourceView.
2021-06-18 06:50:59 -07:00
Matthias Clasen
fb052c8d25 ci: Build Broadway on MacOS
We've seen a build failure if Broadway is built without
the X11 backend. Lets recreate that configuration in ci
so it doesn't break again.
2021-06-18 06:09:14 -07:00
Chun-wei Fan
e35490ba5b gdkdrag-win32.c: Fix drag surface positioning
Determine the root_x and root_y coordinates of the drag surface by
relying on the coordinates of the surface where the drag is being
carried out, plus the coordinates that we receive from the drag event,
which is in-line with what the X11 backend does.

This will prevent the drag surface from being initially drawn at the
correct position, but jumping towards the top-left corner of the screen
shortly afterwards.

The DnD support will still need some more updates to function correctly
on Windows, but at least this is a small improvement.

Fixes issue #3798.
2021-06-18 18:07:50 +08:00
Matthias Clasen
be1b979e51 Merge branch 'matthiasc/for-master' into 'master'
treeviewcolumn: Clip header buttons

Closes #4045

See merge request GNOME/gtk!3682
2021-06-18 04:37:48 +00: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
6c1dce2878 macos: make pasteboard usage reusable
We will want to be able to reuse the pasteboard reading code from
the macOS DnD drop backend. This just removes the pasteboard
bits from the implementation and allows that to be passed in as in
both clipboard and DnD cases we'll have a specific NSPasteboard
to read from.
2021-06-17 17:19:19 -07:00
Christian Hergert
ad1260505d macos: check for GdkMacosBaseView before using as such
We can get events for external windows such as those from native
file chooser dialogs.
2021-06-17 17:18:19 -07:00
Matthias Clasen
d92f8a1b8e treeviewcolumn: Clip header buttons
We don't want to overdraw when dragging a narrow column
around, and we also need the clipping to avoid picking
the wrong column, when a later column button overlaps
an earlier one.

Fixes: #4045
2021-06-17 17:14:14 -07:00
Matthias Clasen
22827f2cc7 macos: Fix a compiler warning 2021-06-17 17:14:14 -07:00
Christian Hergert
b64370cd48 macos: move drag motion to GdkMacosDrag
This doesn't help to be pushed off into the surface, as it makes things
more different than the X11 implementation.
2021-06-17 13:24:39 -07:00
Christian Hergert
6c8e176cc0 macos: fix position of drag surface 2021-06-17 13:23:38 -07:00
Christian Hergert
057bda6cd7 macos: register known clipboard types for drag destination 2021-06-17 13:23:18 -07:00
Matthias Clasen
8df2cce5c1 Merge branch 'wip/chergert/fix-broadway-build' into 'master'
inspector: fix compilation with broadway

See merge request GNOME/gtk!3681
2021-06-17 19:45:16 +00:00
Christian Hergert
352898ae9e inspector: fix compilation with broadway 2021-06-17 11:54:00 -07:00
Matthias Clasen
1bda665662 Merge branch 'matthiasc/for-master' into 'master'
action muxer fixes

See merge request GNOME/gtk!3678
2021-06-17 17:53:16 +00:00
Hugo Carvalho
fad4c60499 Update Portuguese translation
(cherry picked from commit 807537dd5d)
2021-06-17 14:44:54 +00:00
Matthias Clasen
47bb556327 testsuite: Avoid a compiler warning
This was showing up in ci on macos.
2021-06-17 09:37:45 -04:00
Matthias Clasen
4d00f1903a widget-factory: Show Ctrl-? in the menu
We use our own action for showing the shortcuts window,
so we need to associate this shortcut with our action
for it to show up.
2021-06-17 08:59:30 -04:00
Matthias Clasen
7344a03aa3 shortcutcontroller: Don't reinject menu accels
The normal way to associate accels with actions is
to attach a shortcut controller to the widget. The shorcut
controller will inject the accel into the action muxer
tree, so that it can get displayed in widgets that activate
the action (say, in menus.

This approach does not works for generated menus, since the
widgets are not in the hands of the app developer, so attaching
shortcut controllers to them is impractical.

Instead, GtkModelButton has an accel property that gets
bound to the accel coming from the action muxer tree (most
likely put there via gtk_application_set_accel_for_action),
and creates a shortcut controller itself.

The change in this commit is to prevent the shortcut controller
from injecting the accel into the action muxer tree in this case.
Otherwise, the accels get 'stuck' and we won't update them if the
global accels are later changed.

This is a hack, and needs a better solution.
2021-06-17 08:50:26 -04:00
Matthias Clasen
64af90111e window: Propagate accel changes
When the global accels change, tell the
shortcut controller to re-inject them into
the action muxer hierarchy.
2021-06-17 08:50:26 -04:00
Matthias Clasen
3254a3feab shortcutcontroller: Add a way to update accels
This will be used to make accel changes propagate.
2021-06-17 08:50:26 -04:00
Matthias Clasen
d5054f9b99 action muxer: Propagate registrations further up
We were pretty aggressive about not registering
observers further than necessary, stopping at the
first muxer that provides an action.

But even though action changes further up in the tree
won't be relevant in that case, we need to listen to
accel changes, since they may come from higher up
in the tree (e.g. when using
gtk_application_set_accels_for_action with an action
that is defined on a widget.

So, register all the way to the top, and stop propagating
action changes when we hit a muxer that provides the action.
2021-06-17 08:50:26 -04:00
Matthias Clasen
db93090ea8 menutrackeritem: Be more careful with accel changes
In some cases (such as when getting a new parent), the
action muxer doesn't know exactly which detailed actions
have changed accels, so we call primary_accel_changed with
just an action name.

Make the menu tracker item handle that case by matching
either against the detailed name or the the action name.
2021-06-17 08:50:26 -04:00
Matthias Clasen
15c65595b8 action muxer: Propagate accel changes
When we set a new parent on an action muxer,
accels may change, so call primary_accel_changed
for involved actions.
2021-06-17 08:50:26 -04:00
Benjamin Otte
e59e9ad6a9 Merge branch 'wip/otte/for-master' into 'master'
spinner: Behave like any other icon

See merge request GNOME/gtk!3677
2021-06-17 11:47:28 +00:00
Benjamin Otte
e6c4dbfc6d spinner: Behave like any other icon
Take the size from -gtk-icon-size.

Note that min-width/height still works, as those properties are handled
by the generic widget sizing machinery in GTK4.
2021-06-17 12:54:56 +02:00
Matthias Clasen
424dd8a463 actionobserver: Clarify primary_accel_changed docs
Either action_name or action_and_target may be NULL
here, and observer implementations should be careful
when checking those values.
2021-06-16 10:34:37 -04:00
Matthias Clasen
7b1a7629bc print-editor: Make accels work
Sadly, they don't show up anymore with this.
2021-06-16 10:17:49 -04:00
Matthias Clasen
df1116a010 bloatpad: Add icons as resources
This can serve as a useful example for how to add
themed icons as resources.
2021-06-16 09:35:00 -04:00
Matthias Clasen
11916bac7e bloatpad: Give the toolbar a facelift
Make it look more like a toolbar.
2021-06-16 09:26:15 -04:00
Matthias Clasen
d675ae5cc5 bloatpad: Improve accel dialog
Make this dialog a bit less of an eyesore.
2021-06-16 09:09:24 -04:00
Matthias Clasen
43eeff8f15 examples: Use existing icons
The sunny icon doesn't exist anymore.
2021-06-16 08:45:04 -04:00
Matthias Clasen
ece9e7e240 examples: Drop a redundant frame
The frame in the drawing example adds nothing
and looks wrong.
2021-06-16 08:40:01 -04:00
Matthias Clasen
1abbf00dcf Merge branch 'fix-3793' into 'master'
gdksurface-win32.c: Fix up popup placement (fix issue #3793)

Closes #3793

See merge request GNOME/gtk!3674
2021-06-16 10:08:52 +00:00
Matthias Clasen
10564514e8 Merge branch 'media-stream-name-collision' into 'master'
mediastream: Some more api renaming

Closes #4023

See merge request GNOME/gtk!3673
2021-06-16 10:07:29 +00:00
Chun-wei Fan
ba7ec29dc0 gdksurface-win32.c: Fix up popup placement
If we are undergoing a surface move, just apply the next_layout anyways,
even if we are not moving a toplevel surface.

Update the way how we obtain the x and y coordinates of a surface, if it
is a toplevel, apply the x and y coordinates from the results from we
obtained the underlying Win32 HWND, as we did before.  But if it is a
popup, use gdk_win32_surface_get_geometry() to obtain the correct x and
y coordinates to place our popup surface.

Also correct how we compute the shadow dimensions, and the final popup
rectangle as we attempt to layout the popup surface, since GDK-Win32
keeps track of the shadow dimensions in system (unscaled) units, not GDK
units.

Fixes issue #3793.
2021-06-16 16:25:29 +08:00
Chun-wei Fan
85b595bd14 gdksurface-win32.c: Fix formatting for popup functions 2021-06-16 15:02:56 +08:00
Matthias Clasen
56c486abbf Merge branch 'drop-target-name-collision' into 'master'
droptarget: Rename :drop to :current-drop

Closes #4028

See merge request GNOME/gtk!3669
2021-06-16 00:12:53 +00:00
Matthias Clasen
96fc5dc3a7 mediastream: Some more api renaming
Also rename gtk_media_stream_ended to
gtk_media_stream_set_ended, to avoid naming
collision with GtkMediaStream:ended.

The existing entry points still exist, deprecated
and marked as non-introspectable.

Update all internal uses.

Fixes: #4023
2021-06-15 18:33:23 -04:00
Matthias Clasen
b09087d634 droptarget: Rename :drop to :current-drop
Rename the GtkDropTraget:drop property to :current-drop,
to avoid naming collision with the signal of the same
name.

We leave the old property and getter in place, deprecated
and marked as non-introspectable.

Fixes: #4028
2021-06-15 18:21:28 -04:00
Matthias Clasen
5e99513507 Merge branch 'cherry-pick-4ba89f25' into 'master'
cellarea: Don't shrink area too much

See merge request GNOME/gtk!3672
2021-06-15 20:29:28 +00:00
Matthias Clasen
0a9d2f248e Merge branch 'label-underline-markup' into 'master'
label: Fix mnemonic handling

Closes #4041

See merge request GNOME/gtk!3670
2021-06-15 19:43:40 +00:00
Benjamin Otte
16ff055b42 cellarea: Don't shrink area too much
Do not compute rectangles with negative width/height. This avoids
assertion failures further down when those rectangles were actually
checked.

https://bugzilla.redhat.com/show_bug.cgi?id=1962215


(cherry picked from commit 4ba89f25b8)
2021-06-15 18:00:25 +00:00
Matthias Clasen
89f57d4ff6 Add a mnemonic testcase
Add a testcase that tests the label mnemonic handling
that was fixed in the previous commit.
2021-06-15 13:32:31 -04:00
Matthias Clasen
c4a2234a28 label: Fix mnemonic handling
We were not handling the case right in which we
want to use underlines, but not use markup. Since
we are now using pango_parse_markup for this case,
we need to escape the xml markup.

Fixes: #4041
2021-06-15 13:06:10 -04:00
Matthias Clasen
a3882763d8 Revert "progressbar: Avoid redundant storage"
This reverts commit 95747b1a40.

This was wrong - it turns out that while GtkProgressBar
allows you to change its orientation, its box layout is
always vertical.

Fixes: #4037
2021-06-15 07:37:57 -04:00
Emin Tufan Çetin
787fa6bd0d Update Turkish translation 2021-06-15 09:02:34 +00:00
Matthias Clasen
a6b4e53dca Merge branch 'macos-input-method' into 'master'
fix: make input method work again in gtk4

Closes #3968

See merge request GNOME/gtk!3668
2021-06-14 19:20:06 +00:00
Matthias Clasen
00d25ae89c Merge branch 'media-stream-name-collision' into 'master'
mediastream: Rename an api to avoid name collisions

Closes #4023

See merge request GNOME/gtk!3667
2021-06-14 18:44:10 +00:00
Zhi
5776fcd955 fix: make the new nsview as the first responder.
Make the new view as the first responder(focused) so the new view can
accept events from input method.

Fixes #3968.
2021-06-15 00:09:46 +08:00
Matthias Clasen
86b5dba43b mediastream: Rename an api to avoid name collisions
Some bindings can't handle the coexistence of
GtkMediaStream:prepared and gtk_media_stream_prepared.
Help them out by renaming the function to
gtk_media_stream_set_prepared, and rename
gtk_media_stream_unprepared as well, to match.

The existing entry points still exist, deprecated.

Update all internal uses.

Fixes: #4023
2021-06-14 07:50:12 -04:00
Matthias Clasen
e888364d3c Merge branch 'columnview-double-activation' into 'master'
listitemwidget: Claim gesture when activating

Closes #4015

See merge request GNOME/gtk!3663
2021-06-14 10:39:43 +00:00
Matthias Clasen
276f85c9e3 listitemwidget: Claim gesture when activating
Claim the gesture when we are activating a list item.

Otherwise we end up with double activations in
columnviews: first GtkColumnViewCell handles
the event, and then GtkListItemWidget handles
it again.

Fixes: #4015
2021-06-13 08:03:39 -04:00
Matthias Clasen
68eb422333 listitemwidget: Match activation conditions
Make the conditions used for activation in the single-
and double-click case properly match, so that it is
obvious that we won't trigger both of them.
2021-06-13 08:02:06 -04:00
Matthias Clasen
c0f54f899d Merge branch 'filename-annotations' into 'master'
Add type annotations for filename arguments

Closes #633

See merge request GNOME/gtk!3665
2021-06-13 11:38:50 +00:00
Matthias Clasen
65212535df Merge branch 'msvc-fix' into 'master'
Fix illegal instruction crash on x64 CPUs without POPCNT instruction when compiled with MSVC

See merge request GNOME/gtk!3664
2021-06-13 11:38:22 +00:00
Sebastian Cherek
106ac7c782 Update gtkpopcountprivate.h: undefined macro outside msvc 2021-06-12 17:35:13 +00:00
scherek
bc7b6a0e53 Dropped defined() for readability 2021-06-12 19:10:11 +02:00
scherek
e5b89569fd Replaced && with || for POPCNT checks to fix the logic. 2021-06-12 17:32:19 +02:00
Matthias Clasen
938bfff3dd Add type annotations for filename arguments
Add missing "(type filename)" annotations for string
arguments that are filenames.

Fixes: #633
2021-06-12 11:12:06 -04:00
scherek
6835fcf3cf Fix illegal instruction crash on x64 CPUs without POPCNT instruction when compiled with MSVC 2021-06-12 16:18:26 +02:00
Matthias Clasen
2554ee27d9 Merge branch 'listmodel-get-item' into 'master'
docs: Mention the GtkWidget.destroy vfunc

Closes #4024

See merge request GNOME/gtk!3662
2021-06-11 19:56:06 +00:00
Matthias Clasen
007cdf8787 Add tests for empty list models
Test that all our models return NULL for out-of-range
get_item calls, as expected.
2021-06-11 15:38:20 -04:00
Matthias Clasen
a526daf310 selectionfiltermodel: Fix an oversight
When the position is out of range, get_item needs
to return NULL.

Fixes: #4024
2021-06-11 15:37:16 -04:00
Matthias Clasen
ee34e1acc5 docs: Mention the GtkWidget.destroy vfunc
Mention GtkWidget.destroy in the migration guide.
2021-06-11 10:11:53 -04:00
Matthias Clasen
a08fbfa586 docs: Fix a typo in the migration guide 2021-06-11 07:52:30 -04:00
Matthias Clasen
d29f57fd1d Merge branch 'wip/chergert/fix-delayed-focus' into 'master'
window: clear move_focus when focus is already set

See merge request GNOME/gtk!3658
2021-06-10 21:31:47 +00:00
Christian Hergert
a4c5d1d94d window: clear move_focus when focus is already set
This can get set in other places, so we need to ensure it is cleared so
that an after-paint handler does not move the focus to a new widget.
2021-06-10 14:01:41 -07:00
Matthias Clasen
17f1bb1632 Merge branch 'actionable-fixes' into 'master'
tests: Fix check vs toggle button confusion

Closes #4022

See merge request GNOME/gtk!3656
2021-06-10 13:30:25 +00:00
Matthias Clasen
3418504b4b checkbutton: Fix actionable state tracking
If we have a GAction as model, we just have to
call gtk_action_helper_activate() and let
the action helper handle the state updates,

Fixes: #4022
2021-06-10 08:38:12 -04:00
Matthias Clasen
0a78a592ff togglebutton: Fix actionable state tracking
If we have a GAction as model, we just have to let
the action helper handle the state updates. GtkButton
already calls gtk_action_helper_activate() for us.
2021-06-10 08:36:08 -04:00
Matthias Clasen
208c527fb3 button: Add a private getter for the action helper
GtkToggleButton needs to know if it needs to actively
maintain its state, or defer to the action helper.
2021-06-10 08:36:01 -04:00
Matthias Clasen
28990285e2 testgaction: Add more widgetry
Add some toggle and check buttons to test that they
work as expected as GtkActionables.
2021-06-10 08:10:25 -04:00
Matthias Clasen
c7ad8d29e9 Fix the GAction test
We weren't setting the state of the stateful actions.
2021-06-10 08:10:08 -04:00
Matthias Clasen
dba8d1ff77 tests: Fix check vs toggle button confusion
Check buttons aren't toggle buttons anymore.
2021-06-10 07:49:08 -04:00
Matthias Clasen
143770f16d 4.3.1 2021-06-09 18:23:47 -04:00
Matthias Clasen
8a890238f5 Merge branch 'ebassi/docs-for-master' into 'master'
docs: Mention Window::close-request in the migration guide

See merge request GNOME/gtk!3655
2021-06-09 17:30:02 +00:00
Emmanuele Bassi
71be3a8de1 docs: Mention the ::damage-event signal in the migration guide
There is no replacement for damage event tracking.
2021-06-09 18:11:10 +01:00
Emmanuele Bassi
17373c3e77 docs: Mention GdkSurface:mapped
It replaces the ::map-event and ::unmap-event signals on GtkWidget.
2021-06-09 18:08:31 +01:00
Emmanuele Bassi
078ada75d4 docs: Mention Window::close-request in the migration guide
The Widget::delete-event signal was moved to Window::close-request.
2021-06-09 18:03:12 +01:00
Matthias Clasen
51a60b88b7 Merge branch 'ci-install-build' into 'master'
Make a standalone hello world

See merge request GNOME/gtk!3652
2021-06-09 12:59:46 +00:00
Matthias Clasen
193903ce4a ci: Update the image
v32 of the image includes wayland-protocols 1.21, and
other updates from Fedora 34.

While we are at it, drop gtk-doc from the image, and drop
the separate DOCS_IMAGE - no longer used.
2021-06-09 08:42:37 -04:00
Matthias Clasen
386002597b ci: Collect hello build logs 2021-06-09 08:42:30 -04:00
Matthias Clasen
e5a6d4a1c8 ci: Test building against installed GTK
This is meant to ensure that we e.g. install the
right header files, and so on.
2021-06-09 08:42:30 -04:00
Matthias Clasen
06caa57f9a Make a standalone hello world
We want to test building against the installed GTK
in ci, so lets add a standalone project.
2021-06-08 17:41:11 -04:00
Matthias Clasen
5ef6944a41 Merge branch 'row-activated-annotation' into 'master'
treeview: Add a few missing annotations

Closes #3828

See merge request GNOME/gtk!3647
2021-06-08 17:17:45 +00:00
Matthias Clasen
2e415e266f Merge branch 'wip/carlosg/spin-button-swipe-gesture' into 'master'
spinbutton: Connect swipe gesture to the text entry

Closes #4008

See merge request GNOME/gtk!3649
2021-06-08 14:54:26 +00:00
Zhi
970bb804de fix: replace deprecated metods.
Use NSInputContext to replace NSInputManager, which has been deprecated
since 10.6.

Sync from 0e30a96 in gtk3.
2021-06-08 22:47:53 +08:00
Carlos Garnacho
915388cfdb spinbutton: Mind the step in the swipe gesture
The swipe gesture forces values in the spin button that are
"impossible" according to the adjustment. This can break things
in creative ways.

Ensure the steps provided are always multiples of the adjustment
step value, and keep the remainder for further interaction.
2021-06-08 15:18:14 +02:00
Carlos Garnacho
1bf7f5eacb spinbutton: Connect swipe gesture to the text entry
In the GTK3 days, the spin button was an entry, with buttons on
top, and the swipe gesture affected the input on the entry bits.
Now the spin button is a container, so this gesture in the capture
phase applies to all contained children (incl. buttons).

Attach this gesture to the entry itself, so the buttons are left
outside this business. The gesture is still in the capture phase
in order to prevent text selection/edition/etc to happen.

Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4008
2021-06-08 15:17:56 +02:00
Matthias Clasen
6a86acb9ce Apply 1 suggestion(s) to 1 file(s) 2021-06-08 12:59:57 +00:00
Matthias Clasen
e35e7bcd4a Apply 1 suggestion(s) to 1 file(s) 2021-06-08 12:59:38 +00:00
Mohammed Sadiq
517b5173f9 video: Reveal controls on tap
So that the controls shall be shown on touch
2021-06-08 18:06:51 +05:30
Matthias Clasen
37acfcfcd5 Merge branch 'password-entry-buffer' into 'master'
Install gtkpasswordentrybuffer.h

See merge request GNOME/gtk!3646
2021-06-08 12:09:01 +00:00
Matthias Clasen
c2f2a45227 treeview: Documentation tweaks 2021-06-08 07:59:47 -04:00
Matthias Clasen
621e0a13e9 Install gtkpasswordentrybuffer.h 2021-06-08 07:49:42 -04:00
Matthias Clasen
92fcd37a19 Merge branch 'password-entry-buffer' into 'master'
Make GtkPasswordEntryBuffer public

See merge request GNOME/gtk!3645
2021-06-08 11:25:12 +00:00
Matthias Clasen
d8bde48b87 Make GtkPasswordEntryBuffer public 2021-06-08 11:25:11 +00:00
Matthias Clasen
825ffb9422 Merge branch 'ebassi/issue-3892' into 'master'
a11y: Update the level property for tree expanders

Closes #3892

See merge request GNOME/gtk!3470
2021-06-07 18:10:12 +00:00
Emmanuele Bassi
046ef010b3 Merge branch 'glib-main' into 'master'
subprojects: Use GLib main branch

See merge request GNOME/gtk!3642
2021-06-07 14:53:04 +00:00
Philip Withnall
b71ec6cb59 subprojects: Use GLib main branch
GLib upstream has renamed its `master` branch to `main`.

See https://gitlab.gnome.org/GNOME/glib/-/issues/2348.

Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
2021-06-07 14:56:49 +01:00
Matthias Clasen
b1beb3650b treeview: Add a few missing annotations
gtk_tree_view_row_activated and the ::row-activated signal
can (and do) receive NULL for the column occasionally.

This is an introspection api change.

Fixes: #3828
2021-06-06 08:24:52 -04:00
Matthias Clasen
fca19e72ad Merge branch 'matthiasc/for-master' into 'master'
Docs: Tweaks

Closes #3638

See merge request GNOME/gtk!3639
2021-06-05 22:13:21 +00:00
Matthias Clasen
98d2320c93 gtk-builder-tool: Replace can-focus with focusable
The focusable property has the meaning that can-focus had
in GTK 3.

Update tests, and mention this in the migration guide.

Fixes: #3638
2021-06-05 17:56:35 -04:00
Matthias Clasen
effc7a619d Docs: Tweaks
Remove some more redundant "or NULL" blurbs.
2021-06-05 17:38:23 -04:00
Matthias Clasen
0ec017fcc0 Merge branch 'matthiasc/for-master' into 'master'
popovermenu: doc tweaks

See merge request GNOME/gtk!3638
2021-06-05 21:36:06 +00:00
Matthias Clasen
94ad177176 popovermenu: doc tweaks 2021-06-05 17:19:39 -04:00
Matthias Clasen
4616104742 Merge branch 'submenu-action-fixes' into 'master'
Submenu action fixes

Closes #3721

See merge request GNOME/gtk!3272
2021-06-05 13:36:10 +00:00
Matthias Clasen
a3a24b81c8 Merge branch 'msvc-aarch64' into 'master'
gtkpopcountprivate.h: Fix build on ARM/aarch64 Visual Studio

See merge request GNOME/gtk!3637
2021-06-05 13:05:15 +00:00
Matthias Clasen
debcc62775 menusectionbox: Fix submenu-action for nested menus
We were not updating the state of submenu-actions
for nested submenus.

Fixes: #3721
2021-06-05 08:49:18 -04:00
Matthias Clasen
b11f31afea popovermenubar: Make submenu-actions work
We were not updating submenu-action state
for items in menubars.
2021-06-05 08:49:17 -04:00
Matthias Clasen
db2e5648c9 menutrackeritem: Make submenu-actions work again
This broke when GtkActionMuxer stopped being a
GActionGroup.
2021-06-05 08:49:17 -04:00
Matthias Clasen
46d1f04a7c bloatpad: Bring back the menubar
This was lost at some point.
2021-06-05 08:49:17 -04:00
Matthias Clasen
fe774c1ad8 Merge branch 'powimod_icon' into 'master'
Load icon from executable on Windows

Closes #3713

See merge request GNOME/gtk!3326
2021-06-05 12:47:08 +00:00
Chun-wei Fan
08ee36e7c4 gtkpopcountprivate.h: Fix build on ARM/aarch64 Visual Studio
__popcnt() is not supported for ARM nor ARM64 Visual Studio builds, so we must
use the fallback implementation as intrinsics are not supported for this
purpose on ARM/ARM64 Visual Studio builds.
2021-06-05 15:41:14 +08:00
Matthias Clasen
1605ec0a44 Merge branch 'ci-file-filters' into 'master'
GtkFileFilter: Allow case-insensitive patterns

Closes #3705

See merge request GNOME/gtk!359
2021-06-05 01:47:24 +00:00
Matthias Clasen
4b46e11b22 Merge branch 'imcontext-ignore-more-keysyms' into 'master'
imcontext: Ignore more keysyms

See merge request GNOME/gtk!3634
2021-06-05 01:19:39 +00:00
Matthias Clasen
9993e91add Add GtkFileFilter tests 2021-06-04 21:10:01 -04:00
Matthias Clasen
9ac22c1088 GtkFileFilter: Add suffix matches
This is less flexible than a glob pattern, but it is
explicitly case-insensitive, to match the behavior
on Windows.

Fixes: #3705
2021-06-04 21:10:01 -04:00
Matthias Clasen
47400e4bd8 Add a helper to make case-insensitive globs
This will be used in GtkFileFilter in the future.

Tests included.
2021-06-04 21:10:01 -04:00
Matthias Clasen
8981ba4bd2 imcontext: Ignore more keysyms
It finally dawned on my that #3673 is just another
case of unexpected keysyms getting sent our way via
fringe XKB features.

Ignore them all!
2021-06-04 19:01:57 -04:00
Matthias Clasen
74a41eeb70 Merge branch 'matthiasc/for-master' into 'master'
docs: Mention <packing> in migration guide

Closes #3950 and #2271

See merge request GNOME/gtk!3630
2021-06-04 20:24:23 +00:00
Matthias Clasen
ff874318c0 Merge branch 'master' into 'matthiasc/for-master'
# Conflicts:
#   docs/reference/gtk/migrating-3to4.md
2021-06-04 20:24:09 +00:00
Matthias Clasen
a4598567b9 icontheme: Add detail to the 'not found' message
Name the icon theme we're using.

Fixes: #2271
2021-06-04 09:49:05 -04:00
Matthias Clasen
8f95661167 Clean up some comments
These XXX comments aren't useful enough to keep.
2021-06-04 09:49:05 -04:00
Matthias Clasen
e437c55142 Add a doc comment for gsk_rounded_rect_is_circular 2021-06-04 09:49:05 -04:00
Matthias Clasen
ff01067b8b Merge branch 'matthiasc/for-master' into 'master'
docs: Mention <packing> in migration guide

Closes #3950

See merge request GNOME/gtk!3629
2021-06-04 13:21:37 +00:00
Matthias Clasen
7f4630abac wayland: Add a comment
I just had to debug this to rediscover how it works, so
add a comment for next time.
2021-06-04 08:30:52 -04:00
Matthias Clasen
4c9bd6ed9a wayland: Add a comment
I just had to debug this to rediscover how it works, so
add a comment for next time.
2021-06-04 08:29:23 -04:00
Matthias Clasen
b6cd97be1e docs: Escape some xml tags
When mentioning xml tags in markdown, we must write
them as `<foo>`, or they will come out mangled.
2021-06-04 08:06:18 -04:00
Matthias Clasen
c4cbd6ec1b docs: Mention <packing> in migration guide
Add another hint for what to do with child properties.

Fixes: #3950
2021-06-04 07:59:07 -04:00
Matthias Clasen
312289fb11 docs: Mention <packing> in migration guide
Add another hint for what to do with child properties.

Fixes: #3950
2021-06-04 07:42:21 -04:00
Matthias Clasen
036dd60a4e Merge branch 'matthiasc/for-master' into 'master'
fnmatch: Support case-folding

See merge request GNOME/gtk!3628
2021-06-04 04:43:20 +00:00
Matthias Clasen
10c6c93f40 Merge branch 'gtk_combo_box_with_entry_docs_update' into 'master'
Documentation update for combo_box_new_with_entry

See merge request GNOME/gtk!3605
2021-06-04 04:02:48 +00:00
DarkTrick
4d894e08f7 Documentation update for combo_box_new_with_entry 2021-06-04 04:02:48 +00:00
Matthias Clasen
31407d0a4c Move fnmatch testcases to the testsuite
We have a well-working way to test internal
apis now, lets use it for these tests.
2021-06-03 23:58:50 -04:00
Matthias Clasen
bb53cf53e7 fnmatch: Support case-folding
This will be used in GtkFileFilter in the future.

Update all callers.
2021-06-03 23:58:21 -04:00
Matthias Clasen
da9cd4659e Merge branch 'bilelmoussaoui/markdown-links' into 'master'
docs: use markdown syntax for hyperlinks

See merge request GNOME/gtk!3589
2021-06-04 02:45:25 +00:00
Matthias Clasen
d3e6e303fc Merge branch 'GtkCellLayoutWordingImprovement' into 'master'
Added information, that "attributes" refer to CellRenderer "properties".

See merge request GNOME/gtk!3602
2021-06-04 02:21:33 +00:00
DarkTrick
a0c23b1c3d Added information, that "attributes" refer to CellRenderer "properties". 2021-06-04 02:21:31 +00:00
Matthias Clasen
50b3a952c8 Merge branch 'fix-appwindow-allocate' into 'master'
applicationwindow: Allocate tooltips

Closes #3997

See merge request GNOME/gtk!3627
2021-06-04 02:01:53 +00:00
Matthias Clasen
15b24a000d Apply 1 suggestion(s) to 1 file(s) 2021-06-04 01:53:12 +00:00
Matthias Clasen
6a509608f9 applicationwindow: Allocate tooltips
GtkApplicationWindows size_allocate does not chain
up if the menubar is visible; don't forget to allocate
the tooltip window in that case.

Fixes: #3997
2021-06-03 21:43:13 -04:00
Matthias Clasen
df6a52520c Merge branch 'matthiasc/for-master' into 'master'
Cosmetics: Eradicate gdouble

See merge request GNOME/gtk!3626
2021-06-03 21:59:26 +00:00
Matthias Clasen
578db92973 Cosmetics: Eradicate gint
Remove a handful of errant uses of gint.
2021-06-03 17:41:28 -04:00
Matthias Clasen
3ab97fac1f Cosmetics: Eradicate gdouble
Remove 3 errant uses of gdouble.
2021-06-03 17:41:28 -04:00
Matthias Clasen
e8852c9a25 Merge branch 'primary-menu-button' into 'master'
menubutton: Enable F10 for primary menus

See merge request GNOME/gtk!3580
2021-06-03 19:37:23 +00:00
Matthias Clasen
fa0b379d30 Merge branch 'wip/carlosg/no-early-popup-ungrabs' into 'master'
gdk/wayland: Break only implicit grabs on wl_pointer.leave w/ pressed buttons

See merge request GNOME/gtk!3625
2021-06-03 18:10:06 +00:00
Emmanuele Bassi
1565053842 Merge branch 'akamfoad/readme-link-fixes' into 'master'
Update broken links in README.md

Closes #4001

See merge request GNOME/gtk!3623
2021-06-03 15:23:45 +00:00
Carlos Garnacho
8288d9e87c gdk/wayland: Break only implicit grabs on wl_pointer.leave w/ pressed buttons
The releasing of grabs while a button is pressed (e.g. after starting dnd, or
dragging the window, or going to overview with a pressed button, etc...) was
generalized here in https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/1879.

However we shouldn't break all grabs here. In the case of grabbing popups,
compositors will still emit crossing events between client surfaces (e.g.
popping up and selecting a menu item via press-drag-release), breaking all
grabs here means inconsistent client state, that was
https://gitlab.gnome.org/GNOME/gtk/-/issues/2746.

That was fixed in mutter, by essentially making implicit grabs
owner_events=FALSE, however that breaks the mentioned use pattern entirely.
Mutter is changing this behavior back, so GTK should handle these crossing
events.

The grab that we are interested in breaking here is the implicit pointer
one. Popups will be dismissed via other means if the compositor says their
active grab needs breaking. This still leaves dnd/move/resize drags in
one place, while not allowing #2746 to happen with popups.
2021-06-03 17:13:12 +02:00
Akam Foad
a900b30bcf Changing old Gtk4 link to the new one hosted in gtk docs 2021-06-03 14:22:06 +00:00
Akam Foad
9b671d1f79 Update broken links in README.md
Updated Release notes links from https://developer.gnome.org/gtkX/unstable/YYYY.html
to https://developer.gnome.org/gtkX/stable/YYYY.html in the README.md file in the root
folder.

Closes #4001
2021-06-03 14:02:59 +00:00
Emmanuele Bassi
c2d82c23e6 Merge branch 'ebassi/doc-fixes' into 'master'
Small doc fixes

See merge request GNOME/gtk!3622
2021-06-03 10:32:01 +00:00
Emmanuele Bassi
a88b4f517e docs: Fix link to the interactive debugging section
It's in the "running" document.
2021-06-03 09:31:13 +01:00
Emmanuele Bassi
f9f9fa6dc6 docs: Fix the license field
It's LGPL-2.1-or-later, not GPL.
2021-06-03 09:11:09 +01:00
Bilal Elmoussaoui
02672a521a docs: use markdown syntax for hyperlinks 2021-05-25 13:14:01 +00:00
Matthias Clasen
a74420bc1a menubutton: Enable F10 for primary menus
Add a ::primary property to GtkMenuButton, which can
be set to make the menu activatable with F10, like
menubars.
2021-05-24 17:27:40 -04:00
Emmanuele Bassi
8789e78796 a11y: Update the level property for tree expanders
We already have the depth of a tree expander in order to compute the
indentation.

Fixes: #3892
2021-04-22 14:40:35 +01:00
dparisot
82b11623f4 Load icon from executable on Windows 2021-03-21 15:24:28 +01:00
454 changed files with 27813 additions and 21642 deletions

View File

@@ -24,9 +24,8 @@ variables:
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled"
MESON_TEST_TIMEOUT_MULTIPLIER: 3
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v31"
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v32"
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
DOCS_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v31"
.only-default:
only:
@@ -60,6 +59,7 @@ style-check-diff:
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*/*.png"
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*/*.png"
- "${CI_PROJECT_DIR}/_build/testsuite/css/output/*/*.syscap"
- "${CI_PROJECT_DIR}/_build_hello/meson-logs"
cache:
key: "$CI_JOB_NAME"
paths:
@@ -79,9 +79,14 @@ fedora-x86_64:
script:
- .gitlab-ci/show-info-linux.sh
- meson subprojects update
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
- mkdir _install
- meson --prefix=${CI_PROJECT_DIR}/_install
${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
_build
- ninja -C _build
- meson compile -C _build
- meson install -C _build
- PKG_CONFIG_PATH=${CI_PROJECT_DIR}/_install/lib64/pkgconfig:${CI_PROJECT_DIR}/_install/share/pkgconfig meson setup _build_hello examples/hello
- meson compile -C _build_hello
- .gitlab-ci/run-tests.sh _build x11
- .gitlab-ci/run-tests.sh _build wayland
- .gitlab-ci/run-tests.sh _build broadway
@@ -165,6 +170,9 @@ macos:
- export MESON_FORCE_BACKTRACE=1
script:
- meson -Dx11-backend=false
-Dbroadway-backend=true
-Dmacos-backend=true
-Dmedia-gstreamer=disabled
-Dintrospection=disabled
-Dcpp_std=c++11
-Dpixman:tests=disabled
@@ -302,7 +310,7 @@ asan-build:
allow_failure: true
reference:
image: $DOCS_IMAGE
image: $FEDORA_IMAGE
stage: docs
needs: []
variables:

View File

@@ -38,7 +38,6 @@ RUN dnf -y install \
gstreamer1-plugins-good \
gstreamer1-plugins-bad-free-devel \
gstreamer1-plugins-base-devel \
gtk-doc \
hicolor-icon-theme \
iso-codes \
itstool \

View File

@@ -15,7 +15,7 @@ meson \
-Dx11-backend=true \
-Dwayland-backend=true \
-Dbroadway-backend=true \
-Dvulkan=yes \
-Dvulkan=enabled \
-Dprofiler=true \
--werror \
${EXTRA_MESON_FLAGS:-} \

View File

@@ -6,7 +6,7 @@ call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliar
:: FIXME: make warnings fatal
pip3 install --upgrade --user meson==0.56.2 || goto :error
meson _build || goto :error
meson -Dmedia-gstreamer=disabled _build || goto :error
ninja -C _build || goto :error
goto :EOF

210
NEWS
View File

@@ -1,3 +1,213 @@
Overview of Changes in 4.3.2
============================
* GtkToggleButton:
- Fix the actionable implementation
* GtkCheckButton:
- Fix the actionable implementation
- Cancel activation on when the pointer leaves
* GtkMenuButton:
- Make activatable again
- Add a way to have an icon + arrow
* GtkColorButton:
- Make activatable again
* GtkFontButton:
- Make activatable again
* GtkAppChooserButton:
- Make activatable again
* GtkColumnView:
- Fix double activation
* GtkLabel:
- Fix mnemonics without markup
* GtkTreeView:
- Clip header buttons
* GtkTextView:
- Add api to get the RTL and LTR contexts
- Fix some errors in text history grouping
* GtkText:
- Don't show placeholder text on top of entry text
- Add api to compute the cursor extents
- Fix y coordinates for text selection
* GtkFileChooser:
- Don't show Trash in the side bar
* GtkPopoverMenu:
- Add scrollbars to long menus
* GtkActionMuxer:
- Fix propagation of accel changes
* Introspection:
- Annotate all filename arguments
- Rename GtkMediaStream apis to avoid name collisions
- Rename GtkDropTarget properties to avoid name collisions
- Make GtkPasswordEntryBuffer introspectable
* Printing:
- Remove the Google Cloud Print backend
* Theme:
- Sync included icons with the Adwaita icon theme
* GSK:
- Avoid overflowing the vertex counter
- Handle negative scales correctly in the ngl renderer
* GDK:
- Cleanup and simplify OpenGL setup code
- Add a GdkDisplay::init_gl vfunc and gdk_display_prepare_gl() api
- Require EGL 1.4
- Fix EGL + NVidia
* Build:
- Enable gstreamer by default
- Disable Vulkan by default
- Remove the sassc option
- Remove options and checks for X11 extensions
* X11:
- Stop using XComposite
- Remove the Visual cache
* Wayland:
- Fix some DND corner cases
- Work with version 2 of pointer-gestures-v1
- Look for cursor themes in $HOME/.icons
* Windows:
- Fix SIGILL on x64 due to popcnt
- Fix popup placement
- Fix drag icon placement
- Clean up HiDPI and WGL support
- Default to WGL
* MacOs:
- Fix input method support
- Register known clipboard types for drop targets
- Add initial DND support
* Translation updates:
Brazilian Portuguese
Portuguese
Romanian
Turkish
Ukrainian
Overview of Changes in 4.3.1
============================
* GtkEmojiChooser:
- Update data from CLDR 39
- Load Emoji data for both language and territory
* GtkCalendar:
- Fix an off-by-one error in day numbers
* GtkListView:
- Add .activatable style class to activatable items
* GtkCheckButton:
- Don't allow unchecking grouped radio buttons
*GtkToggleButton:
- Fix mnemonic activation propagation
* GtkLabel:
- Make mnemonics work even when invisible
- Fix mnemonic activation propagation
* GtkMenuButton:
- Add a property to mark primary menus and make F10 work
* GtkApplication:
- Fix initial screensaver state async
* GtkEntry:
- Apply xalign to placeholder text (as it was in GTK 3)
* GtkSpinButton:
- Fix swipe gestures
* GtkStackSwitcher:
- Implement GtkOrientable (as it was in GTK 3)
- Fix a use-after-free problem with drag timeouts
* GtkFileChooser:
- Add support for (case-insensitive) suffix matches in GtkFileFilter
* GtkPasswordEntry:
- Make GtkPasswordEntryBuffer public, to make it easier
to write your own password entry widget
* Input:
- Fix interference between various obscure XKB features
(e.g. overlays) and Compose sequences
* Action support:
- Fix submenu-action handling
* Theme:
- Update icons from the Adwaita icon theme
- Fix icon names for GtkSwitch
- Fix switch-off icon
* GSK:
- Improve transformed offscreen rendering
- Add padding between cached glyphs
* Wayland:
- Fix monitor sizes in the presence of transforms
- Add a getter for the EGLDisplay
- Fix click-drag-release sequences for popovers
* X11:
- Support EGL for X11. Fall back to GLX if EGL isn't available
- Always fall back to GLX on NVidia
- Add a getter for the EGLDisplay
* Broadway:
- Add a setter for display scale
* Windows:
- Add a getter for the EGLDisplay
- Make GL work for media playback
* MacOS:
- Fix menubar appearance
* Tools:
- gtk4-builder-tool: Replace can-focus with focusable in 3-to-4 conversion
* Introspection:
- Add missing annotations in a few places (e.g. gtk_free_view_row_activated)
* Build:
- Only build one source file with -mf16c
- Fix devel styling for ci flatpak builds
- Generate appdata for demo flatpaks
* Docs:
- Numerous fixes and additions
* Translation updates:
Friulian
Nepali
Norwegian Bokmål
Ukrainian
Overview of Changes in 4.3.0
============================

View File

@@ -157,8 +157,8 @@ Release notes
The release notes for GTK are part of the migration guide in the API
reference. See:
- [3.x release notes](https://developer.gnome.org/gtk3/unstable/gtk-migrating-2-to-3.html)
- [4.x release notes](https://developer.gnome.org/gtk4/unstable/gtk-migrating-3-to-4.html)
- [3.x release notes](https://developer.gnome.org/gtk3/stable/gtk-migrating-2-to-3.html)
- [4.x release notes](https://docs.gtk.org/gtk4/migrating-3to4.html)
Licensing terms
---------------

View File

@@ -124,9 +124,6 @@
/* Define to 1 if you have the <unistd.h> header file. */
#mesondefine HAVE_UNISTD_H
/* Have the XCOMPOSITE X extension */
#mesondefine HAVE_XCOMPOSITE
/* Have the Xcursor library */
#mesondefine HAVE_XCURSOR

View File

@@ -163,8 +163,8 @@ drag_update_cb (GtkGestureDrag *drag,
static void
drag_end_cb (GtkGestureDrag *drag,
gdouble dx,
gdouble dy,
double dx,
double dy,
gpointer user_data)
{
GtkShadertoy *shadertoy = GTK_SHADERTOY (user_data);

View File

@@ -21,8 +21,10 @@ do_menu (GtkWidget *do_widget)
if (!window)
{
GtkWidget *box;
GtkWidget *sw;
GtkWidget *widget;
GtkWidget *scale;
window = gtk_window_new ();
gtk_window_set_title (GTK_WINDOW (window), "Menu");
@@ -31,11 +33,23 @@ do_menu (GtkWidget *do_widget)
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_window_set_child (GTK_WINDOW (window), box);
sw = gtk_scrolled_window_new ();
gtk_window_set_child (GTK_WINDOW (window), sw);
gtk_widget_set_vexpand (sw, TRUE);
gtk_box_append (GTK_BOX (box), sw);
widget = demo3_widget_new ("/transparent/portland-rose.jpg");
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), widget);
scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0.01, 10.0, 0.1);
gtk_range_set_value (GTK_RANGE (scale), 1.0);
gtk_box_append (GTK_BOX (box), scale);
g_object_bind_property (gtk_range_get_adjustment (GTK_RANGE (scale)), "value",
widget, "scale",
G_BINDING_BIDIRECTIONAL);
}
if (!gtk_widget_get_visible (window))

View File

@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
<id>org.gtk.Demo4.desktop</id>
<id>org.gtk.Demo4</id>
<launchable type="desktop-id">org.gtk.Demo4.desktop</launchable>
<metadata_license>CC0-1.0</metadata_license>
<project_license>LGPL-2.0+</project_license>
<project_license>LGPL-2.1-or-later</project_license>
<name>GTK Demo</name>
<summary>Program to demonstrate GTK functions</summary>
<description>
@@ -30,6 +31,7 @@
<translation type="gettext">gtk-4.0</translation>
<update_contact>matthias.clasen_at_gmail.com</update_contact>
<developer_name>Matthias Clasen and others</developer_name>
<content_rating type="oars-1.1"/>
<releases>
<release version="@BUILD_VERSION@" date="@BUILD_DATE@">
<description>

View File

@@ -150,7 +150,7 @@ gtk_nuclear_media_stream_step (gpointer data)
* call our pause function to pause the stream.
*/
if (nuclear->progress >= DURATION)
gtk_media_stream_ended (GTK_MEDIA_STREAM (nuclear));
gtk_media_stream_stream_ended (GTK_MEDIA_STREAM (nuclear));
/* The timeout function is removed by the pause function,
* so we can just always return this value.
@@ -267,11 +267,11 @@ gtk_nuclear_media_stream_init (GtkNuclearMediaStream *nuclear)
* However, media streams need to tell GTK once they are initialized,
* so we do that here.
*/
gtk_media_stream_prepared (GTK_MEDIA_STREAM (nuclear),
FALSE,
TRUE,
TRUE,
DURATION);
gtk_media_stream_stream_prepared (GTK_MEDIA_STREAM (nuclear),
FALSE,
TRUE,
TRUE,
DURATION);
}
/* And finally, we add the simple constructor we declared in the header. */

View File

@@ -1,7 +1,7 @@
/* Peg Solitaire
* #Keywords: GtkGridView, game
*
* This demo demonstrates how to use drag'n'drop to implement peg solitaire.
* This demo demonstrates how to use drag-and-drop to implement peg solitaire.
*
*/
@@ -98,7 +98,7 @@ solitaire_peg_init (SolitairePeg *peg)
/* Add a little setter for the peg's position.
* We want to track those so that we can check for legal moves
* during drag'n'drop operations.
* during drag-and-drop operations.
*/
static void
solitaire_peg_set_position (SolitairePeg *peg,

View File

@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
<id>org.gtk.IconBrowser4.desktop</id>
<id>org.gtk.IconBrowser4</id>
<launchable type="desktop-id">org.gtk.IconBrowser4.desktop</launchable>
<metadata_license>CC0-1.0</metadata_license>
<project_license>LGPL-2.0+</project_license>
<project_license>LGPL-2.1-or-later</project_license>
<name>GTK Icon Browser</name>
<summary>Program to browse themed icons</summary>
<description>
@@ -29,6 +30,7 @@
<translation type="gettext">gtk-4.0</translation>
<update_contact>matthias.clasen_at_gmail.com</update_contact>
<developer_name>Matthias Clasen and others</developer_name>
<content_rating type="oars-1.1"/>
<releases>
<release version="@BUILD_VERSION@" date="@BUILD_DATE@">
<description>

View File

@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
<id>org.gtk.PrintEditor4.desktop</id>
<id>org.gtk.PrintEditor4</id>
<launchable type="desktop-id">org.gtk.PrintEditor4.desktop</launchable>
<metadata_license>CC0-1.0</metadata_license>
<project_license>LGPL-2.0+</project_license>
<project_license>LGPL-2.1-or-later</project_license>
<name>GTK Print Editor</name>
<summary>Program to demonstrate GTK printing</summary>
<description>
@@ -24,6 +25,7 @@
<translation type="gettext">gtk-4.0</translation>
<update_contact>matthias.clasen_at_gmail.com</update_contact>
<developer_name>Matthias Clasen and others</developer_name>
<content_rating type="oars-1.1"/>
<releases>
<release version="3.99.0" date="2020-07-30">
<description>

View File

@@ -721,7 +721,6 @@ static const char ui_info[] =
" <item>"
" <attribute name='label'>_New</attribute>"
" <attribute name='action'>app.new</attribute>"
" <attribute name='accel'>&lt;Primary&gt;n</attribute>"
" </item>"
" <item>"
" <attribute name='label'>_Open</attribute>"
@@ -730,12 +729,10 @@ static const char ui_info[] =
" <item>"
" <attribute name='label'>_Save</attribute>"
" <attribute name='action'>app.save</attribute>"
" <attribute name='accel'>&lt;Primary&gt;s</attribute>"
" </item>"
" <item>"
" <attribute name='label'>Save _As...</attribute>"
" <attribute name='action'>app.save-as</attribute>"
" <attribute name='accel'>&lt;Primary&gt;s</attribute>"
" </item>"
" </section>"
" <section>"
@@ -756,7 +753,6 @@ static const char ui_info[] =
" <item>"
" <attribute name='label'>_Quit</attribute>"
" <attribute name='action'>app.quit</attribute>"
" <attribute name='accel'>&lt;Primary&gt;q</attribute>"
" </item>"
" </section>"
" </submenu>"
@@ -766,7 +762,6 @@ static const char ui_info[] =
" <item>"
" <attribute name='label'>_About Print Editor</attribute>"
" <attribute name='action'>app.about</attribute>"
" <attribute name='accel'>&lt;Primary&gt;a</attribute>"
" </item>"
" </section>"
" </submenu>"
@@ -794,6 +789,15 @@ startup (GApplication *app)
{
GtkBuilder *builder;
GMenuModel *menubar;
struct {
const char *action_and_target;
const char *accelerators[2];
} accels[] = {
{ "app.new", { "<Control>n", NULL } },
{ "app.quit", { "<Control>q", NULL } },
{ "app.save", { "<Control>s", NULL } },
{ "app.about", { "<Control>a", NULL } },
};
builder = gtk_builder_new ();
gtk_builder_add_from_string (builder, ui_info, -1, NULL);
@@ -802,6 +806,9 @@ startup (GApplication *app)
gtk_application_set_menubar (GTK_APPLICATION (app), menubar);
for (int i = 0; i < G_N_ELEMENTS (accels); i++)
gtk_application_set_accels_for_action (GTK_APPLICATION (app), accels[i].action_and_target, accels[i].accelerators);
g_object_unref (builder);
}

View File

@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
<id>org.gtk.WidgetFactory4.desktop</id>
<id>org.gtk.WidgetFactory4</id>
<launchable type="desktop-id">org.gtk.WidgetFactory4.desktop</launchable>
<metadata_license>CC0-1.0</metadata_license>
<project_license>LGPL-2.0+</project_license>
<project_license>LGPL-2.1-or-later</project_license>
<name>GTK Widget Factory</name>
<summary>Program to demonstrate GTK functions</summary>
<description>
@@ -31,6 +32,7 @@
<translation type="gettext">gtk-4.0</translation>
<update_contact>matthias.clasen_at_gmail.com</update_contact>
<developer_name>Matthias Clasen and others</developer_name>
<content_rating type="oars-1.1"/>
<releases>
<release version="@BUILD_VERSION@" date="@BUILD_DATE@">
<description>

View File

@@ -1997,6 +1997,7 @@ activate (GApplication *app)
const char *accelerators[2];
} accels[] = {
{ "app.about", { "F1", NULL } },
{ "app.shortcuts", { "<Control>question", NULL } },
{ "app.quit", { "<Control>q", NULL } },
{ "app.open-in", { "<Control>n", NULL } },
{ "win.dark", { "<Control>d", NULL } },

View File

@@ -2902,7 +2902,7 @@ bad things might happen.</property>
<action-widgets>
<action-widget response="cancel">cancel_info_dialog</action-widget>
<action-widget response="ok">doit_info_dialog</action-widget>
<action-widget response="ok" default="true">doit_info_dialog</action-widget>
</action-widgets>
</object>
<object class="GtkDialog" id="action_dialog">

View File

@@ -5,7 +5,7 @@ repository_url = "https://gitlab.gnome.org/GNOME/gtk.git"
website_url = "https://www.gtk.org"
authors = "GTK Development Team"
logo_url = "gtk-logo.svg"
license = "GPL-2.1-or-later"
license = "LGPL-2.1-or-later"
description = "The GTK toolkit"
dependencies = [ "GObject-2.0", "cairo-1.0", "Pango-1.0", "GdkWayland-4.0", "GdkX11-4.0" ]
devhelp = true

View File

@@ -5,7 +5,7 @@ repository_url = "https://gitlab.gnome.org/GNOME/gtk.git"
website_url = "https://www.gtk.org"
authors = "GTK Development Team"
logo_url = "gtk-logo.svg"
license = "GPL-2.1-or-later"
license = "LGPL-2.1-or-later"
description = "The GTK toolkit"
dependencies = [ "GObject-2.0", "Graphene-1.0", "Pango-1.0", "Gdk-4.0" ]
devhelp = true

View File

@@ -0,0 +1,54 @@
Title: Drag-and-Drop in GTK
Drag-and-Drop (DND) is a user interaction pattern where users drag a UI element
from one place to another, either inside a single application or between
different application windows.
When the element is 'dropped', data is transferred from the source to the
destination, according to the drag action that is negotiated between both
sides. Most commonly, that is a _copy_, but it can also be a _move_ or a
_link_, depending on the kind of data and how the drag operation has been
set up.
This chapter gives an overview over how Drag-and-Drop is handled with event
controllers in GTK.
## Drag sources
To make data available via DND, you create a [class@Gtk.DragSource]. Drag sources
are event controllers, which initiate a Drag-and-Drop operation when the user clicks
and drags the widget.
A drag source can be set up ahead of time, with the desired drag action(s) and the data
to be transferred. But it is also possible to provide the data when a drag operation
is about to begin, by connecting to the [signal@Gtk.DragSource::prepare] signal.
The GtkDragSource emits the [signal@Gtk.DragSource::drag-begin] signal when the DND
operation starts, and the [signal@Gtk.DragSource::drag-end] signal when it is done.
But it is not normally necessary to handle these signals. One case in which a ::drag-end
handler is necessary is to implement `GDK_ACTION_MOVE`.
## Drop targets
To receive data via DND, you create a [class@Gtk.DropTarget], and tell it what kind of
data to accept. You need to connect to the [signal@Gtk.DropTarget::drop] signal to receive
the data when a DND operation occurs.
While a DND operation is ongoing, GTK provides updates when the pointer moves over
the widget to which the drop target is associated. The [signal@Gtk.DropTarget::enter],
[signal@Gtk.DropTarget::leave] and [signal@Gtk.DropTarget::motion] signals get emitted
for this purpose.
GtkDropTarget provides a simple API, and only provides the data when it has been completely
transferred. If you need to handle the data transfer yourself (for example to provide progress
information during the transfer), you can use the more complicated [class@Gtk.DropTargetAsync].
## Other considerations
It is sometimes necessary to update the UI of the destination while a DND operation is ongoing,
say to scroll or expand a view, or to switch pages. Typically, such UI changes are triggered
by hovering over the widget in question.
[class@Gtk.DropControllerMotion] is an event controller that can help with implementing such
behaviors. It is very similar to [class@Gtk.EventControllerMotion], but provides events during
a DND operation.

View File

@@ -161,19 +161,19 @@ activate (GtkApplication *app,
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *box;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_window_set_child (GTK_WINDOW (window), box);
button = gtk_button_new_with_label ("Hello World");
gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_window_destroy), window);
gtk_box_append (GTK_BOX (box), button);
gtk_window_set_child (GTK_WINDOW (window), button);
gtk_widget_show (window);
}

View File

@@ -46,7 +46,8 @@ display, unless specified otherwise.
<para>
<command>gtk4-launch</command> takes at least one argument, the name of
the application to launch. The name should match application desktop file name,
as residing in /usr/share/application, with or without the '.desktop' suffix.
as residing in the applications subdirectories of the XDG data directories, with
or without the '.desktop' suffix.
</para>
<para>
If called with more than one argument, the rest of them besides the application
@@ -71,4 +72,14 @@ application.
</variablelist>
</refsect1>
<refsect1><title>Environment</title>
<para>Some environment variables affect the behavior of <command>gtk4-launch</command>.</para>
<variablelist>
<varlistentry>
<term><option>XDG_DATA_HOME</option>, <option>XDG_DATA_DIRS</option></term>
<listitem><para>The environment variables specifying the XDG dta directories.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
</refentry>

View File

@@ -5,7 +5,7 @@ repository_url = "https://gitlab.gnome.org/GNOME/gtk.git"
website_url = "https://www.gtk.org"
authors = "GTK Development Team"
logo_url = "gtk-logo.svg"
license = "GPL-2.1-or-later"
license = "LGPL-2.1-or-later"
description = "The GTK toolkit"
dependencies = [ "GObject-2.0", "Graphene-1.0", "Pango-1.0", "Gdk-4.0", "Gsk-4.0" ]
devhelp = true
@@ -57,6 +57,7 @@ content_files = [
"initialization.md",
"actions.md",
"input-handling.md",
"drag-and-drop.md",
"drawing-model.md",
"css-overview.md",
"css-properties.md",

View File

@@ -99,6 +99,12 @@ you should stop using `GdkVisual` APIs, since this object not longer
exists in GTK 4. Most of its APIs are deprecated already and not
useful when dealing with RGBA visuals.
### Stop using `gtk_widget_set_app_paintable`
This is gone in GTK4 with no direct replacement. But for some usecases there
are alternatives. If you want to make the background transparent, you can set
the background color to, for example, `rgba(255, 255, 255, 0)` using CSS instead.
### Stop using `GtkBox` padding, fill and expand child properties
GTK 4 removes these [class@Gtk.Box] child properties, so you should stop using
@@ -133,7 +139,7 @@ or `gtk_style_context_get_color()` only accept the context's current
state for their state argument. You should update all callers to pass
the current state.
### Stop using `gdk_pixbuf_get_from_window()` and `gdk_cairo_set_source_surface()`
### Stop using `gdk_pixbuf_get_from_window()` and `gdk_cairo_set_source_window()`
These functions are not supported in GTK 4. Instead, either use
backend-specific APIs, or render your widgets using
@@ -187,11 +193,22 @@ for this change.
| ::grab-broken-event | - |
Event signals which are not directly related to input have to be dealt with
on a one-by-one basis. If you were using `::configure-event` and
`::window-state-event` to save window state, you should use property
notification for corresponding [class@Gtk.Window] properties, such as
[property@Gtk.Window:default-width], [property@Gtk.Window:default-height],
[property@Gtk.Window:maximized] or [property@Gtk.Window:fullscreened].
on a one-by-one basis:
- If you were using `::configure-event` and `::window-state-event` to save
window state, you should use property notification for corresponding
[class@Gtk.Window] properties, such as [property@Gtk.Window:default-width],
[property@Gtk.Window:default-height], [property@Gtk.Window:maximized] or
[property@Gtk.Window:fullscreened].
- If you were using `::delete-event` to present a confirmation when using
the close button of a window, you should use the
[signal@Gtk.Window::close-request] signal.
- If you were using `::map-event` and `::unmap-event` to track a window
being mapped, you should use property notification for the
[property@Gdk.Surface:mapped] property instead.
- The `::damage-event` signal has no replacement, as the only consumer
of damage events were the offscreen GDK surfaces, which have no
replacement in GTK 4.x.
### Set a proper application ID
@@ -232,6 +249,10 @@ in GTK 3, you can prepare for the switch by using `gtk_widget_destroy()`
only on toplevel windows, and replace all other uses with
`gtk_container_remove()` or `g_object_unref()`.
### Stop using the GtkWidget.destroy vfunc
Instead of implementing GtkWidget.destroy, you can implement GObject.dispose.
### Reduce the use of generic container APIs
GTK 4 removes `gtk_container_add()` and `gtk_container_remove()`. While there
@@ -604,6 +625,9 @@ from `FALSE` to `TRUE`. In addition, there is a [property@Gtk.Widget:focusable]
property, which controls whether an individual widget can receive
the input focus.
The `gtk4-builder-tool` utility, when called with the `--3to4` option of the
`simplify` command, will replace `:can-focus` by `:focusable`.
The feature to automatically keep the focus widget scrolled into view with
`gtk_container_set_focus_vadjustment()` has been removed together with
`GtkContainer`, and is provided by scrollable widgets instead. In the common
@@ -740,7 +764,7 @@ The abstract base class `GtkBin` for single-child containers has been
removed. The former subclasses are now derived directly from `GtkWidget`,
and have a "child" property for their child widget. To add a child, use
the setter for the "child" property (e.g. [method@Gtk.Frame.set_child]) instead
of `gtk_container_add()`. Adding a child in a ui file with <child> still works.
of `gtk_container_add()`. Adding a child in a ui file with `<child>` still works.
The affected classes are:
@@ -766,7 +790,7 @@ expand flags) and [vfunc@Gtk.Widget.get_request_mode] (if you want your
container to support height-for-width).
You may also want to implement the [iface@Gtk.Buildable] interface, to support
adding children with <child> in ui files.
adding children with `<child>` in ui files.
### Adapt to GtkContainer removal
@@ -777,7 +801,7 @@ and have class-specific add() and remove() functions.
The most noticeable change is the use of [method@Gtk.Box.append] or [method@Gtk.Box.prepend]
instead of `gtk_container_add()` for adding children to `GtkBox`, and the change
to use container-specific remove functions, such as [method@Gtk.Stack.remove] instead
of `gtk_container_remove()`. Adding a child in a ui file with <child> still works.
of `gtk_container_remove()`. Adding a child in a ui file with `<child>` still works.
The affected classes are:
@@ -804,6 +828,11 @@ by a layout manager (if they are layout-related), or handled in some
other way. One possibility is to use child meta objects, as seen with
[class@Gtk.AssistantPage], [class@Gtk.StackPage] and the like.
If you used to define child properties with `<packing>` in ui files, you have
to switch to using `<layout>` for the corresponding layout properties.
`gtk4-builder-tool` can help with this conversion, with the `--3to4` option
of the `simplify` command.
The replacements for gtk_container_add() are:
| Widget | Replacement |
@@ -1330,3 +1359,4 @@ of tree models, and widgets instead of cell renderers.
To learn more about the new list widgets, you can read the [List Widget
Overview](#ListWidget).

View File

@@ -59,14 +59,12 @@ example_app_startup (GApplication *app)
}
static void
example_app_create_window (GtkApplication *app,
const char *save_id)
example_app_activate (GApplication *app)
{
ExampleAppWindow *win;
win = example_app_window_new (EXAMPLE_APP (app));
gtk_widget_set_save_id (GTK_WIDGET (win), save_id);
/* FIXME: differentiate save ids */
gtk_window_present (GTK_WINDOW (win));
}
static void
@@ -95,8 +93,8 @@ static void
example_app_class_init (ExampleAppClass *class)
{
G_APPLICATION_CLASS (class)->startup = example_app_startup;
G_APPLICATION_CLASS (class)->activate = example_app_activate;
G_APPLICATION_CLASS (class)->open = example_app_open;
GTK_APPLICATION_CLASS (class)->create_window = example_app_create_window;
}
ExampleApp *
@@ -105,7 +103,5 @@ example_app_new (void)
return g_object_new (EXAMPLE_APP_TYPE,
"application-id", "org.gtk.exampleapp",
"flags", G_APPLICATION_HANDLES_OPEN,
"register-session", TRUE,
"save-state", TRUE,
NULL);
}

View File

@@ -17,8 +17,6 @@ struct _ExampleAppWindow
GtkWidget *words;
GtkWidget *lines;
GtkWidget *lines_label;
GList *files;
};
G_DEFINE_TYPE (ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW)
@@ -213,68 +211,14 @@ example_app_window_dispose (GObject *object)
g_clear_object (&win->settings);
g_list_free_full (win->files, g_object_unref);
win->files = NULL;
G_OBJECT_CLASS (example_app_window_parent_class)->dispose (object);
}
static gboolean
example_app_window_save_state (GtkWidget *widget,
GVariantDict *dict,
gboolean *save_children)
{
ExampleAppWindow *win = EXAMPLE_APP_WINDOW (widget);
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
for (GList *l = win->files; l; l = l->next)
{
g_variant_builder_add (&builder, "s", g_file_peek_path (G_FILE (l->data)));
}
g_variant_dict_insert_value (dict, "files", g_variant_builder_end (&builder));
/* Save window state */
GTK_WIDGET_CLASS (example_app_window_parent_class)->save_state (widget, dict, save_children);
*save_children = TRUE;
return TRUE;
}
static gboolean
example_app_window_restore_state (GtkWidget *widget,
GVariant *state)
{
ExampleAppWindow *win = EXAMPLE_APP_WINDOW (widget);
GVariantIter *iter;
/* Restore window state */
GTK_WIDGET_CLASS (example_app_window_parent_class)->restore_state (widget, state);
if (g_variant_lookup (state, "files", "as", &iter))
{
const char *path;
while (g_variant_iter_next (iter, "&s", &path))
{
GFile *file = g_file_new_for_path (path);
example_app_window_open (win, file);
g_object_unref (file);
}
}
return TRUE;
}
static void
example_app_window_class_init (ExampleAppWindowClass *class)
{
G_OBJECT_CLASS (class)->dispose = example_app_window_dispose;
GTK_WIDGET_CLASS (class)->save_state = example_app_window_save_state;
GTK_WIDGET_CLASS (class)->restore_state = example_app_window_restore_state;
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/exampleapp/window.ui");
@@ -344,6 +288,4 @@ example_app_window_open (ExampleAppWindow *win,
update_words (win);
update_lines (win);
win->files = g_list_append (win->files, g_object_ref (file));
}

View File

@@ -4,7 +4,6 @@
<property name="title" translatable="yes">Example Application</property>
<property name="default-width">600</property>
<property name="default-height">400</property>
<property name="save-id">window</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<child>
@@ -27,7 +26,6 @@
<object class="GtkToggleButton" id="search">
<property name="sensitive">0</property>
<property name="icon-name">edit-find-symbolic</property>
<property name="save-id">search</property>
</object>
</child>
<child type="end">
@@ -40,7 +38,6 @@
<child>
<object class="GtkBox" id="content_box">
<property name="orientation">vertical</property>
<property name="save-id">content_box</property>
<child>
<object class="GtkSearchBar" id="searchbar">
<child>
@@ -52,10 +49,8 @@
</child>
<child>
<object class="GtkBox" id="hbox">
<property name="save-id">hbox</property>
<child>
<object class="GtkRevealer" id="sidebar">
<property name="save-id">sidebar</property>
<property name="transition-type">slide-right</property>
<child>
<object class="GtkScrolledWindow" id="sidebar-sw">
@@ -71,7 +66,6 @@
</child>
<child>
<object class="GtkStack" id="stack">
<property name="save-id">stack</property>
<signal name="notify::visible-child" handler="visible_child_changed"/>
</object>
</child>

View File

@@ -197,6 +197,17 @@ text_buffer_changed_cb (GtkTextBuffer *buffer,
}
}
static void
fullscreen_changed (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
if (gtk_window_is_fullscreen (GTK_WINDOW (object)))
gtk_button_set_icon_name (GTK_BUTTON (user_data), "view-restore-symbolic");
else
gtk_button_set_icon_name (GTK_BUTTON (user_data), "view-fullscreen-symbolic");
}
static GActionEntry win_entries[] = {
{ "copy", window_copy, NULL, NULL, NULL },
{ "paste", window_paste, NULL, NULL, NULL },
@@ -214,17 +225,18 @@ new_window (GApplication *app,
GtkWidget *window, *grid, *scrolled, *view;
GtkWidget *toolbar;
GtkWidget *button;
GtkWidget *sw, *box, *label;
window = gtk_application_window_new (GTK_APPLICATION (app));
gtk_window_set_default_size ((GtkWindow*)window, 640, 480);
g_action_map_add_action_entries (G_ACTION_MAP (window), win_entries, G_N_ELEMENTS (win_entries), window);
gtk_window_set_title (GTK_WINDOW (window), "Bloatpad");
gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (window), TRUE);
grid = gtk_grid_new ();
gtk_window_set_child (GTK_WINDOW (window), grid);
toolbar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_add_css_class (toolbar, "toolbar");
button = gtk_toggle_button_new ();
gtk_button_set_icon_name (GTK_BUTTON (button), "format-justify-left");
gtk_actionable_set_detailed_action_name (GTK_ACTIONABLE (button), "win.justify::left");
@@ -240,21 +252,18 @@ new_window (GApplication *app,
gtk_actionable_set_detailed_action_name (GTK_ACTIONABLE (button), "win.justify::right");
gtk_box_append (GTK_BOX (toolbar), button);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_widget_set_halign (box, GTK_ALIGN_END);
label = gtk_label_new ("Fullscreen:");
gtk_box_append (GTK_BOX (box), label);
sw = gtk_switch_new ();
gtk_widget_set_valign (sw, GTK_ALIGN_CENTER);
gtk_actionable_set_action_name (GTK_ACTIONABLE (sw), "win.fullscreen");
gtk_box_append (GTK_BOX (box), sw);
gtk_box_append (GTK_BOX (toolbar), box);
button = gtk_toggle_button_new ();
gtk_button_set_icon_name (GTK_BUTTON (button), "view-fullscreen-symbolic");
gtk_actionable_set_action_name (GTK_ACTIONABLE (button), "win.fullscreen");
gtk_box_append (GTK_BOX (toolbar), button);
g_signal_connect (window, "notify::fullscreened", G_CALLBACK (fullscreen_changed), button);
gtk_grid_attach (GTK_GRID (grid), toolbar, 0, 0, 1, 1);
scrolled = gtk_scrolled_window_new ();
gtk_widget_set_hexpand (scrolled, TRUE);
gtk_widget_set_vexpand (scrolled, TRUE);
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (scrolled), TRUE);
view = gtk_text_view_new ();
g_object_set_data ((GObject*)window, "bloatpad-text", view);
@@ -344,6 +353,7 @@ static void
combo_changed (GtkComboBox *combo,
gpointer user_data)
{
GtkDialog *dialog = user_data;
GtkEntry *entry = g_object_get_data (user_data, "entry");
const char *action;
char **accels;
@@ -359,6 +369,17 @@ combo_changed (GtkComboBox *combo,
g_strfreev (accels);
gtk_editable_set_text (GTK_EDITABLE (entry), str);
gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_APPLY, FALSE);
}
static void
entry_changed (GtkEntry *entry,
GParamSpec *pspec,
gpointer user_data)
{
GtkDialog *dialog = user_data;
gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_APPLY, TRUE);
}
static void
@@ -372,7 +393,7 @@ response (GtkDialog *dialog,
const char *str;
char **accels;
if (response_id == GTK_RESPONSE_CLOSE)
if (response_id == GTK_RESPONSE_CANCEL)
{
gtk_window_destroy (GTK_WINDOW (dialog));
return;
@@ -388,6 +409,8 @@ response (GtkDialog *dialog,
gtk_application_set_accels_for_action (gtk_window_get_application (user_data), action, (const char **) accels);
g_strfreev (accels);
gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_APPLY, FALSE);
}
static void
@@ -402,22 +425,41 @@ edit_accels (GSimpleAction *action,
GtkWidget *dialog;
int i;
dialog = gtk_dialog_new ();
dialog = gtk_dialog_new_with_buttons ("Accelerators",
NULL,
GTK_DIALOG_USE_HEADER_BAR,
"Close", GTK_RESPONSE_CANCEL,
"Set", GTK_RESPONSE_APPLY,
NULL);
gtk_window_set_application (GTK_WINDOW (dialog), app);
actions = gtk_application_list_action_descriptions (app);
combo = gtk_combo_box_text_new ();
g_object_set (gtk_dialog_get_content_area (GTK_DIALOG (dialog)),
"margin-top", 10,
"margin-bottom", 10,
"margin-start", 10,
"margin-end", 10,
"spacing", 10,
NULL);
gtk_box_append (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), combo);
for (i = 0; actions[i]; i++)
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), actions[i], actions[i]);
g_signal_connect (combo, "changed", G_CALLBACK (combo_changed), dialog);
entry = gtk_entry_new ();
gtk_widget_set_hexpand (entry, TRUE);
g_signal_connect (entry, "notify::text", G_CALLBACK (entry_changed), dialog);
gtk_box_append (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), entry);
gtk_dialog_add_button (GTK_DIALOG (dialog), "Close", GTK_RESPONSE_CLOSE);
gtk_dialog_add_button (GTK_DIALOG (dialog), "Set", GTK_RESPONSE_APPLY);
g_signal_connect (dialog, "response", G_CALLBACK (response), dialog);
g_object_set_data (G_OBJECT (dialog), "combo", combo);
g_object_set_data (G_OBJECT (dialog), "entry", entry);
gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
gtk_widget_show (dialog);
}
@@ -536,7 +578,7 @@ bloat_pad_startup (GApplication *application)
menu = gtk_application_get_menu_by_id (GTK_APPLICATION (application), "icon-menu");
file = g_file_new_for_uri ("resource:///org/gtk/libgtk/icons/16x16/actions/gtk-select-color.png");
file = g_file_new_for_uri ("resource:///org/gtk/libgtk/icons/16x16/actions/insert-image.png");
icon = g_file_icon_new (file);
item = g_menu_item_new ("File Icon", NULL);
g_menu_item_set_icon (item, icon);
@@ -552,7 +594,7 @@ bloat_pad_startup (GApplication *application)
g_object_unref (item);
g_object_unref (icon);
bytes = g_resources_lookup_data ("/org/gtk/libgtk/icons/16x16/actions/gtk-select-font.png", 0, NULL);
bytes = g_resources_lookup_data ("/org/gtk/libgtk/icons/16x16/actions/media-eject.png", 0, NULL);
icon = g_bytes_icon_new (bytes);
item = g_menu_item_new ("Bytes Icon", NULL);
g_menu_item_set_icon (item, icon);
@@ -561,19 +603,19 @@ bloat_pad_startup (GApplication *application)
g_object_unref (icon);
g_bytes_unref (bytes);
icon = G_ICON (gdk_pixbuf_new_from_resource ("/org/gtk/libgtk/icons/16x16/actions/gtk-preferences.png", NULL));
icon = G_ICON (gdk_pixbuf_new_from_resource ("/org/gtk/libgtk/icons/16x16/actions/folder-new.png", NULL));
item = g_menu_item_new ("Pixbuf", NULL);
g_menu_item_set_icon (item, icon);
g_menu_append_item (menu, item);
g_object_unref (item);
g_object_unref (icon);
file = g_file_new_for_uri ("resource:///org/gtk/libgtk/icons/16x16/actions/gtk-page-setup.png");
file = g_file_new_for_uri ("resource:///org/gtk/libgtk/icons/16x16/actions/bookmark-new.png");
icon = g_file_icon_new (file);
emblem = g_emblem_new (icon);
g_object_unref (icon);
g_object_unref (file);
file = g_file_new_for_uri ("resource:///org/gtk/libgtk/icons/16x16/actions/gtk-orientation-reverse-portrait.png");
file = g_file_new_for_uri ("resource:///org/gtk/libgtk/icons/16x16/actions/dialog-warning.png");
icon2 = g_file_icon_new (file);
icon = g_emblemed_icon_new (icon2, emblem);
item = g_menu_item_new ("Emblemed Icon", NULL);

View File

@@ -4,5 +4,10 @@
<gresource prefix="/org/gtk/bloatpad">
<file preprocess="xml-stripblanks">gtk/menus.ui</file>
<file preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
<file>icons/16x16/actions/format-justify-center-symbolic.symbolic.png</file>
<file>icons/16x16/actions/format-justify-left-symbolic.symbolic.png</file>
<file>icons/16x16/actions/format-justify-right-symbolic.symbolic.png</file>
<file>icons/16x16/actions/view-fullscreen-symbolic.symbolic.png</file>
<file>icons/16x16/actions/view-restore-symbolic.symbolic.png</file>
</gresource>
</gresources>

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

View File

@@ -132,7 +132,6 @@ activate (GtkApplication *app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *frame;
GtkWidget *drawing_area;
GtkGesture *drag;
GtkGesture *press;
@@ -142,14 +141,11 @@ activate (GtkApplication *app,
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
frame = gtk_frame_new (NULL);
gtk_window_set_child (GTK_WINDOW (window), frame);
drawing_area = gtk_drawing_area_new ();
/* set a minimum size */
gtk_widget_set_size_request (drawing_area, 100, 100);
gtk_frame_set_child (GTK_FRAME (frame), drawing_area);
gtk_window_set_child (GTK_WINDOW (window), drawing_area);
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (drawing_area), draw_cb, NULL, NULL);

View File

@@ -13,19 +13,19 @@ activate (GtkApplication *app,
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *box;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_window_set_child (GTK_WINDOW (window), box);
button = gtk_button_new_with_label ("Hello World");
gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_window_destroy), window);
gtk_box_append (GTK_BOX (box), button);
gtk_window_set_child (GTK_WINDOW (window), button);
gtk_widget_show (window);
}

View File

@@ -0,0 +1,10 @@
project('hello', 'c',
version: '4.3.0',
meson_version: '>= 0.50.0',
)
executable('hello',
[ 'hello-world.c' ],
dependencies: [ dependency('gtk4') ],
install: false
)

50
examples/labels.js Executable file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/env -S GI_TYPELIB_PATH=${PWD}/build/gtk:${GI_TYPELIB_PATH} LD_PRELOAD=${LD_PRELOAD}:${PWD}/build/gtk/libgtk-4.so gjs
imports.gi.versions['Gtk'] = '4.0';
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const DemoWidget = GObject.registerClass({
GTypeName: 'DemoWidget',
}, class DemoWidget extends Gtk.Widget {
_init(params = {}) {
super._init(params);
let layout_manager = new Gtk.GridLayout ();
this.set_layout_manager (layout_manager);
this.label1 = new Gtk.Label({ label: "Red",
hexpand: true,
vexpand: true });
this.label1.set_parent (this);
let child1 = layout_manager.get_layout_child (this.label1);
child1.set_row (0);
child1.set_column (0);
this.label2 = new Gtk.Label({ label: "Green",
hexpand: true,
vexpand: true });
this.label2.set_parent (this);
let child2 = layout_manager.get_layout_child (this.label2);
child2.set_row (0);
child2.set_column (1);
}
});
// Create a new application
let app = new Gtk.Application({ application_id: 'org.gtk.exampleapp' });
// When the application is launched…
app.connect('activate', () => {
// … create a new window …
let win = new Gtk.ApplicationWindow({ application: app });
// … with a button in it …
let widget = new DemoWidget();
win.set_child(widget);
win.present();
});
// Run the application
app.run([]);

View File

@@ -2,7 +2,6 @@ examples = [
'builder',
'drawing',
'grid-packing',
'hello-world',
'plugman',
'search-bar',
'sunny',

61
examples/squares.py Executable file
View File

@@ -0,0 +1,61 @@
#!/usr/bin/env -S GI_TYPELIB_PATH=${PWD}/build/gtk:${GI_TYPELIB_PATH} LD_PRELOAD=${LD_PRELOAD}:${PWD}/build/gtk/libgtk-4.so python3
import gi
gi.require_version('Gdk', '4.0')
gi.require_version('Gtk', '4.0')
from gi.repository import Gdk
from gi.repository import Gtk
from gi.repository import Graphene
class DemoWidget(Gtk.Widget):
__gtype_name__ = "DemoWidget"
def __init__(self):
super().__init__()
def do_measure(self, orientation, for_size: int):
# We need some space to draw
return 100, 200, -1, -1
def do_snapshot(self, snapshot):
# Draw four color squares
color = Gdk.RGBA()
rect = Graphene.Rect.alloc()
width = self.get_width() / 2
height = self.get_height() / 2
Gdk.RGBA.parse(color, "red")
rect.init(0, 0, width, height)
snapshot.append_color(color, rect)
Gdk.RGBA.parse(color, "green")
rect.init(width, 0, width, height)
snapshot.append_color(color, rect)
Gdk.RGBA.parse(color, "yellow")
rect.init(0, height, width, height)
snapshot.append_color(color, rect)
Gdk.RGBA.parse(color, "blue")
rect.init(width, height, width, height)
snapshot.append_color(color, rect)
def on_activate(app):
# Create a new window
win = Gtk.ApplicationWindow(application=app)
win.set_title("Squares")
icon = DemoWidget()
win.set_child(icon)
win.present()
# Create a new application
app = Gtk.Application(application_id='org.gtk.exampleapp')
app.connect('activate', on_activate)
# Run the application
app.run(None)

View File

@@ -12,7 +12,7 @@ new_window (GApplication *app,
gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (window), TRUE);
gtk_window_set_default_size ((GtkWindow*)window, 640, 480);
gtk_window_set_title (GTK_WINDOW (window), "Sunny");
gtk_window_set_icon_name (GTK_WINDOW (window), "sunny");
gtk_window_set_icon_name (GTK_WINDOW (window), "weather-clear-symbolic");
header = gtk_header_bar_new ();
gtk_window_set_titlebar (GTK_WINDOW (window), header);
@@ -78,7 +78,7 @@ show_about (GSimpleAction *action,
gtk_show_about_dialog (NULL,
"program-name", "Sunny",
"title", "About Sunny",
"logo-icon-name", "sunny",
"logo-icon-name", "weather-clear-symbolic",
"comments", "A cheap Bloatpad clone.",
NULL);
}

View File

@@ -48,6 +48,8 @@ void gdk_broadway_display_show_keyboard (GdkBroadwayDis
GDK_AVAILABLE_IN_ALL
void gdk_broadway_display_hide_keyboard (GdkBroadwayDisplay *display);
GDK_AVAILABLE_IN_4_4
int gdk_broadway_display_get_surface_scale (GdkDisplay *display);
GDK_AVAILABLE_IN_4_4
void gdk_broadway_display_set_surface_scale (GdkDisplay *display,
int scale);

View File

@@ -361,6 +361,29 @@ gdk_broadway_display_set_surface_scale (GdkDisplay *display,
gdk_monitor_set_scale_factor (self->monitor, scale);
}
/**
* gdk_broadway_display_get_surface_scale:
* @display: (type GdkBroadwayDisplay): the display
*
* Gets the surface scale that was previously set by the client or
* gdk_broadway_display_set_surface_scale().
*
* Returns: the scale for surfaces
*
* Since: 4.4
*/
int
gdk_broadway_display_get_surface_scale (GdkDisplay *display)
{
GdkBroadwayDisplay *self;
g_return_val_if_fail (GDK_IS_BROADWAY_DISPLAY (display), 1);
self = GDK_BROADWAY_DISPLAY (display);
return self->scale_factor;
}
static GListModel *
gdk_broadway_display_get_monitors (GdkDisplay *display)
{

View File

@@ -127,7 +127,9 @@ static const GdkDebugKey gdk_debug_keys[] = {
{ "gl-legacy", GDK_DEBUG_GL_LEGACY, "Use a legacy OpenGL context" },
{ "gl-gles", GDK_DEBUG_GL_GLES, "Use a GLES OpenGL context" },
{ "gl-debug", GDK_DEBUG_GL_DEBUG, "Insert debugging information in OpenGL" },
{ "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" },
{ "vulkan-validate", GDK_DEBUG_VULKAN_VALIDATE, "Load the Vulkan validation layer" },
{ "default-settings",GDK_DEBUG_DEFAULT_SETTINGS, "Force default values for xsettings" },
@@ -330,14 +332,13 @@ gdk_display_open_default (void)
}
/*< private >
*
* gdk_get_startup_notification_id
* gdk_get_startup_notification_id:
*
* Returns the original value of the DESKTOP_STARTUP_ID environment
* variable if it was defined and valid, or %NULL otherwise.
*
* Returns: (nullable) (transfer none): the original value of the
* DESKTOP_STARTUP_ID environment variable, or %NULL.
* DESKTOP_STARTUP_ID environment variable
*/
const char *
gdk_get_startup_notification_id (void)

View File

@@ -340,7 +340,7 @@ gdk_cursor_new_from_name (const char *name,
* @texture: the texture providing the pixel data
* @hotspot_x: the horizontal offset of the “hotspot” of the cursor
* @hotspot_y: the vertical offset of the “hotspot” of the cursor
* @fallback: (nullable): %NULL or the `GdkCursor` to fall back to when
* @fallback: (nullable): the `GdkCursor` to fall back to when
* this one cannot be supported
*
* Creates a new cursor from a `GdkTexture`.

View File

@@ -41,10 +41,12 @@ typedef enum {
GDK_DEBUG_GL_LEGACY = 1 << 15,
GDK_DEBUG_GL_GLES = 1 << 16,
GDK_DEBUG_GL_DEBUG = 1 << 17,
GDK_DEBUG_GL_GLX = 1 << 18,
GDK_DEBUG_VULKAN_DISABLE = 1 << 19,
GDK_DEBUG_VULKAN_VALIDATE = 1 << 20,
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 21
GDK_DEBUG_GL_EGL = 1 << 18,
GDK_DEBUG_GL_GLX = 1 << 19,
GDK_DEBUG_GL_WGL = 1 << 20,
GDK_DEBUG_VULKAN_DISABLE = 1 << 21,
GDK_DEBUG_VULKAN_VALIDATE = 1 << 22,
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 23,
} GdkDebugFlags;
extern guint _gdk_debug_flags;

View File

@@ -77,6 +77,23 @@ enum {
LAST_SIGNAL
};
typedef struct _GdkDisplayPrivate GdkDisplayPrivate;
struct _GdkDisplayPrivate {
/* The base context that all other contexts inherit from.
* This context is never exposed to public API and is
* allowed to have a %NULL surface.
*/
GdkGLContext *gl_context;
GError *gl_error;
guint rgba : 1;
guint composited : 1;
guint input_shapes : 1;
GdkDebugFlags debug_flags;
};
static void gdk_display_dispose (GObject *object);
static void gdk_display_finalize (GObject *object);
@@ -85,7 +102,7 @@ static GdkAppLaunchContext *gdk_display_real_get_app_launch_context (GdkDisplay
static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
G_DEFINE_TYPE_WITH_PRIVATE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
static void
gdk_display_get_property (GObject *object,
@@ -119,10 +136,14 @@ gdk_display_real_make_default (GdkDisplay *display)
{
}
static void
gdk_display_real_opened (GdkDisplay *display)
static GdkGLContext *
gdk_display_default_init_gl (GdkDisplay *display,
GError **error)
{
_gdk_display_manager_add_display (gdk_display_manager_get (), display);
g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
_("The current backend does not support OpenGL"));
return NULL;
}
static GdkSeat *
@@ -134,6 +155,12 @@ gdk_display_real_get_default_seat (GdkDisplay *display)
return display->seats->data;
}
static void
gdk_display_real_opened (GdkDisplay *display)
{
_gdk_display_manager_add_display (gdk_display_manager_get (), display);
}
static void
gdk_display_class_init (GdkDisplayClass *class)
{
@@ -143,10 +170,11 @@ gdk_display_class_init (GdkDisplayClass *class)
object_class->dispose = gdk_display_dispose;
object_class->get_property = gdk_display_get_property;
class->get_app_launch_context = gdk_display_real_get_app_launch_context;
class->opened = gdk_display_real_opened;
class->make_default = gdk_display_real_make_default;
class->get_app_launch_context = gdk_display_real_get_app_launch_context;
class->init_gl = gdk_display_default_init_gl;
class->get_default_seat = gdk_display_real_get_default_seat;
class->opened = gdk_display_real_opened;
/**
* GdkDisplay:composited: (attributes org.gtk.Property.get=gdk_display_is_composited)
@@ -294,6 +322,8 @@ free_device_grabs_foreach (gpointer key,
static void
gdk_display_init (GdkDisplay *display)
{
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
display->double_click_time = 250;
display->double_click_distance = 5;
@@ -304,22 +334,26 @@ gdk_display_init (GdkDisplay *display)
g_queue_init (&display->queued_events);
display->debug_flags = _gdk_debug_flags;
priv->debug_flags = _gdk_debug_flags;
display->composited = TRUE;
display->rgba = TRUE;
display->input_shapes = TRUE;
priv->composited = TRUE;
priv->rgba = TRUE;
priv->input_shapes = TRUE;
}
static void
gdk_display_dispose (GObject *object)
{
GdkDisplay *display = GDK_DISPLAY (object);
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
_gdk_display_manager_remove_display (gdk_display_manager_get (), display);
g_queue_clear (&display->queued_events);
g_clear_object (&priv->gl_context);
g_clear_error (&priv->gl_error);
G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
}
@@ -384,11 +418,11 @@ gdk_display_is_closed (GdkDisplay *display)
* gdk_display_get_event:
* @display: a `GdkDisplay`
*
* Gets the next `GdkEvent` to be processed for @display, fetching events from the
* windowing system if necessary.
* Gets the next `GdkEvent` to be processed for @display,
* fetching events from the windowing system if necessary.
*
* Returns: (nullable) (transfer full): the next `GdkEvent` to be processed,
* or %NULL if no events are pending
* Returns: (nullable) (transfer full): the next `GdkEvent`
* to be processed
*/
GdkEvent *
gdk_display_get_event (GdkDisplay *display)
@@ -998,21 +1032,25 @@ gdk_display_get_primary_clipboard (GdkDisplay *display)
gboolean
gdk_display_supports_input_shapes (GdkDisplay *display)
{
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
return display->input_shapes;
return priv->input_shapes;
}
void
gdk_display_set_input_shapes (GdkDisplay *display,
gboolean input_shapes)
{
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
g_return_if_fail (GDK_IS_DISPLAY (display));
if (display->input_shapes == input_shapes)
if (priv->input_shapes == input_shapes)
return;
display->input_shapes = input_shapes;
priv->input_shapes = input_shapes;
g_object_notify_by_pspec (G_OBJECT (display), props[PROP_INPUT_SHAPES]);
}
@@ -1157,32 +1195,136 @@ gdk_display_get_keymap (GdkDisplay *display)
return GDK_DISPLAY_GET_CLASS (display)->get_keymap (display);
}
/*< private >
* gdk_display_make_gl_context_current:
* @display: a `GdkDisplay`
* @context: (optional): a `GdkGLContext`
*
* Makes the given @context the current GL context, or unsets
* the current GL context if @context is %NULL.
*/
gboolean
gdk_display_make_gl_context_current (GdkDisplay *display,
GdkGLContext *context)
static void
gdk_display_init_gl (GdkDisplay *self)
{
return GDK_DISPLAY_GET_CLASS (display)->make_gl_context_current (display, context);
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
GdkGLContext *context;
gint64 before G_GNUC_UNUSED;
gint64 before2 G_GNUC_UNUSED;
before = GDK_PROFILER_CURRENT_TIME;
if (GDK_DISPLAY_DEBUG_CHECK (self, GL_DISABLE))
{
g_set_error_literal (&priv->gl_error, GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("GL support disabled via GDK_DEBUG"));
return;
}
context = GDK_DISPLAY_GET_CLASS (self)->init_gl (self, &priv->gl_error);
if (context == NULL)
return;
before2 = GDK_PROFILER_CURRENT_TIME;
if (!gdk_gl_context_realize (context, &priv->gl_error))
{
g_object_unref (context);
return;
}
gdk_profiler_end_mark (before2, "realize OpenGL context", NULL);
/* Only assign after realize, so GdkGLContext::realize() can use
* gdk_display_get_gl_context() == NULL to differentiate between
* the display's context and any other context.
*/
priv->gl_context = context;
gdk_profiler_end_mark (before, "initialize OpenGL", NULL);
}
/**
* gdk_display_prepare_gl:
* @self: a `GdkDisplay`
* @error: return location for a `GError`
*
* Checks that OpenGL is available for @self and ensures that it is
* properly initialized.
* When this fails, an @error will be set describing the error and this
* function returns %FALSE.
*
* Note that even if this function succeeds, creating a `GdkGLContext`
* may still fail.
*
* This function is idempotent. Calling it multiple times will just
* return the same value or error.
*
* You never need to call this function, GDK will call it automatically
* as needed. But you can use it as a check when setting up code that
* might make use of OpenGL.
*
* Returns: %TRUE if the display supports OpenGL
*
* Since: 4.4
**/
gboolean
gdk_display_prepare_gl (GdkDisplay *self,
GError **error)
{
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
g_return_val_if_fail (GDK_IS_DISPLAY (self), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
for (;;)
{
if (priv->gl_context)
return TRUE;
if (priv->gl_error != NULL)
{
if (error)
*error = g_error_copy (priv->gl_error);
return FALSE;
}
gdk_display_init_gl (self);
/* try again */
}
}
/*< private >
* gdk_display_get_gl_context:
* @self: the `GdkDisplay`
*
* Gets the GL context returned from [vfunc@Gdk.Display.init_gl]
* previously.
*
* If that function has not been called yet or did fail, %NULL is
* returned.
* Call [method@Gdk.Display.prepare_gl] to avoid this.
*
* Returns: The `GdkGLContext`
*/
GdkGLContext *
gdk_display_get_gl_context (GdkDisplay *self)
{
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
return priv->gl_context;
}
GdkDebugFlags
gdk_display_get_debug_flags (GdkDisplay *display)
{
return display ? display->debug_flags : _gdk_debug_flags;
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
return display ? priv->debug_flags : _gdk_debug_flags;
}
void
gdk_display_set_debug_flags (GdkDisplay *display,
GdkDebugFlags flags)
{
display->debug_flags = flags;
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
priv->debug_flags = flags;
}
/**
@@ -1207,21 +1349,25 @@ gdk_display_set_debug_flags (GdkDisplay *display,
gboolean
gdk_display_is_composited (GdkDisplay *display)
{
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
return display->composited;
return priv->composited;
}
void
gdk_display_set_composited (GdkDisplay *display,
gboolean composited)
{
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
g_return_if_fail (GDK_IS_DISPLAY (display));
if (display->composited == composited)
if (priv->composited == composited)
return;
display->composited = composited;
priv->composited = composited;
g_object_notify_by_pspec (G_OBJECT (display), props[PROP_COMPOSITED]);
}
@@ -1248,21 +1394,25 @@ gdk_display_set_composited (GdkDisplay *display,
gboolean
gdk_display_is_rgba (GdkDisplay *display)
{
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
return display->rgba;
return priv->rgba;
}
void
gdk_display_set_rgba (GdkDisplay *display,
gboolean rgba)
{
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
g_return_if_fail (GDK_IS_DISPLAY (display));
if (display->rgba == rgba)
if (priv->rgba == rgba)
return;
display->rgba = rgba;
priv->rgba = rgba;
g_object_notify_by_pspec (G_OBJECT (display), props[PROP_RGBA]);
}

View File

@@ -68,6 +68,10 @@ gboolean gdk_display_is_rgba (GdkDisplay *display);
GDK_AVAILABLE_IN_ALL
gboolean gdk_display_supports_input_shapes (GdkDisplay *display);
GDK_AVAILABLE_IN_4_4
gboolean gdk_display_prepare_gl (GdkDisplay *self,
GError **error);
GDK_AVAILABLE_IN_ALL
GdkDisplay *gdk_display_get_default (void);

View File

@@ -323,7 +323,8 @@ gdk_display_manager_get_default_display (GdkDisplayManager *manager)
* Gets the default `GdkDisplay`.
*
* This is a convenience function for:
* `gdk_display_manager_get_default_display (gdk_display_manager_get ())`.
*
* gdk_display_manager_get_default_display (gdk_display_manager_get ())
*
* Returns: (nullable) (transfer none): a `GdkDisplay`, or %NULL if
* there is no default display

View File

@@ -102,11 +102,6 @@ struct _GdkDisplay
guint vulkan_refcount;
#endif /* GDK_RENDERING_VULKAN */
guint rgba : 1;
guint composited : 1;
guint input_shapes : 1;
GdkDebugFlags debug_flags;
GList *seats;
};
@@ -145,8 +140,8 @@ struct _GdkDisplayClass
GdkKeymap * (*get_keymap) (GdkDisplay *display);
gboolean (*make_gl_context_current) (GdkDisplay *display,
GdkGLContext *context);
GdkGLContext * (*init_gl) (GdkDisplay *display,
GError **error);
GdkSeat * (*get_default_seat) (GdkDisplay *display);
@@ -211,8 +206,7 @@ GdkSurface * gdk_display_create_surface (GdkDisplay *display
int width,
int height);
gboolean gdk_display_make_gl_context_current (GdkDisplay *display,
GdkGLContext *context);
GdkGLContext * gdk_display_get_gl_context (GdkDisplay *display);
void gdk_display_set_rgba (GdkDisplay *display,
gboolean rgba);

View File

@@ -43,6 +43,7 @@
typedef struct _GdkDrawContextPrivate GdkDrawContextPrivate;
struct _GdkDrawContextPrivate {
GdkDisplay *display;
GdkSurface *surface;
cairo_region_t *frame_region;
@@ -77,6 +78,7 @@ gdk_draw_context_dispose (GObject *gobject)
priv->surface->draw_contexts = g_slist_remove (priv->surface->draw_contexts, context);
g_clear_object (&priv->surface);
}
g_clear_object (&priv->display);
G_OBJECT_CLASS (gdk_draw_context_parent_class)->dispose (gobject);
}
@@ -92,10 +94,31 @@ gdk_draw_context_set_property (GObject *gobject,
switch (prop_id)
{
case PROP_DISPLAY:
if (priv->display != NULL)
{
g_assert (g_value_get_object (value) == NULL);
}
else
{
priv->display = g_value_dup_object (value);
}
break;
case PROP_SURFACE:
priv->surface = g_value_dup_object (value);
g_assert (priv->surface != NULL);
priv->surface->draw_contexts = g_slist_prepend (priv->surface->draw_contexts, context);
if (priv->surface)
{
priv->surface->draw_contexts = g_slist_prepend (priv->surface->draw_contexts, context);
if (priv->display)
{
g_assert (priv->display == gdk_surface_get_display (priv->surface));
}
else
{
priv->display = g_object_ref (gdk_surface_get_display (priv->surface));
}
}
break;
default:
@@ -148,7 +171,8 @@ gdk_draw_context_class_init (GdkDrawContextClass *klass)
P_("Display"),
P_("The GDK display used to create the context"),
GDK_TYPE_DISPLAY,
G_PARAM_READABLE |
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
/**
@@ -228,7 +252,7 @@ gdk_draw_context_get_display (GdkDrawContext *context)
g_return_val_if_fail (GDK_IS_DRAW_CONTEXT (context), NULL);
return priv->surface ? gdk_surface_get_display (priv->surface) : NULL;
return priv->display;
}
/**

View File

@@ -294,8 +294,11 @@ gdk_drop_finalize (GObject *object)
/* someone forgot to send a LEAVE signal */
g_warn_if_fail (!priv->entered);
/* Should we emit finish() here if necessary?
* For now that's the backends' job */
* For now that's the backends' job
*/
g_warn_if_fail (priv->state != GDK_DROP_STATE_DROPPING);
g_clear_object (&priv->device);
g_clear_object (&priv->drag);
@@ -571,7 +574,7 @@ gdk_drop_get_drag (GdkDrop *self)
* the ones provided by [method@Gdk.Drop.get_actions]. Those actions may
* change in the future, even depending on the actions you provide here.
*
* The @preferred action is a hint to the drag'n'drop mechanism about which
* The @preferred action is a hint to the drag-and-drop mechanism about which
* action to use when multiple actions are possible.
*
* This function should be called by drag destinations in response to
@@ -862,7 +865,7 @@ gdk_drop_read_value_internal (GdkDrop *self,
* then call [method@Gdk.Drop.read_value_finish] to get the resulting
* `GValue`.
*
* For local drag'n'drop operations that are available in the given
* For local drag-and-drop operations that are available in the given
* `GType`, the value will be copied directly. Otherwise, GDK will
* try to use [func@Gdk.content_deserialize_async] to convert the data.
*/

View File

@@ -481,11 +481,11 @@ _gdk_frame_clock_begin_frame (GdkFrameClock *frame_clock)
* for the current frame or a recent frame.
*
* The `GdkFrameTimings` object may not yet be complete: see
* [method@Gdk.FrameTimings.get_complete].
* [method@Gdk.FrameTimings.get_complete] and
* [method@Gdk.FrameClock.get_history_start].
*
* Returns: (nullable) (transfer none): the `GdkFrameTimings` object
* for the specified frame, or %NULL if it is not available. See
* [method@Gdk.FrameClock.get_history_start].
* for the specified frame, or %NULL if it is not available
*/
GdkFrameTimings *
gdk_frame_clock_get_timings (GdkFrameClock *frame_clock,

View File

@@ -89,8 +89,6 @@
#include <epoxy/gl.h>
typedef struct {
GdkGLContext *shared_context;
int major;
int minor;
int gl_version;
@@ -127,7 +125,28 @@ G_DEFINE_QUARK (gdk-gl-error-quark, gdk_gl_error)
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkGLContext, gdk_gl_context, GDK_TYPE_DRAW_CONTEXT)
static GPrivate thread_current_context = G_PRIVATE_INIT (g_object_unref);
typedef struct _MaskedContext MaskedContext;
static inline MaskedContext *
mask_context (GdkGLContext *context,
gboolean surfaceless)
{
return (MaskedContext *) GSIZE_TO_POINTER (GPOINTER_TO_SIZE (context) | (surfaceless ? 1 : 0));
}
static inline GdkGLContext *
unmask_context (MaskedContext *mask)
{
return GDK_GL_CONTEXT (GSIZE_TO_POINTER (GPOINTER_TO_SIZE (mask) & ~(gsize) 1));
}
static void
unref_unmasked (gpointer data)
{
g_object_unref (unmask_context (data));
}
static GPrivate thread_current_context = G_PRIVATE_INIT (unref_unmasked);
static void
gdk_gl_context_clear_old_updated_area (GdkGLContext *context)
@@ -144,17 +163,14 @@ static void
gdk_gl_context_dispose (GObject *gobject)
{
GdkGLContext *context = GDK_GL_CONTEXT (gobject);
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
GdkGLContext *current;
MaskedContext *current;
gdk_gl_context_clear_old_updated_area (context);
current = g_private_get (&thread_current_context);
if (current == context)
if (unmask_context (current) == context)
g_private_replace (&thread_current_context, NULL);
g_clear_object (&priv->shared_context);
G_OBJECT_CLASS (gdk_gl_context_parent_class)->dispose (gobject);
}
@@ -174,17 +190,10 @@ gdk_gl_context_set_property (GObject *gobject,
const GValue *value,
GParamSpec *pspec)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private ((GdkGLContext *) gobject);
switch (prop_id)
{
case PROP_SHARED_CONTEXT:
{
GdkGLContext *context = g_value_get_object (value);
if (context != NULL)
priv->shared_context = g_object_ref (context);
}
g_assert (g_value_get_object (value) == NULL);
break;
default:
@@ -198,12 +207,10 @@ gdk_gl_context_get_property (GObject *gobject,
GValue *value,
GParamSpec *pspec)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private ((GdkGLContext *) gobject);
switch (prop_id)
{
case PROP_SHARED_CONTEXT:
g_value_set_object (value, priv->shared_context);
g_value_set_object (value, NULL);
break;
default:
@@ -333,23 +340,27 @@ gdk_gl_context_real_get_damage (GdkGLContext *context)
});
}
static gboolean
gdk_gl_context_real_is_shared (GdkGLContext *self,
GdkGLContext *other)
{
if (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (self)) != gdk_draw_context_get_display (GDK_DRAW_CONTEXT (other)))
return FALSE;
/* XXX: Should we check es or legacy here? */
return TRUE;
}
static void
gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
cairo_region_t *region)
{
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
GdkSurface *surface;
GdkGLContext *shared;
cairo_region_t *damage;
int ww, wh;
shared = gdk_gl_context_get_shared_context (context);
if (shared)
{
GDK_DRAW_CONTEXT_GET_CLASS (GDK_DRAW_CONTEXT (shared))->begin_frame (GDK_DRAW_CONTEXT (shared), region);
return;
}
damage = GDK_GL_CONTEXT_GET_CLASS (context)->get_damage (context);
if (context->old_updated_area[1])
@@ -379,15 +390,6 @@ static void
gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
cairo_region_t *painted)
{
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
GdkGLContext *shared;
shared = gdk_gl_context_get_shared_context (context);
if (shared)
{
GDK_DRAW_CONTEXT_GET_CLASS (GDK_DRAW_CONTEXT (shared))->end_frame (GDK_DRAW_CONTEXT (shared), painted);
return;
}
}
static void
@@ -406,6 +408,7 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
klass->realize = gdk_gl_context_real_realize;
klass->get_damage = gdk_gl_context_real_get_damage;
klass->is_shared = gdk_gl_context_real_is_shared;
draw_context_class->begin_frame = gdk_gl_context_real_begin_frame;
draw_context_class->end_frame = gdk_gl_context_real_end_frame;
@@ -414,7 +417,13 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
/**
* GdkGLContext:shared-context: (attributes org.gtk.Property.get=gdk_gl_context_get_shared_context)
*
* The `GdkGLContext` that this context is sharing data with, or %NULL
* Always %NULL
*
* As many contexts can share data now and no single shared context exists
* anymore, this function has been deprecated and now always returns %NULL.
*
* Deprecated: 4.4: Use [method@Gdk.GLContext.is_shared] to check if contexts
* can be shared.
*/
obj_pspecs[PROP_SHARED_CONTEXT] =
g_param_spec_object ("shared-context",
@@ -423,7 +432,8 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
GDK_TYPE_GL_CONTEXT,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
G_PARAM_STATIC_STRINGS |
G_PARAM_DEPRECATED);
gobject_class->set_property = gdk_gl_context_set_property;
gobject_class->get_property = gdk_gl_context_get_property;
@@ -441,6 +451,21 @@ gdk_gl_context_init (GdkGLContext *self)
priv->use_es = -1;
}
/* Must have called gdk_display_prepare_gl() before */
GdkGLContext *
gdk_gl_context_new_for_surface (GdkSurface *surface)
{
GdkDisplay *display = gdk_surface_get_display (surface);
GdkGLContext *shared = gdk_display_get_gl_context (display);
/* assert gdk_display_prepare_gl() had been called */
g_assert (shared);
return g_object_new (G_OBJECT_TYPE (shared),
"surface", surface,
NULL);
}
GdkGLContextPaintData *
gdk_gl_context_get_paint_data (GdkGLContext *context)
{
@@ -812,6 +837,42 @@ gdk_gl_context_set_is_legacy (GdkGLContext *context,
priv->is_legacy = !!is_legacy;
}
/**
* gdk_gl_context_is_shared:
* @self: a `GdkGLContext`
* @other: the `GdkGLContext` that should be compatible with @self
*
* Checks if the two GL contexts can share resources.
*
* When they can, the texture IDs from @other can be used in @self. This
* is particularly useful when passing `GdkGLTexture` objects between
* different contexts.
*
* Contexts created for the same display with the same properties will
* always be compatible, even if they are created for different surfaces.
* For other contexts it depends on the GL backend.
*
* Both contexts must be realized for this check to succeed. If either one
* is not, this function will return %FALSE.
*
* Returns: %TRUE if the two GL contexts are compatible.
*/
gboolean
gdk_gl_context_is_shared (GdkGLContext *self,
GdkGLContext *other)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
GdkGLContextPrivate *priv_other = gdk_gl_context_get_instance_private (other);
g_return_val_if_fail (GDK_IS_GL_CONTEXT (self), FALSE);
g_return_val_if_fail (GDK_IS_GL_CONTEXT (other), FALSE);
if (!priv->realized || !priv_other->realized)
return FALSE;
return GDK_GL_CONTEXT_GET_CLASS (self)->is_shared (self, other);
}
/**
* gdk_gl_context_set_use_es:
* @context: a `GdkGLContext`
@@ -1092,12 +1153,16 @@ void
gdk_gl_context_make_current (GdkGLContext *context)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
GdkGLContext *current;
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));
masked_context = mask_context (context, surfaceless);
current = g_private_get (&thread_current_context);
if (current == context)
if (current == masked_context)
return;
/* we need to realize the GdkGLContext if it wasn't explicitly realized */
@@ -1114,11 +1179,15 @@ gdk_gl_context_make_current (GdkGLContext *context)
}
}
if (gdk_display_make_gl_context_current (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)), context))
if (!GDK_GL_CONTEXT_GET_CLASS (context)->make_current (context, surfaceless))
{
g_private_replace (&thread_current_context, g_object_ref (context));
gdk_gl_context_check_extensions (context);
g_warning ("gdk_gl_context_make_current() failed");
return;
}
g_object_ref (context);
g_private_replace (&thread_current_context, masked_context);
gdk_gl_context_check_extensions (context);
}
/**
@@ -1157,18 +1226,22 @@ gdk_gl_context_get_surface (GdkGLContext *context)
* gdk_gl_context_get_shared_context: (attributes org.gtk.Method.get_property=shared-context)
* @context: a `GdkGLContext`
*
* Retrieves the `GdkGLContext` that this @context share data with.
* Used to retrieves the `GdkGLContext` that this @context share data with.
*
* Returns: (nullable) (transfer none): a `GdkGLContext`
* As many contexts can share data now and no single shared context exists
* anymore, this function has been deprecated and now always returns %NULL.
*
* Returns: (nullable) (transfer none): %NULL
*
* Deprecated: 4.4: Use [method@Gdk.GLContext.is_shared] to check if contexts
* can be shared.
*/
GdkGLContext *
gdk_gl_context_get_shared_context (GdkGLContext *context)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
return priv->shared_context;
return NULL;
}
/**
@@ -1208,12 +1281,14 @@ gdk_gl_context_get_version (GdkGLContext *context,
void
gdk_gl_context_clear_current (void)
{
GdkGLContext *current;
MaskedContext *current;
current = g_private_get (&thread_current_context);
if (current != NULL)
{
if (gdk_display_make_gl_context_current (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (current)), NULL))
GdkGLContext *context = unmask_context (current);
if (GDK_GL_CONTEXT_GET_CLASS (context)->clear_current (context))
g_private_replace (&thread_current_context, NULL);
}
}
@@ -1228,11 +1303,11 @@ gdk_gl_context_clear_current (void)
GdkGLContext *
gdk_gl_context_get_current (void)
{
GdkGLContext *current;
MaskedContext *current;
current = g_private_get (&thread_current_context);
return current;
return unmask_context (current);
}
gboolean

View File

@@ -45,8 +45,8 @@ GType gdk_gl_context_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GdkDisplay * gdk_gl_context_get_display (GdkGLContext *context);
GDK_AVAILABLE_IN_ALL
GdkSurface * gdk_gl_context_get_surface (GdkGLContext *context);
GDK_AVAILABLE_IN_ALL
GdkSurface * gdk_gl_context_get_surface (GdkGLContext *context);
GDK_DEPRECATED_IN_4_4_FOR(gdk_gl_context_is_shared)
GdkGLContext * gdk_gl_context_get_shared_context (GdkGLContext *context);
GDK_AVAILABLE_IN_ALL
void gdk_gl_context_get_version (GdkGLContext *context,
@@ -54,6 +54,9 @@ void gdk_gl_context_get_version (GdkGLContext *
int *minor);
GDK_AVAILABLE_IN_ALL
gboolean gdk_gl_context_is_legacy (GdkGLContext *context);
GDK_AVAILABLE_IN_4_4
gboolean gdk_gl_context_is_shared (GdkGLContext *self,
GdkGLContext *other);
GDK_AVAILABLE_IN_ALL
void gdk_gl_context_set_required_version (GdkGLContext *context,

View File

@@ -27,6 +27,13 @@
G_BEGIN_DECLS
/* Version requirements for EGL contexts.
*
* If you add support for EGL to your backend, please require this.
*/
#define GDK_EGL_MIN_VERSION_MAJOR (1)
#define GDK_EGL_MIN_VERSION_MINOR (4)
#define GDK_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GL_CONTEXT, GdkGLContextClass))
#define GDK_IS_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_GL_CONTEXT))
#define GDK_GL_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_GL_CONTEXT, GdkGLContextClass))
@@ -45,10 +52,16 @@ struct _GdkGLContextClass
{
GdkDrawContextClass parent_class;
gboolean (* realize) (GdkGLContext *context,
GError **error);
gboolean (* realize) (GdkGLContext *context,
GError **error);
cairo_region_t * (* get_damage) (GdkGLContext *context);
gboolean (* make_current) (GdkGLContext *context,
gboolean surfaceless);
gboolean (* clear_current) (GdkGLContext *context);
cairo_region_t * (* get_damage) (GdkGLContext *context);
gboolean (* is_shared) (GdkGLContext *self,
GdkGLContext *other);
};
typedef struct {
@@ -73,6 +86,8 @@ typedef struct {
guint use_es : 1;
} GdkGLContextPaintData;
GdkGLContext * gdk_gl_context_new_for_surface (GdkSurface *surface);
void gdk_gl_context_set_is_legacy (GdkGLContext *context,
gboolean is_legacy);

View File

@@ -53,8 +53,8 @@ G_BEGIN_DECLS
* CAIRO_FORMAT_ARGB32 is represented by different `GdkMemoryFormats`
* on architectures with different endiannesses.
*
* Its naming is modelled after VkFormat (see
* https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VkFormat
* Its naming is modelled after
* [VkFormat](https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VkFormat)
* for details).
*/
typedef enum {

View File

@@ -1065,87 +1065,23 @@ gdk_surface_get_mapped (GdkSurface *surface)
return GDK_SURFACE_IS_MAPPED (surface);
}
GdkGLContext *
gdk_surface_get_shared_data_gl_context (GdkSurface *surface)
{
static int in_shared_data_creation;
GdkDisplay *display;
GdkGLContext *context;
if (in_shared_data_creation)
return NULL;
in_shared_data_creation = 1;
display = gdk_surface_get_display (surface);
context = (GdkGLContext *)g_object_get_data (G_OBJECT (display), "gdk-gl-shared-data-context");
if (context == NULL)
{
GError *error = NULL;
context = GDK_SURFACE_GET_CLASS (surface)->create_gl_context (surface, FALSE, NULL, &error);
if (context == NULL)
{
g_warning ("Failed to create shared context: %s", error->message);
g_clear_error (&error);
}
gdk_gl_context_realize (context, &error);
if (context == NULL)
{
g_warning ("Failed to realize shared context: %s", error->message);
g_clear_error (&error);
}
g_object_set_data (G_OBJECT (display), "gdk-gl-shared-data-context", context);
}
in_shared_data_creation = 0;
return context;
}
GdkGLContext *
gdk_surface_get_paint_gl_context (GdkSurface *surface,
GError **error)
GError **error)
{
GError *internal_error = NULL;
if (GDK_DISPLAY_DEBUG_CHECK (surface->display, GL_DISABLE))
{
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("GL support disabled via GDK_DEBUG"));
return NULL;
}
if (!gdk_display_prepare_gl (surface->display, error))
return NULL;
if (surface->gl_paint_context == NULL)
{
GdkSurfaceClass *class = GDK_SURFACE_GET_CLASS (surface);
if (class->create_gl_context == NULL)
{
g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
_("The current backend does not support OpenGL"));
return NULL;
}
surface->gl_paint_context =
class->create_gl_context (surface, TRUE, NULL, &internal_error);
surface->gl_paint_context = gdk_surface_create_gl_context (surface, error);
if (surface->gl_paint_context == NULL)
return NULL;
}
if (internal_error != NULL)
if (!gdk_gl_context_realize (surface->gl_paint_context, error))
{
g_propagate_error (error, internal_error);
g_clear_object (&(surface->gl_paint_context));
return NULL;
}
gdk_gl_context_realize (surface->gl_paint_context, &internal_error);
if (internal_error != NULL)
{
g_propagate_error (error, internal_error);
g_clear_object (&(surface->gl_paint_context));
g_clear_object (&surface->gl_paint_context);
return NULL;
}
@@ -1170,19 +1106,13 @@ GdkGLContext *
gdk_surface_create_gl_context (GdkSurface *surface,
GError **error)
{
GdkGLContext *paint_context;
g_return_val_if_fail (GDK_IS_SURFACE (surface), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
paint_context = gdk_surface_get_paint_gl_context (surface, error);
if (paint_context == NULL)
if (!gdk_display_prepare_gl (surface->display, error))
return NULL;
return GDK_SURFACE_GET_CLASS (surface)->create_gl_context (surface,
FALSE,
paint_context,
error);
return gdk_gl_context_new_for_surface (surface);
}
/**

View File

@@ -160,10 +160,6 @@ struct _GdkSurfaceClass
void (* set_opaque_region) (GdkSurface *surface,
cairo_region_t *region);
GdkGLContext *(*create_gl_context) (GdkSurface *surface,
gboolean attached,
GdkGLContext *share,
GError **error);
void (* request_layout) (GdkSurface *surface);
gboolean (* compute_size) (GdkSurface *surface);
};
@@ -266,7 +262,6 @@ void _gdk_surface_update_size (GdkSurface *surface);
GdkGLContext * gdk_surface_get_paint_gl_context (GdkSurface *surface,
GError **error);
GdkGLContext * gdk_surface_get_shared_data_gl_context (GdkSurface *surface);
gboolean gdk_surface_handle_event (GdkEvent *event);
GdkSeat * gdk_surface_get_seat_from_event (GdkSurface *surface,

View File

@@ -533,7 +533,7 @@ gdk_texture_get_render_data (GdkTexture *self,
/**
* gdk_texture_save_to_png:
* @texture: a `GdkTexture`
* @filename: the filename to store to
* @filename: (type filename): the filename to store to
*
* Store the given @texture to the @filename as a PNG file.
*

View File

@@ -28,7 +28,9 @@
#import "GdkMacosGLView.h"
#import "GdkMacosWindow.h"
#include "gdkmacosclipboard-private.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacosdrop-private.h"
#include "gdkmacosmonitor-private.h"
#include "gdkmacossurface-private.h"
#include "gdkmacospopupsurface-private.h"
@@ -287,6 +289,9 @@ typedef NSString *CALayerContentsGravity;
[self setContentView:view];
[view release];
/* TODO: We might want to make this more extensible at some point */
_gdk_macos_clipboard_register_drag_types (self);
return self;
}
@@ -597,25 +602,86 @@ typedef NSString *CALayerContentsGravity;
-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
return NSDragOperationNone;
NSPoint location = [sender draggingLocation];
NSDragOperation ret;
GdkMacosDrop *drop;
if (!(drop = _gdk_macos_drop_new ([self gdkSurface], sender)))
return NSDragOperationNone;
_gdk_macos_display_set_drop ([self gdkDisplay],
[sender draggingSequenceNumber],
GDK_DROP (drop));
gdk_drop_emit_enter_event (GDK_DROP (drop),
TRUE,
location.x,
GDK_SURFACE (gdk_surface)->height - location.y,
GDK_CURRENT_TIME);
ret = _gdk_macos_drop_operation (drop);
g_object_unref (drop);
return ret;
}
-(void)draggingEnded:(id <NSDraggingInfo>)sender
{
_gdk_macos_display_set_drop ([self gdkDisplay], [sender draggingSequenceNumber], NULL);
}
-(void)draggingExited:(id <NSDraggingInfo>)sender
{
NSInteger sequence_number = [sender draggingSequenceNumber];
GdkDrop *drop = _gdk_macos_display_find_drop ([self gdkDisplay], sequence_number);
if (drop != NULL)
gdk_drop_emit_leave_event (drop, TRUE, GDK_CURRENT_TIME);
_gdk_macos_display_set_drop ([self gdkDisplay], sequence_number, NULL);
}
-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
{
return NSDragOperationNone;
NSInteger sequence_number = [sender draggingSequenceNumber];
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
GdkDrop *drop = _gdk_macos_display_find_drop (GDK_MACOS_DISPLAY (display), sequence_number);
NSPoint location = [sender draggingLocation];
if (drop == NULL)
return NSDragOperationNone;
_gdk_macos_drop_update_actions (GDK_MACOS_DROP (drop), sender);
gdk_drop_emit_motion_event (drop,
TRUE,
location.x,
GDK_SURFACE (gdk_surface)->height - location.y,
GDK_CURRENT_TIME);
return _gdk_macos_drop_operation (GDK_MACOS_DROP (drop));
}
-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
return YES;
NSInteger sequence_number = [sender draggingSequenceNumber];
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
GdkDrop *drop = _gdk_macos_display_find_drop (GDK_MACOS_DISPLAY (display), sequence_number);
NSPoint location = [sender draggingLocation];
if (drop == NULL)
return NO;
gdk_drop_emit_drop_event (drop,
TRUE,
location.x,
GDK_SURFACE (gdk_surface)->height - location.y,
GDK_CURRENT_TIME);
gdk_drop_emit_leave_event (drop, TRUE, GDK_CURRENT_TIME);
return GDK_MACOS_DROP (drop)->finish_action != 0;
}
-(BOOL)wantsPeriodicDraggingUpdates

View File

@@ -35,11 +35,24 @@ typedef NSString *NSPasteboardType;
G_DECLARE_FINAL_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK, MACOS_CLIPBOARD, GdkClipboard)
GdkClipboard *_gdk_macos_clipboard_new (GdkMacosDisplay *display);
void _gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self);
NSPasteboardType _gdk_macos_clipboard_to_ns_type (const char *mime_type,
NSPasteboardType *alternate);
const char *_gdk_macos_clipboard_from_ns_type (NSPasteboardType ns_type);
GdkClipboard *_gdk_macos_clipboard_new (GdkMacosDisplay *display);
void _gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self);
NSPasteboardType _gdk_macos_clipboard_to_ns_type (const char *mime_type,
NSPasteboardType *alternate);
const char *_gdk_macos_clipboard_from_ns_type (NSPasteboardType ns_type);
void _gdk_macos_clipboard_register_drag_types (NSWindow *window);
GdkContentFormats *_gdk_macos_pasteboard_load_formats (NSPasteboard *pasteboard);
void _gdk_macos_pasteboard_read_async (GObject *object,
NSPasteboard *pasteboard,
GdkContentFormats *formats,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GInputStream *_gdk_macos_pasteboard_read_finish (GObject *object,
GAsyncResult *result,
const char **out_mime_type,
GError **error);
@interface GdkMacosClipboardDataProvider : NSObject <NSPasteboardItemDataProvider>
{

View File

@@ -172,17 +172,15 @@ populate_content_formats (GdkContentFormatsBuilder *builder,
}
static GdkContentFormats *
load_offer_formats (GdkMacosClipboard *self)
load_offer_formats (NSPasteboard *pasteboard)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkContentFormatsBuilder *builder;
GdkContentFormats *formats;
g_assert (GDK_IS_MACOS_CLIPBOARD (self));
builder = gdk_content_formats_builder_new ();
for (NSPasteboardType type in [self->pasteboard types])
for (NSPasteboardType type in [pasteboard types])
populate_content_formats (builder, type);
formats = gdk_content_formats_builder_free_to_formats (builder);
@@ -201,7 +199,7 @@ _gdk_macos_clipboard_load_contents (GdkMacosClipboard *self)
change_count = [self->pasteboard changeCount];
formats = load_offer_formats (self);
formats = load_offer_formats (self->pasteboard);
gdk_clipboard_claim_remote (GDK_CLIPBOARD (self), formats);
gdk_content_formats_unref (formats);
@@ -225,125 +223,13 @@ _gdk_macos_clipboard_read_async (GdkClipboard *clipboard,
GAsyncReadyCallback callback,
gpointer user_data)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkMacosClipboard *self = (GdkMacosClipboard *)clipboard;
GdkContentFormats *offer_formats = NULL;
const char *mime_type;
GInputStream *stream = NULL;
GTask *task = NULL;
g_assert (GDK_IS_MACOS_CLIPBOARD (self));
g_assert (formats != NULL);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, _gdk_macos_clipboard_read_async);
g_task_set_priority (task, io_priority);
offer_formats = load_offer_formats (GDK_MACOS_CLIPBOARD (clipboard));
mime_type = gdk_content_formats_match_mime_type (formats, offer_formats);
if (mime_type == NULL)
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
"%s",
_("No compatible transfer format found"));
goto cleanup;
}
if (strcmp (mime_type, "text/plain;charset=utf-8") == 0)
{
NSString *nsstr = [self->pasteboard stringForType:NSPasteboardTypeString];
if (nsstr != NULL)
{
const char *str = [nsstr UTF8String];
stream = g_memory_input_stream_new_from_data (g_strdup (str),
strlen (str) + 1,
g_free);
}
}
else if (strcmp (mime_type, "text/uri-list") == 0)
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
if ([[self->pasteboard types] containsObject:PTYPE(FILE_URL)])
{
GString *str = g_string_new (NULL);
NSArray *files = [self->pasteboard propertyListForType:NSFilenamesPboardType];
gsize n_files = [files count];
char *data;
guint len;
for (gsize i = 0; i < n_files; ++i)
{
NSString* uriString = [files objectAtIndex:i];
uriString = [@"file://" stringByAppendingString:uriString];
uriString = [uriString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
g_string_append_printf (str,
"%s\r\n",
[uriString cStringUsingEncoding:NSUTF8StringEncoding]);
}
len = str->len;
data = g_string_free (str, FALSE);
stream = g_memory_input_stream_new_from_data (data, len, g_free);
}
G_GNUC_END_IGNORE_DEPRECATIONS;
}
else if (strcmp (mime_type, "application/x-color") == 0)
{
NSColorSpace *colorspace;
NSColor *nscolor;
guint16 color[4];
colorspace = [NSColorSpace genericRGBColorSpace];
nscolor = [[NSColor colorFromPasteboard:self->pasteboard]
colorUsingColorSpace:colorspace];
color[0] = 0xffff * [nscolor redComponent];
color[1] = 0xffff * [nscolor greenComponent];
color[2] = 0xffff * [nscolor blueComponent];
color[3] = 0xffff * [nscolor alphaComponent];
stream = g_memory_input_stream_new_from_data (g_memdup2 (&color, sizeof color),
sizeof color,
g_free);
}
else if (strcmp (mime_type, "image/tiff") == 0)
{
NSData *data = [self->pasteboard dataForType:PTYPE(TIFF)];
stream = create_stream_from_nsdata (data);
}
else if (strcmp (mime_type, "image/png") == 0)
{
NSData *data = [self->pasteboard dataForType:PTYPE(PNG)];
stream = create_stream_from_nsdata (data);
}
if (stream != NULL)
{
g_task_set_task_data (task, g_strdup (mime_type), g_free);
g_task_return_pointer (task, g_steal_pointer (&stream), g_object_unref);
}
else
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_FAILED,
_("Failed to decode contents with mime-type of '%s'"),
mime_type);
}
cleanup:
g_clear_object (&task);
g_clear_pointer (&offer_formats, gdk_content_formats_unref);
GDK_END_MACOS_ALLOC_POOL;
_gdk_macos_pasteboard_read_async (G_OBJECT (clipboard),
GDK_MACOS_CLIPBOARD (clipboard)->pasteboard,
formats,
io_priority,
cancellable,
callback,
user_data);
}
static GInputStream *
@@ -352,15 +238,7 @@ _gdk_macos_clipboard_read_finish (GdkClipboard *clipboard,
const char **out_mime_type,
GError **error)
{
GTask *task = (GTask *)result;
g_assert (GDK_IS_MACOS_CLIPBOARD (clipboard));
g_assert (G_IS_TASK (task));
if (out_mime_type != NULL)
*out_mime_type = g_strdup (g_task_get_task_data (task));
return g_task_propagate_pointer (task, error);
return _gdk_macos_pasteboard_read_finish (G_OBJECT (clipboard), result, out_mime_type, error);
}
static void
@@ -622,4 +500,170 @@ on_data_ready_cb (GObject *object,
write_request_free (wr);
}
void
_gdk_macos_clipboard_register_drag_types (NSWindow *window)
{
[window registerForDraggedTypes:[NSArray arrayWithObjects:PTYPE(STRING),
PTYPE(PBOARD),
PTYPE(URL),
PTYPE(FILE_URL),
PTYPE(COLOR),
PTYPE(TIFF),
PTYPE(PNG),
nil]];
}
@end
GdkContentFormats *
_gdk_macos_pasteboard_load_formats (NSPasteboard *pasteboard)
{
return load_offer_formats (pasteboard);
}
void
_gdk_macos_pasteboard_read_async (GObject *object,
NSPasteboard *pasteboard,
GdkContentFormats *formats,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkContentFormats *offer_formats = NULL;
const char *mime_type;
GInputStream *stream = NULL;
GTask *task = NULL;
g_assert (G_IS_OBJECT (object));
g_assert (pasteboard != NULL);
g_assert (formats != NULL);
task = g_task_new (object, cancellable, callback, user_data);
g_task_set_source_tag (task, _gdk_macos_pasteboard_read_async);
g_task_set_priority (task, io_priority);
offer_formats = load_offer_formats (pasteboard);
mime_type = gdk_content_formats_match_mime_type (formats, offer_formats);
if (mime_type == NULL)
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
"%s",
_("No compatible transfer format found"));
goto cleanup;
}
if (strcmp (mime_type, "text/plain;charset=utf-8") == 0)
{
NSString *nsstr = [pasteboard stringForType:NSPasteboardTypeString];
if (nsstr != NULL)
{
const char *str = [nsstr UTF8String];
stream = g_memory_input_stream_new_from_data (g_strdup (str),
strlen (str) + 1,
g_free);
}
}
else if (strcmp (mime_type, "text/uri-list") == 0)
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
if ([[pasteboard types] containsObject:PTYPE(FILE_URL)])
{
GString *str = g_string_new (NULL);
NSArray *files = [pasteboard propertyListForType:NSFilenamesPboardType];
gsize n_files = [files count];
char *data;
guint len;
for (gsize i = 0; i < n_files; ++i)
{
NSString* uriString = [files objectAtIndex:i];
uriString = [@"file://" stringByAppendingString:uriString];
uriString = [uriString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
g_string_append_printf (str,
"%s\r\n",
[uriString cStringUsingEncoding:NSUTF8StringEncoding]);
}
len = str->len;
data = g_string_free (str, FALSE);
stream = g_memory_input_stream_new_from_data (data, len, g_free);
}
G_GNUC_END_IGNORE_DEPRECATIONS;
}
else if (strcmp (mime_type, "application/x-color") == 0)
{
NSColorSpace *colorspace;
NSColor *nscolor;
guint16 color[4];
colorspace = [NSColorSpace genericRGBColorSpace];
nscolor = [[NSColor colorFromPasteboard:pasteboard]
colorUsingColorSpace:colorspace];
color[0] = 0xffff * [nscolor redComponent];
color[1] = 0xffff * [nscolor greenComponent];
color[2] = 0xffff * [nscolor blueComponent];
color[3] = 0xffff * [nscolor alphaComponent];
stream = g_memory_input_stream_new_from_data (g_memdup2 (&color, sizeof color),
sizeof color,
g_free);
}
else if (strcmp (mime_type, "image/tiff") == 0)
{
NSData *data = [pasteboard dataForType:PTYPE(TIFF)];
stream = create_stream_from_nsdata (data);
}
else if (strcmp (mime_type, "image/png") == 0)
{
NSData *data = [pasteboard dataForType:PTYPE(PNG)];
stream = create_stream_from_nsdata (data);
}
if (stream != NULL)
{
g_task_set_task_data (task, g_strdup (mime_type), g_free);
g_task_return_pointer (task, g_steal_pointer (&stream), g_object_unref);
}
else
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_FAILED,
_("Failed to decode contents with mime-type of '%s'"),
mime_type);
}
cleanup:
g_clear_object (&task);
g_clear_pointer (&offer_formats, gdk_content_formats_unref);
GDK_END_MACOS_ALLOC_POOL;
}
GInputStream *
_gdk_macos_pasteboard_read_finish (GObject *object,
GAsyncResult *result,
const char **out_mime_type,
GError **error)
{
GTask *task = (GTask *)result;
g_assert (G_IS_OBJECT (object));
g_assert (G_IS_TASK (task));
if (out_mime_type != NULL)
*out_mime_type = g_strdup (g_task_get_task_data (task));
return g_task_propagate_pointer (task, error);
}

View File

@@ -81,6 +81,10 @@ struct _GdkMacosDisplay
/* The surface that is receiving keyboard events */
GdkMacosSurface *keyboard_surface;
/* [NSDraggingInfo draggingSequenceNumber] to GdkMacosDr(ag,op) */
GHashTable *active_drags;
GHashTable *active_drops;
/* Used to translate from quartz coordinate space to GDK */
int width;
int height;
@@ -160,6 +164,16 @@ void _gdk_macos_display_warp_pointer (GdkMacosDisp
int x,
int y);
NSEvent *_gdk_macos_display_get_nsevent (GdkEvent *event);
GdkDrag *_gdk_macos_display_find_drag (GdkMacosDisplay *self,
NSInteger sequence_number);
GdkDrop *_gdk_macos_display_find_drop (GdkMacosDisplay *self,
NSInteger sequence_number);
void _gdk_macos_display_set_drag (GdkMacosDisplay *self,
NSInteger sequence_number,
GdkDrag *drag);
void _gdk_macos_display_set_drop (GdkMacosDisplay *self,
NSInteger sequence_number,
GdkDrop *drop);
G_END_DECLS

View File

@@ -788,6 +788,9 @@ get_surface_from_ns_event (GdkMacosDisplay *self,
NSRect view_frame;
view = (GdkMacosBaseView *)[nswindow contentView];
if (!GDK_IS_MACOS_BASE_VIEW (view))
goto find_under_pointer;
surface = GDK_SURFACE ([view gdkSurface]);
point = [nsevent locationInWindow];
@@ -846,6 +849,8 @@ get_surface_from_ns_event (GdkMacosDisplay *self,
}
}
find_under_pointer:
if (!surface)
{
/* Fallback used when no NSSurface set. This happens e.g. when
@@ -864,17 +869,24 @@ get_surface_from_ns_event (GdkMacosDisplay *self,
static GdkMacosSurface *
find_surface_for_keyboard_event (NSEvent *nsevent)
{
GdkMacosBaseView *view = (GdkMacosBaseView *)[[nsevent window] contentView];
GdkSurface *surface = GDK_SURFACE ([view gdkSurface]);
GdkDisplay *display = gdk_surface_get_display (surface);
GdkSeat *seat = gdk_display_get_default_seat (display);
GdkDevice *device = gdk_seat_get_keyboard (seat);
GdkDeviceGrabInfo *grab = _gdk_display_get_last_device_grab (display, device);
NSView *nsview = [[nsevent window] contentView];
if (grab && grab->surface && !grab->owner_events)
return GDK_MACOS_SURFACE (grab->surface);
if (GDK_IS_MACOS_BASE_VIEW (nsview))
{
GdkMacosBaseView *view = (GdkMacosBaseView *)nsview;
GdkSurface *surface = GDK_SURFACE ([view gdkSurface]);
GdkDisplay *display = gdk_surface_get_display (surface);
GdkSeat *seat = gdk_display_get_default_seat (display);
GdkDevice *device = gdk_seat_get_keyboard (seat);
GdkDeviceGrabInfo *grab = _gdk_display_get_last_device_grab (display, device);
return GDK_MACOS_SURFACE (surface);
if (grab && grab->surface && !grab->owner_events)
return GDK_MACOS_SURFACE (grab->surface);
return GDK_MACOS_SURFACE (surface);
}
return NULL;
}
static GdkMacosSurface *
@@ -1090,7 +1102,8 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
if (!(surface = find_surface_for_ns_event (self, nsevent, &x, &y)))
return NULL;
if (!(window = (GdkMacosWindow *)_gdk_macos_surface_get_native (surface)))
if (!(window = (GdkMacosWindow *)_gdk_macos_surface_get_native (surface)) ||
!GDK_IS_MACOS_WINDOW (window))
return NULL;
/* Ignore events and break grabs while the window is being

View File

@@ -31,6 +31,8 @@
#include "gdkmacoscairocontext-private.h"
#include "gdkmacoseventsource-private.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacosdrag-private.h"
#include "gdkmacosdrop-private.h"
#include "gdkmacosglcontext-private.h"
#include "gdkmacoskeymap-private.h"
#include "gdkmacosmonitor-private.h"
@@ -635,17 +637,13 @@ gdk_macos_display_load_clipboard (GdkMacosDisplay *self)
GDK_DISPLAY (self)->clipboard = _gdk_macos_clipboard_new (self);
}
static gboolean
gdk_macos_display_make_gl_context_current (GdkDisplay *display,
GdkGLContext *gl_context)
static GdkGLContext *
gdk_macos_display_init_gl (GdkDisplay *display,
GError **error)
{
g_assert (GDK_IS_MACOS_DISPLAY (display));
g_assert (!gl_context || GDK_IS_MACOS_GL_CONTEXT (gl_context));
if (gl_context == NULL)
return FALSE;
return _gdk_macos_gl_context_make_current (GDK_MACOS_GL_CONTEXT (gl_context));
return g_object_new (GDK_TYPE_MACOS_GL_CONTEXT,
"display", display,
NULL);
}
static void
@@ -663,6 +661,8 @@ gdk_macos_display_finalize (GObject *object)
CFSTR ("NSUserDefaultsDidChangeNotification"),
NULL);
g_clear_pointer (&self->active_drags, g_hash_table_unref);
g_clear_pointer (&self->active_drops, g_hash_table_unref);
g_clear_object (&GDK_DISPLAY (self)->clipboard);
g_clear_pointer (&self->frame_source, g_source_unref);
g_clear_object (&self->monitors);
@@ -691,7 +691,7 @@ gdk_macos_display_class_init (GdkMacosDisplayClass *klass)
display_class->get_name = gdk_macos_display_get_name;
display_class->get_setting = gdk_macos_display_get_setting;
display_class->has_pending = gdk_macos_display_has_pending;
display_class->make_gl_context_current = gdk_macos_display_make_gl_context_current;
display_class->init_gl = gdk_macos_display_init_gl;
display_class->notify_startup_complete = gdk_macos_display_notify_startup_complete;
display_class->queue_events = gdk_macos_display_queue_events;
display_class->sync = gdk_macos_display_sync;
@@ -701,6 +701,8 @@ static void
gdk_macos_display_init (GdkMacosDisplay *self)
{
self->monitors = g_list_store_new (GDK_TYPE_MONITOR);
self->active_drags = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
self->active_drops = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
gdk_display_set_composited (GDK_DISPLAY (self), TRUE);
gdk_display_set_input_shapes (GDK_DISPLAY (self), FALSE);
@@ -1113,3 +1115,55 @@ _gdk_macos_display_get_nsevent (GdkEvent *event)
return NULL;
}
GdkDrag *
_gdk_macos_display_find_drag (GdkMacosDisplay *self,
NSInteger sequence_number)
{
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), NULL);
return g_hash_table_lookup (self->active_drags, GSIZE_TO_POINTER (sequence_number));
}
void
_gdk_macos_display_set_drag (GdkMacosDisplay *self,
NSInteger sequence_number,
GdkDrag *drag)
{
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
g_return_if_fail (!drag || GDK_IS_MACOS_DRAG (drag));
if (drag)
g_hash_table_insert (self->active_drags,
GSIZE_TO_POINTER (sequence_number),
g_object_ref (drag));
else
g_hash_table_remove (self->active_drags,
GSIZE_TO_POINTER (sequence_number));
}
GdkDrop *
_gdk_macos_display_find_drop (GdkMacosDisplay *self,
NSInteger sequence_number)
{
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), NULL);
return g_hash_table_lookup (self->active_drops, GSIZE_TO_POINTER (sequence_number));
}
void
_gdk_macos_display_set_drop (GdkMacosDisplay *self,
NSInteger sequence_number,
GdkDrop *drop)
{
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
g_return_if_fail (!drop || GDK_IS_MACOS_DROP (drop));
if (drop)
g_hash_table_insert (self->active_drops,
GSIZE_TO_POINTER (sequence_number),
g_object_ref (drop));
else
g_hash_table_remove (self->active_drops,
GSIZE_TO_POINTER (sequence_number));
}

View File

@@ -326,12 +326,10 @@ gdk_drag_update (GdkDrag *drag,
&suggested_action,
&possible_actions);
_gdk_macos_drag_surface_drag_motion (self->drag_surface,
x_root - self->hot_x,
y_root - self->hot_y,
suggested_action,
possible_actions,
evtime);
if (GDK_IS_MACOS_SURFACE (self->drag_surface))
_gdk_macos_surface_move (GDK_MACOS_SURFACE (self->drag_surface),
x_root - self->hot_x,
y_root - self->hot_y);
if (!self->did_update)
{
@@ -339,6 +337,8 @@ gdk_drag_update (GdkDrag *drag,
self->start_y = self->last_y;
self->did_update = TRUE;
}
gdk_drag_set_actions (drag, possible_actions);
}
static gboolean

View File

@@ -31,19 +31,13 @@ typedef struct _GdkMacosDragSurfaceClass GdkMacosDragSurfaceClass;
#define GDK_MACOS_DRAG_SURFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_DRAG_SURFACE, GdkMacosDragSurface))
#define GDK_IS_MACOS_DRAG_SURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_DRAG_SURFACE))
GType _gdk_macos_drag_surface_get_type (void);
GdkMacosSurface *_gdk_macos_drag_surface_new (GdkMacosDisplay *display,
GdkFrameClock *frame_clock,
int x,
int y,
int width,
int height);
void _gdk_macos_drag_surface_drag_motion (GdkMacosDragSurface *self,
int x_root,
int y_root,
GdkDragAction suggested_action,
GdkDragAction possible_actions,
guint32 evtime);
GType _gdk_macos_drag_surface_get_type (void);
GdkMacosSurface *_gdk_macos_drag_surface_new (GdkMacosDisplay *display,
GdkFrameClock *frame_clock,
int x,
int y,
int width,
int height);
G_END_DECLS

View File

@@ -123,16 +123,3 @@ _gdk_macos_drag_surface_new (GdkMacosDisplay *display,
return g_steal_pointer (&self);
}
void
_gdk_macos_drag_surface_drag_motion (GdkMacosDragSurface *self,
int x_root,
int y_root,
GdkDragAction suggested_action,
GdkDragAction possible_actions,
guint32 evtime)
{
g_return_if_fail (GDK_IS_MACOS_DRAG_SURFACE (self));
_gdk_macos_surface_move (GDK_MACOS_SURFACE (self), x_root, y_root);
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright © 2021 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_DROP_PRIVATE_H__
#define __GDK_MACOS_DROP_PRIVATE_H__
#include <AppKit/AppKit.h>
#include "gdkdropprivate.h"
#include "gdkmacossurface-private.h"
G_BEGIN_DECLS
#define GDK_TYPE_MACOS_DROP (gdk_macos_drop_get_type ())
#define GDK_MACOS_DROP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_DROP, GdkMacosDrop))
#define GDK_MACOS_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_MACOS_DROP, GdkMacosDropClass))
#define GDK_IS_MACOS_DROP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_DROP))
#define GDK_IS_MACOS_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_MACOS_DROP))
#define GDK_MACOS_DROP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_MACOS_DROP, GdkMacosDropClass))
typedef struct _GdkMacosDrop GdkMacosDrop;
typedef struct _GdkMacosDropClass GdkMacosDropClass;
struct _GdkMacosDrop
{
GdkDrop parent_instance;
NSPasteboard *pasteboard;
GdkDragAction all_actions;
GdkDragAction preferred_action;
GdkDragAction finish_action;
};
struct _GdkMacosDropClass
{
GdkDropClass parent_class;
};
GType gdk_macos_drop_get_type (void) G_GNUC_CONST;
GdkMacosDrop *_gdk_macos_drop_new (GdkMacosSurface *surface,
id<NSDraggingInfo> info);
NSDragOperation _gdk_macos_drop_operation (GdkMacosDrop *self);
void _gdk_macos_drop_update_actions (GdkMacosDrop *self,
id<NSDraggingInfo> info);
G_END_DECLS
#endif /* __GDK_MACOS_DROP_PRIVATE_H__ */

183
gdk/macos/gdkmacosdrop.c Normal file
View File

@@ -0,0 +1,183 @@
/*
* Copyright © 2021 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include "gdkmacosclipboard-private.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacosdrag-private.h"
#include "gdkmacosdrop-private.h"
G_DEFINE_TYPE (GdkMacosDrop, gdk_macos_drop, GDK_TYPE_DROP)
static void
gdk_macos_drop_status (GdkDrop *drop,
GdkDragAction actions,
GdkDragAction preferred)
{
GdkMacosDrop *self = (GdkMacosDrop *)drop;
g_assert (GDK_IS_MACOS_DROP (self));
self->all_actions = actions;
self->preferred_action = preferred;
}
static void
gdk_macos_drop_read_async (GdkDrop *drop,
GdkContentFormats *content_formats,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
_gdk_macos_pasteboard_read_async (G_OBJECT (drop),
GDK_MACOS_DROP (drop)->pasteboard,
content_formats,
io_priority,
cancellable,
callback,
user_data);
}
static GInputStream *
gdk_macos_drop_read_finish (GdkDrop *drop,
GAsyncResult *result,
const char **out_mime_type,
GError **error)
{
return _gdk_macos_pasteboard_read_finish (G_OBJECT (drop), result, out_mime_type, error);
}
static void
gdk_macos_drop_finish (GdkDrop *drop,
GdkDragAction action)
{
g_assert (GDK_IS_MACOS_DROP (drop));
GDK_MACOS_DROP (drop)->finish_action = action;
}
static void
gdk_macos_drop_finalize (GObject *object)
{
GdkMacosDrop *self = (GdkMacosDrop *)object;
if (self->pasteboard)
{
[self->pasteboard release];
self->pasteboard = NULL;
}
G_OBJECT_CLASS (gdk_macos_drop_parent_class)->finalize (object);
}
static void
gdk_macos_drop_class_init (GdkMacosDropClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkDropClass *drop_class = GDK_DROP_CLASS (klass);
object_class->finalize = gdk_macos_drop_finalize;
drop_class->status = gdk_macos_drop_status;
drop_class->read_async = gdk_macos_drop_read_async;
drop_class->read_finish = gdk_macos_drop_read_finish;
drop_class->finish = gdk_macos_drop_finish;
}
static void
gdk_macos_drop_init (GdkMacosDrop *self)
{
}
void
_gdk_macos_drop_update_actions (GdkMacosDrop *self,
id<NSDraggingInfo> info)
{
NSDragOperation op;
GdkDragAction actions = 0;
g_assert (GDK_IS_MACOS_DROP (self));
op = [info draggingSourceOperationMask];
if (op & NSDragOperationCopy)
actions |= GDK_ACTION_COPY;
if (op & NSDragOperationLink)
actions |= GDK_ACTION_LINK;
if (op & NSDragOperationMove)
actions |= GDK_ACTION_MOVE;
gdk_drop_set_actions (GDK_DROP (self), actions);
}
GdkMacosDrop *
_gdk_macos_drop_new (GdkMacosSurface *surface,
id<NSDraggingInfo> info)
{
GdkDrag *drag = NULL;
GdkContentFormats *content_formats;
GdkMacosDrop *self;
GdkDisplay *display;
GdkDevice *device;
GdkSeat *seat;
g_return_val_if_fail (GDK_IS_MACOS_SURFACE (surface), NULL);
g_return_val_if_fail (info != NULL, NULL);
display = gdk_surface_get_display (GDK_SURFACE (surface));
seat = gdk_display_get_default_seat (display);
device = gdk_seat_get_pointer (seat);
drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), [info draggingSequenceNumber]);
content_formats = _gdk_macos_pasteboard_load_formats ([info draggingPasteboard]);
self = g_object_new (GDK_TYPE_MACOS_DROP,
"device", device,
"drag", drag,
"formats", content_formats,
"surface", surface,
NULL);
self->pasteboard = [[info draggingPasteboard] retain];
_gdk_macos_drop_update_actions (self, info);
gdk_content_formats_unref (content_formats);
return g_steal_pointer (&self);
}
NSDragOperation
_gdk_macos_drop_operation (GdkMacosDrop *self)
{
if (self->preferred_action & GDK_ACTION_LINK)
return NSDragOperationLink;
if (self->preferred_action & GDK_ACTION_MOVE)
return NSDragOperationMove;
if (self->preferred_action & GDK_ACTION_COPY)
return NSDragOperationCopy;
return NSDragOperationNone;
}

View File

@@ -19,12 +19,14 @@
#ifndef __GDK_MACOS_GL_CONTEXT_PRIVATE_H__
#define __GDK_MACOS_GL_CONTEXT_PRIVATE_H__
#include "gdkmacosglcontext.h"
#include "gdkglcontextprivate.h"
#include "gdkdisplayprivate.h"
#include "gdksurface.h"
#include "gdkinternals.h"
#include "gdkmacosglcontext.h"
#include "gdkmacosdisplay.h"
#include "gdkmacossurface.h"
#import <OpenGL/OpenGL.h>
@@ -55,11 +57,6 @@ struct _GdkMacosGLContextClass
GdkGLContextClass parent_class;
};
GdkGLContext *_gdk_macos_gl_context_new (GdkMacosSurface *surface,
gboolean attached,
GdkGLContext *share,
GError **error);
gboolean _gdk_macos_gl_context_make_current (GdkMacosGLContext *self);
G_END_DECLS

View File

@@ -145,6 +145,7 @@ ensure_gl_view (GdkMacosGLContext *self)
[nsview setPostsFrameChangedNotifications: YES];
[nsview setNeedsDisplay:YES];
[nswindow setContentView:nsview];
[nswindow makeFirstResponder:nsview];
[nsview release];
if (self->dummy_view != NULL)
@@ -169,12 +170,12 @@ gdk_macos_gl_context_real_realize (GdkGLContext *context,
{
GdkMacosGLContext *self = (GdkMacosGLContext *)context;
GdkSurface *surface;
GdkDisplay *display;
NSOpenGLContext *shared_gl_context = nil;
NSOpenGLContext *gl_context;
NSOpenGLPixelFormat *pixelFormat;
CGLContextObj cgl_context;
GdkGLContext *shared;
GdkGLContext *shared_data;
NSOpenGLContext *existing;
GLint sync_to_framerate = 1;
GLint validate = 0;
@@ -191,21 +192,16 @@ gdk_macos_gl_context_real_realize (GdkGLContext *context,
gdk_gl_context_get_required_version (context, &major, &minor);
surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context));
shared = gdk_gl_context_get_shared_context (context);
shared_data = gdk_surface_get_shared_data_gl_context (surface);
display = gdk_gl_context_get_display (context);
shared = gdk_display_get_gl_context (display);
if (shared != NULL)
{
if (!(shared_gl_context = get_ns_open_gl_context (GDK_MACOS_GL_CONTEXT (shared), error)))
return FALSE;
}
else if (shared_data != NULL)
{
if (!(shared_gl_context = get_ns_open_gl_context (GDK_MACOS_GL_CONTEXT (shared_data), error)))
return FALSE;
}
GDK_DISPLAY_NOTE (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)),
GDK_DISPLAY_NOTE (display,
OPENGL,
g_message ("Creating NSOpenGLContext (version %d.%d)",
major, minor));
@@ -252,7 +248,7 @@ gdk_macos_gl_context_real_realize (GdkGLContext *context,
GLint renderer_id = 0;
[gl_context getValues:&renderer_id forParameter:NSOpenGLContextParameterCurrentRendererID];
GDK_DISPLAY_NOTE (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)),
GDK_DISPLAY_NOTE (display,
OPENGL,
g_message ("Created NSOpenGLContext[%p] using %s",
gl_context,
@@ -314,9 +310,7 @@ gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
* want to replace our damage region for the next frame (to avoid
* doing it multiple times).
*/
if (!self->is_attached &&
gdk_gl_context_get_shared_context (GDK_GL_CONTEXT (context)))
ensure_gl_view (self);
ensure_gl_view (self);
if (self->needs_resize)
{
@@ -409,6 +403,57 @@ gdk_macos_gl_context_surface_resized (GdkDrawContext *draw_context)
g_clear_pointer (&self->damage, cairo_region_destroy);
}
static gboolean
gdk_macos_gl_context_clear_current (GdkGLContext *context)
{
GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
NSOpenGLContext *current;
g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);
current = [NSOpenGLContext currentContext];
if (self->gl_context == current)
{
/* The OpenGL mac programming guide suggests that glFlush() is called
* before switching current contexts to ensure that the drawing commands
* are submitted.
*/
if (current != NULL)
glFlush ();
[NSOpenGLContext clearCurrentContext];
}
return TRUE;
}
static gboolean
gdk_macos_gl_context_make_current (GdkGLContext *context,
gboolean surfaceless)
{
GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
NSOpenGLContext *current;
g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);
current = [NSOpenGLContext currentContext];
if (self->gl_context != current)
{
/* The OpenGL mac programming guide suggests that glFlush() is called
* before switching current contexts to ensure that the drawing commands
* are submitted.
*/
if (current != NULL)
glFlush ();
[self->gl_context makeCurrentContext];
}
return TRUE;
}
static cairo_region_t *
gdk_macos_gl_context_get_damage (GdkGLContext *context)
{
@@ -477,52 +522,4 @@ gdk_macos_gl_context_init (GdkMacosGLContext *self)
{
}
GdkGLContext *
_gdk_macos_gl_context_new (GdkMacosSurface *surface,
gboolean attached,
GdkGLContext *share,
GError **error)
{
GdkMacosGLContext *context;
g_return_val_if_fail (GDK_IS_MACOS_SURFACE (surface), NULL);
g_return_val_if_fail (!share || GDK_IS_MACOS_GL_CONTEXT (share), NULL);
context = g_object_new (GDK_TYPE_MACOS_GL_CONTEXT,
"surface", surface,
"shared-context", share,
NULL);
context->is_attached = !!attached;
return GDK_GL_CONTEXT (context);
}
gboolean
_gdk_macos_gl_context_make_current (GdkMacosGLContext *self)
{
NSOpenGLContext *current;
g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);
if (self->gl_context == NULL)
return FALSE;
current = [NSOpenGLContext currentContext];
if (self->gl_context != current)
{
/* The OpenGL mac programming guide suggests that glFlush() is called
* before switching current contexts to ensure that the drawing commands
* are submitted.
*/
if (current != NULL)
glFlush ();
[self->gl_context makeCurrentContext];
}
return TRUE;
}
G_GNUC_END_IGNORE_DEPRECATIONS

View File

@@ -348,7 +348,7 @@ _gdk_macos_seat_new (GdkMacosDisplay *display)
init_devices (self);
return g_steal_pointer (&self);
return GDK_SEAT (g_steal_pointer (&self));
}
static GdkDeviceToolType

View File

@@ -332,7 +332,7 @@ gdk_macos_surface_drag_begin (GdkSurface *surface,
drag_surface = _gdk_macos_surface_new (GDK_MACOS_DISPLAY (surface->display),
GDK_SURFACE_TEMP,
surface,
-99, -99, 1, 1);
sx, sy, 1, 1);
drag = g_object_new (GDK_TYPE_MACOS_DRAG,
"drag-surface", drag_surface,
"surface", surface,
@@ -358,20 +358,6 @@ gdk_macos_surface_drag_begin (GdkSurface *surface,
return GDK_DRAG (g_steal_pointer (&drag));
}
static GdkGLContext *
gdk_macos_surface_create_gl_context (GdkSurface *surface,
gboolean attached,
GdkGLContext *share,
GError **error)
{
GdkMacosSurface *self = (GdkMacosSurface *)surface;
g_assert (GDK_IS_MACOS_SURFACE (self));
g_assert (!share || GDK_IS_GL_CONTEXT (share));
return _gdk_macos_gl_context_new (self, attached, share, error);
}
static void
gdk_macos_surface_destroy (GdkSurface *surface,
gboolean foreign_destroy)
@@ -495,7 +481,6 @@ gdk_macos_surface_class_init (GdkMacosSurfaceClass *klass)
object_class->get_property = gdk_macos_surface_get_property;
object_class->set_property = gdk_macos_surface_set_property;
surface_class->create_gl_context = gdk_macos_surface_create_gl_context;
surface_class->destroy = gdk_macos_surface_destroy;
surface_class->drag_begin = gdk_macos_surface_drag_begin;
surface_class->get_device_state = gdk_macos_surface_get_device_state;

View File

@@ -10,6 +10,7 @@ gdk_macos_sources = files([
'gdkmacosdisplay-settings.c',
'gdkmacosdisplay-translate.c',
'gdkmacosdrag.c',
'gdkmacosdrop.c',
'gdkmacosdragsurface.c',
'gdkmacosglcontext.c',
'gdkmacoseventsource.c',

View File

@@ -1550,6 +1550,7 @@ pointer_handle_leave (void *data,
GdkWaylandSeat *seat = data;
GdkEvent *event;
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display);
GdkDeviceGrabInfo *grab;
if (!surface)
return;
@@ -1561,8 +1562,11 @@ pointer_handle_leave (void *data,
return;
_gdk_wayland_display_update_serial (display_wayland, serial);
grab = _gdk_display_get_last_device_grab (seat->display,
seat->logical_pointer);
if (seat->pointer_info.button_modifiers != 0)
if (seat->pointer_info.button_modifiers != 0 &&
grab && grab->implicit)
{
gulong display_serial;
@@ -3089,6 +3093,11 @@ seat_handle_capabilities (void *data,
}
else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && seat->wl_pointer)
{
g_clear_pointer (&seat->wp_pointer_gesture_swipe,
zwp_pointer_gesture_swipe_v1_destroy);
g_clear_pointer (&seat->wp_pointer_gesture_pinch,
zwp_pointer_gesture_pinch_v1_destroy);
wl_pointer_release (seat->wl_pointer);
seat->wl_pointer = NULL;
gdk_seat_device_removed (GDK_SEAT (seat), seat->pointer);

View File

@@ -432,12 +432,12 @@ gdk_registry_handle_global (void *data,
display_wayland->subcompositor =
wl_registry_bind (display_wayland->wl_registry, id, &wl_subcompositor_interface, 1);
}
else if (strcmp (interface, "zwp_pointer_gestures_v1") == 0 &&
version == GDK_ZWP_POINTER_GESTURES_V1_VERSION)
else if (strcmp (interface, "zwp_pointer_gestures_v1") == 0)
{
display_wayland->pointer_gestures =
wl_registry_bind (display_wayland->wl_registry,
id, &zwp_pointer_gestures_v1_interface, version);
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)
{
@@ -969,7 +969,7 @@ gdk_wayland_display_class_init (GdkWaylandDisplayClass *class)
display_class->create_surface = _gdk_wayland_display_create_surface;
display_class->get_keymap = _gdk_wayland_display_get_keymap;
display_class->make_gl_context_current = gdk_wayland_display_make_gl_context_current;
display_class->init_gl = gdk_wayland_display_init_gl;
display_class->get_monitors = gdk_wayland_display_get_monitors;
display_class->get_monitor_at_surface = gdk_wayland_display_get_monitor_at_surface;
@@ -991,6 +991,26 @@ gdk_wayland_display_get_toplevel_surfaces (GdkDisplay *display)
return GDK_WAYLAND_DISPLAY (display)->toplevels;
}
static struct wl_cursor_theme *
try_load_theme (GdkWaylandDisplay *display_wayland,
const char *dir,
gboolean dotdir,
const char *name,
int size)
{
struct wl_cursor_theme *theme = NULL;
char *path;
path = g_build_filename (dir, dotdir ? ".icons" : "icons", name, "cursors", NULL);
if (g_file_test (path, G_FILE_TEST_IS_DIR))
theme = wl_cursor_theme_create (path, size, display_wayland->shm);
g_free (path);
return theme;
}
static struct wl_cursor_theme *
get_cursor_theme (GdkWaylandDisplay *display_wayland,
const char *name,
@@ -1000,16 +1020,18 @@ get_cursor_theme (GdkWaylandDisplay *display_wayland,
struct wl_cursor_theme *theme = NULL;
int i;
theme = try_load_theme (display_wayland, g_get_user_data_dir (), FALSE, name, size);
if (theme)
return theme;
theme = try_load_theme (display_wayland, g_get_home_dir (), TRUE, name, size);
if (theme)
return theme;
xdg_data_dirs = g_get_system_data_dirs ();
for (i = 0; xdg_data_dirs[i]; i++)
{
char *path = g_build_filename (xdg_data_dirs[i], "icons", name, "cursors", NULL);
if (g_file_test (path, G_FILE_TEST_IS_DIR))
theme = wl_cursor_theme_create (path, size, display_wayland->shm);
g_free (path);
theme = try_load_theme (display_wayland, xdg_data_dirs[i], FALSE, name, size);
if (theme)
return theme;
}
@@ -1648,6 +1670,7 @@ static TranslationEntry translations[] = {
{ FALSE, "org.gnome.desktop.wm.preferences", "action-middle-click-titlebar", "gtk-titlebar-middle-click", G_TYPE_STRING, { .s = "none" } },
{ FALSE, "org.gnome.desktop.wm.preferences", "action-right-click-titlebar", "gtk-titlebar-right-click", G_TYPE_STRING, { .s = "menu" } },
{ FALSE, "org.gnome.desktop.a11y", "always-show-text-caret", "gtk-keynav-use-caret", G_TYPE_BOOLEAN, { .b = FALSE } },
/* Note, this setting doesn't exist, the portal and gsd fake it */
{ FALSE, "org.gnome.fontconfig", "serial", "gtk-fontconfig-timestamp", G_TYPE_NONE, { .i = 0 } },
};

View File

@@ -153,14 +153,12 @@ struct _GdkWaylandDisplay
/* egl info */
EGLDisplay egl_display;
EGLConfig egl_config;
int egl_major_version;
int egl_minor_version;
guint have_egl : 1;
guint have_egl_khr_create_context : 1;
guint have_egl_buffer_age : 1;
guint have_egl_swap_buffers_with_damage : 1;
guint have_egl_surfaceless_context : 1;
};
struct _GdkWaylandDisplayClass

View File

@@ -163,6 +163,7 @@ gdk_wayland_drag_cancel (GdkDrag *drag,
GdkDragCancelReason reason)
{
gdk_drag_set_cursor (drag, NULL);
gdk_drag_drop_done (drag, FALSE);
}
static void
@@ -290,6 +291,7 @@ data_source_dnd_finished (void *data,
GdkDrag *drag = data;
g_signal_emit_by_name (drag, "dnd-finished");
gdk_drag_drop_done (drag, TRUE);
}
static void

View File

@@ -22,7 +22,9 @@
#include "config.h"
#include "gdkglcontext-wayland.h"
#include "gdkdisplay-wayland.h"
#include "gdksurface-wayland.h"
#include "gdkwaylanddisplay.h"
#include "gdkwaylandglcontext.h"
@@ -53,14 +55,14 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
{
GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
GdkDisplay *display = gdk_gl_context_get_display (context);
GdkGLContext *share = gdk_gl_context_get_shared_context (context);
GdkGLContext *shared_data_context = gdk_surface_get_shared_data_gl_context (gdk_gl_context_get_surface (context));
GdkGLContext *share = gdk_display_get_gl_context (display);
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
EGLContext ctx;
EGLint context_attribs[N_EGL_ATTRS];
int major, minor, flags;
gboolean debug_bit, forward_bit, legacy_bit, use_es;
int i = 0;
G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
gdk_gl_context_get_required_version (context, &major, &minor);
debug_bit = gdk_gl_context_get_debug_enabled (context);
@@ -120,10 +122,9 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
use_es ? "yes" : "no"));
ctx = eglCreateContext (display_wayland->egl_display,
context_wayland->egl_config,
display_wayland->egl_config,
share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
: shared_data_context != NULL ? GDK_WAYLAND_GL_CONTEXT (shared_data_context)->egl_context
: EGL_NO_CONTEXT,
: EGL_NO_CONTEXT,
context_attribs);
/* If context creation failed without the ES bit, let's try again with it */
@@ -147,10 +148,9 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
GDK_DISPLAY_NOTE (display, OPENGL,
g_message ("eglCreateContext failed, switching to OpenGL ES"));
ctx = eglCreateContext (display_wayland->egl_display,
context_wayland->egl_config,
display_wayland->egl_config,
share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
: shared_data_context != NULL ? GDK_WAYLAND_GL_CONTEXT (shared_data_context)->egl_context
: EGL_NO_CONTEXT,
: EGL_NO_CONTEXT,
context_attribs);
}
@@ -177,10 +177,9 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
GDK_DISPLAY_NOTE (display, OPENGL,
g_message ("eglCreateContext failed, switching to legacy"));
ctx = eglCreateContext (display_wayland->egl_display,
context_wayland->egl_config,
display_wayland->egl_config,
share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
: shared_data_context != NULL ? GDK_WAYLAND_GL_CONTEXT (shared_data_context)->egl_context
: EGL_NO_CONTEXT,
: EGL_NO_CONTEXT,
context_attribs);
}
@@ -199,6 +198,8 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
gdk_gl_context_set_is_legacy (context, legacy_bit);
gdk_gl_context_set_use_es (context, use_es);
gdk_profiler_end_mark (start_time, "realize GdkWaylandGLContext", NULL);
return TRUE;
}
@@ -213,17 +214,8 @@ gdk_wayland_gl_context_get_damage (GdkGLContext *context)
if (display_wayland->have_egl_buffer_age)
{
GdkGLContext *shared;
GdkWaylandGLContext *shared_wayland;
shared = gdk_gl_context_get_shared_context (context);
if (shared == NULL)
shared = context;
shared_wayland = GDK_WAYLAND_GL_CONTEXT (shared);
egl_surface = gdk_wayland_surface_get_egl_surface (surface,
shared_wayland->egl_config);
gdk_gl_context_make_current (shared);
egl_surface = gdk_wayland_surface_get_egl_surface (surface);
gdk_gl_context_make_current (context);
eglQuerySurface (display_wayland->egl_display, egl_surface,
EGL_BUFFER_AGE_EXT, &buffer_age);
@@ -256,6 +248,47 @@ gdk_wayland_gl_context_get_damage (GdkGLContext *context)
return GDK_GL_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->get_damage (context);
}
static gboolean
gdk_wayland_gl_context_clear_current (GdkGLContext *context)
{
GdkDisplay *display = gdk_gl_context_get_display (context);
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
return eglMakeCurrent (display_wayland->egl_display,
EGL_NO_SURFACE,
EGL_NO_SURFACE,
EGL_NO_CONTEXT);
}
static gboolean
gdk_wayland_gl_context_make_current (GdkGLContext *context,
gboolean surfaceless)
{
GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
GdkDisplay *display = gdk_gl_context_get_display (context);
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
EGLSurface egl_surface;
if (!surfaceless)
egl_surface = gdk_wayland_surface_get_egl_surface (gdk_gl_context_get_surface (context));
else
egl_surface = EGL_NO_SURFACE;
return eglMakeCurrent (display_wayland->egl_display,
egl_surface,
egl_surface,
context_wayland->egl_context);
}
static void
gdk_wayland_gl_context_begin_frame (GdkDrawContext *draw_context,
cairo_region_t *region)
{
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->begin_frame (draw_context, region);
glDrawBuffers (1, (GLenum[1]) { GL_BACK });
}
static void
gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
cairo_region_t *painted)
@@ -264,18 +297,13 @@ gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
GdkSurface *surface = gdk_gl_context_get_surface (context);
GdkDisplay *display = gdk_surface_get_display (surface);
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
EGLSurface egl_surface;
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->end_frame (draw_context, painted);
if (gdk_gl_context_get_shared_context (context))
return;
gdk_gl_context_make_current (context);
egl_surface = gdk_wayland_surface_get_egl_surface (surface,
context_wayland->egl_config);
egl_surface = gdk_wayland_surface_get_egl_surface (surface);
gdk_wayland_surface_sync (surface);
gdk_wayland_surface_request_frame (surface);
@@ -322,9 +350,12 @@ gdk_wayland_gl_context_class_init (GdkWaylandGLContextClass *klass)
gobject_class->dispose = gdk_wayland_gl_context_dispose;
draw_context_class->begin_frame = gdk_wayland_gl_context_begin_frame;
draw_context_class->end_frame = gdk_wayland_gl_context_end_frame;
context_class->realize = gdk_wayland_gl_context_realize;
context_class->make_current = gdk_wayland_gl_context_make_current;
context_class->clear_current = gdk_wayland_gl_context_clear_current;
context_class->get_damage = gdk_wayland_gl_context_get_damage;
}
@@ -340,6 +371,8 @@ gdk_wayland_gl_context_init (GdkWaylandGLContext *self)
* Retrieves the EGL display connection object for the given GDK display.
*
* Returns: (nullable): the EGL display
*
* Since: 4.4
*/
gpointer
gdk_wayland_display_get_egl_display (GdkDisplay *display)
@@ -348,7 +381,7 @@ gdk_wayland_display_get_egl_display (GdkDisplay *display)
g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), NULL);
if (!gdk_wayland_display_init_gl (display))
if (!gdk_display_prepare_gl (display, NULL))
return NULL;
display_wayland = GDK_WAYLAND_DISPLAY (display);
@@ -393,71 +426,11 @@ out:
return dpy;
}
gboolean
gdk_wayland_display_init_gl (GdkDisplay *display)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
EGLint major, minor;
EGLDisplay dpy;
if (display_wayland->have_egl)
return TRUE;
dpy = get_egl_display (display_wayland);
if (dpy == NULL)
return FALSE;
if (!eglInitialize (dpy, &major, &minor))
return FALSE;
if (!eglBindAPI (EGL_OPENGL_API))
return FALSE;
display_wayland->egl_display = dpy;
display_wayland->egl_major_version = major;
display_wayland->egl_minor_version = minor;
display_wayland->have_egl = TRUE;
display_wayland->have_egl_khr_create_context =
epoxy_has_egl_extension (dpy, "EGL_KHR_create_context");
display_wayland->have_egl_buffer_age =
epoxy_has_egl_extension (dpy, "EGL_EXT_buffer_age");
display_wayland->have_egl_swap_buffers_with_damage =
epoxy_has_egl_extension (dpy, "EGL_EXT_swap_buffers_with_damage");
display_wayland->have_egl_surfaceless_context =
epoxy_has_egl_extension (dpy, "EGL_KHR_surfaceless_context");
GDK_DISPLAY_NOTE (display, OPENGL,
g_message ("EGL API version %d.%d found\n"
" - Vendor: %s\n"
" - Version: %s\n"
" - Client APIs: %s\n"
" - Extensions:\n"
"\t%s",
display_wayland->egl_major_version,
display_wayland->egl_minor_version,
eglQueryString (dpy, EGL_VENDOR),
eglQueryString (dpy, EGL_VERSION),
eglQueryString (dpy, EGL_CLIENT_APIS),
eglQueryString (dpy, EGL_EXTENSIONS)));
return TRUE;
}
#define MAX_EGL_ATTRS 30
static gboolean
find_eglconfig_for_surface (GdkSurface *surface,
EGLConfig *egl_config_out,
GError **error)
static EGLConfig
get_eglconfig (EGLDisplay dpy)
{
GdkDisplay *display = gdk_surface_get_display (surface);
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
EGLint attrs[MAX_EGL_ATTRS];
EGLint count;
EGLConfig config;
@@ -482,59 +455,129 @@ find_eglconfig_for_surface (GdkSurface *surface,
g_assert (i < MAX_EGL_ATTRS);
/* Pick first valid configuration i guess? */
if (!eglChooseConfig (display_wayland->egl_display, attrs, &config, 1, &count) || count < 1)
{
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
_("No available configurations for the given pixel format"));
return FALSE;
}
if (!eglChooseConfig (dpy, attrs, &config, 1, &count) || count < 1)
return NULL;
g_assert (egl_config_out);
*egl_config_out = config;
return TRUE;
return config;
}
GdkGLContext *
gdk_wayland_surface_create_gl_context (GdkSurface *surface,
gboolean attached,
GdkGLContext *share,
GError **error)
{
GdkDisplay *display = gdk_surface_get_display (surface);
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
GdkWaylandGLContext *context;
EGLConfig config;
#undef MAX_EGL_ATTRS
if (!gdk_wayland_display_init_gl (display))
GdkGLContext *
gdk_wayland_display_init_gl (GdkDisplay *display,
GError **error)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
EGLint major, minor;
EGLDisplay dpy;
GdkGLContext *ctx;
G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
G_GNUC_UNUSED gint64 start_time2;
start_time2 = GDK_PROFILER_CURRENT_TIME;
dpy = get_egl_display (display_wayland);
gdk_profiler_end_mark (start_time, "get_egl_display", NULL);
if (dpy == NULL)
{
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("Failed to create EGL display"));
return NULL;
}
start_time2 = GDK_PROFILER_CURRENT_TIME;
if (!eglInitialize (dpy, &major, &minor))
{
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("Could not initialize EGL display"));
return NULL;
}
gdk_profiler_end_mark (start_time2, "eglInitialize", NULL);
if (major < GDK_EGL_MIN_VERSION_MAJOR ||
(major == GDK_EGL_MIN_VERSION_MAJOR && minor < GDK_EGL_MIN_VERSION_MINOR))
{
eglTerminate (dpy);
g_set_error (error, GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("EGL version %d.%d is too old. GTK requires %d.%d"),
major, minor, GDK_EGL_MIN_VERSION_MAJOR, GDK_EGL_MIN_VERSION_MINOR);
return NULL;
}
start_time2 = GDK_PROFILER_CURRENT_TIME;
if (!eglBindAPI (EGL_OPENGL_API))
{
eglTerminate (dpy);
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("No GL implementation is available"));
return NULL;
}
gdk_profiler_end_mark (start_time2, "eglBindAPI", NULL);
if (!display_wayland->have_egl_khr_create_context)
if (!epoxy_has_egl_extension (dpy, "EGL_KHR_create_context"))
{
eglTerminate (dpy);
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_UNSUPPORTED_PROFILE,
_("Core GL is not available on EGL implementation"));
return NULL;
}
if (!find_eglconfig_for_surface (surface, &config, error))
return NULL;
if (!epoxy_has_egl_extension (dpy, "EGL_KHR_surfaceless_context"))
{
eglTerminate (dpy);
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_UNSUPPORTED_PROFILE,
_("Surfaceless contexts are not supported on this EGL implementation"));
return NULL;
}
context = g_object_new (GDK_TYPE_WAYLAND_GL_CONTEXT,
"surface", surface,
"shared-context", share,
NULL);
start_time2 = GDK_PROFILER_CURRENT_TIME;
display_wayland->egl_config = get_eglconfig (dpy);
gdk_profiler_end_mark (start_time2, "get_eglconfig", NULL);
if (!display_wayland->egl_config)
{
eglTerminate (dpy);
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
_("No available configurations for the given pixel format"));
return NULL;
}
context->egl_config = config;
context->is_attached = attached;
display_wayland->egl_display = dpy;
display_wayland->egl_major_version = major;
display_wayland->egl_minor_version = minor;
return GDK_GL_CONTEXT (context);
display_wayland->have_egl_buffer_age =
epoxy_has_egl_extension (dpy, "EGL_EXT_buffer_age");
display_wayland->have_egl_swap_buffers_with_damage =
epoxy_has_egl_extension (dpy, "EGL_EXT_swap_buffers_with_damage");
GDK_DISPLAY_NOTE (display, OPENGL,
g_message ("EGL API version %d.%d found\n"
" - Vendor: %s\n"
" - Version: %s\n"
" - Client APIs: %s\n"
" - Extensions:\n"
"\t%s",
display_wayland->egl_major_version,
display_wayland->egl_minor_version,
eglQueryString (dpy, EGL_VENDOR),
eglQueryString (dpy, EGL_VERSION),
eglQueryString (dpy, EGL_CLIENT_APIS),
eglQueryString (dpy, EGL_EXTENSIONS)));
ctx = g_object_new (GDK_TYPE_WAYLAND_GL_CONTEXT,
"display", display,
NULL);
gdk_profiler_end_mark (start_time, "init Wayland GL", NULL);
return ctx;
}
static void
@@ -563,42 +606,3 @@ gdk_wayland_gl_context_dispose (GObject *gobject)
G_OBJECT_CLASS (gdk_wayland_gl_context_parent_class)->dispose (gobject);
}
gboolean
gdk_wayland_display_make_gl_context_current (GdkDisplay *display,
GdkGLContext *context)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
GdkWaylandGLContext *context_wayland;
GdkSurface *surface;
EGLSurface egl_surface;
if (context == NULL)
{
eglMakeCurrent(display_wayland->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
return TRUE;
}
context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
surface = gdk_gl_context_get_surface (context);
if (context_wayland->is_attached || gdk_draw_context_is_in_frame (GDK_DRAW_CONTEXT (context)))
egl_surface = gdk_wayland_surface_get_egl_surface (surface, context_wayland->egl_config);
else
{
if (display_wayland->have_egl_surfaceless_context)
egl_surface = EGL_NO_SURFACE;
else
egl_surface = gdk_wayland_surface_get_dummy_egl_surface (surface,
context_wayland->egl_config);
}
if (!eglMakeCurrent (display_wayland->egl_display, egl_surface,
egl_surface, context_wayland->egl_context))
{
g_warning ("eglMakeCurrent failed");
return FALSE;
}
return TRUE;
}

View File

@@ -36,8 +36,6 @@ struct _GdkWaylandGLContext
GdkGLContext parent_instance;
EGLContext egl_context;
EGLConfig egl_config;
gboolean is_attached;
};
struct _GdkWaylandGLContextClass
@@ -45,13 +43,8 @@ struct _GdkWaylandGLContextClass
GdkGLContextClass parent_class;
};
gboolean gdk_wayland_display_init_gl (GdkDisplay *display);
GdkGLContext * gdk_wayland_surface_create_gl_context (GdkSurface *surface,
gboolean attach,
GdkGLContext *share,
GdkGLContext * gdk_wayland_display_init_gl (GdkDisplay *display,
GError **error);
gboolean gdk_wayland_display_make_gl_context_current (GdkDisplay *display,
GdkGLContext *context);
G_END_DECLS

View File

@@ -182,11 +182,6 @@ cairo_surface_t * _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *di
struct wl_buffer *_gdk_wayland_shm_surface_get_wl_buffer (cairo_surface_t *surface);
gboolean _gdk_wayland_is_shm_surface (cairo_surface_t *surface);
EGLSurface gdk_wayland_surface_get_egl_surface (GdkSurface *surface,
EGLConfig config);
EGLSurface gdk_wayland_surface_get_dummy_egl_surface (GdkSurface *surface,
EGLConfig config);
struct gtk_surface1 * gdk_wayland_surface_get_gtk_surface (GdkSurface *surface);
void gdk_wayland_seat_set_global_cursor (GdkSeat *seat,

View File

@@ -103,7 +103,6 @@ struct _GdkWaylandSurface
struct gtk_surface1 *gtk_surface;
struct wl_egl_window *egl_window;
struct wl_egl_window *dummy_egl_window;
struct zxdg_exported_v1 *xdg_exported;
struct org_kde_kwin_server_decoration *server_decoration;
} display_server;
@@ -111,7 +110,6 @@ struct _GdkWaylandSurface
struct wl_event_queue *event_queue;
EGLSurface egl_surface;
EGLSurface dummy_egl_surface;
uint32_t reposition_token;
uint32_t received_reposition_token;
@@ -2901,18 +2899,6 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
if (impl->display_server.wl_surface)
{
if (impl->dummy_egl_surface)
{
eglDestroySurface (display_wayland->egl_display, impl->dummy_egl_surface);
impl->dummy_egl_surface = NULL;
}
if (impl->display_server.dummy_egl_window)
{
wl_egl_window_destroy (impl->display_server.dummy_egl_window);
impl->display_server.dummy_egl_window = NULL;
}
if (impl->egl_surface)
{
eglDestroySurface (display_wayland->egl_display, impl->egl_surface);
@@ -4238,7 +4224,6 @@ gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
impl_class->drag_begin = _gdk_wayland_surface_drag_begin;
impl_class->get_scale_factor = gdk_wayland_surface_get_scale_factor;
impl_class->set_opaque_region = gdk_wayland_surface_set_opaque_region;
impl_class->create_gl_context = gdk_wayland_surface_create_gl_context;
impl_class->request_layout = gdk_wayland_surface_request_layout;
impl_class->compute_size = gdk_wayland_surface_compute_size;
}
@@ -4304,8 +4289,7 @@ gdk_wayland_surface_get_wl_egl_window (GdkSurface *surface)
}
EGLSurface
gdk_wayland_surface_get_egl_surface (GdkSurface *surface,
EGLConfig config)
gdk_wayland_surface_get_egl_surface (GdkSurface *surface)
{
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
GdkWaylandSurface *impl;
@@ -4320,35 +4304,12 @@ gdk_wayland_surface_get_egl_surface (GdkSurface *surface,
egl_window = gdk_wayland_surface_get_wl_egl_window (surface);
impl->egl_surface =
eglCreateWindowSurface (display->egl_display, config, egl_window, NULL);
eglCreateWindowSurface (display->egl_display, display->egl_config, egl_window, NULL);
}
return impl->egl_surface;
}
EGLSurface
gdk_wayland_surface_get_dummy_egl_surface (GdkSurface *surface,
EGLConfig config)
{
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
GdkWaylandSurface *impl;
g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (surface), NULL);
impl = GDK_WAYLAND_SURFACE (surface);
if (impl->dummy_egl_surface == NULL)
{
impl->display_server.dummy_egl_window =
wl_egl_window_create (impl->display_server.wl_surface, 1, 1);
impl->dummy_egl_surface =
eglCreateWindowSurface (display->egl_display, config, impl->display_server.dummy_egl_window, NULL);
}
return impl->dummy_egl_surface;
}
struct gtk_surface1 *
gdk_wayland_surface_get_gtk_surface (GdkSurface *surface)
{

View File

@@ -22,6 +22,9 @@
#include "gdkwaylandsurface.h"
#include <wayland-egl.h>
#include <epoxy/egl.h>
G_BEGIN_DECLS
void gdk_wayland_toplevel_set_dbus_properties (GdkToplevel *toplevel,
@@ -38,4 +41,6 @@ void gdk_wayland_toplevel_announce_ssd (GdkTopl
gboolean gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel);
void gdk_wayland_toplevel_uninhibit_idle (GdkToplevel *toplevel);
EGLSurface gdk_wayland_surface_get_egl_surface (GdkSurface *surface);
G_END_DECLS

View File

@@ -481,6 +481,7 @@ register_display_change_notification (GdkDisplay *display)
wclass.lpszClassName = "GdkDisplayChange";
wclass.lpfnWndProc = display_change_window_procedure;
wclass.hInstance = _gdk_app_hmodule;
wclass.style = CS_OWNDC;
klass = RegisterClass (&wclass);
if (klass)
@@ -656,6 +657,13 @@ gdk_win32_display_dispose (GObject *object)
if (display_win32->hwnd != NULL)
{
if (display_win32->dummy_context_wgl.hglrc != NULL)
{
wglMakeCurrent (NULL, NULL);
wglDeleteContext (display_win32->dummy_context_wgl.hglrc);
display_win32->dummy_context_wgl.hglrc = NULL;
}
DestroyWindow (display_win32->hwnd);
display_win32->hwnd = NULL;
}
@@ -982,31 +990,32 @@ _gdk_win32_check_on_arm64 (GdkWin32Display *display)
}
static void
gdk_win32_display_init (GdkWin32Display *display)
gdk_win32_display_init (GdkWin32Display *display_win32)
{
const char *scale_str = g_getenv ("GDK_SCALE");
display->monitors = G_LIST_MODEL (g_list_store_new (GDK_TYPE_MONITOR));
display_win32->monitors = G_LIST_MODEL (g_list_store_new (GDK_TYPE_MONITOR));
_gdk_win32_enable_hidpi (display);
_gdk_win32_check_on_arm64 (display);
_gdk_win32_enable_hidpi (display_win32);
_gdk_win32_check_on_arm64 (display_win32);
/* if we have DPI awareness, set up fixed scale if set */
if (display->dpi_aware_type != PROCESS_DPI_UNAWARE &&
if (display_win32->dpi_aware_type != PROCESS_DPI_UNAWARE &&
scale_str != NULL)
{
display->surface_scale = atol (scale_str);
display_win32->surface_scale = atol (scale_str);
if (display->surface_scale <= 0)
display->surface_scale = 1;
if (display_win32->surface_scale <= 0)
display_win32->surface_scale = 1;
display->has_fixed_scale = TRUE;
display_win32->has_fixed_scale = TRUE;
}
else
display->surface_scale = _gdk_win32_display_get_monitor_scale_factor (display, NULL, NULL, NULL);
display_win32->surface_scale =
gdk_win32_display_get_monitor_scale_factor (display_win32, NULL, NULL);
_gdk_win32_display_init_cursors (display);
gdk_win32_display_check_composited (display);
_gdk_win32_display_init_cursors (display_win32);
gdk_win32_display_check_composited (display_win32);
}
void
@@ -1057,64 +1066,64 @@ gdk_win32_display_get_monitors (GdkDisplay *display)
}
guint
_gdk_win32_display_get_monitor_scale_factor (GdkWin32Display *win32_display,
HMONITOR hmonitor,
HWND hwnd,
int *dpi)
gdk_win32_display_get_monitor_scale_factor (GdkWin32Display *display_win32,
GdkSurface *surface,
HMONITOR hmonitor)
{
gboolean is_scale_acquired = FALSE;
gboolean use_dpi_for_monitor = FALSE;
guint dpix, dpiy;
if (win32_display->have_at_least_win81)
if (display_win32->have_at_least_win81)
{
if (hmonitor != NULL)
if (surface != NULL && hmonitor == NULL)
hmonitor = MonitorFromWindow (GDK_SURFACE_HWND (surface),
MONITOR_DEFAULTTONEAREST);
if (hmonitor != NULL &&
display_win32->shcore_funcs.hshcore != NULL &&
display_win32->shcore_funcs.getDpiForMonitorFunc != NULL)
use_dpi_for_monitor = TRUE;
else
{
if (hwnd != NULL)
{
hmonitor = MonitorFromWindow (hwnd, MONITOR_DEFAULTTONEAREST);
use_dpi_for_monitor = TRUE;
}
}
}
if (use_dpi_for_monitor)
{
/* Use GetDpiForMonitor() for Windows 8.1+, when we have a HMONITOR */
if (win32_display->shcore_funcs.hshcore != NULL &&
win32_display->shcore_funcs.getDpiForMonitorFunc != NULL)
{
if (win32_display->shcore_funcs.getDpiForMonitorFunc (hmonitor,
MDT_EFFECTIVE_DPI,
&dpix,
&dpiy) == S_OK)
{
is_scale_acquired = TRUE;
}
}
if (display_win32->shcore_funcs.getDpiForMonitorFunc (hmonitor,
MDT_EFFECTIVE_DPI,
&dpix,
&dpiy) == S_OK)
is_scale_acquired = TRUE;
}
else
{
/* Go back to GetDeviceCaps() for Windows 8 and earlier, or when we don't
* have a HMONITOR nor a HWND
*/
HDC hdc = GetDC (hwnd);
HDC hdc;
if (surface != NULL)
{
if (GDK_WIN32_SURFACE (surface)->hdc == NULL)
GDK_WIN32_SURFACE (surface)->hdc = GetDC (GDK_SURFACE_HWND (surface));
hdc = GDK_WIN32_SURFACE (surface)->hdc;
}
else
hdc = GetDC (NULL);
/* in case we can't get the DC for the window, return 1 for the scale */
if (hdc == NULL)
{
if (dpi != NULL)
*dpi = USER_DEFAULT_SCREEN_DPI;
return 1;
}
return 1;
dpix = GetDeviceCaps (hdc, LOGPIXELSX);
dpiy = GetDeviceCaps (hdc, LOGPIXELSY);
ReleaseDC (hwnd, hdc);
/*
* If surface is not NULL, the HDC should not be released, since surfaces have
* Win32 windows created with CS_OWNDC
*/
if (surface == NULL)
ReleaseDC (NULL, hdc);
is_scale_acquired = TRUE;
}
@@ -1122,21 +1131,13 @@ _gdk_win32_display_get_monitor_scale_factor (GdkWin32Display *win32_display,
if (is_scale_acquired)
/* USER_DEFAULT_SCREEN_DPI = 96, in winuser.h */
{
if (dpi != NULL)
*dpi = dpix;
if (win32_display->has_fixed_scale)
return win32_display->surface_scale;
if (display_win32->has_fixed_scale)
return display_win32->surface_scale;
else
return dpix / USER_DEFAULT_SCREEN_DPI > 1 ? dpix / USER_DEFAULT_SCREEN_DPI : 1;
}
else
{
if (dpi != NULL)
*dpi = USER_DEFAULT_SCREEN_DPI;
return 1;
}
return 1;
}
static gboolean
@@ -1147,6 +1148,85 @@ gdk_win32_display_get_setting (GdkDisplay *display,
return _gdk_win32_get_setting (name, value);
}
static gboolean
gdk_win32_display_init_gl_backend (GdkDisplay *display,
GError **error)
{
#ifdef GDK_WIN32_ENABLE_EGL
if (GDK_DISPLAY_DEBUG_CHECK (display, GL_EGL))
return gdk_win32_display_init_egl (display, error);
#endif
if (GDK_DISPLAY_DEBUG_CHECK (display, GL_WGL))
return gdk_win32_display_init_wgl (display, error);
/* No env vars set, do the regular GL initialization, first WGL and then EGL,
* as WGL is the more tried-and-tested configuration.
*/
if (gdk_win32_display_init_wgl (display, error))
return TRUE;
g_clear_error (error);
#ifdef GDK_WIN32_ENABLE_EGL
if (gdk_win32_display_init_egl (display, error))
return TRUE;
#endif
g_clear_error (error);
return gdk_win32_display_init_wgl (display, error);
}
static GdkGLContext *
gdk_win32_display_init_gl (GdkDisplay *display,
GError **error)
{
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
GdkGLContext *gl_context = NULL;
if (!gdk_win32_display_init_gl_backend (display, error))
return NULL;
#ifdef GDK_WIN32_ENABLE_EGL
if (display_win32->egl_disp)
gl_context = g_object_new (GDK_TYPE_WIN32_GL_CONTEXT_EGL, "display", display, NULL);
else
#endif
if (display_win32->wgl_pixel_format != 0)
gl_context = g_object_new (GDK_TYPE_WIN32_GL_CONTEXT_WGL, "display", display, NULL);
g_return_val_if_fail (gl_context != NULL, NULL);
return gl_context;
}
/**
* gdk_win32_display_get_egl_display:
* @display: (type GdkWin32Display): a Win32 display
*
* Retrieves the EGL display connection object for the given GDK display.
*
* Returns: (nullable): the EGL display
*/
gpointer
gdk_win32_display_get_egl_display (GdkDisplay *display)
{
GdkWin32Display *display_win32;
g_return_val_if_fail (GDK_IS_WIN32_DISPLAY (display), NULL);
#ifdef GDK_WIN32_ENABLE_EGL
display_win32 = GDK_WIN32_DISPLAY (display);
if (display_win32->wgl_pixel_format != 0)
return NULL;
return display_win32->egl_disp;
#else
/* no EGL support */
return NULL;
#endif
}
static void
gdk_win32_display_class_init (GdkWin32DisplayClass *klass)
{
@@ -1172,7 +1252,6 @@ gdk_win32_display_class_init (GdkWin32DisplayClass *klass)
display_class->create_surface = _gdk_win32_display_create_surface;
display_class->get_keymap = _gdk_win32_display_get_keymap;
display_class->make_gl_context_current = _gdk_win32_display_make_gl_context_current;
display_class->get_monitors = gdk_win32_display_get_monitors;
@@ -1183,6 +1262,7 @@ gdk_win32_display_class_init (GdkWin32DisplayClass *klass)
display_class->get_setting = gdk_win32_display_get_setting;
display_class->set_cursor_theme = gdk_win32_display_set_cursor_theme;
display_class->init_gl = gdk_win32_display_init_gl;
_gdk_win32_surfaceing_init ();
}

View File

@@ -106,6 +106,12 @@ typedef struct _GdkWin32KernelCPUFuncs
funcIsWow64Process2 isWow64Process2;
} GdkWin32KernelCPUFuncs;
typedef struct
{
HDC hdc;
HGLRC hglrc;
} GdkWin32GLDummyContextWGL;
struct _GdkWin32Display
{
GdkDisplay display;
@@ -119,15 +125,15 @@ struct _GdkWin32Display
HWND hwnd;
/* WGL/OpenGL Items */
guint have_wgl : 1;
GdkWin32GLDummyContextWGL dummy_context_wgl;
int wgl_pixel_format;
guint gl_version;
HWND gl_hwnd;
#ifdef GDK_WIN32_ENABLE_EGL
/* EGL (Angle) Items */
guint have_egl : 1;
guint egl_version;
EGLDisplay egl_disp;
EGLConfig egl_config;
HDC hdc_egl_temp;
#endif
@@ -185,10 +191,9 @@ GPtrArray *_gdk_win32_display_get_monitor_list (GdkWin32Display *display);
void gdk_win32_display_check_composited (GdkWin32Display *display);
guint _gdk_win32_display_get_monitor_scale_factor (GdkWin32Display *win32_display,
HMONITOR hmonitor,
HWND hwnd,
int *dpi);
guint gdk_win32_display_get_monitor_scale_factor (GdkWin32Display *display_win32,
GdkSurface *surface,
HMONITOR hmonitor);
typedef struct _GdkWin32MessageFilter GdkWin32MessageFilter;

View File

@@ -793,7 +793,7 @@ gdk_drag_new (GdkDisplay *display,
GdkDragProtocol protocol)
{
GdkWin32Drag *drag_win32;
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (display);
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
GdkDrag *drag;
drag_win32 = g_object_new (GDK_TYPE_WIN32_DRAG,
@@ -805,10 +805,10 @@ gdk_drag_new (GdkDisplay *display,
drag = GDK_DRAG (drag_win32);
if (win32_display->has_fixed_scale)
drag_win32->scale = win32_display->surface_scale;
if (display_win32->has_fixed_scale)
drag_win32->scale = display_win32->surface_scale;
else
drag_win32->scale = _gdk_win32_display_get_monitor_scale_factor (win32_display, NULL, NULL, NULL);
drag_win32->scale = gdk_win32_display_get_monitor_scale_factor (display_win32, NULL, NULL);
drag_win32->protocol = protocol;
@@ -2345,8 +2345,8 @@ gdk_dnd_handle_motion_event (GdkDrag *drag,
state = gdk_event_get_modifier_state (event);
gdk_event_get_position (event, &x, &y);
x_root = x + _gdk_offset_x;
y_root = y + _gdk_offset_y;
x_root = event->surface->x + x;
y_root = event->surface->y + y;
if (drag_win32->drag_surface)
move_drag_surface (drag, x_root, y_root);

View File

@@ -177,7 +177,7 @@ gdk_drop_new (GdkDisplay *display,
GdkDragProtocol protocol)
{
GdkWin32Drop *drop_win32;
GdkWin32Display *win32_display = GDK_WIN32_DISPLAY (display);
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
drop_win32 = g_object_new (GDK_TYPE_WIN32_DROP,
"device", device,
@@ -186,10 +186,10 @@ gdk_drop_new (GdkDisplay *display,
"surface", surface,
NULL);
if (win32_display->has_fixed_scale)
drop_win32->scale = win32_display->surface_scale;
if (display_win32->has_fixed_scale)
drop_win32->scale = display_win32->surface_scale;
else
drop_win32->scale = _gdk_win32_display_get_monitor_scale_factor (win32_display, NULL, NULL, NULL);
drop_win32->scale = gdk_win32_display_get_monitor_scale_factor (display_win32, NULL, NULL);
drop_win32->protocol = protocol;

View File

@@ -2343,7 +2343,6 @@ gdk_event_translate (MSG *msg,
current_root_x = (msg->pt.x + _gdk_offset_x) / impl->surface_scale;
current_root_y = (msg->pt.y + _gdk_offset_y) / impl->surface_scale;
if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
gdk_win32_surface_do_move_resize_drag (window, current_root_x, current_root_y);
else if (_gdk_input_ignore_core == 0)

View File

@@ -0,0 +1,504 @@
/* GDK - The GIMP Drawing Kit
*
* gdkglcontext-win32.c: Win32 specific OpenGL wrappers
*
* Copyright © 2014 Emmanuele Bassi
* Copyright © 2014 Alexander Larsson
* Copyright © 2014 Chun-wei Fan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdkprivate-win32.h"
#include "gdksurface-win32.h"
#include "gdkglcontext-win32.h"
#include "gdkdisplay-win32.h"
#include "gdkwin32display.h"
#include "gdkwin32glcontext.h"
#include "gdkwin32misc.h"
#include "gdkwin32screen.h"
#include "gdkwin32surface.h"
#include "gdkglcontext.h"
#include "gdksurface.h"
#include "gdkinternals.h"
#include "gdkintl.h"
#include <cairo.h>
#include <epoxy/egl.h>
struct _GdkWin32GLContextEGL
{
GdkWin32GLContext parent_instance;
/* EGL (Angle) Context Items */
EGLContext egl_context;
guint do_frame_sync : 1;
};
typedef struct _GdkWin32GLContextClass GdkWin32GLContextEGLClass;
G_DEFINE_TYPE (GdkWin32GLContextEGL, gdk_win32_gl_context_egl, GDK_TYPE_WIN32_GL_CONTEXT)
static void
gdk_win32_gl_context_egl_dispose (GObject *gobject)
{
GdkGLContext *context = GDK_GL_CONTEXT (gobject);
GdkWin32GLContextEGL *context_egl = GDK_WIN32_GL_CONTEXT_EGL (gobject);
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (gdk_gl_context_get_display (context));
GdkSurface *surface = gdk_gl_context_get_surface (context);
if (display_win32 != NULL)
{
if (eglGetCurrentContext () == context_egl->egl_context)
eglMakeCurrent(display_win32->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
GDK_NOTE (OPENGL, g_message ("Destroying EGL (ANGLE) context"));
eglDestroyContext (display_win32->egl_disp,
context_egl->egl_context);
context_egl->egl_context = EGL_NO_CONTEXT;
}
G_OBJECT_CLASS (gdk_win32_gl_context_egl_parent_class)->dispose (gobject);
}
static gboolean
is_egl_force_redraw (GdkSurface *surface)
{
/* We only need to call gdk_window_invalidate_rect () if necessary */
if (surface->gl_paint_context != NULL && gdk_gl_context_get_use_es (surface->gl_paint_context))
{
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
return impl->egl_force_redraw_all;
}
return FALSE;
}
static void
reset_egl_force_redraw (GdkSurface *surface)
{
if (surface->gl_paint_context != NULL && gdk_gl_context_get_use_es (surface->gl_paint_context))
{
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
if (impl->egl_force_redraw_all)
impl->egl_force_redraw_all = FALSE;
}
}
static void
gdk_win32_gl_context_egl_end_frame (GdkDrawContext *draw_context,
cairo_region_t *painted)
{
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
GdkWin32GLContextEGL *context_egl = GDK_WIN32_GL_CONTEXT_EGL (context);
GdkSurface *surface = gdk_gl_context_get_surface (context);
GdkWin32Display *display_win32 = (GDK_WIN32_DISPLAY (gdk_gl_context_get_display (context)));
cairo_rectangle_int_t whole_window;
EGLSurface egl_surface;
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_egl_parent_class)->end_frame (draw_context, painted);
gdk_gl_context_make_current (context);
whole_window =
(GdkRectangle) { 0, 0,
gdk_surface_get_width (surface),
gdk_surface_get_height (surface)
};
egl_surface = gdk_win32_surface_get_egl_surface (surface, display_win32->egl_config, FALSE);
if (is_egl_force_redraw (surface))
{
GdkRectangle rect = {0, 0, gdk_surface_get_width (surface), gdk_surface_get_height (surface)};
/* We need to do gdk_window_invalidate_rect() so that we don't get glitches after maximizing or
* restoring or using aerosnap
*/
gdk_surface_invalidate_rect (surface, &rect);
reset_egl_force_redraw (surface);
}
eglSwapBuffers (display_win32->egl_disp, egl_surface);
}
#ifndef EGL_PLATFORM_ANGLE_ANGLE
#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
#endif
#ifndef EGL_PLATFORM_ANGLE_TYPE_ANGLE
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
#endif
#ifndef EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
#endif
static EGLDisplay
gdk_win32_get_egl_display (GdkWin32Display *display)
{
EGLDisplay disp;
if (epoxy_has_egl_extension (NULL, "EGL_EXT_platform_base"))
{
PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay = (void *) eglGetProcAddress ("eglGetPlatformDisplayEXT");
if (getPlatformDisplay)
{
EGLint disp_attr[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_NONE};
disp = getPlatformDisplay (EGL_PLATFORM_ANGLE_ANGLE, display->hdc_egl_temp, disp_attr);
if (disp != EGL_NO_DISPLAY)
return disp;
}
}
return eglGetDisplay (display->hdc_egl_temp);
}
#define MAX_EGL_ATTRS 30
static gboolean
find_eglconfig_for_window (GdkWin32Display *display,
EGLConfig *egl_config_out,
EGLint *min_swap_interval_out,
GError **error)
{
EGLint attrs[MAX_EGL_ATTRS];
EGLint count;
EGLConfig *configs, chosen_config;
int i = 0;
EGLDisplay egl_disp = display->egl_disp;
attrs[i++] = EGL_CONFORMANT;
attrs[i++] = EGL_OPENGL_ES2_BIT;
attrs[i++] = EGL_SURFACE_TYPE;
attrs[i++] = EGL_WINDOW_BIT;
attrs[i++] = EGL_COLOR_BUFFER_TYPE;
attrs[i++] = EGL_RGB_BUFFER;
attrs[i++] = EGL_RED_SIZE;
attrs[i++] = 1;
attrs[i++] = EGL_GREEN_SIZE;
attrs[i++] = 1;
attrs[i++] = EGL_BLUE_SIZE;
attrs[i++] = 1;
attrs[i++] = EGL_ALPHA_SIZE;
attrs[i++] = 1;
attrs[i++] = EGL_NONE;
g_assert (i < MAX_EGL_ATTRS);
if (!eglChooseConfig (display->egl_disp, attrs, NULL, 0, &count) || count < 1)
{
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
_("No available configurations for the given pixel format"));
return FALSE;
}
configs = g_new (EGLConfig, count);
if (!eglChooseConfig (display->egl_disp, attrs, configs, count, &count) || count < 1)
{
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
_("No available configurations for the given pixel format"));
return FALSE;
}
/* Pick first valid configuration i guess? */
chosen_config = configs[0];
if (!eglGetConfigAttrib (display->egl_disp, chosen_config,
EGL_MIN_SWAP_INTERVAL, min_swap_interval_out))
{
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
"Could not retrieve the minimum swap interval");
g_free (configs);
return FALSE;
}
if (egl_config_out != NULL)
*egl_config_out = chosen_config;
g_free (configs);
return TRUE;
}
gboolean
gdk_win32_display_init_egl (GdkDisplay *display,
GError **error)
{
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
int best_idx = 0;
EGLDisplay egl_disp;
if (display_win32->egl_disp != EGL_NO_DISPLAY)
return TRUE;
egl_disp = gdk_win32_get_egl_display (display_win32);
if (egl_disp == EGL_NO_DISPLAY)
return FALSE;
if (!eglInitialize (egl_disp, NULL, NULL))
{
eglTerminate (egl_disp);
egl_disp = EGL_NO_DISPLAY;
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("No GL implementation is available"));
return FALSE;
}
display_win32->egl_disp = egl_disp;
display_win32->egl_version = epoxy_egl_version (egl_disp);
eglBindAPI(EGL_OPENGL_ES_API);
display_win32->hasEglSurfacelessContext =
epoxy_has_egl_extension (egl_disp, "EGL_KHR_surfaceless_context");
GDK_NOTE (OPENGL,
g_print ("EGL API version %d.%d found\n"
" - Vendor: %s\n"
" - Checked extensions:\n"
"\t* EGL_KHR_surfaceless_context: %s\n",
display_win32->egl_version / 10,
display_win32->egl_version % 10,
eglQueryString (display_win32->egl_disp, EGL_VENDOR),
display_win32->hasEglSurfacelessContext ? "yes" : "no"));
return find_eglconfig_for_window (display_win32, &display_win32->egl_config,
&display_win32->egl_min_swap_interval, error);
}
#define N_EGL_ATTRS 16
static EGLContext
create_egl_context (EGLDisplay display,
EGLConfig config,
GdkGLContext *share,
int flags,
int major,
int minor,
gboolean *is_legacy)
{
EGLContext ctx;
EGLint context_attribs[N_EGL_ATTRS];
int i = 0;
/* ANGLE does not support the GL_OES_vertex_array_object extension, so we need to use ES3 directly */
context_attribs[i++] = EGL_CONTEXT_CLIENT_VERSION;
context_attribs[i++] = 3;
/* Specify the flags */
context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR;
context_attribs[i++] = flags;
context_attribs[i++] = EGL_NONE;
g_assert (i < N_EGL_ATTRS);
ctx = eglCreateContext (display,
config,
share != NULL ? GDK_WIN32_GL_CONTEXT_EGL (share)->egl_context
: EGL_NO_CONTEXT,
context_attribs);
if (ctx != EGL_NO_CONTEXT)
GDK_NOTE (OPENGL, g_message ("Created EGL context[%p]", ctx));
return ctx;
}
static gboolean
gdk_win32_gl_context_egl_realize (GdkGLContext *context,
GError **error)
{
GdkWin32GLContextEGL *context_egl = GDK_WIN32_GL_CONTEXT_EGL (context);
gboolean debug_bit, compat_bit, legacy_bit;
gboolean use_es = FALSE;
EGLContext egl_context;
EGLContext ctx;
/* request flags and specific versions for core (3.2+) WGL context */
int flags = 0;
int major = 0;
int minor = 0;
GdkSurface *surface = gdk_gl_context_get_surface (context);
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
GdkDisplay *display = gdk_gl_context_get_display (context);
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
GdkGLContext *share = gdk_display_get_gl_context (display);
gdk_gl_context_get_required_version (context, &major, &minor);
debug_bit = gdk_gl_context_get_debug_enabled (context);
compat_bit = gdk_gl_context_get_forward_compatible (context);
/*
* A legacy context cannot be shared with core profile ones, so this means we
* must stick to a legacy context if the shared context is a legacy context
*/
/* if GDK_GL_LEGACY is set, we default to a legacy context */
legacy_bit = GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY) ?
TRUE :
share != NULL && gdk_gl_context_is_legacy (share);
use_es = GDK_DISPLAY_DEBUG_CHECK (display, GL_GLES) ||
(share != NULL && gdk_gl_context_get_use_es (share));
if (debug_bit)
flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
if (compat_bit)
flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
GDK_NOTE (OPENGL, g_message ("Creating EGL context version %d.%d (debug:%s, forward:%s, legacy:%s)",
major, minor,
debug_bit ? "yes" : "no",
compat_bit ? "yes" : "no",
legacy_bit ? "yes" : "no"));
ctx = create_egl_context (display_win32->egl_disp,
display_win32->egl_config,
share,
flags,
major,
minor,
&legacy_bit);
if (ctx == EGL_NO_CONTEXT)
{
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("Unable to create a GL context"));
return FALSE;
}
GDK_NOTE (OPENGL, g_print ("Created EGL context[%p]\n", ctx));
context_egl->egl_context = ctx;
/* We are using GLES here */
gdk_gl_context_set_use_es (context, TRUE);
/* Ensure that any other context is created with a legacy bit set */
gdk_gl_context_set_is_legacy (context, legacy_bit);
return TRUE;
}
static gboolean
gdk_win32_gl_context_egl_clear_current (GdkGLContext *context)
{
GdkDisplay *display = gdk_gl_context_get_display (context);
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
if (display_win32->egl_disp != EGL_NO_DISPLAY)
return eglMakeCurrent (display_win32->egl_disp,
EGL_NO_SURFACE,
EGL_NO_SURFACE,
EGL_NO_CONTEXT);
else
return TRUE;
}
static gboolean
gdk_win32_gl_context_egl_make_current (GdkGLContext *context,
gboolean surfaceless)
{
GdkWin32GLContextEGL *context_egl = GDK_WIN32_GL_CONTEXT_EGL (context);
GdkDisplay *display = gdk_gl_context_get_display (context);
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
GdkSurface *surface;
gboolean do_frame_sync = FALSE;
EGLSurface egl_surface;
surface = gdk_gl_context_get_surface (context);
if (!surfaceless)
egl_surface = gdk_win32_surface_get_egl_surface (surface, display_win32->egl_config, FALSE);
else
{
if (display_win32->hasEglSurfacelessContext)
egl_surface = EGL_NO_SURFACE;
else
egl_surface = gdk_win32_surface_get_egl_surface (surface, display_win32->egl_config, TRUE);
}
if (!eglMakeCurrent (display_win32->egl_disp,
egl_surface,
egl_surface,
context_egl->egl_context))
return FALSE;
if (display_win32->egl_min_swap_interval == 0)
eglSwapInterval (display_win32->egl_disp, 0);
else
g_debug ("Can't disable GL swap interval");
return TRUE;
}
static void
gdk_win32_gl_context_egl_begin_frame (GdkDrawContext *draw_context,
cairo_region_t *update_area)
{
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
GdkSurface *surface;
surface = gdk_gl_context_get_surface (context);
gdk_win32_surface_handle_queued_move_resize (draw_context);
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_egl_parent_class)->begin_frame (draw_context, update_area);
}
static void
gdk_win32_gl_context_egl_class_init (GdkWin32GLContextClass *klass)
{
GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS(klass);
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS(klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
context_class->realize = gdk_win32_gl_context_egl_realize;
context_class->make_current = gdk_win32_gl_context_egl_make_current;
context_class->clear_current = gdk_win32_gl_context_egl_clear_current;
draw_context_class->begin_frame = gdk_win32_gl_context_egl_begin_frame;
draw_context_class->end_frame = gdk_win32_gl_context_egl_end_frame;
gobject_class->dispose = gdk_win32_gl_context_egl_dispose;
}
static void
gdk_win32_gl_context_egl_init (GdkWin32GLContextEGL *egl_context)
{
}

View File

@@ -0,0 +1,727 @@
/* GDK - The GIMP Drawing Kit
*
* gdkglcontext-win32.c: Win32 specific OpenGL wrappers
*
* Copyright © 2014 Emmanuele Bassi
* Copyright © 2014 Alexander Larsson
* Copyright © 2014 Chun-wei Fan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdkprivate-win32.h"
#include "gdksurface-win32.h"
#include "gdkglcontext-win32.h"
#include "gdkdisplay-win32.h"
#include "gdkwin32display.h"
#include "gdkwin32glcontext.h"
#include "gdkwin32misc.h"
#include "gdkwin32screen.h"
#include "gdkwin32surface.h"
#include "gdkglcontext.h"
#include "gdkprofilerprivate.h"
#include "gdkinternals.h"
#include "gdkintl.h"
#include "gdksurface.h"
#include <cairo.h>
#include <epoxy/wgl.h>
struct _GdkWin32GLContextWGL
{
GdkWin32GLContext parent_instance;
HGLRC wgl_context;
guint do_frame_sync : 1;
};
typedef struct _GdkWin32GLContextClass GdkWin32GLContextWGLClass;
G_DEFINE_TYPE (GdkWin32GLContextWGL, gdk_win32_gl_context_wgl, GDK_TYPE_WIN32_GL_CONTEXT)
static void
gdk_win32_gl_context_wgl_dispose (GObject *gobject)
{
GdkWin32GLContextWGL *context_wgl = GDK_WIN32_GL_CONTEXT_WGL (gobject);
if (context_wgl->wgl_context != NULL)
{
if (wglGetCurrentContext () == context_wgl->wgl_context)
wglMakeCurrent (NULL, NULL);
GDK_NOTE (OPENGL, g_print ("Destroying WGL context\n"));
wglDeleteContext (context_wgl->wgl_context);
context_wgl->wgl_context = NULL;
}
G_OBJECT_CLASS (gdk_win32_gl_context_wgl_parent_class)->dispose (gobject);
}
static void
gdk_win32_gl_context_wgl_end_frame (GdkDrawContext *draw_context,
cairo_region_t *painted)
{
GdkGLContext *context = GDK_GL_CONTEXT (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)));
cairo_rectangle_int_t whole_window;
gboolean can_wait = display_win32->hasWglOMLSyncControl;
HDC hdc;
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->end_frame (draw_context, painted);
gdk_gl_context_make_current (context);
whole_window = (GdkRectangle) { 0, 0, gdk_surface_get_width (surface), gdk_surface_get_height (surface) };
gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "win32", "swap buffers");
if (surface != NULL)
hdc = GDK_WIN32_SURFACE (surface)->hdc;
else
hdc = display_win32->dummy_context_wgl.hdc;
if (context_wgl->do_frame_sync)
{
glFinish ();
if (can_wait)
{
gint64 ust, msc, sbc;
wglGetSyncValuesOML (hdc, &ust, &msc, &sbc);
wglWaitForMscOML (hdc,
0,
2,
(msc + 1) % 2,
&ust, &msc, &sbc);
}
}
SwapBuffers (hdc);
}
static void
gdk_win32_gl_context_wgl_begin_frame (GdkDrawContext *draw_context,
cairo_region_t *update_area)
{
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
GdkSurface *surface;
surface = gdk_gl_context_get_surface (context);
gdk_win32_surface_handle_queued_move_resize (draw_context);
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->begin_frame (draw_context, update_area);
}
static int
gdk_init_dummy_wgl_context (GdkWin32Display *display_win32);
#define PIXEL_ATTRIBUTES 17
static int
get_wgl_pfd (HDC hdc,
PIXELFORMATDESCRIPTOR *pfd,
GdkWin32Display *display_win32)
{
int best_pf = 0;
pfd->nSize = sizeof (PIXELFORMATDESCRIPTOR);
if (display_win32 != NULL && 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;
/* end of "Update PIXEL_ATTRIBUTES above if any groups are added here!" */
if (display_win32->hasWglARBmultisample)
{
pixelAttribs[i++] = WGL_SAMPLE_BUFFERS_ARB;
pixelAttribs[i++] = 1;
pixelAttribs[i++] = WGL_SAMPLES_ARB;
pixelAttribs[i++] = 8;
}
pixelAttribs[i++] = 0; /* end of pixelAttribs */
best_pf = gdk_init_dummy_wgl_context (display_win32);
if (!wglMakeCurrent (display_win32->dummy_context_wgl.hdc,
display_win32->dummy_context_wgl.hglrc))
{
wglMakeCurrent (hdc_current, hglrc_current);
return 0;
}
wglChoosePixelFormatARB (hdc,
pixelAttribs,
NULL,
1,
&best_pf,
&num_formats);
/* 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->dwLayerMask = PFD_MAIN_PLANE;
best_pf = ChoosePixelFormat (hdc, pfd);
}
return best_pf;
}
/* in WGL, for many OpenGL items, we need a dummy WGL context, so create
* one and cache it for later use
*/
static int
gdk_init_dummy_wgl_context (GdkWin32Display *display_win32)
{
PIXELFORMATDESCRIPTOR pfd;
gboolean set_pixel_format_result = FALSE;
int best_idx = 0;
if (display_win32->dummy_context_wgl.hdc == NULL)
display_win32->dummy_context_wgl.hdc = GetDC (display_win32->hwnd);
memset (&pfd, 0, sizeof (PIXELFORMATDESCRIPTOR));
best_idx = get_wgl_pfd (display_win32->dummy_context_wgl.hdc, &pfd, NULL);
if (best_idx != 0)
set_pixel_format_result = SetPixelFormat (display_win32->dummy_context_wgl.hdc,
best_idx,
&pfd);
if (best_idx == 0 || !set_pixel_format_result)
return 0;
display_win32->dummy_context_wgl.hglrc =
wglCreateContext (display_win32->dummy_context_wgl.hdc);
if (display_win32->dummy_context_wgl.hglrc == NULL)
return 0;
return best_idx;
}
gboolean
gdk_win32_display_init_wgl (GdkDisplay *display,
GError **error)
{
int best_idx = 0;
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
HDC hdc;
if (display_win32->wgl_pixel_format != 0)
return TRUE;
/* acquire and cache dummy Window (HWND & HDC) and
* dummy GL Context, it is used to query functions
* and used for other stuff as well
*/
best_idx = gdk_init_dummy_wgl_context (display_win32);
hdc = display_win32->dummy_context_wgl.hdc;
if (best_idx == 0 ||
!wglMakeCurrent (hdc, display_win32->dummy_context_wgl.hglrc))
{
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("No GL implementation is available"));
return FALSE;
}
display_win32->wgl_pixel_format = best_idx;
display_win32->gl_version = epoxy_gl_version ();
display_win32->hasWglARBCreateContext =
epoxy_has_wgl_extension (hdc, "WGL_ARB_create_context");
display_win32->hasWglEXTSwapControl =
epoxy_has_wgl_extension (hdc, "WGL_EXT_swap_control");
display_win32->hasWglOMLSyncControl =
epoxy_has_wgl_extension (hdc, "WGL_OML_sync_control");
display_win32->hasWglARBPixelFormat =
epoxy_has_wgl_extension (hdc, "WGL_ARB_pixel_format");
display_win32->hasWglARBmultisample =
epoxy_has_wgl_extension (hdc, "WGL_ARB_multisample");
GDK_NOTE (OPENGL,
g_print ("WGL API version %d.%d found\n"
" - Vendor: %s\n"
" - Checked extensions:\n"
"\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_ARB_multisample: %s\n",
display_win32->gl_version / 10,
display_win32->gl_version % 10,
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->hasWglARBmultisample ? "yes" : "no"));
wglMakeCurrent (NULL, NULL);
return TRUE;
}
/* Setup the legacy context after creating it */
static gboolean
ensure_legacy_wgl_context (HDC hdc,
HGLRC hglrc_legacy,
GdkGLContext *share)
{
GdkWin32GLContextWGL *context_wgl;
if (!wglMakeCurrent (hdc, hglrc_legacy))
return FALSE;
if (share != NULL)
{
context_wgl = GDK_WIN32_GL_CONTEXT_WGL (share);
return wglShareLists (hglrc_legacy, context_wgl->wgl_context);
}
return TRUE;
}
static HGLRC
create_wgl_context_with_attribs (HDC hdc,
HGLRC hglrc_base,
GdkGLContext *share,
int flags,
int major,
int minor,
gboolean *is_legacy)
{
HGLRC hglrc;
GdkWin32GLContextWGL *context_wgl;
/* if we have wglCreateContextAttribsARB(), create a
* context with the compatibility profile if a legacy
* context is requested, or when we go into fallback mode
*/
int profile = *is_legacy ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :
WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
int attribs[] = {
WGL_CONTEXT_PROFILE_MASK_ARB, profile,
WGL_CONTEXT_MAJOR_VERSION_ARB, *is_legacy ? 3 : major,
WGL_CONTEXT_MINOR_VERSION_ARB, *is_legacy ? 0 : minor,
WGL_CONTEXT_FLAGS_ARB, flags,
0
};
if (share != NULL)
context_wgl = GDK_WIN32_GL_CONTEXT_WGL (share);
hglrc = wglCreateContextAttribsARB (hdc,
share != NULL ? context_wgl->wgl_context : NULL,
attribs);
return hglrc;
}
static HGLRC
create_wgl_context (HDC hdc,
GdkGLContext *share,
int flags,
int major,
int minor,
gboolean *is_legacy,
gboolean hasWglARBCreateContext)
{
/* We need a legacy context for *all* cases */
HGLRC hglrc_base = wglCreateContext (hdc);
gboolean success = TRUE;
/* 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 ();
/* if we have no wglCreateContextAttribsARB(), return the legacy context when all is set */
if (*is_legacy && !hasWglARBCreateContext)
{
if (ensure_legacy_wgl_context (hdc, hglrc_base, share))
{
wglMakeCurrent (hdc_current, hglrc_current);
return hglrc_base;
}
success = FALSE;
goto gl_fail;
}
else
{
HGLRC hglrc = NULL;
if (!wglMakeCurrent (hdc, hglrc_base))
{
success = FALSE;
goto gl_fail;
}
/*
* We need a Core GL 4.1 context in order to use the GL support in
* the GStreamer media widget backend, but wglCreateContextAttribsARB()
* may only give us the GL context version that we ask for here, and
* nothing more. So, if we are asking for a pre-GL 4.1 context,
* try to ask for a 4.1 context explicitly first. If that is not supported,
* then we fall back to whatever version that we were asking for (or, even a
* legacy context if that fails), at a price of not able to have GL support
* for the media GStreamer backend.
*/
if (major < 4 || (major == 4 && minor < 1))
hglrc = create_wgl_context_with_attribs (hdc,
hglrc_base,
share,
flags,
4,
1,
is_legacy);
if (hglrc == NULL)
hglrc = create_wgl_context_with_attribs (hdc,
hglrc_base,
share,
flags,
major,
minor,
is_legacy);
/* return the legacy context we have if it could be setup properly, in case the 3.0+ context creation failed */
if (hglrc == NULL)
{
if (!(*is_legacy))
{
/* If we aren't using a legacy context in the beginning, try again with a compatibility profile 3.0 context */
hglrc = create_wgl_context_with_attribs (hdc,
hglrc_base,
share,
flags,
0, 0,
is_legacy);
*is_legacy = TRUE;
}
if (hglrc == NULL)
{
if (!ensure_legacy_wgl_context (hdc, hglrc_base, share))
success = FALSE;
}
if (success)
GDK_NOTE (OPENGL, g_print ("Using legacy context as fallback\n"));
}
gl_fail:
if (!success)
{
wglMakeCurrent (NULL, NULL);
wglDeleteContext (hglrc_base);
return NULL;
}
wglMakeCurrent (hdc_current, hglrc_current);
if (hglrc != NULL)
{
wglDeleteContext (hglrc_base);
return hglrc;
}
return hglrc_base;
}
}
static gboolean
set_wgl_pixformat_for_hdc (HDC hdc,
int *best_idx,
GdkWin32Display *display_win32)
{
gboolean already_checked = TRUE;
*best_idx = GetPixelFormat (hdc);
/* one is only allowed to call SetPixelFormat(), and so ChoosePixelFormat()
* one single time per window HDC
*/
if (*best_idx == 0)
{
PIXELFORMATDESCRIPTOR pfd;
gboolean set_pixel_format_result = FALSE;
GDK_NOTE (OPENGL, g_print ("requesting pixel format...\n"));
already_checked = FALSE;
*best_idx = get_wgl_pfd (hdc, &pfd, display_win32);
if (*best_idx != 0)
set_pixel_format_result = SetPixelFormat (hdc, *best_idx, &pfd);
/* ChoosePixelFormat() or SetPixelFormat() failed, bail out */
if (*best_idx == 0 || !set_pixel_format_result)
return FALSE;
}
GDK_NOTE (OPENGL, g_print ("%s""requested and set pixel format: %d\n", already_checked ? "already " : "", *best_idx));
return TRUE;
}
static gboolean
gdk_win32_gl_context_wgl_realize (GdkGLContext *context,
GError **error)
{
GdkWin32GLContextWGL *context_wgl = GDK_WIN32_GL_CONTEXT_WGL (context);
gboolean debug_bit, compat_bit, legacy_bit;
/* request flags and specific versions for core (3.2+) WGL context */
int flags = 0;
int major = 0;
int minor = 0;
HGLRC hglrc;
int pixel_format;
HDC hdc;
HWND hwnd;
GdkSurface *surface = gdk_gl_context_get_surface (context);
GdkDisplay *display = gdk_gl_context_get_display (context);
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
GdkGLContext *share = gdk_display_get_gl_context (display);
gdk_gl_context_get_required_version (context, &major, &minor);
debug_bit = gdk_gl_context_get_debug_enabled (context);
compat_bit = gdk_gl_context_get_forward_compatible (context);
if (surface != NULL)
hdc = GDK_WIN32_SURFACE (surface)->hdc;
else
hdc = display_win32->dummy_context_wgl.hdc;
/*
* A legacy context cannot be shared with core profile ones, so this means we
* must stick to a legacy context if the shared context is a legacy context
*/
legacy_bit = GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY) ?
TRUE :
share != NULL && gdk_gl_context_is_legacy (share);
if (!set_wgl_pixformat_for_hdc (hdc,
&pixel_format,
display_win32))
{
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
_("No available configurations for the given pixel format"));
return FALSE;
}
/* if there isn't wglCreateContextAttribsARB() on WGL, use a legacy context */
if (!legacy_bit)
legacy_bit = !display_win32->hasWglARBCreateContext;
if (debug_bit)
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
if (compat_bit)
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
GDK_NOTE (OPENGL,
g_print ("Creating %s WGL context (version:%d.%d, debug:%s, forward:%s, legacy: %s)\n",
compat_bit ? "core" : "compat",
major,
minor,
debug_bit ? "yes" : "no",
compat_bit ? "yes" : "no",
legacy_bit ? "yes" : "no"));
hglrc = create_wgl_context (hdc,
share,
flags,
major,
minor,
&legacy_bit,
display_win32->hasWglARBCreateContext);
if (hglrc == NULL)
{
g_set_error_literal (error, GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("Unable to create a GL context"));
return FALSE;
}
GDK_NOTE (OPENGL,
g_print ("Created WGL context[%p], pixel_format=%d\n",
hglrc,
pixel_format));
context_wgl->wgl_context = hglrc;
/* No GLES, WGL does not support using EGL contexts */
gdk_gl_context_set_use_es (context, FALSE);
/* Ensure that any other context is created with a legacy bit set */
gdk_gl_context_set_is_legacy (context, legacy_bit);
return TRUE;
}
static gboolean
gdk_win32_gl_context_wgl_clear_current (GdkGLContext *context)
{
return wglMakeCurrent (NULL, NULL);
}
static gboolean
gdk_win32_gl_context_wgl_make_current (GdkGLContext *context,
gboolean surfaceless)
{
GdkWin32GLContextWGL *context_wgl = GDK_WIN32_GL_CONTEXT_WGL (context);
GdkDisplay *display = gdk_gl_context_get_display (context);
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
GdkSurface *surface = gdk_gl_context_get_surface (context);
HDC hdc;
if (surfaceless || surface == NULL)
hdc = display_win32->dummy_context_wgl.hdc;
else
hdc = GDK_WIN32_SURFACE (surface)->hdc;
if (!wglMakeCurrent (hdc, context_wgl->wgl_context))
return FALSE;
if (!surfaceless && display_win32->hasWglEXTSwapControl)
{
gboolean do_frame_sync = FALSE;
/* If there is compositing there is no particular need to delay
* the swap when drawing on the offscreen, rendering to the screen
* happens later anyway, and its up to the compositor to sync that
* to the vblank. */
do_frame_sync = ! gdk_display_is_composited (display);
if (do_frame_sync != context_wgl->do_frame_sync)
{
context_wgl->do_frame_sync = do_frame_sync;
wglSwapIntervalEXT (do_frame_sync ? 1 : 0);
}
}
return TRUE;
}
static void
gdk_win32_gl_context_wgl_class_init (GdkWin32GLContextWGLClass *klass)
{
GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
context_class->realize = gdk_win32_gl_context_wgl_realize;
context_class->make_current = gdk_win32_gl_context_wgl_make_current;
context_class->clear_current = gdk_win32_gl_context_wgl_clear_current;
draw_context_class->begin_frame = gdk_win32_gl_context_wgl_begin_frame;
draw_context_class->end_frame = gdk_win32_gl_context_wgl_end_frame;
gobject_class->dispose = gdk_win32_gl_context_wgl_dispose;
}
static void
gdk_win32_gl_context_wgl_init (GdkWin32GLContextWGL *wgl_context)
{
}
/**
* gdk_win32_display_get_wgl_version:
* @display: a `GdkDisplay`
* @major: (out): return location for the WGL major version
* @minor: (out): return location for the WGL minor version
*
* Retrieves the version of the WGL implementation.
*
* Returns: %TRUE if WGL is available
*/
gboolean
gdk_win32_display_get_wgl_version (GdkDisplay *display,
int *major,
int *minor)
{
GdkWin32Display *display_win32;
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
if (!GDK_IS_WIN32_DISPLAY (display))
return FALSE;
display_win32 = GDK_WIN32_DISPLAY (display);
if (display_win32->wgl_pixel_format == 0)
return FALSE;
if (major != NULL)
*major = display_win32->gl_version / 10;
if (minor != NULL)
*minor = display_win32->gl_version % 10;
return TRUE;
}

File diff suppressed because it is too large Load Diff

View File

@@ -35,24 +35,13 @@
G_BEGIN_DECLS
#define GDK_WIN32_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WIN32_GL_CONTEXT, GdkWin32GLContextClass))
#define GDK_WIN32_GL_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WIN32_GL_CONTEXT, GdkWin32GLContextClass))
#define GDK_WIN32_IS_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WIN32_GL_CONTEXT))
struct _GdkWin32GLContext
{
GdkGLContext parent_instance;
/* WGL Context Items */
HGLRC hglrc;
HDC gl_hdc;
guint need_alpha_bits : 1;
/* other items */
guint is_attached : 1;
guint do_frame_sync : 1;
#ifdef GDK_WIN32_ENABLE_EGL
/* EGL (Angle) Context Items */
EGLContext egl_context;
EGLConfig egl_config;
#endif
};
struct _GdkWin32GLContextClass
@@ -60,15 +49,33 @@ struct _GdkWin32GLContextClass
GdkGLContextClass parent_class;
};
GdkGLContext *
_gdk_win32_surface_create_gl_context (GdkSurface *window,
gboolean attached,
GdkGLContext *share,
GError **error);
/* WGL */
#define GDK_TYPE_WIN32_GL_CONTEXT_WGL (gdk_win32_gl_context_wgl_get_type())
#define GDK_WIN32_GL_CONTEXT_WGL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_WIN32_GL_CONTEXT_WGL, GdkWin32GLContextWGL))
#define GDK_IS_WIN32_GL_CONTEXT_WGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_WIN32_GL_CONTEXT_WGL))
typedef struct _GdkWin32GLContextWGL GdkWin32GLContextWGL;
gboolean gdk_win32_display_init_wgl (GdkDisplay *display,
GError **error);
void gdk_win32_gl_context_wgl_bind_surface (GdkWin32GLContextWGL *ctx,
GdkWin32Surface *win32_surface);
GType gdk_win32_gl_context_wgl_get_type (void) G_GNUC_CONST;
/* EGL */
#define GDK_TYPE_WIN32_GL_CONTEXT_EGL (gdk_win32_gl_context_egl_get_type())
#define GDK_WIN32_GL_CONTEXT_EGL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_WIN32_GL_CONTEXT_EGL, GdkWin32GLContextEGL))
#define GDK_IS_WIN32_GL_CONTEXT_EGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_WIN32_GL_CONTEXT_EGL))
typedef struct _GdkWin32GLContextEGL GdkWin32GLContextEGL;
gboolean gdk_win32_display_init_egl (GdkDisplay *display,
GError **error);
void gdk_win32_surface_destroy_egl_surface (GdkWin32Surface *self);
GType gdk_win32_gl_context_egl_get_type (void) G_GNUC_CONST;
gboolean
_gdk_win32_display_make_gl_context_current (GdkDisplay *display,
GdkGLContext *context);
void
_gdk_win32_surface_invalidate_egl_framebuffer (GdkSurface *surface);

View File

@@ -694,6 +694,7 @@ update_keymap (GdkKeymap *gdk_keymap)
if (hkls_len != keymap->layout_handles->len)
keymap->keysym_tab = g_renew (guint, keymap->keysym_tab, keysym_tab_size);
memset (key_state, 0, sizeof(key_state));
memset (keymap->keysym_tab, 0, keysym_tab_size);
g_array_set_size (keymap->layout_handles, hkls_len);
g_array_set_size (keymap->options, hkls_len);

View File

@@ -681,7 +681,7 @@ enum_monitor (HMONITOR hmonitor,
else
{
/* First acquire the scale using the current screen */
scale = _gdk_win32_display_get_monitor_scale_factor (data->display, NULL, NULL, NULL);
scale = gdk_win32_display_get_monitor_scale_factor (data->display, NULL, NULL);
/* acquire the scale using the monitor which the window is nearest on Windows 8.1+ */
if (data->display->have_at_least_win81)
@@ -695,7 +695,7 @@ enum_monitor (HMONITOR hmonitor,
pt.x = w32mon->work_rect.x + w32mon->work_rect.width / 2;
pt.y = w32mon->work_rect.y + w32mon->work_rect.height / 2;
hmonitor = MonitorFromPoint (pt, MONITOR_DEFAULTTONEAREST);
scale = _gdk_win32_display_get_monitor_scale_factor (data->display, hmonitor, NULL, NULL);
scale = gdk_win32_display_get_monitor_scale_factor (data->display, NULL, hmonitor);
}
}

View File

@@ -78,8 +78,7 @@ init_root_window (GdkWin32Screen *screen_win32)
win32_display = GDK_WIN32_DISPLAY (_gdk_display);
if (win32_display->dpi_aware_type != PROCESS_DPI_UNAWARE)
screen_win32->surface_scale = _gdk_win32_display_get_monitor_scale_factor (win32_display,
NULL,
screen_win32->surface_scale = gdk_win32_display_get_monitor_scale_factor (win32_display,
NULL,
NULL);
else

View File

@@ -352,12 +352,14 @@ RegisterGdkClass (GdkSurfaceType wtype)
{
char sLoc [MAX_PATH+1];
if (0 != GetModuleFileName (_gdk_dll_hinstance, sLoc, MAX_PATH))
// try to load first icon of executable program
if (0 != GetModuleFileName (NULL, sLoc, MAX_PATH))
{
ExtractIconEx (sLoc, 0, &hAppIcon, &hAppIconSm, 1);
if (0 == hAppIcon && 0 == hAppIconSm)
{
// fallback : load icon from GTK DLL
if (0 != GetModuleFileName (_gdk_dll_hinstance, sLoc, MAX_PATH))
{
ExtractIconEx (sLoc, 0, &hAppIcon, &hAppIconSm, 1);
@@ -395,12 +397,13 @@ RegisterGdkClass (GdkSurfaceType wtype)
wcl.hbrBackground = NULL; \
wcl.hCursor = LoadCursor (NULL, IDC_ARROW);
/* MSDN: CS_OWNDC is needed for OpenGL contexts */
wcl.style |= CS_OWNDC;
switch (wtype)
{
case GDK_SURFACE_TOPLEVEL:
case GDK_SURFACE_POPUP:
/* MSDN: CS_OWNDC is needed for OpenGL contexts */
wcl.style |= CS_OWNDC;
if (0 == klassTOPLEVEL)
{
wcl.lpszClassName = L"gdkSurfaceToplevel";
@@ -519,7 +522,7 @@ _gdk_win32_display_create_surface (GdkDisplay *display,
surface->width = width;
surface->height = height;
impl->surface_scale = _gdk_win32_display_get_monitor_scale_factor (display_win32, NULL, NULL, NULL);
impl->surface_scale = gdk_win32_display_get_monitor_scale_factor (display_win32, NULL, NULL);
dwExStyle = 0;
owner = NULL;
@@ -652,6 +655,7 @@ _gdk_win32_display_create_surface (GdkDisplay *display,
impl);
g_object_unref (frame_clock);
impl->hdc = GetDC (impl->handle);
return surface;
}
@@ -1227,6 +1231,7 @@ gdk_win32_surface_layout_popup (GdkSurface *surface,
&shadow_right,
&shadow_top,
&shadow_bottom);
gdk_win32_surface_set_shadow_width (surface,
shadow_left,
shadow_right,
@@ -1236,10 +1241,10 @@ gdk_win32_surface_layout_popup (GdkSurface *surface,
gdk_surface_layout_popup_helper (surface,
width,
height,
impl->shadow.left,
impl->shadow.right,
impl->shadow.top,
impl->shadow.bottom,
shadow_left,
shadow_right,
shadow_top,
shadow_bottom,
monitor,
&bounds,
layout,
@@ -1259,9 +1264,7 @@ gdk_win32_surface_layout_popup (GdkSurface *surface,
final_rect.height);
}
else
{
gdk_win32_surface_move (surface, x, y);
}
gdk_win32_surface_move (surface, x, y);
}
static void
@@ -4415,9 +4418,9 @@ gdk_win32_surface_set_shadow_width (GdkSurface *window,
if (impl->zero_shadow)
return;
impl->shadow.left = left;
impl->shadow.left = left * impl->surface_scale;;
impl->shadow.right = right * impl->surface_scale;
impl->shadow.top = top;
impl->shadow.top = top * impl->surface_scale;;
impl->shadow.bottom = bottom * impl->surface_scale;
impl->shadow_x = left + right;
impl->shadow_y = top + bottom;
@@ -4425,19 +4428,19 @@ gdk_win32_surface_set_shadow_width (GdkSurface *window,
int
_gdk_win32_surface_get_scale_factor (GdkSurface *window)
_gdk_win32_surface_get_scale_factor (GdkSurface *surface)
{
GdkDisplay *display;
GdkWin32Surface *impl;
GdkWin32Display *win32_display;
if (GDK_SURFACE_DESTROYED (window))
if (GDK_SURFACE_DESTROYED (surface))
return 1;
g_return_val_if_fail (window != NULL, 1);
g_return_val_if_fail (surface != NULL, 1);
display = gdk_surface_get_display (window);
impl = GDK_WIN32_SURFACE (window);
display = gdk_surface_get_display (surface);
impl = GDK_WIN32_SURFACE (surface);
win32_display = GDK_WIN32_DISPLAY (display);
@@ -4446,9 +4449,8 @@ _gdk_win32_surface_get_scale_factor (GdkSurface *window)
if (win32_display->has_fixed_scale)
impl->surface_scale = win32_display->surface_scale;
else
impl->surface_scale = _gdk_win32_display_get_monitor_scale_factor (win32_display,
NULL,
GDK_SURFACE_HWND (window),
impl->surface_scale = gdk_win32_display_get_monitor_scale_factor (win32_display,
surface,
NULL);
return impl->surface_scale;
@@ -4553,7 +4555,7 @@ _gdk_win32_surface_request_layout (GdkSurface *surface)
int scale = impl->surface_scale;
RECT rect;
if (GDK_IS_TOPLEVEL (surface) && impl->drag_move_resize_context.native_move_resize_pending)
if (impl->drag_move_resize_context.native_move_resize_pending)
{
surface->width = impl->next_layout.configured_width;
surface->height = impl->next_layout.configured_height;
@@ -4564,8 +4566,18 @@ _gdk_win32_surface_request_layout (GdkSurface *surface)
impl->next_layout.configured_width = (rect.right - rect.left + scale - 1) / scale;
impl->next_layout.configured_height = (rect.bottom - rect.top + scale - 1) / scale;
surface->x = rect.left / scale;
surface->y = rect.top / scale;
if (GDK_IS_TOPLEVEL (surface))
{
surface->x = rect.left / scale;
surface->y = rect.top / scale;
}
else if (GDK_IS_POPUP (surface))
{
gdk_win32_surface_get_geometry (surface,
&surface->x, &surface->y,
NULL, NULL);
}
}
}
@@ -4612,7 +4624,6 @@ gdk_win32_surface_class_init (GdkWin32SurfaceClass *klass)
impl_class->destroy_notify = gdk_win32_surface_destroy_notify;
impl_class->drag_begin = _gdk_win32_surface_drag_begin;
impl_class->create_gl_context = _gdk_win32_surface_create_gl_context;
impl_class->get_scale_factor = _gdk_win32_surface_get_scale_factor;
impl_class->request_layout = _gdk_win32_surface_request_layout;
impl_class->compute_size = _gdk_win32_surface_compute_size;
@@ -4655,9 +4666,9 @@ gdk_win32_popup_init (GdkWin32Popup *popup)
static void
gdk_win32_popup_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdkSurface *surface = GDK_SURFACE (object);
@@ -4679,9 +4690,9 @@ gdk_win32_popup_get_property (GObject *object,
static void
gdk_win32_popup_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GdkSurface *surface = GDK_SURFACE (object);
@@ -4716,9 +4727,9 @@ gdk_win32_popup_class_init (GdkWin32PopupClass *class)
static gboolean
gdk_win32_popup_present (GdkPopup *popup,
int width,
int height,
GdkPopupLayout *layout)
int width,
int height,
GdkPopupLayout *layout)
{
return gdk_win32_surface_present_popup (GDK_SURFACE (popup), width, height, layout);
}
@@ -5034,9 +5045,9 @@ gdk_win32_drag_surface_iface_init (GdkDragSurfaceInterface *iface)
#ifdef GDK_WIN32_ENABLE_EGL
EGLSurface
_gdk_win32_surface_get_egl_surface (GdkSurface *surface,
EGLConfig config,
gboolean is_dummy)
gdk_win32_surface_get_egl_surface (GdkSurface *surface,
EGLConfig config,
gboolean is_dummy)
{
GdkWin32Display *display = GDK_WIN32_DISPLAY (gdk_surface_get_display (surface));
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
@@ -5055,7 +5066,10 @@ _gdk_win32_surface_get_egl_surface (GdkSurface *surface,
else
{
if (impl->egl_surface == EGL_NO_SURFACE)
impl->egl_surface = eglCreateWindowSurface (display->egl_disp, config, display->gl_hwnd, NULL);
impl->egl_surface = eglCreateWindowSurface (display->egl_disp,
config,
GDK_SURFACE_HWND (surface),
NULL);
return impl->egl_surface;
}
@@ -5138,3 +5152,20 @@ gdk_win32_surface_handle_queued_move_resize (GdkDrawContext *draw_context)
return queued_window_rect;
}
void
_gdk_win32_surface_invalidate_egl_framebuffer (GdkSurface *surface)
{
/* If we are using ANGLE, we need to force redraw of the whole Window and its child windows
* as we need to re-acquire the EGL surfaces that we rendered to upload to Cairo explicitly,
* using gdk_window_invalidate_rect (), when we maximize or restore or use aerosnap
*/
#ifdef GDK_WIN32_ENABLE_EGL
if (surface->gl_paint_context != NULL && gdk_gl_context_get_use_es (surface->gl_paint_context))
{
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
impl->egl_force_redraw_all = TRUE;
}
#endif
}

View File

@@ -379,9 +379,9 @@ RECT
gdk_win32_surface_handle_queued_move_resize (GdkDrawContext *draw_context);
#ifdef GDK_WIN32_ENABLE_EGL
EGLSurface _gdk_win32_surface_get_egl_surface (GdkSurface *surface,
EGLConfig config,
gboolean is_dummy);
EGLSurface gdk_win32_surface_get_egl_surface (GdkSurface *surface,
EGLConfig config,
gboolean is_dummy);
#endif
G_END_DECLS

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