3325da7acd9d283f54589f7becc7933bac636373
[chise/xemacs-chise.git.1] / src / frame-msw.c
1 /* Functions for the mswindows window system.
2    Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3    Copyright (C) 1995, 1996 Ben Wing.
4
5 This file is part of XEmacs.
6
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING.  If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 /* Synched up with: Not synched with FSF. */
23
24 /* Authorship:
25
26    Ultimately based on FSF.
27    Substantially rewritten for XEmacs by Ben Wing.
28    Rewritten for mswindows by Jonathan Harris, November 1997 for 21.0.
29    Graphics features added and frame resizing fiddled with by Andy Piper.
30  */
31
32 #include <config.h>
33 #include "lisp.h"
34
35 #include "buffer.h"
36 #include "console-msw.h"
37 #include "glyphs-msw.h"
38 #include "elhash.h"
39 #include "events.h"
40 #include "faces.h"
41 #include "frame.h"
42 #include "redisplay.h"
43 #include "window.h"
44
45 #define MSWINDOWS_FRAME_STYLE (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW)
46 #define MSWINDOWS_POPUP_STYLE (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP \
47                                | WS_CAPTION | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX)
48
49 #define MSWINDOWS_FRAME_EXSTYLE WS_EX_OVERLAPPEDWINDOW
50 #define MSWINDOWS_POPUP_EXSTYLE WS_EX_PALETTEWINDOW
51
52 /* Default popup left top corner offset from the same
53    corner of the parent frame, in pixel */
54 #define POPUP_OFFSET 30
55
56 /* Default popup size, in characters */
57 #define POPUP_WIDTH 30
58 #define POPUP_HEIGHT 10
59
60 /* Default popup size, in characters */
61 #define DEFAULT_FRAME_WIDTH 80
62 #define DEFAULT_FRAME_HEIGHT 35
63
64 #ifdef HAVE_MENUBARS
65 #define ADJR_MENUFLAG TRUE
66 #else
67 #define ADJR_MENUFLAG FALSE
68 #endif
69
70 /* Default properties to use when creating frames.  */
71 Lisp_Object Vdefault_mswindows_frame_plist;
72 Lisp_Object Vmswindows_use_system_frame_size_defaults;
73
74 /* This does not need to be GC protected, as it holds a
75    frame Lisp_Object already protected by Fmake_frame */
76 Lisp_Object Vmswindows_frame_being_created;
77
78 static void
79 mswindows_init_frame_1 (struct frame *f, Lisp_Object props)
80 {
81   Lisp_Object initially_unmapped;
82   Lisp_Object name, height, width, popup, top, left;
83   Lisp_Object frame_obj = Qnil;
84   RECT rect;
85   XEMACS_RECT_WH rect_default;
86   DWORD style, exstyle;
87   HWND hwnd, hwnd_parent;
88
89   /* Pick up relevant properties */
90   initially_unmapped = Fplist_get (props, Qinitially_unmapped, Qnil);
91   name = Fplist_get (props, Qname, Qnil);
92   
93   popup = Fplist_get (props, Qpopup, Qnil);
94   if (EQ (popup, Qt))
95     popup = Fselected_frame (Qnil);
96
97   left = Fplist_get (props, Qleft, Qnil);
98   if (!NILP (left))
99     CHECK_INT (left);
100
101   top = Fplist_get (props, Qtop, Qnil);
102   if (!NILP (top))
103     CHECK_INT (top);
104
105   width = Fplist_get (props, Qwidth, Qnil);
106   if (!NILP (width))
107     CHECK_INT (width);
108
109   height = Fplist_get (props, Qheight, Qnil);
110   if (!NILP (height))
111     CHECK_INT (height);
112
113   f->frame_data = xnew_and_zero (struct mswindows_frame);
114   FRAME_MSWINDOWS_TARGET_RECT (f) = xnew_and_zero (XEMACS_RECT_WH);
115
116   FRAME_MSWINDOWS_TARGET_RECT (f)->left = NILP (left) ? -1 : abs (XINT (left));
117   FRAME_MSWINDOWS_TARGET_RECT (f)->top = NILP (top) ? -1 : abs (XINT (top));
118   FRAME_MSWINDOWS_TARGET_RECT (f)->width = NILP (width) ? -1 : 
119     abs (XINT (width));
120   FRAME_MSWINDOWS_TARGET_RECT (f)->height = NILP (height) ? -1 : 
121     abs (XINT (height));
122       
123   /* Misc frame stuff */
124   FRAME_MSWINDOWS_DATA(f)->button2_need_lbutton = 0;
125   FRAME_MSWINDOWS_DATA(f)->button2_need_rbutton = 0;
126   FRAME_MSWINDOWS_DATA(f)->button2_is_down = 0;
127   FRAME_MSWINDOWS_DATA(f)->ignore_next_lbutton_up = 0;
128   FRAME_MSWINDOWS_DATA(f)->ignore_next_rbutton_up = 0;
129   FRAME_MSWINDOWS_DATA(f)->sizing = 0;
130   FRAME_MSWINDOWS_MENU_HASH_TABLE(f) = Qnil;
131 #ifdef HAVE_TOOLBARS
132   FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE(f) =
133     make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQUAL);
134 #endif
135
136   /* Will initialize these in WM_SIZE handler. We cannot do it now,
137      because we do not know what is CW_USEDEFAULT height and width */
138   FRAME_WIDTH (f) = 0;
139   FRAME_HEIGHT (f) = 0;
140   FRAME_PIXWIDTH (f) = 0;
141   FRAME_PIXHEIGHT (f) = 0;
142
143   if (NILP (popup))
144     {
145       style = MSWINDOWS_FRAME_STYLE;
146       exstyle = MSWINDOWS_FRAME_EXSTYLE;
147       hwnd_parent = NULL;
148
149       rect_default.left = rect_default.top = CW_USEDEFAULT;
150       rect_default.width = rect_default.height = CW_USEDEFAULT;
151     }
152   else
153     {
154       style = MSWINDOWS_POPUP_STYLE;
155       exstyle = MSWINDOWS_POPUP_EXSTYLE;
156
157       CHECK_MSWINDOWS_FRAME (popup);
158       hwnd_parent = FRAME_MSWINDOWS_HANDLE (XFRAME (popup));
159       assert (IsWindow (hwnd_parent));
160
161       /* We cannot use CW_USEDEFAULT when creating a popup window.
162          So by default, we offset the new popup 30 pixels right
163          and down from its parent, and give it size of 30x10 characters.
164          These dimensions look adequate on both high and low res monitors */
165       GetWindowRect (hwnd_parent, &rect);
166       rect_default.left = rect.left + POPUP_OFFSET;
167       rect_default.top = rect.top + POPUP_OFFSET;
168       char_to_real_pixel_size (f, POPUP_WIDTH, POPUP_HEIGHT,
169                                &rect_default.width, &rect_default.height);
170     }
171
172   AdjustWindowRectEx(&rect, style, ADJR_MENUFLAG, exstyle);
173
174   XSETFRAME (frame_obj, f);
175
176   Vmswindows_frame_being_created = frame_obj;
177
178   hwnd = CreateWindowEx (exstyle,
179                          XEMACS_CLASS,
180                          STRINGP(f->name) ? XSTRING_DATA(f->name) :
181                          (STRINGP(name) ? XSTRING_DATA(name) : XEMACS_CLASS),
182                          style,
183                          rect_default.left, rect_default.top,
184                          rect_default.width, rect_default.height,
185                          hwnd_parent, NULL, NULL, NULL);
186
187   Vmswindows_frame_being_created = Qnil;
188
189   if (hwnd == NULL)
190     error ("System call to create frame failed");
191                            
192   FRAME_MSWINDOWS_HANDLE(f) = hwnd;
193
194   SetWindowLong (hwnd, XWL_FRAMEOBJ, (LONG)LISP_TO_VOID(frame_obj));
195   FRAME_MSWINDOWS_DC(f) = GetDC (hwnd);
196   FRAME_MSWINDOWS_CDC(f) = CreateCompatibleDC (FRAME_MSWINDOWS_CDC(f));
197   SetTextAlign (FRAME_MSWINDOWS_DC(f), TA_BASELINE | TA_LEFT | TA_NOUPDATECP);
198 }
199
200 static void
201 mswindows_init_frame_2 (struct frame *f, Lisp_Object props)
202 {
203   if (NILP (Vmswindows_use_system_frame_size_defaults))
204     {
205       /* I don't think anything can set the frame size before this
206          since we don't have X resources. This may change if we look
207          at the registry. Even so these values can get overridden
208          later.*/
209       XEMACS_RECT_WH dest = { -1, -1, DEFAULT_FRAME_WIDTH, 
210                               DEFAULT_FRAME_HEIGHT };
211       mswindows_size_frame_internal (f, &dest);
212     }
213 }
214
215 /* Called after frame's properties are set */
216 static void
217 mswindows_init_frame_3 (struct frame *f)
218 {
219   /* Don't do this earlier or we get a WM_PAINT before the frame is ready.
220    * The SW_x parameter in the first call that an app makes to ShowWindow is
221    * ignored, and the parameter specified in the caller's STARTUPINFO is 
222    * substituted instead. That parameter is SW_HIDE if we were started by
223    * runemacs, so call this twice. #### runemacs is evil */
224   ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOWNORMAL);
225   ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOWNORMAL);
226   SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
227   DragAcceptFiles (FRAME_MSWINDOWS_HANDLE(f), TRUE);
228 }
229
230 static void
231 mswindows_after_init_frame (struct frame *f, int first_on_device,
232                             int first_on_console)
233 {
234   /* Windows, unlike X, is very synchronous. After the initial
235      frame is created, it will never be displayed, except for 
236      hollow border, unless we start pumping messages. Load progress
237      messages show in the bottom of the hollow frame, which is ugly.
238      We redisplay the initial frame here, so modeline and root window
239      background show.
240   */
241   if (first_on_console)
242     redisplay ();
243 }
244
245 static void
246 mswindows_mark_frame (struct frame *f, void (*markobj) (Lisp_Object))
247 {
248   markobj (FRAME_MSWINDOWS_MENU_HASH_TABLE (f));
249 #ifdef HAVE_TOOLBARS
250   markobj (FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE (f));
251 #endif
252 }
253
254 static void
255 mswindows_focus_on_frame (struct frame *f)
256 {
257   SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
258 }
259
260 static void
261 mswindows_delete_frame (struct frame *f)
262 {
263   if (f->frame_data)
264     {
265       DeleteDC(FRAME_MSWINDOWS_CDC(f));
266       ReleaseDC(FRAME_MSWINDOWS_HANDLE(f), FRAME_MSWINDOWS_DC(f));
267       DestroyWindow(FRAME_MSWINDOWS_HANDLE(f));
268       xfree (f->frame_data);
269     }
270   f->frame_data = 0;
271 }
272
273 static void
274 mswindows_set_frame_size (struct frame *f, int width, int height)
275 {
276   RECT rect;
277   rect.left = rect.top = 0;
278   rect.right = width;
279   rect.bottom = height;
280
281   AdjustWindowRectEx (&rect,
282                       GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
283                       GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
284                       GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
285
286   if (IsIconic (FRAME_MSWINDOWS_HANDLE(f)) || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
287     ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
288
289   SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL, 
290                 0, 0, rect.right-rect.left, rect.bottom-rect.top,
291                 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOMOVE);
292 }
293
294 static void
295 mswindows_set_frame_position (struct frame *f, int xoff, int yoff)
296 {
297   SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL, 
298                 xoff, yoff, 0, 0,
299                 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOSIZE);
300 }
301
302 static void
303 mswindows_make_frame_visible (struct frame *f) 
304 {
305   if (f->iconified)
306     ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
307   else
308     ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOWNORMAL);
309   f->visible = 1;
310   f->iconified = 0;
311 }
312
313 static void
314 mswindows_make_frame_invisible (struct frame *f) 
315 {
316   ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_HIDE);
317   f->visible = -1;
318 }
319
320 static int
321 mswindows_frame_totally_visible_p (struct frame *f)
322 {
323   RECT rc_me, rc_other, rc_temp;
324   HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
325
326   /* We test against not a whole window rectangle, only against its
327      client part. So, if non-client are is covered and client area is
328      not, we return true. */
329   GetClientRect (hwnd, &rc_me);
330   MapWindowPoints (hwnd, HWND_DESKTOP, (LPPOINT)&rc_me, 2);
331
332   /* First see if we're off the desktop */
333   GetWindowRect (GetDesktopWindow(), &rc_other);
334   UnionRect(&rc_temp, &rc_me, &rc_other);
335   if (!EqualRect (&rc_temp, &rc_other))
336     return 0;
337   
338   /* Then see if any window above us obscures us */
339   while ((hwnd = GetWindow (hwnd, GW_HWNDPREV)) != NULL)
340     if (IsWindowVisible (hwnd))
341       {
342         GetWindowRect (hwnd, &rc_other);
343         if (IntersectRect(&rc_temp, &rc_me, &rc_other))
344           return 0;
345       }
346
347   return 1;
348 }
349
350 static int
351 mswindows_frame_visible_p (struct frame *f)
352 {
353   return IsWindowVisible (FRAME_MSWINDOWS_HANDLE(f))
354     && !IsIconic (FRAME_MSWINDOWS_HANDLE(f));
355 }
356
357
358 static void
359 mswindows_iconify_frame (struct frame *f)
360 {
361   ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_MINIMIZE);
362   f->visible = 0;
363   f->iconified = 1;
364 }
365
366 static int
367 mswindows_frame_iconified_p (struct frame *f)
368 {
369   return IsIconic (FRAME_MSWINDOWS_HANDLE(f));
370 }
371
372 static void
373 mswindows_set_frame_icon (struct frame *f)
374 {
375   if (IMAGE_INSTANCEP (f->icon)
376       && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (f->icon)))
377     {
378       if (!XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon))
379         {
380           mswindows_initialize_image_instance_icon (XIMAGE_INSTANCE (f->icon), 
381                                                     FALSE);
382         }
383       
384       SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HICON, 
385                     (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->icon));
386     }
387 }
388
389 static void
390 mswindows_set_frame_pointer (struct frame *f)
391 {
392   if (IMAGE_INSTANCEP (f->pointer)
393       && IMAGE_INSTANCE_TYPE (XIMAGE_INSTANCE (f->pointer)) == IMAGE_POINTER)
394     {
395       SetClassLong (FRAME_MSWINDOWS_HANDLE (f), GCL_HCURSOR,
396                     (LONG) XIMAGE_INSTANCE_MSWINDOWS_ICON (f->pointer));
397     }
398 }
399
400 static void
401 mswindows_set_mouse_position (struct window *w, int x, int y)
402 {
403   struct frame *f = XFRAME (w->frame);
404   POINT pt;
405
406   pt.x = w->pixel_left + x;
407   pt.y = w->pixel_top  + y;
408   ClientToScreen (FRAME_MSWINDOWS_HANDLE(f), &pt);
409   SetCursorPos (pt.x, pt.y);
410 }
411
412 static int
413 mswindows_get_mouse_position (struct device *d, Lisp_Object *frame, int *x, int *y)
414 {
415   POINT pt;
416   HWND hwnd;
417
418   GetCursorPos (&pt);
419
420   /* What's under cursor? */
421   hwnd = WindowFromPoint (pt);
422   if (hwnd == NULL)
423     return 0;
424
425   /* Get grandest parent of the window */
426   {
427     HWND hwnd_parent;
428     while ((hwnd_parent = GetParent (hwnd)) != NULL)
429       hwnd = hwnd_parent;
430   }
431
432   /* Make sure it belongs to us */
433   if (GetWindowThreadProcessId (hwnd, NULL) != GetCurrentThreadId ())
434     return 0;
435
436   /* And that the window is an XEmacs frame */
437   {
438     char class_name [sizeof(XEMACS_CLASS) + 1];
439     if (!GetClassName (hwnd, class_name, sizeof(XEMACS_CLASS))
440         || strcmp (class_name, XEMACS_CLASS) != 0)
441       return 0;
442   }
443
444   /* Yippie! */
445   ScreenToClient (hwnd, &pt);
446   VOID_TO_LISP (*frame, GetWindowLong (hwnd, XWL_FRAMEOBJ));
447   *x = pt.x;
448   *y = pt.y;
449   return 1;
450 }
451
452 static void
453 mswindows_raise_frame (struct frame *f)
454 {
455   BringWindowToTop (FRAME_MSWINDOWS_HANDLE(f));
456   /* XXX Should we do SetWindowForeground too ? */
457 }
458
459 static void
460 mswindows_lower_frame (struct frame *f)
461 {
462   SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), HWND_BOTTOM, 0, 0, 0, 0,
463                 SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING);
464 }
465
466 static void
467 mswindows_set_title_from_bufbyte (struct frame *f, Bufbyte *title) 
468 {
469   unsigned int new_checksum = hash_string (title, strlen (title));
470   if (new_checksum != FRAME_MSWINDOWS_TITLE_CHECKSUM(f))
471     {
472       FRAME_MSWINDOWS_TITLE_CHECKSUM(f) = new_checksum;
473       SetWindowText (FRAME_MSWINDOWS_HANDLE(f), title);
474     }
475 }
476
477 static Lisp_Object
478 mswindows_frame_property (struct frame *f, Lisp_Object property)
479 {
480   if (EQ (Qleft, property) || EQ (Qtop, property))
481     {
482       RECT rc;
483       GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
484       return make_int (EQ (Qtop,  property) ? rc.top : rc.left);
485     }
486   return Qunbound;
487 }
488
489 static int
490 mswindows_internal_frame_property_p (struct frame *f, Lisp_Object property)
491 {
492   return EQ (property, Qleft)
493     || EQ (property, Qtop);
494   /* #### frame-x.c has also this. Why?
495     || STRINGP (property);
496   */
497 }
498
499 static Lisp_Object
500 mswindows_frame_properties (struct frame *f)
501 {
502   Lisp_Object props = Qnil;
503   RECT rc;
504   GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rc);
505
506   props = cons3 (Qtop,  make_int (rc.top), props);
507   props = cons3 (Qleft, make_int (rc.left), props);
508
509   return props;
510 }
511
512 static void
513 mswindows_set_frame_properties (struct frame *f, Lisp_Object plist)
514 {
515   int x=-1, y=-1;
516   int width = -1, height = -1;
517   BOOL width_specified_p = FALSE;
518   BOOL height_specified_p = FALSE;
519   BOOL x_specified_p = FALSE;
520   BOOL y_specified_p = FALSE;
521   Lisp_Object tail;
522
523   /* Extract the properties from plist */
524   for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
525     {
526       Lisp_Object prop = Fcar (tail);
527       Lisp_Object val = Fcar (Fcdr (tail));
528
529       if (SYMBOLP (prop))
530         {
531           /* Kludge to handle the font property. */
532           if (EQ (prop, Qfont))
533             {
534               /* If the value is not a string we silently ignore it. */
535               if (STRINGP (val))
536                 {
537                   Lisp_Object frm, font_spec;
538                   
539                   XSETFRAME (frm, f);
540                   font_spec = Fget (Fget_face (Qdefault), Qfont, Qnil);
541
542                   Fadd_spec_to_specifier (font_spec, val, frm, Qnil, Qnil);
543                   update_frame_face_values (f);
544                 }
545             }
546           else if (EQ (prop, Qwidth))
547             {
548               CHECK_INT (val);
549               width = XINT (val);
550               width_specified_p = TRUE;
551             }
552           else if (EQ (prop, Qheight))
553             {
554               CHECK_INT (val);
555               height = XINT (val);
556               height_specified_p = TRUE;
557             }
558           else if (EQ (prop, Qleft))
559             {
560               CHECK_INT (val);
561               x = XINT (val);
562               x_specified_p = TRUE;
563             }
564           else if (EQ (prop, Qtop))
565             {
566               CHECK_INT (val);
567               y = XINT (val);
568               y_specified_p = TRUE;
569             }
570         }
571     }
572
573   /* Now we've extracted the properties, apply them.
574      Do not apply geometric properties during frame creation. This
575      is excessive anyways, and this loses becuase WM_SIZE has not
576      been sent yet, so frame width and height fields are not initialized.
577      
578      unfortunately WM_SIZE loses as well since the resize is only
579      applied once and the first time WM_SIZE is applied not everything
580      is initialised in the frame (toolbars for instance). enabling
581      this always makes no visible difference and fixes a whole host of
582      bugs (and is more consistent with X) so I am going to reenable it.
583      --andyp */
584   if ( FRAME_PIXWIDTH (f) && FRAME_PIXHEIGHT (f)
585        && (width_specified_p || height_specified_p || x_specified_p || y_specified_p))
586     {
587       XEMACS_RECT_WH dest = { x, y, width, height };
588
589       mswindows_size_frame_internal (f, &dest);
590     }
591 }
592
593 void mswindows_size_frame_internal (struct frame* f, XEMACS_RECT_WH* dest)
594 {
595   RECT rect;
596   int pixel_width, pixel_height;
597   int size_p = (dest->width >=0 || dest->height >=0);
598   int move_p = (dest->top >=0 || dest->left >=0);
599   struct device* d = XDEVICE (FRAME_DEVICE (f));
600   char_to_real_pixel_size (f, dest->width, dest->height, &pixel_width, &pixel_height);
601   
602   if (dest->width < 0)
603     pixel_width = FRAME_PIXWIDTH (f);
604   if (dest->height < 0)
605     pixel_height = FRAME_PIXHEIGHT (f);
606
607   GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rect);
608   if (dest->left < 0)
609     dest->left = rect.left;
610   if (dest->top < 0)
611     dest->top = rect.top;
612   
613   rect.left = rect.top = 0;
614   rect.right = pixel_width;
615   rect.bottom = pixel_height;
616
617   AdjustWindowRectEx (&rect,
618                       GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
619                       GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
620                       GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
621
622   /* resize and move the window so that it fits on the screen. This is
623   not restrictive since this will happen later anyway in WM_SIZE.  We
624   have to do this after adjusting the rect to account for menubar
625   etc. */
626   pixel_width = rect.right - rect.left;
627   pixel_height = rect.bottom - rect.top;
628   if (pixel_width > DEVICE_MSWINDOWS_HORZRES(d))
629     {
630       pixel_width = DEVICE_MSWINDOWS_HORZRES(d);
631       size_p=1;
632     }
633   if (pixel_height > DEVICE_MSWINDOWS_VERTRES(d))
634     {
635       pixel_height = DEVICE_MSWINDOWS_VERTRES(d);
636       size_p=1;
637     }
638
639   /* adjust position so window is on screen */
640   if (dest->left + pixel_width > DEVICE_MSWINDOWS_HORZRES(d))
641     {
642       dest->left = DEVICE_MSWINDOWS_HORZRES(d) - pixel_width;
643       move_p=1;
644     }
645   if (dest->top + pixel_height > DEVICE_MSWINDOWS_VERTRES(d))
646     {
647       dest->top = DEVICE_MSWINDOWS_VERTRES(d) - pixel_height;
648       move_p=1;
649     }
650
651   if (IsIconic (FRAME_MSWINDOWS_HANDLE(f)) 
652       || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
653     ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
654
655   SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL, 
656                 dest->left, dest->top, pixel_width, pixel_height,
657                 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING
658                 | (size_p ? 0 : SWP_NOSIZE)
659                 | (move_p ? 0 : SWP_NOMOVE));
660 }
661
662 static Lisp_Object
663 mswindows_get_frame_parent (struct frame *f)
664 {
665   HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
666   hwnd = GetParent (hwnd);
667   if (hwnd)
668     {
669       Lisp_Object parent;
670       VOID_TO_LISP (parent, GetWindowLong (hwnd, XWL_FRAMEOBJ));
671       assert (FRAME_MSWINDOWS_P (XFRAME (parent)));
672       return parent;
673     }
674   else
675     return Qnil;
676 }
677
678 static void
679 mswindows_update_frame_external_traits (struct frame* frm, Lisp_Object name)
680 {
681 }
682
683 static int
684 mswindows_frame_size_fixed_p (struct frame *f)
685 {
686   /* Frame size cannot change if the frame is maximized */
687   return IsZoomed (FRAME_MSWINDOWS_HANDLE (f));
688 }
689
690 void
691 console_type_create_frame_mswindows (void)
692 {
693   /* frame methods */
694   CONSOLE_HAS_METHOD (mswindows, init_frame_1);
695   CONSOLE_HAS_METHOD (mswindows, init_frame_2); 
696   CONSOLE_HAS_METHOD (mswindows, init_frame_3);
697   CONSOLE_HAS_METHOD (mswindows, after_init_frame);
698   CONSOLE_HAS_METHOD (mswindows, mark_frame);
699   CONSOLE_HAS_METHOD (mswindows, focus_on_frame);
700   CONSOLE_HAS_METHOD (mswindows, delete_frame);
701   CONSOLE_HAS_METHOD (mswindows, get_mouse_position);
702   CONSOLE_HAS_METHOD (mswindows, set_mouse_position);
703   CONSOLE_HAS_METHOD (mswindows, raise_frame);
704   CONSOLE_HAS_METHOD (mswindows, lower_frame);
705   CONSOLE_HAS_METHOD (mswindows, make_frame_visible);
706   CONSOLE_HAS_METHOD (mswindows, make_frame_invisible);
707   CONSOLE_HAS_METHOD (mswindows, iconify_frame);
708   CONSOLE_HAS_METHOD (mswindows, set_frame_size);
709   CONSOLE_HAS_METHOD (mswindows, set_frame_position);
710   CONSOLE_HAS_METHOD (mswindows, frame_property);
711   CONSOLE_HAS_METHOD (mswindows, internal_frame_property_p);
712   CONSOLE_HAS_METHOD (mswindows, frame_properties);
713   CONSOLE_HAS_METHOD (mswindows, set_frame_properties);
714   CONSOLE_HAS_METHOD (mswindows, set_title_from_bufbyte);
715 /*  CONSOLE_HAS_METHOD (mswindows, set_icon_name_from_bufbyte); */
716   CONSOLE_HAS_METHOD (mswindows, frame_visible_p);
717   CONSOLE_HAS_METHOD (mswindows, frame_totally_visible_p);
718   CONSOLE_HAS_METHOD (mswindows, frame_iconified_p);
719   CONSOLE_HAS_METHOD (mswindows, set_frame_pointer); 
720   CONSOLE_HAS_METHOD (mswindows, set_frame_icon); 
721   CONSOLE_HAS_METHOD (mswindows, get_frame_parent);
722   CONSOLE_HAS_METHOD (mswindows, update_frame_external_traits);
723   CONSOLE_HAS_METHOD (mswindows, frame_size_fixed_p);
724 }
725
726 void
727 syms_of_frame_mswindows (void)
728 {
729 }
730
731 void
732 vars_of_frame_mswindows (void)
733 {
734   /* Needn't staticpro -- see comment above.  */
735   Vmswindows_frame_being_created = Qnil;
736
737   DEFVAR_LISP ("mswindows-use-system-frame-size-defaults", &Vmswindows_use_system_frame_size_defaults /*
738 Controls whether to use system or XEmacs defaults for frame size.
739 If nil then reasonable defaults are used for intial frame sizes. If t
740 then the system will choose default sizes for the frame.
741 */ );
742   Vmswindows_use_system_frame_size_defaults = Qnil;
743   
744   DEFVAR_LISP ("default-mswindows-frame-plist", &Vdefault_mswindows_frame_plist /*
745 Plist of default frame-creation properties for mswindows frames.
746 These override what is specified in `default-frame-plist', but are
747 overridden by the arguments to the particular call to `make-frame'.
748
749 Note: In many cases, properties of a frame are available as specifiers
750 instead of through the frame-properties mechanism.
751
752 Here is a list of recognized frame properties, other than those
753 documented in `set-frame-properties' (they can be queried and
754 set at any time, except as otherwise noted):
755
756   initially-unmapped            If non-nil, the frame will not be visible
757                                 when it is created.  In this case, you
758                                 need to call `make-frame-visible' to make
759                                 the frame appear.
760   popup                         If non-nil, it should be a frame, and this
761                                 frame will be created as a "popup" frame
762                                 whose parent is the given frame.  This
763                                 will make the window manager treat the
764                                 frame as a dialog box, which may entail
765                                 doing different things (e.g. not asking
766                                 for positioning, and not iconifying
767                                 separate from its parent).
768   top                           Y position (in pixels) of the upper-left
769                                 outermost corner of the frame (i.e. the
770                                 upper-left of the window-manager
771                                 decorations).
772   left                          X position (in pixels) of the upper-left
773                                 outermost corner of the frame (i.e. the
774                                 upper-left of the window-manager
775                                 decorations).
776
777 See also `default-frame-plist', which specifies properties which apply
778 to all frames, not just mswindows frames.
779 */ );
780   Vdefault_mswindows_frame_plist = Qnil;
781
782   mswindows_console_methods->device_specific_frame_props =
783     &Vdefault_mswindows_frame_plist;
784 }