mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-27 22:20:24 +00:00
GdkWin32: Add support for DirectManipulation
Adds support for Precision TouchPads (PTPs) gestures and scroll events.
This commit is contained in:
parent
db2516af0a
commit
8f19099f1a
@ -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;
|
||||
|
||||
|
586
gdk/win32/gdkinput-dmanipulation.c
Normal file
586
gdk/win32/gdkinput-dmanipulation.c
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
||||
/* }}} */
|
32
gdk/win32/gdkinput-dmanipulation.h
Normal file
32
gdk/win32/gdkinput-dmanipulation.h
Normal file
@ -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__ */
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user