[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Dotgnu-pnet-commits] CVS: pnetlib/Xsharp GrabWindow.cs,NONE,1.1 Overrid
From: |
Rhys Weatherley <address@hidden> |
Subject: |
[Dotgnu-pnet-commits] CVS: pnetlib/Xsharp GrabWindow.cs,NONE,1.1 OverrideWindow.cs,NONE,1.1 PopupWindow.cs,NONE,1.1 ModifierMask.cs,1.1,1.2 Screen.cs,1.2,1.3 Xlib.cs.in,1.10,1.11 |
Date: |
Mon, 23 Jun 2003 22:18:58 -0400 |
Update of /cvsroot/dotgnu-pnet/pnetlib/Xsharp
In directory subversions:/tmp/cvs-serv12850/Xsharp
Modified Files:
ModifierMask.cs Screen.cs Xlib.cs.in
Added Files:
GrabWindow.cs OverrideWindow.cs PopupWindow.cs
Log Message:
Add popup window support to Xsharp, to support menu functionality.
--- NEW FILE ---
/*
* GrabWindow.cs - Window that captures all events during an active grab.
*
* Copyright (C) 2003 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
namespace Xsharp
{
using System;
using System.Runtime.InteropServices;
using Xsharp.Events;
// When a "PopupWindow" instance is displayed on-screen, all mouse
// and keyboard events are routed to the grab window. From there,
// they are dispatched to the approriate popup window. The grab
// ends when the last popup window is unmapped.
internal class GrabWindow : OverrideWindow
{
// Internal state.
private PopupWindow[] list;
private PopupWindow lastEntered;
private PopupWindow lastButton;
private IntPtr keyBuffer;
// Constructor.
public GrabWindow(Widget parent)
: base(parent, -1, -1, 1, 1)
{
// Create the initial list of popup windows.
list = new PopupWindow [0];
// The grab window is always mapped, but just
off-screen
// so that it isn't visible to the user.
Map();
}
// Destructor.
~GrabWindow()
{
if(keyBuffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(keyBuffer);
keyBuffer = IntPtr.Zero;
}
}
// Grab control of the mouse and keyboard to manage popups.
private void Grab()
{
try
{
IntPtr display = dpy.Lock();
Xlib.Window handle = GetWidgetHandle();
Xlib.XGrabKeyboard
(display, handle,
Xlib.Bool.False,
1 /* GrabModeAsync */, 1 /*
GrabModeAsync */,
dpy.knownEventTime);
Xlib.XGrabPointer
(display, handle,
Xlib.Bool.False,
(uint)(EventMask.ButtonPressMask |
EventMask.ButtonReleaseMask |
EventMask.PointerMotionMask),
1 /* GrabModeAsync */, 1 /*
GrabModeAsync */,
Xlib.Window.Zero,
Xlib.Cursor.Zero,
dpy.knownEventTime);
Xlib.XFlush(display);
}
finally
{
dpy.Unlock();
}
}
// Ungrab the mouse and keyboard because there are no more popups.
private void Ungrab()
{
try
{
IntPtr display = dpy.Lock();
Xlib.XUngrabPointer(display,
dpy.knownEventTime);
Xlib.XUngrabKeyboard(display,
dpy.knownEventTime);
Xlib.XFlush(display);
}
finally
{
dpy.Unlock();
}
}
// Add a popup to the top of the mapped list.
public void AddPopup(PopupWindow popup)
{
int index;
lock(this)
{
// See if the popup is already in the
list.
for(index = 0; index < list.Length;
++index)
{
if(list[index] == popup)
{
while(index <
(list.Length - 1))
{
list[index] =
list[index + 1];
++index;
}
list[index] = popup;
return;
}
}
// Re-allocate the list and add the new
item.
PopupWindow[] newList = new PopupWindow
[list.Length + 1];
Array.Copy(list, 0, newList, 0,
list.Length);
newList[list.Length] = popup;
list = newList;
// If the list now contains one item,
then grab.
if(list.Length == 1)
{
Grab();
}
}
}
// Remove a popup from the mapped list.
public void RemovePopup(PopupWindow popup)
{
int index;
lock(this)
{
for(index = list.Length - 1; index >=
0; --index)
{
if(list[index] == popup)
{
// Remove the item from
the list.
PopupWindow[] newList;
newList = new
PopupWindow [list.Length - 1];
Array.Copy(list, 0,
newList, 0, index);
Array.Copy(list, index
+ 1, newList, index,
list.Length - index - 1);
list = newList;
// If this was the
entered window, then
// send it a fake
"LeaveNotify" event.
if(lastEntered == popup)
{
lastEntered =
null;
FakeLeave(popup);
}
// If this was the
button window, then clear it.
if(lastButton == popup)
{
lastButton =
null;
}
// If the list is now
empty, then ungrab.
if(list.Length == 0)
{
Ungrab();
}
return;
}
}
}
}
// Lower a popup to the bottom of the mapped list.
public void LowerPopup(PopupWindow popup)
{
int index;
lock(this)
{
for(index = list.Length - 1; index >=
0; --index)
{
if(list[index] == popup)
{
while(index > 0)
{
list[index] =
list[index - 1];
--index;
}
list[0] = popup;
return;
}
}
}
}
// Send a fake "EnterNotify" event to a popup window.
private static void FakeEnter(PopupWindow popup)
{
if(popup != null)
{
XEvent xevent = new XEvent();
xevent.xany.type__ =
(Xlib.Xint)(int)(EventType.EnterNotify);
popup.DispatchEvent(ref xevent);
}
}
// Send a fake "LeaveNotify" event to a popup window.
private static void FakeLeave(PopupWindow popup)
{
if(popup != null)
{
XEvent xevent = new XEvent();
xevent.xany.type__ =
(Xlib.Xint)(int)(EventType.LeaveNotify);
popup.DispatchEvent(ref xevent);
}
}
// Change the "lastEntered" window.
private void ChangeEntered(PopupWindow popup)
{
PopupWindow before = null;
PopupWindow after = null;
lock(this)
{
if(lastEntered != popup)
{
before = lastEntered;
after = popup;
lastEntered = popup;
}
}
if(before != null)
{
FakeLeave(before);
}
if(after != null)
{
FakeEnter(after);
}
}
// Find the popup window that contains a particular mouse position.
private PopupWindow Find(int x, int y, bool defaultIsTop)
{
int index;
PopupWindow popup;
for(index = 0; index < list.Length; ++index)
{
popup = list[index];
if(x >= popup.x && x < (popup.x +
popup.width) &&
y >= popup.y && y < (popup.y +
popup.height))
{
return popup;
}
}
if(defaultIsTop && list.Length > 0)
{
return list[list.Length - 1];
}
else
{
return null;
}
}
// Dispatch an event to this widget.
internal override void DispatchEvent(ref XEvent xevent)
{
Xlib.KeySym keysym;
PopupWindow popup;
switch(xevent.type)
{
case EventType.ButtonPress:
{
// A mouse button was pressed
during the grab.
lock(this)
{
if(lastButton != null)
{
// We currently
have a button window, so
// all mouse
events should go to it.
popup =
lastButton;
}
else
{
// Determine
which popup contains the mouse.
// If nothing
contains, then use the top.
popup =
Find(xevent.xbutton.x_root,
xevent.xbutton.y_root, true);
}
lastButton = popup;
}
ChangeEntered(popup);
if(popup != null)
{
// Adjust the
co-ordinates and re-dispatch.
xevent.xbutton.x__ =
(Xlib.Xint)(xevent.xbutton.x_root - popup.x);
xevent.xbutton.y__ =
(Xlib.Xint)(xevent.xbutton.y_root - popup.y);
popup.DispatchEvent(ref
xevent);
}
}
break;
case EventType.ButtonRelease:
{
// A mouse button was released
during the grab.
lock(this)
{
popup = lastButton;
if(popup != null)
{
// Reset
"lastButton" if this is the last
// button to be
released.
ModifierMask
mask = ModifierMask.AllButtons;
mask &=
~(ModifierMask.Button1Mask <<
(((int)(xevent.xbutton.button__)) - 1));
if((xevent.xbutton.state & mask) == 0)
{
lastButton = null;
}
}
}
ChangeEntered(popup);
if(popup != null)
{
// Adjust the
co-ordinates and re-dispatch.
xevent.xbutton.x__ =
(Xlib.Xint)(xevent.xbutton.x_root - popup.x);
xevent.xbutton.y__ =
(Xlib.Xint)(xevent.xbutton.y_root - popup.y);
popup.DispatchEvent(ref
xevent);
}
}
break;
case EventType.MotionNotify:
{
// The mouse pointer was moved
during the grab.
lock(this)
{
// If there is a last
button window, then use
// that, otherwise find
the one under the mouse.
popup = lastButton;
if(popup == null)
{
popup =
Find(xevent.xmotion.x_root,
xevent.xmotion.y_root, false);
}
}
ChangeEntered(popup);
if(popup != null)
{
// Adjust the
co-ordinates and re-dispatch.
xevent.xmotion.x__ =
(Xlib.Xint)(xevent.xmotion.x_root - popup.x);
xevent.xmotion.y__ =
(Xlib.Xint)(xevent.xmotion.y_root - popup.y);
popup.DispatchEvent(ref
xevent);
}
}
break;
case EventType.KeyPress:
{
// Convert the event into a
symbol and a string.
if(keyBuffer == IntPtr.Zero)
{
keyBuffer =
Marshal.AllocHGlobal(32);
}
keysym = 0;
int len = Xlib.XLookupString
(ref xevent.xkey,
keyBuffer, 32,
ref keysym,
IntPtr.Zero);
String str;
if(len > 0)
{
str =
Marshal.PtrToStringAnsi(keyBuffer, len);
}
else
{
str = null;
}
// Dispatch the event to the
top-most popup.
lock(this)
{
if(list.Length > 0)
{
popup =
list[list.Length - 1];
}
else
{
popup = null;
}
}
if(popup != null)
{
popup.DispatchKeyEvent
((KeyName)keysym, xevent.xkey.state, str);
}
}
break;
case EventType.KeyRelease:
{
// Convert the event into a
symbol and a string.
if(keyBuffer == IntPtr.Zero)
{
keyBuffer =
Marshal.AllocHGlobal(32);
}
keysym = 0;
int len = Xlib.XLookupString
(ref xevent.xkey,
keyBuffer, 32,
ref keysym,
IntPtr.Zero);
// Dispatch the event to the
top-most popup.
lock(this)
{
if(list.Length > 0)
{
popup =
list[list.Length - 1];
}
else
{
popup = null;
}
}
if(popup != null)
{
popup.DispatchKeyReleaseEvent
((KeyName)keysym, xevent.xkey.state);
}
}
break;
default:
{
// Everything else is handled
normally.
base.DispatchEvent(ref xevent);
}
break;
}
}
} // class GrabWindow
} // namespace Xsharp
--- NEW FILE ---
/*
* OverrideWindow.cs - Widget handling for override-redirect windows.
*
* Copyright (C) 2003 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
namespace Xsharp
{
using System;
/// <summary>
/// <para>The <see cref="T:Xsharp.OverrideWindow"/> class manages
/// windows that have the override-redirect bit set.</para>
///
/// <para>Applications should inherit from <see cref="T:Xsharp.PopupWindow"/>
/// instead of this class.</para>
/// </summary>
public class OverrideWindow : InputOutputWidget
{
// Constructor.
internal OverrideWindow(Widget parent, int x, int y, int width, int
height)
: base(parent, x, y, width, height,
new Color(StandardColor.Foreground),
new Color(StandardColor.Background),
true, true)
{
// Nothing to do here.
}
} // class OverrideWindow
} // namespace Xsharp
--- NEW FILE ---
/*
* PopupWindow.cs - Widget handling for popup windows.
*
* Copyright (C) 2003 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
namespace Xsharp
{
using System;
/// <summary>
/// <para>The <see cref="T:Xsharp.PopupWindow"/> class manages
/// popup windows that display top-level on the screen, but do not
/// have window manager borders. The mouse and keyboard will be
/// grabbed while a popup window is mapped to the screen.</para>
/// </summary>
public class PopupWindow : OverrideWindow
{
/// <summary>
/// <para>Constructs a new <see cref="T:Xsharp.PopupWindow"/>
/// instance.</para>
/// </summary>
///
/// <param name="x">
/// <para>The X position of the new window.</para>
/// </param>
///
/// <param name="y">
/// <para>The Y position of the new window.</para>
/// </param>
///
/// <param name="width">
/// <para>The width of the new window.</para>
/// </param>
///
/// <param name="height">
/// <para>The height of the new window.</para>
/// </param>
///
/// <exception cref="T:Xsharp.XException">
/// <para>Raised if any of the parameters are out of range.</para>
/// </exception>
///
/// <summary>
/// <para>This version of the constructor creates the window on
/// the default screen of the primary display.</para>
/// </summary>
public PopupWindow(int x, int y, int width, int height)
: base(TopLevelWindow.GetRoot(null), x, y, width,
height)
{
// Nothing to do here.
}
/// <summary>
/// <para>Constructs a new <see cref="T:Xsharp.PopupWindow"/>
/// instance.</para>
/// </summary>
///
/// <param name="screen">
/// <para>The screen to display the window on, or <see langword="null"/>
/// to use the default screen of the primary display.</para>
/// </param>
///
/// <param name="x">
/// <para>The X position of the new window.</para>
/// </param>
///
/// <param name="y">
/// <para>The Y position of the new window.</para>
/// </param>
///
/// <param name="width">
/// <para>The width of the new window.</para>
/// </param>
///
/// <param name="height">
/// <para>The height of the new window.</para>
/// </param>
///
/// <exception cref="T:Xsharp.XException">
/// <para>Raised if any of the parameters are out of range.</para>
/// </exception>
public PopupWindow(Screen screen, int x, int y, int width, int height)
: base(TopLevelWindow.GetRoot(screen), x, y, width,
height)
{
// Nothing to do here.
}
// Get the grab window that is associated with this popup.
private GrabWindow GetGrabWindow()
{
return screen.grabWindow;
}
/// <summary>
/// <para>Destroy this widget if it is currently active.</para>
/// </summary>
public override void Destroy()
{
GetGrabWindow().RemovePopup(this);
base.Destroy();
}
/// <summary>
/// <para>Map this widget to the screen.</para>
/// </summary>
public override void Map()
{
if(!IsMapped)
{
GetGrabWindow().AddPopup(this);
base.Raise();
base.Map();
}
}
/// <summary>
/// <para>Unmap this widget from the screen.</para>
/// </summary>
public override void Unmap()
{
if(IsMapped)
{
GetGrabWindow().RemovePopup(this);
base.Unmap();
}
}
/// <summary>
/// <para>Raise this widget to the top of its layer.</para>
/// </summary>
public override void Raise()
{
if(IsMapped)
{
GetGrabWindow().AddPopup(this);
}
base.Raise();
}
/// <summary>
/// <para>Lower this widget to the bottom of its layer.</para>
/// </summary>
public override void Lower()
{
if(IsMapped)
{
GetGrabWindow().LowerPopup(this);
}
base.Lower();
}
} // class PopupWindow
} // namespace Xsharp
Index: ModifierMask.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/Xsharp/ModifierMask.cs,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** ModifierMask.cs 28 May 2003 04:17:53 -0000 1.1
--- ModifierMask.cs 24 Jun 2003 02:18:56 -0000 1.2
***************
*** 45,49 ****
Button4Mask = (1<<11),
Button5Mask = (1<<12),
! AnyModifier = (1<<15)
} // enum ModifierMask
--- 45,51 ----
Button4Mask = (1<<11),
Button5Mask = (1<<12),
! AnyModifier = (1<<15),
! AllButtons = Button1Mask | Button2Mask | Button3Mask |
! Button4Mask | Button5Mask
} // enum ModifierMask
Index: Screen.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/Xsharp/Screen.cs,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -r1.2 -r1.3
*** Screen.cs 7 Jun 2003 00:13:09 -0000 1.2
--- Screen.cs 24 Jun 2003 02:18:56 -0000 1.3
***************
*** 45,48 ****
--- 45,49 ----
private const int GCCacheSize = 16;
private Color[] standardColors;
+ internal GrabWindow grabWindow;
// Constructor.
***************
*** 74,77 ****
--- 75,81 ----
// Create the placeholder window for
parent-less widgets.
placeholder = new PlaceholderWindow(rootWindow);
+
+ // Create the grab window for managing popup
window events.
+ grabWindow = new GrabWindow(rootWindow);
}
Index: Xlib.cs.in
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/Xsharp/Xlib.cs.in,v
retrieving revision 1.10
retrieving revision 1.11
diff -C2 -r1.10 -r1.11
*** Xlib.cs.in 20 Jun 2003 23:28:28 -0000 1.10
--- Xlib.cs.in 24 Jun 2003 02:18:56 -0000 1.11
***************
*** 210,213 ****
--- 210,230 ----
out Xuint border_width_return, out Xuint depth_return);
+ [DllImport("X11")]
+ extern public static @X_int@ XGrabKeyboard
+ (IntPtr display, Window grab_window, Bool owner_events,
+ @X_int@ pointer_mode, @X_int@ keyboard_mode, Time
time);
+
+ [DllImport("X11")]
+ extern public static @X_int@ XGrabPointer
+ (IntPtr display, Window grab_window, Bool owner_events,
+ @X_uint@ event_mask, @X_int@ pointer_mode, @X_int@
keyboard_mode,
+ Window confine_to, Cursor cursor, Time time);
+
+ [DllImport("X11")]
+ extern public static @X_int@ XUngrabKeyboard(IntPtr display, Time time);
+
+ [DllImport("X11")]
+ extern public static @X_int@ XUngrabPointer(IntPtr display, Time time);
+
// Declare pixmap-related external functions.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Dotgnu-pnet-commits] CVS: pnetlib/Xsharp GrabWindow.cs,NONE,1.1 OverrideWindow.cs,NONE,1.1 PopupWindow.cs,NONE,1.1 ModifierMask.cs,1.1,1.2 Screen.cs,1.2,1.3 Xlib.cs.in,1.10,1.11,
Rhys Weatherley <address@hidden> <=