1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
25 using System.Collections;
27 using System.Runtime.InteropServices;
29 using System.Threading;
30 using System.Windows.Forms;
32 namespace System.Windows.Forms.X11Internal {
34 internal class X11Hwnd : Hwnd
38 bool refetch_window_type = true;
39 bool refetch_window_opacity = true;
41 IntPtr[] wm_state = new IntPtr[0];
42 IntPtr[] window_type = new IntPtr[0];
46 new X11ThreadQueue queue;
48 const EventMask SelectInputMask = (EventMask.ButtonPressMask |
49 EventMask.ButtonReleaseMask |
50 EventMask.KeyPressMask |
51 EventMask.KeyReleaseMask |
52 EventMask.EnterWindowMask |
53 EventMask.LeaveWindowMask |
54 EventMask.ExposureMask |
55 EventMask.FocusChangeMask |
56 EventMask.PointerMotionMask |
57 EventMask.SubstructureNotifyMask);
59 public X11Hwnd (X11Display display)
61 this.display = display;
62 Queue = XplatUIX11_new.GetInstance().ThreadQueue(Thread.CurrentThread);
65 public X11Hwnd (X11Display display, IntPtr handle) : this (display)
67 if (handle == IntPtr.Zero)
68 throw new ArgumentNullException ("handle");
69 WholeWindow = ClientWindow = handle;
72 // XXX this needs to be here so we don't have to
73 // change Hwnd. once we land, remove this and make
74 // Hwnd.Queue virtual or abstract
75 public new X11ThreadQueue Queue {
77 set { queue = value; }
80 public virtual void CreateWindow (CreateParams cp)
82 if (WholeWindow != IntPtr.Zero || ClientWindow != IntPtr.Zero)
83 throw new Exception ("createwindow called a second time on live X11Hwnd");
85 XSetWindowAttributes Attributes;
91 SetWindowValuemask ValueMask;
93 Attributes = new XSetWindowAttributes();
99 /* Figure out our parent handle */
100 if (cp.Parent != IntPtr.Zero)
101 // the parent handle is specified in the CreateParams
102 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).ClientWindow;
103 else if (StyleSet (cp.Style, WindowStyles.WS_CHILD))
104 // a child control with an unassigned parent gets created under the FosterParent
105 ParentHandle = display.FosterParent.Handle;
107 // for all other cases, the parent is the root window
108 ParentHandle = display.RootWindow.Handle;
110 ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
112 Attributes.bit_gravity = Gravity.NorthWestGravity;
113 Attributes.win_gravity = Gravity.NorthWestGravity;
115 // Save what's under the toolwindow
116 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
117 Attributes.save_under = true;
118 ValueMask |= SetWindowValuemask.SaveUnder;
121 // If we're a popup without caption we override the WM
122 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
123 Attributes.override_redirect = true;
124 ValueMask |= SetWindowValuemask.OverrideRedirect;
127 // Default position on screen, if window manager doesn't place us somewhere else
128 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)
129 && !StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
133 // minimum width/height
134 if (width<1) width=1;
135 if (height<1) height=1;
141 Parent = Hwnd.ObjectFromHandle (cp.Parent);
143 Enabled = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
145 ClientWindow = IntPtr.Zero;
147 WholeWindow = Xlib.XCreateWindow (display.Handle, ParentHandle,
148 X, Y, Width, Height, 0,
149 (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput,
150 IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
151 if (WholeWindow == IntPtr.Zero)
152 throw new Exception ("Coult not create X11 nc window");
154 ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
156 if (display.CustomVisual != IntPtr.Zero && display.CustomColormap != IntPtr.Zero) {
157 ValueMask |= SetWindowValuemask.ColorMap;
158 Attributes.colormap = display.CustomColormap;
161 ClientWindow = Xlib.XCreateWindow (display.Handle, WholeWindow,
162 ClientRect.X, ClientRect.Y, ClientRect.Width, ClientRect.Height, 0,
163 (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput,
164 display.CustomVisual, new UIntPtr ((uint)ValueMask), ref Attributes);
166 if (ClientWindow == IntPtr.Zero)
167 throw new Exception("Could not create X11 client window");
169 #if DriverDebug || DriverDebugCreate
170 Console.WriteLine("Created window {0:X} / {1:X} parent {2:X}, Style {3}, ExStyle {4}", ClientWindow.ToInt32(), WholeWindow.ToInt32(), Parent != null ? Parent.Handle.ToInt32() : 0, (WindowStyles)cp.Style, (WindowExStyles)cp.ExStyle);
173 if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
174 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
177 hints = new XSizeHints();
180 hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
181 Xlib.XSetWMNormalHints (display.Handle, WholeWindow, ref hints);
185 Xlib.XSelectInput (display.Handle, WholeWindow, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
186 if (WholeWindow != ClientWindow)
187 Xlib.XSelectInput (display.Handle, ClientWindow, new IntPtr ((int)SelectInputMask));
189 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
194 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
195 WINDOW_TYPE = display.Atoms._NET_WM_WINDOW_TYPE_NORMAL;
196 Xlib.XSetTransientForHint (display.Handle, WholeWindow, display.RootWindow.Handle);
201 // set the group leader
202 XWMHints wm_hints = new XWMHints ();
204 wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
205 wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
206 wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
207 wm_hints.window_group = ParentHandle == display.RootWindow.Handle ? ParentHandle : WholeWindow;
209 Xlib.XSetWMHints (display.Handle, WholeWindow, ref wm_hints );
211 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE))
212 SetWindowState (FormWindowState.Minimized);
213 else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE))
214 SetWindowState (FormWindowState.Maximized);
216 // for now make all windows dnd enabled
217 display.Dnd.SetAllowDrop (this, true);
219 // Set caption/window title
223 public virtual void DestroyWindow ()
225 if (WholeWindow != IntPtr.Zero) {
226 #if DriverDebug || DriverDebugDestroy
227 Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", WholeWindow.ToInt32());
229 Xlib.XDestroyWindow (display.Handle, WholeWindow);
231 else if (ClientWindow != IntPtr.Zero) {
232 #if DriverDebug || DriverDebugDestroy
233 Console.WriteLine ("XDestroyWindow (client_window = {0:X})", ClientWindow.ToInt32());
235 Xlib.XDestroyWindow (display.Handle, ClientWindow);
239 public void Activate ()
241 if (((IList)display.RootWindow._NET_SUPPORTED).Contains (display.Atoms._NET_ACTIVE_WINDOW)) {
242 display.SendNetWMMessage (WholeWindow, display.Atoms._NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
245 Xlib.XRaiseWindow (display.Handle, WholeWindow);
249 public void Update ()
253 if (!Visible || !PendingExpose || !Mapped)
256 // XXX this SendMessage call should probably not be inside the lock
257 display.SendMessage (ClientWindow, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
259 PendingExpose = false;
266 public void MenuToScreen (ref int x, ref int y)
272 Xlib.XTranslateCoordinates (display.Handle,
273 WholeWindow, display.RootWindow.Handle,
274 x, y, out dest_x_return, out dest_y_return, out child);
280 public virtual void PropertyChanged (XEvent xevent)
282 if (xevent.PropertyEvent.atom == display.Atoms._NET_WM_WINDOW_TYPE) {
283 // we need to recache our WINDOW_TYPE on the next query
284 refetch_window_type = true;
287 else if (xevent.PropertyEvent.atom == display.Atoms._NET_WM_STATE) {
288 // we need to recache our WM_STATE on the next query
290 else if (xevent.PropertyEvent.atom == display.Atoms._NET_WM_NAME) {
291 // update our Text property
293 else if (xevent.PropertyEvent.atom == display.Atoms._NET_WM_WINDOW_OPACITY) {
294 // we need to recache our _NET_WM_WINDOW_OPACITY on the next query.
295 refetch_window_opacity = true;
297 // else we don't care about it
301 public void SetIcon (Icon icon)
304 Xlib.XDeleteProperty (display.Handle, WholeWindow, display.Atoms._NET_WM_ICON);
312 bitmap = icon.ToBitmap();
314 size = bitmap.Width * bitmap.Height + 2;
315 data = new IntPtr[size];
317 data[index++] = (IntPtr)bitmap.Width;
318 data[index++] = (IntPtr)bitmap.Height;
320 for (int y = 0; y < bitmap.Height; y++) {
321 for (int x = 0; x < bitmap.Width; x++) {
322 data[index++] = (IntPtr)bitmap.GetPixel(x, y).ToArgb();
326 Xlib.XChangeProperty (display.Handle, WholeWindow,
327 display.Atoms._NET_WM_ICON, display.Atoms.XA_CARDINAL, 32,
328 PropertyMode.Replace, data, size);
332 public double GetWindowTransparency ()
334 if (refetch_window_opacity) {
341 IntPtr prop = IntPtr.Zero;
343 IntPtr w = WholeWindow;
345 w = display.XGetParent (WholeWindow);
347 Xlib.XGetWindowProperty (display.Handle, w,
348 display.Atoms._NET_WM_WINDOW_OPACITY, IntPtr.Zero, new IntPtr (16), false,
349 display.Atoms.XA_CARDINAL,
350 out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
352 if (((long)nitems == 1) && (prop != IntPtr.Zero)) {
353 uint x11_opacity = (uint)Marshal.ReadInt32(prop, 0);
354 trans = ((double)x11_opacity) / (uint)0xffffffff;
357 if (prop != IntPtr.Zero) {
365 public void SetWindowTransparency (double transparency, Color key)
369 opacity = (uint)(0xffffffff * transparency);
370 x11_opacity = (IntPtr)((int)opacity);
372 IntPtr w = WholeWindow;
374 w = display.XGetParent (WholeWindow);
375 Xlib.XChangeProperty (display.Handle, w,
376 display.Atoms._NET_WM_WINDOW_OPACITY, display.Atoms.XA_CARDINAL, 32,
377 PropertyMode.Replace, ref x11_opacity, 1);
380 public IntPtr DefWndProc (ref Message msg)
382 switch ((Msg)msg.Msg) {
385 PendingExpose = false;
391 PendingNCExpose = false;
395 case Msg.WM_CONTEXTMENU:
397 display.SendMessage (Parent.ClientWindow, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
400 case Msg.WM_MOUSEWHEEL:
401 if (Parent != null) {
402 display.SendMessage (Parent.ClientWindow, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
403 if (msg.Result == IntPtr.Zero)
408 case Msg.WM_SETCURSOR:
409 X11Hwnd parent = (X11Hwnd)Parent;
410 // Pass to parent window first
411 while ((parent != null) && (msg.Result == IntPtr.Zero)) {
412 msg.Result = NativeWindow.WndProc (parent.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
413 parent = (X11Hwnd)Parent;
416 if (msg.Result == IntPtr.Zero) {
419 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
420 case HitTest.HTBOTTOM: handle = Cursors.SizeNS.handle; break;
421 case HitTest.HTBORDER: handle = Cursors.SizeNS.handle; break;
422 case HitTest.HTBOTTOMLEFT: handle = Cursors.SizeNESW.handle; break;
423 case HitTest.HTBOTTOMRIGHT: handle = Cursors.SizeNWSE.handle; break;
424 case HitTest.HTERROR:
425 if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN)
426 display.AudibleAlert();
427 handle = Cursors.Default.handle;
430 case HitTest.HTHELP: handle = Cursors.Help.handle; break;
431 case HitTest.HTLEFT: handle = Cursors.SizeWE.handle; break;
432 case HitTest.HTRIGHT: handle = Cursors.SizeWE.handle; break;
433 case HitTest.HTTOP: handle = Cursors.SizeNS.handle; break;
434 case HitTest.HTTOPLEFT: handle = Cursors.SizeNWSE.handle; break;
435 case HitTest.HTTOPRIGHT: handle = Cursors.SizeNESW.handle; break;
438 case HitTest.HTGROWBOX:
441 case HitTest.HTVSCROLL:
442 case HitTest.HTSYSMENU:
443 case HitTest.HTREDUCE:
444 case HitTest.HTNOWHERE:
445 case HitTest.HTMAXBUTTON:
446 case HitTest.HTMINBUTTON:
448 case HitTest.HSCROLL:
449 case HitTest.HTBOTTOM:
450 case HitTest.HTCAPTION:
451 case HitTest.HTCLIENT:
452 case HitTest.HTCLOSE:
454 default: handle = Cursors.Default.handle; break;
457 display.SetCursor (msg.HWnd, handle);
467 public void AddExpose (bool client, int x, int y, int width, int height)
470 if ((x > Width) || (y > Height) || ((x + width) <= 0) || ((y + height) <= 0))
473 // Keep the invalid area as small as needed
474 if ((x + width) > Width)
477 if ((y + height) > Height)
481 AddInvalidArea(x, y, width, height);
482 PendingExpose = true;
485 AddNcInvalidArea (x, y, width, height);
486 PendingNCExpose = true;
490 public void AddConfigureNotify (XEvent xevent)
492 // We drop configure events for Client windows
493 if ((xevent.ConfigureEvent.window != WholeWindow) || (xevent.ConfigureEvent.window != xevent.ConfigureEvent.xevent))
497 X = xevent.ConfigureEvent.x;
498 Y = xevent.ConfigureEvent.y;
500 // This sucks ass, part 1
501 // Every WM does the ConfigureEvents of toplevel windows different, so there's
502 // no standard way of getting our adjustment.
503 // The code below is needed for KDE and FVWM, the 'whacky_wm' part is for metacity
504 // Several other WMs do their decorations different yet again and we fail to deal
505 // with that, since I couldn't find any frigging commonality between them.
506 // The only sane WM seems to be KDE
508 if (!xevent.ConfigureEvent.send_event) {
514 Xlib.XTranslateCoordinates (display.Handle, WholeWindow, display.RootWindow.Handle,
515 -xevent.ConfigureEvent.x, -xevent.ConfigureEvent.y,
516 out trans_x, out trans_y, out dummy_ptr);
521 // This is a synthetic event, coordinates are in root space
522 X = xevent.ConfigureEvent.x;
523 Y = xevent.ConfigureEvent.y;
528 FrameExtents (out frame_left, out frame_top);
535 Width = xevent.ConfigureEvent.width;
536 Height = xevent.ConfigureEvent.height;
537 ClientRect = Rectangle.Empty;
539 if (!configure_pending) {
540 Queue.AddConfigure (this);
541 configure_pending = true;
545 public void HandleConfigureNotify (XEvent xevent)
547 configure_pending = false;
549 display.SendMessage (Handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
551 // We need to adjust our client window to track the resize of whole_window
552 if (WholeWindow != ClientWindow)
556 public void Invalidate (Rectangle rc, bool clear)
559 AddExpose (true, X, Y, Width, Height);
561 AddExpose (true, rc.X, rc.Y, rc.Width, rc.Height);
565 public void InvalidateNC ()
567 AddExpose (false, 0, 0, Width, Height);
570 // XXX this assumes the queue lock is held
571 public bool PendingNCExpose {
572 get { return nc_expose_pending; }
574 if (nc_expose_pending == value)
576 nc_expose_pending = value;
578 if (nc_expose_pending && !expose_pending)
579 Queue.AddPaint (this);
580 else if (!nc_expose_pending && !expose_pending)
581 Queue.RemovePaint (this);
585 // XXX this assumes the queue lock is held
586 public bool PendingExpose {
587 get { return expose_pending; }
589 if (expose_pending == value)
591 expose_pending = value;
593 if (expose_pending && !nc_expose_pending)
594 Queue.AddPaint (this);
595 else if (!expose_pending && !nc_expose_pending)
596 Queue.RemovePaint (this);
600 public PaintEventArgs PaintEventStart (bool client)
602 PaintEventArgs paint_event;
606 dc = Graphics.FromHwnd (ClientWindow);
608 Region clip_region = new Region ();
609 clip_region.MakeEmpty();
611 foreach (Rectangle r in ClipRectangles)
612 clip_region.Union (r);
614 if (UserClip != null)
615 clip_region.Intersect(UserClip);
617 dc.Clip = clip_region;
618 paint_event = new PaintEventArgs(dc, Invalid);
619 PendingExpose = false;
623 drawing_stack.Push (paint_event);
624 drawing_stack.Push (dc);
629 dc = Graphics.FromHwnd (WholeWindow);
631 if (!nc_invalid.IsEmpty) {
632 dc.SetClip (nc_invalid);
633 paint_event = new PaintEventArgs(dc, nc_invalid);
636 paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, width, height));
638 PendingNCExpose = false;
640 ClearNcInvalidArea ();
642 drawing_stack.Push (paint_event);
643 drawing_stack.Push (dc);
649 public void PaintEventEnd (bool client)
651 Graphics dc = (Graphics)drawing_stack.Pop ();
655 PaintEventArgs pe = (PaintEventArgs)drawing_stack.Pop();
656 pe.SetGraphics (null);
660 public void DrawReversibleRectangle (Rectangle rect, int line_width)
665 gc_values = new XGCValues ();
667 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
668 gc_values.line_width = line_width;
670 // XXX multiscreen support
671 gc_values.foreground = Xlib.XBlackPixel (display.Handle, display.DefaultScreen);
673 // This logic will give us true rubber bands: (libsx, SANE_XOR)
674 //mask = foreground ^ background;
675 //XSetForeground(DisplayHandle, gc, 0xffffffff);
676 //XSetBackground(DisplayHandle, gc, background);
677 //XSetFunction(DisplayHandle, gc, GXxor);
678 //XSetPlaneMask(DisplayHandle, gc, mask);
681 gc = Xlib.XCreateGC (display.Handle, ClientWindow,
682 new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
687 control = Control.FromHandle(Handle);
689 XColor xcolor = new XColor();
691 xcolor.red = (ushort)(control.ForeColor.R * 257);
692 xcolor.green = (ushort)(control.ForeColor.G * 257);
693 xcolor.blue = (ushort)(control.ForeColor.B * 257);
694 Xlib.XAllocColor (display.Handle, display.DefaultColormap, ref xcolor);
695 foreground = (uint)xcolor.pixel.ToInt32();
697 xcolor.red = (ushort)(control.BackColor.R * 257);
698 xcolor.green = (ushort)(control.BackColor.G * 257);
699 xcolor.blue = (ushort)(control.BackColor.B * 257);
700 Xlib.XAllocColor (display.Handle, display.DefaultColormap, ref xcolor);
701 background = (uint)xcolor.pixel.ToInt32();
703 uint mask = foreground ^ background;
705 Xlib.XSetForeground (display.Handle, gc, (UIntPtr)0xffffffff);
706 Xlib.XSetBackground (display.Handle, gc, (UIntPtr)background);
707 Xlib.XSetFunction (display.Handle, gc, GXFunction.GXxor);
708 Xlib.XSetPlaneMask (display.Handle, gc, (IntPtr)mask);
710 if ((rect.Width > 0) && (rect.Height > 0))
711 Xlib.XDrawRectangle (display.Handle, ClientWindow, gc, rect.Left, rect.Top, rect.Width, rect.Height);
712 else if (rect.Width > 0)
713 Xlib.XDrawLine (display.Handle, ClientWindow, gc, rect.X, rect.Y, rect.Right, rect.Y);
715 Xlib.XDrawLine (display.Handle, ClientWindow, gc, rect.X, rect.Y, rect.X, rect.Bottom);
717 Xlib.XFreeGC (display.Handle, gc);
722 // FIXME why do we set this here and also in the MapNotify event handling?
724 Xlib.XMapWindow (display.Handle, WholeWindow);
725 if (WholeWindow != ClientWindow)
726 Xlib.XMapWindow (display.Handle, ClientWindow);
731 // FIXME why do we set this here and also in the UnmapNotify event handling?
733 Xlib.XUnmapWindow (display.Handle, WholeWindow);
736 public void PerformNCCalc ()
738 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
742 rect = DefaultClientRect;
744 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS ();
745 ptr = Marshal.AllocHGlobal (Marshal.SizeOf(ncp));
747 ncp.rgrc1.left = rect.Left;
748 ncp.rgrc1.top = rect.Top;
749 ncp.rgrc1.right = rect.Right;
750 ncp.rgrc1.bottom = rect.Bottom;
752 Marshal.StructureToPtr (ncp, ptr, true);
753 NativeWindow.WndProc (ClientWindow, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
754 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
755 Marshal.FreeHGlobal(ptr);
757 // FIXME - debug this with Menus
759 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
763 if ((rect.Width < 1) || (rect.Height < 1))
764 Xlib.XMoveResizeWindow (display.Handle, ClientWindow, -5, -5, 1, 1);
766 Xlib.XMoveResizeWindow (display.Handle, ClientWindow, rect.X, rect.Y, rect.Width, rect.Height);
772 public void RequestNCRecalc ()
775 display.SendMessage (Handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
780 public void RequestAdditionalWM_NCMessages (bool hover, bool leave)
782 // Missing messages won't crash anything so just don't generate them for the moment.
783 // throw new NotImplementedException( );
786 public void FrameExtents (out int left, out int top)
792 IntPtr prop = IntPtr.Zero;
794 Xlib.XGetWindowProperty (display.Handle, WholeWindow,
795 display.Atoms._NET_FRAME_EXTENTS, IntPtr.Zero, new IntPtr (16), false,
796 display.Atoms.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
797 if (((long)nitems == 4) && (prop != IntPtr.Zero)) {
798 left = Marshal.ReadIntPtr(prop, 0).ToInt32();
799 //right = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
800 top = Marshal.ReadIntPtr(prop, IntPtr.Size * 2).ToInt32();
801 //bottom = Marshal.ReadIntPtr(prop, IntPtr.Size * 3).ToInt32();
807 if (prop != IntPtr.Zero) {
812 static bool StyleSet (int s, WindowStyles ws)
814 return (s & (int)ws) == (int)ws;
817 static bool ExStyleSet (int ex, WindowExStyles exws)
819 return (ex & (int)exws) == (int)exws;
822 // XXX this should be a static method on Hwnd so other backends can use it
823 public static void DeriveStyles(int Style, int ExStyle, out FormBorderStyle border_style, out bool border_static,
824 out TitleStyle title_style, out int caption_height, out int tool_caption_height)
827 // Only MDI windows get caption_heights
829 tool_caption_height = 19;
830 border_static = false;
832 if (StyleSet (Style, WindowStyles.WS_CHILD)) {
833 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
834 border_style = FormBorderStyle.Fixed3D;
835 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
836 border_style = FormBorderStyle.Fixed3D;
837 border_static = true;
838 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
839 border_style = FormBorderStyle.None;
841 border_style = FormBorderStyle.FixedSingle;
843 title_style = TitleStyle.None;
845 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
848 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
849 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW))
850 title_style = TitleStyle.Tool;
852 title_style = TitleStyle.Normal;
855 if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
856 ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW))
857 border_style = (FormBorderStyle) 0xFFFF;
859 border_style = FormBorderStyle.None;
863 title_style = TitleStyle.None;
864 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
865 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW))
866 title_style = TitleStyle.Tool;
868 title_style = TitleStyle.Normal;
871 border_style = FormBorderStyle.None;
873 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
874 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW))
875 border_style = FormBorderStyle.SizableToolWindow;
877 border_style = FormBorderStyle.Sizable;
879 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
880 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE))
881 border_style = FormBorderStyle.Fixed3D;
882 else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
883 border_style = FormBorderStyle.Fixed3D;
884 border_static = true;
885 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME))
886 border_style = FormBorderStyle.FixedDialog;
887 else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW))
888 border_style = FormBorderStyle.FixedToolWindow;
889 else if (StyleSet (Style, WindowStyles.WS_BORDER))
890 border_style = FormBorderStyle.FixedSingle;
891 } else if (StyleSet (Style, WindowStyles.WS_BORDER))
892 border_style = FormBorderStyle.FixedSingle;
897 public void SetHwndStyles (CreateParams cp)
899 DeriveStyles(cp.Style, cp.ExStyle, out this.border_style, out this.border_static, out this.title_style, out this.caption_height, out this.tool_caption_height);
902 public void SetWMStyles (CreateParams cp)
904 MotifWmHints mwmHints;
905 MotifFunctions functions;
906 MotifDecorations decorations;
909 Rectangle client_rect;
911 // Child windows don't need WM window styles
912 if (StyleSet (cp.Style, WindowStyles.WS_CHILDWINDOW))
915 atoms = new IntPtr[8];
916 mwmHints = new MotifWmHints();
920 mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
921 mwmHints.functions = (IntPtr)0;
922 mwmHints.decorations = (IntPtr)0;
924 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)
925 || !StyleSet (cp.Style, WindowStyles.WS_CAPTION | WindowStyles.WS_BORDER | WindowStyles.WS_DLGFRAME)) {
926 /* tool windows get no window manager
927 decorations, and neither do windows
928 which lack CAPTION/BORDER/DLGFRAME
932 /* just because the window doesn't get any decorations doesn't
933 mean we should disable the functions. for instance, without
934 MotifFunctions.Maximize, changing the windowstate to Maximized
935 is ignored by metacity. */
936 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
939 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
940 functions |= MotifFunctions.Move;
941 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
944 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
945 functions |= MotifFunctions.Move | MotifFunctions.Resize;
946 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
949 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
950 functions |= MotifFunctions.Minimize;
951 decorations |= MotifDecorations.Minimize;
954 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
955 functions |= MotifFunctions.Maximize;
956 decorations |= MotifDecorations.Maximize;
959 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
960 functions |= MotifFunctions.Resize;
961 decorations |= MotifDecorations.ResizeH;
964 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
965 decorations |= MotifDecorations.Border;
968 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
969 decorations |= MotifDecorations.Border;
972 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
973 decorations |= MotifDecorations.Border;
976 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
977 functions |= MotifFunctions.Close;
980 functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
981 decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
982 if (cp.Caption == "") {
983 functions &= ~MotifFunctions.Move;
984 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
989 if ((functions & MotifFunctions.Resize) == 0) {
991 SetMinMax (new Rectangle(cp.X, cp.Y, cp.Width, cp.Height), new Size(cp.Width, cp.Height), new Size(cp.Width, cp.Height));
996 mwmHints.functions = (IntPtr)functions;
997 mwmHints.decorations = (IntPtr)decorations;
999 FormWindowState current_state = GetWindowState ();
1000 if (current_state == (FormWindowState)(-1))
1001 current_state = FormWindowState.Normal;
1003 client_rect = ClientRect;
1007 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
1008 // and get those windows in front of their parents
1009 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
1010 WINDOW_TYPE = display.Atoms._NET_WM_WINDOW_TYPE_UTILITY;
1012 Form f = Control.FromHandle(Handle) as Form;
1013 if (f != null && !reparented) {
1014 if (f.Owner != null && f.Owner.Handle != IntPtr.Zero) {
1015 Hwnd owner_hwnd = Hwnd.ObjectFromHandle(f.Owner.Handle);
1016 if (owner_hwnd != null)
1017 Xlib.XSetTransientForHint (display.Handle, WholeWindow,
1018 owner_hwnd.WholeWindow);
1023 Xlib.XChangeProperty (display.Handle, WholeWindow,
1024 display.Atoms._MOTIF_WM_HINTS, display.Atoms._MOTIF_WM_HINTS, 32,
1025 PropertyMode.Replace, ref mwmHints, 5);
1027 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (parent != null) && (parent.WholeWindow != IntPtr.Zero)) {
1028 WINDOW_TYPE = display.Atoms._NET_WM_WINDOW_TYPE_NORMAL;
1029 Xlib.XSetTransientForHint(display.Handle, WholeWindow, parent.WholeWindow);
1030 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
1031 /* this line keeps the window from showing up in gnome's taskbar */
1032 atoms[atom_count++] = display.Atoms._NET_WM_STATE_SKIP_TASKBAR;
1034 if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
1035 Xlib.XMoveResizeWindow (display.Handle, ClientWindow, -5, -5, 1, 1);
1037 Xlib.XMoveResizeWindow (display.Handle, ClientWindow, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
1040 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW))
1041 atoms[atom_count++] = display.Atoms._NET_WM_STATE_SKIP_TASKBAR;
1043 /* we need to add these atoms in the
1044 * event we're maximized, since we're
1045 * replacing the existing
1046 * _NET_WM_STATE here. If we don't
1047 * add them, future calls to
1048 * GetWindowState will return Normal
1049 * for a window which is maximized. */
1050 if (current_state == FormWindowState.Maximized) {
1051 atoms[atom_count++] = display.Atoms._NET_WM_STATE_MAXIMIZED_HORZ;
1052 atoms[atom_count++] = display.Atoms._NET_WM_STATE_MAXIMIZED_VERT;
1055 Set_WM_STATE (atoms, atom_count);
1058 atoms[atom_count++] = display.Atoms.WM_DELETE_WINDOW;
1059 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP))
1060 atoms[atom_count++] = display.Atoms._NET_WM_CONTEXT_HELP;
1062 Xlib.XSetWMProtocols (display.Handle, WholeWindow, atoms, atom_count);
1065 public void ClientToScreen (ref int x, ref int y)
1071 Xlib.XTranslateCoordinates (display.Handle,
1072 ClientWindow, display.RootWindow.Handle,
1073 x, y, out dest_x_return, out dest_y_return, out child);
1079 public void ScreenToClient (ref int x, ref int y)
1085 Xlib.XTranslateCoordinates (display.Handle,
1086 display.RootWindow.Handle, ClientWindow,
1087 x, y, out dest_x_return, out dest_y_return, out child);
1094 public void ScreenToMenu (ref int x, ref int y)
1100 Xlib.XTranslateCoordinates (display.Handle,
1101 display.RootWindow.Handle, WholeWindow,
1102 x, y, out dest_x_return, out dest_y_return, out child);
1108 public void ScrollWindow (Rectangle area, int XAmount, int YAmount, bool with_children)
1111 XGCValues gc_values;
1113 Rectangle r = Rectangle.Intersect (Invalid, area);
1115 /* We have an invalid area in the window we're scrolling.
1116 Adjust our stored invalid rectangle to to match the scrolled amount */
1131 if (area.Contains (Invalid))
1136 gc_values = new XGCValues();
1138 gc_values.graphics_exposures = false;
1140 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
1142 gc = Xlib.XCreateGC (display.Handle, ClientWindow, IntPtr.Zero, ref gc_values);
1150 height = area.Height - YAmount;
1151 dest_y = area.Y + YAmount;
1154 src_y = area.Y - YAmount;
1155 height = area.Height + YAmount;
1161 width = area.Width - XAmount;
1162 dest_x = area.X + XAmount;
1165 src_x = area.X - XAmount;
1166 width = area.Width + XAmount;
1170 Xlib.XCopyArea (display.Handle, ClientWindow, ClientWindow, gc, src_x, src_y, width, height, dest_x, dest_y);
1172 // Generate an expose for the area exposed by the horizontal scroll
1173 // We don't use AddExpose since we're
1175 AddExpose (true, area.X, area.Y, XAmount, area.Height);
1176 } else if (XAmount < 0) {
1177 AddExpose (true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
1180 // Generate an expose for the area exposed by the vertical scroll
1182 AddExpose (true, area.X, area.Y, area.Width, YAmount);
1183 } else if (YAmount < 0) {
1184 AddExpose (true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
1187 Xlib.XFreeGC (display.Handle, gc);
1191 public void SetBorderStyle (FormBorderStyle border_style)
1193 Form form = Control.FromHandle (Handle) as Form;
1194 if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
1195 border_style == FormBorderStyle.SizableToolWindow)) {
1196 form.window_manager = new ToolWindowManager (form);
1199 BorderStyle = border_style;
1203 // XXX this should probably be in Hwnd
1204 public void SetClipRegion (Region region)
1207 Invalidate (new Rectangle(0, 0, Width, Height), false);
1210 // XXX this should probably be in Hwnd
1211 public Region GetClipRegion ()
1216 public void SetMenu (Menu menu)
1223 public void SetMinMax (Rectangle maximized, Size min, Size max)
1228 hints = new XSizeHints();
1230 Xlib.XGetWMNormalHints (display.Handle, WholeWindow, ref hints, out dummy);
1231 if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
1232 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
1233 hints.min_width = min.Width;
1234 hints.min_height = min.Height;
1237 if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
1238 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
1239 hints.max_width = max.Width;
1240 hints.max_height = max.Height;
1243 if (hints.flags != IntPtr.Zero)
1244 Xlib.XSetWMNormalHints (display.Handle, WholeWindow, ref hints);
1246 if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
1247 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
1248 hints.x = maximized.X;
1249 hints.y = maximized.Y;
1250 hints.width = maximized.Width;
1251 hints.height = maximized.Height;
1253 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
1254 Xlib.XSetZoomHints (display.Handle, WholeWindow, ref hints);
1258 public void GetPosition (bool is_toplevel, out int x, out int y, out int width, out int height, out int client_width, out int client_height)
1267 client_width = ClientRect.Width;
1268 client_height = ClientRect.Height;
1271 public void SetPosition (int x, int y, int width, int height)
1273 // Win32 automatically changes negative width/height to 0.
1279 // X requires a sanity check for width & height; otherwise it dies
1280 if (zero_sized && width > 0 && height > 0) {
1287 if ((width < 1) || (height < 1)) {
1292 // Save a server roundtrip (and prevent a feedback loop)
1293 if ((X == x) && (Y == y) &&
1294 (Width == width) && (Height == height)) {
1304 display.SendMessage (Handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
1307 SetMinMax (Rectangle.Empty, new Size(width, height), new Size(width, height));
1310 Xlib.XMoveResizeWindow (display.Handle, WholeWindow, x, y, width, height);
1314 // Update our position/size immediately, so
1315 // that future calls to SetWindowPos aren't
1316 // kept from calling XMoveResizeWindow (by the
1317 // "Save a server roundtrip" block above).
1322 ClientRect = Rectangle.Empty;
1325 public void SetParent (X11Hwnd parent_hwnd)
1327 Parent = parent_hwnd;
1329 #if DriverDebug || DriverDebugParent
1330 Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(Handle), XplatUI.Window(hwnd.parent != null ? parent_hwnd.Handle : IntPtr.Zero));
1332 Xlib.XReparentWindow (display.Handle, WholeWindow,
1333 parent_hwnd == null ? display.FosterParent.ClientWindow : parent_hwnd.ClientWindow,
1337 public void SetCursorPos (int x, int y)
1339 Xlib.XWarpPointer (display.Handle, IntPtr.Zero, ClientWindow, 0, 0, 0, 0, x, y);
1342 public bool SetTopmost (X11Hwnd owner, bool enabled)
1345 WINDOW_TYPE = display.Atoms._NET_WM_WINDOW_TYPE_NORMAL;
1347 Xlib.XSetTransientForHint (display.Handle, WholeWindow, owner.WholeWindow);
1349 Xlib.XSetTransientForHint (display.Handle, WholeWindow, display.RootWindow.WholeWindow);
1352 Xlib.XDeleteProperty (display.Handle, WholeWindow, display.Atoms.XA_WM_TRANSIENT_FOR);
1358 public bool SetVisible (bool visible, bool activate)
1363 if (Control.FromHandle (Handle) is Form) {
1366 s = ((Form)Control.FromHandle(Handle)).WindowState;
1371 case FormWindowState.Minimized: SetWindowState (FormWindowState.Minimized); break;
1372 case FormWindowState.Maximized: SetWindowState (FormWindowState.Maximized); break;
1379 display.SendMessage (Handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
1387 public FormWindowState GetWindowState ()
1393 IntPtr prop = IntPtr.Zero;
1397 XWindowAttributes attributes;
1401 Xlib.XGetWindowProperty (display.Handle, WholeWindow,
1402 display.Atoms._NET_WM_STATE, IntPtr.Zero, new IntPtr (256), false,
1403 display.Atoms.XA_ATOM, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1405 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1406 for (int i = 0; i < (long)nitems; i++) {
1407 // XXX 64 bit clean?
1408 atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
1409 if ((atom == display.Atoms._NET_WM_STATE_MAXIMIZED_HORZ) || (atom == display.Atoms._NET_WM_STATE_MAXIMIZED_VERT))
1411 else if (atom == display.Atoms._NET_WM_STATE_HIDDEN)
1418 return FormWindowState.Minimized;
1419 else if (maximized == 2)
1420 return FormWindowState.Maximized;
1422 attributes = new XWindowAttributes();
1423 Xlib.XGetWindowAttributes (display.Handle, ClientWindow, ref attributes);
1424 if (attributes.map_state == MapState.IsUnmapped)
1425 return (FormWindowState)(-1);
1427 return FormWindowState.Normal;
1431 public void SetWindowState (FormWindowState state)
1433 FormWindowState current_state;
1435 current_state = GetWindowState ();
1437 if (current_state == state)
1441 case FormWindowState.Normal:
1442 if (current_state == FormWindowState.Minimized)
1444 else if (current_state == FormWindowState.Maximized)
1445 display.SendNetWMMessage (WholeWindow,
1446 display.Atoms._NET_WM_STATE, (IntPtr)2 /* toggle */,
1447 display.Atoms._NET_WM_STATE_MAXIMIZED_HORZ,
1448 display.Atoms._NET_WM_STATE_MAXIMIZED_VERT);
1452 case FormWindowState.Minimized:
1453 if (current_state == FormWindowState.Maximized)
1454 display.SendNetWMMessage (WholeWindow,
1455 display.Atoms._NET_WM_STATE, (IntPtr)2 /* toggle */,
1456 display.Atoms._NET_WM_STATE_MAXIMIZED_HORZ,
1457 display.Atoms._NET_WM_STATE_MAXIMIZED_VERT);
1459 // FIXME multiscreen support
1460 Xlib.XIconifyWindow (display.Handle, WholeWindow, display.DefaultScreen);
1463 case FormWindowState.Maximized:
1464 if (current_state == FormWindowState.Minimized)
1467 display.SendNetWMMessage (WholeWindow,
1468 display.Atoms._NET_WM_STATE, (IntPtr)1 /* Add */,
1469 display.Atoms._NET_WM_STATE_MAXIMIZED_HORZ,
1470 display.Atoms._NET_WM_STATE_MAXIMIZED_VERT);
1476 public bool SetZOrder (X11Hwnd after_hwnd, bool top, bool bottom)
1479 Xlib.XRaiseWindow (display.Handle, WholeWindow);
1483 Xlib.XLowerWindow (display.Handle, WholeWindow);
1487 if (after_hwnd == null) {
1488 Update_USER_TIME ();
1489 Xlib.XRaiseWindow (display.Handle, WholeWindow);
1490 display.SendNetWMMessage (WholeWindow, display.Atoms._NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
1494 XWindowChanges values = new XWindowChanges();
1495 values.sibling = after_hwnd.WholeWindow;
1496 values.stack_mode = StackMode.Below;
1498 Xlib.XConfigureWindow (display.Handle, WholeWindow, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
1503 public X11Display Display {
1504 get { return display; }
1507 public string Text {
1508 get { return text; }
1518 Xlib.XChangeProperty(display.Handle, WholeWindow,
1519 display.Atoms._NET_WM_NAME, display.Atoms.UNICODETEXT, 8,
1520 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
1522 // XXX this has problems with UTF8.
1523 // we need to either use the actual
1524 // text if it's latin-1, or convert it
1525 // to compound text if it's in a
1526 // different charset.
1527 Xlib.XStoreName(display.Handle, WholeWindow, text);
1531 public bool GetText (out string text)
1537 IntPtr prop = IntPtr.Zero;
1539 Xlib.XGetWindowProperty (display.Handle, WholeWindow,
1540 display.Atoms._NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
1541 display.Atoms.UNICODETEXT, out actual_atom, out actual_format,
1542 out nitems, out bytes_after, ref prop);
1544 if ((long)nitems > 0 && prop != IntPtr.Zero) {
1545 text = Marshal.PtrToStringUni (prop, (int)nitems);
1550 // fallback on the non-_NET property
1553 textptr = IntPtr.Zero;
1555 Xlib.XFetchName (display.Handle, WholeWindow, ref textptr);
1556 if (textptr != IntPtr.Zero) {
1557 text = Marshal.PtrToStringAnsi(textptr);
1558 Xlib.XFree(textptr);
1567 public IntPtr WINDOW_TYPE {
1569 if (refetch_window_type) {
1570 window_type = GetAtomListProperty (display.Atoms._NET_WM_WINDOW_TYPE);
1571 refetch_window_type = false;
1574 return window_type.Length > 0 ? window_type[0] : IntPtr.Zero;
1577 Set_WINDOW_TYPE (new IntPtr[] {value}, 1);
1581 public void Set_WINDOW_TYPE (IntPtr[] value, int count)
1583 if (refetch_window_type) {
1584 window_type = GetAtomListProperty (display.Atoms._NET_WM_WINDOW_TYPE);
1585 refetch_window_type = false;
1588 if (ArrayDifferent (window_type, value)) {
1589 window_type = value;
1590 Xlib.XChangeProperty (display.Handle, WholeWindow,
1591 display.Atoms._NET_WM_WINDOW_TYPE, display.Atoms.XA_ATOM, 32,
1592 PropertyMode.Replace, window_type, window_type.Length);
1596 public void Set_WM_STATE (IntPtr[] value, int count)
1598 if (ArrayDifferent (wm_state, value)) {
1600 Xlib.XChangeProperty (display.Handle, WholeWindow,
1601 display.Atoms._NET_WM_STATE, display.Atoms.XA_ATOM, 32,
1602 PropertyMode.Replace, wm_state, wm_state.Length);
1606 public void Update_USER_TIME ()
1611 args[0] = display.CurrentTimestamp;
1612 Xlib.XChangeProperty (display.Handle, WholeWindow,
1613 display.Atoms._NET_WM_USER_TIME, display.Atoms.XA_CARDINAL, 32,
1614 PropertyMode.Replace, args, 1);
1617 public IntPtr[] GetAtomListProperty (IntPtr atom)
1623 IntPtr prop = IntPtr.Zero;
1625 Xlib.XGetWindowProperty (display.Handle, WholeWindow,
1626 atom, IntPtr.Zero, new IntPtr (Int32.MaxValue), false,
1627 display.Atoms.XA_ATOM, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1629 if (actual_atom != display.Atoms.XA_ATOM ||
1630 (long)nitems == 0 ||
1631 prop == IntPtr.Zero) {
1632 return new IntPtr[0];
1635 IntPtr[] values = new IntPtr[(long)nitems];
1638 for (int i = 0; i < values.Length; i ++) {
1639 values[i] = Marshal.ReadIntPtr (prop, ofs); ofs += IntPtr.Size;
1647 bool ArrayDifferent (IntPtr[] a, IntPtr[] b)
1649 if (a.Length != b.Length)
1652 for (int i = 0; i < a.Length; i ++) {