diff src/frame-msw.c @ 269:b2472a1930f2 r20-5b33

Import from CVS: tag r20-5b33
author cvs
date Mon, 13 Aug 2007 10:27:19 +0200
parents 83b3d10dcba9
children c5d627a313b1
line wrap: on
line diff
--- a/src/frame-msw.c	Mon Aug 13 10:26:31 2007 +0200
+++ b/src/frame-msw.c	Mon Aug 13 10:27:19 2007 +0200
@@ -31,18 +31,27 @@
 #include <config.h>
 #include "lisp.h"
 
+#include "buffer.h"
 #include "console-msw.h"
-
-#include "buffer.h"
+#include "events.h"
 #include "faces.h"
 #include "frame.h"
-#include "events.h"
+#include "redisplay.h"
 
-#define MSWINDOWS_FRAME_STYLE WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_OVERLAPPEDWINDOW
-#define MSWINDOWS_POPUP_STYLE WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_CAPTION|WS_POPUP
+#define MSWINDOWS_FRAME_STYLE (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW)
+#define MSWINDOWS_POPUP_STYLE (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP \
+			       | WS_CAPTION | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX)
 
 #define MSWINDOWS_FRAME_EXSTYLE WS_EX_OVERLAPPEDWINDOW
-#define MSWINDOWS_POPUP_EXSTYLE WS_EX_OVERLAPPEDWINDOW
+#define MSWINDOWS_POPUP_EXSTYLE WS_EX_PALETTEWINDOW
+
+/* Default popup left top corner offset from the same
+   corner of the parent frame, in pixel */
+#define POPUP_OFFSET 30
+
+/* Default popup size, in characters */
+#define POPUP_WIDTH 30
+#define POPUP_HEIGHT 10
 
 #ifdef HAVE_MENUBARS
 #define ADJR_MENUFLAG TRUE
@@ -52,26 +61,58 @@
 
 /* Default properties to use when creating frames.  */
 Lisp_Object Vdefault_mswindows_frame_plist;
+
 /* Lisp_Object Qname, Qheight, Qwidth, Qinitially_unmapped, Qpopup, Qtop, Qleft; */
 Lisp_Object Qinitially_unmapped, Qpopup;
 
+/* This does not need to be GC protected, as it holds a
+   frame Lisp_Object already protected by Fmake_frame */
+Lisp_Object mswindows_frame_being_created;
+
+/* Geometry, in characters, as specified by proplist during frame
+   creation. Memebers are set to -1 for unspecified */
+XEMACS_RECT_WH mswindows_frame_target_rect;
+
 static void
 mswindows_init_frame_1 (struct frame *f, Lisp_Object props)
 {
   Lisp_Object device = FRAME_DEVICE (f);
   Lisp_Object initially_unmapped;
   Lisp_Object name, height, width, popup, top, left;
-  Lisp_Object frame_obj;
+  Lisp_Object frame_obj = Qnil;
   RECT rect;
+  XEMACS_RECT_WH rect_default;
   DWORD style, exstyle;
+  HWND hwnd, hwnd_parent;
 
+  /* Pick up relevant properties */
   initially_unmapped = Fplist_get (props, Qinitially_unmapped, Qnil);
   name = Fplist_get (props, Qname, Qnil);
-  height = Fplist_get (props, Qheight, Qnil);
-  width = Fplist_get (props, Qwidth, Qnil);
+  
   popup = Fplist_get (props, Qpopup, Qnil);
+  if (EQ (popup, Qt))
+    popup = Fselected_frame (Qnil);
+
+  left = Fplist_get (props, Qleft, Qnil);
+  if (!NILP (left))
+    CHECK_INT (left);
+
   top = Fplist_get (props, Qtop, Qnil);
-  left = Fplist_get (props, Qleft, Qnil);
+  if (!NILP (top))
+    CHECK_INT (top);
+
+  width = Fplist_get (props, Qwidth, Qnil);
+  if (!NILP (width))
+    CHECK_INT (width);
+
+  height = Fplist_get (props, Qheight, Qnil);
+  if (!NILP (height))
+    CHECK_INT (height);
+
+  mswindows_frame_target_rect.left = NILP (left) ? -1 : abs (XINT (left));
+  mswindows_frame_target_rect.top = NILP (top) ? -1 : abs (XINT (top));
+  mswindows_frame_target_rect.width = NILP (width) ? -1 : abs (XINT (width));
+  mswindows_frame_target_rect.height = NILP (height) ? -1 : abs (XINT (height));
 
   /* These shouldn't be here, but the window is created too early.
      The initialization of scrollbar resources is done between
@@ -80,17 +121,8 @@
   f->scrollbar_height = make_int (15);
 
   f->frame_data = xnew_and_zero (struct mswindows_frame);
-  FRAME_WIDTH (f) = INTP(width) ? XINT(width) : 80;
-  FRAME_HEIGHT (f) = INTP(height) ? XINT(height) : 30;
-  char_to_pixel_size (f, FRAME_WIDTH(f), FRAME_HEIGHT (f),
-		      &FRAME_PIXWIDTH (f), &FRAME_PIXHEIGHT (f));
 
-  style = (NILP(popup)) ? MSWINDOWS_FRAME_STYLE : MSWINDOWS_POPUP_STYLE;
-  exstyle = (NILP(popup)) ? MSWINDOWS_FRAME_EXSTYLE : MSWINDOWS_POPUP_EXSTYLE;
-  rect.left = rect.top = 0;
-  rect.right = FRAME_PIXWIDTH (f);
-  rect.bottom = FRAME_PIXHEIGHT (f);
-
+  /* Misc frame stuff */
   FRAME_MSWINDOWS_DATA(f)->button2_need_lbutton = 0;
   FRAME_MSWINDOWS_DATA(f)->button2_need_rbutton = 0;
   FRAME_MSWINDOWS_DATA(f)->button2_is_down = 0;
@@ -100,41 +132,105 @@
 
   FRAME_MSWINDOWS_MENU_HASHTABLE(f) = Qnil;
 
+  /* Will initialize these in WM_SIZE handler. We cannot do it now,
+     because we do not know what is CW_USEDEFAULT height and width */
+  FRAME_WIDTH (f) = 0;
+  FRAME_HEIGHT (f) = 0;
+  FRAME_PIXWIDTH (f) = 0;
+  FRAME_PIXHEIGHT (f) = 0;
+
+  if (NILP (popup))
+    {
+      style = MSWINDOWS_FRAME_STYLE;
+      exstyle = MSWINDOWS_FRAME_EXSTYLE;
+      hwnd_parent = NULL;
+
+      /* We always create am overlapped frame with default size,
+	 and later adjust only requested geometry parameters. */
+      rect_default.left = rect_default.top = CW_USEDEFAULT;
+      rect_default.width = rect_default.height = CW_USEDEFAULT;
+    }
+  else
+    {
+      style = MSWINDOWS_POPUP_STYLE;
+      exstyle = MSWINDOWS_POPUP_EXSTYLE;
+
+      CHECK_MSWINDOWS_FRAME (popup);
+      hwnd_parent = FRAME_MSWINDOWS_HANDLE (XFRAME (popup));
+      assert (IsWindow (hwnd_parent));
+
+      /* We cannot use CW_USEDEFAULT when creating a popup window.
+	 So by default, we offset the new popup 30 pixels right
+	 and down from its parent, and give it size of 30x10 characters.
+	 These dimensions look adequate on both high and low res monitors */
+      GetWindowRect (hwnd_parent, &rect);
+      rect_default.left = rect.left + POPUP_OFFSET;
+      rect_default.top = rect.top + POPUP_OFFSET;
+      char_to_real_pixel_size (f, POPUP_WIDTH, POPUP_HEIGHT,
+			       &rect_default.width, &rect_default.height);
+    }
+
   AdjustWindowRectEx(&rect, style, ADJR_MENUFLAG, exstyle);
 
-  FRAME_MSWINDOWS_HANDLE(f) =
-    CreateWindowEx (exstyle,
-		    XEMACS_CLASS,
-		    STRINGP(f->name) ? XSTRING_DATA(f->name) :
-		    	(STRINGP(name) ? XSTRING_DATA(name) : XEMACS_CLASS),
-		    style,
-		    INTP(left) ? XINT(left) : CW_USEDEFAULT,
-		    INTP(top) ? XINT(top) : CW_USEDEFAULT,
-		    rect.right-rect.left, rect.bottom-rect.top,
-		    NULL, NULL, NULL, NULL);
   XSETFRAME (frame_obj, f);
-  SetWindowLong (FRAME_MSWINDOWS_HANDLE(f), XWL_FRAMEOBJ, (LONG)frame_obj);
-  FRAME_MSWINDOWS_DC(f) = GetDC(FRAME_MSWINDOWS_HANDLE(f));
-  SetTextAlign(FRAME_MSWINDOWS_DC(f), TA_BASELINE|TA_LEFT|TA_NOUPDATECP);
+
+  mswindows_frame_being_created = frame_obj;
+
+  hwnd = CreateWindowEx (exstyle,
+			 XEMACS_CLASS,
+			 STRINGP(f->name) ? XSTRING_DATA(f->name) :
+		    	   (STRINGP(name) ? XSTRING_DATA(name) : XEMACS_CLASS),
+			 style,
+			 rect_default.left, rect_default.top,
+			 rect_default.width, rect_default.height,
+			 hwnd_parent, NULL, NULL, NULL);
+
+  mswindows_frame_being_created = Qnil;
+
+  if (hwnd == NULL)
+    error ("System call to create frame failed");
+			   
+  FRAME_MSWINDOWS_HANDLE(f) = hwnd;
+
+  SetWindowLong (hwnd, XWL_FRAMEOBJ, (LONG)LISP_TO_VOID(frame_obj));
+  FRAME_MSWINDOWS_DC(f) = GetDC (hwnd);
+  FRAME_MSWINDOWS_CDC(f) = CreateCompatibleDC (FRAME_MSWINDOWS_CDC(f));
+  SetTextAlign (FRAME_MSWINDOWS_DC(f), TA_BASELINE | TA_LEFT | TA_NOUPDATECP);
 }
 
-/* Called just before frame's properties are set, size is 10x10 or something */
+#if 0 /* #### unused */
 static void
 mswindows_init_frame_2 (struct frame *f, Lisp_Object props)
 {
 }
+#endif
 
 /* Called after frame's properties are set */
 static void
 mswindows_init_frame_3 (struct frame *f)
 {
-  /* Don't do this earlier or we get a WM_PAINT before the frame is ready*/
+  /* Don't do this earlier or we get a WM_PAINT before the frame is ready */
   ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_SHOWNORMAL);
   SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
   DragAcceptFiles (FRAME_MSWINDOWS_HANDLE(f), TRUE);
 }
 
 static void
+mswindows_after_init_frame (struct frame *f, int first_on_device,
+		            int first_on_console)
+{
+  /* Windows, unlike X, is very synchronous. After the initial
+     frame is created, it will never be displayed, except for 
+     hollow border, unless we start pumping messages. Load progress
+     messages show in the bottom of the hollow frame, which is ugly.
+     We redipsplay the initial frame here, so modeline and root window
+     backgorund show.
+  */
+  if (first_on_console)
+    redisplay ();
+}
+
+static void
 mswindows_mark_frame (struct frame *f, void (*markobj) (Lisp_Object))
 {
   ((markobj) (FRAME_MSWINDOWS_MENU_HASHTABLE (f)));
@@ -143,7 +239,7 @@
 static void
 mswindows_focus_on_frame (struct frame *f)
 {
-    SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
+  SetForegroundWindow (FRAME_MSWINDOWS_HANDLE(f));
 }
 
 static void
@@ -151,37 +247,41 @@
 {
   if (f->frame_data)
     {
+      DeleteDC(FRAME_MSWINDOWS_CDC(f));
       ReleaseDC(FRAME_MSWINDOWS_HANDLE(f), FRAME_MSWINDOWS_DC(f));
       DestroyWindow(FRAME_MSWINDOWS_HANDLE(f));
+      xfree (f->frame_data);
     }
+  f->frame_data = 0;
 }
 
 static void
 mswindows_set_frame_size (struct frame *f, int cols, int rows)
 {
-  RECT rect1, rect2;
-  
-  GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rect1);
-  rect2.left = rect2.top = 0;
-  char_to_pixel_size (f, cols, rows, &rect2.right, &rect2.bottom);
+  RECT rect;
+  rect.left = rect.top = 0;
+  rect.right = cols;
+  rect.bottom = rows;
 
-  AdjustWindowRectEx (&rect2,
+  AdjustWindowRectEx (&rect,
 		      GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
 		      GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
 		      GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
-		    
-  MoveWindow (FRAME_MSWINDOWS_HANDLE(f), rect1.left, rect1.top,
- 	      rect2.right-rect2.left, rect2.bottom-rect2.top, TRUE);
+
+  if (IsIconic (FRAME_MSWINDOWS_HANDLE(f)) || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
+    ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
+
+  SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL, 
+		0, 0, rect.right-rect.left, rect.bottom-rect.top,
+		SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOMOVE);
 }
 
 static void
 mswindows_set_frame_position (struct frame *f, int xoff, int yoff)
 {
-  RECT rect;
-
-  GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rect);
-  MoveWindow (FRAME_MSWINDOWS_HANDLE(f), xoff, yoff,
-	      rect.right-rect.left, rect.bottom-rect.top, TRUE);
+  SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL, 
+		xoff, yoff, 0, 0,
+		SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOSIZE);
 }
 
 static void
@@ -234,11 +334,8 @@
 static void
 mswindows_lower_frame (struct frame *f)
 {
-  RECT rect;
-  
-  GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rect);
-  SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), HWND_BOTTOM, rect.top, rect.left,
-		rect.right-rect.left, rect.bottom-rect.top, 0);
+  SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), HWND_BOTTOM, 0, 0, 0, 0,
+		SWP_NOSIZE | SWP_NOMOVE | SWP_NOSENDCHANGING);
 }
 
 static void
@@ -308,19 +405,24 @@
 	}
     }
 
-  /* Now we've extracted the properties, apply them */
-  if (width_specified_p || height_specified_p || x_specified_p || y_specified_p)
+  /* Now we've extracted the properties, apply them.
+     Do not apply geometric properties during frame creation. This
+     is excessive anyways, and this loses becuase WM_SIZE has not
+     been sent yet, so frame width and height fields are not initialized
+  */ 
+  if (f->init_finished
+      && (width_specified_p || height_specified_p || x_specified_p || y_specified_p))
     {
-      Lisp_Object frame;
+      Lisp_Object frame = Qnil;
       RECT rect;
       int pixel_width, pixel_height;
       XSETFRAME (frame, f);
 
+      char_to_real_pixel_size (f, width, height, &pixel_width, &pixel_height);
       if (!width_specified_p)
-	width = FRAME_WIDTH (f);
+	pixel_width = FRAME_PIXWIDTH (f);
       if (!height_specified_p)
-	height = FRAME_HEIGHT (f);
-      char_to_pixel_size (f, width, height, &pixel_width, &pixel_height);
+	pixel_height = FRAME_PIXHEIGHT (f);
 
       GetWindowRect (FRAME_MSWINDOWS_HANDLE(f), &rect);
       if (!x_specified_p)
@@ -328,24 +430,85 @@
       if (!y_specified_p)
 	y = rect.top;
 
+      rect.left = rect.top = 0;
+      rect.right = pixel_width;
+      rect.bottom = pixel_height;
       AdjustWindowRectEx (&rect,
 			  GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_STYLE),
 			  GetMenu (FRAME_MSWINDOWS_HANDLE(f)) != NULL,
 			  GetWindowLong (FRAME_MSWINDOWS_HANDLE(f), GWL_EXSTYLE));
+      
 
-      MoveWindow (FRAME_MSWINDOWS_HANDLE(f), x, y, pixel_width, pixel_height,
-		  (width_specified_p || height_specified_p));
+      if (IsIconic (FRAME_MSWINDOWS_HANDLE(f)) || IsZoomed (FRAME_MSWINDOWS_HANDLE(f)))
+	ShowWindow (FRAME_MSWINDOWS_HANDLE(f), SW_RESTORE);
+
+      SetWindowPos (FRAME_MSWINDOWS_HANDLE(f), NULL, 
+		    x, y, rect.right - rect.left, rect.bottom - rect.top,
+		    SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING
+		    | ((width_specified_p || height_specified_p) ? 0 : SWP_NOSIZE)
+		    | ((x_specified_p || y_specified_p) ? 0 : SWP_NOMOVE));
     }
 }
 
+static Lisp_Object
+mswindows_get_frame_parent (struct frame *f)
+{
+  HWND hwnd = FRAME_MSWINDOWS_HANDLE(f);
+  hwnd = GetParent (hwnd);
+  if (hwnd)
+    {
+      Lisp_Object parent;
+      VOID_TO_LISP (parent, GetWindowLong (hwnd, XWL_FRAMEOBJ));
+      assert (FRAME_MSWINDOWS_P (XFRAME (parent)));
+      return parent;
+    }
+  else
+    return Qnil;
+}
+
+static void
+mswindows_update_frame_external_traits (struct frame* frm, Lisp_Object name)
+{
+  if (EQ (name, Qfont))
+    {
+      /* We resize the frame along with the font if user preference
+	 of MS style compliance is turned off, and if font size has
+	 really changed
+      */
+      /* #### Frame gets resized after font here */
+      if (1)
+	{
+	  int new_char_height, new_char_width;
+          pixel_to_real_char_size (frm, FRAME_PIXWIDTH(frm), FRAME_PIXHEIGHT(frm),
+				   &new_char_width, &new_char_height);
+	  if (new_char_width != MSWINDOWS_FRAME_CHARWIDTH (frm)
+	      || new_char_height != MSWINDOWS_FRAME_CHARHEIGHT (frm))
+	    {
+	      Lisp_Object frame;
+	      XSETFRAME (frame, frm);
+	      Fset_frame_size (frame, MSWINDOWS_FRAME_CHARWIDTH (frm),
+			       MSWINDOWS_FRAME_CHARHEIGHT (frm), Qnil);
+	    }
+	}
+
+      /* This resizes minibuffer and redraws modeline. */
+      {
+        int width, height;
+	pixel_to_char_size (frm, FRAME_PIXWIDTH(frm), FRAME_PIXHEIGHT(frm),
+			    &width, &height);
+	change_frame_size (frm, height, width, 1);
+      }
+   }
+}
 
 void
 console_type_create_frame_mswindows (void)
 {
   /* frame methods */
   CONSOLE_HAS_METHOD (mswindows, init_frame_1);
-  CONSOLE_HAS_METHOD (mswindows, init_frame_2);
+/*  CONSOLE_HAS_METHOD (mswindows, init_frame_2); */
   CONSOLE_HAS_METHOD (mswindows, init_frame_3);
+  CONSOLE_HAS_METHOD (mswindows, after_init_frame);
   CONSOLE_HAS_METHOD (mswindows, mark_frame);
   CONSOLE_HAS_METHOD (mswindows, focus_on_frame);
   CONSOLE_HAS_METHOD (mswindows, delete_frame);
@@ -369,7 +532,8 @@
   CONSOLE_HAS_METHOD (mswindows, frame_iconified_p);
 /*  CONSOLE_HAS_METHOD (mswindows, set_frame_pointer); */
 /*  CONSOLE_HAS_METHOD (mswindows, set_frame_icon); */
-/*  CONSOLE_HAS_METHOD (mswindows, get_frame_parent); */
+  CONSOLE_HAS_METHOD (mswindows, get_frame_parent);
+  CONSOLE_HAS_METHOD (mswindows, update_frame_external_traits);
 }
 
 void
@@ -389,6 +553,9 @@
 void
 vars_of_frame_mswindows (void)
 {
+  mswindows_frame_being_created = Qnil;
+  staticpro (&mswindows_frame_being_created);
+
   DEFVAR_LISP ("default-mswindows-frame-plist", &Vdefault_mswindows_frame_plist /*
 Plist of default frame-creation properties for mswindows frames.
 These override what is specified in `default-frame-plist', but are