void PerformNCCalc(Hwnd hwnd) { XplatUIWin32.NCCALCSIZE_PARAMS ncp; IntPtr ptr; Rectangle rect; rect = new Rectangle (0, 0, hwnd.Width, hwnd.Height); ncp = new XplatUIWin32.NCCALCSIZE_PARAMS(); ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp)); ncp.rgrc1.left = rect.Left; ncp.rgrc1.top = rect.Top; ncp.rgrc1.right = rect.Right; ncp.rgrc1.bottom = rect.Bottom; Marshal.StructureToPtr(ncp, ptr, true); NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr); ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS)); Marshal.FreeHGlobal(ptr); rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top); hwnd.ClientRect = rect; rect = TranslateClientRectangleToXClientRectangle (hwnd); if (hwnd.visible) { MoveResizeWindow (DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height); } AddExpose (hwnd, hwnd.WholeWindow == hwnd.ClientWindow, 0, 0, hwnd.Width, hwnd.Height); }
internal override bool GetMessage (ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) { XEvent xevent; bool client; Hwnd hwnd; ProcessNextMessage: if (MessageQueue.Count > 0) { xevent = (XEvent) MessageQueue.Dequeue (); } else { UpdateMessageQueue (); if (MessageQueue.Count > 0) { xevent = (XEvent) MessageQueue.Dequeue (); } else { if (!PostQuitState) { msg.hwnd = IntPtr.Zero; msg.message = Msg.WM_ENTERIDLE; return true; } // We reset ourselves so GetMessage can be called again PostQuitState = false; return false; } } // FIXME - handle filtering hwnd = Hwnd.GetObjectFromWindow (xevent.AnyEvent.window); // Handle messages for windows that are already or are about to be destroyed if (hwnd == null) { #if DriverDebug Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32()); #endif goto ProcessNextMessage; } if (hwnd.client_window == xevent.AnyEvent.window) { client = true; //Console.WriteLine("Client message, sending to window {0:X}", msg.hwnd.ToInt32()); } else { client = false; //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32()); } msg.hwnd = hwnd.Handle; // // If you add a new event to this switch make sure to add it in // UpdateMessage also unless it is not coming through the X event system. // switch (xevent.type) { case XEventName.KeyPress: { Keyboard.KeyEvent (FocusWindow, xevent, ref msg); break; } case XEventName.KeyRelease: { Keyboard.KeyEvent (FocusWindow, xevent, ref msg); break; } case XEventName.ButtonPress: { switch (xevent.ButtonEvent.button) { case 1: { MouseState |= MouseButtons.Left; if (client) { msg.message = Msg.WM_LBUTTONDOWN; } else { msg.message = Msg.WM_NCLBUTTONDOWN; WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y); } // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down msg.wParam = GetMousewParam (0); break; } case 2: { MouseState |= MouseButtons.Middle; if (client) { msg.message = Msg.WM_MBUTTONDOWN; } else { msg.message = Msg.WM_NCMBUTTONDOWN; WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y); } msg.wParam = GetMousewParam (0); break; } case 3: { MouseState |= MouseButtons.Right; if (client) { msg.message = Msg.WM_RBUTTONDOWN; } else { msg.message = Msg.WM_NCRBUTTONDOWN; WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y); } msg.wParam = GetMousewParam (0); break; } case 4: { msg.message = Msg.WM_MOUSEWHEEL; msg.wParam = GetMousewParam (120); break; } case 5: { msg.message = Msg.WM_MOUSEWHEEL; msg.wParam = GetMousewParam (-120); break; } } msg.lParam = (IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x); MousePosition.X = xevent.ButtonEvent.x; MousePosition.Y = xevent.ButtonEvent.y; if (!hwnd.Enabled) { IntPtr dummy; msg.hwnd = hwnd.EnabledHwnd; XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle (msg.hwnd).ClientWindow, xevent.ButtonEvent.x, xevent.ButtonEvent.y, out xevent.ButtonEvent.x, out xevent.ButtonEvent.y, out dummy); msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X); } if (Grab.Hwnd != IntPtr.Zero) { msg.hwnd = Grab.Hwnd; } if (!ClickPending.Pending) { ClickPending.Pending = true; ClickPending.Hwnd = msg.hwnd; ClickPending.Message = msg.message; ClickPending.wParam = msg.wParam; ClickPending.lParam = msg.lParam; ClickPending.Time = (long)xevent.ButtonEvent.time; } else { if ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message)) { // Looks like a genuine double click, clicked twice on the same spot with the same keys switch (xevent.ButtonEvent.button) { case 1: { msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK; break; } case 2: { msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK; break; } case 3: { msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK; break; } } } ClickPending.Pending = false; } break; } case XEventName.ButtonRelease: { Dnd.HandleButtonRelease (ref xevent); switch (xevent.ButtonEvent.button) { case 1: { if (client) { msg.message = Msg.WM_LBUTTONUP; } else { msg.message = Msg.WM_NCLBUTTONUP; WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y); } msg.wParam = GetMousewParam (0); MouseState &= ~MouseButtons.Left; break; } case 2: { if (client) { msg.message = Msg.WM_MBUTTONUP; } else { msg.message = Msg.WM_NCMBUTTONUP; WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y); } msg.wParam = GetMousewParam (0); MouseState &= ~MouseButtons.Middle; break; } case 3: { if (client) { msg.message = Msg.WM_RBUTTONUP; } else { msg.message = Msg.WM_NCRBUTTONUP; WholeToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y); } msg.wParam = GetMousewParam (0); MouseState &= ~MouseButtons.Right; break; } case 4: { goto ProcessNextMessage; } case 5: { goto ProcessNextMessage; } } if (!hwnd.Enabled) { IntPtr dummy; msg.hwnd = hwnd.EnabledHwnd; XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle (msg.hwnd).ClientWindow, xevent.ButtonEvent.x, xevent.ButtonEvent.y, out xevent.ButtonEvent.x, out xevent.ButtonEvent.y, out dummy); msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X); } if (Grab.Hwnd != IntPtr.Zero) { msg.hwnd = Grab.Hwnd; } msg.lParam = (IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x); MousePosition.X = xevent.ButtonEvent.x; MousePosition.Y = xevent.ButtonEvent.y; break; } case XEventName.MotionNotify: { if (client) { #if DriverDebugExtra Console.WriteLine("GetMessage(): Window {0:X} MotionNotify x={1} y={2}", client ? hwnd.client_window.ToInt32() : hwnd.whole_window.ToInt32(), xevent.MotionEvent.x, xevent.MotionEvent.y); #endif if (Dnd.HandleMotionNotify (ref xevent)) goto ProcessNextMessage; if (Grab.Hwnd != IntPtr.Zero) { msg.hwnd = Grab.Hwnd; } else { NativeWindow.WndProc (msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT); } msg.message = Msg.WM_MOUSEMOVE; msg.wParam = GetMousewParam (0); msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF); if (!hwnd.Enabled) { IntPtr dummy; msg.hwnd = hwnd.EnabledHwnd; XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle (msg.hwnd).ClientWindow, xevent.MotionEvent.x, xevent.MotionEvent.y, out xevent.MotionEvent.x, out xevent.MotionEvent.y, out dummy); msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X); } HoverState.X = MousePosition.X = xevent.MotionEvent.x; HoverState.Y = MousePosition.Y = xevent.MotionEvent.y; break; } else { #if DriverDebugExtra Console.WriteLine("GetMessage(): non-client area {0:X} MotionNotify x={1} y={2}", client ? hwnd.client_window.ToInt32() : hwnd.whole_window.ToInt32(), xevent.MotionEvent.x, xevent.MotionEvent.y); #endif msg.message = Msg.WM_NCMOUSEMOVE; msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF); if (!hwnd.Enabled) { IntPtr dummy; msg.hwnd = hwnd.EnabledHwnd; XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle (msg.hwnd).ClientWindow, xevent.MotionEvent.x, xevent.MotionEvent.y, out xevent.MotionEvent.x, out xevent.MotionEvent.y, out dummy); msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X); } #if notyet // Not sure we need this... HitTest ht; ht = NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCHITTEST, IntPtr.Zero, msg.lParam); #endif MousePosition.X = xevent.MotionEvent.x; MousePosition.Y = xevent.MotionEvent.y; } break; } case XEventName.EnterNotify: { if (!hwnd.Enabled) { goto ProcessNextMessage; } if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) { goto ProcessNextMessage; } msg.message = Msg.WM_MOUSE_ENTER; HoverState.Timer.Enabled = true; HoverState.Window = xevent.CrossingEvent.window; break; } case XEventName.LeaveNotify: { if (!hwnd.Enabled) { goto ProcessNextMessage; } if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) { goto ProcessNextMessage; } msg.message = Msg.WM_MOUSELEAVE; HoverState.Timer.Enabled = false; HoverState.Window = IntPtr.Zero; break; } #if later case XEventName.CreateNotify: { if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { msg.message = WM_CREATE; // Set up CreateStruct } else { goto ProcessNextMessage; } break; } #endif case XEventName.ReparentNotify: { if (hwnd.parent == null) { // Toplevel if (xevent.ReparentEvent.parent != IntPtr.Zero) { // We need to adjust x/y int dummy_int; hwnd.Reparented = true; gdk_window_get_geometry (gdk_window_lookup (hwnd.whole_window), out hwnd.x, out hwnd.y, out dummy_int, out dummy_int, out dummy_int); msg.message = Msg.WM_WINDOWPOSCHANGED; if (hwnd.opacity != 0xffffffff) { uint opacity; opacity = hwnd.opacity; XChangeProperty (DisplayHandle, XGetParent (hwnd.whole_window), NetAtoms [(int)NA._NET_WM_WINDOW_OPACITY], Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1); } } else { hwnd.Reparented = false; goto ProcessNextMessage; } } break; } case XEventName.ConfigureNotify: { if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas XplatUIWin32.NCCALCSIZE_PARAMS ncp; IntPtr ptr; Rectangle rect; #if DriverDebugExtra Console.WriteLine("GetMessage(): Window {0:X} ConfigureNotify x={1} y={2} width={3} height={4}", hwnd.client_window.ToInt32(), xevent.ConfigureEvent.x, xevent.ConfigureEvent.y, xevent.ConfigureEvent.width, xevent.ConfigureEvent.height); #endif msg.message = Msg.WM_WINDOWPOSCHANGED; hwnd.configure_pending = false; // We need to adjust our client window to track the resize of whole_window rect = hwnd.DefaultClientRect; ncp = new XplatUIWin32.NCCALCSIZE_PARAMS (); ptr = Marshal.AllocHGlobal (Marshal.SizeOf (ncp)); ncp.rgrc1.left = rect.Left; ncp.rgrc1.top = rect.Top; ncp.rgrc1.right = rect.Right; ncp.rgrc1.bottom = rect.Bottom; Marshal.StructureToPtr (ncp, ptr, true); NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr); ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS)); Marshal.FreeHGlobal (ptr); // FIXME - debug this with Menus, need to set hwnd.ClientRect rect = new Rectangle (ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top); //Console.WriteLine("CreateOffscreenbuffer..."); // CreateOffscreenBuffer (ref hwnd.client_offscreen, rect.Width, rect.Height); XMoveResizeWindow (DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height); } else { goto ProcessNextMessage; } msg.lParam = IntPtr.Zero; // FIXME - Generate LPWINDOWPOS structure and pass on break; } case XEventName.FocusIn: { if (!hwnd.Enabled) { goto ProcessNextMessage; } msg.message = Msg.WM_SETFOCUS; msg.wParam = IntPtr.Zero; break; } case XEventName.FocusOut: { if (!hwnd.Enabled) { goto ProcessNextMessage; } msg.message = Msg.WM_KILLFOCUS; msg.wParam = IntPtr.Zero; break; } case XEventName.Expose: { if (PostQuitState) { goto ProcessNextMessage; } if (client) { if (!hwnd.expose_pending) { goto ProcessNextMessage; } } else { if (!hwnd.nc_expose_pending) { goto ProcessNextMessage; } switch (hwnd.border_style) { case FormBorderStyle.Fixed3D: { Graphics g; g = Graphics.FromHwnd (hwnd.whole_window); ControlPaint.DrawBorder3D (g, new Rectangle (0, 0, hwnd.Width, hwnd.Height)); g.Dispose (); break; } case FormBorderStyle.FixedSingle: { Graphics g; g = Graphics.FromHwnd (hwnd.whole_window); ControlPaint.DrawBorder (g, new Rectangle (0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid); g.Dispose (); break; } } #if DriverDebugExtra Console.WriteLine("GetMessage(): Window {0:X} Exposed non-client area {1},{2} {3}x{4}", hwnd.client_window.ToInt32(), xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height); #endif Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height); Region region = new Region (rect); IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed msg.message = Msg.WM_NCPAINT; msg.wParam = hrgn; hwnd.nc_expose_pending = false; break; } #if DriverDebugExtra Console.WriteLine("GetMessage(): Window {0:X} Exposed area {1},{2} {3}x{4}", hwnd.client_window.ToInt32(), xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height); #endif if (Caret.Visible == 1) { Caret.Paused = true; HideCaret (); } if (Caret.Visible == 1) { ShowCaret (); Caret.Paused = false; } msg.message = Msg.WM_PAINT; break; } case XEventName.DestroyNotify: { // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children hwnd = Hwnd.ObjectFromHandle (xevent.DestroyWindowEvent.window); // We may get multiple for the same window, act only one the first (when Hwnd still knows about it) if (hwnd.client_window == xevent.DestroyWindowEvent.window) { msg.hwnd = hwnd.client_window; msg.message = Msg.WM_DESTROY; hwnd.Dispose (); #if DriverDebug Console.WriteLine("Got DestroyNotify on Window {0:X}", msg.hwnd.ToInt32()); #endif } else { goto ProcessNextMessage; } break; } case XEventName.ClientMessage: { if (Dnd.HandleClientMessage (ref xevent)) { goto ProcessNextMessage; } if (xevent.ClientMessageEvent.message_type == (IntPtr)AsyncAtom) { XplatUIDriverSupport.ExecuteClientMessage ((GCHandle)xevent.ClientMessageEvent.ptr1); break; } if (xevent.ClientMessageEvent.message_type == (IntPtr)HoverState.Atom) { msg.message = Msg.WM_MOUSEHOVER; msg.wParam = GetMousewParam (0); msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1); break; } if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) { msg.hwnd = xevent.ClientMessageEvent.ptr1; msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 (); msg.wParam = xevent.ClientMessageEvent.ptr3; msg.lParam = xevent.ClientMessageEvent.ptr4; break; } #if dontcare if (xevent.ClientMessageEvent.message_type == (IntPtr)NetAtoms[(int)NA._XEMBED]) { Console.WriteLine("GOT EMBED MESSAGE {0:X}", xevent.ClientMessageEvent.ptr2.ToInt32()); break; } #endif if (xevent.ClientMessageEvent.message_type == (IntPtr)NetAtoms [(int)NA.WM_PROTOCOLS]) { if (xevent.ClientMessageEvent.ptr1 == (IntPtr)NetAtoms [(int)NA.WM_DELETE_WINDOW]) { msg.message = Msg.WM_CLOSE; Graphics.FromHdcInternal (IntPtr.Zero); break; } // We should not get this, but I'll leave the code in case we need it in the future if (xevent.ClientMessageEvent.ptr1 == (IntPtr)NetAtoms [(int)NA.WM_TAKE_FOCUS]) { goto ProcessNextMessage; } } break; } case XEventName.TimerNotify: { xevent.TimerNotifyEvent.handler (this, EventArgs.Empty); break; } default: { goto ProcessNextMessage; } } return true; }
internal void PerformNCCalc(Hwnd hwnd) { XplatUIWin32.NCCALCSIZE_PARAMS ncp; IntPtr ptr; Rectangle rect; rect = new Rectangle (0, 0, hwnd.Width, hwnd.Height); ncp = new XplatUIWin32.NCCALCSIZE_PARAMS(); ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp)); ncp.rgrc1.left = rect.Left; ncp.rgrc1.top = rect.Top; ncp.rgrc1.right = rect.Right; ncp.rgrc1.bottom = rect.Bottom; Marshal.StructureToPtr(ncp, ptr, true); NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr); ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS)); Marshal.FreeHGlobal(ptr); rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top); hwnd.ClientRect = rect; rect = TranslateClientRectangleToQuartzClientRectangle (hwnd); if (hwnd.visible) { Carbon.HIRect r = new Carbon.HIRect (rect.X, rect.Y, rect.Width, rect.Height); HIViewSetFrame (hwnd.client_window, ref r); } AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height); }
public void PerformNCCalc () { XplatUIWin32.NCCALCSIZE_PARAMS ncp; IntPtr ptr; Rectangle rect; rect = DefaultClientRect; ncp = new XplatUIWin32.NCCALCSIZE_PARAMS (); ptr = Marshal.AllocHGlobal (Marshal.SizeOf(ncp)); ncp.rgrc1.left = rect.Left; ncp.rgrc1.top = rect.Top; ncp.rgrc1.right = rect.Right; ncp.rgrc1.bottom = rect.Bottom; Marshal.StructureToPtr (ncp, ptr, true); NativeWindow.WndProc (ClientWindow, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr); ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS)); Marshal.FreeHGlobal(ptr); // FIXME - debug this with Menus rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top); ClientRect = rect; if (Visible) { if ((rect.Width < 1) || (rect.Height < 1)) Xlib.XMoveResizeWindow (display.Handle, ClientWindow, -5, -5, 1, 1); else Xlib.XMoveResizeWindow (display.Handle, ClientWindow, rect.X, rect.Y, rect.Width, rect.Height); } InvalidateNC (); }