* 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.
When asked for a nonexistent (positive) monitor number,
gdk_x11_display_get_monitor would (at best) return an uninitialized pointer,
instead of returning NULL.
That way, we can store the right region there: The actual painted area
instead of the exposed area (which is way too small).
Also, the GL context is the only user of this data, so storing it there
seems way smarter.
This error message is printed into the journal if a GTK app can't
connect to eithre Wayland or X11. Make it at least mention who is not
capable of connecting to a server.
Unrelated, we might want to improve our error reporting when a GTK app
can't start, so that debugging issues with system startup / login get
easier to resolve.
Instead of calling gdk_surface_invalidate_region(), just
gdk_surface_queue_expose() and rely on the renderer computing the diff
from the previous rendering.
This ensures that the frame clock gets updated with correct presentation
times even if nothing was drawn.
This is necessary for benchmarking but would also be relevant for videos
that want to sync to the frame clock but draw frames a lot less.
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
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
With the previous approach we would spend most of the time waiting for
the swapchain to be filled again because it seems the compositor takes
care of 2 images at once from time to time.
This is not visible in profiles because waiting for a frame is a
read/poll/whatever operation that does not take CPU. It's only
noticeable because the app becomes less responsive.
If G_ENABLE_CONSISTENCY_CHECKS is defined (i.e. if our buildtype is
'debug'), add a opengl debug callback that prints all debug messages
with a severity higher than SEVERITY_NOTIFICATION as a warning to the
console.
Set the display for each event that we put.
Also reorganize the dnd_event_put() function a bit, giving it a surface
directly instead of setting it by implication.
https://bugzilla.gnome.org/show_bug.cgi?id=773299
dest_surface is going to always be NULL for source contexts.
Previously we used to put the root window there to pass this check,
but root windows are gone (and root surfaces never existed to begin
with), so we have to adapt.
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