mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-17 06:29:29 +02:00
Fixes AV in gtk2 TTrayIcon.InternalUpdate and adds a better handle mechanism to it
git-svn-id: trunk@16261 -
This commit is contained in:
parent
a5edfe5a9b
commit
09225df31f
@ -1,442 +1,438 @@
|
|||||||
{%MainUnit gtk2wsextctrls.pp}
|
{%MainUnit gtk2wsextctrls.pp}
|
||||||
{
|
{
|
||||||
gtk2trayicon.inc
|
gtk2trayicon.inc
|
||||||
|
|
||||||
*****************************************************************************
|
*****************************************************************************
|
||||||
* *
|
* *
|
||||||
* See the file COPYING.modifiedLGPL.txt, included in this distribution, *
|
* See the file COPYING.modifiedLGPL.txt, included in this distribution, *
|
||||||
* for details about the copyright. *
|
* for details about the copyright. *
|
||||||
* *
|
* *
|
||||||
* This program is distributed in the hope that it will be useful, *
|
* This program is distributed in the hope that it will be useful, *
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||||
* *
|
* *
|
||||||
*****************************************************************************
|
*****************************************************************************
|
||||||
|
|
||||||
Authors: Felipe Monteiro de Carvalho and Andrew Haines
|
Authors: Felipe Monteiro de Carvalho and Andrew Haines
|
||||||
|
|
||||||
Special thanks for: Danny Milosavljevic and the Lazarus Team
|
Special thanks for: Danny Milosavljevic and the Lazarus Team
|
||||||
|
|
||||||
Gtk2 specific code.
|
Gtk2 specific code.
|
||||||
}
|
}
|
||||||
|
|
||||||
{ TGtk2WSCustomTrayIcon }
|
{ TGtk2WSCustomTrayIcon }
|
||||||
|
|
||||||
const
|
type
|
||||||
SYSTEM_TRAY_REQUEST_DOCK = 0;
|
TGtk2WSTrayIconHandle = record
|
||||||
SYSTEM_TRAY_BEGIN_MESSAGE = 1;
|
AImage: PGtkWidget;
|
||||||
SYSTEM_TRAY_CANCEL_MESSAGE = 2;
|
end;
|
||||||
|
|
||||||
var
|
PGtk2WSTrayIconHandle = ^TGtk2WSTrayIconHandle;
|
||||||
{$ifdef HasX}
|
|
||||||
fDisplay: PDisplay;
|
const
|
||||||
fWindow: TWindow;
|
SYSTEM_TRAY_REQUEST_DOCK = 0;
|
||||||
fScreen: PScreen;
|
SYSTEM_TRAY_BEGIN_MESSAGE = 1;
|
||||||
fScreenID: longint;
|
SYSTEM_TRAY_CANCEL_MESSAGE = 2;
|
||||||
fTrayParent: TWindow;
|
|
||||||
{$endif}
|
var
|
||||||
|
{$ifdef HasX}
|
||||||
GtkForm: PGtkWidget;
|
fDisplay: PDisplay;
|
||||||
Tips: PGtkTooltips;
|
fWindow: TWindow;
|
||||||
|
fScreen: PScreen;
|
||||||
{$ifdef HasX}
|
fScreenID: longint;
|
||||||
{*******************************************************************
|
fTrayParent: TWindow;
|
||||||
* TempX11ErrorHandler ()
|
{$endif}
|
||||||
*
|
|
||||||
* DESCRIPTION: Temp ErrorHandler
|
GtkForm: PGtkWidget;
|
||||||
*
|
Tips: PGtkTooltips;
|
||||||
* PARAMETERS: ?
|
|
||||||
*
|
{$ifdef HasX}
|
||||||
* RETURNS: ?
|
{*******************************************************************
|
||||||
*
|
* TempX11ErrorHandler ()
|
||||||
*******************************************************************}
|
*
|
||||||
function TempX11ErrorHandler(Display:PDisplay; ErrorEv:PXErrorEvent):longint;cdecl;
|
* DESCRIPTION: Temp ErrorHandler
|
||||||
begin
|
*
|
||||||
WriteLn('Error: ' + IntToStr(ErrorEv^.error_code));
|
* PARAMETERS: ?
|
||||||
Result:=0;
|
*
|
||||||
end;
|
* RETURNS: ?
|
||||||
|
*
|
||||||
{*******************************************************************
|
*******************************************************************}
|
||||||
* Send_Message ()
|
function TempX11ErrorHandler(Display:PDisplay; ErrorEv:PXErrorEvent):longint;cdecl;
|
||||||
*
|
begin
|
||||||
* DESCRIPTION: Sends a message to the X client
|
WriteLn('Error: ' + IntToStr(ErrorEv^.error_code));
|
||||||
*
|
Result:=0;
|
||||||
* PARAMETERS: None
|
end;
|
||||||
*
|
|
||||||
* RETURNS: Nothing
|
{*******************************************************************
|
||||||
*
|
* Send_Message ()
|
||||||
*******************************************************************}
|
*
|
||||||
function SendMessage(window: TWindow; msg: Integer; data1, data2, data3: Integer): boolean;
|
* DESCRIPTION: Sends a message to the X client
|
||||||
var
|
*
|
||||||
Ev: TXEvent;
|
* PARAMETERS: None
|
||||||
begin
|
*
|
||||||
FillChar(Ev, SizeOf(TXEvent), $0);
|
* RETURNS: Nothing
|
||||||
|
*
|
||||||
ev.xclient._type := ClientMessage;
|
*******************************************************************}
|
||||||
ev.xclient.window := window;
|
function SendMessage(window: TWindow; msg: Integer; data1, data2, data3: Integer): boolean;
|
||||||
ev.xclient.message_type := XInternAtom (fDisplay, '_NET_SYSTEM_TRAY_OPCODE', False );
|
var
|
||||||
ev.xclient.format := 32;
|
Ev: TXEvent;
|
||||||
ev.xclient.data.l[0] := CurrentTime;
|
begin
|
||||||
ev.xclient.data.l[1] := msg;
|
FillChar(Ev, SizeOf(TXEvent), $0);
|
||||||
ev.xclient.data.l[2] := data1;
|
|
||||||
ev.xclient.data.l[3] := data2;
|
ev.xclient._type := ClientMessage;
|
||||||
ev.xclient.data.l[4] := data3;
|
ev.xclient.window := window;
|
||||||
|
ev.xclient.message_type := XInternAtom (fDisplay, '_NET_SYSTEM_TRAY_OPCODE', False );
|
||||||
XSendEvent(fDisplay, fTrayParent, False, NoEventMask, @ev);
|
ev.xclient.format := 32;
|
||||||
XSync(fDisplay, False);
|
ev.xclient.data.l[0] := CurrentTime;
|
||||||
Result := false;//(untrap_errors() = 0);
|
ev.xclient.data.l[1] := msg;
|
||||||
end;
|
ev.xclient.data.l[2] := data1;
|
||||||
|
ev.xclient.data.l[3] := data2;
|
||||||
{*******************************************************************
|
ev.xclient.data.l[4] := data3;
|
||||||
* SetEmbedded ()
|
|
||||||
*
|
XSendEvent(fDisplay, fTrayParent, False, NoEventMask, @ev);
|
||||||
* DESCRIPTION: Docks the GtkPlug into the system tray
|
XSync(fDisplay, False);
|
||||||
*
|
Result := false;//(untrap_errors() = 0);
|
||||||
* PARAMETERS: None
|
end;
|
||||||
*
|
|
||||||
* RETURNS: Nothing
|
{*******************************************************************
|
||||||
*
|
* SetEmbedded ()
|
||||||
*******************************************************************}
|
*
|
||||||
procedure SetEmbedded;
|
* DESCRIPTION: Docks the GtkPlug into the system tray
|
||||||
var
|
*
|
||||||
old_error: TXErrorHandler;
|
* PARAMETERS: None
|
||||||
buf: array [0..32] of char;
|
*
|
||||||
selection_atom : TAtom;
|
* RETURNS: Nothing
|
||||||
begin
|
*
|
||||||
old_error := XSetErrorHandler(@TempX11ErrorHandler);
|
*******************************************************************}
|
||||||
|
procedure SetEmbedded;
|
||||||
xsync(fdisplay,true);
|
var
|
||||||
buf := PChar('_NET_SYSTEM_TRAY_S' + IntToStr(fScreenID));
|
old_error: TXErrorHandler;
|
||||||
selection_atom := XInternAtom(fDisplay, buf, false);
|
buf: array [0..32] of char;
|
||||||
XGrabServer(fDisplay);
|
selection_atom : TAtom;
|
||||||
|
begin
|
||||||
fTrayParent := XGetSelectionOwner(fDisplay, selection_atom);
|
old_error := XSetErrorHandler(@TempX11ErrorHandler);
|
||||||
if fTrayParent <> None then
|
|
||||||
begin
|
xsync(fdisplay,true);
|
||||||
XSelectInput(fDisplay, fTrayParent, StructureNotifyMask);
|
buf := PChar('_NET_SYSTEM_TRAY_S' + IntToStr(fScreenID));
|
||||||
end;
|
selection_atom := XInternAtom(fDisplay, buf, false);
|
||||||
|
XGrabServer(fDisplay);
|
||||||
XUngrabServer(fDisplay);
|
|
||||||
XFlush(fDisplay);
|
fTrayParent := XGetSelectionOwner(fDisplay, selection_atom);
|
||||||
|
if fTrayParent <> None then
|
||||||
if fTrayParent <> None then
|
begin
|
||||||
SendMessage(fTrayParent, SYSTEM_TRAY_REQUEST_DOCK, fWindow, 0, 0);
|
XSelectInput(fDisplay, fTrayParent, StructureNotifyMask);
|
||||||
|
end;
|
||||||
XSetErrorHandler(old_error);
|
|
||||||
end;
|
XUngrabServer(fDisplay);
|
||||||
{$endif}
|
XFlush(fDisplay);
|
||||||
|
|
||||||
{*******************************************************************
|
if fTrayParent <> None then
|
||||||
* realize_cb ()
|
SendMessage(fTrayParent, SYSTEM_TRAY_REQUEST_DOCK, fWindow, 0, 0);
|
||||||
*
|
|
||||||
* DESCRIPTION: Callback function for the realize signal
|
XSetErrorHandler(old_error);
|
||||||
* Sets the systray icon after the widget is realized
|
end;
|
||||||
*
|
{$endif}
|
||||||
* PARAMETERS: None
|
|
||||||
*
|
{*******************************************************************
|
||||||
* RETURNS: Nothing
|
* realize_cb ()
|
||||||
*
|
*
|
||||||
*******************************************************************}
|
* DESCRIPTION: Callback function for the realize signal
|
||||||
procedure realize_cb(widget: PGtkWidget; user_data: gpointer); cdecl;
|
* Sets the systray icon after the widget is realized
|
||||||
begin
|
*
|
||||||
{$ifdef HasGdk2X}
|
* PARAMETERS: None
|
||||||
|
*
|
||||||
fDisplay := GDK_WINDOW_XDISPLAY(GtkForm^.window);
|
* RETURNS: Nothing
|
||||||
fWindow := GDK_WINDOW_XWINDOW(GtkForm^.window);
|
*
|
||||||
|
*******************************************************************}
|
||||||
{ Doesn´t work
|
procedure realize_cb(widget: PGtkWidget; user_data: gpointer); cdecl;
|
||||||
|
begin
|
||||||
gdk_screen := gtk_widget_get_screen(GtkForm);
|
{$ifdef HasGdk2X}
|
||||||
fScreen := GDK_SCREEN_XSCREEN(gdk_screen); // get the real screen}
|
|
||||||
|
fDisplay := GDK_WINDOW_XDISPLAY(GtkForm^.window);
|
||||||
fScreen := XDefaultScreenOfDisplay(fDisplay);
|
fWindow := GDK_WINDOW_XWINDOW(GtkForm^.window);
|
||||||
fScreenID := XScreenNumberOfScreen(fScreen); // and it's number
|
|
||||||
|
{ Doesn´t work
|
||||||
SetEmbedded;
|
|
||||||
{$endif}
|
gdk_screen := gtk_widget_get_screen(GtkForm);
|
||||||
end;
|
fScreen := GDK_SCREEN_XSCREEN(gdk_screen); // get the real screen}
|
||||||
|
|
||||||
{*******************************************************************
|
fScreen := XDefaultScreenOfDisplay(fDisplay);
|
||||||
* button_release_cb ()
|
fScreenID := XScreenNumberOfScreen(fScreen); // and it's number
|
||||||
*
|
|
||||||
* DESCRIPTION: Callback function for Mouse Click
|
SetEmbedded;
|
||||||
*
|
{$endif}
|
||||||
* PARAMETERS: None
|
end;
|
||||||
*
|
|
||||||
* RETURNS: Nothing
|
{*******************************************************************
|
||||||
*
|
* button_release_cb ()
|
||||||
*******************************************************************}
|
*
|
||||||
function button_release_cb(widget: PGtkWidget; event: PGdkEventButton;
|
* DESCRIPTION: Callback function for Mouse Click
|
||||||
user_data: gpointer): gboolean; cdecl;
|
*
|
||||||
var
|
* PARAMETERS: None
|
||||||
vwsTrayIcon: TCustomTrayIcon;
|
*
|
||||||
begin
|
* RETURNS: Nothing
|
||||||
vwsTrayIcon := TCustomTrayIcon(user_data);
|
*
|
||||||
|
*******************************************************************}
|
||||||
Result := False;
|
function button_release_cb(widget: PGtkWidget; event: PGdkEventButton;
|
||||||
|
user_data: gpointer): gboolean; cdecl;
|
||||||
case event^.button of
|
var
|
||||||
1:
|
vwsTrayIcon: TCustomTrayIcon;
|
||||||
begin
|
begin
|
||||||
if Assigned(vwsTrayIcon.OnClick) then vwsTrayIcon.OnClick(vwsTrayIcon);
|
vwsTrayIcon := TCustomTrayIcon(user_data);
|
||||||
if Assigned(vwsTrayIcon.OnMouseUp) then
|
|
||||||
vwsTrayIcon.OnMouseUp(vwsTrayIcon, mbLeft, [], Round(event^.X), Round(event^.Y));
|
Result := False;
|
||||||
end;
|
|
||||||
|
case event^.button of
|
||||||
2: if Assigned(vwsTrayIcon.OnMouseUp) then
|
1:
|
||||||
vwsTrayIcon.OnMouseUp(vwsTrayIcon, mbMiddle, [], Round(event^.X), Round(event^.Y));
|
begin
|
||||||
|
if Assigned(vwsTrayIcon.OnClick) then vwsTrayIcon.OnClick(vwsTrayIcon);
|
||||||
3:
|
if Assigned(vwsTrayIcon.OnMouseUp) then
|
||||||
begin
|
vwsTrayIcon.OnMouseUp(vwsTrayIcon, mbLeft, [], Round(event^.X), Round(event^.Y));
|
||||||
if Assigned(vwsTrayIcon.OnMouseUp) then
|
end;
|
||||||
vwsTrayIcon.OnMouseUp(vwsTrayIcon, mbRight, [], Round(event^.X), Round(event^.Y));
|
|
||||||
if Assigned(vwsTrayIcon.PopUpMenu) then
|
2: if Assigned(vwsTrayIcon.OnMouseUp) then
|
||||||
vwsTrayIcon.PopUpMenu.PopUp(Mouse.CursorPos.X, Mouse.CursorPos.Y);
|
vwsTrayIcon.OnMouseUp(vwsTrayIcon, mbMiddle, [], Round(event^.X), Round(event^.Y));
|
||||||
end;
|
|
||||||
end;
|
3:
|
||||||
end;
|
begin
|
||||||
|
if Assigned(vwsTrayIcon.OnMouseUp) then
|
||||||
{*******************************************************************
|
vwsTrayIcon.OnMouseUp(vwsTrayIcon, mbRight, [], Round(event^.X), Round(event^.Y));
|
||||||
* button_press_cb ()
|
if Assigned(vwsTrayIcon.PopUpMenu) then
|
||||||
*
|
vwsTrayIcon.PopUpMenu.PopUp(Mouse.CursorPos.X, Mouse.CursorPos.Y);
|
||||||
* DESCRIPTION: Callback function for Mouse Click
|
end;
|
||||||
*
|
end;
|
||||||
* PARAMETERS: None
|
end;
|
||||||
*
|
|
||||||
* RETURNS: Nothing
|
{*******************************************************************
|
||||||
*
|
* button_press_cb ()
|
||||||
*******************************************************************}
|
*
|
||||||
function button_press_cb(widget: PGtkWidget; event: PGdkEventButton;
|
* DESCRIPTION: Callback function for Mouse Click
|
||||||
user_data: gpointer): gboolean; cdecl;
|
*
|
||||||
var
|
* PARAMETERS: None
|
||||||
vwsTrayIcon: TCustomTrayIcon;
|
*
|
||||||
begin
|
* RETURNS: Nothing
|
||||||
vwsTrayIcon := TCustomTrayIcon(user_data);
|
*
|
||||||
|
*******************************************************************}
|
||||||
Result := False;
|
function button_press_cb(widget: PGtkWidget; event: PGdkEventButton;
|
||||||
|
user_data: gpointer): gboolean; cdecl;
|
||||||
if (event^._type = GDK_2BUTTON_PRESS) and Assigned(vwsTrayIcon.OnDblClick) then
|
var
|
||||||
vwsTrayIcon.OnDblClick(vwsTrayIcon)
|
vwsTrayIcon: TCustomTrayIcon;
|
||||||
else
|
begin
|
||||||
begin
|
vwsTrayIcon := TCustomTrayIcon(user_data);
|
||||||
case event^.button of
|
|
||||||
1: if Assigned(vwsTrayIcon.OnMouseDown) then
|
Result := False;
|
||||||
vwsTrayIcon.OnMouseDown(vwsTrayIcon, mbLeft, [], Round(event^.X), Round(event^.Y));
|
|
||||||
|
if (event^._type = GDK_2BUTTON_PRESS) and Assigned(vwsTrayIcon.OnDblClick) then
|
||||||
2: if Assigned(vwsTrayIcon.OnMouseDown) then
|
vwsTrayIcon.OnDblClick(vwsTrayIcon)
|
||||||
vwsTrayIcon.OnMouseDown(vwsTrayIcon, mbMiddle, [], Round(event^.X), Round(event^.Y));
|
else
|
||||||
|
begin
|
||||||
3: if Assigned(vwsTrayIcon.OnMouseDown) then
|
case event^.button of
|
||||||
vwsTrayIcon.OnMouseDown(vwsTrayIcon, mbRight, [], Round(event^.X), Round(event^.Y));
|
1: if Assigned(vwsTrayIcon.OnMouseDown) then
|
||||||
end;
|
vwsTrayIcon.OnMouseDown(vwsTrayIcon, mbLeft, [], Round(event^.X), Round(event^.Y));
|
||||||
end;
|
|
||||||
end;
|
2: if Assigned(vwsTrayIcon.OnMouseDown) then
|
||||||
|
vwsTrayIcon.OnMouseDown(vwsTrayIcon, mbMiddle, [], Round(event^.X), Round(event^.Y));
|
||||||
{*******************************************************************
|
|
||||||
* popup_cb ()
|
3: if Assigned(vwsTrayIcon.OnMouseDown) then
|
||||||
*
|
vwsTrayIcon.OnMouseDown(vwsTrayIcon, mbRight, [], Round(event^.X), Round(event^.Y));
|
||||||
* DESCRIPTION: Callback function for the popup menu
|
end;
|
||||||
*
|
end;
|
||||||
* PARAMETERS: None
|
end;
|
||||||
*
|
|
||||||
* RETURNS: Nothing
|
{*******************************************************************
|
||||||
*
|
* popup_cb ()
|
||||||
*******************************************************************}
|
*
|
||||||
function popup_cb(widget: PGtkWidget; user_data: gpointer): Boolean; cdecl;
|
* DESCRIPTION: Callback function for the popup menu
|
||||||
var
|
*
|
||||||
vwsTrayIcon: TCustomTrayIcon;
|
* PARAMETERS: None
|
||||||
begin
|
*
|
||||||
vwsTrayIcon := TCustomTrayIcon(user_data);
|
* RETURNS: Nothing
|
||||||
|
*
|
||||||
Result := True;
|
*******************************************************************}
|
||||||
|
function popup_cb(widget: PGtkWidget; user_data: gpointer): Boolean; cdecl;
|
||||||
if Assigned(vwsTrayIcon.PopUpMenu) then
|
var
|
||||||
vwsTrayIcon.PopUpMenu.PopUp(Mouse.CursorPos.X, Mouse.CursorPos.Y);
|
vwsTrayIcon: TCustomTrayIcon;
|
||||||
end;
|
begin
|
||||||
|
vwsTrayIcon := TCustomTrayIcon(user_data);
|
||||||
{*******************************************************************
|
|
||||||
* motion_cb ()
|
Result := True;
|
||||||
*
|
|
||||||
* DESCRIPTION: Callback function for the OnMouseMove event
|
if Assigned(vwsTrayIcon.PopUpMenu) then
|
||||||
*
|
vwsTrayIcon.PopUpMenu.PopUp(Mouse.CursorPos.X, Mouse.CursorPos.Y);
|
||||||
* PARAMETERS: None
|
end;
|
||||||
*
|
|
||||||
* RETURNS: Nothing
|
{*******************************************************************
|
||||||
*
|
* motion_cb ()
|
||||||
*******************************************************************}
|
*
|
||||||
function motion_cb(widget: PGtkWidget; event: PGdkEventMotion; user_data: gpointer): Boolean; cdecl;
|
* DESCRIPTION: Callback function for the OnMouseMove event
|
||||||
var
|
*
|
||||||
vwsTrayIcon: TCustomTrayIcon;
|
* PARAMETERS: None
|
||||||
begin
|
*
|
||||||
vwsTrayIcon := TCustomTrayIcon(user_data);
|
* RETURNS: Nothing
|
||||||
|
*
|
||||||
Result := False;
|
*******************************************************************}
|
||||||
|
function motion_cb(widget: PGtkWidget; event: PGdkEventMotion; user_data: gpointer): Boolean; cdecl;
|
||||||
if Assigned(vwsTrayIcon.OnMouseMove) then
|
var
|
||||||
vwsTrayIcon.OnMouseMove(vwsTrayIcon, [], Round(event^.X), Round(event^.Y));
|
vwsTrayIcon: TCustomTrayIcon;
|
||||||
end;
|
begin
|
||||||
|
vwsTrayIcon := TCustomTrayIcon(user_data);
|
||||||
{*******************************************************************
|
|
||||||
* TGtk2WSCustomTrayIcon.Hide ()
|
Result := False;
|
||||||
*
|
|
||||||
* DESCRIPTION: Hides the main tray icon of the program
|
if Assigned(vwsTrayIcon.OnMouseMove) then
|
||||||
*
|
vwsTrayIcon.OnMouseMove(vwsTrayIcon, [], Round(event^.X), Round(event^.Y));
|
||||||
* PARAMETERS: None
|
end;
|
||||||
*
|
|
||||||
* RETURNS: True if sucessfull, otherwise False
|
{*******************************************************************
|
||||||
*
|
* TGtk2WSCustomTrayIcon.Hide ()
|
||||||
*******************************************************************}
|
*
|
||||||
class function TGtk2WSCustomTrayIcon.Hide(const ATrayIcon: TCustomTrayIcon): Boolean;
|
* DESCRIPTION: Hides the main tray icon of the program
|
||||||
begin
|
*
|
||||||
Result := False;
|
* PARAMETERS: None
|
||||||
|
*
|
||||||
gtk_widget_destroy(GtkForm);
|
* RETURNS: True if sucessfull, otherwise False
|
||||||
|
*
|
||||||
GtkForm := nil;
|
*******************************************************************}
|
||||||
|
class function TGtk2WSCustomTrayIcon.Hide(const ATrayIcon: TCustomTrayIcon): Boolean;
|
||||||
g_object_unref(Tips);
|
var
|
||||||
|
TrayHandle: PGtk2WSTrayIconHandle absolute ATrayIcon.Handle;
|
||||||
Tips := nil;
|
begin
|
||||||
|
Result := False;
|
||||||
ATrayIcon.Handle := PtrInt(0);
|
|
||||||
|
gtk_widget_destroy(GtkForm);
|
||||||
Result := True;
|
|
||||||
end;
|
GtkForm := nil;
|
||||||
|
|
||||||
{*******************************************************************
|
g_object_unref(Tips);
|
||||||
* TGtk2WSCustomTrayIcon.Show ()
|
|
||||||
*
|
Tips := nil;
|
||||||
* DESCRIPTION: Shows the main tray icon of the program
|
|
||||||
*
|
{ Free and nil the handle }
|
||||||
* PARAMETERS: None
|
|
||||||
*
|
FreeMem(TrayHandle);
|
||||||
* RETURNS: True if sucessfull, otherwise False
|
|
||||||
*
|
TrayHandle := nil;
|
||||||
*******************************************************************}
|
|
||||||
class function TGtk2WSCustomTrayIcon.Show(const ATrayIcon: TCustomTrayIcon): Boolean;
|
Result := True;
|
||||||
var
|
end;
|
||||||
AImage: PGtkWidget;
|
|
||||||
begin
|
{*******************************************************************
|
||||||
Result := False;
|
* TGtk2WSCustomTrayIcon.Show ()
|
||||||
|
*
|
||||||
{*******************************************************************
|
* DESCRIPTION: Shows the main tray icon of the program
|
||||||
* Creates the GtkPlug
|
*
|
||||||
*******************************************************************}
|
* PARAMETERS: None
|
||||||
|
*
|
||||||
GtkForm := gtk_plug_new(0);
|
* RETURNS: True if sucessfull, otherwise False
|
||||||
|
*
|
||||||
Tips := gtk_tooltips_new;
|
*******************************************************************}
|
||||||
|
class function TGtk2WSCustomTrayIcon.Show(const ATrayIcon: TCustomTrayIcon): Boolean;
|
||||||
g_object_ref(Tips);
|
var
|
||||||
|
TrayHandle: PGtk2WSTrayIconHandle absolute ATrayIcon.Handle;
|
||||||
gtk_object_sink(GTK_OBJECT(Tips));
|
begin
|
||||||
|
Result := False;
|
||||||
gtk_tooltips_set_tip(GTK_TOOLTIPS(Tips), GtkForm, PChar(ATrayIcon.Hint), '');
|
|
||||||
|
ATrayIcon.Handle := PtrInt(GetMem(SizeOf(TGtk2WSTrayIconHandle)));
|
||||||
{*******************************************************************
|
|
||||||
* Connects the signals
|
{*******************************************************************
|
||||||
*******************************************************************}
|
* Creates the GtkPlug
|
||||||
|
*******************************************************************}
|
||||||
gtk_widget_add_events(GtkForm, GDK_ALL_EVENTS_MASK);
|
|
||||||
|
GtkForm := gtk_plug_new(0);
|
||||||
g_signal_connect(GtkForm, 'realize', TGCallback(@realize_cb), ATrayIcon);
|
|
||||||
|
Tips := gtk_tooltips_new;
|
||||||
g_signal_connect(GtkForm, 'popup-menu', TGCallback(@popup_cb), ATrayIcon);
|
|
||||||
|
g_object_ref(Tips);
|
||||||
g_signal_connect(GtkForm, 'motion-notify-event', TGCallback(@motion_cb), ATrayIcon);
|
|
||||||
|
gtk_object_sink(GTK_OBJECT(Tips));
|
||||||
g_signal_connect(GtkForm, 'button-press-event', TGCallback(@button_press_cb), ATrayIcon);
|
|
||||||
|
gtk_tooltips_set_tip(GTK_TOOLTIPS(Tips), GtkForm, PChar(ATrayIcon.Hint), '');
|
||||||
g_signal_connect(GtkForm, 'button-release-event', TGCallback(@button_release_cb), ATrayIcon);
|
|
||||||
|
{*******************************************************************
|
||||||
{*******************************************************************
|
* Connects the signals
|
||||||
* Draws the icon
|
*******************************************************************}
|
||||||
*******************************************************************}
|
|
||||||
|
gtk_widget_add_events(GtkForm, GDK_ALL_EVENTS_MASK);
|
||||||
AImage := gtk_image_new_from_pixbuf(PGdkPixbuf(ATrayIcon.Icon.Handle));
|
|
||||||
|
g_signal_connect(GtkForm, 'realize', TGCallback(@realize_cb), ATrayIcon);
|
||||||
gtk_widget_show(AImage);
|
|
||||||
|
g_signal_connect(GtkForm, 'popup-menu', TGCallback(@popup_cb), ATrayIcon);
|
||||||
gtk_container_add(GTK_CONTAINER(GtkForm), AImage);
|
|
||||||
|
g_signal_connect(GtkForm, 'motion-notify-event', TGCallback(@motion_cb), ATrayIcon);
|
||||||
{*******************************************************************
|
|
||||||
* Now shows the GtkPlug
|
g_signal_connect(GtkForm, 'button-press-event', TGCallback(@button_press_cb), ATrayIcon);
|
||||||
*******************************************************************}
|
|
||||||
|
g_signal_connect(GtkForm, 'button-release-event', TGCallback(@button_release_cb), ATrayIcon);
|
||||||
gtk_widget_show(GtkForm);
|
|
||||||
|
{*******************************************************************
|
||||||
{*******************************************************************
|
* Draws the icon
|
||||||
* We don't use the GtkPlug for anything, but we reuse the image
|
*******************************************************************}
|
||||||
* to update it in InternalUpdate, so we save the image
|
|
||||||
* as the handle
|
TrayHandle^.AImage := gtk_image_new_from_pixbuf(PGdkPixbuf(ATrayIcon.Icon.Handle));
|
||||||
*******************************************************************}
|
|
||||||
ATrayIcon.Handle := PtrInt(AImage);
|
gtk_widget_show(TrayHandle^.AImage);
|
||||||
|
|
||||||
Result := True;
|
gtk_container_add(GTK_CONTAINER(GtkForm), TrayHandle^.AImage);
|
||||||
end;
|
|
||||||
|
{*******************************************************************
|
||||||
{*******************************************************************
|
* Now shows the GtkPlug
|
||||||
* TGtk2WSCustomTrayIcon.InternalUpdate ()
|
*******************************************************************}
|
||||||
*
|
|
||||||
* DESCRIPTION: Makes modifications to the Icon while running
|
gtk_widget_show(GtkForm);
|
||||||
* i.e. without hiding it and showing again
|
|
||||||
*
|
Result := True;
|
||||||
* PARAMETERS: None
|
end;
|
||||||
*
|
|
||||||
* RETURNS: Nothing
|
{*******************************************************************
|
||||||
*
|
* TGtk2WSCustomTrayIcon.InternalUpdate ()
|
||||||
*******************************************************************}
|
*
|
||||||
class procedure TGtk2WSCustomTrayIcon.InternalUpdate(const ATrayIcon: TCustomTrayIcon);
|
* DESCRIPTION: Makes modifications to the Icon while running
|
||||||
var
|
* i.e. without hiding it and showing again
|
||||||
AImage: PGtkWidget;
|
*
|
||||||
AMask: PGdkBitmap;
|
* PARAMETERS: None
|
||||||
GDIObject: PgdiObject;
|
*
|
||||||
begin
|
* RETURNS: Nothing
|
||||||
// Updates the tooltips
|
*
|
||||||
if Assigned(Tips) then gtk_tooltips_set_tip(GTK_TOOLTIPS(Tips), GtkForm, PChar(ATrayIcon.Hint), '');
|
*******************************************************************}
|
||||||
|
class procedure TGtk2WSCustomTrayIcon.InternalUpdate(const ATrayIcon: TCustomTrayIcon);
|
||||||
// Updates the icon
|
var
|
||||||
|
TrayHandle: PGtk2WSTrayIconHandle absolute ATrayIcon.Handle;
|
||||||
AImage := PGtkWidget(ATrayIcon.Handle);
|
begin
|
||||||
|
// Updates the tooltips
|
||||||
if AImage <> nil then
|
if Assigned(Tips) then gtk_tooltips_set_tip(GTK_TOOLTIPS(Tips), GtkForm, PChar(ATrayIcon.Hint), '');
|
||||||
begin
|
|
||||||
GDIObject := PgdiObject(ATrayIcon.Icon.Handle);
|
// Updates the icon
|
||||||
|
|
||||||
AMask := CreateGdkMaskBitmap(
|
if (TrayHandle <> nil) and (TrayHandle^.AImage <> nil) then
|
||||||
GDIObject^.GDIPixmapObject.Mask,
|
begin
|
||||||
GDIObject^.GDIBitmapObject);
|
gtk_image_set_from_pixbuf(GTK_IMAGE(TrayHandle^.AImage), PGdkPixbuf(ATrayIcon.Icon.Handle));
|
||||||
|
end;
|
||||||
gtk_image_set_from_pixmap(GTK_IMAGE(AImage),GDIObject^.GDIPixmapObject.Image, AMask);
|
end;
|
||||||
|
|
||||||
g_object_unref(AMask);
|
{*******************************************************************
|
||||||
end;
|
* TGtk2WSCustomTrayIcon.GetPosition ()
|
||||||
end;
|
*
|
||||||
|
* DESCRIPTION: Returns the position of the tray icon on the display.
|
||||||
{*******************************************************************
|
* This function is utilized to show message boxes near
|
||||||
* TGtk2WSCustomTrayIcon.GetPosition ()
|
* the icon
|
||||||
*
|
*
|
||||||
* DESCRIPTION: Returns the position of the tray icon on the display.
|
* PARAMETERS: None
|
||||||
* This function is utilized to show message boxes near
|
*
|
||||||
* the icon
|
* RETURNS: Nothing
|
||||||
*
|
*
|
||||||
* PARAMETERS: None
|
*******************************************************************}
|
||||||
*
|
class function TGtk2WSCustomTrayIcon.GetPosition(const ATrayIcon: TCustomTrayIcon): TPoint;
|
||||||
* RETURNS: Nothing
|
var
|
||||||
*
|
WindowHandle: PGDKWindow;
|
||||||
*******************************************************************}
|
begin
|
||||||
class function TGtk2WSCustomTrayIcon.GetPosition(const ATrayIcon: TCustomTrayIcon): TPoint;
|
Result := Point(0, 0);
|
||||||
var
|
|
||||||
WindowHandle: PGDKWindow;
|
if not Assigned(GtkForm) then Exit;
|
||||||
begin
|
|
||||||
Result := Point(0, 0);
|
WindowHandle := GtkForm^.window;
|
||||||
|
|
||||||
if not Assigned(GtkForm) then Exit;
|
if not Assigned(WindowHandle) then Exit;
|
||||||
|
|
||||||
WindowHandle := GtkForm^.window;
|
gdk_window_get_origin(WindowHandle, @Result.X, @Result.Y);
|
||||||
|
end;
|
||||||
if not Assigned(WindowHandle) then Exit;
|
|
||||||
|
|
||||||
gdk_window_get_origin(WindowHandle, @Result.X, @Result.Y);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user