/* Functions for the X window system.
Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <stdio.h>
#include <math.h>
#include <setjmp.h>
+#include <ctype.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <X11/bitmaps/gray>
#endif
+#include "xsettings.h"
+
#ifdef USE_GTK
#include "gtkutil.h"
#endif
Lisp_Object Qsuppress_icon;
Lisp_Object Qundefined_color;
Lisp_Object Qcompound_text, Qcancel_timer;
-static Lisp_Object Qfont_param;
+Lisp_Object Qfont_param;
/* In dispnew.c */
#else /* not USE_X_TOOLKIT && not USE_GTK */
FRAME_MENU_BAR_LINES (f) = nlines;
change_window_heights (f->root_window, nlines - olines);
-#endif /* not USE_X_TOOLKIT */
+
+ /* If the menu bar height gets changed, the internal border below
+ the top margin has to be cleared. Also, if the menu bar gets
+ larger, the area for the added lines has to be cleared except for
+ the first menu bar line that is to be drawn later. */
+ if (nlines != olines)
+ {
+ int height = FRAME_INTERNAL_BORDER_WIDTH (f);
+ int width = FRAME_PIXEL_WIDTH (f);
+ int y;
+
+ /* height can be zero here. */
+ if (height > 0 && width > 0)
+ {
+ y = FRAME_TOP_MARGIN_HEIGHT (f);
+
+ BLOCK_INPUT;
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ 0, y, width, height, False);
+ UNBLOCK_INPUT;
+ }
+
+ if (nlines > 1 && nlines > olines)
+ {
+ y = (olines == 0 ? 1 : olines) * FRAME_LINE_HEIGHT (f);
+ height = nlines * FRAME_LINE_HEIGHT (f) - y;
+
+ BLOCK_INPUT;
+ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ 0, y, width, height, False);
+ UNBLOCK_INPUT;
+ }
+
+ if (nlines == 0 && WINDOWP (f->menu_bar_window))
+ clear_glyph_matrix (XWINDOW (f->menu_bar_window)->current_matrix);
+ }
+#endif /* not USE_X_TOOLKIT && not USE_GTK */
adjust_glyphs (f);
}
{
int height = FRAME_INTERNAL_BORDER_WIDTH (f);
int width = FRAME_PIXEL_WIDTH (f);
- int y = nlines * FRAME_LINE_HEIGHT (f);
+ int y = (FRAME_MENU_BAR_LINES (f) + nlines) * FRAME_LINE_HEIGHT (f);
/* height can be zero here. */
if (height > 0 && width > 0)
background, border and mouse colors; also create the
mouse cursor and the gray border tile. */
-static char cursor_bits[] =
- {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
static void
x_make_gc (f)
struct frame *f;
{
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
Lisp_Object font_param = x_get_arg (dpyinfo, parms, Qfont, NULL, NULL,
- RES_TYPE_STRING);
+ RES_TYPE_STRING);
Lisp_Object font;
+ int got_from_gconf = 0;
if (EQ (font_param, Qunbound))
font_param = Qnil;
+
+ if (NILP (font_param))
+ {
+ /* System font takes precedendce over X resources. We must suggest this
+ regardless of font-use-system-font because .emacs may not have been
+ read yet. */
+ const char *system_font = xsettings_get_system_font ();
+ if (system_font) font_param = make_string (system_font,
+ strlen (system_font));
+ }
+
font = !NILP (font_param) ? font_param
: x_get_arg (dpyinfo, parms, Qfont, "font", "Font", RES_TYPE_STRING);
we've applied the `default' face settings. */
x_set_frame_parameters (f, Fcons (Fcons (Qfont_param, font_param), Qnil));
}
- x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
+
+ x_default_parameter (f, parms, Qfont, font,
+ got_from_gconf ? NULL : "font",
+ got_from_gconf ? NULL : "Font",
+ RES_TYPE_STRING);
}
return Qnil;
}
+/* Return current desktop index for the display where frame F is.
+ If we can't find out the current desktop, return 0. */
+
+static int
+x_get_current_desktop (f)
+ struct frame *f;
+{
+ Atom actual_type;
+ unsigned long actual_size, bytes_remaining;
+ int rc, actual_format;
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ long max_len = 10;
+ Display *dpy = FRAME_X_DISPLAY (f);
+ long *data = NULL;
+ int current_desktop;
+
+ BLOCK_INPUT;
+ x_catch_errors (dpy);
+ rc = XGetWindowProperty (dpy, dpyinfo->root_window,
+ XInternAtom (dpy, "_NET_CURRENT_DESKTOP", False),
+ 0, max_len, False, XA_CARDINAL,
+ &actual_type, &actual_format, &actual_size,
+ &bytes_remaining, (unsigned char **)&data);
+
+ if (rc != Success || actual_type != XA_CARDINAL || x_had_errors_p (dpy)
+ || actual_size == 0 || actual_format != 32)
+ current_desktop = 0;
+ else
+ current_desktop = (int)*data;
+
+ if (data) XFree (data);
+ x_uncatch_errors ();
+ UNBLOCK_INPUT;
+ return current_desktop;
+}
+
+/* Return current size for DESKTOP_INDEX on the display where frame F is.
+ If we can't find out the size, return 0, otherwise 1. */
+
+static int
+x_get_desktop_workarea (f, desktop_index, deskw, deskh)
+ struct frame *f;
+ int desktop_index;
+ int *deskw, *deskh;
+{
+ Atom actual_type;
+ unsigned long actual_size, bytes_remaining;
+ int rc, actual_format;
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ long max_len = 1000; /* This handles 250 desktops, who has that many? */
+ Display *dpy = FRAME_X_DISPLAY (f);
+ long *data = NULL;
+ int retval;
+
+ BLOCK_INPUT;
+ x_catch_errors (dpy);
+ rc = XGetWindowProperty (dpy, dpyinfo->root_window,
+ XInternAtom (dpy, "_NET_WORKAREA", False),
+ 0, max_len, False, XA_CARDINAL,
+ &actual_type, &actual_format, &actual_size,
+ &bytes_remaining, (unsigned char **)&data);
+
+ if (rc != Success || actual_type != XA_CARDINAL || x_had_errors_p (dpy)
+ || actual_size < 3 || actual_format != 32)
+ retval = 0;
+ else
+ {
+ int idx;
+
+ if (actual_size == 4 /* Only one info for all desktops. */
+ || desktop_index*4 > actual_size) /* destop_index out of range. */
+ desktop_index = 0;
+
+ idx = desktop_index*4;
+ *deskw = data[idx+2] - data[idx];
+ *deskh = data[idx+3] - data[idx+1];
+ retval = 1;
+ }
+
+ if (data) XFree (data);
+ x_uncatch_errors ();
+ UNBLOCK_INPUT;
+ return retval;
+}
+
DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
1, 1, 0,
doc: /* Make a new X window, which is called a "frame" in Emacs terms.
Lisp_Object name;
int minibuffer_only = 0;
long window_prompting = 0;
- int width, height;
+ int width, height, deskw = -1, deskh = -1, current_desktop = -1;
int count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
Lisp_Object display;
/* Compute the size of the X window. */
window_prompting = x_figure_window_size (f, parms, 1);
+ /* Don't make height higher than display height unless the user asked
+ for it. */
+ height = FRAME_LINES (f);
+ tem = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
+ if (EQ (tem, Qunbound))
+ {
+ int ph = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
+ int dph = DisplayHeight (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f));
+ /* Some desktops have fixed menus above and/or panels below. Try to
+ figure out the usable size we have for emacs. */
+ current_desktop = x_get_current_desktop (f);
+ x_get_desktop_workarea (f, current_desktop, &deskw, &deskh);
+ if (deskh > 0 && deskh < dph) dph = deskh;
+
+ if (ph > dph)
+ {
+ height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, dph) -
+ FRAME_TOOL_BAR_LINES (f) - FRAME_MENU_BAR_LINES (f);
+ if (FRAME_EXTERNAL_TOOL_BAR (f))
+ height -= 2; /* We can't know how big it will be. */
+ if (FRAME_EXTERNAL_MENU_BAR (f))
+ height -= 2; /* We can't know how big it will be. */
+ }
+ }
+
+ /* Don't make width wider than display width unless the user asked
+ for it. */
+ width = FRAME_COLS (f);
+ tem = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
+ if (EQ (tem, Qunbound))
+ {
+ int pw = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, FRAME_COLS (f));
+ int dpw = DisplayWidth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f));
+ if (deskw == -1)
+ {
+ current_desktop = x_get_current_desktop (f);
+ x_get_desktop_workarea (f, current_desktop, &deskw, &deskh);
+ }
+ if (deskw > 0 && deskw < dpw) dpw = deskw;
+
+ if (pw > dpw)
+ width = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, dpw);
+ }
+
+ if (height != FRAME_LINES (f) || width != FRAME_COLS (f))
+ {
+ check_frame_size (f, &height, &width);
+ FRAME_LINES (f) = height;
+ SET_FRAME_COLS (f, width);
+ }
+
+
tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
f->no_split = minibuffer_only || EQ (tem, Qt);
{
XSetWindowAttributes attrs;
unsigned long mask;
+ Atom type = FRAME_X_DISPLAY_INFO (f)->Xatom_net_window_type_tooltip;
BLOCK_INPUT;
mask = CWBackPixel | CWOverrideRedirect | CWEventMask;
f->border_width,
CopyFromParent, InputOutput, CopyFromParent,
mask, &attrs);
+ XChangeProperty (FRAME_X_DISPLAY (f), tip_window,
+ FRAME_X_DISPLAY_INFO (f)->Xatom_net_window_type,
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char *)&type, 1);
UNBLOCK_INPUT;
}
{
FRAME_PTR f = check_x_frame (frame);
char *name;
- Lisp_Object default_font, font = Qnil;
+ Lisp_Object font;
Lisp_Object font_param;
char *default_name = NULL;
- struct gcpro gcpro1;
+ struct gcpro gcpro1, gcpro2;
int count = SPECPDL_INDEX ();
check_x ();
BLOCK_INPUT;
- GCPRO1(font_param);
- font_param = Fframe_parameter (frame, Qfont_param);
+ GCPRO2(font_param, font);
- if (x_last_font_name != NULL)
- default_name = x_last_font_name;
- else if (STRINGP (font_param))
- default_name = SDATA (font_param);
- else if (FONTP (default_font))
+ XSETFONT (font, FRAME_FONT (f));
+ font_param = Ffont_get (font, intern (":name"));
+ if (STRINGP (font_param))
+ default_name = xstrdup (SDATA (font_param));
+ else
{
- XSETFONT (default_font, FRAME_FONT (f));
- default_name = alloca (256);
- if (font_unparse_gtkname (default_font, f, default_name, 256) < 0)
- default_name = NULL;
+ font_param = Fframe_parameter (frame, Qfont_param);
+ if (STRINGP (font_param))
+ default_name = xstrdup (SDATA (font_param));
+ }
+
+ if (default_name == NULL && x_last_font_name != NULL)
+ default_name = xstrdup (x_last_font_name);
+
+ /* Convert fontconfig names to Gtk names, i.e. remove - before number */
+ if (default_name)
+ {
+ char *p = strrchr (default_name, '-');
+ if (p)
+ {
+ char *ep = p+1;
+ while (isdigit (*ep))
+ ++ep;
+ if (*ep == '\0') *p = ' ';
+ }
}
name = xg_get_font_name (f, default_name);
+ xfree (default_name);
if (name)
{