X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=modules%2Finput%2Fgtkimcontextxim.c;h=1a32e5abfd5671efb4bed7e9e354567381c964ec;hb=9d0febc9a64a5bfb0fcfc3a88de4757f6c1ff090;hp=030440270bb97cdd832f02a593a6cc79b6cf0132;hpb=54b45a19b92629605abdcc6d14c1b1c3a1e941af;p=~andy%2Fgtk diff --git a/modules/input/gtkimcontextxim.c b/modules/input/gtkimcontextxim.c index 030440270..1a32e5abf 100644 --- a/modules/input/gtkimcontextxim.c +++ b/modules/input/gtkimcontextxim.c @@ -12,22 +12,18 @@ * 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ -#include +#include "config.h" #include "locale.h" #include #include -#include "gtk/gtkintl.h" -#include "gtk/gtklabel.h" -#include "gtk/gtksignal.h" -#include "gtk/gtkwindow.h" #include "gtkimcontextxim.h" +#include "gtk/gtkintl.h" + typedef struct _StatusWindow StatusWindow; typedef struct _GtkXIMInfo GtkXIMInfo; @@ -86,6 +82,7 @@ struct _GtkXIMInfo GtkSettings *settings; gulong status_set; gulong preedit_set; + gulong display_closed_cb; XIMStyles *xim_styles; GSList *ics; @@ -143,11 +140,15 @@ static void xim_destroy_callback (XIM xim, XPointer call_data); static XIC gtk_im_context_xim_get_ic (GtkIMContextXIM *context_xim); +static void xim_info_display_closed (GdkDisplay *display, + gboolean is_error, + GtkXIMInfo *info); + static GObjectClass *parent_class; GType gtk_type_im_context_xim = 0; -GSList *open_ims = NULL; +static GSList *open_ims = NULL; /* List of status windows for different toplevels */ static GSList *status_windows = NULL; @@ -155,7 +156,7 @@ static GSList *status_windows = NULL; void gtk_im_context_xim_register_type (GTypeModule *type_module) { - static const GTypeInfo im_context_xim_info = + const GTypeInfo im_context_xim_info = { sizeof (GtkIMContextXIMClass), (GBaseInitFunc) NULL, @@ -307,6 +308,7 @@ setup_im (GtkXIMInfo *info) { XIMValuesList *ic_values = NULL; XIMCallback im_destroy_callback; + GdkDisplay *display; if (info->im == NULL) return; @@ -323,25 +325,6 @@ setup_im (GtkXIMInfo *info) NULL); info->settings = gtk_settings_get_for_screen (info->screen); - - if (!g_object_class_find_property (G_OBJECT_GET_CLASS (info->settings), - "gtk-im-preedit-style")) - gtk_settings_install_property (g_param_spec_enum ("gtk-im-preedit-style", - P_("IM Preedit style"), - P_("How to draw the input method preedit string"), - GTK_TYPE_IM_PREEDIT_STYLE, - GTK_IM_PREEDIT_CALLBACK, - G_PARAM_READWRITE)); - - if (!g_object_class_find_property (G_OBJECT_GET_CLASS (info->settings), - "gtk-im-status-style")) - gtk_settings_install_property (g_param_spec_enum ("gtk-im-status-style", - P_("IM Status style"), - P_("How to draw the input method statusbar"), - GTK_TYPE_IM_STATUS_STYLE, - GTK_IM_STATUS_CALLBACK, - G_PARAM_READWRITE)); - info->status_set = g_signal_connect_swapped (info->settings, "notify::gtk-im-status-style", G_CALLBACK (status_style_change), @@ -376,6 +359,10 @@ setup_im (GtkXIMInfo *info) status_style_change (info); preedit_style_change (info); + + display = gdk_screen_get_display (info->screen); + info->display_closed_cb = g_signal_connect (display, "closed", + G_CALLBACK (xim_info_display_closed), info); } static void @@ -394,12 +381,16 @@ xim_info_display_closed (GdkDisplay *display, set_ic_client_window (tmp_list->data, NULL); g_slist_free (ics); - - g_signal_handler_disconnect (info->settings, info->status_set); - g_signal_handler_disconnect (info->settings, info->preedit_set); - - XFree (info->xim_styles->supported_styles); - XFree (info->xim_styles); + + if (info->status_set) + g_signal_handler_disconnect (info->settings, info->status_set); + if (info->preedit_set) + g_signal_handler_disconnect (info->settings, info->preedit_set); + if (info->display_closed_cb) + g_signal_handler_disconnect (display, info->display_closed_cb); + + if (info->xim_styles) + XFree (info->xim_styles); g_free (info->locale); if (info->im) @@ -455,9 +446,6 @@ xim_info_try_im (GtkXIMInfo *info) return; } setup_im (info); - - g_signal_connect (display, "closed", - G_CALLBACK (xim_info_display_closed), info); } } @@ -471,7 +459,9 @@ xim_destroy_callback (XIM xim, info->im = NULL; g_signal_handler_disconnect (info->settings, info->status_set); + info->status_set = 0; g_signal_handler_disconnect (info->settings, info->preedit_set); + info->preedit_set = 0; reinitialize_all_ics (info); xim_info_try_im (info); @@ -484,7 +474,7 @@ get_im (GdkWindow *client_window, { GSList *tmp_list; GtkXIMInfo *info; - GdkScreen *screen = gdk_drawable_get_screen (client_window); + GdkScreen *screen = gdk_window_get_screen (client_window); info = NULL; tmp_list = open_ims; @@ -520,6 +510,7 @@ get_im (GdkWindow *client_window, info->settings = NULL; info->preedit_set = 0; info->status_set = 0; + info->display_closed_cb = 0; info->ics = NULL; info->reconnecting = FALSE; info->im = NULL; @@ -565,6 +556,30 @@ gtk_im_context_xim_finalize (GObject *obj) context_xim->finalizing = TRUE; + if (context_xim->im_info && !context_xim->im_info->ics->next) + { + if (context_xim->im_info->reconnecting) + { + GdkDisplay *display; + + display = gdk_screen_get_display (context_xim->im_info->screen); + XUnregisterIMInstantiateCallback (GDK_DISPLAY_XDISPLAY (display), + NULL, NULL, NULL, + xim_instantiate_callback, + (XPointer)context_xim->im_info); + } + else if (context_xim->im_info->im) + { + XIMCallback im_destroy_callback; + + im_destroy_callback.client_data = NULL; + im_destroy_callback.callback = NULL; + XSetIMValues (context_xim->im_info->im, + XNDestroyCallback, &im_destroy_callback, + NULL); + } + } + set_ic_client_window (context_xim, NULL); g_free (context_xim->locale); @@ -586,7 +601,7 @@ reinitialize_ic (GtkIMContextXIM *context_xim) { context_xim->preedit_length = 0; if (!context_xim->finalizing) - g_signal_emit_by_name (context_xim, "preedit_changed"); + g_signal_emit_by_name (context_xim, "preedit-changed"); } } /* @@ -633,6 +648,8 @@ gtk_im_context_xim_new (void) GtkIMContextXIM *result; const gchar *charset; + if (!GDK_IS_X11_DISPLAY(gdk_display_get_default())) + return NULL; result = g_object_new (GTK_TYPE_IM_CONTEXT_XIM, NULL); result->locale = g_strdup (setlocale (LC_CTYPE, NULL)); @@ -680,7 +697,7 @@ gtk_im_context_xim_filter_keypress (GtkIMContext *context, KeySym keysym; Status status; gboolean result = FALSE; - GdkWindow *root_window = gdk_screen_get_root_window (gdk_drawable_get_screen (event->window)); + GdkWindow *root_window = gdk_screen_get_root_window (gdk_window_get_screen (event->window)); XKeyPressedEvent xevent; @@ -690,9 +707,9 @@ gtk_im_context_xim_filter_keypress (GtkIMContext *context, xevent.type = (event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease; xevent.serial = 0; /* hope it doesn't matter */ xevent.send_event = event->send_event; - xevent.display = GDK_DRAWABLE_XDISPLAY (event->window); - xevent.window = GDK_DRAWABLE_XID (event->window); - xevent.root = GDK_DRAWABLE_XID (root_window); + xevent.display = GDK_WINDOW_XDISPLAY (event->window); + xevent.window = GDK_WINDOW_XID (event->window); + xevent.root = GDK_WINDOW_XID (root_window); xevent.subwindow = xevent.window; xevent.time = event->time; xevent.x = xevent.x_root = 0; @@ -701,9 +718,13 @@ gtk_im_context_xim_filter_keypress (GtkIMContext *context, xevent.keycode = event->hardware_keycode; xevent.same_screen = True; - if (XFilterEvent ((XEvent *)&xevent, GDK_DRAWABLE_XID (context_xim->client_window))) + if (XFilterEvent ((XEvent *)&xevent, GDK_WINDOW_XID (context_xim->client_window))) return TRUE; + if (event->state & + (gtk_accelerator_get_default_mod_mask () & ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK))) + return FALSE; + again: if (ic) num_bytes = XmbLookupString (ic, &xevent, buffer, buffer_size, &keysym, &status); @@ -806,11 +827,11 @@ gtk_im_context_xim_set_cursor_location (GtkIMContext *context, return; spot.x = area->x; - spot.y = area->y; + spot.y = area->y + area->height; preedit_attr = XVaCreateNestedList (0, XNSpotLocation, &spot, - 0); + NULL); XSetICValues (ic, XNPreeditAttributes, preedit_attr, NULL); @@ -857,7 +878,7 @@ gtk_im_context_xim_reset (GtkIMContext *context) preedit_attr = XVaCreateNestedList(0, XNPreeditState, &preedit_state, - 0); + NULL); if (!XGetICValues(ic, XNPreeditAttributes, preedit_attr, NULL)) @@ -869,7 +890,7 @@ gtk_im_context_xim_reset (GtkIMContext *context) preedit_attr = XVaCreateNestedList(0, XNPreeditState, preedit_state, - 0); + NULL); if (have_preedit_state) XSetICValues(ic, XNPreeditAttributes, preedit_attr, @@ -890,7 +911,7 @@ gtk_im_context_xim_reset (GtkIMContext *context) if (context_xim->preedit_length) { context_xim->preedit_length = 0; - g_signal_emit_by_name (context, "preedit_changed"); + g_signal_emit_by_name (context, "preedit-changed"); } XFree (result); @@ -992,7 +1013,7 @@ preedit_start_callback (XIC xic, GtkIMContextXIM *context_xim = GTK_IM_CONTEXT_XIM (context); if (!context_xim->finalizing) - g_signal_emit_by_name (context, "preedit_start"); + g_signal_emit_by_name (context, "preedit-start"); return -1; /* No length limit */ } @@ -1009,11 +1030,11 @@ preedit_done_callback (XIC xic, { context_xim->preedit_length = 0; if (!context_xim->finalizing) - g_signal_emit_by_name (context_xim, "preedit_changed"); + g_signal_emit_by_name (context_xim, "preedit-changed"); } if (!context_xim->finalizing) - g_signal_emit_by_name (context, "preedit_end"); + g_signal_emit_by_name (context, "preedit-end"); } static gint @@ -1135,11 +1156,10 @@ preedit_draw_callback (XIC xic, context->preedit_length += diff; - if (new_text) - g_free (new_text); + g_free (new_text); if (!context->finalizing) - g_signal_emit_by_name (context, "preedit_changed"); + g_signal_emit_by_name (context, "preedit-changed"); } @@ -1154,7 +1174,7 @@ preedit_caret_callback (XIC xic, { context->preedit_cursor = call_data->position; if (!context->finalizing) - g_signal_emit_by_name (context, "preedit_changed"); + g_signal_emit_by_name (context, "preedit-changed"); } else { @@ -1414,7 +1434,7 @@ gtk_im_context_xim_get_ic (GtkIMContextXIM *context_xim) xic = XCreateIC (context_xim->im_info->im, XNInputStyle, im_style, - XNClientWindow, GDK_DRAWABLE_XID (context_xim->client_window), + XNClientWindow, GDK_WINDOW_XID (context_xim->client_window), name1, list1, name2, list2, NULL); @@ -1508,7 +1528,7 @@ claim_status_window (GtkIMContextXIM *context_xim) if (!context_xim->status_window && context_xim->client_widget) { GtkWidget *toplevel = gtk_widget_get_toplevel (context_xim->client_widget); - if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel)) + if (toplevel && gtk_widget_is_toplevel (toplevel)) { StatusWindow *status_window = status_window_get (toplevel); @@ -1542,7 +1562,7 @@ update_in_toplevel (GtkIMContextXIM *context_xim) { GtkWidget *toplevel = gtk_widget_get_toplevel (context_xim->client_widget); - context_xim->in_toplevel = (toplevel && GTK_WIDGET_TOPLEVEL (toplevel)); + context_xim->in_toplevel = (toplevel && gtk_widget_is_toplevel (toplevel)); } else context_xim->in_toplevel = FALSE; @@ -1653,10 +1673,12 @@ on_status_toplevel_configure (GtkWidget *toplevel, if (status_window->window) { height = gdk_screen_get_height (gtk_widget_get_screen (toplevel)); - - gdk_window_get_frame_extents (toplevel->window, &rect); - gtk_widget_size_request (status_window->window, &requisition); - + + gdk_window_get_frame_extents (gtk_widget_get_window (toplevel), + &rect); + gtk_widget_get_preferred_size ( (status_window->window), + &requisition, NULL); + if (rect.y + rect.height + requisition.height < height) y = rect.y + rect.height; else @@ -1715,7 +1737,7 @@ status_window_get (GtkWidget *toplevel) g_signal_connect (toplevel, "destroy", G_CALLBACK (on_status_toplevel_destroy), status_window); - g_signal_connect (toplevel, "configure_event", + g_signal_connect (toplevel, "configure-event", G_CALLBACK (on_status_toplevel_configure), status_window); g_signal_connect (toplevel, "notify::screen", @@ -1730,38 +1752,29 @@ status_window_get (GtkWidget *toplevel) /* Draw the background (normally white) and border for the status window */ static gboolean -on_status_window_expose_event (GtkWidget *widget, - GdkEventExpose *event) +on_status_window_draw (GtkWidget *widget, + cairo_t *cr) { - gdk_draw_rectangle (widget->window, - widget->style->base_gc [GTK_STATE_NORMAL], - TRUE, - 0, 0, - widget->allocation.width, widget->allocation.height); - gdk_draw_rectangle (widget->window, - widget->style->text_gc [GTK_STATE_NORMAL], - FALSE, - 0, 0, - widget->allocation.width - 1, widget->allocation.height - 1); + GtkStyleContext *style; + GdkRGBA color; - return FALSE; -} + style = gtk_widget_get_style_context (widget); -/* We watch the ::style-set signal for our label widget - * and use that to change it's foreground color to match - * the 'text' color of the toplevel window. The text/base - * pair of colors might be reversed from the fg/bg pair - * that are normally used for labels. - */ -static void -on_status_window_style_set (GtkWidget *toplevel, - GtkStyle *previous_style, - GtkWidget *label) -{ - gint i; - - for (i = 0; i < 5; i++) - gtk_widget_modify_fg (label, i, &toplevel->style->text[i]); + gtk_style_context_get_background_color (style, 0, &color); + gdk_cairo_set_source_rgba (cr, &color); + cairo_paint (cr); + + gtk_style_context_get_color (style, 0, &color); + gdk_cairo_set_source_rgba (cr, &color); + cairo_paint (cr); + + cairo_rectangle (cr, + 0, 0, + gtk_widget_get_allocated_width (widget) - 1, + gtk_widget_get_allocated_height (widget) - 1); + cairo_fill (cr); + + return FALSE; } /* Creates the widgets for the status window; called when we @@ -1780,15 +1793,13 @@ status_window_make_window (StatusWindow *status_window) gtk_widget_set_app_paintable (window, TRUE); status_label = gtk_label_new (""); - gtk_misc_set_padding (GTK_MISC (status_label), 1, 1); + g_object_set (status_label, "margin", 1, NULL); gtk_widget_show (status_label); - g_signal_connect (window, "style_set", - G_CALLBACK (on_status_window_style_set), status_label); gtk_container_add (GTK_CONTAINER (window), status_label); - g_signal_connect (window, "expose_event", - G_CALLBACK (on_status_window_expose_event), NULL); + g_signal_connect (window, "draw", + G_CALLBACK (on_status_window_draw), NULL); gtk_window_set_screen (GTK_WINDOW (status_window->window), gtk_widget_get_screen (status_window->toplevel)); @@ -1810,7 +1821,7 @@ status_window_set_text (StatusWindow *status_window, if (!status_window->window) status_window_make_window (status_window); - label = GTK_BIN (status_window->window)->child; + label = gtk_bin_get_child (GTK_BIN (status_window->window)); gtk_label_set_text (GTK_LABEL (label), text); gtk_widget_show (status_window->window); @@ -1833,4 +1844,13 @@ gtk_im_context_xim_shutdown (void) { while (status_windows) status_window_free (status_windows->data); + + while (open_ims) + { + GtkXIMInfo *info = open_ims->data; + GdkDisplay *display = gdk_screen_get_display (info->screen); + + xim_info_display_closed (display, FALSE, info); + open_ims = g_slist_remove_link (open_ims, open_ims); + } }