mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-04-13 09:08:06 -05:00
Support for dead keys and compose sequences on Unix, by instantiating
a GtkIMMulticontext and having that filter most keypresses. I think I've got this right so that it doesn't break any previous deliberate keyboard-handling behaviour that's now _after_ the 'if (filter keypress) return' statement. [originally from svn r9567]
This commit is contained in:
parent
bc6e0952ef
commit
7fc8db15b2
@ -13,6 +13,7 @@
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
@ -24,6 +25,10 @@
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#if GTK_CHECK_VERSION(2,0,0)
|
||||
#include <gtk/gtkimmodule.h>
|
||||
#endif
|
||||
|
||||
#define PUTTY_DO_GLOBALS /* actually _define_ globals */
|
||||
|
||||
#include "putty.h"
|
||||
@ -68,6 +73,9 @@ struct gui_data {
|
||||
*restartitem;
|
||||
GtkWidget *sessionsmenu;
|
||||
GdkPixmap *pixmap;
|
||||
#if GTK_CHECK_VERSION(2,0,0)
|
||||
GtkIMContext *imc;
|
||||
#endif
|
||||
unifont *fonts[4]; /* normal, bold, wide, widebold */
|
||||
int xpos, ypos, gotpos, gravity;
|
||||
GdkCursor *rawcursor, *textcursor, *blankcursor, *waitcursor, *currcursor;
|
||||
@ -489,6 +497,10 @@ gint configure_area(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
|
||||
if (inst->term)
|
||||
term_invalidate(inst->term);
|
||||
|
||||
#if GTK_CHECK_VERSION(2,0,0)
|
||||
gtk_im_context_set_client_window(inst->imc, widget->window);
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -539,21 +551,26 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
|
||||
* inconvenience in having to type a zero before a single-digit
|
||||
* character code.
|
||||
*/
|
||||
if (event->type == GDK_KEY_RELEASE &&
|
||||
(event->keyval == GDK_Meta_L || event->keyval == GDK_Alt_L ||
|
||||
event->keyval == GDK_Meta_R || event->keyval == GDK_Alt_R) &&
|
||||
inst->alt_keycode >= 0 && inst->alt_digits > 1) {
|
||||
if (event->type == GDK_KEY_RELEASE) {
|
||||
if ((event->keyval == GDK_Meta_L || event->keyval == GDK_Alt_L ||
|
||||
event->keyval == GDK_Meta_R || event->keyval == GDK_Alt_R) &&
|
||||
inst->alt_keycode >= 0 && inst->alt_digits > 1) {
|
||||
#ifdef KEY_DEBUGGING
|
||||
printf("Alt key up, keycode = %d\n", inst->alt_keycode);
|
||||
printf("Alt key up, keycode = %d\n", inst->alt_keycode);
|
||||
#endif
|
||||
/*
|
||||
* FIXME: we might usefully try to do something clever here
|
||||
* about interpreting the generated key code in a way that's
|
||||
* appropriate to the line code page.
|
||||
*/
|
||||
output[0] = inst->alt_keycode;
|
||||
end = 1;
|
||||
goto done;
|
||||
}
|
||||
#if GTK_CHECK_VERSION(2,0,0)
|
||||
if (gtk_im_context_filter_keypress(inst->imc, event))
|
||||
return TRUE;
|
||||
#endif
|
||||
/*
|
||||
* FIXME: we might usefully try to do something clever here
|
||||
* about interpreting the generated key code in a way that's
|
||||
* appropriate to the line code page.
|
||||
*/
|
||||
output[0] = inst->alt_keycode;
|
||||
end = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (event->type == GDK_KEY_PRESS) {
|
||||
@ -669,13 +686,13 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
|
||||
output_charset = CS_ISO8859_1;
|
||||
strncpy(output+1, event->string, lenof(output)-1);
|
||||
#else
|
||||
if (gtk_im_context_filter_keypress(inst->imc, event))
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
* GDK 2.0 arranges to have done some translation for us: in
|
||||
* GDK 2.0, event->string is encoded in the current locale.
|
||||
*
|
||||
* (However, it's also deprecated; we really ought to be
|
||||
* using a GTKIMContext.)
|
||||
*
|
||||
* So we use the standard C library function mbstowcs() to
|
||||
* convert from the current locale into Unicode; from there
|
||||
* we can convert to whatever PuTTY is currently working in.
|
||||
@ -1136,6 +1153,14 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if GTK_CHECK_VERSION(2,0,0)
|
||||
void input_method_commit_event(GtkIMContext *imc, gchar *str, gpointer data)
|
||||
{
|
||||
struct gui_data *inst = (struct gui_data *)data;
|
||||
lpage_send(inst->ldisc, CS_UTF8, str, strlen(str), 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
gboolean button_internal(struct gui_data *inst, guint32 timestamp,
|
||||
GdkEventType type, guint ebutton, guint state,
|
||||
gdouble ex, gdouble ey)
|
||||
@ -2328,6 +2353,17 @@ void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,
|
||||
x*inst->font_width+inst->window_border,
|
||||
y*inst->font_height+inst->window_border,
|
||||
len*widefactor*inst->font_width, inst->font_height);
|
||||
|
||||
#if GTK_CHECK_VERSION(2,0,0)
|
||||
{
|
||||
GdkRectangle cursorrect;
|
||||
cursorrect.x = x*inst->font_width+inst->window_border;
|
||||
cursorrect.y = y*inst->font_height+inst->window_border;
|
||||
cursorrect.width = len*widefactor*inst->font_width;
|
||||
cursorrect.height = inst->font_height;
|
||||
gtk_im_context_set_cursor_location(inst->imc, &cursorrect);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
GdkCursor *make_mouse_ptr(struct gui_data *inst, int cursor_val)
|
||||
@ -3446,6 +3482,8 @@ int pt_main(int argc, char **argv)
|
||||
extern int cfgbox(Conf *conf);
|
||||
struct gui_data *inst;
|
||||
|
||||
setlocale(LC_CTYPE, "");
|
||||
|
||||
/*
|
||||
* Create an instance structure and initialise to zeroes
|
||||
*/
|
||||
@ -3507,6 +3545,10 @@ int pt_main(int argc, char **argv)
|
||||
|
||||
inst->area = gtk_drawing_area_new();
|
||||
|
||||
#if GTK_CHECK_VERSION(2,0,0)
|
||||
inst->imc = gtk_im_multicontext_new();
|
||||
#endif
|
||||
|
||||
setup_fonts_ucs(inst);
|
||||
init_cutbuffers();
|
||||
|
||||
@ -3597,6 +3639,10 @@ int pt_main(int argc, char **argv)
|
||||
GTK_SIGNAL_FUNC(selection_get), inst);
|
||||
gtk_signal_connect(GTK_OBJECT(inst->area), "selection_clear_event",
|
||||
GTK_SIGNAL_FUNC(selection_clear), inst);
|
||||
#if GTK_CHECK_VERSION(2,0,0)
|
||||
g_signal_connect(G_OBJECT(inst->imc), "commit",
|
||||
G_CALLBACK(input_method_commit_event), inst);
|
||||
#endif
|
||||
if (conf_get_int(inst->conf, CONF_scrollbar))
|
||||
gtk_signal_connect(GTK_OBJECT(inst->sbar_adjust), "value_changed",
|
||||
GTK_SIGNAL_FUNC(scrollbar_moved), inst);
|
||||
|
@ -29,7 +29,6 @@ int mb_to_wc(int codepage, int flags, const char *mbstr, int mblen,
|
||||
mbstate_t state;
|
||||
|
||||
memset(&state, 0, sizeof state);
|
||||
setlocale(LC_CTYPE, "");
|
||||
|
||||
while (mblen > 0) {
|
||||
size_t i = mbrtowc(wcstr+n, mbstr, (size_t)mblen, &state);
|
||||
@ -40,8 +39,6 @@ int mb_to_wc(int codepage, int flags, const char *mbstr, int mblen,
|
||||
mblen -= i;
|
||||
}
|
||||
|
||||
setlocale(LC_CTYPE, "C");
|
||||
|
||||
return n;
|
||||
} else if (codepage == CS_NONE) {
|
||||
int n = 0;
|
||||
@ -73,7 +70,6 @@ int wc_to_mb(int codepage, int flags, const wchar_t *wcstr, int wclen,
|
||||
int n = 0;
|
||||
|
||||
memset(&state, 0, sizeof state);
|
||||
setlocale(LC_CTYPE, "");
|
||||
|
||||
while (wclen > 0) {
|
||||
int i = wcrtomb(output, wcstr[0], &state);
|
||||
@ -85,8 +81,6 @@ int wc_to_mb(int codepage, int flags, const wchar_t *wcstr, int wclen,
|
||||
wclen--;
|
||||
}
|
||||
|
||||
setlocale(LC_CTYPE, "C");
|
||||
|
||||
return n;
|
||||
} else if (codepage == CS_NONE) {
|
||||
int n = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user