xfns.c 184 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-2013 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"

Jim Blandy's avatar
Jim Blandy committed
45
#ifdef HAVE_X_WINDOWS
46

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

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

56 57
#include "xsettings.h"

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

69 70 71
#ifdef USE_X_TOOLKIT
#include <X11/Shell.h>

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

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

#include "widget.h"

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

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

104 105 106 107
#ifdef USE_LUCID
#include "../lwlib/xlwmenu.h"
#endif

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

113 114
/* Unique id counter for widgets created by the Lucid Widget Library.  */

115 116
extern LWLIB_ID widget_id_tick;

117 118 119 120
#ifdef USE_MOTIF

#endif /* USE_MOTIF */

121 122
#endif /* USE_X_TOOLKIT */

Kenichi Handa's avatar
Kenichi Handa committed
123 124 125 126
#ifdef USE_GTK

#endif /* USE_GTK */

Richard M. Stallman's avatar
Richard M. Stallman committed
127 128
#define MAXREQUEST(dpy) (XMaxRequestSize (dpy))

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

134
#ifdef GLYPH_DEBUG
135 136
static ptrdiff_t image_cache_refcount;
static int dpyinfo_refcount;
137 138
#endif

139 140
static struct x_display_info *x_display_info_for_name (Lisp_Object);

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

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

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

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

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

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

  return dpyinfo;
180
}
181

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

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

202
  block_input ();
203

204
  x_catch_errors (dpy);
205

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

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

223
      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
224

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

229
      XFree (tmp_children);
230

231 232
      if (wm_window == rootw || had_errors)
        break;
233

234 235
      win = wm_window;
    }
236

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

242 243 244 245 246 247 248 249 250 251 252 253 254 255
      /* 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
      */
256
      XTranslateCoordinates (FRAME_X_DISPLAY (f),
257

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

262
			     /* From-position, to-position.  */
263
                             real_x, real_y, &win_x, &win_y,
264

265 266
			     /* Child of win.  */
			     &child);
267

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

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

281 282
                                 /* From-position, to-position.  */
                                 real_x, real_y, &outer_x, &outer_y,
283

284 285
                                 /* Child of win.  */
                                 &child);
286
	}
287

288 289
      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
    }
290

291 292 293 294 295 296 297 298 299 300 301 302

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

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

318
  x_uncatch_errors ();
319

320
  unblock_input ();
321 322

  if (had_errors) return;
323

324 325 326 327 328
  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;
329 330 331

  *xptr = real_x;
  *yptr = real_y;
332 333
}

Jim Blandy's avatar
Jim Blandy committed
334

335

336 337 338 339

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

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


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

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

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

374
  return success_p;
Jim Blandy's avatar
Jim Blandy committed
375 376
}

377 378 379 380

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

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

387
  CHECK_STRING (color_name);
Jim Blandy's avatar
Jim Blandy committed
388

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

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

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

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


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

422 423 424 425 426 427 428 429 430 431 432
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
433 434
  xg_change_toolbar_position (f, new_value);
  fset_tool_bar_position (f, new_value);
435 436 437
#endif
}

438 439
#ifdef USE_GTK

440 441
/* 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.  */
442 443

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

449 450 451 452 453 454
  found = x_find_image_file (file);

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

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

471
      unblock_input ();
472 473 474
    }

  return result;
475
}
476 477

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

  if (!pixbuf)
483
    return 0;
484

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

Gerd Moellmann's avatar
Gerd Moellmann committed
491

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

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

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

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

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

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

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

525
      unblock_input ();
526

527
      update_face_from_frame_parameter (f, Qforeground_color, arg);
528

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

533
  unload_color (f, old_fg);
Jim Blandy's avatar
Jim Blandy committed
534 535
}

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

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

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

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

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

574
      unblock_input ();
575
      update_face_from_frame_parameter (f, Qbackground_color, arg);
576

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

582
static Cursor
583
make_invisible_cursor (struct frame *f)
584 585 586 587 588
{
  Display *dpy = FRAME_X_DISPLAY (f);
  static char const no_data[] = { 0 };
  Pixmap pix;
  XColor col;
589
  Cursor c = 0;
590 591

  x_catch_errors (dpy);
592
  pix = XCreateBitmapFromData (dpy, FRAME_DISPLAY_INFO (f)->root_window,
593 594 595
                               no_data, 1, 1);
  if (! x_had_errors_p (dpy) && pix != None)
    {
596
      Cursor pixc;
597 598 599
      col.pixel = 0;
      col.red = col.green = col.blue = 0;
      col.flags = DoRed | DoGreen | DoBlue;
600 601 602
      pixc = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 0, 0);
      if (! x_had_errors_p (dpy) && pixc != None)
        c = pixc;
603 604 605 606 607 608 609 610
      XFreePixmap (dpy, pix);
    }

  x_uncatch_errors ();

  return c;
}

611
static void
612
x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
613
{
614 615
  struct x_output *x = f->output_data.x;
  Display *dpy = FRAME_X_DISPLAY (f);
616
  Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
617
  Cursor hourglass_cursor, horizontal_drag_cursor;
618
  unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
619
  unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f);
620

621
  /* Don't let pointers be invisible.  */
622
  if (mask_color == pixel)
623 624
    {
      x_free_colors (f, &pixel, 1);
Karoly Lorentey's avatar
Karoly Lorentey committed
625
      pixel = x_copy_color (f, FRAME_FOREGROUND_PIXEL (f));
626
    }
627

628 629
  unload_color (f, x->mouse_pixel);
  x->mouse_pixel = pixel;
Jim Blandy's avatar
Jim Blandy committed
630

631
  block_input ();
632

633
  /* It's not okay to crash if the user selects a screwy cursor.  */
634
  x_catch_errors (dpy);
635

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

645
  if (!NILP (Vx_nontext_pointer_shape))
Jim Blandy's avatar
Jim Blandy committed
646
    {
647
      CHECK_NUMBER (Vx_nontext_pointer_shape);
648 649
      nontext_cursor
	= XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
Jim Blandy's avatar
Jim Blandy committed
650 651
    }
  else
652 653
    nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr);
  x_check_errors (dpy, "bad nontext pointer cursor: %s");
Jim Blandy's avatar
Jim Blandy committed
654

655
  if (!NILP (Vx_hourglass_pointer_shape))
656
    {
657
      CHECK_NUMBER (Vx_hourglass_pointer_shape);
658 659
      hourglass_cursor
	= XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
660 661
    }
  else
662 663
    hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
  x_check_errors (dpy, "bad hourglass pointer cursor: %s");
664

665
  if (!NILP (Vx_mode_pointer_shape))
Jim Blandy's avatar
Jim Blandy committed
666
    {
667
      CHECK_NUMBER (Vx_mode_pointer_shape);
668
      mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
Jim Blandy's avatar
Jim Blandy committed
669 670
    }
  else
671 672
    mode_cursor = XCreateFontCursor (dpy, XC_xterm);
  x_check_errors (dpy, "bad modeline pointer cursor: %s");
673

674
  if (!NILP (Vx_sensitive_text_pointer_shape))
675
    {
676
      CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
677
      hand_cursor
678
	= XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
679 680
    }
  else
681
    hand_cursor = XCreateFontCursor (dpy, XC_hand2);
Jim Blandy's avatar
Jim Blandy committed
682

683 684
  if (!NILP (Vx_window_horizontal_drag_shape))
    {
685
      CHECK_NUMBER (Vx_window_horizontal_drag_shape);
686
      horizontal_drag_cursor
687
	= XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
688 689 690
    }
  else
    horizontal_drag_cursor
691
      = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
692

693
  /* Check and report errors with the above calls.  */
694
  x_check_errors (dpy, "can't set cursor shape: %s");
695
  x_uncatch_errors ();
696

Jim Blandy's avatar
Jim Blandy committed
697 698 699
  {
    XColor fore_color, back_color;

700
    fore_color.pixel = x->mouse_pixel;
701
    x_query_color (f, &fore_color);
Jim Blandy's avatar
Jim Blandy committed
702
    back_color.pixel = mask_color;
703
    x_query_color (f, &back_color);
704

705 706 707
    XRecolorCursor (dpy, cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
708
    XRecolorCursor (dpy, hand_cursor, &fore_color, &back_color);
709 710
    XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
Jim Blandy's avatar
Jim Blandy committed
711 712
  }

713
  if (FRAME_X_WINDOW (f) != 0)
714 715
    XDefineCursor (dpy, FRAME_X_WINDOW (f),
                   f->output_data.x->current_cursor = cursor);
716

717 718
  if (FRAME_DISPLAY_INFO (f)->invisible_cursor == 0)
    FRAME_DISPLAY_INFO (f)->invisible_cursor = make_invisible_cursor (f);
719

720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738
  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;
739

740 741 742 743
  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
744

745 746 747 748
  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;
749

750
  XFlush (dpy);
751
  unblock_input ();
752 753

  update_face_from_frame_parameter (f, Qmouse_color, arg);
Jim Blandy's avatar
Jim Blandy committed
754 755
}

756
static void
757
x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
758
{
759
  unsigned long fore_pixel, pixel;
760
  bool fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
761
  struct x_output *x = f->output_data.x;
Jim Blandy's avatar
Jim Blandy committed
762

763 764 765 766 767 768
  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
769
  else
Karoly Lorentey's avatar
Karoly Lorentey committed
770
    fore_pixel = FRAME_BACKGROUND_PIXEL (f);
771

772
  pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
773
  pixel_allocated_p = 1;
774

775
  /* Make sure that the cursor color differs from the background color.  */
Karoly Lorentey's avatar
Karoly Lorentey committed
776
  if (pixel == FRAME_BACKGROUND_PIXEL (f))
Jim Blandy's avatar
Jim Blandy committed
777
    {
778 779 780 781 782
      if (pixel_allocated_p)
	{
	  x_free_colors (f, &pixel, 1);
	  pixel_allocated_p = 0;
	}
783

784
      pixel = x->mouse_pixel;
785
      if (pixel == fore_pixel)
786 787 788 789 790 791
	{
	  if (fore_pixel_allocated_p)
	    {
	      x_free_colors (f, &fore_pixel, 1);
	      fore_pixel_allocated_p = 0;
	    }
Karoly Lorentey's avatar
Karoly Lorentey committed
792
	  fore_pixel = FRAME_BACKGROUND_PIXEL (f);
793
	}
Jim Blandy's avatar
Jim Blandy committed
794
    }
795

796
  unload_color (f, x->cursor_foreground_pixel);
797 798
  if (!fore_pixel_allocated_p)
    fore_pixel = x_copy_color (f, fore_pixel);
799
  x->cursor_foreground_pixel = fore_pixel;
Jim Blandy's avatar
Jim Blandy committed
800

801
  unload_color (f, x->cursor_pixel);
802 803
  if (!pixel_allocated_p)
    pixel = x_copy_color (f, pixel);
804
  x->cursor_pixel = pixel;
805

806
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
807
    {
808
      block_input ();
809 810
      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