On Saturday 23 December 2006 13:05, Felipe Monteiro de Carvalho wrote:
> On 12/23/06, Bogusław Brandys <[EMAIL PROTECTED]> wrote:
> > Under Windows XP it's enough (taskbar hides itself nicely after a second
> > or two) ,under win9x you must also hide taskbar by yourself (using
> > winapi).We could use it and prepare multiplatform solution (windows +
> > linux GTK) - a function in LCL could be perfect in my opinion.
>
> The Virtual Magnifying Glass ( http://magnifier.sourceforge.net/ ) is
> a Lazarus full-screen app.
>
> On Windows I never had trouble using a maximized borderless window,
> but on Linux with KDE the taskbar is always on front of my app. Anyone
> know how to fix this?
See code below for an Xlib solution used with Kylix (Qt).
Should work with Gtk aswell (replace Form.Handle
with the X handle provided by Gtk)
This code is used on recent and older KDE KWIN versions.
We use kwin as it was the first to provide the correct
window manager behaviour (I think mandrake 8.2 or 9.1, not sure anymore)
If it doesn't work, your window manager sucks :-)
The IFDEFs for FPC are there for some tests with FPC and CLX
dating some years ago. So the FPC RTL may have changed since.
The ifdefs compensate for differences in Xlib.
//**************************************************************************
//
//**************************************************************************
unit WinUtil;
interface
uses QGraphics, Types, Qt, QForms, QControls, QMenus;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Declare new events for callback
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
const QEventType_ItemSelected = QEventType (Integer (QEventType_ClxUser) +
$10);
const QEventType_ResizeLists = QEventType (Integer (QEventType_ClxUser) +
$11);
const QEventType_WindowClosed = QEventType (Integer (QEventType_ClxUser) +
$12);
const QEventType_StopReplay = QEventType (Integer (QEventType_ClxUser) +
$13);
const QEventType_StartReplay = QEventType (Integer (QEventType_ClxUser) +
$14);
const QEventType_UserShow = QEventType (Integer (QEventType_ClxUser) +
$15);
//==========================================================================
procedure SetDesktop (Form : TForm; Desktop : integer);
//==========================================================================
procedure SetFullScreen (Form : TForm; Width : integer = 0; Height :
integer = 0);
//==========================================================================
procedure SetNoWMDecoration (Form : TForm);
//==========================================================================
function GetWMDecoration (Form : TForm) : Boolean;
//==========================================================================
procedure SetWMDecoration (Form : TForm);
//**************************************************************************
//
//**************************************************************************
implementation
uses SysUtils, Xlib {$IFDEF FPC_XLIB}, X, xatom{$ENDIF}{$IFDEF FPC}, Unix
{$ELSE}, Libc {$ENDIF};
{$IFDEF FPC_XLIB}
const NoDelete = False;
NoPropagate = False;
{$ELSE}
const NoDelete = 0;
NoPropagate = 0;
type TAtom = Atom;
TWindow = Window;
{$ENDIF}
var WMNET_Initialized : Boolean;
var _NET_SUPPORTED : TAtom;
//--------------------------------------------------------------------------
// _NET_WM_STATE
//--------------------------------------------------------------------------
var _NET_WM_STATE : TAtom;
var _NET_WM_STATE_MODAL : TAtom;
var _NET_WM_STATE_STICKY : TAtom;
var _NET_WM_STATE_MAXIMIZED_VERT : TAtom;
var _NET_WM_STATE_MAXIMIZED_HORZ : TAtom;
var _NET_WM_STATE_SHADED : TAtom;
var _NET_WM_STATE_SKIP_TASKBAR : TAtom;
var _NET_WM_STATE_SKIP_PAGER : TAtom;
var _NET_WM_STATE_HIDDEN : TAtom;
var _NET_WM_STATE_FULLSCREEN : TAtom;
var _NET_WM_STATE_ABOVE : TAtom;
var _NET_WM_STATE_BELOW : TAtom;
//--------------------------------------------------------------------------
// _NET_WM_DESKTOP
//--------------------------------------------------------------------------
var _NET_WM_DESKTOP : TAtom;
var _NET_CURRENT_DESKTOP : TAtom;
//--------------------------------------------------------------------------
// _NET_WM_ALLOWED_ACTIONS
//--------------------------------------------------------------------------
var _NET_WM_ALLOWED_ACTIONS : TAtom;
var _NET_WM_ACTION_MOVE : TAtom;
var _NET_WM_ACTION_RESIZE : TAtom;
var _NET_WM_ACTION_MINIMIZE : TAtom;
var _NET_WM_ACTION_SHADE : TAtom;
var _NET_WM_ACTION_STICK : TAtom;
var _NET_WM_ACTION_MAXIMIZE_HORZ : TAtom;
var _NET_WM_ACTION_MAXIMIZE_VERT : TAtom;
var _NET_WM_ACTION_FULLSCREEN : TAtom;
var _NET_WM_ACTION_CHANGE_DESKTOP : TAtom;
var _NET_WM_ACTION_CLOSE : TAtom;
//--------------------------------------------------------------------------
// _NET_WM_WINDOW_TYPE
//--------------------------------------------------------------------------
var _NET_WM_WINDOW_TYPE : TAtom;
var _NET_WM_WINDOW_TYPE_DESKTOP : TAtom;
var _NET_WM_WINDOW_TYPE_DOCK : TAtom;
var _NET_WM_WINDOW_TYPE_TOOLBAR : TAtom;
var _NET_WM_WINDOW_TYPE_MENU : TAtom;
var _NET_WM_WINDOW_TYPE_UTILITY : TAtom;
var _NET_WM_WINDOW_TYPE_SPLASH : TAtom;
var _NET_WM_WINDOW_TYPE_DIALOG : TAtom;
var _NET_WM_WINDOW_TYPE_NORMAL : TAtom;
//--------------------------------------------------------------------------
// KDE extensions to _NET_WM_WINDOW_TYPE
//--------------------------------------------------------------------------
var _KDE_NET_WM_WINDOW_TYPE_TOPMENU : TAtom;
var _KDE_NET_WM_WINDOW_TYPE_OVERRIDE : TAtom;
var RootWindow : TWindow;
const _NET_WM_STATE_REMOVE = 0;
const _NET_WM_STATE_ADD = 1;
const _NET_WM_STATE_TOGGLE = 2;
type
TLongIntArray = array of LongInt;
TLongInts = array[0..1000] of LongInt;
PLongInts = ^TLongInts;
//==========================================================================
// Check if TAtom exists
//==========================================================================
function HasProperty(W: TWindow; Prop: TAtom): Boolean;
var PropType : TAtom;
PropFormat : Longint;
Items : Cardinal;
BytesLeft : Cardinal;
Data : PLongInts;
begin
Data := nil;
Result := XGetWindowProperty (QtDisplay, W, Prop, 0, 0, NoDelete,
AnyPropertyType,
@PropType, @PropFormat, @Items, @BytesLeft,
@Data) = Success;
if Data <> nil then XFree(Data);
end;
//--------------------------------------------------------------------------
//==========================================================================
// Initialize the X Atoms
//==========================================================================
procedure WMNET_Init;
{$IFDEF FPC_XLIB}
const OnlyIfExists = True;
{$ELSE}
const OnlyIfExists = 1;
{$ENDIF}
begin
if WMNET_Initialized then Exit;
WMNET_Initialized := True;
_NET_SUPPORTED := XInternAtom
(QtDisplay, '_NET_SUPPORTED', OnlyIfExists);
//--------------------------------------------------------------------------
// _NET_WM_STATE
//--------------------------------------------------------------------------
_NET_WM_STATE := XInternAtom
(QtDisplay, '_NET_WM_STATE', OnlyIfExists);
_NET_WM_STATE_MODAL := XInternAtom
(QtDisplay, '_NET_WM_STATE_MODAL', OnlyIfExists);
_NET_WM_STATE_STICKY := XInternAtom
(QtDisplay, '_NET_WM_STATE_STICKY', OnlyIfExists);
_NET_WM_STATE_MAXIMIZED_VERT := XInternAtom
(QtDisplay, '_NET_WM_STATE_MAXIMIZED_VERT', OnlyIfExists);
_NET_WM_STATE_MAXIMIZED_HORZ := XInternAtom
(QtDisplay, '_NET_WM_STATE_MAXIMIZED_HORZ', OnlyIfExists);
_NET_WM_STATE_SHADED := XInternAtom
(QtDisplay, '_NET_WM_STATE_SHADED', OnlyIfExists);
_NET_WM_STATE_SKIP_TASKBAR := XInternAtom
(QtDisplay, '_NET_WM_STATE_SKIP_TASKBAR', OnlyIfExists);
_NET_WM_STATE_SKIP_PAGER := XInternAtom
(QtDisplay, '_NET_WM_STATE_SKIP_PAGER', OnlyIfExists);
_NET_WM_STATE_HIDDEN := XInternAtom
(QtDisplay, '_NET_WM_STATE_HIDDEN', OnlyIfExists);
_NET_WM_STATE_FULLSCREEN := XInternAtom
(QtDisplay, '_NET_WM_STATE_FULLSCREEN', OnlyIfExists);
_NET_WM_STATE_ABOVE := XInternAtom
(QtDisplay, '_NET_WM_STATE_BELOW', OnlyIfExists);
_NET_WM_STATE_BELOW := XInternAtom
(QtDisplay, '_NET_WM_STATE_BELOW', OnlyIfExists);
//--------------------------------------------------------------------------
// _NET_WM_ALLOWED_ACTIONS
//--------------------------------------------------------------------------
_NET_WM_ALLOWED_ACTIONS := XInternAtom
(QtDisplay, '_NET_WM_ALLOWED_ACTIONS', OnlyIfExists);
if _NET_WM_ALLOWED_ACTIONS = 0 then //typo bug in KDE3.2.0
_NET_WM_ALLOWED_ACTIONS := XInternAtom
(QtDisplay, '_NET_AM_ALLOWED_ACTIONS', OnlyIfExists);
_NET_WM_ACTION_MOVE := XInternAtom
(QtDisplay, '_NET_WM_ACTION_MOVE', OnlyIfExists);
_NET_WM_ACTION_RESIZE := XInternAtom
(QtDisplay, '_NET_WM_ACTION_RESIZE', OnlyIfExists);
_NET_WM_ACTION_MINIMIZE := XInternAtom
(QtDisplay, '_NET_WM_ACTION_MINIMIZE', OnlyIfExists);
_NET_WM_ACTION_SHADE := XInternAtom
(QtDisplay, '_NET_WM_ACTION_SHADE', OnlyIfExists);
_NET_WM_ACTION_STICK := XInternAtom
(QtDisplay, '_NET_WM_ACTION_STICK', OnlyIfExists);
_NET_WM_ACTION_MAXIMIZE_HORZ := XInternAtom
(QtDisplay, '_NET_WM_ACTION_MAXIMIZE_HORZ', OnlyIfExists);
_NET_WM_ACTION_MAXIMIZE_VERT := XInternAtom
(QtDisplay, '_NET_WM_ACTION_MAXIMIZE_VERT', OnlyIfExists);
_NET_WM_ACTION_FULLSCREEN := XInternAtom
(QtDisplay, '_NET_WM_ACTION_FULLSCREEN', OnlyIfExists);
_NET_WM_ACTION_CHANGE_DESKTOP := XInternAtom
(QtDisplay, '_NET_WM_ACTION_CHANGE_DESKTOP', OnlyIfExists);
_NET_WM_ACTION_CLOSE := XInternAtom
(QtDisplay, '_NET_WM_ACTION_CLOSE', OnlyIfExists);
//--------------------------------------------------------------------------
// _NET_WM_WINDOW_TYPE
//--------------------------------------------------------------------------
_NET_WM_WINDOW_TYPE := XInternAtom
(QtDisplay, '_NET_WM_WINDOW_TYPE', OnlyIfExists);
_NET_WM_WINDOW_TYPE_DESKTOP := XInternAtom
(QtDisplay, '_NET_WM_WINDOW_TYPE_DESKTOP', OnlyIfExists);
_NET_WM_WINDOW_TYPE_DOCK := XInternAtom
(QtDisplay, '_NET_WM_WINDOW_TYPE_DOCK', OnlyIfExists);
_NET_WM_WINDOW_TYPE_TOOLBAR := XInternAtom
(QtDisplay, '_NET_WM_WINDOW_TYPE_TOOLBAR', OnlyIfExists);
_NET_WM_WINDOW_TYPE_MENU := XInternAtom
(QtDisplay, '_NET_WM_WINDOW_TYPE_MENU', OnlyIfExists);
_NET_WM_WINDOW_TYPE_UTILITY := XInternAtom
(QtDisplay, '_NET_WM_WINDOW_TYPE_UTILITY', OnlyIfExists);
_NET_WM_WINDOW_TYPE_SPLASH := XInternAtom
(QtDisplay, '_NET_WM_WINDOW_TYPE_SPLASH', OnlyIfExists);
_NET_WM_WINDOW_TYPE_DIALOG := XInternAtom
(QtDisplay, '_NET_WM_WINDOW_TYPE_DIALOG', OnlyIfExists);
_NET_WM_WINDOW_TYPE_NORMAL := XInternAtom
(QtDisplay, '_NET_WM_WINDOW_TYPE_NORMAL', OnlyIfExists);
_KDE_NET_WM_WINDOW_TYPE_TOPMENU := XInternAtom
(QtDisplay, '_KDE_NET_WM_WINDOW_TYPE_TOPMENU', OnlyIfExists);
_KDE_NET_WM_WINDOW_TYPE_OVERRIDE := XInternAtom
(QtDisplay, '_KDE_NET_WM_WINDOW_TYPE_OVERRIDE', OnlyIfExists);
//--------------------------------------------------------------------------
// _NET_WM_DESKTOP
//--------------------------------------------------------------------------
_NET_WM_DESKTOP := XInternAtom
(QtDisplay, '_NET_WM_DESKTOP', OnlyIfExists);
_NET_CURRENT_DESKTOP := XInternAtom
(QtDisplay, '_NET_CURRENT_DESKTOP', OnlyIfExists);
RootWindow := XRootWindow (QtDisplay, XDefaultScreen (QtDisplay));
end;
//--------------------------------------------------------------------------
//==========================================================================
// Get properties of a given TAtom
//==========================================================================
function GetLongIntProperties (W: TWindow; Prop: TAtom): TLongIntArray;
const Increment = 100;
var Offset: Integer;
PropType: TAtom;
PropFormat: Longint;
Items: Cardinal;
BytesLeft: Cardinal;
Data: PLongInts;
I: Integer;
begin
Offset := 0;
SetLength(Result, 0);
BytesLeft := 0;
repeat
if XGetWindowProperty (QtDisplay, W, Prop, Offset, Increment, NoDelete,
AnyPropertyType, @PropType, @PropFormat, @Items,
@BytesLeft, @Data) <> Success then Exit;
if Data = nil then Exit;
if PropFormat <> 32 then Exit;
SetLength(Result, Length(Result) + Integer(Items));
for I := 0 to Items - 1 do
Result [I + Offset] := Data^[I];
Inc (Offset, Items);
XFree (Data);
until BytesLeft = 0;
end;
//--------------------------------------------------------------------------
//==========================================================================
// Send _NET_WM_STATE message
//==========================================================================
procedure SetWMState (W: TWindow; State: Longint);
var ClientMessage : {$IFDEF
FPC_XLIB}TXClientMessageEvent{$ELSE}XClientMessageEvent{$ENDIF};
begin
{$IFDEF FPC_XLIB}
ClientMessage.window := W;
ClientMessage._type := X.ClientMessage;
{$ELSE}
ClientMessage.xwindow := W;
ClientMessage.xtype := Xlib.ClientMessage;
{$ENDIF}
ClientMessage.display := QtDisplay;
ClientMessage.format := 32;
ClientMessage.message_type := _NET_WM_STATE;
ClientMessage.data.l[0] := _NET_WM_STATE_ADD;
ClientMessage.data.l[1] := State;
ClientMessage.data.l[2] := 0;
ClientMessage.data.l[3] := 0;
ClientMessage.data.l[4] := 0;
XSendEvent (QtDisplay, RootWindow, NoPropagate, SubstructureRedirectMask,
@ClientMessage);
end;
//--------------------------------------------------------------------------
//==========================================================================
// Put window on a certain desktop. Desktop range start on 0
//==========================================================================
procedure SetWMDesktop (W: TWindow; Desktop: Longint);
var ClientMessage: {$IFDEF
FPC_XLIB}TXClientMessageEvent{$ELSE}XClientMessageEvent{$ENDIF};
begin
{$IFDEF FPC_XLIB}
ClientMessage.window := W;
ClientMessage._type := X.ClientMessage;
{$ELSE}
ClientMessage.xwindow := W;
ClientMessage.xtype := Xlib.ClientMessage;
{$ENDIF}
ClientMessage.display := QtDisplay;
ClientMessage.format := 32;
ClientMessage.message_type := _NET_WM_DESKTOP;
ClientMessage.data.l[0] := Desktop;
ClientMessage.data.l[1] := 0;
ClientMessage.data.l[2] := 0;
ClientMessage.data.l[3] := 0;
ClientMessage.data.l[4] := 0;
XSendEvent (QtDisplay, RootWindow, NoPropagate, SubstructureRedirectMask,
@ClientMessage);
end;
//--------------------------------------------------------------------------
//==========================================================================
// Set Form fullscreen
//==========================================================================
procedure SetFullScreen (Form : TForm; Width : integer = 0; Height :
integer = 0);
begin
SetNoWMDecoration (Form);
if Width = 0 then Width := QForms.Screen.Width;
if Height = 0 then Height := QForms.Screen.Height;
Form.SetBounds (0, 0, Width, Height);
end;
//--------------------------------------------------------------------------
//==========================================================================
// Set Form on a certain desktop. Range desktop starts from 1
//==========================================================================
procedure SetDesktop (Form : TForm; Desktop : integer);
var Data : TLongInts;
begin
if Desktop <= 0 then exit;
WMNET_Init;
if _NET_WM_DESKTOP = 0 then Exit;
//--------------------------------------------------------------------------
// If window visible then tell the window manager to switch now,
// else just set the property (the WM will switch when set visible)
//--------------------------------------------------------------------------
if Form.Visible then
SetWMDesktop (QWidget_winId (Form.Handle), Desktop - 1)
else
begin
FillChar (Data, SizeOf(Data), $00);
Data[0] := Desktop - 1;
XChangeProperty (QtDisplay, QWidget_winId (Form.Handle),
_NET_WM_DESKTOP, XA_CARDINAL,
32, PropModeReplace, @Data, 1);
end;
end;
//--------------------------------------------------------------------------
//==========================================================================
// Tell the window manager not to draw window decorations. This procedure
uses
// a KDE specific X TAtom, and therefore only works with kwin as WM.
//==========================================================================
procedure SetNoWMDecoration (Form : TForm);
var Data : TLongInts;
begin
WMNET_Init;
if (_NET_WM_WINDOW_TYPE = 0) or
(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE = 0) then exit;
FillChar (Data, SizeOf(Data), $00);
Data[0] := _KDE_NET_WM_WINDOW_TYPE_OVERRIDE;
XChangeProperty (QtDisplay, QWidget_winId (Form.Handle),
_NET_WM_WINDOW_TYPE, XA_Atom,
32, PropModeReplace, @Data, 1);
end;
//--------------------------------------------------------------------------
//==========================================================================
// Returns true if WM Decorations are ON
//==========================================================================
function GetWMDecoration (Form : TForm) : Boolean;
const Increment = 100;
var Offset: Integer;
PropType: TAtom;
PropFormat: Longint;
Items: Cardinal;
BytesLeft: Cardinal;
Data: PLongInts;
I: Integer;
begin
Offset := 0;
BytesLeft := 0;
Result:=True;
repeat
if XGetWindowProperty (QtDisplay, QWidget_WinId(Form.Handle),
_NET_WM_WINDOW_TYPE, Offset, Increment, NoDelete,
AnyPropertyType, @PropType, @PropFormat, @Items,
@BytesLeft, @Data) <> Success then Exit;
if Data = nil then Exit;
if PropFormat <> 32 then
begin
if Assigned(Data) then XFree (Data);
Exit;
end;
for I := 0 to Items - 1 do
if Cardinal (Data^[I]) = _KDE_NET_WM_WINDOW_TYPE_OVERRIDE then
Result := False;
Inc (Offset, Items);
XFree (Data);
until BytesLeft = 0;
end;
//--------------------------------------------------------------------------
//==========================================================================
// Tell the window manager to draw window decorations. This procedure uses
// a KDE specific X TAtom, and therefore only works with kwin as WM.
//==========================================================================
procedure SetWMDecoration (Form : TForm);
var Data : TLongInts;
begin
WMNET_Init;
if (_NET_WM_WINDOW_TYPE = 0) or
(_KDE_NET_WM_WINDOW_TYPE_OVERRIDE = 0) then exit;
FillChar (Data, SizeOf(Data), $00);
Data[0] := _NET_WM_WINDOW_TYPE_NORMAL;
XChangeProperty (QtDisplay, QWidget_winId (Form.Handle),
_NET_WM_WINDOW_TYPE, XA_Atom,
32, PropModeReplace, @Data, 1);
end;
//--------------------------------------------------------------------------
end.
_________________________________________________________________
To unsubscribe: mail [EMAIL PROTECTED] with
"unsubscribe" as the Subject
archives at http://www.lazarus.freepascal.org/mailarchives