forked from AuroraMiddleware/gtk
173 lines
4.5 KiB
C
173 lines
4.5 KiB
C
|
/* GDK - The GIMP Drawing Kit
|
|||
|
* Copyright (C) 2019 Руслан Ижбулатов <lrn1986@gmail.com>
|
|||
|
*
|
|||
|
* 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/>.
|
|||
|
*/
|
|||
|
|
|||
|
#include "config.h"
|
|||
|
|
|||
|
#define COBJMACROS
|
|||
|
#include <msctf.h>
|
|||
|
|
|||
|
#include <gdk/gdk.h>
|
|||
|
|
|||
|
#include "gdkprivate-win32.h"
|
|||
|
|
|||
|
struct _GdkWin32ALPNSink
|
|||
|
{
|
|||
|
ITfActiveLanguageProfileNotifySink itf_alpn_sink;
|
|||
|
|
|||
|
gint ref_count;
|
|||
|
};
|
|||
|
|
|||
|
typedef struct _GdkWin32ALPNSink GdkWin32ALPNSink;
|
|||
|
|
|||
|
static GdkWin32ALPNSink *actlangchangenotify = NULL;
|
|||
|
static ITfSource *itf_source = NULL;
|
|||
|
static DWORD actlangchangenotify_id = 0;
|
|||
|
|
|||
|
static ULONG STDMETHODCALLTYPE
|
|||
|
alpn_sink_addref (ITfActiveLanguageProfileNotifySink *This)
|
|||
|
{
|
|||
|
GdkWin32ALPNSink *alpn_sink = (GdkWin32ALPNSink *) This;
|
|||
|
int ref_count = ++alpn_sink->ref_count;
|
|||
|
|
|||
|
return ref_count;
|
|||
|
}
|
|||
|
|
|||
|
static HRESULT STDMETHODCALLTYPE
|
|||
|
alpn_sink_queryinterface (ITfActiveLanguageProfileNotifySink *This,
|
|||
|
REFIID riid,
|
|||
|
LPVOID *ppvObject)
|
|||
|
{
|
|||
|
*ppvObject = NULL;
|
|||
|
|
|||
|
if (IsEqualGUID (riid, &IID_IUnknown))
|
|||
|
{
|
|||
|
ITfActiveLanguageProfileNotifySink_AddRef (This);
|
|||
|
*ppvObject = This;
|
|||
|
return S_OK;
|
|||
|
}
|
|||
|
|
|||
|
if (IsEqualGUID (riid, &IID_ITfActiveLanguageProfileNotifySink))
|
|||
|
{
|
|||
|
ITfActiveLanguageProfileNotifySink_AddRef (This);
|
|||
|
*ppvObject = This;
|
|||
|
return S_OK;
|
|||
|
}
|
|||
|
|
|||
|
return E_NOINTERFACE;
|
|||
|
}
|
|||
|
|
|||
|
static ULONG STDMETHODCALLTYPE
|
|||
|
alpn_sink_release (ITfActiveLanguageProfileNotifySink *This)
|
|||
|
{
|
|||
|
GdkWin32ALPNSink *alpn_sink = (GdkWin32ALPNSink *) This;
|
|||
|
int ref_count = --alpn_sink->ref_count;
|
|||
|
|
|||
|
if (ref_count == 0)
|
|||
|
{
|
|||
|
g_free (This);
|
|||
|
}
|
|||
|
|
|||
|
return ref_count;
|
|||
|
}
|
|||
|
|
|||
|
static HRESULT STDMETHODCALLTYPE
|
|||
|
alpn_sink_on_activated (ITfActiveLanguageProfileNotifySink *This,
|
|||
|
REFCLSID clsid,
|
|||
|
REFGUID guidProfile,
|
|||
|
BOOL fActivated)
|
|||
|
{
|
|||
|
_gdk_input_locale_is_ime = fActivated;
|
|||
|
return S_OK;
|
|||
|
}
|
|||
|
|
|||
|
static ITfActiveLanguageProfileNotifySinkVtbl alpn_sink_vtbl = {
|
|||
|
alpn_sink_queryinterface,
|
|||
|
alpn_sink_addref,
|
|||
|
alpn_sink_release,
|
|||
|
alpn_sink_on_activated,
|
|||
|
};
|
|||
|
|
|||
|
static GdkWin32ALPNSink *
|
|||
|
alpn_sink_new ()
|
|||
|
{
|
|||
|
GdkWin32ALPNSink *result;
|
|||
|
|
|||
|
result = g_new0 (GdkWin32ALPNSink, 1);
|
|||
|
result->itf_alpn_sink.lpVtbl = &alpn_sink_vtbl;
|
|||
|
result->ref_count = 0;
|
|||
|
|
|||
|
ITfActiveLanguageProfileNotifySink_AddRef (&result->itf_alpn_sink);
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
_gdk_win32_lang_notification_init ()
|
|||
|
{
|
|||
|
HRESULT hr;
|
|||
|
ITfThreadMgr *itf_threadmgr;
|
|||
|
|
|||
|
CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
|
|||
|
|
|||
|
if (actlangchangenotify != NULL)
|
|||
|
return;
|
|||
|
|
|||
|
hr = CoCreateInstance (&CLSID_TF_ThreadMgr,
|
|||
|
NULL,
|
|||
|
CLSCTX_INPROC_SERVER,
|
|||
|
&IID_ITfThreadMgr,
|
|||
|
(LPVOID *) &itf_threadmgr);
|
|||
|
|
|||
|
if (!SUCCEEDED (hr))
|
|||
|
return;
|
|||
|
|
|||
|
hr = ITfThreadMgr_QueryInterface (itf_threadmgr, &IID_ITfSource, (VOID **) &itf_source);
|
|||
|
ITfThreadMgr_Release (itf_threadmgr);
|
|||
|
|
|||
|
if (!SUCCEEDED (hr))
|
|||
|
return;
|
|||
|
|
|||
|
actlangchangenotify = alpn_sink_new ();
|
|||
|
|
|||
|
hr = ITfSource_AdviseSink (itf_source,
|
|||
|
&IID_ITfActiveLanguageProfileNotifySink,
|
|||
|
(IUnknown *) actlangchangenotify,
|
|||
|
&actlangchangenotify_id);
|
|||
|
|
|||
|
if (!SUCCEEDED (hr))
|
|||
|
{
|
|||
|
ITfActiveLanguageProfileNotifySink_Release (&actlangchangenotify->itf_alpn_sink);
|
|||
|
actlangchangenotify = NULL;
|
|||
|
ITfSource_Release (itf_source);
|
|||
|
itf_source = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
_gdk_win32_lang_notification_exit ()
|
|||
|
{
|
|||
|
if (actlangchangenotify != NULL && itf_source != NULL)
|
|||
|
{
|
|||
|
ITfSource_UnadviseSink (itf_source, actlangchangenotify_id);
|
|||
|
ITfSource_Release (itf_source);
|
|||
|
ITfActiveLanguageProfileNotifySink_Release (&actlangchangenotify->itf_alpn_sink);
|
|||
|
}
|
|||
|
|
|||
|
CoUninitialize ();
|
|||
|
}
|