📄 gtkimcontextime.c
字号:
g_free (utf8str); utf8str = NULL; } if (cursor_pos) *cursor_pos = pos;}static voidgtk_im_context_ime_focus_in (GtkIMContext *context){ GtkIMContextIME *context_ime = GTK_IM_CONTEXT_IME (context); GdkWindow *toplevel; GtkWidget *widget = NULL; HWND hwnd, top_hwnd; HIMC himc; if (!GDK_IS_WINDOW (context_ime->client_window)) return; /* swtich current context */ context_ime->focus = TRUE; hwnd = GDK_WINDOW_HWND (context_ime->client_window); himc = ImmGetContext (hwnd); if (!himc) return; toplevel = gdk_window_get_toplevel (context_ime->client_window); if (GDK_IS_WINDOW (toplevel)) { gdk_window_add_filter (toplevel, gtk_im_context_ime_message_filter, context_ime); top_hwnd = GDK_WINDOW_HWND (toplevel); context_ime->toplevel = toplevel; } else { g_warning ("gtk_im_context_ime_focus_in(): " "cannot find toplevel window."); return; } /* trace reparenting (probably no need) */ gdk_window_get_user_data (context_ime->client_window, (gpointer) & widget); if (GTK_IS_WIDGET (widget)) { g_signal_connect (widget, "hierarchy-changed", G_CALLBACK (cb_client_widget_hierarchy_changed), context_ime); } else { /* warning? */ } /* restore preedit context */ ImmSetConversionStatus (himc, context_ime->priv->conversion_mode, context_ime->priv->sentence_mode); if (context_ime->opened) { if (!ImmGetOpenStatus (himc)) ImmSetOpenStatus (himc, TRUE); if (context_ime->preediting) { ImmSetCompositionStringW (himc, SCS_SETSTR, context_ime->priv->comp_str, context_ime->priv->comp_str_len, NULL, 0); FREE_PREEDIT_BUFFER (context_ime); } } /* clean */ ImmReleaseContext (hwnd, himc);}static voidgtk_im_context_ime_focus_out (GtkIMContext *context){ GtkIMContextIME *context_ime = GTK_IM_CONTEXT_IME (context); GdkWindow *toplevel; GtkWidget *widget = NULL; HWND hwnd, top_hwnd; HIMC himc; if (!GDK_IS_WINDOW (context_ime->client_window)) return; /* swtich current context */ context_ime->focus = FALSE; hwnd = GDK_WINDOW_HWND (context_ime->client_window); himc = ImmGetContext (hwnd); if (!himc) return; /* save preedit context */ ImmGetConversionStatus (himc, &context_ime->priv->conversion_mode, &context_ime->priv->sentence_mode); if (ImmGetOpenStatus (himc)) { gboolean preediting = context_ime->preediting; if (preediting) { FREE_PREEDIT_BUFFER (context_ime); context_ime->priv->comp_str_len = ImmGetCompositionStringW (himc, GCS_COMPSTR, NULL, 0); context_ime->priv->comp_str = g_malloc (context_ime->priv->comp_str_len); ImmGetCompositionStringW (himc, GCS_COMPSTR, context_ime->priv->comp_str, context_ime->priv->comp_str_len); context_ime->priv->read_str_len = ImmGetCompositionStringW (himc, GCS_COMPREADSTR, NULL, 0); context_ime->priv->read_str = g_malloc (context_ime->priv->read_str_len); ImmGetCompositionStringW (himc, GCS_COMPREADSTR, context_ime->priv->read_str, context_ime->priv->read_str_len); } ImmSetOpenStatus (himc, FALSE); context_ime->opened = TRUE; context_ime->preediting = preediting; } else { context_ime->opened = FALSE; context_ime->preediting = FALSE; } /* remove signal handler */ gdk_window_get_user_data (context_ime->client_window, (gpointer) & widget); if (GTK_IS_WIDGET (widget)) { g_signal_handlers_disconnect_by_func (G_OBJECT (widget), G_CALLBACK (cb_client_widget_hierarchy_changed), context_ime); } /* remove event fileter */ toplevel = gdk_window_get_toplevel (context_ime->client_window); if (GDK_IS_WINDOW (toplevel)) { gdk_window_remove_filter (toplevel, gtk_im_context_ime_message_filter, context_ime); top_hwnd = GDK_WINDOW_HWND (toplevel); context_ime->toplevel = NULL; } else { g_warning ("gtk_im_context_ime_focus_out(): " "cannot find toplevel window."); } /* clean */ ImmReleaseContext (hwnd, himc);}static voidgtk_im_context_ime_set_cursor_location (GtkIMContext *context, GdkRectangle *area){ gint wx = 0, wy = 0; GtkIMContextIME *context_ime; COMPOSITIONFORM cf; HWND hwnd; HIMC himc; g_return_if_fail (GTK_IS_IM_CONTEXT_IME (context)); context_ime = GTK_IM_CONTEXT_IME (context); if (area) context_ime->cursor_location = *area; if (!context_ime->client_window) return; hwnd = GDK_WINDOW_HWND (context_ime->client_window); himc = ImmGetContext (hwnd); if (!himc) return; get_window_position (context_ime->client_window, &wx, &wy); cf.dwStyle = CFS_POINT; cf.ptCurrentPos.x = wx + context_ime->cursor_location.x; cf.ptCurrentPos.y = wy + context_ime->cursor_location.y; ImmSetCompositionWindow (himc, &cf); ImmReleaseContext (hwnd, himc);}static voidgtk_im_context_ime_set_use_preedit (GtkIMContext *context, gboolean use_preedit){ GtkIMContextIME *context_ime; g_return_if_fail (GTK_IS_IM_CONTEXT_IME (context)); context_ime = GTK_IM_CONTEXT_IME (context); context_ime->use_preedit = use_preedit; if (context_ime->preediting) { HWND hwnd; HIMC himc; hwnd = GDK_WINDOW_HWND (context_ime->client_window); himc = ImmGetContext (hwnd); if (!himc) return; /* FIXME: What to do? */ ImmReleaseContext (hwnd, himc); }}static voidgtk_im_context_ime_set_preedit_font (GtkIMContext *context){ GtkIMContextIME *context_ime; GtkWidget *widget = NULL; HWND hwnd; HIMC himc; HKL ime = GetKeyboardLayout (0); const gchar *lang; gunichar wc; PangoContext *pango_context; PangoFont *font; LOGFONT *logfont; g_return_if_fail (GTK_IS_IM_CONTEXT_IME (context)); context_ime = GTK_IM_CONTEXT_IME (context); if (!context_ime->client_window) return; gdk_window_get_user_data (context_ime->client_window, (gpointer) &widget); if (!GTK_IS_WIDGET (widget)) return; hwnd = GDK_WINDOW_HWND (context_ime->client_window); himc = ImmGetContext (hwnd); if (!himc) return; /* set font */ pango_context = gtk_widget_get_pango_context (widget); if (!pango_context) goto ERROR_OUT; /* Try to make sure we use a font that actually can show the * language in question. */ switch (PRIMARYLANGID (LOWORD (ime))) { case LANG_JAPANESE: lang = "ja"; break; case LANG_KOREAN: lang = "ko"; break; case LANG_CHINESE: switch (SUBLANGID (LOWORD (ime))) { case SUBLANG_CHINESE_TRADITIONAL: lang = "zh_TW"; break; case SUBLANG_CHINESE_SIMPLIFIED: lang = "zh_CN"; break; case SUBLANG_CHINESE_HONGKONG: lang = "zh_HK"; break; case SUBLANG_CHINESE_SINGAPORE: lang = "zh_SG"; break; case SUBLANG_CHINESE_MACAU: lang = "zh_MO"; break; default: lang = "zh"; break; } break; default: lang = ""; break; } if (lang[0]) { /* We know what language it is. Look for a character, any * character, that language needs. */ PangoLanguage *pango_lang = pango_language_from_string (lang); PangoFontset *fontset = pango_context_load_fontset (pango_context, widget->style->font_desc, pango_lang); gunichar *sample = g_utf8_to_ucs4 (pango_language_get_sample_string (pango_lang), -1, NULL, NULL, NULL); wc = 0x4E00; /* In all CJK languages? */ if (sample != NULL) { int i; for (i = 0; sample[i]; i++) if (g_unichar_iswide (sample[i])) { wc = sample[i]; break; } g_free (sample); } font = pango_fontset_get_font (fontset, wc); g_object_unref (fontset); } else font = pango_context_load_font (pango_context, widget->style->font_desc); if (!font) goto ERROR_OUT; logfont = pango_win32_font_logfont (font); if (logfont) ImmSetCompositionFont (himc, logfont); g_object_unref (font);ERROR_OUT: /* clean */ ImmReleaseContext (hwnd, himc);}static GdkFilterReturngtk_im_context_ime_message_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data){ GtkIMContext *context; GtkIMContextIME *context_ime; HWND hwnd; HIMC himc; MSG *msg = (MSG *) xevent; GdkFilterReturn retval = GDK_FILTER_CONTINUE; g_return_val_if_fail (GTK_IS_IM_CONTEXT_IME (data), retval); context = GTK_IM_CONTEXT (data); context_ime = GTK_IM_CONTEXT_IME (data); if (!context_ime->focus) return retval; hwnd = GDK_WINDOW_HWND (context_ime->client_window); himc = ImmGetContext (hwnd); if (!himc) return retval; switch (msg->message) { case WM_IME_COMPOSITION: { gint wx = 0, wy = 0; CANDIDATEFORM cf; get_window_position (context_ime->client_window, &wx, &wy); /* FIXME! */ { HWND hwnd_top; POINT pt; RECT rc; hwnd_top = GDK_WINDOW_HWND (gdk_window_get_toplevel (context_ime->client_window)); GetWindowRect (hwnd_top, &rc); pt.x = wx; pt.y = wy; ClientToScreen (hwnd_top, &pt); wx = pt.x - rc.left; wy = pt.y - rc.top; } cf.dwIndex = 0; cf.dwStyle = CFS_CANDIDATEPOS; cf.ptCurrentPos.x = wx + context_ime->cursor_location.x; cf.ptCurrentPos.y = wy + context_ime->cursor_location.y + context_ime->cursor_location.height; ImmSetCandidateWindow (himc, &cf); if ((msg->lParam & GCS_COMPSTR)) g_signal_emit_by_name (context, "preedit_changed"); if (msg->lParam & GCS_RESULTSTR) { gsize len; gchar *utf8str = NULL; GError *error = NULL; len = ImmGetCompositionStringW (himc, GCS_RESULTSTR, NULL, 0); if (len > 0) { gpointer buf = g_alloca (len); ImmGetCompositionStringW (himc, GCS_RESULTSTR, buf, len); len /= 2; utf8str = g_utf16_to_utf8 (buf, len, NULL, NULL, &error); if (error) { g_warning ("%s", error->message); g_error_free (error); } } if (utf8str) { g_signal_emit_by_name (context, "commit", utf8str); g_free (utf8str); retval = TRUE; } } if (context_ime->use_preedit) retval = TRUE; break; } case WM_IME_STARTCOMPOSITION: context_ime->preediting = TRUE; gtk_im_context_ime_set_cursor_location (context, NULL); g_signal_emit_by_name (context, "preedit_start"); if (context_ime->use_preedit) retval = TRUE; break; case WM_IME_ENDCOMPOSITION: context_ime->preediting = FALSE; g_signal_emit_by_name (context, "preedit_changed"); g_signal_emit_by_name (context, "preedit_end"); if (context_ime->use_preedit) retval = TRUE; break; case WM_IME_NOTIFY: switch (msg->wParam) { case IMN_SETOPENSTATUS: context_ime->opened = ImmGetOpenStatus (himc); gtk_im_context_ime_set_preedit_font (context); break; default: break; } default: break; } ImmReleaseContext (hwnd, himc); return retval;}/* * x and y must be initialized to 0. */static voidget_window_position (GdkWindow *win, gint *x, gint *y){ GdkWindow *parent, *toplevel; gint wx, wy; g_return_if_fail (GDK_IS_WINDOW (win)); g_return_if_fail (x && y); gdk_window_get_position (win, &wx, &wy); *x += wx; *y += wy; parent = gdk_window_get_parent (win); toplevel = gdk_window_get_toplevel (win); if (parent && parent != toplevel) get_window_position (parent, x, y);}/* * probably, this handler isn't needed. */static voidcb_client_widget_hierarchy_changed (GtkWidget *widget, GtkWidget *widget2, GtkIMContextIME *context_ime){ GdkWindow *new_toplevel; g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (GTK_IS_IM_CONTEXT_IME (context_ime)); if (!context_ime->client_window) return; if (!context_ime->focus) return; new_toplevel = gdk_window_get_toplevel (context_ime->client_window); if (context_ime->toplevel == new_toplevel) return; /* remove filter from old toplevel */ if (GDK_IS_WINDOW (context_ime->toplevel)) { gdk_window_remove_filter (context_ime->toplevel, gtk_im_context_ime_message_filter, context_ime); } else { } /* add filter to new toplevel */ if (GDK_IS_WINDOW (new_toplevel)) { gdk_window_add_filter (new_toplevel, gtk_im_context_ime_message_filter, context_ime); } else { } context_ime->toplevel = new_toplevel;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -