// Set this cursor on a widget. internal void SetCursor(Widget widget) { Display dpy = widget.dpy; try { IntPtr display = dpy.Lock(); XWindow window = widget.GetWidgetHandle(); if (source != null) { if (cursor == XCursor.Zero) { XColor foreground = new XColor(); foreground.red = (ushort)0; foreground.green = (ushort)0; foreground.blue = (ushort)0; foreground.flags = (XColor.DoRed | XColor.DoGreen | XColor.DoBlue); XColor background = new XColor(); background.red = (ushort)0xFFFF; background.green = (ushort)0xFFFF; background.blue = (ushort)0xFFFF; background.flags = (XColor.DoRed | XColor.DoGreen | XColor.DoBlue); if (reverse) { cursor = Xlib.XCreatePixmapCursor (display, source.GetPixmapHandle(), mask.GetPixmapHandle(), ref background, ref foreground, (uint)hotspotX, (uint)hotspotY); } else { cursor = Xlib.XCreatePixmapCursor (display, source.GetPixmapHandle(), mask.GetPixmapHandle(), ref foreground, ref background, (uint)hotspotX, (uint)hotspotY); } } Xlib.XDefineCursor(display, window, cursor); } else if (type == CursorType.XC_inherit_parent) { Xlib.XUndefineCursor(display, window); } else { Xlib.XDefineCursor (display, window, dpy.GetCursor(type)); } } finally { dpy.Unlock(); } }
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; }
public WindowManager(SimpleLogger.LogLevel level) { this.Log = new SimpleLogger(level); var pDisplayText = Xlib.XDisplayName(null); var DisplayText = Marshal.PtrToStringAnsi(pDisplayText); if (DisplayText == String.Empty) { Log.Error("No display configured for X11; check the value of the DISPLAY variable is set correctly"); Environment.Exit(1); } Log.Info($"Connecting to X11 Display {DisplayText}"); this.display = Xlib.XOpenDisplay(null); if (display == IntPtr.Zero) { Log.Error("Unable to open the default X display"); Environment.Exit(1); } this.root = Xlib.XDefaultRootWindow(display); OnError = this.ErrorHandler; Xlib.XSetErrorHandler(OnError); // This will trigger a bad access error if another window manager is already running Xlib.XSelectInput(this.display, this.root, EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask | EventMask.ButtonPressMask | EventMask.KeyPressMask); Xlib.XSync(this.display, false); // Setup cursors this.Cursors.DefaultCursor = Xlib.XCreateFontCursor(this.display, FontCursor.XC_left_ptr); this.Cursors.TitleCursor = Xlib.XCreateFontCursor(this.display, FontCursor.XC_fleur); this.Cursors.FrameCursor = Xlib.XCreateFontCursor(this.display, FontCursor.XC_sizing); Xlib.XDefineCursor(this.display, this.root, this.Cursors.DefaultCursor); // Setup colours this.Colours.DesktopBackground = GetPixelByName("black"); this.Colours.WindowBackground = GetPixelByName("white"); this.Colours.InactiveTitleBorder = GetPixelByName("light slate grey"); this.Colours.InactiveTitleColor = GetPixelByName("slate grey"); this.Colours.InactiveFrameColor = GetPixelByName("dark slate grey"); this.Colours.ActiveFrameColor = GetPixelByName("dark goldenrod"); this.Colours.ActiveTitleColor = GetPixelByName("gold"); this.Colours.ActiveTitleBorder = GetPixelByName("saddle brown"); Xlib.XSetWindowBackground(this.display, this.root, this.Colours.DesktopBackground); Xlib.XClearWindow(this.display, this.root); // force a redraw with the new background color }