private void AddFrame(Window child) { const int frame_width = 3; const int title_height = 20; const int inner_border = 1; if (this.WindowIndexByClient.ContainsKey(child)) { return; // Window has already been framed. } var Name = String.Empty; Xlib.XFetchName(this.display, child, ref Name); Log.Debug($"Framing {Name}"); Xlib.XGetWindowAttributes(this.display, child, out var attr); var title = Xlib.XCreateSimpleWindow(this.display, this.root, attr.x, attr.y, attr.width - (2 * inner_border), (title_height - 2 * inner_border), inner_border, this.Colours.InactiveTitleColor, this.Colours.InactiveTitleBorder); // Try to keep the child window in the same place, unless this would push the window decorations off screen. var adjusted_x_loc = (attr.x - frame_width < 0) ? 0 : attr.x - frame_width; var adjusted_y_loc = (attr.y - (title_height + frame_width) < 0) ? 0 : (attr.y - (title_height + frame_width)); var frame = Xlib.XCreateSimpleWindow(this.display, this.root, adjusted_x_loc, adjusted_y_loc, attr.width, attr.height + title_height, 3, this.Colours.InactiveFrameColor, this.Colours.WindowBackground); Xlib.XSelectInput(this.display, title, EventMask.ButtonPressMask | EventMask.ButtonReleaseMask | EventMask.Button1MotionMask | EventMask.ExposureMask); Xlib.XSelectInput(this.display, frame, EventMask.ButtonPressMask | EventMask.ButtonReleaseMask | EventMask.Button1MotionMask | EventMask.FocusChangeMask | EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask); Xlib.XDefineCursor(this.display, title, this.Cursors.TitleCursor); Xlib.XDefineCursor(this.display, frame, this.Cursors.FrameCursor); Xlib.XReparentWindow(this.display, title, frame, 0, 0); Xlib.XReparentWindow(this.display, child, frame, 0, title_height); Xlib.XMapWindow(this.display, title); Xlib.XMapWindow(this.display, frame); // Ensure the child window survives the untimely death of the window manager. Xlib.XAddToSaveSet(this.display, child); // Grab left click events from the client, so we can focus & raise on click SetFocusTrap(child); var wg = new WindowGroup { child = child, frame = frame, title = title }; this.WindowIndexByClient[child] = wg; this.WindowIndexByTitle[title] = wg; this.WindowIndexByFrame[frame] = wg; }