gtk2: add UseStatusIcon define and appropriate gtk2 code which uses GtkStatusIcon instead of X capabilities to show TrayIcon (can be used with fpc >= r13008 #a2bedef1b0)

git-svn-id: trunk@19400 -
This commit is contained in:
paul 2009-04-13 06:06:28 +00:00
parent 9622addb28
commit 3897ab3717
3 changed files with 161 additions and 87 deletions

View File

@ -23,27 +23,33 @@
{ TGtk2WSCustomTrayIcon }
type
{ TGtk2TrayIconHandle }
TGtk2TrayIconHandle = class
private
plug: PGtkWidget;
DrawingArea: PGtkWidget;
Tips: PGtkTooltips;
fEmbedded: Boolean;
fTrayIcon: TCustomTrayIcon;
{$ifdef UseStatusIcon}
FStatusIcon: PGtkStatusIcon;
{$endif}
{$ifdef HasGdk2X}
fDisplay: PDisplay;
fWindow: TWindow;
fScreen: PScreen;
fScreenID: longint;
fTrayParent: TWindow;
{$endif HasGdk2X}
Tips: PGtkTooltips;
fEmbedded: Boolean;
fTrayIcon: TCustomTrayIcon;
{$ifdef HasGdk2X}
function SendMessage(window: TWindow; msg: Integer; data1, data2, data3: Integer): Boolean;
procedure SetEmbedded;
{$endif HasGdk2X}
public
constructor Create(const wsTrayIcon: TCustomTrayIcon);
destructor Destroy; override;
procedure Show;
function GetPosition: TPoint;
procedure Update(NewPixBuf: PGdkPixbuf; NewHint: String);
end;
const
@ -159,21 +165,22 @@ procedure realize_cb(widget: PGtkWidget; user_data: gpointer); cdecl;
var
wsTrayIcon: TCustomTrayIcon absolute user_data;
begin
{$ifdef HasGdk2X}
with TGtk2TrayIconHandle(wsTrayIcon.Handle) do begin
with TGtk2TrayIconHandle(wsTrayIcon.Handle) do
begin
{$ifdef HasGdk2X}
fDisplay := GDK_WINDOW_XDISPLAY(plug^.window);
fWindow := GDK_WINDOW_XWINDOW(plug^.window);
{ Doesn´t work
{ Does not work
gdk_screen := gtk_widget_get_screen(plug);
fScreen := GDK_SCREEN_XSCREEN(gdk_screen); // get the real screen}
fScreen := XDefaultScreenOfDisplay(fDisplay);
fScreenID := XScreenNumberOfScreen(fScreen); // and it's number
SetEmbedded;
SetEmbedded;
{$endif}
end;
{$endif}
end;
{*******************************************************************
@ -189,10 +196,8 @@ end;
function button_release_cb(widget: PGtkWidget; event: PGdkEventButton;
user_data: gpointer): gboolean; cdecl;
var
vwsTrayIcon: TCustomTrayIcon;
vwsTrayIcon: TCustomTrayIcon absolute user_data;
begin
vwsTrayIcon := TCustomTrayIcon(user_data);
Result := False;
case event^.button of
@ -229,10 +234,8 @@ end;
function button_press_cb(widget: PGtkWidget; event: PGdkEventButton;
user_data: gpointer): gboolean; cdecl;
var
vwsTrayIcon: TCustomTrayIcon;
vwsTrayIcon: TCustomTrayIcon absolute user_data;
begin
vwsTrayIcon := TCustomTrayIcon(user_data);
Result := False;
if (event^._type = GDK_2BUTTON_PRESS) and Assigned(vwsTrayIcon.OnDblClick) then
@ -264,14 +267,12 @@ end;
*******************************************************************}
function popup_cb(widget: PGtkWidget; user_data: gpointer): Boolean; cdecl;
var
vwsTrayIcon: TCustomTrayIcon;
vwsTrayIcon: TCustomTrayIcon absolute user_data;
begin
vwsTrayIcon := TCustomTrayIcon(user_data);
Result := True;
if Assigned(vwsTrayIcon.PopUpMenu) then
vwsTrayIcon.PopUpMenu.PopUp(Mouse.CursorPos.X, Mouse.CursorPos.Y);
vwsTrayIcon.PopUpMenu.PopUp(Mouse.CursorPos.X, Mouse.CursorPos.Y);
end;
{*******************************************************************
@ -286,60 +287,153 @@ end;
*******************************************************************}
function motion_cb(widget: PGtkWidget; event: PGdkEventMotion; user_data: gpointer): Boolean; cdecl;
var
vwsTrayIcon: TCustomTrayIcon;
vwsTrayIcon: TCustomTrayIcon absolute user_data;
begin
vwsTrayIcon := TCustomTrayIcon(user_data);
Result := False;
if Assigned(vwsTrayIcon.OnMouseMove) then
vwsTrayIcon.OnMouseMove(vwsTrayIcon, [], Round(event^.X), Round(event^.Y));
end;
{$ifdef UseStatusIcon}
procedure activate_cb_statusicon(status_icon: PGtkStatusIcon; user_data: gpointer); cdecl;
var
vwsTrayIcon: TCustomTrayIcon absolute user_data;
begin
if Assigned(vwsTrayIcon.OnMouseDown) then
with Mouse.CursorPos do
vwsTrayIcon.OnMouseDown(vwsTrayIcon, mbLeft, [], X, Y);
end;
procedure popup_cb_statusicon(status_icon: PGtkStatusIcon; button: guint;
activate_time: guint; user_data: gpointer); cdecl;
var
vwsTrayIcon: TCustomTrayIcon absolute user_data;
begin
if Assigned(vwsTrayIcon.PopUpMenu) then
vwsTrayIcon.PopUpMenu.PopUp(Mouse.CursorPos.X, Mouse.CursorPos.Y);
end;
{$endif}
constructor TGtk2TrayIconHandle.Create(const wsTrayIcon: TCustomTrayIcon);
begin
fTrayIcon := wsTrayIcon;
{*******************************************************************
* Creates the GtkPlug
*******************************************************************}
plug := gtk_plug_new(0);
Tips := gtk_tooltips_new;
g_object_ref(Tips);
gtk_object_sink(GTK_OBJECT(Tips));
gtk_tooltips_set_tip(GTK_TOOLTIPS(Tips), plug, PChar(wsTrayIcon.Hint), '');
{*******************************************************************
* Connects the signals
*******************************************************************}
gtk_widget_add_events(plug, GDK_ALL_EVENTS_MASK);
g_signal_connect(plug, 'realize', TGCallback(@realize_cb), wsTrayIcon);
g_signal_connect(plug, 'popup-menu', TGCallback(@popup_cb), wsTrayIcon);
g_signal_connect(plug, 'motion-notify-event', TGCallback(@motion_cb), wsTrayIcon);
g_signal_connect(plug, 'button-press-event', TGCallback(@button_press_cb), wsTrayIcon);
g_signal_connect(plug, 'button-release-event', TGCallback(@button_release_cb), wsTrayIcon);
{*******************************************************************
* Draws the icon
*******************************************************************}
with wsTrayIcon do
{$ifdef UseStatusIcon}
FStatusIcon := nil;
if Available_GtkStatusIcon_2_10 then
begin
DrawingArea := gtk_image_new_from_pixbuf(PGdkPixbuf(Icon.Handle));
gtk_widget_show(DrawingArea);
gtk_container_add(GTK_CONTAINER(plug), DrawingArea);
FStatusIcon := gtk_status_icon_new();
gtk_status_icon_set_from_pixbuf(FStatusIcon, PGdkPixbuf(FTrayIcon.Icon.Handle));
gtk_status_icon_set_tooltip(FStatusIcon, PChar(FTrayIcon.Hint));
fEmbedded := gtk_status_icon_is_embedded(FStatusIcon);
g_signal_connect(FStatusIcon, 'activate', TGCallback(@activate_cb_statusicon), fTrayIcon);
g_signal_connect(FStatusIcon, 'popup-menu', TGCallback(@popup_cb_statusicon), fTrayIcon);
end
else
{$endif}
begin
// Creates the GtkPlug
plug := gtk_plug_new(0);
Tips := gtk_tooltips_new;
g_object_ref(Tips);
gtk_object_sink(GTK_OBJECT(Tips));
gtk_tooltips_set_tip(GTK_TOOLTIPS(Tips), plug, PChar(wsTrayIcon.Hint), '');
// Connects the signals
gtk_widget_add_events(plug, GDK_ALL_EVENTS_MASK);
g_signal_connect(plug, 'realize', TGCallback(@realize_cb), wsTrayIcon);
g_signal_connect(plug, 'popup-menu', TGCallback(@popup_cb), wsTrayIcon);
g_signal_connect(plug, 'motion-notify-event', TGCallback(@motion_cb), wsTrayIcon);
g_signal_connect(plug, 'button-press-event', TGCallback(@button_press_cb), wsTrayIcon);
g_signal_connect(plug, 'button-release-event', TGCallback(@button_release_cb), wsTrayIcon);
// Draws the icon
with wsTrayIcon do
begin
DrawingArea := gtk_image_new_from_pixbuf(PGdkPixbuf(Icon.Handle));
gtk_widget_show(DrawingArea);
gtk_container_add(GTK_CONTAINER(plug), DrawingArea);
end;
end;
end;
destructor TGtk2TrayIconHandle.Destroy;
begin
gtk_widget_destroy(plug);
plug := nil;
{$ifdef UseStatusIcon}
if FStatusIcon <> nil then
begin
g_object_unref(FStatusIcon);
FStatusIcon := nil;
end
else
{$endif}
begin
gtk_widget_destroy(plug);
plug := nil;
g_object_unref(Tips);
Tips := nil;
g_object_unref(Tips);
Tips := nil;
end;
end;
procedure TGtk2TrayIconHandle.Show;
begin
{$ifdef UseStatusIcon}
if FStatusIcon <> nil then
gtk_status_icon_set_visible(FStatusIcon, True)
else
{$endif}
gtk_widget_show(plug);
end;
function TGtk2TrayIconHandle.GetPosition: TPoint;
var
{$ifdef UseStatusIcon}
AScreen: PGdkScreen;
AArea: TGdkRectangle;
AOrientation: TGtkOrientation;
{$endif}
WindowHandle: PGDKWindow;
begin
{$ifdef UseStatusIcon}
if FStatusIcon <> nil then
begin
gtk_status_icon_get_geometry(FStatusIcon, @AScreen, @AArea, @AOrientation);
Result.x := AArea.x;
Result.y := AArea.y;
end
else
{$endif}
begin
if Assigned(plug) then
begin
WindowHandle := plug^.window;
if Assigned(WindowHandle) then
gdk_window_get_origin(WindowHandle, @Result.X, @Result.Y);
end;
end;
end;
procedure TGtk2TrayIconHandle.Update(NewPixBuf: PGdkPixbuf; NewHint: String);
begin
{$ifdef UseStatusIcon}
if FStatusIcon <> nil then
begin
gtk_status_icon_set_from_pixbuf(FStatusIcon, NewPixBuf);
gtk_status_icon_set_tooltip(FStatusIcon, PChar(NewHint));
end
else
{$endif}
begin
// Updates the tooltips
if Assigned(Tips) then
gtk_tooltips_set_tip(GTK_TOOLTIPS(Tips), plug, PChar(NewHint), '');
// Updates the icon
if Assigned(DrawingArea) then
gtk_image_set_from_pixbuf(GTK_IMAGE(DrawingArea), NewPixbuf);
end;
end;
{*******************************************************************
@ -384,14 +478,11 @@ begin
{*******************************************************************
* Now shows the GtkPlug
*******************************************************************}
with TrayIconHandle do
begin
gtk_widget_show(plug);
if fEmbedded then
Result := True
else
Hide(ATrayIcon);
end;
TrayIconHandle.Show;
if TrayIconHandle.fEmbedded then
Result := True
else
Hide(ATrayIcon);
end;
{*******************************************************************
@ -408,15 +499,7 @@ end;
class procedure TGtk2WSCustomTrayIcon.InternalUpdate(const ATrayIcon: TCustomTrayIcon);
begin
if ATrayIcon.Handle <> 0 then
with TGtk2TrayIconHandle(ATrayIcon.Handle) do
begin
// Updates the tooltips
if Assigned(Tips) then
gtk_tooltips_set_tip(GTK_TOOLTIPS(Tips), plug, PChar(ATrayIcon.Hint), '');
// Updates the icon
if Assigned(DrawingArea) then
gtk_image_set_from_pixbuf(GTK_IMAGE(DrawingArea), PGdkPixbuf(ATrayIcon.Icon.Handle));
end;
TGtk2TrayIconHandle(ATrayIcon.Handle).Update(PGdkPixbuf(ATrayIcon.Icon.Handle), ATrayIcon.Hint);
end;
{*******************************************************************
@ -432,19 +515,9 @@ end;
*
*******************************************************************}
class function TGtk2WSCustomTrayIcon.GetPosition(const ATrayIcon: TCustomTrayIcon): TPoint;
var
WindowHandle: PGDKWindow;
begin
Result := Point(0, 0);
if ATrayIcon.Handle <> 0 then
with TGtk2TrayIconHandle(ATrayIcon.Handle) do
begin
if not Assigned(plug) then
begin
WindowHandle := plug^.window;
if Assigned(WindowHandle) then
gdk_window_get_origin(WindowHandle, @Result.X, @Result.Y);
end;
end;
Result := TGtk2TrayIconHandle(ATrayIcon.Handle).GetPosition;
end;

View File

@ -23,6 +23,8 @@
unit Gtk2WSExtCtrls;
{$I ../gtk/gtkdefines.inc}
//{$define UseStatusIcon} // can be used only with fpc r13008
{$mode objfpc}{$H+}
@ -30,7 +32,7 @@ interface
uses
// libs
Math, GLib2, Gtk2, Gdk2, Gdk2Pixbuf, Gtk2Int, GtkProc, GtkDef,
Math, GLib2, Gtk2, Gdk2, Gdk2Pixbuf, Gtk2Int, GtkProc, GtkDef, {$ifdef UseStatusIcon}Gtk2Ext, {$endif}
// LCL
LCLProc, ExtCtrls, Classes, Controls, SysUtils, LCLType,
// widgetset

View File

@ -123,7 +123,6 @@ uses
GtkWSPrivate,
Gtk2WSPrivate;
// imglist
function RegisterCustomImageList: Boolean; alias : 'WSRegisterCustomImageList';
begin
@ -633,4 +632,4 @@ begin
Result := False;
end;
end.
end.