Ejemplo n.º 1
1
		internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
Ejemplo n.º 2
1
		internal extern static void _XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
Ejemplo n.º 3
1
		internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt)
		{
			GetSystrayManagerWindow();

			if (SystrayMgrWindow != IntPtr.Zero) {
				XSizeHints	size_hints;
				Hwnd		hwnd;

				hwnd = Hwnd.ObjectFromHandle(handle);
				DriverDebug("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());

				// Oh boy.
				if (hwnd.client_window != hwnd.whole_window) {
					Keyboard.DestroyICForWindow (hwnd.client_window);
					XDestroyWindow(DisplayHandle, hwnd.client_window);
					hwnd.client_window = hwnd.whole_window;
				}	

				/* by virtue of the way the tests are ordered when determining if it's PAINT
				   or NCPAINT, client_window == whole_window will always be PAINT.  So, if we're
				   waiting on an nc_expose, drop it and remove the hwnd from the list (unless
				   there's a pending expose). */
				if (hwnd.nc_expose_pending) {
					hwnd.nc_expose_pending = false;
					if (!hwnd.expose_pending)
						hwnd.Queue.Paint.Remove (hwnd);
				}

				// We are going to be directly mapped by the system tray, so mark as mapped
				// so we can later properly unmap it.
				hwnd.mapped = true;

				size_hints = new XSizeHints();

				size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);

 				size_hints.min_width = 24;
 				size_hints.min_height = 24;
 				size_hints.max_width = 24;
 				size_hints.max_height = 24;
 				size_hints.base_width = 24;
 				size_hints.base_height = 24;

				XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);

				int[] atoms = new int[2];
				atoms [0] = 1;			// Version 1
				atoms [1] = 1;			// we want to be mapped

				// This line cost me 3 days...
				XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);

				// Need to pick some reasonable defaults
				tt = new ToolTip();
				tt.AutomaticDelay = 350;
				tt.InitialDelay = 250;
				tt.ReshowDelay = 250;
				tt.ShowAlways = true;

				if ((tip != null) && (tip != string.Empty)) {
					tt.SetToolTip(Control.FromHandle(handle), tip);
					tt.Active = true;
				} else {
					tt.Active = false;
				}

				SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);

				return true;
			}
			tt = null;
			return false;
		}
Ejemplo n.º 4
0
		internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
Ejemplo n.º 5
0
		internal static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return)
		{
			DebugHelper.TraceWriteLine ("XGetWMNormalHints");
			_XGetWMNormalHints(display, window, ref hints, out supplied_return);
		}
Ejemplo n.º 6
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;
		}
Ejemplo n.º 7
0
		internal void SetWindowMinMax (IntPtr handle, Rectangle maximized, Size min, Size max, CreateParams cp)
		{
			Hwnd		hwnd;
			XSizeHints	hints;
			IntPtr		dummy;

			hwnd = Hwnd.ObjectFromHandle(handle);
			if (hwnd == null) {
				return;
			}

			min.Width = Math.Max (min.Width, SystemInformation.MinimumWindowSize.Width);
			min.Height = Math.Max (min.Height, SystemInformation.MinimumWindowSize.Height);
			
			hints = new XSizeHints();

			XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
			if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
				if (cp != null)
					min = TranslateWindowSizeToXWindowSize (cp, min);
				hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
				hints.min_width = min.Width;
				hints.min_height = min.Height;
			}

			if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
				if (cp != null)
					max = TranslateWindowSizeToXWindowSize (cp, max);
				hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
				hints.max_width = max.Width;
				hints.max_height = max.Height;
			}

			if (hints.flags != IntPtr.Zero) {
				// The Metacity team has decided that they won't care about this when clicking the maximize icon, 
				// they will maximize the window to fill the screen/parent no matter what.
				// http://bugzilla.ximian.com/show_bug.cgi?id=80021
				XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
			}

			if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
				if (cp != null)
					maximized.Size = TranslateWindowSizeToXWindowSize (cp);
				hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
				hints.x = maximized.X;
				hints.y = maximized.Y;
				hints.width = maximized.Width;
				hints.height = maximized.Height;

				// Metacity does not seem to follow this constraint for maximized (zoomed) windows
				XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
			}
		}
Ejemplo n.º 8
0
		public bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt)
		{
			IntPtr SystrayMgrWindow;

			Xlib.XGrabServer (display);
			SystrayMgrWindow = Xlib.XGetSelectionOwner (display, Atoms._NET_SYSTEM_TRAY_S);
			Xlib.XUngrabServer (display);

			if (SystrayMgrWindow != IntPtr.Zero) {
				XSizeHints size_hints;
				X11Hwnd hwnd;

				hwnd = (X11Hwnd)Hwnd.ObjectFromHandle(handle);
#if DriverDebug
				Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}",
						  hwnd.WholeWindow.ToInt32(), hwnd.ClientWindow.ToInt32());
#endif

				// Oh boy.
				if (hwnd.ClientWindow != hwnd.WholeWindow) {
					Xlib.XDestroyWindow (display, hwnd.ClientWindow);
					hwnd.ClientWindow = hwnd.WholeWindow;

					try {
						hwnd.Queue.Lock ();

						/* by virtue of the way the tests are ordered when determining if it's PAINT
						   or NCPAINT, ClientWindow == WholeWindow will always be PAINT.  So, if we're
						   waiting on an nc_expose, drop it and remove the hwnd from the list (unless
						   there's a pending expose). */
						hwnd.PendingNCExpose = false;
					}
					finally {
						hwnd.Queue.Unlock ();
					}
				}

				size_hints = new XSizeHints();

				size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);

 				size_hints.min_width = 24;
 				size_hints.min_height = 24;
 				size_hints.max_width = 24;
 				size_hints.max_height = 24;
 				size_hints.base_width = 24;
 				size_hints.base_height = 24;

				Xlib.XSetWMNormalHints (display, hwnd.WholeWindow, ref size_hints);

				int[] atoms = new int[2];
				atoms [0] = 1;			// Version 1
				atoms [1] = 1;			// we want to be mapped

				// This line cost me 3 days...
				Xlib.XChangeProperty (display,
						      hwnd.WholeWindow, Atoms._XEMBED_INFO, Atoms._XEMBED_INFO, 32,
						      PropertyMode.Replace, atoms, 2);

				// Need to pick some reasonable defaults
				tt = new ToolTip();
				tt.AutomaticDelay = 100;
				tt.InitialDelay = 250;
				tt.ReshowDelay = 250;
				tt.ShowAlways = true;

				if ((tip != null) && (tip != string.Empty)) {
					tt.SetToolTip(Control.FromHandle(handle), tip);
					tt.Active = true;
				} else {
					tt.Active = false;
				}

				SendNetClientMessage (SystrayMgrWindow,
						      Atoms._NET_SYSTEM_TRAY_OPCODE,
						      IntPtr.Zero,
						      (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK,
						      hwnd.WholeWindow);

				return true;
			}

			tt = null;
			return false;
		}
Ejemplo n.º 9
0
		internal override IntPtr CreateWindow (CreateParams cp)
		{
			XSetWindowAttributes	Attributes;
			Hwnd			hwnd;
			Hwnd			parent_hwnd = null;
			int			X;
			int			Y;
			int			Width;
			int			Height;
			IntPtr			ParentHandle;
			IntPtr			WholeWindow;
			IntPtr			ClientWindow;
			SetWindowValuemask	ValueMask;
			int[]			atoms;

			hwnd = new Hwnd();

			Attributes = new XSetWindowAttributes();
			X = cp.X;
			Y = cp.Y;
			Width = cp.Width;
			Height = cp.Height;

			if (Width<1) Width=1;
			if (Height<1) Height=1;

			if (cp.Parent != IntPtr.Zero) {
				parent_hwnd = Hwnd.ObjectFromHandle(cp.Parent);
				ParentHandle = parent_hwnd.client_window;
			} else {
				if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
					// We need to use our foster parent window until this poor child gets it's parent assigned
					ParentHandle=FosterParent;
				} else {
					ParentHandle=RootWindow;
				}
			}

			// Set the default location location for forms.
			Point next;
			if (cp.control is Form) {
				next = Hwnd.GetNextStackedFormLocation (cp, parent_hwnd);
				X = next.X;
				Y = next.Y;
			}
			ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;

			Attributes.bit_gravity = Gravity.NorthWestGravity;
			Attributes.win_gravity = Gravity.NorthWestGravity;

			// Save what's under the toolwindow
			if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
				Attributes.save_under = true;
				ValueMask |= SetWindowValuemask.SaveUnder;
			}


			// If we're a popup without caption we override the WM
			if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
				Attributes.override_redirect = true;
				ValueMask |= SetWindowValuemask.OverrideRedirect;
			}

			hwnd.x = X;
			hwnd.y = Y;
			hwnd.width = Width;
			hwnd.height = Height;
			hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
			hwnd.initial_style = cp.WindowStyle;
			hwnd.initial_ex_style = cp.WindowExStyle;

			if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
				hwnd.enabled = false;
			}

			ClientWindow = IntPtr.Zero;

			Size XWindowSize = TranslateWindowSizeToXWindowSize (cp);
			Rectangle XClientRect = TranslateClientRectangleToXClientRectangle (hwnd, cp.control);
				
			lock (XlibLock) {
				WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, XWindowSize.Width, XWindowSize.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
				if (WholeWindow != IntPtr.Zero) {
					ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);

					if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
						ValueMask = SetWindowValuemask.ColorMap;
						Attributes.colormap = CustomColormap;
					}
					ClientWindow = XCreateWindow(DisplayHandle, WholeWindow, XClientRect.X, XClientRect.Y, XClientRect.Width, XClientRect.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, CustomVisual, new UIntPtr ((uint)ValueMask), ref Attributes);
				}
			}

			if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
				throw new Exception("Could not create X11 windows");
			}

			hwnd.Queue = ThreadQueue(Thread.CurrentThread);
			hwnd.WholeWindow = WholeWindow;
			hwnd.ClientWindow = ClientWindow;

			DriverDebug("Created window {0:X} / {1:X} parent {2:X}, Style {3}, ExStyle {4}", ClientWindow.ToInt32(), WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0, (WindowStyles)cp.Style, (WindowExStyles)cp.ExStyle);
			
			if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
				if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
					XSizeHints	hints;

					hints = new XSizeHints();
					hints.x = X;
					hints.y = Y;
					hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
					XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
				}
			}

			lock (XlibLock) {
				XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
				if (hwnd.whole_window != hwnd.client_window)
					XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | Keyboard.KeyEventMask)));
			}

			if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST))
				SetTopmost(hwnd.whole_window, true);

			SetWMStyles(hwnd, cp);
			
			// set the group leader
			XWMHints wm_hints = new XWMHints ();
			
			wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
			wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
			wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
			
			if (ParentHandle != RootWindow) {
				wm_hints.window_group = hwnd.whole_window;
			} else {
				wm_hints.window_group = ParentHandle;
			}
			
			lock (XlibLock) {
				XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
			}

			if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
				SetWindowState(hwnd.Handle, FormWindowState.Minimized);
			} else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
				SetWindowState(hwnd.Handle, FormWindowState.Maximized);
			}

			// for now make all windows dnd enabled
			Dnd.SetAllowDrop (hwnd, true);

			// Set caption/window title
			Text(hwnd.Handle, cp.Caption);

			SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
			SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);

			if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
				hwnd.visible = true;
				MapWindow(hwnd, WindowType.Both);
				if (!(Control.FromHandle(hwnd.Handle) is Form))
					SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
			}

			return hwnd.Handle;
		}
Ejemplo n.º 10
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;
		}
Ejemplo n.º 11
0
		internal override bool SystrayAdd (IntPtr handle, string tip, Icon icon, out ToolTip tt)
		{
			GetSystrayManagerWindow ();
			
			if (SystrayMgrWindow != IntPtr.Zero) {
				uint[]		atoms;
				XSizeHints	size_hints;
				Hwnd		hwnd;
				
				hwnd = Hwnd.ObjectFromHandle (handle);
				#if DriverDebug
					Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
				#endif
				
				XUnmapWindow (DisplayHandle, hwnd.whole_window);
				XUnmapWindow (DisplayHandle, hwnd.client_window);
				
				// Oh boy.
				gdk_window_destroy (gdk_window_lookup (hwnd.client_window));
				hwnd.client_window = hwnd.whole_window;
				
				size_hints = new XSizeHints ();
				
				size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
				size_hints.min_width = icon.Width;
				size_hints.min_height = icon.Height;
				
				size_hints.max_width = icon.Width;
				size_hints.max_height = icon.Height;
				
				size_hints.base_width = icon.Width;
				size_hints.base_height = icon.Height;
				XSetWMNormalHints (DisplayHandle, hwnd.whole_window, ref size_hints);
				
				atoms = new uint [2];
				atoms [0] = 1;	// Version 1
				atoms [1] = 0;	// We're not mapped
				
				// This line cost me 3 days...
				XChangeProperty (DisplayHandle, hwnd.whole_window, NetAtoms [(int)NA._XEMBED_INFO], NetAtoms [(int)NA._XEMBED_INFO], 32, PropertyMode.Replace, atoms, 2);
				
				// Need to pick some reasonable defaults
				tt = new ToolTip ();
				tt.AutomaticDelay = 100;
				tt.InitialDelay = 250;
				tt.ReshowDelay = 250;
				tt.ShowAlways = true;
				
				if ((tip != null) && (tip != string.Empty)) {
					tt.SetToolTip (Control.FromHandle (handle), tip);
					tt.Active = true;
				} else {
					tt.Active = false;
				}
				
				// Make sure the window exists
				XSync (DisplayHandle, hwnd.whole_window);
				
				SendNetClientMessage (SystrayMgrWindow, (IntPtr)NetAtoms [(int)NA._NET_SYSTEM_TRAY_OPCODE], IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
				return true;
			}
			
			tt = null;
			return false;
		}
Ejemplo n.º 12
0
		internal override void SetWindowMinMax (IntPtr handle, Rectangle maximized, Size min, Size max)
		{
			Hwnd		hwnd;
			XSizeHints	hints;
			
			hwnd = Hwnd.ObjectFromHandle (handle);
			if (hwnd == null) {
				return;
			}
			
			hints = new XSizeHints ();
			
			if (min != Size.Empty) {
				hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
				hints.min_width = min.Width;
				hints.min_height = min.Height;
			}
			
			if (max != Size.Empty) {
				hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
				hints.max_width = max.Width;
				hints.max_height = max.Height;
			}
			
			XSetWMNormalHints (DisplayHandle, hwnd.whole_window, ref hints);
			
			if (maximized != Rectangle.Empty) {
				hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
				hints.x = maximized.X;
				hints.y = maximized.Y;
				hints.width = maximized.Width;
				hints.height = maximized.Height;
				
				// Metacity does not seem to follow this constraint for maximized (zoomed) windows
				XSetZoomHints (DisplayHandle, hwnd.whole_window, ref hints);
			}
		}
Ejemplo n.º 13
0
		public virtual void CreateWindow (CreateParams cp)
		{
			if (WholeWindow != IntPtr.Zero || ClientWindow != IntPtr.Zero)
				throw new Exception ("createwindow called a second time on live X11Hwnd");

			XSetWindowAttributes	Attributes;
			int			x;
			int			y;
			int			width;
			int			height;
			IntPtr			ParentHandle;
			SetWindowValuemask	ValueMask;

			Attributes = new XSetWindowAttributes();
			x = cp.X;
			y = cp.Y;
			width = cp.Width;
			height = cp.Height;
			initial_ex_style = (WindowExStyles) cp.ExStyle;

			/* Figure out our parent handle */
			if (cp.Parent != IntPtr.Zero)
				// the parent handle is specified in the CreateParams
				ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).ClientWindow;
			else if (StyleSet (cp.Style, WindowStyles.WS_CHILD))
				// a child control with an unassigned parent gets created under the FosterParent
				ParentHandle = display.FosterParent.Handle;
			else
				// for all other cases, the parent is the root window
				ParentHandle = display.RootWindow.Handle;

			ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;

			Attributes.bit_gravity = Gravity.NorthWestGravity;
			Attributes.win_gravity = Gravity.NorthWestGravity;

			// Save what's under the toolwindow
			if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
				Attributes.save_under = true;
				ValueMask |= SetWindowValuemask.SaveUnder;
			}

			// If we're a popup without caption we override the WM
			if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
				Attributes.override_redirect = true;
				ValueMask |= SetWindowValuemask.OverrideRedirect;
			}

			// Default position on screen, if window manager doesn't place us somewhere else
			if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)
			    && !StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
				if (x<0) x = 50;
				if (y<0) y = 50;
			}
			// minimum width/height
			if (width<1) width=1;
			if (height<1) height=1;

			X = x;
			Y = y;
			Width = width;
			Height = height;
			Parent = Hwnd.ObjectFromHandle (cp.Parent);

			Enabled = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);

			ClientWindow = IntPtr.Zero;

			WholeWindow = Xlib.XCreateWindow (display.Handle, ParentHandle,
							  X, Y, Width, Height, 0,
							  (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput,
							  IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
			if (WholeWindow == IntPtr.Zero)
				throw new Exception ("Coult not create X11 nc window");

			ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);

			if (display.CustomVisual != IntPtr.Zero && display.CustomColormap != IntPtr.Zero) {
				ValueMask |= SetWindowValuemask.ColorMap;
				Attributes.colormap = display.CustomColormap;
			}

			ClientWindow = Xlib.XCreateWindow (display.Handle, WholeWindow,
							   ClientRect.X, ClientRect.Y, ClientRect.Width, ClientRect.Height, 0,
							   (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput,
							   display.CustomVisual, new UIntPtr ((uint)ValueMask), ref Attributes);

			if (ClientWindow == IntPtr.Zero)
				throw new Exception("Could not create X11 client window");

#if DriverDebug || DriverDebugCreate
			Console.WriteLine("Created window {0:X} / {1:X} parent {2:X}, Style {3}, ExStyle {4}", ClientWindow.ToInt32(), WholeWindow.ToInt32(), Parent != null ? Parent.Handle.ToInt32() : 0, (WindowStyles)cp.Style, (WindowExStyles)cp.ExStyle);
#endif

			if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
				if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
					XSizeHints	hints;

					hints = new XSizeHints();
					hints.x = X;
					hints.y = Y;
					hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
					Xlib.XSetWMNormalHints (display.Handle, WholeWindow, ref hints);
				}
			}

			Xlib.XSelectInput (display.Handle, WholeWindow, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
			if (WholeWindow != ClientWindow)
				Xlib.XSelectInput (display.Handle, ClientWindow, new IntPtr ((int)SelectInputMask));

			if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
				WINDOW_TYPE = display.Atoms._NET_WM_WINDOW_TYPE_NORMAL;
				Xlib.XSetTransientForHint (display.Handle, WholeWindow, display.RootWindow.Handle);
			}

			SetWMStyles (cp);
			
			// set the group leader
			XWMHints wm_hints = new XWMHints ();
			
			wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
			wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
			wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
			wm_hints.window_group = ParentHandle == display.RootWindow.Handle ? ParentHandle : WholeWindow;
			
			Xlib.XSetWMHints (display.Handle, WholeWindow, ref wm_hints );

			if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE))
				SetWindowState (FormWindowState.Minimized);
			else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE))
				SetWindowState (FormWindowState.Maximized);

			// for now make all windows dnd enabled
			display.Dnd.SetAllowDrop (this, true);

			// Set caption/window title
			Text = cp.Caption;

			display.SendMessage (Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
                        SendParentNotify (Msg.WM_CREATE, int.MaxValue, int.MaxValue);

			if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
				visible = true;
				Map ();
				if (!(Control.FromHandle(Handle) is Form))
					display.SendMessage (Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
			}
		}
Ejemplo n.º 14
0
		public void SetMinMax (Rectangle maximized, Size min, Size max)
		{
			XSizeHints	hints;
			IntPtr		dummy;

			hints = new XSizeHints();

			Xlib.XGetWMNormalHints (display.Handle, WholeWindow, ref hints, out dummy);
			if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
				hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
				hints.min_width = min.Width;
				hints.min_height = min.Height;
			}

			if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
				hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
				hints.max_width = max.Width;
				hints.max_height = max.Height;
			}

			if (hints.flags != IntPtr.Zero)
				Xlib.XSetWMNormalHints (display.Handle, WholeWindow, ref hints);

			if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
				hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
				hints.x = maximized.X;
				hints.y = maximized.Y;
				hints.width = maximized.Width;
				hints.height = maximized.Height;

				// Metacity does not seem to follow this constraint for maximized (zoomed) windows
				Xlib.XSetZoomHints (display.Handle, WholeWindow, ref hints);
			}
		}
Ejemplo n.º 15
-1
		internal static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints)
		{
			DebugHelper.TraceWriteLine ("XSetZoomHints");
			_XSetZoomHints(display, window, ref hints);
		}