Discussion:
Wx::TaskBarIcon on OS X
Richard Faasen
2014-05-11 17:03:56 UTC
Permalink
I've been trying to get Wx::TaskBarIcon to work on OS X. I got the icon
to show up in the menubar, but I can't get a popup menu to show. I
understand none of the events are working on OS X so I've created a
subclass to override CreatePopupMenu but it doesn't get called either.
Am I doing something obvious wrong? I'm using wxWidgets 2.9.4, wxPerl:
0.9922.

Here's my code.


package MyTaskBarIcon;

use base 'Wx::TaskBarIcon';

sub CreatePopupMenu {
my ($this) = @_;

say "xx"; # This never gets called

my $menu = Wx::Menu->new();
$menu->Append(-1, "menu 1");
$menu->Append(-1, "menu 2");

return $menu;
}



# Creating MyTaskBarIcon

my $trayicon = MyTaskBarIcon->new();

$trayicon->IsOk() || die;

$trayicon->SetIcon(Wx::GetWxPerlIcon(1), "Click me!");



Regards,

Richard
Steve Cookson - gmail
2014-05-11 21:30:54 UTC
Permalink
Hi Richard,
Post by Richard Faasen
I've been trying to get Wx::TaskBarIcon to work on OS X. I got the
icon to show up in the menubar, but I can't get a popup menu to show.
I understand none of the events are working on OS X so I've created a
subclass to override CreatePopupMenu but it doesn't get called either.
0.9922.
Don't you need have some code like this line?

Wx::Event::EVT_TASKBAR_CLICK( $self, $self->{TaskBarIcon},
\&MyTaskBarIcon::CreatePopupMenu);

But EVT_TASKBAR_CLICK would still have to be wrapped. It's not hard to
do, just browse this list and there are plenty of examples of wrapping.

But the doc doesn't say it's not wrapped, are you sure?
http://docs.wxwidgets.org/trunk/classwx_task_bar_icon.html

I guess it would be in wxPerl/XS/TaskBarIcon.xs

If it still doesn't work, come back to the list and I'm sure we can help
wrap it.

Sorry I don't have OS X.

Regards

Steve
Richard Faasen
2014-05-13 06:54:57 UTC
Permalink
Hi Steve,
Post by Steve Cookson - gmail
Post by Richard Faasen
I've been trying to get Wx::TaskBarIcon to work on OS X. I got the icon
to show up in the menubar, but I can't get a popup menu to show. I
understand none of the events are working on OS X so I've created a
subclass to override CreatePopupMenu but it doesn't get called either.
0.9922.
Don't you need have some code like this line?
Wx::Event::EVT_TASKBAR_CLICK( $self, $self->{TaskBarIcon},
\&MyTaskBarIcon::CreatePopupMenu);
I tried all possible events but none of them are being called.
Also in the wx docu it says that for wxCocoa events are not called and
you should override the the CreatePopupMenu() callback instead.

http://docs.wxwidgets.org/trunk/classwx_task_bar_icon.html#a5f67b426e34077c690c49f4e6dcc6919
Post by Steve Cookson - gmail
But EVT_TASKBAR_CLICK would still have to be wrapped. It's not hard to
do, just browse this list and there are plenty of examples of wrapping.
But the doc doesn't say it's not wrapped, are you sure?
http://docs.wxwidgets.org/trunk/classwx_task_bar_icon.html
I guess it would be in wxPerl/XS/TaskBarIcon.xs
I'm not sure what wrapping is exactly and I can't find any xs file that
belongs to WxPerl.

I think that isn't the problem. I think the TaskBarIcon works
differently in OS X, it doesn't work by events but with this
CreatePopupMenu callback but for some reason it's never called.

If anyone likes to take a look I have a simple test script that
demonstrates the problem.

Richard
Steve Cookson - gmail
2014-05-13 10:11:41 UTC
Permalink
Hi Richard,
Post by Richard Faasen
If anyone likes to take a look I have a simple test script that
demonstrates the problem.
Please post your app and I'll check it on Linux. At least we'll know
there are no other problems.

Regards

Steve.
Steve Cookson
2014-05-13 10:29:35 UTC
Permalink
Post by Richard Faasen
I'm not sure what wrapping is exactly and I can't find any xs file
that belongs to WxPerl.
wxPerl is a Perl front-end for wxWidgets, which is written in c++.

Depending on how you installed wxPerl, the wrapping files can be in
different places:

- if you used cpan, they will be in your cpan folder, which on Linux is
a hidden directory called ~/.cpan,
- if you used svn, it will be in the subdirectory specified;
- if you used ppm, it'll be (don't know where ppm puts it's files);

Etc.

Inside those directories are a load of files which create an interface
between wxWidgets and the Perl commands.

The main ones (from memory) are XS and ext. A lot of them are generated
automatically and these will be probably be overwritten if you modify them.

The main one for cocoa seems to be (on my machine
~/Alien-wxWidgets/wxWidgets-3.0.0/src/cocoa/taskbar.mm.

It looks as though it works in the normal way (ie based on events).

See below.

Anyhow post your code and people can look at it.

Regards

Steve.

//
============================================================================
// wxTaskBarIconWindow
// Used by all implementations to forward events from the wxMenu
//
============================================================================
class wxTaskBarIconWindow: public wxWindow
{
DECLARE_EVENT_TABLE()
public:
wxTaskBarIconWindow(wxTaskBarIconCocoaImpl *taskBarIconImpl)
: wxWindow(NULL,-1)
, m_taskBarIconImpl(taskBarIconImpl)
{ wxASSERT(m_taskBarIconImpl); }

void OnMenuEvent(wxCommandEvent& event);
protected:
wxTaskBarIconCocoaImpl *m_taskBarIconImpl;
};
Richard Faasen
2014-05-13 12:13:34 UTC
Permalink
Post by Steve Cookson
The main one for cocoa seems to be (on my machine
~/Alien-wxWidgets/wxWidgets-3.0.0/src/cocoa/taskbar.mm.
Got it! I need some time to figure out how this works.
Post by Steve Cookson
Anyhow post your code and people can look at it.
Here it is. Just search for 'trayicon' to find the interesting parts.

Regards,

Richard



#!/usr/bin/env perl

package MyApp;

use warnings;
use strict;

use Wx;

use base 'Wx::App';

sub OnInit {
my($this) = @_;

my($frame) = MyFrame->new( "Minimal wxPerl app",Wx::Point->new( 50,
50 ),Wx::Size->new( 450, 350 ));

$this->SetTopWindow($frame);

$frame->Show(1);

return 1;
}

###

package MyFrame;

use strict;
use warnings;

use base 'Wx::Frame';

use Wx qw( wxBITMAP_TYPE_ICO wxMENU_TEAROFF wxOK wxICON_INFORMATION
wxVERSION_STRING );
use Wx::Event qw(
EVT_COMMAND EVT_TIMER EVT_MENU
EVT_TASKBAR_CLICK
EVT_TASKBAR_LEFT_DOWN EVT_TASKBAR_LEFT_UP
EVT_TASKBAR_RIGHT_DOWN EVT_TASKBAR_RIGHT_UP
EVT_TASKBAR_LEFT_DCLICK EVT_TASKBAR_RIGHT_DCLICK
EVT_TASKBAR_MOVE
);

sub new {
my($class) = shift;
my($this) = $class->SUPER::new (undef, -1, $_[0], $_[1], $_[2]);

$this->SetIcon (Wx::GetWxPerlIcon());

# Setup menubar

my($mfile) = Wx::Menu->new (undef, wxMENU_TEAROFF);

my( $ID_ABOUT, $ID_EXIT ) = ( 1, 2 );
$mfile->Append( $ID_EXIT, "E&xit\tAlt-X", "Quit this program" );

my($mbar) = Wx::MenuBar->new();

$mbar->Append( $mfile, "&File" );

$this->SetMenuBar($mbar);

EVT_MENU( $this, $ID_EXIT, \&OnQuit );

# Setup trayicon

my $trayicon = MyTaskBarIcon->new();

$trayicon->IsOk() || die;

$trayicon->SetIcon(Wx::GetWxPerlIcon(1), "Click me!");

# Set events - Not being called on OS X

EVT_TASKBAR_CLICK($trayicon, \&OnTaskbarClick);
EVT_TASKBAR_LEFT_DOWN($trayicon, \&OnTaskbarClick);
EVT_TASKBAR_LEFT_UP($trayicon, \&OnTaskbarClick);
EVT_TASKBAR_RIGHT_DOWN($trayicon, \&OnTaskbarClick);
EVT_TASKBAR_RIGHT_UP($trayicon, \&OnTaskbarClick);
EVT_TASKBAR_LEFT_DCLICK($trayicon, \&OnTaskbarClick);
EVT_TASKBAR_RIGHT_DCLICK($trayicon, \&OnTaskbarClick);
EVT_TASKBAR_MOVE($trayicon, \&OnTaskbarClick);

return $this;
}

sub OnTaskbarClick {
my ($this, $event) = @_;

print "OnTaskbarClick called\n"; # This never called

return;
}

sub OnQuit {
my ($this, $event) = @_;

$this->Close(1);

return;
}

### trayicon

package MyTaskBarIcon;

use base 'Wx::TaskBarIcon';

sub CreatePopupMenu {
my ($this) = @_;

print "CreatePopupMenu called\n"; # This never gets called

my $menu = Wx::Menu->new();
$menu->Append(-1, "menu 1");
$menu->Append(-1, "menu 2");

return $menu;
}


###

package main;

my $app = MyApp->new();

$app->MainLoop();
Steve Cookson
2014-05-13 18:43:30 UTC
Permalink
Hi Richard,
Post by Richard Faasen
Here it is. Just search for 'trayicon' to find the interesting parts.
Well I played with it a bit. I couldn't TaskIconBar in Wx::Demo.

Anyhow I took your code and copied it into a piece of working code and
after a bit of messing around it sprang into life.

Firstly, it only appears to work when the App has focus!

Secondly EVT_TASKBAR_CLICK never worked,

EVT_TASKBAR_MOVE worked too much and obscured any results I might have had.

But everything else worked.

Here is my test harness with your embedded code, I had no wrapping
problems with your code.

Code follows.

Regards

Steve

#!/usr/bin/perl -w --

package Player;
use strict;
use warnings;

#use v5.18;
use Wx qw[:everything];
use base qw(Wx::Frame);
use Wx qw( wxBITMAP_TYPE_ICO wxMENU_TEAROFF wxOK wxICON_INFORMATION
wxVERSION_STRING );
use Wx::Event qw(
EVT_COMMAND EVT_TIMER EVT_MENU
EVT_TASKBAR_CLICK
EVT_TASKBAR_LEFT_DOWN EVT_TASKBAR_LEFT_UP
EVT_TASKBAR_RIGHT_DOWN EVT_TASKBAR_RIGHT_UP
EVT_TASKBAR_LEFT_DCLICK EVT_TASKBAR_RIGHT_DCLICK
EVT_TASKBAR_MOVE
);


sub new {
my( $i_main_menu, $parent, $id, $title, $pos, $size, $style, $name
) = @_;
$parent = undef unless defined $parent;
$id = wxID_ANY unless defined $id;
$title = "" unless defined $title;
$pos = wxDefaultPosition unless defined $pos;
$size = wxDefaultSize unless defined $size;
$name = "" unless defined $name;

# Create top level window.
$style = wxNO_BORDER unless defined $style;
$i_main_menu = $i_main_menu->SUPER::new( undef, wxID_ANY, "Frame",
wxDefaultPosition, wxDefaultSize, $style, $name );
my $Main_Szr = Wx::BoxSizer->new( wxVERTICAL);

my $trayicon = Wx::TaskBarIcon->new();

$trayicon->IsOk() || die;

$trayicon->SetIcon(Wx::GetWxPerlIcon(1), "Click me!");

# Set events

EVT_TASKBAR_CLICK($trayicon, sub {
print "EVT_TASKBAR_CLICK triggered\n"; # This never called
});
EVT_TASKBAR_LEFT_DOWN($trayicon, sub {
print "EVT_TASKBAR_LEFT_DOWN triggered\n"; # This called
});
EVT_TASKBAR_LEFT_UP($trayicon, sub {
print "EVT_TASKBAR_LEFT_UP triggered\n"; # This called
});
EVT_TASKBAR_RIGHT_DOWN($trayicon, sub {
print "EVT_TASKBAR_RIGHT_DOWN triggered\n"; # This called
});
EVT_TASKBAR_RIGHT_UP($trayicon, sub {
print "EVT_TASKBAR_RIGHT_UP triggered\n"; # This called
});
EVT_TASKBAR_LEFT_DCLICK($trayicon, sub {
print "EVT_TASKBAR_LEFT_DCLICK triggered\n"; # This called
});
EVT_TASKBAR_RIGHT_DCLICK($trayicon, sub {
print "EVT_TASKBAR_RIGHT_DCLICK triggered\n"; # This called
});
if (0){
EVT_TASKBAR_MOVE($trayicon, sub {
print "EVT_TASKBAR_MOVE triggered\n"; # This called too much
});
}


$i_main_menu->Show(1);
$i_main_menu->SetSizer($Main_Szr);
$i_main_menu->Layout();
return $i_main_menu;
}


package Player_Main_App;

use base qw(Wx::App);
use strict;

sub OnInit {
my( $self ) = shift;

my $Player = Player->new();
$self->SetTopWindow($Player);
$Player->Show(1);

return 1;
}

package main;

unless(caller){

my $player_app = Player_Main_App->new();
$player_app->MainLoop();
}
Steve Cookson
2014-05-13 19:10:51 UTC
Permalink
Actually it's not quite the same on 2.8.11 and 3.0.0. It's a little
Post by Steve Cookson
EVT_TASKBAR_LEFT_DOWN($trayicon, sub {
print "EVT_TASKBAR_LEFT_DOWN triggered\n"; # This called
});
EVT_TASKBAR_LEFT_UP($trayicon, sub {
print "EVT_TASKBAR_LEFT_UP triggered\n"; # This called
});
EVT_TASKBAR_RIGHT_DOWN($trayicon, sub {
print "EVT_TASKBAR_RIGHT_DOWN triggered\n"; # This called
});
EVT_TASKBAR_RIGHT_UP($trayicon, sub {
print "EVT_TASKBAR_RIGHT_UP triggered\n"; # This called
});
EVT_TASKBAR_LEFT_DCLICK($trayicon, sub {
print "EVT_TASKBAR_LEFT_DCLICK triggered\n"; # This called
});
EVT_TASKBAR_RIGHT_DCLICK($trayicon, sub {
print "EVT_TASKBAR_RIGHT_DCLICK triggered\n"; # This called
});
if (0){
EVT_TASKBAR_MOVE($trayicon, sub {
print "EVT_TASKBAR_MOVE triggered\n"; # This called too much
});
}
3.0.0 only seems to support:

EVT_TASKBAR_LEFT_DOWN($trayicon, sub {
print "EVT_TASKBAR_LEFT_DOWN triggered\n"; # This called
});
EVT_TASKBAR_RIGHT_DOWN($trayicon, sub {
print "EVT_TASKBAR_RIGHT_DOWN triggered\n"; # This called
});

I'll look into it some more if I get the opportunity.

Regards

Steve
Richard Faasen
2014-05-14 07:09:42 UTC
Permalink
Hi Steve,
Post by Steve Cookson
Firstly, it only appears to work when the App has focus!
Oh, that's a bit weird because I wanted to use it the app window hidden.
Post by Steve Cookson
But everything else worked.
You did this on Linux, right? Unfortunately I still don't get any
events called on OSX. I think there must be something OS specific here.
I've been doing a lot with Wx lately but this is so far the only thing
I can't get handled. I'm using 2.9.4 by the way.


Richard
Steve Cookson
2014-06-01 12:32:42 UTC
Permalink
Richard,

Just a follow up while I think of it.

1) Did you try 3.0.0?
2) Did you follow up on wx-***@googlegroups.com?

Do you think the problem is wxPerl or wxWidgets?

Regards

Steve
Post by Richard Faasen
Hi Steve,
Firstly, it only appears to work when the App has focus!
Oh, that's a bit weird because I wanted to use it the app window hidden.
But everything else worked.
You did this on Linux, right? Unfortunately I still don't get any events
called on OSX. I think there must be something OS specific here. I've been
doing a lot with Wx lately but this is so far the only thing I can't get
handled. I'm using 2.9.4 by the way.
Richard
Richard Faasen
2014-08-17 23:46:57 UTC
Permalink
Post by Steve Cookson
Just a follow up while I think of it.
1) Did you try 3.0.0?
Yes, the latest versions I tried:

Perl version: v5.20.0
wxWidgets 3.0.0
wxPerl version: 0.9923
No
Post by Steve Cookson
Do you think the problem is wxPerl or wxWidgets?
I think it is a problem in wxWidgets. Someone sent me the following link:

http://trac.wxwidgets.org/ticket/15392

I'm currently doing some work on a wx project in C++, I can try it out later.

Richard

Loading...