Replace the gdk_surface_move_to_rect() API with a new GdkSurface
method called gdk_surface_present_popup() taking a new GdkPopupLayout
object describing how they should be laid out on screen.
The layout properties provided are the same as the ones used with
gdk_surface_move_to_rect(), except they are now set up using
GdkPopupLayout.
Calling gdk_surface_present_popup() will either show the popup at the
position described using the popup layout object and a new unconstrained
size, or reposition it accordingly.
In some situations, such as when a popup is set to autohide, presenting
may immediately fail, in case the grab was not granted by the display
server.
After a successful present, the result of the layout can be queried
using the following methods:
* gdk_surface_get_position() - to get the position relative to its
parent
* gdk_surface_get_width() - to get the current width
* gdk_surface_get_height() - to get the current height
* gdk_surface_get_rect_anchor() - to get the anchor point on the anchor
rectangle the popup was effectively positioned against given
constraints defined by the environment and the layout rules provided
via GdkPopupLayout.
* gdk_surface_get_surface_anchor() - the same as the one above but for
the surface anchor.
A new signal replaces the old "moved-to-rect" one -
"popup-layout-changed". However, it is only intended to be emitted when
the layout changes implicitly by the windowing system, for example if
the monitor resolution changed, or the parent window moved.
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.
We use a compilation symbol in our build to allow the inclusion of
specific headers while building GTK, to avoid the need to include only
the global header.
Each namespace has its own compilation symbol because we used to have
different libraries, and strict symbol visibility between libraries;
now that we have a single library, and we can use private symbols across
namespaces while building GTK, we should have a single compilation
symbol, and simplify the build rules.
The "iconified" state is mostly an X11-ism; every other platform calls
this state "minimized" because it may not involve turning a window into
an icon at all.
Windows/surface's aren't supposed to be explicitly moved by any external
part, so don't provide API for doing so. Usage throughout Gdk is
replaced by the corresponding backend variants.
The generic layer still does the heavy lifting, leaving the backends
more or less just act as thin wrappers, dealing a bit with global
coordinate transformations. The end goal is to remove explicit surface
moving from the generic gdk layer.
To separate how toplevels and popups are configured, a first step is to
introduce a resize-only vfunc for backends to implement. It's meant to
only configure toplevel windows, i.e. popups. Currently it's used for
both types, but introducing the resize-only API is a first step.
1) In the SetWindowPos() function (and the WINDOWPOS struct) the
"hWndInsertAfter" argument/field means the window that will be
directly above after the change, not the window that will be
directly below. MSDN says "precedes" for SetWindowPos(), but
WINDOWPOS documentation is more precise: this is the window
behind which the affected window will be placed. Apparently,
Z-axis goes back-to-front.
Therefore, logging should be reworded correctly.
2) When we switch away from the application and then switch back
to a transient window, we need to bring up its transient-owner
(and its transient-owner's owner and so forth) as well,
otherwise our transient (modal) window might be transient for
something that might not be visible.
3) When we bring up a window, we should bring all of its children
(popup windows) on top of it.
Because Windows doesn't provide a function to bring one window
on top of the other, we have to work around this by calling
SetWindowPos() twice, swapping the windows between the calls.
GTK4 doesn't have WS_CHILD windows anymore, so hWndParent argument
to CreateWindowEx() is always interpreted as the owner window,
not the parent window.
A window with an owner:
* is above the owner in Z-order
* is destroyed when the owner is destroyed
* is hidden when the owner is minimized
This is enforced by the OS.
GTK can only allow this for popup windows.
Desktop window must never[0] be an owner.
[0]: https://devblogs.microsoft.com/oldnewthing/20040224-00/?p=40493
Popups can't be active or inactive, so emitting GDK events
in response to WM_ACTIVATE makes no sense for these kinds
of GDK surfaces.
The jury is still out on whether we should block (return 0)
or ignore (don't return anything) this message.
Blocking WM_NCACTIVATE (which we currently ignore) is definitely
not an option - it completely breaks input somehow.
1) Handle GDK_SURFACE_POPUP in RegisterGdkClass()
(for now pretend it's the same as GDK_SURFACE_TOPLEVEL)
2) Remove useless code from GDK_SURFACE_TOPLEVEL case in _gdk_win32_display_create_surface()
(now there's just GDK_SURFACE_TOPLEVEL there, no need for a type check)
3) Have a separate case for GDK_SURFACE_POPUP and ensure that
it doesn't get WS_CHILDWINDOW (and neither should GDK_SURFACE_TEMP).
Somewhat change the order of initialization (to be closer
to what Wayland backend does).
Also remove the wrapper field that is no longer needed -
it used to hold a pointer to the main GdkWindow instance,
which wrapped GdkWin32ImplWindow. Since impls are gone,
nothing is wrapping anything anymore.
Fix a substitution error, where wrong pointer was added
to the hash table. Added a comment to ensure that future readers
(including myself) won't be confused by the fact that we're
inserting a pointer instead of the handle itself.
We want to use a gdk_surface_new_popup for popups,
and align the constructor names with the surface
types, so rename
gdk_surface_new_popup -> gdk_surface_new_temp
gdk_surface_new_popup_full -> gdk_surface_new_popup
The temp surface type will disappear eventually.
All the information in it is already contained
in the surface object we pass along, and none
of the backend implementations were using the
attributes at all.
We are not creating such surfaces anymore, and
they were only ever meaningfully implemented
on X11. Drop the concept, and the api for determining
if a surface is input-only.
The skip-taskbar, skip-pager and urgency hints were
only ever implemented for X11, and are not very useful
with modern desktops. Relegate the functionality to
x11 backend api, and drop the GtkWindow api.
We preiously did not apply the resizes and moves as they were previously
only done in the Cairo drawing context on Win32. Fix this by applying
this too in the GL drawing context.
Make gdk_win32_surface_get_queued_window_rect() and
gdk_win32_surface_apply_queued_move_resize() not static functions, as we
want to use them in gdkglcontext-win32.c, to fix resizing and moving.
As in commit d45996c, the x and y coordinates passed into begin_drag and
begin_move are no longer root coordinates but are now surface
coordinates.
Use the x and y surface coordinates to acquire the root x and y
coordinates so that resizing and moving can work as expected.
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.
This makes apps use "Segoe UI 9" by default instead of whatever matches "Sans 10".
It also cleans up the code and uses some new pango API while at it.
This was previously disabled in 9e686d1fb5 because it led to a poor glyph coverage
on certain versions of Windows which don't default to "Segoe UI 9" (Chinese, Korean, ..)
because the font fallback list was missing in pango.
This is about to get fixed in https://gitlab.gnome.org/GNOME/pango/merge_requests/34
so enable it again when we detect a new enough pango version.
(See !436 for the original MR)
GTK widgets expect the scroll deltas to be 1 or -1 and calculate a scroll value from that.
Multiplying the delta by the Windows scroll line setting (which defaults to 3) results
in a much larger delta and vastly different behaviour for running a GTK app on Windows
vs on Linux. For example text view and tree view scroll by 9 lines per scroll wheel tick
per default this way while on Linux it is around 3.
Remove the multiplication for now.
See !426 for the gtk3 MR
Enables hinting, antialiasing and set the subpixel orientation according to the
active clear type setting. This ensures that font rendering with the fontconfig backend
looks similar to the win32 backend, at least with the default system font.
See !437
Do not lie to W32 about the formats that we provide or accept.
Originally the logic behind such lies was that GdkPixbuf allows us to
convert any supported image to BMP or PNG, and therefore we should
announce that we always provide/accept BMP and PNG along with other
formats.
But that's not how it works. GDK has built-in serializers and
deserializers for all pixbuf formats (where it just invokes GdkPixbuf
API) and will use them automatically to read or write GdkTexture
objects (internally wrapping GdkPixbuf objects where necessary). The
encoding and decoding of images is handled
by GdkContent(De)Serializers, backend has nothing to do with it.
Therefore W32 GDK backend should only offer formats that it can
actually do conversion for by itself (such as image/bmp <-> CF_DIB,
or text/uri-list <-> CFSTR_SHELLIDLIST).
This leverages the normal input context switching mechanism in GTK
by making it think that the gtk-im-module setting changed.
The backend returns gtk-im-module value as "ime" if W32
IME API says that an IME is in use. Otherwise it returns
and empty string - this still triggers an input context
switching code, which, not being able to create the desired context
(which is and empty string), falls back to looking at current
keyboard layout (currently that code is still a FIXME).
Paired with the code that signals gtk-im-module change on keyboard layout
switches, this is sufficient to make GTK capable of switching to
the appropriate IM context at runtime. At least, the kinds of context
that specify languages for which they are used automatically by default
(once locale matching is implemented), and the IME context.
Loading other kinds of IM context might still work via specifying
the gtk-im-module setting in gtk ini file, but doing so will likely
make GTK incapable of using the IME context that is used
for Korean, Chinese and Japanese (and some other languages).
Until someone figures out a way to actually change gtk-im-module
setting on Windows at runtime with meaningful values, the behaviour
introduced by this commit seems like a sufficient workaround.
Commit 359df028be changed the
code to send GDK_SCROLL_SMOOTH with deltas instead of
GDK_SCROLL_(UP|DOWN|LEFT|RIGHT).
Windows defines deltas inversed for vertical direction
(positive values mean the wheel was turned forward)
but not for horizontal direction
(positive values mean the wheel was turned towards the right).
This commit fixes behavior as both axes were inverted previously.
Commit d64467b334 changed the
code to send GDK_SCROLL_SMOOTH with deltas instead of
GDK_SCROLL_(UP|DOWN|LEFT|RIGHT). Change it again, to send
both the GDK_SCROLL_SMOOTH and the GDK_SCROLL_(UP|DOWN|LEFT|RIGHT)
event separately (with the discrete event marked as emulated),
as this is what other backends (such as wayland) do.
Set delta_x or delta_y for GdkScrollEvent.
HIWORD (wParam) in WM_MOUSE(H)WHEEL is the scroll delta.
A delta value of WHEEL_DELTA (which is 120) means scrolling
one full unit of something (for example, a line).
The delta should also be multiplied by the value that the
SystemParametersInfo (SPI_GETWHEELSCROLL(LINES|CHARS), 0, &value, 0)
call gives back, unless it gives back 0xffffffff, in which case
it indicates that scrolling is page- or screen-based, not line-based
(GDK doesn't support that at the moment).
Also, all deltas should be inverted, since MS sends negative deltas
when scrolling down (rotating the wheel back, in the direction of
the user).
With deltas set the mode should be set to GDK_SCROLL_SMOOTH.
Fixes issue 1263.
Change GdkDrag::action to GdkDrag::selected-action, which is
more clearly different from actions, and follows the existing
name of the struct field and getter.
This lets us drop the ::action-changed signal for the
property change notification. But, can just as well move
the signal class handers which just update the cursor
to the ::action setter. No need to do this in the backends.
* There's no GdkDragContext->dest_surface anymore.
Add dest_window field to GdkWin32DragContext,
and use that instead.
* Remove unused function prototypes
* Add more comments
* Rename variables and fields from 'window' to 'surface'
where appropriate
* Fix header indentation a bit
* Try to ensure that uninitialized/unknown handle variables
and fields are set to INVALID_HANDLE_VALUE instead of NULL,
as there may be cases where NULL is a valid handle value.
In particular, this patch removes:
gdk_surface_get_events()
gdk_surface_set_events()
gdk_surface_get_device_events()
gdk_surface_set_device_events()
Event masks so far still exist for grabs.
* Remove clipdrop->dnd_target_state, it's not used anymore
* Remove non-functioning _gdk_dropfiles_store(), store dropfiles
list in GdkWin32Drop instead
* Fix multiple comment typos
* Fix _gdk_win32_get_clipboard_format_name_as_interned_mimetype() to
leave names that look like mime/types alone
* Refactor _gdk_win32_add_w32format_to_pairs() to populate
GdkContentFormatsBuilder directly, instead of making a GList
* Rename context -> drag (still using GdkDragContext type,
but [almost?] all variables and comments say "drag" now)
* Rename GdkDropContext -> GdkDrop
* Rename some parameter names for clarity
* Rewrite local protocol to look more like OLE2 protocol
instead of mirroring the structure of the X11 API.
* Add handle_events field to GdkWin32DragContext,
to shut off event handling (temporary fix until GTK is patched up)
* Remove _gdk_win32_drag_context_find() - the drag object is stored
in GdkDrop instead. Use _gdk_win32_find_drag_for_dest_surface()
to get it initially.
* Remove target_ctx_for_window, droptarget context is stored
in the surface instead.
* Call gdk_drag_context_set_cursor() just like wayland backend does
(slightly broken for now)
* Clean up the action choosing code (filter source actions by using
keyboard state, pass that to GTK, get all actions supported by GTK in
response, match them up with filtered source actions, return the
result, falling back to COPY in case of multiple actions)
* Check drag_win32->protocol instead of the use_ole2_dnd variable where
possible
* Remove protocol checks from functions that are only used by the local
protocol
* Use event state to manufacture the keyboard state for WM_MOUSEMOVE
* Change function names printed by GDK_NOTE to name the actual
functions, not their theoretical generic GDK stack ancestors
* Consistently use drag_win32 and drop_win32 variables instead of a mix
of that and win32_drag/win32_drop
* Return FALSE from button handler to ensure that GTK gets the button
event to break implicit grab
* Emit leave event on failed idroptarget_drop() calls
There is no reason why we shouldn't pass this flag every time
Z-order changes. We have separate routines that are used to
maintain relative Z-order, so it should be completely OK to
pass SWP_NOOWNERZORDER to let the OS know that it shouldn't try
to maintain relative Z-order of the windows when raising them.
Pass SWP_NOOWNERZORDER when rising TEMP surfaces to the top. This ensures that
they don't drag anything else to the top with them. The use-case for this is
a tooltip appearing for a non-foreground surface, causing said surface to rise
above other surfaces, some of which maybe foreground at the moment.
https://bugzilla.gnome.org/show_bug.cgi?id=784766
According to the old new thing[0], we should use the instance handle
of the GDK/GTK DLL when registering GDK-specific types in the system.
Using the instance handle for the whole application in these circumstances
is not an error, but can potentially clash with the types registered
by the application itself.
Also, extract window class icons from the GDK/GTK DLL, not from the
application executable.
[0]: https://blogs.msdn.microsoft.com/oldnewthing/20050418-59/?p=35873
It's quite old, but mostly harmless (both "message == WM_KEYUP"
and "message = WM_KEYUP" evaluate to not-FALSE, and message
value is not used after that line).
* Remove DC refcounting (we trust GDK to always do
begin_frame/end_frame calls in pairs)
* Now that there's no GDK-provided double-buffer up the stack,
double-buffering is implemented here
(though it's disabled by default - in my tests it didn't provide
any visual improvements, but did decrease performance).
* For some reason delaying window resizes until the point where
we need to blit the double-buffer into the window leads
to visual glitches, so doulbe-buffered windows are resized
in begin_frame, same as non-double-buffered ones.
* New code to clear the paint region, for all drawing modes.
Hopefully, it isn't duplicated anywhere up the stack.
* GL has its own context now, so remove any GL-related comments.
* Layered windows are still used (because cairo actually works
better with them)
* A bit more code re-use for layered windows
* Some functions that were local to gdksurface-win32.c are made
usable for the whole backend
* Drag-indicator drawing is temporarily commented out to match
a similar change in X11 backend
We used to pass 2 regions to GdkDrawCotnext.end_frame() but code was
confusing what they meant. So we now don't do that anymore and only pass
the region that matters: The frame region.
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.
* Previous commit had misleading info. The code was
added to begin_paint() instead of end_paint(). Though
that did not affect its performance in any visible way.
* Company advised to move the code to an "after_paint" signal
handler, so that it works on all renderers, not just Cairo.
This change caused high fluctuation in FPS values in fishbowl
when it is put in a situation where it cannot achieve 60fps
(such as using Cairo renderer at ultra-high resolution).
This seems to be deliberate and not a bug.
There is no easily apparent way of being notified when frame updates
happene exactly, so we just query frame info at the end of each paint.
If we query too often (faster than DWM refresh rate), we just get
the same values twice in a row, but that is, hopefully, highly unlikely.
This commit ensures that each GdkSurface impl remembers the
cursor that GDK sets for it, and that this cursor is set
each time WM_SETCURSOR is called for that sufrace's HWND.
This is needed because W32, unlike X, has no per-window cursors -
the cursor on W32 is a global resource, and we need to keep track
of which cursor should be set when pointer is over which surface
ourselves (WM_SETCURSOR exists exactly for this reason).
This commit also makes GDK remember the surface that has an implicit
grab (since implicit grabs are gone from the upper levels of the toolkit),
and ensures that crossing events are correctly synthesized and the grab
is broken when surface focus changes. This fixes a bug where opening
a new window (by clicking something in some other, pre-existing window)
will make that new window not get any mouse input due to the fact
that the mouse-button-down event from that click caused an implicit
grab on the pre-existing window, and that grab was not released afterward.
Instead of now-unused GdkWin32Cursor class (a subclass of GdkCursor),
add a stand-alone GdkWin32HCursor class that is a wrapper around
HCURSOR handle.
On creation it's given a display instance, a HCURSOR handle and a boolean
that indicates whether the HCURSOR handle can or cannot be destroyed
(this depends on how the handle was obtained).
That information is stored in a hash table inside the GdkWin32Display
singleton, each entry of that table has reference count.
When the GdkWin32HCursor object is finalized, it reduces the reference
count on the table entry in the GdkWin32Display. When it's created,
it either adds such an entry or refs an existing one.
This way two pieces of code (or the same piece of code called
multiple times) that independently obtain the same HCURSOR from the OS
will get to different GdkWin32HCursor instances, but GdkWin32Display
will know that both use the same handle.
Once the reference count reaches 0 on the table entry, it is freed
and the handle (if destroyable) is put on the destruction list,
and an idle destruction function is queued.
If the same handle is once again registered for use before the
idle destructior is invoked (this happens, for example, when
an old cursor is destroyed and then replaced with a new one),
the handle gets removed from the destruction list.
The destructor just calls DestroyCursor() on each handle, calling
SetCursor(NULL) before doing that when the handle is in use.
This ensures that SetCursor(NULL) (which will cause cursor to disappear,
which is bad by itself, and which will also cause flickering if the
cursor is set to a non-NULL again shortly afterward)
is almost never called, unless GTK messes up and keeps using a cursor
beyond its lifetime.
This scheme also ensures that non-destructable cursors are not destroyed.
It's also possible to call _gdk_win32_display_hcursor_ref()
and _gdk_win32_display_hcursor_unref() manually instead of creating
GdkWin32HCursor objects, but that is not recommended.
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