private static void RemovePendingMessages(int msgMin, int msgMax) { if (!control.IsDisposed) { MSG msg = new MSG(); IntPtr handle = control.Handle; while (PeekMessage(ref msg, new HandleRef(control, handle), msgMin, msgMax, 1)) { } } }
internal extern static IntPtr Win32DispatchMessage(ref MSG msg);
internal extern static bool Win32GetMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax);
internal override IntPtr DispatchMessage(ref MSG msg) { return Win32DispatchMessage(ref msg); }
private bool GetMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, bool blocking) { bool result; msg.refobject = 0; if (RetrieveMessage(ref msg)) { return true; } if (blocking) { result = Win32GetMessage(ref msg, hWnd, wFilterMin, wFilterMax); } else { result = Win32PeekMessage(ref msg, hWnd, wFilterMin, wFilterMax, (uint)PeekMessageFlags.PM_REMOVE); if (!result) { return false; } } // We need to fake WM_MOUSE_ENTER switch (msg.message) { case Msg.WM_LBUTTONDOWN: { mouse_state |= MouseButtons.Left; break; } case Msg.WM_MBUTTONDOWN: { mouse_state |= MouseButtons.Middle; break; } case Msg.WM_RBUTTONDOWN: { mouse_state |= MouseButtons.Right; break; } case Msg.WM_LBUTTONUP: { mouse_state &= ~MouseButtons.Left; break; } case Msg.WM_MBUTTONUP: { mouse_state &= ~MouseButtons.Middle; break; } case Msg.WM_RBUTTONUP: { mouse_state &= ~MouseButtons.Right; break; } case Msg.WM_ASYNC_MESSAGE: { XplatUIDriverSupport.ExecuteClientMessage((GCHandle)msg.lParam); break; } case Msg.WM_MOUSEMOVE: { if (msg.hwnd != prev_mouse_hwnd) { TRACKMOUSEEVENT tme; mouse_state = Control.FromParamToMouseButtons ((int)msg.lParam.ToInt32()); // The current message will be sent out next time around StoreMessage(ref msg); // This is the message we want to send at this point msg.message = Msg.WM_MOUSE_ENTER; prev_mouse_hwnd = msg.hwnd; tme = new TRACKMOUSEEVENT(); tme.size = Marshal.SizeOf(tme); tme.hWnd = msg.hwnd; tme.dwFlags = TMEFlags.TME_LEAVE | TMEFlags.TME_HOVER; Win32TrackMouseEvent(ref tme); return result; } break; } case Msg.WM_NCMOUSEMOVE: { if (wm_nc_registered == null || !wm_nc_registered.Contains (msg.hwnd)) break; mouse_state = Control.FromParamToMouseButtons ((int)msg.lParam.ToInt32 ()); TRACKMOUSEEVENT tme; tme = new TRACKMOUSEEVENT (); tme.size = Marshal.SizeOf(tme); tme.hWnd = msg.hwnd; tme.dwFlags = (TMEFlags)wm_nc_registered[msg.hwnd]; Win32TrackMouseEvent (ref tme); return result; } case Msg.WM_DROPFILES: { return Win32DnD.HandleWMDropFiles(ref msg); } case Msg.WM_MOUSELEAVE: { prev_mouse_hwnd = IntPtr.Zero; break; } case Msg.WM_TIMER: { Timer timer=(Timer)timer_list[(int)msg.wParam]; if (timer != null) { timer.FireTick(); } break; } } return result; }
internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) { return Win32PeekMessage(ref msg, hWnd, wFilterMin, wFilterMax, flags); }
/// <summary> /// Send key commands to text view if it has focus /// </summary> /// <param name="msg"></param> /// <returns></returns> public int TranslateAccelerator(MSG[] messagesToTranslate) { int hr = VSConstants.S_FALSE; if (messagesToTranslate == null) { return hr; } // defer to active code window if (activeTextView != null) { IVsWindowPane vsWindowPane = (IVsWindowPane) activeTextView; hr = vsWindowPane.TranslateAccelerator(messagesToTranslate); } else { switch (messagesToTranslate[0].message) { case NativeMethods.WM_KEYDOWN: case NativeMethods.WM_SYSKEYDOWN: case NativeMethods.WM_CHAR: case NativeMethods.WM_SYSCHAR: { Message msg = new Message(); msg.HWnd = messagesToTranslate[0].hwnd; msg.Msg = (int) messagesToTranslate[0].message; msg.LParam = messagesToTranslate[0].lParam; msg.WParam = messagesToTranslate[0].wParam; Control ctrl = FromChildHandle(msg.HWnd); if (ctrl != null && ctrl.PreProcessMessage(ref msg)) hr = VSConstants.S_OK; } break; default: break; } } return hr; }
internal abstract bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags);
internal static void RunLoop(bool Modal, ApplicationContext context) { Queue toplevels; MSG msg; Object queue_id; MWFThread thread; ApplicationContext previous_thread_context; thread = MWFThread.Current; /* * There is a NotWorking test for this, but since we are using this method both for Form.ShowDialog as for ApplicationContexts we'll * fail on nested ShowDialogs, so disable the check for the moment. */ //if (thread.MessageLoop) { // throw new InvalidOperationException ("Starting a second message loop on a single thread is not a valid operation. Use Form.ShowDialog instead."); //} msg = new MSG(); if (context == null) { context = new ApplicationContext(); } previous_thread_context = thread.Context; thread.Context = context; if (context.MainForm != null) { context.MainForm.is_modal = Modal; context.MainForm.context = context; context.MainForm.closing = false; context.MainForm.Visible = true; // Cannot use Show() or scaling gets confused by menus // XXX the above line can be used to close the form. another problem with our handling of Show/Activate. if (context.MainForm != null) { context.MainForm.Activate(); } } #if DebugRunLoop Console.WriteLine("Entering RunLoop(Modal={0}, Form={1})", Modal, context.MainForm != null ? context.MainForm.ToString() : "NULL"); #endif if (Modal) { toplevels = new Queue(); DisableFormsForModalLoop(toplevels, context); // FIXME - need activate? /* make sure the MainForm is enabled */ if (context.MainForm != null) { XplatUI.EnableWindow(context.MainForm.Handle, true); XplatUI.SetModal(context.MainForm.Handle, true); } } else { toplevels = null; } queue_id = XplatUI.StartLoop(Thread.CurrentThread); thread.MessageLoop = true; bool quit = false; while (!quit && XplatUI.GetMessage(queue_id, ref msg, IntPtr.Zero, 0, 0)) { Message m = Message.Create(msg.hwnd, (int)msg.message, msg.wParam, msg.lParam); if (Application.FilterMessage(ref m)) { continue; } switch ((Msg)msg.message) { case Msg.WM_KEYDOWN: case Msg.WM_SYSKEYDOWN: case Msg.WM_CHAR: case Msg.WM_SYSCHAR: case Msg.WM_KEYUP: case Msg.WM_SYSKEYUP: Control c; c = Control.FromHandle(msg.hwnd); // If we have a control with keyboard capture (usually a *Strip) // give it the message, and then drop the message if (keyboard_capture != null) { // WM_SYSKEYUP does not make it into ProcessCmdKey, so do it here if ((Msg)m.Msg == Msg.WM_SYSKEYDOWN) { if (m.WParam.ToInt32() == (int)Keys.Menu) { keyboard_capture.GetTopLevelToolStrip().Dismiss(ToolStripDropDownCloseReason.Keyboard); continue; } } m.HWnd = keyboard_capture.Handle; switch (keyboard_capture.PreProcessControlMessageInternal(ref m)) { case PreProcessControlState.MessageProcessed: continue; case PreProcessControlState.MessageNeeded: case PreProcessControlState.MessageNotNeeded: if (((m.Msg == (int)Msg.WM_KEYDOWN || m.Msg == (int)Msg.WM_CHAR) && !keyboard_capture.ProcessControlMnemonic((char)m.WParam))) { if (c == null || !ControlOnToolStrip(c)) { continue; } else { m.HWnd = msg.hwnd; } } else { continue; } break; } } if (((c != null) && c.PreProcessControlMessageInternal(ref m) != PreProcessControlState.MessageProcessed) || (c == null)) { goto default; } break; case Msg.WM_LBUTTONDOWN: case Msg.WM_MBUTTONDOWN: case Msg.WM_RBUTTONDOWN: if (keyboard_capture != null) { Control c2 = Control.FromHandle(msg.hwnd); // The target is not a winforms control (an embedded control, perhaps), so // release everything if (c2 == null) { ToolStripManager.FireAppClicked(); goto default; } // Skip clicks on owner windows, eg. expanded ComboBox if (Control.IsChild(keyboard_capture.Handle, msg.hwnd)) { goto default; } // Close any active toolstrips drop-downs if we click outside of them, // but also don't close them all if we click outside of the top-most // one, but into its owner. Point c2_point = c2.PointToScreen(new Point( (int)(short)(m.LParam.ToInt32() & 0xffff), (int)(short)(m.LParam.ToInt32() >> 16))); while (keyboard_capture != null && !keyboard_capture.ClientRectangle.Contains(keyboard_capture.PointToClient(c2_point))) { keyboard_capture.Dismiss(); } } goto default; case Msg.WM_QUIT: quit = true; // make sure we exit break; default: XplatUI.TranslateMessage(ref msg); XplatUI.DispatchMessage(ref msg); break; } // If our Form doesn't have a handle anymore, it means it was destroyed and we need to *wait* for WM_QUIT. if ((context.MainForm != null) && (!context.MainForm.IsHandleCreated)) { continue; } // Handle exit, Form might have received WM_CLOSE and set 'closing' in response. if ((context.MainForm != null) && (context.MainForm.closing || (Modal && !context.MainForm.Visible))) { if (!Modal) { XplatUI.PostQuitMessage(0); } else { break; } } } #if DebugRunLoop Console.WriteLine(" RunLoop loop left"); #endif thread.MessageLoop = false; XplatUI.EndLoop(Thread.CurrentThread); if (Modal) { Form old = context.MainForm; context.MainForm = null; EnableFormsForModalLoop(toplevels, context); if (old != null && old.IsHandleCreated) { XplatUI.SetModal(old.Handle, false); } #if DebugRunLoop Console.WriteLine(" Done with the SetModal"); #endif old.RaiseCloseEvents(true, false); old.is_modal = false; } #if DebugRunLoop Console.WriteLine("Leaving RunLoop(Modal={0}, Form={1})", Modal, context.MainForm != null ? context.MainForm.ToString() : "NULL"); #endif if (context.MainForm != null) { context.MainForm.context = null; context.MainForm = null; } thread.Context = previous_thread_context; if (!Modal) { thread.Exit(); } }
static public bool TrackPopupMenu(Menu menu, Point pnt) { if (menu.MenuItems.Count <= 0) // No submenus to track { return(true); } MenuTracker tracker = menu.tracker; tracker.active = true; tracker.popup_active = true; // Set GrabControl Control src_ctrl = (tracker.TopMenu as ContextMenu).SourceControl; tracker.GrabControl = src_ctrl.FindForm(); if (tracker.GrabControl == null) { tracker.GrabControl = src_ctrl.FindRootParent(); } tracker.GrabControl.ActiveTracker = tracker; menu.Wnd = new PopUpWindow(tracker.GrabControl, menu); menu.Wnd.Location = menu.Wnd.PointToClient(pnt); ((PopUpWindow)menu.Wnd).ShowWindow(); bool no_quit = true; Object queue_id = XplatUI.StartLoop(Thread.CurrentThread); while ((menu.Wnd != null) && menu.Wnd.Visible && no_quit) { MSG msg = new MSG(); no_quit = XplatUI.GetMessage(queue_id, ref msg, IntPtr.Zero, 0, 0); switch ((Msg)msg.message) { case Msg.WM_KEYDOWN: case Msg.WM_SYSKEYDOWN: case Msg.WM_CHAR: case Msg.WM_SYSCHAR: case Msg.WM_KEYUP: case Msg.WM_SYSKEYUP: Control c = Control.FromHandle(msg.hwnd); if (c != null) { Message m = Message.Create(msg.hwnd, (int)msg.message, msg.wParam, msg.lParam); c.PreProcessControlMessageInternal(ref m); } break; default: XplatUI.TranslateMessage(ref msg); XplatUI.DispatchMessage(ref msg); break; } } if (tracker.GrabControl.IsDisposed) { return(true); } if (!no_quit) { XplatUI.PostQuitMessage(0); } if (menu.Wnd != null) { menu.Wnd.Dispose(); menu.Wnd = null; } return(true); }
internal static bool PostMessage(ref MSG msg) { DriverDebug("PostMessage ({0}): Called", msg); return(driver.PostMessage(msg.hwnd, msg.message, msg.wParam, msg.lParam)); }
internal static bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) { return(driver.PeekMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax, flags)); }
internal static bool GetMessage(object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax) { return(driver.GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax)); }
private static bool StoreMessage(ref MSG msg) { MSG message = new MSG(); message = msg; message_queue.Enqueue(message); return true; }
internal abstract bool GetMessage(object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax);
static extern bool PeekMessage(ref MSG msg, IntPtr hWnd, int messageFilterMin, int messageFilterMax, int flags);
internal abstract bool TranslateMessage(ref MSG msg);
/// <summary> /// Gives the component a chance to process the message before it is translated and dispatched. /// </summary> /// <param name="pMsg">The message to process.</param> /// <returns>TRUE (not zero) if the message is consumed, otherwise FALSE (zero).</returns> /// <remarks> /// The component can do TranslateAccelerator, do IsDialogMessage, modify pMsg, or take some other action. /// </remarks> public int FPreTranslateMessage(MSG[] pMsg) { return 0; }
internal abstract IntPtr DispatchMessage(ref MSG msg);
internal static IntPtr DispatchMessage(ref MSG msg) { return(driver.DispatchMessage(ref msg)); }
// ---------------------------------------------------------------------------------- /// <summary> /// Allow the embedded editor to handle keyboard messages before they are dispatched /// to the window that has the focus. /// </summary> // ---------------------------------------------------------------------------------- protected override bool PreProcessMessage(ref Message m) { if (_surface != null && _surface._ViewAdapter != null) { // copy the Message into a MSG[] array, so we can pass // it along to the active core editor's IVsWindowPane.TranslateAccelerator var pMsg = new MSG[1]; pMsg[0].hwnd = m.HWnd; pMsg[0].message = (uint)m.Msg; pMsg[0].wParam = m.WParam; pMsg[0].lParam = m.LParam; var vsWindowPane = (IVsWindowPane)_surface._ViewAdapter; return vsWindowPane.TranslateAccelerator(pMsg) == 0; } return base.PreProcessMessage(ref m); }
internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax) { return GetMessage(ref msg, hWnd, wFilterMin, wFilterMax, true); }
public DragDropEffects StartDrag (IntPtr handle, object data, DragDropEffects allowed_effects) { drag_data = new DragData (); drag_data.Window = handle; drag_data.State = DragState.Beginning; drag_data.MouseState = XplatUIX11.MouseState; drag_data.Data = data; drag_data.SupportedTypes = DetermineSupportedTypes (data); drag_data.AllowedEffects = allowed_effects; drag_data.Action = ActionFromEffect (allowed_effects); if (CursorNo == null) { // Make sure the cursors are created CursorNo = new Cursor (typeof (X11Dnd), "DnDNo.cur"); CursorCopy = new Cursor (typeof (X11Dnd), "DnDCopy.cur"); CursorMove = new Cursor (typeof (X11Dnd), "DnDMove.cur"); CursorLink = new Cursor (typeof (X11Dnd), "DnDLink.cur"); } drag_data.LastTopLevel = IntPtr.Zero; control = null; System.Windows.Forms.MSG msg = new MSG(); object queue_id = XplatUI.StartLoop (Thread.CurrentThread); Timer timer = new Timer (); timer.Tick += new EventHandler (DndTickHandler); timer.Interval = 100; int suc; drag_data.State = DragState.Dragging; suc = XplatUIX11.XSetSelectionOwner (display, XdndSelection, drag_data.Window, IntPtr.Zero); if (suc == 0) { Console.Error.WriteLine ("Could not take ownership of XdndSelection aborting drag."); drag_data.Reset (); return DragDropEffects.None; } drag_data.State = DragState.Dragging; drag_data.CurMousePos = new Point (); source = toplevel = target = IntPtr.Zero; dropped = false; tracking = true; motion_poll = -1; timer.Start (); // Send Enter to the window initializing the dnd operation - which initializes the data SendEnter (drag_data.Window, drag_data.Window, drag_data.SupportedTypes); drag_data.LastTopLevel = toplevel; while (tracking && XplatUI.GetMessage (queue_id, ref msg, IntPtr.Zero, 0, 0)) { if (msg.message >= Msg.WM_KEYFIRST && msg.message <= Msg.WM_KEYLAST) { HandleKeyMessage (msg); } else { switch (msg.message) { case Msg.WM_LBUTTONUP: case Msg.WM_RBUTTONUP: case Msg.WM_MBUTTONUP: if (msg.message == Msg.WM_LBUTTONDOWN && drag_data.MouseState != MouseButtons.Left) break;; if (msg.message == Msg.WM_RBUTTONDOWN && drag_data.MouseState != MouseButtons.Right) break; if (msg.message == Msg.WM_MBUTTONDOWN && drag_data.MouseState != MouseButtons.Middle) break; HandleButtonUpMsg (); // We don't want to dispatch button up neither (Match .Net) // Thus we have to remove capture by ourselves RemoveCapture (msg.hwnd); continue; case Msg.WM_MOUSEMOVE: motion_poll = 0; drag_data.CurMousePos.X = Control.LowOrder ((int) msg.lParam.ToInt32 ()); drag_data.CurMousePos.Y = Control.HighOrder ((int) msg.lParam.ToInt32 ()); HandleMouseOver (); // We don't want to dispatch mouse move continue; } XplatUI.DispatchMessage (ref msg); } } timer.Stop (); // If the target is a mwf control, return until DragEnter/DragLeave has been fired, // which means the respective -already sent- dnd ClientMessages have been received and handled. if (control != null) Application.DoEvents (); if (!dropped) return DragDropEffects.None; if (drag_event != null) return drag_event.Effect; // Fallback. return DragDropEffects.None; }
internal override bool TranslateMessage(ref MSG msg) { return Win32TranslateMessage(ref msg); }
public void HandleKeyMessage (MSG msg) { if (VirtualKeys.VK_ESCAPE == (VirtualKeys) msg.wParam.ToInt32()) { QueryContinue (true, DragAction.Cancel); } }
internal extern static bool Win32PeekMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags);
void WaitForHwndMessage (Hwnd hwnd, Msg message, bool process) { MSG msg = new MSG (); XEventQueue queue; queue = ThreadQueue(Thread.CurrentThread); queue.DispatchIdle = false; bool done = false; string key = hwnd.Handle + ":" + message; if (!messageHold.ContainsKey (key)) messageHold.Add (key, 1); else messageHold[key] = ((int)messageHold[key]) + 1; do { DebugHelper.WriteLine ("Waiting for message " + message + " on hwnd " + String.Format("0x{0:x}", hwnd.Handle.ToInt32 ())); DebugHelper.Indent (); if (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) { if ((Msg)msg.message == Msg.WM_QUIT) { PostQuitMessage (0); done = true; } else { DebugHelper.WriteLine ("PeekMessage got " + msg); if (msg.hwnd == hwnd.Handle) { if ((Msg)msg.message == message) { if (process) { TranslateMessage (ref msg); DispatchMessage (ref msg); } break; } else if ((Msg)msg.message == Msg.WM_DESTROY) done = true; } TranslateMessage (ref msg); DispatchMessage (ref msg); } } done = !messageHold.ContainsKey (key) || ((int)messageHold[key] < 1) || done; } while (!done); messageHold.Remove (key); DebugHelper.Unindent (); DebugHelper.WriteLine ("Finished waiting for " + key); queue.DispatchIdle = true; }
internal extern static bool Win32TranslateMessage(ref MSG msg);
internal override IntPtr DispatchMessage(ref MSG msg) { return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam); }
private static bool RetrieveMessage(ref MSG msg) { MSG message; if (message_queue.Count == 0) { return false; } message = (MSG)message_queue.Dequeue(); msg = message; return true; }
internal override void DoEvents() { DebugHelper.Enter (); MSG msg = new MSG (); XEventQueue queue; if (OverrideCursorHandle != IntPtr.Zero) { OverrideCursorHandle = IntPtr.Zero; } queue = ThreadQueue(Thread.CurrentThread); queue.DispatchIdle = false; in_doevents = true; while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) { Message m = Message.Create (msg.hwnd, (int)msg.message, msg.wParam, msg.lParam); if (Application.FilterMessage (ref m)) continue; TranslateMessage (ref msg); DispatchMessage (ref msg); string key = msg.hwnd + ":" + msg.message; if (messageHold[key] != null) { messageHold[key] = ((int)messageHold[key]) - 1; DebugHelper.WriteLine ("Got " + msg + " for " + key); } } in_doevents = false; queue.DispatchIdle = true; DebugHelper.Leave (); }
public virtual int TranslateAccelerator(MSG[] arrMsg) { MSG msg = arrMsg[0]; if ((msg.message < NativeMethods.WM_KEYFIRST || msg.message > NativeMethods.WM_KEYLAST) && (msg.message < NativeMethods.WM_MOUSEFIRST || msg.message > NativeMethods.WM_MOUSELAST)) return 1; return (NativeMethods.IsDialogMessageA(this.panel.Handle, ref msg)) ? 0 : 1; }
internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) { XEvent xevent; bool client; Hwnd hwnd; ProcessNextMessage: if (((XEventQueue)queue_id).Count > 0) { xevent = (XEvent) ((XEventQueue)queue_id).Dequeue (); } else { UpdateMessageQueue ((XEventQueue)queue_id); if (((XEventQueue)queue_id).Count > 0) { xevent = (XEvent) ((XEventQueue)queue_id).Dequeue (); } else if (((XEventQueue)queue_id).Paint.Count > 0) { xevent = ((XEventQueue)queue_id).Paint.Dequeue(); } else { msg.hwnd= IntPtr.Zero; msg.message = Msg.WM_ENTERIDLE; return true; } } hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window); #if DriverDebugDestroy if (hwnd != null) if (hwnd.zombie) Console.WriteLine ( "GetMessage zombie, got Event: " + xevent.ToString () + " for 0x{0:x}", hwnd.Handle.ToInt32()); else Console.WriteLine ( "GetMessage, got Event: " + xevent.ToString () + " for 0x{0:x}", hwnd.Handle.ToInt32()); #endif // Handle messages for windows that are already or are about to be destroyed. // we need a special block for this because unless we remove the hwnd from the paint // queue it will always stay there (since we don't handle the expose), and we'll // effectively loop infinitely trying to repaint a non-existant window. if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) { hwnd.expose_pending = hwnd.nc_expose_pending = false; hwnd.Queue.Paint.Remove (hwnd); goto ProcessNextMessage; } // We need to make sure we only allow DestroyNotify events through for zombie // hwnds, since much of the event handling code makes requests using the hwnd's // client_window, and that'll result in BadWindow errors if there's some lag // between the XDestroyWindow call and the DestroyNotify event. if (hwnd == null || hwnd.zombie && xevent.AnyEvent.type != XEventName.ClientMessage) { DriverDebug("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32()); goto ProcessNextMessage; } // If we get here, that means the window is no more but there are Client Messages // to be processed, probably a Posted message (for instance, an WM_ACTIVATE message) // We don't want anything else to run but the ClientMessage block, so reset all hwnd // properties that might cause other processing to occur. if (hwnd.zombie) { hwnd.resizing_or_moving = false; } if (hwnd.client_window == xevent.AnyEvent.window) { client = true; //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type); } else { client = false; //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32()); } msg.hwnd = hwnd.Handle; // Windows sends WM_ENTERSIZEMOVE when a form resize/move operation starts and WM_EXITSIZEMOVE // when it is done. The problem in X11 is that there is no concept of start-end of a moving/sizing. // Configure events ("this window has resized/moved") are sent for each step of the resize. We send a // WM_ENTERSIZEMOVE when we get the first Configure event. The problem is the WM_EXITSIZEMOVE. // // - There is no way for us to know which is the last Configure event. We can't traverse the events // queue, because the next configure event might not be pending yet. // - We can't get ButtonPress/Release events for the window decorations, because they are not part // of the window(s) we manage. // - We can't rely on the mouse state to change to "up" before the last Configure event. It doesn't. // // We are almost 100% guaranteed to get another event (e.g Expose or other), but we can't know for sure // which, so we have here to check if the mouse buttons state is "up" and send the WM_EXITSIZEMOVE // if (hwnd.resizing_or_moving) { int root_x, root_y, win_x, win_y, keys_buttons; IntPtr root, child; XQueryPointer (DisplayHandle, hwnd.Handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons); if ((keys_buttons & (int)MouseKeyMasks.Button1Mask) == 0 && (keys_buttons & (int)MouseKeyMasks.Button2Mask) == 0 && (keys_buttons & (int)MouseKeyMasks.Button3Mask) == 0) { hwnd.resizing_or_moving = false; SendMessage (hwnd.Handle, Msg.WM_EXITSIZEMOVE, IntPtr.Zero, IntPtr.Zero); } } // // 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); // F1 key special case - WM_HELP sending if (msg.wParam == (IntPtr)VirtualKeys.VK_F1 || msg.wParam == (IntPtr)VirtualKeys.VK_HELP) { // Send wM_HELP and then return it as a keypress message in // case it needs to be preproccessed. HELPINFO helpInfo = new HELPINFO (); GetCursorPos (IntPtr.Zero, out helpInfo.MousePos.x, out helpInfo.MousePos.y); IntPtr helpInfoPtr = Marshal.AllocHGlobal (Marshal.SizeOf (helpInfo)); Marshal.StructureToPtr (helpInfo, helpInfoPtr, true); NativeWindow.WndProc (FocusWindow, Msg.WM_HELP, IntPtr.Zero, helpInfoPtr); Marshal.FreeHGlobal (helpInfoPtr); } 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; msg.wParam = GetMousewParam (0); } else { msg.message = Msg.WM_NCLBUTTONDOWN; msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y); MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y); } break; } case 2: { MouseState |= MouseButtons.Middle; if (client) { msg.message = Msg.WM_MBUTTONDOWN; msg.wParam = GetMousewParam (0); } else { msg.message = Msg.WM_NCMBUTTONDOWN; msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y); MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y); } break; } case 3: { MouseState |= MouseButtons.Right; if (client) { msg.message = Msg.WM_RBUTTONDOWN; msg.wParam = GetMousewParam (0); } else { msg.message = Msg.WM_NCRBUTTONDOWN; msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y); MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y); } break; } case 4: { msg.hwnd = FocusWindow; msg.message=Msg.WM_MOUSEWHEEL; msg.wParam=GetMousewParam(120); break; } case 5: { msg.hwnd = FocusWindow; msg.message=Msg.WM_MOUSEWHEEL; msg.wParam=GetMousewParam(-120); break; } } msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x); mouse_position.X = xevent.ButtonEvent.x; mouse_position.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)(mouse_position.Y << 16 | mouse_position.X); } if (Grab.Hwnd != IntPtr.Zero) { msg.hwnd = Grab.Hwnd; } if (ClickPending.Pending && ((((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; } else { 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; } if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) { SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y); } break; } case XEventName.ButtonRelease: { switch(xevent.ButtonEvent.button) { case 1: { if (client) { msg.message = Msg.WM_LBUTTONUP; } else { msg.message = Msg.WM_NCLBUTTONUP; msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y); MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y); } MouseState &= ~MouseButtons.Left; msg.wParam = GetMousewParam (0); break; } case 2: { if (client) { msg.message = Msg.WM_MBUTTONUP; } else { msg.message = Msg.WM_NCMBUTTONUP; msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y); MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y); } MouseState &= ~MouseButtons.Middle; msg.wParam = GetMousewParam (0); break; } case 3: { if (client) { msg.message = Msg.WM_RBUTTONUP; } else { msg.message = Msg.WM_NCRBUTTONUP; msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y); MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y); } MouseState &= ~MouseButtons.Right; msg.wParam = GetMousewParam (0); 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)(mouse_position.Y << 16 | mouse_position.X); } if (Grab.Hwnd != IntPtr.Zero) { msg.hwnd = Grab.Hwnd; } msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x); mouse_position.X = xevent.ButtonEvent.x; mouse_position.Y = xevent.ButtonEvent.y; // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh* if (msg.message == Msg.WM_LBUTTONUP || msg.message == Msg.WM_MBUTTONUP || msg.message == Msg.WM_RBUTTONUP) { XEvent motionEvent = new XEvent (); motionEvent.type = XEventName.MotionNotify; motionEvent.MotionEvent.display = DisplayHandle; motionEvent.MotionEvent.window = xevent.ButtonEvent.window; motionEvent.MotionEvent.x = xevent.ButtonEvent.x; motionEvent.MotionEvent.y = xevent.ButtonEvent.y; hwnd.Queue.EnqueueLocked (motionEvent); } break; } case XEventName.MotionNotify: { if (client) { DriverDebug("GetMessage(): Window {0:X} MotionNotify x={1} y={2}", client ? hwnd.client_window.ToInt32() : hwnd.whole_window.ToInt32(), xevent.MotionEvent.x, xevent.MotionEvent.y); if (Grab.Hwnd != IntPtr.Zero) { msg.hwnd = Grab.Hwnd; } else { if (hwnd.Enabled) { NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT); } } if (xevent.MotionEvent.is_hint != 0) { IntPtr root, child; int mask; XQueryPointer (DisplayHandle, xevent.AnyEvent.window, out root, out child, out xevent.MotionEvent.x_root, out xevent.MotionEvent.y_root, out xevent.MotionEvent.x, out xevent.MotionEvent.y, out mask); } 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)(mouse_position.Y << 16 | mouse_position.X); } mouse_position.X = xevent.MotionEvent.x; mouse_position.Y = xevent.MotionEvent.y; if ((HoverState.Timer.Enabled) && (((mouse_position.X + HoverState.Size.Width) < HoverState.X) || ((mouse_position.X - HoverState.Size.Width) > HoverState.X) || ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) || ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) { HoverState.Timer.Stop(); HoverState.Timer.Start(); HoverState.X = mouse_position.X; HoverState.Y = mouse_position.Y; } break; } else { HitTest ht; IntPtr dummy; DriverDebug("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); msg.message = Msg.WM_NCMOUSEMOVE; if (!hwnd.Enabled) { 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)(mouse_position.Y << 16 | mouse_position.X); } ht = NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y); NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht); mouse_position.X = xevent.MotionEvent.x; mouse_position.Y = xevent.MotionEvent.y; } break; } case XEventName.EnterNotify: { if (!hwnd.Enabled) { goto ProcessNextMessage; } if (xevent.CrossingEvent.mode == NotifyMode.NotifyGrab || xevent.AnyEvent.window != hwnd.client_window) { goto ProcessNextMessage; } if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) { // Pseudo motion caused by grabbing if (LastPointerWindow == xevent.AnyEvent.window) goto ProcessNextMessage; if (LastPointerWindow != IntPtr.Zero) { Point enter_loc = new Point (xevent.ButtonEvent.x, xevent.ButtonEvent.y); // We need this due to EnterNotify being fired on all the parent controls // of the Control being grabbed, and obviously in that scenario we are not // actuallty entering them Control ctrl = Control.FromHandle (hwnd.client_window); foreach (Control child_control in ctrl.Controls.GetAllControls ()) if (child_control.Bounds.Contains (enter_loc)) goto ProcessNextMessage; // A MouseLeave/LeaveNotify event is sent to the previous window // until the mouse is ungrabbed, not when actually leaving its bounds int x = xevent.CrossingEvent.x_root; int y = xevent.CrossingEvent.y_root; ScreenToClient (LastPointerWindow, ref x, ref y); XEvent leaveEvent = new XEvent (); leaveEvent.type = XEventName.LeaveNotify; leaveEvent.CrossingEvent.display = DisplayHandle; leaveEvent.CrossingEvent.window = LastPointerWindow; leaveEvent.CrossingEvent.x = x; leaveEvent.CrossingEvent.y = y; leaveEvent.CrossingEvent.mode = NotifyMode.NotifyNormal; Hwnd last_pointer_hwnd = Hwnd.ObjectFromHandle (LastPointerWindow); last_pointer_hwnd.Queue.EnqueueLocked (leaveEvent); } } LastPointerWindow = xevent.AnyEvent.window; msg.message = Msg.WM_MOUSE_ENTER; HoverState.X = xevent.CrossingEvent.x; HoverState.Y = xevent.CrossingEvent.y; HoverState.Timer.Enabled = true; HoverState.Window = xevent.CrossingEvent.window; // Win32 sends a WM_MOUSEMOVE after mouse enter XEvent motionEvent = new XEvent (); motionEvent.type = XEventName.MotionNotify; motionEvent.MotionEvent.display = DisplayHandle; motionEvent.MotionEvent.window = xevent.ButtonEvent.window; motionEvent.MotionEvent.x = xevent.ButtonEvent.x; motionEvent.MotionEvent.y = xevent.ButtonEvent.y; hwnd.Queue.EnqueueLocked (motionEvent); break; } case XEventName.LeaveNotify: { if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) { WindowUngrabbed (hwnd.Handle); goto ProcessNextMessage; } if (!hwnd.Enabled) { goto ProcessNextMessage; } if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) { goto ProcessNextMessage; } // If a grab is taking place, ignore it - we handle it in EnterNotify if (Grab.Hwnd != IntPtr.Zero) goto ProcessNextMessage; // Reset the cursor explicitly on X11. // X11 remembers the last set cursor for the window and in cases where // the control won't get a WM_SETCURSOR X11 will restore the last // known cursor, which we don't want. // SetCursor (hwnd.client_window, IntPtr.Zero); 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) && (xevent.ReparentEvent.window == hwnd.whole_window)) { hwnd.Reparented = true; // The location given by the event is not reliable between different wm's, // so use an alternative way of getting it. Point location = GetTopLevelWindowLocation (hwnd); hwnd.X = location.X; hwnd.Y = location.Y; if (hwnd.opacity != 0xffffffff) { IntPtr opacity; opacity = (IntPtr)(Int32)hwnd.opacity; XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1); } SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam); goto ProcessNextMessage; } else { hwnd.Reparented = false; goto ProcessNextMessage; } } goto ProcessNextMessage; } case XEventName.ConfigureNotify: { if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas DriverDebug("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); lock (hwnd.configure_lock) { Form form = Control.FromHandle (hwnd.client_window) as Form; if (form != null && !hwnd.resizing_or_moving) { if (hwnd.x != form.Bounds.X || hwnd.y != form.Bounds.Y) { SendMessage (form.Handle, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_MOVE, IntPtr.Zero); hwnd.resizing_or_moving = true; } else if (hwnd.width != form.Bounds.Width || hwnd.height != form.Bounds.Height) { SendMessage (form.Handle, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_SIZE, IntPtr.Zero); hwnd.resizing_or_moving = true; } if (hwnd.resizing_or_moving) SendMessage (form.Handle, Msg.WM_ENTERSIZEMOVE, IntPtr.Zero, IntPtr.Zero); } SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero); hwnd.configure_pending = false; // We need to adjust our client window to track the resize of whole_window if (hwnd.whole_window != hwnd.client_window) PerformNCCalc(hwnd); } } goto ProcessNextMessage; } case XEventName.FocusIn: { // We received focus. We use X11 focus only to know if the app window does or does not have focus // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know // about it having focus again if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) { goto ProcessNextMessage; } if (FocusWindow == IntPtr.Zero) { Control c = Control.FromHandle (hwnd.client_window); if (c == null) goto ProcessNextMessage; Form form = c.FindForm (); if (form == null) goto ProcessNextMessage; if (ActiveWindow != form.Handle) { ActiveWindow = form.Handle; SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero); } goto ProcessNextMessage; } Keyboard.FocusIn (FocusWindow); SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero); goto ProcessNextMessage; } case XEventName.FocusOut: { // Se the comment for our FocusIn handler if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) { goto ProcessNextMessage; } while (Keyboard.ResetKeyState(FocusWindow, ref msg)) { SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam); } Keyboard.FocusOut(hwnd.client_window); SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero); goto ProcessNextMessage; } // We are already firing WM_SHOWWINDOW messages in the proper places, but I'm leaving this code // in case we break a scenario not taken into account in the tests case XEventName.MapNotify: { /*if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas hwnd.mapped = true; msg.message = Msg.WM_SHOWWINDOW; msg.wParam = (IntPtr) 1; // XXX we're missing the lParam.. break; }*/ goto ProcessNextMessage; } case XEventName.UnmapNotify: { /*if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas hwnd.mapped = false; msg.message = Msg.WM_SHOWWINDOW; msg.wParam = (IntPtr) 0; // XXX we're missing the lParam.. break; }*/ goto ProcessNextMessage; } case XEventName.Expose: { if (!hwnd.Mapped) { if (client) { hwnd.expose_pending = false; } else { hwnd.nc_expose_pending = false; } 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); if (hwnd.border_static) ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter); else ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken); 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; } } DriverDebug("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); 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 == IntPtr.Zero ? (IntPtr)1 : hrgn; msg.refobject = region; break; } DriverDebug("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); if (Caret.Visible == true) { Caret.Paused = true; HideCaret(); } if (Caret.Visible == true) { 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 != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) { CleanupCachedWindows (hwnd); DriverDebug("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window)); msg.hwnd = hwnd.client_window; msg.message=Msg.WM_DESTROY; hwnd.Dispose(); } else { goto ProcessNextMessage; } break; } case XEventName.ClientMessage: { if (Dnd.HandleClientMessage (ref xevent)) { goto ProcessNextMessage; } if (xevent.ClientMessageEvent.message_type == AsyncAtom) { XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1); goto ProcessNextMessage; } if (xevent.ClientMessageEvent.message_type == HoverState.Atom) { msg.message = Msg.WM_MOUSEHOVER; msg.wParam = GetMousewParam(0); msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1); return true; } if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) { DebugHelper.Indent (); DebugHelper.WriteLine (String.Format ("Posted message:" + (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 () + " for 0x{0:x}", xevent.ClientMessageEvent.ptr1.ToInt32 ())); DebugHelper.Unindent (); msg.hwnd = xevent.ClientMessageEvent.ptr1; msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 (); msg.wParam = xevent.ClientMessageEvent.ptr3; msg.lParam = xevent.ClientMessageEvent.ptr4; if (msg.message == (Msg)Msg.WM_QUIT) return false; else return true; } if (xevent.ClientMessageEvent.message_type == _XEMBED) { #if DriverDebugXEmbed Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32()); #endif if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) { XSizeHints hints = new XSizeHints(); IntPtr dummy; XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy); hwnd.width = hints.max_width; hwnd.height = hints.max_height; hwnd.ClientRect = Rectangle.Empty; SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero); } } if (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) { if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) { SendMessage (msg.hwnd, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_CLOSE, IntPtr.Zero); msg.message = Msg.WM_CLOSE; return true; } // We should not get this, but I'll leave the code in case we need it in the future if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) { goto ProcessNextMessage; } } goto ProcessNextMessage; } default: { goto ProcessNextMessage; } } return true; }
int IPropertyPage.TranslateAccelerator(MSG[] pMsg) { Utilities.ArgumentNotNull("pMsg", pMsg); MSG msg = pMsg[0]; if ((msg.message < NativeMethods.WM_KEYFIRST || msg.message > NativeMethods.WM_KEYLAST) && (msg.message < NativeMethods.WM_MOUSEFIRST || msg.message > NativeMethods.WM_MOUSELAST)) { return VSConstants.S_FALSE; } return (NativeMethods.IsDialogMessageA(Control.Handle, ref msg)) ? VSConstants.S_OK : VSConstants.S_FALSE; }
internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) { XEventQueue queue = (XEventQueue) queue_id; bool pending; if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) { throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet"); // FIXME - Implement PM_NOREMOVE flag } pending = false; if (queue.Count > 0) { pending = true; } else { // Only call UpdateMessageQueue if real events are pending // otherwise we go to sleep on the socket if (XPending(DisplayHandle) != 0) { UpdateMessageQueue((XEventQueue)queue_id); pending = true; } else if (((XEventQueue)queue_id).Paint.Count > 0) { pending = true; } } CheckTimers(queue.timer_list, DateTime.UtcNow); if (!pending) { return false; } return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax); }
// Any component that needs idle time, the ability to process // messages before they are translated (for example, to call TranslateAccelerator // or IsDialogMessage), notification about modal states, or the ability to push message // loops must implement this interface and register with the Component Manager. /// <summary> /// Called during each iteration of a message loop that the component pushed. /// </summary> /// <param name="uReason">The reason for the call.</param> /// <param name="pvLoopData">The component's private data.</param> /// <param name="pMsgPeeked">The peeked message, or NULL if no message is in the queue.</param> /// <returns> /// TRUE (not zero) if the message loop should continue, otherwise FALSE (zero). /// If false is returned, the component manager terminates the loop without /// removing pMsgPeeked from the queue. /// </returns> /// <remarks> /// This method is called after peeking the next message in the queue (via PeekMessage) /// but before the message is removed from the queue. This method may be additionally /// called when the next message has already been removed from the queue, in which case /// pMsgPeeked is passed as NULL. /// </remarks> public int FContinueMessageLoop(uint uReason, IntPtr pvLoopData, MSG[] pMsgPeeked) { throw new Exception("The method or operation is not implemented."); }
internal override bool TranslateMessage(ref MSG msg) { return Keyboard.TranslateMessage (ref msg); }
internal static bool HandleEvent (IntPtr callref, IntPtr eventref, IntPtr handle, uint kind, ref MSG msg) { Control control; DataObject data; DragEventArgs drag_event; DragDropEffects allowed; QDPoint point = new QDPoint (); UInt32 actions = 0; IntPtr dragref = IntPtr.Zero; Hwnd hwnd = Hwnd.ObjectFromHandle (handle); if (hwnd == null || hwnd.Handle != handle) return false; GetEventParameter (eventref, kEventParamDragRef, typeDragRef, IntPtr.Zero, (uint) Marshal.SizeOf (typeof (IntPtr)), IntPtr.Zero, ref dragref); XplatUICarbon.GetGlobalMouse (ref point); GetDragAllowableActions (dragref, ref actions); control = Control.FromHandle (hwnd.Handle); allowed = DragActionsToEffects (actions); data = DragToDataObject (dragref); drag_event = new DragEventArgs (data, 0, point.x, point.y, allowed, DragDropEffects.None); switch (kind) { case ControlHandler.kEventControlDragEnter: { bool accept = control.AllowDrop; SetEventParameter (eventref, ControlHandler.kEventParamControlLikesDrag, ControlHandler.typeBoolean, (uint)Marshal.SizeOf (typeof (bool)), ref accept); control.DndEnter (drag_event); effects = drag_event.Effect; return false; } case ControlHandler.kEventControlDragWithin: control.DndOver (drag_event); effects = drag_event.Effect; break; case ControlHandler.kEventControlDragLeave: control.DndLeave (drag_event); break; case ControlHandler.kEventControlDragReceive: control.DndDrop (drag_event); break; } return true; }
internal override void DoEvents() { MSG msg = new MSG(); while (GetMessage(ref msg, IntPtr.Zero, 0, 0, false)) { Message m = Message.Create (msg.hwnd, (int)msg.message, msg.wParam, msg.lParam); if (Application.FilterMessage (ref m)) continue; XplatUI.TranslateMessage(ref msg); XplatUI.DispatchMessage(ref msg); } }
private void PowerEventThread() { //Log.Debug( "Service1.PowerEventThread started" ); Thread.BeginThreadAffinity(); try { _powerEventThreadId = GetCurrentThreadId(); WNDCLASS wndclass; wndclass.style = 0; wndclass.lpfnWndProc = PowerEventThreadWndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = Process.GetCurrentProcess().Handle; wndclass.hIcon = IntPtr.Zero; wndclass.hCursor = IntPtr.Zero; wndclass.hbrBackground = IntPtr.Zero; wndclass.lpszMenuName = null; wndclass.lpszClassName = "TVServicePowerEventThreadWndClass"; RegisterClass(ref wndclass); IntPtr handle = CreateWindowEx(0x80, wndclass.lpszClassName, "", 0x80000000, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, wndclass.hInstance, IntPtr.Zero); if (handle.Equals(IntPtr.Zero)) { Log.Error("TV service PowerEventThread cannot create window handle, exiting thread"); return; } // this thread needs an message loop Log.Debug("TV service PowerEventThread message loop is running"); while (true) { try { MSG msgApi = new MSG(); if (!GetMessageA(ref msgApi, IntPtr.Zero, 0, 0)) // returns false on WM_QUIT return; TranslateMessage(ref msgApi); Log.Debug("TV service PowerEventThread {0}", msgApi.message); DispatchMessageA(ref msgApi); } catch (Exception ex) { Log.Error("TV service PowerEventThread: Exception: {0}", ex.ToString()); } } } finally { Thread.EndThreadAffinity(); Log.Debug("TV service PowerEventThread finished"); } }
internal static bool TranslateMessage(ref MSG msg) { return(driver.TranslateMessage(ref msg)); }