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