Пример #1
0
		public override void PropertyChanged (XEvent xevent)
		{
			if (xevent.PropertyEvent.atom == Display.Atoms._NET_ACTIVE_WINDOW) {
				IntPtr actual_atom;
				int actual_format;
				IntPtr nitems;
				IntPtr bytes_after;
				IntPtr prop = IntPtr.Zero;

				Xlib.XGetWindowProperty (Display.Handle, WholeWindow,
							 Display.Atoms._NET_ACTIVE_WINDOW, IntPtr.Zero, new IntPtr (1), false,
							 Display.Atoms.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);

				if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
					// FIXME - is this 64 bit clean?
					Display.SetActiveWindow ((X11Hwnd)Hwnd.ObjectFromHandle((IntPtr)Marshal.ReadInt32(prop)));
					Xlib.XFree(prop);
				}
			}
			else if (xevent.PropertyEvent.atom == Display.Atoms._NET_SUPPORTED) {
				// we'll need to refetch the supported protocols list
				refetch_net_supported = true;
				_net_supported = null;
			}
			else
				base.PropertyChanged (xevent);
		}
Пример #2
0
		public void Enqueue (XEvent xevent)
		{
			if (Thread.CurrentThread != thread) {
				Console.WriteLine ("Hwnd.Queue.Enqueue called from a different thread without locking.");
				Console.WriteLine (Environment.StackTrace);
			}

			xqueue.Enqueue (xevent);
		}
Пример #3
0
		internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);
Пример #4
0
		void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
			XEvent	xev;

			xev = new XEvent();
			xev.ClientMessageEvent.type = XEventName.ClientMessage;
			xev.ClientMessageEvent.send_event = true;
			xev.ClientMessageEvent.window = window;
			xev.ClientMessageEvent.message_type = message_type;
			xev.ClientMessageEvent.format = 32;
			xev.ClientMessageEvent.ptr1 = l0;
			xev.ClientMessageEvent.ptr2 = l1;
			xev.ClientMessageEvent.ptr3 = l2;
			XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
		}
Пример #5
0
		void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2, IntPtr l3) {
			XEvent	xev;

			xev = new XEvent();
			xev.ClientMessageEvent.type = XEventName.ClientMessage;
			xev.ClientMessageEvent.send_event = true;
			xev.ClientMessageEvent.window = window;
			xev.ClientMessageEvent.message_type = message_type;
			xev.ClientMessageEvent.format = 32;
			xev.ClientMessageEvent.ptr1 = l0;
			xev.ClientMessageEvent.ptr2 = l1;
			xev.ClientMessageEvent.ptr3 = l2;
			xev.ClientMessageEvent.ptr4 = l3;
			XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
		}
Пример #6
0
		internal static void XIfEvent (IntPtr display, ref XEvent xevent, Delegate event_predicate, IntPtr arg)
		{
			DebugHelper.TraceWriteLine ("XIfEvent");
			_XIfEvent (display, ref xevent, event_predicate, arg);
		}
Пример #7
0
		internal static bool XFilterEvent(ref XEvent xevent, IntPtr window)
		{
			DebugHelper.TraceWriteLine ("XFilterEvent");
			return _XFilterEvent(ref xevent, window);
		}
Пример #8
0
		internal static IntPtr XNextEvent(IntPtr display, ref XEvent xevent)
		{
			DebugHelper.TraceWriteLine ("XNextEvent");
			return _XNextEvent(display, ref xevent);
		}
Пример #9
0
		void AddConfigureNotify (XEvent xevent) {
			Hwnd	hwnd;

			hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);

			// Don't waste time
			if (hwnd == null || hwnd.zombie) {
				return;
			}
			if ((xevent.ConfigureEvent.window == hwnd.whole_window)/* && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)*/) {
				if (hwnd.parent == null) {
					// 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;
				}

				// XXX this sucks.  this isn't thread safe
				Control ctrl = Control.FromHandle (hwnd.Handle);
				Size TranslatedSize;
				if (ctrl != null) {
					TranslatedSize = TranslateXWindowSizeToWindowSize (ctrl.GetCreateParams (), xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
				} else {
					TranslatedSize = new Size (xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
				}
				hwnd.width = TranslatedSize.Width;
				hwnd.height = TranslatedSize.Height;
				hwnd.ClientRect = Rectangle.Empty;

				DriverDebug ("AddConfigureNotify (hwnd.Handle = {1}, final hwnd.rect = {0}, reported rect={2})",
					     new Rectangle (hwnd.x, hwnd.y, hwnd.width, hwnd.height), hwnd.Handle,
					     new Rectangle (xevent.ConfigureEvent.x, xevent.ConfigureEvent.y, xevent.ConfigureEvent.width, xevent.ConfigureEvent.width));
				lock (hwnd.configure_lock) {
					if (!hwnd.configure_pending) {
						hwnd.Queue.EnqueueLocked (xevent);
						hwnd.configure_pending = true;
					}
				}
			}
			// We drop configure events for Client windows
		}
Пример #10
0
		private bool HandleFinishedEvent (ref XEvent xevent)
		{
			return true;
		}
Пример #11
0
		private bool HandleStatusEvent (ref XEvent xevent)
		{
			if (drag_data != null && drag_data.State == DragState.Entered) {

				if (!QueryContinue (false, DragAction.Continue))
					return true;

				drag_data.WillAccept = ((int) xevent.ClientMessageEvent.ptr2 & 0x1) != 0;
				
				GiveFeedback (xevent.ClientMessageEvent.ptr5);
			}
			return true;
		}
Пример #12
0
		private bool Accepting_HandleLeaveEvent (ref XEvent xevent)
		{
			if (control != null && drag_event != null)
				control.DndLeave (drag_event);
			// Reset ();
			return true;
		}
Пример #13
0
		private bool Accepting_HandleDropEvent (ref XEvent xevent)
		{
			if (control != null && drag_event != null) {
				drag_event = new DragEventArgs (data,
						0, pos_x, pos_y,
					allowed, drag_event.Effect);
				control.DndDrop (drag_event);
			}
			SendFinished ();
			return true;
		}
Пример #14
0
		private bool Accepting_HandlePositionEvent (ref XEvent xevent)
		{
			pos_x = (int) xevent.ClientMessageEvent.ptr3 >> 16;
			pos_y = (int) xevent.ClientMessageEvent.ptr3 & 0xFFFF;

			// Copy is implicitly allowed
			Control source_control = MwfWindow (source);
			if (source_control == null)
				allowed = EffectsFromX11Source (source, xevent.ClientMessageEvent.ptr5) | DragDropEffects.Copy;
			else
				allowed = drag_data.AllowedEffects;

			IntPtr parent, child, new_child, last_drop_child;
			parent = XplatUIX11.XRootWindow (display, 0);
			child = toplevel;
			last_drop_child = IntPtr.Zero;
			while (true) {
				int xd, yd;
				new_child = IntPtr.Zero;
				
				if (!XplatUIX11.XTranslateCoordinates (display,
						    parent, child, pos_x, pos_y,
						    out xd, out yd, out new_child))
					break;
				if (new_child == IntPtr.Zero)
					break;
				child = new_child;

				Hwnd h = Hwnd.ObjectFromHandle (child);
				if (h != null) {
					Control d = Control.FromHandle (h.client_window);
					if (d != null && d.allow_drop)
						last_drop_child = child;
				}
			}

			if (last_drop_child != IntPtr.Zero)
				child = last_drop_child;

			if (target != child) {
				// We have moved into a new control 
				// or into a control for the first time
				Finish ();
			}
			target = child;
			Hwnd hwnd = Hwnd.ObjectFromHandle (target);
			if (hwnd == null)
				return true;

			Control c = Control.FromHandle (hwnd.client_window);

			if (c == null)
				return true;
			if (!c.allow_drop) {
				SendStatus (source, DragDropEffects.None);
				Finish ();
				return true;
			}

			control = c;
			position_recieved = true;			

			if (converts_pending > 0)
				return true;

			if (!status_sent) {
				drag_event = new DragEventArgs (data, 0, pos_x, pos_y,
					allowed, DragDropEffects.None);
				control.DndEnter (drag_event);
				
				SendStatus (source, drag_event.Effect);
				status_sent = true;
			} else {
				drag_event.x = pos_x;
				drag_event.y = pos_y;
				control.DndOver (drag_event);

				SendStatus (source, drag_event.Effect);
			}
			
			return true;
		}
Пример #15
0
		private bool Accepting_HandleEnterEvent (ref XEvent xevent)
		{
			Reset ();

			source = xevent.ClientMessageEvent.ptr1;
			toplevel = xevent.AnyEvent.window;
			target = IntPtr.Zero;

			ConvertData (ref xevent);

			return true;
		}
Пример #16
0
		internal override int SendInput(IntPtr handle, Queue keys)
		{ 
			if (handle == IntPtr.Zero)
				return 0;

			int count = keys.Count;
			Hwnd hwnd = Hwnd.ObjectFromHandle(handle);

			while (keys.Count > 0) {
			
				MSG msg = (MSG)keys.Dequeue();

				XEvent xevent = new XEvent ();

				xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
				xevent.KeyEvent.display = DisplayHandle;

				if (hwnd != null) {
					xevent.KeyEvent.window = hwnd.whole_window;
				} else {
					xevent.KeyEvent.window = IntPtr.Zero;
				}

				xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);

				hwnd.Queue.EnqueueLocked (xevent);
			}
			return count;
		}
Пример #17
0
		internal override void SetCursorPos(IntPtr handle, int x, int y)
		{
			if (handle == IntPtr.Zero) {
				lock (XlibLock) {
					IntPtr root, child;
					int root_x, root_y, child_x, child_y, mask;

					/* we need to do a
					 * QueryPointer before warping
					 * because if the warp is on
					 * the RootWindow, the x/y are
					 * relative to the current
					 * mouse position
					 */
					QueryPointer (DisplayHandle, RootWindow,
						      out root,
						      out child,
						      out root_x, out root_y,
						      out child_x, out child_y,
						      out mask);

					XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);

					XFlush (DisplayHandle);

					/* then we need to a
					 * QueryPointer after warping
					 * to manually generate a
					 * motion event for the window
					 * we move into.
					 */
					QueryPointer (DisplayHandle, RootWindow,
						      out root,
						      out child,
						      out root_x, out root_y,
						      out child_x, out child_y,
						      out mask);

					Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
					if (child_hwnd == null) {
						return;
					}

					XEvent xevent = new XEvent ();

					xevent.type = XEventName.MotionNotify;
					xevent.MotionEvent.display = DisplayHandle;
					xevent.MotionEvent.window = child_hwnd.client_window;
					xevent.MotionEvent.root = RootWindow;
					xevent.MotionEvent.x = child_x;
					xevent.MotionEvent.y = child_y;
					xevent.MotionEvent.x_root = root_x;
					xevent.MotionEvent.y_root = root_y;
					xevent.MotionEvent.state = mask;

					child_hwnd.Queue.EnqueueLocked (xevent);
				}
			} else {
				Hwnd	hwnd;

				hwnd = Hwnd.ObjectFromHandle(handle);
				lock (XlibLock) {
					XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
				}
			}
		}
Пример #18
0
		void UpdateMessageQueue (XEventQueue queue, bool allowIdle) {
			DateTime	now;
			int		pending;
			Hwnd		hwnd;

			now = DateTime.UtcNow;

			lock (XlibLock) {
				pending = XPending (DisplayHandle);
			}

			if (pending == 0 && allowIdle) {
				if ((queue == null || queue.DispatchIdle) && Idle != null) {
					Idle (this, EventArgs.Empty);
				}

				lock (XlibLock) {
					pending = XPending (DisplayHandle);
				}
			}

			if (pending == 0) {
				int	timeout = 0;

				if (queue != null) {
					if (queue.Paint.Count > 0)
						return;

					timeout = NextTimeout (queue.timer_list, now);
				}

				if (timeout > 0) {
					#if __MonoCS__
					int length = pollfds.Length - 1;
					lock (wake_waiting_lock) {
						if (wake_waiting == false) {
							length ++;
							wake_waiting = true;
						}
					}

					Syscall.poll (pollfds, (uint)length, timeout);
					// Clean out buffer, so we're not busy-looping on the same data
					if (length == pollfds.Length) {
						if (pollfds[1].revents != 0)
							wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
						lock (wake_waiting_lock) {
							wake_waiting = false;
						}
					}
					#endif
					lock (XlibLock) {
						pending = XPending (DisplayHandle);
					}
				}
			}

			if (queue != null)
				CheckTimers (queue.timer_list, now);

			while (true) {
				XEvent xevent = new XEvent ();

				lock (XlibLock) {
					if (XPending (DisplayHandle) == 0)
						break;

					XNextEvent (DisplayHandle, ref xevent);

					if (xevent.AnyEvent.type == XEventName.KeyPress ||
					    xevent.AnyEvent.type == XEventName.KeyRelease) {
						// PreFilter() handles "shift key state updates.
						Keyboard.PreFilter (xevent);
						if (XFilterEvent (ref xevent, Keyboard.ClientWindow)) {
							// probably here we could raise WM_IME_KEYDOWN and
							// WM_IME_KEYUP, but I'm not sure it is worthy.
							continue;
						}
					}
					else if (XFilterEvent (ref xevent, IntPtr.Zero))
						continue;
				}

				hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
				if (hwnd == null)
					continue;

				DebugHelper.WriteLine  ("UpdateMessageQueue got Event: " + xevent.ToString ());

				switch (xevent.type) {
				case XEventName.Expose:
					AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
					break;

				case XEventName.SelectionClear: {
					// Should we do something?
					break;
				}

				case XEventName.SelectionRequest: {
					if (Dnd.HandleSelectionRequestEvent (ref xevent))
						break;
					XEvent sel_event;

					sel_event = new XEvent();
					sel_event.SelectionEvent.type = XEventName.SelectionNotify;
					sel_event.SelectionEvent.send_event = true;
					sel_event.SelectionEvent.display = DisplayHandle;
					sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
					sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
					sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
					sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
					sel_event.SelectionEvent.property = IntPtr.Zero;

					IntPtr format_atom = xevent.SelectionRequestEvent.target;

					// Seems that some apps support asking for supported types
					if (format_atom == TARGETS) {
						int[]	atoms;
						int	atom_count;

						atoms = new int[5];
						atom_count = 0;

						if (Clipboard.IsSourceText) {
							atoms[atom_count++] = (int)Atom.XA_STRING;
							atoms[atom_count++] = (int)OEMTEXT;
							atoms[atom_count++] = (int)UTF8_STRING;
							atoms[atom_count++] = (int)UTF16_STRING;
							atoms[atom_count++] = (int)RICHTEXTFORMAT;
						} else if (Clipboard.IsSourceImage) {
							atoms[atom_count++] = (int)Atom.XA_PIXMAP;
							atoms[atom_count++] = (int)Atom.XA_BITMAP;
						} else {
							// FIXME - handle other types
						}

						XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, 
								(IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
						sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
					} else if (format_atom == (IntPtr)RICHTEXTFORMAT) {
						string rtf_text = Clipboard.GetRtfText ();
						if (rtf_text != null) {
							// The RTF spec mentions that ascii is enough to contain it
							Byte [] bytes = Encoding.ASCII.GetBytes (rtf_text);
							int buflen = bytes.Length;
							IntPtr buffer = Marshal.AllocHGlobal (buflen);

							for (int i = 0; i < buflen; i++)
								Marshal.WriteByte (buffer, i, bytes[i]);

							XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property,
									(IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
							sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
							Marshal.FreeHGlobal(buffer);
						}
					} else if (Clipboard.IsSourceText && 
					           (format_atom == (IntPtr)Atom.XA_STRING 
					            || format_atom == OEMTEXT
					            || format_atom == UTF16_STRING
					            || format_atom == UTF8_STRING)) {
						IntPtr	buffer = IntPtr.Zero;
						int	buflen;
						Encoding encoding = null;

						buflen = 0;

						// Select an encoding depending on the target
						IntPtr target_atom = xevent.SelectionRequestEvent.target;
						if (target_atom == (IntPtr)Atom.XA_STRING || target_atom == OEMTEXT)
							// FIXME - EOMTEXT should encode into ISO2022
							encoding = Encoding.ASCII;
						else if (target_atom == UTF16_STRING)
							encoding = Encoding.Unicode;
						else if (target_atom == UTF8_STRING)
							encoding = Encoding.UTF8;

						Byte [] bytes;

						bytes = encoding.GetBytes (Clipboard.GetPlainText ());
						buffer = Marshal.AllocHGlobal (bytes.Length);
						buflen = bytes.Length;

						for (int i = 0; i < buflen; i++)
							Marshal.WriteByte (buffer, i, bytes [i]);

						if (buffer != IntPtr.Zero) {
							XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
							sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
							Marshal.FreeHGlobal(buffer);
						}
					} else if (Clipboard.GetSource (format_atom.ToInt32 ()) != null) { // check if we have an available value of this format
						if (DataFormats.GetFormat (format_atom.ToInt32 ()).is_serializable) {
							object serializable = Clipboard.GetSource (format_atom.ToInt32 ());

							BinaryFormatter formatter = new BinaryFormatter ();
							MemoryStream memory_stream = new MemoryStream ();
							formatter.Serialize (memory_stream, serializable);

							int buflen = (int)memory_stream.Length;
							IntPtr buffer = Marshal.AllocHGlobal (buflen);
							memory_stream.Position = 0;
							for (int i = 0; i < buflen; i++)
								Marshal.WriteByte (buffer, i, (byte)memory_stream.ReadByte ());
							memory_stream.Close ();

							XChangeProperty (DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target,
									8, PropertyMode.Replace, buffer, buflen);
							sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
							Marshal.FreeHGlobal (buffer);
						}

					} else if (Clipboard.IsSourceImage) {
						if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
							// FIXME - convert image and store as property
						} else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
							// FIXME - convert image and store as property
						}
					}

					XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
					break;
				}

				case XEventName.SelectionNotify: {
					if (Clipboard.Enumerating) {
						Clipboard.Enumerating = false;
						if (xevent.SelectionEvent.property != IntPtr.Zero) {
							XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
							if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
								Clipboard.Formats.Add(xevent.SelectionEvent.property);
								DriverDebug("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
							}
						}
					} else if (Clipboard.Retrieving) {
						Clipboard.Retrieving = false;
						if (xevent.SelectionEvent.property != IntPtr.Zero) {
							TranslatePropertyToClipboard(xevent.SelectionEvent.property);
						} else {
							Clipboard.ClearSources ();
							Clipboard.Item = null;
						}
					} else {
						Dnd.HandleSelectionNotifyEvent (ref xevent);
					}
					break;
				}

				case XEventName.KeyRelease:
					if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
						XEvent nextevent = new XEvent ();

						XPeekEvent (DisplayHandle, ref nextevent);

						if (nextevent.type == XEventName.KeyPress &&
						    nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
						    nextevent.KeyEvent.time == xevent.KeyEvent.time) {
							continue;
						}
					}
					goto case XEventName.KeyPress;
					
				case XEventName.MotionNotify: {
					XEvent peek;

					/* we can't do motion compression across threads, so just punt if we don't match up */
					if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
						peek = hwnd.Queue.Peek();
						if (peek.AnyEvent.type == XEventName.MotionNotify) {
							continue;
						}
					}
					goto case XEventName.KeyPress;
				}

				case XEventName.KeyPress:
					hwnd.Queue.EnqueueLocked (xevent);
					/* Process KeyPresses immediately. Otherwise multiple Compose messages as a result of a
					 * single physical keypress are not processed correctly */
					return;
				case XEventName.ButtonPress:
				case XEventName.ButtonRelease:
				case XEventName.EnterNotify:
				case XEventName.LeaveNotify:
				case XEventName.CreateNotify:
				case XEventName.DestroyNotify:
				case XEventName.FocusIn:
				case XEventName.FocusOut:
				case XEventName.ClientMessage:
				case XEventName.ReparentNotify:
				case XEventName.MapNotify:
				case XEventName.UnmapNotify:
					hwnd.Queue.EnqueueLocked (xevent);
					break;

				case XEventName.ConfigureNotify:
					AddConfigureNotify(xevent);
					break;

				case XEventName.PropertyNotify:
					DriverDebug ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
					if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
						IntPtr	actual_atom;
						int	actual_format;
						IntPtr	nitems;
						IntPtr	bytes_after;
						IntPtr	prop = IntPtr.Zero;
						IntPtr	prev_active;

						prev_active = ActiveWindow;
						XGetWindowProperty(DisplayHandle, RootWindow, _NET_ACTIVE_WINDOW, IntPtr.Zero, new IntPtr (1), false, (IntPtr)Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
						if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
							ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));							
							XFree(prop);

							DebugHelper.WriteLine ("PropertyNotify: _NET_ACTIVE_WINDOW: previous = 0x{0:x}, new = 0x{1:x}", prev_active.ToInt32 (), ActiveWindow.ToInt32 ());
							
							if (prev_active != ActiveWindow) {
								if (prev_active != IntPtr.Zero) {
									PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
								}
								if (ActiveWindow != IntPtr.Zero) {
									PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
								}
							}
							if (ModalWindows.Count == 0) {
								break;
							} else {
								// Modality Handling
								// 
								// If there is a modal window on the stack and the new active 
								// window is MWF window, but not the modal one and not a non-modal 
								// child of the modal one, switch back to the modal window.
								//
								// To identify if a non-modal form is child of a modal form 
								// we match their ApplicationContexts, which will be the same.
								// This is because each modal form runs the loop with a 
								// new ApplicationContext, which is inherited by the non-modal 
								// forms.

								Form activeForm = Control.FromHandle (ActiveWindow) as Form;
								if (activeForm != null) {
									Form modalForm = Control.FromHandle ((IntPtr)ModalWindows.Peek()) as Form;
									if (ActiveWindow != (IntPtr)ModalWindows.Peek() && 
									    (modalForm == null || activeForm.context == modalForm.context)) {
										Activate((IntPtr)ModalWindows.Peek());
									}
								}
								break;
							}
						}
					}
					else if (xevent.PropertyEvent.atom == _NET_WM_STATE) {
						// invalidate our cache - we'll query again the next time someone does GetWindowState.
						hwnd.cached_window_state = (FormWindowState)(-1);
						PostMessage (hwnd.Handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
					}
					break;

				}
			}
		}
Пример #19
0
		internal static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event)
		{
			DebugHelper.TraceWriteLine ("XSendEvent");
			return _XSendEvent(display, window, propagate, event_mask, ref send_event);
		}
Пример #20
0
		void MouseHover(object sender, EventArgs e) {
			XEvent	xevent;
			Hwnd	hwnd;

			HoverState.Timer.Enabled = false;

			if (HoverState.Window != IntPtr.Zero) {
				hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
				if (hwnd != null) {
					xevent = new XEvent ();

					xevent.type = XEventName.ClientMessage;
					xevent.ClientMessageEvent.display = DisplayHandle;
					xevent.ClientMessageEvent.window = HoverState.Window;
					xevent.ClientMessageEvent.message_type = HoverState.Atom;
					xevent.ClientMessageEvent.format = 32;
					xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);

					hwnd.Queue.EnqueueLocked (xevent);

					WakeupMain ();
				}
			}
		}
Пример #21
0
		internal static void XPeekEvent (IntPtr display, ref XEvent xevent)
		{
			DebugHelper.TraceWriteLine ("XPeekEvent");
			_XPeekEvent (display, ref xevent);
		}
Пример #22
0
		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;
		}
Пример #23
0
		internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
Пример #24
0
		internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam)
		{
			XEvent xevent = new XEvent ();
			Hwnd hwnd = Hwnd.ObjectFromHandle(handle);

			xevent.type = XEventName.ClientMessage;
			xevent.ClientMessageEvent.display = DisplayHandle;

			if (hwnd != null) {
				xevent.ClientMessageEvent.window = hwnd.whole_window;
			} else {
				xevent.ClientMessageEvent.window = IntPtr.Zero;
			}

			xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
			xevent.ClientMessageEvent.format = 32;
			xevent.ClientMessageEvent.ptr1 = handle;
			xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
			xevent.ClientMessageEvent.ptr3 = wparam;
			xevent.ClientMessageEvent.ptr4 = lparam;

			if (hwnd != null)
				hwnd.Queue.EnqueueLocked (xevent);
			else
				ThreadQueue(Thread.CurrentThread).EnqueueLocked (xevent);

			return true;
		}
Пример #25
0
		internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
Пример #26
0
		bool GraphicsExposePredicate (IntPtr display, ref XEvent xevent, IntPtr arg)
		{
			return (xevent.type == XEventName.GraphicsExpose || xevent.type == XEventName.NoExpose) &&
				arg == xevent.GraphicsExposeEvent.drawable;
		}
Пример #27
0
		internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
Пример #28
0
		void ProcessGraphicsExpose (Hwnd hwnd)
		{
			XEvent xevent = new XEvent ();
			IntPtr handle = Hwnd.HandleFromObject (hwnd);
			EventPredicate predicate = GraphicsExposePredicate;

			for (;;) {
				XIfEvent (Display, ref xevent, predicate, handle);
				if (xevent.type != XEventName.GraphicsExpose)
					break;

				AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.GraphicsExposeEvent.x, xevent.GraphicsExposeEvent.y,
						xevent.GraphicsExposeEvent.width, xevent.GraphicsExposeEvent.height);

				if (xevent.GraphicsExposeEvent.count == 0)
					break;
			}
		}
Пример #29
0
		internal extern static void XIfEvent (IntPtr display, ref XEvent xevent, Delegate event_predicate, IntPtr arg);
Пример #30
0
		internal override void SendAsyncMethod (AsyncMethodData method)
		{
			Hwnd	hwnd;
			XEvent	xevent = new XEvent ();

			hwnd = Hwnd.ObjectFromHandle(method.Handle);

			xevent.type = XEventName.ClientMessage;
			xevent.ClientMessageEvent.display = DisplayHandle;
			xevent.ClientMessageEvent.window = method.Handle;
			xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
			xevent.ClientMessageEvent.format = 32;
			xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);

			hwnd.Queue.EnqueueLocked (xevent);

			WakeupMain ();
		}