internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
void SetWMStyles(Hwnd hwnd, CreateParams cp) { MotifWmHints mwmHints; MotifFunctions functions; MotifDecorations decorations; int[] atoms; int atom_count; Rectangle client_rect; Form form; IntPtr window_type; bool hide_from_taskbar; IntPtr transient_for_parent; // Windows we manage ourselves don't need WM window styles. if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) { return; } atoms = new int[8]; mwmHints = new MotifWmHints(); functions = 0; decorations = 0; window_type = _NET_WM_WINDOW_TYPE_NORMAL; transient_for_parent = IntPtr.Zero; mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations); mwmHints.functions = (IntPtr)0; mwmHints.decorations = (IntPtr)0; form = cp.control as Form; if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) { /* tool windows get no window manager decorations. */ /* just because the window doesn't get any decorations doesn't mean we should disable the functions. for instance, without MotifFunctions.Maximize, changing the windowstate to Maximized is ignored by metacity. */ functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize; } else if (form != null && form.FormBorderStyle == FormBorderStyle.None) { /* allow borderless window to be maximized */ functions |= MotifFunctions.All | MotifFunctions.Resize; } else { if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) { functions |= MotifFunctions.Move; decorations |= MotifDecorations.Title | MotifDecorations.Menu; } if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) { functions |= MotifFunctions.Move | MotifFunctions.Resize; decorations |= MotifDecorations.Border | MotifDecorations.ResizeH; } if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) { functions |= MotifFunctions.Minimize; decorations |= MotifDecorations.Minimize; } if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) { functions |= MotifFunctions.Maximize; decorations |= MotifDecorations.Maximize; } if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) { functions |= MotifFunctions.Resize; decorations |= MotifDecorations.ResizeH; } if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) { decorations |= MotifDecorations.Border; } if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) { decorations |= MotifDecorations.Border; } if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) { decorations |= MotifDecorations.Border; } if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) { functions |= MotifFunctions.Close; } else { functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close); decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize); if (cp.Caption == "") { functions &= ~MotifFunctions.Move; decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH); } } } if ((functions & MotifFunctions.Resize) == 0) { hwnd.fixed_size = true; Rectangle fixed_rectangle = new Rectangle (cp.X, cp.Y, cp.Width, cp.Height); SetWindowMinMax(hwnd.Handle, fixed_rectangle, fixed_rectangle.Size, fixed_rectangle.Size, cp); } else { hwnd.fixed_size = false; } mwmHints.functions = (IntPtr)functions; mwmHints.decorations = (IntPtr)decorations; DriverDebug ("SetWMStyles ({0}, {1}) functions = {2}, decorations = {3}", hwnd, cp, functions, decorations); if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) { // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy // and get those windows in front of their parents window_type = _NET_WM_WINDOW_TYPE_UTILITY; } else { window_type = _NET_WM_WINDOW_TYPE_NORMAL; } if (!cp.IsSet (WindowExStyles.WS_EX_APPWINDOW)) { hide_from_taskbar = true; } else if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW) && form != null && form.Parent != null && !form.ShowInTaskbar) { hide_from_taskbar = true; } else { hide_from_taskbar = false; } if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) { if (form != null && !hwnd.reparented) { if (form.Owner != null && form.Owner.Handle != IntPtr.Zero) { Hwnd owner_hwnd = Hwnd.ObjectFromHandle (form.Owner.Handle); if (owner_hwnd != null) transient_for_parent = owner_hwnd.whole_window; } } } if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) { transient_for_parent = hwnd.parent.whole_window; } FormWindowState current_state = GetWindowState (hwnd.Handle); if (current_state == (FormWindowState)(-1)) current_state = FormWindowState.Normal; client_rect = TranslateClientRectangleToXClientRectangle (hwnd); lock (XlibLock) { atom_count = 0; atoms [0] = window_type.ToInt32 (); XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1); XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5); if (transient_for_parent != IntPtr.Zero) { XSetTransientForHint (DisplayHandle, hwnd.whole_window, transient_for_parent); } MoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height); if (hide_from_taskbar) { /* this line keeps the window from showing up in gnome's taskbar */ atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32(); } /* we need to add these atoms in the * event we're maximized, since we're * replacing the existing * _NET_WM_STATE here. If we don't * add them, future calls to * GetWindowState will return Normal * for a window which is maximized. */ if (current_state == FormWindowState.Maximized) { atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32(); atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32(); } if (form != null && form.Modal) { atoms[atom_count++] = _NET_WM_STATE_MODAL.ToInt32 (); } XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count); atom_count = 0; IntPtr[] atom_ptrs = new IntPtr[2]; atom_ptrs[atom_count++] = WM_DELETE_WINDOW; if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) { atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP; } XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count); } }
internal static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements) { DebugHelper.TraceWriteLine ("XChangeProperty"); return _XChangeProperty(display, window, property, type, format, mode, ref data, nelements); }
public void SetWMStyles (CreateParams cp) { MotifWmHints mwmHints; MotifFunctions functions; MotifDecorations decorations; IntPtr[] atoms; int atom_count; Rectangle client_rect; // Child windows don't need WM window styles if (StyleSet (cp.Style, WindowStyles.WS_CHILDWINDOW)) return; atoms = new IntPtr[8]; mwmHints = new MotifWmHints(); functions = 0; decorations = 0; mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations); mwmHints.functions = (IntPtr)0; mwmHints.decorations = (IntPtr)0; if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW) || !StyleSet (cp.Style, WindowStyles.WS_CAPTION | WindowStyles.WS_BORDER | WindowStyles.WS_DLGFRAME)) { /* tool windows get no window manager decorations, and neither do windows which lack CAPTION/BORDER/DLGFRAME styles. */ /* just because the window doesn't get any decorations doesn't mean we should disable the functions. for instance, without MotifFunctions.Maximize, changing the windowstate to Maximized is ignored by metacity. */ functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize; } else { if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) { functions |= MotifFunctions.Move; decorations |= MotifDecorations.Title | MotifDecorations.Menu; } if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) { functions |= MotifFunctions.Move | MotifFunctions.Resize; decorations |= MotifDecorations.Border | MotifDecorations.ResizeH; } if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) { functions |= MotifFunctions.Minimize; decorations |= MotifDecorations.Minimize; } if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) { functions |= MotifFunctions.Maximize; decorations |= MotifDecorations.Maximize; } if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) { functions |= MotifFunctions.Resize; decorations |= MotifDecorations.ResizeH; } if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) { decorations |= MotifDecorations.Border; } if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) { decorations |= MotifDecorations.Border; } if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) { decorations |= MotifDecorations.Border; } if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) { functions |= MotifFunctions.Close; } else { functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close); decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize); if (cp.Caption == "") { functions &= ~MotifFunctions.Move; decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH); } } } if ((functions & MotifFunctions.Resize) == 0) { fixed_size = true; SetMinMax (new Rectangle(cp.X, cp.Y, cp.Width, cp.Height), new Size(cp.Width, cp.Height), new Size(cp.Width, cp.Height)); } else { fixed_size = false; } mwmHints.functions = (IntPtr)functions; mwmHints.decorations = (IntPtr)decorations; FormWindowState current_state = GetWindowState (); if (current_state == (FormWindowState)(-1)) current_state = FormWindowState.Normal; client_rect = ClientRect; atom_count = 0; // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy // and get those windows in front of their parents if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) { WINDOW_TYPE = display.Atoms._NET_WM_WINDOW_TYPE_UTILITY; Form f = Control.FromHandle(Handle) as Form; if (f != null && !reparented) { if (f.Owner != null && f.Owner.Handle != IntPtr.Zero) { Hwnd owner_hwnd = Hwnd.ObjectFromHandle(f.Owner.Handle); if (owner_hwnd != null) Xlib.XSetTransientForHint (display.Handle, WholeWindow, owner_hwnd.WholeWindow); } } } Xlib.XChangeProperty (display.Handle, WholeWindow, display.Atoms._MOTIF_WM_HINTS, display.Atoms._MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5); if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (parent != null) && (parent.WholeWindow != IntPtr.Zero)) { WINDOW_TYPE = display.Atoms._NET_WM_WINDOW_TYPE_NORMAL; Xlib.XSetTransientForHint(display.Handle, WholeWindow, parent.WholeWindow); } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) { /* this line keeps the window from showing up in gnome's taskbar */ atoms[atom_count++] = display.Atoms._NET_WM_STATE_SKIP_TASKBAR; } if ((client_rect.Width < 1) || (client_rect.Height < 1)) { Xlib.XMoveResizeWindow (display.Handle, ClientWindow, -5, -5, 1, 1); } else { Xlib.XMoveResizeWindow (display.Handle, ClientWindow, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height); } if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) atoms[atom_count++] = display.Atoms._NET_WM_STATE_SKIP_TASKBAR; /* we need to add these atoms in the * event we're maximized, since we're * replacing the existing * _NET_WM_STATE here. If we don't * add them, future calls to * GetWindowState will return Normal * for a window which is maximized. */ if (current_state == FormWindowState.Maximized) { atoms[atom_count++] = display.Atoms._NET_WM_STATE_MAXIMIZED_HORZ; atoms[atom_count++] = display.Atoms._NET_WM_STATE_MAXIMIZED_VERT; } Set_WM_STATE (atoms, atom_count); atom_count = 0; atoms[atom_count++] = display.Atoms.WM_DELETE_WINDOW; if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) atoms[atom_count++] = display.Atoms._NET_WM_CONTEXT_HELP; Xlib.XSetWMProtocols (display.Handle, WholeWindow, atoms, atom_count); }