gtk/gdk/win32/gdkdisplay-win32.h

200 lines
5.8 KiB
C
Raw Normal View History

/*
* gdkdisplay-win32.h
*
* Copyright 2014 Chun-wei Fan <fanc999@yahoo.com.tw>
*
* 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 "gdkdisplayprivate.h"
#pragma once
#include "gdkwin32screen.h"
GDK W32: New cursor class 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.
2018-03-29 23:38:05 +00:00
#include "gdkwin32cursor.h"
#include "gdkglversionprivate.h"
#ifdef HAVE_EGL
# include <epoxy/egl.h>
#endif
/* Define values used to set DPI-awareness */
typedef enum _GdkWin32ProcessDpiAwareness {
PROCESS_DPI_UNAWARE = 0,
PROCESS_SYSTEM_DPI_AWARE = 1,
PROCESS_PER_MONITOR_DPI_AWARE = 2,
PROCESS_PER_MONITOR_DPI_AWARE_V2 = 3, /* Newer HiDPI type for Windows 10 1607+ */
} GdkWin32ProcessDpiAwareness;
/* From https://docs.microsoft.com/en-US/windows/win32/hidpi/dpi-awareness-context */
/* DPI_AWARENESS_CONTEXT is declared by DEFINE_HANDLE */
#ifndef DPI_AWARENESS_CONTEXT_UNAWARE
#define DPI_AWARENESS_CONTEXT_UNAWARE (HANDLE)-1
#endif
#ifndef DPI_AWARENESS_CONTEXT_SYSTEM_AWARE
#define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE (HANDLE)-2
#endif
#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (HANDLE)-4
#endif
typedef enum _GdkWin32MonitorDpiType {
MDT_EFFECTIVE_DPI = 0,
MDT_ANGULAR_DPI = 1,
MDT_RAW_DPI = 2,
MDT_DEFAULT = MDT_EFFECTIVE_DPI
} GdkWin32MonitorDpiType;
/* APIs from shcore.dll */
typedef HRESULT (WINAPI *funcSetProcessDpiAwareness) (GdkWin32ProcessDpiAwareness value);
typedef HRESULT (WINAPI *funcGetProcessDpiAwareness) (HANDLE handle, GdkWin32ProcessDpiAwareness *awareness);
typedef HRESULT (WINAPI *funcGetDpiForMonitor) (HMONITOR monitor,
GdkWin32MonitorDpiType dpi_type,
UINT *dpi_x,
UINT *dpi_y);
typedef struct _GdkWin32ShcoreFuncs
{
HMODULE hshcore;
funcSetProcessDpiAwareness setDpiAwareFunc;
funcGetProcessDpiAwareness getDpiAwareFunc;
funcGetDpiForMonitor getDpiForMonitorFunc;
} GdkWin32ShcoreFuncs;
/* DPI awareness APIs from user32.dll */
typedef BOOL (WINAPI *funcSetProcessDPIAware) (void);
typedef BOOL (WINAPI *funcIsProcessDPIAware) (void);
/*
* funcSPDAC is SetProcessDpiAwarenessContext() and
* funcGTDAC is GetThreadDpiAwarenessContext() and
* funcADACE is AreDpiAwarenessContextsEqual() provided by user32.dll, on
* Windows 10 Creator Edition and later.
* Treat HANDLE as void*, for convenience, since DPI_AWARENESS_CONTEXT is
* declared using DEFINE_HANDLE.
*/
typedef BOOL (WINAPI *funcSPDAC) (void *);
typedef HANDLE (WINAPI *funcGTDAC) (void);
typedef BOOL (WINAPI *funcADACE) (void *, void *);
typedef struct _GdkWin32User32DPIFuncs
{
funcSetProcessDPIAware setDpiAwareFunc;
funcIsProcessDPIAware isDpiAwareFunc;
funcSPDAC setPDAC;
funcGTDAC getTDAC;
funcADACE areDACEqual;
} GdkWin32User32DPIFuncs;
typedef enum {
GDK_WIN32_TABLET_INPUT_API_NONE,
GDK_WIN32_TABLET_INPUT_API_WINTAB,
GDK_WIN32_TABLET_INPUT_API_WINPOINTER
} GdkWin32TabletInputAPI;
typedef struct
{
gdkglcontext-win32-wgl.c: Fix using wglChoosePixelFormatARB() If we are querying the best supported pixel format for our HDC via wglChoosePixelFormatARB() (i.e. we have the WGL_ARB_pixel_format extension), it may return a pixel format that is different from the pixel format that we used for the dummy context that we have setup, in order to, well, run wglChoosePixelFormatARB(), which sadly requires a WGL context (HGLRC) to be current in order to use it, which means the dummy HDC already has a pixel format that has been set (notice that each HDC is only allowed to have its pixel format to be set *once*). This is notably the case on Intel display drivers. Since we are emulating surfaceless GL contexts, we are using the dummy GL context (and thus dummy HDC that is derived from the notification HWND used in GdkWin32Display) for doing that, we would get into trouble if th actual HDC from the GdkWin32Surface has a different pixel format set. So, as a result, in order to fix this situation, we do the following: * Create yet another dummy HWND in order to grab the HDC to query for the capabilities the GL drivers support, and to call wglChoosePixelFormatARB() as appropriate (or ChoosePixelFormat()) for the final pixel format that we use. * Ditch the dummy GL context, HDC and HWND after obtaining the pixel format. * Then set the final pixel format that we obtained onto the HDC that is derived from the HWND used in GdkWin32Display for notifications, which will become our new dummy HDC. * Create a new dummy HGLRC for use with the new dummy HDC to emulate surfaceless GL support.
2023-05-03 09:58:54 +00:00
HWND hwnd;
HDC hdc;
HGLRC hglrc;
} GdkWin32GLDummyContextWGL;
struct _GdkWin32Display
{
GdkDisplay display;
GdkWin32Screen *screen;
Win32CursorTheme *cursor_theme;
2020-07-24 18:40:36 +00:00
char *cursor_theme_name;
int cursor_theme_size;
HWND hwnd;
/* WGL/OpenGL Items */
GdkWin32GLDummyContextWGL dummy_context_wgl;
GListModel *monitors;
2016-04-20 07:36:00 +00:00
guint hasWglARBCreateContext : 1;
guint hasWglEXTSwapControl : 1;
guint hasWglOMLSyncControl : 1;
guint hasWglARBPixelFormat : 1;
guint hasGlWINSwapHint : 1;
#ifdef HAVE_EGL
guint hasEglKHRCreateContext : 1;
guint hasEglSurfacelessContext : 1;
EGLint egl_min_swap_interval;
#endif
/* HiDPI Items */
guint have_at_least_win81 : 1;
GdkWin32ProcessDpiAwareness dpi_aware_type;
guint has_fixed_scale : 1;
GdkSurface: Rename various functions and variables 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
2018-03-20 11:05:26 +00:00
guint surface_scale;
GdkWin32ShcoreFuncs shcore_funcs;
GdkWin32User32DPIFuncs user32_dpi_funcs;
GdkWin32TabletInputAPI tablet_input_api;
/* Cursor Items (GdkCursor->GdkWin32HCursor) */
GHashTable *cursors;
/* The cursor that is used by current grab (if any) */
GdkWin32HCursor *grab_cursor;
GDK W32: New cursor class 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.
2018-03-29 23:38:05 +00:00
/* HCURSOR -> GdkWin32HCursorTableEntry */
GHashTable *cursor_reftable;
/* ID of the idle callback scheduled to destroy cursors */
guint idle_cursor_destructor_id;
/* A list of cursor handles slated for destruction. */
GList *cursors_for_destruction;
/* Message filters */
GList *filters;
/* Running CPU items */
guint running_on_arm64 : 1;
};
struct _GdkWin32DisplayClass
{
GdkDisplayClass display_class;
};
void _gdk_win32_display_init_monitors (GdkWin32Display *display);
2016-04-20 07:36:00 +00:00
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 *display_win32,
GdkSurface *surface,
HMONITOR hmonitor);
typedef struct _GdkWin32MessageFilter GdkWin32MessageFilter;
struct _GdkWin32MessageFilter
{
GdkWin32MessageFilterFunc function;
gpointer data;
gboolean removed;
guint ref_count;
};