View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0023217 | Lazarus | IDE | public | 2012-10-26 19:03 | 2014-09-14 15:04 |
Reporter | zmey | Assigned To | Zeljan Rikalo | ||
Priority | normal | Severity | minor | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Product Version | 1.0.2 | ||||
Target Version | 1.2.6 | Fixed in Version | 1.3 (SVN) | ||
Summary | 0023217: OnMouseMove don't work with TTrayIcon | ||||
Description | No problem in Lazarus 0.9.30, but problem is in Lazarus>=1.0.1. | ||||
Additional Information | unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls; type { TForm1 } TForm1 = class(TForm) TrayIcon1: TTrayIcon; procedure FormCreate(Sender: TObject); procedure TrayIcon1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); private { private declarations } public { public declarations } end; var Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.TrayIcon1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin halt; end; procedure TForm1.FormCreate(Sender: TObject); begin TrayIcon1.Visible:=true; end; end. | ||||
Tags | No tags attached. | ||||
Fixed in Revision | 46221,46222,46223 | ||||
LazTarget | 1.2.6 | ||||
Widgetset | GTK 2, QT | ||||
Attached Files |
|
|
What widgetset ? |
|
gtk2 |
|
Yes bug present in Lazarus 1.0.2 Linux Gtk2 |
|
qt4 don't work also. |
|
When will be fix? |
|
Why is one year ago bug not assigned and closed? |
|
Because nobody have time for this ? Feel free to create patch and attach, so it will be fixed then. |
|
No problem with lazarus-0.9.30.4 Please, cancel your changes with TTrayIcon. |
|
lazarus_trayicon_onmousemove_mga.patch (6,196 bytes)
diff -ur lazarus.orig/lcl/interfaces/gtk2/gtk2trayicon.inc lazarus/lcl/interfaces/gtk2/gtk2trayicon.inc --- lazarus.orig/lcl/interfaces/gtk2/gtk2trayicon.inc 2012-04-17 11:55:52.000000000 +0400 +++ lazarus/lcl/interfaces/gtk2/gtk2trayicon.inc 2014-04-09 15:19:52.000000000 +0400 @@ -365,6 +365,16 @@ end; end; +function query_tooltip_cb_statusicon({%H-}status_icon: PGtkStatusIcon; + x: guint; y: guint; {%H-}keyboard_mode: gboolean; {%H-}tooltip: gpointer{PGtkTooltip}; user_data: gpointer): gboolean; cdecl; +var + vwsTrayIcon: TCustomTrayIcon absolute user_data; +begin + Result := FALSE; + + if Assigned(vwsTrayIcon.OnMouseMove) then + vwsTrayIcon.OnMouseMove(vwsTrayIcon, [], x, y); +end; {$endif} constructor TGtk2TrayIconHandle.Create(const wsTrayIcon: TCustomTrayIcon); @@ -378,12 +388,14 @@ FStatusIcon := gtk_status_icon_new(); gtk_status_icon_set_from_pixbuf(FStatusIcon, {%H-}PGdkPixbuf(FTrayIcon.Icon.Handle)); gtk_status_icon_set_tooltip(FStatusIcon, PChar(FTrayIcon.Hint)); + g_object_set(PGObject(FStatusIcon), 'has-tooltip', TRUE); 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); g_signal_connect(FStatusIcon, 'button-press-event', TGCallback(@button_press_cb_statusicon), fTrayIcon); g_signal_connect(FStatusIcon, 'button-release-event', TGCallback(@button_release_cb_statusicon), fTrayIcon); + g_signal_connect(FStatusIcon, 'query-tooltip', TGCallback(@query_tooltip_cb_statusicon), fTrayIcon); end else {$endif} @@ -407,8 +419,8 @@ with wsTrayIcon do begin DrawingArea := gtk_image_new_from_pixbuf({%H-}PGdkPixbuf(Icon.Handle)); - gtk_widget_show(DrawingArea); gtk_container_add(GTK_CONTAINER(plug), DrawingArea); + gtk_widget_show(DrawingArea); end; end; end; @@ -478,6 +490,7 @@ begin gtk_status_icon_set_from_pixbuf(FStatusIcon, NewPixBuf); gtk_status_icon_set_tooltip(FStatusIcon, PChar(NewHint)); + g_object_set(PGObject(FStatusIcon), 'has-tooltip', TRUE); end else {$endif} Только в lazarus/lcl/interfaces/gtk2: gtk2trayicon.inc.orig diff -ur lazarus.orig/lcl/interfaces/qt/qtobjects.pas lazarus/lcl/interfaces/qt/qtobjects.pas --- lazarus.orig/lcl/interfaces/qt/qtobjects.pas 2013-06-10 01:42:51.000000000 +0400 +++ lazarus/lcl/interfaces/qt/qtobjects.pas 2014-04-09 15:22:06.000000000 +0400 @@ -527,15 +527,17 @@ { TQtSystemTrayIcon } - TQtSystemTrayIcon = class(TObject) + TQtSystemTrayIcon = class(TQtObject) private FHook: QSystemTrayIcon_hookH; public - Handle: QSystemTrayIconH; FTrayIcon: TCustomTrayIcon; public constructor Create(vIcon: QIconH); virtual; destructor Destroy; override; + procedure AttachEvents; override; + procedure DetachEvents; override; + function EventFilter(Sender: QObjectH; Event: QEventH): Boolean; cdecl; override; public procedure setContextMenu(menu: QMenuH); procedure setIcon(icon: QIconH); @@ -3658,34 +3660,78 @@ inherited Create; if vIcon <> nil then - Handle := QSystemTrayIcon_create(vicon, nil) + TheObject := QObjectH(QSystemTrayIcon_create(vicon, nil)) else - Handle := QSystemTrayIcon_create(); - FHook := QSystemTrayIcon_hook_create(Handle); - QSystemTrayIcon_hook_hook_activated(FHook, @signalActivated); + TheObject := QObjectH(QSystemTrayIcon_create()); + AttachEvents; end; destructor TQtSystemTrayIcon.Destroy; begin - QSystemTrayIcon_hook_destroy(FHook); - QSystemTrayIcon_destroy(Handle); - inherited Destroy; end; +procedure TQtSystemTrayIcon.AttachEvents; +begin + FHook := QSystemTrayIcon_hook_create(QSystemTrayIconH(TheObject)); + QSystemTrayIcon_hook_hook_activated(FHook, @signalActivated); + inherited AttachEvents; +end; + +procedure TQtSystemTrayIcon.DetachEvents; +begin + if FHook <> nil then + QSystemTrayIcon_hook_destroy(FHook); + inherited DetachEvents; +end; + +function TQtSystemTrayIcon.EventFilter(Sender: QObjectH; Event: QEventH): Boolean; cdecl; +var + x, y: integer; + MousePos: TQtPoint; + IconGeometry: TRect; +begin + Result := False; + + if Assigned(FTrayIcon) then begin + case QEvent_type(Event) of + QEventMouseMove: + begin + x := QMouseEvent_x(QMouseEventH(Event)); + y := QMouseEvent_y(QMouseEventH(Event)); + + if Assigned(FTrayIcon.OnMouseMove) then + FTrayIcon.OnMouseMove(FTrayIcon, [], x, y); + end; + QEventToolTip, QEventWheel: + begin + QCursor_pos(@MousePos); + QSystemTrayIcon_geometry(QSystemTrayIconH(Sender), @IconGeometry); + x := MousePos.x - IconGeometry.Left; + y := MousePos.y - IconGeometry.Top; + + if Assigned(FTrayIcon.OnMouseMove) then + FTrayIcon.OnMouseMove(FTrayIcon, [], x, y); + end; + end; + end; + + QEvent_accept(Event); +end; + procedure TQtSystemTrayIcon.setContextMenu(menu: QMenuH); begin - QSystemTrayIcon_setContextMenu(handle, menu); + QSystemTrayIcon_setContextMenu(QSystemTrayIconH(TheObject), menu); end; procedure TQtSystemTrayIcon.setIcon(icon: QIconH); begin - QSystemTrayIcon_setIcon(handle, icon); + QSystemTrayIcon_setIcon(QSystemTrayIconH(TheObject), icon); end; procedure TQtSystemTrayIcon.setToolTip(tip: WideString); begin - QSystemTrayIcon_setToolTip(handle, @tip) + QSystemTrayIcon_setToolTip(QSystemTrayIconH(TheObject), @tip); end; procedure TQtSystemTrayIcon.signalActivated( @@ -3751,17 +3797,17 @@ begin WHint := GetUTF8String(AHint); WTitle := GetUTF8String(ATitle); - QSystemTrayIcon_showMessage(Handle, @WTitle, @WHint, AFlag, ATimeOut); + QSystemTrayIcon_showMessage(QSystemTrayIconH(TheObject), @WTitle, @WHint, AFlag, ATimeOut); end; procedure TQtSystemTrayIcon.Show; begin - QSystemTrayIcon_show(handle); + QSystemTrayIcon_show(QSystemTrayIconH(TheObject)); end; procedure TQtSystemTrayIcon.Hide; begin - QSystemTrayIcon_hide(handle); + QSystemTrayIcon_hide(QSystemTrayIconH(TheObject)); end; { TQtButtonGroup } Только в lazarus/lcl/interfaces/qt: qtobjects.pas.orig |
|
Patch with fix OnMouseMove for tTrayIcon for qt4 and gtk2 is in attachment (for lazarus 1.0.12). There is 1 sec. delay for qt4, but I can not fix, please look. Good for gtk2. |
|
@AlexL Qt4 patch isn't good. You have delay because it passes only QEventTooltip to the event filter and that's ONLY on X11 platforms.No other events are passed through event filter. See what QSysTrayIcon docs says: Only on X11, when a tooltip is requested, the QSystemTrayIcon receives a QHelpEvent of type QEvent::ToolTip. Additionally, the QSystemTrayIcon receives wheel events of type QEvent::Wheel. These are not supported on any other platform. http://qt-project.org/doc/qt-4.8/qsystemtrayicon.html#details Sorry, but your patch is unacceptable for qt part. Didn't test gtk2 one yet. |
|
Forgot to say that some object IS delivering events via QApplication eventFilter (I can see clear MouseMove etc.. over systrayicon) but dunno who can it be. Definitelly it's not QSysTrayIconH object by itself. It's thing to investigate. Just put QEventMouseMove in qtobject.inc in main app eventfilter and one writeln there and you'll see mouse move messages when moving mouse over systrayicon (at least it is so on X11, don't know for win and mac). |
|
Finally investigated: https://qt.gitorious.org/qt/ducklink-qt/source/3040e55a8d4fd4418ae4e76269ebbe0a25406adf:src/gui/util/qsystemtrayicon_win.cpp https://qt.gitorious.org/qt/ducklink-qt/source/3040e55a8d4fd4418ae4e76269ebbe0a25406adf:src/gui/util/qsystemtrayicon_x11.cpp MouseMove will be pretty tricky to implement for qt widgetset (so that it works on linux, win and mac). |
|
Only you can implement cross-platform solution. It's linux patch, and with patch is OK for linux now. It's better, than nothing within 1,5 years. Now you know problem looking patch and can fix. |
|
Didn't I say that your patch IS NOT GOOD in case of qt ? There's nothing to look into your patch since it does not change anything, and QEventToolTip isn't good to provide mouse move event. Maybe I'll fix it when I can be 100% sure that I've catched QSystemTrayIcon private QWidget in application eventfilter (maybe via direct x11 hook). |
|
In any case I have no win or mac, only linux. Maybe gtk2 is OK? |
|
I'll test gtk2 part and commit if it's ok. |
|
|
|
qtsystemtrayicon_events.diff (13,881 bytes)
Index: lcl/interfaces/qt/qtobjects.pas =================================================================== --- lcl/interfaces/qt/qtobjects.pas (revision 44672) +++ lcl/interfaces/qt/qtobjects.pas (working copy) @@ -520,28 +520,6 @@ property Handle: QCursorH read FHandle; end; - { TQtSystemTrayIcon } - - TQtSystemTrayIcon = class(TObject) - private - FHook: QSystemTrayIcon_hookH; - public - Handle: QSystemTrayIconH; - FTrayIcon: TCustomTrayIcon; - public - constructor Create(vIcon: QIconH); virtual; - destructor Destroy; override; - public - procedure setContextMenu(menu: QMenuH); - procedure setIcon(icon: QIconH); - procedure setToolTip(tip: WideString); - procedure signalActivated(AReason: QSystemTrayIconActivationReason); cdecl; - procedure showBaloonHint(const ATitle, AHint: String; - const AFlag: QSystemTrayIconMessageIcon; const ATimeOut: Integer); - procedure Show; - procedure Hide; - end; - { TQtButtonGroup } TQtButtonGroup = class(TObject) @@ -3690,119 +3668,6 @@ QPixmap_fromImage(retval, image, flags); end; -{ TQtSystemTrayIcon } - -constructor TQtSystemTrayIcon.Create(vIcon: QIconH); -begin - inherited Create; - - if vIcon <> nil then - Handle := QSystemTrayIcon_create(vicon, nil) - else - Handle := QSystemTrayIcon_create(); - FHook := QSystemTrayIcon_hook_create(Handle); - QSystemTrayIcon_hook_hook_activated(FHook, @signalActivated); -end; - -destructor TQtSystemTrayIcon.Destroy; -begin - QSystemTrayIcon_hook_destroy(FHook); - QSystemTrayIcon_destroy(Handle); - - inherited Destroy; -end; - -procedure TQtSystemTrayIcon.setContextMenu(menu: QMenuH); -begin - QSystemTrayIcon_setContextMenu(handle, menu); -end; - -procedure TQtSystemTrayIcon.setIcon(icon: QIconH); -begin - QSystemTrayIcon_setIcon(handle, icon); -end; - -procedure TQtSystemTrayIcon.setToolTip(tip: WideString); -begin - QSystemTrayIcon_setToolTip(handle, @tip) -end; - -procedure TQtSystemTrayIcon.signalActivated( - AReason: QSystemTrayIconActivationReason); cdecl; -var - MousePos: TQtPoint; -begin - if not Assigned(FTrayIcon) then - exit; - - QCursor_pos(@MousePos); - {$note: TODO: Mouse events of trayicon can be catched - in QApplication event filter (TQtWidgetSet.EventFilter), - so OnMouseDown and OnMouseUp can be properly sent. - Check if it works ok on qtwin32 and qtmac and - then replace this blind calls to mouse events. - To get systryicon object handle in application event filter - add property "lclsystrayicon" to this handle.} - case AReason of - QSystemTrayIconTrigger: - begin - if Assigned(FTrayIcon.OnMouseDown) then - FTrayIcon.OnMouseDown(FTrayIcon, mbLeft, [], MousePos.x, MousePos.y); - if Assigned(FTrayIcon.OnClick) then - FTrayIcon.OnClick(FTrayIcon); - if Assigned(FTrayIcon.OnMouseUp) then - FTrayIcon.OnMouseUp(FTrayIcon, mbLeft, [], MousePos.x, MousePos.y); - end; - QSystemTrayIconDoubleClick: - begin - if Assigned(FTrayIcon.OnMouseDown) then - FTrayIcon.OnMouseDown(FTrayIcon, mbLeft, [], MousePos.x, MousePos.y); - - if Assigned(FTrayIcon.OnDblClick) then - FTrayIcon.OnDblClick(FTrayIcon); - - if Assigned(FTrayIcon.OnMouseUp) then - FTrayIcon.OnMouseUp(FTrayIcon, mbLeft, [], MousePos.x, MousePos.y); - end; - QSystemTrayIconMiddleClick: - begin - if Assigned(FTrayIcon.OnMouseDown) then - FTrayIcon.OnMouseDown(FTrayIcon, mbMiddle, [], MousePos.x, MousePos.y); - if Assigned(FTrayIcon.OnMouseUp) then - FTrayIcon.OnMouseUp(FTrayIcon, mbMiddle, [], MousePos.x, MousePos.y); - end; - QSystemTrayIconContext: - begin - if Assigned(FTrayIcon.OnMouseDown) then - FTrayIcon.OnMouseDown(FTrayIcon, mbRight, [], MousePos.x, MousePos.y); - - if Assigned(FTrayIcon.OnMouseUp) then - FTrayIcon.OnMouseUp(FTrayIcon, mbRight, [], MousePos.x, MousePos.y); - end; - end; -end; - -procedure TQtSystemTrayIcon.showBaloonHint(const ATitle, AHint: String; - const AFlag: QSystemTrayIconMessageIcon; const ATimeOut: Integer); -var - WHint: WideString; - WTitle: WideString; -begin - WHint := GetUTF8String(AHint); - WTitle := GetUTF8String(ATitle); - QSystemTrayIcon_showMessage(Handle, @WTitle, @WHint, AFlag, ATimeOut); -end; - -procedure TQtSystemTrayIcon.Show; -begin - QSystemTrayIcon_show(handle); -end; - -procedure TQtSystemTrayIcon.Hide; -begin - QSystemTrayIcon_hide(handle); -end; - { TQtButtonGroup } constructor TQtButtonGroup.Create(AParent: QObjectH); Index: lcl/interfaces/qt/qtobject.inc =================================================================== --- lcl/interfaces/qt/qtobject.inc (revision 44672) +++ lcl/interfaces/qt/qtobject.inc (working copy) @@ -91,6 +91,7 @@ System.InitCriticalSection(CriticalSection); SavedHandlesList := TMap.Create(TMapIdType(ituPtrSize), SizeOf(TObject)); FSocketEventMap := TMap.Create(TMapIdType(its4), SizeOf(Pointer)); + SysTrayIconsList := TFPList.Create; StayOnTopList := nil; FAppActive := False; {$IFDEF HASX11} @@ -158,6 +159,13 @@ SavedHintHandlesList := nil; end; {$ENDIF} + + if SysTrayIconsList <> nil then + begin + SysTrayIconsList.Free; + SysTrayIconsList := nil; + end; + FSocketEventMap.Free; FGlobalActions.Free; @@ -547,6 +555,7 @@ ASequence: QKeySequenceH; AKey: WideString; AParent: QWidgetH; + R: TRect; function IsAnyWindowActive: Boolean; begin @@ -555,10 +564,102 @@ (QApplication_activePopupWidget() <> nil); end; + function IsSystemTrayWidget(AEventType: Cardinal): boolean; + var + AName: WideString; + AWidget: QWidgetH; + RGeom: TRect; + AFlags: QtWindowFlags; + i: Integer; + begin + Result := False; + if QObject_isWidgetType(Sender) then + begin + AWidget := QWidgetH(Sender); + QObject_objectName(Sender, @AName); + if UTF8Copy(AName, 1, 16) = 'qtlclsystrayicon' then + begin + for i := 0 to SysTrayIconsList.Count - 1 do + begin + RGeom := TQtSystemTrayIcon(SysTrayIconsList.Items[i]).GetGeometry; + if TQtSystemTrayIcon(SysTrayIconsList.Items[i]).SysTrayWidget = nil then + begin + if QApplication_widgetAt(RGeom.Left, RGeom.Top) = AWidget then + TQtSystemTrayIcon(SysTrayIconsList.Items[i]).AttachSysTrayWidget(AWidget); + end; + end; + exit(True); + end; + if QWidget_isWindow(AWidget) and (QWidget_parentWidget(AWidget) = nil) then + begin + AFlags := QWidget_windowFlags(AWidget); + if QWidget_testAttribute(AWidget, QtWA_AlwaysShowToolTips) and + QWidget_testAttribute(AWidget, QtWA_PaintOnScreen) and + QWidget_testAttribute(AWidget, QtWA_NoSystemBackground) and + not QWidget_testAttribute(AWidget, QtWA_QuitOnClose) and + (AFlags and QtFramelessWindowHint = QtFramelessWindowHint) and + (AFlags and QtX11BypassWindowManagerHint = QtX11BypassWindowManagerHint) then + begin + if HwndFromWidgetH(AWidget) = 0 then + begin + // we must find it by geometry, but it's innacurate since + // qt systrayicon widget returns -1,-1 for left & top, so we + // use QApplication_widgetAt(). + // Another problem is that QSystemTrayIcon geometry is updated + // too late, much after QEventShow/QEventShowToParent + // so no way to catch private QWidget until we enter + // it by mouse. + for i := 0 to SysTrayIconsList.Count - 1 do + begin + RGeom := TQtSystemTrayIcon(SysTrayIconsList.Items[i]).GetGeometry; + if QApplication_widgetAt(RGeom.Left, RGeom.Top) = AWidget then + begin + AName := 'qtlclsystrayicon_' + dbgHex(PtrUInt(AWidget)); + QObject_setObjectName(Sender, @AName); + TQtSystemTrayIcon(SysTrayIconsList.Items[i]).AttachSysTrayWidget(AWidget); + {$IFDEF DEBUGSYSTRAYICON} + DebugLn('Attached systemtrayicon[',dbgs(I),'] with geometry ',dbgs(RGeom),' dbg=', + dbgsName(TQtSystemTrayIcon(SysTrayIconsList.Items[i]).FTrayIcon)); + {$ENDIF} + TQtSystemTrayIcon(SysTrayIconsList.Items[i]).UpdateSystemTrayWidget; + Result := True; + break; + end; + end; + end; + end; + end; + end; + end; + begin Result := False; + + // find QSystemTrayIcon + if QObject_isWidgetType(Sender) and (QObject_parent(Sender) = nil) and + QWidget_isWindow(QWidgetH(Sender)) and + (QWidget_focusPolicy(QWidgetH(Sender)) = QtNoFocus) then + begin + AParent := QWidgetH(Sender); + QWidget_frameGeometry(AParent, @R); + if (R.Left = -1) and (R.Top = -1) and (R.Right > 0) and (R.Bottom > 0) then + begin + {$IFDEF DEBUGSYSTRAYICON} + DebugLn('EVENT: ',dbgs(QEvent_type(Event)),' Sender 0x',dbgHex(PtrUInt(Sender)),' geometry ',dbgs(R)); + {$ENDIF} + if (QEvent_type(Event) = QEventShowToParent) or (QEvent_type(Event) = QEventEnter) then + begin + if IsSystemTrayWidget(QEvent_type(Event)) then + begin + {$IFDEF DEBUGSYSTRAYICON} + DebugLn('Found SystemTrayIcon via event ',dbgs(QEvent_type(Event)),' SYSTRAYICON 0x',dbgHex(PtrUInt(Sender))); + {$ENDIF} + end; + end; + end; + end; + case QEvent_type(Event) of - QEventShortcutOverride: // issue #22827 begin QKeyEvent_text(QKeyEventH(Event), @AKey); @@ -1142,6 +1243,21 @@ System.LeaveCriticalsection(CriticalSection); end; +procedure TQtWidgetSet.RegisterSysTrayIcon(AHandle: TObject); +begin + SysTrayIconsList.Add(AHandle); +end; + +procedure TQtWidgetSet.UnRegisterSysTrayIcon(AHandle: TObject); +begin + SysTrayIconsList.Remove(AHandle); +end; + +function TQtWidgetSet.IsValidSysTrayIcon(AHandle: HWND): Boolean; +begin + Result := SysTrayIconsList.IndexOf(TObject(AHandle)) >= 0; +end; + {$IFDEF HASX11} procedure TQtWidgetSet.AddHintHandle(AHandle: TObject); begin Index: lcl/interfaces/qt/qtwsextctrls.pp =================================================================== --- lcl/interfaces/qt/qtwsextctrls.pp (revision 44672) +++ lcl/interfaces/qt/qtwsextctrls.pp (working copy) @@ -25,7 +25,7 @@ uses // Bindings qt4, - qtwidgets, qtobjects, qtproc, QtWSControls, + qtwidgets, qtobjects, qtsystemtrayicon, qtproc, QtWSControls, // LCL LCLProc, SysUtils, Classes, Controls, Graphics, Forms, ExtCtrls, LCLType, @@ -152,6 +152,7 @@ class procedure InternalUpdate(const ATrayIcon: TCustomTrayIcon); override; class function ShowBalloonHint(const ATrayIcon: TCustomTrayIcon): Boolean; override; class function GetPosition(const ATrayIcon: TCustomTrayIcon): TPoint; override; + class function GetCanvas(const ATrayIcon: TCustomTrayIcon): TCanvas; override; end; implementation @@ -334,6 +335,9 @@ if Assigned(ATrayIcon.PopUpMenu) then if TQtMenu(ATrayIcon.PopUpMenu.Handle).Widget <> nil then SystemTrayIcon.setContextMenu(QMenuH(TQtMenu(ATrayIcon.PopUpMenu.Handle).Widget)); + + SystemTrayIcon.UpdateSystemTrayWidget; + end; class function TQtWSCustomTrayIcon.ShowBalloonHint( @@ -355,6 +359,17 @@ class function TQtWSCustomTrayIcon.GetPosition(const ATrayIcon: TCustomTrayIcon): TPoint; begin Result := Point(0, 0); + if (ATrayIcon.Handle = 0) then + exit; + Result := TQtSystemTrayIcon(ATrayIcon.Handle).GetPosition; end; +class function TQtWSCustomTrayIcon.GetCanvas(const ATrayIcon: TCustomTrayIcon + ): TCanvas; +begin + Result := nil; + if (ATrayIcon.Handle <> 0) then + Result := TQtSystemTrayIcon(ATrayIcon.Handle).Canvas; +end; + end. Index: lcl/interfaces/qt/qtint.pp =================================================================== --- lcl/interfaces/qt/qtint.pp (revision 44672) +++ lcl/interfaces/qt/qtint.pp (working copy) @@ -65,6 +65,7 @@ SavedHandlesList: TMap; FSocketEventMap: TMap; StayOnTopList: TMap; + SysTrayIconsList: TFPList; // global hooks FAppEvenFilterHook: QObject_hookH; FAppFocusChangedHook: QApplication_hookH; @@ -157,6 +158,11 @@ procedure RemoveHandle(AHandle: TObject); function IsValidHandle(AHandle: HWND): Boolean; + // qt systray icons map + procedure RegisterSysTrayIcon(AHandle: TObject); + procedure UnRegisterSysTrayIcon(AHandle: TObject); + function IsValidSysTrayIcon(AHandle: HWND): Boolean; + {$IFDEF HASX11} // qt hints handles map (needed on X11 only) procedure AddHintHandle(AHandle: TObject); @@ -307,7 +313,7 @@ //////////////////////////////////////////////////// Graphics, buttons, Menus, // Bindings - qtprivate, qtwidgets, qtobjects; + qtprivate, qtwidgets, qtobjects, qtsystemtrayicon; function DTFlagsToQtFlags(const Flags: Cardinal): Integer; begin Index: lcl/interfaces/lcl.lpk =================================================================== --- lcl/interfaces/lcl.lpk (revision 44672) +++ lcl/interfaces/lcl.lpk (working copy) @@ -129,7 +129,7 @@ <License Value="modified LGPL-2 "/> <Version Major="1" Minor="3"/> - <Files Count="429"> + <Files Count="430"> <Item1> <Filename Value="carbon/agl.pp"/> <AddToUsesPkgSection Value="False"/> @@ -2135,6 +2135,11 @@ <AddToUsesPkgSection Value="False"/> <UnitName Value="LazPangoCairo1"/> </Item429> + <Item430> + <Filename Value="qt/qtsystemtrayicon.pas"/> + <AddToUsesPkgSection Value="False"/> + <UnitName Value="qtsystemtrayicon"/> + </Item430> </Files> <LazDoc Paths="../../docs/xml/lcl"/> <i18n> |
|
I've attached possible patch + qtsystemtray.pas unit which should be added with patch to lcl/interfaces/qt since TQtSystemTrayIcon is moved from qtobjects.pas to that unit. Everything is fine except that under X11 qt does not provide correct geometry to QSystemTrayIcon when private QWidget is shown so we cannot catch anything without hw interaction (mouse enter into private QWidget of QSystemTrayIcon). Besides that OnMouseMove, and OnPaint works when private QWidget is catched in main TQtWidgetSet.EventFilter(). |
|
Zeljan, hello, Did you look gtk2 part of patch? It will be good to fix this bug before new lazarus's version. |
|
lazarus-1.2.4-mga-qtsystemtrayicon-events.patch (14,042 bytes)
diff -ur lazarus.orig/lcl/interfaces/lcl.lpk lazarus/lcl/interfaces/lcl.lpk --- lazarus.orig/lcl/interfaces/lcl.lpk 2014-06-14 09:36:52.000000000 +0400 +++ lazarus/lcl/interfaces/lcl.lpk 2014-09-02 17:58:51.000000000 +0400 @@ -129,7 +129,7 @@ <License Value="modified LGPL-2 "/> <Version Major="1" Minor="2" Release="4"/> - <Files Count="429"> + <Files Count="430"> <Item1> <Filename Value="carbon/agl.pp"/> <AddToUsesPkgSection Value="False"/> @@ -2134,6 +2134,11 @@ <AddToUsesPkgSection Value="False"/> <UnitName Value="LazPangoCairo1"/> </Item429> + <Item430> + <Filename Value="qt/qtsystemtrayicon.pas"/> + <AddToUsesPkgSection Value="False"/> + <UnitName Value="qtsystemtrayicon"/> + </Item430> </Files> <LazDoc Paths="../../docs/xml/lcl"/> <i18n> diff -ur lazarus.orig/lcl/interfaces/qt/qtint.pp lazarus/lcl/interfaces/qt/qtint.pp --- lazarus.orig/lcl/interfaces/qt/qtint.pp 2014-05-09 18:33:04.000000000 +0400 +++ lazarus/lcl/interfaces/qt/qtint.pp 2014-09-02 17:57:54.000000000 +0400 @@ -65,6 +65,7 @@ SavedHandlesList: TMap; FSocketEventMap: TMap; StayOnTopList: TMap; + SysTrayIconsList: TFPList; // global hooks FAppEvenFilterHook: QObject_hookH; FAppFocusChangedHook: QApplication_hookH; @@ -156,6 +157,11 @@ procedure AddHandle(AHandle: TObject); procedure RemoveHandle(AHandle: TObject); function IsValidHandle(AHandle: HWND): Boolean; + + // qt systray icons map + procedure RegisterSysTrayIcon(AHandle: TObject); + procedure UnRegisterSysTrayIcon(AHandle: TObject); + function IsValidSysTrayIcon(AHandle: HWND): Boolean; {$IFDEF HASX11} // qt hints handles map (needed on X11 only) @@ -311,7 +317,7 @@ //////////////////////////////////////////////////// Graphics, buttons, Menus, // Bindings - qtprivate, qtwidgets, qtobjects; + qtprivate, qtwidgets, qtobjects, qtsystemtrayicon; function DTFlagsToQtFlags(const Flags: Cardinal): Integer; begin diff -ur lazarus.orig/lcl/interfaces/qt/qtobject.inc lazarus/lcl/interfaces/qt/qtobject.inc --- lazarus.orig/lcl/interfaces/qt/qtobject.inc 2014-05-07 19:56:22.000000000 +0400 +++ lazarus/lcl/interfaces/qt/qtobject.inc 2014-09-02 17:54:19.000000000 +0400 @@ -91,6 +91,7 @@ System.InitCriticalSection(CriticalSection); SavedHandlesList := TMap.Create(TMapIdType(ituPtrSize), SizeOf(TObject)); FSocketEventMap := TMap.Create(TMapIdType(its4), SizeOf(Pointer)); + SysTrayIconsList := TFPList.Create; StayOnTopList := nil; FAppActive := False; {$IFDEF HASX11} @@ -158,6 +159,13 @@ SavedHintHandlesList := nil; end; {$ENDIF} + + if SysTrayIconsList <> nil then + begin + SysTrayIconsList.Free; + SysTrayIconsList := nil; + end; + FSocketEventMap.Free; FGlobalActions.Free; @@ -547,6 +555,7 @@ ASequence: QKeySequenceH; AKey: WideString; AParent: QWidgetH; + R: TRect; function IsAnyWindowActive: Boolean; begin @@ -555,8 +564,101 @@ (QApplication_activePopupWidget() <> nil); end; + function IsSystemTrayWidget(AEventType: Cardinal): boolean; + var + AName: WideString; + AWidget: QWidgetH; + RGeom: TRect; + AFlags: QtWindowFlags; + i: Integer; + begin + Result := False; + if QObject_isWidgetType(Sender) then + begin + AWidget := QWidgetH(Sender); + QObject_objectName(Sender, @AName); + if UTF8Copy(AName, 1, 16) = 'qtlclsystrayicon' then + begin + for i := 0 to SysTrayIconsList.Count - 1 do + begin + RGeom := TQtSystemTrayIcon(SysTrayIconsList.Items[i]).GetGeometry; + if TQtSystemTrayIcon(SysTrayIconsList.Items[i]).SysTrayWidget = nil then + begin + if QApplication_widgetAt(RGeom.Left, RGeom.Top) = AWidget then + TQtSystemTrayIcon(SysTrayIconsList.Items[i]).AttachSysTrayWidget(AWidget); + end; + end; + exit(True); + end; + if QWidget_isWindow(AWidget) and (QWidget_parentWidget(AWidget) = nil) then + begin + AFlags := QWidget_windowFlags(AWidget); + if QWidget_testAttribute(AWidget, QtWA_AlwaysShowToolTips) and + QWidget_testAttribute(AWidget, QtWA_PaintOnScreen) and + QWidget_testAttribute(AWidget, QtWA_NoSystemBackground) and + not QWidget_testAttribute(AWidget, QtWA_QuitOnClose) and + (AFlags and QtFramelessWindowHint = QtFramelessWindowHint) and + (AFlags and QtX11BypassWindowManagerHint = QtX11BypassWindowManagerHint) then + begin + if HwndFromWidgetH(AWidget) = 0 then + begin + // we must find it by geometry, but it's innacurate since + // qt systrayicon widget returns -1,-1 for left & top, so we + // use QApplication_widgetAt(). + // Another problem is that QSystemTrayIcon geometry is updated + // too late, much after QEventShow/QEventShowToParent + // so no way to catch private QWidget until we enter + // it by mouse. + for i := 0 to SysTrayIconsList.Count - 1 do + begin + RGeom := TQtSystemTrayIcon(SysTrayIconsList.Items[i]).GetGeometry; + if QApplication_widgetAt(RGeom.Left, RGeom.Top) = AWidget then + begin + AName := 'qtlclsystrayicon_' + dbgHex(PtrUInt(AWidget)); + QObject_setObjectName(Sender, @AName); + TQtSystemTrayIcon(SysTrayIconsList.Items[i]).AttachSysTrayWidget(AWidget); + {$IFDEF DEBUGSYSTRAYICON} + DebugLn('Attached systemtrayicon[',dbgs(I),'] with geometry ',dbgs(RGeom),' dbg=', + dbgsName(TQtSystemTrayIcon(SysTrayIconsList.Items[i]).FTrayIcon)); + {$ENDIF} + TQtSystemTrayIcon(SysTrayIconsList.Items[i]).UpdateSystemTrayWidget; + Result := True; + break; + end; + end; + end; + end; + end; + end; + end; + begin Result := False; + + // find QSystemTrayIcon + if QObject_isWidgetType(Sender) and (QObject_parent(Sender) = nil) and + QWidget_isWindow(QWidgetH(Sender)) and + (QWidget_focusPolicy(QWidgetH(Sender)) = QtNoFocus) then + begin + AParent := QWidgetH(Sender); + QWidget_frameGeometry(AParent, @R); + if (R.Left = -1) and (R.Top = -1) and (R.Right > 0) and (R.Bottom > 0) then + begin + {$IFDEF DEBUGSYSTRAYICON} + DebugLn('EVENT: ',dbgs(QEvent_type(Event)),' Sender 0x',dbgHex(PtrUInt(Sender)),' geometry ',dbgs(R)); + {$ENDIF} + if (QEvent_type(Event) = QEventShowToParent) or (QEvent_type(Event) = QEventEnter) then + begin + if IsSystemTrayWidget(QEvent_type(Event)) then + begin + {$IFDEF DEBUGSYSTRAYICON} + DebugLn('Found SystemTrayIcon via event ',dbgs(QEvent_type(Event)),' SYSTRAYICON 0x',dbgHex(PtrUInt(Sender))); + {$ENDIF} + end; + end; + end; + end; + case QEvent_type(Event) of QEventShortcutOverride: // issue #22827 begin @@ -1140,6 +1242,21 @@ System.LeaveCriticalsection(CriticalSection); end; +procedure TQtWidgetSet.RegisterSysTrayIcon(AHandle: TObject); +begin + SysTrayIconsList.Add(AHandle); +end; + +procedure TQtWidgetSet.UnRegisterSysTrayIcon(AHandle: TObject); +begin + SysTrayIconsList.Remove(AHandle); +end; + +function TQtWidgetSet.IsValidSysTrayIcon(AHandle: HWND): Boolean; +begin + Result := SysTrayIconsList.IndexOf(TObject(AHandle)) >= 0; +end; + procedure TQtWidgetSet.RemoveHandle(AHandle: TObject); begin System.EnterCriticalsection(CriticalSection); diff -ur lazarus.orig/lcl/interfaces/qt/qtobjects.pas lazarus/lcl/interfaces/qt/qtobjects.pas --- lazarus.orig/lcl/interfaces/qt/qtobjects.pas 2014-05-13 01:17:16.000000000 +0400 +++ lazarus/lcl/interfaces/qt/qtobjects.pas 2014-09-02 17:50:35.000000000 +0400 @@ -520,28 +520,6 @@ property Handle: QCursorH read FHandle; end; - { TQtSystemTrayIcon } - - TQtSystemTrayIcon = class(TObject) - private - FHook: QSystemTrayIcon_hookH; - public - Handle: QSystemTrayIconH; - FTrayIcon: TCustomTrayIcon; - public - constructor Create(vIcon: QIconH); virtual; - destructor Destroy; override; - public - procedure setContextMenu(menu: QMenuH); - procedure setIcon(icon: QIconH); - procedure setToolTip(tip: WideString); - procedure signalActivated(AReason: QSystemTrayIconActivationReason); cdecl; - procedure showBaloonHint(const ATitle, AHint: String; - const AFlag: QSystemTrayIconMessageIcon; const ATimeOut: Integer); - procedure Show; - procedure Hide; - end; - { TQtButtonGroup } TQtButtonGroup = class(TObject) @@ -3690,119 +3668,6 @@ QPixmap_fromImage(retval, image, flags); end; -{ TQtSystemTrayIcon } - -constructor TQtSystemTrayIcon.Create(vIcon: QIconH); -begin - inherited Create; - - if vIcon <> nil then - Handle := QSystemTrayIcon_create(vicon, nil) - else - Handle := QSystemTrayIcon_create(); - FHook := QSystemTrayIcon_hook_create(Handle); - QSystemTrayIcon_hook_hook_activated(FHook, @signalActivated); -end; - -destructor TQtSystemTrayIcon.Destroy; -begin - QSystemTrayIcon_hook_destroy(FHook); - QSystemTrayIcon_destroy(Handle); - - inherited Destroy; -end; - -procedure TQtSystemTrayIcon.setContextMenu(menu: QMenuH); -begin - QSystemTrayIcon_setContextMenu(handle, menu); -end; - -procedure TQtSystemTrayIcon.setIcon(icon: QIconH); -begin - QSystemTrayIcon_setIcon(handle, icon); -end; - -procedure TQtSystemTrayIcon.setToolTip(tip: WideString); -begin - QSystemTrayIcon_setToolTip(handle, @tip) -end; - -procedure TQtSystemTrayIcon.signalActivated( - AReason: QSystemTrayIconActivationReason); cdecl; -var - MousePos: TQtPoint; -begin - if not Assigned(FTrayIcon) then - exit; - - QCursor_pos(@MousePos); - {$note: TODO: Mouse events of trayicon can be catched - in QApplication event filter (TQtWidgetSet.EventFilter), - so OnMouseDown and OnMouseUp can be properly sent. - Check if it works ok on qtwin32 and qtmac and - then replace this blind calls to mouse events. - To get systryicon object handle in application event filter - add property "lclsystrayicon" to this handle.} - case AReason of - QSystemTrayIconTrigger: - begin - if Assigned(FTrayIcon.OnMouseDown) then - FTrayIcon.OnMouseDown(FTrayIcon, mbLeft, [], MousePos.x, MousePos.y); - if Assigned(FTrayIcon.OnClick) then - FTrayIcon.OnClick(FTrayIcon); - if Assigned(FTrayIcon.OnMouseUp) then - FTrayIcon.OnMouseUp(FTrayIcon, mbLeft, [], MousePos.x, MousePos.y); - end; - QSystemTrayIconDoubleClick: - begin - if Assigned(FTrayIcon.OnMouseDown) then - FTrayIcon.OnMouseDown(FTrayIcon, mbLeft, [], MousePos.x, MousePos.y); - - if Assigned(FTrayIcon.OnDblClick) then - FTrayIcon.OnDblClick(FTrayIcon); - - if Assigned(FTrayIcon.OnMouseUp) then - FTrayIcon.OnMouseUp(FTrayIcon, mbLeft, [], MousePos.x, MousePos.y); - end; - QSystemTrayIconMiddleClick: - begin - if Assigned(FTrayIcon.OnMouseDown) then - FTrayIcon.OnMouseDown(FTrayIcon, mbMiddle, [], MousePos.x, MousePos.y); - if Assigned(FTrayIcon.OnMouseUp) then - FTrayIcon.OnMouseUp(FTrayIcon, mbMiddle, [], MousePos.x, MousePos.y); - end; - QSystemTrayIconContext: - begin - if Assigned(FTrayIcon.OnMouseDown) then - FTrayIcon.OnMouseDown(FTrayIcon, mbRight, [], MousePos.x, MousePos.y); - - if Assigned(FTrayIcon.OnMouseUp) then - FTrayIcon.OnMouseUp(FTrayIcon, mbRight, [], MousePos.x, MousePos.y); - end; - end; -end; - -procedure TQtSystemTrayIcon.showBaloonHint(const ATitle, AHint: String; - const AFlag: QSystemTrayIconMessageIcon; const ATimeOut: Integer); -var - WHint: WideString; - WTitle: WideString; -begin - WHint := GetUTF8String(AHint); - WTitle := GetUTF8String(ATitle); - QSystemTrayIcon_showMessage(Handle, @WTitle, @WHint, AFlag, ATimeOut); -end; - -procedure TQtSystemTrayIcon.Show; -begin - QSystemTrayIcon_show(handle); -end; - -procedure TQtSystemTrayIcon.Hide; -begin - QSystemTrayIcon_hide(handle); -end; - { TQtButtonGroup } constructor TQtButtonGroup.Create(AParent: QObjectH); diff -ur lazarus.orig/lcl/interfaces/qt/qtwsextctrls.pp lazarus/lcl/interfaces/qt/qtwsextctrls.pp --- lazarus.orig/lcl/interfaces/qt/qtwsextctrls.pp 2013-09-06 10:16:53.000000000 +0400 +++ lazarus/lcl/interfaces/qt/qtwsextctrls.pp 2014-09-02 17:56:37.000000000 +0400 @@ -25,7 +25,7 @@ uses // Bindings qt4, - qtwidgets, qtobjects, qtproc, QtWSControls, + qtwidgets, qtobjects, qtsystemtrayicon, qtproc, QtWSControls, // LCL LCLProc, SysUtils, Classes, Controls, Graphics, Forms, ExtCtrls, LCLType, @@ -152,6 +152,7 @@ class procedure InternalUpdate(const ATrayIcon: TCustomTrayIcon); override; class function ShowBalloonHint(const ATrayIcon: TCustomTrayIcon): Boolean; override; class function GetPosition(const ATrayIcon: TCustomTrayIcon): TPoint; override; + class function GetCanvas(const ATrayIcon: TCustomTrayIcon): TCanvas; override; end; implementation @@ -288,6 +289,8 @@ if TQtMenu(ATrayIcon.PopUpMenu.Handle).Widget <> nil then SystemTrayIcon.setContextMenu(QMenuH(TQtMenu(ATrayIcon.PopUpMenu.Handle).Widget)); + SystemTrayIcon.UpdateSystemTrayWidget; + SystemTrayIcon.show; Result := True; @@ -355,6 +358,17 @@ class function TQtWSCustomTrayIcon.GetPosition(const ATrayIcon: TCustomTrayIcon): TPoint; begin Result := Point(0, 0); + if (ATrayIcon.Handle = 0) then + exit; + Result := TQtSystemTrayIcon(ATrayIcon.Handle).GetPosition; +end; + +class function TQtWSCustomTrayIcon.GetCanvas(const ATrayIcon: TCustomTrayIcon + ): TCanvas; +begin + Result := nil; + if (ATrayIcon.Handle <> 0) then + Result := TQtSystemTrayIcon(ATrayIcon.Handle).Canvas; end; end. |
|
hm...I've succesfully implemented mousemove and paint under qt-x11, but it looks impossible to implement it under qt-win32 since qt implementation does not provide any event to widget's event filter since it uses winapi directly. |
|
Gtk2 part is commited in r46221 |
|
Please test and close if ok. IMPORTANT NOTE: This is fix only for x11 targets. Under qt-win32 it's impossible to implement OnMouseMove and OnPaint without big hack, since qtlib implementation uses pure winapi and does not provide events to underlaying qwidget. |
|
Forgot to add revisions. |
|
Please test and close if ok. IMPORTANT NOTE: This is fix only for x11 targets. Under qt-win32 it's impossible to implement OnMouseMove and OnPaint without big hack, since qtlib implementation uses pure winapi and does not provide events to underlaying qwidget. |
Date Modified | Username | Field | Change |
---|---|---|---|
2012-10-26 19:03 | zmey | New Issue | |
2012-10-26 20:36 | Zeljan Rikalo | LazTarget | => - |
2012-10-26 20:36 | Zeljan Rikalo | Note Added: 0063479 | |
2012-10-26 20:36 | Zeljan Rikalo | Status | new => feedback |
2012-10-26 20:51 | zmey | Note Added: 0063481 | |
2012-10-26 22:03 | Stas | Note Added: 0063484 | |
2012-10-27 06:10 | zmey | Note Added: 0063490 | |
2013-05-14 17:06 | zmey | Note Added: 0067697 | |
2013-05-14 17:06 | zmey | Status | feedback => new |
2013-10-27 09:17 | word | Note Added: 0070989 | |
2013-10-27 13:26 | Zeljan Rikalo | Note Added: 0070993 | |
2013-11-12 19:33 | word | Note Added: 0071285 | |
2014-04-09 16:11 | AlexL | File Added: lazarus_trayicon_onmousemove_mga.patch | |
2014-04-09 16:12 | AlexL | Note Added: 0074232 | |
2014-04-09 18:09 | Zeljan Rikalo | Assigned To | => Zeljan Rikalo |
2014-04-09 18:09 | Zeljan Rikalo | Status | new => assigned |
2014-04-10 17:03 | Zeljan Rikalo | Note Added: 0074273 | |
2014-04-10 17:41 | Zeljan Rikalo | Note Added: 0074276 | |
2014-04-10 22:18 | Zeljan Rikalo | Note Added: 0074285 | |
2014-04-11 07:43 | AlexL | Note Added: 0074291 | |
2014-04-11 08:35 | Zeljan Rikalo | Note Added: 0074292 | |
2014-04-11 08:59 | AlexL | Note Added: 0074295 | |
2014-04-11 09:12 | Zeljan Rikalo | Note Added: 0074296 | |
2014-04-11 14:23 | Zeljan Rikalo | File Added: qtsystemtrayicon.pas | |
2014-04-11 14:23 | Zeljan Rikalo | File Added: qtsystemtrayicon_events.diff | |
2014-04-11 14:26 | Zeljan Rikalo | Note Added: 0074306 | |
2014-05-11 11:05 | AlexL | Note Added: 0074900 | |
2014-09-02 16:42 | AlexL | File Added: lazarus-1.2.4-mga-qtsystemtrayicon-events.patch | |
2014-09-14 13:59 | Zeljan Rikalo | Note Added: 0077212 | |
2014-09-14 14:43 | Zeljan Rikalo | Note Added: 0077213 | |
2014-09-14 14:43 | Zeljan Rikalo | Status | assigned => feedback |
2014-09-14 14:56 | Zeljan Rikalo | LazTarget | - => 1.2.6 |
2014-09-14 14:56 | Zeljan Rikalo | Note Added: 0077214 | |
2014-09-14 14:56 | Zeljan Rikalo | Status | feedback => resolved |
2014-09-14 14:56 | Zeljan Rikalo | Fixed in Version | => 1.3 (SVN) |
2014-09-14 14:56 | Zeljan Rikalo | Resolution | open => fixed |
2014-09-14 14:56 | Zeljan Rikalo | Target Version | => 1.2.6 |
2014-09-14 15:02 | Zeljan Rikalo | Note Added: 0077215 | |
2014-09-14 15:02 | Zeljan Rikalo | Status | resolved => feedback |
2014-09-14 15:04 | Zeljan Rikalo | Fixed in Revision | => 46221,46222,46223 |
2014-09-14 15:04 | Zeljan Rikalo | Widgetset | => GTK 2, QT |
2014-09-14 15:04 | Zeljan Rikalo | Note Added: 0077216 | |
2014-09-14 15:04 | Zeljan Rikalo | Status | feedback => resolved |