xfns.c 190 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

3
Copyright (C) 1989, 1992-2014 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"
Jim Blandy's avatar
Jim Blandy committed
27
#include "frame.h"
Jim Blandy's avatar
Jim Blandy committed
28
#include "window.h"
29
#include "character.h"
Jim Blandy's avatar
Jim Blandy committed
30
#include "buffer.h"
Kenichi Handa's avatar
Kenichi Handa committed
31
#include "intervals.h"
Jim Blandy's avatar
Jim Blandy committed
32
#include "dispextern.h"
Jim Blandy's avatar
Jim Blandy committed
33
#include "keyboard.h"
34
#include "blockinput.h"
35
#include <epaths.h>
Karl Heuer's avatar
Karl Heuer committed
36
#include "charset.h"
Kenichi Handa's avatar
Kenichi Handa committed
37
#include "coding.h"
Karl Heuer's avatar
Karl Heuer committed
38
#include "fontset.h"
39 40
#include "systime.h"
#include "termhooks.h"
41
#include "atimer.h"
42
#include "termchar.h"
Kenichi Handa's avatar
Kenichi Handa committed
43 44
#include "font.h"

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

48
#if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work.  */
49 50
#include "bitmaps/gray.xbm"
#else
Jim Blandy's avatar
Jim Blandy committed
51
#include <X11/bitmaps/gray>
52
#endif
Jim Blandy's avatar
Jim Blandy committed
53

54 55
#include "xsettings.h"

56 57 58 59 60 61 62
#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
63 64 65 66
#ifdef USE_GTK
#include "gtkutil.h"
#endif

67 68 69
#ifdef USE_X_TOOLKIT
#include <X11/Shell.h>

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

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

#include "widget.h"

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

94 95 96 97
#ifdef USE_MOTIF
#include <Xm/Xm.h>
#include <Xm/DialogS.h>
#include <Xm/FileSB.h>
Jan D's avatar
Jan D committed
98 99
#include <Xm/List.h>
#include <Xm/TextF.h>
100 101
#endif

102 103 104 105
#ifdef USE_LUCID
#include "../lwlib/xlwmenu.h"
#endif

Juanma Barranquero's avatar
Juanma Barranquero committed
106
#if !defined (NO_EDITRES)
107
#define HACK_EDITRES
108
extern void _XEditResCheckMessages (Widget, XtPointer, XEvent *, Boolean *);
Dan Nicolaescu's avatar
Dan Nicolaescu committed
109
#endif /* not defined NO_EDITRES */
110

111 112
/* Unique id counter for widgets created by the Lucid Widget Library.  */

113 114
extern LWLIB_ID widget_id_tick;

115 116 117 118
#ifdef USE_MOTIF

#endif /* USE_MOTIF */

119 120
#endif /* USE_X_TOOLKIT */

Kenichi Handa's avatar
Kenichi Handa committed
121 122 123 124
#ifdef USE_GTK

#endif /* USE_GTK */

Richard M. Stallman's avatar
Richard M. Stallman committed
125 126
#define MAXREQUEST(dpy) (XMaxRequestSize (dpy))

127 128 129
static Lisp_Object Qsuppress_icon;
static Lisp_Object Qundefined_color;
static Lisp_Object Qcompound_text, Qcancel_timer;
130
Lisp_Object Qfont_param;
Jim Blandy's avatar
Jim Blandy committed
131

132
#ifdef GLYPH_DEBUG
133 134
static ptrdiff_t image_cache_refcount;
static int dpyinfo_refcount;
135 136
#endif

137 138
static struct x_display_info *x_display_info_for_name (Lisp_Object);

139
/* Let the user specify an X display with a Lisp object.
140
   OBJECT may be nil, a frame or a terminal object.
141 142 143
   nil stands for the selected frame--or, if that is not an X frame,
   the first X display on the list.  */

144
struct x_display_info *
145
check_x_display_info (Lisp_Object object)
146
{
147
  struct x_display_info *dpyinfo = NULL;
148

149
  if (NILP (object))
150
    {
Gerd Moellmann's avatar
Gerd Moellmann committed
151
      struct frame *sf = XFRAME (selected_frame);
152

Gerd Moellmann's avatar
Gerd Moellmann committed
153
      if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
154
	dpyinfo = FRAME_DISPLAY_INFO (sf);
155
      else if (x_display_list != 0)
156
	dpyinfo = x_display_list;
157 158 159
      else
	error ("X windows are not in use or not initialized");
    }
160
  else if (TERMINALP (object))
161
    {
162
      struct terminal *t = get_terminal (object, 1);
163

164
      if (t->type != output_x_window)
165
        error ("Terminal %d is not an X display", t->id);
166

167
      dpyinfo = t->display_info.x;
168
    }
169 170
  else if (STRINGP (object))
    dpyinfo = x_display_info_for_name (object);
171 172
  else
    {
Dmitry Antipov's avatar
Dmitry Antipov committed
173
      struct frame *f = decode_window_system_frame (object);
174
      dpyinfo = FRAME_DISPLAY_INFO (f);
175
    }
176 177

  return dpyinfo;
178
}
179

180
/* Store the screen positions of frame F into XPTR and YPTR.
181 182 183 184
   These are the positions of the containing window manager window,
   not Emacs's own window.  */

void
Dmitry Antipov's avatar
Dmitry Antipov committed
185
x_real_positions (struct frame *f, int *xptr, int *yptr)
186
{
187
  int win_x, win_y, outer_x IF_LINT (= 0), outer_y IF_LINT (= 0);
188 189 190
  int real_x = 0, real_y = 0;
  int had_errors = 0;
  Window win = f->output_data.x->parent_desc;
191 192
  Atom actual_type;
  unsigned long actual_size, bytes_remaining;
193
  int rc, actual_format;
194
  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
195 196 197 198
  long max_len = 400;
  Display *dpy = FRAME_X_DISPLAY (f);
  unsigned char *tmp_data = NULL;
  Atom target_type = XA_CARDINAL;
199

200
  block_input ();
201

202
  x_catch_errors (dpy);
203

204
  if (win == dpyinfo->root_window)
205 206 207 208 209 210 211
    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 (;;)
212
    {
213 214 215
      Window wm_window, rootw;
      Window *tmp_children;
      unsigned int tmp_nchildren;
216
      int success;
217

218 219
      success = XQueryTree (FRAME_X_DISPLAY (f), win, &rootw,
			    &wm_window, &tmp_children, &tmp_nchildren);
220

221
      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
222

223 224 225 226
      /* Don't free tmp_children if XQueryTree failed.  */
      if (! success)
	break;

227
      XFree (tmp_children);
228

229 230
      if (wm_window == rootw || had_errors)
        break;
231

232 233
      win = wm_window;
    }
234

235 236
  if (! had_errors)
    {
237
      unsigned int ign;
238
      Window child, rootw;
239

240 241 242 243 244 245 246 247 248 249 250 251 252 253
      /* Get the real coordinates for the WM window upper left corner */
      XGetGeometry (FRAME_X_DISPLAY (f), win,
                    &rootw, &real_x, &real_y, &ign, &ign, &ign, &ign);

      /* 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
      */
254
      XTranslateCoordinates (FRAME_X_DISPLAY (f),
255

256
			     /* From-window, to-window.  */
257
			     FRAME_DISPLAY_INFO (f)->root_window,
258
                             FRAME_X_WINDOW (f),
259

260
			     /* From-position, to-position.  */
261
                             real_x, real_y, &win_x, &win_y,
262

263 264
			     /* Child of win.  */
			     &child);
265

266
      if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
267
	{
268 269
          outer_x = win_x;
          outer_y = win_y;
270
	}
271 272 273
      else
        {
          XTranslateCoordinates (FRAME_X_DISPLAY (f),
274

275
                                 /* From-window, to-window.  */
276
                                 FRAME_DISPLAY_INFO (f)->root_window,
277
                                 FRAME_OUTER_WINDOW (f),
278

279 280
                                 /* From-position, to-position.  */
                                 real_x, real_y, &outer_x, &outer_y,
281

282 283
                                 /* Child of win.  */
                                 &child);
284
	}
285

286 287
      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
    }
288

289 290 291 292 293 294 295 296 297 298 299 300

  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)
        {
301
          unsigned int ign;
302
          Window rootw;
303
          long *fe = (long *)tmp_data;
304 305 306 307 308 309 310 311 312 313 314 315

          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);

316
  x_uncatch_errors ();
317

318
  unblock_input ();
319 320

  if (had_errors) return;
321

322 323 324 325 326
  f->x_pixels_diff = -win_x;
  f->y_pixels_diff = -win_y;

  FRAME_X_OUTPUT (f)->x_pixels_outer_diff = -outer_x;
  FRAME_X_OUTPUT (f)->y_pixels_outer_diff = -outer_y;
327 328 329

  *xptr = real_x;
  *yptr = real_y;
330 331
}

Jim Blandy's avatar
Jim Blandy committed
332

333

334 335 336 337

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

void
338
gamma_correct (struct frame *f, XColor *color)
339 340 341 342 343 344 345 346 347 348
{
  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;
    }
}


349
/* Decide if color named COLOR_NAME is valid for use on frame F.  If
350 351
   so, return the RGB values in COLOR.  If ALLOC_P,
   allocate the color.  Value is false if COLOR_NAME is invalid, or
352
   no color could be allocated.  */
353

354
bool
355
x_defined_color (struct frame *f, const char *color_name,
356
		 XColor *color, bool alloc_p)
Jim Blandy's avatar
Jim Blandy committed
357
{
358
  bool success_p = 0;
359 360
  Display *dpy = FRAME_X_DISPLAY (f);
  Colormap cmap = FRAME_X_COLORMAP (f);
Jim Blandy's avatar
Jim Blandy committed
361

362
  block_input ();
363 364 365 366
#ifdef USE_GTK
  success_p = xg_check_special_colors (f, color_name, color);
#endif
  if (!success_p)
367
    success_p = XParseColor (dpy, cmap, color_name, color) != 0;
368 369
  if (success_p && alloc_p)
    success_p = x_alloc_nearest_color (f, cmap, color);
370
  unblock_input ();
Jim Blandy's avatar
Jim Blandy committed
371

372
  return success_p;
Jim Blandy's avatar
Jim Blandy committed
373 374
}

375 376 377 378

/* 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
379

380
static int
Dmitry Antipov's avatar
Dmitry Antipov committed
381
x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color)
Jim Blandy's avatar
Jim Blandy committed
382
{
383
  XColor cdef;
Jim Blandy's avatar
Jim Blandy committed
384

385
  CHECK_STRING (color_name);
Jim Blandy's avatar
Jim Blandy committed
386

387 388 389
#if 0 /* 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.  */
390
  if (strcmp (SDATA (color_name), "black") == 0)
391
    return BLACK_PIX_DEFAULT (f);
392
  else if (strcmp (SDATA (color_name), "white") == 0)
393
    return WHITE_PIX_DEFAULT (f);
394
#endif
Jim Blandy's avatar
Jim Blandy committed
395

396
  /* Return MONO_COLOR for monochrome frames.  */
397
  if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
398
    return mono_color;
Jim Blandy's avatar
Jim Blandy committed
399

400
  /* x_defined_color is responsible for coping with failures
401
     by looking for a near-miss.  */
402
  if (x_defined_color (f, SSDATA (color_name), &cdef, 1))
403 404
    return cdef.pixel;

405
  signal_error ("Undefined color", color_name);
Jim Blandy's avatar
Jim Blandy committed
406
}
407 408


Jim Blandy's avatar
Jim Blandy committed
409

Gerd Moellmann's avatar
Gerd Moellmann committed
410 411 412 413 414
/* 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
415
x_set_wait_for_wm (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
Gerd Moellmann's avatar
Gerd Moellmann committed
416 417 418 419
{
  f->output_data.x->wait_for_wm = !NILP (new_value);
}

420 421 422 423 424 425 426 427 428 429 430
static void
x_set_tool_bar_position (struct frame *f,
                         Lisp_Object new_value,
                         Lisp_Object old_value)
{
  if (! EQ (new_value, Qleft) && ! EQ (new_value, Qright)
      && ! EQ (new_value, Qbottom) && ! EQ (new_value, Qtop))
    return;
  if (EQ (new_value, old_value)) return;

#ifdef USE_GTK
431 432
  xg_change_toolbar_position (f, new_value);
  fset_tool_bar_position (f, new_value);
433 434 435
#endif
}

436 437
#ifdef USE_GTK

438 439
/* 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.  */
440 441

int
Dmitry Antipov's avatar
Dmitry Antipov committed
442
xg_set_icon (struct frame *f, Lisp_Object file)
443
{
444 445
  int result = 0;
  Lisp_Object found;
446

447 448 449 450 451 452
  found = x_find_image_file (file);

  if (! NILP (found))
    {
      GdkPixbuf *pixbuf;
      GError *err = NULL;
453
      char *filename = SSDATA (found);
454
      block_input ();
455 456 457 458 459 460 461 462 463 464 465 466 467 468

      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);

	  result = 1;
	}
      else
	g_error_free (err);

469
      unblock_input ();
470 471 472
    }

  return result;
473
}
474 475

int
Dmitry Antipov's avatar
Dmitry Antipov committed
476
xg_set_icon_from_xpm_data (struct frame *f, const char **data)
477
{
478
  GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data);
479 480

  if (!pixbuf)
481
    return 0;
482

483
  gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf);
484 485 486
  g_object_unref (pixbuf);
  return 1;
}
487 488
#endif /* USE_GTK */

Gerd Moellmann's avatar
Gerd Moellmann committed
489

Jim Blandy's avatar
Jim Blandy committed
490
/* Functions called only from `x_set_frame_param'
Jim Blandy's avatar
Jim Blandy committed
491 492
   to set individual parameters.

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

498
static void
499
x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
500
{
501 502
  struct x_output *x = f->output_data.x;
  unsigned long fg, old_fg;
503

504
  fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
505 506
  old_fg = FRAME_FOREGROUND_PIXEL (f);
  FRAME_FOREGROUND_PIXEL (f) = fg;
507

508
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
509
    {
510
      Display *dpy = FRAME_X_DISPLAY (f);
511

512
      block_input ();
513 514
      XSetForeground (dpy, x->normal_gc, fg);
      XSetBackground (dpy, x->reverse_gc, fg);
515

516 517 518 519 520 521
      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);
	}
522

523
      unblock_input ();
524

525
      update_face_from_frame_parameter (f, Qforeground_color, arg);
526

527
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
528
        redraw_frame (f);
Jim Blandy's avatar
Jim Blandy committed
529
    }
530

531
  unload_color (f, old_fg);
Jim Blandy's avatar
Jim Blandy committed
532 533
}

534
static void
535
x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
536
{
537 538
  struct x_output *x = f->output_data.x;
  unsigned long bg;
Jim Blandy's avatar
Jim Blandy committed
539

540
  bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
541 542
  unload_color (f, FRAME_BACKGROUND_PIXEL (f));
  FRAME_BACKGROUND_PIXEL (f) = bg;
543

544
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
545
    {
546
      Display *dpy = FRAME_X_DISPLAY (f);
547

548
      block_input ();
549 550 551 552 553
      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
554 555 556 557
#ifdef USE_GTK
      xg_set_background_color (f, bg);
#endif

558 559 560 561 562 563 564 565
#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)
	  {
566
	    Window window = XSCROLL_BAR (bar)->x_window;
567 568 569 570
	    XSetWindowBackground (dpy, window, bg);
	  }
      }
#endif /* USE_TOOLKIT_SCROLL_BARS */
Jim Blandy's avatar
Jim Blandy committed
571

572
      unblock_input ();
573
      update_face_from_frame_parameter (f, Qbackground_color, arg);
574

575
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
576
        redraw_frame (f);
Jim Blandy's avatar
Jim Blandy committed
577 578 579
    }
}

580
static void
581
x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
582
{
583 584
  struct x_output *x = f->output_data.x;
  Display *dpy = FRAME_X_DISPLAY (f);
585
  Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
586
  Cursor hourglass_cursor, horizontal_drag_cursor, vertical_drag_cursor;
587
  unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
588
  unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f);
589

590
  /* Don't let pointers be invisible.  */
591
  if (mask_color == pixel)
592 593
    {
      x_free_colors (f, &pixel, 1);
Karoly Lorentey's avatar
Karoly Lorentey committed
594
      pixel = x_copy_color (f, FRAME_FOREGROUND_PIXEL (f));
595
    }
596

597 598
  unload_color (f, x->mouse_pixel);
  x->mouse_pixel = pixel;
Jim Blandy's avatar
Jim Blandy committed
599

600
  block_input ();
601

602
  /* It's not okay to crash if the user selects a screwy cursor.  */
603
  x_catch_errors (dpy);
604

605
  if (!NILP (Vx_pointer_shape))
Jim Blandy's avatar
Jim Blandy committed
606
    {
607
      CHECK_NUMBER (Vx_pointer_shape);
608
      cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape));
Jim Blandy's avatar
Jim Blandy committed
609 610
    }
  else
611 612
    cursor = XCreateFontCursor (dpy, XC_xterm);
  x_check_errors (dpy, "bad text pointer cursor: %s");
Jim Blandy's avatar
Jim Blandy committed
613

614
  if (!NILP (Vx_nontext_pointer_shape))
Jim Blandy's avatar
Jim Blandy committed
615
    {
616
      CHECK_NUMBER (Vx_nontext_pointer_shape);
617 618
      nontext_cursor
	= XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
Jim Blandy's avatar
Jim Blandy committed
619 620
    }
  else
621 622
    nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr);
  x_check_errors (dpy, "bad nontext pointer cursor: %s");
Jim Blandy's avatar
Jim Blandy committed
623

624
  if (!NILP (Vx_hourglass_pointer_shape))
625
    {
626
      CHECK_NUMBER (Vx_hourglass_pointer_shape);
627 628
      hourglass_cursor
	= XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
629 630
    }
  else
631 632
    hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
  x_check_errors (dpy, "bad hourglass pointer cursor: %s");
633

634
  if (!NILP (Vx_mode_pointer_shape))
Jim Blandy's avatar
Jim Blandy committed
635
    {
636
      CHECK_NUMBER (Vx_mode_pointer_shape);
637
      mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
Jim Blandy's avatar
Jim Blandy committed
638 639
    }
  else
640 641
    mode_cursor = XCreateFontCursor (dpy, XC_xterm);
  x_check_errors (dpy, "bad modeline pointer cursor: %s");
642

643
  if (!NILP (Vx_sensitive_text_pointer_shape))
644
    {
645
      CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
646
      hand_cursor
647
	= XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
648 649
    }
  else
650
    hand_cursor = XCreateFontCursor (dpy, XC_hand2);
Jim Blandy's avatar
Jim Blandy committed
651

652 653
  if (!NILP (Vx_window_horizontal_drag_shape))
    {
Paul Eggert's avatar
Paul Eggert committed
654
      CHECK_TYPE_RANGED_INTEGER (unsigned, Vx_window_horizontal_drag_shape);
655
      horizontal_drag_cursor
656
	= XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
657 658 659
    }
  else
    horizontal_drag_cursor
660
      = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
661

662 663 664 665 666 667 668 669 670 671
  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);

672
  /* Check and report errors with the above calls.  */
673
  x_check_errors (dpy, "can't set cursor shape: %s");
674
  x_uncatch_errors ();
675

Jim Blandy's avatar
Jim Blandy committed
676 677 678
  {
    XColor fore_color, back_color;

679
    fore_color.pixel = x->mouse_pixel;
680
    x_query_color (f, &fore_color);
Jim Blandy's avatar
Jim Blandy committed
681
    back_color.pixel = mask_color;
682
    x_query_color (f, &back_color);
683

684 685 686
    XRecolorCursor (dpy, cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
687
    XRecolorCursor (dpy, hand_cursor, &fore_color, &back_color);
688 689
    XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
690
    XRecolorCursor (dpy, vertical_drag_cursor, &fore_color, &back_color);
Jim Blandy's avatar
Jim Blandy committed
691 692
  }

693
  if (FRAME_X_WINDOW (f) != 0)
694 695
    XDefineCursor (dpy, FRAME_X_WINDOW (f),
                   f->output_data.x->current_cursor = cursor);
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715

  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;
716

717 718 719 720
  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
721

722 723 724 725
  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;
726

727 728 729 730 731
  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;

732
  XFlush (dpy);
733
  unblock_input ();
734 735

  update_face_from_frame_parameter (f, Qmouse_color, arg);
Jim Blandy's avatar
Jim Blandy committed
736 737
}

738
static void
739
x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
740
{
741
  unsigned long fore_pixel, pixel;
742
  bool fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
743
  struct x_output *x = f->output_data.x;
Jim Blandy's avatar
Jim Blandy committed
744

745 746 747 748 749 750
  if (!NILP (Vx_cursor_fore_pixel))
    {
      fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
				   WHITE_PIX_DEFAULT (f));
      fore_pixel_allocated_p = 1;
    }
Jim Blandy's avatar
Jim Blandy committed
751
  else
Karoly Lorentey's avatar
Karoly Lorentey committed
752
    fore_pixel = FRAME_BACKGROUND_PIXEL (f);
753

754
  pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
755
  pixel_allocated_p = 1;
756

757
  /* Make sure that the cursor color differs from the background color.  */
Karoly Lorentey's avatar
Karoly Lorentey committed
758
  if (pixel == FRAME_BACKGROUND_PIXEL (f))
Jim Blandy's avatar
Jim Blandy committed
759
    {
760 761 762 763 764
      if (pixel_allocated_p)
	{
	  x_free_colors (f, &pixel, 1);
	  pixel_allocated_p = 0;
	}
765

766
      pixel = x->mouse_pixel;
767
      if (pixel == fore_pixel)
768 769 770 771 772 773
	{
	  if (fore_pixel_allocated_p)
	    {
	      x_free_colors (f, &fore_pixel, 1);
	      fore_pixel_allocated_p = 0;
	    }
Karoly Lorentey's avatar
Karoly Lorentey committed
774
	  fore_pixel = FRAME_BACKGROUND_PIXEL (f);
775
	}
Jim Blandy's avatar
Jim Blandy committed
776
    }
777

778
  unload_color (f, x->cursor_foreground_pixel);
779 780
  if (!fore_pixel_allocated_p)
    fore_pixel = x_copy_color (f, fore_pixel);
781
  x->cursor_foreground_pixel = fore_pixel;
Jim Blandy's avatar
Jim Blandy committed
782

783
  unload_color (f, x->cursor_pixel);
784 785
  if (!pixel_allocated_p)
    pixel = x_copy_color (f, pixel);
786
  x->cursor_pixel = pixel;
787

Jim Blandy's avatar