]> 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/>.  */
 
-#include "config.h"
+#include <config.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>
 
+#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))
@@ -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.  */
+  /* 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->internal_border_width = 0;
+  f->internal_border_width = 0; */
 
   UNBLOCK_INPUT;
 
@@ -1023,7 +1028,7 @@ x_wm_set_size_hint (f, flags, user_position)
 }
 
 /* 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.  */
@@ -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
-xg_file_response_cb (w,
+xg_dialog_response_cb (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
-pop_down_file_dialog (arg)
+pop_down_dialog (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_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.  */
@@ -1601,7 +1606,7 @@ xg_get_file_name (f, prompt, default_filename, mustmatch_p, only_dir_p)
 
   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);
@@ -1620,14 +1625,80 @@ xg_get_file_name (f, prompt, default_filename, mustmatch_p, only_dir_p)
   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.
  ***********************************************************************/
 
-/* 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
-   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"
 
@@ -2071,34 +2142,6 @@ xg_create_one_menuitem (item, f, select_cb, highlight_cb, cl_data, group)
   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 *));
@@ -2164,12 +2207,6 @@ create_menus (data, f, select_cb, deactivate_cb, highlight_cb,
       }
       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);
@@ -2389,7 +2426,7 @@ xg_destroy_widgets (list)
 
 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;
@@ -2397,6 +2434,7 @@ xg_update_menubar (menubar, f, list, iter, pos, val,
      int pos;
      widget_value *val;
      GCallback select_cb;
+     GCallback deactivate_cb;
      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.  */
-      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.  */
@@ -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,
-                                             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);
@@ -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,
-                     select_cb, highlight_cb, cl_data);
+                     select_cb, deactivate_cb, highlight_cb, cl_data);
 }
 
 /* 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,
-                     select_cb, highlight_cb, cl_data);
+                     select_cb, deactivate_cb, highlight_cb, cl_data);
 
   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);
-  if (p) xfree (p);
+  xfree (p);
   xg_remove_widget_from_map (id);
 }