⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gtkimcontextxim.c

📁 linux下电话本所依赖的一些图形库
💻 C
📖 第 1 页 / 共 4 页
字号:
  if (!context_xim->ic)    {      const char *name1 = NULL;      XVaNestedList list1 = NULL;      const char *name2 = NULL;      XVaNestedList list2 = NULL;      XIMStyle im_style = 0;      XIC xic = NULL;      if (context_xim->use_preedit &&	  (context_xim->im_info->style & PREEDIT_MASK) == XIMPreeditCallbacks)	{	  im_style |= XIMPreeditCallbacks;	  name1 = XNPreeditAttributes;	  list1 = set_preedit_callback (context_xim);	}      else if ((context_xim->im_info->style & PREEDIT_MASK) == XIMPreeditNone)	im_style |= XIMPreeditNone;      else	im_style |= XIMPreeditNothing;      if ((context_xim->im_info->style & STATUS_MASK) == XIMStatusCallbacks)	{	  im_style |= XIMStatusCallbacks;	  if (name1 == NULL)	    {	      name1 = XNStatusAttributes;	      list1 = set_status_callback (context_xim);	    }	  else	    {	      name2 = XNStatusAttributes;	      list2 = set_status_callback (context_xim);	    }	}      else if ((context_xim->im_info->style & STATUS_MASK) == XIMStatusNone)	im_style |= XIMStatusNone;      else	im_style |= XIMStatusNothing;      xic = XCreateIC (context_xim->im_info->im,		       XNInputStyle, im_style,		       XNClientWindow, GDK_DRAWABLE_XID (context_xim->client_window),		       name1, list1,		       name2, list2,		       NULL);      if (list1)	XFree (list1);      if (list2)	XFree (list2);      if (xic)	{	  /* Don't filter key released events with XFilterEvents unless	   * input methods ask for. This is a workaround for Solaris input	   * method bug in C and European locales. It doubles each key	   * stroke if both key pressed and released events are filtered.	   * (bugzilla #81759)	   */	  gulong mask = 0xaaaaaaaa;	  XGetICValues (xic,			XNFilterEvents, &mask,			NULL);	  context_xim->filter_key_release = (mask & KeyReleaseMask) != 0;	  set_string_conversion_callback (context_xim, xic);	}            context_xim->ic = xic;      update_status_window (context_xim);            if (xic && context_xim->has_focus)	XSetICFocus (xic);    }  return context_xim->ic;}/***************************************************************** * Status Window handling * * A status window is a small window attached to the toplevel * that is used to display information to the user about the * current input operation. * * We claim the toplevel's status window for an input context if: * * A) The input context has a toplevel * B) The input context has the focus * C) The input context has an XIC associated with it * * Tracking A) and C) is pretty reliable since we * compute A) and create the XIC for C) ourselves. * For B) we basically have to depend on our callers * calling ::focus-in and ::focus-out at the right time. * * The toplevel is computed by walking up the GdkWindow * hierarchy from context->client_window until we find a * window that is owned by some widget, and then calling * gtk_widget_get_toplevel() on that widget. This should * handle both cases where we might have GdkWindows without widgets, * and cases where GtkWidgets have strange window hierarchies * (like a torn off GtkHandleBox.) * * The status window is visible if and only if there is text * for it; whenever a new GtkIMContextXIM claims the status * window, we blank out any existing text. We actually only * create a GtkWindow for the status window the first time * it is shown; this is an important optimization when we are * using XIM with something like a simple compose-key input * method that never needs a status window. *****************************************************************//* Called when we no longer need a status window*/static voiddisclaim_status_window (GtkIMContextXIM *context_xim){  if (context_xim->status_window)    {      g_assert (context_xim->status_window->context == context_xim);      status_window_set_text (context_xim->status_window, "");            context_xim->status_window->context = NULL;      context_xim->status_window = NULL;    }}/* Called when we need a status window */static voidclaim_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))	{	  StatusWindow *status_window = status_window_get (toplevel);	  if (status_window->context)	    disclaim_status_window (status_window->context);	  status_window->context = context_xim;	  context_xim->status_window = status_window;	}    }}/* Basic call made whenever something changed that might cause * us to need, or not to need a status window. */static voidupdate_status_window (GtkIMContextXIM *context_xim){  if (context_xim->ic && context_xim->in_toplevel && context_xim->has_focus)    claim_status_window (context_xim);  else    disclaim_status_window (context_xim);}/* Updates the in_toplevel flag for @context_xim */static voidupdate_in_toplevel (GtkIMContextXIM *context_xim){  if (context_xim->client_widget)    {      GtkWidget *toplevel = gtk_widget_get_toplevel (context_xim->client_widget);            context_xim->in_toplevel = (toplevel && GTK_WIDGET_TOPLEVEL (toplevel));    }  else    context_xim->in_toplevel = FALSE;  /* Some paranoia, in case we don't get a focus out */  if (!context_xim->in_toplevel)    context_xim->has_focus = FALSE;    update_status_window (context_xim);}/* Callback when @widget's toplevel changes. It will always * change from NULL to a window, or a window to NULL; * we use that intermediate NULL state to make sure * that we disclaim the toplevel status window for the old * window. */static voidon_client_widget_hierarchy_changed (GtkWidget       *widget,				    GtkWidget       *old_toplevel,				    GtkIMContextXIM *context_xim){  update_in_toplevel (context_xim);}/* Finds the GtkWidget that owns the window, or if none, the * widget owning the nearest parent that has a widget. */static GtkWidget *widget_for_window (GdkWindow *window){  while (window)    {      gpointer user_data;      gdk_window_get_user_data (window, &user_data);      if (user_data)	return user_data;      window = gdk_window_get_parent (window);    }  return NULL;}/* Called when context_xim->client_window changes; takes care of * removing and/or setting up our watches for the toplevel */static voidupdate_client_widget (GtkIMContextXIM *context_xim){  GtkWidget *new_client_widget = widget_for_window (context_xim->client_window);  if (new_client_widget != context_xim->client_widget)    {      if (context_xim->client_widget)	{	  g_signal_handlers_disconnect_by_func (context_xim->client_widget,						G_CALLBACK (on_client_widget_hierarchy_changed),						context_xim);	}      context_xim->client_widget = new_client_widget;      if (context_xim->client_widget)	{	  g_signal_connect (context_xim->client_widget, "hierarchy-changed",			    G_CALLBACK (on_client_widget_hierarchy_changed),			    context_xim);	}      update_in_toplevel (context_xim);    }}/* Called when the toplevel is destroyed; frees the status window */static voidon_status_toplevel_destroy (GtkWidget    *toplevel,			    StatusWindow *status_window){  status_window_free (status_window);}/* Called when the screen for the toplevel changes; updates the * screen for the status window to match. */static voidon_status_toplevel_notify_screen (GtkWindow    *toplevel,				  GParamSpec   *pspec,				  StatusWindow *status_window){  if (status_window->window)    gtk_window_set_screen (GTK_WINDOW (status_window->window),			   gtk_widget_get_screen (GTK_WIDGET (toplevel)));}/* Called when the toplevel window is moved; updates the position of * the status window to follow it. */static gbooleanon_status_toplevel_configure (GtkWidget         *toplevel,			      GdkEventConfigure *event,			      StatusWindow      *status_window){  GdkRectangle rect;  GtkRequisition requisition;  gint y;  gint height;  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);            if (rect.y + rect.height + requisition.height < height)	y = rect.y + rect.height;      else	y = height - requisition.height;            gtk_window_move (GTK_WINDOW (status_window->window), rect.x, y);    }  return FALSE;}/* Frees a status window and removes its link from the status_windows list */static voidstatus_window_free (StatusWindow *status_window){  status_windows = g_slist_remove (status_windows, status_window);  if (status_window->context)    status_window->context->status_window = NULL;   g_signal_handlers_disconnect_by_func (status_window->toplevel,					G_CALLBACK (on_status_toplevel_destroy),					status_window);  g_signal_handlers_disconnect_by_func (status_window->toplevel,					G_CALLBACK (on_status_toplevel_notify_screen),					status_window);  g_signal_handlers_disconnect_by_func (status_window->toplevel,					G_CALLBACK (on_status_toplevel_configure),					status_window);  if (status_window->window)    gtk_widget_destroy (status_window->window);    g_object_set_data (G_OBJECT (status_window->toplevel), "gtk-im-xim-status-window", NULL);   g_free (status_window);}/* Finds the status window object for a toplevel, creating it if necessary. */static StatusWindow *status_window_get (GtkWidget *toplevel){  StatusWindow *status_window;  status_window = g_object_get_data (G_OBJECT (toplevel), "gtk-im-xim-status-window");  if (status_window)    return status_window;    status_window = g_new0 (StatusWindow, 1);  status_window->toplevel = toplevel;  status_windows = g_slist_prepend (status_windows, status_window);  g_signal_connect (toplevel, "destroy",		    G_CALLBACK (on_status_toplevel_destroy),		    status_window);  g_signal_connect (toplevel, "configure_event",		    G_CALLBACK (on_status_toplevel_configure),		    status_window);  g_signal_connect (toplevel, "notify::screen",		    G_CALLBACK (on_status_toplevel_notify_screen),		    status_window);    g_object_set_data (G_OBJECT (toplevel), "gtk-im-xim-status-window", status_window);  return status_window;}/* Draw the background (normally white) and border for the status window */static gbooleanon_status_window_expose_event (GtkWidget      *widget,			       GdkEventExpose *event){  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);  return FALSE;}/* 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 voidon_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]);}/* Creates the widgets for the status window; called when we * first need to show text for the status window. */static voidstatus_window_make_window (StatusWindow *status_window){  GtkWidget *window;  GtkWidget *status_label;    status_window->window = gtk_window_new (GTK_WINDOW_POPUP);  window = status_window->window;  gtk_window_set_resizable (GTK_WINDOW (window), FALSE);  gtk_widget_set_app_paintable (window, TRUE);  status_label = gtk_label_new ("");  gtk_misc_set_padding (GTK_MISC (status_label), 1, 1);  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);    gtk_window_set_screen (GTK_WINDOW (status_window->window),			 gtk_widget_get_screen (status_window->toplevel));  on_status_toplevel_configure (status_window->toplevel, NULL, status_window);}/* Updates the text in the status window, hiding or * showing the window as necessary. */static voidstatus_window_set_text (StatusWindow *status_window,			const gchar  *text){  if (text[0])    {      GtkWidget *label;            if (!status_window->window)	status_window_make_window (status_window);            label = GTK_BIN (status_window->window)->child;      gtk_label_set_text (GTK_LABEL (label), text);        gtk_widget_show (status_window->window);    }  else    {      if (status_window->window)	gtk_widget_hide (status_window->window);    }}/** * gtk_im_context_xim_shutdown: *  * Destroys all the status windows that are kept by the XIM contexts.  This * function should only be called by the XIM module exit routine. **/voidgtk_im_context_xim_shutdown (void){  while (status_windows)    status_window_free (status_windows->data);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -