private 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;
#if debug
Console.WriteLine ("SetWMStyles ({0}, {1}) functions = {2}, decorations = {3}", hwnd, cp, functions, decorations);
#endif
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);
}
}