xfns.c 192 KB
Newer Older
Jim Blandy's avatar
Jim Blandy committed
1
/* Functions for the X window system.
Glenn Morris's avatar
Glenn Morris committed
2

3
Copyright (C) 1989, 1992-2013 Free Software Foundation, Inc.
Jim Blandy's avatar
Jim Blandy committed
4 5 6

This file is part of GNU Emacs.

7
GNU Emacs is free software: you can redistribute it and/or modify
Jim Blandy's avatar
Jim Blandy committed
8
it under the terms of the GNU General Public License as published by
9 10
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jim Blandy's avatar
Jim Blandy committed
11 12 13 14 15 16 17

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
18
along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
Jim Blandy's avatar
Jim Blandy committed
19

Richard M. Stallman's avatar
Richard M. Stallman committed
20
#include <config.h>
21
#include <stdio.h>
22
#include <math.h>
23 24
#include <unistd.h>

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

27 28
#define XLIB_ILLEGAL_ACCESS

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

Jim Blandy's avatar
Jim Blandy committed
49
#ifdef HAVE_X_WINDOWS
50

51 52
#include <sys/types.h>
#include <sys/stat.h>
Jim Blandy's avatar
Jim Blandy committed
53

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

60 61
#include "xsettings.h"

62 63 64 65 66 67 68
#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
69 70 71 72
#ifdef USE_GTK
#include "gtkutil.h"
#endif

73 74 75
#ifdef USE_X_TOOLKIT
#include <X11/Shell.h>

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

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

#include "widget.h"

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

100 101 102 103
#ifdef USE_MOTIF
#include <Xm/Xm.h>
#include <Xm/DialogS.h>
#include <Xm/FileSB.h>
Jan D's avatar
Jan D committed
104 105
#include <Xm/List.h>
#include <Xm/TextF.h>
106 107
#endif

108 109 110 111
#ifdef USE_LUCID
#include "../lwlib/xlwmenu.h"
#endif

Juanma Barranquero's avatar
Juanma Barranquero committed
112
#if !defined (NO_EDITRES)
113
#define HACK_EDITRES
114
extern void _XEditResCheckMessages (Widget, XtPointer, XEvent *, Boolean *);
Dan Nicolaescu's avatar
Dan Nicolaescu committed
115
#endif /* not defined NO_EDITRES */
116

117 118
/* Unique id counter for widgets created by the Lucid Widget Library.  */

119 120
extern LWLIB_ID widget_id_tick;

121 122 123 124
#ifdef USE_MOTIF

#endif /* USE_MOTIF */

125 126
#endif /* USE_X_TOOLKIT */

Kenichi Handa's avatar
Kenichi Handa committed
127 128 129 130
#ifdef USE_GTK

#endif /* USE_GTK */

Richard M. Stallman's avatar
Richard M. Stallman committed
131 132
#define MAXREQUEST(dpy) (XMaxRequestSize (dpy))

133 134 135
static Lisp_Object Qsuppress_icon;
static Lisp_Object Qundefined_color;
static Lisp_Object Qcompound_text, Qcancel_timer;
136
static Lisp_Object Qgeometry, Qworkarea, Qmm_size, Qframes, Qsource;
137
Lisp_Object Qfont_param;
Jim Blandy's avatar
Jim Blandy committed
138

139
#ifdef GLYPH_DEBUG
140 141
static ptrdiff_t image_cache_refcount;
static int dpyinfo_refcount;
142 143
#endif

144 145
static struct x_display_info *x_display_info_for_name (Lisp_Object);

146
/* Let the user specify an X display with a Lisp object.
147
   OBJECT may be nil, a frame or a terminal object.
148 149 150
   nil stands for the selected frame--or, if that is not an X frame,
   the first X display on the list.  */

151
struct x_display_info *
152
check_x_display_info (Lisp_Object object)
153
{
154
  struct x_display_info *dpyinfo = NULL;
155

156
  if (NILP (object))
157
    {
Gerd Moellmann's avatar
Gerd Moellmann committed
158
      struct frame *sf = XFRAME (selected_frame);
159

Gerd Moellmann's avatar
Gerd Moellmann committed
160
      if (FRAME_X_P (sf) && FRAME_LIVE_P (sf))
161
	dpyinfo = FRAME_X_DISPLAY_INFO (sf);
162
      else if (x_display_list != 0)
163
	dpyinfo = x_display_list;
164 165 166
      else
	error ("X windows are not in use or not initialized");
    }
167
  else if (TERMINALP (object))
168
    {
169
      struct terminal *t = get_terminal (object, 1);
170

171
      if (t->type != output_x_window)
172
        error ("Terminal %"pI"d is not an X display", XINT (object));
173

174
      dpyinfo = t->display_info.x;
175
    }
176 177
  else if (STRINGP (object))
    dpyinfo = x_display_info_for_name (object);
178 179
  else
    {
180
      FRAME_PTR f = decode_window_system_frame (object);
181
      dpyinfo = FRAME_X_DISPLAY_INFO (f);
182
    }
183 184

  return dpyinfo;
185
}
186

187

Jim Blandy's avatar
Jim Blandy committed
188 189
/* 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
190

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

Jim Blandy's avatar
Jim Blandy committed
193
struct frame *
194
x_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
Jim Blandy's avatar
Jim Blandy committed
195
{
Jim Blandy's avatar
Jim Blandy committed
196 197
  Lisp_Object tail, frame;
  struct frame *f;
Jim Blandy's avatar
Jim Blandy committed
198

199 200
  if (wdesc == None)
    return NULL;
201

202
  FOR_EACH_FRAME (tail, frame)
Jim Blandy's avatar
Jim Blandy committed
203
    {
Jim Blandy's avatar
Jim Blandy committed
204
      f = XFRAME (frame);
205
      if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
206
	continue;
207
      if (f->output_data.x->hourglass_window == wdesc)
208
	return f;
209
#ifdef USE_X_TOOLKIT
210
      if ((f->output_data.x->edit_widget
211
	   && XtWindow (f->output_data.x->edit_widget) == wdesc)
212 213 214
	  /* A tooltip frame?  */
	  || (!f->output_data.x->edit_widget
	      && FRAME_X_WINDOW (f) == wdesc)
215
          || f->output_data.x->icon_desc == wdesc)
216 217
        return f;
#else /* not USE_X_TOOLKIT */
Jan Djärv's avatar
Jan Djärv committed
218 219 220
#ifdef USE_GTK
      if (f->output_data.x->edit_widget)
      {
Kenichi Handa's avatar
Kenichi Handa committed
221
        GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
Jan Djärv's avatar
Jan Djärv committed
222 223 224 225 226
        struct x_output *x = f->output_data.x;
        if (gwdesc != 0 && gwdesc == x->edit_widget)
          return f;
      }
#endif /* USE_GTK */
227
      if (FRAME_X_WINDOW (f) == wdesc
228
          || f->output_data.x->icon_desc == wdesc)
Jim Blandy's avatar
Jim Blandy committed
229
        return f;
230 231 232 233 234
#endif /* not USE_X_TOOLKIT */
    }
  return 0;
}

Jan Djärv's avatar
Jan Djärv committed
235
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
236 237 238 239
/* Like x_window_to_frame but also compares the window with the widget's
   windows.  */

struct frame *
240
x_any_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
241 242
{
  Lisp_Object tail, frame;
243
  struct frame *f, *found = NULL;
244
  struct x_output *x;
245

246 247
  if (wdesc == None)
    return NULL;
248

249
  FOR_EACH_FRAME (tail, frame)
250
    {
251 252
      if (found)
        break;
253
      f = XFRAME (frame);
254
      if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
255
	{
256 257
	  /* This frame matches if the window is any of its widgets.  */
	  x = f->output_data.x;
258
	  if (x->hourglass_window == wdesc)
259 260 261
	    found = f;
	  else if (x->widget)
	    {
Jan Djärv's avatar
Jan Djärv committed
262
#ifdef USE_GTK
Kenichi Handa's avatar
Kenichi Handa committed
263
              GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
Jan Djärv's avatar
Jan Djärv committed
264
              if (gwdesc != 0
265
                  && gtk_widget_get_toplevel (gwdesc) == x->widget)
Jan Djärv's avatar
Jan Djärv committed
266 267
                found = f;
#else
268 269
	      if (wdesc == XtWindow (x->widget)
		  || wdesc == XtWindow (x->column_widget)
270 271 272 273 274
		  || 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
275
#endif
276 277 278 279
	    }
	  else if (FRAME_X_WINDOW (f) == wdesc)
	    /* A tooltip frame.  */
	    found = f;
280
	}
Jim Blandy's avatar
Jim Blandy committed
281
    }
282

283
  return found;
Jim Blandy's avatar
Jim Blandy committed
284
}
285

286 287 288
/* Likewise, but consider only the menu bar widget.  */

struct frame *
289
x_menubar_window_to_frame (struct x_display_info *dpyinfo, XEvent *event)
290
{
Jan D's avatar
Jan D committed
291
  Window wdesc = event->xany.window;
292 293
  Lisp_Object tail, frame;
  struct frame *f;
294
  struct x_output *x;
295

296 297
  if (wdesc == None)
    return NULL;
298

299
  FOR_EACH_FRAME (tail, frame)
300 301
    {
      f = XFRAME (frame);
302
      if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
303
	continue;
304
      x = f->output_data.x;
Jan Djärv's avatar
Jan Djärv committed
305
#ifdef USE_GTK
Jan D's avatar
Jan D committed
306 307
      if (x->menubar_widget && xg_event_is_for_menubar (f, event))
        return f;
Jan Djärv's avatar
Jan Djärv committed
308
#else
Jan D's avatar
Jan D committed
309
      /* Match if the window is this frame's menubar.  */
310 311
      if (x->menubar_widget
	  && lw_window_is_in_menubar (wdesc, x->menubar_widget))
312
	return f;
Jan Djärv's avatar
Jan Djärv committed
313
#endif
314 315 316 317
    }
  return 0;
}

318 319 320 321
/* Return the frame whose principal (outermost) window is WDESC.
   If WDESC is some other (smaller) window, we return 0.  */

struct frame *
322
x_top_window_to_frame (struct x_display_info *dpyinfo, int wdesc)
323 324 325
{
  Lisp_Object tail, frame;
  struct frame *f;
326
  struct x_output *x;
327

328 329
  if (wdesc == None)
    return NULL;
330

331
  FOR_EACH_FRAME (tail, frame)
332 333
    {
      f = XFRAME (frame);
334
      if (!FRAME_X_P (f) || FRAME_X_DISPLAY_INFO (f) != dpyinfo)
335
	continue;
336
      x = f->output_data.x;
337 338 339 340

      if (x->widget)
	{
	  /* This frame matches if the window is its topmost widget.  */
Jan Djärv's avatar
Jan Djärv committed
341
#ifdef USE_GTK
Kenichi Handa's avatar
Kenichi Handa committed
342
          GtkWidget *gwdesc = xg_win_to_widget (dpyinfo->display, wdesc);
Jan Djärv's avatar
Jan Djärv committed
343 344 345
          if (gwdesc == x->widget)
            return f;
#else
346 347
	  if (wdesc == XtWindow (x->widget))
	    return f;
348 349 350
#if 0 /* I don't know why it did this,
	 but it seems logically wrong,
	 and it causes trouble for MapNotify events.  */
351
	  /* Match if the window is this frame's menubar.  */
352
	  if (x->menubar_widget
353 354
	      && wdesc == XtWindow (x->menubar_widget))
	    return f;
Jan Djärv's avatar
Jan Djärv committed
355
#endif
356
#endif
357 358 359 360
	}
      else if (FRAME_X_WINDOW (f) == wdesc)
	/* Tooltip frame.  */
	return f;
361 362 363
    }
  return 0;
}
Jan Djärv's avatar
Jan Djärv committed
364
#endif /* USE_X_TOOLKIT || USE_GTK */
Jim Blandy's avatar
Jim Blandy committed
365

366 367


368
/* Store the screen positions of frame F into XPTR and YPTR.
369 370 371 372
   These are the positions of the containing window manager window,
   not Emacs's own window.  */

void
373
x_real_positions (FRAME_PTR f, int *xptr, int *yptr)
374
{
375
  int win_x, win_y, outer_x IF_LINT (= 0), outer_y IF_LINT (= 0);
376 377 378
  int real_x = 0, real_y = 0;
  int had_errors = 0;
  Window win = f->output_data.x->parent_desc;
379 380
  Atom actual_type;
  unsigned long actual_size, bytes_remaining;
381
  int rc, actual_format;
382 383 384 385 386
  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;
387

388
  block_input ();
389

390
  x_catch_errors (dpy);
391

392
  if (win == dpyinfo->root_window)
393 394 395 396 397 398 399
    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 (;;)
400
    {
401 402 403
      Window wm_window, rootw;
      Window *tmp_children;
      unsigned int tmp_nchildren;
404
      int success;
405

406 407
      success = XQueryTree (FRAME_X_DISPLAY (f), win, &rootw,
			    &wm_window, &tmp_children, &tmp_nchildren);
408

409
      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
410

411 412 413 414
      /* Don't free tmp_children if XQueryTree failed.  */
      if (! success)
	break;

415
      XFree (tmp_children);
416

417 418
      if (wm_window == rootw || had_errors)
        break;
419

420 421
      win = wm_window;
    }
422

423 424
  if (! had_errors)
    {
425
      unsigned int ign;
426
      Window child, rootw;
427

428 429 430 431 432 433 434 435 436 437 438 439 440 441
      /* 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
      */
442
      XTranslateCoordinates (FRAME_X_DISPLAY (f),
443

444 445
			     /* From-window, to-window.  */
			     FRAME_X_DISPLAY_INFO (f)->root_window,
446
                             FRAME_X_WINDOW (f),
447

448
			     /* From-position, to-position.  */
449
                             real_x, real_y, &win_x, &win_y,
450

451 452
			     /* Child of win.  */
			     &child);
453

454
      if (FRAME_X_WINDOW (f) == FRAME_OUTER_WINDOW (f))
455
	{
456 457
          outer_x = win_x;
          outer_y = win_y;
458
	}
459 460 461
      else
        {
          XTranslateCoordinates (FRAME_X_DISPLAY (f),
462

463 464 465
                                 /* From-window, to-window.  */
                                 FRAME_X_DISPLAY_INFO (f)->root_window,
                                 FRAME_OUTER_WINDOW (f),
466

467 468
                                 /* From-position, to-position.  */
                                 real_x, real_y, &outer_x, &outer_y,
469

470 471
                                 /* Child of win.  */
                                 &child);
472
	}
473

474 475
      had_errors = x_had_errors_p (FRAME_X_DISPLAY (f));
    }
476

477 478 479 480 481 482 483 484 485 486 487 488

  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)
        {
489
          unsigned int ign;
490
          Window rootw;
491
          long *fe = (long *)tmp_data;
492 493 494 495 496 497 498 499 500 501 502 503

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

504
  x_uncatch_errors ();
505

506
  unblock_input ();
507 508

  if (had_errors) return;
509

510 511 512 513 514
  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;
515 516 517

  *xptr = real_x;
  *yptr = real_y;
518 519
}

Jim Blandy's avatar
Jim Blandy committed
520

521

522 523 524 525

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

void
526
gamma_correct (struct frame *f, XColor *color)
527 528 529 530 531 532 533 534 535 536
{
  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;
    }
}


537
/* Decide if color named COLOR_NAME is valid for use on frame F.  If
538 539
   so, return the RGB values in COLOR.  If ALLOC_P,
   allocate the color.  Value is false if COLOR_NAME is invalid, or
540
   no color could be allocated.  */
541

542
bool
543
x_defined_color (struct frame *f, const char *color_name,
544
		 XColor *color, bool alloc_p)
Jim Blandy's avatar
Jim Blandy committed
545
{
546
  bool success_p = 0;
547 548
  Display *dpy = FRAME_X_DISPLAY (f);
  Colormap cmap = FRAME_X_COLORMAP (f);
Jim Blandy's avatar
Jim Blandy committed
549

550
  block_input ();
551 552 553 554
#ifdef USE_GTK
  success_p = xg_check_special_colors (f, color_name, color);
#endif
  if (!success_p)
555
    success_p = XParseColor (dpy, cmap, color_name, color) != 0;
556 557
  if (success_p && alloc_p)
    success_p = x_alloc_nearest_color (f, cmap, color);
558
  unblock_input ();
Jim Blandy's avatar
Jim Blandy committed
559

560
  return success_p;
Jim Blandy's avatar
Jim Blandy committed
561 562
}

563 564 565 566

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

568
static int
569
x_decode_color (FRAME_PTR f, Lisp_Object color_name, int mono_color)
Jim Blandy's avatar
Jim Blandy committed
570
{
571
  XColor cdef;
Jim Blandy's avatar
Jim Blandy committed
572

573
  CHECK_STRING (color_name);
Jim Blandy's avatar
Jim Blandy committed
574

575 576 577
#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.  */
578
  if (strcmp (SDATA (color_name), "black") == 0)
579
    return BLACK_PIX_DEFAULT (f);
580
  else if (strcmp (SDATA (color_name), "white") == 0)
581
    return WHITE_PIX_DEFAULT (f);
582
#endif
Jim Blandy's avatar
Jim Blandy committed
583

584
  /* Return MONO_COLOR for monochrome frames.  */
585
  if (FRAME_X_DISPLAY_INFO (f)->n_planes == 1)
586
    return mono_color;
Jim Blandy's avatar
Jim Blandy committed
587

588
  /* x_defined_color is responsible for coping with failures
589
     by looking for a near-miss.  */
590
  if (x_defined_color (f, SSDATA (color_name), &cdef, 1))
591 592
    return cdef.pixel;

593
  signal_error ("Undefined color", color_name);
Jim Blandy's avatar
Jim Blandy committed
594
}
595 596


Jim Blandy's avatar
Jim Blandy committed
597

Gerd Moellmann's avatar
Gerd Moellmann committed
598 599 600 601 602
/* 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
603
x_set_wait_for_wm (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
Gerd Moellmann's avatar
Gerd Moellmann committed
604 605 606 607
{
  f->output_data.x->wait_for_wm = !NILP (new_value);
}

608 609 610 611 612 613 614 615 616 617 618
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
619 620
  xg_change_toolbar_position (f, new_value);
  fset_tool_bar_position (f, new_value);
621 622 623
#endif
}

624 625
#ifdef USE_GTK

626 627
/* 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.  */
628 629

int
630
xg_set_icon (FRAME_PTR f, Lisp_Object file)
631
{
632 633
  int result = 0;
  Lisp_Object found;
634

635 636 637 638 639 640
  found = x_find_image_file (file);

  if (! NILP (found))
    {
      GdkPixbuf *pixbuf;
      GError *err = NULL;
641
      char *filename = SSDATA (found);
642
      block_input ();
643 644 645 646 647 648 649 650 651 652 653 654 655 656

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

657
      unblock_input ();
658 659 660
    }

  return result;
661
}
662 663

int
664
xg_set_icon_from_xpm_data (FRAME_PTR f, const char **data)
665
{
666
  GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (data);
667 668

  if (!pixbuf)
669
    return 0;
670

671
  gtk_window_set_icon (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), pixbuf);
672 673 674
  g_object_unref (pixbuf);
  return 1;
}
675 676
#endif /* USE_GTK */

Gerd Moellmann's avatar
Gerd Moellmann committed
677

Jim Blandy's avatar
Jim Blandy committed
678
/* Functions called only from `x_set_frame_param'
Jim Blandy's avatar
Jim Blandy committed
679 680
   to set individual parameters.

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

686
static void
687
x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
688
{
689 690
  struct x_output *x = f->output_data.x;
  unsigned long fg, old_fg;
691

692
  fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
693 694
  old_fg = FRAME_FOREGROUND_PIXEL (f);
  FRAME_FOREGROUND_PIXEL (f) = fg;
695

696
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
697
    {
698
      Display *dpy = FRAME_X_DISPLAY (f);
699

700
      block_input ();
701 702
      XSetForeground (dpy, x->normal_gc, fg);
      XSetBackground (dpy, x->reverse_gc, fg);
703

704 705 706 707 708 709
      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);
	}
710

711
      unblock_input ();
712

713
      update_face_from_frame_parameter (f, Qforeground_color, arg);
714

715
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
716
        redraw_frame (f);
Jim Blandy's avatar
Jim Blandy committed
717
    }
718

719
  unload_color (f, old_fg);
Jim Blandy's avatar
Jim Blandy committed
720 721
}

722
static void
723
x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
724
{
725 726
  struct x_output *x = f->output_data.x;
  unsigned long bg;
Jim Blandy's avatar
Jim Blandy committed
727

728
  bg = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
729 730
  unload_color (f, FRAME_BACKGROUND_PIXEL (f));
  FRAME_BACKGROUND_PIXEL (f) = bg;
731

732
  if (FRAME_X_WINDOW (f) != 0)
Jim Blandy's avatar
Jim Blandy committed
733
    {
734
      Display *dpy = FRAME_X_DISPLAY (f);
735

736
      block_input ();
737 738 739 740 741
      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
742 743 744 745
#ifdef USE_GTK
      xg_set_background_color (f, bg);
#endif

746 747 748 749 750 751 752 753
#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)
	  {
754
	    Window window = XSCROLL_BAR (bar)->x_window;
755 756 757 758
	    XSetWindowBackground (dpy, window, bg);
	  }
      }
#endif /* USE_TOOLKIT_SCROLL_BARS */
Jim Blandy's avatar
Jim Blandy committed
759

760
      unblock_input ();
761
      update_face_from_frame_parameter (f, Qbackground_color, arg);
762

763
      if (FRAME_VISIBLE_P (f))
Jim Blandy's avatar
Jim Blandy committed
764
        redraw_frame (f);
Jim Blandy's avatar
Jim Blandy committed
765 766 767
    }
}

768
static Cursor
769
make_invisible_cursor (struct frame *f)
770 771 772 773 774
{
  Display *dpy = FRAME_X_DISPLAY (f);
  static char const no_data[] = { 0 };
  Pixmap pix;
  XColor col;
775
  Cursor c = 0;
776 777 778 779 780 781

  x_catch_errors (dpy);
  pix = XCreateBitmapFromData (dpy, FRAME_X_DISPLAY_INFO (f)->root_window,
                               no_data, 1, 1);
  if (! x_had_errors_p (dpy) && pix != None)
    {
782
      Cursor pixc;
783 784 785
      col.pixel = 0;
      col.red = col.green = col.blue = 0;
      col.flags = DoRed | DoGreen | DoBlue;
786 787 788
      pixc = XCreatePixmapCursor (dpy, pix, pix, &col, &col, 0, 0);
      if (! x_had_errors_p (dpy) && pixc != None)
        c = pixc;
789 790 791 792 793 794 795 796
      XFreePixmap (dpy, pix);
    }

  x_uncatch_errors ();

  return c;
}

797
static void
798
x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
Jim Blandy's avatar
Jim Blandy committed
799
{
800 801
  struct x_output *x = f->output_data.x;
  Display *dpy = FRAME_X_DISPLAY (f);
802
  Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
803
  Cursor hourglass_cursor, horizontal_drag_cursor;
804
  unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
Karoly Lorentey's avatar
Karoly Lorentey committed
805
  unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f);
806

807
  /* Don't let pointers be invisible.  */
808
  if (mask_color == pixel)
809 810
    {
      x_free_colors (f, &pixel, 1);
Karoly Lorentey's avatar
Karoly Lorentey committed
811
      pixel = x_copy_color (f, FRAME_FOREGROUND_PIXEL (f));
812
    }
813

814 815
  unload_color (f, x->mouse_pixel);
  x->mouse_pixel = pixel;
Jim Blandy's avatar
Jim Blandy committed
816