xfns.c 193 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
#ifdef GLYPH_DEBUG
124 125
static ptrdiff_t image_cache_refcount;
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
/* Store the screen positions of frame F into XPTR and YPTR.
172 173 174 175
   These are the positions of the containing window manager window,
   not Emacs's own window.  */

void
Dmitry Antipov's avatar
Dmitry Antipov committed
176
x_real_positions (struct frame *f, int *xptr, int *yptr)
177
{
178
  int win_x, win_y, outer_x IF_LINT (= 0), outer_y IF_LINT (= 0);
179
  int real_x = 0, real_y = 0;
Paul Eggert's avatar
Paul Eggert committed
180
  bool had_errors = false;
181
  Window win = f->output_data.x->parent_desc;
182 183
  Atom actual_type;
  unsigned long actual_size, bytes_remaining;
184
  int rc, actual_format;
185
  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
186 187 188 189
  long max_len = 400;
  Display *dpy = FRAME_X_DISPLAY (f);
  unsigned char *tmp_data = NULL;
  Atom target_type = XA_CARDINAL;
190

191
  block_input ();
192

193
  x_catch_errors (dpy);
194

195
  if (win == dpyinfo->root_window)
196 197 198 199 200 201 202
    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 (;;)
203
    {
204 205 206
      Window wm_window, rootw;
      Window *tmp_children;
      unsigned int tmp_nchildren;
207
      int success;
208

209 210
      success = XQueryTree (FRAME_X_DISPLAY (f), win, &rootw,
			    &wm_window, &tmp_children, &tmp_nchildren);
211

212
      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
213

214 215 216 217
      /* Don't free tmp_children if XQueryTree failed.  */
      if (! success)
	break;

218
      XFree (tmp_children);
219

220 221
      if (wm_window == rootw || had_errors)
        break;
222

223 224
      win = wm_window;
    }
225

226 227
  if (! had_errors)
    {
228
      unsigned int ign;
229
      Window child, rootw;
230

231 232 233 234 235 236 237 238 239 240 241 242 243 244
      /* 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
      */
245
      XTranslateCoordinates (FRAME_X_DISPLAY (f),
246

247
			     /* From-window, to-window.  */
248
			     FRAME_DISPLAY_INFO (f)->root_window,
249
                             FRAME_X_WINDOW (f),
250

251
			     /* From-position, to-position.  */
252
                             real_x, real_y, &win_x, &win_y,
253

254 255
			     /* Child of win.  */
			     &child);
256

257
      if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
258
	{
259 260
          outer_x = win_x;
          outer_y = win_y;
261
	}
262 263 264
      else
        {
          XTranslateCoordinates (FRAME_X_DISPLAY (f),
265

266
                                 /* From-window, to-window.  */
267
                                 FRAME_DISPLAY_INFO (f)->root_window,
268
                                 FRAME_OUTER_WINDOW (f),
269

270 271
                                 /* From-position, to-position.  */
                                 real_x, real_y, &outer_x, &outer_y,
272

273 274
                                 /* Child of win.  */
                                 &child);
275
	}
276

277 278
      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
    }
279

280 281 282 283 284 285 286 287 288 289 290 291

  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)
        {
292
          unsigned int ign;
293
          Window rootw;
294
          long *fe = (long *)tmp_data;
295 296 297 298 299 300 301 302 303 304 305 306

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

307
  x_uncatch_errors ();
308

309
  unblock_input ();
310 311

  if (had_errors) return;
312

313 314 315 316 317
  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;
318 319 320

  *xptr = real_x;
  *yptr = real_y;
321 322
}

323
/* Get the mouse position in frame relative coordinates.  */
324

325 326 327 328 329 330 331 332 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
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);
}
360 361 362 363

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

void
364
gamma_correct (struct frame *f, XColor *color)
365 366 367 368 369 370 371 372 373 374
{
  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;
    }
}


375
/* Decide if color named COLOR_NAME is valid for use on frame F.  If
376 377
   so, return the RGB values in COLOR.  If ALLOC_P,
   allocate the color.  Value is false if COLOR_NAME is invalid, or
378
   no color could be allocated.  */
379

380
bool
381
x_defined_color (struct frame *f, const char *color_name,
382
		 XColor *color, bool alloc_p)
Jim Blandy's avatar
Jim Blandy committed
383
{
Paul Eggert's avatar
Paul Eggert committed
384
  bool success_p = false;
385 386
  Display *dpy = FRAME_X_DISPLAY (f);
  Colormap cmap = FRAME_X_COLORMAP (f);
Jim Blandy's avatar
Jim Blandy committed
387

388
  block_input ();
389 390 391 392
#ifdef USE_GTK
  success_p = xg_check_special_colors (f, color_name, color);
#endif
  if (!success_p)
393
    success_p = XParseColor (dpy, cmap, color_name, color) != 0;
394 395
  if (success_p && alloc_p)
    success_p = x_alloc_nearest_color (f, cmap, color);
396
  unblock_input ();
Jim Blandy's avatar
Jim Blandy committed
397

398
  return success_p;
Jim Blandy's avatar
Jim Blandy committed
399 400
}

401 402 403 404

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

406
static int
Dmitry Antipov's avatar
Dmitry Antipov committed
407
x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color)
Jim Blandy's avatar
Jim Blandy committed
408
{
409
  XColor cdef;
Jim Blandy's avatar
Jim Blandy committed
410

411
  CHECK_STRING (color_name);
Jim Blandy's avatar
Jim Blandy committed
412

Paul Eggert's avatar
Paul Eggert committed
413 414 415
#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.  */
416
  if (strcmp (SDATA (color_name), "black") == 0)
417
    return BLACK_PIX_DEFAULT (f);
418
  else if (strcmp (SDATA (color_name), "white") == 0)
419
    return WHITE_PIX_DEFAULT (f);
420
#endif
Jim Blandy's avatar
Jim Blandy committed
421

422
  /* Return MONO_COLOR for monochrome frames.  */
423
  if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
424
    return mono_color;
Jim Blandy's avatar
Jim Blandy committed
425

426
  /* x_defined_color is responsible for coping with failures
427
     by looking for a near-miss.  */
Paul Eggert's avatar
Paul Eggert committed
428
  if (x_defined_color (f, SSDATA (color_name), &cdef, true))
429 430
    return cdef.pixel;

431
  signal_error ("Undefined color", color_name);
Jim Blandy's avatar
Jim Blandy committed
432
}
433 434


Jim Blandy's avatar
Jim Blandy committed
435

Gerd Moellmann's avatar
Gerd Moellmann committed
436 437 438 439 440
/* 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
441
x_set_wait_for_wm (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
Gerd Moellmann's avatar
Gerd Moellmann committed
442 443 444 445
{
  f->output_data.x->wait_for_wm = !NILP (new_value);
}

446 447 448 449 450
static void
x_set_tool_bar_position (struct frame *f,
                         Lisp_Object new_value,
                         Lisp_Object old_value)
{
451
  Lisp_Object choice = list4 (Qleft, Qright, Qtop, Qbottom);
452

453 454
  if (!NILP (Fmemq (new_value, choice)))
    {
455
#ifdef USE_GTK
456 457 458 459 460 461 462 463
      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");
464
#endif
465 466 467
    }
  else
    wrong_choice (choice, new_value);
468 469
}

470 471
#ifdef USE_GTK

472 473
/* 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.  */
474

Paul Eggert's avatar
Paul Eggert committed
475
bool
Dmitry Antipov's avatar
Dmitry Antipov committed
476
xg_set_icon (struct frame *f, Lisp_Object file)
477
{
Paul Eggert's avatar
Paul Eggert committed
478
  bool result = false;
479
  Lisp_Object found;
480

481 482 483 484 485 486
  found = x_find_image_file (file);

  if (! NILP (found))
    {
      GdkPixbuf *pixbuf;
      GError *err = NULL;
487
      char *filename = SSDATA (found);
488
      block_input ();
489 490 491 492 493 494 495 496 497

      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
498
	  result = true;
499 500 501 502
	}
      else
	g_error_free (err);

503
      unblock_input ();
504 505 506
    }

  return result;
507
}
508

Paul Eggert's avatar
Paul Eggert committed
509
bool
Dmitry Antipov's avatar
Dmitry Antipov committed
510
xg_set_icon_from_xpm_data (struct frame *f, const char **data)
511
{
512
  GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data);
513 514

  if (!pixbuf)
Paul Eggert's avatar
Paul Eggert committed
515
    return false;
516

517
  gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf);
518
  g_object_unref (pixbuf);
Paul Eggert's avatar
Paul Eggert committed
519
  return true;
520
}
521 522
#endif /* USE_GTK */

Gerd Moellmann's avatar
Gerd Moellmann committed
523

Jim Blandy's avatar
Jim Blandy committed
524
/* Functions called only from `x_set_frame_param'
Jim Blandy's avatar
Jim Blandy committed
525 526
   to set individual parameters.

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

532
static void
533
x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
534
{
535 536
  struct x_output *x = f->output_data.x;
  unsigned long fg, old_fg;
537

538
  fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
539 540
  old_fg = FRAME_FOREGROUND_PIXEL (f);
  FRAME_FOREGROUND_PIXEL (f) = fg;
541

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

546
      block_input ();
547 548
      XSetForeground (dpy, x->normal_gc, fg);
      XSetBackground (dpy, x->reverse_gc, fg);
549

550 551 552 553 554 555
      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);
	}
556

557
      unblock_input ();
558

559
      update_face_from_frame_parameter (f, Qforeground_color, arg);
560

561
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
562
        redraw_frame (f);
Jim Blandy's avatar
Jim Blandy committed
563
    }
564

565
  unload_color (f, old_fg);
Jim Blandy's avatar
Jim Blandy committed
566 567
}

568
static void
569
x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
570
{
571 572
  struct x_output *x = f->output_data.x;
  unsigned long bg;
Jim Blandy's avatar
Jim Blandy committed
573

574
  bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
575 576
  unload_color (f, FRAME_BACKGROUND_PIXEL (f));
  FRAME_BACKGROUND_PIXEL (f) = bg;
577

578
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
579
    {
580
      Display *dpy = FRAME_X_DISPLAY (f);
581

582
      block_input ();
583 584 585 586 587
      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
588 589 590 591
#ifdef USE_GTK
      xg_set_background_color (f, bg);
#endif

592 593 594 595 596 597 598 599
#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)
	  {
600
	    Window window = XSCROLL_BAR (bar)->x_window;
601 602 603 604
	    XSetWindowBackground (dpy, window, bg);
	  }
      }
#endif /* USE_TOOLKIT_SCROLL_BARS */
Jim Blandy's avatar
Jim Blandy committed
605

606
      unblock_input ();
607
      update_face_from_frame_parameter (f, Qbackground_color, arg);
608

609
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
610
        redraw_frame (f);
Jim Blandy's avatar
Jim Blandy committed
611 612 613
    }
}

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

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

631 632
  unload_color (f, x->mouse_pixel);
  x->mouse_pixel = pixel;
Jim Blandy's avatar
Jim Blandy committed
633

634
  block_input ();
635

636
  /* It's not okay to crash if the user selects a screwy cursor.  */
637
  x_catch_errors (dpy);
638

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

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

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

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

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

686 687
  if (!NILP (Vx_window_horizontal_drag_shape))
    {
Paul Eggert's avatar
Paul Eggert committed
688
      CHECK_TYPE_RANGED_INTEGER (unsigned, Vx_window_horizontal_drag_shape);
689
      horizontal_drag_cursor
690
	= XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
691 692 693
    }
  else
    horizontal_drag_cursor
694
      = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
695

696 697 698 699 700 701 702 703 704 705
  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);

706
  /* Check and report errors with the above calls.  */
707
  x_check_errors (dpy, "can't set cursor shape: %s");
708
  x_uncatch_errors ();
709

Jim Blandy's avatar
Jim Blandy committed
710 711 712
  {
    XColor fore_color, back_color;

713
    fore_color.pixel = x->mouse_pixel;
714
    x_query_color (f, &fore_color);
Jim Blandy's avatar
Jim Blandy committed
715
    back_color.pixel = mask_color;
716
    x_query_color (f, &back_color);
717

718 719 720
    XRecolorCursor (dpy, cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
721
    XRecolorCursor (dpy, hand_cursor, &fore_color, &back_color);
722 723
    XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
724
    XRecolorCursor (dpy, vertical_drag_cursor, &fore_color, &back_color);
Jim Blandy's avatar
Jim Blandy committed
725 726
  }

727
  if (FRAME_X_WINDOW (f) != 0)
728 729
    XDefineCursor (dpy, FRAME_X_WINDOW (f),
                   f->output_data.x->current_cursor = cursor);
730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749

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

751 752 753 754
  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
755

756 757 758 759
  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;
760

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

766
  XFlush (dpy);
767
  unblock_input ();
768 769

  update_face_from_frame_parameter (f, Qmouse_color, arg);
Jim Blandy's avatar
Jim Blandy committed
770 771
}

772
static void
773
x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
774
{
775
  unsigned long fore_pixel, pixel;
Paul Eggert's avatar
Paul Eggert committed
776
  bool fore_pixel_allocated_p = false, pixel_allocated_p = false;
777
  struct x_output *x = f->output_data.x;
Jim Blandy's avatar
Jim Blandy committed
778

779 780 781 782
  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
783
      fore_pixel_allocated_p = true;
784
    }
Jim Blandy's avatar
Jim Blandy committed
785
  else
Karoly Lorentey's avatar
Karoly Lorentey committed
786
    fore_pixel = FRAME_BACKGROUND_PIXEL (f);
787

788
  pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Paul Eggert's avatar
Paul Eggert committed
789
  pixel_allocated_p = true;
790

791
  /* Make sure that the cursor color differs from the background color.  */
Karoly Lorentey's avatar
Karoly Lorentey committed
792
  if (pixel == FRAME_BACKGROUND_PIXEL (f))
Jim Blandy's avatar
Jim Blandy committed
793
    {
794 795 796
      if (pixel_allocated_p)
	{
	  x_free_colors (f, &pixel, 1);
Paul Eggert's avatar
Paul Eggert committed
797
	  pixel_allocated_p = false;
798
	}
799

800
      pixel = x->mouse_pixel;
801
      if (pixel == fore_pixel)
802 803 804 805
	{
	  if (fore_pixel_allocated_p)
	    {
	      x_free_colors (f, &fore_pixel, 1);
Paul Eggert's avatar
Paul Eggert committed
806
	      fore_pixel_allocated_p = false;
807
	    }
Karoly Lorentey's avatar
Karoly Lorentey committed
808
	  fore_pixel = FRAME_BACKGROUND_PIXEL (f);
809
	}
Jim Blandy's avatar
Jim Blandy committed
810
    }
811

812
  unload_color (f, x->cursor_foreground_pixel);
813 814
  if (!fore_pixel_allocated_p)
    fore_pixel = x_copy_color (f, fore_pixel);
815
  x->cursor_foreground_pixel = fore_pixel;
Jim Blandy's avatar
Jim Blandy committed
816

817
  unload_color (f, x->cursor_pixel);
818 819
  if (!pixel_allocated_p)
    pixel = x_copy_color (f, pixel);
820
  x->cursor_pixel = pixel;
821

822
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
823
    {
824
      block_input ();
825 826
      XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
      XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
827
      unblock_input ();
Jim Blandy's avatar
Jim Blandy committed
828

829
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
830
	{
Paul Eggert's avatar
Paul Eggert committed
831 832
	  x_update_cursor (f, false);
	  x_update_cursor (f, true);
Jim Blandy's avatar
Jim Blandy committed
833 834
	}
    }
835 836

  update_face_from_frame_parameter (f, Qcursor_color, arg);
Jim Blandy's avatar
Jim Blandy committed
837
}
838

Jim Blandy's avatar
Jim Blandy committed
839
/* Set the border-color of frame F to pixel value PIX.
Jim Blandy's avatar
Jim Blandy committed
840
   Note that this does not fully take effect if done before
Jim Blandy's avatar
Jim Blandy committed
841
   F has an x-window.  */
Jim Blandy's avatar
Jim Blandy committed
842

843
static void
844
x_set_border_pixel (struct frame *f, int pix)
Jim Blandy's avatar
Jim Blandy committed
845
{
846
  unload_color (f, f->output_data.x->border_pixel);
847
  f->output_data.x->border_pixel = pix;
Jim Blandy's avatar
Jim Blandy committed
848

849
  if (FRAME_X_WINDOW (f) != 0 && f->border_width > 0)
Jim Blandy's avatar
Jim Blandy committed
850
    {
851
      block_input ();
Paul Eggert's avatar
Paul Eggert committed
852
      XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), pix);
853
      unblock_input ();
Jim Blandy's avatar
Jim Blandy committed
854

855
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
856
        redraw_frame (f);
Jim Blandy's avatar
Jim Blandy committed
857 858 859
    }
}

860 861 862 863 864 865 866 867 868
/* Set the border-color of frame F to value described by ARG.
   ARG can be a string naming a color.
   The border-color is used for the border that is drawn by the X server.
   Note that this does not fully take effect if done before
   F has an x-window; it must be redone when the window is created.

   Note: this is done in two routines because of the way X10 works.

   Note: under X11, this is normally the province of the window manager,
869
   and so emacs's border colors may be overridden.  */