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

205
  block_input ();
206

207
  x_catch_errors (dpy);
208

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

223 224
      success = XQueryTree (FRAME_X_DISPLAY (f), win, &rootw,
			    &wm_window, &tmp_children, &tmp_nchildren);
225

226
      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
227

228 229 230 231
      /* Don't free tmp_children if XQueryTree failed.  */
      if (! success)
	break;

232
      XFree (tmp_children);
233

234 235
      if (wm_window == rootw || had_errors)
        break;
236

237 238
      win = wm_window;
    }
239

240 241
  if (! had_errors)
    {
242
      unsigned int ign;
243
      Window child, rootw;
244

245 246
      /* Get the real coordinates for the WM window upper left corner */
      XGetGeometry (FRAME_X_DISPLAY (f), win,
247
                    &rootw, &real_x, &real_y, &ow, &oh, &ign, &ign);
248 249 250 251 252 253 254 255 256 257 258

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

261
			     /* From-window, to-window.  */
262
			     FRAME_DISPLAY_INFO (f)->root_window,
263
                             FRAME_X_WINDOW (f),
264

265
			     /* From-position, to-position.  */
266
                             real_x, real_y, &win_x, &win_y,
267

268 269
			     /* Child of win.  */
			     &child);
270

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

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

284 285
                                 /* From-position, to-position.  */
                                 real_x, real_y, &outer_x, &outer_y,
286

287 288
                                 /* Child of win.  */
                                 &child);
289
	}
290

291 292
      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
    }
293

294 295 296 297 298 299 300 301 302 303 304 305

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

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

321
  x_uncatch_errors ();
322

323
  unblock_input ();
324 325

  if (had_errors) return;
326

327 328 329 330 331
  if (x_pixels_diff) *x_pixels_diff = -win_x;
  if (y_pixels_diff) *y_pixels_diff = -win_y;

  if (left_offset_x) *left_offset_x = -outer_x;
  if (top_offset_y) *top_offset_y = -outer_x;
332

333 334
  if (xptr) *xptr = real_x;
  if (yptr) *yptr = real_y;
335

336
  if (right_offset_x || bottom_offset_y)
337 338 339 340 341 342 343 344 345 346
    {
      int xy_ign;
      unsigned int ign, fw, fh;
      Window rootw;

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

349 350 351 352 353 354 355 356 357 358 359
/* Store the screen positions of frame F into XPTR and YPTR.
   These are the positions of the containing window manager window,
   not Emacs's own window.  */

void
x_real_positions (struct frame *f, int *xptr, int *yptr)
{
  x_real_pos_and_offsets (f, NULL, NULL, NULL, NULL, NULL, NULL, xptr, yptr);
}


360
/* Get the mouse position in frame relative coordinates.  */
361

362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
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);

391 392 393 394 395
  XTranslateCoordinates (FRAME_X_DISPLAY (f),

                         /* From-window, to-window.  */
                         FRAME_DISPLAY_INFO (f)->root_window,
                         FRAME_X_WINDOW (f),
396

397 398 399 400 401 402 403
                         /* From-position, to-position.  */
                         *x, *y, x, y,

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

  unblock_input ();
404
}
405 406 407 408

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

void
409
gamma_correct (struct frame *f, XColor *color)
410 411 412 413 414 415 416 417 418 419
{
  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;
    }
}


420
/* Decide if color named COLOR_NAME is valid for use on frame F.  If
421 422
   so, return the RGB values in COLOR.  If ALLOC_P,
   allocate the color.  Value is false if COLOR_NAME is invalid, or
423
   no color could be allocated.  */
424

425
bool
426
x_defined_color (struct frame *f, const char *color_name,
427
		 XColor *color, bool alloc_p)
Jim Blandy's avatar
Jim Blandy committed
428
{
Paul Eggert's avatar
Paul Eggert committed
429
  bool success_p = false;
430 431
  Display *dpy = FRAME_X_DISPLAY (f);
  Colormap cmap = FRAME_X_COLORMAP (f);
Jim Blandy's avatar
Jim Blandy committed
432

433
  block_input ();
434 435 436 437
#ifdef USE_GTK
  success_p = xg_check_special_colors (f, color_name, color);
#endif
  if (!success_p)
438
    success_p = XParseColor (dpy, cmap, color_name, color) != 0;
439 440
  if (success_p && alloc_p)
    success_p = x_alloc_nearest_color (f, cmap, color);
441
  unblock_input ();
Jim Blandy's avatar
Jim Blandy committed
442

443
  return success_p;
Jim Blandy's avatar
Jim Blandy committed
444 445
}

446 447 448 449

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

451
static int
Dmitry Antipov's avatar
Dmitry Antipov committed
452
x_decode_color (struct frame *f, Lisp_Object color_name, int mono_color)
Jim Blandy's avatar
Jim Blandy committed
453
{
454
  XColor cdef;
Jim Blandy's avatar
Jim Blandy committed
455

456
  CHECK_STRING (color_name);
Jim Blandy's avatar
Jim Blandy committed
457

Paul Eggert's avatar
Paul Eggert committed
458 459 460
#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.  */
461
  if (strcmp (SDATA (color_name), "black") == 0)
462
    return BLACK_PIX_DEFAULT (f);
463
  else if (strcmp (SDATA (color_name), "white") == 0)
464
    return WHITE_PIX_DEFAULT (f);
465
#endif
Jim Blandy's avatar
Jim Blandy committed
466

467
  /* Return MONO_COLOR for monochrome frames.  */
468
  if (FRAME_DISPLAY_INFO (f)->n_planes == 1)
469
    return mono_color;
Jim Blandy's avatar
Jim Blandy committed
470

471
  /* x_defined_color is responsible for coping with failures
472
     by looking for a near-miss.  */
Paul Eggert's avatar
Paul Eggert committed
473
  if (x_defined_color (f, SSDATA (color_name), &cdef, true))
474 475
    return cdef.pixel;

476
  signal_error ("Undefined color", color_name);
Jim Blandy's avatar
Jim Blandy committed
477
}
478 479


Jim Blandy's avatar
Jim Blandy committed
480

Gerd Moellmann's avatar
Gerd Moellmann committed
481 482 483 484 485
/* 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
486
x_set_wait_for_wm (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
Gerd Moellmann's avatar
Gerd Moellmann committed
487 488 489 490
{
  f->output_data.x->wait_for_wm = !NILP (new_value);
}

491 492 493 494 495
static void
x_set_tool_bar_position (struct frame *f,
                         Lisp_Object new_value,
                         Lisp_Object old_value)
{
496
  Lisp_Object choice = list4 (Qleft, Qright, Qtop, Qbottom);
497

498 499
  if (!NILP (Fmemq (new_value, choice)))
    {
500
#ifdef USE_GTK
501 502 503 504 505 506 507 508
      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");
509
#endif
510 511 512
    }
  else
    wrong_choice (choice, new_value);
513 514
}

515 516
#ifdef USE_GTK

517 518
/* 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.  */
519

Paul Eggert's avatar
Paul Eggert committed
520
bool
Dmitry Antipov's avatar
Dmitry Antipov committed
521
xg_set_icon (struct frame *f, Lisp_Object file)
522
{
Paul Eggert's avatar
Paul Eggert committed
523
  bool result = false;
524
  Lisp_Object found;
525

526 527 528 529 530 531
  found = x_find_image_file (file);

  if (! NILP (found))
    {
      GdkPixbuf *pixbuf;
      GError *err = NULL;
532
      char *filename = SSDATA (found);
533
      block_input ();
534 535 536 537 538 539 540 541 542

      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
543
	  result = true;
544 545 546 547
	}
      else
	g_error_free (err);

548
      unblock_input ();
549 550 551
    }

  return result;
552
}
553

Paul Eggert's avatar
Paul Eggert committed
554
bool
Dmitry Antipov's avatar
Dmitry Antipov committed
555
xg_set_icon_from_xpm_data (struct frame *f, const char **data)
556
{
557
  GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data);
558 559

  if (!pixbuf)
Paul Eggert's avatar
Paul Eggert committed
560
    return false;
561

562
  gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf);
563
  g_object_unref (pixbuf);
Paul Eggert's avatar
Paul Eggert committed
564
  return true;
565
}
566 567
#endif /* USE_GTK */

Gerd Moellmann's avatar
Gerd Moellmann committed
568

Jim Blandy's avatar
Jim Blandy committed
569
/* Functions called only from `x_set_frame_param'
Jim Blandy's avatar
Jim Blandy committed
570 571
   to set individual parameters.

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

577
static void
578
x_set_foreground_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 fg, old_fg;
582

583
  fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
584 585
  old_fg = FRAME_FOREGROUND_PIXEL (f);
  FRAME_FOREGROUND_PIXEL (f) = fg;
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
      XSetForeground (dpy, x->normal_gc, fg);
      XSetBackground (dpy, x->reverse_gc, fg);
594

595 596 597 598 599 600
      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);
	}
601

602
      unblock_input ();
603

604
      update_face_from_frame_parameter (f, Qforeground_color, arg);
605

606
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
607
        redraw_frame (f);
Jim Blandy's avatar
Jim Blandy committed
608
    }
609

610
  unload_color (f, old_fg);
Jim Blandy's avatar
Jim Blandy committed
611 612
}

613
static void
614
x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
615
{
616 617
  struct x_output *x = f->output_data.x;
  unsigned long bg;
Jim Blandy's avatar
Jim Blandy committed
618

619
  bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
620 621
  unload_color (f, FRAME_BACKGROUND_PIXEL (f));
  FRAME_BACKGROUND_PIXEL (f) = bg;
622

623
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
624
    {
625
      Display *dpy = FRAME_X_DISPLAY (f);
626

627
      block_input ();
628 629 630 631 632
      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
633 634 635 636
#ifdef USE_GTK
      xg_set_background_color (f, bg);
#endif

637 638 639 640 641 642 643 644
#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)
	  {
645
	    Window window = XSCROLL_BAR (bar)->x_window;
646 647 648 649
	    XSetWindowBackground (dpy, window, bg);
	  }
      }
#endif /* USE_TOOLKIT_SCROLL_BARS */
Jim Blandy's avatar
Jim Blandy committed
650

651
      unblock_input ();
652
      update_face_from_frame_parameter (f, Qbackground_color, arg);
653

654
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
655
        redraw_frame (f);
Jim Blandy's avatar
Jim Blandy committed
656 657 658
    }
}

659
static void
660
x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
661
{
662 663
  struct x_output *x = f->output_data.x;
  Display *dpy = FRAME_X_DISPLAY (f);
664
  Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
665
  Cursor hourglass_cursor, horizontal_drag_cursor, vertical_drag_cursor;
666
  unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
667
  unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f);
668

669
  /* Don't let pointers be invisible.  */
670
  if (mask_color == pixel)
671 672
    {
      x_free_colors (f, &pixel, 1);
Karoly Lorentey's avatar
Karoly Lorentey committed
673
      pixel = x_copy_color (f, FRAME_FOREGROUND_PIXEL (f));
674
    }
675

676 677
  unload_color (f, x->mouse_pixel);
  x->mouse_pixel = pixel;
Jim Blandy's avatar
Jim Blandy committed
678

679
  block_input ();
680

681
  /* It's not okay to crash if the user selects a screwy cursor.  */
682
  x_catch_errors (dpy);
683

684
  if (!NILP (Vx_pointer_shape))
Jim Blandy's avatar
Jim Blandy committed
685
    {
686
      CHECK_NUMBER (Vx_pointer_shape);
687
      cursor = XCreateFontCursor (dpy, XINT (Vx_pointer_shape));
Jim Blandy's avatar
Jim Blandy committed
688 689
    }
  else
690 691
    cursor = XCreateFontCursor (dpy, XC_xterm);
  x_check_errors (dpy, "bad text pointer cursor: %s");
Jim Blandy's avatar
Jim Blandy committed
692

693
  if (!NILP (Vx_nontext_pointer_shape))
Jim Blandy's avatar
Jim Blandy committed
694
    {
695
      CHECK_NUMBER (Vx_nontext_pointer_shape);
696 697
      nontext_cursor
	= XCreateFontCursor (dpy, XINT (Vx_nontext_pointer_shape));
Jim Blandy's avatar
Jim Blandy committed
698 699
    }
  else
700 701
    nontext_cursor = XCreateFontCursor (dpy, XC_left_ptr);
  x_check_errors (dpy, "bad nontext pointer cursor: %s");
Jim Blandy's avatar
Jim Blandy committed
702

703
  if (!NILP (Vx_hourglass_pointer_shape))
704
    {
705
      CHECK_NUMBER (Vx_hourglass_pointer_shape);
706 707
      hourglass_cursor
	= XCreateFontCursor (dpy, XINT (Vx_hourglass_pointer_shape));
708 709
    }
  else
710 711
    hourglass_cursor = XCreateFontCursor (dpy, XC_watch);
  x_check_errors (dpy, "bad hourglass pointer cursor: %s");
712

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

722
  if (!NILP (Vx_sensitive_text_pointer_shape))
723
    {
724
      CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
725
      hand_cursor
726
	= XCreateFontCursor (dpy, XINT (Vx_sensitive_text_pointer_shape));
727 728
    }
  else
729
    hand_cursor = XCreateFontCursor (dpy, XC_hand2);
Jim Blandy's avatar
Jim Blandy committed
730

731 732
  if (!NILP (Vx_window_horizontal_drag_shape))
    {
Paul Eggert's avatar
Paul Eggert committed
733
      CHECK_TYPE_RANGED_INTEGER (unsigned, Vx_window_horizontal_drag_shape);
734
      horizontal_drag_cursor
735
	= XCreateFontCursor (dpy, XINT (Vx_window_horizontal_drag_shape));
736 737 738
    }
  else
    horizontal_drag_cursor
739
      = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
740

741 742 743 744 745 746 747 748 749 750
  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);

751
  /* Check and report errors with the above calls.  */
752
  x_check_errors (dpy, "can't set cursor shape: %s");
753
  x_uncatch_errors ();
754

Jim Blandy's avatar
Jim Blandy committed
755 756 757
  {
    XColor fore_color, back_color;

758
    fore_color.pixel = x->mouse_pixel;
759
    x_query_color (f, &fore_color);
Jim Blandy's avatar
Jim Blandy committed
760
    back_color.pixel = mask_color;
761
    x_query_color (f, &back_color);
762

763 764 765
    XRecolorCursor (dpy, cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, nontext_cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, mode_cursor, &fore_color, &back_color);
766
    XRecolorCursor (dpy, hand_cursor, &fore_color, &back_color);
767 768
    XRecolorCursor (dpy, hourglass_cursor, &fore_color, &back_color);
    XRecolorCursor (dpy, horizontal_drag_cursor, &fore_color, &back_color);
769
    XRecolorCursor (dpy, vertical_drag_cursor, &fore_color, &back_color);
Jim Blandy's avatar
Jim Blandy committed
770 771
  }

772
  if (FRAME_X_WINDOW (f) != 0)
773 774
    XDefineCursor (dpy, FRAME_X_WINDOW (f),
                   f->output_data.x->current_cursor = cursor);
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794

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

796 797 798 799
  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
800

801 802 803 804
  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;
805

806 807 808 809 810
  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;

811
  XFlush (dpy);
812
  unblock_input ();
813 814

  update_face_from_frame_parameter (f, Qmouse_color, arg);
Jim Blandy's avatar
Jim Blandy committed
815 816
}

817
static void
818
x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
819
{
820
  unsigned long fore_pixel, pixel;
Paul Eggert's avatar
Paul Eggert committed
821
  bool fore_pixel_allocated_p = false, pixel_allocated_p = false;
822
  struct x_output *x = f->output_data.x;
Jim Blandy's avatar
Jim Blandy committed
823

824 825 826 827
  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
828
      fore_pixel_allocated_p = true;
829
    }
Jim Blandy's avatar
Jim Blandy committed
830
  else
Karoly Lorentey's avatar
Karoly Lorentey committed
831
    fore_pixel = FRAME_BACKGROUND_PIXEL (f);
832

833
  pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Paul Eggert's avatar
Paul Eggert committed
834
  pixel_allocated_p = true;
835

836
  /* Make sure that the cursor color differs from the background color.  */
Karoly Lorentey's avatar
Karoly Lorentey committed
837
  if (pixel == FRAME_BACKGROUND_PIXEL (f))
Jim Blandy's avatar
Jim Blandy committed
838
    {
839 840 841
      if (pixel_allocated_p)
	{
	  x_free_colors (f, &pixel, 1);
Paul Eggert's avatar
Paul Eggert committed
842
	  pixel_allocated_p = false;
843
	}
844

845
      pixel = x->mouse_pixel;
846
      if (pixel == fore_pixel)
847 848 849 850
	{
	  if (fore_pixel_allocated_p)
	    {
	      x_free_colors (f, &fore_pixel, 1);
Paul Eggert's avatar
Paul Eggert committed
851
	      fore_pixel_allocated_p = false;
852
	    }
Karoly Lorentey's avatar
Karoly Lorentey committed
853
	  fore_pixel = FRAME_BACKGROUND_PIXEL (f);
854
	}
Jim Blandy's avatar
Jim Blandy committed
855
    }
856

857
  unload_color (f, x->cursor_foreground_pixel);
858 859
  if (!fore_pixel_allocated_p)
    fore_pixel = x_copy_color (f, fore_pixel);
860
  x->cursor_foreground_pixel = fore_pixel;
Jim Blandy's avatar
Jim Blandy committed
861

862
  unload_color (f, x->cursor_pixel);
863 864
  if (!pixel_allocated_p)
    pixel = x_copy_color (f, pixel);
865
  x->cursor_pixel = pixel;
866

867
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
868
    {
869
      block_input ();
870 871
      XSetBackground (FRAME_X_DISPLAY (f), x->cursor_gc, x->cursor_pixel);
      XSetForeground (FRAME_X_DISPLAY (f), x->cursor_gc, fore_pixel);
872
      unblock_input ();
Jim Blandy's avatar
Jim Blandy committed
873

874
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
875
	{
Paul Eggert's avatar
Paul Eggert committed
876 877
	  x_update_cursor (f, false);
	  x_update_cursor (f, true);
Jim Blandy's avatar
Jim Blandy committed
878 879
	}
    }
880 881

  update_face_from_frame_parameter (f, Qcursor_color, arg);
Jim Blandy's avatar
Jim Blandy committed
882
}
883

Jim Blandy's avatar
Jim Blandy committed
884
/* Set the border-color of frame F to pixel value PIX.
Jim Blandy's avatar
Jim Blandy committed
885
   Note that this does not fully take effect if done before
Jim Blandy's avatar
Jim Blandy committed
886
   F has an x-window.  */
Jim Blandy's avatar
Jim Blandy committed
887

888
static void