xfns.c 178 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-2011  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
#include <setjmp.h>
24
#include <ctype.h>
25 26
#include <unistd.h>

27
/* This makes the fields of a Display accessible, in Xlib header files.  */
28

29 30
#define XLIB_ILLEGAL_ACCESS

Jim Blandy's avatar
Jim Blandy committed
31 32
#include "lisp.h"
#include "xterm.h"
Jim Blandy's avatar
Jim Blandy committed
33
#include "frame.h"
Jim Blandy's avatar
Jim Blandy committed
34 35
#include "window.h"
#include "buffer.h"
Kenichi Handa's avatar
Kenichi Handa committed
36
#include "intervals.h"
Jim Blandy's avatar
Jim Blandy committed
37
#include "dispextern.h"
Jim Blandy's avatar
Jim Blandy committed
38
#include "keyboard.h"
39
#include "blockinput.h"
40
#include <epaths.h>
Kenichi Handa's avatar
Kenichi Handa committed
41
#include "character.h"
Karl Heuer's avatar
Karl Heuer committed
42
#include "charset.h"
Kenichi Handa's avatar
Kenichi Handa committed
43
#include "coding.h"
Karl Heuer's avatar
Karl Heuer committed
44
#include "fontset.h"
45 46
#include "systime.h"
#include "termhooks.h"
47
#include "atimer.h"
48
#include "termchar.h"
Kenichi Handa's avatar
Kenichi Handa committed
49 50
#include "font.h"

Jim Blandy's avatar
Jim Blandy committed
51
#ifdef HAVE_X_WINDOWS
52 53

#include <ctype.h>
54 55
#include <sys/types.h>
#include <sys/stat.h>
Jim Blandy's avatar
Jim Blandy committed
56

57
#if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work.  */
58 59
#include "bitmaps/gray.xbm"
#else
Jim Blandy's avatar
Jim Blandy committed
60
#include <X11/bitmaps/gray>
61
#endif
Jim Blandy's avatar
Jim Blandy committed
62

63 64
#include "xsettings.h"

Jan Djärv's avatar
Jan Djärv committed
65 66 67 68
#ifdef USE_GTK
#include "gtkutil.h"
#endif

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

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

#ifdef USG
#undef USG	/* ####KLUDGE for Solaris 2.2 and up */
#include <X11/Xos.h>
#define USG
#else
#include <X11/Xos.h>
#endif

#include "widget.h"

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

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

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

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

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

113 114
extern LWLIB_ID widget_id_tick;

115
extern void free_frame_menubar ();
116
extern double atof ();
117

118 119 120 121
#ifdef USE_MOTIF

#endif /* USE_MOTIF */

122 123
#endif /* USE_X_TOOLKIT */

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

#endif /* USE_GTK */

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

130 131 132 133 134 135
/* The gray bitmap `bitmaps/gray'.  This is done because xterm.c uses
   it, and including `bitmaps/gray' more than once is a problem when
   config.h defines `static' as an empty replacement string.  */

int gray_bitmap_width = gray_width;
int gray_bitmap_height = gray_height;
136
char *gray_bitmap_bits = gray_bits;
137

138
/* Nonzero if using X.  */
139

140
static int x_in_use;
Jim Blandy's avatar
Jim Blandy committed
141

142
Lisp_Object Qnone;
143
Lisp_Object Qsuppress_icon;
Jim Blandy's avatar
Jim Blandy committed
144
Lisp_Object Qundefined_color;
145
Lisp_Object Qcompound_text, Qcancel_timer;
146
Lisp_Object Qfont_param;
Jim Blandy's avatar
Jim Blandy committed
147

148
#if GLYPH_DEBUG
149 150 151
int image_cache_refcount, dpyinfo_refcount;
#endif

152 153 154
#if defined (USE_GTK) && defined (HAVE_FREETYPE)
char *x_last_font_name;
#endif
155

Jim Blandy's avatar
Jim Blandy committed
156

Richard M. Stallman's avatar
Richard M. Stallman committed
157
/* Error if we are not connected to X.  */
158

Karl Heuer's avatar
Karl Heuer committed
159
void
160
check_x (void)
Richard M. Stallman's avatar
Richard M. Stallman committed
161
{
162
  if (! x_in_use)
Richard M. Stallman's avatar
Richard M. Stallman committed
163 164 165
    error ("X windows are not in use or not initialized");
}

166 167
/* Nonzero if we can use mouse menus.
   You should not call this unless HAVE_MENUS is defined.  */
168 169

int
170
have_menus_p (void)
171
{
172 173 174 175 176 177 178
  return x_in_use;
}

/* Extract a frame as a FRAME_PTR, defaulting to the selected frame
   and checking validity for X.  */

FRAME_PTR
179
check_x_frame (Lisp_Object frame)
180 181 182 183
{
  FRAME_PTR f;

  if (NILP (frame))
Gerd Moellmann's avatar
Gerd Moellmann committed
184
    frame = selected_frame;
185
  CHECK_LIVE_FRAME (frame);
Gerd Moellmann's avatar
Gerd Moellmann committed
186
  f = XFRAME (frame);
187
  if (! FRAME_X_P (f))
188
    error ("Non-X frame used");
189
  return f;
190 191
}

192
/* Let the user specify an X display with a Lisp object.
193
   OBJECT may be nil, a frame or a terminal object.
194 195 196
   nil stands for the selected frame--or, if that is not an X frame,
   the first X display on the list.  */

197
struct x_display_info *
198
check_x_display_info (Lisp_Object object)
199
{
200
  struct x_display_info *dpyinfo = NULL;
201

202
  if (NILP (object))
203
    {
Gerd Moellmann's avatar
Gerd Moellmann committed
204
      struct frame *sf = XFRAME (selected_frame);
205

Gerd Moellmann's avatar
Gerd Moellmann committed
206
      if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
207
	dpyinfo = FRAME_X_DISPLAY_INFO (sf);
208
      else if (x_display_list != 0)
209
	dpyinfo = x_display_list;
210 211 212
      else
	error ("X windows are not in use or not initialized");
    }
213
  else if (TERMINALP (object))
214
    {
215
      struct terminal *t = get_terminal (object, 1);
216

217 218
      if (t->type != output_x_window)
        error ("Terminal %d is not an X display", XINT (object));
219

220
      dpyinfo = t->display_info.x;
221
    }
222 223
  else if (STRINGP (object))
    dpyinfo = x_display_info_for_name (object);
224 225
  else
    {
226
      FRAME_PTR f = check_x_frame (object);
227
      dpyinfo = FRAME_X_DISPLAY_INFO (f);
228
    }
229 230

  return dpyinfo;
231
}
232

233

Jim Blandy's avatar
Jim Blandy committed
234 235
/* Return the Emacs frame-object corresponding to an X window.
   It could be the frame's main window or an icon window.  */
Jim Blandy's avatar
Jim Blandy committed
236

237
/* This function can be called during GC, so use GC_xxx type test macros.  */
238

Jim Blandy's avatar
Jim Blandy committed
239
struct frame *
240
x_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
Jim Blandy's avatar
Jim Blandy committed
241
{
Jim Blandy's avatar
Jim Blandy committed
242 243
  Lisp_Object tail, frame;
  struct frame *f;
Jim Blandy's avatar
Jim Blandy committed
244

245 246
  if (wdesc == None) return 0;

247
  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
Jim Blandy's avatar
Jim Blandy committed
248
    {
249
      frame = XCAR (tail);
250
      if (!FRAMEP (frame))
Jim Blandy's avatar
Jim Blandy committed
251
        continue;
Jim Blandy's avatar
Jim Blandy committed
252
      f = XFRAME (frame);
253
      if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
254
	continue;
255
      if (f->output_data.x->hourglass_window == wdesc)
256
	return f;
257
#ifdef USE_X_TOOLKIT
258
      if ((f->output_data.x->edit_widget
259
	   && XtWindow (f->output_data.x->edit_widget) == wdesc)
260 261 262
	  /* A tooltip frame?  */
	  || (!f->output_data.x->edit_widget
	      && FRAME_X_WINDOW (f) == wdesc)
263
          || f->output_data.x->icon_desc == wdesc)
264 265
        return f;
#else /* not USE_X_TOOLKIT */
Jan Djärv's avatar
Jan Djärv committed
266 267 268
#ifdef USE_GTK
      if (f->output_data.x->edit_widget)
      {
Kenichi Handa's avatar
Kenichi Handa committed
269
        GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
Jan Djärv's avatar
Jan Djärv committed
270 271 272 273 274
        struct x_output *x = f->output_data.x;
        if (gwdesc != 0 && gwdesc == x->edit_widget)
          return f;
      }
#endif /* USE_GTK */
275
      if (FRAME_X_WINDOW (f) == wdesc
276
          || f->output_data.x->icon_desc == wdesc)
Jim Blandy's avatar
Jim Blandy committed
277
        return f;
278 279 280 281 282
#endif /* not USE_X_TOOLKIT */
    }
  return 0;
}

Jan Djärv's avatar
Jan Djärv committed
283
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
284 285 286 287
/* Like x_window_to_frame but also compares the window with the widget's
   windows.  */

struct frame *
288
x_any_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
289 290
{
  Lisp_Object tail, frame;
291
  struct frame *f, *found;
292
  struct x_output *x;
293

294 295
  if (wdesc == None) return NULL;

296
  found = NULL;
297
  for (tail = Vframe_list; CONSP (tail) && !found; tail = XCDR (tail))
298
    {
299
      frame = XCAR (tail);
300
      if (!FRAMEP (frame))
301
        continue;
302

303
      f = XFRAME (frame);
304
      if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
305
	{
306 307
	  /* This frame matches if the window is any of its widgets.  */
	  x = f->output_data.x;
308
	  if (x->hourglass_window == wdesc)
309 310 311
	    found = f;
	  else if (x->widget)
	    {
Jan Djärv's avatar
Jan Djärv committed
312
#ifdef USE_GTK
Kenichi Handa's avatar
Kenichi Handa committed
313
              GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
Jan Djärv's avatar
Jan Djärv committed
314
              if (gwdesc != 0
315
                  && gtk_widget_get_toplevel (gwdesc) == x->widget)
Jan Djärv's avatar
Jan Djärv committed
316 317
                found = f;
#else
318 319
	      if (wdesc == XtWindow (x->widget)
		  || wdesc == XtWindow (x->column_widget)
320 321 322 323 324
		  || wdesc == XtWindow (x->edit_widget))
		found = f;
	      /* Match if the window is this frame's menubar.  */
	      else if (lw_window_is_in_menubar (wdesc, x->menubar_widget))
		found = f;
Jan Djärv's avatar
Jan Djärv committed
325
#endif
326 327 328 329
	    }
	  else if (FRAME_X_WINDOW (f) == wdesc)
	    /* A tooltip frame.  */
	    found = f;
330
	}
Jim Blandy's avatar
Jim Blandy committed
331
    }
332

333
  return found;
Jim Blandy's avatar
Jim Blandy committed
334
}
335

336 337 338
/* Likewise, but consider only the menu bar widget.  */

struct frame *
339
x_menubar_window_to_frame (struct x_display_info *dpyinfo, XEvent *event)
340
{
Jan D's avatar
Jan D committed
341
  Window wdesc = event->xany.window;
342 343
  Lisp_Object tail, frame;
  struct frame *f;
344
  struct x_output *x;
345

346 347
  if (wdesc == None) return 0;

348
  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
349
    {
350
      frame = XCAR (tail);
351
      if (!FRAMEP (frame))
352 353
        continue;
      f = XFRAME (frame);
354
      if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
355
	continue;
356
      x = f->output_data.x;
Jan Djärv's avatar
Jan Djärv committed
357
#ifdef USE_GTK
Jan D's avatar
Jan D committed
358 359
      if (x->menubar_widget && xg_event_is_for_menubar (f, event))
        return f;
Jan Djärv's avatar
Jan Djärv committed
360
#else
Jan D's avatar
Jan D committed
361
      /* Match if the window is this frame's menubar.  */
362 363
      if (x->menubar_widget
	  && lw_window_is_in_menubar (wdesc, x->menubar_widget))
364
	return f;
Jan Djärv's avatar
Jan Djärv committed
365
#endif
366 367 368 369
    }
  return 0;
}

370 371 372 373
/* Return the frame whose principal (outermost) window is WDESC.
   If WDESC is some other (smaller) window, we return 0.  */

struct frame *
374
x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
375 376 377
{
  Lisp_Object tail, frame;
  struct frame *f;
378
  struct x_output *x;
379

380 381
  if (wdesc == None) return 0;

382
  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
383
    {
384
      frame = XCAR (tail);
385
      if (!FRAMEP (frame))
386 387
        continue;
      f = XFRAME (frame);
388
      if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
389
	continue;
390
      x = f->output_data.x;
391 392 393 394

      if (x->widget)
	{
	  /* This frame matches if the window is its topmost widget.  */
Jan Djärv's avatar
Jan Djärv committed
395
#ifdef USE_GTK
Kenichi Handa's avatar
Kenichi Handa committed
396
          GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
Jan Djärv's avatar
Jan Djärv committed
397 398 399
          if (gwdesc == x->widget)
            return f;
#else
400 401
	  if (wdesc == XtWindow (x->widget))
	    return f;
402 403 404
#if 0 /* I don't know why it did this,
	 but it seems logically wrong,
	 and it causes trouble for MapNotify events.  */
405
	  /* Match if the window is this frame's menubar.  */
406
	  if (x->menubar_widget
407 408
	      && wdesc == XtWindow (x->menubar_widget))
	    return f;
Jan Djärv's avatar
Jan Djärv committed
409
#endif
410
#endif
411 412 413 414
	}
      else if (FRAME_X_WINDOW (f) == wdesc)
	/* Tooltip frame.  */
	return f;
415 416 417
    }
  return 0;
}
Jan Djärv's avatar
Jan Djärv committed
418
#endif /* USE_X_TOOLKIT || USE_GTK */
Jim Blandy's avatar
Jim Blandy committed
419

420 421


422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
static void x_default_font_parameter (struct frame *, Lisp_Object);

static Lisp_Object unwind_create_frame (Lisp_Object);
static Lisp_Object unwind_create_tip_frame (Lisp_Object);

void x_set_foreground_color (struct frame *, Lisp_Object, Lisp_Object);
static void x_set_wait_for_wm (struct frame *, Lisp_Object, Lisp_Object);
void x_set_background_color (struct frame *, Lisp_Object, Lisp_Object);
void x_set_mouse_color (struct frame *, Lisp_Object, Lisp_Object);
void x_set_cursor_color (struct frame *, Lisp_Object, Lisp_Object);
void x_set_border_color (struct frame *, Lisp_Object, Lisp_Object);
void x_set_cursor_type (struct frame *, Lisp_Object, Lisp_Object);
void x_set_icon_type (struct frame *, Lisp_Object, Lisp_Object);
void x_set_icon_name (struct frame *, Lisp_Object, Lisp_Object);
void x_explicitly_set_name (struct frame *, Lisp_Object, Lisp_Object);
void x_set_menu_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
void x_set_title (struct frame *, Lisp_Object, Lisp_Object);
void x_set_tool_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
void x_set_scroll_bar_foreground (struct frame *, Lisp_Object,
                                  Lisp_Object);
void x_set_scroll_bar_background (struct frame *, Lisp_Object,
                                  Lisp_Object);
static Lisp_Object x_default_scroll_bar_color_parameter (struct frame *,
                                                         Lisp_Object,
                                                         Lisp_Object,
447
                                                         const char *, const char *,
448
                                                         int);
Jim Blandy's avatar
Jim Blandy committed
449

450

451
/* Store the screen positions of frame F into XPTR and YPTR.
452 453 454 455
   These are the positions of the containing window manager window,
   not Emacs's own window.  */

void
456
x_real_positions (FRAME_PTR f, int *xptr, int *yptr)
457
{
458 459 460 461
  int win_x, win_y, outer_x, outer_y;
  int real_x = 0, real_y = 0;
  int had_errors = 0;
  Window win = f->output_data.x->parent_desc;
462 463 464 465 466 467 468 469
  Atom actual_type;
  unsigned long actual_size, bytes_remaining;
  int i, rc, actual_format;
  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
  long max_len = 400;
  Display *dpy = FRAME_X_DISPLAY (f);
  unsigned char *tmp_data = NULL;
  Atom target_type = XA_CARDINAL;
470

471 472
  BLOCK_INPUT;

473
  x_catch_errors (dpy);
474

475
  if (win == dpyinfo->root_window)
476 477 478 479 480 481 482
    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 (;;)
483
    {
484 485 486
      Window wm_window, rootw;
      Window *tmp_children;
      unsigned int tmp_nchildren;
487
      int success;
488

489 490
      success = XQueryTree (FRAME_X_DISPLAY (f), win, &rootw,
			    &wm_window, &tmp_children, &tmp_nchildren);
491

492
      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
493

494 495 496 497 498 499
      /* Don't free tmp_children if XQueryTree failed.  */
      if (! success)
	break;

      XFree ((char *) tmp_children);

500 501
      if (wm_window == rootw || had_errors)
        break;
502

503 504
      win = wm_window;
    }
505

506 507
  if (! had_errors)
    {
508
      unsigned int ign;
509
      Window child, rootw;
510

511 512 513 514 515 516 517 518 519 520 521 522 523 524
      /* 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
      */
525
      XTranslateCoordinates (FRAME_X_DISPLAY (f),
526

527 528
			     /* From-window, to-window.  */
			     FRAME_X_DISPLAY_INFO (f)->root_window,
529
                             FRAME_X_WINDOW (f),
530

531
			     /* From-position, to-position.  */
532
                             real_x, real_y, &win_x, &win_y,
533

534 535
			     /* Child of win.  */
			     &child);
536

537
      if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
538
	{
539 540
          outer_x = win_x;
          outer_y = win_y;
541
	}
542 543 544
      else
        {
          XTranslateCoordinates (FRAME_X_DISPLAY (f),
545

546 547 548
                                 /* From-window, to-window.  */
                                 FRAME_X_DISPLAY_INFO (f)->root_window,
                                 FRAME_OUTER_WINDOW (f),
549

550 551
                                 /* From-position, to-position.  */
                                 real_x, real_y, &outer_x, &outer_y,
552

553 554
                                 /* Child of win.  */
                                 &child);
555
	}
556

557 558
      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
    }
559

560 561 562 563 564 565 566 567 568 569 570 571

  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)
        {
572
          unsigned int ign;
573
          Window rootw;
574
          long *fe = (long *)tmp_data;
575 576 577 578 579 580 581 582 583 584 585 586

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

587
  x_uncatch_errors ();
588

589 590 591
  UNBLOCK_INPUT;

  if (had_errors) return;
592

593 594 595 596 597
  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;
598 599 600

  *xptr = real_x;
  *yptr = real_y;
601 602
}

Jim Blandy's avatar
Jim Blandy committed
603

604

605 606 607 608

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

void
609
gamma_correct (struct frame *f, XColor *color)
610 611 612 613 614 615 616 617 618 619
{
  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;
    }
}


620 621 622 623
/* Decide if color named COLOR_NAME is valid for use on frame F.  If
   so, return the RGB values in COLOR.  If ALLOC_P is non-zero,
   allocate the color.  Value is zero if COLOR_NAME is invalid, or
   no color could be allocated.  */
624

Jim Blandy's avatar
Jim Blandy committed
625
int
626 627
x_defined_color (struct frame *f, const char *color_name,
		 XColor *color, int alloc_p)
Jim Blandy's avatar
Jim Blandy committed
628
{
629
  int success_p = 0;
630 631
  Display *dpy = FRAME_X_DISPLAY (f);
  Colormap cmap = FRAME_X_COLORMAP (f);
Jim Blandy's avatar
Jim Blandy committed
632 633

  BLOCK_INPUT;
634 635 636 637 638
#ifdef USE_GTK
  success_p = xg_check_special_colors (f, color_name, color);
#endif
  if (!success_p)
    success_p = XParseColor (dpy, cmap, color_name, color);
639 640
  if (success_p && alloc_p)
    success_p = x_alloc_nearest_color (f, cmap, color);
Jim Blandy's avatar
Jim Blandy committed
641 642
  UNBLOCK_INPUT;

643
  return success_p;
Jim Blandy's avatar
Jim Blandy committed
644 645
}

646 647 648 649

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

651
static int
652
x_decode_color (FRAME_PTR f, Lisp_Object color_name, int mono_color)
Jim Blandy's avatar
Jim Blandy committed
653
{
654
  XColor cdef;
Jim Blandy's avatar
Jim Blandy committed
655

656
  CHECK_STRING (color_name);
Jim Blandy's avatar
Jim Blandy committed
657

658 659 660
#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.  */
661
  if (strcmp (SDATA (color_name), "black") == 0)
662
    return BLACK_PIX_DEFAULT (f);
663
  else if (strcmp (SDATA (color_name), "white") == 0)
664
    return WHITE_PIX_DEFAULT (f);
665
#endif
Jim Blandy's avatar
Jim Blandy committed
666

667
  /* Return MONO_COLOR for monochrome frames.  */
668
  if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
669
    return mono_color;
Jim Blandy's avatar
Jim Blandy committed
670

671
  /* x_defined_color is responsible for coping with failures
672
     by looking for a near-miss.  */
673
  if (x_defined_color (f, SSDATA (color_name), &cdef, 1))
674 675
    return cdef.pixel;

676
  signal_error ("Undefined color", color_name);
Jim Blandy's avatar
Jim Blandy committed
677
}
678 679


Jim Blandy's avatar
Jim Blandy committed
680

Gerd Moellmann's avatar
Gerd Moellmann committed
681 682 683 684 685
/* 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
686
x_set_wait_for_wm (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
Gerd Moellmann's avatar
Gerd Moellmann committed
687 688 689 690
{
  f->output_data.x->wait_for_wm = !NILP (new_value);
}

691 692 693 694 695 696 697 698 699 700 701
static void
x_set_tool_bar_position (struct frame *f,
                         Lisp_Object new_value,
                         Lisp_Object old_value)
{
  if (! EQ (new_value, Qleft) && ! EQ (new_value, Qright)
      && ! EQ (new_value, Qbottom) && ! EQ (new_value, Qtop))
    return;
  if (EQ (new_value, old_value)) return;

#ifdef USE_GTK
702
  if (xg_change_toolbar_position (f, new_value))
703 704 705 706
    f->tool_bar_position = new_value;
#endif
}

707 708
#ifdef USE_GTK

709 710
/* 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.  */
711 712

int
713
xg_set_icon (FRAME_PTR f, Lisp_Object file)
714
{
715 716
  int result = 0;
  Lisp_Object found;
717

718 719 720 721 722 723
  found = x_find_image_file (file);

  if (! NILP (found))
    {
      GdkPixbuf *pixbuf;
      GError *err = NULL;
724
      char *filename = SSDATA (found);
725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
      BLOCK_INPUT;

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

      UNBLOCK_INPUT;
    }

  return result;
744
}
745 746

int
747
xg_set_icon_from_xpm_data (FRAME_PTR f, const char **data)
748 749
{
  int result = 0;
750
  GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data);
751 752

  if (!pixbuf)
753
    return 0;
754

755
  gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf);
756 757 758
  g_object_unref (pixbuf);
  return 1;
}
759 760
#endif /* USE_GTK */

Gerd Moellmann's avatar
Gerd Moellmann committed
761

Jim Blandy's avatar
Jim Blandy committed
762
/* Functions called only from `x_set_frame_param'
Jim Blandy's avatar
Jim Blandy committed
763 764
   to set individual parameters.

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

void
771
x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
772
{
773 774
  struct x_output *x = f->output_data.x;
  unsigned long fg, old_fg;
775

776
  fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
777 778
  old_fg = FRAME_FOREGROUND_PIXEL (f);
  FRAME_FOREGROUND_PIXEL (f) = fg;
779

780
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
781
    {
782
      Display *dpy = FRAME_X_DISPLAY (f);
783

784 785 786
      BLOCK_INPUT;
      XSetForeground (dpy, x->normal_gc, fg);
      XSetBackground (dpy, x->reverse_gc, fg);
787

788 789 790 791 792 793
      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);
	}
794

Jim Blandy's avatar
Jim Blandy committed
795
      UNBLOCK_INPUT;
796

797
      update_face_from_frame_parameter (f, Qforeground_color, arg);
798

799
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
800
        redraw_frame (f);
Jim Blandy's avatar
Jim Blandy committed
801
    }
802

803
  unload_color (f, old_fg);
Jim Blandy's avatar
Jim Blandy committed
804 805 806
}

void
807
x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
808
{
809 810
  struct x_output *x = f->output_data.x;
  unsigned long bg;
Jim Blandy's avatar
Jim Blandy committed
811

812
  bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
813 814
  unload_color (f, FRAME_BACKGROUND_PIXEL (f));
  FRAME_BACKGROUND_PIXEL (f) = bg;
815

816
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
817
    {
818
      Display *dpy = FRAME_X_DISPLAY (f);
819

820 821 822 823 824 825
      BLOCK_INPUT;
      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
826 827 828 829
#ifdef USE_GTK
      xg_set_background_color (f, bg);
#endif

830 831 832 833 834 835 836 837
#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)
	  {
838
	    Window window = XSCROLL_BAR (bar)->x_window;
839 840 841 842
	    XSetWindowBackground (dpy, window, bg);
	  }
      }
#endif /* USE_TOOLKIT_SCROLL_BARS */
Jim Blandy's avatar
Jim Blandy committed
843

844
      UNBLOCK_INPUT;
845
      update_face_from_frame_parameter (f, Qbackground_color, arg);
Jim Blandy's avatar