Exemplo n.º 1
0
		public X11Display (IntPtr display)
		{
			if (display == IntPtr.Zero) {
				throw new ArgumentNullException("Display",
							"Could not open display (X-Server required. Check your DISPLAY environment variable)");
			}

			this.display = display;

			// Debugging support
			if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
				Xlib.XSynchronize (display, true);
			}

			if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
				ErrorExceptions = true;
			}

			atoms = new X11Atoms (this);

			DoubleClickInterval = 500;

			HoverState.Interval = 500;
			HoverState.Timer = new Timer();
			HoverState.Timer.Enabled = false;
			HoverState.Timer.Interval = HoverState.Interval;
			HoverState.Timer.Tick += new EventHandler(MouseHover);
			HoverState.Size = new Size(4, 4);
			HoverState.X = -1;
			HoverState.Y = -1;

			ActiveWindow = null;
			FocusWindow = null;
			ModalWindows = new Stack(3);

			MouseState = MouseButtons.None;
			MousePosition = new Point(0, 0);

			Caret.Timer = new Timer();
			Caret.Timer.Interval = 500;		// FIXME - where should this number come from?
			Caret.Timer.Tick += new EventHandler(CaretCallback);

			// XXX multiscreen work here
			root_hwnd = new X11RootHwnd (this, Xlib.XRootWindow (display, DefaultScreen));

			// XXX do we need a per-screen foster parent?
			// Create the foster parent
			foster_hwnd = new X11Hwnd (this,
						   Xlib.XCreateSimpleWindow (display, root_hwnd.WholeWindow,
									     0, 0, 1, 1, 4, UIntPtr.Zero, UIntPtr.Zero));

			pollfds = new Pollfd [1];
			pollfds [0] = new Pollfd ();
			pollfds [0].fd = Xlib.XConnectionNumber (display);
			pollfds [0].events = PollEvents.POLLIN;

			Keyboard = new X11Keyboard(display, foster_hwnd.Handle);
			Dnd = new X11Dnd (display, Keyboard);

			ErrorExceptions = false;

			// Handle any upcoming errors
			ErrorHandler = new XErrorHandler (HandleError);
			Xlib.XSetErrorHandler (ErrorHandler);

			X11DesktopColors.Initialize(); // XXX we need to figure out how to make this display specific?

			// Disable keyboard autorepeat
			try {
				Xlib.XkbSetDetectableAutoRepeat (display, true, IntPtr.Zero);
				detectable_key_auto_repeat = true;
			} catch {
				Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
				detectable_key_auto_repeat = false;
			}

			// we re-set our error handler here, X11DesktopColor stuff might have stolen it (gtk does)
			Xlib.XSetErrorHandler (ErrorHandler);

			// create our event thread (just sits on the X socket waiting for events)
			event_thread = new Thread (new ThreadStart (XEventThread));
			event_thread.IsBackground = true;
			event_thread.Start ();
		}
Exemplo n.º 2
0
		public void SetModal (X11Hwnd hwnd, bool Modal)
		{
			if (Modal) {
				ModalWindows.Push(hwnd);
			} else {
				// XXX do we need to pop until the
				// hwnd is off the stack?  or just the
				// most recently pushed hwnd?
				if (ModalWindows.Contains(hwnd)) {
					ModalWindows.Pop();
				}

				if (ModalWindows.Count > 0) {
					X11Hwnd top_hwnd = (X11Hwnd)ModalWindows.Peek();
					top_hwnd.Activate();
				}
			}
		}
Exemplo n.º 3
0
		public void SetFocus (X11Hwnd new_focus)
		{
			if (new_focus == FocusWindow)
				return;

			X11Hwnd prev_focus = FocusWindow;
			FocusWindow = new_focus;

			if (prev_focus != null)
				SendMessage (prev_focus.Handle, Msg.WM_KILLFOCUS,
					     FocusWindow == null ? IntPtr.Zero : FocusWindow.Handle, IntPtr.Zero);
			if (FocusWindow != null)
				SendMessage (FocusWindow.Handle, Msg.WM_SETFOCUS,
					     prev_focus == null ? IntPtr.Zero : prev_focus.Handle, IntPtr.Zero);

			//XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).ClientWindow, RevertTo.None, IntPtr.Zero);
		}
Exemplo n.º 4
0
		public bool GetMessage (object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax)
		{
			X11ThreadQueue queue = (X11ThreadQueue)queue_id;
			XEvent xevent;
			bool client;
			bool got_xevent = false;

			X11Hwnd hwnd;

		ProcessNextMessage:
			do {
				got_xevent = queue.Dequeue (out xevent);

				if (!got_xevent) {
#if spew
					Console.WriteLine (">");
					Console.Out.Flush ();
#endif
					break;
				}

#if spew
				Console.Write ("-");
				Console.Out.Flush ();
#endif

				hwnd = (X11Hwnd)Hwnd.GetObjectFromWindow (xevent.AnyEvent.window);

				// 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.PendingExpose = hwnd.PendingNCExpose = false;
					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
				// ClientWindow, 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) {
#if DriverDebug || DriverDebugDestroy
					Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}",
							  xevent.type, xevent.AnyEvent.window.ToInt32());
#endif
					goto ProcessNextMessage;
				}

				client = hwnd.ClientWindow == xevent.AnyEvent.window;

				msg.hwnd = hwnd.Handle;

				switch (xevent.type) {
				case XEventName.KeyPress:
					Keyboard.KeyEvent (FocusWindow.Handle, xevent, ref msg);
					return true;

				case XEventName.KeyRelease:
					Keyboard.KeyEvent (FocusWindow.Handle, xevent, ref msg);
					return true;

				case XEventName.ButtonPress: {
					switch(xevent.ButtonEvent.button) {
					case 1:
						MouseState |= MouseButtons.Left;
						if (client) {
							msg.message = Msg.WM_LBUTTONDOWN;
						} else {
							msg.message = Msg.WM_NCLBUTTONDOWN;
							hwnd.MenuToScreen (ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
						}
						// TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
						msg.wParam=GetMousewParam(0);
						break;

					case 2:
						MouseState |= MouseButtons.Middle;
						if (client) {
							msg.message = Msg.WM_MBUTTONDOWN;
						} else {
							msg.message = Msg.WM_NCMBUTTONDOWN;
							hwnd.MenuToScreen (ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
						}
						msg.wParam=GetMousewParam(0);
						break;

					case 3:
						MouseState |= MouseButtons.Right;
						if (client) {
							msg.message = Msg.WM_RBUTTONDOWN;
						} else {
							msg.message = Msg.WM_NCRBUTTONDOWN;
							hwnd.MenuToScreen (ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
						}
						msg.wParam=GetMousewParam(0);
						break;

					case 4:
						msg.hwnd = FocusWindow.Handle;
						msg.message=Msg.WM_MOUSEWHEEL;
						msg.wParam=GetMousewParam(120);
						break;

					case 5:
						msg.hwnd = FocusWindow.Handle;
						msg.message=Msg.WM_MOUSEWHEEL;
						msg.wParam=GetMousewParam(-120);
						break;
					}

					msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
					MousePosition.X = xevent.ButtonEvent.x;
					MousePosition.Y = xevent.ButtonEvent.y;

					if (!hwnd.Enabled) {
						RedirectMsgToEnabledAncestor (hwnd, msg, xevent.AnyEvent.window,
									      ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
					}

					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) {
						hwnd.SendParentNotify (msg.message, MousePosition.X, MousePosition.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*
						XEvent motionEvent = new XEvent ();
						motionEvent.type = XEventName.MotionNotify;
						motionEvent.MotionEvent.display = display;
						motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
						motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
						motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
						hwnd.Queue.Enqueue (motionEvent);
					}

					return true;
				}

				case XEventName.ButtonRelease:
					switch(xevent.ButtonEvent.button) {
					case 1:
						if (client) {
							msg.message = Msg.WM_LBUTTONUP;
						} else {
							msg.message = Msg.WM_NCLBUTTONUP;
							hwnd.MenuToScreen (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;
							hwnd.MenuToScreen (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;
							hwnd.MenuToScreen (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) {
						RedirectMsgToEnabledAncestor (hwnd, msg, xevent.AnyEvent.window,
									      ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
					}

					if (Grab.Hwnd != IntPtr.Zero)
						msg.hwnd = Grab.Hwnd;

					msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
					MousePosition.X = xevent.ButtonEvent.x;
					MousePosition.Y = xevent.ButtonEvent.y;

						// 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 = display;
						motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
						motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
						motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
						hwnd.Queue.Enqueue (motionEvent);
					}
					return true;

				case XEventName.MotionNotify:
					/* XXX move the compression stuff here */

					if (client) {
#if DriverDebugExtra
						Console.WriteLine("GetMessage(): Window {0:X} MotionNotify x={1} y={2}",
								  client ? hwnd.ClientWindow.ToInt32() : hwnd.WholeWindow.ToInt32(),
								  xevent.MotionEvent.x, xevent.MotionEvent.y);
#endif

						if (Grab.Hwnd != IntPtr.Zero)
							msg.hwnd = Grab.Hwnd;
						else
							NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);

						msg.message = Msg.WM_MOUSEMOVE;
						msg.wParam = GetMousewParam(0);
						msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);

						if (!hwnd.Enabled) {
							RedirectMsgToEnabledAncestor (hwnd, msg, xevent.AnyEvent.window,
										      ref xevent.MotionEvent.x, ref xevent.MotionEvent.y);
						}

						MousePosition.X = xevent.MotionEvent.x;
						MousePosition.Y = xevent.MotionEvent.y;

						if ((HoverState.Timer.Enabled) &&
						    (((MousePosition.X + HoverState.Size.Width) < HoverState.X) ||
						     ((MousePosition.X - HoverState.Size.Width) > HoverState.X) ||
						     ((MousePosition.Y + HoverState.Size.Height) < HoverState.Y) ||
						     ((MousePosition.Y - HoverState.Size.Height) > HoverState.Y))) {

							HoverState.Timer.Stop();
							HoverState.Timer.Start();
							HoverState.X = MousePosition.X;
							HoverState.Y = MousePosition.Y;
						}
					}
					else {
						HitTest	ht;
						IntPtr dummy;
						int screen_x;
						int screen_y;

						#if DriverDebugExtra
						Console.WriteLine("GetMessage(): non-client area {0:X} MotionNotify x={1} y={2}",
								  client ? hwnd.ClientWindow.ToInt32() : hwnd.WholeWindow.ToInt32(),
								  xevent.MotionEvent.x, xevent.MotionEvent.y);
						#endif
						msg.message = Msg.WM_NCMOUSEMOVE;

						if (!hwnd.Enabled) {
							RedirectMsgToEnabledAncestor (hwnd, msg, xevent.AnyEvent.window,
										      ref xevent.MotionEvent.x, ref xevent.MotionEvent.y);
						}

						// The hit test is sent in screen coordinates
						Xlib.XTranslateCoordinates (display, xevent.AnyEvent.window, RootWindow.Handle,
									    xevent.MotionEvent.x, xevent.MotionEvent.y,
									    out screen_x, out screen_y, out dummy);

						msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
						ht = (HitTest)NativeWindow.WndProc (hwnd.ClientWindow, Msg.WM_NCHITTEST,
										    IntPtr.Zero, msg.lParam).ToInt32 ();
						NativeWindow.WndProc(hwnd.ClientWindow, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);

						MousePosition.X = xevent.MotionEvent.x;
						MousePosition.Y = xevent.MotionEvent.y;
					}

					return true;

				case XEventName.EnterNotify:
					if (!hwnd.Enabled)
						goto ProcessNextMessage;

					if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal)
						goto ProcessNextMessage;

					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;

					return true;

				case XEventName.LeaveNotify:
					if (!hwnd.Enabled)
						goto ProcessNextMessage;

					if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) ||
					    (xevent.CrossingEvent.window != hwnd.ClientWindow))
						goto ProcessNextMessage;

					msg.message=Msg.WM_MOUSELEAVE;
					HoverState.Timer.Enabled = false;
					HoverState.Window = IntPtr.Zero;

					return true;

				case XEventName.ReparentNotify:
					if (hwnd.parent == null) {	// Toplevel
						if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.WholeWindow)) {
							// We need to adjust x/y
							// This sucks ass, part 2
							// Every WM does the reparenting of toplevel windows different, so there's
							// no standard way of getting our adjustment considering frames/decorations
							// The code below is needed for metacity. KDE doesn't works just fine without this
							int	dummy_int;
							IntPtr	dummy_ptr;
							int	new_x;
							int	new_y;
							int	frame_left;
							int	frame_top;

							hwnd.Reparented = true;

							Xlib.XGetGeometry(display, XGetParent(hwnd.WholeWindow),
									  out dummy_ptr, out new_x, out new_y,
									  out dummy_int, out dummy_int, out dummy_int, out dummy_int);
							hwnd.FrameExtents(out frame_left, out frame_top);
							if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
								hwnd.x = new_x;
								hwnd.y = new_y;
								hwnd.whacky_wm = true;
							}

							if (hwnd.opacity != 0xffffffff) {
								IntPtr opacity;

								opacity = (IntPtr)(Int32)hwnd.opacity;
								Xlib.XChangeProperty (display, XGetParent(hwnd.WholeWindow),
										      Atoms._NET_WM_WINDOW_OPACITY, Atoms.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:
					hwnd.HandleConfigureNotify (xevent);
					goto ProcessNextMessage;

				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.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 == null) {
						Control c = Control.FromHandle (hwnd.ClientWindow);
						if (c == null)
							goto ProcessNextMessage;
						Form form = c.FindForm ();
						if (form == null)
							goto ProcessNextMessage;
						X11Hwnd new_active = (X11Hwnd)Hwnd.ObjectFromHandle (form.Handle);
						if (ActiveWindow != new_active) {
							ActiveWindow = new_active;
							SendMessage (ActiveWindow.Handle, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
						}
						goto ProcessNextMessage;
					}
					Keyboard.FocusIn(FocusWindow.Handle);
					SendMessage(FocusWindow.Handle, 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;

					if (FocusWindow == null)
						goto ProcessNextMessage;

					Keyboard.FocusOut(FocusWindow.Handle);

					while (Keyboard.ResetKeyState(FocusWindow.Handle, ref msg))
						SendMessage(FocusWindow.Handle, msg.message, msg.wParam, msg.lParam);

					SendMessage(FocusWindow.Handle, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
					goto ProcessNextMessage;

				case XEventName.Expose:
					if (!hwnd.Mapped) {
						hwnd.PendingExpose = hwnd.PendingNCExpose = false;
						continue;
					}

					msg.hwnd = hwnd.Handle;

					if (client) {
#if DriverDebugExtra
						Console.WriteLine("GetMessage(): Window {0:X} Exposed area {1},{2} {3}x{4}",
								  hwnd.client_window.ToInt32(),
								  xevent.ExposeEvent.x, xevent.ExposeEvent.y,
								  xevent.ExposeEvent.width, xevent.ExposeEvent.height);
#endif
						msg.message = Msg.WM_PAINT;
					}
					else {
						Graphics g;

						switch (hwnd.border_style) {
						case FormBorderStyle.Fixed3D:
							g = Graphics.FromHwnd(hwnd.WholeWindow);
							ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height),
										  Border3DStyle.Sunken);
							g.Dispose();
							break;

						case FormBorderStyle.FixedSingle:
							g = Graphics.FromHwnd(hwnd.WholeWindow);
							ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height),
										Color.Black, ButtonBorderStyle.Solid);
							g.Dispose();
						break;
						}
#if DriverDebugExtra
						Console.WriteLine("GetMessage(): Window {0:X} Exposed non-client area {1},{2} {3}x{4}",
								  hwnd.ClientWindow.ToInt32(),
								  xevent.ExposeEvent.x, xevent.ExposeEvent.y,
								  xevent.ExposeEvent.width, xevent.ExposeEvent.height);
#endif

						Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y,
										xevent.ExposeEvent.width, xevent.ExposeEvent.height);
						Region region = new Region (rect);
						IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
						msg.message = Msg.WM_NCPAINT;
						msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
						msg.refobject = region;
					}

					return true;
						
				case XEventName.DestroyNotify:

					// This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
					hwnd = (X11Hwnd)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.ClientWindow == xevent.DestroyWindowEvent.window)) {
						CleanupCachedWindows (hwnd);

						#if DriverDebugDestroy
						Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.ClientWindow));
						#endif

						msg.hwnd = hwnd.ClientWindow;
						msg.message=Msg.WM_DESTROY;
						hwnd.Dispose();
					}
					else
						goto ProcessNextMessage;

					return true;

				case XEventName.ClientMessage:
					if (Dnd.HandleClientMessage (ref xevent))
						goto ProcessNextMessage;

					if (xevent.ClientMessageEvent.message_type == Atoms.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 == Atoms.PostAtom) {
						msg.hwnd = xevent.ClientMessageEvent.ptr1;
						msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
						msg.wParam = xevent.ClientMessageEvent.ptr3;
						msg.lParam = xevent.ClientMessageEvent.ptr4;

						// if we posted a WM_QUIT message, make sure we return
						// false here as well.
						if (msg.message == (Msg)Msg.WM_QUIT)
							return false;
						else
							return true;
					}

					if (xevent.ClientMessageEvent.message_type == Atoms._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;

							Xlib.XGetWMNormalHints (display, hwnd.WholeWindow, 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 == Atoms.WM_PROTOCOLS) {
						if (xevent.ClientMessageEvent.ptr1 == Atoms.WM_DELETE_WINDOW) {
							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 == Atoms.WM_TAKE_FOCUS) {
							goto ProcessNextMessage;
						}
					}

					goto ProcessNextMessage;

				case XEventName.PropertyNotify:
					// The Hwnd's themselves handle this
					hwnd.PropertyChanged (xevent);
					goto ProcessNextMessage;
				}
			} while (true);

			msg.hwnd= IntPtr.Zero;
			msg.message = Msg.WM_ENTERIDLE;
			return true;
		}
Exemplo n.º 5
0
		public void ResetMouseHover (X11Hwnd hovering)
		{
			HoverState.Timer.Enabled = hovering != null;
			HoverState.X = MousePosition.X;
			HoverState.Y = MousePosition.Y;
			HoverState.Window = hovering == null ? IntPtr.Zero : hovering.Handle;
		}
Exemplo n.º 6
0
		public void UngrabWindow (X11Hwnd hwnd)
		{
			Xlib.XUngrabPointer (display, IntPtr.Zero);
			Xlib.XFlush (display);

			// XXX make sure hwnd is what should have the grab and throw if not
			Grab.Hwnd = IntPtr.Zero;
			Grab.Confined = false;
		}
Exemplo n.º 7
0
		private void RedirectMsgToEnabledAncestor (X11Hwnd hwnd, MSG msg, IntPtr window,
							   ref int event_x, ref int event_y)
		{
			int x, y;

			IntPtr dummy;
			msg.hwnd = hwnd.EnabledHwnd;
			Xlib.XTranslateCoordinates (display, window,
						    Hwnd.ObjectFromHandle(msg.hwnd).ClientWindow,
						    event_x, event_y,
						    out x, out y, out dummy);
			event_x = x;
			event_y = y;
			msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
		}
Exemplo n.º 8
0
		public void GetCursorPos (X11Hwnd hwnd, out int x, out int y)
		{
			IntPtr	use_handle;
			IntPtr	root;
			IntPtr	child;
			int	root_x;
			int	root_y;
			int	win_x;
			int	win_y;
			int	keys_buttons;

			if (hwnd != null)
				use_handle = hwnd.Handle;
			else
				use_handle = RootWindow.Handle;

			QueryPointer (use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);

			if (hwnd != null) {
				x = win_x;
				y = win_y;
			} else {
				x = root_x;
				y = root_y;
			}
		}
Exemplo n.º 9
0
		public void GrabWindow (X11Hwnd hwnd, X11Hwnd confine_to)
		{
			IntPtr	confine_to_window;

			confine_to_window = IntPtr.Zero;

			if (confine_to != null) {
				Console.WriteLine (Environment.StackTrace);

				XWindowAttributes attributes = new XWindowAttributes();

				Xlib.XGetWindowAttributes (display, confine_to.ClientWindow, ref attributes);

				Grab.Area.X = attributes.x;
				Grab.Area.Y = attributes.y;
				Grab.Area.Width = attributes.width;
				Grab.Area.Height = attributes.height;
				Grab.Confined = true;
				confine_to_window = confine_to.ClientWindow;
			}

			Grab.Hwnd = hwnd.ClientWindow;

			Xlib.XGrabPointer (display, hwnd.ClientWindow, false, 
					   EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
					   EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
					   GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
		}
Exemplo n.º 10
0
		public void DestroyWindow (X11Hwnd hwnd)
		{
			CleanupCachedWindows (hwnd);

			hwnd.SendParentNotify (Msg.WM_DESTROY, int.MaxValue, int.MaxValue);

			ArrayList windows = new ArrayList ();

			AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);

			hwnd.DestroyWindow ();

			foreach (X11Hwnd h in windows) {
				SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
			}
		}
Exemplo n.º 11
0
		public void SetActiveWindow (X11Hwnd new_active_window)
		{
			if (new_active_window != ActiveWindow) {
				if (ActiveWindow != null)
					PostMessage (ActiveWindow.Handle, Msg.WM_ACTIVATE,
						     (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);

				ActiveWindow = new_active_window;

				if (ActiveWindow != null)
					PostMessage (ActiveWindow.Handle, Msg.WM_ACTIVATE,
						     (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
                        }

			if (ModalWindows.Count > 0) {
				// Modality handling, if we are modal and the new active window is one
				// of ours but not the modal one, switch back to the modal window

				if (ActiveWindow != null &&
				    NativeWindow.FromHandle (ActiveWindow.Handle) != null) {
					if (ActiveWindow != (X11Hwnd)ModalWindows.Peek())
						((X11Hwnd)ModalWindows.Peek()).Activate ();
				}
			}
                }
Exemplo n.º 12
0
		void CleanupCachedWindows (X11Hwnd hwnd)
		{
			if (ActiveWindow == hwnd) {
				SendMessage (hwnd.ClientWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
				ActiveWindow = null;
			}

			if (FocusWindow == hwnd) {
				SendMessage (hwnd.ClientWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
				FocusWindow = null;
			}

			if (Grab.Hwnd == hwnd.Handle) {
				Grab.Hwnd = IntPtr.Zero;
				Grab.Confined = false;
			}

			DestroyCaret (hwnd.Handle);
		}
Exemplo n.º 13
0
		internal override IntPtr CreateWindow (CreateParams cp)
		{
			X11Hwnd hwnd = new X11Hwnd (display);

			hwnd.CreateWindow (cp);

			return hwnd.Handle;
		}
Exemplo n.º 14
0
		public bool SetZOrder (X11Hwnd after_hwnd, bool top, bool bottom)
		{
			if (top) {
				Xlib.XRaiseWindow (display.Handle, WholeWindow);
				return true;
			}
			else if (bottom) {
				Xlib.XLowerWindow (display.Handle, WholeWindow);
				return true;
			}
			else {
				if (after_hwnd == null) {
					Update_USER_TIME ();
					Xlib.XRaiseWindow (display.Handle, WholeWindow);
					display.SendNetWMMessage (WholeWindow, display.Atoms._NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
					return true;
				}

				XWindowChanges values = new XWindowChanges();
				values.sibling = after_hwnd.WholeWindow;
				values.stack_mode = StackMode.Below;

				Xlib.XConfigureWindow (display.Handle, WholeWindow, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
			}
			return false;
		}
Exemplo n.º 15
0
		public bool SetOwner (X11Hwnd owner)
		{
			if (owner != null) {
				WINDOW_TYPE = display.Atoms._NET_WM_WINDOW_TYPE_NORMAL;
				if (owner != null)
					Xlib.XSetTransientForHint (display.Handle, WholeWindow, owner.WholeWindow);
				else
					Xlib.XSetTransientForHint (display.Handle, WholeWindow, display.RootWindow.WholeWindow);
			}
			else {
				Xlib.XDeleteProperty (display.Handle, WholeWindow, display.Atoms.XA_WM_TRANSIENT_FOR);
			}

			return true;
		}
Exemplo n.º 16
0
		public void SetParent (X11Hwnd parent_hwnd)
		{
			Parent = parent_hwnd;

#if DriverDebug || DriverDebugParent
			Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(Handle), XplatUI.Window(hwnd.parent != null ? parent_hwnd.Handle : IntPtr.Zero));
#endif
			Xlib.XReparentWindow (display.Handle, WholeWindow,
					      parent_hwnd == null ? display.FosterParent.ClientWindow : parent_hwnd.ClientWindow,
					      X, Y);
		}