]> code.delx.au - gnu-emacs/blobdiff - src/gtkutil.c
(set_window_buffer): Always preserve current-buffer.
[gnu-emacs] / src / gtkutil.c
index fd0fbf778b2efa5b0a45fe806a78b78d70bc10ba..140796a015ef558383578f94a2a8a4a90c43c69f 100644 (file)
@@ -17,7 +17,7 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#include "config.h"
+#include <config.h>
 
 #ifdef USE_GTK
 #include <string.h>
 
 #ifdef USE_GTK
 #include <string.h>
@@ -36,6 +36,9 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "coding.h"
 #include <gdk/gdkkeysyms.h>
 
 #include "coding.h"
 #include <gdk/gdkkeysyms.h>
 
+#ifdef HAVE_XFT
+#include <X11/Xft/Xft.h>
+#endif
 
 #define FRAME_TOTAL_PIXEL_HEIGHT(f) \
   (FRAME_PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f))
 
 #define FRAME_TOTAL_PIXEL_HEIGHT(f) \
   (FRAME_PIXEL_HEIGHT (f) + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f))
@@ -909,8 +912,10 @@ xg_create_frame_widgets (f)
   gtk_widget_modify_style (wfixed, style);
 
   /* GTK does not set any border, and they look bad with GTK.  */
   gtk_widget_modify_style (wfixed, style);
 
   /* GTK does not set any border, and they look bad with GTK.  */
+  /* That they look bad is no excuse for imposing this here.  --Stef
+     It should be done by providing the proper default in Fx_create_Frame.
   f->border_width = 0;
   f->border_width = 0;
-  f->internal_border_width = 0;
+  f->internal_border_width = 0; */
 
   UNBLOCK_INPUT;
 
 
   UNBLOCK_INPUT;
 
@@ -1023,7 +1028,7 @@ x_wm_set_size_hint (f, flags, user_position)
 }
 
 /* Change background color of a frame.
 }
 
 /* Change background color of a frame.
-   Since GTK uses the background colour to clear the window, we must
+   Since GTK uses the background color to clear the window, we must
    keep the GTK and X colors in sync.
    F is the frame to change,
    BG is the pixel value to change to.  */
    keep the GTK and X colors in sync.
    F is the frame to change,
    BG is the pixel value to change to.  */
@@ -1263,12 +1268,12 @@ xg_uses_old_file_dialog ()
 }
 
 
 }
 
 
-/* Function that is called when the file dialog pops down.
+/* Function that is called when the file or font dialogs pop down.
    W is the dialog widget, RESPONSE is the response code.
    USER_DATA is what we passed in to g_signal_connect (pointer to int).  */
 
 static void
    W is the dialog widget, RESPONSE is the response code.
    USER_DATA is what we passed in to g_signal_connect (pointer to int).  */
 
 static void
-xg_file_response_cb (w,
+xg_dialog_response_cb (w,
                      response,
                      user_data)
      GtkDialog *w;
                      response,
                      user_data)
      GtkDialog *w;
@@ -1283,7 +1288,7 @@ xg_file_response_cb (w,
 /*  Destroy the dialog.  This makes it pop down.  */
 
 static Lisp_Object
 /*  Destroy the dialog.  This makes it pop down.  */
 
 static Lisp_Object
-pop_down_file_dialog (arg)
+pop_down_dialog (arg)
      Lisp_Object arg;
 {
   struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
      Lisp_Object arg;
 {
   struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
@@ -1593,7 +1598,7 @@ xg_get_file_name (f, prompt, default_filename, mustmatch_p, only_dir_p)
 
   g_signal_connect (G_OBJECT (w),
                     "response",
 
   g_signal_connect (G_OBJECT (w),
                     "response",
-                    G_CALLBACK (xg_file_response_cb),
+                    G_CALLBACK (xg_dialog_response_cb),
                     &filesel_done);
 
   /* Don't destroy the widget if closed by the window manager close button.  */
                     &filesel_done);
 
   /* Don't destroy the widget if closed by the window manager close button.  */
@@ -1601,7 +1606,7 @@ xg_get_file_name (f, prompt, default_filename, mustmatch_p, only_dir_p)
 
   gtk_widget_show (w);
 
 
   gtk_widget_show (w);
 
-  record_unwind_protect (pop_down_file_dialog, make_save_value (w, 0));
+  record_unwind_protect (pop_down_dialog, make_save_value (w, 0));
   while (! filesel_done)
     {
       x_menu_wait_for_event (0);
   while (! filesel_done)
     {
       x_menu_wait_for_event (0);
@@ -1620,14 +1625,80 @@ xg_get_file_name (f, prompt, default_filename, mustmatch_p, only_dir_p)
   return fn;
 }
 
   return fn;
 }
 
+#ifdef HAVE_FREETYPE
+/* Pop up a GTK font selector and return the name of the font the user
+   selects, as a C string.  The returned font name follows GTK's own
+   format:
+
+   `FAMILY [VALUE1 VALUE2] SIZE'
+
+   This can be parsed using font_parse_fcname in font.c.
+   DEFAULT_NAME, if non-zero, is the default font name.  */
+
+char *
+xg_get_font_name (f, default_name)
+     FRAME_PTR f;
+     char *default_name;
+{
+  GtkWidget *w = 0;
+  int count = SPECPDL_INDEX ();
+  char *fontname = NULL;
+  int done = 0;
+
+#if defined (HAVE_GTK_AND_PTHREAD) && defined (__SIGRTMIN)
+  sigblock (sigmask (__SIGRTMIN));
+#endif /* HAVE_GTK_AND_PTHREAD */
+
+  w = gtk_font_selection_dialog_new ("Pick a font");
+  if (default_name)
+    gtk_font_selection_dialog_set_font_name (GTK_FONT_SELECTION_DIALOG (w),
+                                             default_name);
+
+  xg_set_screen (w, f);
+  gtk_widget_set_name (w, "emacs-fontdialog");
+  gtk_window_set_transient_for (GTK_WINDOW (w),
+                                GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)));
+  gtk_window_set_destroy_with_parent (GTK_WINDOW (w), TRUE);
+  gtk_window_set_modal (GTK_WINDOW (w), TRUE);
+
+  g_signal_connect (G_OBJECT (w), "response",
+                   G_CALLBACK (xg_dialog_response_cb), &done);
+
+  /* Don't destroy the widget if closed by the window manager close button.  */
+  g_signal_connect (G_OBJECT (w), "delete-event", G_CALLBACK (gtk_true), NULL);
+
+  gtk_widget_show (w);
+
+  record_unwind_protect (pop_down_dialog, make_save_value (w, 0));
+  while (!done)
+    {
+      x_menu_wait_for_event (0);
+      gtk_main_iteration ();
+    }
+
+#if defined (HAVE_GTK_AND_PTHREAD) && defined (__SIGRTMIN)
+  sigunblock (sigmask (__SIGRTMIN));
+#endif
+
+  if (done == GTK_RESPONSE_OK)
+    fontname = gtk_font_selection_dialog_get_font_name
+      ((GtkFontSelectionDialog *) w);
+
+  unbind_to (count, Qnil);
+
+  return fontname;
+}
+#endif /* HAVE_FREETYPE */
+
+
 \f
 /***********************************************************************
                        Menu functions.
  ***********************************************************************/
 
 \f
 /***********************************************************************
                        Menu functions.
  ***********************************************************************/
 
-/* The name of menu items that can be used for citomization.  Since GTK
+/* The name of menu items that can be used for customization.  Since GTK
    RC files are very crude and primitive, we have to set this on all
    RC files are very crude and primitive, we have to set this on all
-   menu item names so a user can easily cutomize menu items.  */
+   menu item names so a user can easily customize menu items.  */
 
 #define MENU_ITEM_NAME "emacs-menuitem"
 
 
 #define MENU_ITEM_NAME "emacs-menuitem"
 
@@ -2071,34 +2142,6 @@ xg_create_one_menuitem (item, f, select_cb, highlight_cb, cl_data, group)
   return w;
 }
 
   return w;
 }
 
-/* Callback called when keyboard traversal (started by x-menu-bar-open) ends.
-   WMENU is the menu for which traversal has been done.  DATA points to the
-   frame for WMENU.  We must release grabs, some bad interaction between GTK
-   and Emacs makes the menus keep the grabs.  */
-
-static void
-menu_nav_ended (wmenu, data)
-     GtkMenuShell *wmenu;
-     gpointer data;
-{
-  FRAME_PTR f = (FRAME_PTR) data;
-
-  if (FRAME_X_OUTPUT (f)->menubar_widget)
-    {
-      GtkMenuShell *w = GTK_MENU_SHELL (FRAME_X_OUTPUT (f)->menubar_widget);
-      Display *dpy = FRAME_X_DISPLAY (f);
-
-      BLOCK_INPUT;
-      gtk_menu_shell_deactivate (w);
-      gtk_menu_shell_deselect (w);
-
-      XUngrabKeyboard (dpy, CurrentTime);
-      XUngrabPointer (dpy, CurrentTime);
-      UNBLOCK_INPUT;
-    }
-}
-
-
 static GtkWidget *create_menus P_ ((widget_value *, FRAME_PTR, GCallback,
                                    GCallback, GCallback, int, int, int,
                                    GtkWidget *, xg_menu_cb_data *, char *));
 static GtkWidget *create_menus P_ ((widget_value *, FRAME_PTR, GCallback,
                                    GCallback, GCallback, int, int, int,
                                    GtkWidget *, xg_menu_cb_data *, char *));
@@ -2164,12 +2207,6 @@ create_menus (data, f, select_cb, deactivate_cb, highlight_cb,
       }
       else wmenu = gtk_menu_bar_new ();
 
       }
       else wmenu = gtk_menu_bar_new ();
 
-      /* Fix up grabs after keyboard traversal ends.  */
-      g_signal_connect (G_OBJECT (wmenu),
-                        "selection-done",
-                        G_CALLBACK (menu_nav_ended),
-                        f);
-
       /* Put cl_data on the top menu for easier access.  */
       cl_data = make_cl_data (cl_data, f, highlight_cb);
       g_object_set_data (G_OBJECT (wmenu), XG_FRAME_DATA, (gpointer)cl_data);
       /* Put cl_data on the top menu for easier access.  */
       cl_data = make_cl_data (cl_data, f, highlight_cb);
       g_object_set_data (G_OBJECT (wmenu), XG_FRAME_DATA, (gpointer)cl_data);
@@ -2389,7 +2426,7 @@ xg_destroy_widgets (list)
 
 static void
 xg_update_menubar (menubar, f, list, iter, pos, val,
 
 static void
 xg_update_menubar (menubar, f, list, iter, pos, val,
-                   select_cb, highlight_cb, cl_data)
+                   select_cb, deactivate_cb, highlight_cb, cl_data)
      GtkWidget *menubar;
      FRAME_PTR f;
      GList **list;
      GtkWidget *menubar;
      FRAME_PTR f;
      GList **list;
@@ -2397,6 +2434,7 @@ xg_update_menubar (menubar, f, list, iter, pos, val,
      int pos;
      widget_value *val;
      GCallback select_cb;
      int pos;
      widget_value *val;
      GCallback select_cb;
+     GCallback deactivate_cb;
      GCallback highlight_cb;
      xg_menu_cb_data *cl_data;
 {
      GCallback highlight_cb;
      xg_menu_cb_data *cl_data;
 {
@@ -2414,7 +2452,7 @@ xg_update_menubar (menubar, f, list, iter, pos, val,
   else if (! iter && val)
     {
       /* Item(s) added.  Add all new items in one call.  */
   else if (! iter && val)
     {
       /* Item(s) added.  Add all new items in one call.  */
-      create_menus (val, f, select_cb, 0, highlight_cb,
+      create_menus (val, f, select_cb, deactivate_cb, highlight_cb,
                     0, 1, 0, menubar, cl_data, 0);
 
       /* All updated.  */
                     0, 1, 0, menubar, cl_data, 0);
 
       /* All updated.  */
@@ -2521,7 +2559,8 @@ xg_update_menubar (menubar, f, list, iter, pos, val,
           /* Create a possibly empty submenu for menu bar items, since some
              themes don't highlight items correctly without it. */
           GtkWidget *submenu = create_menus (NULL, f,
           /* Create a possibly empty submenu for menu bar items, since some
              themes don't highlight items correctly without it. */
           GtkWidget *submenu = create_menus (NULL, f,
-                                             select_cb, NULL, highlight_cb,
+                                             select_cb, deactivate_cb,
+                                             highlight_cb,
                                              0, 0, 0, 0, cl_data, 0);
           gtk_widget_set_name (w, MENU_ITEM_NAME);
           gtk_menu_shell_insert (GTK_MENU_SHELL (menubar), w, pos);
                                              0, 0, 0, 0, cl_data, 0);
           gtk_widget_set_name (w, MENU_ITEM_NAME);
           gtk_menu_shell_insert (GTK_MENU_SHELL (menubar), w, pos);
@@ -2559,7 +2598,7 @@ xg_update_menubar (menubar, f, list, iter, pos, val,
 
   /* Update the rest of the menu bar.  */
   xg_update_menubar (menubar, f, list, iter, pos, val,
 
   /* Update the rest of the menu bar.  */
   xg_update_menubar (menubar, f, list, iter, pos, val,
-                     select_cb, highlight_cb, cl_data);
+                     select_cb, deactivate_cb, highlight_cb, cl_data);
 }
 
 /* Update the menu item W so it corresponds to VAL.
 }
 
 /* Update the menu item W so it corresponds to VAL.
@@ -2864,7 +2903,7 @@ xg_modify_menubar_widgets (menubar, f, val, deep_p,
                                                   XG_FRAME_DATA);
 
   xg_update_menubar (menubar, f, &list, list, 0, val->contents,
                                                   XG_FRAME_DATA);
 
   xg_update_menubar (menubar, f, &list, list, 0, val->contents,
-                     select_cb, highlight_cb, cl_data);
+                     select_cb, deactivate_cb, highlight_cb, cl_data);
 
   if (deep_p)
     {
 
   if (deep_p)
     {
@@ -3106,7 +3145,7 @@ xg_gtk_scroll_destroy (widget, data)
   int id = (int) (EMACS_INT) data; /* The EMACS_INT cast avoids a warning. */
 
   p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);
   int id = (int) (EMACS_INT) data; /* The EMACS_INT cast avoids a warning. */
 
   p = g_object_get_data (G_OBJECT (widget), XG_LAST_SB_DATA);
-  if (p) xfree (p);
+  xfree (p);
   xg_remove_widget_from_map (id);
 }
 
   xg_remove_widget_from_map (id);
 }