[gtk: 1/2] GdkWin32: Add support for DirectManipulation
- From: Luca Bacci <lbacci src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk: 1/2] GdkWin32: Add support for DirectManipulation
- Date: Sun, 15 May 2022 12:55:27 +0000 (UTC)
commit 8f19099f1ae87591802a4b0aafb12ab49bd011da
Author: Luca Bacci <luca bacci982 gmail com>
Date: Wed May 4 14:56:48 2022 +0200
GdkWin32: Add support for DirectManipulation
Adds support for Precision TouchPads (PTPs) gestures
and scroll events.
gdk/win32/gdkevents-win32.c | 10 +
gdk/win32/gdkinput-dmanipulation.c | 586 +++++++++++++++++++++++++++++++++++++
gdk/win32/gdkinput-dmanipulation.h | 32 ++
gdk/win32/gdkmain-win32.c | 83 ++++++
gdk/win32/gdkprivate-win32.h | 10 +
gdk/win32/gdksurface-win32.c | 11 +-
gdk/win32/gdksurface-win32.h | 4 +
gdk/win32/meson.build | 1 +
8 files changed, 735 insertions(+), 2 deletions(-)
---
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c
index c928a14142..23f99c1ab7 100644
--- a/gdk/win32/gdkevents-win32.c
+++ b/gdk/win32/gdkevents-win32.c
@@ -58,6 +58,7 @@
#include "gdkdeviceprivate.h"
#include "gdkdevice-virtual.h"
#include "gdkdevice-wintab.h"
+#include "gdkinput-dmanipulation.h"
#include "gdkinput-winpointer.h"
#include "gdkwin32dnd.h"
#include "gdkwin32dnd-private.h"
@@ -2656,6 +2657,13 @@ gdk_event_translate (MSG *msg,
return_val = TRUE;
break;
+ case DM_POINTERHITTEST:
+ gdk_dmanipulation_maybe_add_contact (window, msg);
+
+ *ret_valp = 0;
+ return_val = TRUE;
+ break;
+
case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
{
@@ -3156,6 +3164,8 @@ gdk_event_translate (MSG *msg,
if (win32_display->tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINPOINTER)
gdk_winpointer_finalize_surface (window);
+ gdk_dmanipulation_finalize_surface (window);
+
return_val = FALSE;
break;
diff --git a/gdk/win32/gdkinput-dmanipulation.c b/gdk/win32/gdkinput-dmanipulation.c
new file mode 100644
index 0000000000..49244f02c2
--- /dev/null
+++ b/gdk/win32/gdkinput-dmanipulation.c
@@ -0,0 +1,586 @@
+/* gdkinput-dmanipulation.c
+ *
+ * Copyright © 2022 the GTK team
+ *
+ * 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 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
+ */
+
+/* {{{ */
+
+#ifdef WINVER
+#undef WINVER
+#endif
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#endif
+#define WINVER 0x0603
+#define _WIN32_WINNT 0x0603
+#define COBJMACROS
+#include "config.h"
+
+#include <gdk/gdk.h>
+#include "gdkwin32.h"
+#include "gdkprivate-win32.h"
+#include "gdkdevicemanager-win32.h"
+#include "gdkdevice-virtual.h"
+#include "gdkdeviceprivate.h"
+#include "gdkdisplayprivate.h"
+#include "gdkeventsprivate.h"
+#include "gdkseatdefaultprivate.h"
+#include "gdkinput-dmanipulation.h"
+#include "winpointer.h"
+
+#include <windows.h>
+#include <directmanipulation.h>
+
+typedef BOOL
+(WINAPI *getPointerType_t)(UINT32 pointerId, POINTER_INPUT_TYPE *pointerType);
+static getPointerType_t getPointerType;
+
+static IDirectManipulationManager *dmanipulation_manager;
+
+typedef struct
+{
+ IDirectManipulationViewportEventHandlerVtbl *vtable;
+ LONG reference_count;
+
+ enum {
+ GESTURE_PAN,
+ GESTURE_ZOOM,
+ } gesture;
+
+ GdkTouchpadGesturePhase phase;
+ gpointer sequence;
+
+ float scale;
+ float pan_x;
+ float pan_y;
+
+ GdkSurface *surface;
+ GdkDevice *device;
+}
+DManipEventHandler;
+
+static void dmanip_event_handler_running_state_clear (DManipEventHandler *handler);
+static void dmanip_event_handler_free (DManipEventHandler *handler);
+
+static void reset_viewport (IDirectManipulationViewport *viewport);
+
+static gpointer util_get_next_sequence (void);
+static GdkModifierType util_get_modifier_state (void);
+static gboolean util_handler_free (gpointer);
+
+/* }}} */
+/* {{{ ViewportEventHandler */
+
+static STDMETHODIMP_ (ULONG)
+DManipEventHandler_AddRef (IDirectManipulationViewportEventHandler *self_)
+{
+ DManipEventHandler *self = (DManipEventHandler*) self_;
+
+ return (ULONG) InterlockedIncrement (&self->reference_count);
+}
+
+static STDMETHODIMP_ (ULONG)
+DManipEventHandler_Release (IDirectManipulationViewportEventHandler *self_)
+{
+ DManipEventHandler *self = (DManipEventHandler*) self_;
+
+ /* NOTE: This may run from a worker thread */
+
+ LONG new_reference_count = InterlockedDecrement (&self->reference_count);
+
+ if (new_reference_count <= 0)
+ {
+ /* For safety, schedule the cleanup to be executed
+ * on the main thread */
+ g_idle_add (util_handler_free, self);
+
+ return 0;
+ }
+
+ return (ULONG) new_reference_count;
+}
+
+static STDMETHODIMP
+DManipEventHandler_QueryInterface (IDirectManipulationViewportEventHandler *self_,
+ REFIID riid,
+ void **ppvObject)
+{
+ DManipEventHandler *self = (DManipEventHandler*) self_;
+
+ if G_UNLIKELY (!self || !ppvObject)
+ return E_POINTER;
+
+ *ppvObject = NULL;
+
+ if (IsEqualGUID (riid, &IID_IUnknown))
+ *ppvObject = self;
+ else if (IsEqualGUID (riid, &IID_IDirectManipulationViewportEventHandler))
+ *ppvObject = self;
+
+ if (*ppvObject == NULL)
+ return E_NOINTERFACE;
+
+ DManipEventHandler_AddRef (self_);
+ return S_OK;
+}
+
+/* NOTE:
+ *
+ * All DManipEventHandler callbacks are fired from the main thread */
+
+static STDMETHODIMP
+DManipEventHandler_OnViewportUpdated (IDirectManipulationViewportEventHandler *self_,
+ IDirectManipulationViewport *viewport)
+{
+ return S_OK;
+}
+
+static STDMETHODIMP
+DManipEventHandler_OnContentUpdated (IDirectManipulationViewportEventHandler *self_,
+ IDirectManipulationViewport *viewport,
+ IDirectManipulationContent *content)
+{
+ DManipEventHandler *self = (DManipEventHandler*) self_;
+ float transform[6] = {1., 0., 0., 1., 0., 0.};
+ HRESULT hr;
+
+ hr = IDirectManipulationContent_GetContentTransform (content, transform,
+ G_N_ELEMENTS (transform));
+ HR_CHECK_RETURN_VAL (hr, E_FAIL);
+
+ switch (self->gesture)
+ {
+ case GESTURE_PAN:
+ {
+ GdkModifierType state;
+ uint32_t time;
+ float pan_x;
+ float pan_y;
+ GdkEvent *event;
+
+ pan_x = transform[4];
+ pan_y = transform[5];
+
+ state = util_get_modifier_state ();
+ time = (uint32_t) GetMessageTime ();
+
+ event = gdk_scroll_event_new (self->surface,
+ self->device,
+ NULL, time, state,
+ self->pan_x - pan_x,
+ self->pan_y - pan_y,
+ FALSE,
+ GDK_SCROLL_UNIT_SURFACE);
+ _gdk_win32_append_event (event);
+
+ self->pan_x = pan_x;
+ self->pan_y = pan_y;
+ }
+ break;
+ case GESTURE_ZOOM:
+ {
+ GdkModifierType state;
+ uint32_t time;
+ POINT cursor = {0, 0};
+ float scale;
+ GdkEvent *event;
+
+ scale = transform[0];
+
+ state = util_get_modifier_state ();
+ time = (uint32_t) GetMessageTime ();
+ _gdk_win32_get_cursor_pos (&cursor);
+
+ ScreenToClient (GDK_SURFACE_HWND (self->surface), &cursor);
+
+ if (!self->sequence)
+ self->sequence = util_get_next_sequence ();
+
+ event = gdk_touchpad_event_new_pinch (self->surface, self->sequence, self->device,
+ time, state, self->phase, cursor.x, cursor.y,
+ 2, 0.0, 0.0, scale, 0.0);
+ _gdk_win32_append_event (event);
+
+ self->scale = scale;
+ self->phase = GDK_TOUCHPAD_GESTURE_PHASE_UPDATE;
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return S_OK;
+}
+
+static STDMETHODIMP
+DManipEventHandler_OnViewportStatusChanged (IDirectManipulationViewportEventHandler *self_,
+ IDirectManipulationViewport *viewport,
+ DIRECTMANIPULATION_STATUS current,
+ DIRECTMANIPULATION_STATUS previous)
+{
+ DManipEventHandler *self = (DManipEventHandler*) self_;
+
+ if (previous == DIRECTMANIPULATION_RUNNING)
+ {
+ switch (self->gesture)
+ {
+ case GESTURE_PAN:
+ {
+ GdkModifierType state;
+ uint32_t time;
+ GdkEvent *event;
+
+ state = util_get_modifier_state ();
+ time = (uint32_t) GetMessageTime ();
+
+ event = gdk_scroll_event_new (self->surface, self->device,
+ NULL, time, state,
+ 0.0, 0.0, TRUE,
+ GDK_SCROLL_UNIT_SURFACE);
+ _gdk_win32_append_event (event);
+ }
+ break;
+ case GESTURE_ZOOM:
+ {
+ GdkModifierType state;
+ uint32_t time;
+ POINT cursor = {0, 0};
+ GdkEvent *event;
+
+ if (self->phase == GDK_TOUCHPAD_GESTURE_PHASE_BEGIN)
+ break;
+
+ state = util_get_modifier_state ();
+ time = (uint32_t) GetMessageTime ();
+ _gdk_win32_get_cursor_pos (&cursor);
+
+ ScreenToClient (GDK_SURFACE_HWND (self->surface), &cursor);
+
+ event = gdk_touchpad_event_new_pinch (self->surface, self->sequence, self->device,
+ time, state, GDK_TOUCHPAD_GESTURE_PHASE_END,
+ cursor.x, cursor.y, 2, 0., 0., self->scale,
+ 0.);
+ _gdk_win32_append_event (event);
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ dmanip_event_handler_running_state_clear (self);
+ reset_viewport (viewport);
+ }
+
+ return S_OK;
+}
+
+static void
+dmanip_event_handler_running_state_clear (DManipEventHandler *handler)
+{
+ handler->scale = 1.0;
+ handler->pan_x = 0.0;
+ handler->pan_y = 0.0;
+
+ handler->phase = GDK_TOUCHPAD_GESTURE_PHASE_BEGIN;
+ handler->sequence = NULL;
+}
+
+static DManipEventHandler*
+dmanip_event_handler_new (GdkSurface *surface,
+ int gesture)
+{
+ static IDirectManipulationViewportEventHandlerVtbl vtable = {
+ DManipEventHandler_QueryInterface,
+ DManipEventHandler_AddRef,
+ DManipEventHandler_Release,
+ DManipEventHandler_OnViewportStatusChanged,
+ DManipEventHandler_OnViewportUpdated,
+ DManipEventHandler_OnContentUpdated,
+ };
+ DManipEventHandler *handler;
+
+ handler = g_new0 (DManipEventHandler, 1);
+ handler->vtable = &vtable;
+ handler->reference_count = 1;
+
+ handler->gesture = gesture;
+
+ handler->surface = surface;
+ handler->device = _gdk_device_manager->core_pointer;
+
+ dmanip_event_handler_running_state_clear (handler);
+
+ return handler;
+}
+
+static void
+dmanip_event_handler_free (DManipEventHandler *handler)
+{
+ g_free (handler);
+}
+
+
+/* }}} */
+/* {{{ Viewport utils */
+
+
+static void
+reset_viewport (IDirectManipulationViewport *viewport)
+{
+ IDirectManipulationContent *content = NULL;
+ REFIID iid = &IID_IDirectManipulationContent;
+ float identity[6] = {1., 0., 0., 1., 0., 0.};
+ HRESULT hr;
+
+ hr = IDirectManipulationViewport_GetPrimaryContent (viewport, iid, (void**)&content);
+ HR_CHECK (hr);
+
+ hr = IDirectManipulationContent_SyncContentTransform (content, identity,
+ G_N_ELEMENTS (identity));
+ HR_CHECK (hr);
+}
+
+static void
+close_viewport (IDirectManipulationViewport **p_viewport)
+{
+ IDirectManipulationViewport *viewport = *p_viewport;
+
+ if (viewport)
+ {
+ IDirectManipulationViewport_Abandon (viewport);
+ IUnknown_Release (viewport);
+
+ *p_viewport = NULL;
+ }
+}
+
+static void
+create_viewport (GdkSurface *surface,
+ int gesture,
+ IDirectManipulationViewport **pViewport)
+{
+ DIRECTMANIPULATION_CONFIGURATION configuration = 0;
+ HWND hwnd = GDK_SURFACE_HWND (surface);
+ IDirectManipulationViewportEventHandler *handler;
+ DWORD cookie = 0;
+ HRESULT hr;
+
+ hr = IDirectManipulationManager_CreateViewport (dmanipulation_manager, NULL, hwnd,
+ &IID_IDirectManipulationViewport,
+ (void**) pViewport);
+ HR_CHECK_GOTO (hr, failed);
+
+ switch (gesture)
+ {
+ case GESTURE_PAN:
+ configuration = DIRECTMANIPULATION_CONFIGURATION_INTERACTION |
+ DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_X |
+ DIRECTMANIPULATION_CONFIGURATION_TRANSLATION_Y;
+ break;
+ case GESTURE_ZOOM:
+ configuration = DIRECTMANIPULATION_CONFIGURATION_INTERACTION |
+ DIRECTMANIPULATION_CONFIGURATION_SCALING;
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ handler = (IDirectManipulationViewportEventHandler*)
+ dmanip_event_handler_new (surface, gesture);
+
+ hr = IDirectManipulationViewport_AddEventHandler (*pViewport, hwnd, handler, &cookie);
+ HR_CHECK_GOTO (hr, failed);
+
+ hr = IDirectManipulationViewport_ActivateConfiguration (*pViewport, configuration);
+ HR_CHECK_GOTO (hr, failed);
+
+ hr = IDirectManipulationViewport_SetViewportOptions (*pViewport,
+ DIRECTMANIPULATION_VIEWPORT_OPTIONS_DISABLEPIXELSNAPPING);
+
+ hr = IDirectManipulationViewport_Enable (*pViewport);
+ HR_CHECK_GOTO (hr, failed);
+
+ // drop our initial reference
+ IUnknown_Release (handler);
+ return;
+
+failed:
+ if (handler)
+ IUnknown_Release (handler);
+
+ close_viewport (pViewport);
+}
+
+
+/* }}} */
+/* {{{ Public */
+
+
+void gdk_dmanipulation_initialize (void)
+{
+ if (!getPointerType)
+ {
+ HMODULE user32_mod;
+
+ user32_mod = LoadLibraryW (L"user32.dll");
+ if (!user32_mod)
+ {
+ WIN32_API_FAILED ("LoadLibraryW");
+ return;
+ }
+
+ getPointerType = (getPointerType_t)
+ GetProcAddress (user32_mod, "GetPointerType");
+
+ if (!getPointerType)
+ return;
+ }
+
+ if (!gdk_win32_ensure_com ())
+ return;
+
+ if (dmanipulation_manager == NULL)
+ {
+ HRESULT hr;
+
+ hr = CoCreateInstance (&CLSID_DirectManipulationManager,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ &IID_IDirectManipulationManager,
+ (LPVOID*)&dmanipulation_manager);
+ if (FAILED (hr))
+ {
+ if (hr == REGDB_E_CLASSNOTREG || hr == E_NOINTERFACE);
+ /* Not an error,
+ * DirectManipulation is not available */
+ else HR_LOG (hr);
+ }
+ }
+}
+
+void gdk_dmanipulation_initialize_surface (GdkSurface *surface)
+{
+ GdkWin32Surface *surface_win32;
+ HRESULT hr;
+
+ if (!dmanipulation_manager)
+ return;
+
+ surface_win32 = GDK_WIN32_SURFACE (surface);
+
+ create_viewport (surface, GESTURE_PAN,
+ &surface_win32->dmanipulation_viewport_pan);
+
+ create_viewport (surface, GESTURE_ZOOM,
+ &surface_win32->dmanipulation_viewport_zoom);
+
+ hr = IDirectManipulationManager_Activate (dmanipulation_manager,
+ GDK_SURFACE_HWND (surface));
+ HR_CHECK (hr);
+}
+
+void gdk_dmanipulation_finalize_surface (GdkSurface *surface)
+{
+ GdkWin32Surface *surface_win32 = GDK_WIN32_SURFACE (surface);
+
+ close_viewport (&surface_win32->dmanipulation_viewport_zoom);
+ close_viewport (&surface_win32->dmanipulation_viewport_pan);
+}
+
+void gdk_dmanipulation_maybe_add_contact (GdkSurface *surface,
+ MSG *msg)
+{
+ POINTER_INPUT_TYPE type = PT_POINTER;
+ UINT32 pointer_id = GET_POINTERID_WPARAM (msg->wParam);
+
+ if (!dmanipulation_manager)
+ return;
+
+ if (!getPointerType)
+ return;
+
+ if G_UNLIKELY (!getPointerType (pointer_id, &type))
+ {
+ WIN32_API_FAILED_LOG_ONCE ("GetPointerType");
+ return;
+ }
+
+ if (type == PT_TOUCHPAD)
+ {
+ GdkWin32Surface *surface_win32 = GDK_WIN32_SURFACE (surface);
+ HRESULT hr;
+
+ hr = IDirectManipulationViewport_SetContact (surface_win32->dmanipulation_viewport_pan,
+ pointer_id);
+ HR_CHECK (hr);
+
+ hr = IDirectManipulationViewport_SetContact (surface_win32->dmanipulation_viewport_zoom,
+ pointer_id);
+ HR_CHECK (hr);
+ }
+}
+
+
+/* }}} */
+/* {{{ Utils */
+
+
+static gpointer
+util_get_next_sequence (void)
+{
+ //TODO: sequence of other input types?
+ static unsigned char *sequence_counter = 0;
+
+ if (++sequence_counter == 0)
+ sequence_counter++;
+
+ return sequence_counter;
+}
+
+static GdkModifierType
+util_get_modifier_state (void)
+{
+ GdkModifierType mask = 0;
+ BYTE kbd[256];
+
+ GetKeyboardState (kbd);
+ if (kbd[VK_SHIFT] & 0x80)
+ mask |= GDK_SHIFT_MASK;
+ if (kbd[VK_CAPITAL] & 0x80)
+ mask |= GDK_LOCK_MASK;
+ if (kbd[VK_CONTROL] & 0x80)
+ mask |= GDK_CONTROL_MASK;
+ if (kbd[VK_MENU] & 0x80)
+ mask |= GDK_ALT_MASK;
+
+ return mask;
+}
+
+static gboolean
+util_handler_free (gpointer handler)
+{
+ dmanip_event_handler_free ((DManipEventHandler*)handler);
+
+ return G_SOURCE_REMOVE;
+}
+
+
+/* }}} */
diff --git a/gdk/win32/gdkinput-dmanipulation.h b/gdk/win32/gdkinput-dmanipulation.h
new file mode 100644
index 0000000000..77d603c0cf
--- /dev/null
+++ b/gdk/win32/gdkinput-dmanipulation.h
@@ -0,0 +1,32 @@
+/* gdkinput-dmanipulation.h
+ *
+ * Copyright © 2022 the GTK team
+ *
+ * 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 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_INPUT_DMANIPULATION_H__
+#define __GDK_INPUT_DMANIPULATION_H__
+
+void gdk_dmanipulation_initialize (void);
+
+void gdk_dmanipulation_initialize_surface (GdkSurface *surface);
+void gdk_dmanipulation_finalize_surface (GdkSurface *surface);
+
+void gdk_dmanipulation_maybe_add_contact (GdkSurface *surface,
+ MSG *msg);
+
+#endif /* __GDK_INPUT_DMANIPULATION_H__ */
diff --git a/gdk/win32/gdkmain-win32.c b/gdk/win32/gdkmain-win32.c
index d140d8e644..d6f8dc82ed 100644
--- a/gdk/win32/gdkmain-win32.c
+++ b/gdk/win32/gdkmain-win32.c
@@ -36,6 +36,7 @@
#include "gdkkeysyms.h"
#include "gdkintl.h"
#include "gdkprivate-win32.h"
+#include "gdkinput-dmanipulation.h"
#include "gdkwin32.h"
#include <objbase.h>
@@ -49,6 +50,12 @@
static gboolean gdk_synchronize = FALSE;
+/* Whether GDK initialized COM */
+static gboolean co_initialized = FALSE;
+
+/* Whether GDK initialized OLE */
+static gboolean ole_initialized = FALSE;
+
void
_gdk_win32_surfaceing_init (void)
{
@@ -67,6 +74,82 @@ _gdk_win32_surfaceing_init (void)
GDK_NOTE (EVENTS, g_print ("input_locale: %p\n", _gdk_input_locale));
_gdk_win32_clipdrop_init ();
+
+ gdk_dmanipulation_initialize ();
+}
+
+gboolean
+gdk_win32_ensure_com (void)
+{
+ if (!co_initialized)
+ {
+ /* UI thread should only use STA model. See
+ * -> https://devblogs.microsoft.com/oldnewthing/20080424-00/?p=22603
+ * -> https://devblogs.microsoft.com/oldnewthing/20071018-00/?p=24743
+ */
+ const DWORD flags = COINIT_APARTMENTTHREADED |
+ COINIT_DISABLE_OLE1DDE;
+ HRESULT hr;
+
+ hr = CoInitializeEx (NULL, flags);
+ if (SUCCEEDED (hr))
+ co_initialized = TRUE;
+ else switch (hr)
+ {
+ case RPC_E_CHANGED_MODE:
+ g_warning ("COM runtime already initialized on the main "
+ "thread with an incompatible apartment model");
+ break;
+ default:
+ HR_LOG (hr);
+ break;
+ }
+ }
+
+ return co_initialized;
+}
+
+static void
+gdk_win32_finalize_com (void)
+{
+ if (co_initialized)
+ {
+ CoUninitialize ();
+ co_initialized = FALSE;
+ }
+}
+
+gboolean
+gdk_win32_ensure_ole (void)
+{
+ if (!ole_initialized)
+ {
+ HRESULT hr = OleInitialize (NULL);
+ if (SUCCEEDED (hr))
+ ole_initialized = TRUE;
+ else switch (hr)
+ {
+ case RPC_E_CHANGED_MODE:
+ g_warning ("Failed to initialize the OLE2 runtime because "
+ "the thread has an incompatible apartment model");
+ break;
+ default:
+ HR_LOG (hr);
+ break;
+ }
+ }
+
+ return ole_initialized;
+}
+
+static void
+gdk_win32_finalize_ole (void)
+{
+ if (ole_initialized)
+ {
+ OleUninitialize ();
+ ole_initialized = FALSE;
+ }
}
void
diff --git a/gdk/win32/gdkprivate-win32.h b/gdk/win32/gdkprivate-win32.h
index 652272c5cc..3ba99dce83 100644
--- a/gdk/win32/gdkprivate-win32.h
+++ b/gdk/win32/gdkprivate-win32.h
@@ -196,6 +196,9 @@ void _gdk_remove_modal_window (GdkSurface *window);
GdkSurface *_gdk_modal_current (void);
gboolean _gdk_modal_blocked (GdkSurface *window);
+gboolean gdk_win32_ensure_com (void);
+gboolean gdk_win32_ensure_ole (void);
+
#ifdef G_ENABLE_DEBUG
void _gdk_win32_print_paletteentries (const PALETTEENTRY *pep,
const int nentries);
@@ -252,6 +255,13 @@ void _gdk_other_api_failed (const char *where,
#define GDI_CALL(api, arglist) (api arglist ? 1 : (WIN32_GDI_FAILED (#api), 0))
#define API_CALL(api, arglist) (api arglist ? 1 : (WIN32_API_FAILED (#api), 0))
+#define HR_LOG(hr)
+
+#define HR_CHECK_RETURN(hr) { if G_UNLIKELY (FAILED (hr)) return; }
+#define HR_CHECK_RETURN_VAL(hr, val) { if G_UNLIKELY (FAILED (hr)) return val; }
+#define HR_CHECK(hr)
+#define HR_CHECK_GOTO(hr, label) { if G_UNLIKELY (FAILED (hr)) goto label; }
+
extern LRESULT CALLBACK _gdk_win32_surface_procedure (HWND, UINT, WPARAM, LPARAM);
extern GdkDisplay *_gdk_display;
diff --git a/gdk/win32/gdksurface-win32.c b/gdk/win32/gdksurface-win32.c
index 938737e86b..cef3d4c8f5 100644
--- a/gdk/win32/gdksurface-win32.c
+++ b/gdk/win32/gdksurface-win32.c
@@ -44,6 +44,7 @@
#include "gdktoplevelprivate.h"
#include "gdkwin32surface.h"
#include "gdkwin32cursor.h"
+#include "gdkinput-dmanipulation.h"
#include "gdkinput-winpointer.h"
#include "gdkglcontext-win32.h"
#include "gdkdisplay-win32.h"
@@ -639,8 +640,14 @@ _gdk_win32_display_create_surface (GdkDisplay *display,
}
gdk_surface_set_egl_native_window (surface, (void *) impl->handle);
- if (display_win32->tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINPOINTER)
- gdk_winpointer_initialize_surface (surface);
+
+ if (surface_type != GDK_SURFACE_TEMP)
+ {
+ if (display_win32->tablet_input_api == GDK_WIN32_TABLET_INPUT_API_WINPOINTER)
+ gdk_winpointer_initialize_surface (surface);
+
+ gdk_dmanipulation_initialize_surface (surface);
+ }
_gdk_win32_surface_enable_transparency (surface);
_gdk_win32_surface_register_dnd (surface);
diff --git a/gdk/win32/gdksurface-win32.h b/gdk/win32/gdksurface-win32.h
index 08bd0a20b7..cff41117ef 100644
--- a/gdk/win32/gdksurface-win32.h
+++ b/gdk/win32/gdksurface-win32.h
@@ -32,6 +32,7 @@
#include "gdk/gdkcursor.h"
#include <windows.h>
+#include <directmanipulation.h>
#ifdef HAVE_EGL
# include <epoxy/egl.h>
@@ -339,6 +340,9 @@ struct _GdkWin32Surface
} next_layout;
gboolean force_recompute_size;
+ IDirectManipulationViewport *dmanipulation_viewport_pan;
+ IDirectManipulationViewport *dmanipulation_viewport_zoom;
+
#ifdef HAVE_EGL
guint egl_force_redraw_all : 1;
#endif
diff --git a/gdk/win32/meson.build b/gdk/win32/meson.build
index d368648624..156c9ab730 100644
--- a/gdk/win32/meson.build
+++ b/gdk/win32/meson.build
@@ -17,6 +17,7 @@ gdk_win32_sources = files([
'gdkglcontext-win32-wgl.c',
'gdkglobals-win32.c',
'gdkhdataoutputstream-win32.c',
+ 'gdkinput-dmanipulation.c',
'gdkinput-winpointer.c',
'gdkkeys-win32.c',
'gdkkeys-win32-impl.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]