#include "pen_channel.h" #include #include #include #include #include #include namespace { std::unique_ptr> g_pen_sink; std::unique_ptr> g_pen_channel; // Diagnostic counters so the Dart side can see WHAT the observer receives: // - g_ptr_msgs: WM_POINTER* messages seen (is WM_POINTER reaching us at all?) // - g_pen_msgs: of those, PT_PEN with a successful GetPointerPenInfo // - g_mouse_msgs: legacy mouse/touch input messages (Flutter on the old path?) int g_ptr_msgs = 0; int g_pen_msgs = 0; int g_mouse_msgs = 0; int g_last_msg = 0; } // namespace void RegisterPenChannel(flutter::FlutterEngine* engine) { g_pen_channel = std::make_unique>( engine->messenger(), "badnote/pen", &flutter::StandardMethodCodec::GetInstance()); auto handler = std::make_unique< flutter::StreamHandlerFunctions>( [](const flutter::EncodableValue* arguments, std::unique_ptr>&& events) -> std::unique_ptr< flutter::StreamHandlerError> { g_pen_sink = std::move(events); return nullptr; }, [](const flutter::EncodableValue* arguments) -> std::unique_ptr< flutter::StreamHandlerError> { g_pen_sink = nullptr; return nullptr; }); g_pen_channel->SetStreamHandler(std::move(handler)); } void ObservePenMessage(UINT message, WPARAM wparam, LPARAM lparam) { if (!g_pen_sink) { return; } const bool is_pointer = message == WM_POINTERENTER || message == WM_POINTERDOWN || message == WM_POINTERUPDATE || message == WM_POINTERUP; // Legacy input path: if Flutter is feeding us mouse/touch instead of pointer // messages, these tell us so (so we know WM_POINTER never arrives here). const bool is_legacy_input = message == WM_LBUTTONDOWN || message == WM_LBUTTONUP || message == WM_MOUSEMOVE || message == WM_TOUCH; if (!is_pointer && !is_legacy_input) { return; } g_last_msg = static_cast(message); if (is_legacy_input) { ++g_mouse_msgs; } int flags = 0; double tilt_x = 0.0; double tilt_y = 0.0; if (is_pointer) { ++g_ptr_msgs; UINT32 pointerId = GET_POINTERID_WPARAM(wparam); POINTER_INPUT_TYPE type = PT_POINTER; if (GetPointerType(pointerId, &type) && type == PT_PEN) { POINTER_PEN_INFO ppi{}; if (GetPointerPenInfo(pointerId, &ppi)) { ++g_pen_msgs; if (ppi.penFlags & PEN_FLAG_BARREL) flags |= 1; if (ppi.penFlags & PEN_FLAG_INVERTED) flags |= 2; if (ppi.penFlags & PEN_FLAG_ERASER) flags |= 4; tilt_x = static_cast(ppi.tiltX); tilt_y = static_cast(ppi.tiltY); } } if (message == WM_POINTERUP) { flags = 0; // lift-off clears held flags } } // Always emit the diagnostic counters so the Dart overlay can show whether // WM_POINTER / PT_PEN ever reach this observer. flutter::EncodableMap payload{ {flutter::EncodableValue("flags"), flutter::EncodableValue(flags)}, {flutter::EncodableValue("tiltX"), flutter::EncodableValue(tilt_x)}, {flutter::EncodableValue("tiltY"), flutter::EncodableValue(tilt_y)}, {flutter::EncodableValue("diagPtr"), flutter::EncodableValue(g_ptr_msgs)}, {flutter::EncodableValue("diagPen"), flutter::EncodableValue(g_pen_msgs)}, {flutter::EncodableValue("diagMouse"), flutter::EncodableValue(g_mouse_msgs)}, {flutter::EncodableValue("diagMsg"), flutter::EncodableValue(g_last_msg)}, }; g_pen_sink->Success(flutter::EncodableValue(payload)); }