The old code used repeated calls to `ToUnicodeEx` to populate
the translation table, which is slow and buggy. The new code
directly loads the layout driver DLLs from Windows.
See https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/4338
Use the debug envvar 'GDK_DEBUG=gl-egl' to determine whether we want to try to
initialize EGL first before trying WGL, as a means for people to more easily
enable EGL support on Windows to test EGL there (such as to debug the shaders,
for instance)
This will port the EGL code in GDK-Win32 to use the common GDK code to
initialize EGL. However, at the current state, although EGL is
correctly initialized, this code is disabled for now since
gdk_gl_context_make_current() fails as the shaders do not work for EGL
via libANGLE on Windows.
We can now clean things up in gdkglcontext-win32-egl.c as a result.
We have a global GdkGLBackendType now, just set it.
This way, using the variable forces the backend type, and we don't need
special code handling the env vars in the backends.
It also means setting the env var will now "work" on GDK backends that
don't even support that GL backend and simualte another GDK backend
having registered that GL backend already. So you can run
GDK_DEBUG=gl-wgl gtk4-demo
on test what Wayland will do when WGL is in use.
On Windows, GLES is not that widely available unless one installs wrapper
libraries such as libANGLE, so GLES/EGL support on Windows is used more like
a fallback mode if Desktop OpenGL (WGL) support is inadequate on the system.
Hence, unless one forces WGL or EGL, we will first try to initialize WGL, and
then try to initialize GLES if enabled and if WGL initialization failed, and
then just return whatever the last result we can obtain from these
initialization attempts, since unlike X11 EGL contexts, we do not have
separate modes for WGL except for legacy and non-legacy contexts.
It is basically not used by default and is pretty much broken at this point, so
it's about time to drop it.
Let's focus on fixing the OLE2 DnD protocol.
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.
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.
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.
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.
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.
This allows us to use DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 for the
DPI awareness mode, which will help us to better support use cases with
multiple monitors. This is actualy a more advaned version of the
current PROCESS_PER_MONITOR_DPI_AWARE via using SetProcessDpiAwareness().
Note that this is not enabled by default, but also enabled via using
GDK_WIN32_PER_MONITOR_HIDPI, as in the PROCESS_PER_MONITOR_DPI_AWARE
case.
Note also, that appliation compatibility settings and DPI-awareness
manifests takes precedence over this API call, as before.
If GLES support is enabled on Windows, force GLES mode if we are running
on a ARM64 version of Windows (i.e. Windows 10 for ARM).
This is required as ARM64 versions of Windows only provide a software
implementation of OpenGL 1.1/1.2, which is not enough for our purposes.
Thus, we could make instead use the GLES support provided via Google's
libANGLE (which emulates OpenGL/ES 3 with Direct3D 9/11), so that we
can run GtkGLArea programs under OpenGL/ES in ARM64 versions of Windows.
Note that eventually we could update the libepoxy build files for Windows
to not check nor enable WGL when building for ARM64 Windows, as the WGL
items do not work, although they do build.
This is for adding a EGL-based renderer which is done via the ANGLE
project, which translate EGL calls to Direct3D 9/11. This is done as a
possible solution to issue #105, especially for cases where the needed
full GL extensions to map OpenGL to Direct3D is unavailable or
unreliable, or when the OpenGL implementation from the graphics drivers
are problematic.
To enable this, do the following:
-Build ANGLE and ensure the ANGLE libEGL.dll and libGLESv2.dll are
available. A sufficiently-recent ANGLE is needed for things to
work correctly--note that the copy of ANGLE that is included in
qtbase-5.10.1 is sufficient. ANGLE is licensed under a BSD 3-clause
license.
-Build libepoxy on Windows with EGL support enabled.
-Currently, prior to running GTK+ programs, the GDK_DEBUG envvar needs
to be set with gl-gles as at least one of the flags.
Known issues:
-Only OpenGL ES 3 is supported, ANGLE's ES 2 does not support the needed
extensions, notably GL_OES_vertex_array_object, but its ES 3 support is
sufficient.
-There is no autodetection or fallback mechanism to enable using
EGL/Angle automatically yet. There are no plans to do this in this
commit.
It's not a portable API, so remove it. The corresponding backend
specific functions are still available, if they were implemented, e.g.
gdk_macos_monitor_get_workarea() and gdk_x11_monitor_get_workarea().
We only have implementations of this on X11 and Win32,
so make it available as backend api there.
Update all callers to use either the backend api, or
just monitor 0.
ImmIsIME() doesn't work (always returns TRUE) since Vista.
Use ITfActiveLanguageProfileNotifySink to detect TSF changes,
which are equal to IME changes for us.
Also make sure that IMMultiContext re-loads the IM when keyboard layout
changes, otherwise there's a subtle bug that could happen:
* Run GTK application with non-IME layout (US, for example)
* Focus on an editable widget (GtkEntry, for example)
* IM Context is initialized to use the simple IM
* Switch to an IME layout (such as Korean)
* Start typing
* Since IME module is not loaded yet, keypresses are handled
by a default MS IME handler
* Once IME commits a character, GDK will get a WM_KEYDOWN,
which will trigger a GdkKeyEvent, which will be handled by
an event filter in IM Context, which will finally re-evaluate
its status and load IME, and only after that GTK will get
to handle IME by itself - but by that point input would
already be broken.
To avoid this we can emit a dummy event (with Void keyval),
which will cause IM Context to load the appropriate module
immediately.
And make the GdkCairoContext as abstract.
The idea of this and thje following commits is to get rid of all
Cairo code in gdksurface.c (and $backend/gdksurface-$backend.c)
by moving that code into the Cairo context files.
In particular, the GdkSurfaceClass.begin_frame/end_frame()
functions (which are currently exclusively used by the Cairo code
should end up being moved to GdkDrawContextClass.begin/end_frame().
This has multiple benefits:
1. It unifies code between the different drawing contexts.
GL lives in GLContext, Vulkan in VulkanContext and Cairo in
CairoContext. In turn, this makes it way easier to reason about
what's going on in surface-specific code. Currently pretty much
all backends do things wrong when they want to sync to drawing
or to the frame clock.
2. It makes the API of GdkSurface smaller. No drawing code (apart
from creating the contexts) needs to remain.
3. It confines Cairo to the Drawcontext, thereby making it way
more obvious when backends are still using it in situations
where it may now conflict with OpenGL (like when doing the dnd
failed animation or in the APIs that I'm removing in this
branch).
4. We have 2 very different types of Cairo contexts: The X/win32
model, where we have a natively supported Cairo backend but do
double buffering ourselves and use similar surfaces and the
Wayland/Broadway model where we use image surfaces without any
Cairo backend support and have to submit the buffers manually.
By not sharing code between those 2 versions, we can make the
actual code way smaller. We also get around the need to create
1x1 image surfaces in the Wayland backend where we pretend
there's a native Cairo surface.
Add a new W32 backend-specific message filtering mechanism.
Works roughly the same way old event filtering did, but without
events (events are GDK/X11 concept that never really made sense
on W32), so there's no functionality for 'altering' events being
emitted. If an event needs to be emitted in response to a message
do it yourself.
Implemented like this, it should give better performance than
if we were to use GLib signals for this, since W32 sends a LOT
of messages (unlike X11, which doesn't send events as often)
all the time, and invoking the signal machinery on *each* message
would probably be bad.
https://bugzilla.gnome.org/show_bug.cgi?id=773299
Rename GdkWin32Selection to GdkWin32Clipdrop, since GdkSelection
is mostly gone, and the word "selection" does not reflect the
functionality of this object too well.
Clipboard is now handled by a separate thread, most of the code for
it now lives in gdkclipdrop-win32.c, gdkclipboard-win32.c just uses
clipdrop as a backend.
The DnD source part is also put into a thread.
The DnD target part does not spin the main loop, it just
emits a GDK event and returns a default value if it doesn't get a reply
by the time the event is processed.
Both clipboard and DnD use a new GOutputStream subclass to get data
from GTK and put it into a HGLOBAL.
GdkWin32DragContext is split into GdkWin32DragContext and GdkWin32DropContext,
anticipating a similar change that slated to happen to GdkDragContext.
OLE2 DnD protocol is now used by default, set GDK_WIN32_OLE2_DND envvar to 0
to make GDK use the old LOCAL and DROPFILES protocols.
https://bugzilla.gnome.org/show_bug.cgi?id=773299
This affects gdk_device_query_state() for the virtual device. It has
no window, and is forced to query the display itself, and display
defaults its scale to 1 even for HiDPI desktops. Use the same
"query scale of a NULL monitor" trick that we use in other places
to get the global desktop scale.
https://bugzilla.gnome.org/show_bug.cgi?id=773299
This is an automatic rename of various things related
to the window->surface rename.
Public symbols changed by this is:
GDK_MODE_WINDOW
gdk_device_get_window_at_position
gdk_device_get_window_at_position_double
gdk_device_get_last_event_window
gdk_display_get_monitor_at_window
gdk_drag_context_get_source_window
gdk_drag_context_get_dest_window
gdk_drag_context_get_drag_window
gdk_draw_context_get_window
gdk_drawing_context_get_window
gdk_gl_context_get_window
gdk_synthesize_window_state
gdk_surface_get_window_type
gdk_x11_display_set_window_scale
gsk_renderer_new_for_window
gsk_renderer_get_window
gtk_text_view_buffer_to_window_coords
gtk_tree_view_convert_widget_to_bin_window_coords
gtk_tree_view_convert_tree_to_bin_window_coords
The commands that generated this are:
git sed -f g "GDK window" "GDK surface"
git sed -f g window_impl surface_impl
(cd gdk; git sed -f g impl_window impl_surface)
git sed -f g WINDOW_IMPL SURFACE_IMPL
git sed -f g GDK_MODE_WINDOW GDK_MODE_SURFACE
git sed -f g gdk_draw_context_get_window gdk_draw_context_get_surface
git sed -f g gdk_drawing_context_get_window gdk_drawing_context_get_surface
git sed -f g gdk_gl_context_get_window gdk_gl_context_get_surface
git sed -f g gsk_renderer_get_window gsk_renderer_get_surface
git sed -f g gsk_renderer_new_for_window gsk_renderer_new_for_surface
(cd gdk; git sed -f g window_type surface_type)
git sed -f g gdk_surface_get_window_type gdk_surface_get_surface_type
git sed -f g window_at_position surface_at_position
git sed -f g event_window event_surface
git sed -f g window_coord surface_coord
git sed -f g window_state surface_state
git sed -f g window_cursor surface_cursor
git sed -f g window_scale surface_scale
git sed -f g window_events surface_events
git sed -f g monitor_at_window monitor_at_surface
git sed -f g window_under_pointer surface_under_pointer
(cd gdk; git sed -f g for_window for_surface)
git sed -f g window_anchor surface_anchor
git sed -f g WINDOW_IS_TOPLEVEL SURFACE_IS_TOPLEVEL
git sed -f g native_window native_surface
git sed -f g source_window source_surface
git sed -f g dest_window dest_surface
git sed -f g drag_window drag_surface
git sed -f g input_window input_surface
git checkout NEWS* po-properties po docs/reference/gtk/migrating-3to4.xml