diff options
-rw-r--r-- | src/corelib/gdi/fpg_gdi.pas | 41 | ||||
-rw-r--r-- | src/corelib/gdi/fpg_interface.pas | 1 | ||||
-rw-r--r-- | src/corelib/gdi/fpgui_toolkit.lpk | 6 | ||||
-rw-r--r-- | src/corelib/gdi/fpgui_toolkit.pas | 2 | ||||
-rw-r--r-- | src/corelib/x11/fpg_interface.pas | 1 | ||||
-rw-r--r-- | src/corelib/x11/fpg_x11.pas | 93 | ||||
-rw-r--r-- | src/corelib/x11/fpgui_toolkit.lpk | 7 | ||||
-rw-r--r-- | src/corelib/x11/fpgui_toolkit.pas | 2 | ||||
-rw-r--r-- | src/gui/fpg_trayicon.pas | 166 |
9 files changed, 312 insertions, 7 deletions
diff --git a/src/corelib/gdi/fpg_gdi.pas b/src/corelib/gdi/fpg_gdi.pas index 311a4fce..fec0c511 100644 --- a/src/corelib/gdi/fpg_gdi.pas +++ b/src/corelib/gdi/fpg_gdi.pas @@ -304,8 +304,6 @@ type end; - { TfpgGDITimer } - TfpgGDITimer = class(TfpgBaseTimer) private FHandle: THandle; @@ -316,6 +314,16 @@ type end; + TfpgGDISystemTrayIcon = class(TfpgComponent) + public + constructor Create(AOwner: TComponent); override; + procedure Show; + procedure Hide; + function IsSystemTrayAvailable: boolean; + function SupportsMessages: boolean; + end; + + implementation uses @@ -3105,6 +3113,35 @@ begin end; +{ TfpgGDISystemTrayIcon } + +constructor TfpgGDISystemTrayIcon.Create(AOwner: TComponent); +begin + inherited Create(AOwner); +end; + +procedure TfpgGDISystemTrayIcon.Show; +begin + // +end; + +procedure TfpgGDISystemTrayIcon.Hide; +begin + // +end; + +function TfpgGDISystemTrayIcon.IsSystemTrayAvailable: boolean; +begin + Result := False; +end; + +function TfpgGDISystemTrayIcon.SupportsMessages: boolean; +begin + Result := True; +end; + + + initialization wapplication := nil; MouseFocusedWH := 0; diff --git a/src/corelib/gdi/fpg_interface.pas b/src/corelib/gdi/fpg_interface.pas index 8833f44d..5d5d4833 100644 --- a/src/corelib/gdi/fpg_interface.pas +++ b/src/corelib/gdi/fpg_interface.pas @@ -36,6 +36,7 @@ type TfpgMimeDataImpl = class(TfpgGDIMimeDataBase); TfpgDragImpl = class(TfpgGDIDrag); TfpgTimerImpl = class(TfpgGDITimer); + TfpgSystemTrayHandler = class(TfpgGDISystemTrayIcon); implementation diff --git a/src/corelib/gdi/fpgui_toolkit.lpk b/src/corelib/gdi/fpgui_toolkit.lpk index a4f927c2..7654d0d4 100644 --- a/src/corelib/gdi/fpgui_toolkit.lpk +++ b/src/corelib/gdi/fpgui_toolkit.lpk @@ -32,7 +32,7 @@ <Description Value="fpGUI Toolkit"/>
<License Value="LGPL 2 with static linking exception."/>
<Version Minor="8"/>
- <Files Count="96">
+ <Files Count="97">
<Item1>
<Filename Value="..\stdimages.inc"/>
<Type Value="Include"/>
@@ -417,6 +417,10 @@ <Filename Value="..\..\reportengine\u_visu.pas"/>
<UnitName Value="U_Visu"/>
</Item96>
+ <Item97>
+ <Filename Value="..\..\gui\fpg_trayicon.pas"/>
+ <UnitName Value="fpg_trayicon"/>
+ </Item97>
</Files>
<LazDoc Paths="../../../docs/xml/corelib;../../../docs/xml/corelib/x11;../../../docs/xml/corelib/gdi;../../../docs/xml/gui"/>
<RequiredPkgs Count="1">
diff --git a/src/corelib/gdi/fpgui_toolkit.pas b/src/corelib/gdi/fpgui_toolkit.pas index 5caa6228..7496bb18 100644 --- a/src/corelib/gdi/fpgui_toolkit.pas +++ b/src/corelib/gdi/fpgui_toolkit.pas @@ -21,7 +21,7 @@ uses fpg_interface, fpg_editbtn, fpg_imgfmt_jpg, fpg_imgutils, fpg_stylemanager,
fpg_style_win2k, fpg_style_motif, fpg_style_clearlooks, fpg_style_bluecurve,
fpg_style_bitmap, fpg_readonly, fpg_imgfmt_png, U_Command, U_Pdf, U_Report,
- U_ReportImages, U_Visu;
+ U_ReportImages, U_Visu, fpg_trayicon;
implementation
diff --git a/src/corelib/x11/fpg_interface.pas b/src/corelib/x11/fpg_interface.pas index 6f216179..aa30039f 100644 --- a/src/corelib/x11/fpg_interface.pas +++ b/src/corelib/x11/fpg_interface.pas @@ -36,6 +36,7 @@ type TfpgMimeDataImpl = class(TfpgX11MimeData); TfpgDragImpl = class(TfpgX11Drag); TfpgTimerImpl = class(TfpgX11Timer); + TfpgSystemTrayHandler = class(TfpgX11SystemTrayHandler); implementation diff --git a/src/corelib/x11/fpg_x11.pas b/src/corelib/x11/fpg_x11.pas index d1e83d93..046b2f74 100644 --- a/src/corelib/x11/fpg_x11.pas +++ b/src/corelib/x11/fpg_x11.pas @@ -118,6 +118,10 @@ const MWM_INPUT_SYSTEM_MODAL = 2; MWM_INPUT_FULL_APPLICATION_MODAL = 3; PROP_MWM_HINTS_ELEMENTS = 5; +// System Tray message opcodes + SYSTEM_TRAY_REQUEST_DOCK = 0; + SYSTEM_TRAY_BEGIN_MESSAGE = 1; + SYSTEM_TRAY_CANCEL_MESSAGE = 2; type TXWindowStateFlag = (xwsfMapped); @@ -392,6 +396,23 @@ type end; + TfpgX11SystemTrayHandler = class(TfpgComponent) + private + FTrayIconParent: TWindow; + FTrayWidget: TfpgWindowBase; + function GetTrayIconParent: TWindow; + function GetSysTrayWindow: TWindow; + function Send_Message(dest: TWindow; msg: longword; data1, data2, data3: longword): boolean; + property TrayIconParent: TWindow read GetTrayIconParent; + public + constructor Create(AOwner: TComponent); override; + procedure Show; + procedure Hide; + function IsSystemTrayAvailable: boolean; + function SupportsMessages: boolean; + end; + + function fpgColorToX(col: TfpgColor): longword; @@ -3674,6 +3695,78 @@ begin end; end; +{ TfpgX11SystemTrayHandler } + +function TfpgX11SystemTrayHandler.GetTrayIconParent: TWindow; +begin + if FTrayIconParent = None then + FTrayIconParent := GetSysTrayWindow; + Result := FTrayIconParent; +end; + +function TfpgX11SystemTrayHandler.GetSysTrayWindow: TWindow; +var + buf: array[0..32] of char; + selection_atom: TAtom; +begin + XGrabServer(xapplication.Display); + + buf := PChar('_NET_SYSTEM_TRAY_S' + IntToStr(xapplication.DefaultScreen)); + selection_atom := XInternAtom(xapplication.Display, buf, false); + Result := XGetSelectionOwner(xapplication.Display, selection_atom); + + XUngrabServer(xapplication.Display); +end; + +function TfpgX11SystemTrayHandler.Send_Message(dest: TWindow; msg: longword; data1, data2, data3: longword): boolean; +var + ev: TXEvent; +begin + FillChar(ev, SizeOf(TXEvent), 0); + + ev.xclient._type := ClientMessage; + ev.xclient.window := dest; { sender (tray icon window) } + ev.xclient.message_type := XInternAtom(xapplication.Display, '_NET_SYSTEM_TRAY_OPCODE', False ); + ev.xclient.format := 32; + + ev.xclient.data.l[0] := CurrentTime; + ev.xclient.data.l[1] := msg; { message opcode } + ev.xclient.data.l[2] := data1; + ev.xclient.data.l[3] := data2; + ev.xclient.data.l[4] := data3; + + Result := XSendEvent(xapplication.Display, TrayIconParent, False, NoEventMask, @ev) <> 0; + XSync(xapplication.Display, False); +end; + +procedure TfpgX11SystemTrayHandler.Show; +begin + Send_Message(TrayIconParent, SYSTEM_TRAY_REQUEST_DOCK, TfpgX11Window(Owner).WinHandle, 0, 0); +end; + +procedure TfpgX11SystemTrayHandler.Hide; +begin + TfpgX11Window(FTrayWidget).DoSetWindowVisible(False); +end; + +constructor TfpgX11SystemTrayHandler.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FTrayWidget := AOwner as TfpgWindowBase; + FTrayIconParent := None; +end; + +function TfpgX11SystemTrayHandler.IsSystemTrayAvailable: boolean; +begin + Result := GetSysTrayWindow <> None; +end; + +function TfpgX11SystemTrayHandler.SupportsMessages: boolean; +begin + Result := True; +end; + + initialization xapplication := nil; diff --git a/src/corelib/x11/fpgui_toolkit.lpk b/src/corelib/x11/fpgui_toolkit.lpk index dd6750db..5e61d76c 100644 --- a/src/corelib/x11/fpgui_toolkit.lpk +++ b/src/corelib/x11/fpgui_toolkit.lpk @@ -2,7 +2,6 @@ <CONFIG> <Package Version="4"> <Name Value="fpgui_toolkit"/> - <AddToProjectUsesSection Value="False"/> <Author Value="Graeme Geldenhuys"/> <CompilerOptions> <Version Value="11"/> @@ -30,7 +29,7 @@ <Description Value="fpGUI Toolkit"/> <License Value="LGPL 2 with static linking exception."/> <Version Minor="8"/> - <Files Count="97"> + <Files Count="98"> <Item1> <Filename Value="../stdimages.inc"/> <Type Value="Include"/> @@ -419,6 +418,10 @@ <Filename Value="../../reportengine/u_visu.pas"/> <UnitName Value="U_Visu"/> </Item97> + <Item98> + <Filename Value="../../gui/fpg_trayicon.pas"/> + <UnitName Value="fpg_trayicon"/> + </Item98> </Files> <LazDoc Paths="../../../docs/xml/corelib;../../../docs/xml/corelib/x11;../../../docs/xml/corelib/gdi;../../../docs/xml/gui"/> <RequiredPkgs Count="1"> diff --git a/src/corelib/x11/fpgui_toolkit.pas b/src/corelib/x11/fpgui_toolkit.pas index 1f957d56..a9fcc500 100644 --- a/src/corelib/x11/fpgui_toolkit.pas +++ b/src/corelib/x11/fpgui_toolkit.pas @@ -20,7 +20,7 @@ uses fpg_interface, fpg_editbtn, fpg_imgfmt_jpg, fpg_imgutils, fpg_stylemanager, fpg_style_win2k, fpg_style_motif, fpg_style_clearlooks, fpg_style_bluecurve, fpg_style_bitmap, fpg_readonly, fpg_imgfmt_png, U_Command, U_Pdf, U_Report, - U_ReportImages, U_Visu; + U_ReportImages, U_Visu, fpg_trayicon; implementation diff --git a/src/gui/fpg_trayicon.pas b/src/gui/fpg_trayicon.pas new file mode 100644 index 00000000..b439f085 --- /dev/null +++ b/src/gui/fpg_trayicon.pas @@ -0,0 +1,166 @@ +{ + fpGUI - Free Pascal GUI Toolkit + + Copyright (C) 2006 - 2012 See the file AUTHORS.txt, included in this + distribution, for details of the copyright. + + See the file COPYING.modifiedLGPL, included in this distribution, + for details about redistributing fpGUI. + + 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. + + Description: + This unit implements a class that provides an icon for an application + in the system tray. +} +unit fpg_trayicon; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, + SysUtils, + fpg_base, + fpg_main, + fpg_widget, + fpg_menu, + fpg_interface; + +type + + TfpgMessageIconType = (mitNoIcon, mitInformation, mitWarning, mitCritical); + + + TfpgSystemTrayIcon = class(TfpgWidget) + private + FPopupMenu: TfpgPopupMenu; + FImageName: TfpgString; + FImage: TfpgImage; + FOnMessageClicked: TNotifyEvent; + procedure SetImageName(AValue: TfpgString); + protected + FSysTrayHandler: TfpgSystemTrayHandler; + procedure SetVisible(const AValue: boolean); override; + procedure HandlePaint; override; + procedure HandleRMouseUp(x, y: integer; shiftstate: TShiftState); override; + public + constructor Create(AOwner: TComponent); override; + function IsSystemTrayAvailable: boolean; + function SupportsMessages: boolean; + procedure Show; + procedure Hide; + procedure ShowMessage(const ATitle: TfpgString; const AMessage: TfpgString; const AMessageIcon: TfpgMessageIconType; const AMillisecondsTimeoutHint: Word = 10000); + published + property BackgroundColor; + property Hint; + property ImageName: TfpgString read FImageName write SetImageName; + property PopupMenu: TfpgPopupMenu read FPopupMenu write FPopupMenu; + property ShowHint; + property OnClick; + property OnMessageClicked: TNotifyEvent read FOnMessageClicked write FOnMessageClicked; + property OnPaint; + end; + + +implementation + +{ TfpgSystemTrayIcon } + +procedure TfpgSystemTrayIcon.SetImageName(AValue: TfpgString); +begin + if FImageName = AValue then + Exit; + FImageName := AValue; + Repaint; +end; + +procedure TfpgSystemTrayIcon.SetVisible(const AValue: boolean); +begin + if FVisible = AValue then + Exit; + FVisible := AValue; + if FVisible then + Show + else + Hide; +end; + +procedure TfpgSystemTrayIcon.HandlePaint; +var + img: TfpgImage; +begin + inherited HandlePaint; + Canvas.Clear(FBackgroundColor); + if FImageName <> '' then + begin + { request a reference to already loaded image } + img := fpgImages.GetImage(FImageName); + if Assigned(img) then + begin + FCanvas.DrawImage((Width-img.Width) div 2, (Height-img.Height) div 2, img); + end; + end; +end; + +procedure TfpgSystemTrayIcon.HandleRMouseUp(x, y: integer; shiftstate: TShiftState); +begin + inherited HandleRMouseUp(x, y, shiftstate); + if Assigned(FPopupMenu) then + begin + FPopupMenu.ShowAt(self, x, y, True); + end; +end; + +constructor TfpgSystemTrayIcon.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FWidth := 20; + FHeight := 20; + FVisible := False; + + FHint := ''; + FImage := nil; + FImageName := ''; + FPopupMenu := nil; + + FSysTrayHandler := TfpgSystemTrayHandler.Create(self); +end; + +function TfpgSystemTrayIcon.IsSystemTrayAvailable: boolean; +begin + Result := FSysTrayHandler.IsSystemTrayAvailable; +end; + +function TfpgSystemTrayIcon.SupportsMessages: boolean; +begin + { TODO : As far as I know Mac OS X doesn't support this, though they do now + have this Notifications functionility since 10.8 } + Result := FSysTrayHandler.SupportsMessages; +end; + +procedure TfpgSystemTrayIcon.Show; +begin + FSysTrayHandler.Show; + FVisible := True; +end; + +procedure TfpgSystemTrayIcon.Hide; +begin + { TODO : TfpgSystemTrayIcon.Hide not implemented yet! } +// FVisible := False; +// FSysTrayHandler.Hide; +end; + +procedure TfpgSystemTrayIcon.ShowMessage(const ATitle: TfpgString; + const AMessage: TfpgString; const AMessageIcon: TfpgMessageIconType; + const AMillisecondsTimeoutHint: Word); +begin + { TODO : TfpgSystemTrayIcon.ShowMessage not implemented yet! } +end; + +end. + |