xfns.c 188 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"
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
#if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work.  */
50 51
#include "bitmaps/gray.xbm"
#else
Jim Blandy's avatar
Jim Blandy committed
52
#include <X11/bitmaps/gray>
53
#endif
Jim Blandy's avatar
Jim Blandy committed
54

55 56
#include "xsettings.h"

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

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

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

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

#include "widget.h"

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

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

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

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

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

114 115
extern LWLIB_ID widget_id_tick;

116 117 118 119
#ifdef USE_MOTIF

#endif /* USE_MOTIF */

120 121
#endif /* USE_X_TOOLKIT */

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

#endif /* USE_GTK */

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

128 129
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
}

332
/* Get the mouse position in frame relative coordinates.  */
333

334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
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);

  unblock_input ();

  /* Translate root window coordinates to window coordinates.  */
  *x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
  *y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
}
369 370 371 372

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

void
373
gamma_correct (struct frame *f, XColor *color)
374 375 376 377 378 379 380 381 382 383
{
  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;
    }
}


384
/* Decide if color named COLOR_NAME is valid for use on frame F.  If
385 386
   so, return the RGB values in COLOR.  If ALLOC_P,
   allocate the color.  Value is false if COLOR_NAME is invalid, or
387
   no color could be allocated.  */
388

389
bool
390
x_defined_color (struct frame *f, const char *color_name,
391
		 XColor *color, bool alloc_p)
Jim Blandy's avatar
Jim Blandy committed
392
{
393
  bool success_p = 0;
394 395
  Display *dpy = FRAME_X_DISPLAY (f);
  Colormap cmap = FRAME_X_COLORMAP (f);
Jim Blandy's avatar
Jim Blandy committed
396

397
  block_input ();
398 399 400 401
#ifdef USE_GTK
  success_p = xg_check_special_colors (f, color_name, color);
#endif
  if (!success_p)
402
    success_p = XParseColor (dpy, cmap, color_name, color) != 0;
403 404
  if (success_p && alloc_p)
    success_p = x_alloc_nearest_color (f, cmap, color);
405
  unblock_input ();
Jim Blandy's avatar
Jim Blandy committed
406

407
  return success_p;
Jim Blandy's avatar
Jim Blandy committed
408 409
}

410 411 412 413

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

415
static int
Dmitry Antipov's avatar
Dmitry Antipov committed
416
x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color)
Jim Blandy's avatar
Jim Blandy committed
417
{
418
  XColor cdef;
Jim Blandy's avatar
Jim Blandy committed
419

420
  CHECK_STRING (color_name);
Jim Blandy's avatar
Jim Blandy committed
421

422 423 424
#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.  */
425
  if (strcmp (SDATA (color_name), "black") == 0)
426
    return BLACK_PIX_DEFAULT (f);
427
  else if (strcmp (SDATA (color_name), "white") == 0)
428
    return WHITE_PIX_DEFAULT (f);
429
#endif
Jim Blandy's avatar
Jim Blandy committed
430

431
  /* Return MONO_COLOR for monochrome frames.  */
432
  if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
433
    return mono_color;
Jim Blandy's avatar
Jim Blandy committed
434

435
  /* x_defined_color is responsible for coping with failures
436
     by looking for a near-miss.  */
437
  if (x_defined_color (f, SSDATA (color_name), &cdef, 1))
438 439
    return cdef.pixel;

440
  signal_error ("Undefined color", color_name);
Jim Blandy's avatar
Jim Blandy committed
441
}
442 443


Jim Blandy's avatar
Jim Blandy committed
444

Gerd Moellmann's avatar
Gerd Moellmann committed
445 446 447 448 449
/* 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
450
x_set_wait_for_wm (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
Gerd Moellmann's avatar
Gerd Moellmann committed
451 452 453 454
{
  f->output_data.x->wait_for_wm = !NILP (new_value);
}

455 456 457 458 459
static void
x_set_tool_bar_position (struct frame *f,
                         Lisp_Object new_value,
                         Lisp_Object old_value)
{
460
  Lisp_Object choice = list4 (Qleft, Qright, Qtop, Qbottom);
461

462 463
  if (!NILP (Fmemq (new_value, choice)))
    {
464
#ifdef USE_GTK
465 466 467 468 469 470 471 472
      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");
473
#endif
474 475 476
    }
  else
    wrong_choice (choice, new_value);
477 478
}

479 480
#ifdef USE_GTK

481 482
/* 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.  */
483 484

int
Dmitry Antipov's avatar
Dmitry Antipov committed
485
xg_set_icon (struct frame *f, Lisp_Object file)
486
{
487 488
  int result = 0;
  Lisp_Object found;
489

490 491 492 493 494 495
  found = x_find_image_file (file);

  if (! NILP (found))
    {
      GdkPixbuf *pixbuf;
      GError *err = NULL;
496
      char *filename = SSDATA (found);
497
      block_input ();
498 499 500 501 502 503 504 505 506 507 508 509 510 511

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

512
      unblock_input ();
513 514 515
    }

  return result;
516
}
517 518

int
Dmitry Antipov's avatar
Dmitry Antipov committed
519
xg_set_icon_from_xpm_data (struct frame *f, const char **data)
520
{
521
  GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data);
522 523

  if (!pixbuf)
524
    return 0;
525

526
  gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf);
527 528 529
  g_object_unref (pixbuf);
  return 1;
}
530 531
#endif /* USE_GTK */

Gerd Moellmann's avatar
Gerd Moellmann committed
532

Jim Blandy's avatar
Jim Blandy committed
533
/* Functions called only from `x_set_frame_param'
Jim Blandy's avatar
Jim Blandy committed
534 535
   to set individual parameters.

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

541
static void
542
x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
543
{
544 545
  struct x_output *x = f->output_data.x;
  unsigned long fg, old_fg;
546

547
  fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
548 549
  old_fg = FRAME_FOREGROUND_PIXEL (f);
  FRAME_FOREGROUND_PIXEL (f) = fg;
550

551
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
552
    {
553
      Display *dpy = FRAME_X_DISPLAY (f);
554

555
      block_input ();
556 557
      XSetForeground (dpy, x->normal_gc, fg);
      XSetBackground (dpy, x->reverse_gc, fg);
558

559 560 561 562 563 564
      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);
	}
565

566
      unblock_input ();
567

568
      update_face_from_frame_parameter (f, Qforeground_color, arg);
569

570
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
571
        redraw_frame (f);
Jim Blandy's avatar
Jim Blandy committed
572
    }
573

574
  unload_color (f, old_fg);
Jim Blandy's avatar
Jim Blandy committed
575 576
}

577
static void
578
x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
579
{
580 581
  struct x_output *x = f->output_data.x;
  unsigned long bg;
Jim Blandy's avatar
Jim Blandy committed
582

583
  bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
584 585
  unload_color (f, FRAME_BACKGROUND_PIXEL (f));
  FRAME_BACKGROUND_PIXEL (f) = bg;
586

587
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
588
    {
589
      Display *dpy = FRAME_X_DISPLAY (f);
590

591
      block_input ();
592 593 594 595 596
      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
597 598 599 600
#ifdef USE_GTK
      xg_set_background_color (f, bg);
#endif

601 602 603 604 605 606 607 608
#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)
	  {
609
	    Window window = XSCROLL_BAR (bar)->x_window;
610 611 612 613
	    XSetWindowBackground (dpy, window, bg);
	  }
      }
#endif /* USE_TOOLKIT_SCROLL_BARS */
Jim Blandy's avatar
Jim Blandy committed
614

615
      unblock_input ();
616
      update_face_from_frame_parameter (f, Qbackground_color, arg);
617

618
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
619
        redraw_frame (f);
Jim Blandy's avatar
Jim Blandy committed
620 621 622
    }
}

623
static void
624
x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
625
{
626 627
  struct x_output *x = f->output_data.x;
  Display *dpy = FRAME_X_DISPLAY (f);
628
  Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
629
  Cursor hourglass_cursor, horizontal_drag_cursor, vertical_drag_cursor;
630
  unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
631
  unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f);
632

633
  /* Don't let pointers be invisible.  */
634
  if (mask_color == pixel)
635 636
    {
      x_free_colors (f, &pixel, 1);
Karoly Lorentey's avatar
Karoly Lorentey committed
637
      pixel = x_copy_color (f, FRAME_FOREGROUND_PIXEL (f));
638
    }
639

640 641
  unload_color (f, x->mouse_pixel);
  x->mouse_pixel = pixel;
Jim Blandy's avatar
Jim Blandy committed
642

643
  block_input ();
644

645
  /* It's not okay to crash if the user selects a screwy cursor.  */
646
  x_catch_errors (dpy);
647

648
  if (!NILP (Vx_pointer_shape))
Jim Blandy's avatar
Jim Blandy committed
649
    {
650
      CHECK_NUMBER (Vx_pointer_shape);
651
      cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape));
Jim Blandy's avatar
Jim Blandy committed
652 653
    }
  else
654 655
    cursor = XCreateFontCursor (dpy, XC_xterm);
  x_check_errors (dpy, "bad text pointer cursor: %s");
Jim Blandy's avatar
Jim Blandy committed
656

657
  if (!NILP (Vx_nontext_pointer_shape))
Jim Blandy's avatar
Jim Blandy committed
658
    {
659
      CHECK_NUMBER (Vx_nontext_pointer_shape);
660 661
      nontext_cursor
	= XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
Jim Blandy's avatar
Jim Blandy committed
662 663
    }
  else
664 665
    nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr);
  x_check_errors (dpy, "bad nontext pointer cursor: %s");
Jim Blandy's avatar
Jim Blandy committed
666

667
  if (!NILP (Vx_hourglass_pointer_shape))
668
    {
669
      CHECK_NUMBER (Vx_hourglass_pointer_shape);
670 671
      hourglass_cursor
	= XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
672 673
    }
  else
674 675
    hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
  x_check_errors (dpy, "bad hourglass pointer cursor: %s");
676

677
  if (!NILP (Vx_mode_pointer_shape))
Jim Blandy's avatar
Jim Blandy committed
678
    {
679
      CHECK_NUMBER (Vx_mode_pointer_shape);
680
      mode_cursor = XCreateFontCursor (dpy, XINT (Vx_mode_pointer_shape));
Jim Blandy's avatar
Jim Blandy committed
681 682
    }
  else
683 684
    mode_cursor = XCreateFontCursor (dpy, XC_xterm);
  x_check_errors (dpy, "bad modeline pointer cursor: %s");
685

686
  if (!NILP (Vx_sensitive_text_pointer_shape))
687
    {
688
      CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
689
      hand_cursor
690
	= XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
691 692
    }
  else
693
    hand_cursor = XCreateFontCursor (dpy, XC_hand2);
Jim Blandy's avatar
Jim Blandy committed
694

695 696
  if (!NILP (Vx_window_horizontal_drag_shape))
    {
Paul Eggert's avatar
Paul Eggert committed
697
      CHECK_TYPE_RANGED_INTEGER (unsigned, Vx_window_horizontal_drag_shape);
698
      horizontal_drag_cursor
699
	= XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
700 701 702
    }
  else
    horizontal_drag_cursor
703
      = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
704

705 706 707 708 709 710 711 712 713 714
  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);

715
  /* Check and report errors with the above calls.  */
716
  x_check_errors (dpy, "can't set cursor shape: %s");
717
  x_uncatch_errors ();
718

Jim Blandy's avatar
Jim Blandy committed
719 720 721
  {
    XColor fore_color, back_color;

722
    fore_color.pixel = x->mouse_pixel;
723
    x_query_color (f, &fore_color);
Jim Blandy's avatar
Jim Blandy committed
724
    back_color.pixel = mask_color;
725
    x_query_color (f, &back_color);
726

727 728 729
    XRecolorCursor (dpy, cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
730
    XRecolorCursor (dpy, hand_cursor, &fore_color, &back_color);
731 732
    XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
733
    XRecolorCursor (dpy, vertical_drag_cursor, &fore_color, &back_color);
Jim Blandy's avatar
Jim Blandy committed
734 735
  }

736
  if (FRAME_X_WINDOW (f) != 0)
737 738
    XDefineCursor (dpy, FRAME_X_WINDOW (f),
                   f->output_data.x->current_cursor = cursor);
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758

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

760 761 762 763
  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
764

765 766 767 768
  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;
769

770 771 772 773 774
  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;

775
  XFlush (dpy);
776
  unblock_input ();
777 778

  update_face_from_frame_parameter (f, Qmouse_color, arg);
Jim Blandy's avatar
Jim Blandy committed
779 780
}

781
static void
782
x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
783
{
784
  unsigned long fore_pixel, pixel;
785
  bool fore_pixel_allocated_p = 0, pixel_allocated_p = 0;
786
  struct x_output *x = f->output_data.x;
Jim Blandy's avatar
Jim Blandy committed
787

788 789 790 791 792 793
  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
794
  else
Karoly Lorentey's avatar
Karoly Lorentey committed
795
    fore_pixel = FRAME_BACKGROUND_PIXEL (f);
796

797
  pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
798
  pixel_allocated_p = 1;
799

800
  /* Make sure that the cursor color differs from the background color.  */
Karoly Lorentey's avatar
Karoly Lorentey committed
801
  if (pixel == FRAME_BACKGROUND_PIXEL (f))
Jim Blandy's avatar
Jim Blandy committed
802
    {
803 804 805 806 807
      if (pixel_allocated_p)
	{
	  x_free_colors (f, &pixel, 1);
	  pixel_allocated_p = 0;
	}
808

809
      pixel = x->mouse_pixel;
810
      if (pixel == fore_pixel)
811 812 813 814 815 816
	{
	  if (fore_pixel_allocated_p)
	    {
	      x_free_colors (f, &fore_pixel, 1);
	      fore_pixel_allocated_p = 0;
	    }
Karoly Lorentey's avatar
Karoly Lorentey committed
817
	  fore_pixel = FRAME_BACKGROUND_PIXEL (f);
818
	}
Jim Blandy's avatar
Jim Blandy committed
819
    }
820

821
  unload_color (f, x->cursor_foreground_pixel);
822 823
  if (!fore_pixel_allocated_p)
    fore_pixel = x_copy_color (f, fore_pixel);
824
  x->cursor_foreground_pixel = fore_pixel;
Jim Blandy's avatar
Jim Blandy committed
825

826
  unload_color (f, x->cursor_pixel);
827 828
  if (!pixel_allocated_p)
    pixel = x_copy_color (f, pixel);
829
  x->cursor_pixel = pixel;
830

831
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
832
    {