widget.c 26.5 KB
Newer Older
Richard M. Stallman's avatar
Richard M. Stallman committed
1
/* The emacs frame widget.
2
   Copyright (C) 1992, 1993, 2000, 2001, 2002, 2003, 2004,
Glenn Morris's avatar
Glenn Morris committed
3
                 2005, 2006, 2007, 2008, 2009, 2010  Free Software Foundation, Inc.
Richard M. Stallman's avatar
Richard M. Stallman committed
4 5 6

This file is part of GNU Emacs.

7
GNU Emacs is free software: you can redistribute it and/or modify
Richard M. Stallman's avatar
Richard M. Stallman 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.
Richard M. Stallman's avatar
Richard M. Stallman 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/>.  */
Richard M. Stallman's avatar
Richard M. Stallman committed
19 20 21

/* Emacs 19 face widget ported by Fred Pierresteguy */

Karl Heuer's avatar
Karl Heuer committed
22 23 24 25 26 27 28 29 30 31
/* This file has been censored by the Communications Decency Act.
   That law was passed under the guise of a ban on pornography, but
   it bans far more than that.  This file did not contain pornography,
   but it was censored nonetheless.

   For information on US government censorship of the Internet, and
   what you can do to bring back freedom of the press, see the web
   site http://www.vtw.org/
   */

32
#include <config.h>
33
#include <stdio.h>
34
#include <setjmp.h>
Richard M. Stallman's avatar
Richard M. Stallman committed
35 36 37
#include "lisp.h"
#include "xterm.h"

38
#include "keyboard.h"
Richard M. Stallman's avatar
Richard M. Stallman committed
39
#include "frame.h"
Andreas Schwab's avatar
Andreas Schwab committed
40
#include "window.h"
Richard M. Stallman's avatar
Richard M. Stallman committed
41 42

#include "dispextern.h"
43
#include "blockinput.h"
Richard M. Stallman's avatar
Richard M. Stallman committed
44 45 46 47 48

#include <X11/StringDefs.h>
#include <X11/IntrinsicP.h>
#include <X11/cursorfont.h>
#include "widgetprv.h"
49
#include <X11/ObjectP.h>
Richard M. Stallman's avatar
Richard M. Stallman committed
50 51
#include <X11/Shell.h>
#include <X11/ShellP.h>
52
#include "../lwlib/lwlib.h"
Richard M. Stallman's avatar
Richard M. Stallman committed
53

54 55 56
#include <signal.h>
#include "syssignal.h"

57 58 59
#include "character.h"
#include "font.h"

Richard M. Stallman's avatar
Richard M. Stallman committed
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
/* This sucks: this is the first default that x-faces.el tries.  This won't
   be used unless neither the "Emacs.EmacsFrame" resource nor the
   "Emacs.EmacsFrame" resource is set; the frame
   may have the wrong default size if this font doesn't exist, but some other
   font that x-faces.el does.  The workaround is to specify some font in the
   resource database; I don't know a solution other than duplicating the font-
   searching code from x-faces.el in this file.

   This also means that if "Emacs.EmacsFrame" is specified as a non-
   existent font, then Xt is going to substitute "XtDefaultFont" for it,
   which is a different size than this one.  The solution for this is to
   make x-faces.el try to use XtDefaultFont.  The problem with that is that
   XtDefaultFont is almost certainly variable-width.

   #### Perhaps we could have this code explicitly set XtDefaultFont to this?
 */
#define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"


79 80 81 82 83 84
static void EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2);
static void EmacsFrameDestroy (Widget widget);
static void EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs);
void EmacsFrameResize (Widget widget);
static Boolean EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2);
static XtGeometryResult EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result);
Richard M. Stallman's avatar
Richard M. Stallman committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108


#undef XtOffset
#define XtOffset(p_type,field) \
	((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
#define offset(field) XtOffset(EmacsFrame, emacs_frame.field)

static XtResource resources[] = {
  {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
     offset (geometry), XtRString, (XtPointer) 0},
  {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
     offset (iconic), XtRImmediate, (XtPointer) False},

  {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
     offset (frame), XtRImmediate, 0},

  {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
     offset (minibuffer), XtRImmediate, (XtPointer)0},
  {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
     offset (unsplittable), XtRImmediate, (XtPointer)0},
  {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
     offset (internal_border_width), XtRImmediate, (XtPointer)4},
  {XtNinterline, XtCInterline, XtRInt, sizeof (int),
     offset (interline), XtRImmediate, (XtPointer)0},
109
  {XtNfont,  XtCFont, XtRFontStruct, sizeof(struct font *),
Richard M. Stallman's avatar
Richard M. Stallman committed
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
     offset(font),XtRString, DEFAULT_FACE_FONT},
  {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
     offset(foreground_pixel), XtRString, "XtDefaultForeground"},
  {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
     offset(cursor_color), XtRString, "XtDefaultForeground"},
  {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
     offset (bar_cursor), XtRImmediate, (XtPointer)0},
  {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
     offset (visual_bell), XtRImmediate, (XtPointer)0},
  {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
     offset (bell_volume), XtRImmediate, (XtPointer)0},
};

#undef offset

/*
static XtActionsRec
emacsFrameActionsTable [] = {
  {"keypress",  key_press},
  {"focus_in",  emacs_frame_focus_handler},
  {"focus_out", emacs_frame_focus_handler},
};

static char
emacsFrameTranslations [] = "\
<KeyPress>: keypress()\n\
<FocusIn>:  focus_in()\n\
<FocusOut>: focus_out()\n\
";
*/

EmacsFrameClassRec emacsFrameClassRec = {
    { /* core fields */
    /* superclass		*/	&widgetClassRec,
    /* class_name		*/	"EmacsFrame",
    /* widget_size		*/	sizeof(EmacsFrameRec),
    /* class_initialize		*/	0,
    /* class_part_initialize	*/	0,
    /* class_inited		*/	FALSE,
    /* initialize		*/	EmacsFrameInitialize,
    /* initialize_hook		*/	0,
    /* realize			*/	EmacsFrameRealize,
    /* actions			*/	0, /*emacsFrameActionsTable*/
    /* num_actions		*/	0, /*XtNumber (emacsFrameActionsTable)*/
    /* resources		*/	resources,
    /* resource_count		*/	XtNumber(resources),
    /* xrm_class		*/	NULLQUARK,
    /* compress_motion		*/	TRUE,
    /* compress_exposure	*/	TRUE,
    /* compress_enterleave	*/	TRUE,
    /* visible_interest		*/	FALSE,
    /* destroy			*/	EmacsFrameDestroy,
    /* resize			*/	EmacsFrameResize,
    /* expose			*/	XtInheritExpose,
    /* set_values		*/	EmacsFrameSetValues,
    /* set_values_hook		*/	0,
    /* set_values_almost	*/	XtInheritSetValuesAlmost,
    /* get_values_hook		*/	0,
    /* accept_focus		*/	XtInheritAcceptFocus,
    /* version			*/	XtVersion,
    /* callback_private		*/	0,
    /* tm_table			*/	0, /*emacsFrameTranslations*/
    /* query_geometry		*/	EmacsFrameQueryGeometry,
    /* display_accelerator	*/	XtInheritDisplayAccelerator,
    /* extension		*/	0
    }
};

WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;

static void
181
get_default_char_pixel_size (EmacsFrame ew, int *pixel_width, int *pixel_height)
Richard M. Stallman's avatar
Richard M. Stallman committed
182 183
{
  struct frame* f = ew->emacs_frame.frame;
184 185
  *pixel_width = FRAME_COLUMN_WIDTH (f);
  *pixel_height = FRAME_LINE_HEIGHT (f);
Richard M. Stallman's avatar
Richard M. Stallman committed
186 187 188
}

static void
189
pixel_to_char_size (EmacsFrame ew, Dimension pixel_width, Dimension pixel_height, int *char_width, int *char_height)
Richard M. Stallman's avatar
Richard M. Stallman committed
190 191
{
  struct frame* f = ew->emacs_frame.frame;
192 193
  *char_width = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, (int) pixel_width);
  *char_height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, (int) pixel_height);
Richard M. Stallman's avatar
Richard M. Stallman committed
194 195 196
}

static void
197
char_to_pixel_size (EmacsFrame ew, int char_width, int char_height, Dimension *pixel_width, Dimension *pixel_height)
Richard M. Stallman's avatar
Richard M. Stallman committed
198 199
{
  struct frame* f = ew->emacs_frame.frame;
200 201
  *pixel_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, char_width);
  *pixel_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, char_height);
Richard M. Stallman's avatar
Richard M. Stallman committed
202 203 204
}

static void
205
round_size_to_char (EmacsFrame ew, Dimension in_width, Dimension in_height, Dimension *out_width, Dimension *out_height)
Richard M. Stallman's avatar
Richard M. Stallman committed
206 207 208 209 210 211 212 213
{
  int char_width;
  int char_height;
  pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
  char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
}

static Widget
214
get_wm_shell (Widget w)
Richard M. Stallman's avatar
Richard M. Stallman committed
215 216 217 218 219 220 221 222 223 224
{
  Widget wmshell;

  for (wmshell = XtParent (w);
       wmshell && !XtIsWMShell (wmshell);
       wmshell = XtParent (wmshell));

  return wmshell;
}

225 226
#if 0 /* Currently not used.  */

Richard M. Stallman's avatar
Richard M. Stallman committed
227
static void
228 229
mark_shell_size_user_specified (wmshell)
     Widget wmshell;
Richard M. Stallman's avatar
Richard M. Stallman committed
230 231 232 233 234 235 236
{
  if (! XtIsWMShell (wmshell)) abort ();
  /* This is kind of sleazy, but I can't see how else to tell it to make it
     mark the WM_SIZE_HINTS size as user specified when appropriate. */
  ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
}

237 238
#endif

Richard M. Stallman's avatar
Richard M. Stallman committed
239 240 241 242 243 244 245

/* Can't have static frame locals because of some broken compilers.
   Normally, initializing a variable like this doesn't work in emacs,
   but it's ok in this file because it must come after lastfile (and
   thus have its data not go into text space) because Xt needs to
   write to initialized data objects too.
 */
246
#if 0
Richard M. Stallman's avatar
Richard M. Stallman committed
247
static Boolean first_frame_p = True;
248
#endif
Richard M. Stallman's avatar
Richard M. Stallman committed
249 250

static void
251
set_frame_size (EmacsFrame ew)
Richard M. Stallman's avatar
Richard M. Stallman committed
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
{
  /* The widget hierarchy is

	argv[0]			emacsShell	pane	Frame-NAME
	ApplicationShell	EmacsShell	Paned	EmacsFrame

     We accept geometry specs in this order:

	*Frame-NAME.geometry
	*EmacsFrame.geometry
	Emacs.geometry

     Other possibilities for widget hierarchies might be

	argv[0]			frame		pane	Frame-NAME
	ApplicationShell	EmacsShell	Paned	EmacsFrame
     or
	argv[0]			Frame-NAME	pane	Frame-NAME
	ApplicationShell	EmacsShell	Paned	EmacsFrame
     or
	argv[0]			Frame-NAME	pane	emacsTextPane
	ApplicationShell	EmacsFrame	Paned	EmacsTextPane

     With the current setup, the text-display-area is the part which is
     an emacs "frame", since that's the only part managed by emacs proper
     (the menubar and the parent of the menubar and all that sort of thing
     are managed by lwlib.)

280
     The EmacsShell widget is simply a replacement for the Shell widget
Richard M. Stallman's avatar
Richard M. Stallman committed
281 282 283 284 285 286 287 288
     which is able to deal with using an externally-supplied window instead
     of always creating its own.  It is not actually emacs specific, and
     should possibly have class "Shell" instead of "EmacsShell" to simplify
     the resources.

   */

  /* Hairily merged geometry */
289 290
  unsigned int w = FRAME_COLS (ew->emacs_frame.frame);
  unsigned int h = FRAME_LINES (ew->emacs_frame.frame);
291

Richard M. Stallman's avatar
Richard M. Stallman committed
292
  Widget wmshell = get_wm_shell ((Widget) ew);
293
  /* Each Emacs shell is now independent and top-level.  */
294

Richard M. Stallman's avatar
Richard M. Stallman committed
295 296
  if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();

297
  /* We don't need this for the moment. The geometry is computed in
298 299
     xfns.c.  */
#if 0
Richard M. Stallman's avatar
Richard M. Stallman committed
300 301 302 303
  /* If the EmacsFrame doesn't have a geometry but the shell does,
     treat that as the geometry of the frame.  (Is this bogus?
     I'm not sure.) */
  if (ew->emacs_frame.geometry == 0)
304
    XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
305 306 307 308

  /* If the Shell is iconic, then the EmacsFrame is iconic.  (Is
     this bogus? I'm not sure.) */
  if (!ew->emacs_frame.iconic)
309
    XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, NULL);
310 311


Richard M. Stallman's avatar
Richard M. Stallman committed
312 313
  {
    char *geom = 0;
314
    XtVaGetValues (app_shell, XtNgeometry, &geom, NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
315 316 317
    if (geom)
      app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
  }
318

Richard M. Stallman's avatar
Richard M. Stallman committed
319 320 321 322
  if (ew->emacs_frame.geometry)
    frame_flags = XParseGeometry (ew->emacs_frame.geometry,
				   &frame_x, &frame_y,
				   &frame_w, &frame_h);
323

Richard M. Stallman's avatar
Richard M. Stallman committed
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
  if (first_frame_p)
    {
      /* If this is the first frame created:
         ====================================

         - Use the ApplicationShell's size/position, if specified.
           (This is "Emacs.geometry", or the "-geometry" command line arg.)
         - Else use the EmacsFrame's size/position.
           (This is "*Frame-NAME.geometry")

	 - If the AppShell is iconic, the frame should be iconic.

	 AppShell comes first so that -geometry always applies to the first
	 frame created, even if there is an "every frame" entry in the
	 resource database.
       */
      if (app_flags & (XValue | YValue))
	{
	  x = app_x; y = app_y;
	  flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
	}
      else if (frame_flags & (XValue | YValue))
	{
	  x = frame_x; y = frame_y;
	  flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
	}

      if (app_flags & (WidthValue | HeightValue))
	{
	  w = app_w; h = app_h;
	  flags |= (app_flags & (WidthValue | HeightValue));
	}
      else if (frame_flags & (WidthValue | HeightValue))
	{
	  w = frame_w; h = frame_h;
	  flags |= (frame_flags & (WidthValue | HeightValue));
	}

      /* If the AppShell is iconic, then the EmacsFrame is iconic. */
      if (!ew->emacs_frame.iconic)
364
	XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
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 391 392 393 394 395 396 397 398 399 400 401

      first_frame_p = False;
    }
  else
    {
      /* If this is not the first frame created:
         ========================================

         - use the EmacsFrame's size/position if specified
         - Otherwise, use the ApplicationShell's size, but not position.

         So that means that one can specify the position of the first frame
         with "Emacs.geometry" or `-geometry'; but can only specify the
	 position of subsequent frames with "*Frame-NAME.geometry".

	 AppShell comes second so that -geometry does not apply to subsequent
	 frames when there is an "every frame" entry in the resource db,
	 but does apply to the first frame.
       */
      if (frame_flags & (XValue | YValue))
	{
	  x = frame_x; y = frame_y;
	  flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
	}

      if (frame_flags & (WidthValue | HeightValue))
	{
	  w = frame_w; h = frame_h;
	  flags |= (frame_flags & (WidthValue | HeightValue));
	}
      else if (app_flags & (WidthValue | HeightValue))
	{
	  w = app_w;
	  h = app_h;
	  flags |= (app_flags & (WidthValue | HeightValue));
	}
    }
402
#endif /* 0 */
Richard M. Stallman's avatar
Richard M. Stallman committed
403
  {
404
    struct frame *f = ew->emacs_frame.frame;
Richard M. Stallman's avatar
Richard M. Stallman committed
405 406
    Dimension pixel_width, pixel_height;

407 408 409 410 411
    /* Take into account the size of the scrollbar.  Always use the
       number of columns occupied by the scroll bar here otherwise we
       might end up with a frame width that is not a multiple of the
       frame's character width which is bad for vertically split
       windows.  */
412 413
    f->scroll_bar_actual_width
      = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
Richard M. Stallman's avatar
Richard M. Stallman committed
414

415
    compute_fringe_widths (f, 0);
416

417 418 419
#if 0 /* This can run Lisp code, and it is dangerous to give
	 out the frame to Lisp code before it officially exists.
	 This is handled in Fx_create_frame so not needed here.  */
420
    change_frame_size (f, h, w, 1, 0, 0);
421
#endif
Richard M. Stallman's avatar
Richard M. Stallman committed
422 423 424 425
    char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
    ew->core.width = pixel_width;
    ew->core.height = pixel_height;

426
#if 0 /* xfns.c takes care of this now.  */
Richard M. Stallman's avatar
Richard M. Stallman committed
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
    /* If a position was specified, assign it to the shell widget.
       (Else WM won't do anything with it.)
     */
    if (flags & (XValue | YValue))
      {
	/* the tricky things with the sign is to make sure that
	   -0 is printed -0. */
	int len;
	char *tem;
	sprintf (shell_position, "=%c%d%c%d",
		 flags & XNegative ? '-' : '+', x < 0 ? -x : x,
		 flags & YNegative ? '-' : '+', y < 0 ? -y : y);
	len = strlen (shell_position) + 1;
	tem = (char *) xmalloc (len);
	strncpy (tem, shell_position, len);
442
	XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
443 444 445 446 447 448 449 450 451
      }
    else if (flags & (WidthValue | HeightValue))
      {
	int len;
	char *tem;
	sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
	len = strlen (shell_position) + 1;
	tem = (char *) xmalloc (len);
	strncpy (tem, shell_position, len);
452
	XtVaSetValues (wmshell, XtNgeometry, tem, NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
453 454 455 456 457 458 459 460 461
      }

    /* If the geometry spec we're using has W/H components, mark the size
       in the WM_SIZE_HINTS as user specified. */
    if (flags & (WidthValue | HeightValue))
      mark_shell_size_user_specified (wmshell);

    /* Also assign the iconic status of the frame to the Shell, so that
       the WM sees it. */
462
    XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, NULL);
463
#endif /* 0 */
Richard M. Stallman's avatar
Richard M. Stallman committed
464 465 466
  }
}

467 468 469
/* Nonzero tells update_wm_hints not to do anything
   (the caller should call update_wm_hints explicitly later.)  */
int update_hints_inhibit;
Richard M. Stallman's avatar
Richard M. Stallman committed
470 471

static void
472
update_wm_hints (EmacsFrame ew)
Richard M. Stallman's avatar
Richard M. Stallman committed
473 474 475 476 477 478 479 480 481 482 483 484
{
  Widget wmshell = get_wm_shell ((Widget)ew);
  int cw;
  int ch;
  Dimension rounded_width;
  Dimension rounded_height;
  int char_width;
  int char_height;
  int base_width;
  int base_height;
  int min_rows = 0, min_cols = 0;

485 486 487 488
  if (update_hints_inhibit)
    return;

#if 0
Richard M. Stallman's avatar
Richard M. Stallman committed
489
  check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
490
#endif
Richard M. Stallman's avatar
Richard M. Stallman committed
491 492 493 494 495

  pixel_to_char_size (ew, ew->core.width, ew->core.height,
		      &char_width, &char_height);
  char_to_pixel_size (ew, char_width, char_height,
		      &rounded_width, &rounded_height);
496
  get_default_char_pixel_size (ew, &cw, &ch);
Richard M. Stallman's avatar
Richard M. Stallman committed
497 498 499 500 501 502 503 504 505 506 507 508

  base_width = (wmshell->core.width - ew->core.width
		+ (rounded_width - (char_width * cw)));
  base_height = (wmshell->core.height - ew->core.height
		+ (rounded_height - (char_height * ch)));

  /* This is kind of sleazy, but I can't see how else to tell it to
     make it mark the WM_SIZE_HINTS size as user specified.
   */
/*  ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/

  XtVaSetValues (wmshell,
509 510
		 XtNbaseWidth, (XtArgVal) base_width,
		 XtNbaseHeight, (XtArgVal) base_height,
511
		 XtNwidthInc, (XtArgVal) cw,
512 513 514
		 XtNheightInc, (XtArgVal) ch,
		 XtNminWidth, (XtArgVal) (base_width + min_cols * cw),
		 XtNminHeight, (XtArgVal) (base_height + min_rows * ch),
515
		 NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
516 517
}

518 519
#if 0

Richard M. Stallman's avatar
Richard M. Stallman committed
520
static void
521 522
create_frame_gcs (ew)
     EmacsFrame ew;
Richard M. Stallman's avatar
Richard M. Stallman committed
523
{
524
  struct frame *s = ew->emacs_frame.frame;
Richard M. Stallman's avatar
Richard M. Stallman committed
525

Karl Heuer's avatar
Karl Heuer committed
526
  s->output_data.x->normal_gc
527 528
    = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
		 (unsigned long)0, (XGCValues *)0);
Karl Heuer's avatar
Karl Heuer committed
529
  s->output_data.x->reverse_gc
530 531
    = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
		 (unsigned long)0, (XGCValues *)0);
Karl Heuer's avatar
Karl Heuer committed
532
  s->output_data.x->cursor_gc
533 534
    = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
		 (unsigned long)0, (XGCValues *)0);
535 536
  s->output_data.x->black_relief.gc = 0;
  s->output_data.x->white_relief.gc = 0;
Richard M. Stallman's avatar
Richard M. Stallman committed
537 538
}

539 540
#endif /* 0 */

541 542 543 544 545 546 547 548
static char setup_frame_cursor_bits[] =
{
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

Richard M. Stallman's avatar
Richard M. Stallman committed
549
static void
550
setup_frame_gcs (EmacsFrame ew)
Richard M. Stallman's avatar
Richard M. Stallman committed
551 552 553 554
{
  XGCValues gc_values;
  struct frame* s = ew->emacs_frame.frame;
  Pixmap blank_stipple, blank_tile;
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
  unsigned long valuemask = (GCForeground | GCBackground | GCGraphicsExposures
			     | GCStipple | GCTile);
  Lisp_Object font;

  XSETFONT (font, ew->emacs_frame.font);
  font = Ffont_xlfd_name (font, Qnil);
  if (STRINGP (font))
    {
      XFontStruct *xfont = XLoadQueryFont (FRAME_X_DISPLAY_INFO (s)->display,
					   SDATA (font));
      if (xfont)
	{
	  gc_values.font = xfont->fid;
	  valuemask |= GCFont;
	}
    }
Richard M. Stallman's avatar
Richard M. Stallman committed
571 572 573 574 575 576 577 578 579 580

  /* We have to initialize all of our GCs to have a stipple/tile, otherwise
     XGetGCValues returns uninitialized data when we query the stipple
     (instead of None or something sensible) and it makes things hard.

     This should be fixed for real by not querying the GCs but instead having
     some GC-based cache instead of the current face-based cache which doesn't
     effectively cache all of the GC settings we need to use.
   */

581 582 583 584
  blank_stipple
    = XCreateBitmapFromData (XtDisplay (ew),
			     RootWindowOfScreen (XtScreen (ew)),
			     setup_frame_cursor_bits, 2, 2);
Richard M. Stallman's avatar
Richard M. Stallman committed
585 586 587 588

  /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
     never actually get used as a background tile!
   */
589 590 591 592 593 594
  blank_tile
    = XCreatePixmapFromBitmapData (XtDisplay(ew),
				   RootWindowOfScreen (XtScreen (ew)),
				   setup_frame_cursor_bits, 2, 2,
				   (unsigned long)0, (unsigned long)1,
				   ew->core.depth);
Richard M. Stallman's avatar
Richard M. Stallman committed
595 596 597 598 599 600 601

  /* Normal video */
  gc_values.foreground = ew->emacs_frame.foreground_pixel;
  gc_values.background = ew->core.background_pixel;
  gc_values.graphics_exposures = False;
  gc_values.stipple = blank_stipple;
  gc_values.tile = blank_tile;
Karl Heuer's avatar
Karl Heuer committed
602
  XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
603
	     valuemask, &gc_values);
Richard M. Stallman's avatar
Richard M. Stallman committed
604 605 606 607 608 609 610

  /* Reverse video style. */
  gc_values.foreground = ew->core.background_pixel;
  gc_values.background = ew->emacs_frame.foreground_pixel;
  gc_values.graphics_exposures = False;
  gc_values.stipple = blank_stipple;
  gc_values.tile = blank_tile;
Karl Heuer's avatar
Karl Heuer committed
611
  XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
612
	     valuemask, &gc_values);
Richard M. Stallman's avatar
Richard M. Stallman committed
613 614 615 616 617 618

  /* Cursor has to have an empty stipple. */
  gc_values.foreground = ew->core.background_pixel;
  gc_values.background = ew->emacs_frame.cursor_color;
  gc_values.graphics_exposures = False;
  gc_values.tile = blank_tile;
619 620 621 622
  gc_values.stipple
    = XCreateBitmapFromData (XtDisplay (ew),
			     RootWindowOfScreen (XtScreen (ew)),
			     setup_frame_cursor_bits, 16, 16);
Karl Heuer's avatar
Karl Heuer committed
623
  XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
624
	     valuemask, &gc_values);
Richard M. Stallman's avatar
Richard M. Stallman committed
625 626 627
}

static void
628
update_various_frame_slots (EmacsFrame ew)
Richard M. Stallman's avatar
Richard M. Stallman committed
629
{
630 631 632 633 634
  struct frame *f = ew->emacs_frame.frame;
  struct x_output *x = f->output_data.x;
  FRAME_PIXEL_HEIGHT (f) = ew->core.height + x->menubar_height;
  FRAME_PIXEL_WIDTH (f) = ew->core.width;
  f->internal_border_width = ew->emacs_frame.internal_border_width;
Richard M. Stallman's avatar
Richard M. Stallman committed
635 636 637 638

}

static void
639
update_from_various_frame_slots (EmacsFrame ew)
Richard M. Stallman's avatar
Richard M. Stallman committed
640
{
641 642 643 644
  struct frame *f = ew->emacs_frame.frame;
  struct x_output *x = f->output_data.x;
  ew->core.height = FRAME_PIXEL_HEIGHT (f) - x->menubar_height;
  ew->core.width = FRAME_PIXEL_WIDTH (f);
Karoly Lorentey's avatar
Karoly Lorentey committed
645
  ew->core.background_pixel = FRAME_BACKGROUND_PIXEL (f);
646
  ew->emacs_frame.internal_border_width = f->internal_border_width;
Richard M. Stallman's avatar
Richard M. Stallman committed
647
  ew->emacs_frame.font = x->font;
Karoly Lorentey's avatar
Karoly Lorentey committed
648
  ew->emacs_frame.foreground_pixel = FRAME_FOREGROUND_PIXEL (f);
Richard M. Stallman's avatar
Richard M. Stallman committed
649 650 651 652
  ew->emacs_frame.cursor_color = x->cursor_pixel;
  ew->core.border_pixel = x->border_pixel;
}

653
static void
654
EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2)
Richard M. Stallman's avatar
Richard M. Stallman committed
655 656 657 658 659 660 661 662 663 664 665
{
  EmacsFrame ew = (EmacsFrame)new;

  if (!ew->emacs_frame.frame)
    {
      fprintf (stderr,
	       "can't create an emacs frame widget without a frame\n");
      exit (1);
    }

  update_from_various_frame_slots (ew);
666
  set_frame_size (ew);
Richard M. Stallman's avatar
Richard M. Stallman committed
667 668 669 670
}


static void
671
EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs)
Richard M. Stallman's avatar
Richard M. Stallman committed
672 673 674
{
  EmacsFrame ew = (EmacsFrame)widget;

675 676
  /* This used to contain SubstructureRedirectMask, but this turns out
     to be a problem with XIM on Solaris, and events from that mask
677
     don't seem to be used.  Let's check that.  */
678 679 680
  attrs->event_mask = (STANDARD_EVENT_SET
		       | PropertyChangeMask
		       | SubstructureNotifyMask);
Richard M. Stallman's avatar
Richard M. Stallman committed
681 682 683
  *mask |= CWEventMask;
  XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
		  attrs);
684
  update_wm_hints (ew);
Richard M. Stallman's avatar
Richard M. Stallman committed
685 686
}

687
extern void free_frame_faces (struct frame *);
Richard M. Stallman's avatar
Richard M. Stallman committed
688 689

static void
690
EmacsFrameDestroy (Widget widget)
Richard M. Stallman's avatar
Richard M. Stallman committed
691 692 693 694 695
{
  EmacsFrame ew = (EmacsFrame) widget;
  struct frame* s = ew->emacs_frame.frame;

  if (! s) abort ();
Karl Heuer's avatar
Karl Heuer committed
696
  if (! s->output_data.x) abort ();
Richard M. Stallman's avatar
Richard M. Stallman committed
697

698
  BLOCK_INPUT;
699
  x_free_gcs (s);
700 701 702 703
  if (s->output_data.x->white_relief.gc)
    XFreeGC (XtDisplay (widget), s->output_data.x->white_relief.gc);
  if (s->output_data.x->black_relief.gc)
    XFreeGC (XtDisplay (widget), s->output_data.x->black_relief.gc);
704
  UNBLOCK_INPUT;
Richard M. Stallman's avatar
Richard M. Stallman committed
705 706 707
}

void
708
EmacsFrameResize (Widget widget)
Richard M. Stallman's avatar
Richard M. Stallman committed
709 710 711 712 713 714 715
{
  EmacsFrame ew = (EmacsFrame)widget;
  struct frame *f = ew->emacs_frame.frame;
  int columns;
  int rows;

  pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
716
  change_frame_size (f, rows, columns, 0, 1, 0);
717
  update_wm_hints (ew);
Richard M. Stallman's avatar
Richard M. Stallman committed
718
  update_various_frame_slots (ew);
719 720

  cancel_mouse_face (f);
Richard M. Stallman's avatar
Richard M. Stallman committed
721 722 723
}

static Boolean
724
EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, ArgList dum1, Cardinal *dum2)
Richard M. Stallman's avatar
Richard M. Stallman committed
725 726 727 728 729 730 731 732 733 734 735 736
{
  EmacsFrame cur = (EmacsFrame)cur_widget;
  EmacsFrame new = (EmacsFrame)new_widget;

  Boolean needs_a_refresh = False;
  Boolean has_to_recompute_size;
  Boolean has_to_recompute_gcs;
  Boolean has_to_update_hints;

  int char_width, char_height;
  Dimension pixel_width;
  Dimension pixel_height;
737

738
  /* AFAIK, this function is never called. -- Jan D, Oct 2009.  */
Richard M. Stallman's avatar
Richard M. Stallman committed
739 740 741 742 743 744
  has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
			  || (cur->emacs_frame.foreground_pixel
			      != new->emacs_frame.foreground_pixel)
			  || (cur->core.background_pixel
			      != new->core.background_pixel)
			  );
745

Richard M. Stallman's avatar
Richard M. Stallman committed
746 747 748 749 750 751 752 753 754 755 756
  has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
			   && cur->core.width == new->core.width
			   && cur->core.height == new->core.height);

  has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);

  if (has_to_recompute_gcs)
    {
      setup_frame_gcs (new);
      needs_a_refresh = True;
    }
757

Richard M. Stallman's avatar
Richard M. Stallman committed
758 759 760 761 762 763 764 765 766 767 768 769
  if (has_to_recompute_size)
    {
      pixel_width = new->core.width;
      pixel_height = new->core.height;
      pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
			  &char_height);
      char_to_pixel_size (new, char_width, char_height, &pixel_width,
			  &pixel_height);
      new->core.width = pixel_width;
      new->core.height = pixel_height;

      change_frame_size (new->emacs_frame.frame, char_height, char_width,
770
			  1, 0, 0);
Richard M. Stallman's avatar
Richard M. Stallman committed
771 772 773 774 775 776 777 778 779 780 781
      needs_a_refresh = True;
    }

  if (has_to_update_hints)
    update_wm_hints (new);

  update_various_frame_slots (new);

  /* #### This doesn't work, I haven't been able to find ANY kludge that
     will let (x-create-frame '((iconic . t))) work.  It seems that changes
     to wm_shell's iconic slot have no effect after it has been realized,
Karl Heuer's avatar
Karl Heuer committed
782
     and calling XIconifyWindow doesn't work either (even though the window
Richard M. Stallman's avatar
Richard M. Stallman committed
783
     has been created.)  Perhaps there is some property we could smash
Karl Heuer's avatar
Karl Heuer committed
784
     directly, but I'm sick of this for now.
Richard M. Stallman's avatar
Richard M. Stallman committed
785 786 787 788
   */
  if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
    {
      Widget wmshell = get_wm_shell ((Widget) cur);
789 790
      XtVaSetValues (wmshell, XtNiconic,
		     (XtArgVal) new->emacs_frame.iconic, NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
791 792 793 794 795 796
    }

  return needs_a_refresh;
}

static XtGeometryResult
797
EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeometry *result)
Richard M. Stallman's avatar
Richard M. Stallman committed
798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826
{
  EmacsFrame ew = (EmacsFrame)widget;

  int mask = request->request_mode;
  Dimension ok_width, ok_height;

  if (mask & (CWWidth | CWHeight))
    {
      round_size_to_char (ew,
			  (mask & CWWidth) ? request->width : ew->core.width,
			  ((mask & CWHeight) ? request->height
			   : ew->core.height),
			  &ok_width, &ok_height);
      if ((mask & CWWidth) && (ok_width != request->width))
	{
	  result->request_mode |= CWWidth;
	  result->width = ok_width;
	}
      if ((mask & CWHeight) && (ok_height != request->height))
	{
	  result->request_mode |= CWHeight;
	  result->height = ok_height;
	}
    }
  return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
}

/* Special entrypoints */
void
827
EmacsFrameSetCharSize (Widget widget, int columns, int rows)
Richard M. Stallman's avatar
Richard M. Stallman committed
828 829
{
  EmacsFrame ew = (EmacsFrame) widget;
830
  struct frame *f = ew->emacs_frame.frame;
831

832
  x_set_window_size (f, 0, columns, rows);
Richard M. Stallman's avatar
Richard M. Stallman committed
833
}
834

835

Andreas Schwab's avatar
Andreas Schwab committed
836
void
837
widget_store_internal_border (Widget widget)
838 839 840 841
{
  EmacsFrame ew = (EmacsFrame) widget;
  FRAME_PTR f = ew->emacs_frame.frame;

842
  ew->emacs_frame.internal_border_width = f->internal_border_width;
843
}
Miles Bader's avatar
Miles Bader committed
844 845 846

/* arch-tag: 931d28e5-0d59-405a-8325-7d475d0a13d9
   (do not change this comment) */