// Set the handle for this drawable, assuming it is a widget. internal void SetWidgetHandle(XWindow handle) { try { dpy.Lock(); this.handle = (XDrawable)handle; dpy.handleMap[handle] = (Widget)this; } finally { dpy.Unlock(); } }
// Internal constructor that wraps a bitmap XID. internal Bitmap(Display dpy, Screen screen, XPixmap pixmap) : base(dpy, screen, DrawableKind.Bitmap) { SetPixmapHandle(pixmap); try { // Get the geometry of the pixmap from the X server. IntPtr display = dpy.Lock(); XWindow root_return; Xlib.Xint x_return, y_return; Xlib.Xuint width_return, height_return; Xlib.Xuint border_width_return, depth_return; Xlib.XGetGeometry (display, handle, out root_return, out x_return, out y_return, out width_return, out height_return, out border_width_return, out depth_return); this.width = (int)width_return; this.height = (int)height_return; } finally { dpy.Unlock(); } }
// 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(); } }
// Convert an RGB color value into a pixel using this colormap. // This assumes that standard colors have already been expanded. internal XPixel RGBToPixel(Color color) { try { // Acquire the display lock. IntPtr display = dpy.Lock(); // Do we already have a cached pixel value for this color? Object cached = cachedPixels[color]; if (cached != null) { return((XPixel)(cached)); } // Try to allocate the color from the X display server. XColor xcolor; int red = color.Red; int green = color.Green; int blue = color.Blue; xcolor.pixel = XPixel.Zero; xcolor.red = (ushort)(red << 8); xcolor.green = (ushort)(green << 8); xcolor.blue = (ushort)(blue << 8); xcolor.flags = (sbyte)(XColor.DoRed | XColor.DoGreen | XColor.DoBlue); xcolor.pad = (sbyte)0; if (Xlib.XAllocColor(display, colormap, ref xcolor) != 0) { // Cache the value for next time. cachedPixels[color] = xcolor.pixel; return(xcolor.pixel); } // TODO: do a closest color match for the color. // Last ditch: return black or white depending upon // the intensity of the color. if (((color.Red * 54 + color.Green * 183 + color.Blue * 19) / 256) < 128) { return(Xlib.XBlackPixelOfScreen(screen.screen)); } else { return(Xlib.XWhitePixelOfScreen(screen.screen)); } } finally { dpy.Unlock(); } }
/// <summary> /// <para>Send a wakeup message to the event queue for this screen.</para> /// </summary> /// /// <remarks> /// <para>Wakeup messages are sent from one thread to the event queue /// thread, to cause the event queue to stop blocking and return back to /// the caller. The wakeup message involves a round trip to the /// X server, so it should be used sparingly.</para> /// </remarks> public void Wakeup() { try { IntPtr display = dpy.Lock(); Xlib.XSharpSendWakeup (display, placeholder.GetWidgetHandle()); } finally { dpy.Unlock(); } }
internal IntPtr GetFontSet(Display dpy, out FontExtents extents) { lock(typeof(Font)) { // Map this object to the one that actually stores // the font set information. Font font = (Font)(dpy.fonts[this]); if(font == null) { font = this; dpy.fonts[this] = this; } // Search for existing font set information. FontInfo info = font.infoList; while(info != null) { if(info.dpy == dpy) { extents = info.extents; return info.fontSet; } info = info.next; } // Create a new font set. IntPtr fontSet; int ascent, descent, maxWidth; try { IntPtr display = dpy.Lock(); fontSet = CreateFontSet (display, out ascent, out descent, out maxWidth); if(fontSet == IntPtr.Zero) { extents = null; return IntPtr.Zero; } } finally { dpy.Unlock(); } // Associate the font set with the display. info = new FontInfo(); info.next = font.infoList; info.extents = new FontExtents(ascent, descent, maxWidth); info.dpy = dpy; info.fontSet = fontSet; font.infoList = info; // Return the font set to the caller. extents = info.extents; return fontSet; } }
// Internal constructor that wraps a pixmap XID. internal Pixmap(Display dpy, Screen screen, XPixmap pixmap) : base(dpy, screen, DrawableKind.Bitmap) { SetPixmapHandle(pixmap); try { // Get the geometry of the pixmap from the X server. IntPtr display = dpy.Lock(); XWindow root_return; Xlib.Xint x_return, y_return; Xlib.Xuint width_return, height_return; Xlib.Xuint border_width_return, depth_return; Xlib.XGetGeometry (display, handle, out root_return, out x_return, out y_return, out width_return, out height_return, out border_width_return, out depth_return); this.width = (int)width_return; this.height = (int)height_return; } finally { dpy.Unlock(); } }
// Determine if the X server supports embedding - inner version. // "displayName" will be set to a non-null value if it is necessary // to redirect the DISPLAY environment variable elsewhere. private static bool CanEmbed(Display display, bool reportErrors, out String displayName) { IntPtr dpy; Xlib.Xint major, minor; String client; int index; displayName = null; try { dpy = display.Lock(); // See if the X server supports XC-APPGROUP and SECURITY. if(Xlib.XagQueryVersion(dpy, out major, out minor) == XBool.False) { if(reportErrors && !errorReported) { Console.Error.WriteLine ("The X server `{0}' does not support the " + "XC-APPGROUP extension,", display.displayName); Console.Error.WriteLine ("which is required for application " + "embedding."); errorReported = true; } return false; } if(Xlib.XSecurityQueryExtension(dpy, out major, out minor) == XBool.False) { if(reportErrors && !errorReported) { Console.Error.WriteLine ("The X server `{0}' does not support the " + "SECURITY extension,", display.displayName); Console.Error.WriteLine ("which is required for for application " + "embedding."); errorReported = true; } return false; } // If we are in an ssh shell account, then we cannot // connect via ssh's X11 forwarding mechanism as it // does not know how to proxy appgroup security tokens. // Try to discover where the ssh client actually lives. displayName = Environment.GetEnvironmentVariable ("XREALDISPLAY"); client = Environment.GetEnvironmentVariable("SSH_CLIENT"); if(displayName != null && displayName.Length > 0) { // The user specified a display override with // the XREALDISPLAY environment variable. if(!ProbeDisplay(displayName, reportErrors)) { displayName = null; return false; } } else if(client != null && client.Length > 0) { // Synthesize a display name from the ssh client name. index = client.IndexOf(' '); if(index == -1) { index = client.Length; } displayName = client.Substring(0, index) + ":0.0"; if(!ProbeDisplay(displayName, reportErrors)) { displayName = null; return false; } } else if(Environment.GetEnvironmentVariable("SSH_ASKPASS") != null || Environment.GetEnvironmentVariable("SSH_TTY") != null) { // Older versions of bash do not export SSH_CLIENT // within an ssh login session. if(reportErrors && !errorReported) { Console.Error.WriteLine ("The `SSH_CLIENT' environment variable " + "is not exported from the shell."); Console.Error.WriteLine ("Either export `SSH_CLIENT' or set the " + "`XREALDISPLAY' environment"); Console.Error.WriteLine ("variable to the name of the real " + "X display."); errorReported = true; } displayName = null; return false; } else { // No ssh, so use the original "DISPLAY" value as-is. displayName = null; } } catch(MissingMethodException) { displayName = null; return false; } catch(DllNotFoundException) { displayName = null; return false; } catch(EntryPointNotFoundException) { displayName = null; return false; } finally { display.Unlock(); } return true; }
// Activate timers that have fired on a particular display. // We assume that this is called with the display lock. internal static bool ActivateTimers(Display dpy) { // Bail out early if there are no timers, to avoid // calling "DateTime.UtcNow" if we don't need to. if(dpy.timerQueue == null) { return false; } DateTime now = DateTime.UtcNow; Timer timer; DateTime next; bool activated = false; for(;;) { // Remove the first timer from the queue if // it has expired. Bail out if it hasn't. timer = dpy.timerQueue; if(timer == null) { break; } else if(timer.nextDue <= now) { timer.RemoveTimer(); } else { break; } // Invoke the timer's callback delegate. activated = true; if(timer.callback is TimerCallback) { TimerCallback cb1 = timer.callback as TimerCallback; dpy.Unlock(); try { cb1(timer.state); } finally { dpy.Lock(); } } else { EventHandler cb2 = timer.callback as EventHandler; dpy.Unlock(); try { cb2(timer.state, EventArgs.Empty); } finally { dpy.Lock(); } } // Add the timer back onto the queue if necessary. if(!timer.stopped && !timer.onDisplayQueue) { if(timer.period < 0) { timer.stopped = true; } else { next = timer.nextDue + new TimeSpan(timer.period * TimeSpan.TicksPerMillisecond); // if the next due is less than now, the date/time may have changed. // since the timer expired right now the next due might be now + period if(next <= now) { next += new TimeSpan (((((Int64)(now - next).TotalMilliseconds) / timer.period) + 1) * timer.period * TimeSpan.TicksPerMillisecond); } /* do not increment here, since the time might have changed with years this would do a long loop here while(next <= now) { next += new TimeSpan (timer.period * TimeSpan.TicksPerMillisecond); } */ timer.nextDue = next; timer.AddTimer(); } } } return activated; }
// Activate timers that have fired on a particular display. // We assume that this is called with the display lock. internal static bool ActivateTimers(Display dpy) { // Bail out early if there are no timers, to avoid // calling "DateTime.UtcNow" if we don't need to. if (dpy.timerQueue == null) { return(false); } DateTime now = DateTime.UtcNow; Timer timer; DateTime next; bool activated = false; for (;;) { // Remove the first timer from the queue if // it has expired. Bail out if it hasn't. timer = dpy.timerQueue; if (timer == null) { break; } else if (timer.nextDue <= now) { timer.RemoveTimer(); } else { break; } // Invoke the timer's callback delegate. activated = true; if (timer.callback is TimerCallback) { TimerCallback cb1 = timer.callback as TimerCallback; dpy.Unlock(); try { cb1(timer.state); } finally { dpy.Lock(); } } else { EventHandler cb2 = timer.callback as EventHandler; dpy.Unlock(); try { cb2(timer.state, EventArgs.Empty); } finally { dpy.Lock(); } } // Add the timer back onto the queue if necessary. if (!timer.stopped && !timer.onDisplayQueue) { if (timer.period < 0) { timer.stopped = true; } else { next = timer.nextDue + new TimeSpan(timer.period * TimeSpan.TicksPerMillisecond); // if the next due is less than now, the date/time may have changed. // since the timer expired right now the next due might be now + period if (next <= now) { next += new TimeSpan (((((Int64)(now - next).TotalMilliseconds) / timer.period) + 1) * timer.period * TimeSpan.TicksPerMillisecond); } /* * do not increment here, since the time might have changed with years * this would do a long loop here * * while(next <= now) * { * next += new TimeSpan * (timer.period * * TimeSpan.TicksPerMillisecond); * } */ timer.nextDue = next; timer.AddTimer(); } } } return(activated); }
/// <summary> /// <para>Constructs a new <see cref="T:Xsharp.Graphics"/> object and /// attaches it to a <see cref="T:Xsharp.Drawable"/> instance.</para> /// </summary> /// /// <param name="drawable"> /// <para>The drawable to attach this graphics context to. If the /// drawable is a widget, the foreground and background colors of the /// graphics object will be initially set to the widget's standard /// foreground and background colors.</para> /// </param> /// /// <exception cref="T:System.ArgumentNullException"> /// <para>Raised if <paramref name="drawable"/> is <see langword="null"/>. /// </para> /// </exception> /// /// <exception cref="T:Xsharp.XInvalidOperationException"> /// <para>Raised if <paramref name="drawable"/> does not support /// output, is disposed, or is the root window.</para> /// </exception> public Graphics(Drawable drawable) { if(drawable == null) { throw new ArgumentNullException("drawable"); } else if(drawable.Kind == DrawableKind.InputOnlyWidget) { throw new XInvalidOperationException (S._("X_GraphicsIsOutputOnly")); } else if(drawable is RootWindow) { throw new XInvalidOperationException (S._("X_NonRootOperation")); } dpy = drawable.dpy; this.drawable = drawable; XGCValues gcValues = new XGCValues(); InputOutputWidget widget = (drawable as InputOutputWidget); DoubleBuffer buffer = (drawable as DoubleBuffer); Bitmap bitmap = (drawable as Bitmap); if(widget != null) { foreground = widget.Foreground; background = widget.Background; } else if(buffer != null) { foreground = buffer.Widget.Foreground; background = buffer.Widget.Background; } else if(bitmap != null) { foreground = new Color(0x00, 0x00, 0x00); background = new Color(0xFF, 0xFF, 0xFF); } else { foreground = new Color (StandardColor.Foreground); background = new Color (StandardColor.Background); } gcValues.foreground = drawable.ToPixel(foreground); gcValues.background = drawable.ToPixel(background); if(drawable is DoubleBuffer) { ((DoubleBuffer)drawable).Start(this); } try { IntPtr display = dpy.Lock(); drawableHandle = drawable.GetGCHandle(); gc = drawable.screen.GetGC(bitmap != null); if(gc == IntPtr.Zero) { // Create a new GC because the cache is empty. gc = Xlib.XCreateGC(display, drawableHandle, (uint)(GCValueMask.GCForeground | GCValueMask.GCBackground), ref gcValues); if(gc == IntPtr.Zero) { Display.OutOfMemory(); } } else { // Reset the cached GC back to the default settings. // Xlib will take care of stripping the list down // to just the changes that need to be applied. gcValues.function = Xsharp.GCFunction.GXcopy; gcValues.plane_mask = ~((XPixel)0); gcValues.line_width = 0; gcValues.line_style = Xsharp.LineStyle.LineSolid; gcValues.cap_style = Xsharp.CapStyle.CapButt; gcValues.join_style = Xsharp.JoinStyle.JoinMiter; gcValues.fill_style = Xsharp.FillStyle.FillSolid; gcValues.fill_rule = Xsharp.FillRule.EvenOddRule; gcValues.arc_mode = Xsharp.ArcMode.ArcPieSlice; gcValues.ts_x_origin = 0; gcValues.ts_y_origin = 0; gcValues.subwindow_mode = Xsharp.SubwindowMode.ClipByChildren; gcValues.graphics_exposures = true; gcValues.clip_x_origin = 0; gcValues.clip_y_origin = 0; gcValues.clip_mask = XPixmap.Zero; gcValues.dash_offset = 0; gcValues.dashes = (sbyte)4; Xlib.XChangeGC(display, gc, (uint)(GCValueMask.GCFunction | GCValueMask.GCPlaneMask | GCValueMask.GCForeground | GCValueMask.GCBackground | GCValueMask.GCLineWidth | GCValueMask.GCLineStyle | GCValueMask.GCCapStyle | GCValueMask.GCJoinStyle | GCValueMask.GCFillStyle | GCValueMask.GCFillRule | GCValueMask.GCTileStipXOrigin | GCValueMask.GCTileStipYOrigin | GCValueMask.GCSubwindowMode | GCValueMask.GCGraphicsExposures | GCValueMask.GCClipXOrigin | GCValueMask.GCClipYOrigin | GCValueMask.GCClipMask | GCValueMask.GCDashOffset | GCValueMask.GCDashList | GCValueMask.GCArcMode), ref gcValues); } int sn = drawable.screen.ScreenNumber; double px, mm; px = (double)Xlib.XDisplayWidth(display, sn); mm = (double)Xlib.XDisplayWidthMM(display, sn); dpiX = (float)((px * 25.4) / mm); px = (double)Xlib.XDisplayHeight(display, sn); mm = (double)Xlib.XDisplayHeightMM(display, sn); dpiY = (float)((px * 25.4) / mm); } finally { dpy.Unlock(); } if(drawable is DoubleBuffer) { ((DoubleBuffer)drawable).ClearAtStart(this); } isDisposed = false; }
// Determine if the X server supports embedding - inner version. // "displayName" will be set to a non-null value if it is necessary // to redirect the DISPLAY environment variable elsewhere. private static bool CanEmbed(Display display, bool reportErrors, out String displayName) { IntPtr dpy; Xlib.Xint major, minor; String client; int index; displayName = null; try { dpy = display.Lock(); // See if the X server supports XC-APPGROUP and SECURITY. if (Xlib.XagQueryVersion(dpy, out major, out minor) == XBool.False) { if (reportErrors && !errorReported) { Console.Error.WriteLine ("The X server `{0}' does not support the " + "XC-APPGROUP extension,", display.displayName); Console.Error.WriteLine ("which is required for application " + "embedding."); errorReported = true; } return(false); } if (Xlib.XSecurityQueryExtension(dpy, out major, out minor) == XBool.False) { if (reportErrors && !errorReported) { Console.Error.WriteLine ("The X server `{0}' does not support the " + "SECURITY extension,", display.displayName); Console.Error.WriteLine ("which is required for for application " + "embedding."); errorReported = true; } return(false); } // If we are in an ssh shell account, then we cannot // connect via ssh's X11 forwarding mechanism as it // does not know how to proxy appgroup security tokens. // Try to discover where the ssh client actually lives. displayName = Environment.GetEnvironmentVariable ("XREALDISPLAY"); client = Environment.GetEnvironmentVariable("SSH_CLIENT"); if (displayName != null && displayName.Length > 0) { // The user specified a display override with // the XREALDISPLAY environment variable. if (!ProbeDisplay(displayName, reportErrors)) { displayName = null; return(false); } } else if (client != null && client.Length > 0) { // Synthesize a display name from the ssh client name. index = client.IndexOf(' '); if (index == -1) { index = client.Length; } displayName = client.Substring(0, index) + ":0.0"; if (!ProbeDisplay(displayName, reportErrors)) { displayName = null; return(false); } } else if (Environment.GetEnvironmentVariable("SSH_ASKPASS") != null || Environment.GetEnvironmentVariable("SSH_TTY") != null) { // Older versions of bash do not export SSH_CLIENT // within an ssh login session. if (reportErrors && !errorReported) { Console.Error.WriteLine ("The `SSH_CLIENT' environment variable " + "is not exported from the shell."); Console.Error.WriteLine ("Either export `SSH_CLIENT' or set the " + "`XREALDISPLAY' environment"); Console.Error.WriteLine ("variable to the name of the real " + "X display."); errorReported = true; } displayName = null; return(false); } else { // No ssh, so use the original "DISPLAY" value as-is. displayName = null; } } catch (MissingMethodException) { displayName = null; return(false); } catch (DllNotFoundException) { displayName = null; return(false); } catch (EntryPointNotFoundException) { displayName = null; return(false); } finally { display.Unlock(); } return(true); }