xfns.c 206 KB
Newer Older
Jim Blandy's avatar
Jim Blandy committed
1
/* Functions for the X window system.
Glenn Morris's avatar
Glenn Morris committed
2

Paul Eggert's avatar
Paul Eggert committed
3
Copyright (C) 1989, 1992-2015 Free Software Foundation, Inc.
Jim Blandy's avatar
Jim Blandy committed
4 5 6

This file is part of GNU Emacs.

7
GNU Emacs is free software: you can redistribute it and/or modify
Jim Blandy's avatar
Jim Blandy committed
8
it under the terms of the GNU General Public License as published by
9 10
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jim Blandy's avatar
Jim Blandy committed
11 12 13 14 15 16 17

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
18
along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
Jim Blandy's avatar
Jim Blandy committed
19

Richard M. Stallman's avatar
Richard M. Stallman committed
20
#include <config.h>
21
#include <stdio.h>
22
#include <math.h>
23 24
#include <unistd.h>

Jim Blandy's avatar
Jim Blandy committed
25 26
#include "lisp.h"
#include "xterm.h"
Paul Eggert's avatar
Paul Eggert committed
27
#include "menu.h"
Jim Blandy's avatar
Jim Blandy committed
28
#include "frame.h"
Jim Blandy's avatar
Jim Blandy committed
29
#include "window.h"
30
#include "character.h"
Jim Blandy's avatar
Jim Blandy committed
31
#include "buffer.h"
Kenichi Handa's avatar
Kenichi Handa committed
32
#include "intervals.h"
Jim Blandy's avatar
Jim Blandy committed
33
#include "dispextern.h"
Jim Blandy's avatar
Jim Blandy committed
34
#include "keyboard.h"
35
#include "blockinput.h"
36
#include <epaths.h>
Karl Heuer's avatar
Karl Heuer committed
37
#include "charset.h"
Kenichi Handa's avatar
Kenichi Handa committed
38
#include "coding.h"
Karl Heuer's avatar
Karl Heuer committed
39
#include "fontset.h"
40 41
#include "systime.h"
#include "termhooks.h"
42
#include "atimer.h"
43
#include "termchar.h"
Kenichi Handa's avatar
Kenichi Handa committed
44 45
#include "font.h"

46 47
#include <sys/types.h>
#include <sys/stat.h>
Jim Blandy's avatar
Jim Blandy committed
48

49
#include "bitmaps/gray.xbm"
50 51
#include "xsettings.h"

52 53 54 55 56 57 58
#ifdef HAVE_XRANDR
#include <X11/extensions/Xrandr.h>
#endif
#ifdef HAVE_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif

Jan Djärv's avatar
Jan Djärv committed
59 60 61 62
#ifdef USE_GTK
#include "gtkutil.h"
#endif

63 64 65
#ifdef USE_X_TOOLKIT
#include <X11/Shell.h>

66
#ifndef USE_MOTIF
Chong Yidong's avatar
Chong Yidong committed
67 68
#ifdef HAVE_XAW3D
#include <X11/Xaw3d/Paned.h>
Chong Yidong's avatar
Chong Yidong committed
69
#include <X11/Xaw3d/Label.h>
Chong Yidong's avatar
Chong Yidong committed
70
#else /* !HAVE_XAW3D */
71 72
#include <X11/Xaw/Paned.h>
#include <X11/Xaw/Label.h>
Chong Yidong's avatar
Chong Yidong committed
73
#endif /* HAVE_XAW3D */
74
#endif /* USE_MOTIF */
75 76 77 78 79

#ifdef USG
#undef USG	/* ####KLUDGE for Solaris 2.2 and up */
#include <X11/Xos.h>
#define USG
80 81
#ifdef USG /* Pacify gcc -Wunused-macros.  */
#endif
82 83 84 85 86 87 88 89
#else
#include <X11/Xos.h>
#endif

#include "widget.h"

#include "../lwlib/lwlib.h"

90 91 92 93
#ifdef USE_MOTIF
#include <Xm/Xm.h>
#include <Xm/DialogS.h>
#include <Xm/FileSB.h>
Jan D's avatar
Jan D committed
94 95
#include <Xm/List.h>
#include <Xm/TextF.h>
96 97
#endif

98 99 100 101
#ifdef USE_LUCID
#include "../lwlib/xlwmenu.h"
#endif

Juanma Barranquero's avatar
Juanma Barranquero committed
102
#if !defined (NO_EDITRES)
103
#define HACK_EDITRES
104
extern void _XEditResCheckMessages (Widget, XtPointer, XEvent *, Boolean *);
Dan Nicolaescu's avatar
Dan Nicolaescu committed
105
#endif /* not defined NO_EDITRES */
106

107 108
/* Unique id counter for widgets created by the Lucid Widget Library.  */

109 110
extern LWLIB_ID widget_id_tick;

111 112 113 114
#ifdef USE_MOTIF

#endif /* USE_MOTIF */

115 116
#endif /* USE_X_TOOLKIT */

Kenichi Handa's avatar
Kenichi Handa committed
117 118 119 120
#ifdef USE_GTK

#endif /* USE_GTK */

Richard M. Stallman's avatar
Richard M. Stallman committed
121 122
#define MAXREQUEST(dpy) (XMaxRequestSize (dpy))

123
static ptrdiff_t image_cache_refcount;
124
#ifdef GLYPH_DEBUG
125
static int dpyinfo_refcount;
126 127
#endif

128 129
static struct x_display_info *x_display_info_for_name (Lisp_Object);

130
/* Let the user specify an X display with a Lisp object.
131
   OBJECT may be nil, a frame or a terminal object.
132 133 134
   nil stands for the selected frame--or, if that is not an X frame,
   the first X display on the list.  */

135
struct x_display_info *
136
check_x_display_info (Lisp_Object object)
137
{
138
  struct x_display_info *dpyinfo = NULL;
139

140
  if (NILP (object))
141
    {
Gerd Moellmann's avatar
Gerd Moellmann committed
142
      struct frame *sf = XFRAME (selected_frame);
143

Gerd Moellmann's avatar
Gerd Moellmann committed
144
      if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
145
	dpyinfo = FRAME_DISPLAY_INFO (sf);
146
      else if (x_display_list != 0)
147
	dpyinfo = x_display_list;
148 149 150
      else
	error ("X windows are not in use or not initialized");
    }
151
  else if (TERMINALP (object))
152
    {
153
      struct terminal *t = decode_live_terminal (object);
154

155
      if (t->type != output_x_window)
156
        error ("Terminal %d is not an X display", t->id);
157

158
      dpyinfo = t->display_info.x;
159
    }
160 161
  else if (STRINGP (object))
    dpyinfo = x_display_info_for_name (object);
162 163
  else
    {
Dmitry Antipov's avatar
Dmitry Antipov committed
164
      struct frame *f = decode_window_system_frame (object);
165
      dpyinfo = FRAME_DISPLAY_INFO (f);
166
    }
167 168

  return dpyinfo;
169
}
170

171 172 173 174 175 176 177
/* Return the screen positions and offsets of frame F.
   Store the offsets between FRAME_OUTER_WINDOW and the containing
   window manager window into LEFT_OFFSET_X, RIGHT_OFFSET_X,
   TOP_OFFSET_Y and BOTTOM_OFFSET_Y.
   Store the offsets between FRAME_X_WINDOW and the containing
   window manager window into X_PIXELS_DIFF and Y_PIXELS_DIFF.
   Store the screen positions of frame F into XPTR and YPTR.
178 179 180
   These are the positions of the containing window manager window,
   not Emacs's own window.  */
void
181 182 183 184 185 186 187 188
x_real_pos_and_offsets (struct frame *f,
                        int *left_offset_x,
                        int *right_offset_x,
                        int *top_offset_y,
                        int *bottom_offset_y,
                        int *x_pixels_diff,
                        int *y_pixels_diff,
                        int *xptr,
189 190
                        int *yptr,
                        int *outer_border)
191
{
192
  int win_x, win_y, outer_x IF_LINT (= 0), outer_y IF_LINT (= 0);
193
  int real_x = 0, real_y = 0;
Paul Eggert's avatar
Paul Eggert committed
194
  bool had_errors = false;
195
  Window win = f->output_data.x->parent_desc;
196 197
  Atom actual_type;
  unsigned long actual_size, bytes_remaining;
198
  int rc, actual_format;
199
  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
200 201 202 203
  long max_len = 400;
  Display *dpy = FRAME_X_DISPLAY (f);
  unsigned char *tmp_data = NULL;
  Atom target_type = XA_CARDINAL;
204
  unsigned int ow IF_LINT (= 0), oh IF_LINT (= 0);
205

206
  block_input ();
207

208
  x_catch_errors (dpy);
209

210 211 212 213 214 215 216 217 218 219
  if (x_pixels_diff) *x_pixels_diff = 0;
  if (y_pixels_diff) *y_pixels_diff = 0;
  if (left_offset_x) *left_offset_x = 0;
  if (top_offset_y) *top_offset_y = 0;
  if (right_offset_x) *right_offset_x = 0;
  if (bottom_offset_y) *bottom_offset_y = 0;
  if (xptr) *xptr = 0;
  if (yptr) *yptr = 0;
  if (outer_border) *outer_border = 0;

220
  if (win == dpyinfo->root_window)
221 222 223 224 225 226 227
    win = FRAME_OUTER_WINDOW (f);

  /* This loop traverses up the containment tree until we hit the root
     window.  Window managers may intersect many windows between our window
     and the root window.  The window we find just before the root window
     should be the outer WM window. */
  for (;;)
228
    {
229 230 231
      Window wm_window, rootw;
      Window *tmp_children;
      unsigned int tmp_nchildren;
232
      int success;
233

234 235
      success = XQueryTree (FRAME_X_DISPLAY (f), win, &rootw,
			    &wm_window, &tmp_children, &tmp_nchildren);
236

237
      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
238

239 240 241 242
      /* Don't free tmp_children if XQueryTree failed.  */
      if (! success)
	break;

243
      XFree (tmp_children);
244

245 246
      if (wm_window == rootw || had_errors)
        break;
247

248 249
      win = wm_window;
    }
250

251 252
  if (! had_errors)
    {
253
      unsigned int ign;
254
      Window child, rootw;
255

256 257
      /* Get the real coordinates for the WM window upper left corner */
      XGetGeometry (FRAME_X_DISPLAY (f), win,
258
                    &rootw, &real_x, &real_y, &ow, &oh, &ign, &ign);
259

260 261 262 263 264 265
      if (outer_border)
        {
          XWindowAttributes atts;
          XGetWindowAttributes (FRAME_X_DISPLAY (f), win, &atts);
          *outer_border = atts.border_width;
        }
266 267 268 269 270 271 272 273 274 275 276

      /* Translate real coordinates to coordinates relative to our
         window.  For our window, the upper left corner is 0, 0.
         Since the upper left corner of the WM window is outside
         our window, win_x and win_y will be negative:

         ------------------          ---> x
         |      title                |
         | -----------------         v y
         | |  our window
      */
277
      XTranslateCoordinates (FRAME_X_DISPLAY (f),
278

279
			     /* From-window, to-window.  */
280
			     FRAME_DISPLAY_INFO (f)->root_window,
281
                             FRAME_X_WINDOW (f),
282

283
			     /* From-position, to-position.  */
284
                             real_x, real_y, &win_x, &win_y,
285

286 287
			     /* Child of win.  */
			     &child);
288

289
      if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
290
	{
291 292
          outer_x = win_x;
          outer_y = win_y;
293
	}
294 295 296
      else
        {
          XTranslateCoordinates (FRAME_X_DISPLAY (f),
297

298
                                 /* From-window, to-window.  */
299
                                 FRAME_DISPLAY_INFO (f)->root_window,
300
                                 FRAME_OUTER_WINDOW (f),
301

302 303
                                 /* From-position, to-position.  */
                                 real_x, real_y, &outer_x, &outer_y,
304

305 306
                                 /* Child of win.  */
                                 &child);
307
	}
308

309 310
      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
    }
311

312 313 314 315 316 317 318 319 320 321 322 323

  if (dpyinfo->root_window == f->output_data.x->parent_desc)
    {
      /* Try _NET_FRAME_EXTENTS if our parent is the root window.  */
      rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_frame_extents,
                               0, max_len, False, target_type,
                               &actual_type, &actual_format, &actual_size,
                               &bytes_remaining, &tmp_data);

      if (rc == Success && actual_type == target_type && !x_had_errors_p (dpy)
          && actual_size == 4 && actual_format == 32)
        {
324
          unsigned int ign;
325
          Window rootw;
326
          long *fe = (long *)tmp_data;
327 328 329 330 331 332 333 334 335 336 337 338

          XGetGeometry (FRAME_X_DISPLAY (f), win,
                        &rootw, &real_x, &real_y, &ign, &ign, &ign, &ign);
          outer_x = -fe[0];
          outer_y = -fe[2];
          real_x -= fe[0];
          real_y -= fe[2];
        }
    }

  if (tmp_data) XFree (tmp_data);

339
  x_uncatch_errors ();
340

341
  unblock_input ();
342 343

  if (had_errors) return;
344

345 346 347 348
  if (x_pixels_diff) *x_pixels_diff = -win_x;
  if (y_pixels_diff) *y_pixels_diff = -win_y;

  if (left_offset_x) *left_offset_x = -outer_x;
349
  if (top_offset_y) *top_offset_y = -outer_y;
350

351 352
  if (xptr) *xptr = real_x;
  if (yptr) *yptr = real_y;
353

354
  if (right_offset_x || bottom_offset_y)
355 356 357 358 359 360 361 362 363 364
    {
      int xy_ign;
      unsigned int ign, fw, fh;
      Window rootw;

      XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
		    &rootw, &xy_ign, &xy_ign, &fw, &fh, &ign, &ign);
      if (right_offset_x) *right_offset_x = ow - fw + outer_x;
      if (bottom_offset_y) *bottom_offset_y = oh - fh + outer_y;
    }
365 366
}

367 368 369
/* Store the screen positions of frame F into XPTR and YPTR.
   These are the positions of the containing window manager window,
   not Emacs's own window.  */
370

371 372 373
void
x_real_positions (struct frame *f, int *xptr, int *yptr)
{
374 375
  x_real_pos_and_offsets (f, NULL, NULL, NULL, NULL, NULL, NULL, xptr, yptr,
                          NULL);
376 377
}

378

379
/* Get the mouse position in frame relative coordinates.  */
380

381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
void
x_relative_mouse_position (struct frame *f, int *x, int *y)
{
  Window root, dummy_window;
  int dummy;

  eassert (FRAME_X_P (f));

  block_input ();

  XQueryPointer (FRAME_X_DISPLAY (f),
                 DefaultRootWindow (FRAME_X_DISPLAY (f)),

                 /* The root window which contains the pointer.  */
                 &root,

                 /* Window pointer is on, not used  */
                 &dummy_window,

                 /* The position on that root window.  */
                 x, y,

                 /* x/y in dummy_window coordinates, not used.  */
                 &dummy, &dummy,

                 /* Modifier keys and pointer buttons, about which
                    we don't care.  */
                 (unsigned int *) &dummy);

410
  XTranslateCoordinates (FRAME_X_DISPLAY (f),
411

412 413 414
                         /* From-window, to-window.  */
                         FRAME_DISPLAY_INFO (f)->root_window,
                         FRAME_X_WINDOW (f),
415

416 417 418 419 420 421 422
                         /* From-position, to-position.  */
                         *x, *y, x, y,

                         /* Child of win.  */
                         &dummy_window);

  unblock_input ();
423
}
424 425 426 427

/* Gamma-correct COLOR on frame F.  */

void
428
gamma_correct (struct frame *f, XColor *color)
429 430 431 432 433 434 435 436 437 438
{
  if (f->gamma)
    {
      color->red = pow (color->red / 65535.0, f->gamma) * 65535.0 + 0.5;
      color->green = pow (color->green / 65535.0, f->gamma) * 65535.0 + 0.5;
      color->blue = pow (color->blue / 65535.0, f->gamma) * 65535.0 + 0.5;
    }
}


439
/* Decide if color named COLOR_NAME is valid for use on frame F.  If
440 441
   so, return the RGB values in COLOR.  If ALLOC_P,
   allocate the color.  Value is false if COLOR_NAME is invalid, or
442
   no color could be allocated.  */
443

444
bool
445
x_defined_color (struct frame *f, const char *color_name,
446
		 XColor *color, bool alloc_p)
Jim Blandy's avatar
Jim Blandy committed
447
{
Paul Eggert's avatar
Paul Eggert committed
448
  bool success_p = false;
449 450
  Display *dpy = FRAME_X_DISPLAY (f);
  Colormap cmap = FRAME_X_COLORMAP (f);
Jim Blandy's avatar
Jim Blandy committed
451

452
  block_input ();
453 454 455 456
#ifdef USE_GTK
  success_p = xg_check_special_colors (f, color_name, color);
#endif
  if (!success_p)
457
    success_p = XParseColor (dpy, cmap, color_name, color) != 0;
458 459
  if (success_p && alloc_p)
    success_p = x_alloc_nearest_color (f, cmap, color);
460
  unblock_input ();
Jim Blandy's avatar
Jim Blandy committed
461

462
  return success_p;
Jim Blandy's avatar
Jim Blandy committed
463 464
}

465 466 467 468

/* Return the pixel color value for color COLOR_NAME on frame F.  If F
   is a monochrome frame, return MONO_COLOR regardless of what ARG says.
   Signal an error if color can't be allocated.  */
Jim Blandy's avatar
Jim Blandy committed
469

470
static int
Dmitry Antipov's avatar
Dmitry Antipov committed
471
x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color)
Jim Blandy's avatar
Jim Blandy committed
472
{
473
  XColor cdef;
Jim Blandy's avatar
Jim Blandy committed
474

475
  CHECK_STRING (color_name);
Jim Blandy's avatar
Jim Blandy committed
476

Paul Eggert's avatar
Paul Eggert committed
477 478 479
#if false /* Don't do this.  It's wrong when we're not using the default
	     colormap, it makes freeing difficult, and it's probably not
	     an important optimization.  */
480
  if (strcmp (SDATA (color_name), "black") == 0)
481
    return BLACK_PIX_DEFAULT (f);
482
  else if (strcmp (SDATA (color_name), "white") == 0)
483
    return WHITE_PIX_DEFAULT (f);
484
#endif
Jim Blandy's avatar
Jim Blandy committed
485

486
  /* Return MONO_COLOR for monochrome frames.  */
487
  if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
488
    return mono_color;
Jim Blandy's avatar
Jim Blandy committed
489

490
  /* x_defined_color is responsible for coping with failures
491
     by looking for a near-miss.  */
Paul Eggert's avatar
Paul Eggert committed
492
  if (x_defined_color (f, SSDATA (color_name), &cdef, true))
493 494
    return cdef.pixel;

495
  signal_error ("Undefined color", color_name);
Jim Blandy's avatar
Jim Blandy committed
496
}
497 498


Jim Blandy's avatar
Jim Blandy committed
499

Gerd Moellmann's avatar
Gerd Moellmann committed
500 501 502 503 504
/* Change the `wait-for-wm' frame parameter of frame F.  OLD_VALUE is
   the previous value of that parameter, NEW_VALUE is the new value.
   See also the comment of wait_for_wm in struct x_output.  */

static void
505
x_set_wait_for_wm (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
Gerd Moellmann's avatar
Gerd Moellmann committed
506 507 508 509
{
  f->output_data.x->wait_for_wm = !NILP (new_value);
}

510 511 512 513 514
static void
x_set_tool_bar_position (struct frame *f,
                         Lisp_Object new_value,
                         Lisp_Object old_value)
{
515
  Lisp_Object choice = list4 (Qleft, Qright, Qtop, Qbottom);
516

517 518
  if (!NILP (Fmemq (new_value, choice)))
    {
519
#ifdef USE_GTK
520 521 522 523 524 525 526 527
      if (!EQ (new_value, old_value))
	{
	  xg_change_toolbar_position (f, new_value);
	  fset_tool_bar_position (f, new_value);
	}
#else
      if (!EQ (new_value, Qtop))
	error ("The only supported tool bar position is top");
528
#endif
529 530 531
    }
  else
    wrong_choice (choice, new_value);
532 533
}

534 535
#ifdef USE_GTK

536 537
/* Set icon from FILE for frame F.  By using GTK functions the icon
   may be any format that GdkPixbuf knows about, i.e. not just bitmaps.  */
538

Paul Eggert's avatar
Paul Eggert committed
539
bool
Dmitry Antipov's avatar
Dmitry Antipov committed
540
xg_set_icon (struct frame *f, Lisp_Object file)
541
{
Paul Eggert's avatar
Paul Eggert committed
542
  bool result = false;
543
  Lisp_Object found;
544

545 546 547 548 549 550
  found = x_find_image_file (file);

  if (! NILP (found))
    {
      GdkPixbuf *pixbuf;
      GError *err = NULL;
551
      char *filename = SSDATA (ENCODE_FILE (found));
552
      block_input ();
553 554 555 556 557 558 559 560 561

      pixbuf = gdk_pixbuf_new_from_file (filename, &err);

      if (pixbuf)
	{
	  gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
			       pixbuf);
	  g_object_unref (pixbuf);

Paul Eggert's avatar
Paul Eggert committed
562
	  result = true;
563 564 565 566
	}
      else
	g_error_free (err);

567
      unblock_input ();
568 569 570
    }

  return result;
571
}
572

Paul Eggert's avatar
Paul Eggert committed
573
bool
Dmitry Antipov's avatar
Dmitry Antipov committed
574
xg_set_icon_from_xpm_data (struct frame *f, const char **data)
575
{
576
  GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data);
577 578

  if (!pixbuf)
Paul Eggert's avatar
Paul Eggert committed
579
    return false;
580

581
  gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf);
582
  g_object_unref (pixbuf);
Paul Eggert's avatar
Paul Eggert committed
583
  return true;
584
}
585 586
#endif /* USE_GTK */

Gerd Moellmann's avatar
Gerd Moellmann committed
587

Jim Blandy's avatar
Jim Blandy committed
588
/* Functions called only from `x_set_frame_param'
Jim Blandy's avatar
Jim Blandy committed
589 590
   to set individual parameters.

591
   If FRAME_X_WINDOW (f) is 0,
Jim Blandy's avatar
Jim Blandy committed
592
   the frame is being created and its X-window does not exist yet.
Jim Blandy's avatar
Jim Blandy committed
593 594 595
   In that case, just record the parameter's new value
   in the standard place; do not attempt to change the window.  */

596
static void
597
x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
598
{
599 600
  struct x_output *x = f->output_data.x;
  unsigned long fg, old_fg;
601

602
  fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
603 604
  old_fg = FRAME_FOREGROUND_PIXEL (f);
  FRAME_FOREGROUND_PIXEL (f) = fg;
605

606
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
607
    {
608
      Display *dpy = FRAME_X_DISPLAY (f);
609

610
      block_input ();
611 612
      XSetForeground (dpy, x->normal_gc, fg);
      XSetBackground (dpy, x->reverse_gc, fg);
613

614 615 616 617 618 619
      if (x->cursor_pixel == old_fg)
	{
	  unload_color (f, x->cursor_pixel);
	  x->cursor_pixel = x_copy_color (f, fg);
	  XSetBackground (dpy, x->cursor_gc, x->cursor_pixel);
	}
620

621
      unblock_input ();
622

623
      update_face_from_frame_parameter (f, Qforeground_color, arg);
624

625
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
626
        redraw_frame (f);
Jim Blandy's avatar
Jim Blandy committed
627
    }
628

629
  unload_color (f, old_fg);
Jim Blandy's avatar
Jim Blandy committed
630 631
}

632
static void
633
x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
634
{
635 636
  struct x_output *x = f->output_data.x;
  unsigned long bg;
Jim Blandy's avatar
Jim Blandy committed
637

638
  bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
639 640
  unload_color (f, FRAME_BACKGROUND_PIXEL (f));
  FRAME_BACKGROUND_PIXEL (f) = bg;
641

642
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
643
    {
644
      Display *dpy = FRAME_X_DISPLAY (f);
645

646
      block_input ();
647 648 649 650 651
      XSetBackground (dpy, x->normal_gc, bg);
      XSetForeground (dpy, x->reverse_gc, bg);
      XSetWindowBackground (dpy, FRAME_X_WINDOW (f), bg);
      XSetForeground (dpy, x->cursor_gc, bg);

Jan Djärv's avatar
Jan Djärv committed
652 653 654 655
#ifdef USE_GTK
      xg_set_background_color (f, bg);
#endif

656 657 658 659 660 661 662 663
#ifndef USE_TOOLKIT_SCROLL_BARS /* Turns out to be annoying with
				   toolkit scroll bars.  */
      {
	Lisp_Object bar;
	for (bar = FRAME_SCROLL_BARS (f);
	     !NILP (bar);
	     bar = XSCROLL_BAR (bar)->next)
	  {
664
	    Window window = XSCROLL_BAR (bar)->x_window;
665 666 667 668
	    XSetWindowBackground (dpy, window, bg);
	  }
      }
#endif /* USE_TOOLKIT_SCROLL_BARS */
Jim Blandy's avatar
Jim Blandy committed
669

670
      unblock_input ();
671
      update_face_from_frame_parameter (f, Qbackground_color, arg);
672

673
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
674
        redraw_frame (f);
Jim Blandy's avatar
Jim Blandy committed
675 676 677
    }
}

678
static void
679
x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
680
{
681 682
  struct x_output *x = f->output_data.x;
  Display *dpy = FRAME_X_DISPLAY (f);
683
  Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
684
  Cursor hourglass_cursor, horizontal_drag_cursor, vertical_drag_cursor;
685
  unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
686
  unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f);
687

688
  /* Don't let pointers be invisible.  */
689
  if (mask_color == pixel)
690 691
    {
      x_free_colors (f, &pixel, 1);
Karoly Lorentey's avatar
Karoly Lorentey committed
692
      pixel = x_copy_color (f, FRAME_FOREGROUND_PIXEL (f));
693
    }
694

695 696
  unload_color (f, x->mouse_pixel);
  x->mouse_pixel = pixel;
Jim Blandy's avatar
Jim Blandy committed
697

698
  block_input ();
699

700
  /* It's not okay to crash if the user selects a screwy cursor.  */
701
  x_catch_errors (dpy);
702

703
  if (!NILP (Vx_pointer_shape))
Jim Blandy's avatar
Jim Blandy committed
704
    {
705
      CHECK_NUMBER (Vx_pointer_shape);
706
      cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape));
Jim Blandy's avatar
Jim Blandy committed
707 708
    }
  else
709 710
    cursor = XCreateFontCursor (dpy, XC_xterm);
  x_check_errors (dpy, "bad text pointer cursor: %s");
Jim Blandy's avatar
Jim Blandy committed
711

712
  if (!NILP (Vx_nontext_pointer_shape))
Jim Blandy's avatar
Jim Blandy committed
713
    {
714
      CHECK_NUMBER (Vx_nontext_pointer_shape);
715 716
      nontext_cursor
	= XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
Jim Blandy's avatar
Jim Blandy committed
717 718
    }
  else
719 720
    nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr);
  x_check_errors (dpy, "bad nontext pointer cursor: %s");
Jim Blandy's avatar
Jim Blandy committed
721

722
  if (!NILP (Vx_hourglass_pointer_shape))
723
    {
724
      CHECK_NUMBER (Vx_hourglass_pointer_shape);
725 726
      hourglass_cursor
	= XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
727 728
    }
  else
729 730
    hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
  x_check_errors (dpy, "bad hourglass pointer cursor: %s");
731

732
  if (!NILP (Vx_mode_pointer_shape))
Jim Blandy's avatar
Jim Blandy committed
733
    {
734
      CHECK_NUMBER (Vx_mode_pointer_shape);
735
      mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
Jim Blandy's avatar
Jim Blandy committed
736 737
    }
  else
738 739
    mode_cursor = XCreateFontCursor (dpy, XC_xterm);
  x_check_errors (dpy, "bad modeline pointer cursor: %s");
740

741
  if (!NILP (Vx_sensitive_text_pointer_shape))
742
    {
743
      CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
744
      hand_cursor
745
	= XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
746 747
    }
  else
748
    hand_cursor = XCreateFontCursor (dpy, XC_hand2);
Jim Blandy's avatar
Jim Blandy committed
749

750 751
  if (!NILP (Vx_window_horizontal_drag_shape))
    {
Paul Eggert's avatar
Paul Eggert committed
752
      CHECK_TYPE_RANGED_INTEGER (unsigned, Vx_window_horizontal_drag_shape);
753
      horizontal_drag_cursor
754
	= XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
755 756 757
    }
  else
    horizontal_drag_cursor
758
      = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
759

760 761 762 763 764 765 766 767 768 769
  if (!NILP (Vx_window_vertical_drag_shape))
    {
      CHECK_NUMBER (Vx_window_vertical_drag_shape);
      vertical_drag_cursor
	= XCreateFontCursor (dpy, XINT (Vx_window_vertical_drag_shape));
    }
  else
    vertical_drag_cursor
      = XCreateFontCursor (dpy, XC_sb_v_double_arrow);

770
  /* Check and report errors with the above calls.  */
771
  x_check_errors (dpy, "can't set cursor shape: %s");
772
  x_uncatch_errors ();
773

Jim Blandy's avatar
Jim Blandy committed
774 775 776
  {
    XColor fore_color, back_color;

777
    fore_color.pixel = x->mouse_pixel;
778
    x_query_color (f, &fore_color);
Jim Blandy's avatar
Jim Blandy committed
779
    back_color.pixel = mask_color;
780
    x_query_color (f, &back_color);
781

782 783 784
    XRecolorCursor (dpy, cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
785
    XRecolorCursor (dpy, hand_cursor, &fore_color, &back_color);
786 787
    XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
788
    XRecolorCursor (dpy, vertical_drag_cursor, &fore_color, &back_color);
Jim Blandy's avatar
Jim Blandy committed
789 790
  }

791
  if (FRAME_X_WINDOW (f) != 0)
792 793
    XDefineCursor (dpy, FRAME_X_WINDOW (f),
                   f->output_data.x->current_cursor = cursor);
794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813

  if (cursor != x->text_cursor
      && x->text_cursor != 0)
    XFreeCursor (dpy, x->text_cursor);
  x->text_cursor = cursor;

  if (nontext_cursor != x->nontext_cursor
      && x->nontext_cursor != 0)
    XFreeCursor (dpy, x->nontext_cursor);
  x->nontext_cursor = nontext_cursor;

  if (hourglass_cursor != x->hourglass_cursor
      && x->hourglass_cursor != 0)
    XFreeCursor (dpy, x->hourglass_cursor);
  x->hourglass_cursor = hourglass_cursor;

  if (mode_cursor != x->modeline_cursor
      && x->modeline_cursor != 0)
    XFreeCursor (dpy, f->output_data.x->modeline_cursor);
  x->modeline_cursor = mode_cursor;
814

815 816 817 818
  if (hand_cursor != x->hand_cursor
      && x->hand_cursor != 0)
    XFreeCursor (dpy, x->hand_cursor);
  x->hand_cursor = hand_cursor;
Jim Blandy's avatar
Jim Blandy committed
819

820 821 822 823
  if (horizontal_drag_cursor != x->horizontal_drag_cursor
      && x->horizontal_drag_cursor != 0)
    XFreeCursor (dpy, x->horizontal_drag_cursor);
  x->horizontal_drag_cursor = horizontal_drag_cursor;
824

825 826 827 828 829
  if (vertical_drag_cursor != x->vertical_drag_cursor
      && x->vertical_drag_cursor != 0)
    XFreeCursor (dpy, x->vertical_drag_cursor);
  x->vertical_drag_cursor = vertical_drag_cursor;

830
  XFlush (dpy);
831
  unblock_input ();
832 833

  update_face_from_frame_parameter (f, Qmouse_color, arg);
Jim Blandy's avatar
Jim Blandy committed
834 835
}

836
static void
837
x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
838
{
839
  unsigned long fore_pixel, pixel;
Paul Eggert's avatar
Paul Eggert committed
840
  bool fore_pixel_allocated_p = false, pixel_allocated_p = false;
841
  struct x_output *x = f->output_data.x;
Jim Blandy's avatar
Jim Blandy committed
842

843 844 845 846
  if (!NILP (Vx_cursor_fore_pixel))
    {
      fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
				   WHITE_PIX_DEFAULT (f));
Paul Eggert's avatar
Paul Eggert committed
847
      fore_pixel_allocated_p = true;
848
    }
Jim Blandy's avatar
Jim Blandy committed
849
  else
Karoly Lorentey's avatar
Karoly Lorentey committed
850
    fore_pixel = FRAME_BACKGROUND_PIXEL (f);
851

852
  pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Paul Eggert's avatar
Paul Eggert committed
853
  pixel_allocated_p = true;
854

855
  /* Make sure that the cursor color differs from the background color.  */
Karoly Lorentey's avatar
Karoly Lorentey committed
856
  if (pixel == FRAME_BACKGROUND_PIXEL (f))
Jim Blandy's avatar
Jim Blandy committed
857
    {
858 859 860
      if (pixel_allocated_p)
	{
	  x_free_colors (f, &pixel, 1);
Paul Eggert's avatar
Paul Eggert committed
861
	  pixel_allocated_p = false;
862
	}
863

864
      pixel = x->mouse_pixel;
865
      if (pixel == fore_pixel)
866 867 868 869
	{
	  if (fore_pixel_allocated_p)
	    {
	      x_free_colors (f, &fore_pixel, 1);
Paul Eggert's avatar
Paul Eggert committed
870
	      fore_pixel_allocated_p = false;
871
	    }
Karoly Lorentey's avatar
Karoly Lorentey committed
872
	  fore_pixel = FRAME_BACKGROUND_PIXEL (f);
873
	}
Jim Blandy's avatar
Jim Blandy committed
874
    }
875

876
  unload_color (f, x->cursor_foreground_pixel);
877 878
  if (!fore_pixel_allocated_p)
    fore_pixel = x_copy_color (f, fore_pixel);
879
  x->cursor_foreground_pixel = fore_pixel;
Jim Blandy's avatar
Jim Blandy committed
880

881
  unload_color (f, x->cursor_pixel);
882 883
  if (!pixel_allocated_p)
    pixel = x_copy_color (f, pixel);
884
  x->cursor_pixel = pixel;
885

886
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
887
    {
888
      block_input ();
889 890
      XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
      XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
Paul Eggert's avatar